ci/woodpecker/push/main Pipeline failed
- 39+ 页删除与布局标题同名/基本同名的页面内 h1-h4(同屏三标题→两处) - 增量副标题弱化为 14px #64748B 小字:收付款计划/战略回顾/地图版本/会计科目打标 - 标题 emoji 清零,保留标题处改 Lucide 内联 SVG(bar-chart-3/video/scale/clipboard-list/alert-circle/map/history) - KPIListView 增加 hideTitle(仅展示),客户/学习看板隐藏组件内重复页头 - 不动 MainLayout、不改接口/业务逻辑、不碰 MapCanvas.vue
143 lines
4.8 KiB
Vue
143 lines
4.8 KiB
Vue
<template>
|
||
<div class="user-page">
|
||
<div class="page-top">
|
||
<el-button type="primary" @click="openForm(null)">新建用户</el-button>
|
||
</div>
|
||
<el-table :data="users" v-loading="loading" class="full-width-table" border stripe>
|
||
<el-table-column prop="id" label="ID" width="60" />
|
||
<el-table-column prop="username" label="用户名" width="120" />
|
||
<el-table-column prop="name" label="姓名" width="120" />
|
||
<el-table-column prop="role" label="角色" width="120">
|
||
<template #default="{ row }">
|
||
<el-tag :type="roleType(row.role)" size="small">{{ roleLabel(row.role) }}</el-tag>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column prop="phone" label="手机号" width="140" />
|
||
<el-table-column prop="created_at" label="创建时间" width="180" />
|
||
<el-table-column label="操作" width="160" fixed="right">
|
||
<template #default="{ row }">
|
||
<el-button size="small" @click="openForm(row)">编辑</el-button>
|
||
<el-button size="small" type="danger" @click="handleDelete(row)">删除</el-button>
|
||
</template>
|
||
</el-table-column>
|
||
</el-table>
|
||
|
||
<MyDialog v-model="showForm" :title="isEdit ? '编辑用户' : '新建用户'" :width="480">
|
||
<el-form :model="form" label-width="80px">
|
||
<el-form-item label="用户名">
|
||
<el-input v-model="form.username" :disabled="isEdit" />
|
||
</el-form-item>
|
||
<el-form-item label="姓名">
|
||
<el-input v-model="form.name" />
|
||
</el-form-item>
|
||
<el-form-item :label="isEdit ? '新密码' : '密码'">
|
||
<el-input v-model="form.password" type="password" show-password
|
||
:placeholder="isEdit ? '留空则不修改' : '请输入密码'" />
|
||
</el-form-item>
|
||
<el-form-item label="角色">
|
||
<el-select v-model="form.role" style="width:100%">
|
||
<el-option label="CEO" value="ceo" />
|
||
<el-option label="财务" value="finance" />
|
||
<el-option label="业务" value="business" />
|
||
<el-option label="IT" value="it" />
|
||
</el-select>
|
||
</el-form-item>
|
||
<el-form-item label="手机号">
|
||
<el-input v-model="form.phone" />
|
||
</el-form-item>
|
||
</el-form>
|
||
<template #footer>
|
||
<el-button @click="showForm=false">取消</el-button>
|
||
<el-button type="primary" :loading="saving" @click="saveUser">保存</el-button>
|
||
</template>
|
||
</MyDialog>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
import { ref, onMounted } from 'vue'
|
||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||
import { userApi } from '../api/index'
|
||
import MyDialog from '../components/MyDialog.vue'
|
||
|
||
const users = ref<any[]>([])
|
||
const loading = ref(false)
|
||
const showForm = ref(false)
|
||
const isEdit = ref(false)
|
||
const form = ref<any>({})
|
||
const saving = ref(false)
|
||
|
||
function roleLabel(role: string) {
|
||
const map: Record<string, string> = { ceo: 'CEO', finance: '财务', business: '业务', it: 'IT管理' }
|
||
return map[role] || role
|
||
}
|
||
function roleType(role: string) {
|
||
const map: Record<string, string> = { ceo: 'danger', finance: 'success', business: 'warning', it: 'info' }
|
||
return map[role] || ''
|
||
}
|
||
|
||
async function load() {
|
||
loading.value = true
|
||
try { const r: any = await userApi.list(); users.value = r.data || [] } catch (e) {}
|
||
loading.value = false
|
||
}
|
||
|
||
function openForm(row: any) {
|
||
if (row) {
|
||
isEdit.value = true
|
||
form.value = { ...row, password: '' }
|
||
} else {
|
||
isEdit.value = false
|
||
form.value = { username: '', name: '', password: '', role: 'business', phone: '' }
|
||
}
|
||
showForm.value = true
|
||
}
|
||
|
||
async function saveUser() {
|
||
if (saving.value) return
|
||
saving.value = true
|
||
try {
|
||
if (isEdit.value) {
|
||
const payload: any = {}
|
||
if (form.value.name) payload.name = form.value.name
|
||
if (form.value.password) payload.password = form.value.password
|
||
if (form.value.role) payload.role = form.value.role
|
||
if (form.value.phone !== undefined) payload.phone = form.value.phone
|
||
await userApi.update(form.value.id, payload)
|
||
ElMessage.success('已更新')
|
||
} else {
|
||
if (!form.value.username || !form.value.password) {
|
||
ElMessage.warning('用户名和密码必填')
|
||
saving.value = false
|
||
return
|
||
}
|
||
await userApi.create(form.value)
|
||
ElMessage.success('创建成功')
|
||
}
|
||
showForm.value = false
|
||
load()
|
||
} catch (e) {
|
||
ElMessage.error('操作失败')
|
||
} finally {
|
||
saving.value = false
|
||
}
|
||
}
|
||
|
||
async function handleDelete(row: any) {
|
||
try {
|
||
await ElMessageBox.confirm(`确定删除用户"${row.name}"?`, '确认')
|
||
await userApi.delete(row.id)
|
||
ElMessage.success('已删除')
|
||
load()
|
||
} catch (e) {}
|
||
}
|
||
|
||
onMounted(load)
|
||
</script>
|
||
|
||
<style scoped>
|
||
.user-page { }
|
||
.user-page .page-top { display: flex; justify-content: space-between; margin-bottom: 16px; }
|
||
.user-page .page-top h3 { margin: 0; }
|
||
</style>
|