Files
mp-10584/src/views/shop/shopDealerOrder/index.vue
赵忠林 482e2a2718 chore(config): 添加项目配置文件和隐私协议
- 添加 .editorconfig 文件统一代码风格
- 添加 .env.development 和 .env.example 环境配置文件
- 添加 .eslintignore 和 .eslintrc.js 代码检查配置
- 添加 .gitignore 版本控制忽略文件配置
- 添加 .prettierignore 格式化忽略配置
- 添加隐私协议HTML文件
- 添加API密钥管理组件基础结构
2026-01-26 14:05:01 +08:00

449 lines
11 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<a-page-header :title="getPageTitle()" @back="() => $router.go(-1)">
<a-card :bordered="false" :body-style="{ padding: '16px' }">
<ele-pro-table
ref="tableRef"
row-key="id"
:columns="columns"
:datasource="datasource"
:customRow="customRow"
v-model:selection="selection"
tool-class="ele-toolbar-form"
class="sys-org-table"
>
<template #toolbar>
<search
@search="reload"
:selection="selection"
@batchSettle="batchSettle"
@export="handleExport"
@remove="removeBatch"
@importDone="reload"
/>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'title'">
<div>{{ record.title }}</div>
<div class="text-gray-400">用户ID{{ record.userId }}</div>
</template>
<template v-if="column.key === 'orderPrice'">
{{ record.orderPrice.toFixed(2) }}
</template>
<template v-if="column.key === 'degreePrice'">
{{ record.degreePrice.toFixed(2) }}
</template>
<template v-if="column.key === 'price'">
{{ record.price }}
</template>
<template v-if="column.key === 'settledPrice'">
{{ record.settledPrice.toFixed(2) }}
</template>
<template v-if="column.key === 'payPrice'">
{{ record.payPrice.toFixed(2) }}
</template>
<template v-if="column.key === 'dealerInfo'">
<div class="dealer-info">
<div v-if="record.firstUserId" class="dealer-level">
<a-tag color="red">一级</a-tag>
用户{{ record.firstUserId }} - ¥{{
parseFloat(record.firstMoney || '0').toFixed(2)
}}
</div>
<div v-if="record.secondUserId" class="dealer-level">
<a-tag color="orange">二级</a-tag>
用户{{ record.secondUserId }} - ¥{{
parseFloat(record.secondMoney || '0').toFixed(2)
}}
</div>
<div v-if="record.thirdUserId" class="dealer-level">
<a-tag color="gold">三级</a-tag>
用户{{ record.thirdUserId }} - ¥{{
parseFloat(record.thirdMoney || '0').toFixed(2)
}}
</div>
</div>
</template>
<template v-if="column.key === 'isInvalid'">
<a-tag v-if="record.isInvalid === 0" color="success">已签约</a-tag>
<a-tag v-if="record.isInvalid === 1" color="error">未签约</a-tag>
</template>
<template v-if="column.key === 'isSettled'">
<a-tag v-if="record.isSettled === 0" color="orange">未结算</a-tag>
<a-tag v-if="record.isSettled === 1" color="success">已结算</a-tag>
</template>
<template v-if="column.key === 'createTime'">
<div class="flex flex-col">
<a-tooltip title="创建时间">
<span class="text-gray-500">{{ record.createTime }}</span>
</a-tooltip>
<a-tooltip title="结算时间">
<span class="text-purple-500">{{ record.settleTime }}</span>
</a-tooltip>
</div>
</template>
<template v-if="column.key === 'action'">
<template v-if="record.isSettled === 0 && record.isInvalid === 0">
<a @click="openEdit(record)" class="ele-text-success"> 结算 </a>
<a-divider type="vertical" />
</template>
<a-popconfirm
v-if="record.isSettled === 0"
title="确定要删除吗?"
@confirm="remove(record)"
placement="topRight"
>
<a class="text-red-500"> 删除 </a>
</a-popconfirm>
</template>
</template>
</ele-pro-table>
</a-card>
<!-- 编辑弹窗 -->
<ShopDealerOrderEdit
v-model:visible="showEdit"
:data="current"
@done="reload"
/>
</a-page-header>
</template>
<script lang="ts" setup>
import { createVNode, ref } from 'vue';
import { message, Modal } from 'ant-design-vue';
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
import type { EleProTable } from 'ele-admin-pro';
import type {
DatasourceFunction,
ColumnItem
} from 'ele-admin-pro/es/ele-pro-table/types';
import Search from './components/search.vue';
import { getPageTitle } from '@/utils/common';
import ShopDealerOrderEdit from './components/shopDealerOrderEdit.vue';
import {
pageShopDealerOrder,
removeShopDealerOrder,
removeBatchShopDealerOrder
} from '@/api/shop/shopDealerOrder';
import type {
ShopDealerOrder,
ShopDealerOrderParam
} from '@/api/shop/shopDealerOrder/model';
import { exportSdyDealerOrder } from '@/api/sdy/sdyDealerOrder';
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<ShopDealerOrder[]>([]);
// 当前编辑数据
const current = ref<ShopDealerOrder | null>(null);
// 是否显示编辑弹窗
const showEdit = ref(false);
// 加载状态
const loading = ref(true);
// 当前搜索条件
const currentWhere = ref<ShopDealerOrderParam>({});
// 表格数据源
const datasource: DatasourceFunction = ({
page,
limit,
where,
orders,
filters
}) => {
if (filters) {
where.status = filters.status;
}
// 保存当前搜索条件用于导出
currentWhere.value = { ...where };
// 未结算订单
where.isSettled = 0;
where.myOrder = 1;
return pageShopDealerOrder({
...where,
...orders,
page,
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: '订单编号',
dataIndex: 'orderNo',
key: 'orderNo'
},
{
title: '客户名称',
dataIndex: 'title',
key: 'title',
width: 220
},
{
title: '结算电量',
dataIndex: 'orderPrice',
key: 'orderPrice',
align: 'center'
},
{
title: '换算成度',
dataIndex: 'degreePrice',
key: 'degreePrice',
align: 'center'
},
{
title: '结算单价',
dataIndex: 'price',
key: 'price',
align: 'center'
},
{
title: '结算金额',
dataIndex: 'settledPrice',
key: 'settledPrice',
align: 'center'
},
{
title: '税费',
dataIndex: 'rate',
key: 'rate',
align: 'center'
},
{
title: '实发金额',
dataIndex: 'payPrice',
key: 'payPrice',
align: 'center'
},
{
title: '签约状态',
dataIndex: 'isInvalid',
key: 'isInvalid',
align: 'center',
width: 100
},
{
title: '月份',
dataIndex: 'month',
key: 'month',
align: 'center',
width: 100
},
{
title: '结算状态',
dataIndex: 'isSettled',
key: 'isSettled',
align: 'center',
width: 100
},
{
title: '创建时间',
dataIndex: 'createTime',
key: 'createTime',
align: 'center'
},
{
title: '操作',
key: 'action',
width: 180,
fixed: 'right',
align: 'center',
hideInSetting: true
}
]);
/* 搜索 */
const reload = (where?: ShopDealerOrderParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 批量结算 */
const batchSettle = () => {
if (!selection.value.length) {
message.error('请至少选择一条数据');
return;
}
const validOrders = selection.value.filter(
(order) => order.isSettled === 0 && order.isInvalid === 0
);
if (!validOrders.length) {
message.error('所选订单中没有可结算的订单');
return;
}
const totalCommission = validOrders
.reduce((sum, order) => {
return (
sum +
parseFloat(order.firstMoney || '0') +
parseFloat(order.secondMoney || '0') +
parseFloat(order.thirdMoney || '0')
);
}, 0)
.toFixed(2);
Modal.confirm({
title: '批量结算确认',
content: `确定要结算选中的 ${validOrders.length} 个订单吗?总佣金金额:¥${totalCommission}`,
icon: createVNode(ExclamationCircleOutlined),
okText: '确认结算',
okType: 'primary',
cancelText: '取消',
onOk: () => {
const hide = message.loading('正在批量结算...', 0);
// 这里调用批量结算API
setTimeout(() => {
hide();
message.success(`成功结算 ${validOrders.length} 个订单`);
reload();
}, 1500);
}
});
};
/* 导出数据 */
const handleExport = () => {
// 调用导出API传入当前搜索条件
exportSdyDealerOrder(currentWhere.value);
};
/* 打开编辑弹窗 */
const openEdit = (row?: ShopDealerOrder) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 删除单个 */
const remove = (row: ShopDealerOrder) => {
const hide = message.loading('请求中..', 0);
removeShopDealerOrder(row.id)
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
};
/* 批量删除 */
const removeBatch = () => {
if (!selection.value.length) {
message.error('请至少选择一条数据');
return;
}
Modal.confirm({
title: '提示',
content: '确定要删除选中的记录吗?',
icon: createVNode(ExclamationCircleOutlined),
maskClosable: true,
onOk: () => {
const hide = message.loading('请求中..', 0);
removeBatchShopDealerOrder(selection.value.map((d) => d.id))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: ShopDealerOrder) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
export default {
name: 'ShopDealerOrder'
};
</script>
<style lang="less" scoped>
.order-info {
.order-id {
font-weight: 500;
color: #333;
margin-bottom: 4px;
}
.order-price {
color: #ff4d4f;
font-weight: 600;
}
}
.dealer-info {
.dealer-level {
margin-bottom: 6px;
font-size: 12px;
&:last-child {
margin-bottom: 0;
}
}
}
:deep(.detail-section) {
h4 {
color: #1890ff;
margin-bottom: 12px;
border-bottom: 1px solid #f0f0f0;
padding-bottom: 8px;
}
p {
margin: 4px 0;
line-height: 1.5;
}
}
:deep(.ant-table-tbody > tr > td) {
vertical-align: top;
}
:deep(.ant-tag) {
margin: 2px 4px 2px 0;
}
</style>