├── components ├── common │ ├── style │ │ ├── var.wxss │ │ ├── mixins │ │ │ ├── clearfix.wxss │ │ │ ├── ellipsis.wxss │ │ │ └── hairline.wxss │ │ ├── clearfix.wxss │ │ ├── ellipsis.wxss │ │ └── hairline.wxss │ ├── color.js │ ├── utils.js │ ├── index.wxss │ └── component.js ├── btn │ ├── index.json │ ├── index.wxml │ ├── index.js │ ├── native-button-behaviors.js │ └── index.wxss ├── loading │ ├── index.json │ ├── index.js │ ├── index.wxml │ └── index.wxss ├── toptips │ ├── index.json │ ├── index.wxml │ ├── index.wxss │ ├── toptips.js │ └── index.js ├── pop-manager │ ├── index.json │ ├── index.wxml │ ├── index.js │ └── index.wxss ├── actionsheet │ ├── index.json │ ├── index.js │ ├── index.wxml │ └── index.wxss ├── switch │ ├── index.json │ ├── index.wxml │ ├── index.wxss │ └── index.js ├── popup │ ├── index.json │ ├── index.wxml │ └── index.js ├── wxs │ ├── array.wxs │ ├── object.wxs │ ├── utils.wxs │ ├── bem.wxs │ └── memoize.wxs ├── dialog │ ├── index.json │ ├── data.js │ ├── index.wxml │ └── index.wxss ├── mixins │ ├── link.js │ ├── button.js │ ├── observer │ │ ├── props.js │ │ ├── index.js │ │ └── behavior.js │ ├── basic.js │ ├── open-type.js │ ├── touch.js │ └── iphonex.js ├── page │ ├── mixin.js │ ├── blank │ │ └── index.vue │ ├── guide │ │ └── index.vue │ ├── richText │ │ └── index.vue │ ├── video │ │ └── index.vue │ ├── notice │ │ └── index.vue │ ├── image │ │ └── index.vue │ ├── search │ │ └── index.vue │ └── service │ │ └── index.vue ├── jyf-parser │ └── libs │ │ └── handler.wxs ├── mescroll-uni │ ├── mescroll-body.css │ ├── mescroll-uni.css │ ├── components │ │ ├── mescroll-up.css │ │ ├── mescroll-up.vue │ │ ├── mescroll-down.css │ │ ├── mescroll-down.vue │ │ ├── mescroll-top.vue │ │ └── mescroll-empty.vue │ ├── mixins │ │ ├── mescroll-comp.js │ │ ├── mescroll-more-item.js │ │ └── mescroll-more.js │ ├── mescroll-uni-option.js │ └── mescroll-mixins.js ├── empty │ └── index.vue ├── none │ └── index.vue └── search │ └── index.vue ├── uview-ui ├── libs │ ├── css │ │ ├── style.nvue.scss │ │ ├── style.components.scss │ │ ├── style.h5.scss │ │ └── style.mp.scss │ ├── function │ │ ├── bem.js │ │ ├── sys.js │ │ ├── toast.js │ │ ├── randomArray.js │ │ ├── random.js │ │ ├── addUnit.js │ │ ├── trim.js │ │ ├── $parent.js │ │ ├── deepClone.js │ │ ├── debounce.js │ │ ├── throttle.js │ │ ├── color.js │ │ ├── deepMerge.js │ │ ├── type2icon.js │ │ ├── guid.js │ │ ├── timeFrom.js │ │ ├── getParent.js │ │ ├── timeFormat.js │ │ └── queryParams.js │ ├── config │ │ ├── config.js │ │ └── zIndex.js │ ├── mixin │ │ ├── mpShare.js │ │ └── mixin.js │ ├── store │ │ └── index.js │ └── util │ │ ├── province.js │ │ └── emitter.js ├── components │ ├── u-loading-page │ │ └── u-loading-page.vue │ ├── u-parse │ │ └── libs │ │ │ └── handler.wxs │ ├── u-tr │ │ └── u-tr.vue │ ├── u-time-line │ │ └── u-time-line.vue │ ├── u-full-screen │ │ └── u-full-screen.vue │ ├── u-gap │ │ └── u-gap.vue │ ├── u-th │ │ └── u-th.vue │ ├── u-cell-group │ │ └── u-cell-group.vue │ ├── u-td │ │ └── u-td.vue │ ├── u-time-line-item │ │ └── u-time-line-item.vue │ └── u-table │ │ └── u-table.vue ├── index.scss ├── package.json ├── LICENSE └── theme.scss ├── common ├── constant │ ├── index.js │ └── paginate.js ├── enum │ ├── store │ │ └── page │ │ │ └── category │ │ │ ├── index.js │ │ │ └── Style.js │ ├── order │ │ ├── DeliveryType.js │ │ ├── PayStatus.js │ │ ├── ReceiptStatus.js │ │ ├── DeliveryStatus.js │ │ ├── refund │ │ │ ├── index.js │ │ │ ├── RefundType.js │ │ │ ├── AuditStatus.js │ │ │ └── RefundStatus.js │ │ ├── OrderSource.js │ │ ├── index.js │ │ ├── PayType.js │ │ └── OrderStatus.js │ ├── coupon │ │ ├── index.js │ │ ├── ApplyRange.js │ │ ├── ExpireType.js │ │ └── CouponType.js │ ├── setting │ │ └── Key.js │ └── enum.js └── model │ ├── Setting.js │ └── Region.js ├── static ├── empty.png ├── nav │ ├── 1.png │ ├── 2.png │ ├── 3.png │ └── 4.png ├── empty-02.png ├── icon │ ├── add.png │ ├── coupon.png │ ├── minus.png │ ├── saoma.png │ └── saoyisao.png ├── pay │ ├── fail.png │ └── success.png ├── user │ └── tag.png ├── confirm │ ├── do.png │ └── undo.png ├── tabbar │ ├── cart.png │ ├── cate.png │ ├── home.png │ ├── shop.png │ ├── user.png │ ├── cart-active.png │ ├── cate-active.png │ ├── home-active.png │ ├── shop-active.png │ └── user-active.png ├── channel │ └── wechat.png ├── default-avatar.png ├── order │ ├── refund-bg.png │ └── status │ │ ├── close.png │ │ ├── received.png │ │ ├── wait_pay.png │ │ ├── wait_deliver.png │ │ └── wait_receipt.png └── background │ └── user-header.png ├── store ├── modules │ ├── index.js │ └── app.js ├── mutation-types.js ├── getters.js └── index.js ├── uni_modules ├── uni-row │ ├── changelog.md │ └── package.json └── uni-popup │ ├── components │ ├── uni-popup │ │ ├── popup.js │ │ └── keypress.js │ └── uni-popup-dialog │ │ └── keypress.js │ ├── changelog.md │ └── package.json ├── config.js ├── package.json ├── api ├── goods │ └── service.js ├── page.js ├── help.js ├── user │ └── coupon.js ├── confirm.js ├── merchant │ ├── recharge.js │ ├── member.js │ ├── order.js │ ├── staff.js │ ├── book.js │ └── coupon.js ├── region.js ├── points │ └── log.js ├── give.js ├── share.js ├── article.js ├── upload.js ├── balance.js ├── message.js ├── cart.js ├── setting.js ├── goods.js ├── coupon.js ├── settlement.js ├── merchant.js ├── refund.js ├── address.js ├── order.js ├── myCoupon.js ├── login │ └── index.js ├── user.js └── book.js ├── utils ├── request │ └── request.js ├── iconfont-new.scss ├── verify.js └── storage.js ├── pages ├── empty.vue ├── pay │ └── components │ │ └── Popup.vue ├── user │ └── components │ │ └── Popup.vue ├── prestore │ └── components │ │ └── Popup.vue ├── article │ └── detail.vue └── goods │ └── components │ └── SlideImage.vue ├── core └── bootstrap.js ├── app.scss ├── .hbuilderx └── launch.json ├── main.js ├── App.vue ├── subPages └── prestore │ └── components │ └── Popup.vue └── uni.scss /components/common/style/var.wxss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /components/common/style/mixins/clearfix.wxss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /components/common/style/mixins/ellipsis.wxss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /components/common/style/mixins/hairline.wxss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /components/btn/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "component": true 3 | } -------------------------------------------------------------------------------- /components/loading/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "component": true 3 | } -------------------------------------------------------------------------------- /components/toptips/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "component": true 3 | } -------------------------------------------------------------------------------- /components/pop-manager/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "component": true 3 | } 4 | -------------------------------------------------------------------------------- /uview-ui/libs/css/style.nvue.scss: -------------------------------------------------------------------------------- 1 | .nvue { 2 | font-size: 24rpx; 3 | } -------------------------------------------------------------------------------- /common/constant/index.js: -------------------------------------------------------------------------------- 1 | import paginate from './paginate' 2 | 3 | export { paginate } 4 | -------------------------------------------------------------------------------- /static/empty.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fushengqian/fuintUniapp/HEAD/static/empty.png -------------------------------------------------------------------------------- /static/nav/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fushengqian/fuintUniapp/HEAD/static/nav/1.png -------------------------------------------------------------------------------- /static/nav/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fushengqian/fuintUniapp/HEAD/static/nav/2.png -------------------------------------------------------------------------------- /static/nav/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fushengqian/fuintUniapp/HEAD/static/nav/3.png -------------------------------------------------------------------------------- /static/nav/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fushengqian/fuintUniapp/HEAD/static/nav/4.png -------------------------------------------------------------------------------- /components/common/style/clearfix.wxss: -------------------------------------------------------------------------------- 1 | .van-clearfix::after{content:'';display:table;clear:both} -------------------------------------------------------------------------------- /static/empty-02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fushengqian/fuintUniapp/HEAD/static/empty-02.png -------------------------------------------------------------------------------- /static/icon/add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fushengqian/fuintUniapp/HEAD/static/icon/add.png -------------------------------------------------------------------------------- /static/pay/fail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fushengqian/fuintUniapp/HEAD/static/pay/fail.png -------------------------------------------------------------------------------- /static/user/tag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fushengqian/fuintUniapp/HEAD/static/user/tag.png -------------------------------------------------------------------------------- /static/confirm/do.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fushengqian/fuintUniapp/HEAD/static/confirm/do.png -------------------------------------------------------------------------------- /static/icon/coupon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fushengqian/fuintUniapp/HEAD/static/icon/coupon.png -------------------------------------------------------------------------------- /static/icon/minus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fushengqian/fuintUniapp/HEAD/static/icon/minus.png -------------------------------------------------------------------------------- /static/icon/saoma.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fushengqian/fuintUniapp/HEAD/static/icon/saoma.png -------------------------------------------------------------------------------- /static/pay/success.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fushengqian/fuintUniapp/HEAD/static/pay/success.png -------------------------------------------------------------------------------- /static/tabbar/cart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fushengqian/fuintUniapp/HEAD/static/tabbar/cart.png -------------------------------------------------------------------------------- /static/tabbar/cate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fushengqian/fuintUniapp/HEAD/static/tabbar/cate.png -------------------------------------------------------------------------------- /static/tabbar/home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fushengqian/fuintUniapp/HEAD/static/tabbar/home.png -------------------------------------------------------------------------------- /static/tabbar/shop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fushengqian/fuintUniapp/HEAD/static/tabbar/shop.png -------------------------------------------------------------------------------- /static/tabbar/user.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fushengqian/fuintUniapp/HEAD/static/tabbar/user.png -------------------------------------------------------------------------------- /static/confirm/undo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fushengqian/fuintUniapp/HEAD/static/confirm/undo.png -------------------------------------------------------------------------------- /static/icon/saoyisao.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fushengqian/fuintUniapp/HEAD/static/icon/saoyisao.png -------------------------------------------------------------------------------- /uview-ui/libs/function/bem.js: -------------------------------------------------------------------------------- 1 | function bem(name, conf) { 2 | 3 | } 4 | 5 | module.exports.bem = bem; 6 | -------------------------------------------------------------------------------- /static/channel/wechat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fushengqian/fuintUniapp/HEAD/static/channel/wechat.png -------------------------------------------------------------------------------- /static/default-avatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fushengqian/fuintUniapp/HEAD/static/default-avatar.png -------------------------------------------------------------------------------- /static/order/refund-bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fushengqian/fuintUniapp/HEAD/static/order/refund-bg.png -------------------------------------------------------------------------------- /static/order/status/close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fushengqian/fuintUniapp/HEAD/static/order/status/close.png -------------------------------------------------------------------------------- /static/tabbar/cart-active.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fushengqian/fuintUniapp/HEAD/static/tabbar/cart-active.png -------------------------------------------------------------------------------- /static/tabbar/cate-active.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fushengqian/fuintUniapp/HEAD/static/tabbar/cate-active.png -------------------------------------------------------------------------------- /static/tabbar/home-active.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fushengqian/fuintUniapp/HEAD/static/tabbar/home-active.png -------------------------------------------------------------------------------- /static/tabbar/shop-active.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fushengqian/fuintUniapp/HEAD/static/tabbar/shop-active.png -------------------------------------------------------------------------------- /static/tabbar/user-active.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fushengqian/fuintUniapp/HEAD/static/tabbar/user-active.png -------------------------------------------------------------------------------- /static/order/status/received.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fushengqian/fuintUniapp/HEAD/static/order/status/received.png -------------------------------------------------------------------------------- /static/order/status/wait_pay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fushengqian/fuintUniapp/HEAD/static/order/status/wait_pay.png -------------------------------------------------------------------------------- /components/common/color.js: -------------------------------------------------------------------------------- 1 | export const RED = '#f44'; 2 | export const BLUE = '#1989fa'; 3 | export const GREEN = '#07c160'; 4 | -------------------------------------------------------------------------------- /static/background/user-header.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fushengqian/fuintUniapp/HEAD/static/background/user-header.png -------------------------------------------------------------------------------- /store/modules/index.js: -------------------------------------------------------------------------------- 1 | import app from './app' 2 | import user from './user' 3 | 4 | export { 5 | app, 6 | user 7 | } 8 | -------------------------------------------------------------------------------- /common/enum/store/page/category/index.js: -------------------------------------------------------------------------------- 1 | import PageCategoryStyleEnum from './Style' 2 | 3 | export { PageCategoryStyleEnum } 4 | -------------------------------------------------------------------------------- /static/order/status/wait_deliver.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fushengqian/fuintUniapp/HEAD/static/order/status/wait_deliver.png -------------------------------------------------------------------------------- /static/order/status/wait_receipt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fushengqian/fuintUniapp/HEAD/static/order/status/wait_receipt.png -------------------------------------------------------------------------------- /components/actionsheet/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "component": true, 3 | "usingComponents": { 4 | "zan-btn": "../btn/index" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /components/switch/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "component": true, 3 | "usingComponents": { 4 | "van-loading": "../loading/index" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /uni_modules/uni-row/changelog.md: -------------------------------------------------------------------------------- 1 | ## 0.0.4(2021-05-12) 2 | - 新增 组件示例地址 3 | ## 0.0.3(2021-02-05) 4 | - 调整为uni_modules目录规范 5 | - 新增uni-row组件 6 | -------------------------------------------------------------------------------- /components/popup/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "component": true, 3 | "usingComponents": { 4 | "pop-manager": "../pop-manager/index" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /store/mutation-types.js: -------------------------------------------------------------------------------- 1 | export const ACCESS_TOKEN = 'AccessToken' 2 | export const USER_ID = 'userId' 3 | export const PLATFORM = 'platform' 4 | -------------------------------------------------------------------------------- /components/wxs/array.wxs: -------------------------------------------------------------------------------- 1 | function isArray(array) { 2 | return array && array.constructor === 'Array'; 3 | } 4 | 5 | module.exports.isArray = isArray; 6 | -------------------------------------------------------------------------------- /components/toptips/index.wxml: -------------------------------------------------------------------------------- 1 | {{ content }} 2 | -------------------------------------------------------------------------------- /components/dialog/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "component": true, 3 | "usingComponents": { 4 | "pop-manager": "../pop-manager/index", 5 | "zan-button": "../btn/index" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /common/constant/paginate.js: -------------------------------------------------------------------------------- 1 | export default { 2 | content: [], // 列表数据 3 | currentPage: 1, // 当前页码 4 | totalPages: 1, // 最大页码 5 | pageSize: 15, // 每页记录数 6 | totalElements: 0, // 总记录数 7 | } 8 | -------------------------------------------------------------------------------- /store/getters.js: -------------------------------------------------------------------------------- 1 | const getters = { 2 | token: state => state.user.token, 3 | userId: state => state.user.userId, 4 | platform: state => state.app.platform 5 | } 6 | 7 | export default getters 8 | -------------------------------------------------------------------------------- /components/popup/index.wxml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /uview-ui/libs/function/sys.js: -------------------------------------------------------------------------------- 1 | export function os() { 2 | return uni.getSystemInfoSync().platform; 3 | }; 4 | 5 | export function sys() { 6 | return uni.getSystemInfoSync(); 7 | } 8 | 9 | 10 | -------------------------------------------------------------------------------- /common/enum/order/DeliveryType.js: -------------------------------------------------------------------------------- 1 | import Enum from '../enum' 2 | 3 | /** 4 | * 枚举类:配送方式 5 | * DeliveryTypeEnum 6 | */ 7 | export default new Enum([ 8 | { key: 'EXPRESS', name: '快递配送', value: 10 } 9 | ]) 10 | -------------------------------------------------------------------------------- /config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | // 系统名称 3 | name: "fuint会员系统", 4 | // 必填: 后端api地址, 斜杠/结尾 5 | apiUrl: "https://www.fuint.cn/fuint-application/", 6 | // 必填: 默认商户号,从后台商户列表获取 7 | merchantNo: "10001" 8 | } 9 | -------------------------------------------------------------------------------- /common/enum/coupon/index.js: -------------------------------------------------------------------------------- 1 | import ApplyRangeEnum from './ApplyRange' 2 | import ExpireTypeEnum from './ExpireType' 3 | import CouponTypeEnum from './CouponType' 4 | 5 | export { ApplyRangeEnum, CouponTypeEnum, ExpireTypeEnum } 6 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "neoceansoft-keyboard", 3 | "name": "身份证/数字键盘/密码键盘/支付键盘", 4 | "version": "1.0.3", 5 | "description": "数字键盘/密码键盘,下个版本更新支付键盘", 6 | "keywords": [ 7 | "数字键盘、密码键盘、支付键盘" 8 | ] 9 | } -------------------------------------------------------------------------------- /api/goods/service.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | // api地址 4 | const api = { 5 | list: 'clientApi/goods/service/list' 6 | } 7 | 8 | // 商品评价列表 9 | export function list(goodsId) { 10 | return; 11 | } 12 | -------------------------------------------------------------------------------- /api/page.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | // api地址 4 | const apiUri = { 5 | home: 'clientApi/page/home' 6 | } 7 | 8 | // 页面数据 9 | export function home() { 10 | return request.get(apiUri.home) 11 | } 12 | -------------------------------------------------------------------------------- /uview-ui/libs/function/toast.js: -------------------------------------------------------------------------------- 1 | function toast(title, duration = 1500) { 2 | uni.showToast({ 3 | title: title, 4 | icon: 'none', 5 | duration: duration 6 | }) 7 | } 8 | 9 | export default toast 10 | -------------------------------------------------------------------------------- /uview-ui/libs/css/style.components.scss: -------------------------------------------------------------------------------- 1 | // 定义混入指令,用于在非nvue环境下的flex定义,因为nvue没有display属性,会报错 2 | @mixin vue-flex($direction: row) { 3 | /* #ifndef APP-NVUE */ 4 | display: flex; 5 | flex-direction: $direction; 6 | /* #endif */ 7 | } -------------------------------------------------------------------------------- /uview-ui/libs/css/style.h5.scss: -------------------------------------------------------------------------------- 1 | /* H5的时候,隐藏滚动条 */ 2 | ::-webkit-scrollbar { 3 | display: none; 4 | width: 0 !important; 5 | height: 0 !important; 6 | -webkit-appearance: none; 7 | background: transparent; 8 | } 9 | -------------------------------------------------------------------------------- /api/help.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | // api地址 4 | const api = { 5 | list: 'clientApi/article/list' 6 | } 7 | 8 | // 帮助中心列表 9 | export const list = (param) => { 10 | return request.post(api.list, param) 11 | } 12 | -------------------------------------------------------------------------------- /uview-ui/libs/function/randomArray.js: -------------------------------------------------------------------------------- 1 | // 打乱数组 2 | function randomArray(array = []) { 3 | // 原理是sort排序,Math.random()产生0<= x < 1之间的数,会导致x-0.05大于或者小于0 4 | return array.sort(() => Math.random() - 0.5); 5 | } 6 | 7 | export default randomArray 8 | -------------------------------------------------------------------------------- /common/enum/order/PayStatus.js: -------------------------------------------------------------------------------- 1 | import Enum from '../enum' 2 | 3 | /** 4 | * 枚举类:订单支付状态 5 | * PayStatusEnum 6 | */ 7 | export default new Enum([ 8 | { key: 'PENDING', name: '待支付', value: 10 }, 9 | { key: 'SUCCESS', name: '已支付', value: 20 } 10 | ]) 11 | -------------------------------------------------------------------------------- /api/user/coupon.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | // api地址 4 | const api = { 5 | receive: 'clientApi/user/coupon/receive' 6 | } 7 | 8 | // 优惠券列表 9 | export const receive = (data) => { 10 | return request.post(api.receive, data) 11 | } 12 | -------------------------------------------------------------------------------- /common/enum/coupon/ApplyRange.js: -------------------------------------------------------------------------------- 1 | import Enum from '../enum' 2 | 3 | /** 4 | * 枚举类:优惠券适用范围 5 | * ApplyRangeEnum 6 | */ 7 | export default new Enum([ 8 | { key: 'ALL', name: '全部商品', value: 10 }, 9 | { key: 'SOME_GOODS', name: '指定商品', value: 20 } 10 | ]) 11 | -------------------------------------------------------------------------------- /common/enum/coupon/ExpireType.js: -------------------------------------------------------------------------------- 1 | import Enum from '../enum' 2 | 3 | /** 4 | * 枚举类:优惠券到期类型 5 | * ExpireTypeEnum 6 | */ 7 | export default new Enum([ 8 | { key: 'RECEIVE', name: '领取后', value: 10 }, 9 | { key: 'FIXED_TIME', name: '固定时间', value: 20 } 10 | ]) 11 | -------------------------------------------------------------------------------- /common/enum/order/ReceiptStatus.js: -------------------------------------------------------------------------------- 1 | import Enum from '../enum' 2 | 3 | /** 4 | * 枚举类:订单收货状态 5 | * ReceiptStatusEnum 6 | */ 7 | export default new Enum([ 8 | { key: 'NOT_RECEIVED', name: '未收货', value: 10 }, 9 | { key: 'RECEIVED', name: '已收货', value: 20 } 10 | ]) 11 | -------------------------------------------------------------------------------- /common/enum/order/DeliveryStatus.js: -------------------------------------------------------------------------------- 1 | import Enum from '../enum' 2 | 3 | /** 4 | * 枚举类:订单发货状态 5 | * DeliveryStatusEnum 6 | */ 7 | export default new Enum([ 8 | { key: 'NOT_DELIVERED', name: '未发货', value: 10 }, 9 | { key: 'DELIVERED', name: '已发货', value: 20 } 10 | ]) 11 | -------------------------------------------------------------------------------- /common/enum/order/refund/index.js: -------------------------------------------------------------------------------- 1 | import AuditStatusEnum from './AuditStatus' 2 | import RefundStatusEnum from './RefundStatus' 3 | import RefundTypeEnum from './RefundType' 4 | 5 | export { 6 | AuditStatusEnum, 7 | RefundStatusEnum, 8 | RefundTypeEnum 9 | } 10 | -------------------------------------------------------------------------------- /common/enum/order/refund/RefundType.js: -------------------------------------------------------------------------------- 1 | import Enum from '../../enum' 2 | 3 | /** 4 | * 枚举类:售后类型 5 | * RefundTypeEnum 6 | */ 7 | export default new Enum([ 8 | { key: 'RETURN', name: '退货退款', value: 'return' }, 9 | { key: 'EXCHANGE', name: '换货', value: 'exchange' } 10 | ]) 11 | -------------------------------------------------------------------------------- /api/confirm.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | // api地址 4 | const api = { 5 | doConfirm: 'clientApi/confirm/doConfirm', 6 | } 7 | 8 | // 确定核销 9 | export function doConfirm(code, amount, remark) { 10 | return request.post(api.doConfirm, { code, amount, remark }) 11 | } -------------------------------------------------------------------------------- /utils/request/request.js: -------------------------------------------------------------------------------- 1 | /***************纯粹的数据请求(如果使用这种可以删除掉fileUpload.js)******************/ 2 | // import request from "./core/request.js"; 3 | // export default request; 4 | 5 | /********数据请求同时继承了文件上传(包括七牛云上传)************/ 6 | import upload from "./upload/upload" 7 | export default upload 8 | -------------------------------------------------------------------------------- /common/enum/coupon/CouponType.js: -------------------------------------------------------------------------------- 1 | import Enum from '../enum' 2 | 3 | /** 4 | * 枚举类:卡券类型 5 | * CouponTypeEnum 6 | */ 7 | export default new Enum([ 8 | { key: 'C', name: '优惠券', value: 1000 }, 9 | { key: 'P', name: '储值卡', value: 2000 }, 10 | { key: 'T', name: '计次卡', value: 3000 } 11 | ]) 12 | -------------------------------------------------------------------------------- /uview-ui/libs/function/random.js: -------------------------------------------------------------------------------- 1 | function random(min, max) { 2 | if (min >= 0 && max > 0 && max >= min) { 3 | let gab = max - min + 1; 4 | return Math.floor(Math.random() * gab + min); 5 | } else { 6 | return 0; 7 | } 8 | } 9 | 10 | export default random; 11 | -------------------------------------------------------------------------------- /common/enum/order/OrderSource.js: -------------------------------------------------------------------------------- 1 | import Enum from '../enum' 2 | 3 | /** 4 | * 枚举类:订单来源 5 | * OrderSourceEnum 6 | */ 7 | export default new Enum([ 8 | { key: 'MASTER', name: '普通订单', value: 10 }, 9 | { key: 'BARGAIN', name: '砍价订单', value: 20 }, 10 | { key: 'SHARP', name: '秒杀订单', value: 30 } 11 | ]) 12 | -------------------------------------------------------------------------------- /uview-ui/libs/config/config.js: -------------------------------------------------------------------------------- 1 | // 此版本发布于2020-12-17 2 | let version = '1.8.3'; 3 | 4 | export default { 5 | v: version, 6 | version: version, 7 | // 主题名称 8 | type: [ 9 | 'primary', 10 | 'success', 11 | 'info', 12 | 'error', 13 | 'warning' 14 | ] 15 | } -------------------------------------------------------------------------------- /common/enum/order/refund/AuditStatus.js: -------------------------------------------------------------------------------- 1 | import Enum from '../../enum' 2 | 3 | /** 4 | * 枚举类:商家审核状态 5 | * AuditStatusEnum 6 | */ 7 | export default new Enum([ 8 | { key: 'WAIT', name: '待审核', value: 0 }, 9 | { key: 'REVIEWED', name: '已同意', value: 10 }, 10 | { key: 'REJECTED', name: '已拒绝', value: 20 } 11 | ]) 12 | -------------------------------------------------------------------------------- /components/wxs/object.wxs: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | var REGEXP = getRegExp('{|}|"', 'g'); 3 | 4 | function keys(obj) { 5 | return JSON.stringify(obj) 6 | .replace(REGEXP, '') 7 | .split(',') 8 | .map(function(item) { 9 | return item.split(':')[0]; 10 | }); 11 | } 12 | 13 | module.exports.keys = keys; 14 | -------------------------------------------------------------------------------- /uview-ui/libs/function/addUnit.js: -------------------------------------------------------------------------------- 1 | import validation from './test.js'; 2 | 3 | // 添加单位,如果有rpx,%,px等单位结尾或者值为auto,直接返回,否则加上rpx单位结尾 4 | export default function addUnit(value = 'auto', unit = 'rpx') { 5 | value = String(value); 6 | // 用uView内置验证规则中的number判断是否为数值 7 | return validation.number(value) ? `${value}${unit}` : value; 8 | } -------------------------------------------------------------------------------- /api/merchant/recharge.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | // api地址 4 | const api = { 5 | doRecharge: 'merchantApi/balance/doRecharge', 6 | } 7 | 8 | // 提交充值 9 | export const doRecharge = (rechargeAmount, customAmount, memberId) => { 10 | return request.post(api.doRecharge, { rechargeAmount, customAmount, memberId }) 11 | } -------------------------------------------------------------------------------- /common/enum/order/refund/RefundStatus.js: -------------------------------------------------------------------------------- 1 | import Enum from '../../enum' 2 | 3 | /** 4 | * 枚举类:售后单状态 5 | * RefundStatusEnum 6 | */ 7 | export default new Enum([ 8 | { key: 'A', name: '待审核' }, 9 | { key: 'B', name: '已同意' }, 10 | { key: 'C', name: '已拒绝' }, 11 | { key: 'D', name: '已取消' }, 12 | { key: 'E', name: '已完成' } 13 | ]) 14 | -------------------------------------------------------------------------------- /common/enum/store/page/category/Style.js: -------------------------------------------------------------------------------- 1 | import Enum from '../../../enum' 2 | 3 | /** 4 | * 枚举类:地址类型 5 | * PageCategoryStyleEnum 6 | */ 7 | export default new Enum([ 8 | { key: 'ONE_LEVEL_BIG', name: '一级分类[大图]', value: 10 }, 9 | { key: 'ONE_LEVEL_SMALL', name: '一级分类[小图]', value: 11 }, 10 | { key: 'TWO_LEVEL', name: '二级分类', value: 20 } 11 | ]) 12 | -------------------------------------------------------------------------------- /components/common/style/ellipsis.wxss: -------------------------------------------------------------------------------- 1 | .van-ellipsis{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.van-multi-ellipsis--l2{overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}.van-multi-ellipsis--l3{overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical} -------------------------------------------------------------------------------- /components/pop-manager/index.wxml: -------------------------------------------------------------------------------- 1 | 4 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /components/wxs/utils.wxs: -------------------------------------------------------------------------------- 1 | var bem = require('./bem.wxs').bem; 2 | var memoize = require('./memoize.wxs').memoize; 3 | 4 | function isSrc(url) { 5 | return url.indexOf('http') === 0 || url.indexOf('data:image') === 0 || url.indexOf('//') === 0; 6 | } 7 | 8 | module.exports = { 9 | bem: memoize(bem), 10 | isSrc: isSrc, 11 | memoize: memoize 12 | }; 13 | -------------------------------------------------------------------------------- /components/toptips/index.wxss: -------------------------------------------------------------------------------- 1 | .zan-toptips{display:block;position:fixed;-webkit-transform:translateZ(0) translateY(-100%);width:100%;min-height:32px;top:0;line-height:2.3;font-size:14px;text-align:center;color:#fff;background-color:#e64340;z-index:110;opacity:0;-webkit-transition:all .4s ease;transition:all .4s ease}.zan-toptips--show{-webkit-transform:translateZ(0) translateY(0);opacity:1} -------------------------------------------------------------------------------- /api/region.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | // api地址 4 | const api = { 5 | all: 'clientApi/region/all', 6 | tree: 'clientApi/region/tree' 7 | } 8 | 9 | // 获取所有地区 10 | export const all = (param) => { 11 | return request.get(api.all, param) 12 | } 13 | 14 | // 获取所有地区(树状) 15 | export const tree = (param) => { 16 | return request.get(api.tree, param) 17 | } 18 | -------------------------------------------------------------------------------- /api/points/log.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | // api地址 4 | const api = { 5 | list: 'clientApi/points/list', 6 | gift: 'clientApi/points/doGive' 7 | } 8 | 9 | // 积分明细列表 10 | export const list = (param) => { 11 | return request.get(api.list, param) 12 | } 13 | 14 | // 积分转赠 15 | export const gift = (param) => { 16 | return request.post(api.gift, param) 17 | } 18 | -------------------------------------------------------------------------------- /api/give.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | // api地址 4 | const api = { 5 | doGive: 'clientApi/give/doGive', 6 | giveLog: 'clientApi/give/giveLog' 7 | } 8 | 9 | // 转赠 10 | export const doGive = (data) => { 11 | return request.post(api.doGive, data) 12 | } 13 | 14 | // 转赠记录 15 | export const giveLog = (param, option) => { 16 | return request.post(api.giveLog, param) 17 | } 18 | -------------------------------------------------------------------------------- /pages/empty.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 26 | 27 | 30 | -------------------------------------------------------------------------------- /common/enum/setting/Key.js: -------------------------------------------------------------------------------- 1 | import Enum from '../enum' 2 | 3 | /** 4 | * 枚举类:设置项索引 5 | * SettingKeyEnum 6 | */ 7 | export default new Enum([{ 8 | key: 'PAGE_CATEGORY_TEMPLATE', 9 | name: '分类页模板', 10 | value: 'page_category_template' 11 | }, { 12 | key: 'POINTS', 13 | name: '积分设置', 14 | value: 'points' 15 | }, { 16 | key: 'RECHARGE', 17 | name: '充值设置', 18 | value: 'recharge' 19 | }]) 20 | -------------------------------------------------------------------------------- /store/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Vuex from 'vuex' 3 | import { 4 | app, 5 | user 6 | } from './modules' 7 | import getters from './getters' 8 | 9 | Vue.use(Vuex) 10 | 11 | export default new Vuex.Store({ 12 | modules: { 13 | app, 14 | user 15 | }, 16 | state: { 17 | 18 | }, 19 | mutations: { 20 | 21 | }, 22 | actions: { 23 | 24 | }, 25 | getters 26 | }) 27 | -------------------------------------------------------------------------------- /store/modules/app.js: -------------------------------------------------------------------------------- 1 | import { 2 | PLATFORM 3 | } from '@/store/mutation-types' 4 | import storage from '@/utils/storage' 5 | 6 | 7 | const app = { 8 | state: { 9 | // 当前终端平台 10 | platform: '' 11 | }, 12 | 13 | mutations: { 14 | SET_PLATFORM: (state, value) => { 15 | state.platform = value 16 | } 17 | }, 18 | 19 | actions: { 20 | 21 | } 22 | } 23 | 24 | export default app 25 | -------------------------------------------------------------------------------- /api/share.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | // api地址 4 | const api = { 5 | list: 'clientApi/share/list', 6 | getMiniAppLink: 'clientApi/share/getMiniAppLink' 7 | } 8 | 9 | // 分享列表 10 | export const list = (param) => { 11 | return request.post(api.list, param) 12 | } 13 | 14 | // 生成小程序链接 15 | export const getMiniAppLink = (param) => { 16 | return request.post(api.getMiniAppLink, param) 17 | } 18 | -------------------------------------------------------------------------------- /components/loading/index.js: -------------------------------------------------------------------------------- 1 | import { VantComponent } from '../common/component'; 2 | VantComponent({ 3 | props: { 4 | size: { 5 | type: String, 6 | value: '30px' 7 | }, 8 | type: { 9 | type: String, 10 | value: 'circular' 11 | }, 12 | color: { 13 | type: String, 14 | value: '#c9c9c9' 15 | } 16 | } 17 | }); 18 | -------------------------------------------------------------------------------- /components/loading/index.wxml: -------------------------------------------------------------------------------- 1 | 5 | 9 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /uview-ui/libs/config/zIndex.js: -------------------------------------------------------------------------------- 1 | // uniapp在H5中各API的z-index值如下: 2 | /** 3 | * actionsheet: 999 4 | * modal: 999 5 | * navigate: 998 6 | * tabbar: 998 7 | * toast: 999 8 | */ 9 | 10 | export default { 11 | toast: 10090, 12 | noNetwork: 10080, 13 | // popup包含popup,actionsheet,keyboard,picker的值 14 | popup: 10075, 15 | mask: 10070, 16 | navbar: 980, 17 | topTips: 975, 18 | sticky: 970, 19 | indexListSticky: 965, 20 | } -------------------------------------------------------------------------------- /components/common/utils.js: -------------------------------------------------------------------------------- 1 | function isDef(value) { 2 | return value !== undefined && value !== null; 3 | } 4 | function isObj(x) { 5 | const type = typeof x; 6 | return x !== null && (type === 'object' || type === 'function'); 7 | } 8 | function isNumber(value) { 9 | return /^\d+$/.test(value); 10 | } 11 | function range(num, min, max) { 12 | return Math.min(Math.max(num, min), max); 13 | } 14 | export { isObj, isDef, isNumber, range }; 15 | -------------------------------------------------------------------------------- /components/mixins/link.js: -------------------------------------------------------------------------------- 1 | export const link = Behavior({ 2 | properties: { 3 | url: String, 4 | linkType: { 5 | type: String, 6 | value: 'navigateTo' 7 | } 8 | }, 9 | methods: { 10 | jumpLink(urlKey = 'url') { 11 | const url = this.data[urlKey]; 12 | if (url) { 13 | wx[this.data.linkType]({ url }); 14 | } 15 | } 16 | } 17 | }); 18 | -------------------------------------------------------------------------------- /core/bootstrap.js: -------------------------------------------------------------------------------- 1 | import store from '@/store' 2 | import storage from '@/utils/storage' 3 | import { getPlatform } from '@/utils/app' 4 | import { ACCESS_TOKEN, USER_ID } from '@/store/mutation-types' 5 | 6 | export default function Initializer() { 7 | // 当前运行的终端 8 | store.commit('SET_PLATFORM', getPlatform()) 9 | // 用户认证token 10 | store.commit('SET_TOKEN', storage.get(ACCESS_TOKEN)) 11 | // 当前用户ID 12 | store.commit('SET_USER_ID', storage.get(USER_ID)) 13 | } 14 | -------------------------------------------------------------------------------- /uview-ui/libs/function/trim.js: -------------------------------------------------------------------------------- 1 | function trim(str, pos = 'both') { 2 | if (pos == 'both') { 3 | return str.replace(/^\s+|\s+$/g, ""); 4 | } else if (pos == "left") { 5 | return str.replace(/^\s*/, ''); 6 | } else if (pos == 'right') { 7 | return str.replace(/(\s*$)/g, ""); 8 | } else if (pos == 'all') { 9 | return str.replace(/\s+/g, ""); 10 | } else { 11 | return str; 12 | } 13 | } 14 | 15 | export default trim 16 | -------------------------------------------------------------------------------- /components/page/mixin.js: -------------------------------------------------------------------------------- 1 | import util from '@/utils/util' 2 | 3 | export default { 4 | data() { 5 | return {} 6 | }, 7 | methods: { 8 | 9 | /** 10 | * link对象点击事件 11 | * 支持tabBar页面 12 | */ 13 | onLink(linkObj) { 14 | if (!linkObj) return false 15 | // 跳转到指定页面 16 | if (linkObj.type === 'PAGE') { 17 | this.$navTo(linkObj.param.path, linkObj.param.query) 18 | } 19 | return true 20 | } 21 | }, 22 | 23 | } 24 | -------------------------------------------------------------------------------- /uview-ui/libs/mixin/mpShare.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | onLoad() { 3 | // 设置默认的转发参数 4 | this.$u.mpShare = { 5 | title: '', // 默认为小程序名称 6 | path: '', // 默认为当前页面路径 7 | imageUrl: '' // 默认为当前页面的截图 8 | } 9 | }, 10 | onShareAppMessage() { 11 | return this.$u.mpShare 12 | }, 13 | // #ifdef MP-WEIXIN 14 | onShareTimeline() { 15 | return this.$u.mpShare 16 | } 17 | // #endif 18 | } 19 | -------------------------------------------------------------------------------- /components/jyf-parser/libs/handler.wxs: -------------------------------------------------------------------------------- 1 | var inline = { 2 | abbr: 1, 3 | b: 1, 4 | big: 1, 5 | code: 1, 6 | del: 1, 7 | em: 1, 8 | i: 1, 9 | ins: 1, 10 | label: 1, 11 | q: 1, 12 | small: 1, 13 | span: 1, 14 | strong: 1, 15 | sub: 1, 16 | sup: 1 17 | } 18 | module.exports = { 19 | use: function(item) { 20 | return !item.c && !inline[item.name] && (item.attrs.style || '').indexOf('display:inline') == -1 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /uview-ui/components/u-loading-page/u-loading-page.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 22 | 23 | 26 | -------------------------------------------------------------------------------- /uview-ui/components/u-parse/libs/handler.wxs: -------------------------------------------------------------------------------- 1 | var inline = { 2 | abbr: 1, 3 | b: 1, 4 | big: 1, 5 | code: 1, 6 | del: 1, 7 | em: 1, 8 | i: 1, 9 | ins: 1, 10 | label: 1, 11 | q: 1, 12 | small: 1, 13 | span: 1, 14 | strong: 1, 15 | sub: 1, 16 | sup: 1 17 | } 18 | module.exports = { 19 | use: function(item) { 20 | return !item.c && !inline[item.name] && (item.attrs.style || '').indexOf('display:inline') == -1 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app.scss: -------------------------------------------------------------------------------- 1 | /* utils.scss */ 2 | @import "/utils/utils.scss"; 3 | 4 | page { 5 | background: #fafafa; 6 | } 7 | 8 | uni-modal { 9 | z-index: 99999999999999 !important; 10 | } 11 | 12 | @-webkit-keyframes rotate { 13 | 0% { 14 | transform: rotate(0deg) scale(1); 15 | } 16 | 17 | 100% { 18 | transform: rotate(360deg) scale(1); 19 | } 20 | } 21 | 22 | @keyframes rotate { 23 | 0% { 24 | transform: rotate(0deg) scale(1); 25 | } 26 | 27 | 100% { 28 | transform: rotate(360deg) scale(1); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /components/switch/index.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /components/mixins/button.js: -------------------------------------------------------------------------------- 1 | export const button = Behavior({ 2 | externalClasses: ['hover-class'], 3 | properties: { 4 | id: String, 5 | lang: { 6 | type: String, 7 | value: 'en' 8 | }, 9 | businessId: Number, 10 | sessionFrom: String, 11 | sendMessageTitle: String, 12 | sendMessagePath: String, 13 | sendMessageImg: String, 14 | showMessageCard: Boolean, 15 | appParameter: String, 16 | ariaLabel: String 17 | } 18 | }); 19 | -------------------------------------------------------------------------------- /api/article.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | // api地址 4 | const api = { 5 | list: 'clientApi/article/list', 6 | detail: 'clientApi/article/detail', 7 | cate: 'clientApi/article/cateList', 8 | } 9 | 10 | // 文章列表 11 | export const list = (param) => { 12 | return request.post(api.list, param) 13 | } 14 | 15 | // 文章详情 16 | export const detail = (articleId) => { 17 | return request.post(api.detail, { articleId }) 18 | } 19 | 20 | // 文章分类列表 21 | export const cateList = (param) => { 22 | return request.post(api.cate, param) 23 | } -------------------------------------------------------------------------------- /common/enum/order/index.js: -------------------------------------------------------------------------------- 1 | import DeliveryStatusEnum from './DeliveryStatus' 2 | import DeliveryTypeEnum from './DeliveryType' 3 | import OrderSourceEnum from './OrderSource' 4 | import OrderStatusEnum from './OrderStatus' 5 | import PayStatusEnum from './PayStatus' 6 | import PayTypeEnum from './PayType' 7 | import ReceiptStatusEnum from './ReceiptStatus' 8 | 9 | export { 10 | DeliveryStatusEnum, 11 | DeliveryTypeEnum, 12 | OrderSourceEnum, 13 | OrderStatusEnum, 14 | PayStatusEnum, 15 | PayTypeEnum, 16 | ReceiptStatusEnum 17 | } 18 | -------------------------------------------------------------------------------- /common/enum/order/PayType.js: -------------------------------------------------------------------------------- 1 | import Enum from '../enum' 2 | 3 | /** 4 | * 枚举类:订单支付方式 5 | * PayTypeEnum 6 | */ 7 | export default new Enum([ 8 | { key: 'BALANCE', name: '余额支付', value: 'BALANCE' }, 9 | { key: 'WECHAT', name: '微信支付', value: 'JSAPI' }, 10 | { key: 'WECHAT_H5', name: '微信H5支付', value: 'WECHAT_H5' }, 11 | { key: 'CASH', name: '现金支付', value: 'CASH' }, 12 | { key: 'STORE', name: '前台支付', value: 'STORE' }, 13 | { key: 'MICROPAY', name: '微信扫码支付', value: 'MICROPAY' }, 14 | { key: 'ALISCAN', name: '支付宝支付', value: 'ALISCAN' }, 15 | ]) 16 | -------------------------------------------------------------------------------- /components/dialog/data.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = { 4 | // 标题 5 | title: '', 6 | // 内容 7 | message: ' ', 8 | // 选择节点 9 | selector: '#zan-dialog', 10 | // 按钮是否展示为纵向 11 | buttonsShowVertical: false, 12 | // 是否展示确定 13 | showConfirmButton: true, 14 | // 确认按钮文案 15 | confirmButtonText: '确定', 16 | // 确认按钮颜色 17 | confirmButtonColor: '#3CC51F', 18 | // 是否展示取消 19 | showCancelButton: false, 20 | // 取消按钮文案 21 | cancelButtonText: '取消', 22 | // 取消按钮颜色 23 | cancelButtonColor: '#333', 24 | // 点击按钮自动关闭 dialog 25 | autoClose: true 26 | }; -------------------------------------------------------------------------------- /components/page/blank/index.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 28 | 29 | 32 | -------------------------------------------------------------------------------- /api/merchant/member.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | // api地址 4 | const api = { 5 | info: 'merchantApi/member/info', 6 | list: 'merchantApi/member/list', 7 | save: 'merchantApi/member/save', 8 | } 9 | 10 | // 会员详情 11 | export function detail(memberId, param) { 12 | return request.post(api.info, { memberId, ...param }) 13 | } 14 | 15 | // 会员列表 16 | export function list(param, option) { 17 | return request.post(api.list, param, option) 18 | } 19 | 20 | // 保存会员信息 21 | export const save = (param, option) => { 22 | return request.post(api.save, param) 23 | } -------------------------------------------------------------------------------- /api/merchant/order.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | // api地址 4 | const api = { 5 | list: 'merchantApi/order/list', 6 | detail: 'merchantApi/order/detail', 7 | confirm: 'merchantApi/order/confirm' 8 | } 9 | 10 | 11 | // 订单列表 12 | export function list(param, option) { 13 | return request.post(api.list, param, option) 14 | } 15 | 16 | // 订单详情 17 | export function detail(orderId, param) { 18 | return request.get(api.detail, { orderId, ...param }) 19 | } 20 | 21 | // 核销订单 22 | export const confirm = (param, option) => { 23 | return request.post(api.confirm, param) 24 | } -------------------------------------------------------------------------------- /api/merchant/staff.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | // api地址 4 | const api = { 5 | staffList: 'merchantApi/staff/staffList', 6 | saveStaff: 'merchantApi/staff/saveStaff', 7 | info: 'merchantApi/staff/info', 8 | } 9 | 10 | // 获取员工列表 11 | export const getStaffList = (param) => { 12 | return request.post(api.staffList, param) 13 | } 14 | 15 | // 员工详情 16 | export function info(id, param) { 17 | return request.post(api.info, { id, ...param }) 18 | } 19 | 20 | // 保存员工信息 21 | export const save = (param, option) => { 22 | return request.post(api.saveStaff, param) 23 | } -------------------------------------------------------------------------------- /api/upload.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | // api地址 4 | const api = { 5 | uploadUrl: 'clientApi/file/upload' 6 | } 7 | 8 | // 图片上传 9 | export const image = (files) => { 10 | // 文件上传大小, 2M 11 | const maxSize = 1024 * 1024 * 2; 12 | // 执行上传 13 | return new Promise((resolve, reject) => { 14 | request.urlFileUpload({ files, maxSize }) 15 | .then(result => { 16 | const fileIds = result.map(item => { 17 | return item.data; 18 | }) 19 | resolve(fileIds, result) 20 | }) 21 | .catch(err => reject(err)) 22 | }) 23 | } 24 | -------------------------------------------------------------------------------- /uview-ui/index.scss: -------------------------------------------------------------------------------- 1 | // 引入公共基础类 2 | @import "./libs/css/common.scss"; 3 | @import "./libs/css/color.scss"; 4 | 5 | // 非nvue的样式 6 | /* #ifndef APP-NVUE */ 7 | @import "./libs/css/style.vue.scss"; 8 | /* #endif */ 9 | 10 | // nvue的特有样式 11 | /* #ifdef APP-NVUE */ 12 | @import "./libs/css/style.nvue.scss"; 13 | /* #endif */ 14 | 15 | // 小程序特有的样式 16 | /* #ifdef MP */ 17 | @import "./libs/css/style.mp.scss"; 18 | /* #endif */ 19 | 20 | // H5特有的样式 21 | /* #ifdef H5 */ 22 | @import "./libs/css/style.h5.scss"; 23 | /* #endif */ 24 | 25 | /* #ifdef H5 */ 26 | uni-page-head { display: none; } 27 | /* #endif */ -------------------------------------------------------------------------------- /api/balance.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | // api地址 4 | const api = { 5 | list: 'clientApi/balance/list', 6 | setting: 'clientApi/balance/setting', 7 | doRecharge: 'clientApi/balance/doRecharge', 8 | } 9 | 10 | // 余额设置 11 | export const setting = (param) => { 12 | return request.get(api.setting, param) 13 | } 14 | 15 | // 余额明细 16 | export const list = (param) => { 17 | return request.post(api.list, param) 18 | } 19 | 20 | // 提交充值 21 | export const doRecharge = (rechargeAmount, customAmount) => { 22 | return request.post(api.doRecharge, { rechargeAmount, customAmount }) 23 | } -------------------------------------------------------------------------------- /uview-ui/components/u-tr/u-tr.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 18 | 19 | 26 | -------------------------------------------------------------------------------- /api/message.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | // api地址 4 | const api = { 5 | getOne: 'clientApi/message/getOne', 6 | readed: 'clientApi/message/readed', 7 | getSubTemplate: 'clientApi/message/getSubTemplate' 8 | } 9 | 10 | // 读取最新的一条消息 11 | export const getOne = (param, option) => { 12 | return request.get(api.getOne, param) 13 | } 14 | 15 | // 将消息置为已读 16 | export const readed = (param) => { 17 | return request.get(api.readed, param) 18 | } 19 | 20 | // 获取订阅消息模板 21 | export const getSubTemplate = (param, option) => { 22 | return request.get(api.getSubTemplate, param) 23 | } 24 | 25 | -------------------------------------------------------------------------------- /.hbuilderx/launch.json: -------------------------------------------------------------------------------- 1 | { // launch.json 配置了启动调试时相关设置,configurations下节点名称可为 app-plus/h5/mp-weixin/mp-baidu/mp-alipay/mp-qq/mp-toutiao/mp-360/ 2 | // launchtype项可配置值为local或remote, local代表前端连本地云函数,remote代表前端连云端云函数 3 | "version": "0.0", 4 | "configurations": [{ 5 | "default" : 6 | { 7 | "launchtype" : "remote" 8 | }, 9 | "h5" : 10 | { 11 | "launchtype" : "remote" 12 | }, 13 | "mp-weixin" : 14 | { 15 | "launchtype" : "remote" 16 | }, 17 | "type" : "uniCloud" 18 | } 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /common/enum/order/OrderStatus.js: -------------------------------------------------------------------------------- 1 | import Enum from '../enum' 2 | 3 | /** 4 | * 枚举类:订单状态 5 | * OrderStatusEnum 6 | */ 7 | export default new Enum([ 8 | { key: 'CREATED', name: '待支付', value: 'A' }, 9 | { key: 'PAID', name: '已支付', value: 'B' }, 10 | { key: 'CANCEL', name: '已取消', value: 'C' }, 11 | { key: 'DELIVERY', name: '待发货', value: 'D' }, 12 | { key: 'DELIVERED', name: '已发货', value: 'E' }, 13 | { key: 'RECEIVED', name: '已收货', value: 'F' }, 14 | { key: 'DELETED', name: '已删除', value: 'G' }, 15 | { key: 'REFUND', name: '已退款', value: 'H' }, 16 | { key: 'COMPLETE', name: '已完成', value: 'I' }, 17 | ]) 18 | -------------------------------------------------------------------------------- /components/pop-manager/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Component({ 4 | properties: { 5 | show: { 6 | type: Boolean, 7 | value: false 8 | }, 9 | // 是否有遮罩层 10 | overlay: { 11 | type: Boolean, 12 | value: true 13 | }, 14 | // 遮罩层是否会显示 15 | showOverlay: { 16 | type: Boolean, 17 | value: true 18 | }, 19 | // 内容从哪个方向出,可选 center top bottom left right 20 | type: { 21 | type: String, 22 | value: 'center' 23 | } 24 | }, 25 | 26 | methods: { 27 | handleMaskClick: function handleMaskClick() { 28 | this.triggerEvent('clickmask', {}); 29 | } 30 | } 31 | }); -------------------------------------------------------------------------------- /uview-ui/libs/store/index.js: -------------------------------------------------------------------------------- 1 | // 暂时不用vuex模块方式实现,将该方法直接放入到/store/index.js中 2 | const module = { 3 | actions: { 4 | $uStore({rootState}, params) { 5 | let nameArr = params.name.split('.'); 6 | if(nameArr.length >= 2) { 7 | let obj = rootState[nameArr[0]]; 8 | for(let i = 1; i < nameArr.length - 1; i ++) { 9 | obj = obj[nameArr[i]]; 10 | } 11 | obj[nameArr[nameArr.length - 1]] = params.value; 12 | } else { 13 | rootState[params.name] = params.value; 14 | } 15 | } 16 | } 17 | } 18 | 19 | export default module -------------------------------------------------------------------------------- /uview-ui/libs/function/$parent.js: -------------------------------------------------------------------------------- 1 | // 获取父组件的参数,因为支付宝小程序不支持provide/inject的写法 2 | // this.$parent在非H5中,可以准确获取到父组件,但是在H5中,需要多次this.$parent.$parent.xxx 3 | // 这里默认值等于undefined有它的含义,因为最顶层元素(组件)的$parent就是undefined,意味着不传name 4 | // 值(默认为undefined),就是查找最顶层的$parent 5 | export default function $parent(name = undefined) { 6 | let parent = this.$parent; 7 | // 通过while历遍,这里主要是为了H5需要多层解析的问题 8 | while (parent) { 9 | // 父组件 10 | if (parent.$options && parent.$options.name !== name) { 11 | // 如果组件的name不相等,继续上一级寻找 12 | parent = parent.$parent; 13 | } else { 14 | return parent; 15 | } 16 | } 17 | return false; 18 | } -------------------------------------------------------------------------------- /api/cart.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | // api地址 4 | const api = { 5 | list: 'clientApi/cart/list', 6 | save: 'clientApi/cart/save', 7 | clear: 'clientApi/cart/clear', 8 | } 9 | 10 | // 购物车列表 11 | export const list = (cartIds, goodsId, skuId, buyNum, couponId, point, orderMode) => { 12 | return request.post(api.list, { cartIds, goodsId, skuId, buyNum, couponId, point, orderMode }) 13 | } 14 | 15 | // 更新购物车 16 | export const save = (goodsId, action, skuId, buyNum) => { 17 | return request.post(api.save, { goodsId, action, skuId, buyNum }) 18 | } 19 | 20 | // 删除购物车商品 21 | export const clear = (cartId) => { 22 | return request.post(api.clear, { cartId }) 23 | } 24 | -------------------------------------------------------------------------------- /api/setting.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | // api地址 4 | const api = { 5 | recharge: 'clientApi/system/recharge', 6 | system: 'clientApi/system/config', 7 | storeList: 'clientApi/store/list', 8 | storeDetail: 'clientApi/store/detail', 9 | } 10 | 11 | // 充值配置 12 | export function recharge() { 13 | return request.get(api.recharge) 14 | } 15 | 16 | // 系统配置 17 | export function systemConfig() { 18 | return request.get(api.system) 19 | } 20 | 21 | // 店铺列表 22 | export const storeList = (keyword) => { 23 | return request.post(api.storeList, { keyword }) 24 | } 25 | 26 | // 店铺详情 27 | export function storeDetail() { 28 | return request.get(api.storeDetail) 29 | } -------------------------------------------------------------------------------- /components/switch/index.wxss: -------------------------------------------------------------------------------- 1 | @import '../common/index.wxss';.van-switch{display:inline-block;position:relative;width:2em;height:1em;border:1px solid rgba(0,0,0,.1);border-radius:1em;box-sizing:content-box;background-color:#fff;transition:background-color .3s}.van-switch__node{top:0;left:0;position:absolute;border-radius:100%;width:1em;height:1em;z-index:1;transition:.3s;box-shadow:0 3px 1px 0 rgba(0,0,0,.05),0 2px 2px 0 rgba(0,0,0,.1),0 3px 3px 0 rgba(0,0,0,.05);background-color:#fff}.van-switch__loading{top:25%;left:25%;position:absolute!important}.van-switch--on{background-color:#1989fa}.van-switch--on .van-switch__node{-webkit-transform:translateX(1em);transform:translateX(1em)}.van-switch--disabled{opacity:.4} -------------------------------------------------------------------------------- /api/goods.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | // api地址 4 | const api = { 5 | cateList: 'clientApi/goodsApi/cateList', 6 | list: 'clientApi/goodsApi/list', 7 | search: 'clientApi/goodsApi/search', 8 | detail: 'clientApi/goodsApi/detail' 9 | } 10 | 11 | // 商品分类列表 12 | export const cateList = param => { 13 | return request.get(api.cateList, param) 14 | } 15 | 16 | // 商品列表 17 | export const list = param => { 18 | return request.get(api.list, param) 19 | } 20 | 21 | // 商品搜索 22 | export const search = param => { 23 | return request.post(api.search, param) 24 | } 25 | 26 | // 商品详情 27 | export const detail = goodsId => { 28 | return request.post(api.detail, { goodsId }) 29 | } 30 | -------------------------------------------------------------------------------- /components/popup/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Component({ 4 | properties: { 5 | show: { 6 | type: Boolean, 7 | value: false 8 | }, 9 | 10 | overlay: { 11 | type: Boolean, 12 | value: true 13 | }, 14 | 15 | closeOnClickOverlay: { 16 | type: Boolean, 17 | value: true 18 | }, 19 | 20 | // 弹出方向 21 | type: { 22 | type: String, 23 | value: 'center' 24 | } 25 | }, 26 | 27 | methods: { 28 | handleMaskClick: function() { 29 | this.triggerEvent('click-overlay', {}); 30 | 31 | if (!this.data.closeOnClickOverlay) { 32 | return; 33 | } 34 | this.triggerEvent('close', {}); 35 | } 36 | } 37 | }); -------------------------------------------------------------------------------- /uview-ui/libs/function/deepClone.js: -------------------------------------------------------------------------------- 1 | // 判断arr是否为一个数组,返回一个bool值 2 | function isArray (arr) { 3 | return Object.prototype.toString.call(arr) === '[object Array]'; 4 | } 5 | 6 | // 深度克隆 7 | function deepClone (obj) { 8 | // 对常见的“非”值,直接返回原来值 9 | if([null, undefined, NaN, false].includes(obj)) return obj; 10 | if(typeof obj !== "object" && typeof obj !== 'function') { 11 | //原始类型直接返回 12 | return obj; 13 | } 14 | var o = isArray(obj) ? [] : {}; 15 | for(let i in obj) { 16 | if(obj.hasOwnProperty(i)){ 17 | o[i] = typeof obj[i] === "object" ? deepClone(obj[i]) : obj[i]; 18 | } 19 | } 20 | return o; 21 | } 22 | 23 | export default deepClone; 24 | -------------------------------------------------------------------------------- /api/coupon.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | // api地址 4 | const api = { 5 | list: 'clientApi/coupon/list', 6 | receive: 'clientApi/coupon/receive', 7 | detail: 'clientApi/coupon/detail' 8 | } 9 | 10 | // 卡券列表 11 | export const list = (param, option) => { 12 | const options = { 13 | isPrompt: true, //(默认 true 说明:本接口抛出的错误是否提示) 14 | load: true, //(默认 true 说明:本接口是否提示加载动画) 15 | ...option 16 | } 17 | return request.post(api.list, param, options) 18 | } 19 | 20 | // 领券接口 21 | export const receive = (param) => { 22 | return request.post(api.receive, param) 23 | } 24 | 25 | // 会员卡券详情 26 | export function detail(couponId) { 27 | return request.post(api.detail, { couponId }) 28 | } 29 | -------------------------------------------------------------------------------- /components/mixins/observer/props.js: -------------------------------------------------------------------------------- 1 | export function observeProps(props) { 2 | if (!props) { 3 | return; 4 | } 5 | Object.keys(props).forEach(key => { 6 | let prop = props[key]; 7 | if (prop === null || !('type' in prop)) { 8 | prop = { type: prop }; 9 | } 10 | let { observer } = prop; 11 | prop.observer = function () { 12 | if (observer) { 13 | if (typeof observer === 'string') { 14 | observer = this[observer]; 15 | } 16 | observer.apply(this, arguments); 17 | } 18 | this.set(); 19 | }; 20 | props[key] = prop; 21 | }); 22 | } 23 | -------------------------------------------------------------------------------- /uni_modules/uni-popup/components/uni-popup/popup.js: -------------------------------------------------------------------------------- 1 | 2 | export default { 3 | data() { 4 | return { 5 | 6 | } 7 | }, 8 | created(){ 9 | this.popup = this.getParent() 10 | }, 11 | methods:{ 12 | /** 13 | * 获取父元素实例 14 | */ 15 | getParent(name = 'uniPopup') { 16 | let parent = this.$parent; 17 | let parentName = parent.$options.name; 18 | while (parentName !== name) { 19 | parent = parent.$parent; 20 | if (!parent) return false 21 | parentName = parent.$options.name; 22 | } 23 | return parent; 24 | }, 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /api/settlement.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | // api地址 4 | const api = { 5 | submit: 'clientApi/settlement/submit', 6 | prePay: 'clientApi/pay/prePay', 7 | } 8 | 9 | // 结算台订单提交 10 | export const submit = (targetId, selectNum, type, remark, payAmount, usePoint, couponId, cartIds, goodsId, skuId, buyNum, orderMode, payType) => { 11 | return request.post(api.submit, { targetId, selectNum, type, remark, payAmount, usePoint, couponId, cartIds, goodsId, skuId, buyNum, orderMode, payType}) 12 | } 13 | 14 | // 支付前查询 15 | export const prePay = (param) => { 16 | return request.get(api.prePay, param) 17 | } 18 | 19 | // 发起收款 20 | export const doCashier = (param) => { 21 | return request.post(api.submit, param) 22 | } 23 | -------------------------------------------------------------------------------- /components/mescroll-uni/mescroll-body.css: -------------------------------------------------------------------------------- 1 | .mescroll-body { 2 | position: relative; /* 下拉刷新区域相对自身定位 */ 3 | height: auto; /* 不可固定高度,否则overflow:hidden导致无法滑动; 同时使设置的最小高生效,实现列表不满屏仍可下拉*/ 4 | overflow: hidden; /* 当有元素写在mescroll-body标签前面时,可遮住下拉刷新区域 */ 5 | box-sizing: border-box; /* 避免设置padding出现双滚动条的问题 */ 6 | } 7 | 8 | /* 使sticky生效: 父元素不能overflow:hidden或者overflow:auto属性 */ 9 | .mescroll-body.mescorll-sticky{ 10 | overflow: unset !important 11 | } 12 | 13 | /* 适配 iPhoneX */ 14 | @supports (bottom: constant(safe-area-inset-bottom)) or (bottom: env(safe-area-inset-bottom)) { 15 | .mescroll-safearea { 16 | padding-bottom: constant(safe-area-inset-bottom); 17 | padding-bottom: env(safe-area-inset-bottom); 18 | } 19 | } -------------------------------------------------------------------------------- /api/merchant/book.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | // api地址 4 | const api = { 5 | bookList: 'merchantApi/book/list', 6 | bookDetail: 'merchantApi/book/detail', 7 | cancel: 'merchantApi/book/cancel', 8 | confirm: 'merchantApi/book/confirm' 9 | } 10 | 11 | // 我的预约列表 12 | export const bookList = (param) => { 13 | return request.post(api.bookList, param) 14 | } 15 | 16 | // 我的预约详情 17 | export const bookDetail = (bookId) => { 18 | return request.post(api.bookDetail, { bookId }) 19 | } 20 | 21 | // 取消预约 22 | export function cancel(bookId, data) { 23 | return request.post(api.cancel, { bookId, ...data }) 24 | } 25 | 26 | // 确认预约 27 | export function confirm(bookId, status) { 28 | return request.post(api.confirm, { bookId, status }) 29 | } -------------------------------------------------------------------------------- /components/page/guide/index.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 31 | 32 | 37 | -------------------------------------------------------------------------------- /api/merchant.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | // api地址 4 | const api = { 5 | merchantInfo: 'merchantApi/merchant/info', 6 | settingInfo: 'merchantApi/merchantSetting/settingInfo', 7 | saveSetting: 'merchantApi/merchantSetting/saveSetting', 8 | } 9 | 10 | // 当前商户信息 11 | export const info = (param, option) => { 12 | const options = { 13 | isPrompt: true, //(默认 true 说明:本接口抛出的错误是否提示) 14 | load: true, //(默认 true 说明:本接口是否提示加载动画) 15 | ...option 16 | } 17 | return request.get(api.merchantInfo, param, options) 18 | } 19 | 20 | // 商户设置详情 21 | export function settingInfo() { 22 | return request.get(api.settingInfo) 23 | } 24 | 25 | // 保存商户设置信息 26 | export const saveSetting = (param, option) => { 27 | return request.post(api.saveSetting, param) 28 | } -------------------------------------------------------------------------------- /components/mixins/basic.js: -------------------------------------------------------------------------------- 1 | export const basic = Behavior({ 2 | methods: { 3 | $emit() { 4 | this.triggerEvent.apply(this, arguments); 5 | }, 6 | getRect(selector, all) { 7 | return new Promise(resolve => { 8 | wx.createSelectorQuery() 9 | .in(this)[all ? 'selectAll' : 'select'](selector) 10 | .boundingClientRect(rect => { 11 | if (all && Array.isArray(rect) && rect.length) { 12 | resolve(rect); 13 | } 14 | if (!all && rect) { 15 | resolve(rect); 16 | } 17 | }) 18 | .exec(); 19 | }); 20 | } 21 | } 22 | }); 23 | -------------------------------------------------------------------------------- /components/mixins/open-type.js: -------------------------------------------------------------------------------- 1 | export const openType = Behavior({ 2 | properties: { 3 | openType: String 4 | }, 5 | methods: { 6 | bindGetUserInfo(event) { 7 | this.$emit('getuserinfo', event.detail); 8 | }, 9 | bindContact(event) { 10 | this.$emit('contact', event.detail); 11 | }, 12 | bindGetPhoneNumber(event) { 13 | this.$emit('getphonenumber', event.detail); 14 | }, 15 | bindError(event) { 16 | this.$emit('error', event.detail); 17 | }, 18 | bindLaunchApp(event) { 19 | this.$emit('launchapp', event.detail); 20 | }, 21 | bindOpenSetting(event) { 22 | this.$emit('opensetting', event.detail); 23 | }, 24 | } 25 | }); 26 | -------------------------------------------------------------------------------- /components/toptips/toptips.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | function Toptips() { 4 | var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; 5 | 6 | var pages = getCurrentPages(); 7 | var ctx = pages[pages.length - 1]; 8 | var defaultOptions = { 9 | selector: '#zan-toptips', 10 | duration: 3000 11 | }; 12 | 13 | options = Object.assign(defaultOptions, parseParam(options)); 14 | 15 | var $toptips = ctx.selectComponent(options.selector); 16 | delete options.selector; 17 | 18 | $toptips.setData(Object.assign({}, options)); 19 | $toptips && $toptips.show(); 20 | } 21 | 22 | function parseParam() { 23 | var params = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; 24 | 25 | return typeof params === 'object' ? params : { content: params }; 26 | } 27 | 28 | module.exports = Toptips; -------------------------------------------------------------------------------- /components/mixins/touch.js: -------------------------------------------------------------------------------- 1 | export const touch = Behavior({ 2 | methods: { 3 | touchStart(event) { 4 | this.direction = ''; 5 | this.deltaX = 0; 6 | this.deltaY = 0; 7 | this.offsetX = 0; 8 | this.offsetY = 0; 9 | this.startX = event.touches[0].clientX; 10 | this.startY = event.touches[0].clientY; 11 | }, 12 | touchMove(event) { 13 | const touch = event.touches[0]; 14 | this.deltaX = touch.clientX - this.startX; 15 | this.deltaY = touch.clientY - this.startY; 16 | this.offsetX = Math.abs(this.deltaX); 17 | this.offsetY = Math.abs(this.deltaY); 18 | this.direction = this.offsetX > this.offsetY ? 'horizontal' : this.offsetX < this.offsetY ? 'vertical' : ''; 19 | } 20 | } 21 | }); 22 | -------------------------------------------------------------------------------- /main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import App from './App' 3 | import store from './store' 4 | import uView from 'uview-ui' 5 | import bootstrap from './core/bootstrap' 6 | import { 7 | getPlatform, 8 | navTo, 9 | showToast, 10 | showSuccess, 11 | showError, 12 | getShareUrlParams 13 | } from './utils/app' 14 | import './core/ican-H5Api' 15 | 16 | Vue.config.productionTip = false 17 | 18 | App.mpType = 'app' 19 | 20 | // 当前运行的终端 21 | Vue.prototype.$platform = getPlatform() 22 | 23 | // 载入uView库 24 | Vue.use(uView) 25 | 26 | // 挂载全局函数 27 | Vue.prototype.$toast = showToast 28 | Vue.prototype.$success = showSuccess 29 | Vue.prototype.$error = showError 30 | Vue.prototype.$navTo = navTo 31 | Vue.prototype.$getShareUrlParams = getShareUrlParams 32 | 33 | // 实例化应用 34 | const app = new Vue({ 35 | ...App, 36 | store, 37 | created: bootstrap 38 | }) 39 | app.$mount() 40 | -------------------------------------------------------------------------------- /components/page/richText/index.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 36 | 37 | 42 | -------------------------------------------------------------------------------- /components/page/video/index.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 32 | 33 | 39 | -------------------------------------------------------------------------------- /api/refund.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | // api地址 4 | const api = { 5 | list: 'clientApi/refund/list', 6 | goods: 'clientApi/refund/goods', 7 | apply: 'clientApi/refund/submit', 8 | detail: 'clientApi/refund/detail', 9 | delivery: 'clientApi/refund/delivery' 10 | } 11 | 12 | // 售后单列表 13 | export const list = (param, option) => { 14 | return request.get(api.list, param, option) 15 | } 16 | 17 | // 申请售后 18 | export const apply = (orderId, data) => { 19 | return request.post(api.apply, { orderId, type: data.type, remark: data.content, images: data.images }) 20 | } 21 | 22 | // 售后单详情 23 | export const detail = (refundId, param) => { 24 | return request.get(api.detail, { refundId, ...param }) 25 | } 26 | 27 | // 用户发货 28 | export const delivery = (refundId, expressName, expressNo) => { 29 | return request.post(api.delivery, { refundId, expressName, expressNo }) 30 | } 31 | -------------------------------------------------------------------------------- /uview-ui/libs/function/debounce.js: -------------------------------------------------------------------------------- 1 | let timeout = null; 2 | 3 | /** 4 | * 防抖原理:一定时间内,只有最后一次操作,再过wait毫秒后才执行函数 5 | * 6 | * @param {Function} func 要执行的回调函数 7 | * @param {Number} wait 延时的时间 8 | * @param {Boolean} immediate 是否立即执行 9 | * @return null 10 | */ 11 | function debounce(func, wait = 500, immediate = false) { 12 | // 清除定时器 13 | if (timeout !== null) clearTimeout(timeout); 14 | // 立即执行,此类情况一般用不到 15 | if (immediate) { 16 | var callNow = !timeout; 17 | timeout = setTimeout(function() { 18 | timeout = null; 19 | }, wait); 20 | if (callNow) typeof func === 'function' && func(); 21 | } else { 22 | // 设置定时器,当最后一次操作后,timeout不会再被清除,所以在延时wait毫秒后执行func回调方法 23 | timeout = setTimeout(function() { 24 | typeof func === 'function' && func(); 25 | }, wait); 26 | } 27 | } 28 | 29 | export default debounce 30 | -------------------------------------------------------------------------------- /components/common/style/hairline.wxss: -------------------------------------------------------------------------------- 1 | .van-hairline,.van-hairline--bottom,.van-hairline--left,.van-hairline--right,.van-hairline--surround,.van-hairline--top,.van-hairline--top-bottom{position:relative}.van-hairline--bottom::after,.van-hairline--left::after,.van-hairline--right::after,.van-hairline--surround::after,.van-hairline--top-bottom::after,.van-hairline--top::after,.van-hairline::after{content:' ';position:absolute;pointer-events:none;box-sizing:border-box;-webkit-transform-origin:center;transform-origin:center;top:-50%;left:-50%;right:-50%;bottom:-50%;-webkit-transform:scale(.5);transform:scale(.5);border:0 solid #eee}.van-hairline--top::after{border-top-width:1px}.van-hairline--left::after{border-left-width:1px}.van-hairline--right::after{border-right-width:1px}.van-hairline--bottom::after{border-bottom-width:1px}.van-hairline--top-bottom::after{border-width:1px 0}.van-hairline--surround::after{border-width:1px} -------------------------------------------------------------------------------- /api/merchant/coupon.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | // api地址 4 | const api = { 5 | sendCoupon: 'merchantApi/coupon/sendCoupon', 6 | couponList: 'merchantApi/coupon/couponList', 7 | saveCoupon: 'merchantApi/coupon/saveCoupon', 8 | search: 'clientApi/coupon/list', 9 | info: 'clientApi/coupon/detail' 10 | } 11 | 12 | // 查询接口 13 | export const search = (param) => { 14 | return request.post(api.search, param) 15 | } 16 | 17 | // 列表接口 18 | export const couponList = (param) => { 19 | return request.post(api.couponList, param) 20 | } 21 | 22 | // 保存接口 23 | export const saveCoupon = (param) => { 24 | return request.post(api.saveCoupon, param) 25 | } 26 | 27 | // 发放卡券 28 | export const sendCoupon = (param) => { 29 | return request.post(api.sendCoupon, param) 30 | } 31 | 32 | // 卡券详情 33 | export function info(couponId) { 34 | return request.post(api.info, { couponId }) 35 | } -------------------------------------------------------------------------------- /components/mescroll-uni/mescroll-uni.css: -------------------------------------------------------------------------------- 1 | .mescroll-uni-warp{ 2 | height: 100%; 3 | } 4 | 5 | .mescroll-uni-content{ 6 | height: 100%; 7 | } 8 | 9 | .mescroll-uni { 10 | position: relative; 11 | width: 100%; 12 | height: 100%; 13 | min-height: 200rpx; 14 | overflow-y: auto; 15 | box-sizing: border-box; /* 避免设置padding出现双滚动条的问题 */ 16 | } 17 | 18 | /* 定位的方式固定高度 */ 19 | .mescroll-uni-fixed{ 20 | z-index: 1; 21 | position: fixed; 22 | top: 0; 23 | left: 0; 24 | right: 0; 25 | bottom: 0; 26 | width: auto; /* 使right生效 */ 27 | height: auto; /* 使bottom生效 */ 28 | } 29 | 30 | /* 适配 iPhoneX */ 31 | @supports (bottom: constant(safe-area-inset-bottom)) or (bottom: env(safe-area-inset-bottom)) { 32 | .mescroll-safearea { 33 | padding-bottom: constant(safe-area-inset-bottom); 34 | padding-bottom: env(safe-area-inset-bottom); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /uview-ui/libs/function/throttle.js: -------------------------------------------------------------------------------- 1 | let timer, flag; 2 | /** 3 | * 节流原理:在一定时间内,只能触发一次 4 | * 5 | * @param {Function} func 要执行的回调函数 6 | * @param {Number} wait 延时的时间 7 | * @param {Boolean} immediate 是否立即执行 8 | * @return null 9 | */ 10 | function throttle(func, wait = 500, immediate = true) { 11 | if (immediate) { 12 | if (!flag) { 13 | flag = true; 14 | // 如果是立即执行,则在wait毫秒内开始时执行 15 | typeof func === 'function' && func(); 16 | timer = setTimeout(() => { 17 | flag = false; 18 | }, wait); 19 | } 20 | } else { 21 | if (!flag) { 22 | flag = true 23 | // 如果是非立即执行,则在wait毫秒内的结束处执行 24 | timer = setTimeout(() => { 25 | flag = false 26 | typeof func === 'function' && func(); 27 | }, wait); 28 | } 29 | 30 | } 31 | }; 32 | export default throttle 33 | -------------------------------------------------------------------------------- /components/page/notice/index.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 37 | 38 | 41 | -------------------------------------------------------------------------------- /api/address.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | // api地址 4 | const api = { 5 | list: 'clientApi/address/list', 6 | detail: 'clientApi/address/detail', 7 | save: 'clientApi/address/save' 8 | } 9 | 10 | // 个人收货地址列表 11 | export const list = (param) => { 12 | return request.get(api.list, param) 13 | } 14 | 15 | // 收货地址详情 16 | export const detail = (addressId) => { 17 | return request.post(api.detail, { addressId }) 18 | } 19 | 20 | // 保存收货地址 21 | export const save = (name, mobile, provinceId, cityId, regionId, detail, status, addressId) => { 22 | return request.post(api.save, { name, mobile, provinceId, cityId, regionId, detail, status, addressId }) 23 | } 24 | 25 | // 设置默认收货地址 26 | export const setDefault = (addressId, isDefault) => { 27 | return request.post(api.save, { addressId, isDefault }) 28 | } 29 | 30 | // 删除收货地址 31 | export const remove = (addressId, status) => { 32 | return request.post(api.save, { addressId, status }) 33 | } 34 | -------------------------------------------------------------------------------- /components/wxs/bem.wxs: -------------------------------------------------------------------------------- 1 | var array = require('./array.wxs'); 2 | var object = require('./object.wxs'); 3 | var PREFIX = 'van-'; 4 | 5 | function join(name, mods) { 6 | name = PREFIX + name; 7 | mods = mods.map(function(mod) { 8 | return name + '--' + mod; 9 | }); 10 | mods.unshift(name); 11 | return mods.join(' '); 12 | } 13 | 14 | function traversing(mods, conf) { 15 | if (!conf) { 16 | return; 17 | } 18 | 19 | if (typeof conf === 'string' || typeof conf === 'number') { 20 | mods.push(conf); 21 | } else if (array.isArray(conf)) { 22 | conf.forEach(function(item) { 23 | traversing(mods, item); 24 | }); 25 | } else if (typeof conf === 'object') { 26 | object.keys(conf).forEach(function(key) { 27 | conf[key] && mods.push(key); 28 | }); 29 | } 30 | } 31 | 32 | function bem(name, conf) { 33 | var mods = []; 34 | traversing(mods, conf); 35 | return join(name, mods); 36 | } 37 | 38 | module.exports.bem = bem; 39 | -------------------------------------------------------------------------------- /uview-ui/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "uview-ui", 3 | "version": "1.8.3", 4 | "description": "uView UI,是uni-app生态优秀的UI框架,全面的组件和便捷的工具会让您信手拈来,如鱼得水", 5 | "main": "index.js", 6 | "keywords": [ 7 | "uview", 8 | "uView", 9 | "uni-app", 10 | "uni-app ui", 11 | "uniapp", 12 | "uviewui", 13 | "uview ui", 14 | "uviewUI", 15 | "uViewui", 16 | "uViewUI", 17 | "uView UI", 18 | "uni ui", 19 | "uni UI", 20 | "uniapp ui", 21 | "ui", 22 | "UI框架", 23 | "uniapp ui框架", 24 | "uniapp UI" 25 | ], 26 | "scripts": { 27 | "test": "echo \"Error: no test specified\" && exit 1" 28 | }, 29 | "repository": { 30 | "type": "git", 31 | "url": "" 32 | }, 33 | "devDependencies": { 34 | "node-sass": "^4.14.0", 35 | "sass-loader": "^8.0.2" 36 | }, 37 | "author": "uView", 38 | "license": "MIT" 39 | } 40 | -------------------------------------------------------------------------------- /components/mixins/observer/index.js: -------------------------------------------------------------------------------- 1 | import { behavior } from './behavior'; 2 | import { observeProps } from './props'; 3 | export function observe(vantOptions, options) { 4 | const { watch, computed } = vantOptions; 5 | options.behaviors.push(behavior); 6 | if (watch) { 7 | const props = options.properties || {}; 8 | Object.keys(watch).forEach(key => { 9 | if (key in props) { 10 | let prop = props[key]; 11 | if (prop === null || !('type' in prop)) { 12 | prop = { type: prop }; 13 | } 14 | prop.observer = watch[key]; 15 | props[key] = prop; 16 | } 17 | }); 18 | options.properties = props; 19 | } 20 | if (computed) { 21 | options.methods = options.methods || {}; 22 | options.methods.$options = () => vantOptions; 23 | if (options.properties) { 24 | observeProps(options.properties); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /components/mixins/iphonex.js: -------------------------------------------------------------------------------- 1 | let isIPhoneX = null; 2 | function getIsIPhoneX() { 3 | return new Promise((resolve, reject) => { 4 | if (isIPhoneX !== null) { 5 | resolve(isIPhoneX); 6 | } 7 | else { 8 | wx.getSystemInfo({ 9 | success: ({ model, screenHeight }) => { 10 | const iphoneX = /iphone x/i.test(model); 11 | const iphoneNew = /iPhone11/i.test(model) && screenHeight === 812; 12 | isIPhoneX = iphoneX || iphoneNew; 13 | resolve(isIPhoneX); 14 | }, 15 | fail: reject 16 | }); 17 | } 18 | }); 19 | } 20 | export const iphonex = Behavior({ 21 | properties: { 22 | safeAreaInsetBottom: { 23 | type: Boolean, 24 | value: true 25 | } 26 | }, 27 | created() { 28 | getIsIPhoneX().then(isIPhoneX => { 29 | this.set({ isIPhoneX }); 30 | }); 31 | } 32 | }); 33 | -------------------------------------------------------------------------------- /uview-ui/libs/function/color.js: -------------------------------------------------------------------------------- 1 | // 为了让用户能够自定义主题,会逐步弃用此文件,各颜色通过css提供 2 | // 为了给某些特殊场景使用和向后兼容,无需删除此文件(2020-06-20) 3 | let color = { 4 | primary: "#2979ff", 5 | primaryDark: "#2b85e4", 6 | primaryDisabled: "#a0cfff", 7 | primaryLight: "#ecf5ff", 8 | bgColor: "#f3f4f6", 9 | 10 | info: "#909399", 11 | infoDark: "#82848a", 12 | infoDisabled: "#c8c9cc", 13 | infoLight: "#f4f4f5", 14 | 15 | warning: "#ff9900", 16 | warningDark: "#f29100", 17 | warningDisabled: "#fcbd71", 18 | warningLight: "#fdf6ec", 19 | 20 | error: "#fa3534", 21 | errorDark: "#dd6161", 22 | errorDisabled: "#fab6b6", 23 | errorLight: "#fef0f0", 24 | 25 | success: "#19be6b", 26 | successDark: "#18b566", 27 | successDisabled: "#71d5a1", 28 | successLight: "#dbf1e1", 29 | 30 | mainColor: "#303133", 31 | contentColor: "#606266", 32 | tipsColor: "#909399", 33 | lightColor: "#c0c4cc", 34 | borderColor: "#e4e7ed" 35 | } 36 | 37 | export default color; -------------------------------------------------------------------------------- /uview-ui/libs/util/province.js: -------------------------------------------------------------------------------- 1 | var provinceData=[{"label":"北京市","value":"11"},{"label":"天津市","value":"12"},{"label":"河北省","value":"13"},{"label":"山西省","value":"14"},{"label":"内蒙古自治区","value":"15"},{"label":"辽宁省","value":"21"},{"label":"吉林省","value":"22"},{"label":"黑龙江省","value":"23"},{"label":"上海市","value":"31"},{"label":"江苏省","value":"32"},{"label":"浙江省","value":"33"},{"label":"安徽省","value":"34"},{"label":"福建省","value":"35"},{"label":"江西省","value":"36"},{"label":"山东省","value":"37"},{"label":"河南省","value":"41"},{"label":"湖北省","value":"42"},{"label":"湖南省","value":"43"},{"label":"广东省","value":"44"},{"label":"广西壮族自治区","value":"45"},{"label":"海南省","value":"46"},{"label":"重庆市","value":"50"},{"label":"四川省","value":"51"},{"label":"贵州省","value":"52"},{"label":"云南省","value":"53"},{"label":"西藏自治区","value":"54"},{"label":"陕西省","value":"61"},{"label":"甘肃省","value":"62"},{"label":"青海省","value":"63"},{"label":"宁夏回族自治区","value":"64"},{"label":"新疆维吾尔自治区","value":"65"},{"label":"台湾","value":"66"},{"label":"香港","value":"67"},{"label":"澳门","value":"68"}];export default provinceData; -------------------------------------------------------------------------------- /uview-ui/components/u-time-line/u-time-line.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 23 | 24 | 44 | -------------------------------------------------------------------------------- /uni_modules/uni-popup/changelog.md: -------------------------------------------------------------------------------- 1 | ## 1.6.0(2021-07-13) 2 | - 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) 3 | ## 1.5.0(2021-06-23) 4 | - 新增 mask-click 遮罩层点击事件 5 | ## 1.4.5(2021-06-22) 6 | - 修复 nvue 平台中间弹出后,点击内容,再点击遮罩无法关闭的Bug 7 | ## 1.4.4(2021-06-18) 8 | - 修复 H5平台中间弹出后,点击内容,再点击遮罩无法关闭的Bug 9 | ## 1.4.3(2021-06-08) 10 | - 修复 错误的 watch 字段 11 | - 修复 safeArea 属性不生效的问题 12 | - 修复 点击内容,再点击遮罩无法关闭的Bug 13 | ## 1.4.2(2021-05-12) 14 | - 新增 组件示例地址 15 | ## 1.4.1(2021-04-29) 16 | - 修复 组件内放置 input 、textarea 组件,无法聚焦的问题 17 | ## 1.4.0 (2021-04-29) 18 | - 新增 type 属性的 left\right 值,支持左右弹出 19 | - 新增 open(String:type) 方法参数 ,可以省略 type 属性 ,直接传入类型打开指定弹窗 20 | - 新增 backgroundColor 属性,可定义主窗口背景色,默认不显示背景色 21 | - 新增 safeArea 属性,是否适配底部安全区 22 | - 修复 App\h5\微信小程序底部安全区占位不对的Bug 23 | - 修复 App 端弹出等待的Bug 24 | - 优化 提升低配设备性能,优化动画卡顿问题 25 | - 优化 更简单的组件自定义方式 26 | ## 1.2.9(2021-02-05) 27 | - 优化 组件引用关系,通过uni_modules引用组件 28 | ## 1.2.8(2021-02-05) 29 | - 调整为uni_modules目录规范 30 | ## 1.2.7(2021-02-05) 31 | - 调整为uni_modules目录规范 32 | - 新增 支持 PC 端 33 | - 新增 uni-popup-message 、uni-popup-dialog扩展组件支持 PC 端 34 | -------------------------------------------------------------------------------- /api/order.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | // api地址 4 | const api = { 5 | todoCounts: 'clientApi/order/todoCounts', 6 | list: 'clientApi/order/list', 7 | detail: 'clientApi/order/detail', 8 | cancel: 'clientApi/order/cancel', 9 | pay: 'clientApi/pay/doPay', 10 | receipt: 'clientApi/order/receipt', 11 | } 12 | 13 | // 当前用户待处理的订单数量 14 | export function todoCounts(param) { 15 | return request.get(api.todoCounts, param) 16 | } 17 | 18 | // 我的订单列表 19 | export function list(param, option) { 20 | return request.post(api.list, param, option) 21 | } 22 | 23 | // 订单详情 24 | export function detail(orderId, param) { 25 | return request.get(api.detail, { orderId, ...param }) 26 | } 27 | 28 | // 取消订单 29 | export function cancel(orderId, data) { 30 | return request.get(api.cancel, { orderId, ...data }) 31 | } 32 | 33 | // 立即支付 34 | export function pay(orderId, payType, param) { 35 | return request.get(api.pay, { orderId, payType, ...param }) 36 | } 37 | 38 | // 确认收货 39 | export function receipt(orderId, data) { 40 | return request.get(api.receipt, { orderId, ...data }) 41 | } 42 | -------------------------------------------------------------------------------- /components/actionsheet/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Component({ 4 | externalClasses: ['mask-class', 'container-class'], 5 | properties: { 6 | actions: { 7 | type: Array, 8 | value: [] 9 | }, 10 | show: { 11 | type: Boolean, 12 | value: false 13 | }, 14 | cancelWithMask: { 15 | type: Boolean, 16 | value: true 17 | }, 18 | cancelText: { 19 | type: String, 20 | value: '' 21 | } 22 | }, 23 | methods: { 24 | onMaskClick: function onMaskClick() { 25 | if (this.data.cancelWithMask) { 26 | this.cancelClick(); 27 | } 28 | }, 29 | cancelClick: function cancelClick() { 30 | this.triggerEvent('cancel'); 31 | }, 32 | handleBtnClick: function handleBtnClick(_ref) { 33 | var _ref$currentTarget = _ref.currentTarget, 34 | currentTarget = _ref$currentTarget === undefined ? {} : _ref$currentTarget; 35 | 36 | var dataset = currentTarget.dataset || {}; 37 | var index = dataset.index; 38 | 39 | this.triggerEvent('actionclick', { index: index }); 40 | } 41 | } 42 | }); -------------------------------------------------------------------------------- /uview-ui/libs/function/deepMerge.js: -------------------------------------------------------------------------------- 1 | import deepClone from "./deepClone"; 2 | 3 | // JS对象深度合并 4 | function deepMerge(target = {}, source = {}) { 5 | target = deepClone(target); 6 | if (typeof target !== 'object' || typeof source !== 'object') return false; 7 | for (var prop in source) { 8 | if (!source.hasOwnProperty(prop)) continue; 9 | if (prop in target) { 10 | if (typeof target[prop] !== 'object') { 11 | target[prop] = source[prop]; 12 | } else { 13 | if (typeof source[prop] !== 'object') { 14 | target[prop] = source[prop]; 15 | } else { 16 | if (target[prop].concat && source[prop].concat) { 17 | target[prop] = target[prop].concat(source[prop]); 18 | } else { 19 | target[prop] = deepMerge(target[prop], source[prop]); 20 | } 21 | } 22 | } 23 | } else { 24 | target[prop] = source[prop]; 25 | } 26 | } 27 | return target; 28 | } 29 | 30 | export default deepMerge; -------------------------------------------------------------------------------- /uview-ui/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 www.uviewui.com 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /uview-ui/theme.scss: -------------------------------------------------------------------------------- 1 | // 此文件为uView的主题变量,这些变量目前只能通过uni.scss引入才有效,另外由于 2 | // uni.scss中引入的样式会同时混入到全局样式文件和单独每一个页面的样式中,造成微信程序包太大, 3 | // 故uni.scss只建议放scss变量名相关样式,其他的样式可以通过main.js或者App.vue引入 4 | 5 | $u-main-color: #303133; 6 | $u-content-color: #606266; 7 | $u-tips-color: #909399; 8 | $u-light-color: #c0c4cc; 9 | $u-border-color: #e4e7ed; 10 | $u-bg-color: #f3f4f6; 11 | 12 | $u-type-primary: #2979ff; 13 | $u-type-primary-light: #ecf5ff; 14 | $u-type-primary-disabled: #a0cfff; 15 | $u-type-primary-dark: #2b85e4; 16 | 17 | $u-type-warning: #ff9900; 18 | $u-type-warning-disabled: #fcbd71; 19 | $u-type-warning-dark: #f29100; 20 | $u-type-warning-light: #fdf6ec; 21 | 22 | $u-type-success: #19be6b; 23 | $u-type-success-disabled: #71d5a1; 24 | $u-type-success-dark: #18b566; 25 | $u-type-success-light: #dbf1e1; 26 | 27 | $u-type-error: #fa3534; 28 | $u-type-error-disabled: #fab6b6; 29 | $u-type-error-dark: #dd6161; 30 | $u-type-error-light: #fef0f0; 31 | 32 | $u-type-info: #909399; 33 | $u-type-info-disabled: #c8c9cc; 34 | $u-type-info-dark: #82848a; 35 | $u-type-info-light: #f4f4f5; 36 | 37 | $u-form-item-height: 70rpx; 38 | $u-form-item-border-color: #dcdfe6; 39 | -------------------------------------------------------------------------------- /components/btn/index.wxml: -------------------------------------------------------------------------------- 1 | 25 | -------------------------------------------------------------------------------- /components/mescroll-uni/components/mescroll-up.css: -------------------------------------------------------------------------------- 1 | /* 上拉加载区域 */ 2 | .mescroll-upwarp { 3 | box-sizing: border-box; 4 | min-height: 110rpx; 5 | padding: 30rpx 0; 6 | text-align: center; 7 | clear: both; 8 | } 9 | 10 | /*提示文本 */ 11 | .mescroll-upwarp .upwarp-tip, 12 | .mescroll-upwarp .upwarp-nodata { 13 | display: inline-block; 14 | font-size: 28rpx; 15 | vertical-align: middle; 16 | /* color: gray; 已在style设置color,此处删去*/ 17 | } 18 | 19 | .mescroll-upwarp .upwarp-tip { 20 | margin-left: 16rpx; 21 | } 22 | 23 | /*旋转进度条 */ 24 | .mescroll-upwarp .upwarp-progress { 25 | display: inline-block; 26 | width: 32rpx; 27 | height: 32rpx; 28 | border-radius: 50%; 29 | border: 2rpx solid gray; 30 | border-bottom-color: transparent !important; /*已在style设置border-color,此处需加 !important*/ 31 | vertical-align: middle; 32 | } 33 | 34 | /* 旋转动画 */ 35 | .mescroll-upwarp .mescroll-rotate { 36 | animation: mescrollUpRotate 0.6s linear infinite; 37 | } 38 | 39 | @keyframes mescrollUpRotate { 40 | 0% { 41 | transform: rotate(0deg); 42 | } 43 | 44 | 100% { 45 | transform: rotate(360deg); 46 | } 47 | } -------------------------------------------------------------------------------- /uview-ui/libs/function/type2icon.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 根据主题type值,获取对应的图标 3 | * @param String type 主题名称,primary|info|error|warning|success 4 | * @param String fill 是否使用fill填充实体的图标 5 | */ 6 | function type2icon(type = 'success', fill = false) { 7 | // 如果非预置值,默认为success 8 | if (['primary', 'info', 'error', 'warning', 'success'].indexOf(type) == -1) type = 'success'; 9 | let iconName = ''; 10 | // 目前(2019-12-12),info和primary使用同一个图标 11 | switch (type) { 12 | case 'primary': 13 | iconName = 'info-circle'; 14 | break; 15 | case 'info': 16 | iconName = 'info-circle'; 17 | break; 18 | case 'error': 19 | iconName = 'close-circle'; 20 | break; 21 | case 'warning': 22 | iconName = 'error-circle'; 23 | break; 24 | case 'success': 25 | iconName = 'checkmark-circle'; 26 | break; 27 | default: 28 | iconName = 'checkmark-circle'; 29 | } 30 | // 是否是实体类型,加上-fill,在icon组件库中,实体的类名是后面加-fill的 31 | if (fill) iconName += '-fill'; 32 | return iconName; 33 | } 34 | 35 | export default type2icon 36 | -------------------------------------------------------------------------------- /components/toptips/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var FONT_COLOR = '#fff'; 4 | var BG_COLOR = '#e64340'; 5 | 6 | Component({ 7 | properties: { 8 | content: String, 9 | color: { 10 | type: String, 11 | value: FONT_COLOR 12 | }, 13 | backgroundColor: { 14 | type: String, 15 | value: BG_COLOR 16 | }, 17 | isShow: { 18 | type: Boolean, 19 | value: false 20 | }, 21 | duration: { 22 | type: Number, 23 | value: 3000 24 | } 25 | }, 26 | 27 | methods: { 28 | show: function show() { 29 | var _this = this; 30 | 31 | var duration = this.data.duration; 32 | 33 | 34 | this._timer && clearTimeout(this._timer); 35 | this.setData({ 36 | isShow: true 37 | }); 38 | 39 | if (duration > 0 && duration !== Infinity) { 40 | this._timer = setTimeout(function () { 41 | _this.hide(); 42 | }, duration); 43 | } 44 | }, 45 | hide: function hide() { 46 | this._timer = clearTimeout(this._timer); 47 | 48 | this.setData({ 49 | isShow: false, 50 | backgroundColor: BG_COLOR 51 | }); 52 | } 53 | } 54 | }); -------------------------------------------------------------------------------- /api/myCoupon.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | // api地址 4 | const api = { 5 | list: 'clientApi/myCoupon/list', 6 | remove: 'clientApi/myCoupon/remove', 7 | mydetail: 'clientApi/userCouponApi/detail', 8 | detail: 'clientApi/coupon/detail' 9 | } 10 | 11 | // 会员卡券列表 12 | export const list = (param, option) => { 13 | const options = { 14 | isPrompt: true, //(默认 true 说明:本接口抛出的错误是否提示) 15 | load: true, //(默认 true 说明:本接口是否提示加载动画) 16 | ...option 17 | } 18 | return request.get(api.list, param, options) 19 | } 20 | 21 | // 卡券详情 22 | export function detail(couponId, userCouponId, userCouponCode) { 23 | if (parseInt(userCouponId) > 0 || userCouponCode.length > 0) { 24 | if (userCouponId == undefined) { 25 | userCouponId = 0 26 | } 27 | if (userCouponCode == undefined) { 28 | userCouponCode = "" 29 | } 30 | return request.get(api.mydetail, { userCouponId, userCouponCode }) 31 | } else { 32 | return request.post(api.detail, { couponId }) 33 | } 34 | } 35 | 36 | // 删除卡券 37 | export function remove(userCouponId) { 38 | return request.post(api.remove, { userCouponId }) 39 | } 40 | -------------------------------------------------------------------------------- /components/page/image/index.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 41 | 42 | 48 | -------------------------------------------------------------------------------- /api/login/index.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | // api地址 4 | const api = { 5 | register: 'clientApi/sign/register', 6 | login: 'clientApi/sign/signIn', 7 | mpWxLogin: 'clientApi/sign/mpWxLogin', 8 | mpWxAuth: 'clientApi/sign/mpWxAuth', 9 | captcha: 'clientApi/captcha/getCode', 10 | sendSmsCaptcha: 'clientApi/sms/sendVerifyCode', 11 | authLoginConfig: 'clientApi/sign/authLoginConfig' 12 | } 13 | 14 | // 用户注册 15 | export function register(data) { 16 | return request.post(api.register, data) 17 | } 18 | 19 | // 用户登录 20 | export function login(data) { 21 | return request.post(api.login, data) 22 | } 23 | 24 | // 微信小程序快捷登录 25 | export function mpWxLogin(data, option) { 26 | return request.post(api.mpWxLogin, data, option) 27 | } 28 | 29 | // 微信公众号授权 30 | export function mpWxAuth(data, option) { 31 | return request.post(api.mpWxAuth, data, option) 32 | } 33 | 34 | // 图形验证码 35 | export function captcha() { 36 | return request.get(api.captcha) 37 | } 38 | 39 | // 发送短信验证码 40 | export function sendSmsCaptcha(data) { 41 | return request.post(api.sendSmsCaptcha, data) 42 | } 43 | 44 | // 获取授权登录配置 45 | export function authLoginConfig() { 46 | return request.get(api.authLoginConfig) 47 | } -------------------------------------------------------------------------------- /components/dialog/index.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | {{ title }} 4 | 5 | 6 | {{ message }} 7 | 8 | 9 | 10 | 11 | 13 | {{ item.text }} 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /components/wxs/memoize.wxs: -------------------------------------------------------------------------------- 1 | /** 2 | * Simple memoize 3 | * wxs doesn't support fn.apply, so this memoize only support up to 2 args 4 | */ 5 | 6 | function isPrimitive(value) { 7 | var type = typeof value; 8 | return ( 9 | type === 'boolean' || 10 | type === 'number' || 11 | type === 'string' || 12 | type === 'undefined' || 13 | value === null 14 | ); 15 | } 16 | 17 | // mock simple fn.call in wxs 18 | function call(fn, args) { 19 | if (args.length === 2) { 20 | return fn(args[0], args[1]); 21 | } 22 | 23 | if (args.length === 1) { 24 | return fn(args[0]); 25 | } 26 | 27 | return fn(); 28 | } 29 | 30 | function serializer(args) { 31 | if (args.length === 1 && isPrimitive(args[0])) { 32 | return args[0]; 33 | } 34 | var obj = {}; 35 | for (var i = 0; i < args.length; i++) { 36 | obj['key' + i] = args[i]; 37 | } 38 | return JSON.stringify(obj); 39 | } 40 | 41 | function memoize(fn) { 42 | var cache = {}; 43 | 44 | return function() { 45 | var key = serializer(arguments); 46 | if (cache[key] === undefined) { 47 | cache[key] = call(fn, arguments); 48 | } 49 | 50 | return cache[key]; 51 | }; 52 | } 53 | 54 | module.exports.memoize = memoize; 55 | -------------------------------------------------------------------------------- /components/common/index.wxss: -------------------------------------------------------------------------------- 1 | .van-ellipsis{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.van-multi-ellipsis--l2{overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}.van-multi-ellipsis--l3{overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical}.van-clearfix::after{content:'';display:table;clear:both}.van-hairline,.van-hairline--bottom,.van-hairline--left,.van-hairline--right,.van-hairline--surround,.van-hairline--top,.van-hairline--top-bottom{position:relative}.van-hairline--bottom::after,.van-hairline--left::after,.van-hairline--right::after,.van-hairline--surround::after,.van-hairline--top-bottom::after,.van-hairline--top::after,.van-hairline::after{content:' ';position:absolute;pointer-events:none;box-sizing:border-box;-webkit-transform-origin:center;transform-origin:center;top:-50%;left:-50%;right:-50%;bottom:-50%;-webkit-transform:scale(.5);transform:scale(.5);border:0 solid #eee}.van-hairline--top::after{border-top-width:1px}.van-hairline--left::after{border-left-width:1px}.van-hairline--right::after{border-right-width:1px}.van-hairline--bottom::after{border-bottom-width:1px}.van-hairline--top-bottom::after{border-width:1px 0}.van-hairline--surround::after{border-width:1px} -------------------------------------------------------------------------------- /components/mescroll-uni/components/mescroll-up.vue: -------------------------------------------------------------------------------- 1 | 2 | 13 | 14 | 36 | 37 | 40 | -------------------------------------------------------------------------------- /components/switch/index.js: -------------------------------------------------------------------------------- 1 | import { VantComponent } from '../common/component'; 2 | VantComponent({ 3 | field: true, 4 | classes: ['node-class'], 5 | props: { 6 | checked: null, 7 | loading: Boolean, 8 | disabled: Boolean, 9 | activeColor: String, 10 | inactiveColor: String, 11 | size: { 12 | type: String, 13 | value: '30px' 14 | }, 15 | activeValue: { 16 | type: null, 17 | value: true 18 | }, 19 | inactiveValue: { 20 | type: null, 21 | value: false 22 | } 23 | }, 24 | watch: { 25 | checked(value) { 26 | this.set({ value }); 27 | } 28 | }, 29 | created() { 30 | this.set({ value: this.data.checked }); 31 | }, 32 | methods: { 33 | onClick() { 34 | const { activeValue, inactiveValue } = this.data; 35 | if (!this.data.disabled && !this.data.loading) { 36 | const checked = this.data.checked === activeValue; 37 | const value = checked ? inactiveValue : activeValue; 38 | this.$emit('input', value); 39 | this.$emit('change', value); 40 | } 41 | } 42 | } 43 | }); 44 | -------------------------------------------------------------------------------- /api/user.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | // api地址 4 | const api = { 5 | userInfo: 'clientApi/user/info', 6 | qrCode: 'clientApi/user/qrCode', 7 | assets: 'clientApi/user/asset', 8 | setting: 'clientApi/user/setting', 9 | defaultStore: 'clientApi/user/defaultStore', 10 | save: 'clientApi/user/saveInfo' 11 | } 12 | 13 | // 当前登录的用户信息 14 | export const info = (param, option) => { 15 | const options = { 16 | isPrompt: true, //(默认 true 说明:本接口抛出的错误是否提示) 17 | load: true, //(默认 true 说明:本接口是否提示加载动画) 18 | ...option 19 | } 20 | return request.get(api.userInfo, param, options) 21 | } 22 | 23 | // 当前登录的会员码信息 24 | export const qrCode = (param, option) => { 25 | const options = { 26 | isPrompt: true, 27 | load: true, 28 | ...option 29 | } 30 | return request.get(api.qrCode, param, options) 31 | } 32 | 33 | // 账户资产 34 | export const assets = (param, option) => { 35 | return request.get(api.assets, param) 36 | } 37 | 38 | // 获取会员设置 39 | export const setting = (param, option) => { 40 | return request.get(api.setting, param) 41 | } 42 | 43 | // 设置会员的默认店铺 44 | export const defaultStore = (storeId) => { 45 | return request.get(api.defaultStore, { storeId }) 46 | } 47 | 48 | // 保存会员信息 49 | export const save = (param, option) => { 50 | return request.post(api.save, param) 51 | } -------------------------------------------------------------------------------- /uni_modules/uni-popup/components/uni-popup-dialog/keypress.js: -------------------------------------------------------------------------------- 1 | // #ifdef H5 2 | export default { 3 | name: 'Keypress', 4 | props: { 5 | disable: { 6 | type: Boolean, 7 | default: false 8 | } 9 | }, 10 | mounted () { 11 | const keyNames = { 12 | esc: ['Esc', 'Escape'], 13 | tab: 'Tab', 14 | enter: 'Enter', 15 | space: [' ', 'Spacebar'], 16 | up: ['Up', 'ArrowUp'], 17 | left: ['Left', 'ArrowLeft'], 18 | right: ['Right', 'ArrowRight'], 19 | down: ['Down', 'ArrowDown'], 20 | delete: ['Backspace', 'Delete', 'Del'] 21 | } 22 | const listener = ($event) => { 23 | if (this.disable) { 24 | return 25 | } 26 | const keyName = Object.keys(keyNames).find(key => { 27 | const keyName = $event.key 28 | const value = keyNames[key] 29 | return value === keyName || (Array.isArray(value) && value.includes(keyName)) 30 | }) 31 | if (keyName) { 32 | // 避免和其他按键事件冲突 33 | setTimeout(() => { 34 | this.$emit(keyName, {}) 35 | }, 0) 36 | } 37 | } 38 | document.addEventListener('keyup', listener) 39 | this.$once('hook:beforeDestroy', () => { 40 | document.removeEventListener('keyup', listener) 41 | }) 42 | }, 43 | render: () => {} 44 | } 45 | // #endif 46 | -------------------------------------------------------------------------------- /components/actionsheet/index.wxml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 17 | 18 | 19 | {{ item.name }} 20 | 23 | {{ item.subname }} 24 | 25 | 26 | 27 | 28 | 29 | 33 | {{ cancelText }} 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /uni_modules/uni-popup/components/uni-popup/keypress.js: -------------------------------------------------------------------------------- 1 | // #ifdef H5 2 | export default { 3 | name: 'Keypress', 4 | props: { 5 | disable: { 6 | type: Boolean, 7 | default: false 8 | } 9 | }, 10 | mounted () { 11 | const keyNames = { 12 | esc: ['Esc', 'Escape'], 13 | tab: 'Tab', 14 | enter: 'Enter', 15 | space: [' ', 'Spacebar'], 16 | up: ['Up', 'ArrowUp'], 17 | left: ['Left', 'ArrowLeft'], 18 | right: ['Right', 'ArrowRight'], 19 | down: ['Down', 'ArrowDown'], 20 | delete: ['Backspace', 'Delete', 'Del'] 21 | } 22 | const listener = ($event) => { 23 | if (this.disable) { 24 | return 25 | } 26 | const keyName = Object.keys(keyNames).find(key => { 27 | const keyName = $event.key 28 | const value = keyNames[key] 29 | return value === keyName || (Array.isArray(value) && value.includes(keyName)) 30 | }) 31 | if (keyName) { 32 | // 避免和其他按键事件冲突 33 | setTimeout(() => { 34 | this.$emit(keyName, {}) 35 | }, 0) 36 | } 37 | } 38 | document.addEventListener('keyup', listener) 39 | // this.$once('hook:beforeDestroy', () => { 40 | // document.removeEventListener('keyup', listener) 41 | // }) 42 | }, 43 | render: () => {} 44 | } 45 | // #endif 46 | -------------------------------------------------------------------------------- /common/model/Setting.js: -------------------------------------------------------------------------------- 1 | import * as SettingApi from '@/api/setting' 2 | import storage from '@/utils/storage' 3 | 4 | const CACHE_KEY = 'Setting' 5 | 6 | // 写入缓存, 到期时间30分钟 7 | const setStorage = (data) => { 8 | const expireTime = 30 * 60; 9 | storage.set(CACHE_KEY, data, expireTime); 10 | } 11 | 12 | // 获取缓存中的数据 13 | const getStorage = () => { 14 | return storage.get(CACHE_KEY); 15 | } 16 | 17 | // 获取系统设置 18 | const getApiData = () => { 19 | return new Promise((resolve, reject) => { 20 | SettingApi.data() 21 | .then(result => { 22 | resolve(result.data.setting); 23 | }) 24 | }) 25 | } 26 | 27 | /** 28 | * 获取商城设置 29 | * 有缓存的情况下返回缓存, 没有缓存从后端api获取 30 | * @param {bool} isCache 是否从缓存中获取 31 | */ 32 | const data = (isCache = true) => { 33 | return new Promise((resolve, reject) => { 34 | const cacheData = getStorage() 35 | if (isCache && cacheData) { 36 | resolve(cacheData) 37 | } else { 38 | getApiData().then(data => { 39 | setStorage(data) 40 | resolve(data) 41 | }) 42 | } 43 | }) 44 | } 45 | 46 | // 获取指定的系统设置 47 | const item = (key, isCache = true) => { 48 | return new Promise((resolve, reject) => { 49 | data(isCache).then(setting => { 50 | resolve(setting[key]) 51 | }) 52 | }) 53 | } 54 | 55 | export default { 56 | data, 57 | item 58 | } 59 | -------------------------------------------------------------------------------- /pages/pay/components/Popup.vue: -------------------------------------------------------------------------------- 1 | 5 | 6 | 54 | 55 | 58 | -------------------------------------------------------------------------------- /api/book.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | // api地址 4 | const api = { 5 | list: 'clientApi/book/list', 6 | detail: 'clientApi/book/detail', 7 | cate: 'clientApi/book/cateList', 8 | submit: 'clientApi/book/submit', 9 | bookable: 'clientApi/book/bookable', 10 | myBookList: 'clientApi/book/myBook', 11 | myBookDetail: 'clientApi/book/myBookDetail', 12 | cancel: 'clientApi/book/cancel', 13 | } 14 | 15 | // 预约项目列表 16 | export const list = (param) => { 17 | return request.post(api.list, param) 18 | } 19 | 20 | // 预约详情 21 | export const detail = (bookId) => { 22 | return request.post(api.detail, { bookId }) 23 | } 24 | 25 | // 预约分类列表 26 | export const cateList = (param) => { 27 | return request.get(api.cate, param) 28 | } 29 | 30 | // 提交预约 31 | export const submit = (data) => { 32 | return request.post(api.submit, data) 33 | } 34 | 35 | // 是否可预约 36 | export const bookable = (data) => { 37 | return request.post(api.bookable, data) 38 | } 39 | 40 | // 我的预约列表 41 | export const myBookList = (param) => { 42 | return request.get(api.myBookList, param) 43 | } 44 | 45 | // 我的预约详情 46 | export const myBookDetail = (bookId) => { 47 | return request.post(api.myBookDetail, { bookId }) 48 | } 49 | 50 | // 取消预约 51 | export function cancel(bookId, data) { 52 | return request.get(api.cancel, { bookId, ...data }) 53 | } -------------------------------------------------------------------------------- /uview-ui/libs/css/style.mp.scss: -------------------------------------------------------------------------------- 1 | /* start--微信小程序编译后页面有组件名的元素,特别处理--start */ 2 | /* #ifdef MP-WEIXIN || MP-QQ */ 3 | u-td, u-th { 4 | flex: 1; 5 | align-self: stretch; 6 | } 7 | 8 | .u-td { 9 | height: 100%; 10 | } 11 | 12 | u-icon { 13 | display: inline-flex; 14 | align-items: center; 15 | } 16 | 17 | // 各家小程序宫格组件外层设置为100%,避免受到父元素display: flex;的影响 18 | u-grid { 19 | width: 100%; 20 | flex: 0 0 100%; 21 | } 22 | 23 | // 避免小程序线条组件因为父组件display: flex;而失效 24 | u-line { 25 | flex: 1; 26 | } 27 | 28 | u-switch { 29 | display: inline-flex; 30 | align-items: center; 31 | } 32 | 33 | u-dropdown { 34 | flex: 1; 35 | } 36 | /* #endif */ 37 | /* end-微信小程序编译后页面有组件名的元素,特别处理--end */ 38 | 39 | 40 | /* #ifdef MP-QQ || MP-TOUTIAO */ 41 | // 需要做这一切额外的兼容,都是因为TX的无能 42 | u-icon { 43 | line-height: 0; 44 | } 45 | /* #endif */ 46 | 47 | /* start--头条小程序编译后页面有组件名的元素,特别处理--start */ 48 | // 由于头条小程序不支持直接组件名形式写样式,目前只能在写组件的时候给组件加上对应的类名 49 | /* #ifdef MP-TOUTIAO */ 50 | .u-td, .u-th, .u-tr { 51 | flex: 1; 52 | align-self: stretch; 53 | } 54 | 55 | .u-row, .u-col { 56 | flex: 1; 57 | align-self: stretch; 58 | } 59 | 60 | // 避免小程序线条组件因为父组件display: flex;而失效 61 | .u-line { 62 | flex: 1; 63 | } 64 | 65 | .u-dropdown { 66 | flex: 1; 67 | } 68 | /* #endif */ 69 | /* end-头条小程序编译后页面有组件名的元素,特别处理--end */ 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /components/mescroll-uni/components/mescroll-down.css: -------------------------------------------------------------------------------- 1 | /* 下拉刷新区域 */ 2 | .mescroll-downwarp { 3 | position: absolute; 4 | top: -100%; 5 | left: 0; 6 | width: 100%; 7 | height: 100%; 8 | text-align: center; 9 | } 10 | 11 | /* 下拉刷新--内容区,定位于区域底部 */ 12 | .mescroll-downwarp .downwarp-content { 13 | position: absolute; 14 | left: 0; 15 | bottom: 0; 16 | width: 100%; 17 | min-height: 60rpx; 18 | padding: 20rpx 0; 19 | text-align: center; 20 | } 21 | 22 | /* 下拉刷新--提示文本 */ 23 | .mescroll-downwarp .downwarp-tip { 24 | display: inline-block; 25 | font-size: 28rpx; 26 | vertical-align: middle; 27 | margin-left: 16rpx; 28 | /* color: gray; 已在style设置color,此处删去*/ 29 | } 30 | 31 | /* 下拉刷新--旋转进度条 */ 32 | .mescroll-downwarp .downwarp-progress { 33 | display: inline-block; 34 | width: 32rpx; 35 | height: 32rpx; 36 | border-radius: 50%; 37 | border: 2rpx solid gray; 38 | border-bottom-color: transparent !important; /*已在style设置border-color,此处需加 !important*/ 39 | vertical-align: middle; 40 | } 41 | 42 | /* 旋转动画 */ 43 | .mescroll-downwarp .mescroll-rotate { 44 | animation: mescrollDownRotate 0.6s linear infinite; 45 | } 46 | 47 | @keyframes mescrollDownRotate { 48 | 0% { 49 | transform: rotate(0deg); 50 | } 51 | 52 | 100% { 53 | transform: rotate(360deg); 54 | } 55 | } -------------------------------------------------------------------------------- /components/empty/index.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 47 | 48 | 67 | -------------------------------------------------------------------------------- /components/none/index.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 47 | 48 | 67 | -------------------------------------------------------------------------------- /utils/iconfont-new.scss: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'iconfont'; /* Project id 4514721 */ 3 | src: url('https://at.alicdn.com/t/c/font_4514721_cvr3z4lc04l.woff2?t=1722241706974') format('woff2'), 4 | url('https://at.alicdn.com/t/c/font_4514721_cvr3z4lc04l.woff?t=1722241706974') format('woff'), 5 | url('https://at.alicdn.com/t/c/font_4514721_cvr3z4lc04l.ttf?t=1722241706974') format('truetype'), 6 | url('https://at.alicdn.com/t/c/font_4514721_cvr3z4lc04l.svg?t=1722241706974#iconfont') format('svg'); 7 | } 8 | 9 | 10 | .iconfont { 11 | font-family: "iconfont" !important; 12 | font-size: 16px; 13 | font-style: normal; 14 | -webkit-font-smoothing: antialiased; 15 | -moz-osx-font-smoothing: grayscale; 16 | } 17 | 18 | .icon-yanzhengma:before { 19 | content: "\e660"; 20 | } 21 | 22 | .icon-shoujihao:before { 23 | content: "\e60f"; 24 | } 25 | 26 | .icon-gouwu:before { 27 | content: "\e899"; 28 | } 29 | 30 | .icon-fukuan:before { 31 | content: "\e62d"; 32 | } 33 | 34 | .icon-suo:before { 35 | content: "\e63e"; 36 | } 37 | 38 | .icon-tuxingyanzhengma:before { 39 | content: "\e799"; 40 | } 41 | 42 | .icon-fenxiang-post:before { 43 | content: "\e7c5"; 44 | } 45 | 46 | .icon-download-post:before { 47 | content: "\e63f"; 48 | } 49 | 50 | .icon-gift:before { 51 | content: "\e682"; 52 | } 53 | 54 | .icon-copy:before { 55 | content: "\e61c"; 56 | } 57 | 58 | 59 | -------------------------------------------------------------------------------- /pages/user/components/Popup.vue: -------------------------------------------------------------------------------- 1 | 5 | 6 | 56 | 57 | 60 | -------------------------------------------------------------------------------- /components/pop-manager/index.wxss: -------------------------------------------------------------------------------- 1 | .pop{visibility:hidden}.pop--show{visibility:visible}.pop__mask{position:fixed;top:0;left:0;right:0;bottom:0;z-index:14;background:rgba(0,0,0,.5);display:none}.pop__mask--hide{background:0 0}.pop__container{position:fixed;left:50%;top:50%;-webkit-transform:translate3d(-50%,-50%,0);transform:translate3d(-50%,-50%,0);-webkit-transform-origin:center;transform-origin:center;-webkit-transition:all .2s ease;transition:all .2s ease;z-index:15;opacity:0}.pop--show .pop__container{opacity:1}.pop--show .pop__mask{display:block}.pop--left .pop__container{left:0;top:50%;-webkit-transform:translate3d(-100%,-50%,0);transform:translate3d(-100%,-50%,0)}.pop--show.pop--left .pop__container{-webkit-transform:translate3d(0,-50%,0);transform:translate3d(0,-50%,0)}.pop--right .pop__container{right:0;top:50%;left:auto;-webkit-transform:translate3d(100%,-50%,0);transform:translate3d(100%,-50%,0)}.pop--show.pop--right .pop__container{-webkit-transform:translate3d(0,-50%,0);transform:translate3d(0,-50%,0)}.pop--bottom .pop__container{top:auto;left:50%;bottom:0;-webkit-transform:translate3d(-50%,100%,0);transform:translate3d(-50%,100%,0)}.pop--show.pop--bottom .pop__container{-webkit-transform:translate3d(-50%,0,0);transform:translate3d(-50%,0,0)}.pop--top .pop__container{top:0;left:50%;-webkit-transform:translate3d(-50%,-100%,0);transform:translate3d(-50%,-100%,0)}.pop--show.pop--top .pop__container{-webkit-transform:translate3d(-50%,0,0);transform:translate3d(-50%,0,0)} -------------------------------------------------------------------------------- /components/btn/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var nativeButtonBehavior = require('./native-button-behaviors'); 4 | 5 | Component({ 6 | externalClasses: ['custom-class', 'theme-class'], 7 | behaviors: [nativeButtonBehavior], 8 | relations: { 9 | '../btn-group/index': { 10 | type: 'parent', 11 | linked: function linked() { 12 | this.setData({ inGroup: true }); 13 | }, 14 | unlinked: function unlinked() { 15 | this.setData({ inGroup: false }); 16 | } 17 | } 18 | }, 19 | properties: { 20 | type: { 21 | type: String, 22 | value: '' 23 | }, 24 | size: { 25 | type: String, 26 | value: '' 27 | }, 28 | plain: { 29 | type: Boolean, 30 | value: false 31 | }, 32 | disabled: { 33 | type: Boolean, 34 | value: false 35 | }, 36 | loading: { 37 | type: Boolean, 38 | value: false 39 | } 40 | }, 41 | 42 | data: { 43 | inGroup: false, 44 | isLast: false 45 | }, 46 | 47 | methods: { 48 | handleTap: function handleTap() { 49 | if (this.data.disabled) { 50 | this.triggerEvent('disabledclick'); 51 | return; 52 | } 53 | this.triggerEvent('btnclick'); 54 | }, 55 | switchLastButtonStatus: function switchLastButtonStatus() { 56 | var isLast = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; 57 | 58 | this.setData({ isLast: isLast }); 59 | } 60 | } 61 | }); -------------------------------------------------------------------------------- /common/model/Region.js: -------------------------------------------------------------------------------- 1 | import * as Api from '@/api/region' 2 | import storage from '@/utils/storage' 3 | 4 | const REGION_TREE = 'region_tree' 5 | 6 | /** 7 | * 商品分类 model类 8 | * RegionModel 9 | */ 10 | export default { 11 | 12 | // 从服务端获取全部地区数据(树状) 13 | getTreeDataFromApi () { 14 | return new Promise((resolve, reject) => { 15 | Api.tree().then(result => resolve(result.data.data)) 16 | }) 17 | }, 18 | 19 | // 获取所有地区(树状) 20 | getTreeData () { 21 | return new Promise((resolve, reject) => { 22 | // 判断缓存中是否存在 23 | const data = storage.get(REGION_TREE) 24 | // 从服务端获取全部地区数据 25 | if (data) { 26 | resolve(data) 27 | } else { 28 | this.getTreeDataFromApi().then(list => { 29 | // 缓存24小时 30 | storage.set(REGION_TREE, list, 1 * 24 * 60 * 60 * 1000) 31 | resolve(list) 32 | }) 33 | } 34 | }) 35 | }, 36 | 37 | // 获取所有地区的总数 38 | getCitysCount () { 39 | return new Promise((resolve, reject) => { 40 | // 获取所有地区(树状) 41 | this.getTreeData().then(data => { 42 | const cityIds = [] 43 | // 遍历省份 44 | for (const pidx in data) { 45 | const province = data[pidx] 46 | // 遍历城市 47 | for (const cidx in province.city) { 48 | const cityItem = province.city[cidx] 49 | cityIds.push(cityItem.id) 50 | } 51 | } 52 | resolve(cityIds.length) 53 | }) 54 | }) 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /components/mixins/observer/behavior.js: -------------------------------------------------------------------------------- 1 | function setAsync(context, data) { 2 | return new Promise(resolve => { 3 | context.setData(data, resolve); 4 | }); 5 | } 6 | ; 7 | export const behavior = Behavior({ 8 | created() { 9 | if (!this.$options) { 10 | return; 11 | } 12 | const cache = {}; 13 | const { computed } = this.$options(); 14 | const keys = Object.keys(computed); 15 | this.calcComputed = () => { 16 | const needUpdate = {}; 17 | keys.forEach(key => { 18 | const value = computed[key].call(this); 19 | if (cache[key] !== value) { 20 | cache[key] = needUpdate[key] = value; 21 | } 22 | }); 23 | return needUpdate; 24 | }; 25 | }, 26 | attached() { 27 | this.set(); 28 | }, 29 | methods: { 30 | // set data and set computed data 31 | set(data, callback) { 32 | const stack = []; 33 | if (data) { 34 | stack.push(setAsync(this, data)); 35 | } 36 | if (this.calcComputed) { 37 | stack.push(setAsync(this, this.calcComputed())); 38 | } 39 | return Promise.all(stack).then(res => { 40 | if (callback && typeof callback === 'function') { 41 | callback.call(this); 42 | } 43 | return res; 44 | }); 45 | } 46 | } 47 | }); 48 | -------------------------------------------------------------------------------- /utils/verify.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 用户输入内容验证类 3 | */ 4 | 5 | // 是否为空 6 | export const isEmpty = (str) => { 7 | return str.trim() == '' 8 | } 9 | 10 | /** 11 | * 匹配phone 12 | */ 13 | export const isPhone = (str) => { 14 | const reg = /^((0\d{2,3}-\d{7,8})|(1[3456789]\d{9}))$/ 15 | return reg.test(str) 16 | } 17 | 18 | /** 19 | * 匹配phone 20 | */ 21 | export const isMobile = (str) => { 22 | const reg = /^(1[3456789]\d{9})$/ 23 | return reg.test(str) 24 | } 25 | 26 | /** 27 | * 匹配Email地址 28 | */ 29 | export const isEmail = (str) => { 30 | if (str == null || str == "") return false 31 | var result = str.match(/^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/) 32 | if (result == null) return false 33 | return true 34 | } 35 | 36 | /** 37 | * 判断数值类型,包括整数和浮点数 38 | */ 39 | export const isNumber = (str) => { 40 | if (isDouble(str) || isInteger(str)) return true 41 | return false 42 | } 43 | 44 | /** 45 | * 判断是否为正整数(只能输入数字[0-9]) 46 | */ 47 | export const isPositiveInteger = (str) => { 48 | return /(^[0-9]\d*$)/.test(str) 49 | } 50 | 51 | /** 52 | * 匹配integer 53 | */ 54 | export const isInteger = (str) => { 55 | if (str == null || str == "") return false 56 | var result = str.match(/^[-\+]?\d+$/) 57 | if (result == null) return false 58 | return true 59 | } 60 | 61 | /** 62 | * 匹配double或float 63 | */ 64 | export const isDouble = (str) => { 65 | if (str == null || str == "") return false 66 | var result = str.match(/^[-\+]?\d+(\.\d+)?$/) 67 | if (result == null) return false 68 | return true 69 | } 70 | -------------------------------------------------------------------------------- /uview-ui/components/u-full-screen/u-full-screen.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 38 | 39 | 53 | -------------------------------------------------------------------------------- /uview-ui/libs/function/guid.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 本算法来源于简书开源代码,详见:https://www.jianshu.com/p/fdbf293d0a85 3 | * 全局唯一标识符(uuid,Globally Unique Identifier),也称作 uuid(Universally Unique IDentifier) 4 | * 一般用于多个组件之间,给它一个唯一的标识符,或者v-for循环的时候,如果使用数组的index可能会导致更新列表出现问题 5 | * 最可能的情况是左滑删除item或者对某条信息流"不喜欢"并去掉它的时候,会导致组件内的数据可能出现错乱 6 | * v-for的时候,推荐使用后端返回的id而不是循环的index 7 | * @param {Number} len uuid的长度 8 | * @param {Boolean} firstU 将返回的首字母置为"u" 9 | * @param {Nubmer} radix 生成uuid的基数(意味着返回的字符串都是这个基数),2-二进制,8-八进制,10-十进制,16-十六进制 10 | */ 11 | function guid(len = 32, firstU = true, radix = null) { 12 | let chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split(''); 13 | let uuid = []; 14 | radix = radix || chars.length; 15 | 16 | if (len) { 17 | // 如果指定uuid长度,只是取随机的字符,0|x为位运算,能去掉x的小数位,返回整数位 18 | for (let i = 0; i < len; i++) uuid[i] = chars[0 | Math.random() * radix]; 19 | } else { 20 | let r; 21 | // rfc4122标准要求返回的uuid中,某些位为固定的字符 22 | uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-'; 23 | uuid[14] = '4'; 24 | 25 | for (let i = 0; i < 36; i++) { 26 | if (!uuid[i]) { 27 | r = 0 | Math.random() * 16; 28 | uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r]; 29 | } 30 | } 31 | } 32 | // 移除第一个字符,并用u替代,因为第一个字符为数值时,该guuid不能用作id或者class 33 | if (firstU) { 34 | uuid.shift(); 35 | return 'u' + uuid.join(''); 36 | } else { 37 | return uuid.join(''); 38 | } 39 | } 40 | 41 | export default guid; 42 | -------------------------------------------------------------------------------- /App.vue: -------------------------------------------------------------------------------- 1 | 59 | 60 | 64 | 65 | 69 | -------------------------------------------------------------------------------- /components/mescroll-uni/mixins/mescroll-comp.js: -------------------------------------------------------------------------------- 1 | /** 2 | * mescroll-body写在子组件时,需通过mescroll的mixins补充子组件缺少的生命周期 3 | */ 4 | const MescrollCompMixin = { 5 | // 因为子组件无onPageScroll和onReachBottom的页面生命周期,需在页面传递进到子组件 (一级) 6 | onPageScroll(e) { 7 | this.handlePageScroll(e) 8 | }, 9 | onReachBottom() { 10 | this.handleReachBottom() 11 | }, 12 | // 当down的native: true时, 还需传递此方法进到子组件 13 | onPullDownRefresh(){ 14 | this.handlePullDownRefresh() 15 | }, 16 | // mescroll-body写在子子子...组件的情况 (多级) 17 | data() { 18 | return { 19 | mescroll: { 20 | onPageScroll: e=>{ 21 | this.handlePageScroll(e) 22 | }, 23 | onReachBottom: ()=>{ 24 | this.handleReachBottom() 25 | }, 26 | onPullDownRefresh: ()=>{ 27 | this.handlePullDownRefresh() 28 | } 29 | } 30 | } 31 | }, 32 | methods:{ 33 | handlePageScroll(e){ 34 | let item = this.$refs["mescrollItem"]; 35 | if(item && item.mescroll) item.mescroll.onPageScroll(e); 36 | }, 37 | handleReachBottom(){ 38 | let item = this.$refs["mescrollItem"]; 39 | if(item && item.mescroll) item.mescroll.onReachBottom(); 40 | }, 41 | handlePullDownRefresh(){ 42 | let item = this.$refs["mescrollItem"]; 43 | if(item && item.mescroll) item.mescroll.onPullDownRefresh(); 44 | } 45 | } 46 | } 47 | 48 | export default MescrollCompMixin; 49 | -------------------------------------------------------------------------------- /components/page/search/index.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 43 | 44 | 76 | -------------------------------------------------------------------------------- /uview-ui/components/u-gap/u-gap.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 51 | 52 | 55 | -------------------------------------------------------------------------------- /components/common/component.js: -------------------------------------------------------------------------------- 1 | import { basic } from '../mixins/basic'; 2 | import { observe } from '../mixins/observer/index'; 3 | function mapKeys(source, target, map) { 4 | Object.keys(map).forEach(key => { 5 | if (source[key]) { 6 | target[map[key]] = source[key]; 7 | } 8 | }); 9 | } 10 | function VantComponent(vantOptions = {}) { 11 | const options = {}; 12 | mapKeys(vantOptions, options, { 13 | data: 'data', 14 | props: 'properties', 15 | mixins: 'behaviors', 16 | methods: 'methods', 17 | beforeCreate: 'created', 18 | created: 'attached', 19 | mounted: 'ready', 20 | relations: 'relations', 21 | destroyed: 'detached', 22 | classes: 'externalClasses' 23 | }); 24 | const { relation } = vantOptions; 25 | if (relation) { 26 | options.relations = Object.assign(options.relations || {}, { 27 | [`../${relation.name}/index`]: relation 28 | }); 29 | } 30 | // add default externalClasses 31 | options.externalClasses = options.externalClasses || []; 32 | options.externalClasses.push('custom-class'); 33 | // add default behaviors 34 | options.behaviors = options.behaviors || []; 35 | options.behaviors.push(basic); 36 | // map field to form-field behavior 37 | if (vantOptions.field) { 38 | options.behaviors.push('wx://form-field'); 39 | } 40 | // add default options 41 | options.options = { 42 | multipleSlots: true, 43 | addGlobalClass: true 44 | }; 45 | observe(vantOptions, options); 46 | Component(options); 47 | } 48 | export { VantComponent }; 49 | -------------------------------------------------------------------------------- /pages/prestore/components/Popup.vue: -------------------------------------------------------------------------------- 1 | 5 | 6 | 68 | 69 | 72 | -------------------------------------------------------------------------------- /subPages/prestore/components/Popup.vue: -------------------------------------------------------------------------------- 1 | 5 | 6 | 68 | 69 | 72 | -------------------------------------------------------------------------------- /components/mescroll-uni/components/mescroll-down.vue: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 44 | 45 | 48 | -------------------------------------------------------------------------------- /uview-ui/libs/function/timeFrom.js: -------------------------------------------------------------------------------- 1 | import timeFormat from '../../libs/function/timeFormat.js'; 2 | 3 | /** 4 | * 时间戳转为多久之前 5 | * @param String timestamp 时间戳 6 | * @param String | Boolean format 如果为时间格式字符串,超出一定时间范围,返回固定的时间格式; 7 | * 如果为布尔值false,无论什么时间,都返回多久以前的格式 8 | */ 9 | function timeFrom(dateTime = null, format = 'yyyy-mm-dd') { 10 | // 如果为null,则格式化当前时间 11 | if (!dateTime) dateTime = Number(new Date()); 12 | // 如果dateTime长度为10或者13,则为秒和毫秒的时间戳,如果超过13位,则为其他的时间格式 13 | if (dateTime.toString().length == 10) dateTime *= 1000; 14 | let timestamp = + new Date(Number(dateTime)); 15 | 16 | let timer = (Number(new Date()) - timestamp) / 1000; 17 | // 如果小于5分钟,则返回"刚刚",其他以此类推 18 | let tips = ''; 19 | switch (true) { 20 | case timer < 300: 21 | tips = '刚刚'; 22 | break; 23 | case timer >= 300 && timer < 3600: 24 | tips = parseInt(timer / 60) + '分钟前'; 25 | break; 26 | case timer >= 3600 && timer < 86400: 27 | tips = parseInt(timer / 3600) + '小时前'; 28 | break; 29 | case timer >= 86400 && timer < 2592000: 30 | tips = parseInt(timer / 86400) + '天前'; 31 | break; 32 | default: 33 | // 如果format为false,则无论什么时间戳,都显示xx之前 34 | if(format === false) { 35 | if(timer >= 2592000 && timer < 365 * 86400) { 36 | tips = parseInt(timer / (86400 * 30)) + '个月前'; 37 | } else { 38 | tips = parseInt(timer / (86400 * 365)) + '年前'; 39 | } 40 | } else { 41 | tips = timeFormat(timestamp, format); 42 | } 43 | } 44 | return tips; 45 | } 46 | 47 | export default timeFrom; 48 | -------------------------------------------------------------------------------- /components/dialog/index.wxss: -------------------------------------------------------------------------------- 1 | .zan-dialog--container { 2 | width: 80vw; 3 | font-size: 16px; 4 | overflow: hidden; 5 | border-radius: 4px; 6 | background-color: #fff; 7 | color: #333; 8 | } 9 | 10 | .zan-dialog__header { 11 | padding: 15px 0 0; 12 | text-align: center; 13 | } 14 | 15 | .zan-dialog__content { 16 | position: relative; 17 | padding: 15px 20px; 18 | line-height: 1.5; 19 | min-height: 40px; 20 | } 21 | 22 | .zan-dialog__content::after { 23 | content: ''; 24 | position: absolute; 25 | top: 0; 26 | left: 0; 27 | width: 200%; 28 | height: 200%; 29 | -webkit-transform: scale(0.5); 30 | transform: scale(0.5); 31 | -webkit-transform-origin: 0 0; 32 | transform-origin: 0 0; 33 | pointer-events: none; 34 | box-sizing: border-box; 35 | border: 0 solid #e5e5e5; 36 | border-bottom-width: 1px; 37 | } 38 | 39 | .zan-dialog__content--title { 40 | color: #999; 41 | font-size: 14px; 42 | } 43 | 44 | .zan-dialog__content--scroll { 45 | max-height: 70vh; 46 | } 47 | 48 | .zan-dialog__footer { 49 | overflow: hidden; 50 | } 51 | 52 | .zan-dialog__button { 53 | -webkit-box-flex: 1; 54 | flex: 1; 55 | } 56 | 57 | .zan-dialog__button-inside, .zan-dialog__button-inside--first { 58 | margin-bottom: 0; 59 | line-height: 50px; 60 | height: 50px; 61 | } 62 | 63 | .zan-dialog__button-inside--first::after, .zan-dialog__button-inside::after { 64 | border-width: 0; 65 | border-radius: 0; 66 | } 67 | 68 | .zan-dialog__footer--horizon { 69 | display: -webkit-box; 70 | display: flex; 71 | } 72 | 73 | .zan-dialog__footer--horizon .zan-dialog__button-inside::after { 74 | border-left-width: 1px; 75 | } 76 | 77 | .zan-dialog__footer--vertical .zan-dialog__button-inside::after { 78 | border-top-width: 1px; 79 | } 80 | -------------------------------------------------------------------------------- /components/mescroll-uni/mescroll-uni-option.js: -------------------------------------------------------------------------------- 1 | // 全局配置 2 | // mescroll-body 和 mescroll-uni 通用 3 | const GlobalOption = { 4 | down: { 5 | // 其他down的配置参数也可以写,这里只展示了常用的配置: 6 | textInOffset: '下拉刷新', // 下拉的距离在offset范围内的提示文本 7 | textOutOffset: '释放更新', // 下拉的距离大于offset范围的提示文本 8 | textLoading: '加载中 ...', // 加载中的提示文本 9 | textSuccess: '加载成功', // 加载成功的文本 10 | textErr: '加载失败', // 加载失败的文本 11 | beforeEndDelay: 100, // 延时结束的时长 (显示加载成功/失败的时长) 12 | offset: 80, // 在列表顶部,下拉大于80px,松手即可触发下拉刷新的回调 13 | native: false // 是否使用系统自带的下拉刷新; 默认false; 仅在mescroll-body生效 (值为true时,还需在pages配置enablePullDownRefresh:true;详请参考mescroll-native的案例) 14 | }, 15 | up: { 16 | // 其他up的配置参数也可以写,这里只展示了常用的配置: 17 | textLoading: '加载中 ...', // 加载中的提示文本 18 | textNoMore: '亲, 没有更多了', // 没有更多数据的提示文本 19 | offset: 150, // 距底部多远时,触发upCallback,仅mescroll-uni生效 ( mescroll-body配置的是pages.json的 onReachBottomDistance ) 20 | toTop: { 21 | // 回到顶部按钮,需配置src才显示 22 | src: "https://www.mescroll.com/img/mescroll-totop.png", // 图片路径 (建议放入static目录, 如 /static/img/mescroll-totop.png ) 23 | offset: 1000, // 列表滚动多少距离才显示回到顶部按钮,默认1000px 24 | right: 20, // 到右边的距离, 默认20 (支持"20rpx", "20px", "20%"格式的值, 纯数字则默认单位rpx) 25 | bottom: 120, // 到底部的距离, 默认120 (支持"20rpx", "20px", "20%"格式的值, 纯数字则默认单位rpx) 26 | width: 72 // 回到顶部图标的宽度, 默认72 (支持"20rpx", "20px", "20%"格式的值, 纯数字则默认单位rpx) 27 | }, 28 | empty: { 29 | use: true, // 是否显示空布局 30 | // icon: "https://www.mescroll.com/img/mescroll-empty.png", // 图标路径 (建议放入static目录, 如 /static/img/mescroll-empty.png ) 31 | icon: '/static/empty.png', 32 | tip: '亲,暂无相关数据' // 提示 33 | } 34 | } 35 | } 36 | 37 | export default GlobalOption 38 | -------------------------------------------------------------------------------- /components/search/index.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 33 | 34 | 79 | -------------------------------------------------------------------------------- /uview-ui/libs/util/emitter.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 递归使用 call 方式this指向 3 | * @param componentName // 需要找的组件的名称 4 | * @param eventName // 事件名称 5 | * @param params // 需要传递的参数 6 | */ 7 | function broadcast(componentName, eventName, params) { 8 | // 循环子节点找到名称一样的子节点 否则 递归 当前子节点 9 | this.$children.map(child=>{ 10 | if (componentName===child.$options.name) { 11 | child.$emit.apply(child,[eventName].concat(params)) 12 | }else { 13 | broadcast.apply(child,[componentName,eventName].concat(params)) 14 | } 15 | }) 16 | } 17 | export default { 18 | methods: { 19 | /** 20 | * 派发 (向上查找) (一个) 21 | * @param componentName // 需要找的组件的名称 22 | * @param eventName // 事件名称 23 | * @param params // 需要传递的参数 24 | */ 25 | dispatch(componentName, eventName, params) { 26 | let parent = this.$parent || this.$root;//$parent 找到最近的父节点 $root 根节点 27 | let name = parent.$options.name; // 获取当前组件实例的name 28 | // 如果当前有节点 && 当前没名称 且 当前名称等于需要传进来的名称的时候就去查找当前的节点 29 | // 循环出当前名称的一样的组件实例 30 | while (parent && (!name||name!==componentName)) { 31 | parent = parent.$parent; 32 | if (parent) { 33 | name = parent.$options.name; 34 | } 35 | } 36 | // 有节点表示当前找到了name一样的实例 37 | if (parent) { 38 | parent.$emit.apply(parent,[eventName].concat(params)) 39 | } 40 | }, 41 | /** 42 | * 广播 (向下查找) (广播多个) 43 | * @param componentName // 需要找的组件的名称 44 | * @param eventName // 事件名称 45 | * @param params // 需要传递的参数 46 | */ 47 | broadcast(componentName, eventName, params) { 48 | broadcast.call(this,componentName, eventName, params) 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /uni_modules/uni-popup/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "uni-popup", 3 | "displayName": "uni-popup 弹出层", 4 | "version": "1.6.0", 5 | "description": " Popup 组件,提供常用的弹层", 6 | "keywords": [ 7 | "uni-ui", 8 | "uniui", 9 | "弹出层" 10 | ], 11 | "repository": "https://github.com/dcloudio/uni-ui", 12 | "engines": { 13 | "HBuilderX": "" 14 | }, 15 | "directories": { 16 | "example": "../../temps/example_temps" 17 | }, 18 | "dcloudext": { 19 | "category": [ 20 | "前端组件", 21 | "通用组件" 22 | ], 23 | "sale": { 24 | "regular": { 25 | "price": "0.00" 26 | }, 27 | "sourcecode": { 28 | "price": "0.00" 29 | } 30 | }, 31 | "contact": { 32 | "qq": "" 33 | }, 34 | "declaration": { 35 | "ads": "无", 36 | "data": "无", 37 | "permissions": "无" 38 | }, 39 | "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" 40 | }, 41 | "uni_modules": { 42 | "dependencies": [ 43 | "uni-transition" 44 | ], 45 | "encrypt": [], 46 | "platforms": { 47 | "cloud": { 48 | "tcb": "y", 49 | "aliyun": "y" 50 | }, 51 | "client": { 52 | "App": { 53 | "app-vue": "y", 54 | "app-nvue": "y" 55 | }, 56 | "H5-mobile": { 57 | "Safari": "y", 58 | "Android Browser": "y", 59 | "微信浏览器(Android)": "y", 60 | "QQ浏览器(Android)": "y" 61 | }, 62 | "H5-pc": { 63 | "Chrome": "y", 64 | "IE": "y", 65 | "Edge": "y", 66 | "Firefox": "y", 67 | "Safari": "y" 68 | }, 69 | "小程序": { 70 | "微信": "y", 71 | "阿里": "y", 72 | "百度": "y", 73 | "字节跳动": "y", 74 | "QQ": "y" 75 | }, 76 | "快应用": { 77 | "华为": "u", 78 | "联盟": "u" 79 | } 80 | } 81 | } 82 | } 83 | } -------------------------------------------------------------------------------- /uview-ui/libs/function/getParent.js: -------------------------------------------------------------------------------- 1 | // 获取父组件的参数,因为支付宝小程序不支持provide/inject的写法 2 | // this.$parent在非H5中,可以准确获取到父组件,但是在H5中,需要多次this.$parent.$parent.xxx 3 | export default function getParent(name, keys) { 4 | let parent = this.$parent; 5 | // 通过while历遍,这里主要是为了H5需要多层解析的问题 6 | while (parent) { 7 | // 父组件 8 | if (parent.$options.name !== name) { 9 | // 如果组件的name不相等,继续上一级寻找 10 | parent = parent.$parent; 11 | } else { 12 | let data = {}; 13 | // 判断keys是否数组,如果传过来的是一个数组,那么直接使用数组元素值当做键值去父组件寻找 14 | if(Array.isArray(keys)) { 15 | keys.map(val => { 16 | data[val] = parent[val] ? parent[val] : ''; 17 | }) 18 | } else { 19 | // 历遍传过来的对象参数 20 | for(let i in keys) { 21 | // 如果子组件有此值则用,无此值则用父组件的值 22 | // 判断是否空数组,如果是,则用父组件的值,否则用子组件的值 23 | if(Array.isArray(keys[i])) { 24 | if(keys[i].length) { 25 | data[i] = keys[i]; 26 | } else { 27 | data[i] = parent[i]; 28 | } 29 | } else if(keys[i].constructor === Object) { 30 | // 判断是否对象,如果是对象,且有属性,那么使用子组件的值,否则使用父组件的值 31 | if(Object.keys(keys[i]).length) { 32 | data[i] = keys[i]; 33 | } else { 34 | data[i] = parent[i]; 35 | } 36 | } else { 37 | // 只要子组件有传值,即使是false值,也是“传值”了,也需要覆盖父组件的同名参数 38 | data[i] = (keys[i] || keys[i] === false) ? keys[i] : parent[i]; 39 | } 40 | } 41 | } 42 | return data; 43 | } 44 | } 45 | 46 | return {}; 47 | } -------------------------------------------------------------------------------- /uni_modules/uni-row/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "uni-row", 3 | "displayName": "uni-row 布局-行", 4 | "version": "0.0.4", 5 | "description": "流式栅格系统,随着屏幕或视口分为 24 份,可以迅速简便地创建布局。", 6 | "keywords": [ 7 | "uni-ui", 8 | "uniui", 9 | "栅格", 10 | "布局", 11 | "layout" 12 | ], 13 | "repository": "https://github.com/dcloudio/uni-ui", 14 | "engines": { 15 | "HBuilderX": "" 16 | }, 17 | "directories": { 18 | "example": "../../temps/example_temps" 19 | }, 20 | "dcloudext": { 21 | "category": [ 22 | "前端组件", 23 | "通用组件" 24 | ], 25 | "sale": { 26 | "regular": { 27 | "price": "0.00" 28 | }, 29 | "sourcecode": { 30 | "price": "0.00" 31 | } 32 | }, 33 | "contact": { 34 | "qq": "" 35 | }, 36 | "declaration": { 37 | "ads": "无", 38 | "data": "无", 39 | "permissions": "无" 40 | }, 41 | "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" 42 | }, 43 | "uni_modules": { 44 | "dependencies": [], 45 | "encrypt": [], 46 | "platforms": { 47 | "cloud": { 48 | "tcb": "y", 49 | "aliyun": "y" 50 | }, 51 | "client": { 52 | "App": { 53 | "app-vue": "y", 54 | "app-nvue": "y" 55 | }, 56 | "H5-mobile": { 57 | "Safari": "y", 58 | "Android Browser": "y", 59 | "微信浏览器(Android)": "y", 60 | "QQ浏览器(Android)": "y" 61 | }, 62 | "H5-pc": { 63 | "Chrome": "y", 64 | "IE": "y", 65 | "Edge": "y", 66 | "Firefox": "y", 67 | "Safari": "y" 68 | }, 69 | "小程序": { 70 | "微信": "y", 71 | "阿里": "y", 72 | "百度": "y", 73 | "字节跳动": "y", 74 | "QQ": "y" 75 | }, 76 | "快应用": { 77 | "华为": "u", 78 | "联盟": "u" 79 | } 80 | } 81 | } 82 | } 83 | } -------------------------------------------------------------------------------- /components/page/service/index.vue: -------------------------------------------------------------------------------- 1 | 20 | 21 | 69 | 70 | 87 | -------------------------------------------------------------------------------- /components/actionsheet/index.wxss: -------------------------------------------------------------------------------- 1 | .zan-actionsheet { 2 | background-color: #f8f8f8; 3 | } 4 | 5 | .zan-actionsheet__mask { 6 | position: fixed; 7 | top: 0; 8 | left: 0; 9 | right: 0; 10 | bottom: 0; 11 | z-index: 10; 12 | background: rgba(0, 0, 0, 0.7); 13 | display: none; 14 | } 15 | 16 | .zan-actionsheet__container { 17 | position: fixed; 18 | left: 0; 19 | right: 0; 20 | bottom: 0; 21 | background: #f8f8f8; 22 | -webkit-transform: translate3d(0, 50%, 0); 23 | transform: translate3d(0, 50%, 0); 24 | -webkit-transform-origin: center; 25 | transform-origin: center; 26 | -webkit-transition: all 0.2s ease; 27 | transition: all 0.2s ease; 28 | z-index: 11; 29 | opacity: 0; 30 | visibility: hidden; 31 | } 32 | 33 | .zan-actionsheet__btn { 34 | margin-bottom: 0 !important; 35 | } 36 | 37 | .zan-actionsheet__footer .zan-actionsheet__btn { 38 | background: #fff; 39 | } 40 | 41 | .zan-actionsheet__btn-content { 42 | display: -webkit-box; 43 | display: flex; 44 | -webkit-box-orient: horizontal; 45 | -webkit-box-direction: normal; 46 | flex-direction: row; 47 | -webkit-box-pack: center; 48 | justify-content: center; 49 | } 50 | 51 | .zan-actionsheet__subname { 52 | color: #999; 53 | } 54 | 55 | .zan-actionsheet__name, .zan-actionsheet__subname { 56 | height: 45px; 57 | line-height: 45px; 58 | } 59 | 60 | .zan-actionsheet__btn.zan-btn:last-child::after { 61 | border-bottom-width: 0; 62 | } 63 | 64 | .zan-actionsheet__subname { 65 | margin-left: 2px; 66 | font-size: 12px; 67 | } 68 | 69 | .zan-actionsheet__footer { 70 | margin-top: 10px; 71 | } 72 | 73 | .zan-actionsheet__btn--loading .zan-actionsheet__subname { 74 | color: transparent; 75 | } 76 | 77 | .zan-actionsheet--show .zan-actionsheet__container { 78 | opacity: 1; 79 | -webkit-transform: translate3d(0, 0, 0); 80 | transform: translate3d(0, 0, 0); 81 | visibility: visible; 82 | } 83 | 84 | .zan-actionsheet--show .zan-actionsheet__mask { 85 | display: block; 86 | } 87 | -------------------------------------------------------------------------------- /uview-ui/components/u-th/u-th.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 48 | 49 | 63 | -------------------------------------------------------------------------------- /components/mescroll-uni/mixins/mescroll-more-item.js: -------------------------------------------------------------------------------- 1 | /** 2 | * mescroll-more-item的mixins, 仅在多个 mescroll-body 写在子组件时使用 (参考 mescroll-more 案例) 3 | */ 4 | const MescrollMoreItemMixin = { 5 | // 支付宝小程序不支持props的mixin,需写在具体的页面中 6 | // #ifndef MP-ALIPAY || MP-DINGTALK 7 | props:{ 8 | i: Number, // 每个tab页的专属下标 9 | index: { // 当前tab的下标 10 | type: Number, 11 | default(){ 12 | return 0 13 | } 14 | } 15 | }, 16 | // #endif 17 | data() { 18 | return { 19 | downOption:{ 20 | auto:false // 不自动加载 21 | }, 22 | upOption:{ 23 | auto:false // 不自动加载 24 | }, 25 | isInit: false // 当前tab是否已初始化 26 | } 27 | }, 28 | watch:{ 29 | // 监听下标的变化 30 | index(val){ 31 | if (this.i === val && !this.isInit) { 32 | this.isInit = true; // 标记为true 33 | this.mescroll && this.mescroll.triggerDownScroll(); 34 | } 35 | } 36 | }, 37 | methods: { 38 | // 以ref的方式初始化mescroll对象 (兼容字节跳动小程序) 39 | mescrollInitByRef() { 40 | if(!this.mescroll || !this.mescroll.resetUpScroll){ 41 | // 字节跳动小程序编辑器不支持一个页面存在相同的ref, 多mescroll的ref需动态生成, 格式为'mescrollRef下标' 42 | let mescrollRef = this.$refs.mescrollRef || this.$refs['mescrollRef'+this.i]; 43 | if(mescrollRef) this.mescroll = mescrollRef.mescroll 44 | } 45 | }, 46 | // mescroll组件初始化的回调,可获取到mescroll对象 (覆盖mescroll-mixins.js的mescrollInit, 为了标记isInit) 47 | mescrollInit(mescroll) { 48 | this.mescroll = mescroll; 49 | this.mescrollInitByRef && this.mescrollInitByRef(); // 兼容字节跳动小程序 50 | // 自动加载当前tab的数据 51 | if(this.i === this.index){ 52 | this.isInit = true; // 标记为true 53 | this.mescroll.triggerDownScroll(); 54 | } 55 | }, 56 | } 57 | } 58 | 59 | export default MescrollMoreItemMixin; 60 | -------------------------------------------------------------------------------- /uview-ui/libs/function/timeFormat.js: -------------------------------------------------------------------------------- 1 | // padStart 的 polyfill,因为某些机型或情况,还无法支持es7的padStart,比如电脑版的微信小程序 2 | // 所以这里做一个兼容polyfill的兼容处理 3 | if (!String.prototype.padStart) { 4 | // 为了方便表示这里 fillString 用了ES6 的默认参数,不影响理解 5 | String.prototype.padStart = function(maxLength, fillString = ' ') { 6 | if (Object.prototype.toString.call(fillString) !== "[object String]") throw new TypeError( 7 | 'fillString must be String') 8 | let str = this 9 | // 返回 String(str) 这里是为了使返回的值是字符串字面量,在控制台中更符合直觉 10 | if (str.length >= maxLength) return String(str) 11 | 12 | let fillLength = maxLength - str.length, 13 | times = Math.ceil(fillLength / fillString.length) 14 | while (times >>= 1) { 15 | fillString += fillString 16 | if (times === 1) { 17 | fillString += fillString 18 | } 19 | } 20 | return fillString.slice(0, fillLength) + str; 21 | } 22 | } 23 | 24 | // 其他更多是格式化有如下: 25 | // yyyy:mm:dd|yyyy:mm|yyyy年mm月dd日|yyyy年mm月dd日 hh时MM分等,可自定义组合 26 | function timeFormat(dateTime = null, fmt = 'yyyy-mm-dd') { 27 | // 如果为null,则格式化当前时间 28 | if (!dateTime) dateTime = Number(new Date()); 29 | // 如果dateTime长度为10或者13,则为秒和毫秒的时间戳,如果超过13位,则为其他的时间格式 30 | if (dateTime.toString().length == 10) dateTime *= 1000; 31 | let date = new Date(dateTime); 32 | let ret; 33 | let opt = { 34 | "y+": date.getFullYear().toString(), // 年 35 | "m+": (date.getMonth() + 1).toString(), // 月 36 | "d+": date.getDate().toString(), // 日 37 | "h+": date.getHours().toString(), // 时 38 | "M+": date.getMinutes().toString(), // 分 39 | "s+": date.getSeconds().toString() // 秒 40 | // 有其他格式化字符需求可以继续添加,必须转化成字符串 41 | }; 42 | for (let k in opt) { 43 | ret = new RegExp("(" + k + ")").exec(fmt); 44 | if (ret) { 45 | fmt = fmt.replace(ret[1], (ret[1].length == 1) ? (opt[k]) : (opt[k].padStart(ret[1].length, "0"))) 46 | }; 47 | }; 48 | return fmt; 49 | } 50 | 51 | export default timeFormat 52 | -------------------------------------------------------------------------------- /common/enum/enum.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 枚举类 3 | * Enum.IMAGE.name => "图片" 4 | * Enum.getNameByKey('IMAGE') => "图片" 5 | * Enum.getValueByKey('IMAGE') => 10 6 | * Enum.getNameByValue(10) => "图片" 7 | * Enum.getData() => [{key: "IMAGE", name: "图片", value: 10}] 8 | */ 9 | class Enum { 10 | constructor (param) { 11 | const keyArr = [] 12 | const valueArr = [] 13 | 14 | if (!Array.isArray(param)) { 15 | throw new Error('param is not an array!') 16 | } 17 | 18 | param.map(element => { 19 | if (!element.key || !element.name) { 20 | return 21 | } 22 | // 保存key值组成的数组,方便A.getName(name)类型的调用 23 | keyArr.push(element.key) 24 | valueArr.push(element.value) 25 | // 根据key生成不同属性值,以便A.B.name类型的调用 26 | this[element.key] = element 27 | if (element.key !== element.value) { 28 | this[element.value] = element 29 | } 30 | }) 31 | 32 | 33 | // 保存源数组 34 | this.data = param 35 | this.keyArr = keyArr 36 | this.valueArr = valueArr 37 | 38 | // 防止被修改 39 | // Object.freeze(this) 40 | } 41 | 42 | // 根据key得到对象 43 | keyOf (key) { 44 | return this.data[this.keyArr.indexOf(key)] 45 | } 46 | 47 | // 根据key得到对象 48 | valueOf (key) { 49 | return this.data[this.valueArr.indexOf(key)] 50 | } 51 | 52 | // 根据key获取name值 53 | getNameByKey (key) { 54 | const prop = this.keyOf(key) 55 | if (!prop) { 56 | throw new Error('No enum constant' + key) 57 | } 58 | return prop.name 59 | } 60 | 61 | // 根据value获取name值 62 | getNameByValue (value) { 63 | const prop = this.valueOf(value) 64 | if (!prop) { 65 | throw new Error('No enum constant' + value) 66 | } 67 | return prop.name 68 | } 69 | 70 | // 根据key获取value值 71 | getValueByKey (key) { 72 | const prop = this.keyOf(key) 73 | if (!prop) { 74 | throw new Error('No enum constant' + key) 75 | } 76 | return prop.key 77 | } 78 | 79 | // 返回源数组 80 | getData () { 81 | return this.data 82 | } 83 | } 84 | 85 | export default Enum 86 | -------------------------------------------------------------------------------- /uni.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * 这里是uni-app内置的常用样式变量 3 | * 4 | * uni-app 官方扩展插件及插件市场(https://ext.dcloud.net.cn)上很多三方插件均使用了这些样式变量 5 | * 如果你是插件开发者,建议你使用scss预处理,并在插件代码中直接使用这些变量(无需 import 这个文件),方便用户通过搭积木的方式开发整体风格一致的App 6 | * 7 | */ 8 | 9 | /** 10 | * 如果你是App开发者(插件使用者),你可以通过修改这些变量来定制自己的插件主题,实现自定义主题功能 11 | * 12 | * 如果你的项目同样使用了scss预处理,你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件 13 | */ 14 | 15 | /* 颜色变量 */ 16 | $fuint-theme: #00acac; 17 | 18 | /* 行为相关颜色 */ 19 | $uni-color-primary: #007aff; 20 | $uni-color-success: #4cd964; 21 | $uni-color-warning: #f0ad4e; 22 | $uni-color-error: #dd524d; 23 | 24 | /* 文字基本颜色 */ 25 | $uni-text-color:#333;//基本色 26 | $uni-text-color-inverse:#fff;//反色 27 | $uni-text-color-grey:#999;//辅助灰色,如加载更多的提示信息 28 | $uni-text-color-placeholder: #808080; 29 | $uni-text-color-disable:#c0c0c0; 30 | $uni-text-color-active:#fa2209; // 激活的颜色红 31 | 32 | /* 背景颜色 */ 33 | $uni-bg-color:#ffffff; 34 | $uni-bg-color-grey:#f8f8f8; 35 | $uni-bg-color-hover:#f1f1f1;//点击状态颜色 36 | $uni-bg-color-mask:rgba(0, 0, 0, 0.4);//遮罩颜色 37 | 38 | /* 边框颜色 */ 39 | $uni-border-color:#c8c7cc; 40 | 41 | /* 尺寸变量 */ 42 | 43 | /* 文字尺寸 */ 44 | $uni-font-size-sm:24rpx; 45 | $uni-font-size-base:28rpx; 46 | $uni-font-size-lg:32rpx; 47 | 48 | /* 图片尺寸 */ 49 | $uni-img-size-sm:40rpx; 50 | $uni-img-size-base:52rpx; 51 | $uni-img-size-lg:80rpx; 52 | 53 | /* Border Radius */ 54 | $uni-border-radius-sm: 4rpx; 55 | $uni-border-radius-base: 6rpx; 56 | $uni-border-radius-lg: 12rpx; 57 | $uni-border-radius-circle: 50%; 58 | 59 | /* 水平间距 */ 60 | $uni-spacing-row-sm: 10px; 61 | $uni-spacing-row-base: 20rpx; 62 | $uni-spacing-row-lg: 30rpx; 63 | 64 | /* 垂直间距 */ 65 | $uni-spacing-col-sm: 8rpx; 66 | $uni-spacing-col-base: 16rpx; 67 | $uni-spacing-col-lg: 24rpx; 68 | 69 | /* 透明度 */ 70 | $uni-opacity-disabled: 0.3; // 组件禁用态的透明度 71 | 72 | /* 文章场景相关 */ 73 | $uni-color-title: #2C405A; // 文章标题颜色 74 | $uni-font-size-title:40rpx; 75 | $uni-color-subtitle: #555555; // 二级标题颜色 76 | $uni-font-size-subtitle:36rpx; 77 | $uni-color-paragraph: #3F536E; // 文章段落颜色 78 | $uni-font-size-paragraph:30rpx; 79 | 80 | 81 | /* 引入uView全局scss变量文件 */ 82 | @import "uview-ui/theme.scss"; -------------------------------------------------------------------------------- /uview-ui/components/u-cell-group/u-cell-group.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 51 | 52 | 71 | -------------------------------------------------------------------------------- /uview-ui/components/u-td/u-td.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 51 | 52 | 67 | -------------------------------------------------------------------------------- /pages/article/detail.vue: -------------------------------------------------------------------------------- 1 | 21 | 22 | 67 | 68 | 83 | -------------------------------------------------------------------------------- /components/loading/index.wxss: -------------------------------------------------------------------------------- 1 | @import '../common/index.wxss';.van-loading{z-index:0;line-height:0;position:relative;display:inline-block;vertical-align:middle}.van-loading__spinner{z-index:-1;width:100%;height:100%;position:relative;display:inline-block;box-sizing:border-box;-webkit-animation:van-rotate .8s linear infinite;animation:van-rotate .8s linear infinite}.van-loading__spinner--spinner{-webkit-animation-timing-function:steps(12);animation-timing-function:steps(12)}.van-loading__spinner--circular{border:1px solid;border-radius:100%;border-color:transparent;border-top-color:currentColor}.van-loading__dot{top:0;left:0;width:100%;height:100%;position:absolute}.van-loading__dot::before{width:2px;height:25%;content:' ';display:block;margin:0 auto;border-radius:40%;background-color:currentColor}.van-loading__dot:nth-of-type(1){opacity:1;-webkit-transform:rotate(30deg);transform:rotate(30deg)}.van-loading__dot:nth-of-type(2){opacity:.9375;-webkit-transform:rotate(60deg);transform:rotate(60deg)}.van-loading__dot:nth-of-type(3){opacity:.875;-webkit-transform:rotate(90deg);transform:rotate(90deg)}.van-loading__dot:nth-of-type(4){opacity:.8125;-webkit-transform:rotate(120deg);transform:rotate(120deg)}.van-loading__dot:nth-of-type(5){opacity:.75;-webkit-transform:rotate(150deg);transform:rotate(150deg)}.van-loading__dot:nth-of-type(6){opacity:.6875;-webkit-transform:rotate(180deg);transform:rotate(180deg)}.van-loading__dot:nth-of-type(7){opacity:.625;-webkit-transform:rotate(210deg);transform:rotate(210deg)}.van-loading__dot:nth-of-type(8){opacity:.5625;-webkit-transform:rotate(240deg);transform:rotate(240deg)}.van-loading__dot:nth-of-type(9){opacity:.5;-webkit-transform:rotate(270deg);transform:rotate(270deg)}.van-loading__dot:nth-of-type(10){opacity:.4375;-webkit-transform:rotate(300deg);transform:rotate(300deg)}.van-loading__dot:nth-of-type(11){opacity:.375;-webkit-transform:rotate(330deg);transform:rotate(330deg)}.van-loading__dot:nth-of-type(12){opacity:.3125;-webkit-transform:rotate(360deg);transform:rotate(360deg)}@-webkit-keyframes van-rotate{from{-webkit-transform:rotate(0);transform:rotate(0)}to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes van-rotate{from{-webkit-transform:rotate(0);transform:rotate(0)}to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}} -------------------------------------------------------------------------------- /utils/storage.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 缓存数据优化 3 | * const storage = require('@/utils/storage'); 4 | * import storage from '@/utils/storage' 5 | * 使用方法 【 6 | * 一、设置缓存 7 | * string storage.set('k', 'string你好啊'); 8 | * json storage.set('k', { "b": "3" }, 2); 9 | * array storage.set('k', [1, 2, 3]); 10 | * boolean storage.set('k', true); 11 | * 二、读取缓存 12 | * 默认值 storage.get('k') 13 | * string storage.get('k', '你好') 14 | * json storage.get('k', { "a": "1" }) 15 | * 三、移除/清理 16 | * 移除: storage.remove('k'); 17 | * 清理:storage.clear(); 18 | * 】 19 | * @type {String} 20 | */ 21 | 22 | const postfix = '_expiry' // 缓存有效期后缀 23 | 24 | module.exports = { 25 | 26 | /** 27 | * 设置缓存 28 | * @param {[type]} k [键名] 29 | * @param {[type]} v [键值] 30 | * @param {[type]} t [时间、单位秒] 31 | */ 32 | set(k, v, t) { 33 | uni.setStorageSync(k, v) 34 | const seconds = parseInt(t) 35 | if (seconds > 0) { 36 | let timestamp = Date.parse(new Date()) 37 | timestamp = timestamp / 1000 + seconds 38 | uni.setStorageSync(k + postfix, timestamp + '') 39 | } else { 40 | uni.removeStorageSync(k + postfix) 41 | } 42 | }, 43 | 44 | /** 45 | * 获取缓存 46 | * @param {[type]} k [键名] 47 | * @param {[type]} def [获取为空时默认] 48 | */ 49 | get(k, def) { 50 | const deadtime = parseInt(uni.getStorageSync(k + postfix)) 51 | if (deadtime) { 52 | if (parseInt(deadtime) < Date.parse(new Date()) / 1000) { 53 | if (def) { 54 | return def 55 | } else { 56 | return false 57 | } 58 | } 59 | } 60 | const res = uni.getStorageSync(k) 61 | if (res) { 62 | return res 63 | } 64 | if (def == undefined || def == "") { 65 | def = false 66 | } 67 | return def 68 | }, 69 | 70 | /** 71 | * 删除指定缓存 72 | * @param {Object} k 73 | */ 74 | remove(k) { 75 | uni.removeStorageSync(k) 76 | uni.removeStorageSync(k + postfix) 77 | }, 78 | 79 | /** 80 | * 清理所有缓存 81 | * @return {[type]} [description] 82 | */ 83 | clear() { 84 | uni.clearStorageSync() 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /uview-ui/libs/function/queryParams.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 对象转url参数 3 | * @param {*} data,对象 4 | * @param {*} isPrefix,是否自动加上"?" 5 | */ 6 | function queryParams(data = {}, isPrefix = true, arrayFormat = 'brackets') { 7 | let prefix = isPrefix ? '?' : '' 8 | let _result = [] 9 | if (['indices', 'brackets', 'repeat', 'comma'].indexOf(arrayFormat) == -1) arrayFormat = 'brackets'; 10 | for (let key in data) { 11 | let value = data[key] 12 | // 去掉为空的参数 13 | if (['', undefined, null].indexOf(value) >= 0) { 14 | continue; 15 | } 16 | // 如果值为数组,另行处理 17 | if (value.constructor === Array) { 18 | // e.g. {ids: [1, 2, 3]} 19 | switch (arrayFormat) { 20 | case 'indices': 21 | // 结果: ids[0]=1&ids[1]=2&ids[2]=3 22 | for (let i = 0; i < value.length; i++) { 23 | _result.push(key + '[' + i + ']=' + value[i]) 24 | } 25 | break; 26 | case 'brackets': 27 | // 结果: ids[]=1&ids[]=2&ids[]=3 28 | value.forEach(_value => { 29 | _result.push(key + '[]=' + _value) 30 | }) 31 | break; 32 | case 'repeat': 33 | // 结果: ids=1&ids=2&ids=3 34 | value.forEach(_value => { 35 | _result.push(key + '=' + _value) 36 | }) 37 | break; 38 | case 'comma': 39 | // 结果: ids=1,2,3 40 | let commaStr = ""; 41 | value.forEach(_value => { 42 | commaStr += (commaStr ? "," : "") + _value; 43 | }) 44 | _result.push(key + '=' + commaStr) 45 | break; 46 | default: 47 | value.forEach(_value => { 48 | _result.push(key + '[]=' + _value) 49 | }) 50 | } 51 | } else { 52 | _result.push(key + '=' + value) 53 | } 54 | } 55 | return _result.length ? prefix + _result.join('&') : '' 56 | } 57 | 58 | export default queryParams; 59 | -------------------------------------------------------------------------------- /pages/goods/components/SlideImage.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 60 | 61 | 89 | -------------------------------------------------------------------------------- /components/mescroll-uni/mescroll-mixins.js: -------------------------------------------------------------------------------- 1 | // mescroll-body 和 mescroll-uni 通用 2 | 3 | // import MescrollUni from "./mescroll-uni.vue"; 4 | // import MescrollBody from "./mescroll-body.vue"; 5 | 6 | const MescrollMixin = { 7 | // components: { // 非H5端无法通过mixin注册组件, 只能在main.js中注册全局组件或具体界面中注册 8 | // MescrollUni, 9 | // MescrollBody 10 | // }, 11 | data() { 12 | return { 13 | mescroll: null //mescroll实例对象 14 | } 15 | }, 16 | // 注册系统自带的下拉刷新 (配置down.native为true时生效, 还需在pages配置enablePullDownRefresh:true;详请参考mescroll-native的案例) 17 | onPullDownRefresh(){ 18 | this.mescroll && this.mescroll.onPullDownRefresh(); 19 | }, 20 | // 注册列表滚动事件,用于判定在顶部可下拉刷新,在指定位置可显示隐藏回到顶部按钮 (此方法为页面生命周期,无法在子组件中触发, 仅在mescroll-body生效) 21 | onPageScroll(e) { 22 | this.mescroll && this.mescroll.onPageScroll(e); 23 | }, 24 | // 注册滚动到底部的事件,用于上拉加载 (此方法为页面生命周期,无法在子组件中触发, 仅在mescroll-body生效) 25 | onReachBottom() { 26 | this.mescroll && this.mescroll.onReachBottom(); 27 | }, 28 | methods: { 29 | // mescroll组件初始化的回调,可获取到mescroll对象 30 | mescrollInit(mescroll) { 31 | this.mescroll = mescroll; 32 | this.mescrollInitByRef(); // 兼容字节跳动小程序 33 | }, 34 | // 以ref的方式初始化mescroll对象 (兼容字节跳动小程序) 35 | mescrollInitByRef() { 36 | if(!this.mescroll || !this.mescroll.resetUpScroll){ 37 | let mescrollRef = this.$refs.mescrollRef; 38 | if(mescrollRef) this.mescroll = mescrollRef.mescroll 39 | } 40 | }, 41 | // 下拉刷新的回调 (mixin默认resetUpScroll) 42 | downCallback() { 43 | if(this.mescroll.optUp.use){ 44 | this.mescroll.resetUpScroll() 45 | }else{ 46 | setTimeout(()=>{ 47 | this.mescroll.endSuccess(); 48 | }, 500) 49 | } 50 | }, 51 | // 上拉加载的回调 52 | upCallback() { 53 | // mixin默认延时500自动结束加载 54 | setTimeout(()=>{ 55 | this.mescroll.endErr(); 56 | }, 500) 57 | } 58 | }, 59 | mounted() { 60 | this.mescrollInitByRef(); // 兼容字节跳动小程序, 避免未设置@init或@init此时未能取到ref的情况 61 | } 62 | 63 | } 64 | 65 | export default MescrollMixin; 66 | -------------------------------------------------------------------------------- /uview-ui/components/u-time-line-item/u-time-line-item.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 52 | 53 | 84 | -------------------------------------------------------------------------------- /uview-ui/libs/mixin/mixin.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | data() { 3 | return {} 4 | }, 5 | onLoad() { 6 | // getRect挂载到$u上,因为这方法需要使用in(this),所以无法把它独立成一个单独的文件导出 7 | this.$u.getRect = this.$uGetRect 8 | }, 9 | methods: { 10 | // 查询节点信息 11 | // 目前此方法在支付宝小程序中无法获取组件跟接点的尺寸,为支付宝的bug(2020-07-21) 12 | // 解决办法为在组件根部再套一个没有任何作用的view元素 13 | $uGetRect(selector, all) { 14 | return new Promise(resolve => { 15 | uni.createSelectorQuery(). 16 | in(this)[all ? 'selectAll' : 'select'](selector) 17 | .boundingClientRect(rect => { 18 | if (all && Array.isArray(rect) && rect.length) { 19 | resolve(rect) 20 | } 21 | if (!all && rect) { 22 | resolve(rect) 23 | } 24 | }) 25 | .exec() 26 | }) 27 | }, 28 | getParentData(parentName = '') { 29 | // 避免在created中去定义parent变量 30 | if(!this.parent) this.parent = false; 31 | // 这里的本质原理是,通过获取父组件实例(也即u-radio-group的this) 32 | // 将父组件this中对应的参数,赋值给本组件(u-radio的this)的parentData对象中对应的属性 33 | // 之所以需要这么做,是因为所有端中,头条小程序不支持通过this.parent.xxx去监听父组件参数的变化 34 | this.parent = this.$u.$parent.call(this, parentName); 35 | if(this.parent) { 36 | // 历遍parentData中的属性,将parent中的同名属性赋值给parentData 37 | Object.keys(this.parentData).map(key => { 38 | this.parentData[key] = this.parent[key]; 39 | }); 40 | } 41 | }, 42 | // 阻止事件冒泡 43 | preventEvent(e) { 44 | e && e.stopPropagation && e.stopPropagation() 45 | } 46 | }, 47 | onReachBottom() { 48 | uni.$emit('uOnReachBottom') 49 | }, 50 | beforeDestroy() { 51 | // 判断当前页面是否存在parent和chldren,一般在checkbox和checkbox-group父子联动的场景会有此情况 52 | // 组件销毁时,移除子组件在父组件children数组中的实例,释放资源,避免数据混乱 53 | if(this.parent && uni.$u.test.array(this.parent.children)) { 54 | // 组件销毁时,移除父组件中的children数组中对应的实例 55 | const childrenList = this.parent.children 56 | childrenList.map((child, index) => { 57 | // 如果相等,则移除 58 | if(child === this) { 59 | childrenList.splice(index, 1) 60 | } 61 | }) 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /components/btn/native-button-behaviors.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = Behavior({ 4 | properties: { 5 | loading: Boolean, 6 | // 在自定义组件中,无法与外界的 form 组件联动,暂时不开放 7 | // formType: String, 8 | openType: String, 9 | appParameter: String, 10 | // 暂时不开放,直接传入无法设置样式 11 | // hoverClass: { 12 | // type: String, 13 | // value: 'button-hover' 14 | // }, 15 | hoverStopPropagation: Boolean, 16 | hoverStartTime: { 17 | type: Number, 18 | value: 20 19 | }, 20 | hoverStayTime: { 21 | type: Number, 22 | value: 70 23 | }, 24 | lang: { 25 | type: String, 26 | value: 'en' 27 | }, 28 | sessionFrom: { 29 | type: String, 30 | value: '' 31 | }, 32 | sendMessageTitle: String, 33 | sendMessagePath: String, 34 | sendMessageImg: String, 35 | showMessageCard: String 36 | }, 37 | methods: { 38 | bindgetuserinfo: function bindgetuserinfo() { 39 | var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, 40 | _ref$detail = _ref.detail, 41 | detail = _ref$detail === undefined ? {} : _ref$detail; 42 | 43 | this.triggerEvent('getuserinfo', detail); 44 | }, 45 | bindcontact: function bindcontact() { 46 | var _ref2 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, 47 | _ref2$detail = _ref2.detail, 48 | detail = _ref2$detail === undefined ? {} : _ref2$detail; 49 | 50 | this.triggerEvent('contact', detail); 51 | }, 52 | bindgetphonenumber: function bindgetphonenumber() { 53 | var _ref3 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, 54 | _ref3$detail = _ref3.detail, 55 | detail = _ref3$detail === undefined ? {} : _ref3$detail; 56 | 57 | this.triggerEvent('getphonenumber', detail); 58 | }, 59 | bindopensetting: function bindopensetting() { 60 | var _ref4 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, 61 | _ref4$detail = _ref4.detail, 62 | detail = _ref4$detail === undefined ? {} : _ref4$detail; 63 | 64 | this.triggerEvent('opensetting', detail); 65 | }, 66 | binderror: function binderror() { 67 | var _ref5 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, 68 | _ref5$detail = _ref5.detail, 69 | detail = _ref5$detail === undefined ? {} : _ref5$detail; 70 | 71 | this.triggerEvent('error', detail); 72 | } 73 | } 74 | }); -------------------------------------------------------------------------------- /components/mescroll-uni/components/mescroll-top.vue: -------------------------------------------------------------------------------- 1 | 2 | 13 | 14 | 49 | 50 | 84 | -------------------------------------------------------------------------------- /components/mescroll-uni/mixins/mescroll-more.js: -------------------------------------------------------------------------------- 1 | /** 2 | * mescroll-body写在子组件时, 需通过mescroll的mixins补充子组件缺少的生命周期 3 | */ 4 | const MescrollMoreMixin = { 5 | data() { 6 | return { 7 | tabIndex: 0, // 当前tab下标 8 | mescroll: { 9 | onPageScroll: e=>{ 10 | this.handlePageScroll(e) 11 | }, 12 | onReachBottom: ()=>{ 13 | this.handleReachBottom() 14 | }, 15 | onPullDownRefresh: ()=>{ 16 | this.handlePullDownRefresh() 17 | } 18 | } 19 | } 20 | }, 21 | // 因为子组件无onPageScroll和onReachBottom的页面生命周期,需在页面传递进到子组件 22 | onPageScroll(e) { 23 | this.handlePageScroll(e) 24 | }, 25 | onReachBottom() { 26 | this.handleReachBottom() 27 | }, 28 | // 当down的native: true时, 还需传递此方法进到子组件 29 | onPullDownRefresh(){ 30 | this.handlePullDownRefresh() 31 | }, 32 | methods:{ 33 | handlePageScroll(e){ 34 | let mescroll = this.getMescroll(this.tabIndex); 35 | mescroll && mescroll.onPageScroll(e); 36 | }, 37 | handleReachBottom(){ 38 | let mescroll = this.getMescroll(this.tabIndex); 39 | mescroll && mescroll.onReachBottom(); 40 | }, 41 | handlePullDownRefresh(){ 42 | let mescroll = this.getMescroll(this.tabIndex); 43 | mescroll && mescroll.onPullDownRefresh(); 44 | }, 45 | // 根据下标获取对应子组件的mescroll 46 | getMescroll(i){ 47 | if(!this.mescrollItems) this.mescrollItems = []; 48 | if(!this.mescrollItems[i]) { 49 | // v-for中的refs 50 | let vForItem = this.$refs["mescrollItem"]; 51 | if(vForItem){ 52 | this.mescrollItems[i] = vForItem[i] 53 | }else{ 54 | // 普通的refs,不可重复 55 | this.mescrollItems[i] = this.$refs["mescrollItem"+i]; 56 | } 57 | } 58 | let item = this.mescrollItems[i] 59 | return item ? item.mescroll : null 60 | }, 61 | // 切换tab,恢复滚动条位置 62 | tabChange(i){ 63 | let mescroll = this.getMescroll(i); 64 | if(mescroll){ 65 | // 延时(比$nextTick靠谱一些),确保元素已渲染 66 | setTimeout(()=>{ 67 | mescroll.scrollTo(mescroll.getScrollTop(),0) 68 | },30) 69 | } 70 | } 71 | } 72 | } 73 | 74 | export default MescrollMoreMixin; 75 | -------------------------------------------------------------------------------- /components/mescroll-uni/components/mescroll-empty.vue: -------------------------------------------------------------------------------- 1 | 8 | 15 | 16 | 48 | 49 | 91 | -------------------------------------------------------------------------------- /components/btn/index.wxss: -------------------------------------------------------------------------------- 1 | .zan-btn{position:relative;color:#333;background-color:#fff;padding-left:15px;padding-right:15px;border-radius:2px;font-size:16px;line-height:45px;height:45px;box-sizing:border-box;text-decoration:none;text-align:center;vertical-align:middle;overflow:visible}.zan-btn--group{margin-bottom:10px}.zan-btn::after{content:'';position:absolute;top:0;left:0;width:200%;height:200%;-webkit-transform:scale(.5);transform:scale(.5);-webkit-transform-origin:0 0;transform-origin:0 0;pointer-events:none;box-sizing:border-box;border:0 solid #e5e5e5;border-width:1px;border-radius:4px}.zan-btn--primary{color:#fff;background-color:#4b0}.zan-btn--primary::after{border-color:#0a0}.zan-btn--warn{color:#fff;background-color:#f85}.zan-btn--warn::after{border-color:#f85}.zan-btn--danger{color:#fff;background-color:#f44}.zan-btn--danger::after{border-color:#e33}.zan-btn--small{display:inline-block;height:30px;line-height:30px;font-size:12px}.zan-btn--small.zan-btn--group{margin-bottom:0;margin-right:5px}.zan-btn--mini{display:inline-block;line-height:21px;height:22px;font-size:10px;padding-left:5px;padding-right:5px}.zan-btn--mini.zan-btn--group{margin-bottom:0;margin-right:5px}.zan-btn--large{border-radius:0;border:none;line-height:50px;height:50px}.zan-btn--large.zan-btn--group{margin-bottom:0}.zan-btn--plain.zan-btn{background-color:transparent}.zan-btn--plain.zan-btn--primary{color:#06bf04}.zan-btn--plain.zan-btn--warn{color:#f60}.zan-btn--plain.zan-btn--danger{color:#f44}.button-hover{opacity:.9}.zan-btn--loading{color:transparent;opacity:1}.zan-btn--loading::before{position:absolute;left:50%;top:50%;content:' ';width:16px;height:16px;margin-left:-8px;margin-top:-8px;border:3px solid #e5e5e5;border-color:#666 #e5e5e5 #e5e5e5 #e5e5e5;border-radius:8px;box-sizing:border-box;-webkit-animation:btn-spin .6s linear;animation:btn-spin .6s linear;-webkit-animation-iteration-count:infinite;animation-iteration-count:infinite}.zan-btn--danger.zan-btn--loading::before,.zan-btn--primary.zan-btn--loading::before,.zan-btn--warn.zan-btn--loading::before{border-color:#fff rgba(0,0,0,.1) rgba(0,0,0,.1) rgba(0,0,0,.1)}@-webkit-keyframes btn-spin{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes btn-spin{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}.zan-btn.zan-btn--disabled{color:#999!important;background:#f8f8f8!important;border-color:#e5e5e5!important;cursor:not-allowed!important;opacity:1!important}.zan-btn.zan-btn--disabled::after{border-color:#e5e5e5!important}.zan-btn--group.zan-btn--last{margin-bottom:0;margin-right:0} -------------------------------------------------------------------------------- /uview-ui/components/u-table/u-table.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 76 | 77 | 85 | --------------------------------------------------------------------------------