|
|
@@ -1,33 +1,312 @@
|
|
|
<template>
|
|
|
- <div class="card content-box">
|
|
|
- <div class="content-section">
|
|
|
- <h2 class="page-title">子账号管理</h2>
|
|
|
- <el-button type="primary" @click="handleCreateSubAccount"> 创建子账号 </el-button>
|
|
|
- </div>
|
|
|
+ <div class="sub-account-management-container">
|
|
|
+ <ProTable
|
|
|
+ ref="proTable"
|
|
|
+ :columns="columns"
|
|
|
+ :request-api="getTableList"
|
|
|
+ :init-param="initParam"
|
|
|
+ :data-callback="dataCallback"
|
|
|
+ row-key="userId"
|
|
|
+ >
|
|
|
+ <!-- 表格 header 按钮 -->
|
|
|
+ <template #tableHeader="scope">
|
|
|
+ <div class="table-header-btn">
|
|
|
+ <el-button type="primary" :icon="Plus" @click="handleCreateSubAccount"> 新建账号 </el-button>
|
|
|
+ <el-button :icon="Delete" :disabled="!scope.isSelected" @click="handleBatchDelete"> 批量删除 </el-button>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ <template #tableHeaderRight>
|
|
|
+ <el-link type="primary" :underline="false"> 历史操作记录 </el-link>
|
|
|
+ </template>
|
|
|
+ <!-- 可操作权限列 -->
|
|
|
+ <template #permissionCount="scope">
|
|
|
+ <span>{{ scope.row.permissionCount || 0 }}个</span>
|
|
|
+ </template>
|
|
|
+ <!-- 操作列 -->
|
|
|
+ <template #operation="scope">
|
|
|
+ <el-button link type="primary" @click="handleView(scope.row)"> 查看 </el-button>
|
|
|
+ <el-button link type="primary" @click="handleEdit(scope.row)"> 编辑 </el-button>
|
|
|
+ <el-button link type="danger" @click="handleDelete(scope.row)"> 删除 </el-button>
|
|
|
+ </template>
|
|
|
+ </ProTable>
|
|
|
+
|
|
|
+ <!-- 删除确认对话框 -->
|
|
|
+ <el-dialog v-model="deleteDialogVisible" title="删除确认" width="400px" :close-on-click-modal="false">
|
|
|
+ <div class="delete-content">
|
|
|
+ <p v-if="deleteType === 'single'">确定要删除子账号"{{ currentAccount?.accountName }}"吗?</p>
|
|
|
+ <p v-else>确定要删除选中的 {{ selectedAccounts.length }} 个子账号吗?</p>
|
|
|
+ <p class="delete-warning">此操作不可恢复!</p>
|
|
|
+ </div>
|
|
|
+ <template #footer>
|
|
|
+ <div class="dialog-footer">
|
|
|
+ <el-button @click="deleteDialogVisible = false"> 取消 </el-button>
|
|
|
+ <el-button type="danger" @click="handleConfirmDelete" :loading="deleteLoading"> 确定删除 </el-button>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </el-dialog>
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
-<script setup lang="ts" name="subAccountManagement">
|
|
|
+<script setup lang="tsx" name="subAccountManagement">
|
|
|
+import { ref, reactive, onMounted, computed } from "vue";
|
|
|
import { useRouter } from "vue-router";
|
|
|
+import { ElMessage } from "element-plus";
|
|
|
+import { Plus, Delete } from "@element-plus/icons-vue";
|
|
|
+import ProTable from "@/components/ProTable/index.vue";
|
|
|
+import { ColumnProps, ProTableInstance } from "@/components/ProTable/interface";
|
|
|
+import { querySubAccounts, getAllNormalRoles, type RoleItem } from "@/api/modules/accountRoleManagement";
|
|
|
+import { localGet } from "@/utils";
|
|
|
+
|
|
|
+// 子账号数据类型
|
|
|
+interface SubAccountItem {
|
|
|
+ userId: number;
|
|
|
+ accountName: string;
|
|
|
+ phone: string;
|
|
|
+ roleId: number;
|
|
|
+ roleName: string;
|
|
|
+ permissionCount: number;
|
|
|
+}
|
|
|
+
|
|
|
+// 路由
|
|
|
const router = useRouter();
|
|
|
|
|
|
-// 子账号管理页面
|
|
|
+// ProTable 实例
|
|
|
+const proTable = ref<ProTableInstance>();
|
|
|
+
|
|
|
+// 角色列表(用于搜索下拉框)
|
|
|
+const roleList = ref<RoleItem[]>([]);
|
|
|
+
|
|
|
+// 选中的账号
|
|
|
+const selectedAccounts = ref<SubAccountItem[]>([]);
|
|
|
+
|
|
|
+// 删除相关
|
|
|
+const deleteDialogVisible = ref(false);
|
|
|
+const deleteLoading = ref(false);
|
|
|
+const deleteType = ref<"single" | "batch">("single");
|
|
|
+const currentAccount = ref<SubAccountItem | null>(null);
|
|
|
+
|
|
|
+// 获取 storeId
|
|
|
+const getStoreId = (): string => {
|
|
|
+ return localGet("createdId") || localGet("geeker-user")?.userInfo?.storeId || "";
|
|
|
+};
|
|
|
+
|
|
|
+// 加载角色列表(用于搜索下拉框)
|
|
|
+const loadRoleList = async () => {
|
|
|
+ try {
|
|
|
+ const storeId = getStoreId();
|
|
|
+ if (!storeId) return;
|
|
|
+
|
|
|
+ const res = await getAllNormalRoles({ storeId: Number(storeId) });
|
|
|
+ const code = typeof res.code === "string" ? parseInt(res.code) : res.code;
|
|
|
+ if (code === 200) {
|
|
|
+ roleList.value = (res.data || []).map((role: any) => ({
|
|
|
+ ...role,
|
|
|
+ id: role.roleId || role.id,
|
|
|
+ roleId: role.roleId || role.id
|
|
|
+ }));
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error("获取角色列表失败:", error);
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+// 表格列配置
|
|
|
+const columns = reactive<ColumnProps<SubAccountItem>[]>([
|
|
|
+ {
|
|
|
+ type: "selection",
|
|
|
+ fixed: "left",
|
|
|
+ width: 55
|
|
|
+ },
|
|
|
+ {
|
|
|
+ prop: "accountName",
|
|
|
+ label: "账号名称",
|
|
|
+ search: {
|
|
|
+ el: "input",
|
|
|
+ props: { placeholder: "请输入账号名称" }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ {
|
|
|
+ prop: "phone",
|
|
|
+ label: "手机号",
|
|
|
+ search: {
|
|
|
+ el: "input",
|
|
|
+ props: { placeholder: "请输入手机号" }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ {
|
|
|
+ prop: "roleName",
|
|
|
+ label: "角色",
|
|
|
+ search: {
|
|
|
+ el: "select",
|
|
|
+ props: { placeholder: "请选择角色", clearable: true },
|
|
|
+ key: "roleName"
|
|
|
+ },
|
|
|
+ enum: computed(() => {
|
|
|
+ return roleList.value.map(role => ({
|
|
|
+ label: role.roleName,
|
|
|
+ value: role.roleName
|
|
|
+ }));
|
|
|
+ }),
|
|
|
+ fieldNames: { label: "label", value: "value" }
|
|
|
+ },
|
|
|
+ {
|
|
|
+ prop: "permissionCount",
|
|
|
+ label: "可操作权限"
|
|
|
+ },
|
|
|
+ {
|
|
|
+ prop: "operation",
|
|
|
+ label: "操作",
|
|
|
+ fixed: "right",
|
|
|
+ width: 180
|
|
|
+ }
|
|
|
+]);
|
|
|
+
|
|
|
+// 初始化参数
|
|
|
+const initParam = reactive({
|
|
|
+ storeId: getStoreId()
|
|
|
+});
|
|
|
+
|
|
|
+// 数据回调处理
|
|
|
+const dataCallback = (data: any) => {
|
|
|
+ // 如果返回的是数组,转换为分页格式
|
|
|
+ if (Array.isArray(data)) {
|
|
|
+ return {
|
|
|
+ list: data,
|
|
|
+ total: data.length
|
|
|
+ };
|
|
|
+ }
|
|
|
+ // 如果返回的是分页对象
|
|
|
+ if (data.records) {
|
|
|
+ return {
|
|
|
+ list: data.records || [],
|
|
|
+ total: data.total || 0
|
|
|
+ };
|
|
|
+ }
|
|
|
+ // 默认返回
|
|
|
+ return {
|
|
|
+ list: [],
|
|
|
+ total: 0
|
|
|
+ };
|
|
|
+};
|
|
|
+
|
|
|
+// 请求接口
|
|
|
+const getTableList = (params: any) => {
|
|
|
+ const storeId = getStoreId();
|
|
|
+ if (!storeId) {
|
|
|
+ ElMessage.warning("缺少店铺ID");
|
|
|
+ return Promise.resolve({ code: 200, data: [], msg: "缺少店铺ID" });
|
|
|
+ }
|
|
|
+
|
|
|
+ return querySubAccounts(Number(storeId), params.accountName || "", params.phone || "", params.roleName || "");
|
|
|
+};
|
|
|
+
|
|
|
+// 创建子账号
|
|
|
const handleCreateSubAccount = () => {
|
|
|
router.push("/accountRoleManagement/subAccountManagement/create");
|
|
|
};
|
|
|
+
|
|
|
+// 查看
|
|
|
+const handleView = (row: SubAccountItem) => {
|
|
|
+ // TODO: 实现查看功能
|
|
|
+ ElMessage.info("查看功能待实现");
|
|
|
+};
|
|
|
+
|
|
|
+// 编辑
|
|
|
+const handleEdit = (row: SubAccountItem) => {
|
|
|
+ router.push({
|
|
|
+ path: "/accountRoleManagement/subAccountManagement/create",
|
|
|
+ query: {
|
|
|
+ id: row.userId.toString(),
|
|
|
+ accountName: row.accountName
|
|
|
+ }
|
|
|
+ });
|
|
|
+};
|
|
|
+
|
|
|
+// 删除单个账号
|
|
|
+const handleDelete = (row: SubAccountItem) => {
|
|
|
+ currentAccount.value = row;
|
|
|
+ deleteType.value = "single";
|
|
|
+ deleteDialogVisible.value = true;
|
|
|
+};
|
|
|
+
|
|
|
+// 批量删除
|
|
|
+const handleBatchDelete = () => {
|
|
|
+ const selectedList = proTable.value?.selectedList || [];
|
|
|
+ if (selectedList.length === 0) {
|
|
|
+ ElMessage.warning("请选择要删除的子账号");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ selectedAccounts.value = selectedList as SubAccountItem[];
|
|
|
+ deleteType.value = "batch";
|
|
|
+ deleteDialogVisible.value = true;
|
|
|
+};
|
|
|
+
|
|
|
+// 确认删除
|
|
|
+const handleConfirmDelete = async () => {
|
|
|
+ deleteLoading.value = true;
|
|
|
+ try {
|
|
|
+ // TODO: 调用删除接口
|
|
|
+ // 模拟接口调用
|
|
|
+ await new Promise(resolve => setTimeout(resolve, 500));
|
|
|
+
|
|
|
+ if (deleteType.value === "single" && currentAccount.value) {
|
|
|
+ // 单个删除
|
|
|
+ ElMessage.success("删除成功");
|
|
|
+ } else {
|
|
|
+ // 批量删除
|
|
|
+ ElMessage.success(`成功删除 ${selectedAccounts.value.length} 个子账号`);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 刷新表格
|
|
|
+ proTable.value?.getTableList();
|
|
|
+ deleteDialogVisible.value = false;
|
|
|
+ currentAccount.value = null;
|
|
|
+ selectedAccounts.value = [];
|
|
|
+ } catch (error) {
|
|
|
+ ElMessage.error("删除失败,请重试");
|
|
|
+ } finally {
|
|
|
+ deleteLoading.value = false;
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+// 初始化
|
|
|
+onMounted(() => {
|
|
|
+ loadRoleList();
|
|
|
+});
|
|
|
</script>
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
-.content-box {
|
|
|
+.sub-account-management-container {
|
|
|
+ min-height: calc(100vh - 84px);
|
|
|
padding: 20px;
|
|
|
+ background: #ffffff;
|
|
|
+}
|
|
|
+.table-header-btn {
|
|
|
+ display: flex;
|
|
|
+ gap: 12px;
|
|
|
+ align-items: center;
|
|
|
}
|
|
|
-.content-section {
|
|
|
- margin-bottom: 20px;
|
|
|
+
|
|
|
+// 删除对话框内容
|
|
|
+.delete-content {
|
|
|
+ p {
|
|
|
+ margin: 0 0 12px;
|
|
|
+ font-size: 14px;
|
|
|
+ color: var(--el-text-color-primary);
|
|
|
+ &:last-child {
|
|
|
+ margin-bottom: 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .delete-warning {
|
|
|
+ font-weight: 500;
|
|
|
+ color: #e6a23c;
|
|
|
+ }
|
|
|
}
|
|
|
-.page-title {
|
|
|
- margin: 0;
|
|
|
- font-size: 20px;
|
|
|
- font-weight: 600;
|
|
|
- color: var(--el-text-color-primary);
|
|
|
+
|
|
|
+// 对话框底部
|
|
|
+.dialog-footer {
|
|
|
+ display: flex;
|
|
|
+ gap: 12px;
|
|
|
+ justify-content: flex-end;
|
|
|
}
|
|
|
</style>
|