Merge branch 'master' of https://codeup.aliyun.com/bsdtec/biz-mobile-react-cloud
This commit is contained in:
commit
58ba7bd0c7
41 files changed
+5594
-6657
No files matched your search
@@ -22,11 +22,10 @@ VITE_IMAGE_BASE_PATH = http://localhost:9999
|
||||
# ******************** start 开发环境 start ********************
|
||||
# VITE_APP_DEV_SERVICE =http://123.156.228.134:48080/app-api
|
||||
# VITE_APP_DEV_SERVICE = https://stgl.pj.gov.cn/app-api
|
||||
# VITE_APP_DEV_SERVICE = http://192.168.101.24:48080/app-api
|
||||
VITE_APP_DEV_SERVICE = http://localhost:9999
|
||||
VITE_APP_DEV_SERVICE = http://192.168.101.29:9999 # 邓-本地
|
||||
# VITE_APP_DEV_SERVICE = http://localhost:9999
|
||||
# ******************** end 开发环境 end ********************
|
||||
|
||||
|
||||
# ******************** start 生产环境 start ********************
|
||||
#VITE_APP_PROD_SERVICE = http://123.156.228.134:48080/app-api
|
||||
VITE_APP_PROD_SERVICE = https://stgl.pj.gov.cn/app-api
|
||||
|
||||
Generated
+3844
-4944
File diff suppressed because it is too large.
Load diff
+5
-5
@@ -239,7 +239,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"root": "pages/humanFace",
|
||||
"root": "pages/human-face",
|
||||
"pages": [
|
||||
{
|
||||
"path": "list",
|
||||
@@ -275,9 +275,9 @@
|
||||
},
|
||||
{
|
||||
"pagePath": "pages/tabbar/shop",
|
||||
"text": "商店",
|
||||
"iconPath": "static/tabbar/home.png",
|
||||
"selectedIconPath": "static/tabbar/home-select.png"
|
||||
"text": "超市",
|
||||
"iconPath": "static/tabbar/shop.png",
|
||||
"selectedIconPath": "static/tabbar/shop-select.png"
|
||||
},
|
||||
{
|
||||
"pagePath": "pages/tabbar/order",
|
||||
@@ -293,4 +293,4 @@
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -47,7 +47,6 @@ const getDetail = async () => {
|
||||
const { data } = await applyApi.foreignDetail(_pa)
|
||||
if (!isEmpty(data)) {
|
||||
state.detail = data
|
||||
|
||||
const startTime = hooks.useTime(data.applyStartTime, "{y}-{m}-{d}")
|
||||
const endTime = hooks.useTime(data.applyEndTime, "{y}-{m}-{d}")
|
||||
applyForm.displayTimeRangeStr = startTime + "~" + endTime
|
||||
@@ -66,11 +65,12 @@ const doSubmit = async () => {
|
||||
const { isPass } = applyFormRef.value.validate()
|
||||
if (!isPass) return
|
||||
const range = applyForm.displayTimeRange
|
||||
console.log(range);
|
||||
try {
|
||||
uni.showLoading({ title: '申请中...', mask: false });
|
||||
const _pa = {
|
||||
applyStartTime: dayjs(range[0]).valueOf(),
|
||||
applyEndTime: dayjs(range[1]).valueOf(),
|
||||
applyStartTime: hooks.useTime(range[0], "{y}-{m}-{d}"),
|
||||
applyEndTime: hooks.useTime(range[1], "{y}-{m}-{d}"),
|
||||
count: applyForm.count,
|
||||
remark: applyForm.remark,
|
||||
}
|
||||
|
||||
@@ -6,16 +6,17 @@ import { isEmpty } from 'radash'
|
||||
import { hooks, router } from "@@/index"
|
||||
import { applyApi } from "@@/api"
|
||||
|
||||
import { filePath } from "@@/utils/file"
|
||||
|
||||
const state = reactive<any>({
|
||||
pa: {
|
||||
id: null,
|
||||
pagesize: 99,
|
||||
pagesize: 15,
|
||||
},
|
||||
})
|
||||
|
||||
const pageRef = ref<any>(null)
|
||||
const pageHook = hooks.usePage(pageRef, applyApi.foreignItems, null, 'data')
|
||||
const pageHook = hooks.usePage(pageRef, applyApi.codeList, null, 'data.records')
|
||||
const query = (page: number, pagesize: number) => {
|
||||
pageHook.startPage(page, pagesize, false, state.pa);
|
||||
}
|
||||
@@ -46,12 +47,12 @@ onShow(() => {
|
||||
v-for="(v, i) in pageHook.list" :key="i" @tap="hooks.usePreviewImage(v.code)">
|
||||
<view class="flex-row items-center">
|
||||
<view class="flex-row items-center">
|
||||
<tm-tag v-if="v.status == 1" size="m" color="info">未使用</tm-tag>
|
||||
<tm-tag v-if="v.status == 2" size="m" color="success">已使用</tm-tag>
|
||||
<tm-tag v-if="v.status == 0" size="m" color="info">未使用</tm-tag>
|
||||
<tm-tag v-if="v.status == 1" size="m" color="success">已使用</tm-tag>
|
||||
</view>
|
||||
<view class="flex-row items-center sub-text-28">
|
||||
<text class="m-l-30rpx">{{ v.userNameStr }}</text>
|
||||
<text class="m-l-30rpx">{{ v.userMobile }}</text>
|
||||
<text class="m-l-30rpx">{{ v.username }}</text>
|
||||
<text class="m-l-10rpx second-text-26">{{ v.userMobile }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="iconfont icon-erweima font-size-40rpx! color-blue" />
|
||||
|
||||
@@ -17,12 +17,12 @@ const data = {
|
||||
}
|
||||
const state = reactive<any>({
|
||||
pa: {
|
||||
status: data.tabs[0].id,
|
||||
processStatus: data.tabs[0].id,
|
||||
},
|
||||
})
|
||||
|
||||
const pageRef = ref<any>(null)
|
||||
const pageHook = hooks.usePage(pageRef, applyApi.foreignList, null, 'data.list')
|
||||
const pageHook = hooks.usePage(pageRef, applyApi.foreignList, null, 'data.records')
|
||||
const query = (page: number, pagesize: number) => {
|
||||
pageHook.startPage(page, pagesize, false, state.pa);
|
||||
}
|
||||
@@ -38,7 +38,7 @@ onShow(() => {
|
||||
|
||||
const doTab = (e: any) => {
|
||||
const target = data.tabs[e];
|
||||
state.pa.status = target.id
|
||||
state.pa.processStatus = target.id
|
||||
pageRef.value.reload(true)
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ const doApply = async () => {
|
||||
}
|
||||
|
||||
const doCard = (v: any) => {
|
||||
if (v.status == 2) {
|
||||
if (v.processStatus == 2) {
|
||||
router.jump("/pages/apply/foreign-items", { id: v.id })
|
||||
} else {
|
||||
router.jump("/pages/apply/foreign-apply", { type: 'view', id: v.id })
|
||||
@@ -76,9 +76,9 @@ const doCard = (v: any) => {
|
||||
<view class="flex-row items-center">
|
||||
<view class="second-text-26">{{ hooks.useTime(v.createTime, "") }}</view>
|
||||
<view class="flex-row-center m-l-20rpx">
|
||||
<tm-tag v-if="v.status == 1" size="xs" color="info">待审核</tm-tag>
|
||||
<tm-tag v-if="v.status == 2" size="xs" color="success">已通过</tm-tag>
|
||||
<tm-tag v-if="v.status == 3" size="xs" color="error">已拒绝</tm-tag>
|
||||
<tm-tag v-if="v.processStatus == 1" size="xs" color="info">待审核</tm-tag>
|
||||
<tm-tag v-if="v.processStatus == 2" size="xs" color="success">已通过</tm-tag>
|
||||
<tm-tag v-if="v.processStatus == 3" size="xs" color="error">已拒绝</tm-tag>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -88,7 +88,13 @@ const doCard = (v: any) => {
|
||||
<text>数量</text>
|
||||
<text class="m-l-10rpx">{{ v.count }}</text>
|
||||
</view>
|
||||
<view class="flex items-center">
|
||||
<view class="color-red">
|
||||
<text>已使用</text>
|
||||
<text class="m-l-10rpx">{{ v.useCount }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="flex items-center m-t-20rpx second-text-26">
|
||||
<view class="h-1px m-y-20rpx bg-#999 bg-opacity-5" />
|
||||
<text>有效期</text>
|
||||
<text class="m-l-10rpx">
|
||||
{{ hooks.useTime(v.applyStartTime, " {y}-{m}-{d}") }}
|
||||
@@ -96,8 +102,7 @@ const doCard = (v: any) => {
|
||||
{{ hooks.useTime(v.applyEndTime, "{y}-{m}-{d}") }}
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="v.status != 1">
|
||||
<view v-if="v.processStatus != 1 && false">
|
||||
<view class="h-1px m-y-20rpx bg-#999 bg-opacity-5" />
|
||||
<view class="flex items-center justify-between second-text-26">
|
||||
<view class="flex items-center">
|
||||
@@ -111,7 +116,7 @@ const doCard = (v: any) => {
|
||||
</view>
|
||||
</view>
|
||||
<view class="flex items-center justify-end m-t-25rpx">
|
||||
<text v-if="v.status == 2" class="botder_btn">使用</text>
|
||||
<text v-if="v.processStatus == 2" class="botder_btn">使用</text>
|
||||
<text v-else class="botder_btn">查看</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@@ -8,20 +8,20 @@ import { applyApi } from "@@/api"
|
||||
|
||||
const state = reactive<any>({
|
||||
pa: {
|
||||
id: null,
|
||||
bizId: null,
|
||||
pagesize: 99,
|
||||
},
|
||||
})
|
||||
|
||||
const pageRef = ref<any>(null)
|
||||
const pageHook = hooks.usePage(pageRef, applyApi.strideItems, null, 'data')
|
||||
const pageHook = hooks.usePage(pageRef, applyApi.codeList, null, 'data.records')
|
||||
const query = (page: number, pagesize: number) => {
|
||||
pageHook.startPage(page, pagesize, false, state.pa);
|
||||
}
|
||||
|
||||
onLoad((options: any) => {
|
||||
if (!isEmpty(options.id)) {
|
||||
state.pa.id = options.id
|
||||
state.pa.bizId = options.id
|
||||
}
|
||||
});
|
||||
onShow(() => {
|
||||
@@ -43,12 +43,12 @@ onShow(() => {
|
||||
v-for="(v, i) in pageHook.list" :key="i" @tap="hooks.usePreviewImage(v.code)">
|
||||
<view class="flex-row items-center">
|
||||
<view class="flex-row items-center">
|
||||
<tm-tag v-if="v.status == 1" size="m" color="info">未使用</tm-tag>
|
||||
<tm-tag v-if="v.status == 2" size="m" color="success">已使用</tm-tag>
|
||||
<tm-tag v-if="v.status == 0" size="m" color="info">未使用</tm-tag>
|
||||
<tm-tag v-if="v.status == 1" size="m" color="success">已使用</tm-tag>
|
||||
</view>
|
||||
<view class="flex-row items-center sub-text-26">
|
||||
<text class="m-l-30rpx">{{ v.username }}</text>
|
||||
<text class="m-l-30rpx">{{ v.userMobile }}</text>
|
||||
<text class="m-l-10rpx second-text-26">{{ v.userMobile }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="iconfont icon-erweima font-size-40rpx! color-blue" />
|
||||
|
||||
@@ -17,12 +17,12 @@ const data = {
|
||||
}
|
||||
const state = reactive<any>({
|
||||
pa: {
|
||||
status: data.tabs[0].id,
|
||||
processStatus: data.tabs[0].id,
|
||||
},
|
||||
})
|
||||
|
||||
const pageRef = ref<any>(null)
|
||||
const pageHook = hooks.usePage(pageRef, applyApi.strideList, null, 'data.list')
|
||||
const pageHook = hooks.usePage(pageRef, applyApi.strideList, null, 'data.records')
|
||||
const query = (page: number, pagesize: number) => {
|
||||
pageHook.startPage(page, pagesize, false, state.pa);
|
||||
}
|
||||
@@ -38,7 +38,7 @@ onShow(() => {
|
||||
|
||||
const doTab = (e: any) => {
|
||||
const target = data.tabs[e];
|
||||
state.pa.status = target.id
|
||||
state.pa.processStatus = target.id
|
||||
pageRef.value.reload(true)
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ const doApply = async () => {
|
||||
}
|
||||
|
||||
const doCard = (v: any) => {
|
||||
if (v.status == 2) {
|
||||
if (v.processStatus == 2) {
|
||||
router.jump("/pages/apply/stride-items", { id: v.id })
|
||||
} else {
|
||||
router.jump("/pages/apply/stride-apply", { type: 'view', id: v.id })
|
||||
@@ -76,9 +76,9 @@ const doCard = (v: any) => {
|
||||
<view class="flex-row items-center">
|
||||
<view class="second-text-26">{{ hooks.useTime(v.createTime, "") }}</view>
|
||||
<view class="flex-row-center m-l-20rpx">
|
||||
<tm-tag v-if="v.status == 1" size="xs" color="info">待审核</tm-tag>
|
||||
<tm-tag v-if="v.status == 2" size="xs" color="success">已通过</tm-tag>
|
||||
<tm-tag v-if="v.status == 3" size="xs" color="error">已拒绝</tm-tag>
|
||||
<tm-tag v-if="v.processStatus == 1" size="xs" color="info">待审核</tm-tag>
|
||||
<tm-tag v-if="v.processStatus == 2" size="xs" color="success">已通过</tm-tag>
|
||||
<tm-tag v-if="v.processStatus == 3" size="xs" color="error">已拒绝</tm-tag>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -88,8 +88,12 @@ const doCard = (v: any) => {
|
||||
<text>数量</text>
|
||||
<text class="m-l-10rpx">{{ v.count }}</text>
|
||||
</view>
|
||||
<view class="color-red">
|
||||
<text>已使用</text>
|
||||
<text class="m-l-10rpx">{{ v.useCount }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="v.status != 1">
|
||||
<view v-if="v.processStatus != 1 && false">
|
||||
<view class="h-1px m-y-20rpx bg-#999 bg-opacity-5" />
|
||||
<view class="flex items-center justify-between second-text-26">
|
||||
<view class="flex items-center">
|
||||
@@ -103,7 +107,7 @@ const doCard = (v: any) => {
|
||||
</view>
|
||||
</view>
|
||||
<view class="flex items-center justify-end m-t-25rpx">
|
||||
<text v-if="v.status == 2" class="botder_btn">使用</text>
|
||||
<text v-if="v.processStatus == 2" class="botder_btn">使用</text>
|
||||
<text v-else class="botder_btn">查看</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@@ -26,7 +26,7 @@ const state = reactive<any>({
|
||||
})
|
||||
|
||||
const pageRef = ref<any>(null)
|
||||
const pageHook = hooks.usePage(pageRef, boxesApi.page, null, 'data.list')
|
||||
const pageHook = hooks.usePage(pageRef, boxesApi.page, null, 'data.records')
|
||||
const query = (page: number, pagesize: number) => {
|
||||
pageHook.startPage(page, pagesize, false, state.pa);
|
||||
}
|
||||
|
||||
@@ -3,14 +3,16 @@ import { ref, reactive, nextTick } from "vue";
|
||||
import { onLoad, onShow } from "@dcloudio/uni-app";
|
||||
import { isEmpty } from "radash";
|
||||
|
||||
import { hooks, router } from "@@/index";
|
||||
import { hooks, router, constant } from "@@/index";
|
||||
import { faceApi } from "@@/api";
|
||||
const uploadPhotoBaseUrl = import.meta.env.VITE_APP_DEV_SERVICE;
|
||||
|
||||
import { filePath } from "@@/utils/file"
|
||||
|
||||
const state = reactive<any>({
|
||||
detailType: "add",
|
||||
detailId: null,
|
||||
detail: null,
|
||||
header: {}
|
||||
});
|
||||
const applyForm = reactive<any>({
|
||||
faceImg: [],
|
||||
@@ -23,26 +25,28 @@ onLoad(async (options: any) => {
|
||||
const { type, id } = options;
|
||||
if (!isEmpty(type)) state.detailType = type;
|
||||
if (!isEmpty(id)) state.detailId = id;
|
||||
state.header = hooks.useDefaultHeader()
|
||||
if (type === "edit") {
|
||||
applyForm.faceImg = [];
|
||||
uploadFileUrl.value = "";
|
||||
await getDetail();
|
||||
}
|
||||
});
|
||||
onShow(() => {});
|
||||
onShow(() => { });
|
||||
|
||||
const getDetail = async () => {
|
||||
if (isEmpty(state.detailId)) return;
|
||||
const { data } = await faceApi.get({ id: state.detailId });
|
||||
if (!isEmpty(data)) {
|
||||
applyForm.faceImg = [data.faceImg];
|
||||
uploadFileUrl.value = data.faceImg;
|
||||
const img = filePath(data.faceImg)
|
||||
applyForm.faceImg = [img]
|
||||
uploadFileUrl.value = img
|
||||
}
|
||||
};
|
||||
|
||||
const beforeComplete = (uploadFile: any) => {
|
||||
if (JSON.parse(uploadFile.data).code == 0) {
|
||||
uploadFileUrl.value = JSON.parse(uploadFile.data).data;
|
||||
uploadFileUrl.value = JSON.parse(uploadFile.data).data.url;
|
||||
return true;
|
||||
} else {
|
||||
uploadFileUrl.value = "";
|
||||
@@ -55,7 +59,6 @@ const doSubmit = async () => {
|
||||
applyFormRef.value.submit();
|
||||
const { isPass } = applyFormRef.value.validate();
|
||||
if (!isPass || !uploadFileUrl.value) return;
|
||||
|
||||
try {
|
||||
uni.showLoading({ title: "提交中...", mask: false });
|
||||
const { data, code }: any =
|
||||
@@ -80,21 +83,14 @@ const doSubmit = async () => {
|
||||
<tm-form ref="applyFormRef" v-model="applyForm" :rules="applyFormRules" direction="vertical">
|
||||
<tm-form-item name="faceImg" label="人脸图片" :required="false" :showBottom="false">
|
||||
<view class="h-10rpx" />
|
||||
<tm-upload-photo
|
||||
:rangUrl="applyForm.faceImg[0]"
|
||||
:beforeComplete="beforeComplete"
|
||||
v-model="applyForm.faceImg"
|
||||
:maxCount="1"
|
||||
:url="uploadPhotoBaseUrl + '/infra/file/upload'"
|
||||
/>
|
||||
<tm-upload-photo :header="state.header" :rangUrl="applyForm.faceImg[0]" :beforeComplete="beforeComplete"
|
||||
v-model="applyForm.faceImg" :maxCount="1" :url="'/api/admin/sys-file/upload'" />
|
||||
</tm-form-item>
|
||||
</tm-form>
|
||||
</view>
|
||||
<view
|
||||
v-if="state.detailType != 'view'"
|
||||
<view v-if="state.detailType != 'view'"
|
||||
class="bg-#0094ff p-y-20rpx text-center rounded-40rpx m-x-30rpx m-t-60rpx sub-text-30 color-white!"
|
||||
@tap="doSubmit"
|
||||
>
|
||||
@tap="doSubmit">
|
||||
{{ state.detailId ? "修改" : "提交" }}
|
||||
</view>
|
||||
</crud-layout>
|
||||
@@ -1,39 +1,3 @@
|
||||
<template>
|
||||
<crud-layout title="人脸管理" bg="/static/page/blue-bg.png">
|
||||
<z-paging
|
||||
ref="pageRef"
|
||||
height="100%"
|
||||
:fixed="false"
|
||||
v-model="pageHook.list"
|
||||
:default-page-size="10"
|
||||
safe-area-inset-bottom
|
||||
:loading-more-enabled="true"
|
||||
:show-scrollbar="false"
|
||||
@query="query"
|
||||
:auto-clean-list-when-reload="false"
|
||||
:auto-scroll-to-top-when-reload="false"
|
||||
@scroll="pageHook.scroll"
|
||||
>
|
||||
<view class="h-20rpx" />
|
||||
<view class="flex-col card p-x-20rpx p-y-30rpx m-b-20rpx" v-for="(v, i) in pageHook.list" :key="v.id">
|
||||
<view class="flex items-center justify-between second-text-26">
|
||||
<img class="w-100rpx h-100rpx rounded-50rpx" :src="v.faceImg" />
|
||||
<text class="font-600">{{ v.username }}</text>
|
||||
<text class="botder_btn" @click="doEdit(v.id)">修改</text>
|
||||
<tm-modal title="确定删除吗?" height="auto" @confirm="doDel(v.id)">
|
||||
<template v-slot:trigger><text class="botder_btn">删除</text></template>
|
||||
</tm-modal>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<template #bottom>
|
||||
<view 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" />
|
||||
</template>
|
||||
</z-paging>
|
||||
</crud-layout>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive } from "vue";
|
||||
import { onLoad, onShow } from "@dcloudio/uni-app";
|
||||
@@ -41,6 +5,8 @@ import { onLoad, onShow } from "@dcloudio/uni-app";
|
||||
import { hooks, router } from "@@/index";
|
||||
import { faceApi } from "@@/api";
|
||||
|
||||
import { filePath } from "@@/utils/file"
|
||||
|
||||
const state = reactive<any>({
|
||||
pa: {
|
||||
pagesize: 10,
|
||||
@@ -48,12 +14,12 @@ const state = reactive<any>({
|
||||
});
|
||||
|
||||
const pageRef = ref<any>(null);
|
||||
const pageHook = hooks.usePage(pageRef, faceApi.page, null, "data.list");
|
||||
const pageHook = hooks.usePage(pageRef, faceApi.page, null, "data.records");
|
||||
const query = (page: number, pagesize: number) => {
|
||||
pageHook.startPage(page, pagesize, false, state.pa);
|
||||
};
|
||||
|
||||
onLoad(() => {});
|
||||
onLoad(() => { });
|
||||
onShow(() => {
|
||||
if (pageRef.value) {
|
||||
pageRef.value.reload(false);
|
||||
@@ -61,11 +27,11 @@ onShow(() => {
|
||||
});
|
||||
|
||||
const doAdd = () => {
|
||||
router.jump("/pages/humanFace/apply");
|
||||
router.jump("/pages/human-face/apply");
|
||||
};
|
||||
|
||||
const doEdit = (id: string) => {
|
||||
router.jump("/pages/humanFace/apply", { type: "edit", id });
|
||||
router.jump("/pages/human-face/apply", { type: "edit", id });
|
||||
};
|
||||
|
||||
const doDel = (id: string) => {
|
||||
@@ -80,3 +46,34 @@ const doDel = (id: string) => {
|
||||
);
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<crud-layout title="人脸管理" bg="/static/page/blue-bg.png">
|
||||
<z-paging ref="pageRef" height="100%" :fixed="false" v-model="pageHook.list" :default-page-size="10"
|
||||
safe-area-inset-bottom :loading-more-enabled="true" :show-scrollbar="false" @query="query"
|
||||
:auto-clean-list-when-reload="false" :auto-scroll-to-top-when-reload="false" @scroll="pageHook.scroll">
|
||||
<view class="h-20rpx" />
|
||||
<view class="flex-col card p-x-20rpx p-y-30rpx m-b-20rpx" v-for="(v, i) in pageHook.list" :key="v.id">
|
||||
<view class="flex items-center justify-between second-text-26">
|
||||
<div class="flex items-center">
|
||||
<image mode="aspectFill" class="w-100rpx h-100rpx rounded-50rpx" :src="filePath(v.faceImg)" />
|
||||
<view class="w-30rpx" />
|
||||
<text class="font-600">{{ v.username }}</text>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<text class="botder_btn" @click="doEdit(v.id)">修改</text>
|
||||
<view class="w-30rpx" />
|
||||
<tm-modal title="确定删除吗?" height="auto" @confirm="doDel(v.id)">
|
||||
<template v-slot:trigger><text class="botder_btn">删除</text></template>
|
||||
</tm-modal>
|
||||
</div>
|
||||
</view>
|
||||
</view>
|
||||
<template #bottom>
|
||||
<view 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" />
|
||||
</template>
|
||||
</z-paging>
|
||||
</crud-layout>
|
||||
</template>
|
||||
+392
-324
@@ -1,393 +1,461 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, nextTick } from "vue";
|
||||
import { onLoad, onShow } from "@dcloudio/uni-app";
|
||||
import { isEmpty } from "radash"
|
||||
import { isEmpty } from "radash";
|
||||
|
||||
import { hooks, router } from "@@/index"
|
||||
import { merchantApi, foodApi, payApi } from "@@/api"
|
||||
import { hooks, router } from "@@/index";
|
||||
import { merchantApi, foodApi, payApi } from "@@/api";
|
||||
|
||||
import { filePath } from "@@/utils/file"
|
||||
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 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 ProductRow from './components/product-row.vue'
|
||||
import ProductCar from './components/product-car.vue'
|
||||
import ProductTotal from './components/product-total.vue'
|
||||
import ProductRow from "./components/product-row.vue";
|
||||
import ProductCar from "./components/product-car.vue";
|
||||
import ProductTotal from "./components/product-total.vue";
|
||||
|
||||
const data = {
|
||||
|
||||
}
|
||||
const data = {};
|
||||
const state = reactive<any>({
|
||||
detailId: null,
|
||||
systemType: 3,
|
||||
totPrice: 0,
|
||||
totCount: 0,
|
||||
currentClassifyIndex: 0,
|
||||
showCarDialog: false,
|
||||
detailId: null,
|
||||
systemType: 3,
|
||||
totPrice: 0,
|
||||
totCount: 0,
|
||||
currentClassifyIndex: 0,
|
||||
showCarDialog: false,
|
||||
|
||||
detail: {},
|
||||
carList: [],
|
||||
classifyList: [],
|
||||
shopList: [],
|
||||
})
|
||||
detail: {},
|
||||
carList: [],
|
||||
classifyList: [],
|
||||
shopList: [],
|
||||
});
|
||||
|
||||
onLoad((options: any) => {
|
||||
if (!isEmpty(options.id)) {
|
||||
state.detailId = options.id
|
||||
}
|
||||
if (!isEmpty(options.id)) {
|
||||
state.detailId = options.id;
|
||||
}
|
||||
});
|
||||
onShow(() => {
|
||||
getDetail()
|
||||
getShopCar()
|
||||
getClassify()
|
||||
})
|
||||
getDetail();
|
||||
getShopCar();
|
||||
getClassify();
|
||||
});
|
||||
|
||||
const getDetail = async () => {
|
||||
const _pa = { id: state.detailId }
|
||||
const { data } = await merchantApi.detail(_pa)
|
||||
state.detail = data
|
||||
}
|
||||
const _pa = { id: state.detailId };
|
||||
const { data } = await merchantApi.detail(_pa);
|
||||
state.detail = data;
|
||||
};
|
||||
|
||||
const getShopCar = async () => {
|
||||
const _pa = { merchantId: state.detailId }
|
||||
const { data } = await foodApi.getShopCar(_pa)
|
||||
const _pa = { merchantId: state.detailId };
|
||||
const { data } = await foodApi.getShopCar(_pa);
|
||||
|
||||
state.carList = data ?? []
|
||||
state.totPrice = state.carList
|
||||
.map(v => v.totalPrice)
|
||||
.reduce((pre, next) => pre + next, 0);
|
||||
state.totCount = state.carList
|
||||
.map(v => v.productCount)
|
||||
.reduce((pre, next) => pre + next, 0);
|
||||
}
|
||||
state.carList = data ?? [];
|
||||
state.totPrice = state.carList
|
||||
.map((v) => v.totalPrice)
|
||||
.reduce((pre, next) => pre + next, 0);
|
||||
state.totCount = state.carList
|
||||
.map((v) => v.productCount)
|
||||
.reduce((pre, next) => pre + next, 0);
|
||||
};
|
||||
|
||||
const getClassify = async () => {
|
||||
const _pa = { systemType: state.systemType, merchantId: state.detailId }
|
||||
const { data } = await foodApi.classify(_pa)
|
||||
state.classifyList = data
|
||||
if (!isEmpty(state.classifyList)) {
|
||||
getPorduct()
|
||||
}
|
||||
}
|
||||
const _pa = { merchantId: state.detailId };
|
||||
const { data } = await foodApi.classify(_pa);
|
||||
state.classifyList = data;
|
||||
if (!isEmpty(state.classifyList)) {
|
||||
getPorduct();
|
||||
}
|
||||
};
|
||||
|
||||
const updateShopCar = async () => {
|
||||
if (isEmpty(state.carList)) return
|
||||
const list = state.carList
|
||||
.filter(v => v.productCount && v.productCount > 0)
|
||||
.map(v => {
|
||||
return {
|
||||
productCount: v.productCount,
|
||||
productId: v.productId
|
||||
}
|
||||
})
|
||||
if (isEmpty(list)) return
|
||||
const _pa = { merchantId: state.detailId, list: list }
|
||||
const { data, code }: any = await foodApi.updateShopCar(_pa)
|
||||
if (code == 0) await getShopCar()
|
||||
}
|
||||
if (isEmpty(state.carList)) return;
|
||||
const list = state.carList
|
||||
.filter((v) => v.productCount && v.productCount > 0)
|
||||
.map((v) => {
|
||||
return {
|
||||
productCount: v.productCount,
|
||||
productId: v.productId,
|
||||
};
|
||||
});
|
||||
if (isEmpty(list)) return;
|
||||
const _pa = { merchantId: state.detailId, list: list };
|
||||
const { data, code }: any = await foodApi.updateShopCar(_pa);
|
||||
if (code == 0) await getShopCar();
|
||||
};
|
||||
|
||||
const getPorduct = async () => {
|
||||
const target = state.classifyList[state.currentClassifyIndex]
|
||||
if (isEmpty(target)) return
|
||||
const _pa = {
|
||||
systemType: state.systemType,
|
||||
merchantId: state.detailId,
|
||||
categoryId: target.id,
|
||||
const target = state.classifyList[state.currentClassifyIndex];
|
||||
if (isEmpty(target)) return;
|
||||
const _pa = {
|
||||
systemType: state.systemType,
|
||||
merchantId: state.detailId,
|
||||
categoryId: target.id,
|
||||
};
|
||||
const { data } = await foodApi.product(_pa);
|
||||
state.shopList = data;
|
||||
state.shopList.forEach((i) => {
|
||||
if (i && i.foodSPURespVOList && i.foodSPURespVOList.length) {
|
||||
i.foodSPURespVOList.forEach((j) => {
|
||||
j.productCount = 0;
|
||||
j.productId = j.id;
|
||||
});
|
||||
}
|
||||
const { data } = await foodApi.product(_pa)
|
||||
state.shopList = data
|
||||
state.shopList.forEach(i => {
|
||||
if (i && i.foodSPURespVOList && i.foodSPURespVOList.length) {
|
||||
i.foodSPURespVOList.forEach(j => {
|
||||
j.productCount = 0
|
||||
j.productId = j.id
|
||||
})
|
||||
}
|
||||
})
|
||||
const shopList = [...state.shopList]
|
||||
if (state.carList && state.carList.length) {
|
||||
for (const i of shopList) {
|
||||
if (i && i.foodSPURespVOList && i.foodSPURespVOList.length) {
|
||||
for (const j of i.foodSPURespVOList) {
|
||||
for (const v of state.carList) {
|
||||
if (j.id == v.productId) {
|
||||
j.productCount = v.productCount
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
const shopList = [...state.shopList];
|
||||
if (state.carList && state.carList.length) {
|
||||
for (const i of shopList) {
|
||||
if (i && i.foodSPURespVOList && i.foodSPURespVOList.length) {
|
||||
for (const j of i.foodSPURespVOList) {
|
||||
for (const v of state.carList) {
|
||||
if (j.id == v.productId) {
|
||||
j.productCount = v.productCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
state.shopList = shopList;
|
||||
}
|
||||
}
|
||||
state.shopList = shopList;
|
||||
};
|
||||
|
||||
const doAdd = async (item: any) => {
|
||||
chentProductCount(item)
|
||||
}
|
||||
chentProductCount(item);
|
||||
};
|
||||
|
||||
const remove = async (item: any) => {
|
||||
chentProductCount(item)
|
||||
}
|
||||
chentProductCount(item);
|
||||
};
|
||||
|
||||
const chentProductCount = async (item: any) => {
|
||||
const target = state.carList.find(v => v.productId == item.productId)
|
||||
const targetIndex = state.carList.findIndex(v => v.productId == item.productId)
|
||||
if (target) {
|
||||
state.carList[targetIndex].productCount = item.productCount
|
||||
} else {
|
||||
state.carList.push({ ...item, productId: item.id })
|
||||
}
|
||||
nextTick(() => updateShopCar())
|
||||
}
|
||||
const target = state.carList.find((v) => v.productId == item.productId);
|
||||
const targetIndex = state.carList.findIndex(
|
||||
(v) => v.productId == item.productId
|
||||
);
|
||||
if (target) {
|
||||
state.carList[targetIndex].productCount = item.productCount;
|
||||
} else {
|
||||
state.carList.push({ ...item, productId: item.id });
|
||||
}
|
||||
nextTick(() => updateShopCar());
|
||||
};
|
||||
|
||||
const doClassify = (i: any) => {
|
||||
state.currentClassifyIndex = i
|
||||
getClassify()
|
||||
}
|
||||
state.currentClassifyIndex = i;
|
||||
getClassify();
|
||||
};
|
||||
|
||||
const doVisibleCar = async () => {
|
||||
state.showCarDialog = true
|
||||
}
|
||||
state.showCarDialog = true;
|
||||
};
|
||||
|
||||
const submitPay = async () => {
|
||||
try {
|
||||
if (isEmpty(state.carList)) {
|
||||
uni.showToast({ title: '请至少购买一件商品', icon: "none" })
|
||||
return
|
||||
}
|
||||
uni.showLoading({ title: '支付中...', mask: false });
|
||||
const _createtPa = { carParentId: state.carList[0].parentCarId }
|
||||
const { data: createData, code: createCode }: any = await payApi.createHardwareOrder(_createtPa)
|
||||
if (createCode != 0) throw new Error()
|
||||
const _submitPa = { orderId: createData }
|
||||
const { data: submitData, code: submitCode }: any = await payApi.submitHardwareOrder(_submitPa)
|
||||
if (submitCode != 0) throw new Error()
|
||||
uni.hideLoading()
|
||||
uni.showToast({ title: '支付成功', icon: "none" });
|
||||
router.jump("/pages/tabbar/order")
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
uni.hideLoading()
|
||||
try {
|
||||
if (isEmpty(state.carList)) {
|
||||
uni.showToast({ title: "请至少购买一件商品", icon: "none" });
|
||||
return;
|
||||
}
|
||||
}
|
||||
uni.showLoading({ title: "支付中...", mask: false });
|
||||
const _createtPa = { carParentId: state.carList[0].parentCarId };
|
||||
const { data: createData, code: createCode }: any =
|
||||
await payApi.createHardwareOrder(_createtPa);
|
||||
if (createCode != 0) throw new Error();
|
||||
const _submitPa = { orderId: createData };
|
||||
const { data: submitData, code: submitCode }: any =
|
||||
await payApi.submitHardwareOrder(_submitPa);
|
||||
if (submitCode != 0) throw new Error();
|
||||
uni.hideLoading();
|
||||
uni.showToast({ title: "支付成功", icon: "none" });
|
||||
router.jump("/pages/tabbar/order");
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
uni.hideLoading();
|
||||
}
|
||||
};
|
||||
|
||||
const doPay = async () => {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '是否确定购买',
|
||||
confirmColor: '#0094ff',
|
||||
success: async (res) => {
|
||||
if (!res.confirm) return
|
||||
submitPay()
|
||||
}
|
||||
})
|
||||
}
|
||||
uni.showModal({
|
||||
title: "提示",
|
||||
content: "是否确定购买",
|
||||
confirmColor: "#0094ff",
|
||||
success: async (res) => {
|
||||
if (!res.confirm) return;
|
||||
submitPay();
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const getHeight = () => {
|
||||
const rpx = 480
|
||||
return `calc(100vh - ${uni.upx2px(rpx)}px)`
|
||||
}
|
||||
const rpx = 480;
|
||||
return `calc(100vh - ${uni.upx2px(rpx)}px)`;
|
||||
};
|
||||
|
||||
const doPhone = () => {
|
||||
if (isEmpty(state.detail.phone)) {
|
||||
uni.showToast({ title: '该店铺没有预留电话', icon: "none" })
|
||||
return
|
||||
}
|
||||
hooks.useMakePhoneCall(state.detail.phone)
|
||||
}
|
||||
if (isEmpty(state.detail.phone)) {
|
||||
uni.showToast({ title: "该店铺没有预留电话", icon: "none" });
|
||||
return;
|
||||
}
|
||||
hooks.useMakePhoneCall(state.detail.phone);
|
||||
};
|
||||
const doFood = () => {
|
||||
router.jump("/pages/merchant/food", { merchantId: state.detailId })
|
||||
}
|
||||
|
||||
router.jump("/pages/merchant/food", { merchantId: state.detailId });
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<crud-layout mainIsScroll tabBarType="just-flot-back" bg="/static/page/blue-bg.png">
|
||||
<tm-sticky>
|
||||
<!-- start 轮播 start -->
|
||||
<z-swiper>
|
||||
<z-swiper-item v-for="(v, i) in state.detail.swiperPic?.split(',')" :key="i">
|
||||
<image class="w-100vw h-400rpx" :src="filePath(v)" mode="aspectFill" />
|
||||
</z-swiper-item>
|
||||
</z-swiper>
|
||||
<!-- end 轮播 end -->
|
||||
<tm-sticky-header>
|
||||
<view class="m-x-30rpx">
|
||||
<!-- 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" />
|
||||
<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>
|
||||
<view class="m-t-10rpx second-text-28">
|
||||
<text>营业时间</text>
|
||||
<text class="m-l-10rpx">
|
||||
{{ state.detail.jobStartTime }}
|
||||
~
|
||||
{{ state.detail.jobEndTime }}
|
||||
</text>
|
||||
</view>
|
||||
<view class="m-t-10rpx second-text-28">
|
||||
<text>食堂地址</text>
|
||||
<text class="m-l-10rpx">{{ state.detail.addressDes }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- end 简介 end -->
|
||||
<!-- start 功能 start -->
|
||||
<view class="h-15rpx" />
|
||||
<view class="flex-row items-center justify-evenly card p-y-20rpx">
|
||||
<view class="flex-row-center" @tap="doPhone">
|
||||
<view class="flex-row-center w-50rpx h-50rpx bg-#167aff rounded-full">
|
||||
<text class="font-size-28rpx! color-white iconfont icon-dianhua" />
|
||||
</view>
|
||||
<text class="m-l-20rpx sub-text-30">联系食堂</text>
|
||||
</view>
|
||||
<view class="w-1px h-30rpx bg-#c4c4c4" />
|
||||
<view class="flex-row-center"
|
||||
@tap.stop="router.jump('/pages/boxes/list', { id: state.detailId })">
|
||||
<view class="flex-row-center w-50rpx h-50rpx bg-#167aff rounded-full">
|
||||
<text class="font-size-28rpx! color-white iconfont icon-yuding" />
|
||||
</view>
|
||||
<text class="m-l-20rpx sub-text-28">包厢预定</text>
|
||||
</view>
|
||||
<view class="w-1px h-30rpx bg-#c4c4c4" />
|
||||
<view class="flex-row-center" @tap="doFood">
|
||||
<view class="flex-row-center w-50rpx h-50rpx bg-#167aff rounded-full">
|
||||
<text class="font-size-28rpx! color-white iconfont icon-caipu" />
|
||||
</view>
|
||||
<text class="m-l-20rpx sub-text-28">每日菜谱</text>
|
||||
</view>
|
||||
</view>
|
||||
<!-- end 功能 end -->
|
||||
<crud-layout
|
||||
mainIsScroll
|
||||
tabBarType="just-flot-back"
|
||||
bg="/static/page/blue-bg.png"
|
||||
>
|
||||
<tm-sticky>
|
||||
<!-- start 轮播 start -->
|
||||
<z-swiper>
|
||||
<z-swiper-item
|
||||
v-for="(v, i) in state.detail.swiperPic?.split(',')"
|
||||
:key="i"
|
||||
>
|
||||
<image
|
||||
class="w-100vw h-400rpx"
|
||||
:src="filePath(v)"
|
||||
mode="aspectFill"
|
||||
/>
|
||||
</z-swiper-item>
|
||||
</z-swiper>
|
||||
<!-- end 轮播 end -->
|
||||
<tm-sticky-header>
|
||||
<view class="m-x-30rpx">
|
||||
<!-- 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"
|
||||
/>
|
||||
<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>
|
||||
</tm-sticky-header>
|
||||
<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>
|
||||
<view class="m-t-10rpx second-text-28">
|
||||
<text>食堂地址</text>
|
||||
<text class="m-l-10rpx">{{ state.detail.addressDes }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- end 简介 end -->
|
||||
<!-- start 功能 start -->
|
||||
<view class="h-15rpx" />
|
||||
<view class="flex-row items-center justify-evenly card p-y-20rpx">
|
||||
<view class="flex-row-center" @tap="doPhone">
|
||||
<view
|
||||
class="flex-row-center w-50rpx h-50rpx bg-#167aff rounded-full"
|
||||
>
|
||||
<text
|
||||
class="font-size-28rpx! color-white iconfont icon-dianhua"
|
||||
/>
|
||||
</view>
|
||||
<text class="m-l-20rpx sub-text-30">联系食堂</text>
|
||||
</view>
|
||||
<view class="w-1px h-30rpx bg-#c4c4c4" />
|
||||
<view
|
||||
class="flex-row-center"
|
||||
@tap.stop="
|
||||
router.jump('/pages/boxes/list', { id: state.detailId })
|
||||
"
|
||||
>
|
||||
<view
|
||||
class="flex-row-center w-50rpx h-50rpx bg-#167aff rounded-full"
|
||||
>
|
||||
<text
|
||||
class="font-size-28rpx! color-white iconfont icon-yuding"
|
||||
/>
|
||||
</view>
|
||||
<text class="m-l-20rpx sub-text-28">包厢预定</text>
|
||||
</view>
|
||||
<view class="w-1px h-30rpx bg-#c4c4c4" />
|
||||
<view class="flex-row-center" @tap="doFood">
|
||||
<view
|
||||
class="flex-row-center w-50rpx h-50rpx bg-#167aff rounded-full"
|
||||
>
|
||||
<text
|
||||
class="font-size-28rpx! color-white iconfont icon-caipu"
|
||||
/>
|
||||
</view>
|
||||
<text class="m-l-20rpx sub-text-28">每日菜谱</text>
|
||||
</view>
|
||||
</view>
|
||||
<!-- end 功能 end -->
|
||||
</view>
|
||||
</tm-sticky-header>
|
||||
|
||||
<!-- start 商品 start -->
|
||||
<view class="h-15rpx" />
|
||||
<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">
|
||||
<view class="menu_item flex-row-center" v-for="( v, i ) in state.classifyList " :key="v.id"
|
||||
:class="[{ 'menu_item_active': i == state.currentClassifyIndex }]" @tap="doClassify(i)">
|
||||
<view class="menu_item_title show-line">
|
||||
{{ v.name }}
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<scroll-view scroll-y :style="{ height: getHeight() }" class="flex-1 p-b-20rpx">
|
||||
<view v-for="( cV, cI ) in state.shopList " :key="cI">
|
||||
<view class="flex-row-center m-y-20rpx">
|
||||
<view class="w-25rpx h-1px bg-#d2d2d2" />
|
||||
<text class="p-x-15rpx second-text-28">
|
||||
{{ cV.categoryName }}
|
||||
</text>
|
||||
<view class="w-25rpx h-1px bg-#d2d2d2" />
|
||||
</view>
|
||||
<view class="m-x-15rpx">
|
||||
<product-row v-for="( pV, pI ) in cV.foodSPURespVOList " :key="pV.id"
|
||||
v-model="pV.productCount" :productId="pV.productId" :pic="pV.picUrl" :name="pV.name"
|
||||
:price="pV.price" :marketPrice="pV.marketPrice" :salesCount="pV.salesCount"
|
||||
:stock="pV.stock" @add="doAdd(pV)" @remove="remove(pV)" />
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<!-- start 商品 start -->
|
||||
<view class="h-15rpx" />
|
||||
<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"
|
||||
>
|
||||
<view
|
||||
class="menu_item flex-row-center"
|
||||
v-for="(v, i) in state.classifyList"
|
||||
:key="v.id"
|
||||
:class="[{ menu_item_active: i == state.currentClassifyIndex }]"
|
||||
@tap="doClassify(i)"
|
||||
>
|
||||
<view class="menu_item_title show-line">
|
||||
{{ v.name }}
|
||||
</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>
|
||||
</scroll-view>
|
||||
<scroll-view
|
||||
scroll-y
|
||||
:style="{ height: getHeight() }"
|
||||
class="flex-1 p-b-20rpx"
|
||||
>
|
||||
<view v-for="(cV, cI) in state.shopList" :key="cI">
|
||||
<view class="flex-row-center m-y-20rpx">
|
||||
<view class="w-25rpx h-1px bg-#d2d2d2" />
|
||||
<text class="p-x-15rpx second-text-28">
|
||||
{{ cV.categoryName }}
|
||||
</text>
|
||||
<view class="w-25rpx h-1px bg-#d2d2d2" />
|
||||
</view>
|
||||
</template>
|
||||
</crud-layout>
|
||||
<product-car v-model="state.showCarDialog" :carList="state.carList" :totPrice="state.totPrice"
|
||||
:totCount="state.totCount" @add="doAdd" @remove="remove" @submit="doPay" />
|
||||
<view class="m-x-15rpx">
|
||||
<product-row
|
||||
v-for="(pV, pI) in cV.foodSPURespVOList"
|
||||
:key="pV.id"
|
||||
v-model="pV.productCount"
|
||||
:productId="pV.productId"
|
||||
:pic="pV.picUrl"
|
||||
:name="pV.name"
|
||||
:price="pV.price"
|
||||
:marketPrice="pV.marketPrice"
|
||||
:salesCount="pV.salesCount"
|
||||
:stock="pV.stock"
|
||||
@add="doAdd(pV)"
|
||||
@remove="remove(pV)"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-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>
|
||||
</template>
|
||||
</crud-layout>
|
||||
<product-car
|
||||
v-model="state.showCarDialog"
|
||||
:carList="state.carList"
|
||||
:totPrice="state.totPrice"
|
||||
:totCount="state.totCount"
|
||||
@add="doAdd"
|
||||
@remove="remove"
|
||||
@submit="doPay"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
:deep() {
|
||||
.layout_main>scroll-view {
|
||||
padding: 0 !important;
|
||||
}
|
||||
.layout_main > scroll-view {
|
||||
padding: 0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.menu {
|
||||
&_item {
|
||||
width: 100%;
|
||||
height: 88rpx;
|
||||
position: relative;
|
||||
&_item {
|
||||
width: 100%;
|
||||
height: 88rpx;
|
||||
position: relative;
|
||||
transition: all linear 0.2s;
|
||||
|
||||
&_title {
|
||||
width: 100%;
|
||||
line-height: 32rpx;
|
||||
font-size: 30rpx;
|
||||
font-weight: 400;
|
||||
color: #333;
|
||||
margin-left: 28rpx;
|
||||
position: relative;
|
||||
z-index: 0;
|
||||
|
||||
&::before {
|
||||
content: "";
|
||||
width: 64rpx;
|
||||
height: 12rpx;
|
||||
background: linear-gradient(90deg, #0094ff, #e9f5fe) !important;
|
||||
position: absolute;
|
||||
left: -64rpx;
|
||||
bottom: 0;
|
||||
z-index: -1;
|
||||
transition: all linear 0.2s;
|
||||
|
||||
&_title {
|
||||
width: 100%;
|
||||
line-height: 32rpx;
|
||||
font-size: 30rpx;
|
||||
font-weight: 400;
|
||||
color: #333;
|
||||
margin-left: 28rpx;
|
||||
position: relative;
|
||||
z-index: 0;
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
width: 64rpx;
|
||||
height: 12rpx;
|
||||
background: linear-gradient(90deg, #0094ff, #e9f5fe) !important;
|
||||
position: absolute;
|
||||
left: -64rpx;
|
||||
bottom: 0;
|
||||
z-index: -1;
|
||||
transition: all linear 0.2s;
|
||||
}
|
||||
}
|
||||
|
||||
&.menu_item_active {
|
||||
background-color: #fff;
|
||||
border-radius: 20rpx 0 0 20rpx;
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: -20rpx;
|
||||
width: 20rpx;
|
||||
height: 20rpx;
|
||||
background: radial-gradient(circle at 0 100%, transparent 20rpx, #fff 0);
|
||||
}
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: -20rpx;
|
||||
right: 0;
|
||||
width: 20rpx;
|
||||
height: 20rpx;
|
||||
background: radial-gradient(circle at 0% 0%, transparent 20rpx, #fff 0);
|
||||
}
|
||||
|
||||
.menu_item_title {
|
||||
font-weight: 600;
|
||||
|
||||
&::before {
|
||||
left: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.menu_item_active {
|
||||
background-color: #fff;
|
||||
border-radius: 20rpx 0 0 20rpx;
|
||||
|
||||
&::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: -20rpx;
|
||||
width: 20rpx;
|
||||
height: 20rpx;
|
||||
background: radial-gradient(
|
||||
circle at 0 100%,
|
||||
transparent 20rpx,
|
||||
#fff 0
|
||||
);
|
||||
}
|
||||
|
||||
&::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: -20rpx;
|
||||
right: 0;
|
||||
width: 20rpx;
|
||||
height: 20rpx;
|
||||
background: radial-gradient(circle at 0% 0%, transparent 20rpx, #fff 0);
|
||||
}
|
||||
|
||||
.menu_item_title {
|
||||
font-weight: 600;
|
||||
|
||||
&::before {
|
||||
left: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.car {
|
||||
box-shadow: 0 8rpx 40rpx rgba(0, 0, 0, 0.1);
|
||||
box-shadow: 0 8rpx 40rpx rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
@@ -60,13 +60,13 @@ const initDate = () => {
|
||||
})
|
||||
}
|
||||
state.dateList = list
|
||||
state.pa.startTime = state.dateList[0].dateTime
|
||||
state.pa.day = state.dateList[0].dateTime
|
||||
pageRef.value?.reload(false)
|
||||
}
|
||||
|
||||
const doDateItem = (v: any, i: any) => {
|
||||
state.currentDateIndex = i
|
||||
state.pa.startTime = state.dateList[i].dateTime
|
||||
state.pa.day = state.dateList[i].dateTime
|
||||
pageRef.value.reload(true)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,225 +0,0 @@
|
||||
<template>
|
||||
<view class="uni-numbox">
|
||||
<!-- <view @click="_calcValue('minus')" class="uni-numbox__minus uni-numbox-btns" :style="{ background }"> -->
|
||||
<!-- <text class="uni-numbox--text" :class="{ 'uni-numbox--disabled': inputValue <= min || disabled }"
|
||||
:style="{ color }">
|
||||
-
|
||||
</text> -->
|
||||
<text
|
||||
class="cicon-move-round"
|
||||
:class="{
|
||||
'uni-numbox--disabled': inputValue <= min || disabled,
|
||||
'groupon-btn': activity === 'groupon',
|
||||
'seckill-btn': activity === 'seckill',
|
||||
}"
|
||||
@click="_calcValue('minus')"
|
||||
></text>
|
||||
<!-- </view> -->
|
||||
<input
|
||||
:disabled="disabled"
|
||||
@focus="_onFocus"
|
||||
@blur="_onBlur"
|
||||
class="uni-numbox__value"
|
||||
type="number"
|
||||
v-model="inputValue"
|
||||
:style="{ color }"
|
||||
/>
|
||||
<!-- <view @click="_calcValue('plus')" class="uni-numbox__plus uni-numbox-btns">
|
||||
<text class="uni-numbox--text" :class="{ 'uni-numbox--disabled': inputValue >= max || disabled }">+</text>
|
||||
</view> -->
|
||||
<text
|
||||
class="cicon-add-round"
|
||||
:class="{
|
||||
'uni-numbox--disabled': inputValue >= max || disabled,
|
||||
'groupon-btn': activity === 'groupon',
|
||||
'seckill-btn': activity === 'seckill',
|
||||
}"
|
||||
@click="_calcValue('plus')"
|
||||
></text>
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
/**
|
||||
* NumberBox 数字输入框
|
||||
* @description 带加减按钮的数字输入框
|
||||
* @tutorial https://ext.dcloud.net.cn/plugin?id=31
|
||||
* @property {Number} value 输入框当前值
|
||||
* @property {Number} min 最小值
|
||||
* @property {Number} max 最大值
|
||||
* @property {Number} step 每次点击改变的间隔大小
|
||||
* @property {String} background 背景色
|
||||
* @property {String} color 字体颜色(前景色)
|
||||
* @property {Boolean} disabled = [true|false] 是否为禁用状态
|
||||
* @event {Function} change 输入框值改变时触发的事件,参数为输入框当前的 value
|
||||
* @event {Function} focus 输入框聚焦时触发的事件,参数为 event 对象
|
||||
* @event {Function} blur 输入框失焦时触发的事件,参数为 event 对象
|
||||
*/
|
||||
|
||||
export default {
|
||||
name: "UniNumberBox",
|
||||
emits: ["change", "input", "update:modelValue", "blur", "focus"],
|
||||
props: {
|
||||
value: {
|
||||
type: [Number, String],
|
||||
default: 1,
|
||||
},
|
||||
modelValue: {
|
||||
type: [Number, String],
|
||||
default: 1,
|
||||
},
|
||||
min: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
max: {
|
||||
type: Number,
|
||||
default: 100,
|
||||
},
|
||||
step: {
|
||||
type: Number,
|
||||
default: 1,
|
||||
},
|
||||
background: {
|
||||
type: String,
|
||||
default: "#f5f5f5",
|
||||
},
|
||||
color: {
|
||||
type: String,
|
||||
default: "#333",
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
activity: {
|
||||
type: String,
|
||||
default: "none",
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
inputValue: 0,
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
value(val) {
|
||||
this.inputValue = +val;
|
||||
},
|
||||
modelValue(val) {
|
||||
this.inputValue = +val;
|
||||
},
|
||||
},
|
||||
created() {
|
||||
if (this.value === 1) {
|
||||
this.inputValue = +this.modelValue;
|
||||
}
|
||||
if (this.modelValue === 1) {
|
||||
this.inputValue = +this.value;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
_calcValue(type) {
|
||||
if (this.disabled) {
|
||||
return;
|
||||
}
|
||||
const scale = this._getDecimalScale();
|
||||
let value = this.inputValue * scale;
|
||||
let step = this.step * scale;
|
||||
if (type === "minus") {
|
||||
value -= step;
|
||||
if (value < this.min * scale) {
|
||||
return;
|
||||
}
|
||||
if (value > this.max * scale) {
|
||||
value = this.max * scale;
|
||||
}
|
||||
}
|
||||
|
||||
if (type === "plus") {
|
||||
value += step;
|
||||
if (value > this.max * scale) {
|
||||
return;
|
||||
}
|
||||
if (value < this.min * scale) {
|
||||
value = this.min * scale;
|
||||
}
|
||||
}
|
||||
|
||||
this.inputValue = (value / scale).toFixed(String(scale).length - 1);
|
||||
this.$emit("change", +this.inputValue);
|
||||
// TODO vue2 兼容
|
||||
this.$emit("input", +this.inputValue);
|
||||
// TODO vue3 兼容
|
||||
this.$emit("update:modelValue", +this.inputValue);
|
||||
},
|
||||
_getDecimalScale() {
|
||||
let scale = 1;
|
||||
// 浮点型
|
||||
if (~~this.step !== this.step) {
|
||||
scale = Math.pow(10, String(this.step).split(".")[1].length);
|
||||
}
|
||||
return scale;
|
||||
},
|
||||
_onBlur(event) {
|
||||
this.$emit("blur", event);
|
||||
let value = event.detail.value;
|
||||
if (!value) {
|
||||
// this.inputValue = 0;
|
||||
return;
|
||||
}
|
||||
value = +value;
|
||||
if (value > this.max) {
|
||||
value = this.max;
|
||||
} else if (value < this.min) {
|
||||
value = this.min;
|
||||
}
|
||||
const scale = this._getDecimalScale();
|
||||
this.inputValue = value.toFixed(String(scale).length - 1);
|
||||
this.$emit("change", +this.inputValue);
|
||||
this.$emit("input", +this.inputValue);
|
||||
},
|
||||
_onFocus(event) {
|
||||
this.$emit("focus", event);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.uni-numbox .uni-numbox--disabled {
|
||||
color: #c0c0c0 !important;
|
||||
/* #ifdef H5 */
|
||||
cursor: not-allowed;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.uni-numbox {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.uni-numbox__value {
|
||||
width: 74rpx;
|
||||
text-align: center;
|
||||
font-size: 30rpx;
|
||||
}
|
||||
|
||||
.cicon-move-round {
|
||||
font-size: 44rpx;
|
||||
color: var(--ui-BG-Main);
|
||||
}
|
||||
|
||||
.cicon-add-round {
|
||||
font-size: 44rpx;
|
||||
color: var(--ui-BG-Main);
|
||||
}
|
||||
|
||||
.groupon-btn {
|
||||
color: #ff6000;
|
||||
}
|
||||
|
||||
.seckill-btn {
|
||||
color: #ff5854;
|
||||
}
|
||||
</style>
|
||||
@@ -1,51 +1,3 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, withDefaults, defineProps, defineEmits } from "vue";
|
||||
import { onLoad, onShow } from "@dcloudio/uni-app";
|
||||
|
||||
import { hooks, router } from "@@/index";
|
||||
import { merchantApi } from "@@/api";
|
||||
|
||||
import ProductRow from "./product-row.vue";
|
||||
import ProductTotal from "./product-total.vue";
|
||||
|
||||
const emit = defineEmits(["update:modelValue", "submit", "doContainer", "add", "remove"]);
|
||||
|
||||
export type Props = {
|
||||
modelValue: any;
|
||||
carList: any;
|
||||
totPrice: number;
|
||||
totCount: number;
|
||||
};
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
modelValue: false,
|
||||
carList: [],
|
||||
totPrice: 0,
|
||||
totCount: 0,
|
||||
});
|
||||
|
||||
const state = reactive<any>({});
|
||||
|
||||
onLoad(() => {});
|
||||
onShow(() => {});
|
||||
|
||||
const doClose = () => {
|
||||
emit("update:modelValue");
|
||||
};
|
||||
|
||||
const doPay = () => {
|
||||
emit("submit");
|
||||
};
|
||||
|
||||
const doContainer = () => {
|
||||
emit("doContainer");
|
||||
};
|
||||
|
||||
const getHeight = () => {
|
||||
const { bottom } = uni.getSystemInfoSync().safeAreaInsets!;
|
||||
return `-${bottom + 16}px`;
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<tm-drawer z-index="100" v-model:show="props.modelValue" showFooter title="购物车" position="bottom" size="60%" @close="doClose">
|
||||
<product-row
|
||||
@@ -63,16 +15,44 @@ const getHeight = () => {
|
||||
@add="() => emit('add', v)"
|
||||
@remove="emit('remove', v)"
|
||||
/>
|
||||
|
||||
<template #footer>
|
||||
<view class="car z-200 p-x-30rpx p-y-30rpx bg-white" :style="{ marginBottom: getHeight() }">
|
||||
<product-total :totPrice="props.totPrice" :totCount="props.totCount" @submit="doPay" @doContainer="doContainer" />
|
||||
<product-total :totPrice="props.totPrice" :totCount="props.totCount" @doPay="doPay" />
|
||||
</view>
|
||||
</template>
|
||||
</tm-drawer>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.car {
|
||||
box-shadow: 0 8rpx 40rpx rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
</style>
|
||||
<script setup lang="ts">
|
||||
import ProductRow from "./product-row.vue";
|
||||
import ProductTotal from "./product-total.vue";
|
||||
|
||||
const emit = defineEmits(["update:modelValue", "doPay", "add", "remove"]);
|
||||
|
||||
export type Props = {
|
||||
modelValue: any;
|
||||
carList: any;
|
||||
totPrice: number;
|
||||
totCount: number;
|
||||
};
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
modelValue: false,
|
||||
carList: [],
|
||||
totPrice: 0,
|
||||
totCount: 0,
|
||||
});
|
||||
|
||||
const doClose = () => {
|
||||
emit("update:modelValue", false);
|
||||
};
|
||||
|
||||
const doPay = () => {
|
||||
emit("doPay");
|
||||
};
|
||||
|
||||
const getHeight = () => {
|
||||
const { bottom } = uni.getSystemInfoSync().safeAreaInsets!;
|
||||
return `-${bottom + 16}px`;
|
||||
};
|
||||
</script>
|
||||
@@ -17,7 +17,7 @@
|
||||
</view>
|
||||
<view
|
||||
class="second-text-24 w-200rpx py-1 border-1px border-solid border-#0094ff bg-#0094ff c-white! border-rd-8 text-center mt-1 float-right"
|
||||
@tap.stop="handleClickSelectSku(props.productId)"
|
||||
@tap.stop="handleClickAddToCar({ ...props })"
|
||||
>
|
||||
加入购物车
|
||||
</view>
|
||||
@@ -26,25 +26,24 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onLoad, onShow } from "@dcloudio/uni-app";
|
||||
import { hooks, router } from "@@/index";
|
||||
|
||||
const emit = defineEmits(["update:modelValue", "selectSku"]);
|
||||
const emit = defineEmits(["onClickAddToCar"]);
|
||||
|
||||
export type Props = {
|
||||
modelValue: number;
|
||||
productId: number | null;
|
||||
productCount: number;
|
||||
pic: string;
|
||||
name: string;
|
||||
price: number;
|
||||
marketPrice: number;
|
||||
salesCount: number;
|
||||
stock: number;
|
||||
selectSku: () => void;
|
||||
onClickAddToCar?: () => void;
|
||||
};
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
modelValue: 0,
|
||||
productId: null,
|
||||
productCount: 0,
|
||||
pic: "",
|
||||
name: "",
|
||||
price: 0,
|
||||
@@ -53,12 +52,7 @@ const props = withDefaults(defineProps<Props>(), {
|
||||
stock: 0,
|
||||
});
|
||||
|
||||
const handleClickSelectSku = (productId: number | null) => {
|
||||
if (productId) {
|
||||
emit("selectSku", productId);
|
||||
}
|
||||
const handleClickAddToCar = (productData: any) => {
|
||||
emit("onClickAddToCar", productData);
|
||||
};
|
||||
|
||||
onLoad(() => {});
|
||||
onShow(() => {});
|
||||
</script>
|
||||
@@ -0,0 +1,186 @@
|
||||
<template>
|
||||
<tm-drawer z-index="100" v-model:show="props.modelValue" showFooter title="加入购物车" position="bottom" size="60%" @close="doClose">
|
||||
<view class="px-20rpx">
|
||||
<scroll-view scroll-y="true" class="max-h-7xl" @touchmove.stop>
|
||||
<!-- 商品信息 -->
|
||||
<view class="m-3 flex-row">
|
||||
<image class="w-120rpx h-120rpx" :src="productData.pic" mode="aspectFill" />
|
||||
<view class="w-100% ml-3 flex flex-col justify-between">
|
||||
<view class="sub-text-30 font-600! ws-nowrap text-ellipsis overflow-hidden">{{ productData.name }}</view>
|
||||
<view class="flex justify-between items-center">
|
||||
<view class="c-red text-34">¥{{ productData.price }}</view>
|
||||
<view class="sub-text-28">库存{{ productData.salesCount }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 规格 -->
|
||||
<view v-for="property in propertyList" :key="property.id">
|
||||
<view class="sub-text-32 font-600! my-2">{{ property.name }}</view>
|
||||
<view class="flex flex-wrap">
|
||||
<button
|
||||
class="text-center bg-#F4F4F4 border-rd-8 c-black ml-0 mr-2 mb-2 border-none outline-none sub-text-34"
|
||||
v-for="value in property.values"
|
||||
:key="value.id"
|
||||
:disabled="value.disabled === true"
|
||||
:style="{ 'background-color': state.currentPropertyArray[property.id] === value.id ? '#0094ff' : '#F4F4F4' }"
|
||||
@click="onSelectSku(property.id, value.id)"
|
||||
>
|
||||
{{ value.name }}
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 数量 -->
|
||||
<view class="sub-text-32 font-600! my-2">购买数量</view>
|
||||
<view class="flex-row items-center justify-end m-t-20rpx">
|
||||
<text
|
||||
class="size-40rpx rounded-full flex justify-center items-center font-600! bg-#0094ff"
|
||||
:style="{ backgroundColor: state.count <= 1 ? '#999999' : '#0094ff' }"
|
||||
@click="handleNumRemove()"
|
||||
>
|
||||
-
|
||||
</text>
|
||||
<text class="sub-text-28 m-x-20rpx">{{ String(state.count).padStart(2, "0") }}</text>
|
||||
<text
|
||||
class="size-40rpx rounded-full flex justify-center items-center font-600! bg-#0094ff"
|
||||
:style="{ backgroundColor: state.count >= productData.salesCount ? '#999999' : '#0094ff' }"
|
||||
@click="handleNumAdd()"
|
||||
>
|
||||
+
|
||||
</text>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
|
||||
<template #footer>
|
||||
<button class="mx-10 border-rd-8 bg-#0094ff" @tap="handleClickAddToCar">加入购物车</button>
|
||||
</template>
|
||||
</tm-drawer>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, reactive } from "vue";
|
||||
|
||||
const emit = defineEmits(["update:modelValue", "onAddToCar"]);
|
||||
|
||||
const propertyList = reactive([
|
||||
{
|
||||
id: "1",
|
||||
name: "颜色",
|
||||
values: [
|
||||
{ id: "1", name: "红色", disabled: false },
|
||||
{ id: "2", name: "蓝色", disabled: false },
|
||||
],
|
||||
},
|
||||
{ id: "2", name: "版本", values: [{ id: "3", name: "黑色", disabled: false }] },
|
||||
]);
|
||||
|
||||
export type Props = {
|
||||
modelValue: boolean;
|
||||
productData: any;
|
||||
onAddToCar?: () => void;
|
||||
};
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
modelValue: false,
|
||||
productData: {},
|
||||
});
|
||||
|
||||
const state = reactive<any>({
|
||||
count: 1,
|
||||
selectedSku: {}, // 选中的 SKU
|
||||
currentPropertyArray: [], // 当前选中的属性,实际是个 Map。key 是 property 编号,value 是 value 编号
|
||||
});
|
||||
|
||||
// SKU 列表
|
||||
// const skuList = computed(() => {
|
||||
// let skuPrices = props.goodsInfo.skus;
|
||||
// for (let price of skuPrices) {
|
||||
// price.value_id_array = price.properties.map((item) => item.valueId);
|
||||
// }
|
||||
// return skuPrices;
|
||||
// });
|
||||
|
||||
// 当前所选属性下,获取所有有库存的 SKU 们
|
||||
// function getCanUseSkuList() {
|
||||
// let newSkus = [];
|
||||
// for (let sku of skuList.value) {
|
||||
// if (sku.stock <= 0) {
|
||||
// continue;
|
||||
// }
|
||||
// let isOk = true;
|
||||
// state.currentPropertyArray.forEach((propertyId) => {
|
||||
// // propertyId 不为空,并且,这个 条 sku 没有被选中,则排除
|
||||
// if (propertyId.toString() !== "" && sku.value_id_array.indexOf(propertyId) < 0) {
|
||||
// isOk = false;
|
||||
// }
|
||||
// });
|
||||
// if (isOk) {
|
||||
// newSkus.push(sku);
|
||||
// }
|
||||
// }
|
||||
// return newSkus;
|
||||
// }
|
||||
|
||||
// 选择规格
|
||||
function onSelectSku(propertyId: string | number, valueId: string | number) {
|
||||
// 清空已选择
|
||||
let isChecked = true; // 选中 or 取消选中
|
||||
if (state.currentPropertyArray[propertyId] !== undefined && state.currentPropertyArray[propertyId] === valueId) {
|
||||
// 点击已被选中的,删除并填充 ''
|
||||
isChecked = false;
|
||||
state.currentPropertyArray.splice(propertyId, 1, "");
|
||||
} else {
|
||||
// 选中
|
||||
state.currentPropertyArray[propertyId] = valueId;
|
||||
}
|
||||
|
||||
// 选中的 property 大类
|
||||
let choosePropertyId: any = [];
|
||||
state.currentPropertyArray.forEach((currentPropertyId: string) => {
|
||||
if (currentPropertyId !== "") {
|
||||
// currentPropertyId 为空是反选 填充的
|
||||
choosePropertyId.push(currentPropertyId);
|
||||
}
|
||||
});
|
||||
|
||||
// 当前所选 property 下,所有可以选择的 SKU 们
|
||||
// let newSkuList = getCanUseSkuList();
|
||||
|
||||
// 判断所有 property 大类是否选择完成
|
||||
// if (choosePropertyId.length === propertyList.length && newSkuList.length) {
|
||||
// newSkuList[0].name = state.selectedSku.goods_num || 1;
|
||||
// state.selectedSku = newSkuList[0];
|
||||
// } else {
|
||||
// state.selectedSku = {};
|
||||
// }
|
||||
if (choosePropertyId.length === propertyList.length) {
|
||||
state.selectedSku = state.currentPropertyArray;
|
||||
}
|
||||
|
||||
// 改变 property 禁用状态
|
||||
// changeDisabled(isChecked, propertyId, valueId);
|
||||
}
|
||||
|
||||
const handleNumAdd = () => {
|
||||
if (state.count >= props.productData.salesCount) {
|
||||
return;
|
||||
}
|
||||
state.count += 1;
|
||||
};
|
||||
const handleNumRemove = () => {
|
||||
if (state.count <= 1) {
|
||||
return;
|
||||
}
|
||||
state.count -= 1;
|
||||
};
|
||||
|
||||
// 点击加入购物车
|
||||
const handleClickAddToCar = () => {
|
||||
emit("onAddToCar", { productData: props.productData, state });
|
||||
};
|
||||
|
||||
const doClose = () => {
|
||||
emit("update:modelValue", false);
|
||||
};
|
||||
</script>
|
||||
@@ -1,127 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, withDefaults, defineProps, defineEmits } from "vue";
|
||||
import { onLoad, onShow } from "@dcloudio/uni-app";
|
||||
|
||||
import ProductRow from "./product-row.vue";
|
||||
import ProductTotal from "./product-total.vue";
|
||||
import NumberBox from "./number-box.vue";
|
||||
|
||||
const emit = defineEmits(["update:modelValue", "submit", "doContainer", "add", "remove"]);
|
||||
|
||||
export type Props = {
|
||||
modelValue: any;
|
||||
carList: any;
|
||||
totPrice: number;
|
||||
totCount: number;
|
||||
};
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
modelValue: false,
|
||||
carList: [],
|
||||
totPrice: 0,
|
||||
totCount: 0,
|
||||
});
|
||||
|
||||
const state = reactive<any>({
|
||||
selectedSku: {
|
||||
goods_num: 10,
|
||||
stock: 0,
|
||||
},
|
||||
});
|
||||
|
||||
onLoad(() => {});
|
||||
onShow(() => {});
|
||||
|
||||
const doClose = () => {
|
||||
emit("update:modelValue");
|
||||
};
|
||||
|
||||
const onNumberChange = (e: any) => {
|
||||
console.log("11");
|
||||
};
|
||||
const onSelectSku = (propertyId, valueId) => {
|
||||
console.log(propertyId, valueId);
|
||||
};
|
||||
const onAddCart = () => {
|
||||
// emit("submit", state.selectedSku);
|
||||
console.log(222);
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<tm-drawer z-index="100" v-model:show="props.modelValue" showFooter title="加入购物车" position="bottom" size="60%" @close="doClose">
|
||||
<!-- <product-row
|
||||
v-for="(v, i) in props.carList"
|
||||
mode="car"
|
||||
:key="v.id"
|
||||
v-model="v.productCount"
|
||||
:pic="v.productPic"
|
||||
:count="v.productCount"
|
||||
:name="v.name"
|
||||
:price="v.productPrice"
|
||||
:marketPrice="v.marketPrice"
|
||||
:salesCount="v.salesCount"
|
||||
:stock="v.stock"
|
||||
@add="() => emit('add', v)"
|
||||
@remove="emit('remove', v)"
|
||||
/> -->
|
||||
<!-- 属性选择 -->
|
||||
<view class="px-20rpx">
|
||||
<scroll-view scroll-y="true" class="max-h-7xl" @touchmove.stop>
|
||||
<view
|
||||
v-for="property in [
|
||||
{
|
||||
id: '1',
|
||||
name: '颜色',
|
||||
values: [
|
||||
{ id: '2', name: '22', disabled: false },
|
||||
{ id: '2', name: '22', disabled: false },
|
||||
],
|
||||
},
|
||||
{ id: '1', name: '版本', values: [{ id: '3', name: '33', disabled: false }] },
|
||||
]"
|
||||
:key="property.id"
|
||||
>
|
||||
<view>{{ property.name }}</view>
|
||||
<view class="flex flex-wrap">
|
||||
<button
|
||||
class="lh-relaxed w-100rpx text-center bg-#999 border-rd-8 c-white ml-0 mr-2 mb-2"
|
||||
v-for="value in property.values"
|
||||
:key="value.id"
|
||||
:disabled="value.disabled === true"
|
||||
@tap="onSelectSku(property.id, value.id)"
|
||||
>
|
||||
{{ value.name }}
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
<view>购买数量</view>
|
||||
<view class="flex-row items-center justify-end m-t-20rpx">
|
||||
<view class="flex-row-center size-40rpx rounded-full border-1px border-solid border-color-#0094ff" @tap.stop="remove">
|
||||
<view class="iconfont icon-a--" />
|
||||
</view>
|
||||
<view class="sub-text-28 m-x-20rpx">{{ props.modelValue }}</view>
|
||||
<view class="flex-row-center size-40rpx rounded-full bg-#0094ff" @tap.stop="add">
|
||||
<view class="font-size-40rpx color-white iconfont icon-a-" />
|
||||
</view>
|
||||
</view>
|
||||
<!-- <number-box
|
||||
:min="1"
|
||||
:max="state.selectedSku.stock"
|
||||
:step="1"
|
||||
v-model="state.selectedSku.goods_num"
|
||||
@change="onNumberChange($event)"
|
||||
/> -->
|
||||
</scroll-view>
|
||||
</view>
|
||||
|
||||
<template #footer>
|
||||
<button class="ss-reset-button add-btn ui-Shadow-Main" @tap="onAddCart">加入购物车</button>
|
||||
</template>
|
||||
</tm-drawer>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.car {
|
||||
box-shadow: 0 8rpx 40rpx rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
</style>
|
||||
@@ -1,59 +1,37 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, withDefaults, defineProps, defineEmits } from "vue";
|
||||
import { onLoad, onShow } from "@dcloudio/uni-app";
|
||||
|
||||
import { hooks, router } from "@@/index"
|
||||
import { merchantApi } from "@@/api"
|
||||
|
||||
const emit = defineEmits(["submit", "doContainer"])
|
||||
|
||||
export type Props = {
|
||||
totPrice: number,
|
||||
totCount: number,
|
||||
}
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
totPrice: 0,
|
||||
totCount: 0,
|
||||
});
|
||||
|
||||
const state = reactive<any>({
|
||||
|
||||
})
|
||||
|
||||
onLoad(() => {
|
||||
|
||||
});
|
||||
onShow(() => {
|
||||
|
||||
})
|
||||
|
||||
const doPay = () => {
|
||||
emit("submit")
|
||||
}
|
||||
|
||||
const doContainer = () => {
|
||||
emit("doContainer")
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
<template>
|
||||
<view class="flex-row items-center justify-between" @tap="doContainer">
|
||||
<view class="flex-row-center">
|
||||
<view class="flex-row-center size-80rpx rounded-full bg-#0094ff">
|
||||
<view class="color-white! iconfont icon-biaoqianlanicon_gouwuche-xuanzhong" />
|
||||
</view>
|
||||
<view class="flex-col m-l-30rpx">
|
||||
<view class="second-text-36 color-#f63a36!">¥ {{ hooks.useMoney(props.totPrice) }}</view>
|
||||
<view class="sub-text-28">共{{ props.totCount }}件</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="bg-#0094ff p-x-30rpx p-y-20rpx text-center rounded-40rpx sub-text-30 color-white!"
|
||||
@tap.stop="doPay">
|
||||
购买
|
||||
</view>
|
||||
<view class="flex-row items-center justify-between" @tap="doContainer">
|
||||
<view class="flex-row-center">
|
||||
<view class="flex-row-center size-80rpx rounded-full bg-#0094ff">
|
||||
<view class="color-white! iconfont icon-biaoqianlanicon_gouwuche-xuanzhong" />
|
||||
</view>
|
||||
<view class="flex-col m-l-30rpx">
|
||||
<view class="second-text-36 color-#f63a36!">¥ {{ hooks.useMoney(props.totPrice) }}</view>
|
||||
<view class="sub-text-28">共{{ props.totCount }}件</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="bg-#0094ff p-x-30rpx p-y-20rpx text-center rounded-40rpx sub-text-30 color-white!" @tap.stop="doPay">提交订单</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
<script setup lang="ts">
|
||||
import { hooks } from "@@/index";
|
||||
|
||||
const emit = defineEmits(["doPay", "doContainer"]);
|
||||
|
||||
export type Props = {
|
||||
totPrice: number;
|
||||
totCount: number;
|
||||
};
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
totPrice: 0,
|
||||
totCount: 0,
|
||||
});
|
||||
|
||||
const doPay = () => {
|
||||
emit("doPay");
|
||||
};
|
||||
|
||||
const doContainer = () => {
|
||||
emit("doContainer");
|
||||
};
|
||||
</script>
|
||||
@@ -70,6 +70,7 @@
|
||||
<!-- 操作区 -->
|
||||
<view class="modal-footer border-top">
|
||||
<view class="buy-box ss-flex ss-col-center ss-flex ss-col-center ss-row-center">
|
||||
<button class="ss-reset-button add-btn ui-Shadow-Main" @tap="onAddCart">加入购物车</button>
|
||||
<button class="ss-reset-button buy-btn ui-Shadow-Main" @tap="onBuy">立即购买</button>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
+213
-241
@@ -1,204 +1,3 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, nextTick } from "vue";
|
||||
import { onLoad, onShow } from "@dcloudio/uni-app";
|
||||
import { isEmpty } from "radash";
|
||||
|
||||
import { hooks, router } from "@@/index";
|
||||
import { merchantApi, foodApi, payApi } from "@@/api";
|
||||
|
||||
import 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 ProductRow from "./components/product-row.vue";
|
||||
import ProductCar from "./components/product-car.vue";
|
||||
import ProductTotal from "./components/product-total.vue";
|
||||
import ProductSpec from "./components/product-spec.vue";
|
||||
|
||||
const state = reactive<any>({
|
||||
detailId: null,
|
||||
systemType: 3,
|
||||
totPrice: 0,
|
||||
totCount: 0,
|
||||
currentClassifyIndex: 0,
|
||||
showCarDialog: false,
|
||||
showSpecDialog: false,
|
||||
|
||||
detail: {},
|
||||
carList: [],
|
||||
classifyList: [],
|
||||
shopList: [],
|
||||
});
|
||||
|
||||
onLoad((options: any) => {
|
||||
if (!isEmpty(options.id)) {
|
||||
state.detailId = options.id;
|
||||
}
|
||||
});
|
||||
onShow(() => {
|
||||
getDetail();
|
||||
getShopCar();
|
||||
getClassify();
|
||||
});
|
||||
|
||||
const getDetail = async () => {
|
||||
const _pa = { id: state.detailId };
|
||||
const { data } = await merchantApi.detail(_pa);
|
||||
state.detail = data;
|
||||
};
|
||||
|
||||
const getShopCar = async () => {
|
||||
const _pa = { merchantId: state.detailId };
|
||||
const { data } = await foodApi.getShopCar(_pa);
|
||||
|
||||
state.carList = data ?? [];
|
||||
state.totPrice = state.carList.map((v) => v.totalPrice).reduce((pre, next) => pre + next, 0);
|
||||
state.totCount = state.carList.map((v) => v.productCount).reduce((pre, next) => pre + next, 0);
|
||||
};
|
||||
|
||||
const getClassify = async () => {
|
||||
const _pa = { systemType: state.systemType, merchantId: state.detailId };
|
||||
const { data } = await foodApi.classify(_pa);
|
||||
state.classifyList = data;
|
||||
if (!isEmpty(state.classifyList)) {
|
||||
getPorduct();
|
||||
}
|
||||
};
|
||||
|
||||
const updateShopCar = async () => {
|
||||
if (isEmpty(state.carList)) return;
|
||||
const list = state.carList
|
||||
.filter((v) => v.productCount && v.productCount > 0)
|
||||
.map((v) => {
|
||||
return {
|
||||
productCount: v.productCount,
|
||||
productId: v.productId,
|
||||
};
|
||||
});
|
||||
if (isEmpty(list)) return;
|
||||
const _pa = { merchantId: state.detailId, list: list };
|
||||
const { data, code }: any = await foodApi.updateShopCar(_pa);
|
||||
if (code == 0) await getShopCar();
|
||||
};
|
||||
|
||||
const getPorduct = async () => {
|
||||
const target = state.classifyList[state.currentClassifyIndex];
|
||||
if (isEmpty(target)) return;
|
||||
const _pa = {
|
||||
systemType: state.systemType,
|
||||
merchantId: state.detailId,
|
||||
categoryId: target.id,
|
||||
};
|
||||
const { data } = await foodApi.product(_pa);
|
||||
state.shopList = data;
|
||||
state.shopList.forEach((i) => {
|
||||
if (i && i.foodSPURespVOList && i.foodSPURespVOList.length) {
|
||||
i.foodSPURespVOList.forEach((j) => {
|
||||
j.productCount = 0;
|
||||
j.productId = j.id;
|
||||
});
|
||||
}
|
||||
});
|
||||
const shopList = [...state.shopList];
|
||||
if (state.carList && state.carList.length) {
|
||||
for (const i of shopList) {
|
||||
if (i && i.foodSPURespVOList && i.foodSPURespVOList.length) {
|
||||
for (const j of i.foodSPURespVOList) {
|
||||
for (const v of state.carList) {
|
||||
if (j.id == v.productId) {
|
||||
j.productCount = v.productCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
state.shopList = shopList;
|
||||
};
|
||||
|
||||
const doAdd = async (item: any) => {
|
||||
chentProductCount(item);
|
||||
};
|
||||
|
||||
const remove = async (item: any) => {
|
||||
chentProductCount(item);
|
||||
};
|
||||
|
||||
const chentProductCount = async (item: any) => {
|
||||
const target = state.carList.find((v) => v.productId == item.productId);
|
||||
const targetIndex = state.carList.findIndex((v) => v.productId == item.productId);
|
||||
if (target) {
|
||||
state.carList[targetIndex].productCount = item.productCount;
|
||||
} else {
|
||||
state.carList.push({ ...item, productId: item.id });
|
||||
}
|
||||
nextTick(() => updateShopCar());
|
||||
};
|
||||
|
||||
const doClassify = (i: any) => {
|
||||
state.currentClassifyIndex = i;
|
||||
getClassify();
|
||||
};
|
||||
|
||||
const doVisibleCar = async () => {
|
||||
state.showCarDialog = true;
|
||||
};
|
||||
|
||||
const submitPay = async () => {
|
||||
try {
|
||||
if (isEmpty(state.carList)) {
|
||||
uni.showToast({ title: "请至少购买一件商品", icon: "none" });
|
||||
return;
|
||||
}
|
||||
uni.showLoading({ title: "支付中...", mask: false });
|
||||
const _createtPa = { carParentId: state.carList[0].parentCarId };
|
||||
const { data: createData, code: createCode }: any = await payApi.createHardwareOrder(_createtPa);
|
||||
if (createCode != 0) throw new Error();
|
||||
const _submitPa = { orderId: createData };
|
||||
const { data: submitData, code: submitCode }: any = await payApi.submitHardwareOrder(_submitPa);
|
||||
if (submitCode != 0) throw new Error();
|
||||
uni.hideLoading();
|
||||
uni.showToast({ title: "支付成功", icon: "none" });
|
||||
router.jump("/pages/tabbar/order");
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
uni.hideLoading();
|
||||
}
|
||||
};
|
||||
|
||||
const doPay = async () => {
|
||||
uni.showModal({
|
||||
title: "提示",
|
||||
content: "是否确定购买",
|
||||
confirmColor: "#0094ff",
|
||||
success: async (res) => {
|
||||
if (!res.confirm) return;
|
||||
submitPay();
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const getHeight = () => {
|
||||
const rpx = 480;
|
||||
return `calc(100vh - ${uni.upx2px(rpx)}px)`;
|
||||
};
|
||||
|
||||
const doPhone = () => {
|
||||
if (isEmpty(state.detail.phone)) {
|
||||
uni.showToast({ title: "该店铺没有预留电话", icon: "none" });
|
||||
return;
|
||||
}
|
||||
hooks.useMakePhoneCall(state.detail.phone);
|
||||
};
|
||||
const doFood = () => {
|
||||
router.jump("/pages/merchant/food", { merchantId: state.detailId });
|
||||
};
|
||||
|
||||
const selectSku = (productId: number | null) => {
|
||||
state.showSpecDialog = true;
|
||||
console.log(productId);
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<crud-layout mainIsScroll tabBarType="just-flot-back" bg="/static/page/blue-bg.png">
|
||||
<tm-sticky>
|
||||
@@ -212,8 +11,8 @@ const selectSku = (productId: number | null) => {
|
||||
|
||||
<tm-sticky-header>
|
||||
<view class="m-x-30rpx">
|
||||
<!-- start 简介 start -->
|
||||
<view class="h-15rpx" />
|
||||
<!-- start 简介 start -->
|
||||
<view flex-row card p-20rpx>
|
||||
<image class="w-160rpx h-160rpx rounded-12rpx" :src="state.detail.logo" mode="aspectFill" />
|
||||
<view class="flex-1 flex-col m-l-20rpx">
|
||||
@@ -245,32 +44,7 @@ const selectSku = (productId: number | null) => {
|
||||
</view>
|
||||
</view>
|
||||
<!-- end 简介 end -->
|
||||
|
||||
<!-- start 功能 start -->
|
||||
<view class="h-15rpx" />
|
||||
<!-- <view class="flex-row items-center justify-evenly card p-y-20rpx">
|
||||
<view class="flex-row-center" @tap="doPhone">
|
||||
<view class="flex-row-center w-50rpx h-50rpx bg-#167aff rounded-full">
|
||||
<text class="font-size-28rpx! color-white iconfont icon-dianhua" />
|
||||
</view>
|
||||
<text class="m-l-20rpx sub-text-30">联系食堂</text>
|
||||
</view>
|
||||
<view class="w-1px h-30rpx bg-#c4c4c4" />
|
||||
<view class="flex-row-center" @tap.stop="router.jump('/pages/boxes/list', { id: state.detailId })">
|
||||
<view class="flex-row-center w-50rpx h-50rpx bg-#167aff rounded-full">
|
||||
<text class="font-size-28rpx! color-white iconfont icon-yuding" />
|
||||
</view>
|
||||
<text class="m-l-20rpx sub-text-28">包厢预定</text>
|
||||
</view>
|
||||
<view class="w-1px h-30rpx bg-#c4c4c4" />
|
||||
<view class="flex-row-center" @tap="doFood">
|
||||
<view class="flex-row-center w-50rpx h-50rpx bg-#167aff rounded-full">
|
||||
<text class="font-size-28rpx! color-white iconfont icon-caipu" />
|
||||
</view>
|
||||
<text class="m-l-20rpx sub-text-28">每日菜谱</text>
|
||||
</view>
|
||||
</view> -->
|
||||
<!-- end 功能 end -->
|
||||
</view>
|
||||
</tm-sticky-header>
|
||||
|
||||
@@ -305,15 +79,15 @@ const selectSku = (productId: number | null) => {
|
||||
<product-row
|
||||
v-for="pV in cV.foodSPURespVOList"
|
||||
:key="pV.id"
|
||||
v-model="pV.productCount"
|
||||
:productId="pV.productId"
|
||||
:productCount="pV.productCount"
|
||||
:pic="pV.picUrl"
|
||||
:name="pV.name"
|
||||
:price="pV.price"
|
||||
:marketPrice="pV.marketPrice"
|
||||
:salesCount="pV.salesCount"
|
||||
:stock="pV.stock"
|
||||
@select-sku="selectSku"
|
||||
@onClickAddToCar="onClickAddToCar"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
@@ -324,32 +98,230 @@ const selectSku = (productId: number | null) => {
|
||||
|
||||
<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" />
|
||||
<product-total :totPrice="state.totPrice" :totCount="state.totCount" @doContainer="doVisibleCar" @doPay="doPay" />
|
||||
</view>
|
||||
</template>
|
||||
</crud-layout>
|
||||
|
||||
<product-car
|
||||
v-model="state.showCarDialog"
|
||||
v-model="showCarDialog"
|
||||
:carList="state.carList"
|
||||
:totPrice="state.totPrice"
|
||||
:totCount="state.totCount"
|
||||
@add="doAdd"
|
||||
@remove="remove"
|
||||
@submit="doPay"
|
||||
@doPay="doPay"
|
||||
/>
|
||||
<!-- 规格与数量弹框 -->
|
||||
<product-spec
|
||||
v-model="state.showSpecDialog"
|
||||
:carList="state.carList"
|
||||
:totPrice="state.totPrice"
|
||||
:totCount="state.totCount"
|
||||
@add="doAdd"
|
||||
@remove="remove"
|
||||
@submit="doPay"
|
||||
/>
|
||||
<product-sku v-model="showSkuDialog" :productData="curProductData" @onAddToCar="onAddToCar" />
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { reactive, nextTick, ref } from "vue";
|
||||
import { onLoad, onShow } from "@dcloudio/uni-app";
|
||||
import { isEmpty } from "radash";
|
||||
import { hooks, router } from "@@/index";
|
||||
import { merchantApi, foodApi, payApi } from "@@/api";
|
||||
import 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 ProductRow from "./components/product-row.vue";
|
||||
import ProductCar from "./components/product-car.vue";
|
||||
import ProductTotal from "./components/product-total.vue";
|
||||
import ProductSku from "./components/product-sku.vue";
|
||||
|
||||
// 商品详情相关数据
|
||||
const state = reactive<any>({
|
||||
detailId: null,
|
||||
detail: {},
|
||||
carList: [],
|
||||
totPrice: 0,
|
||||
totCount: 0,
|
||||
systemType: 3,
|
||||
classifyList: [],
|
||||
shopList: [],
|
||||
currentClassifyIndex: 0,
|
||||
});
|
||||
// 当前点击加入购物车的商品信息
|
||||
const curProductData = ref<any>({});
|
||||
// sku 弹框开关
|
||||
const showSkuDialog = ref<boolean>(false);
|
||||
// 购物车弹框开关
|
||||
const showCarDialog = ref<boolean>(false);
|
||||
|
||||
onLoad((options: any) => {
|
||||
if (!isEmpty(options.id)) {
|
||||
state.detailId = options.id;
|
||||
}
|
||||
});
|
||||
onShow(() => {
|
||||
getDetail();
|
||||
getShopCar();
|
||||
getClassify();
|
||||
});
|
||||
|
||||
const getDetail = async () => {
|
||||
const { data } = await merchantApi.detail({ id: state.detailId });
|
||||
state.detail = data;
|
||||
};
|
||||
|
||||
const getShopCar = async () => {
|
||||
const { data } = await foodApi.getShopCar({ merchantId: state.detailId });
|
||||
state.carList = data ?? [];
|
||||
state.totPrice = state.carList.map((v) => v.totalPrice).reduce((pre, next) => pre + next, 0);
|
||||
state.totCount = state.carList.map((v) => v.productCount).reduce((pre, next) => pre + next, 0);
|
||||
};
|
||||
|
||||
const getClassify = async () => {
|
||||
const { data } = await foodApi.classify({ systemType: state.systemType, merchantId: state.detailId });
|
||||
state.classifyList = data;
|
||||
if (!isEmpty(state.classifyList)) {
|
||||
getPorduct();
|
||||
}
|
||||
};
|
||||
|
||||
const updateShopCar = async () => {
|
||||
if (isEmpty(state.carList)) return;
|
||||
const list = state.carList
|
||||
.filter((v) => v.productCount && v.productCount > 0)
|
||||
.map((v) => {
|
||||
return {
|
||||
productCount: v.productCount,
|
||||
productId: v.productId,
|
||||
};
|
||||
});
|
||||
if (isEmpty(list)) return;
|
||||
const { data, code }: any = await foodApi.updateShopCar({ merchantId: state.detailId, list: list });
|
||||
if (code == 0) await getShopCar();
|
||||
};
|
||||
|
||||
const getPorduct = async () => {
|
||||
const target = state.classifyList[state.currentClassifyIndex];
|
||||
if (isEmpty(target)) return;
|
||||
const { data } = await foodApi.product({
|
||||
systemType: state.systemType,
|
||||
merchantId: state.detailId,
|
||||
categoryId: target.id,
|
||||
});
|
||||
state.shopList = data;
|
||||
state.shopList.forEach((i) => {
|
||||
if (i && i.foodSPURespVOList && i.foodSPURespVOList.length) {
|
||||
i.foodSPURespVOList.forEach((j) => {
|
||||
j.productCount = 0;
|
||||
j.productId = j.id;
|
||||
});
|
||||
}
|
||||
});
|
||||
const shopList = [...state.shopList];
|
||||
if (state.carList && state.carList.length) {
|
||||
for (const i of shopList) {
|
||||
if (i && i.foodSPURespVOList && i.foodSPURespVOList.length) {
|
||||
for (const j of i.foodSPURespVOList) {
|
||||
for (const v of state.carList) {
|
||||
if (j.id == v.productId) {
|
||||
j.productCount = v.productCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
state.shopList = shopList;
|
||||
};
|
||||
|
||||
const doClassify = (i: any) => {
|
||||
state.currentClassifyIndex = i;
|
||||
getClassify();
|
||||
};
|
||||
|
||||
const getHeight = () => {
|
||||
const rpx = 480;
|
||||
return `calc(100vh - ${uni.upx2px(rpx)}px)`;
|
||||
};
|
||||
|
||||
// 点击添加到购物车
|
||||
const onClickAddToCar = (productData: any) => {
|
||||
showSkuDialog.value = true;
|
||||
curProductData.value = productData;
|
||||
};
|
||||
|
||||
// 加入到购物车时
|
||||
const onAddToCar = (cartGoodsInfo: any) => {
|
||||
showSkuDialog.value = false;
|
||||
console.log(cartGoodsInfo);
|
||||
};
|
||||
|
||||
// 显示购物车
|
||||
const doVisibleCar = async () => {
|
||||
showCarDialog.value = true;
|
||||
};
|
||||
|
||||
// 点击提交订单
|
||||
const doPay = async () => {
|
||||
uni.showModal({
|
||||
title: "提示",
|
||||
content: "是否确定购买",
|
||||
confirmColor: "#0094ff",
|
||||
success: async (res) => {
|
||||
if (!res.confirm) return;
|
||||
submitPay(); // 提交订单
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
// 提交订单
|
||||
const submitPay = async () => {
|
||||
// try {
|
||||
// if (isEmpty(state.carList)) {
|
||||
// uni.showToast({ title: "请至少购买一件商品", icon: "none" });
|
||||
// return;
|
||||
// }
|
||||
// uni.showLoading({ title: "支付中...", mask: false });
|
||||
// const _createtPa = { carParentId: state.carList[0].parentCarId };
|
||||
// const { data: createData, code: createCode }: any = await payApi.createHardwareOrder(_createtPa);
|
||||
// if (createCode != 0) throw new Error();
|
||||
// const _submitPa = { orderId: createData };
|
||||
// const { data: submitData, code: submitCode }: any = await payApi.submitHardwareOrder(_submitPa);
|
||||
// if (submitCode != 0) throw new Error();
|
||||
// uni.hideLoading();
|
||||
// uni.showToast({ title: "支付成功", icon: "none" });
|
||||
// router.jump("/pages/tabbar/order");
|
||||
// } catch (error) {
|
||||
// console.error(error);
|
||||
// uni.hideLoading();
|
||||
// }
|
||||
};
|
||||
// ======================================================
|
||||
|
||||
const skuState = reactive<any>({
|
||||
productId: null,
|
||||
showSpecDialog: false,
|
||||
skuData: [],
|
||||
totCount: 0,
|
||||
});
|
||||
|
||||
const chentProductCount = async (item: any) => {
|
||||
const target = state.carList.find((v) => v.productId == item.productId);
|
||||
const targetIndex = state.carList.findIndex((v) => v.productId == item.productId);
|
||||
if (target) {
|
||||
state.carList[targetIndex].productCount = item.productCount;
|
||||
} else {
|
||||
state.carList.push({ ...item, productId: item.id });
|
||||
}
|
||||
nextTick(() => updateShopCar());
|
||||
};
|
||||
|
||||
const doPhone = () => {
|
||||
if (isEmpty(state.detail.phone)) {
|
||||
uni.showToast({ title: "该店铺没有预留电话", icon: "none" });
|
||||
return;
|
||||
}
|
||||
hooks.useMakePhoneCall(state.detail.phone);
|
||||
};
|
||||
const doFood = () => {
|
||||
router.jump("/pages/merchant/food", { merchantId: state.detailId });
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
:deep() {
|
||||
.layout_main > scroll-view {
|
||||
|
||||
@@ -62,7 +62,6 @@ const getDetail = async () => {
|
||||
<view class="m-t-15rpx" v-html="state.detail.description"></view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="w-500rpx h-60rpx bg-#0094ff flex justify-center border-rd-8">加入购物车</view>
|
||||
</crud-layout>
|
||||
</template>
|
||||
|
||||
|
||||
+74
-53
@@ -2,71 +2,92 @@
|
||||
import { ref, reactive } from "vue";
|
||||
import { onLoad, onShow } from "@dcloudio/uni-app";
|
||||
|
||||
import { hooks, router } from "@@/index"
|
||||
import { merchantApi } from "@@/api"
|
||||
import { hooks, router } from "@@/index";
|
||||
import { merchantApi } from "@@/api";
|
||||
|
||||
import { filePath } from "@@/utils/file"
|
||||
import { filePath } from "@@/utils/file";
|
||||
|
||||
const state = reactive<any>({
|
||||
pa: {
|
||||
pagesize: 10,
|
||||
type: '1'
|
||||
}
|
||||
})
|
||||
|
||||
onLoad(() => {
|
||||
|
||||
pa: {
|
||||
pagesize: 10,
|
||||
type: "1",
|
||||
},
|
||||
});
|
||||
|
||||
onLoad(() => {});
|
||||
onShow(() => {
|
||||
if (pageRef.value) {
|
||||
pageRef.value.reload(false)
|
||||
}
|
||||
})
|
||||
if (pageRef.value) {
|
||||
pageRef.value.reload(false);
|
||||
}
|
||||
});
|
||||
|
||||
const pageRef = ref<any>(null)
|
||||
const pageHook = hooks.usePage(pageRef, merchantApi.page, null, 'data.records')
|
||||
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);
|
||||
}
|
||||
pageHook.startPage(page, pagesize, false, state.pa);
|
||||
};
|
||||
|
||||
const toDetail = async (v: any) => {
|
||||
const isLogin = await hooks.useCheckLogin();
|
||||
if (isLogin) {
|
||||
router.jump("/pages/merchant/detail", { id: v.id });
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
|
||||
<template>
|
||||
<crud-layout bg="/static/page/blue-bg.png">
|
||||
<z-paging ref="pageRef" height="100%" :fixed="false" v-model="pageHook.list" :default-page-size="10"
|
||||
safe-area-inset-bottom :loading-more-enabled="true" :show-scrollbar="false" @query="query"
|
||||
:auto-clean-list-when-reload="false" :auto-scroll-to-top-when-reload="false" @scroll="pageHook.scroll">
|
||||
<template #top>
|
||||
</template>
|
||||
<view class="flex-row card p-20rpx m-b-20rpx" v-for="(v, i) in pageHook.list" :key="i"
|
||||
@tap="router.jump('/pages/merchant/detail', { id: v.id })">
|
||||
<image class="w-160rpx h-160rpx 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>
|
||||
<view class="m-t-10rpx second-text-28">
|
||||
<text>营业时间</text>
|
||||
<text class="m-l-10rpx">
|
||||
{{ v.jobStartTime }}
|
||||
~
|
||||
{{ v.jobEndTime }}
|
||||
</text>
|
||||
</view>
|
||||
<view v-if="v.addressDes" class="m-t-10rpx second-text-28">
|
||||
<text>食堂地址</text>
|
||||
<text class="m-l-10rpx">{{ v.addressDes }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<crud-layout bg="/static/page/blue-bg.png">
|
||||
<z-paging
|
||||
ref="pageRef"
|
||||
height="100%"
|
||||
:fixed="false"
|
||||
v-model="pageHook.list"
|
||||
:default-page-size="10"
|
||||
safe-area-inset-bottom
|
||||
:loading-more-enabled="true"
|
||||
:show-scrollbar="false"
|
||||
@query="query"
|
||||
:auto-clean-list-when-reload="false"
|
||||
:auto-scroll-to-top-when-reload="false"
|
||||
@scroll="pageHook.scroll"
|
||||
>
|
||||
<template #top> </template>
|
||||
<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"
|
||||
/>
|
||||
<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>
|
||||
</z-paging>
|
||||
</crud-layout>
|
||||
<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>
|
||||
<view v-if="v.addressDes" class="m-t-10rpx second-text-28">
|
||||
<text>食堂地址</text>
|
||||
<text class="m-l-10rpx">{{ v.addressDes }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</z-paging>
|
||||
</crud-layout>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
+21
-13
@@ -10,10 +10,9 @@ const data = {
|
||||
serviceList: [
|
||||
{ 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_2.png', router: '/pages/user/diff-price' },
|
||||
{ text: "外来人员就餐", icon: "/static/icon/service_1.png", router: "/pages/apply/foreign-list" },
|
||||
{ text: "跨单位就餐", icon: "/static/icon/service_1.png", router: "/pages/apply/stride-list" },
|
||||
{ text: "人脸管理", icon: "/static/icon/service_5.png", router: "/pages/humanFace/list" },
|
||||
{ text: "人脸管理", icon: "/static/icon/service_5.png", router: "/pages/human-face/list" },
|
||||
{ text: "测试登录", icon: "/static/icon/login.png", router: "/pages/test/login" },
|
||||
],
|
||||
};
|
||||
@@ -56,6 +55,8 @@ const getUserInfo = () => {
|
||||
const userStorage = uni.getStorageSync(userInfoKey);
|
||||
if (!isEmpty(userStorage)) {
|
||||
state.userInfo = userStorage;
|
||||
console.log(state.userInfo,"state.userInfo");
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
@@ -98,7 +99,16 @@ const doLogin = async (loginType, token, accountId, sessionId) => {
|
||||
}
|
||||
};
|
||||
|
||||
const toService = async (v:any)=>{
|
||||
const isLogin = await hooks.useCheckLogin();
|
||||
if(isLogin){
|
||||
router.jump(v.router)
|
||||
}
|
||||
}
|
||||
|
||||
const doLogout = async () => {
|
||||
const isLogin = await hooks.useCheckLogin();
|
||||
if(!isLogin) return
|
||||
uni.showLoading({
|
||||
title: "退出登录中...",
|
||||
mask: true,
|
||||
@@ -116,14 +126,15 @@ const doLogout = async () => {
|
||||
<template>
|
||||
<crud-layout title="我的" bg="/static/page/blue-bg.png">
|
||||
<view class="flex-row items-center">
|
||||
<image class="w-100rpx h-100rpx rounded-full" v-if="state.userInfo.avatar" :src="state.userInfo.avatar" mode="aspectFill" />
|
||||
<image class="w-100rpx h-100rpx rounded-full" v-if="state.userInfo?.sysUser?.avatar" :src="state.userInfo.sysUser.avatar"
|
||||
mode="aspectFill" />
|
||||
<image class="w-100rpx h-100rpx rounded-full" v-else src="/static/icon/default-avatar.png" mode="aspectFill" />
|
||||
<view class="m-l-30rpx" v-if="state.userInfo.id">
|
||||
<view class="m-l-30rpx" v-if="state.userInfo?.sysUser?.userId">
|
||||
<view class="flex-row items-center">
|
||||
<text class="sub-text-30">{{ state.userInfo.nickname }}</text>
|
||||
<text class="sub-text-30">{{ state.userInfo?.sysUser?.name }}</text>
|
||||
<text class="iconfont icon-youjiantou color-#666666 m-l-20rpx"></text>
|
||||
</view>
|
||||
<text class="sub-text-26">ID {{ state.userInfo.id }}</text>
|
||||
<text class="sub-text-26">ID {{ state.userInfo?.sysUser?.userId }}</text>
|
||||
</view>
|
||||
<view v-else class="flex-row items-center m-l-30rpx" @tap="doLogin">
|
||||
<text class="sub-text-32">请先登录</text>
|
||||
@@ -132,12 +143,8 @@ const doLogout = async () => {
|
||||
</view>
|
||||
|
||||
<view class="m-t-40rpx rounded-20rpx shadow-main p-30rpx p-b-40rpx bg-white!">
|
||||
<view
|
||||
class="service_item flex-row items-center justify-between"
|
||||
v-for="(v, i) in data.serviceList"
|
||||
:key="i"
|
||||
@tap="router.jump(v.router)"
|
||||
>
|
||||
<view class="service_item flex-row items-center justify-between" v-for="(v, i) in data.serviceList" :key="i"
|
||||
@tap="toService(v)">
|
||||
<view class="flex-row-center">
|
||||
<image class="w-40rpx h-40rpx" :src="v.icon" mode="aspectFill" />
|
||||
<text class="sub-text-28 m-l-20rpx">{{ v.text }}</text>
|
||||
@@ -147,7 +154,8 @@ const doLogout = async () => {
|
||||
</view>
|
||||
|
||||
<view class="flex-col-center m-t-40rpx m-x-30rpx">
|
||||
<view class="w-full text-center sub-text-28 p-y-20rpx rounded-40rpx border-solid border border-#0094ff" @tap="doLogout">
|
||||
<view class="w-full text-center sub-text-28 p-y-20rpx rounded-40rpx border-solid border border-#0094ff"
|
||||
@tap="doLogout">
|
||||
退出登录
|
||||
</view>
|
||||
</view>
|
||||
|
||||
+174
-138
@@ -2,159 +2,195 @@
|
||||
import { ref, reactive } from "vue";
|
||||
import { onLoad, onShow } from "@dcloudio/uni-app";
|
||||
|
||||
import { hooks, router } from "@@/index"
|
||||
import { orderApi, payApi } from "@@/api"
|
||||
import { hooks, router } from "@@/index";
|
||||
import { orderApi, payApi } from "@@/api";
|
||||
|
||||
import zTabs from "@@/components/other/z-tabs/z-tabs.vue"
|
||||
import zTabs from "@@/components/other/z-tabs/z-tabs.vue";
|
||||
|
||||
const data = {
|
||||
tabs: [
|
||||
{ id: null, name: '全部', disabled: false },
|
||||
{ id: 1, name: '未支付', disabled: false },
|
||||
{ id: 5, name: '待核销', disabled: false },
|
||||
{ id: 10, name: '售后中', disabled: false },
|
||||
{ id: 15, name: '已核销', disabled: false },
|
||||
]
|
||||
}
|
||||
tabs: [
|
||||
{ id: null, name: "全部", disabled: false },
|
||||
{ id: 1, name: "未支付", disabled: false },
|
||||
{ id: 5, name: "待核销", disabled: false },
|
||||
{ id: 10, name: "售后中", disabled: false },
|
||||
{ id: 15, name: "已核销", disabled: false },
|
||||
],
|
||||
};
|
||||
const state = reactive<any>({
|
||||
pa: {
|
||||
orderStatus: data.tabs[0].id,
|
||||
},
|
||||
})
|
||||
|
||||
onLoad(() => {
|
||||
|
||||
pa: {
|
||||
orderStatus: data.tabs[0].id,
|
||||
},
|
||||
});
|
||||
onShow(() => {
|
||||
if (pageRef.value) {
|
||||
pageRef.value.reload(false)
|
||||
}
|
||||
})
|
||||
const doTab = (e: any) => {
|
||||
const target = data.tabs[e];
|
||||
state.pa.orderStatus = target.id
|
||||
pageRef.value.reload(true)
|
||||
}
|
||||
|
||||
const pageRef = ref<any>(null)
|
||||
const pageHook = hooks.usePage(pageRef, orderApi.page, null, 'data.list')
|
||||
onLoad(() => {});
|
||||
onShow(async () => {
|
||||
const isLogin = await hooks.useCheckLogin();
|
||||
if (!isLogin) return;
|
||||
if (pageRef.value) {
|
||||
pageRef.value.reload(false);
|
||||
}
|
||||
});
|
||||
const doTab = (e: any) => {
|
||||
const target = data.tabs[e];
|
||||
state.pa.orderStatus = target.id;
|
||||
pageRef.value.reload(true);
|
||||
};
|
||||
|
||||
const pageRef = ref<any>(null);
|
||||
const pageHook = hooks.usePage(pageRef, orderApi.page, null, "data.list");
|
||||
const query = (page: number, pagesize: number) => {
|
||||
pageHook.startPage(page, pagesize, false, state.pa);
|
||||
}
|
||||
const isLogin = hooks.useStaticCheckLogin();
|
||||
console.log(isLogin,"isLogin");
|
||||
|
||||
if (!isLogin) return;
|
||||
pageHook.startPage(page, pagesize, false, state.pa);
|
||||
};
|
||||
|
||||
const doToDetail = (v: any) => {
|
||||
router.jump("/pages/order/detail", { id: v.id })
|
||||
}
|
||||
router.jump("/pages/order/detail", { id: v.id });
|
||||
};
|
||||
|
||||
const doAppraise = () => {
|
||||
|
||||
}
|
||||
const doAppraise = () => {};
|
||||
|
||||
const doRefund = (v: any) => {
|
||||
router.jump("/pages/refund/apply", { id: v.id })
|
||||
return
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '是否确定退款',
|
||||
confirmColor: '#0094ff',
|
||||
success: async (res) => {
|
||||
if (!res.confirm) return
|
||||
try {
|
||||
uni.showLoading({ title: '退款中...', mask: true });
|
||||
const _pa = { id: v.id }
|
||||
const { data, code }: any = await payApi.refundHardwareOrder(_pa)
|
||||
if (code != 0) throw new Error()
|
||||
pageRef.value.reload(true)
|
||||
uni.hideLoading()
|
||||
uni.showToast({ title: '退款成功', icon: "none" });
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
uni.hideLoading()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
router.jump("/pages/refund/apply", { id: v.id });
|
||||
};
|
||||
</script>
|
||||
|
||||
|
||||
<template>
|
||||
<crud-layout title="订单" bg="/static/page/blue-bg.png">
|
||||
<z-paging ref="pageRef" height="100%" :fixed="false" v-model="pageHook.list" :default-page-size="5"
|
||||
safe-area-inset-bottom :loading-more-enabled="true" :show-scrollbar="false" @query="query"
|
||||
:auto-clean-list-when-reload="false" :auto-scroll-to-top-when-reload="false" @scroll="pageHook.scroll">
|
||||
<template #top>
|
||||
<view class="h-30rpx" />
|
||||
<view class="bg-white rounded-16rpx px-20rpx">
|
||||
<z-tabs :list="data.tabs" @change="doTab" />
|
||||
</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 pageHook.list"
|
||||
:key="i" @tap="doToDetail(v)">
|
||||
<view class="flex-row items-center">
|
||||
<image class="w-80rpx h-80rpx rounded-8rpx" :src="v.merchantLogo" 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.merchantStr }}</view>
|
||||
<view class="m-l-15rpx color-#999 font-size-26rpx! iconfont icon-youjiantou" />
|
||||
</view>
|
||||
<tm-tag v-if="v.orderStatus == 1" color="info" size="xs">未支付</tm-tag>
|
||||
<tm-tag v-if="v.orderStatus == 5" color="success" size="xs">待核销</tm-tag>
|
||||
<tm-tag v-if="v.orderStatus == 10" color="error" size="xs">售后中</tm-tag>
|
||||
<tm-tag v-if="v.orderStatus == 15" size="xs">已核销</tm-tag>
|
||||
</view>
|
||||
<view class="flex-row items-center justify-between m-t-5rpx">
|
||||
<view class="second-text-26">
|
||||
<text>下单时间</text>
|
||||
<text class="m-l-10rpx">
|
||||
{{ hooks.useTime(v.createTime, "{y}-{m}-{d} {h}:{i}:{s}") }}
|
||||
</text>
|
||||
</view>
|
||||
<view class="second-text-22">
|
||||
{{ hooks.useEnum('hardwareRefundStatusEnum', v.refundStatus) }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="relative h-180rpx m-t-20rpx">
|
||||
<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.shopCarList" :key="pI"
|
||||
@tap.stop="router.jump('/pages/merchant/product-detail', { id: pV.productId })">
|
||||
<image class="w-160rpx h-120rpx rounded-8rpx" :src="pV.productPic"
|
||||
mode="aspectFill" />
|
||||
<view class="w-160rpx m-t-10rpx sub-text-28 show-line">
|
||||
{{ pV.productName }}
|
||||
</view>
|
||||
</view>
|
||||
<view class="inline-flex! h-180rpx">
|
||||
<view class="w-160rpx h-full" />
|
||||
</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">¥ {{ hooks.useMoney(v.totalPrice) }}</view>
|
||||
<view class="m-t-10rpx second-text-26">共 {{ v.shopCarList.length }} 件</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 == 10" class="botder_btn" @tap.stop="doAppraise">评价</view>
|
||||
<view v-if="v.orderStatus == 5 && v.orderType == 2" class="botder_btn" @tap.stop="doRefund(v)">退款
|
||||
</view>
|
||||
<view v-if="v.orderStatus == 5 && v.orderType == 2" class="m-l-20rpx botder_btn"
|
||||
@tap.stop="hooks.usePreviewImage(v.orderTypeExtendReserve.qrCode)">
|
||||
核销码
|
||||
</view>
|
||||
</view>
|
||||
<crud-layout title="订单" bg="/static/page/blue-bg.png">
|
||||
<z-paging
|
||||
ref="pageRef"
|
||||
height="100%"
|
||||
:fixed="false"
|
||||
v-model="pageHook.list"
|
||||
:default-page-size="5"
|
||||
safe-area-inset-bottom
|
||||
:loading-more-enabled="true"
|
||||
:show-scrollbar="false"
|
||||
@query="query"
|
||||
:auto-clean-list-when-reload="false"
|
||||
:auto-scroll-to-top-when-reload="false"
|
||||
@scroll="pageHook.scroll"
|
||||
>
|
||||
<template #top>
|
||||
<view class="h-30rpx" />
|
||||
<view class="bg-white rounded-16rpx px-20rpx">
|
||||
<z-tabs :list="data.tabs" @change="doTab" />
|
||||
</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 pageHook.list"
|
||||
:key="i"
|
||||
@tap="doToDetail(v)"
|
||||
>
|
||||
<view class="flex-row items-center">
|
||||
<image
|
||||
class="w-80rpx h-80rpx rounded-8rpx"
|
||||
:src="v.merchantLogo"
|
||||
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.merchantStr }}</view>
|
||||
<view
|
||||
class="m-l-15rpx color-#999 font-size-26rpx! iconfont icon-youjiantou"
|
||||
/>
|
||||
</view>
|
||||
<tm-tag v-if="v.orderStatus == 1" color="info" size="xs"
|
||||
>未支付</tm-tag
|
||||
>
|
||||
<tm-tag v-if="v.orderStatus == 5" color="success" size="xs"
|
||||
>待核销</tm-tag
|
||||
>
|
||||
<tm-tag v-if="v.orderStatus == 10" color="error" size="xs"
|
||||
>售后中</tm-tag
|
||||
>
|
||||
<tm-tag v-if="v.orderStatus == 15" size="xs">已核销</tm-tag>
|
||||
</view>
|
||||
</z-paging>
|
||||
</crud-layout>
|
||||
<view class="flex-row items-center justify-between m-t-5rpx">
|
||||
<view class="second-text-26">
|
||||
<text>下单时间</text>
|
||||
<text class="m-l-10rpx">
|
||||
{{ hooks.useTime(v.createTime, "{y}-{m}-{d} {h}:{i}:{s}") }}
|
||||
</text>
|
||||
</view>
|
||||
<view class="second-text-22">
|
||||
{{ hooks.useEnum("hardwareRefundStatusEnum", v.refundStatus) }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="relative h-180rpx m-t-20rpx">
|
||||
<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.shopCarList"
|
||||
:key="pI"
|
||||
@tap.stop="
|
||||
router.jump('/pages/merchant/product-detail', {
|
||||
id: pV.productId,
|
||||
})
|
||||
"
|
||||
>
|
||||
<image
|
||||
class="w-160rpx h-120rpx rounded-8rpx"
|
||||
:src="pV.productPic"
|
||||
mode="aspectFill"
|
||||
/>
|
||||
<view class="w-160rpx m-t-10rpx sub-text-28 show-line">
|
||||
{{ pV.productName }}
|
||||
</view>
|
||||
</view>
|
||||
<view class="inline-flex! h-180rpx">
|
||||
<view class="w-160rpx h-full" />
|
||||
</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"
|
||||
>¥ {{ hooks.useMoney(v.totalPrice) }}</view
|
||||
>
|
||||
<view class="m-t-10rpx second-text-26"
|
||||
>共 {{ v.shopCarList.length }} 件</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 == 10"
|
||||
class="botder_btn"
|
||||
@tap.stop="doAppraise"
|
||||
>评价</view
|
||||
>
|
||||
<view
|
||||
v-if="v.orderStatus == 5 && v.orderType == 2"
|
||||
class="botder_btn"
|
||||
@tap.stop="doRefund(v)"
|
||||
>退款
|
||||
</view>
|
||||
<view
|
||||
v-if="v.orderStatus == 5 && v.orderType == 2"
|
||||
class="m-l-20rpx botder_btn"
|
||||
@tap.stop="hooks.usePreviewImage(v.orderTypeExtendReserve.qrCode)"
|
||||
>
|
||||
核销码
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</z-paging>
|
||||
</crud-layout>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
<style lang="scss" scoped></style>
|
||||
@@ -32,6 +32,7 @@ const doSubmit = async () => {
|
||||
if (!isPass) return;
|
||||
const tokenKey = constant.storageConstant.TOKEN;
|
||||
const userInfoKey = constant.storageConstant.USERINFO;
|
||||
uni.removeStorageSync(tokenKey)
|
||||
uni.showLoading({ title: "登录中...", mask: true });
|
||||
const res = await userApi.login({
|
||||
...applyForm,
|
||||
|
||||
+8
-17
@@ -3,7 +3,7 @@ import request from "@/sheep/utils/request";
|
||||
export default {
|
||||
foreignList: (params: any) =>
|
||||
request({
|
||||
url: "pay/foreign-ticket/get-all",
|
||||
url: "wallet/wallet-foreign/app/page-join",
|
||||
method: "GET",
|
||||
params,
|
||||
custom: {
|
||||
@@ -12,16 +12,16 @@ export default {
|
||||
}),
|
||||
foreignDetail: (params: any) =>
|
||||
request({
|
||||
url: "pay/foreign-ticket/get-detail",
|
||||
url: "wallet/wallet-foreign/app/detail",
|
||||
method: "GET",
|
||||
params,
|
||||
custom: {
|
||||
showLoading: false,
|
||||
},
|
||||
}),
|
||||
foreignItems: (params: any) =>
|
||||
codeList: (params: any) =>
|
||||
request({
|
||||
url: "pay/foreign-ticket/get-items",
|
||||
url: "wallet/wallet-code-use/app/code-list",
|
||||
method: "GET",
|
||||
params,
|
||||
custom: {
|
||||
@@ -30,7 +30,7 @@ export default {
|
||||
}),
|
||||
foreignApply: (data: any) =>
|
||||
request({
|
||||
url: "pay/foreign-ticket/apply",
|
||||
url: "wallet/wallet-foreign/app/apply",
|
||||
method: "POST",
|
||||
data,
|
||||
custom: {
|
||||
@@ -39,7 +39,7 @@ export default {
|
||||
}),
|
||||
strideList: (params: any) =>
|
||||
request({
|
||||
url: "pay/stride-dept/get-all",
|
||||
url: "wallet/wallet-stride/app/page-join",
|
||||
method: "GET",
|
||||
params,
|
||||
custom: {
|
||||
@@ -48,16 +48,7 @@ export default {
|
||||
}),
|
||||
strideDetail: (params: any) =>
|
||||
request({
|
||||
url: "pay/stride-dept/get-detail",
|
||||
method: "GET",
|
||||
params,
|
||||
custom: {
|
||||
showLoading: false,
|
||||
},
|
||||
}),
|
||||
strideItems: (params: any) =>
|
||||
request({
|
||||
url: "pay/stride-dept/get-items",
|
||||
url: "wallet/wallet-stride/app/detail",
|
||||
method: "GET",
|
||||
params,
|
||||
custom: {
|
||||
@@ -66,7 +57,7 @@ export default {
|
||||
}),
|
||||
strideApply: (data: any) =>
|
||||
request({
|
||||
url: "pay/stride-dept/apply",
|
||||
url: "wallet/wallet-stride/app/apply",
|
||||
method: "POST",
|
||||
data,
|
||||
custom: {
|
||||
|
||||
@@ -3,7 +3,7 @@ import request from "@/sheep/utils/request";
|
||||
export default {
|
||||
page: (params: any) =>
|
||||
request({
|
||||
url: "boxes/info/api/page",
|
||||
url: "canteen/boxesInfo/appPage",
|
||||
method: "GET",
|
||||
params,
|
||||
custom: {
|
||||
@@ -12,7 +12,7 @@ export default {
|
||||
}),
|
||||
detail: (params: any) =>
|
||||
request({
|
||||
url: "boxes/info/api/getInfo",
|
||||
url: "canteen/boxesInfo/getInfo",
|
||||
method: "GET",
|
||||
params,
|
||||
custom: {
|
||||
@@ -21,7 +21,7 @@ export default {
|
||||
}),
|
||||
apply: (data: any) =>
|
||||
request({
|
||||
url: "boxes/info/api/create",
|
||||
url: "canteen/boxesInfo/create",
|
||||
method: "POST",
|
||||
data,
|
||||
custom: {
|
||||
@@ -30,7 +30,7 @@ export default {
|
||||
}),
|
||||
cancel: (data: any) =>
|
||||
request({
|
||||
url: "boxes/info/api/cancel",
|
||||
url: "canteen/boxesInfo/cancel",
|
||||
method: "GET",
|
||||
data,
|
||||
custom: {
|
||||
@@ -39,7 +39,7 @@ export default {
|
||||
}),
|
||||
get: (data: any) =>
|
||||
request({
|
||||
url: "boxes/info/api/get",
|
||||
url: "canteen/boxesInfo/get",
|
||||
method: "GET",
|
||||
data,
|
||||
custom: {
|
||||
@@ -48,7 +48,7 @@ export default {
|
||||
}),
|
||||
MyBookingPage: (data: any) =>
|
||||
request({
|
||||
url: "boxes/info/api/getMyBookingPage",
|
||||
url: "canteen/boxesInfo/getMyBookingPage",
|
||||
method: "GET",
|
||||
data,
|
||||
custom: {
|
||||
|
||||
@@ -3,7 +3,7 @@ import request from "@/sheep/utils/request";
|
||||
export default {
|
||||
page: (params: any) =>
|
||||
request({
|
||||
url: `/sys/user/face-page-join`,
|
||||
url: `/admin/user-face/app/page-join`,
|
||||
method: "GET",
|
||||
params,
|
||||
custom: {
|
||||
@@ -12,7 +12,7 @@ export default {
|
||||
}),
|
||||
del: (params: any) =>
|
||||
request({
|
||||
url: `/sys/user/face-delete`,
|
||||
url: `/admin/user-face/app`,
|
||||
method: "DELETE",
|
||||
params,
|
||||
custom: {
|
||||
@@ -21,7 +21,7 @@ export default {
|
||||
}),
|
||||
create: (data: any) =>
|
||||
request({
|
||||
url: `/sys/user/face-create`,
|
||||
url: `/admin/user-face/app`,
|
||||
method: "POST",
|
||||
data,
|
||||
custom: {
|
||||
@@ -30,7 +30,7 @@ export default {
|
||||
}),
|
||||
get: (params: any) =>
|
||||
request({
|
||||
url: `/sys/user/face-get`,
|
||||
url: `/admin/user-face/app/detail`,
|
||||
method: "GET",
|
||||
params,
|
||||
custom: {
|
||||
@@ -39,7 +39,7 @@ export default {
|
||||
}),
|
||||
put: (data: any) =>
|
||||
request({
|
||||
url: `/sys/user/face-update`,
|
||||
url: `/admin/user-face/app`,
|
||||
method: "PUT",
|
||||
data,
|
||||
custom: {
|
||||
|
||||
@@ -3,7 +3,7 @@ import request from "@/sheep/utils/request";
|
||||
export default {
|
||||
page: (params: any) =>
|
||||
request({
|
||||
url: `/food/api/page`,
|
||||
url: `/canteen/canteenDailyMenu/ad/getCanteenList`,
|
||||
method: "GET",
|
||||
params,
|
||||
custom: {
|
||||
@@ -12,7 +12,7 @@ export default {
|
||||
}),
|
||||
classify: (params: any) =>
|
||||
request({
|
||||
url: `/onlinefood/category/listFood`,
|
||||
url: `/canteen/canteenOnlineCategory/app/getAllSimple`,
|
||||
method: "GET",
|
||||
params,
|
||||
custom: {
|
||||
@@ -30,7 +30,7 @@ export default {
|
||||
}),
|
||||
getShopCar: (params: any) =>
|
||||
request({
|
||||
url: `/hardware/car/get`,
|
||||
url: `/hard/hard-car/app/mch-detail`,
|
||||
method: "GET",
|
||||
params,
|
||||
custom: {
|
||||
@@ -39,7 +39,7 @@ export default {
|
||||
}),
|
||||
updateShopCar: (data: any) =>
|
||||
request({
|
||||
url: `/hardware/car/save-or-upload`,
|
||||
url: `/hard/car/save-or-upload`,
|
||||
method: "POST",
|
||||
data,
|
||||
custom: {
|
||||
|
||||
@@ -21,3 +21,5 @@ export { default as userApi } from "./user";
|
||||
export { default as walletApi } from "./wallet";
|
||||
|
||||
export { default as faceApi } from "./face";
|
||||
|
||||
export { default as shopApi } from "./shop";
|
||||
@@ -0,0 +1,49 @@
|
||||
import request from "@/sheep/utils/request";
|
||||
|
||||
export default {
|
||||
getSupermarketSpuList: (data: any) =>
|
||||
request({
|
||||
url: `/supermarket/supermarketSpu/ad/updateSpuStock`,
|
||||
method: "POST",
|
||||
data,
|
||||
custom: {
|
||||
showLoading: false,
|
||||
},
|
||||
}),
|
||||
// del: (params: any) =>
|
||||
// request({
|
||||
// url: `/sys/user/face-delete`,
|
||||
// method: "DELETE",
|
||||
// params,
|
||||
// custom: {
|
||||
// showLoading: false,
|
||||
// },
|
||||
// }),
|
||||
// create: (data: any) =>
|
||||
// request({
|
||||
// url: `/sys/user/face-create`,
|
||||
// method: "POST",
|
||||
// data,
|
||||
// custom: {
|
||||
// showLoading: false,
|
||||
// },
|
||||
// }),
|
||||
// get: (params: any) =>
|
||||
// request({
|
||||
// url: `/sys/user/face-get`,
|
||||
// method: "GET",
|
||||
// params,
|
||||
// custom: {
|
||||
// showLoading: false,
|
||||
// },
|
||||
// }),
|
||||
// put: (data: any) =>
|
||||
// request({
|
||||
// url: `/sys/user/face-update`,
|
||||
// method: "PUT",
|
||||
// data,
|
||||
// custom: {
|
||||
// showLoading: false,
|
||||
// },
|
||||
// }),
|
||||
};
|
||||
@@ -7,7 +7,7 @@ const basicAuth =
|
||||
export default {
|
||||
userInfo: () =>
|
||||
request({
|
||||
url: "/sys/user/get",
|
||||
url: "/admin/user/info",
|
||||
method: "GET",
|
||||
custom: {
|
||||
showLoading: false,
|
||||
@@ -51,13 +51,13 @@ export default {
|
||||
method: "POST",
|
||||
params: {
|
||||
username,
|
||||
password: encPassword,
|
||||
password: password,
|
||||
randomStr,
|
||||
code,
|
||||
grant_type,
|
||||
scope,
|
||||
},
|
||||
data: { password: encPassword },
|
||||
data: { password: password },
|
||||
header: {
|
||||
skipToken: true,
|
||||
Authorization: basicAuth,
|
||||
|
||||
@@ -1,330 +1,382 @@
|
||||
<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) {
|
||||
// if (newValue.length <= this.curIndex) return 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 .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>
|
||||
@@ -9,3 +9,5 @@ export * from "./use-page";
|
||||
export * from "./use-phone";
|
||||
|
||||
export * from "./use-unit";
|
||||
|
||||
export * from "./use-token";
|
||||
@@ -1,6 +1,11 @@
|
||||
import { filePath } from "../utils/file";
|
||||
|
||||
export const usePreviewImage = (str: string | undefined) => {
|
||||
console.log(str, "str");
|
||||
|
||||
if (str == undefined) return;
|
||||
let urlList = str.split(",");
|
||||
let urlList = str.split(",").map((v) => filePath(v));
|
||||
console.log(urlList);
|
||||
uni.previewImage({
|
||||
urls: urlList,
|
||||
});
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
import storageConstant from "../constant/storage-constant";
|
||||
import { jump } from "../router/index";
|
||||
|
||||
export const useToken = () => {
|
||||
const tokenKey = storageConstant.TOKEN;
|
||||
const tokenStorage = uni.getStorageSync(tokenKey);
|
||||
if (!tokenStorage.access_token) return "";
|
||||
return `Bearer ${tokenStorage.access_token}`;
|
||||
};
|
||||
|
||||
export const useDefaultHeader = () => {
|
||||
const token = useToken();
|
||||
return {
|
||||
"TENANT-ID": "1",
|
||||
"CLIENT-TOC": "Y",
|
||||
Authorization: token,
|
||||
};
|
||||
};
|
||||
|
||||
export const useStaticCheckLogin = () => {
|
||||
const tokenKey = storageConstant.TOKEN;
|
||||
const tokenStorage = uni.getStorageSync(tokenKey);
|
||||
if (tokenStorage) return true;
|
||||
return false;
|
||||
};
|
||||
|
||||
export const useCheckLogin = async (): Promise<boolean> => {
|
||||
const tokenKey = storageConstant.TOKEN;
|
||||
const tokenStorage = uni.getStorageSync(tokenKey);
|
||||
if (tokenStorage) return true;
|
||||
uni.showModal({
|
||||
title: "提示",
|
||||
content: "您还未登录,请先登录",
|
||||
confirmColor: "#0094ff",
|
||||
cancelText: "取消",
|
||||
confirmText: "去登录",
|
||||
success: async (res) => {
|
||||
if (res.confirm) {
|
||||
jump("/pages/test/login", {}, 3);
|
||||
return;
|
||||
}
|
||||
if (!res.confirm) {
|
||||
return;
|
||||
}
|
||||
return;
|
||||
},
|
||||
});
|
||||
return false;
|
||||
};
|
||||
@@ -154,15 +154,15 @@ http.interceptors.response.use(
|
||||
return Promise.resolve(response.data);
|
||||
},
|
||||
(error) => {
|
||||
let errorMessage = "";
|
||||
console.log(error);
|
||||
|
||||
let errorMessage = error.data.msg;
|
||||
if (error !== undefined) {
|
||||
if (errorMessage) {
|
||||
uni.showToast({
|
||||
title: errorMessage || "",
|
||||
icon: "none",
|
||||
mask: true,
|
||||
});
|
||||
}
|
||||
uni.showToast({
|
||||
title: errorMessage || "",
|
||||
icon: "none",
|
||||
mask: true,
|
||||
});
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.0 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.0 KiB |
+2
-9
@@ -5,17 +5,10 @@ import uni from "@dcloudio/vite-plugin-uni";
|
||||
import Unocss from "unocss/vite";
|
||||
|
||||
import { useRouter } from "./src/sheep";
|
||||
import { filePath } from "./src/sheep/utils/file-path";
|
||||
|
||||
export default defineConfig(({ mode }) => {
|
||||
const {
|
||||
NODE_ENV,
|
||||
VITE_APP_DEV_SERVICE,
|
||||
VITE_APP_PROD_SERVICE,
|
||||
VITE_IMAGE_BASE_PATH,
|
||||
} = loadEnv(mode, process.cwd(), "");
|
||||
const baseUrl =
|
||||
NODE_ENV == "development" ? VITE_APP_DEV_SERVICE : VITE_APP_PROD_SERVICE;
|
||||
const { NODE_ENV, VITE_APP_DEV_SERVICE, VITE_APP_PROD_SERVICE, VITE_IMAGE_BASE_PATH } = loadEnv(mode, process.cwd(), "");
|
||||
const baseUrl = NODE_ENV == "development" ? VITE_APP_DEV_SERVICE : VITE_APP_PROD_SERVICE;
|
||||
return {
|
||||
build: {
|
||||
target: "es6",
|
||||
|
||||
Reference in new issue
Block a user