人员列表

This commit is contained in:
2026-07-01 14:59:56 +08:00
parent e9c9dcd9c5
commit 019d09df3e
5 changed files with 506 additions and 0 deletions

View File

@ -0,0 +1,45 @@
import { request } from '@/api';
import type {
WorkerListResponse,
WorkerFormParams,
EditWorkerParams,
WorkerRoleOption,
WorkerRoleOptionResponse,
} from '@/api/types/system/worker.d';
/**
*
* @param params
* @returns Promise<WorkerListResponse>
*/
export async function getWorkerListApi(params: { username?: string } = {}): Promise<WorkerListResponse> {
return request.get<WorkerListResponse>('/worker/getWorkerList', params);
}
/**
*
* @returns Promise<WorkerRoleOptionResponse>
*/
export async function getWorkerRoleIdOptionApi(): Promise<WorkerRoleOptionResponse> {
return request.get<WorkerRoleOptionResponse>('/worker/getWorkerRoleIdOptions', undefined, { showMessage: false });
}
/**
*
* @param params usernameemailrole_id
* @returns Promise<void>
*/
export async function addWorkerApi(params: WorkerFormParams): Promise<void> {
return request.post<void>('/worker/addWorker', params);
}
/**
*
* @param params user_idusernameemailstatus
* @returns Promise<void>
*/
export async function editWorkerApi(params: EditWorkerParams): Promise<void> {
return request.post<void>('/worker/editWorker', params, { showMessage: false });
}
export type { WorkerRoleOption };

49
src/api/types/system/worker.d.ts vendored Normal file
View File

@ -0,0 +1,49 @@
import type { ApiResponse } from '../index';
/** 员工角色信息 */
export interface WorkerRoleInfo {
id: number;
title: string;
}
/** 员工列表单条数据 */
export interface WorkerItem {
id: number;
username: string;
email: string;
role_id: number;
status: number; // 1:正常 2:封禁
created_at: string;
role: WorkerRoleInfo;
}
/** 员工列表响应 */
export type WorkerListResponse = WorkerItem[];
/** 员工角色下拉选项 */
export interface WorkerRoleOption {
id: number;
title: string;
}
/** 员工角色下拉选项响应 */
export type WorkerRoleOptionResponse = WorkerRoleOption[];
/** 新增员工表单参数 */
export interface WorkerFormParams {
username: string;
email: string;
role_id: number | null;
}
/** 编辑员工表单参数 */
export interface EditWorkerParams {
user_id: number;
username: string;
email: string;
status: number; // 1:正常 2:封禁
}
/** 接口返回结构(兼容 data 包裹场景) */
export interface WorkerListApiResponse extends ApiResponse<WorkerItem[]> {}
export interface WorkerRoleOptionApiResponse extends ApiResponse<WorkerRoleOption[]> {}

View File

@ -0,0 +1,285 @@
<template>
<div class="system table_form-container">
<!-- 搜索 -->
<WorkerSearch
:search-form="searchForm"
:buttonLoading="loading"
:search-options="searchOptions"
@search="handleSearch"
@reset="handleReset"
>
<template #button>
<el-button type="primary" @click="handleAdd" v-auth="'worker_addWorker'">新增员工</el-button>
</template>
</WorkerSearch>
<!-- 表格 -->
<WorkerTable
:table-data="workerList"
:columns="tableColumnsOptions"
row-key="id"
:loading="loading"
>
<template #status="{ row }">
<el-tag :type="row.status === 1 ? 'success' : 'danger'">
{{ row.status === 1 ? '正常' : '封禁' }}
</el-tag>
</template>
<template #action="{ row }">
<el-button link type="primary" size="small" @click="handleEdit(row)" v-auth="'worker_editWorker'">
编辑
</el-button>
</template>
</WorkerTable>
<!-- 新增/编辑弹窗 -->
<WorkerDialog
:visible="dialogVisible"
:title="dialogTitle"
:type="dialogType"
:button-loading="submitLoading"
@confirm="handleSubmit"
@cancel="handleCancel"
@close="handleClose"
>
<WorkerForm
:form-data="workerForm"
:form-rules="workerFormRules"
:form-items="workerFormItemOptions"
:options-map="workerFormOptionsMap"
ref="workerFormRef"
:key="formKey"
/>
</WorkerDialog>
</div>
</template>
<script setup lang="ts">
defineOptions({
name: 'Worder'
})
import type { FormInstance } from 'element-plus'
import { usePageLoading, useButtonLoading } from '@/composables/useLoading'
const { loading, startLoading, stopLoading } = usePageLoading()
const { buttonLoading: submitLoading, startButtonLoading: startSubmitLoading, stopButtonLoading: stopSubmitLoading } = useButtonLoading()
//
import WorkerSearch from '@/components/common/Search.vue'
import WorkerTable from '@/components/common/Table.vue'
import WorkerDialog from '@/components/common/Dialog.vue'
import WorkerForm from '@/components/common/Form.vue'
//
import { search, tableColumns, addFormItem, editFormItem } from './options'
import { addRules, editRules } from './rules'
//
import {
getWorkerListApi,
getWorkerRoleIdOptionApi,
addWorkerApi,
editWorkerApi,
} from '@/api/modules/system/worker'
/**
* @description: 定义搜索数据
*/
const searchForm = ref({
username: '',
})
const searchOptions = ref(search)
/**
* @description: 定义表格数据
*/
const workerList = ref<any[]>([])
const tableColumnsOptions = ref(tableColumns)
/**
* @description: 定义弹窗数据
*/
const dialogVisible = ref(false)
const dialogTitle = ref('')
const dialogType = ref<'add' | 'edit'>('add')
//
const formKey = ref(0)
/**
* @description: 定义表单数据
*/
const workerForm = ref<any>({
user_id: 0,
username: '',
email: '',
role_id: null as number | null,
status: 1,
})
const workerFormRef = ref<FormInstance>()
const workerFormRules = ref<any>({})
const workerFormItemOptions = ref<any[]>([])
// /
const workerFormOptionsMap = ref<Record<string, { label: string; value: number }[]>>({
role_id: [],
status: [
{ label: '正常', value: 1 },
{ label: '封禁', value: 2 },
],
})
/**
* @description: 角色下拉数据加载
*/
const fetchRoleOptions = async () => {
try {
const data: any = await getWorkerRoleIdOptionApi()
const list = Array.isArray(data) ? data : (data?.data || [])
workerFormOptionsMap.value.role_id = list.map((item: any) => ({
label: item.title,
value: item.id,
}))
} catch (err) {
console.error('获取员工角色选项失败', err)
}
}
/**
* @description: 获取员工列表
*/
const fetchWorkerList = async () => {
startLoading()
try {
const params: any = {
username: searchForm.value.username || undefined,
}
const data: any = await getWorkerListApi(params)
const list = Array.isArray(data) ? data : (data?.data || [])
workerList.value = list.map((item: any) => ({
...item,
roleTitle: item.role?.title || '-',
}))
} catch (err) {
console.error('获取员工列表失败', err)
} finally {
stopLoading()
}
}
/**
* @description: 页面挂载
*/
onMounted(async () => {
await Promise.all([fetchRoleOptions(), fetchWorkerList()])
})
/**
* @description: 搜索 / 重置
*/
const handleSearch = () => {
fetchWorkerList()
}
const handleReset = () => {
searchForm.value = { username: '' }
fetchWorkerList()
}
/**
* @description: 新增
* 入参字段emailrole_id
*/
const handleAdd = () => {
dialogVisible.value = true
dialogTitle.value = '新增员工'
dialogType.value = 'add'
workerFormItemOptions.value = addFormItem as any
workerFormRules.value = addRules()
formKey.value++
workerForm.value = {
user_id: 0,
email: '',
role_id: null,
}
}
/**
* @description: 编辑
* 入参字段usernameemailstatus
*/
const handleEdit = (row: any) => {
dialogVisible.value = true
dialogTitle.value = '编辑员工'
dialogType.value = 'edit'
workerFormItemOptions.value = editFormItem as any
workerFormRules.value = editRules()
formKey.value++
workerForm.value = {
user_id: row.id,
username: row.username,
email: row.email,
status: row.status,
}
}
/**
* @description: 提交表单
*/
const handleSubmit = async () => {
startSubmitLoading()
try {
await workerFormRef.value?.validate()
if (dialogType.value === 'add') {
const params = {
email: workerForm.value.email,
role_id: workerForm.value.role_id,
}
await addWorkerApi(params)
ElNotification({
message: '新增成功',
type: 'success',
duration: 2000,
customClass: 'global-notification',
})
} else {
const params = {
user_id: workerForm.value.user_id,
username: workerForm.value.username,
email: workerForm.value.email,
status: workerForm.value.status,
}
await editWorkerApi(params)
ElNotification({
message: '编辑成功',
type: 'success',
duration: 2000,
customClass: 'global-notification',
})
}
dialogVisible.value = false
await fetchWorkerList()
} catch (err: any) {
if (err?.message) {
ElNotification({
message: err.message || '操作失败',
type: 'error',
duration: 2000,
customClass: 'global-notification',
})
}
} finally {
stopSubmitLoading()
}
}
/**
* @description: 取消 / 关闭弹窗
*/
const handleCancel = () => {
dialogVisible.value = false
}
const handleClose = () => {
dialogVisible.value = false
}
</script>
<style scoped lang="scss"></style>

View File

@ -0,0 +1,73 @@
/**
* @description:
*/
export const search = [
{
prop: 'username',
label: '用户名',
type: 'input' as const,
placeholder: '请输入用户名',
width: '220px',
},
]
/**
* @description:
*/
export const tableColumns = [
{ prop: 'username', label: '用户名' },
{ prop: 'email', label: '邮箱' },
{ prop: 'roleTitle', label: '角色' },
{ slotName: 'status', label: '状态' },
{ prop: 'created_at', label: '创建时间' },
{ slotName: 'action', label: '操作' },
]
/**
* @description:
* emailrole_id
*/
export const addFormItem = [
{
prop: 'email',
label: '邮箱',
type: 'input' as const,
placeholder: '请输入邮箱',
required: true,
},
{
prop: 'role_id',
label: '角色',
type: 'select' as const,
placeholder: '请选择角色',
required: true,
},
]
/**
* @description:
* usernameemailstatus
*/
export const editFormItem = [
{
prop: 'username',
label: '用户名',
type: 'input' as const,
placeholder: '请输入用户名',
required: true,
},
{
prop: 'email',
label: '邮箱',
type: 'input' as const,
placeholder: '请输入邮箱',
required: true,
},
{
prop: 'status',
label: '状态',
type: 'radio' as const,
placeholder: '请选择状态',
required: true,
},
]

View File

@ -0,0 +1,54 @@
import type { FormRules } from 'element-plus'
/** 邮箱格式校验 */
const emailValidator = (rule: any, value: any, callback: any) => {
if (!value) {
callback()
return
}
const emailReg = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$/
if (!emailReg.test(value)) {
callback(new Error('邮箱格式不正确'))
return
}
callback()
}
/**
* @description:
* emailrole_id
*/
export const addRules = (): FormRules => {
return {
email: [
{ required: true, message: '请输入邮箱', trigger: 'blur' },
{ validator: emailValidator, trigger: 'blur' },
],
role_id: [
{ required: true, message: '请选择角色', trigger: 'change' },
],
}
}
/**
* @description:
* usernameemailstatus
*/
export const editRules = (): FormRules => {
return {
username: [
{ required: true, message: '请输入用户名', trigger: 'blur' },
{ min: 2, max: 50, message: '用户名长度在 2 到 50 个字符', trigger: 'blur' },
],
email: [
{ required: true, message: '请输入邮箱', trigger: 'blur' },
{ validator: emailValidator, trigger: 'blur' },
],
status: [
{ required: true, message: '请选择状态', trigger: 'change' },
],
}
}
/** 兼容旧引用 */
export const rules = (): FormRules => editRules()