Files
mp-10579/src/views/shop/shopDealerUser/index.vue
赵忠林 a9d513fca4 feat(shop): 添加小区、门店、配送员、店员、仓库管理功能及相关API
- 新增小区管理模块,包括查询、添加、修改、删除等功能
- 新增门店管理模块,包含门店基础信息管理功能
- 新增配送员管理模块,支持骑手信息配置及工作状态管理
- 新增店员管理模块,用于门店人员信息维护
- 新增仓库管理模块,支持不同类型的仓库信息管理
- 添加电子围栏功能,支持圆形和方形围栏设置
- 更新经销商用户模型,增加类型、头像、店铺名称等字段
- 更新订单模型,添加物流单号、昵称等字段
- 更新商品模型,调整分销佣金相关字段设计
- 修复信用模块中部分字段映射错误问题
- 优化邀请链接生成逻辑,增加租户ID参数传递
- 移除部分不必要部门字段显示,简化管理员界面
2026-03-04 14:04:57 +08:00

357 lines
9.3 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"
tool-class="ele-toolbar-form"
class="sys-org-table"
>
<template #toolbar>
<search
@search="reload"
:selection="selection"
@add="openEdit"
@remove="removeBatch"
@batchMove="openMove"
/>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'image'">
<a-image :src="record.image" :width="50" />
</template>
<template v-if="column.key === 'type'">
<a-tag v-if="record.type === 0">分销商</a-tag>
<a-tag v-if="record.type === 1" color="orange">门店</a-tag>
<a-tag v-if="record.type === 2" color="purple">总分销商</a-tag>
</template>
<template v-if="column.key === 'qrcode'">
<QrcodeOutlined :style="{fontSize: '24px'}" @click="openQrCode(record)" />
</template>
<template v-if="column.key === 'status'">
<a-tag v-if="record.status === 0" color="green">显示</a-tag>
<a-tag v-if="record.status === 1" color="red">隐藏</a-tag>
</template>
<template v-if="column.key === 'action'">
<a-space>
<a @click="openEdit(record)">修改</a>
<a-divider type="vertical" />
<a-popconfirm
title="确定要删除此记录吗?"
@confirm="remove(record)"
>
<a class="ele-text-danger">删除</a>
</a-popconfirm>
</a-space>
</template>
</template>
</ele-pro-table>
</a-card>
<!-- 编辑弹窗 -->
<ShopDealerUserEdit v-model:visible="showEdit" :data="current" @done="reload" />
<!-- 二维码预览 -->
<a-modal
v-model:visible="showQrModal"
:title="qrModalTitle"
:footer="null"
:width="380"
centered
destroy-on-close
>
<div style="display: flex; justify-content: center">
<a-image v-if="qrModalUrl" :src="qrModalUrl" :width="280" :preview="false" />
</div>
<div style="display: flex; justify-content: center; margin-top: 12px">
<a-space>
<a-button @click="copyQrUrl">复制链接</a-button>
<a-button type="primary" @click="openQrInNewTab">打开原图</a-button>
</a-space>
</div>
</a-modal>
</a-page-header>
</template>
<script lang="ts" setup>
import { createVNode, ref, computed } from 'vue';
import { message, Modal } from 'ant-design-vue';
import { ExclamationCircleOutlined, QrcodeOutlined } from '@ant-design/icons-vue';
import type { EleProTable } from 'ele-admin-pro';
import { toDateString } 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 ShopDealerUserEdit from './components/shopDealerUserEdit.vue';
import { pageShopDealerUser, removeShopDealerUser, removeBatchShopDealerUser } from '@/api/shop/shopDealerUser';
import type { ShopDealerUser, ShopDealerUserParam } from '@/api/shop/shopDealerUser/model';
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<ShopDealerUser[]>([]);
// 当前编辑数据
const current = ref<ShopDealerUser | null>(null);
// 是否显示编辑弹窗
const showEdit = ref(false);
// 是否显示二维码弹窗
const showQrModal = ref(false);
const qrModalUrl = ref<string>('');
const qrModalTitle = ref<string>('二维码');
// 是否显示批量移动弹窗
const showMove = ref(false);
// 加载状态
const loading = ref(true);
const getQrCodeUrl = (userId?: number) => {
return `https://glt-api.websoft.top/api/wx-login/getOrderQRCodeUnlimited/uid_${userId ?? ''}`;
};
const openQrCode = (row: ShopDealerUser) => {
if (!row.userId) {
message.warning('缺少用户ID无法生成二维码');
return;
}
qrModalUrl.value = getQrCodeUrl(row.userId);
qrModalTitle.value = row.realName ? `${row.realName} 的二维码` : `UID_${row.userId} 二维码`;
showQrModal.value = true;
};
const copyQrUrl = async () => {
if (!qrModalUrl.value) {
return;
}
try {
await navigator.clipboard.writeText(qrModalUrl.value);
message.success('已复制');
} catch (e) {
message.error('复制失败,请手动复制');
}
};
const openQrInNewTab = () => {
if (!qrModalUrl.value) {
return;
}
window.open(qrModalUrl.value, '_blank');
};
// 表格数据源
const datasource: DatasourceFunction = ({
page,
limit,
where,
orders,
filters
}) => {
if (filters) {
where.status = filters.status;
}
return pageShopDealerUser({
...where,
...orders,
page,
limit
});
};
// 完整的列配置(包含所有字段)
const columns = ref<ColumnItem[]>([
{
title: '用户ID',
dataIndex: 'userId',
key: 'userId',
width: 90,
},
{
title: '类型',
dataIndex: 'type',
key: 'type',
align: 'center',
width: 120
},
{
title: '真实姓名',
dataIndex: 'realName',
key: 'realName'
},
{
title: '手机号',
dataIndex: 'mobile',
key: 'mobile'
},
{
title: '可提现',
dataIndex: 'money',
key: 'money',
width: 120
},
{
title: '已冻结',
dataIndex: 'freezeMoney',
key: 'freezeMoney',
width: 120
},
{
title: '累积提现',
dataIndex: 'totalMoney',
key: 'totalMoney',
width: 120
},
// {
// title: '推荐人用户ID',
// dataIndex: 'refereeId',
// key: 'refereeId',
// width: 120
// },
// {
// title: '成员数量(一级)',
// dataIndex: 'firstNum',
// key: 'firstNum',
// width: 120
// },
// {
// title: '成员数量(二级)',
// dataIndex: 'secondNum',
// key: 'secondNum',
// width: 120
// },
// {
// title: '成员数量(三级)',
// dataIndex: 'thirdNum',
// key: 'thirdNum',
// width: 120
// },
{
title: '专属二维码',
dataIndex: 'qrcode',
key: 'qrcode',
align: 'center'
},
// {
// title: '备注',
// dataIndex: 'comments',
// key: 'comments',
// ellipsis: true
// },
// {
// title: '排序号',
// dataIndex: 'sortNumber',
// key: 'sortNumber',
// width: 120
// },
{
title: '创建时间',
dataIndex: 'createTime',
key: 'createTime',
width: 200,
align: 'center',
sorter: true,
ellipsis: true,
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
},
{
title: '操作',
key: 'action',
width: 180,
fixed: 'right',
align: 'center',
hideInSetting: true
}
]);
/* 搜索 */
const reload = (where?: ShopDealerUserParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: ShopDealerUser) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: ShopDealerUser) => {
const hide = message.loading('请求中..', 0);
removeShopDealerUser(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);
removeBatchShopDealerUser(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: ShopDealerUser) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
export default {
name: 'ShopDealerUser'
};
</script>
<style lang="less" scoped></style>