cr 4 years ago
commit
2080401327

+ 23 - 0
.env

@@ -0,0 +1,23 @@
1
+# 配置文件(正式环境)
2
+
3
+#node环境(打包为: production,测试为: development)
4
+NODE_ENV = 'production'
5
+
6
+# 运行环境
7
+VUE_APP_ENV = develop
8
+
9
+# 接口请求基地址
10
+VUE_APP_API_BASE_URL = https://whcapi.chuangzhikeji.com
11
+
12
+# 接口请求基地址
13
+VUE_APP_WEBSOCKET_BASE_URL = wss://whcsocket.chuangzhikeji.com
14
+
15
+# 图片基地址
16
+VUE_APP_IMAGE_BASE_URL = https://whcapi.chuangzhikeji.com
17
+VUE_APP_IMAGE_RESOURCE_URL = https://whcoss.chuangzhikeji.com
18
+
19
+# 微信小程序appId
20
+VUE_APP_WX_APPID = wx83192c5ed4977f37
21
+
22
+# 签名加密盐
23
+VUE_APP_SALT =

+ 23 - 0
.env.develop

@@ -0,0 +1,23 @@
1
+# 配置文件(开发环境)
2
+
3
+#node环境(打包为: production,测试为: development)
4
+NODE_ENV = 'production'
5
+
6
+# 运行环境
7
+VUE_APP_ENV = production
8
+
9
+# 接口请求基地址
10
+VUE_APP_API_BASE_URL = https://whc.api.dev.chuangzhikeji.com
11
+
12
+# 接口请求基地址
13
+VUE_APP_WEBSOCKET_BASE_URL = wss://whc.socket.dev.chuangzhikeji.com
14
+
15
+# 图片基地址
16
+VUE_APP_IMAGE_BASE_URL = https://whc.api.dev.chuangzhikeji.com
17
+VUE_APP_IMAGE_RESOURCE_URL = https://whcoss.chuangzhikeji.com
18
+
19
+# 微信小程序appId
20
+VUE_APP_WX_APPID = wxb81eca6ac3c7955c
21
+
22
+# 签名加密盐
23
+VUE_APP_SALT =

+ 23 - 0
.env.production

@@ -0,0 +1,23 @@
1
+# 配置文件(正式环境)
2
+
3
+#node环境(打包为: production,测试为: development)
4
+NODE_ENV = 'production'
5
+
6
+# 运行环境
7
+VUE_APP_ENV = production
8
+
9
+# 接口请求基地址
10
+VUE_APP_API_BASE_URL = https://whcapi.chuangzhikeji.com
11
+
12
+# 接口请求基地址
13
+VUE_APP_WEBSOCKET_BASE_URL = wss://whcsocket.chuangzhikeji.com
14
+
15
+# 图片基地址
16
+VUE_APP_IMAGE_BASE_URL = https://whcapi.chuangzhikeji.com
17
+VUE_APP_IMAGE_RESOURCE_URL = https://whcoss.chuangzhikeji.com
18
+
19
+# 微信小程序appId
20
+VUE_APP_WX_APPID = wx83192c5ed4977f37
21
+
22
+# 签名加密盐
23
+VUE_APP_SALT =

+ 23 - 0
.gitignore

@@ -0,0 +1,23 @@
1
+.DS_Store
2
+node_modules/
3
+unpackage/
4
+dist/
5
+
6
+# local env files
7
+.env.local
8
+.env.*.local
9
+
10
+# Log files
11
+npm-debug.log*
12
+yarn-debug.log*
13
+yarn-error.log*
14
+
15
+# Editor directories and files
16
+.project
17
+.idea
18
+.vscode
19
+*.suo
20
+*.ntvs*
21
+*.njsproj
22
+*.sln
23
+*.sw*

+ 26 - 0
README.md

@@ -0,0 +1,26 @@
1
+# xkjHelperongcheng
2
+
3
+## Project setup
4
+```
5
+yarn install
6
+```
7
+
8
+### Compiles and hot-reloads for development
9
+```
10
+yarn run serve
11
+```
12
+
13
+### Compiles and minifies for production
14
+```
15
+yarn run build
16
+```
17
+
18
+### Run your tests
19
+```
20
+yarn run test
21
+```
22
+
23
+### Lints and fixes files
24
+```
25
+yarn run lint
26
+```

+ 64 - 0
babel.config.js

@@ -0,0 +1,64 @@
1
+const plugins = []
2
+
3
+if (process.env.UNI_OPT_TREESHAKINGNG) {
4
+    plugins.push(require('@dcloudio/vue-cli-plugin-uni-optimize/packages/babel-plugin-uni-api/index.js'))
5
+}
6
+
7
+if (
8
+    (
9
+        process.env.UNI_PLATFORM === 'app-plus' &&
10
+        process.env.UNI_USING_V8
11
+    ) ||
12
+    (
13
+        process.env.UNI_PLATFORM === 'h5' &&
14
+        process.env.UNI_H5_BROWSER === 'builtin'
15
+    )
16
+) {
17
+    const path = require('path')
18
+
19
+    const isWin = /^win/.test(process.platform)
20
+
21
+    const normalizePath = path => (isWin ? path.replace(/\\/g, '/') : path)
22
+
23
+    const input = normalizePath(process.env.UNI_INPUT_DIR)
24
+    try {
25
+        plugins.push([
26
+            require('@dcloudio/vue-cli-plugin-hbuilderx/packages/babel-plugin-console'),
27
+            {
28
+                file(file) {
29
+                    file = normalizePath(file)
30
+                    if (file.indexOf(input) === 0) {
31
+                        return path.relative(input, file)
32
+                    }
33
+                    return false
34
+                },
35
+            },
36
+        ])
37
+    } catch (e) {
38
+    }
39
+}
40
+
41
+process.UNI_LIBRARIES = process.UNI_LIBRARIES || ['@dcloudio/uni-ui']
42
+process.UNI_LIBRARIES.forEach(libraryName => {
43
+    plugins.push([
44
+        'import',
45
+        {
46
+            'libraryName': libraryName,
47
+            'customName': (name) => {
48
+                return `${libraryName}/lib/${name}/${name}`
49
+            },
50
+        },
51
+    ])
52
+})
53
+module.exports = {
54
+    presets: [
55
+        [
56
+            '@vue/app',
57
+            {
58
+                modules: 'commonjs',
59
+                useBuiltIns: process.env.UNI_PLATFORM === 'h5' ? 'usage' : 'entry',
60
+            },
61
+        ],
62
+    ],
63
+    plugins,
64
+}

+ 88 - 0
package.json

@@ -0,0 +1,88 @@
1
+{
2
+    "name": "xkjHelperongcheng",
3
+    "version": "0.1.0",
4
+    "private": true,
5
+    "scripts": {
6
+        "serve": "npm run dev:h5",
7
+        "build": "npm run build:h5",
8
+        "build:app-plus": "cross-env NODE_ENV=production UNI_PLATFORM=app-plus vue-cli-service uni-build",
9
+        "build:custom": "cross-env NODE_ENV=production uniapp-cli custom",
10
+        "build:h5": "cross-env NODE_ENV=production UNI_PLATFORM=h5 vue-cli-service uni-build",
11
+        "build:mp-alipay": "cross-env NODE_ENV=production UNI_PLATFORM=mp-alipay vue-cli-service uni-build",
12
+        "build:mp-baidu": "cross-env NODE_ENV=production UNI_PLATFORM=mp-baidu vue-cli-service uni-build",
13
+        "build:mp-qq": "cross-env NODE_ENV=production UNI_PLATFORM=mp-qq vue-cli-service uni-build",
14
+        "build:mp-toutiao": "cross-env NODE_ENV=production UNI_PLATFORM=mp-toutiao vue-cli-service uni-build",
15
+        "build:mp-weixin-develop": "cross-env NODE_ENV=production UNI_PLATFORM=mp-weixin vue-cli-service uni-build --mode develop",
16
+        "build:mp-weixin-production": "cross-env NODE_ENV=production UNI_PLATFORM=mp-weixin vue-cli-service uni-build --mode production",
17
+        "build:quickapp-native": "cross-env NODE_ENV=production UNI_PLATFORM=quickapp-native vue-cli-service uni-build",
18
+        "build:quickapp-webview": "cross-env NODE_ENV=production UNI_PLATFORM=quickapp-webview vue-cli-service uni-build",
19
+        "dev:app-plus": "cross-env NODE_ENV=development UNI_PLATFORM=app-plus vue-cli-service uni-build --watch",
20
+        "dev:custom": "cross-env NODE_ENV=development uniapp-cli custom",
21
+        "dev:h5": "cross-env NODE_ENV=development UNI_PLATFORM=h5 vue-cli-service uni-serve",
22
+        "dev:mp-alipay": "cross-env NODE_ENV=development UNI_PLATFORM=mp-alipay vue-cli-service uni-build --watch",
23
+        "dev:mp-baidu": "cross-env NODE_ENV=development UNI_PLATFORM=mp-baidu vue-cli-service uni-build --watch",
24
+        "dev:mp-qq": "cross-env NODE_ENV=development UNI_PLATFORM=mp-qq vue-cli-service uni-build --watch",
25
+        "dev:mp-toutiao": "cross-env NODE_ENV=development UNI_PLATFORM=mp-toutiao vue-cli-service uni-build --watch",
26
+        "dev:mp-weixin": "cross-env NODE_ENV=development UNI_PLATFORM=mp-weixin vue-cli-service uni-build --watch --minimize",
27
+        "dev:quickapp-native": "cross-env NODE_ENV=development UNI_PLATFORM=quickapp-native vue-cli-service uni-build --watch",
28
+        "dev:quickapp-webview": "cross-env NODE_ENV=development UNI_PLATFORM=quickapp-webview vue-cli-service uni-build --watch",
29
+        "info": "node node_modules/@dcloudio/vue-cli-plugin-uni/commands/info.js",
30
+        "serve:quickapp-native": "node node_modules/@dcloudio/uni-quickapp-native/bin/serve.js",
31
+        "test:android": "cross-env UNI_PLATFORM=app-plus UNI_OS_NAME=android jest -i",
32
+        "test:h5": "cross-env UNI_PLATFORM=h5 jest -i",
33
+        "test:ios": "cross-env UNI_PLATFORM=app-plus UNI_OS_NAME=ios jest -i",
34
+        "test:mp-baidu": "cross-env UNI_PLATFORM=mp-baidu jest -i",
35
+        "test:mp-weixin": "cross-env UNI_PLATFORM=mp-weixin jest -i"
36
+    },
37
+    "dependencies": {
38
+        "@dcloudio/uni-app-plus": "^2.0.0-27520200518001",
39
+        "@dcloudio/uni-h5": "^2.0.0-27520200518001",
40
+        "@dcloudio/uni-helper-json": "*",
41
+        "@dcloudio/uni-mp-alipay": "^2.0.0-27520200518001",
42
+        "@dcloudio/uni-mp-baidu": "^2.0.0-27520200518001",
43
+        "@dcloudio/uni-mp-qq": "^2.0.0-27520200518001",
44
+        "@dcloudio/uni-mp-toutiao": "^2.0.0-27520200518001",
45
+        "@dcloudio/uni-mp-weixin": "^2.0.0-27520200518001",
46
+        "@dcloudio/uni-quickapp-native": "^2.0.0-27520200518001",
47
+        "@dcloudio/uni-quickapp-webview": "^2.0.0-27520200518001",
48
+        "@dcloudio/uni-stat": "^2.0.0-27520200518001",
49
+        "core-js": "^2.6.5",
50
+        "flyio": "^0.6.2",
51
+        "js-md5": "^0.7.3",
52
+        "regenerator-runtime": "^0.12.1",
53
+        "vue": "^2.6.10",
54
+        "vuex": "^3.2.0",
55
+        "vuex-persistedstate": "^3.0.1"
56
+    },
57
+    "devDependencies": {
58
+        "@dcloudio/types": "*",
59
+        "@dcloudio/uni-automator": "^2.0.0-27520200518001",
60
+        "@dcloudio/uni-cli-shared": "^2.0.0-27520200518001",
61
+        "@dcloudio/uni-migration": "^2.0.0-27520200518001",
62
+        "@dcloudio/uni-template-compiler": "^2.0.0-27520200518001",
63
+        "@dcloudio/vue-cli-plugin-hbuilderx": "^2.0.0-27520200518001",
64
+        "@dcloudio/vue-cli-plugin-uni": "^2.0.0-27520200518001",
65
+        "@dcloudio/vue-cli-plugin-uni-optimize": "^2.0.0-27520200518001",
66
+        "@dcloudio/webpack-uni-mp-loader": "^2.0.0-27520200518001",
67
+        "@dcloudio/webpack-uni-pages-loader": "^2.0.0-27520200518001",
68
+        "@vue/cli-plugin-babel": "^3.0.5",
69
+        "@vue/cli-service": "^3.0.5",
70
+        "babel-plugin-import": "^1.11.0",
71
+        "compression-webpack-plugin": "^4.0.0",
72
+        "cross-env": "^7.0.2",
73
+        "jest": "^25.4.0",
74
+        "mini-types": "*",
75
+        "miniprogram-api-typings": "*",
76
+        "node-sass": "^4.14.1",
77
+        "postcss-comment": "^2.0.0",
78
+        "sass-loader": "^8.0.2",
79
+        "vue-template-compiler": "^2.6.10"
80
+    },
81
+    "browserslist": [
82
+        "Android >= 4",
83
+        "ios >= 8"
84
+    ],
85
+    "uni-app": {
86
+        "scripts": {}
87
+    }
88
+}

+ 22 - 0
postcss.config.js

@@ -0,0 +1,22 @@
1
+const path = require('path')
2
+module.exports = {
3
+    parser: require('postcss-comment'),
4
+    plugins: [
5
+        require('postcss-import')({
6
+            resolve(id, basedir, importOptions) {
7
+                if (id.startsWith('~@/')) {
8
+                    return path.resolve(process.env.UNI_INPUT_DIR, id.substr(3))
9
+                } else if (id.startsWith('@/')) {
10
+                    return path.resolve(process.env.UNI_INPUT_DIR, id.substr(2))
11
+                } else if (id.startsWith('/') && !id.startsWith('//')) {
12
+                    return path.resolve(process.env.UNI_INPUT_DIR, id.substr(1))
13
+                }
14
+                return id
15
+            },
16
+        }),
17
+        require('autoprefixer')({
18
+            remove: process.env.UNI_PLATFORM !== 'h5',
19
+        }),
20
+        require('@dcloudio/vue-cli-plugin-uni/packages/postcss'),
21
+    ],
22
+}

+ 28 - 0
public/index.html

@@ -0,0 +1,28 @@
1
+<!DOCTYPE html>
2
+<html lang="zh-CN">
3
+
4
+<head>
5
+    <meta charset="utf-8">
6
+    <meta http-equiv="X-UA-Compatible" content="IE=edge">
7
+    <title>
8
+        <%= htmlWebpackPlugin.options.title %>
9
+    </title>
10
+    <script>
11
+        document.addEventListener('DOMContentLoaded', function () {
12
+            document.documentElement.style.fontSize = document.documentElement.clientWidth / 20 + 'px'
13
+        })
14
+        var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') || CSS.supports('top: constant(a)'))
15
+        document.write('<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' + (coverSupport ? ', viewport-fit=cover' : '') + '" />')
16
+    </script>
17
+    <link rel="stylesheet" href="<%= BASE_URL %>static/index.<%= VUE_APP_INDEX_CSS_HASH %>.css"/>
18
+</head>
19
+
20
+<body>
21
+    <noscript>
22
+        <strong>Please enable JavaScript to continue.</strong>
23
+    </noscript>
24
+    <div id="app"></div>
25
+    <!-- built files will be auto injected -->
26
+</body>
27
+
28
+</html>

+ 70 - 0
src/App.vue

@@ -0,0 +1,70 @@
1
+<script>
2
+    export default {
3
+        onLaunch: async function (option) {
4
+            const self = this
5
+
6
+            // 调试开关
7
+            uni.setEnableDebug({
8
+                enableDebug: process.env.VUE_APP_ENV === 'develop',
9
+            })
10
+
11
+            // 开发版设置
12
+            if (process.env.VUE_APP_ENV === 'develop') {
13
+
14
+                // 打印接收参数
15
+                console.log(option)
16
+            }
17
+
18
+            uni.getSystemInfo({
19
+                success: function (res) {
20
+                    if (res.model.indexOf('iPhone X') > -1) {
21
+                        self.$store.commit('common/update', {
22
+                            iphoneX: true,
23
+                        })
24
+                    }
25
+                },
26
+            })
27
+        },
28
+
29
+        onShow: async function (option) {
30
+            const self = this
31
+
32
+            // 保存盒子id
33
+            if (option.query.bid) {
34
+                self.$store.commit('user/update', {
35
+                    boxId: option.query.bid,
36
+                })
37
+            }
38
+
39
+            // 保存预览类型
40
+            if (option.query.preview) {
41
+                self.$store.commit('common/update', {
42
+                    preview: option.query.preview,
43
+                })
44
+            }
45
+
46
+            // 登录处理
47
+            // await self.fn.login(option)
48
+
49
+            // 修改配置
50
+            // self.fn.setConfig()
51
+        },
52
+
53
+        onHide: function () {
54
+            const self = this
55
+
56
+            self.$store.commit('user/update', {
57
+                init: false,
58
+            })
59
+        },
60
+    }
61
+</script>
62
+
63
+<style lang="scss">
64
+    @import "common/scss/main";
65
+    @import "common/iconfont/index.css";
66
+
67
+    page {
68
+        background-color: #f8f8f8;
69
+    }
70
+</style>

+ 252 - 0
src/common/api/ajax.js

@@ -0,0 +1,252 @@
1
+import qs from 'qs'
2
+import md5 from 'js-md5'
3
+import config from '../js/config'
4
+import fn from '../js/function'
5
+import plugin from '../js/plugin'
6
+import store from '../store'
7
+
8
+const http = {
9
+    /**
10
+     * ajax请求处理
11
+     * @param type
12
+     * @param url
13
+     * @param data
14
+     * @param map
15
+     * @param repeat
16
+     * @param awaitTime
17
+     * @param isJson
18
+     * @returns {Promise<*|Promise<any>|Promise<Promise<any>|*>>}
19
+     */
20
+    async ajax(type, url, data = {}, {map = {}, repeat = false, awaitTime = 1000, isJson = false} = {}) {
21
+        const self = this
22
+        let httpKey = md5(url + qs.stringify(data))
23
+        let ContentType = 'application/x-www-form-urlencoded;charset=UTF-8;'
24
+
25
+        // 重复请求检测
26
+        if (repeat) {
27
+            let httpInfo = store.state.http[httpKey]
28
+
29
+            if (httpInfo && self.isRepeat(httpKey)) {
30
+                console.warn('重复请求过滤')
31
+                return new Promise((resolve) => {
32
+                    resolve({
33
+                        code: '-1',
34
+                        data: '',
35
+                        message: '正在处理中,请稍等...',
36
+                        requestData: '',
37
+                    })
38
+                })
39
+            } else {
40
+                // 记录请求信息
41
+                store.commit('http/add', httpKey)
42
+            }
43
+        }
44
+
45
+        // 请求数据处理
46
+        data = self.request(data, map)
47
+
48
+        // get请求url处理
49
+        if (type === 'GET') {
50
+            data = qs.stringify(data)
51
+            url = url + '?' + data
52
+        }
53
+
54
+        // json请求类型处理,兼容后台接口混乱问题
55
+        if (isJson) {
56
+            ContentType = 'application/json;charset=UTF-8;'
57
+        } else {
58
+            data = qs.stringify(data)
59
+        }
60
+
61
+        // 添加请求基地址
62
+        if (url.indexOf('http') < 0) {
63
+            url = config.apiBaseUrl + url
64
+        }
65
+
66
+        // 发送请求
67
+        let response = await uni.request({
68
+            url: url,
69
+            data: data,
70
+            header: {
71
+                'Accept': 'application/json',
72
+                'Content-Type': ContentType,
73
+                'appId': store.state.user.appId,
74
+                'companyId': store.state.user.companyId,
75
+                'userId': store.state.user.userId,
76
+                'Authorization': 'Bearer ' + store.state.user.token,
77
+            },
78
+            method: type,
79
+        })
80
+
81
+        return self.response(response, {
82
+            map: map,
83
+            httpKey: httpKey,
84
+            repeat: repeat,
85
+            awaitTime: awaitTime,
86
+            request: arguments,
87
+        })
88
+    },
89
+
90
+    /**
91
+     * 是否是重复请求处理
92
+     * @param httpKey
93
+     * @returns {boolean}
94
+     */
95
+    isRepeat(httpKey) {
96
+        let httpInfo = store.state.http[httpKey]
97
+        let nowTime = new Date().getTime()
98
+        let outTime = 5
99
+
100
+        return httpInfo && nowTime < httpInfo + outTime * 1000
101
+    },
102
+
103
+    /**
104
+     * 请求参数处理
105
+     * @param data
106
+     * @param map
107
+     * @returns {*}
108
+     */
109
+    request(data, map) {
110
+        const self = this
111
+
112
+        // data.device = data.device || 'web'
113
+        // data.timestamp = data.timestamp || self.getTimestamp()
114
+        // data.noncestr = data.noncestr || fn.uuid('')
115
+
116
+        // 请求数据映射处理
117
+        data = fn.deepClone(data)
118
+        data = fn.objSetKey(data, map)
119
+
120
+        for (let key in data) {
121
+            if (data.hasOwnProperty(key) && (data[key] === undefined)) {
122
+                delete data[key]
123
+            }
124
+        }
125
+
126
+        // 签名处理
127
+        // data = self.setSign(data)
128
+
129
+        return data
130
+    },
131
+
132
+    /**
133
+     * 获取时间戳
134
+     */
135
+    getTimestamp() {
136
+        let differTimestamp = store.state.common.differTimestamp || 0
137
+        let localTimestamp = parseInt(new Date().getTime() / 1000)
138
+
139
+        return localTimestamp + differTimestamp
140
+    },
141
+
142
+    /**
143
+     * 添加签名处理
144
+     * @param data
145
+     * @returns {*|{}}
146
+     */
147
+    setSign(data) {
148
+        let sign = '' // 签名
149
+
150
+        data = fn.objSort(data)
151
+        sign = decodeURIComponent(qs.stringify(data))
152
+        data.sign = md5(sign + config.salt)
153
+
154
+        return data
155
+    },
156
+
157
+    /**
158
+     * 请求响应处理
159
+     * @param res
160
+     * @param map
161
+     * @param repeat
162
+     * @param httpKey
163
+     * @param awaitTime
164
+     * @param request
165
+     * @returns {Promise<any>}
166
+     */
167
+    response(res, {map = {}, httpKey = '', repeat = false, awaitTime = '', request = []} = {}) {
168
+        const self = this
169
+
170
+        return new Promise(async resolve => {
171
+            let response = res[1]
172
+            let data = {
173
+                success: response.data.success,
174
+                affectedRows: response.data.affectedRows,
175
+                code: response.data.code,
176
+                message: '无法访问到服务器',
177
+                data: '',
178
+            }
179
+
180
+            // 移除请求记录
181
+            if (repeat) {
182
+                setTimeout(function () {
183
+                    store.commit('http/success', httpKey)
184
+                }, awaitTime)
185
+            }
186
+
187
+            // 请求成功数据处理
188
+            if (response.statusCode === 200) {
189
+                data = {
190
+                    success: response.data.success,
191
+                    affectedRows: response.data.affectedRows,
192
+                    code: response.data.code,
193
+                    message: response.data.message || '',
194
+                    data: fn.objSetKey(response.data.data, map, true),
195
+                }
196
+            } else if (response.statusCode === 401) {
197
+                await plugin.getToken()
198
+                data = await self.ajax(request[0], request[1], request[2], request[3])
199
+            } else {
200
+                console.error(response.data)
201
+            }
202
+
203
+            resolve(data)
204
+        })
205
+    },
206
+}
207
+
208
+export default {
209
+    /**
210
+     * get请求(获取)
211
+     * @param url
212
+     * @param data
213
+     * @param config
214
+     * @returns {*}
215
+     */
216
+    get(url, data, config) {
217
+        return http.ajax('GET', url, data, config)
218
+    },
219
+
220
+    /**
221
+     * post请求(添加)
222
+     * @param url
223
+     * @param data
224
+     * @param config
225
+     * @returns {*}
226
+     */
227
+    post(url, data, config) {
228
+        return http.ajax('POST', url, data, config)
229
+    },
230
+
231
+    /**
232
+     * put请求(修改)
233
+     * @param url
234
+     * @param data
235
+     * @param config
236
+     * @returns {*}
237
+     */
238
+    put(url, data, config) {
239
+        return http.ajax('PUT', url, data, config)
240
+    },
241
+
242
+    /**
243
+     * delete请求(删除)
244
+     * @param url
245
+     * @param data
246
+     * @param config
247
+     * @returns {*}
248
+     */
249
+    delete(url, data, config) {
250
+        return http.ajax('DELETE', url, data, config)
251
+    },
252
+}

+ 91 - 0
src/common/api/index.js

@@ -0,0 +1,91 @@
1
+import qs from 'qs'
2
+import ajax from './ajax'
3
+import plugin from '../js/plugin'
4
+import store from '../store'
5
+
6
+export default {
7
+
8
+    /**
9
+     * get请求
10
+     * @param data
11
+     * @param url
12
+     * @param config
13
+     * @returns {Promise<any>}
14
+     */
15
+    get(url, data = {}, config = {}) {
16
+        return new Promise((resolve, reject) => {
17
+            ajax.get(url, {
18
+                preview: Number(store.state.common.preview),
19
+                ...data,
20
+            }, {
21
+                ...config,
22
+            }).then(res => {
23
+                if (res.code === '0' || config.pass === true) {
24
+                    resolve(res)
25
+                } else {
26
+                    plugin.showToast(res.message)
27
+                    reject(res)
28
+                }
29
+            })
30
+        })
31
+    },
32
+
33
+    /**
34
+     * post请求
35
+     * @param url
36
+     * @param data
37
+     * @param config
38
+     * @returns {Promise<any>}
39
+     */
40
+    post(url, data = {query: ''}, config = {}) {
41
+        if (data.query) {
42
+            url = url + '?' + qs.stringify(data)
43
+            delete data.query
44
+        }
45
+
46
+        return new Promise((resolve, reject) => {
47
+            ajax.post(url, {
48
+                preview: Number(store.state.common.preview),
49
+                ...data,
50
+            }, {
51
+                isJson: true,
52
+                ...config,
53
+            }).then(res => {
54
+                if (res.code === '0' || config.pass === true) {
55
+                    resolve(res)
56
+                } else {
57
+                    plugin.showToast(res.message)
58
+                    reject(res)
59
+                }
60
+            })
61
+        })
62
+    },
63
+
64
+    /**
65
+     * delete请求
66
+     * @param data
67
+     * @param url
68
+     * @returns {Promise<any>}
69
+     */
70
+    delete(url, data = {query: ''}) {
71
+        if (data.query) {
72
+            url = url + '?' + qs.stringify(data)
73
+            delete data.query
74
+        }
75
+
76
+        return new Promise((resolve, reject) => {
77
+            ajax.delete(url, {
78
+                ...data,
79
+            }, {
80
+                isJson: true,
81
+            }).then(res => {
82
+                if (res.code === '0' || config.pass === true) {
83
+                    resolve(res)
84
+                } else {
85
+                    plugin.showToast(res.message)
86
+                    reject(res)
87
+                }
88
+            })
89
+        })
90
+    },
91
+}

File diff suppressed because it is too large
+ 132 - 0
src/common/iconfont/index.css


+ 12 - 0
src/common/js/config.js

@@ -0,0 +1,12 @@
1
+export default {
2
+    nodeEnv: process.env.NODE_ENV, // node运行环境
3
+    appEnv: process.env.VUE_APP_ENV, // APP运行环境
4
+    apiBaseUrl: process.env.VUE_APP_API_BASE_URL, // 接口基地址
5
+    websocketUrl: process.env.VUE_APP_WEBSOCKET_BASE_URL, // websocket基地址
6
+    fileUploadUrl: process.env.VUE_APP_API_BASE_URL, // 文件上传地址
7
+    fileUrl: process.env.VUE_APP_IMAGE_BASE_URL + '/', // 文件基地址
8
+    imageUrl: process.env.VUE_APP_IMAGE_BASE_URL + '/', // 图片基地址
9
+    imageResourceUrl: process.env.VUE_APP_IMAGE_RESOURCE_URL + '/', // 项目图片基地址
10
+    salt: process.env.VUE_APP_SALT, // 签名加密盐
11
+    appId: process.env.VUE_APP_WX_APPID,// 微信appid
12
+}

+ 177 - 0
src/common/js/filters.js

@@ -0,0 +1,177 @@
1
+/**
2
+ *  日期转xx之前
3
+ * @param dateStr 日期字符串 eg:2019-12-30T02:14:14.000+0000
4
+ * @return {string}
5
+ **/
6
+export function dateView(dateStr) {
7
+    if (!dateStr) {
8
+        return ''
9
+    }
10
+    if (isNaN(Date.parse(dateStr))) {
11
+        return dateStr
12
+    }
13
+    dateStr = dateStr.replace(/-/g, '/')
14
+    let dateNow = Date.parse(dateStr)
15
+
16
+    let mius = Date.now() - dateNow
17
+    let minute = 1000 * 60
18
+    let hour = minute * 60
19
+    let day = hour * 24
20
+    let month = day * 30
21
+    let quarter = month * 3
22
+    let year = quarter * 12
23
+    if (mius < minute) {
24
+        return '刚刚'
25
+    } else if (mius < hour) {
26
+        return Math.floor(mius / minute) + '分钟前'
27
+    } else if (mius < day) {
28
+        return Math.floor(mius / hour) + '小时前'
29
+    } else if (mius < month) {
30
+        return Math.floor(mius / day) + '天前'
31
+    } else if (mius < quarter) {
32
+        return Math.floor(mius / month) + '个月前'
33
+    } else if (mius < year) {
34
+        return Math.floor(mius / quarter) + '季度前'
35
+    } else {
36
+        return Math.floor(mius / year) + '年前'
37
+    }
38
+}
39
+
40
+/**
41
+ * 转化为指定格式日期
42
+ * @param date
43
+ * @param format
44
+ * @returns {string}
45
+ */
46
+export function dateFormat(date, format = 'yyyy-MM-dd') {
47
+    if (date) {
48
+        date = date.replace(/-/g, '/')
49
+        date = new Date(Date.parse(date))
50
+
51
+        let o = {
52
+            'M+': date.getMonth() + 1, //月份
53
+            'd+': date.getDate(), //日
54
+            'h+': date.getHours(), //小时
55
+            'm+': date.getMinutes(), //分
56
+            's+': date.getSeconds(), //秒
57
+            'S': date.getMilliseconds(), //毫秒
58
+            'q+': Math.floor((date.getMonth() + 3) / 3), //季度
59
+        }
60
+
61
+        if (/(y+)/.test(format)) {
62
+            format = format.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length))
63
+        }
64
+        for (let k in o) {
65
+            if (new RegExp('(' + k + ')').test(format)) {
66
+                format = format.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (('00' + o[k]).substr(('' + o[k]).length)))
67
+            }
68
+        }
69
+        return format
70
+    } else {
71
+        return date
72
+    }
73
+}
74
+
75
+/**
76
+ * 手机号中间4位隐藏
77
+ * @param str
78
+ * @returns {string|*}
79
+ */
80
+export function phoneHide(str) {
81
+    if (str) {
82
+        return str.substr(0, 3) + ' **** ' + str.substr(7)
83
+    } else {
84
+        return str
85
+    }
86
+}
87
+
88
+/**
89
+ *  日期转(今天、昨天、前天)
90
+ * @param date 日期字符串 eg:2019-12-30T02:14:14.000+0000
91
+ * @return {string}
92
+ **/
93
+export function dateView2(date) {
94
+    date = date.replace(/-/g, '/')
95
+    date = Date.parse(date)
96
+
97
+    let tt = new Date(date)
98
+    let days = parseInt((new Date().getTime() - date) / 86400000)
99
+    let today = new Date().getDate()
100
+    let mouth = tt.getMonth() + 1
101
+    let day = tt.getDate()
102
+    let result, offset
103
+    offset = Math.abs(today - day)
104
+    mouth = mouth < 10 ? '0' + mouth : mouth
105
+    day = day < 10 ? '0' + day : day
106
+
107
+    if (days < 4 && offset < 4) {
108
+        if (offset === 0) {
109
+            result = '今天'
110
+        } else if (offset === 1) {
111
+            result = '昨天'
112
+        } else if (offset === 2) {
113
+            result = '前天'
114
+        }
115
+    } else {
116
+        result = mouth + '-' + day
117
+    }
118
+    return result
119
+}
120
+
121
+/**
122
+ * 时间戳转化为指定格式日期
123
+ * @param val
124
+ * @param format
125
+ * @returns {string}
126
+ */
127
+export function timestampToDate(val, format = 'yyyy-MM-dd') {
128
+    if (val) {
129
+        let date = new Date(val)
130
+
131
+        let o = {
132
+            'M+': date.getMonth() + 1, //月份
133
+            'd+': date.getDate(), //日
134
+            'h+': date.getHours(), //小时
135
+            'm+': date.getMinutes(), //分
136
+            's+': date.getSeconds(), //秒
137
+            'S': date.getMilliseconds(), //毫秒
138
+            'q+': Math.floor((date.getMonth() + 3) / 3), //季度
139
+        }
140
+
141
+        if (/(y+)/.test(format)) {
142
+            format = format.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length))
143
+        }
144
+        for (let k in o) {
145
+            if (new RegExp('(' + k + ')').test(format)) {
146
+                format = format.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (('00' + o[k]).substr(('' + o[k]).length)))
147
+            }
148
+        }
149
+        return format
150
+    } else {
151
+        return val
152
+    }
153
+}
154
+
155
+/**
156
+ * 分转换为人民币
157
+ * @param val
158
+ * @param format
159
+ * @returns {string}
160
+ */
161
+export function minuteToRmb(val) {
162
+    val = val || 0
163
+
164
+    return (Number(val) / 100).toFixed(2)
165
+}
166
+
167
+/**
168
+ * 分转换为人民币
169
+ * @param val
170
+ * @param format
171
+ * @returns {string}
172
+ */
173
+export function minuteToRmb2(val) {
174
+    val = val || 0
175
+
176
+    return Number(val) / 100
177
+}

+ 361 - 0
src/common/js/function.js

@@ -0,0 +1,361 @@
1
+import md5 from 'js-md5'
2
+import plugin from './plugin'
3
+
4
+export default {
5
+    /**
6
+     * 判断数据类型
7
+     * @param obj
8
+     * @returns {*}
9
+     */
10
+    getType(obj) {
11
+        let toString = Object.prototype.toString
12
+        let map = {
13
+            '[object Boolean]': 'boolean',
14
+            '[object Number]': 'number',
15
+            '[object String]': 'string',
16
+            '[object Function]': 'function',
17
+            '[object Array]': 'array',
18
+            '[object Date]': 'date',
19
+            '[object RegExp]': 'regExp',
20
+            '[object Undefined]': 'undefined',
21
+            '[object Null]': 'null',
22
+            '[object Object]': 'object',
23
+        }
24
+        return map[toString.call(obj)]
25
+    },
26
+
27
+    /**
28
+     * 获取系统类型
29
+     * @returns {{userAgent: string, isAndroid: boolean, isIphone: boolean, isIpad: boolean, isWeixin: boolean}}
30
+     */
31
+    getOsType() {
32
+        //#ifdef H5
33
+        return {
34
+            userAgent: navigator.userAgent.toLowerCase(),
35
+            isAndroid: Boolean(navigator.userAgent.match(/android/ig)),
36
+            isIphone: Boolean(navigator.userAgent.match(/iphone|ipod/ig)),
37
+            isIpad: Boolean(navigator.userAgent.match(/ipad/ig)),
38
+            isWeixin: Boolean(navigator.userAgent.match(/MicroMessenger/ig)),
39
+            isAlipay: Boolean(navigator.userAgent.match(/AlipayClient/ig)),
40
+        }
41
+        //#endif
42
+
43
+        //#ifndef H5
44
+        return {
45
+            userAgent: '',
46
+            isAndroid: false,
47
+            isIphone: false,
48
+            isIpad: false,
49
+            isWeixin: false,
50
+            isAlipay: false,
51
+        }
52
+        //#endif
53
+    },
54
+
55
+    /**
56
+     * 深拷贝
57
+     * @param data
58
+     * @returns {*}
59
+     */
60
+    deepClone(data) {
61
+        const self = this
62
+        let result = {}
63
+        let type = self.getType(data)
64
+
65
+        if (type === 'array') {
66
+            result = []
67
+            data.forEach(item => {
68
+                result.push(self.deepClone(item))
69
+            })
70
+        } else if (type === 'object') {
71
+            for (let key in data) {
72
+                if (data.hasOwnProperty(key)) {
73
+                    result[key] = self.deepClone(data[key])
74
+                }
75
+            }
76
+        } else {
77
+            return data
78
+        }
79
+
80
+        return result
81
+    },
82
+
83
+    /**
84
+     * 对象键值映射(默认从左到右)
85
+     * @param data
86
+     * @param map
87
+     * @param orientation
88
+     * @returns {*}
89
+     */
90
+    objSetKey(data, map, orientation = false) {
91
+        const self = this
92
+
93
+        if (self.getType(data) === 'object') {
94
+            // 映射处理(对象数据处理)
95
+            for (let key in map) {
96
+                if (map.hasOwnProperty(key)) {
97
+                    let val = map[key]
98
+                    if (val && val !== key) {
99
+                        if (orientation) {
100
+                            [key, val] = [val, key]
101
+                        }
102
+
103
+                        if (data[key]) {
104
+                            data[val] = data[key]
105
+                            delete data[key]
106
+                        }
107
+                    }
108
+                }
109
+            }
110
+
111
+            // 子数据处理
112
+            for (let key in data) {
113
+                if (data.hasOwnProperty(key)) {
114
+                    let val = data[key]
115
+                    if (self.getType(val) === 'array' || self.getType(val) === 'object') {
116
+                        data[key] = self.objSetKey(val, map, orientation)
117
+                    }
118
+                }
119
+            }
120
+        } else if (self.getType(data) === 'array') {
121
+            // 数组递归处理
122
+            data.forEach((item, index) => {
123
+                item = self.objSetKey(item, map, orientation)
124
+                data.splice(index, 1, item)
125
+            })
126
+        }
127
+        return data
128
+    },
129
+
130
+    /**
131
+     * 对象排序
132
+     * @param obj
133
+     * @returns {{}}
134
+     */
135
+    objSort(obj) {
136
+        let newKey = Object.keys(obj).sort()
137
+        let newObj = {}
138
+        for (let i = 0; i < newKey.length; i++) {
139
+            newObj[newKey[i]] = obj[newKey[i]]
140
+        }
141
+        return newObj
142
+    },
143
+
144
+    /**
145
+     * 生成uuid的没4位数
146
+     * @returns {string}
147
+     * @constructor
148
+     */
149
+    S4() {
150
+        return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1)
151
+    },
152
+
153
+    /**
154
+     * 生成uuid
155
+     * @param separator
156
+     * @returns {string}
157
+     */
158
+    uuid(separator = '-') {
159
+        const self = this
160
+        return (self.S4() + self.S4() + separator + self.S4() + separator + self.S4() + separator + self.S4() + separator + self.S4() + self.S4() + self.S4())
161
+    },
162
+
163
+    /**
164
+     * 创建随机字符串
165
+     * @param num
166
+     * @returns {string} (0-9,a-z)
167
+     */
168
+    randomString(num) {
169
+        let chars = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
170
+        let res = ''
171
+        for (let i = 0; i < num; i++) {
172
+            let id = Math.ceil(Math.random() * 35)
173
+            res += chars[id]
174
+        }
175
+        return res
176
+    },
177
+
178
+    /**
179
+     * 去除2端空格
180
+     * @param string
181
+     */
182
+    trim(string) {
183
+        if (typeof string === 'string') {
184
+            return string.replace(/^\s\s*/, '').replace(/\s\s*$/, '')
185
+        } else {
186
+            return string
187
+        }
188
+    },
189
+
190
+    /**
191
+     * md5加密
192
+     * @param string
193
+     * @returns {*}
194
+     */
195
+    md5(string) {
196
+        return md5(string)
197
+    },
198
+
199
+    /**
200
+     * 获取服务时间列表
201
+     * @param startDay
202
+     * @param length
203
+     */
204
+    getDateList(startDay = 0, length = 7) {
205
+        let dateList = []
206
+        let week = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'] // 星期
207
+        for (let i = 0; i < length; i++) {
208
+            let tmp = ''
209
+            let date = new Date()
210
+            date.setDate(date.getDate() + i + startDay)
211
+            tmp = date.getMonth() + 1 + '月' + (date.getDate()) + '日[' + week[date.getDay()] + ']'
212
+            dateList.push(tmp)
213
+        }
214
+        return dateList
215
+    },
216
+
217
+    /**
218
+     * 获取格式化后的时间
219
+     * @param date
220
+     * @param format
221
+     * @returns {string}
222
+     */
223
+    getDateFormat(date, format = 'yyyy-MM-dd') {
224
+        let o = {
225
+            'M+': date.getMonth() + 1, //月份
226
+            'd+': date.getDate(), //日
227
+            'h+': date.getHours(), //小时
228
+            'm+': date.getMinutes(), //分
229
+            's+': date.getSeconds(), //秒
230
+            'S': date.getMilliseconds(), //毫秒
231
+            'q+': Math.floor((date.getMonth() + 3) / 3), //季度
232
+        }
233
+
234
+        if (/(y+)/.test(format)) {
235
+            format = format.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length))
236
+        }
237
+        for (let k in o) {
238
+            if (new RegExp('(' + k + ')').test(format)) {
239
+                format = format.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (('00' + o[k]).substr(('' + o[k]).length)))
240
+            }
241
+        }
242
+
243
+        return format
244
+    },
245
+
246
+    /**
247
+     * 格式化时间
248
+     * @param val
249
+     * @param format
250
+     * @returns {string|*}
251
+     */
252
+    timestampToDate(val, format = 'yyyy-MM-dd') {
253
+        val = val.replace(/-/g, '/')
254
+
255
+        if (val) {
256
+            let date = new Date(val)
257
+
258
+            let o = {
259
+                'M+': date.getMonth() + 1, //月份
260
+                'd+': date.getDate(), //日
261
+                'h+': date.getHours(), //小时
262
+                'm+': date.getMinutes(), //分
263
+                's+': date.getSeconds(), //秒
264
+                'S': date.getMilliseconds(), //毫秒
265
+                'q+': Math.floor((date.getMonth() + 3) / 3), //季度
266
+            }
267
+
268
+            if (/(y+)/.test(format)) {
269
+                format = format.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length))
270
+            }
271
+            for (let k in o) {
272
+                if (new RegExp('(' + k + ')').test(format)) {
273
+                    format = format.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (('00' + o[k]).substr(('' + o[k]).length)))
274
+                }
275
+            }
276
+            return format
277
+        } else {
278
+            return val
279
+        }
280
+    },
281
+
282
+    /**
283
+     * 富文本标签添加class
284
+     */
285
+    classAdd(string, label, className) {
286
+        if (this.getType(string) === 'string' && string) {
287
+            if (label === 'p') {
288
+                return string
289
+                    .replace(/<p([\s\w"=\/\.:;]+)((?:(style="[^"]+")))/ig, '<p')
290
+                    .replace(/<p([\s\w"=\/\.:;]+)((?:(class="[^"]+")))/ig, '<p')
291
+                    .replace(/<p>/ig, '<p class="' + className + '">')
292
+            } else if (label === 'img') {
293
+                return string
294
+                    .replace(/<img([\s\w"-=\/\.:;]+)((?:(height="[^"]+")))/ig, '<img$1')
295
+                    .replace(/<img([\s\w"-=\/\.:;]+)((?:(width="[^"]+")))/ig, '<img$1')
296
+                    .replace(/<img([\s\w"-=\/\.:;]+)((?:(style="[^"]+")))/ig, '<img$1')
297
+                    .replace(/<img([\s\w"-=\/\.:;]+)((?:(alt="[^"]+")))/ig, '<img$1')
298
+                    .replace(/<img([\s\w"-=\/\.:;]+)/ig, '<img$1 class="' + className + '"')
299
+            }
300
+        } else {
301
+            return string
302
+        }
303
+    },
304
+
305
+    /**
306
+     * 数组转字符串逗号分隔
307
+     * @param str
308
+     * @returns {string}
309
+     */
310
+    arrToStr(arr) {
311
+        let str = ''
312
+        if (arr) {
313
+            for (let item of arr) {
314
+                str += item + ','
315
+            }
316
+            str = str.replace(/,$/igm, '')
317
+        }
318
+
319
+        return str
320
+    },
321
+
322
+    /**
323
+     * 客服
324
+     * @param str
325
+     * @returns {string}
326
+     */
327
+    kefu() {
328
+        //#ifdef H5
329
+        window.doyoo.util.openChat('g=10085481')
330
+        //#endif
331
+
332
+        //#ifndef H5
333
+        plugin.showToast('客服升级中')
334
+        //#endif
335
+    },
336
+
337
+    /**
338
+     * 数组切割
339
+     * @param array
340
+     * @param length
341
+     * @returns {Array|default}
342
+     */
343
+    arrayChunk(array, length) {
344
+        length = parseInt(length)
345
+
346
+        //如果长度小于要划分的长度,返回原数组
347
+        if (length <= 1 || this.length < length) {
348
+            return array
349
+        }
350
+
351
+        let groups = []
352
+        let number = Math.ceil(array.length / length)// 拆分成的二维数组的个数
353
+
354
+        //用slice方法,每四个截取一次
355
+        for (let i = 0; i < number; i++) {
356
+            groups.push(array.slice(length * i, length * (i + 1)))
357
+        }
358
+
359
+        return groups
360
+    },
361
+}

+ 7 - 0
src/common/js/index.js

@@ -0,0 +1,7 @@
1
+import fn from './function'
2
+import plugin from './plugin'
3
+
4
+export default {
5
+    ...fn,
6
+    ...plugin,
7
+}

+ 26 - 0
src/common/js/log.js

@@ -0,0 +1,26 @@
1
+const log = wx.getRealtimeLogManager ? wx.getRealtimeLogManager() : null
2
+
3
+export default {
4
+    info() {
5
+        if (!log) return
6
+        log.info.apply(log, arguments)
7
+    },
8
+    warn() {
9
+        if (!log) return
10
+        log.warn.apply(log, arguments)
11
+    },
12
+    error() {
13
+        if (!log) return
14
+        log.error.apply(log, arguments)
15
+    },
16
+    setFilterMsg(msg) { // 从基础库2.7.3开始支持
17
+        if (!log || !log.setFilterMsg) return
18
+        if (typeof msg !== 'string') return
19
+        log.setFilterMsg(msg)
20
+    },
21
+    addFilterMsg(msg) { // 从基础库2.8.1开始支持
22
+        if (!log || !log.addFilterMsg) return
23
+        if (typeof msg !== 'string') return
24
+        log.addFilterMsg(msg)
25
+    },
26
+}

+ 300 - 0
src/common/js/plugin.js

@@ -0,0 +1,300 @@
1
+import api from '../api/index'
2
+import store from '../store/index'
3
+import router from './router'
4
+import config from './config'
5
+import qs from 'qs'
6
+
7
+export default {
8
+    /**
9
+     * 消息提示
10
+     * @param title
11
+     */
12
+    showToast(title = '') {
13
+        let config = {}
14
+
15
+        if (typeof title === 'string') {
16
+            config.title = title
17
+        } else {
18
+            config = title
19
+        }
20
+
21
+        uni.showToast({
22
+            title: config.title || '',
23
+            icon: 'none',
24
+            duration: 2000,
25
+        })
26
+    },
27
+
28
+    /**
29
+     *  显示模态弹窗
30
+     * @param config
31
+     * @returns {Promise<any>}
32
+     */
33
+    showModal(config = {}) {
34
+        return new Promise(resolve => {
35
+            uni.showModal({
36
+                title: config.title || '温馨提示', //标题
37
+                content: config.content || '', //内容
38
+                showCancel: config.showCancel === false ? config.showCancel : true, //是否显示取消按钮
39
+                cancelText: config.cancelText || '取消', //取消按钮的文字
40
+                cancelColor: config.cancelColor || '#000', //取消按钮的文字颜色
41
+                confirmText: config.confirmText || '确定', //确定按钮的文字
42
+                confirmColor: config.confirmColor || '#000', //确定按钮的文字颜色
43
+                success: res => {
44
+                    resolve(res)
45
+                },
46
+                fail: res => {
47
+                    resolve(res)
48
+                },
49
+            })
50
+        })
51
+    },
52
+
53
+    /**
54
+     * ​显示操作菜单
55
+     * @param list
56
+     * @returns {Promise<any>}
57
+     */
58
+    showActionSheet(list = []) {
59
+        if (list.length) {
60
+            return new Promise(resolve => {
61
+                uni.showActionSheet({
62
+                    itemList: list,
63
+                    success: res => {
64
+                        resolve(res.tapIndex)
65
+                    },
66
+                    fail: () => {
67
+                        console.log('取消选择')
68
+                    },
69
+                })
70
+            })
71
+        } else {
72
+            console.log('至少需要一个元素')
73
+        }
74
+    },
75
+
76
+    /**
77
+     * 设置标题
78
+     * @param title
79
+     */
80
+    setTitle(title) {
81
+        if (title) {
82
+            uni.setNavigationBarTitle({
83
+                title: decodeURIComponent(title),
84
+            })
85
+        }
86
+    },
87
+
88
+    /**
89
+     * 打开分享菜单
90
+     * @param config
91
+     */
92
+    shareMenu(config) {
93
+        // #ifdef MP-WEIXIN
94
+        uni.showShareMenu({
95
+            withShareTicket: true,
96
+            ...config,
97
+        })
98
+        // #endif
99
+    },
100
+
101
+    /**
102
+     * 更新用户信息
103
+     */
104
+    updateUserInfo() {
105
+        // 用户微信信息
106
+        api.get('/User/GerUserInfo').then(res => {
107
+            store.commit('user/update', {
108
+                userInfo: res.data,
109
+            })
110
+        })
111
+
112
+        // 用户积分、会员身份
113
+        api.get('/My/GetMy').then(res => {
114
+            if (res.data) {
115
+                store.commit('user/update', {
116
+                    integral: res.data.pointsInfo.points,
117
+                })
118
+            }
119
+        })
120
+    },
121
+
122
+    /**
123
+     * 支付
124
+     * @param orderId
125
+     * @param price
126
+     */
127
+    pay(orderId, price, jump = false) {
128
+        const self = this
129
+
130
+        return new Promise(resolve => {
131
+            if (store.state.common.payStatus) {
132
+                console.log('支付中...')
133
+
134
+                // 改为支付中的状态
135
+                store.commit('common/update', {
136
+                    payStatus: false,
137
+                })
138
+
139
+                api.post('/Order/Pay', {
140
+                    payMethod: 'WeiXin',
141
+                    orderId: orderId,
142
+                }).then(res => {
143
+                    let options = res.data
144
+
145
+                    uni.requestPayment({
146
+                        timeStamp: options.timeStamp,
147
+                        nonceStr: options.nonceStr,
148
+                        package: options.package,
149
+                        signType: options.signType,
150
+                        paySign: options.paySign,
151
+                        success: function () {
152
+                            console.log('支付成功')
153
+
154
+                            // 改为可以支付的状态
155
+                            store.commit('common/update', {
156
+                                payStatus: true,
157
+                            })
158
+
159
+                            self.orderTake(orderId, 2)
160
+                            api.post('/Order/Query', {
161
+                                orderId: orderId,
162
+                            })
163
+
164
+                            router.replace({
165
+                                path: '/pages/pay/result',
166
+                                query: {
167
+                                    orderId: orderId,
168
+                                    price: price,
169
+                                    type: 'success',
170
+                                },
171
+                            })
172
+                        },
173
+                        fail: function () {
174
+                            console.log('支付失败')
175
+
176
+                            // 改为可以支付的状态
177
+                            store.commit('common/update', {
178
+                                payStatus: true,
179
+                            })
180
+
181
+                            if (jump) {
182
+                                self.orderTake(orderId, 1)
183
+                                router.replace({
184
+                                    path: '/pages/pay/result',
185
+                                    query: {
186
+                                        orderId: orderId,
187
+                                        price: price,
188
+                                        type: 'fail',
189
+                                    },
190
+                                })
191
+                            }
192
+                        },
193
+                        complete: function () {
194
+                            resolve()
195
+                        },
196
+                    })
197
+                })
198
+            }
199
+        })
200
+    },
201
+
202
+    // 订单订阅
203
+    orderTake(orderId, type) {
204
+        api.get('/Subscription/GetMsgTpls', {
205
+            type: type,
206
+        }).then(res => {
207
+            uni.requestSubscribeMessage({
208
+                tmplIds: res.data,
209
+                success: () => {
210
+                    api.post('/Subscription/Subscribe', {
211
+                        type: 4,
212
+                        objectId: orderId.toString(),
213
+                    }).then(() => {
214
+                        console.log('订阅成功')
215
+                    })
216
+                },
217
+                fail: err => {
218
+                    console.log(err)
219
+                },
220
+            })
221
+        })
222
+    },
223
+
224
+    // 接口请求前的初始化
225
+    init() {
226
+        return new Promise(resolve => {
227
+            let timer = setInterval(() => {
228
+                if (store.state.user.init) {
229
+                    clearInterval(timer)
230
+                    resolve()
231
+                }
232
+            }, 10)
233
+        })
234
+    },
235
+
236
+    // 登录处理
237
+    login(option) {
238
+        const self = this
239
+        return new Promise(resolve => {
240
+            uni.login({
241
+                provider: 'weixin',
242
+                success: async result => {
243
+                    api.post('/Login/Login', {
244
+                        code: result.code,
245
+                        appId: config.appId,
246
+                        boxId: option.query.bid,
247
+                        fromUserId: option.query.uid,
248
+                        fromScene: option.scene,
249
+                        fromUrl: option.path + '?' + qs.stringify(option.query),
250
+                        fromExtra: JSON.stringify(option),
251
+                    }).then(res => {
252
+                        store.commit('user/login', res.data)
253
+                        self.updateUserInfo()
254
+                        resolve()
255
+                    })
256
+                    resolve()
257
+                },
258
+            })
259
+        })
260
+    },
261
+
262
+    // 获取token
263
+    getToken() {
264
+        return new Promise(resolve => {
265
+            uni.login({
266
+                provider: 'weixin',
267
+                success: async result => {
268
+                    api.get('/Login/RefreshToken', {
269
+                        code: result.code,
270
+                        appId: config.appId,
271
+                    }).then(res => {
272
+                        let token = res.data.tokenStr
273
+
274
+                        if (token) {
275
+                            store.commit('user/update', {
276
+                                token: token,
277
+                            })
278
+                        }
279
+
280
+                        resolve()
281
+                    })
282
+                },
283
+            })
284
+        })
285
+    },
286
+
287
+    // 修改配置
288
+    setConfig() {
289
+        api.get('/Shop/GetConfig').then(res => {
290
+            let data = JSON.parse(res.data)
291
+
292
+            store.commit('common/update', data)
293
+        })
294
+    },
295
+
296
+    // 打开设置
297
+    openSetting() {
298
+        uni.openSetting()
299
+    },
300
+}

+ 175 - 0
src/common/js/router.js

@@ -0,0 +1,175 @@
1
+import qs from 'qs'
2
+import fn from './function'
3
+import store from '../store/index'
4
+import api from '../api/index'
5
+
6
+export default {
7
+    /**
8
+     * 页面跳转
9
+     * @param router
10
+     * router.isTabBer 跳转到带底部导航的需要为true
11
+     */
12
+    push(router) {
13
+        if (fn.getType(router) === 'string') {
14
+            uni.navigateTo({
15
+                url: router,
16
+                fail: err => {
17
+                    console.log(err)
18
+                },
19
+            })
20
+        } else {
21
+            let query = qs.stringify(router.query)
22
+            let url = query ? router.path + '?' + query : router.path
23
+            let isTabBer = router.isTabBer
24
+            let isHasUrl = false
25
+
26
+            for (let key in router.query) {
27
+                if (router.query.hasOwnProperty(key)) {
28
+                    let item = router.query[key]
29
+                    if (fn.getType(item) === 'string' && item.indexOf('http') > -1) {
30
+                        isHasUrl = true
31
+                    }
32
+                }
33
+            }
34
+
35
+            url = isHasUrl ? url : decodeURIComponent(url)
36
+
37
+            if (isTabBer) {
38
+                uni.switchTab({
39
+                    url: url,
40
+                    fail: err => {
41
+                        console.log(err)
42
+                    },
43
+                })
44
+            } else {
45
+                uni.navigateTo({
46
+                    url: url,
47
+                    fail: err => {
48
+                        console.log(err)
49
+                    },
50
+                })
51
+            }
52
+        }
53
+    },
54
+
55
+    /**
56
+     * 页面重定向
57
+     * @param router
58
+     * router.isReLaunch 关闭其他页面需要为true
59
+     */
60
+    replace(router) {
61
+        if (fn.getType(router) === 'string') {
62
+            uni.redirectTo({
63
+                url: router,
64
+                fail: err => {
65
+                    console.log(err)
66
+                },
67
+            })
68
+        } else {
69
+            let query = qs.stringify(router.query)
70
+            let url = router.path + '?' + query
71
+            let isReLaunch = router.isReLaunch
72
+            let isHasUrl = false
73
+
74
+            for (let key in router.query) {
75
+                if (router.query.hasOwnProperty(key)) {
76
+                    let item = router.query[key]
77
+                    if (fn.getType(item) === 'string' && item.indexOf('http') > -1) {
78
+                        isHasUrl = true
79
+                    }
80
+                }
81
+            }
82
+
83
+            url = isHasUrl ? url : decodeURIComponent(url)
84
+
85
+            if (isReLaunch) {
86
+                uni.reLaunch({
87
+                    url: url,
88
+                    fail: err => {
89
+                        console.log(err)
90
+                    },
91
+                })
92
+            } else {
93
+                uni.redirectTo({
94
+                    url: url,
95
+                    fail: err => {
96
+                        console.log(err)
97
+                    },
98
+                })
99
+            }
100
+        }
101
+    },
102
+
103
+    /**
104
+     * 返回指定页面
105
+     * @param index 后退的页面数
106
+     */
107
+    go(index) {
108
+        index = index || 1
109
+        uni.navigateBack({
110
+            delta: index,
111
+        })
112
+    },
113
+
114
+    /**
115
+     * 返回上一页
116
+     */
117
+    back() {
118
+        const self = this
119
+        let page = getCurrentPages()
120
+
121
+        if (page.length <= 1) {
122
+            // 重定向到首页
123
+            self.push({
124
+                isTabBer: true,
125
+                path: '/pages/index/index',
126
+            })
127
+        } else {
128
+            uni.navigateBack({
129
+                delta: 1,
130
+            })
131
+        }
132
+    },
133
+
134
+    /**
135
+     * 获取path路径
136
+     * @param path
137
+     * @param query
138
+     */
139
+    getPath(path, query) {
140
+        query = {
141
+            ...query,
142
+            'uid': store.state.user.userId,
143
+            'bid': store.state.user.boxId,
144
+        }
145
+
146
+        console.log('分享路径: /' + path + '?' + decodeURIComponent(qs.stringify(query)))
147
+
148
+        return '/' + path + '?' + decodeURIComponent(qs.stringify(query))
149
+    },
150
+
151
+    /**
152
+     * 获取小程序吗参数
153
+     * @param query
154
+     * @returns {{}}
155
+     */
156
+    getScene(query = {}) {
157
+        return new Promise(resolve => {
158
+            if (query.shareId) {
159
+                api.get('/Share/GetSharePath', {
160
+                    id: query.shareId,
161
+                }).then(res => {
162
+                    resolve(JSON.parse(res.data.parameters))
163
+                })
164
+            } else {
165
+                query = {
166
+                    ...query,
167
+                    'uid': store.state.user.userId,
168
+                    'bid': store.state.user.boxId,
169
+                }
170
+
171
+                resolve(query)
172
+            }
173
+        })
174
+    },
175
+}

+ 154 - 0
src/common/js/signalR.js

@@ -0,0 +1,154 @@
1
+const protocal = {
2
+    protocol: 'json',
3
+    version: 1,
4
+}
5
+
6
+const MessageType = {
7
+    /** Indicates the message is an Invocation message and implements the {@link InvocationMessage} interface. */
8
+    Invocation: 1,
9
+    /** Indicates the message is a StreamItem message and implements the {@link StreamItemMessage} interface. */
10
+    StreamItem: 2,
11
+    /** Indicates the message is a Completion message and implements the {@link CompletionMessage} interface. */
12
+    Completion: 3,
13
+    /** Indicates the message is a Stream Invocation message and implements the {@link StreamInvocationMessage} interface. */
14
+    StreamInvocation: 4,
15
+    /** Indicates the message is a Cancel Invocation message and implements the {@link CancelInvocationMessage} interface. */
16
+    CancelInvocation: 5,
17
+    /** Indicates the message is a Ping message and implements the {@link PingMessage} interface. */
18
+    Ping: 6,
19
+    /** Indicates the message is a Close message and implements the {@link CloseMessage} interface. */
20
+    Close: 7,
21
+}
22
+
23
+export class HubConnection {
24
+
25
+    // 构造函数
26
+    constructor() {
27
+        this.connection = {}
28
+        this.openStatus = false
29
+        this.invocationId = 0
30
+    }
31
+
32
+    // 创建链接
33
+    connectSocket(option = {}) {
34
+        if (this.connection != null && this.openStatus) {
35
+            return
36
+        }
37
+
38
+        this.connection = uni.connectSocket({
39
+            ...option,
40
+            success: () => {
41
+                console.log('建立连接成功')
42
+            },
43
+            fail: () => {
44
+                console.log('建立连接失败')
45
+            },
46
+        })
47
+        this.onOpen(() => {
48
+            console.log('连接打开')
49
+            this.openStatus = true
50
+            this.send(protocal)
51
+        })
52
+        this.onClose(() => {
53
+            console.log('连接关闭')
54
+            this.connection = null
55
+            this.openStatus = false
56
+        })
57
+        this.onError(res => {
58
+            console.error('连接出错:' + res.errMsg)
59
+        })
60
+    }
61
+
62
+    // 监听连接打开事件
63
+    onOpen(callback) {
64
+        this.connection.onOpen(res => {
65
+            callback(res)
66
+        })
67
+    }
68
+
69
+    // 监听连接关闭事件
70
+    onClose(callback) {
71
+        this.connection.onClose(res => {
72
+            callback(res)
73
+        })
74
+    }
75
+
76
+    // 监听连接错误事件
77
+    onError(callback) {
78
+        this.connection.onError(res => {
79
+            callback(res)
80
+        })
81
+    }
82
+
83
+    // 接收服务器消息事件
84
+    onMessage(callback) {
85
+        this.connection.onMessage(res => {
86
+            let data = res.data.split('')
87
+            data.length = data.length - 1
88
+
89
+            data.forEach(item => {
90
+                let message = JSON.parse(item)
91
+                if (message.type === MessageType.Invocation) {
92
+                    callback(message)
93
+                } else if (message.type === MessageType.Completion) {
94
+                    if (message.error) {
95
+                        console.error(message.error)
96
+                    }
97
+                }
98
+            })
99
+        })
100
+    }
101
+
102
+    // 发送数据
103
+    send(data, success, fail) {
104
+        this.connection.send({
105
+            data: JSON.stringify(data) + '',
106
+            success: success,
107
+            fail: fail,
108
+        })
109
+    }
110
+
111
+    // 发送消息
112
+    sendData(functionName) {
113
+        let args = []
114
+        for (let i = 1; i < arguments.length; i++) {
115
+            args[i - 1] = arguments[i]
116
+        }
117
+
118
+        let data = {
119
+            target: functionName,
120
+            arguments: args,
121
+            type: MessageType.Invocation,
122
+            invocationId: this.invocationId.toString(),
123
+        }
124
+        this.invocationId++
125
+
126
+        return new Promise((resolve, reject) => {
127
+            this.connection.send({
128
+                data: JSON.stringify(data) + '',
129
+                success: res => {
130
+                    resolve(res)
131
+                },
132
+                fail: res => {
133
+                    reject(res)
134
+                },
135
+            })
136
+        })
137
+    }
138
+
139
+    // 关闭连接
140
+    close(option = {}) {
141
+        this.connection.close({
142
+            code: option.code || 1000,
143
+            reason: option.reason || '客户端主动关闭',
144
+            success: () => {
145
+                this.openStatus = false
146
+                console.log('主动关闭连接')
147
+            },
148
+            fail: res => {
149
+                console.log('主动关闭连接失败')
150
+                console.log(res)
151
+            },
152
+        })
153
+    }
154
+}

+ 58 - 0
src/common/scss/config.scss

@@ -0,0 +1,58 @@
1
+// 行为相关颜色
2
+$uni-color-primary: #007aff;
3
+$uni-color-success: #4cd964;
4
+$uni-color-warning: #f0ad4e;
5
+$uni-color-error: #dd524d;
6
+
7
+// 文字基本颜色
8
+$uni-text-color: #333; //基本色
9
+$uni-text-color-inverse: #fff; //反色
10
+$uni-text-color-grey: #999; //辅助灰色,如加载更多的提示信息
11
+$uni-text-color-placeholder: #808080;
12
+$uni-text-color-disable: #c0c0c0;
13
+
14
+// 背景颜色
15
+$uni-bg-color: #ffffff;
16
+$uni-bg-color-grey: #f8f8f8;
17
+$uni-bg-color-hover: #f1f1f1; //点击状态颜色
18
+$uni-bg-color-mask: rgba(0, 0, 0, 0.4); //遮罩颜色
19
+
20
+// 边框颜色
21
+$uni-border-color: #c8c7cc;
22
+
23
+// 文字尺寸
24
+$uni-font-size-sm: 24 upx;
25
+$uni-font-size-base: 28 upx;
26
+$uni-font-size-lg: 32 upx;
27
+
28
+// 图片尺寸
29
+$uni-img-size-sm: 40 upx;
30
+$uni-img-size-base: 52 upx;
31
+$uni-img-size-lg: 80 upx;
32
+
33
+// Border Radius
34
+$uni-border-radius-sm: 4 upx;
35
+$uni-border-radius-base: 6 upx;
36
+$uni-border-radius-lg: 12 upx;
37
+$uni-border-radius-circle: 50%;
38
+
39
+// 水平间距
40
+$uni-spacing-row-sm: 10px;
41
+$uni-spacing-row-base: 20 upx;
42
+$uni-spacing-row-lg: 30 upx;
43
+
44
+// 垂直间距
45
+$uni-spacing-col-sm: 8 upx;
46
+$uni-spacing-col-base: 16 upx;
47
+$uni-spacing-col-lg: 24 upx;
48
+
49
+// 透明度
50
+$uni-opacity-disabled: 0.3; // 组件禁用态的透明度
51
+
52
+// 文章场景相关
53
+$uni-color-title: #2C405A; // 文章标题颜色
54
+$uni-font-size-title: 40 upx;
55
+$uni-color-subtitle: #555555; // 二级标题颜色
56
+$uni-font-size-subtitle: 36 upx;
57
+$uni-color-paragraph: #3F536E; // 文章段落颜色
58
+$uni-font-size-paragraph: 30 upx;

+ 16 - 0
src/common/scss/function.scss

@@ -0,0 +1,16 @@
1
+// 自定义函数
2
+
3
+// px转换为rem(1px = 0.01rem)设计图为1080
4
+@function px($size) {
5
+    @return $size * (750 / 1080) + rpx;
6
+}
7
+
8
+// px转换为rem(1px = 0.01rem)设计图为750
9
+@function rpx($size) {
10
+    @return $size + rpx;
11
+}
12
+
13
+// px转换为导航栏适配的px
14
+@function px2($size) {
15
+    @return $size * (400 / 1080) + px;
16
+}

+ 20 - 0
src/common/scss/main.scss

@@ -0,0 +1,20 @@
1
+@import "reset";
2
+
3
+// 输入框
4
+.uni-input-placeholder {
5
+    display: flex;
6
+    align-items: center;
7
+}
8
+
9
+// 按钮
10
+.button {
11
+    margin: 0;
12
+    padding: 0;
13
+    line-height: normal;
14
+    border: none;
15
+    background: none;
16
+
17
+    &:after {
18
+        display: none;
19
+    }
20
+}

+ 19 - 0
src/common/scss/mixin.scss

@@ -0,0 +1,19 @@
1
+@import "function";
2
+
3
+//单行省略号
4
+@mixin omit($width: 100%) {
5
+    max-width: $width;
6
+    overflow: hidden;
7
+    text-overflow: ellipsis;
8
+    white-space: nowrap;
9
+    word-wrap: normal;
10
+}
11
+
12
+//多行省略号
13
+@mixin omits($line) {
14
+    display: -webkit-box;
15
+    overflow: hidden;
16
+    text-overflow: ellipsis;
17
+    -webkit-line-clamp: $line;
18
+    -webkit-box-orient: vertical;
19
+}

+ 2 - 0
src/common/scss/public.scss

@@ -0,0 +1,2 @@
1
+@import "function";
2
+@import "mixin";

+ 46 - 0
src/common/scss/reset.scss

@@ -0,0 +1,46 @@
1
+/*css重置*/
2
+
3
+* {
4
+    margin: 0;
5
+    padding: 0;
6
+    box-sizing: border-box;
7
+}
8
+
9
+body {
10
+    font: 14px "Helvetica Neue", "Helvetica", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "\5FAE\8F6F\96C5\9ED1", Arial, sans-serif;
11
+    color: #333;
12
+}
13
+
14
+::-webkit-scrollbar {
15
+    width: 0;
16
+    height: 0;
17
+    color: transparent;
18
+}
19
+
20
+table {
21
+    border-collapse: collapse;
22
+    border-spacing: 0;
23
+}
24
+
25
+ul, li {
26
+    list-style: none;
27
+}
28
+
29
+img {
30
+    display: block;
31
+    border: none;
32
+}
33
+
34
+a:hover, a:visited, a:link, a:active {
35
+    text-decoration: none;
36
+    color: #333333;
37
+}
38
+
39
+input:focus, textarea:focus {
40
+    outline: none;
41
+}
42
+
43
+// 小程序兼容
44
+div, p, ul, li {
45
+    box-sizing: border-box;
46
+}

+ 49 - 0
src/common/store/common.js

@@ -0,0 +1,49 @@
1
+// 公共
2
+const module = {
3
+    // 开启命名空间
4
+    namespaced: true,
5
+
6
+    // 仓库
7
+    state: {
8
+        iphoneX:false,
9
+    },
10
+
11
+    // 同步方法
12
+    mutations: {
13
+        // 更新数据
14
+        update(state, data) {
15
+            for (let key in data) {
16
+                if (data.hasOwnProperty(key)) {
17
+                    state[key] = data[key]
18
+                }
19
+            }
20
+        },
21
+
22
+        // 移除数据
23
+        remove(state, name) {
24
+            if (typeof name === 'string') {
25
+                delete state[name]
26
+            } else {
27
+                for (let key in name) {
28
+                    if (name.hasOwnProperty(key)) {
29
+                        delete state[name[key]]
30
+                    }
31
+                }
32
+            }
33
+        },
34
+
35
+        // 移除所有数据
36
+        removeAll(state) {
37
+            for (let key in state) {
38
+                if (state.hasOwnProperty(key)) {
39
+                    delete state[key]
40
+                }
41
+            }
42
+        },
43
+    },
44
+
45
+    // 异步方法
46
+    actions: {},
47
+}
48
+
49
+export default module

+ 29 - 0
src/common/store/http.js

@@ -0,0 +1,29 @@
1
+const module = {
2
+    // 开启命名空间
3
+    namespaced: true,
4
+
5
+    // 仓库
6
+    state: {},
7
+
8
+    // 同步方法
9
+    mutations: {
10
+        // 添加http请求历史
11
+        add(state, key) {
12
+            let startTime = new Date().getTime()
13
+
14
+            if (!state[key]) {
15
+                state[key] = startTime
16
+            }
17
+        },
18
+
19
+        // 请求成功后删除请求历史
20
+        success(state, key) {
21
+            delete state[key]
22
+        },
23
+    },
24
+
25
+    // 异步方法
26
+    actions: {},
27
+}
28
+
29
+export default module

+ 30 - 0
src/common/store/index.js

@@ -0,0 +1,30 @@
1
+import Vue from 'vue'
2
+import Vuex from 'vuex'
3
+import VuexPersistedState from 'vuex-persistedstate'
4
+import config from '../js/config'
5
+import common from './common'
6
+import user from './user'
7
+import http from './http'
8
+
9
+Vue.use(Vuex)
10
+
11
+const vuexLocal = new VuexPersistedState({
12
+    key: config.appEnv + '_vuex',
13
+    storage: {
14
+        getItem: key => uni.getStorageSync(key),
15
+        setItem: (key, value) => uni.setStorageSync(key, value),
16
+        removeItem: key => uni.removeStorageSync(key),
17
+    },
18
+})
19
+
20
+let store = new Vuex.Store({
21
+    strict: process.env.NODE_ENV !== 'production',
22
+    plugins: [vuexLocal],
23
+    modules: {
24
+        'common': common,
25
+        'user': user,
26
+        'http': http,
27
+    },
28
+})
29
+
30
+export default store

+ 74 - 0
src/common/store/user.js

@@ -0,0 +1,74 @@
1
+// 用户信息
2
+const module = {
3
+    // 开启命名空间
4
+    namespaced: true,
5
+
6
+    // 仓库
7
+    state: {
8
+        appId: '',// appId(系统内部使用)
9
+        companyId: '',// 公司id
10
+        userId: '',// 用户id
11
+        boxId: '',// 盒子id
12
+        token: '',// 聊天使用的
13
+        sessionKeyId: '',// 微信登录的sessionKeyId
14
+        userInfo: '', // 用户信息
15
+        integral: 0,// 用户剩余积分
16
+        vip: false,// 是否是vip
17
+        vipStatus: false,// 是否激活vip
18
+        login: false,// 是否登录
19
+        writeOffUser: false,// 是否有核销权限
20
+        init: false,// 是否初始化
21
+    },
22
+
23
+    // 同步方法
24
+    mutations: {
25
+        // 更新数据
26
+        update(state, data) {
27
+            for (let key in data) {
28
+                if (data.hasOwnProperty(key)) {
29
+                    state[key] = data[key]
30
+                }
31
+            }
32
+        },
33
+
34
+        // 移除数据
35
+        remove(state, name) {
36
+            if (typeof name === 'string') {
37
+                delete state[name]
38
+            } else {
39
+                for (let key in name) {
40
+                    if (name.hasOwnProperty(key)) {
41
+                        delete state[name[key]]
42
+                    }
43
+                }
44
+            }
45
+        },
46
+
47
+        // 登录处理
48
+        login(state, data) {
49
+            state.companyId = data.visitor.companyId || ''
50
+            state.userId = data.visitor.id || ''
51
+            state.boxId = data.visitor.boxId ? data.visitor.boxId : state.boxId
52
+            state.appId = data.visitor.appId || ''
53
+            state.token = data.token || ''
54
+            state.vip = data.visitor.isVip || false
55
+            state.vipStatus = data.visitor.vipStatus === 1 || false
56
+            state.login = data.visitor.nickName ? true : false
57
+            state.writeOffUser = data.visitor.writeOffUser
58
+            state.init = true
59
+        },
60
+
61
+        // 退出登录处理
62
+        logout(state) {
63
+            state.companyId = ''
64
+            state.userId = ''
65
+            state.userInfo = ''
66
+            state.vipStatus = false
67
+        },
68
+    },
69
+
70
+    // 异步方法
71
+    actions: {},
72
+}
73
+
74
+export default module

+ 87 - 0
src/components/image/index.vue

@@ -0,0 +1,87 @@
1
+<template>
2
+    <div class="c-img" @click="handleClick">
3
+        <img :mode="mode" :lazy-load="true" :src="url" alt="">
4
+    </div>
5
+</template>
6
+
7
+<script>
8
+    export default {
9
+        name: 'MyImage',
10
+
11
+        props: {
12
+            // 图片裁剪、缩放的模式(aspectFit:显示长边,aspectFill:显示短边,widthFix:高度自动)
13
+            mode: {
14
+                type: String,
15
+                default: 'aspectFill',
16
+            },
17
+
18
+            // 图片地址
19
+            src: {
20
+                type: String,
21
+                default: '',
22
+            },
23
+        },
24
+
25
+        // 数据
26
+        data() {
27
+            return {
28
+                url: '',
29
+            }
30
+        },
31
+
32
+        // 初始化
33
+        created() {
34
+            this.urlHandle()
35
+        },
36
+
37
+        // 函数
38
+        methods: {
39
+            handleClick() {
40
+                const self = this
41
+
42
+                self.$emit('click')
43
+            },
44
+
45
+            // url处理
46
+            urlHandle() {
47
+                const self = this
48
+                let src = self.src
49
+                let imageResourceUrl = self.config.imageResourceUrl
50
+
51
+                // #ifdef APP
52
+                if (src) {
53
+                    src = src.replace(/^\//, '')
54
+                }
55
+
56
+                imageResourceUrl = imageResourceUrl.replace(/^\//, '')
57
+                // #endif
58
+
59
+                if (!src || src === 'true') {
60
+                    self.url = imageResourceUrl + '/resource/common/default.gif'
61
+                } else if (src.indexOf('resource') > -1) {
62
+                    self.url = imageResourceUrl + src
63
+                } else if (src.indexOf('http') > -1 || src.indexOf('static') > -1) {
64
+                    self.url = src
65
+                } else {
66
+                    self.url = self.config.imageUrl + src
67
+                }
68
+            },
69
+        },
70
+
71
+        // 数据计算
72
+        computed: {},
73
+
74
+        // 数据监听
75
+        watch: {
76
+            src() {
77
+                this.urlHandle()
78
+            },
79
+        },
80
+    }
81
+</script>
82
+
83
+<style lang="scss" scoped>
84
+    .c-img img {
85
+        object-fit: cover;
86
+    }
87
+</style>

+ 133 - 0
src/components/layout/nav.vue

@@ -0,0 +1,133 @@
1
+<template>
2
+    <div class="c-nav" :style="'height:' + (statusBarHeight + height) + 'px;'">
3
+        <div class="c-nav__status-bar" :style="'height:' + statusBarHeight + 'px;'"></div>
4
+        <div class="c-nav__fixed" :style="'top:' + statusBarHeight + 'px; height:' + height + 'px;'">
5
+            <div class="c-nav__content">
6
+                <div class="c-nav__left" @click="back()">
7
+                    <img v-if="icon === 'back'" class="c-nav__icon" src="/static/icon/arrows_left.png" alt="">
8
+                    <img v-if="icon === 'backGray'" class="c-nav__icon" src="/static/common/arrows_left.png" alt="">
9
+                </div>
10
+                <div v-if="title" class="c-nav__title">{{ title }}</div>
11
+                <div class="c-nav__slot">
12
+                    <slot></slot>
13
+                </div>
14
+            </div>
15
+        </div>
16
+    </div>
17
+</template>
18
+
19
+<script>
20
+    export default {
21
+        name: 'MyNav',
22
+
23
+        props: {
24
+            // 左侧按钮
25
+            icon: {
26
+                type: String,
27
+                default: 'back',
28
+            },
29
+
30
+            // 标题
31
+            title: {
32
+                type: String,
33
+                default: '',
34
+            },
35
+        },
36
+
37
+        // 数据
38
+        data() {
39
+            return {
40
+                statusBarHeight: uni.getSystemInfoSync().statusBarHeight, //状态栏高度,
41
+                height: 44,
42
+            }
43
+        },
44
+
45
+        // 初始化
46
+        created() {
47
+            const self = this
48
+
49
+            // #ifdef MP-WEIXIN
50
+            let button = wx.getMenuButtonBoundingClientRect()
51
+            self.height = (button.top - self.statusBarHeight) * 2 + button.height
52
+            // #endif
53
+        },
54
+
55
+        // 函数
56
+        methods: {
57
+            // 返回上一页
58
+            back() {
59
+                const self = this
60
+                self.router.back()
61
+            },
62
+        },
63
+
64
+        // 数据计算
65
+        computed: {},
66
+
67
+        // 数据监听
68
+        watch: {},
69
+    }
70
+</script>
71
+
72
+<style lang="scss" scoped>
73
+    @import "../../common/scss/public";
74
+
75
+    .c-nav {
76
+        background-color: #fff;
77
+
78
+        &__status-bar {
79
+            position: fixed;
80
+            top: 0;
81
+            left: 0;
82
+            z-index: 996;
83
+            width: 100%;
84
+            background-color: #fff;
85
+        }
86
+
87
+        &__fixed {
88
+            position: fixed;
89
+            top: 0;
90
+            left: 0;
91
+            z-index: 996;
92
+            width: 100%;
93
+            background-color: #fff;
94
+        }
95
+
96
+        &__content {
97
+            position: relative;
98
+            display: flex;
99
+            align-items: center;
100
+            width: 100%;
101
+            height: 100%;
102
+            padding: 0 px2(30);
103
+
104
+            /* #ifdef MP */
105
+            padding-right: px2(200);
106
+            /* #endif */
107
+        }
108
+
109
+        &__icon {
110
+            width: px2(60);
111
+            height: px2(60);
112
+            margin-right: px2(30);
113
+        }
114
+
115
+        &__title {
116
+            @include omit(px2(300));
117
+            position: absolute;
118
+            top: 50%;
119
+            left: 50%;
120
+            z-index: 1;
121
+            width: px2(300);
122
+            transform: translate(-50%, -50%);
123
+            font-size: px2(30);
124
+            font-weight: 700;
125
+            text-align: center;
126
+            color: #000;
127
+        }
128
+
129
+        &__slot {
130
+            flex: 1;
131
+        }
132
+    }
133
+</style>

+ 64 - 0
src/components/layout/null.vue

@@ -0,0 +1,64 @@
1
+<template>
2
+    <div class="c-null">
3
+        <img class="c-null__img" src="/static/common/cart_null.jpg" alt="">
4
+        <div class="c-null__title">{{ title }}</div>
5
+    </div>
6
+</template>
7
+
8
+<script>
9
+    export default {
10
+        name: 'MyNull',
11
+
12
+        props: {
13
+            // 标题
14
+            title: {
15
+                type: String,
16
+            },
17
+
18
+            // 副标题
19
+            subTitle: {
20
+                type: String,
21
+                default: '',
22
+            },
23
+        },
24
+
25
+        // 数据
26
+        data() {
27
+            return {}
28
+        },
29
+
30
+        // 初始化
31
+        created() {
32
+        },
33
+
34
+        // 函数
35
+        methods: {},
36
+
37
+        // 数据计算
38
+        computed: {},
39
+
40
+        // 数据监听
41
+        watch: {},
42
+    }
43
+</script>
44
+
45
+<style lang="scss" scoped>
46
+    .c-null {
47
+        display: flex;
48
+        flex-direction: column;
49
+        justify-content: center;
50
+        align-items: center;
51
+        height: px(1100);
52
+
53
+        &__img {
54
+            width: px(740);
55
+            height: px(371);
56
+        }
57
+
58
+        &__title {
59
+            margin-top: px(60);
60
+            font-size: px(38);
61
+            color: #666;
62
+        }
63
+    }
64
+</style>

+ 103 - 0
src/main.js

@@ -0,0 +1,103 @@
1
+import Vue from 'vue'
2
+import App from './App'
3
+import config from './common/js/config'
4
+import router from './common/js/router'
5
+import store from './common/store/index'
6
+import fn from './common/js/index'
7
+import log from './common/js/log'
8
+import api from './common/api/index'
9
+import * as filters from './common/js/filters'
10
+
11
+App.mpType = 'app'
12
+Vue.config.productionTip = false
13
+Vue.prototype.config = config
14
+Vue.prototype.router = router
15
+Vue.prototype.$store = store
16
+Vue.prototype.fn = fn
17
+Vue.prototype.log = log
18
+Vue.prototype.api = api
19
+
20
+// 全局混入
21
+Vue.mixin({
22
+    // 数据
23
+    data() {
24
+        return {}
25
+    },
26
+
27
+    // 页面加载
28
+    onLoad() {
29
+        // #ifdef MP
30
+        uni.hideShareMenu()
31
+        // #endif
32
+    },
33
+
34
+    // 页面隐藏
35
+    onHide() {
36
+        const self = this
37
+
38
+        // 恢复预览类型
39
+        self.$store.commit('common/update', {
40
+            preview: '0',
41
+        })
42
+
43
+        // 改为可以支付的状态
44
+        self.$store.commit('common/update', {
45
+            payStatus: true,
46
+        })
47
+    },
48
+
49
+    methods: {
50
+        // 跳转到指定页面
51
+        jump(option) {
52
+            const self = this
53
+            self.router.push(option)
54
+        },
55
+
56
+        // 替换当前页面为指定页面
57
+        jumpReplace(option) {
58
+            const self = this
59
+            self.router.replace(option)
60
+        },
61
+
62
+        // 跳转到webView
63
+        jumpWebView(url, title) {
64
+            const self = this
65
+            self.router.push({
66
+                path: '/pages/webView/index',
67
+                query: {
68
+                    url: url,
69
+                    title: title,
70
+                },
71
+            })
72
+        },
73
+
74
+        // 返回上一页
75
+        back() {
76
+            const self = this
77
+            self.router.back()
78
+        },
79
+    },
80
+
81
+    // 数据计算
82
+    computed: {
83
+        siteTitle() {
84
+            return this.$store.state.common.siteTitle
85
+        },
86
+        logoUrl() {
87
+            return this.$store.state.common.logoUrl
88
+        },
89
+        iphoneX() {
90
+            return this.$store.state.common.iphoneX
91
+        },
92
+    },
93
+})
94
+
95
+// 注册过滤器
96
+Object.keys(filters).forEach(key => {
97
+    Vue.filter(key, filters[key])
98
+})
99
+
100
+const app = new Vue({
101
+    ...App,
102
+})
103
+app.$mount()

+ 84 - 0
src/manifest.json

@@ -0,0 +1,84 @@
1
+{
2
+    "name": "xkjHelperongcheng",
3
+    "appid": "__UNI__F283109",
4
+    "description": "",
5
+    "versionName": "1.0.0",
6
+    "versionCode": "100",
7
+    "transformPx": false,
8
+    "app-plus": {
9
+        /* 5+App特有相关 */
10
+        "usingComponents": true,
11
+        "splashscreen": {
12
+            "alwaysShowBeforeRender": true,
13
+            "waiting": true,
14
+            "autoclose": true,
15
+            "delay": 0
16
+        },
17
+        "modules": {
18
+            /* 模块配置 */
19
+
20
+        },
21
+        "distribute": {
22
+            /* 应用发布信息 */
23
+            "android": {
24
+                /* android打包配置 */
25
+                "permissions": [
26
+                    "<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
27
+                    "<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
28
+                    "<uses-permission android:name=\"android.permission.READ_CONTACTS\"/>",
29
+                    "<uses-permission android:name=\"android.permission.VIBRATE\"/>",
30
+                    "<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
31
+                    "<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
32
+                    "<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
33
+                    "<uses-permission android:name=\"android.permission.WRITE_CONTACTS\"/>",
34
+                    "<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
35
+                    "<uses-permission android:name=\"android.permission.CAMERA\"/>",
36
+                    "<uses-permission android:name=\"android.permission.RECORD_AUDIO\"/>",
37
+                    "<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
38
+                    "<uses-permission android:name=\"android.permission.MODIFY_AUDIO_SETTINGS\"/>",
39
+                    "<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
40
+                    "<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
41
+                    "<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
42
+                    "<uses-permission android:name=\"android.permission.CALL_PHONE\"/>",
43
+                    "<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
44
+                    "<uses-permission android:name=\"android.permission.ACCESS_COARSE_LOCATION\"/>",
45
+                    "<uses-feature android:name=\"android.hardware.camera\"/>",
46
+                    "<uses-permission android:name=\"android.permission.ACCESS_FINE_LOCATION\"/>",
47
+                    "<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
48
+                ]
49
+            },
50
+            "ios": {
51
+                /* ios打包配置 */
52
+
53
+            },
54
+            "sdkConfigs": {
55
+                /* SDK配置 */
56
+
57
+            }
58
+        }
59
+    },
60
+    "quickapp": {
61
+        /* 快应用特有相关 */
62
+
63
+    },
64
+    "mp-weixin": {
65
+        /* 微信小程序特有相关 */
66
+        "appid": "wxb81eca6ac3c7955c",
67
+        "setting": {
68
+            "urlCheck": false
69
+        },
70
+        "usingComponents": true
71
+    },
72
+    "mp-alipay": {
73
+        "usingComponents": true
74
+    },
75
+    "mp-baidu": {
76
+        "usingComponents": true
77
+    },
78
+    "mp-toutiao": {
79
+        "usingComponents": true
80
+    },
81
+    "mp-qq": {
82
+        "usingComponents": true
83
+    }
84
+}

+ 18 - 0
src/pages.json

@@ -0,0 +1,18 @@
1
+{
2
+    "globalStyle": {
3
+        "navigationBarTitleText": "配送助手",
4
+        "navigationBarTextStyle": "black",
5
+        "navigationBarBackgroundColor": "#fff",
6
+        "backgroundColor": "#fff"
7
+    },
8
+
9
+    "pages": [
10
+        {
11
+            "path": "pages/index/index",
12
+            "style": {
13
+                "navigationBarTitleText": "配送助手",
14
+                "enablePullDownRefresh": true
15
+            }
16
+        }
17
+    ]
18
+}

+ 569 - 0
src/pages/index/index.vue

@@ -0,0 +1,569 @@
1
+<template>
2
+    <div class="page">
3
+        <ul class="tab">
4
+            <li
5
+                class="tab__item"
6
+                :class="{'tab__item--active': tab === index}"
7
+                v-for="(item, index) in list"
8
+                :key="index"
9
+                @click="setTab(index)"
10
+            >
11
+                <div class="tab__text">{{ item.title }}</div>
12
+                <div class="tab__num" v-if="item.num > 0">{{ item.num }}</div>
13
+            </li>
14
+        </ul>
15
+        <div class="page__content">
16
+            <swiper class="page__swiper" :current="tab" @change="swiperChange">
17
+                <swiper-item v-for="(item, index) in list" :key="index">
18
+                    <scroll-view class="page__scroll" :scroll-y="true" @scrolltolower="getMoreList">
19
+                        <ul class="order">
20
+                            <li class="order__item">
21
+                                <div class="order__main">
22
+                                    <div class="order__top">
23
+                                        <div class="des">立即 (建议19:00前送达)</div>
24
+                                        <div class="index">
25
+                                            <span class="symbol">#</span>155
26
+                                        </div>
27
+                                    </div>
28
+                                    <div class="order__con">
29
+                                        <div class="order__title on">西北卖村(北京六里桥店)</div>
30
+                                        <p class="order__des">北京市丰台区六里桥10号院综合楼</p>
31
+                                        <div class="order__title order__title2">周庄子家园(6号楼2单元1701)</div>
32
+                                    </div>
33
+                                </div>
34
+                                <div class="order__btns">
35
+                                    <div class="btn tel">
36
+                                        <my-image src="/static/icon/tal.png"></my-image>
37
+                                        <span >联系</span>
38
+                                    </div>
39
+                                    <div class="btn active">接单</div>
40
+                                </div>
41
+                            </li>
42
+                        </ul>
43
+                        <div class="null" v-if="loading && !item.list.length">
44
+                            <img class="null__img" src="/static/common/order_null.jpg" alt />
45
+                            <div class="null__title">还没有相关数据哦</div>
46
+                            <!-- <div class="null__sub-title">xxx</div> -->
47
+                        </div>
48
+                    </scroll-view>
49
+                </swiper-item>
50
+            </swiper>
51
+        </div>
52
+    </div>
53
+</template>
54
+
55
+<script>
56
+import MyImage from "../../components/image/index";
57
+
58
+export default {
59
+    name: "",
60
+    components: { MyImage },
61
+    // 数据
62
+    data() {
63
+        return {
64
+            tab: 0,
65
+            list: [
66
+                {
67
+                    title: "待接单",
68
+                    status: "0",
69
+                    num: 0,
70
+                    page: 1,
71
+                    list: [],
72
+                },
73
+                {
74
+                    title: "打包中",
75
+                    status: "2",
76
+                    num: 0,
77
+                    page: 1,
78
+                    list: [],
79
+                },
80
+                {
81
+                    title: "待配送",
82
+                    status: "3",
83
+                    num: 0,
84
+                    page: 1,
85
+                    list: [],
86
+                },
87
+                {
88
+                    title: "配送中",
89
+                    status: "4",
90
+                    num: 0,
91
+                    page: 1,
92
+                    list: [],
93
+                },
94
+                {
95
+                    title: "已送达",
96
+                    status: "9",
97
+                    num: 0,
98
+                    page: 1,
99
+                    list: [],
100
+                },
101
+            ],
102
+            loading: false, // 是否加载完成
103
+        };
104
+    },
105
+
106
+    onLoad() {
107
+        const self = this;
108
+
109
+        // if (!self.loading) {
110
+        //     uni.showLoading({
111
+        //         title: '加载中...',
112
+        //     })
113
+        // }
114
+
115
+        self.tab = self.$mp.query.index ? Number(self.$mp.query.index) : 0;
116
+    },
117
+
118
+    onShow() {
119
+        const self = this;
120
+
121
+        // self.getList()
122
+    },
123
+
124
+    // 函数
125
+    methods: {
126
+        // 切换导航
127
+        setTab(index) {
128
+            const self = this;
129
+
130
+            self.tab = index;
131
+        },
132
+
133
+        // swiper切换处理
134
+        swiperChange(val) {
135
+            const self = this;
136
+            self.tab = val.target.current;
137
+            // self.getList()
138
+        },
139
+
140
+        // 获取订单列表
141
+        getList() {
142
+            const self = this;
143
+
144
+            self.list[self.tab].page = 1;
145
+
146
+            self.api
147
+                .get("/Order/GetList", {
148
+                    status: self.list[self.tab].status,
149
+                    pageIndex: self.list[self.tab].page,
150
+                    pageSize: 20,
151
+                })
152
+                .then((res) => {
153
+                    let data = JSON.parse(res.data);
154
+
155
+                    if (data.orderList.length) {
156
+                        self.list[self.tab].page++;
157
+                    }
158
+
159
+                    // self.list[1].num = data.countInfo.unpaidOrderCount
160
+                    // self.list[2].num = data.countInfo.waitShippedOrderCount
161
+                    // self.list[3].num = data.countInfo.waitReceivedOrderCount
162
+                    self.list[self.tab].list = data.orderList;
163
+                    self.loading = true;
164
+                    uni.hideLoading();
165
+                });
166
+        },
167
+
168
+        // 获取更多内容
169
+        getMoreList() {
170
+            return console.log("获取更多");
171
+            const self = this;
172
+
173
+            self.api
174
+                .get("/Order/GetList", {
175
+                    status: self.list[self.tab].status,
176
+                    pageIndex: self.list[self.tab].page,
177
+                    pageSize: 20,
178
+                })
179
+                .then((res) => {
180
+                    let data = JSON.parse(res.data);
181
+
182
+                    if (data.orderList.length) {
183
+                        self.list[self.tab].page++;
184
+                    }
185
+
186
+                    self.list[1].num = data.countInfo.unpaidOrderCount;
187
+                    self.list[2].num = data.countInfo.waitShippedOrderCount;
188
+                    self.list[3].num = data.countInfo.waitReceivedOrderCount;
189
+                    self.list[self.tab].list = self.list[self.tab].list.concat(
190
+                        data.orderList
191
+                    );
192
+                });
193
+        },
194
+
195
+        // 跳转到详情
196
+        jumpDetail(val) {
197
+            const self = this;
198
+
199
+            self.router.push({
200
+                path: "/pages/order/detail",
201
+                query: {
202
+                    orderId: val.shopOrderId,
203
+                },
204
+            });
205
+        },
206
+
207
+        // 跳转到物流信息
208
+        jumpExpress(val) {
209
+            const self = this;
210
+
211
+            self.router.push({
212
+                path: "/pages/order/express",
213
+                query: {
214
+                    orderId: val.shopOrderId,
215
+                },
216
+            });
217
+        },
218
+
219
+        // 取消订单
220
+        cancel(val, key) {
221
+            const self = this;
222
+
223
+            self.fn
224
+                .showModal({
225
+                    title: "取消订单",
226
+                    content: "这么好的宝贝,确定不要了?",
227
+                })
228
+                .then((res) => {
229
+                    if (res.confirm) {
230
+                        self.api
231
+                            .post(
232
+                                "/Order/Cancel",
233
+                                {
234
+                                    orderId: val.shopOrderId,
235
+                                    reason: "",
236
+                                },
237
+                                {
238
+                                    repeat: true,
239
+                                }
240
+                            )
241
+                            .then(() => {
242
+                                if (self.tab !== 0 && self.tab !== 4) {
243
+                                    self.list[self.tab].num--;
244
+                                }
245
+                                self.list[self.tab].list.splice(key, 1);
246
+                                self.fn.showToast("订单取消成功");
247
+                            });
248
+                    }
249
+                });
250
+        },
251
+
252
+        // 支付
253
+        pay(val) {
254
+            const self = this;
255
+
256
+            self.fn.pay(val.shopOrderId, val.buyerPayAmount);
257
+        },
258
+
259
+        // 确认收货处理
260
+        receive(val, key) {
261
+            const self = this;
262
+
263
+            self.fn
264
+                .showModal({
265
+                    title: "确认收货",
266
+                    content: "请你收到货物后再点击“确认”,否则可能钱货两空!",
267
+                })
268
+                .then((res) => {
269
+                    if (res.confirm) {
270
+                        self.api
271
+                            .post(
272
+                                "/Order/SignOff",
273
+                                {
274
+                                    orderId: val.shopOrderId,
275
+                                },
276
+                                {
277
+                                    repeat: true,
278
+                                }
279
+                            )
280
+                            .then(() => {
281
+                                if (self.tab !== 0 && self.tab !== 4) {
282
+                                    self.list[self.tab].num--;
283
+                                }
284
+                                self.list[self.tab].list.splice(key, 1);
285
+                            });
286
+                    }
287
+                });
288
+        },
289
+
290
+        // 删除订单
291
+        remove(val, key) {
292
+            const self = this;
293
+
294
+            self.fn
295
+                .showModal({
296
+                    title: "删除订单",
297
+                    content: "确定删除订单?",
298
+                })
299
+                .then((res) => {
300
+                    if (res.confirm) {
301
+                        self.api
302
+                            .delete(
303
+                                "/Order/Delete",
304
+                                {
305
+                                    orderId: val.shopOrderId,
306
+                                },
307
+                                {
308
+                                    repeat: true,
309
+                                }
310
+                            )
311
+                            .then(() => {
312
+                                if (self.tab !== 0 && self.tab !== 4) {
313
+                                    self.list[self.tab].num--;
314
+                                }
315
+                                self.list[self.tab].list.splice(key, 1);
316
+                                self.fn.showToast("删除成功");
317
+                            });
318
+                    }
319
+                });
320
+        },
321
+    },
322
+
323
+    // 数据计算
324
+    computed: {},
325
+
326
+    // 数据监听
327
+    watch: {},
328
+};
329
+</script>
330
+
331
+<style>
332
+page {
333
+    height: 100%;
334
+}
335
+</style>
336
+
337
+<style lang="scss" scoped>
338
+.page {
339
+    display: flex;
340
+    flex-direction: column;
341
+    height: 100%;
342
+
343
+    &__content {
344
+        flex: 1;
345
+        position: relative;
346
+    }
347
+
348
+    &__swiper {
349
+        position: absolute;
350
+        top: 0;
351
+        left: 0;
352
+        z-index: 1;
353
+        width: 100%;
354
+        height: 100%;
355
+    }
356
+
357
+    &__scroll {
358
+        height: 100%;
359
+    }
360
+}
361
+
362
+.tab {
363
+    display: flex;
364
+    justify-content: space-around;
365
+    align-items: center;
366
+    width: 100%;
367
+    height: px(145);
368
+    background-color: #fff;
369
+
370
+    &__item {
371
+        position: relative;
372
+        display: flex;
373
+        justify-content: center;
374
+        align-items: center;
375
+        flex: 1;
376
+        height: 100%;
377
+
378
+        &--active:before {
379
+            content: "";
380
+            position: absolute;
381
+            bottom: 0;
382
+            left: 0;
383
+            z-index: 1;
384
+            width: 100%;
385
+            height: px(6);
386
+            background-color: #333;
387
+        }
388
+    }
389
+
390
+    &__text {
391
+        font-size: px(42);
392
+        color: #333;
393
+    }
394
+
395
+    &__num {
396
+        position: absolute;
397
+        top: px(30);
398
+        right: px(30);
399
+        z-index: 1;
400
+        display: flex;
401
+        justify-content: center;
402
+        align-items: center;
403
+        min-width: px(42);
404
+        height: px(42);
405
+        transform: translateX(50%);
406
+        padding: 0 px(15);
407
+        font-size: px(30);
408
+        color: #fff;
409
+        border-radius: px(21);
410
+        background-color: #262626;
411
+    }
412
+}
413
+
414
+.order {
415
+    padding-top: px(30);
416
+
417
+    &__item {
418
+        margin: px(20);
419
+        margin-top: px(30);
420
+        background-color: #fff;
421
+        border-radius: px(10);
422
+        box-shadow: 0px 2px 6px -3px rgba(0,0,0,0.5);
423
+    }
424
+    &__main{
425
+        padding: px(40);
426
+    }
427
+    &__top {
428
+        display: flex;
429
+        justify-content: space-between;
430
+        align-items: center;
431
+        .des {
432
+            font-size: px(40);
433
+        }
434
+        .index {
435
+            font-size: px(55);
436
+        }
437
+        .symbol {
438
+            font-size: px(36);
439
+        }
440
+    }
441
+    
442
+
443
+    &__con {
444
+        margin-top: px(60);
445
+        padding-left: px(60);
446
+        position: relative;
447
+        &::after{
448
+            content: "";
449
+            position: absolute;
450
+            left: px(20);
451
+            top: px(60);
452
+            bottom: px(60);
453
+            width: px(3);
454
+            background-color: #a8a8a8;
455
+        }
456
+    }
457
+
458
+    &__title{
459
+        font-size: px(60);
460
+        position: relative;
461
+        &::after{
462
+            content: "";
463
+            position: absolute;
464
+            left: px(-50);
465
+            top: 50%;
466
+            transform: translate(0,-50%);
467
+            z-index: 1;
468
+            width: px(20);
469
+            height: px(20);
470
+            border-radius: 50%;
471
+            background-color: #a8a8a8;
472
+        }
473
+        &.on{
474
+            color: #333;
475
+            &::after{
476
+                background-color: #f68a3f;
477
+            }
478
+        }
479
+    }
480
+    &__title2{
481
+        margin-top: px(60);
482
+            color: #999;
483
+    }
484
+    &__des{
485
+        font-size: px(36);
486
+        margin-top: px(20);
487
+    }
488
+    &__btns{
489
+        display: flex;
490
+        border-top: 1px solid #dedede;
491
+        justify-content: space-between;
492
+        .btn{
493
+            height: px(130);
494
+            line-height: px(130);
495
+            text-align: center;
496
+        }
497
+        .active{
498
+            background-color: #f68a3f;
499
+            color: #333;
500
+            font-size: px(50);
501
+            width: 100%;
502
+        }
503
+        .tel{
504
+            width: px(200);
505
+            flex-shrink: 0;
506
+            display: flex;
507
+            flex-direction: column;
508
+            justify-content: center;
509
+            align-items: center;
510
+            font-size: px(36);
511
+            line-height: 1;
512
+            /deep/ img{
513
+                width: px(60);
514
+                height: px(60);
515
+                margin-bottom: px(10);
516
+            }
517
+        }
518
+        
519
+    }
520
+}
521
+
522
+.caption {
523
+    display: flex;
524
+    align-items: center;
525
+
526
+    &__icon {
527
+        margin-top: px(5);
528
+        font-size: px(44);
529
+        color: #333;
530
+    }
531
+
532
+    &__title {
533
+        margin-left: px(30);
534
+        font-size: px(36);
535
+        color: #333;
536
+    }
537
+
538
+    &__arrows {
539
+        margin: px(5) 0 0 px(20);
540
+        font-size: px(44);
541
+        color: #333;
542
+    }
543
+}
544
+
545
+.null {
546
+    display: flex;
547
+    flex-direction: column;
548
+    justify-content: center;
549
+    align-items: center;
550
+    padding-top: px(145);
551
+
552
+    &__img {
553
+        width: px(739);
554
+        height: px(371);
555
+    }
556
+
557
+    &__title {
558
+        margin-top: px(20);
559
+        font-size: px(42);
560
+        color: #666;
561
+    }
562
+
563
+    &__sub-title {
564
+        margin-top: px(20);
565
+        font-size: px(42);
566
+        color: #999;
567
+    }
568
+}
569
+</style>

BIN
src/static/icon/tal.png


+ 76 - 0
src/uni.scss

@@ -0,0 +1,76 @@
1
+/**
2
+ * 这里是uni-app内置的常用样式变量
3
+ *
4
+ * uni-app 官方扩展插件及插件市场(https://ext.dcloud.net.cn)上很多三方插件均使用了这些样式变量
5
+ * 如果你是插件开发者,建议你使用scss预处理,并在插件代码中直接使用这些变量(无需 import 这个文件),方便用户通过搭积木的方式开发整体风格一致的App
6
+ *
7
+ */
8
+
9
+/**
10
+ * 如果你是App开发者(插件使用者),你可以通过修改这些变量来定制自己的插件主题,实现自定义主题功能
11
+ *
12
+ * 如果你的项目同样使用了scss预处理,你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件
13
+ */
14
+
15
+/* 颜色变量 */
16
+
17
+/* 行为相关颜色 */
18
+$uni-color-primary: #007aff;
19
+$uni-color-success: #4cd964;
20
+$uni-color-warning: #f0ad4e;
21
+$uni-color-error: #dd524d;
22
+
23
+/* 文字基本颜色 */
24
+$uni-text-color: #333; //基本色
25
+$uni-text-color-inverse: #fff; //反色
26
+$uni-text-color-grey: #999; //辅助灰色,如加载更多的提示信息
27
+$uni-text-color-placeholder: #808080;
28
+$uni-text-color-disable: #c0c0c0;
29
+
30
+/* 背景颜色 */
31
+$uni-bg-color: #ffffff;
32
+$uni-bg-color-grey: #f8f8f8;
33
+$uni-bg-color-hover: #f1f1f1; //点击状态颜色
34
+$uni-bg-color-mask: rgba(0, 0, 0, 0.4); //遮罩颜色
35
+
36
+/* 边框颜色 */
37
+$uni-border-color: #c8c7cc;
38
+
39
+/* 尺寸变量 */
40
+
41
+/* 文字尺寸 */
42
+$uni-font-size-sm: 24 upx;
43
+$uni-font-size-base: 28 upx;
44
+$uni-font-size-lg: 32 upx;
45
+
46
+/* 图片尺寸 */
47
+$uni-img-size-sm: 40 upx;
48
+$uni-img-size-base: 52 upx;
49
+$uni-img-size-lg: 80 upx;
50
+
51
+/* Border Radius */
52
+$uni-border-radius-sm: 4 upx;
53
+$uni-border-radius-base: 6 upx;
54
+$uni-border-radius-lg: 12 upx;
55
+$uni-border-radius-circle: 50%;
56
+
57
+/* 水平间距 */
58
+$uni-spacing-row-sm: 10px;
59
+$uni-spacing-row-base: 20 upx;
60
+$uni-spacing-row-lg: 30 upx;
61
+
62
+/* 垂直间距 */
63
+$uni-spacing-col-sm: 8 upx;
64
+$uni-spacing-col-base: 16 upx;
65
+$uni-spacing-col-lg: 24 upx;
66
+
67
+/* 透明度 */
68
+$uni-opacity-disabled: 0.3; // 组件禁用态的透明度
69
+
70
+/* 文章场景相关 */
71
+$uni-color-title: #2C405A; // 文章标题颜色
72
+$uni-font-size-title: 40 upx;
73
+$uni-color-subtitle: #555555; // 二级标题颜色
74
+$uni-font-size-subtitle: 36 upx;
75
+$uni-color-paragraph: #3F536E; // 文章段落颜色
76
+$uni-font-size-paragraph: 30 upx;

+ 9 - 0
tsconfig.json

@@ -0,0 +1,9 @@
1
+{
2
+    "compilerOptions": {
3
+        "types": [
4
+            "@dcloudio/types",
5
+            "miniprogram-api-typings",
6
+            "mini-types"
7
+        ]
8
+    }
9
+}

+ 63 - 0
vue.config.js

@@ -0,0 +1,63 @@
1
+const CompressionWebpackPlugin = require('compression-webpack-plugin')
2
+const path = require('path')
3
+const CopyWebpackPlugin = require('copy-webpack-plugin')
4
+
5
+module.exports = {
6
+    // eslint-loader 是否在保存的时候检查
7
+    lintOnSave: true,
8
+
9
+    // webpack配置
10
+    configureWebpack: config => {
11
+        if (process.env.UNI_PLATFORM === 'h5') {
12
+
13
+            // 开启gzip压缩
14
+            config.plugins = [
15
+                ...config.plugins,
16
+                new CompressionWebpackPlugin({
17
+                    filename: '[path].gz[query]',
18
+                    algorithm: 'gzip',
19
+                    test: new RegExp('\\.(' + ['js', 'css'].join('|') + ')$'),
20
+                    threshold: 8192,
21
+                    minRatio: 0.8,
22
+                }),
23
+            ]
24
+
25
+            // public目录下文件文件设置为静态资源目录
26
+            config.plugins = [
27
+                ...config.plugins,
28
+                new CopyWebpackPlugin([
29
+                    {
30
+                        from: path.join(__dirname, 'public'),
31
+                        to: path.join(__dirname, 'dist', process.env.NODE_ENV === 'production' ? 'build' : 'dev', process.env.UNI_PLATFORM),
32
+                    },
33
+                ]),
34
+            ]
35
+        }
36
+    },
37
+
38
+    // 生产环境是否生成 sourceMap 文件
39
+    productionSourceMap: false,
40
+
41
+    // css相关配置
42
+    css: {
43
+        sourceMap: process.env.NODE_ENV !== 'production',
44
+        loaderOptions: {
45
+            scss: {
46
+                prependData: `@import "~@/common/scss/public.scss";`,
47
+            },
48
+        },
49
+    },
50
+
51
+    // webpack-dev-server 相关配置
52
+    devServer: {
53
+        open: false, // 配置自动启动浏览器
54
+        port: 8080, // 端口号
55
+        https: false,
56
+        hotOnly: true,
57
+        disableHostCheck: true,
58
+        proxy: '',// 设置代理
59
+    },
60
+
61
+    // 第三方插件配置
62
+    pluginOptions: {},
63
+}

File diff suppressed because it is too large
+ 11107 - 0
yarn.lock