2024-06-26 15:11:05 +08:00
|
|
|
|
<template>
|
2025-10-13 09:27:53 +08:00
|
|
|
|
<div class="flowchart-container">
|
|
|
|
|
|
<h2 class="flowchart-title">装备管理系统流程图</h2>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 流程图主体 -->
|
2025-10-14 23:01:29 +08:00
|
|
|
|
<div class="flowchart-wrapper" ref="wrapper">
|
2025-10-13 09:27:53 +08:00
|
|
|
|
|
|
|
|
|
|
<!-- 所有节点 -->
|
|
|
|
|
|
<div class="nodes">
|
|
|
|
|
|
<!-- 装备录入 -->
|
|
|
|
|
|
<div
|
|
|
|
|
|
class="node entry-node"
|
2025-10-14 23:01:29 +08:00
|
|
|
|
:style="{ left: '40px', top: '60px' }"
|
|
|
|
|
|
ref="equipmentEntry"
|
2025-10-13 09:27:53 +08:00
|
|
|
|
@click="handleNodeClick('equipmentEntry')"
|
|
|
|
|
|
>
|
|
|
|
|
|
装备录入
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 装备退役 -->
|
|
|
|
|
|
<div
|
|
|
|
|
|
class="node retire-node"
|
2025-10-14 23:01:29 +08:00
|
|
|
|
:style="{ left: '620px', top: '60px' }"
|
|
|
|
|
|
ref="equipmentRetire"
|
2025-10-13 09:27:53 +08:00
|
|
|
|
@click="handleNodeClick('equipmentRetire')"
|
|
|
|
|
|
>
|
|
|
|
|
|
装备退役
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 录入审核 -->
|
|
|
|
|
|
<div
|
|
|
|
|
|
class="node audit-node"
|
2025-10-14 23:01:29 +08:00
|
|
|
|
:style="{ left: '40px', top: '200px' }"
|
|
|
|
|
|
ref="entryAudit"
|
2025-10-13 09:27:53 +08:00
|
|
|
|
@click="handleNodeClick('entryAudit')"
|
|
|
|
|
|
>
|
|
|
|
|
|
录入审核
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 装备台账 -->
|
|
|
|
|
|
<div
|
|
|
|
|
|
class="node ledger-node"
|
2025-10-14 23:01:29 +08:00
|
|
|
|
:style="{ left: '260px', top: '200px' }"
|
|
|
|
|
|
ref="equipmentLedger"
|
2025-10-13 09:27:53 +08:00
|
|
|
|
@click="handleNodeClick('equipmentLedger')"
|
|
|
|
|
|
>
|
|
|
|
|
|
装备台账
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 装备上架 -->
|
|
|
|
|
|
<div
|
|
|
|
|
|
class="node shelf-node"
|
2025-10-14 23:01:29 +08:00
|
|
|
|
:style="{ left: '260px', top: '340px' }"
|
|
|
|
|
|
ref="equipmentShelf"
|
2025-10-13 09:27:53 +08:00
|
|
|
|
@click="handleNodeClick('equipmentShelf')"
|
|
|
|
|
|
>
|
|
|
|
|
|
装备上架
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 自用出库 -->
|
|
|
|
|
|
<div
|
|
|
|
|
|
class="node self-out-node"
|
2025-10-14 23:01:29 +08:00
|
|
|
|
:style="{ left: '500px', top: '200px' }"
|
|
|
|
|
|
ref="selfUseOut"
|
2025-10-13 09:27:53 +08:00
|
|
|
|
@click="handleNodeClick('selfUseOut')"
|
|
|
|
|
|
>
|
|
|
|
|
|
自用出库
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 装备退库 -->
|
|
|
|
|
|
<div
|
|
|
|
|
|
class="node return-node"
|
2025-10-14 23:01:29 +08:00
|
|
|
|
:style="{ left: '740px', top: '200px' }"
|
|
|
|
|
|
ref="equipmentReturn"
|
2025-10-13 09:27:53 +08:00
|
|
|
|
@click="handleNodeClick('equipmentReturn')"
|
|
|
|
|
|
>
|
|
|
|
|
|
装备退库
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 装备维修 -->
|
|
|
|
|
|
<div
|
|
|
|
|
|
class="node repair-node"
|
2025-10-14 23:01:29 +08:00
|
|
|
|
:style="{ left: '980px', top: '200px' }"
|
|
|
|
|
|
ref="equipmentRepair"
|
2025-10-13 09:27:53 +08:00
|
|
|
|
@click="handleNodeClick('equipmentRepair')"
|
|
|
|
|
|
>
|
|
|
|
|
|
装备维修
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
2025-10-13 19:30:46 +08:00
|
|
|
|
<!-- 共享大厅 -->
|
2025-10-13 09:27:53 +08:00
|
|
|
|
<div
|
|
|
|
|
|
class="node rental-node"
|
2025-10-14 23:01:29 +08:00
|
|
|
|
:style="{ left: '500px', top: '340px' }"
|
|
|
|
|
|
ref="rentalHall"
|
2025-10-13 09:27:53 +08:00
|
|
|
|
@click="handleNodeClick('rentalHall')"
|
|
|
|
|
|
>
|
2025-10-13 19:30:46 +08:00
|
|
|
|
共享大厅
|
2025-10-13 09:27:53 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 共享出库 -->
|
|
|
|
|
|
<div
|
|
|
|
|
|
class="node share-out-node"
|
2025-10-14 23:01:29 +08:00
|
|
|
|
:style="{ left: '740px', top: '340px' }"
|
|
|
|
|
|
ref="shareOut"
|
2025-10-13 09:27:53 +08:00
|
|
|
|
@click="handleNodeClick('shareOut')"
|
|
|
|
|
|
>
|
|
|
|
|
|
共享出库
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 共享退库 -->
|
|
|
|
|
|
<div
|
|
|
|
|
|
class="node share-return-node"
|
2025-10-14 23:01:29 +08:00
|
|
|
|
:style="{ left: '980px', top: '340px' }"
|
|
|
|
|
|
ref="shareReturn"
|
2025-10-13 09:27:53 +08:00
|
|
|
|
@click="handleNodeClick('shareReturn')"
|
|
|
|
|
|
>
|
|
|
|
|
|
共享退库
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 装备下架 -->
|
|
|
|
|
|
<div
|
|
|
|
|
|
class="node off-shelf-node"
|
2025-10-14 23:01:29 +08:00
|
|
|
|
:style="{ left: '260px', top: '500px' }"
|
|
|
|
|
|
ref="equipmentOffShelf"
|
2025-10-13 09:27:53 +08:00
|
|
|
|
@click="handleNodeClick('equipmentOffShelf')"
|
|
|
|
|
|
>
|
|
|
|
|
|
装备下架
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
2025-10-14 23:01:29 +08:00
|
|
|
|
|
|
|
|
|
|
<!-- 连接线(SVG 覆盖层) -->
|
|
|
|
|
|
<svg class="connections" xmlns="http://www.w3.org/2000/svg">
|
|
|
|
|
|
<polyline
|
|
|
|
|
|
v-for="conn in connections"
|
|
|
|
|
|
:key="conn.id"
|
|
|
|
|
|
:points="conn.points"
|
|
|
|
|
|
:class="{ active: activeLine === conn.id }"
|
|
|
|
|
|
marker-end="url(#arrow)"
|
|
|
|
|
|
/>
|
|
|
|
|
|
<!-- 箭头定义,用于直线末端 -->
|
|
|
|
|
|
<defs>
|
|
|
|
|
|
<marker id="arrow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="8" markerHeight="8" orient="auto-start-reverse">
|
|
|
|
|
|
<path d="M 0 0 L 10 5 L 0 10 z" fill="#999" />
|
|
|
|
|
|
</marker>
|
|
|
|
|
|
</defs>
|
|
|
|
|
|
</svg>
|
2025-10-13 09:27:53 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 节点信息面板 -->
|
|
|
|
|
|
<div class="info-panel" v-if="activeNode">
|
|
|
|
|
|
<h3>{{ nodeInfo.name }}</h3>
|
|
|
|
|
|
<p><strong>节点类型:</strong>{{ nodeInfo.type }}</p>
|
|
|
|
|
|
<p><strong>描述:</strong>{{ nodeInfo.description }}</p>
|
|
|
|
|
|
<p><strong>后续节点:</strong>{{ nodeInfo.nextNodes }}</p>
|
|
|
|
|
|
</div>
|
2024-06-26 15:11:05 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<script>
|
|
|
|
|
|
export default {
|
2025-10-13 09:27:53 +08:00
|
|
|
|
name: 'EquipmentFlowChart',
|
2024-06-26 15:11:05 +08:00
|
|
|
|
data() {
|
|
|
|
|
|
return {
|
2025-10-13 09:27:53 +08:00
|
|
|
|
activeNode: null,
|
|
|
|
|
|
activeLine: null,
|
2025-10-14 23:01:29 +08:00
|
|
|
|
connections: [],
|
|
|
|
|
|
// 参考示意图连线定义(按布局方向设置 from/to)
|
|
|
|
|
|
lineDefs: [
|
|
|
|
|
|
{ id: 'entryToAudit', from: 'equipmentEntry', to: 'entryAudit' },
|
|
|
|
|
|
{ id: 'auditToLedger', from: 'entryAudit', to: 'equipmentLedger' },
|
|
|
|
|
|
{ id: 'ledgerToSelf', from: 'equipmentLedger', to: 'selfUseOut' },
|
|
|
|
|
|
{ id: 'selfToReturn', from: 'selfUseOut', to: 'equipmentReturn' },
|
|
|
|
|
|
{ id: 'returnToRepair', from: 'equipmentReturn', to: 'equipmentRepair' },
|
|
|
|
|
|
{ id: 'ledgerToShelf', from: 'equipmentLedger', to: 'equipmentShelf' },
|
|
|
|
|
|
{ id: 'shelfToRental', from: 'equipmentShelf', to: 'rentalHall' },
|
|
|
|
|
|
{ id: 'rentalToShareOut', from: 'rentalHall', to: 'shareOut' },
|
|
|
|
|
|
{ id: 'shareOutToShareReturn', from: 'shareOut', to: 'shareReturn' },
|
|
|
|
|
|
{ id: 'shareReturnToRepair', from: 'shareReturn', to: 'equipmentRepair' },
|
|
|
|
|
|
{ id: 'shelfToOff', from: 'equipmentShelf', to: 'equipmentOffShelf' },
|
|
|
|
|
|
// 顶部/右侧回流到退役
|
|
|
|
|
|
{ id: 'repairToRetire', from: 'equipmentRepair', to: 'equipmentRetire' },
|
|
|
|
|
|
{ id: 'ledgerToRetire', from: 'equipmentLedger', to: 'equipmentRetire' }
|
|
|
|
|
|
],
|
2025-10-13 09:27:53 +08:00
|
|
|
|
nodeData: {
|
|
|
|
|
|
equipmentEntry: {
|
|
|
|
|
|
name: '装备录入',
|
|
|
|
|
|
type: '初始节点',
|
|
|
|
|
|
description: '新增装备信息到系统中,记录装备基本属性',
|
|
|
|
|
|
nextNodes: '录入审核'
|
|
|
|
|
|
},
|
|
|
|
|
|
entryAudit: {
|
|
|
|
|
|
name: '录入审核',
|
|
|
|
|
|
type: '审核节点',
|
|
|
|
|
|
description: '对新录入的装备信息进行真实性和完整性审核',
|
|
|
|
|
|
nextNodes: '装备台账'
|
|
|
|
|
|
},
|
|
|
|
|
|
equipmentLedger: {
|
|
|
|
|
|
name: '装备台账',
|
|
|
|
|
|
type: '核心数据节点',
|
|
|
|
|
|
description: '存储和管理所有装备的基础信息及状态变动记录',
|
|
|
|
|
|
nextNodes: '装备上架、自用出库'
|
|
|
|
|
|
},
|
|
|
|
|
|
equipmentShelf: {
|
|
|
|
|
|
name: '装备上架',
|
|
|
|
|
|
type: '操作节点',
|
2025-10-13 19:30:46 +08:00
|
|
|
|
description: '将装备从库存状态转换为可共享状态,上架到共享平台',
|
|
|
|
|
|
nextNodes: '共享大厅、装备下架'
|
2025-10-13 09:27:53 +08:00
|
|
|
|
},
|
|
|
|
|
|
selfUseOut: {
|
|
|
|
|
|
name: '自用出库',
|
|
|
|
|
|
type: '操作节点',
|
|
|
|
|
|
description: '内部部门领用装备时办理的出库手续',
|
|
|
|
|
|
nextNodes: '装备退库'
|
|
|
|
|
|
},
|
|
|
|
|
|
equipmentReturn: {
|
|
|
|
|
|
name: '装备退库',
|
|
|
|
|
|
type: '操作节点',
|
|
|
|
|
|
description: '内部使用完毕后将装备归还入库的手续办理',
|
|
|
|
|
|
nextNodes: '装备维修'
|
|
|
|
|
|
},
|
|
|
|
|
|
equipmentRepair: {
|
|
|
|
|
|
name: '装备维修',
|
|
|
|
|
|
type: '处理节点',
|
|
|
|
|
|
description: '对有故障或达到维护周期的装备进行维修处理',
|
|
|
|
|
|
nextNodes: '装备退役、装备台账'
|
|
|
|
|
|
},
|
|
|
|
|
|
rentalHall: {
|
2025-10-13 19:30:46 +08:00
|
|
|
|
name: '共享大厅',
|
2025-10-13 09:27:53 +08:00
|
|
|
|
type: '展示节点',
|
2025-10-13 19:30:46 +08:00
|
|
|
|
description: '展示可共享装备信息,提供共享申请入口',
|
2025-10-13 09:27:53 +08:00
|
|
|
|
nextNodes: '共享出库'
|
|
|
|
|
|
},
|
|
|
|
|
|
shareOut: {
|
|
|
|
|
|
name: '共享出库',
|
|
|
|
|
|
type: '操作节点',
|
2025-10-13 19:30:46 +08:00
|
|
|
|
description: '外部单位共享装备时办理的出库手续',
|
2025-10-13 09:27:53 +08:00
|
|
|
|
nextNodes: '共享退库'
|
|
|
|
|
|
},
|
|
|
|
|
|
shareReturn: {
|
|
|
|
|
|
name: '共享退库',
|
|
|
|
|
|
type: '操作节点',
|
2025-10-13 19:30:46 +08:00
|
|
|
|
description: '外部单位共享装备归还时办理的入库手续',
|
2025-10-13 09:27:53 +08:00
|
|
|
|
nextNodes: '装备维修'
|
|
|
|
|
|
},
|
|
|
|
|
|
equipmentOffShelf: {
|
|
|
|
|
|
name: '装备下架',
|
|
|
|
|
|
type: '操作节点',
|
2025-10-13 19:30:46 +08:00
|
|
|
|
description: '将装备从共享平台下架,转为库存或待处理状态',
|
2025-10-13 09:27:53 +08:00
|
|
|
|
nextNodes: '装备退役'
|
|
|
|
|
|
},
|
|
|
|
|
|
equipmentRetire: {
|
|
|
|
|
|
name: '装备退役',
|
|
|
|
|
|
type: '终结节点',
|
|
|
|
|
|
description: '将达到使用年限或无法维修的装备标记为退役状态',
|
|
|
|
|
|
nextNodes: '无'
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-06-26 15:11:05 +08:00
|
|
|
|
};
|
|
|
|
|
|
},
|
2025-10-14 23:01:29 +08:00
|
|
|
|
mounted() {
|
|
|
|
|
|
this.$nextTick(this.updateConnections);
|
|
|
|
|
|
window.addEventListener('resize', this.updateConnections, { passive: true });
|
|
|
|
|
|
},
|
|
|
|
|
|
beforeDestroy() {
|
|
|
|
|
|
window.removeEventListener('resize', this.updateConnections);
|
|
|
|
|
|
},
|
2025-10-13 09:27:53 +08:00
|
|
|
|
computed: {
|
|
|
|
|
|
nodeInfo() {
|
|
|
|
|
|
return this.nodeData[this.activeNode] || {};
|
|
|
|
|
|
}
|
2024-06-26 15:11:05 +08:00
|
|
|
|
},
|
2025-10-13 09:27:53 +08:00
|
|
|
|
methods: {
|
|
|
|
|
|
handleNodeClick(nodeId) {
|
|
|
|
|
|
// 重置状态
|
|
|
|
|
|
this.activeNode = nodeId;
|
|
|
|
|
|
this.activeLine = null;
|
|
|
|
|
|
|
|
|
|
|
|
// 对于有多个出线的节点,默认高亮第一条线
|
|
|
|
|
|
if (nodeId === 'equipmentLedger') {
|
|
|
|
|
|
this.activeLine = 'ledgerToShelf';
|
|
|
|
|
|
} else if (nodeId === 'equipmentShelf') {
|
|
|
|
|
|
this.activeLine = 'shelfToRental';
|
|
|
|
|
|
} else if (nodeId === 'equipmentRepair') {
|
|
|
|
|
|
this.activeLine = 'repairToRetire';
|
|
|
|
|
|
}
|
2025-10-14 23:01:29 +08:00
|
|
|
|
},
|
|
|
|
|
|
updateConnections() {
|
|
|
|
|
|
const buildMetrics = (el) => {
|
|
|
|
|
|
if (!el) return null;
|
|
|
|
|
|
return {
|
|
|
|
|
|
left: el.offsetLeft,
|
|
|
|
|
|
top: el.offsetTop,
|
|
|
|
|
|
width: el.offsetWidth,
|
|
|
|
|
|
height: el.offsetHeight
|
|
|
|
|
|
};
|
|
|
|
|
|
};
|
|
|
|
|
|
const getEdgeAnchors = (rect) => {
|
|
|
|
|
|
const cx = rect.left + rect.width / 2;
|
|
|
|
|
|
const cy = rect.top + rect.height / 2;
|
|
|
|
|
|
return {
|
|
|
|
|
|
left: { x: rect.left, y: cy },
|
|
|
|
|
|
right: { x: rect.left + rect.width, y: cy },
|
|
|
|
|
|
top: { x: cx, y: rect.top },
|
|
|
|
|
|
bottom: { x: cx, y: rect.top + rect.height }
|
|
|
|
|
|
};
|
|
|
|
|
|
};
|
|
|
|
|
|
const conns = [];
|
|
|
|
|
|
this.lineDefs.forEach((ld) => {
|
|
|
|
|
|
const fromEl = this.$refs[ld.from];
|
|
|
|
|
|
const toEl = this.$refs[ld.to];
|
|
|
|
|
|
const f = buildMetrics(fromEl);
|
|
|
|
|
|
const t = buildMetrics(toEl);
|
|
|
|
|
|
if (!f || !t) return;
|
|
|
|
|
|
const fa = getEdgeAnchors(f);
|
|
|
|
|
|
const ta = getEdgeAnchors(t);
|
|
|
|
|
|
const dx = (t.left + t.width / 2) - (f.left + f.width / 2);
|
|
|
|
|
|
const dy = (t.top + t.height / 2) - (f.top + f.height / 2);
|
|
|
|
|
|
// 水平优先:从左右边到对侧左右边
|
|
|
|
|
|
const hStart = dx >= 0 ? fa.right : fa.left;
|
|
|
|
|
|
const hEnd = dx >= 0 ? ta.left : ta.right;
|
|
|
|
|
|
const hLen = Math.abs(hEnd.x - hStart.x) + Math.abs(hEnd.y - hStart.y);
|
|
|
|
|
|
const hMidX = (hStart.x + hEnd.x) / 2;
|
|
|
|
|
|
const hPoints = `${hStart.x},${hStart.y} ${hMidX},${hStart.y} ${hMidX},${hEnd.y} ${hEnd.x},${hEnd.y}`;
|
|
|
|
|
|
// 垂直优先:从上下边到对侧上下边
|
|
|
|
|
|
const vStart = dy >= 0 ? fa.bottom : fa.top;
|
|
|
|
|
|
const vEnd = dy >= 0 ? ta.top : ta.bottom;
|
|
|
|
|
|
const vLen = Math.abs(vEnd.x - vStart.x) + Math.abs(vEnd.y - vStart.y);
|
|
|
|
|
|
const vMidY = (vStart.y + vEnd.y) / 2;
|
|
|
|
|
|
const vPoints = `${vStart.x},${vStart.y} ${vStart.x},${vMidY} ${vEnd.x},${vMidY} ${vEnd.x},${vEnd.y}`;
|
|
|
|
|
|
// 取更短的 L 型路径
|
|
|
|
|
|
const useH = hLen <= vLen;
|
|
|
|
|
|
conns.push({ id: ld.id, points: useH ? hPoints : vPoints });
|
|
|
|
|
|
});
|
|
|
|
|
|
this.connections = conns;
|
2025-10-13 09:27:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-06-26 15:11:05 +08:00
|
|
|
|
};
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
2025-10-13 09:27:53 +08:00
|
|
|
|
<style scoped>
|
|
|
|
|
|
.flowchart-container {
|
|
|
|
|
|
position: relative;
|
|
|
|
|
|
padding: 20px;
|
|
|
|
|
|
background-color: #f8f9fa;
|
|
|
|
|
|
min-height: 100vh;
|
|
|
|
|
|
box-sizing: border-box;
|
|
|
|
|
|
}
|
2024-06-26 15:11:05 +08:00
|
|
|
|
|
2025-10-13 09:27:53 +08:00
|
|
|
|
.flowchart-title {
|
|
|
|
|
|
text-align: center;
|
|
|
|
|
|
color: #333;
|
|
|
|
|
|
margin-bottom: 30px;
|
|
|
|
|
|
font-size: 24px;
|
|
|
|
|
|
}
|
2024-06-26 15:11:05 +08:00
|
|
|
|
|
2025-10-13 09:27:53 +08:00
|
|
|
|
.flowchart-wrapper {
|
|
|
|
|
|
position: relative;
|
2025-10-14 23:01:29 +08:00
|
|
|
|
width: 1200px;
|
2025-10-13 09:27:53 +08:00
|
|
|
|
height: 700px;
|
|
|
|
|
|
margin: 0 auto;
|
|
|
|
|
|
background-color: white;
|
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
|
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
|
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
}
|
2024-06-26 15:11:05 +08:00
|
|
|
|
|
2025-10-13 09:27:53 +08:00
|
|
|
|
/* 连接线样式 */
|
|
|
|
|
|
.connections {
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
top: 0;
|
|
|
|
|
|
left: 0;
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
height: 100%;
|
|
|
|
|
|
pointer-events: none;
|
|
|
|
|
|
}
|
2024-06-26 15:11:05 +08:00
|
|
|
|
|
2025-10-14 23:01:29 +08:00
|
|
|
|
line, path, polyline {
|
2025-10-13 09:27:53 +08:00
|
|
|
|
stroke: #999;
|
|
|
|
|
|
stroke-width: 2px;
|
|
|
|
|
|
fill: none;
|
|
|
|
|
|
transition: all 0.3s ease;
|
|
|
|
|
|
}
|
2024-06-26 15:11:05 +08:00
|
|
|
|
|
2025-10-14 23:01:29 +08:00
|
|
|
|
line.active, path.active, polyline.active {
|
2025-10-13 09:27:53 +08:00
|
|
|
|
stroke: #ff4500;
|
|
|
|
|
|
stroke-width: 2.5px;
|
|
|
|
|
|
}
|
2024-06-26 15:11:05 +08:00
|
|
|
|
|
2025-10-13 09:27:53 +08:00
|
|
|
|
path {
|
|
|
|
|
|
stroke-dasharray: none;
|
|
|
|
|
|
}
|
2024-06-26 15:11:05 +08:00
|
|
|
|
|
2025-10-13 09:27:53 +08:00
|
|
|
|
/* 节点样式 */
|
|
|
|
|
|
.nodes {
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
top: 0;
|
|
|
|
|
|
left: 0;
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
height: 100%;
|
|
|
|
|
|
}
|
2024-06-26 15:11:05 +08:00
|
|
|
|
|
2025-10-13 09:27:53 +08:00
|
|
|
|
.node {
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
width: 120px;
|
|
|
|
|
|
height: 60px;
|
|
|
|
|
|
border-radius: 6px;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
transition: all 0.2s ease;
|
|
|
|
|
|
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.node:hover {
|
|
|
|
|
|
transform: translateY(-2px);
|
|
|
|
|
|
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 节点类型样式 */
|
|
|
|
|
|
.entry-node {
|
|
|
|
|
|
background-color: #e6f7ff;
|
|
|
|
|
|
border: 2px solid #409EFF;
|
|
|
|
|
|
color: #333;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.retire-node {
|
|
|
|
|
|
background-color: #ffe3e0;
|
|
|
|
|
|
border: 2px solid #f5222d;
|
|
|
|
|
|
color: #333;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.audit-node, .repair-node, .shelf-node, .off-shelf-node {
|
|
|
|
|
|
background-color: #f0fff3;
|
|
|
|
|
|
border: 2px solid #52c41a;
|
|
|
|
|
|
color: #333;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.ledger-node {
|
|
|
|
|
|
background-color: #fff1e8;
|
|
|
|
|
|
border: 2px solid #fa8c16;
|
|
|
|
|
|
color: #333;
|
|
|
|
|
|
width: 140px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.self-out-node, .return-node, .share-out-node, .share-return-node {
|
|
|
|
|
|
background-color: #f0e6ff;
|
|
|
|
|
|
border: 2px solid #722ed1;
|
|
|
|
|
|
color: #333;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.rental-node {
|
|
|
|
|
|
background-color: #ffe6f2;
|
|
|
|
|
|
border: 2px solid #eb2f96;
|
|
|
|
|
|
color: #333;
|
|
|
|
|
|
width: 140px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 选中节点样式 */
|
|
|
|
|
|
.node.active {
|
|
|
|
|
|
border-color: #ff4500;
|
|
|
|
|
|
border-width: 2.5px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 信息面板 */
|
|
|
|
|
|
.info-panel {
|
|
|
|
|
|
position: fixed;
|
|
|
|
|
|
right: 30px;
|
|
|
|
|
|
top: 50%;
|
|
|
|
|
|
transform: translateY(-50%);
|
|
|
|
|
|
width: 250px;
|
|
|
|
|
|
background-color: white;
|
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
|
box-shadow: 0 3px 15px rgba(0, 0, 0, 0.15);
|
|
|
|
|
|
padding: 15px;
|
|
|
|
|
|
border-left: 4px solid #409EFF;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.info-panel h3 {
|
|
|
|
|
|
margin-top: 0;
|
|
|
|
|
|
color: #409EFF;
|
|
|
|
|
|
border-bottom: 1px solid #eee;
|
|
|
|
|
|
padding-bottom: 10px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.info-panel p {
|
|
|
|
|
|
margin: 10px 0;
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
color: #666;
|
2024-06-26 15:11:05 +08:00
|
|
|
|
}
|
|
|
|
|
|
</style>
|