Merge remote-tracking branch 'origin/dev' into dev

# Conflicts:
#	.env.development
This commit is contained in:
2026-08-19 15:14:48 +08:00
9 changed files with 3084 additions and 2970 deletions
+2 -4
View File
@@ -1,8 +1,6 @@
VITE_APP_NAME=后台管理系统 VITE_APP_NAME=后台管理系统
#VITE_API_URL=http://localhost:9090/api #VITE_API_URL=http://localhost:9090/api
#VITE_API_URL=http://yxw.wsdns.cn/api VITE_API_URL=https://yxw-api.websoft.top/api
#VITE_SOCKET_URL=ws://localhost:9190 #VITE_SOCKET_URL=ws://localhost:9190
#VITE_API_URL=http://127.0.0.1:9090/api #VITE_API_URL=http://127.0.0.1:9090/api
#VITE_API_URL=https://server.gxwebsoft.com/api VITE_SOCKET_URL=wss://server.websoft.top
#VITE_SOCKET_URL=wss://server.gxwebsoft.com
VITE_API_URL=http://yxw.wsdns.cn/api
+2 -5
View File
@@ -1,6 +1,3 @@
VITE_APP_NAME=后台管理系统 VITE_APP_NAME=后台管理系统
#VITE_API_URL=https://server.jimeigroup.cn/api VITE_API_URL=https://yxw-api.websoft.top/api
#VITE_API_URL=https://server.gxwebsoft.com/api VITE_SOCKET_URL=wss://server.websoft.top
VITE_API_URL=http://yxw.wsdns.cn/api
#VITE_API_URL=http://1.14.132.108:10032/api
VITE_SOCKET_URL=wss://server.gxwebsoft.com
+8
View File
@@ -67,6 +67,14 @@ export async function addOrderPay(data: OrderPay) {
return Promise.reject(new Error(res.data.message)); return Promise.reject(new Error(res.data.message));
} }
export async function updateOrderPay(data: OrderPay) {
const res = await request.put<ApiResult<unknown>>('/shop/order-pay', data);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/** /**
* 根据id查询订单 * 根据id查询订单
*/ */
+2
View File
@@ -35,6 +35,7 @@ export interface Order {
sortNumber?: number; sortNumber?: number;
// 配送方式 // 配送方式
deliveryType?: string; deliveryType?: string;
payTime?: string;
// 付款状态 // 付款状态
payStatus?: number; payStatus?: number;
expressPrice?: string; expressPrice?: string;
@@ -126,6 +127,7 @@ export interface OrderPay {
currPeriods?:number;//当前期数 currPeriods?:number;//当前期数
isAdminRenew?:number;//是否管理员学费 isAdminRenew?:number;//是否管理员学费
orderPays?: OrderPay[]
} }
+2 -2
View File
@@ -119,7 +119,7 @@
<a-page-header <a-page-header
:title="item.nickname" :title="item.nickname"
:sub-title="`${item.createTime}`" :sub-title="`${item.createTime}`"
:avatar="{ src: item.avatar ? item.avatar : 'https://file.gxwebsoft.com/20230217/c8a5c699b3174866a36dd6d378a09bb9.jpg' }" :avatar="{ src: item.avatar ? item.avatar : 'https://file.wsdns.cn/20230217/c8a5c699b3174866a36dd6d378a09bb9.jpg' }"
> >
<template #extra> <template #extra>
<a-button key="2" href="#bottom" @click="onReply(item)">回复</a-button> <a-button key="2" href="#bottom" @click="onReply(item)">回复</a-button>
@@ -147,7 +147,7 @@
<a-page-header <a-page-header
:title="item.nickname" :title="item.nickname"
:sub-title="`${item.createTime}`" :sub-title="`${item.createTime}`"
:avatar="{ src: item.avatar ? item.avatar : 'https://file.gxwebsoft.com/20230217/c8a5c699b3174866a36dd6d378a09bb9.jpg' }" :avatar="{ src: item.avatar ? item.avatar : 'https://file.wsdns.cn/20230217/c8a5c699b3174866a36dd6d378a09bb9.jpg' }"
> >
<template #extra> <template #extra>
<template v-for="(role,index) in loginUser.roles" :key="index"> <template v-for="(role,index) in loginUser.roles" :key="index">
+2 -2
View File
@@ -115,7 +115,7 @@
<a-page-header <a-page-header
:title="item.nickname" :title="item.nickname"
:sub-title="`${item.createTime}`" :sub-title="`${item.createTime}`"
:avatar="{ src: item.avatar ? item.avatar : 'https://file.gxwebsoft.com/20230217/c8a5c699b3174866a36dd6d378a09bb9.jpg' }" :avatar="{ src: item.avatar ? item.avatar : 'https://file.wsdns.cn/20230217/c8a5c699b3174866a36dd6d378a09bb9.jpg' }"
> >
<template #extra> <template #extra>
<a-button key="2" href="#bottom" @click="onReply(item)">回复</a-button> <a-button key="2" href="#bottom" @click="onReply(item)">回复</a-button>
@@ -143,7 +143,7 @@
<a-page-header <a-page-header
:title="item.nickname" :title="item.nickname"
:sub-title="`${item.createTime}`" :sub-title="`${item.createTime}`"
:avatar="{ src: item.avatar ? item.avatar : 'https://file.gxwebsoft.com/20230217/c8a5c699b3174866a36dd6d378a09bb9.jpg' }" :avatar="{ src: item.avatar ? item.avatar : 'https://file.wsdns.cn/20230217/c8a5c699b3174866a36dd6d378a09bb9.jpg' }"
> >
<template #extra> <template #extra>
<template v-for="(role,index) in loginUser.roles" :key="index"> <template v-for="(role,index) in loginUser.roles" :key="index">
@@ -267,9 +267,6 @@
<div>电池押金:¥{{ record.batteryDeposit }}</div> <div>电池押金:¥{{ record.batteryDeposit }}</div>
<div>电池保险:¥{{ record.batteryInsurance }}</div> <div>电池保险:¥{{ record.batteryInsurance }}</div>
</template> </template>
<template v-if="column.key === 'expirationDay'">
<span class="ele-text-danger">{{ expirationDay(record) }}</span>
</template>
<template v-if="column.key === 'duration'"> <template v-if="column.key === 'duration'">
<span class="ele-text-danger">{{ countDuration(record) }}</span> <span class="ele-text-danger">{{ countDuration(record) }}</span>
@@ -278,7 +275,7 @@
</a-table> </a-table>
</a-spin> </a-spin>
</a-card> </a-card>
<a-card title="租期记录" class="order-card"> <a-card title="缴费记录" class="order-card">
<a-spin :spinning="loading"> <a-spin :spinning="loading">
<a-table <a-table
:data-source="renewOrderList" :data-source="renewOrderList"
@@ -286,23 +283,51 @@
ref="tableRef2" ref="tableRef2"
:pagination="true" :pagination="true"
> >
<template #bodyCell="{ column, record }"> <template #bodyCell="{ column, record, index }">
<template v-if="column.key === 'orderNo'"> <template v-if="column.key === 'orderNo'">
<span :class="[record.isAdminRenew === 1 ? 'ele-text-primary' : '']">{{ record.orderNo }}</span> <span
:class="[record.isAdminRenew === 1 ? 'ele-text-primary' : '']"
>{{ record.orderNo }}</span
>
</template> </template>
<template v-if="column.key === 'batteryModel'"> <template v-if="column.key === 'batteryModel'">
<div :class="[record.isAdminRenew === 1 ? 'ele-text-primary' : '']"> <div
:class="[record.isAdminRenew === 1 ? 'ele-text-primary' : '']"
>
<div>电池租金:¥{{ record.batteryRent }}</div> <div>电池租金:¥{{ record.batteryRent }}</div>
<div>电池押金:¥{{ record.batteryDeposit }}</div> <div>电池押金:¥{{ record.batteryDeposit }}</div>
<div>电池保险:¥{{ record.batteryInsurance }}</div> <div>电池保险:¥{{ record.batteryInsurance }}</div>
</div> </div>
</template> </template>
<template v-if="column.key === 'expirationTime'"> <template v-if="column.key === 'expirationTime'">
<div>{{ record.startTime }}</div> <div>
<div>{{ record.expirationTime }}</div> <a-date-picker
value-format="YYYY-MM-DD HH:mm:ss"
@change="changeData(record, 'startTime')"
class="ele-fluid"
placeholder="请选择时间"
v-model:value="record.startTime"
/>
</div>
<div>
<a-date-picker
value-format="YYYY-MM-DD HH:mm:ss"
@change="changeData(record, 'expirationTime')"
class="ele-fluid"
placeholder="请选择时间"
v-model:value="record.expirationTime"
/>
</div>
</template> </template>
<template v-if="column.key === 'expirationDay'"> <template v-if="column.key === 'expirationDay'">
<span class="ele-text-danger">{{ expirationDay(record) }}</span> <span
class="ele-text-danger"
v-if="expirationDay(record, index).includes('逾期')"
>{{ expirationDay(record, index) }}</span
>
<span class="ele-text-success" v-else>{{
expirationDay(record, index)
}}</span>
</template> </template>
<template v-if="column.key === 'action'"> <template v-if="column.key === 'action'">
@@ -435,13 +460,13 @@
<script lang="ts" setup> <script lang="ts" setup>
import { ref, reactive, watch } from 'vue'; import { ref, reactive, watch } from 'vue';
import { Form } from 'ant-design-vue'; import { Form, message } from 'ant-design-vue';
import { assignObject, EleProTable, timeAgo } from 'ele-admin-pro'; import { assignObject, EleProTable, timeAgo } from 'ele-admin-pro';
import { useThemeStore } from '@/store/modules/theme'; import { useThemeStore } from '@/store/modules/theme';
import { formatNumber } from 'ele-admin-pro/es'; import { formatNumber } from 'ele-admin-pro/es';
import { storeToRefs } from 'pinia'; import { storeToRefs } from 'pinia';
import { copyText } from '@/utils/common'; import { copyText } from '@/utils/common';
import { Order } from '@/api/order/model'; import { Order, OrderPay } from '@/api/order/model';
import OrderXufei from '../components/order-xufei.vue'; import OrderXufei from '../components/order-xufei.vue';
import { listEquipmentOrderGoods } from '@/api/apps/equipment/order/goods'; import { listEquipmentOrderGoods } from '@/api/apps/equipment/order/goods';
import { EquipmentOrderGoods } from '@/api/apps/equipment/order/goods/model'; import { EquipmentOrderGoods } from '@/api/apps/equipment/order/goods/model';
@@ -451,9 +476,10 @@
ColumnItem, ColumnItem,
DatasourceFunction DatasourceFunction
} from 'ele-admin-pro/es/ele-pro-table/types'; } from 'ele-admin-pro/es/ele-pro-table/types';
import { listOrder, listOrderPay } from '@/api/order'; import { listOrder, listOrderPay, updateOrderPay } from '@/api/order';
import { CopyOutlined } from '@ant-design/icons-vue'; import { CopyOutlined } from '@ant-design/icons-vue';
import { EquipmentRecord } from '@/api/apps/equipment/record/model'; import { EquipmentRecord } from '@/api/apps/equipment/record/model';
import dayjs from 'dayjs';
const useForm = Form.useForm; const useForm = Form.useForm;
// 是否开启响应式布局 // 是否开启响应式布局
@@ -785,7 +811,8 @@
const getEquipmentRecordList = () => { const getEquipmentRecordList = () => {
EquipmentRecordApi.pageEquipmentRecord({ EquipmentRecordApi.pageEquipmentRecord({
orderId: order.orderId, orderId: order.orderId,
userId: order.userId userId: order.userId,
limit: 100
}).then((data) => { }).then((data) => {
EquipmentRecordList.value = data.list; EquipmentRecordList.value = data.list;
}); });
@@ -808,16 +835,26 @@
// }); // });
// }; // };
const expirationDay = (order) => { const expirationDay = (order, index) => {
const setTime = new Date(order.expirationTime); if (dayjs(order.expirationTime).isBefore(dayjs())) {
const nowTime = new Date(); if (index === 0) {
const restSec = setTime.getTime() - nowTime.getTime(); const useDay = dayjs().diff(dayjs(order.expirationTime), 'd');
console.log('计算剩余天数'); return `逾期${useDay}天`;
console.log(restSec); } else {
// 剩余天数 const useDay = dayjs(order.expirationTime).diff(
const day = parseInt(String(restSec / (60 * 60 * 24 * 1000))); dayjs(props?.data?.payTime),
if (day < 0) { 'd'
return '逾期' + Math.abs(day) + '天'; );
return `使用${useDay}天`;
}
} else {
const day = dayjs(order.expirationTime).diff(dayjs(order.payTime), 'd');
if (day < 0) {
return '逾期' + Math.abs(day) + '天';
} else {
const useDay = dayjs().diff(dayjs(props?.data?.payTime), 'd');
return `使用${useDay}天`;
}
} }
}; };
@@ -850,6 +887,11 @@
} }
}; };
const changeData = async (data: OrderPay) => {
await updateOrderPay(data);
message.success('保存成功');
};
/* 保存编辑 */ /* 保存编辑 */
const save = () => {}; const save = () => {};
@@ -869,6 +911,7 @@
} }
} else { } else {
resetFields(); resetFields();
emit('done')
} }
} }
); );
+69 -47
View File
@@ -31,10 +31,10 @@
<template #bodyCell="{ column, record }"> <template #bodyCell="{ column, record }">
<template v-if="column.key === 'restDay'"> <template v-if="column.key === 'restDay'">
<strong v-if="record.restDay < 0" :style="{ color: 'red' }">{{ <strong v-if="record.restDay < 0" :style="{ color: 'red' }">{{
record.restDay record.restDay
}}</strong> }}</strong>
<span v-else-if="record.restDay >= 0">{{ record.restDay }}</span> <span v-else-if="record.restDay >= 0">{{ record.restDay }}</span>
<span> </span> <span v-if="record.restDay !== ''"> </span>
</template> </template>
<template v-if="column.key === 'merchantName'"> <template v-if="column.key === 'merchantName'">
<div style="display: flex; flex-direction: column"> <div style="display: flex; flex-direction: column">
@@ -52,7 +52,8 @@
<form-outlined <form-outlined
v-if="record.payStatus === 10" v-if="record.payStatus === 10"
@click="onEdit('totalPayPrice', record.totalPrice, record)" @click="onEdit('totalPayPrice', record.totalPrice, record)"
/></p> />
</p>
<p class="ele-text-placeholder" <p class="ele-text-placeholder"
>(含运费{{ record.expressPrice }})</p >(含运费{{ record.expressPrice }})</p
> >
@@ -66,17 +67,17 @@
</template> </template>
<template v-if="column.key === 'payMethod'"> <template v-if="column.key === 'payMethod'">
<a-tag v-if="record.payMethod === '10'" color="orange" <a-tag v-if="record.payMethod === '10'" color="orange"
>余额支付</a-tag >余额支付
> </a-tag>
<a-tag v-if="record.payMethod === '20'" color="green" <a-tag v-if="record.payMethod === '20'" color="green"
>微信支付</a-tag >微信支付
> </a-tag>
<a-tag v-if="record.payMethod === '30'" color="blue" <a-tag v-if="record.payMethod === '30'" color="blue"
>支付宝</a-tag >支付宝
> </a-tag>
<a-tag v-if="record.payMethod === '40'" color="purple" <a-tag v-if="record.payMethod === '40'" color="purple"
>通联支付</a-tag >通联支付
> </a-tag>
</template> </template>
<template v-if="column.key === 'deliveryType'"> <template v-if="column.key === 'deliveryType'">
<span v-if="record.deliveryType === 10">快递配送</span> <span v-if="record.deliveryType === 10">快递配送</span>
@@ -88,37 +89,37 @@
<a-tag <a-tag
v-if="record.payStatus === 10" v-if="record.payStatus === 10"
@click="onAlipayQuery(record.orderId)" @click="onAlipayQuery(record.orderId)"
>未付款</a-tag >未付款
> </a-tag>
<a-tag v-if="record.payStatus === 20" color="green" <a-tag v-if="record.payStatus === 20" color="green"
>已付款</a-tag >已付款
> </a-tag>
</div> </div>
<div class="ele-text-placeholder"> <div class="ele-text-placeholder">
<!-- 发货状态--> <!-- 发货状态-->
<a-tag v-if="record.deliveryStatus === 10">未发货</a-tag> <a-tag v-if="record.deliveryStatus === 10">未发货</a-tag>
<a-tag v-else-if="record.deliveryStatus === 20" color="success" <a-tag v-else-if="record.deliveryStatus === 20" color="success"
>已发货</a-tag >已发货
> </a-tag>
</div> </div>
<div class="ele-text-placeholder"> <div class="ele-text-placeholder">
<!-- 收货状态--> <!-- 收货状态-->
<a-tag v-if="record.receiptStatus === 10">未收货</a-tag> <a-tag v-if="record.receiptStatus === 10">未收货</a-tag>
<a-tag v-else-if="record.receiptStatus === 20" color="success" <a-tag v-else-if="record.receiptStatus === 20" color="success"
>已收货</a-tag >已收货
> </a-tag>
<a-tag v-else-if="record.receiptStatus === 21" color="purple" <a-tag v-else-if="record.receiptStatus === 21" color="purple"
>退租中</a-tag >退租中
> </a-tag>
<a-tag v-else-if="record.receiptStatus === 30" color="error" <a-tag v-else-if="record.receiptStatus === 30" color="error"
>已退租</a-tag >已退租
> </a-tag>
</div> </div>
<div class="ele-text-placeholder" v-if="record.orderSource != 10"> <div class="ele-text-placeholder" v-if="record.orderSource != 10">
<!-- 分期状态--> <!-- 分期状态-->
<a-tag v-if="record.fenqiStatus == 1" color="success" <a-tag v-if="record.fenqiStatus == 1" color="success"
>已完成</a-tag >已完成
> </a-tag>
<!-- <a-tag v-else-if="record.expirationDay < 0" color="error">逾期{{ record.expirationDay }}</a-tag> --> <!-- <a-tag v-else-if="record.expirationDay < 0" color="error">逾期{{ record.expirationDay }}</a-tag> -->
<!-- <a-tag v-else-if="record.expirationDay >= 0" color="warning">剩余{{ record.expirationDay }}</a-tag> --> <!-- <a-tag v-else-if="record.expirationDay >= 0" color="warning">剩余{{ record.expirationDay }}</a-tag> -->
</div> </div>
@@ -155,20 +156,20 @@
</template> </template>
<template v-if="column.key === 'orderSource'"> <template v-if="column.key === 'orderSource'">
<a-tag v-if="Number(record.orderSource) === 10" color="success" <a-tag v-if="Number(record.orderSource) === 10" color="success"
>销售</a-tag >销售
> </a-tag>
<a-tag v-if="Number(record.orderSource) === 20" color="red" <a-tag v-if="Number(record.orderSource) === 20" color="red"
>分期</a-tag >分期
> </a-tag>
<a-tag v-if="Number(record.orderSource) === 30" color="orange" <a-tag v-if="Number(record.orderSource) === 30" color="orange"
>以租代购</a-tag >以租代购
> </a-tag>
<a-tag v-if="Number(record.orderSource) === 40" color="blue" <a-tag v-if="Number(record.orderSource) === 40" color="blue"
>租赁</a-tag >租赁
> </a-tag>
<a-tag v-if="Number(record.orderSource) === 50" color="success" <a-tag v-if="Number(record.orderSource) === 50" color="success"
>续租</a-tag >续租
> </a-tag>
</template> </template>
<template v-if="column.key === 'nickname'"> <template v-if="column.key === 'nickname'">
<User :record="record" /> <User :record="record" />
@@ -179,26 +180,34 @@
<template v-if="column.key === 'equipmentCode'"> <template v-if="column.key === 'equipmentCode'">
{{ record.equipment?.equipmentCode }} {{ record.equipment?.equipmentCode }}
</template> </template>
<template v-if="column.key === 'expirationTime'">
{{
record.orderPays && record.orderPays.length > 0
? record.orderPays[record.orderPays.length - 1].expirationTime
: record.expirationTime
}}
</template>
<template v-if="column.key === 'createTime'"> <template v-if="column.key === 'createTime'">
{{ record.createTime }} {{ record.createTime }}
</template> </template>
<template v-if="column.key === 'action'"> <template v-if="column.key === 'action'">
<a-space> <a-space>
<a-button class="ele-text-primary" @click="openInfo(record)" <a-button class="ele-text-primary" @click="openInfo(record)"
>详情</a-button >详情
> </a-button>
</a-space> </a-space>
<view v-if="record.deliveryStatus == 40"> <view v-if="record.deliveryStatus == 40">
<a-divider type="vertical" /> <a-divider type="vertical" />
<a-button class="ele-text-danger" @click="openChange(record)" <a-button class="ele-text-danger" @click="openChange(record)"
>换电</a-button >换电
> </a-button>
</view> </view>
<view v-if="record.receiptStatus === 20"> <view v-if="record.receiptStatus === 20">
<a-button <a-button
class="ele-text-danger" class="ele-text-danger"
@click="openOrderRefund(record)" @click="openOrderRefund(record)"
>退租</a-button> >退租
</a-button>
</view> </view>
</template> </template>
</template> </template>
@@ -270,6 +279,7 @@
import { getDictionaryOptions } from '@/utils/common'; import { getDictionaryOptions } from '@/utils/common';
import { Equipment } from '@/api/apps/equipment/model'; import { Equipment } from '@/api/apps/equipment/model';
import { utils, writeFile } from 'xlsx'; import { utils, writeFile } from 'xlsx';
import dayjs from "dayjs";
// 当前用户信息 // 当前用户信息
// const userStore = useUserStore(); // const userStore = useUserStore();
@@ -312,10 +322,10 @@
sorter: true sorter: true
}, },
/* { /* {
title: '商品编号', title: '商品编号',
dataIndex: 'goodsId', dataIndex: 'goodsId',
key: 'goodsId' key: 'goodsId'
}, */ }, */
{ {
title: '电池型号', title: '电池型号',
dataIndex: 'batteryModel', dataIndex: 'batteryModel',
@@ -341,7 +351,6 @@
}, },
{ {
title: '到期时间', title: '到期时间',
dataIndex: 'expirationTime',
key: 'expirationTime', key: 'expirationTime',
sorter: true sorter: true
}, },
@@ -477,7 +486,7 @@
const showAdvancedSearch = ref(false); const showAdvancedSearch = ref(false);
// 表格数据源 // 表格数据源
const datasource: DatasourceFunction = ({ const datasource: DatasourceFunction = async ({
page, page,
limit, limit,
where, where,
@@ -500,12 +509,17 @@
where.tenantId = localStorage.getItem('tenantId'); where.tenantId = localStorage.getItem('tenantId');
where.isRenew = 0; where.isRenew = 0;
where.isFreeze = 1; where.isFreeze = 1;
return pageOrder({ const res = await pageOrder({
...where, ...where,
...orders, ...orders,
page, page,
limit limit
}); });
res.list.map(item => {
item.restDay = calRestDay(item);
return item
})
return res
}; };
// 导出 // 导出
const handleExport = () => { const handleExport = () => {
@@ -600,6 +614,11 @@
showEdit.value = true; showEdit.value = true;
}; };
const calRestDay = (row: Order) => {
if (!row.orderPays || row.orderPays.length == 0) return ''
return dayjs(row.orderPays[row.orderPays.length - 1].expirationTime).diff(dayjs(), 'd')
};
const onEditContent = (name, text, item) => { const onEditContent = (name, text, item) => {
orderId.value = item.orderId; orderId.value = item.orderId;
field.value = name; field.value = name;
@@ -716,6 +735,7 @@
p { p {
line-height: 0.8; line-height: 0.8;
} }
.sys-org-table :deep(.ant-table-body) { .sys-org-table :deep(.ant-table-body) {
overflow: auto !important; overflow: auto !important;
overflow: overlay !important; overflow: overlay !important;
@@ -725,9 +745,11 @@
padding: 0 4px; padding: 0 4px;
margin-bottom: 0; margin-bottom: 0;
} }
.price-edit { .price-edit {
padding-right: 5px; padding-right: 5px;
} }
.comments { .comments {
max-width: 200px; max-width: 200px;
} }
+2930 -2886
View File
File diff suppressed because it is too large Load Diff