620 lines
27 KiB
Vue
620 lines
27 KiB
Vue
<script setup lang="ts">
|
||
import { ref } from 'vue'
|
||
import {
|
||
Info,
|
||
Server,
|
||
CheckCircle2,
|
||
AlertTriangle,
|
||
Layers,
|
||
Plus,
|
||
Trash2,
|
||
GripVertical,
|
||
X,
|
||
} from 'lucide-vue-next'
|
||
|
||
const showDrawer = ref(false)
|
||
const drawerForm = ref({
|
||
name: '',
|
||
code: '',
|
||
authFile: '',
|
||
configFile: '',
|
||
firmwareVersion: '',
|
||
status: '在产' as '在产' | '停产',
|
||
})
|
||
|
||
interface ChecklistItem {
|
||
id: number
|
||
text: string
|
||
type: 'text' | 'bool'
|
||
required: boolean
|
||
note: string
|
||
}
|
||
|
||
interface ChecklistData {
|
||
[key: string]: ChecklistItem[]
|
||
}
|
||
|
||
const activeTab = ref('GD30')
|
||
|
||
const stats = [
|
||
{ label: '型号总数', value: '12', icon: Server, color: '#4a7c59' },
|
||
{ label: '在产型号', value: '8', icon: CheckCircle2, color: '#52C41A' },
|
||
{ label: '停产型号', value: '3', icon: AlertTriangle, color: '#FAAD14' },
|
||
{ label: '关联设备总数', value: '5,234', icon: Layers, color: '#722ED1' },
|
||
]
|
||
|
||
const modelData = [
|
||
{
|
||
name: 'GD30 高密度电法仪',
|
||
code: 'GD30-2024',
|
||
authFile: 'auth_gd30_v2.3.lic',
|
||
configFile: 'config_gd30_v1.5.json',
|
||
firmwareVersion: 'v2.3.5',
|
||
deviceCount: 2456,
|
||
status: '在产' as const,
|
||
},
|
||
{
|
||
name: 'GT20 瞬变电磁仪',
|
||
code: 'GT20-2023',
|
||
authFile: 'auth_gt20_v1.8.lic',
|
||
configFile: 'config_gt20_v1.2.json',
|
||
firmwareVersion: 'v1.8.2',
|
||
deviceCount: 1823,
|
||
status: '在产' as const,
|
||
},
|
||
{
|
||
name: 'GM10 大地电磁仪',
|
||
code: 'GM10-2022',
|
||
authFile: 'auth_gm10_v1.5.lic',
|
||
configFile: 'config_gm10_v1.0.json',
|
||
firmwareVersion: 'v1.5.1',
|
||
deviceCount: 955,
|
||
status: '停产' as const,
|
||
},
|
||
]
|
||
|
||
const checklistData = ref<ChecklistData>({
|
||
GD30: [
|
||
{ id: 1, text: '主板SN扫码绑定主机', type: 'text', required: true, note: '唯一SN' },
|
||
{ id: 2, text: '采集板SN录入', type: 'text', required: true, note: '1/6/12通道' },
|
||
{ id: 3, text: '发射板SN录入', type: 'text', required: true, note: '' },
|
||
{ id: 4, text: '内置升压模块检查', type: 'bool', required: true, note: '' },
|
||
{ id: 5, text: 'GPS/北斗检测', type: 'bool', required: true, note: '授时正常' },
|
||
{ id: 6, text: '电池安装与容量检测', type: 'bool', required: true, note: '' },
|
||
{ id: 7, text: '输入电压12~48V测试', type: 'bool', required: true, note: '' },
|
||
{ id: 8, text: '接收电压精度校验', type: 'bool', required: true, note: '按型号量程' },
|
||
{ id: 9, text: '自电补偿±10V', type: 'bool', required: true, note: '' },
|
||
{ id: 10, text: '输入阻抗≥100MΩ', type: 'bool', required: true, note: '' },
|
||
{ id: 11, text: '恒压/恒流模式', type: 'bool', required: true, note: '' },
|
||
{ id: 12, text: '最大发射电流达标', type: 'bool', required: true, note: '6A/10A/10A' },
|
||
{ id: 13, text: '脉冲宽度配置', type: 'bool', required: true, note: '' },
|
||
{ id: 14, text: '调级输出电压', type: 'bool', required: true, note: '100~600V' },
|
||
{ id: 15, text: '系统启动正常', type: 'bool', required: true, note: '' },
|
||
{ id: 16, text: '采集APP连接', type: 'bool', required: true, note: '' },
|
||
{ id: 17, text: 'Geometa账号配置', type: 'bool', required: true, note: '' },
|
||
{ id: 18, text: '授权文件校验', type: 'bool', required: true, note: '' },
|
||
{ id: 19, text: 'USB/WiFi/网口/SD', type: 'bool', required: true, note: '' },
|
||
{ id: 20, text: 'IP66防护与密封', type: 'bool', required: true, note: '' },
|
||
{ id: 21, text: '过流/过压/短路保护', type: 'bool', required: true, note: '' },
|
||
{ id: 22, text: '出厂装箱核对', type: 'bool', required: true, note: '' },
|
||
],
|
||
GT20: [
|
||
{ id: 1, text: '主板SN扫码绑定主机', type: 'text', required: true, note: '唯一SN' },
|
||
{ id: 2, text: '采集板SN录入', type: 'text', required: true, note: '' },
|
||
{ id: 3, text: 'GPS/北斗检测', type: 'bool', required: true, note: '授时正常' },
|
||
{ id: 4, text: '系统启动正常', type: 'bool', required: true, note: '' },
|
||
{ id: 5, text: '整体功能测试', type: 'bool', required: true, note: '' },
|
||
],
|
||
GM10: [
|
||
{ id: 1, text: '主板SN扫码绑定主机', type: 'text', required: true, note: '唯一SN' },
|
||
{ id: 2, text: '传感器模块连接', type: 'bool', required: true, note: '' },
|
||
{ id: 3, text: '接口板安装', type: 'bool', required: true, note: '' },
|
||
{ id: 4, text: '线缆整理', type: 'bool', required: true, note: '' },
|
||
{ id: 5, text: '系统初始化检测', type: 'bool', required: true, note: '' },
|
||
],
|
||
})
|
||
|
||
const editingCell = ref<{ model: string; id: number; field: string } | null>(null)
|
||
|
||
const updateChecklistItem = (model: string, id: number, field: keyof ChecklistItem, value: string | boolean) => {
|
||
checklistData.value = {
|
||
...checklistData.value,
|
||
[model]: checklistData.value[model].map((item: ChecklistItem) =>
|
||
item.id === id ? { ...item, [field]: value } : item
|
||
),
|
||
}
|
||
}
|
||
|
||
const addChecklistItem = (model: string) => {
|
||
const items = checklistData.value[model]
|
||
const newId = items.length > 0 ? Math.max(...items.map((i: ChecklistItem) => i.id)) + 1 : 1
|
||
checklistData.value = {
|
||
...checklistData.value,
|
||
[model]: [...items, { id: newId, text: '新检查项', type: 'bool' as const, required: true, note: '' }],
|
||
}
|
||
}
|
||
|
||
const deleteChecklistItem = (model: string, id: number) => {
|
||
checklistData.value = {
|
||
...checklistData.value,
|
||
[model]: checklistData.value[model].filter((item: ChecklistItem) => item.id !== id).map((item: ChecklistItem, i: number) => ({ ...item, id: i + 1 })),
|
||
}
|
||
}
|
||
|
||
const handleEditBlur = (e: Event, model: string, id: number) => {
|
||
updateChecklistItem(model, id, 'text', (e.target as HTMLInputElement).value)
|
||
editingCell.value = null
|
||
}
|
||
|
||
const handleEditKeydown = (e: KeyboardEvent) => {
|
||
if (e.key === 'Enter') (e.target as HTMLInputElement).blur()
|
||
}
|
||
|
||
const boardVersionData = [
|
||
{
|
||
boardType: '主板',
|
||
requiredVersion: 'v2.3.x',
|
||
validationRule: '版本号前缀必须为 v2.3',
|
||
status: 'active',
|
||
},
|
||
{
|
||
boardType: '采集板',
|
||
requiredVersion: 'v1.8.x',
|
||
validationRule: '版本号前缀必须为 v1.8',
|
||
status: 'active',
|
||
},
|
||
{
|
||
boardType: '发射板',
|
||
requiredVersion: 'v1.5.x',
|
||
validationRule: '版本号前缀必须为 v1.5',
|
||
status: 'active',
|
||
},
|
||
]
|
||
|
||
// Checklist template drawer state
|
||
const showChecklistDrawer = ref(false)
|
||
const newTplModel = ref('GD30')
|
||
const newTplItems = ref<{ text: string }[]>([{ text: '' }])
|
||
|
||
const openChecklistDrawer = () => {
|
||
newTplModel.value = 'GD30'
|
||
newTplItems.value = [{ text: '' }]
|
||
showChecklistDrawer.value = true
|
||
}
|
||
|
||
const addTplItem = () => {
|
||
newTplItems.value.push({ text: '' })
|
||
}
|
||
|
||
const removeTplItem = (index: number) => {
|
||
newTplItems.value.splice(index, 1)
|
||
}
|
||
</script>
|
||
|
||
<template>
|
||
<div class="p-6">
|
||
<!-- Page Header -->
|
||
<div class="mb-6">
|
||
<h2 class="text-2xl font-semibold mb-1">设备型号管理</h2>
|
||
<p class="text-sm" :style="{ color: 'rgba(0, 0, 0, 0.45)' }">管理设备型号及相关配置</p>
|
||
</div>
|
||
|
||
<!-- Info Banner -->
|
||
<div
|
||
class="mb-6 p-4 rounded-lg flex items-start gap-3"
|
||
:style="{ backgroundColor: '#eef5f0', border: '1px solid #a3c4ad' }"
|
||
>
|
||
<Info :size="20" :style="{ color: '#4a7c59', flexShrink: 0, marginTop: '2px' }" />
|
||
<div :style="{ color: '#2d5a3d' }">
|
||
型号管理是平台核心枢纽,每个型号关联授权文件、配置文件和固件版本
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Stat Cards -->
|
||
<div class="grid grid-cols-4 gap-6 mb-6">
|
||
<div
|
||
v-for="(stat, index) in stats"
|
||
:key="index"
|
||
class="bg-white p-6 rounded-lg"
|
||
:style="{ boxShadow: '0 1px 2px rgba(0, 0, 0, 0.05)' }"
|
||
>
|
||
<div class="flex items-center justify-between">
|
||
<div>
|
||
<div class="text-sm mb-2" :style="{ color: 'rgba(0, 0, 0, 0.65)' }">{{ stat.label }}</div>
|
||
<div class="text-3xl font-semibold">{{ stat.value }}</div>
|
||
</div>
|
||
<div
|
||
class="w-12 h-12 rounded-lg flex items-center justify-center"
|
||
:style="{ backgroundColor: `${stat.color}15` }"
|
||
>
|
||
<component :is="stat.icon" :size="24" :style="{ color: stat.color }" />
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Model Table -->
|
||
<div class="bg-white rounded-lg mb-6" :style="{ boxShadow: '0 1px 2px rgba(0, 0, 0, 0.05)' }">
|
||
<div class="p-6 border-b" :style="{ borderColor: '#F0F0F0' }">
|
||
<div class="flex items-center justify-between">
|
||
<h3 class="text-lg font-semibold">型号列表</h3>
|
||
<button
|
||
class="px-4 py-2 rounded text-white flex items-center gap-2"
|
||
:style="{ backgroundColor: '#4a7c59' }"
|
||
@click="showDrawer = true"
|
||
>
|
||
<Plus :size="16" />
|
||
新增型号
|
||
</button>
|
||
</div>
|
||
</div>
|
||
<div class="overflow-x-auto">
|
||
<table class="w-full">
|
||
<thead :style="{ backgroundColor: '#FAFAFA' }">
|
||
<tr>
|
||
<th class="px-6 py-3 text-left text-sm font-medium" :style="{ color: 'rgba(0, 0, 0, 0.85)' }">型号名称</th>
|
||
<th class="px-6 py-3 text-left text-sm font-medium" :style="{ color: 'rgba(0, 0, 0, 0.85)' }">编码</th>
|
||
<th class="px-6 py-3 text-left text-sm font-medium" :style="{ color: 'rgba(0, 0, 0, 0.85)' }">授权文件</th>
|
||
<th class="px-6 py-3 text-left text-sm font-medium" :style="{ color: 'rgba(0, 0, 0, 0.85)' }">配置文件</th>
|
||
<th class="px-6 py-3 text-left text-sm font-medium" :style="{ color: 'rgba(0, 0, 0, 0.85)' }">固件版本</th>
|
||
<th class="px-6 py-3 text-left text-sm font-medium" :style="{ color: 'rgba(0, 0, 0, 0.85)' }">设备数</th>
|
||
<th class="px-6 py-3 text-left text-sm font-medium" :style="{ color: 'rgba(0, 0, 0, 0.85)' }">状态</th>
|
||
<th class="px-6 py-3 text-left text-sm font-medium" :style="{ color: 'rgba(0, 0, 0, 0.85)' }">操作</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr
|
||
v-for="(model, index) in modelData"
|
||
:key="index"
|
||
class="border-b"
|
||
:style="{ borderColor: '#F0F0F0' }"
|
||
>
|
||
<td class="px-6 py-4">{{ model.name }}</td>
|
||
<td class="px-6 py-4" :style="{ color: 'rgba(0, 0, 0, 0.65)' }">{{ model.code }}</td>
|
||
<td class="px-6 py-4">
|
||
<router-link to="/licenses" class="text-sm" style="color: #4a7c59">{{ model.authFile }}</router-link>
|
||
</td>
|
||
<td class="px-6 py-4">
|
||
<router-link to="/config-files" class="text-sm" style="color: #4a7c59">{{ model.configFile }}</router-link>
|
||
</td>
|
||
<td class="px-6 py-4">
|
||
<router-link to="/firmware" class="text-sm" style="color: #4a7c59">{{ model.firmwareVersion }}</router-link>
|
||
</td>
|
||
<td class="px-6 py-4">{{ model.deviceCount.toLocaleString() }}</td>
|
||
<td class="px-6 py-4">
|
||
<span
|
||
class="px-2 py-1 rounded text-xs"
|
||
:style="{
|
||
backgroundColor: model.status === '在产' ? '#F6FFED' : '#FFFBE6',
|
||
color: model.status === '在产' ? '#52C41A' : '#FAAD14',
|
||
border: `1px solid ${model.status === '在产' ? '#B7EB8F' : '#FFE58F'}`,
|
||
}"
|
||
>
|
||
{{ model.status }}
|
||
</span>
|
||
</td>
|
||
<td class="px-6 py-4">
|
||
<div class="flex items-center gap-3">
|
||
<button class="text-sm" :style="{ color: '#4a7c59' }">编辑</button>
|
||
<router-link to="/licenses" class="text-sm" style="color: #4a7c59">授权</router-link>
|
||
<router-link to="/config-files" class="text-sm" style="color: #4a7c59">配置</router-link>
|
||
<router-link to="/firmware" class="text-sm" style="color: #4a7c59">固件</router-link>
|
||
</div>
|
||
</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Assembly Checklist -->
|
||
<div class="bg-white rounded-lg mb-6" :style="{ boxShadow: '0 1px 2px rgba(0, 0, 0, 0.05)' }">
|
||
<div class="p-6 border-b" :style="{ borderColor: '#F0F0F0' }">
|
||
<div class="flex items-center justify-between">
|
||
<h3 class="text-lg font-semibold">装配Checklist模板</h3>
|
||
<button
|
||
class="px-4 py-2 rounded text-white flex items-center gap-2"
|
||
:style="{ backgroundColor: '#4a7c59' }"
|
||
@click="openChecklistDrawer"
|
||
>
|
||
<Plus :size="16" />
|
||
新增模版
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Tabs -->
|
||
<div class="flex border-b" :style="{ borderColor: '#F0F0F0' }">
|
||
<button
|
||
v-for="model in Object.keys(checklistData)"
|
||
:key="model"
|
||
@click="activeTab = model"
|
||
class="px-6 py-3 text-sm font-medium transition-colors"
|
||
:style="{
|
||
color: activeTab === model ? '#4a7c59' : 'rgba(0, 0, 0, 0.65)',
|
||
borderBottom: activeTab === model ? '2px solid #4a7c59' : 'none',
|
||
marginBottom: activeTab === model ? '-1px' : '0',
|
||
}"
|
||
>
|
||
{{ model }}
|
||
</button>
|
||
</div>
|
||
|
||
<!-- Checklist Content -->
|
||
<div class="p-6">
|
||
<table class="w-full">
|
||
<thead :style="{ backgroundColor: '#FAFAFA' }">
|
||
<tr>
|
||
<th class="px-3 py-3 text-left text-sm font-medium" :style="{ color: 'rgba(0, 0, 0, 0.85)', width: '50px' }">序号</th>
|
||
<th class="px-3 py-3 text-left text-sm font-medium" :style="{ color: 'rgba(0, 0, 0, 0.85)' }">项目名称</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr
|
||
v-for="item in checklistData[activeTab]"
|
||
:key="item.id"
|
||
class="border-b"
|
||
:style="{ borderColor: '#F0F0F0' }"
|
||
>
|
||
<td class="px-3 py-3 text-sm" :style="{ color: 'rgba(0, 0, 0, 0.45)' }">
|
||
<div class="flex items-center gap-1">
|
||
<GripVertical :size="14" :style="{ color: '#D9D9D9' }" />
|
||
{{ item.id }}
|
||
</div>
|
||
</td>
|
||
<td class="px-3 py-3 text-sm">
|
||
<input
|
||
v-if="editingCell?.model === activeTab && editingCell?.id === item.id && editingCell?.field === 'text'"
|
||
autofocus
|
||
class="w-full px-2 py-1 border rounded text-sm"
|
||
:style="{ borderColor: '#4a7c59' }"
|
||
:value="item.text"
|
||
@blur="handleEditBlur($event, activeTab, item.id)"
|
||
@keydown="handleEditKeydown"
|
||
/>
|
||
<span
|
||
v-else
|
||
class="cursor-pointer hover:text-blue-500"
|
||
@click="editingCell = { model: activeTab, id: item.id, field: 'text' }"
|
||
>
|
||
{{ item.text }}
|
||
</span>
|
||
</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
|
||
|
||
<!-- New Model Drawer -->
|
||
<div v-if="showDrawer" class="fixed inset-0 z-50 flex justify-end" style="background-color: rgba(0,0,0,0.45)" @click.self="showDrawer = false">
|
||
<div class="bg-white w-[480px] h-full flex flex-col" style="box-shadow: -4px 0 12px rgba(0,0,0,0.1)">
|
||
<!-- Drawer Header -->
|
||
<div class="flex items-center justify-between p-5 border-b" style="border-color: #F0F0F0">
|
||
<h3 class="text-lg font-semibold">新增设备型号</h3>
|
||
<button @click="showDrawer = false" class="p-1 rounded hover:bg-gray-100" style="color: rgba(0,0,0,0.45)">
|
||
<X :size="18" />
|
||
</button>
|
||
</div>
|
||
|
||
<!-- Drawer Body -->
|
||
<div class="flex-1 overflow-y-auto p-6">
|
||
<div class="space-y-5">
|
||
<div>
|
||
<label class="block text-sm mb-2" style="color: rgba(0,0,0,0.85)">型号名称 <span style="color: #FF4D4F">*</span></label>
|
||
<input v-model="drawerForm.name" type="text" class="w-full px-3 py-2 border rounded text-sm" style="border-color: #D9D9D9" placeholder="如:GD30 高密度电法仪" />
|
||
</div>
|
||
|
||
<div>
|
||
<label class="block text-sm mb-2" style="color: rgba(0,0,0,0.85)">型号编码 <span style="color: #FF4D4F">*</span></label>
|
||
<select v-model="drawerForm.code" class="w-full px-3 py-2 border rounded text-sm" style="border-color: #D9D9D9; background-color: #fff">
|
||
<option value="">请选择编码</option>
|
||
<option>GD10-2025</option>
|
||
<option>GD20-2025</option>
|
||
<option>GD30-2025</option>
|
||
<option>GT20-2025</option>
|
||
<option>GM10-2025</option>
|
||
</select>
|
||
</div>
|
||
|
||
<div>
|
||
<label class="block text-sm mb-2" style="color: rgba(0,0,0,0.85)">绑定授权文件</label>
|
||
<select v-model="drawerForm.authFile" class="w-full px-3 py-2 border rounded text-sm" style="border-color: #D9D9D9; background-color: #fff">
|
||
<option value="">请选择授权文件</option>
|
||
<option>auth_gd10_v1.0.lic</option>
|
||
<option>auth_gd20_v2.0.lic</option>
|
||
<option>auth_gd30_v2.3.lic</option>
|
||
<option>auth_gt20_v1.8.lic</option>
|
||
<option>auth_gm10_v1.5.lic</option>
|
||
</select>
|
||
<div class="text-xs mt-1" style="color: rgba(0,0,0,0.45)">授权文件按型号绑定,设备激活时自动下载</div>
|
||
</div>
|
||
|
||
<div>
|
||
<label class="block text-sm mb-2" style="color: rgba(0,0,0,0.85)">绑定配置文件</label>
|
||
<select v-model="drawerForm.configFile" class="w-full px-3 py-2 border rounded text-sm" style="border-color: #D9D9D9; background-color: #fff">
|
||
<option value="">请选择配置文件</option>
|
||
<option>config_gd10_v1.0.json</option>
|
||
<option>config_gd20_v1.2.json</option>
|
||
<option>config_gd30_v1.5.json</option>
|
||
<option>config_gt20_v1.2.json</option>
|
||
<option>config_gm10_v1.0.json</option>
|
||
</select>
|
||
<div class="text-xs mt-1" style="color: rgba(0,0,0,0.45)">配置文件包含发射参数、采集参数、网络参数等</div>
|
||
</div>
|
||
|
||
<div>
|
||
<label class="block text-sm mb-2" style="color: rgba(0,0,0,0.85)">绑定主机固件版本</label>
|
||
<select v-model="drawerForm.firmwareVersion" class="w-full px-3 py-2 border rounded text-sm" style="border-color: #D9D9D9; background-color: #fff">
|
||
<option value="">请选择主机固件版本</option>
|
||
<option>v2.3.5</option>
|
||
<option>v2.3.0</option>
|
||
<option>v2.2.0</option>
|
||
<option>v2.1.0</option>
|
||
<option>v1.8.2</option>
|
||
<option>v1.5.1</option>
|
||
</select>
|
||
</div>
|
||
|
||
<div>
|
||
<label class="block text-sm mb-2" style="color: rgba(0,0,0,0.85)">绑定主协板固件版本</label>
|
||
<select v-model="drawerForm.firmwareVersion" class="w-full px-3 py-2 border rounded text-sm" style="border-color: #D9D9D9; background-color: #fff">
|
||
<option value="">请选择主协板固件版本</option>
|
||
<option>v2.3.5</option>
|
||
<option>v2.3.0</option>
|
||
<option>v2.2.0</option>
|
||
<option>v2.1.0</option>
|
||
<option>v1.8.2</option>
|
||
<option>v1.5.1</option>
|
||
</select>
|
||
</div>
|
||
|
||
<div>
|
||
<label class="block text-sm mb-2" style="color: rgba(0,0,0,0.85)">绑定发射板固件版本</label>
|
||
<select v-model="drawerForm.firmwareVersion" class="w-full px-3 py-2 border rounded text-sm" style="border-color: #D9D9D9; background-color: #fff">
|
||
<option value="">请选择发射板固件版本</option>
|
||
<option>v2.3.5</option>
|
||
<option>v2.3.0</option>
|
||
<option>v2.2.0</option>
|
||
<option>v2.1.0</option>
|
||
<option>v1.8.2</option>
|
||
<option>v1.5.1</option>
|
||
</select>
|
||
</div>
|
||
|
||
<div>
|
||
<label class="block text-sm mb-2" style="color: rgba(0,0,0,0.85)">绑定采集板固件版本</label>
|
||
<select v-model="drawerForm.firmwareVersion" class="w-full px-3 py-2 border rounded text-sm" style="border-color: #D9D9D9; background-color: #fff">
|
||
<option value="">请选择采集板固件版本</option>
|
||
<option>v2.3.5</option>
|
||
<option>v2.3.0</option>
|
||
<option>v2.2.0</option>
|
||
<option>v2.1.0</option>
|
||
<option>v1.8.2</option>
|
||
<option>v1.5.1</option>
|
||
</select>
|
||
</div>
|
||
|
||
<div>
|
||
<label class="block text-sm mb-2" style="color: rgba(0,0,0,0.85)">状态</label>
|
||
<div class="flex items-center gap-4">
|
||
<label class="flex items-center gap-2 cursor-pointer text-sm">
|
||
<input type="radio" v-model="drawerForm.status" value="在产" style="accent-color: #4a7c59" />
|
||
<span>在产</span>
|
||
</label>
|
||
<label class="flex items-center gap-2 cursor-pointer text-sm">
|
||
<input type="radio" v-model="drawerForm.status" value="停产" style="accent-color: #4a7c59" />
|
||
<span>停产</span>
|
||
</label>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Preview -->
|
||
<div class="p-4 rounded-lg" style="background-color: #FAFAFA; border: 1px solid #F0F0F0">
|
||
<div class="text-sm font-medium mb-3">绑定预览</div>
|
||
<div class="space-y-2 text-sm" style="color: rgba(0,0,0,0.65)">
|
||
<div class="flex justify-between">
|
||
<span>授权文件</span>
|
||
<span :style="{ color: drawerForm.authFile ? '#52C41A' : '#FF4D4F' }">{{ drawerForm.authFile || '未绑定' }}</span>
|
||
</div>
|
||
<div class="flex justify-between">
|
||
<span>配置文件</span>
|
||
<span :style="{ color: drawerForm.configFile ? '#52C41A' : '#FF4D4F' }">{{ drawerForm.configFile || '未绑定' }}</span>
|
||
</div>
|
||
<div class="flex justify-between">
|
||
<span>固件版本</span>
|
||
<span :style="{ color: drawerForm.firmwareVersion ? '#52C41A' : '#FF4D4F' }">{{ drawerForm.firmwareVersion || '未绑定' }}</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Drawer Footer -->
|
||
<div class="flex items-center justify-end gap-3 p-5 border-t" style="border-color: #F0F0F0">
|
||
<button class="px-4 py-2 rounded text-sm" style="border: 1px solid #D9D9D9; color: rgba(0,0,0,0.85)" @click="showDrawer = false">取消</button>
|
||
<button
|
||
class="px-4 py-2 rounded text-white text-sm"
|
||
:style="{ backgroundColor: drawerForm.name && drawerForm.code ? '#4a7c59' : '#D9D9D9' }"
|
||
:disabled="!drawerForm.name || !drawerForm.code"
|
||
@click="showDrawer = false"
|
||
>确认创建</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Checklist Template Drawer -->
|
||
<div v-if="showChecklistDrawer" class="fixed inset-0 z-50 flex justify-end" style="background-color: rgba(0,0,0,0.45)" @click.self="showChecklistDrawer = false">
|
||
<div class="bg-white w-[480px] h-full flex flex-col" style="box-shadow: -4px 0 12px rgba(0,0,0,0.1)">
|
||
<!-- Drawer Header -->
|
||
<div class="flex items-center justify-between p-5 border-b" style="border-color: #F0F0F0">
|
||
<h3 class="text-lg font-semibold">新增Checklist模版</h3>
|
||
<button @click="showChecklistDrawer = false" class="p-1 rounded hover:bg-gray-100" style="color: rgba(0,0,0,0.45)">
|
||
<X :size="18" />
|
||
</button>
|
||
</div>
|
||
|
||
<!-- Drawer Body -->
|
||
<div class="flex-1 overflow-y-auto p-6">
|
||
<div class="space-y-5">
|
||
<div>
|
||
<label class="block text-sm mb-2" style="color: rgba(0,0,0,0.85)">设备型号 <span style="color: #FF4D4F">*</span></label>
|
||
<select v-model="newTplModel" class="w-full px-3 py-2 border rounded text-sm" style="border-color: #D9D9D9; background-color: #fff">
|
||
<option value="GD30">GD30</option>
|
||
<option value="GT20">GT20</option>
|
||
<option value="GM10">GM10</option>
|
||
</select>
|
||
</div>
|
||
|
||
<div>
|
||
<label class="block text-sm mb-2" style="color: rgba(0,0,0,0.85)">检查项列表</label>
|
||
<div class="space-y-3">
|
||
<div
|
||
v-for="(item, index) in newTplItems"
|
||
:key="index"
|
||
class="flex items-center gap-2"
|
||
>
|
||
<span class="text-sm w-6 text-center flex-shrink-0" style="color: rgba(0,0,0,0.45)">{{ index + 1 }}</span>
|
||
<input
|
||
v-model="item.text"
|
||
type="text"
|
||
class="flex-1 px-3 py-2 border rounded text-sm"
|
||
style="border-color: #D9D9D9"
|
||
placeholder="请输入检查项名称"
|
||
/>
|
||
<button
|
||
@click="removeTplItem(index)"
|
||
class="p-1 rounded hover:bg-red-50 text-gray-400 hover:text-red-500 transition-colors flex-shrink-0"
|
||
:disabled="newTplItems.length <= 1"
|
||
:style="{ opacity: newTplItems.length <= 1 ? 0.3 : 1 }"
|
||
>
|
||
<Trash2 :size="15" />
|
||
</button>
|
||
</div>
|
||
</div>
|
||
<button
|
||
@click="addTplItem"
|
||
class="mt-3 px-4 py-2 text-sm flex items-center gap-1 rounded transition-colors w-full justify-center"
|
||
:style="{ color: '#4a7c59', border: '1px dashed #4a7c59' }"
|
||
>
|
||
<Plus :size="14" />
|
||
添加检查项
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Drawer Footer -->
|
||
<div class="flex items-center justify-end gap-3 p-5 border-t" style="border-color: #F0F0F0">
|
||
<button class="px-4 py-2 rounded text-sm" style="border: 1px solid #D9D9D9; color: rgba(0,0,0,0.85)" @click="showChecklistDrawer = false">取消</button>
|
||
<button
|
||
class="px-4 py-2 rounded text-white text-sm"
|
||
:style="{ backgroundColor: '#4a7c59' }"
|
||
@click="showChecklistDrawer = false"
|
||
>确认生成</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</template> |