Repository: EastWorld/wechat-app-mall Branch: master Commit: 33102d02aa1b Files: 911 Total size: 2.3 MB Directory structure: gitextract_l7xqrqgw/ ├── .gitignore ├── LICENSE ├── README.md ├── app.js ├── app.json ├── app.wxss ├── components/ │ ├── bind-mobile/ │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ ├── index.wxss │ │ └── sn.txt │ ├── date-time-selecter/ │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ ├── index.wxss │ │ └── sn.txt │ ├── fuwuxieyi/ │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ ├── index.wxss │ │ └── sn.txt │ ├── goods-pop/ │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── login/ │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ ├── index.wxss │ │ └── sn.txt │ ├── payment/ │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ ├── index.wxss │ │ └── sn.txt │ └── vip-success/ │ ├── index.js │ ├── index.json │ ├── index.wxml │ └── index.wxss ├── config.js ├── jsconfig.json ├── miniprogram_npm/ │ ├── @vant/ │ │ └── weapp/ │ │ ├── action-sheet/ │ │ │ ├── index.d.ts │ │ │ ├── index.js │ │ │ ├── index.json │ │ │ ├── index.wxml │ │ │ └── index.wxss │ │ ├── area/ │ │ │ ├── index.d.ts │ │ │ ├── index.js │ │ │ ├── index.json │ │ │ ├── index.wxml │ │ │ ├── index.wxs │ │ │ └── index.wxss │ │ ├── button/ │ │ │ ├── index.d.ts │ │ │ ├── index.js │ │ │ ├── index.json │ │ │ ├── index.wxml │ │ │ ├── index.wxs │ │ │ └── index.wxss │ │ ├── calendar/ │ │ │ ├── calendar.wxml │ │ │ ├── components/ │ │ │ │ ├── header/ │ │ │ │ │ ├── index.d.ts │ │ │ │ │ ├── index.js │ │ │ │ │ ├── index.json │ │ │ │ │ ├── index.wxml │ │ │ │ │ └── index.wxss │ │ │ │ └── month/ │ │ │ │ ├── index.d.ts │ │ │ │ ├── index.js │ │ │ │ ├── index.json │ │ │ │ ├── index.wxml │ │ │ │ ├── index.wxs │ │ │ │ └── index.wxss │ │ │ ├── index.d.ts │ │ │ ├── index.js │ │ │ ├── index.json │ │ │ ├── index.wxml │ │ │ ├── index.wxs │ │ │ ├── index.wxss │ │ │ ├── utils.d.ts │ │ │ ├── utils.js │ │ │ └── utils.wxs │ │ ├── card/ │ │ │ ├── index.d.ts │ │ │ ├── index.js │ │ │ ├── index.json │ │ │ ├── index.wxml │ │ │ └── index.wxss │ │ ├── cascader/ │ │ │ ├── index.d.ts │ │ │ ├── index.js │ │ │ ├── index.json │ │ │ ├── index.wxml │ │ │ ├── index.wxs │ │ │ └── index.wxss │ │ ├── cell/ │ │ │ ├── index.d.ts │ │ │ ├── index.js │ │ │ ├── index.json │ │ │ ├── index.wxml │ │ │ ├── index.wxs │ │ │ └── index.wxss │ │ ├── cell-group/ │ │ │ ├── index.d.ts │ │ │ ├── index.js │ │ │ ├── index.json │ │ │ ├── index.wxml │ │ │ └── index.wxss │ │ ├── checkbox/ │ │ │ ├── index.d.ts │ │ │ ├── index.js │ │ │ ├── index.json │ │ │ ├── index.wxml │ │ │ ├── index.wxs │ │ │ └── index.wxss │ │ ├── checkbox-group/ │ │ │ ├── index.d.ts │ │ │ ├── index.js │ │ │ ├── index.json │ │ │ ├── index.wxml │ │ │ └── index.wxss │ │ ├── circle/ │ │ │ ├── canvas.d.ts │ │ │ ├── canvas.js │ │ │ ├── index.d.ts │ │ │ ├── index.js │ │ │ ├── index.json │ │ │ ├── index.wxml │ │ │ └── index.wxss │ │ ├── col/ │ │ │ ├── index.d.ts │ │ │ ├── index.js │ │ │ ├── index.json │ │ │ ├── index.wxml │ │ │ ├── index.wxs │ │ │ └── index.wxss │ │ ├── collapse/ │ │ │ ├── index.d.ts │ │ │ ├── index.js │ │ │ ├── index.json │ │ │ ├── index.wxml │ │ │ └── index.wxss │ │ ├── collapse-item/ │ │ │ ├── animate.d.ts │ │ │ ├── animate.js │ │ │ ├── index.d.ts │ │ │ ├── index.js │ │ │ ├── index.json │ │ │ ├── index.wxml │ │ │ └── index.wxss │ │ ├── common/ │ │ │ ├── color.d.ts │ │ │ ├── color.js │ │ │ ├── component.d.ts │ │ │ ├── component.js │ │ │ ├── index.wxss │ │ │ ├── relation.d.ts │ │ │ ├── relation.js │ │ │ ├── style/ │ │ │ │ ├── clearfix.wxss │ │ │ │ ├── ellipsis.wxss │ │ │ │ ├── hairline.wxss │ │ │ │ ├── mixins/ │ │ │ │ │ ├── clearfix.wxss │ │ │ │ │ ├── ellipsis.wxss │ │ │ │ │ └── hairline.wxss │ │ │ │ └── var.wxss │ │ │ ├── utils.d.ts │ │ │ ├── utils.js │ │ │ ├── validator.d.ts │ │ │ ├── validator.js │ │ │ ├── version.d.ts │ │ │ └── version.js │ │ ├── config-provider/ │ │ │ ├── index.d.ts │ │ │ ├── index.js │ │ │ ├── index.json │ │ │ ├── index.wxml │ │ │ └── index.wxs │ │ ├── count-down/ │ │ │ ├── index.d.ts │ │ │ ├── index.js │ │ │ ├── index.json │ │ │ ├── index.wxml │ │ │ ├── index.wxss │ │ │ ├── utils.d.ts │ │ │ └── utils.js │ │ ├── datetime-picker/ │ │ │ ├── index.d.ts │ │ │ ├── index.js │ │ │ ├── index.json │ │ │ ├── index.wxml │ │ │ └── index.wxss │ │ ├── definitions/ │ │ │ ├── index.d.ts │ │ │ └── index.js │ │ ├── dialog/ │ │ │ ├── dialog.d.ts │ │ │ ├── dialog.js │ │ │ ├── index.d.ts │ │ │ ├── index.js │ │ │ ├── index.json │ │ │ ├── index.wxml │ │ │ └── index.wxss │ │ ├── divider/ │ │ │ ├── index.d.ts │ │ │ ├── index.js │ │ │ ├── index.json │ │ │ ├── index.wxml │ │ │ ├── index.wxs │ │ │ └── index.wxss │ │ ├── dropdown-item/ │ │ │ ├── index.d.ts │ │ │ ├── index.js │ │ │ ├── index.json │ │ │ ├── index.wxml │ │ │ ├── index.wxss │ │ │ ├── shared.d.ts │ │ │ └── shared.js │ │ ├── dropdown-menu/ │ │ │ ├── index.d.ts │ │ │ ├── index.js │ │ │ ├── index.json │ │ │ ├── index.wxml │ │ │ ├── index.wxs │ │ │ └── index.wxss │ │ ├── empty/ │ │ │ ├── index.d.ts │ │ │ ├── index.js │ │ │ ├── index.json │ │ │ ├── index.wxml │ │ │ ├── index.wxs │ │ │ └── index.wxss │ │ ├── field/ │ │ │ ├── index.d.ts │ │ │ ├── index.js │ │ │ ├── index.json │ │ │ ├── index.wxml │ │ │ ├── index.wxs │ │ │ ├── index.wxss │ │ │ ├── input.wxml │ │ │ ├── props.d.ts │ │ │ ├── props.js │ │ │ ├── textarea.wxml │ │ │ ├── types.d.ts │ │ │ └── types.js │ │ ├── goods-action/ │ │ │ ├── index.d.ts │ │ │ ├── index.js │ │ │ ├── index.json │ │ │ ├── index.wxml │ │ │ └── index.wxss │ │ ├── goods-action-button/ │ │ │ ├── index.d.ts │ │ │ ├── index.js │ │ │ ├── index.json │ │ │ ├── index.wxml │ │ │ └── index.wxss │ │ ├── goods-action-icon/ │ │ │ ├── index.d.ts │ │ │ ├── index.js │ │ │ ├── index.json │ │ │ ├── index.wxml │ │ │ └── index.wxss │ │ ├── grid/ │ │ │ ├── index.d.ts │ │ │ ├── index.js │ │ │ ├── index.json │ │ │ ├── index.wxml │ │ │ ├── index.wxs │ │ │ └── index.wxss │ │ ├── grid-item/ │ │ │ ├── index.d.ts │ │ │ ├── index.js │ │ │ ├── index.json │ │ │ ├── index.wxml │ │ │ ├── index.wxs │ │ │ └── index.wxss │ │ ├── icon/ │ │ │ ├── index.d.ts │ │ │ ├── index.js │ │ │ ├── index.json │ │ │ ├── index.wxml │ │ │ ├── index.wxs │ │ │ └── index.wxss │ │ ├── image/ │ │ │ ├── index.d.ts │ │ │ ├── index.js │ │ │ ├── index.json │ │ │ ├── index.wxml │ │ │ ├── index.wxs │ │ │ └── index.wxss │ │ ├── index-anchor/ │ │ │ ├── index.d.ts │ │ │ ├── index.js │ │ │ ├── index.json │ │ │ ├── index.wxml │ │ │ └── index.wxss │ │ ├── index-bar/ │ │ │ ├── index.d.ts │ │ │ ├── index.js │ │ │ ├── index.json │ │ │ ├── index.wxml │ │ │ └── index.wxss │ │ ├── info/ │ │ │ ├── index.d.ts │ │ │ ├── index.js │ │ │ ├── index.json │ │ │ ├── index.wxml │ │ │ └── index.wxss │ │ ├── loading/ │ │ │ ├── index.d.ts │ │ │ ├── index.js │ │ │ ├── index.json │ │ │ ├── index.wxml │ │ │ ├── index.wxs │ │ │ └── index.wxss │ │ ├── mixins/ │ │ │ ├── basic.d.ts │ │ │ ├── basic.js │ │ │ ├── button.d.ts │ │ │ ├── button.js │ │ │ ├── link.d.ts │ │ │ ├── link.js │ │ │ ├── page-scroll.d.ts │ │ │ ├── page-scroll.js │ │ │ ├── touch.d.ts │ │ │ ├── touch.js │ │ │ ├── transition.d.ts │ │ │ └── transition.js │ │ ├── nav-bar/ │ │ │ ├── index.d.ts │ │ │ ├── index.js │ │ │ ├── index.json │ │ │ ├── index.wxml │ │ │ ├── index.wxs │ │ │ └── index.wxss │ │ ├── notice-bar/ │ │ │ ├── index.d.ts │ │ │ ├── index.js │ │ │ ├── index.json │ │ │ ├── index.wxml │ │ │ ├── index.wxs │ │ │ └── index.wxss │ │ ├── notify/ │ │ │ ├── index.d.ts │ │ │ ├── index.js │ │ │ ├── index.json │ │ │ ├── index.wxml │ │ │ ├── index.wxs │ │ │ ├── index.wxss │ │ │ ├── notify.d.ts │ │ │ └── notify.js │ │ ├── overlay/ │ │ │ ├── index.d.ts │ │ │ ├── index.js │ │ │ ├── index.json │ │ │ ├── index.wxml │ │ │ ├── index.wxss │ │ │ └── overlay.wxml │ │ ├── panel/ │ │ │ ├── index.d.ts │ │ │ ├── index.js │ │ │ ├── index.json │ │ │ ├── index.wxml │ │ │ └── index.wxss │ │ ├── picker/ │ │ │ ├── index.d.ts │ │ │ ├── index.js │ │ │ ├── index.json │ │ │ ├── index.wxml │ │ │ ├── index.wxs │ │ │ ├── index.wxss │ │ │ ├── shared.d.ts │ │ │ ├── shared.js │ │ │ └── toolbar.wxml │ │ ├── picker-column/ │ │ │ ├── index.d.ts │ │ │ ├── index.js │ │ │ ├── index.json │ │ │ ├── index.wxml │ │ │ ├── index.wxs │ │ │ └── index.wxss │ │ ├── popup/ │ │ │ ├── index.d.ts │ │ │ ├── index.js │ │ │ ├── index.json │ │ │ ├── index.wxml │ │ │ ├── index.wxs │ │ │ ├── index.wxss │ │ │ └── popup.wxml │ │ ├── progress/ │ │ │ ├── index.d.ts │ │ │ ├── index.js │ │ │ ├── index.json │ │ │ ├── index.wxml │ │ │ ├── index.wxs │ │ │ └── index.wxss │ │ ├── radio/ │ │ │ ├── index.d.ts │ │ │ ├── index.js │ │ │ ├── index.json │ │ │ ├── index.wxml │ │ │ ├── index.wxs │ │ │ └── index.wxss │ │ ├── radio-group/ │ │ │ ├── index.d.ts │ │ │ ├── index.js │ │ │ ├── index.json │ │ │ ├── index.wxml │ │ │ └── index.wxss │ │ ├── rate/ │ │ │ ├── index.d.ts │ │ │ ├── index.js │ │ │ ├── index.json │ │ │ ├── index.wxml │ │ │ └── index.wxss │ │ ├── row/ │ │ │ ├── index.d.ts │ │ │ ├── index.js │ │ │ ├── index.json │ │ │ ├── index.wxml │ │ │ ├── index.wxs │ │ │ └── index.wxss │ │ ├── search/ │ │ │ ├── index.d.ts │ │ │ ├── index.js │ │ │ ├── index.json │ │ │ ├── index.wxml │ │ │ └── index.wxss │ │ ├── share-sheet/ │ │ │ ├── index.d.ts │ │ │ ├── index.js │ │ │ ├── index.json │ │ │ ├── index.wxml │ │ │ ├── index.wxs │ │ │ ├── index.wxss │ │ │ ├── options.d.ts │ │ │ ├── options.js │ │ │ ├── options.json │ │ │ ├── options.wxml │ │ │ ├── options.wxs │ │ │ └── options.wxss │ │ ├── sidebar/ │ │ │ ├── index.d.ts │ │ │ ├── index.js │ │ │ ├── index.json │ │ │ ├── index.wxml │ │ │ └── index.wxss │ │ ├── sidebar-item/ │ │ │ ├── index.d.ts │ │ │ ├── index.js │ │ │ ├── index.json │ │ │ ├── index.wxml │ │ │ └── index.wxss │ │ ├── skeleton/ │ │ │ ├── index.d.ts │ │ │ ├── index.js │ │ │ ├── index.json │ │ │ ├── index.wxml │ │ │ └── index.wxss │ │ ├── slider/ │ │ │ ├── index.d.ts │ │ │ ├── index.js │ │ │ ├── index.json │ │ │ ├── index.wxml │ │ │ ├── index.wxs │ │ │ └── index.wxss │ │ ├── stepper/ │ │ │ ├── index.d.ts │ │ │ ├── index.js │ │ │ ├── index.json │ │ │ ├── index.wxml │ │ │ ├── index.wxs │ │ │ └── index.wxss │ │ ├── steps/ │ │ │ ├── index.d.ts │ │ │ ├── index.js │ │ │ ├── index.json │ │ │ ├── index.wxml │ │ │ └── index.wxss │ │ ├── sticky/ │ │ │ ├── index.d.ts │ │ │ ├── index.js │ │ │ ├── index.json │ │ │ ├── index.wxml │ │ │ ├── index.wxs │ │ │ └── index.wxss │ │ ├── submit-bar/ │ │ │ ├── index.d.ts │ │ │ ├── index.js │ │ │ ├── index.json │ │ │ ├── index.wxml │ │ │ └── index.wxss │ │ ├── swipe-cell/ │ │ │ ├── index.d.ts │ │ │ ├── index.js │ │ │ ├── index.json │ │ │ ├── index.wxml │ │ │ └── index.wxss │ │ ├── switch/ │ │ │ ├── index.d.ts │ │ │ ├── index.js │ │ │ ├── index.json │ │ │ ├── index.wxml │ │ │ ├── index.wxs │ │ │ └── index.wxss │ │ ├── tab/ │ │ │ ├── index.d.ts │ │ │ ├── index.js │ │ │ ├── index.json │ │ │ ├── index.wxml │ │ │ └── index.wxss │ │ ├── tabbar/ │ │ │ ├── index.d.ts │ │ │ ├── index.js │ │ │ ├── index.json │ │ │ ├── index.wxml │ │ │ └── index.wxss │ │ ├── tabbar-item/ │ │ │ ├── index.d.ts │ │ │ ├── index.js │ │ │ ├── index.json │ │ │ ├── index.wxml │ │ │ └── index.wxss │ │ ├── tabs/ │ │ │ ├── index.d.ts │ │ │ ├── index.js │ │ │ ├── index.json │ │ │ ├── index.wxml │ │ │ ├── index.wxs │ │ │ └── index.wxss │ │ ├── tag/ │ │ │ ├── index.d.ts │ │ │ ├── index.js │ │ │ ├── index.json │ │ │ ├── index.wxml │ │ │ ├── index.wxs │ │ │ └── index.wxss │ │ ├── toast/ │ │ │ ├── index.d.ts │ │ │ ├── index.js │ │ │ ├── index.json │ │ │ ├── index.wxml │ │ │ ├── index.wxss │ │ │ ├── toast.d.ts │ │ │ └── toast.js │ │ ├── transition/ │ │ │ ├── index.d.ts │ │ │ ├── index.js │ │ │ ├── index.json │ │ │ ├── index.wxml │ │ │ ├── index.wxs │ │ │ └── index.wxss │ │ ├── tree-select/ │ │ │ ├── index.d.ts │ │ │ ├── index.js │ │ │ ├── index.json │ │ │ ├── index.wxml │ │ │ ├── index.wxs │ │ │ └── index.wxss │ │ ├── uploader/ │ │ │ ├── index.d.ts │ │ │ ├── index.js │ │ │ ├── index.json │ │ │ ├── index.wxml │ │ │ ├── index.wxs │ │ │ ├── index.wxss │ │ │ ├── shared.d.ts │ │ │ ├── shared.js │ │ │ ├── utils.d.ts │ │ │ └── utils.js │ │ └── wxs/ │ │ ├── add-unit.wxs │ │ ├── array.wxs │ │ ├── bem.wxs │ │ ├── memoize.wxs │ │ ├── object.wxs │ │ ├── style.wxs │ │ └── utils.wxs │ ├── apifm-wxapi/ │ │ └── index.js │ ├── dayjs/ │ │ └── index.js │ ├── mp-html/ │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ ├── index.wxss │ │ ├── node/ │ │ │ ├── node.js │ │ │ ├── node.json │ │ │ ├── node.wxml │ │ │ └── node.wxss │ │ └── parser.js │ ├── wxa-plugin-canvas/ │ │ ├── index/ │ │ │ ├── index.js │ │ │ ├── index.json │ │ │ ├── index.wxml │ │ │ └── index.wxss │ │ └── poster/ │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ ├── index.wxss │ │ └── poster.js │ └── wxbarcode/ │ └── index.js ├── package.json ├── packageCps/ │ └── pages/ │ ├── goods-details/ │ │ ├── cps-jd.js │ │ ├── cps-jd.json │ │ ├── cps-jd.wxml │ │ ├── cps-jd.wxss │ │ ├── cps-pdd.js │ │ ├── cps-pdd.json │ │ ├── cps-pdd.wxml │ │ ├── cps-pdd.wxss │ │ ├── cps-taobao.js │ │ ├── cps-taobao.json │ │ ├── cps-taobao.wxml │ │ └── cps-taobao.wxss │ └── order-list/ │ ├── cps.js │ ├── cps.json │ ├── cps.wxml │ └── cps.wxss ├── packageFx/ │ └── pages/ │ ├── apply/ │ │ ├── form.js │ │ ├── form.json │ │ ├── form.wxml │ │ ├── form.wxss │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── commisionLog/ │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── hehuorenfenxiao/ │ │ ├── fxmember.js │ │ ├── fxmember.json │ │ ├── fxmember.wxml │ │ ├── fxmember.wxss │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── index/ │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── myusers/ │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ ├── index.wxss │ │ ├── myusers-detail.js │ │ ├── myusers-detail.json │ │ ├── myusers-detail.wxml │ │ └── myusers-detail.wxss │ └── report/ │ ├── city.js │ ├── city.json │ ├── city.wxml │ ├── city.wxss │ ├── team.js │ ├── team.json │ ├── team.wxml │ └── team.wxss ├── packageStreamMedia/ │ ├── components/ │ │ ├── TRTCCalling/ │ │ │ ├── TRTCCalling.js │ │ │ ├── TRTCCalling.json │ │ │ ├── TRTCCalling.wxml │ │ │ ├── TRTCCalling.wxss │ │ │ ├── common/ │ │ │ │ └── constants.js │ │ │ ├── controller/ │ │ │ │ └── user-controller.js │ │ │ ├── libs/ │ │ │ │ └── mta_analysis.js │ │ │ ├── model/ │ │ │ │ ├── stream.js │ │ │ │ └── user.js │ │ │ ├── template/ │ │ │ │ ├── audio-template/ │ │ │ │ │ ├── audio-template.wxml │ │ │ │ │ └── audio-template.wxss │ │ │ │ └── video-template/ │ │ │ │ ├── video-template.wxml │ │ │ │ └── video-template.wxss │ │ │ └── utils/ │ │ │ ├── compare-version.js │ │ │ ├── environment.js │ │ │ ├── event.js │ │ │ └── tsignaling-wx.js │ │ └── like-dz/ │ │ ├── like-dz.js │ │ ├── like-dz.json │ │ ├── like-dz.wxml │ │ └── like-dz.wxss │ └── pages/ │ ├── live-anchor/ │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ ├── index.wxss │ │ ├── list.js │ │ ├── list.json │ │ ├── list.wxml │ │ └── list.wxss │ ├── live-client/ │ │ ├── client.js │ │ ├── client.json │ │ ├── client.wxml │ │ ├── client.wxss │ │ ├── list.js │ │ ├── list.json │ │ ├── list.wxml │ │ └── list.wxss │ └── videoCall/ │ ├── videoCall.js │ ├── videoCall.json │ ├── videoCall.wxml │ └── videoCall.wxss ├── pages/ │ ├── about/ │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── address-add/ │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── asset/ │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── card/ │ │ ├── logs.js │ │ ├── logs.json │ │ ├── logs.wxml │ │ └── logs.wxss │ ├── category/ │ │ ├── category.js │ │ ├── category.json │ │ ├── category.wxml │ │ └── category.wxss │ ├── cms/ │ │ ├── list.js │ │ ├── list.json │ │ ├── list.wxml │ │ └── list.wxss │ ├── coupons/ │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ ├── index.wxss │ │ ├── merge.js │ │ ├── merge.json │ │ ├── merge.wxml │ │ └── merge.wxss │ ├── deposit/ │ │ ├── pay.js │ │ ├── pay.json │ │ ├── pay.wxml │ │ └── pay.wxss │ ├── goods/ │ │ ├── fav.js │ │ ├── fav.json │ │ ├── fav.wxml │ │ ├── fav.wxss │ │ ├── his.js │ │ ├── his.json │ │ ├── his.wxml │ │ ├── his.wxss │ │ ├── list-vop.js │ │ ├── list-vop.json │ │ ├── list-vop.wxml │ │ ├── list-vop.wxss │ │ ├── list.js │ │ ├── list.json │ │ ├── list.wxml │ │ └── list.wxss │ ├── goods-details/ │ │ ├── day.js │ │ ├── day.json │ │ ├── day.wxml │ │ ├── day.wxss │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ ├── index.wxss │ │ ├── times01.js │ │ ├── times01.json │ │ ├── times01.wxml │ │ ├── times01.wxss │ │ ├── times02.js │ │ ├── times02.json │ │ ├── times02.wxml │ │ ├── times02.wxss │ │ ├── vop.js │ │ ├── vop.json │ │ ├── vop.wxml │ │ └── vop.wxss │ ├── help/ │ │ ├── detail.js │ │ ├── detail.json │ │ ├── detail.wxml │ │ ├── detail.wxss │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── idCheck/ │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── index/ │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── invoice/ │ │ ├── apply.js │ │ ├── apply.json │ │ ├── apply.wxml │ │ ├── apply.wxss │ │ ├── list.js │ │ ├── list.json │ │ ├── list.wxml │ │ └── list.wxss │ ├── live/ │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── login/ │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── maidan/ │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── my/ │ │ ├── feedback.js │ │ ├── feedback.json │ │ ├── feedback.wxml │ │ ├── feedback.wxss │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ ├── index.wxss │ │ ├── info-menu.js │ │ ├── info-menu.json │ │ ├── info-menu.wxml │ │ ├── info-menu.wxss │ │ ├── info.js │ │ ├── info.json │ │ ├── info.wxml │ │ ├── info.wxss │ │ ├── setting.js │ │ ├── setting.json │ │ ├── setting.wxml │ │ ├── setting.wxss │ │ ├── user-code.js │ │ ├── user-code.json │ │ ├── user-code.wxml │ │ └── user-code.wxss │ ├── notagree/ │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── notice/ │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ ├── index.wxss │ │ ├── show.js │ │ ├── show.json │ │ ├── show.wxml │ │ └── show.wxss │ ├── order/ │ │ ├── refundApply.js │ │ ├── refundApply.json │ │ ├── refundApply.wxml │ │ └── refundApply.wxss │ ├── order-details/ │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ ├── index.wxss │ │ ├── scan-result.js │ │ ├── scan-result.json │ │ ├── scan-result.wxml │ │ └── scan-result.wxss │ ├── order-list/ │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── peisong/ │ │ ├── detail.js │ │ ├── detail.json │ │ ├── detail.wxml │ │ ├── detail.wxss │ │ ├── orders.js │ │ ├── orders.json │ │ ├── orders.wxml │ │ ├── orders.wxss │ │ ├── statistics.js │ │ ├── statistics.json │ │ ├── statistics.wxml │ │ └── statistics.wxss │ ├── pwd-pay/ │ │ ├── modify.js │ │ ├── modify.json │ │ ├── modify.wxml │ │ ├── modify.wxss │ │ ├── reset.js │ │ ├── reset.json │ │ ├── reset.wxml │ │ ├── reset.wxss │ │ ├── set.js │ │ ├── set.json │ │ ├── set.wxml │ │ └── set.wxss │ ├── raffle/ │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── recharge/ │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── recycle/ │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ ├── index.wxss │ │ ├── order-detail.js │ │ ├── order-detail.json │ │ ├── order-detail.wxml │ │ ├── order-detail.wxss │ │ ├── orders.js │ │ ├── orders.json │ │ ├── orders.wxml │ │ └── orders.wxss │ ├── score/ │ │ ├── growth.js │ │ ├── growth.json │ │ ├── growth.wxml │ │ ├── growth.wxss │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── score-excharge/ │ │ ├── growth.js │ │ ├── growth.json │ │ ├── growth.wxml │ │ ├── growth.wxss │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── search/ │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── select-address/ │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── shop/ │ │ ├── select.js │ │ ├── select.json │ │ ├── select.wxml │ │ └── select.wxss │ ├── shop-cart/ │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── sign/ │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── start/ │ │ ├── start.js │ │ ├── start.json │ │ ├── start.wxml │ │ └── start.wxss │ ├── template-cart/ │ │ ├── template-cart.js │ │ ├── template-cart.wxml │ │ └── template-cart.wxss │ ├── test/ │ │ ├── wifi.js │ │ ├── wifi.json │ │ ├── wifi.wxml │ │ └── wifi.wxss │ ├── to-pay-order/ │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── vip/ │ │ ├── detail.js │ │ ├── detail.json │ │ ├── detail.wxml │ │ ├── detail.wxss │ │ ├── history.js │ │ ├── history.json │ │ ├── history.wxml │ │ ├── history.wxss │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── withdraw/ │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ └── wuliu/ │ ├── index.js │ ├── index.json │ ├── index.wxml │ └── index.wxss ├── project.config.json ├── project.private.config.json ├── sitemap.json ├── typings/ │ └── wx.d.ts └── utils/ ├── address_parse.js ├── auth.js ├── image.js ├── pay.js ├── tools.js └── tools.wxs ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ dist/ package-lock.json node_modules/ .DS_Store ================================================ FILE: LICENSE ================================================ Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "{}" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright {yyyy} {name of copyright owner} Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ================================================ FILE: README.md ================================================ # 微信小程序商城 微信小程序商城,微信小程序微店,长期维护版本,欢迎大家踊跃提交贡献代码; 使用说明和常见问题,可参阅下面的说明,如还有疑问,可访问工厂官网 [https://www.it120.cc/](https://www.it120.cc/) 寻求帮助! 新增直播带货支持,具体详见使用说明 # 今日头条/抖音小程序版本 本项目的今日头条/抖音小程序版本,请移步至下面的地址: [https://github.com/EastWorld/tt-app-mall](https://github.com/EastWorld/tt-app-mall) ## 扫码体验 ## 详细配置/使用教程 [https://www.it120.cc/help/ikfe2k.html](https://www.it120.cc/help/ikfe2k.html) **遇到使用问题?** [点击这里找答案,可用关键词搜索](https://www.it120.cc/help/index.html) ## 其他优秀开源模板推荐 - [天使童装](https://github.com/EastWorld/wechat-app-mall) / [码云镜像](https://gitee.com/javazj/wechat-app-mall) / [GitCode镜像](https://gitcode.com/gooking2/wechat-app-mall) - [天使童装(uni-app版本)](https://github.com/gooking/uni-app-mall) / [码云镜像](https://gitee.com/javazj/uni-app-mall) / [GitCode镜像](https://gitcode.com/gooking2/uni-app-mall) - [简约精品商城(uni-app版本)](https://github.com/gooking/uni-app--mini-mall) / [码云镜像](https://gitee.com/javazj/uni-app--mini-mall) / [GitCode镜像](https://gitcode.com/gooking2/uni-app--mini-mall) - [舔果果小铺(升级版)](https://github.com/gooking/TianguoguoXiaopu) - [面馆风格小程序](https://gitee.com/javazj/noodle_shop_procedures) - [AI名片](https://github.com/gooking/visitingCard) / [码云镜像](https://gitee.com/javazj/visitingCard) / [GitCode镜像](https://gitcode.com/gooking2/visitingCard) - [仿海底捞订座排队 (uni-app)](https://github.com/gooking/dingzuopaidui) / [码云镜像](https://gitee.com/javazj/dingzuopaidui) / [GitCode镜像](https://gitcode.com/gooking2/dingzuopaidui) - [H5版本商城/餐饮](https://github.com/gooking/vueMinishop) / [码云镜像](https://gitee.com/javazj/vueMinishop) / [GitCode镜像](https://gitcode.com/gooking2/vueMinishop) - [餐饮点餐](https://github.com/woniudiancang/bee) / [码云镜像](https://gitee.com/woniudiancang/bee) / [GitCode镜像](https://gitcode.com/gooking2/bee) - [企业微展](https://github.com/gooking/qiyeweizan) / [码云镜像](https://gitee.com/javazj/qiyeweizan) / [GitCode镜像](https://gitcode.com/gooking2/qiyeweizan) - [无人棋牌室](https://github.com/gooking/wurenqipai) / [码云镜像](https://gitee.com/javazj/wurenqipai) / [GitCode镜像](https://gitcode.com/gooking2/wurenqipai) - [酒店客房服务小程序](https://github.com/gooking/hotelRoomService) / [码云镜像](https://gitee.com/javazj/hotelRoomService) / [GitCode镜像](https://gitcode.com/gooking2/hotelRoomService) - [面包店风格小程序](https://github.com/gooking/bread) / [码云镜像](https://gitee.com/javazj/bread) / [GitCode镜像](https://gitcode.com/gooking2/bread) - [朋友圈发圈素材小程序](https://github.com/gooking/moments) / [码云镜像](https://gitee.com/javazj/moments) / [GitCode镜像](https://gitcode.com/gooking2/moments) - [小红书企业微展](https://github.com/gooking/xhs-qiyeweizan) / [码云镜像](https://gitee.com/javazj/xhs-qiyeweizan) / [GitCode镜像](https://gitcode.com/gooking2/xhs-qiyeweizan) - [旧物回收、废品回收](https://github.com/gooking/recycle) / [码云镜像](https://gitee.com/javazj/recycle) / [GitCode镜像](https://gitcode.com/gooking2/recycle) - [会员卡(饭卡)储值消费系统](https://github.com/gooking/mealcard) / [码云镜像](https://gitee.com/javazj/mealcard) / [GitCode镜像](https://gitcode.com/gooking2/mealcard) ## 联系作者 | 微信好友 | QQ好友 | | :------: | :------: | | | | ## 本项目使用了下面的组件,在此鸣谢 - [接口 SDK](https://github.com/gooking/apifm-wxapi) - [api工厂](https://admin.s2m.cc) - [vant-weapp](https://youzan.github.io/vant-weapp) - [小程序富文本插件(html 渲染)](https://github.com/jin-yufeng/mp-html) - [小程序海报组件-生成朋友圈分享海报并生成图片](https://github.com/jasondu/wxa-plugin-canvas) - [Apache ECharts](https://github.com/ecomfe/echarts-for-weixin) 底部ICON图标使用: https://www.iconfont.cn/collections/detail?spm=a313x.7781069.0.da5a778a4&cid=18904 ## 如何升级到最新版 - 小程序程序的修改和您后台的数据是独立的,所以不用担心您会丢失数据 - 先把你开发工具下的现有版本程序备份 - 下载最新版的程序,直接覆盖您本地的程序 - 用开发工具修改域名 mall 为你自己的域名 - 开发工具里面上传代码提交微信审核 - 审核通过后,小程序后台去发布新版本即可 - 用户无需重新扫码,关闭小程序重新打开就是新版本了 ================================================ FILE: app.js ================================================ const WXAPI = require('apifm-wxapi') const CONFIG = require('config.js') const AUTH = require('utils/auth') App({ onLaunch: function() { const subDomain = wx.getExtConfigSync().subDomain if (subDomain) { WXAPI.init(subDomain) } else { WXAPI.init(CONFIG.subDomain) WXAPI.setMerchantId(CONFIG.merchantId) } const that = this; // 检测新版本 const updateManager = wx.getUpdateManager() updateManager.onUpdateReady(function () { wx.showModal({ title: '更新提示', content: '新版本已经准备好,是否重启应用?', success(res) { if (res.confirm) { // 新的版本已经下载好,调用 applyUpdate 应用新版本并重启 updateManager.applyUpdate() } } }) }) /** * 初次加载判断网络情况 * 无网络状态下根据实际情况进行调整 */ wx.getNetworkType({ success(res) { const networkType = res.networkType if (networkType === 'none') { that.globalData.isConnected = false wx.showToast({ title: '当前无网络', icon: 'loading', duration: 2000 }) } } }); /** * 监听网络状态变化 * 可根据业务需求进行调整 */ wx.onNetworkStatusChange(function(res) { if (!res.isConnected) { that.globalData.isConnected = false wx.showToast({ title: '网络已断开', icon: 'loading', duration: 2000 }) } else { that.globalData.isConnected = true wx.hideToast() } }) WXAPI.queryConfigBatch('mallName,WITHDRAW_MIN,ALLOW_SELF_COLLECTION,order_hx_uids,subscribe_ids,share_profile,adminUserIds,goodsDetailSkuShowType,shopMod,needIdCheck,balance_pay_pwd,shipping_address_gps,shipping_address_region_level,shopping_cart_vop_open,cps_open,recycle_open,categoryMod,hide_reputation,show_seller_number,show_goods_echarts,show_buy_dynamic,goods_search_show_type,show_3_seller,show_quan_exchange_score,show_score_exchange_growth,show_score_sign,fx_subscribe_ids,share_pic,orderPeriod_open,order_pay_user_balance,wxpay_api_url,sphpay_open,fx_type,invoice_subscribe_ids,zt_open_hx,withdrawal,customerServiceChatCorpId,customerServiceChatUrl,invoice_open,alipay,comment_subscribe_ids,notice_subscribe_ids,hidden_goods_index,create_order_ext,needBindMobile,invoice_share_pic,hot_search_words').then(res => { if (res.code == 0) { res.data.forEach(config => { wx.setStorageSync(config.key, config.value) }) if (this.configLoadOK) { this.configLoadOK() } // wx.setStorageSync('shopMod', '1') // 测试用,不要取消注释 } }) // ---------------检测navbar高度 let menuButtonObject = wx.getMenuButtonBoundingClientRect(); console.log("小程序胶囊信息",menuButtonObject) wx.getSystemInfo({ success: res => { let statusBarHeight = res.statusBarHeight, navTop = menuButtonObject.top,//胶囊按钮与顶部的距离 navHeight = statusBarHeight + menuButtonObject.height + (menuButtonObject.top - statusBarHeight)*2;//导航高度 this.globalData.navHeight = navHeight; this.globalData.navTop = navTop; this.globalData.windowHeight = res.windowHeight; this.globalData.menuButtonObject = menuButtonObject; console.log("navHeight",navHeight); }, fail(err) { console.log(err); } }) }, onShow (e) { // 保存邀请人 if (e && e.query && e.query.inviter_id) { wx.setStorageSync('referrer', e.query.inviter_id) if (e.shareTicket) { wx.getShareInfo({ shareTicket: e.shareTicket, success: res => { wx.login({ success(loginRes) { if (loginRes.code) { WXAPI.shareGroupGetScore( loginRes.code, e.query.inviter_id, res.encryptedData, res.iv ).then(_res => { console.log(_res) }).catch(err => { console.error(err) }) } else { console.error('登录失败!' + loginRes.errMsg) } } }) } }) } } // 自动登录 AUTH.checkHasLogined().then(isLogined => { if (!isLogined) { // 未登录 if (CONFIG.openIdAutoRegister) { // 进行登陆,用户不存在则注册 AUTH.authorize().then( aaa => { if (CONFIG.bindSeller) { AUTH.bindSeller() } this.getUserApiInfo().then(() => { if (this.loginOK) { this.loginOK() } }) }) } else { // 只是登陆 AUTH.login20241025().then( res => { if (res.code == 0) { // 登陆成功 if (CONFIG.bindSeller) { AUTH.bindSeller() } this.getUserApiInfo().then(() => { if (this.loginOK) { this.loginOK() } }) } else { // 用户没注册 if (this.loginFail) { this.loginFail() } } }) } } else { // 已登录 if (CONFIG.bindSeller) { AUTH.bindSeller() } this.getUserApiInfo() } }) }, async getUserApiInfo() { const res = await WXAPI.userDetail(wx.getStorageSync('token')) if (res.code == 0) { this.globalData.apiUserInfoMap = res.data } }, initNickAvatarUrlPOP(_this) { setTimeout(() => { if (this.globalData.apiUserInfoMap && (!this.globalData.apiUserInfoMap.base.nick || !this.globalData.apiUserInfoMap.base.avatarUrl)) { _this.setData({ nickPopShow: true, popnick: this.globalData.apiUserInfoMap.base.nick ? this.globalData.apiUserInfoMap.base.nick : '', popavatarUrl: this.globalData.apiUserInfoMap.base.avatarUrl ? this.globalData.apiUserInfoMap.base.avatarUrl : '', }) } }, 3000) // 3秒后弹出 }, globalData: { isConnected: true, sdkAppID: CONFIG.sdkAppID, apiUserInfoMap: undefined, // 当前登陆用户信息: base/ext/idcard/saleDistributionTeam } }) ================================================ FILE: app.json ================================================ { "pages": [ "pages/start/start", "pages/test/wifi", "pages/shop/select", "pages/index/index", "pages/notice/index", "pages/notice/show", "pages/category/category", "pages/goods/list", "pages/goods/list-vop", "pages/goods/fav", "pages/goods/his", "pages/goods-details/index", "pages/goods-details/vop", "pages/goods-details/day", "pages/goods-details/times01", "pages/goods-details/times02", "pages/shop-cart/index", "pages/to-pay-order/index", "pages/select-address/index", "pages/address-add/index", "pages/order-list/index", "pages/order-details/index", "pages/order-details/scan-result", "pages/order/refundApply", "pages/wuliu/index", "pages/my/index", "pages/withdraw/index", "pages/score-excharge/index", "pages/score-excharge/growth", "pages/asset/index", "pages/recharge/index", "pages/score/index", "pages/score/growth", "pages/sign/index", "pages/maidan/index", "pages/coupons/index", "pages/coupons/merge", "pages/invoice/list", "pages/invoice/apply", "pages/deposit/pay", "pages/live/index", "pages/help/detail", "pages/help/index", "pages/cms/list", "pages/about/index", "pages/idCheck/index", "pages/peisong/detail", "pages/peisong/orders", "pages/peisong/statistics", "pages/pwd-pay/reset", "pages/pwd-pay/modify", "pages/pwd-pay/set", "pages/my/feedback", "pages/search/index", "pages/my/info", "pages/my/setting", "pages/my/info-menu", "pages/recycle/index", "pages/recycle/orders", "pages/recycle/order-detail", "pages/card/logs", "pages/notagree/index", "pages/my/user-code", "pages/raffle/index", "pages/login/index", "pages/vip/index", "pages/vip/detail", "pages/vip/history" ], "requiredPrivateInfos": [ "getLocation", "chooseAddress", "chooseLocation" ], "subpackages": [ { "root": "packageStreamMedia", "name": "packageStreamMedia", "pages": [ "pages/videoCall/videoCall", "pages/live-anchor/index", "pages/live-anchor/list", "pages/live-client/list", "pages/live-client/client" ] }, { "root": "packageCps", "name": "packageCps", "pages": [ "pages/goods-details/cps-jd", "pages/goods-details/cps-pdd", "pages/goods-details/cps-taobao", "pages/order-list/cps" ] }, { "root": "packageFx", "name": "packageFx", "pages": [ "pages/index/index", "pages/hehuorenfenxiao/index", "pages/hehuorenfenxiao/fxmember", "pages/apply/index", "pages/apply/form", "pages/myusers/index", "pages/commisionLog/index", "pages/report/team", "pages/report/city", "pages/myusers/myusers-detail" ] } ], "window": { "backgroundTextStyle": "light", "navigationBarBackgroundColor": "#fff", "navigationBarTitleText": "", "navigationBarTextStyle": "black", "onReachBottomDistance": 50 }, "tabBar": { "color": "#6e6d6b", "selectedColor": "#e64340", "borderStyle": "white", "backgroundColor": "#fff", "list": [ { "pagePath": "pages/index/index", "iconPath": "images/nav/home-off.png", "selectedIconPath": "images/nav/home-on.png", "text": "首页" }, { "pagePath": "pages/category/category", "iconPath": "images/nav/fl-off.png", "selectedIconPath": "images/nav/fl-on.png", "text": "分类" }, { "pagePath": "pages/coupons/index", "iconPath": "images/nav/coupon-off.png", "selectedIconPath": "images/nav/coupon-on.png", "text": "优惠券" }, { "pagePath": "pages/shop-cart/index", "iconPath": "images/nav/cart-off.png", "selectedIconPath": "images/nav/cart-on.png", "text": "购物车" }, { "pagePath": "pages/my/index", "iconPath": "images/nav/my-off.png", "selectedIconPath": "images/nav/my-on.png", "text": "我的" } ] }, "permission": { "scope.userLocation": { "desc": "获取离你最近的门店" } }, "usingComponents": { "fuwuxieyi": "/components/fuwuxieyi/index", "goods-pop": "/components/goods-pop/index", "login": "/components/login/index", "bind-mobile": "/components/bind-mobile/index", "payment": "/components/payment/index", "mp-html": "mp-html", "van-notice-bar": "@vant/weapp/notice-bar/index", "van-search": "@vant/weapp/search/index", "van-divider": "@vant/weapp/divider/index", "van-icon": "@vant/weapp/icon/index", "van-count-down": "@vant/weapp/count-down/index", "van-button": "@vant/weapp/button/index", "van-cell": "@vant/weapp/cell/index", "van-cell-group": "@vant/weapp/cell-group/index", "van-tag": "@vant/weapp/tag/index", "van-card": "@vant/weapp/card/index", "van-progress": "@vant/weapp/progress/index", "van-submit-bar": "@vant/weapp/submit-bar/index", "van-field": "@vant/weapp/field/index", "van-radio": "@vant/weapp/radio/index", "van-radio-group": "@vant/weapp/radio-group/index", "van-sidebar": "@vant/weapp/sidebar/index", "van-sidebar-item": "@vant/weapp/sidebar-item/index", "van-empty": "@vant/weapp/empty/index", "van-goods-action": "@vant/weapp/goods-action/index", "van-goods-action-icon": "@vant/weapp/goods-action-icon/index", "van-goods-action-button": "@vant/weapp/goods-action-button/index", "van-popup": "@vant/weapp/popup/index", "van-picker": "@vant/weapp/picker/index", "van-stepper": "@vant/weapp/stepper/index", "van-sticky": "@vant/weapp/sticky/index", "van-dialog": "@vant/weapp/dialog/index", "van-swipe-cell": "@vant/weapp/swipe-cell/index", "van-calendar": "@vant/weapp/calendar/index", "van-switch": "@vant/weapp/switch/index", "van-rate": "@vant/weapp/rate/index", "van-uploader": "@vant/weapp/uploader/index", "van-grid": "@vant/weapp/grid/index", "van-grid-item": "@vant/weapp/grid-item/index", "van-image": "@vant/weapp/image/index", "van-tab": "@vant/weapp/tab/index", "van-tabs": "@vant/weapp/tabs/index", "van-overlay": "@vant/weapp/overlay/index", "van-datetime-picker": "@vant/weapp/datetime-picker/index", "van-area": "@vant/weapp/area/index", "van-action-sheet": "@vant/weapp/action-sheet/index", "van-checkbox": "@vant/weapp/checkbox/index", "van-checkbox-group": "@vant/weapp/checkbox-group/index" }, "sitemapLocation": "sitemap.json" } ================================================ FILE: app.wxss ================================================ @import "/miniprogram_npm/@vant/weapp/common/index.wxss"; .container { display: flex; flex-direction: column; align-items: center; justify-content: space-between; box-sizing: border-box; } .space { height:20rpx; background-color: #F2f2f2; } .safeAreaOldPaddingBttom { padding-bottom: env(safe-area-inset-bottom); } .safeAreaNewPaddingBttom{ padding-bottom: constant(safe-area-inset-bottom); } .safeAreaOldMarginBttom { margin-bottom: env(safe-area-inset-bottom); } .safeAreaNewMarginBttom{ margin-bottom: constant(safe-area-inset-bottom); } .no-data { width: 100%; display: flex; justify-content: center; align-items: center; } .no-data .line { width:132rpx; height:2rpx; background: #999; } .no-data .txt { font-size:26rpx; color:rgba(153,153,153,1); margin: 0 16rpx; } .ad-img { width: 100vw; } .badge { position: absolute; top: 0; right: 0; box-sizing: border-box; padding: 6rpx; color: #fff; font-size: 18rpx; display: flex; justify-content: center; align-items: center; background-color: #e64340; border: 1rpx solid #fff; border-radius: 50%; } .vw100 { width: 100vw !important; } page { font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', Helvetica, Segoe UI, Arial, Roboto, 'PingFang SC', 'miui', 'Hiragino Sans GB', 'Microsoft Yahei', sans-serif; } .block-btn { padding: 0 32rpx; } .safe-bottom-box { position: fixed; bottom: calc(env(safe-area-inset-bottom) / 2); left: 0; width: 100vw; } .characteristic { padding: 0 24rpx; font-size: 24rpx; color: #999; } ================================================ FILE: components/bind-mobile/index.js ================================================ const WXAPI = require('apifm-wxapi') const AUTH = require('../../utils/auth') Component({ options: { addGlobalClass: true, }, /** * 组件的对外属性,是属性名到属性设置的映射表 */ properties: { title: String, alarmText: String, show: Boolean, }, /** * 组件的内部数据,和 properties 一同用于组件的模板渲染 */ data: { }, // 组件数据字段监听器,用于监听 properties 和 data 的变化 observers: { }, lifetimes: { attached() { }, detached() { // 在组件实例被从页面节点树移除时执行 }, }, /** * 组件的方法列表 */ methods: { close() { this.triggerEvent('cancel') }, async getPhoneNumber(e) { if (e.detail.errMsg.indexOf('privacy permission is not authorized') != -1) { wx.showModal({ content: '请阅读并同意隐私条款以后才能继续本操作', confirmText: '阅读协议', cancelText: '取消', success (res) { if (res.confirm) { wx.requirePrivacyAuthorize() // 弹出用户隐私授权框 } } }) return } if (!e.detail.errMsg) { wx.showModal({ content: 'getPhoneNumber异常', showCancel: false }) return } if (e.detail.errMsg == "getPhoneNumber:fail user deny") { return } if (!e.detail.errMsg || e.detail.errMsg != "getPhoneNumber:ok") { wx.showModal({ content: e.detail.errMsg, showCancel: false }) return; } this._getPhoneNumber(e) }, async _getPhoneNumber(e) { let res const extConfigSync = wx.getExtConfigSync() if (extConfigSync.subDomain) { // 服务商模式 const code = await AUTH.wxaCode() res = await WXAPI.wxappServiceBindMobile({ token: wx.getStorageSync('token'), code, encryptedData: e.detail.encryptedData, iv: e.detail.iv, }) } else { res = await WXAPI.bindMobileWxappV2(wx.getStorageSync('token'), e.detail.code) } if (res.code == 0) { wx.showToast({ title: '绑定成功' }) this.data.mobile = res.data this.triggerEvent('ok', this.data) } else { wx.showModal({ content: res.msg, showCancel: false }) } }, } }) ================================================ FILE: components/bind-mobile/index.json ================================================ { "component": true, "usingComponents": { } } ================================================ FILE: components/bind-mobile/index.wxml ================================================ {{ title }} 立即绑定 ================================================ FILE: components/bind-mobile/index.wxss ================================================ .pop-main { display: flex; flex-direction: column; } .title { padding: 32rpx; text-align: center; } .btn-box { padding: 32rpx; } ================================================ FILE: components/bind-mobile/sn.txt ================================================ app.json usingComponents 加上 "bind-mobile": "/components/bind-mobile/index", 在需要的页面上加这句代码即可 bindMobileOk(e) { console.log(e.detail); // 这里是组件里data的数据 this.setData({ bindMobileShow: false }) }, bindMobileCancel() { this.setData({ bindMobileShow: false }) }, ================================================ FILE: components/date-time-selecter/index.js ================================================ const dayjs = require("dayjs") const weekStr = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'] Component({ options: { addGlobalClass: true, }, /** * 组件的对外属性,是属性名到属性设置的映射表 */ properties: { maxDays: Number, title: String, alarmText: String, show: Boolean, }, /** * 组件的内部数据,和 properties 一同用于组件的模板渲染 */ data: { activeKey: 0, days: undefined, // 左侧的日期列表 day: undefined, // 选中的日期 YYYY-MM-DD times: undefined, // 右侧选中的时间列表 timeSelectIndex: 0, // 选中的索引 timeSelected: undefined, // 用于自动滚到到这个位置 }, // 组件数据字段监听器,用于监听 properties 和 data 的变化 observers: { }, lifetimes: { attached() { const days = [] for (let index = 0; index < this.data.maxDays; index++) { const d = dayjs().add(index, 'day') days.push({ d, isToday: index == 0, day: d.format('YYYY-MM-DD'), display: d.format('MM月DD日') + ' ' + weekStr[d.day()] }) } this.setData({ days, day: days[0].day }) this.initTimes() }, detached() { // 在组件实例被从页面节点树移除时执行 }, }, /** * 组件的方法列表 */ methods: { initTimes() { const dayItem = this.data.days[this.data.activeKey] const times = [] let curHour = dayItem.isToday ? dayjs().hour() : 0 // 当前时间 for (let index = 0; index < 12; index++) { let beginHour = index*2 if (beginHour < curHour) { continue } let endHour = index*2 + 2 if (beginHour < 10) { beginHour = '0' + beginHour } if (endHour < 10) { endHour = '0' + endHour } times.push(beginHour + ':00-' + endHour + ':00') } this.setData({ timeSelectIndex: 0, times, timeSelected: times[0] }) }, dayClick(e) { const activeKey = e.currentTarget.dataset.idx const dayItem = this.data.days[activeKey] this.setData({ activeKey, day: dayItem.day, }) this.initTimes() }, timeClick(e) { const idx = e.currentTarget.dataset.idx const timeSelected = this.data.times[idx] this.setData({ timeSelectIndex: idx, timeSelected, }) }, closeSku() { this.triggerEvent('cancel') }, submit() { this.triggerEvent('ok', this.data) }, } }) ================================================ FILE: components/date-time-selecter/index.json ================================================ { "component": true, "usingComponents": { } } ================================================ FILE: components/date-time-selecter/index.wxml ================================================ {{ title }} {{ item }} 确定 ================================================ FILE: components/date-time-selecter/index.wxss ================================================ .pop-main { height: 80vh; display: flex; flex-direction: column; } .title { padding: 32rpx; text-align: center; } .main { flex: 1; overflow: hidden; display: flex; } .l { width: 250rpx; height: 100%; } .ll { width: 250rpx; } .r { flex: 1; } .time-box { padding: 32rpx; display: flex; justify-content: space-between; } .time-l-active { font-weight: bold; } .btn-box { padding: 32rpx; } ================================================ FILE: components/date-time-selecter/sn.txt ================================================ app.json usingComponents 加上 "date-time-selecter": "/components/date-time-selecter/index", 在需要的页面上加这句代码即可 dayTimeSelectOK(e) { console.log(e.detail); // 这里是组件里data的数据 this.setData({ show: false }) }, dayTimeSelectCancel() { this.setData({ show: false }) }, ================================================ FILE: components/fuwuxieyi/index.js ================================================ const App = getApp(); Component({ options: { addGlobalClass: true, }, /** * 组件的对外属性,是属性名到属性设置的映射表 */ properties: { k: String, }, /** * 组件的内部数据,和 properties 一同用于组件的模板渲染 */ data: { s: false }, // 组件数据字段监听器,用于监听 properties 和 data 的变化 observers: { }, lifetimes: { attached: function () { if (!this.data.k) { this.setData({ s: true }) return } const agreeYxtk = wx.getStorageSync('agreeYxtk_' + this.data.k) if (!agreeYxtk) { this.setData({ s: true }) } }, detached: function () { // 在组件实例被从页面节点树移除时执行 }, }, /** * 组件的方法列表 */ methods: { aggree(){ if (this.data.k) { wx.setStorageSync('agreeYxtk_' + this.data.k, true) } this.setData({ s: false }) }, notagree(){ wx.navigateTo({ url: '/pages/notagree/index' }) }, goYstk(e){ const k = e.currentTarget.dataset.k wx.navigateTo({ url: '/pages/about/index?key=' + k, }) }, navBack: function () { wx.navigateBack({ delta: 1 }) }, //回主页 toIndex: function () { wx.navigateTo({ url: '/pages/admin/home/index/index' }) }, } }) ================================================ FILE: components/fuwuxieyi/index.json ================================================ { "component": true, "usingComponents": { } } ================================================ FILE: components/fuwuxieyi/index.wxml ================================================ 用户协议及隐私政策 您在使用我们的服务时,我们可能会收集和 使用您的相关信息。我们希望通过本 《用户协议》《隐私协议》向您说明,在使用我 们的服务时,我们如何收集、使用、储存和 分享这些信息,以及我们为您提供的访问、 更新、控制和保护这些信息的方式。本《用户协议》《隐私协议》,希望您仔细闭读, 充分理解协议中的内容后再点击同意。 同意 不同意 ================================================ FILE: components/fuwuxieyi/index.wxss ================================================ .btn-add-box-popup .t { font-size: 36rpx; text-align: center; height: 88rpx; line-height: 88rpx; font-weight: bold; } .btn-add-box-popup .bd { padding: 0 32rpx; padding-bottom: 32rpx; } .btn-add-box-popup .del-btn { margin-top: 32rpx; } .content { width: 600rpx; padding: 32rpx; font-size: 32rpx; line-height: 54rpx; } .link { color: #10AEFF; } .btn-group { padding: 32rpx; display: flex; justify-content: space-around; } .mt32 { margin-top: 32rpx; } ================================================ FILE: components/fuwuxieyi/sn.txt ================================================ 在需要的页面上加这句代码即可 k 为页面唯一编号,随便命名即可 不传k,每次都会弹出 ================================================ FILE: components/goods-pop/index.js ================================================ const WXAPI = require('apifm-wxapi') const AUTH = require('../../utils/auth') const TOOLS = require('../../utils/tools.js') // TOOLS.showTabBarBadge(); Component({ behaviors: [], options: { addGlobalClass: true, }, /** * 组件的对外属性,是属性名到属性设置的映射表 */ properties: { skuCurGoodsBaseInfo: null, }, /** * 组件的内部数据,和 properties 一同用于组件的模板渲染 */ data: { skuCurGoodsShow: false, skuCurGoods: undefined }, // 组件数据字段监听器,用于监听 properties 和 data 的变化 observers: { 'skuCurGoodsBaseInfo': function(skuCurGoodsBaseInfo) { console.log('observers-skuCurGoodsBaseInfo', skuCurGoodsBaseInfo) if (!skuCurGoodsBaseInfo) { return } if (skuCurGoodsBaseInfo.stores <= 0) { wx.showToast({ title: '已售罄~', icon: 'none' }) return } this.initGoodsData(skuCurGoodsBaseInfo) } }, lifetimes: { attached: function () { console.log('11', this.data.skuCurGoods); }, detached: function () { // 在组件实例被从页面节点树移除时执行 }, }, pageLifetimes: { // 组件所在页面的生命周期函数 show: function () { console.log('22', this.data.skuCurGoods); }, hide: function () { }, resize: function () { }, }, /** * 组件的方法列表 */ methods: { closeSku(){ // 关闭弹窗 this.setData({ skuCurGoodsShow: false }) wx.showTabBar() }, async initGoodsData(skuCurGoodsBaseInfo) { const skuCurGoodsRes = await WXAPI.goodsDetail(skuCurGoodsBaseInfo.id) if (skuCurGoodsRes.code != 0) { wx.showToast({ title: skuCurGoodsRes.msg, icon: 'none' }) return } wx.hideTabBar() const skuCurGoods = skuCurGoodsRes.data skuCurGoods.basicInfo.storesBuy = 1 // 处理可选配件 skuCurGoods.basicInfo.hasAddition = skuCurGoodsBaseInfo.hasAddition let goodsAddition = [] if (skuCurGoods.basicInfo.hasAddition) { const res = await WXAPI.goodsAddition(skuCurGoodsBaseInfo.id) if (res.code == 0) { goodsAddition = res.data } } console.log('abc:', skuCurGoods); this.setData({ skuCurGoods, goodsAddition, skuGoodsPic: skuCurGoods.basicInfo.pic, selectSizePrice: skuCurGoods.basicInfo.minPrice, selectSizeOPrice: skuCurGoods.basicInfo.originalPrice, skuCurGoodsShow: true }) }, storesJia(){ const skuCurGoods = this.data.skuCurGoods if (skuCurGoods.basicInfo.storesBuy < skuCurGoods.basicInfo.stores) { skuCurGoods.basicInfo.storesBuy++ this.setData({ skuCurGoods }) } }, storesJian(){ const skuCurGoods = this.data.skuCurGoods if (skuCurGoods.basicInfo.storesBuy > 1) { skuCurGoods.basicInfo.storesBuy-- this.setData({ skuCurGoods }) } }, skuSelect(e){ const skuCurGoods = this.data.skuCurGoods const propertyindex = e.currentTarget.dataset.propertyindex const propertychildindex = e.currentTarget.dataset.propertychildindex const property = this.data.skuCurGoods.properties[propertyindex] const child = property.childsCurGoods[propertychildindex] // 当前位置往下的所有sku取消选中状态 for (let index = propertyindex; index < skuCurGoods.properties.length; index++) { const element = skuCurGoods.properties[index] element.optionValueId = null element.childsCurGoods.forEach(child => { child.active = false }) } // 处理选中 property.childsCurGoods.forEach(ele => { if (ele.id == child.id) { ele.active = true } else { ele.active = false } }) // 隐藏没有的sku,不让选中 let _skuList = skuCurGoods.skuList skuCurGoods.properties.forEach(p => { p.childsCurGoods.forEach(c => { // 处理当前选中的sku信息 if (c.active) { _skuList = _skuList.filter(aaa => { return aaa.propertyChildIds.indexOf(p.id + ':' + c.id) != -1 }) } else if(!p.optionValueId) { const nextO = _skuList.find(aaa => { return aaa.propertyChildIds.indexOf(p.id + ':' + c.id) != -1 }) c.hidden = (nextO || p.id == property.id) ? false : true } }) }) // 显示图片 let skuGoodsPic = this.data.skuGoodsPic if (skuCurGoods.subPics && skuCurGoods.subPics.length > 0) { const _subPic = skuCurGoods.subPics.find(ele => { return ele.optionValueId == child.id }) if (_subPic) { skuGoodsPic = _subPic.pic } } this.setData({ skuCurGoods, skuGoodsPic }) // 计算价格 this.calculateGoodsPrice() }, /** * 选择可选配件 */ async additionSelect(e) { const propertyindex = e.currentTarget.dataset.propertyindex const propertychildindex = e.currentTarget.dataset.propertychildindex const goodsAddition = this.data.goodsAddition const property = goodsAddition[propertyindex] const child = property.items[propertychildindex] if (child.active) { // 该操作为取消选择 child.active = false this.setData({ goodsAddition }) this.calculateGoodsPrice() return } // 单选配件取消所有子栏目选中状态 if (property.type == 0) { property.items.forEach(child => { child.active = false }) } // 设置当前选中状态 child.active = true this.setData({ goodsAddition }) this.calculateGoodsPrice() }, async calculateGoodsPrice() { // 计算最终的商品价格 let price = this.data.skuCurGoods.basicInfo.minPrice let originalPrice = this.data.skuCurGoods.basicInfo.originalPrice let totalScoreToPay = this.data.skuCurGoods.basicInfo.minScore let buyNumMax = this.data.skuCurGoods.basicInfo.stores let buyNumber = this.data.skuCurGoods.basicInfo.minBuyNumber // 计算 sku 价格 const needSelectNum = this.data.skuCurGoods.properties ? this.data.skuCurGoods.properties.length : 0 let curSelectNum = 0; let propertyChildIds = ""; let propertyChildNames = ""; if (this.data.skuCurGoods.properties) { this.data.skuCurGoods.properties.forEach(p => { p.childsCurGoods.forEach(c => { if (c.active) { curSelectNum++; propertyChildIds = propertyChildIds + p.id + ":" + c.id + ","; propertyChildNames = propertyChildNames + p.name + ":" + c.name + " "; } }) }) } let canSubmit = true; if (needSelectNum != curSelectNum) { canSubmit = false; } // 计算可选配件 if (this.data.skuCurGoods.basicInfo.hasAddition && this.data.goodsAddition) { this.data.goodsAddition.forEach(ele => { if (ele.required) { const a = ele.items.find(item => { return item.active }) if (!a) { canSubmit = false } } }) } const token = wx.getStorageSync('token') if (canSubmit) { const res = await WXAPI.goodsPriceV2({ token: token ? token : '', goodsId: this.data.skuCurGoods.basicInfo.id, propertyChildIds: propertyChildIds }) if (res.code == 0) { price = res.data.price originalPrice = res.data.originalPrice totalScoreToPay = res.data.score buyNumMax = res.data.stores } } // 计算配件价格 if (this.data.goodsAddition) { this.data.goodsAddition.forEach(big => { big.items.forEach(small => { if (small.active) { price = (price * 100 + small.price * 100) / 100 } }) }) } this.setData({ canSubmit, selectSizePrice: price, selectSizeOPrice: originalPrice, totalScoreToPay: totalScoreToPay, buyNumMax, buyNumber: (buyNumMax >= buyNumber) ? buyNumber : 0 }); }, async addCarSku(){ await this.calculateGoodsPrice() // 加入购物车 if (!this.data.canSubmit) { wx.showToast({ title: '请选择规格/配件', icon: 'none' }) return } const skuCurGoods = this.data.skuCurGoods const sku = [] if (skuCurGoods.properties) { skuCurGoods.properties.forEach(p => { const o = p.childsCurGoods.find(ele => {return ele.active}) if (!o) { return } sku.push({ optionId: o.propertyId, optionValueId: o.id }) }) } const goodsAddition = [] if (this.data.goodsAddition) { this.data.goodsAddition.forEach(ele => { ele.items.forEach(item => { if (item.active) { goodsAddition.push({ id: item.id, pid: item.pid }) } }) }) } const res = await WXAPI.shippingCarInfoAddItem(wx.getStorageSync('token'), skuCurGoods.basicInfo.id, skuCurGoods.basicInfo.storesBuy, sku, goodsAddition) if (res.code == 2000) { wx.navigateTo({ url: '/pages/login/index', }) return } if (res.code == 0) { wx.showToast({ title: '加入成功', icon: 'success' }) wx.showTabBar() TOOLS.showTabBarBadge() // 获取购物车数据,显示TabBarBadge this.setData({ skuCurGoodsShow: false }) } else { wx.showToast({ title: res.msg, icon: 'none' }) } }, } }) ================================================ FILE: components/goods-pop/index.json ================================================ { "component": true, "usingComponents": { } } ================================================ FILE: components/goods-pop/index.wxml ================================================ {{item.name}} {{item.name}} {{small.name}} 购买数量 加入购物车 ================================================ FILE: components/goods-pop/index.wxss ================================================ .sku-container { box-sizing: border-box; width: 100vw; padding: 32rpx 32rpx 0 32rpx; } .sku-container .sku { border-bottom: 1rpx solid #eee; padding-bottom: 24rpx; margin-bottom: 16rpx; } .sku-container .sku .t { color: #333; } .sku-container .sku .items { display: flex; flex-wrap: wrap; } .sku-container .sku .items text { padding: 8rpx 16rpx; border: 1rpx solid #eee; color: #666; margin: 24rpx 24rpx 0 0; font-size: 26rpx; border-radius: 8rpx; } .sku-container .sku .items text.active { border: 1rpx solid #e64340; color: #e64340; } .sku-container .num { display: flex; justify-content: space-between; align-items: center; margin-bottom: 24rpx; } .sku-container .num .t { color: #333; } .btn { padding: 32rpx; } ================================================ FILE: components/login/index.js ================================================ const WXAPI = require('apifm-wxapi') Component({ options: { // 样式隔离 https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/wxml-wxss.html#%E7%BB%84%E4%BB%B6%E6%A0%B7%E5%BC%8F%E9%9A%94%E7%A6%BB styleIsolation: 'apply-shared', }, /** * 组件的对外属性,是属性名到属性设置的映射表 */ properties: { avatarUrl: String, name: String, show: Boolean, }, /** * 组件的内部数据,和 properties 一同用于组件的模板渲染 */ data: { nick: undefined }, // 组件数据字段监听器,用于监听 properties 和 data 的变化 observers: { }, lifetimes: { attached() { this.setData({ nick: this.data.name }) }, detached: function () { // 在组件实例被从页面节点树移除时执行 }, }, /** * 组件的方法列表 */ methods: { async _editNick() { if (!this.data.nick) { wx.showToast({ title: '请填写昵称', icon: 'none' }) return } const postData = { token: wx.getStorageSync('token'), nick: this.data.nick, } // https://www.yuque.com/apifm/nu0f75/ykr2zr const res = await WXAPI.modifyUserInfoV2(postData) if (res.code != 0) { wx.showToast({ title: res.msg, icon: 'none' }) return } wx.showToast({ title: '保存成功', }) this.setData({ show: false }) getApp().getUserApiInfo() }, async onChooseAvatar(e) { let avatarUrl = e.detail.avatarUrl let res = await WXAPI.uploadFileV2(wx.getStorageSync('token'), avatarUrl) if (res.code != 0) { wx.showToast({ title: res.msg, icon: 'none' }) return } avatarUrl = res.data.url // https://www.yuque.com/apifm/nu0f75/ykr2zr res = await WXAPI.modifyUserInfoV2({ token: wx.getStorageSync('token'), avatarUrl, }) if (res.code != 0) { wx.showToast({ title: res.msg, icon: 'none' }) return } this.setData({ avatarUrl }) }, jump() { this.setData({ show: false }) } } }) ================================================ FILE: components/login/index.json ================================================ { "component": true, "usingComponents": { } } ================================================ FILE: components/login/index.wxml ================================================ 头像昵称填写 跳过 保存 ================================================ FILE: components/login/index.wxss ================================================ .btn-add-box-popup { width: 600rpx; } .t-box { margin-top: 32rpx; height: 100rpx; position: relative; } .t { line-height: 100rpx; font-size: 32rpx; text-align: center; } .jump { position: absolute; top: 0; right: 48rpx; line-height: 100rpx; font-size: 28rpx; color: #bbb; } .avatar { margin-top: 32rpx; width: 240rpx; height: 240rpx; padding: 0; border-radius: 50%; } .avatar-img { width: 240rpx; height: 240rpx; } .nick-box { padding: 32rpx 0; } .btn-group { padding: 32rpx; } .abc-box { position: relative; } .abc-box .trip { position: absolute; width: 100%; bottom: 32rpx; left: 0; font-size: 24rpx; background-color: rgba(0, 0, 0, 0.5); color: #fff; } ================================================ FILE: components/login/sn.txt ================================================ 1. app.json, usingComponents "login": "/components/login/index", 2. 在需要的页面上加这句代码即可 show 控制弹框是否显示 avatarUrl 回显的头像 name 回显的昵称 ================================================ FILE: components/payment/index.js ================================================ const WXAPI = require('apifm-wxapi'); const { wxaCode } = require('../../utils/auth'); Component({ options: { addGlobalClass: true, }, /** * 组件的对外属性,是属性名到属性设置的映射表 */ properties: { money: Number, remark: String, nextAction: Object, extData: Object, show: Boolean, }, /** * 组件的内部数据,和 properties 一同用于组件的模板渲染 */ data: { payType: 'wx', alipayOpenMod: '0' }, // 组件数据字段监听器,用于监听 properties 和 data 的变化 observers: { 'show': function(show) { this.setData({ alipayQrcode: null, alipayOpenMod: wx.getStorageSync('alipay') }) } }, lifetimes: { attached() { }, detached() { // 在组件实例被从页面节点树移除时执行 }, }, /** * 组件的方法列表 */ methods: { close() { this.triggerEvent('cancel') }, payTypeChange(event) { this.setData({ payType: event.detail, alipayQrcode: null, }); }, payTypeClick(event) { const { name } = event.currentTarget.dataset; this.setData({ payType: name, alipayQrcode: null, }); }, async submit() { const postData = { token: wx.getStorageSync('token'), money: this.data.money, remark: this.data.remark, } if (this.data.extData) { postData = { ...postData, ...this.data.extData } } if (this.data.nextAction) { postData.nextAction = JSON.stringify(this.data.nextAction) } postData.payName = postData.remark const url = wx.getStorageSync('wxpay_api_url') let res if (this.data.payType == 'wx') { // https://www.yuque.com/apifm/nu0f75/ppadt8 res = await WXAPI.payVariableUrl(url ? url : '/pay/wx/wxapp', postData) } else if (this.data.payType == 'alipay') { // https://www.yuque.com/apifm/nu0f75/hguh83ekxsh71cn7 res = await WXAPI.alipayQrcode(postData) } else { wx.showModal({ content: '暂不支持该支付方式', showCancel: false }) this.close() return } if (res.code != 0) { wx.showModal({ content: JSON.stringify(res), showCancel: false }) this.close() return } if (this.data.payType == 'wx') { wx.requestPayment({ timeStamp: res.data.timeStamp, nonceStr: res.data.nonceStr, package: res.data.package, signType: res.data.signType, paySign: res.data.paySign, fail: aaa => { console.error(aaa) wx.showToast({ title: '支付失败:' + aaa, icon: 'none' }) }, success: () => { wx.showToast({ title: '支付成功' }) this.triggerEvent('ok', this.data) } }) } if (this.data.payType == 'alipay') { const qrcodeRes = JSON.parse(res.data.qrcode) const alipayQrcode = qrcodeRes.alipay_trade_precreate_response.qr_code console.log(alipayQrcode); // 生成二维码 https://www.yuque.com/apifm/nu0f75/xrnyo9 const resQrcode = await WXAPI.commonQrcode({ content: alipayQrcode, width: 650 }) if (resQrcode.code != 0) { wx.showToast({ title: '无法获取二维码', icon: 'none' }) return } console.log(resQrcode.data); this.setData({ alipayQrcode: resQrcode.data }) } }, } }) ================================================ FILE: components/payment/index.json ================================================ { "component": true, "usingComponents": { } } ================================================ FILE: components/payment/index.wxml ================================================ {{ remark }} {{ money }} 选择支付方式 长按图片保存,然后使用支付宝扫一扫付款 立即支付 ================================================ FILE: components/payment/index.wxss ================================================ .pop-main { display: flex; flex-direction: column; } .title { padding: 32rpx; text-align: center; } .btn-box { padding: 32rpx; } .alipayQrcode { margin-left: 50rpx; } .alipayQrcodeText { text-align: center; color: rgb(201, 25, 48); font-size: 24rpx; } .amount { padding: 16rpx; text-align: center; color: #e64340; font-weight: bold; font-size: 52rpx; } .amount text { font-weight: normal; font-size: 28rpx; } ================================================ FILE: components/payment/sn.txt ================================================ app.json usingComponents 加上 "payment": "/components/payment/index", 在需要的页面上加这句代码即可 paymentOk(e) { console.log(e.detail); // 这里是组件里data的数据 this.setData({ paymentShow: false }) }, paymentCancel() { this.setData({ paymentShow: false }) }, ================================================ FILE: components/vip-success/index.js ================================================ Component({ options: { addGlobalClass: true, }, properties: { show: { type: Boolean, value: false }, levelName: { type: String, value: '' }, benefits: { type: Array, value: [] } }, data: { }, methods: { handleMaskClick() { // 点击遮罩层不关闭,必须点击确定按钮 }, stopPropagation() { // 阻止事件冒泡 }, handleConfirm() { this.triggerEvent('confirm') } } }) ================================================ FILE: components/vip-success/index.json ================================================ { "component": true, "usingComponents": { "van-icon": "@vant/weapp/icon/index" } } ================================================ FILE: components/vip-success/index.wxml ================================================ 🎉 恭喜您 成功升级为 {{levelName}} {{item}} 确定 ================================================ FILE: components/vip-success/index.wxss ================================================ .success-modal { position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0, 0, 0, 0.7); display: flex; align-items: center; justify-content: center; z-index: 9999; animation: fadeIn 0.3s ease; } @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } } .modal-content { position: relative; width: 600rpx; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); border-radius: 32rpx; padding: 60rpx 40rpx; display: flex; flex-direction: column; align-items: center; overflow: hidden; animation: scaleIn 0.5s cubic-bezier(0.68, -0.55, 0.265, 1.55); } @keyframes scaleIn { from { transform: scale(0.5); opacity: 0; } to { transform: scale(1); opacity: 1; } } .fireworks { position: absolute; top: 0; left: 0; right: 0; bottom: 0; pointer-events: none; overflow: hidden; } .firework { position: absolute; width: 10rpx; height: 10rpx; border-radius: 50%; background: rgba(255, 255, 255, 0.8); animation: explode 1.5s ease-out infinite; } .firework:nth-child(1) { top: 20%; left: 20%; animation-delay: 0s; } .firework:nth-child(2) { top: 30%; right: 20%; animation-delay: 0.3s; } .firework:nth-child(3) { top: 50%; left: 10%; animation-delay: 0.6s; } .firework:nth-child(4) { top: 60%; right: 15%; animation-delay: 0.9s; } .firework:nth-child(5) { top: 40%; left: 50%; animation-delay: 1.2s; } @keyframes explode { 0% { transform: scale(0); opacity: 1; } 50% { transform: scale(20); opacity: 0.5; } 100% { transform: scale(40); opacity: 0; } } .success-icon { margin-bottom: 32rpx; animation: bounce 1s ease infinite; } @keyframes bounce { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-20rpx); } } .icon-circle { width: 160rpx; height: 160rpx; background: rgba(255, 255, 255, 0.2); border-radius: 50%; display: flex; align-items: center; justify-content: center; backdrop-filter: blur(10rpx); border: 6rpx solid rgba(255, 255, 255, 0.3); box-shadow: 0 8rpx 32rpx rgba(0, 0, 0, 0.2); } .success-title { font-size: 48rpx; font-weight: bold; color: #ffffff; margin-bottom: 16rpx; text-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.2); } .success-desc { font-size: 28rpx; color: rgba(255, 255, 255, 0.9); margin-bottom: 12rpx; } .level-name { font-size: 40rpx; font-weight: bold; color: #ffffff; padding: 16rpx 48rpx; background: rgba(255, 255, 255, 0.2); border-radius: 40rpx; backdrop-filter: blur(10rpx); margin-bottom: 32rpx; } .benefits-preview { display: flex; flex-wrap: wrap; gap: 16rpx; justify-content: center; margin-bottom: 40rpx; } .benefit-tag { padding: 12rpx 24rpx; background: rgba(255, 255, 255, 0.2); border-radius: 24rpx; font-size: 24rpx; color: #ffffff; backdrop-filter: blur(10rpx); } .confirm-btn { width: 100%; padding: 28rpx; background: #ffffff; color: #667eea; font-size: 32rpx; font-weight: bold; border-radius: 48rpx; text-align: center; box-shadow: 0 8rpx 24rpx rgba(0, 0, 0, 0.2); transition: all 0.3s; } .confirm-btn:active { transform: scale(0.95); } ================================================ FILE: config.js ================================================ module.exports = { version: '26.3.13', note: '首页购买动态SDK升级', // 这个为版本描述,无需修改 subDomain: 'tz', // 此处改成你自己的专属域名。什么是专属域名?请看教程 https://www.it120.cc/help/qr6l4m.html merchantId: 951, // 商户ID,可在后台工厂设置-->商户信息查看 sdkAppID: 1400450467, // 腾讯实时音视频应用编号,请看教程 https://www.it120.cc/help/nxoqsl.html bindSeller: false, // true 开启三级分销抢客; false 为不开启 customerServiceType: 'QW', // 客服类型,QW为企业微信,需要在后台系统参数配置企业ID和客服URL,XCX 为小程序的默认客服 openIdAutoRegister: true, // 用户打开小程序的时候自动注册新用户【用户不存在的时候】 } ================================================ FILE: jsconfig.json ================================================ { "compilerOptions": { "target": "es2015", "module": "commonjs" } } ================================================ FILE: miniprogram_npm/@vant/weapp/action-sheet/index.d.ts ================================================ export {}; ================================================ FILE: miniprogram_npm/@vant/weapp/action-sheet/index.js ================================================ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var component_1 = require("../common/component"); var button_1 = require("../mixins/button"); (0, component_1.VantComponent)({ classes: ['list-class'], mixins: [button_1.button], props: { show: Boolean, title: String, cancelText: String, description: String, round: { type: Boolean, value: true, }, zIndex: { type: Number, value: 100, }, actions: { type: Array, value: [], }, overlay: { type: Boolean, value: true, }, closeOnClickOverlay: { type: Boolean, value: true, }, closeOnClickAction: { type: Boolean, value: true, }, safeAreaInsetBottom: { type: Boolean, value: true, }, rootPortal: { type: Boolean, value: false, }, }, methods: { onSelect: function (event) { var _this = this; var index = event.currentTarget.dataset.index; var _a = this.data, actions = _a.actions, closeOnClickAction = _a.closeOnClickAction, canIUseGetUserProfile = _a.canIUseGetUserProfile; var item = actions[index]; if (item) { this.$emit('select', item); if (closeOnClickAction) { this.onClose(); } if (item.openType === 'getUserInfo' && canIUseGetUserProfile) { wx.getUserProfile({ desc: item.getUserProfileDesc || ' ', complete: function (userProfile) { _this.$emit('getuserinfo', userProfile); }, }); } } }, onCancel: function () { this.$emit('cancel'); }, onClose: function () { this.$emit('close'); }, onClickOverlay: function () { this.$emit('click-overlay'); this.onClose(); }, }, }); ================================================ FILE: miniprogram_npm/@vant/weapp/action-sheet/index.json ================================================ { "component": true, "usingComponents": { "van-icon": "../icon/index", "van-popup": "../popup/index", "van-loading": "../loading/index" } } ================================================ FILE: miniprogram_npm/@vant/weapp/action-sheet/index.wxml ================================================ {{ title }} {{ description }} {{ cancelText }} ================================================ FILE: miniprogram_npm/@vant/weapp/action-sheet/index.wxss ================================================ @import '../common/index.wxss';.van-action-sheet{color:var(--action-sheet-item-text-color,#323233);max-height:var(--action-sheet-max-height,90%)!important}.van-action-sheet__cancel,.van-action-sheet__item{background-color:var(--action-sheet-item-background,#fff);font-size:var(--action-sheet-item-font-size,16px);line-height:var(--action-sheet-item-line-height,22px);padding:14px 16px;text-align:center}.van-action-sheet__cancel--hover,.van-action-sheet__item--hover{background-color:#f2f3f5}.van-action-sheet__cancel:after,.van-action-sheet__item:after{border-width:0}.van-action-sheet__cancel{color:var(--action-sheet-cancel-text-color,#646566)}.van-action-sheet__gap{background-color:var(--action-sheet-cancel-padding-color,#f7f8fa);display:block;height:var(--action-sheet-cancel-padding-top,8px)}.van-action-sheet__item--disabled{color:var(--action-sheet-item-disabled-text-color,#c8c9cc)}.van-action-sheet__item--disabled.van-action-sheet__item--hover{background-color:var(--action-sheet-item-background,#fff)}.van-action-sheet__subname{color:var(--action-sheet-subname-color,#969799);font-size:var(--action-sheet-subname-font-size,12px);line-height:var(--action-sheet-subname-line-height,20px);margin-top:var(--padding-xs,8px)}.van-action-sheet__header{font-size:var(--action-sheet-header-font-size,16px);font-weight:var(--font-weight-bold,500);line-height:var(--action-sheet-header-height,48px);text-align:center}.van-action-sheet__description{color:var(--action-sheet-description-color,#969799);font-size:var(--action-sheet-description-font-size,14px);line-height:var(--action-sheet-description-line-height,20px);padding:20px var(--padding-md,16px);text-align:center}.van-action-sheet__close{color:var(--action-sheet-close-icon-color,#c8c9cc);font-size:var(--action-sheet-close-icon-size,22px)!important;line-height:inherit!important;padding:var(--action-sheet-close-icon-padding,0 16px);position:absolute!important;right:0;top:0}.van-action-sheet__loading{display:flex!important} ================================================ FILE: miniprogram_npm/@vant/weapp/area/index.d.ts ================================================ export {}; ================================================ FILE: miniprogram_npm/@vant/weapp/area/index.js ================================================ "use strict"; var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; Object.defineProperty(exports, "__esModule", { value: true }); var component_1 = require("../common/component"); var shared_1 = require("../picker/shared"); var utils_1 = require("../common/utils"); var EMPTY_CODE = '000000'; (0, component_1.VantComponent)({ classes: ['active-class', 'toolbar-class', 'column-class'], props: __assign(__assign({}, shared_1.pickerProps), { showToolbar: { type: Boolean, value: true, }, value: { type: String, observer: function (value) { this.code = value; this.setValues(); }, }, areaList: { type: Object, value: {}, observer: 'setValues', }, columnsNum: { type: null, value: 3, }, columnsPlaceholder: { type: Array, observer: function (val) { this.setData({ typeToColumnsPlaceholder: { province: val[0] || '', city: val[1] || '', county: val[2] || '', }, }); }, } }), data: { columns: [{ values: [] }, { values: [] }, { values: [] }], typeToColumnsPlaceholder: {}, }, mounted: function () { var _this = this; (0, utils_1.requestAnimationFrame)(function () { _this.setValues(); }); }, methods: { getPicker: function () { if (this.picker == null) { this.picker = this.selectComponent('.van-area__picker'); } return this.picker; }, onCancel: function (event) { this.emit('cancel', event.detail); }, onConfirm: function (event) { var index = event.detail.index; var value = event.detail.value; value = this.parseValues(value); this.emit('confirm', { value: value, index: index }); }, emit: function (type, detail) { detail.values = detail.value; delete detail.value; this.$emit(type, detail); }, parseValues: function (values) { var columnsPlaceholder = this.data.columnsPlaceholder; return values.map(function (value, index) { if (value && (!value.code || value.name === columnsPlaceholder[index])) { return __assign(__assign({}, value), { code: '', name: '' }); } return value; }); }, onChange: function (event) { var _this = this; var _a; var _b = event.detail, index = _b.index, picker = _b.picker, value = _b.value; this.code = value[index].code; (_a = this.setValues()) === null || _a === void 0 ? void 0 : _a.then(function () { _this.$emit('change', { picker: picker, values: _this.parseValues(picker.getValues()), index: index, }); }); }, getConfig: function (type) { var areaList = this.data.areaList; return (areaList && areaList["".concat(type, "_list")]) || {}; }, getList: function (type, code) { if (type !== 'province' && !code) { return []; } var typeToColumnsPlaceholder = this.data.typeToColumnsPlaceholder; var list = this.getConfig(type); var result = Object.keys(list).map(function (code) { return ({ code: code, name: list[code], }); }); if (code != null) { // oversea code if (code[0] === '9' && type === 'city') { code = '9'; } result = result.filter(function (item) { return item.code.indexOf(code) === 0; }); } if (typeToColumnsPlaceholder[type] && result.length) { // set columns placeholder var codeFill = type === 'province' ? '' : type === 'city' ? EMPTY_CODE.slice(2, 4) : EMPTY_CODE.slice(4, 6); result.unshift({ code: "".concat(code).concat(codeFill), name: typeToColumnsPlaceholder[type], }); } return result; }, getIndex: function (type, code) { var compareNum = type === 'province' ? 2 : type === 'city' ? 4 : 6; var list = this.getList(type, code.slice(0, compareNum - 2)); // oversea code if (code[0] === '9' && type === 'province') { compareNum = 1; } code = code.slice(0, compareNum); for (var i = 0; i < list.length; i++) { if (list[i].code.slice(0, compareNum) === code) { return i; } } return 0; }, setValues: function () { var picker = this.getPicker(); if (!picker) { return; } var code = this.code || this.getDefaultCode(); var provinceList = this.getList('province'); var cityList = this.getList('city', code.slice(0, 2)); var stack = []; var indexes = []; var columnsNum = this.data.columnsNum; if (columnsNum >= 1) { stack.push(picker.setColumnValues(0, provinceList, false)); indexes.push(this.getIndex('province', code)); } if (columnsNum >= 2) { stack.push(picker.setColumnValues(1, cityList, false)); indexes.push(this.getIndex('city', code)); if (cityList.length && code.slice(2, 4) === '00') { code = cityList[0].code; } } if (columnsNum === 3) { stack.push(picker.setColumnValues(2, this.getList('county', code.slice(0, 4)), false)); indexes.push(this.getIndex('county', code)); } return Promise.all(stack) .catch(function () { }) .then(function () { return picker.setIndexes(indexes); }) .catch(function () { }); }, getDefaultCode: function () { var columnsPlaceholder = this.data.columnsPlaceholder; if (columnsPlaceholder.length) { return EMPTY_CODE; } var countyCodes = Object.keys(this.getConfig('county')); if (countyCodes[0]) { return countyCodes[0]; } var cityCodes = Object.keys(this.getConfig('city')); if (cityCodes[0]) { return cityCodes[0]; } return ''; }, getValues: function () { var picker = this.getPicker(); if (!picker) { return []; } return this.parseValues(picker.getValues().filter(function (value) { return !!value; })); }, getDetail: function () { var values = this.getValues(); var area = { code: '', country: '', province: '', city: '', county: '', }; if (!values.length) { return area; } var names = values.map(function (item) { return item.name; }); area.code = values[values.length - 1].code; if (area.code[0] === '9') { area.country = names[1] || ''; area.province = names[2] || ''; } else { area.province = names[0] || ''; area.city = names[1] || ''; area.county = names[2] || ''; } return area; }, reset: function (code) { this.code = code || ''; return this.setValues(); }, }, }); ================================================ FILE: miniprogram_npm/@vant/weapp/area/index.json ================================================ { "component": true, "usingComponents": { "van-picker": "../picker/index" } } ================================================ FILE: miniprogram_npm/@vant/weapp/area/index.wxml ================================================ ================================================ FILE: miniprogram_npm/@vant/weapp/area/index.wxs ================================================ /* eslint-disable */ function displayColumns(columns, columnsNum) { return columns.slice(0, +columnsNum); } module.exports = { displayColumns: displayColumns, }; ================================================ FILE: miniprogram_npm/@vant/weapp/area/index.wxss ================================================ @import '../common/index.wxss'; ================================================ FILE: miniprogram_npm/@vant/weapp/button/index.d.ts ================================================ export {}; ================================================ FILE: miniprogram_npm/@vant/weapp/button/index.js ================================================ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var component_1 = require("../common/component"); var button_1 = require("../mixins/button"); var version_1 = require("../common/version"); var mixins = [button_1.button]; if ((0, version_1.canIUseFormFieldButton)()) { mixins.push('wx://form-field-button'); } (0, component_1.VantComponent)({ mixins: mixins, classes: ['hover-class', 'loading-class'], data: { baseStyle: '', }, props: { formType: String, icon: String, classPrefix: { type: String, value: 'van-icon', }, plain: Boolean, block: Boolean, round: Boolean, square: Boolean, loading: Boolean, hairline: Boolean, disabled: Boolean, loadingText: String, customStyle: String, loadingType: { type: String, value: 'circular', }, type: { type: String, value: 'default', }, dataset: null, size: { type: String, value: 'normal', }, loadingSize: { type: String, value: '20px', }, color: String, }, methods: { onClick: function (event) { var _this = this; this.$emit('click', event); var _a = this.data, canIUseGetUserProfile = _a.canIUseGetUserProfile, openType = _a.openType, getUserProfileDesc = _a.getUserProfileDesc, lang = _a.lang; if (openType === 'getUserInfo' && canIUseGetUserProfile) { wx.getUserProfile({ desc: getUserProfileDesc || ' ', lang: lang || 'en', complete: function (userProfile) { _this.$emit('getuserinfo', userProfile); }, }); } }, }, }); ================================================ FILE: miniprogram_npm/@vant/weapp/button/index.json ================================================ { "component": true, "usingComponents": { "van-icon": "../icon/index", "van-loading": "../loading/index" } } ================================================ FILE: miniprogram_npm/@vant/weapp/button/index.wxml ================================================ ================================================ FILE: miniprogram_npm/@vant/weapp/button/index.wxs ================================================ /* eslint-disable */ var style = require('../wxs/style.wxs'); function rootStyle(data) { if (!data.color) { return data.customStyle; } var properties = { color: data.plain ? data.color : '#fff', background: data.plain ? null : data.color, }; // hide border when color is linear-gradient if (data.color.indexOf('gradient') !== -1) { properties.border = 0; } else { properties['border-color'] = data.color; } return style([properties, data.customStyle]); } function loadingColor(data) { if (data.plain) { return data.color ? data.color : '#c9c9c9'; } if (data.type === 'default') { return '#c9c9c9'; } return '#fff'; } module.exports = { rootStyle: rootStyle, loadingColor: loadingColor, }; ================================================ FILE: miniprogram_npm/@vant/weapp/button/index.wxss ================================================ @import '../common/index.wxss';.van-button{-webkit-text-size-adjust:100%;align-items:center;-webkit-appearance:none;border-radius:var(--button-border-radius,2px);box-sizing:border-box;display:inline-flex;font-size:var(--button-default-font-size,16px);height:var(--button-default-height,44px);justify-content:center;line-height:var(--button-line-height,20px);padding:0;position:relative;text-align:center;transition:opacity .2s;vertical-align:middle}.van-button:before{background-color:#000;border:inherit;border-color:#000;border-radius:inherit;content:" ";height:100%;left:50%;opacity:0;position:absolute;top:50%;transform:translate(-50%,-50%);width:100%}.van-button:after{border-width:0}.van-button--active:before{opacity:.15}.van-button--unclickable:after{display:none}.van-button--default{background:var(--button-default-background-color,#fff);border:var(--button-border-width,1px) solid var(--button-default-border-color,#ebedf0);color:var(--button-default-color,#323233)}.van-button--primary{background:var(--button-primary-background-color,#07c160);border:var(--button-border-width,1px) solid var(--button-primary-border-color,#07c160);color:var(--button-primary-color,#fff)}.van-button--info{background:var(--button-info-background-color,#1989fa);border:var(--button-border-width,1px) solid var(--button-info-border-color,#1989fa);color:var(--button-info-color,#fff)}.van-button--danger{background:var(--button-danger-background-color,#ee0a24);border:var(--button-border-width,1px) solid var(--button-danger-border-color,#ee0a24);color:var(--button-danger-color,#fff)}.van-button--warning{background:var(--button-warning-background-color,#ff976a);border:var(--button-border-width,1px) solid var(--button-warning-border-color,#ff976a);color:var(--button-warning-color,#fff)}.van-button--plain{background:var(--button-plain-background-color,#fff)}.van-button--plain.van-button--primary{color:var(--button-primary-background-color,#07c160)}.van-button--plain.van-button--info{color:var(--button-info-background-color,#1989fa)}.van-button--plain.van-button--danger{color:var(--button-danger-background-color,#ee0a24)}.van-button--plain.van-button--warning{color:var(--button-warning-background-color,#ff976a)}.van-button--large{height:var(--button-large-height,50px);width:100%}.van-button--normal{font-size:var(--button-normal-font-size,14px);padding:0 15px}.van-button--small{font-size:var(--button-small-font-size,12px);height:var(--button-small-height,30px);min-width:var(--button-small-min-width,60px);padding:0 var(--padding-xs,8px)}.van-button--mini{display:inline-block;font-size:var(--button-mini-font-size,10px);height:var(--button-mini-height,22px);min-width:var(--button-mini-min-width,50px)}.van-button--mini+.van-button--mini{margin-left:5px}.van-button--block{display:flex;width:100%}.van-button--round{border-radius:var(--button-round-border-radius,999px)}.van-button--square{border-radius:0}.van-button--disabled{opacity:var(--button-disabled-opacity,.5)}.van-button__text{display:inline}.van-button__icon+.van-button__text:not(:empty),.van-button__loading-text{margin-left:4px}.van-button__icon{line-height:inherit!important;min-width:1em;vertical-align:top}.van-button--hairline{border-width:0;padding-top:1px}.van-button--hairline:after{border-color:inherit;border-radius:calc(var(--button-border-radius, 2px)*2);border-width:1px}.van-button--hairline.van-button--round:after{border-radius:var(--button-round-border-radius,999px)}.van-button--hairline.van-button--square:after{border-radius:0} ================================================ FILE: miniprogram_npm/@vant/weapp/calendar/calendar.wxml ================================================
{{ computed.getButtonDisabled(type, currentDate, minRange) ? confirmDisabledText : confirmText }}
================================================ FILE: miniprogram_npm/@vant/weapp/calendar/components/header/index.d.ts ================================================ export {}; ================================================ FILE: miniprogram_npm/@vant/weapp/calendar/components/header/index.js ================================================ "use strict"; var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { if (ar || !(i in from)) { if (!ar) ar = Array.prototype.slice.call(from, 0, i); ar[i] = from[i]; } } return to.concat(ar || Array.prototype.slice.call(from)); }; Object.defineProperty(exports, "__esModule", { value: true }); var component_1 = require("../../../common/component"); (0, component_1.VantComponent)({ props: { title: { type: String, value: '日期选择', }, subtitle: String, showTitle: Boolean, showSubtitle: Boolean, firstDayOfWeek: { type: Number, observer: 'initWeekDay', }, }, data: { weekdays: [], }, created: function () { this.initWeekDay(); }, methods: { initWeekDay: function () { var defaultWeeks = ['日', '一', '二', '三', '四', '五', '六']; var firstDayOfWeek = this.data.firstDayOfWeek || 0; this.setData({ weekdays: __spreadArray(__spreadArray([], defaultWeeks.slice(firstDayOfWeek, 7), true), defaultWeeks.slice(0, firstDayOfWeek), true), }); }, onClickSubtitle: function (event) { this.$emit('click-subtitle', event); }, }, }); ================================================ FILE: miniprogram_npm/@vant/weapp/calendar/components/header/index.json ================================================ { "component": true } ================================================ FILE: miniprogram_npm/@vant/weapp/calendar/components/header/index.wxml ================================================ {{ title }} {{ subtitle }} {{ item }} ================================================ FILE: miniprogram_npm/@vant/weapp/calendar/components/header/index.wxss ================================================ @import '../../../common/index.wxss';.van-calendar__header{box-shadow:var(--calendar-header-box-shadow,0 2px 10px hsla(220,1%,50%,.16));flex-shrink:0}.van-calendar__header-subtitle,.van-calendar__header-title{font-weight:var(--font-weight-bold,500);height:var(--calendar-header-title-height,44px);line-height:var(--calendar-header-title-height,44px);text-align:center}.van-calendar__header-title+.van-calendar__header-title,.van-calendar__header-title:empty{display:none}.van-calendar__header-title:empty+.van-calendar__header-title{display:block!important}.van-calendar__weekdays{display:flex}.van-calendar__weekday{flex:1;font-size:var(--calendar-weekdays-font-size,12px);line-height:var(--calendar-weekdays-height,30px);text-align:center} ================================================ FILE: miniprogram_npm/@vant/weapp/calendar/components/month/index.d.ts ================================================ export interface Day { date: Date; type: string; text: number; bottomInfo?: string; } ================================================ FILE: miniprogram_npm/@vant/weapp/calendar/components/month/index.js ================================================ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var component_1 = require("../../../common/component"); var utils_1 = require("../../utils"); (0, component_1.VantComponent)({ props: { date: { type: null, observer: 'setDays', }, type: { type: String, observer: 'setDays', }, color: String, minDate: { type: null, observer: 'setDays', }, maxDate: { type: null, observer: 'setDays', }, showMark: Boolean, rowHeight: null, formatter: { type: null, observer: 'setDays', }, currentDate: { type: null, observer: 'setDays', }, firstDayOfWeek: { type: Number, observer: 'setDays', }, allowSameDay: Boolean, showSubtitle: Boolean, showMonthTitle: Boolean, }, data: { visible: true, days: [], }, methods: { onClick: function (event) { var index = event.currentTarget.dataset.index; var item = this.data.days[index]; if (item.type !== 'disabled') { this.$emit('click', item); } }, setDays: function () { var days = []; var startDate = new Date(this.data.date); var year = startDate.getFullYear(); var month = startDate.getMonth(); var totalDay = (0, utils_1.getMonthEndDay)(startDate.getFullYear(), startDate.getMonth() + 1); for (var day = 1; day <= totalDay; day++) { var date = new Date(year, month, day); var type = this.getDayType(date); var config = { date: date, type: type, text: day, bottomInfo: this.getBottomInfo(type), }; if (this.data.formatter) { config = this.data.formatter(config); } days.push(config); } this.setData({ days: days }); }, getMultipleDayType: function (day) { var currentDate = this.data.currentDate; if (!Array.isArray(currentDate)) { return ''; } var isSelected = function (date) { return currentDate.some(function (item) { return (0, utils_1.compareDay)(item, date) === 0; }); }; if (isSelected(day)) { var prevDay = (0, utils_1.getPrevDay)(day); var nextDay = (0, utils_1.getNextDay)(day); var prevSelected = isSelected(prevDay); var nextSelected = isSelected(nextDay); if (prevSelected && nextSelected) { return 'multiple-middle'; } if (prevSelected) { return 'end'; } return nextSelected ? 'start' : 'multiple-selected'; } return ''; }, getRangeDayType: function (day) { var _a = this.data, currentDate = _a.currentDate, allowSameDay = _a.allowSameDay; if (!Array.isArray(currentDate)) { return ''; } var startDay = currentDate[0], endDay = currentDate[1]; if (!startDay) { return ''; } var compareToStart = (0, utils_1.compareDay)(day, startDay); if (!endDay) { return compareToStart === 0 ? 'start' : ''; } var compareToEnd = (0, utils_1.compareDay)(day, endDay); if (compareToStart === 0 && compareToEnd === 0 && allowSameDay) { return 'start-end'; } if (compareToStart === 0) { return 'start'; } if (compareToEnd === 0) { return 'end'; } if (compareToStart > 0 && compareToEnd < 0) { return 'middle'; } return ''; }, getDayType: function (day) { var _a = this.data, type = _a.type, minDate = _a.minDate, maxDate = _a.maxDate, currentDate = _a.currentDate; if ((0, utils_1.compareDay)(day, minDate) < 0 || (0, utils_1.compareDay)(day, maxDate) > 0) { return 'disabled'; } if (type === 'single') { return (0, utils_1.compareDay)(day, currentDate) === 0 ? 'selected' : ''; } if (type === 'multiple') { return this.getMultipleDayType(day); } /* istanbul ignore else */ if (type === 'range') { return this.getRangeDayType(day); } return ''; }, getBottomInfo: function (type) { if (this.data.type === 'range') { if (type === 'start') { return '开始'; } if (type === 'end') { return '结束'; } if (type === 'start-end') { return '开始/结束'; } } }, }, }); ================================================ FILE: miniprogram_npm/@vant/weapp/calendar/components/month/index.json ================================================ { "component": true } ================================================ FILE: miniprogram_npm/@vant/weapp/calendar/components/month/index.wxml ================================================ {{ computed.formatMonthTitle(date) }} {{ computed.getMark(date) }} {{ item.topInfo }} {{ item.text }} {{ item.bottomInfo }} {{ item.topInfo }} {{ item.text }} {{ item.bottomInfo }} ================================================ FILE: miniprogram_npm/@vant/weapp/calendar/components/month/index.wxs ================================================ /* eslint-disable */ var utils = require('../../utils.wxs'); function getMark(date) { return getDate(date).getMonth() + 1; } var ROW_HEIGHT = 64; function getDayStyle(type, index, date, rowHeight, color, firstDayOfWeek) { var style = []; var current = getDate(date).getDay() || 7; var offset = current < firstDayOfWeek ? (7 - firstDayOfWeek + current) : current === 7 && firstDayOfWeek === 0 ? 0 : (current - firstDayOfWeek); if (index === 0) { style.push(['margin-left', (100 * offset) / 7 + '%']); } if (rowHeight !== ROW_HEIGHT) { style.push(['height', rowHeight + 'px']); } if (color) { if ( type === 'start' || type === 'end' || type === 'start-end' || type === 'multiple-selected' || type === 'multiple-middle' ) { style.push(['background', color]); } else if (type === 'middle') { style.push(['color', color]); } } return style .map(function(item) { return item.join(':'); }) .join(';'); } function formatMonthTitle(date) { date = getDate(date); return date.getFullYear() + '年' + (date.getMonth() + 1) + '月'; } function getMonthStyle(visible, date, rowHeight) { if (!visible) { date = getDate(date); var totalDay = utils.getMonthEndDay( date.getFullYear(), date.getMonth() + 1 ); var offset = getDate(date).getDay(); var padding = Math.ceil((totalDay + offset) / 7) * rowHeight; return 'padding-bottom:' + padding + 'px'; } } module.exports = { getMark: getMark, getDayStyle: getDayStyle, formatMonthTitle: formatMonthTitle, getMonthStyle: getMonthStyle }; ================================================ FILE: miniprogram_npm/@vant/weapp/calendar/components/month/index.wxss ================================================ @import '../../../common/index.wxss';.van-calendar{background-color:var(--calendar-background-color,#fff);display:flex;flex-direction:column;height:100%}.van-calendar__month-title{font-size:var(--calendar-month-title-font-size,14px);font-weight:var(--font-weight-bold,500);height:var(--calendar-header-title-height,44px);line-height:var(--calendar-header-title-height,44px);text-align:center}.van-calendar__days{display:flex;flex-wrap:wrap;position:relative;-webkit-user-select:none;user-select:none}.van-calendar__month-mark{color:var(--calendar-month-mark-color,rgba(242,243,245,.8));font-size:var(--calendar-month-mark-font-size,160px);left:50%;pointer-events:none;position:absolute;top:50%;transform:translate(-50%,-50%);z-index:0}.van-calendar__day,.van-calendar__selected-day{align-items:center;display:flex;justify-content:center;text-align:center}.van-calendar__day{font-size:var(--calendar-day-font-size,16px);height:var(--calendar-day-height,64px);position:relative;width:14.285%}.van-calendar__day--end,.van-calendar__day--multiple-middle,.van-calendar__day--multiple-selected,.van-calendar__day--start,.van-calendar__day--start-end{background-color:var(--calendar-range-edge-background-color,#ee0a24);color:var(--calendar-range-edge-color,#fff)}.van-calendar__day--start{border-radius:4px 0 0 4px}.van-calendar__day--end{border-radius:0 4px 4px 0}.van-calendar__day--multiple-selected,.van-calendar__day--start-end{border-radius:4px}.van-calendar__day--middle{color:var(--calendar-range-middle-color,#ee0a24)}.van-calendar__day--middle:after{background-color:currentColor;bottom:0;content:"";left:0;opacity:var(--calendar-range-middle-background-opacity,.1);position:absolute;right:0;top:0}.van-calendar__day--disabled{color:var(--calendar-day-disabled-color,#c8c9cc);cursor:default}.van-calendar__bottom-info,.van-calendar__top-info{font-size:var(--calendar-info-font-size,10px);left:0;line-height:var(--calendar-info-line-height,14px);position:absolute;right:0}@media (max-width:350px){.van-calendar__bottom-info,.van-calendar__top-info{font-size:9px}}.van-calendar__top-info{top:6px}.van-calendar__bottom-info{bottom:6px}.van-calendar__selected-day{background-color:var(--calendar-selected-day-background-color,#ee0a24);border-radius:4px;color:var(--calendar-selected-day-color,#fff);height:var(--calendar-selected-day-size,54px);width:var(--calendar-selected-day-size,54px)} ================================================ FILE: miniprogram_npm/@vant/weapp/calendar/index.d.ts ================================================ export {}; ================================================ FILE: miniprogram_npm/@vant/weapp/calendar/index.js ================================================ "use strict"; var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { if (ar || !(i in from)) { if (!ar) ar = Array.prototype.slice.call(from, 0, i); ar[i] = from[i]; } } return to.concat(ar || Array.prototype.slice.call(from)); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); var component_1 = require("../common/component"); var utils_1 = require("./utils"); var toast_1 = __importDefault(require("../toast/toast")); var utils_2 = require("../common/utils"); var initialMinDate = (0, utils_1.getToday)().getTime(); var initialMaxDate = (function () { var now = (0, utils_1.getToday)(); return new Date(now.getFullYear(), now.getMonth() + 6, now.getDate()).getTime(); })(); var getTime = function (date) { return date instanceof Date ? date.getTime() : date; }; (0, component_1.VantComponent)({ props: { title: { type: String, value: '日期选择', }, color: String, show: { type: Boolean, observer: function (val) { if (val) { this.initRect(); this.scrollIntoView(); } }, }, formatter: null, confirmText: { type: String, value: '确定', }, confirmDisabledText: { type: String, value: '确定', }, rangePrompt: String, showRangePrompt: { type: Boolean, value: true, }, defaultDate: { type: null, value: (0, utils_1.getToday)().getTime(), observer: function (val) { this.setData({ currentDate: val }); this.scrollIntoView(); }, }, allowSameDay: Boolean, type: { type: String, value: 'single', observer: 'reset', }, minDate: { type: Number, value: initialMinDate, }, maxDate: { type: Number, value: initialMaxDate, }, position: { type: String, value: 'bottom', }, rowHeight: { type: null, value: utils_1.ROW_HEIGHT, }, round: { type: Boolean, value: true, }, poppable: { type: Boolean, value: true, }, showMark: { type: Boolean, value: true, }, showTitle: { type: Boolean, value: true, }, showConfirm: { type: Boolean, value: true, }, showSubtitle: { type: Boolean, value: true, }, safeAreaInsetBottom: { type: Boolean, value: true, }, closeOnClickOverlay: { type: Boolean, value: true, }, maxRange: { type: null, value: null, }, minRange: { type: Number, value: 1, }, firstDayOfWeek: { type: Number, value: 0, }, readonly: Boolean, rootPortal: { type: Boolean, value: false, }, }, data: { subtitle: '', currentDate: null, scrollIntoView: '', }, watch: { minDate: function () { this.initRect(); }, maxDate: function () { this.initRect(); }, }, created: function () { this.setData({ currentDate: this.getInitialDate(this.data.defaultDate), }); }, mounted: function () { if (this.data.show || !this.data.poppable) { this.initRect(); this.scrollIntoView(); } }, methods: { reset: function () { this.setData({ currentDate: this.getInitialDate(this.data.defaultDate) }); this.scrollIntoView(); }, initRect: function () { var _this = this; if (this.contentObserver != null) { this.contentObserver.disconnect(); } var contentObserver = this.createIntersectionObserver({ thresholds: [0, 0.1, 0.9, 1], observeAll: true, }); this.contentObserver = contentObserver; contentObserver.relativeTo('.van-calendar__body'); contentObserver.observe('.month', function (res) { if (res.boundingClientRect.top <= res.relativeRect.top) { // @ts-ignore _this.setData({ subtitle: (0, utils_1.formatMonthTitle)(res.dataset.date) }); } }); }, limitDateRange: function (date, minDate, maxDate) { if (minDate === void 0) { minDate = null; } if (maxDate === void 0) { maxDate = null; } minDate = minDate || this.data.minDate; maxDate = maxDate || this.data.maxDate; if ((0, utils_1.compareDay)(date, minDate) === -1) { return minDate; } if ((0, utils_1.compareDay)(date, maxDate) === 1) { return maxDate; } return date; }, getInitialDate: function (defaultDate) { var _this = this; if (defaultDate === void 0) { defaultDate = null; } var _a = this.data, type = _a.type, minDate = _a.minDate, maxDate = _a.maxDate, allowSameDay = _a.allowSameDay; if (!defaultDate) return []; var now = (0, utils_1.getToday)().getTime(); if (type === 'range') { if (!Array.isArray(defaultDate)) { defaultDate = []; } var _b = defaultDate || [], startDay = _b[0], endDay = _b[1]; var startDate = getTime(startDay || now); var start = this.limitDateRange(startDate, minDate, allowSameDay ? startDate : (0, utils_1.getPrevDay)(new Date(maxDate)).getTime()); var date = getTime(endDay || now); var end = this.limitDateRange(date, allowSameDay ? date : (0, utils_1.getNextDay)(new Date(minDate)).getTime()); return [start, end]; } if (type === 'multiple') { if (Array.isArray(defaultDate)) { return defaultDate.map(function (date) { return _this.limitDateRange(date); }); } return [this.limitDateRange(now)]; } if (!defaultDate || Array.isArray(defaultDate)) { defaultDate = now; } return this.limitDateRange(defaultDate); }, scrollIntoView: function () { var _this = this; (0, utils_2.requestAnimationFrame)(function () { var _a = _this.data, currentDate = _a.currentDate, type = _a.type, show = _a.show, poppable = _a.poppable, minDate = _a.minDate, maxDate = _a.maxDate; if (!currentDate) return; // @ts-ignore var targetDate = type === 'single' ? currentDate : currentDate[0]; var displayed = show || !poppable; if (!targetDate || !displayed) { return; } var months = (0, utils_1.getMonths)(minDate, maxDate); months.some(function (month, index) { if ((0, utils_1.compareMonth)(month, targetDate) === 0) { _this.setData({ scrollIntoView: "month".concat(index) }); return true; } return false; }); }); }, onOpen: function () { this.$emit('open'); }, onOpened: function () { this.$emit('opened'); }, onClose: function () { this.$emit('close'); }, onClosed: function () { this.$emit('closed'); }, onClickDay: function (event) { if (this.data.readonly) { return; } var date = event.detail.date; var _a = this.data, type = _a.type, currentDate = _a.currentDate, allowSameDay = _a.allowSameDay; if (type === 'range') { // @ts-ignore var startDay_1 = currentDate[0], endDay = currentDate[1]; if (startDay_1 && !endDay) { var compareToStart = (0, utils_1.compareDay)(date, startDay_1); if (compareToStart === 1) { var days_1 = this.selectComponent('.month').data.days; days_1.some(function (day, index) { var isDisabled = day.type === 'disabled' && getTime(startDay_1) < getTime(day.date) && getTime(day.date) < getTime(date); if (isDisabled) { (date = days_1[index - 1].date); } return isDisabled; }); this.select([startDay_1, date], true); } else if (compareToStart === -1) { this.select([date, null]); } else if (allowSameDay) { this.select([date, date], true); } } else { this.select([date, null]); } } else if (type === 'multiple') { var selectedIndex_1; // @ts-ignore var selected = currentDate.some(function (dateItem, index) { var equal = (0, utils_1.compareDay)(dateItem, date) === 0; if (equal) { selectedIndex_1 = index; } return equal; }); if (selected) { // @ts-ignore var cancelDate = currentDate.splice(selectedIndex_1, 1); this.setData({ currentDate: currentDate }); this.unselect(cancelDate); } else { // @ts-ignore this.select(__spreadArray(__spreadArray([], currentDate, true), [date], false)); } } else { this.select(date, true); } }, unselect: function (dateArray) { var date = dateArray[0]; if (date) { this.$emit('unselect', (0, utils_1.copyDates)(date)); } }, select: function (date, complete) { if (complete && this.data.type === 'range') { var valid = this.checkRange(date); if (!valid) { // auto selected to max range if showConfirm if (this.data.showConfirm) { this.emit([ date[0], (0, utils_1.getDayByOffset)(date[0], this.data.maxRange - 1), ]); } else { this.emit(date); } return; } } this.emit(date); if (complete && !this.data.showConfirm) { this.onConfirm(); } }, emit: function (date) { this.setData({ currentDate: Array.isArray(date) ? date.map(getTime) : getTime(date), }); this.$emit('select', (0, utils_1.copyDates)(date)); }, checkRange: function (date) { var _a = this.data, maxRange = _a.maxRange, rangePrompt = _a.rangePrompt, showRangePrompt = _a.showRangePrompt; if (maxRange && (0, utils_1.calcDateNum)(date) > maxRange) { if (showRangePrompt) { (0, toast_1.default)({ context: this, message: rangePrompt || "\u9009\u62E9\u5929\u6570\u4E0D\u80FD\u8D85\u8FC7 ".concat(maxRange, " \u5929"), }); } this.$emit('over-range'); return false; } return true; }, onConfirm: function () { var _this = this; if (this.data.type === 'range' && !this.checkRange(this.data.currentDate)) { return; } wx.nextTick(function () { // @ts-ignore _this.$emit('confirm', (0, utils_1.copyDates)(_this.data.currentDate)); }); }, onClickSubtitle: function (event) { this.$emit('click-subtitle', event); }, }, }); ================================================ FILE: miniprogram_npm/@vant/weapp/calendar/index.json ================================================ { "component": true, "usingComponents": { "header": "./components/header/index", "month": "./components/month/index", "van-button": "../button/index", "van-popup": "../popup/index", "van-toast": "../toast/index" } } ================================================ FILE: miniprogram_npm/@vant/weapp/calendar/index.wxml ================================================ ================================================ FILE: miniprogram_npm/@vant/weapp/calendar/index.wxs ================================================ /* eslint-disable */ var utils = require('./utils.wxs'); function getMonths(minDate, maxDate) { var months = []; var cursor = getDate(minDate); cursor.setDate(1); do { months.push(cursor.getTime()); cursor.setMonth(cursor.getMonth() + 1); } while (utils.compareMonth(cursor, getDate(maxDate)) !== 1); return months; } function getButtonDisabled(type, currentDate, minRange) { if (currentDate == null) { return true; } if (type === 'range') { return !currentDate[0] || !currentDate[1]; } if (type === 'multiple') { return currentDate.length < minRange; } return !currentDate; } module.exports = { getMonths: getMonths, getButtonDisabled: getButtonDisabled }; ================================================ FILE: miniprogram_npm/@vant/weapp/calendar/index.wxss ================================================ @import '../common/index.wxss';.van-calendar{background-color:var(--calendar-background-color,#fff);display:flex;flex-direction:column;height:var(--calendar-height,100%)}.van-calendar__close-icon{top:11px}.van-calendar__popup--bottom,.van-calendar__popup--top{height:var(--calendar-popup-height,90%)}.van-calendar__popup--left,.van-calendar__popup--right{height:100%}.van-calendar__body{-webkit-overflow-scrolling:touch;flex:1;overflow:auto}.van-calendar__footer{flex-shrink:0;padding:0 var(--padding-md,16px)}.van-calendar__footer--safe-area-inset-bottom{padding-bottom:env(safe-area-inset-bottom)}.van-calendar__footer+.van-calendar__footer,.van-calendar__footer:empty{display:none}.van-calendar__footer:empty+.van-calendar__footer{display:block!important}.van-calendar__confirm{height:var(--calendar-confirm-button-height,36px)!important;line-height:var(--calendar-confirm-button-line-height,34px)!important;margin:var(--calendar-confirm-button-margin,7px 0)!important} ================================================ FILE: miniprogram_npm/@vant/weapp/calendar/utils.d.ts ================================================ export declare const ROW_HEIGHT = 64; export declare function formatMonthTitle(date: Date): string; export declare function compareMonth(date1: Date | number, date2: Date | number): 0 | 1 | -1; export declare function compareDay(day1: Date | number, day2: Date | number): 0 | 1 | -1; export declare function getDayByOffset(date: Date, offset: number): Date; export declare function getPrevDay(date: Date): Date; export declare function getNextDay(date: Date): Date; export declare function getToday(): Date; export declare function calcDateNum(date: [Date, Date]): number; export declare function copyDates(dates: Date | Date[]): Date | Date[]; export declare function getMonthEndDay(year: number, month: number): number; export declare function getMonths(minDate: number, maxDate: number): number[]; ================================================ FILE: miniprogram_npm/@vant/weapp/calendar/utils.js ================================================ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getMonths = exports.getMonthEndDay = exports.copyDates = exports.calcDateNum = exports.getToday = exports.getNextDay = exports.getPrevDay = exports.getDayByOffset = exports.compareDay = exports.compareMonth = exports.formatMonthTitle = exports.ROW_HEIGHT = void 0; exports.ROW_HEIGHT = 64; function formatMonthTitle(date) { if (!(date instanceof Date)) { date = new Date(date); } return "".concat(date.getFullYear(), "\u5E74").concat(date.getMonth() + 1, "\u6708"); } exports.formatMonthTitle = formatMonthTitle; function compareMonth(date1, date2) { if (!(date1 instanceof Date)) { date1 = new Date(date1); } if (!(date2 instanceof Date)) { date2 = new Date(date2); } var year1 = date1.getFullYear(); var year2 = date2.getFullYear(); var month1 = date1.getMonth(); var month2 = date2.getMonth(); if (year1 === year2) { return month1 === month2 ? 0 : month1 > month2 ? 1 : -1; } return year1 > year2 ? 1 : -1; } exports.compareMonth = compareMonth; function compareDay(day1, day2) { if (!(day1 instanceof Date)) { day1 = new Date(day1); } if (!(day2 instanceof Date)) { day2 = new Date(day2); } var compareMonthResult = compareMonth(day1, day2); if (compareMonthResult === 0) { var date1 = day1.getDate(); var date2 = day2.getDate(); return date1 === date2 ? 0 : date1 > date2 ? 1 : -1; } return compareMonthResult; } exports.compareDay = compareDay; function getDayByOffset(date, offset) { date = new Date(date); date.setDate(date.getDate() + offset); return date; } exports.getDayByOffset = getDayByOffset; function getPrevDay(date) { return getDayByOffset(date, -1); } exports.getPrevDay = getPrevDay; function getNextDay(date) { return getDayByOffset(date, 1); } exports.getNextDay = getNextDay; function getToday() { var today = new Date(); today.setHours(0, 0, 0, 0); return today; } exports.getToday = getToday; function calcDateNum(date) { var day1 = new Date(date[0]).getTime(); var day2 = new Date(date[1]).getTime(); return (day2 - day1) / (1000 * 60 * 60 * 24) + 1; } exports.calcDateNum = calcDateNum; function copyDates(dates) { if (Array.isArray(dates)) { return dates.map(function (date) { if (date === null) { return date; } return new Date(date); }); } return new Date(dates); } exports.copyDates = copyDates; function getMonthEndDay(year, month) { return 32 - new Date(year, month - 1, 32).getDate(); } exports.getMonthEndDay = getMonthEndDay; function getMonths(minDate, maxDate) { var months = []; var cursor = new Date(minDate); cursor.setDate(1); do { months.push(cursor.getTime()); cursor.setMonth(cursor.getMonth() + 1); } while (compareMonth(cursor, maxDate) !== 1); return months; } exports.getMonths = getMonths; ================================================ FILE: miniprogram_npm/@vant/weapp/calendar/utils.wxs ================================================ /* eslint-disable */ function getMonthEndDay(year, month) { return 32 - getDate(year, month - 1, 32).getDate(); } function compareMonth(date1, date2) { date1 = getDate(date1); date2 = getDate(date2); var year1 = date1.getFullYear(); var year2 = date2.getFullYear(); var month1 = date1.getMonth(); var month2 = date2.getMonth(); if (year1 === year2) { return month1 === month2 ? 0 : month1 > month2 ? 1 : -1; } return year1 > year2 ? 1 : -1; } module.exports = { getMonthEndDay: getMonthEndDay, compareMonth: compareMonth }; ================================================ FILE: miniprogram_npm/@vant/weapp/card/index.d.ts ================================================ export {}; ================================================ FILE: miniprogram_npm/@vant/weapp/card/index.js ================================================ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var link_1 = require("../mixins/link"); var component_1 = require("../common/component"); (0, component_1.VantComponent)({ classes: [ 'num-class', 'desc-class', 'thumb-class', 'title-class', 'price-class', 'origin-price-class', ], mixins: [link_1.link], props: { tag: String, num: String, desc: String, thumb: String, title: String, price: { type: String, observer: 'updatePrice', }, centered: Boolean, lazyLoad: Boolean, thumbLink: String, originPrice: String, thumbMode: { type: String, value: 'aspectFit', }, currency: { type: String, value: '¥', }, }, methods: { updatePrice: function () { var price = this.data.price; var priceArr = price.toString().split('.'); this.setData({ integerStr: priceArr[0], decimalStr: priceArr[1] ? ".".concat(priceArr[1]) : '', }); }, onClickThumb: function () { this.jumpLink('thumbLink'); }, }, }); ================================================ FILE: miniprogram_npm/@vant/weapp/card/index.json ================================================ { "component": true, "usingComponents": { "van-tag": "../tag/index" } } ================================================ FILE: miniprogram_npm/@vant/weapp/card/index.wxml ================================================ {{ tag }} {{ title }} {{ desc }} {{ currency }} {{ integerStr }} {{ decimalStr }} {{ currency }} {{ originPrice }} x {{ num }} ================================================ FILE: miniprogram_npm/@vant/weapp/card/index.wxss ================================================ @import '../common/index.wxss';.van-card{background-color:var(--card-background-color,#fafafa);box-sizing:border-box;color:var(--card-text-color,#323233);font-size:var(--card-font-size,12px);padding:var(--card-padding,8px 16px);position:relative}.van-card__header{display:flex}.van-card__header--center{align-items:center;justify-content:center}.van-card__thumb{flex:none;height:var(--card-thumb-size,88px);margin-right:var(--padding-xs,8px);position:relative;width:var(--card-thumb-size,88px)}.van-card__thumb:empty{display:none}.van-card__img{border-radius:8px;height:100%;width:100%}.van-card__content{display:flex;flex:1;flex-direction:column;justify-content:space-between;min-height:var(--card-thumb-size,88px);min-width:0;position:relative}.van-card__content--center{justify-content:center}.van-card__desc,.van-card__title{word-wrap:break-word}.van-card__title{font-weight:700;line-height:var(--card-title-line-height,16px)}.van-card__desc{color:var(--card-desc-color,#646566);line-height:var(--card-desc-line-height,20px)}.van-card__bottom{line-height:20px}.van-card__price{color:var(--card-price-color,#ee0a24);display:inline-block;font-size:var(--card-price-font-size,12px);font-weight:700}.van-card__price-integer{font-size:var(--card-price-integer-font-size,16px)}.van-card__price-decimal,.van-card__price-integer{font-family:var(--card-price-font-family,Avenir-Heavy,PingFang SC,Helvetica Neue,Arial,sans-serif)}.van-card__origin-price{color:var(--card-origin-price-color,#646566);display:inline-block;font-size:var(--card-origin-price-font-size,10px);margin-left:5px;text-decoration:line-through}.van-card__num{float:right}.van-card__tag{left:0;position:absolute!important;top:2px}.van-card__footer{flex:none;text-align:right;width:100%} ================================================ FILE: miniprogram_npm/@vant/weapp/cascader/index.d.ts ================================================ export {}; ================================================ FILE: miniprogram_npm/@vant/weapp/cascader/index.js ================================================ "use strict"; var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { if (ar || !(i in from)) { if (!ar) ar = Array.prototype.slice.call(from, 0, i); ar[i] = from[i]; } } return to.concat(ar || Array.prototype.slice.call(from)); }; Object.defineProperty(exports, "__esModule", { value: true }); var component_1 = require("../common/component"); var FieldName; (function (FieldName) { FieldName["TEXT"] = "text"; FieldName["VALUE"] = "value"; FieldName["CHILDREN"] = "children"; })(FieldName || (FieldName = {})); var defaultFieldNames = { text: FieldName.TEXT, value: FieldName.VALUE, children: FieldName.CHILDREN, }; (0, component_1.VantComponent)({ props: { title: String, value: { type: String, }, placeholder: { type: String, value: '请选择', }, activeColor: { type: String, value: '#1989fa', }, options: { type: Array, value: [], }, swipeable: { type: Boolean, value: false, }, closeable: { type: Boolean, value: true, }, ellipsis: { type: Boolean, value: true, }, showHeader: { type: Boolean, value: true, }, closeIcon: { type: String, value: 'cross', }, fieldNames: { type: Object, value: defaultFieldNames, observer: 'updateFieldNames', }, useTitleSlot: Boolean, }, data: { tabs: [], activeTab: 0, textKey: FieldName.TEXT, valueKey: FieldName.VALUE, childrenKey: FieldName.CHILDREN, innerValue: '', }, watch: { options: function () { this.updateTabs(); }, value: function (newVal) { this.updateValue(newVal); }, }, created: function () { this.updateTabs(); }, methods: { updateValue: function (val) { var _this = this; if (val !== undefined) { var values = this.data.tabs.map(function (tab) { return tab.selected && tab.selected[_this.data.valueKey]; }); if (values.indexOf(val) > -1) { return; } } this.innerValue = val; this.updateTabs(); }, updateFieldNames: function () { var _a = this.data.fieldNames || defaultFieldNames, _b = _a.text, text = _b === void 0 ? 'text' : _b, _c = _a.value, value = _c === void 0 ? 'value' : _c, _d = _a.children, children = _d === void 0 ? 'children' : _d; this.setData({ textKey: text, valueKey: value, childrenKey: children, }); }, getSelectedOptionsByValue: function (options, value) { for (var i = 0; i < options.length; i++) { var option = options[i]; if (option[this.data.valueKey] === value) { return [option]; } if (option[this.data.childrenKey]) { var selectedOptions = this.getSelectedOptionsByValue(option[this.data.childrenKey], value); if (selectedOptions) { return __spreadArray([option], selectedOptions, true); } } } }, updateTabs: function () { var _this = this; var options = this.data.options; var innerValue = this.innerValue; if (!options.length) { return; } if (innerValue !== undefined) { var selectedOptions = this.getSelectedOptionsByValue(options, innerValue); if (selectedOptions) { var optionsCursor_1 = options; var tabs_1 = selectedOptions.map(function (option) { var tab = { options: optionsCursor_1, selected: option, }; var next = optionsCursor_1.find(function (item) { return item[_this.data.valueKey] === option[_this.data.valueKey]; }); if (next) { optionsCursor_1 = next[_this.data.childrenKey]; } return tab; }); if (optionsCursor_1) { tabs_1.push({ options: optionsCursor_1, selected: null, }); } this.setData({ tabs: tabs_1, }); wx.nextTick(function () { _this.setData({ activeTab: tabs_1.length - 1, }); }); return; } } this.setData({ tabs: [ { options: options, selected: null, }, ], activeTab: 0, }); }, onClose: function () { this.$emit('close'); }, onClickTab: function (e) { var _a = e.detail, tabIndex = _a.index, title = _a.title; this.$emit('click-tab', { title: title, tabIndex: tabIndex }); this.setData({ activeTab: tabIndex, }); }, // 选中 onSelect: function (e) { var _this = this; var _a = e.currentTarget.dataset, option = _a.option, tabIndex = _a.tabIndex; if (option && option.disabled) { return; } var _b = this.data, valueKey = _b.valueKey, childrenKey = _b.childrenKey; var tabs = this.data.tabs; tabs[tabIndex].selected = option; if (tabs.length > tabIndex + 1) { tabs = tabs.slice(0, tabIndex + 1); } if (option[childrenKey]) { var nextTab = { options: option[childrenKey], selected: null, }; if (tabs[tabIndex + 1]) { tabs[tabIndex + 1] = nextTab; } else { tabs.push(nextTab); } wx.nextTick(function () { _this.setData({ activeTab: tabIndex + 1, }); }); } this.setData({ tabs: tabs, }); var selectedOptions = tabs.map(function (tab) { return tab.selected; }).filter(Boolean); var value = option[valueKey]; var params = { value: value, tabIndex: tabIndex, selectedOptions: selectedOptions, }; this.innerValue = value; this.$emit('change', params); if (!option[childrenKey]) { this.$emit('finish', params); } }, }, }); ================================================ FILE: miniprogram_npm/@vant/weapp/cascader/index.json ================================================ { "component": true, "usingComponents": { "van-icon": "../icon/index", "van-tab": "../tab/index", "van-tabs": "../tabs/index" } } ================================================ FILE: miniprogram_npm/@vant/weapp/cascader/index.wxml ================================================ {{ title }} {{ option[textKey] }} ================================================ FILE: miniprogram_npm/@vant/weapp/cascader/index.wxs ================================================ var utils = require('../wxs/utils.wxs'); var style = require('../wxs/style.wxs'); function isSelected(tab, valueKey, option) { return tab.selected && tab.selected[valueKey] === option[valueKey] } function optionClass(tab, valueKey, option) { return utils.bem('cascader__option', { selected: isSelected(tab, valueKey, option), disabled: option.disabled }) } function optionStyle(data) { var color = data.option.color || (isSelected(data.tab, data.valueKey, data.option) ? data.activeColor : undefined); return style({ color }); } module.exports = { isSelected: isSelected, optionClass: optionClass, optionStyle: optionStyle, }; ================================================ FILE: miniprogram_npm/@vant/weapp/cascader/index.wxss ================================================ @import '../common/index.wxss';.van-cascader__header{align-items:center;display:flex;height:48px;justify-content:space-between;padding:0 16px}.van-cascader__title{font-size:16px;font-weight:600;line-height:20px}.van-cascader__close-icon{color:#c8c9cc;font-size:22px;height:22px}.van-cascader__tabs-wrap{height:48px!important;padding:0 8px}.van-cascader__tab{color:#323233!important;flex:none!important;font-weight:600!important;padding:0 8px!important}.van-cascader__tab--unselected{color:#969799!important;font-weight:400!important}.van-cascader__option{align-items:center;cursor:pointer;display:flex;font-size:14px;justify-content:space-between;line-height:20px;padding:10px 16px}.van-cascader__option:active{background-color:#f2f3f5}.van-cascader__option--selected{color:#1989fa;font-weight:600}.van-cascader__option--disabled{color:#c8c9cc;cursor:not-allowed}.van-cascader__option--disabled:active{background-color:initial}.van-cascader__options{-webkit-overflow-scrolling:touch;box-sizing:border-box;height:384px;overflow-y:auto;padding-top:6px} ================================================ FILE: miniprogram_npm/@vant/weapp/cell/index.d.ts ================================================ export {}; ================================================ FILE: miniprogram_npm/@vant/weapp/cell/index.js ================================================ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var link_1 = require("../mixins/link"); var component_1 = require("../common/component"); (0, component_1.VantComponent)({ classes: [ 'title-class', 'label-class', 'value-class', 'right-icon-class', 'hover-class', ], mixins: [link_1.link], props: { title: null, value: null, icon: String, size: String, label: String, center: Boolean, isLink: Boolean, required: Boolean, clickable: Boolean, titleWidth: String, customStyle: String, arrowDirection: String, useLabelSlot: Boolean, border: { type: Boolean, value: true, }, titleStyle: String, }, methods: { onClick: function (event) { this.$emit('click', event.detail); this.jumpLink(); }, }, }); ================================================ FILE: miniprogram_npm/@vant/weapp/cell/index.json ================================================ { "component": true, "usingComponents": { "van-icon": "../icon/index" } } ================================================ FILE: miniprogram_npm/@vant/weapp/cell/index.wxml ================================================ {{ title }} {{ label }} {{ value }} ================================================ FILE: miniprogram_npm/@vant/weapp/cell/index.wxs ================================================ /* eslint-disable */ var style = require('../wxs/style.wxs'); var addUnit = require('../wxs/add-unit.wxs'); function titleStyle(data) { return style([ { 'max-width': addUnit(data.titleWidth), 'min-width': addUnit(data.titleWidth), }, data.titleStyle, ]); } module.exports = { titleStyle: titleStyle, }; ================================================ FILE: miniprogram_npm/@vant/weapp/cell/index.wxss ================================================ @import '../common/index.wxss';.van-cell{background-color:var(--cell-background-color,#fff);box-sizing:border-box;color:var(--cell-text-color,#323233);display:flex;font-size:var(--cell-font-size,14px);line-height:var(--cell-line-height,24px);padding:var(--cell-vertical-padding,10px) var(--cell-horizontal-padding,16px);position:relative;width:100%}.van-cell:after{border-bottom:1px solid #ebedf0;bottom:0;box-sizing:border-box;content:" ";left:16px;pointer-events:none;position:absolute;right:16px;transform:scaleY(.5);transform-origin:center}.van-cell--borderless:after{display:none}.van-cell-group{background-color:var(--cell-background-color,#fff)}.van-cell__label{color:var(--cell-label-color,#969799);font-size:var(--cell-label-font-size,12px);line-height:var(--cell-label-line-height,18px);margin-top:var(--cell-label-margin-top,3px)}.van-cell__value{color:var(--cell-value-color,#969799);overflow:hidden;text-align:right;vertical-align:middle}.van-cell__title,.van-cell__value{flex:1}.van-cell__title:empty,.van-cell__value:empty{display:none}.van-cell__left-icon-wrap,.van-cell__right-icon-wrap{align-items:center;display:flex;font-size:var(--cell-icon-size,16px);height:var(--cell-line-height,24px)}.van-cell__left-icon-wrap{margin-right:var(--padding-base,4px)}.van-cell__right-icon-wrap{color:var(--cell-right-icon-color,#969799);margin-left:var(--padding-base,4px)}.van-cell__left-icon{vertical-align:middle}.van-cell__left-icon,.van-cell__right-icon{line-height:var(--cell-line-height,24px)}.van-cell--clickable.van-cell--hover{background-color:var(--cell-active-color,#f2f3f5)}.van-cell--required{overflow:visible}.van-cell--required:before{color:var(--cell-required-color,#ee0a24);content:"*";font-size:var(--cell-font-size,14px);left:var(--padding-xs,8px);position:absolute}.van-cell--center{align-items:center}.van-cell--large{padding-bottom:var(--cell-large-vertical-padding,12px);padding-top:var(--cell-large-vertical-padding,12px)}.van-cell--large .van-cell__title{font-size:var(--cell-large-title-font-size,16px)}.van-cell--large .van-cell__value{font-size:var(--cell-large-value-font-size,16px)}.van-cell--large .van-cell__label{font-size:var(--cell-large-label-font-size,14px)} ================================================ FILE: miniprogram_npm/@vant/weapp/cell-group/index.d.ts ================================================ export {}; ================================================ FILE: miniprogram_npm/@vant/weapp/cell-group/index.js ================================================ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var component_1 = require("../common/component"); (0, component_1.VantComponent)({ props: { title: String, border: { type: Boolean, value: true, }, inset: Boolean, }, }); ================================================ FILE: miniprogram_npm/@vant/weapp/cell-group/index.json ================================================ { "component": true } ================================================ FILE: miniprogram_npm/@vant/weapp/cell-group/index.wxml ================================================ {{ title }} ================================================ FILE: miniprogram_npm/@vant/weapp/cell-group/index.wxss ================================================ @import '../common/index.wxss';.van-cell-group--inset{border-radius:var(--cell-group-inset-border-radius,8px);margin:var(--cell-group-inset-padding,0 16px);overflow:hidden}.van-cell-group__title{color:var(--cell-group-title-color,#969799);font-size:var(--cell-group-title-font-size,14px);line-height:var(--cell-group-title-line-height,16px);padding:var(--cell-group-title-padding,16px 16px 8px)}.van-cell-group__title--inset{padding:var(--cell-group-inset-title-padding,16px 16px 8px 32px)} ================================================ FILE: miniprogram_npm/@vant/weapp/checkbox/index.d.ts ================================================ export {}; ================================================ FILE: miniprogram_npm/@vant/weapp/checkbox/index.js ================================================ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var relation_1 = require("../common/relation"); var component_1 = require("../common/component"); function emit(target, value) { target.$emit('input', value); target.$emit('change', value); } (0, component_1.VantComponent)({ field: true, relation: (0, relation_1.useParent)('checkbox-group'), classes: ['icon-class', 'label-class'], props: { value: Boolean, disabled: Boolean, useIconSlot: Boolean, checkedColor: String, labelPosition: { type: String, value: 'right', }, labelDisabled: Boolean, shape: { type: String, value: 'round', }, iconSize: { type: null, value: 20, }, }, data: { parentDisabled: false, direction: 'vertical', }, methods: { emitChange: function (value) { if (this.parent) { this.setParentValue(this.parent, value); } else { emit(this, value); } }, toggle: function () { var _a = this.data, parentDisabled = _a.parentDisabled, disabled = _a.disabled, value = _a.value; if (!disabled && !parentDisabled) { this.emitChange(!value); } }, onClickLabel: function () { var _a = this.data, labelDisabled = _a.labelDisabled, parentDisabled = _a.parentDisabled, disabled = _a.disabled, value = _a.value; if (!disabled && !labelDisabled && !parentDisabled) { this.emitChange(!value); } }, setParentValue: function (parent, value) { var parentValue = parent.data.value.slice(); var name = this.data.name; var max = parent.data.max; if (value) { if (max && parentValue.length >= max) { return; } if (parentValue.indexOf(name) === -1) { parentValue.push(name); emit(parent, parentValue); } } else { var index = parentValue.indexOf(name); if (index !== -1) { parentValue.splice(index, 1); emit(parent, parentValue); } } }, }, }); ================================================ FILE: miniprogram_npm/@vant/weapp/checkbox/index.json ================================================ { "component": true, "usingComponents": { "van-icon": "../icon/index" } } ================================================ FILE: miniprogram_npm/@vant/weapp/checkbox/index.wxml ================================================ ================================================ FILE: miniprogram_npm/@vant/weapp/checkbox/index.wxs ================================================ /* eslint-disable */ var style = require('../wxs/style.wxs'); var addUnit = require('../wxs/add-unit.wxs'); function iconStyle(checkedColor, value, disabled, parentDisabled, iconSize) { var styles = { 'font-size': addUnit(iconSize), }; if (checkedColor && value && !disabled && !parentDisabled) { styles['border-color'] = checkedColor; styles['background-color'] = checkedColor; } return style(styles); } module.exports = { iconStyle: iconStyle, }; ================================================ FILE: miniprogram_npm/@vant/weapp/checkbox/index.wxss ================================================ @import '../common/index.wxss';.van-checkbox{align-items:center;display:flex;overflow:hidden;-webkit-user-select:none;user-select:none}.van-checkbox--horizontal{margin-right:12px}.van-checkbox__icon-wrap,.van-checkbox__label{line-height:var(--checkbox-size,20px)}.van-checkbox__icon-wrap{flex:none}.van-checkbox__icon{align-items:center;border:1px solid var(--checkbox-border-color,#c8c9cc);box-sizing:border-box;color:transparent;display:flex;font-size:var(--checkbox-size,20px);height:1em;justify-content:center;text-align:center;transition-duration:var(--checkbox-transition-duration,.2s);transition-property:color,border-color,background-color;width:1em}.van-checkbox__icon--round{border-radius:100%}.van-checkbox__icon--checked{background-color:var(--checkbox-checked-icon-color,#1989fa);border-color:var(--checkbox-checked-icon-color,#1989fa);color:#fff}.van-checkbox__icon--disabled{background-color:var(--checkbox-disabled-background-color,#ebedf0);border-color:var(--checkbox-disabled-icon-color,#c8c9cc)}.van-checkbox__icon--disabled.van-checkbox__icon--checked{color:var(--checkbox-disabled-icon-color,#c8c9cc)}.van-checkbox__label{word-wrap:break-word;color:var(--checkbox-label-color,#323233);padding-left:var(--checkbox-label-margin,10px)}.van-checkbox__label--left{float:left;margin:0 var(--checkbox-label-margin,10px) 0 0}.van-checkbox__label--disabled{color:var(--checkbox-disabled-label-color,#c8c9cc)}.van-checkbox__label:empty{margin:0} ================================================ FILE: miniprogram_npm/@vant/weapp/checkbox-group/index.d.ts ================================================ export {}; ================================================ FILE: miniprogram_npm/@vant/weapp/checkbox-group/index.js ================================================ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var relation_1 = require("../common/relation"); var component_1 = require("../common/component"); (0, component_1.VantComponent)({ field: true, relation: (0, relation_1.useChildren)('checkbox', function (target) { this.updateChild(target); }), props: { max: Number, value: { type: Array, observer: 'updateChildren', }, disabled: { type: Boolean, observer: 'updateChildren', }, direction: { type: String, value: 'vertical', }, }, methods: { updateChildren: function () { var _this = this; this.children.forEach(function (child) { return _this.updateChild(child); }); }, updateChild: function (child) { var _a = this.data, value = _a.value, disabled = _a.disabled, direction = _a.direction; child.setData({ value: value.indexOf(child.data.name) !== -1, parentDisabled: disabled, direction: direction, }); }, }, }); ================================================ FILE: miniprogram_npm/@vant/weapp/checkbox-group/index.json ================================================ { "component": true } ================================================ FILE: miniprogram_npm/@vant/weapp/checkbox-group/index.wxml ================================================ ================================================ FILE: miniprogram_npm/@vant/weapp/checkbox-group/index.wxss ================================================ @import '../common/index.wxss';.van-checkbox-group--horizontal{display:flex;flex-wrap:wrap} ================================================ FILE: miniprogram_npm/@vant/weapp/circle/canvas.d.ts ================================================ /// type CanvasContext = WechatMiniprogram.CanvasContext; export declare function adaptor(ctx: CanvasContext & Record): CanvasContext; export {}; ================================================ FILE: miniprogram_npm/@vant/weapp/circle/canvas.js ================================================ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.adaptor = void 0; function adaptor(ctx) { // @ts-ignore return Object.assign(ctx, { setStrokeStyle: function (val) { ctx.strokeStyle = val; }, setLineWidth: function (val) { ctx.lineWidth = val; }, setLineCap: function (val) { ctx.lineCap = val; }, setFillStyle: function (val) { ctx.fillStyle = val; }, setFontSize: function (val) { ctx.font = String(val); }, setGlobalAlpha: function (val) { ctx.globalAlpha = val; }, setLineJoin: function (val) { ctx.lineJoin = val; }, setTextAlign: function (val) { ctx.textAlign = val; }, setMiterLimit: function (val) { ctx.miterLimit = val; }, setShadow: function (offsetX, offsetY, blur, color) { ctx.shadowOffsetX = offsetX; ctx.shadowOffsetY = offsetY; ctx.shadowBlur = blur; ctx.shadowColor = color; }, setTextBaseline: function (val) { ctx.textBaseline = val; }, createCircularGradient: function () { }, draw: function () { }, }); } exports.adaptor = adaptor; ================================================ FILE: miniprogram_npm/@vant/weapp/circle/index.d.ts ================================================ export {}; ================================================ FILE: miniprogram_npm/@vant/weapp/circle/index.js ================================================ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var color_1 = require("../common/color"); var component_1 = require("../common/component"); var utils_1 = require("../common/utils"); var validator_1 = require("../common/validator"); var version_1 = require("../common/version"); var canvas_1 = require("./canvas"); function format(rate) { return Math.min(Math.max(rate, 0), 100); } var PERIMETER = 2 * Math.PI; var BEGIN_ANGLE = -Math.PI / 2; var STEP = 1; (0, component_1.VantComponent)({ props: { text: String, lineCap: { type: String, value: 'round', }, value: { type: Number, value: 0, observer: 'reRender', }, speed: { type: Number, value: 50, }, size: { type: Number, value: 100, observer: function () { this.drawCircle(this.currentValue); }, }, fill: String, layerColor: { type: String, value: color_1.WHITE, }, color: { type: null, value: color_1.BLUE, observer: function () { var _this = this; this.setHoverColor().then(function () { _this.drawCircle(_this.currentValue); }); }, }, type: { type: String, value: '', }, strokeWidth: { type: Number, value: 4, }, clockwise: { type: Boolean, value: true, }, }, data: { hoverColor: color_1.BLUE, }, methods: { getContext: function () { var _this = this; var _a = this.data, type = _a.type, size = _a.size; if (type === '' || !(0, version_1.canIUseCanvas2d)()) { var ctx = wx.createCanvasContext('van-circle', this); return Promise.resolve(ctx); } var dpr = (0, utils_1.getSystemInfoSync)().pixelRatio; return new Promise(function (resolve) { wx.createSelectorQuery() .in(_this) .select('#van-circle') .node() .exec(function (res) { var canvas = res[0].node; var ctx = canvas.getContext(type); if (!_this.inited) { _this.inited = true; canvas.width = size * dpr; canvas.height = size * dpr; ctx.scale(dpr, dpr); } resolve((0, canvas_1.adaptor)(ctx)); }); }); }, setHoverColor: function () { var _this = this; var _a = this.data, color = _a.color, size = _a.size; if ((0, validator_1.isObj)(color)) { return this.getContext().then(function (context) { if (!context) return; var LinearColor = context.createLinearGradient(size, 0, 0, 0); Object.keys(color) .sort(function (a, b) { return parseFloat(a) - parseFloat(b); }) .map(function (key) { return LinearColor.addColorStop(parseFloat(key) / 100, color[key]); }); _this.hoverColor = LinearColor; }); } this.hoverColor = color; return Promise.resolve(); }, presetCanvas: function (context, strokeStyle, beginAngle, endAngle, fill) { var _a = this.data, strokeWidth = _a.strokeWidth, lineCap = _a.lineCap, clockwise = _a.clockwise, size = _a.size; var position = size / 2; var radius = position - strokeWidth / 2; context.setStrokeStyle(strokeStyle); context.setLineWidth(strokeWidth); context.setLineCap(lineCap); context.beginPath(); context.arc(position, position, radius, beginAngle, endAngle, !clockwise); context.stroke(); if (fill) { context.setFillStyle(fill); context.fill(); } }, renderLayerCircle: function (context) { var _a = this.data, layerColor = _a.layerColor, fill = _a.fill; this.presetCanvas(context, layerColor, 0, PERIMETER, fill); }, renderHoverCircle: function (context, formatValue) { var clockwise = this.data.clockwise; // 结束角度 var progress = PERIMETER * (formatValue / 100); var endAngle = clockwise ? BEGIN_ANGLE + progress : 3 * Math.PI - (BEGIN_ANGLE + progress); this.presetCanvas(context, this.hoverColor, BEGIN_ANGLE, endAngle); }, drawCircle: function (currentValue) { var _this = this; var size = this.data.size; this.getContext().then(function (context) { if (!context) return; context.clearRect(0, 0, size, size); _this.renderLayerCircle(context); var formatValue = format(currentValue); if (formatValue !== 0) { _this.renderHoverCircle(context, formatValue); } context.draw(); }); }, reRender: function () { var _this = this; // tofector 动画暂时没有想到好的解决方案 var _a = this.data, value = _a.value, speed = _a.speed; if (speed <= 0 || speed > 1000) { this.drawCircle(value); return; } this.clearMockInterval(); this.currentValue = this.currentValue || 0; var run = function () { _this.interval = setTimeout(function () { if (_this.currentValue !== value) { if (Math.abs(_this.currentValue - value) < STEP) { _this.currentValue = value; } else if (_this.currentValue < value) { _this.currentValue += STEP; } else { _this.currentValue -= STEP; } _this.drawCircle(_this.currentValue); run(); } else { _this.clearMockInterval(); } }, 1000 / speed); }; run(); }, clearMockInterval: function () { if (this.interval) { clearTimeout(this.interval); this.interval = null; } }, }, mounted: function () { var _this = this; this.currentValue = this.data.value; this.setHoverColor().then(function () { _this.drawCircle(_this.currentValue); }); }, destroyed: function () { this.clearMockInterval(); }, }); ================================================ FILE: miniprogram_npm/@vant/weapp/circle/index.json ================================================ { "component": true } ================================================ FILE: miniprogram_npm/@vant/weapp/circle/index.wxml ================================================ {{ text }} ================================================ FILE: miniprogram_npm/@vant/weapp/circle/index.wxss ================================================ @import '../common/index.wxss';.van-circle{display:inline-block;position:relative;text-align:center}.van-circle__text{color:var(--circle-text-color,#323233);left:0;position:absolute;top:50%;transform:translateY(-50%);width:100%} ================================================ FILE: miniprogram_npm/@vant/weapp/col/index.d.ts ================================================ export {}; ================================================ FILE: miniprogram_npm/@vant/weapp/col/index.js ================================================ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var relation_1 = require("../common/relation"); var component_1 = require("../common/component"); (0, component_1.VantComponent)({ relation: (0, relation_1.useParent)('row'), props: { span: Number, offset: Number, }, }); ================================================ FILE: miniprogram_npm/@vant/weapp/col/index.json ================================================ { "component": true } ================================================ FILE: miniprogram_npm/@vant/weapp/col/index.wxml ================================================ ================================================ FILE: miniprogram_npm/@vant/weapp/col/index.wxs ================================================ /* eslint-disable */ var style = require('../wxs/style.wxs'); var addUnit = require('../wxs/add-unit.wxs'); function rootStyle(data) { if (!data.gutter) { return ''; } return style({ 'padding-right': addUnit(data.gutter / 2), 'padding-left': addUnit(data.gutter / 2), }); } module.exports = { rootStyle: rootStyle, }; ================================================ FILE: miniprogram_npm/@vant/weapp/col/index.wxss ================================================ @import '../common/index.wxss';.van-col{box-sizing:border-box;float:left}.van-col--1{width:4.16666667%}.van-col--offset-1{margin-left:4.16666667%}.van-col--2{width:8.33333333%}.van-col--offset-2{margin-left:8.33333333%}.van-col--3{width:12.5%}.van-col--offset-3{margin-left:12.5%}.van-col--4{width:16.66666667%}.van-col--offset-4{margin-left:16.66666667%}.van-col--5{width:20.83333333%}.van-col--offset-5{margin-left:20.83333333%}.van-col--6{width:25%}.van-col--offset-6{margin-left:25%}.van-col--7{width:29.16666667%}.van-col--offset-7{margin-left:29.16666667%}.van-col--8{width:33.33333333%}.van-col--offset-8{margin-left:33.33333333%}.van-col--9{width:37.5%}.van-col--offset-9{margin-left:37.5%}.van-col--10{width:41.66666667%}.van-col--offset-10{margin-left:41.66666667%}.van-col--11{width:45.83333333%}.van-col--offset-11{margin-left:45.83333333%}.van-col--12{width:50%}.van-col--offset-12{margin-left:50%}.van-col--13{width:54.16666667%}.van-col--offset-13{margin-left:54.16666667%}.van-col--14{width:58.33333333%}.van-col--offset-14{margin-left:58.33333333%}.van-col--15{width:62.5%}.van-col--offset-15{margin-left:62.5%}.van-col--16{width:66.66666667%}.van-col--offset-16{margin-left:66.66666667%}.van-col--17{width:70.83333333%}.van-col--offset-17{margin-left:70.83333333%}.van-col--18{width:75%}.van-col--offset-18{margin-left:75%}.van-col--19{width:79.16666667%}.van-col--offset-19{margin-left:79.16666667%}.van-col--20{width:83.33333333%}.van-col--offset-20{margin-left:83.33333333%}.van-col--21{width:87.5%}.van-col--offset-21{margin-left:87.5%}.van-col--22{width:91.66666667%}.van-col--offset-22{margin-left:91.66666667%}.van-col--23{width:95.83333333%}.van-col--offset-23{margin-left:95.83333333%}.van-col--24{width:100%}.van-col--offset-24{margin-left:100%} ================================================ FILE: miniprogram_npm/@vant/weapp/collapse/index.d.ts ================================================ export {}; ================================================ FILE: miniprogram_npm/@vant/weapp/collapse/index.js ================================================ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var component_1 = require("../common/component"); var relation_1 = require("../common/relation"); (0, component_1.VantComponent)({ relation: (0, relation_1.useChildren)('collapse-item'), props: { value: { type: null, observer: 'updateExpanded', }, accordion: { type: Boolean, observer: 'updateExpanded', }, border: { type: Boolean, value: true, }, }, methods: { updateExpanded: function () { this.children.forEach(function (child) { child.updateExpanded(); }); }, switch: function (name, expanded) { var _a = this.data, accordion = _a.accordion, value = _a.value; var changeItem = name; if (!accordion) { name = expanded ? (value || []).concat(name) : (value || []).filter(function (activeName) { return activeName !== name; }); } else { name = expanded ? name : ''; } if (expanded) { this.$emit('open', changeItem); } else { this.$emit('close', changeItem); } this.$emit('change', name); this.$emit('input', name); }, }, }); ================================================ FILE: miniprogram_npm/@vant/weapp/collapse/index.json ================================================ { "component": true } ================================================ FILE: miniprogram_npm/@vant/weapp/collapse/index.wxml ================================================ ================================================ FILE: miniprogram_npm/@vant/weapp/collapse/index.wxss ================================================ @import '../common/index.wxss'; ================================================ FILE: miniprogram_npm/@vant/weapp/collapse-item/animate.d.ts ================================================ /// export declare function setContentAnimate(context: WechatMiniprogram.Component.TrivialInstance, expanded: boolean, mounted: boolean): void; ================================================ FILE: miniprogram_npm/@vant/weapp/collapse-item/animate.js ================================================ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.setContentAnimate = void 0; var utils_1 = require("../common/utils"); function useAnimation(context, expanded, mounted, height) { var animation = wx.createAnimation({ duration: 0, timingFunction: 'ease-in-out', }); if (expanded) { if (height === 0) { animation.height('auto').top(1).step(); } else { animation .height(height) .top(1) .step({ duration: mounted ? 300 : 1, }) .height('auto') .step(); } context.setData({ animation: animation.export(), }); return; } animation.height(height).top(0).step({ duration: 1 }).height(0).step({ duration: 300, }); context.setData({ animation: animation.export(), }); } function setContentAnimate(context, expanded, mounted) { (0, utils_1.getRect)(context, '.van-collapse-item__content') .then(function (rect) { return rect.height; }) .then(function (height) { useAnimation(context, expanded, mounted, height); }); } exports.setContentAnimate = setContentAnimate; ================================================ FILE: miniprogram_npm/@vant/weapp/collapse-item/index.d.ts ================================================ export {}; ================================================ FILE: miniprogram_npm/@vant/weapp/collapse-item/index.js ================================================ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var component_1 = require("../common/component"); var relation_1 = require("../common/relation"); var animate_1 = require("./animate"); (0, component_1.VantComponent)({ classes: ['title-class', 'content-class'], relation: (0, relation_1.useParent)('collapse'), props: { size: String, name: null, title: null, value: null, icon: String, label: String, disabled: Boolean, clickable: Boolean, border: { type: Boolean, value: true, }, isLink: { type: Boolean, value: true, }, }, data: { expanded: false, parentBorder: true, }, mounted: function () { this.updateExpanded(); this.mounted = true; }, methods: { updateExpanded: function () { if (!this.parent) { return; } var _a = this.parent.data, value = _a.value, accordion = _a.accordion, border = _a.border; var _b = this.parent.children, children = _b === void 0 ? [] : _b; var name = this.data.name; var index = children.indexOf(this); var currentName = name == null ? index : name; var expanded = accordion ? value === currentName : (value || []).some(function (name) { return name === currentName; }); if (expanded !== this.data.expanded) { (0, animate_1.setContentAnimate)(this, expanded, this.mounted); } this.setData({ index: index, expanded: expanded, parentBorder: border }); }, onClick: function () { if (this.data.disabled) { return; } var _a = this.data, name = _a.name, expanded = _a.expanded; var index = this.parent.children.indexOf(this); var currentName = name == null ? index : name; this.parent.switch(currentName, !expanded); }, }, }); ================================================ FILE: miniprogram_npm/@vant/weapp/collapse-item/index.json ================================================ { "component": true, "usingComponents": { "van-cell": "../cell/index" } } ================================================ FILE: miniprogram_npm/@vant/weapp/collapse-item/index.wxml ================================================ ================================================ FILE: miniprogram_npm/@vant/weapp/collapse-item/index.wxss ================================================ @import '../common/index.wxss';.van-collapse-item__title .van-cell__right-icon{transform:rotate(90deg);transition:transform var(--collapse-item-transition-duration,.3s)}.van-collapse-item__title--expanded .van-cell__right-icon{transform:rotate(-90deg)}.van-collapse-item__title--disabled .van-cell,.van-collapse-item__title--disabled .van-cell__right-icon{color:var(--collapse-item-title-disabled-color,#c8c9cc)!important}.van-collapse-item__title--disabled .van-cell--hover{background-color:#fff!important}.van-collapse-item__wrapper{overflow:hidden}.van-collapse-item__content{background-color:var(--collapse-item-content-background-color,#fff);color:var(--collapse-item-content-text-color,#969799);font-size:var(--collapse-item-content-font-size,13px);line-height:var(--collapse-item-content-line-height,1.5);padding:var(--collapse-item-content-padding,15px)} ================================================ FILE: miniprogram_npm/@vant/weapp/common/color.d.ts ================================================ export declare const RED = "#ee0a24"; export declare const BLUE = "#1989fa"; export declare const WHITE = "#fff"; export declare const GREEN = "#07c160"; export declare const ORANGE = "#ff976a"; export declare const GRAY = "#323233"; export declare const GRAY_DARK = "#969799"; ================================================ FILE: miniprogram_npm/@vant/weapp/common/color.js ================================================ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.GRAY_DARK = exports.GRAY = exports.ORANGE = exports.GREEN = exports.WHITE = exports.BLUE = exports.RED = void 0; exports.RED = '#ee0a24'; exports.BLUE = '#1989fa'; exports.WHITE = '#fff'; exports.GREEN = '#07c160'; exports.ORANGE = '#ff976a'; exports.GRAY = '#323233'; exports.GRAY_DARK = '#969799'; ================================================ FILE: miniprogram_npm/@vant/weapp/common/component.d.ts ================================================ /// import { VantComponentOptions } from 'definitions/index'; declare function VantComponent(vantOptions: VantComponentOptions): void; export { VantComponent }; ================================================ FILE: miniprogram_npm/@vant/weapp/common/component.js ================================================ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.VantComponent = void 0; var basic_1 = require("../mixins/basic"); function mapKeys(source, target, map) { Object.keys(map).forEach(function (key) { if (source[key]) { target[map[key]] = source[key]; } }); } function VantComponent(vantOptions) { var options = {}; mapKeys(vantOptions, options, { data: 'data', props: 'properties', watch: 'observers', mixins: 'behaviors', methods: 'methods', beforeCreate: 'created', created: 'attached', mounted: 'ready', destroyed: 'detached', classes: 'externalClasses', }); // add default externalClasses options.externalClasses = options.externalClasses || []; options.externalClasses.push('custom-class'); // add default behaviors options.behaviors = options.behaviors || []; options.behaviors.push(basic_1.basic); // add relations var relation = vantOptions.relation; if (relation) { options.relations = relation.relations; options.behaviors.push(relation.mixin); } // map field to form-field behavior if (vantOptions.field) { options.behaviors.push('wx://form-field'); } // add default options options.options = { multipleSlots: true, addGlobalClass: true, }; Component(options); } exports.VantComponent = VantComponent; ================================================ FILE: miniprogram_npm/@vant/weapp/common/index.wxss ================================================ .van-ellipsis{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.van-multi-ellipsis--l2{-webkit-line-clamp:2}.van-multi-ellipsis--l2,.van-multi-ellipsis--l3{-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden;text-overflow:ellipsis}.van-multi-ellipsis--l3{-webkit-line-clamp:3}.van-clearfix:after{clear:both;content:"";display:table}.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{border:0 solid #ebedf0;bottom:-50%;box-sizing:border-box;content:" ";left:-50%;pointer-events:none;position:absolute;right:-50%;top:-50%;transform:scale(.5);transform-origin:center}.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} ================================================ FILE: miniprogram_npm/@vant/weapp/common/relation.d.ts ================================================ /// type TrivialInstance = WechatMiniprogram.Component.TrivialInstance; export declare function useParent(name: string, onEffect?: (this: TrivialInstance) => void): { relations: { [x: string]: WechatMiniprogram.Component.RelationOption; }; mixin: string; }; export declare function useChildren(name: string, onEffect?: (this: TrivialInstance, target: TrivialInstance) => void): { relations: { [x: string]: WechatMiniprogram.Component.RelationOption; }; mixin: string; }; export {}; ================================================ FILE: miniprogram_npm/@vant/weapp/common/relation.js ================================================ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.useChildren = exports.useParent = void 0; function useParent(name, onEffect) { var _a; var path = "../".concat(name, "/index"); return { relations: (_a = {}, _a[path] = { type: 'ancestor', linked: function () { onEffect && onEffect.call(this); }, linkChanged: function () { onEffect && onEffect.call(this); }, unlinked: function () { onEffect && onEffect.call(this); }, }, _a), mixin: Behavior({ created: function () { var _this = this; Object.defineProperty(this, 'parent', { get: function () { return _this.getRelationNodes(path)[0]; }, }); Object.defineProperty(this, 'index', { // @ts-ignore get: function () { var _a, _b; return (_b = (_a = _this.parent) === null || _a === void 0 ? void 0 : _a.children) === null || _b === void 0 ? void 0 : _b.indexOf(_this); }, }); }, }), }; } exports.useParent = useParent; function useChildren(name, onEffect) { var _a; var path = "../".concat(name, "/index"); return { relations: (_a = {}, _a[path] = { type: 'descendant', linked: function (target) { onEffect && onEffect.call(this, target); }, linkChanged: function (target) { onEffect && onEffect.call(this, target); }, unlinked: function (target) { onEffect && onEffect.call(this, target); }, }, _a), mixin: Behavior({ created: function () { var _this = this; Object.defineProperty(this, 'children', { get: function () { return _this.getRelationNodes(path) || []; }, }); }, }), }; } exports.useChildren = useChildren; ================================================ FILE: miniprogram_npm/@vant/weapp/common/style/clearfix.wxss ================================================ .van-clearfix:after{clear:both;content:"";display:table} ================================================ FILE: miniprogram_npm/@vant/weapp/common/style/ellipsis.wxss ================================================ .van-ellipsis{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.van-multi-ellipsis--l2{-webkit-line-clamp:2}.van-multi-ellipsis--l2,.van-multi-ellipsis--l3{-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden;text-overflow:ellipsis}.van-multi-ellipsis--l3{-webkit-line-clamp:3} ================================================ FILE: miniprogram_npm/@vant/weapp/common/style/hairline.wxss ================================================ .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{border:0 solid #ebedf0;bottom:-50%;box-sizing:border-box;content:" ";left:-50%;pointer-events:none;position:absolute;right:-50%;top:-50%;transform:scale(.5);transform-origin:center}.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} ================================================ FILE: miniprogram_npm/@vant/weapp/common/style/mixins/clearfix.wxss ================================================ ================================================ FILE: miniprogram_npm/@vant/weapp/common/style/mixins/ellipsis.wxss ================================================ ================================================ FILE: miniprogram_npm/@vant/weapp/common/style/mixins/hairline.wxss ================================================ ================================================ FILE: miniprogram_npm/@vant/weapp/common/style/var.wxss ================================================ ================================================ FILE: miniprogram_npm/@vant/weapp/common/utils.d.ts ================================================ /// /// /// /// /// export { isDef } from './validator'; export { getSystemInfoSync } from './version'; export declare function range(num: number, min: number, max: number): number; export declare function nextTick(cb: (...args: any[]) => void): void; export declare function addUnit(value?: string | number): string | undefined; export declare function requestAnimationFrame(cb: () => void): NodeJS.Timeout; export declare function pickExclude(obj: unknown, keys: string[]): {}; export declare function getRect(context: WechatMiniprogram.Component.TrivialInstance, selector: string): Promise; export declare function getAllRect(context: WechatMiniprogram.Component.TrivialInstance, selector: string): Promise; export declare function groupSetData(context: WechatMiniprogram.Component.TrivialInstance, cb: () => void): void; export declare function toPromise(promiseLike: Promise | unknown): Promise; export declare function addNumber(num1: any, num2: any): number; export declare const clamp: (num: any, min: any, max: any) => number; export declare function getCurrentPage(): T & WechatMiniprogram.OptionalInterface & WechatMiniprogram.Page.InstanceProperties & WechatMiniprogram.Page.InstanceMethods & WechatMiniprogram.Page.Data & WechatMiniprogram.IAnyObject; export declare const isPC: boolean; export declare const isWxWork: boolean; ================================================ FILE: miniprogram_npm/@vant/weapp/common/utils.js ================================================ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.isWxWork = exports.isPC = exports.getCurrentPage = exports.clamp = exports.addNumber = exports.toPromise = exports.groupSetData = exports.getAllRect = exports.getRect = exports.pickExclude = exports.requestAnimationFrame = exports.addUnit = exports.nextTick = exports.range = exports.getSystemInfoSync = exports.isDef = void 0; var validator_1 = require("./validator"); var version_1 = require("./version"); var validator_2 = require("./validator"); Object.defineProperty(exports, "isDef", { enumerable: true, get: function () { return validator_2.isDef; } }); var version_2 = require("./version"); Object.defineProperty(exports, "getSystemInfoSync", { enumerable: true, get: function () { return version_2.getSystemInfoSync; } }); function range(num, min, max) { return Math.min(Math.max(num, min), max); } exports.range = range; function nextTick(cb) { if ((0, version_1.canIUseNextTick)()) { wx.nextTick(cb); } else { setTimeout(function () { cb(); }, 1000 / 30); } } exports.nextTick = nextTick; function addUnit(value) { if (!(0, validator_1.isDef)(value)) { return undefined; } value = String(value); return (0, validator_1.isNumber)(value) ? "".concat(value, "px") : value; } exports.addUnit = addUnit; function requestAnimationFrame(cb) { return setTimeout(function () { cb(); }, 1000 / 30); } exports.requestAnimationFrame = requestAnimationFrame; function pickExclude(obj, keys) { if (!(0, validator_1.isPlainObject)(obj)) { return {}; } return Object.keys(obj).reduce(function (prev, key) { if (!keys.includes(key)) { prev[key] = obj[key]; } return prev; }, {}); } exports.pickExclude = pickExclude; function getRect(context, selector) { return new Promise(function (resolve) { wx.createSelectorQuery() .in(context) .select(selector) .boundingClientRect() .exec(function (rect) { if (rect === void 0) { rect = []; } return resolve(rect[0]); }); }); } exports.getRect = getRect; function getAllRect(context, selector) { return new Promise(function (resolve) { wx.createSelectorQuery() .in(context) .selectAll(selector) .boundingClientRect() .exec(function (rect) { if (rect === void 0) { rect = []; } return resolve(rect[0]); }); }); } exports.getAllRect = getAllRect; function groupSetData(context, cb) { if ((0, version_1.canIUseGroupSetData)()) { context.groupSetData(cb); } else { cb(); } } exports.groupSetData = groupSetData; function toPromise(promiseLike) { if ((0, validator_1.isPromise)(promiseLike)) { return promiseLike; } return Promise.resolve(promiseLike); } exports.toPromise = toPromise; // 浮点数精度处理 function addNumber(num1, num2) { var cardinal = Math.pow(10, 10); return Math.round((num1 + num2) * cardinal) / cardinal; } exports.addNumber = addNumber; // 限制value在[min, max]之间 var clamp = function (num, min, max) { return Math.min(Math.max(num, min), max); }; exports.clamp = clamp; function getCurrentPage() { var pages = getCurrentPages(); return pages[pages.length - 1]; } exports.getCurrentPage = getCurrentPage; exports.isPC = ['mac', 'windows'].includes((0, version_1.getSystemInfoSync)().platform); // 是否企业微信 exports.isWxWork = (0, version_1.getSystemInfoSync)().environment === 'wxwork'; ================================================ FILE: miniprogram_npm/@vant/weapp/common/validator.d.ts ================================================ export declare function isFunction(val: unknown): val is Function; export declare function isPlainObject(val: unknown): val is Record; export declare function isPromise(val: unknown): val is Promise; export declare function isDef(value: unknown): boolean; export declare function isObj(x: unknown): x is Record; export declare function isNumber(value: string): boolean; export declare function isBoolean(value: unknown): value is boolean; export declare function isImageUrl(url: string): boolean; export declare function isVideoUrl(url: string): boolean; ================================================ FILE: miniprogram_npm/@vant/weapp/common/validator.js ================================================ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.isVideoUrl = exports.isImageUrl = exports.isBoolean = exports.isNumber = exports.isObj = exports.isDef = exports.isPromise = exports.isPlainObject = exports.isFunction = void 0; // eslint-disable-next-line @typescript-eslint/ban-types function isFunction(val) { return typeof val === 'function'; } exports.isFunction = isFunction; function isPlainObject(val) { return val !== null && typeof val === 'object' && !Array.isArray(val); } exports.isPlainObject = isPlainObject; function isPromise(val) { return isPlainObject(val) && isFunction(val.then) && isFunction(val.catch); } exports.isPromise = isPromise; function isDef(value) { return value !== undefined && value !== null; } exports.isDef = isDef; function isObj(x) { var type = typeof x; return x !== null && (type === 'object' || type === 'function'); } exports.isObj = isObj; function isNumber(value) { return /^\d+(\.\d+)?$/.test(value); } exports.isNumber = isNumber; function isBoolean(value) { return typeof value === 'boolean'; } exports.isBoolean = isBoolean; var IMAGE_REGEXP = /\.(jpeg|jpg|gif|png|svg|webp|jfif|bmp|dpg)/i; var VIDEO_REGEXP = /\.(mp4|mpg|mpeg|dat|asf|avi|rm|rmvb|mov|wmv|flv|mkv)/i; function isImageUrl(url) { return IMAGE_REGEXP.test(url); } exports.isImageUrl = isImageUrl; function isVideoUrl(url) { return VIDEO_REGEXP.test(url); } exports.isVideoUrl = isVideoUrl; ================================================ FILE: miniprogram_npm/@vant/weapp/common/version.d.ts ================================================ /// interface WxWorkSystemInfo extends WechatMiniprogram.SystemInfo { environment?: 'wxwork'; } interface SystemInfo extends WxWorkSystemInfo, WechatMiniprogram.SystemInfo { } export declare function getSystemInfoSync(): SystemInfo; export declare function canIUseModel(): boolean; export declare function canIUseFormFieldButton(): boolean; export declare function canIUseAnimate(): boolean; export declare function canIUseGroupSetData(): boolean; export declare function canIUseNextTick(): boolean; export declare function canIUseCanvas2d(): boolean; export declare function canIUseGetUserProfile(): boolean; export {}; ================================================ FILE: miniprogram_npm/@vant/weapp/common/version.js ================================================ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.canIUseGetUserProfile = exports.canIUseCanvas2d = exports.canIUseNextTick = exports.canIUseGroupSetData = exports.canIUseAnimate = exports.canIUseFormFieldButton = exports.canIUseModel = exports.getSystemInfoSync = void 0; var systemInfo; function getSystemInfoSync() { if (systemInfo == null) { systemInfo = wx.getSystemInfoSync(); } return systemInfo; } exports.getSystemInfoSync = getSystemInfoSync; function compareVersion(v1, v2) { v1 = v1.split('.'); v2 = v2.split('.'); var len = Math.max(v1.length, v2.length); while (v1.length < len) { v1.push('0'); } while (v2.length < len) { v2.push('0'); } for (var i = 0; i < len; i++) { var num1 = parseInt(v1[i], 10); var num2 = parseInt(v2[i], 10); if (num1 > num2) { return 1; } if (num1 < num2) { return -1; } } return 0; } function gte(version) { var system = getSystemInfoSync(); return compareVersion(system.SDKVersion, version) >= 0; } function canIUseModel() { return gte('2.9.3'); } exports.canIUseModel = canIUseModel; function canIUseFormFieldButton() { return gte('2.10.3'); } exports.canIUseFormFieldButton = canIUseFormFieldButton; function canIUseAnimate() { return gte('2.9.0'); } exports.canIUseAnimate = canIUseAnimate; function canIUseGroupSetData() { return gte('2.4.0'); } exports.canIUseGroupSetData = canIUseGroupSetData; function canIUseNextTick() { try { return wx.canIUse('nextTick'); } catch (e) { return gte('2.7.1'); } } exports.canIUseNextTick = canIUseNextTick; function canIUseCanvas2d() { return gte('2.9.0'); } exports.canIUseCanvas2d = canIUseCanvas2d; function canIUseGetUserProfile() { return !!wx.getUserProfile; } exports.canIUseGetUserProfile = canIUseGetUserProfile; ================================================ FILE: miniprogram_npm/@vant/weapp/config-provider/index.d.ts ================================================ export {}; ================================================ FILE: miniprogram_npm/@vant/weapp/config-provider/index.js ================================================ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var component_1 = require("../common/component"); (0, component_1.VantComponent)({ props: { themeVars: { type: Object, value: {}, }, }, }); ================================================ FILE: miniprogram_npm/@vant/weapp/config-provider/index.json ================================================ { "component": true } ================================================ FILE: miniprogram_npm/@vant/weapp/config-provider/index.wxml ================================================ ================================================ FILE: miniprogram_npm/@vant/weapp/config-provider/index.wxs ================================================ /* eslint-disable */ var object = require('../wxs/object.wxs'); var style = require('../wxs/style.wxs'); function kebabCase(word) { var newWord = word .replace(getRegExp("[A-Z]", 'g'), function (i) { return '-' + i; }) .toLowerCase() .replace(getRegExp("^-"), ''); return newWord; } function mapThemeVarsToCSSVars(themeVars) { var cssVars = {}; object.keys(themeVars).forEach(function (key) { var cssVarsKey = '--' + kebabCase(key); cssVars[cssVarsKey] = themeVars[key]; }); return style(cssVars); } module.exports = { kebabCase: kebabCase, mapThemeVarsToCSSVars: mapThemeVarsToCSSVars, }; ================================================ FILE: miniprogram_npm/@vant/weapp/count-down/index.d.ts ================================================ export {}; ================================================ FILE: miniprogram_npm/@vant/weapp/count-down/index.js ================================================ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var component_1 = require("../common/component"); var utils_1 = require("./utils"); function simpleTick(fn) { return setTimeout(fn, 30); } (0, component_1.VantComponent)({ props: { useSlot: Boolean, millisecond: Boolean, time: { type: Number, observer: 'reset', }, format: { type: String, value: 'HH:mm:ss', }, autoStart: { type: Boolean, value: true, }, }, data: { timeData: (0, utils_1.parseTimeData)(0), formattedTime: '0', }, destroyed: function () { clearTimeout(this.tid); this.tid = null; }, methods: { // 开始 start: function () { if (this.counting) { return; } this.counting = true; this.endTime = Date.now() + this.remain; this.tick(); }, // 暂停 pause: function () { this.counting = false; clearTimeout(this.tid); }, // 重置 reset: function () { this.pause(); this.remain = this.data.time; this.setRemain(this.remain); if (this.data.autoStart) { this.start(); } }, tick: function () { if (this.data.millisecond) { this.microTick(); } else { this.macroTick(); } }, microTick: function () { var _this = this; this.tid = simpleTick(function () { _this.setRemain(_this.getRemain()); if (_this.remain !== 0) { _this.microTick(); } }); }, macroTick: function () { var _this = this; this.tid = simpleTick(function () { var remain = _this.getRemain(); if (!(0, utils_1.isSameSecond)(remain, _this.remain) || remain === 0) { _this.setRemain(remain); } if (_this.remain !== 0) { _this.macroTick(); } }); }, getRemain: function () { return Math.max(this.endTime - Date.now(), 0); }, setRemain: function (remain) { this.remain = remain; var timeData = (0, utils_1.parseTimeData)(remain); if (this.data.useSlot) { this.$emit('change', timeData); } this.setData({ formattedTime: (0, utils_1.parseFormat)(this.data.format, timeData), }); if (remain === 0) { this.pause(); this.$emit('finish'); } }, }, }); ================================================ FILE: miniprogram_npm/@vant/weapp/count-down/index.json ================================================ { "component": true } ================================================ FILE: miniprogram_npm/@vant/weapp/count-down/index.wxml ================================================ {{ formattedTime }} ================================================ FILE: miniprogram_npm/@vant/weapp/count-down/index.wxss ================================================ @import '../common/index.wxss';.van-count-down{color:var(--count-down-text-color,#323233);font-size:var(--count-down-font-size,14px);line-height:var(--count-down-line-height,20px)} ================================================ FILE: miniprogram_npm/@vant/weapp/count-down/utils.d.ts ================================================ export type TimeData = { days: number; hours: number; minutes: number; seconds: number; milliseconds: number; }; export declare function parseTimeData(time: number): TimeData; export declare function parseFormat(format: string, timeData: TimeData): string; export declare function isSameSecond(time1: number, time2: number): boolean; ================================================ FILE: miniprogram_npm/@vant/weapp/count-down/utils.js ================================================ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.isSameSecond = exports.parseFormat = exports.parseTimeData = void 0; function padZero(num, targetLength) { if (targetLength === void 0) { targetLength = 2; } var str = num + ''; while (str.length < targetLength) { str = '0' + str; } return str; } var SECOND = 1000; var MINUTE = 60 * SECOND; var HOUR = 60 * MINUTE; var DAY = 24 * HOUR; function parseTimeData(time) { var days = Math.floor(time / DAY); var hours = Math.floor((time % DAY) / HOUR); var minutes = Math.floor((time % HOUR) / MINUTE); var seconds = Math.floor((time % MINUTE) / SECOND); var milliseconds = Math.floor(time % SECOND); return { days: days, hours: hours, minutes: minutes, seconds: seconds, milliseconds: milliseconds, }; } exports.parseTimeData = parseTimeData; function parseFormat(format, timeData) { var days = timeData.days; var hours = timeData.hours, minutes = timeData.minutes, seconds = timeData.seconds, milliseconds = timeData.milliseconds; if (format.indexOf('DD') === -1) { hours += days * 24; } else { format = format.replace('DD', padZero(days)); } if (format.indexOf('HH') === -1) { minutes += hours * 60; } else { format = format.replace('HH', padZero(hours)); } if (format.indexOf('mm') === -1) { seconds += minutes * 60; } else { format = format.replace('mm', padZero(minutes)); } if (format.indexOf('ss') === -1) { milliseconds += seconds * 1000; } else { format = format.replace('ss', padZero(seconds)); } return format.replace('SSS', padZero(milliseconds, 3)); } exports.parseFormat = parseFormat; function isSameSecond(time1, time2) { return Math.floor(time1 / 1000) === Math.floor(time2 / 1000); } exports.isSameSecond = isSameSecond; ================================================ FILE: miniprogram_npm/@vant/weapp/datetime-picker/index.d.ts ================================================ export {}; ================================================ FILE: miniprogram_npm/@vant/weapp/datetime-picker/index.js ================================================ "use strict"; var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { if (ar || !(i in from)) { if (!ar) ar = Array.prototype.slice.call(from, 0, i); ar[i] = from[i]; } } return to.concat(ar || Array.prototype.slice.call(from)); }; Object.defineProperty(exports, "__esModule", { value: true }); var component_1 = require("../common/component"); var validator_1 = require("../common/validator"); var shared_1 = require("../picker/shared"); var currentYear = new Date().getFullYear(); function isValidDate(date) { return (0, validator_1.isDef)(date) && !isNaN(new Date(date).getTime()); } function range(num, min, max) { return Math.min(Math.max(num, min), max); } function padZero(val) { return "00".concat(val).slice(-2); } function times(n, iteratee) { var index = -1; var result = Array(n < 0 ? 0 : n); while (++index < n) { result[index] = iteratee(index); } return result; } function getTrueValue(formattedValue) { if (formattedValue === undefined) { formattedValue = '1'; } while (isNaN(parseInt(formattedValue, 10))) { formattedValue = formattedValue.slice(1); } return parseInt(formattedValue, 10); } function getMonthEndDay(year, month) { return 32 - new Date(year, month - 1, 32).getDate(); } var defaultFormatter = function (type, value) { return value; }; (0, component_1.VantComponent)({ classes: ['active-class', 'toolbar-class', 'column-class'], props: __assign(__assign({}, shared_1.pickerProps), { value: { type: null, observer: 'updateValue', }, filter: null, type: { type: String, value: 'datetime', observer: 'updateValue', }, showToolbar: { type: Boolean, value: true, }, formatter: { type: null, value: defaultFormatter, }, minDate: { type: Number, value: new Date(currentYear - 10, 0, 1).getTime(), observer: 'updateValue', }, maxDate: { type: Number, value: new Date(currentYear + 10, 11, 31).getTime(), observer: 'updateValue', }, minHour: { type: Number, value: 0, observer: 'updateValue', }, maxHour: { type: Number, value: 23, observer: 'updateValue', }, minMinute: { type: Number, value: 0, observer: 'updateValue', }, maxMinute: { type: Number, value: 59, observer: 'updateValue', } }), data: { innerValue: Date.now(), columns: [], }, methods: { updateValue: function () { var _this = this; var data = this.data; var val = this.correctValue(data.value); var isEqual = val === data.innerValue; this.updateColumnValue(val).then(function () { if (!isEqual) { _this.$emit('input', val); } }); }, getPicker: function () { if (this.picker == null) { this.picker = this.selectComponent('.van-datetime-picker'); var picker_1 = this.picker; var setColumnValues_1 = picker_1.setColumnValues; picker_1.setColumnValues = function () { var args = []; for (var _i = 0; _i < arguments.length; _i++) { args[_i] = arguments[_i]; } return setColumnValues_1.apply(picker_1, __spreadArray(__spreadArray([], args, true), [false], false)); }; } return this.picker; }, updateColumns: function () { var _a = this.data.formatter, formatter = _a === void 0 ? defaultFormatter : _a; var results = this.getOriginColumns().map(function (column) { return ({ values: column.values.map(function (value) { return formatter(column.type, value); }), }); }); return this.set({ columns: results }); }, getOriginColumns: function () { var filter = this.data.filter; var results = this.getRanges().map(function (_a) { var type = _a.type, range = _a.range; var values = times(range[1] - range[0] + 1, function (index) { var value = range[0] + index; return type === 'year' ? "".concat(value) : padZero(value); }); if (filter) { values = filter(type, values); } return { type: type, values: values }; }); return results; }, getRanges: function () { var data = this.data; if (data.type === 'time') { return [ { type: 'hour', range: [data.minHour, data.maxHour], }, { type: 'minute', range: [data.minMinute, data.maxMinute], }, ]; } var _a = this.getBoundary('max', data.innerValue), maxYear = _a.maxYear, maxDate = _a.maxDate, maxMonth = _a.maxMonth, maxHour = _a.maxHour, maxMinute = _a.maxMinute; var _b = this.getBoundary('min', data.innerValue), minYear = _b.minYear, minDate = _b.minDate, minMonth = _b.minMonth, minHour = _b.minHour, minMinute = _b.minMinute; var result = [ { type: 'year', range: [minYear, maxYear], }, { type: 'month', range: [minMonth, maxMonth], }, { type: 'day', range: [minDate, maxDate], }, { type: 'hour', range: [minHour, maxHour], }, { type: 'minute', range: [minMinute, maxMinute], }, ]; if (data.type === 'date') result.splice(3, 2); if (data.type === 'year-month') result.splice(2, 3); return result; }, correctValue: function (value) { var data = this.data; // validate value var isDateType = data.type !== 'time'; if (isDateType && !isValidDate(value)) { value = data.minDate; } else if (!isDateType && !value) { var minHour = data.minHour; value = "".concat(padZero(minHour), ":00"); } // time type if (!isDateType) { var _a = value.split(':'), hour = _a[0], minute = _a[1]; hour = padZero(range(hour, data.minHour, data.maxHour)); minute = padZero(range(minute, data.minMinute, data.maxMinute)); return "".concat(hour, ":").concat(minute); } // date type value = Math.max(value, data.minDate); value = Math.min(value, data.maxDate); return value; }, getBoundary: function (type, innerValue) { var _a; var value = new Date(innerValue); var boundary = new Date(this.data["".concat(type, "Date")]); var year = boundary.getFullYear(); var month = 1; var date = 1; var hour = 0; var minute = 0; if (type === 'max') { month = 12; date = getMonthEndDay(value.getFullYear(), value.getMonth() + 1); hour = 23; minute = 59; } if (value.getFullYear() === year) { month = boundary.getMonth() + 1; if (value.getMonth() + 1 === month) { date = boundary.getDate(); if (value.getDate() === date) { hour = boundary.getHours(); if (value.getHours() === hour) { minute = boundary.getMinutes(); } } } } return _a = {}, _a["".concat(type, "Year")] = year, _a["".concat(type, "Month")] = month, _a["".concat(type, "Date")] = date, _a["".concat(type, "Hour")] = hour, _a["".concat(type, "Minute")] = minute, _a; }, onCancel: function () { this.$emit('cancel'); }, onConfirm: function () { this.$emit('confirm', this.data.innerValue); }, onChange: function () { var _this = this; var data = this.data; var value; var picker = this.getPicker(); var originColumns = this.getOriginColumns(); if (data.type === 'time') { var indexes = picker.getIndexes(); value = "".concat(+originColumns[0].values[indexes[0]], ":").concat(+originColumns[1] .values[indexes[1]]); } else { var indexes = picker.getIndexes(); var values = indexes.map(function (value, index) { return originColumns[index].values[value]; }); var year = getTrueValue(values[0]); var month = getTrueValue(values[1]); var maxDate = getMonthEndDay(year, month); var date = getTrueValue(values[2]); if (data.type === 'year-month') { date = 1; } date = date > maxDate ? maxDate : date; var hour = 0; var minute = 0; if (data.type === 'datetime') { hour = getTrueValue(values[3]); minute = getTrueValue(values[4]); } value = new Date(year, month - 1, date, hour, minute); } value = this.correctValue(value); this.updateColumnValue(value).then(function () { _this.$emit('input', value); _this.$emit('change', picker); }); }, updateColumnValue: function (value) { var _this = this; var values = []; var type = this.data.type; var formatter = this.data.formatter || defaultFormatter; var picker = this.getPicker(); if (type === 'time') { var pair = value.split(':'); values = [formatter('hour', pair[0]), formatter('minute', pair[1])]; } else { var date = new Date(value); values = [ formatter('year', "".concat(date.getFullYear())), formatter('month', padZero(date.getMonth() + 1)), ]; if (type === 'date') { values.push(formatter('day', padZero(date.getDate()))); } if (type === 'datetime') { values.push(formatter('day', padZero(date.getDate())), formatter('hour', padZero(date.getHours())), formatter('minute', padZero(date.getMinutes()))); } } return this.set({ innerValue: value }) .then(function () { return _this.updateColumns(); }) .then(function () { return picker.setValues(values); }); }, }, created: function () { var _this = this; var innerValue = this.correctValue(this.data.value); this.updateColumnValue(innerValue).then(function () { _this.$emit('input', innerValue); }); }, }); ================================================ FILE: miniprogram_npm/@vant/weapp/datetime-picker/index.json ================================================ { "component": true, "usingComponents": { "van-picker": "../picker/index" } } ================================================ FILE: miniprogram_npm/@vant/weapp/datetime-picker/index.wxml ================================================ ================================================ FILE: miniprogram_npm/@vant/weapp/datetime-picker/index.wxss ================================================ @import '../common/index.wxss'; ================================================ FILE: miniprogram_npm/@vant/weapp/definitions/index.d.ts ================================================ /// interface VantComponentInstance { parent: WechatMiniprogram.Component.TrivialInstance; children: WechatMiniprogram.Component.TrivialInstance[]; index: number; $emit: (name: string, detail?: unknown, options?: WechatMiniprogram.Component.TriggerEventOption) => void; setView: (value: Record, callback?: () => void) => void; } export type VantComponentOptions = { data?: Data; field?: boolean; classes?: string[]; mixins?: string[]; props?: Props; relation?: { relations: Record; mixin: string; }; watch?: Record any>; methods?: Methods; beforeCreate?: () => void; created?: () => void; mounted?: () => void; destroyed?: () => void; } & ThisType, Props, Methods> & Record>; export {}; ================================================ FILE: miniprogram_npm/@vant/weapp/definitions/index.js ================================================ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); ================================================ FILE: miniprogram_npm/@vant/weapp/dialog/dialog.d.ts ================================================ /// /// export type Action = 'confirm' | 'cancel' | 'overlay'; type DialogContext = WechatMiniprogram.Page.TrivialInstance | WechatMiniprogram.Component.TrivialInstance; interface DialogOptions { lang?: string; show?: boolean; title?: string; width?: string | number | null; zIndex?: number; theme?: string; context?: (() => DialogContext) | DialogContext; message?: string; overlay?: boolean; selector?: string; ariaLabel?: string; /** * @deprecated use custom-class instead */ className?: string; customStyle?: string; transition?: string; /** * @deprecated use beforeClose instead */ asyncClose?: boolean; beforeClose?: null | ((action: Action) => Promise | void); businessId?: number; sessionFrom?: string; overlayStyle?: string; appParameter?: string; messageAlign?: string; sendMessageImg?: string; showMessageCard?: boolean; sendMessagePath?: string; sendMessageTitle?: string; confirmButtonText?: string; cancelButtonText?: string; showConfirmButton?: boolean; showCancelButton?: boolean; closeOnClickOverlay?: boolean; confirmButtonOpenType?: string; } declare const Dialog: { (options: DialogOptions): Promise; alert(options: DialogOptions): Promise; confirm(options: DialogOptions): Promise; close(): void; stopLoading(): void; currentOptions: DialogOptions; defaultOptions: DialogOptions; setDefaultOptions(options: DialogOptions): void; resetDefaultOptions(): void; }; export default Dialog; ================================================ FILE: miniprogram_npm/@vant/weapp/dialog/dialog.js ================================================ "use strict"; var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; Object.defineProperty(exports, "__esModule", { value: true }); var queue = []; var defaultOptions = { show: false, title: '', width: null, theme: 'default', message: '', zIndex: 100, overlay: true, selector: '#van-dialog', className: '', asyncClose: false, beforeClose: null, transition: 'scale', customStyle: '', messageAlign: '', overlayStyle: '', confirmButtonText: '确认', cancelButtonText: '取消', showConfirmButton: true, showCancelButton: false, closeOnClickOverlay: false, confirmButtonOpenType: '', }; var currentOptions = __assign({}, defaultOptions); function getContext() { var pages = getCurrentPages(); return pages[pages.length - 1]; } var Dialog = function (options) { options = __assign(__assign({}, currentOptions), options); return new Promise(function (resolve, reject) { var context = (typeof options.context === 'function' ? options.context() : options.context) || getContext(); var dialog = context.selectComponent(options.selector); delete options.context; delete options.selector; if (dialog) { dialog.setData(__assign({ callback: function (action, instance) { action === 'confirm' ? resolve(instance) : reject(instance); } }, options)); wx.nextTick(function () { dialog.setData({ show: true }); }); queue.push(dialog); } else { console.warn('未找到 van-dialog 节点,请确认 selector 及 context 是否正确'); } }); }; Dialog.alert = function (options) { return Dialog(options); }; Dialog.confirm = function (options) { return Dialog(__assign({ showCancelButton: true }, options)); }; Dialog.close = function () { queue.forEach(function (dialog) { dialog.close(); }); queue = []; }; Dialog.stopLoading = function () { queue.forEach(function (dialog) { dialog.stopLoading(); }); }; Dialog.currentOptions = currentOptions; Dialog.defaultOptions = defaultOptions; Dialog.setDefaultOptions = function (options) { currentOptions = __assign(__assign({}, currentOptions), options); Dialog.currentOptions = currentOptions; }; Dialog.resetDefaultOptions = function () { currentOptions = __assign({}, defaultOptions); Dialog.currentOptions = currentOptions; }; Dialog.resetDefaultOptions(); exports.default = Dialog; ================================================ FILE: miniprogram_npm/@vant/weapp/dialog/index.d.ts ================================================ export {}; ================================================ FILE: miniprogram_npm/@vant/weapp/dialog/index.js ================================================ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var component_1 = require("../common/component"); var button_1 = require("../mixins/button"); var color_1 = require("../common/color"); var utils_1 = require("../common/utils"); (0, component_1.VantComponent)({ mixins: [button_1.button], classes: ['cancle-button-class', 'confirm-button-class'], props: { show: { type: Boolean, observer: function (show) { !show && this.stopLoading(); }, }, title: String, message: String, theme: { type: String, value: 'default', }, confirmButtonId: String, className: String, customStyle: String, asyncClose: Boolean, messageAlign: String, beforeClose: null, overlayStyle: String, useSlot: Boolean, useTitleSlot: Boolean, useConfirmButtonSlot: Boolean, useCancelButtonSlot: Boolean, showCancelButton: Boolean, closeOnClickOverlay: Boolean, confirmButtonOpenType: String, width: null, zIndex: { type: Number, value: 2000, }, confirmButtonText: { type: String, value: '确认', }, cancelButtonText: { type: String, value: '取消', }, confirmButtonColor: { type: String, value: color_1.RED, }, cancelButtonColor: { type: String, value: color_1.GRAY, }, showConfirmButton: { type: Boolean, value: true, }, overlay: { type: Boolean, value: true, }, transition: { type: String, value: 'scale', }, rootPortal: { type: Boolean, value: false, }, }, data: { loading: { confirm: false, cancel: false, }, callback: (function () { }), }, methods: { onConfirm: function () { this.handleAction('confirm'); }, onCancel: function () { this.handleAction('cancel'); }, onClickOverlay: function () { this.close('overlay'); }, close: function (action) { this.setData({ show: false }); this.closeAction = action; }, onAfterLeave: function () { var action = this.closeAction; this.$emit('close', action); var callback = this.data.callback; if (callback) { callback(action, this); } }, stopLoading: function () { this.setData({ loading: { confirm: false, cancel: false, }, }); }, handleAction: function (action) { var _a; var _this = this; this.$emit(action, { dialog: this }); var _b = this.data, asyncClose = _b.asyncClose, beforeClose = _b.beforeClose; if (!asyncClose && !beforeClose) { this.close(action); return; } this.setData((_a = {}, _a["loading.".concat(action)] = true, _a)); if (beforeClose) { (0, utils_1.toPromise)(beforeClose(action)).then(function (value) { if (value) { _this.close(action); } else { _this.stopLoading(); } }); } }, }, }); ================================================ FILE: miniprogram_npm/@vant/weapp/dialog/index.json ================================================ { "component": true, "usingComponents": { "van-popup": "../popup/index", "van-button": "../button/index", "van-goods-action": "../goods-action/index", "van-goods-action-button": "../goods-action-button/index" } } ================================================ FILE: miniprogram_npm/@vant/weapp/dialog/index.wxml ================================================ {{ title }} {{ message }} {{ cancelButtonText }} {{ confirmButtonText }} {{ cancelButtonText }} {{ confirmButtonText }} ================================================ FILE: miniprogram_npm/@vant/weapp/dialog/index.wxss ================================================ @import '../common/index.wxss';.van-dialog{background-color:var(--dialog-background-color,#fff);border-radius:var(--dialog-border-radius,16px);font-size:var(--dialog-font-size,16px);overflow:hidden;top:45%!important;width:var(--dialog-width,320px)}@media (max-width:321px){.van-dialog{width:var(--dialog-small-screen-width,90%)}}.van-dialog__header{font-weight:var(--dialog-header-font-weight,500);line-height:var(--dialog-header-line-height,24px);padding-top:var(--dialog-header-padding-top,24px);text-align:center}.van-dialog__header--isolated{padding:var(--dialog-header-isolated-padding,24px 0)}.van-dialog__message{-webkit-overflow-scrolling:touch;font-size:var(--dialog-message-font-size,14px);line-height:var(--dialog-message-line-height,20px);max-height:var(--dialog-message-max-height,60vh);overflow-y:auto;padding:var(--dialog-message-padding,24px);text-align:center}.van-dialog__message-text{word-wrap:break-word}.van-dialog__message--hasTitle{color:var(--dialog-has-title-message-text-color,#646566);padding-top:var(--dialog-has-title-message-padding-top,8px)}.van-dialog__message--round-button{color:#323233;padding-bottom:16px}.van-dialog__message--left{text-align:left}.van-dialog__message--right{text-align:right}.van-dialog__message--justify{text-align:justify}.van-dialog__footer{display:flex}.van-dialog__footer--round-button{padding:8px 24px 16px!important;position:relative!important}.van-dialog__button{flex:1}.van-dialog__cancel,.van-dialog__confirm{border:0!important}.van-dialog-bounce-enter{opacity:0;transform:translate3d(-50%,-50%,0) scale(.7)}.van-dialog-bounce-leave-active{opacity:0;transform:translate3d(-50%,-50%,0) scale(.9)} ================================================ FILE: miniprogram_npm/@vant/weapp/divider/index.d.ts ================================================ export {}; ================================================ FILE: miniprogram_npm/@vant/weapp/divider/index.js ================================================ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var component_1 = require("../common/component"); (0, component_1.VantComponent)({ props: { dashed: Boolean, hairline: Boolean, contentPosition: String, fontSize: String, borderColor: String, textColor: String, customStyle: String, }, }); ================================================ FILE: miniprogram_npm/@vant/weapp/divider/index.json ================================================ { "component": true, "usingComponents": {} } ================================================ FILE: miniprogram_npm/@vant/weapp/divider/index.wxml ================================================ ================================================ FILE: miniprogram_npm/@vant/weapp/divider/index.wxs ================================================ /* eslint-disable */ var style = require('../wxs/style.wxs'); var addUnit = require('../wxs/add-unit.wxs'); function rootStyle(data) { return style([ { 'border-color': data.borderColor, color: data.textColor, 'font-size': addUnit(data.fontSize), }, data.customStyle, ]); } module.exports = { rootStyle: rootStyle, }; ================================================ FILE: miniprogram_npm/@vant/weapp/divider/index.wxss ================================================ @import '../common/index.wxss';.van-divider{align-items:center;border:0 solid var(--divider-border-color,#ebedf0);color:var(--divider-text-color,#969799);display:flex;font-size:var(--divider-font-size,14px);line-height:var(--divider-line-height,24px);margin:var(--divider-margin,16px 0)}.van-divider:after,.van-divider:before{border-color:inherit;border-style:inherit;border-width:1px 0 0;box-sizing:border-box;display:block;flex:1;height:1px}.van-divider:before{content:""}.van-divider--hairline:after,.van-divider--hairline:before{transform:scaleY(.5)}.van-divider--dashed{border-style:dashed}.van-divider--center:before,.van-divider--left:before,.van-divider--right:before{margin-right:var(--divider-content-padding,16px)}.van-divider--center:after,.van-divider--left:after,.van-divider--right:after{content:"";margin-left:var(--divider-content-padding,16px)}.van-divider--left:before{max-width:var(--divider-content-left-width,10%)}.van-divider--right:after{max-width:var(--divider-content-right-width,10%)} ================================================ FILE: miniprogram_npm/@vant/weapp/dropdown-item/index.d.ts ================================================ export {}; ================================================ FILE: miniprogram_npm/@vant/weapp/dropdown-item/index.js ================================================ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var relation_1 = require("../common/relation"); var component_1 = require("../common/component"); (0, component_1.VantComponent)({ classes: ['item-title-class'], field: true, relation: (0, relation_1.useParent)('dropdown-menu', function () { this.updateDataFromParent(); }), props: { value: { type: null, observer: 'rerender', }, title: { type: String, observer: 'rerender', }, disabled: Boolean, titleClass: { type: String, observer: 'rerender', }, options: { type: Array, value: [], observer: 'rerender', }, popupStyle: String, useBeforeToggle: { type: Boolean, value: false, }, rootPortal: { type: Boolean, value: false, }, }, data: { transition: true, showPopup: false, showWrapper: false, displayTitle: '', safeAreaTabBar: false, }, methods: { rerender: function () { var _this = this; wx.nextTick(function () { var _a; (_a = _this.parent) === null || _a === void 0 ? void 0 : _a.updateItemListData(); }); }, updateDataFromParent: function () { if (this.parent) { var _a = this.parent.data, overlay = _a.overlay, duration = _a.duration, activeColor = _a.activeColor, closeOnClickOverlay = _a.closeOnClickOverlay, direction = _a.direction, safeAreaTabBar = _a.safeAreaTabBar; this.setData({ overlay: overlay, duration: duration, activeColor: activeColor, closeOnClickOverlay: closeOnClickOverlay, direction: direction, safeAreaTabBar: safeAreaTabBar, }); } }, onOpen: function () { this.$emit('open'); }, onOpened: function () { this.$emit('opened'); }, onClose: function () { this.$emit('close'); }, onClosed: function () { this.$emit('closed'); this.setData({ showWrapper: false }); }, onOptionTap: function (event) { var option = event.currentTarget.dataset.option; var value = option.value; var shouldEmitChange = this.data.value !== value; this.setData({ showPopup: false, value: value }); this.$emit('close'); this.rerender(); if (shouldEmitChange) { this.$emit('change', value); } }, toggle: function (show, options) { var _this = this; if (options === void 0) { options = {}; } var showPopup = this.data.showPopup; if (typeof show !== 'boolean') { show = !showPopup; } if (show === showPopup) { return; } this.onBeforeToggle(show).then(function (status) { var _a; if (!status) { return; } _this.setData({ transition: !options.immediate, showPopup: show, }); if (show) { (_a = _this.parent) === null || _a === void 0 ? void 0 : _a.getChildWrapperStyle().then(function (wrapperStyle) { _this.setData({ wrapperStyle: wrapperStyle, showWrapper: true }); _this.rerender(); }); } else { _this.rerender(); } }); }, onBeforeToggle: function (status) { var _this = this; var useBeforeToggle = this.data.useBeforeToggle; if (!useBeforeToggle) { return Promise.resolve(true); } return new Promise(function (resolve) { _this.$emit('before-toggle', { status: status, callback: function (value) { return resolve(value); }, }); }); }, }, }); ================================================ FILE: miniprogram_npm/@vant/weapp/dropdown-item/index.json ================================================ { "component": true, "usingComponents": { "van-popup": "../popup/index", "van-cell": "../cell/index", "van-icon": "../icon/index" } } ================================================ FILE: miniprogram_npm/@vant/weapp/dropdown-item/index.wxml ================================================ {{ item.text }} ================================================ FILE: miniprogram_npm/@vant/weapp/dropdown-item/index.wxss ================================================ @import '../common/index.wxss';.van-dropdown-item{left:0;overflow:hidden;position:fixed;right:0}.van-dropdown-item__option{text-align:left}.van-dropdown-item__option--active .van-dropdown-item__icon,.van-dropdown-item__option--active .van-dropdown-item__title{color:var(--dropdown-menu-option-active-color,#ee0a24)}.van-dropdown-item--up{top:0}.van-dropdown-item--down{bottom:0}.van-dropdown-item__icon{display:block;line-height:inherit} ================================================ FILE: miniprogram_npm/@vant/weapp/dropdown-item/shared.d.ts ================================================ export interface Option { text: string; value: string | number; icon: string; } ================================================ FILE: miniprogram_npm/@vant/weapp/dropdown-item/shared.js ================================================ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); ================================================ FILE: miniprogram_npm/@vant/weapp/dropdown-menu/index.d.ts ================================================ export {}; ================================================ FILE: miniprogram_npm/@vant/weapp/dropdown-menu/index.js ================================================ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var component_1 = require("../common/component"); var relation_1 = require("../common/relation"); var utils_1 = require("../common/utils"); var ARRAY = []; (0, component_1.VantComponent)({ field: true, classes: ['title-class'], relation: (0, relation_1.useChildren)('dropdown-item', function () { this.updateItemListData(); }), props: { activeColor: { type: String, observer: 'updateChildrenData', }, overlay: { type: Boolean, value: true, observer: 'updateChildrenData', }, zIndex: { type: Number, value: 10, }, duration: { type: Number, value: 200, observer: 'updateChildrenData', }, direction: { type: String, value: 'down', observer: 'updateChildrenData', }, safeAreaTabBar: { type: Boolean, value: false, }, closeOnClickOverlay: { type: Boolean, value: true, observer: 'updateChildrenData', }, closeOnClickOutside: { type: Boolean, value: true, }, }, data: { itemListData: [], }, beforeCreate: function () { var windowHeight = (0, utils_1.getSystemInfoSync)().windowHeight; this.windowHeight = windowHeight; ARRAY.push(this); }, destroyed: function () { var _this = this; ARRAY = ARRAY.filter(function (item) { return item !== _this; }); }, methods: { updateItemListData: function () { this.setData({ itemListData: this.children.map(function (child) { return child.data; }), }); }, updateChildrenData: function () { this.children.forEach(function (child) { child.updateDataFromParent(); }); }, toggleItem: function (active) { this.children.forEach(function (item, index) { var showPopup = item.data.showPopup; if (index === active) { item.toggle(); } else if (showPopup) { item.toggle(false, { immediate: true }); } }); }, close: function () { this.children.forEach(function (child) { child.toggle(false, { immediate: true }); }); }, getChildWrapperStyle: function () { var _this = this; var _a = this.data, zIndex = _a.zIndex, direction = _a.direction; return (0, utils_1.getRect)(this, '.van-dropdown-menu').then(function (rect) { var _a = rect.top, top = _a === void 0 ? 0 : _a, _b = rect.bottom, bottom = _b === void 0 ? 0 : _b; var offset = direction === 'down' ? bottom : _this.windowHeight - top; var wrapperStyle = "z-index: ".concat(zIndex, ";"); if (direction === 'down') { wrapperStyle += "top: ".concat((0, utils_1.addUnit)(offset), ";"); } else { wrapperStyle += "bottom: ".concat((0, utils_1.addUnit)(offset), ";"); } return wrapperStyle; }); }, onTitleTap: function (event) { var _this = this; var index = event.currentTarget.dataset.index; var child = this.children[index]; if (!child.data.disabled) { ARRAY.forEach(function (menuItem) { if (menuItem && menuItem.data.closeOnClickOutside && menuItem !== _this) { menuItem.close(); } }); this.toggleItem(index); } }, }, }); ================================================ FILE: miniprogram_npm/@vant/weapp/dropdown-menu/index.json ================================================ { "component": true } ================================================ FILE: miniprogram_npm/@vant/weapp/dropdown-menu/index.wxml ================================================ {{ computed.displayTitle(item) }} ================================================ FILE: miniprogram_npm/@vant/weapp/dropdown-menu/index.wxs ================================================ /* eslint-disable */ function displayTitle(item) { if (item.title) { return item.title; } var match = item.options.filter(function(option) { return option.value === item.value; }); var displayTitle = match.length ? match[0].text : ''; return displayTitle; } module.exports = { displayTitle: displayTitle }; ================================================ FILE: miniprogram_npm/@vant/weapp/dropdown-menu/index.wxss ================================================ @import '../common/index.wxss';.van-dropdown-menu{background-color:var(--dropdown-menu-background-color,#fff);box-shadow:var(--dropdown-menu-box-shadow,0 2px 12px hsla(210,1%,40%,.12));display:flex;height:var(--dropdown-menu-height,50px);-webkit-user-select:none;user-select:none}.van-dropdown-menu__item{align-items:center;display:flex;flex:1;justify-content:center;min-width:0}.van-dropdown-menu__item:active{opacity:.7}.van-dropdown-menu__item--disabled:active{opacity:1}.van-dropdown-menu__item--disabled .van-dropdown-menu__title{color:var(--dropdown-menu-title-disabled-text-color,#969799)}.van-dropdown-menu__title{box-sizing:border-box;color:var(--dropdown-menu-title-text-color,#323233);font-size:var(--dropdown-menu-title-font-size,15px);line-height:var(--dropdown-menu-title-line-height,18px);max-width:100%;padding:var(--dropdown-menu-title-padding,0 24px 0 8px);position:relative}.van-dropdown-menu__title:after{border-color:transparent transparent currentcolor currentcolor;border-style:solid;border-width:3px;content:"";margin-top:-5px;opacity:.8;position:absolute;right:11px;top:50%;transform:rotate(-45deg)}.van-dropdown-menu__title--active{color:var(--dropdown-menu-title-active-text-color,#ee0a24)}.van-dropdown-menu__title--down:after{margin-top:-1px;transform:rotate(135deg)} ================================================ FILE: miniprogram_npm/@vant/weapp/empty/index.d.ts ================================================ export {}; ================================================ FILE: miniprogram_npm/@vant/weapp/empty/index.js ================================================ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var component_1 = require("../common/component"); (0, component_1.VantComponent)({ props: { description: String, image: { type: String, value: 'default', }, }, }); ================================================ FILE: miniprogram_npm/@vant/weapp/empty/index.json ================================================ { "component": true, "usingComponents": {} } ================================================ FILE: miniprogram_npm/@vant/weapp/empty/index.wxml ================================================ {{ description }} ================================================ FILE: miniprogram_npm/@vant/weapp/empty/index.wxs ================================================ /* eslint-disable */ var PRESETS = ['error', 'search', 'default', 'network']; function imageUrl(image) { if (PRESETS.indexOf(image) !== -1) { return 'https://img.yzcdn.cn/vant/empty-image-' + image + '.png'; } return image; } module.exports = { imageUrl: imageUrl, }; ================================================ FILE: miniprogram_npm/@vant/weapp/empty/index.wxss ================================================ @import '../common/index.wxss';.van-empty{align-items:center;box-sizing:border-box;display:flex;flex-direction:column;justify-content:center;padding:32px 0}.van-empty__image{height:160px;width:160px}.van-empty__image:empty{display:none}.van-empty__image__img{height:100%;width:100%}.van-empty__image:not(:empty)+.van-empty__image{display:none}.van-empty__description{color:#969799;font-size:14px;line-height:20px;margin-top:16px;padding:0 60px}.van-empty__description:empty,.van-empty__description:not(:empty)+.van-empty__description{display:none}.van-empty__bottom{margin-top:24px} ================================================ FILE: miniprogram_npm/@vant/weapp/field/index.d.ts ================================================ export {}; ================================================ FILE: miniprogram_npm/@vant/weapp/field/index.js ================================================ "use strict"; var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; Object.defineProperty(exports, "__esModule", { value: true }); var utils_1 = require("../common/utils"); var component_1 = require("../common/component"); var props_1 = require("./props"); (0, component_1.VantComponent)({ field: true, classes: ['input-class', 'right-icon-class', 'label-class'], props: __assign(__assign(__assign(__assign({}, props_1.commonProps), props_1.inputProps), props_1.textareaProps), { size: String, icon: String, label: String, error: Boolean, center: Boolean, isLink: Boolean, leftIcon: String, rightIcon: String, autosize: null, required: Boolean, iconClass: String, clickable: Boolean, inputAlign: String, customStyle: String, errorMessage: String, arrowDirection: String, showWordLimit: Boolean, errorMessageAlign: String, readonly: { type: Boolean, observer: 'setShowClear', }, clearable: { type: Boolean, observer: 'setShowClear', }, clearTrigger: { type: String, value: 'focus', }, border: { type: Boolean, value: true, }, titleWidth: { type: String, value: '6.2em', }, clearIcon: { type: String, value: 'clear', }, extraEventParams: { type: Boolean, value: false, } }), data: { focused: false, innerValue: '', showClear: false, }, watch: { value: function (value) { if (value !== this.value) { this.setData({ innerValue: value }); this.value = value; this.setShowClear(); } }, clearTrigger: function () { this.setShowClear(); }, }, created: function () { this.value = this.data.value; this.setData({ innerValue: this.value }); }, methods: { formatValue: function (value) { var maxlength = this.data.maxlength; if (maxlength !== -1 && value.length > maxlength) { return value.slice(0, maxlength); } return value; }, onInput: function (event) { var _a = (event.detail || {}).value, value = _a === void 0 ? '' : _a; var formatValue = this.formatValue(value); this.value = formatValue; this.setShowClear(); return this.emitChange(__assign(__assign({}, event.detail), { value: formatValue })); }, onFocus: function (event) { this.focused = true; this.setShowClear(); this.$emit('focus', event.detail); }, onBlur: function (event) { this.focused = false; this.setShowClear(); this.$emit('blur', event.detail); }, onClickIcon: function () { this.$emit('click-icon'); }, onClickInput: function (event) { this.$emit('click-input', event.detail); }, onClear: function () { var _this = this; this.setData({ innerValue: '' }); this.value = ''; this.setShowClear(); (0, utils_1.nextTick)(function () { _this.emitChange({ value: '' }); _this.$emit('clear', ''); }); }, onConfirm: function (event) { var _a = (event.detail || {}).value, value = _a === void 0 ? '' : _a; this.value = value; this.setShowClear(); this.$emit('confirm', value); }, setValue: function (value) { this.value = value; this.setShowClear(); if (value === '') { this.setData({ innerValue: '' }); } this.emitChange({ value: value }); }, onLineChange: function (event) { this.$emit('linechange', event.detail); }, onKeyboardHeightChange: function (event) { this.$emit('keyboardheightchange', event.detail); }, onBindNicknameReview: function (event) { this.$emit('nicknamereview', event.detail); }, emitChange: function (detail) { var extraEventParams = this.data.extraEventParams; this.setData({ value: detail.value }); var result; var data = extraEventParams ? __assign(__assign({}, detail), { callback: function (data) { result = data; } }) : detail.value; this.$emit('input', data); this.$emit('change', data); return result; }, setShowClear: function () { var _a = this.data, clearable = _a.clearable, readonly = _a.readonly, clearTrigger = _a.clearTrigger; var _b = this, focused = _b.focused, value = _b.value; var showClear = false; if (clearable && !readonly) { var hasValue = !!value; var trigger = clearTrigger === 'always' || (clearTrigger === 'focus' && focused); showClear = hasValue && trigger; } this.setView({ showClear: showClear }); }, noop: function () { }, }, }); ================================================ FILE: miniprogram_npm/@vant/weapp/field/index.json ================================================ { "component": true, "usingComponents": { "van-cell": "../cell/index", "van-icon": "../icon/index" } } ================================================ FILE: miniprogram_npm/@vant/weapp/field/index.wxml ================================================ ================================================ FILE: miniprogram_npm/@vant/weapp/field/index.wxs ================================================ /* eslint-disable */ var style = require('../wxs/style.wxs'); var addUnit = require('../wxs/add-unit.wxs'); function inputStyle(autosize) { if (autosize && autosize.constructor === 'Object') { return style({ 'min-height': addUnit(autosize.minHeight), 'max-height': addUnit(autosize.maxHeight), }); } return ''; } module.exports = { inputStyle: inputStyle, }; ================================================ FILE: miniprogram_npm/@vant/weapp/field/index.wxss ================================================ @import '../common/index.wxss';.van-field{--cell-icon-size:var(--field-icon-size,16px)}.van-field__label{color:var(--field-label-color,#646566)}.van-field__label--disabled{color:var(--field-disabled-text-color,#c8c9cc)}.van-field__body{align-items:center;display:flex}.van-field__body--textarea{box-sizing:border-box;line-height:1.2em;min-height:var(--cell-line-height,24px);padding:3.6px 0}.van-field__control:empty+.van-field__control{display:block}.van-field__control{background-color:initial;border:0;box-sizing:border-box;color:var(--field-input-text-color,#323233);display:none;height:var(--cell-line-height,24px);line-height:inherit;margin:0;min-height:var(--cell-line-height,24px);padding:0;position:relative;resize:none;text-align:left;width:100%}.van-field__control:empty{display:none}.van-field__control--textarea{height:var(--field-text-area-min-height,18px);min-height:var(--field-text-area-min-height,18px)}.van-field__control--error{color:var(--field-input-error-text-color,#ee0a24)}.van-field__control--disabled{background-color:initial;color:var(--field-input-disabled-text-color,#c8c9cc);opacity:1}.van-field__control--center{text-align:center}.van-field__control--right{text-align:right}.van-field__control--custom{align-items:center;display:flex;min-height:var(--cell-line-height,24px)}.van-field__placeholder{color:var(--field-placeholder-text-color,#c8c9cc);left:0;pointer-events:none;position:absolute;right:0;top:0}.van-field__placeholder--error{color:var(--field-error-message-color,#ee0a24)}.van-field__icon-root{align-items:center;display:flex;min-height:var(--cell-line-height,24px)}.van-field__clear-root,.van-field__icon-container{line-height:inherit;margin-right:calc(var(--padding-xs, 8px)*-1);padding:0 var(--padding-xs,8px);vertical-align:middle}.van-field__button,.van-field__clear-root,.van-field__icon-container{flex-shrink:0}.van-field__clear-root{color:var(--field-clear-icon-color,#c8c9cc);font-size:var(--field-clear-icon-size,16px)}.van-field__icon-container{color:var(--field-icon-container-color,#969799);font-size:var(--field-icon-size,16px)}.van-field__icon-container:empty{display:none}.van-field__button{padding-left:var(--padding-xs,8px)}.van-field__button:empty{display:none}.van-field__error-message{color:var(--field-error-message-color,#ee0a24);display:block;font-size:var(--field-error-message-text-font-size,12px);text-align:left}.van-field__error-message--center{text-align:center}.van-field__error-message--right{text-align:right}.van-field__word-limit{color:var(--field-word-limit-color,#646566);font-size:var(--field-word-limit-font-size,12px);line-height:var(--field-word-limit-line-height,16px);margin-top:var(--padding-base,4px);text-align:right}.van-field__word-num{display:inline}.van-field__word-num--full{color:var(--field-word-num-full-color,#ee0a24)} ================================================ FILE: miniprogram_npm/@vant/weapp/field/input.wxml ================================================ ================================================ FILE: miniprogram_npm/@vant/weapp/field/props.d.ts ================================================ /// export declare const commonProps: WechatMiniprogram.Component.PropertyOption; export declare const inputProps: WechatMiniprogram.Component.PropertyOption; export declare const textareaProps: WechatMiniprogram.Component.PropertyOption; ================================================ FILE: miniprogram_npm/@vant/weapp/field/props.js ================================================ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.textareaProps = exports.inputProps = exports.commonProps = void 0; exports.commonProps = { value: String, placeholder: String, placeholderStyle: String, placeholderClass: String, disabled: Boolean, maxlength: { type: Number, value: -1, }, cursorSpacing: { type: Number, value: 50, }, autoFocus: Boolean, focus: Boolean, cursor: { type: Number, value: -1, }, selectionStart: { type: Number, value: -1, }, selectionEnd: { type: Number, value: -1, }, adjustPosition: { type: Boolean, value: true, }, holdKeyboard: Boolean, }; exports.inputProps = { type: { type: String, value: 'text', }, password: Boolean, confirmType: String, confirmHold: Boolean, alwaysEmbed: Boolean, }; exports.textareaProps = { autoHeight: Boolean, fixed: Boolean, showConfirmBar: { type: Boolean, value: true, }, disableDefaultPadding: { type: Boolean, value: true, }, }; ================================================ FILE: miniprogram_npm/@vant/weapp/field/textarea.wxml ================================================ 上传凭证 (选填,最多9张) 售后详情 {{ curRufund.goodInfo.goodsName }} x{{ curRufund.baseInfo.number }} ¥{{ curRufund.baseInfo.amount }} 已申请,等待商家处理,请耐心等待 商家已拒绝,如诉求未解决请联系客服 商家正在处理中,请耐心等待 本次售后已处理完成 📦 商品寄回地址 收货人: {{ logisticsContent.linkMan }} 联系电话: {{ logisticsContent.mobile }} 收货地址: {{ logisticsContent.address }} 已填写快递信息 快递公司: {{ logisticsContent.shipperName }} 快递单号: {{ logisticsContent.trackingNumber }} 申请时间 {{ curRufund.baseInfo.dateAdd }} 售后类型 {{ curRufund.baseInfo.typeStr }} 物流状态 {{ curRufund.baseInfo.logisticsStatusStr }} 售后原因 {{ curRufund.baseInfo.reason }} 备注说明 {{ curRufund.baseInfo.remark }} 举证照片 💬 联系客服 填写快递信息 💡 请填写您寄回商品的快递信息 快递公司 快递单号 ================================================ FILE: pages/order/refundApply.wxss ================================================ /* 页面容器 */ page { background: #F5F5F5; } .refund-container { min-height: 100vh; padding-bottom: 40rpx; } /* 通用标题样式 */ .section-title { display: flex; align-items: center; padding: 32rpx 32rpx 24rpx; position: relative; } .title-line { width: 6rpx; height: 32rpx; background: linear-gradient(180deg, #E4393C 0%, #FF6B6B 100%); border-radius: 3rpx; margin-right: 16rpx; } .title-text { font-size: 32rpx; font-weight: 600; color: #333; letter-spacing: 0.5rpx; } .title-tip { font-size: 24rpx; color: #999; margin-left: 8rpx; } /* 通用卡片样式 */ .section-card { background: #fff; margin: 24rpx 24rpx 0; border-radius: 16rpx; overflow: hidden; box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.04); } /* 售后历史记录 */ .refund-history { background: #fff; margin: 24rpx 24rpx 0; border-radius: 16rpx; overflow: hidden; box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.04); } .history-list { padding: 0 32rpx 24rpx; } .history-item { display: flex; justify-content: space-between; align-items: center; padding: 24rpx 0; border-bottom: 1rpx solid #F0F0F0; } .history-item:last-child { border-bottom: none; } .history-goods { display: flex; flex: 1; margin-right: 24rpx; } .goods-image { width: 120rpx; height: 120rpx; border-radius: 12rpx; background: #F5F5F5; flex-shrink: 0; } .goods-info { flex: 1; margin-left: 20rpx; display: flex; flex-direction: column; justify-content: space-between; } .goods-name { font-size: 28rpx; color: #333; line-height: 40rpx; overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; } .goods-meta { display: flex; justify-content: space-between; align-items: center; margin-top: 8rpx; } .goods-num { font-size: 24rpx; color: #999; } .goods-price { font-size: 28rpx; color: #E4393C; font-weight: 600; } .apply-time { font-size: 24rpx; color: #999; margin-top: 8rpx; } .history-status { display: flex; align-items: center; flex-shrink: 0; } .status-text { font-size: 26rpx; color: #E4393C; font-weight: 500; } .arrow-icon { font-size: 48rpx; color: #DCDCDC; margin-left: 8rpx; line-height: 1; } /* 商品列表 */ .goods-list { padding: 0 32rpx 24rpx; } .goods-item { display: flex; justify-content: space-between; align-items: center; padding: 28rpx 0; border-bottom: 1rpx solid #F0F0F0; } .goods-item:last-child { border-bottom: none; } .goods-item.disabled { opacity: 0.5; } .goods-content { flex: 1; margin-right: 24rpx; } .goods-name-text { font-size: 28rpx; color: #333; line-height: 40rpx; } .not-support { font-size: 24rpx; color: #FF6B6B; margin-top: 8rpx; } /* 商品预览 */ .goods-preview { display: flex; padding: 24rpx 32rpx; background: linear-gradient(135deg, #FFF9F9 0%, #FFFFFF 100%); border-bottom: 1rpx solid #F0F0F0; } .preview-image { width: 140rpx; height: 140rpx; border-radius: 12rpx; background: #F5F5F5; flex-shrink: 0; } .preview-info { flex: 1; margin-left: 24rpx; display: flex; flex-direction: column; justify-content: center; } .preview-name { font-size: 30rpx; color: #333; font-weight: 500; line-height: 42rpx; overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; } .preview-price { font-size: 36rpx; color: #E4393C; font-weight: 600; margin-top: 16rpx; } .preview-price::before { content: '¥'; font-size: 28rpx; } /* 数量选择器 */ .quantity-selector { display: flex; justify-content: space-between; align-items: center; padding: 32rpx; } .selector-label { font-size: 28rpx; color: #333; font-weight: 500; } /* 选项列表 */ .option-list, .reason-list { padding: 0 32rpx 24rpx; } .option-item, .reason-item { display: flex; justify-content: space-between; align-items: center; padding: 28rpx 0; border-bottom: 1rpx solid #F0F0F0; } .option-item:last-child, .reason-item:last-child { border-bottom: none; } .option-text, .reason-text { font-size: 28rpx; color: #333; flex: 1; margin-right: 24rpx; } /* 备注输入框 */ .remark-box { padding: 24rpx 32rpx 32rpx; } .remark-input { width: 100%; min-height: 180rpx; padding: 24rpx; background: #F8F8F8; border-radius: 12rpx; font-size: 28rpx; color: #333; line-height: 42rpx; box-sizing: border-box; } .remark-placeholder { color: #BFBFBF; } /* 上传区域 */ .upload-box { padding: 24rpx 32rpx 32rpx; } /* 提交按钮 */ .submit-box { padding: 40rpx 24rpx 0; } .submit-btn { width: 100%; height: 96rpx; line-height: 96rpx; background: linear-gradient(135deg, #E4393C 0%, #FF6B6B 100%); border-radius: 48rpx; font-size: 32rpx; color: #fff; font-weight: 600; border: none; box-shadow: 0 8rpx 24rpx rgba(228, 57, 60, 0.3); letter-spacing: 2rpx; } .submit-btn::after { border: none; } /* 底部安全区 */ .safe-area { height: 40rpx; } /* ========== 弹窗样式 ========== */ .popup-container { background: #F5F5F5; padding-bottom: 40rpx; } /* 弹窗头部 */ .popup-header { display: flex; justify-content: space-between; align-items: center; padding: 32rpx; background: #fff; position: sticky; top: 0; z-index: 10; } .popup-title { font-size: 34rpx; font-weight: 600; color: #333; } .popup-close { width: 56rpx; height: 56rpx; display: flex; align-items: center; justify-content: center; font-size: 40rpx; color: #999; background: #F5F5F5; border-radius: 50%; } /* 弹窗商品信息 */ .popup-goods { display: flex; padding: 24rpx 32rpx; background: #fff; margin-top: 2rpx; } .popup-goods-image { width: 140rpx; height: 140rpx; border-radius: 12rpx; background: #F5F5F5; flex-shrink: 0; } .popup-goods-info { flex: 1; margin-left: 24rpx; display: flex; flex-direction: column; justify-content: center; } .popup-goods-name { font-size: 30rpx; color: #333; font-weight: 500; line-height: 42rpx; overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; } .popup-goods-meta { display: flex; justify-content: space-between; align-items: center; margin-top: 16rpx; } .popup-goods-num { font-size: 26rpx; color: #999; } .popup-goods-price { font-size: 36rpx; color: #E4393C; font-weight: 600; } /* 状态提示 */ .popup-notice { display: flex; align-items: center; padding: 24rpx 32rpx; margin: 24rpx 24rpx 0; border-radius: 12rpx; background: #FFF9F0; border-left: 6rpx solid #FF9800; } .popup-notice.info { background: #E8F4FF; border-left-color: #1890FF; } .popup-notice.success { background: #F0F9F0; border-left-color: #52C41A; } .popup-notice.error { background: #FFF1F0; border-left-color: #FF4D4F; } .notice-icon { width: 48rpx; height: 48rpx; display: flex; align-items: center; justify-content: center; font-size: 32rpx; margin-right: 16rpx; } .notice-text { flex: 1; font-size: 26rpx; color: #666; line-height: 38rpx; } /* 详细信息 */ .popup-details { background: #fff; margin: 24rpx 24rpx 0; border-radius: 12rpx; padding: 16rpx 32rpx; } .detail-item { display: flex; padding: 24rpx 0; border-bottom: 1rpx solid #F0F0F0; } .detail-item:last-child { border-bottom: none; } .detail-label { width: 160rpx; font-size: 28rpx; color: #999; flex-shrink: 0; } .detail-value { flex: 1; font-size: 28rpx; color: #333; text-align: right; } .detail-value.remark { text-align: left; line-height: 40rpx; } /* 举证照片 */ .popup-photos { background: #fff; margin: 24rpx 24rpx 0; border-radius: 12rpx; padding: 24rpx 32rpx 32rpx; } .photos-title { font-size: 28rpx; color: #333; font-weight: 500; margin-bottom: 20rpx; } .photos-grid { display: flex; flex-wrap: wrap; margin: -8rpx; } .photo-item { width: 200rpx; height: 200rpx; border-radius: 12rpx; background: #F5F5F5; margin: 8rpx; } /* 底部操作 */ .popup-actions { background: #fff; margin: 24rpx 24rpx 0; border-radius: 12rpx; padding: 24rpx 32rpx; } .action-service { display: flex; align-items: center; justify-content: center; padding: 24rpx; background: #F8F8F8; border-radius: 12rpx; margin-bottom: 20rpx; } .service-icon { font-size: 36rpx; margin-right: 12rpx; } .service-text { font-size: 28rpx; color: #333; font-weight: 500; } .action-btn-box { display: flex; } .action-btn { flex: 1; height: 88rpx; line-height: 88rpx; text-align: center; border-radius: 44rpx; font-size: 30rpx; font-weight: 500; border: none; } .action-btn::after { border: none; } .action-btn.cancel { background: linear-gradient(135deg, #E4393C 0%, #FF6B6B 100%); color: #fff; box-shadow: 0 8rpx 24rpx rgba(228, 57, 60, 0.3); } .action-btn.disabled { background: #F5F5F5; color: #BFBFBF; } .action-btn.disabled.success { background: #F0F9F0; color: #52C41A; } /* ========== 寄回地址卡片 ========== */ .back-address-card { background: #fff; margin: 24rpx 24rpx 0; border-radius: 12rpx; overflow: hidden; } .address-header { display: flex; align-items: center; padding: 24rpx 32rpx; background: linear-gradient(135deg, #FFF9F9 0%, #FFFFFF 100%); border-bottom: 1rpx solid #F0F0F0; } .header-icon { font-size: 40rpx; margin-right: 12rpx; } .header-title { font-size: 30rpx; color: #333; font-weight: 600; } .address-content { padding: 24rpx 32rpx; } .address-row { display: flex; margin-bottom: 20rpx; } .address-row:last-child { margin-bottom: 0; } .address-row.full { flex-direction: column; } .address-label { font-size: 28rpx; color: #999; min-width: 140rpx; flex-shrink: 0; } .address-row.full .address-label { margin-bottom: 12rpx; } .address-text { font-size: 28rpx; color: #333; line-height: 40rpx; flex: 1; } /* 填写快递按钮 */ .logistics-action { padding: 0 32rpx 32rpx; } .fill-logistics-btn { width: 100%; height: 88rpx; line-height: 88rpx; background: linear-gradient(135deg, #E4393C 0%, #FF6B6B 100%); border-radius: 44rpx; font-size: 30rpx; color: #fff; font-weight: 600; border: none; box-shadow: 0 8rpx 24rpx rgba(228, 57, 60, 0.3); } .fill-logistics-btn::after { border: none; } /* 已填写快递信息 */ .logistics-filled { padding: 0 32rpx 32rpx; } .filled-header { display: flex; align-items: center; padding: 20rpx 24rpx; background: #F0F9F0; border-radius: 12rpx; margin-bottom: 20rpx; } .filled-icon { width: 40rpx; height: 40rpx; display: flex; align-items: center; justify-content: center; background: #52C41A; color: #fff; border-radius: 50%; font-size: 24rpx; margin-right: 12rpx; } .filled-title { font-size: 28rpx; color: #52C41A; font-weight: 600; } .filled-content { padding: 20rpx 24rpx; background: #F8F8F8; border-radius: 12rpx; } .filled-row { display: flex; align-items: center; margin-bottom: 16rpx; } .filled-row:last-child { margin-bottom: 0; } .filled-label { font-size: 26rpx; color: #999; min-width: 140rpx; } .filled-value { font-size: 28rpx; color: #333; font-weight: 500; } /* ========== 快递信息输入弹窗 ========== */ .logistics-dialog { background: #fff; border-radius: 24rpx; overflow: hidden; } .dialog-header { display: flex; justify-content: space-between; align-items: center; padding: 32rpx; border-bottom: 1rpx solid #F0F0F0; } .dialog-title { font-size: 34rpx; font-weight: 600; color: #333; } .dialog-close { width: 56rpx; height: 56rpx; display: flex; align-items: center; justify-content: center; font-size: 40rpx; color: #999; background: #F5F5F5; border-radius: 50%; } .dialog-content { padding: 32rpx; } .dialog-tip { display: flex; align-items: center; padding: 20rpx 24rpx; background: #FFF9F0; border-radius: 12rpx; margin-bottom: 32rpx; border-left: 6rpx solid #FF9800; } .tip-icon { font-size: 32rpx; margin-right: 12rpx; } .tip-text { font-size: 26rpx; color: #666; line-height: 38rpx; } .input-group { margin-bottom: 32rpx; } .input-group:last-child { margin-bottom: 0; } .input-label { font-size: 28rpx; color: #333; font-weight: 500; margin-bottom: 16rpx; } .input-label::before { content: '*'; color: #E4393C; margin-right: 4rpx; } .input-field { width: 100%; height: 88rpx; padding: 0 24rpx; background: #F8F8F8; border-radius: 12rpx; font-size: 28rpx; color: #333; box-sizing: border-box; } .input-placeholder { color: #BFBFBF; } .dialog-actions { display: flex; padding: 24rpx 32rpx 32rpx; gap: 24rpx; } .dialog-btn { flex: 1; height: 88rpx; line-height: 88rpx; text-align: center; border-radius: 44rpx; font-size: 30rpx; font-weight: 500; border: none; } .dialog-btn::after { border: none; } .cancel-btn { background: #F5F5F5; color: #666; } .confirm-btn { background: linear-gradient(135deg, #E4393C 0%, #FF6B6B 100%); color: #fff; box-shadow: 0 8rpx 24rpx rgba(228, 57, 60, 0.3); } ================================================ FILE: pages/order-details/index.js ================================================ const WXAPI = require('apifm-wxapi') Page({ data:{ orderId:0, goodsList:[] }, onLoad:function(e){ // e.id = e.sfsdffd // e.payOrderNo = 'ZF2408290780106421' this.setData({ orderId: e.id, payOrderNo: e.payOrderNo, }) if (e.payOrderNo) { this.payLogs() } }, onShow() { this.orderDetail() }, async payLogs() { wx.showLoading({ title: '', }) const res = await WXAPI.payLogs({ token: wx.getStorageSync('token'), orderNo: this.data.payOrderNo }) wx.hideLoading() if (res.code != 0) { wx.showModal({ content: res.msg, showCancel: false }) return } const nextAction = res.data[0].nextAction if(!nextAction) { wx.navigateTo({ url: '/pages/asset/index', }) return } const _nextAction = JSON.parse(nextAction) if (_nextAction.type != 0) { wx.navigateTo({ url: '/pages/asset/index', }) return } this.setData({ orderId: _nextAction.id, }) this.orderDetail() }, async orderDetail() { if (!this.data.orderId) { return } wx.showLoading({ title: '', }) const res = await WXAPI.orderDetail(wx.getStorageSync('token'), this.data.orderId) wx.hideLoading() if (res.code != 0) { wx.showModal({ content: res.msg, showCancel: false }) return } // 绘制核销码 if (res.data.orderInfo.hxNumber && res.data.orderInfo.status > 0 && res.data.orderInfo.status < 3) { this.wxaQrcode(res.data.orderInfo.hxNumber) } // 子快递单信息 if (res.data.orderLogisticsShippers) { res.data.orderLogisticsShippers.forEach(ele => { if (ele.traces) { ele.tracesArray = JSON.parse (ele.traces) if (ele.tracesArray && ele.tracesArray.length > 0) { ele.tracesLast = ele.tracesArray[ele.tracesArray.length - 1].AcceptStation + '\n' + ele.tracesArray[ele.tracesArray.length - 1].AcceptTime } } }) } let iotControl = false res.data.goods.forEach(ele => { if (ele.iotControl) { iotControl = true } }) if (iotControl) { // 读取IoT设备列表 this._shopIotDevices() } let orderStores = null if (res.data.orderStores) { orderStores = res.data.orderStores.filter(ele => ele.type == 2) } if (!res.data.extJson || Object.keys(res.data.extJson).length == 0) { delete res.data.extJson } this.setData({ orderDetail: res.data, orderStores }) }, wuliuDetailsTap:function(e){ var orderId = e.currentTarget.dataset.id; wx.navigateTo({ url: "/pages/wuliu/index?id=" + orderId }) }, confirmBtnTap:function(e){ let that = this; let orderId = this.data.orderId; wx.showModal({ title: '确认您已收到商品?', content: '', success: function(res) { if (res.confirm) { WXAPI.orderDelivery(wx.getStorageSync('token'), orderId).then(function (res) { if (res.code == 0) { that.orderDetail() } }) } } }) }, async submitReputation(e) { let that = this; let postJsonString = {}; postJsonString.token = wx.getStorageSync('token'); postJsonString.orderId = this.data.orderId; let reputations = []; let i = 0; while (e.detail.value["orderGoodsId" + i]) { let orderGoodsId = e.detail.value["orderGoodsId" + i]; let goodReputation = e.detail.value["goodReputation" + i]; const goodReputationNumber = goodReputation let goodReputationRemark = e.detail.value["goodReputationRemark" + i]; if (!goodReputation) { goodReputation = 0 } else if(goodReputation <= 1) { goodReputation = 0 } else if(goodReputation <= 4) { goodReputation = 1 } else { goodReputation = 2 } let reputations_json = {}; reputations_json.id = orderGoodsId; reputations_json.reputation = goodReputation; reputations_json.reputationNumber = goodReputationNumber reputations_json.remark = goodReputationRemark; if (this.data.picsList && this.data.picsList[i] && this.data.picsList[i].length > 0) { reputations_json.pics = [] for (let index = 0; index < this.data.picsList[i].length; index++) { const pic = this.data.picsList[i][index]; const res = await WXAPI.uploadFileV2(wx.getStorageSync('token'), pic.url) if (res.code == 0) { reputations_json.pics.push(res.data.url) } } } reputations.push(reputations_json); i++; } postJsonString.reputations = reputations; WXAPI.orderReputation({ postJsonString: JSON.stringify(postJsonString) }).then(function (res) { if (res.code == 0) { that.orderDetail() } }) }, afterPicRead(e) { const idx = e.currentTarget.dataset.idx let picsList = this.data.picsList if (!picsList) { picsList = [] for (let index = 0; index < this.data.orderDetail.goods.length; index++) { picsList[index] = [] } } picsList[idx] = picsList[idx].concat(e.detail.file) this.setData({ picsList }) }, afterPicDel(e) { const idx = e.currentTarget.dataset.idx let picsList = this.data.picsList picsList[idx].splice(e.detail.index, 1) this.setData({ picsList }) }, async wxaQrcode(hxNumber) { // https://www.yuque.com/apifm/nu0f75/ak40es const accountInfo = wx.getAccountInfoSync() const envVersion = accountInfo.miniProgram.envVersion const res = await WXAPI.wxaQrcode({ scene: hxNumber, page: 'pages/order-details/scan-result', autoColor: true, expireHours: 1, env_version: envVersion, check_path: envVersion == 'release' ? true : false, }) if (res.code != 0) { wx.showModal({ content: res.msg, showCancel: false }) return } this.setData({ hxNumberQrcode: res.data }) }, async _shopIotDevices() { // https://www.yuque.com/apifm/nu0f75/ibg4icu15di25hfc const res = await WXAPI.shopIotDevices({ token: wx.getStorageSync('token'), orderId: this.data.orderId }) if (res.code == 0) { this.setData({ shopIotDevices: res.data }) } }, async shopIotCmds(e) { const idx = e.target.dataset.idx const item = this.data.shopIotDevices[idx] // https://www.yuque.com/apifm/nu0f75/rek5dwng8b9cdoko const res = await WXAPI.shopIotCmds({ token: wx.getStorageSync('token'), orderId: this.data.orderId, topic: item.topic }) if (res.code != 0) { wx.showModal({ content: res.msg }) return } this.setData({ cmdList: res.data, cmdListShow: true }) }, cmdClose() { this.setData({ cmdListShow: false }); }, async cmdSelect(event) { // https://www.yuque.com/apifm/nu0f75/uq495hlq3ho5kw4t console.log(event.detail); const res = await WXAPI.shopIotExecute({ token: wx.getStorageSync('token'), orderId: this.data.orderId, topic: event.detail.topic, cmdId: event.detail.id, }) if (res.code != 0) { wx.showModal({ content: res.msg }) } else { wx.showToast({ title: '已发送', }) } }, }) ================================================ FILE: pages/order-details/index.json ================================================ { "navigationBarTitleText": "订单详情" } ================================================ FILE: pages/order-details/index.wxml ================================================ {{orderDetail.orderInfo.statusStr}} 订单编号:{{orderDetail.orderInfo.orderNumber}} 物流信息 {{orderDetail.logistics.trackingNumber}} {{orderDetail.logisticsTraces[orderDetail.logisticsTraces.length-1].AcceptStation}} {{orderDetail.logisticsTraces[orderDetail.logisticsTraces.length-1].AcceptTime}} {{orderDetail.logistics.trackingNumber}} 暂无物流信息 {{orderDetail.logistics.linkMan}} {{orderDetail.logistics.mobile}} {{orderDetail.logistics.provinceStr}} {{orderDetail.logistics.cityStr}} {{orderDetail.logistics.areaStr}} {{orderDetail.logistics.address}} 核销二维码 出示给店员扫码或长按保存 商品信息 module.exports = { url : function(item) { if (item.supplyType == 'cps_jd') { return '/packageCps/pages/goods-details/cps-jd?id=' + item.goodsId } else if (item.supplyType == 'vop_jd') { return '/pages/goods-details/vop?id=' + item.yyId + '&goodsId=' + item.id } else if (item.supplyType == 'cps_pdd') { return '/packageCps/pages/goods-details/cps-pdd?id=' + item.goodsId } else if (item.supplyType == 'cps_taobao') { return '/packageCps/pages/goods-details/cps-taobao?id=' + item.goodsId } else { return '/pages/goods-details/index?id=' + item.goodsId } } }
日期详情 {{ item.remark }} ×{{ item.stores }} {{ item.day }} 优惠券 优惠券 {{item.coupon}} 其他信息 {{ key }} {{ item }} 订单金额 商品金额 ¥ {{orderDetail.orderInfo.amount}} 运费 ¥ {{orderDetail.orderInfo.amountLogistics}} {{ item.name }} ¥ {{ item.amount }} 应付总额 ¥ {{orderDetail.orderInfo.amountReal}} 订单记录 {{ item.typeStr }} {{ item.dateAdd }} 设备控制 {{ item.name }} 控制
================================================ FILE: pages/order-details/index.wxss ================================================ /* 全局样式 */ page { min-height: 100%; background: linear-gradient(to bottom, #f5f7fa 0%, #e8ecf1 100%); } .container { min-height: 100%; padding: 20rpx 24rpx; padding-bottom: 40rpx; } /* 卡片通用样式 */ .card-section { width: 100%; margin-bottom: 24rpx; background: #ffffff; border-radius: 24rpx; overflow: hidden; box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.04); } .card-title { display: flex; align-items: center; padding: 32rpx 32rpx 24rpx; font-size: 32rpx; font-weight: 600; color: #1a1a1a; } .title-line { width: 6rpx; height: 32rpx; background: linear-gradient(to bottom, #ff6b6b, #ee5a52); border-radius: 3rpx; margin-right: 16rpx; } /* 订单状态卡片 */ .status-card { width: 90%; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); border-radius: 24rpx; padding: 40rpx 32rpx; margin-bottom: 24rpx; box-shadow: 0 8rpx 24rpx rgba(102, 126, 234, 0.3); } .status-header { display: flex; align-items: center; } .status-icon-wrap { width: 96rpx; height: 96rpx; background: rgba(255, 255, 255, 0.2); border-radius: 50%; display: flex; align-items: center; justify-content: center; margin-right: 24rpx; backdrop-filter: blur(10rpx); } .status-icon { width: 64rpx; height: 64rpx; } .status-info { flex: 1; } .status-title { font-size: 36rpx; font-weight: 600; color: #ffffff; margin-bottom: 12rpx; text-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1); } .order-number-text { font-size: 24rpx; color: rgba(255, 255, 255, 0.85); letter-spacing: 0.5rpx; } /* 物流信息卡片 */ .logistics-card { margin: 0 32rpx 24rpx; padding: 28rpx; background: linear-gradient(135deg, #f6f8fc 0%, #fafbfd 100%); border-radius: 16rpx; border: 1rpx solid #e8ecf1; } .logistics-header { display: flex; align-items: flex-start; } .logistics-icon { width: 48rpx; height: 48rpx; margin-right: 20rpx; flex-shrink: 0; } .icon-img { width: 100%; height: 100%; } .logistics-info { flex: 1; min-width: 0; } .tracking-number { font-size: 28rpx; font-weight: 500; color: #2c3e50; margin-bottom: 12rpx; } .logistics-status { font-size: 26rpx; color: #5a6c7d; line-height: 40rpx; margin-bottom: 8rpx; } .logistics-time { font-size: 24rpx; color: #95a5a6; } .arrow-icon { width: 32rpx; height: 32rpx; display: flex; align-items: center; justify-content: center; margin-left: 16rpx; flex-shrink: 0; } .multi-logistics { margin: 0 32rpx 24rpx; border-radius: 16rpx; overflow: hidden; } /* 收货地址卡片 */ .address-card { margin: 0 32rpx 32rpx; padding: 28rpx; background: #fff; border-radius: 16rpx; border: 2rpx dashed #e8ecf1; display: flex; align-items: flex-start; } .address-icon { width: 40rpx; height: 40rpx; margin-right: 20rpx; flex-shrink: 0; } .address-info { flex: 1; min-width: 0; } .address-name { font-size: 30rpx; font-weight: 600; color: #2c3e50; margin-bottom: 16rpx; } .address-phone { font-weight: 400; color: #667eea; margin-left: 16rpx; } .address-detail { font-size: 26rpx; color: #5a6c7d; line-height: 40rpx; } /* 核销码卡片 */ .hx-section { background: linear-gradient(135deg, #ffeaa7 0%, #fdcb6e 100%); } .hx-card { padding: 32rpx; display: flex; flex-direction: column; align-items: center; } .hx-tip { font-size: 28rpx; color: #2d3436; margin-bottom: 24rpx; font-weight: 500; } .hx-qrcode { width: 400rpx; height: 400rpx; border-radius: 16rpx; background: #fff; padding: 24rpx; box-shadow: 0 8rpx 24rpx rgba(0, 0, 0, 0.1); } /* 商品信息卡片 */ .goods-section { padding-bottom: 0; } .goods-card { padding: 0 32rpx; } .reputation-group { margin-top: 24rpx; border-radius: 16rpx; overflow: hidden; } .action-btn-wrap { padding: 32rpx; display: flex; justify-content: flex-end; } .action-btn { border: none; border-radius: 48rpx; font-size: 28rpx; font-weight: 500; padding: 0 56rpx; height: 80rpx; line-height: 80rpx; box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.1); } .primary-btn { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: #ffffff; } /* 信息卡片通用样式 */ .info-card { padding: 16rpx 0 24rpx; width: 100%; box-sizing: border-box; } .info-row { display: flex; justify-content: space-between; align-items: flex-start; padding: 24rpx 32rpx; border-bottom: 1rpx solid #f0f2f5; min-height: 60rpx; } .info-row:last-child { border-bottom: none; } .info-label { font-size: 28rpx; color: #7f8c8d; font-weight: 400; flex-shrink: 0; margin-right: 32rpx; line-height: 40rpx; max-width: 240rpx; } .info-value { font-size: 28rpx; color: #2c3e50; font-weight: 500; text-align: right; word-break: break-all; flex: 1; line-height: 40rpx; } /* 其他信息特殊样式 */ .ext-json-section { background: linear-gradient(135deg, #fff9f5 0%, #ffffff 100%); border-left: 4rpx solid #ff6b6b; } .ext-info-card { background: #fff; border-radius: 0; margin: 0; padding: 8rpx 0 24rpx; width: 100%; } .ext-info-row { border-bottom: none !important; background: #fff; margin: 0 32rpx; padding: 20rpx 24rpx; border-radius: 12rpx; margin-bottom: 16rpx; box-shadow: 0 2rpx 12rpx rgba(255, 107, 107, 0.08); border: 1rpx solid #ffe8e8; display: flex; justify-content: left; align-items: center; gap: 16rpx; } .ext-info-row:last-child { margin-bottom: 0; } .ext-label { color: #e74c3c; font-weight: 600; font-size: 24rpx; padding: 8rpx 16rpx; background: linear-gradient(135deg, #ffe0e0 0%, #fff0f0 100%); border-radius: 8rpx; max-width: fit-content; line-height: 32rpx; display: flex; align-items: center; gap: 8rpx; margin-right: 0 !important; text-align: left; } .label-icon { font-size: 20rpx; color: #ff6b6b; line-height: 1; } .ext-value { color: #2c3e50; font-weight: 600; font-size: 30rpx; padding: 12rpx 20rpx; border-radius: 8rpx; line-height: 44rpx; text-align: left; word-break: break-all; margin-right: 0 !important; flex: none; width: auto; } /* 优惠券卡片 */ .coupon-card { padding: 24rpx 32rpx 32rpx; } .coupon-item { display: flex; justify-content: space-between; align-items: center; padding: 24rpx; background: linear-gradient(135deg, #fff3e0 0%, #ffe8cc 100%); border-radius: 12rpx; margin-bottom: 16rpx; } .coupon-item:last-child { margin-bottom: 0; } .coupon-label { font-size: 28rpx; color: #e67e22; font-weight: 500; } .coupon-value { font-size: 28rpx; color: #d35400; font-weight: 600; } .coupon-image { width: 100%; border-radius: 12rpx; margin-bottom: 16rpx; } .coupon-image:last-child { margin-bottom: 0; } /* 订单金额卡片 */ .amount-section { background: #ffffff; } .amount-card { padding: 16rpx 0 24rpx; width: 100%; box-sizing: border-box; } .amount-row { display: flex; justify-content: space-between; align-items: center; padding: 24rpx 32rpx; border-bottom: 1rpx solid #f5f7fa; min-height: 60rpx; } .amount-row:last-child { border-bottom: none; } .amount-label { font-size: 28rpx; color: #7f8c8d; font-weight: 400; line-height: 40rpx; } .amount-value { font-size: 30rpx; color: #2c3e50; font-weight: 600; line-height: 40rpx; } .total-row { margin: 16rpx 32rpx 0; padding: 28rpx 32rpx; background: linear-gradient(135deg, #fff4f4 0%, #ffe8e8 100%); border-radius: 16rpx; border-bottom: none; box-shadow: 0 4rpx 12rpx rgba(231, 76, 60, 0.1); } .total-label { font-size: 32rpx; font-weight: 700; color: #e74c3c; letter-spacing: 1rpx; } .total-value { font-size: 40rpx; font-weight: 700; color: #e74c3c; letter-spacing: 1rpx; } /* 订单记录卡片 */ .logs-card { padding: 24rpx 32rpx 32rpx; } .timeline { position: relative; padding-left: 40rpx; } .timeline-item { position: relative; padding-bottom: 48rpx; } .timeline-item:last-child { padding-bottom: 0; } .timeline-dot { position: absolute; left: -40rpx; top: 8rpx; width: 24rpx; height: 24rpx; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); border-radius: 50%; border: 4rpx solid #ffffff; box-shadow: 0 0 0 4rpx #f0f2f5; z-index: 2; } .timeline-line { position: absolute; left: -28rpx; top: 32rpx; bottom: -32rpx; width: 2rpx; background: linear-gradient(to bottom, #e8ecf1 0%, #f5f7fa 100%); z-index: 1; } .timeline-content { background: linear-gradient(135deg, #f8f9fc 0%, #ffffff 100%); border-radius: 12rpx; padding: 24rpx; border: 1rpx solid #e8ecf1; box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.04); transition: all 0.3s ease; } .log-operation { font-size: 30rpx; font-weight: 600; color: #2c3e50; margin-bottom: 12rpx; line-height: 42rpx; } .log-time { font-size: 24rpx; color: #95a5a6; line-height: 36rpx; display: flex; align-items: center; } .log-time::before { content: '🕐'; margin-right: 8rpx; font-size: 22rpx; } /* 设备控制卡片 */ .iot-card { padding: 16rpx 32rpx 32rpx; } .iot-item { display: flex; justify-content: space-between; align-items: center; padding: 28rpx 24rpx; background: linear-gradient(135deg, #e3f2fd 0%, #e1f5fe 100%); border-radius: 12rpx; margin-bottom: 16rpx; } .iot-item:last-child { margin-bottom: 0; } .iot-name { font-size: 28rpx; color: #1976d2; font-weight: 500; } .iot-control { display: flex; align-items: center; font-size: 26rpx; color: #1565c0; } .iot-control text { margin-right: 8rpx; } /* 底部安全区域 */ .bottom-safe-area { height: 40rpx; } /* 适配暗色模式 */ @media (prefers-color-scheme: dark) { page { background: linear-gradient(to bottom, #1a1a1a 0%, #2d2d2d 100%); } .card-section { background: #2d2d2d; box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.3); } .card-title { color: #f0f0f0; } } /* 动画效果 */ .card-section { animation: fadeInUp 0.4s ease-out; } @keyframes fadeInUp { from { opacity: 0; transform: translateY(20rpx); } to { opacity: 1; transform: translateY(0); } } /* 确保按钮样式正确 */ button::after { border: none; } ================================================ FILE: pages/order-details/scan-result.js ================================================ const WXAPI = require('apifm-wxapi') const AUTH = require('../../utils/auth') Page({ data: { apiOK: false, }, onLoad: function (e) { // e.hxNumber = '2307150981053363' // 读取小程序码中的核销码 console.log('e', e); if (e && e.scene) { const scene = decodeURIComponent(e.scene) if (scene) { e.hxNumber = scene } } this.setData({ hxNumber: e.hxNumber }) AUTH.checkHasLogined().then(isLogined => { if (isLogined) { this.orderDetail() } else { getApp().loginOK = () => { this.orderDetail() } } }) }, onShow() { }, async orderDetail() { wx.showLoading({ title: '', }) // https://www.yuque.com/apifm/nu0f75/qlzy3q const resConfig = await WXAPI.queryConfigValue('order_hx_uids') const res = await WXAPI.orderDetail(wx.getStorageSync('token'), '', this.data.hxNumber) wx.hideLoading() if (resConfig.code != 0) { wx.showModal({ content: resConfig.msg, showCancel: false }) return; } if (res.code != 0) { wx.showModal({ content: res.msg, showCancel: false }) return; } const order_hx_uids = resConfig.data const uid = wx.getStorageSync('uid') if (order_hx_uids.indexOf(uid) != -1) { this.setData({ apiOK: true, canHX: true, orderDetail: res.data }) } else { this.setData({ apiOK: true, orderDetail: res.data }) } }, wuliuDetailsTap: function (e) { var orderId = e.currentTarget.dataset.id; wx.navigateTo({ url: "/pages/wuliu/index?id=" + orderId }) }, async doneHx(){ wx.showLoading({ title: '处理中...', }) const res = await WXAPI.orderHXV2({ token: wx.getStorageSync('token'), hxNumber: this.data.hxNumber }) wx.hideLoading() if (res.code != 0) { wx.showToast({ title: res.msg, icon: 'none' }) } else { wx.showToast({ title: '核销完成', icon: 'none' }) this.orderDetail() } }, }) ================================================ FILE: pages/order-details/scan-result.json ================================================ { "navigationBarTitleText": "订单详情" } ================================================ FILE: pages/order-details/scan-result.wxml ================================================ {{orderDetail.orderInfo.statusStr}} 快递单号:{{orderDetail.logistics.trackingNumber}} {{orderDetail.logisticsTraces[orderDetail.logisticsTraces.length-1].AcceptStation}} {{orderDetail.logisticsTraces[orderDetail.logisticsTraces.length-1].AcceptTime}} 快递单号:{{orderDetail.logistics.trackingNumber}} 暂无物流信息 {{orderDetail.logistics.linkMan}} {{orderDetail.logistics.mobile}} {{orderDetail.logistics.provinceStr}} {{orderDetail.logistics.cityStr}} {{orderDetail.logistics.areaStr}} {{orderDetail.logistics.address}} 商品信息 module.exports = { url : function(item) { if (item.supplyType == 'cps_jd') { return '/packageCps/pages/goods-details/cps-jd?id=' + item.goodsId } else if (item.supplyType == 'vop_jd') { return '/pages/goods-details/vop?id=' + item.yyId + '&goodsId=' + item.id } else if (item.supplyType == 'cps_pdd') { return '/packageCps/pages/goods-details/cps-pdd?id=' + item.goodsId } else if (item.supplyType == 'cps_taobao') { return '/packageCps/pages/goods-details/cps-taobao?id=' + item.goodsId } else { return '/pages/goods-details/index?id=' + item.goodsId } } } {{item.goodsName}} ¥ {{item.amount}} {{item.property}} x {{item.number}} 优惠券 {{item.coupon}} 暂无核销权限 {{ orderDetail.orderInfo.statusStr }} 确认核销 ================================================ FILE: pages/order-details/scan-result.wxss ================================================ page{ min-height: 100%; background-color: #F2f2f2; } .container{ min-height: 100%; overflow: hidden; overflow-y: hidden; } .sec-wrap{ background-color: #fff; margin-top: 20rpx; } .bottom-fiexd{ position: fixed; bottom: 0; left: 0; } .sec-wrap .order-status{ width: 720rpx; margin-left: 30rpx; border-bottom: 1rpx solid #eee; height: 140rpx; display: flex; align-items: center; } .order-status .icon-box{ width: 80rpx; height: 80rpx; overflow: hidden; margin-right: 30rpx; } .order-status .icon-box .icon{ width: 80rpx; height: 80rpx; } .order-status .right-text{ width: 580rpx; overflow: hidden; } .order-status .right-text .status{ font-size:28rpx; color:#000; margin-bottom: 10rpx; } .order-status .right-text .red{ color:#e64340; } .order-status .right-text .des{ font-size:24rpx; color:#999; } .address-sec{ width: 720rpx; margin-left: 30rpx; display: flex; align-items: center; padding: 30rpx 0; } .address-sec .icon-box{ width: 30rpx; align-self: flex-start; overflow: hidden; margin-right: 35rpx; } .address-sec .icon-box .icon{ width: 30rpx; height: 30rpx; } .address-sec .right-box{ width: 620rpx; } .address-sec .right-box .name-tel{ font-size:28rpx; color:#000000; margin-bottom: 20rpx; } .address-sec .right-box .text{ font-size:24rpx; color:#888888; line-height:36rpx; height: 72rpx; overflow: hidden; } .wuliu-box{ width: 720rpx; margin-left: 30rpx; border-bottom: 1rpx solid #eee; display: flex; align-items: center; padding: 30rpx 0; } .wuliu-box .icon-box { width: 40rpx; height: 40rpx; overflow: hidden; margin-right: 31rpx; align-self: flex-start; } .wuliu-box .icon-box .icon{ width: 40rpx; height: 40rpx; } .wuliu-box .arrow-right{ width: 15rpx; height: 24rpx; } .wuliu-box .arrow-right .arrow{ width: 15rpx; height: 24rpx; } .wuliu-box .right-text{ width: 575rpx; margin-right: 30rpx; } .wuliu-box .right-text .order-number{ font-size:28rpx; color:#000; margin-bottom: 14rpx; } .wuliu-box .right-text .wuliu-text, .wuliu-box .right-text .wuliu-date{ font-size:24rpx; color:#888888; line-height:36rpx; } .goods-list{ width:100%; background-color: #fff; margin-bottom: 20rpx; margin-top: 20rpx; } .goods-list .list-title{ font-size: 28rpx; color: #000; padding: 30rpx 0 25rpx 30rpx; } .goods-list .a-goods{ width: 720rpx; margin-left: 30rpx; display: flex; /*justify-content: space-between;*/ border-top: 1px solid #eee; padding: 30rpx 30rpx 30rpx 0; } .goods-list .a-goods .img-box{ width: 160rpx; height:160rpx; overflow: hidden; margin-right: 20rpx; background-color: #d8d8d8; } .goods-list .img-box .img{ width: 160rpx; height:160rpx; } .goods-list .a-goods .text-box{ width: 510rpx; box-sizing: border-box; padding-top: 10rpx; } .goods-list .btn-row{ width: 720rpx; margin-left: 30rpx; border-top: 1rpx solid #eee; } .confirm-btn{ background:#ffffff; border:1rpx solid #e64340; border-radius:6rpx; width:164rpx; height:60rpx; line-height: 60rpx; margin: 20rpx 30rpx 20rpx auto; font-size:26rpx; color:#e64340; text-align:center; } .a-goods .text-box .arow{ display: flex; justify-content: space-between; align-items: center; } .a-goods .text-box .arow .goods-name{ width: 360rpx; font-size:26rpx; height: 74rpx; color:#000000; line-height: 1.6; overflow: hidden; } .a-goods .text-box .arow01{ margin-bottom: 30rpx; } .a-goods .text-box .arow .goods-price{ font-size:26rpx; color:#000000; align-self: flex-start; } .a-goods .text-box .arow .goods-label{ font-size: 26rpx; color: #999; } .a-goods .text-box .arow .goods-num{ font-size: 26rpx; color: #999; } .peisong-way{ width: 100%; background-color: #fff; margin-bottom: 20rpx; } .peisong-way .row-box{ width: 720rpx; display: flex; justify-content: space-between; align-items: center; box-sizing: border-box; padding: 24rpx 0; border-bottom: 1rpx solid #eee; margin-left: 30rpx; } .peisong-way .row-label{ font-size: 28rpx; color: #000; } .peisong-way .right-text{ font-size: 28rpx; color: #666; padding-right: 30rpx; } .peisong-way .liuyan{ width: 510rpx; font-size: 28rpx; } .goods-info{ width: 100%; background-color: #fff; margin-bottom: 120rpx; padding-bottom: 24rpx; } .goods-info .row-box{ width: 100%; display: flex; justify-content: space-between; align-items: center; box-sizing: border-box; padding: 24rpx 30rpx 12rpx 30rpx; font-size: 28rpx; color: #000; } .goods-info .row-box .right-text{ text-align: right; } .jiesuan-box{ display: flex; justify-content: space-between; width: 100%; height: 100rpx; position: fixed; bottom: 0; left: 0; border-top:1px solid #eee; background-color: #fff; z-index: 4; } .jiesuan-box .to-pay-btn{ width:250rpx; text-align: center; height: 100%; line-height: 100rpx; background-color: #e64340; font-size:32rpx; color:#ffffff; border-radius: 0; } .jiesuan-box .left-price{ display: flex; width: 500rpx; justify-content:flex-end; line-height: 100rpx; padding: 0 30rpx 0 0; font-size:28rpx; box-sizing: border-box; } .jiesuan-box .total{ color: #e64340; text-align: right; } .hx-title { text-align: center; } .hx-canvas { width: 650rpx; height: 650rpx; margin-left: 50rpx; } .btn { padding: 32rpx; } ================================================ FILE: pages/order-list/index.js ================================================ const WXAPI = require('apifm-wxapi') Page({ data: { page: 1, tabIndex: 0, statusType: [ { status: 9999, label: '全部' }, { status: 0, label: '待付款' }, { status: 1, label: '待发货' }, { status: 2, label: '待收货' }, { status: 3, label: '待评价' }, ], status: 9999, hasRefund: false, badges: [0, 0, 0, 0, 0] }, statusTap: function(e) { const index = e.detail.index const status = this.data.statusType[index].status this.setData({ page: 1, status }); this.orderList(); }, cancelOrderTap: function(e) { const that = this; const orderId = e.currentTarget.dataset.id; wx.showModal({ title: '确定要取消该订单吗?', content: '', success: function(res) { if (res.confirm) { WXAPI.orderClose(wx.getStorageSync('token'), orderId).then(function(res) { if (res.code == 0) { that.data.page = 1 that.orderList() that.getOrderStatistics() } }) } } }) }, async refundApply (e) { // 申请售后 todo 判断是去申请页面还是去查看页面 const orderId = e.currentTarget.dataset.id; const amount = e.currentTarget.dataset.amount; wx.navigateTo({ url: "/pages/order/refundApply?id=" + orderId }) }, toPayTap: function(e) { // 防止连续点击--开始 if (this.data.payButtonClicked) { wx.showToast({ title: '休息一下~', icon: 'none' }) return } this.data.payButtonClicked = true setTimeout(() => { this.data.payButtonClicked = false }, 3000) // 可自行修改时间间隔(目前是3秒内只能点击一次支付按钮) // 防止连续点击--结束 const that = this; const orderId = e.currentTarget.dataset.id; let money = e.currentTarget.dataset.money; const needScore = e.currentTarget.dataset.score; WXAPI.userAmount(wx.getStorageSync('token')).then(function(res) { if (res.code == 0) { const order_pay_user_balance = wx.getStorageSync('order_pay_user_balance') if (order_pay_user_balance != '1') { res.data.balance = 0 } // 增加提示框 if (res.data.score < needScore) { wx.showToast({ title: '您的积分不足,无法支付', icon: 'none' }) return; } let _msg = '订单金额: ' + money +' 元' if (res.data.balance > 0) { _msg += ',可用余额为 ' + res.data.balance +' 元' if (money - res.data.balance > 0) { _msg += ',仍需微信支付 ' + (money - res.data.balance).toFixed(2) + ' 元' } } if (needScore > 0) { _msg += ',并扣除 ' + needScore + ' 积分' } money = money - res.data.balance wx.showModal({ title: '请确认支付', content: _msg, confirmText: "确认支付", cancelText: "取消支付", success: function (res) { console.log(res); if (res.confirm) { that._toPayTap(orderId, money) } else { console.log('用户点击取消支付') } } }); } else { wx.showModal({ title: '错误', content: '无法获取用户资金信息', showCancel: false }) } }) }, async wxSphGetpaymentparams(e) { const orderId = e.currentTarget.dataset.id const res = await WXAPI.wxSphGetpaymentparams(wx.getStorageSync('token'), orderId) if (res.code != 0) { wx.showToast({ title: res.msg, icon: 'none' }) return; } // 发起支付 wx.requestPayment({ timeStamp: res.data.timeStamp, nonceStr: res.data.nonceStr, package: res.data.package, signType: res.data.signType, paySign: res.data.paySign, fail: aaa => { console.error(aaa) wx.showToast({ title: '支付失败:' + aaa }) }, success: () => { // 提示支付成功 wx.showToast({ title: '支付成功' }) this.orderList() } }) }, _toPayTap: function (orderId, money){ const _this = this if (money <= 0) { // 直接使用余额支付 WXAPI.orderPay(wx.getStorageSync('token'), orderId).then(function (res) { _this.data.page = 1 _this.orderList() _this.getOrderStatistics() }) } else { this.setData({ orderId, money, paymentShow: true, nextAction: { type: 0, id: orderId } }) } }, onLoad: function(options) { if (options && options.type) { if (options.type == 99) { this.setData({ hasRefund: true }); } else { const tabIndex = this.data.statusType.findIndex(ele => { return ele.status == options.type }) this.setData({ status: options.type, tabIndex }); } } this.getOrderStatistics(); this.orderList(); this.setData({ sphpay_open: wx.getStorageSync('sphpay_open') }) }, onReady: function() { // 生命周期函数--监听页面初次渲染完成 }, getOrderStatistics() { WXAPI.orderStatistics(wx.getStorageSync('token')).then(res => { if (res.code == 0) { const badges = this.data.badges; badges[1] = res.data.count_id_no_pay badges[2] = res.data.count_id_no_transfer badges[3] = res.data.count_id_no_confirm badges[4] = res.data.count_id_no_reputation this.setData({ badges }) } }) }, onShow: function() { }, onPullDownRefresh: function () { this.data.page = 1 this.getOrderStatistics() this.orderList() wx.stopPullDownRefresh() }, onReachBottom() { this.setData({ page: this.data.page + 1 }); this.orderList() }, async orderList(){ wx.showLoading({ title: '', }) var postData = { page: this.data.page, pageSize: 20, token: wx.getStorageSync('token') }; if (this.data.hasRefund) { postData.hasRefund = true } if (!postData.hasRefund) { postData.status = this.data.status; } if (postData.status == 9999) { postData.status = '' } const res = await WXAPI.orderList(postData) wx.hideLoading() if (res.code == 0) { if (this.data.page == 1) { this.setData({ orderList: res.data.orderList, logisticsMap: res.data.logisticsMap, goodsMap: res.data.goodsMap }) } else { this.setData({ orderList: this.data.orderList.concat(res.data.orderList), logisticsMap: Object.assign(this.data.logisticsMap, res.data.logisticsMap), goodsMap: Object.assign(this.data.goodsMap, res.data.goodsMap) }) } } else { if (this.data.page == 1) { this.setData({ orderList: null, logisticsMap: {}, goodsMap: {} }) } else { wx.showToast({ title: '没有更多了', icon: 'none' }) } } }, paymentOk(e) { console.log(e.detail); // 这里是组件里data的数据 this.setData({ paymentShow: false }) wx.redirectTo({ url: '/pages/order-list/index', }) }, paymentCancel() { this.setData({ paymentShow: false }) }, goOrderDetail(e) { const item = e.currentTarget.dataset.item wx.navigateTo({ url: '/pages/order-details/index?id=' + item.id, }) }, }) ================================================ FILE: pages/order-list/index.json ================================================ { "navigationBarTitleText":"订单列表", "enablePullDownRefresh": true } ================================================ FILE: pages/order-list/index.wxml ================================================ ================================================ FILE: pages/order-list/index.wxss ================================================ /* 页面容器 - 京东风格 */ .container { min-height: 100vh; background: #f5f5f5; padding-bottom: 20rpx; } /* 订单列表 */ .order-list { width: 100%; padding: 0 20rpx; box-sizing: border-box; } /* 订单卡片 */ .order-card { background: #ffffff; border-radius: 12rpx; margin-top: 20rpx; overflow: hidden; box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.06); } /* 订单头部 */ .order-header { display: flex; justify-content: space-between; align-items: center; padding: 24rpx 28rpx; background: #ffffff; border-bottom: 1px solid #f0f0f0; } .order-header-left { flex: 1; } .order-number { font-size: 24rpx; color: #666666; margin-bottom: 8rpx; font-weight: 400; } .order-time { font-size: 22rpx; color: #999999; } .order-status { font-size: 26rpx; font-weight: 500; color: #E4393C; } /* ========== 1个商品布局:横向,左图右信息 ========== */ .goods-content-single { display: flex; padding: 28rpx 28rpx 20rpx; background: #ffffff; gap: 24rpx; } .goods-image-single { width: 200rpx; height: 200rpx; border-radius: 8rpx; background: #f8f8f8; border: 1px solid #eeeeee; flex-shrink: 0; } .goods-info-single { flex: 1; display: flex; flex-direction: column; justify-content: center; padding: 8rpx 0; } .goods-name { font-size: 28rpx; color: #333333; line-height: 1.5; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; text-overflow: ellipsis; } .goods-price-info { display: flex; justify-content: space-between; align-items: center; margin-top: 16rpx; } .goods-price { font-size: 32rpx; color: #E4393C; font-weight: 700; font-family: DIN, -apple-system, system-ui; } .goods-quantity { font-size: 26rpx; color: #999999; } /* ========== 2个商品布局:左两图+右价格信息 ========== */ .goods-content-double { display: flex; padding: 28rpx 28rpx 20rpx; background: #ffffff; gap: 20rpx; } .goods-left { display: flex; gap: 16rpx; } .goods-item-double { position: relative; } .goods-image-double { width: 200rpx; height: 200rpx; border-radius: 8rpx; background: #f8f8f8; border: 1px solid #eeeeee; } .goods-right { flex: 1; display: flex; align-items: center; justify-content: center; } .price-info-compact { text-align: center; } .goods-count-compact { font-size: 24rpx; color: #999999; margin-bottom: 20rpx; } .total-price-compact { display: flex; flex-direction: column; align-items: center; gap: 12rpx; } .label-compact { font-size: 24rpx; color: #666666; font-weight: 500; } .price-amount { display: flex; align-items: baseline; } .price-symbol-compact { font-size: 24rpx; color: #E4393C; font-weight: 600; } .price-value-compact { font-size: 40rpx; color: #E4393C; font-weight: 700; font-family: DIN, -apple-system, system-ui; } .score-value-compact { font-size: 20rpx; color: #E4393C; margin-top: 4rpx; } /* ========== 多个商品布局:网格 ========== */ .goods-content { padding: 28rpx 28rpx 20rpx; background: #ffffff; } .goods-grid { display: flex; flex-wrap: wrap; gap: 16rpx; } .goods-item { width: 200rpx; position: relative; } .goods-item-hover { opacity: 0.85; } .goods-image { width: 200rpx; height: 200rpx; border-radius: 8rpx; background: #f8f8f8; border: 1px solid #eeeeee; } /* 备注信息 */ .order-remark { display: flex; align-items: flex-start; padding: 20rpx 28rpx; background: #fff9f0; border-top: 1px solid #f0f0f0; border-bottom: 1px solid #f0f0f0; } .remark-label { font-size: 24rpx; color: #E4393C; margin-right: 8rpx; font-weight: 500; flex-shrink: 0; } .remark-text { flex: 1; font-size: 24rpx; color: #666666; line-height: 1.6; word-break: break-all; } /* 订单底部 */ .order-footer { padding: 20rpx 28rpx 24rpx; background: #ffffff; } .order-summary { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20rpx; } .goods-count { font-size: 24rpx; color: #999999; } .total-price { display: flex; align-items: baseline; } .total-price .label { font-size: 24rpx; color: #333333; margin-right: 8rpx; font-weight: 500; } .total-price .price-symbol { font-size: 22rpx; color: #E4393C; font-weight: 600; } .total-price .price-value { font-size: 32rpx; color: #E4393C; font-weight: 700; font-family: DIN, -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui; } .total-price .score-value { font-size: 20rpx; color: #E4393C; margin-left: 8rpx; font-weight: 400; } /* 操作按钮 */ .order-actions { display: flex; justify-content: flex-end; gap: 16rpx; flex-wrap: wrap; } .action-btn { padding: 14rpx 28rpx; border-radius: 4rpx; font-size: 26rpx; font-weight: 400; text-align: center; transition: all 0.2s ease; min-width: 160rpx; } .btn-default { background: #ffffff; color: #666666; border: 1px solid #cccccc; } .btn-default:active { background: #f5f5f5; border-color: #999999; } .btn-primary { background: #E4393C; color: #ffffff; border: 1px solid #E4393C; } .btn-primary:active { background: #c7302f; border-color: #c7302f; } /* 底部安全区域 */ .safeAreaOldMarginBttom, .safeAreaNewMarginBttom { height: 40rpx; } ================================================ FILE: pages/peisong/detail.js ================================================ const app = getApp(); const CONFIG = require('../../config.js') const WXAPI = require('apifm-wxapi') import wxbarcode from 'wxbarcode' Page({ data:{ orderId:0, goodsList:[], fileList: [], membersSelectIndex: -1, membersSelectStr: '请选择分配配送员', }, onLoad:function(e){ // e.peisongOrderId = 54 var peisongOrderId = e.peisongOrderId; this.setData({ peisongOrderId }); this.peisongOrderDetail() this.peisongMemberInfo() }, async peisongOrderDetail() { const res = await WXAPI.peisongOrderDetail(wx.getStorageSync('token'), this.data.peisongOrderId) if (res.code == 0) { this.setData({ peisongOrderDetail: res.data }) } }, async peisongMemberInfo() { const res = await WXAPI.peisongMemberInfo(wx.getStorageSync('token')) if (res.code == 0) { this.setData({ peisongMemberInfo: res.data }) if (res.data.type == 2) { this.peisongMembers() } } }, async peisongMembers() { const res = await WXAPI.peisongMembers({ token: wx.getStorageSync('token') }) if (res.code == 0) { res.data.result.forEach(ele => { ele.showStr = ele.name + ' ' + ele.mobile + ' ' + ele.statusStr }) this.setData({ peisongMembers: res.data.result }) } }, onShow : function () { var that = this; WXAPI.orderDetail(wx.getStorageSync('token'), 0, '', that.data.peisongOrderId).then(function (res) { if (res.code != 0) { wx.showModal({ title: '错误', content: res.msg, showCancel: false }) return; } // 绘制核销码 if (res.data.orderInfo.hxNumber && res.data.orderInfo.status > 0) { wxbarcode.qrcode('qrcode', res.data.orderInfo.hxNumber, 650, 650); } that.setData({ orderDetail: res.data }); }) }, wuliuDetailsTap:function(e){ var orderId = e.currentTarget.dataset.id; wx.navigateTo({ url: "/pages/wuliu/index?id=" + orderId }) }, confirmBtnTap:function(e){ let that = this; let orderId = this.data.orderId; wx.showModal({ title: '确认服务已完成?', content: '', success: function(res) { if (res.confirm) { WXAPI.orderDelivery(wx.getStorageSync('token'), orderId).then(function (res) { if (res.code == 0) { that.onShow(); } }) } } }) }, submitReputation: function (e) { let that = this; let postJsonString = {}; postJsonString.token = wx.getStorageSync('token'); postJsonString.orderId = this.data.orderId; let reputations = []; let i = 0; while (e.detail.value["orderGoodsId" + i]) { let orderGoodsId = e.detail.value["orderGoodsId" + i]; let goodReputation = e.detail.value["goodReputation" + i]; let goodReputationRemark = e.detail.value["goodReputationRemark" + i]; let reputations_json = {}; reputations_json.id = orderGoodsId; reputations_json.reputation = goodReputation; reputations_json.remark = goodReputationRemark; reputations.push(reputations_json); i++; } postJsonString.reputations = reputations; WXAPI.orderReputation({ postJsonString: JSON.stringify(postJsonString) }).then(function (res) { if (res.code == 0) { that.onShow(); } }) }, afterRead(event) { console.log(event.detail); const fileList = this.data.fileList event.detail.file.forEach(ele => { fileList.push({ url: ele.path, name: '图片' }) }) this.setData({ fileList }); }, deletePic(event) { const fileList = this.data.fileList fileList.splice(event.detail.index, 1) this.setData({ fileList }); }, async startService() { const extJsonStr = {} wx.showLoading({ title: '提交中', }) const res = await WXAPI.peisongStartService({ token: wx.getStorageSync('token'), id: this.data.peisongOrderId, extJsonStr: JSON.stringify(extJsonStr) }) wx.hideLoading({ complete: (res) => {}, }) if (res.code != 0) { wx.showToast({ title: res.msg, icon: 'none' }) } else { wx.showToast({ title: '提交成功', icon: 'success' }) this.peisongOrderDetail() this.onShow() } }, async endService() { const extJsonStr = {} let picNumber = 0 wx.showLoading({ title: '提交中', }) const res = await WXAPI.peisongEndService({ token: wx.getStorageSync('token'), id: this.data.peisongOrderId, extJsonStr: JSON.stringify(extJsonStr) }) wx.hideLoading({ complete: (res) => {}, }) if (res.code != 0) { wx.showToast({ title: res.msg, icon: 'none' }) } else { wx.showToast({ title: '提交成功', icon: 'success' }) this.setData({ fileList: [] }) this.peisongOrderDetail() this.onShow() } }, previewImage(e) { const logid = e.currentTarget.dataset.logid const current = e.currentTarget.dataset.current const urls = [] this.data.peisongOrderDetail.logs.forEach(ele => { if (ele.id == logid) { Object.values(ele.extJson).forEach(_ele => { urls.push(_ele) }) } }) wx.previewImage({ urls, current }) }, bindPickerChange: function(e) { const obj = this.data.peisongMembers[e.detail.value] this.setData({ membersSelectIndex: e.detail.value, membersSelectStr: obj.name + ' ' + obj.mobile }) }, async paidan() { if (this.data.membersSelectIndex == -1) { wx.showToast({ title: '请选择洗车工', icon: 'none' }) return } const member = this.data.peisongMembers[this.data.membersSelectIndex] const res = await WXAPI.peisongOrderAllocation(wx.getStorageSync('token'), this.data.peisongOrderId, member.id) if (res.code != 0) { wx.showToast({ title: res.msg, icon: 'none' }) } else { wx.showToast({ title: '派单成功', icon: 'success' }) wx.navigateBack({ complete: (res) => {}, }) } }, callMobile() { wx.makePhoneCall({ phoneNumber: this.data.orderDetail.peisongMember.mobile, }) }, callMobile2() { wx.makePhoneCall({ phoneNumber: this.data.orderDetail.logistics.mobile, }) }, goMap() { const _this = this const latitude = this.data.orderDetail.logistics.latitude const longitude = this.data.orderDetail.logistics.longitude wx.openLocation({ latitude, longitude, scale: 18 }) }, estimatedCompletionTimeChange(value) { this.data.estimatedCompletionTimeChange = value.detail }, async estimatedCompletionTime(){ if (!this.data.estimatedCompletionTimeChange) { wx.showToast({ title: '填写预计完成时间', icon: 'none' }) return; } const res = await WXAPI.peisongOrderEstimatedCompletionTime({ token: wx.getStorageSync('token'), id: this.data.peisongOrderId, estimatedCompletionTime: this.data.estimatedCompletionTimeChange }) if (res.code == 0) { wx.showToast({ title: '设置成功', icon: 'success' }) this.peisongOrderDetail() this.onShow() } else { wx.showToast({ title: res.msg, icon: 'none' }) } }, async peisongOrderGrab(){ if (!this.data.estimatedCompletionTimeChange) { wx.showToast({ title: '填写预计完成时间', icon: 'none' }) return; } const res = await WXAPI.peisongOrderGrab({ token: wx.getStorageSync('token'), id: this.data.peisongOrderId, estimatedCompletionTime: this.data.estimatedCompletionTimeChange }) if (res.code == 0) { wx.showToast({ title: '抢单成功', icon: 'success' }) this.peisongOrderDetail() this.onShow() } else { wx.showToast({ title: res.msg, icon: 'none' }) } }, }) ================================================ FILE: pages/peisong/detail.json ================================================ { "navigationBarTitleText": "订单详情" } ================================================ FILE: pages/peisong/detail.wxml ================================================ 客户已申请退款 操作台 抢单 派单 设置预计完成时间 开始配送 配送完成 优惠券 {{item.coupon}} 商品金额 ¥ {{orderDetail.orderInfo.amount}} 配送费 ¥ {{orderDetail.orderInfo.amountLogistics}} 应付总额 ¥ {{orderDetail.orderInfo.amountReal}} ================================================ FILE: pages/peisong/detail.wxss ================================================ page{ min-height: 100%; background-color: #F2f2f2; } .container{ min-height: 100%; overflow: hidden; overflow-y: hidden; } .sec-wrap{ background-color: #fff; margin-top: 20rpx; } .bottom-fiexd{ position: fixed; bottom: 0; left: 0; } .sec-wrap .order-status{ width: 720rpx; margin-left: 30rpx; border-bottom: 1rpx solid #eee; height: 140rpx; display: flex; align-items: center; } .order-status .icon-box{ width: 80rpx; height: 80rpx; overflow: hidden; margin-right: 30rpx; } .order-status .icon-box .icon{ width: 80rpx; height: 80rpx; } .order-status .right-text{ width: 580rpx; overflow: hidden; } .order-status .right-text .status{ font-size:28rpx; color:#000; margin-bottom: 10rpx; } .order-status .right-text .red{ color:#e64340; } .order-status .right-text .des{ font-size:24rpx; color:#999; } .address-sec{ width: 720rpx; margin-left: 30rpx; display: flex; align-items: center; padding: 30rpx 0; } .address-sec .icon-box{ width: 30rpx; align-self: flex-start; overflow: hidden; margin-right: 35rpx; } .address-sec .icon-box .icon{ width: 30rpx; height: 30rpx; } .address-sec .right-box{ width: 620rpx; } .address-sec .right-box .name-tel{ font-size:28rpx; color:#000000; margin-bottom: 20rpx; } .address-sec .right-box .text{ font-size:24rpx; color:#888888; overflow: hidden; } .wuliu-box{ width: 720rpx; margin-left: 30rpx; border-bottom: 1rpx solid #eee; display: flex; align-items: center; padding: 30rpx 0; } .wuliu-box .icon-box { width: 40rpx; height: 40rpx; overflow: hidden; margin-right: 31rpx; align-self: flex-start; } .wuliu-box .icon-box .icon{ width: 40rpx; height: 40rpx; } .wuliu-box .arrow-right{ width: 15rpx; height: 24rpx; } .wuliu-box .arrow-right .arrow{ width: 15rpx; height: 24rpx; } .wuliu-box .right-text{ width: 575rpx; margin-right: 30rpx; } .wuliu-box .right-text .order-number{ font-size:28rpx; color:#000; margin-bottom: 14rpx; } .wuliu-box .right-text .wuliu-text, .wuliu-box .right-text .wuliu-date{ font-size:24rpx; color:#888888; line-height:36rpx; } .goods-list{ width:100%; background-color: #fff; margin-bottom: 20rpx; margin-top: 20rpx; } .goods-list .list-title{ font-size: 28rpx; color: #000; padding: 30rpx 0 25rpx 30rpx; } .goods-list .a-goods{ width: 720rpx; margin-left: 30rpx; display: flex; /*justify-content: space-between;*/ border-top: 1px solid #eee; padding: 30rpx 30rpx 30rpx 0; } .goods-list .a-goods .img-box{ width: 160rpx; height:160rpx; overflow: hidden; margin-right: 20rpx; background-color: #d8d8d8; } .goods-list .img-box .img{ width: 160rpx; height:160rpx; } .goods-list .a-goods .text-box{ width: 510rpx; box-sizing: border-box; padding-top: 10rpx; } .goods-list .btn-row{ box-sizing: border-box; width: 750rpx; padding: 32rpx; border-top: 1rpx solid #eee; } .confirm-btn{ background:#ffffff; border:1rpx solid #e64340; border-radius:6rpx; width:164rpx; height:60rpx; line-height: 60rpx; margin: 20rpx 30rpx 20rpx auto; font-size:26rpx; color:#e64340; text-align:center; } .a-goods .text-box .arow{ display: flex; justify-content: space-between; align-items: center; } .a-goods .text-box .arow .goods-name{ width: 360rpx; font-size:26rpx; height: 74rpx; color:#000000; line-height: 1.6; overflow: hidden; } .a-goods .text-box .arow01{ margin-bottom: 30rpx; } .a-goods .text-box .arow .goods-price{ font-size:26rpx; color:#000000; align-self: flex-start; } .a-goods .text-box .arow .goods-label{ font-size: 26rpx; color: #999; } .a-goods .text-box .arow .goods-num{ font-size: 26rpx; color: #999; } .peisong-way{ width: 100%; background-color: #fff; margin-bottom: 20rpx; } .peisong-way .row-box{ width: 720rpx; display: flex; justify-content: space-between; align-items: center; box-sizing: border-box; padding: 24rpx 0; border-bottom: 1rpx solid #eee; margin-left: 30rpx; } .peisong-way .row-label{ font-size: 28rpx; color: #000; } .peisong-way .right-text{ font-size: 28rpx; color: #666; padding-right: 30rpx; } .peisong-way .liuyan{ width: 510rpx; font-size: 28rpx; } .goods-info{ width: 100%; background-color: #fff; padding-bottom: 24rpx; } .goods-info .row-box{ width: 100%; display: flex; justify-content: space-between; align-items: center; box-sizing: border-box; padding: 24rpx 30rpx 12rpx 30rpx; font-size: 28rpx; color: #000; } .goods-info .row-box .right-text{ text-align: right; } .jiesuan-box{ display: flex; justify-content: space-between; width: 100%; height: 100rpx; position: fixed; bottom: 0; left: 0; border-top:1px solid #eee; background-color: #fff; z-index: 4; } .jiesuan-box .to-pay-btn{ width:250rpx; text-align: center; height: 100%; line-height: 100rpx; background-color: #e64340; font-size:32rpx; color:#ffffff; border-radius: 0; } .jiesuan-box .left-price{ display: flex; width: 500rpx; justify-content:flex-end; line-height: 100rpx; padding: 0 30rpx 0 0; font-size:28rpx; box-sizing: border-box; } .jiesuan-box .total{ color: #e64340; text-align: right; } .hx-title { text-align: center; } .hx-canvas { width: 650rpx; height: 650rpx; margin-left: 50rpx; } .vant-contaner { box-sizing: border-box; width: 100vw; } .select-peisong-member { padding-left: 0 !important; padding-right: 0 !important; } .pic-box { display: flex; flex-wrap: wrap; } .pic-box .pic { margin: 16rpx 0 0 16rpx; width: 228rpx; height: 228rpx; } .refundStatus { background: #ee0a24; color: #ffffff; padding: 16rpx; text-align: center; } ================================================ FILE: pages/peisong/orders.js ================================================ const WXAPI = require('apifm-wxapi') const APP = getApp() // fixed首次打开不显示标题的bug APP.configLoadOK = () => { } var timer Page({ data: { active: 0, tabs: ['已接单', '服务中', '全部'], }, onLoad: function (options) { this.data.status = options.status // -1 待接单订单 ; 1 待分配订单 ; 其他状态: 我的维修单 this.setData({ status: options.status }) if (options.status == -1) { wx.setNavigationBarTitle({ title: '抢单任务大厅', }) } else if (options.status == 1) { wx.setNavigationBarTitle({ title: '管理员派单管理', }) } else { wx.setNavigationBarTitle({ title: '我的配送单', }) } if (this.data.status == -1) { timer =setInterval(() => { this.peisongOrdersGrabbing() }, 1000) } }, onShow: function () { if (this.data.status != -1) { this.orders() } }, onUnload() { if (timer) { clearTimeout(timer) } }, async orders() { wx.showLoading({ title: '', }) const _data = { token: wx.getStorageSync('token'), } if(this.data.status) { // 管理员派单 _data.statusBatch = this.data.status _data.refundStatusBatch = '0,2' } else { // 我的配送单 _data.uid = wx.getStorageSync('uid') if (this.data.active == 0) { _data.status = 2 } else if (this.data.active == 1) { _data.status = 3 } } const res = await WXAPI.peisongOrders(_data) wx.hideLoading() if (res.code != 0) { this.setData({ orderList: null }) } else { res.data.result.forEach(ele => { if (ele.status == 2) { ele.statusStr = '已接单' } if (ele.status == 3) { ele.statusStr = '配送中' } }) this.setData({ orderList: res.data.result }) } }, async peisongOrdersGrabbing() { // wx.showLoading({ // title: '', // }) const res = await WXAPI.peisongOrdersGrabbing(wx.getStorageSync('token')) // wx.hideLoading({ // complete: (res) => {}, // }) if (res.code != 0) { // wx.showToast({ // title: res.msg, // icon: 'none' // }) this.setData({ orderList: null }) } else { res.data.forEach(ele => { if (ele.status == 2) { ele.statusStr = '已接单' } if (ele.status == 3) { ele.statusStr = '服务中' } }) this.setData({ orderList: res.data }) } }, tabClick(e) { this.setData({ active: e.detail.index }) this.orders() }, }) ================================================ FILE: pages/peisong/orders.json ================================================ { "navigationBarTitleText": "" } ================================================ FILE: pages/peisong/orders.wxml ================================================ ================================================ FILE: pages/peisong/orders.wxss ================================================ ================================================ FILE: pages/peisong/statistics.js ================================================ const WXAPI = require('apifm-wxapi') const dayjs = require("dayjs") Page({ data: { active: 0, tabs: ['本月', '今天', '昨天'], page: 1, month: undefined, today: undefined, yesday: undefined, }, onLoad(options) { this.setData({ month: dayjs().format('YYYYMM'), today: dayjs().format('YYYYMMDD'), yesday: dayjs().add(-1, 'day').format('YYYYMMDD'), }) this.peisongMemberStatistics() }, onShow() { }, onReachBottom() { this.data.page++ this.peisongMemberStatistics() }, tabClick(e) { this.data.page = 1 this.setData({ active: e.detail.index }) this.peisongMemberStatistics() }, async peisongMemberStatistics() { wx.showLoading({ title: '' }) const data = { token: wx.getStorageSync('token'), page: this.data.page, } if (this.data.active == 0) { data.day = this.data.month } else if (this.data.active == 1) { data.day = this.data.today } else if (this.data.active == 2) { data.day = this.data.yesday } const res = await WXAPI.peisongMemberStatistics(data) wx.hideLoading() if (res.code == 0) { if (this.data.page == 1) { this.setData({ list: res.data.result }) } else { this.setData({ list: this.data.list.concat(res.data.result) }) } } else { if (this.data.page > 1) { wx.showToast({ title: '没有更多了~', icon: 'none' }) } else { this.setData({ list: null }) } } }, }) ================================================ FILE: pages/peisong/statistics.json ================================================ { "usingComponents": {}, "navigationBarTitleText": "业绩统计" } ================================================ FILE: pages/peisong/statistics.wxml ================================================ ================================================ FILE: pages/peisong/statistics.wxss ================================================ ================================================ FILE: pages/pwd-pay/modify.js ================================================ const WXAPI = require('apifm-wxapi') const AUTH = require('../../utils/auth') Page({ data: { }, onLoad: function (options) { }, onShow: function () { }, async submit() { if (!this.data.pwdOld) { wx.showToast({ title: '请输入原来的交易密码', icon: 'none' }) return } if (!this.data.pwd) { wx.showToast({ title: '请输入新的交易密码', icon: 'none' }) return } if (!this.data.pwd2) { wx.showToast({ title: '请再次输入新的交易密码', icon: 'none' }) return } if (this.data.pwd != this.data.pwd2) { wx.showToast({ title: '两次输入不一致', icon: 'none' }) return } const res = await WXAPI.modifyPayPassword(wx.getStorageSync('token'), this.data.pwdOld, this.data.pwd) if (res.code == 2000) { AUTH.login(this) return } if (res.code != 0) { wx.showToast({ title: res.msg, icon: 'none' }) return } wx.showToast({ title: '修改成功' }) setTimeout(() => { wx.navigateBack({ delta: 0, }) }, 1000); }, }) ================================================ FILE: pages/pwd-pay/modify.json ================================================ { "navigationBarTitleText": "修改交易密码" } ================================================ FILE: pages/pwd-pay/modify.wxml ================================================ 修改交易密码 ================================================ FILE: pages/pwd-pay/modify.wxss ================================================ .btn { margin-top: 32rpx; } ================================================ FILE: pages/pwd-pay/reset.js ================================================ const WXAPI = require('apifm-wxapi') const AUTH = require('../../utils/auth') Page({ data: { }, onLoad: function (options) { }, onShow: function () { this.getUserApiInfo() }, async getUserApiInfo() { const res = await WXAPI.userDetail(wx.getStorageSync('token')) if (res.code == 2000) { AUTH.login(this) return } if (res.code == 0) { this.setData({ mobile: res.data.base.mobile }) } }, async sendSms() { const res = await WXAPI.smsValidateCodeByToken(wx.getStorageSync('token')) if (res.code == 2000) { AUTH.login(this) return } if (res.code == 0) { this.setData({ smsloading: true, smsloadingSecond: 60 }) wx.showToast({ title: '短信已发送', }) this.countDown() } else { wx.showToast({ title: res.msg, icon: 'none' }) } }, countDown() { const smsloadingSecond = this.data.smsloadingSecond if (smsloadingSecond) { this.setData({ smsloadingSecond: smsloadingSecond-1 }) setTimeout(() => { this.countDown() }, 1000); } else { this.setData({ smsloading: false }) } }, async submit() { if (!this.data.mobile) { wx.showToast({ title: '请先绑定手机号码', icon: 'none' }) return } if (!this.data.code) { wx.showToast({ title: '请输入短信验证码', icon: 'none' }) return } if (!this.data.pwd) { wx.showToast({ title: '请输入交易密码', icon: 'none' }) return } if (!this.data.pwd2) { wx.showToast({ title: '请再次输入交易密码', icon: 'none' }) return } if (this.data.pwd != this.data.pwd2) { wx.showToast({ title: '两次输入不一致', icon: 'none' }) return } const res = await WXAPI.resetPayPassword(this.data.mobile, this.data.code, this.data.pwd) if (res.code == 2000) { AUTH.login(this) return } if (res.code != 0) { wx.showToast({ title: res.msg, icon: 'none' }) return } wx.showToast({ title: '设置成功' }) setTimeout(() => { wx.navigateBack({ delta: 0, }) }, 1000); }, bindMobile() { this.setData({ bindMobileShow: true }) }, bindMobileOk(e) { console.log(e.detail); // 这里是组件里data的数据 this.setData({ bindMobileShow: false }) this.getUserApiInfo() }, bindMobileCancel() { this.setData({ bindMobileShow: false }) }, }) ================================================ FILE: pages/pwd-pay/reset.json ================================================ { "navigationBarTitleText": "重置交易密码" } ================================================ FILE: pages/pwd-pay/reset.wxml ================================================ {{ smsloading ? smsloadingSecond + '秒后重新获取' : '发送验证码' }} 立即绑定 重置交易密码 ================================================ FILE: pages/pwd-pay/reset.wxss ================================================ .btn { margin-top: 32rpx; } ================================================ FILE: pages/pwd-pay/set.js ================================================ const WXAPI = require('apifm-wxapi') const AUTH = require('../../utils/auth') Page({ data: { }, onLoad: function (options) { }, onShow: function () { }, async submit() { if (!this.data.pwd) { wx.showToast({ title: '请输入交易密码', icon: 'none' }) return } if (!this.data.pwd2) { wx.showToast({ title: '请再次输入交易密码', icon: 'none' }) return } if (this.data.pwd != this.data.pwd2) { wx.showToast({ title: '两次输入不一致', icon: 'none' }) return } const res = await WXAPI.setPayPassword(wx.getStorageSync('token'), this.data.pwd) if (res.code == 2000) { AUTH.login(this) return } if (res.code != 0) { wx.showToast({ title: res.msg, icon: 'none' }) return } wx.showToast({ title: '设置成功' }) setTimeout(() => { wx.navigateBack({ delta: 0, }) }, 1000); }, }) ================================================ FILE: pages/pwd-pay/set.json ================================================ { "navigationBarTitleText": "设置交易密码" } ================================================ FILE: pages/pwd-pay/set.wxml ================================================ 设置交易密码 ================================================ FILE: pages/pwd-pay/set.wxss ================================================ .btn { margin-top: 32rpx; } ================================================ FILE: pages/raffle/index.js ================================================ const WXAPI = require('apifm-wxapi'); const { unix } = require('dayjs'); //计数器 var interval = null; //值越大旋转时间越长 即旋转速度 var intime = 50; Page({ data: { id: undefined, border: ['border:none', 'border:none', 'border:none', 'border:none', 'border:none', 'border:none', 'border:none', 'border:none'], btnconfirm: 'https://dcdn.it120.cc/2024/04/12/21578e4c-575a-48dd-9825-072d92f7a3e8.png', clickLuck: 'clickLuck', luckPosition: 0, }, onLoad(e) { this.data.id = e.id this.loadAnimation(); // 进入页面时缓慢切换 this.luckyInfo() }, onShow() {}, onShareAppMessage() { }, async luckyInfo() { wx.showLoading({ title: '' }) const res = await WXAPI.luckyInfo(this.data.id) wx.hideLoading() if (res.code == 0) { let timesPerUser = res.data.info.timesPerUser let luckyGoods = res.data.luckyGoods if (!luckyGoods) { luckyGoods = [] } // 补全9个 for (let index = 0; index < 9; index++) { luckyGoods.push({ goodsId: -2, // 补全 pic: "https://dcdn.it120.cc/2024/04/12/b5fa1fa4-66f2-4ac0-9261-480e6df1df9b.jpg", title: "谢谢参与" }) } const uid = wx.getStorageSync('uid') let logs if (uid) { const res2 = await WXAPI.luckyInfoJoinLogs({ lid: this.data.id, uid }) if (res2.code == 0) { timesPerUser -= res2.data.totalRow logs = res2.data.result } } else { logs = null } this.setData({ timesPerUser, logs, luckyGoods }) } }, loadAnimation() { var e = this; var index = 0; // if (interval == null){ interval = setInterval(function () { if (index > 7) { index = 0; e.data.border[7] = 'border:none' } else if (index != 0) { e.data.border[index - 1] = 'border:none' } e.data.border[index] = 'border:6rpx solid #9077c4;border-radius:40rpx;width:168rpx;height:168rpx' e.setData({ border: e.data.border, }) index++; }, 1000); // } }, async getLuckyInfoJoin() { // 点击抽奖 if (this.data.clickLuck == '') { return; } if (this.data.timesPerUser <= 0) { wx.showToast({ title: '抽奖次数已用完', icon: 'none' }) return } const token = wx.getStorageSync('token') wx.showLoading({ title: '', }) const res = await WXAPI.luckyInfoJoin(this.data.id, token) wx.hideLoading() if (res.code == 2000) { wx.navigateTo({ url: '/pages/login/index', }) return } if (res.code != 0) { wx.showToast({ title: res.msg, icon: 'none' }) return } const prizeName = res.data.prizeName const luckPosition = this.data.luckyGoods.findIndex(ele => ele.title == prizeName) // 服务器返回的中奖的是哪个商品 this.setData({ luckPosition }) this.clickLuck() }, clickLuck() { var e = this; if (this.data.clickLuck == '') { return; } //设置按钮不可点击 this.setData({ btnconfirm: 'https://dcdn.it120.cc/2024/04/12/816d31c4-cb18-4107-8934-00999356a682.png', clickLuck: '', }) //清空计时器 clearInterval(interval); var index = 0; //循环设置每一项的透明度 interval = setInterval(function () { if (index > 7) { index = 0; e.data.border[7] = 'border:none' } else if (index != 0) { e.data.border[index - 1] = 'border:none' } e.data.border[index] = 'border:6rpx solid #9077c4;border-radius:40rpx;width:168rpx;height:168rpx' e.setData({ border: e.data.border }) index++; }, intime); //模拟网络请求时间 设为两秒 var stoptime = 2000; setTimeout(function () { e.stop(e.data.luckPosition); }, stoptime) }, stop(which) { var e = this; //清空计数器 clearInterval(interval); //初始化当前位置 var current = -1; var border = e.data.border; for (var i = 0; i < border.length; i++) { if (border[i] == 'border:6rpx solid #ee6916;border-radius:40rpx;width:168rpx;height:168rpx') { current = i; } } //下标从1开始 var index = current + 1; this.stopLuck(which, index, intime, 10); }, /** * which:中奖位置 * index:当前位置 * time:时间标记 * splittime:每次增加的时间 值越大减速越快 */ stopLuck(which, index, time, splittime) { var e = this; //值越大出现中奖结果后减速时间越长 var border = e.data.border; setTimeout(function () { //重置前一个位置 if (index > 7) { index = 0; border[7] = 'border:none;' } else if (index != 0) { border[index - 1] = 'border:none;' } //当前位置为选中状态 e.data.border[index] = 'border:6rpx solid #ee6916;border-radius:40rpx;width:168rpx;height:168rpx' e.setData({ border: e.data.border }) //如果旋转时间过短或者当前位置不等于中奖位置则递归执行 //直到旋转至中奖位置 if (time < 400 || index != which) { //越来越慢 splittime++; time += splittime; //当前位置+1 index++; e.stopLuck(which, index, time, splittime); } else { //抽奖后是否可以再次抽奖,可以的再次抽奖设为:'clickLuck',不能再次抽奖设为'' e.setData({ clickLuck: 'clickLuck' }) //1秒后显示弹窗 setTimeout(function () { wx.showModal({ title: '中奖提示', content: e.data.luckPosition == 6 ? '非常遗憾,您没有中奖,谢谢您的参与。' : '恭喜抽中: ' + e.data.luckyGoods[e.data.luckPosition].title, showCancel: false, success: function (res) { if (res.confirm) { //设置按钮可以点击 e.setData({ btnconfirm: 'https://dcdn.it120.cc/2024/04/12/21578e4c-575a-48dd-9825-072d92f7a3e8.png', clickLuck: 'clickLuck', }) e.loadAnimation(); e.luckyInfo() } } }) }, 600); } }, time); console.log(time); }, }) ================================================ FILE: pages/raffle/index.json ================================================ { "navigationBarTitleText": "抽奖" } ================================================ FILE: pages/raffle/index.wxml ================================================ 剩余抽奖次数: {{ timesPerUser }} ================================================ FILE: pages/raffle/index.wxss ================================================ page { min-height: 100vh; display: flex; flex-direction: column; align-items: center; justify-content: center; } .frame_view{ bottom: 160rpx; left: 60rpx; right: 60rpx; width:590rpx; height:590rpx; padding: 20rpx; background: #6339b5; z-index: 3; display: flex; flex-direction: column; justify-content: space-between; align-items: center; border-radius: 30rpx; } .frame_row{ width:580rpx; height:180rpx; display: flex; flex-direction: row; justify-content: space-between; align-items: center; } .frame_item{ width:180rpx; height:180rpx; } .top_img_button { box-shadow: 6rpx 6rpx #e85c33; box-sizing: border-box; display: inline-block; height: 42px; line-height: 42px; border-radius: 20px; padding: 0 14px; color:#fe7520; font-size: 14px; background: white; text-align: center; } button:after{ border: none; } .number { margin: 64rpx 0; padding: 8rpx 16rpx; color: #ffffff; background: #9077c4; border-radius: 16rpx; font-size: 30rpx; } .logs { width: 90vw; background: #fff; } ================================================ FILE: pages/recharge/index.js ================================================ const WXAPI = require('apifm-wxapi') const CONFIG = require('../../config.js') Page({ data: { }, onLoad(e) { // 读取系统参数 this.readConfigVal() getApp().configLoadOK = () => { this.readConfigVal() } this.rechargeSendRules() }, onShow: function () { }, readConfigVal() { let recharge_amount_min = wx.getStorageSync('recharge_amount_min') if (!recharge_amount_min) { recharge_amount_min = 0; } this.setData({ recharge_amount_min: recharge_amount_min, needBindMobile: wx.getStorageSync('needBindMobile'), }) }, async rechargeSendRules() { const res = await WXAPI.rechargeSendRules() if (res.code == 0) { this.setData({ rechargeSendRules: res.data }) } }, /** * 点击充值优惠的充值送 */ async rechargeAmount(e) { // 判断是否需要绑定手机号码 // https://www.yuque.com/apifm/nu0f75/zgf8pu if (this.data.needBindMobile == 1) { const resUserDetail = await WXAPI.userDetail(wx.getStorageSync('token')) if (resUserDetail.code == 0 && !resUserDetail.data.base.mobile) { this.setData({ bindMobileShow: true }) return } } var confine = e.currentTarget.dataset.confine; var amount = confine; this.setData({ amount, paymentShow: true }) }, async bindSave() { const amount = this.data.amount; if (!amount || amount * 1 < 0) { wx.showModal({ title: '错误', content: '请填写正确的充值金额', showCancel: false }) return } if (amount * 1 < this.data.recharge_amount_min * 1) { wx.showModal({ title: '错误', content: '单次充值金额至少' + this.data.recharge_amount_min + '元', showCancel: false }) return } // 判断是否需要绑定手机号码 // https://www.yuque.com/apifm/nu0f75/zgf8pu if (this.data.needBindMobile == 1) { console.log(123); const resUserDetail = await WXAPI.userDetail(wx.getStorageSync('token')) if (resUserDetail.code == 0 && !resUserDetail.data.base.mobile) { this.setData({ bindMobileShow: true }) return } } this.setData({ paymentShow: true }) }, bindMobileOk(e) { console.log(e.detail); // 这里是组件里data的数据 this.setData({ bindMobileShow: false }) }, bindMobileCancel() { this.setData({ bindMobileShow: false }) }, paymentOk(e) { console.log(e.detail); // 这里是组件里data的数据 this.setData({ paymentShow: false }) wx.switchTab({ url: '/pages/my/index', }) }, paymentCancel() { this.setData({ paymentShow: false }) }, }) ================================================ FILE: pages/recharge/index.json ================================================ { "navigationBarTitleText": "在线充值" } ================================================ FILE: pages/recharge/index.wxml ================================================ 余额充值 安全便捷 · 即时到账 💰 充值金额 ¥ 快速选择 ¥{{item.confine}} 送¥{{item.send}} ℹ️ 温馨提示 • 充值金额实时到账,可随时使用 • 支持微信支付,安全可靠 • 充值记录可在"我的"页面查看 立即充值 ================================================ FILE: pages/recharge/index.wxss ================================================ /* 页面容器 */ page { background: linear-gradient(180deg, #FF4D4F 0%, #FF7A7C 30%, #F5F5F5 30%, #F5F5F5 100%); min-height: 100vh; } .page-container { min-height: 100vh; padding-bottom: 40rpx; } /* 头部区域 */ .header-section { position: relative; height: 280rpx; overflow: hidden; } .header-bg { position: absolute; top: 0; left: 0; right: 0; height: 100%; background: linear-gradient(135deg, #E4393C 0%, #FF6B6B 100%); } .header-bg::after { content: ''; position: absolute; bottom: -2rpx; left: 0; right: 0; height: 80rpx; background: #F5F5F5; border-radius: 50% 50% 0 0 / 100% 100% 0 0; } .header-content { position: relative; z-index: 2; padding-top: 80rpx; text-align: center; } .header-title { font-size: 44rpx; font-weight: bold; color: #FFFFFF; letter-spacing: 2rpx; margin-bottom: 16rpx; } .header-subtitle { font-size: 26rpx; color: rgba(255, 255, 255, 0.9); letter-spacing: 1rpx; } /* 充值金额卡片 */ .amount-card { margin: -60rpx 30rpx 30rpx; background: #FFFFFF; border-radius: 24rpx; padding: 40rpx 30rpx; box-shadow: 0 8rpx 32rpx rgba(228, 57, 60, 0.15); position: relative; z-index: 10; } .card-title { display: flex; align-items: center; margin-bottom: 30rpx; } .title-icon { font-size: 40rpx; margin-right: 12rpx; } .title-text { font-size: 32rpx; font-weight: 600; color: #333333; } .amount-input-wrapper { display: flex; align-items: center; padding: 30rpx 24rpx; background: #F8F8F8; border-radius: 16rpx; border: 2rpx solid #E8E8E8; transition: all 0.3s; } .amount-input-wrapper:focus-within { background: #FFF; border-color: #E4393C; box-shadow: 0 0 0 4rpx rgba(228, 57, 60, 0.1); } .amount-symbol { font-size: 48rpx; font-weight: bold; color: #E4393C; margin-right: 12rpx; } .amount-input { flex: 1; font-size: 48rpx; font-weight: bold; color: #333333; } .amount-placeholder { color: #BBBBBB; font-size: 28rpx; font-weight: normal; } /* 快速充值选择区域 */ .quick-amount-section { margin: 0 30rpx 30rpx; background: #FFFFFF; border-radius: 24rpx; padding: 30rpx; box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.06); } .section-title { display: flex; align-items: center; justify-content: center; margin-bottom: 30rpx; } .title-line { flex: 1; height: 2rpx; background: linear-gradient(to right, transparent, #E8E8E8, transparent); } .section-title .title-text { padding: 0 24rpx; font-size: 28rpx; font-weight: 500; color: #666666; } .amount-options { display: flex; flex-wrap: wrap; gap: 20rpx; } .amount-option { width: calc(50% - 15rpx); background: linear-gradient(135deg, #FFF8F8 0%, #FFFFFF 100%); border: 2rpx solid #FFE5E5; border-radius: 16rpx; padding: 32rpx 20rpx; text-align: center; position: relative; transition: all 0.3s; overflow: hidden; box-sizing: border-box; } .amount-option::before { content: ''; position: absolute; top: 0; left: 0; right: 0; bottom: 0; background: linear-gradient(135deg, #E4393C 0%, #FF6B6B 100%); opacity: 0; transition: opacity 0.3s; } .amount-option:active { transform: scale(0.95); } .amount-option:active::before { opacity: 1; } .option-amount { font-size: 36rpx; font-weight: bold; color: #E4393C; position: relative; z-index: 1; transition: color 0.3s; } .amount-option:active .option-amount { color: #FFFFFF; } .option-gift { margin-top: 12rpx; position: relative; z-index: 1; } .gift-tag { display: inline-block; background: linear-gradient(135deg, #FF4D4F 0%, #FF6B6B 100%); color: #FFFFFF; font-size: 20rpx; padding: 4rpx 12rpx; border-radius: 20rpx; font-weight: 500; box-shadow: 0 2rpx 8rpx rgba(228, 57, 60, 0.3); transition: all 0.3s; } .amount-option:active .gift-tag { background: #FFFFFF; color: #E4393C; } /* 温馨提示 */ .tips-section { margin: 0 30rpx 30rpx; background: linear-gradient(135deg, #FFF9F0 0%, #FFFFFF 100%); border-radius: 20rpx; padding: 30rpx; border-left: 6rpx solid #FFA940; } .tips-title { display: flex; align-items: center; margin-bottom: 20rpx; font-size: 28rpx; font-weight: 600; color: #333333; } .tips-icon { font-size: 32rpx; margin-right: 8rpx; } .tips-content { padding-left: 8rpx; } .tip-item { font-size: 24rpx; color: #666666; line-height: 40rpx; margin-bottom: 8rpx; } .tip-item:last-child { margin-bottom: 0; } /* 提交按钮区域 */ .submit-section { margin: 60rpx 30rpx 30rpx; } .submit-btn { display: flex; align-items: center; justify-content: center; height: 96rpx; background: linear-gradient(135deg, #E4393C 0%, #FF6B6B 100%); border-radius: 48rpx; box-shadow: 0 8rpx 24rpx rgba(228, 57, 60, 0.4); position: relative; overflow: hidden; transition: all 0.3s; } .submit-btn::before { content: ''; position: absolute; top: 0; left: -100%; width: 100%; height: 100%; background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.3), transparent); transition: left 0.5s; } .submit-btn:active { transform: scale(0.98); box-shadow: 0 4rpx 16rpx rgba(228, 57, 60, 0.3); } .submit-btn:active::before { left: 100%; } .btn-text { font-size: 34rpx; font-weight: bold; color: #FFFFFF; letter-spacing: 2rpx; } .btn-icon { font-size: 32rpx; color: #FFFFFF; margin-left: 8rpx; font-weight: bold; } /* 兼容vant组件样式 */ .amount-input .van-field__control { font-size: 48rpx !important; font-weight: bold; color: #333333; } ================================================ FILE: pages/recycle/index.js ================================================ const WXAPI = require('apifm-wxapi') const AUTH = require('../../utils/auth') Page({ data: { logisticsType: '0', // 0 自己送货 1 快递 shopIndex: -1 }, onLoad(e) { // e.type = 1 // e.orderId = 3 // e.platform = 'jd' this.setData({ type: e.type, orderId: e.orderId, platform: e.platform }) wx.getLocation({ type: 'gcj02', // 返回 gps 坐标,gcj02 返回可用于 wx.openLocation 的坐标 success: res => { this.data.latitude = res.latitude this.data.longitude = res.longitude this.initData() }, fail: err => { console.error(err) this.initData() AUTH.checkAndAuthorize('scope.userLocation') } }) }, onShow() { }, async initData() { this.fetchShops() if (this.data.type == 1 && this.data.platform == 'jd') { this.cpsJdOrderDetail() } if (this.data.type == 1 && this.data.platform == 'pdd') { this.cpsPddOrderDetail() } }, async fetchShops(){ const p = {} if (this.data.latitude) { p.curlatitude = this.data.latitude } if (this.data.longitude) { p.curlongitude = this.data.longitude } const res = await WXAPI.fetchShops(p) if (res.code == 0) { res.data.forEach(ele => { if (ele.distance) { ele.distance = ele.distance.toFixed(3) // 距离保留3位小数 } }) this.setData({ shops: res.data }) } }, async cpsJdOrderDetail() { wx.showLoading({ title: '', }) const res = await WXAPI.cpsJdOrderDetail(wx.getStorageSync('token'), this.data.orderId) wx.hideLoading() if (res.code == 0) { const orderInfo = res.data.orderInfo if (orderInfo.validCode != 17) { wx.showModal({ title: '错误', content: '已完成订单才可以申请回收', showCancel: false, success: res => { wx.navigateBack() } }) } if (orderInfo.recycleOrderId) { wx.showModal({ title: '错误', content: '请勿重复申请回收', showCancel: false, success: res => { wx.navigateBack() } }) } this.setData({ orderInfo, amountRecycle: orderInfo.estimateCosPrice, name: orderInfo.skuName, pic: orderInfo.imageUrl, amount: orderInfo.actualCosPrice, }) } else { wx.showModal({ title: '错误', content: res.msg, showCancel: false, success: res => { wx.navigateBack() } }) } }, async cpsPddOrderDetail() { wx.showLoading({ title: '', }) const res = await WXAPI.cpsPddOrderDetail(wx.getStorageSync('token'), this.data.orderId) wx.hideLoading() if (res.code == 0) { const orderInfo = res.data.orderInfo if (orderInfo.status != 2 && orderInfo.status != 3 && orderInfo.status != 5) { wx.showModal({ title: '错误', content: '已完成订单才可以申请回收', showCancel: false, success: res => { wx.navigateBack() } }) } if (orderInfo.recycleOrderId) { wx.showModal({ title: '错误', content: '请勿重复申请回收', showCancel: false, success: res => { wx.navigateBack() } }) } this.setData({ orderInfo, amountRecycle: orderInfo.orderAmount, name: orderInfo.goodsName, pic: orderInfo.imageUrl, amount: orderInfo.orderAmount, }) } else { wx.showModal({ title: '错误', content: res.msg, showCancel: false, success: res => { wx.navigateBack() } }) } }, logisticsTypeChange(e) { this.setData({ logisticsType: e.detail }) }, logisticsTypeClick(e) { this.setData({ logisticsType: e.currentTarget.dataset.name }) }, shopSelect(e) { this.setData({ shopIndex: e.detail.value }) }, callMobile() { const shop = this.data.shops[this.data.shopIndex] wx.makePhoneCall({ phoneNumber: shop.linkPhone, }) }, goMap() { const shop = this.data.shops[this.data.shopIndex] const latitude = shop.latitude const longitude = shop.longitude wx.openLocation({ latitude, longitude, scale: 18 }) }, async submit() { if (!this.data.amountRecycle) { wx.showToast({ title: '填写回收价格', icon: 'none' }) return } if (this.data.shopIndex == -1) { wx.showToast({ title: '请选择回收点', icon: 'none' }) return } const res = await WXAPI.recycleOrderApply({ token: wx.getStorageSync('token'), type: this.data.type, platform: this.data.platform, buyOrderId: this.data.orderId, name: this.data.name, pic: this.data.pic, amount: this.data.amount, amountRecycle: this.data.amountRecycle, logisticsType: this.data.logisticsType, shopId: this.data.shops[this.data.shopIndex].id, remark: this.data.remark ? this.data.remark : '', }) if (res.code != 0) { wx.showToast({ title: res.msg, icon: 'none' }) return } wx.showModal({ title: '成功', content: '提交成功,耐心等待审核', showCancel: false, success: res => { wx.redirectTo({ url: '/pages/recycle/orders', }) } }) } }) ================================================ FILE: pages/recycle/index.json ================================================ { "navigationBarTitleText":"申请回收" } ================================================ FILE: pages/recycle/index.wxml ================================================ 申请回收 ================================================ FILE: pages/recycle/index.wxss ================================================ .btn { padding: 32rpx; } ================================================ FILE: pages/recycle/order-detail.js ================================================ const WXAPI = require('apifm-wxapi') const AUTH = require('../../utils/auth') import wxbarcode from 'wxbarcode' Page({ data: { logisticsType: '0', // 0 自己送货 1 快递 shopIndex: -1 }, onLoad(e) { // e.id = 3 this.data.id = e.id this.recycleOrderDetail() }, onShow() { }, async recycleOrderDetail() { wx.showLoading({ title: '', }) const res = await WXAPI.recycleOrderDetail(wx.getStorageSync('token'), this.data.id) wx.hideLoading() if (res.code == 0) { const orderInfo = res.data.orderInfo if (orderInfo.shopId) { this.shopSubdetail(orderInfo.shopId) } if (orderInfo.logisticsType == 0) { wxbarcode.qrcode('qrcode', orderInfo.hxNumber, 650, 650); } this.setData({ orderInfo, shipperName: orderInfo.shipperName, trackingNumber: orderInfo.trackingNumber }) } else { wx.showModal({ title: '错误', content: res.msg, showCancel: false, success: res => { wx.navigateBack() } }) } }, async shopSubdetail(shopId) { const res = await WXAPI.shopSubdetail(shopId) if (res.code == 0) { this.setData({ shopInfodetail: res.data }) } }, callMobile() { wx.makePhoneCall({ phoneNumber: this.data.shopInfodetail.info.linkPhone, }) }, goMap() { const shop = this.data.shopInfodetail.info const latitude = shop.latitude const longitude = shop.longitude wx.openLocation({ latitude, longitude, scale: 18 }) }, fahuo() { this.setData({ popupShow: true }) }, popupClose() { this.setData({ popupShow: false }) }, trackingNumberScan() { wx.scanCode({ success: res => { this.setData({ trackingNumber: res.result }) } }) }, async submit() { if (!this.data.shipperName) { wx.showToast({ title: '填写回快递公司', icon: 'none' }) return } if (!this.data.trackingNumber) { wx.showToast({ title: '填写回快递单号', icon: 'none' }) return } this.setData({ submitButtonLoading: true }) const res = await WXAPI.recycleOrderFahuo({ token: wx.getStorageSync('token'), id: this.data.id, shipperName: this.data.shipperName, trackingNumber: this.data.trackingNumber, }) this.setData({ submitButtonLoading: false }) if (res.code != 0) { wx.showToast({ title: res.msg, icon: 'none' }) return } wx.showToast({ title: '提交成功', }) this.popupClose() this.recycleOrderDetail() } }) ================================================ FILE: pages/recycle/order-detail.json ================================================ { "navigationBarTitleText":"回收订单详情" } ================================================ FILE: pages/recycle/order-detail.wxml ================================================ 核销码 工作人员扫描该码完成回收 填写快递信息 确认 ================================================ FILE: pages/recycle/order-detail.wxss ================================================ .btn { padding: 32rpx; } .hx-qrcode { padding: 32rpx; text-align: center; color: #333; } .hx-qrcode .t { font-weight: bold; } .hx-qrcode .t2 { font-size: 26rpx; color: #666; } .hx-qrcode .hx-canvas { width: 650rpx; height: 650rpx; } .statusStr { color: #e64340 !important; font-weight: bold; } ================================================ FILE: pages/recycle/orders.js ================================================ const WXAPI = require('apifm-wxapi') Page({ data: { }, onLoad(e) { this.recycleOrders() }, onShow() { }, async recycleOrders() { wx.showLoading({ title: '', }) const res = await WXAPI.recycleOrders({ token: wx.getStorageSync('token') }) wx.hideLoading() if (res.code == 0) { this.setData({ list: res.data.result }) } }, onPullDownRefresh() { this.recycleOrders() wx.stopPullDownRefresh() }, detail(e) { const id = e.currentTarget.dataset.id wx.navigateTo({ url: `/pages/recycle/order-detail?id=${id}`, }) }, async recycleOrderClose(e) { wx.showModal({ title: '提示', content: '确认要取消该订单吗?', success: res => { if (res.confirm) { this._recycleOrderClose(e) } } }) }, async _recycleOrderClose(e) { const id = e.currentTarget.dataset.id const res = await WXAPI.recycleOrderClose(wx.getStorageSync('token'), id) if (res.code != 0) { wx.showToast({ title: res.msg, icon: 'none' }) return } wx.showToast({ title: '已取消', }) this.recycleOrders() }, async recycleOrderDelete(e) { wx.showModal({ title: '提示', content: '确认要删除该订单吗?', success: res => { if (res.confirm) { this._recycleOrderDelete(e) } } }) }, async _recycleOrderDelete(e) { const id = e.currentTarget.dataset.id const res = await WXAPI.recycleOrderDelete(wx.getStorageSync('token'), id) if (res.code != 0) { wx.showToast({ title: res.msg, icon: 'none' }) return } wx.showToast({ title: '删除成功', }) this.recycleOrders() } }) ================================================ FILE: pages/recycle/orders.json ================================================ { "navigationBarTitleText":"回收订单", "enablePullDownRefresh": true } ================================================ FILE: pages/recycle/orders.wxml ================================================ 订单号 {{ item.orderNumber }} 回收时间 {{ item.dateAdd }} 详情 取消 删除 ================================================ FILE: pages/recycle/orders.wxss ================================================ .btn { margin-left: 16rpx; } ================================================ FILE: pages/score/growth.js ================================================ const WXAPI = require('apifm-wxapi') const AUTH = require('../../utils/auth') Page({ /** * 页面的初始数据 */ data: { growth: 0.00, page: 1 }, /** * 生命周期函数--监听页面加载 */ onLoad(e) { AUTH.checkHasLogined().then(isLogined => { if (isLogined) { this.userAmountV2() this.growthLogsV2() } else { getApp().loginOK = () => { this.userAmountV2() this.growthLogsV2() } } }) }, onShow: function () { }, onReachBottom() { this.data.page++ this.growthLogsV2() }, async userAmountV2() { // https://www.yuque.com/apifm/nu0f75/wrqkcb const res = await WXAPI.userAmountV2(wx.getStorageSync('token')) if (res.code == 0) { this.setData({ growth: res.data.growth }) } }, async growthLogsV2() { wx.showLoading({ title: '', }) // https://www.yuque.com/apifm/nu0f75/gpb15y const res = await WXAPI.growthLogsV2({ token: wx.getStorageSync('token'), page: this.data.page, }) wx.hideLoading() if (res.code == 0) { if (this.data.page == 1) { this.setData({ cashlogs: res.data.result }) } else { this.setData({ cashlogs: this.data.cashlogs.concat(res.data.result) }) } } else { if (this.data.page == 1) { this.setData({ cashlogs: null }) } } }, exchangeGrowth: function (e) { wx.navigateTo({ url: '/pages/score-excharge/growth', }) } }) ================================================ FILE: pages/score/growth.json ================================================ { "navigationBarTitleText": "成长值明细" } ================================================ FILE: pages/score/growth.wxml ================================================ 当前成长值 {{growth}} 🎁 用积分兑换成长值 积分越多,成长越快 暂无成长值明细~ {{ item.typeStr }} {{ item.remark? '('+ item.remark +')' : '' }} {{ item.dateAdd }} 剩余成长值: {{ item.growthLeft }} {{ (item.behavior ==0 ) ? '+' : '' }} {{ item.growth }} ================================================ FILE: pages/score/growth.wxss ================================================ /* 页面整体背景 */ page { background: #f5f5f5; } /* 顶部成长值展示区 - 京东风格渐变红 */ .score { position: relative; display: flex; flex-direction: column; justify-content: center; align-items: center; width: 750rpx; padding: 60rpx 0 80rpx; background: linear-gradient(135deg, #e93b3d 0%, #e4393c 50%, #d42727 100%); box-shadow: 0 4rpx 20rpx rgba(228, 57, 60, 0.3); overflow: hidden; } /* 顶部装饰圆 */ .score::before { content: ''; position: absolute; width: 400rpx; height: 400rpx; background: rgba(255, 255, 255, 0.1); border-radius: 50%; top: -200rpx; right: -100rpx; } .score::after { content: ''; position: absolute; width: 300rpx; height: 300rpx; background: rgba(255, 255, 255, 0.08); border-radius: 50%; bottom: -150rpx; left: -80rpx; } .score view:first-child { position: relative; z-index: 1; font-size: 28rpx; color: rgba(255, 255, 255, 0.9); margin-bottom: 16rpx; letter-spacing: 1rpx; } .score view:last-child { position: relative; z-index: 1; font-size: 80rpx; font-weight: bold; color: #fff; line-height: 90rpx; text-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.15); } /* 空数据提示 */ .no-data { margin-top: 200rpx; text-align: center; font-size: 28rpx; color: #999; } /* 明细列表容器 */ .cashlogs { display: flex; align-items: center; justify-content: space-between; margin: 20rpx 30rpx; padding: 30rpx; background: #fff; border-radius: 16rpx; box-shadow: 0 2rpx 16rpx rgba(0, 0, 0, 0.06); transition: all 0.3s ease; position: relative; overflow: hidden; } /* 列表项左侧装饰条 */ .cashlogs::before { content: ''; position: absolute; left: 0; top: 50%; transform: translateY(-50%); width: 6rpx; height: 60%; background: linear-gradient(180deg, #e93b3d 0%, #e4393c 100%); border-radius: 0 4rpx 4rpx 0; } /* 明细信息区域 */ .cashlogs .profile { flex: 1; display: flex; flex-direction: column; padding-left: 24rpx; } /* 类型描述文字 */ .cashlogs .profile .typeStr { font-size: 30rpx; color: #333; font-weight: 500; margin-bottom: 12rpx; line-height: 40rpx; } /* 日期时间 */ .cashlogs .profile .dateAdd { font-size: 24rpx; color: #999; line-height: 32rpx; } /* 剩余成长值 */ .cashlogs .profile .growthLeft { font-size: 24rpx; color: #666; line-height: 32rpx; margin-top: 4rpx; } /* 成长值金额 */ .cashlogs .amount { flex-shrink: 0; min-width: 120rpx; text-align: right; font-size: 36rpx; font-weight: bold; padding-right: 8rpx; } /* 积分兑换成长值入口 */ .exchange-entry { display: flex; align-items: center; margin: 30rpx 30rpx 20rpx; padding: 32rpx 30rpx; background: linear-gradient(135deg, #fff 0%, #fafafa 100%); border-radius: 20rpx; box-shadow: 0 4rpx 24rpx rgba(0, 0, 0, 0.08); border: 1rpx solid rgba(233, 59, 61, 0.1); transition: all 0.3s ease; position: relative; overflow: hidden; } .exchange-entry::before { content: ''; position: absolute; left: 0; top: 0; bottom: 0; width: 6rpx; background: linear-gradient(180deg, #e93b3d 0%, #e4393c 100%); border-radius: 0 4rpx 4rpx 0; } .exchange-entry:active { transform: translateY(2rpx); box-shadow: 0 2rpx 16rpx rgba(0, 0, 0, 0.12); } .exchange-icon { font-size: 48rpx; margin-right: 24rpx; flex-shrink: 0; } .exchange-content { flex: 1; display: flex; flex-direction: column; } .exchange-title { font-size: 32rpx; font-weight: 500; color: #333; line-height: 44rpx; margin-bottom: 8rpx; } .exchange-desc { font-size: 26rpx; color: #999; line-height: 36rpx; } .exchange-arrow { font-size: 32rpx; color: #ccc; margin-left: 16rpx; flex-shrink: 0; } ================================================ FILE: pages/score/index.js ================================================ const app = getApp() const WXAPI = require('apifm-wxapi') const AUTH = require('../../utils/auth') Page({ /** * 页面的初始数据 */ data: { balance: 0.00, freeze: 0, score: 0, score_sign_continuous: 0, cashlogs: undefined }, /** * 生命周期函数--监听页面加载 */ onLoad: function (options) { AUTH.checkHasLogined().then(isLogined => { if (isLogined) { this.initData() } else { getApp().loginOK = () => { this.initData() } } }) }, onShow: function () { }, initData() { const _this = this const token = wx.getStorageSync('token') WXAPI.userAmount(token).then(function (res) { if (res.code == 0) { _this.setData({ balance: res.data.balance.toFixed(2), freeze: res.data.freeze.toFixed(2), totleConsumed: res.data.totleConsumed.toFixed(2), score: res.data.score }); } else { wx.showToast({ title: res.msg, icon: 'none' }) } }) // 读取积分明细 WXAPI.scoreLogs({ token: token, page:1, pageSize:50 }).then(res => { if (res.code == 0) { _this.setData({ cashlogs: res.data.result }) } }) }, recharge: function (e) { wx.navigateTo({ url: "/pages/recharge/index" }) }, withdraw: function (e) { wx.navigateTo({ url: "/pages/withdraw/index" }) }, sign() { wx.navigateTo({ url: '/pages/sign/index', }) }, exchange() { wx.navigateTo({ url: '/pages/score-excharge/index', }) }, }) ================================================ FILE: pages/score/index.json ================================================ { "navigationBarTitleText": "积分明细" } ================================================ FILE: pages/score/index.wxml ================================================ 我的积分 {{score}} 积分可兑换精美礼品 获取积分 每日签到 签到得积分 积分券兑换 券兑积分 积分明细 📋 暂无积分明细 {{ (item.behavior ==0 ) ? '得' : '用' }} {{ item.typeStr }} {{ item.remark }} {{ item.dateAdd }} {{ (item.behavior ==0 ) ? '+' : '-' }} {{ item.score }} ================================================ FILE: pages/score/index.wxss ================================================ /* 页面容器 */ .page-container { min-height: 100vh; background: #f5f5f5; padding-bottom: 40rpx; } /* 顶部积分卡片 - 京东红色渐变 */ .score-header { padding: 40rpx 30rpx 60rpx; background: linear-gradient(135deg, #E4393C 0%, #FF6B6B 100%); position: relative; } .score-bg { text-align: center; color: #fff; position: relative; z-index: 1; } .score-title { font-size: 28rpx; opacity: 0.95; margin-bottom: 20rpx; font-weight: 400; letter-spacing: 2rpx; } .score-value { font-size: 88rpx; font-weight: bold; line-height: 1.2; margin-bottom: 10rpx; text-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.15); font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', sans-serif; } .score-desc { font-size: 24rpx; opacity: 0.9; margin-top: 10rpx; } /* 获取积分途径区域 */ .score-ways { margin: -30rpx 30rpx 30rpx; background: #fff; border-radius: 20rpx; padding: 30rpx; box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.06); position: relative; z-index: 2; } .section-title { display: flex; align-items: center; margin-bottom: 30rpx; } .title-text { font-size: 32rpx; font-weight: 600; color: #333; position: relative; padding-left: 20rpx; } .title-text::before { content: ''; position: absolute; left: 0; top: 50%; transform: translateY(-50%); width: 6rpx; height: 28rpx; background: linear-gradient(180deg, #E4393C 0%, #FF6B6B 100%); border-radius: 3rpx; } .title-line { flex: 1; height: 1rpx; background: linear-gradient(to right, #eee 0%, transparent 100%); margin-left: 20rpx; } .ways-grid { display: flex; justify-content: space-between; gap: 20rpx; } .way-item { flex: 1; background: linear-gradient(135deg, #fff 0%, #fafafa 100%); border-radius: 16rpx; padding: 40rpx 20rpx 30rpx; text-align: center; border: 2rpx solid #f0f0f0; transition: all 0.3s; position: relative; overflow: hidden; } .way-item::before { content: ''; position: absolute; top: 0; left: 0; right: 0; bottom: 0; background: linear-gradient(135deg, rgba(228, 57, 60, 0.05) 0%, rgba(255, 107, 107, 0.05) 100%); opacity: 0; transition: opacity 0.3s; } .way-item:active::before { opacity: 1; } .way-icon { width: 96rpx; height: 96rpx; border-radius: 50%; margin: 0 auto 20rpx; display: flex; align-items: center; justify-content: center; position: relative; } .sign-icon { background: linear-gradient(135deg, #FF6B6B 0%, #E4393C 100%); box-shadow: 0 8rpx 20rpx rgba(228, 57, 60, 0.3); } .coupon-icon { background: linear-gradient(135deg, #FFA726 0%, #FF6F00 100%); box-shadow: 0 8rpx 20rpx rgba(255, 167, 38, 0.3); } .icon-text { font-size: 40rpx; font-weight: bold; color: #fff; text-shadow: 0 2rpx 4rpx rgba(0, 0, 0, 0.1); } .way-title { font-size: 28rpx; font-weight: 600; color: #333; margin-bottom: 10rpx; } .way-desc { font-size: 22rpx; color: #999; } /* 积分明细区域 */ .score-logs { margin: 0 30rpx; background: #fff; border-radius: 20rpx; padding: 30rpx; box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.06); } /* 空数据样式 */ .no-data { text-align: center; padding: 80rpx 0; } .no-data-icon { font-size: 80rpx; margin-bottom: 20rpx; opacity: 0.3; } .no-data-text { font-size: 28rpx; color: #ccc; } /* 积分明细列表 */ .log-list { margin-top: 10rpx; } .log-item { display: flex; align-items: center; justify-content: space-between; padding: 30rpx 0; border-bottom: 1rpx solid #f5f5f5; position: relative; } .log-item:last-child { border-bottom: none; } .log-left { display: flex; align-items: center; flex: 1; min-width: 0; } .log-icon { width: 80rpx; height: 80rpx; border-radius: 50%; display: flex; align-items: center; justify-content: center; flex-shrink: 0; margin-right: 24rpx; box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1); } .log-icon-text { font-size: 32rpx; font-weight: bold; color: #fff; } .log-info { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 8rpx; } .log-title { font-size: 28rpx; font-weight: 500; color: #333; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .log-remark { font-size: 24rpx; color: #999; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .log-time { font-size: 22rpx; color: #bbb; } .log-amount { font-size: 32rpx; font-weight: 600; flex-shrink: 0; margin-left: 20rpx; display: flex; align-items: baseline; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', sans-serif; } .amount-symbol { font-size: 24rpx; margin-right: 2rpx; } .amount-value { font-size: 36rpx; } ================================================ FILE: pages/score-excharge/growth.js ================================================ const app = getApp() const WXAPI = require('apifm-wxapi') const AUTH = require('../../utils/auth') Page({ /** * 页面的初始数据 */ data: { score: 0, growth: 0, uid: undefined }, /** * 生命周期函数--监听页面加载 */ onLoad: function (options) { AUTH.checkHasLogined().then(isLogined => { if (isLogined) { this.initData() } else { getApp().loginOK = () => { this.initData() } } }) }, onShow: function () { }, async initData(){ const token = wx.getStorageSync('token') const res1 = await WXAPI.userAmount(token) if (res1.code == 0) { this.data.score = res1.data.score this.data.growth = res1.data.growth } const res2 = await WXAPI.scoreDeductionRules(1); if (res2.code == 0) { this.data.deductionRules = res2.data } this.setData({ score: this.data.score, growth: this.data.growth, deductionRules: this.data.deductionRules, }) }, async bindSave() { if (!this.data.score2) { wx.showToast({ title: '请输入积分数量', icon: 'none' }) return } // https://www.yuque.com/apifm/nu0f75/sq3tzp const res = await WXAPI.exchangeScoreToGrowthV2({ token: wx.getStorageSync('token'), deductionScore: this.data.score2 }) if (res.code == 0) { wx.showModal({ content: '恭喜您,成功兑换'+ res.data +'成长值', showCancel: false }) this.initData() } else { wx.showToast({ title: res.msg, icon: 'none' }) } }, }) ================================================ FILE: pages/score-excharge/growth.json ================================================ { "navigationBarTitleText": "积分兑换成长值" } ================================================ FILE: pages/score-excharge/growth.wxml ================================================ 当前积分 {{score}} 当前成长值 {{ growth }} 💎 积分兑换成长值 兑换积分 ℹ️ 积分可兑换成长值,助您快速升级 ================================================ FILE: pages/score-excharge/growth.wxss ================================================ /* 页面整体样式 */ page { height: 100%; background: linear-gradient(180deg, #f5f5f5 0%, #ffffff 100%); } /* 顶部渐变背景区 - 京东红 */ .top-header { background: linear-gradient(135deg, #E3393C 0%, #F44336 100%); padding: 40rpx 30rpx 80rpx; position: relative; overflow: hidden; } .top-header::before { content: ''; position: absolute; top: -50%; right: -20%; width: 400rpx; height: 400rpx; background: rgba(255, 255, 255, 0.1); border-radius: 50%; } .top-header::after { content: ''; position: absolute; bottom: -30%; left: -10%; width: 300rpx; height: 300rpx; background: rgba(255, 255, 255, 0.08); border-radius: 50%; } /* 资产展示卡片 */ .assets-card { background: rgba(255, 255, 255, 0.95); border-radius: 24rpx; padding: 50rpx 40rpx; display: flex; justify-content: space-around; align-items: center; box-shadow: 0 8rpx 32rpx rgba(227, 57, 60, 0.2); backdrop-filter: blur(10rpx); position: relative; z-index: 2; } .asset-item { flex: 1; text-align: center; display: flex; flex-direction: column; align-items: center; } .asset-label { font-size: 26rpx; color: #999999; margin-bottom: 16rpx; font-weight: 400; } .asset-value { font-size: 68rpx; color: #E3393C; font-weight: bold; line-height: 1.2; background: linear-gradient(135deg, #E3393C 0%, #F44336 100%); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; } .asset-unit { font-size: 24rpx; color: #666666; margin-top: 8rpx; } .divider-line { width: 2rpx; height: 100rpx; background: linear-gradient(180deg, rgba(227, 57, 60, 0) 0%, rgba(227, 57, 60, 0.3) 50%, rgba(227, 57, 60, 0) 100% ); margin: 0 20rpx; } /* 主容器 */ .container { background-color: transparent; justify-content: initial; padding: 0 30rpx; margin-top: -50rpx; position: relative; z-index: 3; } /* 兑换卡片 */ .exchange-card { background: #ffffff; border-radius: 24rpx; padding: 40rpx 30rpx; box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.06); margin-bottom: 30rpx; width: 90%; } .card-title { display: flex; align-items: center; margin-bottom: 40rpx; padding-bottom: 30rpx; border-bottom: 2rpx solid #f5f5f5; } .title-icon { font-size: 40rpx; margin-right: 16rpx; } .title-text { font-size: 32rpx; color: #333333; font-weight: bold; } /* 输入区域 */ .input-wrapper { margin-bottom: 30rpx; } .input-label { font-size: 28rpx; color: #666666; margin-bottom: 20rpx; font-weight: 500; } .input-box { background: #f8f8f8; border-radius: 16rpx; padding: 0 24rpx; border: 2rpx solid #f0f0f0; transition: all 0.3s ease; } .input-box .input { height: 88rpx; line-height: 88rpx; font-size: 30rpx; color: #333333; } .placeholder-style { color: #bbbbbb; font-size: 28rpx; } /* 提示信息 */ .exchange-hint { display: flex; align-items: center; background: linear-gradient(135deg, #FFF3F3 0%, #FFE8E8 100%); padding: 20rpx 24rpx; border-radius: 12rpx; border-left: 6rpx solid #E3393C; } .hint-icon { font-size: 28rpx; margin-right: 12rpx; } .hint-text { font-size: 24rpx; color: #E3393C; line-height: 1.6; } /* 兑换按钮 - 京东风格 */ .exchange-btn { width: 690rpx; height: 96rpx; background: linear-gradient(135deg, #E3393C 0%, #F44336 100%); border-radius: 48rpx; display: flex; align-items: center; justify-content: center; box-shadow: 0 8rpx 24rpx rgba(227, 57, 60, 0.35); border: none; margin: 0 auto; position: relative; overflow: hidden; transition: all 0.3s ease; } .exchange-btn::before { content: ''; position: absolute; top: 50%; left: 50%; width: 0; height: 0; border-radius: 50%; background: rgba(255, 255, 255, 0.3); transform: translate(-50%, -50%); transition: width 0.6s, height 0.6s; } .exchange-btn:active { transform: scale(0.98); box-shadow: 0 4rpx 16rpx rgba(227, 57, 60, 0.3); } .exchange-btn:active::before { width: 200%; height: 200%; } .btn-text { font-size: 32rpx; color: #ffffff; font-weight: bold; letter-spacing: 2rpx; position: relative; z-index: 1; } /* 兑换规则样式优化 */ .van-cell-group { margin-top: 30rpx; border-radius: 24rpx; overflow: hidden; box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.06); } /* 移除旧样式 */ .form-box, .row-wrap, .save-btn, .cancel-btn, .addr-details { display: none; } /* 保留的通用样式 */ picker { min-width: 20rpx; height: 100%; margin-right: 20rpx; } .hui { color: #777; } ================================================ FILE: pages/score-excharge/index.js ================================================ const app = getApp() const WXAPI = require('apifm-wxapi') const AUTH = require('../../utils/auth') Page({ /** * 页面的初始数据 */ data: { uid: undefined }, /** * 生命周期函数--监听页面加载 */ onLoad: function(options) { }, onShow: function() { }, bindSave(e) { var that = this; var amount = this.data.amount; if (amount == "") { wx.showModal({ title: '错误', content: '请填写正确的券号', showCancel: false }) return } WXAPI.scoreExchange(wx.getStorageSync('token'), amount).then(function(res) { if (res.code == 700) { wx.showModal({ title: '错误', content: '券号不正确', showCancel: false }) return } if (res.code == 0) { wx.showModal({ title: '成功', content: '恭喜您,成功兑换 ' + res.data.score + ' 积分', showCancel: false, success: function(res) { if (res.confirm) { that.bindCancel(); } } }) } else { wx.showModal({ title: '错误', content: res.data.msg, showCancel: false }) } }) } }) ================================================ FILE: pages/score-excharge/index.json ================================================ { "navigationBarTitleText": "积分券兑换积分" } ================================================ FILE: pages/score-excharge/index.wxml ================================================ 积分券兑换 输入积分券号码,立即获得积分奖励 积分券号码 i 使用说明 积分券仅限本平台使用,不可转让 每个积分券仅可使用一次 兑换成功后积分将立即到账 如有疑问请联系客服 ================================================ FILE: pages/score-excharge/index.wxss ================================================ /* 页面整体样式 - 京东风格 */ page { height: 100%; background: linear-gradient(180deg, #FFF1F0 0%, #FFFFFF 50%); } .exchange-page { min-height: 100vh; position: relative; overflow: hidden; } /* 头部装饰区域 - 京东红色系 */ .header-decoration { position: absolute; top: 0; left: 0; right: 0; height: 400rpx; pointer-events: none; overflow: hidden; } .decoration-circle { position: absolute; border-radius: 50%; opacity: 0.08; } .decoration-circle.circle1 { width: 260rpx; height: 260rpx; background: linear-gradient(135deg, #E1251B, #FF4747); top: -130rpx; right: -80rpx; } .decoration-circle.circle2 { width: 180rpx; height: 180rpx; background: linear-gradient(135deg, #E1251B, #FF6B6B); top: 100rpx; left: -60rpx; } .decoration-circle.circle3 { width: 140rpx; height: 140rpx; background: linear-gradient(135deg, #FF4747, #FF8989); top: 260rpx; right: 120rpx; } /* 主要内容区域 */ .exchange-content { padding: 80rpx 32rpx 40rpx; position: relative; z-index: 1; } /* 标题区域 - 京东风格 */ .title-section { text-align: center; margin-bottom: 60rpx; } .icon-wrapper { width: 120rpx; height: 120rpx; background: linear-gradient(135deg, #E1251B 0%, #FF4747 100%); border-radius: 50%; display: flex; align-items: center; justify-content: center; margin: 0 auto 32rpx; box-shadow: 0 12rpx 32rpx rgba(225, 37, 27, 0.35); position: relative; } .icon-wrapper::after { content: ''; position: absolute; width: 140rpx; height: 140rpx; border: 2rpx solid rgba(225, 37, 27, 0.2); border-radius: 50%; animation: pulse 2s infinite; } @keyframes pulse { 0%, 100% { transform: scale(1); opacity: 1; } 50% { transform: scale(1.15); opacity: 0.5; } } .gift-icon { width: 60rpx; height: 60rpx; filter: brightness(0) invert(1); } .main-title { display: block; font-weight: 700; font-size: 52rpx; color: #333333; margin-bottom: 16rpx; letter-spacing: 2rpx; } .sub-title { display: block; font-size: 28rpx; color: #999999; line-height: 40rpx; } /* 兑换表单 - 京东卡片风格 */ .exchange-form { background: #FFFFFF; border-radius: 24rpx; padding: 48rpx 40rpx; margin-bottom: 40rpx; box-shadow: 0 4rpx 24rpx rgba(0, 0, 0, 0.06); position: relative; } .exchange-form::before { content: ''; position: absolute; top: 0; left: 0; right: 0; height: 8rpx; background: linear-gradient(90deg, #E1251B 0%, #FF4747 100%); border-radius: 24rpx 24rpx 0 0; } .form-item { margin-bottom: 48rpx; } .form-label { display: block; font-weight: 600; font-size: 30rpx; color: #333333; margin-bottom: 24rpx; position: relative; padding-left: 20rpx; } .form-label::before { content: ''; position: absolute; left: 0; top: 50%; transform: translateY(-50%); width: 6rpx; height: 28rpx; background: linear-gradient(180deg, #E1251B, #FF4747); border-radius: 3rpx; } .input-wrapper { position: relative; background: #F8F9FA; border-radius: 16rpx; border: 2rpx solid #E9ECEF; transition: all 0.3s ease; overflow: hidden; } .input-wrapper::after { content: ''; position: absolute; left: 0; bottom: 0; width: 0; height: 4rpx; background: linear-gradient(90deg, #E1251B, #FF4747); transition: width 0.3s ease; } /* 聚焦状态 */ .coupon-input:focus { background: #FFFFFF; } .input-wrapper:focus-within { border-color: #E1251B; background: #FFFFFF; box-shadow: 0 0 0 6rpx rgba(225, 37, 27, 0.08); } .input-wrapper:focus-within::after { width: 100%; } .coupon-input { width: 100%; height: 96rpx; padding: 0 32rpx; font-size: 32rpx; color: #333333; background: transparent; border: none; line-height: 96rpx; } .input-placeholder { color: #BBBBBB; font-size: 28rpx; } /* 兑换按钮 - 京东红 */ .exchange-btn { width: 100%; height: 96rpx; background: linear-gradient(135deg, #E1251B 0%, #FF4747 100%); border-radius: 48rpx; border: none; display: flex; align-items: center; justify-content: center; box-shadow: 0 8rpx 24rpx rgba(225, 37, 27, 0.35); transition: all 0.3s ease; position: relative; overflow: hidden; } .exchange-btn::before { content: ''; position: absolute; top: 0; left: -100%; width: 100%; height: 100%; background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.3), transparent); transition: left 0.5s ease; } .exchange-btn:active::before { left: 100%; } .exchange-btn:active { transform: translateY(2rpx); box-shadow: 0 4rpx 16rpx rgba(225, 37, 27, 0.3); } .exchange-btn::after { border: none; } .btn-text { font-weight: 600; font-size: 34rpx; color: #FFFFFF; letter-spacing: 4rpx; text-shadow: 0 2rpx 4rpx rgba(0, 0, 0, 0.1); } /* 使用说明 - 京东风格 */ .tips-section { background: #FFFFFF; border-radius: 24rpx; padding: 40rpx; box-shadow: 0 4rpx 24rpx rgba(0, 0, 0, 0.06); } .tips-header { display: flex; align-items: center; margin-bottom: 32rpx; padding-bottom: 20rpx; border-bottom: 2rpx solid #F5F5F5; } .info-icon { width: 40rpx; height: 40rpx; border-radius: 50%; background: linear-gradient(135deg, #E1251B, #FF4747); color: #FFFFFF; font-size: 24rpx; font-weight: bold; font-style: italic; display: flex; align-items: center; justify-content: center; margin-right: 16rpx; } .tips-title { font-weight: 600; font-size: 30rpx; color: #333333; } .tips-list { padding-left: 8rpx; } .tips-item { display: flex; align-items: flex-start; margin-bottom: 20rpx; padding-left: 12rpx; } .tips-item:last-child { margin-bottom: 0; } .tips-dot { font-weight: 700; font-size: 32rpx; color: #E1251B; margin-right: 16rpx; line-height: 40rpx; flex-shrink: 0; } .tips-text { flex: 1; font-size: 26rpx; color: #666666; line-height: 40rpx; } ================================================ FILE: pages/search/index.js ================================================ Page({ data: { }, onLoad: function (options) { const hot_search_words = wx.getStorageSync('hot_search_words') this.setData({ list: wx.getStorageSync('searchHis'), hot_search_words: hot_search_words ? hot_search_words.split(',') : null }) }, onShow: function () { }, search(e) { this.setData({ inputVal: e.detail }) if (e.detail) { let searchHis = wx.getStorageSync('searchHis') if (!searchHis) { searchHis = [e.detail] } if (!searchHis.includes(e.detail)) { searchHis.push(e.detail) } wx.setStorageSync('searchHis', searchHis) this.setData({ list: searchHis }) } wx.navigateTo({ url: '/pages/goods/list?name=' + this.data.inputVal, }) }, onClose(e) { const idx = e.currentTarget.dataset.idx const searchHis = this.data.list searchHis.splice(idx, 1) wx.setStorageSync('searchHis', searchHis) this.setData({ list: searchHis }) }, go(e) { const idx = e.currentTarget.dataset.idx const keywords = this.data.list[idx] wx.navigateTo({ url: '/pages/goods/list?name=' + keywords, }) }, go2(e) { const idx = e.currentTarget.dataset.idx const keywords = this.data.hot_search_words[idx] wx.navigateTo({ url: '/pages/goods/list?name=' + keywords, }) }, searchscan() { wx.scanCode({ scanType: ['barCode', 'qrCode', 'datamatrix', 'pdf417'], success: res => { wx.navigateTo({ url: '/pages/goods/list?name=' + res.result, }) } }) } }) ================================================ FILE: pages/search/index.json ================================================ { "navigationBarTitleText": "搜索" } ================================================ FILE: pages/search/index.wxml ================================================ 历史搜索 {{ item }} 热门搜索 {{ index + 1 }} {{ item }} 暂无搜索记录 快去搜索你想要的商品吧~ ================================================ FILE: pages/search/index.wxss ================================================ /* pages/search/index.wxss - 京东风格搜索页面 */ /* 页面整体 */ .search-page { min-height: 100vh; background: linear-gradient(180deg, #E4393C 0%, #E4393C 120rpx, #f5f5f5 120rpx); } /* ==================== 搜索头部区域 ==================== */ .search-header { position: fixed; top: 0; left: 0; right: 0; z-index: 999; background: #E4393C; padding: 16rpx 24rpx; box-shadow: 0 4rpx 12rpx rgba(228, 57, 60, 0.15); } .search-container { position: relative; } /* 覆盖van-search默认样式 */ .search-header .van-search { padding: 0; } .search-header .van-search__content { background: rgba(255, 255, 255, 0.95); border-radius: 48rpx; padding-left: 32rpx; padding-right: 32rpx; box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.08); } .search-header .van-field__control { font-size: 28rpx; color: #333; } .scan-icon { display: flex; align-items: center; justify-content: center; width: 56rpx; height: 56rpx; background: linear-gradient(135deg, #FF6B6B 0%, #E4393C 100%); border-radius: 50%; margin-left: 16rpx; box-shadow: 0 4rpx 12rpx rgba(228, 57, 60, 0.3); } /* ==================== 内容区域 ==================== */ .search-content { padding-top: 120rpx; padding-bottom: 40rpx; } /* ==================== 搜索区块 ==================== */ .search-section { margin: 32rpx 24rpx; background: #fff; border-radius: 24rpx; padding: 32rpx; box-shadow: 0 4rpx 24rpx rgba(0, 0, 0, 0.06); } /* 区块头部 */ .section-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 24rpx; } .header-left { display: flex; align-items: center; } .icon-wrapper { display: flex; align-items: center; justify-content: center; width: 48rpx; height: 48rpx; background: linear-gradient(135deg, #FFE5E5 0%, #FFD5D5 100%); border-radius: 12rpx; margin-right: 16rpx; } .section-title { font-size: 32rpx; font-weight: 600; color: #333; letter-spacing: 0.5rpx; } /* ==================== 标签容器 ==================== */ .tag-container { display: flex; flex-wrap: wrap; gap: 20rpx; } .tag-item { position: relative; display: flex; align-items: center; padding: 16rpx 32rpx; background: #f8f8f8; border-radius: 48rpx; font-size: 28rpx; color: #666; transition: all 0.3s ease; border: 2rpx solid transparent; } .tag-item:active { background: #fff; border-color: #E4393C; transform: translateY(-2rpx); box-shadow: 0 4rpx 12rpx rgba(228, 57, 60, 0.15); } .tag-text { max-width: 400rpx; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } /* 关闭按钮 */ .tag-close { display: flex; align-items: center; justify-content: center; width: 32rpx; height: 32rpx; margin-left: 12rpx; background: #e8e8e8; border-radius: 50%; transition: all 0.2s ease; } .tag-close:active { background: #E4393C; } .tag-close:active .van-icon { color: #fff !important; } /* ==================== 热门标签特殊样式 ==================== */ .hot-tag { background: linear-gradient(135deg, #FFF5F5 0%, #FFE8E8 100%); color: #E4393C; font-weight: 500; border: 2rpx solid #FFD5D5; padding-left: 24rpx; } .hot-tag:active { background: linear-gradient(135deg, #FFE8E8 0%, #FFD5D5 100%); border-color: #E4393C; box-shadow: 0 4rpx 16rpx rgba(228, 57, 60, 0.2); } .hot-badge { display: flex; align-items: center; justify-content: center; width: 32rpx; height: 32rpx; background: linear-gradient(135deg, #FF6B6B 0%, #E4393C 100%); color: #fff; font-size: 20rpx; font-weight: 600; border-radius: 50%; margin-right: 12rpx; box-shadow: 0 2rpx 8rpx rgba(228, 57, 60, 0.3); } /* ==================== 空状态 ==================== */ .empty-state { display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 120rpx 48rpx; margin: 80rpx 24rpx; background: #fff; border-radius: 24rpx; box-shadow: 0 4rpx 24rpx rgba(0, 0, 0, 0.06); } .empty-icon { width: 160rpx; height: 160rpx; display: flex; align-items: center; justify-content: center; background: linear-gradient(135deg, #f8f8f8 0%, #f0f0f0 100%); border-radius: 50%; margin-bottom: 32rpx; } .empty-text { font-size: 32rpx; color: #999; margin-bottom: 16rpx; font-weight: 500; } .empty-tip { font-size: 26rpx; color: #ccc; } /* ==================== 动画效果 ==================== */ @keyframes slideInUp { from { opacity: 0; transform: translateY(30rpx); } to { opacity: 1; transform: translateY(0); } } .search-section { animation: slideInUp 0.4s ease-out; } /* ==================== 响应式优化 ==================== */ @media (max-width: 375px) { .tag-item { padding: 14rpx 28rpx; font-size: 26rpx; } .section-title { font-size: 30rpx; } } ================================================ FILE: pages/select-address/index.js ================================================ const WXAPI = require('apifm-wxapi') const AUTH = require('../../utils/auth') const app = getApp() Page({ data: { page: 1 }, selectTap: function(e) { console.log(e); var id = e.currentTarget.dataset.id; WXAPI.updateAddress({ token: wx.getStorageSync('token'), id: id, isDefault: 'true' }).then(function(res) { wx.navigateBack({}) }) }, addAddess: function() { wx.navigateTo({ url: "/pages/address-add/index" }) }, editAddess: function(e) { console.log(e); wx.navigateTo({ url: "/pages/address-add/index?id=" + e.currentTarget.dataset.id }) }, onLoad() { }, onShow: function() { this.initShippingAddress(); }, async initShippingAddress() { wx.showLoading({ title: '', }) const res = await WXAPI.queryAddressV2({ token: wx.getStorageSync('token') }) wx.hideLoading({ success: (res) => {}, }) if (res.code == 0) { this.setData({ addressList: res.data.result }); } else if (res.code == 700) { this.setData({ addressList: null }); } else { wx.showToast({ title: res.msg, icon: 'none' }) } }, onPullDownRefresh() { this.data.page = 1 this.initShippingAddress() wx.stopPullDownRefresh() }, deleteAddress(e) { const id = e.currentTarget.dataset.id const index = e.currentTarget.dataset.index wx.showModal({ content: '确定要删除该收货地址吗?', success: async (res) => { if (res.confirm) { // https://www.yuque.com/apifm/nu0f75/gb0a2k wx.showLoading({ title: '', }) const res = await WXAPI.deleteAddress(wx.getStorageSync('token'), id) wx.hideLoading() if (res.code != 0) { wx.showToast({ title: res.msg, icon: 'none' }) } else { wx.showToast({ title: '删除成功', icon: 'none' }) this.data.addressList.splice(index, 1) this.setData({ addressList: this.data.addressList }) } } } }) }, }) ================================================ FILE: pages/select-address/index.json ================================================ { "navigationBarTitleText": "选择收货地址", "enablePullDownRefresh": true } ================================================ FILE: pages/select-address/index.wxml ================================================ 默认 {{item.address}} 编辑 删除 新增收货地址 ================================================ FILE: pages/select-address/index.wxss ================================================ /* 容器样式 */ .address-container { min-height: 100vh; background-color: #f5f5f5; padding: 20rpx; box-sizing: border-box; } /* 地址列表 */ .address-list { margin-bottom: 120rpx; } /* 地址卡片 */ .address-item { background: #ffffff; border-radius: 16rpx; margin-bottom: 20rpx; overflow: hidden; box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.08); transition: all 0.3s ease; } .address-item:active { transform: scale(0.98); box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.12); } /* 地址内容区域 */ .address-content { padding: 32rpx 28rpx 24rpx; position: relative; } /* 地址头部 */ .address-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20rpx; } /* 用户信息 */ .user-info { display: flex; align-items: center; gap: 20rpx; } .user-name { font-size: 32rpx; font-weight: 600; color: #333333; letter-spacing: 1rpx; } .user-phone { font-size: 30rpx; color: #666666; font-weight: 500; } /* 默认地址标签 */ .default-tag { background: linear-gradient(135deg, #ff6a00 0%, #ee0a24 100%); color: #ffffff; font-size: 22rpx; padding: 6rpx 16rpx; border-radius: 24rpx; font-weight: 500; letter-spacing: 1rpx; box-shadow: 0 2rpx 8rpx rgba(238, 10, 36, 0.25); } /* 地址详情 */ .address-detail { display: flex; align-items: flex-start; line-height: 1.6; } .address-text { font-size: 28rpx; color: #666666; line-height: 42rpx; word-break: break-all; } /* 操作按钮区域 */ .address-actions { display: flex; align-items: center; border-top: 1rpx solid #f0f0f0; background: #fafafa; } .action-btn { flex: 1; display: flex; align-items: center; justify-content: center; gap: 12rpx; padding: 24rpx 0; font-size: 28rpx; color: #666666; transition: all 0.2s ease; } .action-btn:active { background: #f0f0f0; } .action-btn text { font-weight: 500; } .edit-btn { color: #333333; } .delete-btn { color: #ee0a24; } .action-divider { width: 1rpx; height: 32rpx; background: #e5e5e5; } /* 底部操作区 */ .safe-bottom-box { position: fixed; bottom: 0; left: 0; right: 0; padding: 20rpx 30rpx; padding-bottom: calc(20rpx + env(safe-area-inset-bottom)); background: linear-gradient(to top, rgba(255,255,255,0.98) 0%, rgba(255,255,255,0.95) 100%); backdrop-filter: blur(10rpx); box-shadow: 0 -4rpx 16rpx rgba(0, 0, 0, 0.06); z-index: 100; box-sizing: border-box; } .add-btn { width: 100%; height: 88rpx; background: linear-gradient(135deg, #ff6a00 0%, #ee0a24 100%); border-radius: 44rpx; display: flex; align-items: center; justify-content: center; gap: 12rpx; color: #ffffff; font-size: 32rpx; font-weight: 600; letter-spacing: 2rpx; box-shadow: 0 8rpx 20rpx rgba(238, 10, 36, 0.3); transition: all 0.3s ease; box-sizing: border-box; } .add-btn:active { transform: scale(0.96); box-shadow: 0 4rpx 12rpx rgba(238, 10, 36, 0.4); } ================================================ FILE: pages/shop/select.js ================================================ const WXAPI = require('apifm-wxapi') const AUTH = require('../../utils/auth') const APP = getApp() Page({ /** * 页面的初始数据 */ data: { }, /** * 生命周期函数--监听页面加载 */ onLoad: function (options) { }, /** * 生命周期函数--监听页面初次渲染完成 */ onReady: function () { }, /** * 生命周期函数--监听页面显示 */ onShow: function () { wx.getLocation({ type: 'gcj02', //wgs84 返回 gps 坐标,gcj02 返回可用于 wx.openLocation 的坐标 success: (res) => { this.data.latitude = res.latitude this.data.longitude = res.longitude this.fetchShops(res.latitude, res.longitude, '') }, fail(e){ console.error(e) AUTH.checkAndAuthorize('scope.userLocation') } }) }, async fetchShops(latitude, longitude, kw){ const res = await WXAPI.fetchShops({ curlatitude: latitude, curlongitude: longitude, nameLike: kw }) if (res.code == 0) { res.data.forEach(ele => { ele.distance = ele.distance.toFixed(3) // 距离保留3位小数 }) this.setData({ shops: res.data }) } else { this.setData({ shops: null }) } }, /** * 生命周期函数--监听页面隐藏 */ onHide: function () { }, /** * 生命周期函数--监听页面卸载 */ onUnload: function () { }, /** * 页面相关事件处理函数--监听用户下拉动作 */ onPullDownRefresh: function () { }, /** * 页面上拉触底事件的处理函数 */ onReachBottom: function () { }, searchChange(event){ this.setData({ searchValue: event.detail.value }) }, search(event){ console.log('search') this.setData({ searchValue: event.detail.value }) this.fetchShops(this.data.latitude, this.data.longitude, event.detail.value) }, goShop(e){ const idx = e.currentTarget.dataset.idx wx.setStorageSync('shopInfo', this.data.shops[idx]) wx.setStorageSync('shopIds', this.data.shops[idx].id) wx.setStorageSync('refreshIndex', 1) wx.switchTab({ url: '/pages/index/index' }) } }) ================================================ FILE: pages/shop/select.json ================================================ { "usingComponents": {}, "navigationBarTitleText": "选择门店" } ================================================ FILE: pages/shop/select.wxml ================================================ {{ item.name }} {{ item.distance }} km {{ item.address }} {{ item.openingHours }} {{ item.linkPhone }} 选择门店 ================================================ FILE: pages/shop/select.wxss ================================================ /* 页面容器 */ .page-container { min-height: 100vh; background: linear-gradient(to bottom, #f5f5f5 0%, #ffffff 300rpx); } /* ==================== 搜索栏样式 ==================== */ .search-wrapper { padding: 24rpx 24rpx 20rpx; background: #ffffff; } .search-box { position: relative; background: #f5f5f5; border-radius: 36rpx; height: 72rpx; display: flex; align-items: center; overflow: hidden; box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.04); } .search-icon { position: absolute; width: 32rpx; height: 32rpx; left: 28rpx; z-index: 2; } .search-input { flex: 1; height: 72rpx; padding-left: 72rpx; padding-right: 28rpx; font-size: 28rpx; color: #333; } .search-placeholder { color: #999; font-size: 28rpx; } /* ==================== 门店列表容器 ==================== */ .shops-container { padding: 0 24rpx 24rpx; } /* ==================== 门店卡片样式 ==================== */ .shop-card { position: relative; background: #ffffff; border-radius: 16rpx; margin-top: 24rpx; padding: 32rpx 28rpx 28rpx; box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.06); transition: all 0.3s ease; overflow: hidden; } /* 最近门店卡片特殊样式 */ .shop-card-nearest { border: 2rpx solid #E93B3D; box-shadow: 0 8rpx 24rpx rgba(233, 59, 61, 0.15); } /* ==================== 门店头部 ==================== */ .shop-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 24rpx; padding-right: 12rpx; } .shop-name-wrapper { display: flex; align-items: center; flex: 1; } .shop-icon { width: 32rpx; height: 38rpx; margin-right: 16rpx; } .shop-name { font-size: 32rpx; color: #333333; font-weight: 600; letter-spacing: 0.5rpx; line-height: 44rpx; } .shop-name-active { color: #E93B3D; } /* 距离显示 */ .distance-wrapper { display: flex; align-items: baseline; padding: 8rpx 16rpx; background: #f5f5f5; border-radius: 24rpx; margin-left: 16rpx; } .distance-active { background: linear-gradient(135deg, #FFE8E8 0%, #FFE0E0 100%); } .distance-num { font-size: 32rpx; font-weight: 600; color: #333333; letter-spacing: 0.5rpx; } .distance-active .distance-num { color: #E93B3D; } .distance-unit { font-size: 24rpx; color: #666666; margin-left: 4rpx; } .distance-active .distance-unit { color: #E93B3D; } /* ==================== 门店信息 ==================== */ .shop-info { background: #f9f9f9; border-radius: 12rpx; padding: 24rpx 20rpx; margin-bottom: 24rpx; } .info-item { display: flex; align-items: flex-start; margin-bottom: 20rpx; } .info-item:last-child { margin-bottom: 0; } .info-icon { width: 28rpx; height: 28rpx; margin-right: 16rpx; margin-top: 2rpx; flex-shrink: 0; } .info-text { flex: 1; font-size: 26rpx; color: #666666; line-height: 38rpx; letter-spacing: 0.3rpx; } /* ==================== 操作按钮 ==================== */ .shop-action { margin-top: 8rpx; } /* 进入门店按钮 */ .btn-enter-shop { width: 100%; height: 80rpx; background: linear-gradient(135deg, #E93B3D 0%, #F54749 100%); border-radius: 40rpx; border: none; display: flex; align-items: center; justify-content: center; box-shadow: 0 8rpx 20rpx rgba(233, 59, 61, 0.25); transition: all 0.3s ease; } .btn-enter-shop::after { border: none; } .btn-text { font-size: 30rpx; color: #ffffff; font-weight: 600; letter-spacing: 2rpx; } /* 选择门店按钮 */ .btn-select-shop { width: 100%; height: 80rpx; background: #ffffff; border: 2rpx solid #E93B3D; border-radius: 40rpx; display: flex; align-items: center; justify-content: center; position: relative; transition: all 0.3s ease; } .btn-select-text { font-size: 30rpx; color: #E93B3D; font-weight: 500; letter-spacing: 1rpx; } .btn-arrow { width: 20rpx; height: 20rpx; margin-left: 12rpx; } /* ==================== 响应式优化 ==================== */ @media (max-width: 375px) { .shop-name { font-size: 30rpx; } .distance-num { font-size: 28rpx; } .info-text { font-size: 24rpx; } } /* ==================== 动画效果 ==================== */ @keyframes fadeIn { from { opacity: 0; transform: translateY(20rpx); } to { opacity: 1; transform: translateY(0); } } .shop-card { animation: fadeIn 0.4s ease-out; } ================================================ FILE: pages/shop-cart/index.js ================================================ const WXAPI = require('apifm-wxapi') const TOOLS = require('../../utils/tools.js') const AUTH = require('../../utils/auth') const app = getApp() Page({ data: { shopCarType: 0, //0自营 1云货架 saveHidden: true, allSelect: true, delBtnWidth: 120, //删除按钮宽度单位(rpx) }, //获取元素自适应后的实际宽度 getEleWidth: function (w) { var real = 0; try { var res = wx.getSystemInfoSync().windowWidth var scale = (750 / 2) / (w / 2) // console.log(scale); real = Math.floor(res / scale); return real; } catch (e) { return false; // Do something when catch error } }, initEleWidth: function () { var delBtnWidth = this.getEleWidth(this.data.delBtnWidth); this.setData({ delBtnWidth: delBtnWidth }); }, onLoad: function () { this.initEleWidth(); this.onShow(); this.setData({ shopping_cart_vop_open: wx.getStorageSync('shopping_cart_vop_open') }) }, onShow: function () { this.shippingCarInfo() }, async shippingCarInfo() { const token = wx.getStorageSync('token') if (!token) { return } if (this.data.shopCarType == 0) { //自营购物车 var res = await WXAPI.shippingCarInfo(token) } else if (this.data.shopCarType == 1) { //云货架购物车 var res = await WXAPI.jdvopCartInfoV2(token) } if (res.code == 0) { if (this.data.shopCarType == 0) //自营商品 { res.data.items.forEach(ele => { if (!ele.stores || ele.status == 1) { ele.selected = false } }) } this.setData({ shippingCarInfo: res.data }) } else { this.setData({ shippingCarInfo: null }) } }, toIndexPage: function () { wx.switchTab({ url: "/pages/index/index" }); }, touchS: function (e) { if (e.touches.length == 1) { this.setData({ startX: e.touches[0].clientX }); } }, touchM: function (e) { const index = e.currentTarget.dataset.index; if (e.touches.length == 1) { var moveX = e.touches[0].clientX; var disX = this.data.startX - moveX; var delBtnWidth = this.data.delBtnWidth; var left = ""; if (disX == 0 || disX < 0) { //如果移动距离小于等于0,container位置不变 left = "margin-left:0px"; } else if (disX > 0) { //移动距离大于0,container left值等于手指移动距离 left = "margin-left:-" + disX + "px"; if (disX >= delBtnWidth) { left = "left:-" + delBtnWidth + "px"; } } this.data.shippingCarInfo.items[index].left = left this.setData({ shippingCarInfo: this.data.shippingCarInfo }) } }, touchE: function (e) { var index = e.currentTarget.dataset.index; if (e.changedTouches.length == 1) { var endX = e.changedTouches[0].clientX; var disX = this.data.startX - endX; var delBtnWidth = this.data.delBtnWidth; //如果距离小于删除按钮的1/2,不显示删除按钮 var left = disX > delBtnWidth / 2 ? "margin-left:-" + delBtnWidth + "px" : "margin-left:0px"; this.data.shippingCarInfo.items[index].left = left this.setData({ shippingCarInfo: this.data.shippingCarInfo }) } }, async delItem(e) { const key = e.currentTarget.dataset.key this.delItemDone(key) }, async delItemDone(key) { const token = wx.getStorageSync('token') if(this.data.shopCarType == 0){ var res = await WXAPI.shippingCarInfoRemoveItem(token, key) } if(this.data.shopCarType == 1){ var res = await WXAPI.jdvopCartRemoveV2(token, key) } if (res.code != 0 && res.code != 700) { wx.showToast({ title: res.msg, icon: 'none' }) } else { this.shippingCarInfo() TOOLS.showTabBarBadge() } }, async jiaBtnTap(e) { const index = e.currentTarget.dataset.index; const item = this.data.shippingCarInfo.items[index] const number = item.number + 1 const token = wx.getStorageSync('token') if(this.data.shopCarType == 0){ var res = await WXAPI.shippingCarInfoModifyNumber(token, item.key, number) } else if(this.data.shopCarType == 1){ var res = await WXAPI.jdvopCartModifyNumberV2(token, item.key, number) } this.shippingCarInfo() }, async jianBtnTap(e) { const index = e.currentTarget.dataset.index; const item = this.data.shippingCarInfo.items[index] const number = item.number - 1 if (number <= 0) { // 弹出删除确认 wx.showModal({ content: '确定要删除该商品吗?', success: (res) => { if (res.confirm) { this.delItemDone(item.key) } } }) return } const token = wx.getStorageSync('token') if(this.data.shopCarType == 0) { var res = await WXAPI.shippingCarInfoModifyNumber(token, item.key, number) } if(this.data.shopCarType == 1) { var res = await WXAPI.jdvopCartModifyNumberV2(token, item.key, number) } this.shippingCarInfo() }, changeCarNumber(e) { const key = e.currentTarget.dataset.key const num = e.detail.value const token = wx.getStorageSync('token') if(this.data.shopCarType == 0){ WXAPI.shippingCarInfoModifyNumber(token, key, num).then(res => { this.shippingCarInfo() })} else if(this.data.shopCarType == 1){ WXAPI.jdvopCartModifyNumberV2(token, key, num).then(res => { this.shippingCarInfo() }) } }, async radioClick(e) { var index = e.currentTarget.dataset.index; var item = this.data.shippingCarInfo.items[index] const token = wx.getStorageSync('token') if (this.data.shopCarType == 0) { //自营购物车 if (!item.stores || item.status == 1) { return } var res = await WXAPI.shippingCartSelected(token, item.key, !item.selected) } else if (this.data.shopCarType == 1) { //云货架购物车 var res = await WXAPI.jdvopCartSelectV2(token, item.key, !item.selected) } this.shippingCarInfo() }, onChange(event) { this.setData({ shopCarType: event.detail.name }) this.shippingCarInfo() }, goDetail(e) { const item = e.currentTarget.dataset.item wx.navigateTo({ url: '/pages/goods-details/index?id=' + item.goodsId, }) }, }) ================================================ FILE: pages/shop-cart/index.json ================================================ { "navigationBarTitleText": "购物车" } ================================================ FILE: pages/shop-cart/index.wxml ================================================ ================================================ FILE: pages/shop-cart/index.wxss ================================================ @import "../template-cart/template-cart.wxss"; page{ min-height: 100%; background-color: #F2f2f2; } .container { background-color: #F2f2f2; min-height: 100%; } .pos-fiexd{ position: fixed; bottom: 0; left: 0; } .vtabs{ width: 100vw; } ================================================ FILE: pages/sign/index.js ================================================ const WXAPI = require('apifm-wxapi') const AUTH = require('../../utils/auth') Page({ data: { minDate: new Date().getTime(), maxDate: new Date().getTime(), formatter(day) { return day; }, useFingerprintEmoji: false // 默认用图片,支持Unicode 16及以上的操作系统才用指纹emoji(🫆) }, onLoad: function(options) { this.scoreSignLogs() this.setData({ useFingerprintEmoji: this.shouldUseFingerprintEmoji() }); }, onShow: function() { AUTH.checkHasLogined().then(isLogined => { if (!isLogined) { AUTH.login(this) } }) }, async scoreSignLogs() { const res = await WXAPI.scoreSignLogs({ token: wx.getStorageSync('token') }) if (res.code == 0) { this.setData({ scoreSignLogs: res.data.result, formatter(day) { const _log = res.data.result.find(ele => { const year = day.date.getYear() + 1900 let month = day.date.getMonth() + 1 month = month + '' if (month.length == 1) { month = '0' + month } let date = day.date.getDate() + '' if (date.length == 1) { date = '0' + date } return ele.dateAdd.indexOf(`${year}-${month}-${date}`) == 0 }) if (_log) { day.bottomInfo = '已签到' } return day; } }) } }, async sign() { const res = await WXAPI.scoreSign(wx.getStorageSync('token')) if (res.code == 10000) { wx.showToast({ title: '签到成功', icon: 'success' }) this.scoreSignLogs() return } if (res.code != 0) { wx.showToast({ title: res.msg, icon: 'none' }) } else { wx.showToast({ title: '签到成功', icon: 'success' }) this.scoreSignLogs() } }, /* 简单版判断:满足 Win11-25H2 及以上 / Android16+ / iOS18.4+ 返回 true */ shouldUseFingerprintEmoji() { try { const info = wx.getDeviceInfo ? wx.getDeviceInfo() : wx.getSystemInfoSync(); const plat = (info.platform || '').toLowerCase(); const sys = info.system || ''; if (plat === 'android') { const m = sys.match(/Android\s+(\d+)/); return m ? (parseInt(m[1]) >= 16) : false; } if (plat === 'ios') { const m = sys.match(/iOS\s+(\d+)\.(\d+)/); if (!m) return false; const major = parseInt(m[1]); const minor = parseInt(m[2]); return major > 18 || (major === 18 && minor >= 4); } if (plat === 'windows' || plat === 'win32') { // 开发者工具里 platform 可能是 windows const m = sys.match(/Windows\s+(\d+)\s*H(\d+)/); if (!m) return false; const build = parseInt(m[1]); const h = parseInt(m[2]); return build >= 25 && h >= 2; // 25H2 及以上 } } catch (e) { /* 忽略错误,统一走图片 */ } return false; // 其余系统或解析失败都用 png } }) ================================================ FILE: pages/sign/index.json ================================================ { "navigationBarTitleText": "每日签到" } ================================================ FILE: pages/sign/index.wxml ================================================ 🫆 点击签到 ================================================ FILE: pages/sign/index.wxss ================================================ .todo-dot-bottom { color: red !important; } .zwqd-box { text-align: center; margin: auto; margin-top: 32rpx; } .zwqd-box image { width: 140rpx; height: 140rpx; margin: auto; } .zwqd-box view { margin-top: 16rpx; color: #999; font-size: 26rpx; } .emoji-icon { display: block; /* 同 image 默认 block */ width: 140rpx; height: 140rpx; margin: auto; font-size: 110rpx; /* 视觉上与 140rpx 图片接近,可自行微调 */ line-height: 140rpx; text-align: center; cursor: pointer; } ================================================ FILE: pages/start/start.js ================================================ const WXAPI = require('apifm-wxapi') const CONFIG = require('../../config.js') Page({ data: { swiperMaxNumber: 0, swiperCurrent: 0 }, onLoad(e){ // e.shopId = 6040 // 测试,测试完了注释掉 this.data.shopId = e.shopId this.readConfigVal() // 补偿写法 getApp().configLoadOK = () => { this.readConfigVal() } }, onShow:function(){ }, async readConfigVal() { const mallName = wx.getStorageSync('mallName') if (!mallName) { return } wx.setNavigationBarTitle({ title: wx.getStorageSync('mallName') }) let shopMod = wx.getStorageSync('shopMod') if (!shopMod) { shopMod = 0 } const app_show_pic_version = wx.getStorageSync('app_show_pic_version') if (app_show_pic_version && app_show_pic_version == CONFIG.version) { if (shopMod==1) { this.goShopSelectPage() } else { wx.switchTab({ url: '/pages/index/index', }) } } else { // 展示启动页 const res = await WXAPI.banners({ type: 'app' }) if (res.code == 700) { if (shopMod==1) { this.goShopSelectPage() } else { wx.switchTab({ url: '/pages/index/index', }) } } else { this.setData({ banners: res.data, swiperMaxNumber: res.data.length }); } } }, swiperchange: function (e) { //console.log(e.detail.current) this.setData({ swiperCurrent: e.detail.current }) }, goLeft() { if (this.data.swiperCurrent == 0) { this.setData({ swiperCurrent: this.data.swiperMaxNumber - 1 }) } else { this.setData({ swiperCurrent: this.data.swiperCurrent - 1 }) } }, goRight() { if (this.data.swiperCurrent == this.data.swiperMaxNumber - 1) { this.setData({ swiperCurrent: 0 }) } else { this.setData({ swiperCurrent: this.data.swiperCurrent + 1 }) } }, goToIndex: function (e) { let shopMod = wx.getStorageSync('shopMod') if (!shopMod) { shopMod = 0 } if (getApp().globalData.isConnected) { wx.setStorage({ key: 'app_show_pic_version', data: CONFIG.version }) if (shopMod == 1) { this.goShopSelectPage() } else { wx.switchTab({ url: '/pages/index/index', }); } } else { wx.showToast({ title: '当前无网络', icon: 'none', }) } }, async goShopSelectPage() { if (!this.data.shopId) { wx.redirectTo({ url: '/pages/shop/select' }) return } // 有传入门店ID const res = await WXAPI.shopSubdetail(this.data.shopId) if (res.code != 0) { wx.redirectTo({ url: '/pages/shop/select' }) return } wx.setStorageSync('shopInfo', res.data.info) wx.setStorageSync('shopIds', res.data.info.id) wx.switchTab({ url: '/pages/index/index' }) } }); ================================================ FILE: pages/start/start.json ================================================ { "navigationBarTitleText": "", "enablePullDownRefresh": false, "disableScroll": true, "navigationStyle": "custom" } ================================================ FILE: pages/start/start.wxml ================================================ 立即进入 精彩内容等你探索 加载中... ================================================ FILE: pages/start/start.wxss ================================================ /* 京东风格 - 启动页样式 */ /* 页面容器 */ page { width: 100vw; height: 100vh; overflow: hidden; background: #000; } /* 启动页主容器 */ .start-container { width: 100vw; height: 100vh; position: relative; overflow: hidden; } /* 轮播图容器 */ .swiper_box { width: 100vw; height: 100vh; } swiper-item { width: 100vw; height: 100vh; } /* 轮播项包装器 */ .swiper-item-wrapper { width: 100%; height: 100%; position: relative; } /* 轮播图片 */ .banner-image { width: 100vw; height: 100vh; display: block; } /* 图片渐变遮罩 - 京东风格 */ .image-mask { position: absolute; left: 0; bottom: 0; width: 100%; height: 50%; background: linear-gradient(to bottom, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.75)); z-index: 1; pointer-events: none; } /* 左右切换按钮样式 - 优雅半透明风格 */ .swiper-icon { position: absolute; top: 50%; transform: translateY(-50%); width: 80rpx; height: 80rpx; background: rgba(255, 255, 255, 0.15); border: 2rpx solid rgba(255, 255, 255, 0.3); border-radius: 50%; display: flex; align-items: center; justify-content: center; box-shadow: 0 8rpx 24rpx rgba(0, 0, 0, 0.15); backdrop-filter: blur(20rpx); z-index: 10; transition: all 0.3s ease; } .swiper-icon.left-icon { left: 40rpx; } .swiper-icon.right-icon { right: 40rpx; } .swiper-icon:active { transform: translateY(-50%) scale(0.9); background: rgba(255, 255, 255, 0.25); box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.2); } .swiper-icon image { width: 32rpx; height: 32rpx; filter: brightness(0) invert(1); } /* 指示器容器 */ .dots-wrapper { position: absolute; bottom: 260rpx; left: 0; width: 100%; display: flex; justify-content: center; z-index: 10; } .dots-container { display: flex; align-items: center; gap: 12rpx; padding: 12rpx 24rpx; background: rgba(0, 0, 0, 0.25); backdrop-filter: blur(10rpx); border-radius: 40rpx; } /* 指示器小点 */ .dot { width: 16rpx; height: 16rpx; border-radius: 50%; background: rgba(255, 255, 255, 0.4); transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); } /* 指示器激活状态 - 京东红色 */ .dot-active { width: 48rpx; height: 16rpx; border-radius: 8rpx; background: linear-gradient(90deg, #E93B3D, #FF6B6B); box-shadow: 0 4rpx 12rpx rgba(233, 59, 61, 0.4); } /* 底部按钮区域 */ .jump-btn-box { position: absolute; left: 0; bottom: calc(env(safe-area-inset-bottom) + 80rpx); width: 100vw; display: flex; flex-direction: column; align-items: center; z-index: 10; gap: 24rpx; } /* 进入按钮 - 京东风格 */ .jump-btn { position: relative; padding: 28rpx 120rpx; background: linear-gradient(135deg, #E93B3D 0%, #E61717 100%); border-radius: 60rpx; box-shadow: 0 12rpx 40rpx rgba(233, 59, 61, 0.45), 0 4rpx 12rpx rgba(0, 0, 0, 0.2); overflow: hidden; transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); } .jump-btn:active { transform: scale(0.96); box-shadow: 0 8rpx 28rpx rgba(233, 59, 61, 0.4), 0 2rpx 8rpx rgba(0, 0, 0, 0.2); } /* 按钮文字 */ .btn-text { position: relative; color: #FFFFFF; font-size: 32rpx; font-weight: 600; letter-spacing: 2rpx; z-index: 2; text-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.2); } /* 按钮光泽效果 */ .btn-shine { position: absolute; top: -50%; left: -100%; width: 100%; height: 200%; background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.3), transparent); transform: skewX(-25deg); animation: shine 3s infinite; } @keyframes shine { 0% { left: -100%; } 20% { left: 100%; } 100% { left: 100%; } } /* 提示文字 */ .skip-hint { color: rgba(255, 255, 255, 0.75); font-size: 24rpx; letter-spacing: 1rpx; text-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.3); animation: breath 2s ease-in-out infinite; } @keyframes breath { 0%, 100% { opacity: 0.75; } 50% { opacity: 1; } } /* 全屏加载效果样式 */ .loading-container { width: 100vw; height: 100vh; background: #000; display: flex; flex-direction: column; align-items: center; justify-content: center; position: relative; } /* 加载动画容器 */ .loading-spinner-wrapper { width: 120rpx; height: 120rpx; display: flex; align-items: center; justify-content: center; margin-bottom: 60rpx; } /* 旋转加载图标 */ .loading-spinner { width: 80rpx; height: 80rpx; border: 6rpx solid rgba(255, 255, 255, 0.1); border-top: 6rpx solid #E93B3D; border-radius: 50%; animation: loading-spin 1.5s linear infinite; } /* 加载文字 */ .loading-text { color: rgba(255, 255, 255, 0.8); font-size: 28rpx; font-weight: 400; letter-spacing: 2rpx; text-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.3); animation: loading-text-fade 2s ease-in-out infinite; } /* 加载图标旋转动画 */ @keyframes loading-spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } /* 加载文字淡化动画 */ @keyframes loading-text-fade { 0%, 100% { opacity: 0.6; } 50% { opacity: 1; } } ================================================ FILE: pages/template-cart/template-cart.js ================================================ ================================================ FILE: pages/template-cart/template-cart.wxml ================================================ ================================================ FILE: pages/template-cart/template-cart.wxss ================================================ .container { justify-content: initial; } .no-goods-icon { width: 382rpx; height: 323rpx; margin-top: 109rpx; } .title-box { width: 100vw; margin-top: 30rpx; text-align: center; font-size: 28rpx; color: #999; margin-bottom: 50rpx; } .to-index-btn { line-height: 60rpx; text-align: center; font-size: 28rpx; width: 140rpx; height: 60rpx; background: #FFD43E; border-radius: 30px; border: 2px solid #393640; } .list-top { width: 100%; height: 88rpx; line-height: 88rpx; box-sizing: border-box; display: flex; justify-content: space-between; padding: 0 30rpx; font-size: 28rpx; align-items: center; } .list-top .label { color: #000; } .list-top .edit-btn { color: #999; height: 100%; } .goodsList { width: 100%; padding-bottom: 110rpx; } .a-gooods { width: 725rpx; overflow: hidden; position: relative; margin-left: 18rpx; background-color: white; border-radius: 10rpx; margin-top: 10rpx; } .a-goods-conts { display: flex; justify-content: space-between; padding-left: 30rpx; width: 850rpx; box-sizing: border-box; transition: margin-left 0.2s ease-in-out; } .goods-info { display: flex; padding: 30rpx 0 30rpx 0; width: 720rpx; box-sizing: border-box; } .goods-info .img-box { width: 160rpx; height: 160rpx; overflow: hidden; margin-right: 20rpx; background-color: #d8d8d8; flex-shrink: 0; border-radius: 16rpx; } .goods-info .text-box { width: 440rpx; position: relative; } .goods-info .text-box .goods-title { width: 450rpx; font-size: 28rpx; color: #000; text-overflow: ellipsis; white-space: nowrap; overflow: hidden; padding: 10rpx 20rpx 5rpx 0; } .goods-info .text-box .goods-label { font-size: 26rpx; color: #999; height: 38rpx; line-height: 38rpx; margin: 8rpx 0 25rpx 0; text-overflow: ellipsis; white-space: nowrap; overflow: hidden; } .goods-info .text-box .goods-price { font-size: 26rpx; color: #e64340; } .goods-info .text-box .buy-num { width: 164rpx; height: 48rpx; line-height: 48rpx; position: absolute; right: 30rpx; bottom: 0; display: flex; /*justify-content: space-between;*/ font-size: 24rpx; text-align: center; } .goods-info .text-box .buy-num .jian-btn { width: 48rpx; height: 100%; background-color: #F2F3F5; border-radius: 6rpx; line-height: 46rpx; font-size: 18px; color: #323233; } .goods-info .text-box .buy-num .jian-btn.disabled { background-color: #f5f5f9; border-left: 1rpx solid #eee; border-bottom: 1rpx solid #eee; border-top: 1rpx solid #eee; color: #ccc; border-radius: 6rpx; line-height: 48rpx; font-size: 16px; color: #323233; } .goods-info .text-box .buy-num .jia-btn { width: 48rpx; height: 100%; border-radius: 6rpx; background-color: #F2F3F5; line-height: 48rpx; font-size: 16px; color: #323233; } .goods-info .text-box .buy-num .jia-btn.disabled { background-color: #f5f5f9; color: #ccc; border-radius: 6rpx; line-height: 48rpx; font-size: 16px; color: #323233; } .goods-info .text-box .buy-num input { width: 68rpx; height: 48rpx; min-height: 48rpx; text-align: center; font-size: 24rpx; } .goods-info .img-box .img { width: 160rpx; height: 160rpx; border-radius: 16rpx; } .a-goods-conts .delete-btn { width: 120rpx; line-height: 220rpx; text-align: center; background: #e64340; font-size: 24rpx; color: #fff; } .jiesuan-box { display: flex; justify-content: space-between; width: 100%; height: 100rpx; position: fixed; bottom: 0; left: 0; background-color: #FAFAFA; z-index: 999; } .jiesuan-box .to-pay-btn { text-align: center; line-height: 76rpx; width: 200rpx; height: 76rpx; background: linear-gradient(270deg, #FF972A 0%, #FF444A 100%); border-radius: 38rpx; margin-top: 12rpx; margin-right: 20rpx; color: white; } .jiesuan-box .to-pay-btn.no-select { background-color: #ccc; } .jiesuan-box .left-price { display: flex; width: 510rpx; justify-content: space-between; line-height: 100rpx; padding: 0 30rpx 0 32rpx; font-size: 28rpx; box-sizing: border-box; } .jiesuan-box .total { color: #e64340; } .trip { background: #e64340; padding: 8rpx 32rpx; color: #fff; width: 686rpx; font-size: 24rpx; } .del-icon { position: absolute; right: 0rpx; top: 12rpx; width: 50rpx; height: 50rpx; } .vw100 { width: 700rpx !important; font-size: 24rpx !important; } .radio-box { display: flex; justify-content: center; align-items: center; padding: 8rpx; } ================================================ FILE: pages/test/wifi.js ================================================ Page({ data: { test: '

1893年
奥斯曼大街上诞生了一间70平米的商铺。在128年间,它发展成为一家7万平方米的大型百货商场。它就是巴黎老佛爷奥斯曼旗舰店。

' }, onLoad(options) { }, onShow() { }, }) ================================================ FILE: pages/test/wifi.json ================================================ { "usingComponents": {} } ================================================ FILE: pages/test/wifi.wxml ================================================ ================================================ FILE: pages/test/wifi.wxss ================================================ /* pages/test/wifi.wxss */ ================================================ FILE: pages/to-pay-order/index.js ================================================ const CONFIG = require('../../config.js') const WXAPI = require('apifm-wxapi') const AUTH = require('../../utils/auth') Date.prototype.format = function(format) { var date = { "M+": this.getMonth() + 1, "d+": this.getDate(), "h+": this.getHours(), "m+": this.getMinutes(), "s+": this.getSeconds(), "q+": Math.floor((this.getMonth() + 3) / 3), "S+": this.getMilliseconds() }; if (/(y+)/i.test(format)) { format = format.replace(RegExp.$1, (this.getFullYear() + '').substr(4 - RegExp.$1.length)); } for (var k in date) { if (new RegExp("(" + k + ")").test(format)) { format = format.replace(RegExp.$1, RegExp.$1.length == 1 ? date[k] : ("00" + date[k]).substr(("" + date[k]).length)); } } return format; } Page({ data: { totalScoreToPay: 0, goodsList: [], isNeedLogistics: 0, // 是否需要物流信息 yunPrice: 0, amountLogistics2: 0, allGoodsAndYunPrice: 0, goodsJsonStr: "", orderType: "", //订单类型,购物车下单或立即支付下单,默认是购物车, buyNow 说明是立即购买 pingtuanOpenId: undefined, //拼团的话记录团号 hasNoCoupons: true, coupons: [], couponAmount: 0, //优惠券金额 curCoupon: null, // 当前选择使用的优惠券 curCouponShowText: '请选择使用优惠券', // 当前选择使用的优惠券 peisongType: 'kd', // 配送方式 kd,zq 分别表示快递/到店自取 remark: '', shopIndex: -1, pageIsEnd: false, bindMobileStatus: 0, // 0 未判断 1 已绑定手机号码 2 未绑定手机号码 userScore: 0, // 用户可用积分 deductionScore: '-1', // 本次交易抵扣的积分数, -1 为不抵扣,0 为自动抵扣,其他金额为抵扣多少积分 shopCarType: 0, //0自营购物车,1云货架购物车 dyopen: 0, // 是否开启订阅 dyunit: 0, // 按天 dyduration: 1, // 订阅间隔 dytimes: 1, // 订阅次数 dateStart: undefined, // 订阅首次扣费时间 minDate: new Date().getTime(), maxDate: new Date(2030, 10, 1).getTime(), currentDate: new Date().getTime(), formatter: (type, value) => { if (type === 'year') { return `${value}年`; } if (type === 'month') { return `${value}月`; } if (type === 'day') { return `${value}日`; } if (type === 'hour') { return `${value}点`; } if (type === 'minute') { return `${value}分`; } return value; }, cardId: '0', // 使用的次卡ID // 优惠券选择弹窗相关 couponPickerShow: false, couponPickerShopShow: false, currentShopIndex: -1, currentShopCoupons: [], currentShopSelectedCoupon: null, // 口令兑换相关 exchangeCouponShow: false, exchangeNumber: '', exchangePwd: '' }, onShow() { if (this.data.pageIsEnd) { return } this.doneShow() }, async doneShow() { let goodsList = [] let shopList = [] const token = wx.getStorageSync('token') //立即购买下单 if ("buyNow" == this.data.orderType) { var buyNowInfoMem = wx.getStorageSync('buyNowInfo'); this.data.kjId = buyNowInfoMem.kjId; if (buyNowInfoMem && buyNowInfoMem.shopList) { goodsList = buyNowInfoMem.shopList } } else { //购物车下单 if (this.data.shopCarType == 0) {//自营购物车 var res = await WXAPI.shippingCarInfo(token) shopList = res.data.shopList } else if (this.data.shopCarType == 1) {//云货架购物车 var res = await WXAPI.jdvopCartInfoV2(token) shopList = [{ id: 0, name: '其他', hasNoCoupons: true, serviceDistance: 99999999 }] } if (res.code == 0) { goodsList = res.data.items.filter(ele => { return ele.selected }) const shopIds = [] goodsList.forEach(ele => { if (this.data.shopCarType == 1) { ele.shopId = 0 } shopIds.push(ele.shopId) }) shopList = shopList.filter(ele => { return shopIds.includes(ele.id) }) } } shopList.forEach(ele => { ele.hasNoCoupons = true }) const extRequired = []; // 必填项 if (this.data.create_order_ext) { const _create_order_ext = JSON.parse(this.data.create_order_ext) goodsList.forEach(g => { Object.keys(_create_order_ext).forEach(k => { if (k.split(',').includes(g.goodsId + '')) { console.log(1212, _create_order_ext[k]); _create_order_ext[k].split(',').forEach(v => { if (!extRequired.includes(v)) { extRequired.push(v) } }) } }) }) } this.setData({ shopList, goodsList, peisongType: this.data.peisongType, extRequired }); this.initShippingAddress() this.userAmount() }, onLoad(e) { const nowDate = new Date(); let _data = { isNeedLogistics: 1, dateStart: nowDate.format('yyyy-MM-dd h:m:s'), orderPeriod_open: wx.getStorageSync('orderPeriod_open'), order_pay_user_balance: wx.getStorageSync('order_pay_user_balance'), zt_open_hx: wx.getStorageSync('zt_open_hx'), create_order_ext: wx.getStorageSync('create_order_ext'), needBindMobile: wx.getStorageSync('needBindMobile'), } if (e.orderType) { _data.orderType = e.orderType } if (e.pingtuanOpenId) { _data.pingtuanOpenId = e.pingtuanOpenId } if (e.shopCarType) { _data.shopCarType = e.shopCarType } this.setData(_data) this.getUserApiInfo() this.cardMyList() }, async userAmount() { const res = await WXAPI.userAmount(wx.getStorageSync('token')) const order_pay_user_balance = wx.getStorageSync('order_pay_user_balance') if (res.code == 0) { this.setData({ balance: order_pay_user_balance == '1' ? res.data.balance : 0, userScore: res.data.score }) } }, getDistrictId: function (obj, aaa) { if (!obj) { return ""; } if (!aaa) { return ""; } return aaa; }, remarkChange(e) { this.data.remark = e.detail.value }, async goCreateOrder() { this.setData({ btnLoading: true }) // 检测实名认证状态 if (wx.getStorageSync('needIdCheck') == 1) { const res = await WXAPI.userDetail(wx.getStorageSync('token')) if (res.code == 0 && !res.data.base.isIdcardCheck) { wx.navigateTo({ url: '/pages/idCheck/index', }) this.setData({ btnLoading: false }) return } } const subscribe_ids = wx.getStorageSync('subscribe_ids') if (subscribe_ids) { wx.requestSubscribeMessage({ tmplIds: subscribe_ids.split(','), success(res) { console.log(res) }, fail(e) { console.error(e) }, complete: (e) => { this.createOrder(true) }, }) } else { this.createOrder(true) } }, async createOrder(e) { // shopCarType: 0 //0自营购物车,1云货架购物车 const loginToken = wx.getStorageSync('token') // 用户登录 token const postData = { token: loginToken, goodsJsonStr: this.data.goodsJsonStr, remark: this.data.remark, peisongType: this.data.peisongType, goodsType: this.data.shopCarType, cardId: this.data.cardId, } if (this.data.deductionScore != '-1') { postData.deductionScore = this.data.deductionScore } if (this.data.cardId == '0') { postData.cardId = '' } if (this.data.dyopen == 1) { const orderPeriod = { unit: this.data.dyunit, duration: this.data.dyduration, dateStart: this.data.dateStart, times: this.data.dytimes, autoPay: true } postData.orderPeriod = JSON.stringify(orderPeriod) } if (this.data.kjId) { postData.kjid = this.data.kjId } if (this.data.pingtuanOpenId) { postData.pingtuanOpenId = this.data.pingtuanOpenId } if (postData.peisongType == 'kd' && this.data.curAddressData && this.data.curAddressData.provinceId) { postData.provinceId = this.data.curAddressData.provinceId; } if (postData.peisongType == 'kd' && this.data.curAddressData && this.data.curAddressData.cityId) { postData.cityId = this.data.curAddressData.cityId; } if (postData.peisongType == 'kd' && this.data.curAddressData && this.data.curAddressData.districtId) { postData.districtId = this.data.curAddressData.districtId; } if (postData.peisongType == 'kd' && this.data.curAddressData && this.data.curAddressData.streetId) { postData.streetId = this.data.curAddressData.streetId; } if (this.data.shopCarType == 1) { // vop 需要地址来计算运费 postData.address = this.data.curAddressData.address; postData.linkMan = this.data.curAddressData.linkMan; postData.mobile = this.data.curAddressData.mobile; postData.code = this.data.curAddressData.code; } if (e && this.data.isNeedLogistics > 0 && postData.peisongType == 'kd') { if (!this.data.curAddressData) { wx.hideLoading(); wx.showToast({ title: '请设置收货地址', icon: 'none' }) this.setData({ btnLoading: false }) return; } if (postData.peisongType == 'kd') { postData.address = this.data.curAddressData.address; postData.linkMan = this.data.curAddressData.linkMan; postData.mobile = this.data.curAddressData.mobile; postData.code = this.data.curAddressData.code; } } if (this.data.curCoupon) { postData.couponId = this.data.curCoupon.id; } if (!e) { postData.calculate = "true"; } else { if (postData.peisongType == 'zq' && this.data.shops && this.data.shopIndex == -1) { wx.showToast({ title: '请选择自提门店', icon: 'none' }) this.setData({ btnLoading: false }) return; } const extJsonStr = {} if (this.data.extRequired && this.data.extRequired.length > 0) { const extRequiredMap = this.data.extRequiredMap if (!extRequiredMap) { wx.showToast({ title: '请填写必填项', icon: 'none' }) this.setData({ btnLoading: false }) return; } this.data.extRequired.forEach(k => { if (!extRequiredMap[k]) { wx.showToast({ title: '请填写' + k, icon: 'none' }) this.setData({ btnLoading: false }) return; } extJsonStr[k] = extRequiredMap[k] }) } if (postData.peisongType == 'zq') { if (!this.data.name) { wx.showToast({ title: '请填写联系人', icon: 'none' }) this.setData({ btnLoading: false }) return; } if (!this.data.mobile) { wx.showToast({ title: '请填写联系电话', icon: 'none' }) this.setData({ btnLoading: false }) return; } extJsonStr['联系人'] = this.data.name extJsonStr['联系电话'] = this.data.mobile postData.isCanHx = this.data.zt_open_hx == '1' ? true : false } if (postData.peisongType == 'zq' && this.data.shops) { postData.shopIdZt = this.data.shops[this.data.shopIndex].id postData.shopNameZt = this.data.shops[this.data.shopIndex].name } postData.extJsonStr = JSON.stringify(extJsonStr) } const shopList = this.data.shopList let totalRes = { code: 0, msg: 'success', data: { score: 0, amountReal: 0, orderIds: [] } } if (shopList && shopList.length > 1) { // 多门店的商品下单 let totalScoreToPay = 0 let isNeedLogistics = false let allGoodsAndYunPrice = 0 let yunPrice = 0 let amountLogistics2 = 0 let deductionMoney = 0 let couponAmount = 0 let goodsAdditionalPriceMap = {} for (let index = 0; index < shopList.length; index++) { const curShop = shopList[index] console.log(curShop); postData.filterShopId = curShop.id if (curShop.curCoupon) { postData.couponId = curShop.curCoupon.id } else { postData.couponId = '' } const res = await WXAPI.orderCreate(postData) this.data.pageIsEnd = true if (res.code != 0) { this.data.pageIsEnd = false wx.showModal({ title: '错误', content: res.msg, showCancel: false }) this.setData({ btnLoading: false }) return; } totalRes.data.score += res.data.score totalRes.data.amountReal += res.data.amountReal totalRes.data.orderIds.push(res.data.id) console.log('e:', e); if (!e) { curShop.hasNoCoupons = true console.log(curShop); if (res.data.couponUserList) { curShop.hasNoCoupons = false res.data.couponUserList.forEach(ele => { let moneyUnit = '元' if (ele.moneyType == 1) { moneyUnit = '%' } if (ele.moneyHreshold) { ele.nameExt = ele.name + ' [面值' + ele.money + moneyUnit + ',满' + ele.moneyHreshold + '元可用]' } else { ele.nameExt = ele.name + ' [面值' + ele.money + moneyUnit + ']' } }) curShop.curCouponShowText = '请选择使用优惠券' curShop.coupons = res.data.couponUserList if (res.data.couponId && res.data.couponId.length > 0) { curShop.curCoupon = curShop.coupons.find(ele => { return ele.id == res.data.couponId[0] }) curShop.curCouponShowText = curShop.curCoupon.nameExt } } shopList.splice(index, 1, curShop) // 计算积分抵扣规则 userScore let scoreDeductionRules = res.data.scoreDeductionRules if (scoreDeductionRules) { // 如果可叠加,计算可抵扣的最大积分数 scoreDeductionRules.forEach(ele => { if (ele.loop) { let loopTimes = Math.floor(this.data.userScore / ele.score) // 按剩余积分取最大 let loopTimesMax = Math.floor((res.data.amountTotle + res.data.deductionMoney) / ele.money) // 按金额取最大 if (loopTimes > loopTimesMax) { loopTimes = loopTimesMax } ele.score = ele.score * loopTimes ele.money = ele.money * loopTimes } }) // 剔除积分数为0的情况 scoreDeductionRules = scoreDeductionRules.filter(ele => { return ele.score > 0 }) curShop.scoreDeductionRules = scoreDeductionRules shopList.splice(index, 1, curShop) } totalScoreToPay += res.data.score if (res.data.isNeedLogistics) { isNeedLogistics = true } allGoodsAndYunPrice += res.data.amountReal yunPrice += res.data.amountLogistics amountLogistics2 += res.data.amountLogistics2 || 0 deductionMoney += res.data.deductionMoney couponAmount += res.data.couponAmount goodsAdditionalPriceMap = Object.assign(goodsAdditionalPriceMap, res.data.goodsAdditionalPriceMap) } } this.setData({ shopList, totalScoreToPay, isNeedLogistics, allGoodsAndYunPrice, goodsAdditionalPriceMap, yunPrice, amountLogistics2, hasNoCoupons: true, deductionMoney, couponAmount }); } else { // 单门店单商品下单 if (shopList && shopList.length == 1) { if (shopList[0].curCoupon) { postData.couponId = shopList[0].curCoupon.id } else { postData.couponId = '' } } const res = await WXAPI.orderCreate(postData) this.data.pageIsEnd = true if (res.code != 0) { this.data.pageIsEnd = false wx.showModal({ title: '错误', content: res.msg, showCancel: false }) this.setData({ btnLoading: false }) return; } totalRes = res if (!e) { let hasNoCoupons = true let coupons = null if (res.data.couponUserList) { hasNoCoupons = false res.data.couponUserList.forEach(ele => { let moneyUnit = '元' if (ele.moneyType == 1) { moneyUnit = '%' } if (ele.moneyHreshold) { ele.nameExt = ele.name + ' [面值' + ele.money + moneyUnit + ',满' + ele.moneyHreshold + '元可用]' } else { ele.nameExt = ele.name + ' [面值' + ele.money + moneyUnit + ']' } }) coupons = res.data.couponUserList if (shopList && shopList.length == 1 && !hasNoCoupons) { hasNoCoupons = true const curShop = shopList[0] curShop.hasNoCoupons = false curShop.curCouponShowText = '请选择使用优惠券' curShop.coupons = res.data.couponUserList if (res.data.couponId && res.data.couponId.length > 0) { curShop.curCoupon = curShop.coupons.find(ele => { return ele.id == res.data.couponId[0] }) curShop.curCouponShowText = curShop.curCoupon.nameExt } shopList[0] = curShop } } // 计算积分抵扣规则 userScore let scoreDeductionRules = res.data.scoreDeductionRules if (scoreDeductionRules) { // 如果可叠加,计算可抵扣的最大积分数 scoreDeductionRules.forEach(ele => { if (ele.loop) { let loopTimes = Math.floor(this.data.userScore / ele.score) // 按剩余积分取最大 let loopTimesMax = Math.floor((res.data.amountTotle + res.data.deductionMoney) / ele.money) // 按金额取最大 if (loopTimes > loopTimesMax) { loopTimes = loopTimesMax } ele.score = ele.score * loopTimes ele.money = ele.money * loopTimes } }) // 剔除积分数为0的情况 scoreDeductionRules = scoreDeductionRules.filter(ele => { return ele.score > 0 }) } this.setData({ shopList, totalScoreToPay: res.data.score, isNeedLogistics: res.data.isNeedLogistics, allGoodsAndYunPrice: res.data.amountReal, goodsAdditionalPriceMap: res.data.goodsAdditionalPriceMap, yunPrice: res.data.amountLogistics, amountLogistics2: res.data.amountLogistics2, hasNoCoupons, coupons, deductionMoney: res.data.deductionMoney, couponAmount: res.data.couponAmount, scoreDeductionRules }) } } if (!e) { this.data.pageIsEnd = false return } if (e && "buyNow" != this.data.orderType) { // 清空购物车数据 const keyArrays = [] this.data.goodsList.forEach(ele => { keyArrays.push(ele.key) }) if (this.data.shopCarType == 0) { //自营购物车 WXAPI.shippingCarInfoRemoveItem(loginToken, keyArrays.join()) } else if (this.data.shopCarType == 1) {//云货架购物车 WXAPI.jdvopCartRemoveV2(loginToken, keyArrays.join()) } } this.processAfterCreateOrder(totalRes) }, async processAfterCreateOrder(res) { this.setData({ btnLoading: false }) if (res.data.status != 0) { wx.redirectTo({ url: "/pages/order-list/index" }) return } let orderId = '' if (res.data.orderIds && res.data.orderIds.length > 0) { orderId = res.data.orderIds.join() } else { orderId = res.data.id } // 直接弹出支付,取消支付的话,去订单列表 await this.userAmount() const balance = this.data.balance const userScore = this.data.userScore if (userScore < res.data.score) { wx.showModal({ title: '提示', content: '您当前可用积分不足,请稍后前往订单管理进行支付', showCancel: false, success: res2 => { wx.redirectTo({ url: "/pages/order-list/index" }) } }) return } if (balance || res.data.amountReal * 1 == 0) { // 有余额 const money = (res.data.amountReal * 1 - balance * 1).toFixed(2) if (money <= 0) { // 余额足够 wx.showModal({ title: '请确认支付', content: `您当前可用余额¥${balance},使用余额支付¥${res.data.amountReal}?`, confirmText: "确认支付", cancelText: "暂不付款", success: res2 => { if (res2.confirm) { // 使用余额支付 WXAPI.orderPay(wx.getStorageSync('token'), orderId).then(res3 => { if (res3.code != 0) { wx.showToast({ title: res3.msg, icon: 'none' }) return } wx.redirectTo({ url: "/pages/order-list/index" }) }) } else { wx.redirectTo({ url: "/pages/order-list/index" }) } } }) } else { // 余额不够 wx.showModal({ title: '请确认支付', content: `您当前可用余额¥${balance},仍需支付¥${money}`, confirmText: "确认支付", cancelText: "暂不付款", success: res2 => { if (res2.confirm) { // 使用余额支付 this.setData({ orderId, money, paymentShow: true, nextAction: { type: 0, id: orderId } }) } else { wx.redirectTo({ url: "/pages/order-list/index" }) } } }) } } else { // 没余额 this.setData({ orderId, money: res.data.amountReal, paymentShow: true, nextAction: { type: 0, id: orderId } }) } }, async initShippingAddress() { const res = await WXAPI.defaultAddress(wx.getStorageSync('token')) if (res.code == 0) { this.setData({ curAddressData: res.data.info }); } else { this.setData({ curAddressData: null }); } this.processYunfei(); }, processYunfei() { var goodsList = this.data.goodsList if (goodsList.length == 0) { return } const goodsJsonStr = [] var isNeedLogistics = 0; let inviter_id = 0; let inviter_id_storge = wx.getStorageSync('referrer'); if (inviter_id_storge) { inviter_id = inviter_id_storge; } for (let i = 0; i < goodsList.length; i++) { let carShopBean = goodsList[i]; if (carShopBean.logistics || carShopBean.logisticsId) { isNeedLogistics = 1; } const _goodsJsonStr = { propertyChildIds: carShopBean.propertyChildIds } if (carShopBean.sku && carShopBean.sku.length > 0) { let propertyChildIds = '' carShopBean.sku.forEach(option => { propertyChildIds = propertyChildIds + ',' + option.optionId + ':' + option.optionValueId }) _goodsJsonStr.propertyChildIds = propertyChildIds } if (carShopBean.additions && carShopBean.additions.length > 0) { let goodsAdditionList = [] carShopBean.additions.forEach(option => { goodsAdditionList.push({ pid: option.pid, id: option.id }) }) _goodsJsonStr.goodsAdditionList = goodsAdditionList } _goodsJsonStr.goodsId = carShopBean.goodsId _goodsJsonStr.number = carShopBean.number _goodsJsonStr.logisticsType = 0 _goodsJsonStr.inviter_id = inviter_id goodsJsonStr.push(_goodsJsonStr) } if (this.data.shopCarType == 1) { // vop 商品必须快递 isNeedLogistics = 1 } this.setData({ isNeedLogistics: isNeedLogistics, goodsJsonStr: JSON.stringify(goodsJsonStr) }); this.createOrder(); }, addAddress: function () { wx.navigateTo({ url: "/pages/address-add/index" }) }, selectAddress: function () { wx.navigateTo({ url: "/pages/select-address/index" }) }, bindChangeCoupon: function (e) { const selIndex = e.detail.value; this.setData({ curCoupon: this.data.coupons[selIndex], curCouponShowText: this.data.coupons[selIndex].nameExt }); this.processYunfei() }, bindChangeCouponShop: function (e) { const selIndex = e.detail.value; const shopIndex = e.currentTarget.dataset.sidx const shopList = this.data.shopList const curshop = shopList[shopIndex] curshop.curCoupon = curshop.coupons[selIndex] curshop.curCouponShowText = curshop.coupons[selIndex].nameExt shopList.splice(shopIndex, 1, curshop) this.setData({ shopList }); this.processYunfei() }, radioChange(e) { this.setData({ peisongType: e.detail.value }) this.processYunfei() if (e.detail.value == 'zq') { this.fetchShops() } }, dyChange(e) { this.setData({ dyopen: e.detail.value }) }, dyunitChange(e) { this.setData({ dyunit: e.detail.value }) }, cancelLogin() { wx.navigateBack() }, async fetchShops() { const res = await WXAPI.fetchShops() if (res.code == 0) { let shopIndex = this.data.shopIndex const shopInfo = wx.getStorageSync('shopInfo') if (shopInfo) { shopIndex = res.data.findIndex(ele => { return ele.id == shopInfo.id }) } this.setData({ shops: res.data, shopIndex }) } }, shopSelect(e) { this.setData({ shopIndex: e.detail.value }) }, goMap() { const _this = this const shop = this.data.shops[this.data.shopIndex] const latitude = shop.latitude const longitude = shop.longitude wx.openLocation({ latitude, longitude, scale: 18 }) }, callMobile() { const shop = this.data.shops[this.data.shopIndex] wx.makePhoneCall({ phoneNumber: shop.linkPhone, }) }, async getUserApiInfo() { const res = await WXAPI.userDetail(wx.getStorageSync('token')) if (res.code == 0) { let bindMobileStatus = res.data.base.mobile ? 1 : 2 // 账户绑定的手机号码状态 if (this.data.needBindMobile != 1) { bindMobileStatus = 1 } this.setData({ bindMobileStatus, mobile: res.data.base.mobile, name: res.data.base.nick, }) } }, bindMobile() { this.setData({ bindMobileShow: true }) }, bindMobileOk(e) { console.log(e.detail); // 这里是组件里data的数据 this.setData({ bindMobileShow: false, mobile: e.detail.mobile, bindMobileStatus: 1 }) }, bindMobileCancel() { this.setData({ bindMobileShow: false }) }, deductionScoreChange(event) { this.setData({ deductionScore: event.detail, }) this.processYunfei() }, deductionScoreClick(event) { const { name } = event.currentTarget.dataset; this.setData({ deductionScore: name, }) this.processYunfei() }, cardChange(event) { this.setData({ cardId: event.detail, }) this.processYunfei() }, cardClick(event) { const { name } = event.currentTarget.dataset; this.setData({ cardId: name, }) this.processYunfei() }, dateStartclick(e) { this.setData({ dateStartpop: true }) }, dateStartconfirm(e) { const d = new Date(e.detail) this.setData({ dateStart: d.format('yyyy-MM-dd h:m:s'), dateStartpop: false }) console.log(e); }, dateStartcancel(e) { this.setData({ dateStartpop: false }) }, async cardMyList() { const res = await WXAPI.cardMyList(wx.getStorageSync('token')) if (res.code == 0) { const myCards = res.data.filter(ele => { return ele.status == 0 && ele.amount > 0 && ele.cardInfo.refs }) if (myCards.length > 0) { this.setData({ myCards: res.data }) } } }, paymentOk(e) { console.log(e.detail); // 这里是组件里data的数据 this.setData({ paymentShow: false }) wx.redirectTo({ url: '/pages/order-list/index', }) }, paymentCancel() { this.setData({ paymentShow: false }) }, extRequiredChange(e) { let extRequiredMap = this.data.extRequiredMap if (!extRequiredMap) { extRequiredMap = {} } extRequiredMap[e.target.dataset.name] = e.detail console.log(extRequiredMap); this.setData({ extRequiredMap }) }, // 显示优惠券选择弹窗 showCouponPicker() { this.setData({ couponPickerShow: true }) }, // 关闭优惠券选择弹窗 closeCouponPicker() { this.setData({ couponPickerShow: false }) }, // 选择优惠券 selectCoupon(e) { const index = e.currentTarget.dataset.index const selectedCoupon = this.data.coupons[index] this.setData({ curCoupon: selectedCoupon, curCouponShowText: selectedCoupon.nameExt, couponPickerShow: false }) this.processYunfei() }, // 选择不使用优惠券 selectNoCoupon() { this.setData({ curCoupon: null, curCouponShowText: '请选择使用优惠券', couponPickerShow: false }) this.processYunfei() }, // 显示门店优惠券选择弹窗 showCouponPickerShop(e) { const shopIndex = e.currentTarget.dataset.sidx const shopList = this.data.shopList const currentShop = shopList[shopIndex] this.setData({ currentShopIndex: shopIndex, currentShopCoupons: currentShop.coupons || [], currentShopSelectedCoupon: currentShop.curCoupon || null, couponPickerShopShow: true }) }, // 关闭门店优惠券选择弹窗 closeCouponPickerShop() { this.setData({ couponPickerShopShow: false }) }, // 选择门店优惠券 selectCouponShop(e) { const index = e.currentTarget.dataset.index const selectedCoupon = this.data.currentShopCoupons[index] const shopIndex = this.data.currentShopIndex const shopList = this.data.shopList const curshop = shopList[shopIndex] curshop.curCoupon = selectedCoupon curshop.curCouponShowText = selectedCoupon.nameExt shopList.splice(shopIndex, 1, curshop) this.setData({ shopList, couponPickerShopShow: false }) this.processYunfei() }, // 选择不使用门店优惠券 selectNoCouponShop() { const shopIndex = this.data.currentShopIndex const shopList = this.data.shopList const curshop = shopList[shopIndex] curshop.curCoupon = null curshop.curCouponShowText = '请选择使用优惠券' shopList.splice(shopIndex, 1, curshop) this.setData({ shopList, couponPickerShopShow: false }) this.processYunfei() }, // 显示口令兑换弹窗 showExchangeCoupon() { this.setData({ exchangeCouponShow: true, exchangeNumber: '', exchangePwd: '' }) }, // 关闭口令兑换弹窗 closeExchangeCoupon() { this.setData({ exchangeCouponShow: false }) }, // 确认兑换优惠券 async confirmExchangeCoupon() { if (!this.data.exchangeNumber) { wx.showToast({ title: '请输入券号', icon: 'none' }) return } if (!this.data.exchangePwd) { wx.showToast({ title: '请输入密码', icon: 'none' }) return } wx.showLoading({ title: '兑换中...', }) const res = await WXAPI.exchangeCoupons( wx.getStorageSync('token'), this.data.exchangeNumber, this.data.exchangePwd ) wx.hideLoading() if (res.code != 0) { wx.showToast({ title: res.msg, icon: 'none' }) } else { wx.showToast({ title: '兑换成功', icon: 'success' }) this.setData({ exchangeCouponShow: false }) // 重新加载优惠券列表 this.processYunfei() } }, }) ================================================ FILE: pages/to-pay-order/index.json ================================================ { "navigationBarTitleText": "确认订单" } ================================================ FILE: pages/to-pay-order/index.wxml ================================================ 请先登录 为了保障您的交易安全和订单信息准确 接收订单物流信息 保障账户资金安全 提供专属售后服务 🔒 您的信息将被加密保护,绝不泄露给第三方 {{item.label}} {{option.optionName}}:{{option.optionValueName}} {{option.pname}}:{{option.name}} {{item.label}} {{option.optionName}}:{{option.optionValueName}} {{option.pname}}:{{option.name}} 自动获取 备注 {{ dyunit == 0 ? '天': '' }} {{ dyunit == 1 ? '月': '' }} {{ dyunit == 2 ? '年': '' }} 💰 没有优惠券?点击使用口令兑换 选择优惠券 ¥ {{ item.moneyType == 0 ? item.money : item.money }} 满{{item.moneyHreshold}}元 {{item.name}} {{item.nameExt}} 不使用优惠券 选择优惠券 ¥ {{ item.moneyType == 0 ? item.money : item.money }} 满{{item.moneyHreshold}}元 {{item.name}} {{item.nameExt}} 不使用优惠券 口令兑换优惠券 输入券号和密码即可兑换 取消 立即兑换 ================================================ FILE: pages/to-pay-order/index.wxss ================================================ page,view,image,input,textarea { display: block; box-sizing: border-box; } page { background-color: #f2f2f2; padding-bottom: 48rpx; } .address-box { width: 100vw; margin: 20rpx 0; border-bottom: 1rpx solid #eee; } .add-address { width: 100vw; display: flex; align-items: center; padding-left: 32rpx; } .add-address image { width: 40rpx; height: 40rpx; } .add-address view { margin-left: 16rpx; font-size: 28rpx; color: #000; padding: 40rpx 0; } .show-address { width: 750rpx; box-sizing: border-box; padding: 0 32rpx; display: flex; justify-content: space-between; align-items: center; } .show-address .name-tel { font-size: 28rpx; color: #000; padding: 30rpx 0 20rpx 0; } .show-address .addr-text { font-size: 24rpx; color: #888; padding-bottom: 34rpx; line-height: 36rpx; } .show-address .next { width: 40rpx; height: 40rpx; } form { width: 100%; } .goods-list { width: 100%; background-color: #fff; margin-bottom: 20rpx; } .goods-list .list-title { font-size: 28rpx; color: #000; padding: 30rpx 0 25rpx 30rpx; } .goods-list .a-goods { width: 720rpx; margin-left: 30rpx; display: flex; /*justify-content: space-between;*/ border-top: 1px solid #eee; padding: 30rpx 30rpx 30rpx 0; } .goods-list .a-goods .img-box { width: 160rpx; height: 160rpx; overflow: hidden; margin-right: 20rpx; background-color: #d8d8d8; } .goods-list .img-box .img { width: 160rpx; height: 160rpx; } .goods-list .a-goods .text-box { width: 510rpx; box-sizing: border-box; padding-top: 10rpx; } .a-goods .text-box .arow { display: flex; justify-content: space-between; align-items: center; } .a-goods .text-box .arow .goods-name { width: 360rpx; font-size: 26rpx; height: 74rpx; color: #000; line-height: 1.6; overflow: hidden; } .a-goods .text-box .arow01 { margin-bottom: 30rpx; } .a-goods .text-box .arow .goods-price { font-size: 26rpx; color: #000; align-self: flex-start; } .a-goods .text-box .arow .goods-label { font-size: 26rpx; color: #999; } .a-goods .text-box .arow .goods-num { font-size: 26rpx; color: #999; } .peisong-way { width: 100%; background-color: #fff; margin-bottom: 20rpx; } .peisong-way .row-box { width: 720rpx; display: flex; justify-content: space-between; align-items: center; box-sizing: border-box; padding: 24rpx 0 24rpx 30rpx; border-bottom: 1rpx solid #eee; } .peisong-way .row-label.t { color: #333; } .peisong-way .row-label { font-size: 28rpx; color: #666; } .peisong-way .right-text { font-size: 28rpx; color: #666; padding-right: 30rpx; } .peisong-way .liuyan { width: 510rpx; font-size: 28rpx; } .goods-info { width: 100%; background-color: #fff; margin-bottom: 120rpx; padding-bottom: 24rpx; } .goods-info .row-box { width: 100%; display: flex; justify-content: space-between; align-items: center; box-sizing: border-box; padding: 24rpx 30rpx 12rpx 30rpx; font-size: 28rpx; color: #000; } .goods-info .row-box .right-text { text-align: right; } .row-box .next { width: 40rpx; height: 40rpx; } .jiesuan-box { display: flex; justify-content: space-between; width: 100%; height: 100rpx; position: fixed; bottom: calc(env(safe-area-inset-bottom) / 2); left: 0; border-top: 1px solid #eee; background-color: #fff; z-index: 999; } .jiesuan-box .to-pay-btn { width: 250rpx; text-align: center; height: 100%; line-height: 100rpx; background-color: #e64340; font-size: 32rpx; color: #fff; border-radius: 0; } .jiesuan-box .left-price { display: flex; width: 500rpx; justify-content: flex-end; line-height: 100rpx; padding: 0 30rpx 0 0; font-size: 28rpx; box-sizing: border-box; } .jiesuan-box .total { color: #e64340; text-align: right; } .box-v2 { width: 100vw; } .bottom-box { height: 120rpx; } .cell-group { margin-top: 16rpx; } /* 绑定手机号容器 */ .bind-mobile-container { min-height: 100vh; background: linear-gradient(135deg, #f5f5f5 0%, #e8e8e8 100%); display: flex; align-items: center; justify-content: center; padding: 40rpx; box-sizing: border-box; } /* 卡片主体 */ .bind-mobile-card { width: 100%; max-width: 670rpx; background: #ffffff; border-radius: 24rpx; box-shadow: 0 8rpx 40rpx rgba(0, 0, 0, 0.08); padding: 80rpx 48rpx 60rpx; box-sizing: border-box; position: relative; overflow: hidden; } .bind-mobile-card::before { content: ''; position: absolute; top: 0; left: 0; right: 0; height: 6rpx; background: linear-gradient(90deg, #e93b3d 0%, #e2231a 100%); } /* 图标区域 */ .card-icon { display: flex; justify-content: center; margin-bottom: 40rpx; } .icon-shield { width: 120rpx; height: 140rpx; background: linear-gradient(135deg, #e93b3d 0%, #e2231a 100%); border-radius: 60rpx 60rpx 20rpx 20rpx; position: relative; display: flex; align-items: center; justify-content: center; box-shadow: 0 8rpx 24rpx rgba(233, 59, 61, 0.3); } .shield-inner { width: 56rpx; height: 66rpx; border: 6rpx solid #ffffff; border-radius: 28rpx 28rpx 10rpx 10rpx; position: relative; } .shield-inner::after { content: ''; position: absolute; top: 24rpx; left: 50%; transform: translateX(-50%); width: 12rpx; height: 24rpx; border: 4rpx solid #ffffff; border-top: none; border-left: none; transform: translateX(-50%) rotate(45deg); margin-top: -8rpx; } /* 标题区域 */ .card-title { font-size: 44rpx; font-weight: bold; color: #333333; text-align: center; margin-bottom: 20rpx; letter-spacing: 1rpx; } .card-subtitle { font-size: 28rpx; color: #666666; text-align: center; line-height: 44rpx; margin-bottom: 60rpx; padding: 0 20rpx; } /* 功能列表 */ .feature-list { background: #f8f8f8; border-radius: 16rpx; padding: 32rpx 40rpx; margin-bottom: 60rpx; } .feature-item { display: flex; align-items: center; margin-bottom: 24rpx; } .feature-item:last-child { margin-bottom: 0; } .feature-dot { width: 12rpx; height: 12rpx; background: linear-gradient(135deg, #e93b3d 0%, #e2231a 100%); border-radius: 50%; margin-right: 20rpx; flex-shrink: 0; } .feature-text { font-size: 28rpx; color: #666666; line-height: 40rpx; } /* 按钮区域 */ .bind-btn-wrapper { margin-bottom: 40rpx; } .bind-btn { width: 100%; height: 96rpx; background: linear-gradient(90deg, #e93b3d 0%, #e2231a 100%); border-radius: 48rpx; border: none; display: flex; align-items: center; justify-content: center; box-shadow: 0 8rpx 24rpx rgba(233, 59, 61, 0.3); transition: all 0.3s; position: relative; overflow: hidden; } .bind-btn::after { border: none; } .bind-btn::before { content: ''; position: absolute; top: 0; left: -100%; width: 100%; height: 100%; background: rgba(255, 255, 255, 0.2); transition: left 0.5s; } .bind-btn:active { transform: scale(0.98); box-shadow: 0 4rpx 16rpx rgba(233, 59, 61, 0.4); } .bind-btn-text { font-size: 32rpx; color: #ffffff; font-weight: bold; letter-spacing: 2rpx; } /* 安全提示 */ .security-tips { display: flex; align-items: center; justify-content: center; padding: 24rpx; background: #fff9f0; border-radius: 12rpx; border: 1rpx solid #ffe5cc; } .tips-icon { font-size: 28rpx; margin-right: 12rpx; } .tips-text { font-size: 24rpx; color: #999999; line-height: 34rpx; } /* 优惠券选择器 */ .coupon-selector { display: flex; align-items: center; justify-content: space-between; padding: 32rpx; background: linear-gradient(135deg, #FFF5F5 0%, #FFFFFF 100%); border-radius: 16rpx; margin: 24rpx 0; box-shadow: 0 4rpx 20rpx rgba(228, 57, 60, 0.08); transition: all 0.3s ease; position: relative; overflow: hidden; } .coupon-selector::before { content: ''; position: absolute; top: 0; left: 0; width: 6rpx; height: 100%; background: linear-gradient(180deg, #E4393C 0%, #F75050 100%); } .coupon-selector:active { transform: scale(0.98); box-shadow: 0 2rpx 12rpx rgba(228, 57, 60, 0.12); } .coupon-selector-left { display: flex; align-items: center; flex: 1; } .coupon-icon { font-size: 48rpx; margin-right: 24rpx; } .coupon-text-wrapper { flex: 1; } .coupon-label { font-size: 24rpx; color: #999999; margin-bottom: 8rpx; } .coupon-selected-text { font-size: 28rpx; color: #333333; font-weight: 600; } .coupon-selector-right { display: flex; align-items: center; } .coupon-arrow { font-size: 48rpx; color: #CCCCCC; font-weight: 300; } /* 口令兑换提示 */ .coupon-exchange-tip { display: flex; align-items: center; padding: 24rpx 32rpx; background: linear-gradient(135deg, #FFF9F0 0%, #FFFFFF 100%); border-radius: 16rpx; margin: 24rpx 0; border: 2rpx dashed #FFD700; transition: all 0.3s ease; } .coupon-exchange-tip:active { transform: scale(0.98); background: linear-gradient(135deg, #FFF4E0 0%, #FFFAF0 100%); } .tip-icon { font-size: 40rpx; margin-right: 20rpx; } .tip-text { flex: 1; font-size: 26rpx; color: #FF9500; font-weight: 500; } .tip-arrow { font-size: 40rpx; color: #FFD700; font-weight: 300; } /* 优惠券选择弹窗 */ .coupon-picker-container { background: #FFFFFF; border-radius: 24rpx 24rpx 0 0; max-height: 80vh; display: flex; flex-direction: column; } .coupon-picker-header { display: flex; align-items: center; justify-content: space-between; padding: 32rpx 40rpx; border-bottom: 1rpx solid #F0F0F0; position: relative; } .coupon-picker-header::after { content: ''; position: absolute; bottom: 0; left: 50%; transform: translateX(-50%); width: 80rpx; height: 6rpx; background: linear-gradient(90deg, #E4393C 0%, #F75050 100%); border-radius: 3rpx; } .picker-title { font-size: 36rpx; font-weight: 700; color: #333333; } .picker-close { font-size: 48rpx; color: #999999; font-weight: 300; width: 60rpx; height: 60rpx; display: flex; align-items: center; justify-content: center; border-radius: 50%; transition: all 0.3s ease; } .picker-close:active { background: #F5F5F5; } .coupon-picker-list { box-sizing: border-box; flex: 1; padding: 24rpx; max-height: 60vh; } .coupon-picker-item { margin-bottom: 24rpx; } .picker-coupon-card { position: relative; display: flex; align-items: center; padding: 32rpx; background: linear-gradient(135deg, #FFF5F5 0%, #FFFFFF 100%); border-radius: 16rpx; border: 2rpx solid #F0F0F0; transition: all 0.3s ease; } .picker-coupon-card.selected { border-color: #E4393C; background: linear-gradient(135deg, #FFF0F0 0%, #FFFFFF 100%); box-shadow: 0 8rpx 24rpx rgba(228, 57, 60, 0.15); } .picker-coupon-card:active { transform: scale(0.98); } .picker-coupon-left { display: flex; flex-direction: column; align-items: center; justify-content: center; min-width: 160rpx; padding-right: 32rpx; border-right: 2rpx dashed #E5E5E5; } .picker-amount-wrapper { display: flex; align-items: baseline; margin-bottom: 8rpx; } .picker-currency { font-size: 28rpx; color: #E4393C; font-weight: 600; margin-right: 4rpx; } .picker-amount { font-size: 56rpx; color: #E4393C; font-weight: 700; line-height: 1; } .picker-percent { font-size: 32rpx; color: #E4393C; font-weight: 600; margin-left: 4rpx; } .picker-threshold { font-size: 22rpx; color: #999999; } .picker-coupon-right { flex: 1; padding-left: 32rpx; } .picker-coupon-name { font-size: 30rpx; color: #333333; font-weight: 600; margin-bottom: 12rpx; line-height: 1.4; } .picker-coupon-desc { font-size: 24rpx; color: #999999; line-height: 1.5; } .picker-check-icon { position: absolute; top: 16rpx; right: 16rpx; width: 48rpx; height: 48rpx; background: linear-gradient(135deg, #E4393C 0%, #F75050 100%); border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 28rpx; color: #FFFFFF; font-weight: 700; } .picker-coupon-card.no-coupon { justify-content: center; background: #F7F8FA; border: 2rpx dashed #E5E5E5; } .picker-coupon-card.no-coupon.selected { background: linear-gradient(135deg, #FFF0F0 0%, #FFFFFF 100%); border-color: #E4393C; } .no-coupon-text { font-size: 28rpx; color: #666666; font-weight: 500; } /* 口令兑换弹窗 */ .exchange-coupon-container { width: 600rpx; background: #FFFFFF; border-radius: 24rpx; overflow: hidden; } .exchange-header { padding: 48rpx 40rpx 32rpx; background: linear-gradient(180deg, #FFF5F5 0%, #FFFFFF 100%); text-align: center; position: relative; } .exchange-header::after { content: ''; position: absolute; bottom: 0; left: 50%; transform: translateX(-50%); width: 80rpx; height: 6rpx; background: linear-gradient(90deg, #E4393C 0%, #F75050 100%); border-radius: 3rpx; } .exchange-title { font-size: 36rpx; font-weight: 700; color: #333333; margin-bottom: 12rpx; } .exchange-subtitle { font-size: 24rpx; color: #999999; } .exchange-form { padding: 40rpx 40rpx 24rpx; } .exchange-actions { display: flex; padding: 0 40rpx 40rpx; gap: 24rpx; } .exchange-btn { flex: 1; height: 88rpx; display: flex; align-items: center; justify-content: center; border-radius: 44rpx; font-size: 32rpx; font-weight: 600; transition: all 0.3s ease; } .exchange-btn.cancel { background: #F7F8FA; color: #666666; } .exchange-btn.cancel:active { background: #E5E5E5; } .exchange-btn.confirm { background: linear-gradient(135deg, #E4393C 0%, #F75050 100%); color: #FFFFFF; box-shadow: 0 8rpx 20rpx rgba(228, 57, 60, 0.3); } .exchange-btn.confirm:active { transform: scale(0.98); box-shadow: 0 4rpx 12rpx rgba(228, 57, 60, 0.4); } ================================================ FILE: pages/vip/detail.js ================================================ const WXAPI = require('apifm-wxapi') const AUTH = require('../../utils/auth') Page({ data: { levelId: 0, levelDetail: null, extJsonKeys: [], priceList: [], selectedPrice: null, userBalance: 0, paymentShow: false, money: 0, nextAction: null, successShow: false, successBenefits: [] }, onLoad(options) { if (options.id) { this.setData({ levelId: options.id }) this.loadData() } }, async loadData() { wx.showLoading({ title: '加载中...' }) await Promise.all([ this.getLevelDetail(), this.getPriceList(), this.getUserBalance() ]) wx.hideLoading() }, async getLevelDetail() { const res = await WXAPI.userLevelDetail(this.data.levelId) if (res.code === 0) { const extJsonKeys = [] if (res.data.extJson && typeof res.data.extJson === 'object') { Object.keys(res.data.extJson).forEach(key => { extJsonKeys.push({ key: key, value: res.data.extJson[key] }) }) } this.setData({ levelDetail: res.data, extJsonKeys }) } else { wx.showToast({ title: res.msg || '加载失败', icon: 'none' }) setTimeout(() => { wx.navigateBack() }, 1500) } }, async getPriceList() { const res = await WXAPI.userLevelPrices(this.data.levelId) if (res.code === 0) { const list = res.data || [] if (list.length === 0) { wx.showToast({ title: '该等级暂无可购买项目', icon: 'none' }) } this.setData({ priceList: list, selectedPrice: list.length > 0 ? list[0] : null }) } }, async getUserBalance() { const res = await WXAPI.userAmountV2(wx.getStorageSync('token')) if (res.code === 0) { this.setData({ userBalance: res.data.balance || 0 }) } }, selectPrice(e) { const { item } = e.currentTarget.dataset this.setData({ selectedPrice: item }) }, async handleBuy() { if (!this.data.selectedPrice) { wx.showToast({ title: '请选择购买时长', icon: 'none' }) return } const price = this.data.selectedPrice.price const balance = this.data.userBalance if (balance >= price) { // 余额充足,使用余额购买 this.buyWithBalance() } else { // 余额不足,使用在线支付 this.buyWithOnlinePay(price, balance) } }, buyWithBalance() { const price = this.data.selectedPrice.price const balance = this.data.userBalance wx.showModal({ title: '确认购买', content: `当前余额:¥${balance}\n需支付:¥${price}\n确认使用余额购买?`, confirmText: '确认购买', success: async (res) => { if (res.confirm) { wx.showLoading({ title: '购买中...' }) const result = await WXAPI.userLevelBuy( wx.getStorageSync('token'), this.data.selectedPrice.id, false ) wx.hideLoading() if (result.code === 0) { this.showSuccessModal() } else { wx.showToast({ title: result.msg || '购买失败', icon: 'none' }) } } } }) }, buyWithOnlinePay(price, balance) { const needPay = (price - balance).toFixed(2) wx.showModal({ title: '余额不足', content: `当前余额:¥${balance}\n需支付:¥${price}\n还需支付:¥${needPay}\n是否继续支付?`, confirmText: '去支付', success: (res) => { if (res.confirm) { // 拉起支付组件 this.setData({ money: needPay, paymentShow: true, nextAction: { type: 6, userLevelPriceId: this.data.selectedPrice.id, isAutoRenew: false } }) } } }) }, showSuccessModal() { const benefits = [] const info = this.data.levelDetail.info if (info.rebate < 10) { benefits.push(`${info.rebate}折优惠`) } if (info.upgradeSendScore > 0) { benefits.push(`赠送${info.upgradeSendScore}积分`) } if (info.sendPerMonthScore > 0) { benefits.push(`每月${info.sendPerMonthScore}积分`) } if (info.sendPerMonthCoupons) { benefits.push('专享优惠券') } this.setData({ successShow: true, successBenefits: benefits }) }, handleSuccessConfirm() { this.setData({ successShow: false }) wx.navigateBack() }, paymentOk(e) { console.log('支付成功', e.detail) this.setData({ paymentShow: false }) this.showSuccessModal() }, paymentCancel() { this.setData({ paymentShow: false }) } }) ================================================ FILE: pages/vip/detail.json ================================================ { "navigationBarTitleText": "会员等级详情", "usingComponents": { "vip-success": "/components/vip-success/index" } } ================================================ FILE: pages/vip/detail.wxml ================================================ {{levelDetail.info.name}} LV{{levelDetail.info.level}} 会员权益 购物折扣 {{levelDetail.info.rebate}}折 升级赠送 {{levelDetail.info.upgradeSendScore}}积分 每月赠送 {{levelDetail.info.sendPerMonthScore}}积分 专享优惠券 每月赠送 更多权益 {{item.key}} {{item.value}} 选择购买时长 {{item.duration}} {{item.unitStr}} ¥ {{item.price}} 当前等级暂不开放升级 需支付 ¥{{selectedPrice ? selectedPrice.price : 0}} 立即升级 ================================================ FILE: pages/vip/detail.wxss ================================================ .detail-container { min-height: 100vh; background: #f8f9fa; padding-bottom: 140rpx; } .level-header { position: relative; height: 500rpx; overflow: hidden; } .header-bg { position: absolute; top: 0; left: 0; right: 0; height: 100%; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); } .header-bg::before { content: ''; position: absolute; top: -30%; left: -20%; width: 600rpx; height: 600rpx; background: rgba(255, 255, 255, 0.1); border-radius: 50%; } .header-bg::after { content: ''; position: absolute; bottom: -30%; right: -20%; width: 500rpx; height: 500rpx; background: rgba(255, 255, 255, 0.08); border-radius: 50%; } .header-content { position: relative; z-index: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; height: 100%; gap: 20rpx; } .level-badge-large { width: 160rpx; height: 160rpx; background: rgba(255, 255, 255, 0.2); border-radius: 50%; display: flex; align-items: center; justify-content: center; backdrop-filter: blur(10rpx); border: 6rpx solid rgba(255, 255, 255, 0.3); box-shadow: 0 8rpx 32rpx rgba(0, 0, 0, 0.1); } .badge-icon { width: 80rpx; height: 80rpx; } .level-name { font-size: 48rpx; font-weight: bold; color: #ffffff; text-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.2); } .level-desc { font-size: 28rpx; color: rgba(255, 255, 255, 0.9); } .benefits-section, .ext-section, .price-section { margin: 30rpx; background: #ffffff; border-radius: 24rpx; padding: 32rpx; box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.06); } .section-title { font-size: 32rpx; font-weight: bold; color: #333; margin-bottom: 24rpx; } .benefits-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 20rpx; } .benefit-card { display: flex; flex-direction: column; align-items: center; padding: 32rpx 20rpx; background: linear-gradient(135deg, #f5f7ff 0%, #ffffff 100%); border-radius: 16rpx; border: 2rpx solid #e8ecff; } .benefit-icon { margin-bottom: 16rpx; } .benefit-title { font-size: 24rpx; color: #999; margin-bottom: 8rpx; } .benefit-value { font-size: 28rpx; font-weight: bold; color: #667eea; } .ext-list { display: flex; flex-direction: column; gap: 20rpx; } .ext-item { display: flex; justify-content: space-between; align-items: center; padding: 24rpx; background: #f8f9fa; border-radius: 12rpx; } .ext-label { font-size: 28rpx; color: #666; } .ext-value { font-size: 28rpx; color: #333; font-weight: 500; } .price-list { display: flex; flex-direction: column; gap: 20rpx; } .price-item { position: relative; display: flex; justify-content: space-between; align-items: center; padding: 32rpx; background: #f8f9fa; border-radius: 16rpx; border: 3rpx solid transparent; transition: all 0.3s; } .price-item.active { background: linear-gradient(135deg, #f5f7ff 0%, #ffffff 100%); border-color: #667eea; } .price-duration { display: flex; align-items: baseline; gap: 8rpx; } .duration-num { font-size: 40rpx; font-weight: bold; color: #333; } .duration-unit { font-size: 24rpx; color: #999; } .price-amount { display: flex; align-items: baseline; gap: 4rpx; } .price-symbol { font-size: 24rpx; color: #ff6b35; } .price-num { font-size: 40rpx; font-weight: bold; color: #ff6b35; padding-right: 48rpx; } .price-check { position: absolute; top: 32rpx; right: 16rpx; width: 40rpx; height: 40rpx; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); border-radius: 50%; display: flex; align-items: center; justify-content: center; } .bottom-bar { position: fixed; bottom: 0; left: 0; right: 0; display: flex; align-items: center; justify-content: space-between; padding: 20rpx 30rpx; background: #ffffff; box-shadow: 0 -4rpx 20rpx rgba(0, 0, 0, 0.06); z-index: 100; } .price-info { display: flex; flex-direction: column; gap: 4rpx; } .price-label { font-size: 24rpx; color: #999; } .price-total { font-size: 40rpx; font-weight: bold; color: #ff6b35; } .buy-btn { padding: 24rpx 80rpx; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: #ffffff; font-size: 32rpx; font-weight: bold; border-radius: 48rpx; box-shadow: 0 8rpx 24rpx rgba(102, 126, 234, 0.4); } .empty-price { display: flex; flex-direction: column; align-items: center; gap: 16rpx; padding: 60rpx 0; } .empty-price .empty-text { font-size: 28rpx; color: #999; } ================================================ FILE: pages/vip/history.js ================================================ const WXAPI = require('apifm-wxapi') const AUTH = require('../../utils/auth') Page({ data: { recordList: [], page: 1, pageSize: 20, totalPage: 0, loading: false, hasMore: true, levelMap: {} }, onLoad(options) { this.loadData() }, async loadData() { this.setData({ page: 1, recordList: [], hasMore: true }) await this.loadLevelList() await this.loadRecords() }, async loadLevelList() { const res = await WXAPI.userLevelList({ page: 1, pageSize: 100 }) if (res.code === 0) { const levelMap = {} const list = res.data.result || [] list.forEach(item => { levelMap[item.id] = item.name }) this.setData({ levelMap }) } }, async loadRecords() { if (this.data.loading) return this.setData({ loading: true }) const res = await WXAPI.userLevelBuyLogs({ token: wx.getStorageSync('token'), page: this.data.page, pageSize: this.data.pageSize }) this.setData({ loading: false }) if (res.code === 0) { const list = res.data.result || [] // 添加等级名称 list.forEach(item => { item.levelName = this.data.levelMap[item.levelId] || '未知等级' }) const allRecords = [...this.data.recordList, ...list] this.setData({ recordList: allRecords, totalPage: res.data.totalPage || 0, hasMore: this.data.page < res.data.totalPage }) } else { wx.showToast({ title: res.msg || '加载失败', icon: 'none' }) } }, loadMore() { if (!this.data.hasMore || this.data.loading) return this.setData({ page: this.data.page + 1 }) this.loadRecords() }, onPullDownRefresh() { this.data.page = 1 this.data.totalPage = 0 this.loadData().then(() => { wx.stopPullDownRefresh() }) }, onReachBottom() { this.loadMore() } }) ================================================ FILE: pages/vip/history.json ================================================ { "navigationBarTitleText": "购买记录", "enablePullDownRefresh": true } ================================================ FILE: pages/vip/history.wxml ================================================ {{item.levelName}} ¥ {{item.money}} 订单号 {{item.orderNumber}} 购买时间 {{item.dateAdd}} 备注 {{item.remark}} 暂无购买记录~ 加载中... 加载更多 没有更多了 ================================================ FILE: pages/vip/history.wxss ================================================ .history-container { min-height: 100vh; background: #f8f9fa; padding-bottom: 40rpx; } .stats-card { margin: 30rpx; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); border-radius: 24rpx; padding: 40rpx; display: flex; align-items: center; justify-content: space-around; box-shadow: 0 8rpx 32rpx rgba(102, 126, 234, 0.3); } .stats-item { display: flex; flex-direction: column; align-items: center; gap: 12rpx; } .stats-label { font-size: 24rpx; color: rgba(255, 255, 255, 0.8); } .stats-value { font-size: 40rpx; font-weight: bold; color: #ffffff; } .stats-divider { width: 2rpx; height: 60rpx; background: rgba(255, 255, 255, 0.3); } .record-list { padding: 30rpx; } .record-item { background: #ffffff; border-radius: 20rpx; padding: 32rpx; margin-bottom: 24rpx; box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.06); } .record-header { display: flex; justify-content: space-between; align-items: center; padding-bottom: 24rpx; border-bottom: 2rpx solid #f0f0f0; margin-bottom: 24rpx; } .level-info { display: flex; align-items: center; gap: 12rpx; } .level-icon { width: 48rpx; height: 48rpx; background: linear-gradient(135deg, #f5f7ff 0%, #e8ecff 100%); border-radius: 50%; display: flex; align-items: center; justify-content: center; } .level-name { font-size: 32rpx; font-weight: bold; color: #333; } .record-amount { display: flex; align-items: baseline; gap: 4rpx; } .amount-symbol { font-size: 24rpx; color: #ff6b35; } .amount-num { font-size: 36rpx; font-weight: bold; color: #ff6b35; } .record-body { display: flex; flex-direction: column; gap: 16rpx; } .record-info-item { display: flex; justify-content: space-between; align-items: center; } .info-label { font-size: 26rpx; color: #999; } .info-value { font-size: 26rpx; color: #666; max-width: 400rpx; text-align: right; word-break: break-all; } .empty-wrap { display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 120rpx 0; } .empty-img { width: 300rpx; height: 300rpx; margin-bottom: 32rpx; } .empty-text { font-size: 28rpx; color: #999; } .loading-wrap { display: flex; justify-content: center; align-items: center; padding: 60rpx 0; } .loadmore-wrap { display: flex; justify-content: center; padding: 40rpx 0; } .loadmore-text { font-size: 28rpx; color: #667eea; padding: 16rpx 48rpx; background: #f5f7ff; border-radius: 40rpx; } .no-more { text-align: center; padding: 40rpx 0; font-size: 24rpx; color: #999; } ================================================ FILE: pages/vip/index.js ================================================ const WXAPI = require('apifm-wxapi') const AUTH = require('../../utils/auth') Page({ data: { userLevel: null, levelList: [], loading: true }, onLoad(options) { }, onShow() { AUTH.checkHasLogined().then(isLogined => { if (!isLogined) { AUTH.login(this) } else { this.loadData() } }) }, async loadData() { this.setData({ loading: true }) await Promise.all([ this.getUserLevel(), this.getLevelList() ]) this.setData({ loading: false }) }, async getUserLevel() { const res = await WXAPI.userDetail(wx.getStorageSync('token')) if (res.code === 0) { this.setData({ userLevel: res.data.userLevel }) } }, async getLevelList() { const res = await WXAPI.userLevelList({ page: 1, pageSize: 50 }) if (res.code === 0) { const list = res.data.result || [] // 按等级排序 list.sort((a, b) => b.level - a.level) this.setData({ levelList: list }) } }, goLevelDetail(e) { const { id } = e.currentTarget.dataset wx.navigateTo({ url: `/pages/vip/detail?id=${id}` }) }, goBuyHistory() { wx.navigateTo({ url: '/pages/vip/history' }) }, onPullDownRefresh() { this.loadData().then(() => { wx.stopPullDownRefresh() }) } }) ================================================ FILE: pages/vip/index.json ================================================ { "navigationBarTitleText": "会员权益", "enablePullDownRefresh": true } ================================================ FILE: pages/vip/index.wxml ================================================ {{userLevel.name}} 当前等级 普通会员 升级享更多权益 购买记录 会员等级 选择适合您的会员等级 {{item.name}} 当前 LV{{item.level}} {{item.rebate}}折优惠 升级送{{item.upgradeSendScore}}积分 每月送{{item.sendPerMonthScore}}积分 每月赠送专享优惠券 查看详情 暂无会员等级 加载中... ================================================ FILE: pages/vip/index.wxss ================================================ .vip-container { min-height: 100vh; background: linear-gradient(180deg, #f8f9fa 0%, #ffffff 100%); padding-bottom: 40rpx; } .vip-header { position: relative; } .header-bg { position: absolute; top: 0; left: 0; right: 0; height: 100%; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); } .header-bg::after { content: ''; position: absolute; top: -50%; right: -20%; width: 500rpx; height: 500rpx; background: rgba(255, 255, 255, 0.1); border-radius: 50%; } .header-content { position: relative; z-index: 1; padding: 60rpx 40rpx; display: flex; justify-content: space-between; align-items: center; } .current-level { display: flex; align-items: center; gap: 24rpx; } .level-badge { width: 120rpx; height: 120rpx; background: rgba(255, 255, 255, 0.2); border-radius: 50%; display: flex; align-items: center; justify-content: center; backdrop-filter: blur(10rpx); border: 4rpx solid rgba(255, 255, 255, 0.3); } .badge-icon { width: 60rpx; height: 60rpx; } .level-info { display: flex; flex-direction: column; gap: 8rpx; } .level-name { font-size: 40rpx; font-weight: bold; color: #ffffff; text-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1); } .level-desc { font-size: 24rpx; color: rgba(255, 255, 255, 0.9); } .history-btn { display: flex; align-items: center; gap: 8rpx; padding: 16rpx 24rpx; background: rgba(255, 255, 255, 0.2); border-radius: 40rpx; backdrop-filter: blur(10rpx); border: 2rpx solid rgba(255, 255, 255, 0.3); font-size: 24rpx; color: #ffffff; } .level-list { margin-top: 32rpx; padding: 0 30rpx; } .section-title { text-align: center; margin-bottom: 40rpx; } .title-text { display: block; font-size: 36rpx; font-weight: bold; color: #333; margin-bottom: 12rpx; } .title-desc { font-size: 24rpx; color: #999; } .level-cards { display: flex; flex-direction: column; gap: 24rpx; } .level-card { background: #ffffff; border-radius: 24rpx; padding: 32rpx; box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.06); transition: all 0.3s; border: 2rpx solid transparent; } .level-card:active { transform: scale(0.98); } .level-card.current { border-color: #667eea; background: linear-gradient(135deg, #f5f7ff 0%, #ffffff 100%); box-shadow: 0 8rpx 32rpx rgba(102, 126, 234, 0.2); } .card-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 24rpx; padding-bottom: 24rpx; border-bottom: 2rpx solid #f0f0f0; } .level-title { display: flex; align-items: center; gap: 16rpx; } .level-title .name { font-size: 32rpx; font-weight: bold; color: #333; } .current-tag { padding: 4rpx 16rpx; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: #ffffff; font-size: 20rpx; border-radius: 20rpx; } .level-badge-small { width: 80rpx; height: 80rpx; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); border-radius: 50%; display: flex; align-items: center; justify-content: center; } .level-num { font-size: 24rpx; font-weight: bold; color: #ffffff; } .card-benefits { display: flex; flex-direction: column; gap: 16rpx; margin-bottom: 24rpx; } .benefit-item { display: flex; align-items: center; gap: 12rpx; font-size: 26rpx; color: #666; } .card-footer { display: flex; align-items: center; justify-content: flex-end; gap: 8rpx; padding-top: 16rpx; border-top: 2rpx solid #f0f0f0; } .view-detail { font-size: 24rpx; color: #999; } .loading-wrap { display: flex; justify-content: center; align-items: center; padding: 80rpx 0; } .empty-wrap { display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 120rpx 0; } .empty-img { width: 300rpx; height: 300rpx; margin-bottom: 32rpx; } .empty-text { font-size: 28rpx; color: #999; } ================================================ FILE: pages/withdraw/index.js ================================================ const WXAPI = require('apifm-wxapi') const AUTH = require('../../utils/auth') Page({ /** * 页面的初始数据 */ data: { balance: 0.00 }, /** * 生命周期函数--监听页面加载 */ onLoad: function(options) { this.setData({ balance_pay_pwd: wx.getStorageSync('balance_pay_pwd') }) }, onShow: function() { AUTH.checkHasLogined().then(isLogined => { if (!isLogined) { AUTH.login(this) } else { this.userAmount() } }) }, async userAmount() { const res = await WXAPI.userAmount(wx.getStorageSync('token')) if (res.code === 0) { this.setData({ balance: res.data.balance }) } }, async bindSave() { let minWidthAmount = wx.getStorageSync('WITHDRAW_MIN'); if (!minWidthAmount) { minWidthAmount = 0 } const amount = this.data.amount; if (!amount) { wx.showToast({ title: '请填写正确的提现金额', icon: 'none', }) return } if (this.data.balance_pay_pwd == '1' && !this.data.pwd) { wx.showToast({ title: '请输入交易密码', icon: 'none' }) return } if (amount * 1 < minWidthAmount) { wx.showToast({ title: '提现金额不能低于' + minWidthAmount, icon: 'none', }) return } if (amount * 1 > 2000) { if (!this.data.name) { wx.showToast({ title: '请输入真实姓名', icon: 'none' }) return } } else { this.data.name = '' } const res = await WXAPI.withDrawApplyV3({ token: wx.getStorageSync('token'), money: amount, pwd: this.data.pwd ? this.data.pwd : '', name: this.data.name ? this.data.name : '', }) if (res.code == 0) { wx.showModal({ title: '成功', content: '您的提现申请已提交,等待财务打款', showCancel: false, success: function(res) { if (res.confirm) { wx.navigateBack({ delta: 0, }) } } }) } else { wx.showToast({ title: res.msg, icon: 'none' }) } } }) ================================================ FILE: pages/withdraw/index.json ================================================ { "navigationBarTitleText": "申请提现" } ================================================ FILE: pages/withdraw/index.wxml ================================================ 可提现余额(元) ¥ {{ balance }} 提现将在1-3个工作日内到账 提现信息 💰 提现金额 👤 真实姓名 🔒 交易密码 ℹ️ 温馨提示 • 提现金额将原路返回至您的账户 • 每日最多可申请3次提现 • 如有疑问请联系客服 立即提现 ================================================ FILE: pages/withdraw/index.wxss ================================================ /* 京东风格 - 提现页面样式 */ page { background: #f5f5f5; min-height: 100vh; } .withdraw-container { padding-bottom: 40rpx; } /* 顶部余额卡片 */ .balance-card { padding: 40rpx 30rpx; background: linear-gradient(135deg, #E93323 0%, #C81623 100%); position: relative; overflow: hidden; } .balance-card::before { content: ''; position: absolute; width: 400rpx; height: 400rpx; background: rgba(255, 255, 255, 0.1); border-radius: 50%; top: -200rpx; right: -100rpx; } .balance-card::after { content: ''; position: absolute; width: 300rpx; height: 300rpx; background: rgba(255, 255, 255, 0.08); border-radius: 50%; bottom: -150rpx; left: -50rpx; } .balance-bg { position: relative; z-index: 1; } .balance-label { font-size: 28rpx; color: rgba(255, 255, 255, 0.9); margin-bottom: 20rpx; font-weight: 400; } .balance-amount { display: flex; align-items: baseline; margin-bottom: 16rpx; } .balance-symbol { font-size: 40rpx; color: #fff; font-weight: bold; margin-right: 8rpx; } .balance-value { font-size: 72rpx; color: #fff; font-weight: bold; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', sans-serif; } .balance-tips { font-size: 24rpx; color: rgba(255, 255, 255, 0.8); } /* 提现表单 */ .withdraw-form { margin: 24rpx 30rpx; background: #fff; border-radius: 16rpx; padding: 32rpx; box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.04); } .form-title { font-size: 32rpx; font-weight: 600; color: #333; margin-bottom: 32rpx; padding-left: 16rpx; border-left: 6rpx solid #E93323; } .form-item { margin-bottom: 36rpx; padding-bottom: 32rpx; border-bottom: 1rpx solid #f0f0f0; } .form-item:last-child { margin-bottom: 0; padding-bottom: 0; border-bottom: none; } .item-label { display: flex; align-items: center; font-size: 28rpx; color: #666; margin-bottom: 20rpx; font-weight: 500; } .label-icon { font-size: 32rpx; margin-right: 12rpx; } /* 温馨提示 */ .tips-box { margin: 24rpx 30rpx; background: #fff; border-radius: 16rpx; padding: 32rpx; box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.04); } .tips-title { display: flex; align-items: center; font-size: 28rpx; color: #333; font-weight: 600; margin-bottom: 24rpx; } .tips-icon { font-size: 32rpx; margin-right: 12rpx; } .tips-content { padding-left: 44rpx; } .tips-item { font-size: 26rpx; color: #999; line-height: 44rpx; position: relative; } /* 提交按钮 */ .submit-btn-wrapper { padding: 40rpx 30rpx; position: fixed; bottom: 0; left: 0; right: 0; background: linear-gradient(to top, #fff 0%, rgba(255, 255, 255, 0.95) 100%); z-index: 100; } .submit-btn { height: 96rpx; background: linear-gradient(135deg, #E93323 0%, #C81623 100%); border-radius: 48rpx; display: flex; align-items: center; justify-content: center; box-shadow: 0 8rpx 24rpx rgba(233, 51, 35, 0.3); transition: all 0.3s; position: relative; overflow: hidden; } .submit-btn::before { content: ''; position: absolute; top: 0; left: -100%; width: 100%; height: 100%; background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.3), transparent); transition: left 0.5s; } .submit-btn:active { transform: scale(0.98); box-shadow: 0 4rpx 16rpx rgba(233, 51, 35, 0.4); } .btn-text { font-size: 32rpx; color: #fff; font-weight: 600; letter-spacing: 2rpx; } /* van-field 自定义样式覆盖 */ .form-item .van-field { padding: 0 !important; } .form-item .van-field__control { color: #333; font-weight: 500; } .form-item .van-field__control::-webkit-input-placeholder { color: #ccc; font-weight: 400; } ================================================ FILE: pages/wuliu/index.js ================================================ const WXAPI = require('apifm-wxapi') const app = getApp() Page({ data: {}, onLoad: function (e) { this.data.orderId = e.id this.data.trackingNumber = e.trackingNumber this.orderDetail() }, onShow: function () { }, async orderDetail() { // https://www.yuque.com/apifm/nu0f75/oamel8 const res = await WXAPI.orderDetail(wx.getStorageSync('token'), this.data.orderId) if (res.code != 0) { wx.showModal({ title: '错误', content: res.msg, showCancel: false, success: () => { wx.navigateBack() } }) return; } const orderLogisticsShippers = res.data.orderLogisticsShippers let trackingNumber = this.data.trackingNumber if (!trackingNumber) { trackingNumber = res.data.logistics.trackingNumber } let shipperName = this.data.shipperName if (!shipperName) { shipperName = res.data.logistics.shipperName } let logisticsTraces = null if (this.data.trackingNumber && orderLogisticsShippers) { // 查看子快递单 const entity = orderLogisticsShippers.find(ele => { return ele.trackingNumber == this.data.trackingNumber }) if (entity.traces) { entity.tracesArray = JSON.parse (entity.traces) logisticsTraces = entity.tracesArray.reverse() } } else { if (res.data.logisticsTraces) { logisticsTraces = res.data.logisticsTraces.reverse() } } this.setData({ trackingNumber, shipperName, orderDetail: res.data, logisticsTraces }); }, }) ================================================ FILE: pages/wuliu/index.json ================================================ { "navigationBarTitleText": "物流信息" } ================================================ FILE: pages/wuliu/index.wxml ================================================ 🚚 物流单号 {{ trackingNumber }} 物流公司 {{ shipperName }} 物流轨迹 Package Tracking {{item.AcceptTime}} {{item.AcceptStation}} 最新 ================================================ FILE: pages/wuliu/index.wxss ================================================ page { min-height: 100vh; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); padding-bottom: 40rpx; } .container { min-height: 100vh; } /* ==================== 顶部物流信息卡片 ==================== */ .top-header { padding: 40rpx 30rpx 30rpx; } .header-card { background: linear-gradient(135deg, #ffffff 0%, #f8f9ff 100%); border-radius: 24rpx; padding: 40rpx 32rpx; box-shadow: 0 8rpx 32rpx rgba(102, 126, 234, 0.25); position: relative; overflow: hidden; } .header-card::before { content: ''; position: absolute; top: -50%; right: -20%; width: 300rpx; height: 300rpx; background: linear-gradient(135deg, rgba(102, 126, 234, 0.1) 0%, rgba(118, 75, 162, 0.1) 100%); border-radius: 50%; } .header-content { display: flex; align-items: flex-start; position: relative; z-index: 1; } .header-icon { margin-right: 24rpx; } .icon-truck { width: 88rpx; height: 88rpx; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); border-radius: 20rpx; display: flex; align-items: center; justify-content: center; font-size: 44rpx; box-shadow: 0 8rpx 16rpx rgba(102, 126, 234, 0.3); } .header-info { flex: 1; } .info-row { margin-bottom: 20rpx; } .info-row:last-child { margin-bottom: 0; } .info-label { font-size: 24rpx; color: #8b8fa3; margin-bottom: 8rpx; font-weight: 500; letter-spacing: 1rpx; } .info-value { font-size: 28rpx; color: #2d3142; font-weight: 600; word-break: break-all; } /* ==================== 物流轨迹容器 ==================== */ .timeline-container { background: #ffffff; margin: 0 30rpx; border-radius: 24rpx; padding: 40rpx 0; box-shadow: 0 8rpx 32rpx rgba(0, 0, 0, 0.1); } .timeline-header { padding: 0 40rpx 32rpx; border-bottom: 2rpx solid #f0f1f5; } .timeline-title { font-size: 36rpx; font-weight: 700; color: #2d3142; margin-bottom: 8rpx; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; } .timeline-subtitle { font-size: 22rpx; color: #a8adbf; font-weight: 500; letter-spacing: 2rpx; text-transform: uppercase; } /* ==================== 时间轴内容 ==================== */ .timeline-content { padding: 40rpx 0 20rpx; position: relative; } .timeline-item { display: flex; padding: 0 40rpx; margin-bottom: 32rpx; position: relative; animation: fadeInUp 0.6s ease-out forwards; opacity: 0; } .timeline-item:nth-child(1) { animation-delay: 0.1s; } .timeline-item:nth-child(2) { animation-delay: 0.2s; } .timeline-item:nth-child(3) { animation-delay: 0.3s; } .timeline-item:nth-child(4) { animation-delay: 0.4s; } .timeline-item:nth-child(5) { animation-delay: 0.5s; } @keyframes fadeInUp { from { opacity: 0; transform: translateY(20rpx); } to { opacity: 1; transform: translateY(0); } } /* ==================== 时间轴节点 ==================== */ .timeline-node { width: 48rpx; margin-right: 24rpx; display: flex; justify-content: center; flex-shrink: 0; } .node-wrapper { display: flex; flex-direction: column; align-items: center; width: 100%; height: 100%; } .node-dot { width: 28rpx; height: 28rpx; border-radius: 50%; background: #e5e7eb; position: relative; flex-shrink: 0; transition: all 0.3s ease; } .node-dot-active { width: 32rpx; height: 32rpx; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); box-shadow: 0 0 0 8rpx rgba(102, 126, 234, 0.15), 0 0 0 16rpx rgba(102, 126, 234, 0.08); animation: pulse 2s ease-in-out infinite; } @keyframes pulse { 0%, 100% { box-shadow: 0 0 0 8rpx rgba(102, 126, 234, 0.15), 0 0 0 16rpx rgba(102, 126, 234, 0.08); } 50% { box-shadow: 0 0 0 12rpx rgba(102, 126, 234, 0.2), 0 0 0 24rpx rgba(102, 126, 234, 0.1); } } .dot-inner { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 12rpx; height: 12rpx; border-radius: 50%; background: #ffffff; } .node-line { width: 3rpx; flex: 1; background: linear-gradient(to bottom, #e5e7eb 0%, rgba(229, 231, 235, 0.3) 100%); margin-top: 8rpx; min-height: 60rpx; } .timeline-item-active .node-line { background: linear-gradient(to bottom, rgba(102, 126, 234, 0.3) 0%, rgba(229, 231, 235, 0.3) 100%); } /* ==================== 内容卡片 ==================== */ .timeline-card { flex: 1; background: #f8f9ff; border-radius: 16rpx; padding: 24rpx 28rpx; position: relative; border: 2rpx solid transparent; transition: all 0.3s ease; margin-bottom: 8rpx; } .timeline-item-active .timeline-card { background: linear-gradient(135deg, #f8f9ff 0%, #ffffff 100%); border: 2rpx solid rgba(102, 126, 234, 0.2); box-shadow: 0 4rpx 16rpx rgba(102, 126, 234, 0.15); } .timeline-card::before { content: ''; position: absolute; left: -12rpx; top: 24rpx; width: 0; height: 0; border-top: 8rpx solid transparent; border-bottom: 8rpx solid transparent; border-right: 12rpx solid #f8f9ff; } .timeline-item-active .timeline-card::before { border-right-color: #f8f9ff; } .card-time { font-size: 24rpx; color: #8b8fa3; margin-bottom: 12rpx; font-weight: 500; display: flex; align-items: center; } .card-time::before { content: '🕒'; margin-right: 8rpx; font-size: 22rpx; } .timeline-item-active .card-time { color: #667eea; font-weight: 600; } .card-content { font-size: 28rpx; color: #2d3142; line-height: 44rpx; font-weight: 500; } .timeline-item-active .card-content { font-weight: 600; color: #1a1d2e; } .card-badge { position: absolute; top: -12rpx; right: 20rpx; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: #ffffff; font-size: 20rpx; padding: 4rpx 16rpx; border-radius: 20rpx; font-weight: 600; box-shadow: 0 4rpx 12rpx rgba(102, 126, 234, 0.4); letter-spacing: 1rpx; } /* ==================== 空状态优化 ==================== */ .timeline-container van-empty { padding: 80rpx 0; } ================================================ FILE: project.config.json ================================================ { "description": "项目配置文件,详见文档:https://developers.weixin.qq.com/miniprogram/dev/devtools/projectconfig.html", "setting": { "urlCheck": true, "es6": true, "enhance": true, "postcss": false, "preloadBackgroundData": false, "minified": true, "newFeature": true, "coverView": true, "nodeModules": false, "autoAudits": false, "showShadowRootInWxmlPanel": true, "scopeDataCheck": false, "uglifyFileName": false, "checkInvalidKey": true, "checkSiteMap": true, "uploadWithSourceMap": true, "compileHotReLoad": true, "useMultiFrameRuntime": true, "babelSetting": { "ignore": [], "disablePlugins": [], "outputPath": "" }, "useIsolateContext": true, "userConfirmedBundleSwitch": false, "packNpmManually": false, "packNpmRelationList": [], "minifyWXSS": true, "disableUseStrict": false, "minifyWXML": true, "showES6CompileOption": false, "useCompilerPlugins": false, "ignoreUploadUnusedFiles": true, "useStaticServer": true, "condition": false }, "compileType": "miniprogram", "simulatorType": "wechat", "simulatorPluginLibVersion": {}, "condition": { "plugin": { "list": [] }, "game": { "list": [] }, "gamePlugin": { "list": [] }, "miniprogram": { "list": [] } }, "editorSetting": { "tabIndent": "insertSpaces", "tabSize": 2 }, "packOptions": { "ignore": [], "include": [] }, "appid": "wxa46b09d413fbcaff" } ================================================ FILE: project.private.config.json ================================================ { "setting": { "compileHotReLoad": true, "urlCheck": false, "bigPackageSizeSupport": false }, "condition": {}, "description": "项目私有配置文件。此文件中的内容将覆盖 project.config.json 中的相同字段。项目的改动优先同步到此文件中。详见文档:https://developers.weixin.qq.com/miniprogram/dev/devtools/projectconfig.html", "libVersion": "3.14.1", "projectname": "%E5%A4%A9%E4%BD%BF%E7%AB%A5%E8%A3%85" } ================================================ FILE: sitemap.json ================================================ { "desc": "关于本文件的更多信息,请参考文档 https://developers.weixin.qq.com/miniprogram/dev/framework/sitemap.html", "rules": [{ "action": "allow", "page": "*" }] } ================================================ FILE: typings/wx.d.ts ================================================ // generate time:2017-08-23 21:12:06 // Type definitions for wx app // Definitions by: hellopao /************************************************ * * * 微信小程序 API * * * ************************************************/ interface IAnimation { /** * 透明度,参数范围 0~1 */ opacity(value: number): IAnimation; /** * 颜色值 */ backgroundColor(color: string): IAnimation; /** * 长度值,如果传入 Number 则默认使用 px,可传入其他自定义单位的长度值 */ width(length: number): IAnimation; /** * 长度值,如果传入 Number 则默认使用 px,可传入其他自定义单位的长度值 */ height(length: number): IAnimation; /** * 长度值,如果传入 Number 则默认使用 px,可传入其他自定义单位的长度值 */ top(length: number): IAnimation; /** * 长度值,如果传入 Number 则默认使用 px,可传入其他自定义单位的长度值 */ left(length: number): IAnimation; /** * 长度值,如果传入 Number 则默认使用 px,可传入其他自定义单位的长度值 */ bottom(length: number): IAnimation; /** * 长度值,如果传入 Number 则默认使用 px,可传入其他自定义单位的长度值 */ right(length: number): IAnimation; /** * deg的范围-180~180,从原点顺时针旋转一个deg角度 */ rotate(deg: number): IAnimation; /** * deg的范围-180~180,在X轴旋转一个deg角度 */ rotateX(deg: number): IAnimation; /** * deg的范围-180~180,在Y轴旋转一个deg角度 */ rotateY(deg: number): IAnimation; /** * deg的范围-180~180,在Z轴旋转一个deg角度 */ rotateZ(deg: number): IAnimation; /** * 同transform-function rotate3d */ rotate3d(x: number, y: number, z: number, deg: number): IAnimation; /** * 一个参数时,表示在X轴、Y轴同时缩放sx倍数;两个参数时表示在X轴缩放sx倍数,在Y轴缩放sy倍数 */ scale(sx: number, sy?: number): IAnimation; /** * 在X轴缩放sx倍数 */ scaleX(sx: number): IAnimation; /** * 在Y轴缩放sy倍数 */ scaleY(sy: number): IAnimation; /** * 在Z轴缩放sy倍数 */ scaleZ(sz: number): IAnimation; /** * 在X轴缩放sx倍数,在Y轴缩放sy倍数,在Z轴缩放sz倍数 */ scale3d(sx: number, sy: number, sz: number): IAnimation; /** * 一个参数时,表示在X轴偏移tx,单位px;两个参数时,表示在X轴偏移tx,在Y轴偏移ty,单位px。 */ translate(tx: number, ty?: number): IAnimation; /** * 在X轴偏移tx,单位px */ translateX(tx: number): IAnimation; /** * 在Y轴偏移tx,单位px */ translateY(tx: number): IAnimation; /** * 在Z轴偏移tx,单位px */ translateZ(tx: number): IAnimation; /** * 在X轴偏移tx,在Y轴偏移ty,在Z轴偏移tz,单位px */ translate3d(tx: number, ty: number, tz: number): IAnimation; /** * 参数范围-180~180;一个参数时,Y轴坐标不变,X轴坐标延顺时针倾斜ax度;两个参数时,分别在X轴倾斜ax度,在Y轴倾斜ay度 */ skew(ax: number, ay?: number): IAnimation; /** * 参数范围-180~180;Y轴坐标不变,X轴坐标延顺时针倾斜ax度 */ skewX(ax: number): IAnimation; /** * 参数范围-180~180;X轴坐标不变,Y轴坐标延顺时针倾斜ay度 */ skewY(ay: number): IAnimation; /** * 同transform-function matrix */ matrix(a, b, c, d, tx, ty): IAnimation; /** * 同transform-function matrix3d */ matrix3d(): IAnimation; } interface ICanvasContext { /** * 设置填充色, 如果没有设置 fillStyle,默认颜色为 black。 */ setFillStyle(color: string): void; /** * 设置边框颜色, 如果没有设置 fillStyle,默认颜色为 black。 */ setStrokeStyle(color: string): void; /** * 设置阴影 */ setShadow(offsetX: number, offsetY: number, blur: number, color: string): void; /** * 创建一个线性的渐变颜色。需要使用 addColorStop() 来指定渐变点,至少要两个。 */ createLinearGradient(x0: number, y0: number, x1: number, y1: number): void; /** * 创建一个圆形的渐变颜色。 起点在圆心,终点在圆环。 需要使用 addColorStop() 来指定渐变点,至少要两个。 */ createCircularGradient(x: number, y: number, r: number): void; /** * 创建一个颜色的渐变点。小于最小 stop 的部分会按最小 stop 的 color 来渲染,大于最大 stop 的部分会按最大 stop 的 color 来渲染。需要使用 addColorStop() 来指定渐变点,至少要两个。 */ addColorStop(stop: number, color: string): void; /** * 设置线条端点的样式 */ setLineCap(lineCap: 'butt' | 'round' | 'square'): void; /** * 设置两线相交处的样式 */ setLineJoin(lineJoin: 'bevel' | 'round' | 'miter'): void; /** * 设置线条宽度 */ setLineWidth(lineWidth: number): void; /** * 设置最大倾斜 */ setMiterLimit(miterLimit: number): void; /** * 添加一个矩形路径到当前路径。 */ rect(x: number, y: number, width: number, height: number): void; /** * 填充一个矩形。用 setFillStyle() 设置矩形的填充色,如果没设置默认是黑色。 */ fillRect(x: number, y: number, width: number, height: number): void; /** * 一个矩形(非填充)。用 setFillStroke() 设置矩形线条的颜色,如果没设置默认是黑色。 */ strokeRect(x: number, y: number, width: number, height: number): void; /** * 在给定的矩形区域内,清除画布上的像素 */ clearRect(x: number, y: number, width: number, height: number): void; /** * 对当前路径进行填充 */ fill(): void; /** * 对当前路径进行描边 */ stroke(): void; /** * 开始一个路径 */ beginPath(): void; /** * 关闭一个路径 */ closePath(): void; /** * 把路径移动到画布中的指定点,但不创建线条。 */ moveTo(x: number, y: number): void; /** * 添加一个新点,然后在画布中创建从该点到最后指定点的线条。 */ lineTo(x: number, y: number): void; /** * 添加一个弧形路径到当前路径,顺时针绘制。 */ arc(x: number, y: number, radius: number, startAngle: number, sweepAngle: number): void; /** * 创建二次方贝塞尔曲线 */ quadraticCurveTo(cpx: number, cpy: number, x: number, y: number): void; /** * 创建三次方贝塞尔曲线 */ bezierCurveTo(cpx1: number, cpy1: number, cpx2: number, cpy2: number, x: number, y: number): void; /** * 对横纵坐标进行缩放 */ scale(scaleWidth: number/**横坐标缩放的倍数1 = 100%,0.5 = 50%,2 = 200%,依次类 */, scaleHeight: number/** 纵坐标轴缩放的倍数1 = 100%,0.5 = 50%,2 = 200%,依次类 */): void; /** * 对坐标轴进行顺时针旋转 */ rotate(deg: number/**degrees * Math.PI/180;degrees范围为0~360;旋转角度,以弧度计 */): void; /** * 对坐标原点进行缩放 */ translate(x: number/**水平坐标平移量 */, y: number/**竖直坐标平移量 */): void; /** * 在画布上绘制被填充的文本 */ fillText(text: string, x: number, y: number): void; /** * 设置字体大小 */ setFontSize(fontSize: number): void; /** * 在画布上绘制图像 */ drawImage(imageResource: string, x: number, y: number, width: number, height: number): void; /** * 设置全局画笔透明度。 */ setGlobalAlpha(alpha: number): void; /** * 保存当前坐标轴的缩放、旋转、平移信息 */ save(): void; /** * 恢复之前保存过的坐标轴的缩放、旋转、平移信息 */ restore(): void; /** * 进行绘图 */ draw(): void; } interface IAudioContext { /** * 播放 */ play: () => void; /** * 暂停 */ pause: () => void; /** * 跳转到指定位置,单位 s */ seek: (position: number) => void; } interface IVideoContext { /** * 播放 */ play: () => void; /** * 暂停 */ pause: () => void; /** * 跳转到指定位置,单位 s */ seek: (position: number) => void; /** * 发送弹幕,danmu 包含两个属性 text, color。 */ sendDanmu: (danmu: {text: string; color: string;}) => void; } interface IMapContext { /** * 获取当前地图中心的经纬度,返回的是 gcj02 坐标系,可以用于 wx.openLocation */ getCenterLocation: (obj: { /** * 接口调用成功的回调函数 ,res = { longitude: "经度", latitude: "纬度"} */ success?: (res: {longitude: string; latitude: string}) => void; /** * 接口调用失败的回调函数 */ fail?: () => void; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: () => void; }) => void; /** * 将地图中心移动到当前定位点,需要配合map组件的show-location使用 */ moveToLocation: () => void; } interface Application { setData: (obj: any) => void; } interface AppConstructor { new (): Application; (opts: { /** * 生命周期函数--监听小程序初始化 */ onLaunch?: () => void; /** * 生命周期函数--监听小程序显示 */ onShow?: () => void; /** * 生命周期函数--监听小程序隐藏 */ onHide?: () => void; [key: string]: any; }): Application; } declare var App: AppConstructor; declare function getApp(): Application; declare function getCurrentPages(): Page[]; interface Page { setData: (obj: any) => void; } interface PageConstructor { new (): Page; (opts: { /** * 页面的初始数据 */ data?: any; /** * 页面的初始数据 */ onLoad?: () => void; /** * 生命周期函数--监听页面初次渲染完成 */ onReady?: () => void; /** * 生命周期函数--监听页面显示 */ onShow?: () => void; /** * 生命周期函数--监听页面隐藏 */ onHide?: () => void; /** * 生命周期函数--监听页面卸载 */ onUnload?: () => void; /** * 页面相关事件处理函数--监听用户下拉动作 */ onPullDownRefreash?: () => void; /** * 页面上拉触底事件的处理函数 */ onReachBottom?: () => void; /** * 用户点击右上角分享 */ onShareAppMessage?: () => { /** * 分享标题, 默认值当前小程序名称 */ title: string; /** * 分享描述, 默认值当前小程序名称 */ desc: string; /** * 分享路径 默认值当前页面 path ,必须是以 / 开头的完整路径 */ path: string; }; [key: string]: any; }): Page; } declare var Page: PageConstructor; declare var wx: { // # 网络 # request(obj: { /** * 开发者服务器接口地址 */ url: string; /** * 请求的参数 */ data?: any | string; /** * 设置请求的 header , header 中不能设置 Referer */ header?: any; /** * 默认为 GET,有效值:OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, CONNECT */ method?: string; /** * 默认为 json。如果设置了 dataType 为 json,则会尝试对响应的数据做一次 JSON.parse */ dataType?: string; /** * 收到开发者服务成功返回的回调函数,res = {data: '开发者服务器返回的内容'} */ success?: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; /** * 将本地资源上传到开发者服务器。如页面通过 wx.chooseImage 等接口获取到一个本地资源的临时文件路径后,可通过此接口将本地资源上传到指定服务器。客户端发起一个 HTTPS POST 请求,其中 content-type 为 multipart/form-data 。 */ uploadFile(obj: { /** * 开发者服务器 url */ url: string; /** * 要上传文件资源的路径 */ filePath: string; /** * 文件对应的 key , 开发者在服务器端通过这个 key 可以获取到文件二进制内容 */ name: string; /** * HTTP 请求 Header , header 中不能设置 Referer */ header?: any; /** * HTTP 请求中其他额外的 form data */ formData?: any; /** * 接口调用成功的回调函数 */ success?: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; /** * 下载文件资源到本地。客户端直接发起一个 HTTP GET 请求,返回文件的本地临时路径。 */ downloadFile(obj: { /** * 下载资源的 url */ url: string; /** * HTTP 请求 Header */ header?: any; /** * 下载成功后以 tempFilePath 的形式传给页面,res = {tempFilePath: '文件的临时路径'} */ success?: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; /** * 创建一个 WebSocket 连接;一个微信小程序同时只能有一个 WebSocket 连接,如果当前已存在一个 WebSocket 连接,会自动关闭该连接,并重新创建一个 WebSocket 连接。 */ connectSocket(obj: { /** * 开发者服务器接口地址,必须是 wss 协议,且域名必须是后台配置的合法域名 */ url: string; /** * 请求的数据 */ data?: any; /** * HTTP Header , header 中不能设置 Referer */ header?: any; /** * 默认是GET,有效值: OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, CONNECT */ method?: string; /** * 子协议数组 */ protocols?: string[]; /** * 接口调用成功的回调函数 */ success?: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; /** * 监听WebSocket连接打开事件。 */ onSocketOpen(callback: Function): void; /** * 监听WebSocket错误。 */ onSocketError(callback: Function): void; /** * 通过 WebSocket 连接发送数据,需要先 wx.connectSocket,并在 wx.onSocketOpen 回调之后才能发送。 */ sendSocketMessage(obj: { /** * 需要发送的内容 */ data: undefined; /** * 接口调用成功的回调函数 */ success?: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; /** * 监听WebSocket接受到服务器的消息事件。 */ onSocketMessage(callback: Function): void; /** * 关闭WebSocket连接。 */ closeSocket(obj: { /** * 一个数字值表示关闭连接的状态号,表示连接被关闭的原因。如果这个参数没有被指定,默认的取值是1000 (表示正常连接关闭) */ code?: number; /** * 一个可读的字符串,表示连接被关闭的原因。这个字符串必须是不长于123字节的UTF-8 文本(不是字符) */ reason?: string; /** * 接口调用成功的回调函数 */ success?: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; /** * 监听WebSocket关闭。 */ onSocketClose(callback: Function): void; // # 媒体 # /** * 从本地相册选择图片或使用相机拍照。 */ chooseImage(obj: { /** * 最多可以选择的图片张数,默认9 */ count?: number; /** * original 原图,compressed 压缩图,默认二者都有 */ sizeType?: string[]; /** * album 从相册选图,camera 使用相机,默认二者都有 */ sourceType?: string[]; /** * 成功则返回图片的本地文件路径列表 tempFilePaths */ success: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; /** * 预览图片。 */ previewImage(obj: { /** * 当前显示图片的链接,不填则默认为 urls 的第一张 */ current?: string; /** * 需要预览的图片链接列表 */ urls: string[]; /** * 接口调用成功的回调函数 */ success?: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; /** * 获取图片信息 */ getImageInfo(obj: { /** * 图片的路径,可以是相对路径,临时文件路径,存储文件路径,网络图片路径 */ src: string; /** * 接口调用成功的回调函数 */ success?: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; saveImageToPhotosAlbum(obj: { /** * 图片文件路径,可以是临时文件路径也可以是永久文件路径,不支持网络图片路径 */ filePath: string; /** * 接口调用成功的回调函数 */ success?: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; /** * 开始录音。当主动调用wx.stopRecord,或者录音超过1分钟时自动结束录音,返回录音文件的临时文件路径。当用户离开小程序时,此接口无法调用。 */ startRecord(obj: { /** * 录音成功后调用,返回录音文件的临时文件路径,res = {tempFilePath: '录音文件的临时路径'} */ success?: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; /** * ​ 主动调用停止录音。 */ stopRecord(): void; /** * 开始播放语音,同时只允许一个语音文件正在播放,如果前一个语音文件还没播放完,将中断前一个语音播放。 */ playVoice(obj: { /** * 需要播放的语音文件的文件路径 */ filePath: string; /** * 接口调用成功的回调函数 */ success?: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; /** * 暂停正在播放的语音。再次调用wx.playVoice播放同一个文件时,会从暂停处开始播放。如果想从头开始播放,需要先调用 wx.stopVoice。 */ pauseVoice(): void; /** * 结束播放语音。 */ stopVoice(): void; /** * 获取后台音乐播放状态。 */ getBackgroundAudioPlayerState(obj: { /** * 接口调用成功的回调函数 */ success?: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; /** * 使用后台播放器播放音乐,对于微信客户端来说,只能同时有一个后台音乐在播放。当用户离开小程序后,音乐将暂停播放;当用户点击“显示在聊天顶部”时,音乐不会暂停播放;当用户在其他小程序占用了音乐播放器,原有小程序内的音乐将停止播放。 */ playBackgroundAudio(obj: { /** * 音乐链接,目前支持的格式有 m4a, aac, mp3, wav */ dataUrl: string; /** * 音乐标题 */ title?: string; /** * 封面URL */ coverImgUrl?: string; /** * 接口调用成功的回调函数 */ success?: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; /** * 暂停播放音乐。 */ pauseBackgroundAudio(): void; /** * 控制音乐播放进度。 */ seekBackgroundAudio(obj: { /** * 音乐位置,单位:秒 */ position: number; /** * 接口调用成功的回调函数 */ success?: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; /** * 停止播放音乐。 */ stopBackgroundAudio(): void; /** * 监听音乐播放。 */ onBackgroundAudioPlay(callback: Function): void; /** * 监听音乐暂停。 */ onBackgroundAudioPause(callback: Function): void; /** * 监听音乐停止。 */ onBackgroundAudioStop(callback: Function): void; getBackgroundAudioManager(): void; /** * 创建并返回 audio 上下文 audioContext 对象 */ createAudioContext(audioId: string): IAudioContext; /** * 拍摄视频或从手机相册中选视频,返回视频的临时文件路径。 */ chooseVideo(obj: { /** * album 从相册选视频,camera 使用相机拍摄,默认为:['album', 'camera'] */ sourceType?: string[]; /** * 拍摄视频最长拍摄时间,单位秒。最长支持 60 秒 */ maxDuration?: number; /** * 默认调起的为前置还是后置摄像头。front: 前置,back: 后置,默认 back */ camera?: string; /** * 接口调用成功,返回视频文件的临时文件路径,详见返回参数说明 */ success?: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; saveVideoToPhotosAlbum(obj: { /** * 视频文件路径,可以是临时文件路径也可以是永久文件路径 */ filePath: string; /** * 接口调用成功的回调函数 */ success?: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; /** * 创建并返回 video 上下文 videoContext 对象 */ createVideoContext(videoId: string): IVideoContext; // # 文件 # /** * 保存文件到本地。 */ saveFile(obj: { /** * 需要保存的文件的临时路径 */ tempFilePath: string; /** * 返回文件的保存路径,res = {savedFilePath: '文件的保存路径'} */ success?: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; /** * 获取本地已保存的文件列表 */ getSavedFileList(obj: { /** * 接口调用成功的回调函数,返回结果见success返回参数说明 */ success?: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; /** * 获取本地文件的文件信息。此接口只能用于获取已保存到本地的文件,若需要获取临时文件信息,请使用 wx.getFileInfo 接口。 */ getSavedFileInfo(obj: { /** * 文件路径 */ filePath: string; /** * 接口调用成功的回调函数,返回结果见success返回参数说明 */ success?: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; /** * 删除本地存储的文件 */ removeSavedFile(obj: { /** * 需要删除的文件路径 */ filePath: string; /** * 接口调用成功的回调函数 */ success?: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; /** * 新开页面打开文档,支持格式:doc, xls, ppt, pdf, docx, xlsx, pptx */ openDocument(obj: { /** * 文件路径,可通过 downFile 获得 */ filePath: string; /** * 文件类型,指定文件类型打开文件,有效值 doc, xls, ppt, pdf, docx, xlsx, pptx */ fileType?: string; /** * 接口调用成功的回调函数 */ success?: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; getFileInfo(obj: { /** * 本地文件路径 */ filePath: string; /** * 计算文件摘要的算法,默认值 md5,有效值:md5,sha1 */ digestAlgorithm?: string; /** * 接口调用成功的回调函数 */ success?: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; // # 数据缓存 # /** * 将数据存储在本地缓存中指定的 key 中,会覆盖掉原来该 key 对应的内容,这是一个异步接口。 */ setStorage(obj: { /** * 本地缓存中的指定的 key */ key: string; /** * 需要存储的内容 */ data: any; /** * 接口调用成功的回调函数 */ success?: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; /** * 将 data 存储在本地缓存中指定的 key 中,会覆盖掉原来该 key 对应的内容,这是一个同步接口。 */ setStorageSync(key: string, data: any, ): void; /** * 从本地缓存中异步获取指定 key 对应的内容。 */ getStorage(obj: { /** * 本地缓存中的指定的 key */ key: string; /** * 接口调用的回调函数,res = {data: key对应的内容} */ success: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; /** * 从本地缓存中同步获取指定 key 对应的内容。 */ getStorageSync(key: string): void; /** * 异步获取当前storage的相关信息 */ getStorageInfo(obj: { /** * 接口调用的回调函数,详见返回参数说明 */ success: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; /** * 同步获取当前storage的相关信息 */ getStorageInfoSync(): void; /** * 从本地缓存中异步移除指定 key 。 */ removeStorage(obj: { /** * 本地缓存中的指定的 key */ key: string; /** * 接口调用的回调函数 */ success: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; /** * 从本地缓存中同步移除指定 key 。 */ removeStorageSync(key: string): void; /** * 清理本地数据缓存。 */ clearStorage(): void; /** * 同步清理本地数据缓存 */ clearStorageSync(): void; // # 位置 # /** * 获取当前的地理位置、速度。当用户离开小程序后,此接口无法调用;当用户点击“显示在聊天顶部”时,此接口可继续调用。 */ getLocation(obj: { /** * 默认为 wgs84 返回 gps 坐标,gcj02 返回可用于wx.openLocation的坐标 */ type?: string; /** * 接口调用成功的回调函数,返回内容详见返回参数说明。 */ success: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; /** * 打开地图选择位置 */ chooseLocation(obj: { /** * 接口调用成功的回调函数,返回内容详见返回参数说明。 */ success: Function; /** * 用户取消时调用 */ cancel?: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; /** * ​ 使用微信内置地图查看位置 */ openLocation(obj: { /** * 纬度,范围为-90~90,负数表示南纬 */ latitude: number; /** * 经度,范围为-180~180,负数表示西经 */ longitude: number; /** * 缩放比例,范围5~18,默认为18 */ scale?: number; /** * 位置名 */ name?: string; /** * 地址的详细说明 */ address?: string; /** * 接口调用成功的回调函数 */ success?: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; /** * 创建并返回 map 上下文 mapContext 对象 */ createMapContext(mapId: string): IMapContext; // # 设备 # /** * 获取系统信息。 */ getSystemInfo(obj: { /** * 接口调用成功的回调 */ success: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; /** * 获取系统信息同步接口 */ getSystemInfoSync(): void; /** * 获取网络类型。 */ getNetworkType(obj: { /** * 接口调用成功,返回网络类型 networkType */ success: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; onNetworkStatusChange(callback: Function): void; setScreenBrightness(obj: { /** * 屏幕亮度值,范围 0~1,0 最暗,1 最亮 */ value: number; /** * 接口调用成功 */ success?: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; getScreenBrightness(obj: { /** * 接口调用成功 */ success?: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; vibrateLong(obj: { /** * 接口调用成功的回调函数 */ success?: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; vibrateShort(obj: { /** * 接口调用成功的回调函数 */ success?: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; /** * 监听加速度数据,频率:5次/秒,接口调用后会自动开始监听,可使用 wx.stopAccelerometer 停止监听。 */ onAccelerometerChange(callback: Function): void; startAccelerometer(obj: { /** * 接口调用成功的回调函数 */ success?: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; stopAccelerometer(obj: { /** * 接口调用成功的回调函数 */ success?: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; /** * 监听罗盘数据,频率:5次/秒,接口调用后会自动开始监听,可使用wx.stopCompass停止监听。 */ onCompassChange(callback: Function): void; startCompass(obj: { /** * 接口调用成功的回调函数 */ success?: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; stopCompass(obj: { /** * 接口调用成功的回调函数 */ success?: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; makePhoneCall(obj: { /** * 需要拨打的电话号码 */ phoneNumber: string; /** * 接口调用成功的回调 */ success?: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; /** * 调起客户端扫码界面,扫码成功后返回对应的结果 */ scanCode(obj: { /** * 是否只能从相机扫码,不允许从相册选择图片 */ onlyFromCamera?: boolean; /** * 接口调用成功的回调函数,返回内容详见返回参数说明。 */ success?: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; setClipboardData(obj: { /** * 需要设置的内容 */ data: string; /** * 接口调用成功的回调函数 */ success?: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; getClipboardData(obj: { /** * 接口调用成功的回调函数 */ success?: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; openBluetoothAdapter(obj: { /** * 成功则返回成功初始化信息 */ success: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; closeBluetoothAdapter(obj: { /** * 成功则返回成功关闭模块信息 */ success: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; getBluetoothAdapterState(obj: { /** * 成功则返回本机蓝牙适配器状态 */ success: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; onBluetoothAdapterStateChange(callback: Function): void; startBluetoothDevicesDiscovery(obj: { /** * 蓝牙设备主 service 的 uuid 列表 */ services?: Array; /** * 是否允许重复上报同一设备, 如果允许重复上报,则onDeviceFound 方法会多次上报同一设备,但是 RSSI 值会有不同 */ allowDuplicatesKey?: boolean; /** * 上报设备的间隔,默认为0,意思是找到新设备立即上报,否则根据传入的间隔上报 */ interval?: number; /** * 成功则返回本机蓝牙适配器状态 */ success: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; stopBluetoothDevicesDiscovery(obj: { /** * 成功则返回本机蓝牙适配器状态 */ success: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; getBluetoothDevices(obj: { /** * 成功则返回本机蓝牙适配器状态 */ success: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; onBluetoothDeviceFound(callback: Function): void; getConnectedBluetoothDevices(obj: { /** * 蓝牙设备主 service 的 uuid 列表 */ services: Array; /** * 成功则返回本机蓝牙适配器状态 */ success: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; createBLEConnection(obj: { /** * 蓝牙设备 id,参考 getDevices 接口 */ deviceId: string; /** * 成功则返回本机蓝牙适配器状态 */ success: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; closeBLEConnection(obj: { /** * 蓝牙设备 id,参考 getDevices 接口 */ deviceId: string; /** * 成功则返回本机蓝牙适配器状态 */ success: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; getBLEDeviceServices(obj: { /** * 蓝牙设备 id,参考 getDevices 接口 */ deviceId: string; /** * 成功则返回本机蓝牙适配器状态 */ success: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; getBLEDeviceCharacteristics(obj: { /** * 蓝牙设备 id,参考 device 对象 */ deviceId: string; /** * 蓝牙服务 uuid */ serviceId: string; /** * 成功则返回本机蓝牙适配器状态 */ success: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; readBLECharacteristicValue(obj: { /** * 蓝牙设备 id,参考 device 对象 */ deviceId: string; /** * 蓝牙特征值对应服务的 uuid */ serviceId: string; /** * 蓝牙特征值的 uuid */ characteristicId: string; /** * 成功则返回本机蓝牙适配器状态 */ success: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; writeBLECharacteristicValue(obj: { /** * 蓝牙设备 id,参考 device 对象 */ deviceId: string; /** * 蓝牙特征值对应服务的 uuid */ serviceId: string; /** * 蓝牙特征值的 uuid */ characteristicId: string; /** * 蓝牙设备特征值对应的二进制值(注意:vConsole 无法打印出 ArrayBuffer 类型数据) */ value: undefined; /** * 成功则返回本机蓝牙适配器状态 */ success: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; notifyBLECharacteristicValueChange(obj: { /** * 蓝牙设备 id,参考 device 对象 */ deviceId: string; /** * 蓝牙特征值对应服务的 uuid */ serviceId: string; /** * 蓝牙特征值的 uuid */ characteristicId: string; /** * true: 启用 notify; false: 停用 notify */ state: boolean; /** * 成功则返回本机蓝牙适配器状态 */ success: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; onBLEConnectionStateChange(callback: Function): void; onBLECharacteristicValueChange(callback: Function): void; startBeaconDiscovery(obj: { /** * iBeacon设备广播的 uuids */ uuids: string[]; /** * 接口调用成功的回调函数 */ success?: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; stopBeaconDiscovery(obj: { /** * 接口调用成功的回调函数 */ success?: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; getBeacons(obj: { /** * 接口调用成功的回调函数 */ success?: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; onBeaconUpdate(callback: Function): void; onBeaconServiceChange(callback: Function): void; onUserCaptureScreen(callback: Function): void; addPhoneContact(obj: { /** * 头像本地文件路径 */ photoFilePath?: string; /** * 昵称 */ nickName?: string; /** * 姓氏 */ lastName?: string; /** * 中间名 */ middleName?: string; /** * 名字 */ firstName: string; /** * 备注 */ remark?: string; /** * 手机号 */ mobilePhoneNumber?: string; /** * 微信号 */ weChatNumber?: string; /** * 联系地址国家 */ addressCountry?: string; /** * 联系地址省份 */ addressState?: string; /** * 联系地址城市 */ addressCity?: string; /** * 联系地址街道 */ addressStreet?: string; /** * 联系地址邮政编码 */ addressPostalCode?: string; /** * 公司 */ organization?: string; /** * 职位 */ title?: string; /** * 工作传真 */ workFaxNumber?: string; /** * 工作电话 */ workPhoneNumber?: string; /** * 公司电话 */ hostNumber?: string; /** * 电子邮件 */ email?: string; /** * 网站 */ url?: string; /** * 工作地址国家 */ workAddressCountry?: string; /** * 工作地址省份 */ workAddressState?: string; /** * 工作地址城市 */ workAddressCity?: string; /** * 工作地址街道 */ workAddressStreet?: string; /** * 工作地址邮政编码 */ workAddressPostalCode?: string; /** * 住宅传真 */ homeFaxNumber?: string; /** * 住宅电话 */ homePhoneNumber?: string; /** * 住宅地址国家 */ homeAddressCountry?: string; /** * 住宅地址省份 */ homeAddressState?: string; /** * 住宅地址城市 */ homeAddressCity?: string; /** * 住宅地址街道 */ homeAddressStreet?: string; /** * 住宅地址邮政编码 */ homeAddressPostalCode?: string; /** * 接口调用成功 */ success?: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; // # 界面 # /** * 显示消息提示框 */ showToast(obj: { /** * 提示的内容 */ title: string; /** * 图标,有效值 "success", "loading" */ icon?: string; /** * 自定义图标的本地路径,image 的优先级高于 icon */ image?: string; /** * 提示的延迟时间,单位毫秒,默认:1500 */ duration?: number; /** * 是否显示透明蒙层,防止触摸穿透,默认:false */ mask?: boolean; /** * 接口调用成功的回调函数 */ success?: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; showLoading(obj: { /** * 提示的内容 */ title: string; /** * 是否显示透明蒙层,防止触摸穿透,默认:false */ mask?: boolean; /** * 接口调用成功的回调函数 */ success?: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; /** * 隐藏消息提示框 */ hideToast(): void; hideLoading(): void; /** * ​显示模态弹窗 */ showModal(obj: { /** * 提示的标题 */ title: string; /** * 提示的内容 */ content: string; /** * 是否显示取消按钮,默认为 true */ showCancel?: boolean; /** * 取消按钮的文字,默认为"取消",最多 4 个字符 */ cancelText?: string; /** * 取消按钮的文字颜色,默认为"#000000" */ cancelColor?: undefined; /** * 确定按钮的文字,默认为"确定",最多 4 个字符 */ confirmText?: string; /** * 确定按钮的文字颜色,默认为"#3CC51F" */ confirmColor?: undefined; /** * 接口调用成功的回调函数 */ success?: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; /** * ​显示操作菜单 */ showActionSheet(obj: { /** * 按钮的文字数组,数组长度最大为6个 */ itemList: undefined; /** * 按钮的文字颜色,默认为"#000000" */ itemColor?: undefined; /** * 接口调用成功的回调函数,详见返回参数说明 */ success?: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; setTopBarText(obj: { /** * 置顶栏文字内容 */ text: string; /** * 接口调用成功的回调函数 */ success?: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; /** * 动态设置当前页面的标题。 */ setNavigationBarTitle(obj: { /** * 页面标题 */ title: string; /** * 接口调用成功的回调函数 */ success?: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; /** * 在当前页面显示导航条加载动画。 */ showNavigationBarLoading(): void; /** * 隐藏导航条加载动画。 */ hideNavigationBarLoading(): void; /** * 保留当前页面,跳转到应用内的某个页面,使用wx.navigateBack可以返回到原页面。 */ navigateTo(obj: { /** * 需要跳转的应用内非 tabBar 的页面的路径 , 路径后可以带参数。参数与路径之间使用?分隔,参数键与参数值用=相连,不同参数用&分隔;如 'path?key=value&key2=value2' */ url: string; /** * 接口调用成功的回调函数 */ success?: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; /** * 关闭当前页面,跳转到应用内的某个页面。 */ redirectTo(obj: { /** * 需要跳转的应用内非 tabBar 的页面的路径,路径后可以带参数。参数与路径之间使用?分隔,参数键与参数值用=相连,不同参数用&分隔;如 'path?key=value&key2=value2' */ url: string; /** * 接口调用成功的回调函数 */ success?: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; reLaunch(obj: { /** * 需要跳转的应用内页面路径 , 路径后可以带参数。参数与路径之间使用?分隔,参数键与参数值用=相连,不同参数用&分隔;如 'path?key=value&key2=value2',如果跳转的页面路径是 tabBar 页面则不能带参数 */ url: string; /** * 接口调用成功的回调函数 */ success?: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; /** * 跳转到 tabBar 页面,并关闭其他所有非 tabBar 页面 */ switchTab(obj: { /** * 需要跳转的 tabBar 页面的路径(需在 app.json 的 tabBar 字段定义的页面),路径后不能带参数 */ url: string; /** * 接口调用成功的回调函数 */ success?: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; /** * 关闭当前页面,返回上一页面或多级页面。可通过 getCurrentPages()) 获取当前的页面栈,决定需要返回几层。 */ navigateBack(obj: { /** * 返回的页面数,如果 delta 大于现有页面数,则返回到首页。 */ delta?: number; }): void; /** * 创建一个动画实例animation。调用实例的方法来描述动画。最后通过动画实例的export方法导出动画数据传递给组件的animation属性。 */ createAnimation(obj: { /** * 400 */ duration?: number; /** * "linear" */ timingFunction?: string; /** * 0 */ delay?: number; /** * "50% 50% 0" */ transformOrigin?: string; }): IAnimation; pageScrollTo(obj: { /** * 滚动到页面的目标位置(单位px) */ scrollTop: number; }): void; /** * 创建 canvas 绘图上下文(指定 canvasId).Tip: 需要指定 canvasId,该绘图上下文只作用于对应的 */ createCanvasContext(canvasId: string): ICanvasContext; /** * 把当前画布的内容导出生成图片,并返回文件路径 */ canvasToTempFilePath(canvasId: string): void; startPullDownRefresh(obj: { /** * 接口调用成功的回调函数 */ success?: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; /** * 停止当前页面下拉刷新。 */ stopPullDownRefresh(): void; // # WXML节点信息 # // # 第三方平台 # getExtConfig(obj: { /** * 返回第三方平台自定义的数据 */ success?: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; getExtConfigSync(): void; // # 开放接口 # /** * 调用接口获取登录凭证(code)进而换取用户登录态信息,包括用户的唯一标识(openid) 及本次登录的 会话密钥(session_key)。用户数据的加解密通讯需要依赖会话密钥完成。 */ login(obj: { /** * 接口调用成功的回调函数 */ success?: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; /** * 通过上述接口获得的用户登录态拥有一定的时效性。用户越久未使用小程序,用户登录态越有可能失效。反之如果用户一直在使用小程序,则用户登录态一直保持有效。具体时效逻辑由微信维护,对开发者透明。开发者只需要调用wx.checkSession接口检测当前用户登录态是否有效。登录态过期后开发者可以再调用wx.login获取新的用户登录态。 */ checkSession(obj: { /** * 接口调用成功的回调函数,登录态未过期 */ success?: Function; /** * 接口调用失败的回调函数,登录态已过期 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; authorize(obj: { /** * 需要获取权限的scope,详见 scope 列表 */ scope: string; /** * 接口调用成功的回调函数 */ success?: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; /** * 获取用户信息,withCredentials 为 true 时需要先调用 wx.login 接口。 */ getUserInfo(obj: { /** * 是否带上登录态信息 */ withCredentials?: boolean; /** * 指定返回用户信息的语言,zh_CN 简体中文,zh_TW 繁体中文,en 英文 */ lang?: string; /** * 接口调用成功的回调函数 */ success?: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; /** * 发起微信支付。 */ requestPayment(obj: { /** * 时间戳从1970年1月1日00:00:00至今的秒数,即当前的时间 */ timeStamp: string; /** * 随机字符串,长度为32个字符以下。 */ nonceStr: string; /** * 统一下单接口返回的 prepay_id 参数值,提交格式如:prepay_id=* */ package: string; /** * 签名算法,暂支持 MD5 */ signType: string; /** * 签名,具体签名方案参见小程序支付接口文档; */ paySign: string; /** * 接口调用成功的回调函数 */ success?: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; chooseAddress(obj: { /** * 返回用户选择的收货地址信息 */ success?: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; addCard(obj: { /** * 需要添加的卡券列表,列表内对象说明请参见请求对象说明 */ cardList: undefined; /** * 接口调用成功的回调函数 */ success?: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; openCard(obj: { /** * 需要打开的卡券列表,列表内参数详见openCard 请求对象说明 */ cardList: undefined; /** * 接口调用成功的回调函数 */ success?: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; openSetting(obj: { /** * 接口调用成功的回调函数,返回内容详见返回参数说明。 */ success?: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; getSetting(obj: { /** * 接口调用成功的回调函数,返回内容详见返回参数说明。 */ success?: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; getWeRunData(obj: { /** * 接口调用成功的回调函数 */ success?: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; navigateToMiniProgram(obj: { /** * 要打开的小程序 appId */ appId: string; /** * 打开的页面路径,如果为空则打开首页 */ path?: string; /** * 需要传递给目标小程序的数据,目标小程序可在 App.onLaunch(),App.onShow() 中获取到这份数据。详情 */ extraData?: any; /** * 要打开的小程序版本,有效值 develop(开发版),trial(体验版),release(正式版) ,仅在当前小程序为开发版或体验版时此参数有效;如果当前小程序是体验版或正式版,则打开的小程序必定是正式版。默认值 release */ envVersion?: string; /** * 接口调用成功的回调函数 */ success?: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; chooseInvoiceTitle(obj: { /** * 接口调用成功的回调函数 */ success?: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; checkIsSupportSoterAuthentication(obj: { /** * 接口调用成功的回调函数 */ success?: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; // # 数据 # /** * 自定义分析数据上报接口。使用前,需要在小程序管理后台自定义分析中新建事件,配置好事件名与字段。 */ reportAnalytics(eventName: string, data: string, ): void; // # 拓展接口 # arrayBufferToBase64(arrayBuffer: string): void; base64ToArrayBuffer(base64: string): void; // # 调试接口 # setEnableDebug(obj: { /** * 是否打开调试 */ enableDebug: boolean; /** * 接口调用成功的回调函数 */ success?: Function; /** * 接口调用失败的回调函数 */ fail?: Function; /** * 接口调用结束的回调函数(调用成功、失败都会执行) */ complete?: Function; }): void; } ================================================ FILE: utils/address_parse.js ================================================ const WXAPI = require('apifm-wxapi') var addressList = []; //地址列表 var smartObj = {}; /** * 解析邮编 * @param event识别的地址 * @returns */ async function smart(event) { console.log('event1', event); event = stripscript(event); //过滤特殊字符 console.log('event2', event); let obj = {}; let copyaddress = JSON.parse(JSON.stringify(event)); console.log('copyaddress', copyaddress); copyaddress = copyaddress.split(" "); console.log('地址转为数组:', copyaddress); for (let index = 0; index < copyaddress.length; index++) { let res = copyaddress[index]; if (res) { if (res.length == 1) { res += "XX"; // 过滤掉一位的名字或者地址 } let addressObj = await smatrAddress(res); obj = Object.assign(obj, addressObj); if (JSON.stringify(addressObj) === "{}") { obj.name = res.replace("XX", ""); } } } return obj; } async function smatrAddress(event) { smartObj = {}; let address = event; //address= event.replace(/\s/g, ''); //去除空格 address = stripscript(address); //过滤特殊字符 //身份证号匹配 if (IdentityCodeValid(address)) { smartObj.idCard = address; address = address.replace(address, ""); } //电话匹配 let phone = address.match( /(86-[1][0-9]{10}) | (86[1][0-9]{10})|([1][0-9]{10})/g ); if (phone) { smartObj.phone = phone[0]; address = address.replace(phone[0], ""); } console.log('smatrAddress:', address); let matchAddress = ""; //省匹配 比如输入北京市朝阳区,会用北 北京 北京市 北京市朝 以此类推在addressList里的province中做匹配,会得到北京市 河北省 天津市等等; const resProvince = await WXAPI.provinceV2() const provinceList = resProvince.data let matchProvince = []; //粗略匹配上的省份 // for (let begIndex = 0; begIndex < address.length; begIndex++) { matchAddress = ""; for (let endIndex = 0; endIndex < address.length; endIndex++) { // if (endIndex > begIndex) { matchAddress = address.slice(0, endIndex + 2); provinceList.forEach(res => { if (res.name.indexOf(matchAddress) != -1) { matchProvince.push({ province: res.name, provinceCode: res.id, matchValue: matchAddress }); } }); // } } // } //统计筛选初略统计出的省份 matchProvince.forEach(res => { res.index = 0; matchProvince.forEach(el => { if (res.province == el.province) { el.index++; if (res.matchValue.length > el.matchValue.length) { el.matchValue = res.matchValue; } } }); }); if (matchProvince.length != 0) { let province = matchProvince.reduce((p, v) => (p.index < v.index ? v : p)); smartObj.province = province.province; smartObj.provinceCode = province.provinceCode; address = address.replace(province.matchValue, ""); } //市查找 const resCity = await WXAPI.cityV2() let cityList = resCity.data if (smartObj.provinceCode) { cityList = resCity.data.filter(ele => { return ele.pid == smartObj.provinceCode }) } let matchCity = []; //粗略匹配上的市 matchAddress = ""; for (let endIndex = 0; endIndex < address.length; endIndex++) { matchAddress = address.slice(0, endIndex + 2) cityList.forEach(res => { if (res.name.indexOf(matchAddress) != -1) { matchCity.push({ city: res.name, cityCode: res.id, pid: res.pid, matchValue: matchAddress, province: smartObj.province, provinceCode: smartObj.provinceCode }); } }); } //统计筛选初略统计出的市 matchCity.forEach(res => { res.index = 0; matchCity.forEach(el => { if (res.city == el.city) { el.index++; if (res.matchValue.length > el.matchValue.length) { el.matchValue = res.matchValue; } } }); }); // 直辖市处理 if (smartObj.province == '北京市') { matchCity.push({ city: '北京市', cityCode: '110100000000', matchValue: '', province: smartObj.province, provinceCode: smartObj.provinceCode }); } if (smartObj.province == '上海市') { matchCity.push({ city: '上海市', cityCode: '310100000000', matchValue: '', province: smartObj.province, provinceCode: smartObj.provinceCode }); } if (smartObj.province == '天津市') { matchCity.push({ city: '天津市', cityCode: '120100000000', matchValue: '', province: smartObj.province, provinceCode: smartObj.provinceCode }); } if (smartObj.province == '重庆市') { matchCity.push({ city: '重庆市', cityCode: '500100000000', matchValue: '', province: smartObj.province, provinceCode: smartObj.provinceCode }); } if (matchCity.length != 0) { let city = matchCity.reduce((p, v) => (p.index < v.index ? v : p)); smartObj.city = city.city; smartObj.cityCode = city.cityCode; // smartObj.county = city.county; // smartObj.countyCode = city.countyCode; if (!smartObj.province) { const _province = provinceList.find(ele => { return ele.id == city.pid }) smartObj.province = _province.name; smartObj.provinceCode = city.pid; } address = address.replace(city.matchValue, ""); } //区县查找 const resDistricts = await WXAPI.districts() let districtList = resDistricts.data if (smartObj.cityCode) { districtList = resDistricts.data.filter(ele => { return ele.pid == smartObj.cityCode }) } console.log('smartObj', smartObj); let matchCounty = []; //粗略匹配上的区县 matchAddress = ""; for (let endIndex = 0; endIndex < address.length; endIndex++) { matchAddress = address.slice(0, endIndex + 2); districtList.forEach(res => { if (res.name.indexOf(matchAddress) != -1) { matchCounty.push({ county: res.name, countyCode: res.id, city: smartObj.city, cityCode: smartObj.cityCode, matchValue: matchAddress, province: smartObj.province, provinceCode: smartObj.provinceCode }); } }); } //统计筛选初略统计出的区县 matchCounty.forEach(res => { res.index = 0; matchCounty.forEach(el => { if (res.city == el.city) { el.index++; if (res.matchValue.length > el.matchValue.length) { el.matchValue = res.matchValue; } } }); }); if (matchCounty.length != 0) { let city = matchCounty.reduce((p, v) => (p.index < v.index ? v : p)); smartObj.county = city.county; smartObj.countyCode = city.countyCode; if (!smartObj.province) { smartObj.province = city.province; smartObj.provinceCode = city.provinceCode; } if (!smartObj.city) { smartObj.city = city.city; smartObj.cityCode = city.cityCode; } address = address.replace(city.matchValue, ""); } //街道查找 let matchStreet = []; //粗略匹配上的街道查 matchAddress = ""; for (let endIndex = 0; endIndex < address.length; endIndex++) { matchAddress = address.slice(0, endIndex + 3); addressList.forEach(el => { if (el.name == smartObj.province) { if ( smartObj.province == "北京市" || smartObj.province == "天津市" || smartObj.province == "上海市" || smartObj.province == "重庆市" ) { //nothing } else { el.children.forEach(element => { if (element.name == smartObj.city) { element.children.forEach(item => { if (item.name == smartObj.county) { item.children.forEach(res => { if (res["street"].indexOf(matchAddress) != -1) { matchStreet.push({ street: res.street, streetCode: res.code, matchValue: matchAddress }); } }); } }); } }); } } }); } //统计筛选初略统计出的区县 matchStreet.forEach(res => { res.index = 0; matchStreet.forEach(el => { if (res.city == el.city) { el.index++; if (res.matchValue.length > el.matchValue.length) { el.matchValue = res.matchValue; } } }); }); if (matchStreet.length != 0) { let city = matchStreet.reduce((p, v) => (p.index < v.index ? v : p)); smartObj.street = city.street; smartObj.streetCode = city.streetCode; address = address.replace(city.matchValue, ""); } //姓名查找 if (smartObj.province) { smartObj.address = address; } return smartObj; } ////过滤特殊字符 function stripscript(s) { s = s.replace(/\t/g, " ") s = s.replace(/(\d{3})-(\d{4})-(\d{4})/g, "$1$2$3"); s = s.replace(/(\d{3}) (\d{4}) (\d{4})/g, "$1$2$3"); var pattern = new RegExp( "[`~!@#$^&*()=|{}':;',\\[\\].<>/?~!@#¥……&*()——|{}【】‘;:”“’。,、?-]" ); var rs = ""; for (var i = 0; i < s.length; i++) { rs = rs + s.substr(i, 1).replace(pattern, " "); } rs = rs.replace(/[\r\n]/g, ""); return rs; } function IdentityCodeValid(code) { let pass; var city = { 11: "北京", 12: "天津", 13: "河北", 14: "山西", 15: "内蒙古", 21: "辽宁", 22: "吉林", 23: "黑龙江 ", 31: "上海", 32: "江苏", 33: "浙江", 34: "安徽", 35: "福建", 36: "江西", 37: "山东", 41: "河南", 42: "湖北 ", 43: "湖南", 44: "广东", 45: "广西", 46: "海南", 50: "重庆", 51: "四川", 52: "贵州", 53: "云南", 54: "西藏 ", 61: "陕西", 62: "甘肃", 63: "青海", 64: "宁夏", 65: "新疆", 71: "台湾", 81: "香港", 82: "澳门", 91: "国外 " }; var tip = ""; pass = true; if (!code || !/^\d{17}(\d|X)$/i.test(code)) { tip = "身份证号格式错误"; pass = false; } else if (!city[code.substr(0, 2)]) { tip = "地址编码错误"; pass = false; } else { //18位身份证需要验证最后一位校验位 if (code.length == 18) { code = code.split(""); //∑(ai×Wi)(mod 11) //加权因子 var factor = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]; //校验位 var parity = [1, 0, "X", 9, 8, 7, 6, 5, 4, 3, 2]; var sum = 0; var ai = 0; var wi = 0; for (var i = 0; i < 17; i++) { ai = code[i]; wi = factor[i]; sum += ai * wi; } var last = parity[sum % 11]; if (parity[sum % 11] != code[17]) { tip = "校验位错误"; pass = false; } } } return pass; } module.exports = { smart: smart }; ================================================ FILE: utils/auth.js ================================================ const WXAPI = require('apifm-wxapi') const CONFIG = require('../config.js') async function checkSession(){ return new Promise((resolve, reject) => { wx.checkSession({ success() { return resolve(true) }, fail() { return resolve(false) } }) }) } async function bindSeller() { const token = wx.getStorageSync('token') const referrer = wx.getStorageSync('referrer') if (!token) { return } if (!referrer) { return } const res = await WXAPI.bindSeller({ token, uid: referrer }) } // 检测登录状态,返回 true / false async function checkHasLogined() { const token = wx.getStorageSync('token') if (!token) { return false } const loggined = await checkSession() if (!loggined) { wx.removeStorageSync('token') return false } const checkTokenRes = await WXAPI.checkToken(token) if (checkTokenRes.code != 0) { wx.removeStorageSync('token') return false } return true } async function wxaCode(){ return new Promise((resolve, reject) => { wx.login({ success(res) { return resolve(res.code) }, fail() { wx.showToast({ title: '获取code失败', icon: 'none' }) return resolve('获取code失败') } }) }) } async function login(page){ const _this = this wx.login({ success: function (res) { const extConfigSync = wx.getExtConfigSync() if (extConfigSync.subDomain) { WXAPI.wxappServiceLogin({ code: res.code }).then(function (res) { if (res.code == 10000) { // 去注册 return; } if (res.code != 0) { // 登录错误 wx.showModal({ title: '无法登录', content: res.msg, showCancel: false }) return; } wx.setStorageSync('token', res.data.token) wx.setStorageSync('uid', res.data.uid) if (CONFIG.bindSeller) { _this.bindSeller() } if ( page ) { page.onShow() } }) } else { WXAPI.login_wx(res.code).then(function (res) { if (res.code == 10000) { // 去注册 return; } if (res.code != 0) { // 登录错误 wx.showModal({ title: '无法登录', content: res.msg, showCancel: false }) return; } wx.setStorageSync('token', res.data.token) wx.setStorageSync('uid', res.data.uid) if (CONFIG.bindSeller) { _this.bindSeller() } if ( page ) { page.onShow() } }) } } }) } async function authorize() { // const code = await wxaCode() // const resLogin = await WXAPI.login_wx(code) // if (resLogin.code == 0) { // wx.setStorageSync('token', resLogin.data.token) // wx.setStorageSync('uid', resLogin.data.uid) // return resLogin // } return new Promise((resolve, reject) => { wx.login({ success: function (res) { const code = res.code let referrer = '' // 推荐人 let referrer_storge = wx.getStorageSync('referrer'); if (referrer_storge) { referrer = referrer_storge; } // 下面开始调用注册接口 const extConfigSync = wx.getExtConfigSync() if (extConfigSync.subDomain) { WXAPI.wxappServiceAuthorize({ code: code, referrer: referrer }).then(function (res) { if (res.code == 0) { wx.setStorageSync('token', res.data.token) wx.setStorageSync('uid', res.data.uid) resolve(res) } else { wx.showToast({ title: res.msg, icon: 'none' }) reject(res.msg) } }) } else { WXAPI.authorize({ code: code, referrer: referrer }).then(function (res) { if (res.code == 0) { wx.setStorageSync('token', res.data.token) wx.setStorageSync('uid', res.data.uid) resolve(res) } else { wx.showToast({ title: res.msg, icon: 'none' }) reject(res.msg) } }) } }, fail: err => { reject(err) } }) }) } // 最新的登陆接口,建议用这个 async function login20241025() { const code = await wxaCode() const extConfigSync = wx.getExtConfigSync() if (extConfigSync.subDomain) { // 服务商模式 const res = await WXAPI.wxappServiceLogin({ code }) if (res.code == 10000) { // 去注册 return res } if (res.code != 0) { // 登录错误 wx.showModal({ content: res.msg, showCancel: false }) return res } wx.setStorageSync('token', res.data.token) wx.setStorageSync('uid', res.data.uid) wx.setStorageSync('openid', res.data.openid) wx.setStorageSync('mobile', res.data.mobile) if (CONFIG.bindSeller) { this.bindSeller() } return res } else { // 非服务商模式 const res = await WXAPI.login_wx(code) if (res.code == 10000) { // 去注册 return res; } if (res.code != 0) { // 登录错误 wx.showModal({ content: res.msg, showCancel: false }) return res; } wx.setStorageSync('token', res.data.token) wx.setStorageSync('uid', res.data.uid) wx.setStorageSync('openid', res.data.openid) wx.setStorageSync('mobile', res.data.mobile) if (CONFIG.bindSeller) { this.bindSeller() } return res } } function loginOut(){ wx.removeStorageSync('token') wx.removeStorageSync('uid') wx.removeStorageSync('openid') wx.removeStorageSync('mobile') } async function checkAndAuthorize (scope) { return new Promise((resolve, reject) => { wx.getSetting({ success(res) { if (!res.authSetting[scope]) { wx.authorize({ scope: scope, success() { resolve() // 无返回参数 }, fail(e){ console.error(e) // if (e.errMsg.indexof('auth deny') != -1) { // wx.showToast({ // title: e.errMsg, // icon: 'none' // }) // } wx.showModal({ title: '无权操作', content: '需要获得您的授权', showCancel: false, confirmText: '立即授权', confirmColor: '#e64340', success(res) { wx.openSetting(); }, fail(e){ console.error(e) reject(e) }, }) } }) } else { resolve() // 无返回参数 } }, fail(e){ console.error(e) reject(e) } }) }) } module.exports = { checkHasLogined: checkHasLogined, wxaCode: wxaCode, login: login, login20241025: login20241025, loginOut: loginOut, checkAndAuthorize: checkAndAuthorize, authorize: authorize, bindSeller: bindSeller } ================================================ FILE: utils/image.js ================================================ function imageUtil (originalWidth, originalHeight) { let imageSize = {} wx.getSystemInfo({ success: function (res) { const windowWidth = res.windowWidth imageSize.x = 0 imageSize.y = 0 imageSize.windowWidth = windowWidth imageSize.imageWidth = originalWidth imageSize.imageHeight = originalHeight if (originalWidth > windowWidth) { imageSize.imageWidth = windowWidth imageSize.imageHeight = windowWidth * originalHeight / originalWidth } else { imageSize.x = (windowWidth - originalWidth) / 2 } } }) return imageSize } module.exports = { imageUtil: imageUtil } ================================================ FILE: utils/pay.js ================================================ const WXAPI = require('apifm-wxapi') /** * type: order 支付订单 recharge 充值 paybill 优惠买单 * data: 扩展数据对象,用于保存参数 */ function wxpay(type, money, orderId, redirectUrl, data, content) { const postData = { token: wx.getStorageSync('token'), money: money, remark: "在线充值", content: content ? content : '' } if (type === 'order') { postData.remark = "支付订单 :" + orderId; postData.nextAction = { type: 0, id: orderId }; } if (type === 'paybill') { postData.remark = "优惠买单 :" + data.money; postData.nextAction = { type: 4, uid: wx.getStorageSync('uid'), money: data.money }; } if (type === 'fxsBuy') { postData.remark = "购买分销资格"; postData.nextAction = { type: 13 }; } if (type === 'payTz') { postData.remark = "购买团长 :" + money; postData.nextAction = { type: 14 }; } postData.payName = postData.remark; if (postData.nextAction) { postData.nextAction = JSON.stringify(postData.nextAction); } const url = wx.getStorageSync('wxpay_api_url') WXAPI.payVariableUrl(url ? url : '/pay/wx/wxapp', postData).then(function (res) { if (res.code == 0) { // 发起支付 wx.requestPayment({ timeStamp: res.data.timeStamp, nonceStr: res.data.nonceStr, package: res.data.package, signType: res.data.signType, paySign: res.data.paySign, fail: function (aaa) { console.error(aaa) wx.showToast({ title: '支付失败:' + aaa }) }, success: function () { // 提示支付成功 wx.showToast({ title: '支付成功' }) wx.redirectTo({ url: redirectUrl }); } }) } else { wx.showModal({ title: '出错了', content: JSON.stringify(res), showCancel: false }) } }) } module.exports = { wxpay: wxpay } ================================================ FILE: utils/tools.js ================================================ const WXAPI = require('apifm-wxapi') // 显示购物车tabBar的Badge async function showTabBarBadge(noTabBarPage){ const token = wx.getStorageSync('token') if (!token) { return 0 } let number = 0 // 自营商品 let res = await WXAPI.shippingCarInfo(token) if (res.code == 0) { number += res.data.number } // vop 购物车 const shopping_cart_vop_open = wx.getStorageSync('shopping_cart_vop_open') if (shopping_cart_vop_open == '1') { res = await WXAPI.jdvopCartInfoV2(token) if (res.code == 0) { number += res.data.number } } if (!noTabBarPage) { if (number == 0) { // 删除红点点 wx.removeTabBarBadge({ index: 3 }) } else { // 显示红点点 wx.setTabBarBadge({ index: 3, text: number + '' }) } } return number } module.exports = { showTabBarBadge: showTabBarBadge } ================================================ FILE: utils/tools.wxs ================================================ // 页面上使用的公共类 // // tools.tofix2(12.33333) module.exports = { msg: 'wxs-tools', tofix2: function(num) { return num.toFixed(2) } };