Files
sbu4pe/src/views/equipment/Testers.vue
2025-08-15 12:47:58 +00:00

1000 lines
32 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<script setup>
import { ref, onMounted, reactive, nextTick } from 'vue'
import {
ElTable,
ElTableColumn,
ElInput,
ElButton,
ElMessage,
ElDialog,
ElForm,
ElFormItem,
ElSelect,
ElOption
} from 'element-plus'
import { useRouter } from 'vue-router'
import crypto from '@/utils/crypto';
import request from '@/utils/api'
import ApiPaths from '@/utils/api/api.js';
// =============== 数据定义 ===============
const router = useRouter()
// 当前用户权限组 ID
const currentUserGid = ref(localStorage.getItem('user_gid') || 'guest')
// 表格数据
const tableData = ref([])
const loading = ref(false)
const keyword = ref('')
// 分页
const pagination = ref({
currentPage: 1,
pageSize: 25,
total: 0
})
// 权限控制
const hasCreatePermission = ref(false)
const hasUpdatePermission = ref(false)
// 关联数据列表(下拉选择用)
const brandList = ref([]) // 品牌列表
const customerList = ref([]) // 客户列表
const sourceTypeList = ref([]) // 来源类型列表
const otherSourceList = ref([]) // 其它来源类型列表
const statusList = ref([]) // 状态列表
const locationList = ref([]) // 位置列表
const departmentList = ref([]) // 部门列表
const userList = ref([]) // 负责人列表
// 编辑弹窗相关
const editDialogVisible = ref(false)
const currentEditRow = ref(null)
const userSelectRef = ref(null) // 负责人选择器引用
const editForm = reactive({
id: null,
mhname: '', // 机柜名称
cms_sn: '', // 管理编号
brand_id: null, // 品牌ID关联
model: '', // 型号
sn: '', // 序列号
source_type_id: null,// 来源类型ID关联
other_source_id: null,// 其它来源ID (关联)
customer_id: null, // 客户ID关联
status_id: null, // 状态ID关联
location_id: null, // 位置ID关联
department_id: null, // 部门ID关联
user_id: null, // 负责人ID关联
remark: '' // 备注
})
const editFormRules = reactive({
mhname: [{ required: true, message: '请输入机柜名称', trigger: 'blur' }],
cms_sn: [{ required: true, message: '请输入管理编号', trigger: 'blur' }],
brand_id: [{ required: true, message: '请选择品牌', trigger: 'change' }],
model: [{ required: true, message: '请输入型号', trigger: 'blur' }],
sn: [{ required: true, message: '请输入序列号', trigger: 'blur' }],
source_type_id: [{ required: true, message: '请选择来源类型', trigger: 'change' }],
other_source_id: [{ required: true, message: '请选择其它来源类型', trigger: 'change' }],
customer_id: [{ required: true, message: '请选择客户', trigger: 'change' }],
status_id: [{ required: true, message: '请选择状态', trigger: 'change' }],
location_id: [{ required: true, message: '请选择位置', trigger: 'change' }],
department_id: [{ required: true, message: '请选择部门', trigger: 'change' }],
user_id: [
{ required: true, message: '请选择负责人', trigger: 'change' },
{
validator: (rule, value, callback) => {
const numericValue = Number(value);
const exists = userList.value.some(user => user.id === numericValue);
if (exists || (typeof value === 'string' && value.trim() !== '')) {
callback();
} else {
callback(new Error(`选择的负责人ID ${value} 不存在于列表中,请重新选择`));
}
},
trigger: 'change'
}
]
})
// 新增弹窗相关
const createDialogVisible = ref(false)
const createForm = reactive({
mhname: '', // 机柜名称
cms_sn: '', // 管理编号
brand_id: null, // 品牌ID关联
model: '', // 型号
sn: '', // 序列号
source_type_id: null,// 来源类型ID关联
other_source_id: null,// 其它来源ID (关联)
customer_id: null, // 客户ID关联
status_id: null, // 状态ID关联
location_id: null, // 位置ID关联
department_id: null, // 部门ID关联
user_id: null, // 负责人ID关联
remark: '' // 备注
})
// 新增表单验证规则(与编辑相同)
const createFormRules = reactive({...editFormRules})
// 列定义(与后端返回字段严格匹配)
const columns = [
{ prop: 'ctmname', label: '客户', width: 120 },
{ prop: 'cms_sn', label: '管理编号', width: 130 },
{ prop: 'mhname', label: '机柜名称', width: 140 },
{ prop: 'brandname', label: '品牌', width: 120 },
{ prop: 'model', label: '型号', width: 110 },
{ prop: 'sn', label: '序列号', width: 150 },
{ prop: 'statusname', label: '状态', width: 100 },
{ prop: 'remark', label: '备注' }
]
// =============== 方法定义 ===============
// 用户ID获取函数
const getCurrentUserId = () => {
try {
const encryptedUserInfo = localStorage.getItem('userInfo');
if (!encryptedUserInfo) {
console.warn('未找到用户信息,可能未登录');
return null;
}
const decryptedInfo = crypto.decrypt(encryptedUserInfo);
const userData = JSON.parse(decryptedInfo);
const userId = userData?.userId ? Number(userData.userId) : null;
if (!userId || isNaN(userId)) {
console.warn('用户ID格式无效');
return null;
}
return userId;
} catch (error) {
console.error('获取用户ID失败:', error.message);
return null;
}
};
// 检查权限
const checkPermission = (action) => {
const authorizedGroups = ['1', '6'];
const hasBasePermission = authorizedGroups.includes(currentUserGid.value);
const actionPermissions = {
create_machine: hasBasePermission,
update_machine: hasBasePermission
};
return actionPermissions[action] || false;
};
// 加载用户列表
const fetchUserList = async () => {
try {
const usersRes = await request.get(ApiPaths.user.list);
if (usersRes.code === 200 && Array.isArray(usersRes.data)) {
const uniqueUsers = [];
const seenIds = new Set();
usersRes.data.forEach(user => {
const numericId = Number(String(user.id).trim());
if (!isNaN(numericId) && !seenIds.has(numericId)) {
seenIds.add(numericId);
uniqueUsers.push({
...user,
id: numericId,
login_name: user.login_name || '未知用户'
});
}
});
userList.value = uniqueUsers;
} else {
throw new Error(`负责人接口返回错误: ${usersRes.message || '数据格式异常'}`);
}
} catch (error) {
console.error('负责人数据请求失败:', error);
ElMessage.warning('加载负责人数据失败: ' + error.message);
}
};
// 获取关联数据列表
const fetchRelatedData = async () => {
try {
await fetchUserList();
// 1. 品牌数据
const brandsRes = await request.get(ApiPaths.brand.list);
if (typeof brandsRes !== 'object' || brandsRes === null || !('code' in brandsRes)) {
throw new Error('品牌接口返回格式异常');
}
if (brandsRes.code === 200 && Array.isArray(brandsRes.data)) {
brandList.value = brandsRes.data.map(brand => ({
...brand,
id: Number(brand.id),
name: brand.name || '未知品牌'
}));
} else {
throw new Error(`品牌接口返回错误: ${brandsRes.message || '未知错误'}`);
}
// 2. 客户数据
try {
const customersRes = await request.get(ApiPaths.customer.list);
if (customersRes.code === 200 && Array.isArray(customersRes.data)) {
customerList.value = customersRes.data.map(customer => ({
...customer,
id: Number(customer.id),
name: customer.name || '未知客户'
}));
} else {
throw new Error(`客户接口返回错误: ${customersRes.message || '数据格式异常'}`);
}
} catch (error) {
console.error('客户数据请求失败:', error);
ElMessage.warning('加载客户数据失败: ' + error.message);
}
// 3. 来源类型数据
try {
const sourceTypesRes = await request.get(ApiPaths.sourceType.list);
if (sourceTypesRes.code === 200 && Array.isArray(sourceTypesRes.data)) {
sourceTypeList.value = sourceTypesRes.data.map(type => ({
...type,
id: Number(type.id),
name: type.name || '未知类型'
}));
} else {
throw new Error(`来源类型接口返回错误: ${sourceTypesRes.message || '数据格式异常'}`);
}
} catch (error) {
console.error('来源类型数据请求失败:', error);
ElMessage.warning('加载来源类型数据失败: ' + error.message);
}
// 4. 状态数据
try {
const statusesRes = await request.get(ApiPaths.status.list);
if (statusesRes.code === 200 && Array.isArray(statusesRes.data)) {
statusList.value = statusesRes.data.map(status => ({
...status,
id: Number(status.id),
name: status.name || '未知状态'
}));
} else {
throw new Error(`状态接口返回错误: ${statusesRes.message || '数据格式异常'}`);
}
} catch (error) {
console.error('状态数据请求失败:', error);
ElMessage.warning('加载状态数据失败: ' + error.message);
}
// 5. 位置数据
try {
const locationsRes = await request.get(ApiPaths.location.list);
if (locationsRes.code === 200 && Array.isArray(locationsRes.data)) {
locationList.value = locationsRes.data.map(location => ({
...location,
id: Number(location.id),
name: location.name || '未知位置'
}));
} else {
throw new Error(`位置接口返回错误: ${locationsRes.message || '数据格式异常'}`);
}
} catch (error) {
console.error('位置数据请求失败:', error);
ElMessage.warning('加载位置数据失败: ' + error.message);
}
// 6. 部门数据
try {
const departmentsRes = await request.get(ApiPaths.department.list);
if (departmentsRes.code === 200 && Array.isArray(departmentsRes.data)) {
departmentList.value = departmentsRes.data.map(dept => ({
...dept,
id: Number(dept.id),
name: dept.name || '未知部门'
}));
} else {
throw new Error(`部门接口返回错误: ${departmentsRes.message || '数据格式异常'}`);
}
} catch (error) {
console.error('部门数据请求失败:', error);
ElMessage.warning('加载部门数据失败: ' + error.message);
}
// 7. 其它来源数据
try {
const otherSourceRes = await request.get(ApiPaths.otherSource.list);
if (otherSourceRes.code === 200 && Array.isArray(otherSourceRes.data)) {
otherSourceList.value = otherSourceRes.data.map(source => ({
...source,
id: Number(source.id),
name: source.name || '未知来源'
}));
} else {
throw new Error(`其它来源接口返回错误: ${otherSourceRes.message || '数据格式异常'}`);
}
} catch (error) {
console.error('其它来源数据请求失败:', error);
ElMessage.warning('加载其它来源数据失败: ' + error.message);
}
} catch (error) {
ElMessage.error('加载品牌数据失败: ' + (error.message || '网络错误'));
console.error('品牌数据请求异常详情:', error);
}
};
// 获取仪器列表数据
const fetchData = async () => {
loading.value = true;
try {
const res = await request.postWithoutEncryption(
ApiPaths.machine.list,
{
range: 'machines',
keyword: keyword.value,
page: pagination.value.currentPage,
rows: pagination.value.pageSize
},
{
headers: {
'Content-Type': 'application/json',
Accept: 'application/json'
},
timeout: 10000
}
);
if (![0, 200].includes(res.code)) {
ElMessage.error(res.message || '请求失败');
tableData.value = [];
pagination.value.total = 0;
return;
}
const apiData = res.data;
if (!apiData || typeof apiData !== 'object') {
ElMessage.warning('数据格式异常');
tableData.value = [];
pagination.value.total = 0;
return;
}
tableData.value = Array.isArray(apiData.list) ? apiData.list : [];
pagination.value.total = Number(apiData.total) || 0;
if (tableData.value.length === 0 && pagination.value.total === 0) {
ElMessage.info('暂无数据');
}
} catch (error) {
ElMessage.error('数据加载失败: ' + (error.message || '网络错误'));
console.error('请求异常:', error);
tableData.value = [];
pagination.value.total = 0;
} finally {
loading.value = false;
}
};
// 搜索
const handleSearch = () => {
pagination.value.currentPage = 1;
fetchData();
};
// 回车搜索
const handleKeydown = (e) => {
if (e.key === 'Enter') handleSearch();
};
// 导出
const handleExport = () => {
window.open('/download.php?x=Machine List', '_blank');
};
// 打开新增弹窗
const handleCreate = async () => {
if (!hasCreatePermission.value) {
ElMessage.warning('无新增权限');
return;
}
// 确保关联数据已加载
if (userList.value.length === 0 || brandList.value.length === 0) {
ElMessage.info('正在加载关联数据...');
await fetchRelatedData();
}
// 重置表单
Object.keys(createForm).forEach(key => {
createForm[key] = key.includes('_id') ? null : '';
});
// 显示弹窗
nextTick(() => {
createDialogVisible.value = true;
});
};
// 保存新增设备
const handleSaveCreate = async () => {
try {
// 获取当前登录用户ID用于created_by
const currentUserId = getCurrentUserId();
if (!currentUserId) {
ElMessage.error('无法获取用户信息,请重新登录');
return;
}
// 准备提交数据
const submitData = {
...createForm,
user_id: !isNaN(Number(createForm.user_id)) ? Number(createForm.user_id) : createForm.user_id,
created_by: currentUserId, // 创建人
updated_by: currentUserId // 初始更新人也是创建人
};
const res = await request.postWithoutEncryption(
ApiPaths.machine.create, // 假设新增接口路径
submitData,
{
headers: {
'Content-Type': 'application/json'
}
}
);
if (![0, 200].includes(res.code)) {
ElMessage.error(res.message || '新增失败');
return;
}
// 刷新表格数据
ElMessage.success('新增成功');
createDialogVisible.value = false;
fetchData(); // 重新加载列表数据
} catch (error) {
ElMessage.error('新增失败: ' + (error.message || '网络错误'));
console.error('新增异常:', error);
}
};
// 打开编辑弹窗
const handleEdit = async (row) => {
if (!hasUpdatePermission.value) {
ElMessage.warning('无编辑权限');
return;
}
const originalUserId = row.user_id;
if (userList.value.length === 0) {
ElMessage.info('正在加载负责人数据...');
await fetchUserList();
}
currentEditRow.value = { ...row };
// 填充表单数据
editForm.id = row.id ? Number(row.id) : null;
editForm.mhname = row.mhname || '';
editForm.cms_sn = row.cms_sn || '';
editForm.brand_id = row.brand_id ? Number(row.brand_id) : null;
editForm.model = row.model || '';
editForm.sn = row.sn || '';
editForm.source_type_id = row.source_type_id ? Number(row.source_type_id) : null;
editForm.other_source_id = row.other_source_id ? Number(row.other_source_id) : null;
editForm.customer_id = row.customer_id ? Number(row.customer_id) : null;
editForm.status_id = row.status_id ? Number(row.status_id) : null;
editForm.location_id = row.location_id ? Number(row.location_id) : null;
editForm.department_id = row.department_id ? Number(row.department_id) : null;
editForm.remark = row.remark || '';
// 处理负责人ID匹配
const exactMatch = userList.value.find(u => u.id === Number(originalUserId));
if (exactMatch) {
editForm.user_id = exactMatch.id;
} else {
console.warn(`未找到ID为 ${originalUserId} 的负责人`);
editForm.user_id = originalUserId ? String(originalUserId) : null;
nextTick(() => {
ElMessage({
message: `警告未找到ID为 ${originalUserId} 的负责人,请从下拉列表重新选择`,
type: 'warning',
duration: 5000
});
});
}
nextTick(() => {
editDialogVisible.value = true;
});
};
// 保存编辑内容
const handleSaveEdit = async () => {
try {
const currentUserId = getCurrentUserId();
if (!currentUserId) {
ElMessage.error('无法获取用户信息,请重新登录');
return;
}
const submitData = {
...editForm,
updated_by: currentUserId,
user_id: !isNaN(Number(editForm.user_id)) ? Number(editForm.user_id) : editForm.user_id
};
const res = await request.postWithoutEncryption(
ApiPaths.machine.update,
submitData,
{
headers: {
'Content-Type': 'application/json'
}
}
);
if (![0, 200].includes(res.code)) {
ElMessage.error(res.message || '保存失败');
return;
}
// 更新表格数据
const index = tableData.value.findIndex(item => item.id === editForm.id);
if (index !== -1) {
const updatedRow = {
...tableData.value[index],
...editForm,
brandname: brandList.value.find(b => b.id === editForm.brand_id)?.name || '',
ctmname: customerList.value.find(c => c.id === editForm.customer_id)?.name || '',
statusname: statusList.value.find(s => s.id === editForm.status_id)?.name || '',
username: userList.value.find(u => u.id === Number(editForm.user_id))?.login_name || ''
};
tableData.value.splice(index, 1, updatedRow);
}
ElMessage.success('保存成功');
editDialogVisible.value = false;
} catch (error) {
ElMessage.error('保存失败: ' + (error.message || '网络错误'));
console.error('保存异常:', error);
}
};
// 双击编辑
const handleRowDblclick = (row) => {
handleEdit(row);
};
// 分页事件
const handleSizeChange = (size) => {
pagination.value.pageSize = size;
fetchData();
};
const handleCurrentChange = (page) => {
pagination.value.currentPage = page;
fetchData();
};
// =============== 生命周期 ===============
onMounted(() => {
document.title = '仪器管理';
// 检查权限
hasCreatePermission.value = checkPermission('create_machine');
hasUpdatePermission.value = checkPermission('update_machine');
// 初始加载数据
fetchRelatedData();
fetchData();
});
</script>
<template>
<div class="machine-list-container" style="width: 100%; padding: 10px; border-radius: 8px; background: #fff; box-sizing: border-box;">
<!-- 工具栏 -->
<div class="toolbar" style="margin-bottom: 5px; display: flex; align-items: center; justify-content: space-between">
<div style="display: flex; align-items: center; gap: 10px">
<el-input
v-model="keyword"
placeholder="客户/编号/型号/序列号"
style="width: 240px"
@keydown="handleKeydown"
clearable
/>
<el-button type="primary" @click="handleSearch">搜索</el-button>
<el-button @click="handleExport">导出</el-button>
</div>
<el-button
v-if="hasCreatePermission"
type="success"
@click="handleCreate"
>
新增测试柜
</el-button>
</div>
<!-- 表格 -->
<el-table
:data="tableData"
style="width: 100%"
height="calc(100vh - 180px)"
border
@row-dblclick="handleRowDblclick"
v-loading="loading"
>
<el-table-column type="index" :width="60" />
<el-table-column
v-for="col in columns"
:key="col.prop"
:prop="col.prop"
:label="col.label"
:width="col.width"
:show-overflow-tooltip="true"
/>
<!-- 编辑按钮列 -->
<el-table-column
label="操作"
width="80"
v-if="hasUpdatePermission"
>
<template #default="scope">
<el-button
type="text"
size="small"
@click="handleEdit(scope.row)"
>
编辑
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<div class="pagination" style="margin-top: 10px; text-align: right">
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="pagination.currentPage"
:page-sizes="[25, 50, 100]"
:page-size="pagination.pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="pagination.total"
/>
</div>
<!-- 编辑弹窗 -->
<el-dialog
title="编辑仪器信息"
v-model="editDialogVisible"
width="600px"
:close-on-click-modal="false"
>
<div class="dialog-content">
<el-form
:model="editForm"
:rules="editFormRules"
ref="editFormRef"
label-width="120px"
style="margin-top: 20px"
>
<el-form-item label="机柜名称" prop="mhname">
<el-input v-model="editForm.mhname" style="width: 100%" />
</el-form-item>
<el-form-item label="管理编号" prop="cms_sn">
<el-input v-model="editForm.cms_sn" style="width: 100%" />
</el-form-item>
<el-form-item label="品牌" prop="brand_id">
<el-select v-model="editForm.brand_id" placeholder="请选择品牌" style="width: 100%">
<el-option
v-for="brand in brandList"
:key="brand.id"
:label="brand.name"
:value="brand.id"
/>
</el-select>
</el-form-item>
<el-form-item label="型号" prop="model">
<el-input v-model="editForm.model" style="width: 100%" />
</el-form-item>
<el-form-item label="序列号" prop="sn">
<el-input v-model="editForm.sn" style="width: 100%" />
</el-form-item>
<el-form-item label="来源类型" prop="source_type_id">
<el-select v-model="editForm.source_type_id" placeholder="请选择来源类型" style="width: 100%">
<el-option
v-for="type in sourceTypeList"
:key="type.id"
:label="type.name"
:value="type.id"
/>
</el-select>
</el-form-item>
<el-form-item label="其它来源类型" prop="other_source_id">
<el-select v-model="editForm.other_source_id" placeholder="请选择其它来源类型" style="width: 100%" filterable>
<el-option
v-for="type in otherSourceList"
:key="type.id"
:label="type.name"
:value="type.id"
/>
</el-select>
</el-form-item>
<el-form-item label="客户" prop="customer_id">
<el-select v-model="editForm.customer_id" placeholder="请选择客户" style="width: 100%" filterable>
<el-option
v-for="customer in customerList"
:key="customer.id"
:label="customer.name"
:value="customer.id"
/>
</el-select>
</el-form-item>
<el-form-item label="状态" prop="status_id">
<el-select v-model="editForm.status_id" placeholder="请选择状态" style="width: 100%" filterable>
<el-option
v-for="status in statusList"
:key="status.id"
:label="status.name"
:value="status.id"
/>
</el-select>
</el-form-item>
<el-form-item label="位置" prop="location_id">
<el-select v-model="editForm.location_id" placeholder="请选择位置" style="width: 100%" filterable>
<el-option
v-for="location in locationList"
:key="location.id"
:label="location.name"
:value="location.id"
/>
</el-select>
</el-form-item>
<el-form-item label="负责人" prop="user_id">
<el-select
ref="userSelectRef"
v-model="editForm.user_id"
placeholder="请选择负责人"
style="width: 100%"
filterable
value-key="id"
>
<el-option
v-for="user in userList"
:label="`${user.login_name} : ${user.user_name}`"
:value="user.id"
:key="user.id"
/>
</el-select>
</el-form-item>
<el-form-item label="部门" prop="department_id">
<el-select v-model="editForm.department_id" placeholder="请选择部门" style="width: 100%" filterable>
<el-option
v-for="dept in departmentList"
:key="dept.id"
:label="dept.name"
:value="dept.id"
/>
</el-select>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input
v-model="editForm.remark"
style="width: 100%"
type="textarea"
rows="3"
placeholder="请输入备注信息"
/>
</el-form-item>
</el-form>
</div>
<template #footer>
<el-button @click="editDialogVisible = false">取消</el-button>
<el-button type="primary" @click="handleSaveEdit">保存</el-button>
</template>
</el-dialog>
<!-- 新增弹窗 -->
<el-dialog
title="新增仪器信息"
v-model="createDialogVisible"
width="600px"
:close-on-click-modal="false"
>
<div class="dialog-content">
<el-form
:model="createForm"
:rules="createFormRules"
ref="createFormRef"
label-width="120px"
style="margin-top: 20px"
>
<el-form-item label="机柜名称" prop="mhname">
<el-input v-model="createForm.mhname" style="width: 100%" />
</el-form-item>
<el-form-item label="管理编号" prop="cms_sn">
<el-input v-model="createForm.cms_sn" style="width: 100%" />
</el-form-item>
<el-form-item label="品牌" prop="brand_id">
<el-select v-model="createForm.brand_id" placeholder="请选择品牌" style="width: 100%">
<el-option
v-for="brand in brandList"
:key="brand.id"
:label="brand.name"
:value="brand.id"
/>
</el-select>
</el-form-item>
<el-form-item label="型号" prop="model">
<el-input v-model="createForm.model" style="width: 100%" />
</el-form-item>
<el-form-item label="序列号" prop="sn">
<el-input v-model="createForm.sn" style="width: 100%" />
</el-form-item>
<el-form-item label="来源类型" prop="source_type_id">
<el-select v-model="createForm.source_type_id" placeholder="请选择来源类型" style="width: 100%">
<el-option
v-for="type in sourceTypeList"
:key="type.id"
:label="type.name"
:value="type.id"
/>
</el-select>
</el-form-item>
<el-form-item label="其它来源类型" prop="other_source_id">
<el-select v-model="createForm.other_source_id" placeholder="请选择其它来源类型" style="width: 100%" filterable>
<el-option
v-for="type in otherSourceList"
:key="type.id"
:label="type.name"
:value="type.id"
/>
</el-select>
</el-form-item>
<el-form-item label="客户" prop="customer_id">
<el-select v-model="createForm.customer_id" placeholder="请选择客户" style="width: 100%" filterable>
<el-option
v-for="customer in customerList"
:key="customer.id"
:label="customer.name"
:value="customer.id"
/>
</el-select>
</el-form-item>
<el-form-item label="状态" prop="status_id">
<el-select v-model="createForm.status_id" placeholder="请选择状态" style="width: 100%" filterable>
<el-option
v-for="status in statusList"
:key="status.id"
:label="status.name"
:value="status.id"
/>
</el-select>
</el-form-item>
<el-form-item label="位置" prop="location_id">
<el-select v-model="createForm.location_id" placeholder="请选择位置" style="width: 100%" filterable>
<el-option
v-for="location in locationList"
:key="location.id"
:label="location.name"
:value="location.id"
/>
</el-select>
</el-form-item>
<el-form-item label="负责人" prop="user_id">
<el-select
v-model="createForm.user_id"
placeholder="请选择负责人"
style="width: 100%"
filterable
value-key="id"
>
<el-option
v-for="user in userList"
:label="`${user.login_name} : ${user.user_name}`"
:value="user.id"
:key="user.id"
/>
</el-select>
</el-form-item>
<el-form-item label="部门" prop="department_id">
<el-select v-model="createForm.department_id" placeholder="请选择部门" style="width: 100%" filterable>
<el-option
v-for="dept in departmentList"
:key="dept.id"
:label="dept.name"
:value="dept.id"
/>
</el-select>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input
v-model="createForm.remark"
style="width: 100%"
type="textarea"
rows="3"
placeholder="请输入备注信息"
/>
</el-form-item>
</el-form>
</div>
<template #footer>
<el-button @click="createDialogVisible = false">取消</el-button>
<el-button type="primary" @click="handleSaveCreate">保存</el-button>
</template>
</el-dialog>
</div>
</template>
<style scoped>
.machine-list-container {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
font-size: 14px;
box-sizing: border-box;
}
.toolbar {
background: #f5f7fa;
padding: 5px;
border-radius: 6px;
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
}
.el-table {
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
border-radius: 6px;
overflow: hidden;
}
.dialog-content {
max-height: 50vh;
overflow-y: auto;
padding-right: 10px;
}
.dialog-content::-webkit-scrollbar {
width: 6px;
}
.dialog-content::-webkit-scrollbar-thumb {
background-color: #ddd;
border-radius: 3px;
}
</style>