This commit is contained in:
weiwei committed 2025-03-11 09:04:56 +08:00
1 parent 3ee3cabcdb
commit 67f888a27e
5 files changed
+238 -258

No files matched your search

+2 -2
View File
@@ -27,12 +27,12 @@ VITE_OAUTH2_APP_CLIENT='mini:mini'
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 = 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.60: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://220.191.229.171:8090/api # 线上
# VITE_APP_DEV_SERVICE = http://localhost:9999
# ******************** end 开发环境 end ********************
+163 -163
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, onShow } from "@dcloudio/uni-app"
import { isEmpty, max, min } from "radash"
import dayjs from "dayjs"
import { hooks, 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>
+1 -1
View File
@@ -327,7 +327,7 @@ const doFood = () => {
</view>
</view>
</scroll-view>
<view v-else class="mx-auto mt-10 second-text-28">暂无商品</view>
<view v-else class="mx-auto mt-10 second-text-28">暂无信息</view>
</view>
</tm-sticky>
<!-- end 商品 end -->
+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>
+16 -22
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,10 +44,10 @@ 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" />
<view class="flex-1 flex-col m-l-20rpx">
@@ -65,12 +61,10 @@ const toDetail = async (v: any) => {
</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>营业时间:</view>
<view class="second-text-24">{{ v.jobTime?.split(",")[0] ? "早:" + v.jobTime?.split(",")[0] : "" }}</view>
<view class="second-text-24">{{ v.jobTime?.split(",")[1] ? "中:" + v.jobTime?.split(",")[1] : "" }}</view>
<view class="second-text-24">{{ v.jobTime?.split(",")[2] ? "晚:" + v.jobTime?.split(",")[2] : "" }}</view>
</view>
<view v-if="v.addressDes" class="m-t-10rpx second-text-28">
<text>地址</text>