增加文档管理功能
This commit is contained in:
@@ -28,6 +28,11 @@
|
||||
<el-table-column prop="name" label="姓名" min-width="120" align="center" />
|
||||
<el-table-column prop="phone" label="手机号" min-width="140" align="center" />
|
||||
<el-table-column prop="email" label="邮箱" min-width="180" align="center" />
|
||||
<el-table-column prop="org_id" label="部门" min-width="160" align="center">
|
||||
<template #default="{ row }">
|
||||
{{ orgNameMap[Number(row.org_id)] || (Number(row.org_id) ? `部门${row.org_id}` : "未分配") }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="status" label="状态" width="90" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="Number(row.status) === 1 ? 'success' : 'danger'">
|
||||
@@ -35,8 +40,9 @@
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="260" align="center" fixed="right">
|
||||
<el-table-column label="操作" width="320" align="center" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button text type="primary" @click="openEditDialog(row)">编辑</el-button>
|
||||
<el-button text type="primary" @click="openPasswordDialog(row)">
|
||||
修改密码
|
||||
</el-button>
|
||||
@@ -54,6 +60,45 @@
|
||||
|
||||
<AddUser ref="addUserRef" @success="refreshTenantUsers" />
|
||||
|
||||
<el-dialog v-model="editDialogVisible" title="编辑用户" width="520px" destroy-on-close>
|
||||
<el-form :model="editForm" label-width="90px">
|
||||
<el-form-item label="用户名">
|
||||
<el-input v-model="editForm.account" disabled />
|
||||
</el-form-item>
|
||||
<el-form-item label="姓名">
|
||||
<el-input v-model="editForm.name" placeholder="请输入姓名" />
|
||||
</el-form-item>
|
||||
<el-form-item label="手机号">
|
||||
<el-input v-model="editForm.phone" placeholder="请输入手机号" />
|
||||
</el-form-item>
|
||||
<el-form-item label="邮箱">
|
||||
<el-input v-model="editForm.email" placeholder="请输入邮箱" />
|
||||
</el-form-item>
|
||||
<el-form-item label="状态">
|
||||
<el-radio-group v-model="editForm.status">
|
||||
<el-radio :label="1">启用</el-radio>
|
||||
<el-radio :label="0">禁用</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="所属部门">
|
||||
<el-tree-select
|
||||
v-model="editForm.org_id"
|
||||
:data="orgTree"
|
||||
:props="{ label: 'label', value: 'value', children: 'children' }"
|
||||
value-key="value"
|
||||
placeholder="请选择所属部门(用于文档私密共享按部门可见)"
|
||||
clearable
|
||||
check-strictly
|
||||
style="width: 100%"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="editDialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" :loading="editSubmitting" @click="submitEdit">确定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog v-model="passwordDialogVisible" title="修改密码" width="420px" destroy-on-close>
|
||||
<el-form ref="passwordFormRef" :model="passwordForm" :rules="passwordRules" label-width="90px">
|
||||
<el-form-item label="新密码" prop="password">
|
||||
@@ -76,6 +121,7 @@ import { ref, reactive, watch } from "vue";
|
||||
import { ElMessage, ElMessageBox } from "element-plus";
|
||||
import { Plus } from "@element-plus/icons-vue";
|
||||
import { getTenantUserList, editTenantUser, deleteTenantUser } from "@/api/tenantUser";
|
||||
import { getOrganizationList } from "@/api/erp";
|
||||
import AddUser from "./adduser.vue";
|
||||
|
||||
const props = defineProps<{
|
||||
@@ -88,6 +134,21 @@ const usersLoading = ref(false);
|
||||
const userSearchKeyword = ref("");
|
||||
const addUserRef = ref<{ open: (tenantId: number) => void } | null>(null);
|
||||
|
||||
const orgTree = ref<any[]>([]);
|
||||
const orgNameMap = ref<Record<number, string>>({});
|
||||
|
||||
const editDialogVisible = ref(false);
|
||||
const editSubmitting = ref(false);
|
||||
const editForm = reactive({
|
||||
id: 0,
|
||||
account: "",
|
||||
name: "",
|
||||
phone: "",
|
||||
email: "",
|
||||
status: 1,
|
||||
org_id: undefined as number | undefined,
|
||||
});
|
||||
|
||||
const passwordDialogVisible = ref(false);
|
||||
const passwordSubmitting = ref(false);
|
||||
const currentTenantUserId = ref<number | null>(null);
|
||||
@@ -122,6 +183,41 @@ const buildTenantUserQuery = (tid: number) => {
|
||||
return params;
|
||||
};
|
||||
|
||||
// 将平铺的组织机构列表转换为树结构,供部门选择器使用
|
||||
const buildOrgTree = (list: any[]): any[] => {
|
||||
const nodes = (list || []).map((o) => ({
|
||||
value: Number(o.id),
|
||||
label: o.org_name || o.name || `部门${o.id}`,
|
||||
parent_id: Number(o.parent_id || 0),
|
||||
}));
|
||||
const map = new Map<number, any>();
|
||||
nodes.forEach((n) => map.set(n.value, { ...n, children: [] as any[] }));
|
||||
const tree: any[] = [];
|
||||
map.forEach((node) => {
|
||||
const parent = map.get(node.parent_id);
|
||||
if (parent) parent.children.push(node);
|
||||
else tree.push(node);
|
||||
});
|
||||
return tree;
|
||||
};
|
||||
|
||||
const loadOrgs = async () => {
|
||||
try {
|
||||
const res = await getOrganizationList();
|
||||
if (res?.code === 200) {
|
||||
const list = res?.data?.list || res?.data || [];
|
||||
orgTree.value = buildOrgTree(list);
|
||||
const nameMap: Record<number, string> = {};
|
||||
(list || []).forEach((o: any) => {
|
||||
nameMap[Number(o.id)] = o.org_name || o.name || `部门${o.id}`;
|
||||
});
|
||||
orgNameMap.value = nameMap;
|
||||
}
|
||||
} catch {
|
||||
orgTree.value = [];
|
||||
}
|
||||
};
|
||||
|
||||
const refreshTenantUsers = async () => {
|
||||
const id = props.tid;
|
||||
if (id == null) return;
|
||||
@@ -160,6 +256,7 @@ watch(
|
||||
() => props.tid,
|
||||
(id) => {
|
||||
userSearchKeyword.value = "";
|
||||
loadOrgs();
|
||||
if (id == null) {
|
||||
tenantUsers.value = [];
|
||||
return;
|
||||
@@ -191,6 +288,42 @@ const openPasswordDialog = (row: any) => {
|
||||
passwordDialogVisible.value = true;
|
||||
};
|
||||
|
||||
const openEditDialog = (row: any) => {
|
||||
editForm.id = Number(row?.id || 0);
|
||||
editForm.account = row?.account || "";
|
||||
editForm.name = row?.name || "";
|
||||
editForm.phone = row?.phone || "";
|
||||
editForm.email = row?.email || "";
|
||||
editForm.status = Number(row?.status ?? 1) === 1 ? 1 : 0;
|
||||
editForm.org_id = row?.org_id ? Number(row.org_id) : undefined;
|
||||
editDialogVisible.value = true;
|
||||
};
|
||||
|
||||
const submitEdit = async () => {
|
||||
if (!editForm.id) return;
|
||||
editSubmitting.value = true;
|
||||
try {
|
||||
const res = await editTenantUser(editForm.id, {
|
||||
name: editForm.name,
|
||||
phone: editForm.phone,
|
||||
email: editForm.email,
|
||||
status: editForm.status,
|
||||
org_id: editForm.org_id || 0,
|
||||
});
|
||||
if (res.code === 200) {
|
||||
ElMessage.success("保存成功");
|
||||
editDialogVisible.value = false;
|
||||
refreshTenantUsers();
|
||||
} else {
|
||||
ElMessage.error(res.msg || "保存失败");
|
||||
}
|
||||
} catch (e: any) {
|
||||
ElMessage.error(e?.message || "保存失败");
|
||||
} finally {
|
||||
editSubmitting.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
const submitPassword = async () => {
|
||||
if (!passwordFormRef.value || !currentTenantUserId.value) return;
|
||||
|
||||
|
||||
@@ -27,6 +27,18 @@
|
||||
<el-radio :label="0">禁用</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="所属部门" prop="org_id">
|
||||
<el-tree-select
|
||||
v-model="formData.org_id"
|
||||
:data="orgTree"
|
||||
:props="{ label: 'label', value: 'value', children: 'children' }"
|
||||
value-key="value"
|
||||
placeholder="请选择所属部门(用于文档私密共享按部门可见)"
|
||||
clearable
|
||||
check-strictly
|
||||
style="width: 100%"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<template #footer>
|
||||
@@ -41,9 +53,10 @@
|
||||
* 租户详情内「添加用户」:提交到 /platform/tenantUser/create,
|
||||
* 后端写入 yz_tenant_user(租户-用户绑定,含冗余账号/密码等字段)。
|
||||
*/
|
||||
import { ref, reactive } from 'vue';
|
||||
import { ref, reactive, onMounted } from 'vue';
|
||||
import { ElMessage } from 'element-plus';
|
||||
import { createTenantUser } from '@/api/tenantUser';
|
||||
import { getOrganizationList } from '@/api/erp';
|
||||
|
||||
const emit = defineEmits(['success']);
|
||||
const visible = ref(false);
|
||||
@@ -52,6 +65,8 @@ const submitting = ref(false);
|
||||
const formRef = ref();
|
||||
const currentTenantId = ref<number | null>(null);
|
||||
|
||||
const orgTree = ref<any[]>([]);
|
||||
|
||||
const formData = reactive({
|
||||
account: '',
|
||||
password: '',
|
||||
@@ -59,9 +74,42 @@ const formData = reactive({
|
||||
name: '',
|
||||
phone: '',
|
||||
email: '',
|
||||
status: 1
|
||||
status: 1,
|
||||
org_id: undefined as number | undefined
|
||||
});
|
||||
|
||||
// 将平铺的组织机构列表转换为树结构,供部门选择器使用
|
||||
const buildOrgTree = (list: any[]): any[] => {
|
||||
const nodes = (list || []).map((o) => ({
|
||||
value: Number(o.id),
|
||||
label: o.org_name || o.name || `部门${o.id}`,
|
||||
parent_id: Number(o.parent_id || 0),
|
||||
}));
|
||||
const map = new Map<number, any>();
|
||||
nodes.forEach((n) => map.set(n.value, { ...n, children: [] as any[] }));
|
||||
const tree: any[] = [];
|
||||
map.forEach((node) => {
|
||||
const parent = map.get(node.parent_id);
|
||||
if (parent) parent.children.push(node);
|
||||
else tree.push(node);
|
||||
});
|
||||
return tree;
|
||||
};
|
||||
|
||||
const loadOrgs = async () => {
|
||||
try {
|
||||
const res = await getOrganizationList();
|
||||
if (res?.code === 200) {
|
||||
const list = res?.data?.list || res?.data || [];
|
||||
orgTree.value = buildOrgTree(list);
|
||||
}
|
||||
} catch {
|
||||
orgTree.value = [];
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(loadOrgs);
|
||||
|
||||
const rules = {
|
||||
account: [{ required: true, message: '请输入用户名', trigger: 'blur' }],
|
||||
password: [{ required: true, message: '请输入密码', trigger: 'blur', min: 5 }],
|
||||
@@ -100,7 +148,8 @@ const open = (tenantId: number) => {
|
||||
name: '',
|
||||
phone: '',
|
||||
email: '',
|
||||
status: 1
|
||||
status: 1,
|
||||
org_id: undefined
|
||||
});
|
||||
};
|
||||
|
||||
@@ -120,6 +169,7 @@ const submitForm = async () => {
|
||||
const submitData = {
|
||||
...formData,
|
||||
tid: currentTenantId.value,
|
||||
org_id: formData.org_id || 0,
|
||||
};
|
||||
// 提交时不需要把确认密码发给后端
|
||||
delete (submitData as any).password2;
|
||||
|
||||
Reference in New Issue
Block a user