From 48153e77618e83ba509223b64864b7922774b83d Mon Sep 17 00:00:00 2001
From: jerry <1136009436@qq.com>
Date: Tue, 21 Jan 2025 01:46:34 +0800
Subject: [PATCH] =?UTF-8?q?=E9=A1=B9=E7=9B=AE=E5=88=9D=E5=A7=8B=E5=8C=96?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.env | 27 +
.gitignore | 11 +
.prettierignore | 6 +
.prettierrc | 10 +
App.vue | 129 +
androidPrivacy.json | 3 +
.../custom-back-to-top/custom-back-to-top.vue | 89 +
.../htz-image-upload/htz-image-upload.vue | 831 ++
components/qrcode-modal/qrcode-modal.vue | 121 +
components/search-modal/search-modal.vue | 356 +
.../tui-actionsheet/tui-actionsheet.vue | 201 +
components/thorui/tui-badge/tui-badge.vue | 129 +
.../tui-bottom-popup/tui-bottom-popup.vue | 119 +
.../tui-bubble-popup/tui-bubble-popup.vue | 204 +
.../tui-circular-progress.vue | 309 +
components/thorui/tui-icon/tui-icon.js | 3 +
components/thorui/tui-icon/tui-icon.vue | 82 +
components/thorui/tui-modal/tui-modal.vue | 338 +
.../tui-navigation-bar/tui-navigation-bar.vue | 258 +
.../thorui/tui-numberbox/tui-numberbox.vue | 248 +
components/thorui/tui-sticky/tui-sticky.vue | 166 +
components/thorui/tui-tabbar/tui-tabbar.vue | 287 +
components/thorui/tui-tabs/tui-tabs.vue | 346 +
index.html | 17 +
jsconfig.json | 9 +
main.js | 21 +
manifest.json | 239 +
package.json | 103 +
pages.json | 625 ++
pages/app/sign.vue | 451 +
pages/chat/components/goods.vue | 21 +
pages/chat/components/messageInput.vue | 102 +
pages/chat/components/messageList.vue | 94 +
pages/chat/components/messageListItem.vue | 304 +
pages/chat/components/order.vue | 115 +
pages/chat/components/select-popup.vue | 151 +
pages/chat/components/toolsPopup.vue | 166 +
pages/chat/index.vue | 187 +
pages/chat/util/constants.js | 21 +
pages/chat/util/emoji.js | 58 +
pages/clerk/apply/components/formAvatar.vue | 183 +
pages/clerk/apply/components/formCity.vue | 69 +
pages/clerk/apply/components/formImage.vue | 73 +
pages/clerk/apply/components/formSex.vue | 90 +
pages/clerk/apply/components/formVoice.vue | 255 +
pages/clerk/apply/edit.vue | 213 +
pages/clerk/apply/index.vue | 307 +
.../clerk/detail/components/detail-navbar.vue | 225 +
pages/clerk/detail/components/gameBox.vue | 150 +
pages/clerk/detail/components/giftList.vue | 316 +
pages/clerk/detail/components/giftPopup.vue | 444 +
pages/clerk/detail/components/layout.vue | 263 +
pages/clerk/detail/components/navBar.vue | 89 +
pages/clerk/detail/components/orderPopup.vue | 282 +
pages/clerk/detail/components/photoBox.vue | 50 +
pages/clerk/detail/components/postList.vue | 342 +
pages/clerk/detail/components/priceList.vue | 50 +
pages/clerk/detail/components/radioBox.vue | 112 +
pages/clerk/detail/components/rateList.vue | 125 +
pages/clerk/detail/components/starList.vue | 310 +
pages/clerk/detail/components/stickyBox.vue | 64 +
pages/clerk/detail/components/table-bd.vue | 100 +
pages/clerk/detail/components/table-td.vue | 305 +
pages/clerk/detail/components/table-tr.vue | 208 +
pages/clerk/detail/components/tableList.vue | 98 +
pages/clerk/detail/components/userBox.vue | 270 +
pages/clerk/detail/components/voicePlay.vue | 183 +
pages/clerk/detail/index.vue | 61 +
pages/clerk/fans/components/layout.vue | 82 +
pages/clerk/fans/components/orderList.vue | 212 +
pages/clerk/fans/list.vue | 40 +
pages/commission/commission-ranking.vue | 249 +
pages/commission/components/account-info.vue | 125 +
.../components/account-type-select.vue | 160 +
.../commission/components/commission-auth.vue | 101 +
.../commission/components/commission-info.vue | 112 +
.../commission/components/commission-log.vue | 181 +
.../commission/components/commission-menu.vue | 137 +
pages/commission/goods.vue | 156 +
pages/commission/index.vue | 51 +
pages/commission/order.vue | 328 +
pages/commission/promoter.vue | 297 +
pages/commission/team.vue | 585 ++
pages/commission/wallet.vue | 533 +
pages/commission/withdraw.vue | 467 +
pages/coupon/detail.vue | 390 +
pages/coupon/list.vue | 222 +
pages/goods/comment/add.vue | 190 +
pages/goods/comment/worker/add.vue | 180 +
pages/im/components/cardNotice.vue | 41 +
pages/im/components/cardSwiper.vue | 225 +
pages/im/components/chatBar.vue | 1452 +++
pages/im/components/layout.vue | 336 +
pages/im/components/navigationBar.vue | 194 +
pages/im/components/viewItem.vue | 385 +
pages/im/index - 副本.vue | 204 +
pages/im/index.vue | 194 +
pages/im/util/emoji.js | 33 +
pages/index/cart.vue | 192 +
pages/index/category.vue | 237 +
pages/index/components/first-one.vue | 26 +
pages/index/components/first-two.vue | 66 +
pages/index/components/second-one.vue | 80 +
pages/index/index.vue | 88 +
pages/index/login.vue | 39 +
pages/index/page.vue | 51 +
pages/index/search.vue | 119 +
pages/index/user.vue | 42 +
pages/order/addressSelection.vue | 261 +
pages/order/aftersale/apply.vue | 351 +
pages/order/aftersale/detail.vue | 379 +
pages/order/aftersale/list.vue | 210 +
pages/order/aftersale/log-item.vue | 77 +
pages/order/aftersale/log.vue | 38 +
pages/order/aftersale/return-delivery.vue | 195 +
pages/order/blind/components/layout.vue | 182 +
pages/order/blind/components/orderList.vue | 248 +
pages/order/blind/components/tabBox.vue | 47 +
pages/order/blind/confirm.vue | 435 +
pages/order/blind/detail.vue | 599 ++
pages/order/blind/list.vue | 45 +
pages/order/confirm.vue | 468 +
pages/order/detail.vue | 655 ++
pages/order/express/log.vue | 162 +
pages/order/list.vue | 495 +
pages/order/my/aftersale/apply.vue | 333 +
pages/order/my/aftersale/list.vue | 184 +
pages/order/my/components/layout.vue | 130 +
pages/order/my/components/orderList.vue | 219 +
pages/order/my/components/tabBox.vue | 47 +
pages/order/my/confirm.vue | 426 +
pages/order/my/detail.vue | 580 ++
pages/order/my/index.vue | 39 +
pages/order/my/list - 副本.vue | 514 +
pages/order/my/list.vue | 45 +
pages/order/pickUpVerify.vue | 261 +
pages/order/receive/components/layout.vue | 93 +
pages/order/receive/components/orderList.vue | 163 +
pages/order/receive/components/tabBox.vue | 49 +
pages/order/receive/index.vue | 39 +
pages/order/worker/aftersale/apply.vue | 318 +
pages/order/worker/aftersale/list.vue | 184 +
pages/order/worker/components/layout.vue | 182 +
pages/order/worker/components/orderList.vue | 242 +
pages/order/worker/components/tabBox.vue | 47 +
pages/order/worker/confirm.vue | 433 +
pages/order/worker/detail.vue | 593 ++
pages/order/worker/list.vue | 45 +
pages/pay/index.vue | 295 +
pages/pay/point/index.vue | 308 +
pages/pay/recharge-log.vue | 167 +
pages/pay/recharge.vue | 264 +
pages/pay/result.vue | 318 +
pages/pay/reward/index.vue | 308 +
pages/pay/vip/index.vue | 308 +
pages/pay/worker/index.vue | 308 +
pages/pay/worker/result.vue | 310 +
pages/point/recharge-log.vue | 167 +
pages/point/recharge.vue | 264 +
pages/point/result.vue | 318 +
pages/public/error.vue | 60 +
pages/public/faq.vue | 118 +
pages/public/richtext.vue | 54 +
pages/public/setting.vue | 236 +
pages/public/webview.vue | 18 +
pages/reward/components/layout.vue | 84 +
pages/reward/components/orderList.vue | 169 +
pages/reward/list.vue | 40 +
pages/tabbar/components/home/actionSheet.vue | 220 +
pages/tabbar/components/home/cardList.vue | 448 +
pages/tabbar/components/home/categoryCard.vue | 181 +
.../tabbar/components/home/categorySheet.vue | 67 +
pages/tabbar/components/home/dazi.vue | 49 +
pages/tabbar/components/home/friend.vue | 55 +
.../tabbar/components/home/friend/imgBox.vue | 86 +
.../tabbar/components/home/friend/rankBox.vue | 246 +
.../components/home/friend/stickyBox.vue | 109 +
.../tabbar/components/home/friend/topBox.vue | 260 +
.../components/home/friend/userCard.vue | 210 +
.../tabbar/components/home/navBar - 副本.vue | 78 +
pages/tabbar/components/home/navBar.vue | 106 +
pages/tabbar/components/home/noticeBar.vue | 112 +
pages/tabbar/components/home/peiwan.vue | 58 +
pages/tabbar/components/home/rankBox.vue | 198 +
pages/tabbar/components/home/sexSheet.vue | 61 +
pages/tabbar/components/home/stickyBox.vue | 118 +
pages/tabbar/components/home/topBox.vue | 183 +
pages/tabbar/components/home/userCard.vue | 153 +
pages/tabbar/components/home/userList.vue | 379 +
pages/tabbar/components/home/voicePlay.vue | 184 +
pages/tabbar/components/member/layout.vue | 233 +
pages/tabbar/components/member/navBar.vue | 94 +
pages/tabbar/components/member/viewItem.vue | 216 +
pages/tabbar/components/message/friend.vue | 208 +
pages/tabbar/components/message/gameBox.vue | 149 +
pages/tabbar/components/message/navBar.vue | 106 +
pages/tabbar/components/message/peiwan.vue | 346 +
pages/tabbar/components/message/viewItem.vue | 265 +
pages/tabbar/components/mine/bgBox.vue | 62 +
pages/tabbar/components/mine/layout.vue | 96 +
pages/tabbar/components/mine/mainBox.vue | 502 +
pages/tabbar/components/mine/navBar.vue | 108 +
pages/tabbar/components/mine/vipCard.vue | 109 +
pages/tabbar/components/trend/clerk-popup.vue | 132 +
pages/tabbar/components/trend/fb-popup.vue | 313 +
pages/tabbar/components/trend/formCity.vue | 55 +
pages/tabbar/components/trend/formImage.vue | 68 +
pages/tabbar/components/trend/formVideo.vue | 71 +
pages/tabbar/components/trend/formVoice.vue | 256 +
pages/tabbar/components/trend/imgBox.vue | 149 +
pages/tabbar/components/trend/layout.vue | 179 +
pages/tabbar/components/trend/navBar.vue | 131 +
pages/tabbar/components/trend/postList.vue | 512 +
pages/tabbar/components/trend/userCard.vue | 190 +
pages/tabbar/components/trend/videoBox.vue | 44 +
pages/tabbar/components/trend/voicePlay.vue | 184 +
pages/tabbar/home.vue | 244 +
pages/tabbar/index.vue | 395 +
pages/tabbar/message.vue | 147 +
pages/tabbar/mine.vue | 38 +
pages/tabbar/social.vue | 38 +
pages/tabbar/trend.vue | 38 +
pages/trend/city/components/orderList.vue | 510 +
pages/trend/city/list.vue | 159 +
pages/trend/detail/components/card.vue | 510 +
pages/trend/detail/index.vue | 76 +
pages/trend/my/components/orderList.vue | 500 +
pages/trend/my/list.vue | 143 +
pages/user/address/edit.vue | 305 +
pages/user/address/list.vue | 165 +
.../user/detail/components/detail-navbar.vue | 221 +
pages/user/detail/components/giftList.vue | 316 +
pages/user/detail/components/giftPopup.vue | 445 +
pages/user/detail/components/layout.vue | 286 +
pages/user/detail/components/navBar.vue | 89 +
pages/user/detail/components/photoBox.vue | 50 +
pages/user/detail/components/postList.vue | 362 +
pages/user/detail/components/starList.vue | 310 +
pages/user/detail/components/stickyBox.vue | 59 +
pages/user/detail/components/userBox.vue | 308 +
pages/user/detail/index.vue | 61 +
pages/user/goods-collect.vue | 233 +
pages/user/goods-log.vue | 308 +
pages/user/goods_details_store/index.vue | 275 +
pages/user/info.vue | 475 +
pages/user/vip.vue | 382 +
pages/user/wallet/money.vue | 379 +
pages/user/wallet/score.vue | 323 +
pages/worker/blind/components/gameBox.vue | 149 +
pages/worker/blind/components/layout.vue | 357 +
pages/worker/blind/index.vue | 40 +
pages/worker/levelList/components/layout.vue | 109 +
.../worker/levelList/components/levelList.vue | 105 +
.../worker/levelList/components/table-bd.vue | 100 +
.../worker/levelList/components/table-td.vue | 305 +
.../worker/levelList/components/table-tr.vue | 208 +
pages/worker/levelList/index.vue | 45 +
pages/worker/workerList/components/layout.vue | 115 +
.../workerList/components/workerList.vue | 208 +
pages/worker/workerList/index.vue | 40 +
pages/worker/workerList/set.vue | 148 +
sheep/api/im/memberConversation.js | 80 +
sheep/api/im/memberMessage.js | 44 +
sheep/api/infra/file.js | 45 +
sheep/api/member/address.js | 53 +
sheep/api/member/auth.js | 132 +
sheep/api/member/point.js | 19 +
sheep/api/member/signin.js | 37 +
sheep/api/member/social.js | 76 +
sheep/api/member/user.js | 166 +
sheep/api/migration/app.js | 21 +
sheep/api/migration/index.js | 10 +
sheep/api/migration/third.js | 18 +
sheep/api/pay/channel.js | 14 +
sheep/api/pay/order.js | 22 +
sheep/api/pay/point.js | 37 +
sheep/api/pay/wallet.js | 68 +
sheep/api/product/category.js | 21 +
sheep/api/product/comment.js | 22 +
sheep/api/product/favorite.js | 54 +
sheep/api/product/history.js | 39 +
sheep/api/product/spu.js | 41 +
sheep/api/promotion/activity.js | 16 +
sheep/api/promotion/article.js | 12 +
sheep/api/promotion/combination.js | 68 +
sheep/api/promotion/coupon.js | 101 +
sheep/api/promotion/diy.js | 38 +
sheep/api/promotion/kefu.js | 31 +
sheep/api/promotion/rewardActivity.js | 14 +
sheep/api/promotion/seckill.js | 33 +
sheep/api/system/area.js | 13 +
sheep/api/system/dict.js | 16 +
sheep/api/trade/afterSale.js | 63 +
sheep/api/trade/brokerage.js | 93 +
sheep/api/trade/cart.js | 50 +
sheep/api/trade/config.js | 20 +
sheep/api/trade/delivery.js | 31 +
sheep/api/trade/order.js | 247 +
sheep/api/worker/clerk.js | 195 +
sheep/api/worker/reward.js | 60 +
sheep/api/worker/trend.js | 100 +
.../s-activity-pop/s-activity-pop.vue | 105 +
.../s-address-item/s-address-item.vue | 110 +
.../s-auth-modal/components/account-login.vue | 107 +
.../s-auth-modal/components/change-mobile.vue | 127 +
.../components/change-password.vue | 106 +
.../components/chat-authorization.vue | 170 +
.../s-auth-modal/components/formImage.vue | 73 +
.../s-auth-modal/components/formQrcode.vue | 88 +
.../s-auth-modal/components/formSex.vue | 88 +
.../components/h5-authorization.vue | 194 +
.../components/mp-authorization.vue | 203 +
.../components/reset-password.vue | 119 +
.../s-auth-modal/components/sms-login.vue | 119 +
sheep/components/s-auth-modal/index.scss | 151 +
.../components/s-auth-modal/s-auth-modal.vue | 256 +
.../components/s-block-item/s-block-item.vue | 81 +
sheep/components/s-block/s-block.vue | 54 +
.../components/s-count-down/s-count-down.vue | 173 +
.../s-coupon-block/s-coupon-block.vue | 176 +
.../s-coupon-card/s-coupon-card.vue | 102 +
.../components/s-coupon-get/s-coupon-get.vue | 109 +
.../s-coupon-list/s-coupon-list.vue | 205 +
.../s-coupon-select/s-coupon-select.vue | 140 +
.../components/navbar-item.vue | 66 +
.../s-custom-navbar/components/navbar.vue | 314 +
.../s-custom-navbar/s-custom-navbar.vue | 207 +
.../s-discount-list/s-discount-list.vue | 114 +
sheep/components/s-empty/s-empty.vue | 93 +
.../components/s-float-menu/s-float-menu.vue | 88 +
.../components/s-goods-card/s-goods-card.vue | 286 +
.../s-goods-column/s-goods-column.vue | 751 ++
.../components/s-goods-item/s-goods-item.vue | 181 +
.../s-goods-scroll/s-goods-scroll.vue | 33 +
.../s-goods-shelves/s-goods-shelves.vue | 147 +
.../s-groupon-block/s-groupon-block.vue | 171 +
.../s-hotzone-block/s-hotzone-block.vue | 46 +
.../s-image-banner/s-image-banner.vue | 44 +
.../s-image-block/s-image-block.vue | 27 +
.../components/s-image-cube/s-image-cube.vue | 110 +
sheep/components/s-layout/s-layout.vue | 246 +
.../components/s-line-block/s-line-block.vue | 15 +
.../components/s-live-block/s-live-block.vue | 144 +
sheep/components/s-live-card/s-live-card.vue | 234 +
.../s-menu-button/s-menu-button.vue | 343 +
sheep/components/s-menu-grid/s-menu-grid.vue | 104 +
sheep/components/s-menu-list/s-menu-list.vue | 66 +
.../components/s-menu-tools/s-menu-tools.vue | 118 +
.../s-notice-block/s-notice-block.vue | 38 +
.../components/s-order-card/s-order-card.vue | 132 +
.../s-popup-image/s-popup-image.vue | 85 +
.../s-richtext-block/s-richtext-block.vue | 40 +
.../s-search-block/s-search-block.vue | 164 +
.../s-seckill-block/s-seckill-block.vue | 182 +
.../s-select-groupon-sku.vue | 472 +
.../s-select-seckill-sku.vue | 431 +
.../components/s-select-sku/s-select-sku.vue | 406 +
.../s-share-modal/canvas-poster/index.vue | 168 +
.../canvas-poster/poster/goods.js | 125 +
.../canvas-poster/poster/groupon.js | 122 +
.../canvas-poster/poster/index.js | 39 +
.../canvas-poster/poster/user.js | 74 +
.../s-share-modal/s-share-modal.vue | 196 +
sheep/components/s-statusbar/s-statusbar.vue | 10 +
sheep/components/s-tabbar/s-tabbar.vue | 90 +
.../s-title-block/s-title-block.vue | 108 +
.../s-uploader/choose-and-upload-file.js | 213 +
sheep/components/s-uploader/s-uploader.vue | 675 ++
sheep/components/s-uploader/upload-file.vue | 335 +
sheep/components/s-uploader/upload-image.vue | 306 +
sheep/components/s-uploader/utils.js | 110 +
sheep/components/s-user-card/s-user-card.vue | 185 +
.../s-video-block/s-video-block.vue | 32 +
.../s-wallet-card/s-wallet-card.vue | 119 +
.../s-worker-item/s-worker-item.vue | 198 +
sheep/config/index.js | 23 +
sheep/config/zIndex.js | 20 +
sheep/helper/digit.js | 168 +
sheep/helper/index.js | 714 ++
sheep/helper/test.js | 285 +
sheep/helper/throttle.js | 31 +
sheep/helper/tools.js | 67 +
sheep/helper/utils.js | 172 +
sheep/hooks/useApp.js | 0
sheep/hooks/useGoods.js | 655 ++
sheep/hooks/useModal.js | 141 +
sheep/hooks/useWebSocket.js | 163 +
sheep/index.js | 61 +
sheep/libs/mplive-manifest-plugin.js | 32 +
sheep/libs/permission.js | 246 +
sheep/libs/sdk-h5-weixin.js | 184 +
sheep/platform/index.js | 175 +
sheep/platform/pay.js | 372 +
sheep/platform/provider/apple/app.js | 36 +
sheep/platform/provider/apple/index.js | 9 +
sheep/platform/provider/wechat/index.js | 15 +
sheep/platform/provider/wechat/miniProgram.js | 213 +
.../provider/wechat/officialAccount.js | 106 +
.../platform/provider/wechat/openPlatform.js | 64 +
sheep/platform/share.js | 207 +
sheep/request/index.js | 341 +
sheep/router/index.js | 185 +
sheep/router/utils/strip-json-comments.js | 79 +
sheep/router/utils/uni-read-pages-v3.js | 103 +
sheep/scss/_main.scss | 354 +
sheep/scss/_mixins.scss | 61 +
sheep/scss/_tools.scss | 286 +
sheep/scss/_var.scss | 162 +
sheep/scss/font/OPPOSANS-M-subfont.ttf | Bin 0 -> 9832 bytes
sheep/scss/icon/_coloricon.scss | 1340 +++
sheep/scss/icon/_icon.scss | 181 +
sheep/scss/icon/_sheepicon.scss | 94 +
sheep/scss/icon/_style.scss | 43 +
sheep/scss/index.scss | 27 +
sheep/scss/style/_avatar.scss | 0
sheep/scss/style/_background.scss | 204 +
sheep/scss/style/_border.scss | 140 +
sheep/scss/style/_button.scss | 87 +
sheep/scss/style/_card.scss | 353 +
sheep/scss/style/_code.scss | 55 +
sheep/scss/style/_flex.scss | 79 +
sheep/scss/style/_form.scss | 121 +
sheep/scss/style/_grid.scss | 103 +
sheep/scss/style/_markdown.scss | 62 +
sheep/scss/style/_menu.scss | 54 +
sheep/scss/style/_shadow.scss | 90 +
sheep/scss/style/_table.scss | 133 +
sheep/scss/style/_tag.scss | 0
sheep/scss/style/_text.scss | 104 +
sheep/scss/theme/_dark.scss | 39 +
sheep/scss/theme/_light.scss | 39 +
sheep/scss/theme/_style.scss | 68 +
sheep/scss/ui.scss | 19 +
sheep/store/app.js | 134 +
sheep/store/cart.js | 112 +
sheep/store/index.js | 20 +
sheep/store/modal.js | 31 +
sheep/store/sys.js | 113 +
sheep/store/user.js | 196 +
sheep/ui/su-coupon/su-coupon.vue | 319 +
.../ui/su-data-checkbox/su-data-checkbox.vue | 894 ++
sheep/ui/su-dialog/su-dialog.vue | 269 +
sheep/ui/su-fixed/su-fixed.vue | 217 +
sheep/ui/su-image/su-image.vue | 130 +
sheep/ui/su-inner-navbar/su-inner-navbar.vue | 365 +
sheep/ui/su-navbar/su-navbar.vue | 483 +
sheep/ui/su-notice-bar/su-notice-bar.vue | 473 +
sheep/ui/su-number-box/su-number-box.vue | 225 +
sheep/ui/su-popover/su-popover.vue | 314 +
sheep/ui/su-popup/keypress.js | 45 +
sheep/ui/su-popup/su-popup.vue | 589 ++
sheep/ui/su-progress/su-progress.vue | 203 +
sheep/ui/su-radio/su-radio.vue | 301 +
.../ui/su-region-picker/su-region-picker.vue | 247 +
sheep/ui/su-status-bar/su-status-bar.vue | 16 +
sheep/ui/su-sticky/su-sticky.vue | 264 +
sheep/ui/su-subline/su-subline.vue | 62 +
sheep/ui/su-swiper/su-swiper.vue | 502 +
sheep/ui/su-switch/su-switch.vue | 100 +
sheep/ui/su-tab-item/su-tab-item.vue | 169 +
sheep/ui/su-tab/su-tab.vue | 474 +
sheep/ui/su-tabbar-item/su-tabbar-item.vue | 234 +
sheep/ui/su-tabbar/su-tabbar.vue | 227 +
sheep/ui/su-tabs-item/props.js | 3 +
sheep/ui/su-tabs-item/su-tabs-item.vue | 26 +
sheep/ui/su-tabs/su-tabs.vue | 434 +
sheep/ui/su-time-line/su-time-line.vue | 37 +
.../ui/su-timeline-item/su-timeline-item.vue | 76 +
sheep/ui/su-toolbar/su-toolbar.vue | 129 +
sheep/ui/su-video/su-video.vue | 199 +
sheep/url/index.js | 199 +
sheep/util/adVideoUtils.js | 107 +
sheep/util/const.js | 122 +
sheep/util/index.js | 133 +
sheep/validate/form.js | 164 +
static/activity-left.png | Bin 0 -> 440 bytes
static/activity-right.png | Bin 0 -> 1400 bytes
static/cart-empty.png | Bin 0 -> 5933 bytes
static/collect-empty.png | Bin 0 -> 5849 bytes
static/comment-empty.png | Bin 0 -> 5603 bytes
static/coupon-empty.png | Bin 0 -> 5245 bytes
static/css/iconfont.css | 558 +
static/data-empty.png | Bin 0 -> 5053 bytes
static/goods-empty.png | Bin 0 -> 3192 bytes
static/images/audio.png | Bin 0 -> 1052 bytes
static/images/line.png | Bin 0 -> 3943 bytes
static/images/writeOff.png | Bin 0 -> 2315 bytes
static/internet-empty.png | Bin 0 -> 7003 bytes
static/order-empty.png | Bin 0 -> 4406 bytes
static/soldout-empty.png | Bin 0 -> 7012 bytes
uni.scss | 77 +
uni_modules/all-speech/changelog.md | 25 +
.../components/all-speech/all-speech.vue | 652 ++
.../all-speech/js_sdk/h5-speech/speech.js | 226 +
.../js_sdk/wa-permission/permission.js | 272 +
uni_modules/all-speech/package.json | 82 +
uni_modules/all-speech/readme.md | 89 +
uni_modules/c-svga/changelog.md | 35 +
.../c-svga/components/c-svga/c-svga.vue | 267 +
.../c-svga/components/c-svga/js/getfile.js | 67 +
.../c-svga/components/c-svga/js/render.js | 120 +
.../c-svga/components/c-svga/js/uuid.js | 23 +
.../c-svga/node_modules/howler/LICENSE.md | 20 +
.../c-svga/node_modules/howler/README.md | 564 ++
.../howler/dist/howler.core.min.js | 2 +
.../c-svga/node_modules/howler/dist/howler.js | 3248 ++++++
.../node_modules/howler/dist/howler.min.js | 4 +
.../howler/dist/howler.spatial.min.js | 2 +
.../c-svga/node_modules/howler/package.json | 73 +
.../node_modules/howler/src/howler.core.js | 2587 +++++
.../howler/src/plugins/howler.spatial.js | 659 ++
.../node_modules/svgaplayer-weapp/README.md | 233 +
.../node_modules/svgaplayer-weapp/build.js | 13 +
.../svgaplayer-weapp/dist/svgaplayer.weapp.js | 1 +
.../svgaplayer-weapp/package.json | 45 +
.../svgaplayer-weapp/protobuf_mp/protobuf.js | 133 +
.../protobuf_mp/src/EventEmitter.js | 76 +
.../protobuf_mp/src/asPromise.js | 52 +
.../protobuf_mp/src/base64.js | 139 +
.../protobuf_mp/src/common.js | 398 +
.../protobuf_mp/src/converter.js | 330 +
.../protobuf_mp/src/decoder.js | 118 +
.../svgaplayer-weapp/protobuf_mp/src/enum.js | 171 +
.../svgaplayer-weapp/protobuf_mp/src/field.js | 377 +
.../svgaplayer-weapp/protobuf_mp/src/float.js | 333 +
.../protobuf_mp/src/index-light.js | 103 +
.../protobuf_mp/src/index-minimal.js | 36 +
.../svgaplayer-weapp/protobuf_mp/src/index.js | 12 +
.../protobuf_mp/src/inquire.js | 34 +
.../svgaplayer-weapp/protobuf_mp/src/long.js | 1323 +++
.../protobuf_mp/src/longBits.js | 122 +
.../protobuf_mp/src/mapField.js | 130 +
.../protobuf_mp/src/message.js | 160 +
.../protobuf_mp/src/method.js | 155 +
.../protobuf_mp/src/namespace.js | 435 +
.../protobuf_mp/src/object.js | 199 +
.../svgaplayer-weapp/protobuf_mp/src/oneof.js | 207 +
.../svgaplayer-weapp/protobuf_mp/src/parse.js | 770 ++
.../svgaplayer-weapp/protobuf_mp/src/path.js | 58 +
.../svgaplayer-weapp/protobuf_mp/src/pool.js | 47 +
.../protobuf_mp/src/reader.js | 314 +
.../protobuf_mp/src/reader_buffer.js | 44 +
.../svgaplayer-weapp/protobuf_mp/src/root.js | 439 +
.../svgaplayer-weapp/protobuf_mp/src/roots.js | 6 +
.../svgaplayer-weapp/protobuf_mp/src/rpc.js | 36 +
.../protobuf_mp/src/rpc/service.js | 141 +
.../protobuf_mp/src/service.js | 173 +
.../protobuf_mp/src/tokenize.js | 396 +
.../svgaplayer-weapp/protobuf_mp/src/type.js | 576 ++
.../svgaplayer-weapp/protobuf_mp/src/types.js | 199 +
.../protobuf_mp/src/typescript.jsdoc | 15 +
.../svgaplayer-weapp/protobuf_mp/src/utf8.js | 105 +
.../svgaplayer-weapp/protobuf_mp/src/util.js | 278 +
.../protobuf_mp/src/verifier.js | 157 +
.../protobuf_mp/src/wrappers.js | 81 +
.../protobuf_mp/src/writer.js | 468 +
.../protobuf_mp/src/writer_buffer.js | 81 +
.../svgaplayer-weapp/src/adaptor.ts | 7 +
.../svgaplayer-weapp/src/bezier_path.ts | 16 +
.../svgaplayer-weapp/src/ellipse_path.ts | 20 +
.../svgaplayer-weapp/src/frame_entity.ts | 183 +
.../node_modules/svgaplayer-weapp/src/main.ts | 5 +
.../node_modules/svgaplayer-weapp/src/pako.js | 2 +
.../svgaplayer-weapp/src/parser.ts | 48 +
.../svgaplayer-weapp/src/player.ts | 331 +
.../svgaplayer-weapp/src/proto.js | 5 +
.../svgaplayer-weapp/src/rect_path.ts | 30 +
.../svgaplayer-weapp/src/renderer.ts | 558 +
.../svgaplayer-weapp/src/sprite_entity.ts | 18 +
.../svgaplayer-weapp/src/value_animator.ts | 99 +
.../svgaplayer-weapp/src/video_entity.ts | 37 +
.../svgaplayer-weapp/svgaplayer-weapp.d.ts | 40 +
.../svgaplayer-weapp/tsconfig.json | 73 +
.../svgaplayerweb/CreateJS.README.md | 111 +
.../svgaplayerweb/ISSUE_TEMPLATE.md | 25 +
.../c-svga/node_modules/svgaplayerweb/LICENSE | 201 +
.../svgaplayerweb/LayaBox.README.md | 93 +
.../node_modules/svgaplayerweb/README.md | 184 +
.../node_modules/svgaplayerweb/README.zh.md | 189 +
.../svgaplayerweb/build/svga.createjs.min.js | 1 +
.../svgaplayerweb/build/svga.ie.min.js | 1 +
.../svgaplayerweb/build/svga.layabox.min.js | 1 +
.../svgaplayerweb/build/svga.min.js | 1 +
.../node_modules/svgaplayerweb/index.d.ts | 71 +
.../node_modules/svgaplayerweb/package.json | 61 +
.../svgaplayerweb/patch/layabox/laya.webgl.js | 9018 +++++++++++++++++
.../svgaplayerweb/src/Canvas/autoLoader.js | 41 +
.../svgaplayerweb/src/Canvas/index.js | 11 +
.../svgaplayerweb/src/Canvas/player.js | 305 +
.../svgaplayerweb/src/Canvas/renderer.js | 504 +
.../svgaplayerweb/src/CreateJS/index.js | 8 +
.../svgaplayerweb/src/CreateJS/player.js | 273 +
.../svgaplayerweb/src/CreateJS/renderer.js | 344 +
.../svgaplayerweb/src/LayaBox/index.js | 8 +
.../svgaplayerweb/src/LayaBox/player.js | 281 +
.../svgaplayerweb/src/LayaBox/renderer.js | 519 +
.../svgaplayerweb/src/bezierPath.js | 14 +
.../svgaplayerweb/src/ellipsePath.js | 23 +
.../svgaplayerweb/src/frameEntity.js | 151 +
.../svgaplayerweb/src/mockWorker.js | 207 +
.../node_modules/svgaplayerweb/src/parser.js | 24 +
.../node_modules/svgaplayerweb/src/proto.js | 5 +
.../svgaplayerweb/src/rectPath.js | 24 +
.../svgaplayerweb/src/spriteEntity.js | 33 +
.../svgaplayerweb/src/videoEntity.js | 82 +
.../svgaplayerweb/webpack.config.js | 34 +
uni_modules/c-svga/package.json | 89 +
uni_modules/c-svga/readme.md | 242 +
uni_modules/lime-painter/changelog.md | 223 +
.../components/common/relation.js | 150 +
.../l-painter-image/l-painter-image.vue | 28 +
.../l-painter-qrcode/l-painter-qrcode.vue | 27 +
.../l-painter-text/l-painter-text.vue | 33 +
.../l-painter-view/l-painter-view.vue | 34 +
.../components/l-painter/l-painter.vue | 461 +
.../lime-painter/components/l-painter/nvue.js | 214 +
.../components/l-painter/painter.js | 1 +
.../components/l-painter/props.js | 56 +
.../components/l-painter/single.js | 1 +
.../components/l-painter/utils.js | 368 +
.../components/lime-painter/lime-painter.vue | 248 +
.../lime-painter/hybrid/html/index.html | 119 +
.../lime-painter/hybrid/html/painter.js | 1 +
.../hybrid/html/uni.webview.1.5.3.js | 1 +
uni_modules/lime-painter/package.json | 93 +
uni_modules/lime-painter/parser.js | 388 +
uni_modules/lime-painter/readme.md | 963 ++
uni_modules/mp-html/README.md | 191 +
uni_modules/mp-html/changelog.md | 121 +
.../mp-html/components/mp-html/mp-html.vue | 498 +
.../mp-html/components/mp-html/node/node.vue | 576 ++
.../mp-html/components/mp-html/parser.js | 1333 +++
uni_modules/mp-html/package.json | 76 +
.../static/app-plus/mp-html/js/handler.js | 1 +
.../app-plus/mp-html/js/uni.webview.min.js | 1 +
.../static/app-plus/mp-html/local.html | 1 +
uni_modules/shmily-drag-image/README.md | 112 +
uni_modules/shmily-drag-image/changelog.md | 10 +
.../shmily-drag-image/shmily-drag-image.vue | 566 ++
uni_modules/shmily-drag-image/package.json | 84 +
uni_modules/uni-badge/changelog.md | 29 +
.../components/uni-badge/uni-badge.vue | 268 +
uni_modules/uni-badge/package.json | 88 +
uni_modules/uni-badge/readme.md | 10 +
uni_modules/uni-card/changelog.md | 26 +
.../uni-card/components/uni-card/uni-card.vue | 270 +
uni_modules/uni-card/package.json | 90 +
uni_modules/uni-card/readme.md | 12 +
uni_modules/uni-collapse/changelog.md | 36 +
.../uni-collapse-item/uni-collapse-item.vue | 402 +
.../components/uni-collapse/uni-collapse.vue | 147 +
uni_modules/uni-collapse/package.json | 89 +
uni_modules/uni-collapse/readme.md | 12 +
uni_modules/uni-combox/changelog.md | 15 +
.../components/uni-combox/uni-combox.vue | 275 +
uni_modules/uni-combox/package.json | 90 +
uni_modules/uni-combox/readme.md | 11 +
uni_modules/uni-countdown/changelog.md | 24 +
.../components/uni-countdown/i18n/en.json | 6 +
.../components/uni-countdown/i18n/index.js | 8 +
.../uni-countdown/i18n/zh-Hans.json | 6 +
.../uni-countdown/i18n/zh-Hant.json | 6 +
.../uni-countdown/uni-countdown.vue | 271 +
uni_modules/uni-countdown/package.json | 86 +
uni_modules/uni-countdown/readme.md | 10 +
uni_modules/uni-data-checkbox/changelog.md | 45 +
.../uni-data-checkbox/uni-data-checkbox.vue | 817 ++
uni_modules/uni-data-checkbox/package.json | 84 +
uni_modules/uni-data-checkbox/readme.md | 18 +
uni_modules/uni-data-picker/changelog.md | 58 +
.../components/uni-data-picker/keypress.js | 45 +
.../uni-data-picker/uni-data-picker.vue | 539 +
.../uni-data-pickerview/uni-data-picker.js | 563 +
.../uni-data-pickerview.vue | 333 +
uni_modules/uni-data-picker/package.json | 92 +
uni_modules/uni-data-picker/readme.md | 22 +
uni_modules/uni-dateformat/changelog.md | 10 +
.../components/uni-dateformat/date-format.js | 200 +
.../uni-dateformat/uni-dateformat.vue | 88 +
uni_modules/uni-dateformat/package.json | 88 +
uni_modules/uni-dateformat/readme.md | 11 +
uni_modules/uni-datetime-picker/changelog.md | 89 +
.../uni-datetime-picker/calendar-item.vue | 185 +
.../uni-datetime-picker/calendar.js | 546 +
.../uni-datetime-picker/calendar.vue | 897 ++
.../uni-datetime-picker/i18n/en.json | 19 +
.../uni-datetime-picker/i18n/index.js | 8 +
.../uni-datetime-picker/i18n/zh-Hans.json | 19 +
.../uni-datetime-picker/i18n/zh-Hant.json | 19 +
.../uni-datetime-picker/keypress.js | 45 +
.../uni-datetime-picker/time-picker.vue | 927 ++
.../uni-datetime-picker.vue | 995 ++
.../components/uni-datetime-picker/util.js | 410 +
uni_modules/uni-datetime-picker/package.json | 90 +
uni_modules/uni-datetime-picker/readme.md | 21 +
uni_modules/uni-drawer/changelog.md | 13 +
.../components/uni-drawer/keypress.js | 45 +
.../components/uni-drawer/uni-drawer.vue | 183 +
uni_modules/uni-drawer/package.json | 87 +
uni_modules/uni-drawer/readme.md | 10 +
uni_modules/uni-easyinput/changelog.md | 41 +
.../components/uni-easyinput/common.js | 54 +
.../uni-easyinput/uni-easyinput.vue | 538 +
uni_modules/uni-easyinput/package.json | 90 +
uni_modules/uni-easyinput/readme.md | 11 +
uni_modules/uni-fab/changelog.md | 17 +
.../uni-fab/components/uni-fab/uni-fab.vue | 529 +
uni_modules/uni-fab/package.json | 87 +
uni_modules/uni-fab/readme.md | 9 +
uni_modules/uni-fav/changelog.md | 19 +
.../uni-fav/components/uni-fav/i18n/en.json | 4 +
.../uni-fav/components/uni-fav/i18n/index.js | 8 +
.../components/uni-fav/i18n/zh-Hans.json | 4 +
.../components/uni-fav/i18n/zh-Hant.json | 4 +
.../uni-fav/components/uni-fav/uni-fav.vue | 161 +
uni_modules/uni-fav/package.json | 89 +
uni_modules/uni-fav/readme.md | 10 +
uni_modules/uni-forms/changelog.md | 60 +
.../uni-forms-item/uni-forms-item.vue | 536 +
.../components/uni-forms/uni-forms.vue | 472 +
.../components/uni-forms/validate.js | 486 +
uni_modules/uni-forms/package.json | 90 +
uni_modules/uni-forms/readme.md | 23 +
uni_modules/uni-goods-nav/changelog.md | 18 +
.../components/uni-goods-nav/i18n/en.json | 6 +
.../components/uni-goods-nav/i18n/index.js | 8 +
.../uni-goods-nav/i18n/zh-Hans.json | 6 +
.../uni-goods-nav/i18n/zh-Hant.json | 6 +
.../uni-goods-nav/uni-goods-nav.vue | 229 +
uni_modules/uni-goods-nav/package.json | 88 +
uni_modules/uni-goods-nav/readme.md | 10 +
uni_modules/uni-grid/changelog.md | 13 +
.../uni-grid-item/uni-grid-item.vue | 140 +
.../uni-grid/components/uni-grid/uni-grid.vue | 142 +
uni_modules/uni-grid/package.json | 86 +
uni_modules/uni-grid/readme.md | 11 +
uni_modules/uni-group/changelog.md | 16 +
.../components/uni-group/uni-group.vue | 134 +
uni_modules/uni-group/package.json | 87 +
uni_modules/uni-group/readme.md | 9 +
uni_modules/uni-icons/changelog.md | 22 +
.../uni-icons/components/uni-icons/icons.js | 1169 +++
.../components/uni-icons/uni-icons.vue | 12 +
.../uni-icons/components/uni-icons/uni.ttf | Bin 0 -> 26164 bytes
.../components/uni-icons/uniicons.css | 663 ++
.../components/uni-icons/uniicons.ttf | Bin 0 -> 35760 bytes
uni_modules/uni-icons/package.json | 86 +
uni_modules/uni-icons/readme.md | 8 +
uni_modules/uni-link/changelog.md | 17 +
.../uni-link/components/uni-link/uni-link.vue | 128 +
uni_modules/uni-link/package.json | 87 +
uni_modules/uni-link/readme.md | 11 +
uni_modules/uni-list/changelog.md | 20 +
.../components/uni-list-ad/uni-list-ad.vue | 107 +
.../uni-list-chat/uni-list-chat.scss | 58 +
.../uni-list-chat/uni-list-chat.vue | 538 +
.../uni-list-item/uni-list-item.vue | 475 +
.../uni-list/components/uni-list/uni-list.vue | 108 +
.../components/uni-list/uni-refresh.vue | 65 +
.../components/uni-list/uni-refresh.wxs | 87 +
uni_modules/uni-list/package.json | 91 +
uni_modules/uni-list/readme.md | 346 +
uni_modules/uni-load-more/changelog.md | 19 +
.../components/uni-load-more/i18n/en.json | 5 +
.../components/uni-load-more/i18n/index.js | 8 +
.../uni-load-more/i18n/zh-Hans.json | 5 +
.../uni-load-more/i18n/zh-Hant.json | 5 +
.../uni-load-more/uni-load-more.vue | 399 +
uni_modules/uni-load-more/package.json | 86 +
uni_modules/uni-load-more/readme.md | 14 +
uni_modules/uni-nav-bar/changelog.md | 39 +
.../components/uni-nav-bar/uni-nav-bar.vue | 348 +
.../components/uni-nav-bar/uni-status-bar.vue | 27 +
uni_modules/uni-nav-bar/package.json | 89 +
uni_modules/uni-nav-bar/readme.md | 15 +
uni_modules/uni-notice-bar/changelog.md | 16 +
.../uni-notice-bar/uni-notice-bar.vue | 395 +
uni_modules/uni-notice-bar/package.json | 90 +
uni_modules/uni-notice-bar/readme.md | 13 +
uni_modules/uni-number-box/changelog.md | 25 +
.../uni-number-box/uni-number-box.vue | 220 +
uni_modules/uni-number-box/package.json | 85 +
uni_modules/uni-number-box/readme.md | 13 +
uni_modules/uni-rate/changelog.md | 25 +
.../uni-rate/components/uni-rate/uni-rate.vue | 361 +
uni_modules/uni-rate/package.json | 88 +
uni_modules/uni-rate/readme.md | 12 +
uni_modules/uni-row/changelog.md | 10 +
.../uni-row/components/uni-col/uni-col.vue | 317 +
.../uni-row/components/uni-row/uni-row.vue | 190 +
uni_modules/uni-row/package.json | 87 +
uni_modules/uni-row/readme.md | 10 +
uni_modules/uni-scss/changelog.md | 8 +
uni_modules/uni-scss/index.scss | 1 +
uni_modules/uni-scss/manifest.json | 95 +
uni_modules/uni-scss/package.json | 82 +
uni_modules/uni-scss/readme.md | 4 +
uni_modules/uni-scss/styles/index.scss | 7 +
.../uni-scss/styles/setting/_border.scss | 3 +
.../uni-scss/styles/setting/_color.scss | 66 +
.../uni-scss/styles/setting/_radius.scss | 55 +
.../uni-scss/styles/setting/_space.scss | 56 +
.../uni-scss/styles/setting/_styles.scss | 167 +
.../uni-scss/styles/setting/_text.scss | 24 +
.../uni-scss/styles/setting/_variables.scss | 146 +
.../uni-scss/styles/tools/functions.scss | 19 +
uni_modules/uni-scss/theme.scss | 31 +
uni_modules/uni-scss/variables.scss | 62 +
uni_modules/uni-search-bar/changelog.md | 33 +
.../components/uni-search-bar/i18n/en.json | 4 +
.../components/uni-search-bar/i18n/index.js | 8 +
.../uni-search-bar/i18n/zh-Hans.json | 4 +
.../uni-search-bar/i18n/zh-Hant.json | 4 +
.../uni-search-bar/uni-search-bar.vue | 298 +
uni_modules/uni-search-bar/package.json | 89 +
uni_modules/uni-search-bar/readme.md | 14 +
.../uni-segmented-control/changelog.md | 9 +
.../uni-segmented-control.vue | 145 +
.../uni-segmented-control/package.json | 87 +
uni_modules/uni-segmented-control/readme.md | 13 +
uni_modules/uni-steps/changelog.md | 16 +
.../components/uni-steps/uni-steps.vue | 269 +
uni_modules/uni-steps/package.json | 89 +
uni_modules/uni-steps/readme.md | 13 +
uni_modules/uni-swiper-dot/changelog.md | 12 +
.../uni-swiper-dot/uni-swiper-dot.vue | 218 +
uni_modules/uni-swiper-dot/package.json | 87 +
uni_modules/uni-swiper-dot/readme.md | 11 +
uni_modules/uni-tag/changelog.md | 21 +
.../uni-tag/components/uni-tag/uni-tag.vue | 252 +
uni_modules/uni-tag/package.json | 87 +
uni_modules/uni-tag/readme.md | 13 +
uni_modules/uni-title/changelog.md | 10 +
.../components/uni-title/uni-title.vue | 171 +
uni_modules/uni-title/package.json | 88 +
uni_modules/uni-title/readme.md | 14 +
uni_modules/uni-tooltip/changelog.md | 10 +
.../components/uni-tooltip/uni-tooltip.vue | 68 +
uni_modules/uni-tooltip/package.json | 83 +
uni_modules/uni-tooltip/readme.md | 8 +
uni_modules/uni-transition/changelog.md | 20 +
.../uni-transition/createAnimation.js | 128 +
.../uni-transition/uni-transition.vue | 299 +
uni_modules/uni-transition/package.json | 87 +
uni_modules/uni-transition/readme.md | 11 +
.../components/u-avatar/u-avatar.vue | 270 +
.../components/u-count-down/u-count-down.vue | 175 +
.../components/u-count-down/utils.js | 62 +
.../vk-uview-ui/components/u-icon/u-icon.vue | 369 +
.../components/u-image/u-image.vue | 283 +
.../components/u-input/u-input.vue | 466 +
.../components/u-lazy-load/u-lazy-load.vue | 254 +
.../components/u-loading/u-loading.vue | 108 +
.../components/u-loadmore/u-loadmore.vue | 204 +
.../vk-uview-ui/components/u-mask/u-mask.vue | 137 +
.../components/u-modal/u-modal.vue | 339 +
.../components/u-navbar/u-navbar.vue | 315 +
.../components/u-notice-bar/u-notice-bar.vue | 273 +
.../components/u-search/u-search.vue | 357 +
.../components/u-swiper-indicator.vue | 135 +
.../u-swiper-plus/u-swiper-plus.vue | 529 +
.../components/u-swiper/u-swiper.vue | 341 +
.../components/u-switch/u-switch.vue | 191 +
.../components/u-table/u-table.vue | 85 +
.../u-tabs-swiper/u-tabs-swiper.vue | 490 +
.../vk-uview-ui/components/u-tabs/u-tabs.vue | 399 +
.../vk-uview-ui/components/u-tag/u-tag.vue | 295 +
.../vk-uview-ui/components/u-td/u-td.vue | 66 +
.../vk-uview-ui/components/u-th/u-th.vue | 62 +
.../u-time-line-item/u-time-line-item.vue | 83 +
.../components/u-time-line/u-time-line.vue | 43 +
.../components/u-toast/u-toast.vue | 220 +
.../vk-uview-ui/components/u-tr/u-tr.vue | 25 +
.../u-verification-code.vue | 175 +
.../components/vk-uview-ui/vk-uview-ui.vue | 15 +
uni_modules/vk-uview-ui/iconfont.css | 910 ++
uni_modules/vk-uview-ui/index.js | 149 +
uni_modules/vk-uview-ui/index.scss | 23 +
.../vk-uview-ui/libs/address/areas.json | 1 +
.../vk-uview-ui/libs/address/citys.json | 1 +
.../vk-uview-ui/libs/address/provinces.json | 1 +
uni_modules/vk-uview-ui/libs/config/config.js | 15 +
uni_modules/vk-uview-ui/libs/config/zIndex.js | 20 +
uni_modules/vk-uview-ui/libs/css/color.scss | 155 +
uni_modules/vk-uview-ui/libs/css/common.scss | 176 +
.../libs/css/style.components.scss | 7 +
.../vk-uview-ui/libs/css/style.h5.scss | 8 +
.../vk-uview-ui/libs/css/style.mp.scss | 72 +
.../vk-uview-ui/libs/css/style.nvue.scss | 3 +
.../vk-uview-ui/libs/css/style.vue.scss | 175 +
.../vk-uview-ui/libs/function/$parent.js | 18 +
.../vk-uview-ui/libs/function/addStyle.js | 42 +
.../vk-uview-ui/libs/function/addUnit.js | 8 +
uni_modules/vk-uview-ui/libs/function/bem.js | 4 +
.../vk-uview-ui/libs/function/color.js | 37 +
.../libs/function/colorGradient.js | 134 +
.../vk-uview-ui/libs/function/debounce.js | 29 +
.../vk-uview-ui/libs/function/deepClone.js | 23 +
.../vk-uview-ui/libs/function/deepMerge.js | 30 +
.../vk-uview-ui/libs/function/getParent.js | 47 +
uni_modules/vk-uview-ui/libs/function/guid.js | 41 +
uni_modules/vk-uview-ui/libs/function/md5.js | 385 +
.../vk-uview-ui/libs/function/queryParams.js | 58 +
.../vk-uview-ui/libs/function/random.js | 10 +
.../vk-uview-ui/libs/function/randomArray.js | 7 +
.../vk-uview-ui/libs/function/route.js | 122 +
uni_modules/vk-uview-ui/libs/function/sys.js | 9 +
uni_modules/vk-uview-ui/libs/function/test.js | 287 +
.../vk-uview-ui/libs/function/throttle.js | 34 +
.../vk-uview-ui/libs/function/timeFormat.js | 51 +
.../vk-uview-ui/libs/function/timeFrom.js | 47 +
.../vk-uview-ui/libs/function/toast.js | 9 +
uni_modules/vk-uview-ui/libs/function/trim.js | 15 +
.../vk-uview-ui/libs/function/type2icon.js | 35 +
uni_modules/vk-uview-ui/libs/mixin/mixin.js | 86 +
uni_modules/vk-uview-ui/libs/mixin/mpShare.js | 18 +
uni_modules/vk-uview-ui/libs/request/index.js | 169 +
uni_modules/vk-uview-ui/libs/store/index.js | 19 +
.../vk-uview-ui/libs/util/async-validator.js | 1356 +++
uni_modules/vk-uview-ui/libs/util/emitter.js | 64 +
uni_modules/vk-uview-ui/package.json | 82 +
uni_modules/vk-uview-ui/theme.scss | 38 +
.../z-paging-cell/z-paging-cell.vue | 39 +
.../z-paging-empty-view.vue | 189 +
.../z-paging-swiper-item.vue | 143 +
.../z-paging-swiper/z-paging-swiper.vue | 167 +
.../components/z-paging-load-more.vue | 178 +
.../z-paging/components/z-paging-refresh.vue | 208 +
.../components/z-paging/config/index.js | 3 +
.../components/z-paging/css/z-paging-main.css | 237 +
.../z-paging/css/z-paging-static.css | 50 +
.../z-paging/components/z-paging/i18n/en.json | 23 +
.../components/z-paging/i18n/index.js | 8 +
.../components/z-paging/i18n/zh-Hans.json | 23 +
.../components/z-paging/i18n/zh-Hant.json | 23 +
.../z-paging/js/hooks/useZPaging.js | 25 +
.../z-paging/js/hooks/useZPagingComp.js | 25 +
.../z-paging/js/modules/back-to-top.js | 125 +
.../z-paging/js/modules/chat-record-mode.js | 149 +
.../z-paging/js/modules/common-layout.js | 141 +
.../z-paging/js/modules/data-handle.js | 738 ++
.../components/z-paging/js/modules/empty.js | 144 +
.../components/z-paging/js/modules/i18n.js | 119 +
.../z-paging/js/modules/load-more.js | 370 +
.../components/z-paging/js/modules/loading.js | 95 +
.../components/z-paging/js/modules/nvue.js | 255 +
.../z-paging/js/modules/refresher.js | 824 ++
.../z-paging/js/modules/scroller.js | 518 +
.../z-paging/js/modules/virtual-list.js | 512 +
.../z-paging/js/z-paging-constant.js | 19 +
.../components/z-paging/js/z-paging-enum.js | 45 +
.../z-paging/js/z-paging-interceptor.js | 97 +
.../components/z-paging/js/z-paging-main.js | 503 +
.../components/z-paging/js/z-paging-mixin.js | 22 +
.../components/z-paging/js/z-paging-static.js | 13 +
.../components/z-paging/js/z-paging-utils.js | 270 +
.../z-paging/wxs/z-paging-renderjs.js | 67 +
.../components/z-paging/wxs/z-paging-wxs.wxs | 382 +
.../z-paging/components/z-paging/z-paging.vue | 345 +
uni_modules/z-paging/global.d.ts | 723 ++
uni_modules/z-paging/package.json | 88 +
vite.config.js | 34 +
962 files changed, 172070 insertions(+)
create mode 100644 .env
create mode 100644 .gitignore
create mode 100644 .prettierignore
create mode 100644 .prettierrc
create mode 100644 App.vue
create mode 100644 androidPrivacy.json
create mode 100644 components/custom-back-to-top/custom-back-to-top.vue
create mode 100644 components/htz-image-upload/htz-image-upload.vue
create mode 100644 components/qrcode-modal/qrcode-modal.vue
create mode 100644 components/search-modal/search-modal.vue
create mode 100644 components/thorui/tui-actionsheet/tui-actionsheet.vue
create mode 100644 components/thorui/tui-badge/tui-badge.vue
create mode 100644 components/thorui/tui-bottom-popup/tui-bottom-popup.vue
create mode 100644 components/thorui/tui-bubble-popup/tui-bubble-popup.vue
create mode 100644 components/thorui/tui-circular-progress/tui-circular-progress.vue
create mode 100644 components/thorui/tui-icon/tui-icon.js
create mode 100644 components/thorui/tui-icon/tui-icon.vue
create mode 100644 components/thorui/tui-modal/tui-modal.vue
create mode 100644 components/thorui/tui-navigation-bar/tui-navigation-bar.vue
create mode 100644 components/thorui/tui-numberbox/tui-numberbox.vue
create mode 100644 components/thorui/tui-sticky/tui-sticky.vue
create mode 100644 components/thorui/tui-tabbar/tui-tabbar.vue
create mode 100644 components/thorui/tui-tabs/tui-tabs.vue
create mode 100644 index.html
create mode 100644 jsconfig.json
create mode 100644 main.js
create mode 100644 manifest.json
create mode 100644 package.json
create mode 100644 pages.json
create mode 100644 pages/app/sign.vue
create mode 100644 pages/chat/components/goods.vue
create mode 100644 pages/chat/components/messageInput.vue
create mode 100644 pages/chat/components/messageList.vue
create mode 100644 pages/chat/components/messageListItem.vue
create mode 100644 pages/chat/components/order.vue
create mode 100644 pages/chat/components/select-popup.vue
create mode 100644 pages/chat/components/toolsPopup.vue
create mode 100644 pages/chat/index.vue
create mode 100644 pages/chat/util/constants.js
create mode 100644 pages/chat/util/emoji.js
create mode 100644 pages/clerk/apply/components/formAvatar.vue
create mode 100644 pages/clerk/apply/components/formCity.vue
create mode 100644 pages/clerk/apply/components/formImage.vue
create mode 100644 pages/clerk/apply/components/formSex.vue
create mode 100644 pages/clerk/apply/components/formVoice.vue
create mode 100644 pages/clerk/apply/edit.vue
create mode 100644 pages/clerk/apply/index.vue
create mode 100644 pages/clerk/detail/components/detail-navbar.vue
create mode 100644 pages/clerk/detail/components/gameBox.vue
create mode 100644 pages/clerk/detail/components/giftList.vue
create mode 100644 pages/clerk/detail/components/giftPopup.vue
create mode 100644 pages/clerk/detail/components/layout.vue
create mode 100644 pages/clerk/detail/components/navBar.vue
create mode 100644 pages/clerk/detail/components/orderPopup.vue
create mode 100644 pages/clerk/detail/components/photoBox.vue
create mode 100644 pages/clerk/detail/components/postList.vue
create mode 100644 pages/clerk/detail/components/priceList.vue
create mode 100644 pages/clerk/detail/components/radioBox.vue
create mode 100644 pages/clerk/detail/components/rateList.vue
create mode 100644 pages/clerk/detail/components/starList.vue
create mode 100644 pages/clerk/detail/components/stickyBox.vue
create mode 100644 pages/clerk/detail/components/table-bd.vue
create mode 100644 pages/clerk/detail/components/table-td.vue
create mode 100644 pages/clerk/detail/components/table-tr.vue
create mode 100644 pages/clerk/detail/components/tableList.vue
create mode 100644 pages/clerk/detail/components/userBox.vue
create mode 100644 pages/clerk/detail/components/voicePlay.vue
create mode 100644 pages/clerk/detail/index.vue
create mode 100644 pages/clerk/fans/components/layout.vue
create mode 100644 pages/clerk/fans/components/orderList.vue
create mode 100644 pages/clerk/fans/list.vue
create mode 100644 pages/commission/commission-ranking.vue
create mode 100644 pages/commission/components/account-info.vue
create mode 100644 pages/commission/components/account-type-select.vue
create mode 100644 pages/commission/components/commission-auth.vue
create mode 100644 pages/commission/components/commission-info.vue
create mode 100644 pages/commission/components/commission-log.vue
create mode 100644 pages/commission/components/commission-menu.vue
create mode 100644 pages/commission/goods.vue
create mode 100644 pages/commission/index.vue
create mode 100644 pages/commission/order.vue
create mode 100644 pages/commission/promoter.vue
create mode 100644 pages/commission/team.vue
create mode 100644 pages/commission/wallet.vue
create mode 100644 pages/commission/withdraw.vue
create mode 100644 pages/coupon/detail.vue
create mode 100644 pages/coupon/list.vue
create mode 100644 pages/goods/comment/add.vue
create mode 100644 pages/goods/comment/worker/add.vue
create mode 100644 pages/im/components/cardNotice.vue
create mode 100644 pages/im/components/cardSwiper.vue
create mode 100644 pages/im/components/chatBar.vue
create mode 100644 pages/im/components/layout.vue
create mode 100644 pages/im/components/navigationBar.vue
create mode 100644 pages/im/components/viewItem.vue
create mode 100644 pages/im/index - 副本.vue
create mode 100644 pages/im/index.vue
create mode 100644 pages/im/util/emoji.js
create mode 100644 pages/index/cart.vue
create mode 100644 pages/index/category.vue
create mode 100644 pages/index/components/first-one.vue
create mode 100644 pages/index/components/first-two.vue
create mode 100644 pages/index/components/second-one.vue
create mode 100644 pages/index/index.vue
create mode 100644 pages/index/login.vue
create mode 100644 pages/index/page.vue
create mode 100644 pages/index/search.vue
create mode 100644 pages/index/user.vue
create mode 100644 pages/order/addressSelection.vue
create mode 100644 pages/order/aftersale/apply.vue
create mode 100644 pages/order/aftersale/detail.vue
create mode 100644 pages/order/aftersale/list.vue
create mode 100644 pages/order/aftersale/log-item.vue
create mode 100644 pages/order/aftersale/log.vue
create mode 100644 pages/order/aftersale/return-delivery.vue
create mode 100644 pages/order/blind/components/layout.vue
create mode 100644 pages/order/blind/components/orderList.vue
create mode 100644 pages/order/blind/components/tabBox.vue
create mode 100644 pages/order/blind/confirm.vue
create mode 100644 pages/order/blind/detail.vue
create mode 100644 pages/order/blind/list.vue
create mode 100644 pages/order/confirm.vue
create mode 100644 pages/order/detail.vue
create mode 100644 pages/order/express/log.vue
create mode 100644 pages/order/list.vue
create mode 100644 pages/order/my/aftersale/apply.vue
create mode 100644 pages/order/my/aftersale/list.vue
create mode 100644 pages/order/my/components/layout.vue
create mode 100644 pages/order/my/components/orderList.vue
create mode 100644 pages/order/my/components/tabBox.vue
create mode 100644 pages/order/my/confirm.vue
create mode 100644 pages/order/my/detail.vue
create mode 100644 pages/order/my/index.vue
create mode 100644 pages/order/my/list - 副本.vue
create mode 100644 pages/order/my/list.vue
create mode 100644 pages/order/pickUpVerify.vue
create mode 100644 pages/order/receive/components/layout.vue
create mode 100644 pages/order/receive/components/orderList.vue
create mode 100644 pages/order/receive/components/tabBox.vue
create mode 100644 pages/order/receive/index.vue
create mode 100644 pages/order/worker/aftersale/apply.vue
create mode 100644 pages/order/worker/aftersale/list.vue
create mode 100644 pages/order/worker/components/layout.vue
create mode 100644 pages/order/worker/components/orderList.vue
create mode 100644 pages/order/worker/components/tabBox.vue
create mode 100644 pages/order/worker/confirm.vue
create mode 100644 pages/order/worker/detail.vue
create mode 100644 pages/order/worker/list.vue
create mode 100644 pages/pay/index.vue
create mode 100644 pages/pay/point/index.vue
create mode 100644 pages/pay/recharge-log.vue
create mode 100644 pages/pay/recharge.vue
create mode 100644 pages/pay/result.vue
create mode 100644 pages/pay/reward/index.vue
create mode 100644 pages/pay/vip/index.vue
create mode 100644 pages/pay/worker/index.vue
create mode 100644 pages/pay/worker/result.vue
create mode 100644 pages/point/recharge-log.vue
create mode 100644 pages/point/recharge.vue
create mode 100644 pages/point/result.vue
create mode 100644 pages/public/error.vue
create mode 100644 pages/public/faq.vue
create mode 100644 pages/public/richtext.vue
create mode 100644 pages/public/setting.vue
create mode 100644 pages/public/webview.vue
create mode 100644 pages/reward/components/layout.vue
create mode 100644 pages/reward/components/orderList.vue
create mode 100644 pages/reward/list.vue
create mode 100644 pages/tabbar/components/home/actionSheet.vue
create mode 100644 pages/tabbar/components/home/cardList.vue
create mode 100644 pages/tabbar/components/home/categoryCard.vue
create mode 100644 pages/tabbar/components/home/categorySheet.vue
create mode 100644 pages/tabbar/components/home/dazi.vue
create mode 100644 pages/tabbar/components/home/friend.vue
create mode 100644 pages/tabbar/components/home/friend/imgBox.vue
create mode 100644 pages/tabbar/components/home/friend/rankBox.vue
create mode 100644 pages/tabbar/components/home/friend/stickyBox.vue
create mode 100644 pages/tabbar/components/home/friend/topBox.vue
create mode 100644 pages/tabbar/components/home/friend/userCard.vue
create mode 100644 pages/tabbar/components/home/navBar - 副本.vue
create mode 100644 pages/tabbar/components/home/navBar.vue
create mode 100644 pages/tabbar/components/home/noticeBar.vue
create mode 100644 pages/tabbar/components/home/peiwan.vue
create mode 100644 pages/tabbar/components/home/rankBox.vue
create mode 100644 pages/tabbar/components/home/sexSheet.vue
create mode 100644 pages/tabbar/components/home/stickyBox.vue
create mode 100644 pages/tabbar/components/home/topBox.vue
create mode 100644 pages/tabbar/components/home/userCard.vue
create mode 100644 pages/tabbar/components/home/userList.vue
create mode 100644 pages/tabbar/components/home/voicePlay.vue
create mode 100644 pages/tabbar/components/member/layout.vue
create mode 100644 pages/tabbar/components/member/navBar.vue
create mode 100644 pages/tabbar/components/member/viewItem.vue
create mode 100644 pages/tabbar/components/message/friend.vue
create mode 100644 pages/tabbar/components/message/gameBox.vue
create mode 100644 pages/tabbar/components/message/navBar.vue
create mode 100644 pages/tabbar/components/message/peiwan.vue
create mode 100644 pages/tabbar/components/message/viewItem.vue
create mode 100644 pages/tabbar/components/mine/bgBox.vue
create mode 100644 pages/tabbar/components/mine/layout.vue
create mode 100644 pages/tabbar/components/mine/mainBox.vue
create mode 100644 pages/tabbar/components/mine/navBar.vue
create mode 100644 pages/tabbar/components/mine/vipCard.vue
create mode 100644 pages/tabbar/components/trend/clerk-popup.vue
create mode 100644 pages/tabbar/components/trend/fb-popup.vue
create mode 100644 pages/tabbar/components/trend/formCity.vue
create mode 100644 pages/tabbar/components/trend/formImage.vue
create mode 100644 pages/tabbar/components/trend/formVideo.vue
create mode 100644 pages/tabbar/components/trend/formVoice.vue
create mode 100644 pages/tabbar/components/trend/imgBox.vue
create mode 100644 pages/tabbar/components/trend/layout.vue
create mode 100644 pages/tabbar/components/trend/navBar.vue
create mode 100644 pages/tabbar/components/trend/postList.vue
create mode 100644 pages/tabbar/components/trend/userCard.vue
create mode 100644 pages/tabbar/components/trend/videoBox.vue
create mode 100644 pages/tabbar/components/trend/voicePlay.vue
create mode 100644 pages/tabbar/home.vue
create mode 100644 pages/tabbar/index.vue
create mode 100644 pages/tabbar/message.vue
create mode 100644 pages/tabbar/mine.vue
create mode 100644 pages/tabbar/social.vue
create mode 100644 pages/tabbar/trend.vue
create mode 100644 pages/trend/city/components/orderList.vue
create mode 100644 pages/trend/city/list.vue
create mode 100644 pages/trend/detail/components/card.vue
create mode 100644 pages/trend/detail/index.vue
create mode 100644 pages/trend/my/components/orderList.vue
create mode 100644 pages/trend/my/list.vue
create mode 100644 pages/user/address/edit.vue
create mode 100644 pages/user/address/list.vue
create mode 100644 pages/user/detail/components/detail-navbar.vue
create mode 100644 pages/user/detail/components/giftList.vue
create mode 100644 pages/user/detail/components/giftPopup.vue
create mode 100644 pages/user/detail/components/layout.vue
create mode 100644 pages/user/detail/components/navBar.vue
create mode 100644 pages/user/detail/components/photoBox.vue
create mode 100644 pages/user/detail/components/postList.vue
create mode 100644 pages/user/detail/components/starList.vue
create mode 100644 pages/user/detail/components/stickyBox.vue
create mode 100644 pages/user/detail/components/userBox.vue
create mode 100644 pages/user/detail/index.vue
create mode 100644 pages/user/goods-collect.vue
create mode 100644 pages/user/goods-log.vue
create mode 100644 pages/user/goods_details_store/index.vue
create mode 100644 pages/user/info.vue
create mode 100644 pages/user/vip.vue
create mode 100644 pages/user/wallet/money.vue
create mode 100644 pages/user/wallet/score.vue
create mode 100644 pages/worker/blind/components/gameBox.vue
create mode 100644 pages/worker/blind/components/layout.vue
create mode 100644 pages/worker/blind/index.vue
create mode 100644 pages/worker/levelList/components/layout.vue
create mode 100644 pages/worker/levelList/components/levelList.vue
create mode 100644 pages/worker/levelList/components/table-bd.vue
create mode 100644 pages/worker/levelList/components/table-td.vue
create mode 100644 pages/worker/levelList/components/table-tr.vue
create mode 100644 pages/worker/levelList/index.vue
create mode 100644 pages/worker/workerList/components/layout.vue
create mode 100644 pages/worker/workerList/components/workerList.vue
create mode 100644 pages/worker/workerList/index.vue
create mode 100644 pages/worker/workerList/set.vue
create mode 100644 sheep/api/im/memberConversation.js
create mode 100644 sheep/api/im/memberMessage.js
create mode 100644 sheep/api/infra/file.js
create mode 100644 sheep/api/member/address.js
create mode 100644 sheep/api/member/auth.js
create mode 100644 sheep/api/member/point.js
create mode 100644 sheep/api/member/signin.js
create mode 100644 sheep/api/member/social.js
create mode 100644 sheep/api/member/user.js
create mode 100644 sheep/api/migration/app.js
create mode 100644 sheep/api/migration/index.js
create mode 100644 sheep/api/migration/third.js
create mode 100644 sheep/api/pay/channel.js
create mode 100644 sheep/api/pay/order.js
create mode 100644 sheep/api/pay/point.js
create mode 100644 sheep/api/pay/wallet.js
create mode 100644 sheep/api/product/category.js
create mode 100644 sheep/api/product/comment.js
create mode 100644 sheep/api/product/favorite.js
create mode 100644 sheep/api/product/history.js
create mode 100644 sheep/api/product/spu.js
create mode 100644 sheep/api/promotion/activity.js
create mode 100644 sheep/api/promotion/article.js
create mode 100644 sheep/api/promotion/combination.js
create mode 100644 sheep/api/promotion/coupon.js
create mode 100644 sheep/api/promotion/diy.js
create mode 100644 sheep/api/promotion/kefu.js
create mode 100644 sheep/api/promotion/rewardActivity.js
create mode 100644 sheep/api/promotion/seckill.js
create mode 100644 sheep/api/system/area.js
create mode 100644 sheep/api/system/dict.js
create mode 100644 sheep/api/trade/afterSale.js
create mode 100644 sheep/api/trade/brokerage.js
create mode 100644 sheep/api/trade/cart.js
create mode 100644 sheep/api/trade/config.js
create mode 100644 sheep/api/trade/delivery.js
create mode 100644 sheep/api/trade/order.js
create mode 100644 sheep/api/worker/clerk.js
create mode 100644 sheep/api/worker/reward.js
create mode 100644 sheep/api/worker/trend.js
create mode 100644 sheep/components/s-activity-pop/s-activity-pop.vue
create mode 100644 sheep/components/s-address-item/s-address-item.vue
create mode 100644 sheep/components/s-auth-modal/components/account-login.vue
create mode 100644 sheep/components/s-auth-modal/components/change-mobile.vue
create mode 100644 sheep/components/s-auth-modal/components/change-password.vue
create mode 100644 sheep/components/s-auth-modal/components/chat-authorization.vue
create mode 100644 sheep/components/s-auth-modal/components/formImage.vue
create mode 100644 sheep/components/s-auth-modal/components/formQrcode.vue
create mode 100644 sheep/components/s-auth-modal/components/formSex.vue
create mode 100644 sheep/components/s-auth-modal/components/h5-authorization.vue
create mode 100644 sheep/components/s-auth-modal/components/mp-authorization.vue
create mode 100644 sheep/components/s-auth-modal/components/reset-password.vue
create mode 100644 sheep/components/s-auth-modal/components/sms-login.vue
create mode 100644 sheep/components/s-auth-modal/index.scss
create mode 100644 sheep/components/s-auth-modal/s-auth-modal.vue
create mode 100644 sheep/components/s-block-item/s-block-item.vue
create mode 100644 sheep/components/s-block/s-block.vue
create mode 100644 sheep/components/s-count-down/s-count-down.vue
create mode 100644 sheep/components/s-coupon-block/s-coupon-block.vue
create mode 100644 sheep/components/s-coupon-card/s-coupon-card.vue
create mode 100644 sheep/components/s-coupon-get/s-coupon-get.vue
create mode 100644 sheep/components/s-coupon-list/s-coupon-list.vue
create mode 100644 sheep/components/s-coupon-select/s-coupon-select.vue
create mode 100644 sheep/components/s-custom-navbar/components/navbar-item.vue
create mode 100644 sheep/components/s-custom-navbar/components/navbar.vue
create mode 100644 sheep/components/s-custom-navbar/s-custom-navbar.vue
create mode 100644 sheep/components/s-discount-list/s-discount-list.vue
create mode 100644 sheep/components/s-empty/s-empty.vue
create mode 100644 sheep/components/s-float-menu/s-float-menu.vue
create mode 100644 sheep/components/s-goods-card/s-goods-card.vue
create mode 100644 sheep/components/s-goods-column/s-goods-column.vue
create mode 100644 sheep/components/s-goods-item/s-goods-item.vue
create mode 100644 sheep/components/s-goods-scroll/s-goods-scroll.vue
create mode 100644 sheep/components/s-goods-shelves/s-goods-shelves.vue
create mode 100644 sheep/components/s-groupon-block/s-groupon-block.vue
create mode 100644 sheep/components/s-hotzone-block/s-hotzone-block.vue
create mode 100644 sheep/components/s-image-banner/s-image-banner.vue
create mode 100644 sheep/components/s-image-block/s-image-block.vue
create mode 100644 sheep/components/s-image-cube/s-image-cube.vue
create mode 100644 sheep/components/s-layout/s-layout.vue
create mode 100644 sheep/components/s-line-block/s-line-block.vue
create mode 100644 sheep/components/s-live-block/s-live-block.vue
create mode 100644 sheep/components/s-live-card/s-live-card.vue
create mode 100644 sheep/components/s-menu-button/s-menu-button.vue
create mode 100644 sheep/components/s-menu-grid/s-menu-grid.vue
create mode 100644 sheep/components/s-menu-list/s-menu-list.vue
create mode 100644 sheep/components/s-menu-tools/s-menu-tools.vue
create mode 100644 sheep/components/s-notice-block/s-notice-block.vue
create mode 100644 sheep/components/s-order-card/s-order-card.vue
create mode 100644 sheep/components/s-popup-image/s-popup-image.vue
create mode 100644 sheep/components/s-richtext-block/s-richtext-block.vue
create mode 100644 sheep/components/s-search-block/s-search-block.vue
create mode 100644 sheep/components/s-seckill-block/s-seckill-block.vue
create mode 100644 sheep/components/s-select-groupon-sku/s-select-groupon-sku.vue
create mode 100644 sheep/components/s-select-seckill-sku/s-select-seckill-sku.vue
create mode 100644 sheep/components/s-select-sku/s-select-sku.vue
create mode 100644 sheep/components/s-share-modal/canvas-poster/index.vue
create mode 100644 sheep/components/s-share-modal/canvas-poster/poster/goods.js
create mode 100644 sheep/components/s-share-modal/canvas-poster/poster/groupon.js
create mode 100644 sheep/components/s-share-modal/canvas-poster/poster/index.js
create mode 100644 sheep/components/s-share-modal/canvas-poster/poster/user.js
create mode 100644 sheep/components/s-share-modal/s-share-modal.vue
create mode 100644 sheep/components/s-statusbar/s-statusbar.vue
create mode 100644 sheep/components/s-tabbar/s-tabbar.vue
create mode 100644 sheep/components/s-title-block/s-title-block.vue
create mode 100644 sheep/components/s-uploader/choose-and-upload-file.js
create mode 100644 sheep/components/s-uploader/s-uploader.vue
create mode 100644 sheep/components/s-uploader/upload-file.vue
create mode 100644 sheep/components/s-uploader/upload-image.vue
create mode 100644 sheep/components/s-uploader/utils.js
create mode 100644 sheep/components/s-user-card/s-user-card.vue
create mode 100644 sheep/components/s-video-block/s-video-block.vue
create mode 100644 sheep/components/s-wallet-card/s-wallet-card.vue
create mode 100644 sheep/components/s-worker-item/s-worker-item.vue
create mode 100644 sheep/config/index.js
create mode 100644 sheep/config/zIndex.js
create mode 100644 sheep/helper/digit.js
create mode 100644 sheep/helper/index.js
create mode 100644 sheep/helper/test.js
create mode 100644 sheep/helper/throttle.js
create mode 100644 sheep/helper/tools.js
create mode 100644 sheep/helper/utils.js
create mode 100644 sheep/hooks/useApp.js
create mode 100644 sheep/hooks/useGoods.js
create mode 100644 sheep/hooks/useModal.js
create mode 100644 sheep/hooks/useWebSocket.js
create mode 100644 sheep/index.js
create mode 100644 sheep/libs/mplive-manifest-plugin.js
create mode 100644 sheep/libs/permission.js
create mode 100644 sheep/libs/sdk-h5-weixin.js
create mode 100644 sheep/platform/index.js
create mode 100644 sheep/platform/pay.js
create mode 100644 sheep/platform/provider/apple/app.js
create mode 100644 sheep/platform/provider/apple/index.js
create mode 100644 sheep/platform/provider/wechat/index.js
create mode 100644 sheep/platform/provider/wechat/miniProgram.js
create mode 100644 sheep/platform/provider/wechat/officialAccount.js
create mode 100644 sheep/platform/provider/wechat/openPlatform.js
create mode 100644 sheep/platform/share.js
create mode 100644 sheep/request/index.js
create mode 100644 sheep/router/index.js
create mode 100644 sheep/router/utils/strip-json-comments.js
create mode 100644 sheep/router/utils/uni-read-pages-v3.js
create mode 100644 sheep/scss/_main.scss
create mode 100644 sheep/scss/_mixins.scss
create mode 100644 sheep/scss/_tools.scss
create mode 100644 sheep/scss/_var.scss
create mode 100644 sheep/scss/font/OPPOSANS-M-subfont.ttf
create mode 100644 sheep/scss/icon/_coloricon.scss
create mode 100644 sheep/scss/icon/_icon.scss
create mode 100644 sheep/scss/icon/_sheepicon.scss
create mode 100644 sheep/scss/icon/_style.scss
create mode 100644 sheep/scss/index.scss
create mode 100644 sheep/scss/style/_avatar.scss
create mode 100644 sheep/scss/style/_background.scss
create mode 100644 sheep/scss/style/_border.scss
create mode 100644 sheep/scss/style/_button.scss
create mode 100644 sheep/scss/style/_card.scss
create mode 100644 sheep/scss/style/_code.scss
create mode 100644 sheep/scss/style/_flex.scss
create mode 100644 sheep/scss/style/_form.scss
create mode 100644 sheep/scss/style/_grid.scss
create mode 100644 sheep/scss/style/_markdown.scss
create mode 100644 sheep/scss/style/_menu.scss
create mode 100644 sheep/scss/style/_shadow.scss
create mode 100644 sheep/scss/style/_table.scss
create mode 100644 sheep/scss/style/_tag.scss
create mode 100644 sheep/scss/style/_text.scss
create mode 100644 sheep/scss/theme/_dark.scss
create mode 100644 sheep/scss/theme/_light.scss
create mode 100644 sheep/scss/theme/_style.scss
create mode 100644 sheep/scss/ui.scss
create mode 100644 sheep/store/app.js
create mode 100644 sheep/store/cart.js
create mode 100644 sheep/store/index.js
create mode 100644 sheep/store/modal.js
create mode 100644 sheep/store/sys.js
create mode 100644 sheep/store/user.js
create mode 100644 sheep/ui/su-coupon/su-coupon.vue
create mode 100644 sheep/ui/su-data-checkbox/su-data-checkbox.vue
create mode 100644 sheep/ui/su-dialog/su-dialog.vue
create mode 100644 sheep/ui/su-fixed/su-fixed.vue
create mode 100644 sheep/ui/su-image/su-image.vue
create mode 100644 sheep/ui/su-inner-navbar/su-inner-navbar.vue
create mode 100644 sheep/ui/su-navbar/su-navbar.vue
create mode 100644 sheep/ui/su-notice-bar/su-notice-bar.vue
create mode 100644 sheep/ui/su-number-box/su-number-box.vue
create mode 100644 sheep/ui/su-popover/su-popover.vue
create mode 100644 sheep/ui/su-popup/keypress.js
create mode 100644 sheep/ui/su-popup/su-popup.vue
create mode 100644 sheep/ui/su-progress/su-progress.vue
create mode 100644 sheep/ui/su-radio/su-radio.vue
create mode 100644 sheep/ui/su-region-picker/su-region-picker.vue
create mode 100644 sheep/ui/su-status-bar/su-status-bar.vue
create mode 100644 sheep/ui/su-sticky/su-sticky.vue
create mode 100644 sheep/ui/su-subline/su-subline.vue
create mode 100644 sheep/ui/su-swiper/su-swiper.vue
create mode 100644 sheep/ui/su-switch/su-switch.vue
create mode 100644 sheep/ui/su-tab-item/su-tab-item.vue
create mode 100644 sheep/ui/su-tab/su-tab.vue
create mode 100644 sheep/ui/su-tabbar-item/su-tabbar-item.vue
create mode 100644 sheep/ui/su-tabbar/su-tabbar.vue
create mode 100644 sheep/ui/su-tabs-item/props.js
create mode 100644 sheep/ui/su-tabs-item/su-tabs-item.vue
create mode 100644 sheep/ui/su-tabs/su-tabs.vue
create mode 100644 sheep/ui/su-time-line/su-time-line.vue
create mode 100644 sheep/ui/su-timeline-item/su-timeline-item.vue
create mode 100644 sheep/ui/su-toolbar/su-toolbar.vue
create mode 100644 sheep/ui/su-video/su-video.vue
create mode 100644 sheep/url/index.js
create mode 100644 sheep/util/adVideoUtils.js
create mode 100644 sheep/util/const.js
create mode 100644 sheep/util/index.js
create mode 100644 sheep/validate/form.js
create mode 100644 static/activity-left.png
create mode 100644 static/activity-right.png
create mode 100644 static/cart-empty.png
create mode 100644 static/collect-empty.png
create mode 100644 static/comment-empty.png
create mode 100644 static/coupon-empty.png
create mode 100644 static/css/iconfont.css
create mode 100644 static/data-empty.png
create mode 100644 static/goods-empty.png
create mode 100644 static/images/audio.png
create mode 100644 static/images/line.png
create mode 100644 static/images/writeOff.png
create mode 100644 static/internet-empty.png
create mode 100644 static/order-empty.png
create mode 100644 static/soldout-empty.png
create mode 100644 uni.scss
create mode 100644 uni_modules/all-speech/changelog.md
create mode 100644 uni_modules/all-speech/components/all-speech/all-speech.vue
create mode 100644 uni_modules/all-speech/js_sdk/h5-speech/speech.js
create mode 100644 uni_modules/all-speech/js_sdk/wa-permission/permission.js
create mode 100644 uni_modules/all-speech/package.json
create mode 100644 uni_modules/all-speech/readme.md
create mode 100644 uni_modules/c-svga/changelog.md
create mode 100644 uni_modules/c-svga/components/c-svga/c-svga.vue
create mode 100644 uni_modules/c-svga/components/c-svga/js/getfile.js
create mode 100644 uni_modules/c-svga/components/c-svga/js/render.js
create mode 100644 uni_modules/c-svga/components/c-svga/js/uuid.js
create mode 100644 uni_modules/c-svga/node_modules/howler/LICENSE.md
create mode 100644 uni_modules/c-svga/node_modules/howler/README.md
create mode 100644 uni_modules/c-svga/node_modules/howler/dist/howler.core.min.js
create mode 100644 uni_modules/c-svga/node_modules/howler/dist/howler.js
create mode 100644 uni_modules/c-svga/node_modules/howler/dist/howler.min.js
create mode 100644 uni_modules/c-svga/node_modules/howler/dist/howler.spatial.min.js
create mode 100644 uni_modules/c-svga/node_modules/howler/package.json
create mode 100644 uni_modules/c-svga/node_modules/howler/src/howler.core.js
create mode 100644 uni_modules/c-svga/node_modules/howler/src/plugins/howler.spatial.js
create mode 100644 uni_modules/c-svga/node_modules/svgaplayer-weapp/README.md
create mode 100644 uni_modules/c-svga/node_modules/svgaplayer-weapp/build.js
create mode 100644 uni_modules/c-svga/node_modules/svgaplayer-weapp/dist/svgaplayer.weapp.js
create mode 100644 uni_modules/c-svga/node_modules/svgaplayer-weapp/package.json
create mode 100644 uni_modules/c-svga/node_modules/svgaplayer-weapp/protobuf_mp/protobuf.js
create mode 100644 uni_modules/c-svga/node_modules/svgaplayer-weapp/protobuf_mp/src/EventEmitter.js
create mode 100644 uni_modules/c-svga/node_modules/svgaplayer-weapp/protobuf_mp/src/asPromise.js
create mode 100644 uni_modules/c-svga/node_modules/svgaplayer-weapp/protobuf_mp/src/base64.js
create mode 100644 uni_modules/c-svga/node_modules/svgaplayer-weapp/protobuf_mp/src/common.js
create mode 100644 uni_modules/c-svga/node_modules/svgaplayer-weapp/protobuf_mp/src/converter.js
create mode 100644 uni_modules/c-svga/node_modules/svgaplayer-weapp/protobuf_mp/src/decoder.js
create mode 100644 uni_modules/c-svga/node_modules/svgaplayer-weapp/protobuf_mp/src/enum.js
create mode 100644 uni_modules/c-svga/node_modules/svgaplayer-weapp/protobuf_mp/src/field.js
create mode 100644 uni_modules/c-svga/node_modules/svgaplayer-weapp/protobuf_mp/src/float.js
create mode 100644 uni_modules/c-svga/node_modules/svgaplayer-weapp/protobuf_mp/src/index-light.js
create mode 100644 uni_modules/c-svga/node_modules/svgaplayer-weapp/protobuf_mp/src/index-minimal.js
create mode 100644 uni_modules/c-svga/node_modules/svgaplayer-weapp/protobuf_mp/src/index.js
create mode 100644 uni_modules/c-svga/node_modules/svgaplayer-weapp/protobuf_mp/src/inquire.js
create mode 100644 uni_modules/c-svga/node_modules/svgaplayer-weapp/protobuf_mp/src/long.js
create mode 100644 uni_modules/c-svga/node_modules/svgaplayer-weapp/protobuf_mp/src/longBits.js
create mode 100644 uni_modules/c-svga/node_modules/svgaplayer-weapp/protobuf_mp/src/mapField.js
create mode 100644 uni_modules/c-svga/node_modules/svgaplayer-weapp/protobuf_mp/src/message.js
create mode 100644 uni_modules/c-svga/node_modules/svgaplayer-weapp/protobuf_mp/src/method.js
create mode 100644 uni_modules/c-svga/node_modules/svgaplayer-weapp/protobuf_mp/src/namespace.js
create mode 100644 uni_modules/c-svga/node_modules/svgaplayer-weapp/protobuf_mp/src/object.js
create mode 100644 uni_modules/c-svga/node_modules/svgaplayer-weapp/protobuf_mp/src/oneof.js
create mode 100644 uni_modules/c-svga/node_modules/svgaplayer-weapp/protobuf_mp/src/parse.js
create mode 100644 uni_modules/c-svga/node_modules/svgaplayer-weapp/protobuf_mp/src/path.js
create mode 100644 uni_modules/c-svga/node_modules/svgaplayer-weapp/protobuf_mp/src/pool.js
create mode 100644 uni_modules/c-svga/node_modules/svgaplayer-weapp/protobuf_mp/src/reader.js
create mode 100644 uni_modules/c-svga/node_modules/svgaplayer-weapp/protobuf_mp/src/reader_buffer.js
create mode 100644 uni_modules/c-svga/node_modules/svgaplayer-weapp/protobuf_mp/src/root.js
create mode 100644 uni_modules/c-svga/node_modules/svgaplayer-weapp/protobuf_mp/src/roots.js
create mode 100644 uni_modules/c-svga/node_modules/svgaplayer-weapp/protobuf_mp/src/rpc.js
create mode 100644 uni_modules/c-svga/node_modules/svgaplayer-weapp/protobuf_mp/src/rpc/service.js
create mode 100644 uni_modules/c-svga/node_modules/svgaplayer-weapp/protobuf_mp/src/service.js
create mode 100644 uni_modules/c-svga/node_modules/svgaplayer-weapp/protobuf_mp/src/tokenize.js
create mode 100644 uni_modules/c-svga/node_modules/svgaplayer-weapp/protobuf_mp/src/type.js
create mode 100644 uni_modules/c-svga/node_modules/svgaplayer-weapp/protobuf_mp/src/types.js
create mode 100644 uni_modules/c-svga/node_modules/svgaplayer-weapp/protobuf_mp/src/typescript.jsdoc
create mode 100644 uni_modules/c-svga/node_modules/svgaplayer-weapp/protobuf_mp/src/utf8.js
create mode 100644 uni_modules/c-svga/node_modules/svgaplayer-weapp/protobuf_mp/src/util.js
create mode 100644 uni_modules/c-svga/node_modules/svgaplayer-weapp/protobuf_mp/src/verifier.js
create mode 100644 uni_modules/c-svga/node_modules/svgaplayer-weapp/protobuf_mp/src/wrappers.js
create mode 100644 uni_modules/c-svga/node_modules/svgaplayer-weapp/protobuf_mp/src/writer.js
create mode 100644 uni_modules/c-svga/node_modules/svgaplayer-weapp/protobuf_mp/src/writer_buffer.js
create mode 100644 uni_modules/c-svga/node_modules/svgaplayer-weapp/src/adaptor.ts
create mode 100644 uni_modules/c-svga/node_modules/svgaplayer-weapp/src/bezier_path.ts
create mode 100644 uni_modules/c-svga/node_modules/svgaplayer-weapp/src/ellipse_path.ts
create mode 100644 uni_modules/c-svga/node_modules/svgaplayer-weapp/src/frame_entity.ts
create mode 100644 uni_modules/c-svga/node_modules/svgaplayer-weapp/src/main.ts
create mode 100644 uni_modules/c-svga/node_modules/svgaplayer-weapp/src/pako.js
create mode 100644 uni_modules/c-svga/node_modules/svgaplayer-weapp/src/parser.ts
create mode 100644 uni_modules/c-svga/node_modules/svgaplayer-weapp/src/player.ts
create mode 100644 uni_modules/c-svga/node_modules/svgaplayer-weapp/src/proto.js
create mode 100644 uni_modules/c-svga/node_modules/svgaplayer-weapp/src/rect_path.ts
create mode 100644 uni_modules/c-svga/node_modules/svgaplayer-weapp/src/renderer.ts
create mode 100644 uni_modules/c-svga/node_modules/svgaplayer-weapp/src/sprite_entity.ts
create mode 100644 uni_modules/c-svga/node_modules/svgaplayer-weapp/src/value_animator.ts
create mode 100644 uni_modules/c-svga/node_modules/svgaplayer-weapp/src/video_entity.ts
create mode 100644 uni_modules/c-svga/node_modules/svgaplayer-weapp/svgaplayer-weapp.d.ts
create mode 100644 uni_modules/c-svga/node_modules/svgaplayer-weapp/tsconfig.json
create mode 100644 uni_modules/c-svga/node_modules/svgaplayerweb/CreateJS.README.md
create mode 100644 uni_modules/c-svga/node_modules/svgaplayerweb/ISSUE_TEMPLATE.md
create mode 100644 uni_modules/c-svga/node_modules/svgaplayerweb/LICENSE
create mode 100644 uni_modules/c-svga/node_modules/svgaplayerweb/LayaBox.README.md
create mode 100644 uni_modules/c-svga/node_modules/svgaplayerweb/README.md
create mode 100644 uni_modules/c-svga/node_modules/svgaplayerweb/README.zh.md
create mode 100644 uni_modules/c-svga/node_modules/svgaplayerweb/build/svga.createjs.min.js
create mode 100644 uni_modules/c-svga/node_modules/svgaplayerweb/build/svga.ie.min.js
create mode 100644 uni_modules/c-svga/node_modules/svgaplayerweb/build/svga.layabox.min.js
create mode 100644 uni_modules/c-svga/node_modules/svgaplayerweb/build/svga.min.js
create mode 100644 uni_modules/c-svga/node_modules/svgaplayerweb/index.d.ts
create mode 100644 uni_modules/c-svga/node_modules/svgaplayerweb/package.json
create mode 100644 uni_modules/c-svga/node_modules/svgaplayerweb/patch/layabox/laya.webgl.js
create mode 100644 uni_modules/c-svga/node_modules/svgaplayerweb/src/Canvas/autoLoader.js
create mode 100644 uni_modules/c-svga/node_modules/svgaplayerweb/src/Canvas/index.js
create mode 100644 uni_modules/c-svga/node_modules/svgaplayerweb/src/Canvas/player.js
create mode 100644 uni_modules/c-svga/node_modules/svgaplayerweb/src/Canvas/renderer.js
create mode 100644 uni_modules/c-svga/node_modules/svgaplayerweb/src/CreateJS/index.js
create mode 100644 uni_modules/c-svga/node_modules/svgaplayerweb/src/CreateJS/player.js
create mode 100644 uni_modules/c-svga/node_modules/svgaplayerweb/src/CreateJS/renderer.js
create mode 100644 uni_modules/c-svga/node_modules/svgaplayerweb/src/LayaBox/index.js
create mode 100644 uni_modules/c-svga/node_modules/svgaplayerweb/src/LayaBox/player.js
create mode 100644 uni_modules/c-svga/node_modules/svgaplayerweb/src/LayaBox/renderer.js
create mode 100644 uni_modules/c-svga/node_modules/svgaplayerweb/src/bezierPath.js
create mode 100644 uni_modules/c-svga/node_modules/svgaplayerweb/src/ellipsePath.js
create mode 100644 uni_modules/c-svga/node_modules/svgaplayerweb/src/frameEntity.js
create mode 100644 uni_modules/c-svga/node_modules/svgaplayerweb/src/mockWorker.js
create mode 100644 uni_modules/c-svga/node_modules/svgaplayerweb/src/parser.js
create mode 100644 uni_modules/c-svga/node_modules/svgaplayerweb/src/proto.js
create mode 100644 uni_modules/c-svga/node_modules/svgaplayerweb/src/rectPath.js
create mode 100644 uni_modules/c-svga/node_modules/svgaplayerweb/src/spriteEntity.js
create mode 100644 uni_modules/c-svga/node_modules/svgaplayerweb/src/videoEntity.js
create mode 100644 uni_modules/c-svga/node_modules/svgaplayerweb/webpack.config.js
create mode 100644 uni_modules/c-svga/package.json
create mode 100644 uni_modules/c-svga/readme.md
create mode 100644 uni_modules/lime-painter/changelog.md
create mode 100644 uni_modules/lime-painter/components/common/relation.js
create mode 100644 uni_modules/lime-painter/components/l-painter-image/l-painter-image.vue
create mode 100644 uni_modules/lime-painter/components/l-painter-qrcode/l-painter-qrcode.vue
create mode 100644 uni_modules/lime-painter/components/l-painter-text/l-painter-text.vue
create mode 100644 uni_modules/lime-painter/components/l-painter-view/l-painter-view.vue
create mode 100644 uni_modules/lime-painter/components/l-painter/l-painter.vue
create mode 100644 uni_modules/lime-painter/components/l-painter/nvue.js
create mode 100644 uni_modules/lime-painter/components/l-painter/painter.js
create mode 100644 uni_modules/lime-painter/components/l-painter/props.js
create mode 100644 uni_modules/lime-painter/components/l-painter/single.js
create mode 100644 uni_modules/lime-painter/components/l-painter/utils.js
create mode 100644 uni_modules/lime-painter/components/lime-painter/lime-painter.vue
create mode 100644 uni_modules/lime-painter/hybrid/html/index.html
create mode 100644 uni_modules/lime-painter/hybrid/html/painter.js
create mode 100644 uni_modules/lime-painter/hybrid/html/uni.webview.1.5.3.js
create mode 100644 uni_modules/lime-painter/package.json
create mode 100644 uni_modules/lime-painter/parser.js
create mode 100644 uni_modules/lime-painter/readme.md
create mode 100644 uni_modules/mp-html/README.md
create mode 100644 uni_modules/mp-html/changelog.md
create mode 100644 uni_modules/mp-html/components/mp-html/mp-html.vue
create mode 100644 uni_modules/mp-html/components/mp-html/node/node.vue
create mode 100644 uni_modules/mp-html/components/mp-html/parser.js
create mode 100644 uni_modules/mp-html/package.json
create mode 100644 uni_modules/mp-html/static/app-plus/mp-html/js/handler.js
create mode 100644 uni_modules/mp-html/static/app-plus/mp-html/js/uni.webview.min.js
create mode 100644 uni_modules/mp-html/static/app-plus/mp-html/local.html
create mode 100644 uni_modules/shmily-drag-image/README.md
create mode 100644 uni_modules/shmily-drag-image/changelog.md
create mode 100644 uni_modules/shmily-drag-image/components/shmily-drag-image/shmily-drag-image.vue
create mode 100644 uni_modules/shmily-drag-image/package.json
create mode 100644 uni_modules/uni-badge/changelog.md
create mode 100644 uni_modules/uni-badge/components/uni-badge/uni-badge.vue
create mode 100644 uni_modules/uni-badge/package.json
create mode 100644 uni_modules/uni-badge/readme.md
create mode 100644 uni_modules/uni-card/changelog.md
create mode 100644 uni_modules/uni-card/components/uni-card/uni-card.vue
create mode 100644 uni_modules/uni-card/package.json
create mode 100644 uni_modules/uni-card/readme.md
create mode 100644 uni_modules/uni-collapse/changelog.md
create mode 100644 uni_modules/uni-collapse/components/uni-collapse-item/uni-collapse-item.vue
create mode 100644 uni_modules/uni-collapse/components/uni-collapse/uni-collapse.vue
create mode 100644 uni_modules/uni-collapse/package.json
create mode 100644 uni_modules/uni-collapse/readme.md
create mode 100644 uni_modules/uni-combox/changelog.md
create mode 100644 uni_modules/uni-combox/components/uni-combox/uni-combox.vue
create mode 100644 uni_modules/uni-combox/package.json
create mode 100644 uni_modules/uni-combox/readme.md
create mode 100644 uni_modules/uni-countdown/changelog.md
create mode 100644 uni_modules/uni-countdown/components/uni-countdown/i18n/en.json
create mode 100644 uni_modules/uni-countdown/components/uni-countdown/i18n/index.js
create mode 100644 uni_modules/uni-countdown/components/uni-countdown/i18n/zh-Hans.json
create mode 100644 uni_modules/uni-countdown/components/uni-countdown/i18n/zh-Hant.json
create mode 100644 uni_modules/uni-countdown/components/uni-countdown/uni-countdown.vue
create mode 100644 uni_modules/uni-countdown/package.json
create mode 100644 uni_modules/uni-countdown/readme.md
create mode 100644 uni_modules/uni-data-checkbox/changelog.md
create mode 100644 uni_modules/uni-data-checkbox/components/uni-data-checkbox/uni-data-checkbox.vue
create mode 100644 uni_modules/uni-data-checkbox/package.json
create mode 100644 uni_modules/uni-data-checkbox/readme.md
create mode 100644 uni_modules/uni-data-picker/changelog.md
create mode 100644 uni_modules/uni-data-picker/components/uni-data-picker/keypress.js
create mode 100644 uni_modules/uni-data-picker/components/uni-data-picker/uni-data-picker.vue
create mode 100644 uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-picker.js
create mode 100644 uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-pickerview.vue
create mode 100644 uni_modules/uni-data-picker/package.json
create mode 100644 uni_modules/uni-data-picker/readme.md
create mode 100644 uni_modules/uni-dateformat/changelog.md
create mode 100644 uni_modules/uni-dateformat/components/uni-dateformat/date-format.js
create mode 100644 uni_modules/uni-dateformat/components/uni-dateformat/uni-dateformat.vue
create mode 100644 uni_modules/uni-dateformat/package.json
create mode 100644 uni_modules/uni-dateformat/readme.md
create mode 100644 uni_modules/uni-datetime-picker/changelog.md
create mode 100644 uni_modules/uni-datetime-picker/components/uni-datetime-picker/calendar-item.vue
create mode 100644 uni_modules/uni-datetime-picker/components/uni-datetime-picker/calendar.js
create mode 100644 uni_modules/uni-datetime-picker/components/uni-datetime-picker/calendar.vue
create mode 100644 uni_modules/uni-datetime-picker/components/uni-datetime-picker/i18n/en.json
create mode 100644 uni_modules/uni-datetime-picker/components/uni-datetime-picker/i18n/index.js
create mode 100644 uni_modules/uni-datetime-picker/components/uni-datetime-picker/i18n/zh-Hans.json
create mode 100644 uni_modules/uni-datetime-picker/components/uni-datetime-picker/i18n/zh-Hant.json
create mode 100644 uni_modules/uni-datetime-picker/components/uni-datetime-picker/keypress.js
create mode 100644 uni_modules/uni-datetime-picker/components/uni-datetime-picker/time-picker.vue
create mode 100644 uni_modules/uni-datetime-picker/components/uni-datetime-picker/uni-datetime-picker.vue
create mode 100644 uni_modules/uni-datetime-picker/components/uni-datetime-picker/util.js
create mode 100644 uni_modules/uni-datetime-picker/package.json
create mode 100644 uni_modules/uni-datetime-picker/readme.md
create mode 100644 uni_modules/uni-drawer/changelog.md
create mode 100644 uni_modules/uni-drawer/components/uni-drawer/keypress.js
create mode 100644 uni_modules/uni-drawer/components/uni-drawer/uni-drawer.vue
create mode 100644 uni_modules/uni-drawer/package.json
create mode 100644 uni_modules/uni-drawer/readme.md
create mode 100644 uni_modules/uni-easyinput/changelog.md
create mode 100644 uni_modules/uni-easyinput/components/uni-easyinput/common.js
create mode 100644 uni_modules/uni-easyinput/components/uni-easyinput/uni-easyinput.vue
create mode 100644 uni_modules/uni-easyinput/package.json
create mode 100644 uni_modules/uni-easyinput/readme.md
create mode 100644 uni_modules/uni-fab/changelog.md
create mode 100644 uni_modules/uni-fab/components/uni-fab/uni-fab.vue
create mode 100644 uni_modules/uni-fab/package.json
create mode 100644 uni_modules/uni-fab/readme.md
create mode 100644 uni_modules/uni-fav/changelog.md
create mode 100644 uni_modules/uni-fav/components/uni-fav/i18n/en.json
create mode 100644 uni_modules/uni-fav/components/uni-fav/i18n/index.js
create mode 100644 uni_modules/uni-fav/components/uni-fav/i18n/zh-Hans.json
create mode 100644 uni_modules/uni-fav/components/uni-fav/i18n/zh-Hant.json
create mode 100644 uni_modules/uni-fav/components/uni-fav/uni-fav.vue
create mode 100644 uni_modules/uni-fav/package.json
create mode 100644 uni_modules/uni-fav/readme.md
create mode 100644 uni_modules/uni-forms/changelog.md
create mode 100644 uni_modules/uni-forms/components/uni-forms-item/uni-forms-item.vue
create mode 100644 uni_modules/uni-forms/components/uni-forms/uni-forms.vue
create mode 100644 uni_modules/uni-forms/components/uni-forms/validate.js
create mode 100644 uni_modules/uni-forms/package.json
create mode 100644 uni_modules/uni-forms/readme.md
create mode 100644 uni_modules/uni-goods-nav/changelog.md
create mode 100644 uni_modules/uni-goods-nav/components/uni-goods-nav/i18n/en.json
create mode 100644 uni_modules/uni-goods-nav/components/uni-goods-nav/i18n/index.js
create mode 100644 uni_modules/uni-goods-nav/components/uni-goods-nav/i18n/zh-Hans.json
create mode 100644 uni_modules/uni-goods-nav/components/uni-goods-nav/i18n/zh-Hant.json
create mode 100644 uni_modules/uni-goods-nav/components/uni-goods-nav/uni-goods-nav.vue
create mode 100644 uni_modules/uni-goods-nav/package.json
create mode 100644 uni_modules/uni-goods-nav/readme.md
create mode 100644 uni_modules/uni-grid/changelog.md
create mode 100644 uni_modules/uni-grid/components/uni-grid-item/uni-grid-item.vue
create mode 100644 uni_modules/uni-grid/components/uni-grid/uni-grid.vue
create mode 100644 uni_modules/uni-grid/package.json
create mode 100644 uni_modules/uni-grid/readme.md
create mode 100644 uni_modules/uni-group/changelog.md
create mode 100644 uni_modules/uni-group/components/uni-group/uni-group.vue
create mode 100644 uni_modules/uni-group/package.json
create mode 100644 uni_modules/uni-group/readme.md
create mode 100644 uni_modules/uni-icons/changelog.md
create mode 100644 uni_modules/uni-icons/components/uni-icons/icons.js
create mode 100644 uni_modules/uni-icons/components/uni-icons/uni-icons.vue
create mode 100644 uni_modules/uni-icons/components/uni-icons/uni.ttf
create mode 100644 uni_modules/uni-icons/components/uni-icons/uniicons.css
create mode 100644 uni_modules/uni-icons/components/uni-icons/uniicons.ttf
create mode 100644 uni_modules/uni-icons/package.json
create mode 100644 uni_modules/uni-icons/readme.md
create mode 100644 uni_modules/uni-link/changelog.md
create mode 100644 uni_modules/uni-link/components/uni-link/uni-link.vue
create mode 100644 uni_modules/uni-link/package.json
create mode 100644 uni_modules/uni-link/readme.md
create mode 100644 uni_modules/uni-list/changelog.md
create mode 100644 uni_modules/uni-list/components/uni-list-ad/uni-list-ad.vue
create mode 100644 uni_modules/uni-list/components/uni-list-chat/uni-list-chat.scss
create mode 100644 uni_modules/uni-list/components/uni-list-chat/uni-list-chat.vue
create mode 100644 uni_modules/uni-list/components/uni-list-item/uni-list-item.vue
create mode 100644 uni_modules/uni-list/components/uni-list/uni-list.vue
create mode 100644 uni_modules/uni-list/components/uni-list/uni-refresh.vue
create mode 100644 uni_modules/uni-list/components/uni-list/uni-refresh.wxs
create mode 100644 uni_modules/uni-list/package.json
create mode 100644 uni_modules/uni-list/readme.md
create mode 100644 uni_modules/uni-load-more/changelog.md
create mode 100644 uni_modules/uni-load-more/components/uni-load-more/i18n/en.json
create mode 100644 uni_modules/uni-load-more/components/uni-load-more/i18n/index.js
create mode 100644 uni_modules/uni-load-more/components/uni-load-more/i18n/zh-Hans.json
create mode 100644 uni_modules/uni-load-more/components/uni-load-more/i18n/zh-Hant.json
create mode 100644 uni_modules/uni-load-more/components/uni-load-more/uni-load-more.vue
create mode 100644 uni_modules/uni-load-more/package.json
create mode 100644 uni_modules/uni-load-more/readme.md
create mode 100644 uni_modules/uni-nav-bar/changelog.md
create mode 100644 uni_modules/uni-nav-bar/components/uni-nav-bar/uni-nav-bar.vue
create mode 100644 uni_modules/uni-nav-bar/components/uni-nav-bar/uni-status-bar.vue
create mode 100644 uni_modules/uni-nav-bar/package.json
create mode 100644 uni_modules/uni-nav-bar/readme.md
create mode 100644 uni_modules/uni-notice-bar/changelog.md
create mode 100644 uni_modules/uni-notice-bar/components/uni-notice-bar/uni-notice-bar.vue
create mode 100644 uni_modules/uni-notice-bar/package.json
create mode 100644 uni_modules/uni-notice-bar/readme.md
create mode 100644 uni_modules/uni-number-box/changelog.md
create mode 100644 uni_modules/uni-number-box/components/uni-number-box/uni-number-box.vue
create mode 100644 uni_modules/uni-number-box/package.json
create mode 100644 uni_modules/uni-number-box/readme.md
create mode 100644 uni_modules/uni-rate/changelog.md
create mode 100644 uni_modules/uni-rate/components/uni-rate/uni-rate.vue
create mode 100644 uni_modules/uni-rate/package.json
create mode 100644 uni_modules/uni-rate/readme.md
create mode 100644 uni_modules/uni-row/changelog.md
create mode 100644 uni_modules/uni-row/components/uni-col/uni-col.vue
create mode 100644 uni_modules/uni-row/components/uni-row/uni-row.vue
create mode 100644 uni_modules/uni-row/package.json
create mode 100644 uni_modules/uni-row/readme.md
create mode 100644 uni_modules/uni-scss/changelog.md
create mode 100644 uni_modules/uni-scss/index.scss
create mode 100644 uni_modules/uni-scss/manifest.json
create mode 100644 uni_modules/uni-scss/package.json
create mode 100644 uni_modules/uni-scss/readme.md
create mode 100644 uni_modules/uni-scss/styles/index.scss
create mode 100644 uni_modules/uni-scss/styles/setting/_border.scss
create mode 100644 uni_modules/uni-scss/styles/setting/_color.scss
create mode 100644 uni_modules/uni-scss/styles/setting/_radius.scss
create mode 100644 uni_modules/uni-scss/styles/setting/_space.scss
create mode 100644 uni_modules/uni-scss/styles/setting/_styles.scss
create mode 100644 uni_modules/uni-scss/styles/setting/_text.scss
create mode 100644 uni_modules/uni-scss/styles/setting/_variables.scss
create mode 100644 uni_modules/uni-scss/styles/tools/functions.scss
create mode 100644 uni_modules/uni-scss/theme.scss
create mode 100644 uni_modules/uni-scss/variables.scss
create mode 100644 uni_modules/uni-search-bar/changelog.md
create mode 100644 uni_modules/uni-search-bar/components/uni-search-bar/i18n/en.json
create mode 100644 uni_modules/uni-search-bar/components/uni-search-bar/i18n/index.js
create mode 100644 uni_modules/uni-search-bar/components/uni-search-bar/i18n/zh-Hans.json
create mode 100644 uni_modules/uni-search-bar/components/uni-search-bar/i18n/zh-Hant.json
create mode 100644 uni_modules/uni-search-bar/components/uni-search-bar/uni-search-bar.vue
create mode 100644 uni_modules/uni-search-bar/package.json
create mode 100644 uni_modules/uni-search-bar/readme.md
create mode 100644 uni_modules/uni-segmented-control/changelog.md
create mode 100644 uni_modules/uni-segmented-control/components/uni-segmented-control/uni-segmented-control.vue
create mode 100644 uni_modules/uni-segmented-control/package.json
create mode 100644 uni_modules/uni-segmented-control/readme.md
create mode 100644 uni_modules/uni-steps/changelog.md
create mode 100644 uni_modules/uni-steps/components/uni-steps/uni-steps.vue
create mode 100644 uni_modules/uni-steps/package.json
create mode 100644 uni_modules/uni-steps/readme.md
create mode 100644 uni_modules/uni-swiper-dot/changelog.md
create mode 100644 uni_modules/uni-swiper-dot/components/uni-swiper-dot/uni-swiper-dot.vue
create mode 100644 uni_modules/uni-swiper-dot/package.json
create mode 100644 uni_modules/uni-swiper-dot/readme.md
create mode 100644 uni_modules/uni-tag/changelog.md
create mode 100644 uni_modules/uni-tag/components/uni-tag/uni-tag.vue
create mode 100644 uni_modules/uni-tag/package.json
create mode 100644 uni_modules/uni-tag/readme.md
create mode 100644 uni_modules/uni-title/changelog.md
create mode 100644 uni_modules/uni-title/components/uni-title/uni-title.vue
create mode 100644 uni_modules/uni-title/package.json
create mode 100644 uni_modules/uni-title/readme.md
create mode 100644 uni_modules/uni-tooltip/changelog.md
create mode 100644 uni_modules/uni-tooltip/components/uni-tooltip/uni-tooltip.vue
create mode 100644 uni_modules/uni-tooltip/package.json
create mode 100644 uni_modules/uni-tooltip/readme.md
create mode 100644 uni_modules/uni-transition/changelog.md
create mode 100644 uni_modules/uni-transition/components/uni-transition/createAnimation.js
create mode 100644 uni_modules/uni-transition/components/uni-transition/uni-transition.vue
create mode 100644 uni_modules/uni-transition/package.json
create mode 100644 uni_modules/uni-transition/readme.md
create mode 100644 uni_modules/vk-uview-ui/components/u-avatar/u-avatar.vue
create mode 100644 uni_modules/vk-uview-ui/components/u-count-down/u-count-down.vue
create mode 100644 uni_modules/vk-uview-ui/components/u-count-down/utils.js
create mode 100644 uni_modules/vk-uview-ui/components/u-icon/u-icon.vue
create mode 100644 uni_modules/vk-uview-ui/components/u-image/u-image.vue
create mode 100644 uni_modules/vk-uview-ui/components/u-input/u-input.vue
create mode 100644 uni_modules/vk-uview-ui/components/u-lazy-load/u-lazy-load.vue
create mode 100644 uni_modules/vk-uview-ui/components/u-loading/u-loading.vue
create mode 100644 uni_modules/vk-uview-ui/components/u-loadmore/u-loadmore.vue
create mode 100644 uni_modules/vk-uview-ui/components/u-mask/u-mask.vue
create mode 100644 uni_modules/vk-uview-ui/components/u-modal/u-modal.vue
create mode 100644 uni_modules/vk-uview-ui/components/u-navbar/u-navbar.vue
create mode 100644 uni_modules/vk-uview-ui/components/u-notice-bar/u-notice-bar.vue
create mode 100644 uni_modules/vk-uview-ui/components/u-search/u-search.vue
create mode 100644 uni_modules/vk-uview-ui/components/u-swiper-plus/components/u-swiper-indicator.vue
create mode 100644 uni_modules/vk-uview-ui/components/u-swiper-plus/u-swiper-plus.vue
create mode 100644 uni_modules/vk-uview-ui/components/u-swiper/u-swiper.vue
create mode 100644 uni_modules/vk-uview-ui/components/u-switch/u-switch.vue
create mode 100644 uni_modules/vk-uview-ui/components/u-table/u-table.vue
create mode 100644 uni_modules/vk-uview-ui/components/u-tabs-swiper/u-tabs-swiper.vue
create mode 100644 uni_modules/vk-uview-ui/components/u-tabs/u-tabs.vue
create mode 100644 uni_modules/vk-uview-ui/components/u-tag/u-tag.vue
create mode 100644 uni_modules/vk-uview-ui/components/u-td/u-td.vue
create mode 100644 uni_modules/vk-uview-ui/components/u-th/u-th.vue
create mode 100644 uni_modules/vk-uview-ui/components/u-time-line-item/u-time-line-item.vue
create mode 100644 uni_modules/vk-uview-ui/components/u-time-line/u-time-line.vue
create mode 100644 uni_modules/vk-uview-ui/components/u-toast/u-toast.vue
create mode 100644 uni_modules/vk-uview-ui/components/u-tr/u-tr.vue
create mode 100644 uni_modules/vk-uview-ui/components/u-verification-code/u-verification-code.vue
create mode 100644 uni_modules/vk-uview-ui/components/vk-uview-ui/vk-uview-ui.vue
create mode 100644 uni_modules/vk-uview-ui/iconfont.css
create mode 100644 uni_modules/vk-uview-ui/index.js
create mode 100644 uni_modules/vk-uview-ui/index.scss
create mode 100644 uni_modules/vk-uview-ui/libs/address/areas.json
create mode 100644 uni_modules/vk-uview-ui/libs/address/citys.json
create mode 100644 uni_modules/vk-uview-ui/libs/address/provinces.json
create mode 100644 uni_modules/vk-uview-ui/libs/config/config.js
create mode 100644 uni_modules/vk-uview-ui/libs/config/zIndex.js
create mode 100644 uni_modules/vk-uview-ui/libs/css/color.scss
create mode 100644 uni_modules/vk-uview-ui/libs/css/common.scss
create mode 100644 uni_modules/vk-uview-ui/libs/css/style.components.scss
create mode 100644 uni_modules/vk-uview-ui/libs/css/style.h5.scss
create mode 100644 uni_modules/vk-uview-ui/libs/css/style.mp.scss
create mode 100644 uni_modules/vk-uview-ui/libs/css/style.nvue.scss
create mode 100644 uni_modules/vk-uview-ui/libs/css/style.vue.scss
create mode 100644 uni_modules/vk-uview-ui/libs/function/$parent.js
create mode 100644 uni_modules/vk-uview-ui/libs/function/addStyle.js
create mode 100644 uni_modules/vk-uview-ui/libs/function/addUnit.js
create mode 100644 uni_modules/vk-uview-ui/libs/function/bem.js
create mode 100644 uni_modules/vk-uview-ui/libs/function/color.js
create mode 100644 uni_modules/vk-uview-ui/libs/function/colorGradient.js
create mode 100644 uni_modules/vk-uview-ui/libs/function/debounce.js
create mode 100644 uni_modules/vk-uview-ui/libs/function/deepClone.js
create mode 100644 uni_modules/vk-uview-ui/libs/function/deepMerge.js
create mode 100644 uni_modules/vk-uview-ui/libs/function/getParent.js
create mode 100644 uni_modules/vk-uview-ui/libs/function/guid.js
create mode 100644 uni_modules/vk-uview-ui/libs/function/md5.js
create mode 100644 uni_modules/vk-uview-ui/libs/function/queryParams.js
create mode 100644 uni_modules/vk-uview-ui/libs/function/random.js
create mode 100644 uni_modules/vk-uview-ui/libs/function/randomArray.js
create mode 100644 uni_modules/vk-uview-ui/libs/function/route.js
create mode 100644 uni_modules/vk-uview-ui/libs/function/sys.js
create mode 100644 uni_modules/vk-uview-ui/libs/function/test.js
create mode 100644 uni_modules/vk-uview-ui/libs/function/throttle.js
create mode 100644 uni_modules/vk-uview-ui/libs/function/timeFormat.js
create mode 100644 uni_modules/vk-uview-ui/libs/function/timeFrom.js
create mode 100644 uni_modules/vk-uview-ui/libs/function/toast.js
create mode 100644 uni_modules/vk-uview-ui/libs/function/trim.js
create mode 100644 uni_modules/vk-uview-ui/libs/function/type2icon.js
create mode 100644 uni_modules/vk-uview-ui/libs/mixin/mixin.js
create mode 100644 uni_modules/vk-uview-ui/libs/mixin/mpShare.js
create mode 100644 uni_modules/vk-uview-ui/libs/request/index.js
create mode 100644 uni_modules/vk-uview-ui/libs/store/index.js
create mode 100644 uni_modules/vk-uview-ui/libs/util/async-validator.js
create mode 100644 uni_modules/vk-uview-ui/libs/util/emitter.js
create mode 100644 uni_modules/vk-uview-ui/package.json
create mode 100644 uni_modules/vk-uview-ui/theme.scss
create mode 100644 uni_modules/z-paging/components/z-paging-cell/z-paging-cell.vue
create mode 100644 uni_modules/z-paging/components/z-paging-empty-view/z-paging-empty-view.vue
create mode 100644 uni_modules/z-paging/components/z-paging-swiper-item/z-paging-swiper-item.vue
create mode 100644 uni_modules/z-paging/components/z-paging-swiper/z-paging-swiper.vue
create mode 100644 uni_modules/z-paging/components/z-paging/components/z-paging-load-more.vue
create mode 100644 uni_modules/z-paging/components/z-paging/components/z-paging-refresh.vue
create mode 100644 uni_modules/z-paging/components/z-paging/config/index.js
create mode 100644 uni_modules/z-paging/components/z-paging/css/z-paging-main.css
create mode 100644 uni_modules/z-paging/components/z-paging/css/z-paging-static.css
create mode 100644 uni_modules/z-paging/components/z-paging/i18n/en.json
create mode 100644 uni_modules/z-paging/components/z-paging/i18n/index.js
create mode 100644 uni_modules/z-paging/components/z-paging/i18n/zh-Hans.json
create mode 100644 uni_modules/z-paging/components/z-paging/i18n/zh-Hant.json
create mode 100644 uni_modules/z-paging/components/z-paging/js/hooks/useZPaging.js
create mode 100644 uni_modules/z-paging/components/z-paging/js/hooks/useZPagingComp.js
create mode 100644 uni_modules/z-paging/components/z-paging/js/modules/back-to-top.js
create mode 100644 uni_modules/z-paging/components/z-paging/js/modules/chat-record-mode.js
create mode 100644 uni_modules/z-paging/components/z-paging/js/modules/common-layout.js
create mode 100644 uni_modules/z-paging/components/z-paging/js/modules/data-handle.js
create mode 100644 uni_modules/z-paging/components/z-paging/js/modules/empty.js
create mode 100644 uni_modules/z-paging/components/z-paging/js/modules/i18n.js
create mode 100644 uni_modules/z-paging/components/z-paging/js/modules/load-more.js
create mode 100644 uni_modules/z-paging/components/z-paging/js/modules/loading.js
create mode 100644 uni_modules/z-paging/components/z-paging/js/modules/nvue.js
create mode 100644 uni_modules/z-paging/components/z-paging/js/modules/refresher.js
create mode 100644 uni_modules/z-paging/components/z-paging/js/modules/scroller.js
create mode 100644 uni_modules/z-paging/components/z-paging/js/modules/virtual-list.js
create mode 100644 uni_modules/z-paging/components/z-paging/js/z-paging-constant.js
create mode 100644 uni_modules/z-paging/components/z-paging/js/z-paging-enum.js
create mode 100644 uni_modules/z-paging/components/z-paging/js/z-paging-interceptor.js
create mode 100644 uni_modules/z-paging/components/z-paging/js/z-paging-main.js
create mode 100644 uni_modules/z-paging/components/z-paging/js/z-paging-mixin.js
create mode 100644 uni_modules/z-paging/components/z-paging/js/z-paging-static.js
create mode 100644 uni_modules/z-paging/components/z-paging/js/z-paging-utils.js
create mode 100644 uni_modules/z-paging/components/z-paging/wxs/z-paging-renderjs.js
create mode 100644 uni_modules/z-paging/components/z-paging/wxs/z-paging-wxs.wxs
create mode 100644 uni_modules/z-paging/components/z-paging/z-paging.vue
create mode 100644 uni_modules/z-paging/global.d.ts
create mode 100644 uni_modules/z-paging/package.json
create mode 100644 vite.config.js
diff --git a/.env b/.env
new file mode 100644
index 0000000..486391d
--- /dev/null
+++ b/.env
@@ -0,0 +1,27 @@
+# 版本号
+SHOPRO_VERSION = v1.8.3
+
+# 后端接口 - 正式环境(通过 process.env.NODE_ENV 非 development)
+SHOPRO_BASE_URL = http://localhost:48080
+
+# 后端接口 - 测试环境(通过 process.env.NODE_ENV = development)
+SHOPRO_DEV_BASE_URL = http://127.0.0.1:48080
+### SHOPRO_DEV_BASE_URL = https://peiwan.mfzt.site
+
+# 后端接口前缀(一般不建议调整)
+SHOPRO_API_PATH = /app-api
+
+# 后端 websocket 接口前缀
+SHOPRO_WEBSOCKET_PATH = /infra/ws
+
+# 开发环境运行端口
+SHOPRO_DEV_PORT = 3000
+
+# 客户端静态资源地址 空=默认使用服务端指定的CDN资源地址前缀 | local=本地 | http(s)://xxx.xxx=自定义静态资源地址前缀
+SHOPRO_STATIC_URL = https://file.sheepjs.com
+
+# 是否开启直播 1 开启直播 | 0 关闭直播 (小程序官方后台未审核开通直播权限时请勿开启)
+SHOPRO_MPLIVE_ON = 0
+
+# 租户ID 默认 1
+SHOPRO_TENANT_ID = 1
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..43dda18
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,11 @@
+unpackage/*
+node_modules/*
+.idea/*
+deploy.sh
+.hbuilderx/
+.vscode/
+**/.DS_Store
+yarn.lock
+package-lock.json
+*.keystore
+pnpm-lock.yaml
diff --git a/.prettierignore b/.prettierignore
new file mode 100644
index 0000000..7384df0
--- /dev/null
+++ b/.prettierignore
@@ -0,0 +1,6 @@
+/unpackage/*
+/node_modules/**
+/uni_modules/**
+/public/*
+**/*.svg
+**/*.sh
diff --git a/.prettierrc b/.prettierrc
new file mode 100644
index 0000000..fe0a3f9
--- /dev/null
+++ b/.prettierrc
@@ -0,0 +1,10 @@
+{
+ "printWidth": 100,
+ "semi": true,
+ "vueIndentScriptAndStyle": true,
+ "singleQuote": true,
+ "trailingComma": "all",
+ "proseWrap": "never",
+ "htmlWhitespaceSensitivity": "strict",
+ "endOfLine": "auto"
+}
diff --git a/App.vue b/App.vue
new file mode 100644
index 0000000..1c143ef
--- /dev/null
+++ b/App.vue
@@ -0,0 +1,129 @@
+
+
+
diff --git a/androidPrivacy.json b/androidPrivacy.json
new file mode 100644
index 0000000..0d726ca
--- /dev/null
+++ b/androidPrivacy.json
@@ -0,0 +1,3 @@
+{
+ "prompt" : "template"
+}
diff --git a/components/custom-back-to-top/custom-back-to-top.vue b/components/custom-back-to-top/custom-back-to-top.vue
new file mode 100644
index 0000000..37bc253
--- /dev/null
+++ b/components/custom-back-to-top/custom-back-to-top.vue
@@ -0,0 +1,89 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/htz-image-upload/htz-image-upload.vue b/components/htz-image-upload/htz-image-upload.vue
new file mode 100644
index 0000000..897499a
--- /dev/null
+++ b/components/htz-image-upload/htz-image-upload.vue
@@ -0,0 +1,831 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ×
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/qrcode-modal/qrcode-modal.vue b/components/qrcode-modal/qrcode-modal.vue
new file mode 100644
index 0000000..a94dc44
--- /dev/null
+++ b/components/qrcode-modal/qrcode-modal.vue
@@ -0,0 +1,121 @@
+
+
+
+
+ 长按二维码 关注公众号
+ 用于接收消息提醒
+ 点击验证
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/components/search-modal/search-modal.vue b/components/search-modal/search-modal.vue
new file mode 100644
index 0000000..bc5c1ba
--- /dev/null
+++ b/components/search-modal/search-modal.vue
@@ -0,0 +1,356 @@
+
+
+
+ 筛选
+
+ 年龄
+
+ {{age.text}}
+
+
+
+ 性别
+
+ {{sex.text}}
+
+
+
+ 是否同城(会员特权)
+
+ {{city.text}}
+
+
+
+ 城市(会员特权)
+
+ 全部
+ {{query.city}}
+ 切换城市
+
+
+
+ 确定
+
+
+
+
+
+
+
+
+
diff --git a/components/thorui/tui-actionsheet/tui-actionsheet.vue b/components/thorui/tui-actionsheet/tui-actionsheet.vue
new file mode 100644
index 0000000..84901ea
--- /dev/null
+++ b/components/thorui/tui-actionsheet/tui-actionsheet.vue
@@ -0,0 +1,201 @@
+
+
+
+
+ {{tips}}
+
+
+
+ {{item.text}}
+
+
+ 取消
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/components/thorui/tui-badge/tui-badge.vue b/components/thorui/tui-badge/tui-badge.vue
new file mode 100644
index 0000000..d361637
--- /dev/null
+++ b/components/thorui/tui-badge/tui-badge.vue
@@ -0,0 +1,129 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/components/thorui/tui-bottom-popup/tui-bottom-popup.vue b/components/thorui/tui-bottom-popup/tui-bottom-popup.vue
new file mode 100644
index 0000000..c06e4ed
--- /dev/null
+++ b/components/thorui/tui-bottom-popup/tui-bottom-popup.vue
@@ -0,0 +1,119 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/components/thorui/tui-bubble-popup/tui-bubble-popup.vue b/components/thorui/tui-bubble-popup/tui-bubble-popup.vue
new file mode 100644
index 0000000..dbb3cea
--- /dev/null
+++ b/components/thorui/tui-bubble-popup/tui-bubble-popup.vue
@@ -0,0 +1,204 @@
+
+
+
+
+
+
+
+
+
diff --git a/components/thorui/tui-circular-progress/tui-circular-progress.vue b/components/thorui/tui-circular-progress/tui-circular-progress.vue
new file mode 100644
index 0000000..2fc86a4
--- /dev/null
+++ b/components/thorui/tui-circular-progress/tui-circular-progress.vue
@@ -0,0 +1,309 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/components/thorui/tui-icon/tui-icon.js b/components/thorui/tui-icon/tui-icon.js
new file mode 100644
index 0000000..0304802
--- /dev/null
+++ b/components/thorui/tui-icon/tui-icon.js
@@ -0,0 +1,3 @@
+export default {
+
+}
diff --git a/components/thorui/tui-icon/tui-icon.vue b/components/thorui/tui-icon/tui-icon.vue
new file mode 100644
index 0000000..665c71a
--- /dev/null
+++ b/components/thorui/tui-icon/tui-icon.vue
@@ -0,0 +1,82 @@
+
+ {{ icons[name] || '' }}
+
+
+
+
+
+
\ No newline at end of file
diff --git a/components/thorui/tui-modal/tui-modal.vue b/components/thorui/tui-modal/tui-modal.vue
new file mode 100644
index 0000000..b6e2898
--- /dev/null
+++ b/components/thorui/tui-modal/tui-modal.vue
@@ -0,0 +1,338 @@
+
+
+
+
+ {{ title }}
+ {{ content }}
+
+
+ {{ item.text || '确定' }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/components/thorui/tui-navigation-bar/tui-navigation-bar.vue b/components/thorui/tui-navigation-bar/tui-navigation-bar.vue
new file mode 100644
index 0000000..7db07ea
--- /dev/null
+++ b/components/thorui/tui-navigation-bar/tui-navigation-bar.vue
@@ -0,0 +1,258 @@
+
+
+
+
+ {{ title }}
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/components/thorui/tui-numberbox/tui-numberbox.vue b/components/thorui/tui-numberbox/tui-numberbox.vue
new file mode 100644
index 0000000..2fb6e7e
--- /dev/null
+++ b/components/thorui/tui-numberbox/tui-numberbox.vue
@@ -0,0 +1,248 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/thorui/tui-sticky/tui-sticky.vue b/components/thorui/tui-sticky/tui-sticky.vue
new file mode 100644
index 0000000..050047f
--- /dev/null
+++ b/components/thorui/tui-sticky/tui-sticky.vue
@@ -0,0 +1,166 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/components/thorui/tui-tabbar/tui-tabbar.vue b/components/thorui/tui-tabbar/tui-tabbar.vue
new file mode 100644
index 0000000..e03aab7
--- /dev/null
+++ b/components/thorui/tui-tabbar/tui-tabbar.vue
@@ -0,0 +1,287 @@
+
+
+
+
+
+
+
+
+ {{ item.isDot ? '' : item.num }}
+
+
+ {{ item.text }}
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/components/thorui/tui-tabs/tui-tabs.vue b/components/thorui/tui-tabs/tui-tabs.vue
new file mode 100644
index 0000000..b734d7d
--- /dev/null
+++ b/components/thorui/tui-tabs/tui-tabs.vue
@@ -0,0 +1,346 @@
+
+
+
+
+ {{ item[field] }} ({{item[badgeField]}})
+
+ {{ item.isDot ? '' : item[badgeField] }}
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..2269a69
--- /dev/null
+++ b/index.html
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/jsconfig.json b/jsconfig.json
new file mode 100644
index 0000000..b1968ee
--- /dev/null
+++ b/jsconfig.json
@@ -0,0 +1,9 @@
+{
+ "compilerOptions": {
+ "jsx": "preserve",
+ "baseUrl": ".",
+ "paths": {
+ "@/*": ["./*"]
+ }
+ }
+}
diff --git a/main.js b/main.js
new file mode 100644
index 0000000..3d6411c
--- /dev/null
+++ b/main.js
@@ -0,0 +1,21 @@
+import App from './App';
+
+// 引入 uView UI
+import uView from './uni_modules/vk-uview-ui';
+
+import { createSSRApp } from 'vue';
+import { setupPinia } from './sheep/store';
+
+
+export function createApp() {
+
+ const app = createSSRApp(App);
+
+ app.use(uView);
+
+ setupPinia(app);
+
+ return {
+ app,
+ };
+}
diff --git a/manifest.json b/manifest.json
new file mode 100644
index 0000000..28f1440
--- /dev/null
+++ b/manifest.json
@@ -0,0 +1,239 @@
+{
+ "name": "晚趣语音",
+ "appid": "__UNI__458F814",
+ "description": "基于 uni-app + Vue3 技术驱动的在线商城系统,内含诸多功能与丰富的活动,期待您的使用和反馈。",
+ "versionName": "2.1.0",
+ "versionCode": 183,
+ "transformPx": false,
+ "app-plus": {
+ "usingComponents": true,
+ "nvueCompiler": "uni-app",
+ "nvueStyleCompiler": "uni-app",
+ "compilerVersion": 3,
+ "nvueLaunchMode": "fast",
+ "splashscreen": {
+ "alwaysShowBeforeRender": true,
+ "waiting": true,
+ "autoclose": true,
+ "delay": 0
+ },
+ "safearea": {
+ "bottom": {
+ "offset": "none"
+ }
+ },
+ "modules": {
+ "Payment": {},
+ "Share": {},
+ "VideoPlayer": {},
+ "OAuth": {}
+ },
+ "distribute": {
+ "android": {
+ "permissions": [
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ ""
+ ],
+ "minSdkVersion": 21,
+ "schemes": "shopro"
+ },
+ "ios": {
+ "urlschemewhitelist": [
+ "baidumap",
+ "iosamap"
+ ],
+ "dSYMs": false,
+ "privacyDescription": {
+ "NSPhotoLibraryUsageDescription": "需要同意访问您的相册选取图片才能完善该条目",
+ "NSPhotoLibraryAddUsageDescription": "需要同意访问您的相册才能保存该图片",
+ "NSCameraUsageDescription": "需要同意访问您的摄像头拍摄照片才能完善该条目",
+ "NSUserTrackingUsageDescription": "开启追踪并不会获取您在其它站点的隐私信息,该行为仅用于标识设备,保障服务安全和提升浏览体验"
+ },
+ "urltypes": "shopro",
+ "capabilities": {
+ "entitlements": {
+ "com.apple.developer.associated-domains": [
+ "applinks:shopro.sheepjs.com"
+ ]
+ }
+ },
+ "idfa": true
+ },
+ "sdkConfigs": {
+ "speech": {
+ "ifly": {}
+ },
+ "ad": {},
+ "oauth": {
+ "apple": {},
+ "weixin": {
+ "appid": "wxae7a0c156da9383b",
+ "UniversalLinks": "https://shopro.sheepjs.com/uni-universallinks/__UNI__082C0BA/"
+ }
+ },
+ "payment": {
+ "weixin": {
+ "__platform__": [
+ "ios",
+ "android"
+ ],
+ "appid": "wxae7a0c156da9383b",
+ "UniversalLinks": "https://shopro.sheepjs.com/uni-universallinks/__UNI__082C0BA/"
+ },
+ "alipay": {
+ "__platform__": [
+ "ios",
+ "android"
+ ]
+ }
+ },
+ "share": {
+ "weixin": {
+ "appid": "wxae7a0c156da9383b",
+ "UniversalLinks": "https://shopro.sheepjs.com/uni-universallinks/__UNI__082C0BA/"
+ }
+ }
+ },
+ "orientation": [
+ "portrait-primary"
+ ],
+ "splashscreen": {
+ "androidStyle": "common",
+ "iosStyle": "common",
+ "useOriginalMsgbox": true
+ },
+ "icons": {
+ "android": {
+ "hdpi": "unpackage/res/icons/72x72.png",
+ "xhdpi": "unpackage/res/icons/96x96.png",
+ "xxhdpi": "unpackage/res/icons/144x144.png",
+ "xxxhdpi": "unpackage/res/icons/192x192.png"
+ },
+ "ios": {
+ "appstore": "unpackage/res/icons/1024x1024.png",
+ "ipad": {
+ "app": "unpackage/res/icons/76x76.png",
+ "app@2x": "unpackage/res/icons/152x152.png",
+ "notification": "unpackage/res/icons/20x20.png",
+ "notification@2x": "unpackage/res/icons/40x40.png",
+ "proapp@2x": "unpackage/res/icons/167x167.png",
+ "settings": "unpackage/res/icons/29x29.png",
+ "settings@2x": "unpackage/res/icons/58x58.png",
+ "spotlight": "unpackage/res/icons/40x40.png",
+ "spotlight@2x": "unpackage/res/icons/80x80.png"
+ },
+ "iphone": {
+ "app@2x": "unpackage/res/icons/120x120.png",
+ "app@3x": "unpackage/res/icons/180x180.png",
+ "notification@2x": "unpackage/res/icons/40x40.png",
+ "notification@3x": "unpackage/res/icons/60x60.png",
+ "settings@2x": "unpackage/res/icons/58x58.png",
+ "settings@3x": "unpackage/res/icons/87x87.png",
+ "spotlight@2x": "unpackage/res/icons/80x80.png",
+ "spotlight@3x": "unpackage/res/icons/120x120.png"
+ }
+ }
+ }
+ }
+ },
+ "quickapp": {},
+ "quickapp-native": {
+ "icon": "/static/logo.png",
+ "package": "com.example.demo",
+ "features": [
+ {
+ "name": "system.clipboard"
+ }
+ ]
+ },
+ "quickapp-webview": {
+ "icon": "/static/logo.png",
+ "package": "com.example.demo",
+ "minPlatformVersion": 1070,
+ "versionName": "1.0.0",
+ "versionCode": 100
+ },
+ "mp-weixin": {
+ "appid": "wx2708b75e03e8440a",
+ "setting": {
+ "urlCheck": false,
+ "minified": true,
+ "postcss": true
+ },
+ "optimization": {
+ "subPackages": true
+ },
+ "plugins": {},
+ "lazyCodeLoading": "requiredComponents",
+ "usingComponents": {},
+ "permission": {},
+ "requiredPrivateInfos": [
+ "chooseAddress"
+ ]
+ },
+ "mp-alipay": {
+ "usingComponents": true
+ },
+ "mp-baidu": {
+ "usingComponents": true
+ },
+ "mp-toutiao": {
+ "usingComponents": true
+ },
+ "mp-jd": {
+ "usingComponents": true
+ },
+ "h5": {
+ "template": "index.html",
+ "router": {
+ "mode": "hash",
+ "base": "./"
+ },
+ "sdkConfigs": {
+ "maps": {}
+ },
+ "async": {
+ "timeout": 20000
+ },
+ "title": "晚趣语音",
+ "optimization": {
+ "treeShaking": {
+ "enable": true
+ }
+ }
+ },
+ "vueVersion": "3",
+ "_spaceID": "192b4892-5452-4e1d-9f09-eee1ece40639",
+ "locale": "zh-Hans",
+ "fallbackLocale": "zh-Hans"
+}
\ No newline at end of file
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..b158175
--- /dev/null
+++ b/package.json
@@ -0,0 +1,103 @@
+{
+ "id": "shopro",
+ "name": "shopro",
+ "displayName": "晚趣语音",
+ "version": "2.2.0",
+ "description": "晚趣语音,一套代码,同时发行到iOS、Android、H5、微信小程序多个平台,请使用手机扫码快速体验强大功能",
+ "scripts": {
+ "prettier": "prettier --write \"{pages,sheep}/**/*.{js,json,tsx,css,less,scss,vue,html,md}\""
+ },
+ "repository": "https://github.com/sheepjs/shop.git",
+ "keywords": [
+ "商城",
+ "B2C",
+ "商城模板"
+ ],
+ "author": "",
+ "license": "MIT",
+ "bugs": {
+ "url": "https://github.com/sheepjs/shop/issues"
+ },
+ "homepage": "https://github.com/dcloudio/hello-uniapp#readme",
+ "dcloudext": {
+ "category": [
+ "前端页面模板",
+ "uni-app前端项目模板"
+ ],
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": ""
+ },
+ "declaration": {
+ "ads": "无",
+ "data": "无",
+ "permissions": "无"
+ },
+ "npmurl": ""
+ },
+ "uni_modules": {
+ "dependencies": [],
+ "encrypt": [],
+ "platforms": {
+ "cloud": {
+ "tcb": "u",
+ "aliyun": "u"
+ },
+ "client": {
+ "App": {
+ "app-vue": "y",
+ "app-nvue": "u"
+ },
+ "H5-mobile": {
+ "Safari": "y",
+ "Android Browser": "y",
+ "微信浏览器(Android)": "y",
+ "QQ浏览器(Android)": "y"
+ },
+ "H5-pc": {
+ "Chrome": "y",
+ "IE": "y",
+ "Edge": "y",
+ "Firefox": "y",
+ "Safari": "y"
+ },
+ "小程序": {
+ "微信": "y",
+ "阿里": "u",
+ "百度": "u",
+ "字节跳动": "u",
+ "QQ": "u",
+ "京东": "u"
+ },
+ "快应用": {
+ "华为": "u",
+ "联盟": "u"
+ },
+ "Vue": {
+ "vue2": "u",
+ "vue3": "y"
+ }
+ }
+ }
+ },
+ "dependencies": {
+ "dayjs": "^1.11.7",
+ "lodash": "^4.17.21",
+ "lodash-es": "^4.17.21",
+ "luch-request": "^3.0.8",
+ "pinia": "^2.0.33",
+ "pinia-plugin-persist-uni": "^1.2.0",
+ "weixin-js-sdk": "^1.6.0"
+ },
+ "devDependencies": {
+ "prettier": "^2.8.7",
+ "vconsole": "^3.15.0"
+ }
+}
diff --git a/pages.json b/pages.json
new file mode 100644
index 0000000..cd8ad0e
--- /dev/null
+++ b/pages.json
@@ -0,0 +1,625 @@
+{
+ "easycom": {
+ "autoscan": true,
+ "custom": {
+ "^s-(.*)": "@/sheep/components/s-$1/s-$1.vue",
+ "^su-(.*)": "@/sheep/ui/su-$1/su-$1.vue"
+ }
+ },
+ "pages": [
+ {
+ "path": "pages/tabbar/index",
+ "style": {
+ "navigationStyle": "custom"
+ }
+ },
+ {
+ "path": "pages/index/login",
+ "style": {
+ "navigationBarTitleText": "登录"
+ }
+ }
+ ],
+ "subPackages": [
+ {
+ "root": "pages/trend",
+ "pages": [
+ {
+ "path": "city/list",
+ "style": {
+ "navigationStyle": "custom"
+ }
+ },
+ {
+ "path": "detail/index",
+ "style": {
+ "navigationStyle": "custom"
+ }
+ },
+ {
+ "path": "my/list",
+ "style": {
+ "navigationStyle": "custom"
+ },
+ "meta": {
+ "auth": true
+ }
+ }
+ ]
+ },
+ {
+ "root": "pages/reward",
+ "pages": [
+ {
+ "path": "list",
+ "style": {
+ "navigationStyle": "custom"
+ },
+ "meta": {
+ "auth": true
+ }
+ }
+ ]
+ },
+ {
+ "root": "pages/worker",
+ "pages": [
+ {
+ "path": "levelList/index",
+ "style": {
+ "navigationStyle": "custom"
+ }
+ },
+ {
+ "path": "workerList/index",
+ "style": {
+ "navigationStyle": "custom"
+ },
+ "meta": {
+ "auth": true
+ }
+ },
+ {
+ "path": "workerList/set",
+ "style": {
+ "navigationStyle": "custom"
+ }
+ },
+ {
+ "path": "blind/index",
+ "style": {
+ "navigationStyle": "custom"
+ }
+ }
+ ]
+ },
+ {
+ "root": "pages/clerk",
+ "pages": [
+ {
+ "path": "apply/index",
+ "style": {
+ "navigationStyle": "custom"
+ },
+ "meta": {
+ "auth": true
+ }
+ },
+ {
+ "path": "fans/list",
+ "style": {
+ "navigationStyle": "custom"
+ },
+ "meta": {
+ "auth": true
+ }
+ },
+ {
+ "path": "apply/edit",
+ "style": {
+ "navigationStyle": "custom"
+ }
+ },
+ {
+ "path": "detail/index",
+ "style": {
+ "navigationStyle": "custom"
+ }
+ }
+ ]
+ },
+ {
+ "root": "pages/goods",
+ "pages": [
+ {
+ "path": "comment/worker/add",
+ "style": {
+ "navigationBarTitleText": "评价店员"
+ },
+ "meta": {
+ "auth": true
+ }
+ }
+ ]
+ },
+ {
+ "root": "pages/order",
+ "pages": [
+ {
+ "path": "worker/confirm",
+ "style": {
+ "navigationStyle": "custom"
+ }
+ },
+ {
+ "path": "blind/confirm",
+ "style": {
+ "navigationStyle": "custom"
+ },
+ "meta": {
+ "auth": true
+ }
+ },
+ {
+ "path": "worker/aftersale/apply",
+ "style": {
+ "navigationStyle": "custom"
+ }
+ },
+ {
+ "path": "my/aftersale/apply",
+ "style": {
+ "navigationStyle": "custom"
+ }
+ },
+ {
+ "path": "worker/aftersale/list",
+ "style": {
+ "navigationStyle": "custom"
+ }
+ },
+ {
+ "path": "blind/detail",
+ "style": {
+ "navigationStyle": "custom"
+ }
+ },
+ {
+ "path": "worker/detail",
+ "style": {
+ "navigationStyle": "custom"
+ }
+ },
+ {
+ "path": "my/detail",
+ "style": {
+ "navigationStyle": "custom"
+ }
+ },
+ {
+ "path": "worker/list",
+ "style": {
+ "navigationStyle": "custom"
+ },
+ "meta": {
+ "auth": true
+ }
+ },
+ {
+ "path": "blind/list",
+ "style": {
+ "navigationStyle": "custom"
+ },
+ "meta": {
+ "auth": true
+ }
+ },
+ {
+ "path": "my/list",
+ "style": {
+ "navigationStyle": "custom"
+ },
+ "meta": {
+ "auth": true
+ }
+ },
+ {
+ "path": "receive/index",
+ "style": {
+ "navigationStyle": "custom"
+ }
+ },
+ {
+ "path": "my/index",
+ "style": {
+ "navigationStyle": "custom"
+ }
+ }
+ ]
+ },
+ {
+ "root": "pages/user",
+ "pages": [{
+ "path": "info",
+ "style": {
+ "navigationBarTitleText": "我的信息"
+ },
+ "meta": {
+ "auth": true,
+ "sync": true,
+ "title": "用户信息",
+ "group": "用户中心"
+ }
+ },
+ {
+ "path": "vip",
+ "style": {
+ "navigationStyle": "custom"
+ },
+ "meta": {
+ "auth": true
+ }
+ },
+ {
+ "path": "detail/index",
+ "style": {
+ "navigationStyle": "custom"
+ },
+ "meta": {
+ "auth": true
+ }
+ },
+ {
+ "path": "wallet/money",
+ "style": {
+ "navigationBarTitleText": "我的余额"
+ },
+ "meta": {
+ "auth": true,
+ "sync": true,
+ "title": "用户余额",
+ "group": "用户中心"
+ }
+ },
+ {
+ "path": "wallet/score",
+ "style": {
+ "navigationBarTitleText": "我的积分"
+ },
+ "meta": {
+ "auth": true,
+ "sync": true,
+ "title": "用户积分",
+ "group": "用户中心"
+ }
+ }
+ ]
+ },
+ {
+ "root": "pages/commission",
+ "pages": [{
+ "path": "index",
+ "style": {
+ "navigationBarTitleText": "分销"
+ },
+ "meta": {
+ "auth": true,
+ "sync": true,
+ "title": "分销中心",
+ "group": "分销商城"
+ }
+ },
+ {
+ "path": "wallet",
+ "style": {
+ "navigationBarTitleText": "我的佣金"
+ },
+ "meta": {
+ "auth": true,
+ "sync": true,
+ "title": "用户佣金",
+ "group": "分销中心"
+ }
+ },
+ {
+ "path": "order",
+ "style": {
+ "navigationBarTitleText": "分销订单"
+ },
+ "meta": {
+ "auth": true,
+ "sync": true,
+ "title": "分销订单",
+ "group": "分销商城"
+ }
+ },
+ {
+ "path": "team",
+ "style": {
+ "navigationBarTitleText": "我的团队"
+ },
+ "meta": {
+ "auth": true,
+ "sync": true,
+ "title": "我的团队",
+ "group": "分销商城"
+ }
+ }, {
+ "path": "promoter",
+ "style": {
+ "navigationBarTitleText": "推广人排行榜"
+ },
+ "meta": {
+ "auth": true,
+ "sync": true,
+ "title": "推广人排行榜",
+ "group": "分销商城"
+ }
+ }, {
+ "path": "commission-ranking",
+ "style": {
+ "navigationBarTitleText": "佣金排行榜"
+ },
+ "meta": {
+ "auth": true,
+ "sync": true,
+ "title": "佣金排行榜",
+ "group": "分销商城"
+ }
+ }, {
+ "path": "withdraw",
+ "style": {
+ "navigationBarTitleText": "申请提现"
+ },
+ "meta": {
+ "auth": true,
+ "sync": true,
+ "title": "申请提现",
+ "group": "分销商城"
+ }
+ }
+ ]
+ },
+ {
+ "root": "pages/app",
+ "pages": [{
+ "path": "sign",
+ "style": {
+ "navigationBarTitleText": "签到中心"
+ },
+ "meta": {
+ "auth": true,
+ "sync": true,
+ "title": "签到中心",
+ "group": "应用"
+ }
+ }]
+ },
+ {
+ "root": "pages/public",
+ "pages": [{
+ "path": "setting",
+ "style": {
+ "navigationBarTitleText": "系统设置"
+ },
+ "meta": {
+ "auth": true,
+ "sync": true,
+ "title": "系统设置",
+ "group": "通用"
+ }
+ },
+ {
+ "path": "richtext",
+ "style": {
+ "navigationBarTitleText": "富文本"
+ },
+ "meta": {
+ "sync": true,
+ "title": "富文本",
+ "group": "通用"
+ }
+ },
+ {
+ "path": "faq",
+ "style": {
+ "navigationBarTitleText": "常见问题"
+ },
+ "meta": {
+ "sync": true,
+ "title": "常见问题",
+ "group": "通用"
+ }
+ },
+ {
+ "path": "error",
+ "style": {
+ "navigationBarTitleText": "错误页面"
+ }
+ },
+ {
+ "path": "webview",
+ "style": {
+ "navigationBarTitleText": ""
+ }
+ }
+ ]
+ },
+ {
+ "root": "pages/coupon",
+ "pages": [{
+ "path": "list",
+ "style": {
+ "navigationBarTitleText": "领券中心"
+ },
+ "meta": {
+ "auth": true,
+ "sync": true,
+ "title": "领券中心",
+ "group": "优惠券"
+ }
+ },
+ {
+ "path": "detail",
+ "style": {
+ "navigationBarTitleText": "优惠券"
+ },
+ "meta": {
+ "auth": false,
+ "sync": true,
+ "title": "优惠券详情",
+ "group": "优惠券"
+ }
+ }
+ ]
+ },
+ {
+ "root": "pages/chat",
+ "pages": [{
+ "path": "index",
+ "style": {
+ "navigationBarTitleText": "客服"
+ },
+ "meta": {
+ "auth": true,
+ "sync": true,
+ "title": "客服",
+ "group": "客服"
+ }
+ }]
+ },
+ {
+ "root": "pages/im",
+ "pages": [{
+ "path": "index",
+ "style": {
+ "navigationBarTitleText": "聊天"
+ },
+ "meta": {
+ "auth": true,
+ "sync": true,
+ "title": "聊天",
+ "group": "聊天"
+ }
+ }]
+ },
+ {
+ "root": "pages/point",
+ "pages": [
+ {
+ "path": "recharge",
+ "style": {
+ "navigationBarTitleText": "充值积分"
+ },
+ "meta": {
+ "auth": true,
+ "sync": true,
+ "title": "充值积分",
+ "group": "支付"
+ }
+ },
+ {
+ "path": "recharge-log",
+ "style": {
+ "navigationBarTitleText": "充值记录"
+ },
+ "meta": {
+ "auth": true,
+ "sync": true,
+ "title": "充值记录",
+ "group": "支付"
+ }
+ },
+ {
+ "path": "result",
+ "style": {
+ "navigationBarTitleText": "支付结果"
+ },
+ "meta": {
+ "auth": true,
+ "sync": true,
+ "title": "支付结果",
+ "group": "支付"
+ }
+ }
+ ]
+ },
+ {
+ "root": "pages/pay",
+ "pages": [{
+ "path": "index",
+ "style": {
+ "navigationBarTitleText": "收银台"
+ }
+ },
+ {
+ "path": "result",
+ "style": {
+ "navigationBarTitleText": "支付结果"
+ }
+ },
+ {
+ "path": "worker/index",
+ "style": {
+ "navigationStyle": "custom"
+ }
+ },
+ {
+ "path": "point/index",
+ "style": {
+ "navigationStyle": "custom"
+ }
+ },
+ {
+ "path": "vip/index",
+ "style": {
+ "navigationStyle": "custom"
+ }
+ },
+ {
+ "path": "reward/index",
+ "style": {
+ "navigationStyle": "custom"
+ }
+ },
+ {
+ "path": "worker/result",
+ "style": {
+ "navigationStyle": "custom"
+ }
+ },
+ {
+ "path": "recharge",
+ "style": {
+ "navigationBarTitleText": "充值余额"
+ },
+ "meta": {
+ "auth": true,
+ "sync": true,
+ "title": "充值余额",
+ "group": "支付"
+ }
+ },
+ {
+ "path": "recharge-log",
+ "style": {
+ "navigationBarTitleText": "充值记录"
+ },
+ "meta": {
+ "auth": true,
+ "sync": true,
+ "title": "充值记录",
+ "group": "支付"
+ }
+ }
+ ]
+ }
+ ],
+ "globalStyle": {
+ "navigationBarTextStyle": "black",
+ "navigationBarTitleText": "晚趣语音",
+ "navigationBarBackgroundColor": "#FFFFFF",
+ "backgroundColor": "#FFFFFF",
+ "navigationStyle": "custom"
+ }
+}
diff --git a/pages/app/sign.vue b/pages/app/sign.vue
new file mode 100644
index 0000000..7a4702c
--- /dev/null
+++ b/pages/app/sign.vue
@@ -0,0 +1,451 @@
+
+
+
+
+
+
+
+
+
+ 签到日历
+
+ 已连续签到 {{ state.signInfo.continuousDay }} 天
+
+
+
+
+
+ 第{{ item.day }}天
+
+
+
+
+ + {{ item.point }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 签到说明
+ 1、已累计签到{{state.signInfo.totalDay}}天
+
+ 2、据说连续签到第 {{ state.maxDay }} 天可获得超额积分,一定要坚持签到哦~~~
+
+
+
+
+
+
+
+
+
+
+ {{ state.signResult.point }} 积分
+ {{ state.signResult.experience }} 经验
+
+
+ 已连续打卡 {{ state.signResult.day }} 天
+
+
+
+ 签到成功
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/chat/components/goods.vue b/pages/chat/components/goods.vue
new file mode 100644
index 0000000..eabdd21
--- /dev/null
+++ b/pages/chat/components/goods.vue
@@ -0,0 +1,21 @@
+
+
+
+
+
+
diff --git a/pages/chat/components/messageInput.vue b/pages/chat/components/messageInput.vue
new file mode 100644
index 0000000..1714ac5
--- /dev/null
+++ b/pages/chat/components/messageInput.vue
@@ -0,0 +1,102 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/chat/components/messageList.vue b/pages/chat/components/messageList.vue
new file mode 100644
index 0000000..d08fd83
--- /dev/null
+++ b/pages/chat/components/messageList.vue
@@ -0,0 +1,94 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 有新消息
+
+
+
+
+
diff --git a/pages/chat/components/messageListItem.vue b/pages/chat/components/messageListItem.vue
new file mode 100644
index 0000000..3379539
--- /dev/null
+++ b/pages/chat/components/messageListItem.vue
@@ -0,0 +1,304 @@
+
+
+
+
+
+
+
+ {{ formatDate(message.createTime) }}
+
+
+
+ {{ message.content }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/chat/components/order.vue b/pages/chat/components/order.vue
new file mode 100644
index 0000000..3a68172
--- /dev/null
+++ b/pages/chat/components/order.vue
@@ -0,0 +1,115 @@
+
+
+
+
+
+
+
+
+ 共 {{ orderData.productCount }} 件商品,总金额:
+
+ ¥{{ fen2yuan(orderData.payPrice) }}
+
+
+
+
+
+
+
+
+
diff --git a/pages/chat/components/select-popup.vue b/pages/chat/components/select-popup.vue
new file mode 100644
index 0000000..60711af
--- /dev/null
+++ b/pages/chat/components/select-popup.vue
@@ -0,0 +1,151 @@
+
+
+
+
+
+
+
+
+
diff --git a/pages/chat/components/toolsPopup.vue b/pages/chat/components/toolsPopup.vue
new file mode 100644
index 0000000..d446197
--- /dev/null
+++ b/pages/chat/components/toolsPopup.vue
@@ -0,0 +1,166 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 图片
+
+
+
+
+ 订单
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/chat/index.vue b/pages/chat/index.vue
new file mode 100644
index 0000000..5b20a61
--- /dev/null
+++ b/pages/chat/index.vue
@@ -0,0 +1,187 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/chat/util/constants.js b/pages/chat/util/constants.js
new file mode 100644
index 0000000..bdf5cb3
--- /dev/null
+++ b/pages/chat/util/constants.js
@@ -0,0 +1,21 @@
+export const KeFuMessageContentTypeEnum = {
+ TEXT: 1, // 文本消息
+ IMAGE: 2, // 图片消息
+ VOICE: 3, // 语音消息
+ VIDEO: 4, // 视频消息
+ SYSTEM: 5, // 系统消息
+ // ========== 商城特殊消息 ==========
+ PRODUCT: 10,// 商品消息
+ ORDER: 11,// 订单消息"
+};
+export const UserTypeEnum = {
+ MEMBER: 1, // 会员 面向 c 端,普通用户
+ ADMIN: 2, // 管理员 面向 b 端,管理后台
+};
+// Promotion 的 WebSocket 消息类型枚举类
+export const WebSocketMessageTypeConstants = {
+ KEFU_MESSAGE_TYPE: 'kefu_message_type', // 客服消息类型
+ IM_MESSAGE_READ: 'im_message_read_status_change', // IM消息已读
+ IM_MESSAGE_NEWS: 'im_message_news', // IM新消息
+ KEFU_MESSAGE_ADMIN_READ: 'kefu_message_read_status_change' // 客服消息管理员已读
+}
diff --git a/pages/chat/util/emoji.js b/pages/chat/util/emoji.js
new file mode 100644
index 0000000..83e6e84
--- /dev/null
+++ b/pages/chat/util/emoji.js
@@ -0,0 +1,58 @@
+export const emojiList = [
+ { name: '[笑掉牙]', file: 'xiaodiaoya.png' },
+ { name: '[可爱]', file: 'keai.png' },
+ { name: '[冷酷]', file: 'lengku.png' },
+ { name: '[闭嘴]', file: 'bizui.png' },
+ { name: '[生气]', file: 'shengqi.png' },
+ { name: '[惊恐]', file: 'jingkong.png' },
+ { name: '[瞌睡]', file: 'keshui.png' },
+ { name: '[大笑]', file: 'daxiao.png' },
+ { name: '[爱心]', file: 'aixin.png' },
+ { name: '[坏笑]', file: 'huaixiao.png' },
+ { name: '[飞吻]', file: 'feiwen.png' },
+ { name: '[疑问]', file: 'yiwen.png' },
+ { name: '[开心]', file: 'kaixin.png' },
+ { name: '[发呆]', file: 'fadai.png' },
+ { name: '[流泪]', file: 'liulei.png' },
+ { name: '[汗颜]', file: 'hanyan.png' },
+ { name: '[惊悚]', file: 'jingshu.png' },
+ { name: '[困~]', file: 'kun.png' },
+ { name: '[心碎]', file: 'xinsui.png' },
+ { name: '[天使]', file: 'tianshi.png' },
+ { name: '[晕]', file: 'yun.png' },
+ { name: '[啊]', file: 'a.png' },
+ { name: '[愤怒]', file: 'fennu.png' },
+ { name: '[睡着]', file: 'shuizhuo.png' },
+ { name: '[面无表情]', file: 'mianwubiaoqing.png' },
+ { name: '[难过]', file: 'nanguo.png' },
+ { name: '[犯困]', file: 'fankun.png' },
+ { name: '[好吃]', file: 'haochi.png' },
+ { name: '[呕吐]', file: 'outu.png' },
+ { name: '[龇牙]', file: 'ziya.png' },
+ { name: '[懵比]', file: 'mengbi.png' },
+ { name: '[白眼]', file: 'baiyan.png' },
+ { name: '[饿死]', file: 'esi.png' },
+ { name: '[凶]', file: 'xiong.png' },
+ { name: '[感冒]', file: 'ganmao.png' },
+ { name: '[流汗]', file: 'liuhan.png' },
+ { name: '[笑哭]', file: 'xiaoku.png' },
+ { name: '[流口水]', file: 'liukoushui.png' },
+ { name: '[尴尬]', file: 'ganga.png' },
+ { name: '[惊讶]', file: 'jingya.png' },
+ { name: '[大惊]', file: 'dajing.png' },
+ { name: '[不好意思]', file: 'buhaoyisi.png' },
+ { name: '[大闹]', file: 'danao.png' },
+ { name: '[不可思议]', file: 'bukesiyi.png' },
+ { name: '[爱你]', file: 'aini.png' },
+ { name: '[红心]', file: 'hongxin.png' },
+ { name: '[点赞]', file: 'dianzan.png' },
+ { name: '[恶魔]', file: 'emo.png' },
+];
+
+export let emojiPage = {};
+emojiList.forEach((item, index) => {
+ if (!emojiPage[Math.floor(index / 30) + 1]) {
+ emojiPage[Math.floor(index / 30) + 1] = [];
+ }
+ emojiPage[Math.floor(index / 30) + 1].push(item);
+});
diff --git a/pages/clerk/apply/components/formAvatar.vue b/pages/clerk/apply/components/formAvatar.vue
new file mode 100644
index 0000000..73b8f4a
--- /dev/null
+++ b/pages/clerk/apply/components/formAvatar.vue
@@ -0,0 +1,183 @@
+
+
+
+ 上传头像
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/clerk/apply/components/formCity.vue b/pages/clerk/apply/components/formCity.vue
new file mode 100644
index 0000000..b101a8a
--- /dev/null
+++ b/pages/clerk/apply/components/formCity.vue
@@ -0,0 +1,69 @@
+
+
+
+ 所在城市
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/clerk/apply/components/formImage.vue b/pages/clerk/apply/components/formImage.vue
new file mode 100644
index 0000000..ad63575
--- /dev/null
+++ b/pages/clerk/apply/components/formImage.vue
@@ -0,0 +1,73 @@
+
+
+
+ 上传图片
+ {{imgList.length}}/{{number}}
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/clerk/apply/components/formSex.vue b/pages/clerk/apply/components/formSex.vue
new file mode 100644
index 0000000..00ddbdc
--- /dev/null
+++ b/pages/clerk/apply/components/formSex.vue
@@ -0,0 +1,90 @@
+
+
+ 性别
+
+ {{item.name}}
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/clerk/apply/components/formVoice.vue b/pages/clerk/apply/components/formVoice.vue
new file mode 100644
index 0000000..1422d8c
--- /dev/null
+++ b/pages/clerk/apply/components/formVoice.vue
@@ -0,0 +1,255 @@
+
+
+
+ 录音
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 停止播放
+ 播放录音
+
+
+
+
+
+
+ 重录
+
+
+
+
+
+
+
+
+ 停止播放
+ 播放录音
+
+
+
+
+
+ 上传录音文件
+
+
+
+ 重录
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/clerk/apply/edit.vue b/pages/clerk/apply/edit.vue
new file mode 100644
index 0000000..4d017c4
--- /dev/null
+++ b/pages/clerk/apply/edit.vue
@@ -0,0 +1,213 @@
+
+
+
+
+
+
+
+
+
+
+ 昵称
+
+
+
+
+ 年龄
+
+
+
+ 微信
+
+
+
+ 手机号
+
+
+
+ 相关经验
+
+
+
+ 自我介绍
+
+
+
+ 所在城市
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 提交申请
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/clerk/apply/index.vue b/pages/clerk/apply/index.vue
new file mode 100644
index 0000000..ff88263
--- /dev/null
+++ b/pages/clerk/apply/index.vue
@@ -0,0 +1,307 @@
+
+
+
+
+
+
+
+ 获取实时审核结果
+ 立即订阅
+
+
+
+
+
+
+
+
+
+ 昵称
+
+
+
+
+ 年龄
+
+
+
+ 微信
+
+
+
+ 手机号
+
+
+
+ 自我介绍
+
+
+
+ 所在城市
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 我已阅读并接受
+ 《达人申请协议》
+
+
+
+ 提交申请
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/clerk/detail/components/detail-navbar.vue b/pages/clerk/detail/components/detail-navbar.vue
new file mode 100644
index 0000000..f4b7e2f
--- /dev/null
+++ b/pages/clerk/detail/components/detail-navbar.vue
@@ -0,0 +1,225 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.label }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/clerk/detail/components/gameBox.vue b/pages/clerk/detail/components/gameBox.vue
new file mode 100644
index 0000000..7930cef
--- /dev/null
+++ b/pages/clerk/detail/components/gameBox.vue
@@ -0,0 +1,150 @@
+
+
+
+
+
+ 服务类型
+
+
+ {{option.name}}
+
+
+
+
+
+
+ 选项
+
+
+ {{option.name}}
+
+
+
+
+
+
+ 选项
+
+
+ {{option.name}}
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/clerk/detail/components/giftList.vue b/pages/clerk/detail/components/giftList.vue
new file mode 100644
index 0000000..63eefff
--- /dev/null
+++ b/pages/clerk/detail/components/giftList.vue
@@ -0,0 +1,316 @@
+
+
+
+
+ 选择礼物
+
+
+ 取消
+
+
+
+
+
+
+
+ 特效
+ ·{{item.tag}}
+
+
+ {{item.tag}}
+
+
+ {{item.name}}
+ {{ fen2yuan(item.money) }} 钻石
+
+
+
+
+
+
+
+
+
+
+ {{gift.name}}
+ {{ fen2yuan(gift.money) }} 钻石
+
+ 取消
+ 确定
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/clerk/detail/components/giftPopup.vue b/pages/clerk/detail/components/giftPopup.vue
new file mode 100644
index 0000000..397d7f0
--- /dev/null
+++ b/pages/clerk/detail/components/giftPopup.vue
@@ -0,0 +1,444 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 服务类型
+
+
+
+ 赠礼
+
+
+
+
+
+
+ 打赏金额
+
+
+
+
+
+
+
+
+ 赠送礼物
+
+
+ 已选【{{gift.name}}】
+ 点击选择礼物
+
+
+
+
+
+
+ 礼物数量
+
+
+
+
+
+
+
+
+
+ 心动留言
+
+
+
+
+
+
+
+
+ 您的微信号
+
+
+
+
+
+
+
+
+
+
+
+
+ 立即赠送
+
+
+
+
+
+ 总价:
+ {{ fen2yuan(gift.money*form.count) }}
+ 钻石
+
+
+ 立即赠送
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/clerk/detail/components/layout.vue b/pages/clerk/detail/components/layout.vue
new file mode 100644
index 0000000..f552d28
--- /dev/null
+++ b/pages/clerk/detail/components/layout.vue
@@ -0,0 +1,263 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 立即下单
+ 赠礼
+
+
+ 立即下单
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/clerk/detail/components/navBar.vue b/pages/clerk/detail/components/navBar.vue
new file mode 100644
index 0000000..8504cbe
--- /dev/null
+++ b/pages/clerk/detail/components/navBar.vue
@@ -0,0 +1,89 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/clerk/detail/components/orderPopup.vue b/pages/clerk/detail/components/orderPopup.vue
new file mode 100644
index 0000000..a50c285
--- /dev/null
+++ b/pages/clerk/detail/components/orderPopup.vue
@@ -0,0 +1,282 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 购买数量
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 总价:
+ {{ fen2yuan(game.price*order.num) }}
+ 钻石
+
+
+ 立即下单
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/clerk/detail/components/photoBox.vue b/pages/clerk/detail/components/photoBox.vue
new file mode 100644
index 0000000..7d575ed
--- /dev/null
+++ b/pages/clerk/detail/components/photoBox.vue
@@ -0,0 +1,50 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/clerk/detail/components/postList.vue b/pages/clerk/detail/components/postList.vue
new file mode 100644
index 0000000..7c1bca8
--- /dev/null
+++ b/pages/clerk/detail/components/postList.vue
@@ -0,0 +1,342 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{item.city}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/clerk/detail/components/priceList.vue b/pages/clerk/detail/components/priceList.vue
new file mode 100644
index 0000000..284ef71
--- /dev/null
+++ b/pages/clerk/detail/components/priceList.vue
@@ -0,0 +1,50 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/clerk/detail/components/radioBox.vue b/pages/clerk/detail/components/radioBox.vue
new file mode 100644
index 0000000..da299ce
--- /dev/null
+++ b/pages/clerk/detail/components/radioBox.vue
@@ -0,0 +1,112 @@
+
+
+
+
+
+
+
+
+ {{option.name}}
+
+
+ {{option.number}}
+ 钻石
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/clerk/detail/components/rateList.vue b/pages/clerk/detail/components/rateList.vue
new file mode 100644
index 0000000..648d122
--- /dev/null
+++ b/pages/clerk/detail/components/rateList.vue
@@ -0,0 +1,125 @@
+
+
+
+
+
+
+
+ {{item.userNickname}}
+
+
+ {{item.createTimeStr}}
+
+
+
+
+ {{clerk.nickname}}
+ 服务类型:{{item.skuName}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/clerk/detail/components/starList.vue b/pages/clerk/detail/components/starList.vue
new file mode 100644
index 0000000..32ff751
--- /dev/null
+++ b/pages/clerk/detail/components/starList.vue
@@ -0,0 +1,310 @@
+
+
+
+
+ 礼物墙
+ (已点亮:{{starNum}}/{{total}})
+
+
+
+
+
+
+
+ 特效
+ ·{{item.tag}}
+
+
+ {{item.tag}}
+
+
+ {{item.name}}
+ x {{item.playNum}}
+ 点亮
+ 赠送
+ 已下架
+
+
+
+
+
+
+
+
+
+
+ {{gift.name}}
+ {{ fen2yuan(gift.money) }} 钻石
+
+ 取消
+ 点亮
+ 赠送
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/clerk/detail/components/stickyBox.vue b/pages/clerk/detail/components/stickyBox.vue
new file mode 100644
index 0000000..089eda2
--- /dev/null
+++ b/pages/clerk/detail/components/stickyBox.vue
@@ -0,0 +1,64 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/clerk/detail/components/table-bd.vue b/pages/clerk/detail/components/table-bd.vue
new file mode 100644
index 0000000..8819269
--- /dev/null
+++ b/pages/clerk/detail/components/table-bd.vue
@@ -0,0 +1,100 @@
+
+
+
+
+
+
+
+
+
diff --git a/pages/clerk/detail/components/table-td.vue b/pages/clerk/detail/components/table-td.vue
new file mode 100644
index 0000000..13c6ea3
--- /dev/null
+++ b/pages/clerk/detail/components/table-td.vue
@@ -0,0 +1,305 @@
+
+
+
+
+
+
+
+
+
diff --git a/pages/clerk/detail/components/table-tr.vue b/pages/clerk/detail/components/table-tr.vue
new file mode 100644
index 0000000..2b12c95
--- /dev/null
+++ b/pages/clerk/detail/components/table-tr.vue
@@ -0,0 +1,208 @@
+
+
+
+
+
+
+
+
+
diff --git a/pages/clerk/detail/components/tableList.vue b/pages/clerk/detail/components/tableList.vue
new file mode 100644
index 0000000..50ddbde
--- /dev/null
+++ b/pages/clerk/detail/components/tableList.vue
@@ -0,0 +1,98 @@
+
+
+
+
+
+ 服务项目
+ 价格
+
+
+
+
+ {{tb.name}}
+
+
+
+
+
+ {{tb2.name}}
+
+
+
+
+
+
+ {{ fen2yuan(tb2.price) }}
+
+
+
+
+
+
+
+
+
+ {{tb2.name}}
+
+
+
+ {{tb3.name}}
+
+
+
+
+
+
+
+
+
+
+
+ {{ fen2yuan(tb3.price) }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/clerk/detail/components/userBox.vue b/pages/clerk/detail/components/userBox.vue
new file mode 100644
index 0000000..3e6ce6f
--- /dev/null
+++ b/pages/clerk/detail/components/userBox.vue
@@ -0,0 +1,270 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{clerk.nickname}}
+
+
+ {{clerkLevel.name}}
+
+
+ 可接单
+ 休息中
+
+
+
+
+
+
+
+
+
+ {{clerk.age}}
+
+
+ {{clerk.intro}}
+
+
+
+
+
+
+
+
+ {{categoryName}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/clerk/detail/components/voicePlay.vue b/pages/clerk/detail/components/voicePlay.vue
new file mode 100644
index 0000000..4eee5b7
--- /dev/null
+++ b/pages/clerk/detail/components/voicePlay.vue
@@ -0,0 +1,183 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{sec}}"
+
+
+
+
diff --git a/pages/clerk/detail/index.vue b/pages/clerk/detail/index.vue
new file mode 100644
index 0000000..3f63706
--- /dev/null
+++ b/pages/clerk/detail/index.vue
@@ -0,0 +1,61 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/clerk/fans/components/layout.vue b/pages/clerk/fans/components/layout.vue
new file mode 100644
index 0000000..f0bb9d9
--- /dev/null
+++ b/pages/clerk/fans/components/layout.vue
@@ -0,0 +1,82 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/clerk/fans/components/orderList.vue b/pages/clerk/fans/components/orderList.vue
new file mode 100644
index 0000000..adc3a4f
--- /dev/null
+++ b/pages/clerk/fans/components/orderList.vue
@@ -0,0 +1,212 @@
+
+
+
+
+
+
+
+
+
+ {{item.nickname}}
+
+
+ 在线
+
+
+
+ 休息中
+
+
+ {{item.city}}
+
+
+ 女
+ 男
+ {{item.age}}岁
+
+
+ {{item.fansNum}}人收藏
+
+
+
+
+ {{item.intro}}
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/clerk/fans/list.vue b/pages/clerk/fans/list.vue
new file mode 100644
index 0000000..6825d61
--- /dev/null
+++ b/pages/clerk/fans/list.vue
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/commission/commission-ranking.vue b/pages/commission/commission-ranking.vue
new file mode 100644
index 0000000..d8dd4ab
--- /dev/null
+++ b/pages/commission/commission-ranking.vue
@@ -0,0 +1,249 @@
+
+
+
+
+
+
+
+
+ {{ item }}
+
+
+
+
+
+
+
+
+ {{ index + 1 }}
+
+
+
+
+
+ {{ item.nickname }}
+
+ ¥{{ fen2yuan(item.brokeragePrice) }}
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/commission/components/account-info.vue b/pages/commission/components/account-info.vue
new file mode 100644
index 0000000..d904b8d
--- /dev/null
+++ b/pages/commission/components/account-info.vue
@@ -0,0 +1,125 @@
+
+
+
+
+
+
+
+
+
+ 当前佣金(元)
+
+ {{ state.showMoney ? fen2yuan(state.summary.brokeragePrice || 0) : '***' }}
+
+
+
+ 昨天的佣金(元)
+
+ {{ state.showMoney ? fen2yuan(state.summary.yesterdayPrice || 0) : '***' }}
+
+
+
+ 累计已提(元)
+
+ {{ state.showMoney ? fen2yuan(state.summary.withdrawPrice || 0) : '***' }}
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/commission/components/account-type-select.vue b/pages/commission/components/account-type-select.vue
new file mode 100644
index 0000000..c5ee5c0
--- /dev/null
+++ b/pages/commission/components/account-type-select.vue
@@ -0,0 +1,160 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/commission/components/commission-auth.vue b/pages/commission/components/commission-auth.vue
new file mode 100644
index 0000000..9a484fa
--- /dev/null
+++ b/pages/commission/components/commission-auth.vue
@@ -0,0 +1,101 @@
+
+
+
+
+
+
+
+ 抱歉!您没有分销权限
+ 该功能暂不可用
+
+
+
+
+
+
+
+
+
diff --git a/pages/commission/components/commission-info.vue b/pages/commission/components/commission-info.vue
new file mode 100644
index 0000000..948f380
--- /dev/null
+++ b/pages/commission/components/commission-info.vue
@@ -0,0 +1,112 @@
+
+
+
+
+
+
+
+
+
+
+ {{ userInfo.nickname }}
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/commission/components/commission-log.vue b/pages/commission/components/commission-log.vue
new file mode 100644
index 0000000..2c4b70c
--- /dev/null
+++ b/pages/commission/components/commission-log.vue
@@ -0,0 +1,181 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.title }} {{ fen2yuan(item.price) }} 元
+
+
+
+ {{ dayjs(item.createTime).fromNow() }}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/commission/components/commission-menu.vue b/pages/commission/components/commission-menu.vue
new file mode 100644
index 0000000..988b9b7
--- /dev/null
+++ b/pages/commission/components/commission-menu.vue
@@ -0,0 +1,137 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/commission/goods.vue b/pages/commission/goods.vue
new file mode 100644
index 0000000..509cc04
--- /dev/null
+++ b/pages/commission/goods.vue
@@ -0,0 +1,156 @@
+
+
+
+
+
+
+
+ 预计佣金:计算中
+
+ 预计佣金:{{ fen2yuan(item.brokerageMinPrice) }}
+
+
+ 预计佣金:{{ fen2yuan(item.brokerageMinPrice) }} ~
+ {{ fen2yuan(item.brokerageMaxPrice) }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/commission/index.vue b/pages/commission/index.vue
new file mode 100644
index 0000000..1b7ee06
--- /dev/null
+++ b/pages/commission/index.vue
@@ -0,0 +1,51 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/commission/order.vue b/pages/commission/order.vue
new file mode 100644
index 0000000..54232a4
--- /dev/null
+++ b/pages/commission/order.vue
@@ -0,0 +1,328 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/commission/promoter.vue b/pages/commission/promoter.vue
new file mode 100644
index 0000000..b7d0a89
--- /dev/null
+++ b/pages/commission/promoter.vue
@@ -0,0 +1,297 @@
+
+
+
+
+
+
+
+
+
+ {{ index + 4 }}
+
+
+
+
+ {{item.nickname}}
+
+ {{ item.brokerageUserCount }}人
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/commission/team.vue b/pages/commission/team.vue
new file mode 100644
index 0000000..df1ac58
--- /dev/null
+++ b/pages/commission/team.vue
@@ -0,0 +1,585 @@
+
+
+
+
+
+
+
+
+ 一级({{ state.summary.firstBrokerageUserCount || 0 }})
+
+
+ 二级({{ state.summary.secondBrokerageUserCount || 0 }})
+
+
+
+
+
+
+
+
+
+
+
+ 团队排序
+
+
+
+
+ 团队排序
+
+
+
+ 团队排序
+
+
+
+ 金额排序
+
+
+
+ 金额排序
+
+
+
+ 金额排序
+
+
+
+ 订单排序
+
+
+
+ 订单排序
+
+
+
+ 订单排序
+
+
+
+
+
+
+
+
+
+
+ {{ item.nickname }}
+
+ 加入时间:
+ {{ sheep.$helper.timeFormat(item.brokerageTime, 'yyyy-mm-dd hh:MM:ss') }}
+
+
+
+
+
+ {{ item.brokerageUserCount || 0 }} 人
+
+
+ {{ item.orderCount || 0 }}单
+
+ {{ item.brokeragePrice || 0 }}元
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/commission/wallet.vue b/pages/commission/wallet.vue
new file mode 100644
index 0000000..bc69563
--- /dev/null
+++ b/pages/commission/wallet.vue
@@ -0,0 +1,533 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 转余额
+ 将您的佣金转为钻石继续消费
+
+ ¥
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.description }}
+
+ +{{ fen2yuan(item.price) }}
+ {{ fen2yuan(item.price) }}
+
+
+
+ {{
+ sheep.$helper.timeFormat(item.createTime, 'yyyy-mm-dd hh:MM:ss')
+ }}
+ 待结算
+ 已结算
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/commission/withdraw.vue b/pages/commission/withdraw.vue
new file mode 100644
index 0000000..e60309f
--- /dev/null
+++ b/pages/commission/withdraw.vue
@@ -0,0 +1,467 @@
+
+
+
+
+
+
+ 可提现金额(元)
+ {{ fen2yuan(state.brokerageInfo.brokeragePrice) }}
+
+
+
+
+
+
+ 提现至
+
+ 请选择提现方式
+ 钱包余额
+ 银行卡转账
+ 微信零钱
+ 支付宝账户
+
+
+
+
+ 提现金额
+
+ ¥
+
+
+
+
+ 提现账号
+
+
+
+
+
+
+ 收款码
+
+
+
+
+
+
+
+ 持卡人
+
+
+
+
+
+ 提现银行
+
+
+
+
+
+
+
+
+ 开户地址
+
+
+
+
+
+
+
+
+
+ 提现说明
+ 最低提现金额 {{ fen2yuan(state.minPrice) }} 元
+
+ 冻结佣金:¥{{ fen2yuan(state.brokerageInfo.frozenPrice) }}
+ (每笔佣金的冻结期为 {{ state.frozenDays }} 天,到期后可提现)
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/coupon/detail.vue b/pages/coupon/detail.vue
new file mode 100644
index 0000000..2fca525
--- /dev/null
+++ b/pages/coupon/detail.vue
@@ -0,0 +1,390 @@
+
+
+
+
+
+
+
+
+
+
+
+ {{ state.coupon.name }}
+
+ 满 {{ fen2yuan(state.coupon.usePrice) }} 元,
+ {{
+ state.coupon.discountType === 1
+ ? '减 ' + fen2yuan(state.coupon.discountPrice) + ' 元'
+ : '打 ' + state.coupon.discountPercent / 10.0 + ' 折'
+ }}
+
+
+
+ 有效期:领取后 {{ state.coupon.fixedEndTerm }} 天内可用
+
+
+ 有效期: {{ sheep.$helper.timeFormat(state.coupon.validStartTime, 'yyyy-mm-dd') }} 至
+ {{ sheep.$helper.timeFormat(state.coupon.validEndTime, 'yyyy-mm-dd') }}
+
+
+
+
+
+ 优惠券类型
+ {{ state.coupon.discountType === 1 ? '满减券' : '折扣券' }}
+
+
+
+
+ {{ state.coupon.description }}
+
+
+
+
+
+
+
+
+
+ 全场通用
+
+
+
+
+ {{ state.coupon.productScope === 2 ? '指定商品可用' : '指定分类可用' }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/coupon/list.vue b/pages/coupon/list.vue
new file mode 100644
index 0000000..ec5ea45
--- /dev/null
+++ b/pages/coupon/list.vue
@@ -0,0 +1,222 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/goods/comment/add.vue b/pages/goods/comment/add.vue
new file mode 100644
index 0000000..bfbc800
--- /dev/null
+++ b/pages/goods/comment/add.vue
@@ -0,0 +1,190 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 商品质量
+
+
+
+ 服务态度
+
+
+
+
+
+
+ uploadSuccess(payload, index)"
+ />
+
+
+
+ toggleAnonymous(index, event)">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/goods/comment/worker/add.vue b/pages/goods/comment/worker/add.vue
new file mode 100644
index 0000000..0cf7976
--- /dev/null
+++ b/pages/goods/comment/worker/add.vue
@@ -0,0 +1,180 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 店员质量
+
+
+
+ 服务态度
+
+
+
+
+
+
+
+ uploadSuccess(payload, index)"
+ limit="9" mode="grid" :imageStyles="{ width: '168rpx', height: '168rpx' }" />
+
+
+
+ toggleAnonymous(index, event)">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/im/components/cardNotice.vue b/pages/im/components/cardNotice.vue
new file mode 100644
index 0000000..fe43f5f
--- /dev/null
+++ b/pages/im/components/cardNotice.vue
@@ -0,0 +1,41 @@
+
+
+
+
+ 投诉举报
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/im/components/cardSwiper.vue b/pages/im/components/cardSwiper.vue
new file mode 100644
index 0000000..7494020
--- /dev/null
+++ b/pages/im/components/cardSwiper.vue
@@ -0,0 +1,225 @@
+
+
+
+
+
+
+
+
+
+
+ 15开黑卡/局
+ LOL手游
+ 下单前聊一聊
+
+ 找TA开黑
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/im/components/chatBar.vue b/pages/im/components/chatBar.vue
new file mode 100644
index 0000000..97df5cb
--- /dev/null
+++ b/pages/im/components/chatBar.vue
@@ -0,0 +1,1452 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{btnText}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/im/components/layout.vue b/pages/im/components/layout.vue
new file mode 100644
index 0000000..5d29165
--- /dev/null
+++ b/pages/im/components/layout.vue
@@ -0,0 +1,336 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 有新消息
+
+
+
+
+
+
+
+
+
diff --git a/pages/im/components/navigationBar.vue b/pages/im/components/navigationBar.vue
new file mode 100644
index 0000000..cde82cb
--- /dev/null
+++ b/pages/im/components/navigationBar.vue
@@ -0,0 +1,194 @@
+
+
+
+
+
+
+ {{user.nickname}}
+
+
+
+
+
+
+
+
+ 会话重连中
+
+
+ 在线
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/im/components/viewItem.vue b/pages/im/components/viewItem.vue
new file mode 100644
index 0000000..830dc26
--- /dev/null
+++ b/pages/im/components/viewItem.vue
@@ -0,0 +1,385 @@
+
+
+
+
+ {{item.content}}
+
+
+
+
+ 温馨提示
+ {{item.content}}
+
+
+
+
+
+
+ {{showDayTime(item.createTime)}}
+
+
+
+
+
+
+
+ {{item.content}}
+
+
+ {{item.content}}
+
+
+
+
+
+
+ {{item.voiceSec}}”
+
+
+
+
+
+
+
+
+
+
+
+
+ {{item.content}}
+
+
+
+
+ {{item.content}}
+
+
+
+
+
+
+ {{item.voiceSec}}”
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/im/index - 副本.vue b/pages/im/index - 副本.vue
new file mode 100644
index 0000000..7390a29
--- /dev/null
+++ b/pages/im/index - 副本.vue
@@ -0,0 +1,204 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/im/index.vue b/pages/im/index.vue
new file mode 100644
index 0000000..ee4b170
--- /dev/null
+++ b/pages/im/index.vue
@@ -0,0 +1,194 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/im/util/emoji.js b/pages/im/util/emoji.js
new file mode 100644
index 0000000..fb04e14
--- /dev/null
+++ b/pages/im/util/emoji.js
@@ -0,0 +1,33 @@
+export default [
+ "😀", "😁", "😃", "😄", "😅", "😆", "😉", "😊", "😋", "😎", "😍",
+ "😘", "😗", "😙", "😚", "😇", "😐", "😑", "😶", "😏", "😣", "😥", "😮", "😯", "😪",
+ "😫", "😴", "😌", "😛", "😜", "😝", "😒", "😓", "😔", "😕", "😲", "😷", "😖", "😞", "😟",
+ "😤", "😢", "😭", "😦", "😧", "😨", "😬", "😰", "😱", "😳", "😵", "😡", "😠",
+ "👦", "👧", "👨", "👩", "👴", "👵", "👶", "👱", "👮", "👲", "👳", "👷", "👸", "💂", "🎅", "👰", "👼",
+ "💆", "💇", "🙍", "🙎", "🙅", "🙆", "💁", "🙋", "🙇", "🙌", "🙏", "👤", "👥", "🚶", "🏃", "👯",
+ "💃", "👫", "👬", "👭", "💏", "💑", "👪", "💪", "👈", "👉", "☝", "👆", "👇", "✌", "✋", "👌",
+ "👍", "👎", "✊", "👊", "👋", "👏", "👐", "✍", "👣", "👀", "👂", "👃", "👅", "👄", "💋", "👓",
+ "👔", "👙", "👛", "👜", "👝", "🎒", "💼", "👞", "👟", "👠", "👡", "👢", "👑",
+ "👒", "🎩", "🎓", "💄", "💅", "💍", "🌂", "📶", "📳", "📴", "♻", "🏧","🚮", "🚰", "♿", "🚹", "🚺",
+ "🚻", "🚼", "🚾", "⚠", "🚸", "⛔", "🚫", "🚳", "🚭", "🚯", "🚱", "🚷", "🔞", "💈",
+ "🙈", "🐒", "🐶", "🐕", "🐩", "🐺", "🐱","🐈", "🐯", "🐅", "🐆", "🐴", "🐎", "🐮", "🐂",
+ "🐃","🐄","🐷","🐖","🐗","🐽","🐏","🐑","🐐","🐪","🐫","🐘","🐭",
+ "🐁","🐀","🐹","🐰","🐇","🐻","🐨","🐼","🐾","🐔","🐓","🐣","🐤","🐥",
+ "🐦", "🐧", "🐸", "🐊","🐢", "🐍", "🐲", "🐉", "🐳", "🐋", "🐬", "🐟", "🐠", "🐡",
+ "🐙", "🐚", "🐌", "🐛", "🐜", "🐝", "🐞", "🦋", "💐", "🌸", "💮", "🌹", "🌺",
+ "🌻", "🌼", "🌷", "🌱", "🌲", "🌳", "🌴", "🌵", "🌾", "🌿", "🍀", "🍁", "🍂", "🍃",
+ "🌍","🌎","🌏","🌐","🌑","🌒","🌓","🌔","🌕","🌖","🌗","🌘","🌙","🌚",
+ "🌛","🌜","☀","🌝","🌞","⭐","🌟","🌠","☁","⛅","☔","⚡","❄","🔥","💧","🌊",
+ "🏀", "🏈", "🏉", "🎾", "🎱", "🎳", "⛳", "🎣", "🎽", "🎿",
+ "😈", "👿", "👹", "👺", "💀", "☠", "👻", "👽", "👾", "💣",
+ "🌋", "🗻", "🏠", "🏡", "🏢", "🏣", "🏤", "🏥", "🏦", "🏨",
+ "⛲", "🌁", "🌃", "🌆", "🌇", "🎠", "🎡", "🎢", "🚂",
+ "🚌", "🚍", "🚎", "🚏", "🚐", "🚑", "🚒", "🚓", "🚔", "🚕", "🚖", "🚗", "🚘",
+ "💌", "💎", "🔪", "💈", "🚪", "🚽", "🚿", "🛁", "⌛", "⏳", "⌚", "⏰", "🎈", "🎉",
+ "💤", "💢", "💬", "💭", "♨", "🌀", "🔔", "🔕", "✡", "✝", "🔯", "📛", "🔰", "🔱", "⭕", "✅",
+ "☑", "✔", "✖", "❌", "❎", "➕", "➖", "➗", "➰", "➿", "〽", "✳", "✴", "❇", "‼", "⁉", "❓", "❔", "❕", "❗",
+ "🕛", "🕧", "🕐", "🕜", "🕑", "🕝", "🕒", "🕞", "🕓", "🕟", "🕔", "🕠", "🕕", "🕡",
+ "🕖", "🕢", "🕗", "🕣", "🕘", "🕤", "🕙", "🕥", "🕚", "🕦", "⏱", "⏲", "🕰",
+ "💘", "❤", "💓", "💔", "💕", "💖", "💗", "💙", "💚", "💛", "💜", "💝", "💞", "💟❣",
+ "🍇", "🍈", "🍉", "🍊", "🍋", "🍌", "🍍", "🍎", "🍏", "🍐", "🍑", "🍒", "🍓",
+]
\ No newline at end of file
diff --git a/pages/index/cart.vue b/pages/index/cart.vue
new file mode 100644
index 0000000..633b567
--- /dev/null
+++ b/pages/index/cart.vue
@@ -0,0 +1,192 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/index/category.vue b/pages/index/category.vue
new file mode 100644
index 0000000..4c88f38
--- /dev/null
+++ b/pages/index/category.vue
@@ -0,0 +1,237 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/index/components/first-one.vue b/pages/index/components/first-one.vue
new file mode 100644
index 0000000..2decc86
--- /dev/null
+++ b/pages/index/components/first-one.vue
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/index/components/first-two.vue b/pages/index/components/first-two.vue
new file mode 100644
index 0000000..482931c
--- /dev/null
+++ b/pages/index/components/first-two.vue
@@ -0,0 +1,66 @@
+
+
+
+
+
+
+
+
+
+
+ {{ item.title }}
+ ¥{{ fen2yuan(item.price) }}
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/index/components/second-one.vue b/pages/index/components/second-one.vue
new file mode 100644
index 0000000..86b7078
--- /dev/null
+++ b/pages/index/components/second-one.vue
@@ -0,0 +1,80 @@
+
+
+
+
+
+
+ {{ props.data[activeMenu].name }}
+
+
+
+
+
+
+
+ {{ item.name }}
+
+
+
+
+
+
+
+
+
diff --git a/pages/index/index.vue b/pages/index/index.vue
new file mode 100644
index 0000000..c62c563
--- /dev/null
+++ b/pages/index/index.vue
@@ -0,0 +1,88 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/index/login.vue b/pages/index/login.vue
new file mode 100644
index 0000000..e498870
--- /dev/null
+++ b/pages/index/login.vue
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
diff --git a/pages/index/page.vue b/pages/index/page.vue
new file mode 100644
index 0000000..b5d8ef3
--- /dev/null
+++ b/pages/index/page.vue
@@ -0,0 +1,51 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/index/search.vue b/pages/index/search.vue
new file mode 100644
index 0000000..8497298
--- /dev/null
+++ b/pages/index/search.vue
@@ -0,0 +1,119 @@
+
+
+
+
+
+
+
+
+ 搜索历史
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/index/user.vue b/pages/index/user.vue
new file mode 100644
index 0000000..705451a
--- /dev/null
+++ b/pages/index/user.vue
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/order/addressSelection.vue b/pages/order/addressSelection.vue
new file mode 100644
index 0000000..2432d41
--- /dev/null
+++ b/pages/order/addressSelection.vue
@@ -0,0 +1,261 @@
+
+
+
+
+
+
+
+
+
+
+ {{ state.addressInfo.name }}
+ {{ state.addressInfo.mobile }}
+
+
+ [默认]
+ {{ state.addressInfo.areaName }} {{ state.addressInfo.detailAddress }}
+
+
+
+ 设置收货地址
+
+
+
+
+
+
+
+
+
+
+ {{ state.pickUpInfo.name }}
+ {{ state.pickUpInfo.phone }}
+
+ {{ state.pickUpInfo.areaName }}{{ ', ' + state.pickUpInfo.detailAddress }}
+
+
+
+ 选择自提门店
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/order/aftersale/apply.vue b/pages/order/aftersale/apply.vue
new file mode 100644
index 0000000..805ea94
--- /dev/null
+++ b/pages/order/aftersale/apply.vue
@@ -0,0 +1,351 @@
+
+
+
+
+
+
+
+
+
+
+
+ 售后类型
+
+
+
+
+
+
+
+
+ 退款金额
+
+ ¥{{ fen2yuan(state.item.payPrice) }}
+
+
+
+
+ 申请原因
+
+ {{ formData.applyReason }}
+ 请选择申请原因~
+
+
+
+
+
+
+ 相关描述
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 申请原因
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/order/aftersale/detail.vue b/pages/order/aftersale/detail.vue
new file mode 100644
index 0000000..6b7bfcc
--- /dev/null
+++ b/pages/order/aftersale/detail.vue
@@ -0,0 +1,379 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.title }}
+
+
+
+
+
+
+
+
+
+ {{ formatAfterSaleStatusDescription(state.info) }}
+
+
+ {{ sheep.$helper.timeFormat(state.info.updateTime, 'yyyy-mm-dd hh:MM:ss') }}
+
+
+
+
+
+
+
+ 退款总额
+ ¥{{ fen2yuan(state.info.refundPrice) }}
+
+
+
+
+
+
+
+
+
+ 服务单号:
+ {{ state.info.no }}
+
+
+
+ 申请时间:
+
+ {{ sheep.$helper.timeFormat(state.info.createTime, 'yyyy-mm-dd hh:MM:ss') }}
+
+
+
+ 售后类型:
+ {{ state.info.way === 10 ? '仅退款' : '退款退货' }}
+
+
+ 申请原因:
+ {{ state.info.applyReason }}
+
+
+ 相关描述:
+ {{ state.info.applyDescription }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/order/aftersale/list.vue b/pages/order/aftersale/list.vue
new file mode 100644
index 0000000..5ec22b4
--- /dev/null
+++ b/pages/order/aftersale/list.vue
@@ -0,0 +1,210 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ 服务单号:{{ order.no }}
+ {{ formatAfterSaleStatus(order) }}
+
+
+
+
+ {{ order.way === 10 ? '仅退款' : '退款退货' }}
+ {{ formatAfterSaleStatusDescription(order) }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/order/aftersale/log-item.vue b/pages/order/aftersale/log-item.vue
new file mode 100644
index 0000000..01329df
--- /dev/null
+++ b/pages/order/aftersale/log-item.vue
@@ -0,0 +1,77 @@
+
+
+
+
+
+
+
+
+ {{ item.content }}
+
+ {{ sheep.$helper.timeFormat(item.createTime, 'yyyy-mm-dd hh:MM:ss') }}
+
+
+
+
+
+
diff --git a/pages/order/aftersale/log.vue b/pages/order/aftersale/log.vue
new file mode 100644
index 0000000..a8df8a2
--- /dev/null
+++ b/pages/order/aftersale/log.vue
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/order/aftersale/return-delivery.vue b/pages/order/aftersale/return-delivery.vue
new file mode 100644
index 0000000..fa3ecec
--- /dev/null
+++ b/pages/order/aftersale/return-delivery.vue
@@ -0,0 +1,195 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/order/blind/components/layout.vue b/pages/order/blind/components/layout.vue
new file mode 100644
index 0000000..3a0e444
--- /dev/null
+++ b/pages/order/blind/components/layout.vue
@@ -0,0 +1,182 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/order/blind/components/orderList.vue b/pages/order/blind/components/orderList.vue
new file mode 100644
index 0000000..5cc40ec
--- /dev/null
+++ b/pages/order/blind/components/orderList.vue
@@ -0,0 +1,248 @@
+
+
+
+
+
+ {{ order.no }}
+
+ {{order.statusStr}}
+
+
+
+
+
+
+
+
+ {{order.nickname}}
+ 订单时间:{{order.createTimeStr}}
+ 服务内容:{{item.spuName}} {{item.properties.map((property) => property.valueName).join(' ')}}×{{item.count}}
+ 性别要求:女生
+ 性别要求:男生
+
+ 微信:{{order.weixin}}
+
+
+
+
+
+ 剩余时间:
+
+ 已结束
+
+
+
+
+ 暂未接单
+
+ 备注:{{order.userRemark}}
+ 取消原因:{{order.cancelReason}}
+
+
+ {{order.brokeragePrice}}
+ /钻
+
+
+
+
+
+
+ 也被其它店员抢单
+ 查看详情
+ 取消接单
+ 取消订单
+ 邀请好友抢单
+ 邀请评价
+ 立即抢单
+ 结束服务
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/order/blind/components/tabBox.vue b/pages/order/blind/components/tabBox.vue
new file mode 100644
index 0000000..db9711d
--- /dev/null
+++ b/pages/order/blind/components/tabBox.vue
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/order/blind/confirm.vue b/pages/order/blind/confirm.vue
new file mode 100644
index 0000000..92e7541
--- /dev/null
+++ b/pages/order/blind/confirm.vue
@@ -0,0 +1,435 @@
+
+
+
+
+
+
+ 订单备注
+
+
+
+
+
+
+
+
+
+
+ 技能金额
+
+
+ ¥{{ fen2yuan(state.orderInfo.price.totalPrice) }}
+
+
+
+
+ 积分抵扣
+
+ {{ state.pointStatus ? '剩余积分' : '当前积分' }}
+
+
+ {{ state.pointStatus ? state.orderInfo.totalPoint - state.orderInfo.usePoint : (state.orderInfo.totalPoint || 0) }}
+
+
+
+
+
+
+
+ TA添加你的微信号
+
+
+
+
+
+
+ 优惠券
+
+
+ -¥{{ fen2yuan(state.orderInfo.price.couponPrice) }}
+
+
+ {{
+ state.couponInfo.length > 0 ? state.couponInfo.length + ' 张可用' : '暂无可用优惠券'
+ }}
+
+
+
+
+
+ 活动优惠
+
+
+
+ -¥{{ fen2yuan(state.orderInfo.price.discountPrice) }}
+
+
+
+
+
+ 会员优惠
+
+
+ -¥{{ fen2yuan(state.orderInfo.price.vipPrice) }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/order/blind/detail.vue b/pages/order/blind/detail.vue
new file mode 100644
index 0000000..3368079
--- /dev/null
+++ b/pages/order/blind/detail.vue
@@ -0,0 +1,599 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ formatBlindOrderStatus(state.orderInfo) }}
+
+
+ {{ formatBlindOrderStatusDescription(state.orderInfo) }}
+
+
+
+
+
+
+
+ {{ state.orderInfo.receiverName }}
+
+ {{ state.orderInfo.receiverMobile }}
+
+
+ {{ state.orderInfo.receiverAreaName }} {{ state.orderInfo.receiverDetailAddress }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 订单编号:
+ {{ state.orderInfo.no }}
+
+
+
+
+ 下单时间:
+
+ {{ sheep.$helper.timeFormat(state.orderInfo.createTime, 'yyyy-mm-dd hh:MM:ss') }}
+
+
+
+ 支付时间:
+
+ {{ sheep.$helper.timeFormat(state.orderInfo.payTime, 'yyyy-mm-dd hh:MM:ss') }}
+
+
+
+ 支付方式:
+ {{ state.orderInfo.payChannelName || '-' }}
+
+
+
+
+
+
+
+ 订单总额
+
+ ¥{{ fen2yuan(state.orderInfo.totalPrice) }}
+
+
+
+ 优惠劵金额
+ -¥{{ fen2yuan(state.orderInfo.couponPrice) }}
+
+
+ 积分抵扣
+ -¥{{ fen2yuan(state.orderInfo.pointPrice) }}
+
+
+ 活动优惠
+ ¥{{ fen2yuan(state.orderInfo.discountPrice) }}
+
+
+ 会员优惠
+ -¥{{ fen2yuan(state.orderInfo.vipPrice) }}
+
+
+ 用户付款
+ ¥{{ fen2yuan(state.orderInfo.payPrice) }}
+
+
+ 佣金比例
+ {{state.orderInfo.brokeragePercent}}%
+
+
+ {{ state.orderInfo.status == '30' ? '结算佣金' : '可得佣金' }}
+ ¥{{ fen2yuan(state.orderInfo.brokeragePrice) }}
+
+
+ 已退款
+ ¥{{ fen2yuan(state.orderInfo.refundPrice) }}
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/order/blind/list.vue b/pages/order/blind/list.vue
new file mode 100644
index 0000000..03a1146
--- /dev/null
+++ b/pages/order/blind/list.vue
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/order/confirm.vue b/pages/order/confirm.vue
new file mode 100644
index 0000000..b18df4f
--- /dev/null
+++ b/pages/order/confirm.vue
@@ -0,0 +1,468 @@
+
+
+
+
+
+
+
+
+
+ 订单备注
+
+
+
+
+
+
+
+
+
+
+ 商品金额
+
+
+ ¥{{ fen2yuan(state.orderInfo.price.totalPrice) }}
+
+
+
+
+ 积分抵扣
+
+ {{ state.pointStatus ? '剩余积分' : '当前积分' }}
+
+
+ {{ state.pointStatus ? state.orderInfo.totalPoint - state.orderInfo.usePoint : (state.orderInfo.totalPoint || 0) }}
+
+
+
+
+
+
+
+
+ 运费
+
+
+ +¥{{ fen2yuan(state.orderInfo.price.deliveryPrice) }}
+
+ 免运费
+
+
+
+
+ 联系人
+
+
+
+
+
+ 联系电话
+
+
+
+
+
+
+ 优惠券
+
+
+ -¥{{ fen2yuan(state.orderInfo.price.couponPrice) }}
+
+
+ {{
+ state.couponInfo.length > 0 ? state.couponInfo.length + ' 张可用' : '暂无可用优惠券'
+ }}
+
+
+
+
+
+ 活动优惠
+
+
+
+ -¥{{ fen2yuan(state.orderInfo.price.discountPrice) }}
+
+
+
+
+
+ 会员优惠
+
+
+ -¥{{ fen2yuan(state.orderInfo.price.vipPrice) }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/order/detail.vue b/pages/order/detail.vue
new file mode 100644
index 0000000..ed0119f
--- /dev/null
+++ b/pages/order/detail.vue
@@ -0,0 +1,655 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ formatOrderStatus(state.orderInfo) }}
+
+
+ {{ formatOrderStatusDescription(state.orderInfo) }}
+
+
+
+
+
+
+
+ {{ state.orderInfo.receiverName }}
+
+ {{ state.orderInfo.receiverMobile }}
+
+
+ {{ state.orderInfo.receiverAreaName }} {{ state.orderInfo.receiverDetailAddress }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 订单编号:
+ {{ state.orderInfo.no }}
+
+
+
+
+ 下单时间:
+
+ {{ sheep.$helper.timeFormat(state.orderInfo.createTime, 'yyyy-mm-dd hh:MM:ss') }}
+
+
+
+ 支付时间:
+
+ {{ sheep.$helper.timeFormat(state.orderInfo.payTime, 'yyyy-mm-dd hh:MM:ss') }}
+
+
+
+ 支付方式:
+ {{ state.orderInfo.payChannelName || '-' }}
+
+
+
+
+
+
+
+ 商品总额
+
+ ¥{{ fen2yuan(state.orderInfo.totalPrice) }}
+
+
+
+ 运费
+ ¥{{ fen2yuan(state.orderInfo.deliveryPrice) }}
+
+
+ 优惠劵金额
+ -¥{{ fen2yuan(state.orderInfo.couponPrice) }}
+
+
+ 积分抵扣
+ -¥{{ fen2yuan(state.orderInfo.pointPrice) }}
+
+
+ 活动优惠
+ ¥{{ fen2yuan(state.orderInfo.discountPrice) }}
+
+
+ 会员优惠
+ -¥{{ fen2yuan(state.orderInfo.vipPrice) }}
+
+
+ {{ state.orderInfo.payStatus ? '已付款' : '需付款' }}
+ ¥{{ fen2yuan(state.orderInfo.payPrice) }}
+
+
+ 已退款
+ ¥{{ fen2yuan(state.orderInfo.refundPrice) }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/order/express/log.vue b/pages/order/express/log.vue
new file mode 100644
index 0000000..eb992a5
--- /dev/null
+++ b/pages/order/express/log.vue
@@ -0,0 +1,162 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 快递单号:{{ state.info.logisticsNo }}
+ 快递公司:{{ state.info.logisticsName }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.content }}
+
+ {{ sheep.$helper.timeFormat(item.time, 'yyyy-mm-dd hh:MM:ss') }}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/order/list.vue b/pages/order/list.vue
new file mode 100644
index 0000000..926ecfd
--- /dev/null
+++ b/pages/order/list.vue
@@ -0,0 +1,495 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 共 {{ order.productCount }} 件商品,总金额:
+ ¥{{ fen2yuan(order.payPrice) }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/order/my/aftersale/apply.vue b/pages/order/my/aftersale/apply.vue
new file mode 100644
index 0000000..6d86283
--- /dev/null
+++ b/pages/order/my/aftersale/apply.vue
@@ -0,0 +1,333 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ 退回余额
+
+ ¥{{ fen2yuan(state.item.payPrice) }}
+
+
+
+
+
+
+
+ 取消原因
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 取消原因
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/order/my/aftersale/list.vue b/pages/order/my/aftersale/list.vue
new file mode 100644
index 0000000..9ed49bf
--- /dev/null
+++ b/pages/order/my/aftersale/list.vue
@@ -0,0 +1,184 @@
+
+
+
+
+
+
+
+
+ 服务单号:{{ order.no }}
+ {{ formatAfterSaleStatus(order) }}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/order/my/components/layout.vue b/pages/order/my/components/layout.vue
new file mode 100644
index 0000000..8b493d8
--- /dev/null
+++ b/pages/order/my/components/layout.vue
@@ -0,0 +1,130 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/order/my/components/orderList.vue b/pages/order/my/components/orderList.vue
new file mode 100644
index 0000000..f44058e
--- /dev/null
+++ b/pages/order/my/components/orderList.vue
@@ -0,0 +1,219 @@
+
+
+
+
+
+ {{ order.no }}
+
+ {{order.statusStr}}
+
+
+
+
+
+
+
+
+ {{item.nickname}}
+ 待接单..
+ 订单时间:{{order.createTimeStr}}
+ 服务内容:{{item.spuName}} {{item.properties.map((property) => property.valueName).join(' ')}}×{{item.count}}
+ 开始服务时间:{{order.deliveryTimeStr}}
+
+ 剩余时间:
+
+ 已结束
+
+
+
+
+ 暂未接单
+
+ 取消原因:{{order.cancelReason}}
+
+
+ {{order.payPrice}}
+ /钻
+
+
+
+
+
+
+ 查看详情
+ 取消订单
+ 取消订单
+ 再来一单
+ 评价
+ 继续支付
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/order/my/components/tabBox.vue b/pages/order/my/components/tabBox.vue
new file mode 100644
index 0000000..db9711d
--- /dev/null
+++ b/pages/order/my/components/tabBox.vue
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/order/my/confirm.vue b/pages/order/my/confirm.vue
new file mode 100644
index 0000000..2476e5d
--- /dev/null
+++ b/pages/order/my/confirm.vue
@@ -0,0 +1,426 @@
+
+
+
+
+
+
+ 订单备注
+
+
+
+
+
+
+
+
+
+
+ 商品金额
+
+
+ ¥{{ fen2yuan(state.orderInfo.price.totalPrice) }}
+
+
+
+
+ 积分抵扣
+
+ {{ state.pointStatus ? '剩余积分' : '当前积分' }}
+
+
+ {{ state.pointStatus ? state.orderInfo.totalPoint - state.orderInfo.usePoint : (state.orderInfo.totalPoint || 0) }}
+
+
+
+
+
+
+
+ 你的微信号
+
+
+
+
+
+
+ 优惠券
+
+
+ -¥{{ fen2yuan(state.orderInfo.price.couponPrice) }}
+
+
+ {{
+ state.couponInfo.length > 0 ? state.couponInfo.length + ' 张可用' : '暂无可用优惠券'
+ }}
+
+
+
+
+
+ 活动优惠
+
+
+
+ -¥{{ fen2yuan(state.orderInfo.price.discountPrice) }}
+
+
+
+
+
+ 会员优惠
+
+
+ -¥{{ fen2yuan(state.orderInfo.price.vipPrice) }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/order/my/detail.vue b/pages/order/my/detail.vue
new file mode 100644
index 0000000..e03b0c4
--- /dev/null
+++ b/pages/order/my/detail.vue
@@ -0,0 +1,580 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ formatWorkerOrderStatus(state.orderInfo) }}
+
+
+ {{ formatMyOrderStatusDescription(state.orderInfo) }}
+
+
+
+
+
+
+
+ {{ state.orderInfo.receiverName }}
+
+ {{ state.orderInfo.receiverMobile }}
+
+
+ {{ state.orderInfo.receiverAreaName }} {{ state.orderInfo.receiverDetailAddress }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 订单编号:
+ {{ state.orderInfo.no }}
+
+
+
+
+ 下单时间:
+
+ {{ sheep.$helper.timeFormat(state.orderInfo.createTime, 'yyyy-mm-dd hh:MM:ss') }}
+
+
+
+ 支付时间:
+
+ {{ sheep.$helper.timeFormat(state.orderInfo.payTime, 'yyyy-mm-dd hh:MM:ss') }}
+
+
+
+ 支付方式:
+ {{ state.orderInfo.payChannelName || '-' }}
+
+
+
+
+
+
+
+ 订单总额
+
+ ¥{{ fen2yuan(state.orderInfo.totalPrice) }}
+
+
+
+ 优惠劵金额
+ -¥{{ fen2yuan(state.orderInfo.couponPrice) }}
+
+
+ 积分抵扣
+ -¥{{ fen2yuan(state.orderInfo.pointPrice) }}
+
+
+ 活动优惠
+ ¥{{ fen2yuan(state.orderInfo.discountPrice) }}
+
+
+ 会员优惠
+ -¥{{ fen2yuan(state.orderInfo.vipPrice) }}
+
+
+ {{ state.orderInfo.payStatus ? '实付款' : '需付款' }}
+ ¥{{ fen2yuan(state.orderInfo.payPrice) }}
+
+
+ 已退款
+ ¥{{ fen2yuan(state.orderInfo.refundPrice) }}
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/order/my/index.vue b/pages/order/my/index.vue
new file mode 100644
index 0000000..96befc2
--- /dev/null
+++ b/pages/order/my/index.vue
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/order/my/list - 副本.vue b/pages/order/my/list - 副本.vue
new file mode 100644
index 0000000..b7718c0
--- /dev/null
+++ b/pages/order/my/list - 副本.vue
@@ -0,0 +1,514 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 共 {{ order.productCount }} 件商品,总金额:
+ ¥{{ fen2yuan(order.payPrice) }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/order/my/list.vue b/pages/order/my/list.vue
new file mode 100644
index 0000000..6e2bdbb
--- /dev/null
+++ b/pages/order/my/list.vue
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/order/pickUpVerify.vue b/pages/order/pickUpVerify.vue
new file mode 100644
index 0000000..1e8bb6e
--- /dev/null
+++ b/pages/order/pickUpVerify.vue
@@ -0,0 +1,261 @@
+
+
+
+
+ 核销信息
+
+
+
+
+
+
+
+
+ {{ orderInfo.pickUpVerifyCode }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 使用说明
+
+ 可将二维码出示给店员扫描或提供数字核销码
+
+
+
+
+ 自提地址信息
+
+ 查看位置
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/order/receive/components/layout.vue b/pages/order/receive/components/layout.vue
new file mode 100644
index 0000000..7944220
--- /dev/null
+++ b/pages/order/receive/components/layout.vue
@@ -0,0 +1,93 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/order/receive/components/orderList.vue b/pages/order/receive/components/orderList.vue
new file mode 100644
index 0000000..5c21013
--- /dev/null
+++ b/pages/order/receive/components/orderList.vue
@@ -0,0 +1,163 @@
+
+
+
+
+
+ 123213123123
+
+ 待服务
+
+
+
+
+
+
+ 碎冰冰
+ 订单时间:2024-08-10
+ 服务内容:文字×1
+
+ 微信:rbtnet
+
+
+ 剩余时间:已结束
+ 取消原因:
+
+
+ 5.00
+ /钻
+
+
+
+
+
+
+ 结束服务
+ 取消接单
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/order/receive/components/tabBox.vue b/pages/order/receive/components/tabBox.vue
new file mode 100644
index 0000000..532c152
--- /dev/null
+++ b/pages/order/receive/components/tabBox.vue
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/order/receive/index.vue b/pages/order/receive/index.vue
new file mode 100644
index 0000000..be27386
--- /dev/null
+++ b/pages/order/receive/index.vue
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/order/worker/aftersale/apply.vue b/pages/order/worker/aftersale/apply.vue
new file mode 100644
index 0000000..4ebd868
--- /dev/null
+++ b/pages/order/worker/aftersale/apply.vue
@@ -0,0 +1,318 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ 退款金额
+
+ ¥{{ fen2yuan(state.item.payPrice) }}
+
+
+
+
+ 取消原因
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 申请原因
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/order/worker/aftersale/list.vue b/pages/order/worker/aftersale/list.vue
new file mode 100644
index 0000000..78f9d26
--- /dev/null
+++ b/pages/order/worker/aftersale/list.vue
@@ -0,0 +1,184 @@
+
+
+
+
+
+
+
+
+ 服务单号:{{ order.no }}
+ {{ formatAfterSaleStatus(order) }}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/order/worker/components/layout.vue b/pages/order/worker/components/layout.vue
new file mode 100644
index 0000000..846bfd9
--- /dev/null
+++ b/pages/order/worker/components/layout.vue
@@ -0,0 +1,182 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/order/worker/components/orderList.vue b/pages/order/worker/components/orderList.vue
new file mode 100644
index 0000000..ad1856f
--- /dev/null
+++ b/pages/order/worker/components/orderList.vue
@@ -0,0 +1,242 @@
+
+
+
+
+
+ {{ order.no }}
+
+ {{order.statusStr}}
+
+
+
+
+
+
+
+
+ {{order.nickname}}
+ 订单时间:{{order.createTimeStr}}
+ 服务内容:{{item.spuName}} {{item.properties.map((property) => property.valueName).join(' ')}}×{{item.count}}
+
+ 微信:{{order.weixin}}
+
+
+
+
+
+ 剩余时间:
+
+ 已结束
+
+
+
+
+ 暂未接单
+
+ 备注:{{order.userRemark}}
+ 取消原因:{{order.cancelReason}}
+
+
+ {{order.brokeragePrice}}
+ /钻
+
+
+
+
+
+
+ 查看详情
+ 取消接单
+ 取消订单
+ 再来一单
+ 评价
+ 继续支付
+ 开始接单
+ 结束服务
+ 邀请老板
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/order/worker/components/tabBox.vue b/pages/order/worker/components/tabBox.vue
new file mode 100644
index 0000000..db9711d
--- /dev/null
+++ b/pages/order/worker/components/tabBox.vue
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/order/worker/confirm.vue b/pages/order/worker/confirm.vue
new file mode 100644
index 0000000..bbd3809
--- /dev/null
+++ b/pages/order/worker/confirm.vue
@@ -0,0 +1,433 @@
+
+
+
+
+
+
+ 订单备注
+
+
+
+
+
+
+
+
+
+
+ 技能金额
+
+
+ ¥{{ fen2yuan(state.orderInfo.price.totalPrice) }}
+
+
+
+
+ 积分抵扣
+
+ {{ state.pointStatus ? '剩余积分' : '当前积分' }}
+
+
+ {{ state.pointStatus ? state.orderInfo.totalPoint - state.orderInfo.usePoint : (state.orderInfo.totalPoint || 0) }}
+
+
+
+
+
+
+
+ TA添加你的微信号
+
+
+
+
+
+
+ 优惠券
+
+
+ -¥{{ fen2yuan(state.orderInfo.price.couponPrice) }}
+
+
+ {{
+ state.couponInfo.length > 0 ? state.couponInfo.length + ' 张可用' : '暂无可用优惠券'
+ }}
+
+
+
+
+
+ 活动优惠
+
+
+
+ -¥{{ fen2yuan(state.orderInfo.price.discountPrice) }}
+
+
+
+
+
+ 会员优惠
+
+
+ -¥{{ fen2yuan(state.orderInfo.price.vipPrice) }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/order/worker/detail.vue b/pages/order/worker/detail.vue
new file mode 100644
index 0000000..26316bf
--- /dev/null
+++ b/pages/order/worker/detail.vue
@@ -0,0 +1,593 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ formatWorkerOrderStatus(state.orderInfo) }}
+
+
+ {{ formatWorkerOrderStatusDescription(state.orderInfo) }}
+
+
+
+
+
+
+
+ {{ state.orderInfo.receiverName }}
+
+ {{ state.orderInfo.receiverMobile }}
+
+
+ {{ state.orderInfo.receiverAreaName }} {{ state.orderInfo.receiverDetailAddress }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 订单编号:
+ {{ state.orderInfo.no }}
+
+
+
+
+ 下单时间:
+
+ {{ sheep.$helper.timeFormat(state.orderInfo.createTime, 'yyyy-mm-dd hh:MM:ss') }}
+
+
+
+ 支付时间:
+
+ {{ sheep.$helper.timeFormat(state.orderInfo.payTime, 'yyyy-mm-dd hh:MM:ss') }}
+
+
+
+ 支付方式:
+ {{ state.orderInfo.payChannelName || '-' }}
+
+
+
+
+
+
+
+ 订单总额
+
+ ¥{{ fen2yuan(state.orderInfo.totalPrice) }}
+
+
+
+ 优惠劵金额
+ -¥{{ fen2yuan(state.orderInfo.couponPrice) }}
+
+
+ 积分抵扣
+ -¥{{ fen2yuan(state.orderInfo.pointPrice) }}
+
+
+ 活动优惠
+ ¥{{ fen2yuan(state.orderInfo.discountPrice) }}
+
+
+ 会员优惠
+ -¥{{ fen2yuan(state.orderInfo.vipPrice) }}
+
+
+ 用户付款
+ ¥{{ fen2yuan(state.orderInfo.payPrice) }}
+
+
+ 佣金比例
+ {{state.orderInfo.brokeragePercent}}%
+
+
+ {{ state.orderInfo.payStatus ? '结算佣金' : '可得佣金' }}
+ ¥{{ fen2yuan(state.orderInfo.brokeragePrice) }}
+
+
+ 已退款
+ ¥{{ fen2yuan(state.orderInfo.refundPrice) }}
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/order/worker/list.vue b/pages/order/worker/list.vue
new file mode 100644
index 0000000..27d5ece
--- /dev/null
+++ b/pages/order/worker/list.vue
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/pay/index.vue b/pages/pay/index.vue
new file mode 100644
index 0000000..ef8bfe1
--- /dev/null
+++ b/pages/pay/index.vue
@@ -0,0 +1,295 @@
+
+
+
+
+
+
+
+
+
+ 选择支付方式
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/pay/point/index.vue b/pages/pay/point/index.vue
new file mode 100644
index 0000000..830ac1e
--- /dev/null
+++ b/pages/pay/point/index.vue
@@ -0,0 +1,308 @@
+
+
+
+
+
+
+
+
+
+ 选择支付方式
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/pay/recharge-log.vue b/pages/pay/recharge-log.vue
new file mode 100644
index 0000000..5dd3e36
--- /dev/null
+++ b/pages/pay/recharge-log.vue
@@ -0,0 +1,167 @@
+
+
+
+
+
+
+
+ 充值钻石
+
+ {{ fen2yuan(item.payPrice) }} 钻
+ (赠送 {{ fen2yuan(item.bonusPrice) }} 钻)
+
+
+
+ 支付状态
+
+ {{ item.refundStatus === 10 ? '已退款' : '已支付' }}
+
+
+
+ 充值渠道
+ {{ item.payChannelName }}
+
+
+ 充值单号
+ {{ item.payOrderChannelOrderNo }}
+
+
+ 充值时间
+
+ {{ sheep.$helper.timeFormat(item.payTime, 'yyyy-mm-dd hh:MM:ss') }}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/pay/recharge.vue b/pages/pay/recharge.vue
new file mode 100644
index 0000000..d63c640
--- /dev/null
+++ b/pages/pay/recharge.vue
@@ -0,0 +1,264 @@
+
+
+
+
+
+ 当前钻石(钻)
+ {{ fen2yuan(userWallet.balance) }}
+
+
+
+
+
+ 充值钻石
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/pay/result.vue b/pages/pay/result.vue
new file mode 100644
index 0000000..e4cc298
--- /dev/null
+++ b/pages/pay/result.vue
@@ -0,0 +1,318 @@
+
+
+
+
+
+
+
+
+ 支付成功
+ 支付失败
+ 该订单已关闭
+ 检测支付结果...
+
+ ¥{{ fen2yuan(state.orderInfo.price) }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 获取实时发货信息与订单状态
+ 立即订阅
+
+
+
+
+
+
+
+
+
diff --git a/pages/pay/reward/index.vue b/pages/pay/reward/index.vue
new file mode 100644
index 0000000..3541dda
--- /dev/null
+++ b/pages/pay/reward/index.vue
@@ -0,0 +1,308 @@
+
+
+
+
+
+
+
+
+
+ 选择支付方式
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/pay/vip/index.vue b/pages/pay/vip/index.vue
new file mode 100644
index 0000000..bd47e5b
--- /dev/null
+++ b/pages/pay/vip/index.vue
@@ -0,0 +1,308 @@
+
+
+
+
+
+
+
+
+
+ 选择支付方式
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/pay/worker/index.vue b/pages/pay/worker/index.vue
new file mode 100644
index 0000000..db34839
--- /dev/null
+++ b/pages/pay/worker/index.vue
@@ -0,0 +1,308 @@
+
+
+
+
+
+
+
+
+
+ 选择支付方式
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/pay/worker/result.vue b/pages/pay/worker/result.vue
new file mode 100644
index 0000000..bd3fa33
--- /dev/null
+++ b/pages/pay/worker/result.vue
@@ -0,0 +1,310 @@
+
+
+
+
+
+
+
+
+ 支付成功
+ 支付失败
+ 该订单已关闭
+ 检测支付结果...
+
+ ¥{{ fen2yuan(state.orderInfo.price) }}
+
+
+
+
+
+
+
+
+
+
+
+
+ 获取实时接单信息与订单状态
+ 立即订阅
+
+
+
+
+
+
+
+
+
diff --git a/pages/point/recharge-log.vue b/pages/point/recharge-log.vue
new file mode 100644
index 0000000..3e44fb6
--- /dev/null
+++ b/pages/point/recharge-log.vue
@@ -0,0 +1,167 @@
+
+
+
+
+
+
+
+ 充值积分
+
+ {{ item.payPrice }} 积分
+ (赠送 {{ item.bonusPrice }} 积分)
+
+
+
+ 支付状态
+
+ {{ item.refundStatus === 10 ? '已退款' : '已支付' }}
+
+
+
+ 充值渠道
+ {{ item.payChannelName }}
+
+
+ 充值单号
+ {{ item.payOrderChannelOrderNo }}
+
+
+ 充值时间
+
+ {{ sheep.$helper.timeFormat(item.payTime, 'yyyy-mm-dd hh:MM:ss') }}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/point/recharge.vue b/pages/point/recharge.vue
new file mode 100644
index 0000000..f919e83
--- /dev/null
+++ b/pages/point/recharge.vue
@@ -0,0 +1,264 @@
+
+
+
+
+
+ 当前积分(个)
+ {{ userInfo.point }}
+
+
+
+
+
+ 充值积分
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/point/result.vue b/pages/point/result.vue
new file mode 100644
index 0000000..d188e52
--- /dev/null
+++ b/pages/point/result.vue
@@ -0,0 +1,318 @@
+
+
+
+
+
+
+
+
+ 支付成功
+ 支付失败
+ 该订单已关闭
+ 检测支付结果...
+
+ ¥{{ fen2yuan(state.orderInfo.price) }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 获取实时发货信息与订单状态
+ 立即订阅
+
+
+
+
+
+
+
+
+
diff --git a/pages/public/error.vue b/pages/public/error.vue
new file mode 100644
index 0000000..3c9097d
--- /dev/null
+++ b/pages/public/error.vue
@@ -0,0 +1,60 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/public/faq.vue b/pages/public/faq.vue
new file mode 100644
index 0000000..ebfeaf8
--- /dev/null
+++ b/pages/public/faq.vue
@@ -0,0 +1,118 @@
+
+
+
+
+
+
+
+
+
+ {{ item.content }}
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/public/richtext.vue b/pages/public/richtext.vue
new file mode 100644
index 0000000..e4a0921
--- /dev/null
+++ b/pages/public/richtext.vue
@@ -0,0 +1,54 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/public/setting.vue b/pages/public/setting.vue
new file mode 100644
index 0000000..6a08ff9
--- /dev/null
+++ b/pages/public/setting.vue
@@ -0,0 +1,236 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/public/webview.vue b/pages/public/webview.vue
new file mode 100644
index 0000000..1327295
--- /dev/null
+++ b/pages/public/webview.vue
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/reward/components/layout.vue b/pages/reward/components/layout.vue
new file mode 100644
index 0000000..c5cab70
--- /dev/null
+++ b/pages/reward/components/layout.vue
@@ -0,0 +1,84 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/reward/components/orderList.vue b/pages/reward/components/orderList.vue
new file mode 100644
index 0000000..126279a
--- /dev/null
+++ b/pages/reward/components/orderList.vue
@@ -0,0 +1,169 @@
+
+
+
+
+
+
+
+
+
+ {{order.nickname}}
+ 礼物名称:{{order.gift}}×{{order.count}}
+ 到账金额:{{order.money}}
+ 心动留言:{{order.msg}}
+
+ 微信:{{order.weixin}}
+
+
+
+
+ 订单时间:{{order.createTimeStr}}
+
+
+ {{order.payMoney}}
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/reward/list.vue b/pages/reward/list.vue
new file mode 100644
index 0000000..abc3de3
--- /dev/null
+++ b/pages/reward/list.vue
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/tabbar/components/home/actionSheet.vue b/pages/tabbar/components/home/actionSheet.vue
new file mode 100644
index 0000000..ba318d4
--- /dev/null
+++ b/pages/tabbar/components/home/actionSheet.vue
@@ -0,0 +1,220 @@
+
+
+
+
+ {{tips}}
+
+
+
+
+ {{item.text}}
+
+
+
+ 取消
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/tabbar/components/home/cardList.vue b/pages/tabbar/components/home/cardList.vue
new file mode 100644
index 0000000..577bdc6
--- /dev/null
+++ b/pages/tabbar/components/home/cardList.vue
@@ -0,0 +1,448 @@
+
+
+
+
+
+ 获取未读消息提醒
+ 立即订阅
+
+
+
+
+
+
+
+
+
+
+ {{item.nickname}}
+
+
+ {{item.age}}
+
+
+
+ {{item.age}}
+
+
+
+
+
+ {{item.city}}
+
+ 未知
+
+
+
+
+ 已注册{{item.day}}天
+ 可交换名片
+
+
+
+
+
+
+
+
+
+
+
+ 密聊
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/tabbar/components/home/categoryCard.vue b/pages/tabbar/components/home/categoryCard.vue
new file mode 100644
index 0000000..cf0e7af
--- /dev/null
+++ b/pages/tabbar/components/home/categoryCard.vue
@@ -0,0 +1,181 @@
+
+
+
+
+
+
+
+
+ 技能分类
+
+
+
+
+
+
+
+
+
+
+
+ {{item.name}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/tabbar/components/home/categorySheet.vue b/pages/tabbar/components/home/categorySheet.vue
new file mode 100644
index 0000000..8b944b3
--- /dev/null
+++ b/pages/tabbar/components/home/categorySheet.vue
@@ -0,0 +1,67 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/tabbar/components/home/dazi.vue b/pages/tabbar/components/home/dazi.vue
new file mode 100644
index 0000000..ddfda62
--- /dev/null
+++ b/pages/tabbar/components/home/dazi.vue
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/tabbar/components/home/friend.vue b/pages/tabbar/components/home/friend.vue
new file mode 100644
index 0000000..4764e54
--- /dev/null
+++ b/pages/tabbar/components/home/friend.vue
@@ -0,0 +1,55 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/tabbar/components/home/friend/imgBox.vue b/pages/tabbar/components/home/friend/imgBox.vue
new file mode 100644
index 0000000..e2076b5
--- /dev/null
+++ b/pages/tabbar/components/home/friend/imgBox.vue
@@ -0,0 +1,86 @@
+
+
+
+
+
+
+
+ +{{imgList.length-3}}
+
+
+
+
+
+ 暂未上传相册
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/tabbar/components/home/friend/rankBox.vue b/pages/tabbar/components/home/friend/rankBox.vue
new file mode 100644
index 0000000..d0cf316
--- /dev/null
+++ b/pages/tabbar/components/home/friend/rankBox.vue
@@ -0,0 +1,246 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ {{list[1].nickname}}
+ ???
+
+
+
+
+
+
+
+ {{list[0].nickname}}
+ ???
+
+
+
+
+
+
+
+ {{list[2].nickname}}
+ ???
+
+
+ 更新时间: {{updateTime}}
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/tabbar/components/home/friend/stickyBox.vue b/pages/tabbar/components/home/friend/stickyBox.vue
new file mode 100644
index 0000000..9b05d5d
--- /dev/null
+++ b/pages/tabbar/components/home/friend/stickyBox.vue
@@ -0,0 +1,109 @@
+
+
+
+
+
+
+
+ 更多用户
+
+
+
+ 筛选
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/tabbar/components/home/friend/topBox.vue b/pages/tabbar/components/home/friend/topBox.vue
new file mode 100644
index 0000000..2237f41
--- /dev/null
+++ b/pages/tabbar/components/home/friend/topBox.vue
@@ -0,0 +1,260 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/tabbar/components/home/friend/userCard.vue b/pages/tabbar/components/home/friend/userCard.vue
new file mode 100644
index 0000000..803ce69
--- /dev/null
+++ b/pages/tabbar/components/home/friend/userCard.vue
@@ -0,0 +1,210 @@
+
+
+
+
+
+
+
+ 新人推荐
+
+
+
+
+
+
+
+
+ {{item.nickname}}
+
+
+
+
+
+
+
+
+
+
+ 置顶用户
+
+
+
+
+
+
+
+
+
+
+
+
+ {{item.nickname}}
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/tabbar/components/home/navBar - 副本.vue b/pages/tabbar/components/home/navBar - 副本.vue
new file mode 100644
index 0000000..3bbe7b9
--- /dev/null
+++ b/pages/tabbar/components/home/navBar - 副本.vue
@@ -0,0 +1,78 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/tabbar/components/home/navBar.vue b/pages/tabbar/components/home/navBar.vue
new file mode 100644
index 0000000..e4fd304
--- /dev/null
+++ b/pages/tabbar/components/home/navBar.vue
@@ -0,0 +1,106 @@
+
+
+
+
+
+
+
+
+
+ {{item.name}}
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/tabbar/components/home/noticeBar.vue b/pages/tabbar/components/home/noticeBar.vue
new file mode 100644
index 0000000..9cc4e9b
--- /dev/null
+++ b/pages/tabbar/components/home/noticeBar.vue
@@ -0,0 +1,112 @@
+
+
+
+
+ 最新消息
+
+
+
+ {{item}}
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/tabbar/components/home/peiwan.vue b/pages/tabbar/components/home/peiwan.vue
new file mode 100644
index 0000000..3cf0030
--- /dev/null
+++ b/pages/tabbar/components/home/peiwan.vue
@@ -0,0 +1,58 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/tabbar/components/home/rankBox.vue b/pages/tabbar/components/home/rankBox.vue
new file mode 100644
index 0000000..600faa8
--- /dev/null
+++ b/pages/tabbar/components/home/rankBox.vue
@@ -0,0 +1,198 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ {{list[1].nickname}}
+ ???
+
+
+
+
+
+
+
+ {{list[0].nickname}}
+ ???
+
+
+
+
+
+
+
+ {{list[2].nickname}}
+ ???
+
+
+ 更新时间: {{updateTime}}
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/tabbar/components/home/sexSheet.vue b/pages/tabbar/components/home/sexSheet.vue
new file mode 100644
index 0000000..87b2d28
--- /dev/null
+++ b/pages/tabbar/components/home/sexSheet.vue
@@ -0,0 +1,61 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/tabbar/components/home/stickyBox.vue b/pages/tabbar/components/home/stickyBox.vue
new file mode 100644
index 0000000..79d21f1
--- /dev/null
+++ b/pages/tabbar/components/home/stickyBox.vue
@@ -0,0 +1,118 @@
+
+
+
+
+
+
+
+ 更多达人
+
+
+
+ {{searchTabs.categoryLabel}}
+
+
+
+ {{searchTabs.sexLabel}}
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/tabbar/components/home/topBox.vue b/pages/tabbar/components/home/topBox.vue
new file mode 100644
index 0000000..8f6d628
--- /dev/null
+++ b/pages/tabbar/components/home/topBox.vue
@@ -0,0 +1,183 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 随机下单
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/tabbar/components/home/userCard.vue b/pages/tabbar/components/home/userCard.vue
new file mode 100644
index 0000000..bd6d0ab
--- /dev/null
+++ b/pages/tabbar/components/home/userCard.vue
@@ -0,0 +1,153 @@
+
+
+
+
+
+
+
+ 新人推荐
+
+
+
+
+
+
+
+
+ {{item.nickname}}
+
+
+
+
+
+
+
+
+
+
+ 人气达人
+
+
+
+
+
+
+
+
+
+ {{item.nickname}}
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/tabbar/components/home/userList.vue b/pages/tabbar/components/home/userList.vue
new file mode 100644
index 0000000..18019d6
--- /dev/null
+++ b/pages/tabbar/components/home/userList.vue
@@ -0,0 +1,379 @@
+
+
+
+
+
+
+
+
+
+
+
+ {{item.nickname}}
+
+
+ {{item.age}}
+
+
+
+ {{item.age}}
+
+
+
+
+
+
+
+
+
+
+
+ {{item.clerkLevel.name}}
+
+
+
+
+
+ 在线
+
+
+
+ 离线
+
+
+
+
+
+ {{categoryName}}
+
+
+
+
+ {{item.intro}}
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/tabbar/components/home/voicePlay.vue b/pages/tabbar/components/home/voicePlay.vue
new file mode 100644
index 0000000..fb95eec
--- /dev/null
+++ b/pages/tabbar/components/home/voicePlay.vue
@@ -0,0 +1,184 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{sec}}"
+
+
+
+
diff --git a/pages/tabbar/components/member/layout.vue b/pages/tabbar/components/member/layout.vue
new file mode 100644
index 0000000..d3bcce3
--- /dev/null
+++ b/pages/tabbar/components/member/layout.vue
@@ -0,0 +1,233 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{item}}
+
+
+
+
+
+
+
+
+
diff --git a/pages/tabbar/components/member/navBar.vue b/pages/tabbar/components/member/navBar.vue
new file mode 100644
index 0000000..dafb8da
--- /dev/null
+++ b/pages/tabbar/components/member/navBar.vue
@@ -0,0 +1,94 @@
+
+
+
+
+
+
+
+
+
+
+
+ {{title}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/tabbar/components/member/viewItem.vue b/pages/tabbar/components/member/viewItem.vue
new file mode 100644
index 0000000..87c81f5
--- /dev/null
+++ b/pages/tabbar/components/member/viewItem.vue
@@ -0,0 +1,216 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ {{item.nickname}}
+
+
+
+
+
+
+
+
+ 19:39
+
+
+
+ [已读]
+ 希望打个赏哦
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/tabbar/components/message/friend.vue b/pages/tabbar/components/message/friend.vue
new file mode 100644
index 0000000..1337205
--- /dev/null
+++ b/pages/tabbar/components/message/friend.vue
@@ -0,0 +1,208 @@
+
+
+
+
+
+
+
+
+
+
+ {{item}}
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/tabbar/components/message/gameBox.vue b/pages/tabbar/components/message/gameBox.vue
new file mode 100644
index 0000000..a9e02d1
--- /dev/null
+++ b/pages/tabbar/components/message/gameBox.vue
@@ -0,0 +1,149 @@
+
+
+
+
+
+ 服务类型
+
+
+ {{option.name}}
+
+
+
+
+
+
+ 选项
+
+
+ {{option.name}}
+
+
+
+
+
+
+ 选项
+
+
+ {{option.name}}
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/tabbar/components/message/navBar.vue b/pages/tabbar/components/message/navBar.vue
new file mode 100644
index 0000000..85e02b3
--- /dev/null
+++ b/pages/tabbar/components/message/navBar.vue
@@ -0,0 +1,106 @@
+
+
+
+
+
+
+
+
+
+ {{item.name}}
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/tabbar/components/message/peiwan.vue b/pages/tabbar/components/message/peiwan.vue
new file mode 100644
index 0000000..0f6c54c
--- /dev/null
+++ b/pages/tabbar/components/message/peiwan.vue
@@ -0,0 +1,346 @@
+
+
+
+
+
+ 店员性别
+
+
+
+
+
+
+
+
+
+
+
+ 小姐姐
+
+
+
+
+
+
+
+
+
+
+ 小哥哥
+
+
+
+
+
+
+ 店员等级
+
+
+
+ {{option.name}}
+
+
+
+
+
+
+
+ 购买数量
+
+
+
+
+
+
+
+
+
+ 排除下单过的店员
+
+
+
+
+
+
+
+
+
+
+
+ 总价:
+ {{ fen2yuan(game.price*form.num) }}
+ 钻石
+
+
+ 立即下单
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/tabbar/components/message/viewItem.vue b/pages/tabbar/components/message/viewItem.vue
new file mode 100644
index 0000000..ce8bd94
--- /dev/null
+++ b/pages/tabbar/components/message/viewItem.vue
@@ -0,0 +1,265 @@
+
+
+
+
+
+
+
+
+
+
+
+ 通知助手
+
+ 前天
+
+
+
+ 希望打个赏哦
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{item.nickname}}
+
+
+
+
+
+
+
+
+ {{item.time}}
+
+
+
+ 已读
+ {{item.lastMessageContent}}
+ [语音消息]
+ [图片消息]
+
+
+
+
+
+
+ {{item.unreadMessageCount}}
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/tabbar/components/mine/bgBox.vue b/pages/tabbar/components/mine/bgBox.vue
new file mode 100644
index 0000000..acf464e
--- /dev/null
+++ b/pages/tabbar/components/mine/bgBox.vue
@@ -0,0 +1,62 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/tabbar/components/mine/layout.vue b/pages/tabbar/components/mine/layout.vue
new file mode 100644
index 0000000..80b8a00
--- /dev/null
+++ b/pages/tabbar/components/mine/layout.vue
@@ -0,0 +1,96 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/tabbar/components/mine/mainBox.vue b/pages/tabbar/components/mine/mainBox.vue
new file mode 100644
index 0000000..d91404c
--- /dev/null
+++ b/pages/tabbar/components/mine/mainBox.vue
@@ -0,0 +1,502 @@
+
+
+
+
+
+
+
+ {{ userInfo?.nickname || nickname }}
+
+
+
+ ID: {{ userInfo?.id || 88888 }}
+
+
+
+
+
+ 钻石
+
+
+
+
+ 积分
+
+
+
+ 动态
+
+
+ 礼物
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 我的订单
+
+
+
+ 待付款
+ {{numData.orderCount['unpaidCount']}}
+
+
+
+
+ 待服务
+
+
+
+
+ 服务中
+
+
+
+
+ 已完成
+
+
+
+
+
+ 接单中心
+
+
+
+
+ 接单中心
+
+
+
+
+ 抢单中心
+
+
+
+
+ 达人资料
+
+
+
+
+ 打赏记录
+
+
+
+
+
+
+
+
+ 常用工具
+
+
+
+
+
+
+ 达人申请
+
+
+
+
+ 分销中心
+
+
+
+
+ 签到有礼
+
+
+
+
+ 收藏达人
+
+
+
+
+ 优惠券
+
+
+
+
+ 购买授权
+
+
+
+
+ 申请提现
+
+
+
+
+
+
+
+
+
+
+ 尔加科技版权所有
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/tabbar/components/mine/navBar.vue b/pages/tabbar/components/mine/navBar.vue
new file mode 100644
index 0000000..93c98a2
--- /dev/null
+++ b/pages/tabbar/components/mine/navBar.vue
@@ -0,0 +1,108 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ {{userInfo.nickname}}
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/tabbar/components/mine/vipCard.vue b/pages/tabbar/components/mine/vipCard.vue
new file mode 100644
index 0000000..4a17861
--- /dev/null
+++ b/pages/tabbar/components/mine/vipCard.vue
@@ -0,0 +1,109 @@
+
+
+
+
+ VIP会员中心
+
+
+
+
+ 查看特权
+
+
+
+ 立即开通
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/tabbar/components/trend/clerk-popup.vue b/pages/tabbar/components/trend/clerk-popup.vue
new file mode 100644
index 0000000..41f15a3
--- /dev/null
+++ b/pages/tabbar/components/trend/clerk-popup.vue
@@ -0,0 +1,132 @@
+
+
+
+
+ 切换店员
+
+
+
+
+
+
+
+
+
+ {{item.nickname}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/tabbar/components/trend/fb-popup.vue b/pages/tabbar/components/trend/fb-popup.vue
new file mode 100644
index 0000000..20640c4
--- /dev/null
+++ b/pages/tabbar/components/trend/fb-popup.vue
@@ -0,0 +1,313 @@
+
+
+
+
+
+
+
+
+
+ 发布动态
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 立即发布
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/tabbar/components/trend/formCity.vue b/pages/tabbar/components/trend/formCity.vue
new file mode 100644
index 0000000..58d3a0f
--- /dev/null
+++ b/pages/tabbar/components/trend/formCity.vue
@@ -0,0 +1,55 @@
+
+
+
+ 关联店员
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/tabbar/components/trend/formImage.vue b/pages/tabbar/components/trend/formImage.vue
new file mode 100644
index 0000000..ebe341f
--- /dev/null
+++ b/pages/tabbar/components/trend/formImage.vue
@@ -0,0 +1,68 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/tabbar/components/trend/formVideo.vue b/pages/tabbar/components/trend/formVideo.vue
new file mode 100644
index 0000000..a74af80
--- /dev/null
+++ b/pages/tabbar/components/trend/formVideo.vue
@@ -0,0 +1,71 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/tabbar/components/trend/formVoice.vue b/pages/tabbar/components/trend/formVoice.vue
new file mode 100644
index 0000000..3028da4
--- /dev/null
+++ b/pages/tabbar/components/trend/formVoice.vue
@@ -0,0 +1,256 @@
+
+
+
+ 录音
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 停止播放
+ 播放录音
+
+
+
+
+
+
+ 重录
+
+
+
+
+
+
+
+
+ 停止播放
+ 播放录音
+
+
+
+
+
+ 上传录音文件
+
+
+
+ 重录
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/tabbar/components/trend/imgBox.vue b/pages/tabbar/components/trend/imgBox.vue
new file mode 100644
index 0000000..060ed7c
--- /dev/null
+++ b/pages/tabbar/components/trend/imgBox.vue
@@ -0,0 +1,149 @@
+
+
+
+
+
+
+
+ 观看视频解锁
+
+
+
+
+
+
+
+
+
+
+
+
+ +{{imgList.length-2}}
+
+
+
+
+
+ 观看视频解锁
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/tabbar/components/trend/layout.vue b/pages/tabbar/components/trend/layout.vue
new file mode 100644
index 0000000..ee38589
--- /dev/null
+++ b/pages/tabbar/components/trend/layout.vue
@@ -0,0 +1,179 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 获取实时动态提醒
+ 立即订阅
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/tabbar/components/trend/navBar.vue b/pages/tabbar/components/trend/navBar.vue
new file mode 100644
index 0000000..5fbdf9c
--- /dev/null
+++ b/pages/tabbar/components/trend/navBar.vue
@@ -0,0 +1,131 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{item.name}}
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/tabbar/components/trend/postList.vue b/pages/tabbar/components/trend/postList.vue
new file mode 100644
index 0000000..1b5fe42
--- /dev/null
+++ b/pages/tabbar/components/trend/postList.vue
@@ -0,0 +1,512 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{item.city}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/tabbar/components/trend/userCard.vue b/pages/tabbar/components/trend/userCard.vue
new file mode 100644
index 0000000..d8f58e3
--- /dev/null
+++ b/pages/tabbar/components/trend/userCard.vue
@@ -0,0 +1,190 @@
+
+
+
+
+
+
+
+ 置顶用户
+
+
+
+
+
+
+
+
+
+
+
+
+ {{item.nickname}}
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/tabbar/components/trend/videoBox.vue b/pages/tabbar/components/trend/videoBox.vue
new file mode 100644
index 0000000..10f336d
--- /dev/null
+++ b/pages/tabbar/components/trend/videoBox.vue
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/tabbar/components/trend/voicePlay.vue b/pages/tabbar/components/trend/voicePlay.vue
new file mode 100644
index 0000000..6720241
--- /dev/null
+++ b/pages/tabbar/components/trend/voicePlay.vue
@@ -0,0 +1,184 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{sec}}"
+
+
+
+
diff --git a/pages/tabbar/home.vue b/pages/tabbar/home.vue
new file mode 100644
index 0000000..f237486
--- /dev/null
+++ b/pages/tabbar/home.vue
@@ -0,0 +1,244 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/tabbar/index.vue b/pages/tabbar/index.vue
new file mode 100644
index 0000000..73b8995
--- /dev/null
+++ b/pages/tabbar/index.vue
@@ -0,0 +1,395 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{gift.username}}
+ 赠送
+ {{gift.nickname}}
+ {{gift.name}}
+ x{{gift.count}}
+
+
+ 关闭
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/tabbar/message.vue b/pages/tabbar/message.vue
new file mode 100644
index 0000000..0a63119
--- /dev/null
+++ b/pages/tabbar/message.vue
@@ -0,0 +1,147 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/tabbar/mine.vue b/pages/tabbar/mine.vue
new file mode 100644
index 0000000..ec77f11
--- /dev/null
+++ b/pages/tabbar/mine.vue
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/tabbar/social.vue b/pages/tabbar/social.vue
new file mode 100644
index 0000000..69d947a
--- /dev/null
+++ b/pages/tabbar/social.vue
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/tabbar/trend.vue b/pages/tabbar/trend.vue
new file mode 100644
index 0000000..595bb2a
--- /dev/null
+++ b/pages/tabbar/trend.vue
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/trend/city/components/orderList.vue b/pages/trend/city/components/orderList.vue
new file mode 100644
index 0000000..23dec4f
--- /dev/null
+++ b/pages/trend/city/components/orderList.vue
@@ -0,0 +1,510 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{item.city}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/trend/city/list.vue b/pages/trend/city/list.vue
new file mode 100644
index 0000000..93009b7
--- /dev/null
+++ b/pages/trend/city/list.vue
@@ -0,0 +1,159 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/trend/detail/components/card.vue b/pages/trend/detail/components/card.vue
new file mode 100644
index 0000000..9bff436
--- /dev/null
+++ b/pages/trend/detail/components/card.vue
@@ -0,0 +1,510 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{item.city}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/trend/detail/index.vue b/pages/trend/detail/index.vue
new file mode 100644
index 0000000..c8237bb
--- /dev/null
+++ b/pages/trend/detail/index.vue
@@ -0,0 +1,76 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/trend/my/components/orderList.vue b/pages/trend/my/components/orderList.vue
new file mode 100644
index 0000000..d0e266b
--- /dev/null
+++ b/pages/trend/my/components/orderList.vue
@@ -0,0 +1,500 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{item.city}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/trend/my/list.vue b/pages/trend/my/list.vue
new file mode 100644
index 0000000..417b0b4
--- /dev/null
+++ b/pages/trend/my/list.vue
@@ -0,0 +1,143 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/user/address/edit.vue b/pages/user/address/edit.vue
new file mode 100644
index 0000000..b88ee07
--- /dev/null
+++ b/pages/user/address/edit.vue
@@ -0,0 +1,305 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 设为默认地址
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/user/address/list.vue b/pages/user/address/list.vue
new file mode 100644
index 0000000..58b6214
--- /dev/null
+++ b/pages/user/address/list.vue
@@ -0,0 +1,165 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/user/detail/components/detail-navbar.vue b/pages/user/detail/components/detail-navbar.vue
new file mode 100644
index 0000000..1723c51
--- /dev/null
+++ b/pages/user/detail/components/detail-navbar.vue
@@ -0,0 +1,221 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.label }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/user/detail/components/giftList.vue b/pages/user/detail/components/giftList.vue
new file mode 100644
index 0000000..63eefff
--- /dev/null
+++ b/pages/user/detail/components/giftList.vue
@@ -0,0 +1,316 @@
+
+
+
+
+ 选择礼物
+
+
+ 取消
+
+
+
+
+
+
+
+ 特效
+ ·{{item.tag}}
+
+
+ {{item.tag}}
+
+
+ {{item.name}}
+ {{ fen2yuan(item.money) }} 钻石
+
+
+
+
+
+
+
+
+
+
+ {{gift.name}}
+ {{ fen2yuan(gift.money) }} 钻石
+
+ 取消
+ 确定
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/user/detail/components/giftPopup.vue b/pages/user/detail/components/giftPopup.vue
new file mode 100644
index 0000000..8abb4d6
--- /dev/null
+++ b/pages/user/detail/components/giftPopup.vue
@@ -0,0 +1,445 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 赠送类型
+
+
+
+ 赠礼
+
+
+
+
+
+
+ 打赏金额
+
+
+
+
+
+
+
+
+ 赠送礼物
+
+
+ 已选【{{gift.name}}】
+ 点击选择礼物
+
+
+
+
+
+
+ 礼物数量
+
+
+
+
+
+
+
+
+
+ 心动留言
+
+
+
+
+
+
+
+
+ 您的微信号
+
+
+
+
+
+
+
+
+
+
+
+
+ 立即赠送
+
+
+
+
+
+ 总价:
+ {{ fen2yuan(gift.money*form.count) }}
+ 钻石
+
+
+ 立即赠送
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/user/detail/components/layout.vue b/pages/user/detail/components/layout.vue
new file mode 100644
index 0000000..0e1764e
--- /dev/null
+++ b/pages/user/detail/components/layout.vue
@@ -0,0 +1,286 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 赠礼
+ 密聊
+
+
+ 密聊
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/user/detail/components/navBar.vue b/pages/user/detail/components/navBar.vue
new file mode 100644
index 0000000..42ca85b
--- /dev/null
+++ b/pages/user/detail/components/navBar.vue
@@ -0,0 +1,89 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/user/detail/components/photoBox.vue b/pages/user/detail/components/photoBox.vue
new file mode 100644
index 0000000..7d575ed
--- /dev/null
+++ b/pages/user/detail/components/photoBox.vue
@@ -0,0 +1,50 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/user/detail/components/postList.vue b/pages/user/detail/components/postList.vue
new file mode 100644
index 0000000..5080775
--- /dev/null
+++ b/pages/user/detail/components/postList.vue
@@ -0,0 +1,362 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{item.city}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/user/detail/components/starList.vue b/pages/user/detail/components/starList.vue
new file mode 100644
index 0000000..32ff751
--- /dev/null
+++ b/pages/user/detail/components/starList.vue
@@ -0,0 +1,310 @@
+
+
+
+
+ 礼物墙
+ (已点亮:{{starNum}}/{{total}})
+
+
+
+
+
+
+
+ 特效
+ ·{{item.tag}}
+
+
+ {{item.tag}}
+
+
+ {{item.name}}
+ x {{item.playNum}}
+ 点亮
+ 赠送
+ 已下架
+
+
+
+
+
+
+
+
+
+
+ {{gift.name}}
+ {{ fen2yuan(gift.money) }} 钻石
+
+ 取消
+ 点亮
+ 赠送
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/user/detail/components/stickyBox.vue b/pages/user/detail/components/stickyBox.vue
new file mode 100644
index 0000000..7739659
--- /dev/null
+++ b/pages/user/detail/components/stickyBox.vue
@@ -0,0 +1,59 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/user/detail/components/userBox.vue b/pages/user/detail/components/userBox.vue
new file mode 100644
index 0000000..3c8e75c
--- /dev/null
+++ b/pages/user/detail/components/userBox.vue
@@ -0,0 +1,308 @@
+
+
+
+
+
+
+
+
+
+
+ {{clerk.nickname}}
+
+
+ L1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{clerk.age}}
+ {{clerk.city}}
+
+ {{clerk.intro}}
+
+
+ 已注册{{clerk.day}}天
+ 可交换名片
+
+
+
+ {{categoryName}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/user/detail/index.vue b/pages/user/detail/index.vue
new file mode 100644
index 0000000..440f970
--- /dev/null
+++ b/pages/user/detail/index.vue
@@ -0,0 +1,61 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/user/goods-collect.vue b/pages/user/goods-collect.vue
new file mode 100644
index 0000000..af5e64a
--- /dev/null
+++ b/pages/user/goods-collect.vue
@@ -0,0 +1,233 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/user/goods-log.vue b/pages/user/goods-log.vue
new file mode 100644
index 0000000..b52efe3
--- /dev/null
+++ b/pages/user/goods-log.vue
@@ -0,0 +1,308 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/user/goods_details_store/index.vue b/pages/user/goods_details_store/index.vue
new file mode 100644
index 0000000..07b6850
--- /dev/null
+++ b/pages/user/goods_details_store/index.vue
@@ -0,0 +1,275 @@
+
+
+
+
+
+
+
+
+ {{ item.name }}
+
+ {{ item.areaName }}{{ ', ' + item.detailAddress }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 距离{{ item.distance.toFixed(2) }}千米
+ 查看地图
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/user/info.vue b/pages/user/info.vue
new file mode 100644
index 0000000..3699790
--- /dev/null
+++ b/pages/user/info.vue
@@ -0,0 +1,475 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/user/vip.vue b/pages/user/vip.vue
new file mode 100644
index 0000000..ca0b0ba
--- /dev/null
+++ b/pages/user/vip.vue
@@ -0,0 +1,382 @@
+
+
+
+
+ VIP尊享会员
+
+
+ VIP会员({{showDayTime(userInfo.vipEndTime)}}到期)
+ 暂未激活VIP会员
+
+
+
+
+
+ {{item.num}}{{item.unit}}
+ ¥{{item.month}}/{{item.tip}}
+ ¥{{item.pay}}
+ 新人优惠
+
+
+
+
+ VIP特权
+
+
+
+
+
+
+
+ 每天3次发布动态无广告
+ 每天免费发布3次无广告增加曝光
+
+
+
+
+
+
+
+ 每天5次交换名片
+ 每天可以免费交换5次名片
+
+
+
+
+
+
+
+ 打招呼聊天免费
+ 打招呼聊天发送消息无限制
+
+
+
+
+
+
+
+ 每天3次首页置顶
+ 每天可以免费置顶3次
+
+
+
+
+
+
+
+ 可查看同城的用户
+ 离得近奔现的概率更高
+
+
+
+
+ 已开通
+
+
+
+ ¥{{pay.pay}} 立即购买
+ 每天不到¥{{pay.day}}
+
+
+
+
+
+
+
+ 已开通
+
+
+
+ ¥{{pay.pay}} 购买会员
+ 每天不到¥{{pay.day}}
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/user/wallet/money.vue b/pages/user/wallet/money.vue
new file mode 100644
index 0000000..b6c9d0d
--- /dev/null
+++ b/pages/user/wallet/money.vue
@@ -0,0 +1,379 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 总收入¥{{ fen2yuan(state.summary.totalIncome) }}
+ 总支出¥{{ fen2yuan(state.summary.totalExpense) }}
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.title }}
+
+
+ +{{ fen2yuan(item.price) }}
+ {{ fen2yuan(item.price) }}
+
+
+
+ {{ sheep.$helper.timeFormat(state.createTime, 'yyyy-mm-dd hh:MM:ss') }}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/user/wallet/score.vue b/pages/user/wallet/score.vue
new file mode 100644
index 0000000..f49866e
--- /dev/null
+++ b/pages/user/wallet/score.vue
@@ -0,0 +1,323 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.title }}{{ item.description ? ' - ' + item.description : '' }}
+ {{
+ sheep.$helper.timeFormat(item.createTime, 'yyyy-mm-dd hh:MM:ss')
+ }}
+
+ +{{ item.point }}
+ {{ item.point }}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/worker/blind/components/gameBox.vue b/pages/worker/blind/components/gameBox.vue
new file mode 100644
index 0000000..4c4687b
--- /dev/null
+++ b/pages/worker/blind/components/gameBox.vue
@@ -0,0 +1,149 @@
+
+
+
+
+
+ 技能类型
+
+
+ {{option.name}}
+
+
+
+
+
+
+ 选项
+
+
+ {{option.name}}
+
+
+
+
+
+
+ 选项
+
+
+ {{option.name}}
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/worker/blind/components/layout.vue b/pages/worker/blind/components/layout.vue
new file mode 100644
index 0000000..022d227
--- /dev/null
+++ b/pages/worker/blind/components/layout.vue
@@ -0,0 +1,357 @@
+
+
+
+
+
+
+
+
+ 达人性别
+
+
+
+
+
+
+
+
+
+
+
+ 小姐姐
+
+
+
+
+
+
+
+
+
+
+ 小哥哥
+
+
+
+
+
+
+ 达人等级
+
+
+
+ {{option.name}}
+
+
+
+
+
+
+
+ 购买数量
+
+
+
+
+
+
+
+
+
+ 排除下单过的达人
+
+
+
+
+
+
+
+
+
+
+
+ 总价:
+ {{ fen2yuan(game.price*form.num) }}
+ 钻石
+
+
+ 立即下单
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/worker/blind/index.vue b/pages/worker/blind/index.vue
new file mode 100644
index 0000000..f4756f4
--- /dev/null
+++ b/pages/worker/blind/index.vue
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/worker/levelList/components/layout.vue b/pages/worker/levelList/components/layout.vue
new file mode 100644
index 0000000..5823785
--- /dev/null
+++ b/pages/worker/levelList/components/layout.vue
@@ -0,0 +1,109 @@
+
+
+
+
+
+
+
+
+ 当前等级:{{clerkLevel}}
+
+
+
+
+ 保存配置
+
+
+
+
+
+
+
+
diff --git a/pages/worker/levelList/components/levelList.vue b/pages/worker/levelList/components/levelList.vue
new file mode 100644
index 0000000..e26a464
--- /dev/null
+++ b/pages/worker/levelList/components/levelList.vue
@@ -0,0 +1,105 @@
+
+
+
+
+ 技能列表
+ 开关
+
+
+
+
+ {{tb.name}}
+
+
+
+
+
+ {{tb2.name}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{tb2.name}}
+
+
+
+ {{tb3.name}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/worker/levelList/components/table-bd.vue b/pages/worker/levelList/components/table-bd.vue
new file mode 100644
index 0000000..8819269
--- /dev/null
+++ b/pages/worker/levelList/components/table-bd.vue
@@ -0,0 +1,100 @@
+
+
+
+
+
+
+
+
+
diff --git a/pages/worker/levelList/components/table-td.vue b/pages/worker/levelList/components/table-td.vue
new file mode 100644
index 0000000..13c6ea3
--- /dev/null
+++ b/pages/worker/levelList/components/table-td.vue
@@ -0,0 +1,305 @@
+
+
+
+
+
+
+
+
+
diff --git a/pages/worker/levelList/components/table-tr.vue b/pages/worker/levelList/components/table-tr.vue
new file mode 100644
index 0000000..2b12c95
--- /dev/null
+++ b/pages/worker/levelList/components/table-tr.vue
@@ -0,0 +1,208 @@
+
+
+
+
+
+
+
+
+
diff --git a/pages/worker/levelList/index.vue b/pages/worker/levelList/index.vue
new file mode 100644
index 0000000..7737e8b
--- /dev/null
+++ b/pages/worker/levelList/index.vue
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/worker/workerList/components/layout.vue b/pages/worker/workerList/components/layout.vue
new file mode 100644
index 0000000..ff333ca
--- /dev/null
+++ b/pages/worker/workerList/components/layout.vue
@@ -0,0 +1,115 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 添加
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/worker/workerList/components/workerList.vue b/pages/worker/workerList/components/workerList.vue
new file mode 100644
index 0000000..c3292e9
--- /dev/null
+++ b/pages/worker/workerList/components/workerList.vue
@@ -0,0 +1,208 @@
+
+
+
+
+
+
+
+
+ 在线
+ 离线
+
+
+
+
+
+ {{item.nickname}}
+
+
+ {{item.age}}
+
+
+
+ {{item.age}}
+
+
+ 待审核
+ 已审核
+
+
+
+ 编辑资料
+ 技能管理
+ 在线状态
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/worker/workerList/index.vue b/pages/worker/workerList/index.vue
new file mode 100644
index 0000000..37b091f
--- /dev/null
+++ b/pages/worker/workerList/index.vue
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/worker/workerList/set.vue b/pages/worker/workerList/set.vue
new file mode 100644
index 0000000..e4f5d72
--- /dev/null
+++ b/pages/worker/workerList/set.vue
@@ -0,0 +1,148 @@
+
+
+
+
+
+ 接单时间段
+
+
+
+
+
+ 当前在线状态
+
+
+
+
+
+ 盲盒订单提醒
+
+
+
+
+
+
+ 保存
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/sheep/api/im/memberConversation.js b/sheep/api/im/memberConversation.js
new file mode 100644
index 0000000..17bb4a7
--- /dev/null
+++ b/sheep/api/im/memberConversation.js
@@ -0,0 +1,80 @@
+import request from '@/sheep/request';
+
+const ImConversationApi = {
+ // 获得会话列表
+ getMemberConversationPage: (params) => {
+ return request({
+ url: '/im/member-conversation/page',
+ method: 'GET',
+ params,
+ custom: {
+ auth: true,
+ showLoading: false,
+ },
+ });
+ },
+ getRandomMemberConversation: () => {
+ return request({
+ url: '/im/member-conversation/getRandom',
+ method: 'GET',
+ custom: {
+ auth: true,
+ showLoading: false,
+ },
+ });
+ },
+ // 创建会话
+ createMemberConversation: (data) => {
+ return request({
+ url: '/im/member-conversation/create',
+ method: 'POST',
+ data,
+ custom: {
+ auth: true,
+ showLoading: false,
+ },
+ });
+ },
+ // 删除会话
+ deleteMemberConversation: (id) => {
+ return request({
+ url: '/im/member-conversation/delete',
+ method: 'DELETE',
+ params: {
+ id
+ },
+ custom: {
+ auth: true,
+ showLoading: false,
+ },
+ });
+ },
+ // 拉黑
+ slashedMemberConversation: (id) => {
+ return request({
+ url: '/im/member-conversation/slashed',
+ method: 'DELETE',
+ params: {
+ id
+ },
+ custom: {
+ auth: true,
+ showLoading: false,
+ },
+ });
+ },
+ // 置顶会话
+ pinnedMemberConversation: (data) => {
+ return request({
+ url: '/im/member-conversation/pinned',
+ method: 'PUT',
+ data,
+ custom: {
+ auth: true,
+ showLoading: false,
+ },
+ });
+ },
+};
+
+export default ImConversationApi;
diff --git a/sheep/api/im/memberMessage.js b/sheep/api/im/memberMessage.js
new file mode 100644
index 0000000..f10bb64
--- /dev/null
+++ b/sheep/api/im/memberMessage.js
@@ -0,0 +1,44 @@
+import request from '@/sheep/request';
+
+const ImMessageApi = {
+ // 获得消息列表
+ getMemberMessagePage: (params) => {
+ return request({
+ url: '/im/member-message/page',
+ method: 'GET',
+ params,
+ custom: {
+ auth: true,
+ showLoading: false,
+ },
+ });
+ },
+ // 更新消息已读
+ updateReadStatus: (messageId) => {
+ return request({
+ url: '/im/member-message/update-read-status',
+ method: 'POST',
+ params: { messageId },
+ custom: {
+ auth: true,
+ showLoading: false,
+ },
+ });
+ },
+ // 发送消息
+ sendImMessage: (data) => {
+ return request({
+ url: '/im/member-message/send',
+ method: 'POST',
+ data,
+ custom: {
+ auth: true,
+ showLoading: false,
+ showSuccess: false,
+ successMsg: '保存成功'
+ },
+ });
+ },
+};
+
+export default ImMessageApi;
diff --git a/sheep/api/infra/file.js b/sheep/api/infra/file.js
new file mode 100644
index 0000000..f7f2a96
--- /dev/null
+++ b/sheep/api/infra/file.js
@@ -0,0 +1,45 @@
+import { baseUrl, apiPath, tenantId } from '@/sheep/config';
+
+const FileApi = {
+ // 上传文件
+ uploadFile: (file) => {
+ // TODO 芋艿:访问令牌的接入;
+ const token = uni.getStorageSync('token');
+ uni.showLoading({
+ title: '上传中',
+ });
+ return new Promise((resolve, reject) => {
+ uni.uploadFile({
+ url: baseUrl + apiPath + '/infra/file/upload',
+ filePath: file,
+ name: 'file',
+ header: {
+ // Accept: 'text/json',
+ Accept: '*/*',
+ 'tenant-id': tenantId,
+ // Authorization: 'Bearer test247',
+ },
+ success: (uploadFileRes) => {
+ let result = JSON.parse(uploadFileRes.data);
+ if (result.error === 1) {
+ uni.showToast({
+ icon: 'none',
+ title: result.msg,
+ });
+ } else {
+ return resolve(result);
+ }
+ },
+ fail: (error) => {
+ console.log('上传失败:', error);
+ return resolve(false);
+ },
+ complete: () => {
+ uni.hideLoading();
+ },
+ });
+ });
+ },
+};
+
+export default FileApi;
diff --git a/sheep/api/member/address.js b/sheep/api/member/address.js
new file mode 100644
index 0000000..d0c16ce
--- /dev/null
+++ b/sheep/api/member/address.js
@@ -0,0 +1,53 @@
+import request from '@/sheep/request';
+
+const AddressApi = {
+ // 获得用户收件地址列表
+ getAddressList: () => {
+ return request({
+ url: '/member/address/list',
+ method: 'GET'
+ });
+ },
+ // 创建用户收件地址
+ createAddress: (data) => {
+ return request({
+ url: '/member/address/create',
+ method: 'POST',
+ data,
+ custom: {
+ showSuccess: true,
+ successMsg: '保存成功'
+ },
+ });
+ },
+ // 更新用户收件地址
+ updateAddress: (data) => {
+ return request({
+ url: '/member/address/update',
+ method: 'PUT',
+ data,
+ custom: {
+ showSuccess: true,
+ successMsg: '更新成功'
+ },
+ });
+ },
+ // 获得用户收件地址
+ getAddress: (id) => {
+ return request({
+ url: '/member/address/get',
+ method: 'GET',
+ params: { id }
+ });
+ },
+ // 删除用户收件地址
+ deleteAddress: (id) => {
+ return request({
+ url: '/member/address/delete',
+ method: 'DELETE',
+ params: { id }
+ });
+ },
+};
+
+export default AddressApi;
diff --git a/sheep/api/member/auth.js b/sheep/api/member/auth.js
new file mode 100644
index 0000000..a1c0660
--- /dev/null
+++ b/sheep/api/member/auth.js
@@ -0,0 +1,132 @@
+import request from '@/sheep/request';
+
+const AuthUtil = {
+ // 使用手机 + 密码登录
+ login: (data) => {
+ return request({
+ url: '/member/auth/login',
+ method: 'POST',
+ data,
+ custom: {
+ showSuccess: true,
+ loadingMsg: '登录中',
+ successMsg: '登录成功',
+ },
+ });
+ },
+ // 使用手机 + 验证码登录
+ smsLogin: (data) => {
+ return request({
+ url: '/member/auth/sms-login',
+ method: 'POST',
+ data,
+ custom: {
+ showSuccess: true,
+ loadingMsg: '登录中',
+ successMsg: '登录成功',
+ },
+ });
+ },
+ // 发送手机验证码
+ sendSmsCode: (mobile, scene) => {
+ return request({
+ url: '/member/auth/send-sms-code',
+ method: 'POST',
+ data: {
+ mobile,
+ scene,
+ },
+ custom: {
+ loadingMsg: '发送中',
+ showSuccess: true,
+ successMsg: '发送成功',
+ },
+ });
+ },
+ // 登出系统
+ logout: () => {
+ return request({
+ url: '/member/auth/logout',
+ method: 'POST',
+ });
+ },
+ // 刷新令牌
+ refreshToken: (refreshToken) => {
+ return request({
+ url: '/member/auth/refresh-token',
+ method: 'POST',
+ params: {
+ refreshToken
+ },
+ custom: {
+ loading: false, // 不用加载中
+ showError: false, // 不展示错误提示
+ },
+ });
+ },
+ // 社交授权的跳转
+ socialAuthRedirect: (type, redirectUri) => {
+ return request({
+ url: '/member/auth/social-auth-redirect',
+ method: 'GET',
+ params: {
+ type,
+ redirectUri,
+ },
+ custom: {
+ showSuccess: true,
+ loadingMsg: '登陆中',
+ },
+ });
+ },
+ // 社交快捷登录
+ socialLogin: (type, code, state) => {
+ return request({
+ url: '/member/auth/social-login',
+ method: 'POST',
+ data: {
+ type,
+ code,
+ state,
+ },
+ custom: {
+ showSuccess: true,
+ loadingMsg: '登陆中',
+ },
+ });
+ },
+ // 微信小程序的一键登录
+ weixinMiniAppLogin: (phoneCode, loginCode, state) => {
+ return request({
+ url: '/member/auth/weixin-mini-app-login',
+ method: 'POST',
+ data: {
+ phoneCode,
+ loginCode,
+ state
+ },
+ custom: {
+ showSuccess: true,
+ loadingMsg: '登陆中',
+ successMsg: '登录成功',
+ },
+ });
+ },
+ // 创建微信 JS SDK 初始化所需的签名
+ createWeixinMpJsapiSignature: (url) => {
+ return request({
+ url: '/member/auth/create-weixin-jsapi-signature',
+ method: 'POST',
+ params: {
+ url
+ },
+ custom: {
+ showError: false,
+ showLoading: false,
+ },
+ })
+ },
+ //
+};
+
+export default AuthUtil;
diff --git a/sheep/api/member/point.js b/sheep/api/member/point.js
new file mode 100644
index 0000000..188ffd4
--- /dev/null
+++ b/sheep/api/member/point.js
@@ -0,0 +1,19 @@
+import request from '@/sheep/request';
+
+const PointApi = {
+ // 获得用户积分记录分页
+ getPointRecordPage: (params) => {
+ if (params.addStatus === undefined) {
+ delete params.addStatus
+ }
+ const queryString = Object.keys(params)
+ .map((key) => encodeURIComponent(key) + '=' + params[key])
+ .join('&');
+ return request({
+ url: `/member/point/record/page?${queryString}`,
+ method: 'GET',
+ });
+ }
+};
+
+export default PointApi;
diff --git a/sheep/api/member/signin.js b/sheep/api/member/signin.js
new file mode 100644
index 0000000..35169ef
--- /dev/null
+++ b/sheep/api/member/signin.js
@@ -0,0 +1,37 @@
+import request from '@/sheep/request';
+
+const SignInApi = {
+ // 获得签到规则列表
+ getSignInConfigList: () => {
+ return request({
+ url: '/member/sign-in/config/list',
+ method: 'GET',
+ });
+ },
+ // 获得个人签到统计
+ getSignInRecordSummary: () => {
+ return request({
+ url: '/member/sign-in/record/get-summary',
+ method: 'GET',
+ });
+ },
+ // 签到
+ createSignInRecord: () => {
+ return request({
+ url: '/member/sign-in/record/create',
+ method: 'POST',
+ });
+ },
+ // 获得签到记录分页
+ getSignRecordPage: (params) => {
+ const queryString = Object.keys(params)
+ .map((key) => encodeURIComponent(key) + '=' + params[key])
+ .join('&');
+ return request({
+ url: `/member/sign-in/record/page?${queryString}`,
+ method: 'GET',
+ });
+ },
+};
+
+export default SignInApi;
\ No newline at end of file
diff --git a/sheep/api/member/social.js b/sheep/api/member/social.js
new file mode 100644
index 0000000..14e6edf
--- /dev/null
+++ b/sheep/api/member/social.js
@@ -0,0 +1,76 @@
+import request from '@/sheep/request';
+
+const SocialApi = {
+ // 获得社交用户
+ getSocialUser: (type) => {
+ return request({
+ url: '/member/social-user/get',
+ method: 'GET',
+ params: {
+ type
+ },
+ custom: {
+ showLoading: false,
+ },
+ });
+ },
+ // 社交绑定
+ socialBind: (type, code, state) => {
+ return request({
+ url: '/member/social-user/bind',
+ method: 'POST',
+ data: {
+ type,
+ code,
+ state
+ },
+ custom: {
+ custom: {
+ showSuccess: true,
+ loadingMsg: '绑定中',
+ successMsg: '绑定成功',
+ },
+ },
+ });
+ },
+ // 社交绑定
+ socialUnbind: (type, openid) => {
+ return request({
+ url: '/member/social-user/unbind',
+ method: 'DELETE',
+ data: {
+ type,
+ openid
+ },
+ custom: {
+ showLoading: false,
+ loadingMsg: '解除绑定',
+ successMsg: '解绑成功',
+ },
+ });
+ },
+ // 获取订阅消息模板列表
+ getSubscribeTemplateList: () =>
+ request({
+ url: '/member/social-user/get-subscribe-template-list',
+ method: 'GET',
+ custom: {
+ showError: false,
+ showLoading: false,
+ },
+ }),
+ // 获取微信小程序码
+ getWxaQrcode: async (path, query) => {
+ return await request({
+ url: '/member/social-user/wxa-qrcode',
+ method: 'POST',
+ data: {
+ scene: query,
+ path,
+ checkPath: false, // TODO 开发环境暂不检查 path 是否存在
+ },
+ });
+ },
+};
+
+export default SocialApi;
\ No newline at end of file
diff --git a/sheep/api/member/user.js b/sheep/api/member/user.js
new file mode 100644
index 0000000..671324c
--- /dev/null
+++ b/sheep/api/member/user.js
@@ -0,0 +1,166 @@
+import request from '@/sheep/request';
+
+const UserApi = {
+ // 获取会员列表
+ getUserPage: (params) => {
+ return request({
+ url: '/member/user/page',
+ method: 'GET',
+ params,
+ custom: {
+ auth: false,
+ showLoading: false,
+ },
+ });
+ },
+ // 获得基本信息
+ getUserInfo: () => {
+ return request({
+ url: '/member/user/get',
+ method: 'GET',
+ custom: {
+ showLoading: false,
+ auth: true,
+ },
+ });
+ },
+ // 获得榜单信息
+ getWeekTopList: () => {
+ return request({
+ url: '/member/user/getWeekTopList',
+ method: 'GET',
+ custom: {
+ auth: false,
+ showLoading: false,
+ },
+ });
+ },
+ // 获得首页信息
+ getHomeData: () => {
+ return request({
+ url: '/member/user/getHomeData',
+ method: 'GET',
+ custom: {
+ auth: false,
+ showLoading: false,
+ },
+ });
+ },
+ // 获得基本信息
+ getUserInfoById: (id) => {
+ return request({
+ url: '/member/user/getByUserId',
+ method: 'GET',
+ params: { id },
+ custom: {
+ showLoading: false,
+ auth: false,
+ },
+ });
+ },
+ // 交换名片
+ getQrcodeByUserId: (id) => {
+ return request({
+ url: '/member/user/getQrcodeByUserId',
+ method: 'GET',
+ params: { id },
+ custom: {
+ showLoading: false,
+ auth: true,
+ },
+ });
+ },
+ // 判断是否关注公众号
+ getQrcode: () => {
+ return request({
+ url: '/mp/user/getQrcode',
+ method: 'GET',
+ custom: {
+ showLoading: false,
+ auth: true,
+ },
+ });
+ },
+ // 修改基本信息
+ updateUser: (data) => {
+ return request({
+ url: '/member/user/update',
+ method: 'PUT',
+ data,
+ custom: {
+ auth: true,
+ showSuccess: true,
+ successMsg: '更新成功'
+ },
+ });
+ },
+ // 首页置顶
+ slashed: () => {
+ return request({
+ url: '/member/user/slashed',
+ method: 'PUT',
+ custom: {
+ auth: true,
+ showSuccess: true,
+ successMsg: '置顶成功'
+ },
+ });
+ },
+ // 修改用户手机
+ updateUserMobile: (data) => {
+ return request({
+ url: '/member/user/update-mobile',
+ method: 'PUT',
+ data,
+ custom: {
+ loadingMsg: '验证中',
+ showSuccess: true,
+ successMsg: '修改成功'
+ },
+ });
+ },
+ // 基于微信小程序的授权码,修改用户手机
+ updateUserMobileByWeixin: (code) => {
+ return request({
+ url: '/member/user/update-mobile-by-weixin',
+ method: 'PUT',
+ data: {
+ code
+ },
+ custom: {
+ showSuccess: true,
+ loadingMsg: '获取中',
+ successMsg: '修改成功'
+ },
+ });
+ },
+ // 修改密码
+ updateUserPassword: (data) => {
+ return request({
+ url: '/member/user/update-password',
+ method: 'PUT',
+ data,
+ custom: {
+ loadingMsg: '验证中',
+ showSuccess: true,
+ successMsg: '修改成功'
+ },
+ });
+ },
+ // 重置密码
+ resetUserPassword: (data) => {
+ return request({
+ url: '/member/user/reset-password',
+ method: 'PUT',
+ data,
+ custom: {
+ loadingMsg: '验证中',
+ showSuccess: true,
+ successMsg: '修改成功'
+ }
+ });
+ },
+
+};
+
+export default UserApi;
diff --git a/sheep/api/migration/app.js b/sheep/api/migration/app.js
new file mode 100644
index 0000000..158414f
--- /dev/null
+++ b/sheep/api/migration/app.js
@@ -0,0 +1,21 @@
+import request from '@/sheep/request';
+
+// TODO 芋艿:小程序直播还不支持
+export default {
+ //小程序直播
+ mplive: {
+ getRoomList: (ids) =>
+ request({
+ url: 'app/mplive/getRoomList',
+ method: 'GET',
+ params: {
+ ids: ids.join(','),
+ }
+ }),
+ getMpLink: () =>
+ request({
+ url: 'app/mplive/getMpLink',
+ method: 'GET'
+ }),
+ },
+};
diff --git a/sheep/api/migration/index.js b/sheep/api/migration/index.js
new file mode 100644
index 0000000..31a85ef
--- /dev/null
+++ b/sheep/api/migration/index.js
@@ -0,0 +1,10 @@
+const files = import.meta.glob('./*.js', { eager: true });
+let api = {};
+Object.keys(files).forEach((key) => {
+ api = {
+ ...api,
+ [key.replace(/(.*\/)*([^.]+).*/gi, '$2')]: files[key].default,
+ };
+});
+
+export default api;
\ No newline at end of file
diff --git a/sheep/api/migration/third.js b/sheep/api/migration/third.js
new file mode 100644
index 0000000..325638c
--- /dev/null
+++ b/sheep/api/migration/third.js
@@ -0,0 +1,18 @@
+import request from '@/sheep/request';
+
+export default {
+ // 苹果相关
+ apple: {
+ // 第三方登录
+ login: (data) =>
+ request({
+ url: 'third/apple/login',
+ method: 'POST',
+ data,
+ custom: {
+ showSuccess: true,
+ loadingMsg: '登陆中',
+ },
+ }),
+ },
+};
diff --git a/sheep/api/pay/channel.js b/sheep/api/pay/channel.js
new file mode 100644
index 0000000..4e7bfc5
--- /dev/null
+++ b/sheep/api/pay/channel.js
@@ -0,0 +1,14 @@
+import request from '@/sheep/request';
+
+const PayChannelApi = {
+ // 获得指定应用的开启的支付渠道编码列表
+ getEnableChannelCodeList: (appId) => {
+ return request({
+ url: '/pay/channel/get-enable-code-list',
+ method: 'GET',
+ params: { appId }
+ });
+ },
+};
+
+export default PayChannelApi;
diff --git a/sheep/api/pay/order.js b/sheep/api/pay/order.js
new file mode 100644
index 0000000..f985359
--- /dev/null
+++ b/sheep/api/pay/order.js
@@ -0,0 +1,22 @@
+import request from '@/sheep/request';
+
+const PayOrderApi = {
+ // 获得支付订单
+ getOrder: (id) => {
+ return request({
+ url: '/pay/order/get',
+ method: 'GET',
+ params: { id }
+ });
+ },
+ // 提交支付订单
+ submitOrder: (data) => {
+ return request({
+ url: '/pay/order/submit',
+ method: 'POST',
+ data
+ });
+ }
+};
+
+export default PayOrderApi;
diff --git a/sheep/api/pay/point.js b/sheep/api/pay/point.js
new file mode 100644
index 0000000..09c7a1d
--- /dev/null
+++ b/sheep/api/pay/point.js
@@ -0,0 +1,37 @@
+import request from '@/sheep/request';
+
+const PayPointApi = {
+ // 获得钱包充值套餐列表
+ getPointRechargePackageList: () => {
+ return request({
+ url: '/pay/point-recharge-package/list',
+ method: 'GET',
+ custom: {
+ showError: false,
+ showLoading: false,
+ },
+ });
+ },
+ // 创建钱包充值记录(发起充值)
+ createPointRecharge: (data) => {
+ return request({
+ url: '/pay/point-recharge/create',
+ method: 'POST',
+ data,
+ });
+ },
+ // 获得钱包充值记录分页
+ getPointRechargePage: (params) => {
+ return request({
+ url: '/pay/point-recharge/page',
+ method: 'GET',
+ params,
+ custom: {
+ showError: false,
+ showLoading: false,
+ },
+ });
+ },
+};
+
+export default PayPointApi;
diff --git a/sheep/api/pay/wallet.js b/sheep/api/pay/wallet.js
new file mode 100644
index 0000000..023902a
--- /dev/null
+++ b/sheep/api/pay/wallet.js
@@ -0,0 +1,68 @@
+import request from '@/sheep/request';
+
+const PayWalletApi = {
+ // 获取钱包
+ getPayWallet() {
+ return request({
+ url: '/pay/wallet/get',
+ method: 'GET',
+ custom: {
+ showLoading: false,
+ auth: true,
+ },
+ });
+ },
+ // 获得钱包流水分页
+ getWalletTransactionPage: (params) => {
+ const queryString = Object.keys(params)
+ .map((key) => encodeURIComponent(key) + '=' + params[key])
+ .join('&');
+ return request({
+ url: `/pay/wallet-transaction/page?${queryString}`,
+ method: 'GET',
+ });
+ },
+ // 获得钱包流水统计
+ getWalletTransactionSummary: (params) => {
+ const queryString = `createTime=${params.createTime[0]}&createTime=${params.createTime[1]}`;
+ return request({
+ url: `/pay/wallet-transaction/get-summary?${queryString}`,
+ // url: `/pay/wallet-transaction/get-summary`,
+ method: 'GET',
+ // params: params
+ });
+ },
+ // 获得钱包充值套餐列表
+ getWalletRechargePackageList: () => {
+ return request({
+ url: '/pay/wallet-recharge-package/list',
+ method: 'GET',
+ custom: {
+ showError: false,
+ showLoading: false,
+ },
+ });
+ },
+ // 创建钱包充值记录(发起充值)
+ createWalletRecharge: (data) => {
+ return request({
+ url: '/pay/wallet-recharge/create',
+ method: 'POST',
+ data,
+ });
+ },
+ // 获得钱包充值记录分页
+ getWalletRechargePage: (params) => {
+ return request({
+ url: '/pay/wallet-recharge/page',
+ method: 'GET',
+ params,
+ custom: {
+ showError: false,
+ showLoading: false,
+ },
+ });
+ },
+};
+
+export default PayWalletApi;
diff --git a/sheep/api/product/category.js b/sheep/api/product/category.js
new file mode 100644
index 0000000..3b6f8f0
--- /dev/null
+++ b/sheep/api/product/category.js
@@ -0,0 +1,21 @@
+import request from '@/sheep/request';
+
+const CategoryApi = {
+ // 查询分类列表
+ getCategoryList: () => {
+ return request({
+ url: '/product/category/list',
+ method: 'GET',
+ });
+ },
+ // 查询分类列表,指定编号
+ getCategoryListByIds: (ids) => {
+ return request({
+ url: '/product/category/list-by-ids',
+ method: 'GET',
+ params: { ids },
+ });
+ },
+};
+
+export default CategoryApi;
diff --git a/sheep/api/product/comment.js b/sheep/api/product/comment.js
new file mode 100644
index 0000000..2bbffd1
--- /dev/null
+++ b/sheep/api/product/comment.js
@@ -0,0 +1,22 @@
+import request from '@/sheep/request';
+
+const CommentApi = {
+ // 获得商品评价分页
+ getCommentPage: (spuId, pageNo, pageSize, type) => {
+ return request({
+ url: '/product/comment/page',
+ method: 'GET',
+ params: {
+ spuId,
+ pageNo,
+ pageSize,
+ type,
+ },
+ custom: {
+ showLoading: false,
+ showError: false,
+ },
+ });
+ },
+};
+export default CommentApi;
diff --git a/sheep/api/product/favorite.js b/sheep/api/product/favorite.js
new file mode 100644
index 0000000..134c231
--- /dev/null
+++ b/sheep/api/product/favorite.js
@@ -0,0 +1,54 @@
+import request from '@/sheep/request';
+
+const FavoriteApi = {
+ // 获得商品收藏分页
+ getFavoritePage: (data) => {
+ return request({
+ url: '/product/favorite/page',
+ method: 'GET',
+ params: data,
+ });
+ },
+ // 检查是否收藏过商品
+ isFavoriteExists: (spuId) => {
+ return request({
+ url: '/product/favorite/exits',
+ method: 'GET',
+ params: {
+ spuId,
+ },
+ });
+ },
+ // 添加商品收藏
+ createFavorite: (spuId) => {
+ return request({
+ url: '/product/favorite/create',
+ method: 'POST',
+ data: {
+ spuId,
+ },
+ custom: {
+ auth: true,
+ showSuccess: true,
+ successMsg: '收藏成功',
+ },
+ });
+ },
+ // 取消商品收藏
+ deleteFavorite: (spuId) => {
+ return request({
+ url: '/product/favorite/delete',
+ method: 'DELETE',
+ data: {
+ spuId,
+ },
+ custom: {
+ auth: true,
+ showSuccess: true,
+ successMsg: '取消成功',
+ },
+ });
+ },
+};
+
+export default FavoriteApi;
diff --git a/sheep/api/product/history.js b/sheep/api/product/history.js
new file mode 100644
index 0000000..9ed53e3
--- /dev/null
+++ b/sheep/api/product/history.js
@@ -0,0 +1,39 @@
+import request from '@/sheep/request';
+
+const SpuHistoryApi = {
+ // 删除商品浏览记录
+ deleteBrowseHistory: (spuIds) => {
+ return request({
+ url: '/product/browse-history/delete',
+ method: 'DELETE',
+ data: { spuIds },
+ custom: {
+ showSuccess: true,
+ successMsg: '删除成功',
+ },
+ });
+ },
+ // 清空商品浏览记录
+ cleanBrowseHistory: () => {
+ return request({
+ url: '/product/browse-history/clean',
+ method: 'DELETE',
+ custom: {
+ showSuccess: true,
+ successMsg: '清空成功',
+ },
+ });
+ },
+ // 获得商品浏览记录分页
+ getBrowseHistoryPage: (data) => {
+ return request({
+ url: '/product/browse-history/page',
+ method: 'GET',
+ data,
+ custom: {
+ showLoading: false
+ },
+ });
+ },
+};
+export default SpuHistoryApi;
diff --git a/sheep/api/product/spu.js b/sheep/api/product/spu.js
new file mode 100644
index 0000000..3b84c1d
--- /dev/null
+++ b/sheep/api/product/spu.js
@@ -0,0 +1,41 @@
+import request from '@/sheep/request';
+
+const SpuApi = {
+ // 获得商品 SPU 列表
+ getSpuListByIds: (ids) => {
+ return request({
+ url: '/product/spu/list-by-ids',
+ method: 'GET',
+ params: { ids },
+ custom: {
+ showLoading: false,
+ showError: false,
+ },
+ });
+ },
+ // 获得商品 SPU 分页
+ getSpuPage: (params) => {
+ return request({
+ url: '/product/spu/page',
+ method: 'GET',
+ params,
+ custom: {
+ showLoading: false,
+ showError: false,
+ },
+ });
+ },
+ // 查询商品
+ getSpuDetail: (id) => {
+ return request({
+ url: '/product/spu/get-detail',
+ method: 'GET',
+ params: { id },
+ custom: {
+ showLoading: false,
+ showError: false,
+ },
+ });
+ },
+};
+export default SpuApi;
diff --git a/sheep/api/promotion/activity.js b/sheep/api/promotion/activity.js
new file mode 100644
index 0000000..eb47ce1
--- /dev/null
+++ b/sheep/api/promotion/activity.js
@@ -0,0 +1,16 @@
+import request from '@/sheep/request';
+
+const ActivityApi = {
+ // 获得单个商品,近期参与的每个活动
+ getActivityListBySpuId: (spuId) => {
+ return request({
+ url: '/promotion/activity/list-by-spu-id',
+ method: 'GET',
+ params: {
+ spuId,
+ },
+ });
+ },
+};
+
+export default ActivityApi;
diff --git a/sheep/api/promotion/article.js b/sheep/api/promotion/article.js
new file mode 100644
index 0000000..ded5fb1
--- /dev/null
+++ b/sheep/api/promotion/article.js
@@ -0,0 +1,12 @@
+import request from '@/sheep/request';
+
+export default {
+ // 获得文章详情
+ getArticle: (id, title) => {
+ return request({
+ url: '/promotion/article/get',
+ method: 'GET',
+ params: { id, title }
+ });
+ }
+}
diff --git a/sheep/api/promotion/combination.js b/sheep/api/promotion/combination.js
new file mode 100644
index 0000000..8dfa0c2
--- /dev/null
+++ b/sheep/api/promotion/combination.js
@@ -0,0 +1,68 @@
+import request from '@/sheep/request';
+
+// 拼团 API
+const CombinationApi = {
+
+ // 获得拼团活动分页
+ getCombinationActivityPage: (params) => {
+ return request({
+ url: '/promotion/combination-activity/page',
+ method: 'GET',
+ params,
+ });
+ },
+
+ // 获得拼团活动明细
+ getCombinationActivity: (id) => {
+ return request({
+ url: '/promotion/combination-activity/get-detail',
+ method: 'GET',
+ params: {
+ id,
+ },
+ });
+ },
+
+ // 获得最近 n 条拼团记录(团长发起的)
+ getHeadCombinationRecordList: (activityId, status, count) => {
+ return request({
+ url: '/promotion/combination-record/get-head-list',
+ method: 'GET',
+ params: {
+ activityId,
+ status,
+ count,
+ },
+ });
+ },
+
+ // 获得我的拼团记录分页
+ getCombinationRecordPage: (params) => {
+ return request({
+ url: "/promotion/combination-record/page",
+ method: 'GET',
+ params
+ });
+ },
+
+ // 获得拼团记录明细
+ getCombinationRecordDetail: (id) => {
+ return request({
+ url: '/promotion/combination-record/get-detail',
+ method: 'GET',
+ params: {
+ id,
+ },
+ });
+ },
+
+ // 获得拼团记录的概要信息
+ getCombinationRecordSummary: () => {
+ return request({
+ url: '/promotion/combination-record/get-summary',
+ method: 'GET',
+ });
+ },
+};
+
+export default CombinationApi;
diff --git a/sheep/api/promotion/coupon.js b/sheep/api/promotion/coupon.js
new file mode 100644
index 0000000..c9dfa52
--- /dev/null
+++ b/sheep/api/promotion/coupon.js
@@ -0,0 +1,101 @@
+import request from '@/sheep/request';
+
+const CouponApi = {
+ // 获得优惠劵模板列表
+ getCouponTemplateListByIds: (ids) => {
+ return request({
+ url: '/promotion/coupon-template/list-by-ids',
+ method: 'GET',
+ params: { ids },
+ custom: {
+ showLoading: false, // 不展示 Loading,避免领取优惠劵时,不成功提示
+ showError: false,
+ },
+ });
+ },
+ // 获得优惠劵模版列表
+ getCouponTemplateList: (spuId, productScope, count) => {
+ return request({
+ url: '/promotion/coupon-template/list',
+ method: 'GET',
+ params: { spuId, productScope, count },
+ });
+ },
+ // 获得优惠劵模版分页
+ getCouponTemplatePage: (params) => {
+ return request({
+ url: '/promotion/coupon-template/page',
+ method: 'GET',
+ params,
+ });
+ },
+ // 获得优惠劵模版
+ getCouponTemplate: (id) => {
+ return request({
+ url: '/promotion/coupon-template/get',
+ method: 'GET',
+ params: { id },
+ });
+ },
+ // 我的优惠劵列表
+ getCouponPage: (params) => {
+ return request({
+ url: '/promotion/coupon/page',
+ method: 'GET',
+ params,
+ });
+ },
+ // 领取优惠券
+ takeCoupon: (templateId) => {
+ return request({
+ url: '/promotion/coupon/take',
+ method: 'POST',
+ data: { templateId },
+ custom: {
+ auth: true,
+ showLoading: true,
+ loadingMsg: '领取中',
+ showSuccess: true,
+ successMsg: '领取成功',
+ },
+ });
+ },
+ // 获得优惠劵
+ getCoupon: (id) => {
+ return request({
+ url: '/promotion/coupon/get',
+ method: 'GET',
+ params: { id },
+ });
+ },
+ // 获得未使用的优惠劵数量
+ getUnusedCouponCount: () => {
+ return request({
+ url: '/promotion/coupon/get-unused-count',
+ method: 'GET',
+ custom: {
+ showLoading: false,
+ auth: true,
+ },
+ });
+ },
+ // 获得匹配指定商品的优惠劵列表
+ getMatchCouponList: (price, spuIds, skuIds, categoryIds) => {
+ return request({
+ url: '/promotion/coupon/match-list',
+ method: 'GET',
+ params: {
+ price,
+ spuIds: spuIds.join(','),
+ skuIds: skuIds.join(','),
+ categoryIds: categoryIds.join(','),
+ },
+ custom: {
+ showError: false,
+ showLoading: false, // 避免影响 settlementOrder 结算的结果
+ },
+ });
+ }
+};
+
+export default CouponApi;
diff --git a/sheep/api/promotion/diy.js b/sheep/api/promotion/diy.js
new file mode 100644
index 0000000..e524f69
--- /dev/null
+++ b/sheep/api/promotion/diy.js
@@ -0,0 +1,38 @@
+import request from '@/sheep/request';
+
+const DiyApi = {
+ getUsedDiyTemplate: () => {
+ return request({
+ url: '/promotion/diy-template/used',
+ method: 'GET',
+ custom: {
+ showError: false,
+ showLoading: false,
+ },
+ });
+ },
+ getDiyTemplate: (id) => {
+ return request({
+ url: '/promotion/diy-template/get',
+ method: 'GET',
+ params: {
+ id
+ },
+ custom: {
+ showError: false,
+ showLoading: false,
+ },
+ });
+ },
+ getDiyPage: (id) => {
+ return request({
+ url: '/promotion/diy-page/get',
+ method: 'GET',
+ params: {
+ id
+ }
+ });
+ },
+};
+
+export default DiyApi;
diff --git a/sheep/api/promotion/kefu.js b/sheep/api/promotion/kefu.js
new file mode 100644
index 0000000..86481ab
--- /dev/null
+++ b/sheep/api/promotion/kefu.js
@@ -0,0 +1,31 @@
+import request from '@/sheep/request';
+
+const KeFuApi = {
+ sendKefuMessage: (data) => {
+ return request({
+ url: '/promotion/kefu-message/send',
+ method: 'POST',
+ data,
+ custom: {
+ auth: true,
+ showLoading: true,
+ loadingMsg: '发送中',
+ showSuccess: true,
+ successMsg: '发送成功',
+ },
+ });
+ },
+ getKefuMessagePage: (params) => {
+ return request({
+ url: '/promotion/kefu-message/page',
+ method: 'GET',
+ params,
+ custom: {
+ auth: true,
+ showLoading: false,
+ },
+ });
+ },
+};
+
+export default KeFuApi;
diff --git a/sheep/api/promotion/rewardActivity.js b/sheep/api/promotion/rewardActivity.js
new file mode 100644
index 0000000..5f74db7
--- /dev/null
+++ b/sheep/api/promotion/rewardActivity.js
@@ -0,0 +1,14 @@
+import request from '@/sheep/request';
+
+const RewardActivityApi = {
+ // 获得满减送活动
+ getRewardActivity: (id) => {
+ return request({
+ url: '/promotion/reward-activity/get',
+ method: 'GET',
+ params: { id },
+ });
+ }
+};
+
+export default RewardActivityApi;
\ No newline at end of file
diff --git a/sheep/api/promotion/seckill.js b/sheep/api/promotion/seckill.js
new file mode 100644
index 0000000..4d41e8b
--- /dev/null
+++ b/sheep/api/promotion/seckill.js
@@ -0,0 +1,33 @@
+import request from "@/sheep/request";
+
+const SeckillApi = {
+ // 获得秒杀时间段列表
+ getSeckillConfigList: () => {
+ return request({ url: 'promotion/seckill-config/list', method: 'GET' });
+ },
+
+ // 获得当前秒杀活动
+ getNowSeckillActivity: () => {
+ return request({ url: 'promotion/seckill-activity/get-now', method: 'GET' });
+ },
+
+ // 获得秒杀活动分页
+ getSeckillActivityPage: (params) => {
+ return request({ url: 'promotion/seckill-activity/page', method: 'GET', params });
+ },
+
+ /**
+ * 获得秒杀活动明细
+ * @param {number} id 秒杀活动编号
+ * @return {*}
+ */
+ getSeckillActivity: (id) => {
+ return request({
+ url: 'promotion/seckill-activity/get-detail',
+ method: 'GET',
+ params: { id }
+ });
+ }
+}
+
+export default SeckillApi;
diff --git a/sheep/api/system/area.js b/sheep/api/system/area.js
new file mode 100644
index 0000000..7c41eff
--- /dev/null
+++ b/sheep/api/system/area.js
@@ -0,0 +1,13 @@
+import request from '@/sheep/request';
+
+const AreaApi = {
+ // 获得地区树
+ getAreaTree: () => {
+ return request({
+ url: '/system/area/tree',
+ method: 'GET'
+ });
+ },
+};
+
+export default AreaApi;
diff --git a/sheep/api/system/dict.js b/sheep/api/system/dict.js
new file mode 100644
index 0000000..cab64f7
--- /dev/null
+++ b/sheep/api/system/dict.js
@@ -0,0 +1,16 @@
+import request from '@/sheep/request';
+
+const DictApi = {
+ // 根据字典类型查询字典数据信息
+ getDictDataListByType: (type) => {
+ return request({
+ url: `/system/dict-data/type`,
+ method: 'GET',
+ params: {
+ type,
+ },
+ });
+ },
+};
+
+export default DictApi;
diff --git a/sheep/api/trade/afterSale.js b/sheep/api/trade/afterSale.js
new file mode 100644
index 0000000..44c4dd3
--- /dev/null
+++ b/sheep/api/trade/afterSale.js
@@ -0,0 +1,63 @@
+import request from '@/sheep/request';
+
+const AfterSaleApi = {
+ // 获得售后分页
+ getAfterSalePage: (params) => {
+ return request({
+ url: `/trade/after-sale/page`,
+ method: 'GET',
+ params,
+ custom: {
+ showLoading: false,
+ },
+ });
+ },
+ // 创建售后
+ createAfterSale: (data) => {
+ return request({
+ url: `/trade/after-sale/create`,
+ method: 'POST',
+ data,
+ });
+ },
+ // 获得售后
+ getAfterSale: (id) => {
+ return request({
+ url: `/trade/after-sale/get`,
+ method: 'GET',
+ params: {
+ id,
+ },
+ });
+ },
+ // 取消售后
+ cancelAfterSale: (id) => {
+ return request({
+ url: `/trade/after-sale/cancel`,
+ method: 'DELETE',
+ params: {
+ id,
+ },
+ });
+ },
+ // 获得售后日志列表
+ getAfterSaleLogList: (afterSaleId) => {
+ return request({
+ url: `/trade/after-sale-log/list`,
+ method: 'GET',
+ params: {
+ afterSaleId,
+ },
+ });
+ },
+ // 退回货物
+ deliveryAfterSale: (data) => {
+ return request({
+ url: `/trade/after-sale/delivery`,
+ method: 'PUT',
+ data,
+ });
+ }
+};
+
+export default AfterSaleApi;
diff --git a/sheep/api/trade/brokerage.js b/sheep/api/trade/brokerage.js
new file mode 100644
index 0000000..206e7ec
--- /dev/null
+++ b/sheep/api/trade/brokerage.js
@@ -0,0 +1,93 @@
+import request from '@/sheep/request';
+
+const BrokerageApi = {
+ // 绑定分销用户
+ bindBrokerageUser: (data)=>{
+ return request({
+ url: '/trade/brokerage-user/bind',
+ method: 'PUT',
+ data
+ });
+ },
+ // 获得个人分销信息
+ getBrokerageUser: () => {
+ return request({
+ url: '/trade/brokerage-user/get',
+ method: 'GET'
+ });
+ },
+ // 获得个人分销统计
+ getBrokerageUserSummary: () => {
+ return request({
+ url: '/trade/brokerage-user/get-summary',
+ method: 'GET',
+ });
+ },
+ // 获得分销记录分页
+ getBrokerageRecordPage: params => {
+ if (params.status === undefined) {
+ delete params.status
+ }
+ const queryString = Object.keys(params)
+ .map(key => encodeURIComponent(key) + '=' + params[key])
+ .join('&');
+ return request({
+ url: `/trade/brokerage-record/page?${queryString}`,
+ method: 'GET',
+ });
+ },
+ // 创建分销提现
+ createBrokerageWithdraw: data => {
+ return request({
+ url: '/trade/brokerage-withdraw/create',
+ method: 'POST',
+ data,
+ });
+ },
+ // 获得商品的分销金额
+ getProductBrokeragePrice: spuId => {
+ return request({
+ url: '/trade/brokerage-record/get-product-brokerage-price',
+ method: 'GET',
+ params: { spuId }
+ });
+ },
+ // 获得分销用户排行(基于佣金)
+ getRankByPrice: params => {
+ const queryString = `times=${params.times[0]}×=${params.times[1]}`;
+ return request({
+ url: `/trade/brokerage-user/get-rank-by-price?${queryString}`,
+ method: 'GET',
+ });
+ },
+ // 获得分销用户排行分页(基于佣金)
+ getBrokerageUserChildSummaryPageByPrice: params => {
+ const queryString = Object.keys(params)
+ .map(key => encodeURIComponent(key) + '=' + params[key])
+ .join('&');
+ return request({
+ url: `/trade/brokerage-user/rank-page-by-price?${queryString}`,
+ method: 'GET',
+ });
+ },
+ // 获得分销用户排行分页(基于用户量)
+ getBrokerageUserRankPageByUserCount: params => {
+ const queryString = Object.keys(params)
+ .map(key => encodeURIComponent(key) + '=' + params[key])
+ .join('&');
+ return request({
+ url: `/trade/brokerage-user/rank-page-by-user-count?${queryString}`,
+ method: 'GET',
+ });
+ },
+ // 获得下级分销统计分页
+ getBrokerageUserChildSummaryPage: params => {
+ return request({
+ url: '/trade/brokerage-user/child-summary-page',
+ method: 'GET',
+ params,
+ })
+ }
+}
+
+export default BrokerageApi
diff --git a/sheep/api/trade/cart.js b/sheep/api/trade/cart.js
new file mode 100644
index 0000000..63cea18
--- /dev/null
+++ b/sheep/api/trade/cart.js
@@ -0,0 +1,50 @@
+import request from '@/sheep/request';
+
+const CartApi = {
+ addCart: (data) => {
+ return request({
+ url: '/trade/cart/add',
+ method: 'POST',
+ data: data,
+ custom: {
+ showSuccess: true,
+ successMsg: '已添加到购物车~',
+ }
+ });
+ },
+ updateCartCount: (data) => {
+ return request({
+ url: '/trade/cart/update-count',
+ method: 'PUT',
+ data: data
+ });
+ },
+ updateCartSelected: (data) => {
+ return request({
+ url: '/trade/cart/update-selected',
+ method: 'PUT',
+ data: data
+ });
+ },
+ deleteCart: (ids) => {
+ return request({
+ url: '/trade/cart/delete',
+ method: 'DELETE',
+ params: {
+ ids
+ }
+ });
+ },
+ getCartList: () => {
+ return request({
+ url: '/trade/cart/list',
+ method: 'GET',
+ custom: {
+ showLoading: false,
+ auth: true,
+ },
+ });
+ },
+};
+
+export default CartApi;
\ No newline at end of file
diff --git a/sheep/api/trade/config.js b/sheep/api/trade/config.js
new file mode 100644
index 0000000..92dccae
--- /dev/null
+++ b/sheep/api/trade/config.js
@@ -0,0 +1,20 @@
+import request from '@/sheep/request';
+
+const TradeConfigApi = {
+ // 获得交易配置
+ getTradeConfig: (userId) => {
+ return request({
+ url: `/trade/config/get`,
+ params: {
+ userId,
+ },
+ custom: {
+ auth: false,
+ showLoading: false,
+ },
+ method: 'GET',
+ });
+ },
+};
+
+export default TradeConfigApi;
diff --git a/sheep/api/trade/delivery.js b/sheep/api/trade/delivery.js
new file mode 100644
index 0000000..a6551da
--- /dev/null
+++ b/sheep/api/trade/delivery.js
@@ -0,0 +1,31 @@
+import request from '@/sheep/request';
+
+const DeliveryApi = {
+ // 获得快递公司列表
+ getDeliveryExpressList: () => {
+ return request({
+ url: `/trade/delivery/express/list`,
+ method: 'get',
+ });
+ },
+ // 获得自提门店列表
+ getDeliveryPickUpStoreList: (params) => {
+ return request({
+ url: `/trade/delivery/pick-up-store/list`,
+ method: 'GET',
+ params,
+ });
+ },
+ // 获得自提门店
+ getDeliveryPickUpStore: (id) => {
+ return request({
+ url: `/trade/delivery/pick-up-store/get`,
+ method: 'GET',
+ params: {
+ id,
+ },
+ });
+ },
+};
+
+export default DeliveryApi;
diff --git a/sheep/api/trade/order.js b/sheep/api/trade/order.js
new file mode 100644
index 0000000..77118ba
--- /dev/null
+++ b/sheep/api/trade/order.js
@@ -0,0 +1,247 @@
+import request from '@/sheep/request';
+import { isEmpty } from '@/sheep/helper/utils';
+
+const OrderApi = {
+ // 计算订单信息
+ settlementOrder: (data) => {
+ const data2 = {
+ ...data,
+ };
+ // 移除多余字段
+ if (!(data.couponId > 0)) {
+ delete data2.couponId;
+ }
+ if (!(data.addressId > 0)) {
+ delete data2.addressId;
+ }
+ if (!(data.pickUpStoreId > 0)) {
+ delete data2.pickUpStoreId;
+ }
+ if (isEmpty(data.receiverName)) {
+ delete data2.receiverName;
+ }
+ if (isEmpty(data.receiverMobile)) {
+ delete data2.receiverMobile;
+ }
+ if (!(data.combinationActivityId > 0)) {
+ delete data2.combinationActivityId;
+ }
+ if (!(data.combinationHeadId > 0)) {
+ delete data2.combinationHeadId;
+ }
+ if (!(data.seckillActivityId > 0)) {
+ delete data2.seckillActivityId;
+ }
+ // 解决 SpringMVC 接受 List- 参数的问题
+ delete data2.items;
+ for (let i = 0; i < data.items.length; i++) {
+ data2[encodeURIComponent('items[' + i + '' + '].skuId')] = data.items[i].skuId + '';
+ data2[encodeURIComponent('items[' + i + '' + '].count')] = data.items[i].count + '';
+ if (data.items[i].cartId) {
+ data2[encodeURIComponent('items[' + i + '' + '].cartId')] = data.items[i].cartId + '';
+ }
+ }
+ const queryString = Object.keys(data2)
+ .map((key) => key + '=' + data2[key])
+ .join('&');
+ return request({
+ url: `/trade/order/settlement?${queryString}`,
+ method: 'GET',
+ custom: {
+ showError: true,
+ showLoading: true,
+ },
+ });
+ },
+ clerkOrder: (data) => {
+ const data2 = {
+ ...data,
+ };
+ // 移除多余字段
+ if (!(data.couponId > 0)) {
+ delete data2.couponId;
+ }
+ if (!(data.addressId > 0)) {
+ delete data2.addressId;
+ }
+ if (!(data.pickUpStoreId > 0)) {
+ delete data2.pickUpStoreId;
+ }
+ if (isEmpty(data.receiverName)) {
+ delete data2.receiverName;
+ }
+ if (isEmpty(data.receiverMobile)) {
+ delete data2.receiverMobile;
+ }
+ if (!(data.combinationActivityId > 0)) {
+ delete data2.combinationActivityId;
+ }
+ if (!(data.combinationHeadId > 0)) {
+ delete data2.combinationHeadId;
+ }
+ if (!(data.seckillActivityId > 0)) {
+ delete data2.seckillActivityId;
+ }
+ // 解决 SpringMVC 接受 List
- 参数的问题
+ delete data2.items;
+ for (let i = 0; i < data.items.length; i++) {
+ data2[encodeURIComponent('items[' + i + '' + '].skuId')] = data.items[i].skuId + '';
+ data2[encodeURIComponent('items[' + i + '' + '].count')] = data.items[i].count + '';
+ if (data.items[i].cartId) {
+ data2[encodeURIComponent('items[' + i + '' + '].cartId')] = data.items[i].cartId + '';
+ }
+ }
+ const queryString = Object.keys(data2)
+ .map((key) => key + '=' + data2[key])
+ .join('&');
+ return request({
+ url: `/trade/order/clerkOrder?${queryString}`,
+ method: 'GET',
+ custom: {
+ showError: true,
+ showLoading: true,
+ },
+ });
+ },
+ // 创建订单
+ createOrder: (data) => {
+ return request({
+ url: `/trade/order/create`,
+ method: 'POST',
+ data,
+ });
+ },
+ // 创建陪玩订单
+ createWorkerOrder: (data) => {
+ return request({
+ url: `/trade/order/createWorkerOrder`,
+ method: 'POST',
+ data,
+ });
+ },
+ // 获得订单
+ getOrder: (id) => {
+ return request({
+ url: `/trade/order/get-detail`,
+ method: 'GET',
+ params: {
+ id,
+ },
+ custom: {
+ showLoading: false,
+ },
+ });
+ },
+ // 订单列表
+ getOrderPage: (params) => {
+ return request({
+ url: '/trade/order/page',
+ method: 'GET',
+ params,
+ custom: {
+ auth: true,
+ showLoading: false,
+ },
+ });
+ },
+ // 订单列表
+ getWorkerOrderPage: (params) => {
+ return request({
+ url: '/trade/order/worker/page',
+ method: 'GET',
+ params,
+ custom: {
+ auth: true,
+ showLoading: false,
+ },
+ });
+ },
+ // 订单列表
+ getBlindOrderPage: (params) => {
+ return request({
+ url: '/trade/order/blind/page',
+ method: 'GET',
+ params,
+ custom: {
+ auth: true,
+ showLoading: false,
+ },
+ });
+ },
+ // 确认收货
+ receiveOrder: (id) => {
+ return request({
+ url: `/trade/order/receive`,
+ method: 'PUT',
+ params: {
+ id,
+ },
+ });
+ },
+ // 确认接单
+ deliveryOrder: (id) => {
+ return request({
+ url: `/trade/order/delivery`,
+ method: 'PUT',
+ data: {
+ id: id,
+ logisticsId: 0
+ },
+ });
+ },
+ // 取消订单
+ cancelOrder: (id) => {
+ return request({
+ url: `/trade/order/cancel`,
+ method: 'DELETE',
+ params: {
+ id,
+ },
+ });
+ },
+ // 删除订单
+ deleteOrder: (id) => {
+ return request({
+ url: `/trade/order/delete`,
+ method: 'DELETE',
+ params: {
+ id,
+ },
+ });
+ },
+ // 获得交易订单的物流轨迹
+ getOrderExpressTrackList: (id) => {
+ return request({
+ url: `/trade/order/get-express-track-list`,
+ method: 'GET',
+ params: {
+ id,
+ },
+ });
+ },
+ // 获得交易订单数量
+ getOrderCount: () => {
+ return request({
+ url: '/trade/order/get-count',
+ method: 'GET',
+ custom: {
+ showLoading: false,
+ auth: true,
+ },
+ });
+ },
+ // 创建单个评论
+ createOrderItemComment: (data) => {
+ return request({
+ url: `/trade/order/item/create-comment`,
+ method: 'POST',
+ data,
+ custom: {
+ showSuccess: true,
+ successMsg: '评价成功'
+ },
+ });
+ },
+};
+
+export default OrderApi;
diff --git a/sheep/api/worker/clerk.js b/sheep/api/worker/clerk.js
new file mode 100644
index 0000000..cf2c7be
--- /dev/null
+++ b/sheep/api/worker/clerk.js
@@ -0,0 +1,195 @@
+import request from '@/sheep/request';
+
+const ClerkApi = {
+ // 创建店员申请
+ createClerkApply: (data) => {
+ return request({
+ url: '/worker/clerk-apply/create',
+ method: 'POST',
+ data,
+ custom: {
+ showSuccess: true,
+ successMsg: '提交成功'
+ },
+ });
+ },
+ // 更新店员申请
+ updateClerkApply: (data) => {
+ return request({
+ url: '/worker/clerk-apply/update',
+ method: 'PUT',
+ data,
+ custom: {
+ showSuccess: true,
+ successMsg: '提交成功'
+ },
+ });
+ },
+ // 更新店员在线状态
+ updateOnlineStatus: (data) => {
+ return request({
+ url: '/worker/clerk-apply/updateOnlineStatus',
+ method: 'PUT',
+ data,
+ custom: {
+ showSuccess: true,
+ successMsg: '提交成功'
+ },
+ });
+ },
+ // 获得店员申请
+ getClerkApply: (id) => {
+ return request({
+ url: '/worker/clerk-apply/get',
+ method: 'GET',
+ params: { id },
+ custom: {
+ auth: true,
+ showLoading: false,
+ },
+ });
+ },
+ // 获得店员等级
+ getClerkLevel: (id) => {
+ return request({
+ url: '/worker/clerk-apply/getClerkLevel',
+ method: 'GET',
+ params: { id },
+ custom: {
+ auth: true,
+ showLoading: false,
+ },
+ });
+ },
+ // 获得店员申请
+ getClerk: (params) => {
+ return request({
+ url: '/worker/clerk/get',
+ method: 'GET',
+ params,
+ custom: {
+ auth: false,
+ showLoading: false,
+ },
+ });
+ },
+ // 获得店员盲盒
+ getClerkBlind: () => {
+ return request({
+ url: '/worker/clerk/getClerkBlind',
+ method: 'GET',
+ custom: {
+ auth: false,
+ showLoading: false,
+ },
+ });
+ },
+ // 获得商品分类列表
+ getCategoryListByParentId: (parentId) => {
+ return request({
+ url: '/worker/category/getCategoryListByParentId',
+ method: 'GET',
+ params: { parentId },
+ custom: {
+ auth: false,
+ showLoading: false,
+ },
+ });
+ },
+
+ // 保存技能管理
+ saveGoodsList: (data) => {
+ return request({
+ url: '/worker/clerk-apply/save',
+ method: 'PUT',
+ data,
+ custom: {
+ showSuccess: true,
+ successMsg: '保存成功'
+ },
+ });
+ },
+ // 获得店员列表
+ getClerkPage: (params) => {
+ return request({
+ url: '/worker/clerk/page',
+ method: 'GET',
+ params,
+ custom: {
+ auth: false,
+ showLoading: false,
+ },
+ });
+ },
+ // 获得店员关注列表
+ getClerkFansPage: (params) => {
+ return request({
+ url: '/worker/clerk-fans/page',
+ method: 'GET',
+ params,
+ custom: {
+ auth: false,
+ showLoading: false,
+ },
+ });
+ },
+ // 获得首页信息
+ getHomeData: () => {
+ return request({
+ url: '/worker/clerk/getHomeData',
+ method: 'GET',
+ custom: {
+ auth: false,
+ showLoading: false,
+ },
+ });
+ },
+ // 获得首页信息
+ getClerkList: () => {
+ return request({
+ url: '/worker/clerk/getClerkList',
+ method: 'GET',
+ custom: {
+ auth: true,
+ showLoading: false,
+ },
+ });
+ },
+ // 获得榜单信息
+ getWeekTopList: () => {
+ return request({
+ url: '/worker/clerk/getWeekTopList',
+ method: 'GET',
+ custom: {
+ auth: false,
+ showLoading: false,
+ },
+ });
+ },
+ // 获得店员申请列表
+ getClerkApplyPage: (params) => {
+ return request({
+ url: '/worker/clerk-apply/page',
+ method: 'GET',
+ params,
+ custom: {
+ auth: true,
+ showLoading: false,
+ },
+ });
+ },
+ // 获得商品列表
+ getGoodsList: (id) => {
+ return request({
+ url: '/worker/clerk-apply/list',
+ method: 'GET',
+ params: { id },
+ custom: {
+ auth: true,
+ showLoading: false,
+ },
+ });
+ },
+};
+
+export default ClerkApi;
diff --git a/sheep/api/worker/reward.js b/sheep/api/worker/reward.js
new file mode 100644
index 0000000..d269732
--- /dev/null
+++ b/sheep/api/worker/reward.js
@@ -0,0 +1,60 @@
+import request from '@/sheep/request';
+
+const RewardApi = {
+ // 获得礼物列表
+ getGiftList: () => {
+ return request({
+ url: '/worker/gift/getList',
+ method: 'GET',
+ custom: {
+ auth: true,
+ showLoading: false,
+ },
+ });
+ },
+ // 获得打赏礼物列表
+ getRewardGiftList: (params) => {
+ return request({
+ url: '/worker/reward/getGiftList',
+ method: 'GET',
+ params: params,
+ custom: {
+ auth: false,
+ showLoading: false,
+ },
+ });
+ },
+ // 获得礼物列表
+ getTopList: () => {
+ return request({
+ url: '/worker/reward/getTopList',
+ method: 'GET',
+ custom: {
+ auth: false,
+ showLoading: false,
+ },
+ });
+ },
+ // 创建打赏订单
+ createRewardOrder: (data) => {
+ return request({
+ url: `/worker/reward/createOrder`,
+ method: 'POST',
+ data,
+ });
+ },
+ // 获得打赏分页
+ getRewardPage: (params) => {
+ return request({
+ url: '/worker/reward/page',
+ method: 'GET',
+ params,
+ custom: {
+ auth: true,
+ showLoading: false,
+ },
+ });
+ },
+};
+
+export default RewardApi;
diff --git a/sheep/api/worker/trend.js b/sheep/api/worker/trend.js
new file mode 100644
index 0000000..3e33e73
--- /dev/null
+++ b/sheep/api/worker/trend.js
@@ -0,0 +1,100 @@
+import request from '@/sheep/request';
+
+const TrendApi = {
+ // 发布动态
+ createTrend: (data) => {
+ return request({
+ url: '/worker/trend/create',
+ method: 'POST',
+ data,
+ custom: {
+ auth: true,
+ showSuccess: true,
+ successMsg: '发布成功,请等待管理员审核'
+ },
+ });
+ },
+ // 动态点赞
+ createTrendLike: (data) => {
+ return request({
+ url: '/worker/trend-like/create',
+ method: 'POST',
+ data,
+ custom: {
+ auth: true,
+ showSuccess: false,
+ showLoading: false,
+ successMsg: '点赞成功'
+ },
+ });
+ },
+ // 删除动态
+ deleteTrendLike: (id) => {
+ return request({
+ url: '/worker/trend/delete',
+ method: 'DELETE',
+ params: {
+ id,
+ },
+ custom: {
+ auth: true,
+ showSuccess: true,
+ showLoading: false,
+ successMsg: '删除成功'
+ },
+ });
+ },
+ // 获得动态详情
+ getTrend: (id) => {
+ return request({
+ url: '/worker/trend/get',
+ method: 'GET',
+ params: { id },
+ custom: {
+ auth: false,
+ showLoading: false,
+ },
+ });
+ },
+ // 店员关注
+ createClerkFans: (data) => {
+ return request({
+ url: '/worker/clerk-fans/create',
+ method: 'POST',
+ data,
+ custom: {
+ auth: true,
+ showSuccess: false,
+ showLoading: false,
+ successMsg: '关注成功'
+ },
+ });
+ },
+ // 获得动态分页
+ getTrendPage: (params) => {
+ return request({
+ url: '/worker/trend/page',
+ method: 'GET',
+ params,
+ custom: {
+ auth: false,
+ showLoading: false,
+ },
+ });
+ },
+ // 获得动态分页
+ getMyTrendPage: (params) => {
+ return request({
+ url: '/worker/trend/myPage',
+ method: 'GET',
+ params,
+ custom: {
+ auth: true,
+ showLoading: false,
+ },
+ });
+ },
+
+};
+
+export default TrendApi;
diff --git a/sheep/components/s-activity-pop/s-activity-pop.vue b/sheep/components/s-activity-pop/s-activity-pop.vue
new file mode 100644
index 0000000..432dc45
--- /dev/null
+++ b/sheep/components/s-activity-pop/s-activity-pop.vue
@@ -0,0 +1,105 @@
+
+
+
+
+ 营销活动
+
+
+
+ 满减
+
+
+ {{ formatRewardActivityRule(state.activityMap[item.id], rule) }}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sheep/components/s-address-item/s-address-item.vue b/sheep/components/s-address-item/s-address-item.vue
new file mode 100644
index 0000000..45e361f
--- /dev/null
+++ b/sheep/components/s-address-item/s-address-item.vue
@@ -0,0 +1,110 @@
+
+
+
+
+
+
+ {{ props.item.areaName }}
+
+
+ {{ props.item.detailAddress }}
+
+ {{ props.item.name }} {{ props.item.mobile }}
+
+
+ 请选择收货地址
+
+
+
+
+
+
+
+
+
+
diff --git a/sheep/components/s-auth-modal/components/account-login.vue b/sheep/components/s-auth-modal/components/account-login.vue
new file mode 100644
index 0000000..579614c
--- /dev/null
+++ b/sheep/components/s-auth-modal/components/account-login.vue
@@ -0,0 +1,107 @@
+
+
+
+
+
+
+
+ 短信登录
+
+ 账号登录
+
+ 如果未设置过密码,请点击忘记密码
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sheep/components/s-auth-modal/components/change-mobile.vue b/sheep/components/s-auth-modal/components/change-mobile.vue
new file mode 100644
index 0000000..f4dd5f1
--- /dev/null
+++ b/sheep/components/s-auth-modal/components/change-mobile.vue
@@ -0,0 +1,127 @@
+
+
+
+
+
+
+ {{ userInfo.mobile ? '更换手机号' : '绑定手机号' }}
+
+ 为了您的账号安全,请使用本人手机号码
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sheep/components/s-auth-modal/components/change-password.vue b/sheep/components/s-auth-modal/components/change-password.vue
new file mode 100644
index 0000000..b02ea02
--- /dev/null
+++ b/sheep/components/s-auth-modal/components/change-password.vue
@@ -0,0 +1,106 @@
+
+
+
+
+
+ 修改密码
+ 如密码丢失或未设置,请点击忘记密码重新设置
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sheep/components/s-auth-modal/components/chat-authorization.vue b/sheep/components/s-auth-modal/components/chat-authorization.vue
new file mode 100644
index 0000000..b2fc774
--- /dev/null
+++ b/sheep/components/s-auth-modal/components/chat-authorization.vue
@@ -0,0 +1,170 @@
+
+
+
+
+
+
+ 完善资料
+
+ 完善您的交友名片、个人相册
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sheep/components/s-auth-modal/components/formImage.vue b/sheep/components/s-auth-modal/components/formImage.vue
new file mode 100644
index 0000000..a6045f6
--- /dev/null
+++ b/sheep/components/s-auth-modal/components/formImage.vue
@@ -0,0 +1,73 @@
+
+
+
+ 上传相册
+ {{imgList.length}}/{{number}}
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/sheep/components/s-auth-modal/components/formQrcode.vue b/sheep/components/s-auth-modal/components/formQrcode.vue
new file mode 100644
index 0000000..5f2ded4
--- /dev/null
+++ b/sheep/components/s-auth-modal/components/formQrcode.vue
@@ -0,0 +1,88 @@
+
+
+ 交换名片
+
+ {{item.name}}
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/sheep/components/s-auth-modal/components/formSex.vue b/sheep/components/s-auth-modal/components/formSex.vue
new file mode 100644
index 0000000..34b84e0
--- /dev/null
+++ b/sheep/components/s-auth-modal/components/formSex.vue
@@ -0,0 +1,88 @@
+
+
+ 性别
+
+ {{item.name}}
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/sheep/components/s-auth-modal/components/h5-authorization.vue b/sheep/components/s-auth-modal/components/h5-authorization.vue
new file mode 100644
index 0000000..2a907f3
--- /dev/null
+++ b/sheep/components/s-auth-modal/components/h5-authorization.vue
@@ -0,0 +1,194 @@
+
+
+
+
+
+
+ 授权信息
+
+ 完善您的头像、昵称、性别、年龄
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sheep/components/s-auth-modal/components/mp-authorization.vue b/sheep/components/s-auth-modal/components/mp-authorization.vue
new file mode 100644
index 0000000..65efd16
--- /dev/null
+++ b/sheep/components/s-auth-modal/components/mp-authorization.vue
@@ -0,0 +1,203 @@
+
+
+
+
+
+
+ 授权信息
+
+ 完善您的头像、昵称、手机号
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sheep/components/s-auth-modal/components/reset-password.vue b/sheep/components/s-auth-modal/components/reset-password.vue
new file mode 100644
index 0000000..bc1be8b
--- /dev/null
+++ b/sheep/components/s-auth-modal/components/reset-password.vue
@@ -0,0 +1,119 @@
+
+
+
+
+
+ 重置密码
+ 为了您的账号安全,设置密码前请先进行安全验证
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sheep/components/s-auth-modal/components/sms-login.vue b/sheep/components/s-auth-modal/components/sms-login.vue
new file mode 100644
index 0000000..0651b78
--- /dev/null
+++ b/sheep/components/s-auth-modal/components/sms-login.vue
@@ -0,0 +1,119 @@
+
+
+
+
+
+
+ 短信登录
+
+ 账号登录
+
+
+ 未注册的手机号,验证后自动注册账号
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sheep/components/s-auth-modal/index.scss b/sheep/components/s-auth-modal/index.scss
new file mode 100644
index 0000000..c4424e7
--- /dev/null
+++ b/sheep/components/s-auth-modal/index.scss
@@ -0,0 +1,151 @@
+@keyframes title-animation {
+ 0% {
+ font-size: 32rpx;
+ }
+ 100% {
+ font-size: 36rpx;
+ }
+}
+
+.login-wrap {
+ padding: 50rpx 34rpx;
+ min-height: 500rpx;
+ background-color: #fff;
+ border-radius: 20rpx 20rpx 0 0;
+}
+
+.head-box {
+ .head-title {
+ min-width: 160rpx;
+ font-size: 36rpx;
+ font-weight: bold;
+ color: #333333;
+ line-height: 36rpx;
+ }
+ .head-title-active {
+ width: 160rpx;
+ font-size: 32rpx;
+ font-weight: 600;
+ color: #999;
+ line-height: 36rpx;
+ }
+ .head-title-animation {
+ animation-name: title-animation;
+ animation-duration: 0.1s;
+ animation-timing-function: ease-out;
+ animation-fill-mode: forwards;
+ }
+ .head-title-line {
+ position: relative;
+ &::before {
+ content: '';
+ width: 1rpx;
+ height: 34rpx;
+ background-color: #e4e7ed;
+ position: absolute;
+ left: -30rpx;
+ top: 50%;
+ transform: translateY(-50%);
+ }
+ }
+ .head-subtitle {
+ font-size: 26rpx;
+ font-weight: 400;
+ color: #afb6c0;
+ text-align: left;
+ display: flex;
+ }
+}
+
+// .code-btn[disabled] {
+// background-color: #fff;
+// }
+.code-btn-start {
+ width: 160rpx;
+ height: 56rpx;
+ line-height: normal;
+ border: 2rpx solid var(--ui-BG-Main);
+ border-radius: 28rpx;
+ font-size: 26rpx;
+ font-weight: 400;
+ color: var(--ui-BG-Main);
+ opacity: 1;
+}
+
+.forgot-btn {
+ width: 160rpx;
+ line-height: 56rpx;
+ font-size: 30rpx;
+ font-weight: 500;
+ color: #999;
+}
+
+.login-btn-start {
+ width: 158rpx;
+ height: 56rpx;
+ line-height: normal;
+ background: linear-gradient(90deg, var(--ui-BG-Main), var(--ui-BG-Main-gradient));
+ border-radius: 28rpx;
+ font-size: 26rpx;
+ font-weight: 500;
+ color: #fff;
+}
+
+.type-btn {
+ padding: 20rpx;
+ margin: 40rpx auto;
+ width: 200rpx;
+ font-size: 30rpx;
+ font-weight: 500;
+ color: #999999;
+}
+
+.auto-login-box {
+ width: 100%;
+ .auto-login-btn {
+ width: 68rpx;
+ height: 68rpx;
+ border-radius: 50%;
+ margin: 0 30rpx;
+ }
+ .auto-login-img {
+ width: 68rpx;
+ height: 68rpx;
+ border-radius: 50%;
+ }
+}
+
+.agreement-box {
+ margin: 80rpx auto 0;
+ .protocol-check {
+ transform: scale(0.7);
+ }
+ .agreement-text {
+ font-size: 26rpx;
+ font-weight: 500;
+ color: #999999;
+ .tcp-text {
+ color: var(--ui-BG-Main);
+ }
+ }
+}
+
+// 修改密码
+.editPwd-btn-box {
+ .save-btn {
+ width: 690rpx;
+ line-height: 70rpx;
+ background: linear-gradient(90deg, var(--ui-BG-Main), var(--ui-BG-Main-gradient));
+ border-radius: 35rpx;
+ font-size: 28rpx;
+ font-weight: 500;
+ color: #ffffff;
+ }
+ .forgot-btn {
+ width: 690rpx;
+ line-height: 70rpx;
+ font-size: 28rpx;
+ font-weight: 500;
+ color: #999999;
+ }
+}
diff --git a/sheep/components/s-auth-modal/s-auth-modal.vue b/sheep/components/s-auth-modal/s-auth-modal.vue
new file mode 100644
index 0000000..0d591a9
--- /dev/null
+++ b/sheep/components/s-auth-modal/s-auth-modal.vue
@@ -0,0 +1,256 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sheep/components/s-block-item/s-block-item.vue b/sheep/components/s-block-item/s-block-item.vue
new file mode 100644
index 0000000..5e65b36
--- /dev/null
+++ b/sheep/components/s-block-item/s-block-item.vue
@@ -0,0 +1,81 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sheep/components/s-block/s-block.vue b/sheep/components/s-block/s-block.vue
new file mode 100644
index 0000000..152b8a6
--- /dev/null
+++ b/sheep/components/s-block/s-block.vue
@@ -0,0 +1,54 @@
+
+
+
+
+
+
diff --git a/sheep/components/s-count-down/s-count-down.vue b/sheep/components/s-count-down/s-count-down.vue
new file mode 100644
index 0000000..98b3a1f
--- /dev/null
+++ b/sheep/components/s-count-down/s-count-down.vue
@@ -0,0 +1,173 @@
+
+
+ {{ tipText }}
+ {{ day }}{{bgColor.isDay?'天':''}}
+ {{ dayText }}
+ {{ hour }}
+ {{ hourText }}
+ {{ minute }}
+ {{ minuteText }}
+ {{ second }}
+ {{ secondText }}
+
+
+
+
+
+
\ No newline at end of file
diff --git a/sheep/components/s-coupon-block/s-coupon-block.vue b/sheep/components/s-coupon-block/s-coupon-block.vue
new file mode 100644
index 0000000..89a0f0e
--- /dev/null
+++ b/sheep/components/s-coupon-block/s-coupon-block.vue
@@ -0,0 +1,176 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/sheep/components/s-coupon-card/s-coupon-card.vue b/sheep/components/s-coupon-card/s-coupon-card.vue
new file mode 100644
index 0000000..dac69e3
--- /dev/null
+++ b/sheep/components/s-coupon-card/s-coupon-card.vue
@@ -0,0 +1,102 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/sheep/components/s-coupon-get/s-coupon-get.vue b/sheep/components/s-coupon-get/s-coupon-get.vue
new file mode 100644
index 0000000..6df6b55
--- /dev/null
+++ b/sheep/components/s-coupon-get/s-coupon-get.vue
@@ -0,0 +1,109 @@
+
+
+
+
+ 优惠券
+
+ 可使用优惠券
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sheep/components/s-coupon-list/s-coupon-list.vue b/sheep/components/s-coupon-list/s-coupon-list.vue
new file mode 100644
index 0000000..411a4c0
--- /dev/null
+++ b/sheep/components/s-coupon-list/s-coupon-list.vue
@@ -0,0 +1,205 @@
+
+
+
+
+ {{ data.discountType === 1 ? '满减券' : '折扣券' }}
+
+
+
+
+ {{ data.name }}
+
+
+
+ ¥
+
+ {{
+ data.discountType === 1
+ ? fen2yuan(data.discountPrice)
+ : data.discountPercent / 10.0
+ }}
+
+ 折
+
+
+
+
+
+ 有效期:领取后 {{ data.fixedEndTerm }} 天内可用
+
+
+ 有效期: {{ sheep.$helper.timeFormat(data.validStartTime, 'yyyy-mm-dd') }} 至
+ {{ sheep.$helper.timeFormat(data.validEndTime, 'yyyy-mm-dd') }}
+
+
+ 满 {{ fen2yuan(data.usePrice) }} 可用
+
+
+
+
+
+
+
+
+ {{ data.description }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/sheep/components/s-coupon-select/s-coupon-select.vue b/sheep/components/s-coupon-select/s-coupon-select.vue
new file mode 100644
index 0000000..3572e1b
--- /dev/null
+++ b/sheep/components/s-coupon-select/s-coupon-select.vue
@@ -0,0 +1,140 @@
+
+
+
+
+ 优惠券
+
+
+
+
+
+
+
+ 可用原因:
+ {{ item.description || '已达到使用门槛' }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sheep/components/s-custom-navbar/components/navbar-item.vue b/sheep/components/s-custom-navbar/components/navbar-item.vue
new file mode 100644
index 0000000..fce7ce7
--- /dev/null
+++ b/sheep/components/s-custom-navbar/components/navbar-item.vue
@@ -0,0 +1,66 @@
+
+
+
+
+
+ {{ data.text }}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sheep/components/s-custom-navbar/components/navbar.vue b/sheep/components/s-custom-navbar/components/navbar.vue
new file mode 100644
index 0000000..36050ec
--- /dev/null
+++ b/sheep/components/s-custom-navbar/components/navbar.vue
@@ -0,0 +1,314 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sheep/components/s-custom-navbar/s-custom-navbar.vue b/sheep/components/s-custom-navbar/s-custom-navbar.vue
new file mode 100644
index 0000000..aabc215
--- /dev/null
+++ b/sheep/components/s-custom-navbar/s-custom-navbar.vue
@@ -0,0 +1,207 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sheep/components/s-discount-list/s-discount-list.vue b/sheep/components/s-discount-list/s-discount-list.vue
new file mode 100644
index 0000000..22fbd43
--- /dev/null
+++ b/sheep/components/s-discount-list/s-discount-list.vue
@@ -0,0 +1,114 @@
+
+
+
+ 活动优惠
+
+
+
+ 共{{ item.goods_ids.length }}件,
+
+ 满{{ item.discount_rule.full }}打{{ item.discount_rule.discount }}折,已减
+
+ 满赠
+
+ 满{{ item.discount_rule.full }}减{{ item.discount_rule.discount }},已减
+
+ ¥{{ item.promo_discount_money || '0.00' }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sheep/components/s-empty/s-empty.vue b/sheep/components/s-empty/s-empty.vue
new file mode 100644
index 0000000..16e40ed
--- /dev/null
+++ b/sheep/components/s-empty/s-empty.vue
@@ -0,0 +1,93 @@
+
+
+
+
+ {{ text }}
+
+
+
+
+
+
+
+
diff --git a/sheep/components/s-float-menu/s-float-menu.vue b/sheep/components/s-float-menu/s-float-menu.vue
new file mode 100644
index 0000000..b53db00
--- /dev/null
+++ b/sheep/components/s-float-menu/s-float-menu.vue
@@ -0,0 +1,88 @@
+
+
+
+
+
+
+
+
+
diff --git a/sheep/components/s-goods-card/s-goods-card.vue b/sheep/components/s-goods-card/s-goods-card.vue
new file mode 100644
index 0000000..59f2bf1
--- /dev/null
+++ b/sheep/components/s-goods-card/s-goods-card.vue
@@ -0,0 +1,286 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sheep/components/s-goods-column/s-goods-column.vue b/sheep/components/s-goods-column/s-goods-column.vue
new file mode 100644
index 0000000..228c64e
--- /dev/null
+++ b/sheep/components/s-goods-column/s-goods-column.vue
@@ -0,0 +1,751 @@
+
+
+
+
+
+
+
+
+
+
+
+ {{ data.title || data.name }}
+
+
+ {{ priceUnit }}
+ {{ isArray(data.price) ? fen2yuan(data.price[0]) : fen2yuan(data.price) }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ data.title || data.name }}
+
+
+ {{ priceUnit }}
+ {{ isArray(data.price) ? fen2yuan(data.price[0]) : fen2yuan(data.price) }}
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ data.title || data.name }}
+
+
+ {{ data.subtitle || data.introduction }}
+
+
+
+
+ {{ item.title }}
+
+
+
+
+
+ {{ priceUnit }}
+ {{ isArray(data.price) ? fen2yuan(data.price[0]) : fen2yuan(data.price) }}
+
+
+
+ {{ priceUnit }}
+ {{ fen2yuan(data.marketPrice) }}
+
+
+
+
+ {{ salesAndStock }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 秒杀
+
+ 拼团
+
+
+
+
+
+ {{ data.title || data.name }}
+
+
+ {{ data.subtitle || data.introduction }}
+
+
+
+
+
+
+ {{ item.title }}
+
+
+
+
+
+ {{ priceUnit }}
+ {{ isArray(data.price) ? fen2yuan(data.price[0]) : fen2yuan(data.price) }}
+
+
+ {{ priceUnit }}
+ {{ fen2yuan(data.marketPrice) }}
+
+
+
+ {{ salesAndStock }}
+
+
+
+
+
+ 去购买
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ data.title || data.name }}
+
+
+ {{ data.subtitle || data.introduction }}
+
+
+
+
+
+
+ {{ item.title }}
+
+
+
+
+
+ {{ priceUnit }}
+ {{ isArray(data.price) ? fen2yuan(data.price[0]) : fen2yuan(data.price) }}
+
+
+ {{ priceUnit }}
+ {{ fen2yuan(data.marketPrice) }}
+
+
+
+ {{ salesAndStock }}
+
+
+
+
+ 去购买
+
+
+
+
+
+
+
diff --git a/sheep/components/s-goods-item/s-goods-item.vue b/sheep/components/s-goods-item/s-goods-item.vue
new file mode 100644
index 0000000..456bb16
--- /dev/null
+++ b/sheep/components/s-goods-item/s-goods-item.vue
@@ -0,0 +1,181 @@
+
+
+
+
+
+
+
+
+
+
+ {{ title }}
+ {{ skuString }}
+
+
+
+
+
+
+ ¥{{ fen2yuan(price) }}
+
+ x {{ num }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sheep/components/s-goods-scroll/s-goods-scroll.vue b/sheep/components/s-goods-scroll/s-goods-scroll.vue
new file mode 100644
index 0000000..175cc66
--- /dev/null
+++ b/sheep/components/s-goods-scroll/s-goods-scroll.vue
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sheep/components/s-goods-shelves/s-goods-shelves.vue b/sheep/components/s-goods-shelves/s-goods-shelves.vue
new file mode 100644
index 0000000..e2ce60a
--- /dev/null
+++ b/sheep/components/s-goods-shelves/s-goods-shelves.vue
@@ -0,0 +1,147 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sheep/components/s-groupon-block/s-groupon-block.vue b/sheep/components/s-groupon-block/s-groupon-block.vue
new file mode 100644
index 0000000..d7e6fcf
--- /dev/null
+++ b/sheep/components/s-groupon-block/s-groupon-block.vue
@@ -0,0 +1,171 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/sheep/components/s-hotzone-block/s-hotzone-block.vue b/sheep/components/s-hotzone-block/s-hotzone-block.vue
new file mode 100644
index 0000000..246d6d4
--- /dev/null
+++ b/sheep/components/s-hotzone-block/s-hotzone-block.vue
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sheep/components/s-image-banner/s-image-banner.vue b/sheep/components/s-image-banner/s-image-banner.vue
new file mode 100644
index 0000000..478e7af
--- /dev/null
+++ b/sheep/components/s-image-banner/s-image-banner.vue
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+
+
diff --git a/sheep/components/s-image-block/s-image-block.vue b/sheep/components/s-image-block/s-image-block.vue
new file mode 100644
index 0000000..c898749
--- /dev/null
+++ b/sheep/components/s-image-block/s-image-block.vue
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/sheep/components/s-image-cube/s-image-cube.vue b/sheep/components/s-image-cube/s-image-cube.vue
new file mode 100644
index 0000000..9794d8f
--- /dev/null
+++ b/sheep/components/s-image-cube/s-image-cube.vue
@@ -0,0 +1,110 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sheep/components/s-layout/s-layout.vue b/sheep/components/s-layout/s-layout.vue
new file mode 100644
index 0000000..3fc666f
--- /dev/null
+++ b/sheep/components/s-layout/s-layout.vue
@@ -0,0 +1,246 @@
+
+
+
+
+ emits('search', e)"
+ :defaultSearch="defaultSearch"
+ />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sheep/components/s-line-block/s-line-block.vue b/sheep/components/s-line-block/s-line-block.vue
new file mode 100644
index 0000000..c0628f9
--- /dev/null
+++ b/sheep/components/s-line-block/s-line-block.vue
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
diff --git a/sheep/components/s-live-block/s-live-block.vue b/sheep/components/s-live-block/s-live-block.vue
new file mode 100644
index 0000000..9d1ad03
--- /dev/null
+++ b/sheep/components/s-live-block/s-live-block.vue
@@ -0,0 +1,144 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sheep/components/s-live-card/s-live-card.vue b/sheep/components/s-live-card/s-live-card.vue
new file mode 100644
index 0000000..9cefee0
--- /dev/null
+++ b/sheep/components/s-live-card/s-live-card.vue
@@ -0,0 +1,234 @@
+
+
+
+
+
+
+ {{ state.liveStatus[data.status].title }}
+
+
+
+
+ {{ data.name }}
+
+
+ 主播:{{ data.anchor_name }}
+
+
+
+
+
+
+
+ {{ state.liveStatus[data.status].title }}
+
+
+
+
+ {{ data.name }}
+
+
+ 主播:{{ data.anchor_name }}
+
+
+
+
+
+
+
+
diff --git a/sheep/components/s-menu-button/s-menu-button.vue b/sheep/components/s-menu-button/s-menu-button.vue
new file mode 100644
index 0000000..ef647b8
--- /dev/null
+++ b/sheep/components/s-menu-button/s-menu-button.vue
@@ -0,0 +1,343 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ state.cur + 1 }} / {{ menuList.length }}
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/sheep/components/s-menu-grid/s-menu-grid.vue b/sheep/components/s-menu-grid/s-menu-grid.vue
new file mode 100644
index 0000000..d05a49d
--- /dev/null
+++ b/sheep/components/s-menu-grid/s-menu-grid.vue
@@ -0,0 +1,104 @@
+
+
+
+
+
+
+
+
+ {{ item.badge.text }}
+
+
+
+
+
+
+ {{ item.title }}
+
+
+ {{ item.subtitle }}
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/sheep/components/s-menu-list/s-menu-list.vue b/sheep/components/s-menu-list/s-menu-list.vue
new file mode 100644
index 0000000..ecbb396
--- /dev/null
+++ b/sheep/components/s-menu-list/s-menu-list.vue
@@ -0,0 +1,66 @@
+
+
+
+
+
+
+
+
diff --git a/sheep/components/s-menu-tools/s-menu-tools.vue b/sheep/components/s-menu-tools/s-menu-tools.vue
new file mode 100644
index 0000000..147ead2
--- /dev/null
+++ b/sheep/components/s-menu-tools/s-menu-tools.vue
@@ -0,0 +1,118 @@
+
+
+
+
+
+ 快捷菜单
+
+
+
+
+ {{ item.title }}
+
+
+
+
+
+
+
+
+
+
diff --git a/sheep/components/s-notice-block/s-notice-block.vue b/sheep/components/s-notice-block/s-notice-block.vue
new file mode 100644
index 0000000..e7d74a0
--- /dev/null
+++ b/sheep/components/s-notice-block/s-notice-block.vue
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sheep/components/s-order-card/s-order-card.vue b/sheep/components/s-order-card/s-order-card.vue
new file mode 100644
index 0000000..b3d851b
--- /dev/null
+++ b/sheep/components/s-order-card/s-order-card.vue
@@ -0,0 +1,132 @@
+
+
+
+
+
+
+
+
diff --git a/sheep/components/s-popup-image/s-popup-image.vue b/sheep/components/s-popup-image/s-popup-image.vue
new file mode 100644
index 0000000..b10f477
--- /dev/null
+++ b/sheep/components/s-popup-image/s-popup-image.vue
@@ -0,0 +1,85 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sheep/components/s-richtext-block/s-richtext-block.vue b/sheep/components/s-richtext-block/s-richtext-block.vue
new file mode 100644
index 0000000..4daa264
--- /dev/null
+++ b/sheep/components/s-richtext-block/s-richtext-block.vue
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
diff --git a/sheep/components/s-search-block/s-search-block.vue b/sheep/components/s-search-block/s-search-block.vue
new file mode 100644
index 0000000..1e9c2b5
--- /dev/null
+++ b/sheep/components/s-search-block/s-search-block.vue
@@ -0,0 +1,164 @@
+
+
+
+
+
+ {{ placeholder }}
+
+
+
+
+
+ {{ item }}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sheep/components/s-seckill-block/s-seckill-block.vue b/sheep/components/s-seckill-block/s-seckill-block.vue
new file mode 100644
index 0000000..bfc61be
--- /dev/null
+++ b/sheep/components/s-seckill-block/s-seckill-block.vue
@@ -0,0 +1,182 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/sheep/components/s-select-groupon-sku/s-select-groupon-sku.vue b/sheep/components/s-select-groupon-sku/s-select-groupon-sku.vue
new file mode 100644
index 0000000..6259a08
--- /dev/null
+++ b/sheep/components/s-select-groupon-sku/s-select-groupon-sku.vue
@@ -0,0 +1,472 @@
+
+
+
+
+
+
+
+
+
+ {{ property.name }}
+
+
+
+
+
+ 购买数量
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sheep/components/s-select-seckill-sku/s-select-seckill-sku.vue b/sheep/components/s-select-seckill-sku/s-select-seckill-sku.vue
new file mode 100644
index 0000000..99b28a5
--- /dev/null
+++ b/sheep/components/s-select-seckill-sku/s-select-seckill-sku.vue
@@ -0,0 +1,431 @@
+
+
+
+
+
+
+
+
+
+
+ {{ property.name }}
+
+
+
+
+
+ 购买数量
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sheep/components/s-select-sku/s-select-sku.vue b/sheep/components/s-select-sku/s-select-sku.vue
new file mode 100644
index 0000000..b339d4a
--- /dev/null
+++ b/sheep/components/s-select-sku/s-select-sku.vue
@@ -0,0 +1,406 @@
+
+
+
+
+
+
+
+
+
+
+
+ {{ property.name }}
+
+
+
+
+
+ 购买数量
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/sheep/components/s-share-modal/canvas-poster/index.vue b/sheep/components/s-share-modal/canvas-poster/index.vue
new file mode 100644
index 0000000..9e67943
--- /dev/null
+++ b/sheep/components/s-share-modal/canvas-poster/index.vue
@@ -0,0 +1,168 @@
+
+
+
+
+
+
+
+
diff --git a/sheep/components/s-share-modal/canvas-poster/poster/goods.js b/sheep/components/s-share-modal/canvas-poster/poster/goods.js
new file mode 100644
index 0000000..883e4be
--- /dev/null
+++ b/sheep/components/s-share-modal/canvas-poster/poster/goods.js
@@ -0,0 +1,125 @@
+import sheep from '@/sheep';
+import { formatImageUrlProtocol, getWxaQrcode } from './index';
+
+const goods = async (poster) => {
+ const width = poster.width;
+ const userInfo = sheep.$store('user').userInfo;
+ const wxa_qrcode = await getWxaQrcode(poster.shareInfo.path, poster.shareInfo.query);
+ return [
+ {
+ type: 'image',
+ src: formatImageUrlProtocol(sheep.$url.cdn(sheep.$store('app').platform.share.posterInfo.goods_bg)),
+ css: {
+ width,
+ position: 'fixed',
+ 'object-fit': 'contain',
+ top: '0',
+ left: '0',
+ zIndex: -1,
+ },
+ },
+ {
+ type: 'text',
+ text: userInfo.nickname,
+ css: {
+ color: '#333',
+ fontSize: 16,
+ fontFamily: 'sans-serif',
+ position: 'fixed',
+ top: width * 0.06,
+ left: width * 0.22,
+ },
+ },
+ {
+ type: 'image',
+ src: formatImageUrlProtocol(sheep.$url.cdn(userInfo.avatar)),
+ css: {
+ position: 'fixed',
+ left: width * 0.04,
+ top: width * 0.04,
+ width: width * 0.14,
+ height: width * 0.14,
+ },
+ },
+ {
+ type: 'image',
+ src: formatImageUrlProtocol(poster.shareInfo.poster.image),
+ css: {
+ position: 'fixed',
+ left: width * 0.03,
+ top: width * 0.21,
+ width: width * 0.94,
+ height: width * 0.94,
+ },
+ },
+ {
+ type: 'text',
+ text: poster.shareInfo.poster.title,
+ css: {
+ position: 'fixed',
+ left: width * 0.04,
+ top: width * 1.18,
+ color: '#333',
+ fontSize: 14,
+ lineHeight: 15,
+ maxWidth: width * 0.91,
+ },
+ },
+ {
+ type: 'text',
+ text: '¥' + poster.shareInfo.poster.price,
+ css: {
+ position: 'fixed',
+ left: width * 0.04,
+ top: width * 1.31,
+ fontSize: 20,
+ fontFamily: 'OPPOSANS',
+ color: '#333',
+ },
+ },
+ {
+ type: 'text',
+ text:
+ poster.shareInfo.poster.original_price > 0
+ ? '¥' + poster.shareInfo.poster.original_price
+ : '',
+ css: {
+ position: 'fixed',
+ left: width * 0.3,
+ top: width * 1.33,
+ color: '#999',
+ fontSize: 10,
+ fontFamily: 'OPPOSANS',
+ textDecoration: 'line-through',
+ },
+ },
+ // #ifndef MP-WEIXIN
+ {
+ type: 'qrcode',
+ text: poster.shareInfo.link,
+ css: {
+ position: 'fixed',
+ left: width * 0.75,
+ top: width * 1.3,
+ width: width * 0.2,
+ height: width * 0.2,
+ },
+ },
+ // #endif
+ // #ifdef MP-WEIXIN
+ {
+ type: 'image',
+ src: wxa_qrcode,
+ css: {
+ position: 'fixed',
+ left: width * 0.75,
+ top: width * 1.3,
+ width: width * 0.2,
+ height: width * 0.2,
+ },
+ },
+ // #endif
+ ];
+};
+
+export default goods;
diff --git a/sheep/components/s-share-modal/canvas-poster/poster/groupon.js b/sheep/components/s-share-modal/canvas-poster/poster/groupon.js
new file mode 100644
index 0000000..4b33c8c
--- /dev/null
+++ b/sheep/components/s-share-modal/canvas-poster/poster/groupon.js
@@ -0,0 +1,122 @@
+import sheep from '@/sheep';
+import { formatImageUrlProtocol, getWxaQrcode } from './index';
+
+const groupon = async (poster) => {
+ const width = poster.width;
+ const userInfo = sheep.$store('user').userInfo;
+ const wxa_qrcode = await getWxaQrcode(poster.shareInfo.path, poster.shareInfo.query);
+ return [
+ {
+ type: 'image',
+ src: formatImageUrlProtocol(sheep.$url.cdn(sheep.$store('app').platform.share.posterInfo.groupon_bg)),
+ css: {
+ width,
+ position: 'fixed',
+ 'object-fit': 'contain',
+ top: '0',
+ left: '0',
+ zIndex: -1,
+ },
+ },
+ {
+ type: 'text',
+ text: userInfo.nickname,
+ css: {
+ color: '#333',
+ fontSize: 16,
+ fontFamily: 'sans-serif',
+ position: 'fixed',
+ top: width * 0.06,
+ left: width * 0.22,
+ },
+ },
+ {
+ type: 'image',
+ src: formatImageUrlProtocol(sheep.$url.cdn(userInfo.avatar)),
+ css: {
+ position: 'fixed',
+ left: width * 0.04,
+ top: width * 0.04,
+ width: width * 0.14,
+ height: width * 0.14,
+ },
+ },
+ {
+ type: 'image',
+ src: formatImageUrlProtocol(poster.shareInfo.poster.image),
+ css: {
+ position: 'fixed',
+ left: width * 0.03,
+ top: width * 0.21,
+ width: width * 0.94,
+ height: width * 0.94,
+ borderRadius: 10,
+ },
+ },
+ {
+ type: 'text',
+ text: poster.shareInfo.poster.title,
+ css: {
+ color: '#333',
+ fontSize: 14,
+ position: 'fixed',
+ top: width * 1.18,
+ left: width * 0.04,
+ maxWidth: width * 0.91,
+ lineHeight: 5,
+ },
+ },
+ {
+ type: 'text',
+ text: '¥' + poster.shareInfo.poster.price,
+ css: {
+ color: '#ff0000',
+ fontSize: 20,
+ fontFamily: 'OPPOSANS',
+ position: 'fixed',
+ top: width * 1.3,
+ left: width * 0.04,
+ },
+ },
+ {
+ type: 'text',
+ text: '2人团',
+ css: {
+ color: '#fff',
+ fontSize: 12,
+ fontFamily: 'OPPOSANS',
+ position: 'fixed',
+ left: width * 0.84,
+ top: width * 1.3,
+ },
+ },
+ // #ifndef MP-WEIXIN
+ {
+ type: 'qrcode',
+ text: poster.shareInfo.link,
+ css: {
+ position: 'fixed',
+ left: width * 0.5,
+ top: width * 1.3,
+ width: width * 0.2,
+ height: width * 0.2,
+ },
+ },
+ // #endif
+ // #ifdef MP-WEIXIN
+ {
+ type: 'image',
+ src: wxa_qrcode,
+ css: {
+ position: 'fixed',
+ left: width * 0.75,
+ top: width * 1.3,
+ width: width * 0.2,
+ height: width * 0.2,
+ },
+ },
+ // #endif
+ ];
+};
+
+export default groupon;
diff --git a/sheep/components/s-share-modal/canvas-poster/poster/index.js b/sheep/components/s-share-modal/canvas-poster/poster/index.js
new file mode 100644
index 0000000..0724e7f
--- /dev/null
+++ b/sheep/components/s-share-modal/canvas-poster/poster/index.js
@@ -0,0 +1,39 @@
+import user from './user';
+import goods from './goods';
+import groupon from './groupon';
+import SocialApi from '@/sheep/api/member/social';
+
+export function getPosterData(options) {
+ switch (options.shareInfo.poster.type) {
+ case 'user':
+ return user(options);
+ case 'goods':
+ return goods(options);
+ case 'groupon':
+ return groupon(options);
+ }
+}
+
+export function formatImageUrlProtocol(url) {
+ // #ifdef H5
+ // H5平台 https协议下需要转换
+ if (window.location.protocol === 'https:' && url.indexOf('http:') === 0) {
+ url = url.replace('http:', 'https:');
+ }
+ // #endif
+
+ // #ifdef MP-WEIXIN
+ // 小程序平台 需要强制转换为https协议
+ if (url.indexOf('http:') === 0) {
+ url = url.replace('http:', 'https:');
+ }
+ // #endif
+
+ return url;
+}
+
+// 获得微信小程序码 (Base64 image)
+export async function getWxaQrcode(path, query) {
+ const res = await SocialApi.getWxaQrcode(path, query);
+ return 'data:image/png;base64,' + res.data;
+}
diff --git a/sheep/components/s-share-modal/canvas-poster/poster/user.js b/sheep/components/s-share-modal/canvas-poster/poster/user.js
new file mode 100644
index 0000000..5c4d3b9
--- /dev/null
+++ b/sheep/components/s-share-modal/canvas-poster/poster/user.js
@@ -0,0 +1,74 @@
+import sheep from '@/sheep';
+import { formatImageUrlProtocol, getWxaQrcode } from './index';
+
+const user = async (poster) => {
+ const width = poster.width;
+ const userInfo = sheep.$store('user').userInfo;
+ const wxa_qrcode = await getWxaQrcode(poster.shareInfo.path, poster.shareInfo.query);
+ return [
+ {
+ type: 'image',
+ src: formatImageUrlProtocol(sheep.$url.cdn(sheep.$store('app').platform.share.posterInfo.user_bg)),
+ css: {
+ width,
+ position: 'fixed',
+ 'object-fit': 'contain',
+ top: '0',
+ left: '0',
+ zIndex: -1,
+ },
+ },
+ {
+ type: 'text',
+ text: userInfo.nickname,
+ css: {
+ color: '#333',
+ fontSize: 14,
+ textAlign: 'center',
+ fontFamily: 'sans-serif',
+ position: 'fixed',
+ top: width * 0.4,
+ left: width / 2,
+ },
+ },
+ {
+ type: 'image',
+ src: formatImageUrlProtocol(sheep.$url.cdn(userInfo.avatar)),
+ css: {
+ position: 'fixed',
+ left: width * 0.4,
+ top: width * 0.16,
+ width: width * 0.2,
+ height: width * 0.2,
+ },
+ },
+ // #ifndef MP-WEIXIN
+ {
+ type: 'qrcode',
+ text: poster.shareInfo.link,
+ css: {
+ position: 'fixed',
+ left: width * 0.35,
+ top: width * 0.84,
+ width: width * 0.3,
+ height: width * 0.3,
+ },
+ },
+ // #endif
+ // #ifdef MP-WEIXIN
+ {
+ type: 'image',
+ src: wxa_qrcode,
+ css: {
+ position: 'fixed',
+ left: width * 0.35,
+ top: width * 0.84,
+ width: width * 0.3,
+ height: width * 0.3,
+ },
+ },
+ // #endif
+ ];
+};
+
+export default user;
diff --git a/sheep/components/s-share-modal/s-share-modal.vue b/sheep/components/s-share-modal/s-share-modal.vue
new file mode 100644
index 0000000..717940e
--- /dev/null
+++ b/sheep/components/s-share-modal/s-share-modal.vue
@@ -0,0 +1,196 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sheep/components/s-statusbar/s-statusbar.vue b/sheep/components/s-statusbar/s-statusbar.vue
new file mode 100644
index 0000000..8b58c97
--- /dev/null
+++ b/sheep/components/s-statusbar/s-statusbar.vue
@@ -0,0 +1,10 @@
+
+
+
+
+
diff --git a/sheep/components/s-tabbar/s-tabbar.vue b/sheep/components/s-tabbar/s-tabbar.vue
new file mode 100644
index 0000000..369a823
--- /dev/null
+++ b/sheep/components/s-tabbar/s-tabbar.vue
@@ -0,0 +1,90 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sheep/components/s-title-block/s-title-block.vue b/sheep/components/s-title-block/s-title-block.vue
new file mode 100644
index 0000000..cb61033
--- /dev/null
+++ b/sheep/components/s-title-block/s-title-block.vue
@@ -0,0 +1,108 @@
+
+
+
+
+
+ {{ data.title }}
+
+ {{ data.description }}
+
+
+
+ {{ data.more.text }}
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/sheep/components/s-uploader/choose-and-upload-file.js b/sheep/components/s-uploader/choose-and-upload-file.js
new file mode 100644
index 0000000..604ff9d
--- /dev/null
+++ b/sheep/components/s-uploader/choose-and-upload-file.js
@@ -0,0 +1,213 @@
+'use strict';
+import FileApi from '@/sheep/api/infra/file';
+
+const ERR_MSG_OK = 'chooseAndUploadFile:ok';
+const ERR_MSG_FAIL = 'chooseAndUploadFile:fail';
+
+function chooseImage(opts) {
+ const {
+ count,
+ sizeType = ['original', 'compressed'],
+ sourceType = ['album', 'camera'],
+ extension,
+ } = opts;
+ return new Promise((resolve, reject) => {
+ uni.chooseImage({
+ count,
+ sizeType,
+ sourceType,
+ extension,
+ success(res) {
+ resolve(normalizeChooseAndUploadFileRes(res, 'image'));
+ },
+ fail(res) {
+ reject({
+ errMsg: res.errMsg.replace('chooseImage:fail', ERR_MSG_FAIL),
+ });
+ },
+ });
+ });
+}
+
+function chooseVideo(opts) {
+ const { camera, compressed, maxDuration, sourceType = ['album', 'camera'], extension } = opts;
+ return new Promise((resolve, reject) => {
+ uni.chooseVideo({
+ camera,
+ compressed,
+ maxDuration,
+ sourceType,
+ extension,
+ success(res) {
+ const { tempFilePath, duration, size, height, width } = res;
+ resolve(
+ normalizeChooseAndUploadFileRes(
+ {
+ errMsg: 'chooseVideo:ok',
+ tempFilePaths: [tempFilePath],
+ tempFiles: [
+ {
+ name: (res.tempFile && res.tempFile.name) || '',
+ path: tempFilePath,
+ size,
+ type: (res.tempFile && res.tempFile.type) || '',
+ width,
+ height,
+ duration,
+ fileType: 'video',
+ cloudPath: '',
+ },
+ ],
+ },
+ 'video',
+ ),
+ );
+ },
+ fail(res) {
+ reject({
+ errMsg: res.errMsg.replace('chooseVideo:fail', ERR_MSG_FAIL),
+ });
+ },
+ });
+ });
+}
+
+function chooseAll(opts) {
+ const { count, extension } = opts;
+ return new Promise((resolve, reject) => {
+ let chooseFile = uni.chooseFile;
+ if (typeof wx !== 'undefined' && typeof wx.chooseMessageFile === 'function') {
+ chooseFile = wx.chooseMessageFile;
+ }
+ if (typeof chooseFile !== 'function') {
+ return reject({
+ errMsg: ERR_MSG_FAIL + ' 请指定 type 类型,该平台仅支持选择 image 或 video。',
+ });
+ }
+ chooseFile({
+ type: 'all',
+ count,
+ extension,
+ success(res) {
+ resolve(normalizeChooseAndUploadFileRes(res));
+ },
+ fail(res) {
+ reject({
+ errMsg: res.errMsg.replace('chooseFile:fail', ERR_MSG_FAIL),
+ });
+ },
+ });
+ });
+}
+
+function normalizeChooseAndUploadFileRes(res, fileType) {
+ res.tempFiles.forEach((item, index) => {
+ if (!item.name) {
+ item.name = item.path.substring(item.path.lastIndexOf('/') + 1);
+ }
+ if (fileType) {
+ item.fileType = fileType;
+ }
+ item.cloudPath = Date.now() + '_' + index + item.name.substring(item.name.lastIndexOf('.'));
+ });
+ if (!res.tempFilePaths) {
+ res.tempFilePaths = res.tempFiles.map((file) => file.path);
+ }
+ return res;
+}
+
+function uploadCloudFiles(files, max = 5, onUploadProgress) {
+ files = JSON.parse(JSON.stringify(files));
+ const len = files.length;
+ let count = 0;
+ let self = this;
+ return new Promise((resolve) => {
+ while (count < max) {
+ next();
+ }
+
+ function next() {
+ let cur = count++;
+ if (cur >= len) {
+ !files.find((item) => !item.url && !item.errMsg) && resolve(files);
+ return;
+ }
+ const fileItem = files[cur];
+ const index = self.files.findIndex((v) => v.uuid === fileItem.uuid);
+ fileItem.url = '';
+ delete fileItem.errMsg;
+
+ uniCloud
+ .uploadFile({
+ filePath: fileItem.path,
+ cloudPath: fileItem.cloudPath,
+ fileType: fileItem.fileType,
+ onUploadProgress: (res) => {
+ res.index = index;
+ onUploadProgress && onUploadProgress(res);
+ },
+ })
+ .then((res) => {
+ fileItem.url = res.fileID;
+ fileItem.index = index;
+ if (cur < len) {
+ next();
+ }
+ })
+ .catch((res) => {
+ fileItem.errMsg = res.errMsg || res.message;
+ fileItem.index = index;
+ if (cur < len) {
+ next();
+ }
+ });
+ }
+ });
+}
+
+function uploadFiles(choosePromise, { onChooseFile, onUploadProgress }) {
+ return choosePromise
+ .then((res) => {
+ if (onChooseFile) {
+ const customChooseRes = onChooseFile(res);
+ if (typeof customChooseRes !== 'undefined') {
+ return Promise.resolve(customChooseRes).then((chooseRes) =>
+ typeof chooseRes === 'undefined' ? res : chooseRes,
+ );
+ }
+ }
+ return res;
+ })
+ .then((res) => {
+ if (res === false) {
+ return {
+ errMsg: ERR_MSG_OK,
+ tempFilePaths: [],
+ tempFiles: [],
+ };
+ }
+ return res;
+ })
+ .then(async (files) => {
+ for (let file of files.tempFiles) {
+ const { data } = await FileApi.uploadFile(file.path);
+ file.url = data;
+ }
+ return files;
+ });
+}
+
+function chooseAndUploadFile(
+ opts = {
+ type: 'all',
+ },
+) {
+ if (opts.type === 'image') {
+ return uploadFiles(chooseImage(opts), opts);
+ } else if (opts.type === 'video') {
+ return uploadFiles(chooseVideo(opts), opts);
+ }
+ return uploadFiles(chooseAll(opts), opts);
+}
+
+export { chooseAndUploadFile, uploadCloudFiles };
diff --git a/sheep/components/s-uploader/s-uploader.vue b/sheep/components/s-uploader/s-uploader.vue
new file mode 100644
index 0000000..95cfb05
--- /dev/null
+++ b/sheep/components/s-uploader/s-uploader.vue
@@ -0,0 +1,675 @@
+
+
+
+
+
+ {{ subtitle }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sheep/components/s-uploader/upload-file.vue b/sheep/components/s-uploader/upload-file.vue
new file mode 100644
index 0000000..233d281
--- /dev/null
+++ b/sheep/components/s-uploader/upload-file.vue
@@ -0,0 +1,335 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.name }}
+
+
+
+
+
+
+
+
+
+ 点击重试
+
+
+
+
+
+
+
+
+
diff --git a/sheep/components/s-uploader/upload-image.vue b/sheep/components/s-uploader/upload-image.vue
new file mode 100644
index 0000000..b66956a
--- /dev/null
+++ b/sheep/components/s-uploader/upload-image.vue
@@ -0,0 +1,306 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sheep/components/s-uploader/utils.js b/sheep/components/s-uploader/utils.js
new file mode 100644
index 0000000..c1e8073
--- /dev/null
+++ b/sheep/components/s-uploader/utils.js
@@ -0,0 +1,110 @@
+/**
+ * 获取文件名和后缀
+ * @param {String} name
+ */
+export const get_file_ext = (name) => {
+ const last_len = name.lastIndexOf('.');
+ const len = name.length;
+ return {
+ name: name.substring(0, last_len),
+ ext: name.substring(last_len + 1, len),
+ };
+};
+
+/**
+ * 获取扩展名
+ * @param {Array} fileExtname
+ */
+export const get_extname = (fileExtname) => {
+ if (!Array.isArray(fileExtname)) {
+ let extname = fileExtname.replace(/(\[|\])/g, '');
+ return extname.split(',');
+ } else {
+ return fileExtname;
+ }
+ return [];
+};
+
+/**
+ * 获取文件和检测是否可选
+ */
+export const get_files_and_is_max = (res, _extname) => {
+ let filePaths = [];
+ let files = [];
+ if (!_extname || _extname.length === 0) {
+ return {
+ filePaths,
+ files,
+ };
+ }
+ res.tempFiles.forEach((v) => {
+ let fileFullName = get_file_ext(v.name);
+ const extname = fileFullName.ext.toLowerCase();
+ if (_extname.indexOf(extname) !== -1) {
+ files.push(v);
+ filePaths.push(v.path);
+ }
+ });
+ if (files.length !== res.tempFiles.length) {
+ uni.showToast({
+ title: `当前选择了${res.tempFiles.length}个文件 ,${
+ res.tempFiles.length - files.length
+ } 个文件格式不正确`,
+ icon: 'none',
+ duration: 5000,
+ });
+ }
+
+ return {
+ filePaths,
+ files,
+ };
+};
+
+/**
+ * 获取图片信息
+ * @param {Object} filepath
+ */
+export const get_file_info = (filepath) => {
+ return new Promise((resolve, reject) => {
+ uni.getImageInfo({
+ src: filepath,
+ success(res) {
+ resolve(res);
+ },
+ fail(err) {
+ reject(err);
+ },
+ });
+ });
+};
+/**
+ * 获取封装数据
+ */
+export const get_file_data = async (files, type = 'image') => {
+ // 最终需要上传数据库的数据
+ let fileFullName = get_file_ext(files.name);
+ const extname = fileFullName.ext.toLowerCase();
+ let filedata = {
+ name: files.name,
+ uuid: files.uuid,
+ extname: extname || '',
+ cloudPath: files.cloudPath,
+ fileType: files.fileType,
+ url: files.path || files.path,
+ size: files.size, //单位是字节
+ image: {},
+ path: files.path,
+ video: {},
+ };
+ if (type === 'image') {
+ const imageinfo = await get_file_info(files.path);
+ delete filedata.video;
+ filedata.image.width = imageinfo.width;
+ filedata.image.height = imageinfo.height;
+ filedata.image.location = imageinfo.path;
+ } else {
+ delete filedata.image;
+ }
+ return filedata;
+};
diff --git a/sheep/components/s-user-card/s-user-card.vue b/sheep/components/s-user-card/s-user-card.vue
new file mode 100644
index 0000000..754d536
--- /dev/null
+++ b/sheep/components/s-user-card/s-user-card.vue
@@ -0,0 +1,185 @@
+
+
+
+
+
+
+
+
+
+
+
+ {{ userInfo?.nickname || nickname }}
+
+
+
+
+
+
+
+
+
+
+
+
+ 点击绑定手机号确保账户安全
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/sheep/components/s-video-block/s-video-block.vue b/sheep/components/s-video-block/s-video-block.vue
new file mode 100644
index 0000000..38e5b84
--- /dev/null
+++ b/sheep/components/s-video-block/s-video-block.vue
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
diff --git a/sheep/components/s-wallet-card/s-wallet-card.vue b/sheep/components/s-wallet-card/s-wallet-card.vue
new file mode 100644
index 0000000..aff0bf8
--- /dev/null
+++ b/sheep/components/s-wallet-card/s-wallet-card.vue
@@ -0,0 +1,119 @@
+
+
+
+
+
+
+
+
+
diff --git a/sheep/components/s-worker-item/s-worker-item.vue b/sheep/components/s-worker-item/s-worker-item.vue
new file mode 100644
index 0000000..1c304e6
--- /dev/null
+++ b/sheep/components/s-worker-item/s-worker-item.vue
@@ -0,0 +1,198 @@
+
+
+
+
+
+
+
+
+
+
+
+ {{ title }}
+ {{ skuString }}
+
+ 开始服务时间:
+ 剩余时间:
+
+
+
+
+
+
+ ¥{{ fen2yuan(price) }}
+
+ x {{ num }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sheep/config/index.js b/sheep/config/index.js
new file mode 100644
index 0000000..f6669a3
--- /dev/null
+++ b/sheep/config/index.js
@@ -0,0 +1,23 @@
+// 开发环境配置
+export let baseUrl;
+export let version;
+if (process.env.NODE_ENV === 'development') {
+ baseUrl = import.meta.env.SHOPRO_DEV_BASE_URL;
+} else {
+ baseUrl = import.meta.env.SHOPRO_BASE_URL;
+}
+version = import.meta.env.SHOPRO_VERSION;
+console.log(`[晚趣语音 ${version}]`);
+
+export const apiPath = import.meta.env.SHOPRO_API_PATH;
+export const staticUrl = import.meta.env.SHOPRO_STATIC_URL;
+export const tenantId = import.meta.env.SHOPRO_TENANT_ID;
+export const websocketPath = import.meta.env.SHOPRO_WEBSOCKET_PATH;
+
+export default {
+ baseUrl,
+ apiPath,
+ staticUrl,
+ tenantId,
+ websocketPath,
+};
diff --git a/sheep/config/zIndex.js b/sheep/config/zIndex.js
new file mode 100644
index 0000000..6652d48
--- /dev/null
+++ b/sheep/config/zIndex.js
@@ -0,0 +1,20 @@
+// uniapp在H5中各API的z-index值如下:
+/**
+ * actionsheet: 999
+ * modal: 999
+ * navigate: 998
+ * tabbar: 998
+ * toast: 999
+ */
+
+export default {
+ toast: 10090,
+ noNetwork: 10080,
+ popup: 10075, // popup包含popup,actionsheet,keyboard,picker的值
+ mask: 10070,
+ navbar: 980,
+ topTips: 975,
+ sticky: 970,
+ indexListSticky: 965,
+ popover: 960,
+};
diff --git a/sheep/helper/digit.js b/sheep/helper/digit.js
new file mode 100644
index 0000000..be50b32
--- /dev/null
+++ b/sheep/helper/digit.js
@@ -0,0 +1,168 @@
+let _boundaryCheckingState = true; // 是否进行越界检查的全局开关
+
+/**
+ * 把错误的数据转正
+ * @private
+ * @example strip(0.09999999999999998)=0.1
+ */
+function strip(num, precision = 15) {
+ return +parseFloat(Number(num).toPrecision(precision));
+}
+
+/**
+ * Return digits length of a number
+ * @private
+ * @param {*number} num Input number
+ */
+function digitLength(num) {
+ // Get digit length of e
+ const eSplit = num.toString().split(/[eE]/);
+ const len = (eSplit[0].split('.')[1] || '').length - +(eSplit[1] || 0);
+ return len > 0 ? len : 0;
+}
+
+/**
+ * 把小数转成整数,如果是小数则放大成整数
+ * @private
+ * @param {*number} num 输入数
+ */
+function float2Fixed(num) {
+ if (num.toString().indexOf('e') === -1) {
+ return Number(num.toString().replace('.', ''));
+ }
+ const dLen = digitLength(num);
+ return dLen > 0 ? strip(Number(num) * Math.pow(10, dLen)) : Number(num);
+}
+
+/**
+ * 检测数字是否越界,如果越界给出提示
+ * @private
+ * @param {*number} num 输入数
+ */
+function checkBoundary(num) {
+ if (_boundaryCheckingState) {
+ if (num > Number.MAX_SAFE_INTEGER || num < Number.MIN_SAFE_INTEGER) {
+ console.warn(`${num} 超出了精度限制,结果可能不正确`);
+ }
+ }
+}
+
+/**
+ * 把递归操作扁平迭代化
+ * @param {number[]} arr 要操作的数字数组
+ * @param {function} operation 迭代操作
+ * @private
+ */
+function iteratorOperation(arr, operation) {
+ const [num1, num2, ...others] = arr;
+ let res = operation(num1, num2);
+
+ others.forEach((num) => {
+ res = operation(res, num);
+ });
+
+ return res;
+}
+
+/**
+ * 高精度乘法
+ * @export
+ */
+export function times(...nums) {
+ if (nums.length > 2) {
+ return iteratorOperation(nums, times);
+ }
+
+ const [num1, num2] = nums;
+ const num1Changed = float2Fixed(num1);
+ const num2Changed = float2Fixed(num2);
+ const baseNum = digitLength(num1) + digitLength(num2);
+ const leftValue = num1Changed * num2Changed;
+
+ checkBoundary(leftValue);
+
+ return leftValue / Math.pow(10, baseNum);
+}
+
+/**
+ * 高精度加法
+ * @export
+ */
+export function plus(...nums) {
+ if (nums.length > 2) {
+ return iteratorOperation(nums, plus);
+ }
+
+ const [num1, num2] = nums;
+ // 取最大的小数位
+ const baseNum = Math.pow(10, Math.max(digitLength(num1), digitLength(num2)));
+ // 把小数都转为整数然后再计算
+ return (times(num1, baseNum) + times(num2, baseNum)) / baseNum;
+}
+
+/**
+ * 高精度减法
+ * @export
+ */
+export function minus(...nums) {
+ if (nums.length > 2) {
+ return iteratorOperation(nums, minus);
+ }
+
+ const [num1, num2] = nums;
+ const baseNum = Math.pow(10, Math.max(digitLength(num1), digitLength(num2)));
+ return (times(num1, baseNum) - times(num2, baseNum)) / baseNum;
+}
+
+/**
+ * 高精度除法
+ * @export
+ */
+export function divide(...nums) {
+ if (nums.length > 2) {
+ return iteratorOperation(nums, divide);
+ }
+
+ const [num1, num2] = nums;
+ const num1Changed = float2Fixed(num1);
+ const num2Changed = float2Fixed(num2);
+ checkBoundary(num1Changed);
+ checkBoundary(num2Changed);
+ // 重要,这里必须用strip进行修正
+ return times(
+ num1Changed / num2Changed,
+ strip(Math.pow(10, digitLength(num2) - digitLength(num1))),
+ );
+}
+
+/**
+ * 四舍五入
+ * @export
+ */
+export function round(num, ratio) {
+ const base = Math.pow(10, ratio);
+ let result = divide(Math.round(Math.abs(times(num, base))), base);
+ if (num < 0 && result !== 0) {
+ result = times(result, -1);
+ }
+ // 位数不足则补0
+ return result;
+}
+
+/**
+ * 是否进行边界检查,默认开启
+ * @param flag 标记开关,true 为开启,false 为关闭,默认为 true
+ * @export
+ */
+export function enableBoundaryChecking(flag = true) {
+ _boundaryCheckingState = flag;
+}
+
+export default {
+ times,
+ plus,
+ minus,
+ divide,
+ round,
+ enableBoundaryChecking,
+};
diff --git a/sheep/helper/index.js b/sheep/helper/index.js
new file mode 100644
index 0000000..bdd0134
--- /dev/null
+++ b/sheep/helper/index.js
@@ -0,0 +1,714 @@
+import test from './test.js';
+import { round } from './digit.js';
+/**
+ * @description 如果value小于min,取min;如果value大于max,取max
+ * @param {number} min
+ * @param {number} max
+ * @param {number} value
+ */
+function range(min = 0, max = 0, value = 0) {
+ return Math.max(min, Math.min(max, Number(value)));
+}
+
+/**
+ * @description 用于获取用户传递值的px值 如果用户传递了"xxpx"或者"xxrpx",取出其数值部分,如果是"xxxrpx"还需要用过uni.upx2px进行转换
+ * @param {number|string} value 用户传递值的px值
+ * @param {boolean} unit
+ * @returns {number|string}
+ */
+export function getPx(value, unit = false) {
+ if (test.number(value)) {
+ return unit ? `${value}px` : Number(value);
+ }
+ // 如果带有rpx,先取出其数值部分,再转为px值
+ if (/(rpx|upx)$/.test(value)) {
+ return unit ? `${uni.upx2px(parseInt(value))}px` : Number(uni.upx2px(parseInt(value)));
+ }
+ return unit ? `${parseInt(value)}px` : parseInt(value);
+}
+
+/**
+ * @description 进行延时,以达到可以简写代码的目的
+ * @param {number} value 堵塞时间 单位ms 毫秒
+ * @returns {Promise} 返回promise
+ */
+export function sleep(value = 30) {
+ return new Promise((resolve) => {
+ setTimeout(() => {
+ resolve();
+ }, value);
+ });
+}
+/**
+ * @description 运行期判断平台
+ * @returns {string} 返回所在平台(小写)
+ * @link 运行期判断平台 https://uniapp.dcloud.io/frame?id=判断平台
+ */
+export function os() {
+ return uni.getSystemInfoSync().platform.toLowerCase();
+}
+/**
+ * @description 获取系统信息同步接口
+ * @link 获取系统信息同步接口 https://uniapp.dcloud.io/api/system/info?id=getsysteminfosync
+ */
+export function sys() {
+ return uni.getSystemInfoSync();
+}
+
+/**
+ * @description 取一个区间数
+ * @param {Number} min 最小值
+ * @param {Number} max 最大值
+ */
+function random(min, max) {
+ if (min >= 0 && max > 0 && max >= min) {
+ const gab = max - min + 1;
+ return Math.floor(Math.random() * gab + min);
+ }
+ return 0;
+}
+
+/**
+ * @param {Number} len uuid的长度
+ * @param {Boolean} firstU 将返回的首字母置为"u"
+ * @param {Nubmer} radix 生成uuid的基数(意味着返回的字符串都是这个基数),2-二进制,8-八进制,10-十进制,16-十六进制
+ */
+export function guid(len = 32, firstU = true, radix = null) {
+ const chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('');
+ const uuid = [];
+ radix = radix || chars.length;
+
+ if (len) {
+ // 如果指定uuid长度,只是取随机的字符,0|x为位运算,能去掉x的小数位,返回整数位
+ for (let i = 0; i < len; i++) uuid[i] = chars[0 | (Math.random() * radix)];
+ } else {
+ let r;
+ // rfc4122标准要求返回的uuid中,某些位为固定的字符
+ uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-';
+ uuid[14] = '4';
+
+ for (let i = 0; i < 36; i++) {
+ if (!uuid[i]) {
+ r = 0 | (Math.random() * 16);
+ uuid[i] = chars[i == 19 ? (r & 0x3) | 0x8 : r];
+ }
+ }
+ }
+ // 移除第一个字符,并用u替代,因为第一个字符为数值时,该guuid不能用作id或者class
+ if (firstU) {
+ uuid.shift();
+ return `u${uuid.join('')}`;
+ }
+ return uuid.join('');
+}
+
+/**
+* @description 获取父组件的参数,因为支付宝小程序不支持provide/inject的写法
+ this.$parent在非H5中,可以准确获取到父组件,但是在H5中,需要多次this.$parent.$parent.xxx
+ 这里默认值等于undefined有它的含义,因为最顶层元素(组件)的$parent就是undefined,意味着不传name
+ 值(默认为undefined),就是查找最顶层的$parent
+* @param {string|undefined} name 父组件的参数名
+*/
+export function $parent(name = undefined) {
+ let parent = this.$parent;
+ // 通过while历遍,这里主要是为了H5需要多层解析的问题
+ while (parent) {
+ // 父组件
+ if (parent.$options && parent.$options.name !== name) {
+ // 如果组件的name不相等,继续上一级寻找
+ parent = parent.$parent;
+ } else {
+ return parent;
+ }
+ }
+ return false;
+}
+
+/**
+ * @description 样式转换
+ * 对象转字符串,或者字符串转对象
+ * @param {object | string} customStyle 需要转换的目标
+ * @param {String} target 转换的目的,object-转为对象,string-转为字符串
+ * @returns {object|string}
+ */
+export function addStyle(customStyle, target = 'object') {
+ // 字符串转字符串,对象转对象情形,直接返回
+ if (
+ test.empty(customStyle) ||
+ (typeof customStyle === 'object' && target === 'object') ||
+ (target === 'string' && typeof customStyle === 'string')
+ ) {
+ return customStyle;
+ }
+ // 字符串转对象
+ if (target === 'object') {
+ // 去除字符串样式中的两端空格(中间的空格不能去掉,比如padding: 20px 0如果去掉了就错了),空格是无用的
+ customStyle = trim(customStyle);
+ // 根据";"将字符串转为数组形式
+ const styleArray = customStyle.split(';');
+ const style = {};
+ // 历遍数组,拼接成对象
+ for (let i = 0; i < styleArray.length; i++) {
+ // 'font-size:20px;color:red;',如此最后字符串有";"的话,会导致styleArray最后一个元素为空字符串,这里需要过滤
+ if (styleArray[i]) {
+ const item = styleArray[i].split(':');
+ style[trim(item[0])] = trim(item[1]);
+ }
+ }
+ return style;
+ }
+ // 这里为对象转字符串形式
+ let string = '';
+ for (const i in customStyle) {
+ // 驼峰转为中划线的形式,否则css内联样式,无法识别驼峰样式属性名
+ const key = i.replace(/([A-Z])/g, '-$1').toLowerCase();
+ string += `${key}:${customStyle[i]};`;
+ }
+ // 去除两端空格
+ return trim(string);
+}
+
+/**
+ * @description 添加单位,如果有rpx,upx,%,px等单位结尾或者值为auto,直接返回,否则加上px单位结尾
+ * @param {string|number} value 需要添加单位的值
+ * @param {string} unit 添加的单位名 比如px
+ */
+export function addUnit(value = 'auto', unit = 'px') {
+ value = String(value);
+ return test.number(value) ? `${value}${unit}` : value;
+}
+
+/**
+ * @description 深度克隆
+ * @param {object} obj 需要深度克隆的对象
+ * @returns {*} 克隆后的对象或者原值(不是对象)
+ */
+function deepClone(obj) {
+ // 对常见的“非”值,直接返回原来值
+ if ([null, undefined, NaN, false].includes(obj)) return obj;
+ if (typeof obj !== 'object' && typeof obj !== 'function') {
+ // 原始类型直接返回
+ return obj;
+ }
+ const o = test.array(obj) ? [] : {};
+ for (const i in obj) {
+ if (obj.hasOwnProperty(i)) {
+ o[i] = typeof obj[i] === 'object' ? deepClone(obj[i]) : obj[i];
+ }
+ }
+ return o;
+}
+
+/**
+ * @description JS对象深度合并
+ * @param {object} target 需要拷贝的对象
+ * @param {object} source 拷贝的来源对象
+ * @returns {object|boolean} 深度合并后的对象或者false(入参有不是对象)
+ */
+export function deepMerge(target = {}, source = {}) {
+ target = deepClone(target);
+ if (typeof target !== 'object' || typeof source !== 'object') return false;
+ for (const prop in source) {
+ if (!source.hasOwnProperty(prop)) continue;
+ if (prop in target) {
+ if (typeof target[prop] !== 'object') {
+ target[prop] = source[prop];
+ } else if (typeof source[prop] !== 'object') {
+ target[prop] = source[prop];
+ } else if (target[prop].concat && source[prop].concat) {
+ target[prop] = target[prop].concat(source[prop]);
+ } else {
+ target[prop] = deepMerge(target[prop], source[prop]);
+ }
+ } else {
+ target[prop] = source[prop];
+ }
+ }
+ return target;
+}
+
+/**
+ * @description error提示
+ * @param {*} err 错误内容
+ */
+function error(err) {
+ // 开发环境才提示,生产环境不会提示
+ if (process.env.NODE_ENV === 'development') {
+ console.error(`SheepJS:${err}`);
+ }
+}
+
+/**
+ * @description 打乱数组
+ * @param {array} array 需要打乱的数组
+ * @returns {array} 打乱后的数组
+ */
+function randomArray(array = []) {
+ // 原理是sort排序,Math.random()产生0<= x < 1之间的数,会导致x-0.05大于或者小于0
+ return array.sort(() => Math.random() - 0.5);
+}
+
+// padStart 的 polyfill,因为某些机型或情况,还无法支持es7的padStart,比如电脑版的微信小程序
+// 所以这里做一个兼容polyfill的兼容处理
+if (!String.prototype.padStart) {
+ // 为了方便表示这里 fillString 用了ES6 的默认参数,不影响理解
+ String.prototype.padStart = function (maxLength, fillString = ' ') {
+ if (Object.prototype.toString.call(fillString) !== '[object String]') {
+ throw new TypeError('fillString must be String');
+ }
+ const str = this;
+ // 返回 String(str) 这里是为了使返回的值是字符串字面量,在控制台中更符合直觉
+ if (str.length >= maxLength) return String(str);
+
+ const fillLength = maxLength - str.length;
+ let times = Math.ceil(fillLength / fillString.length);
+ while ((times >>= 1)) {
+ fillString += fillString;
+ if (times === 1) {
+ fillString += fillString;
+ }
+ }
+ return fillString.slice(0, fillLength) + str;
+ };
+}
+
+/**
+ * @description 格式化时间
+ * @param {String|Number} dateTime 需要格式化的时间戳
+ * @param {String} fmt 格式化规则 yyyy:mm:dd|yyyy:mm|yyyy年mm月dd日|yyyy年mm月dd日 hh时MM分等,可自定义组合 默认yyyy-mm-dd
+ * @returns {string} 返回格式化后的字符串
+ */
+function timeFormat(dateTime = null, formatStr = 'yyyy-mm-dd') {
+ let date;
+ // 若传入时间为假值,则取当前时间
+ if (!dateTime) {
+ date = new Date();
+ }
+ // 若为unix秒时间戳,则转为毫秒时间戳(逻辑有点奇怪,但不敢改,以保证历史兼容)
+ else if (/^\d{10}$/.test(dateTime?.toString().trim())) {
+ date = new Date(dateTime * 1000);
+ }
+ // 若用户传入字符串格式时间戳,new Date无法解析,需做兼容
+ else if (typeof dateTime === 'string' && /^\d+$/.test(dateTime.trim())) {
+ date = new Date(Number(dateTime));
+ }
+ // 其他都认为符合 RFC 2822 规范
+ else {
+ // 处理平台性差异,在Safari/Webkit中,new Date仅支持/作为分割符的字符串时间
+ date = new Date(typeof dateTime === 'string' ? dateTime.replace(/-/g, '/') : dateTime);
+ }
+
+ const timeSource = {
+ y: date.getFullYear().toString(), // 年
+ m: (date.getMonth() + 1).toString().padStart(2, '0'), // 月
+ d: date.getDate().toString().padStart(2, '0'), // 日
+ h: date.getHours().toString().padStart(2, '0'), // 时
+ M: date.getMinutes().toString().padStart(2, '0'), // 分
+ s: date.getSeconds().toString().padStart(2, '0'), // 秒
+ // 有其他格式化字符需求可以继续添加,必须转化成字符串
+ };
+
+ for (const key in timeSource) {
+ const [ret] = new RegExp(`${key}+`).exec(formatStr) || [];
+ if (ret) {
+ // 年可能只需展示两位
+ const beginIndex = key === 'y' && ret.length === 2 ? 2 : 0;
+ formatStr = formatStr.replace(ret, timeSource[key].slice(beginIndex));
+ }
+ }
+
+ return formatStr;
+}
+
+/**
+ * @description 时间戳转为多久之前
+ * @param {String|Number} timestamp 时间戳
+ * @param {String|Boolean} format
+ * 格式化规则如果为时间格式字符串,超出一定时间范围,返回固定的时间格式;
+ * 如果为布尔值false,无论什么时间,都返回多久以前的格式
+ * @returns {string} 转化后的内容
+ */
+function timeFrom(timestamp = null, format = 'yyyy-mm-dd') {
+ if (timestamp == null) timestamp = Number(new Date());
+ timestamp = parseInt(timestamp);
+ // 判断用户输入的时间戳是秒还是毫秒,一般前端js获取的时间戳是毫秒(13位),后端传过来的为秒(10位)
+ if (timestamp.toString().length == 10) timestamp *= 1000;
+ let timer = new Date().getTime() - timestamp;
+ timer = parseInt(timer / 1000);
+ // 如果小于5分钟,则返回"刚刚",其他以此类推
+ let tips = '';
+ switch (true) {
+ case timer < 300:
+ tips = '刚刚';
+ break;
+ case timer >= 300 && timer < 3600:
+ tips = `${parseInt(timer / 60)}分钟前`;
+ break;
+ case timer >= 3600 && timer < 86400:
+ tips = `${parseInt(timer / 3600)}小时前`;
+ break;
+ case timer >= 86400 && timer < 2592000:
+ tips = `${parseInt(timer / 86400)}天前`;
+ break;
+ default:
+ // 如果format为false,则无论什么时间戳,都显示xx之前
+ if (format === false) {
+ if (timer >= 2592000 && timer < 365 * 86400) {
+ tips = `${parseInt(timer / (86400 * 30))}个月前`;
+ } else {
+ tips = `${parseInt(timer / (86400 * 365))}年前`;
+ }
+ } else {
+ tips = timeFormat(timestamp, format);
+ }
+ }
+ return tips;
+}
+
+export function parseTimeData(time) {
+ time = time - new Date().getTime();
+ return time
+}
+
+/**
+ * @description 去除空格
+ * @param String str 需要去除空格的字符串
+ * @param String pos both(左右)|left|right|all 默认both
+ */
+function trim(str, pos = 'both') {
+ str = String(str);
+ if (pos == 'both') {
+ return str.replace(/^\s+|\s+$/g, '');
+ }
+ if (pos == 'left') {
+ return str.replace(/^\s*/, '');
+ }
+ if (pos == 'right') {
+ return str.replace(/(\s*$)/g, '');
+ }
+ if (pos == 'all') {
+ return str.replace(/\s+/g, '');
+ }
+ return str;
+}
+
+/**
+ * @description 对象转url参数
+ * @param {object} data,对象
+ * @param {Boolean} isPrefix,是否自动加上"?"
+ * @param {string} arrayFormat 规则 indices|brackets|repeat|comma
+ */
+function queryParams(data = {}, isPrefix = true, arrayFormat = 'brackets') {
+ const prefix = isPrefix ? '?' : '';
+ const _result = [];
+ if (['indices', 'brackets', 'repeat', 'comma'].indexOf(arrayFormat) == -1)
+ arrayFormat = 'brackets';
+ for (const key in data) {
+ const value = data[key];
+ // 去掉为空的参数
+ if (['', undefined, null].indexOf(value) >= 0) {
+ continue;
+ }
+ // 如果值为数组,另行处理
+ if (value.constructor === Array) {
+ // e.g. {ids: [1, 2, 3]}
+ switch (arrayFormat) {
+ case 'indices':
+ // 结果: ids[0]=1&ids[1]=2&ids[2]=3
+ for (let i = 0; i < value.length; i++) {
+ _result.push(`${key}[${i}]=${value[i]}`);
+ }
+ break;
+ case 'brackets':
+ // 结果: ids[]=1&ids[]=2&ids[]=3
+ value.forEach((_value) => {
+ _result.push(`${key}[]=${_value}`);
+ });
+ break;
+ case 'repeat':
+ // 结果: ids=1&ids=2&ids=3
+ value.forEach((_value) => {
+ _result.push(`${key}=${_value}`);
+ });
+ break;
+ case 'comma':
+ // 结果: ids=1,2,3
+ let commaStr = '';
+ value.forEach((_value) => {
+ commaStr += (commaStr ? ',' : '') + _value;
+ });
+ _result.push(`${key}=${commaStr}`);
+ break;
+ default:
+ value.forEach((_value) => {
+ _result.push(`${key}[]=${_value}`);
+ });
+ }
+ } else {
+ _result.push(`${key}=${value}`);
+ }
+ }
+ return _result.length ? prefix + _result.join('&') : '';
+}
+
+/**
+ * 显示消息提示框
+ * @param {String} title 提示的内容,长度与 icon 取值有关。
+ * @param {Number} duration 提示的延迟时间,单位毫秒,默认:2000
+ */
+function toast(title, duration = 2000) {
+ uni.showToast({
+ title: String(title),
+ icon: 'none',
+ duration,
+ });
+}
+
+/**
+ * @description 根据主题type值,获取对应的图标
+ * @param {String} type 主题名称,primary|info|error|warning|success
+ * @param {boolean} fill 是否使用fill填充实体的图标
+ */
+function type2icon(type = 'success', fill = false) {
+ // 如果非预置值,默认为success
+ if (['primary', 'info', 'error', 'warning', 'success'].indexOf(type) == -1) type = 'success';
+ let iconName = '';
+ // 目前(2019-12-12),info和primary使用同一个图标
+ switch (type) {
+ case 'primary':
+ iconName = 'info-circle';
+ break;
+ case 'info':
+ iconName = 'info-circle';
+ break;
+ case 'error':
+ iconName = 'close-circle';
+ break;
+ case 'warning':
+ iconName = 'error-circle';
+ break;
+ case 'success':
+ iconName = 'checkmark-circle';
+ break;
+ default:
+ iconName = 'checkmark-circle';
+ }
+ // 是否是实体类型,加上-fill,在icon组件库中,实体的类名是后面加-fill的
+ if (fill) iconName += '-fill';
+ return iconName;
+}
+
+/**
+ * @description 数字格式化
+ * @param {number|string} number 要格式化的数字
+ * @param {number} decimals 保留几位小数
+ * @param {string} decimalPoint 小数点符号
+ * @param {string} thousandsSeparator 千分位符号
+ * @returns {string} 格式化后的数字
+ */
+function priceFormat(number, decimals = 0, decimalPoint = '.', thousandsSeparator = ',') {
+ number = `${number}`.replace(/[^0-9+-Ee.]/g, '');
+ const n = !isFinite(+number) ? 0 : +number;
+ const prec = !isFinite(+decimals) ? 0 : Math.abs(decimals);
+ const sep = typeof thousandsSeparator === 'undefined' ? ',' : thousandsSeparator;
+ const dec = typeof decimalPoint === 'undefined' ? '.' : decimalPoint;
+ let s = '';
+
+ s = (prec ? round(n, prec) + '' : `${Math.round(n)}`).split('.');
+ const re = /(-?\d+)(\d{3})/;
+ while (re.test(s[0])) {
+ s[0] = s[0].replace(re, `$1${sep}$2`);
+ }
+
+ if ((s[1] || '').length < prec) {
+ s[1] = s[1] || '';
+ s[1] += new Array(prec - s[1].length + 1).join('0');
+ }
+ return s.join(dec);
+}
+
+/**
+ * @description 获取duration值
+ * 如果带有ms或者s直接返回,如果大于一定值,认为是ms单位,小于一定值,认为是s单位
+ * 比如以30位阈值,那么300大于30,可以理解为用户想要的是300ms,而不是想花300s去执行一个动画
+ * @param {String|number} value 比如: "1s"|"100ms"|1|100
+ * @param {boolean} unit 提示: 如果是false 默认返回number
+ * @return {string|number}
+ */
+function getDuration(value, unit = true) {
+ const valueNum = parseInt(value);
+ if (unit) {
+ if (/s$/.test(value)) return value;
+ return value > 30 ? `${value}ms` : `${value}s`;
+ }
+ if (/ms$/.test(value)) return valueNum;
+ if (/s$/.test(value)) return valueNum > 30 ? valueNum : valueNum * 1000;
+ return valueNum;
+}
+
+/**
+ * @description 日期的月或日补零操作
+ * @param {String} value 需要补零的值
+ */
+function padZero(value) {
+ return `00${value}`.slice(-2);
+}
+
+/**
+ * @description 获取某个对象下的属性,用于通过类似'a.b.c'的形式去获取一个对象的的属性的形式
+ * @param {object} obj 对象
+ * @param {string} key 需要获取的属性字段
+ * @returns {*}
+ */
+function getProperty(obj, key) {
+ if (!obj) {
+ return;
+ }
+ if (typeof key !== 'string' || key === '') {
+ return '';
+ }
+ if (key.indexOf('.') !== -1) {
+ const keys = key.split('.');
+ let firstObj = obj[keys[0]] || {};
+
+ for (let i = 1; i < keys.length; i++) {
+ if (firstObj) {
+ firstObj = firstObj[keys[i]];
+ }
+ }
+ return firstObj;
+ }
+ return obj[key];
+}
+
+/**
+ * @description 设置对象的属性值,如果'a.b.c'的形式进行设置
+ * @param {object} obj 对象
+ * @param {string} key 需要设置的属性
+ * @param {string} value 设置的值
+ */
+function setProperty(obj, key, value) {
+ if (!obj) {
+ return;
+ }
+ // 递归赋值
+ const inFn = function (_obj, keys, v) {
+ // 最后一个属性key
+ if (keys.length === 1) {
+ _obj[keys[0]] = v;
+ return;
+ }
+ // 0~length-1个key
+ while (keys.length > 1) {
+ const k = keys[0];
+ if (!_obj[k] || typeof _obj[k] !== 'object') {
+ _obj[k] = {};
+ }
+ const key = keys.shift();
+ // 自调用判断是否存在属性,不存在则自动创建对象
+ inFn(_obj[k], keys, v);
+ }
+ };
+
+ if (typeof key !== 'string' || key === '') {
+ } else if (key.indexOf('.') !== -1) {
+ // 支持多层级赋值操作
+ const keys = key.split('.');
+ inFn(obj, keys, value);
+ } else {
+ obj[key] = value;
+ }
+}
+
+/**
+ * @description 获取当前页面路径
+ */
+function page() {
+ const pages = getCurrentPages();
+ // 某些特殊情况下(比如页面进行redirectTo时的一些时机),pages可能为空数组
+ return `/${pages[pages.length - 1]?.route ?? ''}`;
+}
+
+/**
+ * @description 获取当前路由栈实例数组
+ */
+function pages() {
+ const pages = getCurrentPages();
+ return pages;
+}
+
+/**
+ * 获取H5-真实根地址 兼容hash+history模式
+ */
+export function getRootUrl() {
+ let url = '';
+ // #ifdef H5
+ url = location.origin + '/h5';
+
+ if (location.hash !== '') {
+ url += '/#/';
+ }
+ // #endif
+ return url;
+}
+
+/**
+ * copyText 多端复制文本
+ */
+export function copyText(text) {
+ // #ifndef H5
+ uni.setClipboardData({
+ data: text,
+ success: function () {
+ toast('复制成功!');
+ },
+ fail: function () {
+ toast('复制失败!');
+ },
+ });
+ // #endif
+ // #ifdef H5
+ var createInput = document.createElement('textarea');
+ createInput.value = text;
+ document.body.appendChild(createInput);
+ createInput.select();
+ document.execCommand('Copy');
+ createInput.className = 'createInput';
+ createInput.style.display = 'none';
+ toast('复制成功');
+ // #endif
+}
+
+export default {
+ range,
+ getPx,
+ sleep,
+ os,
+ sys,
+ random,
+ guid,
+ $parent,
+ addStyle,
+ addUnit,
+ deepClone,
+ deepMerge,
+ error,
+ randomArray,
+ timeFormat,
+ parseTimeData,
+ timeFrom,
+ trim,
+ queryParams,
+ toast,
+ type2icon,
+ priceFormat,
+ getDuration,
+ padZero,
+ getProperty,
+ setProperty,
+ page,
+ pages,
+ test,
+ getRootUrl,
+ copyText,
+};
diff --git a/sheep/helper/test.js b/sheep/helper/test.js
new file mode 100644
index 0000000..ca550a1
--- /dev/null
+++ b/sheep/helper/test.js
@@ -0,0 +1,285 @@
+/**
+ * 验证电子邮箱格式
+ */
+function email(value) {
+ return /^\w+((-\w+)|(\.\w+))*\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/.test(value);
+}
+
+/**
+ * 验证手机格式
+ */
+function mobile(value) {
+ return /^1[23456789]\d{9}$/.test(value);
+}
+
+/**
+ * 验证URL格式
+ */
+function url(value) {
+ return /^((https|http|ftp|rtsp|mms):\/\/)(([0-9a-zA-Z_!~*'().&=+$%-]+: )?[0-9a-zA-Z_!~*'().&=+$%-]+@)?(([0-9]{1,3}.){3}[0-9]{1,3}|([0-9a-zA-Z_!~*'()-]+.)*([0-9a-zA-Z][0-9a-zA-Z-]{0,61})?[0-9a-zA-Z].[a-zA-Z]{2,6})(:[0-9]{1,4})?((\/?)|(\/[0-9a-zA-Z_!~*'().;?:@&=+$,%#-]+)+\/?)$/.test(
+ value,
+ );
+}
+
+/**
+ * 验证日期格式
+ */
+function date(value) {
+ if (!value) return false;
+ // 判断是否数值或者字符串数值(意味着为时间戳),转为数值,否则new Date无法识别字符串时间戳
+ if (number(value)) value = +value;
+ return !/Invalid|NaN/.test(new Date(value).toString());
+}
+
+/**
+ * 验证ISO类型的日期格式
+ */
+function dateISO(value) {
+ return /^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])$/.test(value);
+}
+
+/**
+ * 验证十进制数字
+ */
+function number(value) {
+ return /^[\+-]?(\d+\.?\d*|\.\d+|\d\.\d+e\+\d+)$/.test(value);
+}
+
+/**
+ * 验证字符串
+ */
+function string(value) {
+ return typeof value === 'string';
+}
+
+/**
+ * 验证整数
+ */
+function digits(value) {
+ return /^\d+$/.test(value);
+}
+
+/**
+ * 验证身份证号码
+ */
+function idCard(value) {
+ return /^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$/.test(value);
+}
+
+/**
+ * 是否车牌号
+ */
+function carNo(value) {
+ // 新能源车牌
+ const xreg =
+ /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领A-Z]{1}[A-Z]{1}(([0-9]{5}[DF]$)|([DF][A-HJ-NP-Z0-9][0-9]{4}$))/;
+ // 旧车牌
+ const creg =
+ /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领A-Z]{1}[A-Z]{1}[A-HJ-NP-Z0-9]{4}[A-HJ-NP-Z0-9挂学警港澳]{1}$/;
+ if (value.length === 7) {
+ return creg.test(value);
+ }
+ if (value.length === 8) {
+ return xreg.test(value);
+ }
+ return false;
+}
+
+/**
+ * 金额,只允许2位小数
+ */
+function amount(value) {
+ // 金额,只允许保留两位小数
+ return /^[1-9]\d*(,\d{3})*(\.\d{1,2})?$|^0\.\d{1,2}$/.test(value);
+}
+
+/**
+ * 中文
+ */
+function chinese(value) {
+ const reg = /^[\u4e00-\u9fa5]+$/gi;
+ return reg.test(value);
+}
+
+/**
+ * 只能输入字母
+ */
+function letter(value) {
+ return /^[a-zA-Z]*$/.test(value);
+}
+
+/**
+ * 只能是字母或者数字
+ */
+function enOrNum(value) {
+ // 英文或者数字
+ const reg = /^[0-9a-zA-Z]*$/g;
+ return reg.test(value);
+}
+
+/**
+ * 验证是否包含某个值
+ */
+function contains(value, param) {
+ return value.indexOf(param) >= 0;
+}
+
+/**
+ * 验证一个值范围[min, max]
+ */
+function range(value, param) {
+ return value >= param[0] && value <= param[1];
+}
+
+/**
+ * 验证一个长度范围[min, max]
+ */
+function rangeLength(value, param) {
+ return value.length >= param[0] && value.length <= param[1];
+}
+
+/**
+ * 是否固定电话
+ */
+function landline(value) {
+ const reg = /^\d{3,4}-\d{7,8}(-\d{3,4})?$/;
+ return reg.test(value);
+}
+
+/**
+ * 判断是否为空
+ */
+function empty(value) {
+ switch (typeof value) {
+ case 'undefined':
+ return true;
+ case 'string':
+ if (value.replace(/(^[ \t\n\r]*)|([ \t\n\r]*$)/g, '').length == 0) return true;
+ break;
+ case 'boolean':
+ if (!value) return true;
+ break;
+ case 'number':
+ if (value === 0 || isNaN(value)) return true;
+ break;
+ case 'object':
+ if (value === null || value.length === 0) return true;
+ for (const i in value) {
+ return false;
+ }
+ return true;
+ }
+ return false;
+}
+
+/**
+ * 是否json字符串
+ */
+function jsonString(value) {
+ if (typeof value === 'string') {
+ try {
+ const obj = JSON.parse(value);
+ if (typeof obj === 'object' && obj) {
+ return true;
+ }
+ return false;
+ } catch (e) {
+ return false;
+ }
+ }
+ return false;
+}
+
+/**
+ * 是否数组
+ */
+function array(value) {
+ if (typeof Array.isArray === 'function') {
+ return Array.isArray(value);
+ }
+ return Object.prototype.toString.call(value) === '[object Array]';
+}
+
+/**
+ * 是否对象
+ */
+function object(value) {
+ return Object.prototype.toString.call(value) === '[object Object]';
+}
+
+/**
+ * 是否短信验证码
+ */
+function code(value, len = 6) {
+ return new RegExp(`^\\d{${len}}$`).test(value);
+}
+
+/**
+ * 是否函数方法
+ * @param {Object} value
+ */
+function func(value) {
+ return typeof value === 'function';
+}
+
+/**
+ * 是否promise对象
+ * @param {Object} value
+ */
+function promise(value) {
+ return object(value) && func(value.then) && func(value.catch);
+}
+
+/** 是否图片格式
+ * @param {Object} value
+ */
+function image(value) {
+ const newValue = value.split('?')[0];
+ const IMAGE_REGEXP = /\.(jpeg|jpg|gif|png|svg|webp|jfif|bmp|dpg)/i;
+ return IMAGE_REGEXP.test(newValue);
+}
+
+/**
+ * 是否视频格式
+ * @param {Object} value
+ */
+function video(value) {
+ const VIDEO_REGEXP = /\.(mp4|mpg|mpeg|dat|asf|avi|rm|rmvb|mov|wmv|flv|mkv|m3u8)/i;
+ return VIDEO_REGEXP.test(value);
+}
+
+/**
+ * 是否为正则对象
+ * @param {Object}
+ * @return {Boolean}
+ */
+function regExp(o) {
+ return o && Object.prototype.toString.call(o) === '[object RegExp]';
+}
+
+export default {
+ email,
+ mobile,
+ url,
+ date,
+ dateISO,
+ number,
+ digits,
+ idCard,
+ carNo,
+ amount,
+ chinese,
+ letter,
+ enOrNum,
+ contains,
+ range,
+ rangeLength,
+ empty,
+ isEmpty: empty,
+ isNumber: number,
+ jsonString,
+ landline,
+ object,
+ array,
+ code,
+};
diff --git a/sheep/helper/throttle.js b/sheep/helper/throttle.js
new file mode 100644
index 0000000..c318127
--- /dev/null
+++ b/sheep/helper/throttle.js
@@ -0,0 +1,31 @@
+let timer;
+let flag;
+/**
+ * 节流原理:在一定时间内,只能触发一次
+ *
+ * @param {Function} func 要执行的回调函数
+ * @param {Number} wait 延时的时间
+ * @param {Boolean} immediate 是否立即执行
+ * @return null
+ */
+function throttle(func, wait = 500, immediate = true) {
+ if (immediate) {
+ if (!flag) {
+ flag = true;
+ // 如果是立即执行,则在wait毫秒内开始时执行
+ typeof func === 'function' && func();
+ timer = setTimeout(() => {
+ flag = false;
+ }, wait);
+ } else {
+ }
+ } else if (!flag) {
+ flag = true;
+ // 如果是非立即执行,则在wait毫秒内的结束处执行
+ timer = setTimeout(() => {
+ flag = false;
+ typeof func === 'function' && func();
+ }, wait);
+ }
+}
+export default throttle;
diff --git a/sheep/helper/tools.js b/sheep/helper/tools.js
new file mode 100644
index 0000000..49efcec
--- /dev/null
+++ b/sheep/helper/tools.js
@@ -0,0 +1,67 @@
+import router from '@/sheep/router';
+export default {
+ /**
+ * 打电话
+ * @param {String} phoneNumber - 数字字符串
+ */
+ callPhone(phoneNumber = '') {
+ let num = phoneNumber.toString();
+ uni.makePhoneCall({
+ phoneNumber: num,
+ fail(err) {
+ console.log('makePhoneCall出错', err);
+ },
+ });
+ },
+
+ /**
+ * 微信头像
+ * @param {String} url -图片地址
+ */
+ checkMPUrl(url) {
+ // #ifdef MP
+ if (
+ url.substring(0, 4) === 'http' &&
+ url.substring(0, 5) !== 'https' &&
+ url.substring(0, 12) !== 'http://store' &&
+ url.substring(0, 10) !== 'http://tmp' &&
+ url.substring(0, 10) !== 'http://usr'
+ ) {
+ url = 'https' + url.substring(4, url.length);
+ }
+ // #endif
+ return url;
+ },
+
+ /**
+ * getUuid 生成唯一id
+ */
+ getUuid(len = 32, firstU = true, radix = null) {
+ const chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('');
+ const uuid = [];
+ radix = radix || chars.length;
+
+ if (len) {
+ // 如果指定uuid长度,只是取随机的字符,0|x为位运算,能去掉x的小数位,返回整数位
+ for (let i = 0; i < len; i++) uuid[i] = chars[0 | (Math.random() * radix)];
+ } else {
+ let r;
+ // rfc4122标准要求返回的uuid中,某些位为固定的字符
+ uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-';
+ uuid[14] = '4';
+
+ for (let i = 0; i < 36; i++) {
+ if (!uuid[i]) {
+ r = 0 | (Math.random() * 16);
+ uuid[i] = chars[i == 19 ? (r & 0x3) | 0x8 : r];
+ }
+ }
+ }
+ // 移除第一个字符,并用u替代,因为第一个字符为数值时,该guuid不能用作id或者class
+ if (firstU) {
+ uuid.shift();
+ return `u${uuid.join('')}`;
+ }
+ return uuid.join('');
+ },
+};
diff --git a/sheep/helper/utils.js b/sheep/helper/utils.js
new file mode 100644
index 0000000..a0dd86f
--- /dev/null
+++ b/sheep/helper/utils.js
@@ -0,0 +1,172 @@
+export function isArray(value) {
+ if (typeof Array.isArray === 'function') {
+ return Array.isArray(value);
+ } else {
+ return Object.prototype.toString.call(value) === '[object Array]';
+ }
+}
+
+export function isObject(value) {
+ return Object.prototype.toString.call(value) === '[object Object]';
+}
+
+export function isNumber(value) {
+ return !isNaN(Number(value));
+}
+
+export function isFunction(value) {
+ return typeof value == 'function';
+}
+
+export function isString(value) {
+ return typeof value == 'string';
+}
+
+export function isEmpty(value) {
+ if (value === '' || value === undefined || value === null){
+ return true;
+ }
+
+ if (isArray(value)) {
+ return value.length === 0;
+ }
+
+ if (isObject(value)) {
+ return Object.keys(value).length === 0;
+ }
+
+ return false
+}
+
+export function isBoolean(value) {
+ return typeof value === 'boolean';
+}
+
+export function last(data) {
+ if (isArray(data) || isString(data)) {
+ return data[data.length - 1];
+ }
+}
+
+export function cloneDeep(obj) {
+ const d = isArray(obj) ? [...obj] : {};
+
+ if (isObject(obj)) {
+ for (const key in obj) {
+ if (obj[key]) {
+ if (obj[key] && typeof obj[key] === 'object') {
+ d[key] = cloneDeep(obj[key]);
+ } else {
+ d[key] = obj[key];
+ }
+ }
+ }
+ }
+
+ return d;
+}
+
+export function clone(obj) {
+ return Object.create(Object.getPrototypeOf(obj), Object.getOwnPropertyDescriptors(obj));
+}
+
+export function deepMerge(a, b) {
+ let k;
+ for (k in b) {
+ a[k] = a[k] && a[k].toString() === '[object Object]' ? deepMerge(a[k], b[k]) : (a[k] = b[k]);
+ }
+ return a;
+}
+
+export function contains(parent, node) {
+ while (node && (node = node.parentNode)) if (node === parent) return true;
+ return false;
+}
+
+export function orderBy(list, key) {
+ return list.sort((a, b) => a[key] - b[key]);
+}
+
+export function deepTree(list) {
+ const newList = [];
+ const map = {};
+
+ list.forEach((e) => (map[e.id] = e));
+
+ list.forEach((e) => {
+ const parent = map[e.parentId];
+
+ if (parent) {
+ (parent.children || (parent.children = [])).push(e);
+ } else {
+ newList.push(e);
+ }
+ });
+
+ const fn = (list) => {
+ list.map((e) => {
+ if (e.children instanceof Array) {
+ e.children = orderBy(e.children, 'orderNum');
+
+ fn(e.children);
+ }
+ });
+ };
+
+ fn(newList);
+
+ return orderBy(newList, 'orderNum');
+}
+
+export function revDeepTree(list = []) {
+ const d = [];
+ let id = 0;
+
+ const deep = (list, parentId) => {
+ list.forEach((e) => {
+ if (!e.id) {
+ e.id = id++;
+ }
+
+ e.parentId = parentId;
+
+ d.push(e);
+
+ if (e.children && isArray(e.children)) {
+ deep(e.children, e.id);
+ }
+ });
+ };
+
+ deep(list || [], null);
+
+ return d;
+}
+
+export function basename(path) {
+ let index = path.lastIndexOf('/');
+ index = index > -1 ? index : path.lastIndexOf('\\');
+ if (index < 0) {
+ return path;
+ }
+ return path.substring(index + 1);
+}
+
+export function isWxBrowser() {
+ const ua = navigator.userAgent.toLowerCase();
+ if (ua.match(/MicroMessenger/i) == 'micromessenger') {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+/**
+ * @description 如果value小于min,取min;如果value大于max,取max
+ * @param {number} min
+ * @param {number} max
+ * @param {number} value
+ */
+export function range(min = 0, max = 0, value = 0) {
+ return Math.max(min, Math.min(max, Number(value)));
+}
diff --git a/sheep/hooks/useApp.js b/sheep/hooks/useApp.js
new file mode 100644
index 0000000..e69de29
diff --git a/sheep/hooks/useGoods.js b/sheep/hooks/useGoods.js
new file mode 100644
index 0000000..1969da9
--- /dev/null
+++ b/sheep/hooks/useGoods.js
@@ -0,0 +1,655 @@
+import { ref } from 'vue';
+import dayjs from 'dayjs';
+import $url from '@/sheep/url';
+import { formatDate } from '@/sheep/util';
+
+/**
+ * 格式化销量
+ * @param {'exact' | string} type 格式类型:exact=精确值,其它=大致数量
+ * @param {number} num 销量
+ * @return {string} 格式化后的销量字符串
+ */
+export function formatSales(type, num) {
+ let prefix = type !== 'exact' && num < 10 ? '销量' : '已售';
+ return formatNum(prefix, type, num)
+}
+
+/**
+ * 格式化兑换量
+ * @param {'exact' | string} type 格式类型:exact=精确值,其它=大致数量
+ * @param {number} num 销量
+ * @return {string} 格式化后的销量字符串
+ */
+export function formatExchange(type, num) {
+ return formatNum('已兑换', type, num)
+}
+
+
+/**
+ * 格式化库存
+ * @param {'exact' | any} type 格式类型:exact=精确值,其它=大致数量
+ * @param {number} num 销量
+ * @return {string} 格式化后的销量字符串
+ */
+export function formatStock(type, num) {
+ return formatNum('库存', type, num)
+}
+
+/**
+ * 格式化数字
+ * @param {string} prefix 前缀
+ * @param {'exact' | string} type 格式类型:exact=精确值,其它=大致数量
+ * @param {number} num 销量
+ * @return {string} 格式化后的销量字符串
+ */
+export function formatNum(prefix, type, num) {
+ num = (num || 0);
+ // 情况一:精确数值
+ if (type === 'exact') {
+ return prefix + num;
+ }
+ // 情况二:小于等于 10
+ if (num < 10) {
+ return `${prefix}≤10`;
+ }
+ // 情况三:大于 10,除第一位外,其它位都显示为0
+ // 例如:100 - 199 显示为 100+
+ // 9000 - 9999 显示为 9000+
+ const numStr = num.toString();
+ const first = numStr[0];
+ const other = '0'.repeat(numStr.length - 1);
+ return `${prefix}${first}${other}+`;
+}
+
+// 格式化价格
+export function formatPrice(e) {
+ return e.length === 1 ? e[0] : e.join('~');
+}
+
+// 视频格式后缀列表
+const VIDEO_SUFFIX_LIST = ['.avi', '.mp4']
+
+/**
+ * 转换商品轮播的链接列表:根据链接的后缀,判断是视频链接还是图片链接
+ *
+ * @param {string[]} urlList 链接列表
+ * @return {{src: string, type: 'video' | 'image' }[]} 转换后的链接列表
+ */
+export function formatGoodsSwiper(urlList) {
+ return urlList?.filter(url => url).map((url, key) => {
+ const isVideo = VIDEO_SUFFIX_LIST.some(suffix => url.includes(suffix));
+ const type = isVideo ? 'video' : 'image'
+ const src = $url.cdn(url);
+ return { type, src }
+ }) || [];
+}
+
+/**
+ * 格式化订单状态的颜色
+ *
+ * @param order 订单
+ * @return {string} 颜色的 class 名称
+ */
+export function formatOrderColor(order) {
+ if (order.status === 0) {
+ return 'info-color';
+ }
+ if (order.status === 10
+ || order.status === 20
+ || (order.status === 30 && !order.commentStatus)) {
+ return 'warning-color';
+ }
+ if (order.status === 30 && order.commentStatus) {
+ return 'success-color';
+ }
+ return 'danger-color';
+}
+
+/**
+ * 格式化订单状态
+ *
+ * @param order 订单
+ */
+export function formatOrderStatus(order) {
+ if (order.status === 0) {
+ return '待付款';
+ }
+ if (order.status === 10 && order.deliveryType === 1) {
+ return '待发货';
+ }
+ if (order.status === 10 && order.deliveryType === 2) {
+ return '待核销';
+ }
+ if (order.status === 20) {
+ return '待收货';
+ }
+ if (order.status === 30 && !order.commentStatus) {
+ return '待评价';
+ }
+ if (order.status === 30 && order.commentStatus) {
+ return '已完成';
+ }
+ return '已关闭';
+}
+
+/**
+ * 格式化订单状态
+ *
+ * @param order 订单
+ */
+export function formatWorkerOrderStatus(order) {
+ if (order.status === 0) {
+ order.statusStr = '待付款';
+ return order.statusStr;
+ }
+ if (order.status === 10) {
+ order.statusStr = '待服务';
+ return order.statusStr;
+ }
+ if (order.status === 20) {
+ order.statusStr = '服务中';
+ return order.statusStr;
+ }
+ if (order.status === 30) {
+ order.statusStr = '已完成';
+ return order.statusStr;
+ }
+
+ order.statusStr = '已取消';
+ return order.statusStr;
+}
+
+/**
+ * 格式化订单状态
+ *
+ * @param order 订单
+ */
+export function formatBlindOrderStatus(order) {
+ if (order.status === 0) {
+ order.statusStr = '待付款';
+ return order.statusStr;
+ }
+ if (order.status === 10) {
+ order.statusStr = '待抢单';
+ return order.statusStr;
+ }
+ if (order.status === 20) {
+ order.statusStr = '服务中';
+ return order.statusStr;
+ }
+ if (order.status === 30) {
+ order.statusStr = '已完成';
+ return order.statusStr;
+ }
+
+ order.statusStr = '已取消';
+ return order.statusStr;
+}
+
+/**
+ * 格式化订单状态
+ *
+ * @param order 订单
+ */
+export function formatMyOrderStatus(order) {
+ if (order.status === 0) {
+ order.statusStr = '待付款';
+ return order.statusStr;
+ }
+ if (order.status === 10) {
+ order.statusStr = '待服务';
+ return order.statusStr;
+ }
+ if (order.status === 20) {
+ order.statusStr = '服务中';
+ return order.statusStr;
+ }
+ if (order.status === 30 && !order.commentStatus) {
+ order.statusStr = '待评价';
+ return order.statusStr;
+ }
+ if (order.status === 30 && order.commentStatus) {
+ order.statusStr = '已完成';
+ return order.statusStr;
+ }
+
+ order.statusStr = '已取消';
+ return order.statusStr;
+}
+
+/**
+ * 格式化订单状态的描述
+ *
+ * @param order 订单
+ */
+export function formatOrderStatusDescription(order) {
+ if (order.status === 0) {
+ return `请在 ${ formatDate(order.payExpireTime) } 前完成支付`;
+ }
+ if (order.status === 10) {
+ return '商家未发货,请耐心等待';
+ }
+ if (order.status === 20) {
+ return '商家已发货,请耐心等待';
+ }
+ if (order.status === 30 && !order.commentStatus) {
+ return '已收货,快去评价一下吧';
+ }
+ if (order.status === 30 && order.commentStatus) {
+ return '交易完成,感谢您的支持';
+ }
+ return '订单取消';
+}
+
+/**
+ * 格式化订单状态的描述
+ *
+ * @param order 订单
+ */
+export function formatMyOrderStatusDescription(order) {
+ if (order.status === 0) {
+ return `请在 ${ formatDate(order.payExpireTime) } 前完成支付`;
+ }
+ if (order.status === 10) {
+ return '店员未接单,请耐心等待';
+ }
+ if (order.status === 20) {
+ return '店员已接单,请打开微信搜索权限,等待添加';
+ }
+ if (order.status === 30 && !order.commentStatus) {
+ return '店员已完成服务,快去评价一下吧';
+ }
+ if (order.status === 30 && order.commentStatus) {
+ return '店员已完成服务,感谢您的支持';
+ }
+ return '订单已取消,有缘自会相遇';
+}
+
+
+/**
+ * 格式化订单状态的描述
+ *
+ * @param order 订单
+ */
+export function formatWorkerOrderStatusDescription(order) {
+ if (order.status === 0) {
+ return `老板未付款,可以主动联系老板下单`;
+ }
+ if (order.status === 10) {
+ return '老板已付款,请尽快添加老板,开始服务';
+ }
+ if (order.status === 20) {
+ return '已抢单成功,快去添加老板,开始服务';
+ }
+ if (order.status === 30 && !order.commentStatus) {
+ return '已完成服务,快去邀请老板评价一下吧';
+ }
+ if (order.status === 30 && order.commentStatus) {
+ return '已完成服务,做的很好';
+ }
+ return '交易关闭';
+}
+
+/**
+ * 格式化订单状态的描述
+ *
+ * @param order 订单
+ */
+export function formatBlindOrderStatusDescription(order) {
+ if (order.status === 0) {
+ return `老板未付款,可以主动联系老板下单`;
+ }
+ if (order.status === 10) {
+ return '老板已付款,抢单成功后添加老板,开始服务';
+ }
+ if (order.status === 20) {
+ return '已抢单成功,快去添加老板,开始服务';
+ }
+ if (order.status === 30 && !order.commentStatus) {
+ return '已完成服务,快去邀请老板评价一下吧';
+ }
+ if (order.status === 30 && order.commentStatus) {
+ return '已完成服务,做的很好';
+ }
+ return '交易关闭';
+}
+
+/**
+ * 处理订单的 button 操作按钮数组
+ *
+ * @param order 订单
+ */
+export function handleOrderButtons(order) {
+ order.buttons = []
+ if (order.type === 3) { // 查看拼团
+ order.buttons.push('combination');
+ }
+ if (order.status === 20) { // 确认收货
+ order.buttons.push('confirm');
+ }
+ if (order.logisticsId > 0) { // 查看物流
+ order.buttons.push('express');
+ }
+ if (order.status === 0) { // 取消订单 / 发起支付
+ order.buttons.push('cancel');
+ order.buttons.push('pay');
+ }
+ if (order.status === 30 && !order.commentStatus) { // 发起评价
+ order.buttons.push('comment');
+ }
+ if (order.status === 40) { // 删除订单
+ order.buttons.push('delete');
+ }
+}
+
+/**
+ * 处理订单的 button 操作按钮数组
+ *
+ * @param order 订单
+ */
+export function handleWorkerOrderButtons(order) {
+ order.buttons = []
+ if (order.status === 10) { // 待服务
+ order.buttons.push('unpay');
+ order.buttons.push('agree');
+ }
+ if (order.status === 20) { // 服务中
+ order.buttons.push('unpay');
+ order.buttons.push('confirm');
+ }
+ if (order.status === 0) { // 取消订单 / 发起支付
+ order.buttons.push('detail');
+ order.buttons.push('invite');
+ }
+ if (order.status === 30) { // 已完成
+ order.buttons.push('detail');
+ order.buttons.push('invite');
+ }
+ if (order.status === 40) { // 取消订单
+ order.buttons.push('detail');
+ order.buttons.push('invite');
+ }
+
+}
+
+/**
+ * 处理订单的 button 操作按钮数组
+ *
+ * @param order 订单
+ */
+export function handleBlindOrderButtons(order, userId) {
+ order.buttons = []
+ if (order.status === 10) { // 待服务
+ order.buttons.push('detail');
+ order.buttons.push('agree');
+ //order.buttons.push('invite');
+ }
+ if (order.status === 20) { // 服务中
+ // 抢单后
+ if(order.workerUserId == userId){
+ order.buttons.push('unpay');
+ order.buttons.push('confirm');
+ }else{
+ order.buttons.push('other');
+ }
+ }
+ if (order.status === 0) { // 取消订单 / 发起支付
+ order.buttons.push('detail');
+ //order.buttons.push('invite');
+ }
+ if (order.status === 30) { // 已完成
+ order.buttons.push('detail');
+ if(order.workerUserId == userId){
+ order.buttons.push('invite2');
+ }
+ }
+ if (order.status === 40) { // 取消订单
+ order.buttons.push('detail');
+ //order.buttons.push('invite');
+ }
+
+}
+
+/**
+ * 处理订单的 button 操作按钮数组
+ *
+ * @param order 订单
+ */
+export function handleMyOrderButtons(order) {
+ order.buttons = []
+ if (order.type === 3) { // 查看拼团
+ order.buttons.push('combination');
+ }
+ if (order.status === 10) { // 待服务
+ order.buttons.push('unpay');
+ order.buttons.push('buy');
+ }
+ if (order.status === 20) { // 服务中
+ order.buttons.push('detail');
+ order.buttons.push('buy');
+ }
+ if (order.logisticsId > 0) { // 查看物流
+ order.buttons.push('express');
+ }
+ if (order.status === 0) { // 取消订单 / 发起支付
+ order.buttons.push('cancel');
+ order.buttons.push('pay');
+ }
+ if (order.status === 30 && !order.commentStatus) { // 发起评价
+ order.buttons.push('comment');
+ order.buttons.push('buy');
+ }
+ if (order.status === 30 && order.commentStatus) { // 发起评价
+ order.buttons.push('detail');
+ order.buttons.push('buy');
+ }
+ if (order.status === 40) { // 删除订单
+ //order.buttons.push('delete');
+ order.buttons.push('detail');
+ order.buttons.push('buy');
+ }
+}
+
+/**
+ * 格式化售后状态
+ *
+ * @param afterSale 售后
+ */
+export function formatAfterSaleStatus(afterSale) {
+ if (afterSale.status === 10) {
+ return '申请售后';
+ }
+ if (afterSale.status === 20) {
+ return '商品待退货';
+ }
+ if (afterSale.status === 30) {
+ return '商家待收货';
+ }
+ if (afterSale.status === 40) {
+ return '等待退款';
+ }
+ if (afterSale.status === 50) {
+ return '取消成功';
+ }
+ if (afterSale.status === 61) {
+ return '买家取消';
+ }
+ if (afterSale.status === 62) {
+ return '商家拒绝';
+ }
+ if (afterSale.status === 63) {
+ return '商家拒收货';
+ }
+ return '未知状态';
+}
+
+/**
+ * 格式化售后状态的描述
+ *
+ * @param afterSale 售后
+ */
+export function formatAfterSaleStatusDescription(afterSale) {
+ if (afterSale.status === 10) {
+ return '退款申请待商家处理';
+ }
+ if (afterSale.status === 20) {
+ return '请退货并填写物流信息';
+ }
+ if (afterSale.status === 30) {
+ return '退货退款申请待商家处理';
+ }
+ if (afterSale.status === 40) {
+ return '等待退款';
+ }
+ if (afterSale.status === 50) {
+ return '退款成功';
+ }
+ if (afterSale.status === 61) {
+ return '退款关闭';
+ }
+ if (afterSale.status === 62) {
+ return `商家不同意退款申请,拒绝原因:${afterSale.auditReason}`;
+ }
+ if (afterSale.status === 63) {
+ return `商家拒绝收货,不同意退款,拒绝原因:${afterSale.auditReason}`;
+ }
+ return '未知状态';
+}
+
+/**
+ * 处理售后的 button 操作按钮数组
+ *
+ * @param afterSale 售后
+ */
+export function handleAfterSaleButtons(afterSale) {
+ afterSale.buttons = [];
+ if ([10, 20, 30].includes(afterSale.status)) { // 取消订单
+ afterSale.buttons.push('cancel');
+ }
+ if (afterSale.status === 20) { // 退货信息
+ afterSale.buttons.push('delivery');
+ }
+}
+
+/**
+ * 倒计时
+ * @param toTime 截止时间
+ * @param fromTime 起始时间,默认当前时间
+ * @return {{s: string, ms: number, h: string, m: string}} 持续时间
+ */
+export function useDurationTime(toTime, fromTime = '') {
+ toTime = getDayjsTime(toTime);
+ if (fromTime === '') {
+ fromTime = dayjs();
+ }
+ let duration = ref(toTime - fromTime);
+ if (duration.value > 0) {
+ setTimeout(() => {
+ if (duration.value > 0) {
+ duration.value -= 1000;
+ }
+ }, 1000);
+ }
+
+ let durationTime = dayjs.duration(duration.value);
+ return {
+ h: (durationTime.months() * 30 * 24 + durationTime.days() * 24 + durationTime.hours())
+ .toString()
+ .padStart(2, '0'),
+ m: durationTime.minutes().toString().padStart(2, '0'),
+ s: durationTime.seconds().toString().padStart(2, '0'),
+ ms: durationTime.$ms,
+ };
+}
+
+/**
+ * 转换为 Dayjs
+ * @param {any} time 时间
+ * @return {dayjs.Dayjs}
+ */
+function getDayjsTime(time) {
+ time = time.toString();
+ if (time.indexOf('-') > 0) {
+ // 'date'
+ return dayjs(time);
+ }
+ if (time.length > 10) {
+ // 'timestamp'
+ return dayjs(parseInt(time));
+ }
+ if (time.length === 10) {
+ // 'unixTime'
+ return dayjs.unix(parseInt(time));
+ }
+}
+
+/**
+ * 将分转成元
+ *
+ * @param price 分,例如说 100 分
+ * @returns {string} 元,例如说 1.00 元
+ */
+export function fen2yuan(price) {
+ return (price / 100.0).toFixed(2)
+}
+
+/**
+ * 从商品 SKU 数组中,转换出商品属性的数组
+ *
+ * 类似结构:[{
+ * id: // 属性的编号
+ * name: // 属性的名字
+ * values: [{
+ * id: // 属性值的编号
+ * name: // 属性值的名字
+ * }]
+ * }]
+ *
+ * @param skus 商品 SKU 数组
+ */
+export function convertProductPropertyList(skus) {
+ let result = [];
+ for (const sku of skus) {
+ if (!sku.properties) {
+ continue
+ }
+ for (const property of sku.properties) {
+ // ① 先处理属性
+ let resultProperty = result.find(item => item.id === property.propertyId)
+ if (!resultProperty) {
+ resultProperty = {
+ id: property.propertyId,
+ name: property.propertyName,
+ values: []
+ }
+ result.push(resultProperty)
+ }
+ // ② 再处理属性值
+ let resultValue = resultProperty.values.find(item => item.id === property.valueId)
+ if (!resultValue) {
+ resultProperty.values.push({
+ id: property.valueId,
+ name: property.valueName
+ })
+ }
+ }
+ }
+ return result;
+}
+
+/**
+ * 格式化满减送活动的规则
+ *
+ * @param activity 活动信息
+ * @param rule 优惠规格
+ * @returns {string} 规格字符串
+ */
+export function formatRewardActivityRule(activity, rule) {
+ if (activity.conditionType === 10) {
+ return `满 ${fen2yuan(rule.limit)} 元减 ${fen2yuan(rule.discountPrice)} 元`;
+ }
+ if (activity.conditionType === 20) {
+ return `满 ${rule.limit} 件减 ${fen2yuan(rule.discountPrice)} 元`;
+ }
+ return '';
+}
diff --git a/sheep/hooks/useModal.js b/sheep/hooks/useModal.js
new file mode 100644
index 0000000..003fe80
--- /dev/null
+++ b/sheep/hooks/useModal.js
@@ -0,0 +1,141 @@
+import $store from '@/sheep/store';
+import $helper from '@/sheep/helper';
+import dayjs from 'dayjs';
+import { ref } from 'vue';
+import test from '@/sheep/helper/test.js';
+import AuthUtil from '@/sheep/api/member/auth';
+
+// 打开授权弹框
+export function showAuthModal(type = 'smsLogin') {
+ const modal = $store('modal');
+ if (modal.auth !== '') {
+ // 注意:延迟修改,保证下面的 closeAuthModal 先执行掉
+ setTimeout(() => {
+ modal.$patch((state) => {
+ state.auth = type;
+ });
+ }, 500);
+ closeAuthModal();
+ } else {
+ modal.$patch((state) => {
+ state.auth = type;
+ });
+ }
+}
+
+// 关闭授权弹框
+export function closeAuthModal() {
+ $store('modal').$patch((state) => {
+ state.auth = '';
+ });
+}
+
+// 打开分享弹框
+export function showShareModal() {
+ $store('modal').$patch((state) => {
+ state.share = true;
+ });
+}
+
+// 关闭分享弹框
+export function closeShareModal() {
+ $store('modal').$patch((state) => {
+ state.share = false;
+ });
+}
+
+// 打开快捷菜单
+export function showMenuTools() {
+ $store('modal').$patch((state) => {
+ state.menu = true;
+ });
+}
+
+// 关闭快捷菜单
+export function closeMenuTools() {
+ $store('modal').$patch((state) => {
+ state.menu = false;
+ });
+}
+
+// 发送短信验证码 60秒
+export function getSmsCode(event, mobile) {
+ const modalStore = $store('modal');
+ const lastSendTimer = modalStore.lastTimer[event];
+ if (typeof lastSendTimer === 'undefined') {
+ $helper.toast('短信发送事件错误');
+ return;
+ }
+
+ const duration = dayjs().unix() - lastSendTimer;
+ const canSend = duration >= 60;
+ if (!canSend) {
+ $helper.toast('请稍后再试');
+ return;
+ }
+ // 只有 mobile 非空时才校验。因为部分场景(修改密码),不需要输入手机
+ if (mobile && !test.mobile(mobile)) {
+ $helper.toast('手机号码格式不正确');
+ return;
+ }
+
+ // 发送验证码 + 更新上次发送验证码时间
+ let scene = -1;
+ switch (event) {
+ case 'resetPassword':
+ scene = 4;
+ break;
+ case 'changePassword':
+ scene = 3;
+ break;
+ case 'changeMobile':
+ scene = 2;
+ break;
+ case 'smsLogin':
+ scene = 1;
+ break;
+ }
+ AuthUtil.sendSmsCode(mobile, scene).then((res) => {
+ if (res.code === 0) {
+ modalStore.$patch((state) => {
+ state.lastTimer[event] = dayjs().unix();
+ });
+ }
+ });
+}
+
+// 获取短信验证码倒计时 -- 60秒
+export function getSmsTimer(event, mobile = '') {
+ const modalStore = $store('modal');
+ const lastSendTimer = modalStore.lastTimer[event];
+
+ if (typeof lastSendTimer === 'undefined') {
+ $helper.toast('短信发送事件错误');
+ return;
+ }
+
+ const duration = ref(dayjs().unix() - lastSendTimer - 60);
+ const canSend = duration.value >= 0;
+
+ if (canSend) {
+ return '获取验证码';
+ }
+
+ if (!canSend) {
+ setTimeout(() => {
+ duration.value++;
+ }, 1000);
+ return -duration.value.toString() + ' 秒';
+ }
+}
+
+// 记录广告弹框历史
+export function saveAdvHistory(adv) {
+ const modal = $store('modal');
+
+ modal.$patch((state) => {
+ if (!state.advHistory.includes(adv.imgUrl)) {
+ state.advHistory.push(adv.imgUrl);
+ }
+ });
+}
diff --git a/sheep/hooks/useWebSocket.js b/sheep/hooks/useWebSocket.js
new file mode 100644
index 0000000..c3980c4
--- /dev/null
+++ b/sheep/hooks/useWebSocket.js
@@ -0,0 +1,163 @@
+import { onBeforeUnmount, reactive, ref, getCurrentInstance } from 'vue';
+import { baseUrl, websocketPath } from '@/sheep/config';
+import { copyValueToTarget } from '@/sheep/util';
+
+/**
+ * WebSocket 创建 hook
+ * @param opt 连接配置
+ * @return {{options: *}}
+ */
+export function useWebSocket(opt) {
+ const { proxy } = getCurrentInstance();
+
+ const getAccessToken = () => {
+ return uni.getStorageSync('token');
+ };
+
+ const getUrl = () => {
+ return (baseUrl + websocketPath).replace('http', 'ws') + '?token=' + getAccessToken();
+ };
+
+ const options = reactive({
+ url: getUrl(), // ws 地址
+ isReconnecting: false, // 正在重新连接
+ reconnectInterval: 3000, // 重连间隔,单位毫秒
+ heartBeatInterval: 5000, // 心跳间隔,单位毫秒
+ pingTimeoutDuration: 1000, // 超过这个时间,后端没有返回pong,则判定后端断线了。
+ heartBeatTimer: null, // 心跳计时器
+ destroy: false, // 是否销毁
+ pingTimeout: null, // 心跳检测定时器
+ reconnectTimeout: null, // 重连定时器ID的属性
+ onConnected: () => {
+ }, // 连接成功时触发
+ onClosed: () => {
+ }, // 连接关闭时触发
+ onMessage: (data) => {
+ }, // 收到消息
+ });
+ const SocketTask = ref(null); // SocketTask 由 uni.connectSocket() 接口创建
+
+ const initEventListeners = () => {
+ // 监听 WebSocket 连接打开事件
+ SocketTask.value.onOpen(() => {
+ console.log('WebSocket 连接成功');
+ // 连接成功时触发
+ options.onConnected();
+ // 开启心跳检查
+ startHeartBeat();
+ });
+ // 监听 WebSocket 接受到服务器的消息事件
+ SocketTask.value.onMessage((res) => {
+ try {
+ if (res.data === 'pong') {
+ // 收到心跳重置心跳超时检查
+ resetPingTimeout();
+ } else {
+ options.onMessage(JSON.parse(res.data));
+ }
+ } catch (error) {
+ console.error(error);
+ }
+ });
+ // 监听 WebSocket 连接关闭事件
+ SocketTask.value.onClose((event) => {
+ // 情况一:实例销毁
+ if (options.destroy) {
+ options.onClosed();
+ } else { // 情况二:连接失败重连
+ // 停止心跳检查
+ stopHeartBeat();
+ // 重连
+ reconnect();
+ }
+ });
+ };
+
+ // 发送消息
+ const sendMessage = (message) => {
+ if (SocketTask.value && !options.destroy) {
+ SocketTask.value.send({ data: message });
+ }
+ };
+ // 开始心跳检查
+ const startHeartBeat = () => {
+ options.heartBeatTimer = setInterval(() => {
+ sendMessage('ping');
+ options.pingTimeout = setTimeout(() => {
+ // 如果在超时时间内没有收到 pong,则认为连接断开
+ reconnect();
+ }, options.pingTimeoutDuration);
+ }, options.heartBeatInterval);
+ };
+ // 停止心跳检查
+ const stopHeartBeat = () => {
+ clearInterval(options.heartBeatTimer);
+ resetPingTimeout();
+ };
+
+ // WebSocket 重连
+ const reconnect = () => {
+ if (options.destroy || !SocketTask.value) {
+ // 如果WebSocket已被销毁或尚未完全关闭,不进行重连
+ return;
+ }
+
+ // 重连中
+ options.isReconnecting = true;
+
+ // 清除现有的重连标志,以避免多次重连
+ if (options.reconnectTimeout) {
+ clearTimeout(options.reconnectTimeout);
+ }
+
+ // 设置重连延迟
+ options.reconnectTimeout = setTimeout(() => {
+ // 检查组件是否仍在运行和WebSocket是否关闭
+ if (!options.destroy) {
+ // 重置重连标志
+ options.isReconnecting = false;
+ // 初始化新的WebSocket连接
+ initSocket();
+ }
+ }, options.reconnectInterval);
+ };
+
+ const resetPingTimeout = () => {
+ if (options.pingTimeout) {
+ clearTimeout(options.pingTimeout);
+ options.pingTimeout = null; // 清除超时ID
+ }
+ };
+
+ const close = () => {
+ options.destroy = true;
+ stopHeartBeat();
+ if (options.reconnectTimeout) {
+ clearTimeout(options.reconnectTimeout);
+ }
+ if (SocketTask.value) {
+ SocketTask.value.close();
+ SocketTask.value = null;
+ }
+ };
+
+ const initSocket = () => {
+ options.destroy = false;
+ copyValueToTarget(options, opt);
+ SocketTask.value = uni.connectSocket({
+ url: getUrl(),
+ complete: () => {
+ },
+ success: () => {
+ },
+ });
+ initEventListeners();
+ };
+
+ initSocket();
+
+ onBeforeUnmount(() => {
+ close();
+ });
+ return { options };
+}
diff --git a/sheep/index.js b/sheep/index.js
new file mode 100644
index 0000000..f00fd29
--- /dev/null
+++ b/sheep/index.js
@@ -0,0 +1,61 @@
+import $url from '@/sheep/url';
+import $router from '@/sheep/router';
+import $platform from '@/sheep/platform';
+import $helper from '@/sheep/helper';
+import zIndex from '@/sheep/config/zIndex.js';
+import $store from '@/sheep/store';
+import dayjs from 'dayjs';
+import relativeTime from 'dayjs/plugin/relativeTime';
+import duration from 'dayjs/plugin/duration';
+import 'dayjs/locale/zh-cn';
+
+dayjs.locale('zh-cn');
+dayjs.extend(relativeTime);
+dayjs.extend(duration);
+
+const sheep = {
+ $store,
+ $url,
+ $router,
+ $platform,
+ $helper,
+ $zIndex: zIndex,
+};
+
+// 加载Shopro底层依赖
+export async function ShoproInit() {
+ // 应用初始化
+ await $store('app').init();
+ await $store('user').getTradeConfig();
+
+ // #ifdef MP
+ // 小程序场景值
+ const config = uni.getLaunchOptionsSync();
+ if(config.scene){
+ $store('sys').setScene(config.scene);
+ }
+ // #endif
+
+ // 平台初始化加载(各平台provider提供不同的加载流程)
+ $platform.load();
+
+ if (process.env.NODE_ENV === 'development') {
+ ShoproDebug();
+ }
+}
+
+// 开发模式
+function ShoproDebug() {
+ // 开发环境引入vconsole调试
+ // #ifdef H5
+ // import("vconsole").then(vconsole => {
+ // new vconsole.default();
+ // });
+ // #endif
+
+ // TODO 芋艿:可以打印路由
+ // 同步前端页面到后端
+ // console.log(ROUTES)
+}
+
+export default sheep;
diff --git a/sheep/libs/mplive-manifest-plugin.js b/sheep/libs/mplive-manifest-plugin.js
new file mode 100644
index 0000000..d1df9bf
--- /dev/null
+++ b/sheep/libs/mplive-manifest-plugin.js
@@ -0,0 +1,32 @@
+const fs = require('fs');
+
+const manifestPath = process.env.UNI_INPUT_DIR + '/manifest.json';
+
+let Manifest = fs.readFileSync(manifestPath, {
+ encoding: 'utf-8'
+});
+
+function mpliveMainfestPlugin(isOpen) {
+ if (process.env.UNI_PLATFORM !== 'mp-weixin') return;
+
+ const manifestData = JSON.parse(Manifest)
+
+ if (isOpen === '0') {
+ delete manifestData['mp-weixin'].plugins['live-player-plugin'];
+ }
+
+ if (isOpen === '1') {
+ manifestData['mp-weixin'].plugins['live-player-plugin'] = {
+ "version": "1.3.5",
+ "provider": "wx2b03c6e691cd7370"
+ }
+ }
+
+ Manifest = JSON.stringify(manifestData, null, 2)
+
+ fs.writeFileSync(manifestPath, Manifest, {
+ "flag": "w"
+ })
+}
+
+export default mpliveMainfestPlugin
diff --git a/sheep/libs/permission.js b/sheep/libs/permission.js
new file mode 100644
index 0000000..59f9413
--- /dev/null
+++ b/sheep/libs/permission.js
@@ -0,0 +1,246 @@
+/// null = 未请求,1 = 已允许,0 = 拒绝|受限, 2 = 系统未开启
+
+var isIOS;
+
+function album() {
+ var result = 0;
+ var PHPhotoLibrary = plus.ios.import('PHPhotoLibrary');
+ var authStatus = PHPhotoLibrary.authorizationStatus();
+ if (authStatus === 0) {
+ result = null;
+ } else if (authStatus == 3) {
+ result = 1;
+ } else {
+ result = 0;
+ }
+ plus.ios.deleteObject(PHPhotoLibrary);
+ return result;
+}
+
+function camera() {
+ var result = 0;
+ var AVCaptureDevice = plus.ios.import('AVCaptureDevice');
+ var authStatus = AVCaptureDevice.authorizationStatusForMediaType('vide');
+ if (authStatus === 0) {
+ result = null;
+ } else if (authStatus == 3) {
+ result = 1;
+ } else {
+ result = 0;
+ }
+ plus.ios.deleteObject(AVCaptureDevice);
+ return result;
+}
+
+function location() {
+ var result = 0;
+ var cllocationManger = plus.ios.import('CLLocationManager');
+ var enable = cllocationManger.locationServicesEnabled();
+ var status = cllocationManger.authorizationStatus();
+ if (!enable) {
+ result = 2;
+ } else if (status === 0) {
+ result = null;
+ } else if (status === 3 || status === 4) {
+ result = 1;
+ } else {
+ result = 0;
+ }
+ plus.ios.deleteObject(cllocationManger);
+ return result;
+}
+
+function push() {
+ var result = 0;
+ var UIApplication = plus.ios.import('UIApplication');
+ var app = UIApplication.sharedApplication();
+ var enabledTypes = 0;
+ if (app.currentUserNotificationSettings) {
+ var settings = app.currentUserNotificationSettings();
+ enabledTypes = settings.plusGetAttribute('types');
+ if (enabledTypes == 0) {
+ result = 0;
+ console.log('推送权限没有开启');
+ } else {
+ result = 1;
+ console.log('已经开启推送功能!');
+ }
+ plus.ios.deleteObject(settings);
+ } else {
+ enabledTypes = app.enabledRemoteNotificationTypes();
+ if (enabledTypes == 0) {
+ result = 3;
+ console.log('推送权限没有开启!');
+ } else {
+ result = 4;
+ console.log('已经开启推送功能!');
+ }
+ }
+ plus.ios.deleteObject(app);
+ plus.ios.deleteObject(UIApplication);
+ return result;
+}
+
+function contact() {
+ var result = 0;
+ var CNContactStore = plus.ios.import('CNContactStore');
+ var cnAuthStatus = CNContactStore.authorizationStatusForEntityType(0);
+ if (cnAuthStatus === 0) {
+ result = null;
+ } else if (cnAuthStatus == 3) {
+ result = 1;
+ } else {
+ result = 0;
+ }
+ plus.ios.deleteObject(CNContactStore);
+ return result;
+}
+
+function record() {
+ var result = null;
+ var avaudiosession = plus.ios.import('AVAudioSession');
+ var avaudio = avaudiosession.sharedInstance();
+ var status = avaudio.recordPermission();
+ console.log('permissionStatus:' + status);
+ if (status === 1970168948) {
+ result = null;
+ } else if (status === 1735552628) {
+ result = 1;
+ } else {
+ result = 0;
+ }
+ plus.ios.deleteObject(avaudiosession);
+ return result;
+}
+
+function calendar() {
+ var result = null;
+ var EKEventStore = plus.ios.import('EKEventStore');
+ var ekAuthStatus = EKEventStore.authorizationStatusForEntityType(0);
+ if (ekAuthStatus == 3) {
+ result = 1;
+ console.log('日历权限已经开启');
+ } else {
+ console.log('日历权限没有开启');
+ }
+ plus.ios.deleteObject(EKEventStore);
+ return result;
+}
+
+function memo() {
+ var result = null;
+ var EKEventStore = plus.ios.import('EKEventStore');
+ var ekAuthStatus = EKEventStore.authorizationStatusForEntityType(1);
+ if (ekAuthStatus == 3) {
+ result = 1;
+ console.log('备忘录权限已经开启');
+ } else {
+ console.log('备忘录权限没有开启');
+ }
+ plus.ios.deleteObject(EKEventStore);
+ return result;
+}
+
+function requestIOS(permissionID) {
+ return new Promise((resolve, reject) => {
+ switch (permissionID) {
+ case 'push':
+ resolve(push());
+ break;
+ case 'location':
+ resolve(location());
+ break;
+ case 'record':
+ resolve(record());
+ break;
+ case 'camera':
+ resolve(camera());
+ break;
+ case 'album':
+ resolve(album());
+ break;
+ case 'contact':
+ resolve(contact());
+ break;
+ case 'calendar':
+ resolve(calendar());
+ break;
+ case 'memo':
+ resolve(memo());
+ break;
+ default:
+ resolve(0);
+ break;
+ }
+ });
+}
+
+function requestAndroid(permissionID) {
+ return new Promise((resolve, reject) => {
+ plus.android.requestPermissions(
+ [permissionID],
+ function (resultObj) {
+ var result = 0;
+ for (var i = 0; i < resultObj.granted.length; i++) {
+ var grantedPermission = resultObj.granted[i];
+ console.log('已获取的权限:' + grantedPermission);
+ result = 1;
+ }
+ for (var i = 0; i < resultObj.deniedPresent.length; i++) {
+ var deniedPresentPermission = resultObj.deniedPresent[i];
+ console.log('拒绝本次申请的权限:' + deniedPresentPermission);
+ result = 0;
+ }
+ for (var i = 0; i < resultObj.deniedAlways.length; i++) {
+ var deniedAlwaysPermission = resultObj.deniedAlways[i];
+ console.log('永久拒绝申请的权限:' + deniedAlwaysPermission);
+ result = -1;
+ }
+ resolve(result);
+ },
+ function (error) {
+ console.log('result error: ' + error.message);
+ resolve({
+ code: error.code,
+ message: error.message,
+ });
+ },
+ );
+ });
+}
+
+function gotoAppPermissionSetting() {
+ if (permission.isIOS) {
+ var UIApplication = plus.ios.import('UIApplication');
+ var application2 = UIApplication.sharedApplication();
+ var NSURL2 = plus.ios.import('NSURL');
+ var setting2 = NSURL2.URLWithString('app-settings:');
+ application2.openURL(setting2);
+ plus.ios.deleteObject(setting2);
+ plus.ios.deleteObject(NSURL2);
+ plus.ios.deleteObject(application2);
+ } else {
+ var Intent = plus.android.importClass('android.content.Intent');
+ var Settings = plus.android.importClass('android.provider.Settings');
+ var Uri = plus.android.importClass('android.net.Uri');
+ var mainActivity = plus.android.runtimeMainActivity();
+ var intent = new Intent();
+ intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
+ var uri = Uri.fromParts('package', mainActivity.getPackageName(), null);
+ intent.setData(uri);
+ mainActivity.startActivity(intent);
+ }
+}
+
+const permission = {
+ get isIOS() {
+ return typeof isIOS === 'boolean'
+ ? isIOS
+ : (isIOS = uni.getSystemInfoSync().platform === 'ios');
+ },
+ requestIOS: requestIOS,
+ requestAndroid: requestAndroid,
+ gotoAppSetting: gotoAppPermissionSetting,
+};
+
+export default permission;
diff --git a/sheep/libs/sdk-h5-weixin.js b/sheep/libs/sdk-h5-weixin.js
new file mode 100644
index 0000000..984b8db
--- /dev/null
+++ b/sheep/libs/sdk-h5-weixin.js
@@ -0,0 +1,184 @@
+/**
+ * 本模块封装微信浏览器下的一些方法。
+ * 更多微信网页开发sdk方法,详见:https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/JS-SDK.html
+ * 有 the permission value is offline verifying 报错请参考 @see https://segmentfault.com/a/1190000042289419 解决
+ */
+
+import jweixin from 'weixin-js-sdk';
+import $helper from '@/sheep/helper';
+import AuthUtil from '@/sheep/api/member/auth';
+
+let configSuccess = false;
+
+export default {
+ // 判断是否在微信中
+ isWechat() {
+ const ua = window.navigator.userAgent.toLowerCase();
+ // noinspection EqualityComparisonWithCoercionJS
+ return ua.match(/micromessenger/i) == 'micromessenger';
+ },
+
+ isReady(api) {
+ jweixin.ready(api);
+ },
+
+ // 初始化 JSSDK
+ async init(callback) {
+ if (!this.isWechat()) {
+ $helper.toast('请使用微信网页浏览器打开');
+ return;
+ }
+
+ // 调用后端接口,获得 JSSDK 初始化所需的签名
+ const url = location.href.split('#')[0];
+ const { code, data } = await AuthUtil.createWeixinMpJsapiSignature(url);
+ if (code === 0) {
+ jweixin.config({
+ debug: false,
+ appId: data.appId,
+ timestamp: data.timestamp,
+ nonceStr: data.nonceStr,
+ signature: data.signature,
+ jsApiList: ['chooseWXPay', 'openLocation', 'getLocation','updateTimelineShareData','scanQRCode'], // TODO 芋艿:后续可以设置更多权限;
+ openTagList: data.openTagList
+ });
+ }
+
+ // 监听结果
+ configSuccess = true;
+ jweixin.error((err) => {
+ configSuccess = false;
+ console.error('微信 JSSDK 初始化失败', err);
+ // $helper.toast('微信JSSDK:' + err.errMsg);
+ });
+ jweixin.ready(() => {
+ if (configSuccess) {
+ console.log('微信 JSSDK 初始化成功');
+ }
+ })
+
+ // 回调
+ if (callback) {
+ callback(data);
+ }
+ },
+
+ //在需要定位页面调用 TODO 芋艿:未测试
+ getLocation(callback) {
+ this.isReady(() => {
+ jweixin.getLocation({
+ type: 'gcj02', // 默认为wgs84的gps坐标,如果要返回直接给openLocation用的火星坐标,可传入'gcj02'
+ success: function (res) {
+ callback(res);
+ },
+ fail: function (res) {
+ console.log('%c微信H5sdk,getLocation失败:', 'color:green;background:yellow');
+ },
+ });
+ });
+ },
+
+ // 获取微信收货地址
+ openAddress(callback) {
+ this.isReady(() => {
+ jweixin.openAddress({
+ success: function (res) {
+ callback.success && callback.success(res);
+ },
+ fail: function (err) {
+ callback.error && callback.error(err);
+ console.log('%c微信H5sdk,openAddress失败:', 'color:green;background:yellow');
+ },
+ complete: function (res) {},
+ });
+ });
+ },
+
+ // 微信扫码 TODO 芋艿:未测试
+ scanQRCode(callback) {
+ this.isReady(() => {
+ jweixin.scanQRCode({
+ needResult: 1, // 默认为0,扫描结果由微信处理,1则直接返回扫描结果,
+ scanType: ['qrCode', 'barCode'], // 可以指定扫二维码还是一维码,默认二者都有
+ success: function (res) {
+ callback(res);
+ },
+ fail: function (res) {
+ console.log('%c微信H5sdk,scanQRCode失败:', 'color:green;background:yellow');
+ },
+ });
+ });
+ },
+
+ // 更新微信分享信息 TODO 芋艿:未测试
+ updateShareInfo(data, callback = null) {
+ this.isReady(() => {
+ const shareData = {
+ title: data.title,
+ desc: data.desc,
+ link: data.link,
+ imgUrl: data.image,
+ success: function (res) {
+ if (callback) {
+ callback(res);
+ }
+ // 分享后的一些操作,比如分享统计等等
+ },
+ cancel: function (res) {},
+ };
+
+ // 新版 分享聊天api
+ jweixin.updateAppMessageShareData(shareData);
+ // 新版 分享到朋友圈api
+ jweixin.updateTimelineShareData(shareData);
+ });
+ },
+
+ // 打开坐标位置 TODO 芋艿:未测试
+ openLocation(data, callback) {
+ this.isReady(() => {
+ jweixin.openLocation({
+ ...data,
+ success: function (res) {
+ console.log(res);
+ }
+ });
+ });
+ },
+
+ // 选择图片 TODO 芋艿:未测试
+ chooseImage(callback) {
+ this.isReady(() => {
+ jweixin.chooseImage({
+ count: 1,
+ sizeType: ['compressed'],
+ sourceType: ['album'],
+ success: function (rs) {
+ callback(rs);
+ },
+ });
+ });
+ },
+
+ // 微信支付
+ wxpay(data, callback) {
+ this.isReady(() => {
+ jweixin.chooseWXPay({
+ timestamp: data.timeStamp, // 支付签名时间戳,注意微信jssdk中的所有使用timestamp字段均为小写。但最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符
+ nonceStr: data.nonceStr, // 支付签名随机串,不长于 32 位
+ package: data.packageValue, // 统一支付接口返回的prepay_id参数值,提交格式如:prepay_id=\*\*\*)
+ signType: data.signType, // 签名方式,默认为'SHA1',使用新版支付需传入'MD5'
+ paySign: data.paySign, // 支付签名
+ success: function (res) {
+ callback.success && callback.success(res);
+ },
+ fail: function (err) {
+ callback.fail && callback.fail(err);
+ },
+ cancel: function (err) {
+ callback.cancel && callback.cancel(err);
+ },
+ });
+ });
+ },
+};
diff --git a/sheep/platform/index.js b/sheep/platform/index.js
new file mode 100644
index 0000000..50e4b8a
--- /dev/null
+++ b/sheep/platform/index.js
@@ -0,0 +1,175 @@
+/**
+ * Shopro 第三方平台功能聚合
+ * @version 1.0.3
+ * @author lidongtony
+ * @param {String} name - 厂商+平台名称
+ * @param {String} provider - 厂商
+ * @param {String} platform - 平台名称
+ * @param {String} os - 系统型号
+ * @param {Object} device - 设备信息
+ */
+
+import { isEmpty } from 'lodash-es';
+// #ifdef H5
+import { isWxBrowser } from '@/sheep/helper/utils';
+// #endif
+import wechat from './provider/wechat/index.js';
+import apple from './provider/apple';
+import share from './share';
+import Pay from './pay';
+
+const device = uni.getSystemInfoSync();
+
+const os = device.platform;
+
+let name = '';
+let provider = '';
+let platform = '';
+let isWechatInstalled = true;
+
+// #ifdef H5
+if (isWxBrowser()) {
+ name = 'WechatOfficialAccount';
+ provider = 'wechat';
+ platform = 'officialAccount';
+} else {
+ name = 'H5';
+ platform = 'h5';
+}
+// #endif
+
+// #ifdef APP-PLUS
+name = 'App';
+platform = 'openPlatform';
+// 检查微信客户端是否安装,否则AppleStore会因此拒绝上架
+if (os === 'ios') {
+ isWechatInstalled = plus.ios.import('WXApi').isWXAppInstalled();
+}
+// #endif
+
+// #ifdef MP-WEIXIN
+name = 'WechatMiniProgram';
+platform = 'miniProgram';
+provider = 'wechat';
+// #endif
+
+if (isEmpty(name)) {
+ uni.showToast({
+ title: '暂不支持该平台',
+ icon: 'none',
+ });
+}
+
+// 加载当前平台前置行为
+const load = () => {
+ if (provider === 'wechat') {
+ wechat.load();
+ }
+};
+
+// 使用厂商独占sdk name = 'wechat' | 'alipay' | 'apple'
+const useProvider = (_provider = '') => {
+ if (_provider === '') _provider = provider;
+ if (_provider === 'wechat') return wechat;
+ if (_provider === 'apple') return apple;
+};
+
+// 支付服务转发
+const pay = (payment, orderType, orderSN, flag) => {
+ return new Pay(payment, orderType, orderSN, flag);
+};
+
+/**
+ * 检查更新 (只检查小程序和App)
+ * @param {Boolean} silence - 静默检查
+ */
+const checkUpdate = (silence = false) => {
+ let canUpdate;
+ // #ifdef MP-WEIXIN
+ useProvider().checkUpdate(silence);
+ // #endif
+
+ // #ifdef APP-PLUS
+ // TODO: 热更新
+ // #endif
+};
+
+/**
+ * 检查网络
+ * @param {Boolean} silence - 静默检查
+ */
+async function checkNetwork() {
+ const networkStatus = await uni.getNetworkType();
+ if (networkStatus.networkType == 'none') {
+ return Promise.resolve(false);
+ }
+ return Promise.resolve(true);
+}
+
+// 获取小程序胶囊信息
+const getCapsule = () => {
+ // #ifdef MP
+ let capsule = uni.getMenuButtonBoundingClientRect();
+ if (!capsule) {
+ capsule = {
+ bottom: 56,
+ height: 32,
+ left: 278,
+ right: 365,
+ top: 24,
+ width: 87,
+ };
+ }
+ return capsule;
+ // #endif
+
+ // #ifndef MP
+ return {
+ bottom: 56,
+ height: 32,
+ left: 278,
+ right: 365,
+ top: 24,
+ width: 87,
+ };
+ // #endif
+};
+
+const capsule = getCapsule();
+
+// 标题栏高度
+const getNavBar = () => {
+ return device.statusBarHeight + 44;
+};
+const navbar = getNavBar();
+
+function getLandingPage() {
+ let page = '';
+ // #ifdef H5
+ page = location.href.split('?')[0];
+ // #endif
+ return page;
+}
+
+// 设置ios+公众号网页落地页 解决微信sdk签名问题
+const landingPage = getLandingPage();
+
+const _platform = {
+ name,
+ device,
+ os,
+ provider,
+ platform,
+ useProvider,
+ checkUpdate,
+ checkNetwork,
+ pay,
+ share,
+ load,
+ capsule,
+ navbar,
+ landingPage,
+ isWechatInstalled,
+};
+
+export default _platform;
diff --git a/sheep/platform/pay.js b/sheep/platform/pay.js
new file mode 100644
index 0000000..9f6206b
--- /dev/null
+++ b/sheep/platform/pay.js
@@ -0,0 +1,372 @@
+import sheep from '@/sheep';
+// #ifdef H5
+import $wxsdk from '@/sheep/libs/sdk-h5-weixin';
+// #endif
+import { getRootUrl } from '@/sheep/helper';
+import PayOrderApi from '@/sheep/api/pay/order';
+
+/**
+ * 支付
+ *
+ * @param {String} payment = ['wechat','alipay','wallet','mock'] - 支付方式
+ * @param {String} orderType = ['goods','recharge','groupon'] - 订单类型
+ * @param {String} id - 订单号
+ */
+
+export default class SheepPay {
+ constructor(payment, orderType, id, flag) {
+ this.payment = payment;
+ this.id = id;
+ this.orderType = orderType;
+ this.flag = flag;
+ this.payAction();
+ }
+
+ payAction() {
+ const payAction = {
+ WechatOfficialAccount: {
+ wechat: () => {
+ this.wechatOfficialAccountPay();
+ },
+ alipay: () => {
+ this.redirectPay(); // 现在公众号可以直接跳转支付宝页面
+ },
+ wallet: () => {
+ this.walletPay();
+ },
+ mock: () => {
+ this.mockPay();
+ }
+ },
+ WechatMiniProgram: {
+ wechat: () => {
+ this.wechatMiniProgramPay();
+ },
+ alipay: () => {
+ this.copyPayLink();
+ },
+ wallet: () => {
+ this.walletPay();
+ },
+ mock: () => {
+ this.mockPay();
+ }
+ },
+ App: {
+ wechat: () => {
+ this.wechatAppPay();
+ },
+ alipay: () => {
+ this.alipay();
+ },
+ wallet: () => {
+ this.walletPay();
+ },
+ mock: () => {
+ this.mockPay();
+ }
+ },
+ H5: {
+ wechat: () => {
+ this.wechatWapPay();
+ },
+ alipay: () => {
+ this.redirectPay();
+ },
+ wallet: () => {
+ this.walletPay();
+ },
+ mock: () => {
+ this.mockPay();
+ }
+ },
+ };
+ return payAction[sheep.$platform.name][this.payment]();
+ }
+
+ // 预支付
+ prepay(channel) {
+ return new Promise(async (resolve, reject) => {
+ let data = {
+ id: this.id,
+ channelCode: channel,
+ channelExtras: {}
+ };
+ // 特殊逻辑:微信公众号、小程序支付时,必须传入 openid
+ if (['wx_pub', 'wx_lite'].includes(channel)) {
+ const openid = await sheep.$platform.useProvider('wechat').getOpenid();
+ // 如果获取不到 openid,微信无法发起支付,此时需要引导
+ if (!openid) {
+ this.bindWeixin();
+ return;
+ }
+ data.channelExtras.openid = openid;
+ }
+ // 发起预支付 API 调用
+ PayOrderApi.submitOrder(data).then((res) => {
+ // 成功时
+ res.code === 0 && resolve(res);
+ // 失败时
+ if (res.code !== 0 && res.msg.indexOf('无效的openid') >= 0) {
+ // 特殊逻辑:微信公众号、小程序支付时,必须传入 openid 不正确的情况
+ if (res.msg.indexOf('无效的openid') >= 0 // 获取的 openid 不正确时,或者随便输入了个 openid
+ || res.msg.indexOf('下单账号与支付账号不一致') >= 0) { // https://developers.weixin.qq.com/community/develop/doc/00008c53c347804beec82aed051c00
+ this.bindWeixin();
+ }
+ }
+ });
+ });
+ }
+ // #ifdef H5
+ // 微信公众号 JSSDK 支付
+ async wechatOfficialAccountPay() {
+ let { code, data } = await this.prepay('wx_pub');
+ if (code !== 0) {
+ return;
+ }
+ const payConfig = JSON.parse(data.displayContent);
+ $wxsdk.wxpay(payConfig, {
+ success: () => {
+ this.payResult('success');
+ },
+ cancel: () => {
+ sheep.$helper.toast('支付已手动取消');
+ },
+ fail: (error) => {
+ if (error.errMsg.indexOf('chooseWXPay:没有此SDK或暂不支持此SDK模拟') >= 0) {
+ sheep.$helper.toast('发起微信支付失败,原因:可能是微信开发者工具不支持,建议使用微信打开网页后支付');
+ return
+ }
+ this.payResult('fail');
+ },
+ });
+ }
+
+ // 浏览器微信 H5 支付 TODO 芋艿:待接入
+ async wechatWapPay() {
+ const { error, data } = await this.prepay();
+ if (error === 0) {
+ const redirect_url = `${getRootUrl()}pages/pay/result?id=${this.id}&payment=${this.payment}&orderType=${this.orderType}`;
+ location.href = `${data.pay_data.h5_url}&redirect_url=${encodeURIComponent(redirect_url)}`;
+ }
+ }
+
+ // 支付链接 TODO 芋艿:待接入
+ async redirectPay() {
+ let { error, data } = await this.prepay();
+ if (error === 0) {
+ const redirect_url = `${getRootUrl()}pages/pay/result?id=${this.id}&payment=${this.payment}&orderType=${this.orderType}`;
+ location.href = data.pay_data + encodeURIComponent(redirect_url);
+ }
+ }
+
+ // #endif
+
+ // 微信小程序支付
+ async wechatMiniProgramPay() {
+ // let that = this;
+ let { code, data } = await this.prepay('wx_lite');
+ if (code !== 0) {
+ return;
+ }
+ // 调用微信小程序支付
+ const payConfig = JSON.parse(data.displayContent);
+ uni.requestPayment({
+ provider: 'wxpay',
+ timeStamp: payConfig.timeStamp,
+ nonceStr: payConfig.nonceStr,
+ package: payConfig.packageValue,
+ signType: payConfig.signType,
+ paySign: payConfig.paySign,
+ success: (res) => {
+ this.payResult('success');
+ },
+ fail: (err) => {
+ if (err.errMsg === 'requestPayment:fail cancel') {
+ sheep.$helper.toast('支付已手动取消');
+ } else {
+ this.payResult('fail');
+ }
+ },
+ });
+ }
+
+ // 余额支付
+ async walletPay() {
+ const { code } = await this.prepay('wallet');
+ code === 0 && this.payResult('success');
+ }
+
+ // 模拟支付
+ async mockPay() {
+ const { code } = await this.prepay('mock');
+ code === 0 && this.payResult('success');
+ }
+
+ // 支付宝复制链接支付 TODO 芋艿:待接入
+ async copyPayLink() {
+ let that = this;
+ let { error, data } = await this.prepay();
+ if (error === 0) {
+ // 引入showModal 点击确认 复制链接;
+ uni.showModal({
+ title: '支付宝支付',
+ content: '复制链接到外部浏览器',
+ confirmText: '复制链接',
+ success: (res) => {
+ if (res.confirm) {
+ sheep.$helper.copyText(data.pay_data);
+ }
+ },
+ });
+ }
+ }
+
+ // 支付宝支付 TODO 芋艿:待接入
+ async alipay() {
+ let that = this;
+ const { error, data } = await this.prepay();
+ if (error === 0) {
+ uni.requestPayment({
+ provider: 'alipay',
+ orderInfo: data.pay_data, //支付宝订单数据
+ success: (res) => {
+ that.payResult('success');
+ },
+ fail: (err) => {
+ if (err.errMsg === 'requestPayment:fail [paymentAlipay:62001]user cancel') {
+ sheep.$helper.toast('支付已手动取消');
+ } else {
+ that.payResult('fail');
+ }
+ },
+ });
+ }
+ }
+
+ // 微信支付 TODO 芋艿:待接入
+ async wechatAppPay() {
+ let that = this;
+ let { error, data } = await this.prepay();
+ if (error === 0) {
+ uni.requestPayment({
+ provider: 'wxpay',
+ orderInfo: data.pay_data, //微信订单数据(官方说是string。实测为object)
+ success: (res) => {
+ that.payResult('success');
+ },
+ fail: (err) => {
+ err.errMsg !== 'requestPayment:fail cancel' && that.payResult('fail');
+ },
+ });
+ }
+ }
+
+ // 支付结果跳转,success:成功,fail:失败
+ payResult(resultType) {
+ if(this.flag == 'worker'){
+ sheep.$router.redirect('/pages/pay/worker/result', {
+ id: this.id,
+ orderType: this.orderType,
+ payState: resultType
+ });
+ }else if(this.flag == 'reward'){
+ sheep.$helper.toast('打赏成功');
+ uni.navigateBack();
+ }else if(this.flag == 'point'){
+ sheep.$router.redirect('/pages/point/result', {
+ id: this.id,
+ orderType: this.orderType,
+ payState: resultType
+ });
+ }else if(this.flag == 'vip'){
+ sheep.$helper.toast('开通成功');
+ sheep.$router.redirect('/pages/user/vip');
+ }else {
+ sheep.$router.redirect('/pages/pay/result', {
+ id: this.id,
+ orderType: this.orderType,
+ payState: resultType
+ });
+ }
+ }
+
+ // 引导绑定微信
+ bindWeixin() {
+ uni.showModal({
+ title: '微信支付',
+ content: '请先绑定微信再使用微信支付',
+ success: function (res) {
+ if (res.confirm) {
+ sheep.$platform.useProvider('wechat').bind();
+ }
+ },
+ });
+ }
+
+}
+
+export function getPayMethods(channels) {
+ const payMethods = [
+ {
+ icon: '/static/img/shop/pay/wechat.png',
+ title: '微信支付',
+ value: 'wechat',
+ disabled: true,
+ },
+ {
+ icon: '/static/img/shop/pay/alipay.png',
+ title: '支付宝支付',
+ value: 'alipay',
+ disabled: true,
+ },
+ {
+ icon: '/static/img/shop/pay/wallet.png',
+ title: '余额支付',
+ value: 'wallet',
+ disabled: true,
+ },
+ {
+ icon: '/static/img/shop/pay/apple.png',
+ title: 'Apple Pay',
+ value: 'apple',
+ disabled: true,
+ },
+ {
+ icon: '/static/img/shop/pay/wallet.png',
+ title: '模拟支付',
+ value: 'mock',
+ disabled: true,
+ }
+ ];
+ const platform = sheep.$platform.name
+
+ // 1. 处理【微信支付】
+ const wechatMethod = payMethods[0];
+ if ((platform === 'WechatOfficialAccount' && channels.includes('wx_pub'))
+ || (platform === 'WechatMiniProgram' && channels.includes('wx_lite'))
+ || (platform === 'H5' && channels.includes('wx_pub'))
+ || (platform === 'App' && channels.includes('wx_app'))) {
+ wechatMethod.disabled = false;
+ }
+
+ // 2. 处理【支付宝支付】
+ const alipayMethod = payMethods[1];
+ if ((platform === 'WechatOfficialAccount' && channels.includes('alipay_wap'))
+ || platform === 'WechatMiniProgram' && channels.includes('alipay_wap')
+ || platform === 'App' && channels.includes('alipay_app')) {
+ alipayMethod.disabled = false;
+ }
+ // 3. 处理【余额支付】
+ const walletMethod = payMethods[2];
+ if (channels.includes('wallet')) {
+ walletMethod.disabled = false;
+ }
+ // 4. 处理【苹果支付】TODO 芋艿:未来接入
+ // 5. 处理【模拟支付】
+ const mockMethod = payMethods[4];
+ if (channels.includes('mock')) {
+ mockMethod.disabled = false;
+ }
+ return payMethods;
+}
\ No newline at end of file
diff --git a/sheep/platform/provider/apple/app.js b/sheep/platform/provider/apple/app.js
new file mode 100644
index 0000000..c1c9149
--- /dev/null
+++ b/sheep/platform/provider/apple/app.js
@@ -0,0 +1,36 @@
+// import third from '@/sheep/api/third';
+// TODO 芋艿:等后面搞 App 再弄
+
+const login = () => {
+ return new Promise(async (resolve, reject) => {
+ const loginRes = await uni.login({
+ provider: 'apple',
+ success: () => {
+ uni.getUserInfo({
+ provider: 'apple',
+ success: async (res) => {
+ if (res.errMsg === 'getUserInfo:ok') {
+ const payload = res.userInfo;
+ const { error } = await third.apple.login({
+ payload,
+ shareInfo: uni.getStorageSync('shareLog') || {},
+ });
+ if (error === 0) {
+ resolve(true);
+ } else {
+ resolve(false);
+ }
+ }
+ },
+ });
+ },
+ fail: (err) => {
+ resolve(false);
+ },
+ });
+ });
+};
+
+export default {
+ login,
+};
diff --git a/sheep/platform/provider/apple/index.js b/sheep/platform/provider/apple/index.js
new file mode 100644
index 0000000..388c093
--- /dev/null
+++ b/sheep/platform/provider/apple/index.js
@@ -0,0 +1,9 @@
+// #ifdef APP-PLUS
+import service from './app';
+// #endif
+
+let apple = {};
+if (typeof service !== 'undefined') {
+ apple = service;
+}
+export default apple;
diff --git a/sheep/platform/provider/wechat/index.js b/sheep/platform/provider/wechat/index.js
new file mode 100644
index 0000000..3bb2c7f
--- /dev/null
+++ b/sheep/platform/provider/wechat/index.js
@@ -0,0 +1,15 @@
+// #ifdef H5
+import service from './officialAccount';
+// #endif
+
+// #ifdef MP-WEIXIN
+import service from './miniProgram';
+// #endif
+
+// #ifdef APP-PLUS
+import service from './openPlatform';
+// #endif
+
+const wechat = service;
+
+export default wechat;
diff --git a/sheep/platform/provider/wechat/miniProgram.js b/sheep/platform/provider/wechat/miniProgram.js
new file mode 100644
index 0000000..5e95eda
--- /dev/null
+++ b/sheep/platform/provider/wechat/miniProgram.js
@@ -0,0 +1,213 @@
+import AuthUtil from '@/sheep/api/member/auth';
+import SocialApi from '@/sheep/api/member/social';
+import UserApi from '@/sheep/api/member/user';
+
+const socialType = 34; // 社交类型 - 微信小程序
+
+let subscribeEventList = [];
+
+// 加载微信小程序
+function load() {
+ checkUpdate();
+ getSubscribeTemplate();
+}
+
+// 微信小程序静默授权登陆
+const login = async () => {
+ return new Promise(async (resolve, reject) => {
+ // 1. 获得微信 code
+ const codeResult = await uni.login();
+ if (codeResult.errMsg !== 'login:ok') {
+ return resolve(false);
+ }
+
+ // 2. 社交登录
+ const loginResult = await AuthUtil.socialLogin(socialType, codeResult.code, 'default');
+ if (loginResult.code === 0) {
+ setOpenid(loginResult.data.openid);
+ return resolve(true);
+ } else {
+ return resolve(false);
+ }
+ });
+};
+
+// 微信小程序手机号授权登陆
+const mobileLogin = async (e) => {
+ return new Promise(async (resolve, reject) => {
+ if (e.errMsg !== 'getPhoneNumber:ok') {
+ return resolve(false);
+ }
+
+ // 1. 获得微信 code
+ const codeResult = await uni.login();
+ if (codeResult.errMsg !== 'login:ok') {
+ return resolve(false);
+ }
+
+ // 2. 一键登录
+ const loginResult = await AuthUtil.weixinMiniAppLogin(e.code, codeResult.code, 'default');
+ if (loginResult.code === 0) {
+ setOpenid(loginResult.data.openid);
+ return resolve(true);
+ } else {
+ return resolve(false);
+ }
+ });
+};
+
+// 微信小程序绑定
+const bind = () => {
+ return new Promise(async (resolve, reject) => {
+ // 1. 获得微信 code
+ const codeResult = await uni.login();
+ if (codeResult.errMsg !== 'login:ok') {
+ return resolve(false);
+ }
+
+ // 2. 绑定账号
+ const bindResult = await SocialApi.socialBind(socialType, codeResult.code, 'default');
+ if (bindResult.code === 0) {
+ setOpenid(bindResult.data);
+ return resolve(true);
+ } else {
+ return resolve(false);
+ }
+ });
+};
+
+// 微信小程序解除绑定
+const unbind = async (openid) => {
+ const { code } = await SocialApi.socialUnbind(socialType, openid);
+ return code === 0;
+};
+
+// 绑定用户手机号
+const bindUserPhoneNumber = (e) => {
+ return new Promise(async (resolve, reject) => {
+ const { code } = await UserApi.updateUserMobileByWeixin(e.code);
+ if (code === 0) {
+ resolve(true);
+ }
+ resolve(false);
+ });
+};
+
+// 设置 openid 到本地存储,目前只有 pay 支付时会使用
+function setOpenid(openid) {
+ uni.setStorageSync('openid', openid);
+}
+
+// 获得 openid
+async function getOpenid(force = false) {
+ let openid = uni.getStorageSync('openid');
+ if (!openid && force) {
+ const info = await getInfo();
+ if (info && info.openid) {
+ openid = info.openid;
+ setOpenid(openid);
+ }
+ }
+ return openid;
+}
+
+// 获得社交信息
+async function getInfo() {
+ const { code, data } = await SocialApi.getSocialUser(socialType);
+ if (code !== 0) {
+ return undefined;
+ }
+ return data;
+}
+
+// ========== 非登录相关的逻辑 ==========
+
+// 小程序更新
+const checkUpdate = async (silence = true) => {
+ if (uni.canIUse('getUpdateManager')) {
+ const updateManager = uni.getUpdateManager();
+ updateManager.onCheckForUpdate(function(res) {
+ // 请求完新版本信息的回调
+ if (res.hasUpdate) {
+ updateManager.onUpdateReady(function() {
+ uni.showModal({
+ title: '更新提示',
+ content: '新版本已经准备好,是否重启应用?',
+ success: function(res) {
+ if (res.confirm) {
+ // 新的版本已经下载好,调用 applyUpdate 应用新版本并重启
+ updateManager.applyUpdate();
+ }
+ },
+ });
+ });
+ updateManager.onUpdateFailed(function() {
+ // 新的版本下载失败
+ // uni.showModal({
+ // title: '已经有新版本了哟~',
+ // content: '新版本已经上线啦,请您删除当前小程序,重新搜索打开~',
+ // });
+ });
+ } else {
+ if (!silence) {
+ uni.showModal({
+ title: '当前为最新版本',
+ showCancel: false,
+ });
+ }
+ }
+ });
+ }
+};
+
+// 获取订阅消息模板
+async function getSubscribeTemplate() {
+ const { code, data } = await SocialApi.getSubscribeTemplateList();
+ if (code === 0) {
+ subscribeEventList = data;
+ }
+}
+
+// 订阅消息
+function subscribeMessage(event, callback= undefined) {
+ let tmplIds = [];
+ if (typeof event === 'string') {
+ const temp = subscribeEventList.find(item => item.title.includes(event));
+ if (temp) {
+ tmplIds.push(temp.id);
+ }
+ }
+ if (typeof event === 'object') {
+ event.forEach((e) => {
+ const temp = subscribeEventList.find(item => item.title.includes(e));
+ if (temp) {
+ tmplIds.push(temp.id);
+ }
+ });
+ }
+ if (tmplIds.length === 0) return;
+
+ uni.requestSubscribeMessage({
+ tmplIds,
+ success: ()=>{
+ // 不管是拒绝还是同意都触发
+ callback && callback()
+ },
+ fail: (err) => {
+ console.log(err);
+ },
+ });
+}
+
+export default {
+ load,
+ login,
+ bind,
+ unbind,
+ bindUserPhoneNumber,
+ mobileLogin,
+ getInfo,
+ getOpenid,
+ subscribeMessage,
+ checkUpdate,
+};
diff --git a/sheep/platform/provider/wechat/officialAccount.js b/sheep/platform/provider/wechat/officialAccount.js
new file mode 100644
index 0000000..ed7beb3
--- /dev/null
+++ b/sheep/platform/provider/wechat/officialAccount.js
@@ -0,0 +1,106 @@
+import $wxsdk from '@/sheep/libs/sdk-h5-weixin';
+import { getRootUrl } from '@/sheep/helper';
+import AuthUtil from '@/sheep/api/member/auth';
+import SocialApi from '@/sheep/api/member/social';
+
+const socialType = 31; // 社交类型 - 微信公众号
+
+// 加载微信公众号JSSDK
+async function load() {
+ $wxsdk.init();
+}
+
+// 微信公众号登陆
+async function login(code = '', state = '') {
+ // 情况一:没有 code 时,去获取 code
+ if (!code) {
+ const loginUrl = await getLoginUrl();
+ if (loginUrl) {
+ uni.setStorageSync('returnUrl', location.href);
+ window.location = loginUrl;
+ }
+ // 情况二:有 code 时,使用 code 去自动登录
+ } else {
+ // 解密 code 发起登陆
+ const loginResult = await AuthUtil.socialLogin(socialType, code, state);
+ if (loginResult.code === 0) {
+ setOpenid(loginResult.data.openid);
+ return loginResult;
+ }
+ }
+ return false;
+}
+
+// 微信公众号绑定
+async function bind(code = '', state = '') {
+ // 情况一:没有 code 时,去获取 code
+ if (code === '') {
+ const loginUrl = await getLoginUrl('bind');
+ if (loginUrl) {
+ uni.setStorageSync('returnUrl', location.href);
+ window.location = loginUrl;
+ }
+ } else {
+ // 情况二:有 code 时,使用 code 去自动绑定
+ const loginResult = await SocialApi.socialBind(socialType, code, state);
+ if (loginResult.code === 0) {
+ setOpenid(loginResult.data);
+ return loginResult;
+ }
+ }
+ return false;
+}
+
+// 微信公众号解除绑定
+const unbind = async (openid) => {
+ const { code } = await SocialApi.socialUnbind(socialType, openid);
+ return code === 0;
+};
+
+// 获取公众号登陆地址
+async function getLoginUrl(event = 'login') {
+ const page = getRootUrl() + 'pages/index/login'
+ + '?event=' + event; // event 目的,区分是 login 还是 bind
+ const { code, data } = await AuthUtil.socialAuthRedirect(socialType, page);
+ if (code !== 0) {
+ return undefined;
+ }
+ return data;
+}
+
+// 设置 openid 到本地存储,目前只有 pay 支付时会使用
+function setOpenid(openid) {
+ uni.setStorageSync('openid', openid);
+}
+
+// 获得 openid
+async function getOpenid(force = false) {
+ let openid = uni.getStorageSync('openid');
+ if (!openid && force) {
+ const info = await getInfo();
+ if (info && info.openid) {
+ openid = info.openid;
+ setOpenid(openid);
+ }
+ }
+ return openid;
+}
+
+// 获得社交信息
+async function getInfo() {
+ const { code, data } = await SocialApi.getSocialUser(socialType);
+ if (code !== 0) {
+ return undefined;
+ }
+ return data;
+}
+
+export default {
+ load,
+ login,
+ bind,
+ unbind,
+ getInfo,
+ getOpenid,
+ jsWxSdk: $wxsdk,
+};
diff --git a/sheep/platform/provider/wechat/openPlatform.js b/sheep/platform/provider/wechat/openPlatform.js
new file mode 100644
index 0000000..a80f0d7
--- /dev/null
+++ b/sheep/platform/provider/wechat/openPlatform.js
@@ -0,0 +1,64 @@
+// 登录
+import third from '@/sheep/api/migration/third';
+import SocialApi from '@/sheep/api/member/social';
+import $share from '@/sheep/platform/share';
+
+// TODO 芋艿:等后面搞 App 再弄
+const socialType = 32; // 社交类型 - 微信开放平台
+
+const load = async () => {};
+
+// 微信开放平台移动应用授权登陆
+const login = () => {
+ return new Promise(async (resolve, reject) => {
+ const loginRes = await uni.login({
+ provider: 'weixin',
+ onlyAuthorize: true,
+ });
+ debugger
+ if (loginRes.errMsg == 'login:ok') {
+ // TODO third.wechat.login 函数未实现
+ const res = await third.wechat.login({
+ platform: 'openPlatform',
+ shareInfo: uni.getStorageSync('shareLog') || {},
+ payload: encodeURIComponent(
+ JSON.stringify({
+ code: loginRes.code,
+ }),
+ ),
+ });
+
+ if (res.error === 0) {
+ $share.bindBrokerageUser()
+ resolve(true);
+ }
+ } else {
+ uni.showToast({
+ icon: 'none',
+ title: loginRes.errMsg,
+ });
+ }
+ resolve(false);
+ });
+};
+
+// 微信 App 解除绑定
+const unbind = async (openid) => {
+ const { code } = await SocialApi.socialUnbind(socialType, openid);
+ return code === 0;
+};
+
+// 获得社交信息
+async function getInfo() {
+ const { code, data } = await SocialApi.getSocialUser(socialType);
+ if (code !== 0) {
+ return undefined;
+ }
+ return data;
+}
+
+export default {
+ load,
+ login,
+ getInfo
+};
diff --git a/sheep/platform/share.js b/sheep/platform/share.js
new file mode 100644
index 0000000..50f70bc
--- /dev/null
+++ b/sheep/platform/share.js
@@ -0,0 +1,207 @@
+import $store from '@/sheep/store';
+import $platform from '@/sheep/platform';
+import $router from '@/sheep/router';
+import $url from '@/sheep/url';
+import BrokerageApi from '@/sheep/api/trade/brokerage';
+// #ifdef H5
+import $wxsdk from '@/sheep/libs/sdk-h5-weixin';
+// #endif
+
+// 设置分享的平台渠道: 1=H5,2=微信公众号网页,3=微信小程序,4=App,...按需扩展
+const platformMap = ['H5', 'WechatOfficialAccount', 'WechatMiniProgram', 'App'];
+
+// 设置分享方式: 1=直接转发,2=海报,3=复制链接,...按需扩展
+const fromMap = ['forward', 'poster', 'link'];
+
+// TODO 芋艿:分享的接入
+// 设置分享信息参数
+const getShareInfo = (
+ scene = {
+ title: '', // 自定义分享标题
+ desc: '', // 自定义描述
+ image: '', // 自定义分享图片
+ params: {}, // 自定义分享参数
+ },
+ poster = {
+ // 自定义海报数据
+ type: 'user',
+ },
+) => {
+ const shareInfo = {
+ title: '', // 分享标题
+ desc: '', // 描述
+ image: '', // 分享图片
+ path: '', // 分享页面+参数
+ link: '', // 分享Url+参数
+ query: '', // 分享参数
+ poster, // 海报所需数据
+ };
+
+ const app = $store('app');
+ const shareConfig = app.platform.share;
+
+ // 自动拼接分享用户参数
+ const query = buildSpmQuery(scene.params);
+ shareInfo.query = query;
+
+ // 配置分享链接地址
+ shareInfo.link = buildSpmLink(query, shareConfig.linkAddress);
+ // 配置页面地址带参数
+ shareInfo.path = buildSpmPath(query);
+
+ // 配置转发参数
+ if (shareConfig.methods.includes('forward')) {
+ // TODO puhui999: forward 这块有点问题
+ if (shareConfig.forwardInfo.title === '' || shareConfig.forwardInfo.image === '') {
+ console.log('请在平台设置中配置转发信息');
+ }
+ // 设置自定义分享信息
+ shareInfo.title = scene.title || shareConfig.forwardInfo.title;
+ shareInfo.image = $url.cdn(scene.image || shareConfig.forwardInfo.image);
+ shareInfo.desc = scene.desc || shareConfig.forwardInfo.subtitle;
+ shareInfo.path = buildSpmPath(scene.path, query);
+ }
+
+ return shareInfo;
+};
+
+/**
+ * 构造 spm 分享参数
+ *
+ * @param params json 格式,其中包含:1)shareId 分享用户的编号;2)page 页面类型;3)query 页面 ID(参数);4)platform 平台类型;5)from 分享来源类型。
+ * @return 分享串 `spm=${shareId}.${page}.${query}.${platform}.${from}`
+ */
+const buildSpmQuery = (params) => {
+ const user = $store('user');
+ let shareId = '0'; // 设置分享者用户ID
+ if (typeof params.shareId === 'undefined') {
+ if (user.isLogin) {
+ shareId = user.userInfo.id;
+ }
+ }
+ let page = '1'; // 页面类型: 1=首页(默认),2=商品,3=拼团商品,4=秒杀商品,5=邀请参团,6=分销邀请...按需扩展
+ if (typeof params.page !== 'undefined') {
+ page = params.page;
+ }
+ let query = '0'; // 设置页面ID: 如商品ID、拼团ID等
+ if (typeof params.query !== 'undefined') {
+ query = params.query;
+ }
+ let platform = platformMap.indexOf($platform.name) + 1;
+ let from = '1';
+ if (typeof params.from !== 'undefined') {
+ from = platformMap.indexOf(params.from) + 1;
+ }
+ // spmParams = ... 可按需扩展
+ return `spm=${shareId}.${page}.${query}.${platform}.${from}`;
+};
+
+// 构造页面分享参数: 所有的分享都先到首页进行 spm 参数解析
+const buildSpmPath = (query) => {
+ // 默认是主页,页面 page,例如 pages/index/index,根路径前不要填加 /,
+ // 不能携带参数(参数请放在scene字段里),如果不填写这个字段,默认跳主页面。scancode_time为系统保留参数,不允许配置
+ return `pages/tabbar/index`;
+};
+
+// 构造分享链接
+const buildSpmLink = (query, linkAddress = '') => {
+ return `${linkAddress}?${query}`;
+};
+
+// 解析Spm
+const decryptSpm = (spm) => {
+ const user = $store('user');
+ let shareParamsArray = spm.split('.');
+ let shareParams = {
+ spm,
+ shareId: 0,
+ page: '',
+ query: {},
+ platform: '',
+ from: '',
+ };
+ let query;
+ shareParams.shareId = shareParamsArray[0];
+ switch (shareParamsArray[1]) {
+ case '1':
+ // 默认首页不跳转
+ shareParams.page = '/pages/tabbar/index';
+ break;
+ case '2':
+ // 普通商品
+ shareParams.page = '/pages/goods/index';
+ shareParams.query = {
+ id: shareParamsArray[2],
+ };
+ break;
+ case '3':
+ // 拼团商品
+ shareParams.page = '/pages/goods/groupon';
+ query = shareParamsArray[2].split(',');
+ shareParams.query = {
+ id: query[0],
+ activity_id: query[1], // TODO 芋艿:接入分享后,应该统一成 id 参数
+ };
+ break;
+ case '4':
+ // 秒杀商品
+ shareParams.page = '/pages/goods/seckill';
+ query = shareParamsArray[2].split(',');
+ shareParams.query = {
+ id: query[1],
+ };
+ break;
+ case '5':
+ // 参与拼团
+ shareParams.page = '/pages/activity/groupon/detail';
+ shareParams.query = {
+ id: shareParamsArray[2],
+ };
+ break;
+ }
+ shareParams.platform = platformMap[shareParamsArray[3] - 1];
+ shareParams.from = fromMap[shareParamsArray[4] - 1];
+ if (shareParams.shareId !== 0) {
+ // 已登录 绑定推广员
+ if (user.isLogin) {
+ bindBrokerageUser(shareParams.shareId);
+ } else {
+ // 记录分享者编号
+ uni.setStorageSync('shareId', shareParams.shareId);
+ }
+ }
+
+ if (shareParams.page !== '/pages/tabbar/index') {
+ $router.go(shareParams.page, shareParams.query);
+ }
+ return shareParams;
+};
+
+// 绑定推广员
+const bindBrokerageUser = async (val= undefined) => {
+ try {
+ const shareId = val || uni.getStorageSync('shareId');
+ if (!shareId) {
+ return;
+ }
+ await BrokerageApi.bindBrokerageUser({ bindUserId: shareId });
+ uni.removeStorageSync('shareId');
+ } catch {
+ }
+};
+
+// 更新公众号分享sdk
+const updateShareInfo = (shareInfo) => {
+ // #ifdef H5
+ if ($platform.name === 'WechatOfficialAccount') {
+ $wxsdk.updateShareInfo(shareInfo);
+ }
+ // #endif
+};
+
+export default {
+ getShareInfo,
+ updateShareInfo,
+ decryptSpm,
+ bindBrokerageUser,
+};
diff --git a/sheep/request/index.js b/sheep/request/index.js
new file mode 100644
index 0000000..f436f61
--- /dev/null
+++ b/sheep/request/index.js
@@ -0,0 +1,341 @@
+/**
+ * Shopro-request
+ * @description api模块管理,loading配置,请求拦截,错误处理
+ */
+
+import Request from 'luch-request';
+import { apiPath, baseUrl, tenantId } from '@/sheep/config';
+import $store from '@/sheep/store';
+import sheep from '@/sheep';
+import $platform from '@/sheep/platform';
+import { showAuthModal } from '@/sheep/hooks/useModal';
+import AuthUtil from '@/sheep/api/member/auth';
+import { getTerminal } from '@/sheep/util/const';
+
+const options = {
+ // 显示操作成功消息 默认不显示
+ showSuccess: false,
+ // 成功提醒 默认使用后端返回值
+ successMsg: '',
+ // 显示失败消息 默认显示
+ showError: true,
+ // 失败提醒 默认使用后端返回信息
+ errorMsg: '',
+ // 显示请求时loading模态框 默认显示
+ showLoading: true,
+ // loading提醒文字
+ loadingMsg: '加载中',
+ // 需要授权才能请求 默认放开
+ auth: false,
+ // ...
+};
+
+// Loading全局实例
+let LoadingInstance = {
+ target: null,
+ count: 0,
+};
+
+/**
+ * 关闭loading
+ */
+function closeLoading() {
+ if (LoadingInstance.count > 0) LoadingInstance.count--;
+ if (LoadingInstance.count === 0) uni.hideLoading();
+}
+
+/**
+ * @description 请求基础配置 可直接使用访问自定义请求
+ */
+const http = new Request({
+ baseURL: baseUrl + apiPath,
+ timeout: 8000,
+ method: 'GET',
+ header: {
+ Accept: 'text/json',
+ 'Content-Type': 'application/json;charset=UTF-8',
+ platform: $platform.name,
+ },
+ // #ifdef APP-PLUS
+ sslVerify: false,
+ // #endif
+ // #ifdef H5
+ // 跨域请求时是否携带凭证(cookies)仅H5支持(HBuilderX 2.6.15+)
+ withCredentials: false,
+ // #endif
+ custom: options,
+});
+
+/**
+ * @description 请求拦截器
+ */
+http.interceptors.request.use(
+ (config) => {
+ // 自定义处理【auth 授权】:必须登录的接口,则跳出 AuthModal 登录弹窗
+ if (config.custom.auth && !$store('user').isLogin) {
+ showAuthModal();
+ return Promise.reject();
+ }
+
+ // 自定义处理【loading 加载中】:如果需要显示 loading,则显示 loading
+ if (config.custom.showLoading) {
+ LoadingInstance.count++;
+ LoadingInstance.count === 1 &&
+ uni.showLoading({
+ title: config.custom.loadingMsg,
+ mask: true,
+ fail: () => {
+ uni.hideLoading();
+ },
+ });
+ }
+
+ // 增加 token 令牌、terminal 终端、tenant 租户的请求头
+ const token = getAccessToken();
+ if (token) {
+ config.header['Authorization'] = token;
+ }
+ config.header['terminal'] = getTerminal();
+
+ config.header['Accept'] = '*/*';
+ config.header['tenant-id'] = tenantId;
+ return config;
+ },
+ (error) => {
+ return Promise.reject(error);
+ },
+);
+
+/**
+ * @description 响应拦截器
+ */
+http.interceptors.response.use(
+ (response) => {
+ // 约定:如果是 /auth/ 下的 URL 地址,并且返回了 accessToken 说明是登录相关的接口,则自动设置登陆令牌
+ if (response.config.url.indexOf('/member/auth/') >= 0 && response.data?.data?.accessToken) {
+ $store('user').setToken(response.data.data.accessToken, response.data.data.refreshToken);
+ }
+
+ // 自定处理【loading 加载中】:如果需要显示 loading,则关闭 loading
+ response.config.custom.showLoading && closeLoading();
+
+ // 自定义处理【error 错误提示】:如果需要显示错误提示,则显示错误提示
+ if (response.data.code !== 0) {
+ // 特殊:如果 401 错误码,则跳转到登录页 or 刷新令牌
+ if (response.data.code === 401) {
+ return refreshToken(response.config);
+ }
+
+ if (response.data.code === -149) {
+ uni.showModal({
+ title: '积分不足',
+ content: response.data.msg,
+ confirmText: '去充值',
+ success: function (res) {
+ if (res.confirm) {
+ sheep.$router.go('/pages/point/recharge');
+ }
+ },
+ });
+ return;
+ }
+
+ if (response.data.code === 1004001009){
+ showAuthModal('chatAuthorization');
+ return;
+ }
+
+ if (response.data.code === -151){
+ uni.showModal({
+ title: '会员特权',
+ content: response.data.msg,
+ showCancel: false,
+ success: function (res) {
+ if (res.confirm) {
+ sheep.$router.go('/pages/user/vip');
+ }
+ },
+ });
+ return;
+ }
+
+ if (response.data.code === 1004001015){
+ $store('modal').$patch((state) => {
+ state.qrcode = true;
+ });
+ return;
+ }
+
+ // 错误提示
+ if (response.config.custom.showError) {
+ uni.showToast({
+ title: response.data.msg || '服务器开小差啦,请稍后再试~',
+ icon: 'none',
+ mask: true,
+ });
+ }
+ }
+
+ // 自定义处理【showSuccess 成功提示】:如果需要显示成功提示,则显示成功提示
+ if (response.config.custom.showSuccess
+ && response.config.custom.successMsg !== ''
+ && response.data.code === 0) {
+ uni.showToast({
+ title: response.config.custom.successMsg,
+ icon: 'none',
+ });
+ }
+
+ // 返回结果:包括 code + data + msg
+ return Promise.resolve(response.data);
+ },
+ (error) => {
+ const userStore = $store('user');
+ const isLogin = userStore.isLogin;
+ let errorMessage = '网络请求出错';
+ if (error !== undefined) {
+ switch (error.statusCode) {
+ case 400:
+ errorMessage = '请求错误';
+ break;
+ case 401:
+ errorMessage = isLogin ? '您的登陆已过期' : '请先登录';
+ // 正常情况下,后端不会返回 401 错误,所以这里不处理 handleAuthorized
+ break;
+ case 403:
+ errorMessage = '拒绝访问';
+ break;
+ case 404:
+ errorMessage = '请求出错';
+ break;
+ case 408:
+ errorMessage = '请求超时';
+ break;
+ case 429:
+ errorMessage = '请求频繁, 请稍后再访问';
+ break;
+ case 500:
+ errorMessage = '服务器开小差啦,请稍后再试~';
+ break;
+ case 501:
+ errorMessage = '服务未实现';
+ break;
+ case 502:
+ errorMessage = '网络错误';
+ break;
+ case 503:
+ errorMessage = '服务不可用';
+ break;
+ case 504:
+ errorMessage = '网络超时';
+ break;
+ case 505:
+ errorMessage = 'HTTP 版本不受支持';
+ break;
+ }
+ if (error.errMsg.includes('timeout')) errorMessage = '请求超时';
+ // #ifdef H5
+ if (error.errMsg.includes('Network'))
+ errorMessage = window.navigator.onLine ? '服务器异常' : '请检查您的网络连接';
+ // #endif
+ }
+
+ if (error && error.config) {
+ if (error.config.custom.showError === false) {
+ uni.showToast({
+ title: error.data?.msg || errorMessage,
+ icon: 'none',
+ mask: true,
+ });
+ }
+ error.config.custom.showLoading && closeLoading();
+ }
+
+ return false;
+ },
+);
+
+// Axios 无感知刷新令牌,参考 https://www.dashingdog.cn/article/11 与 https://segmentfault.com/a/1190000020210980 实现
+let requestList = [] // 请求队列
+let isRefreshToken = false // 是否正在刷新中
+const refreshToken = async (config) => {
+ // 如果当前已经是 refresh-token 的 URL 地址,并且还是 401 错误,说明是刷新令牌失败了,直接返回 Promise.reject(error)
+ if (config.url.indexOf('/member/auth/refresh-token') >= 0) {
+ return Promise.reject('error')
+ }
+
+ // 如果未认证,并且未进行刷新令牌,说明可能是访问令牌过期了
+ if (!isRefreshToken) {
+ isRefreshToken = true
+ // 1. 如果获取不到刷新令牌,则只能执行登出操作
+ const refreshToken = getRefreshToken()
+ if (!refreshToken) {
+ return handleAuthorized()
+ }
+ // 2. 进行刷新访问令牌
+ try {
+ const refreshTokenResult = await AuthUtil.refreshToken(refreshToken);
+ if (refreshTokenResult.code !== 0) {
+ // 如果刷新不成功,直接抛出 e 触发 2.2 的逻辑
+ // noinspection ExceptionCaughtLocallyJS
+ throw new Error('刷新令牌失败');
+ }
+ // 2.1 刷新成功,则回放队列的请求 + 当前请求
+ config.header.Authorization = 'Bearer ' + getAccessToken()
+ requestList.forEach((cb) => {
+ cb()
+ })
+ requestList = []
+ return request(config)
+ } catch (e) {
+ // 为什么需要 catch 异常呢?刷新失败时,请求因为 Promise.reject 触发异常。
+ // 2.2 刷新失败,只回放队列的请求
+ requestList.forEach((cb) => {
+ cb()
+ })
+ // 提示是否要登出。即不回放当前请求!不然会形成递归
+ return handleAuthorized()
+ } finally {
+ requestList = []
+ isRefreshToken = false
+ }
+ } else {
+ // 添加到队列,等待刷新获取到新的令牌
+ return new Promise((resolve) => {
+ requestList.push(() => {
+ config.header.Authorization = 'Bearer ' + getAccessToken() // 让每个请求携带自定义token 请根据实际情况自行修改
+ resolve(request(config))
+ })
+ })
+ }
+}
+
+/**
+ * 处理 401 未登录的错误
+ */
+const handleAuthorized = () => {
+ const userStore = $store('user');
+ userStore.logout(true);
+ showAuthModal();
+ // 登录超时
+ return Promise.reject({
+ code: 401,
+ msg: userStore.isLogin ? '您的登陆已过期' : '请先登录'
+ })
+}
+
+/** 获得访问令牌 */
+const getAccessToken = () => {
+ return uni.getStorageSync('token');
+}
+
+/** 获得刷新令牌 */
+const getRefreshToken = () => {
+ return uni.getStorageSync('refresh-token');
+}
+
+const request = (config) => {
+ return http.middleware(config);
+};
+
+export default request;
diff --git a/sheep/router/index.js b/sheep/router/index.js
new file mode 100644
index 0000000..0a4ecc3
--- /dev/null
+++ b/sheep/router/index.js
@@ -0,0 +1,185 @@
+import $store from '@/sheep/store';
+import { showAuthModal, showShareModal } from '@/sheep/hooks/useModal';
+import { isNumber, isString, isEmpty, startsWith, isObject, isNil, clone } from 'lodash-es';
+import throttle from '@/sheep/helper/throttle';
+
+const _go = (
+ path,
+ params = {},
+ options = {
+ redirect: false,
+ },
+) => {
+ let page = ''; // 跳转页面
+ let query = ''; // 页面参数
+ let url = ''; // 跳转页面完整路径
+
+ if (isString(path)) {
+ // 判断跳转类型是 path | 还是http
+ if (startsWith(path, 'http')) {
+ // #ifdef H5
+ window.location = path;
+ return;
+ // #endif
+ // #ifndef H5
+ page = `/pages/public/webview`;
+ query = `url=${encodeURIComponent(path)}`;
+ // #endif
+ } else if (startsWith(path, 'action:')) {
+ handleAction(path);
+ return;
+ } else {
+ [page, query] = path.split('?');
+ }
+ if (!isEmpty(params)) {
+ let query2 = paramsToQuery(params);
+ if (isEmpty(query)) {
+ query = query2;
+ } else {
+ query += '&' + query2;
+ }
+ }
+ }
+
+ if (isObject(path)) {
+ page = path.url;
+ if (!isNil(path.params)) {
+ query = paramsToQuery(path.params);
+ }
+ }
+
+ const nextRoute = ROUTES_MAP[page];
+
+ // 未找到指定跳转页面
+ // mark: 跳转404页
+ if (!nextRoute) {
+ console.log(`%c跳转路径参数错误<${page || 'EMPTY'}>`, 'color:red;background:yellow');
+ return;
+ }
+
+ // 页面登录拦截
+ if (nextRoute.meta?.auth && !$store('user').isLogin) {
+ showAuthModal();
+ return;
+ }
+
+ url = page;
+ if (!isEmpty(query)) {
+ url += `?${query}`;
+ }
+
+ // 跳转底部导航
+ if (TABBAR.includes(page)) {
+ uni.switchTab({
+ url,
+ });
+ return;
+ }
+
+ // 使用redirect跳转
+ if (options.redirect) {
+ uni.redirectTo({
+ url,
+ });
+ return;
+ }
+
+ uni.navigateTo({
+ url,
+ });
+};
+
+// 限流 防止重复点击跳转
+function go(...args) {
+ throttle(() => {
+ _go(...args);
+ });
+}
+
+function paramsToQuery(params) {
+ if (isEmpty(params)) {
+ return '';
+ }
+ // return new URLSearchParams(Object.entries(params)).toString();
+ let query = [];
+ for (let key in params) {
+ query.push(key + '=' + params[key]);
+ }
+
+ return query.join('&');
+}
+
+function back() {
+ // #ifdef H5
+ history.back();
+ // #endif
+
+ // #ifndef H5
+ uni.navigateBack();
+ // #endif
+}
+
+function redirect(path, params = {}) {
+ go(path, params, {
+ redirect: true,
+ });
+}
+
+// 检测是否有浏览器历史
+function hasHistory() {
+ // #ifndef H5
+ const pages = getCurrentPages();
+ if (pages.length > 1) {
+ return true;
+ }
+ return false;
+ // #endif
+
+ // #ifdef H5
+ return !!history.state.back;
+ // #endif
+}
+
+function getCurrentRoute(field = '') {
+ let currentPage = getCurrentPage();
+ // #ifdef MP
+ currentPage.$page['route'] = currentPage.route;
+ currentPage.$page['options'] = currentPage.options;
+ // #endif
+ if (field !== '') {
+ return currentPage.$page[field];
+ } else {
+ return currentPage.$page;
+ }
+}
+
+function getCurrentPage() {
+ let pages = getCurrentPages();
+ return pages[pages.length - 1];
+}
+
+function handleAction(path) {
+ const action = path.split(':');
+ switch (action[1]) {
+ case 'showShareModal':
+ showShareModal();
+ break;
+ }
+}
+
+function error(errCode, errMsg = '') {
+ redirect('/pages/public/error', {
+ errCode,
+ errMsg,
+ });
+}
+
+export default {
+ go,
+ back,
+ hasHistory,
+ redirect,
+ getCurrentPage,
+ getCurrentRoute,
+ error,
+};
diff --git a/sheep/router/utils/strip-json-comments.js b/sheep/router/utils/strip-json-comments.js
new file mode 100644
index 0000000..5995992
--- /dev/null
+++ b/sheep/router/utils/strip-json-comments.js
@@ -0,0 +1,79 @@
+const singleComment = Symbol('singleComment');
+const multiComment = Symbol('multiComment');
+
+const stripWithoutWhitespace = () => '';
+const stripWithWhitespace = (string, start, end) => string.slice(start, end).replace(/\S/g, ' ');
+
+const isEscaped = (jsonString, quotePosition) => {
+ let index = quotePosition - 1;
+ let backslashCount = 0;
+
+ while (jsonString[index] === '\\') {
+ index -= 1;
+ backslashCount += 1;
+ }
+
+ return Boolean(backslashCount % 2);
+};
+
+export default function stripJsonComments(jsonString, { whitespace = true } = {}) {
+ if (typeof jsonString !== 'string') {
+ throw new TypeError(
+ `Expected argument \`jsonString\` to be a \`string\`, got \`${typeof jsonString}\``,
+ );
+ }
+
+ const strip = whitespace ? stripWithWhitespace : stripWithoutWhitespace;
+
+ let isInsideString = false;
+ let isInsideComment = false;
+ let offset = 0;
+ let result = '';
+
+ for (let index = 0; index < jsonString.length; index++) {
+ const currentCharacter = jsonString[index];
+ const nextCharacter = jsonString[index + 1];
+
+ if (!isInsideComment && currentCharacter === '"') {
+ const escaped = isEscaped(jsonString, index);
+ if (!escaped) {
+ isInsideString = !isInsideString;
+ }
+ }
+
+ if (isInsideString) {
+ continue;
+ }
+
+ if (!isInsideComment && currentCharacter + nextCharacter === '//') {
+ result += jsonString.slice(offset, index);
+ offset = index;
+ isInsideComment = singleComment;
+ index++;
+ } else if (isInsideComment === singleComment && currentCharacter + nextCharacter === '\r\n') {
+ index++;
+ isInsideComment = false;
+ result += strip(jsonString, offset, index);
+ offset = index;
+ continue;
+ } else if (isInsideComment === singleComment && currentCharacter === '\n') {
+ isInsideComment = false;
+ result += strip(jsonString, offset, index);
+ offset = index;
+ } else if (!isInsideComment && currentCharacter + nextCharacter === '/*') {
+ result += jsonString.slice(offset, index);
+ offset = index;
+ isInsideComment = multiComment;
+ index++;
+ continue;
+ } else if (isInsideComment === multiComment && currentCharacter + nextCharacter === '*/') {
+ index++;
+ isInsideComment = false;
+ result += strip(jsonString, offset, index + 1);
+ offset = index + 1;
+ continue;
+ }
+ }
+
+ return result + (isInsideComment ? strip(jsonString.slice(offset)) : jsonString.slice(offset));
+}
diff --git a/sheep/router/utils/uni-read-pages-v3.js b/sheep/router/utils/uni-read-pages-v3.js
new file mode 100644
index 0000000..303f10a
--- /dev/null
+++ b/sheep/router/utils/uni-read-pages-v3.js
@@ -0,0 +1,103 @@
+'use strict';
+Object.defineProperty(exports, '__esModule', {
+ value: true,
+});
+const fs = require('fs');
+import stripJsonComments from './strip-json-comments';
+import { isArray, isEmpty } from 'lodash';
+
+class TransformPages {
+ constructor({ includes, pagesJsonDir }) {
+ this.includes = includes;
+ this.uniPagesJSON = JSON.parse(stripJsonComments(fs.readFileSync(pagesJsonDir, 'utf-8')));
+ this.routes = this.getPagesRoutes().concat(this.getSubPackagesRoutes());
+ this.tabbar = this.getTabbarRoutes();
+ this.routesMap = this.transformPathToKey(this.routes);
+ }
+ /**
+ * 通过读取pages.json文件 生成直接可用的routes
+ */
+ getPagesRoutes(pages = this.uniPagesJSON.pages, rootPath = null) {
+ let routes = [];
+ for (let i = 0; i < pages.length; i++) {
+ const item = pages[i];
+ let route = {};
+ for (let j = 0; j < this.includes.length; j++) {
+ const key = this.includes[j];
+ let value = item[key];
+ if (key === 'path') {
+ value = rootPath ? `/${rootPath}/${value}` : `/${value}`;
+ }
+ if (key === 'aliasPath' && i == 0 && rootPath == null) {
+ route[key] = route[key] || '/';
+ } else if (value !== undefined) {
+ route[key] = value;
+ }
+ }
+ routes.push(route);
+ }
+ return routes;
+ }
+ /**
+ * 解析小程序分包路径
+ */
+ getSubPackagesRoutes() {
+ if (!(this.uniPagesJSON && this.uniPagesJSON.subPackages)) {
+ return [];
+ }
+ const subPackages = this.uniPagesJSON.subPackages;
+ let routes = [];
+ for (let i = 0; i < subPackages.length; i++) {
+ const subPages = subPackages[i].pages;
+ const root = subPackages[i].root;
+ const subRoutes = this.getPagesRoutes(subPages, root);
+ routes = routes.concat(subRoutes);
+ }
+ return routes;
+ }
+
+ getTabbarRoutes() {
+ if (!(this.uniPagesJSON && this.uniPagesJSON.tabBar && this.uniPagesJSON.tabBar.list)) {
+ return [];
+ }
+ const tabbar = this.uniPagesJSON.tabBar.list;
+ let tabbarMap = [];
+ tabbar.forEach((bar) => {
+ tabbarMap.push('/' + bar.pagePath);
+ });
+ return tabbarMap;
+ }
+
+ transformPathToKey(list) {
+ if (!isArray(list) || isEmpty(list)) {
+ return [];
+ }
+ let map = {};
+ list.forEach((i) => {
+ map[i.path] = i;
+ });
+ return map;
+ }
+}
+
+function uniReadPagesV3Plugin({ pagesJsonDir, includes }) {
+ let defaultIncludes = ['path', 'aliasPath', 'name'];
+ includes = [...defaultIncludes, ...includes];
+ let pages = new TransformPages({
+ pagesJsonDir,
+ includes,
+ });
+ return {
+ name: 'uni-read-pages-v3',
+ config(config) {
+ return {
+ define: {
+ ROUTES: pages.routes,
+ ROUTES_MAP: pages.routesMap,
+ TABBAR: pages.tabbar,
+ },
+ };
+ },
+ };
+}
+exports.default = uniReadPagesV3Plugin;
diff --git a/sheep/scss/_main.scss b/sheep/scss/_main.scss
new file mode 100644
index 0000000..999513a
--- /dev/null
+++ b/sheep/scss/_main.scss
@@ -0,0 +1,354 @@
+body {
+ color: var(--text-a);
+ background-color: var(--ui-BG-1) !important;
+ font-family: system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans',
+ sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
+}
+
+/* ==================
+ 初始化
+ ==================== */
+.ui-link {
+ cursor: pointer;
+}
+navigator {
+ display: inline-flex;
+}
+navigator.navigator-hover {
+ background-color: inherit;
+ transform: translate(1rpx, 1rpx);
+ // opacity: 1;
+}
+
+/* ==================
+ 辅助类
+ ==================== */
+.none {
+ display: none !important;
+}
+.inline {
+ display: inline !important;
+}
+.inline-block {
+ display: inline-block !important;
+}
+.block {
+ display: block !important;
+}
+.touch-none {
+ pointer-events: none;
+}
+.touch-all {
+ pointer-events: all;
+}
+.flex {
+ display: flex !important;
+}
+.inline-flex {
+ display: inline-flex !important;
+}
+.w-100 {
+ width: 100%;
+}
+/* -- 浮动 -- */
+.cf::after,
+.cf::before {
+ content: '';
+ display: table;
+}
+.cf::after {
+ clear: both;
+}
+.fl {
+ float: left;
+}
+.fr {
+ float: right;
+}
+.position-center {
+ @include position-center;
+}
+.position-relative {
+ position: relative;
+}
+/* -- 工具类 -- */
+@function negativify-map($map) {
+ $result: ();
+ @each $key, $value in $map {
+ @if $key != 0 {
+ $result: map-merge($result, ('n' + $key: (-$value)));
+ }
+ }
+ @return $result;
+}
+
+$utilities: () !default;
+$utilities: map-merge(
+ (
+ 'margin': (
+ responsive: true,
+ property: margin,
+ class: m,
+ values:
+ map-merge(
+ $spacers,
+ (
+ auto: auto,
+ )
+ ),
+ ),
+ 'margin-x': (
+ property: margin-right margin-left,
+ class: mx,
+ values:
+ map-merge(
+ $spacers,
+ (
+ auto: auto,
+ )
+ ),
+ ),
+ 'margin-y': (
+ property: margin-top margin-bottom,
+ class: my,
+ values:
+ map-merge(
+ $spacers,
+ (
+ auto: auto,
+ )
+ ),
+ ),
+ 'margin-top': (
+ property: margin-top,
+ class: mt,
+ values:
+ map-merge(
+ $spacers,
+ (
+ auto: auto,
+ )
+ ),
+ ),
+ 'margin-right': (
+ property: margin-right,
+ class: mr,
+ values:
+ map-merge(
+ $spacers,
+ (
+ auto: auto,
+ )
+ ),
+ ),
+ 'margin-bottom': (
+ property: margin-bottom,
+ class: mb,
+ values:
+ map-merge(
+ $spacers,
+ (
+ auto: auto,
+ )
+ ),
+ ),
+ 'margin-left': (
+ property: margin-left,
+ class: ml,
+ values:
+ map-merge(
+ $spacers,
+ (
+ auto: auto,
+ )
+ ),
+ ),
+ 'padding': (
+ responsive: true,
+ property: padding,
+ class: p,
+ values: $spacers,
+ ),
+ 'padding-x': (
+ property: padding-right padding-left,
+ class: px,
+ values: $spacers,
+ ),
+ 'padding-y': (
+ property: padding-top padding-bottom,
+ class: py,
+ values: $spacers,
+ ),
+ 'padding-top': (
+ property: padding-top,
+ class: pt,
+ values: $spacers,
+ ),
+ 'padding-right': (
+ property: padding-right,
+ class: pr,
+ values: $spacers,
+ ),
+ 'padding-bottom': (
+ property: padding-bottom,
+ class: pb,
+ values: $spacers,
+ ),
+ 'padding-left': (
+ property: padding-left,
+ class: pl,
+ values: $spacers,
+ ),
+ 'font-weight': (
+ property: font-weight,
+ class: text,
+ values: (
+ light: $font-weight-light,
+ lighter: $font-weight-lighter,
+ normal: $font-weight-normal,
+ bold: $font-weight-bold,
+ bolder: $font-weight-bolder,
+ ),
+ ),
+ 'text-align': (
+ property: text-align,
+ class: text,
+ values: left right center,
+ ),
+ 'font-color': (
+ property: color,
+ class: text,
+ values:
+ map-merge(
+ $colors,
+ map-merge(
+ $grays,
+ map-merge(
+ $darks,
+ (
+ 'reset': inherit,
+ )
+ )
+ )
+ ),
+ ),
+ 'line-height': (
+ property: line-height,
+ class: lh,
+ values: (
+ 1: 1,
+ sm: $line-height-sm,
+ base: $line-height-base,
+ lg: $line-height-lg,
+ ),
+ ),
+ 'white-space': (
+ property: white-space,
+ class: text,
+ values: (
+ nowrap: nowrap,
+ ),
+ ),
+ 'radius': (
+ property: border-radius,
+ class: radius,
+ values: (
+ null: $radius,
+ sm: $radius-sm,
+ lg: $radius-lg,
+ 0: 0,
+ ),
+ ),
+ 'round': (
+ property: border-radius,
+ class: round,
+ values: (
+ null: $round-pill,
+ circle: 50%,
+ ),
+ ),
+ 'radius-top': (
+ property: border-top-left-radius border-top-right-radius,
+ class: radius-top,
+ values: (
+ null: $radius,
+ ),
+ ),
+ 'radius-right': (
+ property: border-top-right-radius border-bottom-right-radius,
+ class: radius-right,
+ values: (
+ null: $radius,
+ ),
+ ),
+ 'radius-bottom': (
+ property: border-bottom-right-radius border-bottom-left-radius,
+ class: radius-bottom,
+ values: (
+ null: $radius,
+ ),
+ ),
+ 'radius-left': (
+ property: border-bottom-left-radius border-top-left-radius,
+ class: radius-left,
+ values: (
+ null: $radius,
+ ),
+ ),
+ 'radius-lr': (
+ property: border-top-left-radius border-bottom-right-radius,
+ class: radius-lr,
+ values: (
+ null: $radius,
+ ),
+ ),
+ 'radius-lrs': (
+ property: border-top-right-radius border-bottom-left-radius,
+ class: radius-lr,
+ values: (
+ null: 0,
+ ),
+ ),
+ 'radius-rl': (
+ property: border-top-right-radius border-bottom-left-radius,
+ class: radius-rl,
+ values: (
+ null: $radius,
+ ),
+ ),
+ 'radius-rls': (
+ property: border-top-left-radius border-bottom-right-radius,
+ class: radius-rl,
+ values: (
+ null: 0,
+ ),
+ ),
+ ),
+ $utilities
+);
+@each $key, $utility in $utilities {
+ @if type-of($utility) == 'map' {
+ $values: map-get($utility, values);
+ @if type-of($values) == 'string' or type-of(nth($values, 1)) != 'list' {
+ $values: zip($values, $values);
+ }
+ @each $key, $value in $values {
+ $properties: map-get($utility, property);
+ @if type-of($properties) == 'string' {
+ $properties: append((), $properties);
+ }
+ $property-class: if(
+ map-has-key($utility, class),
+ map-get($utility, class),
+ nth($properties, 1)
+ );
+ $property-class: if($property-class == null, '', $property-class);
+ $property-class-modifier: if($key, if($property-class == '', '', '-') + $key, '');
+ .#{$property-class + $property-class-modifier} {
+ @each $property in $properties {
+ #{$property}: $value !important;
+ }
+ }
+ }
+ }
+}
diff --git a/sheep/scss/_mixins.scss b/sheep/scss/_mixins.scss
new file mode 100644
index 0000000..299f7b1
--- /dev/null
+++ b/sheep/scss/_mixins.scss
@@ -0,0 +1,61 @@
+@mixin bg-square {
+ background: {
+ color: #fff;
+ image: linear-gradient(45deg, #eee 25%, transparent 25%, transparent 75%, #eee 75%),
+ linear-gradient(45deg, #eee 25%, transparent 25%, transparent 75%, #eee 75%);
+ size: 40rpx 40rpx;
+ position: 0 0, 20rpx 20rpx;
+ }
+}
+
+@mixin flex($direction: row) {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: $direction;
+}
+@mixin flex-bar {
+ position: relative;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+}
+@mixin flex-center {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+
+@mixin arrow {
+ content: '';
+ height: 0;
+ width: 0;
+ position: absolute;
+}
+@mixin arrow-top {
+ @include arrow;
+ // border-color: transparent transparent $ui-BG;
+ border-style: none solid solid;
+ border-width: 0 20rpx 20rpx;
+}
+
+@mixin arrow-right {
+ @include arrow;
+ // border-color: transparent $ui-BG transparent;
+ border-style: solid solid solid none;
+ border-width: 20rpx 20rpx 20rpx 0;
+}
+@mixin position-center {
+ position: absolute !important;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ margin: auto;
+}
+
+@mixin blur {
+ -webkit-backdrop-filter: blur(20px);
+ backdrop-filter: blur(20px);
+ color: var(--ui-TC);
+}
diff --git a/sheep/scss/_tools.scss b/sheep/scss/_tools.scss
new file mode 100644
index 0000000..e1fb636
--- /dev/null
+++ b/sheep/scss/_tools.scss
@@ -0,0 +1,286 @@
+/* ==================
+ 常用工具
+ ==================== */
+
+.ss-bg-opactity-block {
+ background-color: rgba(#000, 0.2);
+ color: #fff;
+}
+
+/* ==================
+ flex布局
+ ==================== */
+
+.ss-flex {
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+}
+
+.ss-flex-1 {
+ flex: 1;
+}
+
+.ss-flex-col {
+ display: flex;
+ flex-direction: column;
+}
+
+.ss-flex-wrap {
+ flex-wrap: wrap;
+}
+
+.ss-flex-nowrap {
+ flex-wrap: nowrap;
+}
+
+.ss-col-center {
+ align-items: center;
+}
+
+.ss-col-top {
+ align-items: flex-start;
+}
+
+.ss-col-bottom {
+ align-items: flex-end;
+}
+
+.ss-col-stretch {
+ align-items: stretch;
+}
+
+.ss-row-center {
+ justify-content: center;
+}
+
+.ss-row-left {
+ justify-content: flex-start;
+}
+
+.ss-row-right {
+ justify-content: flex-end;
+}
+
+.ss-row-between {
+ justify-content: space-between;
+}
+
+.ss-row-around {
+ justify-content: space-around;
+}
+
+.ss-self-start {
+ align-self: flex-start;
+}
+
+.ss-self-end {
+ align-self: flex-end;
+}
+
+.ss-self-center {
+ align-self: center;
+}
+.ss-h-100 {
+ height: 100%;
+}
+.ss-w-100 {
+ width: 100%;
+}
+
+/* ==================
+
+ margin padding: 内外边距
+
+ ==================== */
+@for $i from 0 through 100 {
+ // 只要双数和能被5除尽的数
+ @if $i % 2==0 or $i % 5==0 {
+ // 得出:u-margin-30或者u-m-30
+ .ss-margin-#{$i},
+ .ss-m-#{$i} {
+ margin: $i + rpx;
+ }
+ .ss-m-x-#{$i} {
+ margin-left: $i + rpx;
+ margin-right: $i + rpx;
+ }
+ .ss-m-y-#{$i} {
+ margin-top: $i + rpx;
+ margin-bottom: $i + rpx;
+ }
+
+ // 得出:u-padding-30或者u-p-30
+ .ss-padding-#{$i},
+ .ss-p-#{$i} {
+ padding: $i + rpx;
+ }
+ .ss-p-x-#{$i} {
+ padding-left: $i + rpx;
+ padding-right: $i + rpx;
+ }
+ .ss-p-y-#{$i} {
+ padding-top: $i + rpx;
+ padding-bottom: $i + rpx;
+ }
+
+ @each $short, $long in l left, t top, r right, b bottom {
+ // 缩写版,结果如: u-m-l-30
+ // 定义外边距
+ .ss-m-#{$short}-#{$i} {
+ margin-#{$long}: $i + rpx;
+ }
+
+ // 定义内边距
+ .ss-p-#{$short}-#{$i} {
+ padding-#{$long}: $i + rpx;
+ }
+
+ // 完整版,结果如:u-margin-left-30
+ // 定义外边距
+ .ss-margin-#{$long}-#{$i} {
+ margin-#{$long}: $i + rpx;
+ }
+
+ // 定义内边距
+ .ss-padding-#{$long}-#{$i} {
+ padding-#{$long}: $i + rpx;
+ }
+ }
+ }
+}
+
+/* ==================
+
+ radius
+
+ ==================== */
+@for $i from 0 through 100 {
+ // 只要双数和能被5除尽的数
+ @if $i % 2==0 or $i % 5==0 {
+ .ss-radius-#{$i},
+ .ss-r-#{$i} {
+ border-radius: $i + rpx;
+ }
+
+ .ss-r-t-#{$i} {
+ border-top-left-radius: $i + rpx;
+ border-top-right-radius: $i + rpx;
+ }
+
+ .ss-r-b-#{$i} {
+ border-bottom-left-radius: $i + rpx;
+ border-bottom-right-radius: $i + rpx;
+ }
+
+ @each $short, $long in tl 'top-left', tr 'top-right', bl 'bottom-right', br 'bottom-right' {
+ // 定义外边距
+ .ss-r-#{$short}-#{$i} {
+ border-#{$long}-radius: $i + rpx;
+ }
+
+ // 定义内边距
+ .ss-radius-#{$long}-#{$i} {
+ border-#{$long}-radius: $i + rpx;
+ }
+ }
+ }
+}
+
+/* ==================
+
+ 溢出省略号
+ @param {Number} 行数
+
+ ==================== */
+@mixin ellipsis($rowCount: 1) {
+ // @if $rowCount <=1 {
+ // overflow: hidden;
+ // text-overflow: ellipsis;
+ // white-space: nowrap;
+ // } @else {
+ // min-width: 0;
+ // overflow: hidden;
+ // text-overflow: ellipsis;
+ // display: -webkit-box;
+ // -webkit-line-clamp: $rowCount;
+ // -webkit-box-orient: vertical;
+ // }
+ min-width: 0;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ display: -webkit-box;
+ -webkit-line-clamp: $rowCount;
+ -webkit-box-orient: vertical;
+}
+
+@for $i from 1 through 6 {
+ .ss-line-#{$i} {
+ @include ellipsis($i);
+ }
+}
+
+/* ==================
+ hover
+ ==================== */
+.ss-hover-class {
+ background-color: $gray-c;
+ opacity: 0.6;
+}
+.ss-hover-btn {
+ transform: translate(1px, 1px);
+}
+
+/* ==================
+ 底部安全区域
+ ==================== */
+
+.ss-safe-bottom {
+ padding-bottom: 0;
+ padding-bottom: calc(constant(safe-area-inset-bottom) / 5 * 3);
+ padding-bottom: calc(env(safe-area-inset-bottom) / 5 * 3);
+}
+
+/* ==================
+
+ 字体大小
+
+ ==================== */
+
+@for $i from 20 through 50 {
+ .ss-font-#{$i} {
+ font-size: $i + rpx;
+ }
+}
+
+/* ==================
+ 按钮
+ ==================== */
+.ss-reset-button {
+ padding: 0;
+ margin: 0;
+ font-size: inherit;
+ background-color: transparent;
+ color: inherit;
+ position: relative;
+ border: 0rpx;
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ align-items: center;
+ justify-content: center;
+ box-sizing: border-box;
+ text-align: center;
+ text-decoration: none;
+ white-space: nowrap;
+ vertical-align: baseline;
+ transform: translate(0, 0);
+}
+.ss-reset-button.button-hover {
+ transform: translate(1px, 1px);
+ background: none;
+}
+
+.ss-reset-button::after {
+ border: none;
+}
diff --git a/sheep/scss/_var.scss b/sheep/scss/_var.scss
new file mode 100644
index 0000000..b9986cc
--- /dev/null
+++ b/sheep/scss/_var.scss
@@ -0,0 +1,162 @@
+@import './mixins';
+
+//颜色 ,渐变背景60%
+$yellow: #ffc300; //ss-黄
+$orange: #ff6000; //ss-橘
+$red: #ff3000; //ss-红
+$pink: #e03997;
+$mauve: #b745cb;
+$purple: #652abf; //rgba(101, 42, 191, 1); // ss-紫
+$blue: #0081ff;
+$cyan: #37c0fe;
+$green: #7ea19e; //ss-绿
+$olive: #8dc63f;
+$grey: #8799a3;
+$brown: #a5673f;
+$black: #484848; //ss-黑
+$golden: #e9b461; //ss-金
+
+$colors: ();
+$colors: map-merge(
+ (
+ 'yellow': $yellow,
+ 'orange': $orange,
+ 'red': $red,
+ 'pink': $pink,
+ 'mauve': $mauve,
+ 'purple': $purple,
+ 'violet': $purple,
+ 'blue': $blue,
+ 'cyan': $cyan,
+ 'green': $green,
+ 'olive': $olive,
+ 'grey': $grey,
+ 'brown': $brown,
+ 'black': $black,
+ 'golden': $golden,
+ ),
+ $colors
+);
+
+//灰度
+$bg-page: #f6f6f6;
+$white: #ffffff;
+$gray-f: #f8f9fa;
+$gray-e: #eeeeee;
+$gray-d: #dddddd;
+$gray-c: #cccccc;
+$gray-b: #bbbbbb;
+$gray-a: #aaaaaa;
+$dark-9: #999999;
+$dark-8: #888888;
+$dark-7: #777777;
+$dark-6: #666666;
+$dark-5: #555555;
+$dark-4: #484848; //ss-黑
+$dark-3: #333333;
+$dark-2: #222222;
+$dark-1: #111111;
+$black: #000000;
+
+$grays: ();
+$grays: map-merge(
+ (
+ 'white': $white,
+ 'gray-f': $gray-f,
+ 'gray-e': $gray-e,
+ 'gray-d': $gray-d,
+ 'gray-c': $gray-c,
+ 'gray-b': $gray-b,
+ 'gray-a': $gray-a,
+ 'gray': $gray-a,
+ ),
+ $grays
+);
+
+$darks: ();
+$darks: map-merge(
+ (
+ 'dark-9': $dark-9,
+ 'dark-8': $dark-8,
+ 'dark-7': $dark-7,
+ 'dark-6': $dark-6,
+ 'dark-5': $dark-5,
+ 'dark-4': $dark-4,
+ 'dark-3': $dark-3,
+ 'dark-2': $dark-2,
+ 'dark-1': $dark-1,
+ 'black': $black,
+ ),
+ $darks
+);
+
+// 边框
+$border-width: 1rpx !default; // 边框大小
+$border-color: $gray-d !default; // 边框颜色
+
+// 圆角
+$radius: 10rpx !default; // 默认圆角大小
+$radius-lg: 40rpx !default; // 大圆角
+$radius-sm: 6rpx !default; // 小圆角
+$round-pill: 1000rpx !default; // 半圆
+
+// 动画过渡
+$transition-base: all 0.2s ease-in-out !default; // 默认过渡
+$transition-base-out: all 0.04s ease-in-out !default; // 进场过渡
+$transition-fade: opacity 0.15s linear !default; // 透明过渡
+$transition-collapse: height 0.35s ease !default; // 收缩过渡
+
+// 间距
+$spacer: 20rpx !default;
+$spacers: () !default;
+$spacers: map-merge(
+ (
+ 0: 0,
+ 1: $spacer * 0.25,
+ 2: $spacer * 0.5,
+ 3: $spacer,
+ 4: $spacer * 1.5,
+ 5: $spacer * 3,
+ 6: $spacer * 5,
+ ),
+ $spacers
+);
+// 字形
+$font-weight-lighter: lighter !default;
+$font-weight-light: 300 !default;
+$font-weight-normal: 400 !default;
+$font-weight-bold: 700 !default;
+$font-weight-bolder: 900 !default;
+$fontsize: () !default;
+$fontsize: map-merge(
+ (
+ xs: 20,
+ sm: 24,
+ df: 28,
+ lg: 32,
+ xl: 36,
+ xxl: 44,
+ sl: 80,
+ xsl: 120,
+ ),
+ $fontsize
+);
+// 段落
+$line-height-base: 1.5 !default;
+$line-height-lg: 2 !default;
+$line-height-sm: 1.25 !default;
+// 图标
+$iconsize: () !default;
+$iconsize: map-merge(
+ (
+ xs: 0.5,
+ sm: 0.75,
+ df: 1,
+ lg: 1.25,
+ xl: 1.5,
+ xxl: 2,
+ sl: 6,
+ xsl: 10,
+ ),
+ $iconsize
+);
diff --git a/sheep/scss/font/OPPOSANS-M-subfont.ttf b/sheep/scss/font/OPPOSANS-M-subfont.ttf
new file mode 100644
index 0000000000000000000000000000000000000000..88ff8353fd5fb53cf1a4d7055ba7e09a12a94514
GIT binary patch
literal 9832
zcmcI~d3apKm2XwuZnbu)Ey-GJNxfKVZPwQ6MN)T5t(IC+FWUFDTf1y6wj^xX7;Fdx
z8yh?EGMNw(AVY{fc>w|#GO=N71_y=!AsCoIf|+4hJbZ*CBrutYb^HD5cFUHXyf=Tm
z?{$B5Z{4aor_MQb&Z$%9UP1{W(PSSHNOg02QR%{1YzA6hM)8f#`nMhSKN3L*Eg*!s
zCjE=s&>lsIu#9{7hl30k1RAF=<=_dnZ
zkPMMw;v>7s&14U`h1?qWFc1K~8}Z~^ho_iS0FPC|W4{iMe=VNCzk!ls&{9lH#0)Al
zpf{f+p>-We1-0QMouuKO9ylNPL*O@o&jTxg&j|^f3H&1P?}66>zb4y){DPwY=N}FG
zpHa}-w)&2Np>~(s*=293ZZMk6B;JWLTD5g8R76B`$=T$hlT
zv_3f{HElyvV{?D2Z)18!rb?~RZpzBm<>cn&7i=ypDlRG2ml-_6-oF2tfdBs^D4|&4
zNa)XW;D>^reTbTZBtWN>YNcGQRA(g!`ec({NYF-6!M_sDo?h9{mRDZB_)6<{zvub+
zTWu$Qz&^b4qF}bHRGDZY&HmG$#J9zZl!{z&2qQ^>^XwdSSAkhbmRg~uda8|LOeX%+
zJ4MrW(zN+4d-wg|6G46DJ?fxe5pUse0%-!=65!&Y8yY|+#!@ZlDb1isiD8NiN|pLj
zqoFKYn^2aWFFmlO@+pV-EG@GR8)_;VIz{`F*1G!2hgzJ^J?CtB&@pZn)cQfIy*D9Y
zl0Fb1wUyRdF}2Ps{<;ZzWeS{T_p{H)2Fz7zO2%xOLTV_pQGMz9WJR`C6N`y4?co!;
z&g3K0mF#n!56p_cqw%v3bWR@H`^|6eJw#iVPmc=f(bKz*oLc$%Nyvjrc+!CfelH=c@SnZnzx4|0-qrEzFdlw0K^m*Y^)z*gKbfS@vjd{oD;|@E
zhIoGhysJZU{;Qlr+*YbJsM!%T1S7u4XVmFoZ{U4iq2`#t!(
z1dM-Xk`EF!`9h+E{3+n3!|dR%aFJsw$Xo
z<$I&^Av*pBaL`6MCq%EL`UuJr#Row}%`M_7x~qzw5VwMk<8(&6QZT&onc0>{09>IMJAAE!Sbx?2?Qsbcr6EV8>-b^xZ0
zJrd-R>&K&jyQ-~xq3#Frz!TrriO56*!$)2XW?rQ3xmr)nr5Y)Eq?&fas
z3BLDndOIX~6X55GJXxy?yJlFDEz579nN`osH5Hd$CA>F4))1b2Vm|gN?aODC*OMNi
z{U~UUCCQ*&8={;0j0CtI$z|kIT72^)EvTC`kN19li}=9fPM6F1IE@jX6x0=4oc=x0
z;^XweriS|F;2PyY=B_mz~6tbLv)RipjR
zrMf*WTfV-bBWcvt(x+{8?%u`{?W4w4w{AL`yK(zi?bgbHjvSla!P;Pfh>J)`w0{KKVUKcfYkV4&C*$`&Wk9gPb1~
z__-gj@MCg7QVCR`Ea#W$0DD!;ZuAMTMPu4mn%gZPE
z+)m8hE65NFWvzPPY+aZ_EBQ0N198Ky-I2eOAox=d-%=@}yZm
z>OJVSnZ4=84)zb?Bc%rKp}w_~Qi)#$_(dE``3|=h{o3u1mUnE4Z;PxnlzQ?o!9-$P
z{ML5wPKRSBOLbM~a*IskwT^L9cUFaqvv{xx{FH&8`c;19Hwuz#XR>euKlF1M#8~5;
z<6^Y>GkmhKJU4`xpYJJwD63N1%WXjsno4QMN_~fsX02uD>KYboy>=?y&QkolTk
zC5K`I?nQX4Kr1}U4#%>`%dcM8TApNac^;P9bg&O@Bxu&ns}9RiJ6Vo7oZ`o
z)6~Aoc$U=7hTFv__f5)175c#evq6{QsVl*5ov3%G}dWKOUpJF7sbT4
zVO}lf-OBFg`jj9=1g0d(FeQ(rhxd9nFDHAwYO|}mug`awJ}cgvn-lJh>2%R8%}0;&
z;D_^m8af%naln%Y!PkZt$@BvzvmG1U;;X6k3=Yex;`?{bjnccs1C7ot-Ly`$br?CG
z6zFyZ@F2cG%)objR`IJX?`}PHip6kmAV$+a@^Kp2+9<{$j=nCo5Jtbh^~jN}50Bn_
zWcJ9-9EN@-t^-^G{S7Z6SXKa79$V-X+SQ{gJ@btdvoBp(I&yT&KmBvn=bzI&s`>O&
z@m=v>I9<@Ga=;+ILfm7L2rCzVKJC9ebMpHv=E^&7ur^Uif6MV3z(W+qULR9LiFvd`
ze41Vme;D6vq34?|ViiOO8_9?4nh`ff@%)Zl@`%t4n$jK(Ir`E3?I`mau9_#My
z?e2EJ`NE5DzWL${Z?@CMhaYs(#+OwFHzc-`Qm3UlMcA)Uk5#JWJQ&`H6S0uC^PvZ|UL?w;F|UCJI?
zV_$Dm(G6JMi0xFid2*k1jk#szzOW4@tk$lcsiWTCkojz7|>1<0xZw0ki}B#FT+
z+9bre2C7%;ah77Xc^Ka#(p
zyxuuy9qw*)cFB7i>U$rpU#zz8Y-;(|#9Loj%JQqWH+uTpow4qL0lt=Y$is}exVN6Vs7GrnXhOM-)(&eheXtCAR*XKe3ZCqaGA+OJZ@}gY%v?ikoKI9r@ic+H~sHC8U
zSuAy5-}Y!hs;LnZAtG}xR*SV=@}By}-X8jK^SzUAePJ!luioC+umI8h2c+fcA8;d;
z#`pZ6ke85&gzcNwL?Cw~^5D@&g>*%Y%hno*C(k4I2s<_fse-mV9~&Dz9HofN&lzcQ
zICOhUx$d(dUV0gLah_Zo+pMjx&cbKngcm_g@#G~57mps-P??a(
zMFS#M5p`{h9*$N-tij`O9(6c!_9AFxq%m-Yya3%0c)SIdB`DV5no3(t%ap<_jph_9
zUwL6(3cnC}N&FNA&d}drP12DKCN$(Bt~rQU8iyD(NelHc3Tv=Z$0n`AHn*`QX`u&U
zV|w1E)Qu?}8QF0;63ZGbeL!o>H901;8ayR^6$N#r+LVmO$~M1FDL#CS07|lG3XZP7
z!}*-hWQ9(lGwDppI=#Y_OuP2AO-yv$c24z_aw7hzO!~=j+sTu*6d>O?AO;4TX!Jd!tFUUodI5_B
zR6;0{;Hgob?BMyI^_5siY1iSZ#q*7ZU;+g31^k258}?#!OkAusGgBKE8y%CMUDju9
z<+a?bf`Y8vnCRHJR%;(X*`Bm)m8w{kWr~k8WvPo*8*|gNIld;F#-L8mOUo|sTWTmviCWAf+4~lG^Qql?m;WE|%zF()bQF_~G&n+n(>zc}Er?!ucHqRt?
zXa;u9-25|>1?iFsr=_;;(4k15E5}?HN$nfwI{KGm4jznXuhsdK;s=?FKL2g>H5D7He>FPRi*Lv9#4RPS1kMQ?V5f+BC}hHq$smm%lToCE5A&XS{q@&<7cX8s^~%gM
zXQ%0&w(+(np1_4JiGNF{xSS~IAu~+FjNGTwRSXDQndWTkGtac1rMdiimXBo^`!v(g
zPeU?=#QDF6z9br@@@ea_AZNcqnHrb|V8_Snd+z@ZPg_cJUmF)g
zld=q1822qY&hgRTedqq3S6hD0$9X7YMR=8$jt7W4c$$}j`*dW>d0K$$J?xHNYHhB_
zHfmDU>(Vv6YF4MH6Vlc6usquAO<5lwpSe*MSsttfX=tE!X2aU^7y!94_#OJ;cfZ^F
zdh11Mr?cWQ`nt%M9dZ8if{Cp_PI0SoK*E}6Q$RXTE?HpE{E_bo(h2esf-g~|-j_W6
z*y#KFbGqr9U1E5CQBgh${Z^>iv)V8+KRh%)KQufq&LLk~UtLpQUsGK#ejiP9bLbL(
zP;a-_^MZ9T29&Z0_TP9r=mr81
zvvd~C=o5>(k;r~#_u$`UnTpSEJ@&z^xBmOFL+|XWm~xm}l^eRv))BLL#A@i=An%m>
z-Bz31ZL_-R?XMM>Y8IRm_xDWxWapmqGqnbbz2&x#PkilP_sm|{>pRg_S*kZXb~QEa
za_9@Y)$esqPj_}sam5r!5n`^-u!m+MhA6`Vtmd?D47rkd&QOs|;rc=wZ5Rbp68&tZ
zZt{rtrs|fil6?I@WyL_5r~jNGek8v0t1F*nZLTjf6&0Cj?7I#_k885Z+iM)Nx9li1
zHx-w)6&ALZ*#`?Q4t(WDJCCzno5~9{*3AV5!^$ULXuah%Et38Y1-i+Z&|Zc_&d^|J
zC*wL>$vVg-Ar7371g%bgsil2{b({(69PcN;czby3aGd1}5+z*b&2N|V+#%gB96y4L
z%|%%Rybgi)V!RbUzzCPc^MuH3feW}s@RsX-e&GU{rr9vnH%StEh%~Y1iHZFe?n5Yb
zD1X4SNSbH@>7pwnjopj33eqGzhCAAYbYf&Th3@yE?G}>9#z_wQGv2TRrz{gN=ZK2^
zJ&9%iK+NnQDMfLz&A8t~%GfC0zaJr5_EkLJN?cS%YN#x5f$61st8fNmZ$()O!2zBg
z#&ZnO(G!5o`HHBdqOJaIYvsbI;X@V=kmy?X&^Ap6MwBCnClM5M*kMSJKH{Th9Mo~3WF
zFr1*r*kSfEyCe`{y-+5!2~)y8;aTBNvTWIi?6~YnnJCYYTjUe+ee%Qd=j0!SrG&MG
z9S(aW>=Q+_qF7O@7*Xs|998_i;x)zl;j!V>;RE4E!(R;lbwpl-FJec;p@_#L-ir8R
zWLaceSWYYQ7=cm6P+FHiuOe>MemQkFZ!kEOECp8
ze-m>#=F3=_q*;FA;cw#bWB5WsMSPM9hD$B@nu5k&)j!y0s7`UVEDO~cbk`QD3&{D`
zh3Y(KI2fwSk%O2F)x*%f7^*8U-z}kfIDGE6L-lyPmpB=!E8(*rgMCq00s(bTh3beS
z>H1Kekyx4+stcqT--ZOo%P?jtRF{(!x+hc*L;LYiT|uhp$xuBU{9X>#<4HUfLvUs#-;pHr=E-R!;EKfS2(tCkl0
zW8<^_g{`XjiQw!F{<&S#D(C#%(&Fk+@A%mCO|xW_%;Rg1U1WhwV-2Rr65`}=G8%}0
z>`U4i{N1%v#9=$V>#}>grAn^@&j%O
z^!P#dIGL4b+lsb%GJ)$VR3U7dbFvF_sfbgWZwc_L{i}R>CH|+udPnG&k*Z)){_G19$$I$nN>ygYAE~
literal 0
HcmV?d00001
diff --git a/sheep/scss/icon/_coloricon.scss b/sheep/scss/icon/_coloricon.scss
new file mode 100644
index 0000000..f391ca4
--- /dev/null
+++ b/sheep/scss/icon/_coloricon.scss
@@ -0,0 +1,1340 @@
+@font-face {
+ font-family: 'coloricon';
+ src: url('data:application/x-font-woff2;charset=utf-8;base64,d09GMgABAAAAAJB0AAsAAAABT2gAAJAjAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHEIGVgC2EAqEpFiDtnIBNgIkA41oC4Z2AAQgBYUFB6ZDW0MUcaXY+Rchm9sGAFyUefbfx8xAsHGggXE4nBkINg4AzP0LZv///5+cLMaY94fewyMalFrZ2ga5yULJUZe2LpVkI+Nw45t15DA3bZWGke2LGWi24f4YvmNgiXRNPyTiB06y8TyfitG1IxylZTxRDuTdZltIe+EMrNUGezNRT7j6BH0uGz5KPBxOJbIZrz905GlCkIxEiwJKk3WZsDHNRZuYNIPT4YJSRLtm5eKScbKb7NmZ82/KaUVkxN1piXVhjne77IFbJX7B2Wvyk7d4tkFifr9Uf99o5o6aHtMpxT+s8/7P7mUuC2wb9qLR0RMUgKNMJ/AnQunNJh449t770YvECqLpQEZR1DSwaJ3ILApoII0bDctGQMihH3gCXEEpgRMvlTSNAOCh1n5vINEZmoROL5RONEmXSKK3d19c9r7rQgBx86qRaLAb6Cbo+d6wbddLtJ1YeZ7jeIa+mauvUpFBzpNbdtwONODM9AeiJTjt7YDD83Pr/f/HWP4lPWBBxRhVS+gxGCNyEq0iSKnAQARmEUoJysA7RTBQMUEZVqIXeqGCkXeKnhclFLLzApXA6PbLf/7enXPX+2sWZmtwHljiA4QDDSShUCdrOMr6/TzZ5v+ZXarUXREIRYGlzlhWsAAWFpQu6wJzL1IUEAXsWHDXxlxsYHmKDVsKYN07KRTFsnzBkgr5UTNDmppWNaSbvDzvfTr9f6mVznmVIPeGHjr48DNWbPgAUALKrdxKK0rYsFoFyVbgokO2MztTlD8CBrdZIqFSKgwzv4J3AMAAxcFzYgfzxatbVWX/xXVYw1IssnlYzaCbU3tcggxQFyz7NdDkiiw5rpcqKc39X6qWuwDpsAsQJ8eqcFPbo4AFFDIV5oYXst7DhmpPrWMI3X/u7Px/bvYf2lD9c5I8g4hCiBiwEllL8kxm5ia+C+tOAy001bdWtBMRZFO1ulkzS95LTY1PTZ+KFhIhmWeI4ICUw/+o0166Ufqf9SRD4YOh8AFgWBMupZQia7FXew3aPQ7aBwjz3VRN/a9b8KF7ZpRUydYHpjiLEDsNsvVAYEcPWZeZa8+1QWLHT2Qp+CPJAdoN0kDt4bL+15omOs4UxjP+29VVQEIH3KVGdjxKBNeZBwVFwLa1HAIM4GDklqDpcJNuY7GOy/tRhCZeMGb+S9W8ApQo09YmodIqtyhPzmnL4WI7rZzzcopve0+b//8MMH8aODMAgRkAFAcgaQKgZAxAygBIUQAIMgOS8oLFDulKyfaWrm11BqBkAHQBSElLahtpO/uk9Lq1aFNKvedc6zW3nO79mH65X9I0MKLIIFFgR5JgABhOjiUWAIdZZdpS5zJX+eNMkCNCoifIFBKE0u5cX0mj0WL81uHcoUgvjF2dMLv7VP58xBMZn1FEzkUUqhaqKdcoupdISbJzcYBuj/lufVW92Oue7pmRQiRICBKCiPxaTsO9B9uUFmiZdgfDLKJNEKvJ7Xu3IdzWDwTrm1dQQFklt7rKjb3D2KzDzY80Zp0uGiMBswafp0fAcAwoL0A83b5UOCVeThUQyerIwcIzmVLl0FAjVAr3KCNSIdSEu3cLwEn8ls8/uIjBYJRFXqquvNRimMYf0H54+HL0KxtSTwGu7gmDg0EwBIbKLoaHTBX0ExskiMbD9/Zg2RHYWmMhTH0YwKPg4HHmxpOPIKHEspkVwIqVW2eTRu06dOmz3+G5JIMyImMyKTOyLi05mu/5jQXnXmILKmtjWzrUq9bJcv9DFYImDhHN5OF2XPHtfo8pkiGXhWhVptIGW+ywfff4e+1ywOTVa7Iph/ai1vpdx7//X6zCiimmmafs9eFHHXfWfvUxr7vrMXADv1UUTOnqWeHo7vFz2rHv6sWadfahdbK9/19nLl+/5jW/Cr/VZnc4XW4PgAiTFM2wHC+Ikqyomm6Ylu24nh+EUZykWV6UVd20XT+M07ys236c1/28RFNAOEFSTBabw+XxBUKRWNJUsEyuUKrUGq2O1huMJnMli9Vmdzhdbk/TIFAABkcgUWgMFocnEElkCpVGZ9TwZbE5XB5fIBQxLBSYYHBCEeFEUuIQJTsrqqYbxIUybjEPaE6JsqCe9nQ4DFWooCsoOMQZ65x1znTnXXDRJZddcdU1191w0y1h1Lhzx1333AcGODXDKA+BDdiBAziBC7jBmRfAC3zQ9QgCIAhCIAwiIApiIA4SIAlSIA0yIAtyIA8KoAhKoAwqoApqoA4aoAkdn8ACRzRY9RK0QQd0wbksb8GlbO/AAAx99MlnXxLOldljv8NyfHXcCRXNcso33/1w2gKzVbLKHM38NEZz5bTQUiut/dJGW+2Ut95Y4+Rqr4OOOqmtszq66Kqu3/74K083//wP86mv1GrdNdBDT2v00lsffdOkkKJxBQpF0aKNdkEpZR10ijZejFj99DdAnIEGibdRgk0SJdlsi2QpUqXZapvtdthpl90WJltrsSKLLDHYEHvtM9QwwxU74KBDKquiqmqqG2GkI0466pi5athgqWWWW6GmWiZYGZI1k0yOpEbkgN3QEQBj3NGQ/CF4J4/0IER6EYb9EYEDEAMzoAHpQxzpRzwZQCIZRBIZQjIZRpSMIIWMIo2MIZ2MI4NMIJNMohGZQmMyjSZkBk3JLJqROTQn82hBFpBFFtGSLKEVWUZrsoJssoocIkUeWUM7so72ZAMdyCY6ki10ItvoTHbQleyiG9lDPtlHD3KAAnKInuQIfcgx+pET9CenGEDOMJCcYxC5wFByiSJyhWJyjWHkBsPJLUaQO4wk9xhNHjCGPGIseUI5eUYFecF48ooJ5A0TyTuqyAcmkU9MJV+YQb4xk/xgFvnF7K1TK0D0MAd2xVyij3nEAPOJIRYQIywkxlhETLCYmGIJMcNSYo5lxAJXEktcRaxwNbHGcmKDa4gtVhA7XEvssQp2w2rigDXEEWuJE9YRZ1xPXHADccV64oYNxB0biQdqiCc2ES/cSLyxhfjgJuKLrcQP24g/tsN0uJ0EYAcJxC4ShL0kGPtICO4ioThIwnCIhONuEoF7YHccJpGoI1E4QqJxlIhxL4nBr0gsfk3icB+Jx/0kAQ+QRBwnSThBkvEgScFDJBUPkzScJOl4lGTgMZKJx0kWTpFsPEFy8CTJxVOwIJ4meXiG5ONZUoDTpBBnSBGeI8V4npTgLClFPSnDOVKOF2AhvAiBl0gFXiaVeIVU4VUYDF6DhfE6qcYbpAZvklq8BYvgbVKHd2BRvAuDw3lSj/dIA94njfgNacJviQS/I834PWnBB6QVH5I2/IG044+kA38infgz6cJHpBsfE3l8AkPABRgSLhJFfErU8BlRx+dwAr4gGvgShoKviCa+Jtr4hujgW6KL7+AG/AWOx1/hRnwPN+EH2AOX4Gb8CLfgJ7gVf4Pb8DPcjr/DHfgH3Il/wl34F9yNf8M9+A/ci//CffgfDA3/h2HgF7gfl+EBCuBBCsFDFIaHAUXgEUAxMCE1gD0pFramhvAooDh4DFA8PA4oAZ4AlAhPAkqCpwAlw9OAojARpcAzgFLhWUBp8BygdKJMGfA8oEx4AVAjeBFQY3gJUBN4GVBTeAVQM3gVUHN4DVALeB1QFrwBqCW8CagVvAWoNbwNKBveAZQD7wLKhfcA5cH7gNrAB4DawoeA2sFHgNrDx4A6wCeAOsKngDrBZ4A6w+eAusAXgLqCgLoRJeoOBZQPA4B6wLCo4EjzBGxDveBLQL3hK0B94GtAfeEbQP1gYuoPk9AA+BbQQNiLBsGkNBi+AzQEvgc0FH6gQviRiuAnKoafqQR+oVIiR2VwHg2D82k4XEAj4GIaCZfTKJiMRsOvNAauprFwDZXDjDQO9qYKuI7Gw280AX6nSviDJsL1VAUH0iTYhybDTDQFjqapsC9Ng8VoOvxJM2BbmgmL0yyYnmbDElQNS9IVsBTNgaVpLvxF82AZmg/L0gJYjhbCIFoEJ9Ji2I6WwPa0FCanZbA8XQkr0FWwIl0NK9FymJuugZVpBcxDK2EVuhZWpVUwL62Gv2kN/ENr4V9aB1PQdbAaXQ//0Q3wP60noA0wH22E+akGVqdNcAxthjXoRliAtsCadBOsRVvhWNoGa9N2WIdqYV26GdajW4iAbiVCuo2I6HaYknbAVLQTpqZdMDzaDSOgO2BEdCeMhPYQGdpLZGkfjIz2wyh0AEalu2AHOgij0SEYne6G9eke2IAOw4ZUB2PQEdiIjsLGdC+MSb+Ck+nXMBbdB6fQ/TA2HYNx6AE4lY7DaXQCxqUHYTx6CManh2ECegROp5NwBj0KZ9JjcBY9DmfTKTiHnoBz6Uk4iJ4iWvQ0HEfPwCH0LExDp+FgOgOH0nOwCT0Pm9JZuJDq4SI6B5vRC7A5vQhb0EswLb0Dl9B7cCn9Bi6j38PM9AeYhT6DWelzmI2+hNnpK9iSvoat6BJcQT/CtfR3uJL+CVcxAGA/BmCYgwF3OImBRDQOg2TE4ZCCOAIyEEdCFWJOqEbMBesRO0IX4ih4hWlh2IJfb3iyPoQX9CO8YQSbbf4rtnBYc3ffAOj29WOOxyyvMS+j/vNTRiRKCH7qEclaiuKaY589GRP6vBKllqrk5U5BKmmgCot2ZQq5Vqg6LFL2TMwMjcipeLsgF2wfzZxq1MLes3hGLvCoPo2oc8jYO0d/qsCpG3ElVaZHYxGRpJ+SKwmDct4Jor5yZ7JP9Zf2DN11RYrcmlrKSVusThXqTyWlJ1kLaqI/tCc0pEFZsnfx3iGjOKmiXhEjqtRKiNmIKEwETm3qqpWEop3pQTgJFCc1hT4lcCnVg7Er3wKlnHWKjbVRyIbq+DEyu3hELlow3pMzMeTOt2FTp2GMigheKFrSUekv4igCooGI1BQOxExykpTVP5GVMmsmuEFFjWQuuBPZaNTJhXpbaB/jNE5e06PH8Yi9NlAopXd98gtx4aKranJN77jnc0zaPfKsK18C0vzzUF28x+N6XbcA+XB5qNaHz2SbYZUMaVzRBjnbE5UnSH0roWrVnVeZU5q7X/s2RrkwR0N9hmTx3YsF6q6Tn9oi6208ugO85J6HsJX4rWM7UqtEsGpId+MaVSlt7L1Ct0DbsWptdtG5EPH941zmIZbIXQff8gTf09LVlVuUwXrX3nDDqncBBhoW6RVyJcorWEq58yIuEpKImUk3F6WGcwv0QKota0YQfqqEt9tGPyBg5pgZQb2bNRps+AnxFtiuNUE/Pm5x2V/geA+axXa/2sryOR6AxxLX16yjl1X7lM2sVsrm2c/efX5SbDvvbM7ne9qgwcPjWPKQSselWedLujTHg6yBpcjx9jVG/IAiAVzqPfeQAAJNM3C3YS01zcz3c77ZyK2zCLsWDX8vKGW5rHTMY/MSRWpYD4+yNW03zMqX8S7+Dt13aoKO+tMBpHUy/YGE0q2fHAXPMJ78LnZbcfdggC7dfpBRk9QI1Et8aq11BItXyCyn0nbdDX5kjK6wXa1ENVzh/idsvr40jPUOAa+u9Tca+lt3h78Er/XyeBGY9+DpwXR8cBuLyvi0tV7hfIbZ27ccOc+h7wGrZbnaPXn6lTdLVpmO8lriJCFoanpgTiH8+Rp3f4f+r3zGbccscwmqCSDccnt+q/vNzyKIaKrb0bnC6BLYKUIAmAjMDqBZOBQvtp2X+k4YQbKMcoy2ErMBgUmbwmQZMbNHgRaI8S5UMEV8O7OKiXfLdDXeG+es+em2tc4d2MJM7kwgHxvx1no/ElFSzWq62+t9iF00ZWMQr80ss+rEHOAzPc77MDFxhouiezYK1rYPKHc978ktO6utCV4XGDkgZDllNz8I0+ioivUaXrJ1UtOwRCMN59iLjecBuSUWbBVqnBRuhzrA0iyls+RpttukttAhRFWpaxzIudS2lgjo3d2yLAAxrwfkclaWsC57KyAQDGnreJy/rDZ9eNjbiNTX3hEC2UnYh9AzAgdvZxvrKKaPzGnaJO+31xSgRsmwxek6o3aTooQ1R5EdYAx+foxE+Jq+l9jUM5C2NltzzgXWtHzYhzlSFV9xOvjalhCaftyOkM/mdGryCF9h6JkoRhabZrAxRYHIQKBiRkHNccWCsbhJcALNZTUm/xx3DBbrp9i3ejpWVvPcltf2em4FeIG6qUuGAhBMW+EdRAsGzuw04CoeeesYb+592rj0yv9Bj3my38q3yPndTxqXX9Mf9tknekDIh266Sc9GcsDofRjbTSGm5u1qvZ0rpNfM6Yle7aNBODZgqkOz7nWWDXpj/aV1/eEwDoAivbUUoM4MgBVGOGmNwrOH0EnZSTKacpmYOenJ80h573LTov+1RQNoCDTDwhhMzB4DKZH5gLSl4xVbNbVxa90/aNUu3n36+/fGY1bjnFnii3+zEUWvmQYkGAv9gmutUQxn+F1jsoOTrcze30jVhLvVnB3NlovKRivjPU13/aZ/+zyGDniy7d/v95K236wjREEqjm5SSMwj2gS630+RGlg0EeK7zhCMBRnctIHp7UcMFoCN77CtQQX7NrXLfhDuXYuOHRc8Zj+8duSd2Jg8xuITvsiVyNgdOhI1/kqYNRRamgvMC9Eo72s3l7Ip8t1fIfwEUrEhJA6ABFY08l1Zc/ZEIte6pS8WC5gvbfGnwjHZWC3YywNADYSGKyyv/HL5wbJ7vm7Dyk3FtQ7FR2X7lhNLMHTA0HAP0DI7MxhGMBY1EMNJJ4HpKxmQKTQDQGvzkoVP0HrJoLYQ69HXmCBpACIdoECZmKqa4NjYkJvqxO0S3bg5PxHehoGAf2xd/utY9L9n4H8uvwauUr1ikxMb4EcyjevOxbsvrYnCYmA8WH29h5PoEUQQ703QCyGGNDgJ/sBOWBxg5HHrW7hChRe+XdmXBQriKrAXmXeZgRDOW/Zqby0AmpLeSBqehgiI3kjs5i3z46nBaL2ZgPjdrKcJIUwmRpt6s+PdUYB7PnNWa30TvZlWbht9kCqSs2ydK4194r506F3NX9BDxtqT9bMVjZkkgNYdY1+mFIx5WnskID2iO0vrHPp7THowoO4NZgzj+sC6QpSSKZ9MBny0h7XHfrU7co/546/eIdGxaFkaHkqjX8hXqFauGDOoP4ZPk7nX+UmzqTq/Fuk9dJOabAZB2BYxx/KzuYxJjDR2l3sk8vyZb8wp0p+OTSKhADgkOUPtOyydgsd3hQeH549du3LmaFoF1UqlVCpP1feiMIhalXjcHr389u2y5EOQrLcCsb3OsJgJnGnbC06IYd23K3LhFCQonxHpzKaw0X3TV4OGdXlYqPTIkqwNzBNgYhjB6vlHYEA3ZcFC2MlLfit0gxYR3OnOHO19Y8ZPlSUFH+85eErYQ1UT6nUmJiTUJXpnW1SVnBX+eUxp3/ChJfsWssVDTObd5jLPF77wwrE7j4tBwJyjSm6G5Pb5Me1wG6kXPk7IOJ/0M9hm6O0DGbQqeMTN1gOveApc8IYHK+DhOmB/4kBbUj9+7WuBfPK7QJ/8iacf/lD423+OJFnCKHHpnhOLKIKN03Lreepxh0LgcEzAEbYOQwLLSN1zPN5j+IxH3lQhac1NILQM1CZkQQZfdvgRRFGAxu9ih34pyKmXvM7oCBwWzwM7AhfcWcv6YqQZTUTdJMqb7hfs4bZ9qzru5TSsHgt3qc0xSvnHD2HIyOT3UfpgRlvtkUfHC73Gp5UA6gEACgLF/2owWyWn4el9NS/j8jU/4mxSHf7xr6s/TJ0BQu9x8X9QvwjPH6pa3MtdktHt3F0+yLscHao6jNBDRw4Tuolgpbq2qdLD1BevPTjH6Ocolnd23lORZNFvn7xgAITDndP3o1mLsxMXTYBxtHvqnqTjbwKocy/SYCsbPWGLXR5xW4EbjoI59tdO1WW5N1LE+HqV3NHGCaT78AfOQ+L9QeB5HL5D3CpHbwjROSUShDB698tgP9i3/+/0L/MjB4r/NP7wN7RvLab/gR1cGF+p/Ov0Y9/WvzkvIuuh9BC7D3/EZm1u4ApRrBKcbrNPrVpcdC4cRw6LMeiSD2IB9jdMkLqXrluL0pQMzMZ5Tt73fZb6vWMHO9cRPSrhxOvTK+My+ym1duXf34dvtb/SvvjTEy7J2Phcv+C3oT7BP75hr5df7V3+ZXOXK+f67GCi9+B54nR4ggYJzekZuv+Fh2+2e7YtjYd2pQ5cY2pPApNnPiXdy2PbQIiQaT7K8+tPd4auzey+3B1jcdHe7hAe9I23OuQwFi86Bq9OTrodo0Hq7XRwD/unu8a1OjvSf644f66w+FxBXBalX/vA/NaxuaWMnG9Z3LvyHD4n0Ptbhos71xOWObjfhVH73Haz2VTaf9RK9RdkV15DYo+FFiVkDKU+yijA4ClkyNEq+8BnCM5yOLE7RRYqXh5zppweix+dc1theF1kLDcExoIVASHqiuzXVzlxjo8TXMYLXqJnZLV8el8UH2JYGuNN4FYIyQm9Tz/IzFcMnntOmaorbK3EnJRgDba1+OOHyFMDic6ZW6WM4RzIQE2JvPGdEsmNp4K3qdtt72O9T4G/aOW7xsDXcY8EbH4xodSgg44iTWjh+JnAVJyQnyeLMYaxUB1xz90iH8TL68+UgnW+VpOTUHMR/ePTKjGD3XA+q8Lg6OVtdYvtGOrip7HpKcC7rUftkcNsWxtlWdOCWGrva1ZnojGbPm3zLYUtiArLHaO2Mm6NYm4PeTkL9uJpnBHrPqSIu++Mq7/poYe1j2zEeR0TEigmqA+2wXYLj0EiQWyMgbAl43LWbLuY0NkzE1qmpYqsKHpc/DQP+IoWCIsalbhdCuvFF1Oc8vS/BxtfD6nPr5DrmmA7DQ467R8pKPedgG+uI4YIKlCCXwEjkCnVRkLY/4ju4bhLK5vdJGF8hHxgj5sw6X1EPdxHV2+Ge7gBzd7HzKNHiYtnCRUkPAQjD62S/QBDT4xfcPqKfua1sW0vRxHIWArLoTVHPE9KL0wrvWm385t2Kem0u9UJF5XNxQadtcIMwnYhab5rSQ6aNIBVFk4Sizbw4X4ay/ZzhUG7CIu0JzJOMlN7ZYIAaQMv1ZfOvqQzanhsZdbLfGUmwYswFeKsSaez74juB6v6q9Pcvzv4cmP5zIvdfoKR6z9m9ja1V5rf0wVQv8omUCP1YzfyOkU0LCCMidsOUcPpDc5stNQ2XHLp9VKN1MyMMj3dFNZ7wuKg6xAM9s3B04zZ7P+UoNAPBrl+Gm1DbYbp4YGFZsDIugrBjqpIFusJw4rmEAjjbcSsShVl64qnTnZAG2QWdcHprwFNEA9AVqJJbooyhkxQfM1iNnsLuTHFxeSmO96irrOIx+pmo5bRrHgitigdhMGpDc5srNM7uD9oO3e8e+799fS21+YUpjUiSAqo1QEwCrOasjVhS8rjusjlUEhVlTtsnKHvYsK9aozD03sBmLrH+k1QbnuAoIxA6X5LeNTFfgMG+z/v7eqtTWoyN5JMa8Jjsu61ogB7SXwtNSbuwOZ4xI2Aqlrcjq7v1lEVdpzztAadz1Sn470q613BTa3rAEL0pnZ9XoXrj5J8CtU+W5feZlHYwJ4FyBbbVxAIbFzCVpCsQ8flxCNc7ltXw9g9CEimZeBW+D7Pq5X397kvLP309XCAE6hiWhTPJ8wi9izN+ERDgDemmmdSQ/06G48CjAh6f209bhY0C4n6oJTqHsVSlar+9lq+3BJTnLvwL6t/pnym0TbtUa5/ttnZs9L2c8gdSLCNIJzZb2IzSJVcRPB5J21D7gRCmCKKSsqU50VdPrTYMcuS/3L8ZDvlH0t7IuFAMlQO+gB+UEfeN+scwyUEPUFQ0q6gMIe2XqnoBftZMN+xSRm4wBULROUbipW6Xqya9EOGa3JrAxCb/Ms3I34l0n5V/GUUXmntx/p6v3kstv+Z2cLH+lWcXG+qv6xU6qrf/NqocbRm/AP9trlJTklt3u5Ntc9+cBadvnQv//l1J5VhwMGCnx3YkR1GSwAhw/n54ma+7wC3QLOzHgaShvfyftjtFOLg6Yp5kWYhMM0BcRI8E9pctIDtztsI3DOCRAdDL/+Z/gIpMClkU6PvXyaAsAIsrG7PrhA86dncoUpR96qo0+BrWk1u6Dis0ozv12ssn+ghyUoOJA9Sw5tCVjTMZelASEum/iYL6qWwXYkb5aj8lzYI3cMOvwMxjD3DQA3RCDOcbP5p2HGJBIzhy3qGrvHQHUc0tzAvkO/0JN3B7zHIX8PconTaryVR3j/VuWn5ZaCNY9qatiS3xq8hAc24dpxAihEjrkeQtpgmJ0KkgUR7sN5DH/KoU6pr4m26zc/aqkXtqJpqGDW3S6cJlcOT4bX+Gip3HfZK/Qfa7TjwvqrFLq/BqSSTPAMOTdCvXfTzYGy0OeCTgHc1IdJqL0ZYfBjOz/1j+Fio/2NgEf96Gc2DHXBT7IpYb1SOxrGgfzRQjpHG85+ttjaV3lwdtBNrw462Vv9m/MP14XJgxrJNeeUMSt2epGdd5U6oVPr8WrDkWdpaDo4E8Z9xzWe1JQPiQE5VY+cCCxqTqpZZX1st8YZZeoNMdhkdLXKH6Dbte8L6QFdjvwYjnI6c1u6iSoqF0mq61sr9wR8WL6vXcJg/NdX9t06+m8SZnxeokFGiqtxd9V2oRjY9Z9RmjVKXPTUn7NwFdolwd3MvykGfNeUrmAZaFc2S1SWznt63HozBhmhydkIdp+oUnA5W0V2r4xnWU31+CJSbAHviGvuBV+c/Yv9iz+QdpaGGrDdbGgYIpieRtKYwPkg/KYoAD0lYbwLdlvzSbaaqAdi3uVHZz8lo2Dl9/+mXS3emGbegPmjCgGGB1IIgjaceCc6eOyoRUqXEKyA+xord4xtGFUhdQ9Jipj6QUhKjSsdaoKI0R0TGGn6/s8Dwi4ZXCRKU57hcGxzMk8Pz270JP9OSpGrAgVzU2PATnE2XKU1s1htgbVSRWFNAY53iQV6ut5M73+HbZvY5Q+C2TfumtJEXI86NjOcG6aA2zKcLu1OKfPrZCa6gm+AuvtaRPFhHvUL4DpFQxT2A92SVqAo7VywbdTwVO6YCudnCc1KtOOCX8X4rESMS8S2mlvxHLtSlB2qM3XMIEgg8emOSqMUC+Mq2xSFTjTzRGkKXTIF5xEvxHuHpyyD2EuQxNaJqBdwISsqumARj6TF9bRTLmqPHW530fnZVi5lO7qBShnWhJnBj7A7Lp19T6VhrWvB6F4zEyverwiQ80oEGxNs9KDURO2gy7IlUbNLUBMxEadlVNWNIGkFEqT+k4LlwI4bEPrvnxMhWjspHLwA49+DTjLJNgCOpXZwjeujaIeSUO6/JEFwfbpAd5xkmWTExH15CF2oJkiwqZ4GpDRQ1bT3JT4QVqQc4N9T7kQBiwGOYvPW5HsPvEsCcRbA7OBaoLXokGx+UsY7uSMl/yay3dmKqbb8axCl4OPtykGiyQCmav/x6d2wnVh2Pctwd53sjt9y+MRQWoAuGixHPORxU6nSYeLDRVmAyvwsBNCS9MoA3pdP1RRW09oMpoBaL7vpZc1C7ff+4e+6cNXRv3FHqRXe+e9W/Hh93j0XXvCsdRX7/U09bmEDo1zk1mPRYveRG3abfjkM3iFpeo1NLuxHsAmbEVPViPinIJ8TmDl4xZJiSXMSUe+2M3sW9qse4eJ6oTIRV1rGrEPtbT6lySHNDVpR/LOsXVzgKN+wGm7tTjakDaftsHYE717lhWeIgOoehl4jWsEn1YDbzp5adH5zG548di25dudI5c7QJd1cEDW6hvtCh9QbJd5Mt8ecWebQvnV/fb8CSr5SoR/GuKD98khwD843QOAYBxNuAByUTv6CBZc9CSTyi5dbq6cuJE0GlvSECo1UycYu7H0+jQgEo7InNKvzt3jzCb/UCu8XmClL1VhkJXNJJuwmXpEUtLBW4ioGplfXNrkXvnihT4DsUtm5z8/5tG/ufmFNBW8sbY0pR83PJNgAFIIogdqh5Qvpn6MEIQCekmQOJLsIXhc0Ho8n7Zyfvmp6a80uirOOwDS7GFyHzKmy0+P/aIXOUWLWfB3RPdfmyVSBQjZuoPqN6w+S+xkYtTUmZMH7CXGAXTKwYY7WB2BrJY3lwY0F5zu5xMhclMuz6RgPENeXEyZPj06dMqMKt5KkNon62OE9hkn12TZ8MPi0NWszcHFuQDiwpmcVhqQbEAhHOzAkwXhcPDTC8GG8II0vS0hGBZ7jjU+QXkBXjdgJhaEC44pRxoNkSNxwOF6c3FL6mNCykWucRRJUFGFFMtVmqA2L5SdzFQRrLITMBAgNIibYSW+9ONl1dLkFv0EZd1SIlcDL9oTNgUBel+iTvUQR3pFgtYVXYFwoHadySfYaSLN9C6kE4Umd4DlmHBDgHvWDeDVl4ZnewJqxIAVgWI9hIQtihQgSsAxJFiUBmIpVRBJqoCTABxX4pzsaGxlySRXyq+hBCCYiiYRyb08HkGG3yaP6xuysuSgHxcQm082oCkLwgppmuimn1njcQDTpvtOq0NliyCRs7d58KpgZ0AJ2DUv5bBe8/XabK18aa6H61o3vv/p1mbFN68LcXPjZ4+eW24pY1D0Wlk/DfugOT8+NI16pelDDmQsJ6NwnB3KpfdkoFU5W/eJIwsAQzIlxYXDik0B/ye7v/A86d8MkEw/2SaoUBF/tPVs4C+MGET/MPtsz28GGER3Ana/s6kdlfspDhtoRsFKvt3r7m29HDXMqJtYzljrMwuPx90HkESQ+GGbjASvMnY/EbJE/C7B90vQkHCl5jh10qprVlxs4xWE40Q9E6lKl8lnc9YumYb7DunZQXA6Yhma7ncp37B4XWwhagXMtvRasmtSLya/rFqvErM780sLathjtiIuOOI13GE72htHQiBgS7JTsD8g97nF1HpYTmybUbCgAMkMMdiZm3BAfGuvM+GOQx39m7tcXj11zg9SnSs6hXv/z4d7rde/KruKd8EX+34pfjBYQJ6dkUWA2nxxJg17vWlW/miNYMDKNAmWKZdFSGYevUv6n2sprjJDW/tvUvr8mF/z5dR33N3grEESfaixg8wDXt+z3BOfKczxjr//gxgRRhO/tGeLmpQpLnuWG4O9lrkR8MlCpxqZGq64iFnbrfYwgqtDbtXHYVIVF90LkQudk+EWuQdFoAd41lOTD5ujjAUL2mxk0m4spAnS6A99l3CQkmvq6rfFWOUiv+Jf2r6l/IbOo9qoojjhtClXUuo2fKqB+x2Z6Rjb0Kn2Ao0lNpHBttrMNY3y8jk1fWRgmHI+Zchge/6RNN2484q6YOaK8D5w74tqMFTmaMKFM4hH0mPaYq7GNxLoOpp7p8nsm7zPVoRtMUxADHMXvm5fWz2dk4ZtCrFBRjG1cBIftc8DoLPGOASxnZCQuOeQdeRWJcUQmN7x+5XUGThwBgAI8ZK5cq0CMgLGrVLEi+UoYbDKQ8AsYEpKkJipFFt3xirpgwEWlxV2KvO9SvwkQJqi7d3MT1PrqaIijU9NW5VjueBuUZpcIhkoHYzCjtP7mJ+Xk0aN4kXDfNCfV8+59POW+2dL1Wh3NSZ05hUA0qTr24oMX+sKl6OGyLondPrkTt7znwAfJ1rq70LrfySn58gtJVSXIf6Z8l2ZQCfzxBG1yabExeyHG0GBNHY9JqcJg0cavB6tD6vaHhdxl2f8fzmtD7fRPgH/2uD7+9Li+b6FtdY0hGzXbJghDV5WeB8gzlMaQG9mEtkiDHsdZmsYxddFUf9uCIlv8yYBTUHLAuVLi25V6E8zGNMzqaaI9ITTC4E3DT6NaScDaxvPl1sIIqU2MHXKIaB8IpgIChy5BRQt6JUQuiCJQd003iiDprK9XoTxAV53bUMObt4QuywkvrD0Ce2MNh5wIPzlTwNqRdaSN6Jp5tfzF4hFxylBUHlwMxtXe5bBIhr5/EIBHAHz8YYgTZ9+QYmRFCVzw8UsinzPv6FAJKHsimkCGCIDYeEnKcpzEcW2OaXRdj9P4KLysTGvtVU7RsolyyXAZPx0HmL9BfBEg1ZLwknWVCqgsO2IkjW8k2ETmNKNeZIZgrwDaES6/gvJpEFYzOiueGORUdC2UTDsNKg5dibKCAaS5usdamVzACcUFhGbq2OgeAJkkKEYo/NyHpD94rwvpTo27ij35k3WQVAEeCu5IFXIkdx2CPBNNp2UN05bzURJN/7VvS5Wtf0RRKrcOtfl+lKlxGCvaTwS5mdQ9BGuQB24xSDB7PG1hmWjCBHcWZ9nO7DZj8Yd2NoxV0SZwzE0C0F8HYhCEUQNMKLF7+C/a8Fn02uQyHQhPlurzvTdUBCQuT37NlYmp8OhXjokUKlm32B5HGpR6oF91jNrWFW8hpw+wMBeUzm7LMeFtsyCshg3zDAY49ZgpRk4uzDvYCBRq2KN9AVQYKDIATGCk4AyoFbKjDDSGfCft0KpC0F5w2d3Vna8hkoifoCdflJ1vKScbl9ChaSPGcHq2JoPCWhpAbi4yE3LsqCt8z+gCogMam9lMABzD8nWZULuga3wFOwLO/7/l+6/vQXD4BR/t99DXWt4Ybp2+bN5xpGeEP8wXEIEBUkDqwgzfCMrrwB/eMUnCH/9NTjeqpgxQ8agiU9cNOWKAmDutwEpl22aE13nBGdgmO4rNZM5xXlZkFhmXYuWQml38Nq7nwr/iRQCZV8BU1PuWv1LpCbb7TFlOi/U+oeUYOQGEFOA31MfhFgRwSlwbXwpQKKltl04JzJEx3NSI1WGW94OIFNwZTGFDhxtT5ArjxGppwydSq5qjti+amuqDVCKj6so79UBUfLRj+cXYtq6BGXNAHjKxUzAI/rwltfwhi5ObMz4Sy2hf8ACle4Zzuk3CFKnxwmFazOclY2cggtQdZL2XYoP/EY/eWXRXAvrDsmir6BXQ4J9/D8ZTtuGWwpcCGJV415CM05uvq/jAPAdMGorLUBt9rAgwTF5bHtUxbCFl6kQr+fpFZWeGWSDbrKh56bLOUJO06cqwgaMn5jXktB9fJCezMCE0qcnpathuY6xAGkuv+LzH1F1OWhO//4tanICCNb3m5ahbdY2sStOOAHAuQGGVmUSCAO7t/y/9mJTXvHLLNq5jKKntxrRcEZ4D9+9aPjUJzl7XVwim6DYbEqmEXMSqi5Z+LA0tGIdyHceKXE37FEau5LDAjZ48OkBRI9q4ic/XQp49LL7BChie62+a6MlUGYODfTGG0m24ndQX3CtSuht126sGYSR3FCqq7ZgiXDDcmLoTceLvfOvef3jguRf+H/1fsUbXmMYIcgwfQuYf6mFH4wBQRsvxQWBEyoRf4ZQQq0leO97Ewjf0I4YorZGATp8U/oQ4vZRlyIOYTI9VduiQtdmyZW/aPFixKX3533TkzIP91HqXhHuNya6aqwMfDQfYySmJSLvX+ZDM0QGYLzvR14bls7N6m7gwtx4vnb1PfHMhHigiyNLayS1irJvd5npgPebccNbYVwJp70NtpKO8IbpKZ4UfZNcvA8Eeq0Q55c3vdbahnD56FrmLXzN63f7nTVhPWFzqi+WYijD7o88f74h3K/sT3W4t8chmCg/ssEScXERbh2AgQRpHWBEnjA6nGeDYztwjb/6awBrHQc50s9yKtfOwuXYXrZddxnTRqejkHKGCLagaWPEW9pIkXf3DjJbUjaX9iCD1nRoXGSlYuHrznI2mcHGrsV2AlsZrJLTDy4GE23JqIIHpiVp/CFTAJ3n2kQUP5N6YMo1nCErdOPlzYajdGO/D+D31THjwl4YOntG83x2ITGBESs6wMy7aMxEObsiuk+DJ046Jv2yhdQJJh6E3vPf/9a6K8L575QL9IfudZ+WUt3iZPvX+14sovX/4ojoVcQDQTmyd82fXKqsnq67AUHV/1RU5xPR6J8nRDuRMIZaiLLxcJzOnPt4jPVCZ8Y7SDTUFLtWrz5aDhVSi5g8f9J8n7xPhXiaTF3x6qu0Eay+xEh0QKBPBNFsRFCP4iBB/5uuSd8P1O7NDfmqwBgR/J0xDPgu7fMAV7tQYxn7js9j0V7dtmHxhwMzw3bJX7G6J3fyc4NG8emCtmUutgyEC0bd5gcLHHjps/0USItZ1BZ4G12YfJzz96UO85Nkv+88dBJr5vFg9kAtQmQTlM1sn1YfBd/yO+Dw0FdJMPFzW04L1f1KVWHTzP7H2Mf7XC+sZsVHmM2/ed8epC1bwx0mMGmrF+LwBfHwQa+vXvTom+9eBLPNPr/NM39qUMrs3Fm/Whnxx/4kHvMajTk8P85HhrZWgyDUf5qXueNS8iJeSO3cDa05VmL2oNWIgEZ6g7l6kRtUdyUXb2QzaYUngG3BjYOZ3hluphIVbzPCCtBUDX/ORQ8PjqEsEtiYcdAxMLJ8bgw0Ut7Drf/BUf3/P5hOC0fHYb077uJSHbSE0MeHivDvf0KM82aVW4YYycd39h2gN6G1F7B1ctGQI9FCUz4osYl7EqlanisBIAFa5NdMpmhxxelrbZ4vppif1KupXZW5tDsbpZ5Sqq1xhh/MgWqcVMBwLnCAlA7nWRYUSpXlkT658pAeGeSfLdo6+2twdVaEz/GTGZ1owFEUQDfZVuAt5c0LrdpGlyW+qFYeGfNBNxjonPSbajeNJcNGYfvo5Yp22GA9PVTKLyk+n/0iwsA70zFmZRSzUNcBE9CB8Pov/L2YcFq1TF6PT6VXM+0gZOei1X9MZbjKAaDyu2hmcd1uYR8HU112TI2pKXhe+9ABoPKgeMzeCAB49rNLJH0FFvfVcSLlDxCiVaw18P7PH4ddjfkycxdB2BIZqQ1NiRkNeAQ3bFWq98IS06WN/VRPTrD9PtN13ge40S2Ia1KhSyht8wxNIyEwfroSTmCDY3f8ZQP/MLatoLrKzphAi/ftxnavT/ovWbeRTU2F4u7f50eJ5DjkiZM62sXSDRWTIWYE1sGI06FyqMROCySZCABhzMILOSueZkIW1P5cwE/iKYqBqru15etlYvdmHTBdqFhKURZv4wt+9CGefldEZ61Nq6CHDkymSzWS6wFqyk4WgphwQpEEwyGAlwGtmpzIl0Cpi3nQfmpZFnH6TVVr2C996AN36AHHJLrYkg5n/hW4iwtzt8eIqN53tujkqsbxUFMIAxJRdhF5t7V4tBpIfDuiX96v+rsfdq6c+tnuEora6jvjolPJukU0Esohyi9ZHe0RkCergcVGvr6lqq+upaAIRjH+BPxzkUEgFEY8S34baCUVGnv+VLFuCBJNij1uKyJbseYDpzDY49qESRVhB+xZPplJOWJ2m1mtAccaTkpQPrjWOa2cv703MyHZanqZOH3K6OJOm7o1NLl8UGcRgC3CHHmEg6dPhGhlj5GSiwBRJ26vCiH4y7K+cz+9Ob2ojjDC1oA1tJ4vVdUZV3cHTUrwU1xpquQshsa5CSdtvmdJD3MT7dmSaccU4pocFMMsj1aueDDj/GadFUCHEWkXMBRE644917+3XZ9IdNtaJWH0QiV4j2P3J7pyQKgNfTvuQDqMUXwp0LZ7fOgGEvEEYvFBYPTZFDnCR5afFzi49OsaLSnirOo/8moiDS2QSl5Uynr9ySI66JoKiNO6jUf4yNTXoxfKY2e6qf2kP3oSN6vhTVQ938bPNO2qZFpDy4aQOz31mC0n1qitt9TD0szsBq0R7wlxyskEUjovHJTy20OnR5v6yUh4zwzQGmsX3TFyjJRzZz1XDh6ItEnNaWjYOPAmMEtnhIQkhrW/2MUtRVPerZxLepAr0IfvHLDdxRKtgqREDrb/5Kz5es9WemvD+1qYLt4v2JCjgfGjbkBQUhOdTF3dH5FZSwFQ5cPlk2hop0rTt3Xem3jyog95IkZWKLjHK9uTE5lacpHUjiSYvDnFRAELM7rcLyuUop3b0bMZK2eV+02GUcaiesV1e0vyACCCXy6Gd4Zu/eujOoIjdqLuk71mvUUmdXLvTlBFfYPJqUGELX5UKcUNTPyAfsNnM7LcYq4aPPmSD7Jz92kE0M2pihyxUSctpEJPJYua/KcNy01Hqf6oyYRbqkC16t+GKTQu3OAzEjrJ3irMkYJ9Ildlj+RaZPXe6zCv7KoQcXoFCz69mftP2dP9O934SJ9/DmlL6rqsSa551fZHOFRX0kb/Y81bHVoUUtOqce4VJOmZ/KTrAf3rJkagYrMcVlOz/NUeZThxUXNPLAfKgXRx90x12S1dOWVKQDuz4AnHDHr7QiJJ2lTsihDwQ0xb6cKRg2404ScaT0reRPdJIf9K3ZTufZJR2hCFQBXrW4TQvrMw08eTMrMnuwnbIlseGlHnwz9gbdXCb0IrrVa6L95AbTJLK/KAe4YwDZ4vWT76XCGsIptVfAmtfHuQjTWV0yGwJyJ7PAz4ZBBuYxDFs8zKrSmL9Tl8sB9VdOm05ag1Roa2qDTw1WvyyGD3vCSTnIOHel8OnPvOyNx4uLxmlkDs7N8djUAl3grIC9C1ZoUDD6M0fI0A7MrD7ybdt13wYeA4w1Omw7USo5A9x9gAIMGeJGM6B/1dgVkAjFFhRwi+UBJOxTisM70TQkBhSCx0/NLzYiAVs9s5K98a0aQmOH4+ZT4+JjN4rlt0tKlcHkfhONoKIyCoDzdxoV+65VHlZvm6XK6NhJ2xO4nF6adP67skjwU+h05UYkYgVA+W3Z3pvhNlXH9JY3u1VgF4KQPAjStR/Bn9QVKHwMJtJsTP3wt3aN0JFSAEHpdPf6QbLZ5cjPjOUdfJy4QINpmZS5AiQMNFKbD9EP+ao4MsosQqoMSqcY3xDXLE5OCO08xD8dLkmDhcKmQUuaStDHM7e1OwlxeSUw/aNf/Uqy/VP9Q4u0oCkyik2yE2pR7e6jkyHcggWb4xSqKSd2Vw7+M4g/eh5hB8IrtsJKAM3iuXh6Jc8dbbFgCku/RHkryYn9SQ7Mi6ZvT1ZzpaMmK5COtZTJ6NFj+17P6rAZ/oF217dn6ZVyShvolWwJNrv9dtEDan476/mqTcd+JyrHYForcO73KpeYChvWrIDOYwgOxdZGqYgC1cS29nDRuvqNCD8XKlE6hxVqTfndfTt+x4PD4enKULRVHC/NrBr1FbNgybFafy6lwuztLoE3tLwY+67iG6Ix0cNx2lpIxOMhlTv5AXKtEEyOlwYH+3YqXsrvGDb+z0meI7xs/IVjykQLQNXY3DlqvMDJClvIbsvIL/W5/2OSnoH5oi7AqietYlmsXq+zrLx4YeTpTwzfd2Uw1MF2jMaHe1rAqxkf9Ngbn6UPn2HZvFBkPcpSt8NAYMHke3uQ93lYh8HO0hZE4wuBMW9K47FD3FjAZEbq2jSm/MRFq2zaFVQr7fpVUayW1Mvjy54VhmcV9ehxcUJIHa+zG2bzuMhlufBzjrjafFbUJQPnG8tCWqHX0gl1ic1lw1vNiZF6KMOt6sxijOrEN2Kwb0reiBH39Jr+TSp9M5qUlQ2tlbPURQ5SZRM2cpLLi1jOIB/EAIXWgx1BhxkWOJtjyF/WfI306vOrnhVr7mhSJLFAL4jyBzoaJ2OKe/d3N48N6wjEUNh/CZApnphYy5ymZS6OdKguAnGuuFrvaj05aawE23XxjH41xEPhGkgFFgabSlxGWZGSe0JhiGG6m1Fu4i9QYFZJGwN99KW9G2dQx+s2kn0WVg4KrsmER38Td695c3r+uPbU4Oo8qAPQ3WjJHO477vqV+CN/ym9T92k/Ss12JasKngqyPwwr572xvKjNvBdag1u1far2CagtX3DAFOVSpY17eY81JbtWsQdsu6LWqjlrLGehLssL0gqxz7Ba2XUSgsPjp9iZ5N/Pqp8kUuFsICuz/D8fRQpWm5t29kmnVonzbCOeU9re4+758mO66+ScocGf/ec7gfrteMaVmLi/63RJMnk9PM14FjmxqcnXuJ8PdlWF14g/u67JM5AVM7fiL6y78ouiNDExAmzwK5JE+SfHZyTOsfEpE85lTk9RWQxC/liY2F2F/yyGXUzocPCuKJ0vp5RTmhLfuIwuj1AlZ88Z3hXj12++jtYTwrr5lTWUIIc7XzbHRdJZnFIekWXlNSp8K3zIGQC1Ok15d+YN48rGrhSVXypVJ89IamfXQgfIGjgsSsLQD8ikXZsUvYcmSoS/29NjtDVh07b97nMGuFhIEbIW28BFoKSUiuYJEjHeoJU2A8fJLRedc52b0LnhDSdI92+wcKQA4+N46d35rLtIOlNC4Usn8kVKJj4wMvQPnLHN/fh1HEyqvcXiXzmX+bAdwvEBTDqcEj6Go/H5P+c38KF0gj9cg/FtXcjrs9LaK/Ts5ithRcHo3CSsWaymVXgfrxK4KoC3P7bOpk/raJxBTO5hyNb/1at61xZX7itzVA01zrxTFxAxluXk7D+0TOznCWmVNZeLa/9ph706moCnVKW/n5yz1PFc4/OAe0oVxOoxb5iNNPBzqlBoBW9w8qfc6d92KyPz/iJUpzmRGPpvg5hF/7A0zddiGxOlIRT8AxNJiW4lstGr9MGGonTUfbPiVAtj2NNTYaQRAYJqPPiKnLB1xj4T3+EupUygxrxF2XfbSwTUHHgaRYjom/XUVwmSM70Yhym225FTAzEgY1zoVLE3yBjFFCiiIGC9TU/IlYPvhL2TJoTobTNFOMu+oyUQ0Ns4k+bB6aZbIhgVXnPK2XQi0dKj9qNaIiOFAoZS3+vqtQejUQrCCOlTEBWzQuU+LfEpRpj0ETpRFc+qX8pUiwDykJ82owgjZDzwIjTy33FYIwAW4zr8Fh8Y86/K7WrIVeT2rxFPREKAoaemE6gXSI+h3eKxLUmI9mAhZOaHUdDHdwqcTY+ceEKuHrwe9k6+txJEQz1uJd70CB1weHo5vrvYUyrb4EwGdZSCNB3zMjZh+m8oRlikG1YcF+hPoFXjD1SKH+IsK1bmcyRKx1mQ5+BAkzzADJ2bf9qFN/JfEXn2hySG9HsKDQMZI4EYdlFVJAvDGANGgGQZMMh2cRHFQyKXGyZg37jAh73ORenhM1FxNTWQKCUGplZcsZNad/ZEX1JaLsyEWSrUObPw/Nr0EpTkeaDw2CtWdLRtrHHuDe8bdyRiyZ0b3q2fpiKRwL8LjpUYkjtV3RXT+LBmUY8imjpLZC14KggjFQ3wliRyBw/qm3ypb5P+YGbxOOCsvuBr5WBc8bLc/xYHa/elhuaoc5/2eY3/y8eqwlkjrVwA3j1+Nw5QqaplWUzr2T3Df0a3J6JQaTcwZYFgmqQIwNn0YLAIwpQ3pXtZ16yndkywhAglCg8IKCIg6616+AgdQwgQL9JfIKuGYigWrL/Jvfloafqn5Zmby0tLKXSdlB/jKkcP+8tS0/bdD5OeMUoUdHUi0KbPtE2YrMQp17xf2h8UpFA9AkWJRTuJTUxlVcpwbfzWUkOVqMzAODALVJGqAx/DRYFgcbtZnjdmamlpCkNxaSlA+a3yzjOzzbgV56PtVZ2wXg8b3bkAQPlLUzYck/Nj8FYQJYEvi7x1a1/KqaFnj6qkJ2xhfe4azGWWV2QBiVLgXj7lfIBklDCJ5gZxmUbGJ7dwJVZrSdLcIhCHnLOyLJZ4Ajp3zbskSYoBydaBmLLx6KNexvd6N072terv6fGj51EserAFbXmQV8k+H8ayikBvhSHRepSOmXqdSRFfnZlrm4jU61rXS4jOTUdIb51rryRFuIVLBKFJbOg4+gcAEFRR3lm1YWVoUDEFztm4MSdpeBEwpQQVT1Q7RlkNWEUliB44xoT33w/SB9knDbGOkj860urAao7km8GJ7bLgafDEuiWCCrx5/oR0ACjliduQKODAkiCBURlhjJhY9IlMNgNNdyG9JBJEmGRBAZGyYAJKWAqAb0B8XpEeBlPIz0aCZ5B//0UmPbMAcOZRYH7caHzK/UgnMv3vS70TQeELxFtAItigVq8XkFIHElVlcGcHVEaiAmXweOF3SbDm67EjcrA3h92MZxrHRYu/Te7EkL6TfUeatyuDVc4iSCU3x1i9nLvWTODbKgI8puIjGhHsPCXMZQvzasCbw3z4yi6LDBo1F7YbkKiNgkayXdarh2ZJkByP+MTaOjimn8CEXBtz44VchGSySAnhuY1dC8Gc+Nt/MjjY+sQieCAH3otczKqlF48io9DTzZjq0PCNImFmyplQ9RefT7no3tPfIoERMzYzbqtnC7dEIIlf6RJDb2bI883GRWdcogSCPL98ZzjySE4z6ITPVcJS00T8se9tY0R6B5ZowkgZLFSanR5JWpDlo8dEpA12GWp2A3i3a0gWbARnPvv6gkEfeNtsUBUc0SoSZ6QelOyk+e4NraRGWJaDxqPodFC7c2I1eWcNJpYgH0uuxteQdtQgckLsWIr3D13FrkOd7mmq3jXuR5sdMlT+JlvzuuNW5lSWS3OeNwR996I+6PiSwq54OCv5oUGxDvnjuP725F8i8gaH1FyLRqYw+ODp6yE/09NCw1MsXi+uTn8FtpC/kqXJD8EwtobIyRDtIxvmHJyVRB6PzQNTyNI1TB+cELNF4pqf7UCPYBJrCB4Z3vtI2HgpPRxX5Sqm18VEmZ8c4CJ9Y5pQoGu+6UbdaVcXv3ZhyM3hrjimKrzoyfcE9PCeemukTdd6oce/R/D0PTV1PeaRii3SOpfNE7Oy7jt7t8yaXhP+7xjp8P1eOavF2/n+Pw9ef72ursluf/aFwizLLWBWXWxUusvdvbaFLlHpsXVLW5qefbHbm+rqoFwUkODn1xfRd+eOI9KRmzsU8e5ITWurj3dUBZvz/fsPHi5pb38/x8fbZhvzTF7K+LSh90lWltY5Zs95SwuYFTPG9mbAW/akcRTIViBS1xD81psBNvv3aMOe7xe9XnrkROtLqPGj4JtXSmsHprvFfhAScfODWLJ+oPbylpDgjwLRS617ki6/vmh9aLHj0iUHNH1wPcN3+4bZ4Wh7YOB2pJ+9YbvvErmkIsmqCbMmLTosz6dQ7EFJpBeRlJ3iwSLERZ12LNNFEeJhsW56M4gKnabITglVJUIJkCEitWRDBERVrdqHRQlZc9kVWSRneVCpiniqUqSoKlJkrMYCWVERgnIKl1sVSMCwjySY8OoVE61CqpauK6oTHijwGPRWPUa/b8jJ5TuKETTyDD8bQUAZfW77Xb1rLd0+vRmcv0St8F7ouGKfh4hXqR/x6+4MW/I3Ffc+rAzYO7z86mclIZ6wMdNG8qigYIITcdTixbelNuPsnGN7NNhSptN3Ksoj69S7lqGzy5BtTk4dp0IgqCbeOEis5vEqOH05OR9/aQ9rf+zqRvw4IT7Wm5PTV8Hh8YjVB29UEwUCTkVdTh9/OcLq4kUBqQUol1ltQ4ah4uLAxGbNzXVMmOCYcclNcnMvXwY9XrXKIcVo79sj8rEog01NxGphWrQo7360D02dsabQq4d04a6aSn2i7y9y41ObPaKzpz86Cno63ms9mvnqsV1/Kw/04t4DhX93CU3VxRITfK0cubQF4SxdQ6nKdnrw4PerU44FzOgI7Dh2jvsUx55f6xBsOuj2NPr9wXGuf0Vy/KQvfIykzgg4ZpNz2EcUStM4un5FiduoxVWLatxENPEQ94nWz7R0LVgKZy7rpdC1AERJQAIh+McU4cn3xgOfXVm1uLLSfY7zh/HhoAs+lUsXV+2B48ISoWjg2Bcx+jp6e+3U2M18Wof2ww+1SXcsAFBeJY3fvA0FXetUEgg3jO1vwB54//72hv1jFoElTv3AfAc3ieZVmZXYRRvIA8QWiQ84MrneqAcWiQGi2GgDid1sErY9NkD0yIdsqZy9WyyXMv65KnRcHYI4AWwfP//N0qz+sU7xzih4JgO/WTFiy2KZlp9l0LMkn6z76J+h39kyLE58+nTCQmIfS0x2ujVkERFvET50y6kwhiixX9EKkWCukUjtpd7Kc8UASPMnymjJ79hi1adt1y6e/gspvu0Qkb9OL9b1t/dbbengk+bUBHSuJ9OeljxrSPI98k/yo6L4pUmMJK+KSPNKdKVRfH7USfjRSshW9lGOpSwZVuZ+61OoZ53spneflFWUT7fcnbsiK3VMYj1p4WJzt28mtFBYECiPnm/QXLw4E/LMioHvnG02h5oFxmQi86IsyPFdPBUo8BKi2GPQbSrP31jB+OlV+kGRcGn8MB22L1ckioDE4CkCr7drfMNTQhUeyQhESlwZkfBEkqrKqiTV7MpNAuOv/KhcLrnkFoidxnJng2x35H17Z/Hkcv/o0P771t2hd7jTu32enn13eYTRclwtTKWWbcHLsRzPxlKuaX6omsCnbIyolPnakczKNsbVOtU4HR4dgDzVf1u930t1m+pe6liIq5Fle3oYlwgmIIERr1/gXUI8nBWfLki36Zqnn+BP0kwpLmBp7fjapQFH8QLwIZiar47QVHTcPNXSwxWRKWdcHUwtAJk+cZmXYrpOojKAEX6al38BKPP9W11fX0nxxIt8tq80ULn5lL1UAVD4xwosOa/PyfhTOi+fo1G5X+URYDA0w9OgXdKLLzRoC/HKeUtm1pgx0WapaHN21oEoFnO222WCRC0p5nBhQQjJGNtwPqJdmCu0R6x+9kzNJ5x1X8/6sRuC7pYm1U5bHv1ZUX6x+UvfKtOkjDRrpGn6fyU0cYnzykOLx731+Kxz2nTTDM+zU9MT086MzoxHP45KmJ4QLPYfeLb4fqM19ohu3vIJR8aPquAlJnmuOyJ4lO9K8srh96Xfv9/q3XqstXWWic5KTZ1NRTRNrzcL0E2GD0qZdK/EYBWRyi+5vhzzkNrNOUMgNWV7bbYpo6tiKgqnLwfRxNPEFFAY0tzQ7wZEsrjyci5rb4xzKGXx0muzdplDids8ZefySwjLvEwQCYNY4VkI12l0YQSJ06cgKo2kGST5y7WYc9DxWpyZpy7U692OWbyZYsKsu2trr6jzNI8bcmzu3mCuUGCwgsVpK2ZxBy16aw/ovMwVg9Z81wYzRZzZme6t92M8R3Senjoge/XYsN2Q73sOTyaPWEBpUKhn8nDN9ngYumDYHhAKigwJs7CNQjwq6w6BUa4D4/QBSueNmBWf12m5WYnAl58ozc971pe++FQqkyolp04VmpJ2dnh7r92cJ8Sq/dRYYR5KQ3G+WR57b2mi7XvvHF0xB3K839smfvJszOa8l/Wn9SBgqTFRTV7wXiAr1f/HHvbjjnL9Djs8blSYRUPZod76CXPccdzBXwl4UzmjXP9Djv8r2W2J1eMO+VcsU0nKFf9Npo5SPf5LPN26R6gYCMPk1XzMhohkELosJHj6eBmR5r1ALAbGgTM9yZXzikcGxgaPFL3x+S0RGginTrhQU3en4zqvh435PVukdR0Ny0lHULoFDVVfvd9iL7nWIyGesQ3nQ89DcrqciICNhMxg/v0XY/CJhQGTzxrqb5OYzXegdwvAcjCrRvzGd+QXFRpJemQBkJUHD/ARzlluz1qqgOUnxR1qEG7G9U4HW8imDq87dRKn0ug1KtzUujMd5w+H48/TMHp/BCE8a9v1lmw9PbLziR9ZYLy/ebN+uYhgnZSYfG55b3O2Q8mpP0/I1B8/+8c6x8btDqsTAeEdAa/joH+D6Xt0g7/+gPMoFQ0GVIdQSvJQGn7yTVh/yjf3OF0jfXtdGgo1gOXZqZoD/6MKlIoIfnqw8TTxvbE/6nOubhyds1tSvIXm2/SPoZmwbwwv4sjcxip58EIGVtpCdv32Ah8hWpobOqapYJrvJsJP+W9eO4Ys+ulpFjQQMAoksjrUYEraf9DyoGCahp71NBsQy9qkbbNH2gDt7hZJWC2LPkNDMbspZxqa+Y9GrZ4+3gYM0o6ReWYDR44NmLVNG5Je4mSs+glT0gFYCvC8MP1lRDyljsYGsW6KmDklbdBcTzadJYd3BiwHpbFA29Rgb2AM2Oy3ssxPu0tEE0/xLntWd4aaqv63thIfGT/SbdU9wrz3r5gA/XhjYviDxOix18gPAfQAkBcmYTrogl59NmOu9q3P5Xt3CDYa917F/Nli4jr59UCNVcQv/GMsI0ohdm4quXvRQuNRTe2SnqJT+6otMvgZRjsfGNHdTKv56+Y/X78P4vy9gdtG8bzOkwAInjpQEfb01S/pn2gdaAVczxp4V2Q/eNBOPoDSUKFv11gWkyMtZmbO/cpfcnt4/3nUD8kjrJ+cVmP5WHUoXtGkrKZMWEXghQhN1Vg/rHqp8xB1uYcobVsjWJFBbj90iOsBY+INlDNcXN13Fn0L+lf9c4BWQNt+dtL4or8aHWwnFzcFbl6GB8jtvf9NT88gPWaDBsGwpLGtsZPXwIsUNwt6enqB771Pgd8u1N4TfxtYuyC+l2/8IZP6MYESuBQP5VnDouXo5XiYzVw+TjF2Z+ezbZb3Lh8KJuWxgbaU/3ESCVgqO88avNMzCvLZ1nl5bODNsALjYNT3jcSMupXnXXmA/HUxmAZNgB+M30Lv7sjvyps0g02DIi/BSqsAeYDi1CB7u/vtu+2KO001wH/vvYrQ9R9dl/a7l3kRcJvPYePqyUNv5G80r0vkJQV7wDTHiwN5iAMSwGDskNeQWETu1YZtC/N+vYXlb+TFu+QlcljxslXZoWQaeYHUfvet5723tSSOQ78Ds3n//TMUm7+Mkzhr3hAuEP5eQSu4Rn6L0oAA0gFwZBk3igEfSH1uZ0NhNQA19fQECw8Ei4TBB0TBRrzahKJ0EPBpw59PV0mdjp52Nq+PT2m/WpRHq3wD6eHzx46SCgiE2VYazuZwaDZ0IwRRH+7RkZg67I8rHAeFDGT7PVLXrN0BtFHgc2H4B/Zj5DTynn3VfEuff6c/gfmPf+v6tphd5X9Bnd6XjPqFLxR0eWHpA0p5vwosvLe2+lCYKGc1lIA/i7+qi/LvnF4KWpqeVlH6q7gJ3GncIO4HpP7wWQV0S/qzp95K4GQI7Ad3uz8NCljzW95+EYdO4wfx+/M6mKeRJ2+a/TuiSddwZ2VVnDHEi8ylJqfhL+xrjdBHT/0S8s+F/mOqf+DJbLQlwA+yO/ozJ9oVSq6qSoZ0UdY3T92O4bgkQ1VVULILJ+bnqZ+TcyFc3SWGc3uq9/a1z87OoHOcOs4Zlen8eQXWBUqpWutcIfOrU4/Zod/mFAoWSxGv1weIj1SMYubiFSRSfMUb9D9RjI+H3laK5mDT5poNVd0MyNj5o5gBSVJTJZBJ2I1LrU43AkNGPZpr3G/O6MdL283PT7dDE/S4L7gJQVzV0ZKfeyQZm2AIMoHMEQSNlXYvv7wT8s43/YMaadVpjYcMMLbSHcuvoKMYqF2tcRznp/YHazDwSmvpCDABgAFss18uTjFY4TbcH2YigVJTIQlDdOpIjyRd/k0FLtEVBnf3JVHamMzk94czYCihsZrU/2T21EpGVYFX58+CoDZr2snN+QUztJk84+rrENoWJFANVvi40cUStuOrPx1Y6zeachvoWyFIlFfa3YBRCMYYAAgC5g5JAvHWYzqHHK6s3A+WrcUsdvgDKwQxh0zs2B3STmOHLcYAwqM0CxoJE6x53N8E9c17BYwJ68IMdDHn5AHP57xtZuV2Sf7/17mtwPyPxtTmFyw4EscnO38C7zST40QL6kRhUW2M6j1Qgds5uWy0KB1PywfjqnadNv8AYCP5QCSiPqWmCySzGhsftJhYcgO4lnBpZ2ep0fByw6U5gkHihQXegrPsjewi7PFkccykhgEPphQUeq8lj6jpHjbC8k0/RTF48QEuI1ijx8kFg1Sk6nNqjO/pd4c7aYDN978FMMRFWfkYE+tmOoa0CGDqZvvmUOA3KiFxSSXYbG19HsTMRTY3YLNLSGyUTuELg+cT50XBigN3mRFQfgpWqhHR6VszKYAipACr1QZI3I6VqbNiJmZh9+ru0K3RtZurg5JmjP/KYX+u0CPuSC+8eL81sJENWVZAMC9ULoiCsuhGGtejoQBLiKKmf7D9SaFU3OAZfci1sEa3zcji/79W6FGaJRXVs1ThrG6kQGgnFFmojoaYIloHRXaikFW9A87bsqngTSqCtJvgvE4S/JVkyZRH2r3O4W87p5q61pjU2T0LYLPssemS4QJ2yfRxOc1kwZRq0vvd/tjwo2hK80VqI9BRTRdMqOXQTtMFMw01GRoC7mBoN0DBS6TwAwC24oj4EV9BxoD/C0gLwZOZxH8AztotbqbEr/EKVEG+ap20BsfTYCeRroK1Gy+dvUWBLAFFyBbGWNKmdCpFIkSpljQUQVomjBTVgJmn6UBcDEFSw2wgO50MOiJn3BSWGEjHPh+DujLw/18IRBRb8P1YN2Le2+IejRo2cywjDBYkbCXWOsrPwJIfdTw/zi7kbQan6yBSD1XuzTkHzv2uejGgykhh24kBU25zvywkZjiFdJXdvDJVzRd35QyYCcz6t9zebyq4qZQkRtM6JZTGoMF5uqEjAwEiFJ77GlSTFkZyQ+Pj00NHFkhqnMrZ9vTT1GBqT3MoC6dHiA8vUKzfn52BIBmzwlOoI+LY1j89npGRWkOuaV9ERExEvxnXfCA6AgRBc4T+Hx72EZfyrGzmc72vZ2ftTvAhiy2TwHAzBcZxJys6WRKxZIpwSaLFFSsTDnGn4L0TPFWCFneg3aJdJt5uXaFno2TgNuGVRr/BUTYzPNMozX6FEk8AIyvur0GE3uGevnkJHDXgNXGUzBuCNNeo5rR4vKVuWTags4zHt6SBMpZLSAEKZdfXZycNLQIPHhpUECMxz1hFiwgdkD4wBAuHvFg4akTmKjfD4cDI349bCO2hsJQMKSRj850RRPu1Jse+CyI9mYyUBOy2YE1iF3573hX83aVXefbOfhqG7wpsshSo0qEIe3NhzXfBkcOsK0+xJLLzbklAJGke+CDs+aVfoLTLOTCAwkCEBKWhuRg7A5ZCMXdPoSAZYBm51IIFVUIBlFz7pMiGGGs+NhFXHBq0YzHvR5R+pJzyZWHpPYXyfmnhyzv3ckBuiGochHxsRkOQJLOEQIXi6w/GaeR0SAhE8L3zLep2uJFh1t9X00qcrFAQYxiNFcfZryl34ia/bkQ+shlKrNyyKizOhJ5EyAL/E+Vge0D5Kv8OXeC28tXb/eVgEpiCSUmdR3aWoEYroi1qBLJt8MwMvI2IHEnE7HvyiLSDcYWmUlOQv9aEZtLv71f/z71eIQJgu9nU6WNhBP8o9R/3ZNvWFu77m/n8ptxePv3C/tlMpn3wrZyOVDp9vpZo+99Pqj122TZzNSzb/183aqxYWkGdkN2wviGbsD4ovWl902vmZjS5v1ZgQda28/IN2Kf10OnraH2Zg6Y0dxqftkBpX4vthqp51TY1vJrELGygpJ+EPe6lJaU1Wilg2RaXo6i/9ByNhyh6IC+7VWS9stR49PklRX1O8o2UXrzAx1u8uKhoeP48vktdfGHxHPQ8M6IthtcfsopspHmZ/HGbKlwas/26jWkInm7CGQm8uGU4rCCZlsi06/FQCA8ihM832JNxB2HC7zfc93cJMI+EecJHGMHO9OvEC287nW+yqepJFreKJZPXsNJ4WRb2qmlvEvAZWTjXheYkx1JWXYug8IylrRcKt++Ptj16PMd666HnZZpkpTsSZa3Tekl9rGe2J/PYH4/wZ2miZ3O3lQZybjXXBPgcXvjVgEM2ECXirh4SYa3CWsClAW/Ybs4178cZYg37jyH0QIdxhgNmNQVH6IebaMGX0HOY//7DnKP433+BM78FxGeBvz2c84hGutZv5zrHuO46fJpzSboLfl13nOO6nir/byDmOEb4HOYpECFmnFS4oKBcBAFFmMwIZ2V7sRPjYPIkra6rt477lOUji0zA6MXeE9dJB1M1qWt6Qu0knyV3ZVFsOaFjOJlocnT0f1XZoYJUSg+GOzWNH+YitFwq8hAk2uvnbJgcHQBsg77L6Qncqb6x2uNhlvIGv3l9LQtul6asbFmP4dYKu1jgw6nmzVYtw5CALYgnxXM9OA1NWnOBpr+g+M27I99tigfLQzbgiek36/9Py4Lifo3AXNvQxPHgKgWqtWWkH9+AGQhVlcNKtWY884F2rbZ9tJ7qgLZNq61NsiHRqg3atoF5IWrb3QFzrpm2rZU2Le7cBqRzW+ZFYc2J2t8f3j1wIay0t7VtwMnpBXnPsKctcOAakWZQDoCt557huamZ97e1bxl0q1GtbncBFwTqSP2jDzxaozCTb98eQSaRAgF9BE1PYtLibU60jdVeklrH9CCXryA7kZ7Ll3vWP4ZeuYz0yAQbFrVmAxzG15MDZh79mmz1zyyZS14+s0lPhq0C2Qozvhder1u41xXQx4V9PrBefV7Fap8HjwRBHN9upYDKyqCkFQsAZ17yOPjR5wyG8XMpgn9J8Dg+lujSPJl06EcxhSDJ3hS356Me9vTjFwHEGdGPmrkFs7PapRBo1zJEjiQcEV3oN+8vKi6vvDEeS+4fHtaag+xQDYRUDwopcWkLUt+JDRMZt1AeGWloGPHl8xKvsw1nwc9XYkcv6VX+ni8TTNbmE/2l/rKW5bvUW1DGhRUee6/xxGSaBQ0V2+29VyTg0Lzu60VM+TP22DxKR7N11MrGJYEeHrpLKu6wrAAo45r0xw/aKBO0eP5NEge3WZUwwdurl9AcyOmwlEkGZKMFBvx4QkuaS7Qg1ejK4pz83hAI6bEcv4IwT4EH+OO1Z5jAt0jOyyIQ3vitOjzTXKJavo4I/LzQNFhFLE7e7hBmrGNKkuEwu5N9GfwcTZd7dnr/SZlNIsyUGOscwrYXJ6uIbl9QGjprOiaF2wQOBfHaJTKt+UBiyERw4pimXyIrkrWdPdYrbZOEaXFaVfCEPnFYIcyk/ezRtuyaj4iqOkRuWgb9Zs+yrfEgOgg/ikto+qiMovqoUU/aFIqJ9tyfyaOjHj3Wv6vSx1pMyC4Thzl6MAf2AS2wzsbdDEkNDr0FveDqLurjgxgny7AdBYYIHFrkh9Tn1CNOtAXta9XDNPOafYVXW09KyrCUwcXDhyf2vd3DwyX70OkmhYyIcxZ53qN+pdQ4uxO1p2pOZLgWIcZp+bNWjgBBjIm6ndJpFcOeqKq3k/quWWyzbldQIUgW5EboulUScf02gdhNBXIz6QMBkFq0hFvvykZzu0NjfgROhQM6jQpnPicv+n+1RgOKNU/cpx88mgOZxAIEwDqdEKcqFz2XCHUlHbatUQjIHHQBKg8uoLSVs+gDXkpns0+SQcD93K32ZIr6wJM7E+kOJu5xhv8SXnYu4r0rWEMiF6EdBTaDF+wIZAvWoKBSCdgv2bhsQQK9pSqxjbHkz37PQHNwLwHZjc6Eojsn83+0rqt+ZShKQ0Xk56Bm+MkP4M8vILr2BOVYvHy94FQge3jhkNapr9b7mLi5VtDn5FkxUO1SaVxZ5ylpujE7TwGUXujAfC3SS6GiN4S3IH6TCKzKPlRNjQ1QKwKo1ZPlVairOvE0+byzQFL75/VE+Fb7SuPVzb43EMBwJNpXrTv4Vfh297UcjHqWIeyKezZsuT/zorCaGm10vq3lDr7o/OCMlDzWJMUP3NOKT+or8YzqGouLnbh9qiISiNfbStI+mZBbZfWdCbApjx+rBN2S7lqfnZKKv0exVyK3hbebd/kdUJ3bAWjHxuZtJ+xXsgn/OShBQI6a5K7XMhOaC5MhRgrUVPic0+ZFCoXlkiALAZuBVMjeIGg1Jtsb4wtaH1jSmvwqWdDIr7ZC8sL8GIgRC+UXQjGd3/tWfrk51wxv+P+/jXqUaqUOnzcrAIKAxFGXGOgv5LkIcbJyTvkGiE+ms+hkvoETyiFDqNDijpiP2c22DrqJzw3bWF4/ebHgrPcmI5S7D3dlKRvDRj3IbBRCg/EPqOUdvHXlyBwIxsk07PIqHJsu+PPykotQajbKPb7VirlZvSOcPuuSp6inKK3wL1v4DvU2ptXWvUOUzaQnlrTrLpaJ4YaFpG1oHtnlpicRBNDV0fcKlY9e02kxviN+x/b7vWzZz/m6RsDfGrwi+OKRM1RhKsSAziij36YE9dECOfSHj5SF9xLIAlRH6lL7EyLVreoovL+6i6RD4UgAzuiPu+QEbfCod4+WiN42MEPV/xlXXFhuncSiAfoAigHwQtgajQqnwak0dwvuSuSo5vQCcT1jXxiUY3dLwfd/iFA3LJuUdnL5kxTgeX96uUM8pY6GBsnIFNE5Z8FBCz3BGW8FHJkzSUsDz8wM9gbJN/uXlflrd4lo4pk1uGW94K7MbHVBfAlfJx1oRDGU53ab8pgaBji3YqiXqMAcR4U48YixV+zO+6vDfJS+d2iH7tFcf+Or0VyU0b6xfO81Q3vz3QnKYhaNfhwGEGuEnWs6EDQahcPTQyPrJP6B/jJLzrF2CFtIlOAF6iyMU70OMSr4vaIjTJHhmIiICGlkaWSkp4ZBEL5S2ohJko+WCnSQ5FOYECcH/ZMvv0KcoF554eb0mFVVA3iuWX9paV7JgDkHP1C1nrIi8vUtFAxlzvqt9QpK9XotnmOuzS8pKWXdIMuPqGJmg1LJPVU4tyIyKxQgJ8jVOYTK7gi2RgyrxqJlBlbi6MPpyads7GUJ+ka1OZWcnurTvdv6/ncRLB3Cnphc65dDST3ReiXlpJeDTGkvtd2Xkp6MJ2ATdoWc6O2vuzRi6hbonwuGs1HmA1+Kjp1c6ZNB3s1LUFqFdyVBSewsc75lKG27dz3ciVIaG8o91AOBuoT24xLHTF+4rKOjzFj7kR1wmaUUNGqnJiiETWMOkOKvlpUqlqDh0n9oORoUr0ub7rn7S2OX29F770kPrMaiAS8Pz5i2utroyynG0mG2CYIQbOCuuDpM2nLxzHa4E754jrDdRVJv2IaGmKFrnaUNeHjdyMi6pOFFIEa42zxclijSirvTPW8yfbDzITmIzi+UQzFQQT4UC3taXPmqzM3ZiQgXaLcUw0XQZi1ULAoq5iSyKhppKRqnX6KWFszcXZWrwQJArdjPA3tHXpifchQrbzuTSdgLzy0pMfGFIPRJA/zPzwgE+6cB+K1+saP0yUUOldWbZ2IsWg5ln5V6WPua7WgdbmwlUgbXOfSfZ7u/GePQ1BFtUgv0+3yy2gy3qiQNDZEqT4hDYEGVJN9yhteHG/sd1g1SiK2rqphmEACrc9lcFpdkTQokB3i7KOxclIaCvKJaFSS0U6zOlRCaNMNko6imSUJYnWuv4KugolqQh9IEemEEQRzQ5y3aFhkw//FE5HoLczStJpVguiB4hox+IVZ/FzRxroTCiEnAZZ17vm8MVkQVeUqrjsZp2GB1o+wTSa2zf/Aaa2uOjeT6xmAqd9BP6aisULazdOqyqIJ1mriqo1LPSnHYZmP3JXRw/VqCINik8PfEvwkJjI6WT+FwoY40uAQWBnfjDu+zAdw6mfNp3Rxu6zdlNo3dOnTt0FgT07R/qO0aQysseaWFHxdP3D0hM54du/NtKGhIOtx7RpvX187Fe2PyMyCge/Zp6P0Gy3MJsoW8tAJ6ZMTok9BuPRFQcp7WmaTyBIp/nYnu+ynYRD09nXg4Eq57PCli0mQ14eSm71P2ZVaxo0B5golkwn0xhaDmI966KRX360zmrvldPFlceqGAWRWBeBLg9Coa1AbXT+7vYphqSW23FCFpTRldH47B2cQ3Tl1q9Ls2eGoKbkOUQfm5xdZK2M8gIjxeE58+Az/4fqOLc4PyESXcNjUVfgXiNhDIERkQiI5fJvrN+ye+BJX07QuyzlaY3IyIpO+mieL9tIL2gdCMHOZrg4vakGGuQRnU0QmXwSJ3ucdTh2LUj+Cp0+g8CX7opXvq4R4HC0ntremkF5b3xLgo+jG0yUUe5CMT+EALyM4rV3aadegreRi89fhcOwoLg6kE1FmPEG5H/xWf0V0Hj47CuadudNR5vGfg/5shBAM63YbGEQOQYMiShm7pa50rtgnKOqeYZJlH3fndm+u2x9VjZi/mRR4nmZcs8jd2+QsKPTIPeRYXDWj0XlCGdxcIwBNr/c/8Op04gJAM0UYeRWNwoUXotYwzAZXqBtv4mG3ZarU+J/f1qQEvWC/UZr0vj6I2TmRk5UjzGpNnzVRnvdYCLGAX7jHINJuNYXJfy4HmYX15gaEel18u5Kh6wyQ+Uk/Wk2h6/fweNm9CgZGZRr0maUNySqTn46D6yE4+oUBAC5qIebc6/s4DOifad9R37/6I33fuU5tsnqvH5rhcmj1AVaTQuTLhprcpgXe6B3fiV79LSAq7J96f4K/etCalwFGvI9NelLEb5KU0j38a2Aj1zKQEZRXbmKlBaRa0eY1+/csAqJ+Y05rmPjmF6oVYLS20rGZ9W/qFZvYzNkpDVx1pniUOxDDtmuva1jpPm6jXXfAdl6Y7ke3IxdPErec3zhI2oTRyByEO7lGaJAH23N6/kxpH8/JwWgNjB1CwpiIPZuoBWF1ZCIutxqWBhBVofSQT5aFr0Y0opjqyriDBN87rhKrumT8S7b8BN25Qc98eVWnTZrP5hPeXcQBjXMH3cY7k/OLDa/ri8M6ItFSdrr39RNDJykr7Xsg6Z87JBO0lJSeass7du0eve5wdsV78yMENzVkBh9ycfX59erpGy3JOWlJW1r8bB9VLGhNj+dZgAMNo/e3Z4yu/nS8XFUERdvyxqslvPUU1gSmPn/xmWo2vzw2JibN8Y5EXLIAFxdedV53w2yDLc4Njxn3002NtQE1N4La+16aP/z+vvDGJ8TWjRlVHHDGZvQYTwoMys054gdeJPHNz0J6MjCCN7l2vXOfHSz082lLyVMOkoCo1cSIvb0/QHkiqKFXUE8+dMOedbDyj+g2Ym4MrFEhFEc0Vz5+LIVZWrkFj9c1enFdznvnTZuakxSRnbh2YXn1d0/JPxMymqrpVzrS4mFtQ5KjyOfMxc0NodUD1b08ez64OXHrKb711tbMDYygqksuH1wlBPybVBNQ4/fTTR2HR6SFUHr0BZnPEgwh+TsZBKwDDjIu2L3zXxJKFPOmdmDHpGV0rxEIAmqmBZsHkzNu4VZhh3VSN6mB2tDwft9swrJNXnoffjQ3fDeoI+hbCwqHmY0+fUACJY8amZKJO5KoIoQhiAwdH+kt0e3nmH4N3VaS2dGL5nLxzhJWdQmymYUFONbqDOHyskMxBd5NhCu/+J7a7SfBCJhfC0BEugJG4ikzSnbL9pV04Dw5bofSNCe9YupJetL41/afdN4ZKa9bXRC9cUfTGJQaUR0E5uVAkFJWTEwX5JPplVf6cd8smRaTz68yBMhqZk1tqOavs474sfnw/ZgmwXv/+Ppt+/roDvwQMdvlH5Y9hoZt+wnQiOZEZa1smk4IWOQ6Pnjs+l2u1ZN1AXPYuOTSQDszabkJObKkEkZlwzjbM29aw0B+U17HLj545Pf+Zc0PDz+1BaV9G+sNCPRB4Gxw3kgC12P334QCWOGCtxS7329ApW3ccXVGXmwCUmERl0BUu8nsXnluNqKcoHkHSlBQpZISBndP8+1ffOdJe2HRdgTPEZ2KG/4XBWchMyt1q8FPRyPxD955i+DaFK43MaTJNaHZrtNqANQgPEyrCwoywW60EbbGVbLo8513KW8MbN8f+tNvonPU145NBV5EryMlgo4eAMbPnKQj+JETfj/Y/ZCjuTSpHEpXTbBrf7N5ovdUeEx4mig8LwzhssfZok1fS6HEr3qX+EwsqsT8dNpoB14xOBV+xaazxQwrj3J7FPdYvBqxhXYUF15tLMF1sRrBI86KHCfOUyS6HXd/67d5r1wWRqC3Zjbr+HCvRr8gjFjLywJrIsHngx3XG3cJp8Eh2Y0M2TM+CV+NwNl6Du4mn4vxP6pSdJ/2T7KDYwoIYiK60wkIoBq9hvl0j2wDxeEsG4SzjLCFj514ivaYPUEeQuHfncVvL8e42sNwasZ+nEQJwled9D0YxIIrkpNx1i8Z7+p0LKsT29xo14OHdsM273qO9VEji4LW7LMLiwI4PH1awsc0sssngacviO6ZqKNm9ZfhA7xeu9FopbAUB+j0j3yu1HPTItphM+8z7vFxyT3H8oH2YP5+V++7FByvVkeP5ZLisflAJw2NfDyJ37yKDTm3wfFxoabK7w0uZ/8aM072mhuUCNXdTsP2aUGTw7l3n/8trNGwFNZDLMBYLZ/D8HgGOrcE5M6Bao/tbjo5chklgAPT1tHcuOPwFztLayQjGjbB+Q2qMaPNxqEikD5BFbNCYZ1S4Fo//FbtaxXnq0QikyNDdO4NJI6sqPGRqzwoZ/c2SzoQ1ExMaNAmPTyAaCr/8HUyyHuFSjmyNzbDPutd1Pa2WuoRd9jJ/0WTCu29IvPRrZwoNH4f3l5nXwHkKOxY7MWIdlQsBJQwlaOffWP5ZTlGzaRzG0UMR6lIocSRYwS4FAhj0Z5QH8bHNEpt0m4adzHyLDPqusFgmayY6qhBsLawb+W9dQRIPZWyoz8TgtVpd/eTlky2vIk5VhRfeZrH6LN6yaFRSPdAaiGzjNoI4239sadzJyA8ZsDuB0y/sPhDCzG/aCax/a+F2ZcTOOyBqMcY61CLunZunwLbPX/hi2c3av39LAt+leghSwxgX+dyTuHvfkhkMg8OP7TkXIQPTr+ouSp347L/PnxwJwxuwWH8PS9+9t2d/c/qI48J4UPRVTeHBSZ5fbl6PH5b+/H8wvOdgrs4AmX/8hONb4OVyy0LND2GYbzCQfsjkvfqPisfYshyfnBOYGaMvRreMnFY/JH0weU8q/XuTDySfMoqmvZ+k6ICfeNvHcqF8dF9MvhBBH0pZMM6cqKqEmuDDnfDqEGFBn1V6qdclRxZlfjuAC7rbvBJpUq6UN8WduhxNBw3YeHG9Nv4GZ/ZuKIHKoe4NUCYJfI8uh0we5ie6Gkc/DUxJTSVxTLkkusDUo49EM6WT6GJTEQhco+nY/2Kj88efibV+D5GgVZnGkR4yvWT488myWHmFfNN9oSmmQ6KXeRhHxq4MRnLDpk7YRnzfZXx0hNRiXygQXCrPyMj3b7Obm4sn/rK40Xn/886aquvXq96LaDMg2MiPHomNNY80z3+36aI75bEEgx2vc7Jc/cO2yWOABisfCYyb/ddxy7BVgsV3dKGSdzjgPu9+ChSrUxXc490LmjDLdYtvcU+z/ECdJchjg+5TUdTdd1U+prNc+m8qe60tCOT8TxQS4hkJQPMdPCeAV5+GV6rPsBN3Y4br8cATxODUjOZOkhgDbxdZaNV1wiktxbZsjyz3p0BjOWhk9PL+oTSbPII1s16k8KDSnY/VFR8kpsibvwHVFxr3pd2YRITOF8s1DRzXbXCE4LGRowjM5ULVLHaM4QFa9QBg/P9XUvxZ+9wKvNKOI8Od4idLrSHFv9BoF9HuY1uJAP93tt99ODEkZFAF9VTVxFOyt5SWfJ4qdY48GjmR+2BPUdTqiiHt6SUHlkUgM4fIZrt2ui9gr8JEVvCzlk0h6bZu5YxkauJp0fzc5XCXCLMfY6y8m+0+MfRMsmDflUcEJu8DJ14k3D0fwHnMJY3pHJ3mj3R8/tz4qdTYXe3pa2JwP9LsmIUSU10cKgmj9rwauzgS/25zb+GbsEhVsRDc5qnM/22HbQZ/UM5XGqwJzcU2AW/+ScQi/MPY+9GmhsXF+lydWDIWqOL/4V04l+mv6Ypkd48m23mUZ7I3NcUpMPGG6jz5Dx9LTcPtaDLe+hSLMG+RhAseSu4aGXubr9hsJkFW0d2HCHnO9yha+IaOo+nJUhxsG/o6PyKzT2uocpQ7ZAMNdKHDsfJeUax7zrxARTwiVGAgSlWJgQikqTCi3YKkOO5SenTVmTRk7IeDpJU24auVBU2/qLHgkpn6V5NFk1/dHin39kiQj1vW2NcYPHZ7bFAToTVgr1l2y3xa+I2NxO6Et63093W/p8/7hN0dt0Gcj75EYc2KwU/QxmlnadPf4qZVoKsXs9XQ5F9dIZ8X4Haidj4g8oAyD6wF51b7ZqZoCDFQeUoi6xMrPAE5+u6XSeyEUyKQuXFjY9cDYVKSEJAosHOaTd7bXjs/aHblOTLib1G4+6BTX6FYCKyIL+4h7GY49jUbMXRT/nUXv6r0Ez59g3z9TI5vacn4D4tlm3n8ihXA6ZkNlLC2WgU6xBkcX+gdnMUqmWnd4hxurqwhKYhF63eGMwoiCX39345+/O3+z+aR+aVy8xRaNZw8A978RSZT5SlPaOQY8U3G9LnhlLnaSEUZFAOtjsOnGJaXVMXRDlxOJXb24iGEU73lfoJPT/GJljVGi1tDzNaUOkVZ7oAieDvdpVbmLiBpLAnHgBISawMUNUK/LqGBt8vjzJ8zoa+Co7y/e3CkatXFTxvLfNNqWny60F3U7YGVFceM/LEiyStGW/QgVaNdRCCDyw6xAsc1rV1iJsfRIupX1VUCxfdKr3Iz0xh4NEcJlDe5g08HZFr22Ti//Sp8jW57wJX+lMOsTF74Xzd93ho6SOce9Cd8w12UvjpTFbXTWJ3DU+6byGUKVKa343hHQZz108TQB66OGQcEENO6bVPB+kjmNiB4ujGEmSi4GO0G38rFENV5C36+d1zkGiWGCL0L0RLjnNaIObgHwAonlAVjol1gLtuVtSbForQQSukzVYvVDn0p0BHOV9Bca4RxDlriUwgIv9nvZX9BvkKW2VdkqyiNDfHEToV0TZfYJipZBeIzV2lWydL4yxchIxzG+fXlFKSBfgJT4OoaxMbIi8yzlHZsw9aOyW59G5EWntr2y92sUtIky481SSLd0utvPVrI+nhm3VBgg9iIcIUiIhxrEBHunS7fFO4s7Dgs7pSvw1l4Nd75AYw3jiDj2hHes++havGhUv9Qj4RpCR6hh0ADUDUsigIV7DwGsBSvnM+RqAWCxbX43V1eZPzIUgx4dSyPsmmfyxXRF8bXPkV0iKE28SV9k+TI2kkdvygLvX0M/6K1+XhHUu4HJ0x3mDDKRx9t0EUsWUgW+qbQ8HL/QK80I2p50MOHt5ZHvr9DdSWdCoAkrYLOYeGWwGWVl08rYGtASenMXvEDchcR3aX+gICJMpYRZoaf1GX9z8iyRsQlzFD4I1pOL55K+v9J1JNJF6knOOEX6H/fnrvY11X0O64/MgmP0T5fk94EmSyLabEbHOd2FY9UYNS4gS9x+T0prla+37Fpl/g3nwOi6YhB3Mu9fl3bpooRw6dq294BYAoWVYjwN8f+/GbEao127fz626rjdg69nRkSu8zyxrFjK509h06fdjQ1reEwcWt14tLE/AMHHCWhc/HOL90XRce8CiLFKg9p94bmJZe97FSNnArM/yn8DDlVf3TMSx5KM85vrkHYe7EoMua+du7f28v1sha8nvKJm6b+wMFVHImK19TnNtwh9SAwN7sYoptzH+3iU+YJOFVT0xuWgSFP55WtrUF9XSC5B4i/oX04bflzy4dTO6cEbDMyLdYy842lJ9I1MHZMb+0sMJnekO75hPVDq0iqz5zwO7sp0BaD9mF0ck5STdlEsw4QTBQLeJd6RTDxuCHvAu7NBlk+oDAEgCSWRn3ZF2UvcKP/1IIwomi3IGCYWIwJ12R6vO8Po0s+eDzzsRGnulNgdfepqV+Zfnn0lu2tTY9+Ff402H2qOvDIpN5Vxvfa9r6vL7hVcFvRte/7npSnXLdv9jIpDbB2clfg6kncz/aWkfNu8UUvFhba+kHuYY8znmQ8gvTHD+a2N+FmcZv4nW15gWtXBc2bs92QYPhI+Ln6jg5eLSMTpkYtCvzLruLiRqD97O0GiD/kE3mZh6SAn+KSmVlhiTb/MW35lVKDB8WzQyKbI5u0iJ6H9a73L2tHlrRT2ssjS5dVYAJAYF0OqRIH3235fpczCGtDb4SlgVkL3X7w1dK2wLyxaZpcXWjF9umlGzO0W2dDvzTg8PJ0DLCB7dLHOUmRg0k9SWtL3lwxXLG5z6YxThzKds9ZIVSExOR/dXkqMAkB2smaAKdE+hI+/GnmTz9yQWHA0xmwlhmxkWlBZBg/tNn4LgY1hwKRCSgSWXrfBRRqZKI4i7SDjsKBT+nS14cQSNLnYt5NBP5ca/Pxds3mNhpi72WVz8X7rH74XZQ4lOOeYxJMHikb0tpSJNOwSeqYV962u14l17l4et39xw8S2pXAtfL+DdxCOFoWm7fYs2E/VzX6FFzJCUw/4tDq+qSN1H1EUflSQLQ2LAwgX19A6XbAu04uRP2LKq/FGFUVvW+rvcdPrLy6vM5DamqzsXaen/hqzCX/v3uSbWLFtRjjtYW/th6wveYft3394Q0MOmdvZquZM84xwUOoocQyc9PWdN4gus8p9Pu1Jf474l1CnL+2lsV4X2DkhXo68d2yfdb352Uro0eWHmJG4bLlCm8SFKM5Sws7bEi65fIF89aKn6ar9mAtp/Ux4ZA6G0TA9fqx9UFCViNQlM9vf4fx2s00F0axPHuZg+ISsLw8IQVG8TJxT3FET4uYVDjmDkE6H85uW1+kdeU2rPZHPNdDdO8Sms+pCqMk4qO8xH1lrY+hQSk7KFBgIv5UBFHEMk6RTg2famXZHCkUqBFuj1Bk9NHqvcCowJ7WIqAn2T+5x/624EmRi51Bl4uoJYoHb3XT9RRhvyEjrVzMCt/9p11WQ8OFzgbngVXjsTh+padzRPmfb709GNEc0fftt4O+g+dnt1i05x5+dOGk6/t33U7B+Y8+c9424mJ8ii0OEIgScpFSwxSkd48cGYo4GTHU1dX7DN2+1RexZxAStQC5P2/UUsx23rdJL+tD5vVABaqc1gHT+hipvVjmhiAwagWoNfF88BLyRBUtS1meEnnlYGyVeNrrjU81L4Tm71j4ysixeO/Zmm3tXVtdbq4RisQJqz0RPskIJYAJ72T/9hM4M2DJd7giS9xjAWioKZyfb8lfGwCP4OTLmbRkCoK+KdKqF7Cgt0Y26QUhNLtwPfC1cjKWOSvEdxKRdyEsm37WhoSRfa7xUpz0Yxwk9hhEJGoqWmZ+YlukP4m/OXXI0Ldls6NoNWzW7VvEPRGnCbwZ+iKAKhRsumbksEb2pyEVEMghUESSw3r0hG2PVEFoqUl6UmPp1JSw12r9+D5VZDZSWaB46C65hLNn/KS1U7sgU732lMB4AbHnnUpAqdBAUS+1vMENuebk1NVFkWtaGKh9z1FS7PRgaiUlg8X8tYMlJXftGUMsIPGXF3+eqYZn4zLFCw0LoK9+JL2KHzuoSG+MS4WvXpszZ86dWFBA1i9Qb755MmhjDkZMKPSGvYyGx4DEYBxYXHQ4QgYICYAwM1GTL2VzIes8FilZNflipXPR5JdK2cLAlxxWa7gJLMPVUcabhuzsQdtYOR3TdjBGTIyjWjjTgB3zskdSdQfwixJgDAPInzPQfksYqIKvteC5V/ERkl0p5gH+b5RhLENKOUhubPeav2lxPmxhhbE6bDXNm11lFrLWXjdNW2PU7Sf3e1m69IesddosN9ywAsGme07TnCpOS7VUFxff9/N2gmqYV1GRnb3/ZvFQzEE0hCW6Q25BxuUchoZkEPJJbS60kyCXPQMUWm7c0VbZ8ZxFsSR+D6ant3nu5jVRFMrBSb+uwjBKzciA5G6CjzxoPYiJCvexMyqLag6BB3ipFZ/Btki9HWjxU3r8X51nnJdxQUJBcGgXk4MLBKASJVRM47uvOVDRG0BRmnldBmQjqXASZg5JLfcmZribFs43cdtFNPEQd2rqrMzwgWfZ5TB7nlX4h/8Z8ZYHwgJGvMLICIGinEYMaEN6creK9VY90SNaZzy8FvaV0938ts63dpfdMt8VelJp7Tw5oUaXapI/ChqpiW6NZssWJYb1iIUkbNmqobeHFhj6ppmm/JWUWrwOR7r/lZKT3w1lkyjiZT51n4zDvPBZ6dR6DtpghJ3RSiefF2D5nukI6j4ZYhXicpgyZ9ZsR022KDXY5Qg4JOtXpmZzwP2oC8qUyYTCoJn7zoSBRCeP7v6loC0O/7FpxvnHvs6WNRZDvY0umTQVssQn219gEeg3TU3bbCaQZd6X06fdnlWrGp0044njYBzYILkMiwYoAkhiU//Fr87E1ExChTHhc2V1DBohrG/8zACHdtrcGBuJiTLFBEsrjIt8LEwT0qCkigrgBzvbbuQ7LPIOuMFOuKZ6K5w/HbHr+TRvZnBw5hdRoOhc5djRYy/lU5fJWJ9Cm5H+KvtMt227xW1eg0GFQpsokAqtbz2/0snud0wcl9ux5mBBXFwAC/lkHf91YoqLMeBX+RmMA/HMnGTU8QWjPbQr3smWGCz3+fvLmtaQa5NKS+Lxk6CaAprSPsxhML4xOQmElpLFKDRS1dWF6VVQGT0huMniXnOaOa/jXMNIlyoI8FgnVWJiI6bPqdIZwspNgeT74Kjbrro6sGud21Eqgy6a6bl9rkfIyMx6XzxXf/8h2bkyudIiuWP7codLnO+MttlldJmz4SnK44hr4hQ84N101/WoNYMhqsw0km01XbkqExwNYmxhNm+or2idGnsw5Bz+4TGcpOXwhcC+vvxk8zm5Qus9fFsu5Zjbb5GWWVnh9P/iGTwI7XZJVVnMUyi3EqIO0NbVnSEABPDH2TQ4BVv/FtT4cnrm1gujSpY6HIOJaFsR32ZkHPytMB1RYdkGZGt8sa9VD4pyqrJiei9Nd3J+Mcqhqi8Rctyls3MQeElv01OQ6dvslYg/Dq06717mfn7V2ZqQ8ZBg+mOFR3juwzxz6cQDByaWms0Pb4/2XG783jfbonHy97da7bkyhTlncy8ULYOGQgqUXrqj3SsyZqaBwjDSgnE/ardTTCXwBWnjFlHymcJSgNWXCKU1zGJ8si3V0RLjOCBKuNxsCOg9wjAhcYxKCNJe/fNQKB+aR6xqfa7sudaGnsA3EGmDHz7OzTl37vy5nJySEvCLbOG8RTEfeizsycqa1gNMccDnil0zziGKwHZbu+PWbe/gbsMMFDZ04ngTRfCgU4cYAw/fvlu3KTrYpkdhCOB9MueAIVvvjOpn2VUGPfgVhfguYLY8/AEg2lQBRoRtTZjboulnH2/vr2vjuvaPrSsOzmssLYCVmoMLrdGi6+2aWhob0dzM8zBZ19dzNEmE45ovLk5oqgqPXP7qtjpu9mr+zslThBTBfoHaq30PpXoEeJ7wAjySJNmo8dqL8M1y8+qQsx+PAondkiBggUiy0kntVIEpmpsSx0eA6fVHJ4JKJ2fy6fKPWc2dIeBFCv/ZUQKA7cy8aaDMRY1Rqgg8XQJJryi8kgemuALBY/tzE75/KKDK7ac/f+L45JMvAzD293coDeMfPmlx7NylPSA/YAx+vAhHk3pOniDk5Kk7q/iU9dzLxFCzJHxi0xcXgVcEGXgA7msCgBDcqPtM8+68urjXW3Rpb6fIRyFe8+2XzSnEe6fMR3zdAO8fQ+oR9sDIpBu+CUxyd3mrfOInAgAIIMh7Vuy2dDARLv8V6Cz00LaL5SuEfz0NcvYQ9rfLxcaoC0KT5ns/GKc+B7PLibnufnKVPKh5I5wHV114uq/7wYNB7A3BVXBe80b2Ti+vXa3Hb0CpQJQQL4TYCT4sBSt9bCF09wARlPr7YrCM3jxvHgRvgkO5eXto4tYXCHfuFEasMijaeDJWTAQkECG+C4PE+O73fgLs1fMLGL3V5rgiTVlHR1lcHihVQRW8jO3sPANSk0x0eHs5bmffvtXV5Xj8hLHZnO7JE2M4UEYRhV+4dJiMKQZR0jbj3IVnEIhJGnBT0tNK9vFvA4hof2veGY9047vVub87F2fW5Ji/i9wUs+n1FpBEJCMQRcp0yAeASt7ZKUiM562P8uHX/+CWxWvqnz9dH63K6dMatfP087mKsTTCLIeryhNFtXAr10LAeZvkL/YhWlqxAhqyhwANShNAGurudjwJEnacBXEG41DkeZ1MTRE1TlZlKU6FRA4JZEBGdLXPA49CKJYA8KfeQHxnDSu0cWVg5ecD/MoaoRZIN1gL2WvjfNNWL0yeKAlNzfYoELwBBZ67SmhKGPstHO4Xl+yS6fadGkxy9VekLMP4pAMKabJRphekbm/Kh0iUOaQmTNOnCZC8vFgJgYAGyd0Za17Oh3NNEu2Wgzw2f2nqCn/8NGMa7+YUV3deiFtxQfMDZ1sT92haMkK1jHKk3XSvEDIjw8rL43xgEMsYSwRZd+irjXA66E23k2+U4AkxPPvVBn84WClSYm85p44XFYEe5PI0sg0TGbZmzdgAk+cWbQX7OuTk3xbZpIdje0PKRZB4mcpEdgwgUZGAAgET7Eb297s73DEAZg0cj6GkdnH6du1bW1KyO33xdml3yWnRTRzig62bhFFPMJlAfnZeHVowdnhZo0bQ0gE2w+xARXZjeA6m9PJfhh076ihe8OCBAxjfFBWAx9C1lEc1DK9EgLNF2hTYwaA1hMAEa9b/p321bgfekcS5MTTrnVpSlSsMPGeM9c+1LcyHql/MEqwaY6LmOxn2KNc2KkISkakMSssO9kK6mZESspm/ugp6Tzofe4t/QPqtTbzXCp9VXHot/dKldHMhM/GGujUGHkwc2OIWXZ26DoL0GNbhlQ9Gi2li0PyAeYF9s2ILpqR5Oerr9d44we8q5Ni1OihmOaII3pKv+BkczJpTIU4kKhZ+9kW8/DMsPee0TkbosgfFb5RPcic2cgbS819QJcfPqK3vm55SftE7O/o19OaqFx2MjRtGeH19bmVkfGUs4XbUayqzNWtanl+h24/3nwjp6XZAohYizIopadz+aqf6jBUv/JYmWqznNMOpfn91WmFkd61S2qeiOTZpCiGtgsnJQqHEoNPIGp1B0wwCCApDekIYDRdhWgEJjU3ZIpzLuQsLDU5wgdP2NCx3nDA8qNHZ5J5z1wsmsXqvZbzfwsxZp2z3FrlGFZUFlyVxBu5tOpk567cbf/z8Mc4F1kRPbkVAkTDK/SaxxHK35BOXiLXoLK+tWTPTtRy7pq7Jcs2eFCloCri34dCbR+Ef5wVKcAsTvsj+r4Efpx82DEbgwcyYnGvsIPVeRoSVQIUUkzV0goUrKbSi2rMJXxDYKQ3LpTIwV3PPOBF4FNFyX7SzMFz27h05mzFyn0ljZBodmW6YrRHzh8LRuJXYij3i9mEdLSf3WPKs2zKJKFfIOYbCWiHKal7wnB6ZB6jCNEbiUlqrJbCtkId1cseSukawJw0+RpawxdvN7zU8uVxrzf1aTcHg83lIl8mlwUuQRFQvbk/bk+99dGPsb9hLyqVCt6YLRIOolgwnU2+rQcx9NJd1QcyzaRfF0rDPlt2ezUYJp9kAnjX0S4EV0lfjGWEnkySV5rqbZs7a4AA46/tsBm3sxK0DFSkN6/dVs8IAbMVLvQLlfvlmZcKOnjJTAytxa9twwxWlpASed7O2d6aQAZwVYBXyWUrQxj7vs+j4Mzx/Xb3qmeaKUktoM5f+3zRNt58nvTlr8fShUW1NSKRy29I2S8ntlw1Y8J3on7kyYoPGabasp9VZW8XZI306yukBkTa1G1oVtJumXwMROSMt8HhP/JI/t6WW9oDSsIXtfTEV8d2EveZMNjdGawfM94IatMLbVorCyFIFnAZ5oyW7I3l2OYzsTfEkbXkBQxMzKQY5WkzIlCx7e0TPp9ntkaiRktQQDUh84MIony97UzjmD9CWv2hXgVUo9GKFz3K5T7WyVGn1VyShNw5Zoewt8/hy7jCzgI7OB1jd7ZHZvI4Vq5XJD5vFHlvD4Ke57jNj8+kTBLnZY3jTe6aTpNLoZbA/L9jJmcdv2gXr7qt/KO+K6RRxmZE8O56Bm1/s6hRUOAN5nSxuS8jWmbYFcjQPkmmnrdmr/22VX1tW/zTfcqMkfB7LJQhba4iPnUW5u8Ub2KJjw1KClEGELVyoRnftaSkMnCvI7paAlHYDbfHMYhcEcZoKjxEm3sKyNWCUZvBibSUPGv3ecJo1trxAYLcWa8yzNZFzLQELb9i7q5ERpVxwTF9UjkYnD2tqrVJMFjGNHAl6WHqIfzQNRXoGvT+k3bTIsMUYk5HmS8fqtMRPjsVN0rNOvgZZ4kGw1Pu1BK0FrK9brGddRcB5JJM1hbOOEe/BsNfTDEYxlsgXcpvpp3OHkxmu43dwd7syU2e5O5pJfmB6qwbwwbsTSQJI9Igc6+aviqZqb4gW0QipYUTQGOqfvuE7fcNBy+N2CTPb+aEF0+icLTI6B++1SrCa/bXD75On3Y6ek7mS2IpcSAuQjjwhrLxpXF3KG62zRD1rBM4p9eIJaSy18uEeRBLD0hBvPcsppMkztALhnNddhRjd8pQkw6/LIgVAOD6I6dQFzQKXAMD3Ym6Zzlc+M7oNMgJi8pdsP7sS9B92TaUAb/7+T2i8/03MjO0PX3yN/ENTIPDGMwEAAiheS4BfM79/8H5s5GYx+sRFRsrL2SuS1V5VWNut9brXlW57Q+G+t3Awc++l0Y5hqQ7YO3zZS5PLvaLx2asmT3Zr/drrFuHeMGW5t/D5yhEa1BUCChACpximHfIxOuti+GaO69Al34p8UloqaCUrfWN+SS2PHg6FEuTgM3VSVTXsSUdfHDijhSepZ0a1jiAZZ0LfzsvltCtuojaxRbebjS9RBDgSBZO/8HEzNHTMOkutoRrUIrslntUnkiwqsMcljltXftHGbm/poQsOtvZM9me2M+ZtWi1zlRw5x4J/uBqa4KmxflIdfyDoSmcEua1ZICJOdt5UzMpuO823SzYMjO+uA/J3kGJKKaeSamqp/2eT1Fba/lT9kHSm7NzA+hfyJ+SM40yaM65D/m188i/jL7z8s/j/8L+/P+N/wb5/fv/+dWGYNrvD6XJ7vD5/IBgKR6KxeOL/uvItM53J5vKFYqlcqdbqjaa0Wu1Ot9cfDEfjyXQ2XyxX6812t1dkwP9PJ8mKqumGadmO6/kAIkwo40Iq07Id1/ODMIqTNMuLsqqbttP9ME7zsm77cV73g6AAwwmSohmW4wVRkhVV0w3Tsh3X84MwipM0y4uyqpu264dxmpfX+/P9/ddtP87rfgAQgpEoNAaLwxOIJDKFSqMzmCw2h8vjC4QisUQqkyuUKrVGq9MbjCazxWqzO5wut8fr8we3vrBM4VzqnpJHB2H2QbDe5/dZVqmQchxnLeMNF37AtnGuRka71/qQcXCphC7dSgiZkzhXBKSi/iIjJUHgv9nP2Kmfj7AgSOmywjSvEZcyiGWHbYl2gfcp60iqJH89ToyQ9VYeIlRaZzbqo6wEZ2GOW5WoNoWyEgwWDhf4wTVCOpd3MJUMyTHMqwpgjurr2XubnRukpc6H9tv4WzKFB+g9sTDNSvMlkBbJ7AAInIH6rBl2eXlxkwdpjF8DMDXV0lR2xePj8vUryyIgvUBBkCGjLl7Hd6TviVz+J02GjSBvtN5nsAJwFOykIXIDzMNPxn5DBYmxDAmabBv2svowDfh8tXNQflxKydAOeUHpV9bGrCUm28sUZh/WBMGO0rtov5ia9d1AufqnN4HKkqdqzKRdWour3uUcwTiglj4m46iivsMXCGOhgG8Mxyh17ylBdcQkC72WSb0bK3m6IBM4d1tQF0zGejfoUh0AjLpoZlQimVT4uMXH95qTxoIFUYlU6AlORX9FTokfhPEEUxgLFW8ZINIe5dz7zhSiQeBh7Stj1ZihYUuWNYgerJ1xkA0vxnr/ysPcVyWqcLzKSOVyJvIQs0KrC2Dvd2gFRt3EgQCYpnVYsnRKU6w1qheq9Vjo5Tyca73TSM0PgllomLME4PscHQqH5mXWy46jHVP/S6+RayntjSNZGANckeyKDjt3R4QxSw9VmvOJuwJDKiTbkUzqQ1JbxiC9wDsbs1KtazA5JQKaQ9QBIkJcJHBN6WLw9XXFbQMOpStTsIFAgDYheZ+i2nVOfIhOwA+cvmj31XhcPQtvRXX/VUKy5F7pmZKzALao5h6aK70X3NNLBojK3HCg+aAi8c8PPcjnNL8OKXI2H8nlQeqpubROsxXqIdbBcaZ/LWmwcrH/I7/KV6/zWGA2BtaOs+LpRIPSECmpNO35aDyN19wPJkYHMssCgIyfbdSd6WoFgNu1EozrIBeA6lDEQYoh2hcks44DmkljewDE0c0ACDMO1GNRfRWchbED6xTJ9A67ASRCCcZr1XEakhi0EDgZA2F9/x8BPunfWAYsFiXUD/ps6LS2yOviC6ngB7ZjsQjvDOkl0xIwS3JNU7cUXPv8FEG53lB3SgkgUj1xT48MHOQn6CqZUs8d5NJHPDdhb0ecdWR51ik9GfDL3QfuFOORwE7Bmn0oAvNflJSVKvU+Z48GPLaMGx9t2OkxIRzlQSkpAxzzQCYT8N+mtldVnqcmqtlyZB3OwjADd+t+MHnf9BWCsmFR4JLYhTbZPckVz/TG6boj/YIzLo7d+n7gZ/0IkBS5yGgIIUu2GHlWH/qBHV3JWjMP93ZL7aIxrgRM2+Cjbbvok22bXtYYhsC2LZV7zG5leZV6TRq3c4H938xBl4ZvO4+owzlk+Qa2cDemj9eXhyurlOywVA76fLbsTP8xvll2cdHnu1T/hwNfZ3X+K4PUyV5LYKy0iNyv1SuOIhVAJQcPDtTQPcadC2UAJTf4Ai5CEmqXCpGzFZyd5o/DgJnJ7bsV7KV2wfC5jdHbBpI0vieTv+qRYp30qX8KLQHza4XQrAQv7hM/SY58tZJG795hh9SM4WESNMwxhKRK2VlH2BgduJC38OHmO1narzKDICJiIMAx86VuxBgnfSm46hQS/r7AjC1nhtlYMO9m/kr10i2rdLIoYBqDgE+ZNB3DD9Q7CEcV6mKv8n4uC5N1HaSxFqulD3uQYOK6/FP223BszqRGhhDU7ONnYu5DJnqojjOtEDGl/Sr77kGcsN57w5WmLQwBpqquE3aW9W4Cfm4aksUFnUEw6RmEVtakK1qkkmMOgkTTHzmn5ZW0baHwfQakqKE+JjgQw0WhZY3qzKwHrqFwRBrAmNJKxqzDJByUDn3WRZ7VXc3nQdZeuygcEg0z9pQgrIWj32QkJwASD9QjJAtsoOQMYFZtJQSQxNpjAR+vXFbftqt9SoOu9Chy9nR6Gw2JzJPNcpIG9rUYabEyzNiSFvjlGlfRm17DTMRIz9YnarZnN9buMeq0XP2ogyZKQcaZQKVtJJb2AR13ihWpg+kRlXqPaIlsyis3pX4zyizBdl0heERl47dVjq/5bKIDjlekM9XSHCZMOCwZFtbH+PZW57YxmeXKEmOkDSfr08zZLDTq4VpQ+WyR/oNqL1LTJQtbTrOOTIinsTThKnpCkUxV2cmp1CSfTCG6knEIMvoizFwqfcoPwEN3Wr0R/baYEA28xPeMeM3tHoc0JidXqgaQDIOhim+VoxJVzk7MlBE71YyWHsWZTKy6kzYtg40bdOXv7FYApP0eqtSFphXuhPP1Lp/odT4rC+YgqlBUWuxEhXZCIpnKbJvjxh2YiLWIkV4aVwI2dvt24uC9mJAkKeACH2Y8RJ/72osdjdaC/PU4+0YCN5MbmI7/0hc=')
+ format('woff2');
+ /* #ifdef MP-ALIPAY */
+ src: url('//at.alicdn.com/t/font_1656945_d66u4pxvlq6.woff2') format('woff2'),
+ url('//at.alicdn.com/t/font_1656945_d66u4pxvlq6.woff') format('woff'),
+ url('//at.alicdn.com/t/font_1656945_d66u4pxvlq6.ttf') format('truetype');
+ /* #endif */
+ font-weight: normal;
+ font-style: normal;
+}
+[class*='cicon-'] {
+ font-family: 'coloricon';
+ display: inline-block;
+}
+
+.cicon-Aa:before {
+ content: '\e7a1';
+}
+.cicon-accounts:before {
+ content: '\e681';
+}
+.cicon-accounts-o:before {
+ content: '\e686';
+}
+.cicon-add:before {
+ content: '\e6e4';
+}
+.cicon-add-round:before {
+ content: '\e717';
+}
+.cicon-add-round-o:before {
+ content: '\e718';
+}
+.cicon-alarm:before {
+ content: '\e61e';
+}
+.cicon-album:before {
+ content: '\e759';
+}
+.cicon-alipay:before {
+ content: '\e6e1';
+}
+.cicon-android:before {
+ content: '\e6e2';
+}
+.cicon-angle:before {
+ content: '\e605';
+}
+.cicon-apple:before {
+ content: '\e8e7';
+}
+.cicon-apps:before {
+ content: '\e737';
+}
+.cicon-archive:before {
+ content: '\e7ae';
+}
+.cicon-archive-o:before {
+ content: '\e7ad';
+}
+.cicon-arrow:before {
+ content: '\e608';
+}
+.cicon-at-line:before {
+ content: '\e75c';
+}
+.cicon-avatar:before {
+ content: '\e663';
+}
+.cicon-avatar-o:before {
+ content: '\e665';
+}
+.cicon-avatars:before {
+ content: '\e67e';
+}
+.cicon-avatars-o:before {
+ content: '\e680';
+}
+.cicon-back:before {
+ content: '\e600';
+}
+.cicon-backspace:before {
+ content: '\e6a9';
+}
+.cicon-backup:before {
+ content: '\e61f';
+}
+.cicon-backup-restore:before {
+ content: '\e62d';
+}
+.cicon-barcode:before {
+ content: '\e71f';
+}
+.cicon-book:before {
+ content: '\e6a2';
+}
+.cicon-bookmark:before {
+ content: '\e6a3';
+}
+.cicon-bookmark-o:before {
+ content: '\e697';
+}
+.cicon-bookmarks:before {
+ content: '\e6a6';
+}
+.cicon-box:before {
+ content: '\e714';
+}
+.cicon-box-block:before {
+ content: '\e6ac';
+}
+.cicon-box-right:before {
+ content: '\e6a0';
+}
+.cicon-brand:before {
+ content: '\e726';
+}
+.cicon-brand-o:before {
+ content: '\e727';
+}
+.cicon-building:before {
+ content: '\e6c3';
+}
+.cicon-building-o:before {
+ content: '\e6c7';
+}
+.cicon-camera:before {
+ content: '\e6fa';
+}
+.cicon-camera-add:before {
+ content: '\e736';
+}
+.cicon-camera-add-o:before {
+ content: '\e735';
+}
+.cicon-camera-lens:before {
+ content: '\e68f';
+}
+.cicon-camera-lens-o:before {
+ content: '\e68e';
+}
+.cicon-camera-o:before {
+ content: '\e6fb';
+}
+.cicon-camera-rotate:before {
+ content: '\e71e';
+}
+.cicon-card:before {
+ content: '\e744';
+}
+.cicon-cardboard:before {
+ content: '\e7a9';
+}
+.cicon-cardboard-o:before {
+ content: '\e7aa';
+}
+.cicon-cardboard-off-o:before {
+ content: '\e7af';
+}
+.cicon-cart:before {
+ content: '\e70b';
+}
+.cicon-cart-o:before {
+ content: '\e708';
+}
+.cicon-chat:before {
+ content: '\e739';
+}
+.cicon-chat-bubble:before {
+ content: '\e69b';
+}
+.cicon-chat-bubble-o:before {
+ content: '\e6a7';
+}
+.cicon-chat-list:before {
+ content: '\e69d';
+}
+.cicon-chat-list-o:before {
+ content: '\e6aa';
+}
+.cicon-chat-o:before {
+ content: '\e73c';
+}
+.cicon-chat-smile:before {
+ content: '\e779';
+}
+.cicon-chat-smile-o:before {
+ content: '\e78e';
+}
+.cicon-chat-smiles:before {
+ content: '\e76b';
+}
+.cicon-chat-smiles-o:before {
+ content: '\e74a';
+}
+.cicon-check:before {
+ content: '\e69f';
+}
+.cicon-checkbox:before {
+ content: '\e713';
+}
+.cicon-checkbox-o:before {
+ content: '\e715';
+}
+.cicon-check-round:before {
+ content: '\e6f1';
+}
+.cicon-check-round-o:before {
+ content: '\e6f2';
+}
+.cicon-choiceness:before {
+ content: '\e728';
+}
+.cicon-choiceness-o:before {
+ content: '\e729';
+}
+.cicon-chrome:before {
+ content: '\e6e3';
+}
+.cicon-circle:before {
+ content: '\e7b0';
+}
+.cicon-circle-o:before {
+ content: '\e7b1';
+}
+.cicon-close:before {
+ content: '\e6ed';
+}
+.cicon-close-round:before {
+ content: '\e6f3';
+}
+.cicon-close-round-o:before {
+ content: '\e6f4';
+}
+.cicon-clothes:before {
+ content: '\e72a';
+}
+.cicon-clothes-o:before {
+ content: '\e72b';
+}
+.cicon-cloud:before {
+ content: '\e64e';
+}
+.cicon-cloud-done:before {
+ content: '\e641';
+}
+.cicon-cloud-download:before {
+ content: '\e647';
+}
+.cicon-cloud-o:before {
+ content: '\e646';
+}
+.cicon-cloud-off:before {
+ content: '\e64b';
+}
+.cicon-cloud-upload:before {
+ content: '\e687';
+}
+.cicon-code-box:before {
+ content: '\e7c3';
+}
+.cicon-coin:before {
+ content: '\e78a';
+}
+.cicon-coin-o:before {
+ content: '\e79d';
+}
+.cicon-comment:before {
+ content: '\e738';
+}
+.cicon-comment-o:before {
+ content: '\e70e';
+}
+.cicon-community:before {
+ content: '\e742';
+}
+.cicon-community-o:before {
+ content: '\e743';
+}
+.cicon-countdown:before {
+ content: '\e722';
+}
+.cicon-countdown-o:before {
+ content: '\e723';
+}
+.cicon-creative:before {
+ content: '\e72c';
+}
+.cicon-creative-o:before {
+ content: '\e72d';
+}
+.cicon-crop:before {
+ content: '\e6d9';
+}
+.cicon-crown:before {
+ content: '\e776';
+}
+.cicon-crown-o:before {
+ content: '\e777';
+}
+.cicon-cut:before {
+ content: '\e74b';
+}
+.cicon-DarkMode:before {
+ content: '\e7c4';
+}
+.cicon-dashboard:before {
+ content: '\e62e';
+}
+.cicon-delete:before {
+ content: '\e6bd';
+}
+.cicon-delete-close:before {
+ content: '\e6ae';
+}
+.cicon-delete-line:before {
+ content: '\e707';
+}
+.cicon-delete-line-o:before {
+ content: '\e709';
+}
+.cicon-delete-o:before {
+ content: '\e69a';
+}
+.cicon-deliver:before {
+ content: '\e7f7';
+}
+.cicon-deliver-o:before {
+ content: '\e6ff';
+}
+.cicon-demo:before {
+ content: '\e916';
+}
+.cicon-discover:before {
+ content: '\e70c';
+}
+.cicon-discover-o:before {
+ content: '\e702';
+}
+.cicon-discuss-fill:before {
+ content: '\e790';
+}
+.cicon-discuss-line:before {
+ content: '\e78f';
+}
+.cicon-dollar:before {
+ content: '\e79f';
+}
+.cicon-dollar-o:before {
+ content: '\e79e';
+}
+.cicon-done:before {
+ content: '\e633';
+}
+.cicon-done-all:before {
+ content: '\e62a';
+}
+.cicon-douyin:before {
+ content: '\e6e7';
+}
+.cicon-drop-down:before {
+ content: '\e61c';
+}
+.cicon-drop-up:before {
+ content: '\e61d';
+}
+.cicon-eject:before {
+ content: '\e63a';
+}
+.cicon-ellipse:before {
+ content: '\e74c';
+}
+.cicon-emoji:before {
+ content: '\e78d';
+}
+.cicon-emoji-o:before {
+ content: '\e6ee';
+}
+.cicon-equalizer:before {
+ content: '\e802';
+}
+.cicon-eraser:before {
+ content: '\e770';
+}
+.cicon-eraser-o:before {
+ content: '\e772';
+}
+.cicon-evaluate:before {
+ content: '\e7f0';
+}
+.cicon-evaluate-o:before {
+ content: '\e700';
+}
+.cicon-event-close:before {
+ content: '\e6a5';
+}
+.cicon-event-done:before {
+ content: '\e6b2';
+}
+.cicon-event-list:before {
+ content: '\e6b8';
+}
+.cicon-explore:before {
+ content: '\e628';
+}
+.cicon-explore-line:before {
+ content: '\e719';
+}
+.cicon-explore-line-o:before {
+ content: '\e710';
+}
+.cicon-explore-o:before {
+ content: '\e626';
+}
+.cicon-extension:before {
+ content: '\e620';
+}
+.cicon-extension-o:before {
+ content: '\e63f';
+}
+.cicon-eye:before {
+ content: '\e740';
+}
+.cicon-eye-favor:before {
+ content: '\e7b4';
+}
+.cicon-eye-favor-o:before {
+ content: '\e7b5';
+}
+.cicon-eye-o:before {
+ content: '\e741';
+}
+.cicon-eye-off:before {
+ content: '\e7b3';
+}
+.cicon-eye-off-o:before {
+ content: '\e7b2';
+}
+.cicon-facebook:before {
+ content: '\e6ea';
+}
+.cicon-favorite:before {
+ content: '\e623';
+}
+.cicon-favorite-o:before {
+ content: '\e621';
+}
+.cicon-female:before {
+ content: '\e72f';
+}
+.cicon-file:before {
+ content: '\e857';
+}
+.cicon-file-copy:before {
+ content: '\e85c';
+}
+.cicon-file-copy-o:before {
+ content: '\e7bc';
+}
+.cicon-file-o:before {
+ content: '\e7bb';
+}
+.cicon-file-text:before {
+ content: '\e858';
+}
+.cicon-file-text-o:before {
+ content: '\e7b9';
+}
+.cicon-filter:before {
+ content: '\e6ec';
+}
+.cicon-fingerprint:before {
+ content: '\e63b';
+}
+.cicon-first-page:before {
+ content: '\e60c';
+}
+.cicon-flag:before {
+ content: '\e64d';
+}
+.cicon-flag-o:before {
+ content: '\e64c';
+}
+.cicon-flash-close:before {
+ content: '\e73b';
+}
+.cicon-flash-off:before {
+ content: '\e6d5';
+}
+.cicon-flash-on:before {
+ content: '\e6dc';
+}
+.cicon-flash-open:before {
+ content: '\e74f';
+}
+.cicon-folder:before {
+ content: '\e6a1';
+}
+.cicon-folder-add:before {
+ content: '\e6b4';
+}
+.cicon-folder-o:before {
+ content: '\e6b0';
+}
+.cicon-folder-special:before {
+ content: '\e65c';
+}
+.cicon-forward:before {
+ content: '\e601';
+}
+.cicon-fullscreen:before {
+ content: '\e915';
+}
+.cicon-fullscreen-exit:before {
+ content: '\e914';
+}
+.cicon-game:before {
+ content: '\e6c0';
+}
+.cicon-game-o:before {
+ content: '\e6d1';
+}
+.cicon-git-commit:before {
+ content: '\e7be';
+}
+.cicon-git-commit-o:before {
+ content: '\e7bd';
+}
+.cicon-github:before {
+ content: '\e6e9';
+}
+.cicon-github-circle:before {
+ content: '\ead8';
+}
+.cicon-goods:before {
+ content: '\e778';
+}
+.cicon-goodsnew:before {
+ content: '\e7bf';
+}
+.cicon-goodsnew-o:before {
+ content: '\e7c0';
+}
+.cicon-goods-o:before {
+ content: '\e70f';
+}
+.cicon-GooglePlaylogo:before {
+ content: '\e6e5';
+}
+.cicon-grid:before {
+ content: '\e6ce';
+}
+.cicon-grid-o:before {
+ content: '\e6cc';
+}
+.cicon-group:before {
+ content: '\e7f5';
+}
+.cicon-group-o:before {
+ content: '\e753';
+}
+.cicon-guanli:before {
+ content: '\e750';
+}
+.cicon-headset:before {
+ content: '\e6a4';
+}
+.cicon-headset-mic:before {
+ content: '\e6b1';
+}
+.cicon-help:before {
+ content: '\e66b';
+}
+.cicon-help-o:before {
+ content: '\e65e';
+}
+.cicon-home:before {
+ content: '\e70d';
+}
+.cicon-home-2:before {
+ content: '\e6fd';
+}
+.cicon-home-2-o:before {
+ content: '\e6cf';
+}
+.cicon-home-3:before {
+ content: '\e6fc';
+}
+.cicon-home-3-o:before {
+ content: '\e6e0';
+}
+.cicon-home-4:before {
+ content: '\e732';
+}
+.cicon-home-4-o:before {
+ content: '\e6e6';
+}
+.cicon-home-community:before {
+ content: '\e799';
+}
+.cicon-home-dot:before {
+ content: '\e794';
+}
+.cicon-home-dot-o:before {
+ content: '\e797';
+}
+.cicon-home-line:before {
+ content: '\e793';
+}
+.cicon-home-line-o:before {
+ content: '\e792';
+}
+.cicon-home-o:before {
+ content: '\e70a';
+}
+.cicon-home-sm:before {
+ content: '\e798';
+}
+.cicon-home-smile:before {
+ content: '\e79c';
+}
+.cicon-home-smile-o:before {
+ content: '\e7a0';
+}
+.cicon-home-smline:before {
+ content: '\e791';
+}
+.cicon-home-smline-o:before {
+ content: '\e731';
+}
+.cicon-home-sm-o:before {
+ content: '\e79b';
+}
+.cicon-hotel:before {
+ content: '\e7a8';
+}
+.cicon-hotel-o:before {
+ content: '\e7a3';
+}
+.cicon-huohu:before {
+ content: '\e72e';
+}
+.cicon-IE:before {
+ content: '\e922';
+}
+.cicon-image-text:before {
+ content: '\e781';
+}
+.cicon-image-text-o:before {
+ content: '\e758';
+}
+.cicon-import-export:before {
+ content: '\e615';
+}
+.cicon-info:before {
+ content: '\e6ef';
+}
+.cicon-info-o:before {
+ content: '\e705';
+}
+.cicon-input:before {
+ content: '\e75f';
+}
+.cicon-input-o:before {
+ content: '\e6c8';
+}
+.cicon-keyboard:before {
+ content: '\e6b6';
+}
+.cicon-kinds:before {
+ content: '\e748';
+}
+.cicon-last-page:before {
+ content: '\e60d';
+}
+.cicon-layout:before {
+ content: '\e7e8';
+}
+.cicon-layout-o:before {
+ content: '\e7e7';
+}
+.cicon-LightMode:before {
+ content: '\e7ba';
+}
+.cicon-link:before {
+ content: '\e6ab';
+}
+.cicon-link-off:before {
+ content: '\e6b9';
+}
+.cicon-loader-fill:before {
+ content: '\e76d';
+}
+.cicon-loading:before {
+ content: '\e746';
+}
+.cicon-loading1:before {
+ content: '\e749';
+}
+.cicon-loading2:before {
+ content: '\e7f1';
+}
+.cicon-location-off:before {
+ content: '\e671';
+}
+.cicon-location-off-o:before {
+ content: '\e66d';
+}
+.cicon-location-on:before {
+ content: '\e65f';
+}
+.cicon-location-on-o:before {
+ content: '\e661';
+}
+.cicon-lock:before {
+ content: '\e6ad';
+}
+.cicon-lock-o:before {
+ content: '\e6b3';
+}
+.cicon-lock-open:before {
+ content: '\e6ba';
+}
+.cicon-logout:before {
+ content: '\e76e';
+}
+.cicon-loop:before {
+ content: '\e616';
+}
+.cicon-magic:before {
+ content: '\e6b7';
+}
+.cicon-magic-o:before {
+ content: '\e6c2';
+}
+.cicon-mail:before {
+ content: '\e6be';
+}
+.cicon-mail-o:before {
+ content: '\e6bc';
+}
+.cicon-male:before {
+ content: '\e730';
+}
+.cicon-mic:before {
+ content: '\e656';
+}
+.cicon-mic-none:before {
+ content: '\e642';
+}
+.cicon-mic-off:before {
+ content: '\e652';
+}
+.cicon-miniprogram:before {
+ content: '\e7d6';
+}
+.cicon-mobile:before {
+ content: '\e854';
+}
+.cicon-mobile-o:before {
+ content: '\e7b6';
+}
+.cicon-moneybag:before {
+ content: '\e7ce';
+}
+.cicon-moneybag-o:before {
+ content: '\e7d1';
+}
+.cicon-more:before {
+ content: '\e688';
+}
+.cicon-more-tag:before {
+ content: '\e672';
+}
+.cicon-move:before {
+ content: '\e768';
+}
+.cicon-move-round:before {
+ content: '\e602';
+}
+.cicon-move-round-o:before {
+ content: '\e603';
+}
+.cicon-music:before {
+ content: '\e795';
+}
+.cicon-music-off:before {
+ content: '\e796';
+}
+.cicon-my:before {
+ content: '\e78c';
+}
+.cicon-my-o:before {
+ content: '\e78b';
+}
+.cicon-near-me:before {
+ content: '\e654';
+}
+.cicon-near-me-o:before {
+ content: '\e649';
+}
+.cicon-not:before {
+ content: '\e667';
+}
+.cicon-notice:before {
+ content: '\e666';
+}
+.cicon-notice-active:before {
+ content: '\e66f';
+}
+.cicon-notice-active-o:before {
+ content: '\e65d';
+}
+.cicon-notice-o:before {
+ content: '\e664';
+}
+.cicon-notice-off:before {
+ content: '\e6b5';
+}
+.cicon-notice-off-o:before {
+ content: '\e6bb';
+}
+.cicon-numcode:before {
+ content: '\e755';
+}
+.cicon-order:before {
+ content: '\e786';
+}
+.cicon-order-o:before {
+ content: '\e7b8';
+}
+.cicon-paint:before {
+ content: '\e75d';
+}
+.cicon-paint-o:before {
+ content: '\e75a';
+}
+.cicon-palette:before {
+ content: '\e696';
+}
+.cicon-palette-o:before {
+ content: '\e691';
+}
+.cicon-pause:before {
+ content: '\e669';
+}
+.cicon-pause-circle:before {
+ content: '\e678';
+}
+.cicon-person:before {
+ content: '\e679';
+}
+.cicon-person-add:before {
+ content: '\e668';
+}
+.cicon-person-add-o:before {
+ content: '\e66a';
+}
+.cicon-person-o:before {
+ content: '\e67d';
+}
+.cicon-person-pin-circle:before {
+ content: '\e66c';
+}
+.cicon-person-pin-circle-o:before {
+ content: '\e670';
+}
+.cicon-phone:before {
+ content: '\e6f0';
+}
+.cicon-phone-call:before {
+ content: '\e6d7';
+}
+.cicon-pic:before {
+ content: '\e756';
+}
+.cicon-pic-o:before {
+ content: '\e69e';
+}
+.cicon-pin-drop:before {
+ content: '\e648';
+}
+.cicon-pin-drop-o:before {
+ content: '\e655';
+}
+.cicon-place:before {
+ content: '\e651';
+}
+.cicon-place-o:before {
+ content: '\e650';
+}
+.cicon-play-arrow:before {
+ content: '\e66e';
+}
+.cicon-play-circle:before {
+ content: '\e674';
+}
+.cicon-play-circle-o:before {
+ content: '\e67f';
+}
+.cicon-popover:before {
+ content: '\e74e';
+}
+.cicon-popover-o:before {
+ content: '\e757';
+}
+.cicon-present:before {
+ content: '\e73a';
+}
+.cicon-present-o:before {
+ content: '\e711';
+}
+.cicon-progress:before {
+ content: '\e784';
+}
+.cicon-qq:before {
+ content: '\e7d9';
+}
+.cicon-qr-code-fill:before {
+ content: '\e767';
+}
+.cicon-qr-code-line:before {
+ content: '\e75e';
+}
+.cicon-quill:before {
+ content: '\e760';
+}
+.cicon-quill-o:before {
+ content: '\e761';
+}
+.cicon-radio:before {
+ content: '\e6d4';
+}
+.cicon-radiobox:before {
+ content: '\e763';
+}
+.cicon-radiobox-o:before {
+ content: '\e75b';
+}
+.cicon-recharge:before {
+ content: '\e71c';
+}
+.cicon-recharge-o:before {
+ content: '\e71d';
+}
+.cicon-record:before {
+ content: '\e7a4';
+}
+.cicon-record-o:before {
+ content: '\e7a6';
+}
+.cicon-redo:before {
+ content: '\e612';
+}
+.cicon-redpacket:before {
+ content: '\e7d3';
+}
+.cicon-redpacket-o:before {
+ content: '\e71a';
+}
+.cicon-refresh:before {
+ content: '\e611';
+}
+.cicon-repair:before {
+ content: '\e73f';
+}
+.cicon-repair-o:before {
+ content: '\e73e';
+}
+.cicon-repeat:before {
+ content: '\e617';
+}
+.cicon-replay:before {
+ content: '\e619';
+}
+.cicon-reply:before {
+ content: '\e618';
+}
+.cicon-reply-all:before {
+ content: '\e614';
+}
+.cicon-road-map:before {
+ content: '\e769';
+}
+.cicon-road-map-o:before {
+ content: '\e76a';
+}
+.cicon-round:before {
+ content: '\e716';
+}
+.cicon-round-angle:before {
+ content: '\e6f5';
+}
+.cicon-round-angle-o:before {
+ content: '\e6f6';
+}
+.cicon-round-arrow-line:before {
+ content: '\e734';
+}
+.cicon-round-box:before {
+ content: '\e604';
+}
+.cicon-safe:before {
+ content: '\e77f';
+}
+.cicon-safe-check:before {
+ content: '\e875';
+}
+.cicon-safe-check-o:before {
+ content: '\e876';
+}
+.cicon-safe-flash:before {
+ content: '\e783';
+}
+.cicon-safe-flash-o:before {
+ content: '\e775';
+}
+.cicon-safe-key:before {
+ content: '\e76c';
+}
+.cicon-safe-key-o:before {
+ content: '\e766';
+}
+.cicon-safe-o:before {
+ content: '\e77e';
+}
+.cicon-save:before {
+ content: '\e677';
+}
+.cicon-save-o:before {
+ content: '\e684';
+}
+.cicon-scan:before {
+ content: '\e703';
+}
+.cicon-scissors:before {
+ content: '\e762';
+}
+.cicon-search:before {
+ content: '\e6f7';
+}
+.cicon-search-line:before {
+ content: '\e771';
+}
+.cicon-searchlist:before {
+ content: '\e720';
+}
+.cicon-search-o:before {
+ content: '\e782';
+}
+.cicon-search-sm:before {
+ content: '\e631';
+}
+.cicon-service:before {
+ content: '\e73d';
+}
+.cicon-service-fill:before {
+ content: '\e704';
+}
+.cicon-service-o:before {
+ content: '\e721';
+}
+.cicon-set:before {
+ content: '\e773';
+}
+.cicon-set-list:before {
+ content: '\e76f';
+}
+.cicon-set-o:before {
+ content: '\e774';
+}
+.cicon-settings:before {
+ content: '\e77a';
+}
+.cicon-settings-o:before {
+ content: '\e780';
+}
+.cicon-share:before {
+ content: '\e6c5';
+}
+.cicon-share-line-o:before {
+ content: '\e74d';
+}
+.cicon-shengji:before {
+ content: '\e747';
+}
+.cicon-shopping-cart:before {
+ content: '\e685';
+}
+.cicon-shopping-cart-o:before {
+ content: '\e676';
+}
+.cicon-show:before {
+ content: '\e785';
+}
+.cicon-show-o:before {
+ content: '\e787';
+}
+.cicon-shuffle:before {
+ content: '\e61a';
+}
+.cicon-sip:before {
+ content: '\e764';
+}
+.cicon-sip-o:before {
+ content: '\e765';
+}
+.cicon-skip-next:before {
+ content: '\e6dd';
+}
+.cicon-skip-previous:before {
+ content: '\e6d6';
+}
+.cicon-slack:before {
+ content: '\e87b';
+}
+.cicon-slack-square:before {
+ content: '\e891';
+}
+.cicon-sort:before {
+ content: '\e6bf';
+}
+.cicon-sort-order:before {
+ content: '\e6fe';
+}
+.cicon-sound:before {
+ content: '\e77b';
+}
+.cicon-sponsor:before {
+ content: '\e77c';
+}
+.cicon-sponsor-o:before {
+ content: '\e77d';
+}
+.cicon-star:before {
+ content: '\e683';
+}
+.cicon-star-half:before {
+ content: '\e67c';
+}
+.cicon-star-o:before {
+ content: '\e67b';
+}
+.cicon-stock:before {
+ content: '\e789';
+}
+.cicon-stop:before {
+ content: '\e6db';
+}
+.cicon-store:before {
+ content: '\e7ac';
+}
+.cicon-store-0:before {
+ content: '\e7ab';
+}
+.cicon-store-2:before {
+ content: '\e7a7';
+}
+.cicon-store-2-o:before {
+ content: '\e7a5';
+}
+.cicon-sub-left:before {
+ content: '\e60b';
+}
+.cicon-sub-right:before {
+ content: '\e60f';
+}
+.cicon-subtitles:before {
+ content: '\e6da';
+}
+.cicon-subtitles-o:before {
+ content: '\e6d8';
+}
+.cicon-sync-alt:before {
+ content: '\e613';
+}
+.cicon-tag:before {
+ content: '\e751';
+}
+.cicon-tag-o:before {
+ content: '\e752';
+}
+.cicon-taobao:before {
+ content: '\e712';
+}
+.cicon-terminal:before {
+ content: '\e7c1';
+}
+.cicon-terminal-o:before {
+ content: '\e7c2';
+}
+.cicon-thumb-down:before {
+ content: '\e6c1';
+}
+.cicon-thumb-down-o:before {
+ content: '\e6c9';
+}
+.cicon-thumb-up:before {
+ content: '\e6c6';
+}
+.cicon-thumb-up-line:before {
+ content: '\e71b';
+}
+.cicon-thumb-up-line-o:before {
+ content: '\e6eb';
+}
+.cicon-thumb-up-o:before {
+ content: '\e6cb';
+}
+.cicon-ticket:before {
+ content: '\e800';
+}
+.cicon-ticket-o:before {
+ content: '\e701';
+}
+.cicon-time:before {
+ content: '\e6f8';
+}
+.cicon-time-o:before {
+ content: '\e6f9';
+}
+.cicon-timer:before {
+ content: '\e69c';
+}
+.cicon-title:before {
+ content: '\e82f';
+}
+.cicon-titles:before {
+ content: '\e745';
+}
+.cicon-toggle:before {
+ content: '\e706';
+}
+.cicon-toggle-o:before {
+ content: '\e733';
+}
+.cicon-topbar:before {
+ content: '\e788';
+}
+.cicon-translate:before {
+ content: '\e79a';
+}
+.cicon-tree:before {
+ content: '\e659';
+}
+.cicon-Tt:before {
+ content: '\e7a2';
+}
+.cicon-twiter:before {
+ content: '\e6e8';
+}
+.cicon-cicon-community-o:before {
+ content: '\e6df';
+}
+.cicon-undo:before {
+ content: '\e61b';
+}
+.cicon-unfold-less:before {
+ content: '\e60e';
+}
+.cicon-unfold-more:before {
+ content: '\e609';
+}
+.cicon-upstage:before {
+ content: '\e724';
+}
+.cicon-upstage-o:before {
+ content: '\e725';
+}
+.cicon-view-agenda:before {
+ content: '\e639';
+}
+.cicon-view-array:before {
+ content: '\e636';
+}
+.cicon-view-carousel:before {
+ content: '\e638';
+}
+.cicon-view-column:before {
+ content: '\e632';
+}
+.cicon-view-day:before {
+ content: '\e627';
+}
+.cicon-view-headline:before {
+ content: '\e62b';
+}
+.cicon-view-list:before {
+ content: '\e63c';
+}
+.cicon-view-module:before {
+ content: '\e629';
+}
+.cicon-view-quilt:before {
+ content: '\e630';
+}
+.cicon-volume:before {
+ content: '\e6c4';
+}
+.cicon-volume-off:before {
+ content: '\e6cd';
+}
+.cicon-warn:before {
+ content: '\e662';
+}
+.cicon-warn-o:before {
+ content: '\e675';
+}
+.cicon-wechat-pay:before {
+ content: '\e7e6';
+}
+.cicon-weibo-fill:before {
+ content: '\e7e4';
+}
+.cicon-weibo-o:before {
+ content: '\e7e3';
+}
+.cicon-weixin:before {
+ content: '\e6de';
+}
+.cicon-whatshot:before {
+ content: '\e6ca';
+}
+.cicon-whatshot-o:before {
+ content: '\e6d0';
+}
+.cicon-wifi:before {
+ content: '\e6d2';
+}
+.cicon-wifi-off:before {
+ content: '\e6d3';
+}
+.cicon-yamaxun:before {
+ content: '\e7b7';
+}
+.cicon-zuoji:before {
+ content: '\e754';
+}
diff --git a/sheep/scss/icon/_icon.scss b/sheep/scss/icon/_icon.scss
new file mode 100644
index 0000000..f277fc8
--- /dev/null
+++ b/sheep/scss/icon/_icon.scss
@@ -0,0 +1,181 @@
+@font-face {
+ font-family: 'colorui'; /* Project id 2620914 */
+ src: url('data:application/x-font-woff2;charset=utf-8;base64,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')
+ format('woff2');
+ /* #ifdef MP-ALIPAY */
+ src: url('//at.alicdn.com/t/font_2620914_57y9q5zpbel.woff?t=1624238023908') format('woff'),
+ url('//at.alicdn.com/t/font_2620914_57y9q5zpbel.ttf?t=1624238023908') format('truetype');
+ /* #endif */
+}
+
+[class*='_icon-'] {
+ font-family: 'colorui' !important;
+ display: inline-block;
+}
+@font-face {
+ font-family: 'ui-num';
+ src: url('data:application/x-font-ttf;base64,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')
+ format('woff2');
+ font-weight: normal;
+ font-style: normal;
+}
+
+._icon-checkbox:before {
+ content: '\e713';
+}
+
+._icon-box:before {
+ content: '\e714';
+}
+
+._icon-checkbox-o:before {
+ content: '\e715';
+}
+
+._icon-round:before {
+ content: '\e716';
+}
+
+._icon-home-o:before {
+ content: '\e70a';
+}
+
+._icon-home:before {
+ content: '\e70d';
+}
+
+._icon-edit:before {
+ content: '\e649';
+}
+
+._icon-close:before {
+ content: '\e6ed';
+}
+
+._icon-check-round:before {
+ content: '\e6f1';
+}
+
+._icon-check-round-o:before {
+ content: '\e6f2';
+}
+
+._icon-close-round:before {
+ content: '\e6f3';
+}
+
+._icon-close-round-o:before {
+ content: '\e6f4';
+}
+
+._icon-waiting:before {
+ content: '\e6f8';
+}
+
+._icon-waiting-o:before {
+ content: '\e6f9';
+}
+
+._icon-warn:before {
+ content: '\e662';
+}
+
+._icon-warn-o:before {
+ content: '\e675';
+}
+
+._icon-more:before {
+ content: '\e688';
+}
+
+._icon-delete:before {
+ content: '\e707';
+}
+
+._icon-delete-o:before {
+ content: '\e709';
+}
+
+._icon-add-round:before {
+ content: '\e717';
+}
+
+._icon-add-round-o:before {
+ content: '\e718';
+}
+
+._icon-add:before {
+ content: '\e6e4';
+}
+
+._icon-info:before {
+ content: '\e6ef';
+}
+
+._icon-info-o:before {
+ content: '\e705';
+}
+
+._icon-move:before {
+ content: '\e768';
+}
+
+._icon-title:before {
+ content: '\e82f';
+}
+
+._icon-titles:before {
+ content: '\e745';
+}
+
+._icon-loading:before {
+ content: '\e746';
+}
+
+._icon-copy-o:before {
+ content: '\e7bc';
+}
+
+._icon-copy:before {
+ content: '\e85c';
+}
+
+._icon-loader:before {
+ content: '\e76d';
+}
+
+._icon-search:before {
+ content: '\e782';
+}
+
+._icon-back:before {
+ content: '\e600';
+}
+
+._icon-forward:before {
+ content: '\e601';
+}
+
+._icon-arrow:before {
+ content: '\e608';
+}
+
+._icon-drop-down:before {
+ content: '\e61c';
+}
+
+._icon-drop-up:before {
+ content: '\e61d';
+}
+
+._icon-check:before {
+ content: '\e69f';
+}
+
+._icon-move-round:before {
+ content: '\e602';
+}
+
+._icon-move-round-o:before {
+ content: '\e603';
+}
diff --git a/sheep/scss/icon/_sheepicon.scss b/sheep/scss/icon/_sheepicon.scss
new file mode 100644
index 0000000..cf7ea08
--- /dev/null
+++ b/sheep/scss/icon/_sheepicon.scss
@@ -0,0 +1,94 @@
+@font-face {
+ font-family: 'sheepicon';
+ src: url('data:application/x-font-woff2;charset=utf-8;base64,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')
+ format('woff2');
+}
+
+[class*='sicon-'] {
+ font-family: 'sheepicon';
+ display: inline-block;
+}
+
+.sicon-edit:before {
+ content: '\e711';
+}
+
+.sicon-basic:before {
+ content: '\e712';
+}
+
+.sicon-home:before {
+ content: '\e70c';
+}
+
+.sicon-more:before {
+ content: '\e707';
+}
+
+.sicon-check-line:before {
+ content: '\e708';
+}
+
+.sicon-transport:before {
+ content: '\e709';
+}
+
+.sicon-goods-card:before {
+ content: '\e70a';
+}
+
+.sicon-collect:before {
+ content: '\e70b';
+}
+
+.sicon-warning-line:before {
+ content: '\e70d';
+}
+
+.sicon-score1:before {
+ content: '\e70e';
+}
+
+.sicon-score2:before {
+ content: '\e70f';
+}
+
+.sicon-goods-list:before {
+ content: '\e710';
+}
+
+.sicon-back:before {
+ content: '\e706';
+}
+
+.sicon-unchecked:before {
+ content: '\e703';
+}
+
+.sicon-warning-outline:before {
+ content: '\e6ff';
+}
+
+.sicon-question-outline:before {
+ content: '\e700';
+}
+
+.sicon-circlecheck:before {
+ content: '\e701';
+}
+
+.sicon-circleclose:before {
+ content: '\e702';
+}
+
+.sicon-delivery:before {
+ content: '\e6fd';
+}
+
+.sicon-orders:before {
+ content: '\e6fe';
+}
+
+.sicon-qrcode:before {
+ content: '\e6f9';
+}
diff --git a/sheep/scss/icon/_style.scss b/sheep/scss/icon/_style.scss
new file mode 100644
index 0000000..a2c4dc8
--- /dev/null
+++ b/sheep/scss/icon/_style.scss
@@ -0,0 +1,43 @@
+@import './icon'; //核心图标库
+@import './coloricon'; //扩展图标库
+@import './sheepicon';
+.icon-spin {
+ animation: icon-spin 2s infinite linear;
+}
+
+.icon-pulse {
+ animation: icon-spin 1s infinite steps(8);
+}
+
+@keyframes icon-spin {
+ 0% {
+ transform: rotate(0deg);
+ }
+ 100% {
+ transform: rotate(359deg);
+ }
+}
+.icon-90 {
+ transform: rotate(90deg);
+}
+.icon-180 {
+ transform: rotate(180deg);
+}
+.icon-270 {
+ transform: rotate(270deg);
+}
+.icon-x {
+ transform: scale(-1, 1);
+}
+.icon-y {
+ transform: scale(1, -1);
+}
+.icon-fw {
+ width: calc(18em / 14);
+ text-align: center;
+}
+@each $class, $value in $iconsize {
+ .icon-#{$class} {
+ transform: scale(#{$value});
+ }
+}
diff --git a/sheep/scss/index.scss b/sheep/scss/index.scss
new file mode 100644
index 0000000..c841956
--- /dev/null
+++ b/sheep/scss/index.scss
@@ -0,0 +1,27 @@
+@import './tools';
+@import './ui';
+
+/* 字体文件 */
+@font-face {
+ font-family: OPPOSANS;
+ src: url('~@/sheep/scss/font/OPPOSANS-M-subfont.ttf');
+}
+.font-OPPOSANS {
+ font-family: OPPOSANS;
+}
+page {
+ -webkit-overflow-scrolling: touch; // 解决ios滑动不流畅
+ height: 100%;
+ width: 100%;
+ // font-family: OPPOSANS;
+ word-break: break-all; //英文文本不换行
+ white-space: normal;
+ background-color: $bg-page;
+ color: $dark-3;
+}
+::-webkit-scrollbar {
+ width: 0;
+ height: 0;
+ color: transparent;
+ display: none;
+}
diff --git a/sheep/scss/style/_avatar.scss b/sheep/scss/style/_avatar.scss
new file mode 100644
index 0000000..e69de29
diff --git a/sheep/scss/style/_background.scss b/sheep/scss/style/_background.scss
new file mode 100644
index 0000000..775f37f
--- /dev/null
+++ b/sheep/scss/style/_background.scss
@@ -0,0 +1,204 @@
+/* ==================
+ 背景
+ ==================== */
+/* -- 基础色 -- */
+@each $color, $value in map-merge($colors, $darks) {
+ .bg-#{$color} {
+ background-color: $value !important;
+ @if $color == 'yellow' {
+ color: #333333 !important;
+ } @else {
+ color: #ffffff !important;
+ }
+ }
+}
+
+/* -- 浅色 -- */
+@each $color, $value in $colors {
+ .bg-#{$color}-light {
+ background-image: linear-gradient(45deg, white, mix(white, $value, 85%)) !important;
+ color: $value !important;
+ }
+
+ .bg-#{$color}-thin {
+ background-color: rgba($value, var(--ui-BG-opacity)) !important;
+ color: $value !important;
+ }
+}
+
+/* -- 渐变色 -- */
+
+@each $color, $value in $colors {
+ @each $colorsub, $valuesub in $colors {
+ @if $color != $colorsub {
+ .bg-#{$color}-#{$colorsub} {
+ // background-color: $value !important;
+ background-image: linear-gradient(130deg, $value, $valuesub) !important;
+ color: #ffffff !important;
+ }
+ }
+ }
+}
+.bg-yellow-gradient {
+ background-image: linear-gradient(45deg, #f5fe00, #ff6600) !important;
+ color: $dark-3 !important;
+}
+.bg-orange-gradient {
+ background-image: linear-gradient(90deg, #ff6000, #fe832a) !important;
+ color: $white !important;
+}
+.bg-red-gradient {
+ background-image: linear-gradient(45deg, #f33a41, #ed0586) !important;
+ color: $white !important;
+}
+.bg-pink-gradient {
+ background-image: linear-gradient(45deg, #fea894, #ff1047) !important;
+ color: $white !important;
+}
+.bg-mauve-gradient {
+ background-image: linear-gradient(45deg, #c01f95, #7115cc) !important;
+ color: $white !important;
+}
+.bg-purple-gradient {
+ background-image: linear-gradient(45deg, #9829ea, #5908fb) !important;
+ color: $white !important;
+}
+.bg-blue-gradient {
+ background-image: linear-gradient(45deg, #00b8f9, #0166eb) !important;
+ color: $white !important;
+}
+.bg-cyan-gradient {
+ background-image: linear-gradient(45deg, #06edfe, #48b2fe) !important;
+ color: $white !important;
+}
+.bg-green-gradient {
+ background-image: linear-gradient(45deg, #3ab54a, #8cc63f) !important;
+ color: $white !important;
+}
+.bg-olive-gradient {
+ background-image: linear-gradient(45deg, #90e630, #39d266) !important;
+ color: $white !important;
+}
+.bg-grey-gradient {
+ background-image: linear-gradient(45deg, #9aadb9, #354855) !important;
+ color: $white !important;
+}
+.bg-brown-gradient {
+ background-image: linear-gradient(45deg, #ca6f2e, #cb1413) !important;
+ color: $white !important;
+}
+
+@each $color, $value in $grays {
+ .bg-#{$color} {
+ background-color: $value !important;
+ color: #333333 !important;
+ }
+}
+
+.bg-square {
+ @include bg-square;
+}
+.bg-none {
+ background: transparent !important;
+ color: inherit !important;
+}
+
+[class*='bg-mask'] {
+ position: relative;
+ //background: transparent !important;
+ color: #ffffff !important;
+ > view,
+ > text {
+ position: relative;
+ z-index: 1;
+ color: #ffffff;
+ }
+ &::before {
+ content: '';
+ border-radius: inherit;
+ width: 100%;
+ height: 100%;
+ @include position-center;
+ background-color: rgba(0, 0, 0, 0.4);
+ z-index: 0;
+ }
+ @at-root .bg-mask-80::before {
+ background: rgba(0, 0, 0, 0.8) !important;
+ }
+ @at-root .bg-mask-50::before {
+ background: rgba(0, 0, 0, 0.5) !important;
+ }
+ @at-root .bg-mask-20::before {
+ background: rgba(0, 0, 0, 0.2) !important;
+ }
+ @at-root .bg-mask-top::before {
+ background-color: rgba(0, 0, 0, 0);
+ background-image: linear-gradient(rgba(0, 0, 0, 1), rgba(0, 0, 0, 0.618), rgba(0, 0, 0, 0.01));
+ }
+ @at-root .bg-white-top {
+ background-color: rgba(0, 0, 0, 0);
+ background-image: linear-gradient(rgba(255, 255, 255, 1), rgba(255, 255, 255, 0.3));
+ }
+ @at-root .bg-mask-bottom::before {
+ background-color: rgba(0, 0, 0, 0);
+ background-image: linear-gradient(rgba(0, 0, 0, 0.01), rgba(0, 0, 0, 0.618), rgba(0, 0, 0, 1));
+ }
+}
+.bg-img {
+ background-size: cover;
+ background-position: center;
+ background-repeat: no-repeat;
+}
+
+[class*='bg-blur'] {
+ position: relative;
+ > view,
+ > text {
+ position: relative;
+ z-index: 1;
+ }
+ &::before {
+ content: '';
+ width: 100%;
+ height: 100%;
+ @include position-center;
+ border-radius: inherit;
+ transform-origin: 0 0;
+ pointer-events: none;
+ box-sizing: border-box;
+ }
+}
+@supports (-webkit-backdrop-filter: blur(20px)) or (backdrop-filter: blur(20px)) {
+ .bg-blur::before {
+ @include blur;
+ background-color: var(--ui-Blur-1);
+ }
+ .bg-blur-1::before {
+ @include blur;
+ background-color: var(--ui-Blur-2);
+ }
+ .bg-blur-2::before {
+ @include blur;
+ background-color: var(--ui-Blur-3);
+ }
+}
+@supports not (backdrop-filter: blur(5px)) {
+ .bg-blur {
+ color: var(--ui-TC);
+ &::before {
+ background-color: var(--ui-BG);
+ }
+ }
+ .bg-blur-1 {
+ color: var(--ui-TC);
+ &::before {
+ background-color: var(--ui-BG-1);
+ }
+ }
+ .bg-blur-2 {
+ color: var(--ui-TC);
+ &::before {
+ background-color: var(--ui-BG-2);
+ }
+ }
+}
diff --git a/sheep/scss/style/_border.scss b/sheep/scss/style/_border.scss
new file mode 100644
index 0000000..4ef1d54
--- /dev/null
+++ b/sheep/scss/style/_border.scss
@@ -0,0 +1,140 @@
+/* ==================
+ 边框
+ ==================== */
+/* -- 实线 -- */
+.border {
+ overflow: initial !important;
+ @at-root [class*='border'],
+ [class*='dashed'] {
+ position: relative;
+ &.dline {
+ --ui-Border: var(--ui-BG-3);
+ }
+ &::after {
+ content: ' ';
+ width: 200%;
+ height: 200%;
+ position: absolute;
+ z-index: 0;
+ top: 0;
+ left: 0;
+ transform: scale(0.5);
+ transform-origin: 0 0;
+ pointer-events: none;
+ box-sizing: border-box;
+ border-radius: inherit;
+ }
+ &.radius::after {
+ border-radius: calc(#{$radius} * 2);
+ }
+ &.round::after {
+ border-radius: #{$round-pill};
+ }
+ }
+ &::after {
+ border: 1px solid var(--ui-Border);
+ }
+ &s::after {
+ border: 4rpx solid var(--ui-Border);
+ }
+ &ss::after {
+ border: 8rpx solid var(--ui-Border);
+ }
+ @each $value in (top, right, bottom, left) {
+ &-#{$value}::after {
+ border-#{$value}: 1px solid var(--ui-Border);
+ }
+ &s-#{$value}::after {
+ border-#{$value}: 4rpx solid var(--ui-Border);
+ }
+ &ss-#{$value}::after {
+ border-#{$value}: 8rpx solid var(--ui-Border);
+ }
+ }
+}
+/* -- 虚线 -- */
+.dashed {
+ &::after {
+ border: 4rpx dashed var(--ui-Border);
+ }
+ &s::after {
+ border: 6rpx dashed var(--ui-Border);
+ }
+ @each $value in (top, right, bottom, left) {
+ &-#{$value}::after {
+ border-#{$value}: 4rpx dashed var(--ui-Border);
+ }
+ &s-#{$value}::after {
+ border-#{$value}: 6rpx dashed var(--ui-Border);
+ }
+ }
+}
+@each $color, $value in map-merge($colors, map-merge($darks, $grays)) {
+ .border-#{$color}::after,
+ .border-#{$color}[class*='-shine']::before {
+ border-color: $value !important;
+ }
+}
+@each $value in (a, b, c, d, e) {
+ .main-#{$value}-border::after,
+ .main-#{$value}-border[class*='-shine']::before {
+ border-color: var(--main-#{$value}) !important;
+ }
+}
+.dashed-shine,
+.dasheds-shine {
+ position: relative;
+ overflow: hidden;
+ &::after,
+ &::before {
+ border-style: dashed;
+ border-color: var(--ui-Border);
+ animation: shineafter 1s infinite linear;
+ width: calc(200% + 40px);
+ height: 200%;
+ border-width: 2px 0;
+ }
+ &::before {
+ content: ' ';
+ position: absolute;
+ transform: scale(0.5);
+ transform-origin: 0 0;
+ pointer-events: none;
+ box-sizing: border-box;
+ animation: shinebefore 1s infinite linear;
+ width: 200%;
+ height: calc(200% + 40px);
+ border-width: 0 2px;
+ }
+}
+.dasheds-shine {
+ &::after,
+ &::before {
+ border-width: 4px 0;
+ }
+ &::before {
+ border-width: 0 4px;
+ }
+}
+
+@keyframes shineafter {
+ 0% {
+ top: 0;
+ left: -22px;
+ }
+ 100% {
+ top: 0px;
+ left: 0px;
+ }
+}
+
+@keyframes shinebefore {
+ 0% {
+ top: -22px;
+ left: 0;
+ }
+ 100% {
+ top: 0px;
+ left: 0px;
+ }
+}
diff --git a/sheep/scss/style/_button.scss b/sheep/scss/style/_button.scss
new file mode 100644
index 0000000..7069345
--- /dev/null
+++ b/sheep/scss/style/_button.scss
@@ -0,0 +1,87 @@
+.ui-btn-box {
+ display: inline-block;
+}
+.ui-btn {
+ position: relative;
+ border: 0rpx;
+ display: inline-block;
+ align-items: center;
+ justify-content: center;
+ box-sizing: border-box;
+ padding: 0.7857em 1.5em 0.7857em;
+ font-size: 28rpx;
+ line-height: 1em;
+ text-align: center;
+ text-decoration: none;
+ overflow: visible;
+ margin: 0 0.25em 0 0;
+ transform: translate(0rpx, 0rpx);
+ border-radius: $radius;
+ white-space: nowrap;
+ color: var(--text-a);
+ background-color: var(--ui-BG);
+ vertical-align: baseline;
+ &:first-child:last-child {
+ margin: 0;
+ }
+ &:not([class*='round'])::after {
+ border-radius: calc(#{$radius} * 2);
+ }
+ &:not([class*='border'])::after {
+ // content: ' ';
+ // width: 200%;
+ // height: 200%;
+ // display: block;
+ // position: absolute;
+ // z-index: 0;
+ // top: 0;
+ // left: 0;
+ // transform: scale(0.5);
+ // transform-origin: 0 0;
+ // pointer-events: none;
+ // box-sizing: border-box;
+ display: none;
+ }
+ &.round::after {
+ border-radius: #{$round-pill};
+ }
+ &.icon {
+ padding: 0.8em 0.8em;
+ }
+
+ &.sm {
+ font-size: 24rpx;
+ }
+
+ &.lg {
+ font-size: 32rpx;
+ }
+
+ &.xl {
+ font-size: 36rpx;
+ }
+
+ &.block {
+ width: 100%;
+ display: block;
+ font-size: 32rpx;
+ }
+
+ &[disabled] {
+ opacity: 0.6;
+ }
+
+ &.none-style {
+ background-color: transparent !important;
+ position: absolute;
+ width: 100%;
+ height: 100%;
+ top: 0;
+ left: 0;
+ display: flex;
+ }
+}
+
+.ui-btn:not(.icon) [class*='icon-'] {
+ margin: 0 0.25em;
+}
diff --git a/sheep/scss/style/_card.scss b/sheep/scss/style/_card.scss
new file mode 100644
index 0000000..17aa6b3
--- /dev/null
+++ b/sheep/scss/style/_card.scss
@@ -0,0 +1,353 @@
+/* ==================
+ 卡片
+ ==================== */
+
+.ui-cards {
+ display: block;
+ overflow: hidden;
+ & .ui-btn.badge {
+ top: 0;
+ right: 0;
+ font-size: 24rpx;
+ padding: 0rpx 15rpx;
+ height: 40rpx;
+ }
+ &.no-card > .ui-item {
+ margin: 0rpx;
+ border-radius: 0rpx;
+ }
+ & > .ui-item {
+ display: block;
+ overflow: hidden;
+ border-radius: 10rpx;
+ margin: 30rpx;
+ }
+ & > .ui-item.shadow-blur {
+ overflow: initial;
+ }
+ .grid.grid-square {
+ margin-bottom: -20rpx;
+ }
+ &.article {
+ display: block;
+ & > .ui-item {
+ padding: 30rpx;
+ background-color: var(--box-bg);
+ display: flex;
+ align-items: flex-start;
+ }
+ & > .time {
+ padding: 30rpx 0 0 30rpx;
+ }
+ & > .ui-item .title {
+ font-size: 30rpx;
+ font-weight: 900;
+ color: #333333;
+ }
+ & > .ui-item .content {
+ flex: 1;
+ }
+ & > .ui-item > image {
+ width: 240rpx;
+ height: 6.4em;
+ margin-left: 20rpx;
+ border-radius: 6rpx;
+ }
+ & > .ui-item .content .desc {
+ font-size: 12px;
+ color: var(--text-c);
+ }
+ & > .ui-item .content .text-content {
+ font-size: 28rpx;
+ color: #888;
+ }
+ }
+ &.case {
+ .image {
+ position: relative;
+ image {
+ width: 100%;
+ display: block;
+ }
+ .ui-tag {
+ position: absolute;
+ right: 0;
+ top: 0;
+ }
+ .ui-bar {
+ position: absolute;
+ bottom: 0;
+ width: 100%;
+ background-color: transparent;
+ padding: 0rpx 30rpx;
+ }
+ .bg-black {
+ position: absolute;
+ bottom: 0;
+ width: 100%;
+ background-color: rgba(0, 0, 0, 0.6);
+ }
+ }
+ &.no-card .image {
+ margin: 30rpx 30rpx 0;
+ overflow: hidden;
+ border-radius: 10rpx;
+ }
+ }
+ &.dynamic {
+ display: block;
+ & > .ui-item {
+ display: block;
+ overflow: hidden;
+ & > .text-content {
+ padding: 0 30rpx 0;
+ font-size: 30rpx;
+ margin-bottom: 20rpx;
+ }
+ & .square-img {
+ width: 100%;
+ height: 200rpx;
+ border-radius: 6rpx;
+ }
+ & .only-img {
+ width: 100%;
+ height: 320rpx;
+ border-radius: 6rpx;
+ }
+ }
+ }
+ &.goods {
+ display: block;
+ & > .ui-item {
+ padding: 30rpx;
+ display: flex;
+ position: relative;
+ background-color: var(--ui-BG);
+ & + .ui-item {
+ border-top: 1rpx solid #eeeeee;
+ }
+ .content {
+ width: 410rpx;
+ padding: 0rpx;
+ }
+ .title {
+ font-size: 30rpx;
+ font-weight: 900;
+ color: #333333;
+ line-height: 1.4;
+ height: 1.4em;
+ overflow: hidden;
+ }
+ }
+ &.col-goods.col-twice {
+ display: flex;
+ flex-wrap: wrap;
+ padding-bottom: 30rpx;
+ & > .ui-item {
+ width: calc(50% - 30rpx);
+ margin: 20rpx 20rpx 0rpx 20rpx;
+ .content {
+ padding: 20rpx;
+ }
+ }
+ & > .ui-item:nth-child(2n) {
+ margin-left: 0rpx;
+ }
+ }
+ &.col-goods > .ui-item {
+ padding: 0rpx;
+ display: block;
+ border: 0px;
+ .content {
+ width: 100%;
+ padding: 30rpx;
+ }
+ }
+ &.no-card > .ui-item .content {
+ width: 470rpx;
+ padding: 0rpx;
+ }
+ &.no-card > .ui-item .title,
+ &.col-goods > .ui-item .title {
+ height: 3em;
+ overflow: hidden;
+ }
+ & > .ui-item .text-linecut-2 {
+ -webkit-line-clamp: 1;
+ }
+ &.no-card > .ui-item .text-linecut-2,
+ &.col-goods > .ui-item .text-linecut-2 {
+ -webkit-line-clamp: 2;
+ line-height: 1.6em;
+ height: 3.2em;
+ }
+ & > .ui-item > image {
+ width: 200rpx;
+ height: 200rpx;
+ margin-right: 20rpx;
+ border-radius: 6rpx;
+ }
+ &.no-card > .ui-item > image {
+ width: 220rpx;
+ height: 170rpx;
+ }
+ &.col-goods > .ui-item > image {
+ width: 100%;
+ height: 340rpx;
+ border-bottom-left-radius: 0rpx;
+ border-bottom-right-radius: 0rpx;
+ display: block;
+ }
+ &.col-goods.col-twice > .ui-item > image {
+ height: 236rpx;
+ }
+ }
+ &.loan {
+ display: block;
+ & > .ui-item {
+ padding: 30rpx 0 30rpx 30rpx;
+ display: flex;
+ position: relative;
+ background-color: var(--box-bg);
+
+ .content {
+ width: 450rpx;
+ padding: 0rpx;
+ .tag-list {
+ width: 450rpx;
+ display: flex;
+ flex-wrap: wrap;
+ font-size: 12px;
+ margin-top: 18rpx;
+ }
+ }
+ .action {
+ flex: 1;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ flex-direction: column;
+ }
+ }
+ }
+ &.houses {
+ display: block;
+ & > .ui-item {
+ padding: 20rpx;
+ display: flex;
+ position: relative;
+ background-color: var(--box-bg);
+ .image {
+ width: 230rpx;
+ height: 180rpx;
+ margin-right: 20rpx;
+ border-radius: 6rpx;
+ }
+ .content {
+ width: 400rpx;
+ padding: 0rpx;
+ .tag-list {
+ width: 400rpx;
+ display: flex;
+ flex-wrap: wrap;
+ font-size: 12px;
+ margin-top: 10rpx;
+ .ui-item {
+ height: 20px;
+ line-height: 20px;
+ }
+ }
+ }
+ .action {
+ flex: 1;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ flex-direction: column;
+ }
+ }
+ }
+
+ &.product {
+ display: flex;
+ flex-wrap: wrap;
+ padding-bottom: 30rpx;
+ & > .ui-item {
+ width: calc(100% - 15rpx);
+ margin: 20rpx 20rpx 0rpx 20rpx;
+ background-color: var(--box-bg);
+ position: relative;
+ box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
+ // display: flex;
+ // flex-wrap: wrap;
+ .content {
+ padding: 20rpx;
+ // width: calc(100% - 345rpx);
+ .text-cut {
+ font-size: 16px;
+ }
+ }
+ .image {
+ width: 100%;
+ height: 240rpx;
+ border-radius: 6rpx 0 0 6rpx;
+ display: block;
+ }
+ .ui-progress-tag {
+ width: 4em;
+ text-align: right;
+ font-size: 12px;
+ }
+ .border-top {
+ width: 100%;
+ }
+ .ui-tag {
+ position: absolute;
+ top: 0;
+ left: 0;
+ border-radius: 6rpx 0 6rpx 0;
+ }
+ }
+ // & > .ui-item:nth-child(2n) {
+ // margin-left: 0rpx;
+ // }
+ }
+ &.shop {
+ display: flex;
+ flex-wrap: wrap;
+ padding-bottom: 30rpx;
+ & > .ui-item {
+ width: calc(50% - 30rpx);
+ margin: 20rpx 20rpx 0rpx 20rpx;
+ background-color: var(--box-bg);
+ padding: 20rpx;
+ .content {
+ margin-top: 15rpx;
+ }
+ .image {
+ width: 100%;
+ height: 285rpx;
+ border-radius: 6rpx;
+ display: block;
+ }
+ }
+ & > .ui-item:nth-child(2n) {
+ margin-left: 0rpx;
+ }
+ }
+
+ &.orders .ui-item {
+ margin-top: 30rpx;
+ .address-box {
+ padding: 15rpx;
+ margin: 0 30rpx 30rpx;
+ border: 1px solid;
+ border-color: var(--main-a);
+ border-radius: 10px;
+ position: relative;
+ .ui-form-group {
+ min-height: 10px;
+ }
+ }
+ }
+}
diff --git a/sheep/scss/style/_code.scss b/sheep/scss/style/_code.scss
new file mode 100644
index 0000000..5221c88
--- /dev/null
+++ b/sheep/scss/style/_code.scss
@@ -0,0 +1,55 @@
+.ui-code {
+ font-family: Monaco, Menlo, Consolas, 'Courier New';
+ font-size: 90%;
+ position: relative;
+ z-index: 1;
+ color: var(--ui-TC);
+ .ui-rich-text {
+ display: inline-block;
+ }
+
+ &.code {
+ display: inline-block;
+ padding: 0 10rpx;
+ margin: 0 10rpx;
+ border-radius: $radius-sm;
+ line-height: 1.6;
+ vertical-align: baseline;
+ }
+
+ &.pre {
+ display: block;
+ margin: 1em 0;
+ line-height: 1.6;
+ &.hasTitle {
+ margin: 3.2em 0 1em;
+ }
+ // border-radius: $radius-sm;
+ .ui-code-title {
+ position: absolute;
+ top: -2.2em;
+ color: var(--ui-TC-2);
+ left: 0;
+ }
+ .ui-rich-text {
+ padding: 40rpx;
+ white-space: pre-wrap;
+ word-break: break-all;
+ word-wrap: break-word;
+ }
+ .ui-scroll-view {
+ &.ui-scroll {
+ max-height: 500px;
+ white-space: pre;
+ }
+ }
+ .ui-copy-btn {
+ position: absolute;
+ z-index: 2;
+ top: 0;
+ right: 0;
+ padding: 0.8em;
+ border-radius: 0 $radius-sm 0 $radius-sm;
+ }
+ }
+}
diff --git a/sheep/scss/style/_flex.scss b/sheep/scss/style/_flex.scss
new file mode 100644
index 0000000..1daa45b
--- /dev/null
+++ b/sheep/scss/style/_flex.scss
@@ -0,0 +1,79 @@
+/* ==================
+ 弹性布局
+ ==================== */
+.flex {
+ display: flex !important;
+ &-sub {
+ flex: 1 !important;
+ }
+ &-twice {
+ flex: 2 !important;
+ }
+ &-treble {
+ flex: 3 !important;
+ }
+ &-column {
+ flex-direction: column !important;
+ }
+ &-row {
+ flex-direction: row !important;
+ }
+ &-column-reverse {
+ flex-direction: column-reverse !important;
+ }
+ &-row-reverse {
+ flex-direction: row-reverse !important;
+ }
+ &-wrap {
+ flex-wrap: wrap !important;
+ }
+ &-center {
+ @include flex-center;
+ }
+ &-bar {
+ @include flex-bar;
+ }
+}
+.basis {
+ @each $class, $value in (xs: 20%, sm: 40%, df: 50%, lg: 60%, xl: 80%) {
+ &-#{$class} {
+ flex-basis: $value !important;
+ }
+ }
+}
+.align {
+ @each $class,
+ $value
+ in (start: flex-start, end: flex-end, center: center, stretch: stretch, baseline: baseline)
+ {
+ &-#{$class} {
+ align-items: $value !important;
+ }
+ }
+}
+.self {
+ @each $class,
+ $value
+ in (start: flex-start, end: flex-end, center: center, stretch: stretch, baseline: baseline)
+ {
+ &-#{$class} {
+ align-self: $value !important;
+ }
+ }
+}
+.justify {
+ @each $class,
+ $value
+ in (
+ start: flex-start,
+ end: flex-end,
+ center: center,
+ between: space-between,
+ around: space-around
+ )
+ {
+ &-#{$class} {
+ justify-content: $value !important;
+ }
+ }
+}
diff --git a/sheep/scss/style/_form.scss b/sheep/scss/style/_form.scss
new file mode 100644
index 0000000..91d3eb3
--- /dev/null
+++ b/sheep/scss/style/_form.scss
@@ -0,0 +1,121 @@
+/* ==================
+ 表单
+ ==================== */
+.ui-form-item {
+ padding: 1rpx 24rpx;
+ display: flex;
+ align-items: center;
+ min-height: 100rpx;
+ justify-content: space-between;
+ .title {
+ text-align: justify;
+ padding-right: 30rpx;
+ font-size: 30rpx;
+ position: relative;
+ height: 60rpx;
+ line-height: 60rpx;
+ }
+ .content {
+ flex: 1;
+ }
+ input,
+ ui-input {
+ flex: 1;
+ font-size: 30rpx;
+ color: #555;
+ padding-right: 20rpx;
+ }
+ text[class*='icon-'] {
+ font-size: 36rpx;
+ padding: 0;
+ box-sizing: border-box;
+ }
+ textarea {
+ margin: 32rpx 0 30rpx;
+ height: 4.6em;
+ width: 100%;
+ line-height: 1.2em;
+ flex: 1;
+ font-size: 28rpx;
+ padding: 0;
+ }
+ picker,
+ .arrow {
+ flex: 1;
+ padding-right: 40rpx;
+ overflow: hidden;
+ position: relative;
+ }
+ picker .picker,
+ .arrow > view {
+ line-height: 100rpx;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ overflow: hidden;
+ width: 100%;
+ }
+ picker::after,
+ .arrow::after {
+ font-family: 'ui';
+ display: block;
+ content: '\e605';
+ position: absolute;
+ font-size: 34rpx;
+ color: #8799a3;
+ line-height: 100rpx;
+ width: 60rpx;
+ text-align: center;
+ top: 0;
+ bottom: 0;
+ right: -20rpx;
+ margin: auto;
+ }
+ textarea[disabled],
+ textarea[disabled] .placeholder {
+ color: transparent;
+ }
+ &.align-start .title {
+ height: 1em;
+ margin-top: 32rpx;
+ line-height: 1em;
+ }
+ .grid-square {
+ > view {
+ background-color: #f8f8f8;
+ border-radius: 12rpx;
+ .mask {
+ background-color: rgba(0, 0, 0, 0.6);
+ position: absolute;
+ font-size: 20rpx;
+ color: #ffffff;
+ width: 100%;
+ bottom: 0;
+ text-align: center;
+ padding: 6rpx 0;
+ &.red-mask {
+ background-color: rgba(255, 80, 80, 0.6);
+ }
+ }
+ [class*='icon'] {
+ position: absolute;
+ width: 100%;
+ height: 100%;
+ display: flex;
+ align-items: center;
+ transform: scale(1.5);
+ justify-content: center;
+ }
+ .text-gray {
+ position: absolute;
+ width: 100%;
+ font-size: 24rpx;
+ text-align: center;
+ bottom: 20rpx;
+ }
+ }
+ }
+}
+.disabled {
+ opacity: 0.6;
+ cursor: not-allowed !important;
+}
diff --git a/sheep/scss/style/_grid.scss b/sheep/scss/style/_grid.scss
new file mode 100644
index 0000000..b1b5230
--- /dev/null
+++ b/sheep/scss/style/_grid.scss
@@ -0,0 +1,103 @@
+/* ==================
+ 栅栏
+ ==================== */
+@use 'sass:math';
+
+@mixin make_col($screen) {
+ @for $i from 1 through 12 {
+ .ui-col-#{$screen}-#{$i} {
+ width: calc(100% / 12 * #{$i});
+ }
+ .ui-cols-#{$screen}-#{$i} .ui-item {
+ width: calc(100% / #{$i});
+ }
+ }
+}
+.ui-container {
+ box-sizing: border-box;
+ margin-left: auto;
+ margin-right: auto;
+ padding-left: 30rpx;
+ padding-right: 30rpx;
+ width: 100%;
+ max-width: 1440px;
+ &-fluid {
+ max-width: 100%;
+ padding-left: 0;
+ padding-right: 0;
+ }
+}
+.ui-grid {
+ display: flex;
+ flex-wrap: wrap;
+ &.multi-column {
+ display: block;
+ column-count: 2;
+ column-width: 0px;
+ column-gap: 0px;
+ > .ui-item {
+ break-inside: avoid;
+ padding: 0.001em;
+ }
+ }
+ &.grid-square {
+ overflow: hidden;
+ > .ui-item {
+ margin-right: 20rpx;
+ margin-bottom: 20rpx;
+ position: relative;
+ overflow: hidden;
+ }
+ @for $i from 1 through 12 {
+ &.ui-cols-#{$i} > .ui-item {
+ padding-bottom: calc((100% - #{20rpx * ($i - 1)}) / #{$i});
+ height: 0;
+ width: calc((100% - #{20rpx * ($i - 1)}) / #{$i});
+ }
+ }
+ @for $i from 1 through 12 {
+ &.ui-cols-#{$i} > .ui-item:nth-child(#{$i}n) {
+ margin-right: 0;
+ }
+ }
+ }
+}
+@for $i from 1 through 12 {
+ .ui-cols-#{$i} .ui-item {
+ width: calc(100% / #{$i});
+ }
+}
+@for $i from 1 through 12 {
+ .ui-col-#{$i} {
+ width: calc(100% / 12 * #{$i});
+ }
+}
+// 小屏
+@media screen and (min-width: 0px) {
+ @include make_col('xs');
+}
+
+// 小屏
+@media screen and (min-width: 320px) {
+ @include make_col('sm');
+}
+
+// 中屏
+@media screen and (min-width: 768px) {
+ @include make_col('md');
+}
+
+// 普通屏
+@media screen and (min-width: 1025px) {
+ @include make_col('lg');
+}
+
+// 大屏
+@media screen and (min-width: 1440px) {
+ @include make_col('xl');
+}
+
+// 超大屏
+@media screen and (min-width: 1920px) {
+ @include make_col('xxl');
+}
diff --git a/sheep/scss/style/_markdown.scss b/sheep/scss/style/_markdown.scss
new file mode 100644
index 0000000..37b023d
--- /dev/null
+++ b/sheep/scss/style/_markdown.scss
@@ -0,0 +1,62 @@
+.cu-markdown {
+ position: relative;
+ z-index: 1;
+ &.selectable {
+ cursor: auto;
+ user-select: text;
+ }
+ inline {
+ display: inline-block;
+ }
+
+ .list {
+ .list-item {
+ line-height: 1.8;
+ .list {
+ margin-left: 1.28571em;
+ .ui-title {
+ transform: scale(0.6);
+ &:before {
+ content: '\e716';
+ }
+ }
+ }
+ }
+ .list-item-p {
+ position: relative;
+ padding-left: 1.5em;
+ .list-item-t {
+ display: block;
+ width: 1.3em;
+ text-align: center;
+ position: absolute;
+ left: 0;
+ }
+ }
+ }
+ .md-table + .md-table {
+ margin-top: 30rpx;
+ }
+}
+
+.paragraph {
+ margin: 0 0 40rpx;
+ line-height: 1.8;
+}
+
+.blockquote {
+ @extend .paragraph;
+ padding: 20rpx 30rpx;
+ border-left-style: solid;
+ border-left-width: 10rpx;
+ border-color: var(--ui-Border);
+ background: none repeat scroll 0 0 rgba(102, 128, 153, 0.05);
+
+ .paragraph {
+ margin-bottom: 30rpx;
+ }
+
+ .paragraph:last-child {
+ margin-bottom: 0;
+ }
+}
diff --git a/sheep/scss/style/_menu.scss b/sheep/scss/style/_menu.scss
new file mode 100644
index 0000000..a4a8282
--- /dev/null
+++ b/sheep/scss/style/_menu.scss
@@ -0,0 +1,54 @@
+.ui-menu {
+ background-color: var(--ui-BG);
+}
+
+.ui-menu-item {
+ position: relative;
+ @include flex-bar;
+ min-height: 4em;
+ padding: 0 30rpx;
+ .ui-menu-item-icon {
+ width: 1.7em;
+ margin-right: 0.3em;
+ position: relative;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ transform: scale(1.3);
+ }
+ .ui-menu-item-icon .ui-menu-item-image {
+ width: 1.2em;
+ height: 1.2em;
+ display: inline-block;
+ }
+ .ui-menu-item-content {
+ flex: 1;
+ position: relative;
+ @include flex-bar;
+ }
+ .ui-menu-item-arrow {
+ width: 1.6em;
+ text-align: center;
+ color: var(--ui-TC-3);
+ }
+ &::after {
+ content: ' ';
+ width: calc(200% - 120rpx);
+ left: 30rpx;
+ position: absolute;
+ top: 0;
+ box-sizing: border-box;
+ height: 200%;
+ border-top: 1px solid var(--ui-Border);
+ border-radius: inherit;
+ transform: scale(1);
+ transform-origin: 0 0;
+ pointer-events: none;
+ }
+ &.first-item::after {
+ display: none;
+ }
+ &:first-child::after {
+ display: none;
+ }
+}
diff --git a/sheep/scss/style/_shadow.scss b/sheep/scss/style/_shadow.scss
new file mode 100644
index 0000000..27cb3f6
--- /dev/null
+++ b/sheep/scss/style/_shadow.scss
@@ -0,0 +1,90 @@
+/* ==================
+ 阴影
+ ==================== */
+
+.shadow {
+ box-shadow: var(--ui-Shadow);
+ &-sm {
+ box-shadow: var(--ui-Shadow-sm);
+ }
+ &-lg {
+ box-shadow: var(--ui-Shadow-lg);
+ }
+ &-inset {
+ box-shadow: var(--ui-Shadow-inset);
+ }
+ @each $color, $value in $colors {
+ @at-root .shadow-#{$color} {
+ box-shadow: 0 0.5em 1em rgba($value, var(--ui-Shadow-opacity));
+ }
+ &-sm.shadow-#{$color} {
+ box-shadow: 0 0.125em 0.25em rgba($value, var(--ui-Shadow-opacity));
+ }
+ &-lg.shadow-#{$color} {
+ box-shadow: 0 1em 3em rgba($value, var(--ui-Shadow-opacity-lg));
+ }
+ }
+
+ &-warp {
+ position: relative;
+ }
+ &-warp:before,
+ &-warp:after {
+ position: absolute;
+ content: '';
+ bottom: -10rpx;
+ left: 20rpx;
+ width: calc(50% - #{40rpx});
+ height: 30rpx;
+ transform: skew(0deg, -6deg);
+ transform-origin: 50% 50%;
+ background-color: rgba(0, 0, 0, var(--ui-Shadow-opacity));
+ filter: blur(20rpx);
+ z-index: -1;
+ opacity: 0.5;
+ }
+ &-warp:after {
+ right: 20rpx;
+ left: auto;
+ transform: skew(0deg, 6deg);
+ }
+ &-blur {
+ position: relative;
+ }
+ &-blur::before {
+ content: '';
+ display: block;
+ background: inherit;
+ filter: blur(20rpx);
+ position: absolute;
+ width: 100%;
+ height: 100%;
+ top: 0.5em;
+ left: 0.5em;
+ z-index: -1;
+ opacity: var(--ui-Shadow-opacity-lg);
+ transform-origin: 0 0;
+ border-radius: inherit;
+ transform: scale(1, 1);
+ }
+}
+.drop-shadow {
+ filter: drop-shadow(0 0 30rpx rgba(0, 0, 0, 0.1));
+ &-sm {
+ filter: drop-shadow(0 4rpx 4rpx rgba(0, 0, 0, 0.06));
+ }
+ &-lg {
+ filter: drop-shadow(0 30rpx 60rpx rgba(0, 0, 0, 0.2));
+ }
+ @each $color, $value in $colors {
+ @at-root .drop-shadow-#{$color} {
+ filter: drop-shadow(0 15rpx 15rpx rgba(darken($value, 10%), 0.3));
+ }
+ &-sm.drop-shadow-#{$color} {
+ filter: drop-shadow(0 4rpx 4rpx rgba(darken($value, 10%), 0.3));
+ }
+ &-lg.drop-shadow-#{$color} {
+ filter: drop-shadow(0 50rpx 100rpx rgba(darken($value, 10%), 0.2));
+ }
+ }
+}
diff --git a/sheep/scss/style/_table.scss b/sheep/scss/style/_table.scss
new file mode 100644
index 0000000..ad5effa
--- /dev/null
+++ b/sheep/scss/style/_table.scss
@@ -0,0 +1,133 @@
+.ui-table {
+ background-color: var(--ui-BG);
+ max-width: 100%;
+ display: table;
+ &.table-full {
+ width: 100%;
+ }
+ &.table-radius {
+ border-radius: $radius;
+ .ui-table-header {
+ .ui-table-tr {
+ border-top-left-radius: $radius;
+ border-top-right-radius: $radius;
+ }
+ .ui-table-th {
+ &:first-child {
+ border-top-left-radius: $radius;
+ }
+ &:last-child {
+ border-top-right-radius: $radius;
+ }
+ }
+ }
+ }
+ .ui-table-header {
+ display: table-header-group;
+ .ui-table-th {
+ font-weight: bold;
+ border-bottom: 1px solid var(--ui-Border);
+ white-space: nowrap;
+
+ padding: 1em 0.8em;
+ }
+ }
+
+ .ui-table-tr {
+ display: table-row;
+ z-index: 1;
+ }
+
+ .ui-table-body {
+ display: table-row-group;
+ position: relative;
+ .ui-table-tr:hover {
+ background-color: var(--ui-BG-1) !important;
+ }
+ .ui-table-loading {
+ min-height: 300px;
+ position: absolute !important;
+ width: 100%;
+ height: 100%;
+ z-index: 2;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ border: 1px solid var(--ui-Border);
+ }
+ }
+
+ .ui-table-td,
+ .ui-table-th {
+ display: table-cell;
+ text-align: unset;
+ padding: 0.5em 0.8em;
+ // font-size: 90%;
+ vertical-align: middle;
+ }
+}
+
+.ui-table.table-border {
+ &,
+ & .ui-table-td,
+ & .ui-table-th {
+ position: relative;
+ &::after {
+ content: ' ';
+ width: 200%;
+ height: 200%;
+ position: absolute;
+ top: 0;
+ left: 0;
+ border-radius: inherit;
+ transform: scale(0.5);
+ transform-origin: 0 0;
+ pointer-events: none;
+ box-sizing: border-box;
+ border: 1px solid var(--ui-Border);
+ z-index: 1;
+ }
+ }
+ .ui-table-td,
+ .ui-table-th {
+ &::after {
+ border-width: 1px 1px 0 0;
+ }
+ &:last-child::after {
+ border-right: none;
+ }
+ }
+}
+.ui-table.table-radius {
+ &::after {
+ border-radius: calc(#{$radius} * 2);
+ }
+ & .ui-table-tr .ui-table-th:first-child {
+ border-top-left-radius: calc(#{$radius} * 2);
+ }
+ & .ui-table-tr .ui-table-th:last-child {
+ border-top-right-radius: calc(#{$radius} * 2);
+ }
+ & .ui-table-tr:last-child .ui-table-td:first-child {
+ border-bottom-left-radius: #{$radius};
+ }
+ & .ui-table-tr:last-child .ui-table-td:last-child {
+ border-bottom-right-radius: #{$radius};
+ }
+}
+.ui-table.table-striped > .ui-table-body > .ui-table-tr:nth-child(2n + 1),
+.ui-table.table-striped > .ui-table-body > .ui-table-tr:nth-child(2n + 1) {
+ background-color: var(--ui-BG-1);
+}
+
+.table-responsive {
+ width: inherit;
+ height: 100%;
+ max-width: 100%;
+ overflow: hidden;
+ box-sizing: border-box;
+ .table-responsive-box {
+ position: relative;
+ overflow: hidden;
+ }
+}
diff --git a/sheep/scss/style/_tag.scss b/sheep/scss/style/_tag.scss
new file mode 100644
index 0000000..e69de29
diff --git a/sheep/scss/style/_text.scss b/sheep/scss/style/_text.scss
new file mode 100644
index 0000000..8249022
--- /dev/null
+++ b/sheep/scss/style/_text.scss
@@ -0,0 +1,104 @@
+/* ==================
+ 文本
+ ==================== */
+@use 'sass:math';
+.font-0 {
+ font-size: 24rpx;
+ --textSize: -4rpx;
+}
+.font-1 {
+ font-size: 28rpx;
+ --textSize: 0rpx;
+}
+.font-2 {
+ font-size: 32rpx;
+ --textSize: 4rpx;
+}
+.font-3 {
+ font-size: 36rpx;
+ --textSize: 8rpx;
+}
+.font-4 {
+ font-size: 40rpx;
+ --textSize: 12rpx;
+}
+.text {
+ @each $class, $value in $fontsize {
+ &-#{$class},
+ &-#{math.div($value ,2)} {
+ font-size: calc(#{$value}rpx + var(--textSize)) !important;
+ }
+ }
+ &-cut {
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ overflow: hidden;
+ }
+ @at-root [class*='text-linecut'] {
+ display: -webkit-box;
+ -webkit-box-orient: vertical;
+ -webkit-line-clamp: 2;
+ overflow: hidden;
+ word-break: break-all;
+ }
+ @for $i from 2 through 10 {
+ &-linecut-#{$i} {
+ -webkit-line-clamp: #{$i};
+ }
+ }
+ &-justify {
+ text-align: justify;
+ }
+ &-justify-line {
+ text-align: justify;
+ line-height: 0.5em;
+ margin-top: 0.5em;
+ &::after {
+ content: '.';
+ display: inline-block;
+ width: 100%;
+ }
+ }
+
+ &-Abc {
+ text-transform: Capitalize !important;
+ }
+ &-ABC {
+ text-transform: Uppercase !important;
+ }
+ &-abc {
+ text-transform: Lowercase !important;
+ }
+ &-del,
+ &-line {
+ text-decoration: line-through !important;
+ }
+ &-bottomline {
+ text-decoration: underline !important;
+ }
+ &-italic {
+ font-style: italic !important;
+ }
+ &-style-none {
+ text-decoration: none !important;
+ }
+ &-break {
+ word-break: break-word !important;
+ overflow-wrap: break-word !important;
+ }
+ &-reset {
+ color: inherit !important;
+ }
+ &-price::before {
+ content: '¥';
+ font-size: 80%;
+ margin-right: 4rpx;
+ }
+ &-hide {
+ font: 0/0 a;
+ color: transparent;
+ text-shadow: none;
+ background-color: transparent;
+ border: 0;
+ }
+}
diff --git a/sheep/scss/theme/_dark.scss b/sheep/scss/theme/_dark.scss
new file mode 100644
index 0000000..8caad17
--- /dev/null
+++ b/sheep/scss/theme/_dark.scss
@@ -0,0 +1,39 @@
+// 核心主题样式文件
+@mixin theme-dark {
+ // 背景色
+ --ui-BG: #393939;
+ --ui-BG-1: #333333;
+ --ui-BG-2: #2c2c2c;
+ --ui-BG-3: #292929;
+ --ui-BG-4: #222222;
+
+ // 文本色
+ --ui-TC: #ffffff;
+ --ui-TC-1: #d4d4d4;
+ --ui-TC-2: #919191;
+ --ui-TC-3: #6a6a6a;
+ --ui-TC-4: #474747;
+
+ // 模糊
+ --ui-Blur: rgba(38, 38, 38, 0.98);
+ --ui-Blur-1: rgba(38, 38, 38, 0.75);
+ --ui-Blur-2: rgba(38, 38, 38, 0.25);
+ --ui-Blur-3: rgba(38, 38, 38, 0.05);
+
+ // 边框
+ --ui-Border: rgba(119, 119, 119, 0.25);
+ --ui-Outline: rgba(255, 255, 255, 0.1);
+ --ui-Line: rgba(119, 119, 119, 0.25);
+
+ // 透明与阴影
+ --ui-Shadow: 0 0.5em 1em rgba(0, 0, 0, 0.45);
+ --ui-Shadow-sm: 0 0.125em 0.25em rgba(0, 0, 0, 0.475);
+ --ui-Shadow-lg: 0 1em 3em rgba(0, 0, 0, 0.475);
+ --ui-Shadow-inset: inset 0 1px 2px rgba(0, 0, 0, 0.475);
+
+ --ui-Shadow-opacity: 0.55;
+ --ui-Shadow-opacity-sm: 0.175;
+ --ui-Shadow-opacity-lg: 0.75;
+
+ --ui-BG-opacity: 0.1;
+}
diff --git a/sheep/scss/theme/_light.scss b/sheep/scss/theme/_light.scss
new file mode 100644
index 0000000..af5f245
--- /dev/null
+++ b/sheep/scss/theme/_light.scss
@@ -0,0 +1,39 @@
+// 核心主题样式文件
+@mixin theme-light {
+ // 背景色
+ --ui-BG: #ffffff;
+ --ui-BG-1: #f6f6f6;
+ --ui-BG-2: #f1f1f1;
+ --ui-BG-3: #e8e8e8;
+ --ui-BG-4: #e0e0e0;
+
+ // 文本色
+ --ui-TC: #303030;
+ --ui-TC-1: #525252;
+ --ui-TC-2: #777777;
+ --ui-TC-3: #9e9e9e;
+ --ui-TC-4: #c6c6c6;
+
+ // 模糊
+ --ui-Blur: rgba(255, 255, 255, 0.98);
+ --ui-Blur-1: rgba(255, 255, 255, 0.75);
+ --ui-Blur-2: rgba(255, 255, 255, 0.25);
+ --ui-Blur-3: rgba(255, 255, 255, 0.05);
+
+ // 边框
+ --ui-Border: rgba(119, 119, 119, 0.25);
+ --ui-Outline: rgba(0, 0, 0, 0.1);
+ --ui-Line: rgba(119, 119, 119, 0.25);
+
+ // 透明与阴影
+ --ui-Shadow: 0 0.5em 1em rgba(0, 0, 0, 0.15);
+ --ui-Shadow-sm: 0 0.125em 0.25em rgba(0, 0, 0, 0.075);
+ --ui-Shadow-lg: 0 1em 3em rgba(0, 0, 0, 0.175);
+ --ui-Shadow-inset: inset 0 0.1em 0.2em rgba(0, 0, 0, 0.075);
+
+ --ui-Shadow-opacity: 0.45;
+ --ui-Shadow-opacity-sm: 0.075;
+ --ui-Shadow-opacity-lg: 0.65;
+
+ --ui-BG-opacity: 0.1;
+}
diff --git a/sheep/scss/theme/_style.scss b/sheep/scss/theme/_style.scss
new file mode 100644
index 0000000..1eef587
--- /dev/null
+++ b/sheep/scss/theme/_style.scss
@@ -0,0 +1,68 @@
+@import './light'; //浅蓝主题
+@import './dark'; //深蓝主题
+// 多主题
+.theme-light {
+ @include theme-light;
+}
+.theme-dark {
+ @include theme-dark;
+}
+.theme-auto {
+ @include theme-light;
+}
+@media (prefers-color-scheme: dark) {
+ .theme-auto {
+ @include theme-dark;
+ }
+}
+
+@each $value in ('', '-1', '-2', '-3', '-4') {
+ // 背景色 + 文字色 : 白色 + 默认色;
+ .ui-BG#{$value} {
+ background-color: var(--ui-BG#{$value}) !important;
+ color: var(--ui-TC);
+ }
+ // 文字颜色
+ .ui-TC#{$value} {
+ color: var(--ui-TC#{$value}) !important;
+ }
+ // 主题色背景
+ .ui-BG-Main#{$value} {
+ background-color: var(--ui-BG-Main#{$value}) !important;
+ color: var(--ui-BG-Main-TC) !important;
+ }
+ // 主题色渐变,横向
+ .ui-BG-Main-Gradient {
+ background: linear-gradient(90deg, var(--ui-BG-Main), var(--ui-BG-Main-gradient)) !important;
+ color: var(--ui-BG-Main-TC) !important;
+ }
+ // 主题色文字
+ .ui-TC-Main#{$value} {
+ color: var(--ui-BG-Main#{$value}) !important;
+ }
+ // 主题色阴影
+ .ui-Shadow-Main {
+ box-shadow: var(--ui-Main-box-shadow) !important;
+ }
+ .ui-BG-Main-light {
+ background: var(----ui-BG-Main-light) !important;
+ color: var(--ui-BG-Main#{$value}) !important;
+ }
+}
+
+@each $color, $value in $colors {
+ .main-#{$color} {
+ --ui-BG-Main: #{$value};
+ --ui-BG-Main-tag: #{rgba($value, 0.05)};
+ --ui-BG-Main-gradient: #{rgba($value, 0.6)};
+ --ui-BG-Main-light: #{rgba($value, 0.2)};
+ --ui-BG-Main-opacity-1: #{rgba($value, 0.1)};
+ --ui-BG-Main-opacity-4: #{rgba($value, 0.4)};
+ --ui-Main-box-shadow: 0 0.2em 0.5em #{rgba($value, var(--ui-Shadow-opacity))};
+ --ui-BG-Main-1: #{mix(rgba(255, 255, 255, 0.7), desaturate($value, 20%), 10%)};
+ --ui-BG-Main-2: #{mix(rgba(255, 255, 255, 0.6), desaturate($value, 40%), 20%)};
+ --ui-BG-Main-3: #{mix(rgba(119, 119, 119, 0.2), desaturate($value, 40%), 40%)};
+ --ui-BG-Main-4: #{mix(rgba(119, 119, 119, 0.1), desaturate($value, 40%), 60%)};
+ --ui-BG-Main-TC: #ffffff !important;
+ }
+}
diff --git a/sheep/scss/ui.scss b/sheep/scss/ui.scss
new file mode 100644
index 0000000..b9b7381
--- /dev/null
+++ b/sheep/scss/ui.scss
@@ -0,0 +1,19 @@
+@import './theme/style'; //系统主题
+@import './main'; //主样式*
+
+@import './style/background'; //背景
+@import './style/grid'; //列
+@import './style/flex'; //布局
+@import './style/border'; //边框
+@import './style/text'; //文本
+@import './style/shadow'; //阴影
+@import './icon/style'; //图标
+@import './style/tag'; //标签
+@import './style/button'; //按钮
+@import './style/avatar'; //头像
+@import './style/table'; //表格
+@import './style/code'; //代码片段
+@import './style/form'; //表单
+@import './style/menu'; //表单
+@import './style/markdown'; //表单
+@import './style/card'; //表单
diff --git a/sheep/store/app.js b/sheep/store/app.js
new file mode 100644
index 0000000..2f95dbe
--- /dev/null
+++ b/sheep/store/app.js
@@ -0,0 +1,134 @@
+import DiyApi from '@/sheep/api/promotion/diy';
+import { defineStore } from 'pinia';
+import $platform from '@/sheep/platform';
+import $router from '@/sheep/router';
+import user from './user';
+import sys from './sys';
+
+const app = defineStore({
+ id: 'app',
+ state: () => ({
+ info: {
+ // 应用信息
+ name: '', // 商城名称
+ logo: '', // logo
+ version: '', // 版本号
+ copyright: '', // 版权信息 I
+ copytime: '', // 版权信息 II
+
+ cdnurl: '', // 云存储域名
+ filesystem: '', // 云存储平台
+ },
+ platform: {
+ share: {
+ methods: [], // 支持的分享方式
+ forwardInfo: {}, // 默认转发信息
+ posterInfo: {}, // 海报信息
+ linkAddress: '', // 复制链接地址
+ },
+ bind_mobile: 0, // 登陆后绑定手机号提醒 (弱提醒,可手动关闭)
+ },
+ template: {
+ // 店铺装修模板
+ basic: {}, // 基本信息
+ home: {
+ // 首页模板
+ style: {},
+ data: [],
+ },
+ user: {
+ // 个人中心模板
+ style: {},
+ data: [],
+ },
+ },
+ shareInfo: {}, // 全局分享信息
+ has_wechat_trade_managed: 0 // 小程序发货信息管理 0 没有 || 1 有
+ }),
+ actions: {
+ // 获取Shopro应用配置和模板
+ async init(templateId = null) {
+ // 检查网络
+ const networkStatus = await $platform.checkNetwork();
+ if (!networkStatus) {
+ $router.error('NetworkError');
+ }
+
+ // 加载装修配置
+ await adaptTemplate(this.template, templateId)
+
+ // TODO 芋艿:未来支持管理后台可配;对应 https://api.shopro.sheepjs.com/shop/api/init
+ if (true) {
+ this.info = {
+ name: '晚趣语音',
+ logo: 'https://rbtnet.oss-cn-hangzhou.aliyuncs.com/aa361225849eeb86428e1a3d647d6f7b94354e74de212403bb968e6ad85e79b3.jpeg',
+ version: '2.2.0',
+ copyright: '上海尔加网络科技提供技术支持',
+ copytime: 'Copyright© 2018-2024',
+
+ cdnurl: 'https://file.sheepjs.com', // 云存储域名
+ filesystem: 'qcloud', // 云存储平台
+ };
+ this.platform = {
+ share: {
+ methods: ["poster", "link"],
+ linkAddress: 'https://peiwan.mfzt.site/h5', // TODO 芋艿:可以考虑改到 .env 那
+ posterInfo: {
+ "user_bg": "/static/img/shop/config/user-poster-bg.png",
+ "goods_bg": "/static/img/shop/config/goods-poster-bg.png",
+ "groupon_bg": "/static/img/shop/config/groupon-poster-bg.png"
+ }
+ },
+ bind_mobile: 0
+ };
+ this.has_wechat_trade_managed = 0;
+
+ // 加载主题
+ const sysStore = sys();
+ sysStore.setTheme();
+
+ // 模拟用户登录
+ const userStore = user();
+ if (userStore.isLogin) {
+ userStore.loginAfter();
+ }
+ return Promise.resolve(true);
+ } else {
+ $router.error('InitError', res.msg || '加载失败');
+ }
+ },
+ },
+ persist: {
+ enabled: true,
+ strategies: [
+ {
+ key: 'app-store',
+ },
+ ],
+ },
+});
+
+// todo: @owen 先做数据适配,后期重构
+const adaptTemplate = async (appTemplate, templateId) => {
+ const { data: diyTemplate } = templateId
+ // 查询指定模板,一般是预览时使用
+ ? await DiyApi.getDiyTemplate(templateId)
+ : await DiyApi.getUsedDiyTemplate();
+ // 模板不存在
+ if (!diyTemplate) {
+ $router.error('TemplateError');
+ return
+ }
+
+ const tabBar = diyTemplate?.property?.tabBar;
+ if (tabBar) {
+ appTemplate.basic.tabbar = tabBar
+ if (tabBar?.theme) {
+ appTemplate.basic.theme = tabBar?.theme;
+ }
+ }
+ appTemplate.home = diyTemplate?.home;
+ appTemplate.user = diyTemplate?.user;
+}
+
+export default app;
diff --git a/sheep/store/cart.js b/sheep/store/cart.js
new file mode 100644
index 0000000..edde779
--- /dev/null
+++ b/sheep/store/cart.js
@@ -0,0 +1,112 @@
+import { defineStore } from 'pinia';
+import CartApi from '@/sheep/api/trade/cart';
+
+const cart = defineStore({
+ id: 'cart',
+ state: () => ({
+ list: [], // 购物车列表
+ selectedIds: [], // 已选列表
+ isAllSelected: false, // 是否全选
+ totalPriceSelected: 0, // 选中项总金额
+ }),
+ actions: {
+ // 获取购物车列表
+ async getList() {
+ const { data, code } = await CartApi.getCartList();
+ if (code === 0) {
+ this.list = data.validList;
+
+ // 计算各种关联属性
+ this.selectedIds = [];
+ this.isAllSelected = true;
+ this.totalPriceSelected = 0;
+ this.list.forEach((item) => {
+ if (item.selected) {
+ this.selectedIds.push(item.id);
+ this.totalPriceSelected += item.count * item.sku.price;
+ } else {
+ this.isAllSelected = false;
+ }
+ });
+ }
+ },
+
+ // 添加购物车
+ async add(goodsInfo) {
+ // 添加购物项
+ const { code } = await CartApi.addCart({
+ skuId: goodsInfo.id,
+ count: goodsInfo.goods_num,
+ });
+ // 刷新购物车列表
+ if (code === 0) {
+ await this.getList();
+ }
+ },
+
+ // 更新购物车
+ async update(goodsInfo) {
+ const { code } = await CartApi.updateCartCount({
+ id: goodsInfo.goods_id,
+ count: goodsInfo.goods_num,
+ });
+ if (code === 0) {
+ await this.getList();
+ }
+ },
+
+ // 移除购物车
+ async delete(ids) {
+ let idsTemp = '';
+ if (Array.isArray(ids)) {
+ idsTemp = ids.join(',');
+ } else {
+ idsTemp = ids;
+ }
+ const { code } = await CartApi.deleteCart(idsTemp);
+ if (code === 0) {
+ await this.getList();
+ }
+ },
+
+ // 单选购物车商品
+ async selectSingle(goodsId) {
+ const { code } = await CartApi.updateCartSelected({
+ ids: [goodsId],
+ selected: !this.selectedIds.includes(goodsId), // 取反
+ });
+ if (code === 0) {
+ await this.getList();
+ }
+ },
+
+ // 全选购物车商品
+ async selectAll(flag) {
+ const { code } = await CartApi.updateCartSelected({
+ ids: this.list.map((item) => item.id),
+ selected: flag
+ });
+ if (code === 0) {
+ await this.getList();
+ }
+ },
+
+ // 清空购物车。注意,仅用于用户退出时,重置数据
+ emptyList() {
+ this.list = [];
+ this.selectedIds = [];
+ this.isAllSelected = true;
+ this.totalPriceSelected = 0;
+ },
+ },
+ persist: {
+ enabled: true,
+ strategies: [
+ {
+ key: 'cart-store',
+ },
+ ],
+ },
+});
+
+export default cart;
diff --git a/sheep/store/index.js b/sheep/store/index.js
new file mode 100644
index 0000000..3d06698
--- /dev/null
+++ b/sheep/store/index.js
@@ -0,0 +1,20 @@
+import { createPinia } from 'pinia';
+import piniaPersist from 'pinia-plugin-persist-uni';
+
+// 自动注入所有pinia模块
+const files = import.meta.glob('./*.js', { eager: true });
+const modules = {};
+Object.keys(files).forEach((key) => {
+ modules[key.replace(/(.*\/)*([^.]+).*/gi, '$2')] = files[key].default;
+});
+
+export const setupPinia = (app) => {
+ const pinia = createPinia();
+ pinia.use(piniaPersist);
+
+ app.use(pinia);
+};
+
+export default (name) => {
+ return modules[name]();
+};
diff --git a/sheep/store/modal.js b/sheep/store/modal.js
new file mode 100644
index 0000000..0cb8383
--- /dev/null
+++ b/sheep/store/modal.js
@@ -0,0 +1,31 @@
+import { defineStore } from 'pinia';
+
+const modal = defineStore({
+ id: 'modal',
+ state: () => ({
+ auth: '', // 授权弹框 accountLogin|smsLogin|resetPassword|changeMobile|changePassword|changeUsername
+ share: false, // 分享弹框
+ menu: false, // 快捷菜单弹框
+ qrcode: false, // 关注公众号
+ search: false, // 搜索弹窗
+ advHistory: [], // 广告弹框记录
+ lastTimer: {
+ // 短信验证码计时器,为了防止刷新请求做了持久化
+ smsLogin: 0,
+ changeMobile: 0,
+ resetPassword: 0,
+ changePassword: 0,
+ }
+ }),
+ persist: {
+ enabled: true,
+ strategies: [
+ {
+ key: 'modal-store',
+ paths: ['lastTimer', 'advHistory'],
+ },
+ ],
+ },
+});
+
+export default modal;
diff --git a/sheep/store/sys.js b/sheep/store/sys.js
new file mode 100644
index 0000000..0ed2240
--- /dev/null
+++ b/sheep/store/sys.js
@@ -0,0 +1,113 @@
+import { defineStore } from 'pinia';
+import app from './app';
+
+const sys = defineStore({
+ id: 'sys',
+ state: () => ({
+ theme: '', // 主题,
+ mode: 'light', // 明亮模式、暗黑模式(暂未支持)
+ modeAuto: false, // 跟随系统
+ fontSize: 1, // 设置默认字号等级(0-4)
+ searchTabs: {
+ sexLabel: '性别',
+ sex2Label: '性别',
+ cityLabel: '城市',
+ categoryLabel: '分类',
+ },
+ categoryList: [],
+ clerk: {},
+ clerkTabIndex: 1,
+ user: {},
+ userTabIndex: 0,
+ homeTabIndex: 0,
+ messageTabIndex: 0,
+
+ currentClerk: {
+ id: -1,
+ avatar: 'https://rbtnet.oss-cn-hangzhou.aliyuncs.com/aa361225849eeb86428e1a3d647d6f7b94354e74de212403bb968e6ad85e79b3.jpeg',
+ },
+ clerkList: [],
+ gift: {
+ id: -1,
+ },
+ giftList: [],
+ scene: "0", // 小程序场景值
+ tradeConfig: {
+ brokerageEnabled: false,
+ weixinEnabled: false,
+ giftEnabled: false,
+ qrcode: '',
+ },
+ }),
+ getters: {},
+ actions: {
+ setTheme(theme = '') {
+ if (theme === '') {
+ this.theme = app().template?.basic.theme || 'orange';
+ } else {
+ this.theme = theme;
+ }
+ },
+ setSexLabel(label) {
+ this.searchTabs.sexLabel = label;
+ },
+ setSex2Label(label) {
+ this.searchTabs.sex2Label = label;
+ },
+ setCityLabel(label) {
+ this.searchTabs.cityLabel = label;
+ },
+ setClerkTabIndex(e) {
+ this.clerkTabIndex = e;
+ },
+ setUserTabIndex(e) {
+ this.userTabIndex = e;
+ },
+ setHomeTabIndex(e) {
+ this.homeTabIndex = e;
+ },
+ setMessageTabIndex(e) {
+ this.messageTabIndex = e;
+ },
+ setCategoryLabel(label) {
+ this.searchTabs.categoryLabel = label;
+ },
+ setCategoryList(list) {
+ this.categoryList = list;
+ },
+ setClerk(o) {
+ this.clerk = o;
+ },
+ setUser(o) {
+ this.user = o;
+ },
+ setCurrentClerk(o) {
+ this.currentClerk = o;
+ },
+ setClerkList(list) {
+ this.clerkList = list;
+ },
+ setGift(e) {
+ this.gift = e;
+ },
+ setGiftList(list) {
+ this.giftList = list;
+ },
+ setScene(scene) {
+ this.scene = scene;
+ },
+ setTradeConfig(config) {
+ this.tradeConfig = config;
+ },
+ },
+ persist: {
+ enabled: true,
+ strategies: [
+ {
+ key: 'sys-store',
+ },
+ ],
+ },
+});
+
+export default sys;
diff --git a/sheep/store/user.js b/sheep/store/user.js
new file mode 100644
index 0000000..25c71d2
--- /dev/null
+++ b/sheep/store/user.js
@@ -0,0 +1,196 @@
+import { defineStore } from 'pinia';
+import $share from '@/sheep/platform/share';
+import { clone, cloneDeep } from 'lodash-es';
+import cart from './cart';
+import app from './app';
+import { showAuthModal } from '@/sheep/hooks/useModal';
+import UserApi from '@/sheep/api/member/user';
+import PayWalletApi from '@/sheep/api/pay/wallet';
+import TradeConfigApi from '@/sheep/api/trade/config';
+import OrderApi from '@/sheep/api/trade/order';
+import CouponApi from '@/sheep/api/promotion/coupon';
+
+// 默认用户信息
+const defaultUserInfo = {
+ id: null,
+ avatar: '', // 头像
+ nickname: '', // 昵称
+ age: 0,
+ sex: 1,
+ visible: false,
+ qrcodeShow: 0,
+ photo: '',
+ gender: 0, // 性别
+ mobile: '', // 手机号
+ point: 0, // 积分
+ isVip: false,
+};
+
+const defaultTradeConfig = {
+ brokerageEnabled: false,
+ weixinEnabled: false,
+ giftEnabled: false,
+ friendEnabled: false,
+ peiwanEnabled: false,
+ adUnitId: '',
+ qrcode: '',
+};
+
+// 默认钱包信息
+const defaultUserWallet = {
+ balance: 0, // 余额
+};
+
+// 默认订单、优惠券等其他资产信息
+const defaultNumData = {
+ unusedCouponCount: 0,
+ orderCount: {
+ allCount: 0,
+ unpaidCount: 0,
+ undeliveredCount: 0,
+ deliveredCount: 0,
+ uncommentedCount: 0,
+ afterSaleCount: 0,
+ },
+};
+
+const user = defineStore({
+ id: 'user',
+ state: () => ({
+ userInfo: clone(defaultUserInfo), // 用户信息
+ tradeConfig: clone(defaultTradeConfig), // 系统配置
+ userWallet: clone(defaultUserWallet), // 用户钱包信息
+ isLogin: !!uni.getStorageSync('token'), // 登录状态
+ numData: cloneDeep(defaultNumData), // 用户其他数据
+ lastUpdateTime: 0, // 上次更新时间
+ }),
+
+ actions: {
+ setTradeConfig(config) {
+ this.tradeConfig = config;
+ },
+ // 获取用户信息
+ async getInfo() {
+ const { code, data } = await UserApi.getUserInfo();
+ if (code !== 0) {
+ return;
+ }
+ this.userInfo = data;
+ return Promise.resolve(data);
+ },
+
+ async getTradeConfig() {
+ const { code, data } = await TradeConfigApi.getTradeConfig(this.userInfo.id);
+ if (code !== 0) {
+ return;
+ }
+ this.tradeConfig = data;
+ },
+
+ // 获得用户钱包
+ async getWallet() {
+ const { code, data } = await PayWalletApi.getPayWallet();
+ if (code !== 0) {
+ return;
+ }
+ this.userWallet = data;
+ },
+
+ // 获取订单、优惠券等其他资产信息
+ getNumData() {
+ OrderApi.getOrderCount().then((res) => {
+ if (res.code === 0) {
+ this.numData.orderCount = res.data;
+ }
+ });
+ CouponApi.getUnusedCouponCount().then((res) => {
+ if (res.code === 0) {
+ this.numData.unusedCouponCount = res.data;
+ }
+ });
+ },
+
+ // 设置 token
+ setToken(token = '', refreshToken = '') {
+ if (token === '') {
+ this.isLogin = false;
+ uni.removeStorageSync('token');
+ uni.removeStorageSync('refresh-token');
+ } else {
+ this.isLogin = true;
+ uni.setStorageSync('token', token);
+ uni.setStorageSync('refresh-token', refreshToken);
+ this.loginAfter();
+ }
+ return this.isLogin;
+ },
+
+ // 更新用户相关信息 (手动限流,5 秒之内不刷新)
+ async updateUserData() {
+ if (!this.isLogin) {
+ this.resetUserData();
+ return;
+ }
+ // 防抖,5 秒之内不刷新
+ const nowTime = new Date().getTime();
+ if (this.lastUpdateTime + 5000 > nowTime) {
+ return;
+ }
+ this.lastUpdateTime = nowTime;
+
+ // 获取最新信息
+ await this.getInfo();
+ this.getTradeConfig();
+ this.getWallet();
+ this.getNumData();
+ return this.userInfo;
+ },
+
+ // 重置用户默认数据
+ resetUserData() {
+ // 清空 token
+ this.setToken();
+ // 清空用户相关的缓存
+ this.userInfo = clone(defaultUserInfo);
+ this.userWallet = clone(defaultUserWallet);
+ this.numData = cloneDeep(defaultNumData);
+ // 清空购物车的缓存
+ cart().emptyList();
+ },
+
+ // 登录后,加载各种信息
+ // TODO 芋艿:整理下;
+ async loginAfter() {
+ await this.updateUserData();
+
+ // 加载购物车
+ cart().getList();
+ // 登录后设置全局分享参数
+ $share.getShareInfo();
+
+ // 提醒绑定手机号
+ if (app().platform.bind_mobile && !this.userInfo.mobile) {
+ showAuthModal('changeMobile');
+ }
+
+ // 绑定推广员
+ $share.bindBrokerageUser();
+ },
+
+ // 登出系统
+ async logout() {
+ this.resetUserData();
+ return !this.isLogin;
+ },
+ },
+ persist: {
+ enabled: true,
+ strategies: [
+ {
+ key: 'user-store',
+ },
+ ],
+ },
+});
+
+export default user;
diff --git a/sheep/ui/su-coupon/su-coupon.vue b/sheep/ui/su-coupon/su-coupon.vue
new file mode 100644
index 0000000..472d17f
--- /dev/null
+++ b/sheep/ui/su-coupon/su-coupon.vue
@@ -0,0 +1,319 @@
+
+
+
+
+
+
+ {{ type === 'reduce' ? value : Number(value) }}
+ {{ type === 'reduce' ? '元' : '折' }}
+
+ {{ props.title }}
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ type === 'reduce' ? value : Number(value) }}
+ {{ type === 'reduce' ? '元' : '折' }}
+
+
+ {{ props.title }}
+ 仅剩:{{ props.surplus }}张
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ type === 'reduce' ? value : Number(value) }}
+ {{ type === 'reduce' ? '元' : '折' }}
+
+
+ {{ props.title }}
+ 有效期:{{ props.sellBy }}
+
+
+
+
+
+
+ 仅剩:{{ props.surplus }}张
+
+
+
+
+
+
+
+
diff --git a/sheep/ui/su-data-checkbox/su-data-checkbox.vue b/sheep/ui/su-data-checkbox/su-data-checkbox.vue
new file mode 100644
index 0000000..537ead5
--- /dev/null
+++ b/sheep/ui/su-data-checkbox/su-data-checkbox.vue
@@ -0,0 +1,894 @@
+
+
+
+
+
+ {{ mixinDatacomErrorMessage }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sheep/ui/su-dialog/su-dialog.vue b/sheep/ui/su-dialog/su-dialog.vue
new file mode 100644
index 0000000..b53e9ce
--- /dev/null
+++ b/sheep/ui/su-dialog/su-dialog.vue
@@ -0,0 +1,269 @@
+
+
+
+
+
+
+
+
+
diff --git a/sheep/ui/su-fixed/su-fixed.vue b/sheep/ui/su-fixed/su-fixed.vue
new file mode 100644
index 0000000..e2a9808
--- /dev/null
+++ b/sheep/ui/su-fixed/su-fixed.vue
@@ -0,0 +1,217 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sheep/ui/su-image/su-image.vue b/sheep/ui/su-image/su-image.vue
new file mode 100644
index 0000000..35f8410
--- /dev/null
+++ b/sheep/ui/su-image/su-image.vue
@@ -0,0 +1,130 @@
+
+
+
+
+
+
+
diff --git a/sheep/ui/su-inner-navbar/su-inner-navbar.vue b/sheep/ui/su-inner-navbar/su-inner-navbar.vue
new file mode 100644
index 0000000..8072032
--- /dev/null
+++ b/sheep/ui/su-inner-navbar/su-inner-navbar.vue
@@ -0,0 +1,365 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ title }}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sheep/ui/su-navbar/su-navbar.vue b/sheep/ui/su-navbar/su-navbar.vue
new file mode 100644
index 0000000..e02249a
--- /dev/null
+++ b/sheep/ui/su-navbar/su-navbar.vue
@@ -0,0 +1,483 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sheep/ui/su-notice-bar/su-notice-bar.vue b/sheep/ui/su-notice-bar/su-notice-bar.vue
new file mode 100644
index 0000000..fc5075a
--- /dev/null
+++ b/sheep/ui/su-notice-bar/su-notice-bar.vue
@@ -0,0 +1,473 @@
+
+
+
+
+
+
+
+
+
+ {{ text }}
+
+
+
+
+
+ {{ moreText }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sheep/ui/su-number-box/su-number-box.vue b/sheep/ui/su-number-box/su-number-box.vue
new file mode 100644
index 0000000..6b662cd
--- /dev/null
+++ b/sheep/ui/su-number-box/su-number-box.vue
@@ -0,0 +1,225 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sheep/ui/su-popover/su-popover.vue b/sheep/ui/su-popover/su-popover.vue
new file mode 100644
index 0000000..adff127
--- /dev/null
+++ b/sheep/ui/su-popover/su-popover.vue
@@ -0,0 +1,314 @@
+
+
+
+
+
+
+
+
+ {{ tips }}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sheep/ui/su-popup/keypress.js b/sheep/ui/su-popup/keypress.js
new file mode 100644
index 0000000..6141c4c
--- /dev/null
+++ b/sheep/ui/su-popup/keypress.js
@@ -0,0 +1,45 @@
+// #ifdef H5
+export default {
+ name: 'Keypress',
+ props: {
+ disable: {
+ type: Boolean,
+ default: false,
+ },
+ },
+ mounted() {
+ const keyNames = {
+ esc: ['Esc', 'Escape'],
+ tab: 'Tab',
+ enter: 'Enter',
+ space: [' ', 'Spacebar'],
+ up: ['Up', 'ArrowUp'],
+ left: ['Left', 'ArrowLeft'],
+ right: ['Right', 'ArrowRight'],
+ down: ['Down', 'ArrowDown'],
+ delete: ['Backspace', 'Delete', 'Del'],
+ };
+ const listener = ($event) => {
+ if (this.disable) {
+ return;
+ }
+ const keyName = Object.keys(keyNames).find((key) => {
+ const keyName = $event.key;
+ const value = keyNames[key];
+ return value === keyName || (Array.isArray(value) && value.includes(keyName));
+ });
+ if (keyName) {
+ // 避免和其他按键事件冲突
+ setTimeout(() => {
+ this.$emit(keyName, {});
+ }, 0);
+ }
+ };
+ document.addEventListener('keyup', listener);
+ // this.$once('hook:beforeDestroy', () => {
+ // document.removeEventListener('keyup', listener)
+ // })
+ },
+ render: () => {},
+};
+// #endif
diff --git a/sheep/ui/su-popup/su-popup.vue b/sheep/ui/su-popup/su-popup.vue
new file mode 100644
index 0000000..b55b007
--- /dev/null
+++ b/sheep/ui/su-popup/su-popup.vue
@@ -0,0 +1,589 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sheep/ui/su-progress/su-progress.vue b/sheep/ui/su-progress/su-progress.vue
new file mode 100644
index 0000000..4612705
--- /dev/null
+++ b/sheep/ui/su-progress/su-progress.vue
@@ -0,0 +1,203 @@
+
+
+
+
+
+
+
+
+
+
+
+ {{ percentage }}%
+
+
+
+
+ {{ percentage }}%
+
+
+
+
+ {{ percentage }}%
+
+
+
+
+
+
+
+
+
diff --git a/sheep/ui/su-radio/su-radio.vue b/sheep/ui/su-radio/su-radio.vue
new file mode 100644
index 0000000..6fc4f74
--- /dev/null
+++ b/sheep/ui/su-radio/su-radio.vue
@@ -0,0 +1,301 @@
+
+
+
+
+
+
+
+ {{ label }}
+
+
+
+
+
+
+
+
+
diff --git a/sheep/ui/su-region-picker/su-region-picker.vue b/sheep/ui/su-region-picker/su-region-picker.vue
new file mode 100644
index 0000000..1f8d89e
--- /dev/null
+++ b/sheep/ui/su-region-picker/su-region-picker.vue
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+ {{ province.name }}
+
+
+
+
+ {{ city.name }}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sheep/ui/su-status-bar/su-status-bar.vue b/sheep/ui/su-status-bar/su-status-bar.vue
new file mode 100644
index 0000000..9af07f9
--- /dev/null
+++ b/sheep/ui/su-status-bar/su-status-bar.vue
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
diff --git a/sheep/ui/su-sticky/su-sticky.vue b/sheep/ui/su-sticky/su-sticky.vue
new file mode 100644
index 0000000..a8831a2
--- /dev/null
+++ b/sheep/ui/su-sticky/su-sticky.vue
@@ -0,0 +1,264 @@
+
+
+
+
+
+
+
+
+
diff --git a/sheep/ui/su-subline/su-subline.vue b/sheep/ui/su-subline/su-subline.vue
new file mode 100644
index 0000000..c11d176
--- /dev/null
+++ b/sheep/ui/su-subline/su-subline.vue
@@ -0,0 +1,62 @@
+
+
+
+
+
+
+
+
+
diff --git a/sheep/ui/su-swiper/su-swiper.vue b/sheep/ui/su-swiper/su-swiper.vue
new file mode 100644
index 0000000..7465db1
--- /dev/null
+++ b/sheep/ui/su-swiper/su-swiper.vue
@@ -0,0 +1,502 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ state.cur + 1 }} / {{ props.list.length }}
+
+
+
+
+
+
+
+
+
+
diff --git a/sheep/ui/su-switch/su-switch.vue b/sheep/ui/su-switch/su-switch.vue
new file mode 100644
index 0000000..d63e800
--- /dev/null
+++ b/sheep/ui/su-switch/su-switch.vue
@@ -0,0 +1,100 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sheep/ui/su-tab-item/su-tab-item.vue b/sheep/ui/su-tab-item/su-tab-item.vue
new file mode 100644
index 0000000..615df2f
--- /dev/null
+++ b/sheep/ui/su-tab-item/su-tab-item.vue
@@ -0,0 +1,169 @@
+
+
+
+
+
+ {{ props.data.title }}
+
+
+ {{ props.data.tag }}
+
+
+ {{ props.data.subtitle }}
+
+
+
+
+
+
+
+
+
diff --git a/sheep/ui/su-tab/su-tab.vue b/sheep/ui/su-tab/su-tab.vue
new file mode 100644
index 0000000..17a7983
--- /dev/null
+++ b/sheep/ui/su-tab/su-tab.vue
@@ -0,0 +1,474 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sheep/ui/su-tabbar-item/su-tabbar-item.vue b/sheep/ui/su-tabbar-item/su-tabbar-item.vue
new file mode 100644
index 0000000..cc55ac1
--- /dev/null
+++ b/sheep/ui/su-tabbar-item/su-tabbar-item.vue
@@ -0,0 +1,234 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ text }}
+
+
+
+
+
+
+
+
+
diff --git a/sheep/ui/su-tabbar/su-tabbar.vue b/sheep/ui/su-tabbar/su-tabbar.vue
new file mode 100644
index 0000000..92e0352
--- /dev/null
+++ b/sheep/ui/su-tabbar/su-tabbar.vue
@@ -0,0 +1,227 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sheep/ui/su-tabs-item/props.js b/sheep/ui/su-tabs-item/props.js
new file mode 100644
index 0000000..3908c36
--- /dev/null
+++ b/sheep/ui/su-tabs-item/props.js
@@ -0,0 +1,3 @@
+export default {
+ props: {},
+};
diff --git a/sheep/ui/su-tabs-item/su-tabs-item.vue b/sheep/ui/su-tabs-item/su-tabs-item.vue
new file mode 100644
index 0000000..7139684
--- /dev/null
+++ b/sheep/ui/su-tabs-item/su-tabs-item.vue
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
diff --git a/sheep/ui/su-tabs/su-tabs.vue b/sheep/ui/su-tabs/su-tabs.vue
new file mode 100644
index 0000000..05d7dcb
--- /dev/null
+++ b/sheep/ui/su-tabs/su-tabs.vue
@@ -0,0 +1,434 @@
+
+
+
+
+
+
+
+
+ {{ item[keyName] }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sheep/ui/su-time-line/su-time-line.vue b/sheep/ui/su-time-line/su-time-line.vue
new file mode 100644
index 0000000..9c3f8c1
--- /dev/null
+++ b/sheep/ui/su-time-line/su-time-line.vue
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
diff --git a/sheep/ui/su-timeline-item/su-timeline-item.vue b/sheep/ui/su-timeline-item/su-timeline-item.vue
new file mode 100644
index 0000000..ddf7a0b
--- /dev/null
+++ b/sheep/ui/su-timeline-item/su-timeline-item.vue
@@ -0,0 +1,76 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sheep/ui/su-toolbar/su-toolbar.vue b/sheep/ui/su-toolbar/su-toolbar.vue
new file mode 100644
index 0000000..17351ec
--- /dev/null
+++ b/sheep/ui/su-toolbar/su-toolbar.vue
@@ -0,0 +1,129 @@
+
+
+
+
+ {{ cancelText }}
+
+
+ {{ title }}
+
+
+ {{ confirmText }}
+
+
+
+
+
+
+
+
diff --git a/sheep/ui/su-video/su-video.vue b/sheep/ui/su-video/su-video.vue
new file mode 100644
index 0000000..a75a79c
--- /dev/null
+++ b/sheep/ui/su-video/su-video.vue
@@ -0,0 +1,199 @@
+
+
+
+
+
+
+
diff --git a/sheep/url/index.js b/sheep/url/index.js
new file mode 100644
index 0000000..d216f83
--- /dev/null
+++ b/sheep/url/index.js
@@ -0,0 +1,199 @@
+import $store from '@/sheep/store';
+import { staticUrl } from '@/sheep/config';
+
+const cdn = (url = '', cdnurl = '') => {
+ if (!url) return '';
+ if (url.indexOf('http') === 0) {
+ return url;
+ }
+ if (cdnurl === '') {
+ cdnurl = $store('app').info.cdnurl;
+ }
+ return cdnurl + url;
+};
+export default {
+ // 添加cdn域名前缀
+ cdn,
+ // 对象存储自动剪裁缩略图
+ thumb: (url = '', params) => {
+ url = cdn(url);
+ return append_thumbnail_params(url, params);
+ },
+ // 静态资源地址
+ static: (url = '', staticurl = '') => {
+ if (staticurl === '') {
+ staticurl = staticUrl;
+ }
+ if (staticurl !== 'local') {
+ url = cdn(url, staticurl);
+ }
+ return url;
+ },
+ // css背景图片地址
+ css: (url = '', staticurl = '') => {
+ if (staticurl === '') {
+ staticurl = staticUrl;
+ }
+ if (staticurl !== 'local') {
+ url = cdn(url, staticurl);
+ }
+ // #ifdef APP-PLUS
+ if (staticurl === 'local') {
+ url = plus.io.convertLocalFileSystemURL(url);
+ }
+ // #endif
+ return `url(${url})`;
+ },
+};
+
+/**
+ * 追加对象存储自动裁剪/压缩参数
+ *
+ * @return string
+ */
+function append_thumbnail_params(url, params) {
+ const filesystem = $store('app').info.filesystem;
+ if (filesystem === 'public') {
+ return url;
+ }
+ let width = params.width || '200'; // 宽度
+ let height = params.height || '200'; // 高度
+ let mode = params.mode || 'lfit'; // 缩放模式
+ let quality = params.quality || 90; // 压缩质量
+ let gravity = params.gravity || 'center'; // 剪裁质量
+ let suffix = '';
+ let crop_str = '';
+ let quality_str = '';
+ let size = width + 'x' + height;
+ switch (filesystem) {
+ case 'aliyun':
+ // 裁剪
+ if (!gravity && gravity != 'center') {
+ // 指定了裁剪区域
+ mode = 'mfit';
+ crop_str = '/crop,g_' + gravityFormatMap('aliyun', gravity) + ',w_' + width + ',h_' + height;
+ }
+
+ // 质量压缩
+ if (quality > 0 && quality < 100) {
+ quality_str = '/quality,q_' + quality;
+ }
+
+ // 缩放参数
+ suffix = 'x-oss-process=image/resize,m_' + mode + ',w_' + width + ',h_' + height;
+
+ // 拼接裁剪和质量压缩
+ suffix += crop_str + quality_str;
+ break;
+ case 'qcloud':
+ let mode_str = 'thumbnail';
+ if (mode == 'fill' || (!gravity && gravity != 'center')) {
+ // 指定了裁剪区域
+ mode_str = 'crop';
+ mode = 'fill';
+ crop_str = '/gravity/' + gravityFormatMap('qcloud', gravity);
+ }
+
+ // 质量压缩
+ if (quality > 0 && quality < 100) {
+ quality_str = '/rquality/' + quality;
+ }
+
+ switch (mode) {
+ case 'lfit':
+ size = '' + size + '>';
+ break;
+ case 'mfit':
+ size = '!' + size + 'r';
+ case 'fill':
+ break;
+ case 'pad':
+ size = size + '/pad/1';
+ break;
+ case 'fixed':
+ size = size + '!';
+ break;
+ }
+
+ suffix = 'imageMogr2/' + mode_str + '/' + size + crop_str + quality_str;
+ break;
+ case 'qiniu':
+ if (mode == 'fill' || (!gravity && gravity != 'center')) {
+ // 指定了裁剪区域,全部转为 mfit
+ mode = 'mfit';
+ crop_str = '/gravity/' + gravityFormatMap('qiniu', gravity) + '/crop/' + size;
+ }
+ // 质量压缩
+ if (quality > 0 && quality < 100) {
+ quality_str = '/quality/' + quality;
+ }
+
+ switch (mode) {
+ case 'lfit':
+ case 'pad': // 七牛不支持在缩放之后,尺寸不足时,填充背景色,所以这里和 lfit 模式一样
+ size = size + '>';
+ break;
+ case 'mfit':
+ size = '!' + size + 'r';
+ break;
+ case 'fill':
+ // 会被转为 mfit
+ break;
+ case 'fixed':
+ size = size + '!';
+ break;
+ }
+
+ suffix = 'imageMogr2/thumbnail/' + size + crop_str + quality_str;
+ break;
+ }
+ return url + '?' + suffix;
+}
+
+/**
+ * 裁剪区域格式转换
+ *
+ * @param string $type aliyun|qcloud|qiniu
+ * @param string $gravity 统一的裁剪区域字符
+ *
+ * @return string
+ */
+function gravityFormatMap(type, gravity) {
+ let gravityFormat = {
+ aliyun: {
+ north_west: 'nw', // 左上
+ north: 'north', // 中上
+ north_east: 'ne', // 右上
+ west: 'west', // 左中
+ center: 'center', // 中部
+ east: 'east', // 右中
+ south_west: 'sw', // 左下
+ south: 'south', // 中下
+ south_east: 'se', // 右下
+ },
+ qcloud: {
+ northwest: 'nw', // 左上
+ north: 'north', // 中上
+ northeast: 'ne', // 右上
+ west: 'west', // 左中
+ center: 'center', // 中部
+ east: 'east', // 右中
+ southwest: 'sw', // 左下
+ south: 'south', // 中下
+ southeast: 'se', // 右下
+ },
+ qiniu: {
+ NorthWest: 'nw', // 左上
+ North: 'north', // 中上
+ NorthEast: 'ne', // 右上
+ West: 'west', // 左中
+ Center: 'center', // 中部
+ East: 'east', // 右中
+ SouthWest: 'sw', // 左下
+ South: 'south', // 中下
+ SouthEast: 'se', // 右下
+ },
+ };
+
+ return gravityFormat[type][gravity];
+}
diff --git a/sheep/util/adVideoUtils.js b/sheep/util/adVideoUtils.js
new file mode 100644
index 0000000..2696826
--- /dev/null
+++ b/sheep/util/adVideoUtils.js
@@ -0,0 +1,107 @@
+let videoAd = null;
+let adVideoUtils = {
+ /**
+ * @param {String} adUnitId 小程序广告视频id
+ * videoAdInit 初始化激励广告
+ */
+ videoAdInit(adUnitId) {
+ if (videoAd) {
+ videoAd = null;
+ }
+ if (uni.createRewardedVideoAd) {
+ videoAd = uni.createRewardedVideoAd({
+ adUnitId: adUnitId,
+ });
+ if (videoAd) {
+ videoAd.onLoad(() => {
+ console.log('激励视频 广告加载成功');
+ });
+ videoAd.onError((err) => {
+ console.log('onError event emit');
+ });
+ }
+ // return videoAd;
+ }
+ },
+ /**
+ * @param {String} adUnitId 小程序广告视频id
+ * videoAdInit 初始化插屏广告
+ */
+ insertVideoAdInit(adUnitId) {
+ if (videoAd) {
+ videoAd = null;
+ }
+ if (uni.createInterstitialAd) {
+ videoAd = uni.createInterstitialAd({
+ adUnitId: adUnitId,
+ });
+ if (videoAd) {
+ videoAd.onLoad(() => {
+ console.log('插屏视频 广告加载成功');
+ });
+ videoAd.onError((err) => {
+ console.log('onError event emit');
+ });
+ }
+ // return videoAd;
+ }
+ },
+ /* 显示广告 ture为播放完成 */
+ videoAdShow() {
+ return new Promise((resolve, reject) => {
+ adVideoUtils._showAd().then((val) => {
+ if (val) {
+ videoAd.onClose((res) => {
+ videoAd.offClose();
+ if (res.isEnded) {
+ //成功 给予奖励
+ resolve(true);
+ } else {
+ resolve(false);
+ }
+ });
+ videoAd.onError((err) => {
+ if (err.errCode == "1004") {
+ reject("1004");
+ } else {
+ reject(err);
+ }
+ });
+ } else {
+ resolve(true);
+ //reject(err);
+ }
+ });
+ });
+ },
+ _showAd() {
+ return new Promise((resolve) => {
+ videoAd
+ .show()
+ .then(() => {
+ console.log("广告显示成功");
+ uni.setStorageSync("adClick", false);
+ resolve(true);
+ })
+ .catch((err) => {
+ console.log("广告组件出现问题", err);
+ // 可以手动加载一次
+ videoAd
+ .load()
+ .then(() => {
+ console.log("手动加载成功");
+ uni.setStorageSync("adClick", false);
+ resolve(true);
+ // 加载成功后需要再显示广告
+ return videoAd.show();
+ })
+ .catch((err) => {
+ resolve(false);
+ console.log("广告组件出现问题2次加载", err);
+ // this.showUToast("加载失败啦,请稍后在试", "error");
+ });
+ });
+ });
+ },
+};
+export default adVideoUtils;
\ No newline at end of file
diff --git a/sheep/util/const.js b/sheep/util/const.js
new file mode 100644
index 0000000..ad36845
--- /dev/null
+++ b/sheep/util/const.js
@@ -0,0 +1,122 @@
+// ========== COMMON - 公共模块 ==========
+
+/**
+ * 与后端Terminal枚举一一对应
+ */
+export const TerminalEnum = {
+ UNKNOWN: 0, // 未知, 目的:在无法解析到 terminal 时,使用它
+ WECHAT_MINI_PROGRAM: 10, //微信小程序
+ WECHAT_WAP: 11, // 微信公众号
+ H5: 20, // H5 网页
+ APP: 31, // 手机 App
+};
+
+/**
+ * 将 uni-app 提供的平台转换为后端所需的 terminal值
+ *
+ * @return 终端
+ */
+export const getTerminal = () => {
+ const platformType = uni.getSystemInfoSync().uniPlatform;
+ // 与后端terminal枚举一一对应
+ switch (platformType) {
+ case 'app':
+ return TerminalEnum.APP;
+ case 'web':
+ return TerminalEnum.H5;
+ case 'mp-weixin':
+ return TerminalEnum.WECHAT_MINI_PROGRAM;
+ default:
+ return TerminalEnum.UNKNOWN;
+ }
+};
+
+// ========== MALL - 营销模块 ==========
+
+import dayjs from "dayjs";
+
+/**
+ * 优惠类型枚举
+ */
+export const PromotionDiscountTypeEnum = {
+ PRICE: {
+ type: 1,
+ name: '满减'
+ },
+ PERCENT: {
+ type: 2,
+ name: '折扣'
+ }
+}
+
+/**
+ * 优惠劵模板的有限期类型的枚举
+ */
+export const CouponTemplateValidityTypeEnum = {
+ DATE: {
+ type: 1,
+ name: '固定日期可用'
+ },
+ TERM: {
+ type: 2,
+ name: '领取之后可用'
+ }
+}
+
+/**
+ * 营销的商品范围枚举
+ */
+export const PromotionProductScopeEnum = {
+ ALL: {
+ scope: 1,
+ name: '通用劵'
+ },
+ SPU: {
+ scope: 2,
+ name: '商品劵'
+ },
+ CATEGORY: {
+ scope: 3,
+ name: '品类劵'
+ }
+}
+
+
+// 时间段的状态枚举
+export const TimeStatusEnum = {
+ WAIT_START: '即将开始',
+ STARTED: '进行中',
+ END: '已结束',
+}
+
+// Promotion 的 WebSocket 消息类型枚举类
+export const WebSocketMessageTypeConstants = {
+ IM_MESSAGE_READ: 'im_message_read_status_change', // IM消息已读
+ IM_MESSAGE_NEWS: 'im_message_news', // IM新消息
+}
+
+/**
+ * 微信小程序的订阅模版
+ */
+export const WxaSubscribeTemplate = {
+ TRADE_ORDER_DELIVERY: "订单已接单提醒",
+ CLERK_APPLY_SUCCESS: "认证审核通知",
+ CLERK_BLIND: "抢单提醒",
+ CLERK_ORDER: "新订单通知",
+ TREND_APPLY_SUCCESS: "审核通过提醒",
+ REWARD_SUCCESS: "收到打赏通知",
+ UNREAD_MESSAGE: "未读回信提醒",
+ PROMOTION_COMBINATION_SUCCESS: "拼团结果通知",
+ PAY_WALLET_RECHARGER_SUCCESS: "充值成功通知",
+}
+
+export const getTimeStatusEnum = (startTime, endTime) => {
+ const now = dayjs();
+ if (now.isBefore(startTime)) {
+ return TimeStatusEnum.WAIT_START;
+ } else if (now.isAfter(endTime)) {
+ return TimeStatusEnum.END;
+ } else {
+ return TimeStatusEnum.STARTED;
+ }
+}
diff --git a/sheep/util/index.js b/sheep/util/index.js
new file mode 100644
index 0000000..e2d8ff7
--- /dev/null
+++ b/sheep/util/index.js
@@ -0,0 +1,133 @@
+import dayjs from "dayjs";
+
+/**
+ * 将一个整数转换为分数保留两位小数
+ * @param {number | string | undefined} num 整数
+ * @return {number} 分数
+ */
+export const formatToFraction = (num) => {
+ if (typeof num === 'undefined') return 0
+ const parsedNumber = typeof num === 'string' ? parseFloat(num) : num
+ return parseFloat((parsedNumber / 100).toFixed(2))
+}
+
+/**
+ * 将一个数转换为 1.00 这样
+ * 数据呈现的时候使用
+ *
+ * @param {number | string | undefined} num 整数
+ * @return {string} 分数
+ */
+export const floatToFixed2 = (num) => {
+ let str = '0.00'
+ if (typeof num === 'undefined') {
+ return str
+ }
+ const f = formatToFraction(num)
+ const decimalPart = f.toString().split('.')[1]
+ const len = decimalPart ? decimalPart.length : 0
+ switch (len) {
+ case 0:
+ str = f.toString() + '.00'
+ break
+ case 1:
+ str = f.toString() + '.0'
+ break
+ case 2:
+ str = f.toString()
+ break
+ }
+ return str
+}
+
+/**
+ * 将一个分数转换为整数
+ *
+ * @param {number | string | undefined} num 分数
+ * @return {number} 整数
+ */
+export const convertToInteger = (num) => {
+ if (typeof num === 'undefined') return 0
+ const parsedNumber = typeof num === 'string' ? parseFloat(num) : num
+ // TODO 分转元后还有小数则四舍五入
+ return Math.round(parsedNumber * 100)
+}
+
+/**
+ * 时间日期转换
+ * @param {dayjs.ConfigType} date 当前时间,new Date() 格式
+ * @param {string} format 需要转换的时间格式字符串
+ * @description format 字符串随意,如 `YYYY-mm、YYYY-mm-dd`
+ * @description format 季度:"YYYY-mm-dd HH:MM:SS QQQQ"
+ * @description format 星期:"YYYY-mm-dd HH:MM:SS WWW"
+ * @description format 几周:"YYYY-mm-dd HH:MM:SS ZZZ"
+ * @description format 季度 + 星期 + 几周:"YYYY-mm-dd HH:MM:SS WWW QQQQ ZZZ"
+ * @returns {string} 返回拼接后的时间字符串
+ */
+export function formatDate(date, format= 'YYYY-MM-DD HH:mm:ss') {
+ // 日期不存在,则返回空
+ if (!date) {
+ return ''
+ }
+ // 日期存在,则进行格式化
+ if (format === undefined) {
+ format = 'YYYY-MM-DD HH:mm:ss'
+ }
+ return dayjs(date).format(format)
+}
+
+/**
+ * 构造树型结构数据
+ *
+ * @param {*} data 数据源
+ * @param {*} id id字段 默认 'id'
+ * @param {*} parentId 父节点字段 默认 'parentId'
+ * @param {*} children 孩子节点字段 默认 'children'
+ * @param {*} rootId 根Id 默认 0
+ */
+export function handleTree(data, id = 'id', parentId = 'parentId', children = 'children', rootId = 0) {
+ // 对源数据深度克隆
+ const cloneData = JSON.parse(JSON.stringify(data))
+ // 循环所有项
+ const treeData = cloneData.filter(father => {
+ let branchArr = cloneData.filter(child => {
+ //返回每一项的子级数组
+ return father[id] === child[parentId]
+ });
+ branchArr.length > 0 ? father.children = branchArr : '';
+ //返回第一层
+ return father[parentId] === rootId;
+ });
+ return treeData !== '' ? treeData : data;
+}
+
+/**
+ * 重置分页对象
+ *
+ * TODO 芋艿:需要处理其它页面
+ *
+ * @param pagination 分页对象
+ */
+export function resetPagination(pagination) {
+ pagination.list = [];
+ pagination.total = 0;
+ pagination.pageNo = 1;
+}
+
+/**
+ * 将值复制到目标对象,且以目标对象属性为准,例:target: {a:1} source:{a:2,b:3} 结果为:{a:2}
+ * @param target 目标对象
+ * @param source 源对象
+ */
+export const copyValueToTarget = (target, source) => {
+ const newObj = Object.assign({}, target, source)
+ // 删除多余属性
+ Object.keys(newObj).forEach((key) => {
+ // 如果不是target中的属性则删除
+ if (Object.keys(target).indexOf(key) === -1) {
+ delete newObj[key]
+ }
+ })
+ // 更新目标对象值
+ Object.assign(target, newObj)
+}
diff --git a/sheep/validate/form.js b/sheep/validate/form.js
new file mode 100644
index 0000000..07b5725
--- /dev/null
+++ b/sheep/validate/form.js
@@ -0,0 +1,164 @@
+/**
+ * Validate v1.0.0 通用验证
+ * @description 项目中用到的表单验证规则
+ */
+import test from '@/sheep/helper/test.js';
+
+// 手机号
+export const mobile = {
+ rules: [
+ {
+ required: true,
+ errorMessage: '请输入手机号',
+ },
+ {
+ validateFunction: function (rule, value, data, callback) {
+ if (!test.mobile(value)) {
+ callback('手机号码格式不正确');
+ }
+ return true;
+ },
+ },
+ ],
+};
+
+// 密码
+export const password = {
+ rules: [
+ {
+ required: true,
+ errorMessage: '请输入密码',
+ },
+ {
+ validateFunction: function (rule, value, data, callback) {
+ if (!/^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]+\S{5,12}$/.test(value)) {
+ callback('需包含字母和数字,长度在6-12之间');
+ }
+ return true;
+ },
+ },
+ ],
+};
+
+// 短信验证码
+export const code = {
+ rules: [
+ {
+ required: true,
+ errorMessage: '请输入验证码',
+ },
+ ],
+};
+
+// 真实姓名
+export const realName = {
+ rules: [
+ {
+ required: true,
+ errorMessage: '请输入姓名',
+ },
+ {
+ validateFunction: function (rule, value, data, callback) {
+ if (!test.chinese(value)) {
+ callback('请输入汉字');
+ }
+ return true;
+ },
+ },
+ ],
+};
+
+export const taxName = {
+ rules: [
+ {
+ required: true,
+ errorMessage: '请输入发票抬头名称',
+ },
+ {
+ validateFunction: function (rule, value, data, callback) {
+ if (!test.chinese(value)) {
+ callback('请输入汉字');
+ }
+ return true;
+ },
+ },
+ ],
+};
+
+// 税号
+export const taxNo = {
+ rules: [
+ {
+ required: true,
+ errorMessage: '请输入税号',
+ },
+ ],
+};
+
+// 开户行
+export const bankName = {
+ rules: [
+ {
+ required: true,
+ errorMessage: '请输入开户行',
+ },
+ {
+ validateFunction: function (rule, value, data, callback) {
+ if (!test.chinese(value)) {
+ callback('请输入汉字');
+ }
+ return true;
+ },
+ },
+ ],
+};
+// 银行卡号
+export const bankCode = {
+ rules: [
+ {
+ required: true,
+ errorMessage: '请输入银行卡号',
+ },
+ {
+ validateFunction: function (rule, value, data, callback) {
+ if (!test.number(value)) {
+ callback('请输入正确账号');
+ }
+ return true;
+ },
+ },
+ ],
+};
+
+// 支付宝账号
+export const alipayAccount = {
+ rules: [
+ {
+ required: true,
+ errorMessage: '请输入支付宝账号',
+ },
+ {
+ validateFunction: function (rule, value, data, callback) {
+ let isEmail = test.email(value);
+ let isMobile = test.mobile(value);
+
+ if (!isEmail && !isMobile) {
+ callback('请输入正确账号');
+ }
+ return true;
+ },
+ },
+ ],
+};
+
+export default {
+ mobile,
+ alipayAccount,
+ bankCode,
+ bankName,
+ realName,
+ password,
+ code,
+ taxNo,
+ taxName,
+};
diff --git a/static/activity-left.png b/static/activity-left.png
new file mode 100644
index 0000000000000000000000000000000000000000..62e3b835ee5313f86e55b0a058df04c1729c280b
GIT binary patch
literal 440
zcmeAS@N?(olHy`uVBq!ia0vp^B|z-K!3-n?{wN*>QceLrA+A9B|MTnrpIwKN_s{=-
zegn#e2tL04|M8XoPjCExcH{rkt6&CD{f+-mZvB691*p-^&EqD}6w#6(zhDN1`}6M!
z#Mi&yUl8DMZhgb~efzopr0LnVe8UO$Q
literal 0
HcmV?d00001
diff --git a/static/activity-right.png b/static/activity-right.png
new file mode 100644
index 0000000000000000000000000000000000000000..e18a96c8314d3cb8e66478c8e06ed07688f2eb6a
GIT binary patch
literal 1400
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
KF{w53Nc)6RoWE+fOFf+`?
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
literal 0
HcmV?d00001
diff --git a/static/comment-empty.png b/static/comment-empty.png
new file mode 100644
index 0000000000000000000000000000000000000000..810a3b1c00626a828b3102dd113d7336218588f6
GIT binary patch
literal 5603
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
W$rPvHafW|CYfKC+4L<9+Cj1}5&Fp9Z
literal 0
HcmV?d00001
diff --git a/static/coupon-empty.png b/static/coupon-empty.png
new file mode 100644
index 0000000000000000000000000000000000000000..9e14d9d1907a882ea19c88e4d7392f94c4a20213
GIT binary patch
literal 5245
zcmX|FcRbbq_b2z7Ng_Kk%a$2JL`Ij)tZ)%BvI&(fJ2J9WS5~%&GRn>lx#mTK>+a!R
zGko8DevilR{dm34J@a{<=e*v3-BfckLsn)!W*QnAR%0W5OW>FI?`5O|BvU%?8ycE3
zmgW#^1HdE@c1R>Dkw_tu$piwKMA{`1ckm=YA>n}ll}aX)v3L@mNW|grSR4U}l1LN+
znT+4r0YYT*4v|R30AV7PK&28Wl>Pk!JcR=Ifrmn&062g`*xe-%NJQcufw)K7p#Y6`
zcXx3_5}*J%016&Y#1Y6i-03zNk0p?B1j6a*DV|6^IXS`MDQGMnI6!kO7Jqzvip3Ez
zI3gN@Lt(He3~n2R*~Z|3!vAzEo>^4j7u0w9S3K#*u)$jxo^HX7)Q!xP9rXmbnw
zukb%iKmwknm9?c+#L_YXC;?1h1V94h0odi0H5{GyG8OOucZVbVBe3+Z9P#T9^3Ns;*b;ybF#I>;HU`)RkOTC>
z;fcVW|Ni|8a3GL&{=-2441vLcO98l%cc_O)M^x(G{=wny-u@1S3S8NFr=dpRtEvyR
zG_#`7H8IdMSF^Dbbrj(A^!Q;KX0au3V$VA%~3n0Hxw(`*#N@6x^1nm`9$@=}Yv
zR8Qw?B5oNzHt-P^<9`K%nEf`?=W%qji`)KVZ*h06yW7-2c5k-7r@-HMx+3qfqv9U2
zy(lZpS!Z;hxi&_#DmMiVHOMzxG}WP@VV5)3*R_sV#xC{w@agh=B@w>gN~e`ptjYeG-F{Yc%SpaVHZ_dM0_mPZw|XTH@t?op{E3brIe-!
z8WHR`P|ID7c<;|EUC9t1=XZRD!!$r@)d!481d0!bFGkz=athSFe!snI;
znE!Hdw8dN-Y@B&2;bD~3#F$NOOj34V60PUOk@Ij)<<3O=4yI+SZJ$KS)?K2~?dE&n
znVJ)+ec40<|Dcer%f)#w`YN-|bIH0kM{qbZXfi(nCyd9NEsiS0S8JU&tr{o}T66YJ)Pw
zWe(T)xjR?FXBTb;B;+o3Tn{!Mimx
zacbxe2__C6oC{YOwr#qby{Tt3{59!92REF(f+M4dV`}CVxl>_7wXoJgL|>^fiN(xD
zvx-?6thAmI|FF+T)6lP)A#0|ck(Yc(|9cr^x^az;Kle{uANMHjydRT
z73BH>rO~F&TB`jJQSJUSe)>vhaxyp~TU&5G0Dn3bt)7(Kdpo5MS7G%&;IovUfYxb|
z(~V9SU#G9V&h{Dnhx;XU@I3>gO**W%nQX}^|KVV|Q2s%D)h;N!ENtgMBG5Ea-3K9K
zhc;duz|pT6#nj0ZjDzQp%6?X+S`Pye0=3fx{6Fy6uCjz@4;zF8)OX*juD87Y(!DGg
zWF`8re8lZZKPI-r++3OX%40)d$WF=~6^@MV2YaNyq*O*reS
ztO+6?4t964sORsr>B|QRx!J%Tf>o@Uhbq%L-%u(=V4O1yMb8vNl-{{}N{sFWzpBd(
z_1~(xx;yOhmet$kM16D=l7n9@t2Ula{GN_f6Iy+=To7>|*R*5p@@DMt%Igc?2e~}Y
z-t`L%2me(I7Zgve(>M^1e9zCMNin9$Z1R4G~28bmA2
zbl+i_obsjyXiJ7FdoI@`|KZ-nS})l|)5
z>`VE)?%(|Bqejhht3
z&gj-Mdix&TRlSRkzD%{{DRlDC=eG2IgnoRN0~+$sx~iI;HsX9P-sa_tnF4v+UQ0~Q
z4>$9A?!aq&hJk7&zS1+5s+RY;D&Iee?3=CzvB}U#X!VF4{7N@|orIC?d<385*L##1_2a{+r|2=c;!<-3C-R63qp)(@v
zw+1q_FUp%4w>$uIca_C&y6{ZqH>8Og`CQ}-OPkCR4Bs_rb33+e;l~Ea5DMP`v_Dv7
z^g18ymdcFKCl84ukeleADVQ*}FJOtuZt+vgjzvX;=fvRTM}C2(lF5!Dhr6Th`nf7G
zjz8s_;H@F=|D@NN$z+kb{hKJdf{>WK2t?q!xqVyQOqr%wKxn^_a_4PE4}xw+mUe0P_KSiotYsn3CC66z^j@sU
zY`ONz%|=|A5;WY5N`H5#$Mh>`yYO^kS~i0IitgY?OrAqg2UTGq)O=FjJ#;!LCSdH_
z9kR~R^UqiNM9LfOna;_noU2H3@lS~HpM}1KzkH?u-`mS$TJdbI8G9Aex252)Hzc@^
zj3)bkX)+!R68Os2dXuXiR%kGj&;o-ww4;wEQ45-PNjH#kcYRAx39DPfA9wZjcr!BR
zbB7h8W_iX^Y8a@KMRgB2*^l?XXp|jlRhPSzATe=wDHzi3(Qd`#K*E@A4Chrf9#f$v
z97O=WYkyEtSt_zg@+UX(LcIO5QEjXj+W#yWcs8-wIi4&ul|gLkAI7rYLu-H8!RErPAA+oFodFWnD-%G+p}@b6{NO4s2#7oN!52P
z2xr(Vi8&80@?4R^O
zAux+^s=zfZnd|e3k@Xzh6%`=?A^A<-3Y|A|;0|G*-=C2#gD3kJXf^Ub8CLT>S}{@(
z>9htRW#A(jao%6zShS>#yQCY_ihXOIYCiuUb**~B+i8EKNR=PkmH+CGq{Vq|m0K5F
zn7LrBhDj`lfkUH@VZPHmwmJ2Np`Sry#~0A*;i6uR_>bG8NU`tG*bT$DG>)OF?7V_6AoTE(M8SMnMm@o*EA)k2p_f26^e1TpAkv~Q*!?;jRcBkA|KGKM&%!G_?c*A
zK=HL4rbz0LN8(KuNHFAy)qLv`wk|uhzH+7+Yr6T%;YfwwG3UJs0w(Yt5ny^Xwk2;iPXI6|J7>u&(Xey86h%uDAMS3q0k@
zefuW^$dTpSr!T$Kv`pw+X-1?q!WHowXI1RjdIgH@s;dfX`5w^u!u&;Hc3fv9ShW1k
zh;>Jh-WdL#DU6`pqP$r*5A5SI@nRoNd=O(eYrL<-mK4Wb)-R=@<0m`aUo9dzc#-Ox
z#j)PIzPEFzBf36V`_?6f64*&W@hUkr25IRc-wEhP+VoU3<*c8U6K}5_b-R2&z0~xS
z@eYU8Etj1?0nJLxiO(Yq?{0J-^CcE%ie5p@_Maeo5}nKZU`i*Fi$4nCZ%wzbKK7k`
z&mb3m7Bmo_Ec%LcTDsVGBe}kL5?@|1%49O@hyML#cv;~pvtopos^D79U4<(m;K%Z7
zbsSzw0x|ccRSJ1IP994JfX*P!h3EYAN@!Kv|Dhc`yUH$l7)-KxqxsYdWn%T6M@eS+
z>6CvueokfBfT+6}IqK>?G5u$IIU#Af!Z7i7=2EAyQKq`wwHpO;k-DwDsY!M(u5}CI
z@25m-IE@Gd#Mz+l)c$e|5aUVr{5;vLEZ~w=N-yglAiBW&ywZ#BcW7r`>QqY4X#Q*<
zrcrT+hDZso9|&%444zDBoM7?%tQ+j@?RT=-_w>!9lFAOZoZnFKfKW>uD_VDOAt|j?
z_PS`4_$_CJ54a`s^~cv%UfHwUtN9}DItM*0xh?if-OXaSq;s2HXTgz68
zo0=AXc}~VZ&sSm}oZss1P>d8~P8wiW>%VO#azq}`;h(5)D2fgnVoPDPuYP(;Y}?;w
z)!+V`l=_2`v8q|BdW>S;o=LvWksx)m~&JjeZRe*Uei9BJuj@YhH0LdBMqIi6Q~&?L_alWbud|6t4RWQbUT10^0zH)6mZU3?Q=VRQfY
z?Y-@?nu+?iXInReDfZdt7KUk++=*+VnZdejxp?dl*;)I~wo!U8*ofY@>
zwDaP(9LM`GWMME@4EeprOryZ{33C;VNNWutCrd@fF^x(8QT?{&w@{{0eYuPbPqj%;po+-Ay#1c+
zuS~>g;;}R;A*7Q^a18YJNlXL^e#U{co3bNHR6rUd`>s$>feR@AFTp
zc1N_E*`E0+ahNR-`c2q&02f*WD$B{^!&?zUg+NE=6sjSSw0jkhN@Iq1
zQlb%Of0R}lFS}K}@=atAv5d-(@SXtx-e-2#aiN;$M;cjM;i&S`Z;7sgX
zHO7fWFVXgvl~Wets*@ccozjxn1;CEf`alh`@{kreR{d~Qy>wR7COb0u2UaoUo3=9msmKG+Cz?=B*=3oY%
zoLM687#Nrk4mQrF|C|&Gopz#sMC{PbAU_1UjBZ!{SMJJQ0HcoL34#u6!1Dis(4!9XNXno6SqeqfeDp#Tg2R}&Z#FxY=N(HJ~nAW>K}7Kg?V
z(3lex8jr%^iBvl3-xL;!!J#l%6cz`tA*_qob{D6kzQ9Z@B;W?+yxJA_J?CDBKPT
zyMsh;qcDJRe0%}~0|t=%pC5&x>;fdj9V7;U#B2lCzc36EgFiVr+1^0|801|V;0K&&
z905-t12OS%tv?1Bu2$VOvWptBXreAj85cY<&{}TiXCgfEEBYKsW#xizlu?VT&uP
zur>J7GJFNPwzRyuy^R4DqA)nePj*3xdvY+k^u3s6e)?yaE6XdZ2qc6tm$+S)P{29!pjaN`rx)3XZz44Fdh>mM2$p9E}R7ygx4UIlambjA@#01u!8fJP!y
z2t+c#32Y;v8_+l)FM&uoK0XG3flUWUNM!2a;URE1cd2w>g8)?l5f+wK05Cv0pi`h1
zpfLavP~dalzy_c;d=tL0Nu}-W?eF7>lqt3EmB2y&742x}#Gn{%^T^K9)ZFMgSYP|9
zx~7I|o1C=dMX`{3DbF8Ax!=l4&xj4k3HEUk$xHTf5cRtax_MfNKmT=EQUBWt?y6GG
z8r~1@8=5-U_quz(uw>bP8yx;K3SnfL9G{y;%>lc;3=e0WIG99jygEc&p^$%^+pEPH
zZZ3|N#H&y#6W^4DNa*Fc#8AFp-w*a^IP}=3y5}*T8VBgj^;GBMgM-b*p11kFUe+d8
zN!zf6pPh|qu@cbX{@&suJH1^Jac8*A^DlO*ru;8%-J|?~fq}oz(!|g?ZW+65eNWI(
zc#xDQS^xaqyVO*EX8{(&L?I!e8n3?HV6}Khw4rj142KcLAy|NQ*!z#WbI8TLnvNHy
zrhn3m#vd%iergLnO%9)xwUxGweAqtnBd|NDD;wL9G~mR?iG3U99V^GpA(1X%^#47k
z2kz2CmTazssO(2lx~K9coxyrHp4Dw-X+KC3hxXi8QEx!aj&`+Kz^n@iBY0Wwf`;mf
z0z{($z7|9CmTLV89X{0#K67z6S`5sDePkVfM$n0|C9ipfcd(pMiT(_%XZK|fVdXuc
z*K9PocTdzm^v0Jr5y_Ukv*M)8+Ch*Uy*o1~GnRC=izZu8ScVeC!Rs2H$h@(>O?|Gw
zZeDbS+4!KhbnDM^ZKH*piosmJueS>`v-2W}hloMG+562ez$$wtA8SHY26@V!HWcwC
zn11$Bk2XJ|H7mw#n9I1Hjw$#v@Tm7(iBEqGSJCCdtSNJte8~S=vDwchXJb
z;p!k)lgvcU3&&p9hv9~=o$+BzF88qC+rj7ptG`tb^6yBMR7B-5-k4VHoJB?Z{c1>
zDkTp58stulm2l3N`+6{Z)}7ep0EzSQ8rpvfO0iF@X6>Dv-9vsq-8BV{!VhWXF?^KD!7*Yjlz{T8lj=&zQR0WxpXnOoo(S%!)zmGNXR$Y_bo3QfvpedVA3
z9y0vF`3rM)C!)o>O`yrz@DHC0DEdK9Cu2tzq4v3|sIZaP_+j=^x>pOka28Sj2e#C%w~^HE|5fWcluVh$Yi
z@J0BOS2Pz{Y?Fab^C_@<-|$#QA>3W6D1kpMMXQ4><5MZn=ww(DU@AB2tC^P9X9sC-
zOCSaG8xcn^8-iwWXAti-=xHq?JV&^8D2$oy^Wbd0rELDv%+=J1Vt=>T>qm>c;t){U
z{?*h4J*lC1E!o&K^Q@s#$kkL^PwB-ao){10P^=OszBMgEHC5i(y(@fRpnOOe}o_*n0>8c$4dOo}6u=Uqi@Y3h`
zukQ4==DBNKxlL8>t{!F{U1Rmxd>+a4gj0=l)683MTkSiidr3)0dW34pKAp6Nfv-$H
z#k&y2mWOobKZzS}e3=XsA2&8DJo8vjEyhWw-MEbI#s-QF3|gIO)=YEei?U
zn$=#5sh$^7FcFKK_Dft}m3Ac9j#uDy;w9mo1O*2>1Lz654Wu_O`T3Q#M9ET~^+_0U
z_CIvqg|%DXavtyR?`st}L?WQOQlWQwORsy(JPUlc%{-(QPI@(PcaKe*jMFM>YHfXq
zm9?7WkhLcm+~2EF;K(uH{yG{~xqU_Ff=6rF?OB3ei
z$id>`>cA_Ak2qGX{$K|u(ns}YBYezL-4|N%#MD(mhp5s|MESDL`tzbwhrz_AK6NEs
z6PMWBqpY*zUw^D>H5|qXg;t;S3aE37iVW%gMM^ove8(rkMc#ToM6Et@Fkbu9WGF_5
z#dNB?8mnZLrKc^YtMu?fKdcTPHhoxo@Ok)lNTs4a!`B+eESaqGE>AVDR+U)g1NwWK
zaG!g5Q1@Mr7ZZV>X4>n|SC7%}4DRqQnN`pH742KE$5nXVK0Nldc4?ld>idT80UcRy
z?sU8vZ{OYu6k+DL%;KlYCTf+H!ve9`3n*-+=er1ro_J4od073Jy_@sq#c?L5-m(qM
zcVbfi`d@_srn*RbT(&`&d`t=FH~-WGbzQ6VSIQ@enfr1N@zTfM<6{yUvrBDKr(&6}
zslLQafIekf-EmDRuFK$I!z>gRT|1xqdkIrHzxE|_dTsxJ3bPet^=T8hw$lZ2o!YVF
z&Z`meW-Qx{cJW{h1bXMzXY7d_k-OI<$qrud(LfTCS+%J`YAbAxDX7QH-<;!(FGNtq%`jYDs?s28|2QH1x|SlBppG|l$}q%S@wZ?SnVomWiBuV5u4YN=*C1B&DSW&{|s@+
zOgcq_hu8+DxI4Xj`hl^c>pJimjXP0HCXK{U#RU_qc0Wd_m{*RV^4m@C$~!)*g^Z70
zPgCCf-=X^X>)R!34g|V=%B_jRH|r`eecR?e
z-9ocB)67S!=V_oyBk@Z`-{!9q>1!?5k1~4q{`*fR?}-&6#DMY0RN1~3`px&7YjPM+
zMwOokA{2j;l(+>s$TeEe4pVV4R29^q_K!I{xS))<*yEP_=*FGbZIV?E<(L=ey1-9s
zUtW@4azt{j(;hchc}=qts*(~66|;D(hX^{Xn%;5wOyWSm8nvL{q0$Wb(A
zkSJ!(5jJtZaVX55`^T$-8v0w4mAAiYs>}rM$sUW?tW>5QUfJe$yklW6XsT))9<7ML
z5Z0q_xL0$Uuz$n4K1p;&Q$+iQv}-1>u>Ia|L-ONTBn<_#UoCnv{(&j}uI`Px)wtMp
z|I!;cT*i(*w$CK{`)ZU!g(`Ta=Y2TYZD_+g?46L&PRo~QSt;8=18Ntfbb9|YK0Y(J
zzW^e^WnwJ%?n&pY>EtEbf?_Z53~S=r(T8J)c4tX=fuoaC!c>S&xH=`~;$^tZB6cg!
z$4LFX6qgPjS^EO69l6@P7ZRNZcxR-cx<+PY+mM
zDu_EnYJib@1W~JXQ@rKj8;f#@Q^oj
z^h=N%FMIY?LYcX6iIzAPi3+0scwLejDD!kd>3VIK@jJn6SuUM21yO-GOH2*#F7Jot
z%fejtNec9aMY&B{puA>)w9%$Hv1dj-Jj%Pgvm)GU-h~ORGsGS*8+{>VbgxO1jV_$`B7>s{6PJO9{5}*;d|x_*19xqT7(1g5ocP>
z%R=X6SBt4MDFh
zEt^W*AM^0uFBIYph+uvF7{nal=62e+$vwtQui$i*WbKcqrIHe|DV6OtZui37jBKv7
zwz2>66SkJeq%ND+X*aj9C4}ETPx+2a@%7uN@~t0vrl%v5TUp{Ib%Q_lwv|xpA!i%=
zrzM5)AHyADd1iEbAM@`mG`wuL?L{v5UbTE%PR>9&FQlrql2tK0n^fQM$}D;&b2$i9
z7^pf}_0gZo05k7*o^olt5?p0wXTioUFd*1B5ZGm}_F61)9}+XgeNB{+<7ixu%_E*@
zKBa<86k&dH=JQzu1>4e|mYe}Iy+qJtV{nf8DivPCp6nVwd^?T}TiSKD=m9GE)%m}e
zWzMV!T_IX~f46dl7=-WmXygv)^m0_ssl7_i&la@e;|S2w({yGw?Y;S~iuMn0)er}G
zGrLpPnkgP8pDJ!b{&o}kEn{$d4NT{g*-oVEa_@9m6k>j;`66tDp+27bH+nagv#p9T-dn`_roE`u+&pn$99bS)hIAH_jC-!0uxiH~6T`y4
znU&PNaHV3h@+;bZ788{7dzOcb-8UoMW=8f)))#ime5cnW!hwMLw*U23nRT1KII9Oq{(-r;)A01%d?Psns=ykss#
z#E(%!z1)@Z@iMc?^>cQ!iyBJfRvgT|ET%)>G@3p_{LbDV*Li(iK#0AlvtB^y`9e@^
zw@XsgY4)3^S_I1%in5)u=Ob996@0?am*42Ko^O#eRH)?1wZc~4h)m@0$-l(c@`StS
zR5^aS4f|WjNtSD5tmS>WclNA?Pc~;|Y5jPp{iKGKC7-pqdgT?rMvW%Acp2`y!mG4x
zvZL&~Wu3FBi1uuKrx6-U3p{4ocqw5+jiwWkMTsxe&sYm~cWsyp?sRW*`S%Lm;tzU<
Wu;Hoc{`Y%=!P3;uq}j+j_5T2+^XVf1
literal 0
HcmV?d00001
diff --git a/static/goods-empty.png b/static/goods-empty.png
new file mode 100644
index 0000000000000000000000000000000000000000..bd42ecaa0e3ce2a02a7fbdb1e20857cb2f034158
GIT binary patch
literal 3192
zcmaJ@c{tQ<_aA0t&AygBQQ{$9nh^@wBOyz+v6Zqm*+mQ~`!hu(i5}a7G8EHjB*xO0igMfJUP;030BY
z$ka6w1vr<%++=e&t842UbSBW~Z$66+BxoD-ot>Ta^>qS)u&}VOwzjsiva+MNb;(oI5QmAtfvXzNBQLc-GQ37-8<{
zO!^Cpy!5a?`h$C_D>p|-kGO@G@Wso_&W+SP*cRg
z(Kn$PLyB5C=eeY@8Eel%%DSE%LgjQw$q(H7|JB=8Fiys=c&n{qyKnNC_NCcVB!liC
zl}BE%{G~k}Slhv=DSQRTOv#iV@k(R}=Px!*kxt@jylJHJBqn4`lQ*vOjX9W6d=BaM
zUZhbEot~x*W^C`JnAPVrSi#%RfC7Da4pa84lqZ^{D3M6qe)4Xi@qUQ!P}VQ5=f2OHvBy5|CGgr+dlP>+q@i+%(``k}#ChjV}1oVbC4$!Vv>?
ziJ~Eu$3{j)uIx1-CfiL#wsX-I)+hcex=w;!VDD3E3`kV1p=@Fb+
zMjM!6dEI{%etQbLcBOjcQ`s-+OkFw@6Kmr-voiTARbp9JUY8y6x~{D&E-Ww#c}plI
z!PRw+$|=sdm258_)=M{)bXB4(?She)S^Ew*q3-tR@tOU+`jpO#WXaU#h^!-YgP-$<
z>g2^EiXv8g*+YfR+c9@{^+vY4Mzbsp@y&p^(i0$13Oj#$KI=V4s44dEZ*1>ejDE3W8Np|($0Oc^zA6I8e-My6bG4B+U0{kz_#hf5N}N=t={TcPPy5#;^b=w9~QKveX2k1
z9wjRB>R)pzGPA6#SQkp?e2;wxWhCp!8%?(OP}3k_b%Fjav`u^Eq52=Ro$|HBjYRwM
zbTC$oTaoF^{g-c@M1!YQIh{+kH_B7w=KW@Cw0;rshkC=**N(#)nN6d!Whjog4AXqj
zp1+Z~HxhBJK9RA*^^R@Ve6lt1rC+r|^pKcPXCW3dwS8bU@vM~_tEpq0G^ZOn)C7Ow
z<{R`0=<2wvotkD$@=6h0)GJG}ots~nsXZX_nb@z3SqQ$oZax1*2CF=eULp|iCkGp_
zFrBmLuYzzH8&6)hhGs7NmZHyj^0th+DLLLI2QX&ND=y88FSD^VCDJF2<)u{$e=CE1
z1r3Qm(bOu|3sO88Rap%3pg%HhU!ZjUDUsVW>WBh>Zu6lioghYjRp%%o81AC89R4^#
zWke!N7lRUEnb)~rf^!pVj^!pwP3tA_*FfeuyNgM7L`UA~9_(PlLv9!DqjauwI$Y>x
z_sj&2&HkF>1JOO>|AC=bPxB+
zuQJMczOn0T$Mc#N5lj**Yq%Tl}fS1XZ-ITq!pa>o)i`8
zvOd0XIqGlg{4j=8y)XS#LzCSrRK*3Bh*u+Q(o)KZA`~=Ka49SspT>+;<2ytP7i(TL
zPRi7bVj`#JGbtP+-$(&`TDz>iIJ*W%fgT*9BJJKrC=}JttRBCVJ#|mg(!cX8b*g2?
z#Nra$JgP8zDMs=p_hjdl)8y88lP62i@H}PAX9a%bLqF^{5)=VhmoFmnG)!OeI^utG
z9ESpzkH+5~obkck0~Mp(cuS)>oy0!ckeloyoR2A_xC3mV1DV13-1*Re?wiANR3fMS
zNd%VRtfVfacIabYSEb4{ht6+K5YO>k^-ZEqr$yez;4;Jb4juK_M>6vN#AYf%%EvER
z7fe(KecKL?3wF;hm?`*D7|*NL~+
z{FKdQlKby>typL!Sprwl-AP2tAi<%#%2Sg&?oY5Rt|g59KuZ~~*6a<-i&2L03)C$N
z!sJ@u$1}C>pNAymw-)f@f;-O)Z<(VbZzgFg#30f(Wf3)j+FSZvH(IT=_}cRNQl1B9
z(Gv4Tn(k^3TYOll&+T^j%pYsO`twmRLm^|W8vaLaPxNgLMk9KIClfvg9rpe*A@{ZC
z?wiugOf#Rxh(RT!iiCGkeP&Ou=kltzezcYV>3Je55r<(-QPO0-Wlw?Oxu!9>U4Ek($Azyqj<+HPg`
zD+#nGJT{N&5|sAj-*LgL97*vy5fWd={l4zMe-Y2AZVJtNKbV^1cj&
ziCD!S2n9#OtcER}B#;Uv57KZ+7NYl215NL18~)bHzb{r;^_1}Owom9dROb5gQqn_{
z6NvM+SIyDbWiQ?MrjdSF7E8E;^7MpY!bnNgaJK_;J`8Otvnl@bSjSSenoYtzgflr8
zGT%^EI1}&mcwSg%7_rn>wIfHC)`>S7awu(GNHsvM?mF~k1d%lS;Cyb=2`S_3Uxec$
zDEI*XPgJ1&uZ&E1K9)*%n5%%5gCOqF%c<~Ny%NNlrcoX32)h6^HONJVG@|)2F-+Iw
zH12v#VMhr=i~pugy&UpAPH*ICNlOo*iN{)PI;+sN6KufDEjy4^C~(>Y@n?<}*`^-riyRPl2>*H|xe;~svJhtru`pqYie
z|Gc>VG2i#Q1mYmD2z%X9+iK0;@SAs
z^w4X3lVpZyb$l8U5n@D+}yn%njknYMFm7lt5#m%Xh
zpmd1
z=eE?|yI;yy_C77w&M(#utNpNCow8h%+bJDWD}SuRR~&XBuzW1!*ZIRG?cjhrv!UND
g+;9A!Or9_WCHG`Qa90BsfPXK@*3$9HJ99YlzX8Fh2mk;8
literal 0
HcmV?d00001
diff --git a/static/images/audio.png b/static/images/audio.png
new file mode 100644
index 0000000000000000000000000000000000000000..885164baf6e832735e85f1cc39dc343c80f1b461
GIT binary patch
literal 1052
zcmV+%1mpXOP)Px&)=5M`R9Hv7m}|)1a~Q`zU#A&4jdFNJIW@F7Ew+q?y|4_eu^R1#*)n7lYLpk-
znnNT_R`$aAlw>R;TJ0ecHnF^zGLiOTMp(|d^nLv9r`zqm@8@^@?}zKn{o=U}pXc}g
z{jQT}AQ7<-Z~$;1FcCNbI2afQ`~d6(J_f!5egt+)`ZF6!8H0#861W&RA2<^@W)%BB
zfGxl~!0VDWWa3rBMZ{ge0^l%UuS}4l`xEd5uvF3;HTHesBEo;43akSTt#MeX^9*pk
zq;LD__k@dxJ%Clft(5_@YQB$)B)!(lupiu;Sm6x~?n3jn$
zpzeH0Pj~wG2VD7-Yk+G843;(b3C`|(&7E*_f#
zq=+~O*aS>UczOl6q8nT}#Z!UDfKw7a+f`Rey2EhC0-q(F^o1*c6M*%=*-774e+#(C
za90CslMY6OYrBh2xC$iwfA2QTa8A0}S5^&IPVr{oUcmLbR)*n*fOBdsie3t?0J){&pgZP|fPE|CEi~NMz)=;-?JDV$D{yY_p9LmeyM)38EFbP
z9&pEVRz8P3oA
zzJ!rgtKlNT_t~G)kD*q61CBP_KAyXuo9ZSMu=C;uvNLDL8W*e#LdL_H$iCVppg
zudV$1f5~b|H*^N;I-{1X?wXtJR+{`XYbABvF!WpG99~}E%q9^lY`p1QCh6{8x})vq
zdmRAJJsO<2DRFW%GPpMixM1D~+h-j#Tp?o;*l+@Ec0SycPi+jLLzDftVj
W(NK=1K;=sS0000evaQ~`WXXjR!wUxEB1={?m=bCrK;Q;KfJ-n%^_;WYyqSGu
zLl9iA@$r#a-h4CP%r`UpI}Z58@X4T$k5?_oUzVYUOx3?`>4r*f_hU^nQM1xJ;4MS=
zQh(<$C?&Ww=`{RSXqHl7(&46BnHR+|dD5c_AvN!T;uI8oYJNr)r(tdeZT|)E<)jBZ
z-@~OMYkvSi$Kq-D#3Mm60rIalEMAd;Wb`}cF}j7DXfjbz@fU#3OTB~DNCMHkHaMzSXGW1=q5;x&$zY)E{MT((>nx}`hN
z?&Dz`Ss+ij2F3(JHFuxEnHc0Jpy(0vJ_7bN6N_$Dbi#|&hZxn^4(K;HlpSxwN1hNUa}3$gZzp`
z2ZmP`LU6{TG6z*`#N640UQghWl5>5ILQfSD^5{L}>U}Q)sIz3%%2j2m#%yMX4T~k%
z0N-lw#uK|POkE-RTl5Jk=JfR{EX+V|5{mv|W^GdoE-1LgsQ{dG8;K))E(*_|3JMxJ
ztCJ9jWKi9ng7bF)6YLX)#%FXljaQJ^sOluZgH
zH&G4-tDl7QxGKhBVOlPDRna?)a9}wnnYAs^V9};1G&-4Wa9t3^I)Amx$XSY_t`YneoXP~#=4J_IU8Eki*-BENTE>#G
zko00eoObi#xOE!y(+TNgVj%=i9xA1z_E59S=>Z?!Sn$)eeza=jYmjL6Qd|9elM4B(
zHe2oZw!w43+_>9iqy#8>m@LE#N|)9`3HNsRf(P=G6rACR*@g))KgmvoVR2f;4zsKq
z9zDjxn9dlgV#-Bywqq)>_5@-zb08z16)$mJXW1I$n!V^1GrDDEx2@2&@@~je+wWes
z@h~QBb|qtWHsg^me(TOp3rw&%56t=1oKIpN{-Z`dnX%-D#0X1`_ixsbTbl1`oBI6G6QvixiNFEdODR}+><<6E