├── README.md
├── components
├── upload-image
│ ├── upload-image.wxss
│ ├── upload-image.json
│ ├── upload-image.wxml
│ └── upload-image.js
├── navigation-bar
│ ├── navigation-bar.wxss
│ ├── navigation-bar.json
│ ├── navigation-bar.js
│ └── navigation-bar.wxml
├── scroll-y
│ ├── scroll-y.json
│ ├── scroll-y.wxss
│ ├── scroll-y.wxml
│ └── scroll-y.js
├── tab-nav-roll
│ ├── tab-nav-roll.json
│ ├── tab-nav-roll.wxml
│ ├── tab-nav-roll.wxss
│ └── tab-nav-roll.js
├── login-authorization
│ ├── login-authorization.json
│ ├── login-authorization.wxml
│ ├── login-authorization.js
│ └── login-authorization.wxss
├── picker
│ ├── picker.json
│ ├── picker.wxml
│ ├── picker.wxss
│ └── picker.js
└── turntable
│ ├── turntable.json
│ ├── turntable.wxss
│ ├── turntable.wxml
│ └── turntable.js
├── pages
├── activity
│ ├── activity.wxss
│ ├── activity.json
│ ├── activity.wxml
│ └── activity.js
├── logs
│ ├── logs.json
│ ├── logs.wxss
│ ├── logs.wxml
│ └── logs.js
├── index
│ ├── index.json
│ ├── index.wxss
│ ├── index.wxml
│ └── index.js
├── mine
│ ├── mine.json
│ ├── mine.js
│ ├── mine.wxss
│ └── mine.wxml
├── login
│ ├── login.json
│ ├── login.wxml
│ ├── login.wxss
│ └── login.js
├── edit-card
│ ├── edit-card.json
│ ├── edit-card.wxss
│ ├── edit-card.js
│ └── edit-card.wxml
├── client-pool
│ ├── client-pool.json
│ ├── client-pool.wxss
│ ├── client-pool.wxml
│ └── client-pool.js
├── message
│ ├── message.json
│ ├── message.wxml
│ ├── message.wxss
│ └── message.js
├── goods
│ ├── goods.json
│ ├── goods.wxml
│ ├── goods.wxss
│ └── goods.js
└── home
│ ├── home.json
│ ├── home.js
│ ├── home.wxss
│ └── home.wxml
├── WeChat_applet.zip
├── image
├── home
│ ├── btn1.png
│ ├── btn2.png
│ ├── btn3.png
│ └── edit.png
├── mine
│ ├── bg_1.jpg
│ ├── icon_erwei.png
│ ├── user_icon1.png
│ ├── user_icon2.png
│ ├── user_icon3.png
│ └── user_icon4.png
├── common
│ ├── bus.png
│ ├── finish.png
│ ├── praise.png
│ ├── icon_add.png
│ ├── icon_right.png
│ ├── praiseing.gif
│ ├── shopcard.jpg
│ ├── shopcard_1.png
│ ├── underline.png
│ ├── unpraise.png
│ ├── pull_refresh.gif
│ └── select_black.png
├── login
│ └── defPic.png
├── message
│ └── tip.png
├── customer
│ ├── btn_call.png
│ └── bot_icon1.png
└── tabbar
│ ├── home_checked.png
│ ├── msg_checked.png
│ ├── center_checked.png
│ ├── client_checked.png
│ ├── goods_checked.png
│ ├── goods_uncheck.png
│ ├── home_unchecked.png
│ ├── msg_unchecked.png
│ ├── center_unchecked.png
│ └── client_unchecked.png
├── sitemap.json
├── .gitignore
├── utils
├── tools.js
├── request.js
├── publicData.js
├── util.js
└── WxValidate.js
├── api
└── loginApi.js
├── project.config.json
├── assets
├── moduleLess
│ └── login-authorization
│ │ └── login-authorization.less
└── less
│ ├── style.less
│ ├── message
│ └── message.less
│ └── goods
│ └── goods.less
├── app.json
├── js
└── common.js
├── app.js
└── app.wxss
/README.md:
--------------------------------------------------------------------------------
1 | # WeChat_couponents
--------------------------------------------------------------------------------
/components/upload-image/upload-image.wxss:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/components/navigation-bar/navigation-bar.wxss:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/components/scroll-y/scroll-y.json:
--------------------------------------------------------------------------------
1 | {
2 | "component": true
3 | }
--------------------------------------------------------------------------------
/pages/activity/activity.wxss:
--------------------------------------------------------------------------------
1 | .zhuanpan{
2 | width: 50%;
3 | }
--------------------------------------------------------------------------------
/components/tab-nav-roll/tab-nav-roll.json:
--------------------------------------------------------------------------------
1 | {
2 | "component": true
3 | }
--------------------------------------------------------------------------------
/components/upload-image/upload-image.json:
--------------------------------------------------------------------------------
1 | {
2 | "component": true
3 | }
--------------------------------------------------------------------------------
/components/navigation-bar/navigation-bar.json:
--------------------------------------------------------------------------------
1 | {
2 | "component": true
3 | }
--------------------------------------------------------------------------------
/components/login-authorization/login-authorization.json:
--------------------------------------------------------------------------------
1 | {
2 | "component": true
3 | }
--------------------------------------------------------------------------------
/WeChat_applet.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ZRH86/WeChat_couponents/HEAD/WeChat_applet.zip
--------------------------------------------------------------------------------
/components/picker/picker.json:
--------------------------------------------------------------------------------
1 | {
2 | "component": true,
3 | "usingComponents": {}
4 | }
--------------------------------------------------------------------------------
/components/upload-image/upload-image.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/image/home/btn1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ZRH86/WeChat_couponents/HEAD/image/home/btn1.png
--------------------------------------------------------------------------------
/image/home/btn2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ZRH86/WeChat_couponents/HEAD/image/home/btn2.png
--------------------------------------------------------------------------------
/image/home/btn3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ZRH86/WeChat_couponents/HEAD/image/home/btn3.png
--------------------------------------------------------------------------------
/image/home/edit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ZRH86/WeChat_couponents/HEAD/image/home/edit.png
--------------------------------------------------------------------------------
/image/mine/bg_1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ZRH86/WeChat_couponents/HEAD/image/mine/bg_1.jpg
--------------------------------------------------------------------------------
/pages/logs/logs.json:
--------------------------------------------------------------------------------
1 | {
2 | "navigationBarTitleText": "查看启动日志",
3 | "usingComponents": {}
4 | }
--------------------------------------------------------------------------------
/components/turntable/turntable.json:
--------------------------------------------------------------------------------
1 | {
2 | "component": true,
3 | "usingComponents": {}
4 | }
5 |
--------------------------------------------------------------------------------
/image/common/bus.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ZRH86/WeChat_couponents/HEAD/image/common/bus.png
--------------------------------------------------------------------------------
/image/login/defPic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ZRH86/WeChat_couponents/HEAD/image/login/defPic.png
--------------------------------------------------------------------------------
/image/message/tip.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ZRH86/WeChat_couponents/HEAD/image/message/tip.png
--------------------------------------------------------------------------------
/image/common/finish.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ZRH86/WeChat_couponents/HEAD/image/common/finish.png
--------------------------------------------------------------------------------
/image/common/praise.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ZRH86/WeChat_couponents/HEAD/image/common/praise.png
--------------------------------------------------------------------------------
/components/upload-image/upload-image.js:
--------------------------------------------------------------------------------
1 | Component({
2 | data: {},
3 | properties: {},
4 | methods: {}
5 | })
--------------------------------------------------------------------------------
/image/common/icon_add.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ZRH86/WeChat_couponents/HEAD/image/common/icon_add.png
--------------------------------------------------------------------------------
/image/common/icon_right.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ZRH86/WeChat_couponents/HEAD/image/common/icon_right.png
--------------------------------------------------------------------------------
/image/common/praiseing.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ZRH86/WeChat_couponents/HEAD/image/common/praiseing.gif
--------------------------------------------------------------------------------
/image/common/shopcard.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ZRH86/WeChat_couponents/HEAD/image/common/shopcard.jpg
--------------------------------------------------------------------------------
/image/common/shopcard_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ZRH86/WeChat_couponents/HEAD/image/common/shopcard_1.png
--------------------------------------------------------------------------------
/image/common/underline.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ZRH86/WeChat_couponents/HEAD/image/common/underline.png
--------------------------------------------------------------------------------
/image/common/unpraise.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ZRH86/WeChat_couponents/HEAD/image/common/unpraise.png
--------------------------------------------------------------------------------
/image/customer/btn_call.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ZRH86/WeChat_couponents/HEAD/image/customer/btn_call.png
--------------------------------------------------------------------------------
/image/mine/icon_erwei.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ZRH86/WeChat_couponents/HEAD/image/mine/icon_erwei.png
--------------------------------------------------------------------------------
/image/mine/user_icon1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ZRH86/WeChat_couponents/HEAD/image/mine/user_icon1.png
--------------------------------------------------------------------------------
/image/mine/user_icon2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ZRH86/WeChat_couponents/HEAD/image/mine/user_icon2.png
--------------------------------------------------------------------------------
/image/mine/user_icon3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ZRH86/WeChat_couponents/HEAD/image/mine/user_icon3.png
--------------------------------------------------------------------------------
/image/mine/user_icon4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ZRH86/WeChat_couponents/HEAD/image/mine/user_icon4.png
--------------------------------------------------------------------------------
/components/navigation-bar/navigation-bar.js:
--------------------------------------------------------------------------------
1 | Component({
2 | data: {},
3 | properties: {},
4 | methods: {}
5 | })
--------------------------------------------------------------------------------
/image/common/pull_refresh.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ZRH86/WeChat_couponents/HEAD/image/common/pull_refresh.gif
--------------------------------------------------------------------------------
/image/common/select_black.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ZRH86/WeChat_couponents/HEAD/image/common/select_black.png
--------------------------------------------------------------------------------
/image/customer/bot_icon1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ZRH86/WeChat_couponents/HEAD/image/customer/bot_icon1.png
--------------------------------------------------------------------------------
/image/tabbar/home_checked.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ZRH86/WeChat_couponents/HEAD/image/tabbar/home_checked.png
--------------------------------------------------------------------------------
/image/tabbar/msg_checked.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ZRH86/WeChat_couponents/HEAD/image/tabbar/msg_checked.png
--------------------------------------------------------------------------------
/image/tabbar/center_checked.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ZRH86/WeChat_couponents/HEAD/image/tabbar/center_checked.png
--------------------------------------------------------------------------------
/image/tabbar/client_checked.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ZRH86/WeChat_couponents/HEAD/image/tabbar/client_checked.png
--------------------------------------------------------------------------------
/image/tabbar/goods_checked.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ZRH86/WeChat_couponents/HEAD/image/tabbar/goods_checked.png
--------------------------------------------------------------------------------
/image/tabbar/goods_uncheck.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ZRH86/WeChat_couponents/HEAD/image/tabbar/goods_uncheck.png
--------------------------------------------------------------------------------
/image/tabbar/home_unchecked.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ZRH86/WeChat_couponents/HEAD/image/tabbar/home_unchecked.png
--------------------------------------------------------------------------------
/image/tabbar/msg_unchecked.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ZRH86/WeChat_couponents/HEAD/image/tabbar/msg_unchecked.png
--------------------------------------------------------------------------------
/image/tabbar/center_unchecked.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ZRH86/WeChat_couponents/HEAD/image/tabbar/center_unchecked.png
--------------------------------------------------------------------------------
/image/tabbar/client_unchecked.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ZRH86/WeChat_couponents/HEAD/image/tabbar/client_unchecked.png
--------------------------------------------------------------------------------
/pages/activity/activity.json:
--------------------------------------------------------------------------------
1 | {
2 | "usingComponents": {
3 | "zhuanpan": "/components/turntable/turntable"
4 | }
5 | }
--------------------------------------------------------------------------------
/pages/index/index.json:
--------------------------------------------------------------------------------
1 | {
2 | "usingComponents": {},
3 | "enablePullDownRefresh": true,
4 | "backgroundTextStyle": "dark"
5 | }
--------------------------------------------------------------------------------
/pages/mine/mine.json:
--------------------------------------------------------------------------------
1 | {
2 | "navigationBarTitleText": "我的",
3 | "enablePullDownRefresh": false,
4 | "backgroundTextStyle": "dark"
5 | }
--------------------------------------------------------------------------------
/pages/logs/logs.wxss:
--------------------------------------------------------------------------------
1 | .log-list {
2 | display: flex;
3 | flex-direction: column;
4 | padding: 40rpx;
5 | }
6 | .log-item {
7 | margin: 10rpx;
8 | }
9 |
--------------------------------------------------------------------------------
/pages/login/login.json:
--------------------------------------------------------------------------------
1 | {
2 | "navigationBarTitleText": "登录",
3 | "usingComponents": {},
4 | "enablePullDownRefresh": false,
5 | "backgroundTextStyle": "dark"
6 | }
--------------------------------------------------------------------------------
/pages/edit-card/edit-card.json:
--------------------------------------------------------------------------------
1 | {
2 | "navigationBarTitleText": "编辑名片",
3 | "usingComponents": {},
4 | "enablePullDownRefresh": false,
5 | "backgroundTextStyle": "dark"
6 | }
--------------------------------------------------------------------------------
/sitemap.json:
--------------------------------------------------------------------------------
1 | {
2 | "desc": "关于本文件的更多信息,请参考文档 https://developers.weixin.qq.com/miniprogram/dev/framework/sitemap.html",
3 | "rules": [{
4 | "action": "allow",
5 | "page": "*"
6 | }]
7 | }
--------------------------------------------------------------------------------
/pages/logs/logs.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{index + 1}}.{{key}}. {{log}}
5 |
6 |
7 |
--------------------------------------------------------------------------------
/pages/client-pool/client-pool.json:
--------------------------------------------------------------------------------
1 | {
2 | "navigationBarTitleText": "客户池",
3 | "usingComponents": {
4 | "picker-element": "../../components/picker/picker"
5 | },
6 | "enablePullDownRefresh": false,
7 | "backgroundTextStyle": "dark"
8 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules/
3 | /dist/
4 | /target/
5 | /server/dist/
6 | npm-debug.log*
7 | yarn-debug.log*
8 | yarn-error.log*
9 | package-lock.json
10 |
11 | # Editor directories and files
12 | .idea
13 | .vscode
14 | *.suo
15 | *.ntvs*
16 | *.njsproj
17 | *.sln
18 |
--------------------------------------------------------------------------------
/pages/message/message.json:
--------------------------------------------------------------------------------
1 | {
2 | "navigationBarTitleText": "消息",
3 | "usingComponents": {
4 | "scroll-y": "../../components/scroll-y/scroll-y",
5 | "turntable": "../../components/turntable/turntable"
6 | },
7 | "enablePullDownRefresh": false,
8 | "backgroundTextStyle": "dark"
9 | }
--------------------------------------------------------------------------------
/pages/goods/goods.json:
--------------------------------------------------------------------------------
1 | {
2 | "navigationBarTitleText": "商品",
3 | "usingComponents": {
4 | "tab-nav-roll": "../../components/tab-nav-roll/tab-nav-roll",
5 | "scroll-y": "../../components/scroll-y/scroll-y"
6 | },
7 | "enablePullDownRefresh": false,
8 | "backgroundTextStyle": "dark"
9 | }
--------------------------------------------------------------------------------
/pages/logs/logs.js:
--------------------------------------------------------------------------------
1 | //logs.js
2 | const util = require('../../utils/util.js')
3 |
4 | Page({
5 | data: {
6 | logs: []
7 | },
8 | onLoad: function () {
9 | // this.setData({
10 | // logs: (wx.getStorageSync('logs') || []).map(log => {
11 | // return util.formatTime(new Date(log))
12 | // })
13 | // })
14 | }
15 | })
16 |
--------------------------------------------------------------------------------
/utils/tools.js:
--------------------------------------------------------------------------------
1 | function _typeof(obj) {
2 | return Object.prototype.toString.call(obj).slice(8, -1).toLowerCase();
3 | }
4 | function isString(obj) { //是否字符串
5 | return _typeof(obj) === 'string'
6 | }
7 | function isPlainObject(obj) {
8 | return _typeof(obj) === 'object';
9 | }
10 | module.exports = {
11 | isString,
12 | isPlainObject
13 | }
--------------------------------------------------------------------------------
/pages/index/index.wxss:
--------------------------------------------------------------------------------
1 | /**index.wxss**/
2 | .userinfo {
3 | display: flex;
4 | flex-direction: column;
5 | align-items: center;
6 | }
7 |
8 | .userinfo-avatar {
9 | width: 128rpx;
10 | height: 128rpx;
11 | margin: 20rpx;
12 | border-radius: 50%;
13 | }
14 |
15 | .userinfo-nickname {
16 | color: #aaa;
17 | }
18 |
19 | .usermotto {
20 | margin-top: 200px;
21 | }
--------------------------------------------------------------------------------
/pages/home/home.json:
--------------------------------------------------------------------------------
1 | {
2 | "navigationBarTitleText": "~~~",
3 | "usingComponents": {
4 | "tab-nav-roll": "../../components/tab-nav-roll/tab-nav-roll",
5 | "scroll-y": "../../components/scroll-y/scroll-y",
6 | "login-authorization": "../../components/login-authorization/login-authorization"
7 | },
8 | "enablePullDownRefresh": false,
9 | "backgroundTextStyle": "dark"
10 | }
--------------------------------------------------------------------------------
/api/loginApi.js:
--------------------------------------------------------------------------------
1 | import request from '../utils/request'
2 |
3 | const url = 'https://www.easy-mock.com/mock'
4 |
5 | const homeApi = {
6 | login(dataObj) {
7 | console.log(dataObj)
8 | return request.networkpost({
9 | url: `${url}/5d6874546d1ba0766849df36/example/shishi`,
10 | headers: '',
11 | data: dataObj,
12 | })
13 | }
14 | }
15 |
16 | export default homeApi
--------------------------------------------------------------------------------
/pages/mine/mine.js:
--------------------------------------------------------------------------------
1 | Page({
2 | data: {
3 | entrance: [
4 | [
5 | {title: '我的名片', icon: '../../image/mine/user_icon1.png'},
6 | {title: '我的方案', icon: '../../image/mine/user_icon2.png'},
7 | {title: '我的活动', icon: '../../image/mine/user_icon4.png'}
8 | ], [
9 | {title: '我的名片', icon: '../../image/mine/user_icon1.png'},
10 | {title: '我的方案', icon: '../../image/mine/user_icon2.png'}
11 | ]
12 | ]
13 | },
14 | onShow() {
15 |
16 | }
17 | })
--------------------------------------------------------------------------------
/components/tab-nav-roll/tab-nav-roll.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 | {{item.name}}
4 |
5 |
6 |
--------------------------------------------------------------------------------
/pages/index/index.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
10 |
11 |
12 | {{motto}}
13 |
14 |
15 |
--------------------------------------------------------------------------------
/components/scroll-y/scroll-y.wxss:
--------------------------------------------------------------------------------
1 | .scroll-view {
2 | position: absolute;
3 | top: 0;
4 | bottom: 0;
5 | left: 0;
6 | right: 0;
7 | }
8 |
9 | .icon-refresh {
10 | width: 100rpx;
11 | height: 100rpx;
12 | }
13 |
14 | .pull-refresh {
15 | height: 140rpx;
16 | display: flex;
17 | justify-content: center;
18 | align-items: center;
19 | transition: all .5s ease-in-out;
20 | overflow: hidden;
21 | }
22 |
23 | .chu {
24 | height: 110rpx;
25 | }
26 |
27 | .jin {
28 | height: 0rpx;
29 | }
30 |
31 | .f-color-666 {
32 | color: #666;
33 | }
34 |
35 | .fs24 {
36 | font-size: 24rpx;
37 | }
--------------------------------------------------------------------------------
/components/navigation-bar/navigation-bar.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | {{ navigationBarTitle }}
12 |
13 |
14 |
--------------------------------------------------------------------------------
/components/scroll-y/scroll-y.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {{pull.pullText}}
6 |
7 |
8 |
9 |
10 | {{push.pullText}}
11 |
12 |
13 |
--------------------------------------------------------------------------------
/pages/login/login.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
19 |
20 |
--------------------------------------------------------------------------------
/components/login-authorization/login-authorization.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 你还未登录哦!
6 | 请先登录再进行操作
7 |
8 |
9 |
10 | 暂不登录
11 | 立即登录
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/pages/edit-card/edit-card.wxss:
--------------------------------------------------------------------------------
1 | .edit-card-title{
2 | background: #f5f5f5;
3 | padding: 0 50rpx;
4 | line-height: 3.5em;
5 | }
6 | .basic-info{
7 | display: flex;
8 | align-items: center;
9 | padding-left: 50rpx;
10 | padding-right: 50rpx;
11 | }
12 | .h90{
13 | height: 90rpx;
14 | border-bottom: 2rpx solid #f5f5f5;
15 | }
16 | .basic-info-label{
17 | width: 100rpx;
18 | color: #333;
19 | }
20 | .basic-info-input{
21 | flex: 1;
22 | }
23 | .placeholder-color{
24 | color: #ccc;
25 | }
26 | .image-list{
27 | display: flex;
28 | justify-content: space-between;
29 | flex-wrap: wrap;
30 | }
31 | .wh{
32 | width: 100%;
33 | height: 200rpx;
34 | }
35 | .save{
36 | width: 100%;
37 | height: 80rpx;
38 | line-height: 80rpx;
39 | border-radius: 10rpx;
40 | color: #fff;
41 | background: linear-gradient(to right, #ddbf93, #b08351);
42 | }
--------------------------------------------------------------------------------
/pages/activity/activity.wxml:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
22 |
--------------------------------------------------------------------------------
/project.config.json:
--------------------------------------------------------------------------------
1 | {
2 | "description": "项目配置文件",
3 | "packOptions": {
4 | "ignore": []
5 | },
6 | "setting": {
7 | "urlCheck": false,
8 | "es6": true,
9 | "postcss": true,
10 | "minified": true,
11 | "newFeature": true,
12 | "coverView": true,
13 | "autoAudits": true,
14 | "checkInvalidKey": true,
15 | "checkSiteMap": true,
16 | "uploadWithSourceMap": true,
17 | "babelSetting": {
18 | "ignore": [],
19 | "disablePlugins": [],
20 | "outputPath": ""
21 | }
22 | },
23 | "compileType": "miniprogram",
24 | "libVersion": "2.9.3",
25 | "appid": "wxc15b8be1227941c4",
26 | "projectname": "weixin",
27 | "debugOptions": {
28 | "hidedInDevtools": []
29 | },
30 | "isGameTourist": false,
31 | "simulatorType": "wechat",
32 | "simulatorPluginLibVersion": {},
33 | "condition": {
34 | "search": {
35 | "current": -1,
36 | "list": []
37 | },
38 | "conversation": {
39 | "current": -1,
40 | "list": []
41 | },
42 | "game": {
43 | "currentL": -1,
44 | "list": []
45 | },
46 | "miniprogram": {
47 | "current": -1,
48 | "list": []
49 | }
50 | }
51 | }
--------------------------------------------------------------------------------
/components/tab-nav-roll/tab-nav-roll.wxss:
--------------------------------------------------------------------------------
1 | .trigger-number{
2 | position: relative;
3 | height: 80rpx;
4 | white-space: nowrap;
5 | }
6 | .trigger-number-item{
7 | display: inline-block;
8 | text-align: center;
9 | line-height: 80rpx;
10 | padding-left: 20rpx;
11 | padding-right: 20rpx;
12 | }
13 | .trigger-number-item2{
14 | width: 50%;
15 | }
16 | .trigger-number-item3{
17 | width: 30%;
18 | }
19 | .trigger-number-item-text{
20 | position: relative;
21 | display: inline;
22 | }
23 | .tab-bottom-line{
24 | height: 4rpx;
25 | background: #bb7d41;
26 | position: absolute;
27 | left: 0;
28 | top: 75rpx;
29 | }
30 | /* .active{
31 | background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHMAAAALCAYAAABMMrJKAAAA1UlEQVRYhe2VYQ7CIAyFa+L9/+xAnsSjtM8gBQqiydRtwHjJ0kI2SPrt5V3utwU0sAD4R8RUIXFVQmVf2a19L8xpv3xPiu/hewj0bBBB0t1wI95+zNcRMT6HZyBKHHYJMcEDK8Ri/Q5c2Isg7Q+zI0CrgWBCnQEdMCoQg+tML5w58pML04+BHGLc2x+gVfcwc0dUhv8CkgtHKtCKA+05aa33BPdp34K6hHmmHFyjbmCeNQfXqHGYMwfXqEmYMwe/UzMwZw7+rkNhzhz8rw6AOXNwExHRA6NCWTurLNEkAAAAAElFTkSuQmCC) 0rpx 25rpx no-repeat;
32 | } */
--------------------------------------------------------------------------------
/components/picker/picker.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
13 |
14 |
15 |
16 |
17 | {{isUseKeywordOfShow?itemIn[keyWordsOfShow]:itemIn}}
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/pages/login/login.wxss:
--------------------------------------------------------------------------------
1 | .container {
2 | width: 100%;
3 | height: 100%;
4 | display: flex;
5 | flex-direction: column;
6 | align-items: center;
7 | justify-content: space-sbetween;
8 | }
9 |
10 | .logo {
11 | width: 240rpx;
12 | height: 240rpx;
13 | margin-top: 60rpx;
14 | }
15 |
16 | .logo image {
17 | width: 100%;
18 | height: 100%;
19 | }
20 |
21 | .user-info {
22 | width: 100%;
23 | margin-top: 80rpx;
24 | display: flex;
25 | flex-direction: column;
26 | justify-content: center;
27 | align-items: center;
28 | }
29 |
30 | .user-info-form {
31 | width: 75%;
32 | }
33 |
34 | .user-info-item {
35 | margin-bottom: 20rpx;
36 | box-sizing: border-box;
37 | }
38 |
39 | .login-title {
40 | font-size: 32rpx;
41 | color: #ccc;
42 | }
43 |
44 | input {
45 | width: 100%;
46 | height: 80rpx;
47 | border-bottom: 1rpx solid #eee;
48 | padding: 10rpx 20rpx;
49 | }
50 |
51 | .placeholder {
52 | color: #eee;
53 | font-size: 20rpx;
54 | }
55 |
56 | .login-button {
57 | margin-top: 50rpx;
58 | }
59 |
60 | button {
61 | height: 80rpx;
62 | line-height: 80rpx;
63 | background: linear-gradient(to right, #ddbf93, #b08351);
64 | color: #fff;
65 | font-size: 32rpx;
66 | }
67 |
68 | button::after {
69 | border: none;
70 | }
--------------------------------------------------------------------------------
/pages/mine/mine.wxss:
--------------------------------------------------------------------------------
1 | .container-mine {
2 | background: #f5f5f5;
3 | }
4 |
5 | .mine-info {
6 | position: relative;
7 | width: 100%;
8 | height: 360rpx;
9 | }
10 |
11 | .mine-bg {
12 | width: 100%;
13 | height: 360rpx;
14 | opacity: .4;
15 | }
16 |
17 | .mine-info-head {
18 | position: absolute;
19 | top: 0;
20 | left: 0;
21 | right: 0;
22 | height: 360rpx;
23 | background: rgba(0, 0, 0, .3);
24 | display: flex;
25 | flex-direction: column;
26 | justify-content: center;
27 | align-items: center;
28 | }
29 |
30 | .mine-info-head-image {
31 | width: 120rpx;
32 | height: 120rpx;
33 | border-radius: 500rpx;
34 | border: 4rpx solid #fff;
35 | }
36 |
37 | .qr-code {
38 | position: absolute;
39 | top: 30rpx;
40 | right: 0;
41 | width: 140rpx;
42 | height: 60rpx;
43 | }
44 | .entrance-list-item{
45 | display: flex;
46 | justify-content: space-between;
47 | align-items: center;
48 | background: #fff;
49 | border-bottom: 2rpx solid #f5f5f5;
50 | }
51 | .entrance-list-item-title{
52 | display: flex;
53 | align-items: center;
54 | }
55 | .entrance-list-item-image{
56 | width: 60rpx;
57 | height: 60rpx;
58 | }
59 | .log-out-button{
60 | width: 70%;
61 | background: linear-gradient(to right, #ddbf93, #b08351);
62 | color: #fff;
63 | }
64 | .log-out-button::after{
65 | border: none;
66 | }
--------------------------------------------------------------------------------
/components/login-authorization/login-authorization.js:
--------------------------------------------------------------------------------
1 | import {ossImgShow1} from '../../utils/util'
2 | Component({
3 | data: {
4 | loginBoxImg: ossImgShow1('Marketing/NameCard/Authorization/loginBox.png'),
5 | isshowModal: false,
6 | animationMask: {},
7 | animationDialog: {}
8 | },
9 | properties: {},
10 | methods: {
11 | showModal() {
12 | this.setData({
13 | isshowModal: true
14 | });
15 | setTimeout(() => {
16 | this._animationExport(1, 0);
17 | }, 100);
18 | },
19 | hideModal() {
20 | this._animationExport(0, -75);
21 | setTimeout(() => {
22 | this.setData({
23 | isshowModal: false
24 | });
25 | }, 200);
26 | },
27 | _animationExport(opacity, translateY) {
28 | let animation = wx.createAnimation({
29 | duration: 200,
30 | timingFunction: 'linear'
31 | });
32 | animation.opacity(opacity).step();
33 | this.setData({
34 | animationMask: animation.export()
35 | });
36 | animation.opacity(opacity).translateY(translateY).step();
37 | this.setData({
38 | animationDialog: animation.export()
39 | });
40 | },
41 | onGotUserInfo(e) {
42 | console.log(e)
43 | }
44 | }
45 | });
--------------------------------------------------------------------------------
/assets/moduleLess/login-authorization/login-authorization.less:
--------------------------------------------------------------------------------
1 | @import "../../less/style.less";
2 | .login-mask{
3 | position: fixed;
4 | top: 0;
5 | bottom: 0;
6 | .width(100%);
7 | .bg(rgba(0, 0, 0, .5));
8 | z-index: 99;
9 | .login-tip {
10 | position: absolute;
11 | top: 50%;
12 | left: 50%;
13 | transform: translate(-50%, -50%);
14 | .width(70%);
15 | .bg(#fff);
16 | display: flex;
17 | flex-direction: column;
18 | justify-content: center;
19 | align-items: center;
20 | border-radius: 10rpx;
21 | .login-tip-content {
22 | display: flex;
23 | flex-direction: column;
24 | justify-content: center;
25 | align-items: center;
26 | .padding-1(20rpx, 30rpx);
27 | .login-tip-text {
28 | .lh();
29 | .fs(30rpx);
30 | }
31 | .login-image {
32 | .width(400 rpx);
33 | }
34 | }
35 | }
36 | .login-tip-btn{
37 | display: flex;
38 | width: 100%;
39 | .button{
40 | position: relative;
41 | flex: 1;
42 | display: flex;
43 | justify-content: center;
44 | align-items: center;
45 | .heigth(80rpx);
46 | .color(#666);
47 | border: 1rpx solid #eee;
48 | button{
49 | position: absolute;
50 | left: 0;
51 | right: 0;
52 | top: 0;
53 | bottom: 0;
54 | opacity: 0;
55 | }
56 | }
57 | .active{
58 | .color(#b08351);
59 | border-left: 1rpx solid #eee;
60 | }
61 | }
62 | }
--------------------------------------------------------------------------------
/components/login-authorization/login-authorization.wxss:
--------------------------------------------------------------------------------
1 | .login-mask {
2 | position: fixed;
3 | top: 0;
4 | bottom: 0;
5 | width: 100%;
6 | background: rgba(0, 0, 0, 0.5);
7 | z-index: 99;
8 | }
9 | .login-mask .login-tip {
10 | position: absolute;
11 | top: 50%;
12 | left: 50%;
13 | transform: translate(-50%, -50%);
14 | width: 70%;
15 | background: #fff;
16 | display: flex;
17 | flex-direction: column;
18 | justify-content: center;
19 | align-items: center;
20 | border-radius: 10rpx;
21 | }
22 | .login-mask .login-tip .login-tip-content {
23 | display: flex;
24 | flex-direction: column;
25 | justify-content: center;
26 | align-items: center;
27 | padding: 20rpx 30rpx;
28 | }
29 | .login-mask .login-tip .login-tip-content .login-tip-text {
30 | line-height: 1.5em;
31 | font-size: 30rpx;
32 | }
33 | .login-mask .login-tip .login-tip-content .login-image {
34 | width: 400 rpx;
35 | }
36 | .login-mask .login-tip-btn {
37 | display: flex;
38 | width: 100%;
39 | }
40 | .login-mask .login-tip-btn .button {
41 | position: relative;
42 | flex: 1;
43 | display: flex;
44 | justify-content: center;
45 | align-items: center;
46 | height: 80rpx;
47 | color: #666;
48 | border: 1rpx solid #eee;
49 | }
50 | .login-mask .login-tip-btn .button .get-user-info {
51 | position: absolute;
52 | left: 0;
53 | right: 0;
54 | top: 0;
55 | bottom: 0;
56 | opacity: 0;
57 | }
58 | .login-mask .login-tip-btn .active {
59 | color: #b08351;
60 | border-left: 1rpx solid #eee;
61 | }
62 |
--------------------------------------------------------------------------------
/pages/message/message.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | 客户名
12 | {{item.date}}
13 |
14 | 我对商品有意向,请联系我!我对商品有意向,请联系我!我对商品有意向,请联系我!
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 | 微信提醒剩余121次点我增加
25 |
26 |
--------------------------------------------------------------------------------
/pages/index/index.js:
--------------------------------------------------------------------------------
1 | //index.js
2 | //获取应用实例
3 | const app = getApp()
4 |
5 | Page({
6 | data: {
7 | motto: 'Hello World',
8 | userInfo: {},
9 | hasUserInfo: false,
10 | canIUse: wx.canIUse('button.open-type.getUserInfo')
11 | },
12 | //事件处理函数
13 | bindViewTap: function () {
14 | wx.navigateTo({
15 | url: '../logs/logs'
16 | })
17 | },
18 | onLoad: function () {
19 | /**
20 | * 获取用户登录信息
21 | * 1、获取到-跳转home
22 | * 2、未获取到-跳转login进行登录
23 | */
24 | if(!app.globalData.hasUserInfo) {
25 | wx.switchTab({
26 | url: '../home/home'
27 | })
28 | } else {
29 | wx.reLaunch({
30 | url: '../login/login'
31 | })
32 | }
33 | // if (app.globalData.userInfo) {
34 | // this.setData({
35 | // userInfo: app.globalData.userInfo,
36 | // hasUserInfo: true
37 | // })
38 | // } else if (this.data.canIUse) {
39 | // // 由于 getUserInfo 是网络请求,可能会在 Page.onLoad 之后才返回
40 | // // 所以此处加入 callback 以防止这种情况
41 | // app.userInfoReadyCallback = res => {
42 | // this.setData({
43 | // userInfo: res.userInfo,
44 | // hasUserInfo: true
45 | // })
46 | // }
47 | // } else {
48 | // // 在没有 open-type=getUserInfo 版本的兼容处理
49 | // wx.getUserInfo({
50 | // success: res => {
51 | // app.globalData.userInfo = res.userInfo
52 | // this.setData({
53 | // userInfo: res.userInfo,
54 | // hasUserInfo: true
55 | // })
56 | // }
57 | // })
58 | // }
59 | },
60 | getUserInfo: function (e) {
61 | app.globalData.userInfo = e.detail.userInfo
62 | this.setData({
63 | userInfo: e.detail.userInfo,
64 | hasUserInfo: true
65 | })
66 | },
67 | login() {
68 | wx.navigateTo({
69 | url: '../login/login'
70 | })
71 | }
72 | })
73 |
--------------------------------------------------------------------------------
/components/picker/picker.wxss:
--------------------------------------------------------------------------------
1 | .full-box {
2 | position: fixed;
3 | left: 0;
4 | right: 0;
5 | bottom: 0;
6 | top: 0;
7 | z-index: 9999;
8 | opacity: 0;
9 | background: rgba(0, 0, 0, .4);
10 | transition: all .4s ease-in-out 0;
11 | pointer-events: none;
12 | }
13 |
14 | .full-box.cur {
15 | opacity: 1;
16 | pointer-events: auto
17 | }
18 |
19 | .modal {
20 | position: absolute;
21 | width: 100%;
22 | height: 50%;
23 | bottom: -50%;
24 | left: 0;
25 | background: transparent;
26 | transition: all .4s ease-in-out 0;
27 | }
28 |
29 | .picker {
30 | position: absolute;
31 | width: 100%;
32 | height: 235px;
33 | bottom: -235px;
34 | left: 0;
35 | background: #fff;
36 | display: flex;
37 | flex-direction: column;
38 | transition: all .4s ease-in-out 0;
39 | }
40 |
41 | .cur .picker {
42 | bottom: 0;
43 | }
44 |
45 | .cur .modal {
46 | bottom: 50%;
47 | }
48 |
49 | .picker-line {
50 | display: flex;
51 | justify-content: center;
52 | align-items: center;
53 | }
54 |
55 | .picker-header {
56 | height: 20%;
57 | box-sizing: border-box;
58 | padding: 0 20rpx;
59 | display: flex;
60 | justify-content: space-between;
61 | align-items: center;
62 | border-bottom: 1px solid #eeeeee;
63 | }
64 |
65 | .picker-header view {
66 | height: 100%;
67 | display: flex;
68 | justify-content: center;
69 | align-items: center;
70 | }
71 |
72 | .picker-header view text {
73 | font-size: 36rpx;
74 | }
75 |
76 | .picker-content {
77 | flex-grow: 1;
78 | }
79 |
80 | .line1 {
81 | overflow: hidden;
82 | text-overflow: ellipsis;
83 | white-space: nowrap;
84 | lines: 1
85 | }
--------------------------------------------------------------------------------
/assets/less/style.less:
--------------------------------------------------------------------------------
1 | //颜色
2 | @main: #b08351;
3 | @ccc: #ccc;
4 | @f5f5f5: #f5f5f5;
5 |
6 | // 盒子宽高
7 | .size(@w, @h) { width: @w; height: @h}
8 |
9 | // 高度
10 | .heigth(@h) { height: @h}
11 |
12 | // 宽度
13 | .width(@w) {width: @w;}
14 |
15 | // 行高
16 | .lh(@lh: 1.5em) { line-height: @lh;}
17 |
18 | // 内填充(上下左右)
19 | .padding(@p) { padding: @p; }
20 |
21 | // 内填充你(左右 or 上下)
22 | .padding-1(@lr: 0, @tb: 0) { padding: @lr @tb; }
23 |
24 | // 外填充(上下左右)
25 | .margin(@m) { margin: @m; }
26 |
27 | // 内填充你(左右 or 上下)
28 | .margin-1(@lr: 0, @tb: 0) { margin: @lr @tb; }
29 |
30 | // 文字、图片居中
31 | .center(text-x) {text-align: center;}
32 | .center(text-y) {display: table-cell; vertical-align: middle;}
33 |
34 | // 字体大小
35 | .fs(@fs) {font-size: @fs;}
36 |
37 | // 字体颜色,包括连接与非连接
38 | .color(@color) { color: @color;}
39 |
40 | // 背景颜色
41 | .bg(@bg) {background: @bg}
42 |
43 | // 背景渐变
44 | .bg-gradient( @c1: #eee, @c2: #999, @direction: right) { background: linear-gradient(to @direction, @c1, @c2);}
45 |
46 | // 元素垂直水平居中
47 | .center() { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);}
48 |
49 | // 文本渐变
50 | .font-gradient(@c1: #eee, @c2: #999, @direction: right){
51 | background: linear-gradient(to @direction, @c1, @c2);
52 | -webkit-background-clip: text;
53 | color: transparent;
54 | -webkit-text-fill-color: transparent;
55 | text-fill-color: transparent;
56 | }
57 |
58 | // 禁止换行,文本溢出省略号(一行)
59 | .ellipsis() {
60 | white-space: normal; // 设置文字在一行显示,不能换行
61 | word-wrap: break-word;
62 | word-break: break-all;
63 | -o-text-overflow: ellipsis;
64 | -ms-text-overflow: ellipsis;
65 | text-overflow: ellipsis; // 规定当文本溢出时,显示省略符号来代表被修剪的文本
66 | }
67 |
68 | // 文本溢出省略号显示(多行)
69 | .ellipsis-mult(@n: 3) { display: -webkit-box; overflow: hidden; -webkit-line-clamp: @n; -webkit-box-orient: vertical;}
--------------------------------------------------------------------------------
/app.json:
--------------------------------------------------------------------------------
1 | {
2 | "pages": [
3 | "pages/index/index",
4 | "pages/login/login",
5 | "pages/home/home",
6 | "pages/goods/goods",
7 | "pages/client-pool/client-pool",
8 | "pages/message/message",
9 | "pages/mine/mine",
10 | "pages/edit-card/edit-card",
11 | "pages/activity/activity"
12 | ],
13 | "window": {
14 | "backgroundTextStyle": "light",
15 | "navigationBarBackgroundColor": "#fff",
16 | "navigationBarTitleText": "WeChat",
17 | "navigationBarTextStyle": "black"
18 | },
19 | "sitemapLocation": "sitemap.json",
20 | "tabBar": {
21 | "color": "#ccc",
22 | "selectedColor": "#b08351",
23 | "borderStyle": "black",
24 | "list": [
25 | {
26 | "selectedIconPath": "image/tabbar/home_checked.png",
27 | "iconPath": "image/tabbar/home_unchecked.png",
28 | "pagePath": "pages/home/home",
29 | "text": "首页"
30 | },
31 | {
32 | "selectedIconPath": "image/tabbar/goods_checked.png",
33 | "iconPath": "image/tabbar/goods_uncheck.png",
34 | "pagePath": "pages/activity/activity",
35 | "text": "商品"
36 | },
37 | {
38 | "selectedIconPath": "image/tabbar/client_checked.png",
39 | "iconPath": "image/tabbar/client_unchecked.png",
40 | "pagePath": "pages/client-pool/client-pool",
41 | "text": "客户"
42 | },
43 | {
44 | "selectedIconPath": "image/tabbar/msg_checked.png",
45 | "iconPath": "image/tabbar/msg_unchecked.png",
46 | "pagePath": "pages/message/message",
47 | "text": "消息"
48 | },
49 | {
50 | "selectedIconPath": "image/tabbar/center_checked.png",
51 | "iconPath": "image/tabbar/center_unchecked.png",
52 | "pagePath": "pages/mine/mine",
53 | "text": "我的"
54 | }
55 | ]
56 | }
57 | }
--------------------------------------------------------------------------------
/pages/mine/mine.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | 姜欣欣
8 | (设计顾问)
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | {{value.title}}
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/components/scroll-y/scroll-y.js:
--------------------------------------------------------------------------------
1 | Component({
2 | options: {
3 | multipleSlots: true, // 在组建定义时的选项中启用多slot支持
4 | },
5 | /**
6 | * 组件的属性列表
7 | */
8 | properties: {
9 | listLength: {
10 | type: Number,
11 | value: 0
12 | },
13 | pull: {
14 | type: Object,
15 | value: {}
16 | },
17 | push: {
18 | type: Object,
19 | value: {}
20 | }
21 | },
22 | pageLifetimes: {
23 | show() {
24 | this.setData({
25 | pull: this.properties.pull,
26 | push: this.properties.push,
27 | })
28 | },
29 | },
30 | /**
31 | * 组件的初始数据
32 | */
33 | data: {
34 | pull: {},
35 | push: {},
36 | slideStart: [],
37 | moveTime: 0,
38 | },
39 | created() {
40 |
41 | },
42 | ready() {
43 |
44 | },
45 | attached() {
46 |
47 | },
48 | methods: {
49 | touchstart(e) {
50 | this.setData({
51 | slideStart: e.touches[0]
52 | })
53 | },
54 | touchmove(e) {
55 | let moveTime = new Date().getTime();
56 | if (moveTime - this.data.moveTime <= 2000) {
57 | return
58 | } else {
59 | this.setData({
60 | moveTime: moveTime
61 | })
62 | }
63 | let slideStart = this.data.slideStart;
64 | let slideMove = e.touches[0];
65 | let startX = slideStart.pageX;
66 | let startY = slideStart.pageY;
67 | let moveEndX = slideMove.pageX;
68 | let moveEndY = slideMove.pageY;
69 | let X = moveEndX - startX;
70 | let Y = moveEndY - startY;
71 | if (Math.abs(Y) > Math.abs(X) && Y > 0) {
72 | console.log("top 2 bottom");
73 | this.pullRefresh()
74 | } else if (Math.abs(Y) > Math.abs(X) && Y < 0) {
75 | console.log("bottom 2 top");
76 | this.loadMore()
77 | }
78 | },
79 | /**下拉刷新 */
80 | pullRefresh(e) {
81 | this.triggerEvent('refresh', {refresh: true}) // 将num通过参数的形式传递给父组件
82 | },
83 | /**上拉加载更多 */
84 | loadMore(e) {
85 | this.triggerEvent('toload', {toload: true}) // 将num通过参数的形式传递给父组件
86 | }
87 | }
88 | })
--------------------------------------------------------------------------------
/assets/less/message/message.less:
--------------------------------------------------------------------------------
1 | @import "../style.less";
2 |
3 | .message{
4 | .message-item {
5 | display: flex;
6 | justify-content: center;
7 | align-items: center;
8 | border-bottom: 2rpx solid #f5f5f5;
9 | .message-head {
10 | position: relative;
11 | image {
12 | width: 100rpx;
13 | height: 100rpx;
14 | border-radius: 500rpx;
15 | box-shadow: 2rpx 6rpx 10rpx #ccc;
16 | }
17 | .unread {
18 | position: absolute;
19 | top: 5rpx;
20 | right: 20rpx;
21 | width: 20rpx;
22 | height: 20rpx;
23 | border-radius: 500rpx;
24 | background: #E70012;
25 | }
26 | }
27 | .message-referral {
28 | flex: 1;
29 | width: 250rpx;
30 | .message-referral-1 {
31 | display: flex;
32 | justify-content: space-between;
33 | align-items: center;
34 | .message-referral-name {
35 | width: 310rpx;
36 | }
37 | }
38 | }
39 | .message-icon-right {
40 | width: 30rpx;
41 | display: flex;
42 | align-items: center;
43 | justify-content: flex-end;
44 | }
45 | }
46 | }
47 | .message-tip{
48 | position: fixed;
49 | right: 50rpx;
50 | bottom: 10%;
51 | .size(190rpx, 190rpx);
52 | image{
53 | .size(100%, auto);
54 | }
55 | .message-tip-text{
56 | position: absolute;
57 | top: 0;
58 | left: 0;
59 | .size(100%, 140rpx);
60 | .color(#fff);
61 | .fs(22rpx);
62 | text-align: center;
63 | display: flex;
64 | flex-direction: column;
65 | justify-content: center;
66 | align-items: center;
67 | view{
68 | display: flex;
69 | .lh(40rpx);
70 | view{
71 | .fs(28rpx);
72 | position: relative;
73 | top: -.2em;
74 | font-weight: 700;
75 | .font-gradient(orange, #00a700, bottom);
76 | }
77 | }
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/pages/edit-card/edit-card.js:
--------------------------------------------------------------------------------
1 | import WxValidate from '../../utils/WxValidate';
2 | Page({
3 | data: {
4 | basicInfo: {
5 | tel: '',
6 | post: '',
7 | weChat: '',
8 | specialPlane: '',
9 | email: '',
10 | intro: ''
11 | }
12 | },
13 | onLoad() {
14 | this.initValidate()
15 | },
16 | initValidate() {
17 | const rules = {
18 | tel: {
19 | required: true,
20 | tel: true,
21 | }, post: {
22 | required: true,
23 | }, weChat: {
24 | required: true,
25 | }, specialPlane: {
26 | required: true,
27 | }, email: {
28 | required: true,
29 | email: true
30 | }
31 | };
32 | const messages = {
33 | tel: {
34 | required: '请输入手机号',
35 | tel: '请输入正确格式手机号',
36 | }, post: {
37 | required: '请输入职位',
38 | }, weChat: {
39 | required: '请输入微信号',
40 | }, specialPlane: {
41 | required: '请输入座机号',
42 | }, email: {
43 | required: '请输入电子邮箱',
44 | email: '请输入正确格式电子邮箱',
45 | }
46 | };
47 | this.WxValidate = new WxValidate(rules, messages)
48 | },
49 | formChange(val) {
50 | let obj = {}
51 | obj[`basicInfo.${val.currentTarget.dataset.val}`]= val.detail.value
52 | this.setData(obj)
53 | },
54 | submitForm(e) {
55 | const params = e.detail.value
56 | if (!this.WxValidate.checkForm(params)) {
57 | const error = this.WxValidate.errorList[0]
58 | this.showModal(error)
59 | return false
60 | }
61 | },
62 | showModal(error) {
63 | wx.showToast({
64 | title: error.msg,
65 | icon: 'none',
66 | duration: 2000
67 | })
68 | },
69 | })
--------------------------------------------------------------------------------
/pages/goods/goods.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 | nav-{{item + 1}}
6 |
7 |
8 |
9 |
11 |
12 |
13 |
14 |
15 | {{item.title}}
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 | {{count}}
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/pages/login/login.js:
--------------------------------------------------------------------------------
1 | import WxValidate from '../../utils/WxValidate';
2 | import LoginApi from '../../api/loginApi'
3 | Page({
4 | data: {
5 | userInfo: {
6 | userName: '',
7 | password: '',
8 | }
9 | }, onLoad() {
10 | this.initValidate()
11 | }, initValidate() {
12 | const rules = {
13 | userName: {
14 | required: true,
15 | rangelength: [2, 20],
16 | },
17 | password: {
18 | required: true,
19 | rangelength: [6, 16],
20 | }
21 | }
22 | const messages = {
23 | userName: {
24 | required: '请输入账号',
25 | rangelength: '请输入2~4位字符账号'
26 | },
27 | password: {
28 | required: '请输入密码',
29 | rangelength: '请输入6~16位字符密码'
30 | },
31 |
32 | }
33 | // 创建实例对象
34 | this.WxValidate = new WxValidate(rules, messages)
35 | /**
36 | * 也可以自定义验证规则
37 | */
38 | // this.WxValidate.addMethod('assistance', (value, param) => {
39 | // return this.WxValidate.optional(value) || (value.length >= 1 && value.length <= 2)
40 | // }, '请勾选 《顺风男服务协议》')
41 | }, bindUserNameInput(e) { // 获取账号、赋值
42 | this.data.userInfo.userName = e.detail.value
43 | }, bindPasswordInput(e) { // 获取密码、赋值
44 | this.data.userInfo.password = e.detail.value
45 | }, login(params) { // 登录,暂存在本地存储
46 | LoginApi.login(params).then(res => {
47 | console.log('登录返回值', res)
48 | wx.setStorage({
49 | key: "userInfo",
50 | data: JSON.stringify(res.data)
51 | })
52 | console.log(res.data, res.data.token)
53 | wx.setStorage({
54 | key: "token",
55 | data: res.data.token
56 | })
57 | wx.switchTab({
58 | url: '../home/home'
59 | })
60 | })
61 | }, submitForm(e) {
62 | /**
63 | * 表单提交
64 | */
65 | const params = e.detail.value
66 | if (!this.WxValidate.checkForm(params)) {
67 | const error = this.WxValidate.errorList[0]
68 | this.showModal(error)
69 | return false
70 | }
71 | /**
72 | * 验证成功
73 | */
74 | this.login(params);
75 | }, showModal(error) {
76 | wx.showToast({
77 | title: error.msg,
78 | icon: 'none',
79 | duration: 2000
80 | })
81 | }, tologin() {
82 |
83 | },
84 | })
--------------------------------------------------------------------------------
/pages/message/message.wxss:
--------------------------------------------------------------------------------
1 | .message .message-item {
2 | display: flex;
3 | justify-content: center;
4 | align-items: center;
5 | border-bottom: 2rpx solid #f5f5f5;
6 | }
7 | .message .message-item .message-head {
8 | position: relative;
9 | }
10 | .message .message-item .message-head image {
11 | width: 100rpx;
12 | height: 100rpx;
13 | border-radius: 500rpx;
14 | box-shadow: 2rpx 6rpx 10rpx #ccc;
15 | }
16 | .message .message-item .message-head .unread {
17 | position: absolute;
18 | top: 5rpx;
19 | right: 20rpx;
20 | width: 20rpx;
21 | height: 20rpx;
22 | border-radius: 500rpx;
23 | background: #E70012;
24 | }
25 | .message .message-item .message-referral {
26 | flex: 1;
27 | width: 250rpx;
28 | }
29 | .message .message-item .message-referral .message-referral-1 {
30 | display: flex;
31 | justify-content: space-between;
32 | align-items: center;
33 | }
34 | .message .message-item .message-referral .message-referral-1 .message-referral-name {
35 | width: 310rpx;
36 | }
37 | .message .message-item .message-icon-right {
38 | width: 30rpx;
39 | display: flex;
40 | align-items: center;
41 | justify-content: flex-end;
42 | }
43 | .message-tip {
44 | position: fixed;
45 | right: 50rpx;
46 | bottom: 10%;
47 | width: 190rpx;
48 | height: 190rpx;
49 | }
50 | .message-tip image {
51 | width: 100%;
52 | height: auto;
53 | }
54 | .message-tip .message-tip-text {
55 | position: absolute;
56 | top: 0;
57 | left: 0;
58 | width: 100%;
59 | height: 140rpx;
60 | color: #fff;
61 | font-size: 22rpx;
62 | text-align: center;
63 | display: flex;
64 | flex-direction: column;
65 | justify-content: center;
66 | align-items: center;
67 | }
68 | .message-tip .message-tip-text view {
69 | display: flex;
70 | line-height: 40rpx;
71 | }
72 | .message-tip .message-tip-text view view {
73 | font-size: 28rpx;
74 | position: relative;
75 | top: -0.2em;
76 | font-weight: 700;
77 | background: linear-gradient(to bottom, orange, #00a700);
78 | -webkit-background-clip: text;
79 | color: transparent;
80 | -webkit-text-fill-color: transparent;
81 | text-fill-color: transparent;
82 | }
83 |
--------------------------------------------------------------------------------
/components/tab-nav-roll/tab-nav-roll.js:
--------------------------------------------------------------------------------
1 | Component({
2 | options: {
3 | addGlobalClass: true, //
4 | multipleSlots: true, // 在组建定义时的选项中启用多slot支持
5 | },
6 | /**
7 | * 组件的属性列表
8 | */
9 | properties: {
10 | tabData: { // 属性名
11 | type: Array,
12 | value: 'BBBBB'
13 | },
14 | tabType: {
15 | type: String,
16 | value: ''
17 | }
18 | },
19 | /**
20 | * 组件的初始数据
21 | */
22 | data: {
23 | activeType: '',
24 | scrollLeft: '0',
25 | lineWidth: 20,
26 | eleLeft: 0,
27 | animationLine: {}
28 | },
29 | pageLifetimes: {
30 | show() {
31 | this.data.activeType = this.properties.tabType
32 | },
33 | },
34 | created() {
35 |
36 | },
37 | ready() {
38 | this.queryElement('.active')
39 | },
40 | attached() {
41 |
42 | },
43 | methods: {
44 | queryElement(ele, X) {
45 | let _this = this;
46 | let query = wx.createSelectorQuery().in(this);
47 | query.select(ele).boundingClientRect()
48 | query.exec(function (res) {
49 | console.log(res)
50 | _this.setData({
51 | lineWidth: res[0].width,
52 | eleLeft: res[0].left
53 | })
54 | _this._animationExport(X ? X : _this.data.eleLeft - 22)
55 | })
56 | },
57 | _animationExport(X) {
58 | console.log('X->', X)
59 | let animation = wx.createAnimation({
60 | duration: 200,
61 | timingFunction: 'linear'
62 | });
63 | animation.left(X).step();
64 | this.setData({
65 | animationLine: animation.export()
66 | })
67 | console.log('animation->', this.data.animationLine)
68 | },
69 | tabChange(e) {
70 | let itemData = e.currentTarget.dataset['item']
71 | this.setData({ activeType: itemData.type })
72 | let winWidth = wx.getSystemInfoSync().windowWidth
73 | console.log(e.currentTarget.dataset['index'] * (winWidth / 4) - (winWidth / 4))
74 | this.setData({scrollLeft: `${e.currentTarget.dataset['index'] * (winWidth / 4) - (winWidth / 4)}`})
75 | this.triggerEvent('increment', {itemData: itemData}) // 将num通过参数的形式传递给父组件
76 | this.queryElement('.active', e.currentTarget.dataset['index'] * (winWidth / 4) - (winWidth / 4))
77 | }
78 | }
79 | })
80 |
--------------------------------------------------------------------------------
/utils/request.js:
--------------------------------------------------------------------------------
1 | let token = wx.getStorageSync('token')
2 | console.log('TOKEN', token)
3 |
4 | function networkpost(dataObj) {
5 | let promise = new Promise((resolve, reject) => {
6 | wx.request({
7 | url: dataObj.url,
8 | header: {
9 | 'Content-Type': 'application/json',
10 | 'token': token
11 | },
12 | data: dataObj.data,
13 | method: 'POST',
14 | success: function (res) { // 请求成功
15 | //自行处理返回结果
16 | console.log('返回结果:')
17 | console.log(res.data)
18 | // dataObj.app.netWorkData.result = res.data
19 | resolve(res.data);
20 | },
21 | fail: function (res) { // 请求失败
22 | wx.showToast({
23 | title: '网络错误,请稍后再试',
24 | icon: 'none',
25 | duration: 2000
26 | })
27 | reject({ success: false });
28 | },
29 | })
30 | });
31 | return promise;
32 | }
33 | //get请求
34 | function networkget(dataObj) {
35 | let promise = new Promise((resolve, reject) => {
36 | wx.request({
37 | url: dataObj.url,
38 | header: {
39 | 'Content-Type': 'application/json',
40 | 'token': token
41 | },
42 | data: dataObj.params,
43 | method: 'GET',
44 | success: function (res) {
45 | if (res.statusCode == 200) {
46 | resolve({ bool: true });
47 | } else {
48 | reject({ bool: false });
49 | }
50 | //返回结果自行处理
51 | console.log('返回结果:')
52 | console.log(res.data)
53 | // dataObj.app.netWorkData.result = res.data
54 | },
55 | fail: function (res) { // 请求失败
56 | wx.showToast({
57 | title: '网络错误,请稍后再试',
58 | icon: 'none',
59 | duration: 2000
60 | })
61 | reject({ bool: false });
62 | },
63 | })
64 | });
65 | return promise;
66 | }
67 | module.exports = {
68 | networkget,
69 | networkpost
70 | }
--------------------------------------------------------------------------------
/js/common.js:
--------------------------------------------------------------------------------
1 | const VerifyFactory = function (type, str) { }
2 | VerifyFactory.prototype = {
3 | character: function (str, mixLength, maxLength) { // 任意字符-限制长度
4 | if(str.length < mixLength) {
5 | return {bool: false, msg: `最少输入${mixLength}位`};
6 | } else if(str.length > maxLength) {
7 | return {bool: false, msg: `最多输入${maxLength}位`};
8 | } else {
9 | return {bool: true, msg: ``};
10 | }
11 | },
12 | email: function (str) { // 邮箱
13 | return (function () {
14 | var reg = /^(\w)+(\.\w+)*@(\w)+((\.\w{2,3}){1,3})$/;
15 | return reg.test(str);
16 | })(str);
17 | },
18 | phone: function (str) { // 手机号
19 | return (function (str) {
20 | var reg = /^1[3|4|5|7|8][0-9]{9}$/;
21 | return reg.test(str);
22 | })(str);
23 | },
24 | certno: function (str) { // 身份证号
25 | return (function () {
26 | var reg = /(^\d{15}$)|(^\d{17}([0-9]|X)$)/;
27 | return reg.test(str);
28 | })(str);
29 | },
30 | password: function (str) { // 6-16位:字母或者数字
31 | return (function () {
32 | if (str.length < 6) {
33 | return '请输入6-16位密码';
34 | } else if (str.length > 16) {
35 | return '请输入6-16位密码';
36 | } else {
37 | const reg = /^[a-zA-Z0-9]{6,16}$/;
38 | return reg.test(str) == true ? true : '请输入正确格式';
39 | }
40 | })(str);
41 | },
42 | confirmPwd: function (str1, str2) { // 确认密码
43 | return (function () {
44 | return (str1 == str2);
45 | })(str1, str2);
46 | },
47 | code: function (user, curr) { // 图片验证码
48 | return (function (user, curr) {
49 | var curr = curr.toLowerCase();
50 | var reg = /^[a-zA-Z]{4}$/;
51 | if (reg.test(user)) { // 验证码格式正确判断是否相符
52 | var usertest = user.toLowerCase();
53 | return (usertest == curr) ? 2 : 1;
54 | } else {
55 | return 0; // 验证码格式不对
56 | }
57 | })(user, curr);
58 | },
59 | dynamic: function (str) { // 动态验证码 -- 6位数字
60 | return (function () {
61 | var reg = /^[0-9]{6}$/;
62 | return reg.test(str);
63 | })(str);
64 | }
65 | }
66 |
67 | module.exports = {
68 | VerifyFactory: VerifyFactory
69 | }
--------------------------------------------------------------------------------
/components/turntable/turntable.wxss:
--------------------------------------------------------------------------------
1 | /* components/zhuanpan/zhuanpan.wxss */
2 |
3 | .canvas-container {
4 | margin: 0 auto;
5 | position: relative;
6 | display: flex;
7 | align-items: center;
8 | justify-content: center;
9 | }
10 |
11 | .img-container {
12 | margin: 0 auto;
13 | position: absolute;
14 | display: flex;
15 | align-items: center;
16 | justify-content: center;
17 | left: 0;
18 | top: 0;
19 | z-index:10;
20 | }
21 |
22 | .gb-wheel-run {
23 | box-shadow: 0 0 5rpx 0rpx rgba(0, 0, 0, 0.98);
24 | width: 500rpx;
25 | height: 500rpx;
26 | border-radius: 50%;
27 | border: 30rpx solid #f1ecec;
28 | box-sizing: border-box;
29 | position: absolute;
30 | left: 27rpx;
31 | top: -19rpx;
32 | opacity: 0.7;
33 | }
34 |
35 | .gb-wheel-content {
36 | position: relative;
37 | margin: 0 auto;
38 | z-index: 2;
39 | width: 660rpx;
40 | height: 660rpx;
41 | border-radius: 50%;
42 | border: 20rpx solid #f1ecec;
43 | box-shadow: 0 0 5rpx 0rpx rgba(0, 0, 0, 0.98);
44 | opacity: 0.7;
45 | overflow: hidden;
46 | }
47 |
48 | .canvas-list {
49 | position: absolute;
50 | left: 0;
51 | top: 0;
52 | width: inherit;
53 | height: inherit;
54 | z-index: 8;
55 | }
56 |
57 | .canvas-item2 {
58 | position: absolute;
59 | left: 0px;
60 | top: 0;
61 | width: 660rpx;
62 | height: 328rpx;
63 | color: #e4370e;
64 | font-weight: bold;
65 | transform-origin: 330rpx 330rpx;
66 | overflow: hidden;
67 | }
68 |
69 | .canvas-item2-after {
70 | position: absolute;
71 | top: 0;
72 | left: 0;
73 | width: 330rpx;
74 | height: 330rpx;
75 | transform-origin: 330rpx 330rpx;
76 | opacity: 1;
77 | }
78 |
79 | .gb-wheel-list {
80 | position: absolute;
81 | left: 0;
82 | top: 0;
83 | width: 100%;
84 | height: 100%;
85 | z-index: 9;
86 | }
87 |
88 | .gb-wheel-item {
89 | position: absolute;
90 | left: 0;
91 | top: 0;
92 | width: 100%;
93 | height: 100%;
94 | color: #fff;
95 | text-shadow: 0 1px 1px rgba(255, 255, 255, 0.6);
96 | }
97 |
98 | .gb-wheel-icontent {
99 | position: relative;
100 | display: block;
101 | padding-top: 50rpx;
102 | margin: 0 auto;
103 | text-align: center;
104 | transform-origin: 50% 328rpx;
105 | }
106 |
--------------------------------------------------------------------------------
/components/turntable/turntable.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | {{item.name}}
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/pages/message/message.js:
--------------------------------------------------------------------------------
1 | import {timeCycle} from '../../utils/util'
2 | Page({
3 | data: {
4 | messageList: [
5 | {createTime: '2019-11-12 16:33'},
6 | {createTime: '2019-11-12 14:55'},
7 | ],
8 | pull: {
9 | isLoading: false,
10 | loading: '../../image/common/pull_refresh.gif',
11 | pullText: '正在加载'
12 | },
13 | push: {
14 | isLoading: false,
15 | loading: '../../image/common/pull_refresh.gif',
16 | pullText: '-上拉加载更多-'
17 | },
18 | slideStart: [],
19 | moveTime: 0,
20 | },
21 | onLoad() {
22 | this.tranMessageList()
23 | },
24 | tranMessageList() {
25 | let data = this.data.messageList.map(item => {
26 | item.date = timeCycle(item.createTime, '/');
27 | return item;
28 | })
29 | this.setData({
30 | messageList: data
31 | })
32 | },
33 | refresh(e) {
34 | console.log('刷新', e)
35 | this.setData({
36 | 'pull.isLoading': true,
37 | 'pull.loading': '../../image/common/pull_refresh.gif',
38 | 'pull.pullText': '正在加载',
39 | })
40 | setTimeout(() => {
41 | this.setData({
42 | 'pull.loading': '../../image/common/finish.png',
43 | 'pull.pullText': '刷新完成'
44 | })
45 | this.tranMessageList()
46 | }, 4000)
47 | setTimeout(() => {
48 | this.setData({
49 | 'pull.isLoading': false,
50 | })
51 | console.log('+++++ 刷新完成 +++++')
52 | }, 6000)
53 | },
54 | toload(e) {
55 | console.log('加载', e),
56 | this.setData({
57 | 'push.isLoading': true,
58 | 'push.pullText': '正在加载',
59 | 'push.loading': '../../image/common/pull_refresh.gif',
60 | })
61 | if (this.data.messageList.length < 30) {
62 | setTimeout(() => {
63 | let data = this.data.messageList.concat([
64 | {createTime: '2019-11-12 16:33'},
65 | {createTime: '2019-11-12 14:55'},
66 | ])
67 | this.setData({
68 | messageList: data,
69 | 'push.isLoading': false,
70 | 'push.pullText': '- 上拉加载更多 -',
71 | 'push.loading': '../../image/common/finish.png',
72 | })
73 | this.tranMessageList()
74 | console.log('===== 加载完成 =====')
75 | }, 2000)
76 | }
77 | },
78 | /**跳转客户详情 */
79 | toCustomerDetails() {
80 |
81 | }
82 | })
--------------------------------------------------------------------------------
/pages/client-pool/client-pool.wxss:
--------------------------------------------------------------------------------
1 | .client-pool {
2 | position: relative;
3 | flex: 1;
4 | }
5 | .client-pool-search {
6 | position: fixed;
7 | top: 0;
8 | left: 0;
9 | width: 100%;
10 | box-sizing: border-box;
11 | background: #fff;
12 | z-index: 99;
13 | }
14 | .client-pool-search-body {
15 | display: flex;
16 | align-items: center;
17 | height: 70rpx;
18 | background: #f5f5f5;
19 | }
20 |
21 | .client-pool-search-body input {
22 | flex: 1;
23 | }
24 |
25 | .client-pool-search-condition {
26 | display: flex;
27 | justify-content: space-between;
28 | align-items: center;
29 | border-bottom: 2rpx solid #f5f5f5;
30 | }
31 |
32 | .client-pool-search-condition-left {
33 | display: flex;
34 | }
35 |
36 | .select-black {
37 | width: 24rpx;
38 | height: 12rpx;
39 | }
40 |
41 | .praise-view {
42 | display: flex;
43 | justify-content: center;
44 | align-items: center;
45 | width: 100rpx;
46 | height: 100rpx;
47 | }
48 |
49 | .praise {
50 | width: 100rpx;
51 | height: 100rpx;
52 | }
53 |
54 | .praise-mini {
55 | width: 40rpx;
56 | height: 35rpx;
57 | }
58 |
59 | .client-pool-list {
60 | position: absolute;
61 | top: 0rpx;
62 | left: 0;
63 | right: 0;
64 | bottom: 0;
65 | }
66 |
67 | .scroll-view {
68 | position: absolute;
69 | box-sizing: border-box;
70 | }
71 | .placeholder{
72 | height: 180rpx;
73 | width: 100%;
74 | }
75 | .client-pool-list-item {
76 | position: relative;
77 | width: 100%;
78 | padding-right: 130rpx;
79 | display: flex;
80 | align-items: center;
81 | border-bottom: 2rpx solid #f5f5f5;
82 | box-sizing: border-box;
83 | }
84 |
85 | .client-pool-list-item-img {
86 | width: 100rpx;
87 | }
88 |
89 | .client-pool-list-item-img image {
90 | width: 100rpx;
91 | height: 100rpx;
92 | border-radius: 500rpx;
93 | border: 4rpx solid #fff;
94 | box-shadow: 2rpx 10rpx 20rpx #ccc;
95 | }
96 |
97 | .client-pool-list-item-info {
98 | flex: 1;
99 | width: 250rpx;
100 | }
101 |
102 | .client-pool-list-item-info-data {
103 | display: flex;
104 | }
105 |
106 | .client-pool-list-item-info-time {
107 | width: 200rpx;
108 | }
109 |
110 | .client-pool-list-item-info-source {
111 | width: 220rpx;
112 | }
113 |
114 | .client-pool-list-item-status {
115 | position: absolute;
116 | right: 0;
117 | top: 0;
118 | bottom: 0;
119 | width: 130rpx;
120 | display: flex;
121 | align-items: center;
122 | justify-content: flex-end;
123 | }
124 |
125 | .client-pool-list-item-status>.status {
126 | background: #E70012;
127 | border-radius: 500rpx;
128 | }
129 |
130 | .pull-refresh {
131 | height: 140rpx;
132 | display: flex;
133 | justify-content: center;
134 | align-items: center;
135 | transition: all .5s ease-in-out;
136 | overflow: hidden;
137 | }
138 |
139 | .chu {
140 | height: 110rpx;
141 | }
142 |
143 | .jin {
144 | height: 0rpx;
145 | }
--------------------------------------------------------------------------------
/pages/home/home.js:
--------------------------------------------------------------------------------
1 | import util from '../../utils/util'
2 | import {cluesType} from '../../utils/publicData'
3 | import {toDescribe} from '../../utils/util'
4 | Page({
5 | data: {
6 | triggerNumber: [
7 | {title: '客户总量', num: '2312'},
8 | {title: '名片转发数', num: '32'},
9 | {title: '转介绍浏览人数', num: '2'},
10 | {title: '邀请新人数', num: '435'},
11 | ],
12 | tabData: cluesType,
13 | tabType: 'page_businesscard',
14 | clueData: [
15 | {createTime: '2019-11-12 16:33'},
16 | {createTime: '2019-11-12 14:55'}
17 | ],
18 | pull: {
19 | isLoading: false,
20 | loading: '../../image/common/pull_refresh.gif',
21 | pullText: '正在加载'
22 | },
23 | push: {
24 | isLoading: false,
25 | loading: '../../image/common/pull_refresh.gif',
26 | pullText: '-上拉加载更多-'
27 | },
28 | },
29 | homeTabChange(e) {
30 | this.setData({ tabType: e.detail.itemData.type })
31 | },
32 | time() {
33 | let newData = this.data.clueData.map(item => {
34 | item.time = util.timeCycle(item.createTime)
35 | return item
36 | })
37 | this.setData({ clueData: newData})
38 | },
39 | toEditCard() {
40 | wx.navigateTo({
41 | url: '/pages/edit-card/edit-card'
42 | })
43 | },
44 | refresh(e) {
45 | console.log('刷新', e)
46 | this.setData({
47 | 'pull.isLoading': true,
48 | 'pull.loading': '../../image/common/pull_refresh.gif',
49 | 'pull.pullText': '正在加载',
50 | })
51 | setTimeout(() => {
52 | this.setData({
53 | 'pull.loading': '../../image/common/finish.png',
54 | 'pull.pullText': '刷新完成'
55 | })
56 | }, 4000)
57 | setTimeout(() => {
58 | this.setData({
59 | 'pull.isLoading': false,
60 | })
61 | console.log('+++++ 刷新完成 +++++')
62 | }, 6000)
63 | },
64 | toload(e) {
65 | console.log('加载', e),
66 | this.setData({
67 | 'push.isLoading': true,
68 | 'push.pullText': '正在加载',
69 | 'push.loading': '../../image/common/pull_refresh.gif',
70 | })
71 | if (this.data.clueData.length < 30) {
72 | setTimeout(() => {
73 | let data = this.data.clueData.concat([
74 | {createTime: '2019-11-12 16:33'},
75 | {createTime: '2019-11-12 14:55'},
76 | ])
77 | this.setData({
78 | clueData: data,
79 | 'push.isLoading': false,
80 | 'push.pullText': '- 上拉加载更多 -',
81 | 'push.loading': '../../image/common/finish.png',
82 | })
83 | console.log('===== 加载完成 =====')
84 | }, 2000)
85 | }
86 | },
87 | /**跳转客户详情 */
88 | toCustomerDetails() {
89 |
90 | },
91 | click() {
92 | this.selectComponent('#login_authorization').showModal()
93 | },
94 | onShow() {
95 | this.time()
96 | }
97 | })
--------------------------------------------------------------------------------
/utils/publicData.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 来源
3 | */
4 | const sourceData = [
5 | { key: '', label: '全部' },
6 | { key: 'search', label: '搜索' },
7 | { key: 'scan_designer_card', label: '扫设计顾问名片' },
8 | { key: 'scan_designer_ab', label: ' 扫设计顾问ab券活动码' },
9 | { key: 'scan_openid_ab ', label: '扫用户ab券活动码' },
10 | { key: 'share_imagetext ', label: '分享方案页面' },
11 | { key: 'share_card_designer ', label: '分享设计顾问名片' },
12 | { key: 'share_ab ', label: '分享ab券的活动页面' },
13 | { key: 'share_other ', label: '分享其他页面' }
14 | ];
15 | /**
16 | * 新旧用户
17 | */
18 | const cateData = [
19 | {key: '', label: '全部'},
20 | {key: '0', label: '新用户'},
21 | {key: '1', label: '有联系方式'},
22 | ];
23 | /**
24 | * 线索类型
25 | */
26 | const cluesType = [
27 | {name: '全部', type: ''},
28 | {name: '查看名片', type: 'page_businesscard'},
29 | {name: '复制微信', type: 'btn_businesscard_copywechat'},
30 | {name: '保存电话', type: 'btn_businesscard_savephonenumber'},
31 | {name: '收藏方案', type: 'btn_plan_like'},
32 | {name: '找你设计', type: 'btn_plan_design'},
33 | {name: '拨打手机', type: 'btn_businesscard_mobilephone'},
34 | {name: '拨打座机', type: 'btn_businesscard_telephone'},
35 | {name: '复制邮箱', type: 'btn_businesscard_copyemail'},
36 | {name: '分享方案', type: 'btn_planlist_share'},
37 | {name: '分享名片', type: 'btn_businesscard_sharecard'},
38 | {name: 'AB券转发', type: 'btn_invitedgift_invite'},
39 | ];
40 | /**
41 | * 商品列表
42 | */
43 | const goodsList = [
44 | {title: '单人沙发', like: 1, goodsImg: 'http://mkmarketing.oss-cn-hangzhou.aliyuncs.com/Marketing/namecard/product/image/EAD670176 D1882/common/SM_IMAGE/SM_001.jpg'},
45 | {title: '双人沙发', like: 0, goodsImg: 'http://mkmarketing.oss-cn-hangzhou.aliyuncs.com/Marketing/namecard/product/image/11M9007U212301/common/SM_IMAGE/SM_001.jpg?x-oss-process=image/resize,m_pad,h_500,w_500,color_FFFFFF'},
46 | {title: '早安床头柜', like: 0, goodsImg: 'http://mkmarketing.oss-cn-hangzhou.aliyuncs.com/Marketing/namecard/product/image/CACLA-016-063/common/SM_IMAGE/SM_001.jpg'},
47 | {title: '单人沙发', like: 1, goodsImg: 'http://mkmarketing.oss-cn-hangzhou.aliyuncs.com/Marketing/namecard/product/image/EAD670176 D1882/common/SM_IMAGE/SM_001.jpg'},
48 | {title: '双人沙发', like: 0, goodsImg: 'http://mkmarketing.oss-cn-hangzhou.aliyuncs.com/Marketing/namecard/product/image/11M9007U212301/common/SM_IMAGE/SM_001.jpg?x-oss-process=image/resize,m_pad,h_500,w_500,color_FFFFFF'},
49 | {title: '早安床头柜', like: 0, goodsImg: 'http://mkmarketing.oss-cn-hangzhou.aliyuncs.com/Marketing/namecard/product/image/CACLA-016-063/common/SM_IMAGE/SM_001.jpg'},
50 | {title: '单人沙发', like: 0, goodsImg: 'http://mkmarketing.oss-cn-hangzhou.aliyuncs.com/Marketing/namecard/product/image/EAD670176 D1882/common/SM_IMAGE/SM_001.jpg'},
51 | {title: '双人沙发', like: 1, goodsImg: 'http://mkmarketing.oss-cn-hangzhou.aliyuncs.com/Marketing/namecard/product/image/11M9007U212301/common/SM_IMAGE/SM_001.jpg?x-oss-process=image/resize,m_pad,h_500,w_500,color_FFFFFF'},
52 | {title: '早安床头柜', like: 0, goodsImg: 'http://mkmarketing.oss-cn-hangzhou.aliyuncs.com/Marketing/namecard/product/image/CACLA-016-063/common/SM_IMAGE/SM_001.jpg'}
53 | ];
54 |
55 | module.exports = {
56 | sourceData,
57 | cateData,
58 | cluesType,
59 | goodsList
60 | };
--------------------------------------------------------------------------------
/utils/util.js:
--------------------------------------------------------------------------------
1 | const formatTime = date => {
2 | const year = date.getFullYear()
3 | const month = date.getMonth() + 1
4 | const day = date.getDate()
5 | const hour = date.getHours()
6 | const minute = date.getMinutes()
7 | const second = date.getSeconds()
8 |
9 | return [year, month, day].map(formatNumber).join('/') + ' ' + [hour, minute, second].map(formatNumber).join(':')
10 | }
11 |
12 | const formatNumber = n => {
13 | n = n.toString()
14 | return n[1] ? n : '0' + n
15 | }
16 |
17 | const timeCycle = (d, sign1 = '-') => {
18 | const time = d.replace(/\-/g, '/');
19 | const date = new Date(time);
20 | const nowDate = new Date();
21 | const dateTime = date.getTime();
22 | const nowDateTime = nowDate.getTime();
23 | const year = date.getFullYear()
24 | const month = date.getMonth() + 1
25 | const day = date.getDate()
26 | const hour = date.getHours()
27 | const minute = date.getMinutes()
28 | const second = date.getSeconds()
29 | if (nowDateTime - dateTime < 300000) {
30 | return '刚刚'
31 | } else if (nowDateTime - dateTime < 86400000) {
32 | return `${hour}:${minute}`
33 | } else if (nowDateTime - dateTime < 2592000000) {
34 | return `${month}${sign1}${day} ${hour}:${minute}`
35 | } else {
36 | return `${year}${sign1}${month}${sign1}${day} ${hour}:${minute}`
37 | }
38 | }
39 | /**转换时间为多久前 */
40 | const howLongAgo = d => {
41 | const time = d.replace(/\-/g, '/')
42 | const date = new Date(time);
43 | const nowDate = new Date();
44 | const oldTimestamp = date.getTime();
45 | const nowTimestamp = nowDate.getTime();
46 | const minute = 60 * 1000; // 1分钟
47 | const hour = 60 * minute; // 1小时
48 | const day = 24 * hour; // 1天
49 | const month = 31 * day; // 月
50 | const year = 12 * month; // 年
51 | const timeDiff = nowTimestamp - oldTimestamp;
52 | let r = 0;
53 | if (timeDiff > year) {
54 | r = (timeDiff / year);
55 | return r.toFixed(0) + "年前";
56 | }
57 | if (timeDiff > month) {
58 | r = (timeDiff / month);
59 | return r.toFixed(0) + "个月前";
60 | }
61 | if (timeDiff > day) {
62 | r = (timeDiff / day);
63 | return r.toFixed(0) + "天前";
64 | }
65 | if (timeDiff > hour) {
66 | r = (timeDiff / hour);
67 | return r.toFixed(0) + "小时前";
68 | }
69 | if (timeDiff > minute) {
70 | r = (timeDiff / minute);
71 | return r.toFixed(0) + "分钟前";
72 | }
73 | return "刚刚";
74 | }
75 | /**
76 | * 数组对象过滤
77 | * @param {array} array 需要转换的数组对象
78 | * @param {code} code 要转换的值
79 | * @param {key} key 判断的属性
80 | * @param {value} value 返回的属性
81 | */
82 | const toDescribe = (array = [], code = "", key = "", value = "") => {
83 | for (let i = 0; i <= array.length; i++) {
84 | if (array[i]) {
85 | if (array[i][key] === code) {
86 | return array[i][value]
87 | }
88 | }
89 | }
90 | }
91 |
92 | /**
93 | * oss路径拼接
94 | * @url 需要拼接的路径
95 | */
96 | const ossImgShow1 = (url) => {
97 | return 'https://mkmarketing-oss.markorhome.com/' + url + "?x-oss-process=style/mk_sm&r=" + new Date().getTime();
98 | }
99 |
100 | module.exports = {
101 | formatTime: formatTime,
102 | formatNumber: formatNumber,
103 | timeCycle: timeCycle,
104 | howLongAgo: howLongAgo,
105 | toDescribe: toDescribe,
106 | ossImgShow1: ossImgShow1
107 | }
108 |
--------------------------------------------------------------------------------
/assets/less/goods/goods.less:
--------------------------------------------------------------------------------
1 | @import "../style.less";
2 | .goods-container{
3 | display: flex;
4 | .goods-nav{
5 | position: absolute;
6 | left: 0;
7 | right: 150rpx;
8 | top: 0;
9 | bottom: 0;
10 | .size(150rpx, 100%);
11 | border-right: 2rpx solid #eee;
12 | .goods-nav-item{
13 | .lh(3em);
14 | .fs(26rpx);
15 | .color(#999);
16 | display: flex;
17 | .goods-nav-item-left{
18 | .size(10rpx, 3em);
19 | }
20 | }
21 | .goods-nav-item-active{
22 | .goods-nav-item-left{
23 | .bg-gradient(#ddbf93, #b08351);
24 | }
25 | .bg(rgba(176, 131, 81, .5));
26 | .color(#fff);
27 | }
28 | }
29 | .goods {
30 | flex: 1;
31 | display: flex;
32 | flex-wrap: wrap;
33 | position: absolute;
34 | top: 0;
35 | bottom: 0;
36 | right: 0;
37 | left: 150rpx;
38 | .scroll-view {
39 | .goods-item {
40 | width: 50%;
41 | display: inline-block;
42 | box-sizing: border-box;
43 | .goods-item-img{
44 | display: flex;
45 | justify-content: center;
46 | .goods-img {
47 | .size(95%, auto);
48 | }
49 | }
50 | .goods-shop {
51 | display: flex;
52 | justify-content: space-between;
53 | align-items: center;
54 | .shop-card {
55 | .size(60rpx, 60rpx)
56 | }
57 | .red{
58 | .color(red);
59 | }
60 | }
61 | }
62 | }
63 | }
64 | .bus {
65 | width: 100rpx;
66 | height: 100rpx;
67 | position: fixed;
68 | left: 80%;
69 | top: 80%;
70 | background: rgba(120, 188, 255, 0.6);
71 | border: 1rpx solid rgba(0, 116, 255, 0.61);
72 | border-radius: 50%;
73 | image {
74 | width: 80rpx;
75 | height: 80rpx;
76 | position: absolute;
77 | left: 50%;
78 | top: 50%;
79 | transform: translate(-50%, -50%);
80 | }
81 | .count {
82 | display: block;
83 | height: 40rpx;
84 | line-height: 40rpx;
85 | font-size: 24rpx;
86 | background: #ff4611;
87 | padding: 0 12rpx;
88 | border-radius: 20rpx;
89 | color: #fff;
90 | position: absolute;
91 | left: 68rpx;
92 | top: 0;
93 | }
94 | }
95 | .scale {
96 | background: rgba(120, 188, 255, 0.3);
97 | border: 1rpx solid rgba(0, 116, 255, 0.4);
98 | image {
99 | transform: scale(1.2);
100 | }
101 | }
102 | .good_box {
103 | width: 80rpx;
104 | height: 80rpx;
105 | position: fixed;
106 | border-radius: 50%;
107 | overflow: hidden;
108 | left: 50%;
109 | top: 50%;
110 | z-index: +99;
111 | border: 2rpx solid rgba(0, 116, 255, 0.61);
112 | background: rgba(120, 188, 255, 0.2);
113 | image {
114 | display: block;
115 | width: 100%;
116 | height: 100%;
117 | }
118 | }
119 | .goods_hover {
120 | transform: scale(0.95);
121 | }
122 | }
123 |
124 | @keyframes mymove {
125 | 0% {
126 | transform: rotate(50deg);
127 | }
128 | 25% {
129 | transform: rotate(100deg);
130 | }
131 | 50% {
132 | transform: rotate(150deg);
133 | }
134 | 75% {
135 | transform: rotate(200deg);
136 | }
137 | 100% {
138 | transform: rotate(360deg);
139 | }
140 | }
--------------------------------------------------------------------------------
/pages/goods/goods.wxss:
--------------------------------------------------------------------------------
1 | .goods-container {
2 | display: flex;
3 | }
4 | .goods-container .goods-nav {
5 | position: absolute;
6 | left: 0;
7 | right: 150rpx;
8 | top: 0;
9 | bottom: 0;
10 | width: 150rpx;
11 | height: 100%;
12 | border-right: 2rpx solid #eee;
13 | }
14 | .goods-container .goods-nav .goods-nav-item {
15 | line-height: 3em;
16 | font-size: 26rpx;
17 | color: #999;
18 | display: flex;
19 | }
20 | .goods-container .goods-nav .goods-nav-item .goods-nav-item-left {
21 | width: 10rpx;
22 | height: 3em;
23 | }
24 | .goods-container .goods-nav .goods-nav-item-active {
25 | background: rgba(176, 131, 81, 0.5);
26 | color: #fff;
27 | }
28 | .goods-container .goods-nav .goods-nav-item-active .goods-nav-item-left {
29 | background: linear-gradient(to right, #ddbf93, #b08351);
30 | }
31 | .goods-container .goods {
32 | flex: 1;
33 | display: flex;
34 | flex-wrap: wrap;
35 | position: absolute;
36 | top: 0;
37 | bottom: 0;
38 | right: 0;
39 | left: 150rpx;
40 | }
41 | .goods-container .goods .scroll-view .goods-item {
42 | width: 50%;
43 | display: inline-block;
44 | box-sizing: border-box;
45 | }
46 | .goods-container .goods .scroll-view .goods-item .goods-item-img {
47 | display: flex;
48 | justify-content: center;
49 | }
50 | .goods-container .goods .scroll-view .goods-item .goods-item-img .goods-img {
51 | width: 95%;
52 | height: auto;
53 | }
54 | .goods-container .goods .scroll-view .goods-item .goods-shop {
55 | display: flex;
56 | justify-content: space-between;
57 | align-items: center;
58 | }
59 | .goods-container .goods .scroll-view .goods-item .goods-shop .shop-card {
60 | width: 60rpx;
61 | height: 60rpx;
62 | }
63 | .goods-container .goods .scroll-view .goods-item .goods-shop .red {
64 | color: red;
65 | }
66 | .goods-container .bus {
67 | width: 100rpx;
68 | height: 100rpx;
69 | position: fixed;
70 | left: 80%;
71 | top: 80%;
72 | background: rgba(120, 188, 255, 0.6);
73 | border: 1rpx solid rgba(0, 116, 255, 0.61);
74 | border-radius: 50%;
75 | }
76 | .goods-container .bus image {
77 | width: 80rpx;
78 | height: 80rpx;
79 | position: absolute;
80 | left: 50%;
81 | top: 50%;
82 | transform: translate(-50%, -50%);
83 | }
84 | .goods-container .bus .count {
85 | display: block;
86 | height: 40rpx;
87 | line-height: 40rpx;
88 | font-size: 24rpx;
89 | background: #ff4611;
90 | padding: 0 12rpx;
91 | border-radius: 20rpx;
92 | color: #fff;
93 | position: absolute;
94 | left: 68rpx;
95 | top: 0;
96 | }
97 | .goods-container .scale {
98 | background: rgba(120, 188, 255, 0.3);
99 | border: 1rpx solid rgba(0, 116, 255, 0.4);
100 | }
101 | .goods-container .scale image {
102 | transform: scale(1.2);
103 | }
104 | .goods-container .good_box {
105 | width: 80rpx;
106 | height: 80rpx;
107 | position: fixed;
108 | border-radius: 50%;
109 | overflow: hidden;
110 | left: 50%;
111 | top: 50%;
112 | z-index: 99;
113 | border: 2rpx solid rgba(0, 116, 255, 0.61);
114 | background: rgba(120, 188, 255, 0.2);
115 | }
116 | .goods-container .good_box image {
117 | display: block;
118 | width: 100%;
119 | height: 100%;
120 | }
121 | .goods-container .goods_hover {
122 | transform: scale(0.95);
123 | }
124 | @keyframes mymove {
125 | 0% {
126 | transform: rotate(50deg);
127 | }
128 | 25% {
129 | transform: rotate(100deg);
130 | }
131 | 50% {
132 | transform: rotate(150deg);
133 | }
134 | 75% {
135 | transform: rotate(200deg);
136 | }
137 | 100% {
138 | transform: rotate(360deg);
139 | }
140 | }
141 |
--------------------------------------------------------------------------------
/pages/home/home.wxss:
--------------------------------------------------------------------------------
1 | .home-container {
2 | position: absolute;
3 | top: 0;
4 | bottom: 0;
5 | left: 0;
6 | right: 0;
7 | background: #f5f5f5 url('https://mkmarketing.oss-cn-hangzhou.aliyuncs.com/Marketing/NameCard/source/image/sales_banner.jpg') no-repeat;
8 | background-size: 100% auto;
9 | overflow: hidden;
10 | }
11 |
12 | .home {
13 | /* height: 200rpx; */
14 | display: flex;
15 | flex-direction: column;
16 | }
17 |
18 | .home-header {
19 | width: 100%;
20 | height: 350rpx;
21 | }
22 |
23 | .home-header-item {
24 | width: 90%;
25 | height: 320rpx;
26 | margin-top: 40rpx;
27 | background: #fff;
28 | border-radius: 10rpx;
29 | box-sizing: border-box;
30 | box-shadow: 2rpx 10rpx 20rpx #ccc;
31 | }
32 |
33 | .user-info {
34 | position: relative;
35 | display: flex;
36 | }
37 |
38 | .user-info-head {
39 | box-sizing: border-box;
40 | }
41 |
42 | .user-info-head image {
43 | width: 130rpx;
44 | height: 130rpx;
45 | border-radius: 500rpx;
46 | border: 4rpx solid #fff;
47 | box-shadow: 2rpx 10rpx 20rpx #ccc;
48 | }
49 |
50 | .user-name {
51 | line-height: 80rpx;
52 | }
53 |
54 | .user-post {
55 | line-height: 40rpx;
56 | -webkit-background-clip: text;
57 | -webkit-text-fill-color: transparent;
58 | background-image: linear-gradient(90deg, #ddbf93, #b08351);
59 | }
60 |
61 | .edit-info {
62 | width: 150rpx;
63 | height: 50rpx;
64 | position: absolute;
65 | top: -30rpx;
66 | right: -30rpx;
67 | }
68 |
69 | .trigger-number {
70 | display: flex;
71 | border-top: 2rpx solid #eee;
72 | }
73 |
74 | .trigger-number-item {
75 | flex: 1;
76 | }
77 |
78 | .home-shortcut {
79 | display: flex;
80 | }
81 |
82 | .home-shortcut-item {
83 | flex: 1;
84 | }
85 |
86 | .home-shortcut-item image {
87 | width: 100%;
88 | height: 110rpx;
89 | }
90 |
91 | .home-clue-nav {
92 | position: relative;
93 | border-bottom: 2rpx solid #ccc;
94 | }
95 |
96 | .scroll-view {
97 | position: absolute;
98 | top: 570rpx;
99 | bottom: 0;
100 | width: 100%;
101 | flex: 1;
102 | }
103 |
104 | .home-clue-list-item {
105 | display: flex;
106 | background: #fff;
107 | border-radius: 10rpx;
108 | box-shadow: 2rpx 10rpx 20rpx #eee;
109 | }
110 |
111 | .home-clue-list-item-img image {
112 | width: 100rpx;
113 | height: 100rpx;
114 | border-radius: 500rpx;
115 | border: 3rpx solid #fff;
116 | box-shadow: 2rpx 10rpx 20rpx #eee;
117 | box-sizing: border-box;
118 | }
119 |
120 | .home-clue-list-item-info {
121 | position: relative;
122 | flex: 1;
123 | }
124 |
125 | .icon-right {
126 | position: absolute;
127 | top: 50%;
128 | right: 10rpx;
129 | transform: translateY(-50%);
130 | width: 15rpx;
131 | height: 30rpx;
132 | }
133 |
134 | .home-clue-list-item-info-msg {
135 | line-height: 2em;
136 | }
137 |
138 | .shishi-bg {
139 | width: 100%;
140 | height: 400rpx;
141 | position: relative;
142 | }
143 |
144 | .shishi-bg::after {
145 | content: '';
146 | width: 120%;
147 | height: 300rpx;
148 | position: absolute;
149 | left: 50%;
150 | top: 0;
151 | transform: translateX(-50%);
152 | border-radius: 0 0 20% 20%;
153 | background: rgb(116, 116, 255);
154 | }
155 |
156 | .shishi-bg-li {
157 | position: absolute;
158 | top: 50rpx;
159 | left: 50%;
160 | transform: translateX(-50%);
161 | width: 85%;
162 | height: 350rpx;
163 | background: blue;
164 | border-radius: 30rpx;
165 | z-index: 999;
166 | }
--------------------------------------------------------------------------------
/pages/edit-card/edit-card.wxml:
--------------------------------------------------------------------------------
1 |
2 |
61 |
--------------------------------------------------------------------------------
/pages/home/home.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 | {{item.time}}
46 |
47 |
48 |
49 |
50 |
51 |
52 | 客户名
53 | 查看了你的名片,沟通从此刻开始。
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
--------------------------------------------------------------------------------
/app.js:
--------------------------------------------------------------------------------
1 | //app.js
2 | App({
3 | onLaunch () {
4 | // 展示本地存储能力
5 | var logs = wx.getStorageSync('logs') || []
6 | logs.unshift(Date.now())
7 | wx.setStorageSync('logs', logs)
8 | this.screenSize();
9 | // 登录
10 | wx.login({
11 | success: res => {
12 | // 发送 res.code 到后台换取 openId, sessionKey, unionId
13 | }
14 | })
15 | // 获取用户信息
16 | wx.getSetting({
17 | success: res => {
18 | if (res.authSetting['scope.userInfo']) {
19 | // 已经授权,可以直接调用 getUserInfo 获取头像昵称,不会弹框
20 | wx.getUserInfo({
21 | success: res => {
22 | // 可以将 res 发送给后台解码出 unionId
23 | this.globalData.userInfo = res.userInfo
24 | // 由于 getUserInfo 是网络请求,可能会在 Page.onLoad 之后才返回
25 | // 所以此处加入 callback 以防止这种情况
26 | if (this.userInfoReadyCallback) {
27 | this.userInfoReadyCallback(res)
28 | }
29 | }
30 | })
31 | }
32 | }
33 | }),
34 | wx.getStorage({
35 | key: 'userInfo',
36 | success: (res) => {
37 | if (res.data) {
38 | this.globalData.userInfo = res.data
39 | this.globalData.hasUserInfo = true
40 | }
41 | }
42 | })
43 | },
44 | screenSize () {
45 | var that = this;
46 | // 获取屏幕宽高
47 | wx.getSystemInfo({
48 | success(res) {
49 | var ww = res.windowWidth;
50 | var hh = res.windowHeight;
51 | that.globalData.ww = ww;
52 | that.globalData.hh = hh;
53 | }
54 | })
55 | },
56 | bezier (points, times) {
57 | // 0、以3个控制点为例,点A,B,C,AB上设置点D,BC上设置点E,DE连线上设置点F,则最终的贝塞尔曲线是点F的坐标轨迹。
58 | // 1、计算相邻控制点间距。
59 | // 2、根据完成时间,计算每次执行时D在AB方向上移动的距离,E在BC方向上移动的距离。
60 | // 3、时间每递增100ms,则D,E在指定方向上发生位移, F在DE上的位移则可通过AD/AB = DF/DE得出。
61 | // 4、根据DE的正余弦值和DE的值计算出F的坐标。
62 | // 邻控制AB点间距
63 | var bezier_points = [];
64 | var points_D = [];
65 | var points_E = [];
66 | const DIST_AB = Math.sqrt(Math.pow(points[1]['x'] - points[0]['x'], 2) + Math.pow(points[1]['y'] - points[0]['y'], 2));
67 | // 邻控制BC点间距
68 | const DIST_BC = Math.sqrt(Math.pow(points[2]['x'] - points[1]['x'], 2) + Math.pow(points[2]['y'] - points[1]['y'], 2));
69 | // D每次在AB方向上移动的距离
70 | const EACH_MOVE_AD = DIST_AB / times;
71 | // E每次在BC方向上移动的距离
72 | const EACH_MOVE_BE = DIST_BC / times;
73 | // 点AB的正切
74 | const TAN_AB = (points[1]['y'] - points[0]['y']) / (points[1]['x'] - points[0]['x']);
75 | // 点BC的正切
76 | const TAN_BC = (points[2]['y'] - points[1]['y']) / (points[2]['x'] - points[1]['x']);
77 | // 点AB的弧度值
78 | const RADIUS_AB = Math.atan(TAN_AB);
79 | // 点BC的弧度值
80 | const RADIUS_BC = Math.atan(TAN_BC);
81 | // 每次执行
82 | for (var i = 1; i <= times; i++) {
83 | // AD的距离
84 | var dist_AD = EACH_MOVE_AD * i;
85 | // BE的距离
86 | var dist_BE = EACH_MOVE_BE * i;
87 | // D点的坐标
88 | var point_D = {};
89 | point_D['x'] = dist_AD * Math.cos(RADIUS_AB) + points[0]['x'];
90 | point_D['y'] = dist_AD * Math.sin(RADIUS_AB) + points[0]['y'];
91 | points_D.push(point_D);
92 | // E点的坐标
93 | var point_E = {};
94 | point_E['x'] = dist_BE * Math.cos(RADIUS_BC) + points[1]['x'];
95 | point_E['y'] = dist_BE * Math.sin(RADIUS_BC) + points[1]['y'];
96 | points_E.push(point_E);
97 | // 此时线段DE的正切值
98 | var tan_DE = (point_E['y'] - point_D['y']) / (point_E['x'] - point_D['x']);
99 | // tan_DE的弧度值
100 | var radius_DE = Math.atan(tan_DE);
101 | // 地市DE的间距
102 | var dist_DE = Math.sqrt(Math.pow((point_E['x'] - point_D['x']), 2) + Math.pow((point_E['y'] - point_D['y']), 2));
103 | // 此时DF的距离
104 | var dist_DF = (dist_AD / DIST_AB) * dist_DE;
105 | // 此时DF点的坐标
106 | var point_F = {};
107 | point_F['x'] = dist_DF * Math.cos(radius_DE) + point_D['x'];
108 | point_F['y'] = dist_DF * Math.sin(radius_DE) + point_D['y'];
109 | bezier_points.push(point_F);
110 | }
111 | return {
112 | 'bezier_points': bezier_points
113 | };
114 | },
115 | globalData: {
116 | userInfo: null,
117 | hasUserInfo: false
118 | }
119 | })
--------------------------------------------------------------------------------
/pages/client-pool/client-pool.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
22 |
23 |
24 | 来源
25 |
26 |
31 |
32 |
33 |
34 |
35 | 分类
36 |
37 |
38 |
39 |
40 |
41 | 共108名顾客
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 | {{pull.pullText}}
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 | wang...
58 |
59 | {{item.date}}活跃
60 | 来源: 你是扫码进来的吗
61 |
62 |
63 |
64 | New
65 | 手机号
66 |
67 |
68 |
69 |
70 |
71 |
72 | {{push.pullText}}
73 |
74 |
75 |
76 |
--------------------------------------------------------------------------------
/app.wxss:
--------------------------------------------------------------------------------
1 | /**app.wxss**/
2 | @import "./assets/wxss/icon.wxss";
3 | page {
4 | height: 100%;
5 | /* background-color:rgb(220, 253, 171); */
6 | }
7 |
8 | .container {
9 | width: 100%;
10 | height: 100%;
11 | display: flex;
12 | flex-direction: column;
13 | /* align-items: center; */
14 | /* justify-content: space-sbetween; */
15 | /* padding: 200rpx 0; */
16 | box-sizing: border-box;
17 | }
18 |
19 | .fs16 {
20 | font-size: 16rpx;
21 | }
22 |
23 | .fs20 {
24 | font-size: 20rpx;
25 | }
26 |
27 | .fs22 {
28 | font-size: 22rpx;
29 | }
30 |
31 | .fs24 {
32 | font-size: 24rpx;
33 | }
34 |
35 | .fs26 {
36 | font-size: 26rpx;
37 | }
38 |
39 | .fs28 {
40 | font-size: 28rpx;
41 | }
42 |
43 | .fs30 {
44 | font-size: 30rpx;
45 | }
46 |
47 | .fs32 {
48 | font-size: 32rpx;
49 | }
50 |
51 | .fs34 {
52 | font-size: 34rpx;
53 | }
54 |
55 | .fs36 {
56 | font-size: 36rpx;
57 | }
58 |
59 | .fs38 {
60 | font-size: 38rpx;
61 | }
62 |
63 | .fs40 {
64 | font-size: 40rpx;
65 | }
66 |
67 | .f-color-fff {
68 | color: #fff;
69 | }
70 |
71 | .f-color-ccc {
72 | color: #ccc;
73 | }
74 |
75 | .f-color-666 {
76 | color: #666;
77 | }
78 |
79 | .f-color-999 {
80 | color: #999;
81 | }
82 |
83 | .f-color-f5 {
84 | color: #f5f5f5;
85 | }
86 |
87 | .f-color-main {
88 | color: #b08351;
89 | }
90 |
91 | .pt6 {
92 | padding-top: 6rpx;
93 | }
94 |
95 | .pr6 {
96 | padding-right: 6rpx;
97 | }
98 |
99 | .pb6 {
100 | padding-bottom: 6rpx;
101 | }
102 |
103 | .pl6 {
104 | padding-left: 6rpx;
105 | }
106 |
107 | .pt10 {
108 | padding-top: 10rpx;
109 | }
110 |
111 | .pr10 {
112 | padding-right: 10rpx;
113 | }
114 |
115 | .pb10 {
116 | padding-bottom: 10rpx;
117 | }
118 |
119 | .pl10 {
120 | padding-left: 10rpx;
121 | }
122 |
123 | .pt30 {
124 | padding-top: 30rpx;
125 | }
126 |
127 | .pr30 {
128 | padding-right: 30rpx;
129 | }
130 |
131 | .pb30 {
132 | padding-bottom: 30rpx;
133 | }
134 |
135 | .pl30 {
136 | padding-left: 30rpx;
137 | }
138 |
139 | .pt20 {
140 | padding-top: 20rpx;
141 | }
142 |
143 | .pr20 {
144 | padding-right: 20rpx;
145 | }
146 |
147 | .pb20 {
148 | padding-bottom: 20rpx;
149 | }
150 |
151 | .pl20 {
152 | padding-left: 20rpx;
153 | }
154 |
155 | .pt40 {
156 | padding-top: 40rpx;
157 | }
158 |
159 | .pr40 {
160 | padding-right: 40rpx;
161 | }
162 |
163 | .pb40 {
164 | padding-bottom: 40rpx;
165 | }
166 |
167 | .pl40 {
168 | padding-left: 40rpx;
169 | }
170 |
171 | .mt10 {
172 | margin-top: 10rpx;
173 | }
174 |
175 | .mr10 {
176 | margin-right: 10rpx;
177 | }
178 |
179 | .mb10 {
180 | margin-bottom: 10rpx;
181 | }
182 |
183 | .ml10 {
184 | margin-left: 10rpx;
185 | }
186 |
187 | .mt30 {
188 | margin-top: 30rpx;
189 | }
190 |
191 | .mr30 {
192 | margin-right: 30rpx;
193 | }
194 |
195 | .mb30 {
196 | margin-bottom: 30rpx;
197 | }
198 |
199 | .ml30 {
200 | margin-left: 30rpx;
201 | }
202 |
203 | .mt20 {
204 | margin-top: 20rpx;
205 | }
206 |
207 | .mr20 {
208 | margin-right: 20rpx;
209 | }
210 |
211 | .mb20 {
212 | margin-bottom: 20rpx;
213 | }
214 |
215 | .ml20 {
216 | margin-left: 20rpx;
217 | }
218 |
219 | .mt40 {
220 | margin-top: 40rpx;
221 | }
222 |
223 | .mr40 {
224 | margin-right: 40rpx;
225 | }
226 |
227 | .mb40 {
228 | margin-bottom: 40rpx;
229 | }
230 |
231 | .ml40 {
232 | margin-left: 40rpx;
233 | }
234 |
235 | .lh1-5 {
236 | line-height: 1.5em;
237 | }
238 |
239 | .lh2 {
240 | line-height: 2em;
241 | }
242 |
243 | .lh2-5 {
244 | line-height: 2.5em;
245 | }
246 |
247 | .lh3 {
248 | line-height: 3em;
249 | }
250 |
251 | .lh3-5 {
252 | line-height: 3.5em;
253 | }
254 |
255 | .lh4 {
256 | line-height: 4em;
257 | }
258 |
259 |
260 | /* 单行省略 */
261 |
262 | .uniline {
263 | overflow: hidden;
264 | text-overflow: ellipsis;
265 | white-space: nowrap;
266 | }
267 |
268 |
269 | /* 多行省略 */
270 |
271 | .multi-line {
272 | display: -webkit-box;
273 | -webkit-box-orient: vertical;
274 | -webkit-line-clamp: 2;
275 | overflow: hidden;
276 | }
277 |
278 | .multi-line-3 {
279 | -webkit-line-clamp: 3;
280 | }
281 |
282 | .multi-line-4 {
283 | -webkit-line-clamp: 4;
284 | }
285 |
286 | .flex-center-center {
287 | display: flex;
288 | flex-direction: column;
289 | justify-content: center;
290 | align-items: center;
291 | }
292 |
293 |
294 | /* 下划线 */
295 |
296 | .underline {
297 | text-decoration: underline;
298 | color: #647D9A;
299 | }
300 |
301 |
302 | /* 选择图片 */
303 |
304 | .select-image {
305 | position: relative;
306 | width: 30%;
307 | height: 0;
308 | padding-bottom: 30%;
309 | border: 2rpx dashed transparent;
310 | background: linear-gradient(white, white) padding-box, repeating-linear-gradient(-45deg, #ccc 0, #ccc 0.25em, white 0, white 0.6em);
311 | }
312 |
313 | .icon_add {
314 | position: absolute;
315 | top: 50%;
316 | left: 50%;
317 | transform: translate(-50%, -50%);
318 | width: 100rpx;
319 | height: 100rpx;
320 | }
321 |
322 | .icon-right {
323 | width: 14rpx;
324 | height: 28rpx;
325 | }
326 |
327 | .icon-refresh {
328 | width: 100rpx;
329 | height: 100rpx;
330 | }
331 |
332 | .z-index-1 {
333 | z-index: -1;
334 | }
335 |
336 | /* 隐藏滚动条 */
337 | ::-webkit-scrollbar {
338 | width: 0;
339 | height: 0;
340 | color: transparent;
341 | }
--------------------------------------------------------------------------------
/pages/goods/goods.js:
--------------------------------------------------------------------------------
1 | var app = getApp()
2 | import { goodsList } from '../../utils/publicData'
3 | Page({
4 | data: {
5 | navActive: 5,
6 | goodsList: goodsList,
7 | selectGoods: {
8 | url: '',
9 | bool: false,
10 | left: '',
11 | top: ''
12 | },
13 | imgUrls: [
14 | '../../images/banner1.jpg',
15 | '../../images/banner2.jpg',
16 | '../../images/banner3.jpg'
17 | ],
18 | pull: {
19 | isLoading: false,
20 | loading: '../../image/common/pull_refresh.gif',
21 | pullText: '正在加载'
22 | },
23 | push: {
24 | isLoading: false,
25 | loading: '../../image/common/pull_refresh.gif',
26 | pullText: '-上拉加载更多-'
27 | },
28 | indicatorDots: false,
29 | autoplay: false,
30 | interval: 5000,
31 | duration: 500,
32 | goods_list: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
33 | hideCount: false,
34 | count: 0,
35 | needAni: false,
36 | hide_good_box: true
37 | },
38 | onLoad() {
39 | var that = this;
40 | this.busPos = {};
41 | this.busPos['x'] = app.globalData.ww * 0.8;
42 | this.busPos['y'] = app.globalData.hh * 0.8;
43 | },
44 | tabSelect(e) {
45 | this.setData({
46 | navActive: e.target.dataset.index
47 | })
48 | },
49 | refresh(e) {
50 | console.log('刷新', e);
51 | this.setData({
52 | 'pull.isLoading': true,
53 | 'pull.loading': '../../image/common/pull_refresh.gif',
54 | 'pull.pullText': '正在加载',
55 | });
56 | setTimeout(() => {
57 | this.setData({
58 | 'pull.loading': '../../image/common/finish.png',
59 | 'pull.pullText': '刷新完成'
60 | })
61 | }, 4000);
62 | setTimeout(() => {
63 | this.setData({
64 | 'pull.isLoading': false,
65 | });
66 | console.log('+++++ 刷新完成 +++++')
67 | }, 6000)
68 | },
69 | toload(e) {
70 | console.log('加载', e);
71 | this.setData({
72 | 'push.isLoading': true,
73 | 'push.pullText': '正在加载',
74 | 'push.loading': '../../image/common/pull_refresh.gif',
75 | });
76 | if (this.data.goodsList.length < 30) {
77 | setTimeout(() => {
78 | let data = this.data.goodsList.concat([
79 | {title: '单人沙发', goodsImg: 'http://mkmarketing.oss-cn-hangzhou.aliyuncs.com/Marketing/namecard/product/image/EAD670176 D1882/common/SM_IMAGE/SM_001.jpg'},
80 | {title: '双人沙发', goodsImg: 'http://mkmarketing.oss-cn-hangzhou.aliyuncs.com/Marketing/namecard/product/image/11M9007U212301/common/SM_IMAGE/SM_001.jpg?x-oss-process=image/resize,m_pad,h_500,w_500,color_FFFFFF'},
81 | {title: '早安床头柜', goodsImg: 'http://mkmarketing.oss-cn-hangzhou.aliyuncs.com/Marketing/namecard/product/image/CACLA-016-063/common/SM_IMAGE/SM_001.jpg'}
82 | ]);
83 | this.setData({
84 | goodsList: data,
85 | 'push.isLoading': false,
86 | 'push.pullText': '- 上拉加载更多 -',
87 | 'push.loading': '../../image/common/finish.png',
88 | });
89 | console.log('===== 加载完成 =====')
90 | }, 2000)
91 | }
92 | },
93 | busAnimation() {
94 | that.setData({
95 | needAni: true
96 | });
97 | setTimeout(() => {
98 | that.setData({
99 | needAni: false
100 | });
101 | }, 500);
102 | },
103 | touchOnGoods (e) {
104 | if (!this.data.hide_good_box) return;
105 | this.finger = {};
106 | var topPoint = {};
107 | this.finger['x'] = e.touches["0"].clientX > app.globalData.ww - 75 ? app.globalData.ww - 80 : e.touches["0"].clientX;
108 | this.finger['y'] = e.touches["0"].clientY;
109 | if (this.finger['y'] < this.busPos['y']) {
110 | topPoint['y'] = this.finger['y'] - 150;
111 | } else {
112 | topPoint['y'] = this.busPos['y'] - 150;
113 | }
114 | topPoint['x'] = Math.abs(this.finger['x'] - this.busPos['x']) / 2 + this.finger['x'];
115 | this.linePos = app.bezier([this.finger, topPoint, this.busPos], 30);
116 | this.startAnimation();
117 | },
118 | startAnimation () {
119 | var index = 0,
120 | that = this,
121 | bezier_points = that.linePos['bezier_points'];
122 | this.setData({
123 | hide_good_box: false,
124 | bus_x: that.finger['x'],
125 | bus_y: that.finger['y']
126 | });
127 | this.timer = setInterval(() => {
128 | index++;
129 | that.setData({
130 | bus_x: bezier_points[index]['x'],
131 | bus_y: bezier_points[index]['y']
132 | });
133 | if (index >= 28) {
134 | clearInterval(that.timer);
135 | that.setData({
136 | hide_good_box: true,
137 | hideCount: false,
138 | count: that.data.count += 1
139 | })
140 | }
141 | }, 33);
142 | },
143 | giveLike(e) {
144 | let ind = e.target.dataset.ind;
145 | let key = `goodsList[${ind}].like`;
146 | this.setData({
147 | [key]: !this.data.goodsList[ind].like
148 | });
149 | }
150 | });
--------------------------------------------------------------------------------
/pages/client-pool/client-pool.js:
--------------------------------------------------------------------------------
1 | import { howLongAgo } from '../../utils/util'
2 | import { sourceData, cateData } from '../../utils/publicData'
3 | Page({
4 | data: {
5 | praise: false,
6 | sourceData: sourceData,
7 | cateData: cateData,
8 | clientCondition: {
9 | data: {
10 | searchValue: '',
11 | sourceValue: '',
12 | cateValue: '',
13 | },
14 | pageNum: 1,
15 | pageSize: 10
16 | },
17 | cluesData: [],
18 | pull: {
19 | isLoading: false,
20 | loading: '../../image/common/pull_refresh.gif',
21 | pullText: '正在刷新'
22 | },
23 | push: {
24 | isLoading: false,
25 | loading: '../../image/common/pull_refresh.gif',
26 | pullText: '-上拉加载更多-'
27 | },
28 | slideStart: 0,
29 | moveTime: 0,
30 | isShow_01: false,
31 | picker_01_data:[],
32 | },
33 | onLoad() {
34 | this.loadMore()
35 | },
36 | /**搜索框内容改变 */
37 | searchChange(e) {
38 | this.setData({
39 | 'clientCondition.data.searchValue': e.detail.value
40 | })
41 | },
42 | /**点击键盘搜索按钮触发 */
43 | bindconfirm(e) {
44 | console.log('搜索', e)
45 | },
46 | /**清空搜索框内容 */
47 | clearSearchValue() {
48 | this.setData({
49 | 'clientCondition.data.searchValue': ''
50 | })
51 | },
52 | /**滚动选择器选择来源、类别 */
53 | bindPickerChange(e) {
54 | if (e.target.dataset.type == 'source') {
55 | this.setData({
56 | 'clientCondition.data.sourceValue': this.data.sourceData[e.detail.value].key
57 | })
58 | } else if (e.target.dataset.type == 'cate') {
59 | this.setData({
60 | 'clientCondition.data.cateValue': this.data.cateData[e.detail.value].key
61 | })
62 | }
63 | },
64 | bindpraise() {
65 | if (this.data.praise === false) {
66 | this.setData({
67 | 'praise': 2
68 | })
69 | setTimeout(() => {
70 | this.setData({
71 | 'praise': true
72 | })
73 | }, 1000)
74 | } else {
75 | this.setData({
76 | 'praise': 2
77 | })
78 | setTimeout(() => {
79 | this.setData({
80 | 'praise': false
81 | })
82 | }, 1000)
83 | }
84 | },
85 | tranTime() {
86 | let data = this.data.cluesData.map(item => {
87 | item.date = howLongAgo(item.time)
88 | return item
89 | })
90 | this.setData({
91 | cluesData: data
92 | })
93 | },
94 | /**触发下拉刷新 */
95 | touchstart(e) {
96 | this.setData({
97 | slideStart: e.touches[0]
98 | })
99 | console.log('开始', e)
100 | },
101 | touchmove(e) {
102 | let moveTime = new Date().getTime();
103 | if (moveTime - this.data.moveTime <= 2000) {
104 | return
105 | } else {
106 | this.setData({
107 | moveTime: moveTime
108 | })
109 | }
110 | let slideStart = this.data.slideStart;
111 | let slideMove = e.touches[0];
112 | let startX = slideStart.pageX;
113 | let startY = slideStart.pageY;
114 | let moveEndX = slideMove.pageX;
115 | let moveEndY = slideMove.pageY;
116 | let X = moveEndX - startX;
117 | let Y = moveEndY - startY;
118 | if (Math.abs(Y) > Math.abs(X) && Y > 0) {
119 | console.log("top 2 bottom");
120 | this.pullRefresh()
121 | } else if (Math.abs(Y) > Math.abs(X) && Y < 0) {
122 | console.log("bottom 2 top");
123 | this.loadMore()
124 | }
125 | },
126 | /**下拉刷新 */
127 | pullRefresh(e) {
128 | this.setData({
129 | 'pull.isLoading': true,
130 | 'pull.loading': '../../image/common/pull_refresh.gif',
131 | 'pull.pullText': '正在刷新~'
132 | })
133 | setTimeout(() => {
134 | this.setData({
135 | 'pull.loading': '../../image/common/finish.png',
136 | 'pull.pullText': '刷新完成'
137 | })
138 | }, 4000)
139 | setTimeout(() => {
140 | this.setData({
141 | 'pull.isLoading': false,
142 | })
143 | }, 6000)
144 | },
145 | /**上拉加载更多 */
146 | loadMore() {
147 | this.setData({
148 | 'push.isLoading': true,
149 | 'push.pullText': '正在加载',
150 | 'push.loading': '../../image/common/pull_refresh.gif',
151 | })
152 | if (this.data.cluesData.length < 30) {
153 | setTimeout(() => {
154 | let data = this.data.cluesData.concat([
155 | { time: '2019-11-20 15:50' },
156 | { time: '2018-06-20 15:32' }
157 | ])
158 | this.setData({
159 | cluesData: data,
160 | 'push.isLoading': false,
161 | 'push.pullText': '- 上拉加载更多 -',
162 | 'push.loading': '../../image/common/finish.png',
163 | })
164 | this.tranTime()
165 | }, 2000)
166 | }
167 | },
168 | /**跳转客户详情 */
169 | toCustomerDetails() {
170 |
171 | },
172 | myPickerChange(e) {
173 | console.log('自定义组件选择的结果', e.detail)
174 | this.setData({
175 | address: e.detail
176 | })
177 | },
178 | showPicker_01() {
179 | this.setData({
180 | isShow_01: true,
181 | })
182 | },
183 | sureCallBack_01(e) {
184 | let data = e.detail
185 | this.setData({
186 | isShow_01: false,
187 | picker_01_data: e.detail.choosedData,
188 | picker_01_index: JSON.stringify(e.detail.choosedIndexArr)
189 | })
190 | console.log(this.data.picker_01_data, this.data.picker_01_index)
191 | },
192 | cancleCallBack_01() {
193 | this.setData({
194 | isShow_01: false,
195 | })
196 | },
197 | })
--------------------------------------------------------------------------------
/pages/activity/activity.js:
--------------------------------------------------------------------------------
1 | Page({
2 | data: {
3 | size: 400,//转盘大小,
4 | musicflg: false, //声音
5 | fastJuedin: true,//快速决定
6 | repeat: true,//不重复抽取
7 | probability: true,// 概率
8 | s_awards: '',//结果
9 | option: '标题',
10 | //转盘的总数据,想添加多个可以往这数组里添加一条格式一样的数据
11 | zhuanpanArr: [
12 | {
13 | id: 0,
14 | option: '我帅吗?',//转盘的标题名称
15 | awards: [
16 | {
17 | id: 0, // id递增
18 | name: "帅", // 选项名 超过9个字时字体会变小点 大于13个数时会隐藏掉超出的
19 | color: '#FFA827', // 选项的背景颜色
20 | probability: 200 // 概率 0代表永远也转不到这个选项,数字越大概率也就越大,data中的probability属性设置为true时是才生效, 这属性也必须填写,不填写会出错
21 | },
22 | {
23 | id: 1,
24 | name: "很帅",
25 | color: '#AA47BC',
26 | probability: 10
27 | },
28 | {
29 | id: 2,
30 | name: "贼帅",
31 | color: '#42A5F6',
32 | probability: 10
33 | },
34 | {
35 | id: 3,
36 | name: "非常帅",
37 | color: '#66BB6A',
38 | probability: 10
39 | },
40 | {
41 | id: 4,
42 | name: "超级帅",
43 | color: '#FFA500',
44 | probability: 100
45 | },
46 | {
47 | id: 5,
48 | name: "宇宙无敌第一帅",
49 | color: '#FF4500',
50 | probability: 0
51 | },
52 | {
53 | id: 6,
54 | name: "你最美",
55 | color: '#AA47BC',
56 | probability: 10
57 | }
58 | ]
59 | }
60 | ],
61 | //更改数据可以更改这属性,格式要像下面这样写才行
62 | awardsConfig: {
63 | option: '我帅吗?',//转盘的标题名称
64 | awards: [
65 | {
66 | id: 0, // id递增
67 | name: "帅帅帅", // 选项名 超过9个字时字体会变小点 大于13个数时会隐藏掉超出的
68 | color: '#FFA827', // 选项的背景颜色
69 | probability: 100 // 概率 0代表永远也转不到这个选项,数字越大概率也就越大,data中的probability属性设置为true时是才生效, 这属性也必须填写,不填写会出错
70 | },
71 | {
72 | id: 1,
73 | name: "很帅",
74 | color: '#AA47BC',
75 | probability: 10
76 | },
77 | {
78 | id: 2,
79 | name: "贼帅",
80 | color: '#42A5F6',
81 | probability: 10
82 | },
83 | {
84 | id: 3,
85 | name: "非常帅",
86 | color: '#66BB6A',
87 | probability: 10
88 | },
89 | {
90 | id: 4,
91 | name: "超级帅",
92 | color: '#FFA500',
93 | probability: 100
94 | },
95 | {
96 | id: 5,
97 | name: "宇宙无敌第一帅",
98 | color: '#FF4500',
99 | probability: 0
100 | },
101 | {
102 | id: 6,
103 | name: "你最美",
104 | color: '#AA47BC',
105 | probability: 10
106 | },
107 | ]
108 | }
109 | },
110 |
111 | //接收当前转盘初始化时传来的参数
112 | getData(e) {
113 | this.setData({
114 | option: e.detail.option
115 | })
116 | },
117 |
118 | //接收当前转盘结束后的答案选项
119 | getAwards(e) {
120 | wx.showToast({
121 | title: e.detail,
122 | icon: 'none'
123 | })
124 | this.setData({
125 | s_awards: e.detail,
126 | })
127 | },
128 |
129 | //开始转动或者结束转动
130 | startZhuan(e) {
131 | this.setData({
132 | zhuanflg: e.detail ? true : false
133 | })
134 | },
135 |
136 | //切换转盘选项
137 | switchZhuanpan(e) {
138 | //当转盘停止时才执行切换转盘
139 | if (!this.data.zhuanflg) {
140 | var idx = e.currentTarget.dataset.idx, zhuanpanArr = this.data.zhuanpanArr, obj = {};
141 | for (let i in zhuanpanArr) {
142 | if (this.data.option != zhuanpanArr[i].option && zhuanpanArr[i].id == idx) {
143 | obj.option = zhuanpanArr[i].option;
144 | obj.awards = zhuanpanArr[i].awards;
145 | this.setData({
146 | awardsConfig: obj //其实默认要更改当前转盘的数据要传个这个对象,才有效果
147 | })
148 | break;
149 | }
150 | }
151 | }
152 | },
153 |
154 | //转盘声音
155 | switch1Change1(e) {
156 | var value = e.detail.value;
157 | if (this.data.zhuanflg) {
158 | wx.showToast({
159 | title: '当转盘停止转动后才有效',
160 | icon: 'none'
161 | })
162 | return;
163 | } else {
164 | this.setData({
165 | musicflg: value
166 | })
167 | }
168 | },
169 |
170 | //不重复抽取
171 | switch1Change2(e) {
172 | var value = e.detail.value;
173 | if (this.data.zhuanflg) {
174 | wx.showToast({
175 | title: '当转盘停止转动后才有效',
176 | icon: 'none'
177 | })
178 | return;
179 | } else {
180 | this.setData({
181 | repeat: value
182 | })
183 | }
184 | },
185 |
186 | //快速决定
187 | switch1Change3(e) {
188 | var value = e.detail.value;
189 | if (this.data.zhuanflg) {
190 | wx.showToast({
191 | title: '当转盘停止转动后才有效',
192 | icon: 'none'
193 | })
194 | return;
195 | } else {
196 | this.setData({
197 | fastJuedin: value
198 | })
199 | }
200 | },
201 |
202 | //概率 == 如果不重复抽取开启的话 概率是无效的
203 | switch1Change4(e) {
204 | var value = e.detail.value;
205 | if (this.data.zhuanflg) {
206 | wx.showToast({
207 | title: '当转盘停止转动后才有效',
208 | icon: 'none'
209 | })
210 | return;
211 | } else {
212 | this.setData({
213 | probability: value
214 | })
215 | }
216 | },
217 |
218 | onLoad: function () {
219 | //实例化组件对象,这样有需要时就能调用组件内的方法
220 | this.zhuanpan = this.selectComponent("#zhuanpan");
221 |
222 | //可以这样调用 示例:this.zhuanpan.switchZhuanpan(data);
223 | //上面这方法可用来切换转盘选项数据,参数可以看组件构造器中的switchZhuanpan方法
224 | }
225 | })
226 |
--------------------------------------------------------------------------------
/components/turntable/turntable.js:
--------------------------------------------------------------------------------
1 | // components/zhuanpan/zhuanpan.js
2 | //创建并返回内部 audio 上下文 innerAudioContext 对象
3 | const start = wx.createInnerAudioContext();
4 | const mid = wx.createInnerAudioContext();
5 | const stop = wx.createInnerAudioContext();
6 |
7 | Component({
8 | options: {
9 | multipleSlots: true // 在组件定义时的选项中启用多slot支持
10 | },
11 |
12 | /**
13 | * 组件的属性列表
14 | * 用于组件自定义设置 组件的对外属性
15 | */
16 | properties: {
17 | myProperty: { // 属性名 myProperty2: String, 简化的定义方式
18 | type: String, // 类型(必填),目前接受的类型包括:String, Number, Boolean, Object, Array, null(表示任意类型)
19 | value: '', // 属性默认 初始值(可选),如果未指定则会根据类型选择一个
20 | observer: function (newVal, oldVal, changedPath) {
21 | // 属性被改变时执行的函数(可选),也可以写成在methods段中定义的方法名字符串, 如:'_propertyChange'
22 | // 通常 newVal 就是新设置的数据, oldVal 是旧数据
23 | }
24 | },
25 |
26 | probability: {
27 | type: Boolean, // 概率开关,默认false 随机
28 | value: false
29 | },
30 |
31 | musicflg: {
32 | type: Boolean, // 转盘声音开关,默认true
33 | value: true
34 | },
35 |
36 | fastJuedin: {
37 | type: Boolean, // 快速转动转盘的开关,默认false
38 | value: false
39 | },
40 |
41 | repeat: {
42 | type: Boolean, // 重复抽取开关,默认false
43 | value: false
44 | },
45 |
46 | size: {
47 | type: Number, // 转盘大小,传入宽度即可
48 | value: 600
49 | },
50 |
51 | zhuanpanArr: { // 可以切换的转盘选项, 支持多个
52 | type: Array,
53 | value: [
54 | {
55 | id: 0,
56 | option: '转盘的标题名称',
57 | awards: [
58 | {
59 | id: 0,
60 | name: "最多17个选项", // 选项名
61 | color: 'red', // 选项的背景颜色
62 | probability: 10 // 概率 0代表永远也转不到这个选项,数字越大概率也就越大
63 | },
64 | {
65 | id: 1,
66 | name: "选项最多填13字", // 超过9个字时字体会变小点
67 | color: 'green',
68 | probability: 10
69 | }
70 | ]
71 | }
72 | ]
73 | },
74 |
75 | // 限制:最多17个选项, 单个选项最多填10-13个字,多余部分会隐藏
76 | awardsConfig: { // 默认的当前转盘选项
77 | type: Object,
78 | value: {
79 | option: '我的小决定?',
80 | awards: [
81 | {
82 | id: 0,
83 | name: "最多17个选项",
84 | color: 'red',
85 | probability: 0
86 | },
87 | {
88 | id: 1,
89 | name: "选项最多填13字",
90 | color: 'green',
91 | probability: 0
92 | }
93 | ],
94 | },
95 | observer: function (newVal, oldVal, changedPath) {
96 | if (newVal) {
97 | this.switchZhuanpan(newVal, true);
98 | }
99 | }
100 | }
101 |
102 | },
103 |
104 | /**
105 | * 私有数据,组件的初始数据
106 | * 可用于模版渲染
107 | */
108 | data: {
109 | animationData: {}, // 转盘动画
110 | zhuanflg: false, // 转盘是否可以点击切换的标志位
111 | fastTime: 7600, // 转盘快速转动的时间
112 | slowTime: 3900, // 转盘慢速转动的时间
113 | runDegs: 0, // 转盘旋转了多少圈
114 | timer: null, // 清除转盘的时间clearTimeout(timer)
115 | block1: 'block', // 控制显示或隐藏转盘中心的图片
116 | block2: 'none',
117 | block3: 'none',
118 | block4: 'none'
119 | },
120 |
121 | //组件生命周期函数,在组件实例进入页面节点树时执行,注意此时不能调用 setData
122 | created: function () { },
123 |
124 | // 组件生命周期函数,在组件实例进入页面节点树时执行
125 | attached: function () {
126 | console.log('===============attached===============');
127 | start.src = 'https://gamesdata.oss-cn-hangzhou.aliyuncs.com/xiaojueding/start.mp3'; // 转盘开始转动的音乐
128 | mid.src = 'https://gamesdata.oss-cn-hangzhou.aliyuncs.com/xiaojueding/mid.mp3'; // 快速决定时,转盘开始转动的音乐
129 | stop.src = 'https://gamesdata.oss-cn-hangzhou.aliyuncs.com/xiaojueding/stop.mp3'; // 转盘停止转动的音乐
130 |
131 | this.setData({
132 | awardsConfig: this.data.zhuanpanArr[0]
133 | })
134 | this.initAdards();
135 | },
136 |
137 | /**
138 | * 组件的方法列表
139 | * 更新属性和数据的方法与更新页面数据的方法类似
140 | */
141 | methods: {
142 | /*
143 | * 公有方法
144 | */
145 | //判断值是否为空
146 | isNull(str) {
147 | if (str == null || str == undefined || str == '') {
148 | return true;
149 | } else {
150 | return false;
151 | }
152 | },
153 |
154 | //初始化数据
155 | initAdards() {
156 | var that = this, awardsConfig = that.data.awardsConfig;
157 | var t = awardsConfig.awards.length; // 选项长度
158 | var e = 1 / t, i = 360 / t, r = i - 90;
159 |
160 | for (var g = 0; g < t; g++) {
161 | awardsConfig.awards[g].item2Deg = g * i + 90 - i / 2 + "deg";//当前下标 * 360/长度 + 90 - 360/长度/2
162 | awardsConfig.awards[g].afterDeg = r + "deg";
163 | awardsConfig.awards[g].opacity = '1';
164 | }
165 |
166 | that.setData({
167 | turnNum: e, // 页面的单位是turn
168 | awardsConfig: awardsConfig,
169 | })
170 |
171 | that._change();//向父组件传出当前转盘的初始数据
172 | },
173 |
174 | //重置转盘
175 | reset() {
176 | var that = this, awardsConfig = that.data.awardsConfig;
177 | var animation = wx.createAnimation({
178 | duration: 1,
179 | timingFunction: "ease"
180 | });
181 | that.animation = animation;
182 | animation.rotate(0).step(), that.data.runDegs = 0;
183 |
184 | that.setData({
185 | animationData: animation.export(),
186 | block3: 'none',
187 | block4: 'block'
188 | })
189 |
190 | for (let x in awardsConfig.awards) {
191 | awardsConfig.awards[x].opacity = '1';
192 | }
193 |
194 | setTimeout(function () {
195 | that.setData({
196 | block1: 'block',
197 | block4: 'none',
198 | awardsConfig: awardsConfig,
199 | })
200 | }, 300)
201 | },
202 |
203 | //父组件需要切换当前转盘的选项
204 | //如果有需要切换不同转盘的选项时,可以调用这方法
205 | //data: 转盘的数据
206 | //flag: 当转盘在转动过程中如果你想停止的话,可以传个true值,默认可不传
207 | switchZhuanpan(data, flag) {
208 | this.setData({
209 | awardsConfig: data,
210 | block1: 'block',
211 | block1: 'none',
212 | block3: 'none',
213 | block4: 'none',
214 | zhuanflg: false,
215 | })
216 | this.initAdards();
217 |
218 | if (flag) {
219 | this.reset();
220 | clearTimeout(this.data.timer);
221 | start.stop();
222 | mid.stop();
223 | stop.stop();
224 | wx.removeStorageSync('repeatArr');
225 | }
226 | },
227 |
228 |
229 |
230 | /*
231 | * 内部私有方法建议以下划线开头
232 | * triggerEvent 用于触发事件,过triggerEvent来给父组件传递信息的
233 | * 写法: this.triggerEvent('cancelEvent', { num: 1 }) // 可以将num通过参数的形式传递给父组件
234 | */
235 |
236 | // GO转盘开始转动
237 | _zhuan() {
238 | var that = this, awardsConfig = that.data.awardsConfig, runDegs = that.data.runDegs;
239 | //>>> 是无符号移位运算符
240 | var r = Math.random() * awardsConfig.awards.length >>> 0, runNum = 8;
241 |
242 |
243 | /*=============不重复抽取=============*/
244 | if (that.data.repeat) {
245 | r = that._queryRepeat(r);
246 | } else {
247 | wx.removeStorageSync('repeatArr');
248 |
249 | console.log('是否开启了概率???', that.data.probability);
250 | //开启概率 probability这属性必须要传个ture
251 | if (that.data.probability) {
252 | r = that._openProbability();
253 | }
254 | }
255 | /*=============不重复抽取=============*/
256 |
257 |
258 | console.log('当前答案选项的下标=====', r);
259 | setTimeout(function () {
260 | //转盘开始转动音乐
261 | that.data.musicflg ? that.data.fastJuedin ? mid.play() : start.play() : '';
262 |
263 | //要转多少度deg
264 | runDegs = runDegs || 0, runDegs = runDegs + (360 - runDegs % 360) + (2160 - r * (360 / awardsConfig.awards.length));
265 |
266 | var animation = wx.createAnimation({
267 | duration: that.data.fastJuedin ? that.data.slowTime : that.data.fastTime,
268 | timingFunction: "ease"
269 | });
270 | that.animation = animation;
271 |
272 | //这动画执行的是差值
273 | //如果第一次写rotate(360) 那么第二次再写rotate(360)将不起效果
274 | animation.rotate(runDegs).step(), 0 == r && (runDegs = 0);
275 |
276 | that.setData({
277 | animationData: animation.export(),
278 | block1: 'none',
279 | block2: 'block',
280 | zhuanflg: true,
281 | })
282 |
283 | that._setatZhuan(true);
284 | }, 100);
285 |
286 | that.setData({
287 | timer: setTimeout(function () {
288 | //转盘停止后,答案区域高亮显示,其他区域增加透明度
289 | for (let x in awardsConfig.awards) {
290 | if (x != r) {
291 | awardsConfig.awards[x].opacity = '0.3';
292 | } else {
293 | awardsConfig.awards[x].opacity = '1';
294 | }
295 | }
296 |
297 | //转盘停止后的音乐
298 | !that.data.musicflg ? '' : stop.play();
299 |
300 | that.setData({
301 | animationData: {},
302 | s_awards: awardsConfig.awards[r].name,//最终选中的结果
303 | awardsConfig: awardsConfig,
304 | block2: 'none',
305 | block3: 'block',
306 | zhuanflg: false,
307 | })
308 | that._myAwards();
309 | that._setatZhuan(false);
310 | }, that.data.fastJuedin ? that.data.slowTime : that.data.fastTime)
311 | })
312 | },
313 |
314 |
315 | // 开启概率
316 | // 传的数越大概率越大
317 | // 传入0的话就永远摇不到这个选项
318 | _openProbability() {
319 | var that = this, awards = that.data.awardsConfig.awards, arr = [];
320 | //5, 5, 20, 10 ,30 ,30, 0
321 | for (let i in awards) {
322 | if (awards[i].probability != 0) {
323 | for (var x = 0; x < awards[i].probability; x++) {
324 | //把当前的概率数字 以当前选项下标的形式 都添加都空数组中,然后随机这个数组
325 | arr.push(i);
326 | }
327 | }
328 | }
329 | var s = Math.floor(Math.random() * arr.length);
330 | return arr[s];
331 | },
332 |
333 | //不重复抽取
334 | //r:随机数 当前选项进行随机
335 | _queryRepeat(r) {
336 | var that = this, flag = true, repeatArr = wx.getStorageSync('repeatArr'), repeatArr2 = [], awardsConfig = that.data.awardsConfig;
337 | if (that.isNull(repeatArr)) {
338 | repeatArr2.push(r), wx.setStorageSync('repeatArr', repeatArr2);
339 | return r;
340 | } else {
341 | var len = awardsConfig.awards.length, r = Math.random() * len >>> 0;
342 | for (let i in repeatArr) {
343 | if (r == repeatArr[i]) {
344 | flag = false;
345 | if (repeatArr.length == len) {
346 | wx.removeStorageSync('repeatArr');
347 | repeatArr2.push(r), wx.setStorageSync('repeatArr', repeatArr2);
348 | return r;
349 | } else {
350 | return that._queryRepeat();//递归调用
351 | }
352 | }
353 | }
354 | if (flag) {
355 | repeatArr.push(r), wx.setStorageSync('repeatArr', repeatArr);
356 | return r;
357 | }
358 | }
359 | },
360 |
361 | //初始化数据时向外传的参
362 | _change() {
363 | this.triggerEvent('myData', this.data.awardsConfig);// 向父组件传出当前转盘的数组数据
364 | },
365 |
366 | //当前转盘的结果
367 | _myAwards() {
368 | this.triggerEvent('myAwards', this.data.s_awards)
369 | },
370 |
371 | //转盘开始转动或者结速转动后的要传的值
372 | _setatZhuan(e) {
373 | this.triggerEvent('startZhuan', e);
374 | },
375 |
376 | }
377 | })
378 |
--------------------------------------------------------------------------------
/components/picker/picker.js:
--------------------------------------------------------------------------------
1 | // picker/picker.js
2 | import { isPlainObject } from '../../utils/tools'
3 |
4 | Component({
5 | /**
6 | * 组件的属性列表
7 | */
8 | properties: {
9 | scrollType: {
10 | type: String,
11 | value: 'normal'// "link": scroll间联动 "normal": scroll相互独立
12 | },
13 | listData: {
14 | type: Array,
15 | value: [],
16 | observer: function (newVal) {
17 | if (newVal.length === 0 || this._compareDate()) return
18 | this._setTempData()
19 | const tempArr = [...new Array(newVal.length).keys()].map(() => 0)
20 | this.data.lastValue = this.data.tempValue = tempArr
21 | this._setDefault()
22 |
23 | // let {defaultPickData} = this.properties;
24 | // if(newVal.length === 0) return;
25 | //
26 | // this._setDefault(newVal, defaultPickData)
27 | }
28 | },
29 | defaultPickData: {
30 | type: Array,
31 | value: [],
32 | observer: function (newVal) {
33 | if (newVal.length === 0 || this._compareDate()) return
34 | this._setTempData()
35 | this._setDefault()
36 | }
37 | },
38 | keyWordsOfShow: {
39 | type: String,
40 | value: 'name'
41 | },
42 | isShowPicker: {
43 | type: Boolean,
44 | value: false,
45 | observer: function (newVal) {
46 | if (newVal) {
47 | this._openPicker()
48 | } else {
49 | this._closePicker()
50 | }
51 | }
52 | },
53 | titleText: {// 标题文案
54 | type: String,
55 | value: '标题'
56 | },
57 | cancelText: {// 取消按钮文案
58 | type: String,
59 | value: '取消'
60 | },
61 | sureText: {// 确定按钮文案
62 | type: String,
63 | value: '确定'
64 | },
65 | pickerHeaderStyle: String, // 标题栏样式 view
66 | sureStyle: String, // 标题栏确定样式 text
67 | cancelStyle: String, // 标题栏取消样式 text
68 | titleStyle: String, // 标题栏标题样式 view
69 | maskStyle: String, // 设置蒙层的样式(详见picker-view) view
70 | indicatorStyle: String, // 设置选择器中间选中框的样式(详见picker-view) view
71 | chooseItemTextStyle: String// 设置picker列表文案样式 text
72 | },
73 |
74 | /**
75 | * 组件的初始数据
76 | */
77 | data: {
78 | columnsData: [],
79 | value: [],
80 | backData: [],
81 | height: 0,
82 | isOpen: false,
83 | isUseKeywordOfShow: false,
84 | scrollEnd: true, // 滚动是否结束
85 | lastValue: [], // 上次各个colum的选择索引
86 | tempValue: [],
87 | isFirstOpen: true,
88 | onlyKey: '',
89 | defaultPickDataTemp: '',
90 | listDataTemp: ''
91 | },
92 | /**
93 | * 组件的方法列表
94 | */
95 | methods: {
96 | tapModal() {
97 | this.properties.isShowPicker = false
98 | this._closePicker()
99 | },
100 | cancle() {
101 | this.triggerEvent('cancle')
102 | this._closePicker()
103 | },
104 | sure() {
105 | const { scrollEnd, tempValue } = this.data
106 | if (!scrollEnd) return
107 | const backData = this._getBackDataFromValue(tempValue)
108 | this.setData({
109 | backData
110 | })
111 | this.triggerEvent('sure', {
112 | choosedData: backData,
113 | choosedIndexArr: tempValue
114 | })
115 | this._closePicker()
116 | },
117 | _bindChange(e) {
118 | const { scrollType } = this.properties
119 | const { lastValue } = this.data
120 | let val = e.detail.value
121 | switch (scrollType) {
122 | case 'normal':
123 | this.data.tempValue = val.concat()
124 | this.data.tempValue = val.concat()
125 | break
126 | case 'link':
127 | // let column_02 = this._getColumnData(this.properties.listData[val[0]].children);
128 | // let column_03 = this._getColumnData(this.properties.listData[val[0]].children[val[1]].children);
129 | var tempArray = []
130 | if (val.length > 1) {
131 | val.slice(0, val.length - 1).reduce((t, c, i) => {
132 | const v = t[c].children
133 | tempArray.push(this._getColumnData(v))
134 | return v
135 | }, this.properties.listData)
136 | }
137 | // let columnsData = [this.data.columnsData[0],column_02,column_03];
138 | var columnsData = [this.data.columnsData[0], ...tempArray]
139 |
140 | // 设置value关联
141 | var compareIndex = this._getScrollCompareIndex(lastValue, val)
142 | if (compareIndex > -1) {
143 | let tempI = 1
144 | while (val[compareIndex + tempI] !== undefined) {
145 | val[compareIndex + tempI] = 0
146 | tempI++
147 | }
148 | }
149 | val = this._validate(val)
150 | this.data.lastValue = val.concat()
151 | this.data.tempValue = val.concat()
152 | this.setData({
153 | columnsData
154 | // value: val
155 | })
156 | }
157 | },
158 | _validate(val) {
159 | const { columnsData } = this.data
160 | columnsData.forEach((v, i) => {
161 | if (columnsData[i].length - 1 < val[i]) {
162 | val[i] = columnsData[i].length - 1
163 | }
164 | })
165 | this.setData({
166 | value: val
167 | })
168 | return val
169 | },
170 | _bindpickend() {
171 | this.data.scrollEnd = true
172 | },
173 | _bindpickstart() {
174 | this.data.scrollEnd = false
175 | },
176 | _openPicker() {
177 | if (!this.data.isFirstOpen) {
178 | if (this.properties.listData.length !== 0) {
179 | this._setDefault(this._computedBackData(this.data.backData))
180 | }
181 | }
182 | this.data.isFirstOpen = false
183 | this.setData({
184 | isOpen: true
185 | })
186 | },
187 | _closePicker() {
188 | this.setData({
189 | isOpen: false
190 | })
191 | },
192 | _getColumnData(arr) {
193 | return arr.map((v) => this._fomateObj(v))
194 | },
195 | _fomateObj(o) {
196 | const tempO = {}
197 | for (const k in o) {
198 | k !== 'children' && (tempO[k] = o[k])
199 | }
200 | return tempO
201 | },
202 | _getScrollCompareIndex(arr1, arr2) {
203 | let tempIndex = -1
204 | for (let i = 0, len = arr1.length; i < len; i++) {
205 | if (arr1[i] !== arr2[i]) {
206 | tempIndex = i
207 | break
208 | }
209 | }
210 | return tempIndex
211 | },
212 | // 根据id获取索引
213 | _getIndexByIdOfObject(listData, idArr, key, arr) {
214 | if (!Array.isArray(listData)) return
215 | for (let i = 0, len = listData.length; i < len; i++) {
216 | if (listData[i][key] === idArr[arr.length][key]) {
217 | arr.push(i)
218 | return this._getIndexByIdOfObject(listData[i].children, idArr, key, arr)
219 | }
220 | }
221 | },
222 | _setDefault(inBackData) {
223 | const { scrollType } = this.properties
224 | let { listData, defaultPickData } = this.properties
225 |
226 | const { lastValue } = this.data
227 | if (inBackData) {
228 | defaultPickData = inBackData
229 | }
230 | let backData = []
231 | switch (scrollType) {
232 | case 'normal':
233 | if (isPlainObject(listData[0][0])) {
234 | this.setData({
235 | isUseKeywordOfShow: true
236 | })
237 | }
238 | if (Array.isArray(defaultPickData) && defaultPickData.length > 0) {
239 | backData = listData.map((v, i) => v[defaultPickData[i]])
240 | this.data.tempValue = defaultPickData
241 | this.data.lastValue = defaultPickData
242 | } else {
243 | backData = listData.map((v) => v[0])
244 | }
245 | this.setData({
246 | columnsData: listData,
247 | backData: backData,
248 | value: defaultPickData
249 | })
250 | break
251 | case 'link':
252 | // let column_01 = this._getColumnData(newVal);
253 | // let column_02 = this._getColumnData(newVal[0].children);
254 | // let column_03 = this._getColumnData(newVal[0].children[0].children);
255 | // let columnsData = [column_01,column_02,column_03];
256 | var columnsData = []
257 | // 如果默认值
258 | if (Array.isArray(defaultPickData) && defaultPickData.length > 0 && defaultPickData.every((v, i) => isPlainObject(v))) {
259 | const key = this.data.onlyKey = Object.keys(defaultPickData[0])[0]
260 |
261 | const arr = []
262 |
263 | this._getIndexByIdOfObject(listData, defaultPickData, key, arr)
264 |
265 | defaultPickData = arr
266 | let tempI = 0
267 | do {
268 | lastValue.push(defaultPickData[tempI])
269 | columnsData.push(this._getColumnData(listData))
270 | listData = listData[defaultPickData[tempI]].children
271 | tempI++
272 | } while (listData)
273 | backData = columnsData.map((v, i) => v[defaultPickData[i]])
274 | // 如果没有默认值
275 | } else {
276 | this.data.onlyKey = this.properties.keyWordsOfShow || 'name'
277 | do {
278 | lastValue.push(0)
279 | columnsData.push(this._getColumnData(listData))
280 | listData = listData[0].children
281 | } while (listData)
282 | backData = columnsData.map((v) => v[0])
283 | }
284 | this.data.tempValue = defaultPickData
285 | this.data.lastValue = defaultPickData
286 | this.setData({
287 | isUseKeywordOfShow: true,
288 | columnsData,
289 | backData
290 | })
291 | setTimeout(() => {
292 | this.setData({
293 | value: defaultPickData
294 | })
295 | }, 0)
296 | break
297 | }
298 | },
299 | _computedBackData(backData) {
300 | const { scrollType, listData } = this.properties
301 | const { onlyKey } = this.data
302 | if (scrollType === 'normal') {
303 | return backData.map((v, i) => listData[i].findIndex((vv, ii) => this._compareObj(v, vv)))
304 | } else {
305 | const t = backData.map((v, i) => {
306 | const o = {}
307 | o[onlyKey] = v[onlyKey]
308 | return o
309 | })
310 |
311 | return t
312 | }
313 | },
314 | _compareObj(o1, o2) {
315 | const { keyWordsOfShow } = this.properties
316 | if (typeof o1 !== 'object') {
317 | return o1 === o2
318 | } else {
319 | return o1[keyWordsOfShow] === o2[keyWordsOfShow]
320 | }
321 | },
322 | _getBackDataFromValue(val) {
323 | let tempArr = []
324 | if (val.length > 0) {
325 | tempArr = this.data.columnsData.reduce((t, v, i) => {
326 | return t.concat(v[val[i]])
327 | }, [])
328 | } else {
329 | tempArr = this.data.columnsData.map((v, i) => v[0])
330 | }
331 | return tempArr
332 | },
333 | _compareDate() { // 完全相等返回true
334 | const { defaultPickDataTemp, listDataTemp } = this.data
335 | const { defaultPickData, listData } = this.properties
336 |
337 | return defaultPickDataTemp === defaultPickData && listDataTemp === listData
338 | },
339 | _setTempData() {
340 | const { defaultPickData, listData } = this.properties
341 | this.data.defaultPickDataTemp = defaultPickData
342 | this.data.listDataTemp = listData
343 | }
344 | }
345 | })
--------------------------------------------------------------------------------
/utils/WxValidate.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 表单验证
3 | *
4 | * @param {Object} rules 验证字段的规则
5 | * @param {Object} messages 验证字段的提示信息
6 | *
7 | */
8 | class WxValidate {
9 | constructor(rules = {}, messages = {}) {
10 | Object.assign(this, {
11 | data: {},
12 | rules,
13 | messages,
14 | })
15 | this.__init()
16 | }
17 |
18 | /**
19 | * __init
20 | */
21 | __init() {
22 | this.__initMethods()
23 | this.__initDefaults()
24 | this.__initData()
25 | }
26 |
27 | /**
28 | * 初始化数据
29 | */
30 | __initData() {
31 | this.form = {}
32 | this.errorList = []
33 | }
34 |
35 | /**
36 | * 初始化默认提示信息
37 | */
38 | __initDefaults() {
39 | this.defaults = {
40 | messages: {
41 | required: '这是必填字段。',
42 | email: '请输入有效的电子邮件地址。',
43 | tel: '请输入11位的手机号码。',
44 | url: '请输入有效的网址。',
45 | date: '请输入有效的日期。',
46 | dateISO: '请输入有效的日期(ISO),例如:2009-06-23,1998/01/22。',
47 | number: '请输入有效的数字。',
48 | digits: '只能输入数字。',
49 | idcard: '请输入18位的有效身份证。',
50 | cardNo: '请正确输入银行卡号',
51 | equalTo: this.formatTpl('输入值必须和 {0} 相同。'),
52 | contains: this.formatTpl('输入值必须包含 {0}。'),
53 | minlength: this.formatTpl('最少要输入 {0} 个字符。'),
54 | maxlength: this.formatTpl('最多可以输入 {0} 个字符。'),
55 | rangelength: this.formatTpl('请输入长度在 {0} 到 {1} 之间的字符。'),
56 | min: this.formatTpl('请输入不小于 {0} 的数值。'),
57 | max: this.formatTpl('请输入不大于 {0} 的数值。'),
58 | range: this.formatTpl('请输入范围在 {0} 到 {1} 之间的数值。'),
59 | }
60 | }
61 | }
62 |
63 | /**
64 | * 初始化默认验证方法
65 | */
66 | __initMethods() {
67 | const that = this
68 | that.methods = {
69 | /**
70 | * 验证必填元素
71 | */
72 | required(value, param) {
73 | if (!that.depend(param)) {
74 | return 'dependency-mismatch'
75 | } else if (typeof value === 'number') {
76 | value = value.toString()
77 | } else if (typeof value === 'boolean') {
78 | return !0
79 | }
80 |
81 | return value.length > 0
82 | },
83 | /**
84 | * 验证电子邮箱格式
85 | */
86 | email(value) {
87 | return that.optional(value) || /^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/.test(value)
88 | },
89 | /**
90 | * 验证手机格式
91 | */
92 | tel(value) {
93 | return that.optional(value) || /^1[34578]\d{9}$/.test(value)
94 | },
95 | /**
96 | * 验证URL格式
97 | */
98 | url(value) {
99 | return that.optional(value) || /^(?:(?:(?:https?|ftp):)?\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})).?)(?::\d{2,5})?(?:[/?#]\S*)?$/i.test(value)
100 | },
101 | /**
102 | * 验证日期格式
103 | */
104 | date(value) {
105 | return that.optional(value) || !/Invalid|NaN/.test(new Date(value).toString())
106 | },
107 | /**
108 | * 验证ISO类型的日期格式
109 | */
110 | dateISO(value) {
111 | return that.optional(value) || /^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])$/.test(value)
112 | },
113 | /**
114 | * 验证十进制数字
115 | */
116 | number(value) {
117 | return that.optional(value) || /^(?:-?\d+|-?\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/.test(value)
118 | },
119 | /**
120 | * 验证整数
121 | */
122 | digits(value) {
123 | return that.optional(value) || /^\d+$/.test(value)
124 | },
125 | /**
126 | * 验证身份证号码
127 | */
128 | idcard(value) {
129 | return that.optional(value) || /^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$/.test(value)
130 | },
131 | /**
132 | * 银行卡
133 | */
134 | cardNo(value) {
135 | return that.optional(value) || /^([1-9]{1})(\d{14}|\d{18})$/.test(value)
136 | },
137 | /**
138 | * 验证两个输入框的内容是否相同
139 | */
140 | equalTo(value, param) {
141 | return that.optional(value) || value === that.data[param]
142 | },
143 | /**
144 | * 验证是否包含某个值
145 | */
146 | contains(value, param) {
147 | return that.optional(value) || value.indexOf(param) >= 0
148 | },
149 | /**
150 | * 验证最小长度
151 | */
152 | minlength(value, param) {
153 | return that.optional(value) || value.length >= param
154 | },
155 | /**
156 | * 验证最大长度
157 | */
158 | maxlength(value, param) {
159 | return that.optional(value) || value.length <= param
160 | },
161 | /**
162 | * 验证一个长度范围[min, max]
163 | */
164 | rangelength(value, param) {
165 | return that.optional(value) || (value.length >= param[0] && value.length <= param[1])
166 | },
167 | /**
168 | * 验证最小值
169 | */
170 | min(value, param) {
171 | return that.optional(value) || value >= param
172 | },
173 | /**
174 | * 验证最大值
175 | */
176 | max(value, param) {
177 | return that.optional(value) || value <= param
178 | },
179 | /**
180 | * 验证一个值范围[min, max]
181 | */
182 | range(value, param) {
183 | return that.optional(value) || (value >= param[0] && value <= param[1])
184 | },
185 | }
186 | }
187 |
188 | /**
189 | * 添加自定义验证方法
190 | * @param {String} name 方法名
191 | * @param {Function} method 函数体,接收两个参数(value, param),value表示元素的值,param表示参数
192 | * @param {String} message 提示信息
193 | */
194 | addMethod(name, method, message) {
195 | this.methods[name] = method
196 | this.defaults.messages[name] = message !== undefined ? message : this.defaults.messages[name]
197 | }
198 |
199 | /**
200 | * 判断验证方法是否存在
201 | */
202 | isValidMethod(value) {
203 | let methods = []
204 | for (let method in this.methods) {
205 | if (method && typeof this.methods[method] === 'function') {
206 | methods.push(method)
207 | }
208 | }
209 | return methods.indexOf(value) !== -1
210 | }
211 |
212 | /**
213 | * 格式化提示信息模板
214 | */
215 | formatTpl(source, params) {
216 | const that = this
217 | if (arguments.length === 1) {
218 | return function () {
219 | let args = Array.from(arguments)
220 | args.unshift(source)
221 | return that.formatTpl.apply(this, args)
222 | }
223 | }
224 | if (params === undefined) {
225 | return source
226 | }
227 | if (arguments.length > 2 && params.constructor !== Array) {
228 | params = Array.from(arguments).slice(1)
229 | }
230 | if (params.constructor !== Array) {
231 | params = [params]
232 | }
233 | params.forEach(function (n, i) {
234 | source = source.replace(new RegExp("\\{" + i + "\\}", "g"), function () {
235 | return n
236 | })
237 | })
238 | return source
239 | }
240 |
241 | /**
242 | * 判断规则依赖是否存在
243 | */
244 | depend(param) {
245 | switch (typeof param) {
246 | case 'boolean':
247 | param = param
248 | break
249 | case 'string':
250 | param = !!param.length
251 | break
252 | case 'function':
253 | param = param()
254 | default:
255 | param = !0
256 | }
257 | return param
258 | }
259 |
260 | /**
261 | * 判断输入值是否为空
262 | */
263 | optional(value) {
264 | return !this.methods.required(value) && 'dependency-mismatch'
265 | }
266 |
267 | /**
268 | * 获取自定义字段的提示信息
269 | * @param {String} param 字段名
270 | * @param {Object} rule 规则
271 | */
272 | customMessage(param, rule) {
273 | const params = this.messages[param]
274 | const isObject = typeof params === 'object'
275 | if (params && isObject) return params[rule.method]
276 | }
277 |
278 | /**
279 | * 获取某个指定字段的提示信息
280 | * @param {String} param 字段名
281 | * @param {Object} rule 规则
282 | */
283 | defaultMessage(param, rule) {
284 | let message = this.customMessage(param, rule) || this.defaults.messages[rule.method]
285 | let type = typeof message
286 |
287 | if (type === 'undefined') {
288 | message = `Warning: No message defined for ${rule.method}.`
289 | } else if (type === 'function') {
290 | message = message.call(this, rule.parameters)
291 | }
292 |
293 | return message
294 | }
295 |
296 | /**
297 | * 缓存错误信息
298 | * @param {String} param 字段名
299 | * @param {Object} rule 规则
300 | * @param {String} value 元素的值
301 | */
302 | formatTplAndAdd(param, rule, value) {
303 | let msg = this.defaultMessage(param, rule)
304 |
305 | this.errorList.push({
306 | param: param,
307 | msg: msg,
308 | value: value,
309 | })
310 | }
311 |
312 | /**
313 | * 验证某个指定字段的规则
314 | * @param {String} param 字段名
315 | * @param {Object} rules 规则
316 | * @param {Object} data 需要验证的数据对象
317 | */
318 | checkParam(param, rules, data) {
319 |
320 | // 缓存数据对象
321 | this.data = data
322 |
323 | // 缓存字段对应的值
324 | const value = data[param] !== null && data[param] !== undefined ? data[param] : ''
325 |
326 | // 遍历某个指定字段的所有规则,依次验证规则,否则缓存错误信息
327 | for (let method in rules) {
328 |
329 | // 判断验证方法是否存在
330 | if (this.isValidMethod(method)) {
331 |
332 | // 缓存规则的属性及值
333 | const rule = {
334 | method: method,
335 | parameters: rules[method]
336 | }
337 |
338 | // 调用验证方法
339 | const result = this.methods[method](value, rule.parameters)
340 |
341 | // 若result返回值为dependency-mismatch,则说明该字段的值为空或非必填字段
342 | if (result === 'dependency-mismatch') {
343 | continue
344 | }
345 |
346 | this.setValue(param, method, result, value)
347 |
348 | // 判断是否通过验证,否则缓存错误信息,跳出循环
349 | if (!result) {
350 | this.formatTplAndAdd(param, rule, value)
351 | break
352 | }
353 | }
354 | }
355 | }
356 |
357 | /**
358 | * 设置字段的默认验证值
359 | * @param {String} param 字段名
360 | */
361 | setView(param) {
362 | this.form[param] = {
363 | $name: param,
364 | $valid: true,
365 | $invalid: false,
366 | $error: {},
367 | $success: {},
368 | $viewValue: ``,
369 | }
370 | }
371 |
372 | /**
373 | * 设置字段的验证值
374 | * @param {String} param 字段名
375 | * @param {String} method 字段的方法
376 | * @param {Boolean} result 是否通过验证
377 | * @param {String} value 字段的值
378 | */
379 | setValue(param, method, result, value) {
380 | const params = this.form[param]
381 | params.$valid = result
382 | params.$invalid = !result
383 | params.$error[method] = !result
384 | params.$success[method] = result
385 | params.$viewValue = value
386 | }
387 |
388 | /**
389 | * 验证所有字段的规则,返回验证是否通过
390 | * @param {Object} data 需要验证数据对象
391 | */
392 | checkForm(data) {
393 | this.__initData()
394 |
395 | for (let param in this.rules) {
396 | this.setView(param)
397 | this.checkParam(param, this.rules[param], data)
398 | }
399 |
400 | return this.valid()
401 | }
402 |
403 | /**
404 | * 返回验证是否通过
405 | */
406 | valid() {
407 | return this.size() === 0
408 | }
409 |
410 | /**
411 | * 返回错误信息的个数
412 | */
413 | size() {
414 | return this.errorList.length
415 | }
416 |
417 | /**
418 | * 返回所有错误信息
419 | */
420 | validationErrors() {
421 | return this.errorList
422 | }
423 | }
424 |
425 | export default WxValidate
--------------------------------------------------------------------------------