|
|
|
@ -21,53 +21,136 @@
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</template></el-table-column>
|
|
|
|
</template></el-table-column>
|
|
|
|
</el-table>
|
|
|
|
</el-table>
|
|
|
|
<el-dialog v-model="dialogVisible" :title="editingId?'编辑地址':'新增地址'" width="600px" destroy-on-close>
|
|
|
|
<el-dialog v-model="dialogVisible" :title="editingId?'编辑地址':'新增地址'" width="900px" destroy-on-close>
|
|
|
|
<el-form :model="form" label-width="100px">
|
|
|
|
<el-form :model="form" label-width="100px">
|
|
|
|
<el-form-item label="名称" required><el-input v-model="form.name"/></el-form-item>
|
|
|
|
<el-form-item label="名称" required><el-input v-model="form.name"/></el-form-item>
|
|
|
|
<el-form-item label="URL" required><el-input v-model="form.url"/></el-form-item>
|
|
|
|
<el-form-item label="URL" required><el-input v-model="form.url"/></el-form-item>
|
|
|
|
<el-form-item label="品牌" required><el-select v-model="form.brandId"><el-option v-for="b in brandList" :key="b.id" :label="b.brandName" :value="b.id"/></el-select></el-form-item>
|
|
|
|
<el-form-item label="品牌" required>
|
|
|
|
<!-- 关联机床区域 -->
|
|
|
|
<el-select v-model="form.brandId" @change="onBrandChange">
|
|
|
|
<el-form-item label="关联机床">
|
|
|
|
<el-option v-for="b in brandList" :key="b.id" :label="b.brandName" :value="b.id"/>
|
|
|
|
<el-checkbox-group v-model="form.machineIds">
|
|
|
|
</el-select>
|
|
|
|
<el-checkbox v-for="m in machineList" :key="m.machineId" :label="m.machineId">{{m.machineName}}</el-checkbox>
|
|
|
|
</el-form-item>
|
|
|
|
</el-checkbox-group>
|
|
|
|
<el-form-item label="关联机床">
|
|
|
|
</el-form-item>
|
|
|
|
<el-transfer
|
|
|
|
<el-form-item label="采集间隔" required><el-input-number v-model="form.collectInterval" :min="5"/></el-form-item>
|
|
|
|
v-model="form.machineIds"
|
|
|
|
</el-form>
|
|
|
|
:data="transferMachines"
|
|
|
|
<template #footer><el-button @click="dialogVisible=false">取消</el-button><el-button type="primary" :loading="submitting" @click="handleSubmit">保存</el-button></template>
|
|
|
|
:titles="['可关联机床', '已关联']"
|
|
|
|
</el-dialog>
|
|
|
|
:props="{ key: 'id', label: 'label' }"
|
|
|
|
</div>
|
|
|
|
filterable
|
|
|
|
|
|
|
|
filter-placeholder="搜索机床"
|
|
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|
<template #default="{ option }">
|
|
|
|
|
|
|
|
<span>
|
|
|
|
|
|
|
|
<span :style="dotStyle(option)"></span>
|
|
|
|
|
|
|
|
{{ option.name }}
|
|
|
|
|
|
|
|
<template v-if="option.deviceCode"> ({{ option.deviceCode }})</template>
|
|
|
|
|
|
|
|
</span>
|
|
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
</el-transfer>
|
|
|
|
|
|
|
|
<div class="transfer-legend">
|
|
|
|
|
|
|
|
<span><span class="status-dot online"></span>在线</span>
|
|
|
|
|
|
|
|
<span><span class="status-dot offline"></span>离线</span>
|
|
|
|
|
|
|
|
<span><span class="status-dot disabled-dot"></span>停用</span>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
|
|
<el-form-item label="采集间隔" required><el-input-number v-model="form.collectInterval" :min="5"/></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>
|
|
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
|
|
<script setup lang="ts">
|
|
|
|
import {ref, reactive, onMounted, watch} from 'vue'
|
|
|
|
import {ref, reactive, onMounted} from 'vue'
|
|
|
|
import {useRouter} from 'vue-router'
|
|
|
|
import {useRouter} from 'vue-router'
|
|
|
|
import {ElMessage,ElMessageBox} from 'element-plus'
|
|
|
|
import {ElMessage,ElMessageBox} from 'element-plus'
|
|
|
|
import request from '@/utils/request'
|
|
|
|
import request from '@/utils/request'
|
|
|
|
import {useMockMode} from '@/composables/useMockMode'
|
|
|
|
import {useMockMode} from '@/composables/useMockMode'
|
|
|
|
|
|
|
|
import type { ApiResponse, Brand, CollectAddress } from '@/types'
|
|
|
|
const router=useRouter();const{isMock}=useMockMode()
|
|
|
|
const router=useRouter();const{isMock}=useMockMode()
|
|
|
|
import type { ApiResponse, Brand, Workshop, CollectAddress } from '@/types'
|
|
|
|
|
|
|
|
const loading=ref(false);const tableData=ref<CollectAddress[]>([]);const brandList=ref<Brand[]>([])
|
|
|
|
const loading=ref(false);const tableData=ref<CollectAddress[]>([]);const brandList=ref<Brand[]>([])
|
|
|
|
const dialogVisible=ref(false);const submitting=ref(false);const editingId=ref<number|null>(null)
|
|
|
|
const dialogVisible=ref(false);const submitting=ref(false);const editingId=ref<number|null>(null)
|
|
|
|
const query=reactive({brandId:undefined as number|undefined})
|
|
|
|
const query=reactive({brandId:undefined as number|undefined})
|
|
|
|
const form=reactive({name:'',url:'',brandId:undefined as number|undefined,collectInterval:30,machineIds: [] as number[]})
|
|
|
|
const form=reactive({name:'',url:'',brandId:undefined as number|undefined,collectInterval:30,machineIds:[] as number[]})
|
|
|
|
// 机床列表(关联机床)
|
|
|
|
interface TransferMachine { id: number; name: string; label: string; deviceCode?: string; isOnline: number; isEnabled: number }
|
|
|
|
const machineList=ref<{ machineId:number; machineName:string }[]>([])
|
|
|
|
const transferMachines=ref<TransferMachine[]>([])
|
|
|
|
// 加载某品牌的机床列表
|
|
|
|
|
|
|
|
async function loadMachinesForBrandName(brandName:string){ if(!brandName){ machineList.value = []; return } const r: ApiResponse<{ items: { machineId:number; machineName:string }[] }> = await request.get('/admin/machine', { params: { brandName } }); machineList.value = r.data?.items || [] }
|
|
|
|
|
|
|
|
function resetQuery(){query.brandId=undefined;loadData()}
|
|
|
|
function resetQuery(){query.brandId=undefined;loadData()}
|
|
|
|
function goDetail(id:number){router.push((isMock.value?'/mock/collect-address/':'/collect-address/')+id)}
|
|
|
|
function goDetail(id:number){router.push((isMock.value?'/mock/collect-address/':'/collect-address/')+id)}
|
|
|
|
async function loadData(){loading.value=true;try{const r:any=await request.get('/admin/collect-address');tableData.value=r.data?.items||[]}finally{loading.value=false}}
|
|
|
|
async function loadData(){loading.value=true;try{const r:any=await request.get('/admin/collect-address');tableData.value=r.data?.items||[]}finally{loading.value=false}}
|
|
|
|
function handleAdd(){editingId.value=null;Object.assign(form,{name:'',url:'',brandId:undefined,collectInterval:30,machineIds: []});dialogVisible.value=true}
|
|
|
|
|
|
|
|
function handleEdit(row:any){editingId.value=row.id;Object.assign(form,row);dialogVisible.value=true}
|
|
|
|
function handleAdd(){
|
|
|
|
async function handleSubmit(){submitting.value=true;try{await request[editingId.value?'put':'post'](editingId.value?`/admin/collect-address/${editingId.value}`:'/admin/collect-address',{...form});ElMessage.success('保存成功');dialogVisible.value=false;loadData()}finally{submitting.value=false}}
|
|
|
|
editingId.value=null
|
|
|
|
async function handleDelete(row:any){await ElMessageBox.confirm('确定删除【'+row.name+'】?此操作不可恢复。','提示',{type:'warning'});await request.delete(`/admin/collect-address/${row.id}`);ElMessage.success('已删除');loadData()}
|
|
|
|
Object.assign(form,{name:'',url:'',brandId:undefined,collectInterval:30,machineIds:[]})
|
|
|
|
async function loadDrops(){const r:any=await request.get('/admin/brand');brandList.value=r.data?.items||[]}
|
|
|
|
transferMachines.value=[]
|
|
|
|
|
|
|
|
dialogVisible.value=true
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async function handleEdit(row: any){
|
|
|
|
|
|
|
|
editingId.value=row.id
|
|
|
|
|
|
|
|
Object.assign(form,{name:row.name,url:row.url,brandId:row.brandId,collectInterval:row.collectInterval,machineIds:[]})
|
|
|
|
|
|
|
|
// 加载穿梭框数据 + 已关联机床
|
|
|
|
|
|
|
|
await loadTransferData(row.brandId, row.id)
|
|
|
|
|
|
|
|
dialogVisible.value=true
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** 品牌切换时重新加载穿梭框 */
|
|
|
|
|
|
|
|
async function onBrandChange(){
|
|
|
|
|
|
|
|
form.machineIds=[]
|
|
|
|
|
|
|
|
await loadTransferData(form.brandId, editingId.value ?? undefined)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** 加载穿梭框:同品牌下未关联其他地址的机床 + 当前地址已关联的机床 */
|
|
|
|
|
|
|
|
async function loadTransferData(brandId?: number, addressId?: number){
|
|
|
|
|
|
|
|
if(!brandId){ transferMachines.value=[]; return }
|
|
|
|
|
|
|
|
try{
|
|
|
|
|
|
|
|
// 获取该品牌全部机床
|
|
|
|
|
|
|
|
const brandName = brandList.value.find((b: any) => b.id === brandId)?.brandName ?? ''
|
|
|
|
|
|
|
|
const rAll: any = await request.get('/admin/machine', {params: {brandName, pageSize: 999}})
|
|
|
|
|
|
|
|
const allMachines = rAll.data?.items ?? []
|
|
|
|
|
|
|
|
// 未关联任何采集地址的机床ID
|
|
|
|
|
|
|
|
const freeMachines = allMachines.filter((m: any) => !m.collectAddressId || m.collectAddressId === 0)
|
|
|
|
|
|
|
|
const freeIds = new Set(freeMachines.map((m: any) => m.id))
|
|
|
|
|
|
|
|
// 当前地址已关联的机床
|
|
|
|
|
|
|
|
let ownIds = new Set<number>()
|
|
|
|
|
|
|
|
if(addressId){
|
|
|
|
|
|
|
|
const rOwn: any = await request.get(`/admin/collect-address/${addressId}/machines`)
|
|
|
|
|
|
|
|
const items = rOwn.data?.items ?? []
|
|
|
|
|
|
|
|
ownIds = new Set(items.map((m: any) => m.machineId))
|
|
|
|
|
|
|
|
form.machineIds = items.map((m: any) => m.machineId)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
transferMachines.value = allMachines
|
|
|
|
|
|
|
|
.filter((m: any) => freeIds.has(m.id) || ownIds.has(m.id))
|
|
|
|
|
|
|
|
.map((m: any) => ({ id: m.id, name: m.name, label: m.name, deviceCode: m.deviceCode, isOnline: m.isOnline, isEnabled: m.isEnabled }))
|
|
|
|
|
|
|
|
}catch{ transferMachines.value=[] }
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async function handleSubmit(){
|
|
|
|
|
|
|
|
submitting.value=true
|
|
|
|
|
|
|
|
try{
|
|
|
|
|
|
|
|
await request[editingId.value?'put':'post'](editingId.value?`/admin/collect-address/${editingId.value}`:'/admin/collect-address',{...form})
|
|
|
|
|
|
|
|
ElMessage.success('保存成功');dialogVisible.value=false;loadData()
|
|
|
|
|
|
|
|
}finally{submitting.value=false}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
async function handleDelete(row:any){
|
|
|
|
|
|
|
|
await ElMessageBox.confirm('确定删除【'+row.name+'】?此操作不可恢复。','提示',{type:'warning'})
|
|
|
|
|
|
|
|
await request.delete(`/admin/collect-address/${row.id}`)
|
|
|
|
|
|
|
|
ElMessage.success('已删除');loadData()
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
async function loadDrops(){const r:any=await request.get('/admin/brand');brandList.value=r.data?.items||[]}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** 机床状态色点 */
|
|
|
|
|
|
|
|
function dotStyle(m: TransferMachine): Record<string, string> {
|
|
|
|
|
|
|
|
const color = !m.isEnabled ? '#f56c6c' : m.isOnline ? '#67c23a' : '#c0c4cc'
|
|
|
|
|
|
|
|
return { display: 'inline-block', width: '8px', height: '8px', borderRadius: '50%', marginRight: '6px', verticalAlign: 'middle', backgroundColor: color }
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
onMounted(()=>{loadData();loadDrops()})
|
|
|
|
onMounted(()=>{loadData();loadDrops()})
|
|
|
|
// 监听品牌变化,自动加载对应机床
|
|
|
|
|
|
|
|
watch(() => form.brandId, async (newVal)=>{
|
|
|
|
|
|
|
|
const b = brandList.value.find((bb:any)=> bb.id===newVal)
|
|
|
|
|
|
|
|
const brandName = b?.brandName ?? ''
|
|
|
|
|
|
|
|
await loadMachinesForBrandName(brandName)
|
|
|
|
|
|
|
|
form.machineIds = []
|
|
|
|
|
|
|
|
}, { immediate: true })
|
|
|
|
|
|
|
|
</script>
|
|
|
|
</script>
|
|
|
|
|
|
|
|
<style scoped>
|
|
|
|
|
|
|
|
.status-dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; margin-right: 6px; vertical-align: middle; }
|
|
|
|
|
|
|
|
.status-dot.online { background-color: #67c23a; }
|
|
|
|
|
|
|
|
.status-dot.offline { background-color: #c0c4cc; }
|
|
|
|
|
|
|
|
.status-dot.disabled-dot { background-color: #f56c6c; }
|
|
|
|
|
|
|
|
.transfer-legend { display: flex; gap: 16px; margin-top: 8px; font-size: 12px; color: #909399; align-items: center; }
|
|
|
|
|
|
|
|
.transfer-legend .status-dot { margin-right: 4px; }
|
|
|
|
|
|
|
|
</style>
|
|
|
|
|