共富商城

This commit is contained in:
zjf committed 2025-09-04 19:58:06 +08:00
1 parent 153e40bb37
commit 22ebd0927d
4 files changed
+348 -2

No files matched your search

@@ -0,0 +1,319 @@
<template>
<el-dialog :title="`绑定用户 - ${merchantInfo.name}`" v-model="visible"
:close-on-click-modal="false" draggable width="80%" top="5vh">
<!-- 搜索区域 -->
<div class="mb20">
<el-row :gutter="20">
<el-col :span="8">
<el-input v-model="searchForm.name" placeholder="请输入用户名称" clearable @keyup.enter="getUserList">
<template #prefix>
<el-icon><Search /></el-icon>
</template>
</el-input>
</el-col>
<el-col :span="8">
<el-input v-model="searchForm.phone" placeholder="请输入手机号" clearable @keyup.enter="getUserList">
<template #prefix>
<el-icon><Search /></el-icon>
</template>
</el-input>
</el-col>
<el-col :span="8">
<el-button type="primary" @click="getUserList">查询</el-button>
<el-button @click="resetSearch">重置</el-button>
</el-col>
</el-row>
</div>
<el-row :gutter="20">
<!-- 可选用户列表 -->
<el-col :span="12">
<div class="panel-title">可选用户</div>
<el-table
:data="availableUsers"
v-loading="userLoading"
height="400"
@selection-change="handleUserSelectionChange"
:row-key="row => row.userId">
<el-table-column type="selection" width="55" />
<el-table-column prop="name" label="用户名称" show-overflow-tooltip />
<el-table-column prop="phone" label="手机号" show-overflow-tooltip />
</el-table>
<div class="mt10">
<el-button type="primary" @click="bindSelectedUsers" :disabled="selectedUsers.length === 0">
绑定选中用户
</el-button>
</div>
</el-col>
<!-- 已绑定用户列表 -->
<el-col :span="12">
<div class="panel-title">已绑定用户</div>
<el-table
:data="boundUsers"
v-loading="boundLoading"
height="400"
@selection-change="handleBoundUserSelectionChange">
<el-table-column type="selection" width="55" />
<el-table-column prop="name" label="用户名称" show-overflow-tooltip />
<el-table-column prop="phone" label="手机号" show-overflow-tooltip />
<el-table-column prop="roleType" label="角色" width="100">
<template #default="scope">
<el-tag :type="scope.row.roleType === 1 ? 'success' : 'info'">
{{ scope.row.roleType === 1 ? '管理员' : '普通用户' }}
</el-tag>
</template>
</el-table-column>
<el-table-column prop="status" label="状态" width="80">
<template #default="scope">
<el-tag :type="scope.row.status === 1 ? 'success' : 'danger'">
{{ scope.row.status === 1 ? '启用' : '禁用' }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="操作" width="120">
<template #default="scope">
<el-button size="small" @click="updateUserRole(scope.row)">
改角色
</el-button>
<el-button size="small" type="danger" @click="unbindUser(scope.row)">
解绑
</el-button>
</template>
</el-table-column>
</el-table>
<div class="mt10">
<el-button type="danger" @click="batchUnbindUsers" :disabled="selectedBoundUsers.length === 0">
批量解绑
</el-button>
</div>
</el-col>
</el-row>
<template #footer>
<span class="dialog-footer">
<el-button @click="visible = false">关闭</el-button>
</span>
</template>
</el-dialog>
</template>
<script setup lang="ts" name="BindUserDialog">
import { useMessage } from "/@/hooks/message";
import {
getUserSelectList,
getMerchantUsers,
batchBindUsers,
unbindUser as unbindUserApi,
batchUnbindUsers as batchUnbindUsersApi,
updateUserRole as updateUserRoleApi
} from '/@/api/supermarket/mallMerchantUser';
import { Search } from '@element-plus/icons-vue';
const emit = defineEmits(['refresh']);
// 定义变量
const visible = ref(false);
const merchantInfo = ref<any>({});
const userLoading = ref(false);
const boundLoading = ref(false);
// 搜索表单
const searchForm = reactive({
name: '',
phone: ''
});
// 用户列表
const availableUsers = ref<any[]>([]);
const boundUsers = ref<any[]>([]);
const selectedUsers = ref<any[]>([]);
const selectedBoundUsers = ref<any[]>([]);
// 打开对话框
const openDialog = (merchant: any) => {
visible.value = true;
merchantInfo.value = merchant;
// 重置数据
availableUsers.value = [];
boundUsers.value = [];
selectedUsers.value = [];
selectedBoundUsers.value = [];
// 加载数据
getUserList();
getBoundUsers();
};
// 获取可选用户列表
const getUserList = async () => {
try {
userLoading.value = true;
const res = await getUserSelectList({
name: searchForm.name,
phone: searchForm.phone,
current: 1,
size: 100
});
// 根据新的接口格式处理数据
const allUsers = res.data || [];
// 过滤掉已绑定的用户
const boundUserIds = boundUsers.value.map(user => user.userId);
availableUsers.value = allUsers.filter((user: any) => !boundUserIds.includes(user.userId));
} catch (err: any) {
useMessage().error(err.msg || '获取用户列表失败');
} finally {
userLoading.value = false;
}
};
// 获取已绑定用户列表
const getBoundUsers = async () => {
try {
boundLoading.value = true;
const res = await getMerchantUsers(merchantInfo.value.id);
boundUsers.value = res.data || [];
} catch (err: any) {
useMessage().error(err.msg || '获取绑定用户失败');
} finally {
boundLoading.value = false;
}
};
// 重置搜索
const resetSearch = () => {
searchForm.name = '';
searchForm.phone = '';
getUserList();
};
// 用户选择变化
const handleUserSelectionChange = (selection: any[]) => {
selectedUsers.value = selection;
};
// 已绑定用户选择变化
const handleBoundUserSelectionChange = (selection: any[]) => {
selectedBoundUsers.value = selection;
};
// 绑定选中用户
const bindSelectedUsers = async () => {
if (selectedUsers.value.length === 0) {
useMessage().warning('请选择要绑定的用户');
return;
}
try {
const bindData = {
merchantId: merchantInfo.value.id,
userIds: selectedUsers.value.map(user => user.userId)
};
await batchBindUsers(bindData);
useMessage().success('绑定成功');
// 刷新数据
getUserList();
getBoundUsers();
emit('refresh');
} catch (err: any) {
useMessage().error(err.msg || '绑定失败');
}
};
// 解绑用户
const unbindUser = async (user: any) => {
try {
await useMessage().confirm(`确定要解绑用户 ${user.name} 吗?`);
await unbindUserApi(user.userId);
useMessage().success('解绑成功');
// 刷新数据
getUserList();
getBoundUsers();
emit('refresh');
} catch (err: any) {
if (err !== 'cancel') {
useMessage().error(err.msg || '解绑失败');
}
}
};
// 批量解绑用户
const batchUnbindUsers = async () => {
if (selectedBoundUsers.value.length === 0) {
useMessage().warning('请选择要解绑的用户');
return;
}
try {
await useMessage().confirm(`确定要解绑选中的 ${selectedBoundUsers.value.length} 个用户吗?`);
const unbindData = {
userIds: selectedBoundUsers.value.map(user => user.userId)
};
await batchUnbindUsersApi(unbindData);
useMessage().success('批量解绑成功');
// 刷新数据
getUserList();
getBoundUsers();
emit('refresh');
} catch (err: any) {
if (err !== 'cancel') {
useMessage().error(err.msg || '批量解绑失败');
}
}
};
// 更新用户角色
const updateUserRole = async (user: any) => {
try {
const newRoleType = user.roleType === 1 ? 2 : 1;
const roleText = newRoleType === 1 ? '管理员' : '普通用户';
await useMessage().confirm(`确定要将用户 ${user.name} 的角色改为 ${roleText} 吗?`);
await updateUserRoleApi({
userId: user.userId,
roleType: newRoleType
});
useMessage().success('角色更新成功');
getBoundUsers();
} catch (err: any) {
if (err !== 'cancel') {
useMessage().error(err.msg || '角色更新失败');
}
}
};
// 暴露方法
defineExpose({
openDialog
});
</script>
<style scoped>
.panel-title {
font-size: 16px;
font-weight: bold;
margin-bottom: 10px;
padding-bottom: 8px;
border-bottom: 1px solid #e4e7ed;
}
.mt10 {
margin-top: 10px;
}
.mb20 {
margin-bottom: 20px;
}
</style>
+5 -1
View File
@@ -99,7 +99,7 @@ const form = reactive({
contactName: '',
contactPhone: '',
email: '',
status: '',
status: 1, // 默认正常状态
licenseNo: '',
address: '',
images: '',
@@ -122,6 +122,10 @@ const openDialog = (id: string) => {
// 重置表单数据
nextTick(() => {
dataFormRef.value?.resetFields();
// 新增时设置默认状态为正常
if (!id) {
form.status = 1;
}
});
// 获取mallMerchant信息
+14 -1
View File
@@ -55,10 +55,12 @@
<el-table-column prop="address" label="详细地址" show-overflow-tooltip/>
<el-table-column prop="images" label="商户图片" show-overflow-tooltip/>
<el-table-column prop="remark" label="备注" show-overflow-tooltip/>
<el-table-column label="操作" width="150">
<el-table-column label="操作" width="200">
<template #default="scope">
<el-button icon="edit-pen" text type="primary" v-auth="'supermarket_mallMerchant_edit'"
@click="formDialogRef.openDialog(scope.row.id)">编辑</el-button>
<el-button icon="user" text type="success"
@click="handleBindUsers(scope.row)">绑定用户</el-button>
<el-button icon="delete" text type="primary" v-auth="'supermarket_mallMerchant_del'" @click="handleDelete([scope.row.id])">删除</el-button>
</template>
</el-table-column>
@@ -69,10 +71,14 @@
<!-- 编辑、新增 -->
<form-dialog ref="formDialogRef" @refresh="getDataList(false)" />
<!-- 绑定用户对话框 -->
<bind-user-dialog ref="bindUserDialogRef" @refresh="getDataList(false)" />
</div>
</template>
<script setup lang="ts" name="systemMallMerchant">
import { defineAsyncComponent } from 'vue';
import { BasicTableProps, useTable } from "/@/hooks/table";
import { fetchList, delObjs } from "/@/api/supermarket/mallMerchant";
import { useMessage, useMessageBox } from "/@/hooks/message";
@@ -80,11 +86,13 @@ import { useDict } from '/@/hooks/dict';
// 引入组件
const FormDialog = defineAsyncComponent(() => import('./form.vue'));
const BindUserDialog = defineAsyncComponent(() => import('./bindUser.vue'));
// 定义查询字典
const { common_data_status } = useDict('common_data_status')
// 定义变量内容
const formDialogRef = ref()
const bindUserDialogRef = ref()
// 搜索变量
const queryRef = ref()
const showSearch = ref(true)
@@ -143,4 +151,9 @@ const handleDelete = async (ids: string[]) => {
useMessage().error(err.msg);
}
};
// 绑定用户操作
const handleBindUsers = (merchant: any) => {
bindUserDialogRef.value?.openDialog(merchant);
};
</script>
@@ -465,6 +465,16 @@ const onSubmit = async () => {
submitData.categoryId = form.categoryId.slice(-1)[0];
}
// 处理时间格式:转换为 LocalDateTime 格式 (yyyy-MM-dd HH:mm:ss)
if (form.saleStartTime) {
const date = new Date(form.saleStartTime);
submitData.saleStartTime = date.toISOString().slice(0, 19).replace('T', ' ');
}
if (form.saleEndTime) {
const date = new Date(form.saleEndTime);
submitData.saleEndTime = date.toISOString().slice(0, 19).replace('T', ' ');
}
// 如果是单价SPU模式,清空SKU列表
if (form.priceType === 2) {
submitData.skuList = [];