Compare commits
87 Commits
486ea5013a
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 224db6202c | |||
| dbd3800314 | |||
| 4545fbfab5 | |||
| 49af2cd078 | |||
| bca9390042 | |||
| bad6348393 | |||
| c56ea0dd73 | |||
| 4d7f73aedf | |||
| 3945b36b0a | |||
| 4344adeb0b | |||
| 11a0637039 | |||
| b53dc2dd4f | |||
| 0c0d5e55d5 | |||
| b7461002dc | |||
| 68262d0519 | |||
| d757f99b5d | |||
| e910a76437 | |||
| 85d52f5065 | |||
| 915ff6b184 | |||
| e92323a15b | |||
| 048ce5fd05 | |||
| 448ee810de | |||
| 6cd0361f33 | |||
| 0b1f0b9e26 | |||
| 531a955fe2 | |||
| cb40ce643f | |||
| f547216c2b | |||
| 62c9994444 | |||
| 100744cfaf | |||
| 74dba2ef29 | |||
| dccdd43e3a | |||
| eb1abb69fd | |||
| 68cce822be | |||
| 5bbfff9e21 | |||
| 7f6ace8ac6 | |||
| bb9a32d296 | |||
| bfc04c54aa | |||
| 5b8c7d4a2d | |||
| 634e801eb5 | |||
| 7b3676eda7 | |||
| 6c4c2ac85d | |||
| b87c8e8292 | |||
| 32aa0eb971 | |||
| 178e8ff5cb | |||
| 0562554266 | |||
| 877469ab43 | |||
| 13fd77f13b | |||
| f2f7fcde48 | |||
| 16dac8d97f | |||
| b676a1acd9 | |||
| a270c9be70 | |||
| d6f3f9c812 | |||
| 23af4c25e3 | |||
| be328f9243 | |||
| 93e9c5227b | |||
| 222bae69d9 | |||
| c94ddeed1a | |||
| 935d56227d | |||
| a06d74934f | |||
| 60cb832b02 | |||
| b502385272 | |||
| 1fc0aa432b | |||
| 074b0057da | |||
| 52b63a757f | |||
| 51c708f9fa | |||
| 91af869899 | |||
| 4fb648f003 | |||
| 792aa4268a | |||
| 8d7f82b07c | |||
| 7f0f11cf14 | |||
| cfdc8d088c | |||
| 84b6ff15c7 | |||
| 8b0ad91bd4 | |||
| 351e20f0c0 | |||
| 3ce85e2396 | |||
| 43b5ea640e | |||
| 7a3dd0fae8 | |||
| 9dda08a1b1 | |||
| 0602dc6c72 | |||
| c17b70af2d | |||
| 0883e88df0 | |||
| 00013cb46c | |||
| 107783062b | |||
| 2df1a93e6b | |||
| 2610f4e6f1 | |||
| 2280c0518b | |||
| 82b09c68a5 |
@@ -4,8 +4,10 @@ VITE_APP_TITLE='uniapp-vue3-project'
|
|||||||
# 开发环境配置
|
# 开发环境配置
|
||||||
VITE_APP_ENV='development'
|
VITE_APP_ENV='development'
|
||||||
|
|
||||||
|
VITE_APP_ID='wx92e663dc11d0c0a8'
|
||||||
|
|
||||||
# 接口地址
|
# 接口地址
|
||||||
VITE_APP_BASE_API='/api'
|
VITE_APP_BASE_API='https://apidev.lakeapp.cn/'
|
||||||
|
|
||||||
# 删除console
|
# 删除console
|
||||||
VITE_DROP_CONSOLE=false
|
VITE_DROP_CONSOLE=false
|
||||||
|
|||||||
@@ -4,8 +4,10 @@ VITE_APP_TITLE='uniapp-vue3-project'
|
|||||||
# 生产环境配置
|
# 生产环境配置
|
||||||
VITE_APP_ENV='production'
|
VITE_APP_ENV='production'
|
||||||
|
|
||||||
|
VITE_APP_ID='wx67a750d0ceed4d88'
|
||||||
|
|
||||||
# 接口地址
|
# 接口地址
|
||||||
VITE_APP_BASE_API='/'
|
VITE_APP_BASE_API='https://api.lakeapp.cn/'
|
||||||
|
|
||||||
# 删除console
|
# 删除console
|
||||||
VITE_DROP_CONSOLE=true
|
VITE_DROP_CONSOLE=true
|
||||||
|
|||||||
14
.env.test
14
.env.test
@@ -1,11 +1,17 @@
|
|||||||
# 页面标题
|
# 页面标题
|
||||||
VITE_APP_TITLE='uniapp-vue3-project'
|
VITE_APP_TITLE='uniapp-vue3-project'
|
||||||
|
|
||||||
# 生产环境配置
|
# 开发环境配置
|
||||||
VITE_APP_ENV='production'
|
VITE_APP_ENV='test'
|
||||||
|
|
||||||
|
VITE_APP_ID='wx92e663dc11d0c0a8'
|
||||||
|
|
||||||
# 接口地址
|
# 接口地址
|
||||||
VITE_APP_BASE_API='/'
|
#VITE_APP_BASE_API='https://apidev.lakeapp.cn/'
|
||||||
|
VITE_APP_BASE_API='https://api.lakeapp.cn/'
|
||||||
|
|
||||||
# 删除console
|
# 删除console
|
||||||
VITE_DROP_CONSOLE=true
|
VITE_DROP_CONSOLE=false
|
||||||
|
|
||||||
|
# 是否开启Mock
|
||||||
|
VITE_USE_MOCK=true
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ const WX_DESC = envType == 'production' ? '正式环境' : '测试环境'
|
|||||||
(async () => {
|
(async () => {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
const manifest = path.resolve(__dirname, './src/manifest.json')
|
const manifest = path.resolve(__dirname, './src/manifest.json')
|
||||||
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
const manifestConfig = JSON.parse(fs.readFileSync(manifest).toString())
|
const manifestConfig = JSON.parse(fs.readFileSync(manifest).toString())
|
||||||
const appId = manifestConfig['mp-weixin'].appid
|
const appId = manifestConfig['mp-weixin'].appid
|
||||||
|
|||||||
27
keys/private.wx67a750d0ceed4d88.key
Normal file
27
keys/private.wx67a750d0ceed4d88.key
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
-----BEGIN RSA PRIVATE KEY-----
|
||||||
|
MIIEowIBAAKCAQEAw7dY+KsQ9Qa1Q0Amp2bNWW3/ch/2OmS5SsiXSfRgVLKcUB1C
|
||||||
|
1svyjDUzqaw53Rhn4WdwUCFQCkhWs1ud7NA/eudaqLmvrX0SaH6bJz2XCzyNoElM
|
||||||
|
amHh0U4sKEFcOcY9FPsriislpCmKnOKjyKB6fnpzIn7JxespswhiDsiKC2dk/8nB
|
||||||
|
GFeN559MYy6qOUyFrykkcF21oSfOynhw+ziqxRBIKh30dR1nUy+FZrZiVx2Bj/id
|
||||||
|
39AbZ89lK8pzdlFHtXqd56UCe5fEselh+KbT4eKIEhHoO+vSqralASLDMxijgA3V
|
||||||
|
49AUmpQ6F4nW9GfF3/IreX8X7k457M6FKo8L1QIDAQABAoIBABnTb+IgcLRkljax
|
||||||
|
mGguoJpUcYjVvuAlum2r2orfvHZwuz+3HMLLVs45lv+kwl3ygoKz65YnTzCMKySv
|
||||||
|
yj8dm8LUFJp/Jjd2cZ9oVYDwF6Zb7zRfd73x/KJp9lm5hjn5dsX1/uDUoLrw4GGj
|
||||||
|
Zolq478c2WSL5oQ/a9k8GfRpcg3e88L89r6QjZuQ3jmVxe4fJlYbUR3YXE2t3c41
|
||||||
|
v/uQfxXvvVrYGc8/jZE4AQcFbZhKu1xfl7dy8AEisZa4OxU5Gd+onHcnUgGO6oRn
|
||||||
|
x0pZQnZJZoTLJe8uB0jl+OPLLQbRcA01jITKAHKOqOQYgynfzy6xfMWhNk/4YWtf
|
||||||
|
oJ+wFmECgYEA7H/Iov01m7+k+oe3XyiQC0zMLtHWzF3thdAUJFRZPBfzb5X/F9a2
|
||||||
|
k+feK69aXHnsWtVKO1kZ+FMMs7OU0LOX+LRDeeiJqlhnuOC63NfyZ6yfgOEBq38s
|
||||||
|
C7rxgsuS6D5VvEzj57sjBGRTyfjNZVvfflBMVn9JgwVzdo9RumLnD98CgYEA09qv
|
||||||
|
IJtFlPcAbIuKQMRUnrLVDI5hMYzQUwpj4RkBOASIgCtJHUoN4GvdAaYeE6q9eeD1
|
||||||
|
TyKyIJekECejOqLdzidE/aOVRWcgiEjxjGf4e9n4/6q9CJGH7v2WMNbziALHb6We
|
||||||
|
KBwrIdaakD7m2yVZ1PxTyljCXx3wvv3IN/khSssCgYEAv8CH2+cz3RlQ2bTKcARC
|
||||||
|
bncRInEPGNqbaCCjBCXDyF6fCX1zvE9h76BTWdYujMZqZeeD7YS78sTbiqRzZ5gG
|
||||||
|
Ayedgi2R2SUezB6iQ8dvirHDDcriALv26Xfks6j9bwKDn040h0ILDVePPDZXyvPn
|
||||||
|
zNGsY4GHCA2WZa2klVv1fr8CgYBCkMPWCvOiCronYPDfyNCNzMMEXvhLCWOrs+gO
|
||||||
|
Ij0vzLzXCMLAYTRa/4lBq2Bn7Y37baOmadBuTTdPnCS9l875p30V9QBB/lVKfSDo
|
||||||
|
bQK2Z5bFPnCG8LM1dJhsYB3E7pqbif5XvAIRb8zA5gLDeMjxExeAzMLGADJU0IjI
|
||||||
|
jY7YYQKBgFy7WTwnEV4NTjus1FXj4Bf1BYJRrDRtxMNiKWZZ+C1XQqA1zWiIfDzt
|
||||||
|
B1LKjBwWZsM2ali582PcMkJYPVZBG+hMmHlAme/acpzGF4oiANZp+kCcrnxFvKvs
|
||||||
|
PAO6ui1zDN92bGNf/LQQOf1TM29sUbAFnwxNFOxvs2FbpWvFj0V3
|
||||||
|
-----END RSA PRIVATE KEY-----
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
-----BEGIN RSA PRIVATE KEY-----
|
|
||||||
MIIEowIBAAKCAQEAtAuySwDuVUqiKAgtB8yhmDXMbFtgSZQiC4FtahrqAxcwcett
|
|
||||||
khfncnldZZGMUtK3dM/xA5YaKe18vish3qbymwc+863r2NKIFtWhWIglXDuutGgT
|
|
||||||
U9/IqCnh4Dx8Owlw5/EzbvHSXj1/uzwuAVO6cxkkEvz9mxYixuB3YCd8yKQ5rLnu
|
|
||||||
EwNf063fI+jDVUBeyEejSZJ0pi3OzWdXJOjS9UYv2bAYOfJluGucfDXMbfdz8euy
|
|
||||||
T8WRCPJp4X2QoQU5WcSxWnvRSllwAfposZTIcu/msXm77QwoYqCHvJ2suGzL+SXa
|
|
||||||
c73wQB289dXqHbYmSa7bPmTmOEyCPYao0oIh8wIDAQABAoIBACfpb9ywmCTQJqI5
|
|
||||||
LcJM2oWjZ22d0/p7nBBw4JBk5vtIaLTYO7HnGqeFv+6EFVdG3uRGNGdXHvWsb7q4
|
|
||||||
VQnGeIFlWc8q/t1RzllBgkLd62pG0LOtXpt5QEIHBstunRt5PE4uafhuIvRBLc+T
|
|
||||||
x58DsJFTQWv0KUP35D2yBMSL/F19qqF6oe43kYbAei8w608XXKOT/rODdk1Ie3yx
|
|
||||||
AOgM4DvTqcSdqL/SDJ6r8xoplDNk4l+QYCJ9z7JodnJfU5OQVWw8WFWRg3jP9k/S
|
|
||||||
DsojcusTs1s14X8V3/TbR1vVW6g4Q5QnNFozHaKRZAD9DuBStrL02hgAq7oXdg+g
|
|
||||||
IoMR+AECgYEA7VVuOWwt2aWXks9aPpOVs9knMdrpxbO1nE/B2JECICElFtL8xwUi
|
|
||||||
BxWcM++wJNtKTAjJfpnFGZkyHfmnB8V0itGIz1lCZTs/yraJqaLxQdbHjEnCoCRq
|
|
||||||
tl1751hsBS15XFDskKHGFZj0wv9nq3I0wUoMjhsRV+Lopq+uHCodcgMCgYEAwjTO
|
|
||||||
dwh/0cTjiGOV8iX9WdM0I3wnYfcAgDbxGKNyZNw8oQ52vzTn1VG+LcxMcy+OUq/a
|
|
||||||
B/XBjkUI4WyHfK7zM6rhlQB8pWR3i+yPyLXJ69oRQwYAeHQzgZ6Z+sSsusHcG/wN
|
|
||||||
J/Z9EqiWQK/tZsBXQxDpHqxwz9Xl1BlL0xX9BVECgYBHKsr2pR3KmgEtoMfq486M
|
|
||||||
M52xMXfQNOdMjA4QpssAX3ADvBjYhQ2DGlPQrxsesjNBQZFKSUn1Nx70JhyUE/2y
|
|
||||||
csqXgqiKOo4Sd1IocBfwKjuEMcoOw1zMepPg937MvqoZqJqHdDs11rvujS/FFWYE
|
|
||||||
X/QL2MoGlKA2+482GtrhiQKBgQCTt8jnn45hx2nuXxk5w42umkiJSTFHgbJe0+uU
|
|
||||||
+xXTA/YV50OJcrt4daG7gi8QWjbeTCYCcfrUtUvo8z0nKIeSYEMPq/wjbYTE6J4B
|
|
||||||
Y8z/2bHRkiofdPuMd0/V/20G7Nf4bUKwh/tgit0mvOpNgrWdLKq1CyMP4znal5cm
|
|
||||||
Kw520QKBgB+I8yfp/E01ruSccdgRH3WMGStuHhSxcQ8WWD9oFdOn+klxr8h4al3+
|
|
||||||
Ibo6SJkKmwg2/IEsuc52qZPH5594XfQ7HxfVf9RVwdR96epRqah/cHofIVCX1wQB
|
|
||||||
CCirZNNiBe2hQxDyAHn492a6dzcjMojDN5JS+Yt071CB0Tph7+2c
|
|
||||||
-----END RSA PRIVATE KEY-----
|
|
||||||
40
manifest.modify.ts
Normal file
40
manifest.modify.ts
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
// @ts-ignore
|
||||||
|
const fs = require('fs');
|
||||||
|
// @ts-ignore
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
const currentDir = path.dirname(__filename);
|
||||||
|
const manifestPath = path.join(currentDir, 'src/manifest.json');
|
||||||
|
|
||||||
|
const VITE_APP_WX_APPID = process.env.NODE_ENV === 'production' ? 'wx67a750d0ceed4d88' : 'wx92e663dc11d0c0a8';
|
||||||
|
fs.readFile(manifestPath, (err, data) => {
|
||||||
|
if(err) {
|
||||||
|
console.error(err);
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
if(!VITE_APP_WX_APPID) {
|
||||||
|
console.log('写入失败,没读到appid');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const _data = JSON.parse(data.toString());
|
||||||
|
_data['mp-weixin'].appid = VITE_APP_WX_APPID;
|
||||||
|
const newData = JSON.stringify(_data, null, 2);
|
||||||
|
fs.writeFile(
|
||||||
|
manifestPath,
|
||||||
|
newData,
|
||||||
|
{
|
||||||
|
encoding: 'utf-8'
|
||||||
|
},
|
||||||
|
(err) => {
|
||||||
|
if(err) {
|
||||||
|
console.log('APPID 写入失败', err);
|
||||||
|
} else {
|
||||||
|
console.log(`APPID 写入成功 ${VITE_APP_WX_APPID}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
} catch (parseError) {
|
||||||
|
console.error('解析 manifest.json 失败', parseError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
68
package.json
68
package.json
@@ -4,10 +4,12 @@
|
|||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "uni -p mp-weixin",
|
"dev": "uni -p mp-weixin",
|
||||||
"build:test": "uni build --mode test -p mp-weixin",
|
"dev:test": "cross-env NODE_ENV=development node manifest.modify.ts && uni -p mp-weixin --mode development",
|
||||||
"build:prod": "uni build --mode production -p mp-weixin",
|
"dev:prod": "cross-env NODE_ENV=production node manifest.modify.ts && uni -p mp-weixin --mode production",
|
||||||
"deploy:test": "uni build --mode test -p mp-weixin && node deploy.ts test",
|
"build:test": "cross-env NODE_ENV=production UNI_PLATFORM=mp-weixin vue-cli-service uni-build --mode test",
|
||||||
"deploy:prod": "uni build --mode production -p mp-weixin && node deploy.ts production",
|
"build:prod": "cross-env NODE_ENV=production UNI_PLATFORM=mp-weixin vue-cli-service uni-build --mode production",
|
||||||
|
"deploy:test": "cross-env NODE_ENV=test node manifest.modify.ts && uni build --mode test -p mp-weixin && node deploy.ts test",
|
||||||
|
"deploy:prod": "cross-env NODE_ENV=production node manifest.modify.ts && uni build --mode production -p mp-weixin && node deploy.ts production",
|
||||||
"type-check": "vue-tsc --noEmit",
|
"type-check": "vue-tsc --noEmit",
|
||||||
"eslint": "eslint --fix",
|
"eslint": "eslint --fix",
|
||||||
"stylelint": "stylelint \"src/**/*.(vue|scss|css)\" --fix",
|
"stylelint": "stylelint \"src/**/*.(vue|scss|css)\" --fix",
|
||||||
@@ -15,53 +17,53 @@
|
|||||||
"postinstall": "simple-git-hooks"
|
"postinstall": "simple-git-hooks"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@dcloudio/uni-app": "3.0.0-3090920231225001",
|
"@dcloudio/uni-app": "3.0.0-alpha-4010520240507001",
|
||||||
"@dcloudio/uni-app-plus": "3.0.0-3090920231225001",
|
"@dcloudio/uni-app-plus": "3.0.0-alpha-4010520240507001",
|
||||||
"@dcloudio/uni-components": "3.0.0-3090920231225001",
|
"@dcloudio/uni-components": "3.0.0-alpha-4010520240507001",
|
||||||
"@dcloudio/uni-h5": "3.0.0-3090920231225001",
|
"@dcloudio/uni-mp-weixin": "3.0.0-alpha-4010520240507001",
|
||||||
"@dcloudio/uni-mp-weixin": "3.0.0-3090920231225001",
|
"dayjs": "^1.11.10",
|
||||||
"@dcloudio/uni-mp-xhs": "3.0.0-3090920231225001",
|
|
||||||
"pinia": "2.0.36",
|
"pinia": "2.0.36",
|
||||||
"uview-plus": "^3.1.38",
|
"pinia-plugin-persistedstate": "^3.2.1",
|
||||||
"vue": "3.2.47",
|
"uview-plus": "^3.1.41",
|
||||||
"vue-i18n": "^9.1.9",
|
"vue": "3.4.21",
|
||||||
"z-paging": "^2.6.2"
|
"vue-i18n": "^9.9.0",
|
||||||
|
"z-paging": "^2.6.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@antfu/eslint-config": "1.1.0",
|
"@antfu/eslint-config": "1.1.0",
|
||||||
"@dcloudio/types": "^3.4.3",
|
"@dcloudio/types": "^3.4.8",
|
||||||
"@dcloudio/uni-automator": "3.0.0-3090920231225001",
|
"@dcloudio/uni-automator": "3.0.0-alpha-4010520240507001",
|
||||||
"@dcloudio/uni-cli-shared": "3.0.0-3090920231225001",
|
"@dcloudio/uni-cli-shared": "3.0.0-alpha-4010520240507001",
|
||||||
"@dcloudio/uni-stacktracey": "3.0.0-3090920231225001",
|
"@dcloudio/uni-stacktracey": "3.0.0-alpha-4010520240507001",
|
||||||
"@dcloudio/vite-plugin-uni": "3.0.0-3090920231225001",
|
"@dcloudio/vite-plugin-uni": "3.0.0-alpha-4010520240507001",
|
||||||
"@types/node": "^20.8.10",
|
"@types/node": "^20.10.3",
|
||||||
"@typescript-eslint/parser": "^6.10.0",
|
"@typescript-eslint/parser": "^6.13.1",
|
||||||
"@uni-helper/uni-app-types": "^0.5.9",
|
"@uni-helper/uni-app-types": "^0.5.12",
|
||||||
"@unocss/eslint-plugin": "^0.57.2",
|
"@unocss/eslint-plugin": "^0.57.7",
|
||||||
"@vue/runtime-core": "^3.2.45",
|
"@vue/runtime-core": "^3.4.21",
|
||||||
"@vue/tsconfig": "^0.4.0",
|
"@vue/tsconfig": "^0.4.0",
|
||||||
"czg": "^1.7.1",
|
"czg": "^1.7.1",
|
||||||
"eslint": "^8.53.0",
|
"eslint": "^8.55.0",
|
||||||
"lint-staged": "^15.0.2",
|
"lint-staged": "^15.2.0",
|
||||||
"miniprogram-ci": "^1.9.8",
|
"miniprogram-ci": "^1.9.10",
|
||||||
"picocolors": "^1.0.0",
|
"picocolors": "^1.0.0",
|
||||||
"postcss-html": "^1.5.0",
|
"postcss-html": "^1.5.0",
|
||||||
"postcss-scss": "^4.0.9",
|
"postcss-scss": "^4.0.9",
|
||||||
"sass": "^1.69.5",
|
"sass": "^1.69.5",
|
||||||
"simple-git-hooks": "^2.9.0",
|
"simple-git-hooks": "^2.9.0",
|
||||||
"stylelint": "^15.11.0",
|
"stylelint": "^15.11.0",
|
||||||
"stylelint-config-recess-order": "^4.3.0",
|
"stylelint-config-recess-order": "^4.4.0",
|
||||||
"stylelint-config-standard": "^34.0.0",
|
"stylelint-config-standard": "^34.0.0",
|
||||||
"stylelint-config-standard-vue": "^1.0.0",
|
"stylelint-config-standard-vue": "^1.0.0",
|
||||||
"stylelint-order": "^6.0.3",
|
"stylelint-order": "^6.0.3",
|
||||||
"typescript": "^5.2.2",
|
"typescript": "^5.3.2",
|
||||||
"unocss": "^0.57.2",
|
"unocss": "^0.57.7",
|
||||||
"unocss-applet": "^0.7.7",
|
"unocss-applet": "^0.7.8",
|
||||||
"unplugin-auto-import": "^0.16.7",
|
"unplugin-auto-import": "^0.16.7",
|
||||||
"unplugin-vue-components": "^0.25.2",
|
"unplugin-vue-components": "^0.25.2",
|
||||||
"vite": "^4.5.2",
|
"vite": "^5.2.8",
|
||||||
"vite-plugin-imagemin": "^0.6.1",
|
"vite-plugin-imagemin": "^0.6.1",
|
||||||
"vue-tsc": "^1.8.22"
|
"vue-tsc": "^1.8.24"
|
||||||
},
|
},
|
||||||
"lint-staged": {
|
"lint-staged": {
|
||||||
"src/**/*.{js,jsx,ts,tsx}": "eslint --fix",
|
"src/**/*.{js,jsx,ts,tsx}": "eslint --fix",
|
||||||
|
|||||||
3141
pnpm-lock.yaml
generated
3141
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
253
src/App.vue
253
src/App.vue
@@ -1,21 +1,244 @@
|
|||||||
<script setup lang="ts">
|
<script lang='ts'>
|
||||||
import { mpUpdate } from '@/utils';
|
import {
|
||||||
|
getCompanyId,
|
||||||
|
getRegisterStoreId,
|
||||||
|
mpUpdate,
|
||||||
|
setCompanyId,
|
||||||
|
setReferrerUserId,
|
||||||
|
setRegisterStoreId
|
||||||
|
} from '@/utils';
|
||||||
|
import { Logger } from '@/utils/common/logger';
|
||||||
|
|
||||||
|
const logger = new Logger();
|
||||||
|
|
||||||
|
export default {
|
||||||
|
onLaunch: async (options: any) => {
|
||||||
|
const miniProgram = uni.getAccountInfoSync().miniProgram;
|
||||||
|
const env = miniProgram.envVersion;
|
||||||
|
|
||||||
|
console.log(`App Launch options ${env}: `, options);
|
||||||
|
|
||||||
|
//生产
|
||||||
|
if(env === 'release') {
|
||||||
|
logger.info(`App Launch options ${env}: `, options);
|
||||||
|
|
||||||
|
async function getVersionStatus() {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
uni.request({
|
||||||
|
url: 'https://api.lakeapp.cn/wechat/version_info',
|
||||||
|
success(res) {
|
||||||
|
console.log(res);
|
||||||
|
resolve(res);
|
||||||
|
},
|
||||||
|
fail(exception) {
|
||||||
|
reject(exception);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}).then((res) => {
|
||||||
|
const { version, audit } = res.data;
|
||||||
|
// if(miniProgram.version === version && audit == 1) {
|
||||||
|
if(audit == 1) {
|
||||||
|
setCompanyId('1150930317231112193');
|
||||||
|
setRegisterStoreId('1150930317436633090');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
await getVersionStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
//测试、开发 trial,develop
|
||||||
|
else {
|
||||||
|
//生产环境
|
||||||
|
if(import.meta.env.VITE_APP_BASE_API.includes('api.lakeapp')) {
|
||||||
|
// setCompanyId('1150930317231112193');
|
||||||
|
// setRegisterStoreId('1150930317436633090');
|
||||||
|
|
||||||
|
setCompanyId('1471673498334113794');
|
||||||
|
setRegisterStoreId('1471673498413805570');
|
||||||
|
}
|
||||||
|
//测试
|
||||||
|
else {
|
||||||
|
setCompanyId('1724629180555919361');
|
||||||
|
setRegisterStoreId('1725026299888406529');
|
||||||
|
// setRegisterStoreId('17250262998884000000');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(options?.query) {
|
||||||
|
|
||||||
|
// options.query.scene = 'companyId%3D1150930317231112193%26wxOpenId%3D111%26ticketId%3D123456%26storeId%3D1150930317436633090'
|
||||||
|
|
||||||
|
//保存登录邀请员工id
|
||||||
|
if(options.query.referrerUserId) {
|
||||||
|
setReferrerUserId(options.query.referrerUserId);
|
||||||
|
}
|
||||||
|
|
||||||
|
//保存注册门店id
|
||||||
|
if(options.query.companyId) {
|
||||||
|
setCompanyId(options.query.companyId);
|
||||||
|
}
|
||||||
|
|
||||||
|
//保存注册门店id
|
||||||
|
if(options.query.storeId) {
|
||||||
|
setRegisterStoreId(options.query.storeId);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(options?.query.scene) {
|
||||||
|
function getQueryParam(queryParams: string, key: string) {
|
||||||
|
let regex = new RegExp('(?:[?&]|^)' + key + '=([^&]+)'),
|
||||||
|
match = queryParams.match(regex);
|
||||||
|
return match && match[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
//保存注册门店id
|
||||||
|
const params = decodeURIComponent(options?.query.scene);
|
||||||
|
if(params.includes('companyId')) {
|
||||||
|
setCompanyId(getQueryParam(params, 'companyId') || '');
|
||||||
|
}
|
||||||
|
if(params.includes('storeId')) {
|
||||||
|
setRegisterStoreId(getQueryParam(params, 'storeId') || '');
|
||||||
|
}
|
||||||
|
if(options?.query.scene === 'edit_avatar_nickname') {
|
||||||
|
setTimeout(() => {
|
||||||
|
uni.reLaunch({
|
||||||
|
url: '/pages/mine/subs/profile/index'
|
||||||
|
});
|
||||||
|
}, 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//原先商品团购
|
||||||
|
if(options?.path?.includes('ticketsBuy/ticketsBuy') && options?.query.couponsId) {
|
||||||
|
setTimeout(() => {
|
||||||
|
uni.reLaunch({
|
||||||
|
url: 'pages/common/groupbuy/detail?id=' + options?.query.couponsId
|
||||||
|
});
|
||||||
|
}, 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.info(`App Launch options ${env}: { companyId: `, getCompanyId() + ', storeId: ' + getRegisterStoreId() + ' }');
|
||||||
|
|
||||||
|
// #ifdef MP
|
||||||
|
mpUpdate();
|
||||||
|
// #endif
|
||||||
|
},
|
||||||
|
onShow: async () => {
|
||||||
|
console.log('App Show');
|
||||||
|
},
|
||||||
|
onHide: async () => {
|
||||||
|
console.log('App Hide');
|
||||||
|
},
|
||||||
|
|
||||||
|
globalData: {
|
||||||
|
logger: logger,
|
||||||
|
companyId: getCompanyId(),
|
||||||
|
storeId: getRegisterStoreId()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// onLaunch(async (options) => {
|
||||||
|
// console.log('App Launch options ', options);
|
||||||
|
// // globalData.logger.info('launch options : ', options);
|
||||||
|
//
|
||||||
|
// const miniProgram = uni.getAccountInfoSync().miniProgram;
|
||||||
|
// const env = miniProgram.envVersion;
|
||||||
|
//
|
||||||
|
// logger.info('launch options env : ', `${env} ${options}`);
|
||||||
|
// //生产
|
||||||
|
// if(env === 'release' || env === 'trial') {
|
||||||
|
// async function getVersionStatus() {
|
||||||
|
// return new Promise((resolve, reject) => {
|
||||||
|
// uni.request({
|
||||||
|
// url: 'https://api.lakeapp.cn/wechat/version_info',
|
||||||
|
// success(res) {
|
||||||
|
// console.log(res);
|
||||||
|
// resolve(res);
|
||||||
|
// },
|
||||||
|
// fail(exception) {
|
||||||
|
// reject(exception);
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// }).then((res) => {
|
||||||
|
// const { version, audit } = res.data;
|
||||||
|
// // if(miniProgram.version === version && audit == 1) {
|
||||||
|
// if(audit == 1) {
|
||||||
|
// setCompanyId('1150930317231112193');
|
||||||
|
// setRegisterStoreId('1150930317436633090');
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// await getVersionStatus();
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// //测试、开发 trial,develop
|
||||||
|
// else {
|
||||||
|
// // setCompanyId('1724629180555919361');
|
||||||
|
// // setRegisterStoreId('1725026299888406529');
|
||||||
|
// setCompanyId('1471673498334113794');
|
||||||
|
// setRegisterStoreId('1471673498413805570');
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if(options?.query) {
|
||||||
|
//
|
||||||
|
// // options.query.scene = 'companyId%3D1150930317231112193%26wxOpenId%3D111%26ticketId%3D123456%26storeId%3D1150930317436633090'
|
||||||
|
//
|
||||||
|
// //保存登录邀请员工id
|
||||||
|
// if(options.query.referrerUserId) {
|
||||||
|
// setReferrerUserId(options.query.referrerUserId);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// //保存注册门店id
|
||||||
|
// if(options.query.companyId) {
|
||||||
|
// setCompanyId(options.query.companyId);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// //保存注册门店id
|
||||||
|
// if(options.query.storeId) {
|
||||||
|
// setRegisterStoreId(options.query.storeId);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if(options?.query.scene) {
|
||||||
|
// function getQueryParam(queryParams: string, key: string) {
|
||||||
|
// let regex = new RegExp('(?:[?&]|^)' + key + '=([^&]+)'),
|
||||||
|
// match = queryParams.match(regex);
|
||||||
|
// return match && match[1];
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// //保存注册门店id
|
||||||
|
// const params = decodeURIComponent(options?.query.scene);
|
||||||
|
// if(params.includes('companyId')) {
|
||||||
|
// setCompanyId(getQueryParam(params, 'companyId') || '');
|
||||||
|
// }
|
||||||
|
// if(params.includes('storeId')) {
|
||||||
|
// setRegisterStoreId(getQueryParam(params, 'storeId') || '');
|
||||||
|
// }
|
||||||
|
// if(options?.query.scene === 'edit_avatar_nickname') {
|
||||||
|
// setTimeout(() => {
|
||||||
|
// uni.reLaunch({
|
||||||
|
// url: '/pages/mine/subs/profile/index'
|
||||||
|
// });
|
||||||
|
// }, 500);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // #ifdef MP
|
||||||
|
// mpUpdate();
|
||||||
|
// // #endif
|
||||||
|
// });
|
||||||
|
// onShow(() => {
|
||||||
|
// console.log('App Show');
|
||||||
|
// });
|
||||||
|
// onHide(() => {
|
||||||
|
// console.log('App Hide');
|
||||||
|
// });
|
||||||
|
|
||||||
onLaunch(() => {
|
|
||||||
console.log('App Launch');
|
|
||||||
// #ifdef MP
|
|
||||||
mpUpdate();
|
|
||||||
// #endif
|
|
||||||
});
|
|
||||||
onShow(() => {
|
|
||||||
console.log('App Show');
|
|
||||||
});
|
|
||||||
onHide(() => {
|
|
||||||
console.log('App Hide');
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang='scss'>
|
||||||
/* 每个页面公共css */
|
/* 每个页面公共css */
|
||||||
@import 'uview-plus/index.scss';
|
@import 'uview-plus/index.scss';
|
||||||
@import '@/static/styles/common.scss';
|
@import '@/static/styles/common.scss';
|
||||||
|
|||||||
@@ -2,11 +2,13 @@
|
|||||||
* 通用接口
|
* 通用接口
|
||||||
*/
|
*/
|
||||||
import type { SendCodeParams, SendCodeResult, UploadImageResult } from './types';
|
import type { SendCodeParams, SendCodeResult, UploadImageResult } from './types';
|
||||||
import { post, upload } from '@/utils/request';
|
import { get, post, upload } from '@/utils/request';
|
||||||
|
|
||||||
enum URL {
|
enum URL {
|
||||||
upload = '/common/upload',
|
upload = '/common/upload',
|
||||||
sendCode = '/sendCode',
|
sendCode = '/sendCode',
|
||||||
|
barCode = '/ext2/qr/barimg',
|
||||||
|
qrCode = '/ext2/qr/qrimg'
|
||||||
}
|
}
|
||||||
|
|
||||||
// 图片上传
|
// 图片上传
|
||||||
@@ -15,3 +17,12 @@ export const uploadImage = (imagePath: string) =>
|
|||||||
|
|
||||||
// 发送验证码
|
// 发送验证码
|
||||||
export const sendCode = (data: SendCodeParams) => post<SendCodeResult>({ url: URL.sendCode, data });
|
export const sendCode = (data: SendCodeParams) => post<SendCodeResult>({ url: URL.sendCode, data });
|
||||||
|
|
||||||
|
export const generateBarCode = (data: string) => get<ArrayBuffer>({
|
||||||
|
url: `${URL.barCode}?v=${data}`,
|
||||||
|
responseType: 'arraybuffer'
|
||||||
|
});
|
||||||
|
export const generateQrCode = (data: string) => get<ArrayBuffer>({
|
||||||
|
url: `${URL.qrCode}?v=${data}`,
|
||||||
|
responseType: 'arraybuffer'
|
||||||
|
});
|
||||||
|
|||||||
4
src/api/company/index.ts
Normal file
4
src/api/company/index.ts
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
import { get } from '@/utils/request';
|
||||||
|
|
||||||
|
export const getCompanyList = (maOpenId: string) => get({ url: `/wc/wechat/company?maOpenId=${maOpenId}` });
|
||||||
|
export const getCompanyInfo = () => get({ url: `/ext/zconfig/company_find` });
|
||||||
14
src/api/goods/index.ts
Normal file
14
src/api/goods/index.ts
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
import { get } from '@/utils';
|
||||||
|
import { CategoryBean, GoodsBean } from '@/api/goods/types';
|
||||||
|
|
||||||
|
enum URL {
|
||||||
|
categoryList = '/ext/goods/category_list',
|
||||||
|
goodsList = '/ext/goods/query',
|
||||||
|
goodsDetail = '/ext/goods/info'
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getCategoryList = () => get<CategoryBean[]>({ url: URL.categoryList });
|
||||||
|
|
||||||
|
export const getGoodsList = (params: any) => get<GoodsBean[]>({ url: URL.goodsList, data: params });
|
||||||
|
|
||||||
|
export const getGoodsDetail = (goodsId: string) => get<GoodsBean>({ url: URL.goodsDetail + `?goodsId=${goodsId}` });
|
||||||
70
src/api/goods/types.ts
Normal file
70
src/api/goods/types.ts
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
export interface CategoryBean {
|
||||||
|
typeId: string;
|
||||||
|
typeName: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GoodsBean {
|
||||||
|
id: string;
|
||||||
|
goodsId: string;
|
||||||
|
goodsName: string;
|
||||||
|
goodsCode: string,
|
||||||
|
allow_integral: number;
|
||||||
|
available: number;
|
||||||
|
back_factory: number;
|
||||||
|
brand_id: string;
|
||||||
|
brand_name: string;
|
||||||
|
code: string;
|
||||||
|
company_id: string;
|
||||||
|
cost_price: number;
|
||||||
|
create_time: string;
|
||||||
|
creator_id: string;
|
||||||
|
discount: number;
|
||||||
|
images: string;
|
||||||
|
market_time: string;
|
||||||
|
material_id: string;
|
||||||
|
material_name: string;
|
||||||
|
name: string;
|
||||||
|
price: number;
|
||||||
|
send_num: number;
|
||||||
|
priceExt: number;
|
||||||
|
price_ext: number;
|
||||||
|
payPrice: number;
|
||||||
|
profile: string;
|
||||||
|
remark: string;
|
||||||
|
remark1: string;
|
||||||
|
remark2: string;
|
||||||
|
remark3: string;
|
||||||
|
remark4: string;
|
||||||
|
season_id: string;
|
||||||
|
season_name: string;
|
||||||
|
status: number;
|
||||||
|
stocks: StockBean[],
|
||||||
|
store_id: string;
|
||||||
|
suplier_id: string;
|
||||||
|
suplier_name: string;
|
||||||
|
type_id: string;
|
||||||
|
type_name: string;
|
||||||
|
update_time: string;
|
||||||
|
years_id: string;
|
||||||
|
years_name: string;
|
||||||
|
|
||||||
|
/*extra params*/
|
||||||
|
goodsNum: number;
|
||||||
|
salePrice: number;
|
||||||
|
originPrice: number;
|
||||||
|
consumePrice: number;
|
||||||
|
stockStock: StockBean
|
||||||
|
checkedStock: StockBean;
|
||||||
|
checked: boolean | false;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface StockBean {
|
||||||
|
colorId: string;
|
||||||
|
colorName: string;
|
||||||
|
existingNumber: number;
|
||||||
|
sizeId: string;
|
||||||
|
sizeName: string;
|
||||||
|
stockId: string;
|
||||||
|
images: string,
|
||||||
|
count: number;
|
||||||
|
}
|
||||||
25
src/api/groupbuy/index.ts
Normal file
25
src/api/groupbuy/index.ts
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
import { get, post } from '@/utils/request';
|
||||||
|
import { GroupBuyBean, RecordBean } from '@/api/groupbuy/types';
|
||||||
|
import { GoodsBean } from '@/api/goods/types';
|
||||||
|
|
||||||
|
export const getGroupBuyList = (data: {
|
||||||
|
pageNum: number,
|
||||||
|
pageSize: number,
|
||||||
|
obj: {
|
||||||
|
timeStatus: number,
|
||||||
|
}
|
||||||
|
}) => post({ url: '/group/coupons/wx_query', data });
|
||||||
|
|
||||||
|
export const getGroupBuyDetail = (
|
||||||
|
id: string) => get<GroupBuyBean>({ url: `wechat/coupons/group/get/${id}` });
|
||||||
|
|
||||||
|
export const getGroupBuyRecordList = (groupId: string, pageNum: number, pageSize: number) => post<RecordBean[]>({
|
||||||
|
url: `wechat/coupons/group/order/list?groupId=${groupId}&pageNum=${pageNum}&pageSize=${pageSize}`
|
||||||
|
});
|
||||||
|
|
||||||
|
export const preOrder = (data: any) => post<GoodsBean>({ url: 'wechat/coupons/group/pre_v2', data });
|
||||||
|
|
||||||
|
export const progress = (data: any) => post<any>({ url: 'wechat/coupons/group/pay/progress', data });
|
||||||
|
|
||||||
|
export const pay = (data: any) => post<any>({ url: 'wechat/coupons/group/pay', data });
|
||||||
|
|
||||||
37
src/api/groupbuy/types.ts
Normal file
37
src/api/groupbuy/types.ts
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
import { GoodsBean } from '@/api/goods/types';
|
||||||
|
import { CouponBean } from '@/api/user/types';
|
||||||
|
|
||||||
|
export interface GroupBuyBean {
|
||||||
|
companyId: string;
|
||||||
|
content: string;
|
||||||
|
couponsList: CouponBean[];
|
||||||
|
createTime: string;
|
||||||
|
creatorId: string;
|
||||||
|
creatorName: string;
|
||||||
|
endDate: string;
|
||||||
|
fake: number;
|
||||||
|
goods: GoodsBean;
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
offsetPrice: number;
|
||||||
|
payPrice: number;
|
||||||
|
goodsPrice: number;
|
||||||
|
periodDay: number;
|
||||||
|
price: number;
|
||||||
|
publicNum: number;
|
||||||
|
sendNum: number;
|
||||||
|
startDate: string;
|
||||||
|
status: number;
|
||||||
|
threshold: number;
|
||||||
|
title: string;
|
||||||
|
totalNum: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RecordBean {
|
||||||
|
bizId: string;
|
||||||
|
createTime: string;
|
||||||
|
goodsCode: string;
|
||||||
|
goodsNum: number;
|
||||||
|
groupId: string;
|
||||||
|
memberImage: string;
|
||||||
|
}
|
||||||
26
src/api/order/index.ts
Normal file
26
src/api/order/index.ts
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
import { get, post } from '@/utils';
|
||||||
|
|
||||||
|
enum URL {
|
||||||
|
orderCreate = '/sales/wx_order_create',
|
||||||
|
orderList = '/sales/wx_query',
|
||||||
|
orderDetail = '/order/wx_get/',
|
||||||
|
paymentList = '/sales/payment/',
|
||||||
|
overPayment = '/sales/over_payment'
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export const orderCreate = (data: any) => post({ url: URL.orderCreate, data });
|
||||||
|
|
||||||
|
export const getOrderList = (data: {
|
||||||
|
pageNum: number,
|
||||||
|
pageSize: number,
|
||||||
|
obj: {
|
||||||
|
payStatus: number
|
||||||
|
}
|
||||||
|
}) => post({ url: URL.orderList, data });
|
||||||
|
|
||||||
|
export const getOrderDetail = (orderId: string) => get<any>({ url: URL.orderDetail + `${orderId}` });
|
||||||
|
|
||||||
|
export const getPaymentList = (orderId: string) => get<any>({ url: URL.paymentList + `${orderId}` });
|
||||||
|
export const overPayment = (data: any) => post({ url: URL.overPayment, data });
|
||||||
|
|
||||||
78
src/api/order/types.ts
Normal file
78
src/api/order/types.ts
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
import { GoodsBean, StockBean } from '@/api/goods/types';
|
||||||
|
|
||||||
|
export interface OrderBean {
|
||||||
|
allowIntegral: boolean;
|
||||||
|
bizId: string;
|
||||||
|
classify: number;
|
||||||
|
address: any,
|
||||||
|
companyId: string;
|
||||||
|
consignTime: string;
|
||||||
|
consumerId: string;
|
||||||
|
consumerName: string;
|
||||||
|
coupon: string;
|
||||||
|
couponIds: string;
|
||||||
|
couponsStatus: number;
|
||||||
|
createTime: string;
|
||||||
|
creatorId: number;
|
||||||
|
creatorName: string;
|
||||||
|
device: string;
|
||||||
|
discount: number;
|
||||||
|
discountPrice: number;
|
||||||
|
finishTime: string;
|
||||||
|
freePrice: number;
|
||||||
|
goodsNum: number;
|
||||||
|
id: string;
|
||||||
|
integral: number;
|
||||||
|
itemNum: number;
|
||||||
|
marketingPrice: number;
|
||||||
|
marketingText: string;
|
||||||
|
modifierIds: string;
|
||||||
|
needPaid: number;
|
||||||
|
ogList: any[];
|
||||||
|
orderGoods: GoodsBean[];
|
||||||
|
changeStockNum: number;
|
||||||
|
consumePrice: number;
|
||||||
|
discountOriginPrice: number;
|
||||||
|
goodsCode: string;
|
||||||
|
goodsId: string;
|
||||||
|
goodsName: string;
|
||||||
|
goodsPriceModify: string;
|
||||||
|
goodsTypeName: string;
|
||||||
|
images: string;
|
||||||
|
offset: string;
|
||||||
|
orderId: string;
|
||||||
|
orderNo: string;
|
||||||
|
originPrice: number;
|
||||||
|
originStockNum: number;
|
||||||
|
priceModify: [];
|
||||||
|
produceIntegral: number;
|
||||||
|
salePrice: number;
|
||||||
|
stockId: string;
|
||||||
|
stockStock: StockBean[];
|
||||||
|
payStatus: number;//状态 1.未支付 2.已支付
|
||||||
|
payTypeIds: string;
|
||||||
|
printed: string;
|
||||||
|
produceIntegralNumber: number;
|
||||||
|
profit: string;
|
||||||
|
reducePrice: number;
|
||||||
|
relatedId: string;
|
||||||
|
remark: string;
|
||||||
|
replacementOrder: string;
|
||||||
|
saleNum: number;
|
||||||
|
salers: [];
|
||||||
|
status: number;
|
||||||
|
storeId: string;
|
||||||
|
storeName: string;
|
||||||
|
storeOrder: string;
|
||||||
|
totalPrice: number;
|
||||||
|
transactionPrice: number;
|
||||||
|
type: number;
|
||||||
|
typeName: string;
|
||||||
|
updateTime: string;
|
||||||
|
updated: boolean;
|
||||||
|
useGold: number;
|
||||||
|
wholePrice: number;
|
||||||
|
|
||||||
|
//extra field
|
||||||
|
countdown: number;
|
||||||
|
}
|
||||||
@@ -1,18 +1,78 @@
|
|||||||
/**
|
/**
|
||||||
* 用户信息相关接口
|
* 用户信息相关接口
|
||||||
*/
|
*/
|
||||||
import type { LoginByCodeParams, LoginParams, LoginResult } from './types';
|
import type { CouponBean, LoginParams, LoginResult, RegisterParams, TerminalBean } from './types';
|
||||||
import { get, post } from '@/utils/request';
|
import { get, post } from '@/utils/request';
|
||||||
import type { UserState } from '@/store/modules/user/types';
|
import { UserBean } from '@/store/modules/user/types';
|
||||||
|
|
||||||
enum URL {
|
enum URL {
|
||||||
login = '/user/login',
|
// login = '/member/login',
|
||||||
loginByCode = '/user/loginByCode',
|
login = '/wc/wechat/LoginByMa',
|
||||||
|
loginByCode = '/wc/wechat/LoginByMaCode',
|
||||||
|
register = '/wc/wechat/register',
|
||||||
|
telephone = '/wc/wechat/telephone',
|
||||||
|
uploadAvatar = '/wc/wechat/uploadImage',
|
||||||
logout = '/user/logout',
|
logout = '/user/logout',
|
||||||
profile = '/user/profile',
|
// profile = '/user/profile',
|
||||||
|
profile = 'wc/wechat/member_detail',
|
||||||
|
updateProfile = '/member/wx_update',
|
||||||
|
|
||||||
|
// wc/wechat/member_detail
|
||||||
|
addressList = '/ext/addr/list',
|
||||||
|
addressDetail = '/ext/addr/find',
|
||||||
|
addressCreate = '/ext/addr/create',
|
||||||
|
addressUpdate = '/ext/addr/update',
|
||||||
|
addressDelete = '/ext/addr/delete',
|
||||||
|
dynamicCode = '/member/dynccode',
|
||||||
|
rechargeList = '/ext/recharge/rule_config',
|
||||||
|
preRecharge = '/memberIncoming/wx_incoming_pre',
|
||||||
|
recharge = '/memberIncoming/wx_save',
|
||||||
|
rechargeVerify = '/memberIncoming/wx_paid',
|
||||||
|
couponList = '/wechat/coupons/coupons/pageList',
|
||||||
|
integralList = '/ext/member/integral_query',
|
||||||
|
tradeList = '/memberIncoming/wx_balance_records',
|
||||||
|
terminal = 'wechat/coupons/terminal?companyId=',
|
||||||
|
cardLink = '/wc/wechat/get_card_url',
|
||||||
|
registerCoupon = '/couponsStrategy/wx_register_coupon'
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getUserProfile = () => get<UserState>({ url: URL.profile });
|
export const getUserProfile = () => get<UserBean>({ url: URL.profile });
|
||||||
|
|
||||||
|
export const updateProfile = (data: any) => post<any>({ url: URL.updateProfile, data });
|
||||||
|
|
||||||
export const login = (data: LoginParams) => post<LoginResult>({ url: URL.login, data });
|
export const login = (data: LoginParams) => post<LoginResult>({ url: URL.login, data });
|
||||||
export const loginByCode = (data: LoginByCodeParams) => post<any>({ url: URL.loginByCode, data });
|
export const loginByCode = (code: string, companyId: string) => post<any>({ url: URL.loginByCode + `?code=${code}` });
|
||||||
|
|
||||||
|
export const getTelephone = (data: any) => post<any>({ url: URL.telephone, data });
|
||||||
|
|
||||||
|
export const register = (data: RegisterParams) => post<LoginResult>({ url: URL.register, data });
|
||||||
|
|
||||||
export const logout = () => post<any>({ url: URL.logout });
|
export const logout = () => post<any>({ url: URL.logout });
|
||||||
|
|
||||||
|
export const getAddressList = () => get<any>({ url: URL.addressList });
|
||||||
|
export const getAddressDetail = (id: string) => get<any>({ url: URL.addressDetail + `?id=${id}` });
|
||||||
|
|
||||||
|
export const addressCreate = (data: any) => post<any>({ url: URL.addressCreate, data });
|
||||||
|
export const addressUpdate = (data: any) => post<any>({ url: URL.addressUpdate, data });
|
||||||
|
export const addressDelete = (id: string) => post<any>({ url: URL.addressDelete + `?addrid=${id}` });
|
||||||
|
|
||||||
|
export const getDynamicCode = () => post<any>({ url: URL.dynamicCode });
|
||||||
|
|
||||||
|
export const getRechargeList = () => get<any>({ url: URL.rechargeList });
|
||||||
|
|
||||||
|
export const preRecharge = (data: any) => post({ url: URL.preRecharge, data });
|
||||||
|
|
||||||
|
export const recharge = (data: any) => post({ url: URL.recharge, data });
|
||||||
|
export const rechargeVerify = (data: any) => post({ url: URL.rechargeVerify, data });
|
||||||
|
|
||||||
|
export const getCouponList = (data: any) => post<CouponBean[]>({ url: URL.couponList, data });
|
||||||
|
|
||||||
|
export const getIntegralList = (data: any) => get({ url: URL.integralList, data });
|
||||||
|
|
||||||
|
export const getTerminal = (companyId: string) => get<TerminalBean>({ url: URL.terminal + companyId });
|
||||||
|
|
||||||
|
export const getTradeList = (data: any) => post<any>({ url: URL.tradeList, data });
|
||||||
|
|
||||||
|
export const getCardLink = () => get<string>({ url: URL.cardLink });
|
||||||
|
|
||||||
|
export const getRegisterCoupon = () => get<any>({ url: URL.registerCoupon });
|
||||||
|
|||||||
@@ -1,6 +1,24 @@
|
|||||||
|
import { UserBean } from '@/store/modules/user/types';
|
||||||
|
|
||||||
export interface LoginParams {
|
export interface LoginParams {
|
||||||
phone: string;
|
// phone: string;
|
||||||
code: string;
|
code: string;
|
||||||
|
userInfo: any;
|
||||||
|
storeId: string;
|
||||||
|
// referrerUserId: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RegisterParams {
|
||||||
|
unionId: string,
|
||||||
|
openId: string,
|
||||||
|
maOpenId: string,
|
||||||
|
image: string,
|
||||||
|
nickName: string,
|
||||||
|
telephone: string,
|
||||||
|
birthday: string,
|
||||||
|
companyId: string,
|
||||||
|
creatorId: string,
|
||||||
|
gender: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface LoginByCodeParams {
|
export interface LoginByCodeParams {
|
||||||
@@ -8,8 +26,95 @@ export interface LoginByCodeParams {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface LoginResult {
|
export interface LoginResult {
|
||||||
|
|
||||||
|
sessionKey: string;
|
||||||
|
user: UserBean;
|
||||||
|
userInfo: any;
|
||||||
token: string;
|
token: string;
|
||||||
user_id: number;
|
maOpenId: string;
|
||||||
user_name: string;
|
}
|
||||||
avatar: string;
|
|
||||||
|
export interface IntegralBean {
|
||||||
|
id: string;
|
||||||
|
createtime: string;
|
||||||
|
exsitvalue: number;
|
||||||
|
remark: string;
|
||||||
|
type: number;
|
||||||
|
value: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface CouponBean {
|
||||||
|
companyId: string;
|
||||||
|
couponsId: string;
|
||||||
|
createTime: string;
|
||||||
|
creatorId: number;
|
||||||
|
creatorName: string;
|
||||||
|
dayType: number;
|
||||||
|
endTime: string;
|
||||||
|
id: string;
|
||||||
|
images: string;
|
||||||
|
imcomingId: string;
|
||||||
|
memberId: string;
|
||||||
|
memberName: string;
|
||||||
|
name: string;
|
||||||
|
notice: number;
|
||||||
|
offsetPrice: number;
|
||||||
|
orderId: null;
|
||||||
|
periodDay: number;
|
||||||
|
reduce: number;
|
||||||
|
remark: string;
|
||||||
|
startTime: string;
|
||||||
|
status: number;
|
||||||
|
strategyType: string;
|
||||||
|
telephone: string;
|
||||||
|
threshold: number;
|
||||||
|
type: number;
|
||||||
|
userTime: string;
|
||||||
|
|
||||||
|
checked: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TerminalBean {
|
||||||
|
applyId: string;
|
||||||
|
bindId: string;
|
||||||
|
bindName: string;
|
||||||
|
bindStatus: number;
|
||||||
|
company: string;
|
||||||
|
companyId: string;
|
||||||
|
companyName: string;
|
||||||
|
contact: string;
|
||||||
|
createTime: string;
|
||||||
|
creatorId: string;
|
||||||
|
creatorName: string;
|
||||||
|
deviceRole: string;
|
||||||
|
employee: string;
|
||||||
|
expireTime: string;
|
||||||
|
id: string;
|
||||||
|
managerPermission: string;
|
||||||
|
name: string;
|
||||||
|
permission: {
|
||||||
|
deletablePer: boolean,
|
||||||
|
profitPer: boolean,
|
||||||
|
exportTypes: any[],
|
||||||
|
checkoutPer: boolean,
|
||||||
|
showPhoneNumber: boolean,
|
||||||
|
storePer: any[]
|
||||||
|
};
|
||||||
|
checkoutPer: boolean;
|
||||||
|
deletablePer: boolean;
|
||||||
|
exportPer: boolean;
|
||||||
|
exportTypes: any[];
|
||||||
|
profitPer: boolean;
|
||||||
|
showPhoneNumber: boolean;
|
||||||
|
storePer: any[];
|
||||||
|
signDate: string;
|
||||||
|
status: number;
|
||||||
|
store: string;
|
||||||
|
storeId: string;
|
||||||
|
storeName: string;
|
||||||
|
storeOrder: number;
|
||||||
|
terminalKey: string;
|
||||||
|
terminalSn: string;
|
||||||
|
token: string;
|
||||||
|
type: number;
|
||||||
}
|
}
|
||||||
|
|||||||
109
src/components/company-dialog.vue
Normal file
109
src/components/company-dialog.vue
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
<template>
|
||||||
|
<uni-popup ref='popupRef' type='bottom' :mask-click='false' @touchmove.stop.prevent=''>
|
||||||
|
<view class='content'>
|
||||||
|
<text class='title'>切换门店</text>
|
||||||
|
<scroll-view scroll-y style='max-height: 600rpx;padding: 15rpx'>
|
||||||
|
<view class='store-item' v-for='(item, index) in companyList' :key='index' @click='() => {
|
||||||
|
handleClick(index)
|
||||||
|
}'>
|
||||||
|
<view class='c-flex-row'>
|
||||||
|
<text>{{ item?.companyName || '' }}</text>
|
||||||
|
<image v-if='index===currentIndex' src='/static/images/ic_checkmark_red.png' />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</scroll-view>
|
||||||
|
<view class='close-btn primary-button' @click='close'>
|
||||||
|
<text>取消</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</uni-popup>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang='ts' setup>
|
||||||
|
const props = defineProps({
|
||||||
|
companyList: {
|
||||||
|
type: Array,
|
||||||
|
default: () => []
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const popupRef = ref();
|
||||||
|
const currentIndex = ref(0);
|
||||||
|
let callback: Function;
|
||||||
|
|
||||||
|
const show = (companyId: string, fn: Function) => {
|
||||||
|
if(companyId) {
|
||||||
|
currentIndex.value = props.companyList.findIndex(item => item.id === companyId);
|
||||||
|
}
|
||||||
|
callback = fn;
|
||||||
|
popupRef.value.open();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleClick = (index: number) => {
|
||||||
|
currentIndex.value = index;
|
||||||
|
callback(index);
|
||||||
|
close();
|
||||||
|
};
|
||||||
|
|
||||||
|
const close = () => {
|
||||||
|
popupRef.value.close();
|
||||||
|
};
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
show, close
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang='scss' scoped>
|
||||||
|
.content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
background: #FFFFFF;
|
||||||
|
border-radius: 20rpx 20rpx 0 0;
|
||||||
|
padding: 20rpx 30rpx 30rpx 30rpx;
|
||||||
|
|
||||||
|
.title {
|
||||||
|
display: flex;
|
||||||
|
align-self: center;
|
||||||
|
font-size: 30rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
padding: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.store-item {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
font-size: 35rpx;
|
||||||
|
color: #333333;
|
||||||
|
//padding: 20rpx 20rpx;
|
||||||
|
|
||||||
|
|
||||||
|
.c-flex-row {
|
||||||
|
text {
|
||||||
|
display: flex;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
image {
|
||||||
|
width: 30rpx;
|
||||||
|
height: 30rpx;
|
||||||
|
margin-right: 30rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.store-item:after {
|
||||||
|
content: '';
|
||||||
|
background: #F5F5F5;
|
||||||
|
height: 0.5rpx;
|
||||||
|
width: 100%;
|
||||||
|
margin: 25rpx 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.close-btn {
|
||||||
|
background: #F5F5F5;
|
||||||
|
color: #333333;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
74
src/components/official-account-dialog.vue
Normal file
74
src/components/official-account-dialog.vue
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
<template>
|
||||||
|
|
||||||
|
<uni-popup type='bottom' ref='popupRef'>
|
||||||
|
<view class='popup-content c-flex-column'>
|
||||||
|
<view class='c-flex-row'>
|
||||||
|
<text>关注公众号</text>
|
||||||
|
<image :src='assetsUrl("ic_close.png")' @click.stop='close' />
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<image class='qrcode' :src='assetsUrl("official_account_qrcode.png")' show-menu-by-longpress />
|
||||||
|
<text class='tips'>长按关注会员中心公众号\n
|
||||||
|
获得更多优惠和服务信息
|
||||||
|
</text>
|
||||||
|
</view>
|
||||||
|
</uni-popup>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang='ts' setup>
|
||||||
|
import { assetsUrl } from '@/utils/assets';
|
||||||
|
|
||||||
|
const popupRef = ref();
|
||||||
|
const show = () => {
|
||||||
|
popupRef.value.open();
|
||||||
|
};
|
||||||
|
|
||||||
|
const close = () => {
|
||||||
|
popupRef.value.close();
|
||||||
|
};
|
||||||
|
|
||||||
|
defineExpose({ show });
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang='scss' scoped>
|
||||||
|
.popup-content {
|
||||||
|
background: #FFFFFF;
|
||||||
|
border-radius: 20rpx 20rpx 0 0;
|
||||||
|
padding: 38rpx;
|
||||||
|
align-items: center;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
view:nth-of-type(1) {
|
||||||
|
image {
|
||||||
|
width: 35rpx;
|
||||||
|
height: 35rpx;
|
||||||
|
align-self: flex-end;
|
||||||
|
position: absolute;
|
||||||
|
right: 38rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
text {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #333333;
|
||||||
|
align-self: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.qrcode {
|
||||||
|
width: 377rpx;
|
||||||
|
height: 377rpx;
|
||||||
|
margin-top: 50rpx;
|
||||||
|
align-self: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tips {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #333333;
|
||||||
|
align-self: center;
|
||||||
|
margin-top: 10rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
92
src/components/payment-button.vue
Normal file
92
src/components/payment-button.vue
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
<template>
|
||||||
|
<sqb-pay style='width: 100%;' @bindnavigateTo='navigateTo'
|
||||||
|
:return_url='payParams.return_url'
|
||||||
|
:total_amount='payParams.total_amount'
|
||||||
|
:terminal_sn='payParams.terminal_sn'
|
||||||
|
:client_sn='payParams.client_sn'
|
||||||
|
:subject='payParams.subject'
|
||||||
|
:subject_img='payParams.subject_img '
|
||||||
|
:merchant_name='payParams.merchant_name'
|
||||||
|
:notify_url='payParams.notify_url'
|
||||||
|
:sign='payParams.sign'>
|
||||||
|
|
||||||
|
<slot name='button'></slot>
|
||||||
|
</sqb-pay>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang='ts' setup>
|
||||||
|
import { PropType } from 'vue';
|
||||||
|
import { parseParameter, sortASCII } from '@/utils';
|
||||||
|
import { hexMD5 } from '@/utils/common/md5';
|
||||||
|
import { useUserStore } from '@/store';
|
||||||
|
|
||||||
|
const userState = useUserStore();
|
||||||
|
const { terminalInfo } = storeToRefs(userState);
|
||||||
|
|
||||||
|
export interface SqbPayParams {
|
||||||
|
return_url: string;
|
||||||
|
total_amount: number;
|
||||||
|
client_sn: string;
|
||||||
|
terminal_sn: string;
|
||||||
|
subject: string;
|
||||||
|
subject_img: string;
|
||||||
|
merchant_name: string;
|
||||||
|
notify_url: string;
|
||||||
|
sign: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
payParams: {
|
||||||
|
type: Object as PropType<SqbPayParams>,
|
||||||
|
default: () => {
|
||||||
|
return {
|
||||||
|
return_url: '',
|
||||||
|
total_amount: 0,
|
||||||
|
client_sn: '',
|
||||||
|
terminal_sn: '',
|
||||||
|
subject: '',
|
||||||
|
subject_img: '',
|
||||||
|
merchant_name: '',
|
||||||
|
notify_url: '',
|
||||||
|
sign: ''
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
watch(() => props.payParams, (newValue, prevValue) => {
|
||||||
|
if(newValue) {
|
||||||
|
let signParams = buildSignParams.value;
|
||||||
|
const signStr = parseParameter(signParams) + '&key=' + terminalInfo.value.terminalKey;
|
||||||
|
props.payParams.sign = hexMD5(signStr).toUpperCase();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const buildSignParams = computed(() => {
|
||||||
|
return sortASCII({
|
||||||
|
client_sn: props.payParams.client_sn || '',
|
||||||
|
return_url: props.payParams.return_url,
|
||||||
|
total_amount: Number((props.payParams.total_amount * 100).toFixed(2)),
|
||||||
|
terminal_sn: props.payParams.terminal_sn,
|
||||||
|
subject: props.payParams.subject,
|
||||||
|
subject_img: props.payParams.subject_img,
|
||||||
|
merchant_name: props.payParams.merchant_name,
|
||||||
|
notify_url: props.payParams.notify_url
|
||||||
|
}, true);
|
||||||
|
});
|
||||||
|
|
||||||
|
const navigateTo = (e: any) => {
|
||||||
|
console.log('--------------_>>>>>>navigateTo ', e);
|
||||||
|
uni.redirectTo({
|
||||||
|
url: e.detail.url,
|
||||||
|
fail(e) {
|
||||||
|
uni.showToast({
|
||||||
|
title: '支付失败'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang='scss' scoped>
|
||||||
|
</style>
|
||||||
114
src/components/payment-dialog.vue
Normal file
114
src/components/payment-dialog.vue
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
<template>
|
||||||
|
<uni-popup type='bottom' ref='popupRef' :mask-click='false' @touchmove.stop.prevent=''>
|
||||||
|
<view class='popup-content c-flex-column'>
|
||||||
|
<view class='c-flex-row'>
|
||||||
|
<image :src='assetsUrl("ic_back.png")' @click.stop='close()' />
|
||||||
|
<text>选择支付方式</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class='c-flex-row' @click.stop='doPayment(PAYMENT_TYPE_WECHAT)'>
|
||||||
|
<image :src='assetsUrl("ic_wechat.png")' />
|
||||||
|
<text>微信支付</text>
|
||||||
|
<image :src='assetsUrl(currentType===PAYMENT_TYPE_WECHAT?"ic_checkbox_active.png":"ic_checkbox_normal.png")' />
|
||||||
|
</view>
|
||||||
|
<view class='divider' style='margin: 40rpx 0' />
|
||||||
|
<view class='c-flex-row' @click.stop='doPayment(PAYMENT_TYPE_BALANCE)'>
|
||||||
|
<image :src='assetsUrl("ic_balance.png")' />
|
||||||
|
<text>余额(剩余¥{{ userInfo.balance }})</text>
|
||||||
|
<image :src='assetsUrl(currentType===PAYMENT_TYPE_BALANCE?"ic_checkbox_active.png":"ic_checkbox_normal.png")' />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</uni-popup>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang='ts' setup>
|
||||||
|
import { assetsUrl } from '@/utils/assets';
|
||||||
|
import { useUserStore } from '@/store';
|
||||||
|
|
||||||
|
const popupRef = ref();
|
||||||
|
const PAYMENT_TYPE_WECHAT = ref(0);
|
||||||
|
const PAYMENT_TYPE_BALANCE = ref(1);
|
||||||
|
const currentType = ref(PAYMENT_TYPE_WECHAT.value);
|
||||||
|
|
||||||
|
const userStore = useUserStore();
|
||||||
|
|
||||||
|
const { userInfo } = storeToRefs(userStore);
|
||||||
|
|
||||||
|
const emits = defineEmits(['change']);
|
||||||
|
const show = () => {
|
||||||
|
popupRef.value.open();
|
||||||
|
};
|
||||||
|
|
||||||
|
const close = () => {
|
||||||
|
popupRef.value.close();
|
||||||
|
};
|
||||||
|
|
||||||
|
const doPayment = (paymentType: number) => {
|
||||||
|
emits('change', paymentType);
|
||||||
|
currentType.value = paymentType;
|
||||||
|
switch (paymentType) {
|
||||||
|
case PAYMENT_TYPE_WECHAT.value:
|
||||||
|
console.log('PAYMENT_TYPE_WECHAT');
|
||||||
|
break;
|
||||||
|
case PAYMENT_TYPE_BALANCE.value:
|
||||||
|
console.log('PAYMENT_TYPE_BALANCE');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
close();
|
||||||
|
};
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
show
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang='scss' scoped>
|
||||||
|
.popup-content {
|
||||||
|
background: #FFFFFF;
|
||||||
|
border-radius: 20rpx 20rpx 0 0;
|
||||||
|
padding: 38rpx 45rpx 140rpx 45rpx;
|
||||||
|
|
||||||
|
view:nth-of-type(1) {
|
||||||
|
display: flex;
|
||||||
|
margin-bottom: 70rpx;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
image {
|
||||||
|
width: 35rpx;
|
||||||
|
height: 35rpx;
|
||||||
|
align-self: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
text {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #333333;
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
view:nth-of-type(n+2) {
|
||||||
|
image:nth-of-type(1) {
|
||||||
|
width: 47rpx;
|
||||||
|
height: 47rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
text {
|
||||||
|
align-self: center;
|
||||||
|
flex: 1;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #333333;
|
||||||
|
margin-left: 23rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
image:nth-of-type(2) {
|
||||||
|
width: 35rpx;
|
||||||
|
height: 35rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
296
src/components/sku-dialog.vue
Normal file
296
src/components/sku-dialog.vue
Normal file
@@ -0,0 +1,296 @@
|
|||||||
|
<template>
|
||||||
|
<uni-popup ref='popupRef' type='bottom' :mask-click='false' @touchmove.stop.prevent=''>
|
||||||
|
<view class='content'>
|
||||||
|
<view class='c-flex-row' style='align-items: flex-start'>
|
||||||
|
<image class='goods-image' :src='goodsDetailBean?.images||defaultImage' />
|
||||||
|
<view class='c-flex-column' style='flex: 1;display: inline-grid'>
|
||||||
|
<text class='goods-name'>{{ goodsDetailBean?.name || '未知' }}</text>
|
||||||
|
<text class='goods-price'>
|
||||||
|
{{ flashPrice > 0 ? `${flashPrice}` : `${goodsDetailBean?.consumePrice || 0}` || 0
|
||||||
|
}}
|
||||||
|
</text>
|
||||||
|
</view>
|
||||||
|
<image class='close-image' :src='assetsUrl("ic_close.png")' @click.stop='close' />
|
||||||
|
</view>
|
||||||
|
<view class='sku-view c-flex-column'>
|
||||||
|
<view class='sku-title'>颜色</view>
|
||||||
|
<view class='sku-color-list c-flex-row'>
|
||||||
|
<view class='sku-item'
|
||||||
|
:class='{"sku-item-active":currentColorIndex==index}'
|
||||||
|
v-for='(item, index) in skuColorList' :key='index'
|
||||||
|
@click='colorChange(index)'>
|
||||||
|
<text>{{ item||'均色' }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class='sku-title' style='margin-top: 43rpx'>尺码</view>
|
||||||
|
<view class='sku-color-list c-flex-row'>
|
||||||
|
<view class='sku-item'
|
||||||
|
v-if='(skuSizeList?.length||0)>0'
|
||||||
|
:class='{"sku-item-active":currentSizeIndex==index,"sku-item-disabled":item.existingNumber<=0}'
|
||||||
|
v-for='(item, index) in skuSizeList' :key='index'
|
||||||
|
@click='sizeChange(index)'>
|
||||||
|
<text>{{ item.sizeName||'均码' }}</text>
|
||||||
|
</view>
|
||||||
|
<text v-else style='color: #999999;font-size: 30rpx'>暂无库存</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class='c-flex-row' style='margin-top: 52rpx'>
|
||||||
|
<text class='sku-title'>购买数量</text>
|
||||||
|
<view class='count-change-view c-flex-row'>
|
||||||
|
<view class='count-image' @click.stop='countChange(false)'>
|
||||||
|
<image :src='assetsUrl("ic_reduce.png")' />
|
||||||
|
</view>
|
||||||
|
<text>{{ goodsCount }}</text>
|
||||||
|
<view class='count-image' @click.stop='countChange(true)'>
|
||||||
|
<image :src='assetsUrl("ic_plus.png")' />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<button class='primary-button' :plain='currentSizeIndex<0' :disabled='currentSizeIndex<0' @click='confirm'>
|
||||||
|
确定
|
||||||
|
</button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</uni-popup>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang='ts' setup>
|
||||||
|
import { PropType, ref } from 'vue';
|
||||||
|
import { assetsUrl, defaultImage } from '@/utils/assets';
|
||||||
|
import { showToast } from '@/utils';
|
||||||
|
import { getGoodsDetail } from '@/api/goods';
|
||||||
|
import { GoodsBean, StockBean } from '@/api/goods/types';
|
||||||
|
import { useUserStore } from '@/store';
|
||||||
|
|
||||||
|
const userStore = useUserStore();
|
||||||
|
const { userInfo } = storeToRefs(userStore);
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
flashPrice: {
|
||||||
|
type: Number,
|
||||||
|
default: -1
|
||||||
|
},
|
||||||
|
exists: Object as PropType<StockBean>
|
||||||
|
});
|
||||||
|
const popupRef = ref();
|
||||||
|
const goodsDetailBean = ref<GoodsBean>();
|
||||||
|
const skuColorList = ref<string[]>([]);
|
||||||
|
const currentColorIndex = ref(0);
|
||||||
|
const currentSizeIndex = ref(-1);
|
||||||
|
const goodsCount = ref(1);
|
||||||
|
let callback: Function;
|
||||||
|
|
||||||
|
const show = async (goodsId: string, fn: Function) => {
|
||||||
|
callback = fn;
|
||||||
|
|
||||||
|
goodsDetailBean.value = await getGoodsDetail(goodsId);
|
||||||
|
goodsDetailBean.value.price = userStore.getRealGoodsPrice(goodsDetailBean.value?.price,goodsDetailBean.value?.priceExt)
|
||||||
|
goodsDetailBean.value.consumePrice = Number((goodsDetailBean.value?.price * userInfo?.value.userDiscount).toFixed(2));
|
||||||
|
|
||||||
|
if((goodsDetailBean.value?.stocks?.length || 0) <= 0) {
|
||||||
|
showToast('暂无库存');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
goodsDetailBean.value?.stocks?.map((res: { colorName: string }) => res.colorName).forEach((colorName: string) => {
|
||||||
|
if(!skuColorList.value.includes(colorName)) {
|
||||||
|
skuColorList.value.push(colorName);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
popupRef.value.open();
|
||||||
|
}, 200);
|
||||||
|
|
||||||
|
if(props.exists) {
|
||||||
|
const colorIndex = skuColorList.value?.findIndex(res => res === props.exists?.colorName);
|
||||||
|
const sizeIndex = skuSizeList.value?.findIndex(res => res.sizeId === props.exists?.sizeId);
|
||||||
|
|
||||||
|
colorChange(colorIndex || 0);
|
||||||
|
sizeChange(sizeIndex || 0);
|
||||||
|
goodsCount.value = props.exists?.count;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(skuSizeList) {
|
||||||
|
// skuSizeList.value![0].existingNumber = 2;
|
||||||
|
// skuSizeList.value![2].existingNumber = 2;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const skuSizeList = computed(() => {
|
||||||
|
const currentColorName = skuColorList.value[currentColorIndex.value];
|
||||||
|
let sizeList = goodsDetailBean.value?.stocks?.filter((res: { colorName: string }) => {
|
||||||
|
return res.colorName === currentColorName;
|
||||||
|
});
|
||||||
|
currentSizeIndex.value = sizeList?.findIndex(res => res.existingNumber > 0) || 0;
|
||||||
|
return sizeList;
|
||||||
|
});
|
||||||
|
|
||||||
|
const colorChange = (index: number) => {
|
||||||
|
currentColorIndex.value = index;
|
||||||
|
};
|
||||||
|
|
||||||
|
const sizeChange = (index: number) => {
|
||||||
|
if((skuSizeList.value![index].existingNumber || 0) <= 0) {
|
||||||
|
showToast('库存不足');
|
||||||
|
} else {
|
||||||
|
currentSizeIndex.value = index;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const countChange = (isPlus: boolean) => {
|
||||||
|
if(isPlus) {
|
||||||
|
goodsCount.value += 1;
|
||||||
|
} else {
|
||||||
|
if(goodsCount.value > 1) {
|
||||||
|
goodsCount.value -= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const confirm = () => {
|
||||||
|
if(callback instanceof Function) {
|
||||||
|
callback({
|
||||||
|
...goodsDetailBean.value,
|
||||||
|
checkedStock: {
|
||||||
|
...skuSizeList.value![currentSizeIndex.value],
|
||||||
|
count: goodsCount.value
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
popupRef.value.close();
|
||||||
|
};
|
||||||
|
|
||||||
|
const close = () => {
|
||||||
|
popupRef.value.close();
|
||||||
|
};
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
show
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang='scss' scoped>
|
||||||
|
.content {
|
||||||
|
background: #FFFFFF;
|
||||||
|
border-radius: 20rpx 20rpx 0 0;
|
||||||
|
padding: 23rpx 30rpx 78rpx 30rpx;
|
||||||
|
|
||||||
|
.goods-image {
|
||||||
|
width: 186rpx;
|
||||||
|
height: 186rpx;
|
||||||
|
border-radius: 10rpx;
|
||||||
|
margin-top: -50rpx;
|
||||||
|
margin-right: 18rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.goods-name {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 32rpx;
|
||||||
|
color: #333333;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.goods-price {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 40rpx;
|
||||||
|
color: #D95554;
|
||||||
|
margin-top: 40rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.goods-price:before {
|
||||||
|
content: '¥';
|
||||||
|
font-size: 28rpx;
|
||||||
|
margin-right: 2rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.close-image {
|
||||||
|
width: 45rpx;
|
||||||
|
height: 45rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sku-view {
|
||||||
|
margin-top: 30rpx;
|
||||||
|
|
||||||
|
.sku-title {
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #333333;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sku-color-list {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns:repeat(4, 1fr);
|
||||||
|
margin-top: 20rpx;
|
||||||
|
gap: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sku-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
background: #F2F2F2;
|
||||||
|
border-radius: 26rpx;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 26rpx;
|
||||||
|
color: #333333;
|
||||||
|
padding: 7rpx 32rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sku-item-active {
|
||||||
|
@extend .sku-item;
|
||||||
|
background: #FFF1F1;
|
||||||
|
color: #D95554;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sku-item-disabled {
|
||||||
|
@extend .sku-item;
|
||||||
|
background: #F2F2F2;
|
||||||
|
color: #BEBEBE;
|
||||||
|
}
|
||||||
|
|
||||||
|
.count-change-view {
|
||||||
|
.count-image {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 54rpx;
|
||||||
|
height: 54rpx;
|
||||||
|
background: #FBFBFB;
|
||||||
|
|
||||||
|
image {
|
||||||
|
width: 15rpx;
|
||||||
|
height: 2rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.count-image:nth-of-type(2) image {
|
||||||
|
width: 17rpx;
|
||||||
|
height: 17rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
text {
|
||||||
|
display: flex;
|
||||||
|
width: 54rpx;
|
||||||
|
height: 54rpx;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #333333;
|
||||||
|
background: #F2F2F2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.primary-button {
|
||||||
|
width: 100%;
|
||||||
|
margin-top: 50rpx;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
88
src/components/tabbar/tabbar.vue
Normal file
88
src/components/tabbar/tabbar.vue
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
<template>
|
||||||
|
<view class='tab-container'>
|
||||||
|
<view v-for='(item, index) in titles' :key='index' class='tab-item' :class='{"tab-item-active":currentIndex==index}'
|
||||||
|
:style='{"flex": fixed?1:0,
|
||||||
|
"min-width":fixed?"150rpx":"auto",
|
||||||
|
"color": currentIndex==index?itemActiveColor:itemColor}'
|
||||||
|
@click.stop='onChange(index)'>
|
||||||
|
<text>{{ item }}</text>
|
||||||
|
<view class='indicator' v-if='currentIndex==index' :style='{
|
||||||
|
background: indicatorColor,
|
||||||
|
}' />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang='ts' setup>
|
||||||
|
const props = defineProps({
|
||||||
|
titles: {
|
||||||
|
type: Object as PropType<string[]>,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
|
||||||
|
index: {
|
||||||
|
type: Number,
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
|
|
||||||
|
fixed: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
}
|
||||||
|
,
|
||||||
|
itemColor: {
|
||||||
|
type: String,
|
||||||
|
default: '#666666'
|
||||||
|
},
|
||||||
|
itemActiveColor: {
|
||||||
|
type: String,
|
||||||
|
default: '#333333'
|
||||||
|
},
|
||||||
|
indicatorColor: {
|
||||||
|
type: String,
|
||||||
|
default: '#333333'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const emits = defineEmits(['change']);
|
||||||
|
const currentIndex = ref<number>(0);
|
||||||
|
|
||||||
|
watch(() => props.index, (newVal) => {
|
||||||
|
currentIndex.value = newVal;
|
||||||
|
});
|
||||||
|
|
||||||
|
const onChange = (index: number) => {
|
||||||
|
currentIndex.value = index;
|
||||||
|
emits('change', index);
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang='scss' scoped>
|
||||||
|
.tab-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
background: #FFFFFF;
|
||||||
|
height: 85rpx;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.tab-item {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 30rpx;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-item-active {
|
||||||
|
@extend .tab-item;
|
||||||
|
font-size: 34rpx;
|
||||||
|
|
||||||
|
.indicator {
|
||||||
|
width: 68rpx;
|
||||||
|
height: 6rpx;
|
||||||
|
margin-top: 13rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -2,44 +2,40 @@
|
|||||||
"name": "SUKE-MP",
|
"name": "SUKE-MP",
|
||||||
"appid": "",
|
"appid": "",
|
||||||
"description": "",
|
"description": "",
|
||||||
"versionName": "1.0.0",
|
"versionName": "3.0.2",
|
||||||
"versionCode": "100",
|
"versionCode": "302",
|
||||||
"transformPx": false,
|
"transformPx": false,
|
||||||
/* 5+App特有相关 */
|
"app-plus": {
|
||||||
"app-plus":
|
|
||||||
{
|
|
||||||
"usingComponents": true,
|
"usingComponents": true,
|
||||||
"nvueStyleCompiler": "uni-app",
|
"nvueStyleCompiler": "uni-app",
|
||||||
"compilerVersion": 3,
|
"compilerVersion": 3,
|
||||||
"splashscreen":
|
"splashscreen": {
|
||||||
{
|
|
||||||
"alwaysShowBeforeRender": true,
|
"alwaysShowBeforeRender": true,
|
||||||
"waiting": true,
|
"waiting": true,
|
||||||
"autoclose": true,
|
"autoclose": true,
|
||||||
"delay": 0
|
"delay": 0
|
||||||
},
|
},
|
||||||
/* 模块配置 */
|
|
||||||
"modules": {}
|
"modules": {}
|
||||||
},
|
},
|
||||||
/* 小程序特有相关 */
|
"mp-weixin": {
|
||||||
"mp-weixin":
|
|
||||||
{
|
|
||||||
"appid": "wx67a750d0ceed4d88",
|
"appid": "wx67a750d0ceed4d88",
|
||||||
"setting":
|
"setting": {
|
||||||
{
|
|
||||||
"urlCheck": false
|
"urlCheck": false
|
||||||
},
|
},
|
||||||
"usingComponents": true
|
"usingComponents": true,
|
||||||
|
"plugins": {
|
||||||
|
"sqb-pay": {
|
||||||
|
"version": "1.3.0",
|
||||||
|
"provider": "wx55540b288c5ce319"
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"uniStatistics":
|
"uniStatistics": {
|
||||||
{
|
|
||||||
"enable": false
|
"enable": false
|
||||||
},
|
},
|
||||||
"vueVersion": "3",
|
"vueVersion": "3",
|
||||||
"h5":
|
"h5": {
|
||||||
{
|
"router": {
|
||||||
"router":
|
|
||||||
{
|
|
||||||
"mode": "hash",
|
"mode": "hash",
|
||||||
"base": "/uniapp-vue3-template/"
|
"base": "/uniapp-vue3-template/"
|
||||||
}
|
}
|
||||||
|
|||||||
180
src/pages.json
180
src/pages.json
@@ -11,13 +11,14 @@
|
|||||||
{
|
{
|
||||||
"path": "pages/home/index",
|
"path": "pages/home/index",
|
||||||
"style": {
|
"style": {
|
||||||
"navigationBarTitleText": "首页"
|
"navigationBarTitleText": "首页",
|
||||||
|
"navigationStyle": "custom"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "pages/qrcode/index",
|
"path": "pages/qrcode/index",
|
||||||
"style": {
|
"style": {
|
||||||
"navigationBarTitleText": "支付码"
|
"navigationBarTitleText": "会员支付码"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -31,6 +32,18 @@
|
|||||||
"style": {
|
"style": {
|
||||||
"navigationBarTitleText": "我的"
|
"navigationBarTitleText": "我的"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/index/index",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "肃客会员"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/coupons/ticketsBuy/ticketsBuy",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "团购详情"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"subPackages": [
|
"subPackages": [
|
||||||
@@ -41,9 +54,166 @@
|
|||||||
"path": "login/index",
|
"path": "login/index",
|
||||||
"navigationStyle": "custom"
|
"navigationStyle": "custom"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "register/index",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "用户注册"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "register/reward",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "注册有礼"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "groupbuy/index",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "团购秒杀",
|
||||||
|
"backgroundColor": "#F32B2B",
|
||||||
|
"backgroundColorTop": "#F32B2B",
|
||||||
|
"navigationBarTextStyle": "white",
|
||||||
|
"navigationBarBackgroundColor": "#F32B2B"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "groupbuy/detail",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "商品团购券"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "groupbuy/order-confirm",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "确认订单",
|
||||||
|
"usingComponents": {
|
||||||
|
"sqb-pay": "plugin://sqb-pay/sqb-pay"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "webview/index",
|
"path": "webview/index",
|
||||||
"navigationBarTitleText": "网页"
|
"navigationBarTitleText": "网页"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "payresult/index",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "支付结果"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"root": "pages/home/subs",
|
||||||
|
"pages": [
|
||||||
|
{
|
||||||
|
"path": "group/join",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "扫码加群"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"root": "pages/mall/subs",
|
||||||
|
"pages": [
|
||||||
|
{
|
||||||
|
"path": "goods/detail",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "商品详情"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "order/order-confirm",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "确认订单",
|
||||||
|
"usingComponents": {
|
||||||
|
"sqb-pay": "plugin://sqb-pay/sqb-pay"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "shoppingcart/index",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "购物车"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "search/index",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "搜索"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"root": "pages/mine/subs",
|
||||||
|
"pages": [
|
||||||
|
{
|
||||||
|
"path": "profile/index",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "会员信息"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "integral/index",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "我的积分"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "recharge/index",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "会员充值",
|
||||||
|
"usingComponents": {
|
||||||
|
"sqb-pay": "plugin://sqb-pay/sqb-pay"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "coupon/index",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "优惠券"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "order/index",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "我的订单"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "order/detail",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "订单详情",
|
||||||
|
"usingComponents": {
|
||||||
|
"sqb-pay": "plugin://sqb-pay/sqb-pay"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "trade/index",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "消费记录"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "address/index",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "收货地址"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "address/create",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "新增收货地址"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "contact/index",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "联系商家"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -90,8 +260,8 @@
|
|||||||
},
|
},
|
||||||
"globalStyle": {
|
"globalStyle": {
|
||||||
"navigationBarTextStyle": "black",
|
"navigationBarTextStyle": "black",
|
||||||
"navigationBarTitleText": "uni-app",
|
"navigationBarTitleText": "VIP顾客中心",
|
||||||
"navigationBarBackgroundColor": "#F8F8F8",
|
"navigationBarBackgroundColor": "#FFFFFF",
|
||||||
"backgroundColor": "#F8F8F8"
|
"backgroundColor": "#F7F7F7"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
120
src/pages/common/groupbuy/components/coupon-item.vue
Normal file
120
src/pages/common/groupbuy/components/coupon-item.vue
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
<template>
|
||||||
|
<view class='coupon-content'>
|
||||||
|
<image :src='assetsUrl("bg_coupon.png")' />
|
||||||
|
<view class='left-content accent-text-color' :class='{"left-content-disabled": item.status==1}'>
|
||||||
|
<text>{{ item.reduce }}</text>
|
||||||
|
<text>满{{ item.threshold }}元可用</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class='right-content accent-text-color' :class='{"right-content-disabled": item.status==1}'>
|
||||||
|
<text>{{ item?.name }}</text>
|
||||||
|
<text>有效期至{{ dayjs(item.startTime).format('YYYY-MM-DD') }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang='ts' setup>
|
||||||
|
|
||||||
|
import { assetsUrl } from '@/utils/assets';
|
||||||
|
import dayjs from 'dayjs';
|
||||||
|
|
||||||
|
defineProps({
|
||||||
|
item: Object
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang='scss' scoped>
|
||||||
|
.coupon-content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
height: 200rpx;
|
||||||
|
position: relative;
|
||||||
|
margin: 10rpx 30rpx 20rpx 30rpx;
|
||||||
|
|
||||||
|
image {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
.left-content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
position: relative;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding-left: 50rpx;
|
||||||
|
|
||||||
|
text:nth-of-type(1) {
|
||||||
|
font-size: 55rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
text:nth-of-type(1):after {
|
||||||
|
content: '元';
|
||||||
|
font-size: 24rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
text:nth-of-type(2) {
|
||||||
|
font-size: 26rpx;
|
||||||
|
font-weight: 400;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.left-content-disabled {
|
||||||
|
@extend .left-content;
|
||||||
|
color: #C2C2C2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.right-content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
position: relative;
|
||||||
|
flex: 1;
|
||||||
|
justify-content: center;
|
||||||
|
margin-left: 60rpx;
|
||||||
|
|
||||||
|
text:nth-of-type(1) {
|
||||||
|
font-size: 30rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
text:nth-of-type(2) {
|
||||||
|
font-size: 26rpx;
|
||||||
|
margin-top: 20rpx;
|
||||||
|
color: #333333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-text {
|
||||||
|
display: flex;
|
||||||
|
width: 146rpx;
|
||||||
|
height: 55rpx;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
border-radius: 28rpx;
|
||||||
|
border: #F32B2B solid 2rpx;
|
||||||
|
font-size: 28rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #F32B2B;
|
||||||
|
position: absolute;
|
||||||
|
right: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-text-disabled {
|
||||||
|
@extend .btn-text;
|
||||||
|
color: #C2C2C2;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.right-content-disabled {
|
||||||
|
@extend .right-content;
|
||||||
|
color: #C2C2C2;
|
||||||
|
|
||||||
|
text:nth-of-type(2) {
|
||||||
|
color: #C2C2C2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
692
src/pages/common/groupbuy/detail.vue
Normal file
692
src/pages/common/groupbuy/detail.vue
Normal file
@@ -0,0 +1,692 @@
|
|||||||
|
<template>
|
||||||
|
<view class='content'>
|
||||||
|
<view class='swiper-container'>
|
||||||
|
<swiper class='swiper' :interval='1500' :duration='1000' @change='swiperChange'>
|
||||||
|
<swiper-item v-for='(item,index) in bannerList' :key='index'>
|
||||||
|
<image :src='item||defaultImage' mode='aspectFill' />
|
||||||
|
</swiper-item>
|
||||||
|
</swiper>
|
||||||
|
<view class='indicator'>
|
||||||
|
<text>{{ swiperIndex + 1 }}</text>
|
||||||
|
<text>/{{ bannerList.length }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class='countdown c-flex-row'>
|
||||||
|
<view class='super-second-kill'>
|
||||||
|
超级\n秒杀
|
||||||
|
</view>
|
||||||
|
<view class='price c-flex-column' style='flex: 1'>
|
||||||
|
<text>{{ groupBuyBean?.payPrice || 0 }}</text>
|
||||||
|
<text>¥{{ groupBuyBean?.price || 0 }}</text>
|
||||||
|
</view>
|
||||||
|
<view v-if='isPending()' class='countdown-time c-flex-column'>
|
||||||
|
<view class='c-flex-row'>{{ countdownTime?.days || 0 }}天
|
||||||
|
<text class='time'>{{ countdownTime?.hours || '00' }}</text>
|
||||||
|
:
|
||||||
|
<text class='time'>{{ countdownTime?.minutes || '00' }}</text>
|
||||||
|
:
|
||||||
|
<text class='time'>{{ countdownTime?.seconds || '00' }}</text>
|
||||||
|
</view>
|
||||||
|
<text>距离活动结束仅剩</text>
|
||||||
|
</view>
|
||||||
|
<view v-else>
|
||||||
|
<text style='font-size: 35rpx;color: #FFFFFF'>
|
||||||
|
{{ isNotStated() ? '未开始' : '已结束' }}
|
||||||
|
</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class='goods-info-view c-flex-column'>
|
||||||
|
<view class='c-flex-row'>
|
||||||
|
<text class='goods-price accent-text-color'>{{ groupBuyBean?.payPrice || 0 }}</text>
|
||||||
|
<text>销量{{ groupBuyBean?.totalNum || 0 }}</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class='c-flex-row'>
|
||||||
|
<text style='flex: 1'>{{ groupBuyBean?.name || '未知' }}</text>
|
||||||
|
<view class='share-button c-flex-column'>
|
||||||
|
<image :src='assetsUrl("ic_share.png")'></image>
|
||||||
|
<button class='btn' plain open-type='share'>分享</button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class='goods-sku-view c-flex-column'>
|
||||||
|
<view class='c-flex-row' @click.stop='showSkuDialog'>
|
||||||
|
<text>选择</text>
|
||||||
|
<text>规格 颜色/尺码</text>
|
||||||
|
<image :src='assetsUrl("ic_arrow_right_gray.png")' />
|
||||||
|
<text>共{{ getStockColorCount }}种颜色可选</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class='recommend-view c-flex-column' v-if='(recommendList?.length||0)>0'>
|
||||||
|
<text>浏览此商品的客户还浏览了</text>
|
||||||
|
<scroll-view scroll-x>
|
||||||
|
<view style='display: inline-block' v-for='(item, index) in recommendList'
|
||||||
|
:key='index'>
|
||||||
|
<view class='recommend-item c-flex-column'>
|
||||||
|
<image :src='item.images||defaultImage' />
|
||||||
|
<text>{{ item.goodsName || '未知' }}</text>
|
||||||
|
<text class='goods-price'>{{ item.price }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</scroll-view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 商品详情图片 -->
|
||||||
|
<view class='card-view image-container' v-if='groupBuyBean?.content'>
|
||||||
|
<text class='card-view-title'>商品详情</text>
|
||||||
|
<image
|
||||||
|
v-for='(item,index) in JSON.parse(groupBuyBean?.content).filter((a: any) => a.type === 2).map((b: any) => b.images)'
|
||||||
|
:src='item' mode='aspectFill' :key='index' />
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 商品详情 -->
|
||||||
|
<view class='card-view goods-container'>
|
||||||
|
<view class='c-flex-row'>
|
||||||
|
<image :src='groupBuyBean?.goods?.images' />
|
||||||
|
<view class='c-flex-column'>
|
||||||
|
<text class='goods-name'>{{ groupBuyBean?.goods?.name }}</text>
|
||||||
|
<text style='color: #a6a6a6'>精选</text>
|
||||||
|
<view class='tag-view c-flex-row'>
|
||||||
|
<text>团长推荐</text>
|
||||||
|
<text>今日必买</text>
|
||||||
|
</view>
|
||||||
|
<text style='color: #a6a6a6'>不参与会员折扣</text>
|
||||||
|
<text style='color: #F32B2B'>¥{{ groupBuyBean?.goods?.payPrice }}</text>
|
||||||
|
<text class='bought_count'>已团{{ groupBuyBean?.sendNum }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 商品详情优惠券 -->
|
||||||
|
<view class='card-view coupon-container'>
|
||||||
|
<text class='card-view-title'>赠送优惠券</text>
|
||||||
|
<view class='c-flex-column'>
|
||||||
|
<coupon-item v-for='(item,index) in groupBuyBean?.couponsList' :key='index' :item='item' />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 商品详情跟团记录 -->
|
||||||
|
<view class='card-view record-container'>
|
||||||
|
<text class='card-view-title'>跟团记录</text>
|
||||||
|
<u-list :list='recordList' :border='false' @scrolltolower='loadMore'>
|
||||||
|
<u-list-item v-for='(item,index) in recordList' :key='index'>
|
||||||
|
<view class='item-view c-flex-row'>
|
||||||
|
<image :src='item.memberImage' />
|
||||||
|
<view class='c-flex-column' style='flex: 1'>
|
||||||
|
<text>{{ item.goodsCode }}</text>
|
||||||
|
<text>{{ item.createTime }}</text>
|
||||||
|
</view>
|
||||||
|
<text>+{{ item.goodsNum }}</text>
|
||||||
|
</view>
|
||||||
|
</u-list-item>
|
||||||
|
<u-loadmore status='loading' />
|
||||||
|
</u-list>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class='bottom-view c-flex-row'>
|
||||||
|
<button v-if='isPending()' class='place-order-button' @click.stop='placeOrder'>跟团购买</button>
|
||||||
|
<button v-else class='place-order-button-disable' :plain='true' :disabled='true'>
|
||||||
|
{{ isNotStated() ? '即将开始' : '已结束' }}
|
||||||
|
</button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<sku-dialog ref='skuDialogRef' :flash-price='Number(groupBuyBean?.payPrice) || 0' />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang='ts' setup>
|
||||||
|
import { assetsUrl, defaultImage } from '@/utils/assets';
|
||||||
|
import dayjs from 'dayjs';
|
||||||
|
import { formatTimeWithZeroPad, goPath, isLogin } from '@/utils';
|
||||||
|
import SkuDialog from '@/components/sku-dialog.vue';
|
||||||
|
import CouponItem from './components/coupon-item.vue';
|
||||||
|
|
||||||
|
import { getGroupBuyDetail, getGroupBuyRecordList, preOrder } from '@/api/groupbuy';
|
||||||
|
import { getGoodsList } from '@/api/goods';
|
||||||
|
import { GoodsBean } from '@/api/goods/types';
|
||||||
|
import { useUserStore } from '@/store';
|
||||||
|
import { GroupBuyBean, RecordBean } from '@/api/groupbuy/types';
|
||||||
|
|
||||||
|
const userStore = useUserStore();
|
||||||
|
const { userInfo } = storeToRefs(userStore);
|
||||||
|
|
||||||
|
const skuDialogRef = ref();
|
||||||
|
const groupBuyBean = ref<GroupBuyBean>();
|
||||||
|
const recommendList = ref<GoodsBean[]>();
|
||||||
|
|
||||||
|
const bannerList = ref([]);
|
||||||
|
const swiperIndex = ref(0);
|
||||||
|
|
||||||
|
let interval: number;
|
||||||
|
const countdownTime = ref<{
|
||||||
|
days: string,
|
||||||
|
hours: string,
|
||||||
|
minutes: string,
|
||||||
|
seconds: string
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const recordList = ref<RecordBean[]>([]);
|
||||||
|
const currentPageNum = ref(1);
|
||||||
|
|
||||||
|
onLoad(async (e: any) => {
|
||||||
|
if(isLogin()) {
|
||||||
|
await uni.showLoading();
|
||||||
|
groupBuyBean.value = await getGroupBuyDetail(e.id);
|
||||||
|
// setCompanyId('1512403904150138881');
|
||||||
|
// groupBuyBean.value = await getGroupBuyDetail('1740922051118063618');
|
||||||
|
if(groupBuyBean.value) {
|
||||||
|
groupBuyBean.value.goods.price = groupBuyBean.value.price;
|
||||||
|
bannerList.value = JSON.parse(groupBuyBean.value.content).filter((item: any) => item.type === 2).map((item: any) => item.images);
|
||||||
|
countdown();
|
||||||
|
await fetchRecommendList();
|
||||||
|
await fetchBuyRecordList();
|
||||||
|
}
|
||||||
|
uni.hideLoading();
|
||||||
|
} else {
|
||||||
|
goPath('/pages/common/login/index');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
onUnload(() => {
|
||||||
|
if(interval) {
|
||||||
|
clearInterval(interval);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
onShareAppMessage((e) => {
|
||||||
|
return {
|
||||||
|
title: groupBuyBean.value?.goods?.name || 'VIP顾客中心',
|
||||||
|
path: `/pages/common/groupbuy/detail?id=${groupBuyBean.value?.id}&companyId=${getApp().globalData?.companyId}&storeId=${getApp().globalData?.storeId}`
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const isNotStated = () => {
|
||||||
|
return dayjs(groupBuyBean.value?.startDate).isAfter(Date.now());
|
||||||
|
};
|
||||||
|
|
||||||
|
const isPending = () => {
|
||||||
|
return dayjs(groupBuyBean.value?.startDate).isBefore(Date.now()) && dayjs(groupBuyBean.value?.endDate).isAfter(Date.now());
|
||||||
|
};
|
||||||
|
|
||||||
|
const isEnded = () => {
|
||||||
|
return dayjs(groupBuyBean.value?.endDate).isBefore(Date.now());
|
||||||
|
};
|
||||||
|
|
||||||
|
const getStockColorCount = computed(() => {
|
||||||
|
const list = Array.from(new Set(groupBuyBean.value?.goods?.stocks?.map(item => item.colorName)))
|
||||||
|
.map(colorName => groupBuyBean.value?.goods?.stocks?.find(item => item.colorName === colorName)!);
|
||||||
|
return list.length;
|
||||||
|
});
|
||||||
|
|
||||||
|
const fetchRecommendList = async () => {
|
||||||
|
const { rows } = await getGoodsList({
|
||||||
|
page: {
|
||||||
|
page: 1,
|
||||||
|
pageSize: 20,
|
||||||
|
bean: {
|
||||||
|
keyword: '',
|
||||||
|
typeIds: []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
recommendList.value = rows;
|
||||||
|
};
|
||||||
|
|
||||||
|
const fetchBuyRecordList = async (refresh: boolean = true) => {
|
||||||
|
if(!refresh) {
|
||||||
|
currentPageNum.value += 1;
|
||||||
|
}
|
||||||
|
const { list } = await getGroupBuyRecordList(groupBuyBean?.value?.id || '', currentPageNum.value, 20);
|
||||||
|
recordList.value = recordList.value.concat(list);
|
||||||
|
};
|
||||||
|
|
||||||
|
const loadMore = () => {
|
||||||
|
fetchBuyRecordList(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const swiperChange = (e: any) => {
|
||||||
|
swiperIndex.value = e.detail.current;
|
||||||
|
};
|
||||||
|
|
||||||
|
const countdown = () => {
|
||||||
|
interval = setInterval(() => {
|
||||||
|
if(groupBuyBean.value?.endDate) {
|
||||||
|
let now = new Date();
|
||||||
|
let end = dayjs(groupBuyBean.value?.endDate).toDate().getTime();
|
||||||
|
let remaining = Math.floor((end - now.getTime()) / 1000);
|
||||||
|
if(remaining > 0) {
|
||||||
|
countdownTime.value = {
|
||||||
|
days: formatTimeWithZeroPad(Math.floor(remaining / 60 / 60 / 24)),
|
||||||
|
hours: formatTimeWithZeroPad(Math.floor(remaining / 60 / 60 % 24)),
|
||||||
|
minutes: formatTimeWithZeroPad(Math.floor(remaining / 60 % 60)),
|
||||||
|
seconds: formatTimeWithZeroPad(Math.floor(remaining % 60))
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
clearInterval(interval);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, 1000);
|
||||||
|
};
|
||||||
|
|
||||||
|
const showSkuDialog = (fn: Function) => {
|
||||||
|
skuDialogRef.value.show(groupBuyBean?.value?.goods?.goodsId, fn);
|
||||||
|
};
|
||||||
|
|
||||||
|
const placeOrder = async () => {
|
||||||
|
|
||||||
|
async function create(bean: GoodsBean) {
|
||||||
|
const params = {
|
||||||
|
'colorId': bean.checkedStock.colorId,
|
||||||
|
'sizeId': bean.checkedStock.sizeId,
|
||||||
|
'goodsId': groupBuyBean?.value?.goods.goodsId,
|
||||||
|
'groupId': groupBuyBean?.value?.id,
|
||||||
|
'memberId': userInfo.value.id,
|
||||||
|
'shareId': '123456'
|
||||||
|
};
|
||||||
|
|
||||||
|
const result = await preOrder(params);
|
||||||
|
goPath(`/pages/common/groupbuy/order-confirm?orderBean=${encodeURIComponent(JSON.stringify(result))}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
showSkuDialog((e: GoodsBean) => {
|
||||||
|
create(e);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang='scss' scoped>
|
||||||
|
.content {
|
||||||
|
padding-bottom: 200rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.swiper-container {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.swiper {
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
height: 750rpx;
|
||||||
|
|
||||||
|
image {
|
||||||
|
width: 100%;
|
||||||
|
height: 750rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.indicator {
|
||||||
|
background: rgba(1, 1, 1, 0.5);
|
||||||
|
border-radius: 45rpx;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #FFFFFF;
|
||||||
|
position: absolute;
|
||||||
|
right: 20rpx;
|
||||||
|
bottom: 20rpx;
|
||||||
|
padding: 5rpx 25rpx;
|
||||||
|
|
||||||
|
text:nth-of-type(1) {
|
||||||
|
font-size: 30rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
text:nth-of-type(2) {
|
||||||
|
font-size: 24rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.countdown {
|
||||||
|
display: flex;
|
||||||
|
height: 130rpx;
|
||||||
|
position: relative;
|
||||||
|
padding: 15rpx 30rpx;
|
||||||
|
background-image: url('https://img.lakeapp.cn/wx/images/bg_groupbuy_countdown.png');
|
||||||
|
background-size: 100% 100%;
|
||||||
|
|
||||||
|
.super-second-kill {
|
||||||
|
display: flex;
|
||||||
|
width: 100rpx;
|
||||||
|
height: 100rpx;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
background: rgba(255, 255, 255, 0.3);
|
||||||
|
border-radius: 20rpx;
|
||||||
|
border: 1rpx solid #FFFFFF;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 36rpx;
|
||||||
|
text-align: center;
|
||||||
|
color: #FFFFFF;
|
||||||
|
margin-right: 23rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.price {
|
||||||
|
color: #FFFFFF;
|
||||||
|
|
||||||
|
text:nth-of-type(1) {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 55rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
text:nth-of-type(1):before {
|
||||||
|
content: '¥ ';
|
||||||
|
font-size: 30rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
text:nth-of-type(2) {
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 30rpx;
|
||||||
|
text-decoration-line: line-through;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.countdown-time {
|
||||||
|
color: #FFFFFF;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
view:nth-of-type(1) {
|
||||||
|
margin-bottom: 20rpx;
|
||||||
|
align-self: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
.time {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 40rpx;
|
||||||
|
height: 40rpx;
|
||||||
|
margin-left: 12rpx;
|
||||||
|
margin-right: 12rpx;
|
||||||
|
background: #FFFFFF;
|
||||||
|
border-radius: 7rpx;
|
||||||
|
color: #F32B2B;
|
||||||
|
}
|
||||||
|
|
||||||
|
.time:nth-of-type(1) {
|
||||||
|
margin-left: 18rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.time:nth-of-type(3) {
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
text:not(.time):nth-of-type(1) {
|
||||||
|
align-self: flex-end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.goods-info-view {
|
||||||
|
background: #FFFFFF;
|
||||||
|
padding: 20rpx 30rpx;
|
||||||
|
|
||||||
|
view:nth-of-type(1) {
|
||||||
|
text:nth-of-type(1) {
|
||||||
|
display: flex;
|
||||||
|
font-size: 40rpx;
|
||||||
|
text-align: center;
|
||||||
|
align-items: flex-end;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.goods-price:before {
|
||||||
|
content: "¥";
|
||||||
|
font-size: 30rpx;
|
||||||
|
margin-bottom: 5rpx;
|
||||||
|
margin-right: 5rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
text:nth-of-type(2) {
|
||||||
|
font-size: 26rpx;
|
||||||
|
font-weight: 400;
|
||||||
|
color: #999999;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
view:nth-of-type(2) {
|
||||||
|
text {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 32rpx;
|
||||||
|
color: #333333;
|
||||||
|
margin-right: 10rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.share-button {
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
image {
|
||||||
|
width: 36rpx;
|
||||||
|
height: 32rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
background: #00000000;
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #636566;
|
||||||
|
white-space: nowrap;
|
||||||
|
padding: 0;
|
||||||
|
border: none !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.goods-sku-view {
|
||||||
|
background: #FFFFFF;
|
||||||
|
padding: 20rpx 30rpx;
|
||||||
|
margin-top: 20rpx;
|
||||||
|
|
||||||
|
view:nth-of-type(n+1) {
|
||||||
|
position: relative;
|
||||||
|
align-items: center;
|
||||||
|
height: 80rpx;
|
||||||
|
|
||||||
|
text:nth-of-type(1) {
|
||||||
|
width: 100rpx;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #999999;
|
||||||
|
}
|
||||||
|
|
||||||
|
text:nth-of-type(2) {
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #333333;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
image {
|
||||||
|
width: 13rpx;
|
||||||
|
height: 24rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
text:nth-of-type(3) {
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #999999;
|
||||||
|
position: absolute;
|
||||||
|
top: 50rpx;
|
||||||
|
left: 100rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
view:nth-of-type(1) {
|
||||||
|
align-items: flex-start;
|
||||||
|
//padding-top: 20rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.recommend-view {
|
||||||
|
background: #FFFFFF;
|
||||||
|
padding: 20rpx 30rpx;
|
||||||
|
margin-top: 20rpx;
|
||||||
|
|
||||||
|
text {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #333333;
|
||||||
|
}
|
||||||
|
|
||||||
|
scroll-view {
|
||||||
|
width: 100%;
|
||||||
|
margin-top: 20rpx;
|
||||||
|
white-space: nowrap;
|
||||||
|
height: 300rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.recommend-item {
|
||||||
|
margin-right: 20rpx;
|
||||||
|
|
||||||
|
image {
|
||||||
|
width: 200rpx;
|
||||||
|
height: 200rpx;
|
||||||
|
border-radius: 10rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
text:nth-of-type(1) {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #333333;
|
||||||
|
margin-top: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
text:nth-of-type(2) {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #F32B2B;
|
||||||
|
}
|
||||||
|
|
||||||
|
.goods-price:before {
|
||||||
|
content: "¥";
|
||||||
|
font-size: 28rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.bottom-view {
|
||||||
|
background: #FFFFFF;
|
||||||
|
padding: 20rpx 30rpx 78rpx 30rpx;
|
||||||
|
position: fixed;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
|
||||||
|
.place-order-button {
|
||||||
|
display: flex;
|
||||||
|
flex: 1;
|
||||||
|
font-weight: bold;
|
||||||
|
width: 100%;
|
||||||
|
font-size: 30rpx;
|
||||||
|
height: 80rpx;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
background: #F32B2B;
|
||||||
|
color: #FFFFFF;
|
||||||
|
border-radius: 40rpx;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.place-order-button-disable {
|
||||||
|
@extend .place-order-button;
|
||||||
|
background: #b9b5b5;
|
||||||
|
color: #FFFFFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-view {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
background: #FFFFFF;
|
||||||
|
margin-top: 20rpx;
|
||||||
|
|
||||||
|
.card-view-title {
|
||||||
|
margin: 20rpx 30rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #333333;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-container {
|
||||||
|
image {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.goods-container {
|
||||||
|
padding: 30rpx;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
image {
|
||||||
|
width: 200rpx;
|
||||||
|
height: 200rpx;
|
||||||
|
margin-right: 15rpx;
|
||||||
|
border-radius: 8rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.c-flex-column {
|
||||||
|
justify-content: space-between;
|
||||||
|
position: relative;
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
|
text {
|
||||||
|
margin-top: 5rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.goods-name {
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #333333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tag-view {
|
||||||
|
text {
|
||||||
|
background: #fff0ee;
|
||||||
|
margin-right: 10rpx;
|
||||||
|
padding: 5rpx 10rpx;
|
||||||
|
color: #fc6e51;
|
||||||
|
border-radius: 8rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.bought_count {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
right: 0;
|
||||||
|
color: #fc6e51;
|
||||||
|
font-size: 20rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.record-container {
|
||||||
|
|
||||||
|
.item-view {
|
||||||
|
margin: 10rpx 30rpx;
|
||||||
|
|
||||||
|
image {
|
||||||
|
width: 80rpx;
|
||||||
|
height: 80rpx;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.c-flex-column {
|
||||||
|
margin: 0 15rpx;
|
||||||
|
|
||||||
|
text:nth-of-type(1) {
|
||||||
|
font-size: 20rpx;
|
||||||
|
color: #333333;
|
||||||
|
}
|
||||||
|
|
||||||
|
text:nth-of-type(2) {
|
||||||
|
font-size: 15rpx;
|
||||||
|
color: #666666;
|
||||||
|
margin-top: 10rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
text:nth-of-type(1) {
|
||||||
|
color: #F32B2B;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
208
src/pages/common/groupbuy/index.vue
Normal file
208
src/pages/common/groupbuy/index.vue
Normal file
@@ -0,0 +1,208 @@
|
|||||||
|
<template>
|
||||||
|
<view class='content'>
|
||||||
|
<view class='tab c-flex-row'>
|
||||||
|
<text class='tab-item' :class='{"tab-item-active":tabIndex==0}' @click.stop='tabIndex=0'>团购中</text>
|
||||||
|
<text class='tab-item' :class='{"tab-item-active":tabIndex==1}' @click.stop='tabIndex=1'>即将开始</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<scroll-view class='scroll-view'>
|
||||||
|
<!-- <u-list class='scroll-view' :border='false' @scrolltolower='loadMore'>-->
|
||||||
|
<!-- <u-list-item v-for='(item,index) in groupbuyList' :key='index'>-->
|
||||||
|
<view class='c-flex-column' v-for='(item,index) in groupbuyList' :key='index'>
|
||||||
|
<view class='item c-flex-row' @click.stop='goPath(`/pages/common/groupbuy/detail?id=${item.id}`)'>
|
||||||
|
<image class='goods-image' mode='aspectFill' :src='JSON.parse(item.content)[0].images||defaultImage' />
|
||||||
|
<view class='c-flex-column' style='flex: 1'>
|
||||||
|
<view class='goods-name'>{{ item.name }}</view>
|
||||||
|
<view class='middle-view c-flex-row'>
|
||||||
|
<text>原价:¥{{ item.price }}</text>
|
||||||
|
<view v-if='(item.price - item.payPrice)>0' class='decline c-flex-row'>
|
||||||
|
<image :src='assetsUrl("ic_decline.png")' />
|
||||||
|
<text>直降¥{{ (item.price - item.payPrice).toFixed(2) }}</text>
|
||||||
|
</view>
|
||||||
|
<text>{{ tabIndex == 0 ? '即将恢复' : '即将开始' }}</text>
|
||||||
|
</view>
|
||||||
|
<view class='bottom-price c-flex-row' :class='{"bottom-price-disabled":tabIndex==1}'>
|
||||||
|
<text>{{ item.payPrice }}</text>
|
||||||
|
<text>团购</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class='divider' style='margin: 0 30rpx' />
|
||||||
|
</view>
|
||||||
|
<!-- </u-list-item>-->
|
||||||
|
<!-- </u-list>-->
|
||||||
|
|
||||||
|
<u-empty v-if='groupbuyList.length === 0' text='暂无团购活动' marginTop='100' />
|
||||||
|
</scroll-view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang='ts' setup>
|
||||||
|
|
||||||
|
import { assetsUrl, defaultImage } from '@/utils/assets';
|
||||||
|
import { getGroupBuyList } from '@/api/groupbuy';
|
||||||
|
import { goPath } from '@/utils';
|
||||||
|
|
||||||
|
const tabIndex = ref(0);
|
||||||
|
const groupbuyList = ref<any[]>([]);
|
||||||
|
const currentPageNum = ref(1);
|
||||||
|
|
||||||
|
onLoad((e) => {
|
||||||
|
fetchData();
|
||||||
|
});
|
||||||
|
|
||||||
|
watch(() => tabIndex.value, () => {
|
||||||
|
fetchData();
|
||||||
|
});
|
||||||
|
|
||||||
|
const fetchData = async (refresh: boolean = true) => {
|
||||||
|
await uni.showLoading();
|
||||||
|
if(!refresh) {
|
||||||
|
currentPageNum.value += 1;
|
||||||
|
}
|
||||||
|
const { list } = await getGroupBuyList({
|
||||||
|
pageNum: currentPageNum.value,
|
||||||
|
pageSize: 100,
|
||||||
|
obj: {
|
||||||
|
timeStatus: tabIndex.value + 1
|
||||||
|
}
|
||||||
|
});
|
||||||
|
groupbuyList.value = list;
|
||||||
|
uni.hideLoading();
|
||||||
|
};
|
||||||
|
|
||||||
|
const loadMore = () => {
|
||||||
|
fetchData(false);
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang='scss' scoped>
|
||||||
|
.content {
|
||||||
|
background: #F32B2B;
|
||||||
|
padding-top: 30rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab {
|
||||||
|
height: 92rpx;
|
||||||
|
|
||||||
|
.tab-item:nth-of-type(1) {
|
||||||
|
border-radius: 30rpx 0 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-item:nth-of-type(2) {
|
||||||
|
border-radius: 0 30rpx 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-item {
|
||||||
|
display: flex;
|
||||||
|
flex: 1;
|
||||||
|
height: 100%;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #999999;
|
||||||
|
background: #F2F2F2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-item-active {
|
||||||
|
@extend .tab-item;
|
||||||
|
background: #FFFFFF;
|
||||||
|
color: #333333;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.scroll-view {
|
||||||
|
background: #FFFFFF;
|
||||||
|
height: 100vh;
|
||||||
|
|
||||||
|
.item {
|
||||||
|
padding: 20rpx 30rpx 40rpx 30rpx;
|
||||||
|
background: #FFFFFF;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.goods-image {
|
||||||
|
width: 180rpx;
|
||||||
|
height: 180rpx;
|
||||||
|
border-radius: 10rpx;
|
||||||
|
margin-right: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.goods-name {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #333333;
|
||||||
|
-webkit-line-clamp: 1;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
margin-top: 30rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.middle-view {
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-top: 16rpx;
|
||||||
|
|
||||||
|
text:nth-of-type(1) {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 26rpx;
|
||||||
|
color: #333333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.decline {
|
||||||
|
image {
|
||||||
|
width: 45rpx;
|
||||||
|
height: 45rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
text {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #AD6021;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
text:nth-of-type(2) {
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #AD6021;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.bottom-price {
|
||||||
|
display: flex;
|
||||||
|
width: 390rpx;
|
||||||
|
height: 83rpx;
|
||||||
|
margin-top: 20rpx;
|
||||||
|
align-self: flex-end;
|
||||||
|
background-image: url("https://img.lakeapp.cn/wx/images/bg_groupbuy_price.png");
|
||||||
|
background-size: 100% 100%;
|
||||||
|
color: #FFFFFF;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
text:nth-of-type(1) {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 40rpx;
|
||||||
|
color: #FFFFFF;
|
||||||
|
margin-left: 30rpx;
|
||||||
|
margin-bottom: 5rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
text:nth-of-type(1):before {
|
||||||
|
content: "秒杀价 ¥ ";
|
||||||
|
font-size: 24rpx;
|
||||||
|
margin-bottom: 5rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
text:nth-of-type(2) {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #FFFFFF;
|
||||||
|
margin-right: 50rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.bottom-price-disabled {
|
||||||
|
background-image: url("https://img.lakeapp.cn/wx/images/bg_groupbuy_price_disabled.png");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
185
src/pages/common/groupbuy/order-confirm.vue
Normal file
185
src/pages/common/groupbuy/order-confirm.vue
Normal file
@@ -0,0 +1,185 @@
|
|||||||
|
<template>
|
||||||
|
<view class='content'>
|
||||||
|
|
||||||
|
<view class='card-view'>
|
||||||
|
<template class='c-flex-row' v-for='item in orderBean?.orderGoods' :key='item.id'>
|
||||||
|
<image class='goods-image' :src='item?.images||defaultImage' />
|
||||||
|
<view class='c-flex-column' style='flex: 1'>
|
||||||
|
<text class='goods-name'>{{ item?.goodsName || item?.goodsCode }}</text>
|
||||||
|
<text class='goods-sku'>{{ item?.stockStock?.colorName }} {{ item?.stockStock?.sizeName }}</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class='c-flex-column'>
|
||||||
|
<text class='goods-num'>x{{ item?.goodsNum }}</text>
|
||||||
|
<view class='c-flex-row'>
|
||||||
|
<text class='goods-price' style='margin-right: 10rpx;text-decoration: line-through'>¥{{ item?.originPrice }}
|
||||||
|
</text>
|
||||||
|
<text class='goods-price'>¥{{ item?.consumePrice }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class='card-view'>
|
||||||
|
<text style='flex: 1'>实付</text>
|
||||||
|
<text style='color: #F32B2B'>¥{{ orderBean?.totalPrice || 0 }}</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class='bottom-view c-flex-row'>
|
||||||
|
<sqb-pay @navigateTo='navigateTo'
|
||||||
|
:return_url='buildSqbParams.return_url'
|
||||||
|
:total_amount='buildSqbParams.total_amount'
|
||||||
|
:terminal_sn='buildSqbParams.terminal_sn'
|
||||||
|
:client_sn='buildSqbParams.client_sn'
|
||||||
|
:subject='buildSqbParams.subject'
|
||||||
|
:subject_img='buildSqbParams.subject_img '
|
||||||
|
:merchant_name='buildSqbParams.merchant_name'
|
||||||
|
:notify_url='buildSqbParams.notify_url'
|
||||||
|
:sign='buildSqbParams.sign'>
|
||||||
|
<button class='confirm-button' @click='payment'>支付</button>
|
||||||
|
</sqb-pay>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang='ts' setup>
|
||||||
|
import { pay, progress } from '@/api/groupbuy';
|
||||||
|
import { OrderBean } from '@/api/order/types';
|
||||||
|
import { parseParameter, showToast, sortASCII } from '@/utils';
|
||||||
|
import { hexMD5 } from '@/utils/common/md5';
|
||||||
|
import { useUserStore } from '@/store';
|
||||||
|
import { handlePayResult } from '@/utils/order';
|
||||||
|
import { defaultImage } from '@/utils/assets';
|
||||||
|
|
||||||
|
const userState = useUserStore();
|
||||||
|
const { terminalInfo } = storeToRefs(userState);
|
||||||
|
|
||||||
|
const orderBean = ref<OrderBean>();
|
||||||
|
|
||||||
|
onLoad((e: any) => {
|
||||||
|
orderBean.value = JSON.parse(decodeURIComponent(e?.orderBean));
|
||||||
|
});
|
||||||
|
|
||||||
|
const buildSqbParams = computed(() => {
|
||||||
|
const params = sortASCII({
|
||||||
|
client_sn: orderBean.value?.id || '',
|
||||||
|
return_url: '/pages/common/payresult/index',
|
||||||
|
total_amount: Number(((orderBean.value?.totalPrice || 0) * 100).toFixed(2)),
|
||||||
|
terminal_sn: terminalInfo.value.terminalSn,
|
||||||
|
subject: '商品团购券',
|
||||||
|
subject_img: orderBean?.value?.orderGoods[0].images || '',
|
||||||
|
merchant_name: terminalInfo.value.companyName,
|
||||||
|
notify_url: 'https://www.baidu.com'
|
||||||
|
}, true);
|
||||||
|
|
||||||
|
return {
|
||||||
|
...params,
|
||||||
|
sign: hexMD5(parseParameter(params) + '&key=' + terminalInfo.value.terminalKey).toUpperCase()
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const navigateTo = (e: any) => {
|
||||||
|
handlePayResult(orderBean.value?.id, e, {
|
||||||
|
onSuccess: () => {
|
||||||
|
showToast('支付成功', {
|
||||||
|
icon: 'success',
|
||||||
|
complete: () => {
|
||||||
|
pay({
|
||||||
|
'orderId': orderBean.value?.id,
|
||||||
|
'result': 'xxx'
|
||||||
|
}).then(res => {
|
||||||
|
uni.navigateBack();
|
||||||
|
});
|
||||||
|
uni.hideLoading();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const payment = () => {
|
||||||
|
const params = {
|
||||||
|
'id': orderBean.value?.id,
|
||||||
|
'orderSn': buildSqbParams.value.client_sn,
|
||||||
|
'terminal_key': terminalInfo.value.terminalKey,
|
||||||
|
'terminal_sn': terminalInfo.value.terminalSn
|
||||||
|
};
|
||||||
|
progress(params);
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang='scss' scoped>
|
||||||
|
.content {
|
||||||
|
.card-view:nth-of-type(1) {
|
||||||
|
margin-top: 30rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-view {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
margin: 10rpx 30rpx;
|
||||||
|
background: #FFFFFF;
|
||||||
|
font-size: 35rpx;
|
||||||
|
padding: 30rpx;
|
||||||
|
|
||||||
|
.goods-image {
|
||||||
|
width: 130rpx;
|
||||||
|
height: 130rpx;
|
||||||
|
margin-right: 15rpx;
|
||||||
|
border-radius: 8rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.goods-name {
|
||||||
|
color: #333333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.goods-sku {
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #666666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.c-flex-column {
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
.goods-num {
|
||||||
|
display: flex;
|
||||||
|
font-size: 30rpx;
|
||||||
|
justify-content: flex-end;
|
||||||
|
color: #999999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.goods-price {
|
||||||
|
@extend .goods-num;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.bottom-view {
|
||||||
|
background: #FFFFFF;
|
||||||
|
padding: 20rpx 30rpx 78rpx 33rpx;
|
||||||
|
position: fixed;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
|
||||||
|
sqb-pay {
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
|
.confirm-button {
|
||||||
|
display: flex;
|
||||||
|
flex: 1;
|
||||||
|
font-weight: bold;
|
||||||
|
width: 100%;
|
||||||
|
font-size: 30rpx;
|
||||||
|
height: 80rpx;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
background: #F32B2B;
|
||||||
|
color: #FFFFFF;
|
||||||
|
border-radius: 40rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -1,167 +1,119 @@
|
|||||||
<template>
|
<template>
|
||||||
<view>
|
<view class='content'>
|
||||||
<view class="login-form-wrap">
|
<view class='title'>
|
||||||
<view class="title">
|
欢迎登录VIP顾客中心
|
||||||
欢迎登录
|
</view>
|
||||||
</view>
|
|
||||||
<input v-model="tel" class="u-border-bottom" type="number" placeholder="请输入手机号">
|
|
||||||
<view class="u-border-bottom my-40rpx flex">
|
|
||||||
<input v-model="code" class="flex-1" type="number" placeholder="请输入验证码">
|
|
||||||
<view>
|
|
||||||
<u-code ref="uCodeRef" @change="codeChange" />
|
|
||||||
<u-button :text="tips" type="success" size="mini" @click="getCode" />
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<button :style="[inputStyle]" class="login-btn" @tap="submit">
|
|
||||||
登录
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<view class="alternative">
|
<image class='logo' :src='assetsUrl("ic_logo.jpeg")' />
|
||||||
<view class="password">
|
|
||||||
密码登录
|
<button class='login-btn' @tap='wechatLogin'>
|
||||||
</view>
|
微信登录
|
||||||
<view class="issue">
|
</button>
|
||||||
遇到问题
|
<view class='hint'>
|
||||||
</view>
|
<image @click.stop='bindCheck'
|
||||||
</view>
|
:src='isAgreePrivacy?("/static/images/ic_checked_green.png"):("/static/images/ic_checked_gray.png")' />
|
||||||
</view>
|
|
||||||
<view class="login-type-wrap">
|
<text @click.stop='bindCheck'>请先阅读并同意
|
||||||
<view class="item wechat">
|
<text class='link' @click.stop='openPrivacy'>
|
||||||
<view class="icon">
|
《小程序隐私保护协议》
|
||||||
<u-icon size="35" name="weixin-fill" color="rgb(83,194,64)" />
|
</text>
|
||||||
</view>
|
并授权使用您的账号信息(如昵称、头像、收获地址)以便您统一管理
|
||||||
微信
|
|
||||||
</view>
|
|
||||||
<view class="item QQ">
|
|
||||||
<view class="icon">
|
|
||||||
<u-icon size="35" name="qq-fill" color="rgb(17,183,233)" />
|
|
||||||
</view>
|
|
||||||
QQ
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="hint">
|
|
||||||
登录代表同意
|
|
||||||
<text class="link">
|
|
||||||
用户协议、隐私政策,
|
|
||||||
</text>
|
</text>
|
||||||
并授权使用您的账号信息(如昵称、头像、收获地址)以便您统一管理
|
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang='ts'>
|
||||||
import uCode from 'uview-plus/components/u-code/u-code.vue';
|
import { useUserStore } from '@/store';
|
||||||
import { setToken } from '@/utils/auth';
|
import { assetsUrl } from '@/utils/assets';
|
||||||
|
import { showToast } from '@/utils';
|
||||||
|
|
||||||
const tel = ref<string>('18502811111');
|
const userStore = useUserStore();
|
||||||
const code = ref<string>('1234');
|
const isAgreePrivacy = ref(false);
|
||||||
const tips = ref<string>();
|
|
||||||
const uCodeRef = ref<InstanceType<typeof uCode> | null>(null);
|
|
||||||
|
|
||||||
const inputStyle = computed<CSSStyleDeclaration>(() => {
|
function wechatLogin() {
|
||||||
const style = {} as CSSStyleDeclaration;
|
if(!isAgreePrivacy.value) {
|
||||||
if (tel.value && code.value) {
|
showToast('请先阅读并同意小程序隐私保护协议');
|
||||||
style.color = '#fff';
|
return;
|
||||||
style.backgroundColor = uni.$u.color.warning;
|
|
||||||
}
|
}
|
||||||
return style;
|
|
||||||
});
|
|
||||||
|
|
||||||
function codeChange(text: string) {
|
uni.showLoading();
|
||||||
tips.value = text;
|
userStore.login().then(() => {
|
||||||
}
|
uni.hideLoading();
|
||||||
|
|
||||||
function getCode() {
|
|
||||||
if (uCodeRef.value?.canGetCode) {
|
|
||||||
// 模拟向后端请求验证码
|
|
||||||
uni.showLoading({
|
|
||||||
title: '正在获取验证码',
|
|
||||||
});
|
|
||||||
setTimeout(() => {
|
|
||||||
uni.hideLoading();
|
|
||||||
uni.$u.toast('验证码已发送');
|
|
||||||
// 通知验证码组件内部开始倒计时
|
|
||||||
uCodeRef.value?.start();
|
|
||||||
}, 1000);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
uni.$u.toast('倒计时结束后再发送');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function submit() {
|
|
||||||
if (uni.$u.test.mobile(tel.value)) {
|
|
||||||
setToken('1234567890');
|
|
||||||
uni.reLaunch({ url: '/pages/home/index' });
|
uni.reLaunch({ url: '/pages/home/index' });
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const bindCheck = () => {
|
||||||
|
isAgreePrivacy.value = !isAgreePrivacy.value;
|
||||||
|
};
|
||||||
|
|
||||||
|
const openPrivacy = () => {
|
||||||
|
wx.openPrivacyContract({
|
||||||
|
success: () => {
|
||||||
|
}, // 打开成功
|
||||||
|
fail: () => {
|
||||||
|
}, // 打开失败
|
||||||
|
complete: () => {
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang='scss' scoped>
|
||||||
.login-form-wrap {
|
.content {
|
||||||
margin: 80rpx auto 0;
|
background: #FFFFFF;
|
||||||
width: 600rpx;
|
height: 100vh;
|
||||||
|
|
||||||
.title {
|
|
||||||
margin-bottom: 100rpx;
|
|
||||||
font-size: 60rpx;
|
|
||||||
text-align: left;
|
|
||||||
font-weight: 500;
|
|
||||||
}
|
|
||||||
|
|
||||||
input {
|
|
||||||
padding-bottom: 6rpx;
|
|
||||||
margin-bottom: 10rpx;
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tips {
|
|
||||||
margin-top: 8rpx;
|
|
||||||
margin-bottom: 60rpx;
|
|
||||||
color: $u-info;
|
|
||||||
}
|
|
||||||
|
|
||||||
.login-btn {
|
|
||||||
padding: 12rpx 0;
|
|
||||||
font-size: 30rpx;
|
|
||||||
color: $u-tips-color;
|
|
||||||
background-color: rgb(253 243 208);
|
|
||||||
border: none;
|
|
||||||
|
|
||||||
&::after {
|
|
||||||
border: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.alternative {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
margin-top: 30rpx;
|
|
||||||
color: $u-tips-color;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.login-type-wrap {
|
.title {
|
||||||
display: flex;
|
font-size: 60rpx;
|
||||||
justify-content: space-between;
|
text-align: left;
|
||||||
padding: 350rpx 150rpx 150rpx;
|
font-weight: 500;
|
||||||
|
margin: 50rpx;
|
||||||
|
}
|
||||||
|
|
||||||
.item {
|
.logo {
|
||||||
display: flex;
|
width: 300rpx;
|
||||||
align-items: center;
|
height: 300rpx;
|
||||||
font-size: 28rpx;
|
align-self: center;
|
||||||
color: $u-content-color;
|
margin: 30rpx;
|
||||||
flex-direction: column;
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-btn {
|
||||||
|
padding: 12rpx 0;
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #FFFFFF;
|
||||||
|
background-color: #1cbf1e;
|
||||||
|
border: none;
|
||||||
|
border-radius: 45rpx;
|
||||||
|
margin: 100rpx 45rpx 0 45rpx;
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
border: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.hint {
|
.hint {
|
||||||
padding: 20rpx 40rpx;
|
display: inline-block;
|
||||||
font-size: 20rpx;
|
padding: 20rpx 50rpx;
|
||||||
|
font-size: 25rpx;
|
||||||
color: $u-tips-color;
|
color: $u-tips-color;
|
||||||
|
position: absolute;
|
||||||
|
align-items: center;
|
||||||
|
bottom: 50rpx;
|
||||||
|
|
||||||
.link {
|
.link {
|
||||||
color: $u-warning;
|
color: $u-warning;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
image {
|
||||||
|
width: 30rpx;
|
||||||
|
height: 30rpx;
|
||||||
|
margin-right: 10rpx;
|
||||||
|
margin-bottom: -5rpx;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
11
src/pages/common/payresult/index.vue
Normal file
11
src/pages/common/payresult/index.vue
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
<template>
|
||||||
|
<text>支付成功</text>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang='ts' setup>
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang='scss' scoped>
|
||||||
|
|
||||||
|
</style>
|
||||||
207
src/pages/common/register/index.vue
Normal file
207
src/pages/common/register/index.vue
Normal file
@@ -0,0 +1,207 @@
|
|||||||
|
<template>
|
||||||
|
<view class='content'>
|
||||||
|
<view class='c-flex-column avatar-container'>
|
||||||
|
<image class='avatar' :src='avatarUrl' />
|
||||||
|
<button class='avatar-button' open-type='chooseAvatar' @chooseavatar='chooseAvatar' />
|
||||||
|
</view>
|
||||||
|
<view class='c-flex-row' style='margin-top: 60rpx'>
|
||||||
|
<label class='row-title'>姓名</label>
|
||||||
|
<input class='row-value' type='nickname' placeholder='请输入手机号' v-model='nickName' />
|
||||||
|
</view>
|
||||||
|
<view class='divider' />
|
||||||
|
<view class='c-flex-row'>
|
||||||
|
<label class='row-title'>手机号</label>
|
||||||
|
<input class='row-value' placeholder='请输入手机号' type='text' v-model='telephone' />
|
||||||
|
<button class='primary-button authorize-button' open-type='getPhoneNumber' @getphonenumber='getPhoneNumber'>
|
||||||
|
获取手机号
|
||||||
|
</button>
|
||||||
|
</view>
|
||||||
|
<view class='divider' />
|
||||||
|
<view class='c-flex-row'>
|
||||||
|
<label class='row-title'>生日</label>
|
||||||
|
<picker mode='date' @change='changeDate'>
|
||||||
|
<text class='row-value'>{{ dayjs(birthday).format('YYYY-MM-DD') || '请选择生日' }}</text>
|
||||||
|
</picker>
|
||||||
|
</view>
|
||||||
|
<view class='divider' />
|
||||||
|
<view class='c-flex-row'>
|
||||||
|
<label class='row-title'>性别</label>
|
||||||
|
<view class='c-flex-row' @click.stop='changeGender(0)'>
|
||||||
|
<image class='gender-image'
|
||||||
|
:src='assetsUrl(gender==="男"?"ic_checkbox_active.png":"ic_checkbox_normal.png")' />
|
||||||
|
<text class='gender-text'>男</text>
|
||||||
|
</view>
|
||||||
|
<view class='c-flex-row' @click.stop='changeGender(1)'>
|
||||||
|
<image class='gender-image'
|
||||||
|
:src='assetsUrl(gender==="女"?"ic_checkbox_active.png":"ic_checkbox_normal.png")' />
|
||||||
|
<text class='gender-text'>女</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view style='height: 100rpx' />
|
||||||
|
<button class='primary-button submit-button' @click='save'>确定</button>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang='ts' setup>
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import { getTelephone } from '@/api/user';
|
||||||
|
import { useUserStore } from '@/store';
|
||||||
|
import { assetsUrl } from '@/utils/assets';
|
||||||
|
import { getRegisterStoreId, getSessionKey, showToast } from '@/utils';
|
||||||
|
import dayjs from 'dayjs';
|
||||||
|
|
||||||
|
const userStore = useUserStore();
|
||||||
|
const { userInfo } = storeToRefs(userStore);
|
||||||
|
|
||||||
|
const birthday = ref(userInfo.value.birthday || dayjs().format('YYYY-MM-DD'));
|
||||||
|
const nickName = ref(userInfo.value.nickName);
|
||||||
|
const gender = ref(userInfo.value.gender);
|
||||||
|
const telephone = ref(userInfo.value.telephone);
|
||||||
|
const avatarUrl = ref(userInfo.value.image);
|
||||||
|
|
||||||
|
const chooseAvatar = (e: any) => {
|
||||||
|
uni.showLoading();
|
||||||
|
uni.uploadFile({
|
||||||
|
url: import.meta.env.VITE_APP_BASE_API + '/wc/wechat/uploadImage',
|
||||||
|
filePath: e.detail.avatarUrl,
|
||||||
|
name: 'fileName',
|
||||||
|
header: {
|
||||||
|
'Content-Type': 'multipart/form-data'
|
||||||
|
},
|
||||||
|
success: (res: any) => {
|
||||||
|
avatarUrl.value = JSON.parse(res.data).data;
|
||||||
|
},
|
||||||
|
error: (err: any) => {
|
||||||
|
showToast('上传失败');
|
||||||
|
},
|
||||||
|
complete() {
|
||||||
|
uni.hideLoading();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const getPhoneNumber = (e: any) => {
|
||||||
|
if(e.detail.errMsg === 'getPhoneNumber:ok') {
|
||||||
|
uni.login({
|
||||||
|
success: res => {
|
||||||
|
getTelephone({
|
||||||
|
sessionKey: getSessionKey(),
|
||||||
|
code: res.code,
|
||||||
|
iv: e.detail.iv,
|
||||||
|
encryptedData: e.detail.encryptedData
|
||||||
|
}).then(response => {
|
||||||
|
if(response.phoneNumber) {
|
||||||
|
telephone.value = response.phoneNumber;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const changeDate = (e: any) => {
|
||||||
|
birthday.value = e.detail.value;
|
||||||
|
};
|
||||||
|
|
||||||
|
const changeGender = (index: number) => {
|
||||||
|
gender.value = index === 0 ? '男' : '女';
|
||||||
|
};
|
||||||
|
|
||||||
|
const save = async () => {
|
||||||
|
if(!getRegisterStoreId()) {
|
||||||
|
showToast('请从公众号消息窗口点击店名打开小程序');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await uni.showLoading();
|
||||||
|
const registerForm = {
|
||||||
|
image: avatarUrl.value,
|
||||||
|
avatarUrl: avatarUrl.value,
|
||||||
|
nickName: nickName.value,
|
||||||
|
telephone: telephone.value,
|
||||||
|
birthday: dayjs(birthday.value).isValid() ? dayjs(birthday.value).format('YYYY-MM-DD HH:mm:ss') : dayjs().format('YYYY-MM-DD HH:mm:ss'),
|
||||||
|
gender: gender.value
|
||||||
|
};
|
||||||
|
|
||||||
|
getApp().globalData?.logger.info('register params: ', registerForm);
|
||||||
|
const result = await userStore.register(registerForm);
|
||||||
|
getApp().globalData?.logger.info('register params: ', registerForm);
|
||||||
|
if(result) {
|
||||||
|
showToast('注册成功');
|
||||||
|
await uni.reLaunch({
|
||||||
|
url: '/pages/home/index'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
uni.hideLoading();
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang='scss' scoped>
|
||||||
|
.content {
|
||||||
|
display: flex;
|
||||||
|
background: white;
|
||||||
|
padding: 30rpx;
|
||||||
|
|
||||||
|
.divider {
|
||||||
|
margin: 30rpx 5rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.row-title {
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #666666;
|
||||||
|
width: 150rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.row-value {
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #333333;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar-container {
|
||||||
|
align-items: center;
|
||||||
|
margin-top: 20rpx;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.avatar {
|
||||||
|
width: 150rpx;
|
||||||
|
height: 150rpx;
|
||||||
|
border-radius: 10rpx;
|
||||||
|
background-color: #f2f2f2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar-button {
|
||||||
|
width: 150rpx;
|
||||||
|
height: 150rpx;
|
||||||
|
background-color: transparent;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.authorize-button {
|
||||||
|
width: auto;
|
||||||
|
font-size: 20rpx;
|
||||||
|
min-width: auto;
|
||||||
|
height: 50rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.gender-image {
|
||||||
|
width: 37rpx;
|
||||||
|
height: 37rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.gender-text {
|
||||||
|
width: 80rpx;
|
||||||
|
color: #333333;
|
||||||
|
font-size: 30rpx;
|
||||||
|
margin-left: 10rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.submit-button {
|
||||||
|
display: flex;
|
||||||
|
margin-top: 40rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
228
src/pages/common/register/reward.vue
Normal file
228
src/pages/common/register/reward.vue
Normal file
@@ -0,0 +1,228 @@
|
|||||||
|
<template>
|
||||||
|
<view class='content'>
|
||||||
|
<image class='bg-image' :src='assetsUrl("bg_register.png")' />
|
||||||
|
|
||||||
|
<image :src='assetsUrl("ic_register_gift_text.png")'
|
||||||
|
style='align-self: center;position: relative;width: 356rpx;height: 124rpx;margin-top: 70rpx' />
|
||||||
|
<view class='card-view'>
|
||||||
|
<view class='mobile-view c-flex-row' style='display: none'>
|
||||||
|
<image :src='assetsUrl("ic_register_mobile.png")' />
|
||||||
|
<input placeholder='请输入手机号' inputmode='number' maxLength='11' />
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class='captcha-view c-flex-row' style='display: none'>
|
||||||
|
<view class='c-flex-row'>
|
||||||
|
<image :src='assetsUrl("ic_register_captcha.png")' />
|
||||||
|
<input placeholder='请输入验证码' inputmode='number' maxLength='6' />
|
||||||
|
</view>
|
||||||
|
<text @click.stop='startCountdown'>{{ countdown }}</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<text class='btn_register' style='display: none' @click.stop='register'>注册领券</text>
|
||||||
|
|
||||||
|
<image :src='companyConfigInfo.regqrcode||defaultImage' :show-menu-by-longpress='true' mode='aspectFill'
|
||||||
|
style='width: 439rpx;height: 439rpx;align-self: center' />
|
||||||
|
<text style='font-size: 26rpx;
|
||||||
|
margin-top: 10rpx;
|
||||||
|
align-self: center;color: #666666;'>长按扫码注册
|
||||||
|
</text>
|
||||||
|
|
||||||
|
<template v-if='couponBean&&couponBean.status==0'>
|
||||||
|
<view class='divider' />
|
||||||
|
<view class='coupon c-flex-column' @click.stop='goPath("/pages/mine/subs/coupon/index")'>
|
||||||
|
<view class='c-flex-row'>
|
||||||
|
<text class='coupon-name'>{{ couponBean.title }}</text>
|
||||||
|
<image :src='assetsUrl("ic_arrow_right_gray.png")' />
|
||||||
|
</view>
|
||||||
|
<text class='expired-time'>
|
||||||
|
有效期至{{ dayjs(Date.now()).add(couponBean.triggerEndDay, 'day').format('YYYY.MM.DD') }}
|
||||||
|
</text>
|
||||||
|
</view>
|
||||||
|
<view class='divider' />
|
||||||
|
|
||||||
|
<text style='font-size: 28rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #333333;margin-top: 20rpx'>福利详情
|
||||||
|
</text>
|
||||||
|
<text style='font-size: 28rpx;
|
||||||
|
color: #333333;margin-top: 14rpx'>1.优惠金额{{ couponBean.reduce }}元\n
|
||||||
|
2.满{{ couponBean.threshold }}减{{ couponBean.reduce }}\n
|
||||||
|
3.赠送{{ couponBean.publicNum }}张
|
||||||
|
</text>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<text style='font-size: 28rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #333333;margin-top: 20rpx'>
|
||||||
|
微信扫一扫领取会员卡
|
||||||
|
</text>
|
||||||
|
<text style='font-size: 28rpx;
|
||||||
|
color: #333333;margin-top: 14rpx'>
|
||||||
|
1、及时接受消费小票\n
|
||||||
|
2、随时查询消费记录\n
|
||||||
|
3、及时接收优惠信息
|
||||||
|
</text>
|
||||||
|
</template>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang='ts' setup>
|
||||||
|
import { assetsUrl, defaultImage } from '@/utils/assets';
|
||||||
|
import { useUserStore } from '@/store';
|
||||||
|
import { goPath } from '@/utils';
|
||||||
|
import { getRegisterCoupon } from '@/api/user';
|
||||||
|
import dayjs from 'dayjs';
|
||||||
|
|
||||||
|
const userStore = useUserStore();
|
||||||
|
const { companyConfigInfo } = storeToRefs(userStore);
|
||||||
|
|
||||||
|
const countdown = ref('获取验证码');
|
||||||
|
const couponBean = ref();
|
||||||
|
|
||||||
|
onLoad(async (e) => {
|
||||||
|
couponBean.value = await getRegisterCoupon();
|
||||||
|
});
|
||||||
|
|
||||||
|
const startCountdown = () => {
|
||||||
|
if(countdown.value !== '获取验证码') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let time = 120;
|
||||||
|
let interval = setInterval(() => {
|
||||||
|
time--;
|
||||||
|
countdown.value = `${time}s 重新获取`;
|
||||||
|
if(time == 0) {
|
||||||
|
clearInterval(interval);
|
||||||
|
countdown.value = '获取验证码';
|
||||||
|
}
|
||||||
|
}, 1000);
|
||||||
|
};
|
||||||
|
|
||||||
|
const register = () => {
|
||||||
|
};
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang='scss' scoped>
|
||||||
|
.content {
|
||||||
|
position: relative;
|
||||||
|
height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg-image {
|
||||||
|
position: fixed;
|
||||||
|
height: 100vh;
|
||||||
|
width: 100%;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-view {
|
||||||
|
background: #FFFFFF;
|
||||||
|
border-radius: 10rpx;
|
||||||
|
margin: 0 40rpx;
|
||||||
|
padding: 50rpx;
|
||||||
|
top: 150rpx;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.mobile-view {
|
||||||
|
border-radius: 10rpx;
|
||||||
|
border: 1rpx solid #D8D8D8;
|
||||||
|
padding-left: 28rpx;
|
||||||
|
|
||||||
|
image {
|
||||||
|
width: 36rpx;
|
||||||
|
height: 36rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
flex: 1;
|
||||||
|
height: 80rpx;
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #333333;
|
||||||
|
margin-left: 26rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.captcha-view {
|
||||||
|
margin-top: 20rpx;
|
||||||
|
|
||||||
|
.c-flex-row {
|
||||||
|
border-radius: 10rpx;
|
||||||
|
border: 1rpx solid #D8D8D8;
|
||||||
|
padding-left: 28rpx;
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
|
image {
|
||||||
|
width: 33rpx;
|
||||||
|
height: 26rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
height: 80rpx;
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #333333;
|
||||||
|
margin-left: 26rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
text {
|
||||||
|
display: flex;
|
||||||
|
height: 80rpx;
|
||||||
|
background: #FFD436;
|
||||||
|
border-radius: 10rpx;
|
||||||
|
margin-left: 12rpx;
|
||||||
|
padding: 0 15rpx;
|
||||||
|
font-size: 28rpx;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
color: #FFFFFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn_register {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
height: 90rpx;
|
||||||
|
background: #F53636;
|
||||||
|
border-radius: 10rpx;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #FFFFFF;
|
||||||
|
margin-top: 46rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.divider {
|
||||||
|
border-bottom-style: dashed;
|
||||||
|
border-color: #E98585;
|
||||||
|
border-width: 0.2rpx;
|
||||||
|
margin-top: 34rpx
|
||||||
|
}
|
||||||
|
|
||||||
|
.coupon {
|
||||||
|
margin-top: 30rpx;
|
||||||
|
|
||||||
|
.coupon-name {
|
||||||
|
display: flex;
|
||||||
|
font-size: 36rpx;
|
||||||
|
color: #D95554;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
image {
|
||||||
|
width: 13rpx;
|
||||||
|
height: 24rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.expired-time {
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #333333;
|
||||||
|
margin-top: 2rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -1,12 +1,12 @@
|
|||||||
<template>
|
<template>
|
||||||
<web-view class="h-full" :src="url" />
|
<web-view class='h-full' :src='url' />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang='ts'>
|
||||||
const url = ref<string>('');
|
const url = ref<string>('');
|
||||||
|
|
||||||
onLoad((params: any) => {
|
onLoad((params: any) => {
|
||||||
if (params.url)
|
if(params.url)
|
||||||
url.value = params.url;
|
url.value = decodeURIComponent(params.url);
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
29
src/pages/coupons/ticketsBuy/ticketsBuy.vue
Normal file
29
src/pages/coupons/ticketsBuy/ticketsBuy.vue
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
<template>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang='ts' setup>
|
||||||
|
onLoad((options) => {
|
||||||
|
getApp().logger?.info('ticketsBuy options: ', options);
|
||||||
|
let couponId = options?.couponsId;
|
||||||
|
if(options?.query && couponId == undefined) {
|
||||||
|
const params = decodeURIComponent(options?.query);
|
||||||
|
couponId = getQueryParam(params, 'couponsId');
|
||||||
|
}
|
||||||
|
setTimeout(() => {
|
||||||
|
uni.reLaunch({
|
||||||
|
url: `/pages/common/groupbuy/detail?id=${couponId}`
|
||||||
|
});
|
||||||
|
}, 300);
|
||||||
|
});
|
||||||
|
|
||||||
|
function getQueryParam(queryParams: string, key: string) {
|
||||||
|
let regex = new RegExp('(?:[?&]|^)' + key + '=([^&]+)'),
|
||||||
|
match = queryParams.match(regex);
|
||||||
|
return match && match[1];
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang='scss' scoped>
|
||||||
|
|
||||||
|
</style>
|
||||||
@@ -1,18 +1,403 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class='flex flex-col items-center justify-center'>
|
<view class='u-flex-column'>
|
||||||
<swiper class='swiper'>
|
<swiper class='swiper' :indicator-dots='true' :autoplay='true' :interval='3000' :duration='1000'
|
||||||
<swiper-item v-for='(item, index) in bannerList' :key='index'>
|
@change='swiperChange'>
|
||||||
<image :src='item' mode='aspectFill' />
|
<swiper-item v-for='(item, index) in companyConfigInfo?.bannerinx' :key='index'>
|
||||||
|
<image :src='item.src||defaultImage' mode='aspectFill' />
|
||||||
</swiper-item>
|
</swiper-item>
|
||||||
</swiper>
|
</swiper>
|
||||||
|
|
||||||
|
<view class='basic-view'>
|
||||||
|
<view class='indicator-view'>
|
||||||
|
<view v-for='(item,index) in companyConfigInfo?.bannerinx' :key='item' class='normal'
|
||||||
|
:class="{'active': index === currentBannerIndex}">
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class='user-info-card' @click.stop='goPath("/pages/mine/index")'>
|
||||||
|
<image class='user-avatar' :src='userInfo?.image||defaultAvatar' mode='aspectFill' />
|
||||||
|
<text class='user-name primary-text-color'>{{ userInfo?.nickName || '点击注册会员' }}</text>
|
||||||
|
<view class='integral-view primary-text-color' @click.stop='goPath("/pages/mine/subs/integral/index")'>
|
||||||
|
<text>{{ userInfo?.integration || 0 }}</text>
|
||||||
|
<text>积分</text>
|
||||||
|
</view>
|
||||||
|
<view class='divider' style='height: 83rpx' />
|
||||||
|
<view class='balance-view' @click.stop='goPath("/pages/mine/subs/recharge/index")'>
|
||||||
|
<text class='accent-text-color'>{{ userInfo?.balance || 0 }}</text>
|
||||||
|
<text>余额(元)</text>
|
||||||
|
</view>
|
||||||
|
<view class='divider' style='height: 83rpx' />
|
||||||
|
<view class='switch-view' @click.stop='switchCompany'>
|
||||||
|
<image :src='assetsUrl("ic_switch_company.png")' />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class='menu-view'>
|
||||||
|
<view @click.stop='goPath("/pages/mine/subs/recharge/index")'>
|
||||||
|
<image :src='assetsUrl("ic_member_card2.png")' style='width: 108rpx;height: 72rpx;padding: 11rpx 0' />
|
||||||
|
<text>会员充值</text>
|
||||||
|
</view>
|
||||||
|
<view class='divider' style='margin: 0;height: 153rpx' />
|
||||||
|
<view @click.stop='goPath("/pages/mine/subs/coupon/index")'>
|
||||||
|
<image :src='assetsUrl("ic_coupon2.png")' style='width: 108rpx;height: 95rpx' />
|
||||||
|
<text>优惠券</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class='second-menu-view'>
|
||||||
|
<view v-for='(item, index) in submenuList' :key='index'>
|
||||||
|
<view class='menu-item' @click='goPath(item.path)'>
|
||||||
|
<image :src='item.icon' />
|
||||||
|
<text>{{ item.title }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<text class='hot-recommend'>热门推荐</text>
|
||||||
|
|
||||||
|
<view class='bottom-banner-view'>
|
||||||
|
<swiper :indicator-dots='true' :autoplay='true' :interval='3000' :duration='1000'>
|
||||||
|
<swiper-item v-for='(item, index) in companyConfigInfo?.bannerhot' :key='index'>
|
||||||
|
<image :src='item.src' mode='aspectFill' />
|
||||||
|
</swiper-item>
|
||||||
|
</swiper>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
<CompanyDialog ref='companyDialogRef' :companyList='companyList' />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang='ts'>
|
<script setup lang='ts'>
|
||||||
|
import CompanyDialog from '@/components/company-dialog.vue';
|
||||||
|
import { getCompanyList } from '@/api/company';
|
||||||
import { useUserStore } from '@/store';
|
import { useUserStore } from '@/store';
|
||||||
|
import { assetsUrl, defaultAvatar, defaultImage } from '@/utils/assets';
|
||||||
|
import { getOpenId, goPath, isLogin } from '@/utils';
|
||||||
|
import { storeToRefs } from 'pinia';
|
||||||
|
import { UserBean } from '@/store/modules/user/types';
|
||||||
|
|
||||||
const store = useUserStore();
|
const companyDialogRef = ref();
|
||||||
|
const userStore = useUserStore();
|
||||||
|
const { userInfo, companyConfigInfo } = storeToRefs(userStore);
|
||||||
|
const currentBannerIndex = ref(0);
|
||||||
|
|
||||||
const bannerList = ref<string[]>(['1', '2', '3', '4']);
|
const submenuList = [
|
||||||
console.log('store.user_name', store.user_name);
|
{
|
||||||
|
title: '注册有礼',
|
||||||
|
icon: assetsUrl('ic_register_gift2.png'),
|
||||||
|
path: '/pages/common/register/reward'
|
||||||
|
// path: '/pages/coupons/ticketsBuy/ticketsBuy?couponsId=1797773484774432769'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '团购秒杀',
|
||||||
|
icon: assetsUrl('ic_groupbuy2.png'),
|
||||||
|
path: '/pages/common/groupbuy/index'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '入群有礼',
|
||||||
|
icon: assetsUrl('ic_group_gift2.png'),
|
||||||
|
path: '/pages/home/subs/group/join'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
const companyList = ref([]);
|
||||||
|
const userList = ref<UserBean[]>([]);
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
wx.getPrivacySetting({
|
||||||
|
success: res => {
|
||||||
|
console.log(res); // 返回结果为: res = { needAuthorization: true/false, privacyContractName: '《xxx隐私保护指引》' }
|
||||||
|
if(res.needAuthorization) {
|
||||||
|
// 需要弹出隐私协议
|
||||||
|
// agreementPopupRef.value.show();
|
||||||
|
} else {
|
||||||
|
// 用户已经同意过隐私协议,所以不需要再弹出隐私协议,也能调用隐私接口
|
||||||
|
}
|
||||||
|
},
|
||||||
|
fail: (res) => {
|
||||||
|
console.log('fail ', res);
|
||||||
|
},
|
||||||
|
complete: () => {
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
onLoad((e) => {
|
||||||
|
console.log('home load e ', e);
|
||||||
|
});
|
||||||
|
|
||||||
|
onShow(async () => {
|
||||||
|
if(isLogin()) {
|
||||||
|
// userStore.getProfile();
|
||||||
|
fetchCompanyList();
|
||||||
|
} else {
|
||||||
|
// setToken('42ae187265fb4688804fd294cbcf99f1')
|
||||||
|
uni.showModal({
|
||||||
|
title: '提示',
|
||||||
|
content: '您还未登录,请先登录',
|
||||||
|
showCancel: true,
|
||||||
|
success: (res) => {
|
||||||
|
if(res.confirm) {
|
||||||
|
goPath('/pages/common/login/index');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const switchCompany = () => {
|
||||||
|
fetchCompanyList((companyList: any[], userList: any[]) => {
|
||||||
|
companyDialogRef.value.show(getApp().globalData?.companyId, (index: number) => {
|
||||||
|
userStore.setUserInfo(userList[index]);
|
||||||
|
userStore.setCompanyInfo(companyList[index]);
|
||||||
|
|
||||||
|
avatarModifyRemind();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
function avatarModifyRemind() {
|
||||||
|
setTimeout(() => {
|
||||||
|
if(userInfo.value.image === defaultAvatar) {
|
||||||
|
uni.showModal({
|
||||||
|
title: '提示',
|
||||||
|
content: '为了提供更优质的个性化服务,请先修改头像',
|
||||||
|
showCancel: true,
|
||||||
|
success: (res) => {
|
||||||
|
if(res.confirm) {
|
||||||
|
goPath('/pages/mine/subs/profile/index');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, 300);
|
||||||
|
}
|
||||||
|
|
||||||
|
const fetchCompanyList = (fn: any = undefined) => {
|
||||||
|
const maOpenId = getOpenId() || userInfo.value?.maOpenId || (userList.value.filter((res: UserBean) => res?.maOpenId !== '')[0]?.maOpenId);
|
||||||
|
getCompanyList(maOpenId).then(res => {
|
||||||
|
companyList.value = res.map((res: { company: any }) => res.company);
|
||||||
|
userList.value = res.map((res: { user: any }) => res.user);
|
||||||
|
|
||||||
|
if(companyList.value.length === 0) {
|
||||||
|
uni.showModal({
|
||||||
|
title: '提示',
|
||||||
|
content: '当前店铺还未注册,请先注册',
|
||||||
|
showCancel: true,
|
||||||
|
success: (res) => {
|
||||||
|
if(res.confirm) {
|
||||||
|
goPath('/pages/common/register/index');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(fn != undefined && fn instanceof Function) {
|
||||||
|
fn(companyList.value, userList.value);
|
||||||
|
} else {
|
||||||
|
let index = companyList.value.findIndex((res: { id: string }) => res.id === getApp().globalData?.companyId);
|
||||||
|
//未在当前公司下注册
|
||||||
|
if(index < 0) {
|
||||||
|
if(!getApp()?.globalData?.storeId) {
|
||||||
|
goPath('/pages/common/register/index');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
index = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
userStore.setUserInfo(userList.value[index]);
|
||||||
|
userStore.setCompanyInfo(companyList.value[index]);
|
||||||
|
avatarModifyRemind();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const swiperChange = (e: any) => {
|
||||||
|
currentBannerIndex.value = e.detail.current;
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style lang='scss'>
|
||||||
|
.swiper {
|
||||||
|
display: flex;
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
height: 520rpx;
|
||||||
|
|
||||||
|
image {
|
||||||
|
width: 100%;
|
||||||
|
height: 520rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.basic-view {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
position: relative;
|
||||||
|
top: -100rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.indicator-view {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
position: absolute;
|
||||||
|
justify-content: center;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
top: -20rpx;
|
||||||
|
|
||||||
|
.normal {
|
||||||
|
width: 16rpx;
|
||||||
|
height: 16rpx;
|
||||||
|
background: #707070;
|
||||||
|
border-radius: 50%;
|
||||||
|
margin: 0 8rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.active {
|
||||||
|
@extend .normal;
|
||||||
|
background: #333333;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.card {
|
||||||
|
background: #FFFFFF;
|
||||||
|
border-radius: 20rpx 20rpx 20rpx 20rpx;
|
||||||
|
margin: 0 24rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-info-card {
|
||||||
|
@extend .card;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
padding: 30rpx;
|
||||||
|
align-items: center;
|
||||||
|
margin-top: 14rpx;
|
||||||
|
|
||||||
|
.user-avatar {
|
||||||
|
width: 88rpx;
|
||||||
|
height: 88rpx;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-name {
|
||||||
|
display: flex;
|
||||||
|
flex: 1;
|
||||||
|
font-size: 30rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-left: 16rpx;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
margin-right: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.integral-view {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
text:nth-child(1) {
|
||||||
|
font-size: 36rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
text:nth-child(2) {
|
||||||
|
font-size: 26rpx;
|
||||||
|
font-weight: 400;
|
||||||
|
margin-top: 10rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.balance-view {
|
||||||
|
@extend .integral-view;
|
||||||
|
|
||||||
|
text:nth-child(1) {
|
||||||
|
font-size: 36rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.switch-view {
|
||||||
|
image {
|
||||||
|
width: 50rpx;
|
||||||
|
height: 50rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.divider {
|
||||||
|
margin: 0 30rpx;
|
||||||
|
width: 0.5rpx;
|
||||||
|
height: 100%;
|
||||||
|
background: #C7C7C7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-view {
|
||||||
|
@extend .card;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
position: relative;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
padding: 40rpx 0 32rpx 0;
|
||||||
|
margin-top: 20rpx;
|
||||||
|
|
||||||
|
view:not(:nth-of-type(2)):nth-of-type(n+1) {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
text {
|
||||||
|
font-size: 32rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #333333;
|
||||||
|
margin-top: 16rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.second-menu-view {
|
||||||
|
@extend .menu-view;
|
||||||
|
|
||||||
|
image {
|
||||||
|
width: 88rpx;
|
||||||
|
height: 88rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
text {
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #333333;
|
||||||
|
margin-top: 23rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.hot-recommend {
|
||||||
|
margin-top: 30rpx;
|
||||||
|
margin-left: 24rpx;
|
||||||
|
font-size: 36rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #333333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bottom-banner-view {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
margin: 20rpx 24rpx 0 24rpx;
|
||||||
|
border-radius: 20rpx;
|
||||||
|
height: 285rpx;
|
||||||
|
|
||||||
|
swiper {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
image {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
border-radius: 20rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
61
src/pages/home/subs/group/join.vue
Normal file
61
src/pages/home/subs/group/join.vue
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
<template>
|
||||||
|
<view class='content card-view'>
|
||||||
|
<text class='title'>入群步骤</text>
|
||||||
|
<view class='indicator' />
|
||||||
|
<text class='step-title'>
|
||||||
|
1.长按识别下方二维码,添加【店铺福利群】
|
||||||
|
</text>
|
||||||
|
<view class='divider' style='margin-top: 28rpx' />
|
||||||
|
<image :src=' companyConfigInfo.groupqrcode||defaultImage' show-menu-by-longpress />
|
||||||
|
<text class='step-title'>
|
||||||
|
2.识别【店铺福利群】发您的二维码,即可入群
|
||||||
|
</text>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang='ts' setup>
|
||||||
|
|
||||||
|
import { useUserStore } from '@/store';
|
||||||
|
import { defaultImage } from '@/utils/assets';
|
||||||
|
|
||||||
|
const userStore = useUserStore();
|
||||||
|
const { companyConfigInfo } = storeToRefs(userStore);
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang='scss' scoped>
|
||||||
|
.content {
|
||||||
|
display: flex;
|
||||||
|
margin: 20rpx;
|
||||||
|
padding: 37rpx 20rpx 30rpx 20rpx;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
font-size: 36rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #333333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.indicator {
|
||||||
|
width: 72rpx;
|
||||||
|
height: 10rpx;
|
||||||
|
background: #333333;
|
||||||
|
border-radius: 50rpx;
|
||||||
|
margin-top: 10rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.step-title {
|
||||||
|
font-size: 30rpx;
|
||||||
|
font-weight: 400;
|
||||||
|
color: #333333;
|
||||||
|
margin-top: 55rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
image {
|
||||||
|
width: 432rpx;
|
||||||
|
height: 432rpx;
|
||||||
|
margin-top: 67rpx;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
15
src/pages/index/index.vue
Normal file
15
src/pages/index/index.vue
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<template>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang='ts' setup>
|
||||||
|
onMounted(() => {
|
||||||
|
uni.reLaunch({
|
||||||
|
url: '/pages/home/index'
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang='scss' scoped>
|
||||||
|
|
||||||
|
</style>
|
||||||
@@ -1,25 +1,341 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="flex flex-col items-center justify-center">
|
<view class='content' v-if='companyConfigInfo.mallopen==1'>
|
||||||
<image
|
<view class='search-view'>
|
||||||
class="mb-50rpx mt-200rpx h-200rpx w-200rpx"
|
<view class='search-input' @click.stop='goPath("/pages/mall/subs/search/index")'>
|
||||||
src="@/static/images/logo.png"
|
<image :src=' assetsUrl("ic_search.png")'></image>
|
||||||
width="200rpx"
|
<input placeholder='输入名称、款号搜索' :disabled='true' />
|
||||||
height="200rpx"
|
</view>
|
||||||
/>
|
</view>
|
||||||
<view class="flex justify-center">
|
|
||||||
<text class="font-size-36rpx color-gray-700">
|
<view class='container'>
|
||||||
{{ title }}
|
<scroll-view class='category-list' :scroll-y='true'>
|
||||||
</text>
|
<view v-for='(item,index) in categoryList' :key='index' class='category-item'
|
||||||
|
@click.stop='changeCategory(index)'
|
||||||
|
:class="{'category-item-active': index === categorySelectedIndex}">
|
||||||
|
<text>{{ item.typeName }}</text>
|
||||||
|
</view>
|
||||||
|
</scroll-view>
|
||||||
|
|
||||||
|
<scroll-view class='goods-list' :scroll-y='true' type='custom' @scrolltolower='loadMore'>
|
||||||
|
<grid-view type='masonry' :cross-axis-count='2'>
|
||||||
|
<view v-for='(item, index) in goodsList' :key='index' class='goods-item'
|
||||||
|
@click.stop='goPath(`/pages/mall/subs/goods/detail?goodsId=${item.goodsId}`)'>
|
||||||
|
<image class='goods-image' :src='item.images||defaultImage' />
|
||||||
|
<text class='goods-name'>{{ item.goodsName || '未知' }}</text>
|
||||||
|
<text class='goods-price'>¥{{ (item.price * userInfo.userDiscount).toFixed(2) }}
|
||||||
|
<text v-if='userInfo.userDiscount>0&&userInfo.userDiscount<1'
|
||||||
|
style='text-decoration: line-through;color: #999999;font-size: 25rpx'>
|
||||||
|
¥{{ item.price }}
|
||||||
|
</text>
|
||||||
|
</text>
|
||||||
|
<image class='add-image' :src='assetsUrl("ic_add_goods.png")' @click.stop='addShoppingCart(item)' />
|
||||||
|
</view>
|
||||||
|
</grid-view>
|
||||||
|
<u-empty v-if='goodsList.length === 0' text='暂无商品数据' />
|
||||||
|
</scroll-view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class='shopping-cart' @click.stop='goPath("/pages/mall/subs/shoppingcart/index")'>
|
||||||
|
<image :src='assetsUrl("ic_shopping_cart.png")' />
|
||||||
|
<text v-if='totalCount>0'>{{ totalCount }}</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
<view class='content' v-else style='align-items: center;justify-content:center;'>
|
||||||
|
<image :src='assetsUrl("bg_mall_close.png")' style='width: 200rpx; height: 200rpx;' />
|
||||||
|
</view>
|
||||||
|
<sku-dialog ref='skuDialogRef' />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang='ts'>
|
||||||
|
import { onShareAppMessage, onShareTimeline } from '@dcloudio/uni-app';
|
||||||
|
import SkuDialog from '@/components/sku-dialog.vue';
|
||||||
|
import { assetsUrl, defaultImage } from '@/utils/assets';
|
||||||
|
import { goLogin, goPath, isLogin, showToast } from '@/utils';
|
||||||
|
import { getCategoryList, getGoodsList } from '@/api/goods';
|
||||||
|
import { CategoryBean, GoodsBean } from '@/api/goods/types';
|
||||||
|
import useShoppingCartStore from '@/store/modules/shoppingcart';
|
||||||
import { useUserStore } from '@/store';
|
import { useUserStore } from '@/store';
|
||||||
|
|
||||||
const title = ref<string>();
|
const userStore = useUserStore();
|
||||||
title.value = import.meta.env.VITE_APP_TITLE;
|
const { userInfo, companyConfigInfo } = storeToRefs(userStore);
|
||||||
|
const shoppingCartStore = useShoppingCartStore();
|
||||||
|
const { totalCount } = storeToRefs(shoppingCartStore);
|
||||||
|
|
||||||
const store = useUserStore();
|
const skuDialogRef = ref();
|
||||||
console.log('store.user_name', store.user_name);
|
const categoryList = ref<CategoryBean[]>([]);
|
||||||
|
const categorySelectedIndex = ref<number>(0);
|
||||||
|
const goodsList = ref<GoodsBean[]>([]);
|
||||||
|
const currentPageNum = ref<number>(1);
|
||||||
|
|
||||||
|
onLoad(() => {
|
||||||
|
if(!isLogin()) {
|
||||||
|
goLogin();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
userStore.$onAction(({ name, after }) => {
|
||||||
|
after(() => {
|
||||||
|
//更新用户信息
|
||||||
|
if(name === 'setUserInfo') {
|
||||||
|
fetchCategoryList();
|
||||||
|
shoppingCartStore.resetData();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
fetchCategoryList();
|
||||||
|
});
|
||||||
|
|
||||||
|
onShareAppMessage((e) => {
|
||||||
|
return {
|
||||||
|
title: 'VIP顾客中心',
|
||||||
|
path: '/pages/mall/index'
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
onShareTimeline((e) => {
|
||||||
|
return {
|
||||||
|
title: 'VIP顾客中心',
|
||||||
|
path: '/pages/mall/index'
|
||||||
|
};
|
||||||
|
});
|
||||||
|
const fetchCategoryList = async () => {
|
||||||
|
if(companyConfigInfo.value.mallopen == 1) {
|
||||||
|
const list = await getCategoryList();
|
||||||
|
list.unshift({ typeName: '上新精选', typeId: '2' });
|
||||||
|
list.unshift({ typeName: '热销商品', typeId: '1' });
|
||||||
|
list.unshift({ typeName: '全部分类', typeId: '0' });
|
||||||
|
categoryList.value = list;
|
||||||
|
await changeCategory(0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const changeCategory = async (index: number) => {
|
||||||
|
categorySelectedIndex.value = index;
|
||||||
|
await fetchGoodsList();
|
||||||
|
};
|
||||||
|
|
||||||
|
const fetchGoodsList = async (refresh: boolean = true) => {
|
||||||
|
currentPageNum.value = refresh ? 1 : currentPageNum.value + 1;
|
||||||
|
|
||||||
|
let typeId = [categoryList.value[categorySelectedIndex.value].typeId];
|
||||||
|
let sort = undefined;
|
||||||
|
if(typeId[0] === '0') {
|
||||||
|
typeId = [];
|
||||||
|
sort = undefined;
|
||||||
|
} else if(typeId[0] === '1') {
|
||||||
|
typeId = [];
|
||||||
|
sort = 'good_num DESC';
|
||||||
|
} else if(typeId[0] === '2') {
|
||||||
|
typeId = [];
|
||||||
|
sort = 'update_time DESC';
|
||||||
|
}
|
||||||
|
const { rows } = await getGoodsList({
|
||||||
|
page: {
|
||||||
|
pageNum: currentPageNum.value,
|
||||||
|
pageSize: 30,
|
||||||
|
bean: {
|
||||||
|
keyword: '',
|
||||||
|
typeIds: typeId,
|
||||||
|
sort: sort
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if(refresh) {
|
||||||
|
goodsList.value = rows;
|
||||||
|
} else {
|
||||||
|
goodsList.value = goodsList.value.concat(rows);
|
||||||
|
}
|
||||||
|
|
||||||
|
goodsList.value.forEach(e => {
|
||||||
|
e.price = userStore.getRealGoodsPrice(e.price, e.priceExt);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const loadMore = () => {
|
||||||
|
fetchGoodsList(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const randomImageHeight = () => {
|
||||||
|
const height = getRandomFloatInRange(1, 2) * 200 + 'rpx';
|
||||||
|
console.log('--------->>>', height);
|
||||||
|
return height;
|
||||||
|
};
|
||||||
|
|
||||||
|
const getRandomFloatInRange = (a: number, b: number) => {
|
||||||
|
return Math.random() * (b - a) + a;
|
||||||
|
};
|
||||||
|
|
||||||
|
const addShoppingCart = (goodsBean: GoodsBean) => {
|
||||||
|
skuDialogRef.value.show(goodsBean.goodsId, (e: GoodsBean) => {
|
||||||
|
//重新选择sku后判断当前购物中是否存在相同sku的商品
|
||||||
|
const existsIndex = shoppingCartStore.getSameGoodsIndex(e?.id || '', e.checkedStock.colorId, e.checkedStock.sizeId);
|
||||||
|
//不存在则更新当前商品sku
|
||||||
|
if(existsIndex < 0) {
|
||||||
|
shoppingCartStore.save(e);
|
||||||
|
}
|
||||||
|
//如果已存在,则更新已存在商品数量,并删除当前商品
|
||||||
|
else {
|
||||||
|
shoppingCartStore.updateCount(existsIndex, e.checkedStock.count);
|
||||||
|
}
|
||||||
|
showToast('添加购物车成功');
|
||||||
|
});
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style lang='scss' scoped>
|
||||||
|
.content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-view {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
background: white;
|
||||||
|
padding: 19rpx 30rpx;
|
||||||
|
|
||||||
|
.search-input {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
background: #F7F7F7;
|
||||||
|
padding: 17rpx 23rpx;
|
||||||
|
font-size: 26rpx;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
image {
|
||||||
|
width: 32rpx;
|
||||||
|
height: 32rpx;
|
||||||
|
margin-right: 20rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
margin-top: 20rpx;
|
||||||
|
|
||||||
|
.category-list {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
width: 280rpx;
|
||||||
|
height: 100vh;
|
||||||
|
|
||||||
|
.category-item {
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
height: 92rpx;
|
||||||
|
overflow: hidden;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
white-space: nowrap;
|
||||||
|
|
||||||
|
text {
|
||||||
|
width: 60%;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 30rpx;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.category-item-active {
|
||||||
|
@extend .category-item;
|
||||||
|
background: #FFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
.category-item-active:before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
width: 5rpx;
|
||||||
|
left: 15rpx;
|
||||||
|
height: 30rpx;
|
||||||
|
background: #333333;
|
||||||
|
color: #333333;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.goods-list {
|
||||||
|
display: flex;
|
||||||
|
background: white;
|
||||||
|
padding: 38rpx 20rpx 0 20rpx;
|
||||||
|
height: 100vh;
|
||||||
|
|
||||||
|
.goods-item {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
position: relative;
|
||||||
|
margin-bottom: 10rpx;
|
||||||
|
padding: 10rpx 10rpx;
|
||||||
|
|
||||||
|
.goods-image {
|
||||||
|
border-radius: 10rpx;
|
||||||
|
width: 100%;
|
||||||
|
max-height: 300rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.goods-name {
|
||||||
|
font-size: 28rpx;
|
||||||
|
font-weight: 400;
|
||||||
|
color: #333333;
|
||||||
|
-webkit-line-clamp: 2;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
margin-top: 10rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.goods-price {
|
||||||
|
font-size: 36rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #F32B2B;
|
||||||
|
}
|
||||||
|
|
||||||
|
.add-image {
|
||||||
|
width: 42rpx;
|
||||||
|
height: 42rpx;
|
||||||
|
position: absolute;
|
||||||
|
bottom: 10rpx;
|
||||||
|
right: 10rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.shopping-cart {
|
||||||
|
display: flex;
|
||||||
|
position: fixed;
|
||||||
|
bottom: 30rpx;
|
||||||
|
right: 40rpx;
|
||||||
|
width: 90rpx;
|
||||||
|
height: 90rpx;
|
||||||
|
background: #FFFFFF;
|
||||||
|
border-radius: 50%;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
box-shadow: 0 0 20rpx 1rpx rgba(78, 78, 78, 0.16);
|
||||||
|
|
||||||
|
image {
|
||||||
|
width: 40rpx;
|
||||||
|
height: 40rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
text {
|
||||||
|
display: flex;
|
||||||
|
min-width: 39rpx;
|
||||||
|
min-height: 39rpx;
|
||||||
|
background: #F32B2B;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
top: -5rpx;
|
||||||
|
right: -5rpx;
|
||||||
|
color: white;
|
||||||
|
font-size: 26rpx;
|
||||||
|
position: absolute;
|
||||||
|
border-radius: 50%;
|
||||||
|
border: 2rpx solid #FFFFFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
114
src/pages/mall/subs/components/coupon-dialog.vue
Normal file
114
src/pages/mall/subs/components/coupon-dialog.vue
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
<template>
|
||||||
|
<uni-popup type='bottom' ref='popupRef' :is-mask-click='false'>
|
||||||
|
<view class='popup-content c-flex-column'>
|
||||||
|
<view class='c-flex-row'>
|
||||||
|
<text>优惠券</text>
|
||||||
|
<text @click.stop='confirm'>确定</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<scroll-view scroll-y>
|
||||||
|
<coupon-item v-if='coupons.length>0' v-for='(item,index) in coupons' :item='item' :key='index'
|
||||||
|
@confirm='confirmItem(index)' />
|
||||||
|
<u-loadmore v-else status='loading' />
|
||||||
|
</scroll-view>
|
||||||
|
</view>
|
||||||
|
</uni-popup>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang='ts' setup>
|
||||||
|
import CouponItem from '../components/coupon-item.vue';
|
||||||
|
import { getCompanyId } from '@/utils';
|
||||||
|
import { getCouponList } from '@/api/user';
|
||||||
|
import { CouponBean } from '@/api/user/types';
|
||||||
|
import { useUserStore } from '@/store';
|
||||||
|
|
||||||
|
const popupRef = ref();
|
||||||
|
|
||||||
|
const userStore = useUserStore();
|
||||||
|
const { userInfo } = storeToRefs(userStore);
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
orderPrice: {
|
||||||
|
type: Number,
|
||||||
|
default: 0
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const emits = defineEmits(['confirm']);
|
||||||
|
const coupons = ref<CouponBean[]>([]);
|
||||||
|
|
||||||
|
const fetchData = async (status: number) => {
|
||||||
|
const { list } = await getCouponList({
|
||||||
|
companyId: getApp()?.globalData?.companyId,
|
||||||
|
memberId: userInfo.value?.id,
|
||||||
|
status: status,
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 100
|
||||||
|
});
|
||||||
|
list.filter((item: CouponBean) => item.status = (props.orderPrice >= item.threshold) ? 0 : 1);
|
||||||
|
coupons.value = list;
|
||||||
|
};
|
||||||
|
|
||||||
|
const show = () => {
|
||||||
|
popupRef.value.open();
|
||||||
|
fetchData(0);
|
||||||
|
};
|
||||||
|
|
||||||
|
const confirmItem = (index: number) => {
|
||||||
|
coupons.value.forEach(item => {
|
||||||
|
item.checked = false;
|
||||||
|
});
|
||||||
|
coupons.value[index].checked = !coupons.value[index].checked;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const confirm = () => {
|
||||||
|
close();
|
||||||
|
emits('confirm', coupons.value.filter(item => item.checked)[0]);
|
||||||
|
};
|
||||||
|
|
||||||
|
const close = () => {
|
||||||
|
popupRef.value.close();
|
||||||
|
};
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
show
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang='scss' scoped>
|
||||||
|
.popup-content {
|
||||||
|
background: #FFFFFF;
|
||||||
|
border-radius: 20rpx 20rpx 0 0;
|
||||||
|
padding: 38rpx 45rpx 10rpx 45rpx;
|
||||||
|
|
||||||
|
view:nth-of-type(1) {
|
||||||
|
display: flex;
|
||||||
|
margin-bottom: 70rpx;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
text:nth-of-type(1) {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #333333;
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
text:nth-of-type(2) {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #F32B2B;
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
scroll-view {
|
||||||
|
height: 600rpx;
|
||||||
|
max-height: 600rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
</style>
|
||||||
118
src/pages/mall/subs/components/coupon-item.vue
Normal file
118
src/pages/mall/subs/components/coupon-item.vue
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
<template>
|
||||||
|
<view class='coupon-content' @click.stop='()=>{emits("confirm")}'>
|
||||||
|
<image v-if='item?.status==0' :src='assetsUrl("bg_coupon.png")' />
|
||||||
|
<image v-else-if='item?.status==1' :src='assetsUrl("bg_coupon_expired.png")' />
|
||||||
|
<view class='left-content accent-text-color' :class='{"left-content-disabled": item?.status==1}'>
|
||||||
|
<text>{{ item?.reduce }}</text>
|
||||||
|
<text>满{{ item?.threshold }}元可用</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class='right-content accent-text-color' :class='{"right-content-disabled": item?.status==1}'>
|
||||||
|
<text>{{ item?.name }}</text>
|
||||||
|
<text>有效期至{{ dayjs(item?.startTime).format('YYYY-MM-DD') }}</text>
|
||||||
|
<image v-if='item?.status==0' class='checkbox'
|
||||||
|
:src='assetsUrl(item.checked?"ic_checkbox_active.png":"ic_checkbox_normal.png")'
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang='ts' setup>
|
||||||
|
import { PropType } from 'vue';
|
||||||
|
|
||||||
|
import { assetsUrl } from '@/utils/assets';
|
||||||
|
import { CouponBean } from '@/api/user/types';
|
||||||
|
import dayjs from 'dayjs';
|
||||||
|
|
||||||
|
defineProps({
|
||||||
|
item: Object as PropType<CouponBean>
|
||||||
|
});
|
||||||
|
|
||||||
|
const emits = defineEmits(['confirm']);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang='scss' scoped>
|
||||||
|
.coupon-content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
height: 200rpx;
|
||||||
|
position: relative;
|
||||||
|
margin: 10rpx 0 10rpx 0;
|
||||||
|
|
||||||
|
image {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
.left-content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
position: relative;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding-left: 50rpx;
|
||||||
|
|
||||||
|
text:nth-of-type(1) {
|
||||||
|
font-size: 55rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
text:nth-of-type(1):after {
|
||||||
|
content: '元';
|
||||||
|
font-size: 24rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
text:nth-of-type(2) {
|
||||||
|
font-size: 26rpx;
|
||||||
|
font-weight: 400;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.left-content-disabled {
|
||||||
|
@extend .left-content;
|
||||||
|
color: #C2C2C2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.right-content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
position: relative;
|
||||||
|
flex: 1;
|
||||||
|
justify-content: center;
|
||||||
|
margin-left: 60rpx;
|
||||||
|
|
||||||
|
text:nth-of-type(1) {
|
||||||
|
font-size: 30rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
text:nth-of-type(2) {
|
||||||
|
font-size: 26rpx;
|
||||||
|
margin-top: 20rpx;
|
||||||
|
color: #333333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.checkbox {
|
||||||
|
display: flex;
|
||||||
|
width: 42rpx;
|
||||||
|
height: 42rpx;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-weight: bold;
|
||||||
|
position: absolute;
|
||||||
|
right: 36rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.right-content-disabled {
|
||||||
|
@extend .right-content;
|
||||||
|
color: #C2C2C2;
|
||||||
|
|
||||||
|
text:nth-of-type(2) {
|
||||||
|
color: #C2C2C2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
489
src/pages/mall/subs/goods/detail.vue
Normal file
489
src/pages/mall/subs/goods/detail.vue
Normal file
@@ -0,0 +1,489 @@
|
|||||||
|
<template>
|
||||||
|
<view class='content'>
|
||||||
|
<view class='swiper-container'>
|
||||||
|
<swiper class='swiper' :interval='1500' :duration='1000' @change='swiperChange'>
|
||||||
|
<swiper-item v-for='(item,index) in [goodsBean?.images]' :key='index'>
|
||||||
|
<image :src='item||defaultImage' mode='aspectFill' />
|
||||||
|
</swiper-item>
|
||||||
|
</swiper>
|
||||||
|
<view class='indicator' style='display: none'>
|
||||||
|
<text>{{ swiperIndex + 1 }}</text>
|
||||||
|
<text>/{{ bannerList.length }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class='goods-info-view c-flex-column' style='margin-right: 10rpx'>
|
||||||
|
<view class='c-flex-row'>
|
||||||
|
<text class='goods-price accent-text-color'>
|
||||||
|
¥{{ ((goodsBean?.price || 0) * userInfo.userDiscount).toFixed(2) }}
|
||||||
|
<text v-if='userInfo.userDiscount>0&&userInfo.userDiscount<1'
|
||||||
|
style='display:unset;text-decoration: line-through;font-size: 30rpx;color: #999999'>
|
||||||
|
¥{{ goodsBean?.price || 0 }}
|
||||||
|
</text>
|
||||||
|
</text>
|
||||||
|
<text>销量{{ goodsBean?.salesCount || 0 }}</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class='c-flex-row'>
|
||||||
|
<text style='flex: 1'>{{ goodsBean?.name || '未知' }}</text>
|
||||||
|
<view class='share-button'>
|
||||||
|
<image :src='assetsUrl("ic_share.png")'></image>
|
||||||
|
<button class='btn' plain open-type='share'>分享</button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class='goods-sku-view c-flex-column'>
|
||||||
|
<view class='c-flex-row' @click.stop='showSkuDialog'>
|
||||||
|
<text>选择</text>
|
||||||
|
<text>规格 颜色/尺码</text>
|
||||||
|
<image :src='assetsUrl("ic_arrow_right_gray.png")' />
|
||||||
|
<text>共{{ getStockColorCount }}种颜色可选</text>
|
||||||
|
</view>
|
||||||
|
<view class='divider' style='width:auto;height: 0.5rpx;margin-left: 100rpx;display: none' />
|
||||||
|
<view class='c-flex-row' style='display: none' @click.stop='showSkuDialog'>
|
||||||
|
<text>参数</text>
|
||||||
|
<text>品牌 风格 季节 款号</text>
|
||||||
|
<image :src='assetsUrl("ic_arrow_right_gray.png")' />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class='recommend-view c-flex-column' v-if='(recommendList?.length||0)>0'>
|
||||||
|
<text>浏览此商品的客户还浏览了</text>
|
||||||
|
<scroll-view scroll-x>
|
||||||
|
<view style='display: inline-block' v-for='(item, index) in recommendList'
|
||||||
|
:key='index'>
|
||||||
|
<view class='recommend-item c-flex-column'>
|
||||||
|
<image :src='item.images||defaultImage' />
|
||||||
|
<text>{{ item.goodsName || '未知' }}</text>
|
||||||
|
<text class='goods-price'>{{ (item.price * userInfo.userDiscount).toFixed(2) }}
|
||||||
|
<text v-if='userInfo.userDiscount>0&&userInfo.userDiscount<1'
|
||||||
|
style='text-decoration: line-through;font-size: 25rpx;color: #999999'>{{ item.price }}
|
||||||
|
</text>
|
||||||
|
</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</scroll-view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class='goods-detail c-flex-column' style='display: none'>
|
||||||
|
<text>商品详情</text>
|
||||||
|
<image :src='assetsUrl("test_bg.png")' mode='aspectFill' />
|
||||||
|
<image :src='assetsUrl("test_bg.png")' mode='aspectFill' />
|
||||||
|
<image :src='assetsUrl("test_bg.png")' mode='aspectFill' />
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class='bottom-view c-flex-row'>
|
||||||
|
<view class='small-button-view' @click.stop='goBack'>
|
||||||
|
<view class='small-button-item'>
|
||||||
|
<image :src='assetsUrl("ic_goods_store.png")' />
|
||||||
|
<text>商家</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class='small-button-item' @click.stop='goPath("/pages/mine/subs/order/index")'>
|
||||||
|
<image :src='assetsUrl("ic_goods_order.png")' />
|
||||||
|
<text>订单</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class='small-button-item'>
|
||||||
|
<view class='shoppingcart-count' @click.stop='goPath("/pages/mall/subs/shoppingcart/index")'>
|
||||||
|
<image :src='assetsUrl("ic_goods_shoppingcart.png")' />
|
||||||
|
<text v-if='totalCount>0'>{{ totalCount }}</text>
|
||||||
|
</view>
|
||||||
|
<text>购物车</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class='primary-button-view c-flex-row'>
|
||||||
|
<view class='add-shoppingcart-button' @click.stop='addShoppingCart'>加入购物车</view>
|
||||||
|
<view class='place-order-button' @click.stop='placeOrder'>立即下单</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<sku-dialog ref='skuDialogRef' :bean='goodsBean' />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang='ts' setup>
|
||||||
|
import { assetsUrl, defaultImage } from '@/utils/assets';
|
||||||
|
import SkuDialog from '@/components/sku-dialog.vue';
|
||||||
|
import { goPath, showToast } from '@/utils';
|
||||||
|
import { getGoodsDetail, getGoodsList } from '@/api/goods';
|
||||||
|
import { GoodsBean } from '@/api/goods/types';
|
||||||
|
import useShoppingCartStore from '@/store/modules/shoppingcart';
|
||||||
|
import { useUserStore } from '@/store';
|
||||||
|
|
||||||
|
const shoppingCartStore = useShoppingCartStore();
|
||||||
|
const { totalCount } = storeToRefs(shoppingCartStore);
|
||||||
|
|
||||||
|
const userStore = useUserStore();
|
||||||
|
const { userInfo } = storeToRefs(userStore);
|
||||||
|
|
||||||
|
const goodsBean = ref<GoodsBean>();
|
||||||
|
const recommendList = ref<GoodsBean[]>();
|
||||||
|
|
||||||
|
const skuDialogRef = ref();
|
||||||
|
|
||||||
|
const bannerList = ref([]);
|
||||||
|
const swiperIndex = ref(0);
|
||||||
|
|
||||||
|
onLoad(async (e: any) => {
|
||||||
|
await uni.showLoading();
|
||||||
|
goodsBean.value = await getGoodsDetail(e.goodsId);
|
||||||
|
goodsBean.value.price = userStore.getRealGoodsPrice(goodsBean.value?.price, goodsBean.value?.priceExt);
|
||||||
|
const { rows } = await getGoodsList({
|
||||||
|
page: {
|
||||||
|
page: 1,
|
||||||
|
pageSize: 20,
|
||||||
|
bean: {
|
||||||
|
keyword: '',
|
||||||
|
typeIds: []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
recommendList.value = rows;
|
||||||
|
recommendList.value?.forEach(e => {
|
||||||
|
e.price = userStore.getRealGoodsPrice(e.price, e.priceExt);
|
||||||
|
});
|
||||||
|
uni.hideLoading();
|
||||||
|
});
|
||||||
|
|
||||||
|
onShareAppMessage((e) => {
|
||||||
|
return {
|
||||||
|
title: goodsBean.value?.name || 'VIP顾客中心',
|
||||||
|
path: `/pages/common/groupbuy/detail?id=${goodsBean.value?.id}&companyId=${getApp().globalData?.companyId}&storeId=${getApp().globalData?.storeId}`
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const getStockColorCount = computed(() => {
|
||||||
|
const list = Array.from(new Set(goodsBean.value?.stocks?.map(item => item.colorName)))
|
||||||
|
.map(colorName => goodsBean.value?.stocks?.find(item => item.colorName === colorName)!);
|
||||||
|
return list.length;
|
||||||
|
});
|
||||||
|
|
||||||
|
const swiperChange = (e: any) => {
|
||||||
|
swiperIndex.value = e.detail.current;
|
||||||
|
};
|
||||||
|
|
||||||
|
const goBack = () => {
|
||||||
|
uni.navigateBack();
|
||||||
|
};
|
||||||
|
|
||||||
|
const showSkuDialog = (fn: Function) => {
|
||||||
|
skuDialogRef.value.show(goodsBean.value?.id, fn);
|
||||||
|
};
|
||||||
|
|
||||||
|
const addShoppingCart = () => {
|
||||||
|
showSkuDialog((e: GoodsBean) => {
|
||||||
|
const index = shoppingCartStore.getSameGoodsIndex(goodsBean.value?.id || '', e.checkedStock?.colorId, e.checkedStock?.sizeId);
|
||||||
|
if(index >= 0) {
|
||||||
|
shoppingCartStore.updateCount(index, e.checkedStock?.count);
|
||||||
|
} else {
|
||||||
|
shoppingCartStore.save(e);
|
||||||
|
}
|
||||||
|
showToast('加入购物车成功');
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const placeOrder = () => {
|
||||||
|
showSkuDialog((e: GoodsBean) => {
|
||||||
|
const orderBean = {
|
||||||
|
totalPrice: (e.consumePrice * e.checkedStock.count).toFixed(2),
|
||||||
|
orderGoods: [e]
|
||||||
|
};
|
||||||
|
goPath(`/pages/mall/subs/order/order-confirm?orderBean=${encodeURIComponent(JSON.stringify(orderBean))}`);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang='scss' scoped>
|
||||||
|
.content {
|
||||||
|
padding-bottom: 200rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.swiper-container {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.swiper {
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
height: 750rpx;
|
||||||
|
|
||||||
|
image {
|
||||||
|
width: 100%;
|
||||||
|
height: 750rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.indicator {
|
||||||
|
background: rgba(1, 1, 1, 0.5);
|
||||||
|
border-radius: 45rpx;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #FFFFFF;
|
||||||
|
position: absolute;
|
||||||
|
right: 20rpx;
|
||||||
|
bottom: 20rpx;
|
||||||
|
padding: 5rpx 25rpx;
|
||||||
|
|
||||||
|
text:nth-of-type(1) {
|
||||||
|
font-size: 30rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
text:nth-of-type(2) {
|
||||||
|
font-size: 24rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.goods-info-view {
|
||||||
|
background: #FFFFFF;
|
||||||
|
padding: 20rpx 30rpx;
|
||||||
|
|
||||||
|
view:nth-of-type(1) {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
|
||||||
|
text:nth-of-type(1) {
|
||||||
|
display: flex;
|
||||||
|
font-size: 40rpx;
|
||||||
|
text-align: center;
|
||||||
|
align-items: flex-end;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.goods-price:before {
|
||||||
|
//content: "¥";
|
||||||
|
//font-size: 30rpx;
|
||||||
|
//margin-bottom: 5rpx;
|
||||||
|
//margin-right: 5rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
text:nth-of-type(2) {
|
||||||
|
font-size: 26rpx;
|
||||||
|
font-weight: 400;
|
||||||
|
color: #999999;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
view:nth-of-type(2) {
|
||||||
|
text {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 32rpx;
|
||||||
|
color: #333333;
|
||||||
|
margin-right: 10rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.share-button {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
image {
|
||||||
|
width: 36rpx;
|
||||||
|
height: 32rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
background: #00000000;
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #636566;
|
||||||
|
white-space: nowrap;
|
||||||
|
padding: 0;
|
||||||
|
border: none !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.goods-sku-view {
|
||||||
|
background: #FFFFFF;
|
||||||
|
padding: 20rpx 30rpx;
|
||||||
|
margin-top: 20rpx;
|
||||||
|
|
||||||
|
view:nth-of-type(n+1) {
|
||||||
|
position: relative;
|
||||||
|
align-items: center;
|
||||||
|
height: 85rpx;
|
||||||
|
|
||||||
|
text:nth-of-type(1) {
|
||||||
|
width: 100rpx;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #999999;
|
||||||
|
}
|
||||||
|
|
||||||
|
text:nth-of-type(2) {
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #333333;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
image {
|
||||||
|
width: 13rpx;
|
||||||
|
height: 24rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
text:nth-of-type(3) {
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #999999;
|
||||||
|
position: absolute;
|
||||||
|
top: 50rpx;
|
||||||
|
left: 100rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
view:nth-of-type(1) {
|
||||||
|
align-items: flex-start;
|
||||||
|
//padding-top: 20rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.recommend-view {
|
||||||
|
background: #FFFFFF;
|
||||||
|
padding: 20rpx 30rpx;
|
||||||
|
margin-top: 20rpx;
|
||||||
|
|
||||||
|
text {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #333333;
|
||||||
|
}
|
||||||
|
|
||||||
|
scroll-view {
|
||||||
|
width: 100%;
|
||||||
|
margin-top: 20rpx;
|
||||||
|
white-space: nowrap;
|
||||||
|
height: 300rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.recommend-item {
|
||||||
|
margin-right: 20rpx;
|
||||||
|
|
||||||
|
image {
|
||||||
|
width: 200rpx;
|
||||||
|
height: 200rpx;
|
||||||
|
border-radius: 10rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
text:nth-of-type(1) {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #333333;
|
||||||
|
margin-top: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
text:nth-of-type(2) {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #F32B2B;
|
||||||
|
}
|
||||||
|
|
||||||
|
.goods-price:before {
|
||||||
|
content: "¥";
|
||||||
|
font-size: 28rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.bottom-view {
|
||||||
|
background: #FFFFFF;
|
||||||
|
padding: 20rpx 30rpx 78rpx 33rpx;
|
||||||
|
position: fixed;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
|
||||||
|
.small-button-view {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
flex: 1;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-right: 35rpx;
|
||||||
|
|
||||||
|
.small-button-item {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
image {
|
||||||
|
width: 34rpx;
|
||||||
|
height: 34rpx;
|
||||||
|
margin-bottom: 10rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
text {
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 20rpx;
|
||||||
|
color: #333333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shoppingcart-count {
|
||||||
|
display: flex;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
text {
|
||||||
|
display: flex;
|
||||||
|
box-sizing: border-box;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
position: absolute;
|
||||||
|
top: -15rpx;
|
||||||
|
right: -20rpx;
|
||||||
|
min-width: 35rpx;
|
||||||
|
min-height: 30rpx;
|
||||||
|
background: #F32B2B;
|
||||||
|
color: #FFFFFF;
|
||||||
|
padding: 2rpx;
|
||||||
|
border-radius: 50%;
|
||||||
|
border: 2rpx solid #FFFFFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.primary-button-view {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 30rpx;
|
||||||
|
|
||||||
|
.add-shoppingcart-button {
|
||||||
|
display: flex;
|
||||||
|
width: 224rpx;
|
||||||
|
height: 80rpx;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
background: #FFE2E2;
|
||||||
|
color: #F32B2B;
|
||||||
|
border-radius: 40rpx 0 0 40rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.place-order-button {
|
||||||
|
display: flex;
|
||||||
|
width: 198rpx;
|
||||||
|
height: 80rpx;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
background: #F32B2B;
|
||||||
|
color: #FFFFFF;
|
||||||
|
border-radius: 0 40rpx 40rpx 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.goods-detail {
|
||||||
|
background: #FFFFFF;
|
||||||
|
margin-top: 20rpx;
|
||||||
|
|
||||||
|
text {
|
||||||
|
margin: 20rpx 30rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #333333;
|
||||||
|
}
|
||||||
|
|
||||||
|
image {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
550
src/pages/mall/subs/order/order-confirm.vue
Normal file
550
src/pages/mall/subs/order/order-confirm.vue
Normal file
@@ -0,0 +1,550 @@
|
|||||||
|
<template>
|
||||||
|
<scroll-view scroll-y>
|
||||||
|
<view class='content'>
|
||||||
|
<view class='c-flex-row'>
|
||||||
|
<view class='tab c-flex-row' :class='{"tab-active": tabIndex === 0}' @click.stop='tabIndex=0'>
|
||||||
|
<image :src='assetsUrl("ic_order_dd.png")' />
|
||||||
|
<text>到店</text>
|
||||||
|
</view>
|
||||||
|
<view class='tab c-flex-row' :class='{"tab-active": tabIndex === 1}' @click.stop='tabIndex=1'>
|
||||||
|
<image :src='assetsUrl("ic_order_yj.png")' />
|
||||||
|
<text>邮寄</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view v-show='tabIndex==1' class='address-view c-flex-column'
|
||||||
|
@click.stop='goPath("/pages/mine/subs/address/index")'>
|
||||||
|
|
||||||
|
<view v-if='deliveryAddress?.addrid'>
|
||||||
|
<view class='user-info c-flex-row'>
|
||||||
|
<text class='status' v-if='deliveryAddress?.defaultstatus==1'>默认</text>
|
||||||
|
<text>{{ deliveryAddress?.name }}</text>
|
||||||
|
<text>{{ deliveryAddress?.mobile }}</text>
|
||||||
|
<view style='flex: 1' />
|
||||||
|
<image :src='assetsUrl("ic_arrow_right_gray.png")' />
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class='addr c-flex-row'>
|
||||||
|
<image :src='assetsUrl("ic_location.png")' />
|
||||||
|
<text>{{ deliveryAddress?.addr }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view v-else class='user-info c-flex-row'>
|
||||||
|
<text style='flex: 1'>请选择收货地址</text>
|
||||||
|
<image :src='assetsUrl("ic_arrow_right_gray.png")' />
|
||||||
|
</view>
|
||||||
|
<image class='dashed-line' :src='assetsUrl("ic_address_dashed_line.png")' />
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class='goods-info-view c-flex-column'>
|
||||||
|
<view class='c-flex-row' style='margin-bottom: 20rpx' v-for='(item,index) in orderBean?.orderGoods'
|
||||||
|
:key='index'>
|
||||||
|
<image class='goods-image' :src='item.images||defaultImage' />
|
||||||
|
<view class='c-flex-column' style='flex: 1;'>
|
||||||
|
<view class='c-flex-row'>
|
||||||
|
<text class='goods-name'>{{ item.name || '未知' }}</text>
|
||||||
|
</view>
|
||||||
|
<text style='color: #999999;margin-top: 30rpx'>
|
||||||
|
{{ item.code }}
|
||||||
|
</text>
|
||||||
|
<view class='bottom-sku-view c-flex-row'>
|
||||||
|
<text>
|
||||||
|
{{ item.checkedStock.colorName || '均色' }},{{ item.checkedStock.sizeName || '均码' }}
|
||||||
|
x{{ item.checkedStock.count }}
|
||||||
|
</text>
|
||||||
|
<text>¥{{ item.price }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class='divider' />
|
||||||
|
|
||||||
|
<view class='remark-view c-flex-row'>
|
||||||
|
<text>备注</text>
|
||||||
|
<input placeholder='请填写订单备注' @input='orderBean!.remark = $event.detail.value' />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class='card-view'>
|
||||||
|
<view class='c-flex-row'>
|
||||||
|
<text class='card-view-title'>商品总价</text>
|
||||||
|
<text class='card-view-value'>¥{{ orderBean?.totalPrice || 0 }}</text>
|
||||||
|
</view>
|
||||||
|
<view class='c-flex-row' style='display: none'>
|
||||||
|
<text class='card-view-title'>运费</text>
|
||||||
|
<text class='card-view-value'>¥0</text>
|
||||||
|
</view>
|
||||||
|
<view class='c-flex-row' @click.stop='showCouponDialog'>
|
||||||
|
<text class='card-view-title'>优惠券
|
||||||
|
<text style='font-size: 22rpx;color: #F32B2B;'>已选最大优惠</text>
|
||||||
|
</text>
|
||||||
|
<view class='card-view-value' style='color: #F32B2B;margin: 0'>-¥{{ checkedCoupon?.reduce || 0 }}
|
||||||
|
<image :src='assetsUrl("ic_arrow_right_gray.png")' />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class='divider' />
|
||||||
|
<view class='c-flex-row'>
|
||||||
|
<view style='flex: 1' />
|
||||||
|
<view class='c-flex-row'>
|
||||||
|
<text class='card-view-value'>共1件商品 合计:
|
||||||
|
<text style='font-size: 34rpx;color:#F32B2B'>¥{{ totalPrice || 0 }}</text>
|
||||||
|
</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class='payment-way c-flex-row' @click.stop='changePayment'>
|
||||||
|
<text>支付方式</text>
|
||||||
|
<view>{{ paymentType === 0 ? '微信支付' : '余额' }}
|
||||||
|
<image style='display: none' :src='assetsUrl("ic_arrow_right_gray.png")' />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class='bottom-view c-flex-row'>
|
||||||
|
<text>合计</text>
|
||||||
|
<text>¥{{ totalPrice || 0 }}</text>
|
||||||
|
<sqb-pay @navigateTo='navigateTo'
|
||||||
|
:return_url='buildSqbParams.return_url'
|
||||||
|
:total_amount='buildSqbParams.total_amount'
|
||||||
|
:terminal_sn='buildSqbParams.terminal_sn'
|
||||||
|
:client_sn='buildSqbParams.client_sn'
|
||||||
|
:subject='buildSqbParams.subject'
|
||||||
|
:subject_img='buildSqbParams.subject_img '
|
||||||
|
:merchant_name='buildSqbParams.merchant_name'
|
||||||
|
:notify_url='buildSqbParams.notify_url'
|
||||||
|
:sign='buildSqbParams.sign'>
|
||||||
|
<button class='confirm-order' @click='createOrder'>确认订单</button>
|
||||||
|
</sqb-pay>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</scroll-view>
|
||||||
|
<payment-dialog ref='paymentDialogRef' @change='args => paymentType=args' />
|
||||||
|
<coupon-dialog ref='couponDialogRef' @confirm='confirmCoupon' :order-price='orderBean?.totalPrice' />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang='ts' setup>
|
||||||
|
import { assetsUrl, defaultImage } from '@/utils/assets';
|
||||||
|
import PaymentDialog from '@/components/payment-dialog.vue';
|
||||||
|
import CouponDialog from '@/pages/mall/subs/components/coupon-dialog.vue';
|
||||||
|
import { goPath, parseParameter, showToast, sortASCII } from '@/utils';
|
||||||
|
import { hexMD5 } from '@/utils/common/md5';
|
||||||
|
import { getPaymentList, orderCreate, overPayment } from '@/api/order';
|
||||||
|
import { CouponBean } from '@/api/user/types';
|
||||||
|
import { OrderBean } from '@/api/order/types';
|
||||||
|
import { useUserStore } from '@/store';
|
||||||
|
import { handlePayResult } from '@/utils/order';
|
||||||
|
import useShoppingCartStore from '@/store/modules/shoppingcart';
|
||||||
|
|
||||||
|
const userStore = useUserStore();
|
||||||
|
const { userInfo, terminalInfo, deliveryAddress } = storeToRefs(userStore);
|
||||||
|
const shoppingCartStore = useShoppingCartStore();
|
||||||
|
|
||||||
|
const couponDialogRef = ref();
|
||||||
|
const paymentDialogRef = ref();
|
||||||
|
const paymentType = ref(0);
|
||||||
|
const tabIndex = ref(0);
|
||||||
|
|
||||||
|
const checkedCoupon = ref<CouponBean>();
|
||||||
|
|
||||||
|
const orderBean = ref<OrderBean>();
|
||||||
|
|
||||||
|
onLoad((e) => {
|
||||||
|
orderBean.value = JSON.parse(decodeURIComponent(e?.orderBean));
|
||||||
|
createOrder();
|
||||||
|
});
|
||||||
|
|
||||||
|
const totalPrice = computed(() => {
|
||||||
|
return (orderBean?.value?.totalPrice || 0) - (checkedCoupon.value?.reduce || 0);
|
||||||
|
});
|
||||||
|
|
||||||
|
const buildSqbParams = computed(() => {
|
||||||
|
const params = sortASCII({
|
||||||
|
client_sn: orderBean.value?.id || '',
|
||||||
|
return_url: '/pages/common/payresult/index',
|
||||||
|
total_amount: Number(((totalPrice.value || 0) * 100).toFixed(2)),
|
||||||
|
terminal_sn: terminalInfo.value?.terminalSn,
|
||||||
|
subject: orderBean?.value?.orderGoods[0].name || '未知',
|
||||||
|
subject_img: orderBean?.value?.orderGoods[0].images || '',
|
||||||
|
merchant_name: terminalInfo.value?.companyName,
|
||||||
|
notify_url: 'https://www.baidu.com'
|
||||||
|
}, true);
|
||||||
|
|
||||||
|
return {
|
||||||
|
...params,
|
||||||
|
sign: hexMD5(parseParameter(params) + '&key=' + terminalInfo.value?.terminalKey).toUpperCase()
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const changePayment = () => {
|
||||||
|
// paymentDialogRef.value.show();
|
||||||
|
};
|
||||||
|
|
||||||
|
const showCouponDialog = () => {
|
||||||
|
couponDialogRef.value.show();
|
||||||
|
};
|
||||||
|
|
||||||
|
const confirmCoupon = (item: CouponBean) => {
|
||||||
|
checkedCoupon.value = item;
|
||||||
|
createOrder();
|
||||||
|
};
|
||||||
|
const navigateTo = (e: any) => {
|
||||||
|
handlePayResult(orderBean.value?.id, e, {
|
||||||
|
onSuccess: () => {
|
||||||
|
console.log('pay success');
|
||||||
|
payment();
|
||||||
|
},
|
||||||
|
onFailure: () => {
|
||||||
|
console.error('pay onFailure');
|
||||||
|
if(orderBean.value?.id) {
|
||||||
|
orderBean.value.id = '';
|
||||||
|
}
|
||||||
|
createOrder();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const createOrder = async () => {
|
||||||
|
if(!terminalInfo.value) {
|
||||||
|
showToast('当前店铺未配置收款渠道,请联系商家');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//邮寄
|
||||||
|
if(tabIndex.value == 1 && !deliveryAddress.value.addrid) {
|
||||||
|
showToast('请选择收货地址');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const params = {
|
||||||
|
// 'discount': 0,
|
||||||
|
// 'freePrice': 0,
|
||||||
|
'reducePrice': checkedCoupon.value == undefined ? 0 : checkedCoupon.value?.reduce,
|
||||||
|
'totalPrice': totalPrice.value,
|
||||||
|
// 'integral': 0,
|
||||||
|
// 'allowIntegral': 0,
|
||||||
|
// 'produceIntegralNumber': 0,
|
||||||
|
'couponIds': checkedCoupon.value?.id,
|
||||||
|
'remark': orderBean.value?.remark,
|
||||||
|
'address': tabIndex.value == 0 ? undefined : JSON.stringify(deliveryAddress.value),
|
||||||
|
'orderGoods': orderBean?.value?.orderGoods?.map(item => (
|
||||||
|
{
|
||||||
|
'goodsId': item.id,
|
||||||
|
'goodsCode': item.code,
|
||||||
|
'goodsNum': item.checkedStock.count,
|
||||||
|
'stockId': item.checkedStock.stockId,
|
||||||
|
'originPrice': item.price,
|
||||||
|
// 'consumePrice': item.price * ((userInfo.value?.levelEntity?.discount || 0) / 100),
|
||||||
|
'consumePrice': item.consumePrice,
|
||||||
|
'discount': userInfo.value?.levelEntity?.discount || 0
|
||||||
|
// 'discountOriginPrice': 0,
|
||||||
|
// 'produceIntegral': 0,
|
||||||
|
// 'priceModify': [0],
|
||||||
|
// 'offset': 0
|
||||||
|
}
|
||||||
|
))
|
||||||
|
};
|
||||||
|
|
||||||
|
if(orderBean.value?.id == undefined || orderBean.value?.id == '') {
|
||||||
|
await uni.showLoading();
|
||||||
|
const result = await orderCreate(params);
|
||||||
|
orderBean.value!.id = result.id;
|
||||||
|
uni.hideLoading();
|
||||||
|
}
|
||||||
|
|
||||||
|
//删除购物车已存在商品
|
||||||
|
orderBean?.value?.orderGoods?.forEach(item => {
|
||||||
|
const index = shoppingCartStore.getSameGoodsIndex(item.id, item.checkedStock.colorId, item.checkedStock.sizeId);
|
||||||
|
if(index >= 0) {
|
||||||
|
shoppingCartStore.delete(index);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const payment = async () => {
|
||||||
|
await uni.showLoading();
|
||||||
|
const paymentList = await getPaymentList(orderBean.value?.id || '');
|
||||||
|
const paymentParams = {
|
||||||
|
orderId: orderBean?.value?.id,
|
||||||
|
produceIntegralNumber: Math.round((orderBean?.value?.totalPrice || 0) + (orderBean?.value?.useGold || 0)),
|
||||||
|
transactionPrice: orderBean?.value?.totalPrice,
|
||||||
|
useGold: orderBean.value?.useGold || 0,
|
||||||
|
detailBos: [{
|
||||||
|
integralNumber: Math.floor(orderBean?.value?.totalPrice || 0),
|
||||||
|
onlinePayResult: '',
|
||||||
|
payName: '收钱吧',
|
||||||
|
payTypeId: paymentList.find((res: any) => res.type === 'ShouQianBa')?.id,
|
||||||
|
transactionPrice: Number(orderBean?.value?.totalPrice)
|
||||||
|
}]
|
||||||
|
};
|
||||||
|
await overPayment(paymentParams);
|
||||||
|
showToast('支付成功', {
|
||||||
|
icon: 'success',
|
||||||
|
complete: () => {
|
||||||
|
uni.navigateBack();
|
||||||
|
uni.hideLoading();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang='scss' scoped>
|
||||||
|
.content {
|
||||||
|
padding: 20rpx 30rpx 200rpx 30rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab {
|
||||||
|
height: 63rpx;
|
||||||
|
background: #E8E8E8;
|
||||||
|
border-radius: 10rpx 0 10rpx 0;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
margin-top: 17rpx;
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
|
text {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #333333;
|
||||||
|
margin-left: 10rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab:nth-of-type(1) {
|
||||||
|
border-radius: 10rpx 0 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab:nth-of-type(2) {
|
||||||
|
border-radius: 0 10rpx 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-active {
|
||||||
|
background: #FFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab:nth-of-type(1) image {
|
||||||
|
width: 42rpx;
|
||||||
|
height: 42rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab:nth-of-type(2) image {
|
||||||
|
width: 38rpx;
|
||||||
|
height: 29rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.address-view {
|
||||||
|
padding-top: 38rpx;
|
||||||
|
background: #FFFFFF;
|
||||||
|
|
||||||
|
.user-info {
|
||||||
|
margin-left: 20rpx;
|
||||||
|
margin-right: 20rpx;
|
||||||
|
|
||||||
|
.status {
|
||||||
|
padding: 2rpx 10rpx;
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #F32B2B;
|
||||||
|
border-radius: 5rpx;
|
||||||
|
border: 1rpx solid #F32B2B;
|
||||||
|
margin-right: 12rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
text:nth-of-type(n+2) {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #333333;
|
||||||
|
margin-left: 10rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
image {
|
||||||
|
width: 8rpx;
|
||||||
|
height: 16rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.addr {
|
||||||
|
margin-top: 15rpx;
|
||||||
|
margin-left: 20rpx;
|
||||||
|
|
||||||
|
image {
|
||||||
|
width: 30rpx;
|
||||||
|
height: 37rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
text {
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 26rpx;
|
||||||
|
color: #999999;
|
||||||
|
margin-left: 16rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.dashed-line {
|
||||||
|
width: 100%;
|
||||||
|
height: 8rpx;
|
||||||
|
margin-top: 37rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.goods-info-view {
|
||||||
|
display: flex;
|
||||||
|
position: relative;
|
||||||
|
background: #FFFFFF;
|
||||||
|
margin-top: 20rpx;
|
||||||
|
border-radius: 10rpx;
|
||||||
|
padding: 30rpx 20rpx;
|
||||||
|
|
||||||
|
.goods-image {
|
||||||
|
width: 180rpx;
|
||||||
|
height: 180rpx;
|
||||||
|
border-radius: 10rpx;
|
||||||
|
margin-right: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.goods-name {
|
||||||
|
font-size: 30rpx;
|
||||||
|
font-weight: 400;
|
||||||
|
-webkit-line-clamp: 2;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
overflow: hidden;
|
||||||
|
margin-right: 20rpx;
|
||||||
|
color: #333333;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bottom-sku-view {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-top: 10rpx;
|
||||||
|
|
||||||
|
text:nth-of-type(1) {
|
||||||
|
font-size: 26rpx;
|
||||||
|
font-weight: 400;
|
||||||
|
flex: 1;
|
||||||
|
color: #999999;
|
||||||
|
}
|
||||||
|
|
||||||
|
text:nth-of-type(2) {
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #333333;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-right: 5rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
text:nth-of-type(3) {
|
||||||
|
font-size: 34rpx;
|
||||||
|
color: #333333;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.divider {
|
||||||
|
margin: 30rpx 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.remark-view {
|
||||||
|
text {
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #333333;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
min-width: 200rpx;
|
||||||
|
font-weight: 400;
|
||||||
|
text-align: right;
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #333333;
|
||||||
|
z-index: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-view {
|
||||||
|
margin-top: 20rpx;
|
||||||
|
padding: 0 25rpx 0 23rpx;
|
||||||
|
|
||||||
|
view:not(.divider):nth-of-type(n+1) {
|
||||||
|
margin: 20rpx 0;
|
||||||
|
|
||||||
|
.card-view-title {
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #333333;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-view-value {
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 26rpx;
|
||||||
|
color: #333333;
|
||||||
|
|
||||||
|
image {
|
||||||
|
width: 8rpx;
|
||||||
|
height: 16rpx;
|
||||||
|
margin-left: 16rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.payment-way {
|
||||||
|
background: #FFFFFF;
|
||||||
|
border-radius: 10rpx;
|
||||||
|
padding: 22rpx 23rpx;
|
||||||
|
margin-top: 20rpx;
|
||||||
|
|
||||||
|
text:nth-of-type(1) {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #333333;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
view:nth-of-type(1) {
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #333333;
|
||||||
|
|
||||||
|
image {
|
||||||
|
width: 8rpx;
|
||||||
|
height: 16rpx;
|
||||||
|
margin-left: 13rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.bottom-view {
|
||||||
|
background: #FFFFFF;
|
||||||
|
position: fixed;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
padding: 20rpx 30rpx 78rpx 30rpx;
|
||||||
|
|
||||||
|
text:nth-of-type(1) {
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #333333;
|
||||||
|
}
|
||||||
|
|
||||||
|
text:nth-of-type(2) {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 36rpx;
|
||||||
|
color: #F32B2B;
|
||||||
|
margin-left: 14rpx;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
sqb-pay .confirm-order {
|
||||||
|
display: flex;
|
||||||
|
padding: 0 45rpx;
|
||||||
|
height: 80rpx;
|
||||||
|
border: 2rpx solid #F32B2B;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #F32B2B;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
background: #FFFFFF;
|
||||||
|
border-radius: 40rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
145
src/pages/mall/subs/search/index.vue
Normal file
145
src/pages/mall/subs/search/index.vue
Normal file
@@ -0,0 +1,145 @@
|
|||||||
|
<template>
|
||||||
|
<view class='content'>
|
||||||
|
<view class='search-view'>
|
||||||
|
<view class='search-input'>
|
||||||
|
<image :src='assetsUrl("ic_search.png")' />
|
||||||
|
<input placeholder='输入名称、款号搜索' @input='bindInput' />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<scroll-view class='goods-list'>
|
||||||
|
<grid-view :cross-axis-count='2'>
|
||||||
|
<view v-for='(item, index) in goodsList' :key='index' class='goods-item'
|
||||||
|
@click.stop='goPath(`/pages/mall/subs/goods/detail?goodsId=${item.goodsId}`)'>
|
||||||
|
<image class='goods-image' :src='item.images||defaultImage' />
|
||||||
|
<text class='goods-name'>{{ item.goodsName || '未知' }}</text>
|
||||||
|
<text class='goods-price'>¥{{ (item.price * userInfo.userDiscount).toFixed(2) }}
|
||||||
|
<text v-if='userInfo.userDiscount>0&&userInfo.userDiscount<1'
|
||||||
|
style='text-decoration: line-through;color: #999999;font-size: 25rpx'>¥{{ item.price }}
|
||||||
|
</text>
|
||||||
|
</text>
|
||||||
|
<image class='add-image' :src='assetsUrl("ic_add_goods.png")' @click.stop='addShoppingCart(item)' />
|
||||||
|
</view>
|
||||||
|
</grid-view>
|
||||||
|
</scroll-view>
|
||||||
|
</view>
|
||||||
|
<sku-dialog ref='skuDialogRef' />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang='ts' setup>
|
||||||
|
import SkuDialog from '@/components/sku-dialog.vue';
|
||||||
|
import { assetsUrl, defaultImage } from '@/utils/assets';
|
||||||
|
import { goPath } from '@/utils';
|
||||||
|
import { getGoodsList } from '@/api/goods';
|
||||||
|
import useShoppingCartStore from '@/store/modules/shoppingcart';
|
||||||
|
import { GoodsBean } from '@/api/goods/types';
|
||||||
|
import { useUserStore } from '@/store';
|
||||||
|
|
||||||
|
const skuDialogRef = ref();
|
||||||
|
const shoppingCartStore = useShoppingCartStore();
|
||||||
|
|
||||||
|
const userStore = useUserStore();
|
||||||
|
const { userInfo } = storeToRefs(userStore);
|
||||||
|
|
||||||
|
const goodsList = ref<GoodsBean[]>([]);
|
||||||
|
|
||||||
|
onLoad((e) => {
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
const bindInput = async (e: any) => {
|
||||||
|
const { rows } = await getGoodsList({
|
||||||
|
page: {
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 100,
|
||||||
|
bean: {
|
||||||
|
keyword: e.detail.value,
|
||||||
|
typeIds: []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
goodsList.value = rows;
|
||||||
|
};
|
||||||
|
|
||||||
|
const addShoppingCart = (goodsBean: GoodsBean) => {
|
||||||
|
skuDialogRef.value.show(goodsBean.goodsId, (e: GoodsBean) => {
|
||||||
|
shoppingCartStore.save(e);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang='scss' scoped>
|
||||||
|
.content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
height: 100vh;
|
||||||
|
padding: 0 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-view {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
background: white;
|
||||||
|
padding: 19rpx 30rpx;
|
||||||
|
|
||||||
|
.search-input {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
background: #F7F7F7;
|
||||||
|
padding: 17rpx 23rpx;
|
||||||
|
font-size: 26rpx;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
image {
|
||||||
|
width: 32rpx;
|
||||||
|
height: 32rpx;
|
||||||
|
margin-right: 20rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.goods-list {
|
||||||
|
display: flex;
|
||||||
|
background: white;
|
||||||
|
|
||||||
|
.goods-item {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
position: relative;
|
||||||
|
padding: 10rpx 10rpx;
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
|
.goods-image {
|
||||||
|
border-radius: 10rpx;
|
||||||
|
width: 100%;
|
||||||
|
max-height: 400rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.goods-name {
|
||||||
|
font-size: 28rpx;
|
||||||
|
font-weight: 400;
|
||||||
|
color: #333333;
|
||||||
|
-webkit-line-clamp: 1;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
margin-top: 10rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.goods-price {
|
||||||
|
font-size: 36rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #F32B2B;
|
||||||
|
}
|
||||||
|
|
||||||
|
.add-image {
|
||||||
|
width: 42rpx;
|
||||||
|
height: 42rpx;
|
||||||
|
position: absolute;
|
||||||
|
bottom: 10rpx;
|
||||||
|
right: 10rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
333
src/pages/mall/subs/shoppingcart/index.vue
Normal file
333
src/pages/mall/subs/shoppingcart/index.vue
Normal file
@@ -0,0 +1,333 @@
|
|||||||
|
<template>
|
||||||
|
<view class='content'>
|
||||||
|
<view class='c-flex-row'>
|
||||||
|
<text class='manage' @click.stop='isEditMode = !isEditMode' :style='isEditMode?"color:#F32B2B":"color:#333333"'>
|
||||||
|
{{ isEditMode ? '退出管理' : '管理' }}
|
||||||
|
</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class='card-view' v-if='totalCount>0'>
|
||||||
|
<scroll-view>
|
||||||
|
<view class='c-flex-column' v-for='(item, index) in shoppingCartList' :key='index'>
|
||||||
|
<view class='c-flex-row'>
|
||||||
|
<image class='checkbox'
|
||||||
|
:src='assetsUrl(item.checked?"ic_checkbox_active_red.png":"ic_checkbox_normal.png")'
|
||||||
|
@click.stop='handleCheck(item)' />
|
||||||
|
<image class='goods-image' :src='item.images||defaultImage' />
|
||||||
|
<view class='c-flex-column'>
|
||||||
|
<text>{{ item.name }}</text>
|
||||||
|
<view class='c-flex-row'>
|
||||||
|
<view class='sku-view' @click.stop='showSkuDialog(index)'>
|
||||||
|
<text>{{ item?.checkedStock?.colorName||'均色' }},{{ item?.checkedStock?.sizeName||'均码' }}
|
||||||
|
x{{ item?.checkedStock?.count }}
|
||||||
|
</text>
|
||||||
|
<image :src='assetsUrl("ic_arrow_down_gray.png")' />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<text style='margin-top: 50rpx'>
|
||||||
|
¥{{ (item?.price * userInfo.userDiscount).toFixed(2) }}
|
||||||
|
<text v-if='userInfo.userDiscount>0&&userInfo.userDiscount<1'
|
||||||
|
style='text-decoration: line-through;color: #999999;font-size: 25rpx'>¥{{ item?.price }}
|
||||||
|
</text>
|
||||||
|
</text>
|
||||||
|
<view class='count-change-view c-flex-row'>
|
||||||
|
<view class='count-image' @click.stop='countChange(index,false)'>
|
||||||
|
<image :src='assetsUrl("ic_reduce.png")' />
|
||||||
|
</view>
|
||||||
|
<text>{{ item?.checkedStock?.count || 0 }}</text>
|
||||||
|
<view class='count-image' @click.stop='countChange(index,true)'>
|
||||||
|
<image :src='assetsUrl("ic_plus.png")' />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</scroll-view>
|
||||||
|
</view>
|
||||||
|
<u-empty v-else text='暂无数据' margin-top='100' />
|
||||||
|
|
||||||
|
<view class='bottom-view c-flex-row'>
|
||||||
|
<view class='c-flex-row' @click.stop='handleAllCheck'>
|
||||||
|
<image :src='assetsUrl(checkedAll?"ic_checkbox_active.png":"ic_checkbox_normal.png")' />
|
||||||
|
<text>全选</text>
|
||||||
|
</view>
|
||||||
|
<view style='flex: 1' />
|
||||||
|
|
||||||
|
<text v-if='isEditMode' class='settlement' @click.stop='deleteShoppingCart'>删除</text>
|
||||||
|
<view v-else class='c-flex-row'>
|
||||||
|
<text>合计:
|
||||||
|
<text>¥{{ totalPayPrice.toFixed(2) }}</text>
|
||||||
|
</text>
|
||||||
|
<text class='settlement' @click.stop='settlement'>结算</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<sku-dialog ref='skuDialogRef' :bean='temporaryGoodsBean' :exists='temporaryStockBean' />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang='ts' setup>
|
||||||
|
|
||||||
|
import { assetsUrl, defaultImage } from '@/utils/assets';
|
||||||
|
import useShoppingCartStore from '@/store/modules/shoppingcart';
|
||||||
|
import { goPath, showToast } from '@/utils';
|
||||||
|
import { GoodsBean, StockBean } from '@/api/goods/types';
|
||||||
|
import SkuDialog from '@/components/sku-dialog.vue';
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import { useUserStore } from '@/store';
|
||||||
|
|
||||||
|
const isEditMode = ref(false);
|
||||||
|
const checkedAll = ref(false);
|
||||||
|
|
||||||
|
const shoppingCartStore = useShoppingCartStore();
|
||||||
|
const { shoppingCartList, totalCount } = storeToRefs(shoppingCartStore);
|
||||||
|
|
||||||
|
const userStore = useUserStore();
|
||||||
|
const { userInfo } = storeToRefs(userStore);
|
||||||
|
|
||||||
|
const skuDialogRef = ref();
|
||||||
|
const temporaryGoodsBean = ref<GoodsBean>();
|
||||||
|
const temporaryStockBean = ref<StockBean>();
|
||||||
|
|
||||||
|
const totalPayPrice = computed(() => {
|
||||||
|
return shoppingCartList.value.filter(res => res.checked).reduce((a, b) => a + b.consumePrice * b.checkedStock.count, 0) || 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleCheck = (item: any) => {
|
||||||
|
item.checked = !item.checked;
|
||||||
|
if(!item.checked) {
|
||||||
|
checkedAll.value = false;
|
||||||
|
} else {
|
||||||
|
checkedAll.value = shoppingCartList.value.every(res => res.checked);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleAllCheck = () => {
|
||||||
|
checkedAll.value = !checkedAll.value;
|
||||||
|
shoppingCartList.value.forEach(res => {
|
||||||
|
res.checked = checkedAll.value;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const deleteShoppingCart = () => {
|
||||||
|
shoppingCartStore.deleteIfChecked();
|
||||||
|
checkedAll.value = false;
|
||||||
|
isEditMode.value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
const showSkuDialog = (index: number) => {
|
||||||
|
new Promise((resolve, _) => {
|
||||||
|
temporaryGoodsBean.value = shoppingCartList.value[index];
|
||||||
|
temporaryStockBean.value = shoppingCartList.value[index].checkedStock;
|
||||||
|
resolve(temporaryGoodsBean.value);
|
||||||
|
}).then((res: any) => {
|
||||||
|
skuDialogRef.value.show(res.id, (e: GoodsBean) => {
|
||||||
|
//重新选择sku后判断当前购物中是否存在相同sku的商品
|
||||||
|
const existsIndex = shoppingCartStore.getSameGoodsIndex(res?.id || '', e.checkedStock.colorId, e.checkedStock.sizeId);
|
||||||
|
//不存在则更新当前商品sku
|
||||||
|
if(existsIndex < 0) {
|
||||||
|
shoppingCartStore.updateStock(index, e.checkedStock);
|
||||||
|
}
|
||||||
|
//如果已存在,则更新已存在商品数量,并删除当前商品
|
||||||
|
else {
|
||||||
|
shoppingCartStore.updateCount(existsIndex, e.checkedStock.count - (temporaryGoodsBean?.value?.checkedStock?.count || 0));
|
||||||
|
if(existsIndex != index) {
|
||||||
|
shoppingCartStore.delete(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const countChange = (index: number, isPlus: Boolean) => {
|
||||||
|
if(isPlus) {
|
||||||
|
shoppingCartStore.updateCount(index, 1);
|
||||||
|
} else {
|
||||||
|
if(shoppingCartList.value[index].checkedStock.count > 1) {
|
||||||
|
shoppingCartStore.updateCount(index, -1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const settlement = () => {
|
||||||
|
if(shoppingCartList.value.filter(res => res.checked).length == 0) {
|
||||||
|
showToast('请选择商品');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const orderBean = {
|
||||||
|
totalPrice: totalPayPrice.value,
|
||||||
|
orderGoods: shoppingCartList.value.filter(res => res.checked)
|
||||||
|
};
|
||||||
|
goPath(`/pages/mall/subs/order/order-confirm?orderBean=${encodeURIComponent(JSON.stringify(orderBean))}`);
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang='scss' scoped>
|
||||||
|
.content {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.manage {
|
||||||
|
width: 100%;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #333333;
|
||||||
|
background: #FFFFFF;
|
||||||
|
align-self: flex-end;
|
||||||
|
padding: 20rpx 30rpx;
|
||||||
|
text-align: end;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-view {
|
||||||
|
margin: 30rpx 30rpx 180rpx 30rpx;
|
||||||
|
border-radius: 10rpx;
|
||||||
|
background: #FFFFFF;
|
||||||
|
padding: 10rpx 20rpx 10rpx 17rpx;
|
||||||
|
|
||||||
|
.c-flex-column:nth-of-type(1) {
|
||||||
|
margin: 20rpx 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
view:nth-of-type(1) {
|
||||||
|
.checkbox {
|
||||||
|
width: 35rpx;
|
||||||
|
height: 35rpx;
|
||||||
|
margin-right: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.goods-image {
|
||||||
|
width: 186rpx;
|
||||||
|
height: 186rpx;
|
||||||
|
border-radius: 10rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.c-flex-column {
|
||||||
|
flex: 1;
|
||||||
|
height: 186rpx;
|
||||||
|
margin-left: 20rpx;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
text:nth-of-type(1) {
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #333333;
|
||||||
|
-webkit-line-clamp: 2;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sku-view {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
position: relative;
|
||||||
|
background: #F2F2F2;
|
||||||
|
margin-top: 10rpx;
|
||||||
|
align-items: center;
|
||||||
|
border-radius: 22rpx;
|
||||||
|
padding: 5rpx 20rpx;
|
||||||
|
|
||||||
|
text {
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #999999;
|
||||||
|
}
|
||||||
|
|
||||||
|
image {
|
||||||
|
width: 20rpx;
|
||||||
|
height: 20rpx;
|
||||||
|
margin-left: 13rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
text:nth-of-type(2) {
|
||||||
|
display: flex;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 32rpx;
|
||||||
|
color: #333333;
|
||||||
|
margin-top: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.count-change-view {
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
|
||||||
|
.count-image {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 54rpx;
|
||||||
|
height: 54rpx;
|
||||||
|
background: #FBFBFB;
|
||||||
|
|
||||||
|
image {
|
||||||
|
width: 15rpx;
|
||||||
|
height: 2rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.count-image:nth-of-type(2) image {
|
||||||
|
width: 17rpx;
|
||||||
|
height: 17rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
text {
|
||||||
|
display: flex;
|
||||||
|
width: 54rpx;
|
||||||
|
height: 54rpx;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #333333;
|
||||||
|
background: #F2F2F2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.bottom-view {
|
||||||
|
background: #FFFFFF;
|
||||||
|
position: fixed;
|
||||||
|
padding: 12rpx 30rpx 78rpx 30rpx;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
|
||||||
|
image {
|
||||||
|
width: 35rpx;
|
||||||
|
height: 35rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.c-flex-row:nth-of-type(1) {
|
||||||
|
text {
|
||||||
|
margin-left: 10rpx;
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #333333;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
text:nth-of-type(1) {
|
||||||
|
font-size: 30rpx;
|
||||||
|
|
||||||
|
text {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 36rpx;
|
||||||
|
color: #F32B2B;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.settlement {
|
||||||
|
display: flex;
|
||||||
|
background: #F32B2B;
|
||||||
|
border-radius: 43rpx;
|
||||||
|
padding: 17rpx 75rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #FFFFFF;
|
||||||
|
margin-left: 37rpx;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -1,25 +1,383 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="flex flex-col items-center justify-center">
|
<view class='content'>
|
||||||
<image
|
<view class='user-info-view'>
|
||||||
class="mb-50rpx mt-200rpx h-200rpx w-200rpx"
|
<image
|
||||||
src="@/static/images/logo.png"
|
class='image-bg'
|
||||||
width="200rpx"
|
:src='companyConfigInfo.userbgcover'
|
||||||
height="200rpx"
|
/>
|
||||||
/>
|
|
||||||
<view class="flex justify-center">
|
<view class='top-row'>
|
||||||
<text class="font-size-36rpx color-gray-700">
|
<image :src='userInfo?.image||defaultAvatar' />
|
||||||
{{ title }}
|
<view class='u-flex-column'>
|
||||||
</text>
|
<text>{{ userInfo?.nickName || '未登录' }}</text>
|
||||||
|
<text>{{ userInfo?.telephone }}</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<image :src='assetsUrl("ic_qrcode_white.png")' @click.stop='gotoPath("qrcode")' />
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class='bottom-row'>
|
||||||
|
<view @click.stop='gotoPath("/pages/mine/subs/integral/index")'>
|
||||||
|
<text>{{ userInfo?.integration || 0 }}</text>
|
||||||
|
<text>积分</text>
|
||||||
|
</view>
|
||||||
|
<view @click.stop='gotoPath("/pages/mine/subs/recharge/index")'>
|
||||||
|
<text>{{ userInfo?.balance || 0 }}</text>
|
||||||
|
<text>余额</text>
|
||||||
|
</view>
|
||||||
|
<view @click.stop='gotoPath("/pages/mine/subs/coupon/index")'>
|
||||||
|
<text>{{ userInfo?.couponsCount || 0 }}</text>
|
||||||
|
<text>优惠券</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class='integral-add-view'>
|
||||||
|
<text>将会员卡放入微信卡包,及时了解积分变动</text>
|
||||||
|
<text @click.stop='openCard'>去添加</text>
|
||||||
|
<image :src='assetsUrl("ic_arrow_right_yellow.png")' />
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<text class='title-view'>
|
||||||
|
我的订单
|
||||||
|
</text>
|
||||||
|
<view class='card-order-view'>
|
||||||
|
<view v-for='(item,index) in orderActionList' :key='index' @click.stop='gotoPath(item.path)'>
|
||||||
|
<image :src='item.icon' />
|
||||||
|
<text>{{ item.title }}</text>
|
||||||
|
<text v-if='index==0&&unPaidOrderCount>0'>{{ unPaidOrderCount }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<text class='title-view'>
|
||||||
|
会员服务
|
||||||
|
</text>
|
||||||
|
|
||||||
|
<view class='card-service-view'>
|
||||||
|
<view v-for='(item,index) in serviceList' :key='index' @click.stop='gotoPath(item.path)'>
|
||||||
|
<image :src='item.icon' />
|
||||||
|
<text>{{ item.title }}</text>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
|
<official-account-dialog ref='officialAccountDialogRef' />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang='ts'>
|
||||||
|
import { assetsUrl, defaultAvatar } from '@/utils/assets';
|
||||||
|
import { goLogin, goPath, isLogin } from '@/utils';
|
||||||
|
import { isPending } from '@/utils/order';
|
||||||
|
import { getCardLink } from '@/api/user';
|
||||||
|
import { getOrderList } from '@/api/order';
|
||||||
|
import OfficialAccountDialog from '@/components/official-account-dialog.vue';
|
||||||
import { useUserStore } from '@/store';
|
import { useUserStore } from '@/store';
|
||||||
|
|
||||||
const title = ref<string>();
|
const userStore = useUserStore();
|
||||||
title.value = import.meta.env.VITE_APP_TITLE;
|
const officialAccountDialogRef = ref();
|
||||||
|
|
||||||
|
const orderActionList = ref([{
|
||||||
|
title: '未支付',
|
||||||
|
icon: assetsUrl('ic_order_progressing.png'),
|
||||||
|
path: '/pages/mine/subs/order/index?index=1'
|
||||||
|
}, {
|
||||||
|
title: '已支付',
|
||||||
|
icon: assetsUrl('ic_order_finish.png'),
|
||||||
|
path: '/pages/mine/subs/order/index?index=2'
|
||||||
|
}, {
|
||||||
|
title: '全部订单',
|
||||||
|
icon: assetsUrl('ic_order_all.png'),
|
||||||
|
path: '/pages/mine/subs/order/index?index=0'
|
||||||
|
}]);
|
||||||
|
|
||||||
|
const serviceList = [
|
||||||
|
{
|
||||||
|
title: '会员信息',
|
||||||
|
icon: assetsUrl('ic_member_service_info.png'),
|
||||||
|
path: '/pages/mine/subs/profile/index'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '消费记录',
|
||||||
|
icon: assetsUrl('ic_member_service_record.png'),
|
||||||
|
path: '/pages/mine/subs/trade/index'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '关注公众号',
|
||||||
|
icon: assetsUrl('ic_member_service_follow.png'),
|
||||||
|
path: 'follow_official_account'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '收货地址',
|
||||||
|
icon: assetsUrl('ic_member_service_address.png'),
|
||||||
|
path: '/pages/mine/subs/address/index'
|
||||||
|
}, {
|
||||||
|
title: '联系商家',
|
||||||
|
icon: assetsUrl('ic_member_service_contact.png'),
|
||||||
|
path: '/pages/mine/subs/contact/index'
|
||||||
|
}
|
||||||
|
// ,{
|
||||||
|
// title: '推广中心',
|
||||||
|
// icon: assetsUrl + 'ic_order_progressing.png',
|
||||||
|
// path: ''
|
||||||
|
// }
|
||||||
|
];
|
||||||
|
|
||||||
const store = useUserStore();
|
const store = useUserStore();
|
||||||
console.log('store.user_name', store.user_name);
|
const { userInfo, companyInfo, companyConfigInfo } = storeToRefs(store);
|
||||||
|
|
||||||
|
const cardLink = ref('');
|
||||||
|
const unPaidOrderCount = ref(0);
|
||||||
|
|
||||||
|
onLoad(() => {
|
||||||
|
if(!isLogin()) {
|
||||||
|
goLogin();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
onShow(async () => {
|
||||||
|
const { list } = await getOrderList({
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 9999,
|
||||||
|
obj: { payStatus: 1 }
|
||||||
|
});
|
||||||
|
unPaidOrderCount.value = list.filter((item: any) => isPending(item))?.length || 0;
|
||||||
|
const { cardurl } = await getCardLink();
|
||||||
|
cardLink.value = cardurl;
|
||||||
|
await userStore.getProfile();
|
||||||
|
});
|
||||||
|
|
||||||
|
const openCard = () => {
|
||||||
|
// const url = 'https://mp.weixin.qq.com/bizmall/activatemembercard?action=preshow&&encrypt_card_id=LI%2FNyDp0x3z8XXorvvrHzSR4VUPa2vlioBg2xkDT3HqybiAFNsNgjH7pBpyKGrSA&outer_str=1702887425732870145&biz=MzU2MTg5MjgxMg%3D%3D#wechat_redirect';
|
||||||
|
goPath(`/pages/common/webview/index?url=${encodeURIComponent(cardLink.value)}`);
|
||||||
|
// uni.navigateToMiniProgram({ appId: 'wxeb490c6f9b154ef9' });
|
||||||
|
// uni.addCard({
|
||||||
|
// cardList: [
|
||||||
|
// {
|
||||||
|
// cardId: 'pzCtO1NU8FDcF3v09_Q76-7ZuN8I',
|
||||||
|
// cardExt: JSON.stringify({ 'code': '12345', openId: 'wxc480826360455685', 'timestamp': Date.now(), 'signature': '' })
|
||||||
|
// }
|
||||||
|
// ]
|
||||||
|
// });
|
||||||
|
};
|
||||||
|
|
||||||
|
const gotoPath = (path: string) => {
|
||||||
|
if(path === 'follow_official_account') {
|
||||||
|
showOfficialAccountDialog();
|
||||||
|
} else if(path === 'qrcode') {
|
||||||
|
uni.switchTab({
|
||||||
|
url: '/pages/qrcode/index'
|
||||||
|
});
|
||||||
|
} else if(path === 'call') {
|
||||||
|
uni.makePhoneCall({
|
||||||
|
phoneNumber: companyInfo.value.telphone
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
goPath(path);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const showOfficialAccountDialog = () => {
|
||||||
|
officialAccountDialogRef.value.show();
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style lang='scss' scoped>
|
||||||
|
.content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
padding: 30rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-info-view {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
position: relative;
|
||||||
|
height: 275rpx;
|
||||||
|
|
||||||
|
.image-bg {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
position: absolute;
|
||||||
|
border-radius: 8rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.top-row {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
position: relative;
|
||||||
|
margin-left: 33rpx;
|
||||||
|
margin-top: 43rpx;
|
||||||
|
margin-right: 28rpx;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
image:nth-of-type(1) {
|
||||||
|
width: 80rpx;
|
||||||
|
height: 80rpx;
|
||||||
|
border-radius: 50%;
|
||||||
|
border: #FFFFFF solid 2rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
view:nth-of-type(1) {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
color: white;
|
||||||
|
flex: 1;
|
||||||
|
margin-left: 20rpx;
|
||||||
|
|
||||||
|
text:nth-of-type(1) {
|
||||||
|
font-size: 30rpx;
|
||||||
|
font-weight: 800;
|
||||||
|
}
|
||||||
|
|
||||||
|
text:nth-of-type(2) {
|
||||||
|
font-size: 24rpx;
|
||||||
|
font-weight: 400;
|
||||||
|
margin-top: 5rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
image:nth-of-type(2) {
|
||||||
|
width: 36rpx;
|
||||||
|
height: 36rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.bottom-row {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: center;
|
||||||
|
position: relative;
|
||||||
|
margin-top: 33rpx;
|
||||||
|
|
||||||
|
view:nth-of-type(n+1) {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
|
text:nth-of-type(1) {
|
||||||
|
font-size: 36rpx;
|
||||||
|
font-weight: 400;
|
||||||
|
color: #FFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
text:nth-of-type(2) {
|
||||||
|
font-size: 26rpx;
|
||||||
|
font-weight: 400;
|
||||||
|
margin-top: 8rpx;
|
||||||
|
color: #FFFFFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.integral-add-view {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
background: #F8ECDE;
|
||||||
|
align-items: center;
|
||||||
|
border-radius: 10rpx;
|
||||||
|
padding: 20rpx 17rpx;
|
||||||
|
margin-top: 30rpx;
|
||||||
|
|
||||||
|
text:nth-of-type(1) {
|
||||||
|
display: flex;
|
||||||
|
font-size: 24rpx;
|
||||||
|
font-weight: 400;
|
||||||
|
color: #333333;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
text:nth-of-type(2) {
|
||||||
|
font-size: 26rpx;
|
||||||
|
font-weight: 400;
|
||||||
|
color: #DB7400;
|
||||||
|
}
|
||||||
|
|
||||||
|
image {
|
||||||
|
width: 30rpx;
|
||||||
|
height: 30rpx;
|
||||||
|
margin-left: 14rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.title-view {
|
||||||
|
font-size: 30rpx;
|
||||||
|
font-weight: 800;
|
||||||
|
color: #333333;
|
||||||
|
margin-top: 30rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-view {
|
||||||
|
display: flex;
|
||||||
|
background: #FFFFFF;
|
||||||
|
border-radius: 20rpx;
|
||||||
|
margin-top: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-order-view {
|
||||||
|
@extend .card-view;
|
||||||
|
flex-direction: row;
|
||||||
|
padding: 30rpx 0;
|
||||||
|
|
||||||
|
view:nth-of-type(n+1) {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
position: relative;
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
|
image {
|
||||||
|
width: 58rpx;
|
||||||
|
height: 58rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
text:nth-of-type(1) {
|
||||||
|
font-size: 28rpx;
|
||||||
|
font-weight: 400;
|
||||||
|
color: #333333;
|
||||||
|
margin-top: 10rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
text:nth-of-type(2) {
|
||||||
|
display: flex;
|
||||||
|
position: absolute;
|
||||||
|
min-width: 40rpx;
|
||||||
|
min-height: 35rpx;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 26rpx;
|
||||||
|
justify-content: center;
|
||||||
|
background: #F32B2B;
|
||||||
|
border-radius: 50%;
|
||||||
|
color: #FFFFFF;
|
||||||
|
top: -10rpx;
|
||||||
|
right: 70rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-service-view {
|
||||||
|
@extend .card-view;
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns:repeat(4, 1fr);
|
||||||
|
|
||||||
|
view:nth-of-type(n+1) {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 30rpx 0;
|
||||||
|
font-size: 26rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
image {
|
||||||
|
width: 54rpx;
|
||||||
|
height: 54rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|||||||
93
src/pages/mine/subs/address/components/item.vue
Normal file
93
src/pages/mine/subs/address/components/item.vue
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
<template>
|
||||||
|
<view class='card-view' @click.stop='emits("onChecked",item)'>
|
||||||
|
<view class='c-flex-row'>
|
||||||
|
<text class='status' v-if='item?.defaultstatus==1'>默认</text>
|
||||||
|
<text>
|
||||||
|
{{ item?.name }}
|
||||||
|
</text>
|
||||||
|
<text>
|
||||||
|
{{ item?.mobile }}
|
||||||
|
</text>
|
||||||
|
</view>
|
||||||
|
<text class='address'>
|
||||||
|
{{ item?.addr }}
|
||||||
|
</text>
|
||||||
|
|
||||||
|
<view class='btn-view c-flex-row'>
|
||||||
|
<text @click.stop='emits("onEdit",item)'>编辑</text>
|
||||||
|
<text @click.stop='emits("onDelete",item)'>删除</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang='ts' setup>
|
||||||
|
|
||||||
|
import { PropType } from 'vue';
|
||||||
|
|
||||||
|
defineProps({
|
||||||
|
item: Object as PropType<{ name: string, mobile: string, addr: string, defaultstatus: number }>
|
||||||
|
});
|
||||||
|
const emits = defineEmits(['onEdit', 'onDelete', 'onChecked']);
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang='scss' scoped>
|
||||||
|
.card-view {
|
||||||
|
margin: 20rpx 30rpx;
|
||||||
|
padding: 38rpx 30rpx 30rpx 34rpx;
|
||||||
|
|
||||||
|
view:nth-of-type(1) {
|
||||||
|
.status {
|
||||||
|
border-radius: 5rpx;
|
||||||
|
border: 1rpx solid #F32B2B;
|
||||||
|
color: #F32B2B;
|
||||||
|
font-size: 24prx;
|
||||||
|
padding: 1rpx 8rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
text:nth-of-type(2) {
|
||||||
|
font-size: 32rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-left: 10rpx;
|
||||||
|
color: #333333;
|
||||||
|
}
|
||||||
|
|
||||||
|
text:nth-of-type(3) {
|
||||||
|
font-size: 32rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-left: 20rpx;
|
||||||
|
color: #333333;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.address {
|
||||||
|
font-size: 26rpx;
|
||||||
|
font-weight: 400;
|
||||||
|
margin-top: 10rpx;
|
||||||
|
color: #999999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-view {
|
||||||
|
display: flex;
|
||||||
|
align-self: flex-end;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
text:nth-of-type(n+1) {
|
||||||
|
display: flex;
|
||||||
|
width: 84rpx;
|
||||||
|
height: 48rpx;
|
||||||
|
border-radius: 24rpx;
|
||||||
|
border: 1rpx solid #F32B2B;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
color: #F32B2B;
|
||||||
|
margin-left: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
text:nth-of-type(2) {
|
||||||
|
border: 1rpx solid #DDDDDD;
|
||||||
|
color: #666666;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
184
src/pages/mine/subs/address/create.vue
Normal file
184
src/pages/mine/subs/address/create.vue
Normal file
@@ -0,0 +1,184 @@
|
|||||||
|
<template>
|
||||||
|
<view class='content'>
|
||||||
|
<view class='c-flex-row'>
|
||||||
|
<text>收货人</text>
|
||||||
|
<input placeholder='请输入收货人姓名' v-model='params.name' @input='bindConsignee' />
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class='divider' />
|
||||||
|
<view class='c-flex-row'>
|
||||||
|
<text>手机号</text>
|
||||||
|
<input placeholder='请输入收货人手机号' v-model='params.mobile' @input='bindMobile' :maxlength='11' />
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class='divider' />
|
||||||
|
<view class='c-flex-row detail-row'>
|
||||||
|
<text>详细地址</text>
|
||||||
|
<view class='c-flex-column'>
|
||||||
|
<textarea placeholder='详细地址:如街道、门牌\n号、楼栋号、单元室等'
|
||||||
|
v-model='params.addr'
|
||||||
|
@input='bindAddress' />
|
||||||
|
<view class='tips-view c-flex-row'>
|
||||||
|
<image :src='assetsUrl("ic_tips.png")' />
|
||||||
|
<text>记得完善门牌号</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class='divider' />
|
||||||
|
<view class='c-flex-column'>
|
||||||
|
<text style='width: auto'>设为默认地址</text>
|
||||||
|
<text style='width: auto'>提醒:每次下单会默认推荐使用该地址</text>
|
||||||
|
<!-- @change='ev=>{params.defaultstatus = ev.detail.value}'-->
|
||||||
|
<switch color='#F32B2B' @change='bindStatus' :checked='params.defaultstatus == 1' />
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class='bottom-button-view'>
|
||||||
|
<button class='primary-button' @click.stop='save'>保存地址</button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang='ts' setup>
|
||||||
|
|
||||||
|
import { assetsUrl } from '@/utils/assets';
|
||||||
|
import { addressCreate, addressUpdate } from '@/api/user';
|
||||||
|
|
||||||
|
const params = ref<{
|
||||||
|
addrid: string,
|
||||||
|
name: string,
|
||||||
|
mobile: string,
|
||||||
|
zonecode: string,
|
||||||
|
addr: string,
|
||||||
|
defaultstatus: number
|
||||||
|
}>({
|
||||||
|
addrid: '',
|
||||||
|
name: '',
|
||||||
|
mobile: '',
|
||||||
|
zonecode: '',
|
||||||
|
addr: '',
|
||||||
|
defaultstatus: 0
|
||||||
|
});
|
||||||
|
|
||||||
|
onLoad(async (e: any) => {
|
||||||
|
if(e.bean) {
|
||||||
|
params.value = JSON.parse(decodeURIComponent(e.bean));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const bindConsignee = (e: any) => {
|
||||||
|
params.value.name = e.detail.value;
|
||||||
|
};
|
||||||
|
|
||||||
|
const bindMobile = (e: any) => {
|
||||||
|
params.value.mobile = e.detail.value;
|
||||||
|
};
|
||||||
|
|
||||||
|
const bindAddress = (e: any) => {
|
||||||
|
params.value.addr = e.detail.value;
|
||||||
|
};
|
||||||
|
|
||||||
|
const bindStatus = (e: any) => {
|
||||||
|
params.value.defaultstatus = e.detail.value == true ? 1 : 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
const save = async () => {
|
||||||
|
let result = false;
|
||||||
|
if(params.value.addrid) {
|
||||||
|
result = await addressUpdate(params.value);
|
||||||
|
} else {
|
||||||
|
result = await addressCreate(
|
||||||
|
params.value
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(result === true) {
|
||||||
|
uni.showToast({
|
||||||
|
title: '保存成功',
|
||||||
|
icon: 'none',
|
||||||
|
success(result) {
|
||||||
|
uni.navigateBack();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang='scss' scoped>
|
||||||
|
.content {
|
||||||
|
background: #FFFFFF;
|
||||||
|
padding: 28rpx 28rpx 0 28rpx;
|
||||||
|
|
||||||
|
view:not(.divider):nth-of-type(n+1) {
|
||||||
|
height: 100rpx;
|
||||||
|
|
||||||
|
text:nth-of-type(n+1) {
|
||||||
|
font-size: 32rpx;
|
||||||
|
font-weight: 400;
|
||||||
|
color: #333333;
|
||||||
|
width: 170rpx;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
font-size: 30rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-row {
|
||||||
|
height: 236rpx !important;
|
||||||
|
align-items: flex-start;
|
||||||
|
padding-top: 28rpx;
|
||||||
|
|
||||||
|
text:nth-of-type(1) {
|
||||||
|
width: 170rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
view:nth-of-type(1) {
|
||||||
|
flex: 1;
|
||||||
|
margin: 0 20rpx 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
textarea {
|
||||||
|
height: 200rpx;
|
||||||
|
width: 100%;
|
||||||
|
font-size: 30rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tips-view {
|
||||||
|
image {
|
||||||
|
width: 32rpx;
|
||||||
|
height: 32rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
text {
|
||||||
|
font-size: 26rpx !important;
|
||||||
|
font-weight: 400;
|
||||||
|
color: #999999 !important;
|
||||||
|
margin-left: 20rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.c-flex-column {
|
||||||
|
display: flex;
|
||||||
|
position: relative;
|
||||||
|
justify-content: center;
|
||||||
|
height: 170rpx !important;
|
||||||
|
|
||||||
|
text:nth-of-type(2) {
|
||||||
|
font-size: 24rpx !important;
|
||||||
|
color: #CCCCCC !important;
|
||||||
|
margin-top: 10rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch {
|
||||||
|
position: absolute;
|
||||||
|
align-self: center;
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
</style>
|
||||||
73
src/pages/mine/subs/address/index.vue
Normal file
73
src/pages/mine/subs/address/index.vue
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
<template>
|
||||||
|
<view class='content'>
|
||||||
|
<scroll-view :scroll-y='true'>
|
||||||
|
<item v-for='(item,index) in addressList' :key='index' :item='item'
|
||||||
|
@on-checked='onChecked(item)'
|
||||||
|
@on-edit='args => goPath(`create?bean=${encodeURIComponent(JSON.stringify(args))}`)'
|
||||||
|
@on-delete='args => {handleDelete(args)}' />
|
||||||
|
<u-empty v-if='addressList.length === 0' text='暂无数据' margin-top='100' />
|
||||||
|
</scroll-view>
|
||||||
|
|
||||||
|
<view class='bottom-button-view'>
|
||||||
|
<button class='primary-button' @click.stop='goPath("create")'>+新增地址</button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang='ts' setup>
|
||||||
|
|
||||||
|
import Item from './components/item.vue';
|
||||||
|
import { goPath } from '@/utils';
|
||||||
|
import { addressDelete, getAddressList } from '@/api/user';
|
||||||
|
import { useUserStore } from '@/store';
|
||||||
|
|
||||||
|
const userStore = useUserStore();
|
||||||
|
|
||||||
|
const addressList = ref<{
|
||||||
|
name: string,
|
||||||
|
mobile: string,
|
||||||
|
addr: string,
|
||||||
|
status: number,
|
||||||
|
defaultstatus: number,
|
||||||
|
}[]>([]);
|
||||||
|
|
||||||
|
onLoad((e) => {
|
||||||
|
// fetchAddressList();
|
||||||
|
});
|
||||||
|
|
||||||
|
onShow(() => {
|
||||||
|
fetchAddressList();
|
||||||
|
});
|
||||||
|
|
||||||
|
const fetchAddressList = async () => {
|
||||||
|
addressList.value = await getAddressList();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleDelete = async (item: any) => {
|
||||||
|
uni.showModal(
|
||||||
|
{
|
||||||
|
title: '提示',
|
||||||
|
content: '确定删除该地址吗?',
|
||||||
|
success: async (res) => {
|
||||||
|
if(res.confirm) {
|
||||||
|
const result = await addressDelete(item?.addrid);
|
||||||
|
if(result) {
|
||||||
|
await fetchAddressList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onChecked = (e: any) => {
|
||||||
|
const pages = getCurrentPages();
|
||||||
|
if(pages.length >= 2 && pages[pages.length - 2].route?.includes('pages/mall/subs/order/order-confirm')) {
|
||||||
|
userStore.setDeliveryAddress(e);
|
||||||
|
uni.navigateBack();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang='scss' scoped>
|
||||||
|
</style>
|
||||||
79
src/pages/mine/subs/components/official-account-dialog.vue
Normal file
79
src/pages/mine/subs/components/official-account-dialog.vue
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
<template>
|
||||||
|
|
||||||
|
<uni-popup type='bottom' ref='popupRef' :mask-click='false' @touchmove.stop.prevent=''>
|
||||||
|
<view class='popup-content c-flex-column'>
|
||||||
|
<view class='c-flex-row'>
|
||||||
|
<text>关注公众号</text>
|
||||||
|
<image :src='assetsUrl("ic_close.png")' @click.stop='close()' />
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<image class='qrcode' :src='assetsUrl("test_bg.png")' />
|
||||||
|
|
||||||
|
<text class='tips'>长按关注会员中心公众号
|
||||||
|
获得更多优惠和服务信息
|
||||||
|
</text>
|
||||||
|
</view>
|
||||||
|
</uni-popup>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang='ts' setup>
|
||||||
|
import { assetsUrl } from '@/utils/assets';
|
||||||
|
|
||||||
|
const popupRef = ref();
|
||||||
|
const show = () => {
|
||||||
|
popupRef.value.open();
|
||||||
|
};
|
||||||
|
|
||||||
|
const close = () => {
|
||||||
|
popupRef.value.close();
|
||||||
|
};
|
||||||
|
|
||||||
|
defineExpose({ show });
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang='scss' scoped>
|
||||||
|
.popup-content {
|
||||||
|
background: #FFFFFF;
|
||||||
|
border-radius: 20rpx 20rpx 0 0;
|
||||||
|
padding: 38rpx 45rpx 140rpx 45rpx;
|
||||||
|
|
||||||
|
view:nth-of-type(1) {
|
||||||
|
display: flex;
|
||||||
|
margin-bottom: 70rpx;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
image {
|
||||||
|
width: 35rpx;
|
||||||
|
height: 35rpx;
|
||||||
|
align-self: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
text {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #333333;
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.qrcode {
|
||||||
|
width: 377rpx;
|
||||||
|
height: 377rpx;
|
||||||
|
margin-top: 50rpx;
|
||||||
|
align-self: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tips {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #333333;
|
||||||
|
margin-top: 10rpx;
|
||||||
|
margin-bottom: 104rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
</style>
|
||||||
61
src/pages/mine/subs/contact/index.vue
Normal file
61
src/pages/mine/subs/contact/index.vue
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
<template>
|
||||||
|
<view class='card-view'>
|
||||||
|
<view class='c-flex-row'>
|
||||||
|
<text class='key'>姓名</text>
|
||||||
|
<text class='value'>{{ companyConfigInfo?.contactname}}</text>
|
||||||
|
</view>
|
||||||
|
<view class='divider' />
|
||||||
|
<view class='c-flex-row'>
|
||||||
|
<text class='key'>手机号</text>
|
||||||
|
<text class='value'>{{companyConfigInfo?.contacttelephone}}</text>
|
||||||
|
<image :src='assetsUrl("ic_contact_merchant.png")' @click.stop='call' />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang='ts' setup>
|
||||||
|
import { useUserStore } from '@/store';
|
||||||
|
import { assetsUrl } from '@/utils/assets';
|
||||||
|
|
||||||
|
const { companyConfigInfo } = storeToRefs(useUserStore());
|
||||||
|
const call = () => {
|
||||||
|
uni.makePhoneCall({
|
||||||
|
phoneNumber: companyConfigInfo.value.contacttelephone
|
||||||
|
});
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang='scss' scoped>
|
||||||
|
.card-view {
|
||||||
|
background-color: #fff;
|
||||||
|
padding: 30rpx 20rpx;
|
||||||
|
margin: 24rpx;
|
||||||
|
border-radius: 10rpx;
|
||||||
|
|
||||||
|
.divider {
|
||||||
|
margin: 30rpx 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.c-flex-row {
|
||||||
|
.key {
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #7E7E7E;
|
||||||
|
width: 120rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.value {
|
||||||
|
display: flex;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #333333;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
image {
|
||||||
|
width: 39rpx;
|
||||||
|
height: 41rpx;
|
||||||
|
margin-right: 10rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
127
src/pages/mine/subs/coupon/components/coupon-item.vue
Normal file
127
src/pages/mine/subs/coupon/components/coupon-item.vue
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
<template>
|
||||||
|
<view class='coupon-content'>
|
||||||
|
<image v-if='item?.status==0' :src='assetsUrl("bg_coupon.png")' />
|
||||||
|
<image v-else-if='item?.status==1||item?.status==2' :src='assetsUrl("bg_coupon_expired.png")' />
|
||||||
|
<view class='left-content accent-text-color' :class='{"left-content-disabled": item?.status!=0}'>
|
||||||
|
<text>{{ item?.reduce }}</text>
|
||||||
|
<text>满{{ item?.threshold }}元可用</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class='right-content accent-text-color' :class='{"right-content-disabled": item?.status!=0}'>
|
||||||
|
<text>{{ item?.name }}</text>
|
||||||
|
<text>有效期至{{ dayjs(item?.startTime).format('YYYY-MM-DD') }}</text>
|
||||||
|
<text class='btn-text' :class='{"btn-text-disabled": item?.status!=0}' @click.stop='goPath("/pages/mall/index")'>
|
||||||
|
立即使用
|
||||||
|
</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang='ts' setup>
|
||||||
|
|
||||||
|
import { assetsUrl } from '@/utils/assets';
|
||||||
|
import dayjs from 'dayjs';
|
||||||
|
import { PropType } from 'vue';
|
||||||
|
import { CouponBean } from '@/api/user/types';
|
||||||
|
import { goPath } from '@/utils';
|
||||||
|
|
||||||
|
defineProps({
|
||||||
|
item: Object as PropType<CouponBean>
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang='scss' scoped>
|
||||||
|
.coupon-content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
height: 200rpx;
|
||||||
|
position: relative;
|
||||||
|
margin: 30rpx 30rpx 10rpx 30rpx;
|
||||||
|
|
||||||
|
image {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
.left-content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
position: relative;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding-left: 50rpx;
|
||||||
|
|
||||||
|
text:nth-of-type(1) {
|
||||||
|
font-size: 55rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
text:nth-of-type(1):after {
|
||||||
|
content: '元';
|
||||||
|
font-size: 24rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
text:nth-of-type(2) {
|
||||||
|
font-size: 26rpx;
|
||||||
|
font-weight: 400;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.left-content-disabled {
|
||||||
|
@extend .left-content;
|
||||||
|
color: #C2C2C2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.right-content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
position: relative;
|
||||||
|
flex: 1;
|
||||||
|
justify-content: center;
|
||||||
|
margin-left: 60rpx;
|
||||||
|
|
||||||
|
text:nth-of-type(1) {
|
||||||
|
font-size: 30rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
text:nth-of-type(2) {
|
||||||
|
font-size: 26rpx;
|
||||||
|
margin-top: 20rpx;
|
||||||
|
color: #333333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-text {
|
||||||
|
display: flex;
|
||||||
|
width: 146rpx;
|
||||||
|
height: 55rpx;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
border-radius: 28rpx;
|
||||||
|
border: #F32B2B solid 2rpx;
|
||||||
|
font-size: 28rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #F32B2B;
|
||||||
|
position: absolute;
|
||||||
|
right: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-text-disabled {
|
||||||
|
@extend .btn-text;
|
||||||
|
color: #C2C2C2;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.right-content-disabled {
|
||||||
|
@extend .right-content;
|
||||||
|
color: #C2C2C2;
|
||||||
|
|
||||||
|
text:nth-of-type(2) {
|
||||||
|
color: #C2C2C2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
75
src/pages/mine/subs/coupon/index.vue
Normal file
75
src/pages/mine/subs/coupon/index.vue
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
<template>
|
||||||
|
<tabbar :titles='["全部","未使用","已使用"]' :indicator-color='"#D95554"' @change='tabChange' />
|
||||||
|
<u-list @scrolltolower='onLoadMore'>
|
||||||
|
<coupon-item v-for='item in couponList' :item='item' :key='item.id' />
|
||||||
|
<u-loadmore v-if='couponList.length>0' :status='loadingStatus' />
|
||||||
|
<u-empty v-if='couponList.length === 0' text='暂无优惠券' marginTop='100' />
|
||||||
|
</u-list>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang='ts' setup>
|
||||||
|
import { ref } from 'vue';
|
||||||
|
|
||||||
|
import CouponItem from './components/coupon-item.vue';
|
||||||
|
import { getCouponList } from '@/api/user';
|
||||||
|
import { useUserStore } from '@/store';
|
||||||
|
import { getCompanyId } from '@/utils';
|
||||||
|
import { CouponBean } from '@/api/user/types';
|
||||||
|
|
||||||
|
const store = useUserStore();
|
||||||
|
const { userInfo } = storeToRefs(store);
|
||||||
|
|
||||||
|
const couponStatus = ref<number | any>(undefined);
|
||||||
|
const couponList = ref<CouponBean[]>([]);
|
||||||
|
const currentPageNum = ref(1);
|
||||||
|
const loadingStatus = ref('loading');
|
||||||
|
|
||||||
|
onLoad(async () => {
|
||||||
|
await fetchData();
|
||||||
|
});
|
||||||
|
|
||||||
|
const tabChange = (index: number) => {
|
||||||
|
switch (index) {
|
||||||
|
case 0:
|
||||||
|
couponStatus.value = undefined;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
couponStatus.value = 0;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
couponStatus.value = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
currentPageNum.value = 1;
|
||||||
|
fetchData();
|
||||||
|
};
|
||||||
|
|
||||||
|
const fetchData = async (refresh: boolean = true) => {
|
||||||
|
loadingStatus.value = 'loading';
|
||||||
|
if(!refresh) {
|
||||||
|
currentPageNum.value += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { list } = await getCouponList({
|
||||||
|
companyId: getCompanyId(),
|
||||||
|
memberId: userInfo.value?.id,
|
||||||
|
status: couponStatus.value,
|
||||||
|
pageNum: currentPageNum.value,
|
||||||
|
pageSize: 20
|
||||||
|
});
|
||||||
|
if(refresh) {
|
||||||
|
couponList.value = list;
|
||||||
|
} else {
|
||||||
|
couponList.value = couponList.value.concat(list);
|
||||||
|
}
|
||||||
|
loadingStatus.value = 'no';
|
||||||
|
};
|
||||||
|
|
||||||
|
const onLoadMore = () => {
|
||||||
|
fetchData(false);
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang='scss' scoped>
|
||||||
|
|
||||||
|
</style>
|
||||||
47
src/pages/mine/subs/integral/components/integral-item.vue
Normal file
47
src/pages/mine/subs/integral/components/integral-item.vue
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
<template>
|
||||||
|
<view class='card-view'>
|
||||||
|
<!-- <text class='category-title'>2023-02-12</text>-->
|
||||||
|
<!-- <view class='item c-flex-column' v-for='(item,index) in 3' :key='index'>-->
|
||||||
|
<view class='c-flex-row'>
|
||||||
|
<text class='primary-text-color' style='flex: 1'>{{item?.remark}}</text>
|
||||||
|
<text class='accent-text-color'>{{item?.value}}</text>
|
||||||
|
</view>
|
||||||
|
<view class='c-flex-row'>
|
||||||
|
<text class='secondary-text-color' style='flex: 1'>{{ item?.createtime }}</text>
|
||||||
|
<text style='color: #999999'>会员积分:¥30.00</text>
|
||||||
|
</view>
|
||||||
|
<!-- <view class='divider' style='margin-top: 20rpx'/>-->
|
||||||
|
<!-- </view>-->
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang='ts' setup>
|
||||||
|
import { IntegralBean } from '@/api/user/types';
|
||||||
|
|
||||||
|
defineProps({
|
||||||
|
item: Object as PropType<IntegralBean>
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang='scss' scoped>
|
||||||
|
.card-view {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
padding: 16rpx 23rpx 20rpx 30rpx;
|
||||||
|
margin: 10rpx 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.category-title {
|
||||||
|
font-size: 34rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #333333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item {
|
||||||
|
margin: 10rpx 0;
|
||||||
|
|
||||||
|
view:nth-of-type(2) {
|
||||||
|
margin-top: 10rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
82
src/pages/mine/subs/integral/index.vue
Normal file
82
src/pages/mine/subs/integral/index.vue
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
<template>
|
||||||
|
<view class='content'>
|
||||||
|
<view class='top-view c-flex-column'>
|
||||||
|
<text>{{ userInfo?.integration }}</text>
|
||||||
|
<text>会员积分</text>
|
||||||
|
</view>
|
||||||
|
<text class='integral-detail-title'>积分明细</text>
|
||||||
|
<scroll-view style='margin: 10rpx 20rpx'>
|
||||||
|
<u-list @scrolltolower='loadMore'>
|
||||||
|
<integral-item v-for='(item,index) in tradeList' :key='index' :item='item' />
|
||||||
|
<u-empty v-if='tradeList.length === 0' text='暂无数据' margin-top='100' />
|
||||||
|
</u-list>
|
||||||
|
</scroll-view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang='ts' setup>
|
||||||
|
import IntegralItem from './components/integral-item.vue';
|
||||||
|
import { getIntegralList } from '@/api/user';
|
||||||
|
import { useUserStore } from '@/store';
|
||||||
|
|
||||||
|
const userStore = useUserStore();
|
||||||
|
const { userInfo } = storeToRefs(userStore);
|
||||||
|
const tradeList = ref([]);
|
||||||
|
const currentPageNum = ref(1);
|
||||||
|
|
||||||
|
onLoad((e) => {
|
||||||
|
fetchData();
|
||||||
|
});
|
||||||
|
|
||||||
|
const fetchData = async (refresh: boolean = true) => {
|
||||||
|
currentPageNum.value = refresh ? 1 : currentPageNum.value + 1;
|
||||||
|
const { rows } = await getIntegralList({
|
||||||
|
fbean: { 'pageNum': currentPageNum.value, 'pageSize': 20, 'bean': {} }
|
||||||
|
});
|
||||||
|
if(refresh) {
|
||||||
|
tradeList.value = rows;
|
||||||
|
} else {
|
||||||
|
tradeList.value = tradeList.value.concat(rows);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const loadMore = () => {
|
||||||
|
fetchData(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang='scss' scoped>
|
||||||
|
|
||||||
|
.top-view {
|
||||||
|
height: 195rpx;
|
||||||
|
background: linear-gradient(#F32B2B, #F95D5D);
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
text:nth-of-type(1) {
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 50rpx;
|
||||||
|
color: #FFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
text:nth-of-type(2) {
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 26rpx;
|
||||||
|
color: #FFFFFF;
|
||||||
|
margin-top: 10rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.integral-detail-title {
|
||||||
|
margin: 20rpx 24rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #333333;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
scroll-view {
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
170
src/pages/mine/subs/order/components/order-item.vue
Normal file
170
src/pages/mine/subs/order/components/order-item.vue
Normal file
@@ -0,0 +1,170 @@
|
|||||||
|
<template>
|
||||||
|
<view class='card-view' @click.stop='goPath(`/pages/mine/subs/order/detail?orderId=${item?.id}`)'>
|
||||||
|
<view class='goods-info-view c-flex-row'>
|
||||||
|
<image class='goods-image' :src='item?.orderGoods[0].images||defaultImage' />
|
||||||
|
<view class='c-flex-column' style='flex: 1;'>
|
||||||
|
<view class='c-flex-row'>
|
||||||
|
<text class='goods-name'>{{ item?.orderGoods[0].goodsName || '未知' }}</text>
|
||||||
|
<text class='status'>
|
||||||
|
<text v-if='item?.payStatus == 2'>已支付</text>
|
||||||
|
<text v-else-if='isPending(item)'>待支付</text>
|
||||||
|
<text v-else style='color: #999999'>已过期</text>
|
||||||
|
</text>
|
||||||
|
</view>
|
||||||
|
<view class='bottom-view c-flex-row'>
|
||||||
|
<text>
|
||||||
|
{{ item?.orderGoods[0].stockStock.colorName||'均色' }},{{ item?.orderGoods[0].stockStock.sizeName||'均码' }}
|
||||||
|
</text>
|
||||||
|
<text>
|
||||||
|
共{{ item?.itemNum }}件
|
||||||
|
</text>
|
||||||
|
<text>{{ item?.totalPrice }}元</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class='action-view c-flex-row'>
|
||||||
|
<view class='countdown c-flex-row' v-if='isPending(item)'>
|
||||||
|
<image :src='assetsUrl("ic_time.png")' />
|
||||||
|
<text class='primary-text-color'>支付剩余时间
|
||||||
|
<text class='accent-text-color'>{{ dayjs.unix(item?.countdown || 0).format('mm:ss') || '00:00' }}</text>
|
||||||
|
</text>
|
||||||
|
</view>
|
||||||
|
<view v-else style='flex: 1' />
|
||||||
|
|
||||||
|
<view class='c-flex-row'>
|
||||||
|
<text class='add-shoppingcart secondary-text-color' @click.stop='add(item?.orderGoods[0])'>加入购物车</text>
|
||||||
|
<text class='payment accent-text-color' v-if='isPending(item)'
|
||||||
|
@click.stop='goPath(`/pages/mine/subs/order/detail?orderId=${item?.id}`)'>立即支付
|
||||||
|
</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang='ts' setup>
|
||||||
|
import { PropType } from 'vue';
|
||||||
|
import { assetsUrl, defaultImage } from '@/utils/assets';
|
||||||
|
import { goPath } from '@/utils';
|
||||||
|
import { isPending } from '@/utils/order';
|
||||||
|
import { OrderBean } from '@/api/order/types';
|
||||||
|
import { GoodsBean } from '@/api/goods/types';
|
||||||
|
import dayjs from 'dayjs';
|
||||||
|
|
||||||
|
const emits = defineEmits(['addShoppingCart', 'payment']);
|
||||||
|
|
||||||
|
defineProps({
|
||||||
|
item: Object as PropType<OrderBean>
|
||||||
|
});
|
||||||
|
|
||||||
|
const add = (item: GoodsBean | undefined) => {
|
||||||
|
emits('addShoppingCart', item);
|
||||||
|
};
|
||||||
|
|
||||||
|
const pay = (orderId: string | undefined) => {
|
||||||
|
emits('payment', orderId);
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang='scss' scoped>
|
||||||
|
.card-view {
|
||||||
|
padding: 30rpx 20rpx 20rpx 30rpx;
|
||||||
|
margin: 20rpx 24rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.goods-info-view {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.goods-image {
|
||||||
|
width: 180rpx;
|
||||||
|
height: 180rpx;
|
||||||
|
border-radius: 10rpx;
|
||||||
|
margin-right: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.goods-name {
|
||||||
|
font-size: 30rpx;
|
||||||
|
font-weight: 400;
|
||||||
|
-webkit-line-clamp: 2;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
overflow: hidden;
|
||||||
|
margin-right: 20rpx;
|
||||||
|
color: #333333;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status {
|
||||||
|
font-size: 26rpx;
|
||||||
|
font-weight: 400;
|
||||||
|
color: #F32B2B;
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bottom-view {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-top: 40rpx;
|
||||||
|
|
||||||
|
text:nth-of-type(1) {
|
||||||
|
font-size: 26rpx;
|
||||||
|
font-weight: 400;
|
||||||
|
flex: 1;
|
||||||
|
color: #999999;
|
||||||
|
}
|
||||||
|
|
||||||
|
text:nth-of-type(2) {
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #333333;
|
||||||
|
margin-right: 5rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
text:nth-of-type(3) {
|
||||||
|
font-size: 34rpx;
|
||||||
|
color: #333333;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-view {
|
||||||
|
margin-top: 37rpx;
|
||||||
|
|
||||||
|
.countdown {
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
|
image {
|
||||||
|
width: 37rpx;
|
||||||
|
height: 37rpx;
|
||||||
|
margin-right: 5rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
text {
|
||||||
|
font-size: 26rpx;
|
||||||
|
font-weight: 400;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
view:nth-of-type(2) {
|
||||||
|
text {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 12rpx 28rpx;
|
||||||
|
font-size: 26rpx;
|
||||||
|
border-radius: 34rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.add-shoppingcart {
|
||||||
|
border: 2rpx solid #ACACAC;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.payment {
|
||||||
|
border: 2rpx solid #F32B2B;
|
||||||
|
margin-left: 20rpx;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
452
src/pages/mine/subs/order/detail.vue
Normal file
452
src/pages/mine/subs/order/detail.vue
Normal file
@@ -0,0 +1,452 @@
|
|||||||
|
<template>
|
||||||
|
<scroll-view scroll-y>
|
||||||
|
<view class='content'>
|
||||||
|
<view class='countdown c-flex-row' v-if='isPending(orderBean?.order)'>
|
||||||
|
<image :src='assetsUrl("ic_order.png")' />
|
||||||
|
<view class='c-flex-column'>
|
||||||
|
<text>
|
||||||
|
待支付
|
||||||
|
</text>
|
||||||
|
<view class='c-flex-row'>
|
||||||
|
<image :src='assetsUrl("ic_time.png")' />
|
||||||
|
<text>支付剩余时间
|
||||||
|
<text style='color: #F32B2B'>{{ dayjs.unix(orderBean?.order?.countdown || 0).format('mm:ss') }}</text>
|
||||||
|
</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class='address-view c-flex-column'
|
||||||
|
v-if='orderBean?.order?.address'>
|
||||||
|
<view class='user-info c-flex-row'>
|
||||||
|
<text class='status' v-if='orderBean.order.address.defaultstatus==1'>默认</text>
|
||||||
|
<text>{{ orderBean?.order?.address.name }}</text>
|
||||||
|
<text>{{ orderBean?.order?.address.mobile }}</text>
|
||||||
|
<view style='flex: 1' />
|
||||||
|
<text style='color: #5B96FB'
|
||||||
|
@click.stop='copy(orderBean?.order?.address.name+","+orderBean?.order?.address.mobile+","+orderBean?.order?.address.addr)'>
|
||||||
|
复制
|
||||||
|
</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class='addr c-flex-row'>
|
||||||
|
<image :src='assetsUrl("ic_location.png")' />
|
||||||
|
<text>{{ orderBean?.order?.address.addr }}</text>
|
||||||
|
</view>
|
||||||
|
<image class='dashed-line' :src='assetsUrl("ic_address_dashed_line.png")' />
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class='goods-info-view c-flex-column'>
|
||||||
|
<view class='c-flex-row' style='margin-bottom: 20rpx' v-for='(item,index) in orderBean?.order.orderGoods'
|
||||||
|
:key='index'>
|
||||||
|
<image class='goods-image' :src='item.stockStock.images||defaultImage' />
|
||||||
|
<view class='c-flex-column' style='flex: 1;'>
|
||||||
|
<view class='c-flex-row'>
|
||||||
|
<text class='goods-name'>{{ item.goodsName || '未知' }}</text>
|
||||||
|
</view>
|
||||||
|
<text style='color: #999999;margin-top: 30rpx'>
|
||||||
|
{{ item.goodsCode }}
|
||||||
|
</text>
|
||||||
|
<view class='bottom-view c-flex-row'>
|
||||||
|
<text>
|
||||||
|
{{ item.stockStock.colorName||'均色' }},{{ item.stockStock.sizeName||'均码' }} x{{ item.goodsNum }}
|
||||||
|
</text>
|
||||||
|
<text>{{ item.consumePrice }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class='divider' />
|
||||||
|
|
||||||
|
<view class='remark-view c-flex-row'>
|
||||||
|
<text style='flex: 1'>备注</text>
|
||||||
|
<text>{{ orderBean?.order?.remark || '无备注' }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class='card-view'>
|
||||||
|
<view class='c-flex-row'>
|
||||||
|
<text class='card-view-title'>商品总价</text>
|
||||||
|
<text class='card-view-value'>¥{{ orderBean?.order?.totalPrice }}</text>
|
||||||
|
</view>
|
||||||
|
<view class='c-flex-row'>
|
||||||
|
<text class='card-view-title'>运费</text>
|
||||||
|
<text class='card-view-value'>¥0</text>
|
||||||
|
</view>
|
||||||
|
<view class='c-flex-row'>
|
||||||
|
<text class='card-view-title'>优惠券
|
||||||
|
<text style='font-size: 22rpx;color: #F32B2B;'>已选最大优惠</text>
|
||||||
|
</text>
|
||||||
|
<text class='card-view-value' style='color: #F32B2B;margin: 0'>-¥{{ orderBean?.order?.reducePrice }}
|
||||||
|
</text>
|
||||||
|
</view>
|
||||||
|
<view class='divider' />
|
||||||
|
<view class='c-flex-row'>
|
||||||
|
<view style='flex: 1' />
|
||||||
|
<view class='c-flex-row'>
|
||||||
|
<text class='card-view-value'>共{{ orderBean?.order?.itemNum }}件商品 合计:
|
||||||
|
<text style='font-size: 34rpx;color:#F32B2B'>¥{{ orderBean?.order?.totalPrice }}</text>
|
||||||
|
</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class='order-no c-flex-column'>
|
||||||
|
<text>订单编号:{{ orderBean?.order?.id }}
|
||||||
|
<text style='color: #5B96FB;margin-left: 10rpx' @click.stop='copy(orderBean?.order?.id||"")'>复制</text>
|
||||||
|
</text>
|
||||||
|
<text>下单时间:{{ orderBean?.order?.createTime }}</text>
|
||||||
|
<text>
|
||||||
|
支付状态:
|
||||||
|
<text v-if='orderBean?.order?.payStatus == 2' style='color: #F32B2B'>已支付</text>
|
||||||
|
<text v-else-if='isPending(orderBean?.order)' style='color: #F32B2B'>待支付</text>
|
||||||
|
<text v-else style='color: #999999'>已过期</text>
|
||||||
|
</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class='bottom-action-view c-flex-row' v-if='isPending(orderBean?.order)'>
|
||||||
|
<text @click.stop='cancel' style='display: none'>取消订单</text>
|
||||||
|
<sqb-pay @navigateTo='navigateTo'
|
||||||
|
:return_url='buildSqbParams.return_url'
|
||||||
|
:total_amount='buildSqbParams.total_amount'
|
||||||
|
:terminal_sn='buildSqbParams.terminal_sn'
|
||||||
|
:client_sn='buildSqbParams.client_sn'
|
||||||
|
:subject='buildSqbParams.subject'
|
||||||
|
:merchant_name='buildSqbParams.merchant_name'
|
||||||
|
:notify_url='buildSqbParams.notify_url'
|
||||||
|
:sign='buildSqbParams.sign'>
|
||||||
|
<button @click='payment'>立即支付</button>
|
||||||
|
</sqb-pay>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</scroll-view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang='ts' setup>
|
||||||
|
import { assetsUrl, defaultImage } from '@/utils/assets';
|
||||||
|
import { getOrderDetail } from '@/api/order';
|
||||||
|
import { OrderBean } from '@/api/order/types';
|
||||||
|
import { copy, parseParameter, sortASCII } from '@/utils';
|
||||||
|
import { hexMD5 } from '@/utils/common/md5';
|
||||||
|
import { useUserStore } from '@/store';
|
||||||
|
import { getOrderDeadline, handlePayResult, isPending } from '@/utils/order';
|
||||||
|
import dayjs from 'dayjs';
|
||||||
|
|
||||||
|
const userState = useUserStore();
|
||||||
|
const { terminalInfo } = storeToRefs(userState);
|
||||||
|
|
||||||
|
const orderBean = ref<{
|
||||||
|
order: OrderBean,
|
||||||
|
stock: any[],
|
||||||
|
paymentList: []
|
||||||
|
}>();
|
||||||
|
|
||||||
|
let currentInterval = 0;
|
||||||
|
|
||||||
|
onLoad(async (e: any) => {
|
||||||
|
await fetchData(e.orderId);
|
||||||
|
handleCountdown();
|
||||||
|
});
|
||||||
|
|
||||||
|
const fetchData = async (orderId: string) => {
|
||||||
|
await uni.showLoading();
|
||||||
|
orderBean.value = await getOrderDetail(orderId);
|
||||||
|
if(orderBean.value?.order.address) {
|
||||||
|
orderBean.value.order.address = JSON.parse(orderBean?.value.order?.address);
|
||||||
|
}
|
||||||
|
uni.hideLoading();
|
||||||
|
};
|
||||||
|
|
||||||
|
onUnload(() => {
|
||||||
|
clearInterval(currentInterval);
|
||||||
|
});
|
||||||
|
|
||||||
|
const buildSqbParams = computed(() => {
|
||||||
|
const params = sortASCII({
|
||||||
|
client_sn: orderBean.value?.order?.id || '',
|
||||||
|
return_url: '/pages/common/payresult/index',
|
||||||
|
total_amount: Number(((orderBean.value?.order?.totalPrice || 0) * 100).toFixed(2)),
|
||||||
|
terminal_sn: terminalInfo.value.terminalSn,
|
||||||
|
subject: '商品支付',
|
||||||
|
merchant_name: terminalInfo.value.companyName,
|
||||||
|
notify_url: 'https://www.baidu.com'
|
||||||
|
}, true);
|
||||||
|
return {
|
||||||
|
...params,
|
||||||
|
sign: hexMD5(parseParameter(params) + '&key=' + terminalInfo.value.terminalKey).toUpperCase()
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const navigateTo = (e: any) => {
|
||||||
|
handlePayResult(orderBean.value?.order.id, e, {
|
||||||
|
onSuccess: () => {
|
||||||
|
fetchData(orderBean.value?.order.id || '');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCountdown = () => {
|
||||||
|
clearInterval(currentInterval);
|
||||||
|
currentInterval = setInterval(() => {
|
||||||
|
if(orderBean.value != undefined) {
|
||||||
|
if(isPending(orderBean.value?.order)) {
|
||||||
|
let second = (getOrderDeadline(orderBean.value?.order) - Date.now()) / 1000;
|
||||||
|
orderBean.value.order.countdown = second;
|
||||||
|
if(second <= 0) {
|
||||||
|
fetchData(orderBean.value?.order.id || '');
|
||||||
|
}
|
||||||
|
second--;
|
||||||
|
} else {
|
||||||
|
clearInterval(currentInterval);
|
||||||
|
fetchData(orderBean.value?.order.id || '');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, 1000);
|
||||||
|
};
|
||||||
|
|
||||||
|
const cancel = () => {
|
||||||
|
};
|
||||||
|
const payment = () => {
|
||||||
|
console.log(buildSqbParams.value);
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang='scss' scoped>
|
||||||
|
.content {
|
||||||
|
padding: 20rpx 30rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.countdown {
|
||||||
|
padding: 10rpx 30rpx 30rpx 30rpx;
|
||||||
|
|
||||||
|
image:nth-of-type(1) {
|
||||||
|
width: 60rpx;
|
||||||
|
height: 74rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
view:not(.c-flex-row):nth-of-type(1) {
|
||||||
|
margin-left: 23rpx;
|
||||||
|
|
||||||
|
text:nth-of-type(1) {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 36rpx;
|
||||||
|
color: #333333;
|
||||||
|
}
|
||||||
|
|
||||||
|
view:nth-of-type(1) {
|
||||||
|
margin-top: 5rpx;
|
||||||
|
|
||||||
|
image {
|
||||||
|
width: 30rpx;
|
||||||
|
height: 30rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
text {
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 26rpx;
|
||||||
|
color: #333333;
|
||||||
|
margin-left: 8rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.address-view {
|
||||||
|
padding-top: 30rpx;
|
||||||
|
background: #FFFFFF;
|
||||||
|
|
||||||
|
.user-info {
|
||||||
|
margin-left: 20rpx;
|
||||||
|
margin-right: 20rpx;
|
||||||
|
|
||||||
|
.status {
|
||||||
|
padding: 2rpx 10rpx;
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #F32B2B;
|
||||||
|
border-radius: 5rpx;
|
||||||
|
border: 1rpx solid #F32B2B;
|
||||||
|
margin-right: 12rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
text:nth-of-type(n+2) {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #333333;
|
||||||
|
margin-left: 10rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
image {
|
||||||
|
width: 8rpx;
|
||||||
|
height: 16rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.addr {
|
||||||
|
margin-top: 15rpx;
|
||||||
|
margin-left: 20rpx;
|
||||||
|
|
||||||
|
image {
|
||||||
|
width: 30rpx;
|
||||||
|
height: 37rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
text {
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 26rpx;
|
||||||
|
color: #999999;
|
||||||
|
margin-left: 16rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.dashed-line {
|
||||||
|
width: 100%;
|
||||||
|
height: 8rpx;
|
||||||
|
margin-top: 37rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.goods-info-view {
|
||||||
|
display: flex;
|
||||||
|
position: relative;
|
||||||
|
background: #FFFFFF;
|
||||||
|
margin-top: 20rpx;
|
||||||
|
border-radius: 10rpx;
|
||||||
|
padding: 30rpx 20rpx;
|
||||||
|
|
||||||
|
.goods-image {
|
||||||
|
width: 180rpx;
|
||||||
|
height: 180rpx;
|
||||||
|
border-radius: 10rpx;
|
||||||
|
margin-right: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.goods-name {
|
||||||
|
font-size: 30rpx;
|
||||||
|
font-weight: 400;
|
||||||
|
-webkit-line-clamp: 2;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
overflow: hidden;
|
||||||
|
margin-right: 20rpx;
|
||||||
|
color: #333333;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bottom-view {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-top: 10rpx;
|
||||||
|
|
||||||
|
text:nth-of-type(1) {
|
||||||
|
font-size: 26rpx;
|
||||||
|
font-weight: 400;
|
||||||
|
flex: 1;
|
||||||
|
color: #999999;
|
||||||
|
}
|
||||||
|
|
||||||
|
text:nth-of-type(2) {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 36rpx;
|
||||||
|
color: #333333;
|
||||||
|
}
|
||||||
|
|
||||||
|
text:nth-of-type(2):before {
|
||||||
|
content: '¥';
|
||||||
|
}
|
||||||
|
|
||||||
|
text:nth-of-type(3) {
|
||||||
|
font-size: 34rpx;
|
||||||
|
color: #333333;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.divider {
|
||||||
|
margin: 30rpx 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.remark-view {
|
||||||
|
text {
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #333333;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-view {
|
||||||
|
margin-top: 20rpx;
|
||||||
|
padding: 0 25rpx 0 23rpx;
|
||||||
|
|
||||||
|
view:not(.divider):nth-of-type(n+1) {
|
||||||
|
margin: 20rpx 0;
|
||||||
|
|
||||||
|
.card-view-title {
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #333333;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-view-value {
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 26rpx;
|
||||||
|
color: #333333;
|
||||||
|
|
||||||
|
image {
|
||||||
|
width: 8rpx;
|
||||||
|
height: 16rpx;
|
||||||
|
margin-left: 16rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.order-no {
|
||||||
|
background: #FFFFFF;
|
||||||
|
border-radius: 10rpx;
|
||||||
|
padding: 22rpx 23rpx;
|
||||||
|
margin-top: 20rpx;
|
||||||
|
margin-bottom: 200rpx;
|
||||||
|
|
||||||
|
text:nth-of-type(n+1) {
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 26rpx;
|
||||||
|
color: #333333;
|
||||||
|
}
|
||||||
|
|
||||||
|
text:nth-of-type(3) {
|
||||||
|
margin-bottom: 0rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.bottom-action-view {
|
||||||
|
background: #FFFFFF;
|
||||||
|
position: fixed;
|
||||||
|
height: 80rpx;
|
||||||
|
justify-content: flex-end;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
padding: 12rpx 30rpx 78rpx 30rpx;
|
||||||
|
|
||||||
|
text:nth-of-type(1) {
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #333333;
|
||||||
|
border-radius: 50rpx;
|
||||||
|
padding: 17rpx 45rpx;
|
||||||
|
border: 1rpx solid #707070;
|
||||||
|
margin-right: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
sqb-pay button {
|
||||||
|
padding: 0 45rpx;
|
||||||
|
border-radius: 50rpx;
|
||||||
|
border: 2rpx solid #F32B2B;
|
||||||
|
font-weight: bold;
|
||||||
|
background: #FFFFFF;
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #F32B2B;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
104
src/pages/mine/subs/order/index.vue
Normal file
104
src/pages/mine/subs/order/index.vue
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
<template>
|
||||||
|
<tabbar :titles="['全部', '未支付', '已支付']" :index='payStatus' @change='tabChange' />
|
||||||
|
<u-list :list='orderList' :border='false' @scrolltolower='loadMore'>
|
||||||
|
<u-list-item v-for='(item,index) in orderList' :key='index'>
|
||||||
|
<order-item :item='item' @addShoppingCart='addShoppingCart' @pay='payment' />
|
||||||
|
</u-list-item>
|
||||||
|
<u-loadmore v-if='orderList.length>0' :status='loadingStatus' />
|
||||||
|
<u-empty v-if='orderList.length === 0' text='暂无数据' margin-top='100' />
|
||||||
|
</u-list>
|
||||||
|
<sku-dialog ref='skuDialogRef' :exists='temporaryStockBean' />
|
||||||
|
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang='ts' setup>
|
||||||
|
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import { showToast } from '@/utils';
|
||||||
|
import { getOrderDeadline, isPending } from '@/utils/order';
|
||||||
|
import { getOrderList } from '@/api/order';
|
||||||
|
import OrderItem from '@/pages/mine/subs/order/components/order-item.vue';
|
||||||
|
import { OrderBean } from '@/api/order/types';
|
||||||
|
import SkuDialog from '@/components/sku-dialog.vue';
|
||||||
|
import { GoodsBean, StockBean } from '@/api/goods/types';
|
||||||
|
import useShoppingCartStore from '@/store/modules/shoppingcart';
|
||||||
|
|
||||||
|
const shoppingCartStore = useShoppingCartStore();
|
||||||
|
const skuDialogRef = ref();
|
||||||
|
const temporaryStockBean = ref<StockBean>();
|
||||||
|
const orderList = ref<OrderBean[]>([]);
|
||||||
|
const currentPageNum = ref(1);
|
||||||
|
const payStatus = ref(0);
|
||||||
|
const loadingStatus = ref('loading');
|
||||||
|
|
||||||
|
let currentInterval = 0;
|
||||||
|
|
||||||
|
onLoad((e: any) => {
|
||||||
|
const index = Number(e.index) || 0;
|
||||||
|
tabChange(index);
|
||||||
|
});
|
||||||
|
|
||||||
|
onUnload(() => {
|
||||||
|
clearInterval(currentInterval);
|
||||||
|
});
|
||||||
|
|
||||||
|
const tabChange = (index: number) => {
|
||||||
|
payStatus.value = index;
|
||||||
|
fetchData(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const fetchData = async (refresh: boolean = true) => {
|
||||||
|
loadingStatus.value = 'loading';
|
||||||
|
if(!refresh) {
|
||||||
|
currentPageNum.value += 1;
|
||||||
|
}
|
||||||
|
const { list } = await getOrderList({
|
||||||
|
pageNum: currentPageNum.value,
|
||||||
|
pageSize: 20,
|
||||||
|
obj: { payStatus: payStatus.value }
|
||||||
|
});
|
||||||
|
if(refresh) {
|
||||||
|
orderList.value = list;
|
||||||
|
} else {
|
||||||
|
orderList.value = orderList.value.concat(list);
|
||||||
|
}
|
||||||
|
loadingStatus.value = 'no';
|
||||||
|
handleCountdown(orderList.value.filter(item => item.payStatus == 1));
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCountdown = (items: OrderBean[]) => {
|
||||||
|
clearInterval(currentInterval);
|
||||||
|
currentInterval = setInterval(() => {
|
||||||
|
items.forEach(item => {
|
||||||
|
if(isPending(item)) {
|
||||||
|
let second = (getOrderDeadline(item) - Date.now()) / 1000;
|
||||||
|
item.countdown = second;
|
||||||
|
if(item.countdown <= 0) {
|
||||||
|
item.countdown = 0;
|
||||||
|
}
|
||||||
|
second--;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, 1000);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const loadMore = () => {
|
||||||
|
fetchData(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const addShoppingCart = (item: GoodsBean) => {
|
||||||
|
skuDialogRef.value.show(item.goodsId, (e: GoodsBean) => {
|
||||||
|
shoppingCartStore.save(e);
|
||||||
|
showToast('加入购物车成功');
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const payment = (orderId: string) => {
|
||||||
|
console.log(orderId);
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang='scss' scoped>
|
||||||
|
|
||||||
|
</style>
|
||||||
256
src/pages/mine/subs/profile/index.vue
Normal file
256
src/pages/mine/subs/profile/index.vue
Normal file
@@ -0,0 +1,256 @@
|
|||||||
|
<template>
|
||||||
|
<view class='content'>
|
||||||
|
<view class='top-card-view'>
|
||||||
|
<image class='bg-image' :src='companyConfigInfo.userbgcover' />
|
||||||
|
<image class='avatar-image' :src='params.image' />
|
||||||
|
<text>{{ userInfo.nickName }}</text>
|
||||||
|
<text>{{ userInfo.levelName }}</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class='basic-info-view c-flex-column'>
|
||||||
|
<view class='c-flex-row'>
|
||||||
|
<text>头像</text>
|
||||||
|
<view class='avatar-view'>
|
||||||
|
<image class='avatar-image' :src='params.image' />
|
||||||
|
<button class='avatar-btn' open-type='chooseAvatar' @chooseavatar='chooseAvatar' />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class='c-flex-row'>
|
||||||
|
<text class='nickname'>姓名</text>
|
||||||
|
<input placeholder='请输入姓名' type='nickname' v-model='userInfo.nickName' @change='bindNickname' />
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class='divider' />
|
||||||
|
<view class='c-flex-row'>
|
||||||
|
<text>手机号</text>
|
||||||
|
<input placeholder='请输入手机号' :disabled='(userInfo.telephone?.length||0)!=0'
|
||||||
|
v-model='params.telephone'
|
||||||
|
@input='bindTelephone' />
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class='divider' />
|
||||||
|
<view class='c-flex-row'>
|
||||||
|
<text>性别</text>
|
||||||
|
<view class='c-flex-row' @click.stop='changeGender(0)'>
|
||||||
|
<image class='gender-image'
|
||||||
|
:src='assetsUrl(params?.gender=="男"?"ic_checkbox_active.png":"ic_checkbox_normal.png")' />
|
||||||
|
<text class='gender-text'>男</text>
|
||||||
|
</view>
|
||||||
|
<view class='c-flex-row' @click.stop='changeGender(1)'>
|
||||||
|
<image class='gender-image'
|
||||||
|
:src='assetsUrl(params?.gender=="女"?"ic_checkbox_active.png":"ic_checkbox_normal.png")' />
|
||||||
|
<text class='gender-text'>女</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class='divider' />
|
||||||
|
<view class='c-flex-row'>
|
||||||
|
<text>生日</text>
|
||||||
|
<picker mode='date' :disabled='(userInfo.birthday?.length||0)!=0' @change='changeDate'>
|
||||||
|
<text>{{ dayjs(params?.birthday || Date.now()).format('YYYY-MM-DD') || '请选择生日' }}</text>
|
||||||
|
</picker>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<button class='primary-button' @click.stop='save'>保存</button>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang='ts' setup>
|
||||||
|
import { assetsUrl } from '@/utils/assets';
|
||||||
|
import { useUserStore } from '@/store';
|
||||||
|
import { showToast } from '@/utils';
|
||||||
|
import { updateProfile } from '@/api/user';
|
||||||
|
import dayjs from 'dayjs';
|
||||||
|
|
||||||
|
const store = useUserStore();
|
||||||
|
const { userInfo, companyConfigInfo } = storeToRefs(store);
|
||||||
|
|
||||||
|
const params = ref<{
|
||||||
|
avatarUrl: string | undefined;
|
||||||
|
image: string;
|
||||||
|
nickName: string;
|
||||||
|
telephone: string;
|
||||||
|
gender: string;
|
||||||
|
birthday: string;
|
||||||
|
}>({
|
||||||
|
avatarUrl: userInfo.value.image,
|
||||||
|
image: userInfo.value.image,
|
||||||
|
nickName: userInfo.value.nickName,
|
||||||
|
telephone: userInfo.value.telephone,
|
||||||
|
gender: userInfo.value.gender,
|
||||||
|
birthday: userInfo.value.birthday|| dayjs().format('YYYY-MM-DD')
|
||||||
|
});
|
||||||
|
|
||||||
|
onLoad(() => {
|
||||||
|
// store.getProfile();
|
||||||
|
});
|
||||||
|
|
||||||
|
const chooseAvatar = (e: any) => {
|
||||||
|
uni.showLoading();
|
||||||
|
uni.uploadFile({
|
||||||
|
url: import.meta.env.VITE_APP_BASE_API + '/wc/wechat/uploadImage',
|
||||||
|
filePath: e.detail.avatarUrl,
|
||||||
|
name: 'fileName',
|
||||||
|
header: {
|
||||||
|
'Content-Type': 'multipart/form-data'
|
||||||
|
},
|
||||||
|
success: (res: any) => {
|
||||||
|
params.value!.avatarUrl = JSON.parse(res.data).data;
|
||||||
|
params.value!.image = JSON.parse(res.data).data;
|
||||||
|
},
|
||||||
|
error: (err: any) => {
|
||||||
|
showToast('上传失败');
|
||||||
|
},
|
||||||
|
complete() {
|
||||||
|
uni.hideLoading();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const bindNickname = (e: any) => {
|
||||||
|
params.value!.nickName = e.detail.value;
|
||||||
|
};
|
||||||
|
|
||||||
|
const bindTelephone = (e: any) => {
|
||||||
|
params.value!.telephone = e.detail.value;
|
||||||
|
};
|
||||||
|
|
||||||
|
const changeGender = (index: number) => {
|
||||||
|
params.value!.gender = index == 0 ? '男' : '女';
|
||||||
|
};
|
||||||
|
|
||||||
|
const changeDate = (e: any) => {
|
||||||
|
params.value!.birthday = e.detail.value;
|
||||||
|
};
|
||||||
|
|
||||||
|
const save = async () => {
|
||||||
|
const newUserInfo = {
|
||||||
|
...userInfo.value,
|
||||||
|
...params.value
|
||||||
|
};
|
||||||
|
|
||||||
|
delete params.value.avatarUrl;
|
||||||
|
|
||||||
|
const result = await updateProfile({
|
||||||
|
...params.value,
|
||||||
|
birthday: dayjs(birthday.value).isValid() ? dayjs(birthday.value).format('YYYY-MM-DD HH:mm:ss') : dayjs().format('YYYY-MM-DD HH:mm:ss'),
|
||||||
|
birthdayType: 0
|
||||||
|
});
|
||||||
|
|
||||||
|
if(result) {
|
||||||
|
await store.setUserInfo(newUserInfo);
|
||||||
|
showToast('修改成功', {
|
||||||
|
icon: 'success', complete: () => {
|
||||||
|
uni.navigateBack();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
showToast('服务异常,操作失败', { icon: 'error' });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang='scss' scoped>
|
||||||
|
.top-card-view {
|
||||||
|
display: flex;
|
||||||
|
height: 338rpx;
|
||||||
|
position: relative;
|
||||||
|
margin: 30rpx;
|
||||||
|
|
||||||
|
.bg-image {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
border-radius: 30rpx;
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar-image {
|
||||||
|
width: 95rpx;
|
||||||
|
height: 95rpx;
|
||||||
|
margin-left: 36rpx;
|
||||||
|
margin-top: 60rpx;
|
||||||
|
background: #FFFFFF;
|
||||||
|
border: 1rpx solid #707070;
|
||||||
|
position: relative;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
text:nth-of-type(1) {
|
||||||
|
font-size: 30rpx;
|
||||||
|
font-weight: 800;
|
||||||
|
color: #FFFFFF;
|
||||||
|
position: absolute;
|
||||||
|
top: 64rpx;
|
||||||
|
left: 158rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
text:nth-of-type(2) {
|
||||||
|
font-size: 24rpx;
|
||||||
|
font-weight: 400;
|
||||||
|
color: #FFFFFF;
|
||||||
|
position: absolute;
|
||||||
|
top: 116rpx;
|
||||||
|
left: 158rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.basic-info-view {
|
||||||
|
margin: 0 30rpx 30rpx 30rpx;
|
||||||
|
|
||||||
|
.avatar-view {
|
||||||
|
display: flex;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.avatar-image {
|
||||||
|
width: 110rpx;
|
||||||
|
height: 110rpx;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar-btn {
|
||||||
|
@extend .avatar-image;
|
||||||
|
position: absolute;
|
||||||
|
border: none;
|
||||||
|
background: #00000000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
font-size: 30rpx;
|
||||||
|
font-weight: 400;
|
||||||
|
color: #333333;
|
||||||
|
}
|
||||||
|
|
||||||
|
view:not(.divider):nth-of-type(n+1) {
|
||||||
|
padding: 0 20rpx;
|
||||||
|
height: 120rpx;
|
||||||
|
|
||||||
|
.gender-image {
|
||||||
|
width: 37rpx;
|
||||||
|
height: 37rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.gender-text {
|
||||||
|
width: 80rpx;
|
||||||
|
color: #333333;
|
||||||
|
font-size: 30rpx;
|
||||||
|
margin-left: 10rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
text:not(.gender-text):nth-of-type(1) {
|
||||||
|
font-size: 30rpx;
|
||||||
|
width: 120rpx;
|
||||||
|
font-weight: 400;
|
||||||
|
color: #7E7E7E;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nickname:before {
|
||||||
|
content: '*';
|
||||||
|
color: #F32B2B;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
289
src/pages/mine/subs/recharge/index.vue
Normal file
289
src/pages/mine/subs/recharge/index.vue
Normal file
@@ -0,0 +1,289 @@
|
|||||||
|
<template>
|
||||||
|
<view class='content'>
|
||||||
|
<view class='balance-view'>
|
||||||
|
<image :src='assetsUrl("bg_member_recharge.png")' />
|
||||||
|
<view class='balance-content'>
|
||||||
|
<text>累计余额(元)</text>
|
||||||
|
<text>¥{{ userInfo?.totalIncoming }}</text>
|
||||||
|
</view>
|
||||||
|
<view class='balance-content'>
|
||||||
|
<text>当前余额(元)</text>
|
||||||
|
<text class='accent-text-color'>¥{{ userInfo?.balance }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class='recharge-option-card'>
|
||||||
|
<view class='top-border'></view>
|
||||||
|
<text class='title'>充值金额</text>
|
||||||
|
<scroll-view scroll-y style='flex: 1;padding-bottom: 180rpx'>
|
||||||
|
<view class='option-item' :class="{'option-item-active': currentIndex==index}"
|
||||||
|
v-for='(item,index) in rechargeItems' :key='index' @click.stop='change(index)'>
|
||||||
|
<image v-if='currentIndex==index' class='checked-image' src='/static/images/ic_recharge_checked.png' />
|
||||||
|
<label class='amount-title'>{{ item.rechargeamount }}元</label>
|
||||||
|
<view class='divider' style='margin-bottom: 36rpx' />
|
||||||
|
<view class='card-view'>
|
||||||
|
<view class='title-container'>
|
||||||
|
<text>充值{{ item?.rechargeamount || 0 }}送{{ item?.rewardamount || 0
|
||||||
|
}}元
|
||||||
|
</text>
|
||||||
|
<text class='accent-text-color'>
|
||||||
|
实得{{ item?.rechargeamount + (item?.rewardamount) }}元
|
||||||
|
</text>
|
||||||
|
</view>
|
||||||
|
<text class='description'>送{{ item.rewardamount || 0 }}元、送{{ item.rewardcouponamount || 0
|
||||||
|
}}元优惠券共{{ item.rewardcouponnum || 0 }}张、
|
||||||
|
返利{{ item.rewardrefundamount || 0 }}元
|
||||||
|
</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</scroll-view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class='bottom-button-view'>
|
||||||
|
<!-- <payment-button style='flex: 1' :payParams='buildSignParams'>-->
|
||||||
|
<sqb-pay style='width: 100%;' @navigateTo='navigateTo'
|
||||||
|
:return_url='buildSqbParams.return_url'
|
||||||
|
:total_amount='buildSqbParams.total_amount'
|
||||||
|
:terminal_sn='buildSqbParams.terminal_sn'
|
||||||
|
:client_sn='buildSqbParams.client_sn'
|
||||||
|
:subject='buildSqbParams.subject'
|
||||||
|
:merchant_name='buildSqbParams.merchant_name'
|
||||||
|
:notify_url='buildSqbParams.notify_url'
|
||||||
|
:sign='buildSqbParams.sign'>
|
||||||
|
<button class='primary-button'>充值</button>
|
||||||
|
</sqb-pay>
|
||||||
|
<!-- </payment-button>-->
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang='ts' setup>
|
||||||
|
import { assetsUrl } from '@/utils/assets';
|
||||||
|
import { useUserStore } from '@/store';
|
||||||
|
import { getRechargeList, preRecharge, rechargeVerify } from '@/api/user';
|
||||||
|
import { parseParameter, sortASCII } from '@/utils';
|
||||||
|
import { hexMD5 } from '@/utils/common/md5';
|
||||||
|
import { handlePayResult } from '@/utils/order';
|
||||||
|
|
||||||
|
const userState = useUserStore();
|
||||||
|
const { userInfo, terminalInfo } = storeToRefs(userState);
|
||||||
|
|
||||||
|
const rechargeOptionBackgroundUrl = assetsUrl('bg_member_recharge_item.png');
|
||||||
|
|
||||||
|
const rechargeItems = ref<{
|
||||||
|
itemid: string
|
||||||
|
rechargeamount: number
|
||||||
|
rewardamount: number
|
||||||
|
rewardcouponamount: number,
|
||||||
|
rewardcouponnum: number
|
||||||
|
rechargetype: number,
|
||||||
|
rewardrefundamount: number
|
||||||
|
}[]>([]);
|
||||||
|
const currentIndex = ref<number>(0);
|
||||||
|
const preRechargeOrderId = ref();
|
||||||
|
|
||||||
|
onLoad(async () => {
|
||||||
|
const { ruleitems } = await getRechargeList();
|
||||||
|
rechargeItems.value = ruleitems;
|
||||||
|
// rechargeItems.value.push(rechargeItems.value[0]);
|
||||||
|
// rechargeItems.value.push(rechargeItems.value[0]);
|
||||||
|
// rechargeItems.value.push(rechargeItems.value[0]);
|
||||||
|
// rechargeItems.value.push(rechargeItems.value[0]);
|
||||||
|
|
||||||
|
console.log(rechargeItems.value);
|
||||||
|
await change(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
const change = async (index: number) => {
|
||||||
|
currentIndex.value = index;
|
||||||
|
const { id } = await preRecharge({
|
||||||
|
itemid: rechargeItems.value[index].itemid
|
||||||
|
});
|
||||||
|
preRechargeOrderId.value = id;
|
||||||
|
};
|
||||||
|
|
||||||
|
const buildSqbParams = computed(() => {
|
||||||
|
const params = sortASCII({
|
||||||
|
client_sn: preRechargeOrderId.value,
|
||||||
|
return_url: '/pages/common/payresult/index',
|
||||||
|
total_amount: Number(((rechargeItems.value[currentIndex.value]?.rechargeamount || 0) * 100).toFixed(2)),
|
||||||
|
terminal_sn: terminalInfo.value.terminalSn,
|
||||||
|
subject: '充值',
|
||||||
|
merchant_name: terminalInfo.value.companyName,
|
||||||
|
notify_url: 'https://www.baidu.com'
|
||||||
|
}, true);
|
||||||
|
return {
|
||||||
|
...params,
|
||||||
|
sign: hexMD5(parseParameter(params) + '&key=' + terminalInfo.value.terminalKey).toUpperCase()
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const navigateTo = (e: any) => {
|
||||||
|
handlePayResult(preRechargeOrderId.value, e, {
|
||||||
|
onSuccess: async () => {
|
||||||
|
await goRecharge();
|
||||||
|
await userState.setUserInfo({
|
||||||
|
...userInfo.value,
|
||||||
|
balance: Number(userInfo.value.balance) + Number(rechargeItems.value[currentIndex.value].rechargeamount) + Number(rechargeItems.value[currentIndex.value]?.rewardamount)
|
||||||
|
});
|
||||||
|
await uni.navigateBack();
|
||||||
|
},
|
||||||
|
onFailure: () => {
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const goRecharge = async () => {
|
||||||
|
// const result = await recharge({
|
||||||
|
// itemid: rechargeItems.value[currentIndex.value].itemid
|
||||||
|
// });
|
||||||
|
// console.log('platform recharge result ', result);
|
||||||
|
await rechargeVerify({
|
||||||
|
payid: preRechargeOrderId.value
|
||||||
|
});
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang='scss' scoped>
|
||||||
|
.balance-view {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
height: 280rpx;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
image {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
.balance-content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
position: relative;
|
||||||
|
flex: 1;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
color: white;
|
||||||
|
|
||||||
|
text:nth-of-type(1) {
|
||||||
|
font-size: 30rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
text:nth-of-type(2) {
|
||||||
|
font-size: 40rpx;
|
||||||
|
margin-top: 10rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.recharge-option-card {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
background: #F5F5F5;
|
||||||
|
position: relative;
|
||||||
|
//margin-top: -25rpx;
|
||||||
|
|
||||||
|
.top-border {
|
||||||
|
background: #FFFFFF;
|
||||||
|
height: 30rpx;
|
||||||
|
margin-top: -35rpx;
|
||||||
|
border-radius: 30rpx 30rpx 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
font-size: 30rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #333333;
|
||||||
|
background: #FFFFFF;
|
||||||
|
border-radius: 10rpx 10rpx 0 0;
|
||||||
|
padding: 10rpx 20rpx 20rpx 20rpx;
|
||||||
|
margin-bottom: 20rpx;
|
||||||
|
margin-top: -15rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.option-item {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
margin: 10rpx 20rpx 20rpx 20rpx;
|
||||||
|
background: #FFFFFF;
|
||||||
|
border-radius: 20rpx;
|
||||||
|
padding-top: 20rpx;
|
||||||
|
box-sizing: border-box;
|
||||||
|
border: solid #00000000 2rpx;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.amount-title {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 40rpx;
|
||||||
|
width: fit-content;
|
||||||
|
color: #333333;
|
||||||
|
margin-left: 30rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.amount-title:after {
|
||||||
|
content: "";
|
||||||
|
display: block;
|
||||||
|
border: 2rpx solid black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.checked-image {
|
||||||
|
width: 70rpx;
|
||||||
|
height: 70rpx;
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
top: 0;
|
||||||
|
border-radius: 0 18rpx 0 0
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-view {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
width: 100%;
|
||||||
|
height: 167rpx;
|
||||||
|
border-radius: 20rpx;
|
||||||
|
//background-image: url(v-bind(rechargeOptionBackgroundUrl));
|
||||||
|
background-image: url('https://img.lakeapp.cn/wx/images/bg_member_recharge_item.png');
|
||||||
|
background-size: 100% 100%;
|
||||||
|
justify-content: flex-start;
|
||||||
|
color: #FFFFFF;
|
||||||
|
|
||||||
|
.title-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-top: 27rpx;
|
||||||
|
padding: 0 30rpx;
|
||||||
|
|
||||||
|
text:nth-of-type(1) {
|
||||||
|
display: flex;
|
||||||
|
font-size: 36rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
text:nth-of-type(2) {
|
||||||
|
display: flex;
|
||||||
|
font-size: 30rpx;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 185rpx;
|
||||||
|
height: 50rpx;
|
||||||
|
background: #FFFFFF;
|
||||||
|
border-radius: 25rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.description {
|
||||||
|
margin-top: 30rpx;
|
||||||
|
margin-left: 30rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.option-item-active {
|
||||||
|
@extend .option-item;
|
||||||
|
border: 2rpx solid #f95e5d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
48
src/pages/mine/subs/trade/components/trade-item.vue
Normal file
48
src/pages/mine/subs/trade/components/trade-item.vue
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
<template>
|
||||||
|
<view class='card-view'>
|
||||||
|
<!-- <text class='category-title'>2023-02-12</text>-->
|
||||||
|
<!-- <view class='item c-flex-column' v-for='(item,index) in 3' :key='index'>-->
|
||||||
|
<view class='c-flex-row'>
|
||||||
|
<text class='primary-text-color' style='flex: 1'>{{ item.name }}</text>
|
||||||
|
<text class='accent-text-color'>{{item.type===1?'-':'+'}}{{
|
||||||
|
item.transactionPrice || 0 }}</text>
|
||||||
|
</view>
|
||||||
|
<view class='c-flex-row'>
|
||||||
|
<text class='secondary-text-color' style='flex: 1'>{{ item.createTime }}</text>
|
||||||
|
<text style='color: #999999'>会员余额:¥{{ item.finalPrice || 0 }}</text>
|
||||||
|
</view>
|
||||||
|
<!-- <view class='divider' style='margin-top: 20rpx' />-->
|
||||||
|
<!-- </view>-->
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang='ts' setup>
|
||||||
|
import { PropType } from 'vue';
|
||||||
|
|
||||||
|
defineProps({
|
||||||
|
item: Object as PropType<any>
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang='scss' scoped>
|
||||||
|
.card-view {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
padding: 16rpx 23rpx 20rpx 30rpx;
|
||||||
|
margin: 20rpx 0 10rpx 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.category-title {
|
||||||
|
font-size: 34rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #333333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item {
|
||||||
|
margin: 10rpx 0;
|
||||||
|
|
||||||
|
view:nth-of-type(2) {
|
||||||
|
margin-top: 10rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
103
src/pages/mine/subs/trade/index.vue
Normal file
103
src/pages/mine/subs/trade/index.vue
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
<template>
|
||||||
|
<tabbar :titles='["全部","充值","消费"]' @change='changeTab' :item-active-color='"#D95554"'
|
||||||
|
:indicator-color='"#D95554"' />
|
||||||
|
<view class='content'>
|
||||||
|
<!-- <view class='c-flex-row'>-->
|
||||||
|
<!-- <text>选择日期</text>-->
|
||||||
|
<!-- <picker mode='date' @change='changeDate'>-->
|
||||||
|
<!-- <view class='current-date c-flex-row'>-->
|
||||||
|
<!-- <text>{{ tradeDate }}</text>-->
|
||||||
|
<!-- <image :src='assetsUrl("ic_triangle_down.png")' />-->
|
||||||
|
<!-- </view>-->
|
||||||
|
<!-- </picker>-->
|
||||||
|
<!-- </view>-->
|
||||||
|
|
||||||
|
<u-list @scrolltolower='loadMore'>
|
||||||
|
<trade-item v-for='(item,index) in tradeList' :key='index' :item='item' />
|
||||||
|
<u-loadmore v-if='tradeList.length>0' :status='loadingStatus' />
|
||||||
|
<u-empty v-if='tradeList.length === 0' text='暂无数据' margin-top='100' />
|
||||||
|
</u-list>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang='ts' setup>
|
||||||
|
import TradeItem from './components/trade-item.vue';
|
||||||
|
import { getTradeList } from '@/api/user';
|
||||||
|
import dayjs from 'dayjs';
|
||||||
|
|
||||||
|
const tradeList = ref([]);
|
||||||
|
const tradeType = ref('');
|
||||||
|
const tradeDate = ref();
|
||||||
|
const currentPageNum = ref(1);
|
||||||
|
const loadingStatus = ref('loading');
|
||||||
|
|
||||||
|
onLoad((e) => {
|
||||||
|
tradeDate.value = dayjs(Date.now()).format('YYYY-MM-DD');
|
||||||
|
fetchData();
|
||||||
|
});
|
||||||
|
|
||||||
|
const changeDate = (e: any) => {
|
||||||
|
tradeDate.value = e.detail.value;
|
||||||
|
fetchData();
|
||||||
|
};
|
||||||
|
|
||||||
|
const changeTab = (index: number) => {
|
||||||
|
switch (index) {
|
||||||
|
case 0:
|
||||||
|
tradeType.value = '';
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
tradeType.value = '会员充值';
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
tradeType.value = '余额消费';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
fetchData();
|
||||||
|
};
|
||||||
|
|
||||||
|
const fetchData = async (refresh: boolean = true) => {
|
||||||
|
currentPageNum.value = refresh ? 1 : currentPageNum.value + 1;
|
||||||
|
loadingStatus.value = 'loading';
|
||||||
|
const { list } = await getTradeList({
|
||||||
|
// startDate: tradeDate.value,
|
||||||
|
// endDate: dayjs(tradeDate.value).add(1, 'day').format('YYYY-MM-DD'),
|
||||||
|
name: tradeType.value,
|
||||||
|
pageNum: currentPageNum.value,
|
||||||
|
pageSize: 20
|
||||||
|
});
|
||||||
|
if(refresh) {
|
||||||
|
tradeList.value = list;
|
||||||
|
} else {
|
||||||
|
tradeList.value = tradeList.value.concat(list);
|
||||||
|
}
|
||||||
|
loadingStatus.value = 'no';
|
||||||
|
};
|
||||||
|
|
||||||
|
const loadMore = () => {
|
||||||
|
fetchData(false);
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang='scss' scoped>
|
||||||
|
.content {
|
||||||
|
padding: 20rpx 24rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.current-date {
|
||||||
|
height: 50rpx;
|
||||||
|
background: #FFFFFF;
|
||||||
|
border-radius: 5rpx;
|
||||||
|
font-size: 28rpx;
|
||||||
|
font-weight: 400;
|
||||||
|
color: #333333;
|
||||||
|
padding: 0 20rpx;
|
||||||
|
margin-left: 10rpx;
|
||||||
|
|
||||||
|
image {
|
||||||
|
width: 19rpx;
|
||||||
|
height: 11rpx;
|
||||||
|
margin-left: 15rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -1,25 +1,258 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="flex flex-col items-center justify-center">
|
<view class='content'>
|
||||||
<image
|
<view class='member-info-view'>
|
||||||
class="mb-50rpx mt-200rpx h-200rpx w-200rpx"
|
<image :src='assetsUrl("ic_crown.png")' />
|
||||||
src="@/static/images/logo.png"
|
<view class='flex flex-col'>
|
||||||
width="200rpx"
|
<text>{{ userInfo?.levelName }}</text>
|
||||||
height="200rpx"
|
<view />
|
||||||
/>
|
</view>
|
||||||
<view class="flex justify-center">
|
</view>
|
||||||
<text class="font-size-36rpx color-gray-700">
|
|
||||||
{{ title }}
|
<view class='qrcode-card'>
|
||||||
</text>
|
<view class='balance-view'>
|
||||||
|
<text class='balance-text'>账户余额:{{ userInfo?.balance || 0 }}元</text>
|
||||||
|
<view class='btn-recharge' @click.stop='goPath("/pages/mine/subs/recharge/index")'>
|
||||||
|
<text>去充值</text>
|
||||||
|
<image :src='assetsUrl("ic_arrow_right.png")' />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class='divider' />
|
||||||
|
<view class='barcode-view'>
|
||||||
|
<image class='barcode' :src='code?.barCode'></image>
|
||||||
|
<text>{{ codeContent }}</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class='qrcode-view'>
|
||||||
|
<image class='qrcode' :src='code?.qrCode'></image>
|
||||||
|
<text>倒计时{{ codeRefreshInterval }}S后自动更新</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class='card-info-view'>
|
||||||
|
<view>
|
||||||
|
<image :src='assetsUrl("ic_card.png")' />
|
||||||
|
<text>卡信息</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<text>店铺名称({{ userInfo?.creatorName }})</text>
|
||||||
|
<text>{{ userInfo?.storeId }}</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang='ts'>
|
||||||
|
import { onLoad } from '@dcloudio/uni-app';
|
||||||
|
import { assetsUrl } from '@/utils/assets';
|
||||||
|
import { generateBarCode, generateQrCode } from '@/api/common';
|
||||||
|
import { getDynamicCode } from '@/api/user';
|
||||||
import { useUserStore } from '@/store';
|
import { useUserStore } from '@/store';
|
||||||
|
import { goLogin, goPath, isLogin } from '@/utils';
|
||||||
const title = ref<string>();
|
|
||||||
title.value = import.meta.env.VITE_APP_TITLE;
|
|
||||||
|
|
||||||
const store = useUserStore();
|
const store = useUserStore();
|
||||||
console.log('store.user_name', store.user_name);
|
const { userInfo } = storeToRefs(store);
|
||||||
|
|
||||||
|
const code = ref<{ barCode: string, qrCode: string }>();
|
||||||
|
const codeContent = ref<string>('');
|
||||||
|
const codeRefreshInterval = ref(30);
|
||||||
|
|
||||||
|
onLoad(() => {
|
||||||
|
if(!isLogin()) {
|
||||||
|
goLogin();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
generateCode();
|
||||||
|
|
||||||
|
setInterval(() => {
|
||||||
|
codeRefreshInterval.value -= 1;
|
||||||
|
if(codeRefreshInterval.value == 0) {
|
||||||
|
codeRefreshInterval.value = 30;
|
||||||
|
generateCode();
|
||||||
|
}
|
||||||
|
}, 1000);
|
||||||
|
});
|
||||||
|
|
||||||
|
const generateCode = async () => {
|
||||||
|
const { dynccode } = await getDynamicCode();
|
||||||
|
codeContent.value = dynccode;
|
||||||
|
const barCode = await generateBarCode(codeContent.value);
|
||||||
|
const qrCode = await generateQrCode(codeContent.value);
|
||||||
|
code.value = {
|
||||||
|
barCode: convertBase64(barCode),
|
||||||
|
qrCode: convertBase64(qrCode)
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const convertBase64 = (data: ArrayBuffer) => {
|
||||||
|
return 'data:image/png;base64,' + uni.arrayBufferToBase64(data);
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style lang='scss' scoped>
|
||||||
|
.content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
padding: 28rpx 24rpx 0 24rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.member-info-view {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
image {
|
||||||
|
width: 39rpx;
|
||||||
|
height: 34rpx;
|
||||||
|
margin-right: 10rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
view:nth-of-type(1) {
|
||||||
|
text {
|
||||||
|
font-size: 32rpx;
|
||||||
|
font-weight: 800;
|
||||||
|
color: #333333;
|
||||||
|
}
|
||||||
|
|
||||||
|
view {
|
||||||
|
width: 100%;
|
||||||
|
height: 4rpx;
|
||||||
|
margin-top: 4rpx;
|
||||||
|
background: #333333
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.qrcode-card {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
background: #FFFFFF;
|
||||||
|
border-radius: 20rpx;
|
||||||
|
padding: 25rpx;
|
||||||
|
margin-top: 27rpx;
|
||||||
|
|
||||||
|
.balance-view {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.balance-text {
|
||||||
|
font-size: 36rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #333333;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-recharge {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
width: 178rpx;
|
||||||
|
height: 63rpx;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
background: #333333;
|
||||||
|
border-radius: 32rpx;
|
||||||
|
|
||||||
|
text {
|
||||||
|
font-size: 30rpx;
|
||||||
|
font-weight: 400;
|
||||||
|
color: #FFFFFF;
|
||||||
|
white-space: nowrap;
|
||||||
|
margin-left: 10rpx;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
image {
|
||||||
|
width: 30rpx;
|
||||||
|
height: 30rpx;
|
||||||
|
margin-left: 13rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.divider {
|
||||||
|
width: 100%;
|
||||||
|
height: 1rpx;
|
||||||
|
background: #D4D4D4;
|
||||||
|
margin-top: 35rpx;
|
||||||
|
margin-bottom: 50rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.barcode-view {
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
image {
|
||||||
|
//width: 100%;
|
||||||
|
height: 130rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
text {
|
||||||
|
font-size: 26rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #333333;
|
||||||
|
margin-top: 10rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.qrcode-view {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
margin-top: 57rpx;
|
||||||
|
|
||||||
|
image {
|
||||||
|
width: 432rpx;
|
||||||
|
height: 432rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
text {
|
||||||
|
font-size: 26rpx;
|
||||||
|
font-weight: 400;
|
||||||
|
color: #666666;
|
||||||
|
margin-top: 18rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-info-view {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
margin-top: 57rpx;
|
||||||
|
margin-left: 5rpx;
|
||||||
|
|
||||||
|
view:nth-of-type(1) {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 20rpx;
|
||||||
|
|
||||||
|
image {
|
||||||
|
width: 35rpx;
|
||||||
|
height: 32rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
text {
|
||||||
|
font-size: 30rpx;
|
||||||
|
font-weight: 400;
|
||||||
|
margin-left: 10rpx;
|
||||||
|
color: #666666;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
text:nth-of-type(1) {
|
||||||
|
font-size: 30rpx;
|
||||||
|
font-weight: 400;
|
||||||
|
color: #333333;
|
||||||
|
}
|
||||||
|
|
||||||
|
text:nth-of-type(2) {
|
||||||
|
font-size: 32rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-top: 18rpx;
|
||||||
|
color: #333333;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@@ -3,7 +3,9 @@ import { getToken } from '@/utils/auth';
|
|||||||
// 登录页面
|
// 登录页面
|
||||||
const loginPage = '/pages/common/login/index';
|
const loginPage = '/pages/common/login/index';
|
||||||
// 页面白名单
|
// 页面白名单
|
||||||
const whiteList = ['/', '/pages/common/login/index', '/pages/home/index'];
|
const whiteList = ['/', '/pages/common/login/index', '/pages/home/index','/pages/common/register/index',
|
||||||
|
'/pages/common/register/reward',
|
||||||
|
'/pages/mine/index','/pages/mine/subs/order/index'];
|
||||||
|
|
||||||
// 检查地址白名单
|
// 检查地址白名单
|
||||||
function checkWhite(url: string) {
|
function checkWhite(url: string) {
|
||||||
|
|||||||
7
src/project.private.config.json
Normal file
7
src/project.private.config.json
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"description": "项目私有配置文件。此文件中的内容将覆盖 project.config.json 中的相同字段。项目的改动优先同步到此文件中。详见文档:https://developers.weixin.qq.com/miniprogram/dev/devtools/projectconfig.html",
|
||||||
|
"projectname": "肃客会员",
|
||||||
|
"setting": {
|
||||||
|
"compileHotReLoad": true
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
src/static/images/ic_checked_gray.png
Normal file
BIN
src/static/images/ic_checked_gray.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.4 KiB |
BIN
src/static/images/ic_checked_green.png
Normal file
BIN
src/static/images/ic_checked_green.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.6 KiB |
BIN
src/static/images/ic_checkmark_red.png
Normal file
BIN
src/static/images/ic_checkmark_red.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.4 KiB |
1
src/static/images/ic_noimage.svg
Normal file
1
src/static/images/ic_noimage.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 4.9 KiB |
BIN
src/static/images/ic_recharge_checked.png
Normal file
BIN
src/static/images/ic_recharge_checked.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.3 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 3.9 KiB |
@@ -1,4 +1,79 @@
|
|||||||
page {
|
page {
|
||||||
font-size: 28rpx;
|
font-size: 25rpx;
|
||||||
background-color: #f9f9f8;
|
background-color: #F5F5F5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.primary-text-color {
|
||||||
|
color: #333333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.secondary-text-color {
|
||||||
|
color: #666666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.accent-text-color {
|
||||||
|
color: #F32B2B;
|
||||||
|
}
|
||||||
|
|
||||||
|
.primary-bg-color {
|
||||||
|
background: #FFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
.accent-bg-color {
|
||||||
|
background: #333333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.c-flex-row {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.c-flex-column {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
@extend .c-flex-column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-view {
|
||||||
|
@extend .c-flex-column;
|
||||||
|
background: #FFFFFF;
|
||||||
|
border-radius: 20rpx;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.divider {
|
||||||
|
width: 100%;
|
||||||
|
height: 0.3rpx;
|
||||||
|
background: #E4E4E4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bottom-button-view {
|
||||||
|
display: flex;
|
||||||
|
position: fixed;
|
||||||
|
background: #FFFFFF;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
padding: 10rpx 30rpx 78rpx 30rpx;
|
||||||
|
|
||||||
|
button {
|
||||||
|
width: 100% !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.primary-button {
|
||||||
|
@extend .accent-bg-color;
|
||||||
|
display: flex;
|
||||||
|
height: 80rpx;
|
||||||
|
border-radius: 43rpx;
|
||||||
|
font-size: 30rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
min-width: 80%;
|
||||||
|
color: #FFFFFF;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,12 +5,12 @@ import { createPinia } from 'pinia';
|
|||||||
import useAppStore from './modules/app';
|
import useAppStore from './modules/app';
|
||||||
import useUserStore from './modules/user';
|
import useUserStore from './modules/user';
|
||||||
|
|
||||||
// import piniaPersist from 'pinia-plugin-persist-uni';
|
import piniaPersist from 'pinia-plugin-persistedstate';
|
||||||
|
|
||||||
// 安装pinia状态管理插件
|
// 安装pinia状态管理插件
|
||||||
function setupStore(app: App) {
|
function setupStore(app: App) {
|
||||||
const store = createPinia();
|
const store = createPinia();
|
||||||
// store.use(piniaPersist);
|
store.use(piniaPersist);
|
||||||
|
|
||||||
app.use(store);
|
app.use(store);
|
||||||
}
|
}
|
||||||
|
|||||||
78
src/store/modules/shoppingcart/index.ts
Normal file
78
src/store/modules/shoppingcart/index.ts
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
import { defineStore } from 'pinia';
|
||||||
|
import { GoodsBean, StockBean } from '@/api/goods/types';
|
||||||
|
import { getCompanyId } from '@/utils';
|
||||||
|
|
||||||
|
const useShoppingCartStore = defineStore('shoppingCart', {
|
||||||
|
state: (): { shoppingCartList: GoodsBean[] } => ({
|
||||||
|
shoppingCartList: uni.getStorageSync(`shoppingCart_${getCompanyId()}`) === '' ? [] : uni.getStorageSync(`shoppingCart_${getCompanyId()}`) as GoodsBean[]
|
||||||
|
}),
|
||||||
|
|
||||||
|
persist: {
|
||||||
|
// 修改存储中使用的键名称,默认为当前 Store的 id
|
||||||
|
key: 'shoppingCartState',
|
||||||
|
storage: {
|
||||||
|
setItem(key, value) {
|
||||||
|
uni.setStorageSync(key, value); // [!code warning]
|
||||||
|
uni.setStorageSync(`shoppingCart_${getCompanyId()}`, JSON.parse(value).shoppingCartList);
|
||||||
|
},
|
||||||
|
getItem(key) {
|
||||||
|
return uni.getStorageSync(uni.getStorageSync(`shoppingCart_${getCompanyId()}`)) || '';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 部分持久化状态的点符号路径数组,[]意味着没有状态被持久化(默认为undefined,持久化整个状态)
|
||||||
|
paths: undefined
|
||||||
|
},
|
||||||
|
|
||||||
|
getters: {
|
||||||
|
getShoppingCartList(): GoodsBean[] {
|
||||||
|
return this.shoppingCartList;
|
||||||
|
},
|
||||||
|
|
||||||
|
totalCount(): number {
|
||||||
|
return this.shoppingCartList.length;
|
||||||
|
},
|
||||||
|
|
||||||
|
getSameGoodsIndex: (state) => (goodsId: string, colorId: string, sizeId: string) => {
|
||||||
|
if(Array.isArray(state.shoppingCartList)) {
|
||||||
|
return state.shoppingCartList?.findIndex(res => res.id === goodsId && res.checkedStock.colorId === colorId && res.checkedStock.sizeId === sizeId);
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
actions: {
|
||||||
|
save(partial: Partial<GoodsBean>) {
|
||||||
|
if(!Array.isArray(this.shoppingCartList)) {
|
||||||
|
this.shoppingCartList = [];
|
||||||
|
}
|
||||||
|
this.shoppingCartList.push(partial as GoodsBean);
|
||||||
|
},
|
||||||
|
|
||||||
|
updateCount(index: number, count: number) {
|
||||||
|
this.shoppingCartList[index].checkedStock.count += count;
|
||||||
|
},
|
||||||
|
|
||||||
|
updateStock(index: number, stock: StockBean) {
|
||||||
|
this.shoppingCartList[index].checkedStock = stock;
|
||||||
|
},
|
||||||
|
|
||||||
|
delete(index: number) {
|
||||||
|
this.shoppingCartList.splice(index, 1);
|
||||||
|
},
|
||||||
|
|
||||||
|
deleteIfChecked() {
|
||||||
|
this.shoppingCartList = this.shoppingCartList.filter(res => res.checked == undefined || res.checked === false);
|
||||||
|
},
|
||||||
|
|
||||||
|
resetData() {
|
||||||
|
this.shoppingCartList = uni.getStorageSync(`shoppingCart_${getCompanyId()}`);
|
||||||
|
},
|
||||||
|
|
||||||
|
clearAll() {
|
||||||
|
this.shoppingCartList = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export default useShoppingCartStore;
|
||||||
@@ -1,82 +1,204 @@
|
|||||||
import { defineStore } from 'pinia';
|
import { defineStore } from 'pinia';
|
||||||
import type { UserState, providerType } from './types';
|
import type { providerType, UserBean } from './types';
|
||||||
|
import { getTerminal, getUserProfile, login, logout as userLogout, register } from '@/api/user/index';
|
||||||
import {
|
import {
|
||||||
getUserProfile,
|
clearToken,
|
||||||
loginByCode,
|
getCompanyId,
|
||||||
login as userLogin,
|
getRegisterStoreId,
|
||||||
logout as userLogout,
|
setCompanyId,
|
||||||
} from '@/api/user/index';
|
setOpenId,
|
||||||
import { clearToken, setToken } from '@/utils/auth';
|
setSessionKey,
|
||||||
import type { LoginParams } from '@/api/user/types';
|
setToken
|
||||||
|
} from '@/utils/auth';
|
||||||
|
import type { RegisterParams, TerminalBean } from '@/api/user/types';
|
||||||
|
import { getCompanyInfo } from '@/api/company';
|
||||||
|
|
||||||
const useUserStore = defineStore('user', {
|
const useUserStore = defineStore('user', {
|
||||||
state: (): UserState => ({
|
state: () => ({
|
||||||
user_id: '',
|
userInfo: {} as UserBean,
|
||||||
user_name: '江阳小道',
|
terminalInfo: {} as TerminalBean,
|
||||||
avatar: '',
|
companyInfo: {} as any,
|
||||||
token: '',
|
companyConfigInfo: {
|
||||||
|
bannerhot: [] as any[],
|
||||||
|
bannerinx: [] as any[],
|
||||||
|
goodsdisable: 0,
|
||||||
|
goodsstockzero: 0,
|
||||||
|
mallopen: 0,
|
||||||
|
regqrcode: undefined,
|
||||||
|
userbgcover: undefined,
|
||||||
|
groupqrcode: undefined,
|
||||||
|
contactname: '',
|
||||||
|
contacttelephone: ''
|
||||||
|
},
|
||||||
|
deliveryAddress: {
|
||||||
|
addrid: '',
|
||||||
|
name: '',
|
||||||
|
mobile: '',
|
||||||
|
addr: '',
|
||||||
|
defaultstatus: 0
|
||||||
|
}
|
||||||
}),
|
}),
|
||||||
getters: {
|
|
||||||
userInfo(state: UserState): UserState {
|
persist: {
|
||||||
return { ...state };
|
// 修改存储中使用的键名称,默认为当前 Store的 id
|
||||||
|
key: 'userState',
|
||||||
|
storage: {
|
||||||
|
setItem(key, value) {
|
||||||
|
uni.setStorageSync(key, value); // [!code warning]
|
||||||
|
},
|
||||||
|
getItem(key) {
|
||||||
|
return uni.getStorageSync(key); // [!code warning]
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
// 部分持久化状态的点符号路径数组,[]意味着没有状态被持久化(默认为undefined,持久化整个状态)
|
||||||
|
paths: undefined
|
||||||
},
|
},
|
||||||
|
|
||||||
|
getters: {
|
||||||
|
getUserDiscount(): number {
|
||||||
|
if(this.userInfo?.levelEntity?.discount > 0 && this.userInfo?.levelEntity?.discount < 10) {
|
||||||
|
return this.userInfo?.levelEntity?.discount / 10;
|
||||||
|
} else if(this.userInfo?.levelEntity?.discount >= 10 && this.userInfo?.levelEntity?.discount <= 100) {
|
||||||
|
return this.userInfo?.levelEntity?.discount / 100;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
},
|
||||||
|
|
||||||
|
getRealGoodsPrice: (state) => (price: number, priceExt: number) => {
|
||||||
|
return state.userInfo.salePrice == 'price_ext' ? priceExt || 0 : price;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
// 设置用户的信息
|
login(provider: providerType = 'weixin') {
|
||||||
setInfo(partial: Partial<UserState>) {
|
|
||||||
this.$patch(partial);
|
|
||||||
},
|
|
||||||
// 重置用户信息
|
|
||||||
resetInfo() {
|
|
||||||
this.$reset();
|
|
||||||
},
|
|
||||||
// 获取用户信息
|
|
||||||
async info() {
|
|
||||||
const result = await getUserProfile();
|
|
||||||
this.setInfo(result);
|
|
||||||
},
|
|
||||||
// 异步登录并存储token
|
|
||||||
login(loginForm: LoginParams) {
|
|
||||||
return new Promise(async (resolve, reject) => {
|
|
||||||
try {
|
|
||||||
const result = await userLogin(loginForm);
|
|
||||||
const token = result?.token;
|
|
||||||
if (token) {
|
|
||||||
setToken(token);
|
|
||||||
}
|
|
||||||
resolve(result);
|
|
||||||
} catch (error) {
|
|
||||||
reject(error)
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
// Logout
|
|
||||||
async logout() {
|
|
||||||
await userLogout();
|
|
||||||
this.resetInfo();
|
|
||||||
clearToken();
|
|
||||||
},
|
|
||||||
// 小程序授权登录
|
|
||||||
authLogin(provider: providerType = 'weixin') {
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
uni.login({
|
uni.login({
|
||||||
provider,
|
provider,
|
||||||
success: async (result: UniApp.LoginRes) => {
|
success: async (result: UniApp.LoginRes) => {
|
||||||
if (result.code) {
|
if(result.code) {
|
||||||
const res = await loginByCode({ code: result.code });
|
const wechatUserInfo = await uni.getUserInfo();
|
||||||
|
const userInfo = {
|
||||||
|
...wechatUserInfo.userInfo,
|
||||||
|
encryptedData: wechatUserInfo?.encryptedData,
|
||||||
|
rawData: JSON.parse(wechatUserInfo?.rawData),
|
||||||
|
signature: wechatUserInfo?.signature,
|
||||||
|
iv: wechatUserInfo.iv
|
||||||
|
};
|
||||||
|
getApp().globalData?.logger.info('login params: ', userInfo);
|
||||||
|
const res = await login({
|
||||||
|
code: result.code,
|
||||||
|
userInfo: userInfo,
|
||||||
|
storeId: getRegisterStoreId()
|
||||||
|
// referrerUserId: '1727303781559697409'
|
||||||
|
// referrerUserId: getReferrerUserId()
|
||||||
|
});
|
||||||
|
getApp().globalData?.logger.info('login result: ', res);
|
||||||
|
setToken(res.token);
|
||||||
|
setSessionKey(res.sessionKey);
|
||||||
|
setOpenId(res.maOpenId);
|
||||||
|
if(res.user) {
|
||||||
|
this.setUserInfo(res.user);
|
||||||
|
} else {
|
||||||
|
this.setUserInfo(res.userInfo);
|
||||||
|
}
|
||||||
|
// }
|
||||||
resolve(res);
|
resolve(res);
|
||||||
} else {
|
} else {
|
||||||
|
getApp().globalData?.logger.error('login error: ', result.errMsg);
|
||||||
reject(new Error(result.errMsg));
|
reject(new Error(result.errMsg));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
fail: (err: any) => {
|
fail: (err: any) => {
|
||||||
console.error(`login error: ${err}`);
|
console.error(`login error: ${err}`);
|
||||||
|
getApp().globalData?.logger.error('login error: ', err);
|
||||||
reject(err);
|
reject(err);
|
||||||
},
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
},
|
|
||||||
|
register(params: {
|
||||||
|
image: string,
|
||||||
|
avatarUrl: string,
|
||||||
|
nickName: string,
|
||||||
|
telephone: string,
|
||||||
|
birthday: string,
|
||||||
|
gender: string
|
||||||
|
}) {
|
||||||
|
const registerForm = {
|
||||||
|
...params,
|
||||||
|
unionId: this.userInfo.unionId,
|
||||||
|
openId: this.userInfo.openId,
|
||||||
|
maOpenId: this.userInfo.maOpenId,
|
||||||
|
companyId: getCompanyId(),
|
||||||
|
creatorId: this.userInfo.creatorId,
|
||||||
|
storeId: getRegisterStoreId()
|
||||||
|
} as RegisterParams;
|
||||||
|
return new Promise(async (resolve, reject) => {
|
||||||
|
try {
|
||||||
|
const result = await register(registerForm);
|
||||||
|
resolve(result);
|
||||||
|
} catch (error) {
|
||||||
|
reject(error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// 设置用户的信息
|
||||||
|
async setUserInfo(partial: Partial<UserBean>) {
|
||||||
|
this.userInfo = partial as UserBean;
|
||||||
|
// this.userInfo.levelEntity?.discount = 79;
|
||||||
|
// this.userInfo.salePrice = 'price_ext';
|
||||||
|
if(this.userInfo) {
|
||||||
|
this.userInfo.userDiscount = this.getUserDiscount;
|
||||||
|
await setCompanyId(this.userInfo.companyId);
|
||||||
|
if(getApp().globalData){
|
||||||
|
getApp().globalData.companyId = this.userInfo.companyId;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
await clearToken();
|
||||||
|
}
|
||||||
|
this.fetchTerminal();
|
||||||
|
this.fetchCompanyInfo();
|
||||||
|
},
|
||||||
|
|
||||||
|
setCompanyInfo(partial: Partial<any>) {
|
||||||
|
this.companyInfo = partial as any;
|
||||||
|
if(getApp()?.globalData) {
|
||||||
|
getApp().globalData.companyId = this.companyInfo.id;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
setDeliveryAddress(partial: Partial<any>) {
|
||||||
|
this.deliveryAddress = partial as any;
|
||||||
|
},
|
||||||
|
|
||||||
|
// 获取用户信息
|
||||||
|
async getProfile() {
|
||||||
|
const result = await getUserProfile();
|
||||||
|
await this.setUserInfo(result);
|
||||||
|
},
|
||||||
|
|
||||||
|
async fetchCompanyInfo() {
|
||||||
|
this.companyConfigInfo = await getCompanyInfo();
|
||||||
|
},
|
||||||
|
|
||||||
|
async fetchTerminal() {
|
||||||
|
this.terminalInfo = await getTerminal(this.userInfo?.companyId);
|
||||||
|
},
|
||||||
|
|
||||||
|
// 重置用户信息
|
||||||
|
resetInfo() {
|
||||||
|
this.$reset();
|
||||||
|
},
|
||||||
|
|
||||||
|
// Logout
|
||||||
|
async logout() {
|
||||||
|
await userLogout();
|
||||||
|
this.resetInfo();
|
||||||
|
clearToken();
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
export default useUserStore;
|
export default useUserStore;
|
||||||
|
|||||||
@@ -1,9 +1,56 @@
|
|||||||
export type RoleType = '' | '*' | 'user';
|
export type RoleType = '' | '*' | 'user';
|
||||||
export interface UserState {
|
|
||||||
user_id?: string;
|
export interface UserBean {
|
||||||
user_name?: string;
|
|
||||||
avatar?: string;
|
|
||||||
token?: string;
|
token?: string;
|
||||||
|
address: string;
|
||||||
|
balance: number;
|
||||||
|
birthday: string;
|
||||||
|
birthdayMD: string;
|
||||||
|
birthdayType: number;
|
||||||
|
card: string;
|
||||||
|
companyId: string;
|
||||||
|
consumption: string;
|
||||||
|
consumptionDay: string;
|
||||||
|
couponsCount: number;
|
||||||
|
createTime: string;
|
||||||
|
creatorId: string;
|
||||||
|
creatorName: string;
|
||||||
|
customerPrice: string;
|
||||||
|
email: string;
|
||||||
|
gender: string;
|
||||||
|
gold: string;
|
||||||
|
goodsNum: number;
|
||||||
|
id: string;
|
||||||
|
image: string | 'https://img.1216.top/lake/def_avatar.png';
|
||||||
|
integration: number;
|
||||||
|
lastConsumTime: string;
|
||||||
|
levelEntity: any;
|
||||||
|
levelId: string;
|
||||||
|
levelName: string;
|
||||||
|
maOpenId: string;
|
||||||
|
memberLabel: string;
|
||||||
|
name: string;
|
||||||
|
nickName: string;
|
||||||
|
openId: string;
|
||||||
|
orderNum: number;
|
||||||
|
ownerId: string;
|
||||||
|
ownerName: string;
|
||||||
|
registerDay: number;
|
||||||
|
relatedRate: number;
|
||||||
|
remark: string;
|
||||||
|
salePrice: string;
|
||||||
|
source: string;
|
||||||
|
status: string;
|
||||||
|
storeId: string;
|
||||||
|
telephone: string;
|
||||||
|
totalConsumption: string;
|
||||||
|
totalIncoming: number;
|
||||||
|
totalIntegral: number;
|
||||||
|
unionId: string;
|
||||||
|
updateTime: string;
|
||||||
|
useCouponsPrice: number;
|
||||||
|
wirelinedTelephone: string;
|
||||||
|
userDiscount:number
|
||||||
}
|
}
|
||||||
|
|
||||||
export type providerType =
|
export type providerType =
|
||||||
|
|||||||
60
src/uni_modules/uni-popup/changelog.md
Normal file
60
src/uni_modules/uni-popup/changelog.md
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
## 1.7.9(2022-04-02)
|
||||||
|
- 修复 弹出层内部无法滚动的bug
|
||||||
|
## 1.7.8(2022-03-28)
|
||||||
|
- 修复 小程序中高度错误的bug
|
||||||
|
## 1.7.7(2022-03-17)
|
||||||
|
- 修复 快速调用open出现问题的Bug
|
||||||
|
## 1.7.6(2022-02-14)
|
||||||
|
- 修复 safeArea 属性不能设置为false的bug
|
||||||
|
## 1.7.5(2022-01-19)
|
||||||
|
- 修复 isMaskClick 失效的bug
|
||||||
|
## 1.7.4(2022-01-19)
|
||||||
|
- 新增 cancelText \ confirmText 属性 ,可自定义文本
|
||||||
|
- 新增 maskBackgroundColor 属性 ,可以修改蒙版颜色
|
||||||
|
- 优化 maskClick属性 更新为 isMaskClick ,解决微信小程序警告的问题
|
||||||
|
## 1.7.3(2022-01-13)
|
||||||
|
- 修复 设置 safeArea 属性不生效的bug
|
||||||
|
## 1.7.2(2021-11-26)
|
||||||
|
- 优化 组件示例
|
||||||
|
## 1.7.1(2021-11-26)
|
||||||
|
- 修复 vuedoc 文字错误
|
||||||
|
## 1.7.0(2021-11-19)
|
||||||
|
- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
|
||||||
|
- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-popup](https://uniapp.dcloud.io/component/uniui/uni-popup)
|
||||||
|
## 1.6.2(2021-08-24)
|
||||||
|
- 新增 支持国际化
|
||||||
|
## 1.6.1(2021-07-30)
|
||||||
|
- 优化 vue3下事件警告的问题
|
||||||
|
## 1.6.0(2021-07-13)
|
||||||
|
- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
|
||||||
|
## 1.5.0(2021-06-23)
|
||||||
|
- 新增 mask-click 遮罩层点击事件
|
||||||
|
## 1.4.5(2021-06-22)
|
||||||
|
- 修复 nvue 平台中间弹出后,点击内容,再点击遮罩无法关闭的Bug
|
||||||
|
## 1.4.4(2021-06-18)
|
||||||
|
- 修复 H5平台中间弹出后,点击内容,再点击遮罩无法关闭的Bug
|
||||||
|
## 1.4.3(2021-06-08)
|
||||||
|
- 修复 错误的 watch 字段
|
||||||
|
- 修复 safeArea 属性不生效的问题
|
||||||
|
- 修复 点击内容,再点击遮罩无法关闭的Bug
|
||||||
|
## 1.4.2(2021-05-12)
|
||||||
|
- 新增 组件示例地址
|
||||||
|
## 1.4.1(2021-04-29)
|
||||||
|
- 修复 组件内放置 input 、textarea 组件,无法聚焦的问题
|
||||||
|
## 1.4.0 (2021-04-29)
|
||||||
|
- 新增 type 属性的 left\right 值,支持左右弹出
|
||||||
|
- 新增 open(String:type) 方法参数 ,可以省略 type 属性 ,直接传入类型打开指定弹窗
|
||||||
|
- 新增 backgroundColor 属性,可定义主窗口背景色,默认不显示背景色
|
||||||
|
- 新增 safeArea 属性,是否适配底部安全区
|
||||||
|
- 修复 App\h5\微信小程序底部安全区占位不对的Bug
|
||||||
|
- 修复 App 端弹出等待的Bug
|
||||||
|
- 优化 提升低配设备性能,优化动画卡顿问题
|
||||||
|
- 优化 更简单的组件自定义方式
|
||||||
|
## 1.2.9(2021-02-05)
|
||||||
|
- 优化 组件引用关系,通过uni_modules引用组件
|
||||||
|
## 1.2.8(2021-02-05)
|
||||||
|
- 调整为uni_modules目录规范
|
||||||
|
## 1.2.7(2021-02-05)
|
||||||
|
- 调整为uni_modules目录规范
|
||||||
|
- 新增 支持 PC 端
|
||||||
|
- 新增 uni-popup-message 、uni-popup-dialog扩展组件支持 PC 端
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
// #ifdef H5
|
||||||
|
export default {
|
||||||
|
name: 'Keypress',
|
||||||
|
props: {
|
||||||
|
disable: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted () {
|
||||||
|
const keyNames = {
|
||||||
|
esc: ['Esc', 'Escape'],
|
||||||
|
tab: 'Tab',
|
||||||
|
enter: 'Enter',
|
||||||
|
space: [' ', 'Spacebar'],
|
||||||
|
up: ['Up', 'ArrowUp'],
|
||||||
|
left: ['Left', 'ArrowLeft'],
|
||||||
|
right: ['Right', 'ArrowRight'],
|
||||||
|
down: ['Down', 'ArrowDown'],
|
||||||
|
delete: ['Backspace', 'Delete', 'Del']
|
||||||
|
}
|
||||||
|
const listener = ($event) => {
|
||||||
|
if (this.disable) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const keyName = Object.keys(keyNames).find(key => {
|
||||||
|
const keyName = $event.key
|
||||||
|
const value = keyNames[key]
|
||||||
|
return value === keyName || (Array.isArray(value) && value.includes(keyName))
|
||||||
|
})
|
||||||
|
if (keyName) {
|
||||||
|
// 避免和其他按键事件冲突
|
||||||
|
setTimeout(() => {
|
||||||
|
this.$emit(keyName, {})
|
||||||
|
}, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
document.addEventListener('keyup', listener)
|
||||||
|
this.$once('hook:beforeDestroy', () => {
|
||||||
|
document.removeEventListener('keyup', listener)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
render: () => {}
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
@@ -0,0 +1,271 @@
|
|||||||
|
<template>
|
||||||
|
<view class="uni-popup-dialog">
|
||||||
|
<view class="uni-dialog-title">
|
||||||
|
<text class="uni-dialog-title-text" :class="['uni-popup__'+dialogType]">{{titleText}}</text>
|
||||||
|
</view>
|
||||||
|
<view v-if="mode === 'base'" class="uni-dialog-content">
|
||||||
|
<slot>
|
||||||
|
<text class="uni-dialog-content-text">{{content}}</text>
|
||||||
|
</slot>
|
||||||
|
</view>
|
||||||
|
<view v-else class="uni-dialog-content">
|
||||||
|
<slot>
|
||||||
|
<input class="uni-dialog-input" v-model="val" type="text" :placeholder="placeholderText" :focus="focus" >
|
||||||
|
</slot>
|
||||||
|
</view>
|
||||||
|
<view class="uni-dialog-button-group">
|
||||||
|
<view class="uni-dialog-button" @click="closeDialog">
|
||||||
|
<text class="uni-dialog-button-text">{{closeText}}</text>
|
||||||
|
</view>
|
||||||
|
<view class="uni-dialog-button uni-border-left" @click="onOk">
|
||||||
|
<text class="uni-dialog-button-text uni-button-color">{{okText}}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import popup from '../uni-popup/popup.js'
|
||||||
|
import {
|
||||||
|
initVueI18n
|
||||||
|
} from '@dcloudio/uni-i18n'
|
||||||
|
import messages from '../uni-popup/i18n/index.js'
|
||||||
|
const { t } = initVueI18n(messages)
|
||||||
|
/**
|
||||||
|
* PopUp 弹出层-对话框样式
|
||||||
|
* @description 弹出层-对话框样式
|
||||||
|
* @tutorial https://ext.dcloud.net.cn/plugin?id=329
|
||||||
|
* @property {String} value input 模式下的默认值
|
||||||
|
* @property {String} placeholder input 模式下输入提示
|
||||||
|
* @property {String} type = [success|warning|info|error] 主题样式
|
||||||
|
* @value success 成功
|
||||||
|
* @value warning 提示
|
||||||
|
* @value info 消息
|
||||||
|
* @value error 错误
|
||||||
|
* @property {String} mode = [base|input] 模式、
|
||||||
|
* @value base 基础对话框
|
||||||
|
* @value input 可输入对话框
|
||||||
|
* @property {String} content 对话框内容
|
||||||
|
* @property {Boolean} beforeClose 是否拦截取消事件
|
||||||
|
* @event {Function} confirm 点击确认按钮触发
|
||||||
|
* @event {Function} close 点击取消按钮触发
|
||||||
|
*/
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "uniPopupDialog",
|
||||||
|
mixins: [popup],
|
||||||
|
emits:['confirm','close'],
|
||||||
|
props: {
|
||||||
|
value: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
placeholder: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
type: {
|
||||||
|
type: String,
|
||||||
|
default: 'error'
|
||||||
|
},
|
||||||
|
mode: {
|
||||||
|
type: String,
|
||||||
|
default: 'base'
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
content: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
beforeClose: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
cancelText:{
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
confirmText:{
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
dialogType: 'error',
|
||||||
|
focus: false,
|
||||||
|
val: ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
okText() {
|
||||||
|
return this.confirmText || t("uni-popup.ok")
|
||||||
|
},
|
||||||
|
closeText() {
|
||||||
|
return this.cancelText || t("uni-popup.cancel")
|
||||||
|
},
|
||||||
|
placeholderText() {
|
||||||
|
return this.placeholder || t("uni-popup.placeholder")
|
||||||
|
},
|
||||||
|
titleText() {
|
||||||
|
return this.title || t("uni-popup.title")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
type(val) {
|
||||||
|
this.dialogType = val
|
||||||
|
},
|
||||||
|
mode(val) {
|
||||||
|
if (val === 'input') {
|
||||||
|
this.dialogType = 'info'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
value(val) {
|
||||||
|
this.val = val
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
// 对话框遮罩不可点击
|
||||||
|
this.popup.disableMask()
|
||||||
|
// this.popup.closeMask()
|
||||||
|
if (this.mode === 'input') {
|
||||||
|
this.dialogType = 'info'
|
||||||
|
this.val = this.value
|
||||||
|
} else {
|
||||||
|
this.dialogType = this.type
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.focus = true
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
/**
|
||||||
|
* 点击确认按钮
|
||||||
|
*/
|
||||||
|
onOk() {
|
||||||
|
if (this.mode === 'input'){
|
||||||
|
this.$emit('confirm', this.val)
|
||||||
|
}else{
|
||||||
|
this.$emit('confirm')
|
||||||
|
}
|
||||||
|
if(this.beforeClose) return
|
||||||
|
this.popup.close()
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 点击取消按钮
|
||||||
|
*/
|
||||||
|
closeDialog() {
|
||||||
|
this.$emit('close')
|
||||||
|
if(this.beforeClose) return
|
||||||
|
this.popup.close()
|
||||||
|
},
|
||||||
|
close(){
|
||||||
|
this.popup.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" >
|
||||||
|
.uni-popup-dialog {
|
||||||
|
width: 300px;
|
||||||
|
border-radius: 11px;
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-dialog-title {
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
display: flex;
|
||||||
|
/* #endif */
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: center;
|
||||||
|
padding-top: 25px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-dialog-title-text {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-dialog-content {
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
display: flex;
|
||||||
|
/* #endif */
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-dialog-content-text {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #6C6C6C;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-dialog-button-group {
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
display: flex;
|
||||||
|
/* #endif */
|
||||||
|
flex-direction: row;
|
||||||
|
border-top-color: #f5f5f5;
|
||||||
|
border-top-style: solid;
|
||||||
|
border-top-width: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-dialog-button {
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
display: flex;
|
||||||
|
/* #endif */
|
||||||
|
|
||||||
|
flex: 1;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
height: 45px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-border-left {
|
||||||
|
border-left-color: #f0f0f0;
|
||||||
|
border-left-style: solid;
|
||||||
|
border-left-width: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-dialog-button-text {
|
||||||
|
font-size: 16px;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-button-color {
|
||||||
|
color: #007aff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-dialog-input {
|
||||||
|
flex: 1;
|
||||||
|
font-size: 14px;
|
||||||
|
border: 1px #eee solid;
|
||||||
|
height: 40px;
|
||||||
|
padding: 0 10px;
|
||||||
|
border-radius: 5px;
|
||||||
|
color: #555;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-popup__success {
|
||||||
|
color: #4cd964;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-popup__warn {
|
||||||
|
color: #f0ad4e;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-popup__error {
|
||||||
|
color: #dd524d;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-popup__info {
|
||||||
|
color: #909399;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,143 @@
|
|||||||
|
<template>
|
||||||
|
<view class="uni-popup-message">
|
||||||
|
<view class="uni-popup-message__box fixforpc-width" :class="'uni-popup__'+type">
|
||||||
|
<slot>
|
||||||
|
<text class="uni-popup-message-text" :class="'uni-popup__'+type+'-text'">{{message}}</text>
|
||||||
|
</slot>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import popup from '../uni-popup/popup.js'
|
||||||
|
/**
|
||||||
|
* PopUp 弹出层-消息提示
|
||||||
|
* @description 弹出层-消息提示
|
||||||
|
* @tutorial https://ext.dcloud.net.cn/plugin?id=329
|
||||||
|
* @property {String} type = [success|warning|info|error] 主题样式
|
||||||
|
* @value success 成功
|
||||||
|
* @value warning 提示
|
||||||
|
* @value info 消息
|
||||||
|
* @value error 错误
|
||||||
|
* @property {String} message 消息提示文字
|
||||||
|
* @property {String} duration 显示时间,设置为 0 则不会自动关闭
|
||||||
|
*/
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'uniPopupMessage',
|
||||||
|
mixins:[popup],
|
||||||
|
props: {
|
||||||
|
/**
|
||||||
|
* 主题 success/warning/info/error 默认 success
|
||||||
|
*/
|
||||||
|
type: {
|
||||||
|
type: String,
|
||||||
|
default: 'success'
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 消息文字
|
||||||
|
*/
|
||||||
|
message: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 显示时间,设置为 0 则不会自动关闭
|
||||||
|
*/
|
||||||
|
duration: {
|
||||||
|
type: Number,
|
||||||
|
default: 3000
|
||||||
|
},
|
||||||
|
maskShow:{
|
||||||
|
type:Boolean,
|
||||||
|
default:false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.popup.maskShow = this.maskShow
|
||||||
|
this.popup.messageChild = this
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
timerClose(){
|
||||||
|
if(this.duration === 0) return
|
||||||
|
clearTimeout(this.timer)
|
||||||
|
this.timer = setTimeout(()=>{
|
||||||
|
this.popup.close()
|
||||||
|
},this.duration)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style lang="scss" >
|
||||||
|
.uni-popup-message {
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
display: flex;
|
||||||
|
/* #endif */
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-popup-message__box {
|
||||||
|
background-color: #e1f3d8;
|
||||||
|
padding: 10px 15px;
|
||||||
|
border-color: #eee;
|
||||||
|
border-style: solid;
|
||||||
|
border-width: 1px;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (min-width: 500px) {
|
||||||
|
.fixforpc-width {
|
||||||
|
margin-top: 20px;
|
||||||
|
border-radius: 4px;
|
||||||
|
flex: none;
|
||||||
|
min-width: 380px;
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
max-width: 50%;
|
||||||
|
/* #endif */
|
||||||
|
/* #ifdef APP-NVUE */
|
||||||
|
max-width: 500px;
|
||||||
|
/* #endif */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-popup-message-text {
|
||||||
|
font-size: 14px;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-popup__success {
|
||||||
|
background-color: #e1f3d8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-popup__success-text {
|
||||||
|
color: #67C23A;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-popup__warn {
|
||||||
|
background-color: #faecd8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-popup__warn-text {
|
||||||
|
color: #E6A23C;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-popup__error {
|
||||||
|
background-color: #fde2e2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-popup__error-text {
|
||||||
|
color: #F56C6C;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-popup__info {
|
||||||
|
background-color: #F2F6FC;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-popup__info-text {
|
||||||
|
color: #909399;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,187 @@
|
|||||||
|
<template>
|
||||||
|
<view class="uni-popup-share">
|
||||||
|
<view class="uni-share-title"><text class="uni-share-title-text">{{shareTitleText}}</text></view>
|
||||||
|
<view class="uni-share-content">
|
||||||
|
<view class="uni-share-content-box">
|
||||||
|
<view class="uni-share-content-item" v-for="(item,index) in bottomData" :key="index" @click.stop="select(item,index)">
|
||||||
|
<image class="uni-share-image" :src="item.icon" mode="aspectFill"></image>
|
||||||
|
<text class="uni-share-text">{{item.text}}</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="uni-share-button-box">
|
||||||
|
<button class="uni-share-button" @click="close">{{cancelText}}</button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import popup from '../uni-popup/popup.js'
|
||||||
|
import {
|
||||||
|
initVueI18n
|
||||||
|
} from '@dcloudio/uni-i18n'
|
||||||
|
import messages from '../uni-popup/i18n/index.js'
|
||||||
|
const { t } = initVueI18n(messages)
|
||||||
|
export default {
|
||||||
|
name: 'UniPopupShare',
|
||||||
|
mixins:[popup],
|
||||||
|
emits:['select'],
|
||||||
|
props: {
|
||||||
|
title: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
beforeClose: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
bottomData: [{
|
||||||
|
text: '微信',
|
||||||
|
icon: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/c2b17470-50be-11eb-b680-7980c8a877b8.png',
|
||||||
|
name: 'wx'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: '支付宝',
|
||||||
|
icon: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/d684ae40-50be-11eb-8ff1-d5dcf8779628.png',
|
||||||
|
name: 'wx'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: 'QQ',
|
||||||
|
icon: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/e7a79520-50be-11eb-b997-9918a5dda011.png',
|
||||||
|
name: 'qq'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: '新浪',
|
||||||
|
icon: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/0dacdbe0-50bf-11eb-8ff1-d5dcf8779628.png',
|
||||||
|
name: 'sina'
|
||||||
|
},
|
||||||
|
// {
|
||||||
|
// text: '百度',
|
||||||
|
// icon: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/1ec6e920-50bf-11eb-8a36-ebb87efcf8c0.png',
|
||||||
|
// name: 'copy'
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// text: '其他',
|
||||||
|
// icon: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/2e0fdfe0-50bf-11eb-b997-9918a5dda011.png',
|
||||||
|
// name: 'more'
|
||||||
|
// }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {},
|
||||||
|
computed: {
|
||||||
|
cancelText() {
|
||||||
|
return t("uni-popup.cancel")
|
||||||
|
},
|
||||||
|
shareTitleText() {
|
||||||
|
return this.title || t("uni-popup.shareTitle")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
/**
|
||||||
|
* 选择内容
|
||||||
|
*/
|
||||||
|
select(item, index) {
|
||||||
|
this.$emit('select', {
|
||||||
|
item,
|
||||||
|
index
|
||||||
|
})
|
||||||
|
this.close()
|
||||||
|
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 关闭窗口
|
||||||
|
*/
|
||||||
|
close() {
|
||||||
|
if(this.beforeClose) return
|
||||||
|
this.popup.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style lang="scss" >
|
||||||
|
.uni-popup-share {
|
||||||
|
background-color: #fff;
|
||||||
|
border-top-left-radius: 11px;
|
||||||
|
border-top-right-radius: 11px;
|
||||||
|
}
|
||||||
|
.uni-share-title {
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
display: flex;
|
||||||
|
/* #endif */
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
height: 40px;
|
||||||
|
}
|
||||||
|
.uni-share-title-text {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
.uni-share-content {
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
display: flex;
|
||||||
|
/* #endif */
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: center;
|
||||||
|
padding-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-share-content-box {
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
display: flex;
|
||||||
|
/* #endif */
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
width: 360px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-share-content-item {
|
||||||
|
width: 90px;
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
display: flex;
|
||||||
|
/* #endif */
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 10px 0;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-share-content-item:active {
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-share-image {
|
||||||
|
width: 30px;
|
||||||
|
height: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-share-text {
|
||||||
|
margin-top: 10px;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #3B4144;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-share-button-box {
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
display: flex;
|
||||||
|
/* #endif */
|
||||||
|
flex-direction: row;
|
||||||
|
padding: 10px 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-share-button {
|
||||||
|
flex: 1;
|
||||||
|
border-radius: 50px;
|
||||||
|
color: #666;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-share-button::after {
|
||||||
|
border-radius: 50px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"uni-popup.cancel": "cancel",
|
||||||
|
"uni-popup.ok": "ok",
|
||||||
|
"uni-popup.placeholder": "pleace enter",
|
||||||
|
"uni-popup.title": "Hint",
|
||||||
|
"uni-popup.shareTitle": "Share to"
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
import en from './en.json'
|
||||||
|
import zhHans from './zh-Hans.json'
|
||||||
|
import zhHant from './zh-Hant.json'
|
||||||
|
export default {
|
||||||
|
en,
|
||||||
|
'zh-Hans': zhHans,
|
||||||
|
'zh-Hant': zhHant
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"uni-popup.cancel": "取消",
|
||||||
|
"uni-popup.ok": "确定",
|
||||||
|
"uni-popup.placeholder": "请输入",
|
||||||
|
"uni-popup.title": "提示",
|
||||||
|
"uni-popup.shareTitle": "分享到"
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"uni-popup.cancel": "取消",
|
||||||
|
"uni-popup.ok": "確定",
|
||||||
|
"uni-popup.placeholder": "請輸入",
|
||||||
|
"uni-popup.title": "提示",
|
||||||
|
"uni-popup.shareTitle": "分享到"
|
||||||
|
}
|
||||||
45
src/uni_modules/uni-popup/components/uni-popup/keypress.js
Normal file
45
src/uni_modules/uni-popup/components/uni-popup/keypress.js
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
// #ifdef H5
|
||||||
|
export default {
|
||||||
|
name: 'Keypress',
|
||||||
|
props: {
|
||||||
|
disable: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted () {
|
||||||
|
const keyNames = {
|
||||||
|
esc: ['Esc', 'Escape'],
|
||||||
|
tab: 'Tab',
|
||||||
|
enter: 'Enter',
|
||||||
|
space: [' ', 'Spacebar'],
|
||||||
|
up: ['Up', 'ArrowUp'],
|
||||||
|
left: ['Left', 'ArrowLeft'],
|
||||||
|
right: ['Right', 'ArrowRight'],
|
||||||
|
down: ['Down', 'ArrowDown'],
|
||||||
|
delete: ['Backspace', 'Delete', 'Del']
|
||||||
|
}
|
||||||
|
const listener = ($event) => {
|
||||||
|
if (this.disable) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const keyName = Object.keys(keyNames).find(key => {
|
||||||
|
const keyName = $event.key
|
||||||
|
const value = keyNames[key]
|
||||||
|
return value === keyName || (Array.isArray(value) && value.includes(keyName))
|
||||||
|
})
|
||||||
|
if (keyName) {
|
||||||
|
// 避免和其他按键事件冲突
|
||||||
|
setTimeout(() => {
|
||||||
|
this.$emit(keyName, {})
|
||||||
|
}, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
document.addEventListener('keyup', listener)
|
||||||
|
// this.$once('hook:beforeDestroy', () => {
|
||||||
|
// document.removeEventListener('keyup', listener)
|
||||||
|
// })
|
||||||
|
},
|
||||||
|
render: () => {}
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
26
src/uni_modules/uni-popup/components/uni-popup/popup.js
Normal file
26
src/uni_modules/uni-popup/components/uni-popup/popup.js
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created(){
|
||||||
|
this.popup = this.getParent()
|
||||||
|
},
|
||||||
|
methods:{
|
||||||
|
/**
|
||||||
|
* 获取父元素实例
|
||||||
|
*/
|
||||||
|
getParent(name = 'uniPopup') {
|
||||||
|
let parent = this.$parent;
|
||||||
|
let parentName = parent.$options.name;
|
||||||
|
while (parentName !== name) {
|
||||||
|
parent = parent.$parent;
|
||||||
|
if (!parent) return false
|
||||||
|
parentName = parent.$options.name;
|
||||||
|
}
|
||||||
|
return parent;
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
474
src/uni_modules/uni-popup/components/uni-popup/uni-popup.vue
Normal file
474
src/uni_modules/uni-popup/components/uni-popup/uni-popup.vue
Normal file
@@ -0,0 +1,474 @@
|
|||||||
|
<template>
|
||||||
|
<view v-if="showPopup" class="uni-popup" :class="[popupstyle, isDesktop ? 'fixforpc-z-index' : '']">
|
||||||
|
<view @touchstart="touchstart">
|
||||||
|
<uni-transition key="1" v-if="maskShow" name="mask" mode-class="fade" :styles="maskClass"
|
||||||
|
:duration="duration" :show="showTrans" @click="onTap" />
|
||||||
|
<uni-transition key="2" :mode-class="ani" name="content" :styles="transClass" :duration="duration"
|
||||||
|
:show="showTrans" @click="onTap">
|
||||||
|
<view class="uni-popup__wrapper" :style="{ backgroundColor: bg }" :class="[popupstyle]" @click="clear">
|
||||||
|
<slot />
|
||||||
|
</view>
|
||||||
|
</uni-transition>
|
||||||
|
</view>
|
||||||
|
<!-- #ifdef H5 -->
|
||||||
|
<keypress v-if="maskShow" @esc="onTap" />
|
||||||
|
<!-- #endif -->
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// #ifdef H5
|
||||||
|
import keypress from './keypress.js'
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PopUp 弹出层
|
||||||
|
* @description 弹出层组件,为了解决遮罩弹层的问题
|
||||||
|
* @tutorial https://ext.dcloud.net.cn/plugin?id=329
|
||||||
|
* @property {String} type = [top|center|bottom|left|right|message|dialog|share] 弹出方式
|
||||||
|
* @value top 顶部弹出
|
||||||
|
* @value center 中间弹出
|
||||||
|
* @value bottom 底部弹出
|
||||||
|
* @value left 左侧弹出
|
||||||
|
* @value right 右侧弹出
|
||||||
|
* @value message 消息提示
|
||||||
|
* @value dialog 对话框
|
||||||
|
* @value share 底部分享示例
|
||||||
|
* @property {Boolean} animation = [true|false] 是否开启动画
|
||||||
|
* @property {Boolean} maskClick = [true|false] 蒙版点击是否关闭弹窗(废弃)
|
||||||
|
* @property {Boolean} isMaskClick = [true|false] 蒙版点击是否关闭弹窗
|
||||||
|
* @property {String} backgroundColor 主窗口背景色
|
||||||
|
* @property {String} maskBackgroundColor 蒙版颜色
|
||||||
|
* @property {Boolean} safeArea 是否适配底部安全区
|
||||||
|
* @event {Function} change 打开关闭弹窗触发,e={show: false}
|
||||||
|
* @event {Function} maskClick 点击遮罩触发
|
||||||
|
*/
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'uniPopup',
|
||||||
|
components: {
|
||||||
|
// #ifdef H5
|
||||||
|
keypress
|
||||||
|
// #endif
|
||||||
|
},
|
||||||
|
emits: ['change', 'maskClick'],
|
||||||
|
props: {
|
||||||
|
// 开启动画
|
||||||
|
animation: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
// 弹出层类型,可选值,top: 顶部弹出层;bottom:底部弹出层;center:全屏弹出层
|
||||||
|
// message: 消息提示 ; dialog : 对话框
|
||||||
|
type: {
|
||||||
|
type: String,
|
||||||
|
default: 'center'
|
||||||
|
},
|
||||||
|
// maskClick
|
||||||
|
isMaskClick: {
|
||||||
|
type: Boolean,
|
||||||
|
default: null
|
||||||
|
},
|
||||||
|
// TODO 2 个版本后废弃属性 ,使用 isMaskClick
|
||||||
|
maskClick: {
|
||||||
|
type: Boolean,
|
||||||
|
default: null
|
||||||
|
},
|
||||||
|
backgroundColor: {
|
||||||
|
type: String,
|
||||||
|
default: 'none'
|
||||||
|
},
|
||||||
|
safeArea: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
maskBackgroundColor: {
|
||||||
|
type: String,
|
||||||
|
default: 'rgba(0, 0, 0, 0.4)'
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
watch: {
|
||||||
|
/**
|
||||||
|
* 监听type类型
|
||||||
|
*/
|
||||||
|
type: {
|
||||||
|
handler: function(type) {
|
||||||
|
if (!this.config[type]) return
|
||||||
|
this[this.config[type]](true)
|
||||||
|
},
|
||||||
|
immediate: true
|
||||||
|
},
|
||||||
|
isDesktop: {
|
||||||
|
handler: function(newVal) {
|
||||||
|
if (!this.config[newVal]) return
|
||||||
|
this[this.config[this.type]](true)
|
||||||
|
},
|
||||||
|
immediate: true
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 监听遮罩是否可点击
|
||||||
|
* @param {Object} val
|
||||||
|
*/
|
||||||
|
maskClick: {
|
||||||
|
handler: function(val) {
|
||||||
|
this.mkclick = val
|
||||||
|
},
|
||||||
|
immediate: true
|
||||||
|
},
|
||||||
|
isMaskClick: {
|
||||||
|
handler: function(val) {
|
||||||
|
this.mkclick = val
|
||||||
|
},
|
||||||
|
immediate: true
|
||||||
|
},
|
||||||
|
// H5 下禁止底部滚动
|
||||||
|
showPopup(show) {
|
||||||
|
// #ifdef H5
|
||||||
|
// fix by mehaotian 处理 h5 滚动穿透的问题
|
||||||
|
document.getElementsByTagName('body')[0].style.overflow = show ? 'hidden' : 'visible'
|
||||||
|
// #endif
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
duration: 300,
|
||||||
|
ani: [],
|
||||||
|
showPopup: false,
|
||||||
|
showTrans: false,
|
||||||
|
popupWidth: 0,
|
||||||
|
popupHeight: 0,
|
||||||
|
config: {
|
||||||
|
top: 'top',
|
||||||
|
bottom: 'bottom',
|
||||||
|
center: 'center',
|
||||||
|
left: 'left',
|
||||||
|
right: 'right',
|
||||||
|
message: 'top',
|
||||||
|
dialog: 'center',
|
||||||
|
share: 'bottom'
|
||||||
|
},
|
||||||
|
maskClass: {
|
||||||
|
position: 'fixed',
|
||||||
|
bottom: 0,
|
||||||
|
top: 0,
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
backgroundColor: 'rgba(0, 0, 0, 0.4)'
|
||||||
|
},
|
||||||
|
transClass: {
|
||||||
|
position: 'fixed',
|
||||||
|
left: 0,
|
||||||
|
right: 0
|
||||||
|
},
|
||||||
|
maskShow: true,
|
||||||
|
mkclick: true,
|
||||||
|
popupstyle: this.isDesktop ? 'fixforpc-top' : 'top'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
isDesktop() {
|
||||||
|
return this.popupWidth >= 500 && this.popupHeight >= 500
|
||||||
|
},
|
||||||
|
bg() {
|
||||||
|
if (this.backgroundColor === '' || this.backgroundColor === 'none') {
|
||||||
|
return 'transparent'
|
||||||
|
}
|
||||||
|
return this.backgroundColor
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
const fixSize = () => {
|
||||||
|
const {
|
||||||
|
windowWidth,
|
||||||
|
windowHeight,
|
||||||
|
windowTop,
|
||||||
|
safeArea,
|
||||||
|
screenHeight,
|
||||||
|
safeAreaInsets
|
||||||
|
} = uni.getSystemInfoSync()
|
||||||
|
this.popupWidth = windowWidth
|
||||||
|
this.popupHeight = windowHeight + (windowTop || 0)
|
||||||
|
// TODO fix by mehaotian 是否适配底部安全区 ,目前微信ios 、和 app ios 计算有差异,需要框架修复
|
||||||
|
if (safeArea && this.safeArea) {
|
||||||
|
// #ifdef MP-WEIXIN
|
||||||
|
this.safeAreaInsets = screenHeight - safeArea.bottom
|
||||||
|
// #endif
|
||||||
|
// #ifndef MP-WEIXIN
|
||||||
|
this.safeAreaInsets = safeAreaInsets.bottom
|
||||||
|
// #endif
|
||||||
|
} else {
|
||||||
|
this.safeAreaInsets = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fixSize()
|
||||||
|
// #ifdef H5
|
||||||
|
// window.addEventListener('resize', fixSize)
|
||||||
|
// this.$once('hook:beforeDestroy', () => {
|
||||||
|
// window.removeEventListener('resize', fixSize)
|
||||||
|
// })
|
||||||
|
// #endif
|
||||||
|
},
|
||||||
|
// #ifndef VUE3
|
||||||
|
// TODO vue2
|
||||||
|
destroyed() {
|
||||||
|
this.setH5Visible()
|
||||||
|
},
|
||||||
|
// #endif
|
||||||
|
// #ifdef VUE3
|
||||||
|
// TODO vue3
|
||||||
|
unmounted() {
|
||||||
|
this.setH5Visible()
|
||||||
|
},
|
||||||
|
// #endif
|
||||||
|
created() {
|
||||||
|
// this.mkclick = this.isMaskClick || this.maskClick
|
||||||
|
if (this.isMaskClick === null && this.maskClick === null) {
|
||||||
|
this.mkclick = true
|
||||||
|
} else {
|
||||||
|
this.mkclick = this.isMaskClick !== null ? this.isMaskClick : this.maskClick
|
||||||
|
}
|
||||||
|
if (this.animation) {
|
||||||
|
this.duration = 300
|
||||||
|
} else {
|
||||||
|
this.duration = 0
|
||||||
|
}
|
||||||
|
// TODO 处理 message 组件生命周期异常的问题
|
||||||
|
this.messageChild = null
|
||||||
|
// TODO 解决头条冒泡的问题
|
||||||
|
this.clearPropagation = false
|
||||||
|
this.maskClass.backgroundColor = this.maskBackgroundColor
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
setH5Visible() {
|
||||||
|
// #ifdef H5
|
||||||
|
// fix by mehaotian 处理 h5 滚动穿透的问题
|
||||||
|
document.getElementsByTagName('body')[0].style.overflow = 'visible'
|
||||||
|
// #endif
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 公用方法,不显示遮罩层
|
||||||
|
*/
|
||||||
|
closeMask() {
|
||||||
|
this.maskShow = false
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 公用方法,遮罩层禁止点击
|
||||||
|
*/
|
||||||
|
disableMask() {
|
||||||
|
this.mkclick = false
|
||||||
|
},
|
||||||
|
// TODO nvue 取消冒泡
|
||||||
|
clear(e) {
|
||||||
|
// #ifndef APP-NVUE
|
||||||
|
e.stopPropagation()
|
||||||
|
// #endif
|
||||||
|
this.clearPropagation = true
|
||||||
|
},
|
||||||
|
|
||||||
|
open(direction) {
|
||||||
|
// fix by mehaotian 处理快速打开关闭的情况
|
||||||
|
if (this.showPopup) {
|
||||||
|
clearTimeout(this.timer)
|
||||||
|
this.showPopup = false
|
||||||
|
}
|
||||||
|
let innerType = ['top', 'center', 'bottom', 'left', 'right', 'message', 'dialog', 'share']
|
||||||
|
if (!(direction && innerType.indexOf(direction) !== -1)) {
|
||||||
|
direction = this.type
|
||||||
|
}
|
||||||
|
if (!this.config[direction]) {
|
||||||
|
console.error('缺少类型:', direction)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this[this.config[direction]]()
|
||||||
|
this.$emit('change', {
|
||||||
|
show: true,
|
||||||
|
type: direction
|
||||||
|
})
|
||||||
|
},
|
||||||
|
close(type) {
|
||||||
|
this.showTrans = false
|
||||||
|
this.$emit('change', {
|
||||||
|
show: false,
|
||||||
|
type: this.type
|
||||||
|
})
|
||||||
|
clearTimeout(this.timer)
|
||||||
|
// // 自定义关闭事件
|
||||||
|
// this.customOpen && this.customClose()
|
||||||
|
this.timer = setTimeout(() => {
|
||||||
|
this.showPopup = false
|
||||||
|
}, 300)
|
||||||
|
},
|
||||||
|
// TODO 处理冒泡事件,头条的冒泡事件有问题 ,先这样兼容
|
||||||
|
touchstart() {
|
||||||
|
this.clearPropagation = false
|
||||||
|
},
|
||||||
|
|
||||||
|
onTap() {
|
||||||
|
if (this.clearPropagation) {
|
||||||
|
// fix by mehaotian 兼容 nvue
|
||||||
|
this.clearPropagation = false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.$emit('maskClick')
|
||||||
|
if (!this.mkclick) return
|
||||||
|
this.close()
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 顶部弹出样式处理
|
||||||
|
*/
|
||||||
|
top(type) {
|
||||||
|
this.popupstyle = this.isDesktop ? 'fixforpc-top' : 'top'
|
||||||
|
this.ani = ['slide-top']
|
||||||
|
this.transClass = {
|
||||||
|
position: 'fixed',
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
backgroundColor: this.bg
|
||||||
|
}
|
||||||
|
// TODO 兼容 type 属性 ,后续会废弃
|
||||||
|
if (type) return
|
||||||
|
this.showPopup = true
|
||||||
|
this.showTrans = true
|
||||||
|
this.$nextTick(() => {
|
||||||
|
if (this.messageChild && this.type === 'message') {
|
||||||
|
this.messageChild.timerClose()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 底部弹出样式处理
|
||||||
|
*/
|
||||||
|
bottom(type) {
|
||||||
|
this.popupstyle = 'bottom'
|
||||||
|
this.ani = ['slide-bottom']
|
||||||
|
this.transClass = {
|
||||||
|
position: 'fixed',
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
bottom: 0,
|
||||||
|
// paddingBottom: this.safeAreaInsets + 'px',
|
||||||
|
backgroundColor: this.bg
|
||||||
|
}
|
||||||
|
// TODO 兼容 type 属性 ,后续会废弃
|
||||||
|
if (type) return
|
||||||
|
this.showPopup = true
|
||||||
|
this.showTrans = true
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 中间弹出样式处理
|
||||||
|
*/
|
||||||
|
center(type) {
|
||||||
|
this.popupstyle = 'center'
|
||||||
|
this.ani = ['zoom-out', 'fade']
|
||||||
|
this.transClass = {
|
||||||
|
position: 'fixed',
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
/* #endif */
|
||||||
|
bottom: 0,
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
top: 0,
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center'
|
||||||
|
}
|
||||||
|
// TODO 兼容 type 属性 ,后续会废弃
|
||||||
|
if (type) return
|
||||||
|
this.showPopup = true
|
||||||
|
this.showTrans = true
|
||||||
|
},
|
||||||
|
left(type) {
|
||||||
|
this.popupstyle = 'left'
|
||||||
|
this.ani = ['slide-left']
|
||||||
|
this.transClass = {
|
||||||
|
position: 'fixed',
|
||||||
|
left: 0,
|
||||||
|
bottom: 0,
|
||||||
|
top: 0,
|
||||||
|
backgroundColor: this.bg,
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column'
|
||||||
|
/* #endif */
|
||||||
|
}
|
||||||
|
// TODO 兼容 type 属性 ,后续会废弃
|
||||||
|
if (type) return
|
||||||
|
this.showPopup = true
|
||||||
|
this.showTrans = true
|
||||||
|
},
|
||||||
|
right(type) {
|
||||||
|
this.popupstyle = 'right'
|
||||||
|
this.ani = ['slide-right']
|
||||||
|
this.transClass = {
|
||||||
|
position: 'fixed',
|
||||||
|
bottom: 0,
|
||||||
|
right: 0,
|
||||||
|
top: 0,
|
||||||
|
backgroundColor: this.bg,
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column'
|
||||||
|
/* #endif */
|
||||||
|
}
|
||||||
|
// TODO 兼容 type 属性 ,后续会废弃
|
||||||
|
if (type) return
|
||||||
|
this.showPopup = true
|
||||||
|
this.showTrans = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style lang="scss">
|
||||||
|
.uni-popup {
|
||||||
|
position: fixed;
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
z-index: 99;
|
||||||
|
|
||||||
|
/* #endif */
|
||||||
|
&.top,
|
||||||
|
&.left,
|
||||||
|
&.right {
|
||||||
|
/* #ifdef H5 */
|
||||||
|
top: var(--window-top);
|
||||||
|
/* #endif */
|
||||||
|
/* #ifndef H5 */
|
||||||
|
top: 0;
|
||||||
|
/* #endif */
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-popup__wrapper {
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
display: block;
|
||||||
|
/* #endif */
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
/* iphonex 等安全区设置,底部安全区适配 */
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
// padding-bottom: constant(safe-area-inset-bottom);
|
||||||
|
// padding-bottom: env(safe-area-inset-bottom);
|
||||||
|
/* #endif */
|
||||||
|
&.left,
|
||||||
|
&.right {
|
||||||
|
/* #ifdef H5 */
|
||||||
|
padding-top: var(--window-top);
|
||||||
|
/* #endif */
|
||||||
|
/* #ifndef H5 */
|
||||||
|
padding-top: 0;
|
||||||
|
/* #endif */
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.fixforpc-z-index {
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
z-index: 999;
|
||||||
|
/* #endif */
|
||||||
|
}
|
||||||
|
|
||||||
|
.fixforpc-top {
|
||||||
|
top: 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
90
src/uni_modules/uni-popup/package.json
Normal file
90
src/uni_modules/uni-popup/package.json
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
{
|
||||||
|
"id": "uni-popup",
|
||||||
|
"displayName": "uni-popup 弹出层",
|
||||||
|
"version": "1.7.9",
|
||||||
|
"description": " Popup 组件,提供常用的弹层",
|
||||||
|
"keywords": [
|
||||||
|
"uni-ui",
|
||||||
|
"弹出层",
|
||||||
|
"弹窗",
|
||||||
|
"popup",
|
||||||
|
"弹框"
|
||||||
|
],
|
||||||
|
"repository": "https://github.com/dcloudio/uni-ui",
|
||||||
|
"engines": {
|
||||||
|
"HBuilderX": ""
|
||||||
|
},
|
||||||
|
"directories": {
|
||||||
|
"example": "../../temps/example_temps"
|
||||||
|
},
|
||||||
|
"dcloudext": {
|
||||||
|
"category": [
|
||||||
|
"前端组件",
|
||||||
|
"通用组件"
|
||||||
|
],
|
||||||
|
"sale": {
|
||||||
|
"regular": {
|
||||||
|
"price": "0.00"
|
||||||
|
},
|
||||||
|
"sourcecode": {
|
||||||
|
"price": "0.00"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"contact": {
|
||||||
|
"qq": ""
|
||||||
|
},
|
||||||
|
"declaration": {
|
||||||
|
"ads": "无",
|
||||||
|
"data": "无",
|
||||||
|
"permissions": "无"
|
||||||
|
},
|
||||||
|
"npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
|
||||||
|
},
|
||||||
|
"uni_modules": {
|
||||||
|
"dependencies": [
|
||||||
|
"uni-scss",
|
||||||
|
"uni-transition"
|
||||||
|
],
|
||||||
|
"encrypt": [],
|
||||||
|
"platforms": {
|
||||||
|
"cloud": {
|
||||||
|
"tcb": "y",
|
||||||
|
"aliyun": "y"
|
||||||
|
},
|
||||||
|
"client": {
|
||||||
|
"App": {
|
||||||
|
"app-vue": "y",
|
||||||
|
"app-nvue": "y"
|
||||||
|
},
|
||||||
|
"H5-mobile": {
|
||||||
|
"Safari": "y",
|
||||||
|
"Android Browser": "y",
|
||||||
|
"微信浏览器(Android)": "y",
|
||||||
|
"QQ浏览器(Android)": "y"
|
||||||
|
},
|
||||||
|
"H5-pc": {
|
||||||
|
"Chrome": "y",
|
||||||
|
"IE": "y",
|
||||||
|
"Edge": "y",
|
||||||
|
"Firefox": "y",
|
||||||
|
"Safari": "y"
|
||||||
|
},
|
||||||
|
"小程序": {
|
||||||
|
"微信": "y",
|
||||||
|
"阿里": "y",
|
||||||
|
"百度": "y",
|
||||||
|
"字节跳动": "y",
|
||||||
|
"QQ": "y"
|
||||||
|
},
|
||||||
|
"快应用": {
|
||||||
|
"华为": "u",
|
||||||
|
"联盟": "u"
|
||||||
|
},
|
||||||
|
"Vue": {
|
||||||
|
"vue2": "y",
|
||||||
|
"vue3": "y"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
17
src/uni_modules/uni-popup/readme.md
Normal file
17
src/uni_modules/uni-popup/readme.md
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
|
||||||
|
|
||||||
|
## Popup 弹出层
|
||||||
|
> **组件名:uni-popup**
|
||||||
|
> 代码块: `uPopup`
|
||||||
|
> 关联组件:`uni-transition`
|
||||||
|
|
||||||
|
|
||||||
|
弹出层组件,在应用中弹出一个消息提示窗口、提示框等
|
||||||
|
|
||||||
|
### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-popup)
|
||||||
|
#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
20
src/uni_modules/uni-transition/changelog.md
Normal file
20
src/uni_modules/uni-transition/changelog.md
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
## 1.3.1(2021-11-23)
|
||||||
|
- 修复 init 方法初始化问题
|
||||||
|
## 1.3.0(2021-11-19)
|
||||||
|
- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
|
||||||
|
- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-transition](https://uniapp.dcloud.io/component/uniui/uni-transition)
|
||||||
|
## 1.2.1(2021-09-27)
|
||||||
|
- 修复 init 方法不生效的 Bug
|
||||||
|
## 1.2.0(2021-07-30)
|
||||||
|
- 组件兼容 vue3,如何创建 vue3 项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
|
||||||
|
## 1.1.1(2021-05-12)
|
||||||
|
- 新增 示例地址
|
||||||
|
- 修复 示例项目缺少组件的 Bug
|
||||||
|
## 1.1.0(2021-04-22)
|
||||||
|
- 新增 通过方法自定义动画
|
||||||
|
- 新增 custom-class 非 NVUE 平台支持自定义 class 定制样式
|
||||||
|
- 优化 动画触发逻辑,使动画更流畅
|
||||||
|
- 优化 支持单独的动画类型
|
||||||
|
- 优化 文档示例
|
||||||
|
## 1.0.2(2021-02-05)
|
||||||
|
- 调整为 uni_modules 目录规范
|
||||||
@@ -0,0 +1,128 @@
|
|||||||
|
// const defaultOption = {
|
||||||
|
// duration: 300,
|
||||||
|
// timingFunction: 'linear',
|
||||||
|
// delay: 0,
|
||||||
|
// transformOrigin: '50% 50% 0'
|
||||||
|
// }
|
||||||
|
// #ifdef APP-NVUE
|
||||||
|
const nvueAnimation = uni.requireNativePlugin('animation')
|
||||||
|
// #endif
|
||||||
|
class MPAnimation {
|
||||||
|
constructor(options, _this) {
|
||||||
|
this.options = options
|
||||||
|
this.animation = uni.createAnimation(options)
|
||||||
|
this.currentStepAnimates = {}
|
||||||
|
this.next = 0
|
||||||
|
this.$ = _this
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
_nvuePushAnimates(type, args) {
|
||||||
|
let aniObj = this.currentStepAnimates[this.next]
|
||||||
|
let styles = {}
|
||||||
|
if (!aniObj) {
|
||||||
|
styles = {
|
||||||
|
styles: {},
|
||||||
|
config: {}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
styles = aniObj
|
||||||
|
}
|
||||||
|
if (animateTypes1.includes(type)) {
|
||||||
|
if (!styles.styles.transform) {
|
||||||
|
styles.styles.transform = ''
|
||||||
|
}
|
||||||
|
let unit = ''
|
||||||
|
if(type === 'rotate'){
|
||||||
|
unit = 'deg'
|
||||||
|
}
|
||||||
|
styles.styles.transform += `${type}(${args+unit}) `
|
||||||
|
} else {
|
||||||
|
styles.styles[type] = `${args}`
|
||||||
|
}
|
||||||
|
this.currentStepAnimates[this.next] = styles
|
||||||
|
}
|
||||||
|
_animateRun(styles = {}, config = {}) {
|
||||||
|
let ref = this.$.$refs['ani'].ref
|
||||||
|
if (!ref) return
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
nvueAnimation.transition(ref, {
|
||||||
|
styles,
|
||||||
|
...config
|
||||||
|
}, res => {
|
||||||
|
resolve()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
_nvueNextAnimate(animates, step = 0, fn) {
|
||||||
|
let obj = animates[step]
|
||||||
|
if (obj) {
|
||||||
|
let {
|
||||||
|
styles,
|
||||||
|
config
|
||||||
|
} = obj
|
||||||
|
this._animateRun(styles, config).then(() => {
|
||||||
|
step += 1
|
||||||
|
this._nvueNextAnimate(animates, step, fn)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
this.currentStepAnimates = {}
|
||||||
|
typeof fn === 'function' && fn()
|
||||||
|
this.isEnd = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
step(config = {}) {
|
||||||
|
// #ifndef APP-NVUE
|
||||||
|
this.animation.step(config)
|
||||||
|
// #endif
|
||||||
|
// #ifdef APP-NVUE
|
||||||
|
this.currentStepAnimates[this.next].config = Object.assign({}, this.options, config)
|
||||||
|
this.currentStepAnimates[this.next].styles.transformOrigin = this.currentStepAnimates[this.next].config.transformOrigin
|
||||||
|
this.next++
|
||||||
|
// #endif
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
run(fn) {
|
||||||
|
// #ifndef APP-NVUE
|
||||||
|
this.$.animationData = this.animation.export()
|
||||||
|
this.$.timer = setTimeout(() => {
|
||||||
|
typeof fn === 'function' && fn()
|
||||||
|
}, this.$.durationTime)
|
||||||
|
// #endif
|
||||||
|
// #ifdef APP-NVUE
|
||||||
|
this.isEnd = false
|
||||||
|
let ref = this.$.$refs['ani'] && this.$.$refs['ani'].ref
|
||||||
|
if(!ref) return
|
||||||
|
this._nvueNextAnimate(this.currentStepAnimates, 0, fn)
|
||||||
|
this.next = 0
|
||||||
|
// #endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const animateTypes1 = ['matrix', 'matrix3d', 'rotate', 'rotate3d', 'rotateX', 'rotateY', 'rotateZ', 'scale', 'scale3d',
|
||||||
|
'scaleX', 'scaleY', 'scaleZ', 'skew', 'skewX', 'skewY', 'translate', 'translate3d', 'translateX', 'translateY',
|
||||||
|
'translateZ'
|
||||||
|
]
|
||||||
|
const animateTypes2 = ['opacity', 'backgroundColor']
|
||||||
|
const animateTypes3 = ['width', 'height', 'left', 'right', 'top', 'bottom']
|
||||||
|
animateTypes1.concat(animateTypes2, animateTypes3).forEach(type => {
|
||||||
|
MPAnimation.prototype[type] = function(...args) {
|
||||||
|
// #ifndef APP-NVUE
|
||||||
|
this.animation[type](...args)
|
||||||
|
// #endif
|
||||||
|
// #ifdef APP-NVUE
|
||||||
|
this._nvuePushAnimates(type, args)
|
||||||
|
// #endif
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
export function createAnimation(option, _this) {
|
||||||
|
if(!_this) return
|
||||||
|
clearTimeout(_this.timer)
|
||||||
|
return new MPAnimation(option, _this)
|
||||||
|
}
|
||||||
@@ -0,0 +1,277 @@
|
|||||||
|
<template>
|
||||||
|
<view v-if="isShow" ref="ani" :animation="animationData" :class="customClass" :style="transformStyles" @click="onClick"><slot></slot></view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { createAnimation } from './createAnimation'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transition 过渡动画
|
||||||
|
* @description 简单过渡动画组件
|
||||||
|
* @tutorial https://ext.dcloud.net.cn/plugin?id=985
|
||||||
|
* @property {Boolean} show = [false|true] 控制组件显示或隐藏
|
||||||
|
* @property {Array|String} modeClass = [fade|slide-top|slide-right|slide-bottom|slide-left|zoom-in|zoom-out] 过渡动画类型
|
||||||
|
* @value fade 渐隐渐出过渡
|
||||||
|
* @value slide-top 由上至下过渡
|
||||||
|
* @value slide-right 由右至左过渡
|
||||||
|
* @value slide-bottom 由下至上过渡
|
||||||
|
* @value slide-left 由左至右过渡
|
||||||
|
* @value zoom-in 由小到大过渡
|
||||||
|
* @value zoom-out 由大到小过渡
|
||||||
|
* @property {Number} duration 过渡动画持续时间
|
||||||
|
* @property {Object} styles 组件样式,同 css 样式,注意带’-‘连接符的属性需要使用小驼峰写法如:`backgroundColor:red`
|
||||||
|
*/
|
||||||
|
export default {
|
||||||
|
name: 'uniTransition',
|
||||||
|
emits:['click','change'],
|
||||||
|
props: {
|
||||||
|
show: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
modeClass: {
|
||||||
|
type: [Array, String],
|
||||||
|
default() {
|
||||||
|
return 'fade'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
duration: {
|
||||||
|
type: Number,
|
||||||
|
default: 300
|
||||||
|
},
|
||||||
|
styles: {
|
||||||
|
type: Object,
|
||||||
|
default() {
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
customClass:{
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
isShow: false,
|
||||||
|
transform: '',
|
||||||
|
opacity: 1,
|
||||||
|
animationData: {},
|
||||||
|
durationTime: 300,
|
||||||
|
config: {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
show: {
|
||||||
|
handler(newVal) {
|
||||||
|
if (newVal) {
|
||||||
|
this.open()
|
||||||
|
} else {
|
||||||
|
// 避免上来就执行 close,导致动画错乱
|
||||||
|
if (this.isShow) {
|
||||||
|
this.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
immediate: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
// 生成样式数据
|
||||||
|
stylesObject() {
|
||||||
|
let styles = {
|
||||||
|
...this.styles,
|
||||||
|
'transition-duration': this.duration / 1000 + 's'
|
||||||
|
}
|
||||||
|
let transform = ''
|
||||||
|
for (let i in styles) {
|
||||||
|
let line = this.toLine(i)
|
||||||
|
transform += line + ':' + styles[i] + ';'
|
||||||
|
}
|
||||||
|
return transform
|
||||||
|
},
|
||||||
|
// 初始化动画条件
|
||||||
|
transformStyles() {
|
||||||
|
return 'transform:' + this.transform + ';' + 'opacity:' + this.opacity + ';' + this.stylesObject
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
// 动画默认配置
|
||||||
|
this.config = {
|
||||||
|
duration: this.duration,
|
||||||
|
timingFunction: 'ease',
|
||||||
|
transformOrigin: '50% 50%',
|
||||||
|
delay: 0
|
||||||
|
}
|
||||||
|
this.durationTime = this.duration
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
/**
|
||||||
|
* ref 触发 初始化动画
|
||||||
|
*/
|
||||||
|
init(obj = {}) {
|
||||||
|
if (obj.duration) {
|
||||||
|
this.durationTime = obj.duration
|
||||||
|
}
|
||||||
|
this.animation = createAnimation(Object.assign(this.config, obj),this)
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 点击组件触发回调
|
||||||
|
*/
|
||||||
|
onClick() {
|
||||||
|
this.$emit('click', {
|
||||||
|
detail: this.isShow
|
||||||
|
})
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* ref 触发 动画分组
|
||||||
|
* @param {Object} obj
|
||||||
|
*/
|
||||||
|
step(obj, config = {}) {
|
||||||
|
if (!this.animation) return
|
||||||
|
for (let i in obj) {
|
||||||
|
try {
|
||||||
|
if(typeof obj[i] === 'object'){
|
||||||
|
this.animation[i](...obj[i])
|
||||||
|
}else{
|
||||||
|
this.animation[i](obj[i])
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error(`方法 ${i} 不存在`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.animation.step(config)
|
||||||
|
return this
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* ref 触发 执行动画
|
||||||
|
*/
|
||||||
|
run(fn) {
|
||||||
|
if (!this.animation) return
|
||||||
|
this.animation.run(fn)
|
||||||
|
},
|
||||||
|
// 开始过度动画
|
||||||
|
open() {
|
||||||
|
clearTimeout(this.timer)
|
||||||
|
this.transform = ''
|
||||||
|
this.isShow = true
|
||||||
|
let { opacity, transform } = this.styleInit(false)
|
||||||
|
if (typeof opacity !== 'undefined') {
|
||||||
|
this.opacity = opacity
|
||||||
|
}
|
||||||
|
this.transform = transform
|
||||||
|
// 确保动态样式已经生效后,执行动画,如果不加 nextTick ,会导致 wx 动画执行异常
|
||||||
|
this.$nextTick(() => {
|
||||||
|
// TODO 定时器保证动画完全执行,目前有些问题,后面会取消定时器
|
||||||
|
this.timer = setTimeout(() => {
|
||||||
|
this.animation = createAnimation(this.config, this)
|
||||||
|
this.tranfromInit(false).step()
|
||||||
|
this.animation.run()
|
||||||
|
this.$emit('change', {
|
||||||
|
detail: this.isShow
|
||||||
|
})
|
||||||
|
}, 20)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 关闭过度动画
|
||||||
|
close(type) {
|
||||||
|
if (!this.animation) return
|
||||||
|
this.tranfromInit(true)
|
||||||
|
.step()
|
||||||
|
.run(() => {
|
||||||
|
this.isShow = false
|
||||||
|
this.animationData = null
|
||||||
|
this.animation = null
|
||||||
|
let { opacity, transform } = this.styleInit(false)
|
||||||
|
this.opacity = opacity || 1
|
||||||
|
this.transform = transform
|
||||||
|
this.$emit('change', {
|
||||||
|
detail: this.isShow
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 处理动画开始前的默认样式
|
||||||
|
styleInit(type) {
|
||||||
|
let styles = {
|
||||||
|
transform: ''
|
||||||
|
}
|
||||||
|
let buildStyle = (type, mode) => {
|
||||||
|
if (mode === 'fade') {
|
||||||
|
styles.opacity = this.animationType(type)[mode]
|
||||||
|
} else {
|
||||||
|
styles.transform += this.animationType(type)[mode] + ' '
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (typeof this.modeClass === 'string') {
|
||||||
|
buildStyle(type, this.modeClass)
|
||||||
|
} else {
|
||||||
|
this.modeClass.forEach(mode => {
|
||||||
|
buildStyle(type, mode)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return styles
|
||||||
|
},
|
||||||
|
// 处理内置组合动画
|
||||||
|
tranfromInit(type) {
|
||||||
|
let buildTranfrom = (type, mode) => {
|
||||||
|
let aniNum = null
|
||||||
|
if (mode === 'fade') {
|
||||||
|
aniNum = type ? 0 : 1
|
||||||
|
} else {
|
||||||
|
aniNum = type ? '-100%' : '0'
|
||||||
|
if (mode === 'zoom-in') {
|
||||||
|
aniNum = type ? 0.8 : 1
|
||||||
|
}
|
||||||
|
if (mode === 'zoom-out') {
|
||||||
|
aniNum = type ? 1.2 : 1
|
||||||
|
}
|
||||||
|
if (mode === 'slide-right') {
|
||||||
|
aniNum = type ? '100%' : '0'
|
||||||
|
}
|
||||||
|
if (mode === 'slide-bottom') {
|
||||||
|
aniNum = type ? '100%' : '0'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.animation[this.animationMode()[mode]](aniNum)
|
||||||
|
}
|
||||||
|
if (typeof this.modeClass === 'string') {
|
||||||
|
buildTranfrom(type, this.modeClass)
|
||||||
|
} else {
|
||||||
|
this.modeClass.forEach(mode => {
|
||||||
|
buildTranfrom(type, mode)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.animation
|
||||||
|
},
|
||||||
|
animationType(type) {
|
||||||
|
return {
|
||||||
|
fade: type ? 1 : 0,
|
||||||
|
'slide-top': `translateY(${type ? '0' : '-100%'})`,
|
||||||
|
'slide-right': `translateX(${type ? '0' : '100%'})`,
|
||||||
|
'slide-bottom': `translateY(${type ? '0' : '100%'})`,
|
||||||
|
'slide-left': `translateX(${type ? '0' : '-100%'})`,
|
||||||
|
'zoom-in': `scaleX(${type ? 1 : 0.8}) scaleY(${type ? 1 : 0.8})`,
|
||||||
|
'zoom-out': `scaleX(${type ? 1 : 1.2}) scaleY(${type ? 1 : 1.2})`
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 内置动画类型与实际动画对应字典
|
||||||
|
animationMode() {
|
||||||
|
return {
|
||||||
|
fade: 'opacity',
|
||||||
|
'slide-top': 'translateY',
|
||||||
|
'slide-right': 'translateX',
|
||||||
|
'slide-bottom': 'translateY',
|
||||||
|
'slide-left': 'translateX',
|
||||||
|
'zoom-in': 'scale',
|
||||||
|
'zoom-out': 'scale'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 驼峰转中横线
|
||||||
|
toLine(name) {
|
||||||
|
return name.replace(/([A-Z])/g, '-$1').toLowerCase()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style></style>
|
||||||
87
src/uni_modules/uni-transition/package.json
Normal file
87
src/uni_modules/uni-transition/package.json
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
{
|
||||||
|
"id": "uni-transition",
|
||||||
|
"displayName": "uni-transition 过渡动画",
|
||||||
|
"version": "1.3.1",
|
||||||
|
"description": "元素的简单过渡动画",
|
||||||
|
"keywords": [
|
||||||
|
"uni-ui",
|
||||||
|
"uniui",
|
||||||
|
"动画",
|
||||||
|
"过渡",
|
||||||
|
"过渡动画"
|
||||||
|
],
|
||||||
|
"repository": "https://github.com/dcloudio/uni-ui",
|
||||||
|
"engines": {
|
||||||
|
"HBuilderX": ""
|
||||||
|
},
|
||||||
|
"directories": {
|
||||||
|
"example": "../../temps/example_temps"
|
||||||
|
},
|
||||||
|
"dcloudext": {
|
||||||
|
"category": [
|
||||||
|
"前端组件",
|
||||||
|
"通用组件"
|
||||||
|
],
|
||||||
|
"sale": {
|
||||||
|
"regular": {
|
||||||
|
"price": "0.00"
|
||||||
|
},
|
||||||
|
"sourcecode": {
|
||||||
|
"price": "0.00"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"contact": {
|
||||||
|
"qq": ""
|
||||||
|
},
|
||||||
|
"declaration": {
|
||||||
|
"ads": "无",
|
||||||
|
"data": "无",
|
||||||
|
"permissions": "无"
|
||||||
|
},
|
||||||
|
"npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
|
||||||
|
},
|
||||||
|
"uni_modules": {
|
||||||
|
"dependencies": ["uni-scss"],
|
||||||
|
"encrypt": [],
|
||||||
|
"platforms": {
|
||||||
|
"cloud": {
|
||||||
|
"tcb": "y",
|
||||||
|
"aliyun": "y"
|
||||||
|
},
|
||||||
|
"client": {
|
||||||
|
"App": {
|
||||||
|
"app-vue": "y",
|
||||||
|
"app-nvue": "y"
|
||||||
|
},
|
||||||
|
"H5-mobile": {
|
||||||
|
"Safari": "y",
|
||||||
|
"Android Browser": "y",
|
||||||
|
"微信浏览器(Android)": "y",
|
||||||
|
"QQ浏览器(Android)": "y"
|
||||||
|
},
|
||||||
|
"H5-pc": {
|
||||||
|
"Chrome": "y",
|
||||||
|
"IE": "y",
|
||||||
|
"Edge": "y",
|
||||||
|
"Firefox": "y",
|
||||||
|
"Safari": "y"
|
||||||
|
},
|
||||||
|
"小程序": {
|
||||||
|
"微信": "y",
|
||||||
|
"阿里": "y",
|
||||||
|
"百度": "y",
|
||||||
|
"字节跳动": "y",
|
||||||
|
"QQ": "y"
|
||||||
|
},
|
||||||
|
"快应用": {
|
||||||
|
"华为": "u",
|
||||||
|
"联盟": "u"
|
||||||
|
},
|
||||||
|
"Vue": {
|
||||||
|
"vue2": "y",
|
||||||
|
"vue3": "y"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
11
src/uni_modules/uni-transition/readme.md
Normal file
11
src/uni_modules/uni-transition/readme.md
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
|
||||||
|
|
||||||
|
## Transition 过渡动画
|
||||||
|
> **组件名:uni-transition**
|
||||||
|
> 代码块: `uTransition`
|
||||||
|
|
||||||
|
|
||||||
|
元素过渡动画
|
||||||
|
|
||||||
|
### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-transition)
|
||||||
|
#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839
|
||||||
3
src/utils/assets.ts
Normal file
3
src/utils/assets.ts
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
export const assetsUrl = (name: string) => `https://img.lakeapp.cn/wx/images/${name}`;
|
||||||
|
export const defaultAvatar = 'https://thirdwx.qlogo.cn/mmopen/vi_32/POgEwh4mIHO4nibH0KlMECNjjGxQUq24ZEaGT4poC6icRiccVGKSyXwibcPq4BWmiaIGuG1icwxaQX6grC9VemZoJ8rg/132';
|
||||||
|
export const defaultImage = '/static/images/ic_noimage.svg';
|
||||||
@@ -1,15 +1,89 @@
|
|||||||
const TokenKey = 'admin-token';
|
const TokenKey = 'accessToken';
|
||||||
|
const SessionKey = 'sessionKey';
|
||||||
|
const OpenIdKey = 'openId';
|
||||||
|
const CompanyIdKey = 'companyId';
|
||||||
|
const ReferrerUserIdKey = 'referrerUserId';
|
||||||
|
const RegisterStoreIdKey = 'storeId';
|
||||||
|
|
||||||
const TokenPrefix = 'Bearer ';
|
const TokenPrefix = 'Bearer ';
|
||||||
|
|
||||||
function isLogin() {
|
function isLogin() {
|
||||||
return !!uni.getStorageSync(TokenKey);
|
return !!uni.getStorageSync(TokenKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getToken() {
|
function getToken() {
|
||||||
return uni.getStorageSync(TokenKey);
|
return uni.getStorageSync(TokenKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
function setToken(token: string) {
|
function setToken(token: string) {
|
||||||
uni.setStorageSync(TokenKey, token);
|
uni.setStorageSync(TokenKey, token);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getSessionKey() {
|
||||||
|
return uni.getStorageSync(SessionKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setSessionKey(sessionKey: string) {
|
||||||
|
uni.setStorageSync(SessionKey, sessionKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getOpenId() {
|
||||||
|
return uni.getStorageSync(OpenIdKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setOpenId(openId: string) {
|
||||||
|
uni.setStorageSync(OpenIdKey, openId);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getCompanyId() {
|
||||||
|
return uni.getStorageSync(CompanyIdKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setCompanyId(companyId: string) {
|
||||||
|
if(companyId) {
|
||||||
|
uni.setStorageSync(CompanyIdKey, companyId);
|
||||||
|
if(getApp()?.globalData) {
|
||||||
|
getApp().globalData.companyId = companyId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getReferrerUserId() {
|
||||||
|
return uni.getStorageSync(ReferrerUserIdKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setReferrerUserId(referrerUserId: string) {
|
||||||
|
uni.setStorageSync(ReferrerUserIdKey, referrerUserId);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setRegisterStoreId(storeId: string) {
|
||||||
|
uni.setStorageSync(RegisterStoreIdKey, storeId);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getRegisterStoreId() {
|
||||||
|
return uni.getStorageSync(RegisterStoreIdKey);
|
||||||
|
}
|
||||||
|
|
||||||
function clearToken() {
|
function clearToken() {
|
||||||
uni.removeStorageSync(TokenKey);
|
uni.removeStorageSync(TokenKey);
|
||||||
|
uni.removeStorageSync(CompanyIdKey);
|
||||||
|
uni.removeStorageSync(SessionKey);
|
||||||
}
|
}
|
||||||
export { TokenPrefix, isLogin, getToken, setToken, clearToken };
|
|
||||||
|
export {
|
||||||
|
TokenPrefix,
|
||||||
|
isLogin,
|
||||||
|
getToken,
|
||||||
|
setToken,
|
||||||
|
getSessionKey,
|
||||||
|
setSessionKey,
|
||||||
|
getOpenId,
|
||||||
|
setOpenId,
|
||||||
|
getCompanyId,
|
||||||
|
setCompanyId,
|
||||||
|
getReferrerUserId,
|
||||||
|
setReferrerUserId,
|
||||||
|
getRegisterStoreId,
|
||||||
|
setRegisterStoreId,
|
||||||
|
clearToken
|
||||||
|
};
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user