初始化

This commit is contained in:
zg
2026-07-15 16:13:27 +08:00
parent 6d6f559793
commit c4023c1623
276 changed files with 42622 additions and 0 deletions

View File

@@ -0,0 +1,309 @@
<template>
<div class="form-page">
<el-page-header @back="handleBack" :title="isEdit ? '编辑用户' : '新增用户'" />
<el-divider />
<el-card shadow="never" class="form-card">
<el-form ref="formRef" :model="form" :rules="rules" label-width="100px">
<!-- ===== 基本信息 ===== -->
<el-divider content-position="left"><span class="section-label">基本信息</span></el-divider>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="用户名" prop="username">
<el-input v-model="form.username" placeholder="请输入用户名" :disabled="isEdit" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="真实姓名" prop="realName">
<el-input v-model="form.realName" placeholder="请输入真实姓名" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="邮箱" prop="email">
<el-input v-model="form.email" placeholder="请输入邮箱" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="手机号">
<el-input v-model="form.phone" placeholder="请输入手机号" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="岗位">
<el-input v-model="form.post" placeholder="请输入岗位" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item v-if="!isEdit" label="密码" prop="password">
<el-input v-model="form.password" type="password" placeholder="请输入密码" show-password />
</el-form-item>
</el-col>
</el-row>
<el-form-item label="状态" prop="status">
<el-switch v-model="form.status" :active-value="1" :inactive-value="0" active-text="启用" inactive-text="禁用" />
</el-form-item>
<!-- ===== 系统 & 角色绑定仅编辑模式 ===== -->
<template v-if="isEdit">
<el-divider content-position="left"><span class="section-label">系统绑定</span></el-divider>
<el-form-item label="绑定系统">
<el-checkbox-group v-model="bindSystemIds" @change="onSystemChange">
<el-checkbox
v-for="sys in allSystems"
:key="sys.systemId"
:label="sys.systemId"
>
{{ sys.systemName }}
<el-tag size="small" type="info" style="margin-left:4px">{{ sys.systemCode }}</el-tag>
</el-checkbox>
</el-checkbox-group>
</el-form-item>
<el-divider content-position="left"><span class="section-label">角色分配</span></el-divider>
<p class="hint-text">先选择系统再为该用户分配该系统下的角色</p>
<el-form-item label="选择系统">
<el-select
v-model="roleSystemId"
placeholder="请选择系统"
clearable
style="width:280px"
@change="onRoleSystemChange"
>
<el-option
v-for="sys in allSystems"
:key="sys.systemId"
:label="sys.systemName + ' (' + sys.systemCode + ')'"
:value="sys.systemId"
/>
</el-select>
</el-form-item>
<el-form-item v-if="roleSystemId" label="分配角色">
<el-checkbox-group v-model="assignRoleIds">
<el-checkbox
v-for="r in currentRoleList"
:key="r.id"
:label="r.id"
>
{{ r.roleName }}
<span style="color:var(--text-muted);font-size:12px;margin-left:4px">{{ r.roleCode }}</span>
</el-checkbox>
</el-checkbox-group>
<el-empty v-if="currentRoleList.length === 0" description="该系统下暂无角色" :image-size="60" />
</el-form-item>
</template>
<!-- ===== 按钮 ===== -->
<el-divider />
<div class="form-footer">
<el-button @click="handleBack">取消</el-button>
<el-button type="primary" :loading="submitLoading" @click="handleSubmit">保存</el-button>
</div>
</el-form>
</el-card>
</div>
</template>
<script setup lang="ts">
import { computed, reactive, ref, onMounted } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { ElMessage } from 'element-plus'
import type { FormInstance, FormRules } from 'element-plus'
import request from '@/utils/request'
const route = useRoute()
const router = useRouter()
const isEdit = ref(false)
const editId = ref<string>()
const submitLoading = ref(false)
const formRef = ref<FormInstance>()
const form = reactive({
username: '',
realName: '',
email: '',
phone: '',
post: '',
password: '',
status: 1,
})
const rules = computed<FormRules>(() => ({
username: [{ required: true, message: '请输入用户名', trigger: 'blur' }],
realName: [{ required: true, message: '请输入真实姓名', trigger: 'blur' }],
email: [{ required: true, message: '请输入邮箱', trigger: 'blur' }],
password: isEdit.value ? [] : [{ required: true, message: '请输入密码', trigger: 'blur' }],
status: [{ required: true, message: '请选择状态', trigger: 'change' }],
}))
// ===== 系统绑定 =====
const allSystems = ref<any[]>([])
const bindSystemIds = ref<string[]>([])
async function fetchAllSystems() {
try {
const res = await request.get('/zgapi/v1/auth/system/list')
allSystems.value = res.data ?? []
} catch { /* ignore */ }
}
async function fetchUserSystems() {
if (!editId.value) return
try {
const res = await request.get(`/zgapi/v1/admin/user/${editId.value}/system`)
bindSystemIds.value = res.data ?? []
} catch { /* ignore */ }
}
async function onSystemChange(_val: string[]) {
// 用户取消勾选系统时,清除该系统下的角色选择
await saveSystems()
}
async function saveSystems() {
if (!editId.value) return
try {
await request.post(`/zgapi/v1/admin/user/${editId.value}/system`, bindSystemIds.value)
} catch { /* ignore */ }
}
// ===== 角色分配 =====
const roleSystemId = ref<string>()
const assignRoleIds = ref<string[]>([])
const currentRoleList = ref<any[]>([])
async function onRoleSystemChange(sysId: string | undefined) {
assignRoleIds.value = []
if (!sysId) { currentRoleList.value = []; return }
// 加载该系统下的角色列表
try {
const res = await request.post('/zgapi/v1/admin/role/page', { page: 1, pageSize: 999, systemId: sysId })
currentRoleList.value = res.data?.records ?? []
} catch {
currentRoleList.value = []
}
// 加载用户在该系统下的已有角色
if (!editId.value) return
try {
const res = await request.get(`/zgapi/v1/admin/user/${editId.value}/role/${sysId}`)
assignRoleIds.value = res.data ?? []
} catch { /* ignore */ }
}
async function saveRoles() {
if (!editId.value || !roleSystemId.value) return
try {
await request.post(`/zgapi/v1/admin/user/${editId.value}/role`, assignRoleIds.value, {
params: { systemId: roleSystemId.value }
})
ElMessage.success('角色已保存')
} catch { /* ignore */ }
}
// ===== 加载与提交 =====
async function loadData() {
const id = route.params.id as string
if (!id) { isEdit.value = false; return }
isEdit.value = true
editId.value = id
try {
const res = await request.get(`/zgapi/v1/admin/user/${editId.value}`)
const data = res.data
if (data) {
Object.assign(form, {
username: data.username ?? '',
realName: data.realName ?? '',
email: data.email ?? '',
phone: data.phone ?? '',
post: data.post ?? '',
password: '',
status: data.status ?? 1,
})
setTimeout(() => formRef.value?.clearValidate(), 0)
}
} catch {
ElMessage.error('加载用户信息失败')
router.back()
}
}
function handleBack() { router.back() }
async function handleSubmit() {
const valid = await formRef.value?.validate().catch(() => false)
if (!valid) return
submitLoading.value = true
try {
const payload: any = {
username: form.username,
realName: form.realName,
email: form.email,
phone: form.phone,
post: form.post,
status: form.status,
}
if (isEdit.value) {
await request.put('/zgapi/v1/admin/user', { ...payload, id: editId.value })
// 保存系统绑定
await saveSystems()
// 如果有选择角色系统,保存角色
if (roleSystemId.value) await saveRoles()
ElMessage.success('用户信息已保存')
} else {
await request.post('/zgapi/v1/admin/user', { ...payload, password: form.password })
ElMessage.success('新增成功')
}
router.back()
} catch (e: any) {
const msg = e?.response?.data?.msg || e?.message
if (msg && msg !== '请求失败') ElMessage.error(msg)
} finally {
submitLoading.value = false
}
}
onMounted(async () => {
await fetchAllSystems()
await loadData()
if (isEdit.value) {
await fetchUserSystems()
}
})
</script>
<style scoped>
.form-page { display:flex; flex-direction:column; }
:deep(.el-page-header) { margin-bottom:4px; }
:deep(.el-page-header + .el-divider) { margin:0 0 20px; }
.form-card { max-width:860px; margin:0 auto; width:100%; }
.section-label { font-size:15px; font-weight:600; color:var(--text-primary); }
.hint-text { font-size:13px; color:var(--text-muted); margin-bottom:16px; }
.form-footer { display:flex; justify-content:flex-end; gap:12px; }
@media (max-width: 768px) {
.form-card { max-width: 100%; padding: 0 8px; }
.form-footer { flex-direction: column; }
.form-footer .el-button { width: 100%; }
}
</style>