# Conflicts:
#	.env
This commit is contained in:
zjf committed 2025-05-19 13:20:57 +08:00
commit ad854b563b
77 files changed
+2468 -22484

No files matched your search

+18 -25
View File
@@ -2,7 +2,7 @@
VITE_IS_TOC=true
#是否是H5模式
VITE_IS_H5=false
VITE_IS_H5=true
#是否是微服务架构
VITE_IS_MICRO=true
@@ -16,29 +16,22 @@ VITE_PWD_ENC_KEY='pigxpigxpigxpigx'
# OAUTH2 APP模式客户端信息
VITE_OAUTH2_APP_CLIENT='mini:mini'
# 图片访问基础地址
VITE_IMAGE_BASE_PATH = http://localhost:9999
# VITE_IMAGE_BASE_PATH = http://192.168.101.64:9999 # 邓-本地
# VITE_IMAGE_BASE_PATH = https://123.156.230.15:8089/api # 线上
# VITE_IMAGE_BASE_PATH = http://220.191.229.171:8090/api # 线上
# VITE_IMAGE_BASE_PATH = https://stgl.pj.gov.cn/api # 线上
# VITE_IMAGE_BASE_PATH = http://pjcloud.center.takin.cc # 张
# VITE_IMAGE_BASE_PATH = http://59.202.170.152:81/api # 信创线上
# --------------------------- 开发环境 api地址 ----------------------------------
# VITE_APP_DEV_SERVICE = https://stgl.pj.gov.cn/api # 域名线上
#VITE_APP_DEV_SERVICE = http://59.202.170.152:81/api # 信创线上
VITE_APP_DEV_SERVICE = http://192.168.101.125:9999 # 邓-本地
# VITE_APP_DEV_SERVICE = http://123.156.230.15:8089/api # 测试线上
# ******************** start 开发环境 start ********************
# VITE_APP_DEV_SERVICE = http://59.202.170.152:81/api # 信创线上
# VITE_APP_DEV_SERVICE = https://stgl.pj.gov.cn/api
# VITE_APP_DEV_SERVICE = http://192.168.101.64:9999 # 邓-本地
VITE_APP_DEV_SERVICE = http://127.0.0.1:9999
; VITE_APP_DEV_SERVICE = http://123.156.230.15:8089/api/ # 访客线上
# VITE_APP_DEV_SERVICE = http://220.191.229.171:8090/api # 线上
# ******************** end 开发环境 end ********************
# --------------------------- 开发环境 图片访问基础地址 ---------------------------
# VITE_IMAGE_DEV_PATH = https://stgl.pj.gov.cn/api # 域名线上
#VITE_IMAGE_DEV_PATH = http://59.202.170.152:81/api # 信创线上
VITE_IMAGE_DEV_PATH = http://192.168.101.125:9999 # 邓-本地
# VITE_IMAGE_DEV_PATH = http://123.156.230.15:8089/api # 测试线上
# ******************** start 生产环境 start ****************
# VITE_APP_PROD_SERVICE = http://123.156.228.134:48080/app-api
# VITE_APP_PROD_SERVICE = http://59.202.170.152:81/api
# VITE_APP_PROD_SERVICE = https://stgl.pj.gov.cn/api
#VITE_APP_PROD_SERVICE = http://123.156.230.15:8089/api
VITE_APP_PROD_SERVICE = http://127.0.0.1:9999
# VITE_APP_PROD_SERVICE = http://59.202.170.152:81/api # 信创线上
# ******************** end 生产环境 end ********************
# --------------------------- 生产环境 api地址 ----------------------------------
VITE_APP_PROD_SERVICE = https://stgl.pj.gov.cn/api # 域名线上
#VITE_APP_PROD_SERVICE = http://59.202.170.152:81/api # 信创线上
#VITE_APP_PROD_SERVICE = http://123.156.228.134:48080/app-api
# --------------------------- 生产环境 图片访问基础地址 ---------------------------
VITE_APP_PROD_IMAGE = https://stgl.pj.gov.cn/api # 域名线上
-21474
View File
File diff suppressed because it is too large. Load diff
-1
View File
@@ -58,7 +58,6 @@
"@dcloudio/uni-mp-weixin": "3.0.0-4020920240930001",
"@dcloudio/uni-mp-xhs": "3.0.0-4020920240930001",
"@dcloudio/uni-quickapp-webview": "3.0.0-4020920240930001",
"@vant/weapp": "^1.11.7",
"@vue/compiler-core": "^3.5.11",
"@zebra-ui/swiper": "^2.2.8",
"crypto-js": "^4.2.0",
+97
View File
@@ -74,6 +74,9 @@ importers:
pinia:
specifier: ^2.2.6
version: 2.3.1(typescript@4.9.5)(vue@3.5.13(typescript@4.9.5))
qrcode:
specifier: ^1.5.4
version: 1.5.4
qs:
specifier: ^6.13.1
version: 6.14.0
@@ -2001,6 +2004,9 @@ packages:
cjs-module-lexer@1.4.3:
resolution: {integrity: sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==}
cliui@6.0.0:
resolution: {integrity: sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==}
cliui@7.0.4:
resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==}
@@ -2150,6 +2156,10 @@ packages:
supports-color:
optional: true
decamelize@1.2.0:
resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==}
engines: {node: '>=0.10.0'}
decimal.js@10.5.0:
resolution: {integrity: sha512-8vDa8Qxvr/+d94hSh5P3IJwI5t8/c0KsMp+g8bNw9cY2icONa5aPfvKeieW1WlG0WQYwwhJ7mjui2xtiePQSXw==}
@@ -2190,6 +2200,9 @@ packages:
resolution: {integrity: sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==}
engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0}
dijkstrajs@1.0.3:
resolution: {integrity: sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==}
dom-walk@0.1.2:
resolution: {integrity: sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==}
@@ -3205,6 +3218,10 @@ packages:
resolution: {integrity: sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w==}
engines: {node: '>=4.0.0'}
pngjs@5.0.0:
resolution: {integrity: sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==}
engines: {node: '>=10.13.0'}
postcss-import@14.1.0:
resolution: {integrity: sha512-flwI+Vgm4SElObFVPpTIT7SU7R3qk2L7PyduMcokiaVKuWv9d/U+Gm/QAd8NDLuykTWTkcrjOeD2Pp1rMeBTGw==}
engines: {node: '>=10.0.0'}
@@ -3297,6 +3314,11 @@ packages:
resolution: {integrity: sha512-EXtzRZmC+YGmGlDFbXKxQiMZNwCLEO6BANKXG4iCtSIM0yqc/pappSx3RIKr4r0uh5JsBckOXeKrB3Iz7mdQpQ==}
hasBin: true
qrcode@1.5.4:
resolution: {integrity: sha512-1ca71Zgiu6ORjHqFBDpnSMTR2ReToX4l1Au1VFLyVeBTFavzQnv5JxMFr3ukHVKpSrSA2MCk0lNJSykjUfz7Zg==}
engines: {node: '>=10.13.0'}
hasBin: true
qs@6.13.0:
resolution: {integrity: sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==}
engines: {node: '>=0.6'}
@@ -3371,6 +3393,9 @@ packages:
resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==}
engines: {node: '>=0.10.0'}
require-main-filename@2.0.0:
resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==}
requires-port@1.0.0:
resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==}
@@ -3476,6 +3501,9 @@ packages:
resolution: {integrity: sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==}
engines: {node: '>= 0.8.0'}
set-blocking@2.0.0:
resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==}
setprototypeof@1.2.0:
resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==}
@@ -3919,11 +3947,18 @@ packages:
resolution: {integrity: sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==}
engines: {node: '>=10'}
which-module@2.0.1:
resolution: {integrity: sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==}
which@2.0.2:
resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
engines: {node: '>= 8'}
hasBin: true
wrap-ansi@6.2.0:
resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==}
engines: {node: '>=8'}
wrap-ansi@7.0.0:
resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==}
engines: {node: '>=10'}
@@ -3989,6 +4024,9 @@ packages:
resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==}
engines: {node: '>=0.4'}
y18n@4.0.3:
resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==}
y18n@5.0.8:
resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==}
engines: {node: '>=10'}
@@ -4000,10 +4038,18 @@ packages:
resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==}
engines: {node: '>= 6'}
yargs-parser@18.1.3:
resolution: {integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==}
engines: {node: '>=6'}
yargs-parser@20.2.9:
resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==}
engines: {node: '>=10'}
yargs@15.4.1:
resolution: {integrity: sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==}
engines: {node: '>=8'}
yargs@16.2.0:
resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==}
engines: {node: '>=10'}
@@ -6833,6 +6879,12 @@ snapshots:
cjs-module-lexer@1.4.3: {}
cliui@6.0.0:
dependencies:
string-width: 4.2.3
strip-ansi: 6.0.1
wrap-ansi: 6.2.0
cliui@7.0.4:
dependencies:
string-width: 4.2.3
@@ -6946,6 +6998,8 @@ snapshots:
dependencies:
ms: 2.1.3
decamelize@1.2.0: {}
decimal.js@10.5.0: {}
dedent@0.7.0: {}
@@ -6970,6 +7024,8 @@ snapshots:
diff-sequences@27.5.1: {}
dijkstrajs@1.0.3: {}
dom-walk@0.1.2: {}
domexception@2.0.1:
@@ -8176,6 +8232,8 @@ snapshots:
pngjs@3.4.0: {}
pngjs@5.0.0: {}
postcss-import@14.1.0(postcss@8.5.1):
dependencies:
postcss: 8.5.1
@@ -8269,6 +8327,12 @@ snapshots:
qrcode-terminal@0.12.0: {}
qrcode@1.5.4:
dependencies:
dijkstrajs: 1.0.3
pngjs: 5.0.0
yargs: 15.4.1
qs@6.13.0:
dependencies:
side-channel: 1.1.0
@@ -8339,6 +8403,8 @@ snapshots:
require-from-string@2.0.2: {}
require-main-filename@2.0.0: {}
requires-port@1.0.0: {}
resolve-cwd@3.0.0:
@@ -8469,6 +8535,8 @@ snapshots:
transitivePeerDependencies:
- supports-color
set-blocking@2.0.0: {}
setprototypeof@1.2.0: {}
shebang-command@2.0.0:
@@ -8935,10 +9003,18 @@ snapshots:
tr46: 2.1.0
webidl-conversions: 6.1.0
which-module@2.0.1: {}
which@2.0.2:
dependencies:
isexe: 2.0.0
wrap-ansi@6.2.0:
dependencies:
ansi-styles: 4.3.0
string-width: 4.2.3
strip-ansi: 6.0.1
wrap-ansi@7.0.0:
dependencies:
ansi-styles: 4.3.0
@@ -8984,14 +9060,35 @@ snapshots:
xtend@4.0.2: {}
y18n@4.0.3: {}
y18n@5.0.8: {}
yallist@3.1.1: {}
yaml@1.10.2: {}
yargs-parser@18.1.3:
dependencies:
camelcase: 5.3.1
decamelize: 1.2.0
yargs-parser@20.2.9: {}
yargs@15.4.1:
dependencies:
cliui: 6.0.0
decamelize: 1.2.0
find-up: 4.1.0
get-caller-file: 2.0.5
require-directory: 2.1.1
require-main-filename: 2.0.0
set-blocking: 2.0.0
string-width: 4.2.3
which-module: 2.0.1
y18n: 4.0.3
yargs-parser: 18.1.3
yargs@16.2.0:
dependencies:
cliui: 7.0.4
+97 -54
View File
@@ -1,6 +1,7 @@
<script lang="ts">
import isDevEnv from "./sheep/utils/isDevEnv"
import { getAppInfo } from "@@/utils/getAppInfo"
import getLaunchParam from "@/sheep/utils/getLaunchParam"
// import { onLaunch, onShow, onHide } from "@dcloudio/uni-app"
// onLaunch(() => {})
@@ -31,22 +32,30 @@ const tabbar: TabbarItem[] = [
iconPath: "/static/tabbar/selfMerchant.png",
selectedIconPath: "/static/tabbar/selfMerchant-select.png",
launchParam: ["selfMerchant"],
auth: [],
auth: ["user"],
},
{
pagePath: "pages/tabbar/coopMerchant",
text: "合作商家",
iconPath: "/static/tabbar/coopMerchant.png",
selectedIconPath: "/static/tabbar/coopMerchant-select.png",
launchParam: ["selfMerchant"],
launchParam: ["coopMerchant"],
auth: ["user"],
},
{
pagePath: "pages/tabbar/cabinet",
text: "智能柜",
iconPath: "/static/tabbar/cabinet.png",
selectedIconPath: "/static/tabbar/cabinet-select.png",
launchParam: [],
auth: ["doorAdmin"],
},
{
pagePath: "pages/tabbar/order",
text: "订单",
iconPath: "/static/tabbar/order.png",
selectedIconPath: "/static/tabbar/order-select.png",
launchParam: ["canteen", "selfMerchant"],
launchParam: ["canteen", "selfMerchant", "coopMerchant"],
auth: ["user"],
},
{
@@ -65,21 +74,32 @@ const tabbar: TabbarItem[] = [
launchParam: [],
auth: ["merchant"],
},
{
pagePath: "pages/tabbar/visitor",
text: "访客",
iconPath: "/static/tabbar/visitor.png",
selectedIconPath: "/static/tabbar/visitor-select.png",
launchParam: [],
auth: [],
},
{
pagePath: "pages/tabbar/message",
text: "通知公告",
iconPath: "/static/tabbar/message.png",
selectedIconPath: "/static/tabbar/message-select.png",
launchParam: ["message"],
auth: [],
},
{
pagePath: "pages/tabbar/my",
text: "我的",
iconPath: "/static/tabbar/my.png",
selectedIconPath: "/static/tabbar/my-select.png",
launchParam: ["canteen", "selfMerchant"],
auth: ["user", "merchant"],
launchParam: ["canteen", "selfMerchant", "coopMerchant"],
auth: ["user", "merchant", "doorAdmin"],
},
]
// 获取启动参数
const getLaunchParam = () => {
return new URL(window.location.href).searchParams.get("launchParam")
}
// 设置tabbar项目
const setTabbarItem = (index: number, item: TabbarItem, visible: boolean) => {
uni.setTabBarItem({
@@ -93,55 +113,69 @@ const setTabbarItem = (index: number, item: TabbarItem, visible: boolean) => {
}
// 根据启动参数设置tabbar项目
const setTabbarByLaunchParam = (launchParam: string) => {
tabbar.forEach((item, index) => {
const visible = item.launchParam.includes(launchParam)
setTabbarItem(index, item, visible)
})
}
// 根据用户角色设置tabbar项目
const setTabbarByUserRole = (role: string) => {
tabbar.forEach((item, index) => {
const visible = item.auth.includes(role)
setTabbarItem(index, item, visible)
})
const setTabbar = (launchParam?: string, auth?: string) => {
if (launchParam && !auth) {
tabbar.forEach((item, index) => {
const visible = item.launchParam.includes(launchParam)
setTabbarItem(index, item, visible)
})
return
}
if (!launchParam && auth) {
tabbar.forEach((item, index) => {
const visible = item.auth.includes(auth)
setTabbarItem(index, item, visible)
})
}
if (launchParam && auth) {
tabbar.forEach((item, index) => {
const visible = item.launchParam.includes(launchParam) && item.auth.includes(auth)
setTabbarItem(index, item, visible)
})
}
}
export default {
async onLaunch() {
if (isDevEnv()) return
uni.setNavigationBarTitle({ title: "" })
// 环境判断
const appInfo = await getAppInfo()
if (appInfo == "zzd") {
// 浙政钉环境
const launchParam = getLaunchParam()
console.log("app launch 启动路径参数", launchParam)
switch (launchParam) {
switch (getLaunchParam()) {
case "canteen":
uni.switchTab({ url: "/pages/tabbar/canteen" })
break
case "selfMerchant":
uni.switchTab({ url: "/pages/tabbar/selfMerchant" })
break
case "coopMerchant":
uni.switchTab({ url: "/pages/tabbar/coopMerchant" })
break
case "thirdApp":
uni.navigateTo({ url: "/pages/thirdApp/thirdAppList" })
break
default:
break
}
} else if (appInfo == "sh") {
// 诗画环境
const userRole = uni.getStorageSync("userRole")
switch (userRole) {
case "merchant":
return uni.switchTab({ url: "/pages/tabbar/individualOrder" })
case "user":
return uni.switchTab({ url: "/pages/tabbar/coopMerchant" })
default:
return uni.redirectTo({ url: "/pages/user/userRole" })
const launchParam = getLaunchParam()
if (launchParam) {
switch (userRole) {
case "merchant":
return uni.switchTab({ url: "/pages/tabbar/individualOrder" })
case "user":
if (launchParam === "selfMerchant") return uni.switchTab({ url: "/pages/tabbar/selfMerchant" })
if (launchParam === "coopMerchant") return uni.reLaunch({ url: "/pages/tabbar/coopMerchant" })
return
case "doorAdmin":
return uni.switchTab({ url: "/pages/tabbar/cabinet" })
default:
return uni.redirectTo({ url: "/pages/user/userRole" })
}
}
}
},
@@ -158,35 +192,44 @@ export default {
}
const launchParam = getLaunchParam()
console.log("tabbar launch 启动路径参数", launchParam)
const appInfo = await getAppInfo()
if (appInfo == "zzd") {
// 浙政钉环境
if (launchParam) {
setTabbarByLaunchParam(launchParam)
setTabbar(launchParam)
uni.showTabBar()
} else {
uni.hideTabBar()
uni.showToast({ title: "启动参数不合法", icon: "none" })
// uni.showToast({ title: "启动参数不合法", icon: "none" })
}
} else if (appInfo == "sh") {
// 是诗画环境
const userRole = uni.getStorageSync("userRole")
switch (userRole) {
case "user":
setTabbarByUserRole("user")
uni.showTabBar()
break
case "merchant":
setTabbarByUserRole("merchant")
uni.showTabBar()
break
default:
uni.hideTabBar()
uni.removeStorageSync("userRole")
uni.showToast({ title: "用户身份未确认", icon: "none" })
break
if (launchParam) {
switch (userRole) {
case "user":
setTabbar(launchParam, "user")
uni.showTabBar()
break
case "merchant":
setTabbar(undefined, "merchant")
uni.showTabBar()
break
case "doorAdmin":
setTabbar(undefined, "doorAdmin")
uni.showTabBar()
break
default:
uni.hideTabBar()
uni.removeStorageSync("userRole")
uni.showToast({ title: "用户身份未确认", icon: "none" })
uni.reLaunch({ url: "/pages/user/userRole" })
break
}
} else {
uni.hideTabBar()
// uni.showToast({ title: "启动参数不合法", icon: "none" })
}
}
},
+97 -8
View File
@@ -30,6 +30,13 @@
"disableScroll": true
}
},
{
"path": "pages/tabbar/cabinet",
"style": {
"navigationBarTitleText": "智能柜",
"disableScroll": true
}
},
{
"path": "pages/tabbar/order",
"style": {
@@ -51,6 +58,20 @@
"disableScroll": true
}
},
{
"path": "pages/tabbar/visitor",
"style": {
"navigationBarTitleText": "访客",
"disableScroll": true
}
},
{
"path": "pages/tabbar/message",
"style": {
"navigationBarTitleText": "通知公告",
"disableScroll": true
}
},
{
"path": "pages/tabbar/my",
"style": {
@@ -167,7 +188,7 @@
]
},
{
"root": "pages/merchant",
"root": "pages/canteen",
"pages": [
{
"path": "detail",
@@ -329,13 +350,6 @@
"disableScroll": true
}
},
{
"path": "cabinetList",
"style": {
"navigationBarTitleText": "智能柜列表",
"disableScroll": true
}
},
{
"path": "cabinetDetail",
"style": {
@@ -359,6 +373,57 @@
}
]
},
{
"root": "pages/water",
"pages": [
{
"path": "waterTotal",
"style": {
"navigationBarTitleText": "月度流水统计"
}
}
]
},
{
"root": "pages/visitor",
"pages": [
{
"path": "apply",
"style": {
"navigationBarTitleText": "访客申请"
}
},
{
"path": "applyRecord",
"style": {
"navigationBarTitleText": "申请记录"
}
},
{
"path": "invitation",
"style": {
"navigationBarTitleText": "访客邀约"
}
},
{
"path": "invitationRecord",
"style": {
"navigationBarTitleText": "邀约记录"
}
}
]
},
{
"root": "pages/thirdApp",
"pages": [
{
"path": "thirdAppList",
"style": {
"navigationBarTitleText": "第三方应用"
}
}
]
},
{
"root": "pages/integrated",
"pages": [
@@ -398,6 +463,12 @@
"iconPath": "",
"selectedIconPath": ""
},
{
"pagePath": "pages/tabbar/cabinet",
"text": "",
"iconPath": "",
"selectedIconPath": ""
},
{
"pagePath": "pages/tabbar/order",
"text": "",
@@ -416,6 +487,18 @@
"iconPath": "",
"selectedIconPath": ""
},
{
"pagePath": "pages/tabbar/visitor",
"text": "",
"iconPath": "",
"selectedIconPath": ""
},
{
"pagePath": "pages/tabbar/message",
"text": "通知公告",
"iconPath": "",
"selectedIconPath": ""
},
{
"pagePath": "pages/tabbar/my",
"text": "",
@@ -441,6 +524,12 @@
// selectedIconPath: "static/tabbar/coopMerchant-select.png",
// },
// {
// pagePath: "pages/tabbar/cabinet",
// text: "智能柜",
// iconPath: "static/tabbar/coopMerchant.png",
// selectedIconPath: "static/tabbar/coopMerchant-select.png",
// },
// {
// "pagePath": "pages/tabbar/order",
// "text": "订单",
// "iconPath": "static/tabbar/order.png",
+114 -105
View File
@@ -1,6 +1,6 @@
<script setup lang="ts">
import { ref, reactive } from "vue";
import { onLoad, onShow } from "@dcloudio/uni-app";
import { ref, reactive } from "vue"
import { onLoad, onShow } from "@dcloudio/uni-app"
import { isEmpty } from "radash"
import dayjs from "dayjs"
@@ -8,129 +8,138 @@ import { hooks, router } from "@@/index"
import { applyApi } from "@@/api"
const state = reactive<any>({
detailType: "add",
detailId: null,
detail: null,
detailType: "add",
detailId: null,
detail: null,
})
const applyForm = reactive<any>({
displayTimeRange: "",
displayTimeRangeStr: "",
count: 1,
remark: "",
displayTimeRange: "",
displayTimeRangeStr: "",
count: 1,
remark: "",
})
const applyFormRules = reactive<any>({
displayTimeRangeStr: [
{ required: true, message: '请选择使用时间' }
],
count: [
{ required: true, message: '请输入申请数量' },
{ required: true, min: 1, message: '最少申请1张' },
{ required: true, max: 20, message: '最多申请20张' },
]
displayTimeRangeStr: [{ required: true, message: "请选择使用时间" }],
count: [
{ required: true, message: "请输入申请数量" },
{ required: true, min: 1, message: "最少申请1张" },
{ required: true, max: 20, message: "最多申请20张" },
],
})
onLoad((options: any) => {
const { type, id } = options
if (!isEmpty(type)) state.detailType = type
if (!isEmpty(id)) state.detailId = id
if (type === 'view') {
getDetail()
}
});
onShow(() => {
const { type, id } = options
if (!isEmpty(type)) state.detailType = type
if (!isEmpty(id)) state.detailId = id
if (type === "view") {
getDetail()
}
})
onShow(() => {})
const getDetail = async () => {
if (isEmpty(state.detailId)) return
const _pa = { id: state.detailId }
const { data } = await applyApi.foreignDetail(_pa)
if (!isEmpty(data)) {
state.detail = data
const startTime = hooks.useTime(data.applyStartTime, "{y}-{m}-{d}")
const endTime = hooks.useTime(data.applyEndTime, "{y}-{m}-{d}")
applyForm.displayTimeRangeStr = startTime + "~" + endTime
applyForm.count = data.count
if (isEmpty(data.remark)) {
applyForm.remark = "无"
} else {
applyForm.remark = data.remark
}
}
if (isEmpty(state.detailId)) return
const _pa = { id: state.detailId }
const { data } = await applyApi.foreignDetail(_pa)
if (!isEmpty(data)) {
state.detail = data
const startTime = hooks.useTime(data.applyStartTime, "{y}-{m}-{d}")
const endTime = hooks.useTime(data.applyEndTime, "{y}-{m}-{d}")
applyForm.displayTimeRangeStr = startTime + "~" + endTime
applyForm.count = data.count
if (isEmpty(data.remark)) {
applyForm.remark = "无"
} else {
applyForm.remark = data.remark
}
}
}
const applyFormRef = ref<any>(null)
const doSubmit = async () => {
applyFormRef.value.submit()
const { isPass } = applyFormRef.value.validate()
if (!isPass) return
const range = applyForm.displayTimeRange
console.log(range);
try {
uni.showLoading({ title: '申请中...', mask: false });
const _pa = {
applyStartTime: hooks.useTime(range[0], "{y}-{m}-{d}"),
applyEndTime: hooks.useTime(range[1], "{y}-{m}-{d}"),
count: applyForm.count,
remark: applyForm.remark,
}
const { data, code }: any = await applyApi.foreignApply(_pa)
if (code != 0) throw new Error()
uni.hideLoading()
uni.showToast({ title: '申请成功', icon: "none" });
router.back()
} catch (error) {
console.error(error);
uni.hideLoading()
}
applyFormRef.value.submit()
const { isPass } = applyFormRef.value.validate()
if (!isPass) return
const range = applyForm.displayTimeRange
console.log(range)
try {
uni.showLoading({ title: "申请中...", mask: false })
const _pa = {
applyStartTime: hooks.useTime(range[0], "{y}-{m}-{d}"),
applyEndTime: hooks.useTime(range[1], "{y}-{m}-{d}"),
count: applyForm.count,
remark: applyForm.remark,
}
const { data, code }: any = await applyApi.foreignApply(_pa)
if (code != 0) throw new Error()
uni.hideLoading()
uni.showToast({ title: "申请成功", icon: "none" })
router.back()
} catch (error) {
console.error(error)
uni.hideLoading()
}
}
</script>
<template>
<crud-layout title="外来人员就餐" bg="/static/page/blue-bg.png">
<view class="h-30rpx" />
<view class="card p-x-30rpx p-y-40rpx">
<tm-form ref="applyFormRef" v-model="applyForm" :rules="applyFormRules" direction="vertical">
<tm-form-item name="displayTimeRangeStr" label="使用时间" :showBottom="false">
<tm-between-time start="2020-1-1" end="2030-1-1" v-model="applyForm.displayTimeRange"
v-model:model-str="applyForm.displayTimeRangeStr" format="YYYY-MM-DD">
<view :style="{ pointerEvents: state.detailType == 'view' ? 'auto' : 'none' }">
<tm-input v-model="applyForm.displayTimeRangeStr" disabled placeholder="请选择使用时间..">
<template v-slot:rightIcon>
<text v-if="state.detailType != 'view'"
class="p-0.5rem color-#b1b1b1 iconfont icon-xiangxiajiantouxiao"></text>
</template>
</tm-input>
</view>
</tm-between-time>
</tm-form-item>
<view class="h-30rpx" />
<tm-form-item name="count" label="申请数量" :showBottom="false">
<tm-input v-model="applyForm.count" type="number" :disabled="state.detailType == 'view'"
:showClear="state.detailType != 'view'" placeholder="请输入申请数量.." />
</tm-form-item>
<view class="h-30rpx" />
<tm-form-item name="remark" label="备注" :required="false" :showBottom="false">
<tm-input v-model="applyForm.remark" type="textarea" :disabled="state.detailType == 'view'"
:showClear="state.detailType != 'view'"
:placeholder="state.detailType == 'view' ? '' : '请输入备注..'"></tm-input>
</tm-form-item>
</tm-form>
</view>
<view v-if="state.detailType != 'view'"
class="bg-#0094ff p-y-20rpx text-center rounded-40rpx m-x-30rpx m-t-60rpx sub-text-30 color-white!"
@tap="doSubmit">
提交
</view>
</crud-layout>
<crud-layout title="外来人员就餐" bg="/static/page/blue-bg.png">
<view class="h-30rpx" />
<view class="card p-x-30rpx p-y-40rpx">
<tm-form ref="applyFormRef" v-model="applyForm" :rules="applyFormRules" direction="vertical">
<tm-form-item name="displayTimeRangeStr" label="使用时间" :showBottom="false">
<tm-between-time
start="2020-1-1"
end="2030-1-1"
v-model="applyForm.displayTimeRange"
v-model:model-str="applyForm.displayTimeRangeStr"
format="YYYY-MM-DD"
>
<view :style="{ pointerEvents: state.detailType == 'view' ? 'auto' : 'none' }">
<tm-input v-model="applyForm.displayTimeRangeStr" disabled placeholder="请选择使用时间..">
<template v-slot:rightIcon>
<text v-if="state.detailType != 'view'" class="p-0.5rem color-#b1b1b1 iconfont icon-xiangxiajiantouxiao"></text>
</template>
</tm-input>
</view>
</tm-between-time>
</tm-form-item>
<view class="h-30rpx" />
<tm-form-item name="count" label="申请数量" :showBottom="false">
<tm-input
v-model="applyForm.count"
type="number"
:disabled="state.detailType == 'view'"
:showClear="state.detailType != 'view'"
placeholder="请输入申请数量.."
/>
</tm-form-item>
<view class="h-30rpx" />
<tm-form-item name="remark" label="备注" :required="false" :showBottom="false">
<tm-input
v-model="applyForm.remark"
type="textarea"
:disabled="state.detailType == 'view'"
:showClear="state.detailType != 'view'"
:placeholder="state.detailType == 'view' ? '' : '请输入备注..'"
></tm-input>
</tm-form-item>
</tm-form>
</view>
<view
v-if="state.detailType != 'view'"
class="bg-#0094ff p-y-20rpx text-center rounded-40rpx m-x-30rpx m-t-60rpx sub-text-30 color-white!"
@tap="doSubmit"
>
提交
</view>
</crud-layout>
</template>
<style lang="scss" scoped>
:deep() {
.tmFormItemLabel {
padding-bottom: 10rpx !important;
}
.tmFormItemLabel {
padding-bottom: 10rpx !important;
}
}
</style>
</style>
+1 -1
View File
@@ -30,7 +30,7 @@
<image class="w-50rpx h-50rpx mr-3" src="@/static/page/印章.svg" />
<view>
<view class="second-text-26">第一步</view>
<tm-text font-size="28">购买需钱包余额大于100元</tm-text>
<tm-text font-size="28">购买需消费钱包余额大于100元</tm-text>
</view>
</view>
<view class="flex items-center p-10rpx">
+49 -7
View File
@@ -81,7 +81,15 @@
</tm-sheet>
<tm-sheet v-for="(item, index) in state.detail.cabinetList" :key="index" :margin="[0, 20]" class="second-text-28">
<tm-text font-size="32">{{ "柜门" + state.detail.deviceCode + "-" + item.cabinetNo }}</tm-text>
<view class="flex justify-between items-center">
<tm-text font-size="32">{{ "柜门" + state.detail.deviceCode + "-" + item.cabinetNo }}</tm-text>
<view class="flex">
<tm-button block size="s" class="px-1" @click="checkOpenAccess(item.cabinetNo)">检修开门</tm-button>
&nbsp;&nbsp;
<tm-button block size="s" class="px-1" color="warn" @click="checkCloseAccess(item.cabinetNo)">检修关门</tm-button>
</view>
</view>
<view class="flex justify-between mt-1">
<text>货柜号:</text>
<text>{{ item.cabinetNo }}</text>
@@ -119,28 +127,62 @@ import { onLoad, onShow } from "@dcloudio/uni-app"
import { doorApi } from "@/sheep/api"
const state = reactive<any>({
hardDoorId: "",
id: "",
detail: {},
})
onLoad((option: any) => {
if (!option.hardDoorId) return
state.hardDoorId = option.hardDoorId
if (!option.id) return
state.id = option.id
})
onShow(async () => {
try {
uni.showLoading({ title: "加载中...", mask: true })
const res = await doorApi.hardDoorDetail({ hardDoorId: state.hardDoorId })
const res = await doorApi.hardDoorDetail({ hardDoorId: state.id })
if (res.code == 0) {
state.detail = res.data
return
} else {
uni.showToast({ title: res.msg, icon: "none" })
}
uni.showToast({ title: res.msg, icon: "none" })
} catch (error: any) {
uni.showToast({ title: error.msg, icon: "none" })
} finally {
uni.hideLoading()
}
})
// 检修开门
const checkOpenAccess = async (cabinetNo: string) => {
try {
uni.showLoading({ title: "开门中...", mask: true })
const res: any = await doorApi.openAccess({ hardDoorId: state.id, cabinetNo })
if (res.code == 0) {
uni.showToast({ title: "开门成功", icon: "none" })
} else {
uni.showToast({ title: res.msg, icon: "none" })
}
} catch (error: any) {
uni.showToast({ title: error.msg, icon: "none" })
} finally {
uni.hideLoading()
}
}
// 检修关门
const checkCloseAccess = async (cabinetNo: string) => {
try {
uni.showLoading({ title: "关门中...", mask: true })
const res = await doorApi.closeAccess({ hardDoorId: state.id, cabinetNo })
if (res.code == 0) {
uni.showToast({ title: "关门成功", icon: "none" })
} else {
uni.showToast({ title: res.msg, icon: "none" })
}
} catch (error: any) {
uni.showToast({ title: error.msg, icon: "none" })
} finally {
uni.hideLoading()
}
}
</script>
+183 -61
View File
@@ -1,9 +1,8 @@
<template>
<crud-layout bg="/static/page/blue-bg.png">
<crud-layout mainIsScroll bg="/static/page/blue-bg.png">
<z-paging
ref="pageRef"
height="100%"
:fixed="false"
height="100%"
safe-area-inset-bottom
:loading-more-enabled="true"
:show-scrollbar="false"
@@ -11,6 +10,7 @@
:auto-scroll-to-top-when-reload="false"
>
<template #top>
<view class="h-5rpx" />
<view class="bg-white rounded-20rpx my-20rpx font-bold">
<z-tabs
:list="
@@ -38,100 +38,153 @@
<view v-for="(item, index) in state.cabinetList" :key="index">
<tm-text class="text-center">第 {{ index + 1 }} 层</tm-text>
<view class="flex flex-wrap mb-4">
<view v-for="(v, i) in item[index + 1]" :key="i" class="w-1/5 h-150 p-1">
<view v-if="v.spuId && v.spuDetail" class="card w-full h-full flex items-center justify-center">
<image class="w-full h-full" :src="v.spuDetail.pic" />
<view v-for="(v, i) in item[index + 1]" :key="i" class="w-1/5 h-230 p-1">
<view v-if="v.spuId && v.spuDetail" class="flex-col items-center relative">
<view class="absolute top-[-10rpx] right-[-10rpx] z-200" @click="doUnPutaway(v)">
<image class="w-36rpx h-36rpx" src="@/static/page/关闭.svg" />
</view>
<image class="w-full h-150 rounded-2" :src="v.spuDetail.pic" @click.stop="hooks.usePreviewImage(v.spuDetail.pic)" />
<view class="sub-text-22">
{{ v.spuDetail.name?.length > 4 ? v.spuDetail.name.substring(0, 4) + "..." : v.spuDetail.name }}
</view>
<view class="sub-text-22 c-red!">¥{{ displayPrice(v.spuDetail.price) }}</view>
</view>
<view v-else class="card w-full h-full p-2 flex items-center justify-center active:bg-#e8e8e8!" @click="doPutaway">
<view v-else class="card w-full h-150 p-2 flex items-center justify-center active:bg-#e8e8e8!" @click="doPutaway(v.id)">
<image class="w-half h-half" src="@/static/page/加号.svg" />
</view>
</view>
</view>
</view>
</view>
<view class="h-30rpx" />
</z-paging>
<tm-drawer
title="选择商品"
:showClose="true"
:showFooter="true"
size="90%"
title=""
:showClose="false"
:showFooter="false"
size="98%"
placement="bottom"
v-model:show="state.showDrawer"
zIndex="999"
:duration="100"
zIndex="100"
>
<tm-tabs
item-width="50%"
gap="0"
line-full
line-height="4rpx"
round="10"
active-title-color=""
:list="['平台商品', '我的商品']"
@change="goodsTabsChange"
/>
<view class="h-30rpx" />
<z-paging
ref="pageRef"
:fixed="true"
height="98%"
v-model="pageHook.list"
:default-page-size="10"
safe-area-inset-bottom
:loading-more-enabled="true"
:show-scrollbar="false"
@query="query"
:auto-clean-list-when-reload="false"
:auto-scroll-to-top-when-reload="false"
@scroll="pageHook.scroll"
>
<template #top>
<view class="px-4 pt-2">
<tm-input v-model="queryParams.name" type="text" inputPadding="16" :showClear="true" placeholder="请输入货品名称">
<template v-slot:rightIcon>
<tm-button class="mr-1" size="m" @click="searchGoods">搜索</tm-button>
</template>
</tm-input>
</view>
<z-tabs
:list="['平台商品', '我的商品']"
bar-width="150"
:active-style="{
fontSize: '30rpx',
}"
:inactive-style="{
fontSize: '30rpx',
}"
@change="goodsTabsChange"
/>
</template>
<tm-checkbox-group v-model="state.checkboxValue" direction="column">
<view
v-for="(item, index) in listview"
:key="index"
class="w-full h-100rpx flex items-center p-2 border-1 border-solid border-b-coolGray"
:class="[state.checkboxValue.includes(item.id) ? 'bg-#e8e8e8' : '']"
>
<tm-checkbox class="w-full h-full" :value="item.id">
<template v-slot:label="checked">
<tm-text>{{ 11111 }}</tm-text>
</template>
</tm-checkbox>
</view>
</tm-checkbox-group>
<tm-radio-group v-model="state.radioValue" direction="column">
<view
v-for="(item, index) in pageHook.list"
:key="index"
class="w-full flex items-center p-2"
:class="[state.radioValue == item.id ? 'bg-#e8e8e8' : '']"
>
<tm-radio class="w-full h-full px-2" :value="item.id">
<template v-slot:label="checked">
<view class="flex items-center">
<image class="w-130rpx h-130rpx" :src="item.pic" />
<view class="ml-2 flex-1 flex-col">
<tm-text font-size="30">{{ item.name }}</tm-text>
<view class="flex justify-between my-1">
<tm-text font-size="26">种类:{{ item.categoryName }}</tm-text>
<tm-text font-size="26">售卖数量:{{ item.salesCount }}</tm-text>
<tm-text font-size="26">库存:{{ item.repertoryCount || 0 }}</tm-text>
</view>
<view class="flex justify-between items-center">
<tm-text font-size="30" color="red">¥{{ displayPrice(item.price) }}</tm-text>
</view>
</view>
</view>
</template>
</tm-radio>
</view>
</tm-radio-group>
<view class="h-30rpx" />
<view class="h-30rpx" />
<template #footer>
<view class="px-20rpx flex justify-between">
<tm-button skin="thin" block>取消</tm-button>
&nbsp;&nbsp;
<tm-button block>上架</tm-button>
</view>
</template>
<template #bottom>
<view class="px-20rpx pt-2 flex justify-between">
<tm-button skin="thin" block @click="state.showDrawer = false">取消</tm-button>
&nbsp;&nbsp;
<tm-button block @click="confirmPutaway" :disabled="!state.radioValue">上架</tm-button>
</view>
</template>
</z-paging>
</tm-drawer>
</crud-layout>
</template>
<script setup lang="ts">
import { computed, reactive } from "vue"
import { computed, reactive, ref } from "vue"
import zTabs from "@@/components/other/z-tabs/z-tabs.vue"
import { doorApi } from "@/sheep/api"
import { onLoad, onShow } from "@dcloudio/uni-app"
import { displayPrice } from "@/sheep/utils/formatMoney"
import { hooks } from "@/sheep"
const state = reactive<any>({
hardDoorId: "",
id: "",
detail: {},
curDoorTabIndex: 0,
cabinetList: [],
curGoodsTabIndex: 0,
cabinetList: [],
showDrawer: false,
checkboxValue: [],
cabinetNoId: "",
radioValue: "",
})
const queryParams = reactive({
name: "",
skuType: "0",
spuCategoryIdIsNotNull: true,
})
const pageRef = ref()
const curCabinetNo = computed(() => {
if (state.detail.cabinetList) return state.detail.cabinetList[state.curDoorTabIndex].cabinetNo
})
onLoad((option: any) => {
if (!option.hardDoorId) return
state.hardDoorId = option.hardDoorId
if (!option.id) return
state.id = option.id
})
onShow(async () => {
if (!state.hardDoorId) return
if (!state.id) return
try {
uni.showLoading({ title: "加载中...", mask: true })
const res = await doorApi.hardDoorDetail({ hardDoorId: state.hardDoorId })
const res = await doorApi.hardDoorDetail({ hardDoorId: state.id })
if (res.code == 0) {
state.detail = res.data
} else {
@@ -151,7 +204,7 @@ onShow(async () => {
const getCabinetList = async () => {
try {
uni.showLoading({ title: "加载中...", mask: true })
const res = await doorApi.cabinetList({ hardId: state.hardDoorId, cabinetNo: curCabinetNo.value })
const res = await doorApi.cabinetList({ hardId: state.detail.hardId, cabinetNo: curCabinetNo.value })
if (res.code == 0) {
state.cabinetList = res.data
} else {
@@ -169,13 +222,82 @@ const doorTabsChange = async (e: number) => {
await getCabinetList()
}
const goodsTabsChange = (index: number) => {
state.curGoodsTabIndex = index
const goodsTabsChange = async (e: number) => {
state.curGoodsTabIndex = e
queryParams.skuType = e.toString()
pageRef.value.reload(true)
}
// 上架
const doPutaway = () => {
// 点击上架
const doPutaway = async (cabinetNoId: string) => {
state.curGoodsTabIndex = 0
queryParams.skuType = "0"
queryParams.name = ""
state.cabinetNoId = cabinetNoId
state.radioValue = ""
state.showDrawer = true
}
// 搜索商品
const searchGoods = () => {
state.radioValue = ""
pageRef.value.reload(true)
}
const pageHook = hooks.usePage(pageRef, doorApi.hardDoorSpuPage, null, "data.records")
const query = (page: number, pagesize: number) => {
pageHook.startPage(page, pagesize, false, queryParams)
}
// 确认上架
const confirmPutaway = async () => {
if (!state.radioValue) return uni.showToast({ title: "请先选择商品", icon: "none" })
try {
uni.showLoading({ title: "上架中...", mask: true })
const res = await doorApi.putaway({ id: state.cabinetNoId, hardSpuId: state.radioValue })
if (res.code == 0) {
state.showDrawer = false
state.cabinetNoId = ""
state.radioValue = ""
await getCabinetList()
} else {
uni.showToast({ title: res.msg, icon: "none" })
}
} catch (error: any) {
uni.showToast({ title: error.msg, icon: "none" })
} finally {
uni.hideLoading()
}
}
// 确认下架
const doUnPutaway = (v: any) => {
if (!v.id) return uni.showToast({ title: "绑定id不存在", icon: "none" })
if (!v.spuId) return uni.showToast({ title: "商品id不存在", icon: "none" })
uni.showModal({
title: "提示",
content: "确定要下架该商品吗?",
success: async (res) => {
if (res.confirm) {
try {
uni.showLoading({ title: "下架中...", mask: true })
const res: any = await doorApi.unPutaway({ id: v.id, hardSpuId: v.spuId })
if (res.code == 0) {
uni.showToast({ title: "下架成功", icon: "none" })
await getCabinetList()
} else {
uni.showToast({ title: res.msg, icon: "none" })
}
} catch (error: any) {
uni.showToast({ title: error.msg, icon: "none" })
} finally {
uni.hideLoading()
}
}
},
})
}
</script>
+14 -10
View File
@@ -62,9 +62,9 @@
<template #main-bottom>
<view class="m-30rpx flex justify-between">
<tm-button block @click="openDoor" :disabled="false">开门补货</tm-button>
<tm-button block @click="openDoor" :disabled="!state.cabinetPutawayList.length">开门补货</tm-button>
&nbsp;&nbsp;
<tm-button block @click="replenishmentComplete" :disabled="!state['flowId' + curCabinetNo.value]">补货完成</tm-button>
<tm-button block @click="replenishmentComplete" :disabled="!state['flowId' + curCabinetNo]">补货完成</tm-button>
</view>
</template>
</crud-layout>
@@ -78,7 +78,7 @@ import { doorApi } from "@/sheep/api"
import { displayPrice } from "@/sheep/utils/formatMoney"
const state = reactive<any>({
hardDoorId: "",
id: "",
detail: {},
curDoorTabIndex: 0,
cabinetPutawayList: [],
@@ -89,15 +89,15 @@ const curCabinetNo = computed(() => {
const putawayList = computed(() => state.cabinetPutawayList.map((item: any) => ({ hardSpuId: item.spuId, plusCount: item.plusCount || 0 })))
onLoad((option: any) => {
if (!option.hardDoorId) return
state.hardDoorId = option.hardDoorId
if (!option.id) return
state.id = option.id
})
onShow(async () => {
if (!state.hardDoorId) return
if (!state.id) return
try {
uni.showLoading({ title: "加载中...", mask: true })
const res = await doorApi.hardDoorDetail({ hardDoorId: state.hardDoorId })
const res = await doorApi.hardDoorDetail({ hardDoorId: state.id })
if (res.code == 0) {
state.detail = res.data
} else {
@@ -117,7 +117,7 @@ onShow(async () => {
const getCabinetPutawayList = async () => {
try {
uni.showLoading({ title: "加载中...", mask: true })
const res = await doorApi.cabinetPutawayList({ hardDoorId: state.detail.id, cabinetNo: curCabinetNo.value })
const res = await doorApi.cabinetPutawayList({ hardDoorId: state.id, cabinetNo: curCabinetNo.value })
if (res.code == 0) {
state.cabinetPutawayList = res.data
} else {
@@ -138,9 +138,11 @@ const doorTabsChange = async (e: number) => {
// 开门补货
const openDoor = async () => {
if (!state.id) return
if (!state.cabinetPutawayList.length) return uni.showToast({ title: "请先上架商品", icon: "none" })
try {
uni.showLoading({ title: "正在开门", mask: true })
const res = await doorApi.openRepertory({ hardDoorId: state.detail.id, cabinetNo: curCabinetNo.value })
const res = await doorApi.openRepertory({ hardDoorId: state.id, cabinetNo: curCabinetNo.value })
if (res.code == 0) {
state["flowId" + curCabinetNo.value] = res.data
uni.showToast({ title: "开门成功", icon: "none" })
@@ -161,7 +163,9 @@ const replenishmentComplete = async () => {
uni.showLoading({ title: "正在保存", mask: true })
const res = await doorApi.repertoryDone({ flowId: state["flowId" + curCabinetNo.value], list: putawayList.value })
if (res.code == 0) {
uni.showToast({ title: "保存成功", icon: "none" })
state["flowId" + curCabinetNo.value] = ""
uni.showToast({ title: "补货成功", icon: "none" })
await getCabinetPutawayList()
} else {
uni.showToast({ title: res.msg || "保存失败", icon: "none" })
}
@@ -36,7 +36,16 @@ const remove = (v) => emit("remove", v)
</script>
<template>
<tm-drawer z-index="100" v-model:show="props.modelValue" showFooter title="购物车" position="bottom" size="60%" @close="doClose">
<tm-drawer
z-index="100"
v-model:show="props.modelValue"
showFooter
title="购物车"
position="bottom"
size="60%"
bgColor="#ECF4F9"
@close="doClose"
>
<view v-for="(v, i) in props.cartList" :key="v.id">
<product-row
v-model="v.productCount"
@@ -46,14 +46,14 @@ const remove = () => {
<template>
<view
class="flex-row items-start card p-x-15rpx p-y-25rpx m-b-20rpx"
@tap="props.productId && router.jump('/pages/merchant/product-detail', { id: props.productId })"
@tap="props.productId && router.jump('/pages/canteen/product-detail', { id: props.productId })"
>
<image v-if="props.mode == 'default'" class="size-180rpx rounded-12rpx" :src="props.pic" mode="aspectFill" />
<image v-if="props.mode == 'cart'" class="size-120rpx rounded-12rpx" :src="props.pic" mode="aspectFill" />
<view class="flex-1 m-l-20rpx">
<view class="sub-text-28 show-line">{{ props.name }}</view>
<view class="m-t-10rpx flex-row items-center">
<view class="w-100rpx second-text-32 color-red!"> ¥{{ hooks.useMoney(props.price) }} </view>
<view class="w-110rpx second-text-32 color-red!"> ¥{{ hooks.useMoney(props.price) }} </view>
<view v-if="props.mode == 'default'" class="m-l-20rpx second-text-24 line-through">¥{{ hooks.useMoney(props.marketPrice) }}</view>
<view v-if="props.mode == 'cart'" class="m-l-40rpx second-text-24">x{{ props.count }}</view>
</view>
@@ -3,7 +3,7 @@ import { reactive, nextTick } from "vue"
import { onLoad, onShow } from "@dcloudio/uni-app"
import { isEmpty } from "radash"
import { hooks, router } from "@@/index"
import { merchantApi, foodApi, payApi } from "@@/api"
import { merchantApi, foodApi, payApi, orderApi } from "@@/api"
import { filePath } from "@@/utils/file"
import ProductRow from "./components/product-row.vue"
@@ -24,6 +24,10 @@ const state = reactive<any>({
currentClassifyIndex: 0,
showCartDialog: false,
showBookingDialog: false,
bookingTimeList: [],
selectedBookingTime: "",
})
onLoad((options: any) => {
@@ -154,8 +158,30 @@ const updateFoodCart = async () => {
// 打开购物车
const doVisibleCart = async () => (state.showCartDialog = true)
// 购买
// 购买 打开预订时间段选择对话框
const doBuy = async () => {
state.selectedBookingTime = ""
try {
uni.showLoading({ title: "加载中...", mask: true })
const res: any = await orderApi.apptList()
if (res.code == 0) {
state.bookingTimeList = res.data
state.selectedBookingTime = res.data[0].id
// 打开预约时间段选择对话框
state.showBookingDialog = true
} else {
uni.showToast({ title: res.msg, icon: "none" })
}
} catch (error: any) {
uni.showToast({ title: error.msg, icon: "none" })
} finally {
uni.hideLoading()
}
}
// 预约时间段对话框确认
const bookingDialogConfirm = () => {
if (!state.selectedBookingTime) return uni.showToast({ title: "请选择预订时间段", icon: "none" })
uni.showModal({
title: "提示",
content: "是否确定购买",
@@ -175,10 +201,12 @@ const submitBuy = async () => {
const _createtPa = {
carParentId: state.cartList[0].parentCarId,
hardType: "CANTEEN",
apptId: state.selectedBookingTime,
}
const { data: createData, code: createCode }: any = await payApi.createHardwareOrder(_createtPa)
if (createCode != 0) throw new Error()
uni.showToast({ title: "支付成功", icon: "none" })
state.showBookingDialog = false
router.jump("/pages/tabbar/order")
} catch (error) {
console.error(error)
@@ -196,7 +224,7 @@ const doPhone = () => {
}
const doFood = () => {
router.jump("/pages/merchant/food", { merchantId: state.detailId })
router.jump("/pages/canteen/food", { merchantId: state.detailId })
}
</script>
@@ -338,6 +366,37 @@ const doFood = () => {
@remove="(v) => chentProductCartCount(v)"
@submit="doBuy"
/>
<tm-modal
v-model:show="state.showBookingDialog"
:overlayClick="false"
:showCancel="true"
title="请选择预订时间段"
cancelText="取消"
confirmText="确认"
position="bottom"
height="520rpx"
zIndex="800"
>
<tm-radio-group v-model="state.selectedBookingTime" direction="column">
<view v-for="(item, index) in state.bookingTimeList" :key="index" class="w-full flex items-center p-2 mx-2">
<tm-radio class="w-full h-full px-2" :value="item.id">
<template v-slot:label="checked">
<view>{{ item.title }}</view>
<view>{{ item.startTime }} ~ {{ item.endTime }}</view>
</template>
</tm-radio>
</view>
</tm-radio-group>
<template #footer>
<view class="flex px-4 w-full">
<tm-button @click="state.showBookingDialog = false" :block="true" skin="thin">取消</tm-button>
&nbsp;&nbsp;
<tm-button @click="bookingDialogConfirm" :block="true">确认</tm-button>
</view>
</template>
</tm-modal>
</template>
<style lang="scss" scoped>
@@ -88,7 +88,7 @@ const doTab = (e: any) => {
}
const doProduct = (v: any) => {
// router.jump("/pages/merchant/product-detail", { spuId: v.spuId })
// router.jump("/pages/canteen/product-detail", { spuId: v.spuId })
}
</script>
@@ -4,6 +4,7 @@ import { onLoad, onShow } from "@dcloudio/uni-app"
import { isEmpty } from "radash"
import { productApi } from "@@/api"
import { filePath } from "@@/utils/file"
import { hooks } from "@@/index"
const state = reactive<any>({
detailId: null,
@@ -38,8 +39,8 @@ const getDetail = async () => {
<view class="flex-col justify-between card p-y-20rpx p-x-30rpx">
<view class="flex-row items-center justify-between">
<view class="flex-row items-center">
<view class="second-text-46 color-#f63a36!">¥{{ state.detail.price }}</view>
<view class="m-l-20rpx second-text-28 line-through">¥{{ state.detail.marketPrice }}</view>
<view class="second-text-46 color-#f63a36!">¥{{ hooks.useMoney(state.detail.price) }}</view>
<view class="m-l-20rpx second-text-28 line-through">¥{{ hooks.useMoney(state.detail.marketPrice) }}</view>
</view>
<view class="second-text-26">已售{{ state.detail.salesCount }}</view>
</view>
+6 -1
View File
@@ -71,7 +71,12 @@ const doCancelRefund = async () => {
<crud-layout title="订单详情" mainIsScroll bg="/static/page/blue-bg.png">
<view class="flex-row-center m-t-30rpx" v-if="state.detail.orderStatus == 5 && state.detail.orderType == 2">
<view class="flex-row-center bg-white w-550rpx rounded-16rpx">
<image class="w-500rpx" :src="filePath(state.detail.reserveCode)" mode="widthFix" />
<image
class="w-500rpx"
:src="filePath(state.detail.reserveCode)"
mode="widthFix"
@click.stop="hooks.usePreviewImage(filePath(state.detail.reserveCode))"
/>
</view>
</view>
<view class="h-30rpx" />
+3 -1
View File
@@ -59,6 +59,8 @@ onShow(() => {
})
const goBack = () => {
router.jump("/pages/tabbar/my", {}, 2)
const url: string = window.location.href.split("h5")[0] + "h5/?launchParam=coopMerchant#/pages/tabbar/order"
window.location.replace(url)
// router.jump(url, {}, 2)
}
</script>
+26 -16
View File
@@ -1,7 +1,7 @@
<template>
<crud-layout bg="/static/page/blue-bg.png">
<view class="h-screen flex flex-col">
<view class="mx-auto text-34 py-2 h-80rpx">{{ scanData.name }}</view>
<view class="mx-auto text-34 py-2 h-80rpx">{{ scanCodeData.name }}</view>
<tm-sheet class="flex flex-row">
<span class="text-2xl text-[#333] mr-1 line-height-normal">¥</span>
@@ -36,8 +36,8 @@
</template>
<script setup lang="ts">
import { ref, computed } from "vue"
import { onShow } from "@dcloudio/uni-app"
import { ref, computed, reactive } from "vue"
import { onLoad, onShow } from "@dcloudio/uni-app"
import { usePayStore } from "@/sheep/stores/pay"
import payApi from "@@/api/pay"
import { storePrice } from "@/sheep/utils/formatMoney"
@@ -46,23 +46,33 @@ import { merchantApi, walletApi } from "@/sheep/api"
import numberKeyboard from "@/sheep/components/numberKeyboard.vue"
import { filePath } from "@/sheep/utils/file"
import { hooks } from "@@/index"
import { isEmpty } from "radash"
const amount = ref("")
const scanData = ref<{ id?: string; name?: string }>({})
const disabled = ref(false)
const scanCodeData = reactive({
id: "",
name: "",
})
const walletList = ref<any>([])
const curWalletId = ref("")
const disabled = ref(false)
const amount = ref("")
onLoad((options: any) => {
if (!isEmpty(options.id)) {
scanCodeData.id = options.id
} else {
uni.showToast({ title: "参数不存在", icon: "none" })
}
})
onShow(async () => {
uni.showLoading({ title: "加载中...", mask: true })
scanData.value.id = usePayStore().payData.id
if (scanData.value.id) {
const { data } = await merchantApi.detail({ id: scanData.value.id })
scanData.value.name = data.name
usePayStore().setPayData(scanData.value)
if (scanCodeData.id) {
const { data } = await merchantApi.detail({ id: scanCodeData.id })
scanCodeData.name = data.name
disabled.value = false
} else {
uni.showToast({ title: "扫码信息不存在", icon: "none" })
uni.showToast({ title: "参数不存在", icon: "none" })
disabled.value = true
}
@@ -88,7 +98,7 @@ const displayAmount = computed(() => {
// 点击支付
const handlePay = () => {
if (!scanData.value.id || !scanData.value.name) return uni.showToast({ title: "扫码信息不存在", icon: "none" })
if (!scanCodeData.id || !scanCodeData.name) return uni.showToast({ title: "扫码参数不存在", icon: "none" })
if (!amount.value) {
uni.showToast({ title: "请输入金额", icon: "none" })
return
@@ -112,7 +122,7 @@ const pay = async () => {
try {
uni.showLoading({ title: "支付中...", mask: true })
const res = await payApi.createQrCodeOrder({
merchantId: scanData.value.id,
merchantId: scanCodeData.id,
customPrice: storePrice(Number(amount.value)),
walletId: curWalletId.value,
})
@@ -120,11 +130,11 @@ const pay = async () => {
uni.showToast({ title: res.msg || "支付失败", icon: "error" })
} else {
uni.hideLoading()
usePayStore().setPayData({ ...scanData.value, customPrice: Number(amount.value).toFixed(2) })
usePayStore().setPayData({ id: scanCodeData.id, name: scanCodeData.name, customPrice: Number(amount.value).toFixed(2) })
router.jump("/pages/pay/payComplete", {}, 2)
}
} catch (error: any) {
uni.showToast({ title: "错误", icon: "error" })
uni.showToast({ title: "请求错误", icon: "error" })
uni.hideLoading()
}
}
+1 -1
View File
@@ -124,7 +124,7 @@ const doSubmit = async () => {
class="flex-row items-start justify-between"
v-for="(v, i) in state.shopCarList"
:key="i"
@tap.stop="router.jump('/pages/merchant/product-detail', { id: v.productId })"
@tap.stop="router.jump('/pages/canteen/product-detail', { id: v.productId })"
>
<view class="flex-row items-center">
<image class="w-160rpx h-160rpx rounded-8rpx" :src="filePath(v.productPic)" mode="aspectFill" />
@@ -17,16 +17,16 @@
<view class="h-30rpx" />
<tm-sheet v-for="(item, index) in pageHook.list" :key="index" :margin="[0, 20]">
<tm-text font-size="32">{{ item.hardName }} {{ item.deviceCode }}</tm-text>
<view class="card flex justify-around items-center my-1 p-2">
<view class="flex-col items-center p-2 rounded-1 active:bg-#E8E8E8" @click="doDetail(item.hardId)">
<view class="flex justify-around items-center my-1">
<view class="flex-col items-center p-2 rounded-1 active:bg-#E8E8E8" @click="doDetail(item.id)">
<image class="w-50 h-50" src="@/static/page/货柜详情.svg" />
<tm-text>货柜详情</tm-text>
</view>
<view class="flex-col items-center p-2 rounded-1 active:bg-#E8E8E8" @click="replenishment(item.hardId)">
<view class="flex-col items-center p-2 rounded-1 active:bg-#E8E8E8" @click="replenishment(item.id)">
<image class="w-50 h-50" src="@/static/page/开门.svg" />
<tm-text>货柜补货</tm-text>
</view>
<view class="flex-col items-center p-2 rounded-1 active:bg-#E8E8E8" @click="openPutaway(item.hardId)">
<view class="flex-col items-center p-2 rounded-1 active:bg-#E8E8E8" @click="openPutaway(item.id)">
<image class="w-50 h-50" src="@/static/page/货柜上架.svg" />
<tm-text>商品上架</tm-text>
</view>
@@ -40,6 +40,12 @@
import { ref } from "vue"
import { hooks, router } from "@/sheep"
import { doorApi } from "@/sheep/api"
import { onLoad } from "@dcloudio/uni-app"
onLoad(() => {
const app = getApp()
app._initTabbar()
})
const pageRef = ref<any>(null)
@@ -50,20 +56,20 @@ const query = (page: number, pagesize: number) => {
}
// 货柜详情
const doDetail = (hardDoorId: string) => {
if (!hardDoorId) return
router.jump("/pages/cabinet/cabinetDetail", { hardDoorId }, 1)
const doDetail = (id: string) => {
if (!id) return
router.jump("/pages/cabinet/cabinetDetail", { id }, 1)
}
// 商品补货
const replenishment = (hardDoorId: string) => {
if (!hardDoorId) return
router.jump("/pages/cabinet/replenishment", { hardDoorId }, 1)
const replenishment = (id: string) => {
if (!id) return
router.jump("/pages/cabinet/replenishment", { id }, 1)
}
// 商品上架
const openPutaway = (hardDoorId: string) => {
if (!hardDoorId) return
router.jump("/pages/cabinet/putaway", { hardDoorId }, 1)
const openPutaway = (id: string) => {
if (!id) return
router.jump("/pages/cabinet/putaway", { id }, 1)
}
</script>
+1 -1
View File
@@ -31,7 +31,7 @@ const query = (page: number, pagesize: number) => {
const toDetail = async (v: any) => {
const isLogin = await hooks.useCheckLogin()
if (isLogin) {
router.jump("/pages/merchant/detail", { id: v.id })
router.jump("/pages/canteen/detail", { id: v.id })
}
}
</script>
+28 -1
View File
@@ -4,13 +4,16 @@ import { onLoad, onShow } from "@dcloudio/uni-app"
import { merchantApi } from "@@/api"
import { hooks, router } from "@@/index"
import { filePath } from "@@/utils/file"
import zTabs from "@@/components/other/z-tabs/z-tabs.vue"
const pageRef = ref<any>(null)
const state = reactive<any>({
pa: {
pagesize: 10,
type: "2",
catgoryId: null,
},
tabs: [{ id: null, name: "全部", disabled: false }],
})
const pageHook = hooks.usePage(pageRef, merchantApi.page, null, "data.records")
@@ -18,14 +21,31 @@ const query = (page: number, pagesize: number) => {
pageHook.startPage(page, pagesize, false, state.pa)
}
onLoad(() => {
onLoad(async () => {
const app = getApp()
app._initTabbar()
try {
const res: any = await merchantApi.selectCatgory({})
if (res.code == 0) {
state.tabs = state.tabs.concat(res.data)
} else {
state.tabs = [{ id: null, name: "全部", disabled: false }]
}
} catch (error: any) {
uni.showToast({ title: error, icon: "none" })
}
})
onShow(() => {
// pageRef.value && pageRef.value.reload(false)
})
const doTab = (e: any) => {
const target = state.tabs[e]
state.pa.catgoryId = target.id
pageRef.value.reload(true)
}
const toDetail = async (v: any) => {
const isLogin = await hooks.useCheckLogin()
if (isLogin) {
@@ -52,6 +72,13 @@ const toDetail = async (v: any) => {
:auto-scroll-to-top-when-reload="false"
@scroll="pageHook.scroll"
>
<template #top>
<view class="h-30rpx" />
<view class="bg-white rounded-16rpx px-20rpx">
<z-tabs :list="state.tabs" @change="doTab" />
</view>
</template>
<view class="h-20rpx" />
<view class="flex-row card p-20rpx m-b-20rpx" v-for="(v, i) in pageHook.list" :key="i" @tap="toDetail(v)">
<image class="w-180rpx h-180rpx rounded-12rpx my-auto" :src="filePath(v.logoPic)" mode="aspectFill" />
+29 -18
View File
@@ -3,6 +3,7 @@
<z-paging
ref="pageRef"
:fixed="false"
height="100%"
v-model="pageHook.list"
:default-page-size="10"
safe-area-inset-bottom
@@ -15,24 +16,27 @@
>
<template #top>
<view class="h-30rpx" />
<view class="bg-white rounded-12rpx p-20rpx flex justify-between items-center">
<text class="text-30 font-600">流水统计</text>
<tm-text color="#999999">{{ formatVal }}</tm-text>
<view class="flex items-center cursor-pointer">
<tm-between-time
start="2020-1-1"
end="2050-1-1"
v-model="state.date"
v-model:model-str="state.formatVal"
@confirm="datePickerConfirm"
format="YYYY-MM-DD"
:quickDate="[]"
:drawerSize="900"
>
<image class="w-[30rpx] h-[30rpx]" src="@/static/page/filter.svg" />
<text class="ml-1 text-30">筛选</text>
</tm-between-time>
<view class="flex items-center justify-between">
<view class="flex-1 bg-white rounded-12rpx p-20rpx flex justify-between items-center">
<text class="text-30 font-600">流水统计</text>
<tm-text color="#999999" font-size="26">{{ formatVal }}</tm-text>
<view class="flex items-center cursor-pointer">
<tm-between-time
start="2020-1-1"
end="2050-1-1"
v-model="state.date"
v-model:model-str="state.formatVal"
@confirm="datePickerConfirm"
format="YYYY-MM-DD"
:quickDate="[]"
drawerSize="900"
>
<image class="w-[30rpx] h-[30rpx]" src="@/static/page/filter.svg" />
<text class="ml-1 text-30">筛选</text>
</tm-between-time>
</view>
</view>
<tm-button size="m" class="px-1 ml-1" @click="doWaterTotal">月度流水</tm-button>
</view>
</template>
@@ -96,7 +100,7 @@ const state = reactive<any>({
createTimeList: [],
},
formatVal: "",
date: "",
date: [],
})
const formatVal = computed(() => (state.date.length === 2 ? state.formatVal : ""))
const pageHook = hooks.usePage(pageRef, flowStatisticsApi.page, null, "data")
@@ -124,4 +128,11 @@ const datePickerConfirm = (date: any) => {
state.pa.createTimeList = formatVal.value.split("~")
pageRef.value.reload(false)
}
// 月度流水
const doWaterTotal = () => {
uni.navigateTo({
url: "/pages/water/waterTotal",
})
}
</script>
+23 -23
View File
@@ -36,8 +36,8 @@
<view class="flex-col justify-center card p-3 m-b-20rpx" v-for="(v, i) in pageHook.list" :key="i">
<view class="flex-row items-center">
<image class="w-100rpx h-100rpx rounded-8rpx" :src="filePath(v.logoPic)" mode="aspectFill" />
<view class="flex-1 flex-col m-l-20rpx">
<image class="w-110rpx h-110rpx rounded-8rpx" :src="filePath(v.logoPic)" mode="aspectFill" />
<view class="flex-1 m-l-20rpx">
<view class="flex-row items-center justify-between">
<view class="flex-row items-center">
<view class="main-text-28">{{ v.merchantName }}</view>
@@ -47,36 +47,36 @@
<tm-tag v-if="v.orderStatus == 5" color="success" size="xs">已支付</tm-tag>
<tm-tag v-if="v.orderStatus == 10" color="error" size="xs">售后</tm-tag>
<tm-tag v-if="v.orderStatus == 20" size="xs">已核销</tm-tag>
<tm-tag v-if="v.orderStatus == 30" color="info" size="xs">已取消(智能柜)</tm-tag>
</view>
<view class="flex justify-between items-center m-t-5rpx">
<view class="second-text-22">
<text>{{ v.username }}</text>
<text class="m-l-10rpx">{{ v.userMobile }}</text>
</view>
<view class="second-text-22 h-30rpx">{{ hooks.useEnum("hardwareRefundStatusEnum", v.refundStatus) }}</view>
</view>
<view class="flex justify-between items-center">
<view class="flex flex-col">
<view class="second-text-22">
<text>{{ v.username }}</text>
<text class="m-l-10rpx">{{ v.userMobile }}</text>
</view>
<view class="second-text-22">
<text>下单时间</text>
<text class="m-l-10rpx">
{{ hooks.useTime(v.createTime, "{y}-{m}-{d} {h}:{i}:{s}") }}
</text>
</view>
</view>
<view class="flex flex-col items-end justify-center m-t-5rpx">
<view class="second-text-22 h-30rpx">{{ hooks.useEnum("hardwareRefundStatusEnum", v.refundStatus) }}</view>
<view class="flex">
<view v-if="v.carList?.length" class="m-t-4rpx m-r-10rpx second-text-26">共 {{ v.carList.length }} 件</view>
<view class="main-text-30 color-red!">¥ {{ hooks.useMoney(v.totalPrice) }}</view>
</view>
<view class="second-text-22">
<text>下单时间</text>
<text class="m-l-10rpx">{{ hooks.useTime(v.createTime, "{y}-{m}-{d} {h}:{i}:{s}") }}</text>
</view>
<view class="main-text-30 color-red! min-w-140rpx text-right">¥ {{ hooks.useMoney(v.totalPrice) }}</view>
<!-- <view class="second-text-24">共 {{ v.carList.length }} 件</view> -->
</view>
<view v-if="v.payType == '9'" class="sub-text-24">{{ v.productDesc }}</view>
</view>
</view>
<div class="flex justify-end items-center mt-1">
<view class="flex justify-end items-center mt-1">
<view v-if="v.orderType == '1' && v.refundStatus" class="ml-1 botder_btn" @tap.stop="refundDetail(v)">售后详情</view>
<view v-if="v.orderStatus == '5' && v.orderType == '1'" class="ml-1 botder_btn" @tap.stop="doIndividualRefund(v)">
<view
v-if="v.orderStatus == '5' && v.orderType == '1' && v.payType != '9'"
class="ml-1 botder_btn"
@tap.stop="doIndividualRefund(v)"
>
申请退款
</view>
</div>
</view>
</view>
</z-paging>
+70
View File
@@ -0,0 +1,70 @@
<template>
<crud-layout bg="/static/page/blue-bg.png">
<z-paging
ref="pageRef"
height="100%"
:fixed="false"
v-model="pageHook.list"
:default-page-size="10"
safe-area-inset-bottom
:loading-more-enabled="true"
:show-scrollbar="false"
@query="query"
:auto-clean-list-when-reload="false"
:auto-scroll-to-top-when-reload="false"
@scroll="pageHook.scroll"
>
<view class="h-30rpx" />
<tm-sheet v-if="false" v-for="(item, index) in pageHook.list" :key="index" :margin="[0, 20]">
<view class="text-36 overflow-hidden text-nowrap text-ellipsis">
文本TmText文本TmText文本TmText文本TmText文本TmText文本TmText文本TmText文本TmText文本TmText文本TmText文本TmText文本
</view>
<view class="flex items-center">
<image src="@/static/page/时间.svg" mode="aspectFill" class="w-28rpx h-28rpx mr-1" />
<tm-text font-size="26">2025-06-06</tm-text>
</view>
<swiper class="my-1" circular :indicator-dots="false" indicator-active-color="#0779FD" indicator-color="#ffffff" :autoplay="true">
<swiper-item>
<image
class="w-full h-full"
:src="'https://stgl.pj.gov.cn/api/admin/sys-file/oss/file?fileName=3378726f7c4b40128c238c8827d6350e.jpg'"
mode="aspectFill"
/>
</swiper-item>
</swiper>
<tm-text
@item-click="doDetail(item.id)"
class="line-10"
:heightLight="['高亮显示', '正则', '邮箱']"
label="支持多文本高亮显示,比如根据正则高亮电话号码,邮箱等,点击后打电话,发邮件。"
/>
</tm-sheet>
</z-paging>
</crud-layout>
</template>
<script setup lang="ts">
import { ref } from "vue"
import { hooks, router } from "@/sheep"
import { doorApi } from "@/sheep/api"
import { onLoad } from "@dcloudio/uni-app"
onLoad(() => {
const app = getApp()
app._initTabbar()
})
const pageRef = ref<any>(null)
const pageHook = hooks.usePage(pageRef, doorApi.hardDoorPage, null, "data.records")
const query = (page: number, pagesize: number) => {
pageHook.startPage(page, pagesize, false, {})
}
// 公告详情
const doDetail = (id: string) => {
if (!id) return
router.jump("/pages/cabinet/cabinetDetail", { id }, 1)
}
</script>
+87 -36
View File
@@ -42,6 +42,13 @@
切换角色
</view>
</view>
<view class="absolute bottom-0 left-0 right-0 second-text-26 text-center my-1">
<text>联系热线:</text>
<text @click="doPhone('18367908152')">18367908152</text>
&nbsp;
<text @click="doPhone('15657370065')">15657370065</text>
</view>
</crud-layout>
</template>
@@ -54,7 +61,6 @@ import { getAppInfo } from "@@/utils/getAppInfo"
import { hooks, router, constant } from "@@/index"
import { userApi } from "@@/api"
import isDevEnv from "@/sheep/utils/isDevEnv"
import { usePayStore } from "@/sheep/stores/pay"
// import dd from "gdt-jsapi"
const state = reactive<{
@@ -76,7 +82,7 @@ const state = reactive<{
// { text: "外来人员就餐", icon: "/static/icon/service_1.png", router: "/pages/apply/foreign-list" },
// { text: "跨单位就餐", icon: "/static/icon/service_1.png", router: "/pages/apply/stride-list" },
{ text: "人脸管理", icon: "/static/icon/service_5.png", router: "/pages/human-face/list" },
// { text: "智能柜列表", icon: "/static/icon/service_5.png", router: "/pages/cabinet/cabinetList" },
{ text: "清除缓存", icon: "/static/icon/clear-storage.png", router: "" },
// { text: "意见反馈", icon: "/static/icon/service_5.png", router: "/pages/integrated/feedback/index" },
],
appInfo: "",
@@ -118,6 +124,22 @@ const storage = {
uni.removeStorageSync(STORAGE_KEYS.USER_INFO)
state.userInfo = {}
},
// 清除缓存
clearCache: () => {
uni.showModal({
title: "确定清除缓存吗?",
content: "清除缓存将自动刷新页面",
success: (res) => {
if (res.confirm) {
uni.clearStorageSync()
uni.removeStorageSync("userRole")
state.userInfo = {}
uni.reLaunch({ url: "/pages/tabbar/my" })
}
},
})
},
}
const login = {
@@ -247,19 +269,20 @@ const login = {
const scanCode = {
// 扫一扫
scan: async () => {
usePayStore().setPayData({})
try {
const decodedString = await scanCode.getScanResult()
if (decodedString) {
scanCode.processScanResult(decodedString)
}
// else {
// uni.showToast({ title: "无效的二维码", icon: "none" })
// }
} catch (error: any) {
// if (error) {
// uni.showToast({ title: error, icon: "none" })
// }
// 获取扫码结果
const scanResult = await scanCode.getScanResult()
if (!scanResult) return uni.showToast({ title: "扫码错误", icon: "none" })
// 判断扫码结果
if (scanResult.startsWith("http")) {
// 扫码结果是url链接
scanCode.processUrlScanResult(scanResult.replace("/#", ""))
} else {
// 扫码结果是base64字符串
const decodedString = scanCode.decodeBase64(scanResult)
if (!decodedString) return
scanCode.processBase64ScanResult(decodedString)
}
},
@@ -267,32 +290,33 @@ const scanCode = {
getScanResult: async (): Promise<string | undefined> => {
if (isDevEnv()) {
// 开发环境模拟扫码
// const testQrCode = "eyJpZCI6IjE4OTYxNTcyMDc2NDQwNTM1MDYiLCJuYW1lIjoi5rWL6K+V5ZWG5oi3In0=" // 线上-测试超市-收款码
// const testQrCode = "eyJpZCI6IjE5MDU4MTY3NTEwNDM0NTI5MzAiLCJuYW1lIjoi5paw5Y6/5bqc6LaF5biCIn0=" // 测试环境-邓本地-新县府超市-收款码
// const testQrCode = "eyJpZCI6IjE5MDc2ODQwNTY4NDA4NDMyNjYiLCJuYW1lIjoi5pm66IO95p+c6Ieq6JCl5ZWG5oi3MSJ9" // 测试环境-邓本地-智能柜自营商户1-收款码
const testQrCode = "eyJoYXJkRG9vcklkIjoiMTkxMTYwNDg5ODQ1NTc4OTU2OSIsImNhYmluZXRObyI6IjEifQ==" // 测试智能柜货柜二维码
// const testQrCode = "eyJpZCI6IjE4OTYxNTcyMDc2NDQwNTM1MDYiLCJuYW1lIjoi5rWL6K+V5ZWG5oi3In0=" // 线上-测试超市-收款二维码
// const testQrCode = "eyJpZCI6IjE5MDU4MTY3NTEwNDM0NTI5MzAiLCJuYW1lIjoi5paw5Y6/5bqc6LaF5biCIn0=" // 邓本地-测试环境-新县府超市收款二维码
// const testQrCode = "eyJoYXJkRG9vcklkIjoiMTkxNDI0MjgzMDkyOTk4OTYzNCIsImNhYmluZXRObyI6IjEifQ==" // 测试智能柜柜门二维码
const testQrCode = "http://192.168.101.45:8889/h5/#/pages/pay/scanPay?id=1905816751043452930&name=测试新县府超市" // 邓本地-测试环境-新县府超市收款二维码
// const testQrCode = "http://192.168.101.45:8889/h5/#/pages/pay/scanPay?hardDoorId=1914242830929989634&cabinetNo=1" // 测试智能柜柜门二维码
uni.showModal({ content: "开发环境不是浙政钉和诗画环境,扫码仅供测试,收款商家为测试商户超市" })
return scanCode.decodeBase64(testQrCode)
return testQrCode
} else if (state.appInfo == "zzd") {
// 浙政钉扫码
const res: any = await (window as any).dd.scan({ type: "all" })
return scanCode.decodeBase64(res.text)
return res.text
} else if (state.appInfo == "sh") {
// 诗画扫码
const res = await (window as any).CP2.showScanQr({ needResult: 1 })
if (res.code == 1) return scanCode.decodeBase64(res.data.qrCode)
if (res.code == 1) return res.data.qrCode
} else {
uni.showToast({ title: "当前环境未知", icon: "none" })
}
},
// 处理扫码结果
processScanResult: (decodedString: string) => {
// 处理base64扫码结果
processBase64ScanResult: (decodedString: string) => {
try {
const decodedJson = JSON.parse(decodedString)
if (decodedJson?.id && decodedJson?.name) {
usePayStore().setPayData(decodedJson)
router.jump("/pages/pay/scanPay")
if (decodedJson.id) {
router.jump("/pages/pay/scanPay", { id: decodedJson.id })
} else if (decodedJson?.hardDoorId && decodedJson?.cabinetNo) {
router.jump("/pages/cabinet/buy", { hardDoorId: decodedJson.hardDoorId, cabinetNo: decodedJson.cabinetNo })
} else {
@@ -303,6 +327,23 @@ const scanCode = {
}
},
// 处理url扫码结果
processUrlScanResult: (url: string) => {
const searchParams = new URL(url).searchParams
const id = searchParams.get("id")
const name = searchParams.get("name")
const hardDoorId = searchParams.get("hardDoorId")
const cabinetNo = searchParams.get("cabinetNo")
if (id) {
router.jump("/pages/pay/scanPay", { id, name })
} else if (hardDoorId && cabinetNo) {
router.jump("/pages/cabinet/buy", { hardDoorId, cabinetNo })
} else {
uni.showToast({ title: "无效的二维码", icon: "none" })
}
},
// 解码base64
decodeBase64: (base64String: string): string | undefined => {
try {
@@ -328,17 +369,17 @@ const scanCode = {
const onTabLogin = () => (isDevEnv() ? router.jump("/pages/test/login") : login.checkAppInfo())
const onTabMenu = async (item: any, index: number) => {
if (index == state.menuList.length - 1) {
router.jump(item.router)
return
}
const isLogin = await hooks.useCheckLogin()
if (isLogin) {
if (item.text === "扫一扫") {
await scanCode.scan()
} else {
router.jump(item.router)
switch (item.text) {
case "扫一扫":
await scanCode.scan()
break
case "清除缓存":
storage.clearCache()
break
default:
router.jump(item.router)
}
}
}
@@ -378,12 +419,22 @@ onLoad(async () => {
// 获取应用信息
state.appInfo = await getAppInfo()
await userApi.userRole()
// 获取存储中的用户信息
storage.getUserInfo()
})
onShow(() => {
// 获取存储中的用户信息
storage.getUserInfo()
})
// 联系客服
const doPhone = (phone: string) => {
hooks.useMakePhoneCall(phone)
}
</script>
<style lang="scss" scoped>
+36 -43
View File
@@ -3,11 +3,12 @@ import { ref, reactive } from "vue"
import { onLoad, onShow } from "@dcloudio/uni-app"
import { hooks, router } from "@@/index"
import { orderApi, payApi } from "@@/api"
import { orderApi } from "@@/api"
import { filePath } from "@@/utils/file"
import zTabs from "@@/components/other/z-tabs/z-tabs.vue"
import getLaunchParam from "@/sheep/utils/getLaunchParam"
const data = {
tabs: [
@@ -44,9 +45,11 @@ const doTab = (e: any) => {
const pageRef = ref<any>(null)
const pageHook = hooks.usePage(
pageRef,
new URL(window.location.href).searchParams.get("launchParam") == "canteen"
getLaunchParam() == "canteen"
? orderApi.caneenPage
: new URL(window.location.href).searchParams.get("launchParam") == "selfMerchant"
: getLaunchParam() == "selfMerchant"
? orderApi.supPage
: getLaunchParam() == "coopMerchant"
? orderApi.supPage
: async () => [],
null,
@@ -54,7 +57,6 @@ const pageHook = hooks.usePage(
)
const query = (page: number, pagesize: number) => {
const isLogin = hooks.useStaticCheckLogin()
console.log(isLogin, "isLogin")
if (!isLogin) return
pageHook.startPage(page, pagesize, false, state.pa)
@@ -62,7 +64,7 @@ const query = (page: number, pagesize: number) => {
// 查看订单和核销码
const doToDetail = (v: any) => {
// router.jump("/pages/order/detail", { id: v.id })
router.jump("/pages/order/detail", { id: v.id })
}
const doAppraise = () => {}
@@ -95,10 +97,10 @@ const doRefund = (v: any) => {
</view>
</template>
<view class="h-20rpx" />
<view class="flex-col justify-center card p-3 m-b-20rpx" v-for="(v, i) in pageHook.list" :key="i" @tap="doToDetail(v)">
<view class="flex-col justify-center card p-3 m-b-20rpx" v-for="(v, i) in pageHook.list" :key="i">
<view class="flex-row items-center">
<image class="w-80rpx h-80rpx rounded-8rpx" :src="filePath(v.logoPic)" mode="aspectFill" />
<view class="flex-1 flex-col m-l-20rpx">
<image class="w-110rpx h-110rpx rounded-8rpx" :src="filePath(v.logoPic)" mode="aspectFill" />
<view class="flex-1 m-l-20rpx">
<view class="flex-row items-center justify-between">
<view class="flex-row items-center">
<view class="main-text-28">{{ v.merchantName }}</view>
@@ -108,51 +110,42 @@ const doRefund = (v: any) => {
<tm-tag v-if="v.orderStatus == 5" color="success" size="xs">已支付</tm-tag>
<tm-tag v-if="v.orderStatus == 10" color="error" size="xs">售后</tm-tag>
<tm-tag v-if="v.orderStatus == 20" size="xs">已核销</tm-tag>
<tm-tag v-if="v.orderStatus == 30" color="info" size="xs">已取消(智能柜)</tm-tag>
</view>
<view class="flex-row items-center justify-between m-t-5rpx">
<view class="second-text-20">
<text>下单时间</text>
<text class="m-l-10rpx">
{{ hooks.useTime(v.createTime, "{y}-{m}-{d} {h}:{i}:{s}") }}
</text>
<text class="m-l-10rpx">{{ hooks.useTime(v.createTime, "{y}-{m}-{d} {h}:{i}:{s}") }}</text>
</view>
<view class="second-text-22">{{ hooks.useEnum("hardwareRefundStatusEnum", v.refundStatus) }}</view>
</view>
<view class="flex-row items-center justify-between m-t-5rpx">
<view class="sub-text-24">
<text v-if="v.payType == '9'">{{ v.productDesc }}</text>
</view>
<view class="main-text-30 color-red! text-right">¥ {{ hooks.useMoney(v.totalPrice) }}</view>
</view>
</view>
</view>
<view class="relative h-0rpx m-t-[20rpx] flex justify-end items-center">
<!-- <view class="absolute top-0 right-0 bottom-0 left-0 h-180rpx">
<scroll-view scroll-x class="flex-row-center whitespace-nowrap">
<view class="flex-row items-center">
<view
class="inline-flex! flex-col justify-center h-180rpx m-r-20rpx"
v-for="(pV, pI) in v.carList"
:key="pI"
@tap.stop="
router.jump('/pages/merchant/product-detail', {
id: pV.productId,
})
"
>
<image class="w-160rpx h-120rpx rounded-8rpx" :src="filePath(pV.productPic)" mode="aspectFill" />
<view class="w-160rpx m-t-10rpx sub-text-24 show-line text-center">
{{ pV.productName }}
</view>
</view>
<view class="inline-flex! h-180rpx">
<view class="w-160rpx h-full" />
</view>
<view class="flex items-center ml-[120rpx]">
<scroll-view v-if="['5', '20'].includes(v.orderStatus) && v.orderType == 2" scroll-x class="flex-row-center whitespace-nowrap">
<view class="flex-row items-center">
<view class="inline-flex! flex-col items-center m-r-20rpx" v-for="(pV, pI) in v.carList" :key="pI">
<image class="w-60rpx h-60rpx rounded-8rpx" :src="filePath(pV.productPic)" mode="aspectFill" />
<view class="w-80rpx m-t-10rpx sub-text-24 show-line text-center">{{ pV.productName }}</view>
</view>
</scroll-view>
</view> -->
<!-- <view class="absolute top-0 right-0 bottom-0 z-10 flex-col items-end w-160rpx p-x-20rpx bg-white bg-opacity-95"> -->
<view v-if="v.carList?.length" class="m-t-2rpx m-r-20rpx second-text-26">共 {{ v.carList.length }} 件</view>
<view class="main-text-30 color-red!">¥ {{ hooks.useMoney(v.totalPrice) }}</view>
<!-- </view> -->
</view>
<view v-if="['5', '10'].includes(v.orderStatus)" class="flex-row items-center justify-end p-t-20rpx">
<!-- <view v-if="v.orderStatus == 5 && v.orderType == 2" class="botder_btn" @tap.stop="doRefund(v)">退款</view> -->
<view v-if="v.orderStatus == 5 && v.orderType == 2" class="m-l-20rpx botder_btn" @tap.stop="doToDetail(v)">核销码</view>
</view>
</scroll-view>
<view
v-if="v.carList?.length && ['5', '20'].includes(v.orderStatus) && v.orderType == 2"
class="w-200rpx m-x-10rpx second-text-26"
>
共 {{ v.carList.length }} 件
</view>
<view v-if="['5', '10'].includes(v.orderStatus)" class="w-500rpx flex-row items-center justify-end">
<!-- <view v-if="v.orderStatus == 5 && v.orderType == 2" class="botder_btn" @tap.stop="doRefund(v)">退款</view> -->
<view v-if="v.orderStatus == 5 && v.orderType == 2" class="m-l-20rpx botder_btn" @tap.stop="doToDetail(v)">核销码</view>
</view>
</view>
</view>
</z-paging>
+31
View File
@@ -0,0 +1,31 @@
<template>
<view class="flex-row h-100rpx bg-#f6f8fa px-10rpx py-10rpx rounded-16rpx">
<view
class="w-50% flex-row-center color-#818898 font-size-28rpx! rounded-16rpx"
:style="{ color: index == cur ? '#fff' : '#818898', backgroundColor: index == cur ? '#00a624' : '#f6f8fa' }"
v-for="(item, index) in tablist"
@click="changeTab(index)"
>
{{ item.name }}
</view>
</view>
</template>
<script setup lang="ts">
import { reactive, ref } from "vue"
import { onLoad, onShow } from "@dcloudio/uni-app"
let cur = ref(0)
let tablist = ref([
{
name: "我的订单",
},
{
name: "历史订单",
},
])
onLoad(() => {})
const changeTab = (index: number) => {
cur.value = index
}
</script>
+49
View File
@@ -0,0 +1,49 @@
<template>
<crud-layout mainIsScroll bg="/static/page/blue-bg.png">
<view class="h-30rpx" />
<tm-sheet :margin="[0]">
<view class="flex-row items-center justify-center flex-wrap">
<view class="w-half flex justify-center py-2 rounded-1">
<view class="w-half text-center rounded-1 active:bg-#e8e8e8 duration-200" @click="router.jump('/pages/visitor/apply')">
<image class="w-80 h-80 px-2 pt-2" src="@/static/page/货柜详情.svg" />
<tm-text font-size="32">访客申请</tm-text>
</view>
</view>
<view class="w-half flex justify-center py-2 rounded-1">
<view class="w-half text-center rounded-1 active:bg-#e8e8e8 duration-200" @click="router.jump('/pages/visitor/applyRecord')">
<image class="w-80 h-80 px-2 pt-2" src="@/static/page/货柜详情.svg" />
<tm-text font-size="32">申请记录</tm-text>
</view>
</view>
<view class="w-half flex justify-center py-2 rounded-1">
<view class="w-half text-center rounded-1 active:bg-#e8e8e8 duration-200" @click="router.jump('/pages/visitor/invitation')">
<image class="w-80 h-80 px-2 pt-2" src="@/static/page/货柜详情.svg" />
<tm-text font-size="32">访客邀约</tm-text>
</view>
</view>
<view class="w-half flex justify-center py-2 rounded-1">
<view class="w-half text-center rounded-1 active:bg-#e8e8e8 duration-200" @click="router.jump('/pages/visitor/invitationRecord')">
<image class="w-80 h-80 px-2 pt-2" src="@/static/page/货柜详情.svg" />
<tm-text font-size="32">邀约记录</tm-text>
</view>
</view>
<view class="w-half flex justify-center py-2 rounded-1">
<view class="w-half text-center rounded-1 active:bg-#e8e8e8 duration-200">
<image class="w-80 h-80 px-2 pt-2" src="@/static/page/货柜详情.svg" />
<tm-text font-size="32">核销</tm-text>
</view>
</view>
</view>
</tm-sheet>
</crud-layout>
</template>
<script setup lang="ts">
import { onLoad } from "@dcloudio/uni-app"
import { router } from "@/sheep"
onLoad(() => {
const app = getApp()
app._initTabbar()
})
</script>
+1 -1
View File
@@ -30,7 +30,7 @@ const doSubmit = async () => {
const userInfoKey = constant.storageConstant.USERINFO
uni.removeStorageSync(tokenKey)
uni.showLoading({ title: "登录中...", mask: true })
const res = await userApi.login({
const res: any = await userApi.login({
...applyForm,
grant_type: "password",
scope: "server",
+115
View File
@@ -0,0 +1,115 @@
<template>
<crud-layout bg="/static/page/blue-bg.png">
<z-paging
ref="pageRef"
height="100%"
:fixed="false"
v-model="pageHook.list"
:default-page-size="10"
safe-area-inset-bottom
:loading-more-enabled="true"
:show-scrollbar="false"
@query="query"
:auto-clean-list-when-reload="false"
:auto-scroll-to-top-when-reload="false"
@scroll="pageHook.scroll"
>
<view class="h-20rpx" />
<view class="flex-row card p-20rpx m-b-20rpx" v-for="(v, i) in pageHook.list" :key="i" @tap="toDetail(v)">
<image class="w-180rpx h-180rpx rounded-12rpx my-auto" :src="filePath(v.logoPic)" mode="aspectFill" />
<view class="flex-1 flex-col m-l-20rpx">
<view class="sub-text-34">
<text class="mr-2">{{ v.name }}</text>
<!-- <tm-tag v-if="v.supType == '10' && Number(v.mchCount) > 0" size="xs" skin="thin">共{{ v.mchCount }}家</tm-tag> -->
</view>
<view class="m-t-10rpx">
<view class="flex justify-between items-center">
<view>
<view v-if="v.phone" class="flex items-center">
<image class="w-24rpx h-24rpx" src="@/static/page/phone.svg" />
<view class="second-text-28 ml-1">{{ v.phone }}</view>
</view>
</view>
<tm-tag size="xs">{{ v.deptName.length > 5 ? v.deptName.substring(0, 5) + "..." : v.deptName }}</tm-tag>
</view>
<view v-if="v.addressDes" class="second-text-28">
<image class="w-24rpx h-24rpx" src="@/static/page/address.svg" />
<text class="ml-1">地址:</text>
<text class="m-l-10rpx">{{ v.addressDes }}</text>
</view>
</view>
</view>
</view>
<tm-modal
v-model:show="state.show"
:overlayClick="false"
title="注意"
position="bottom"
:showCancel="true"
cancelText="取消"
confirmText="继续访问"
@confirm="thirdAppJump()"
@cancel="state.show = false"
>
<tm-text font-size="30" color="#999999">您即将离开智慧后勤应用并跳转到第三方应用,请注意个人隐私和账号财产安全</tm-text>
</tm-modal>
</z-paging>
</crud-layout>
</template>
<script setup lang="ts">
import { ref, reactive } from "vue"
import { onLoad, onShow } from "@dcloudio/uni-app"
import { hooks, router } from "@@/index"
import { merchantApi } from "@@/api"
import { filePath } from "@@/utils/file"
const params = reactive<any>({
type: "4",
})
const state = reactive({
show: false,
})
onLoad(() => {
const app = getApp()
app._initTabbar()
})
onShow(() => {
if (pageRef.value) {
pageRef.value.reload(false)
}
})
const pageRef = ref<any>(null)
const pageHook = hooks.usePage(pageRef, merchantApi.page, null, "data.records")
const query = (page: number, pagesize: number) => {
pageHook.startPage(page, pagesize, false, params)
}
const toDetail = async (v: any) => {
const isLogin = await hooks.useCheckLogin()
if (isLogin) {
state.show = true
}
}
// 确认或拒绝协议
const thirdAppJump = async () => {
try {
uni.showLoading({ title: "跳转中", mask: true })
const res: any = await merchantApi.lbLogin()
if (res.code == 0) {
state.show = false
if (!res.data) return uni.showToast({ title: "url错误", icon: "none" })
window.location.href = res.data
}
} catch (error: any) {
uni.showToast({ title: error, icon: "none" })
} finally {
uni.hideLoading()
}
}
</script>
+52 -19
View File
@@ -4,7 +4,7 @@
<view class="main-text-40 mb-2">请选择您的身份</view>
</view>
<view class="px-6 my-20">
<view class="px-6">
<view
class="card mb-6 overflow-hidden relative border-8 border-solid border-white duration-200"
:class="{ 'border-8 border-solid border-blue!': userRole === 'user' }"
@@ -19,7 +19,7 @@
</view>
<view
class="card overflow-hidden relative border-8 border-solid border-white duration-200"
class="card mb-6 overflow-hidden relative border-8 border-solid border-white duration-200"
:class="{ 'border-8 border-solid border-blue!': userRole === 'merchant' }"
@click="selectRole('merchant')"
>
@@ -30,6 +30,19 @@
<view class="main-text-32 mb-1">我是商户</view>
</view>
</view>
<view
class="card overflow-hidden relative border-8 border-solid border-white duration-200"
:class="{ 'border-8 border-solid border-blue!': userRole === 'doorAdmin' }"
@click="selectRole('doorAdmin')"
>
<view class="flex-row items-center p-6">
<view class="w-64 h-64 rounded-full flex-col-center mr-8">
<image src="@/static/page/doorAdminRole.svg" />
</view>
<view class="main-text-32 mb-1">我是智能柜管理员</view>
</view>
</view>
</view>
<view class="flex-row-center px-10 mt-auto pb-10 font-bold">
@@ -39,32 +52,52 @@
</template>
<script setup lang="ts">
import { userApi } from "@/sheep/api"
import { ref } from "vue"
import { userApi } from "@/sheep/api"
import getLaunchParam from "@/sheep/utils/getLaunchParam"
const userRole = ref("user")
const selectRole = (role: "user" | "merchant") => (userRole.value = role)
const selectRole = (role: "user" | "merchant" | "doorAdmin") => (userRole.value = role)
// 确认选择
const confirmRole = async () => {
if (userRole.value === "user") {
uni.setStorageSync("userRole", userRole.value)
uni.reLaunch({ url: "/pages/tabbar/coopMerchant" })
return
}
if (userRole.value === "merchant") {
uni.showLoading({ title: "正在验证身份", mask: true })
const res = await userApi.isMerchant().finally(() => uni.hideLoading())
if (res.code == 0) {
if (res.data) {
uni.setStorageSync("userRole", userRole.value)
uni.reLaunch({ url: "/pages/tabbar/individualOrder" })
return
switch (userRole.value) {
case "user":
uni.setStorageSync("userRole", userRole.value)
if (getLaunchParam() === "selfMerchant") return uni.reLaunch({ url: "/pages/tabbar/selfMerchant" })
if (getLaunchParam() === "coopMerchant") return uni.reLaunch({ url: "/pages/tabbar/coopMerchant" })
break
case "merchant":
uni.showLoading({ title: "正在验证身份", mask: true })
const res1: any = await userApi.userRole().finally(() => uni.hideLoading())
if (res1.code == 0) {
if (res1.data.isMch) {
uni.setStorageSync("userRole", userRole.value)
uni.reLaunch({ url: "/pages/tabbar/individualOrder" })
} else {
uni.showToast({ title: "您不是商户", icon: "none" })
}
} else {
uni.showToast({ title: "您不是商户", icon: "none" })
uni.showToast({ title: "身份验证失败", icon: "none" })
}
}
break
case "doorAdmin":
uni.showLoading({ title: "正在验证身份", mask: true })
const res2: any = await userApi.userRole().finally(() => uni.hideLoading())
if (res2.code == 0) {
if (res2.data.isHardDoorAdmin) {
uni.setStorageSync("userRole", userRole.value)
uni.reLaunch({ url: "/pages/tabbar/cabinet" })
} else {
uni.showToast({ title: "您不是智能柜管理员", icon: "none" })
}
} else {
uni.showToast({ title: "身份验证失败", icon: "none" })
}
break
default:
uni.showToast({ title: "请选择您的身份", icon: "none" })
}
}
</script>
+174
View File
@@ -0,0 +1,174 @@
<template>
<crud-layout mainIsScroll bg="/static/page/blue-bg.png">
<view class="h-30rpx" />
<tm-sheet margin="[0, 20]">
<view class="mx-auto text-center text-lg">访客申请</view>
<tm-text color="#999999" class="bg-#FFF7E6 p-1 pl-2 my-1">!访客需要填写以下验证信息</tm-text>
<tm-form @submit="onsubmit" v-model="form" :rules="rules">
<tm-form-item name="username" label="您的姓名">
<tm-input color="transparent" v-model="form.username" placeholder="姓名" />
</tm-form-item>
<tm-form-item name="username" label="联系方式">
<tm-input color="transparent" v-model="form.username" placeholder="联系方式" />
</tm-form-item>
<tm-form-item name="username" label="公司名称">
<tm-input color="transparent" v-model="form.username" placeholder="公司名称" />
</tm-form-item>
<tm-form-item name="pingtai" label="拜访原因">
<tm-picker
v-model="form.pingtai"
v-model:modelStr="_pingtaistr"
rangText="name"
:list="[
{ id: 1, name: '1111' },
{ id: 2, name: '2222' },
{ id: 3, name: '3333' },
]"
>
<tm-input :modelValue="_pingtaistr" placeholder="请选择拜访原因" style="pointer-events: none" disabled color="transparent">
<template v-slot:rightIcon>
<tm-icon name="arrow-right-s-line"></tm-icon>
</template>
</tm-input>
</tm-picker>
</tm-form-item>
<tm-form-item name="username" label="随行人员">
<view class="flex items-center" v-for="(v, i) in form.entourage" :key="i">
<tm-input color="transparent" v-model="form.entourage[i].username" placeholder="姓名" />
&nbsp;
<tm-input color="transparent" v-model="form.entourage[i].phone" placeholder="手机号" />
&nbsp;
<view class="w-80rpx">
<tm-button v-if="i > 0 && i < 6" color="error" size="s" btnIcon width="40" rounded @click="removeEntourage(i)">—</tm-button>
</view>
</view>
<tm-button skin="thin" block size="s" class="my-2" @click="addEntourage">添加</tm-button>
</tm-form-item>
<tm-form-item name="username" label="车牌号">
<view v-for="(v, i) in form.carPlate" :key="i" class="flex items-center">
<tm-input color="transparent" v-model="form.carPlate[i]" :placeholder="`车牌号${i + 1}`" />
&nbsp;
<view class="w-80rpx">
<tm-button v-if="i > 0 && i < 6" color="error" size="s" btnIcon width="40" rounded @click="removeCarPlate(i)">—</tm-button>
</view>
</view>
<tm-button skin="thin" block size="s" class="my-2" @click="addCarPlate">添加</tm-button>
</tm-form-item>
<tm-form-item name="pingtai" label="到访单位">
<tm-picker
v-model="form.pingtai"
v-model:modelStr="_pingtaistr"
rangText="name"
:list="[
{ id: 1, name: '1111' },
{ id: 2, name: '2222' },
{ id: 3, name: '3333' },
]"
>
<tm-input :modelValue="_pingtaistr" placeholder="请选择到访单位" style="pointer-events: none" disabled color="transparent">
<template v-slot:rightIcon>
<tm-icon name="arrow-right-s-line"></tm-icon>
</template>
</tm-input>
</tm-picker>
</tm-form-item>
<tm-form-item name="username" label="接待人">
<tm-input color="transparent" v-model="form.username" placeholder="接待人" />
</tm-form-item>
<tm-form-item name="time" label="到访时间">
<tm-picker-date v-model="form.time" v-model:modelStr="_timestr" type="minute" start="2020-01-01 00:00" end="2080-01-01 23:59">
<tm-input :modelValue="form.time" placeholder="请选择到访时间" style="pointer-events: none" disabled color="transparent">
<template v-slot:rightIcon>
<tm-icon name="arrow-right-s-line"></tm-icon>
</template>
</tm-input>
</tm-picker-date>
</tm-form-item>
<tm-form-item name="textarea" label="备注">
<tm-input v-model="form.textarea" :maxlength="100" placeholder="请输入" type="textarea" show-char-count color="transparent">
</tm-input>
</tm-form-item>
<hr class="mb-4" />
<tm-button form-type="submit" block>提交</tm-button>
</tm-form>
</tm-sheet>
<view class="h-30rpx" />
</crud-layout>
</template>
<script setup lang="ts">
import { reactive, ref } from "vue"
const form = reactive({
username: "",
price: "",
checkbox: [],
radio: "",
time: "2024-6-5",
pingtai: [],
store: 0,
score: 0,
textarea: "",
entourage: [
{
username: "",
phone: "",
},
],
carPlate: [""],
})
const _timestr = ref(form.time)
const _pingtaistr = ref("")
const rules: Record<string, TM.FORM_RULE[]> = {
username: [{ required: true, message: "姓名2到5个字符", rule: /^.{2,5}$/ }],
address: [
{ required: true, message: "地址不能为空" },
{ required: true, message: "长度要小于3", max: 2 },
],
price: [{ required: true, message: "价格要大于等于99", type: "number", min: 99 }],
checkbox: [{ required: true }],
radio: [{ required: true }],
time: [{ required: true, type: "date" }],
pingtai: [{ required: true }],
store: [{ required: true, min: 1, max: 100, message: "介于1-100之间" }],
score: [{ required: true, min: 5, max: 5, message: "必须打5分哦" }],
textarea: [{ required: true, max: 100, message: "请输入内容" }],
}
// 添加随从
const addEntourage = () => {
if (form.entourage.length > 5) return uni.showToast({ title: "最多添加6个随从", icon: "none" })
form.entourage.push({
username: "",
phone: "",
})
}
// 移除随从
const removeEntourage = (index: number) => {
form.entourage.splice(index, 1)
}
// 添加车牌号
const addCarPlate = () => {
if (form.carPlate.length > 3) return uni.showToast({ title: "最多添加4个车牌", icon: "none" })
form.carPlate.push("")
}
// 移除车牌号
const removeCarPlate = (index: number) => {
form.carPlate.splice(index, 1)
}
// 表单提交
const onsubmit = (evt: TM.FORM_SUBMIT_RESULT) => {
console.log("校验结果:", evt)
if (!evt.isPass) return
uni.showModal({ title: "提示", content: "确认提交吗?", confirmColor: "#0094ff" })
}
</script>
+107
View File
@@ -0,0 +1,107 @@
<template>
<crud-layout bg="/static/page/blue-bg.png">
<z-paging
ref="pageRef"
height="100%"
:fixed="false"
v-model="pageHook.list"
:default-page-size="10"
safe-area-inset-bottom
:loading-more-enabled="true"
:show-scrollbar="false"
@query="query"
:auto-clean-list-when-reload="false"
:auto-scroll-to-top-when-reload="false"
@scroll="pageHook.scroll"
>
<template #top>
<view class="h-30rpx" />
<view class="bg-white rounded-16rpx px-20rpx">
<z-tabs :list="tabs" @change="doTab" />
</view>
</template>
<view class="h-20rpx" />
<view class="flex-col justify-center card p-3 m-b-20rpx" v-for="(v, i) in pageHook.list" :key="i">
<view class="flex-row items-center">
<image class="w-110rpx h-110rpx rounded-8rpx" :src="filePath(v.logoPic)" mode="aspectFill" />
<view class="flex-1 m-l-20rpx">
<view class="flex-row items-center justify-between">
<view class="flex-row items-center">
<view class="main-text-28">{{ v.merchantName }}</view>
<!-- <view class="m-l-15rpx color-#999 font-size-26rpx! iconfont icon-youjiantou" /> -->
</view>
<tm-tag v-if="v.orderStatus == 1" color="info" size="xs">未支付</tm-tag>
<tm-tag v-if="v.orderStatus == 5" color="success" size="xs">已支付</tm-tag>
<tm-tag v-if="v.orderStatus == 10" color="error" size="xs">售后</tm-tag>
<tm-tag v-if="v.orderStatus == 20" size="xs">已核销</tm-tag>
<tm-tag v-if="v.orderStatus == 30" color="info" size="xs">已取消(智能柜)</tm-tag>
</view>
<view class="flex-row items-center justify-between m-t-5rpx">
<view class="second-text-20">
<text>下单时间</text>
<text class="m-l-10rpx">{{ hooks.useTime(v.createTime, "{y}-{m}-{d} {h}:{i}:{s}") }}</text>
</view>
<view class="second-text-22">{{ hooks.useEnum("hardwareRefundStatusEnum", v.refundStatus) }}</view>
</view>
<view class="flex-row items-center justify-between m-t-5rpx">
<view class="sub-text-24">
<text v-if="v.payType == '9'">{{ v.productDesc }}</text>
</view>
<view class="main-text-30 color-red! text-right">¥ {{ hooks.useMoney(v.totalPrice) }}</view>
</view>
</view>
</view>
<view class="flex items-center ml-[120rpx]">
<view v-if="['5', '10'].includes(v.orderStatus)" class="w-500rpx flex-row items-center justify-end">
<!-- <view v-if="v.orderStatus == 5 && v.orderType == 2" class="botder_btn" @tap.stop="doRefund(v)">退款</view> -->
<view v-if="v.orderStatus == 5 && v.orderType == 2" class="m-l-20rpx botder_btn">核销码</view>
</view>
</view>
</view>
</z-paging>
</crud-layout>
</template>
<script setup lang="ts">
import { ref, reactive } from "vue"
import { onShow } from "@dcloudio/uni-app"
import { hooks } from "@@/index"
import { filePath } from "@@/utils/file"
import zTabs from "@@/components/other/z-tabs/z-tabs.vue"
const tabs = [
{ id: null, name: "全部", disabled: false },
{ id: 1, name: "待核销", disabled: false },
{ id: 5, name: "待到访", disabled: false },
{ id: 10, name: "已到访", disabled: false },
{ id: 20, name: "已取消", disabled: false },
]
const state = reactive<any>({
pa: {
orderStatus: tabs[0].id,
},
})
onShow(async () => {
const isLogin = await hooks.useCheckLogin()
if (!isLogin) return
if (pageRef.value) {
pageRef.value.reload(false)
}
})
const doTab = (e: any) => {
const target = tabs[e]
state.pa.orderStatus = target.id
pageRef.value.reload(true)
}
const pageRef = ref<any>(null)
const pageHook = hooks.usePage(pageRef, async () => [], null, "data.records")
const query = (page: number, pagesize: number) => {
const isLogin = hooks.useStaticCheckLogin()
if (!isLogin) return
pageHook.startPage(page, pagesize, false, state.pa)
}
</script>
+121
View File
@@ -0,0 +1,121 @@
<template>
<crud-layout mainIsScroll bg="/static/page/blue-bg.png">
<view class="h-30rpx" />
<tm-sheet margin="[0, 20]">
<view class="mx-auto text-center text-lg">访客邀约</view>
<tm-form @submit="onsubmit" v-model="form" :rules="rules">
<tm-form-item name="username" label="访客姓名">
<tm-input color="transparent" v-model="form.username" placeholder="访客姓名" />
</tm-form-item>
<tm-form-item name="username" label="访客手机号">
<tm-input color="transparent" v-model="form.username" placeholder="访客手机号" />
</tm-form-item>
<tm-form-item name="username" label="来访公司名称">
<tm-input color="transparent" v-model="form.username" placeholder="来访公司名称" />
</tm-form-item>
<tm-form-item name="pingtai" label="拜访原因">
<tm-picker
v-model="form.pingtai"
v-model:modelStr="_pingtaistr"
rangText="name"
:list="[
{ id: 1, name: '1111' },
{ id: 2, name: '2222' },
{ id: 3, name: '3333' },
]"
>
<tm-input :modelValue="_pingtaistr" placeholder="请选择拜访原因" style="pointer-events: none" disabled color="transparent">
<template v-slot:rightIcon>
<tm-icon name="arrow-right-s-line"></tm-icon>
</template>
</tm-input>
</tm-picker>
</tm-form-item>
<tm-form-item name="time" label="到访时间">
<tm-picker-date v-model="form.time" v-model:modelStr="_timestr" type="minute" start="2020-01-01 00:00" end="2080-01-01 23:59">
<tm-input :modelValue="form.time" placeholder="请选择到访时间" style="pointer-events: none" disabled color="transparent">
<template v-slot:rightIcon>
<tm-icon name="arrow-right-s-line"></tm-icon>
</template>
</tm-input>
</tm-picker-date>
</tm-form-item>
<tm-form-item name="pingtai" label="拜访部门">
<tm-picker
v-model="form.pingtai"
v-model:modelStr="_pingtaistr"
rangText="name"
:list="[
{ id: 1, name: '1111' },
{ id: 2, name: '2222' },
{ id: 3, name: '3333' },
]"
>
<tm-input :modelValue="_pingtaistr" placeholder="请选择拜访部门" style="pointer-events: none" disabled color="transparent">
<template v-slot:rightIcon>
<tm-icon name="arrow-right-s-line"></tm-icon>
</template>
</tm-input>
</tm-picker>
</tm-form-item>
<tm-form-item name="username" label="随行人员">
<view class="flex">
<tm-input color="transparent" v-model="form.username" placeholder="姓名" />
&nbsp;
<tm-input color="transparent" v-model="form.username" placeholder="手机号" />
</view>
<view class="flex">
<tm-input color="transparent" v-model="form.username" placeholder="姓名" />
&nbsp;
<tm-input color="transparent" v-model="form.username" placeholder="手机号" />
</view>
</tm-form-item>
<tm-button form-type="submit" block>提交</tm-button>
</tm-form>
</tm-sheet>
</crud-layout>
</template>
<script setup lang="ts">
import { ref } from "vue"
const form = ref({
username: "",
price: "",
checkbox: [] as string[],
radio: "",
time: "2024-6-5",
pingtai: [] as string[],
store: 0,
score: 0,
textarea: "",
})
const _timestr = ref(form.value.time)
const _pingtaistr = ref("")
const rules: Record<string, TM.FORM_RULE[]> = {
username: [{ required: true, message: "姓名2到5个字符", rule: /^.{2,5}$/ }],
address: [
{ required: true, message: "地址不能为空" },
{ required: true, message: "长度要小于3", max: 2 },
],
price: [{ required: true, message: "价格要大于等于99", type: "number", min: 99 }],
checkbox: [{ required: true }],
radio: [{ required: true }],
time: [{ required: true, type: "date" }],
pingtai: [{ required: true }],
store: [{ required: true, min: 1, max: 100, message: "介于1-100之间" }],
score: [{ required: true, min: 5, max: 5, message: "必须打5分哦" }],
textarea: [{ required: true, max: 100, message: "请输入内容" }],
}
// 表单提交
const onsubmit = (evt: TM.FORM_SUBMIT_RESULT) => {
console.log("校验结果:", evt)
if (!evt.isPass) return
uni.showModal({ title: "提示", content: "确认提交吗?", confirmColor: "#0094ff" })
}
</script>
+106
View File
@@ -0,0 +1,106 @@
<template>
<crud-layout bg="/static/page/blue-bg.png">
<z-paging
ref="pageRef"
height="100%"
:fixed="false"
v-model="pageHook.list"
:default-page-size="10"
safe-area-inset-bottom
:loading-more-enabled="true"
:show-scrollbar="false"
@query="query"
:auto-clean-list-when-reload="false"
:auto-scroll-to-top-when-reload="false"
@scroll="pageHook.scroll"
>
<template #top>
<view class="h-30rpx" />
<view class="bg-white rounded-16rpx px-20rpx">
<z-tabs :list="tabs" @change="doTab" />
</view>
</template>
<view class="h-20rpx" />
<view class="flex-col justify-center card p-3 m-b-20rpx" v-for="(v, i) in pageHook.list" :key="i">
<view class="flex-row items-center">
<image class="w-110rpx h-110rpx rounded-8rpx" :src="filePath(v.logoPic)" mode="aspectFill" />
<view class="flex-1 m-l-20rpx">
<view class="flex-row items-center justify-between">
<view class="flex-row items-center">
<view class="main-text-28">{{ v.merchantName }}</view>
<!-- <view class="m-l-15rpx color-#999 font-size-26rpx! iconfont icon-youjiantou" /> -->
</view>
<tm-tag v-if="v.orderStatus == 1" color="info" size="xs">未支付</tm-tag>
<tm-tag v-if="v.orderStatus == 5" color="success" size="xs">已支付</tm-tag>
<tm-tag v-if="v.orderStatus == 10" color="error" size="xs">售后</tm-tag>
<tm-tag v-if="v.orderStatus == 20" size="xs">已核销</tm-tag>
<tm-tag v-if="v.orderStatus == 30" color="info" size="xs">已取消(智能柜)</tm-tag>
</view>
<view class="flex-row items-center justify-between m-t-5rpx">
<view class="second-text-20">
<text>下单时间</text>
<text class="m-l-10rpx">{{ hooks.useTime(v.createTime, "{y}-{m}-{d} {h}:{i}:{s}") }}</text>
</view>
<view class="second-text-22">{{ hooks.useEnum("hardwareRefundStatusEnum", v.refundStatus) }}</view>
</view>
<view class="flex-row items-center justify-between m-t-5rpx">
<view class="sub-text-24">
<text v-if="v.payType == '9'">{{ v.productDesc }}</text>
</view>
<view class="main-text-30 color-red! text-right">¥ {{ hooks.useMoney(v.totalPrice) }}</view>
</view>
</view>
</view>
<view class="flex items-center ml-[120rpx]">
<view v-if="['5', '10'].includes(v.orderStatus)" class="w-500rpx flex-row items-center justify-end">
<!-- <view v-if="v.orderStatus == 5 && v.orderType == 2" class="botder_btn" @tap.stop="doRefund(v)">退款</view> -->
<view v-if="v.orderStatus == 5 && v.orderType == 2" class="m-l-20rpx botder_btn">核销码</view>
</view>
</view>
</view>
</z-paging>
</crud-layout>
</template>
<script setup lang="ts">
import { ref, reactive } from "vue"
import { onShow } from "@dcloudio/uni-app"
import { hooks } from "@@/index"
import { filePath } from "@@/utils/file"
import zTabs from "@@/components/other/z-tabs/z-tabs.vue"
const tabs = [
{ id: null, name: "全部", disabled: false },
{ id: 1, name: "待审核", disabled: false },
{ id: 5, name: "待到访", disabled: false },
{ id: 20, name: "已取消", disabled: false },
]
const state = reactive<any>({
pa: {
orderStatus: tabs[0].id,
},
})
onShow(async () => {
const isLogin = await hooks.useCheckLogin()
if (!isLogin) return
if (pageRef.value) {
pageRef.value.reload(false)
}
})
const doTab = (e: any) => {
const target = tabs[e]
state.pa.orderStatus = target.id
pageRef.value.reload(true)
}
const pageRef = ref<any>(null)
const pageHook = hooks.usePage(pageRef, async () => [], null, "data.records")
const query = (page: number, pagesize: number) => {
const isLogin = hooks.useStaticCheckLogin()
if (!isLogin) return
pageHook.startPage(page, pagesize, false, state.pa)
}
</script>
+2 -2
View File
@@ -167,10 +167,10 @@ const doTransferMoney = (v: any) => {
</view>
<view class="second-text-50">
<text v-if="v.cardNumber" class="iconfont icon-fuzhi" @tap.stop="hooks.useCopy(v.cardNumber)" />
<text class="m-l-20rpx iconfont icon-erweima" @tap.stop="doPreviewQrCode(v)" />
<text v-if="v.walletTypeUniqueCode != '2'" class="m-l-20rpx iconfont icon-erweima" @tap.stop="doPreviewQrCode(v)" />
</view>
</view>
<view class="h-1px m-t-10rpx bg-#999 bg-opacity-5" />
<view v-if="v.cardNumber" class="h-1px m-t-10rpx bg-#999 bg-opacity-5" />
</view>
<view class="flex-row items-center justify-between m-t-10rpx">
<view class="flex-row items-center">
+138
View File
@@ -0,0 +1,138 @@
<template>
<crud-layout bg="/static/page/blue-bg.png">
<z-paging
ref="pageRef"
:fixed="false"
height="100%"
safe-area-inset-bottom
:loading-more-enabled="true"
:show-scrollbar="false"
:auto-clean-list-when-reload="false"
:auto-scroll-to-top-when-reload="false"
>
<template #top>
<view class="h-30rpx" />
<view class="bg-white rounded-12rpx p-20rpx flex justify-between items-center">
<text class="text-30 font-600">月度流水统计</text>
<tm-text color="#999999" font-size="26">{{ formatVal }}</tm-text>
<view class="flex items-center cursor-pointer">
<tm-between-time
start="2020-1-1"
end="2050-1-1"
v-model="state.date"
v-model:model-str="state.formatVal"
@confirm="datePickerConfirm"
format="YYYY-MM-DD"
:quickDate="[]"
drawerSize="900"
>
<image class="w-[30rpx] h-[30rpx]" src="@/static/page/filter.svg" />
<text class="ml-1 text-30">筛选</text>
</tm-between-time>
</view>
</view>
</template>
<view class="h-20rpx" />
<view v-if="state.waterData.merchantId" class="bg-white rounded-16rpx p-3 mb-2 shadow-md">
<view class="flex justify-between items-center text-sm text-gray-800 mb-1">
<view class="flex items-center">
<image class="w-50rpx h-50rpx rounded-8rpx" :src="filePath(state.waterData.logoPic)" mode="aspectFill" />
<view class="ml-2">{{ state.waterData.merchantName }}</view>
</view>
<view>{{ state.waterData.day }}</view>
</view>
<view class="bg-gray-100 rounded-12rpx p-2">
<view class="flex justify-between mb-2">
<view class="flex-1 flex items-center p-2 bg-white rounded-8rpx">
<text class="flex-1 text-sm text-center text-gray-600">流水金额</text>
<text class="flex-1 text-sm text-center text-gray-800">¥ {{ hooks.useMoney(state.waterData.totalPayPrice) }}</text>
</view>
<view class="flex-1 flex items-center p-2 bg-white rounded-8rpx ml-2">
<text class="flex-1 text-sm text-center text-gray-600">流水次数</text>
<text class="flex-1 text-sm text-center text-gray-800">{{ state.waterData.totalPayCount || 0 }}</text>
</view>
</view>
<view class="flex justify-between mb-2">
<view class="flex-1 flex items-center p-2 bg-white rounded-8rpx">
<text class="flex-1 text-sm text-center text-gray-600">盈利金额</text>
<text class="flex-1 text-sm text-center text-green-500">¥ {{ hooks.useMoney(state.waterData.totalProfitPrice) }}</text>
</view>
<view class="flex-1 flex items-center p-2 bg-white rounded-8rpx ml-2">
<text class="flex-1 text-sm text-center text-gray-600">盈利次数</text>
<text class="flex-1 text-sm text-center text-green-500">{{ state.waterData.totalProfitCount || 0 }}</text>
</view>
</view>
<view class="flex justify-between mb-0">
<view class="flex-1 flex items-center p-2 bg-white rounded-8rpx">
<text class="flex-1 text-sm text-center text-gray-600">退款金额</text>
<text class="flex-1 text-sm text-center text-red-500">¥ {{ hooks.useMoney(state.waterData.totalRefundPrice) }}</text>
</view>
<view class="flex-1 flex items-center p-2 bg-white rounded-8rpx ml-2">
<text class="flex-1 text-sm text-center text-gray-600">退款次数</text>
<text class="flex-1 text-sm text-center text-red-500">{{ state.waterData.totalRefundCount || 0 }}</text>
</view>
</view>
</view>
</view>
</z-paging>
</crud-layout>
</template>
<script setup lang="ts">
import { ref, reactive, computed } from "vue"
import { onLoad, onShow } from "@dcloudio/uni-app"
import { hooks } from "@@/index"
import { filePath } from "@@/utils/file"
import { flowStatisticsApi } from "@@/api"
const pageRef = ref<any>(null)
const state = reactive<any>({
pa: {
createTimeList: [hooks.useTime(new Date(), "{y}-{m}-{d}"), hooks.useTime(new Date(), "{y}-{m}-{d}")],
},
formatVal: "",
date: [hooks.useTime(new Date(), "{y}-{m}"), hooks.useTime(new Date(), "{y}-{m}")],
waterData: {},
})
const formatVal = computed(() => (state.date.length === 2 ? state.formatVal : ""))
onLoad(() => {
const app = getApp()
app._initTabbar()
})
onShow(() => {
const isLogin = hooks.useCheckLogin()
if (!isLogin) return
getWaterTotalData()
})
const getWaterTotalData = async () => {
const isLogin = hooks.useStaticCheckLogin()
if (!isLogin) return
try {
uni.showLoading({ title: "加载中", mask: true })
const res: any = await flowStatisticsApi.mchWaterTotal({
createTimeList: state.pa.createTimeList,
})
if (res.code == 0) {
state.waterData = res.data
uni.hideLoading()
} else {
state.waterData = {}
uni.showToast({ title: res.msg, icon: "none" })
}
} catch (error: any) {
uni.showToast({ title: error.msg, icon: "none" })
}
}
// 时间范围选择器确认
const datePickerConfirm = (date: any) => {
if (!formatVal.value) return
state.pa.createTimeList = formatVal.value.split("~")
getWaterTotalData()
}
</script>
+44 -65
View File
@@ -1,67 +1,46 @@
import request from "@/sheep/utils/request";
import request from "@/sheep/utils/request"
export default {
foreignList: (params: any) =>
request({
url: "wallet/wallet-foreign/app/page-join",
method: "GET",
params,
custom: {
showLoading: false,
},
}),
foreignDetail: (params: any) =>
request({
url: "wallet/wallet-foreign/app/detail",
method: "GET",
params,
custom: {
showLoading: false,
},
}),
codeList: (params: any) =>
request({
url: "wallet/wallet-code-use/app/code-list",
method: "GET",
params,
custom: {
showLoading: false,
},
}),
foreignApply: (data: any) =>
request({
url: "wallet/wallet-foreign/app/apply",
method: "POST",
data,
custom: {
showLoading: false,
},
}),
strideList: (params: any) =>
request({
url: "wallet/wallet-stride/app/page-join",
method: "GET",
params,
custom: {
showLoading: false,
},
}),
strideDetail: (params: any) =>
request({
url: "wallet/wallet-stride/app/detail",
method: "GET",
params,
custom: {
showLoading: false,
},
}),
strideApply: (data: any) =>
request({
url: "wallet/wallet-stride/app/apply",
method: "POST",
data,
custom: {
showLoading: false,
},
}),
};
foreignList: (params: any) =>
request({
url: "wallet/wallet-foreign/app/page-join",
method: "GET",
params,
}),
foreignDetail: (params: any) =>
request({
url: "wallet/wallet-foreign/app/detail",
method: "GET",
params,
}),
codeList: (params: any) =>
request({
url: "wallet/wallet-code-use/app/code-list",
method: "GET",
params,
}),
foreignApply: (data: any) =>
request({
url: "wallet/wallet-foreign/app/apply",
method: "POST",
data,
}),
strideList: (params: any) =>
request({
url: "wallet/wallet-stride/app/page-join",
method: "GET",
params,
}),
strideDetail: (params: any) =>
request({
url: "wallet/wallet-stride/app/detail",
method: "GET",
params,
}),
strideApply: (data: any) =>
request({
url: "wallet/wallet-stride/app/apply",
method: "POST",
data,
}),
}
+38 -56
View File
@@ -1,58 +1,40 @@
import request from "@/sheep/utils/request";
import request from "@/sheep/utils/request"
export default {
page: (params: any) =>
request({
url: "canteen/boxesInfo/appPage",
method: "GET",
params,
custom: {
showLoading: false,
},
}),
detail: (params: any) =>
request({
url: "canteen/boxesInfo/getInfo",
method: "GET",
params,
custom: {
showLoading: false,
},
}),
apply: (data: any) =>
request({
url: "canteen/boxesInfo/create",
method: "POST",
data,
custom: {
showLoading: false,
},
}),
cancel: (data: any) =>
request({
url: "canteen/boxesInfo/cancel",
method: "GET",
data,
custom: {
showLoading: false,
},
}),
get: (data: any) =>
request({
url: "canteen/boxesInfo/get",
method: "GET",
data,
custom: {
showLoading: false,
},
}),
MyBookingPage: (data: any) =>
request({
url: "canteen/boxesInfo/getMyBookingPage",
method: "GET",
data,
custom: {
showLoading: false,
},
}),
};
page: (params: any) =>
request({
url: "canteen/boxesInfo/appPage",
method: "GET",
params,
}),
detail: (params: any) =>
request({
url: "canteen/boxesInfo/getInfo",
method: "GET",
params,
}),
apply: (data: any) =>
request({
url: "canteen/boxesInfo/create",
method: "POST",
data,
}),
cancel: (data: any) =>
request({
url: "canteen/boxesInfo/cancel",
method: "GET",
data,
}),
get: (data: any) =>
request({
url: "canteen/boxesInfo/get",
method: "GET",
data,
}),
MyBookingPage: (data: any) =>
request({
url: "canteen/boxesInfo/getMyBookingPage",
method: "GET",
data,
}),
}
+8 -11
View File
@@ -1,13 +1,10 @@
import request from "@/sheep/utils/request";
import request from "@/sheep/utils/request"
export default {
setting: (params: any) =>
request({
url: "wallet/wallet-setting/app/get-setting",
method: "GET",
params,
custom: {
showLoading: false,
},
}),
};
setting: (params: any) =>
request({
url: "wallet/wallet-setting/app/get-setting",
method: "GET",
params,
}),
}
+38 -34
View File
@@ -11,9 +11,6 @@ export default {
url: "hard/hard-auth/app/get-auth-hard-door",
method: "POST",
data,
custom: {
showLoading: false,
},
}),
/**
* app获取智能柜授权信息
@@ -25,9 +22,6 @@ export default {
url: "hard/hard-auth/app/get-auth-hard-door",
method: "POST",
data,
custom: {
showLoading: false,
},
}),
/**
* app查询智能柜列表(有分页)
@@ -37,9 +31,6 @@ export default {
url: "hard/hard-door-manager/app/page",
method: "GET",
params,
custom: {
showLoading: false,
},
}),
/**
@@ -51,9 +42,6 @@ export default {
url: "hard/hard-door-manager/app/detail",
method: "GET",
params,
custom: {
showLoading: false,
},
}),
/**
@@ -61,14 +49,11 @@ export default {
* @param id 绑定id
* @param hardSpuId 商品id
*/
putaway: (data: { hardDoorId: any }) =>
putaway: (data: { id: any; hardSpuId: any }): Promise<any> =>
request({
url: "hard/hard-spu/app/putaway",
method: "POST",
data,
custom: {
showLoading: false,
},
}),
/**
@@ -76,14 +61,11 @@ export default {
* @param id 绑定id
* @param hardSpuId 商品id
*/
unPutaway: (data: { hardDoorId: { id: any; hardSpuId: any } }) =>
unPutaway: (data: { id: any; hardSpuId: any }) =>
request({
url: "hard/hard-spu/app/un-putaway",
method: "POST",
data,
custom: {
showLoading: false,
},
}),
/**
* app查询货柜补货商品列表
@@ -95,9 +77,6 @@ export default {
url: "hard/hard-spu/app/cabinet-putaway-list",
method: "GET",
params,
custom: {
showLoading: false,
},
}),
/**
@@ -110,13 +89,10 @@ export default {
url: "hard/hard-spu/app/cabinet-list",
method: "GET",
params,
custom: {
showLoading: false,
},
}),
/**
* app上架完成
* 补货完成
* @param flowId
* @param list
*/
@@ -125,13 +101,10 @@ export default {
url: "hard/hard-spu-repertory/app/repertory-done",
method: "POST",
data,
custom: {
showLoading: false,
},
}),
/**
* 上架开门
* 补货开门
* @param hardDoorId 智能柜编号
* @param cabinetNo 货柜编号
*/
@@ -140,8 +113,39 @@ export default {
url: "hard/hard-door-flow/app/open-repertory",
method: "POST",
data,
custom: {
showLoading: false,
},
}),
/**
* app商品列表
* @param name
* @param skuType
*/
hardDoorSpuPage: (params: { name: any; skuType: any }): Promise<any> =>
request({
url: "hard/hard-spu/app/page",
method: "GET",
params,
}),
/**
* app检修开门
* @param hardDoorId 智能柜id
* @param cabinetNo 货柜编号
*/
openAccess: (data: { hardDoorId: string; cabinetNo: string }): Promise<any> =>
request({
url: "hard/hard-door-flow/app/open-access",
method: "POST",
data,
}),
/**
* app检修关门
* @param hardDoorId 智能柜id
* @param cabinetNo 货柜编号
*/
closeAccess: (data: { hardDoorId: string; cabinetNo: string }): Promise<any> =>
request({
url: "hard/hard-door-flow/app/close-access",
method: "POST",
data,
}),
}
+32 -47
View File
@@ -1,49 +1,34 @@
import request from "@/sheep/utils/request";
import request from "@/sheep/utils/request"
export default {
page: (params: any) =>
request({
url: `/admin/user-face/app/page-join`,
method: "GET",
params,
custom: {
showLoading: false,
},
}),
del: (params: any) =>
request({
url: `/admin/user-face/app`,
method: "DELETE",
params,
custom: {
showLoading: false,
},
}),
create: (data: any) =>
request({
url: `/admin/user-face/app`,
method: "POST",
data,
custom: {
showLoading: false,
},
}),
get: (params: any) =>
request({
url: `/admin/user-face/app/detail`,
method: "GET",
params,
custom: {
showLoading: false,
},
}),
put: (data: any) =>
request({
url: `/admin/user-face/app`,
method: "PUT",
data,
custom: {
showLoading: false,
},
}),
};
page: (params: any) =>
request({
url: `/admin/user-face/app/page-join`,
method: "GET",
params,
}),
del: (params: any) =>
request({
url: `/admin/user-face/app`,
method: "DELETE",
params,
}),
create: (data: any) =>
request({
url: `/admin/user-face/app`,
method: "POST",
data,
}),
get: (params: any) =>
request({
url: `/admin/user-face/app/detail`,
method: "GET",
params,
}),
put: (data: any) =>
request({
url: `/admin/user-face/app`,
method: "PUT",
data,
}),
}
+12 -3
View File
@@ -1,13 +1,22 @@
import request from "@/sheep/utils/request"
export default {
/**
* app查询商户每天流水记录
*/
page: (params: any) =>
request({
url: "/hard/hard-total/app/mch-water-day",
method: "GET",
params,
custom: {
showLoading: false,
},
}),
/**
* app查询商户全部流水记录
*/
mchWaterTotal: (params: any) =>
request({
url: "/hard/hard-total/app/mch-water-total",
method: "GET",
params,
}),
}
-18
View File
@@ -10,54 +10,36 @@ export default {
current: data.current,
size: data.size,
},
custom: {
showLoading: false,
},
}),
classify: (params: any) =>
request({
url: `/canteen/canteenOnlineCategory/app/getAllSimple`,
method: "GET",
params,
custom: {
showLoading: false,
},
}),
product: (params: any) =>
request({
url: `/canteen/canteenOnlineSpu/app/getCanteenSpuList`,
method: "GET",
params,
custom: {
showLoading: false,
},
}),
getShopCar: (params: any) =>
request({
url: `/hard/hard-car/app/mch-detail`,
method: "GET",
params,
custom: {
showLoading: false,
},
}),
updateShopCar: (data: any) =>
request({
url: `/hard/hard-car/app/save-or-upload`,
method: "POST",
data,
custom: {
showLoading: false,
},
}),
checkSpuStock: (params) => {
return request({
url: "/canteen/canteenOnlineSpu/app/checkSpuStock",
method: "GET",
params,
custom: {
showLoading: false,
},
})
},
}
-6
View File
@@ -6,9 +6,6 @@ export default {
url: "hard/hard-auth/app/get-auth-hard-door",
method: "POST",
data,
custom: {
showLoading: false,
},
}),
/**
* app获取智能柜授权信息
@@ -21,8 +18,5 @@ export default {
url: "hard/hard-auth/app/auth-hard-door",
method: "POST",
data,
custom: {
showLoading: false,
},
}),
}
-9
View File
@@ -6,25 +6,16 @@ export default {
url: "/hard/hard-order/app/mch-page-join",
method: "GET",
params,
custom: {
showLoading: false,
},
}),
refuseRefund: (data: { id: string; auditReason: string }) =>
request({
url: "/hard/hard-after-sale/app/mch-disagree",
method: "POST",
data,
custom: {
showLoading: false,
},
}),
agreeRefund: (params: { id: string }) =>
request({
url: `/hard/hard-after-sale/app/mch-agree?id=${params.id}`,
method: "POST",
custom: {
showLoading: false,
},
}),
}
+17 -9
View File
@@ -6,26 +6,34 @@ export default {
url: "/wallet/mch-manage/app/page-join",
method: "GET",
params,
custom: {
showLoading: false,
},
}),
childrenPage: (params: any) =>
request({
url: "/wallet/mch-manage/app/children-page-join",
method: "GET",
params,
custom: {
showLoading: false,
},
}),
detail: (params: any): Promise<any> =>
request({
url: "/wallet/mch-manage/app/detail",
method: "GET",
params,
custom: {
showLoading: false,
},
}),
/**
* 店铺分类查询
*/
selectCatgory: (params: any) =>
request({
url: "/wallet/mch-catgory/app/select",
method: "GET",
params,
}),
/**
* 宁波银行登录
*/
lbLogin: () =>
request({
url: "/wallet/mch-manage/app/lb-login",
method: "GET",
}),
}
+8 -12
View File
@@ -6,35 +6,31 @@ export default {
url: `/hard/hard-order/app/caneen-page-join`,
method: "GET",
params,
custom: {
showLoading: false,
},
}),
supPage: (params: any) =>
request({
url: `/hard/hard-order/app/sup-page-join`,
method: "GET",
params,
custom: {
showLoading: false,
},
}),
detail: (params: any) =>
request({
url: `/hard/hard-order/app/detail`,
method: "GET",
params,
custom: {
showLoading: false,
},
}),
shopCarList: (params: any) =>
request({
url: `/hard/hard-car/app/order-id`,
method: "GET",
params,
custom: {
showLoading: false,
},
}),
/**
* 预约时间列表
*/
apptList: () =>
request({
url: "/hard/hard-appt/app/list",
method: "GET",
}),
}
-15
View File
@@ -23,9 +23,6 @@ export default {
url: "/hard/hard-order/app/create-order",
method: "GET",
params,
custom: {
showLoading: false,
},
})
},
// 创建二维码订单
@@ -34,9 +31,6 @@ export default {
url: "/hard/hard-order/app/create-order-scan-qrcode",
method: "POST",
data,
custom: {
showLoading: false,
},
})
},
// 结算
@@ -45,9 +39,6 @@ export default {
url: "/hardware/order/submit-order",
method: "POST",
data,
custom: {
showLoading: false,
},
})
},
// 退款
@@ -56,9 +47,6 @@ export default {
url: "/hardware/order/refund",
method: "GET",
params,
custom: {
showLoading: false,
},
})
},
// 转账
@@ -67,9 +55,6 @@ export default {
url: "/wallet/wallet-rule-transaction/app/transfer-accounts",
method: "POST",
data,
custom: {
showLoading: false,
},
})
},
}
+30 -30
View File
@@ -1,32 +1,32 @@
import request from "@/sheep/utils/request";
import request from "@/sheep/utils/request"
export default {
create: (data: any) => {
return request({
url: "/hard/hard-after-sale/app/create",
method: "POST",
data,
});
},
cancel: (params: any) => {
return request({
url: "/hard/hard-after-sale/app/cancel",
method: "GET",
params,
});
},
get: (params: any) => {
return request({
url: "/hard/hard-after-sale/app/detail-by-order-id",
method: "GET",
params,
});
},
history: (params: any) => {
return request({
url: "/hard/hard-after-sale/app/history",
method: "GET",
params,
});
},
};
create: (data: any) => {
return request({
url: "/hard/hard-after-sale/app/create",
method: "POST",
data,
})
},
cancel: (params: any) => {
return request({
url: "/hard/hard-after-sale/app/cancel",
method: "GET",
params,
})
},
get: (params: any) => {
return request({
url: "/hard/hard-after-sale/app/detail-by-order-id",
method: "GET",
params,
})
},
history: (params: any) => {
return request({
url: "/hard/hard-after-sale/app/history",
method: "GET",
params,
})
},
}
-12
View File
@@ -6,36 +6,24 @@ export default {
url: `/supermarket/supermarketCategory/app/simpleAll`,
method: "GET",
params,
custom: {
showLoading: false,
},
}),
getSupermarketSpuList: (data: any) =>
request({
url: `/supermarket/supermarketSpu/app/selectListAll`,
method: "POST",
data,
custom: {
showLoading: false,
},
}),
getSupermarketSpuDetail: (params: any) =>
request({
url: `/supermarket/supermarketSpu/app/SpuDetails`,
method: "GET",
params,
custom: {
showLoading: false,
},
}),
checkSpuStock: (params) => {
return request({
url: "/supermarket/supermarketSpu/app/checkSpuStock",
method: "GET",
params,
custom: {
showLoading: false,
},
})
},
}
+29 -41
View File
@@ -4,65 +4,40 @@ import { encryption } from "@/sheep/utils/encryption"
// 将 Basic Auth 字符串提取为常量
const BASIC_AUTH = "Basic " + window.btoa(import.meta.env.VITE_OAUTH2_APP_CLIENT)
// 定义接口类型
interface LoginParams {
username: string
password: string
randomStr: string
code: string
grant_type: string
scope: string
}
export default {
// 获取用户信息
userInfo: (): Promise<any> =>
request({
url: "/admin/user/info",
method: "GET",
custom: {
showLoading: false,
loadingMsg: "登录中",
},
}),
// 浙政钉授权
// 浙政钉授权登录
auth: (token: string): Promise<any> =>
request({
url: "/thirdparty/thirdPartyOAth2/zzdsso",
method: "POST",
data: { token },
custom: {
showLoading: false,
loadingMsg: "授权中",
},
}),
// 诗画授权
// 诗画授权登录
authsh: (data: { accountId: string; sessionId: string }): Promise<any> =>
request({
url: "/thirdparty/thirdPartyOAth2/shjnsso",
method: "POST",
custom: {
showLoading: false,
loadingMsg: "授权中",
},
data,
}),
// 刷新token
refreshToken: (params: { refreshToken: string }) =>
request({
url: `/sys/auth/refresh-token`,
method: "POST",
params,
custom: {
showLoading: false,
},
}),
// refreshToken: (params: { refreshToken: string }) =>
// request({
// url: `/sys/auth/refresh-token`,
// method: "POST",
// params,
// }),
// 登录
login: (params: LoginParams) => {
// 账号密码登录
login: (params: any) => {
const { username, password, randomStr, code, grant_type, scope } = params
const encPassword = encryption(password, import.meta.env.VITE_PWD_ENC_KEY)
@@ -83,9 +58,6 @@ export default {
Authorization: BASIC_AUTH,
"content-type": "application/x-www-form-urlencoded",
},
custom: {
showLoading: false,
},
})
},
// 判断是否是商户角色
@@ -93,8 +65,24 @@ export default {
request({
url: "/admin/role/isMchUser",
method: "GET",
custom: {
showLoading: false,
},
}),
// 判断用户移动端角色
userRole: () =>
request({
url: "/admin/role/app/user-role",
method: "GET",
}),
// 根据手机号发送验证码
getMobilePhoneCode: (mobilePhone: string) =>
request({
url: `/thirdparty/thirdPartyOAth2/loginSms?mobilePhone=${mobilePhone}`,
method: "POST",
}),
// 设备认证
verifyDevice: (data: { mobilePhone: string; code: string }) =>
request({
url: "/thirdparty/thirdPartyOAth2/verify-device",
method: "POST",
data,
}),
}
-33
View File
@@ -5,90 +5,60 @@ export default {
request({
url: "/wallet/wallet-manage/app/get-all",
method: "GET",
custom: {
showLoading: false,
},
}),
getQrCode: (params: any) =>
request({
url: "wallet/wallet-manage/app/get-qr-code",
method: "GET",
params,
custom: {
showLoading: false,
},
}),
detail: (params: any) =>
request({
url: "wallet/wallet-manage/app/detail",
method: "GET",
params,
custom: {
showLoading: false,
},
}),
bind: (data: any) =>
request({
url: "wallet/wallet-active/app/bind-card",
method: "POST",
data,
custom: {
showLoading: false,
},
}),
freeze: (data: any) =>
request({
url: "wallet/wallet-freeze/app/apply-freeze",
method: "POST",
data,
custom: {
showLoading: false,
},
}),
balanceDetail: (params: any) =>
request({
url: "pay/wallet/get-id",
method: "GET",
params,
custom: {
showLoading: false,
},
}),
transaction: (params: any) =>
request({
url: "wallet/wallet-transaction/app/page",
method: "GET",
params,
custom: {
showLoading: false,
},
}),
summary: (params: any) =>
request({
url: "pay/wallet-transaction/get-summary-by-id",
method: "GET",
params,
custom: {
showLoading: false,
},
}),
rechargeList: (params: any) =>
request({
url: "wallet/wallet-recharge-package/app/list",
method: "GET",
params,
custom: {
showLoading: false,
},
}),
recharge: (data: any) =>
request({
url: "wallet/wallet-recharge/app/create",
method: "POST",
data,
custom: {
showLoading: false,
},
}),
/**
* 是够能够使用智能柜
@@ -98,8 +68,5 @@ export default {
url: "wallet/wallet-manage/app/is-use-door",
method: "GET",
data: {},
custom: {
showLoading: false,
},
}),
}
@@ -1,5 +1,5 @@
<script setup>
import { defineProps, computed } from "vue"
import { computed } from "vue"
import { router } from "@@/index"
const props = defineProps({
@@ -1,5 +1,5 @@
<script setup>
import { defineProps, computed } from "vue"
import { computed } from "vue"
import { router } from "@@/index"
const props = defineProps({
@@ -1,31 +1,31 @@
<script setup lang="ts">
import { defineProps, withDefaults } from "vue";
import { withDefaults } from "vue"
export interface Props {
type: "top" | "bottom";
bgColor: string;
type: "top" | "bottom"
bgColor: string
}
const props = withDefaults(defineProps<Props>(), {
type: "top",
bgColor: "transparent",
});
type: "top",
bgColor: "transparent",
})
function getHeight() {
const { top, bottom } = uni.getSystemInfoSync().safeAreaInsets!;
if (props.type && props.type === "bottom") {
return bottom + "px";
}
return top + "px";
const { top, bottom } = uni.getSystemInfoSync().safeAreaInsets!
if (props.type && props.type === "bottom") {
return bottom + "px"
}
return top + "px"
}
</script>
<template>
<view class="safe" :style="{ backgroundColor: props.bgColor, height: getHeight() }"></view>
<view class="safe" :style="{ backgroundColor: props.bgColor, height: getHeight() }"></view>
</template>
<style lang="scss">
.safe-top {
width: 100%;
width: 100%;
}
</style>
</style>
@@ -1,5 +1,5 @@
<script setup lang="ts">
import { defineProps, withDefaults, watch, ref, reactive, onMounted } from "vue"
import { watch, reactive, onMounted } from "vue"
import { router } from "@@/index"
export type Props = {
+1 -1
View File
@@ -31,7 +31,7 @@
class="flex-1 h-[80rpx] flex items-center justify-center bg-white mx-[5px] rounded-lg cursor-pointer select-none active:bg-[#f0f0f0]"
@click="handleDelete"
>
<image class="w-[30rpx] h-[30rpx]" src="@/static/page/keyboardDelete.svg" />
<image class="w-[40rpx] h-[40rpx]" src="@/static/page/keyboardDelete.svg" />
</view>
</view>
</view>
@@ -0,0 +1,26 @@
import { h, render } from "vue"
import VerifyDeviceImpModel from "./verifyDeviceImpModel.vue"
let VerifyDeviceImpModelInstance: boolean | null = null
const showVerifyDeviceImpModel = (onClose: () => any = () => null) => {
return new Promise((resolve, reject) => {
if (VerifyDeviceImpModelInstance) return
const close = () => {
render(null, document.body)
VerifyDeviceImpModelInstance = false
onClose()
}
const vnode = h(VerifyDeviceImpModel, {
show: true,
showCancel: false,
close,
})
render(vnode, document.body)
VerifyDeviceImpModelInstance = true
})
}
export default showVerifyDeviceImpModel
@@ -0,0 +1,133 @@
<template>
<tm-modal
:show="show"
:overlayClick="false"
position="bottom"
:showCancel="showCancel"
title="您的设备需要验证"
height="650rpx"
zIndex="999"
cancelText="取消"
confirmText="确认"
@confirm=""
@cancel=""
@close="close"
>
<tm-form ref="formRef" v-model="form" :rules="formRules" direction="vertical">
<tm-form-item name="mobilePhone" label="手机号">
<tm-input v-model.trim="form.mobilePhone" :maxlength="11" placeholder="请输入手机号" />
</tm-form-item>
<view class="h-10rpx" />
<tm-form-item name="code" label="验证码">
<tm-input v-model.trim="form.code" :maxlength="6" placeholder="请输入验证码" :disabled="form.mobilePhone.length != 11">
<template v-slot:right>
<tm-button class="ml-1 px-2" color="primary" size="m" @click="getCode" :disabled="state.codeBtnDisabled">
<text>获取验证码</text><text v-if="state.isTiming">{{ state.countDown }} s</text>
</tm-button>
</template>
</tm-input>
</tm-form-item>
</tm-form>
<template #footer>
<tm-button block color="primary" @tap="doSubmit" :disabled="state.verifyBtnDisabled">验 证</tm-button>
</template>
</tm-modal>
</template>
<script setup lang="ts">
import { ref, reactive, watch, computed, onUnmounted } from "vue"
import { userApi } from "@@/api"
const props = withDefaults(
defineProps<{
show: boolean
showCancel?: boolean
close?: () => void
}>(),
{
showCancel: true,
close: () => void 0,
},
)
const show = ref(props.show)
const formRef = ref()
const form = reactive<any>({
mobilePhone: "",
code: "",
})
const state = reactive({
countDown: 60,
codeBtnDisabled: true,
verifyBtnDisabled: false,
isTiming: false,
})
const formRules = reactive<any>({
mobilePhone: [{ required: true, message: "请输入手机号" }],
code: [{ required: true, message: "请输入验证码" }],
})
let timer: any = null
// 获取验证码
const getCode = async () => {
if (state.codeBtnDisabled) return
try {
uni.showLoading({ title: "发送中...", mask: true })
const res: any = await userApi.getMobilePhoneCode(form.mobilePhone)
if (res.code == 0) {
state.codeBtnDisabled = true
state.isTiming = true
timer = setInterval(() => {
state.countDown--
if (state.countDown === 0) {
state.isTiming = false
state.codeBtnDisabled = false
state.countDown = 60
clearInterval(timer)
}
}, 1000)
} else {
uni.showToast({ title: res.msg || "验证码发送失败", icon: "none" })
}
} catch (error: any) {
uni.showToast({ title: error.message, icon: "none" })
} finally {
uni.hideLoading()
}
}
watch(
() => form.mobilePhone,
(val) => {
if (val.length == 11) {
state.codeBtnDisabled = false
} else {
state.codeBtnDisabled = true
}
},
)
// 提交设备验证
const doSubmit = async () => {
formRef.value.submit()
const { isPass } = formRef.value.validate()
if (!isPass) return
uni.showLoading({ title: "验证中...", mask: true })
const res: any = await userApi.verifyDevice({ mobilePhone: form.mobilePhone, code: form.code })
if (res.code != 0) {
uni.showToast({ title: res.msg || "验证失败", icon: "none" })
return
}
uni.hideLoading()
uni.showToast({ title: "设备验证成功", icon: "none" })
show.value = false
}
onUnmounted(() => {
clearInterval(timer)
})
</script>
+7 -11
View File
@@ -1,12 +1,8 @@
import { filePath } from "../utils/file";
export const usePreviewImage = (str: string | undefined) => {
console.log(str, "str");
if (str == undefined) return;
let urlList = str.split(",").map((v) => filePath(v));
console.log(urlList);
uni.previewImage({
urls: urlList,
});
};
if (str == undefined) return
let urlList = str.split(",")
console.log(urlList)
uni.previewImage({
urls: urlList,
})
}
+2
View File
@@ -4,9 +4,11 @@ export const getAppInfo = async (): Promise<string> => {
const res = await (window as any).CP2.getAppInfo()
// 浙政钉环境
if (res.code === 0) {
console.log("环境:zzd")
return "zzd"
} else {
// 诗画环境
console.log("环境:sh")
return "sh"
}
} catch (error) {
+6
View File
@@ -0,0 +1,6 @@
// 获取启动参数
const getLaunchParam = (): "canteen" | "selfMerchant" | "coopMerchant" | "thirdApp" | null => {
return new URL(window.location.href).searchParams.get("launchParam") as "canteen" | "selfMerchant" | "coopMerchant" | "thirdApp" | null
}
export default getLaunchParam
+44 -123
View File
@@ -1,38 +1,14 @@
import Request from "luch-request"
import { isEmpty } from "radash"
import isDevEnv from "./isDevEnv"
import { router, constant } from "@@/index"
import { userApi } from "../api"
import { isEmpty } from "radash"
import isDevEnv from "./isDevEnv"
import { getAppInfo } from "@@/utils/getAppInfo"
import showVerifyDeviceImpModel from "../components/verifyDeviceImpModel/verifyDeviceImpModel"
// 常量定义
const TOKEN_KEY = constant.storageConstant.TOKEN
const USER_INFO_KEY = constant.storageConstant.USERINFO
// Loading 状态管理
const LoadingInstance = {
target: null,
count: 0,
}
// 关闭加载提示
function closeLoading() {
if (LoadingInstance.count > 0) LoadingInstance.count--
if (LoadingInstance.count === 0) uni.hideLoading()
}
// 显示加载提示
function showLoading(message: string) {
LoadingInstance.count++
if (LoadingInstance.count === 1) {
uni.showLoading({
title: message,
mask: true,
fail: () => uni.hideLoading(),
})
}
}
// 读取token并处理Authorization请求头
const getAuthHeader = (tokenStorage: any) => {
if (isDevEnv()) {
@@ -45,10 +21,12 @@ const getAuthHeader = (tokenStorage: any) => {
async function handleZzdLogin(): Promise<boolean> {
try {
uni.showLoading({ title: "加载中...", mask: true })
const params = new URL(window.location.href).searchParams
const token = params.get("uabaseToken")
const token = new URL(window.location.href).searchParams.get("uabaseToken")
if (!token) return false
if (!token) {
uni.showToast({ title: "用户凭证已失效,请重新进入智慧后勤应用", icon: "none", duration: 6000 })
return false
}
const res = await userApi.auth(token)
if (res?.code == 0) {
@@ -66,8 +44,8 @@ async function handleZzdLogin(): Promise<boolean> {
}
return false
}
} catch (error) {
uni.showToast({ title: "登录错误", icon: "none" })
} catch (error: any) {
uni.showToast({ title: error, icon: "none" })
return false
} finally {
uni.hideLoading()
@@ -78,15 +56,16 @@ async function handleZzdLogin(): Promise<boolean> {
async function handleShLogin(): Promise<boolean> {
try {
uni.showLoading({ title: "登录中...", mask: true })
const userInfo = await (window as any).CP2.getUserInfo()
if (userInfo.code == 0 || !userInfo.data.accountId || !userInfo.data.sessionId) {
uni.showToast({ title: "获取诗画用户信息失败", icon: "none" })
return false
}
const { accountId, sessionId } = userInfo.data
const response = await userApi.authsh({ accountId, sessionId })
// const response = await userApi.authsh({ accountId: "67e790d6a95d5a7b507e53dd", sessionId: "67fdff553cbc284e352ebb4d" }) // 测试
// const userInfo = await (window as any).CP2.getUserInfo()
// if (userInfo.code == 0 || !userInfo.data.accountId || !userInfo.data.sessionId) {
// uni.showToast({ title: "获取诗画用户信息失败", icon: "none" })
// return false
// }
// const { accountId, sessionId } = userInfo.data
// const response = await userApi.authsh({ accountId, sessionId })
const response = await userApi.authsh({ accountId: "67e790d6a95d5a7b507e53dd", sessionId: "68215b03a95d5a4899d20cb4" }) // 测试
if (response.code == 0) {
uni.setStorageSync(TOKEN_KEY, { accessToken: response.data.accessToken })
@@ -99,9 +78,19 @@ async function handleShLogin(): Promise<boolean> {
uni.removeStorageSync(USER_INFO_KEY)
if (response.msg == "token已失效") {
uni.showToast({ title: "用户凭证已失效,请退出并重新进入智慧后勤应用", icon: "none", duration: 6000 })
} else {
uni.showToast({ title: response.msg || "登录失败", icon: "none" })
return false
}
if (response.data == -1) {
uni.showToast({ title: "您的设备需要信任验证", icon: "none" })
await showVerifyDeviceImpModel(async () => {
await autoLogin()
uni.reLaunch({ url: window.location.href.split("#")[1] })
})
return false
}
uni.showToast({ title: response.msg || "登录失败", icon: "none" })
return false
}
} catch (error) {
@@ -146,42 +135,6 @@ async function checkAndRefreshToken(tokenStorage: any) {
}
}
// 处理错误响应
function handleErrorResponse(response: any) {
if (!response.config?.custom?.showError) return
switch (response.data.code) {
case 401:
// 处理未授权情况
setTimeout(() => {
uni.removeStorageSync(TOKEN_KEY)
uni.removeStorageSync(USER_INFO_KEY)
}, 500)
break
case 424:
// 处理token过期
autoLogin()
break
default:
uni.showToast({
title: response.data.msg || "服务器开小差啦,请稍后再试~",
icon: "none",
mask: true,
})
}
}
// 处理成功提示
function handleSuccessMessage(response: any) {
const { data, config } = response
if (data.code === 0 && data.message && config?.custom?.showSuccess) {
uni.showToast({
title: config.custom.successMsg || data.message,
icon: "none",
})
}
}
// 创建请求实例
const http = new Request({
baseURL: import.meta.env.VITE_API_URL,
@@ -197,7 +150,6 @@ const http = new Request({
successMsg: "", // 成功消息
showError: true, // 显示失败消息 默认显示
errorMsg: "", // 失败提醒 默认使用后端返回信息
showLoading: true, // 显示请求时loading模态框 默认显示
loadingMsg: "加载中", // loading提醒文字
auth: false, // 需要授权才能请求 默认放开
},
@@ -205,35 +157,26 @@ const http = new Request({
// 请求拦截器
http.interceptors.request.use(async (config) => {
// console.log("config", config)
const tokenStorage = uni.getStorageSync(TOKEN_KEY)
const config_header: any = config?.header || {}
const config_header: any = config.header || {}
// 设置租户请求头
config_header["TENANT-ID"] = "1"
if (import.meta.env.VITE_IS_TOC === "true") {
config_header["CLIENT-TOC"] = "Y"
}
if (import.meta.env.VITE_IS_TOC === "true") config_header["CLIENT-TOC"] = "Y"
// 处理 loading
if (config.custom?.showLoading) {
showLoading(config.custom.loadingMsg)
}
// 不需要设置认证头的接口
// 不需要设置认证头的接口路径
const skipAuthUrls = ["/thirdparty/thirdPartyOAth2", "/sys/auth/refresh-token", "/auth/oauth2/token"]
// 判断是否需要设置认证头
const needAuth = !skipAuthUrls.some((url) => config.url?.startsWith(url))
if (needAuth) {
if (!skipAuthUrls.some((url) => config.url?.startsWith(url))) {
if (!isEmpty(tokenStorage)) {
// token过期刷新检查
// token存在,token过期刷新检查
await checkAndRefreshToken(tokenStorage)
const authHeader = getAuthHeader(tokenStorage)
if (authHeader) {
config_header.Authorization = authHeader
}
if (authHeader) config_header.Authorization = authHeader
} else {
// token不存在,则发起登录
await autoLogin()
@@ -241,9 +184,7 @@ http.interceptors.request.use(async (config) => {
// 登录后重新获取token
const newTokenStorage = uni.getStorageSync(TOKEN_KEY)
const authHeader = getAuthHeader(newTokenStorage)
if (authHeader) {
config_header.Authorization = authHeader
}
if (authHeader) config_header.Authorization = authHeader
}
}
@@ -253,12 +194,9 @@ http.interceptors.request.use(async (config) => {
// 响应拦截器
http.interceptors.response.use(
async (response) => {
// 关闭loading
if (response.config?.custom?.showLoading) {
closeLoading()
}
// console.log("response", response)
// OAuth2 token请求特殊处理
// 账号密码登录响应结果特殊处理
if (response.config.url === "/auth/oauth2/token") {
return Promise.resolve({
code: 0,
@@ -267,22 +205,10 @@ http.interceptors.response.use(
})
}
// 错误处理和错误提示
if (response.data.code !== 0) {
handleErrorResponse(response)
return Promise.resolve(response.data)
}
// 成功提示
handleSuccessMessage(response)
return Promise.resolve(response.data)
},
async (error) => {
// 处理 loading
if (error.config?.custom?.showLoading) {
closeLoading()
}
// console.log("error", error)
// 处理 424 错误(token过期)
if (error.statusCode === 424) {
@@ -292,7 +218,6 @@ http.interceptors.response.use(
uni.removeStorageSync(USER_INFO_KEY)
uni.showToast({ title: "登录已过期,请重新登录", icon: "none" })
router.jump("/pages/test/login")
return false
} else {
await autoLogin()
}
@@ -300,11 +225,7 @@ http.interceptors.response.use(
// 显示错误信息
if (error?.data?.msg) {
uni.showToast({
title: error.data.msg,
icon: "none",
mask: true,
})
uni.showToast({ title: error.data.msg, icon: "none", mask: true })
}
return Promise.resolve(error.data)
},
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

+1
View File
@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1745315220266" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3915" data-spm-anchor-id="a313x.search_index.0.i2.114e3a81xJ17Of" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M791.551175 0.003021H198.656924C118.273161-0.508978 53.249353 64.51483 52.737355 144.386595V819.200604c0 79.871764 65.023808 144.895573 144.895572 144.895573h3.071991v24.575927c0 19.455943 15.871953 35.327896 35.327896 35.327896h2.559993c19.455943 0 35.327896-15.871953 35.327895-35.327896v-24.575927h475.646597v24.575927c0 19.455943 15.871953 35.327896 35.327896 35.327896h2.559992c19.455943 0 35.327896-15.871953 35.327896-35.327896v-24.575927h3.071991c79.871764 0 144.895573-65.023808 144.895573-144.895573V179.714491c0-99.327707-80.383763-179.71147-179.199472-179.71147zM129.537128 819.200604V144.898593c0-37.887888 30.719909-68.095799 68.095799-68.095799h275.967186v811.005608H197.632927c-37.37589-0.511998-68.095799-30.719909-68.095799-68.607798z m764.925744 0c0 37.887888-30.719909 68.607798-68.095799 68.607798h-275.967186V76.290796h241.151288c56.831832 0 102.911696 46.079864 102.911697 102.911696v639.998112z" p-id="3916" data-spm-anchor-id="a313x.search_index.0.i3.114e3a81xJ17Of" class="" fill="#505873"></path><path d="M364.544435 371.201926h2.559992c23.551931 0 35.327896 11.775965 35.327896 35.327896v66.047805c0 23.551931-11.775965 35.327896-35.327896 35.327895h-2.559992c-23.551931 0-35.327896-11.775965-35.327896-35.327895V406.529822c0-23.551931 11.775965-35.327896 35.327896-35.327896zM657.407571 371.201926h2.559992c23.551931 0 35.327896 11.775965 35.327896 35.327896v66.047805c0 23.551931-11.775965 35.327896-35.327896 35.327895h-2.559992c-23.551931 0-35.327896-11.775965-35.327896-35.327895V406.529822c-0.511998-23.551931 11.263967-35.327896 35.327896-35.327896z" fill="#FF402A" p-id="3917" data-spm-anchor-id="a313x.search_index.0.i6.114e3a81xJ17Of" class=""></path></svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

+1
View File
@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1744973847967" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2622" width="64" height="64" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M983.779031 312.718444a510.292766 510.292766 0 0 0-109.738544-162.758931A510.292766 510.292766 0 0 0 512 0.000569a510.292766 510.292766 0 0 0-362.040487 149.958944A510.292766 510.292766 0 0 0 0.000569 512a510.292766 510.292766 0 0 0 149.958944 362.040487A510.292766 510.292766 0 0 0 512 1023.999431a510.292766 510.292766 0 0 0 362.040487-149.958944A510.292766 510.292766 0 0 0 1023.999431 512a508.813657 508.813657 0 0 0-40.2204-199.281556zM512 951.40929c-242.289509 0-439.40929-197.119781-439.40929-439.40929S269.710491 72.59071 512 72.59071 951.40929 269.710491 951.40929 512 754.289509 951.40929 512 951.40929z" p-id="2623" fill="#0779FD"></path><path d="M693.020243 330.979757c-12.515542-12.515542-31.516409-13.767096-42.439064-2.844442L512 466.716495 373.418821 328.135315c-10.922655-10.922655-29.923522-9.6711-42.439064 2.844442-12.515542 12.515542-13.767096 31.516409-2.844442 42.439064L466.716495 512l-138.58118 138.581179c-10.922655 10.922655-9.6711 29.923522 2.844442 42.439064 12.515542 12.515542 31.516409 13.767096 42.439064 2.844442L512 557.226616l138.581179 138.638069c10.922655 10.922655 29.923522 9.6711 42.439064-2.844442 12.515542-12.515542 13.767096-31.516409 2.844442-42.439064L557.226616 512l138.638069-138.581179c10.922655-10.922655 9.6711-29.923522-2.844442-42.439064z" p-id="2624" fill="#0779FD"></path></svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

+1
View File
@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1746521850802" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4594" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M512 32C246.944 32 32 246.944 32 512c0 265.088 214.944 480 480 480 265.088 0 480-214.912 480-480 0-265.056-214.912-480-480-480z m0 878.56C291.936 910.56 113.44 732.064 113.44 512S291.936 113.44 512 113.44 910.56 291.936 910.56 512 732.064 910.56 512 910.56z" fill="#333333" p-id="4595"></path><path d="M699.2 647.552l-152.8-110.464V271.904a8.608 8.608 0 0 0-8.576-8.576h-51.52a8.608 8.608 0 0 0-8.576 8.576v295.04c0 2.816 1.28 5.376 3.52 7.008l177.216 129.184a8.64 8.64 0 0 0 12-1.792l30.656-41.792a8.544 8.544 0 0 0-1.92-12z" fill="#333333" p-id="4596"></path></svg>

After

Width:  |  Height:  |  Size: 900 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB