# Conflicts:
#	.env
This commit is contained in:
zjf committed 2025-03-21 15:23:13 +08:00
commit e4cd31b377
31 files changed
+1505 -932

No files matched your search

+11 -12
View File
@@ -17,23 +17,22 @@ VITE_PWD_ENC_KEY='pigxpigxpigxpigx'
VITE_OAUTH2_APP_CLIENT='mini:mini' VITE_OAUTH2_APP_CLIENT='mini:mini'
# 图片访问基础地址 # 图片访问基础地址
VITE_IMAGE_BASE_PATH = http://localhost:9999 #VITE_IMAGE_BASE_PATH = http://localhost:9999
# VITE_IMAGE_BASE_PATH = http://192.168.101.29:9999 # 邓-本地 # VITE_IMAGE_BASE_PATH = http://192.168.101.64:9999 # 邓-本地
# VITE_IMAGE_BASE_PATH = http://192.168.101.37:9999 # 邓-本地
# VITE_IMAGE_BASE_PATH = https://123.156.230.15:8089/api # 线上 # 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 = http://220.191.229.171:8090/api # 线上
# VITE_IMAGE_BASE_PATH = https://stgl.pj.gov.cn/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://pjcloud.center.takin.cc # 张
#VITE_IMAGE_BASE_PATH = http://59.202.170.152:81/api # 信创线上 VITE_IMAGE_BASE_PATH = http://59.202.170.152:81/api # 信创线上
# ******************** start 开发环境 start ******************** # ******************** start 开发环境 start ********************
; VITE_APP_DEV_SERVICE = http://59.202.170.152:81/api # 信创线上 # 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 = https://stgl.pj.gov.cn/app-api
# VITE_APP_DEV_SERVICE = http://192.168.101.50:9999 # 邓-本地 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://127.0.0.1:9999
# VITE_APP_DEV_SERVICE = http://123.156.230.15:8089/api/ # 线上 # VITE_APP_DEV_SERVICE = http://123.156.230.15:8089/api/ # 线上
# VITE_APP_DEV_SERVICE = http://220.191.229.171:8090/api # 线上 # VITE_APP_DEV_SERVICE = http://220.191.229.171:8090/api # 线上
; VITE_APP_DEV_SERVICE = http://localhost:9999 # VITE_APP_DEV_SERVICE = http://localhost:9999
# ******************** end 开发环境 end ******************** # ******************** end 开发环境 end ********************
# ******************** start 生产环境 start **************** # ******************** start 生产环境 start ****************
@@ -41,8 +40,8 @@ VITE_APP_DEV_SERVICE = https://stgl.pj.gov.cn/api
#VITE_APP_PROD_SERVICE = http://59.202.170.152:81/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 = https://stgl.pj.gov.cn/api
# VITE_APP_PROD_SERVICE = http://220.191.229.171:8090/api # VITE_APP_PROD_SERVICE = http://220.191.229.171:8090/api
#VITE_APP_PROD_SERVICE = http://59.202.170.152:81/api # 信创线上 VITE_APP_PROD_SERVICE = http://59.202.170.152:81/api # 信创线上
# ******************** end 生产环境 end ******************** # ******************** end 生产环境 end ********************
VITE_DEV_ENV = dev # VITE_DEV_ENV = dev
#VITE_DEV_ENV = prod # VITE_DEV_ENV = prod
+21 -22
View File
@@ -1,25 +1,24 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<script src="https://dapp.tmuyun.com/oss-static/app/jcommind.js"></script> <script src="https://dapp.tmuyun.com/oss-static/app/jcommind.js"></script>
<script> <script src="https://g.alicdn.com/gdt/jsapi/1.9.43/index.js"></script>
var coverSupport = <script>
"CSS" in window && var coverSupport =
typeof CSS.supports === "function" && "CSS" in window && typeof CSS.supports === "function" && (CSS.supports("top: env(a)") || CSS.supports("top: constant(a)"))
(CSS.supports("top: env(a)") || CSS.supports("top: constant(a)")); document.write(
document.write( '<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' +
'<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' + (coverSupport ? ", viewport-fit=cover" : "") +
(coverSupport ? ", viewport-fit=cover" : "") + '" />',
'" />' )
); </script>
</script> <title></title>
<title></title> <!--preload-links-->
<!--preload-links--> <!--app-context-->
<!--app-context--> </head>
</head> <body>
<body> <div id="app"><!--app-html--></div>
<div id="app"><!--app-html--></div> <script type="module" src="/src/main.ts"></script>
<script type="module" src="/src/main.ts"></script> </body>
</body>
</html> </html>
+2
View File
@@ -62,12 +62,14 @@
"@zebra-ui/swiper": "^2.2.8", "@zebra-ui/swiper": "^2.2.8",
"crypto-js": "^4.2.0", "crypto-js": "^4.2.0",
"dayjs": "^1.11.13", "dayjs": "^1.11.13",
"gdt-jsapi": "^1.9.51",
"luch-request": "^3.1.1", "luch-request": "^3.1.1",
"pinia": "^2.2.6", "pinia": "^2.2.6",
"qs": "^6.13.1", "qs": "^6.13.1",
"radash": "^12.1.0", "radash": "^12.1.0",
"vue": "^3.3.11", "vue": "^3.3.11",
"vue-i18n": "^9.1.9", "vue-i18n": "^9.1.9",
"vue-waterfall-plugin-next": "^2.6.5",
"z-paging": "^2.8.0" "z-paging": "^2.8.0"
}, },
"devDependencies": { "devDependencies": {
+24
View File
@@ -65,6 +65,9 @@ importers:
dayjs: dayjs:
specifier: ^1.11.13 specifier: ^1.11.13
version: 1.11.13 version: 1.11.13
gdt-jsapi:
specifier: ^1.9.51
version: 1.9.51
luch-request: luch-request:
specifier: ^3.1.1 specifier: ^3.1.1
version: 3.1.1 version: 3.1.1
@@ -83,6 +86,9 @@ importers:
vue-i18n: vue-i18n:
specifier: ^9.1.9 specifier: ^9.1.9
version: 9.14.2(vue@3.5.13(typescript@4.9.5)) version: 9.14.2(vue@3.5.13(typescript@4.9.5))
vue-waterfall-plugin-next:
specifier: ^2.6.5
version: 2.6.5
z-paging: z-paging:
specifier: ^2.8.0 specifier: ^2.8.0
version: 2.8.4 version: 2.8.4
@@ -1295,6 +1301,9 @@ packages:
'@polka/url@1.0.0-next.28': '@polka/url@1.0.0-next.28':
resolution: {integrity: sha512-8LduaNlMZGwdZ6qWrKlfa+2M4gahzFkprZiAt2TF8uS0qQgBizKXpXURqvTJ4WtmupWxaLqjRb2UCTe72mu+Aw==} resolution: {integrity: sha512-8LduaNlMZGwdZ6qWrKlfa+2M4gahzFkprZiAt2TF8uS0qQgBizKXpXURqvTJ4WtmupWxaLqjRb2UCTe72mu+Aw==}
'@remax/mini-types@0.1.0':
resolution: {integrity: sha512-bVDcbUrp6p0PZwfS0xGVQS6k9f8B35BtZaYt/W/IGKh7VALYQ+tS2KcytLRmIJ/Vmohaw5ikIRN89I+frPdh4g==}
'@rollup/pluginutils@5.1.4': '@rollup/pluginutils@5.1.4':
resolution: {integrity: sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ==} resolution: {integrity: sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ==}
engines: {node: '>=14.0.0'} engines: {node: '>=14.0.0'}
@@ -2404,6 +2413,9 @@ packages:
function-bind@1.1.2: function-bind@1.1.2:
resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
gdt-jsapi@1.9.51:
resolution: {integrity: sha512-VN1iIK7kJU2g2oxY/n8waCREhWxcVwR8qHAE1keVnUJHI6mTdgTelICzq++niRRCaLqUVWC1pYvftEVgk4sq8A==}
generic-names@4.0.0: generic-names@4.0.0:
resolution: {integrity: sha512-ySFolZQfw9FoDb3ed9d80Cm9f0+r7qj+HJkWjeD9RBfpxEVTlVhol+gvaQB/78WbwYfbnNh8nWHHBSlg072y6A==} resolution: {integrity: sha512-ySFolZQfw9FoDb3ed9d80Cm9f0+r7qj+HJkWjeD9RBfpxEVTlVhol+gvaQB/78WbwYfbnNh8nWHHBSlg072y6A==}
@@ -3846,6 +3858,9 @@ packages:
peerDependencies: peerDependencies:
typescript: '*' typescript: '*'
vue-waterfall-plugin-next@2.6.5:
resolution: {integrity: sha512-8ACGbdjoyKLiJfnKXB8h8f9eE14lhyzfI1N1nrfVAIRczSpNY1KRwGOnVXN5OHqheLl3V1C0uVVRPtjTJkHkhw==}
vue@3.5.13: vue@3.5.13:
resolution: {integrity: sha512-wmeiSMxkZCSc+PM2w2VRsOYAZC8GdipNFRTsLSfodVqI9mbejKeXEGr8SckuLnrQPGe3oJN5c3K0vpoU9q/wCQ==} resolution: {integrity: sha512-wmeiSMxkZCSc+PM2w2VRsOYAZC8GdipNFRTsLSfodVqI9mbejKeXEGr8SckuLnrQPGe3oJN5c3K0vpoU9q/wCQ==}
peerDependencies: peerDependencies:
@@ -5960,6 +5975,8 @@ snapshots:
'@polka/url@1.0.0-next.28': {} '@polka/url@1.0.0-next.28': {}
'@remax/mini-types@0.1.0': {}
'@rollup/pluginutils@5.1.4(rollup@4.34.2)': '@rollup/pluginutils@5.1.4(rollup@4.34.2)':
dependencies: dependencies:
'@types/estree': 1.0.6 '@types/estree': 1.0.6
@@ -7202,6 +7219,11 @@ snapshots:
function-bind@1.1.2: {} function-bind@1.1.2: {}
gdt-jsapi@1.9.51:
dependencies:
'@babel/runtime': 7.26.7
'@remax/mini-types': 0.1.0
generic-names@4.0.0: generic-names@4.0.0:
dependencies: dependencies:
loader-utils: 3.3.1 loader-utils: 3.3.1
@@ -8834,6 +8856,8 @@ snapshots:
semver: 7.7.1 semver: 7.7.1
typescript: 4.9.5 typescript: 4.9.5
vue-waterfall-plugin-next@2.6.5: {}
vue@3.5.13(typescript@4.9.5): vue@3.5.13(typescript@4.9.5):
dependencies: dependencies:
'@vue/compiler-dom': 3.5.13 '@vue/compiler-dom': 3.5.13
+11 -12
View File
@@ -1,18 +1,17 @@
import { createSSRApp } from "vue"; import { createSSRApp } from "vue"
import "uno.css"; import "uno.css"
import * as Pinia from "pinia"; import pinia from "../src/sheep/stores/index"
import App from "./App.vue"; import App from "./App.vue"
import tmUi from "./uni_modules/tm-ui"; import tmUi from "./uni_modules/tm-ui"
export function createApp() { export function createApp() {
const app = createSSRApp(App); const app = createSSRApp(App)
app.use(Pinia.createPinia()); app.use(pinia)
app.use(tmUi); app.use(tmUi)
return { return {
app, app,
Pinia, }
};
} }
+38
View File
@@ -30,6 +30,20 @@
"disableScroll": true "disableScroll": true
} }
}, },
// {
// "path": "pages/tabbar/flowStatistics",
// "style": {
// "navigationBarTitleText": "流水统计",
// "disableScroll": true
// }
// },
// {
// "path": "pages/tabbar/individualOrder",
// "style": {
// "navigationBarTitleText": "订单",
// "disableScroll": true
// }
// },
{ {
"path": "pages/tabbar/my", "path": "pages/tabbar/my",
"style": { "style": {
@@ -256,6 +270,18 @@
} }
} }
] ]
},
{
"root": "pages/pay",
"pages": [
{
"path": "scanPay",
"style": {
"navigationBarTitleText": "",
"disableScroll": true
}
}
]
} }
], ],
"globalStyle": { "globalStyle": {
@@ -285,6 +311,18 @@
"iconPath": "static/tabbar/order.png", "iconPath": "static/tabbar/order.png",
"selectedIconPath": "static/tabbar/order-select.png" "selectedIconPath": "static/tabbar/order-select.png"
}, },
// {
// "pagePath": "pages/tabbar/flowStatistics",
// "text": "流水统计",
// "iconPath": "static/tabbar/order.png",
// "selectedIconPath": "static/tabbar/order-select.png"
// },
// {
// "pagePath": "pages/tabbar/individualOrder",
// "text": "订单",
// "iconPath": "static/tabbar/order.png",
// "selectedIconPath": "static/tabbar/order-select.png"
// },
{ {
"pagePath": "pages/tabbar/my", "pagePath": "pages/tabbar/my",
"text": "我的", "text": "我的",
+163 -163
View File
@@ -1,215 +1,215 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref, reactive } from "vue"; import { ref, reactive } from "vue"
import { onLoad, onShow } from "@dcloudio/uni-app"; import { onLoad } from "@dcloudio/uni-app"
import { isEmpty, max, min } from "radash" import { isEmpty, max, min } from "radash"
import dayjs from "dayjs" import dayjs from "dayjs"
import { hooks, router } from "@@/index" import { router } from "@@/index"
import { boxesApi } from "@@/api" import { boxesApi } from "@@/api"
const data = {
}
const state = reactive<any>({ const state = reactive<any>({
detailType: "add", detailType: "add",
detailId: null, detailId: null,
detail: null, detail: null,
rechargeList: [], rechargeList: [],
selectRechargeList: [], selectRechargeList: [],
selectRechargeIdList: [], selectRechargeIdList: [],
pickerDate: { pickerDate: {
start: "", start: "",
end: "", end: "",
} },
}) })
const applyForm = reactive<any>({ const applyForm = reactive<any>({
displayTimeRange: "", displayTimeRange: "",
displayTimeRangeStr: "", displayTimeRangeStr: "",
bxDate: null, bxDate: null,
}) })
const applyFormRules = reactive<any>({ const applyFormRules = reactive<any>({
bxDate: [ bxDate: [{ required: true, message: "预约时间不能为空" }],
{ required: true, message: '预约时间不能为空' }
],
}) })
onLoad((options: any) => { onLoad((options: any) => {
const { type, id } = options const { type, id } = options
if (!isEmpty(type)) state.detailType = type if (!isEmpty(type)) state.detailType = type
if (!isEmpty(id)) state.detailId = id if (!isEmpty(id)) state.detailId = id
if (type === 'view') { if (type === "view") {
getDetail() getDetail()
} }
const today = dayjs() const today = dayjs()
state.pickerDate.start = dayjs().format('YYYY-MM-DD') state.pickerDate.start = dayjs().format("YYYY-MM-DD")
state.pickerDate.end = today.add(2, 'month').format('YYYY-MM-DD') state.pickerDate.end = today.add(2, "month").format("YYYY-MM-DD")
applyForm.bxDate = state.pickerDate.start applyForm.bxDate = state.pickerDate.start
getDateRange() getDateRange()
});
onShow(() => {
}) })
const getDetail = async () => { const getDetail = async () => {
if (isEmpty(state.detailId)) return if (isEmpty(state.detailId)) return
const _pa = { id: state.detailId } const _pa = { id: state.detailId }
const { data } = await boxesApi.detail(_pa) const { data } = await boxesApi.detail(_pa)
if (!isEmpty(data)) { if (!isEmpty(data)) {
state.detail = data state.detail = data
} }
} }
const getDateRange = async () => { const getDateRange = async () => {
const _pa = { id: state.detailId, currentDate: applyForm.bxDate } const _pa = { id: state.detailId, currentDate: applyForm.bxDate }
const { data } = await boxesApi.get(_pa) const { data } = await boxesApi.get(_pa)
data.avaliabilityRespList.forEach(v => { data.avaliabilityRespList.forEach((v) => {
v.dateTime = `${v.bxDate} ${v.hour}` v.dateTime = `${v.bxDate} ${v.hour}`
v.timestamp = dayjs(v.dateTime).valueOf() v.timestamp = dayjs(v.dateTime).valueOf()
}); })
state.rechargeList = data.avaliabilityRespList state.rechargeList = data.avaliabilityRespList
} }
const bxDateConfirm = async (e: any) => { const bxDateConfirm = async (e: any) => {
getDateRange() getDateRange()
} }
const doTimeItem = (v: any) => { const doTimeItem = (v: any) => {
if (v.status == 1) { if (v.status == 1) {
uni.showToast({ title: '该时间段已被预约', icon: "none" }) uni.showToast({ title: "该时间段已被预约", icon: "none" })
return return
} }
const flag = state.selectRechargeList.some(i => i.id == v.id) const flag = state.selectRechargeList.some((i) => i.id == v.id)
if (flag) { if (flag) {
state.selectRechargeList = state.selectRechargeList.filter(i => i.id != v.id) state.selectRechargeList = state.selectRechargeList.filter((i) => i.id != v.id)
if (state.selectRechargeList.length >= 2) { if (state.selectRechargeList.length >= 2) {
const { timestamp: targetMin } = min(state.selectRechargeList, (i: any) => i.timestamp) const { timestamp: targetMin } = min(state.selectRechargeList, (i: any) => i.timestamp)
state.rechargeList.forEach(i => { state.rechargeList.forEach((i) => {
if (i.timestamp <= v.timestamp) { if (i.timestamp <= v.timestamp) {
state.selectRechargeList = state.selectRechargeList.filter(j => j.id != i.id) state.selectRechargeList = state.selectRechargeList.filter((j) => j.id != i.id)
} }
}) })
} }
} else { } else {
state.selectRechargeList.push({ ...v }) state.selectRechargeList.push({ ...v })
if (state.selectRechargeList.length >= 2) { if (state.selectRechargeList.length >= 2) {
const { timestamp: targetMax } = max(state.selectRechargeList, (i: any) => i.timestamp) const { timestamp: targetMax } = max(state.selectRechargeList, (i: any) => i.timestamp)
const { timestamp: targetMin } = min(state.selectRechargeList, (i: any) => i.timestamp) const { timestamp: targetMin } = min(state.selectRechargeList, (i: any) => i.timestamp)
state.rechargeList.forEach(i => { state.rechargeList.forEach((i) => {
if (i.timestamp >= targetMin && i.timestamp <= targetMax) { if (i.timestamp >= targetMin && i.timestamp <= targetMax) {
state.selectRechargeList.push({ ...i }) state.selectRechargeList.push({ ...i })
} }
}) })
} }
} }
state.selectRechargeIdList = state.selectRechargeList.map(v => v.id) state.selectRechargeIdList = state.selectRechargeList.map((v) => v.id)
} }
const applyFormRef = ref<any>(null) const applyFormRef = ref<any>(null)
const doSubmit = async () => { const doSubmit = async () => {
applyFormRef.value.submit() applyFormRef.value.submit()
const { isPass } = applyFormRef.value.validate() const { isPass } = applyFormRef.value.validate()
if (!isPass) return if (!isPass) return
try { try {
const { hour: hourMax } = max(state.selectRechargeList, (i: any) => i.timestamp) const { hour: hourMax } = max(state.selectRechargeList, (i: any) => i.timestamp)
const { hour: hourMin } = min(state.selectRechargeList, (i: any) => i.timestamp) const { hour: hourMin } = min(state.selectRechargeList, (i: any) => i.timestamp)
const _pa = { const _pa = {
boxesId: state.detailId, boxesId: state.detailId,
startTime: hourMin, startTime: hourMin,
endTime: hourMax, endTime: hourMax,
bxDate: applyForm.bxDate, bxDate: applyForm.bxDate,
} }
const { data, code }: any = await boxesApi.apply(_pa) const { data, code }: any = await boxesApi.apply(_pa)
if (code != 0) throw new Error() if (code != 0) throw new Error()
uni.showLoading({ title: '预定中...', mask: false }) uni.showLoading({ title: "预定中...", mask: false })
uni.hideLoading() uni.hideLoading()
uni.showToast({ title: '申请成功', icon: "none" }) uni.showToast({ title: "申请成功", icon: "none" })
router.jump("/pages/boxes/apply-list") router.jump("/pages/boxes/apply-list")
} catch (error) { } catch (error) {
console.error(error); console.error(error)
uni.hideLoading() uni.hideLoading()
} }
} }
</script> </script>
<template> <template>
<crud-layout title="预定" mainIsScroll bg="/static/page/blue-bg.png"> <crud-layout title="预定" mainIsScroll bg="/static/page/blue-bg.png">
<view class="h-30rpx" /> <view class="h-30rpx" />
<view class="card p-x-30rpx p-y-40rpx"> <view class="card p-x-30rpx p-y-40rpx">
<tm-form ref="applyFormRef" v-model="applyForm" :rules="applyFormRules" direction="vertical"> <tm-form ref="applyFormRef" v-model="applyForm" :rules="applyFormRules" direction="vertical">
<tm-form-item name="bxDate" label="预约时间" :showBottom="false"> <tm-form-item name="bxDate" label="预约时间" :showBottom="false">
<tm-picker-date v-model="applyForm.bxDate" :start="state.pickerDate.start" <tm-picker-date
:end="state.pickerDate.end" v-model:model-str="applyForm.bxDate" format="YYYY-MM-DD" v-model="applyForm.bxDate"
@confirm="bxDateConfirm"> :start="state.pickerDate.start"
<view :style="{ pointerEvents: state.detailType == 'view' ? 'auto' : 'none' }"> :end="state.pickerDate.end"
<tm-input v-model="applyForm.bxDate" disabled placeholder="请选择使用时间.."> v-model:model-str="applyForm.bxDate"
<template v-slot:rightIcon> format="YYYY-MM-DD"
<text v-if="state.detailType != 'view'" @confirm="bxDateConfirm"
class="p-0.5rem color-#b1b1b1 iconfont icon-xiangxiajiantouxiao"></text> >
</template> <view :style="{ pointerEvents: state.detailType == 'view' ? 'auto' : 'none' }">
</tm-input> <tm-input v-model="applyForm.bxDate" disabled placeholder="请选择使用时间..">
</view> <template v-slot:rightIcon>
</tm-picker-date> <text v-if="state.detailType != 'view'" class="p-0.5rem color-#b1b1b1 iconfont icon-xiangxiajiantouxiao"></text>
</tm-form-item> </template>
</tm-form> </tm-input>
</view> </view>
<view class="prefix_title m-t-35rpx">时间段</view> </tm-picker-date>
<view class="recharge p-30rpx bg-white rounded-20rpx m-t-20rpx shadow-main"> </tm-form-item>
<view </tm-form>
:class="[state.selectRechargeIdList.includes(v.id) ? 'recharge_item_active' : '', v.status == 1 ? 'recharge_item_disabled' : '']" </view>
class="recharge_item" v-for="(v, i) in state.rechargeList" :key="i" @tap="doTimeItem(v)"> <view class="prefix_title m-t-35rpx ml-4">时间段</view>
<text class="sub-text-24 text-center">{{ v.bxDate }}</text> <view class="recharge p-30rpx bg-white rounded-20rpx m-t-20rpx shadow-main">
<text class="sub-text-24 text-center">{{ v.hour }}</text> <view
</view> :class="[state.selectRechargeIdList.includes(v.id) ? 'recharge_item_active' : '', v.status == 1 ? 'recharge_item_disabled' : '']"
</view> class="recharge_item"
<template #main-bottom> v-for="(v, i) in state.rechargeList"
<view v-if="state.detailType != 'view'" :key="i"
class="bg-#0094ff p-y-20rpx text-center rounded-40rpx m-x-30rpx m-y-30rpx sub-text-30 color-white!" @tap="doTimeItem(v)"
@tap="doSubmit"> >
提交 <text class="sub-text-24 text-center">{{ v.bxDate }}</text>
</view> <text class="sub-text-24 text-center">{{ v.hour }}</text>
</template> </view>
</crud-layout> </view>
<template #main-bottom>
<view
v-if="state.detailType != 'view'"
class="bg-#0094ff p-y-20rpx text-center rounded-40rpx m-x-30rpx m-y-30rpx sub-text-30 color-white!"
@tap="doSubmit"
>
提交
</view>
</template>
</crud-layout>
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped>
:deep() { :deep() {
.tmFormItemLabel { .tmFormItemLabel {
padding-bottom: 10rpx !important; padding-bottom: 10rpx !important;
} }
} }
.recharge_item_active { .recharge_item_active {
background: #e9f5fe; background: #e9f5fe;
border: 1px solid #e9f5fe !important; border: 1px solid #e9f5fe !important;
&>text { & > text {
color: #0094ff !important; color: #0094ff !important;
} }
} }
.recharge_item_disabled { .recharge_item_disabled {
background: #999; background: #999;
border: 1px solid #999 !important; border: 1px solid #999 !important;
&>text { & > text {
color: white !important; color: white !important;
} }
} }
.recharge { .recharge {
display: grid; display: grid;
grid-template-columns: repeat(3, 1fr); grid-template-columns: repeat(3, 1fr);
grid-gap: 15rpx; grid-gap: 15rpx;
border-bottom: 1px solid #f9f9f9; border-bottom: 1px solid #f9f9f9;
&_item { &_item {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
border: 1px solid #cccccc; border: 1px solid #cccccc;
border-radius: 16rpx; border-radius: 16rpx;
padding: 20rpx 0; padding: 20rpx 0;
} }
} }
</style> </style>
+49 -54
View File
@@ -1,83 +1,78 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref, reactive } from "vue"; import { reactive } from "vue"
import { onLoad, onShow } from "@dcloudio/uni-app"; import { onLoad, onShow } from "@dcloudio/uni-app"
import { isEmpty } from "radash" import { isEmpty } from "radash"
import { hooks, router } from "@@/index" import { router } from "@@/index"
import { boxesApi } from "@@/api" import { boxesApi } from "@@/api"
import zSwiper from "@zebra-ui/swiper/components/z-swiper/z-swiper.vue" import zSwiper from "@zebra-ui/swiper/components/z-swiper/z-swiper.vue"
import zSwiperItem from "@zebra-ui/swiper/components/z-swiper-item/z-swiper-item.vue" import zSwiperItem from "@zebra-ui/swiper/components/z-swiper-item/z-swiper-item.vue"
import { filePath } from "@/sheep/utils/file"
const data = {
}
const state = reactive<any>({ const state = reactive<any>({
detailId: null, detailId: null,
detail: {}, detail: {},
}) })
onLoad((options: any) => { onLoad((options: any) => {
if (!isEmpty(options.id)) { if (!isEmpty(options.id)) {
state.detailId = options.id state.detailId = options.id
} }
}); })
onShow(() => { onShow(() => {
getDetail() getDetail()
}) })
const getDetail = async () => { const getDetail = async () => {
const _pa = { id: state.detailId } const _pa = { id: state.detailId }
const { data } = await boxesApi.detail(_pa) const { data } = await boxesApi.detail(_pa)
state.detail = data state.detail = data
state.detail.imagesArray = data.images?.split(",") state.detail.imagesArray = data.images?.split(",")
} }
const doSubmit = () => { const doSubmit = () => {
router.jump('/pages/boxes/apply', { id: state.detail.id }) router.jump("/pages/boxes/apply", { id: state.detail.id })
} }
</script> </script>
<template> <template>
<crud-layout title="" mainIsScroll tabBarType="just-flot-back" bg="/static/page/blue-bg.png"> <crud-layout mainIsScroll tabBarType="just-flot-back" bg="/static/page/blue-bg.png">
<z-swiper> <z-swiper>
<z-swiper-item v-for="(v, i) in state.detail.imagesArray" :key="i"> <z-swiper-item v-for="(v, i) in state.detail.imagesArray" :key="i">
<image class="w-100vw" :src="v" mode="widthFix" /> <image class="w-100vw" :src="filePath(v)" mode="widthFix" />
</z-swiper-item> </z-swiper-item>
</z-swiper> </z-swiper>
<view class="p-x-15rpx"> <view class="p-x-15rpx">
<view class="flex-col justify-between card p-y-20rpx p-x-30rpx"> <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 justify-between">
<view class="flex-row items-center"> <view class="flex-row items-center">
<view class="second-text-46 color-#f63a36!">¥{{ state.detail.price }}</view> <view class="second-text-46 color-#f63a36!">¥{{ state.detail.price }}</view>
</view> </view>
<view class="second-text-26">可容纳{{ state.detail.capacity }}</view> <view class="second-text-26">可容纳{{ state.detail.capacity }}</view>
</view> </view>
<view class="flex-col m-t-15rpx"> <view class="flex-col m-t-15rpx">
<view class="sub-text-32">{{ state.detail.name }}</view> <view class="sub-text-32">{{ state.detail.name }}</view>
</view> </view>
</view> </view>
<view class="h-15rpx" /> <view class="h-15rpx" />
<view class="flex-col justify-between card p-y-20rpx p-x-30rpx"> <view class="flex-col justify-between card p-y-20rpx p-x-30rpx">
<view class="prefix_title">详情</view> <view class="prefix_title">详情</view>
<view class="m-t-15rpx" v-html="state.detail.description"></view> <view class="m-t-15rpx" v-html="state.detail.description"></view>
</view> </view>
</view> </view>
<template #main-bottom> <template #main-bottom>
<view class="bg-#0094ff p-y-20rpx text-center rounded-40rpx m-x-60rpx m-y-30rpx sub-text-30 color-white!" <view class="bg-#0094ff p-y-20rpx text-center rounded-40rpx m-x-60rpx m-y-30rpx sub-text-30 color-white!" @tap="doSubmit">
@tap="doSubmit"> 预定
预定 </view>
</view> </template>
</template> </crud-layout>
</crud-layout>
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped>
:deep() { :deep() {
.layout_main>scroll-view { .layout_main > scroll-view {
padding: 0 !important; padding: 0 !important;
} }
} }
</style> </style>
+13 -5
View File
@@ -1,5 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref, reactive } from "vue" import { ref, reactive, computed } from "vue"
import { onLoad, onShow } from "@dcloudio/uni-app" import { onLoad, onShow } from "@dcloudio/uni-app"
import { isEmpty } from "radash" import { isEmpty } from "radash"
@@ -8,6 +8,7 @@ import { boxesApi } from "@@/api"
import zTabs from "@@/components/other/z-tabs/z-tabs.vue" import zTabs from "@@/components/other/z-tabs/z-tabs.vue"
import CustomWaterfallsFlow from "@@/components/other/custom-waterfalls-flow/custom-waterfalls-flow.vue" import CustomWaterfallsFlow from "@@/components/other/custom-waterfalls-flow/custom-waterfalls-flow.vue"
import { filePath } from "@/sheep/utils/file"
const data = { const data = {
tabs: [ tabs: [
@@ -25,6 +26,13 @@ const state = reactive<any>({
}, },
}) })
// 重新设置图片路径
const boxesList = computed(() => {
return pageHook.list.map((item: any) => {
return { ...item, images: filePath(item.images) }
})
})
const pageRef = ref<any>(null) const pageRef = ref<any>(null)
const pageHook = hooks.usePage(pageRef, boxesApi.page, null, "data.records") const pageHook = hooks.usePage(pageRef, boxesApi.page, null, "data.records")
const query = (page: number, pagesize: number) => { const query = (page: number, pagesize: number) => {
@@ -61,7 +69,7 @@ const doCard = (v: any) => {
height="100%" height="100%"
:fixed="false" :fixed="false"
v-model="pageHook.list" v-model="pageHook.list"
:default-page-size="5" :default-page-size="999"
safe-area-inset-bottom safe-area-inset-bottom
:loading-more-enabled="true" :loading-more-enabled="true"
:show-scrollbar="false" :show-scrollbar="false"
@@ -76,16 +84,16 @@ const doCard = (v: any) => {
</view> </view>
</template> </template>
<view class="h-20rpx" /> <view class="h-20rpx" />
<custom-waterfalls-flow v-model="pageHook.list" imageKey="images" :columnSpace="1" @wapperClick="doCard" @imageClick="doCard"> <custom-waterfalls-flow v-model="boxesList" imageKey="images" :columnSpace="1" @wapperClick="doCard" @imageClick="doCard">
<template v-slot:default="v"> <template v-slot:default="v">
<view class="p-x-15rpx p-t-10rpx p-b-20rpx"> <view class="p-x-15rpx p-t-10rpx p-b-20rpx">
<view class="sub-text-28 show-line">{{ v.name }}</view> <view class="sub-text-28 show-line">{{ v.name }}</view>
<view class="m-t-10rpx flex-row items-center"> <view class="m-t-10rpx flex-row items-center">
<view class="second-text-32 color-#f63a36!"> ¥{{ v.price }} </view> <view class="second-text-32 color-#f63a36!"> ¥{{ v.price }} </view>
</view> </view>
<view class="flex-row items-center m-t-10rpx"> <view class="flex-row items-center justify-between m-t-10rpx">
<view class="second-text-26">可容纳{{ v.capacity }}人</view> <view class="second-text-26">可容纳{{ v.capacity }}人</view>
<view class="w-1px h-20rpx m-x-5rpx bg-#999" /> <view class="w-2rpx h-20rpx m-x-5rpx bg-#999" />
<view class="flex-row-center"> <view class="flex-row-center">
<tm-tag v-if="v.status == 0" size="xs" color="success"> <tm-tag v-if="v.status == 0" size="xs" color="success">
{{ hooks.useEnum("boxesBxStatusEnum", v.status.toString()) }} {{ hooks.useEnum("boxesBxStatusEnum", v.status.toString()) }}
+2 -6
View File
@@ -72,7 +72,7 @@ const doDel = (id: string) => {
<text class="font-600">{{ v.username }}</text> <text class="font-600">{{ v.username }}</text>
</div> </div>
<div class="flex items-center"> <div class="flex items-center">
<text class="botder_btn" @click="doEdit(v.id)">修改</text> <!-- <text class="botder_btn" @click="doEdit(v.id)">修改</text> -->
<view class="w-30rpx" /> <view class="w-30rpx" />
<tm-modal v-if="false" title="确定删除吗?" height="auto" @confirm="doDel(v.id)"> <tm-modal v-if="false" title="确定删除吗?" height="auto" @confirm="doDel(v.id)">
<template v-slot:trigger><text class="botder_btn">删除</text></template> <template v-slot:trigger><text class="botder_btn">删除</text></template>
@@ -81,11 +81,7 @@ const doDel = (id: string) => {
</view> </view>
</view> </view>
<template #bottom> <template #bottom>
<view <view v-if="false" class="bg-#0094ff p-y-20rpx text-center rounded-40rpx m-x-30rpx m-t-60rpx sub-text-30 color-white!" @tap="doAdd">
v-if="false"
class="bg-#0094ff p-y-20rpx text-center rounded-40rpx m-x-30rpx m-t-60rpx sub-text-30 color-white!"
@tap="doAdd"
>
添加 添加
</view> </view>
<view class="h-30rpx" /> <view class="h-30rpx" />
+27 -22
View File
@@ -1,5 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref, reactive, nextTick } from "vue" import { reactive, nextTick } from "vue"
import { onLoad, onShow } from "@dcloudio/uni-app" import { onLoad, onShow } from "@dcloudio/uni-app"
import { isEmpty } from "radash" import { isEmpty } from "radash"
@@ -15,7 +15,6 @@ import ProductRow from "./components/product-row.vue"
import ProductCar from "./components/product-car.vue" import ProductCar from "./components/product-car.vue"
import ProductTotal from "./components/product-total.vue" import ProductTotal from "./components/product-total.vue"
const data = {}
const state = reactive<any>({ const state = reactive<any>({
detailId: null, detailId: null,
totPrice: 0, totPrice: 0,
@@ -41,9 +40,14 @@ onShow(() => {
}) })
const getDetail = async () => { const getDetail = async () => {
uni.showLoading({
title: "加载中...",
mask: true,
})
const _pa = { id: state.detailId } const _pa = { id: state.detailId }
const { data } = await merchantApi.detail(_pa) const { data } = await merchantApi.detail(_pa)
state.detail = data state.detail = data
uni.hideLoading()
} }
const getShopCar = async () => { const getShopCar = async () => {
@@ -201,7 +205,7 @@ const getHeight = () => {
const doPhone = () => { const doPhone = () => {
if (isEmpty(state.detail.phone)) { if (isEmpty(state.detail.phone)) {
uni.showToast({ title: "该店铺没有预留电话", icon: "none" }) uni.showToast({ title: "该商户没有预留电话", icon: "none" })
return return
} }
hooks.useMakePhoneCall(state.detail.phone) hooks.useMakePhoneCall(state.detail.phone)
@@ -226,26 +230,30 @@ const doFood = () => {
<!-- start 简介 start --> <!-- start 简介 start -->
<view class="h-15rpx" /> <view class="h-15rpx" />
<view flex-row card p-20rpx> <view flex-row card p-20rpx>
<image class="w-160rpx h-160rpx rounded-12rpx" :src="filePath(state.detail.logoPic)" mode="aspectFill" /> <image class="w-180rpx h-180rpx rounded-12rpx" :src="filePath(state.detail.logoPic)" mode="aspectFill" />
<view class="flex-1 flex-col m-l-20rpx"> <view class="flex-1 flex-col m-l-20rpx">
<view class="flex-row items-center justify-between"> <view class="flex-row items-center justify-between">
<view class="flex-row-center sub-text-36"> <view class="flex-row-center sub-text-34">
<text>{{ state.detail.name }}</text> <text>{{ state.detail.name }}</text>
</view> </view>
<view> <view>
<tm-tag size="s">{{ state.detail.deptName }}</tm-tag> <tm-tag size="s">{{ state.detail.deptName }}</tm-tag>
</view> </view>
</view> </view>
<view class="m-t-10rpx second-text-28"> <view class="second-text-24">
<text>营业时间</text> <view class="second-text-28">营业时间:</view>
<text class="m-l-10rpx"> <view>
{{ state.detail.jobStartTime }} {{ state.detail.jobTime?.split(",")[0] ? "早:" + state.detail.jobTime?.split(",")[0] : "" }}
~ </view>
{{ state.detail.jobEndTime }} <view>
</text> {{ state.detail.jobTime?.split(",")[1] ? "中:" + state.detail.jobTime?.split(",")[1] : "" }}
</view>
<view>
{{ state.detail.jobTime?.split(",")[2] ? "晚:" + state.detail.jobTime?.split(",")[2] : "" }}
</view>
</view> </view>
<view class="m-t-10rpx second-text-28"> <view v-if="state.detail.addressDes" class="m-t-10rpx second-text-28">
<text>食堂地址</text> <text>食堂地址:</text>
<text class="m-l-10rpx">{{ state.detail.addressDes }}</text> <text class="m-l-10rpx">{{ state.detail.addressDes }}</text>
</view> </view>
</view> </view>
@@ -283,6 +291,7 @@ const doFood = () => {
<view class="h-15rpx" /> <view class="h-15rpx" />
<view class="flex-row"> <view class="flex-row">
<scroll-view <scroll-view
v-if="state.classifyList.length > 0"
scroll-y scroll-y
:style="{ height: getHeight() }" :style="{ height: getHeight() }"
class="menu w-200rpx h-full p-l-12rpx p-b-20rpx bg-#f6f6f6" class="menu w-200rpx h-full p-l-12rpx p-b-20rpx bg-#f6f6f6"
@@ -299,7 +308,7 @@ const doFood = () => {
</view> </view>
</view> </view>
</scroll-view> </scroll-view>
<scroll-view scroll-y :style="{ height: getHeight() }" class="flex-1 p-b-20rpx"> <scroll-view v-if="state.shopList.length > 0" scroll-y :style="{ height: getHeight() }" class="flex-1 p-b-20rpx">
<view v-for="(pV, pI) in state.shopList" :key="pI"> <view v-for="(pV, pI) in state.shopList" :key="pI">
<view class="m-x-15rpx"> <view class="m-x-15rpx">
<product-row <product-row
@@ -318,17 +327,13 @@ const doFood = () => {
</view> </view>
</view> </view>
</scroll-view> </scroll-view>
<view v-else class="mx-auto mt-10 second-text-28">暂无信息</view>
</view> </view>
</tm-sticky> </tm-sticky>
<!-- end 商品 end --> <!-- end 商品 end -->
<template #main-bottom> <template #main-bottom>
<view class="car z-200 p-x-30rpx p-y-30rpx bg-white"> <view v-if="state.classifyList.length > 0" class="car z-200 p-x-30rpx p-y-30rpx bg-white">
<product-total <product-total :totPrice="state.totPrice" :totCount="state.totCount" @doContainer="doVisibleCar" @submit="doPay" />
:totPrice="state.totPrice"
:totCount="state.totCount"
@doContainer="doVisibleCar"
@submit="doPay"
/>
</view> </view>
</template> </template>
</crud-layout> </crud-layout>
+55 -18
View File
@@ -1,19 +1,19 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref, reactive, computed, watch } from "vue" import { ref, reactive, computed } from "vue"
import { onLoad, onShow } from "@dcloudio/uni-app" import { onLoad, onShow } from "@dcloudio/uni-app"
import { isEmpty } from "radash" import { isEmpty } from "radash"
import dayjs from "dayjs" import dayjs from "dayjs"
import { hooks, router } from "@@/index" import { hooks, router } from "@@/index"
import { foodApi } from "@@/api" import { foodApi } from "@@/api"
import zTabs from "@@/components/other/z-tabs/z-tabs.vue" import zTabs from "@@/components/other/z-tabs/z-tabs.vue"
import CustomWaterfallsFlow from "@@/components/other/custom-waterfalls-flow/custom-waterfalls-flow.vue" import { LazyImg, Waterfall } from "vue-waterfall-plugin-next"
import "vue-waterfall-plugin-next/dist/style.css"
// import CustomWaterfallsFlow from "@@/components/other/custom-waterfalls-flow/custom-waterfalls-flow.vue"
import { filePath } from "@@/utils/file" import { filePath } from "@@/utils/file"
const data = { const menus = {
tabs: [ tabs: [
{ id: null, name: "全部", disabled: false }, // { id: null, name: "全部", disabled: false },
{ id: 1, name: "早餐", disabled: false }, { id: 1, name: "早餐", disabled: false },
{ id: 2, name: "午餐", disabled: false }, { id: 2, name: "午餐", disabled: false },
{ id: 3, name: "晚餐", disabled: false }, { id: 3, name: "晚餐", disabled: false },
@@ -26,7 +26,7 @@ const state = reactive<any>({
pa: { pa: {
merchantId: null, merchantId: null,
startTime: null, startTime: null,
hourType: data.tabs[0].id, hourType: menus.tabs[0].id,
}, },
}) })
@@ -60,7 +60,7 @@ const initDate = () => {
const now = new Date() const now = new Date()
for (let i = 0; i < 10; i++) { for (let i = 0; i < 10; i++) {
const date = dayjs(now).add(i, "d") const date = dayjs(now).add(i, "d")
const weekDayStr = date.isSame(now, "day") ? "今天" : data.weekDays[date.day()] const weekDayStr = date.isSame(now, "day") ? "今天" : menus.weekDays[date.day()]
list.push({ list.push({
weekDayStr, weekDayStr,
date: date.toDate(), date: date.toDate(),
@@ -76,17 +76,19 @@ const initDate = () => {
const doDateItem = (v: any, i: any) => { const doDateItem = (v: any, i: any) => {
state.currentDateIndex = i state.currentDateIndex = i
state.pa.startTime = state.dateList[i].dateTime state.pa.startTime = state.dateList[i].dateTime
pageHook.list = []
pageRef.value.reload(true) pageRef.value.reload(true)
} }
const doTab = (e: any) => { const doTab = (e: any) => {
const target = data.tabs[e] const target = menus.tabs[e]
state.pa.hourType = target.id state.pa.hourType = target.id
pageHook.list = []
pageRef.value.reload(true) pageRef.value.reload(true)
} }
const doProduct = (v: any) => { const doProduct = (v: any) => {
router.jump("/pages/merchant/product-detail", { id: v.spuId }) // router.jump("/pages/merchant/product-detail", { spuId: v.spuId })
} }
</script> </script>
@@ -97,7 +99,7 @@ const doProduct = (v: any) => {
height="100%" height="100%"
:fixed="false" :fixed="false"
v-model="pageHook.list" v-model="pageHook.list"
:default-page-size="5" :default-page-size="8"
safe-area-inset-bottom safe-area-inset-bottom
:loading-more-enabled="true" :loading-more-enabled="true"
:show-scrollbar="false" :show-scrollbar="false"
@@ -107,7 +109,7 @@ const doProduct = (v: any) => {
@scroll="pageHook.scroll" @scroll="pageHook.scroll"
> >
<template #top> <template #top>
<view class="bg-#1777FF p-15rpx pt-10"> <view class="bg-#1777FF p-15rpx">
<scroll-view scroll-x class="whitespace-nowrap"> <scroll-view scroll-x class="whitespace-nowrap">
<view class="flex-row items-center space-x-15rpx"> <view class="flex-row items-center space-x-15rpx">
<view <view
@@ -117,19 +119,54 @@ const doProduct = (v: any) => {
:key="i" :key="i"
@tap="doDateItem(v, i)" @tap="doDateItem(v, i)"
> >
<view class="">{{ v.dayTime }}</view> <view>{{ v.dayTime }}</view>
<view class="">{{ v.weekDayStr }}</view> <view>{{ v.weekDayStr }}</view>
</view> </view>
</view> </view>
</scroll-view> </scroll-view>
</view> </view>
<view class="bg-white rounded-16rpx px-20rpx m-x-10rpx m-t-15rpx"> <view class="bg-white rounded-16rpx px-20rpx m-x-10rpx m-t-15rpx">
<z-tabs :list="data.tabs" @change="doTab" /> <z-tabs :list="menus.tabs" @change="doTab" />
</view> </view>
</template> </template>
<view class="h-20rpx" /> <view class="h-20rpx" />
<view class="m-x-10rpx">
<custom-waterfalls-flow v-model="foodList" imageKey="picUrl" :columnSpace="1" @wapperClick="doProduct" @imageClick="doProduct"> <view class="m-x-20rpx">
<Waterfall
v-if="foodList.length"
:list="foodList"
:gutter="10"
:breakpoints="{
1200: { rowPerView: 4 },
800: { rowPerView: 3 },
375: { rowPerView: 2 },
}"
:hasAroundGutter="false"
backgroundColor="#ffffff00"
:crossOrigin="false"
:animationDuration="100"
>
<template #default="{ item, url, index }">
<div class="card">
<LazyImg class="rounded-2" :url="item.picUrl" />
<view class="p-x-15rpx p-y-25rpx">
<view class="sub-text-28 show-line">{{ item.name }}</view>
<view class="m-t-10rpx flex-row items-center">
<view class="second-text-32 color-#f63a36!"> ¥{{ hooks.useMoney(item.price) }} </view>
<view class="m-l-20rpx second-text-24 line-through"> ¥{{ hooks.useMoney(item.marketPrice) }} </view>
</view>
<view class="flex-row items-center">
<view class="second-text-24">{{ hooks.useFormatNum("库存", "", item.stock) }}</view>
<view class="w-1px h-20rpx m-x-5rpx bg-#999" />
<view class="second-text-24">{{ hooks.useFormatNum("销量", "", item.salesCount) }}</view>
</view>
</view>
</div>
</template>
</Waterfall>
<!-- <custom-waterfalls-flow v-model="foodList" imageKey="picUrl" :columnSpace="1" @wapperClick="doProduct" @imageClick="doProduct">
<template v-slot:default="v"> <template v-slot:default="v">
<view class="p-x-15rpx p-y-25rpx"> <view class="p-x-15rpx p-y-25rpx">
<view class="sub-text-28 show-line">{{ v.name }}</view> <view class="sub-text-28 show-line">{{ v.name }}</view>
@@ -144,7 +181,7 @@ const doProduct = (v: any) => {
</view> </view>
</view> </view>
</template> </template>
</custom-waterfalls-flow> </custom-waterfalls-flow> -->
</view> </view>
</z-paging> </z-paging>
</crud-layout> </crud-layout>
+56 -70
View File
@@ -1,87 +1,73 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref, reactive } from "vue"; import { reactive } from "vue"
import { onLoad, onShow } from "@dcloudio/uni-app"; import { onLoad, onShow } from "@dcloudio/uni-app"
import { isEmpty } from "radash"; import { isEmpty } from "radash"
import { hooks } from "@@/index"
import { productApi } from "@@/api"
import { filePath } from "@@/utils/file"
import zSwiper from "@zebra-ui/swiper/components/z-swiper/z-swiper.vue"
import zSwiperItem from "@zebra-ui/swiper/components/z-swiper-item/z-swiper-item.vue"
import { hooks } from "@@/index";
import { productApi } from "@@/api";
import { filePath } from "@@/utils/file";
import zSwiper from "@zebra-ui/swiper/components/z-swiper/z-swiper.vue";
import zSwiperItem from "@zebra-ui/swiper/components/z-swiper-item/z-swiper-item.vue";
const data = {};
const state = reactive<any>({ const state = reactive<any>({
detailId: null, detailId: null,
detail: null, detail: null,
}); })
onLoad((options: any) => { onLoad((options: any) => {
if (!isEmpty(options.id)) { if (!isEmpty(options.id)) {
state.detailId = options.id; state.detailId = options.id
} }
}); })
onShow(() => { onShow(() => {
getDetail(); getDetail()
}); })
const getDetail = async () => { const getDetail = async () => {
const _pa = { id: state.detailId }; uni.showLoading({
const { data } = await productApi.get(_pa); title: "加载中...",
state.detail = data; })
}; const _pa = { id: state.detailId }
const { data } = await productApi.get(_pa)
state.detail = data
uni.hideLoading()
}
</script> </script>
<template> <template>
<crud-layout <crud-layout title="订单详情" tabBarType="just-flot-back" bg="/static/page/blue-bg.png">
title="订单详情" <view v-if="state.detail">
tabBarType="just-flot-back" <image class="w-100vw" :src="filePath(state.detail.picUrl)" mode="widthFix" />
bg="/static/page/blue-bg.png" <view class="p-x-15rpx">
> <view class="flex-col justify-between card p-y-20rpx p-x-30rpx">
<image <view class="flex-row items-center justify-between">
class="w-100vw" <view class="flex-row items-center">
:src="filePath(state.detail.picUrl)" <view class="second-text-46 color-#f63a36!">¥{{ state.detail.price }}</view>
mode="widthFix" <view class="m-l-20rpx second-text-28 line-through">¥{{ state.detail.marketPrice }}</view>
/> </view>
<view class="p-x-15rpx"> <view class="second-text-26">已售{{ state.detail.salesCount }}</view>
<view class="flex-col justify-between card p-y-20rpx p-x-30rpx"> </view>
<view class="flex-row items-center justify-between"> <view class="flex-col m-t-15rpx">
<view class="flex-row items-center"> <view class="sub-text-32">{{ state.detail.name }}</view>
<view class="second-text-46 color-#f63a36!" <view class="m-t-15rpx second-text-26">{{ state.detail.introduction }}</view>
>¥{{ state.detail.price }}</view </view>
> </view>
<view class="m-l-20rpx second-text-28 line-through" <view v-if="false" class="m-t-15rpx flex-row items-center justify-between card p-y-20rpx p-x-30rpx">
>¥{{ state.detail.marketPrice }}</view <view class="prefix_title">评价</view>
> </view>
</view> <view v-if="state.detail.description" class="m-t-15rpx flex-col justify-between card p-y-20rpx p-x-30rpx">
<view class="second-text-26">已售{{ state.detail.salesCount }}</view> <view class="prefix_title">详情</view>
</view> <view class="m-t-15rpx" v-html="state.detail.description"></view>
<view class="flex-col m-t-15rpx"> </view>
<view class="sub-text-32">{{ state.detail.name }}</view> </view>
<view class="m-t-15rpx second-text-26">{{ </view>
state.detail.introduction <view v-else class="second-text-28 mt-24 text-center">暂无数据</view>
}}</view> </crud-layout>
</view>
</view>
<view
v-if="false"
class="m-t-15rpx flex-row items-center justify-between card p-y-20rpx p-x-30rpx"
>
<view class="prefix_title">评价</view>
</view>
<view v-if="state.detail.description" class="m-t-15rpx flex-col justify-between card p-y-20rpx p-x-30rpx">
<view class="prefix_title">详情</view>
<view class="m-t-15rpx" v-html="state.detail.description"></view>
</view>
</view>
</crud-layout>
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped>
:deep() { :deep() {
.layout_main > scroll-view { .layout_main > scroll-view {
padding: 0 !important; padding: 0 !important;
} }
} }
</style> </style>
+175
View File
@@ -0,0 +1,175 @@
<template>
<crud-layout bg="/static/page/blue-bg.png">
<view class="h-screen flex flex-col position-relative">
<view class="mx-auto text-34 py-2">支付</view>
<tm-sheet class="flex flex-row">
<span class="text-2xl text-[#333] mr-1 line-height-normal">¥</span>
<span class="text-3xl font-medium text-[#333]">{{ displayAmount }}</span>
</tm-sheet>
<tm-button class="mt-40" :block="true" @click="disabled ? '' : handlePay()" :disabled="disabled">支付</tm-button>
<view class="bg-[#f5f5f5] px-1 py-2 rounded-4 absolute bottom-0 w-full">
<view class="flex mb-2.5" v-for="(row, rowIndex) in keyboardLayout" :key="rowIndex">
<view
class="flex-1 h-[60px] flex items-center justify-center bg-white text-2xl text-[#333] mx-[5px] rounded-lg cursor-pointer select-none active:bg-[#f0f0f0]"
v-for="(key, keyIndex) in row"
:key="keyIndex"
@click="handleKeyPress(key)"
>
{{ key }}
</view>
</view>
<view class="flex mb-0">
<view
class="flex-1 h-[60px] flex items-center justify-center bg-white text-2xl text-[#333] mx-[5px] rounded-lg cursor-pointer select-none active:bg-[#f0f0f0]"
@click="handleKeyPress('.')"
>
.
</view>
<view
class="flex-auto h-[60px] flex items-center justify-center bg-white text-2xl text-[#333] mx-[5px] rounded-lg cursor-pointer select-none active:bg-[#f0f0f0]"
@click="handleKeyPress('0')"
>
0
</view>
<view
class="flex-1 h-[60px] flex items-center justify-center bg-white mx-[5px] rounded-lg cursor-pointer select-none active:bg-[#f0f0f0]"
@click="handleDelete"
>
<svg
t="1742457305987"
class="icon"
viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
p-id="4499"
width="24"
height="24"
>
<path
d="M897.706667 831.146667H286.72c-8.533333 0-15.36-3.413333-20.48-10.24L39.253333 527.36c-6.826667-8.533333-6.826667-22.186667 0-30.72l226.986667-293.546667c5.12-6.826667 11.946667-10.24 20.48-10.24h610.986667c51.2 0 92.16 40.96 92.16 92.16v453.973334c0 51.2-40.96 92.16-92.16 92.16z m-599.04-51.2h599.04c22.186667 0 40.96-18.773333 40.96-40.96V285.013333c0-22.186667-18.773333-40.96-40.96-40.96H298.666667L92.16 512l206.506667 267.946667z"
fill="#333333"
p-id="4500"
></path>
<path
d="M670.72 650.24c-6.826667 0-13.653333-1.706667-18.773333-6.826667L426.666667 416.426667c-10.24-10.24-10.24-25.6 0-35.84 10.24-10.24 25.6-10.24 35.84 0l226.986666 226.986666c10.24 10.24 10.24 25.6 0 35.84-6.826667 5.12-11.946667 6.826667-18.773333 6.826667z"
fill="#333333"
p-id="4501"
></path>
<path
d="M443.733333 650.24c-6.826667 0-13.653333-1.706667-18.773333-6.826667-10.24-10.24-10.24-25.6 0-35.84l226.986667-226.986666c10.24-10.24 25.6-10.24 35.84 0 10.24 10.24 10.24 25.6 0 35.84L462.506667 643.413333c-5.12 5.12-11.946667 6.826667-18.773334 6.826667z"
fill="#333333"
p-id="4502"
></path>
</svg>
</view>
</view>
</view>
</view>
</crud-layout>
</template>
<script setup lang="ts">
import { ref, computed } from "vue"
import { onShow } from "@dcloudio/uni-app"
import { usePayStore } from "@/sheep/stores/pay"
import payApi from "@@/api/pay"
import { storePrice } from "@/sheep/utils/formatMoney"
import { router } from "@/sheep"
const amount = ref("")
const keyboardLayout = ref([
["1", "2", "3"],
["4", "5", "6"],
["7", "8", "9"],
])
const scanData = ref<{ id?: string; name?: string }>({})
const disabled = ref(false)
onShow(() => {
scanData.value = usePayStore().payData
if (scanData.value.id && scanData.value.name) {
disabled.value = false
} else {
uni.showToast({ title: "扫码信息不存在", icon: "none" })
disabled.value = true
}
})
const displayAmount = computed(() => {
if (!amount.value) return "0"
return (
amount.value
// .toString()
// .toFixed(2)
.replace(/\B(?=(\d{3})+(?!\d))/g, ",")
)
})
// 按下键盘
const handleKeyPress = (key) => {
if (key === "." && amount.value.includes(".")) return
if (key === "." && !amount.value) {
amount.value = "0."
return
}
if (amount.value.includes(".")) {
const decimalPlaces = amount.value.split(".")[1]
if (decimalPlaces && decimalPlaces.length >= 2) return
}
amount.value += key
}
// 点击删除
const handleDelete = () => {
amount.value = amount.value.slice(0, -1)
}
// 点击支付
const handlePay = () => {
if (!scanData.value.id || !scanData.value.name) return uni.showToast({ title: "扫码信息不存在", icon: "none" })
if (!amount.value) {
uni.showToast({ title: "请输入金额", icon: "none" })
return
}
if (Number(amount.value) === 0) {
uni.showToast({ title: "金额不能为0", icon: "none" })
return
}
uni.showModal({
title: "确定支付吗?",
success: async (res) => {
if (res.confirm) {
await pay()
}
},
})
}
// handle pay
const pay = async () => {
try {
uni.showLoading({ title: "支付中...", mask: true })
const res = await payApi.createQrCodeOrder({
merchantId: scanData.value.id,
customPrice: storePrice(Number(amount.value)),
})
if (res.code != 0) {
throw new Error()
}
uni.showToast({ title: "支付成功", icon: "success" })
usePayStore().payData = {}
setTimeout(() => {
router.back()
uni.hideLoading()
}, 1000)
} catch (error: any) {
// uni.showToast({ title: "错误", icon: "error" })
uni.hideLoading()
}
}
</script>
+3 -19
View File
@@ -22,9 +22,7 @@ const state = reactive<any>({
selectList: [], selectList: [],
}) })
const uploadApplyPicUrls = ref<Array<Record<string, any> | string>>([]) // 补充凭证图片 const uploadApplyPicUrls = ref<Array<Record<string, any> | string>>([]) // 补充凭证图片
const applyPicUrls = computed(() => const applyPicUrls = computed(() => uploadApplyPicUrls.value.map((item: any) => JSON.parse(item.response).data.url).join(","))
uploadApplyPicUrls.value.map((item: any) => JSON.parse(item.response).data.url).join(","),
)
const applyForm = reactive<any>({ const applyForm = reactive<any>({
way: data.payType[0].type, way: data.payType[0].type,
@@ -154,14 +152,7 @@ const doSubmit = async () => {
<view class="sub-text-28">售后类型</view> <view class="sub-text-28">售后类型</view>
<view class="m-t-20rpx"> <view class="m-t-20rpx">
<tm-radio-group @change="radioChange" direction="column" gap="20" v-model="applyForm.way"> <tm-radio-group @change="radioChange" direction="column" gap="20" v-model="applyForm.way">
<tm-radio <tm-radio :disabled="v.disabled" v-for="(v, i) in data.payType" :key="i" v-show="v.visible" :value="v.type" :label="v.text" />
:disabled="v.disabled"
v-for="(v, i) in data.payType"
:key="i"
v-show="v.visible"
:value="v.type"
:label="v.text"
/>
</tm-radio-group> </tm-radio-group>
</view> </view>
</view> </view>
@@ -187,7 +178,6 @@ const doSubmit = async () => {
</tm-picker> </tm-picker>
</view> </view>
<view class="flex-col justify-center card p-x-20rpx p-y-30rpx m-b-20rpx"> <view class="flex-col justify-center card p-x-20rpx p-y-30rpx m-b-20rpx">
<<<<<<< HEAD
<view class="sub-text-28">补充凭证图片</view> <view class="sub-text-28">补充凭证图片</view>
<view class="m-t-20rpx"> <view class="m-t-20rpx">
<tm-upload-photo <tm-upload-photo
@@ -201,15 +191,9 @@ const doSubmit = async () => {
<view class="sub-text-20 c-red!">注:图片大小不超过5M,最多上传6张</view> <view class="sub-text-20 c-red!">注:图片大小不超过5M,最多上传6张</view>
</view> </view>
<view class="flex-col justify-center card p-x-20rpx p-y-30rpx m-b-20rpx"> <view class="flex-col justify-center card p-x-20rpx p-y-30rpx m-b-20rpx">
======= >>>>>>> c3eaafa5d0575ebd0fa74be0180c5cfe8a9901ea
<view class="sub-text-28">相关描述</view> <view class="sub-text-28">相关描述</view>
<view class="m-t-20rpx"> <view class="m-t-20rpx">
<tm-input <tm-input v-model="applyForm.remark" type="textarea" :showClear="false" placeholder="客官~请描述您遇到的问题"></tm-input>
v-model="applyForm.remark"
type="textarea"
:showClear="false"
placeholder="客官~请描述您遇到的问题"
></tm-input>
</view> </view>
</view> </view>
<view class="h-30rpx" /> <view class="h-30rpx" />
+27 -29
View File
@@ -14,24 +14,18 @@
<view class="h-15rpx" /> <view class="h-15rpx" />
<!-- start 简介 start --> <!-- start 简介 start -->
<view flex-row card p-20rpx> <view flex-row card p-20rpx>
<image class="w-120rpx h-120rpx rounded-12rpx" :src="filePath(state.detail.logoPic)" mode="aspectFill" /> <image class="w-180rpx h-180rpx rounded-12rpx" :src="filePath(state.detail.logoPic)" mode="aspectFill" />
<view class="flex-1 flex-col m-l-20rpx"> <view class="flex-1 flex-col m-l-20rpx">
<view class="flex-row items-center justify-between"> <view class="flex-row items-center justify-between">
<view class="flex-row-center sub-text-36"> <view class="flex-row-center sub-text-32">{{ state.detail.name }}</view>
<text>{{ state.detail.name }}</text> <tm-tag size="s">{{ state.detail.deptName }}</tm-tag>
</view>
<view>
<tm-tag size="s">{{ state.detail.deptName }}</tm-tag>
</view>
</view> </view>
<view class="second-text-28">{{ state.detail.phone }}</view> <view class="second-text-24">{{ state.detail.phone }}</view>
<view class="m-t-10rpx second-text-28"> <view class="second-text-24">
<text>营业时间</text> <view class="second-text-28">营业时间:</view>
<text class="m-l-10rpx"> <view>{{ state.detail.jobTime?.split(",")[0] ? "早:" + state.detail.jobTime?.split(",")[0] : "" }}</view>
{{ state.detail.jobStartTime }} <view>{{ state.detail.jobTime?.split(",")[1] ? "中:" + state.detail.jobTime?.split(",")[1] : "" }}</view>
~ <view>{{ state.detail.jobTime?.split(",")[2] ? "晚:" + state.detail.jobTime?.split(",")[2] : "" }}</view>
{{ state.detail.jobEndTime }}
</text>
</view> </view>
<view v-if="state.detail.addressDes" class="m-t-10rpx second-text-28"> <view v-if="state.detail.addressDes" class="m-t-10rpx second-text-28">
<text>地址</text> <text>地址</text>
@@ -47,11 +41,7 @@
<!-- start 商品 start --> <!-- start 商品 start -->
<view class="flex-row"> <view class="flex-row">
<scroll-view <scroll-view scroll-y :style="{ height: getHeight() }" class="menu w-200rpx h-full p-l-12rpx p-b-20rpx bg-#f6f6f6">
scroll-y
:style="{ height: getHeight() }"
class="menu w-200rpx h-full p-l-12rpx p-b-20rpx bg-#f6f6f6"
>
<view <view
class="menu_item flex-row-center" class="menu_item flex-row-center"
v-for="(v, i) in state.classifyList" v-for="(v, i) in state.classifyList"
@@ -86,12 +76,7 @@
<template #main-bottom> <template #main-bottom>
<view class="car z-200 p-x-30rpx p-y-30rpx bg-white"> <view class="car z-200 p-x-30rpx p-y-30rpx bg-white">
<product-total <product-total :totPrice="state.totPrice" :totCount="state.totCount" @doContainer="doVisibleCar" @doPay="doPay" />
:totPrice="state.totPrice"
:totCount="state.totCount"
@doContainer="doVisibleCar"
@doPay="doPay"
/>
</view> </view>
</template> </template>
</crud-layout> </crud-layout>
@@ -149,9 +134,22 @@ onLoad((options: any) => {
} }
}) })
onShow(async () => { onShow(async () => {
await getDetail() uni.showLoading({
await getShopCar() title: "加载中...",
await getClassify() mask: true,
})
try {
await getDetail()
await getShopCar()
await getClassify()
} catch (error) {
uni.showToast({
title: "加载失败",
icon: "error",
})
} finally {
uni.hideLoading()
}
}) })
const getDetail = async () => { const getDetail = async () => {
+125
View File
@@ -0,0 +1,125 @@
<template>
<crud-layout bg="/static/page/blue-bg.png">
<z-paging
ref="pageRef"
:fixed="false"
v-model="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="scroll"
>
<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">{{ state.nowVal }}</tm-text>
<view class="flex items-center cursor-pointer">
<tm-between-time
start="2020-1-1"
end="2040-1-1"
v-model="state.newdata"
v-model:model-str="state.nowVal"
@confirm="datePickerConfirm"
>
<svg
t="1742280333491"
class="icon"
viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
p-id="4288"
width="16"
height="14"
>
<path
d="M568.552727 954.181818a86.341818 86.341818 0 0 1-41.425454-10.472727l-114.269091-62.836364a86.574545 86.574545 0 0 1-44.916364-76.101818V442.181818a16.989091 16.989091 0 0 0-6.981818-13.730909L97.047273 218.298182 93.090909 214.807273A85.876364 85.876364 0 0 1 155.927273 69.818182h711.214545A86.574545 86.574545 0 0 1 930.909091 214.807273l-3.490909 3.490909-266.24 213.410909a17.454545 17.454545 0 0 0-6.050909 13.730909v422.4A86.341818 86.341818 0 0 1 568.552727 954.181818zM141.963636 166.632727l262.283637 209.454546A85.178182 85.178182 0 0 1 437.061818 442.181818v362.589091a17.92 17.92 0 0 0 8.610909 15.592727l114.269091 62.138182a17.687273 17.687273 0 0 0 17.687273 0 17.221818 17.221818 0 0 0 8.378182-15.36V445.44a85.876364 85.876364 0 0 1 31.883636-67.258182l263.214546-211.549091a17.687273 17.687273 0 0 0 1.62909-18.152727 17.454545 17.454545 0 0 0-15.592727-8.843636H155.927273a17.221818 17.221818 0 0 0-13.963637 27.694545zM920.669091 512h-188.974546a34.443636 34.443636 0 0 1 0-69.818182h188.974546a34.443636 34.443636 0 0 1 0 69.818182z m0 128.930909h-188.974546a34.443636 34.443636 0 0 1 0-69.818182h188.974546a34.443636 34.443636 0 0 1 0 69.818182z m0 128h-188.974546a34.443636 34.443636 0 0 1 0-69.818182h188.974546a34.443636 34.443636 0 0 1 0 69.818182z"
p-id="4289"
/>
</svg>
<text class="ml-1 text-30">筛选</text>
</tm-between-time>
</view>
</view>
</template>
<view class="h-20rpx" />
<view class="bg-white rounded-16rpx p-2 mb-2 shadow-md" v-for="(v, i) in list" :key="i">
<view class="text-28 text-gray-800 font-medium px-2 mb-2">
{{ "2022-01-01" }}
</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 mr-1">
<text class="flex-1 text-center text-gray-600">流水金额</text>
<text class="flex-1 text-center text-26 text-gray-800 font-medium">¥{{ 1145 }}</text>
</view>
<view class="flex-1 flex items-center p-2 bg-white rounded-8rpx ml-1">
<text class="flex-1 text-center text-gray-600">流水次数</text>
<text class="flex-1 text-center text-26 text-gray-800 font-medium">{{ 1145 }}</text>
</view>
</view>
<view class="flex justify-between mb-2">
<view class="flex-1 flex items-center p-2 bg-white rounded-8rpx mr-1">
<text class="flex-1 text-center text-gray-600">退款金额</text>
<text class="flex-1 text-center text-26 text-red-500 font-medium">¥{{ 1145 }}</text>
</view>
<view class="flex-1 flex items-center p-2 bg-white rounded-8rpx ml-1">
<text class="flex-1 text-center text-gray-600">退款次数</text>
<text class="flex-1 text-center text-26 text-red-500 font-medium">{{ 1145 }}</text>
</view>
</view>
<view class="flex justify-between mb-0">
<view class="flex-1 flex items-center p-2 bg-white rounded-8rpx mr-1">
<text class="flex-1 text-center text-gray-600">盈利金额</text>
<text class="flex-1 text-center text-26 text-green-500 font-medium">¥{{ 1145 }}</text>
</view>
<view class="flex-1 flex items-center p-2 bg-white rounded-8rpx ml-1">
<text class="flex-1 text-center text-gray-600">盈利次数</text>
<text class="flex-1 text-center text-26 text-green-500 font-medium">{{ 1145 }}</text>
</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 { orderApi } from "@@/api"
const pageRef = ref<any>(null)
const state = reactive<any>({
pa: {
payTimeList: [],
},
nowVal: "",
newdata: "",
})
const { list, startPage, scroll } = hooks.usePage(pageRef, orderApi.page, null, "data.records")
onShow(() => {
// const isLogin = await hooks.useCheckLogin()
// if (!isLogin) return
})
const query = (page: number, pagesize: number) => {
// const isLogin = hooks.useStaticCheckLogin()
// if (!isLogin) return
startPage(page, pagesize, false, state.pa)
}
// 时间范围选择器确认
const datePickerConfirm = (date: any) => {
state.pa.payTimeList = state.newdata
pageRef.value.reload(false)
}
</script>
+8 -14
View File
@@ -1,7 +1,6 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref, reactive } from "vue" import { ref, reactive } from "vue"
import { onLoad, onShow } from "@dcloudio/uni-app" import { onShow } from "@dcloudio/uni-app"
import { hooks, router } from "@@/index" import { hooks, router } from "@@/index"
import { merchantApi } from "@@/api" import { merchantApi } from "@@/api"
import { filePath } from "@@/utils/file" import { filePath } from "@@/utils/file"
@@ -13,7 +12,6 @@ const state = reactive<any>({
}, },
}) })
onLoad(() => {})
onShow(() => { onShow(() => {
if (pageRef.value) { if (pageRef.value) {
pageRef.value.reload(false) pageRef.value.reload(false)
@@ -52,23 +50,19 @@ const toDetail = async (v: any) => {
> >
<view class="h-20rpx" /> <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)"> <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-160rpx h-160rpx rounded-12rpx" :src="filePath(v.logoPic)" mode="aspectFill" /> <image class="w-180rpx h-180rpx rounded-12rpx" :src="filePath(v.logoPic)" mode="aspectFill" />
<view class="flex-1 flex-col m-l-20rpx"> <view class="flex-1 flex-col m-l-20rpx">
<view class="flex-row items-center justify-between"> <view class="flex-row items-center justify-between">
<view class="flex-row-center sub-text-34"> <view class="flex-row-center sub-text-34">{{ v.name }}</view>
<text>{{ v.name }}</text>
</view>
<view> <view>
<tm-tag size="s">{{ v.deptName }}</tm-tag> <tm-tag size="s">{{ v.deptName }}</tm-tag>
</view> </view>
</view> </view>
<view class="m-t-10rpx second-text-28"> <view class="second-text-24">
<text>营业时间</text> <view class="second-text-28">营业时间:</view>
<text class="m-l-10rpx"> <view>{{ v.jobTime?.split(",")[0] ? "早:" + v.jobTime?.split(",")[0] : "" }}</view>
{{ v.jobStartTime }} <view>{{ v.jobTime?.split(",")[1] ? "中:" + v.jobTime?.split(",")[1] : "" }}</view>
~ <view>{{ v.jobTime?.split(",")[2] ? "晚:" + v.jobTime?.split(",")[2] : "" }}</view>
{{ v.jobEndTime }}
</text>
</view> </view>
<view v-if="v.addressDes" class="m-t-10rpx second-text-28"> <view v-if="v.addressDes" class="m-t-10rpx second-text-28">
<text>食堂地址</text> <text>食堂地址</text>
+139
View File
@@ -0,0 +1,139 @@
<template>
<crud-layout bg="/static/page/blue-bg.png">
<z-paging
ref="pageRef"
:fixed="false"
v-model="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="scroll"
>
<template #top>
<view class="h-30rpx" />
<view class="bg-white rounded-16rpx px-20rpx">
<z-tabs :list="tabs" @change="tabChange" />
</view>
</template>
<view class="h-20rpx" />
<view class="flex-col justify-center card p-x-15rpx p-y-25rpx m-b-20rpx" v-for="(v, i) in 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">
<view class="flex-row items-center justify-between">
<view class="flex-row items-center">
<view class="main-text-28">{{ v.merchantName }}</view>
<view v-if="false" class="m-l-15rpx color-#999 font-size-26rpx! iconfont icon-youjiantou" />
</view>
<tm-tag v-if="v.orderStatus !== 1" color="success" size="xs">已支付</tm-tag>
<tm-tag v-if="v.orderStatus == 2" color="info" size="xs">售后</tm-tag>
</view>
<view class="flex justify-between items-end m-t-5rpx">
<view class="flex flex-col m-t-5rpx">
<view class="second-text-20">
<text>{{ "某个人" }}</text>
<text class="m-l-10rpx">{{ "13155555555" }}</text>
</view>
<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>
<view class="flex flex-row">
<view class="m-t-14rpx m-r-20rpx second-text-26">共 {{ v.carList.length }} 件</view>
<view class="m-t-10rpx main-text-30 color-red!">¥ {{ hooks.useMoney(v.totalPrice) }}</view>
</view>
</view>
</view>
</view>
<view class="h-20rpx m-t-[-10rpx] 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>
</scroll-view>
</view> -->
</view>
<view class="flex-row items-center justify-end">
<view class="botder_btn" @tap.stop="">退款</view>
</view>
</view>
</z-paging>
<!-- <tm-drawer ref="calendarView" placement="bottom" v-model:show="state.showDrawer">
<view style="height: 1800rpx"></view>
</tm-drawer> -->
</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"
import { orderApi } from "@@/api"
const pageRef = ref<any>(null)
// 选项卡
const tabs = [
{ id: null, name: "全部", disabled: false },
{ id: 1, name: "已支付", disabled: false },
{ id: 2, name: "售后", disabled: false },
]
const state = reactive<any>({
pa: {
orderStatus: tabs[0].id,
},
// showDrawer: false,
})
const { list, startPage, scroll } = hooks.usePage(pageRef, orderApi.page, null, "data.records")
onShow(() => {
// const isLogin = await hooks.useCheckLogin()
// if (!isLogin) return
})
// 切换选项卡
const tabChange = (e: number) => {
state.pa.orderStatus = tabs[e].id
pageRef.value.reload(true)
}
const query = (page: number, pagesize: number) => {
// const isLogin = hooks.useStaticCheckLogin()
// if (!isLogin) return
startPage(page, pagesize, false, state.pa)
}
// 点击退款
// const tabRefund = (v: any) => {
// state.showDrawer = true
// }
</script>
+63 -18
View File
@@ -48,6 +48,8 @@ import { filePath } from "@@/utils/file"
import { hooks, router, constant } from "@@/index" import { hooks, router, constant } from "@@/index"
import { userApi } from "@@/api" import { userApi } from "@@/api"
import isDevEnv from "@/sheep/utils/isDevEnv" import isDevEnv from "@/sheep/utils/isDevEnv"
import { usePayStore } from "@/sheep/stores/pay"
// import dd from "gdt-jsapi"
interface MenuItem { interface MenuItem {
text: string text: string
@@ -59,6 +61,7 @@ const state = reactive<{ wallet: any; userInfo: any; menuList: MenuItem[] }>({
wallet: [], wallet: [],
userInfo: {}, userInfo: {},
menuList: [ menuList: [
{ text: "扫一扫", icon: "/static/icon/scan.png", router: "" },
{ text: "钱包管理", icon: "/static/icon/service_3.png", router: "/pages/wallet/list" }, { text: "钱包管理", icon: "/static/icon/service_3.png", router: "/pages/wallet/list" },
// { text: "包厢预定", icon: "/static/icon/service_4.png", router: "/pages/boxes/apply-list" }, // { text: "包厢预定", icon: "/static/icon/service_4.png", router: "/pages/boxes/apply-list" },
// { text: "外来人员就餐", icon: "/static/icon/service_1.png", router: "/pages/apply/foreign-list" }, // { text: "外来人员就餐", icon: "/static/icon/service_1.png", router: "/pages/apply/foreign-list" },
@@ -172,6 +175,40 @@ const doLogout = async () => {
uni.showToast({ title: "退出登录成功", icon: "none" }) uni.showToast({ title: "退出登录成功", icon: "none" })
} }
// 扫一扫
const doScanCode = async () => {
usePayStore().setPayData({})
try {
const res: any = await (window as any).dd.scan({ type: "all", sourceType: ["camera"], scanType: ["cameraScan"] })
// const decodedString = decodeBase64("eyJpZCI6IjE4ODk0ODM5Mzg0ODQ1MzEyMDEiLCJuYW1lIjoi5rWL6K+V6LaF5biCIn0=")
const decodedString = decodeBase64(res.text)
if (decodedString) {
const decodedJson = JSON.parse(decodedString)
if (decodedJson?.id && decodedJson?.name) {
usePayStore().setPayData(decodedJson)
router.jump("/pages/pay/scanPay")
} else {
uni.showToast({
title: "无效的二维码",
icon: "none",
})
}
} else {
uni.showToast({
title: "无效的二维码",
icon: "none",
})
}
} catch (error: any) {
if (error) {
uni.showToast({
title: error,
icon: "none",
})
}
}
}
const onTabMenu = async (v: MenuItem, i: number) => { const onTabMenu = async (v: MenuItem, i: number) => {
if (i == state.menuList.length - 1) { if (i == state.menuList.length - 1) {
router.jump(v.router) router.jump(v.router)
@@ -179,7 +216,32 @@ const onTabMenu = async (v: MenuItem, i: number) => {
} }
const isLogin = await hooks.useCheckLogin() const isLogin = await hooks.useCheckLogin()
if (isLogin) { if (isLogin) {
router.jump(v.router) if (v.text === "扫一扫") {
await doScanCode()
} else {
router.jump(v.router)
}
}
}
// 解码base64
const decodeBase64 = (base64String: string) => {
try {
const decodedBinaryString = atob(base64String)
const uint8Array = new Uint8Array(decodedBinaryString.length)
for (let i = 0; i < decodedBinaryString.length; i++) {
uint8Array[i] = decodedBinaryString.charCodeAt(i)
}
const decoder = new TextDecoder("utf-8")
const decodedString = decoder.decode(uint8Array)
console.log("解码结果", decodedString)
return decodedString
} catch (error) {
console.error("Base64 解码失败:", error)
uni.showToast({
title: "解码失败,无效的二维码",
icon: "none",
})
} }
} }
@@ -208,23 +270,6 @@ onLoad(() => {
onShow(() => { onShow(() => {
getStorageUserInfo() getStorageUserInfo()
}) })
// {
// "accessToken": {
// "tokenValue": "06d43795-a3ef-4019-a70f-25830e7183a4",
// "issuedAt": "2025-01-24T11:10:30.423604599Z",
// "expiresAt": "2025-01-25T11:10:30.423604599Z",
// "tokenType": {
// "value": "Bearer"
// },
// "scopes": []
// },
// "refreshToken": {
// "tokenValue": "FmRVP4l3d7t3263h9LeKnV8hdU0lPasMuI1wank_EbylRQPNLm7XP4_OtUV-zH9AbMZc9f14Qk2IXhw-33fWMGGKipVY8crbvVyWV5DeAcfeU8fYyQuNDh9rw3Dq0w75",
// "issuedAt": "2025-01-24T11:10:30.423699280Z",
// "expiresAt": "2025-01-31T11:10:30.423699280Z"
// }
// }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
+12 -12
View File
@@ -13,7 +13,7 @@ const data = {
tabs: [ tabs: [
{ id: null, name: "全部", disabled: false }, { id: null, name: "全部", disabled: false },
{ id: 1, name: "未支付", disabled: false }, { id: 1, name: "未支付", disabled: false },
{ id: 5, name: "待核销", disabled: false }, { id: 5, name: "已支付", disabled: false },
{ id: 10, name: "售后", disabled: false }, { id: 10, name: "售后", disabled: false },
{ id: 20, name: "已核销", disabled: false }, { id: 20, name: "已核销", disabled: false },
], ],
@@ -49,7 +49,7 @@ const query = (page: number, pagesize: number) => {
} }
const doToDetail = (v: any) => { const doToDetail = (v: any) => {
router.jump("/pages/order/detail", { id: v.id }) // router.jump("/pages/order/detail", { id: v.id })
} }
const doAppraise = () => {} const doAppraise = () => {}
@@ -94,7 +94,7 @@ const doRefund = (v: any) => {
<view class="flex-row items-center justify-between"> <view class="flex-row items-center justify-between">
<view class="flex-row items-center"> <view class="flex-row items-center">
<view class="main-text-28">{{ v.merchantName }}</view> <view class="main-text-28">{{ v.merchantName }}</view>
<view class="m-l-15rpx color-#999 font-size-26rpx! iconfont icon-youjiantou" /> <!-- <view class="m-l-15rpx color-#999 font-size-26rpx! iconfont icon-youjiantou" /> -->
</view> </view>
<tm-tag v-if="v.orderStatus == 1" color="info" size="xs">未支付</tm-tag> <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 == 5" color="success" size="xs">待核销</tm-tag>
@@ -108,14 +108,14 @@ const doRefund = (v: any) => {
{{ hooks.useTime(v.createTime, "{y}-{m}-{d} {h}:{i}:{s}") }} {{ hooks.useTime(v.createTime, "{y}-{m}-{d} {h}:{i}:{s}") }}
</text> </text>
</view> </view>
<view class="second-text-22"> <!-- <view class="second-text-22">
{{ hooks.useEnum("hardwareRefundStatusEnum", v.refundStatus) }} {{ hooks.useEnum("hardwareRefundStatusEnum", v.refundStatus) }}
</view> </view> -->
</view> </view>
</view> </view>
</view> </view>
<view class="relative h-180rpx m-t-20rpx"> <view class="relative h-0rpx m-t-[-10rpx] flex justify-end items-center">
<view class="absolute top-0 right-0 bottom-0 left-0 h-180rpx"> <!-- <view class="absolute top-0 right-0 bottom-0 left-0 h-180rpx">
<scroll-view scroll-x class="flex-row-center whitespace-nowrap"> <scroll-view scroll-x class="flex-row-center whitespace-nowrap">
<view class="flex-row items-center"> <view class="flex-row items-center">
<view <view
@@ -138,11 +138,11 @@ const doRefund = (v: any) => {
</view> </view>
</view> </view>
</scroll-view> </scroll-view>
</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 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 class="main-text-30 color-red!">¥ {{ hooks.useMoney(v.totalPrice) }}</view> <view class="m-t-2rpx m-r-20rpx second-text-26">共 {{ v.carList.length }} 件</view>
<view class="m-t-10rpx second-text-26">共 {{ v.carList.length }} 件</view> <view class="main-text-30 color-red!">¥ {{ hooks.useMoney(v.totalPrice) }}</view>
</view> <!-- </view> -->
</view> </view>
<view v-if="['5', '10'].includes(v.orderStatus)" class="flex-row items-center justify-end p-t-20rpx"> <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="botder_btn" @tap.stop="doRefund(v)">退款</view> -->
+21 -31
View File
@@ -1,31 +1,27 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref, reactive } from "vue" import { ref, reactive } from "vue"
import { onLoad, onShow } from "@dcloudio/uni-app" import { onShow } from "@dcloudio/uni-app"
import { hooks, router } from "@@/index"
import { merchantApi } from "@@/api" import { merchantApi } from "@@/api"
import { hooks, router } from "@@/index"
import { filePath } from "@@/utils/file" import { filePath } from "@@/utils/file"
const pageRef = ref<any>(null)
const state = reactive<any>({ const state = reactive<any>({
pa: { pa: {
pagesize: 10, pagesize: 10,
type: "2", type: "2",
}, },
}) })
const { startPage, list, scroll } = hooks.usePage(pageRef, merchantApi.page, null, "data.records")
onLoad(() => {})
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) => { const query = (page: number, pagesize: number) => {
pageHook.startPage(page, pagesize, false, state.pa) startPage(page, pagesize, false, state.pa)
} }
onShow(() => {
pageRef.value && pageRef.value.reload(false)
})
const toDetail = async (v: any) => { const toDetail = async (v: any) => {
const isLogin = await hooks.useCheckLogin() const isLogin = await hooks.useCheckLogin()
if (isLogin) { if (isLogin) {
@@ -40,7 +36,7 @@ const toDetail = async (v: any) => {
ref="pageRef" ref="pageRef"
height="100%" height="100%"
:fixed="false" :fixed="false"
v-model="pageHook.list" v-model="list"
:default-page-size="10" :default-page-size="10"
safe-area-inset-bottom safe-area-inset-bottom
:loading-more-enabled="true" :loading-more-enabled="true"
@@ -48,29 +44,23 @@ const toDetail = async (v: any) => {
@query="query" @query="query"
:auto-clean-list-when-reload="false" :auto-clean-list-when-reload="false"
:auto-scroll-to-top-when-reload="false" :auto-scroll-to-top-when-reload="false"
@scroll="pageHook.scroll" @scroll="scroll"
> >
<view class="h-20rpx" /> <view class="h-20rpx" />
<view class="flex-col card p-20rpx m-b-20rpx" v-for="(v, i) in pageHook.list" :key="i" @tap="toDetail(v)"> <view class="flex-col card p-20rpx m-b-20rpx" v-for="(v, i) in list" :key="i" @tap="toDetail(v)">
<view class="flex-row-center"> <view class="flex-row-center">
<image class="w-120rpx h-120rpx rounded-12rpx" :src="filePath(v.logoPic)" mode="aspectFill" /> <image class="w-180rpx h-180rpx rounded-12rpx" :src="filePath(v.logoPic)" mode="aspectFill" />
<view class="flex-1 flex-col m-l-20rpx"> <view class="flex-1 flex-col m-l-20rpx">
<view class="flex-row items-center justify-between"> <view class="flex-row items-center justify-between">
<view class="flex-row-center sub-text-34"> <view class="flex-row-center sub-text-34">{{ v.name }}</view>
<text> {{ v.name }}</text> <tm-tag size="s">{{ v.deptName }}</tm-tag>
</view>
<view>
<tm-tag size="s">{{ v.deptName }}</tm-tag>
</view>
</view> </view>
<view class="second-text-28">{{ v.phone }}</view> <view class="second-text-24">{{ v.phone }}</view>
<view class="m-t-10rpx second-text-28"> <view class="second-text-24">
<text>营业时间</text> <view class="second-text-28">营业时间:</view>
<text class="m-l-10rpx"> <view>{{ v.jobTime?.split(",")[0] ? "早:" + v.jobTime?.split(",")[0] : "" }}</view>
{{ v.jobStartTime }} <view>{{ v.jobTime?.split(",")[1] ? "中:" + v.jobTime?.split(",")[1] : "" }}</view>
~ <view>{{ v.jobTime?.split(",")[2] ? "晚:" + v.jobTime?.split(",")[2] : "" }}</view>
{{ v.jobEndTime }}
</text>
</view> </view>
<view v-if="v.addressDes" class="m-t-10rpx second-text-28"> <view v-if="v.addressDes" class="m-t-10rpx second-text-28">
<text>地址</text> <text>地址</text>
+6 -6
View File
@@ -172,11 +172,13 @@ const doFreeze = async () => {
<text class="sub-text-40 color-red!"> ¥{{ hooks.useMoney(v.balance) }} </text> <text class="sub-text-40 color-red!"> ¥{{ hooks.useMoney(v.balance) }} </text>
</view> </view>
<view class="flex-row items-center justify-end space-x-20rpx m-t-10rpx"> <view class="flex-row items-center justify-end space-x-20rpx m-t-10rpx">
<view v-if="v.walletTypeUniqueCode == 1 && !v.cardNumber" class="botder_btn" @tap.stop="openBindDialog(v)"> 绑定 </view> <!-- <view v-if="v.walletTypeUniqueCode == 1 && !v.cardNumber" class="botder_btn" @tap.stop="openBindDialog(v)">绑定</view> -->
<view v-if="v.walletTypeUniqueCode == 1 && v.cardNumber && v.isFreeze != 1" class="botder_btn" @tap.stop="openFreezeDialog(v)"> <view v-if="v.walletTypeUniqueCode == 1 && v.cardNumber && v.isFreeze != 1" class="botder_btn" @tap.stop="openFreezeDialog(v)">
申请冻结 申请冻结
</view> </view>
<view class="botder_btn" @tap.stop="router.jump('/pages/wallet/recharge', { id: v.id })"> 去充值 </view> <view v-if="v.walletTypeUniqueCode == 2" class="botder_btn" @tap.stop="router.jump('/pages/wallet/recharge', { id: v.id })">
去充值
</view>
</view> </view>
</view> </view>
</z-paging> </z-paging>
@@ -198,7 +200,7 @@ const doFreeze = async () => {
</tm-form-item> </tm-form-item>
</tm-form> </tm-form>
<view class="h-50rpx" /> <view class="h-50rpx" />
<view class="bg-#0094ff p-y-20rpx text-center rounded-40rpx sub-text-30 color-white!" @tap="doBind"> 绑定 </view> <!-- <view class="bg-#0094ff p-y-20rpx text-center rounded-40rpx sub-text-30 color-white!" @tap="doBind">绑定</view> -->
</tm-drawer> </tm-drawer>
<tm-drawer <tm-drawer
z-index="100" z-index="100"
@@ -216,7 +218,7 @@ const doFreeze = async () => {
</tm-form-item> </tm-form-item>
</tm-form> </tm-form>
<view class="h-50rpx" /> <view class="h-50rpx" />
<view class="bg-#0094ff p-y-20rpx text-center rounded-40rpx sub-text-30 color-white!" @tap="doFreeze"> 冻结 </view> <!-- <view class="bg-#0094ff p-y-20rpx text-center rounded-40rpx sub-text-30 color-white!" @tap="doFreeze">冻结</view> -->
</tm-drawer> </tm-drawer>
<tm-drawer <tm-drawer
z-index="100" z-index="100"
@@ -233,5 +235,3 @@ const doFreeze = async () => {
</view> </view>
</tm-drawer> </tm-drawer>
</template> </template>
<style lang="scss" scoped></style>
+2 -2
View File
@@ -7,8 +7,8 @@ export default {
method: "POST", method: "POST",
data, data,
params: { params: {
pageNo: data.pageNo, current: data.current,
pagesize: data.pagesize, size: data.size,
}, },
custom: { custom: {
showLoading: false, showLoading: false,
+62 -51
View File
@@ -1,53 +1,64 @@
import request from "@/sheep/utils/request"; import request from "@/sheep/utils/request"
export default { export default {
// 获得支付订单 // 获得支付订单
getOrder: (params) => { getOrder: (params) => {
return request({ return request({
url: "/pay/order/get", url: "/pay/order/get",
method: "GET", method: "GET",
params, params,
}); })
}, },
// 提交支付订单 // 提交支付订单
submitOrder: (data) => { submitOrder: (data) => {
return request({ return request({
url: "/pay/order/submit", url: "/pay/order/submit",
method: "POST", method: "POST",
data, data,
}); })
}, },
// 创建硬件订单 // 创建硬件订单
createHardwareOrder: (params) => { createHardwareOrder: (params) => {
return request({ return request({
url: "/hard/hard-order/app/create-order", url: "/hard/hard-order/app/create-order",
method: "GET", method: "GET",
params, params,
custom: { custom: {
showLoading: false, showLoading: false,
}, },
}); })
}, },
// 结算 // 创建二维码订单
submitHardwareOrder: (data) => { createQrCodeOrder: (data): any => {
return request({ return request({
url: "/hardware/order/submit-order", url: "/hard/hard-order/app/create-order-scan-qrcode",
method: "POST", method: "POST",
data, data,
custom: { custom: {
showLoading: false, showLoading: false,
}, },
}); })
}, },
// 退款 // 结算
refundHardwareOrder: (params) => { submitHardwareOrder: (data) => {
return request({ return request({
url: "/hardware/order/refund", url: "/hardware/order/submit-order",
method: "GET", method: "POST",
params, data,
custom: { custom: {
showLoading: false, showLoading: false,
}, },
}); })
}, },
}; // 退款
refundHardwareOrder: (params) => {
return request({
url: "/hardware/order/refund",
method: "GET",
params,
custom: {
showLoading: false,
},
})
},
}
@@ -1,382 +1,363 @@
<template> <template>
<view class="waterfalls-flow"> <view class="waterfalls-flow">
<view <view
v-for="(item, index) in data.column" v-for="(item, index) in data.column"
:key="index" :key="index"
class="waterfalls-flow-column" class="waterfalls-flow-column"
:id="`waterfalls_flow_column_${index + 1}`" :id="`waterfalls_flow_column_${index + 1}`"
:msg="msg" :msg="msg"
:style="{ width: w, 'margin-left': index == 0 ? 0 : m }" :style="{ width: w, 'margin-left': index == 0 ? 0 : m }"
> >
<view <view
:class="['column-value', { 'column-value-show': item2.o }]" :class="['column-value', { 'column-value-show': item2.o }]"
v-for="(item2, index2) in columnValue(index)" v-for="(item2, index2) in columnValue(index)"
:key="index2" :key="index2"
:style="[s1]" :style="[s1]"
@click.stop="wapperClick(item2)" @click.stop="wapperClick(item2)"
> >
<view class="inner" v-if="data.seat == 1"> <view class="inner" v-if="data.seat == 1">
<!-- #ifdef MP-WEIXIN --> <!-- #ifdef MP-WEIXIN -->
<!-- #ifdef VUE2 --> <!-- #ifdef VUE2 -->
<slot name="slot{{item2.index}}"></slot> <slot name="slot{{item2.index}}"></slot>
<!-- #endif --> <!-- #endif -->
<!-- #ifdef VUE3 --> <!-- #ifdef VUE3 -->
<slot :name="`slot${item2.index}`"></slot> <slot :name="`slot${item2.index}`"></slot>
<!-- #endif --> <!-- #endif -->
<!-- #endif --> <!-- #endif -->
<!-- #ifndef MP-WEIXIN --> <!-- #ifndef MP-WEIXIN -->
<slot v-bind="item2"></slot> <slot v-bind="item2"></slot>
<!-- #endif --> <!-- #endif -->
</view> </view>
<image <image
:class="[ :class="[
'img', 'img',
{ {
'img-hide': 'img-hide': item2[hideImageKey] == true || item2[hideImageKey] == 1,
item2[hideImageKey] == true || item2[hideImageKey] == 1, },
}, { 'img-error': !item2[data.imageKey] },
{ 'img-error': !item2[data.imageKey] }, ]"
]" :src="item2[data.imageKey]"
:src="item2[data.imageKey]" mode="widthFix"
mode="widthFix" @load="imgLoad(item2, index + 1)"
@load="imgLoad(item2, index + 1)" @error="imgError(item2, index + 1)"
@error="imgError(item2, index + 1)" @click.stop="imageClick(item2)"
@click.stop="imageClick(item2)" ></image>
></image> <view class="inner" v-if="data.seat == 2">
<view class="inner" v-if="data.seat == 2"> <!-- #ifdef MP-WEIXIN -->
<!-- #ifdef MP-WEIXIN --> <!-- #ifdef VUE2 -->
<!-- #ifdef VUE2 --> <slot name="slot{{item2.index}}"></slot>
<slot name="slot{{item2.index}}"></slot> <!-- #endif -->
<!-- #endif --> <!-- #ifdef VUE3 -->
<!-- #ifdef VUE3 --> <slot :name="`slot${item2.index}`"></slot>
<slot :name="`slot${item2.index}`"></slot> <!-- #endif -->
<!-- #endif --> <!-- #endif -->
<!-- #endif --> <!-- #ifndef MP-WEIXIN -->
<!-- #ifndef MP-WEIXIN --> <slot v-bind="item2"></slot>
<slot v-bind="item2"></slot> <!-- #endif -->
<!-- #endif --> </view>
</view> </view>
</view> </view>
</view> </view>
</view>
</template> </template>
<script> <script>
export default { export default {
props: { props: {
modelValue: Array, modelValue: Array,
column: { column: {
// 列的数量 // 列的数量
type: [String, Number], type: [String, Number],
default: 2, default: 2,
}, },
maxColumn: { maxColumn: {
// 最大列数 // 最大列数
type: [String, Number], type: [String, Number],
default: 5, default: 5,
}, },
columnSpace: { columnSpace: {
// 列之间的间距 百分比 // 列之间的间距 百分比
type: [String, Number], type: [String, Number],
default: 2, default: 2,
}, },
imageKey: { imageKey: {
// 图片key // 图片key
type: [String], type: [String],
default: "image", default: "image",
}, },
hideImageKey: { hideImageKey: {
// 隐藏图片key // 隐藏图片key
type: [String], type: [String],
default: "hide", default: "hide",
}, },
seat: { seat: {
// 文本的位置,1图片之上 2图片之下 // 文本的位置,1图片之上 2图片之下
type: [String, Number], type: [String, Number],
default: 2, default: 2,
}, },
listStyle: { listStyle: {
// 单个展示项的样式:eg:{'background':'red'} // 单个展示项的样式:eg:{'background':'red'}
type: Object, type: Object,
}, },
}, },
data() { data() {
return { return {
data: { data: {
list: this.modelValue ? this.modelValue : [], list: this.modelValue ? this.modelValue : [],
column: this.column < 2 ? 2 : this.column, column: this.column < 2 ? 2 : this.column,
columnSpace: this.columnSpace <= 5 ? this.columnSpace : 5, columnSpace: this.columnSpace <= 5 ? this.columnSpace : 5,
imageKey: this.imageKey, imageKey: this.imageKey,
seat: this.seat, seat: this.seat,
}, },
msg: 0, msg: 0,
listInitStyle: { listInitStyle: {
"border-radius": "12rpx", "border-radius": "12rpx",
"margin-bottom": "20rpx", "margin-bottom": "20rpx",
"background-color": "#fff", "background-color": "#fff",
}, },
adds: [], //预置数据 adds: [], //预置数据
isLoaded: true, isLoaded: true,
curIndex: 0, curIndex: 0,
isRefresh: true, isRefresh: true,
flag: false, flag: false,
refreshDatas: [], refreshDatas: [],
}; }
}, },
computed: { computed: {
// 计算列宽 // 计算列宽
w() { w() {
const column_rate = `${100 / this.data.column - +this.data.columnSpace}%`; const column_rate = `${100 / this.data.column - +this.data.columnSpace}%`
return column_rate; return column_rate
}, },
// 计算margin // 计算margin
m() { m() {
const column_margin = `${ const column_margin = `${
(100 - (100 - (100 / this.data.column - +this.data.columnSpace).toFixed(5) * this.data.column) / (this.data.column - 1)
(100 / this.data.column - +this.data.columnSpace).toFixed(5) * }%`
this.data.column) / return column_margin
(this.data.column - 1) },
}%`; // list样式
return column_margin; s1() {
}, return { ...this.listInitStyle, ...this.listStyle }
// list样式 },
s1() { },
return { ...this.listInitStyle, ...this.listStyle }; created() {
}, // 初始化
}, this.refresh()
created() { },
// 初始化 methods: {
this.refresh(); // 预加载图片
}, loadImages(idx = 0) {
methods: { let count = 0
// 预加载图片 const newList = this.data.list.filter((item, index) => index >= idx)
loadImages(idx = 0) { for (let i = 0; i < newList.length; i++) {
let count = 0; // #ifndef APP-PLUS
const newList = this.data.list.filter((item, index) => index >= idx); uni.getImageInfo({
for (let i = 0; i < newList.length; i++) { src: `${newList[i][this.imageKey]}.jpg`,
// #ifndef APP-PLUS complete: (res) => {
uni.getImageInfo({ count++
src: `${newList[i][this.imageKey]}.jpg`, if (count == newList.length) this.initValue(idx)
complete: (res) => { },
count++; })
if (count == newList.length) this.initValue(idx); // #endif
}, // #ifdef APP-PLUS
}); plus.io.getImageInfo({
// #endif src: `${newList[i][this.imageKey]}.jpg`,
// #ifdef APP-PLUS complete: (res) => {
plus.io.getImageInfo({ count++
src: `${newList[i][this.imageKey]}.jpg`, if (count == newList.length) this.initValue(idx)
complete: (res) => { },
count++; })
if (count == newList.length) this.initValue(idx); // #endif
}, }
}); },
// #endif // 刷新
} refresh() {
}, if (!this.isLoaded) {
// 刷新 this.refreshDatas = this.modelValue
refresh() { return false
if (!this.isLoaded) { }
this.refreshDatas = this.modelValue; setTimeout(() => {
return false; this.refreshDatas = []
} this.isRefresh = true
setTimeout(() => { this.adds = []
this.refreshDatas = []; this.data.list = this.modelValue ? this.modelValue : []
this.isRefresh = true; this.data.column = this.column < 2 ? 2 : this.column >= this.maxColumn ? this.maxColumn : this.column
this.adds = []; this.data.columnSpace = this.columnSpace <= 5 ? this.columnSpace : 5
this.data.list = this.modelValue ? this.modelValue : []; this.data.imageKey = this.imageKey
this.data.column = this.data.seat = this.seat
this.column < 2 this.curIndex = 0
? 2 // 每列的数据初始化
: this.column >= this.maxColumn for (let i = 1; i <= this.data.column; i++) {
? this.maxColumn this.data[`column_${i}_values`] = []
: this.column; this.msg++
this.data.columnSpace = this.columnSpace <= 5 ? this.columnSpace : 5; }
this.data.imageKey = this.imageKey; this.$nextTick(() => {
this.data.seat = this.seat; this.initValue(this.curIndex, "refresh==>")
this.curIndex = 0; })
// 每列的数据初始化 }, 1)
for (let i = 1; i <= this.data.column; i++) { },
this.data[`column_${i}_values`] = []; columnValue(index) {
this.msg++; return this.data[`column_${index + 1}_values`]
} },
this.$nextTick(() => { change(newValue) {
this.initValue(this.curIndex, "refresh==>"); for (let i = 0; i < this.data.list.length; i++) {
}); const cv = this.data[`column_${this.data.list[i].column}_values`]
}, 1); for (let j = 0; j < cv.length; j++) {
}, if (newValue[i] && i === cv[j].index) {
columnValue(index) { this.data[`column_${this.data.list[i].column}_values`][j] = Object.assign(cv[j], newValue[i])
return this.data[`column_${index + 1}_values`]; this.msg++
}, break
change(newValue) { }
for (let i = 0; i < this.data.list.length; i++) { }
const cv = this.data[`column_${this.data.list[i].column}_values`]; }
for (let j = 0; j < cv.length; j++) { },
if (newValue[i] && i === cv[j].index) { getMin(a, s) {
this.data[`column_${this.data.list[i].column}_values`][j] = let m = a[0][s]
Object.assign(cv[j], newValue[i]); let mo = a[0]
this.msg++; for (var i = a.length - 1; i >= 0; i--) {
break; if (a[i][s] < m) {
} m = a[i][s]
} }
} }
}, mo = a.filter((i) => i[s] == m)
getMin(a, s) { return mo[0]
let m = a[0][s]; },
let mo = a[0]; // 计算每列的高度
for (var i = a.length - 1; i >= 0; i--) { getMinColumnHeight() {
if (a[i][s] < m) { return new Promise((resolve) => {
m = a[i][s]; const heightArr = []
} for (let i = 1; i <= this.data.column; i++) {
} const query = uni.createSelectorQuery().in(this)
mo = a.filter((i) => i[s] == m); query
return mo[0]; .select(`#waterfalls_flow_column_${i}`)
}, .boundingClientRect((data) => {
// 计算每列的高度 heightArr.push({ column: i, height: data.height })
getMinColumnHeight() { })
return new Promise((resolve) => { .exec(() => {
const heightArr = []; if (this.data.column <= heightArr.length) {
for (let i = 1; i <= this.data.column; i++) { resolve(this.getMin(heightArr, "height"))
const query = uni.createSelectorQuery().in(this); }
query })
.select(`#waterfalls_flow_column_${i}`) }
.boundingClientRect((data) => { })
heightArr.push({ column: i, height: data.height }); },
}) async initValue(i, from) {
.exec(() => { this.isLoaded = false
if (this.data.column <= heightArr.length) { if (i >= this.data.list.length || this.refreshDatas.length) {
resolve(this.getMin(heightArr, "height")); this.msg++
} this.loaded()
}); return false
} }
}); const minHeightRes = await this.getMinColumnHeight()
}, const c = this.data[`column_${minHeightRes.column}_values`]
async initValue(i, from) { this.data.list[i].column = minHeightRes.column
this.isLoaded = false; c.push({ ...this.data.list[i], cIndex: c.length, index: i, o: 0 })
if (i >= this.data.list.length || this.refreshDatas.length) { this.msg++
this.msg++; },
this.loaded(); // 图片加载完成
return false; imgLoad(item, c) {
} const i = item.index
const minHeightRes = await this.getMinColumnHeight(); item.o = 1
const c = this.data[`column_${minHeightRes.column}_values`]; this.$set(this.data[`column_${c}_values`], item.cIndex, JSON.parse(JSON.stringify(item)))
this.data.list[i].column = minHeightRes.column; this.initValue(i + 1)
c.push({ ...this.data.list[i], cIndex: c.length, index: i, o: 0 }); },
this.msg++; // 图片加载失败
}, imgError(item, c) {
// 图片加载完成 const i = item.index
imgLoad(item, c) { item.o = 1
const i = item.index; item[this.data.imageKey] = null
item.o = 1; this.$set(this.data[`column_${c}_values`], item.cIndex, JSON.parse(JSON.stringify(item)))
this.$set( this.initValue(i + 1)
this.data[`column_${c}_values`], },
item.cIndex, // 渲染结束
JSON.parse(JSON.stringify(item)) loaded() {
); if (this.refreshDatas.length) {
this.initValue(i + 1); this.isLoaded = true
}, this.refresh()
// 图片加载失败 return false
imgError(item, c) { }
const i = item.index; this.curIndex = this.data.list.length
item.o = 1; if (this.adds.length) {
item[this.data.imageKey] = null; this.data.list = this.adds[0]
this.$set( this.adds.splice(0, 1)
this.data[`column_${c}_values`], this.initValue(this.curIndex)
item.cIndex, } else {
JSON.parse(JSON.stringify(item)) if (this.data.list.length) this.$emit("loaded")
); this.isLoaded = true
this.initValue(i + 1); this.isRefresh = false
}, }
// 渲染结束 },
loaded() { // 单项点击事件
if (this.refreshDatas.length) { wapperClick(item) {
this.isLoaded = true; this.$emit("wapperClick", item)
this.refresh(); },
return false; // 图片点击事件
} imageClick(item) {
this.curIndex = this.data.list.length; this.$emit("imageClick", item)
if (this.adds.length) { },
this.data.list = this.adds[0]; },
this.adds.splice(0, 1); watch: {
this.initValue(this.curIndex); modelValue: {
} else { deep: true,
if (this.data.list.length) this.$emit("loaded"); handler(newValue, oldValue) {
this.isLoaded = true; setTimeout(() => {
this.isRefresh = false; this.$nextTick(() => {
} if (this.isRefresh) return false
}, if (this.isLoaded) {
// 单项点击事件 this.refresh()
wapperClick(item) { if (newValue.length <= this.curIndex) return this.change(newValue)
this.$emit("wapperClick", item); this.data.list = newValue
}, this.$nextTick(() => {
// 图片点击事件 this.initValue(this.curIndex, "watch==>")
imageClick(item) { })
this.$emit("imageClick", item); } else {
}, this.adds.push(newValue)
}, }
watch: { })
modelValue: { }, 10)
deep: true, },
handler(newValue, oldValue) { },
setTimeout(() => { column(newValue) {
this.$nextTick(() => { this.refresh()
if (this.isRefresh) return false; },
if (this.isLoaded) { },
this.refresh(); }
if (newValue.length <= this.curIndex)
return this.change(newValue);
this.data.list = newValue;
this.$nextTick(() => {
this.initValue(this.curIndex, "watch==>");
});
} else {
this.adds.push(newValue);
}
});
}, 10);
},
},
column(newValue) {
this.refresh();
},
},
};
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.waterfalls-flow { .waterfalls-flow {
overflow: hidden; overflow: hidden;
&-column { &-column {
float: left; float: left;
} }
} }
.column-value { .column-value {
width: 100%; width: 100%;
font-size: 0; font-size: 0;
overflow: hidden; overflow: hidden;
transition: opacity 0.4s; transition: opacity 0.4s;
opacity: 0; opacity: 0;
&-show { &-show {
opacity: 1; opacity: 1;
} }
.inner { .inner {
font-size: 30rpx; font-size: 30rpx;
} }
.img { .img {
width: 100%; width: 100%;
&-hide { &-hide {
display: none; display: none;
} }
&-error { &-error {
background: #f2f2f2 background: #f2f2f2
url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAC4AAAAiAQMAAAAatXkPAAAABlBMVEUAAADMzMzIT8AyAAAAAXRSTlMAQObYZgAAAIZJREFUCNdlzjEKwkAUBNAfEGyCuYBkLyLuxRYW2SKlV1JSeA2tUiZg4YrLjv9PGsHqNTPMSAQuyAJgRDHSyvBPwtZoSJXakeJI9iuRLGDygdl6V0yKDtyMAeMPZySj8yfD+UapvRPj2JOwkyAooSV5IwdDjPdCPspe8LyTl9IKJvDETKKRv6vnlUasgg0fAAAAAElFTkSuQmCC) url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAC4AAAAiAQMAAAAatXkPAAAABlBMVEUAAADMzMzIT8AyAAAAAXRSTlMAQObYZgAAAIZJREFUCNdlzjEKwkAUBNAfEGyCuYBkLyLuxRYW2SKlV1JSeA2tUiZg4YrLjv9PGsHqNTPMSAQuyAJgRDHSyvBPwtZoSJXakeJI9iuRLGDygdl6V0yKDtyMAeMPZySj8yfD+UapvRPj2JOwkyAooSV5IwdDjPdCPspe8LyTl9IKJvDETKKRv6vnlUasgg0fAAAAAElFTkSuQmCC)
no-repeat center center; no-repeat center center;
} }
} }
} }
</style> </style>
+8
View File
@@ -0,0 +1,8 @@
// https://pinia.vuejs.org/
import { createPinia } from "pinia"
// 创建
const pinia = createPinia()
// 导出
export default pinia
+14
View File
@@ -0,0 +1,14 @@
import { defineStore } from "pinia"
export const usePayStore = defineStore("pay", {
state: (): { payData: { id?: string; name?: string } } => {
return {
payData: {},
}
},
actions: {
setPayData(data: any) {
this.payData = data
},
},
})
+21
View File
@@ -0,0 +1,21 @@
/**
* 显示价格把分转换到元
* @param price
* @returns
*/
export function displayPrice(price: any, suffix: string = "元", fixed = 2) {
if (typeof price === "undefined") return "0.00" + suffix
const parsedNumber = typeof price === "string" ? parseFloat(price) : price
return (parsedNumber / 100.0).toFixed(fixed) + suffix
}
/**
* 把显示价格改为分
* @param price
* @returns
*/
export const storePrice = (num: number | string | undefined) => {
if (typeof num === "undefined") return 0
const parsedNumber = typeof num === "string" ? parseFloat(num) : num
return Math.round(parsedNumber * 100)
}
+2 -2
View File
@@ -1,2 +1,2 @@
export default () => import.meta.env.VITE_DEV_ENV === "dev" // export default () => import.meta.env.VITE_DEV_ENV === "dev"
// export default () => process.env.NODE_ENV === "development" export default () => process.env.NODE_ENV === "development"
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB