Compare commits

...

3 Commits

Author SHA1 Message Date
weipengfei 995017dff0 新增预约取货功能 2024-07-10 17:18:47 +08:00
weipengfei bd7886dd3b 调整价格显示 2024-07-10 17:18:15 +08:00
weipengfei df365d0692 更新 2024-07-09 17:56:26 +08:00
8 changed files with 756 additions and 15 deletions

View File

@ -121,6 +121,13 @@ export function saleOrderListApi(data) {
return request.get(`/store_order/StoreOrder/lists`, { params: data }) return request.get(`/store_order/StoreOrder/lists`, { params: data })
} }
/**
* @description 预约订单列表
*/
export function userProductStorageListApi(data) {
return request.get(`/user_product_storage_log/UserProductStorageLog/lists`, { params: data })
}
/** /**
* @description 采购订单提交 * @description 采购订单提交
*/ */

View File

@ -65,6 +65,12 @@ const list = ref([
ico: "DataAnalysis", ico: "DataAnalysis",
count: 0, count: 0,
}, },
{
name: "subOrder",
title: "预约取货",
ico: "Clock",
count: 0,
},
{ {
name: "convert", name: "convert",
title: "订单核销", title: "订单核销",

View File

@ -30,10 +30,16 @@ const routes = [
component: () => import('@/views/order/index.vue'), component: () => import('@/views/order/index.vue'),
}, },
{ {
path: '/orderCount', path: '/subOrder',
name: 'orderCount', name: 'subOrder',
meta: { title: '订单统计' }, meta: { title: '订单统计' },
component: () => import('@/views/saleOrder/indexCount.vue'), component: () => import('@/views/subOrder/index.vue'),
},
{
path: '/order',
name: 'order',
meta: { title: '预约取货' },
component: () => import('@/views/order/index.vue'),
}, },
{ {
path: '/wallet', path: '/wallet',

View File

@ -66,8 +66,8 @@ const close = () => {
<div class="shop-info-right"> <div class="shop-info-right">
<div class="shop-info-right-top">{{ form.store_name }}</div> <div class="shop-info-right-top">{{ form.store_name }}</div>
<div> <div>
<!-- <div class="shop-info-right-price" v-if="priceKey.off_activity == 1"> <div class="shop-info-right-price" v-if="priceKey.off_activity == 1">
<span class="unit-name">活动:</span> ¥<span>{{ form[priceKey.price] }}</span> <span class="unit-name">商户:</span> ¥<span>{{ form[priceKey.price] }}</span>
<span class="unit-name" v-if="form.unit_name">/{{ form.unit_name }}</span> <span class="unit-name" v-if="form.unit_name">/{{ form.unit_name }}</span>
</div> </div>
<div class="shop-info-right-price" v-if="priceKey.off_activity == 1"> <div class="shop-info-right-price" v-if="priceKey.off_activity == 1">
@ -76,13 +76,13 @@ const close = () => {
/{{ form.unit_name }}</span> /{{ form.unit_name }}</span>
</div> </div>
<div class="shop-info-right-price" v-else> <div class="shop-info-right-price" v-else>
¥<span>{{ form[priceKey.op_price] }}</span>
<span class="unit-name">/{{ form.unit_name }}</span>
</div> -->
<div class="shop-info-right-price">
¥<span>{{ form[priceKey.price] }}</span> ¥<span>{{ form[priceKey.price] }}</span>
<span class="unit-name">/{{ form.unit_name }}</span> <span class="unit-name">/{{ form.unit_name }}</span>
</div> </div>
<!-- <div class="shop-info-right-price">
¥<span>{{ form[priceKey.price] }}</span>
<span class="unit-name">/{{ form.unit_name }}</span>
</div> -->
</div> </div>
</div> </div>
</div> </div>

View File

@ -107,8 +107,8 @@ onUnmounted(() => {
<div class="shop-item" v-for="(item, index) in storeList" :key="index" @click="changeItem(item)"> <div class="shop-item" v-for="(item, index) in storeList" :key="index" @click="changeItem(item)">
<el-image loading="lazy" :src="item.image"></el-image> <el-image loading="lazy" :src="item.image"></el-image>
<div class="shop-name">{{ item.store_name }}</div> <div class="shop-name">{{ item.store_name }}</div>
<!-- <div class="shop-price" v-if="priceKey.off_activity == 1"> <div class="shop-price" v-if="priceKey.off_activity == 1">
<span class="unit-name">活动:</span> ¥<span>{{ item[priceKey.price] }}</span> <span class="unit-name">商户:</span> ¥<span>{{ item[priceKey.price] }}</span>
<span class="unit-name" v-if="item.unit_name">/{{ item.unit_name }}</span> <span class="unit-name" v-if="item.unit_name">/{{ item.unit_name }}</span>
</div> </div>
<div class="shop-price" v-if="priceKey.off_activity == 1"> <div class="shop-price" v-if="priceKey.off_activity == 1">
@ -116,13 +116,13 @@ onUnmounted(() => {
/{{ item.unit_name }}</span> /{{ item.unit_name }}</span>
</div> </div>
<div class="shop-price" v-else> <div class="shop-price" v-else>
¥<span>{{ item[priceKey.op_price] }}</span>
<span class="unit-name">/{{ item.unit_name }}</span>
</div> -->
<div class="shop-price">
¥<span>{{ item[priceKey.price] }}</span> ¥<span>{{ item[priceKey.price] }}</span>
<span class="unit-name">/{{ item.unit_name }}</span> <span class="unit-name">/{{ item.unit_name }}</span>
</div> </div>
<!-- <div class="shop-price">
¥<span>{{ item[priceKey.price] }}</span>
<span class="unit-name">/{{ item.unit_name }}</span>
</div> -->
<div class="no-stock-re" v-if="item.stock <= 0"> <div class="no-stock-re" v-if="item.stock <= 0">
<div> <div>
<span>次日提</span> <span>次日提</span>

View File

@ -0,0 +1,316 @@
<script setup>
import { onMounted, onUnmounted, ref } from "vue";
import {
orderListApi,
orderStatusApi,
orderLadingApi,
cartListApi,
cashierinfoListApi,
cashierinfoDetailsApi
} from "@/api/store.js";
import { useUserStore } from "@/store/user.js";
import { ElMessage } from "element-plus";
import { useRouter } from "vue-router";
import mitt from "@/utils/mitt.js";
import pay from "@/components/pay.vue";
const userStore = useUserStore();
const router = useRouter();
const formData = ref({
id: "",
});
const list = ref([]);
const payRef = ref(null);
const loading = ref(false);
const total = ref(0);
const activeStore = ref(0);
const activeStoreList = ref(["商品信息", "订单详情"]);
const orderLadingSn = ref("");
const dialogVisible = ref(false);
const orderLadingComfirm = (order_sn) => {
orderLadingSn.value = order_sn;
dialogVisible.value = true;
};
const orderLading = () => {
dialogVisible.value = false;
orderLadingApi({
order_sn: orderLadingSn.value,
staff_id: userStore.userInfo.service.service_id,
}).then((res) => {
ElMessage({
message: res.message,
type: "success",
});
router.push({
name: "home",
});
});
};
const rePay = () => {
payRef.value.setForm({
isRePay: true,
data: formData.value
});
payRef.value.drawer = true;
};
const getOrderStatus = (id) => {
orderStatusApi({
order_sn: id,
})
.then((res) => {
if (res.data.paid == 1 || res.message == "支付成功") {
ElMessage({
message: res.message,
type: "success",
});
mitt.emit("update-sale-order-detail", {});
formData.value.paid = 1;
} else {
ElMessage({
message: res.message,
type: "error",
});
}
})
.catch((err) => { });
};
const where = ref({
page_no: 1,
page_size: 15,
loadend: false,
loading: false,
});
const goods_list = ref([]);
const getOrderList = () => {
return console.log("触底");
if (formData.value.id && !where.value.loadend) {
console.log("加载");
where.value.loading = true;
cashierinfoListApi({
pid: formData.value.id,
page_no: where.value.page_no,
page_size: where.value.page_size,
}).then((res) => {
goods_list.value = [...goods_list.value, ...res.data.lists];
if (res.data.lists.length < where.value.page_size)
where.value.loadend = true;
where.value.loading = false;
where.value.page_no++;
});
}
};
const getDetail = () => {
loading.value = true;
cashierinfoDetailsApi({
id: formData.value.oid,
}).then(res => {
formData.value = res.data;
setTimeout(() => {
loading.value = false;
}, 200)
})
}
const emit = defineEmits(['rePaySuccess'])
const paySuccess = (data = null) => {
// data = {
// out_trade_no: "PF171568087790938356", //
// create_time: "2024-05-14 17:59:05", //
// trade_type: "MICROPAY", //
// transaction_id: "4200002159202405159003084211", //
// }
// if(data) onPrint(data);
setTimeout(()=>{
emit('rePaySuccess');
})
};
onMounted(() => {
mitt.on("set-sale-order-detail", (res) => {
console.log("===", res);
formData.value = res;
where.value.page_no = 1;
where.value.loadend = false;
where.value.loading = false;
goods_list.value = [];
getDetail();
// getOrderList();
});
});
onUnmounted(() => {
mitt.off("set-sale-order-detail");
});
</script>
<template>
<div class="my-order">
<div class="detail" v-if="formData.id" v-loading="loading">
<div class="table" v-infinite-scroll="getOrderList" :infinite-scroll-distance="300"
:infinite-scroll-delay="300" style="overflow: auto" :infinite-scroll-immediate="false">
<div class="table-title">订单信息</div>
<div class="table-info">
<div class="info-item">
<div class="info-item-title">订单编号:</div>
<div class="info-item-info">{{ formData.order_id }}</div>
</div>
<div class="info-item">
<div class="info-item-title">商品款数:</div>
<div class="info-item-info">{{ formData.total_num || 0 }}</div>
</div>
<div class="info-item">
<div class="info-item-title">商品总价:</div>
<!-- <div class="info-item-info">¥{{ formData.total_price }}</div> -->
<div class="info-item-info">¥{{ formData.pay_price }}</div>
</div>
<div class="info-item">
<div class="info-item-title">创建时间:</div>
<div class="info-item-info">{{ formData.pay_time }}</div>
</div>
<div class="info-item">
<div class="info-item-title">优惠抵扣:</div>
<div class="info-item-info">¥{{ formData.deduction_price }}</div>
</div>
<div class="info-item">
<div class="info-item-title">实际支付:</div>
<div class="info-item-info">¥{{ formData.pay_price }}</div>
</div>
<div class="info-item">
<div class="info-item-title">支付时间:</div>
<div class="info-item-info">{{ formData.pay_time }}</div>
</div>
<div class="info-item">
<div class="info-item-title">支付方式:</div>
<div class="info-item-info">
<span v-if="formData.pay_type_name">{{ formData.pay_type_name }}</span>
<span v-else-if="formData.pay_type == 9">微信收款</span>
<span v-else-if="formData.pay_type == 17">现金支付</span>
<span v-else-if="formData.pay_type == 13">支付宝收款</span>
<span v-else-if="formData.pay_type == 3">余额支付</span>
<span v-else-if="formData.pay_type == 1">微信支付</span>
</div>
</div>
</div>
<div class="table-title" v-if="formData.uid">用户信息</div>
<div class="table-info" v-if="formData.uid">
<div class="info-item">
<div class="info-item-title">用户ID:</div>
<div class="info-item-info">{{ formData.uid }}</div>
</div>
<div class="info-item">
<div class="info-item-title">用户昵称:</div>
<div class="info-item-info">{{ formData.nickname }}</div>
</div>
<div class="info-item">
<div class="info-item-title">用户电话:</div>
<div class="info-item-info">{{ formData.mobile }}</div>
</div>
</div>
<div style="font-size: 0.9rem">
共计
<span style="color: #ff4a00">{{ formData.product?.length || " " }}</span> 款商品
</div>
<el-table :data="formData.product">
<el-table-column label="商品信息">
<template #default="{ row }">
<div style="display: flex; align-items: center">
<el-image style="height: 3rem; width: 3rem;flex-shrink: 0;" :src="row.cart_info?.image"></el-image>
<span style="margin-left: 0.5rem">{{ row.cart_info?.name }}</span>
</div>
</template>
</el-table-column>
<el-table-column prop="cart_info.price" label="单价" width="150" />
<el-table-column prop="cart_info.cart_num" label="数量" width="150" />
<el-table-column prop="cart_info.pay_price" label="总价" width="150">
</el-table-column>
</el-table>
<div style="height: 8rem;"></div>
</div>
<div class="footer" v-if="!formData.paid">
<el-button type="primary" size="large" @click="rePay">重新支付</el-button>
</div>
</div>
<div v-else>
<el-empty></el-empty>
</div>
<pay ref="payRef" @paySuccess="paySuccess" />
</div>
</template>
<style scoped lang="scss">
.my-order {
border-radius: 1.2rem;
height: 100%;
flex: 1;
background-color: #fff;
position: relative;
overflow: hidden;
.detail {
height: 100%;
box-sizing: border-box;
position: relative;
.table {
padding: 1rem;
overflow-y: auto;
height: 100%;
.table-title {
font-weight: bold;
}
.table-info {
display: flex;
flex-wrap: wrap;
color: #777;
font-size: 0.9rem;
padding-bottom: 1rem;
margin-bottom: 1rem;
border-bottom: 1px solid #eee;
&:last-child {
border-bottom: none;
}
.info-item {
width: 33%;
display: flex;
padding-top: 1rem;
.info-item-title {
flex-shrink: 0;
padding-right: 1rem;
}
}
}
}
.footer {
position: absolute;
bottom: 0;
left: 0;
z-index: 1;
width: 100%;
height: 6rem;
box-sizing: border-box;
background-color: #fff;
display: flex;
justify-content: flex-end;
align-items: center;
padding: 0 2rem;
border-top: 1px solid #eee;
}
}
}
</style>

View File

@ -0,0 +1,360 @@
<script setup>
import { ref, onMounted, onUnmounted } from "vue";
import {
orderListApi,
orderStatusApi,
orderLadingApi,
cartListApi,
userProductStorageListApi,
} from "@/api/store.js";
import { useUserStore } from "@/store/user.js";
import { ElMessage } from "element-plus";
import { useRouter } from "vue-router";
import mitt from "@/utils/mitt.js";
import moment from "moment";
const userStore = useUserStore();
const props = defineProps({
isSystem: {
type: Boolean,
default: false,
},
source: {
type: Number,
default: 1,
},
});
const lists = ref([]);
const tabPosition = ref(1); // 1-, 2-
const changeTabPosition = (e) => {
where.value.page_no = 1;
loadEnd.value = false;
loading.value = false;
orderList.value = [];
getOrderList(true);
};
const payRef = ref(null);
const date = ref("");
const changeDate = () => {
where.value.start_time = moment(date.value[0]).format('YYYY-MM-DD 00:00:00');
where.value.end_time = moment(date.value[1]).format('YYYY-MM-DD 23:59:59');
getOrderList(true);
};
const disabledDate = (time) => {
return time.getTime() > Date.now();
}
const where = ref({
page_no: 1,
page_size: 20,
order_id: "",
start_time: "",
end_time: "",
});
const loading = ref(false);
const total = ref(0);
const activeStore = ref(0);
const loadEnd = ref(false);
const orderList = ref([]);
const getOrderList = (reload = false) => {
if (reload) where.value.page_no = 1;
else if (loadEnd.value || loading.value) return;
loading.value = true;
if (tabPosition.value == 1) where.value.paid = null;
if (tabPosition.value == 2) where.value.paid = 0;
userProductStorageListApi(where.value)
.then((res) => {
if (reload) orderList.value = res.data.lists;
else orderList.value = [...orderList.value, ...res.data.lists];
if (where.value.page_no == 1 && orderList.value.length > 0) mitt.emit("set-sale-order-detail", orderList.value[0]);
if (res.data.lists.length < where.value.page_size) loadEnd.value = true;
else where.value.page_no++;
activeStore.value = 0;
console.log(where.value.page_no);
total.value = res.data.count;
loading.value = false;
})
.catch((err) => {
loadEnd.value = true;
loading.value = false;
});
};
const setForm = (item, index) => {
activeStore.value = index;
mitt.emit("set-sale-order-detail", item);
};
defineExpose({
getOrderList
})
onMounted(() => {
mitt.on("update-sale-order-detail", (item) => {
console.log("===");
orderList.value[activeStore.value].paid = 1;
});
});
onUnmounted(() => {
mitt.off("update-sale-order-detail");
})
</script>
<template>
<div class="my-order">
<div class="header-nav">
<div class="nav-item">
{{ "收银订单" }}
</div>
<div class="nav-item-btn">
<el-radio-group v-model="tabPosition" @change="changeTabPosition" size="small">
<el-radio-button :value="1">全部</el-radio-button>
<el-radio-button :value="2">未支付</el-radio-button>
</el-radio-group>
<el-date-picker v-model="date" type="daterange" start-placeholder="开始时间" end-placeholder="结束时间"
size="small" value-format="YYYY/MM/DD" :disabled-date="disabledDate" @change="changeDate"
:clearable="false" style="width: 14rem; margin-left: 1rem" />
</div>
</div>
<div class="header-input">
<el-input v-model="where.order_id" placeholder="请输入订单编号" @keydown.enter="getOrderList(true)"
@clear="getOrderList(true)">
<template #suffix>
<el-icon v-if="where.order_id != ''" size="18" @click="where.order_id = '';getOrderList(true)" style="cursor: pointer;margin-right: 0.5rem;">
<CircleClose />
</el-icon>
</template>
<template #append>
<el-button type="primary" style="
background-color: #1890ff;
color: #fff;
border-radius: 0 0.315rem 0.315rem 0;
" @click="getOrderList(true)">搜索</el-button>
</template>
</el-input>
</div>
<div class="order-lists" v-loading="loading" v-infinite-scroll="getOrderList" :infinite-scroll-distance="300"
:infinite-scroll-delay="500" style="overflow: auto">
<div class="item" :class="{ 'item-active': activeStore == index }" v-for="(item, index) in orderList"
:key="index" @click="setForm(item, index)">
<div class="top">
<div class="sn" :class="'cahier'">单号: {{ item.order_id }}</div>
<div class="create-time">{{ item.update_time }}</div>
</div>
<div class="shop">
<!-- <div class="left" v-if="item.product_info">
<el-image v-for="(shop, imgkey) in item.product_info.slice(0, 5)" :key="imgkey"
:src="shop.image" class="shop-img"></el-image>
<div v-if="item.product_info.length == 1" class="shop-name">
{{ item.product_info[0].store_name }}
</div>
</div> -->
<div class="left" >
<el-image
:src="item.store_name_img" class="shop-img"></el-image>
<div class="shop-name">
{{ item.store_name }}
<br />
<span style=" display: block; font-size: 0.8rem; color: #777;">{{ item.store_info }}</span>
</div>
</div>
<div class="right">
<div class="money">¥{{ item.price }}</div>
<div class="count">{{ item.nums }}款商品</div>
</div>
</div>
<div class="bottom">
<div class="pay">
<div v-if="item.paid">
{{ item.paid_name }}
<spna v-if="item.pay_type_name">({{ item.pay_type_name }})</spna>
<span v-else-if="item.pay_type == 9">(微信收款)</span>
<span v-else-if="item.pay_type == 17">(现金支付)</span>
<span v-else-if="item.pay_type == 13">(支付宝收款)</span>
<span v-else-if="item.pay_type == 3">(余额支付)</span>
<span v-else-if="item.pay_type == 1">(微信支付)</span>
</div>
<div v-else style="color: #ff4a00">{{ item.paid_name }}</div>
</div>
<!-- <div class="cashier" v-if="item.service_info">
收银员: {{ item.service_info.nickname }}
</div>
<div class="cashier" v-else>平台订单</div> -->
</div>
</div>
<div v-if="loadEnd" class="load-end">没有更多了</div>
<div v-if="loading" class="load-end">加载中...</div>
</div>
</div>
</template>
<style scoped lang="scss">
.my-order {
border-radius: 1.2rem;
height: 100%;
background-color: #fff;
width: 30rem;
position: relative;
overflow: hidden;
.header-nav {
display: flex;
flex-direction: column;
justify-content: space-between;
padding: 1rem;
height: 3.5rem;
span {
color: #ff4a00;
}
.nav-item {
font-weight: bold;
}
.nav-item-btn {
display: flex;
justify-content: space-between;
align-items: center;
}
}
.header-input {
padding: 1rem;
padding-top: 0;
height: 2.5rem;
border-bottom: 1px solid #eee;
}
.order-lists {
height: calc(100vh - 100px - 10.2rem);
overflow-y: auto;
.item {
padding: 1rem;
border-bottom: 1px solid #eee;
.top {
display: flex;
justify-content: space-between;
align-items: flex-end;
.sn {
font-weight: bold;
font-size: 0.9rem;
}
.cahier {
&::before {
content: "收银";
font-weight: 400;
font-size: 0.7rem;
padding: 0.1rem 0.1rem;
margin-right: 0.2rem;
border: 1px solid #2ec479;
color: #2ec479;
border-radius: 0.187rem;
}
}
.cahier2 {
&::before {
content: "平台";
font-weight: 400;
font-size: 0.7rem;
padding: 0.1rem 0.1rem;
margin-right: 0.2rem;
border: 1px solid #ff4a00;
color: #ff4a00;
border-radius: 0.187rem;
}
}
.create-time {
font-size: 0.8rem;
}
}
.shop {
display: flex;
justify-content: space-between;
.right {
flex-shrink: 0;
display: flex;
flex-direction: column;
justify-content: center;
.money {
font-size: 1rem;
color: #ff4a00;
font-weight: bold;
}
.count {
font-size: 0.7rem;
color: #999;
}
}
.left {
height: 4.5rem;
display: flex;
align-items: center;
.shop-img {
width: 3.5rem;
height: 3.5rem;
border-radius: 0.3rem;
margin-right: 0.4rem;
}
.shop-name {
font-size: 0.9rem;
color: #333;
display: -webkit-box;
-webkit-box-orient: vertical;
overflow: hidden;
/* 将文本限制为三行 */
-webkit-line-clamp: 3;
}
}
}
.bottom {
display: flex;
justify-content: space-between;
font-size: 0.9rem;
color: #777;
.manage-btn {
color: #fff;
background-color: #e6a23c;
border-radius: 0.2rem;
padding: 0 0.2rem;
margin-left: 0.5rem;
}
}
}
.item-active {
background-color: #efefef;
}
}
.load-end {
text-align: center;
padding: 1rem;
color: #333;
font-size: 0.8rem;
}
}
</style>

View File

@ -0,0 +1,46 @@
<script setup>
import order from "./component/order.vue";
import detail from "./component/detail.vue";
import padding from "@/components/padding.vue";
import { ref, nextTick } from "vue";
const orderRef = ref(null);
const rePaySuccess = ()=>{
orderRef.value?.getOrderList(true);
}
</script>
<template>
<div class="my-card">
<order style="flex-shrink: 0;" ref="orderRef"/>
<padding />
<detail ref="detailRef" @rePaySuccess="rePaySuccess"/>
</div>
</template>
<style lang="scss">
.my-card {
display: flex;
}
/* 修改滚动条的样式 */
::-webkit-scrollbar {
width: 0.315rem; /* 设置滚动条的宽度 */
}
/* 设置滚动条的轨道样式 */
::-webkit-scrollbar-track {
background-color: #f1f1f1; /* 设置轨道的背景色 */
/* margin: 1.25rem 0; */
}
/* 设置滚动条的滑块样式 */
::-webkit-scrollbar-thumb {
background-color: #ccc; /* 设置滑块的背景色 */
border-radius: 0.315rem; /* 设置滑块的圆角 */
}
/* 设置滚动条鼠标悬停时的滑块样式 */
::-webkit-scrollbar-thumb:hover {
background-color: #999; /* 设置鼠标悬停时滑块的背景色 */
}
</style>