You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
haoliang-net/frontend/src/views/worker/WorkerListPage.vue

100 lines
7.3 KiB
Vue

<template>
<div>
<div class="mb-16"><el-button type="primary" @click="handleAdd">+ </el-button></div>
<el-form :inline="true" class="mb-16">
<el-form-item label="状态"><el-select v-model="query.isEnabled" clearable><el-option label="启用" :value="1"/><el-option label="停用" :value="0"/></el-select></el-form-item>
<el-form-item><el-input v-model="query.keyword" placeholder="工号/姓名" clearable/></el-form-item>
<el-form-item><el-button type="primary" @click="loadData">查询</el-button><el-button @click="resetQuery">重置</el-button></el-form-item>
</el-form>
<el-table :data="tableData" border stripe v-loading="loading">
<el-table-column type="selection" width="40"/>
<el-table-column prop="code" label="工号" width="120"/>
<el-table-column prop="name" label="姓名" width="120"><template #default="{row}"><el-link type="primary" @click="goDetail(row.id)">{{row.name}}</el-link></template></el-table-column>
<el-table-column label="状态" width="80" align="center"><template #default="{row}"><el-tag :type="row.isEnabled?'success':'danger'" size="small">{{row.isEnabled?'启用':'停用'}}</el-tag></template></el-table-column>
<el-table-column prop="machineCount" label="绑定机床数" width="100" align="center"/>
<el-table-column prop="machineNames" label="绑定机床" show-overflow-tooltip/>
<el-table-column label="操作" width="120" align="center"><template #default="{row}">
<el-button link type="primary" @click="handleEdit(row)">编辑</el-button>
<el-button link type="danger" @click="handleDelete(row)" :disabled="row.machineCount>0">删除</el-button>
</template></el-table-column>
</el-table>
<div v-if="selectedRows.length" style="margin-top:12px;padding:8px 12px;background:#ecf5ff;border-radius:4px">
已选{{selectedRows.length}}项 <el-button size="small" @click="batchStatus(1)">批量启用</el-button><el-button size="small" @click="batchStatus(0)">批量停用</el-button>
</div>
<!-- 分页控件 -->
<div style="margin-top:12px;display:flex;justify-content:flex-end;align-items:center">
<el-pagination
:total="pagination.total"
:page-size="pagination.pageSize"
:page-sizes="[20, 50, 100]"
layout="total, sizes, prev, pager, next, jumper"
:current-page="pagination.currentPage"
@current-change="handlePageChange"
@size-change="handleSizeChange"
/>
</div>
<el-dialog v-model="dialogVisible" :title="editingId?'编辑工人':'新增工人'" width="500px" destroy-on-close>
<el-form :model="form" :rules="rules" ref="workerForm" label-width="100px">
<el-form-item label="工号" prop="code">
<el-input v-model="form.code" maxlength="50" @blur="()=>workerForm?.validateField('code')"/>
</el-form-item>
<el-form-item label="姓名" prop="name">
<el-input v-model="form.name" maxlength="50"/>
</el-form-item>
<el-form-item label="绑定机床" prop="machineIds">
<el-select v-model="form.machineIds" multiple filterable>
<el-option v-for="m in availableMachines" :key="m.id" :label="m.name" :value="m.id"/>
</el-select>
</el-form-item>
</el-form>
<template #footer><el-button @click="dialogVisible=false">取消</el-button><el-button type="primary" :loading="submitting" @click="handleSubmit">保存</el-button></template>
</el-dialog>
</div>
</template>
<script setup lang="ts">
import {ref, reactive,onMounted} from 'vue'
import {useRouter} from 'vue-router'
import {ElMessage,ElMessageBox} from 'element-plus'
import request from '@/utils/request'
import type { FormInstance, FormRules } from 'element-plus'
import {useMockMode} from '@/composables/useMockMode'
import type { ApiResponse, Worker, Workshop, CollectAddress } from '@/types'
const router=useRouter();const{isMock}=useMockMode()
const loading=ref(false);const tableData=ref<Worker[]>([]);const selectedRows=ref<Worker[]>([])
// 分页信息
const pagination=ref<{ currentPage: number; pageSize: number; total: number }>({ currentPage: 1, pageSize: 20, total: 0 })
const dialogVisible=ref(false);const submitting=ref(false);const editingId=ref<number|null>(null)
const availableMachines=ref<{ id: number; name: string }[]>([])
const query=reactive({isEnabled:undefined as number | undefined,keyword:''})
const form=reactive({code:'',name:'',machineIds:[] as number[]})
const workerForm=ref<FormInstance | null>(null)
// 工号唯一性校验规则
const rules=reactive({
code: [] as any[],
})
function validateWorkerCode(rule: unknown, value: string, callback: (err?:Error)=>void){
const v = (value ?? '').toString().trim()
if(!v){ callback(new Error('工号为必填项')) ; return }
// 新增模式下检查重复
if(editingId.value === null){
const exists = tableData.value.some((r:any)=> r.code === v)
if(exists){ callback(new Error('该工号已存在')) ; return }
}
callback()
}
// 将校验函数挂载到 rules
rules.code = [{ validator: validateWorkerCode, trigger: 'blur' }]
function resetQuery(){query.isEnabled=undefined;query.keyword='';loadData()}
function goDetail(id:number){router.push((isMock.value?'/mock/worker/':'/worker/')+id)}
async function loadData(){loading.value=true;try{const ps=pagination.value.pageSize;const cp=pagination.value.currentPage;const r: ApiResponse<{ items: Worker[]; total?: number }> = await request.get('/admin/worker',{params:{...query,page:cp,pageSize:ps}});tableData.value=r.data?.items||[];pagination.value.total= r.data?.total ?? (r.data?.items?.length ?? 0)}finally{loading.value=false}}
function handleAdd(){editingId.value=null;Object.assign(form,{code:'',name:'',machineIds:[]});dialogVisible.value=true}
function handleEdit(row: Worker){editingId.value=row.id;Object.assign(form,{code:row.code,name:row.name,machineIds:row.machines?.map(m=>m.id)||[]});dialogVisible.value=true}
async function handleSubmit(){submitting.value=true;try{const ok = await (workerForm.value?.validate ? new Promise<boolean>((resolve)=>workerForm.value!.validate((valid:boolean)=>resolve(valid))) : Promise.resolve(true)); if(!ok){return} await request.post(editingId.value?'/admin/worker/update':'/admin/worker',{...form,id:editingId.value});ElMessage.success('保存成功');dialogVisible.value=false;loadData()}finally{submitting.value=false}}
async function handleDelete(row:any){await ElMessageBox.confirm('确定删除【'+row.name+'】?此操作不可恢复。','提示',{type:'warning'});await request.post('/admin/worker/delete',{id:row.id});ElMessage.success('已删除');loadData()}
async function batchStatus(isEnabled:number){await ElMessageBox.confirm('确定对选中的'+selectedRows.value.length+'项操作?','提示',{type:'warning'});await request.post('/admin/worker/batch-status',{ids:selectedRows.value.map((r:any)=>r.id),isEnabled});ElMessage.success('操作成功');loadData()}
async function loadDrops(){const r: ApiResponse<{ items: Array<{ id: number; name: string }> }> = await request.get('/admin/worker/available-machines'); availableMachines.value = r.data?.items ?? []}
function handlePageChange(page:number){pagination.value.currentPage=page;loadData()}
function handleSizeChange(size:number){pagination.value.pageSize=size;pagination.value.currentPage=1;loadData()}
onMounted(()=>{loadData();loadDrops()})
</script>