This commit is contained in:
ctw committed 2025-01-08 09:26:31 +08:00
commit 0488f13df3
14 files changed
+1082 -853

No files matched your search

+8 -3
View File
@@ -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.processStatus != 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">
+3 -3
View File
@@ -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" />
+5 -1
View File
@@ -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.processStatus != 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">
+1 -1
View File
@@ -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);
}
+392 -324
View File
@@ -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>
+2 -2
View File
@@ -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)
}
+74 -53
View File
@@ -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>
+16 -5
View File
@@ -55,6 +55,8 @@ const getUserInfo = () => {
const userStorage = uni.getStorageSync(userInfoKey);
if (!isEmpty(userStorage)) {
state.userInfo = userStorage;
console.log(state.userInfo,"state.userInfo");
}
};
@@ -97,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,
@@ -115,15 +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"
<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>
@@ -133,7 +144,7 @@ const doLogout = async () => {
<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)">
@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>
+174 -138
View File
@@ -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>
+6 -6
View File
@@ -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: {
+4 -4
View File
@@ -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: {
+1 -1
View File
@@ -7,7 +7,7 @@ const basicAuth =
export default {
userInfo: () =>
request({
url: "/sys/user/get",
url: "/admin/user/info",
method: "GET",
custom: {
showLoading: false,
@@ -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>
+32
View File
@@ -1,4 +1,5 @@
import storageConstant from "../constant/storage-constant";
import { jump } from "../router/index";
export const useToken = () => {
const tokenKey = storageConstant.TOKEN;
@@ -15,3 +16,34 @@ export const useDefaultHeader = () => {
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;
};