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

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_IMAGE_BASE_PATH = http://localhost:9999
# VITE_IMAGE_BASE_PATH = http://192.168.101.29:9999 # 邓-本地
# VITE_IMAGE_BASE_PATH = http://192.168.101.37:9999 # 邓-本地
#VITE_IMAGE_BASE_PATH = http://localhost:9999
# VITE_IMAGE_BASE_PATH = http://192.168.101.64:9999 # 邓-本地
# VITE_IMAGE_BASE_PATH = https://123.156.230.15:8089/api # 线上
# VITE_IMAGE_BASE_PATH = http://220.191.229.171:8090/api # 线上
# VITE_IMAGE_BASE_PATH = https://stgl.pj.gov.cn/api # 线上
# VITE_IMAGE_BASE_PATH = http://pjcloud.center.takin.cc # 张
#VITE_IMAGE_BASE_PATH = http://59.202.170.152:81/api # 信创线上
VITE_IMAGE_BASE_PATH = http://59.202.170.152:81/api # 信创线上
# ******************** start 开发环境 start ********************
; VITE_APP_DEV_SERVICE = http://59.202.170.152:81/api # 信创线上
VITE_APP_DEV_SERVICE = https://stgl.pj.gov.cn/api
# VITE_APP_DEV_SERVICE = http://192.168.101.50:9999 # 邓-本地
; VITE_APP_DEV_SERVICE = http://127.0.0.1:9999
# VITE_APP_DEV_SERVICE = http://59.202.170.152:81/api # 信创线上
# VITE_APP_DEV_SERVICE = https://stgl.pj.gov.cn/app-api
VITE_APP_DEV_SERVICE = http://192.168.101.64:9999 # 邓-本地
# VITE_APP_DEV_SERVICE = http://127.0.0.1:9999
# VITE_APP_DEV_SERVICE = http://123.156.230.15:8089/api/ # 线上
# VITE_APP_DEV_SERVICE = http://220.191.229.171:8090/api # 线上
; VITE_APP_DEV_SERVICE = http://localhost:9999
# VITE_APP_DEV_SERVICE = http://localhost:9999
# ******************** end 开发环境 end ********************
# ******************** 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 = https://stgl.pj.gov.cn/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 ********************
VITE_DEV_ENV = dev
#VITE_DEV_ENV = prod
# VITE_DEV_ENV = dev
# VITE_DEV_ENV = prod
+21 -22
View File
@@ -1,25 +1,24 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<script src="https://dapp.tmuyun.com/oss-static/app/jcommind.js"></script>
<script>
var coverSupport =
"CSS" in window &&
typeof CSS.supports === "function" &&
(CSS.supports("top: env(a)") || CSS.supports("top: constant(a)"));
document.write(
'<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' +
(coverSupport ? ", viewport-fit=cover" : "") +
'" />'
);
</script>
<title></title>
<!--preload-links-->
<!--app-context-->
</head>
<body>
<div id="app"><!--app-html--></div>
<script type="module" src="/src/main.ts"></script>
</body>
<head>
<meta charset="UTF-8" />
<script src="https://dapp.tmuyun.com/oss-static/app/jcommind.js"></script>
<script src="https://g.alicdn.com/gdt/jsapi/1.9.43/index.js"></script>
<script>
var coverSupport =
"CSS" in window && typeof CSS.supports === "function" && (CSS.supports("top: env(a)") || CSS.supports("top: constant(a)"))
document.write(
'<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' +
(coverSupport ? ", viewport-fit=cover" : "") +
'" />',
)
</script>
<title></title>
<!--preload-links-->
<!--app-context-->
</head>
<body>
<div id="app"><!--app-html--></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>
+2
View File
@@ -62,12 +62,14 @@
"@zebra-ui/swiper": "^2.2.8",
"crypto-js": "^4.2.0",
"dayjs": "^1.11.13",
"gdt-jsapi": "^1.9.51",
"luch-request": "^3.1.1",
"pinia": "^2.2.6",
"qs": "^6.13.1",
"radash": "^12.1.0",
"vue": "^3.3.11",
"vue-i18n": "^9.1.9",
"vue-waterfall-plugin-next": "^2.6.5",
"z-paging": "^2.8.0"
},
"devDependencies": {
+24
View File
@@ -65,6 +65,9 @@ importers:
dayjs:
specifier: ^1.11.13
version: 1.11.13
gdt-jsapi:
specifier: ^1.9.51
version: 1.9.51
luch-request:
specifier: ^3.1.1
version: 3.1.1
@@ -83,6 +86,9 @@ importers:
vue-i18n:
specifier: ^9.1.9
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:
specifier: ^2.8.0
version: 2.8.4
@@ -1295,6 +1301,9 @@ packages:
'@polka/url@1.0.0-next.28':
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':
resolution: {integrity: sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ==}
engines: {node: '>=14.0.0'}
@@ -2404,6 +2413,9 @@ packages:
function-bind@1.1.2:
resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
gdt-jsapi@1.9.51:
resolution: {integrity: sha512-VN1iIK7kJU2g2oxY/n8waCREhWxcVwR8qHAE1keVnUJHI6mTdgTelICzq++niRRCaLqUVWC1pYvftEVgk4sq8A==}
generic-names@4.0.0:
resolution: {integrity: sha512-ySFolZQfw9FoDb3ed9d80Cm9f0+r7qj+HJkWjeD9RBfpxEVTlVhol+gvaQB/78WbwYfbnNh8nWHHBSlg072y6A==}
@@ -3846,6 +3858,9 @@ packages:
peerDependencies:
typescript: '*'
vue-waterfall-plugin-next@2.6.5:
resolution: {integrity: sha512-8ACGbdjoyKLiJfnKXB8h8f9eE14lhyzfI1N1nrfVAIRczSpNY1KRwGOnVXN5OHqheLl3V1C0uVVRPtjTJkHkhw==}
vue@3.5.13:
resolution: {integrity: sha512-wmeiSMxkZCSc+PM2w2VRsOYAZC8GdipNFRTsLSfodVqI9mbejKeXEGr8SckuLnrQPGe3oJN5c3K0vpoU9q/wCQ==}
peerDependencies:
@@ -5960,6 +5975,8 @@ snapshots:
'@polka/url@1.0.0-next.28': {}
'@remax/mini-types@0.1.0': {}
'@rollup/pluginutils@5.1.4(rollup@4.34.2)':
dependencies:
'@types/estree': 1.0.6
@@ -7202,6 +7219,11 @@ snapshots:
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:
dependencies:
loader-utils: 3.3.1
@@ -8834,6 +8856,8 @@ snapshots:
semver: 7.7.1
typescript: 4.9.5
vue-waterfall-plugin-next@2.6.5: {}
vue@3.5.13(typescript@4.9.5):
dependencies:
'@vue/compiler-dom': 3.5.13
+11 -12
View File
@@ -1,18 +1,17 @@
import { createSSRApp } from "vue";
import "uno.css";
import * as Pinia from "pinia";
import { createSSRApp } from "vue"
import "uno.css"
import pinia from "../src/sheep/stores/index"
import App from "./App.vue";
import tmUi from "./uni_modules/tm-ui";
import App from "./App.vue"
import tmUi from "./uni_modules/tm-ui"
export function createApp() {
const app = createSSRApp(App);
const app = createSSRApp(App)
app.use(Pinia.createPinia());
app.use(tmUi);
app.use(pinia)
app.use(tmUi)
return {
app,
Pinia,
};
return {
app,
}
}
+38
View File
@@ -30,6 +30,20 @@
"disableScroll": true
}
},
// {
// "path": "pages/tabbar/flowStatistics",
// "style": {
// "navigationBarTitleText": "流水统计",
// "disableScroll": true
// }
// },
// {
// "path": "pages/tabbar/individualOrder",
// "style": {
// "navigationBarTitleText": "订单",
// "disableScroll": true
// }
// },
{
"path": "pages/tabbar/my",
"style": {
@@ -256,6 +270,18 @@
}
}
]
},
{
"root": "pages/pay",
"pages": [
{
"path": "scanPay",
"style": {
"navigationBarTitleText": "",
"disableScroll": true
}
}
]
}
],
"globalStyle": {
@@ -285,6 +311,18 @@
"iconPath": "static/tabbar/order.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",
"text": "我的",
+164 -164
View File
@@ -1,215 +1,215 @@
<script setup lang="ts">
import { ref, reactive } from "vue";
import { onLoad, onShow } from "@dcloudio/uni-app";
import { ref, reactive } from "vue"
import { onLoad } from "@dcloudio/uni-app"
import { isEmpty, max, min } from "radash"
import dayjs from "dayjs"
import { hooks, router } from "@@/index"
import { router } from "@@/index"
import { boxesApi } from "@@/api"
const data = {
}
const state = reactive<any>({
detailType: "add",
detailId: null,
detail: null,
rechargeList: [],
selectRechargeList: [],
selectRechargeIdList: [],
pickerDate: {
start: "",
end: "",
}
detailType: "add",
detailId: null,
detail: null,
rechargeList: [],
selectRechargeList: [],
selectRechargeIdList: [],
pickerDate: {
start: "",
end: "",
},
})
const applyForm = reactive<any>({
displayTimeRange: "",
displayTimeRangeStr: "",
bxDate: null,
displayTimeRange: "",
displayTimeRangeStr: "",
bxDate: null,
})
const applyFormRules = reactive<any>({
bxDate: [
{ required: true, message: '预约时间不能为空' }
],
bxDate: [{ required: true, message: "预约时间不能为空" }],
})
onLoad((options: any) => {
const { type, id } = options
if (!isEmpty(type)) state.detailType = type
if (!isEmpty(id)) state.detailId = id
if (type === 'view') {
getDetail()
}
const today = dayjs()
state.pickerDate.start = dayjs().format('YYYY-MM-DD')
state.pickerDate.end = today.add(2, 'month').format('YYYY-MM-DD')
applyForm.bxDate = state.pickerDate.start
getDateRange()
});
onShow(() => {
const { type, id } = options
if (!isEmpty(type)) state.detailType = type
if (!isEmpty(id)) state.detailId = id
if (type === "view") {
getDetail()
}
const today = dayjs()
state.pickerDate.start = dayjs().format("YYYY-MM-DD")
state.pickerDate.end = today.add(2, "month").format("YYYY-MM-DD")
applyForm.bxDate = state.pickerDate.start
getDateRange()
})
const getDetail = async () => {
if (isEmpty(state.detailId)) return
const _pa = { id: state.detailId }
const { data } = await boxesApi.detail(_pa)
if (!isEmpty(data)) {
state.detail = data
}
if (isEmpty(state.detailId)) return
const _pa = { id: state.detailId }
const { data } = await boxesApi.detail(_pa)
if (!isEmpty(data)) {
state.detail = data
}
}
const getDateRange = async () => {
const _pa = { id: state.detailId, currentDate: applyForm.bxDate }
const { data } = await boxesApi.get(_pa)
data.avaliabilityRespList.forEach(v => {
v.dateTime = `${v.bxDate} ${v.hour}`
v.timestamp = dayjs(v.dateTime).valueOf()
});
state.rechargeList = data.avaliabilityRespList
const _pa = { id: state.detailId, currentDate: applyForm.bxDate }
const { data } = await boxesApi.get(_pa)
data.avaliabilityRespList.forEach((v) => {
v.dateTime = `${v.bxDate} ${v.hour}`
v.timestamp = dayjs(v.dateTime).valueOf()
})
state.rechargeList = data.avaliabilityRespList
}
const bxDateConfirm = async (e: any) => {
getDateRange()
getDateRange()
}
const doTimeItem = (v: any) => {
if (v.status == 1) {
uni.showToast({ title: '该时间段已被预约', icon: "none" })
return
}
const flag = state.selectRechargeList.some(i => i.id == v.id)
if (flag) {
state.selectRechargeList = state.selectRechargeList.filter(i => i.id != v.id)
if (state.selectRechargeList.length >= 2) {
const { timestamp: targetMin } = min(state.selectRechargeList, (i: any) => i.timestamp)
state.rechargeList.forEach(i => {
if (i.timestamp <= v.timestamp) {
state.selectRechargeList = state.selectRechargeList.filter(j => j.id != i.id)
}
})
}
} else {
state.selectRechargeList.push({ ...v })
if (state.selectRechargeList.length >= 2) {
const { timestamp: targetMax } = max(state.selectRechargeList, (i: any) => i.timestamp)
const { timestamp: targetMin } = min(state.selectRechargeList, (i: any) => i.timestamp)
state.rechargeList.forEach(i => {
if (i.timestamp >= targetMin && i.timestamp <= targetMax) {
state.selectRechargeList.push({ ...i })
}
})
}
}
state.selectRechargeIdList = state.selectRechargeList.map(v => v.id)
if (v.status == 1) {
uni.showToast({ title: "该时间段已被预约", icon: "none" })
return
}
const flag = state.selectRechargeList.some((i) => i.id == v.id)
if (flag) {
state.selectRechargeList = state.selectRechargeList.filter((i) => i.id != v.id)
if (state.selectRechargeList.length >= 2) {
const { timestamp: targetMin } = min(state.selectRechargeList, (i: any) => i.timestamp)
state.rechargeList.forEach((i) => {
if (i.timestamp <= v.timestamp) {
state.selectRechargeList = state.selectRechargeList.filter((j) => j.id != i.id)
}
})
}
} else {
state.selectRechargeList.push({ ...v })
if (state.selectRechargeList.length >= 2) {
const { timestamp: targetMax } = max(state.selectRechargeList, (i: any) => i.timestamp)
const { timestamp: targetMin } = min(state.selectRechargeList, (i: any) => i.timestamp)
state.rechargeList.forEach((i) => {
if (i.timestamp >= targetMin && i.timestamp <= targetMax) {
state.selectRechargeList.push({ ...i })
}
})
}
}
state.selectRechargeIdList = state.selectRechargeList.map((v) => v.id)
}
const applyFormRef = ref<any>(null)
const doSubmit = async () => {
applyFormRef.value.submit()
const { isPass } = applyFormRef.value.validate()
if (!isPass) return
try {
const { hour: hourMax } = max(state.selectRechargeList, (i: any) => i.timestamp)
const { hour: hourMin } = min(state.selectRechargeList, (i: any) => i.timestamp)
const _pa = {
boxesId: state.detailId,
startTime: hourMin,
endTime: hourMax,
bxDate: applyForm.bxDate,
}
const { data, code }: any = await boxesApi.apply(_pa)
if (code != 0) throw new Error()
uni.showLoading({ title: '预定中...', mask: false })
uni.hideLoading()
uni.showToast({ title: '申请成功', icon: "none" })
router.jump("/pages/boxes/apply-list")
} catch (error) {
console.error(error);
uni.hideLoading()
}
applyFormRef.value.submit()
const { isPass } = applyFormRef.value.validate()
if (!isPass) return
try {
const { hour: hourMax } = max(state.selectRechargeList, (i: any) => i.timestamp)
const { hour: hourMin } = min(state.selectRechargeList, (i: any) => i.timestamp)
const _pa = {
boxesId: state.detailId,
startTime: hourMin,
endTime: hourMax,
bxDate: applyForm.bxDate,
}
const { data, code }: any = await boxesApi.apply(_pa)
if (code != 0) throw new Error()
uni.showLoading({ title: "预定中...", mask: false })
uni.hideLoading()
uni.showToast({ title: "申请成功", icon: "none" })
router.jump("/pages/boxes/apply-list")
} catch (error) {
console.error(error)
uni.hideLoading()
}
}
</script>
<template>
<crud-layout title="预定" mainIsScroll bg="/static/page/blue-bg.png">
<view class="h-30rpx" />
<view class="card p-x-30rpx p-y-40rpx">
<tm-form ref="applyFormRef" v-model="applyForm" :rules="applyFormRules" direction="vertical">
<tm-form-item name="bxDate" label="预约时间" :showBottom="false">
<tm-picker-date v-model="applyForm.bxDate" :start="state.pickerDate.start"
:end="state.pickerDate.end" v-model:model-str="applyForm.bxDate" format="YYYY-MM-DD"
@confirm="bxDateConfirm">
<view :style="{ pointerEvents: state.detailType == 'view' ? 'auto' : 'none' }">
<tm-input v-model="applyForm.bxDate" disabled placeholder="请选择使用时间..">
<template v-slot:rightIcon>
<text v-if="state.detailType != 'view'"
class="p-0.5rem color-#b1b1b1 iconfont icon-xiangxiajiantouxiao"></text>
</template>
</tm-input>
</view>
</tm-picker-date>
</tm-form-item>
</tm-form>
</view>
<view class="prefix_title m-t-35rpx">时间段</view>
<view class="recharge p-30rpx bg-white rounded-20rpx m-t-20rpx shadow-main">
<view
:class="[state.selectRechargeIdList.includes(v.id) ? 'recharge_item_active' : '', v.status == 1 ? 'recharge_item_disabled' : '']"
class="recharge_item" v-for="(v, i) in state.rechargeList" :key="i" @tap="doTimeItem(v)">
<text class="sub-text-24 text-center">{{ v.bxDate }}</text>
<text class="sub-text-24 text-center">{{ v.hour }}</text>
</view>
</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>
<crud-layout title="预定" mainIsScroll bg="/static/page/blue-bg.png">
<view class="h-30rpx" />
<view class="card p-x-30rpx p-y-40rpx">
<tm-form ref="applyFormRef" v-model="applyForm" :rules="applyFormRules" direction="vertical">
<tm-form-item name="bxDate" label="预约时间" :showBottom="false">
<tm-picker-date
v-model="applyForm.bxDate"
:start="state.pickerDate.start"
:end="state.pickerDate.end"
v-model:model-str="applyForm.bxDate"
format="YYYY-MM-DD"
@confirm="bxDateConfirm"
>
<view :style="{ pointerEvents: state.detailType == 'view' ? 'auto' : 'none' }">
<tm-input v-model="applyForm.bxDate" disabled placeholder="请选择使用时间..">
<template v-slot:rightIcon>
<text v-if="state.detailType != 'view'" class="p-0.5rem color-#b1b1b1 iconfont icon-xiangxiajiantouxiao"></text>
</template>
</tm-input>
</view>
</tm-picker-date>
</tm-form-item>
</tm-form>
</view>
<view class="prefix_title m-t-35rpx ml-4">时间段</view>
<view class="recharge p-30rpx bg-white rounded-20rpx m-t-20rpx shadow-main">
<view
:class="[state.selectRechargeIdList.includes(v.id) ? 'recharge_item_active' : '', v.status == 1 ? 'recharge_item_disabled' : '']"
class="recharge_item"
v-for="(v, i) in state.rechargeList"
:key="i"
@tap="doTimeItem(v)"
>
<text class="sub-text-24 text-center">{{ v.bxDate }}</text>
<text class="sub-text-24 text-center">{{ v.hour }}</text>
</view>
</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>
<style lang="scss" scoped>
:deep() {
.tmFormItemLabel {
padding-bottom: 10rpx !important;
}
.tmFormItemLabel {
padding-bottom: 10rpx !important;
}
}
.recharge_item_active {
background: #e9f5fe;
border: 1px solid #e9f5fe !important;
background: #e9f5fe;
border: 1px solid #e9f5fe !important;
&>text {
color: #0094ff !important;
}
& > text {
color: #0094ff !important;
}
}
.recharge_item_disabled {
background: #999;
border: 1px solid #999 !important;
background: #999;
border: 1px solid #999 !important;
&>text {
color: white !important;
}
& > text {
color: white !important;
}
}
.recharge {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-gap: 15rpx;
border-bottom: 1px solid #f9f9f9;
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-gap: 15rpx;
border-bottom: 1px solid #f9f9f9;
&_item {
display: flex;
flex-direction: column;
border: 1px solid #cccccc;
border-radius: 16rpx;
padding: 20rpx 0;
}
&_item {
display: flex;
flex-direction: column;
border: 1px solid #cccccc;
border-radius: 16rpx;
padding: 20rpx 0;
}
}
</style>
</style>
+50 -55
View File
@@ -1,83 +1,78 @@
<script setup lang="ts">
import { ref, reactive } from "vue";
import { onLoad, onShow } from "@dcloudio/uni-app";
import { reactive } from "vue"
import { onLoad, onShow } from "@dcloudio/uni-app"
import { isEmpty } from "radash"
import { hooks, router } from "@@/index"
import { router } from "@@/index"
import { boxesApi } from "@@/api"
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 { filePath } from "@/sheep/utils/file"
const data = {
}
const state = reactive<any>({
detailId: null,
detail: {},
detailId: null,
detail: {},
})
onLoad((options: any) => {
if (!isEmpty(options.id)) {
state.detailId = options.id
}
});
if (!isEmpty(options.id)) {
state.detailId = options.id
}
})
onShow(() => {
getDetail()
getDetail()
})
const getDetail = async () => {
const _pa = { id: state.detailId }
const { data } = await boxesApi.detail(_pa)
state.detail = data
state.detail.imagesArray = data.images?.split(",")
const _pa = { id: state.detailId }
const { data } = await boxesApi.detail(_pa)
state.detail = data
state.detail.imagesArray = data.images?.split(",")
}
const doSubmit = () => {
router.jump('/pages/boxes/apply', { id: state.detail.id })
router.jump("/pages/boxes/apply", { id: state.detail.id })
}
</script>
<template>
<crud-layout title="" mainIsScroll tabBarType="just-flot-back" bg="/static/page/blue-bg.png">
<z-swiper>
<z-swiper-item v-for="(v, i) in state.detail.imagesArray" :key="i">
<image class="w-100vw" :src="v" mode="widthFix" />
</z-swiper-item>
</z-swiper>
<view class="p-x-15rpx">
<view class="flex-col justify-between card p-y-20rpx p-x-30rpx">
<view class="flex-row items-center justify-between">
<view class="flex-row items-center">
<view class="second-text-46 color-#f63a36!">¥{{ state.detail.price }}</view>
</view>
<view class="second-text-26">可容纳{{ state.detail.capacity }}</view>
</view>
<view class="flex-col m-t-15rpx">
<view class="sub-text-32">{{ state.detail.name }}</view>
</view>
</view>
<view class="h-15rpx" />
<view class="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>
<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!"
@tap="doSubmit">
预定
</view>
</template>
</crud-layout>
<crud-layout mainIsScroll tabBarType="just-flot-back" bg="/static/page/blue-bg.png">
<z-swiper>
<z-swiper-item v-for="(v, i) in state.detail.imagesArray" :key="i">
<image class="w-100vw" :src="filePath(v)" mode="widthFix" />
</z-swiper-item>
</z-swiper>
<view class="p-x-15rpx">
<view class="flex-col justify-between card p-y-20rpx p-x-30rpx">
<view class="flex-row items-center justify-between">
<view class="flex-row items-center">
<view class="second-text-46 color-#f63a36!">¥{{ state.detail.price }}</view>
</view>
<view class="second-text-26">可容纳{{ state.detail.capacity }}</view>
</view>
<view class="flex-col m-t-15rpx">
<view class="sub-text-32">{{ state.detail.name }}</view>
</view>
</view>
<view class="h-15rpx" />
<view class="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>
<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!" @tap="doSubmit">
预定
</view>
</template>
</crud-layout>
</template>
<style lang="scss" scoped>
:deep() {
.layout_main>scroll-view {
padding: 0 !important;
}
.layout_main > scroll-view {
padding: 0 !important;
}
}
</style>
</style>
+13 -5
View File
@@ -1,5 +1,5 @@
<script setup lang="ts">
import { ref, reactive } from "vue"
import { ref, reactive, computed } from "vue"
import { onLoad, onShow } from "@dcloudio/uni-app"
import { isEmpty } from "radash"
@@ -8,6 +8,7 @@ import { boxesApi } from "@@/api"
import zTabs from "@@/components/other/z-tabs/z-tabs.vue"
import CustomWaterfallsFlow from "@@/components/other/custom-waterfalls-flow/custom-waterfalls-flow.vue"
import { filePath } from "@/sheep/utils/file"
const data = {
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 pageHook = hooks.usePage(pageRef, boxesApi.page, null, "data.records")
const query = (page: number, pagesize: number) => {
@@ -61,7 +69,7 @@ const doCard = (v: any) => {
height="100%"
:fixed="false"
v-model="pageHook.list"
:default-page-size="5"
:default-page-size="999"
safe-area-inset-bottom
:loading-more-enabled="true"
:show-scrollbar="false"
@@ -76,16 +84,16 @@ const doCard = (v: any) => {
</view>
</template>
<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">
<view class="p-x-15rpx p-t-10rpx p-b-20rpx">
<view class="sub-text-28 show-line">{{ v.name }}</view>
<view class="m-t-10rpx flex-row items-center">
<view class="second-text-32 color-#f63a36!"> ¥{{ v.price }} </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="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">
<tm-tag v-if="v.status == 0" size="xs" color="success">
{{ 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>
</div>
<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" />
<tm-modal v-if="false" title="确定删除吗?" height="auto" @confirm="doDel(v.id)">
<template v-slot:trigger><text class="botder_btn">删除</text></template>
@@ -81,11 +81,7 @@ const doDel = (id: string) => {
</view>
</view>
<template #bottom>
<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"
>
<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">
添加
</view>
<view class="h-30rpx" />
+27 -22
View File
@@ -1,5 +1,5 @@
<script setup lang="ts">
import { ref, reactive, nextTick } from "vue"
import { reactive, nextTick } from "vue"
import { onLoad, onShow } from "@dcloudio/uni-app"
import { isEmpty } from "radash"
@@ -15,7 +15,6 @@ import ProductRow from "./components/product-row.vue"
import ProductCar from "./components/product-car.vue"
import ProductTotal from "./components/product-total.vue"
const data = {}
const state = reactive<any>({
detailId: null,
totPrice: 0,
@@ -41,9 +40,14 @@ onShow(() => {
})
const getDetail = async () => {
uni.showLoading({
title: "加载中...",
mask: true,
})
const _pa = { id: state.detailId }
const { data } = await merchantApi.detail(_pa)
state.detail = data
uni.hideLoading()
}
const getShopCar = async () => {
@@ -201,7 +205,7 @@ const getHeight = () => {
const doPhone = () => {
if (isEmpty(state.detail.phone)) {
uni.showToast({ title: "该店铺没有预留电话", icon: "none" })
uni.showToast({ title: "该商户没有预留电话", icon: "none" })
return
}
hooks.useMakePhoneCall(state.detail.phone)
@@ -226,26 +230,30 @@ const doFood = () => {
<!-- start 简介 start -->
<view class="h-15rpx" />
<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-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>
</view>
<view>
<tm-tag size="s">{{ state.detail.deptName }}</tm-tag>
</view>
</view>
<view class="m-t-10rpx second-text-28">
<text>营业时间</text>
<text class="m-l-10rpx">
{{ state.detail.jobStartTime }}
~
{{ state.detail.jobEndTime }}
</text>
<view class="second-text-24">
<view class="second-text-28">营业时间:</view>
<view>
{{ state.detail.jobTime?.split(",")[0] ? "早:" + state.detail.jobTime?.split(",")[0] : "" }}
</view>
<view>
{{ 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 class="m-t-10rpx second-text-28">
<text>食堂地址</text>
<view v-if="state.detail.addressDes" class="m-t-10rpx second-text-28">
<text>食堂地址:</text>
<text class="m-l-10rpx">{{ state.detail.addressDes }}</text>
</view>
</view>
@@ -283,6 +291,7 @@ const doFood = () => {
<view class="h-15rpx" />
<view class="flex-row">
<scroll-view
v-if="state.classifyList.length > 0"
scroll-y
:style="{ height: getHeight() }"
class="menu w-200rpx h-full p-l-12rpx p-b-20rpx bg-#f6f6f6"
@@ -299,7 +308,7 @@ const doFood = () => {
</view>
</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 class="m-x-15rpx">
<product-row
@@ -318,17 +327,13 @@ const doFood = () => {
</view>
</view>
</scroll-view>
<view v-else class="mx-auto mt-10 second-text-28">暂无信息</view>
</view>
</tm-sticky>
<!-- end 商品 end -->
<template #main-bottom>
<view class="car z-200 p-x-30rpx p-y-30rpx bg-white">
<product-total
:totPrice="state.totPrice"
:totCount="state.totCount"
@doContainer="doVisibleCar"
@submit="doPay"
/>
<view v-if="state.classifyList.length > 0" class="car z-200 p-x-30rpx p-y-30rpx bg-white">
<product-total :totPrice="state.totPrice" :totCount="state.totCount" @doContainer="doVisibleCar" @submit="doPay" />
</view>
</template>
</crud-layout>
+55 -18
View File
@@ -1,19 +1,19 @@
<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 { isEmpty } from "radash"
import dayjs from "dayjs"
import { hooks, router } from "@@/index"
import { foodApi } from "@@/api"
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"
const data = {
const menus = {
tabs: [
{ id: null, name: "全部", disabled: false },
// { id: null, name: "全部", disabled: false },
{ id: 1, name: "早餐", disabled: false },
{ id: 2, name: "午餐", disabled: false },
{ id: 3, name: "晚餐", disabled: false },
@@ -26,7 +26,7 @@ const state = reactive<any>({
pa: {
merchantId: null,
startTime: null,
hourType: data.tabs[0].id,
hourType: menus.tabs[0].id,
},
})
@@ -60,7 +60,7 @@ const initDate = () => {
const now = new Date()
for (let i = 0; i < 10; i++) {
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({
weekDayStr,
date: date.toDate(),
@@ -76,17 +76,19 @@ const initDate = () => {
const doDateItem = (v: any, i: any) => {
state.currentDateIndex = i
state.pa.startTime = state.dateList[i].dateTime
pageHook.list = []
pageRef.value.reload(true)
}
const doTab = (e: any) => {
const target = data.tabs[e]
const target = menus.tabs[e]
state.pa.hourType = target.id
pageHook.list = []
pageRef.value.reload(true)
}
const doProduct = (v: any) => {
router.jump("/pages/merchant/product-detail", { id: v.spuId })
// router.jump("/pages/merchant/product-detail", { spuId: v.spuId })
}
</script>
@@ -97,7 +99,7 @@ const doProduct = (v: any) => {
height="100%"
:fixed="false"
v-model="pageHook.list"
:default-page-size="5"
:default-page-size="8"
safe-area-inset-bottom
:loading-more-enabled="true"
:show-scrollbar="false"
@@ -107,7 +109,7 @@ const doProduct = (v: any) => {
@scroll="pageHook.scroll"
>
<template #top>
<view class="bg-#1777FF p-15rpx pt-10">
<view class="bg-#1777FF p-15rpx">
<scroll-view scroll-x class="whitespace-nowrap">
<view class="flex-row items-center space-x-15rpx">
<view
@@ -117,19 +119,54 @@ const doProduct = (v: any) => {
:key="i"
@tap="doDateItem(v, i)"
>
<view class="">{{ v.dayTime }}</view>
<view class="">{{ v.weekDayStr }}</view>
<view>{{ v.dayTime }}</view>
<view>{{ v.weekDayStr }}</view>
</view>
</view>
</scroll-view>
</view>
<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>
</template>
<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">
<view class="p-x-15rpx p-y-25rpx">
<view class="sub-text-28 show-line">{{ v.name }}</view>
@@ -144,7 +181,7 @@ const doProduct = (v: any) => {
</view>
</view>
</template>
</custom-waterfalls-flow>
</custom-waterfalls-flow> -->
</view>
</z-paging>
</crud-layout>
+56 -70
View File
@@ -1,87 +1,73 @@
<script setup lang="ts">
import { ref, reactive } from "vue";
import { onLoad, onShow } from "@dcloudio/uni-app";
import { isEmpty } from "radash";
import { reactive } from "vue"
import { onLoad, onShow } from "@dcloudio/uni-app"
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>({
detailId: null,
detail: null,
});
detailId: null,
detail: null,
})
onLoad((options: any) => {
if (!isEmpty(options.id)) {
state.detailId = options.id;
}
});
if (!isEmpty(options.id)) {
state.detailId = options.id
}
})
onShow(() => {
getDetail();
});
getDetail()
})
const getDetail = async () => {
const _pa = { id: state.detailId };
const { data } = await productApi.get(_pa);
state.detail = data;
};
uni.showLoading({
title: "加载中...",
})
const _pa = { id: state.detailId }
const { data } = await productApi.get(_pa)
state.detail = data
uni.hideLoading()
}
</script>
<template>
<crud-layout
title="订单详情"
tabBarType="just-flot-back"
bg="/static/page/blue-bg.png"
>
<image
class="w-100vw"
:src="filePath(state.detail.picUrl)"
mode="widthFix"
/>
<view class="p-x-15rpx">
<view class="flex-col justify-between card p-y-20rpx p-x-30rpx">
<view class="flex-row items-center justify-between">
<view class="flex-row items-center">
<view class="second-text-46 color-#f63a36!"
>¥{{ state.detail.price }}</view
>
<view class="m-l-20rpx second-text-28 line-through"
>¥{{ state.detail.marketPrice }}</view
>
</view>
<view class="second-text-26">已售{{ state.detail.salesCount }}</view>
</view>
<view class="flex-col m-t-15rpx">
<view class="sub-text-32">{{ state.detail.name }}</view>
<view class="m-t-15rpx second-text-26">{{
state.detail.introduction
}}</view>
</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>
<crud-layout title="订单详情" tabBarType="just-flot-back" bg="/static/page/blue-bg.png">
<view v-if="state.detail">
<image class="w-100vw" :src="filePath(state.detail.picUrl)" mode="widthFix" />
<view class="p-x-15rpx">
<view class="flex-col justify-between card p-y-20rpx p-x-30rpx">
<view class="flex-row items-center justify-between">
<view class="flex-row items-center">
<view class="second-text-46 color-#f63a36!">¥{{ state.detail.price }}</view>
<view class="m-l-20rpx second-text-28 line-through">¥{{ state.detail.marketPrice }}</view>
</view>
<view class="second-text-26">已售{{ state.detail.salesCount }}</view>
</view>
<view class="flex-col m-t-15rpx">
<view class="sub-text-32">{{ state.detail.name }}</view>
<view class="m-t-15rpx second-text-26">{{ state.detail.introduction }}</view>
</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>
</view>
<view v-else class="second-text-28 mt-24 text-center">暂无数据</view>
</crud-layout>
</template>
<style lang="scss" scoped>
:deep() {
.layout_main > scroll-view {
padding: 0 !important;
}
.layout_main > scroll-view {
padding: 0 !important;
}
}
</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: [],
})
const uploadApplyPicUrls = ref<Array<Record<string, any> | string>>([]) // 补充凭证图片
const applyPicUrls = computed(() =>
uploadApplyPicUrls.value.map((item: any) => JSON.parse(item.response).data.url).join(","),
)
const applyPicUrls = computed(() => uploadApplyPicUrls.value.map((item: any) => JSON.parse(item.response).data.url).join(","))
const applyForm = reactive<any>({
way: data.payType[0].type,
@@ -154,14 +152,7 @@ const doSubmit = async () => {
<view class="sub-text-28">售后类型</view>
<view class="m-t-20rpx">
<tm-radio-group @change="radioChange" direction="column" gap="20" v-model="applyForm.way">
<tm-radio
:disabled="v.disabled"
v-for="(v, i) in data.payType"
:key="i"
v-show="v.visible"
:value="v.type"
:label="v.text"
/>
<tm-radio :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>
</view>
</view>
@@ -187,7 +178,6 @@ const doSubmit = async () => {
</tm-picker>
</view>
<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="m-t-20rpx">
<tm-upload-photo
@@ -201,15 +191,9 @@ const doSubmit = async () => {
<view class="sub-text-20 c-red!">注:图片大小不超过5M,最多上传6张</view>
</view>
<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="m-t-20rpx">
<tm-input
v-model="applyForm.remark"
type="textarea"
:showClear="false"
placeholder="客官~请描述您遇到的问题"
></tm-input>
<tm-input v-model="applyForm.remark" type="textarea" :showClear="false" placeholder="客官~请描述您遇到的问题"></tm-input>
</view>
</view>
<view class="h-30rpx" />
+27 -29
View File
@@ -14,24 +14,18 @@
<view class="h-15rpx" />
<!-- start 简介 start -->
<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-row items-center justify-between">
<view class="flex-row-center sub-text-36">
<text>{{ state.detail.name }}</text>
</view>
<view>
<tm-tag size="s">{{ state.detail.deptName }}</tm-tag>
</view>
<view class="flex-row-center sub-text-32">{{ state.detail.name }}</view>
<tm-tag size="s">{{ state.detail.deptName }}</tm-tag>
</view>
<view class="second-text-28">{{ state.detail.phone }}</view>
<view class="m-t-10rpx second-text-28">
<text>营业时间</text>
<text class="m-l-10rpx">
{{ state.detail.jobStartTime }}
~
{{ state.detail.jobEndTime }}
</text>
<view class="second-text-24">{{ state.detail.phone }}</view>
<view class="second-text-24">
<view class="second-text-28">营业时间:</view>
<view>{{ state.detail.jobTime?.split(",")[0] ? "早:" + state.detail.jobTime?.split(",")[0] : "" }}</view>
<view>{{ 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 v-if="state.detail.addressDes" class="m-t-10rpx second-text-28">
<text>地址</text>
@@ -47,11 +41,7 @@
<!-- start 商品 start -->
<view class="flex-row">
<scroll-view
scroll-y
:style="{ height: getHeight() }"
class="menu w-200rpx h-full p-l-12rpx p-b-20rpx bg-#f6f6f6"
>
<scroll-view scroll-y :style="{ height: getHeight() }" class="menu w-200rpx h-full p-l-12rpx p-b-20rpx bg-#f6f6f6">
<view
class="menu_item flex-row-center"
v-for="(v, i) in state.classifyList"
@@ -86,12 +76,7 @@
<template #main-bottom>
<view class="car z-200 p-x-30rpx p-y-30rpx bg-white">
<product-total
:totPrice="state.totPrice"
:totCount="state.totCount"
@doContainer="doVisibleCar"
@doPay="doPay"
/>
<product-total :totPrice="state.totPrice" :totCount="state.totCount" @doContainer="doVisibleCar" @doPay="doPay" />
</view>
</template>
</crud-layout>
@@ -149,9 +134,22 @@ onLoad((options: any) => {
}
})
onShow(async () => {
await getDetail()
await getShopCar()
await getClassify()
uni.showLoading({
title: "加载中...",
mask: true,
})
try {
await getDetail()
await getShopCar()
await getClassify()
} catch (error) {
uni.showToast({
title: "加载失败",
icon: "error",
})
} finally {
uni.hideLoading()
}
})
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">
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 { filePath } from "@@/utils/file"
@@ -13,7 +12,6 @@ const state = reactive<any>({
},
})
onLoad(() => {})
onShow(() => {
if (pageRef.value) {
pageRef.value.reload(false)
@@ -52,23 +50,19 @@ const toDetail = async (v: any) => {
>
<view class="h-20rpx" />
<view class="flex-row card p-20rpx m-b-20rpx" v-for="(v, i) in pageHook.list" :key="i" @tap="toDetail(v)">
<image class="w-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-row items-center justify-between">
<view class="flex-row-center sub-text-34">
<text>{{ v.name }}</text>
</view>
<view class="flex-row-center sub-text-34">{{ v.name }}</view>
<view>
<tm-tag size="s">{{ v.deptName }}</tm-tag>
</view>
</view>
<view class="m-t-10rpx second-text-28">
<text>营业时间</text>
<text class="m-l-10rpx">
{{ v.jobStartTime }}
~
{{ v.jobEndTime }}
</text>
<view class="second-text-24">
<view class="second-text-28">营业时间:</view>
<view>{{ v.jobTime?.split(",")[0] ? "早:" + v.jobTime?.split(",")[0] : "" }}</view>
<view>{{ v.jobTime?.split(",")[1] ? "中:" + v.jobTime?.split(",")[1] : "" }}</view>
<view>{{ v.jobTime?.split(",")[2] ? "晚:" + v.jobTime?.split(",")[2] : "" }}</view>
</view>
<view v-if="v.addressDes" class="m-t-10rpx second-text-28">
<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 { userApi } from "@@/api"
import isDevEnv from "@/sheep/utils/isDevEnv"
import { usePayStore } from "@/sheep/stores/pay"
// import dd from "gdt-jsapi"
interface MenuItem {
text: string
@@ -59,6 +61,7 @@ const state = reactive<{ wallet: any; userInfo: any; menuList: MenuItem[] }>({
wallet: [],
userInfo: {},
menuList: [
{ text: "扫一扫", icon: "/static/icon/scan.png", router: "" },
{ 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_1.png", router: "/pages/apply/foreign-list" },
@@ -172,6 +175,40 @@ const doLogout = async () => {
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) => {
if (i == state.menuList.length - 1) {
router.jump(v.router)
@@ -179,7 +216,32 @@ const onTabMenu = async (v: MenuItem, i: number) => {
}
const isLogin = await hooks.useCheckLogin()
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(() => {
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>
<style lang="scss" scoped>
+12 -12
View File
@@ -13,7 +13,7 @@ const data = {
tabs: [
{ id: null, name: "全部", disabled: false },
{ id: 1, name: "未支付", disabled: false },
{ id: 5, name: "待核销", disabled: false },
{ id: 5, name: "已支付", disabled: false },
{ id: 10, name: "售后", disabled: false },
{ id: 20, name: "已核销", disabled: false },
],
@@ -49,7 +49,7 @@ const query = (page: number, pagesize: number) => {
}
const doToDetail = (v: any) => {
router.jump("/pages/order/detail", { id: v.id })
// router.jump("/pages/order/detail", { id: v.id })
}
const doAppraise = () => {}
@@ -94,7 +94,7 @@ const doRefund = (v: any) => {
<view class="flex-row items-center justify-between">
<view class="flex-row items-center">
<view class="main-text-28">{{ v.merchantName }}</view>
<view class="m-l-15rpx color-#999 font-size-26rpx! iconfont icon-youjiantou" />
<!-- <view class="m-l-15rpx color-#999 font-size-26rpx! iconfont icon-youjiantou" /> -->
</view>
<tm-tag v-if="v.orderStatus == 1" color="info" size="xs">未支付</tm-tag>
<tm-tag v-if="v.orderStatus == 5" color="success" size="xs">待核销</tm-tag>
@@ -108,14 +108,14 @@ const doRefund = (v: any) => {
{{ hooks.useTime(v.createTime, "{y}-{m}-{d} {h}:{i}:{s}") }}
</text>
</view>
<view class="second-text-22">
<!-- <view class="second-text-22">
{{ hooks.useEnum("hardwareRefundStatusEnum", v.refundStatus) }}
</view>
</view> -->
</view>
</view>
</view>
<view class="relative h-180rpx m-t-20rpx">
<view class="absolute top-0 right-0 bottom-0 left-0 h-180rpx">
<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">
<scroll-view scroll-x class="flex-row-center whitespace-nowrap">
<view class="flex-row items-center">
<view
@@ -138,11 +138,11 @@ const doRefund = (v: any) => {
</view>
</view>
</scroll-view>
</view>
<view class="absolute top-0 right-0 bottom-0 z-10 flex-col items-end w-160rpx p-x-20rpx bg-white bg-opacity-95">
<view class="main-text-30 color-red!">¥ {{ hooks.useMoney(v.totalPrice) }}</view>
<view class="m-t-10rpx second-text-26">共 {{ v.carList.length }} 件</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="m-t-2rpx m-r-20rpx second-text-26">共 {{ v.carList.length }} 件</view>
<view class="main-text-30 color-red!">¥ {{ hooks.useMoney(v.totalPrice) }}</view>
<!-- </view> -->
</view>
<view v-if="['5', '10'].includes(v.orderStatus)" class="flex-row items-center justify-end p-t-20rpx">
<!-- <view v-if="v.orderStatus == 5 && v.orderType == 2" class="botder_btn" @tap.stop="doRefund(v)">退款</view> -->
+21 -31
View File
@@ -1,31 +1,27 @@
<script setup lang="ts">
import { ref, reactive } from "vue"
import { onLoad, onShow } from "@dcloudio/uni-app"
import { hooks, router } from "@@/index"
import { onShow } from "@dcloudio/uni-app"
import { merchantApi } from "@@/api"
import { hooks, router } from "@@/index"
import { filePath } from "@@/utils/file"
const pageRef = ref<any>(null)
const state = reactive<any>({
pa: {
pagesize: 10,
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) => {
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 isLogin = await hooks.useCheckLogin()
if (isLogin) {
@@ -40,7 +36,7 @@ const toDetail = async (v: any) => {
ref="pageRef"
height="100%"
:fixed="false"
v-model="pageHook.list"
v-model="list"
:default-page-size="10"
safe-area-inset-bottom
:loading-more-enabled="true"
@@ -48,29 +44,23 @@ const toDetail = async (v: any) => {
@query="query"
:auto-clean-list-when-reload="false"
:auto-scroll-to-top-when-reload="false"
@scroll="pageHook.scroll"
@scroll="scroll"
>
<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">
<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-row items-center justify-between">
<view class="flex-row-center sub-text-34">
<text> {{ v.name }}</text>
</view>
<view>
<tm-tag size="s">{{ v.deptName }}</tm-tag>
</view>
<view class="flex-row-center sub-text-34">{{ v.name }}</view>
<tm-tag size="s">{{ v.deptName }}</tm-tag>
</view>
<view class="second-text-28">{{ v.phone }}</view>
<view class="m-t-10rpx second-text-28">
<text>营业时间</text>
<text class="m-l-10rpx">
{{ v.jobStartTime }}
~
{{ v.jobEndTime }}
</text>
<view class="second-text-24">{{ v.phone }}</view>
<view class="second-text-24">
<view class="second-text-28">营业时间:</view>
<view>{{ v.jobTime?.split(",")[0] ? "早:" + v.jobTime?.split(",")[0] : "" }}</view>
<view>{{ v.jobTime?.split(",")[1] ? "中:" + v.jobTime?.split(",")[1] : "" }}</view>
<view>{{ v.jobTime?.split(",")[2] ? "晚:" + v.jobTime?.split(",")[2] : "" }}</view>
</view>
<view v-if="v.addressDes" class="m-t-10rpx second-text-28">
<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>
</view>
<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>
<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>
</z-paging>
@@ -198,7 +200,7 @@ const doFreeze = async () => {
</tm-form-item>
</tm-form>
<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
z-index="100"
@@ -216,7 +218,7 @@ const doFreeze = async () => {
</tm-form-item>
</tm-form>
<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
z-index="100"
@@ -233,5 +235,3 @@ const doFreeze = async () => {
</view>
</tm-drawer>
</template>
<style lang="scss" scoped></style>
+2 -2
View File
@@ -7,8 +7,8 @@ export default {
method: "POST",
data,
params: {
pageNo: data.pageNo,
pagesize: data.pagesize,
current: data.current,
size: data.size,
},
custom: {
showLoading: false,
+62 -51
View File
@@ -1,53 +1,64 @@
import request from "@/sheep/utils/request";
import request from "@/sheep/utils/request"
export default {
// 获得支付订单
getOrder: (params) => {
return request({
url: "/pay/order/get",
method: "GET",
params,
});
},
// 提交支付订单
submitOrder: (data) => {
return request({
url: "/pay/order/submit",
method: "POST",
data,
});
},
// 创建硬件订单
createHardwareOrder: (params) => {
return request({
url: "/hard/hard-order/app/create-order",
method: "GET",
params,
custom: {
showLoading: false,
},
});
},
// 结算
submitHardwareOrder: (data) => {
return request({
url: "/hardware/order/submit-order",
method: "POST",
data,
custom: {
showLoading: false,
},
});
},
// 退款
refundHardwareOrder: (params) => {
return request({
url: "/hardware/order/refund",
method: "GET",
params,
custom: {
showLoading: false,
},
});
},
};
// 获得支付订单
getOrder: (params) => {
return request({
url: "/pay/order/get",
method: "GET",
params,
})
},
// 提交支付订单
submitOrder: (data) => {
return request({
url: "/pay/order/submit",
method: "POST",
data,
})
},
// 创建硬件订单
createHardwareOrder: (params) => {
return request({
url: "/hard/hard-order/app/create-order",
method: "GET",
params,
custom: {
showLoading: false,
},
})
},
// 创建二维码订单
createQrCodeOrder: (data): any => {
return request({
url: "/hard/hard-order/app/create-order-scan-qrcode",
method: "POST",
data,
custom: {
showLoading: false,
},
})
},
// 结算
submitHardwareOrder: (data) => {
return request({
url: "/hardware/order/submit-order",
method: "POST",
data,
custom: {
showLoading: false,
},
})
},
// 退款
refundHardwareOrder: (params) => {
return request({
url: "/hardware/order/refund",
method: "GET",
params,
custom: {
showLoading: false,
},
})
},
}
@@ -1,382 +1,363 @@
<template>
<view class="waterfalls-flow">
<view
v-for="(item, index) in data.column"
:key="index"
class="waterfalls-flow-column"
:id="`waterfalls_flow_column_${index + 1}`"
:msg="msg"
:style="{ width: w, 'margin-left': index == 0 ? 0 : m }"
>
<view
:class="['column-value', { 'column-value-show': item2.o }]"
v-for="(item2, index2) in columnValue(index)"
:key="index2"
:style="[s1]"
@click.stop="wapperClick(item2)"
>
<view class="inner" v-if="data.seat == 1">
<!-- #ifdef MP-WEIXIN -->
<!-- #ifdef VUE2 -->
<slot name="slot{{item2.index}}"></slot>
<!-- #endif -->
<!-- #ifdef VUE3 -->
<slot :name="`slot${item2.index}`"></slot>
<!-- #endif -->
<!-- #endif -->
<!-- #ifndef MP-WEIXIN -->
<slot v-bind="item2"></slot>
<!-- #endif -->
</view>
<image
:class="[
'img',
{
'img-hide':
item2[hideImageKey] == true || item2[hideImageKey] == 1,
},
{ 'img-error': !item2[data.imageKey] },
]"
:src="item2[data.imageKey]"
mode="widthFix"
@load="imgLoad(item2, index + 1)"
@error="imgError(item2, index + 1)"
@click.stop="imageClick(item2)"
></image>
<view class="inner" v-if="data.seat == 2">
<!-- #ifdef MP-WEIXIN -->
<!-- #ifdef VUE2 -->
<slot name="slot{{item2.index}}"></slot>
<!-- #endif -->
<!-- #ifdef VUE3 -->
<slot :name="`slot${item2.index}`"></slot>
<!-- #endif -->
<!-- #endif -->
<!-- #ifndef MP-WEIXIN -->
<slot v-bind="item2"></slot>
<!-- #endif -->
</view>
</view>
</view>
</view>
<view class="waterfalls-flow">
<view
v-for="(item, index) in data.column"
:key="index"
class="waterfalls-flow-column"
:id="`waterfalls_flow_column_${index + 1}`"
:msg="msg"
:style="{ width: w, 'margin-left': index == 0 ? 0 : m }"
>
<view
:class="['column-value', { 'column-value-show': item2.o }]"
v-for="(item2, index2) in columnValue(index)"
:key="index2"
:style="[s1]"
@click.stop="wapperClick(item2)"
>
<view class="inner" v-if="data.seat == 1">
<!-- #ifdef MP-WEIXIN -->
<!-- #ifdef VUE2 -->
<slot name="slot{{item2.index}}"></slot>
<!-- #endif -->
<!-- #ifdef VUE3 -->
<slot :name="`slot${item2.index}`"></slot>
<!-- #endif -->
<!-- #endif -->
<!-- #ifndef MP-WEIXIN -->
<slot v-bind="item2"></slot>
<!-- #endif -->
</view>
<image
:class="[
'img',
{
'img-hide': item2[hideImageKey] == true || item2[hideImageKey] == 1,
},
{ 'img-error': !item2[data.imageKey] },
]"
:src="item2[data.imageKey]"
mode="widthFix"
@load="imgLoad(item2, index + 1)"
@error="imgError(item2, index + 1)"
@click.stop="imageClick(item2)"
></image>
<view class="inner" v-if="data.seat == 2">
<!-- #ifdef MP-WEIXIN -->
<!-- #ifdef VUE2 -->
<slot name="slot{{item2.index}}"></slot>
<!-- #endif -->
<!-- #ifdef VUE3 -->
<slot :name="`slot${item2.index}`"></slot>
<!-- #endif -->
<!-- #endif -->
<!-- #ifndef MP-WEIXIN -->
<slot v-bind="item2"></slot>
<!-- #endif -->
</view>
</view>
</view>
</view>
</template>
<script>
export default {
props: {
modelValue: Array,
column: {
// 列的数量
type: [String, Number],
default: 2,
},
maxColumn: {
// 最大列数
type: [String, Number],
default: 5,
},
columnSpace: {
// 列之间的间距 百分比
type: [String, Number],
default: 2,
},
imageKey: {
// 图片key
type: [String],
default: "image",
},
hideImageKey: {
// 隐藏图片key
type: [String],
default: "hide",
},
seat: {
// 文本的位置,1图片之上 2图片之下
type: [String, Number],
default: 2,
},
listStyle: {
// 单个展示项的样式:eg:{'background':'red'}
type: Object,
},
},
data() {
return {
data: {
list: this.modelValue ? this.modelValue : [],
column: this.column < 2 ? 2 : this.column,
columnSpace: this.columnSpace <= 5 ? this.columnSpace : 5,
imageKey: this.imageKey,
seat: this.seat,
},
msg: 0,
listInitStyle: {
"border-radius": "12rpx",
"margin-bottom": "20rpx",
"background-color": "#fff",
},
adds: [], //预置数据
isLoaded: true,
curIndex: 0,
isRefresh: true,
flag: false,
refreshDatas: [],
};
},
computed: {
// 计算列宽
w() {
const column_rate = `${100 / this.data.column - +this.data.columnSpace}%`;
return column_rate;
},
// 计算margin
m() {
const column_margin = `${
(100 -
(100 / this.data.column - +this.data.columnSpace).toFixed(5) *
this.data.column) /
(this.data.column - 1)
}%`;
return column_margin;
},
// list样式
s1() {
return { ...this.listInitStyle, ...this.listStyle };
},
},
created() {
// 初始化
this.refresh();
},
methods: {
// 预加载图片
loadImages(idx = 0) {
let count = 0;
const newList = this.data.list.filter((item, index) => index >= idx);
for (let i = 0; i < newList.length; i++) {
// #ifndef APP-PLUS
uni.getImageInfo({
src: `${newList[i][this.imageKey]}.jpg`,
complete: (res) => {
count++;
if (count == newList.length) this.initValue(idx);
},
});
// #endif
// #ifdef APP-PLUS
plus.io.getImageInfo({
src: `${newList[i][this.imageKey]}.jpg`,
complete: (res) => {
count++;
if (count == newList.length) this.initValue(idx);
},
});
// #endif
}
},
// 刷新
refresh() {
if (!this.isLoaded) {
this.refreshDatas = this.modelValue;
return false;
}
setTimeout(() => {
this.refreshDatas = [];
this.isRefresh = true;
this.adds = [];
this.data.list = this.modelValue ? this.modelValue : [];
this.data.column =
this.column < 2
? 2
: this.column >= this.maxColumn
? this.maxColumn
: this.column;
this.data.columnSpace = this.columnSpace <= 5 ? this.columnSpace : 5;
this.data.imageKey = this.imageKey;
this.data.seat = this.seat;
this.curIndex = 0;
// 每列的数据初始化
for (let i = 1; i <= this.data.column; i++) {
this.data[`column_${i}_values`] = [];
this.msg++;
}
this.$nextTick(() => {
this.initValue(this.curIndex, "refresh==>");
});
}, 1);
},
columnValue(index) {
return this.data[`column_${index + 1}_values`];
},
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) {
this.data[`column_${this.data.list[i].column}_values`][j] =
Object.assign(cv[j], newValue[i]);
this.msg++;
break;
}
}
}
},
getMin(a, s) {
let m = a[0][s];
let mo = a[0];
for (var i = a.length - 1; i >= 0; i--) {
if (a[i][s] < m) {
m = a[i][s];
}
}
mo = a.filter((i) => i[s] == m);
return mo[0];
},
// 计算每列的高度
getMinColumnHeight() {
return new Promise((resolve) => {
const heightArr = [];
for (let i = 1; i <= this.data.column; i++) {
const query = uni.createSelectorQuery().in(this);
query
.select(`#waterfalls_flow_column_${i}`)
.boundingClientRect((data) => {
heightArr.push({ column: i, height: data.height });
})
.exec(() => {
if (this.data.column <= heightArr.length) {
resolve(this.getMin(heightArr, "height"));
}
});
}
});
},
async initValue(i, from) {
this.isLoaded = false;
if (i >= this.data.list.length || this.refreshDatas.length) {
this.msg++;
this.loaded();
return false;
}
const minHeightRes = await this.getMinColumnHeight();
const c = this.data[`column_${minHeightRes.column}_values`];
this.data.list[i].column = minHeightRes.column;
c.push({ ...this.data.list[i], cIndex: c.length, index: i, o: 0 });
this.msg++;
},
// 图片加载完成
imgLoad(item, c) {
const i = item.index;
item.o = 1;
this.$set(
this.data[`column_${c}_values`],
item.cIndex,
JSON.parse(JSON.stringify(item))
);
this.initValue(i + 1);
},
// 图片加载失败
imgError(item, c) {
const i = item.index;
item.o = 1;
item[this.data.imageKey] = null;
this.$set(
this.data[`column_${c}_values`],
item.cIndex,
JSON.parse(JSON.stringify(item))
);
this.initValue(i + 1);
},
// 渲染结束
loaded() {
if (this.refreshDatas.length) {
this.isLoaded = true;
this.refresh();
return false;
}
this.curIndex = this.data.list.length;
if (this.adds.length) {
this.data.list = this.adds[0];
this.adds.splice(0, 1);
this.initValue(this.curIndex);
} else {
if (this.data.list.length) this.$emit("loaded");
this.isLoaded = true;
this.isRefresh = false;
}
},
// 单项点击事件
wapperClick(item) {
this.$emit("wapperClick", item);
},
// 图片点击事件
imageClick(item) {
this.$emit("imageClick", item);
},
},
watch: {
modelValue: {
deep: true,
handler(newValue, oldValue) {
setTimeout(() => {
this.$nextTick(() => {
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();
},
},
};
props: {
modelValue: Array,
column: {
// 列的数量
type: [String, Number],
default: 2,
},
maxColumn: {
// 最大列数
type: [String, Number],
default: 5,
},
columnSpace: {
// 列之间的间距 百分比
type: [String, Number],
default: 2,
},
imageKey: {
// 图片key
type: [String],
default: "image",
},
hideImageKey: {
// 隐藏图片key
type: [String],
default: "hide",
},
seat: {
// 文本的位置,1图片之上 2图片之下
type: [String, Number],
default: 2,
},
listStyle: {
// 单个展示项的样式:eg:{'background':'red'}
type: Object,
},
},
data() {
return {
data: {
list: this.modelValue ? this.modelValue : [],
column: this.column < 2 ? 2 : this.column,
columnSpace: this.columnSpace <= 5 ? this.columnSpace : 5,
imageKey: this.imageKey,
seat: this.seat,
},
msg: 0,
listInitStyle: {
"border-radius": "12rpx",
"margin-bottom": "20rpx",
"background-color": "#fff",
},
adds: [], //预置数据
isLoaded: true,
curIndex: 0,
isRefresh: true,
flag: false,
refreshDatas: [],
}
},
computed: {
// 计算列宽
w() {
const column_rate = `${100 / this.data.column - +this.data.columnSpace}%`
return column_rate
},
// 计算margin
m() {
const column_margin = `${
(100 - (100 / this.data.column - +this.data.columnSpace).toFixed(5) * this.data.column) / (this.data.column - 1)
}%`
return column_margin
},
// list样式
s1() {
return { ...this.listInitStyle, ...this.listStyle }
},
},
created() {
// 初始化
this.refresh()
},
methods: {
// 预加载图片
loadImages(idx = 0) {
let count = 0
const newList = this.data.list.filter((item, index) => index >= idx)
for (let i = 0; i < newList.length; i++) {
// #ifndef APP-PLUS
uni.getImageInfo({
src: `${newList[i][this.imageKey]}.jpg`,
complete: (res) => {
count++
if (count == newList.length) this.initValue(idx)
},
})
// #endif
// #ifdef APP-PLUS
plus.io.getImageInfo({
src: `${newList[i][this.imageKey]}.jpg`,
complete: (res) => {
count++
if (count == newList.length) this.initValue(idx)
},
})
// #endif
}
},
// 刷新
refresh() {
if (!this.isLoaded) {
this.refreshDatas = this.modelValue
return false
}
setTimeout(() => {
this.refreshDatas = []
this.isRefresh = true
this.adds = []
this.data.list = this.modelValue ? this.modelValue : []
this.data.column = this.column < 2 ? 2 : this.column >= this.maxColumn ? this.maxColumn : this.column
this.data.columnSpace = this.columnSpace <= 5 ? this.columnSpace : 5
this.data.imageKey = this.imageKey
this.data.seat = this.seat
this.curIndex = 0
// 每列的数据初始化
for (let i = 1; i <= this.data.column; i++) {
this.data[`column_${i}_values`] = []
this.msg++
}
this.$nextTick(() => {
this.initValue(this.curIndex, "refresh==>")
})
}, 1)
},
columnValue(index) {
return this.data[`column_${index + 1}_values`]
},
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) {
this.data[`column_${this.data.list[i].column}_values`][j] = Object.assign(cv[j], newValue[i])
this.msg++
break
}
}
}
},
getMin(a, s) {
let m = a[0][s]
let mo = a[0]
for (var i = a.length - 1; i >= 0; i--) {
if (a[i][s] < m) {
m = a[i][s]
}
}
mo = a.filter((i) => i[s] == m)
return mo[0]
},
// 计算每列的高度
getMinColumnHeight() {
return new Promise((resolve) => {
const heightArr = []
for (let i = 1; i <= this.data.column; i++) {
const query = uni.createSelectorQuery().in(this)
query
.select(`#waterfalls_flow_column_${i}`)
.boundingClientRect((data) => {
heightArr.push({ column: i, height: data.height })
})
.exec(() => {
if (this.data.column <= heightArr.length) {
resolve(this.getMin(heightArr, "height"))
}
})
}
})
},
async initValue(i, from) {
this.isLoaded = false
if (i >= this.data.list.length || this.refreshDatas.length) {
this.msg++
this.loaded()
return false
}
const minHeightRes = await this.getMinColumnHeight()
const c = this.data[`column_${minHeightRes.column}_values`]
this.data.list[i].column = minHeightRes.column
c.push({ ...this.data.list[i], cIndex: c.length, index: i, o: 0 })
this.msg++
},
// 图片加载完成
imgLoad(item, c) {
const i = item.index
item.o = 1
this.$set(this.data[`column_${c}_values`], item.cIndex, JSON.parse(JSON.stringify(item)))
this.initValue(i + 1)
},
// 图片加载失败
imgError(item, c) {
const i = item.index
item.o = 1
item[this.data.imageKey] = null
this.$set(this.data[`column_${c}_values`], item.cIndex, JSON.parse(JSON.stringify(item)))
this.initValue(i + 1)
},
// 渲染结束
loaded() {
if (this.refreshDatas.length) {
this.isLoaded = true
this.refresh()
return false
}
this.curIndex = this.data.list.length
if (this.adds.length) {
this.data.list = this.adds[0]
this.adds.splice(0, 1)
this.initValue(this.curIndex)
} else {
if (this.data.list.length) this.$emit("loaded")
this.isLoaded = true
this.isRefresh = false
}
},
// 单项点击事件
wapperClick(item) {
this.$emit("wapperClick", item)
},
// 图片点击事件
imageClick(item) {
this.$emit("imageClick", item)
},
},
watch: {
modelValue: {
deep: true,
handler(newValue, oldValue) {
setTimeout(() => {
this.$nextTick(() => {
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>
<style lang="scss" scoped>
.waterfalls-flow {
overflow: hidden;
overflow: hidden;
&-column {
float: left;
}
&-column {
float: left;
}
}
.column-value {
width: 100%;
font-size: 0;
overflow: hidden;
transition: opacity 0.4s;
opacity: 0;
width: 100%;
font-size: 0;
overflow: hidden;
transition: opacity 0.4s;
opacity: 0;
&-show {
opacity: 1;
}
&-show {
opacity: 1;
}
.inner {
font-size: 30rpx;
}
.inner {
font-size: 30rpx;
}
.img {
width: 100%;
.img {
width: 100%;
&-hide {
display: none;
}
&-hide {
display: none;
}
&-error {
background: #f2f2f2
url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAC4AAAAiAQMAAAAatXkPAAAABlBMVEUAAADMzMzIT8AyAAAAAXRSTlMAQObYZgAAAIZJREFUCNdlzjEKwkAUBNAfEGyCuYBkLyLuxRYW2SKlV1JSeA2tUiZg4YrLjv9PGsHqNTPMSAQuyAJgRDHSyvBPwtZoSJXakeJI9iuRLGDygdl6V0yKDtyMAeMPZySj8yfD+UapvRPj2JOwkyAooSV5IwdDjPdCPspe8LyTl9IKJvDETKKRv6vnlUasgg0fAAAAAElFTkSuQmCC)
no-repeat center center;
}
}
&-error {
background: #f2f2f2
url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAC4AAAAiAQMAAAAatXkPAAAABlBMVEUAAADMzMzIT8AyAAAAAXRSTlMAQObYZgAAAIZJREFUCNdlzjEKwkAUBNAfEGyCuYBkLyLuxRYW2SKlV1JSeA2tUiZg4YrLjv9PGsHqNTPMSAQuyAJgRDHSyvBPwtZoSJXakeJI9iuRLGDygdl6V0yKDtyMAeMPZySj8yfD+UapvRPj2JOwkyAooSV5IwdDjPdCPspe8LyTl9IKJvDETKKRv6vnlUasgg0fAAAAAElFTkSuQmCC)
no-repeat center center;
}
}
}
</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 () => process.env.NODE_ENV === "development"
// export default () => import.meta.env.VITE_DEV_ENV === "dev"
export default () => process.env.NODE_ENV === "development"
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB