Commit 2418f8cb by suyuchen

feat(tickets): 重构工单管理界面并添加沟通功能

- 将服务管理重命名为收费管理 - 添加通信历史记录功能及样式 - 重置表格列结构,更新工单列表显示字段 - 添加服务订单号输入和显示功能 - 实现工单沟通弹窗和消息发送功能 - 添加工单删除确认功能 - 创建工单新增页面 - 在工单操作
parent bb1b815d
...@@ -43,9 +43,12 @@ flowchart TD ...@@ -43,9 +43,12 @@ flowchart TD
%% 维修工单 %% 维修工单
T1 -- 维修工单 --> R1[提交维修需求] T1 -- 维修工单 --> R1[提交维修需求]
R1 --> RB1{收到报价单} R1 --> RB1{收到报价单}
RB1 -- 是 --> RC1[确认报价 或 拒绝报价]
RB1 -- 同意报价 --> RC1[确认报价]
RB1 -- 拒绝报价 --> RE1[拒绝报价\n工单结束]
RB1 -- 价格不合适 --> RF1[要求重新报价]
RC1 --> RD1[等待维修完成] RC1 --> RD1[等待维修完成]
RB1 -- 否 --> RE1[无进一步行动]
%% 普通工单 %% 普通工单
T1 -- 普通工单 --> N1[描述问题并提交] T1 -- 普通工单 --> N1[描述问题并提交]
...@@ -71,11 +74,15 @@ flowchart TD ...@@ -71,11 +74,15 @@ flowchart TD
T2 -- 维修工单 --> B2{评估维修需求} T2 -- 维修工单 --> B2{评估维修需求}
B2 --> C2[生成报价单\n- 项目明细\n- 配件/人工费用\n- 总金额\n- 有效期1个月] B2 --> C2[生成报价单\n- 项目明细\n- 配件/人工费用\n- 总金额\n- 有效期1个月]
C2 --> D2[发送报价单\n账号/邮件/电话] C2 --> D2[发送报价单\n账号/邮件/电话]
D2 --> E2{1个月内确认?}
E2 -- 是 --> F2[安排并执行维修] D2 --> E2{客户反馈}
E2 -- 否 --> G2[报价失效\n重新评估]
F2 --> H2[完成维修服务] E2 -- 同意 --> F2[安排并执行维修]
E2 -- 拒绝 --> J2[关闭工单]
E2 -- 价格不合适 --> G2[重新评估维修需求]
G2 --> B2 G2 --> B2
F2 --> H2[完成维修服务]
%% ========= 普通工单 ========= %% ========= 普通工单 =========
T2 -- 普通工单 --> N5[受理工单] T2 -- 普通工单 --> N5[受理工单]
...@@ -100,6 +107,7 @@ flowchart TD ...@@ -100,6 +107,7 @@ flowchart TD
A1 --> A2 A1 --> A2
D2 --> RB1 D2 --> RB1
RC1 --> H2 RC1 --> H2
RF1 --> G2
``` ```
![列表图](./img_3.png) ![列表图](./img_4.png)
\ No newline at end of file \ No newline at end of file
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
<path d="M4 4h12a2 2 0 012 2v8a2 2 0 01-2 2H4a2 2 0 01-2-2V6a2 2 0 012-2z"/> <path d="M4 4h12a2 2 0 012 2v8a2 2 0 01-2 2H4a2 2 0 01-2-2V6a2 2 0 012-2z"/>
<path d="M7 9h6M7 12h4"/> <path d="M7 9h6M7 12h4"/>
</svg> </svg>
<span>服务管理</span> <span>收费管理</span>
</div> </div>
<svg class="nav-arrow nav-icon" viewBox="0 0 20 20"> <svg class="nav-arrow nav-icon" viewBox="0 0 20 20">
<path d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z"/> <path d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z"/>
......
img_6.png

47.8 KB

...@@ -950,6 +950,47 @@ ...@@ -950,6 +950,47 @@
gap: 8px; gap: 8px;
} }
.communication-history {
max-height: 300px;
overflow-y: auto;
border: 1px solid var(--border-color);
border-radius: 6px;
padding: 16px;
margin-bottom: 16px;
background: var(--bg-color);
}
.communication-message {
margin-bottom: 16px;
padding-bottom: 16px;
border-bottom: 1px solid var(--border-color);
}
.communication-message:last-child {
border-bottom: none;
margin-bottom: 0;
padding-bottom: 0;
}
.communication-message-header {
display: flex;
justify-content: space-between;
margin-bottom: 8px;
font-size: 14px;
font-weight: 500;
color: var(--text-primary);
}
.communication-message-content {
font-size: 14px;
color: var(--text-secondary);
line-height: 1.5;
}
.communication-send {
margin-top: 16px;
}
.file-item { .file-item {
display: flex; display: flex;
align-items: center; align-items: center;
...@@ -1626,7 +1667,7 @@ ...@@ -1626,7 +1667,7 @@
</svg> </svg>
导出 导出
</button> </button>
<button class="btn btn-secondary">批量操作</button> <!-- <button class="btn btn-secondary">批量操作</button>-->
</div> </div>
</div> </div>
...@@ -1668,24 +1709,27 @@ ...@@ -1668,24 +1709,27 @@
<input type="checkbox"> <input type="checkbox">
</th> </th>
<th class="sortable" data-sort="ticketNo"> <th class="sortable" data-sort="ticketNo">
工单号 工单
<span class="sort-icon"></span> <span class="sort-icon"></span>
</th> </th>
<th>客户名称 / 国家</th> <th>问题类型</th>
<th>设备信息</th> <th>状态</th>
<th class="sortable" data-sort="submitTime"> <th class="sortable">
提交时间 答复人
<span class="sort-icon"></span>
</th> </th>
<th class="sortable" data-sort="priority"> <th class="sortable">
优先级 标题
<span class="sort-icon"></span>
</th> </th>
<th>SLA 状态</th> <th>创建时间</th>
<th>当前处理人</th> <th>提交人员</th>
<th>工单状态</th> <th>更新时间</th>
<th>问题分类</th> <th>价格</th>
<th>来源类型</th> <th>SLA计时</th>
<th>客户名称</th>
<th>服务订单号</th>
<th>设备信息</th>
<th>设备序列号</th>
<th>国家/地区</th>
<th>操作</th> <th>操作</th>
</tr> </tr>
</thead> </thead>
...@@ -1696,33 +1740,26 @@ ...@@ -1696,33 +1740,26 @@
<a href="ticket-detail.html?id=TK-2024-001" class="ticket-link">#TK-2024-001</a> <a href="ticket-detail.html?id=TK-2024-001" class="ticket-link">#TK-2024-001</a>
<span class="unread-dot"></span> <span class="unread-dot"></span>
</td> </td>
<td>ABC 公司<br><span style="color: var(--text-tertiary); font-size: 12px;">中国</span></td>
<td>
<div>服务器集群-A</div>
<span style="color: var(--text-tertiary); font-size: 12px;">SN: SRV-2024-001</span>
</td>
<td>2024-01-15<br><span style="color: var(--text-tertiary); font-size: 12px;">10:30:25</span></td>
<td><span class="priority-tag priority-t1">T1</span></td>
<td>
<span class="status-badge status-danger">
<svg width="12" height="12" viewBox="0 0 12 12" fill="currentColor">
<path d="M6 2L2 6h2v4h4V6h2L6 2z"/>
</svg>
已逾期
</span>
</td>
<td>张三</td>
<td><span class="status-badge status-processing">处理中</span></td>
<td>硬件故障 / 服务器</td> <td>硬件故障 / 服务器</td>
<td> <td><span class="status-badge status-processing">处理中</span></td>
<span class="source-badge source-web">Web 门户</span> <td>张三</td>
</td> <td>服务器无法启动</td>
<td>2024-01-15<br><span style="color: var(--text-tertiary); font-size: 12px;">10:30:25</span></td>
<td>系统</td>
<td>2024-01-15<br><span style="color: var(--text-tertiary); font-size: 12px;">14:20:10</span></td>
<td>100 元</td>
<td>2小时45分钟</td>
<td>ABC 公司</td>
<td>SO-2024-001</td>
<td>服务器集群-A</td>
<td>SRV-2024-001</td>
<td>中国</td>
<td> <td>
<div class="action-btns"> <div class="action-btns">
<button class="action-btn" onclick="openDetailModal('TK-2024-001')">查看</button>
<button class="action-btn" onclick="openEditModal('TK-2024-001')">编辑</button> <button class="action-btn" onclick="openEditModal('TK-2024-001')">编辑</button>
<!-- <button class="action-btn" onclick="openTransferModal('TK-2024-001')">移交</button> <button class="action-btn" onclick="openDetailModal('TK-2024-001')">查看</button>
<button class="action-btn" onclick="openEscalateModal('TK-2024-001')">升级</button> --> <button class="action-btn" onclick="openCommunicationModal('TK-2024-001')">沟通</button>
<button class="action-btn" onclick="deleteTicket('TK-2024-001')">删除</button>
</div> </div>
</td> </td>
</tr> </tr>
...@@ -1731,33 +1768,26 @@ ...@@ -1731,33 +1768,26 @@
<td> <td>
<a href="ticket-detail.html?id=TK-2024-002" class="ticket-link">#TK-2024-002</a> <a href="ticket-detail.html?id=TK-2024-002" class="ticket-link">#TK-2024-002</a>
</td> </td>
<td>XYZ 科技<br><span style="color: var(--text-tertiary); font-size: 12px;">美国</span></td> <td>软件故障 / 应用程序</td>
<td> <td><span class="status-badge status-warning">待响应</span></td>
<div>数据库-DB01</div> <td>李四</td>
<span style="color: var(--text-tertiary); font-size: 12px;">SN: DB-2024-002</span> <td>应用程序频繁崩溃</td>
</td> <td>2024-01-15<br><span style="color: var(--text-tertiary); font-size: 12px;">09:15:30</span></td>
<td>2024-01-15<br><span style="color: var(--text-tertiary); font-size: 12px;">09:15:10</span></td> <td>王五</td>
<td><span class="priority-tag priority-t2">T2</span></td> <td>2024-01-15<br><span style="color: var(--text-tertiary); font-size: 12px;">09:15:30</span></td>
<td> <td>50 元</td>
<span class="status-badge status-warning"> <td>3小时10分钟</td>
<svg width="12" height="12" viewBox="0 0 12 12" fill="currentColor"> <td>XYZ 有限公司</td>
<path d="M6 2v8M6 10h.01"/> <td>SO-2024-002</td>
</svg> <td>工作站-WK001</td>
预警 <td>WK-2024-001</td>
</span> <td>中国</td>
</td>
<td>张三</td>
<td><span class="status-badge status-waiting">待客户</span></td>
<td>软件问题 / 数据库</td>
<td>
<span class="source-badge source-email">邮件</span>
</td>
<td> <td>
<div class="action-btns"> <div class="action-btns">
<button class="action-btn" onclick="openDetailModal('TK-2024-002')">查看</button>
<button class="action-btn" onclick="openEditModal('TK-2024-002')">编辑</button> <button class="action-btn" onclick="openEditModal('TK-2024-002')">编辑</button>
<!-- <button class="action-btn" onclick="openTransferModal('TK-2024-002')">移交</button> <button class="action-btn" onclick="openDetailModal('TK-2024-002')">查看</button>
<button class="action-btn" onclick="openEscalateModal('TK-2024-002')">升级</button> --> <button class="action-btn" onclick="openCommunicationModal('TK-2024-002')">沟通</button>
<button class="action-btn" onclick="deleteTicket('TK-2024-002')">删除</button>
</div> </div>
</td> </td>
</tr> </tr>
...@@ -1766,33 +1796,26 @@ ...@@ -1766,33 +1796,26 @@
<td> <td>
<a href="ticket-detail.html?id=TK-2024-003" class="ticket-link">#TK-2024-003</a> <a href="ticket-detail.html?id=TK-2024-003" class="ticket-link">#TK-2024-003</a>
</td> </td>
<td>DEF 集团<br><span style="color: var(--text-tertiary); font-size: 12px;">欧洲</span></td> <td>网络故障 / 连接中断</td>
<td> <td><span class="status-badge status-danger">已逾期</span></td>
<div>网络设备-NW01</div> <td>赵六</td>
<span style="color: var(--text-tertiary); font-size: 12px;">SN: NW-2024-003</span> <td>网络连接频繁断开</td>
</td> <td>2024-01-14<br><span style="color: var(--text-tertiary); font-size: 12px;">16:45:20</span></td>
<td>2024-01-14<br><span style="color: var(--text-tertiary); font-size: 12px;">16:45:30</span></td> <td>陈七</td>
<td><span class="priority-tag priority-t3">T3</span></td> <td>2024-01-14<br><span style="color: var(--text-tertiary); font-size: 12px;">18:30:15</span></td>
<td> <td>80 元</td>
<span class="status-badge status-normal"> <td>22小时15分钟</td>
<svg width="12" height="12" viewBox="0 0 12 12" fill="currentColor"> <td>DEF 集团</td>
<path d="M10 3L4.5 8.5 2 6"/> <td>SO-2024-003</td>
</svg> <td>路由器-RTR001</td>
正常 <td>RTR-2024-003</td>
</span> <td>美国</td>
</td>
<td>张三</td>
<td><span class="status-badge status-processing">处理中</span></td>
<td>网络问题 / 连接</td>
<td>
<span class="source-badge source-api">API 接口</span>
</td>
<td> <td>
<div class="action-btns"> <div class="action-btns">
<button class="action-btn" onclick="openDetailModal('TK-2024-003')">查看</button>
<button class="action-btn" onclick="openEditModal('TK-2024-003')">编辑</button> <button class="action-btn" onclick="openEditModal('TK-2024-003')">编辑</button>
<!-- <button class="action-btn" onclick="openTransferModal('TK-2024-003')">移交</button> <button class="action-btn" onclick="openDetailModal('TK-2024-003')">查看</button>
<button class="action-btn" onclick="openEscalateModal('TK-2024-003')">升级</button> --> <button class="action-btn" onclick="openCommunicationModal('TK-2024-003')">沟通</button>
<button class="action-btn" onclick="deleteTicket('TK-2024-003')">删除</button>
</div> </div>
</td> </td>
</tr> </tr>
...@@ -1802,68 +1825,26 @@ ...@@ -1802,68 +1825,26 @@
<a href="ticket-detail.html?id=TK-2024-004" class="ticket-link">#TK-2024-004</a> <a href="ticket-detail.html?id=TK-2024-004" class="ticket-link">#TK-2024-004</a>
<span class="unread-dot"></span> <span class="unread-dot"></span>
</td> </td>
<td>GHI 公司<br><span style="color: var(--text-tertiary); font-size: 12px;">中国</span></td> <td>硬件故障 / 打印机</td>
<td> <td><span class="status-badge status-normal">已解决</span></td>
<div>应用服务器-APP01</div> <td>孙八</td>
<span style="color: var(--text-tertiary); font-size: 12px;">SN: APP-2024-004</span> <td>打印机无法打印</td>
</td> <td>2024-01-14<br><span style="color: var(--text-tertiary); font-size: 12px;">14:20:10</span></td>
<td>2024-01-14<br><span style="color: var(--text-tertiary); font-size: 12px;">14:20:15</span></td> <td>周九</td>
<td><span class="priority-tag priority-t1">T1</span></td> <td>2024-01-14<br><span style="color: var(--text-tertiary); font-size: 12px;">15:45:30</span></td>
<td> <td>-</td>
<span class="status-badge status-warning"> <td>-</td>
<svg width="12" height="12" viewBox="0 0 12 12" fill="currentColor"> <td>GHI 企业</td>
<path d="M6 2v8M6 10h.01"/> <td>SO-2024-004</td>
</svg> <td>激光打印机-LP001</td>
预警 <td>LP-2024-0888</td>
</span> <td>日本</td>
</td>
<td>张三</td>
<td><span class="status-badge status-processing">处理中</span></td>
<td>性能问题 / 应用</td>
<td>
<span class="source-badge source-phone">电话</span>
</td>
<td> <td>
<div class="action-btns"> <div class="action-btns">
<button class="action-btn" onclick="openDetailModal('TK-2024-004')">查看</button>
<button class="action-btn" onclick="openEditModal('TK-2024-004')">编辑</button> <button class="action-btn" onclick="openEditModal('TK-2024-004')">编辑</button>
<!-- <button class="action-btn" onclick="openTransferModal('TK-2024-004')">移交</button> <button class="action-btn" onclick="openDetailModal('TK-2024-004')">查看</button>
<button class="action-btn" onclick="openEscalateModal('TK-2024-004')">升级</button> --> <button class="action-btn" onclick="openCommunicationModal('TK-2024-004')">沟通</button>
</div> <button class="action-btn" onclick="deleteTicket('TK-2024-004')">删除</button>
</td>
</tr>
<tr>
<td><input type="checkbox"></td>
<td>
<a href="ticket-detail.html?id=TK-2024-005" class="ticket-link">#TK-2024-005</a>
</td>
<td>JKL 科技<br><span style="color: var(--text-tertiary); font-size: 12px;">美国</span></td>
<td>
<div>存储设备-STOR01</div>
<span style="color: var(--text-tertiary); font-size: 12px;">SN: STO-2024-005</span>
</td>
<td>2024-01-13<br><span style="color: var(--text-tertiary); font-size: 12px;">11:30:42</span></td>
<td><span class="priority-tag priority-t4">T4</span></td>
<td>
<span class="status-badge status-normal">
<svg width="12" height="12" viewBox="0 0 12 12" fill="currentColor">
<path d="M10 3L4.5 8.5 2 6"/>
</svg>
正常
</span>
</td>
<td>张三</td>
<td><span class="status-badge status-pending">待响应</span></td>
<td>咨询问题 / 使用</td>
<td>
<span class="source-badge source-chat">在线客服</span>
</td>
<td>
<div class="action-btns">
<button class="action-btn" onclick="openDetailModal('TK-2024-005')">查看</button>
<button class="action-btn" onclick="openEditModal('TK-2024-005')">编辑</button>
<!-- <button class="action-btn" onclick="openTransferModal('TK-2024-005')">移交</button>
<button class="action-btn" onclick="openEscalateModal('TK-2024-005')">升级</button> -->
</div> </div>
</td> </td>
</tr> </tr>
...@@ -2155,6 +2136,11 @@ ...@@ -2155,6 +2136,11 @@
<input type="text" class="form-input" id="editTicketId" readonly> <input type="text" class="form-input" id="editTicketId" readonly>
</div> </div>
<div class="form-group">
<label class="form-label">服务订单号</label>
<input type="text" class="form-input" id="editServiceOrderNo" placeholder="请输入服务订单号">
</div>
<div class="form-row"> <div class="form-row">
<div class="form-group"> <div class="form-group">
<label class="form-label">客户名称 <span style="color: var(--danger-color);">*</span></label> <label class="form-label">客户名称 <span style="color: var(--danger-color);">*</span></label>
...@@ -2317,6 +2303,38 @@ ...@@ -2317,6 +2303,38 @@
</div> </div>
</div> </div>
<!-- 通信弹窗 -->
<div class="modal-overlay" id="communicationModal">
<div class="modal" style="max-width: 800px;">
<div class="modal-header">
<h2 class="modal-title">工单沟通 - <span id="communicationTicketId">#TK-2024-001</span></h2>
<button class="modal-close" onclick="closeCommunicationModal()">
<svg class="nav-icon" viewBox="0 0 20 20" style="width: 20px; height: 20px;">
<path d="M6 6l8 8M14 6l-8 8"/>
</svg>
</button>
</div>
<div class="modal-body">
<!-- 沟通历史 -->
<div class="communication-history" id="communicationHistory">
<!-- 沟通历史将通过JavaScript动态生成 -->
</div>
<!-- 发送消息区域 -->
<div class="communication-send">
<div class="form-group">
<label class="form-label">发送消息</label>
<textarea class="form-input" id="messageInput" rows="3" placeholder="输入要发送的消息..."></textarea>
</div>
</div>
</div>
<div class="modal-footer">
<button class="btn-secondary" onclick="closeCommunicationModal()">取消</button>
<button class="btn-primary" onclick="sendMessage(document.getElementById('communicationTicketId').textContent.replace('#', ''))">发送消息</button>
</div>
</div>
</div>
<script> <script>
// 文件上传相关变量 // 文件上传相关变量
let newTicketFiles = []; let newTicketFiles = [];
...@@ -2992,7 +3010,9 @@ ...@@ -2992,7 +3010,9 @@
// 打开新增工单弹窗 // 打开新增工单弹窗
function openNewTicketModal() { function openNewTicketModal() {
document.getElementById('newTicketModal').classList.add('active'); window.location.href = '工单新增.html'
// document.getElementById('newTicketModal').classList.add('active');
} }
// 关闭新增工单弹窗 // 关闭新增工单弹窗
...@@ -3289,6 +3309,8 @@ ...@@ -3289,6 +3309,8 @@
// 打开编辑弹窗 // 打开编辑弹窗
function openEditModal(ticketId) { function openEditModal(ticketId) {
window.location.href = '工单新增.html'
return;
const modal = document.getElementById('editModal'); const modal = document.getElementById('editModal');
document.getElementById('editTicketId').value = '#' + ticketId; document.getElementById('editTicketId').value = '#' + ticketId;
...@@ -3309,6 +3331,12 @@ ...@@ -3309,6 +3331,12 @@
document.getElementById('editCountry').value = countrySpan.textContent.trim(); document.getElementById('editCountry').value = countrySpan.textContent.trim();
} }
// 填充服务订单号 (cells[13] 是新增的附加服务订单号列)
if (cells.length > 13) {
const serviceOrderNo = cells[13].textContent.trim();
document.getElementById('editServiceOrderNo').value = serviceOrderNo;
}
// 填充设备信息 // 填充设备信息
const deviceDiv = cells[3].querySelector('div'); const deviceDiv = cells[3].querySelector('div');
if (deviceDiv) { if (deviceDiv) {
...@@ -3370,6 +3398,7 @@ ...@@ -3370,6 +3398,7 @@
document.getElementById('editStatus').value = ''; document.getElementById('editStatus').value = '';
document.getElementById('editAssignee').value = ''; document.getElementById('editAssignee').value = '';
document.getElementById('editDescription').value = ''; document.getElementById('editDescription').value = '';
document.getElementById('editServiceOrderNo').value = '';
// 清空文件列表 // 清空文件列表
editTicketFiles = []; editTicketFiles = [];
renderEditFileList(); renderEditFileList();
...@@ -3389,6 +3418,7 @@ ...@@ -3389,6 +3418,7 @@
const status = document.getElementById('editStatus').value; const status = document.getElementById('editStatus').value;
const assignee = document.getElementById('editAssignee').value; const assignee = document.getElementById('editAssignee').value;
const description = document.getElementById('editDescription').value.trim(); const description = document.getElementById('editDescription').value.trim();
const serviceOrderNo = document.getElementById('editServiceOrderNo').value.trim();
if (!customer || !country || !device || !priority || !description) { if (!customer || !country || !device || !priority || !description) {
alert('请填写所有必填项'); alert('请填写所有必填项');
...@@ -3441,6 +3471,11 @@ ...@@ -3441,6 +3471,11 @@
// 更新当前处理人 // 更新当前处理人
cells[7].textContent = assignee || cells[7].textContent; cells[7].textContent = assignee || cells[7].textContent;
// 更新服务订单号 (cells[13] 是新增的附加服务订单号列)
if (cells.length > 13 && serviceOrderNo) {
cells[13].textContent = serviceOrderNo;
}
// 重新初始化工单数据(因为表格内容已更新) // 重新初始化工单数据(因为表格内容已更新)
initTickets(); initTickets();
} }
...@@ -3449,6 +3484,76 @@ ...@@ -3449,6 +3484,76 @@
closeEditModal(); closeEditModal();
} }
// 通信弹窗相关函数
function openCommunicationModal(ticketId) {
// 显示通信弹窗
document.getElementById('communicationModal').classList.add('active');
// 设置工单ID
document.getElementById('communicationTicketId').textContent = '#' + ticketId;
// 这里可以加载通信历史记录
loadCommunicationHistory(ticketId);
}
function closeCommunicationModal() {
document.getElementById('communicationModal').classList.remove('active');
}
function loadCommunicationHistory(ticketId) {
// 加载通信历史记录的逻辑
// 为了演示,我们添加一些模拟数据
const historyContainer = document.getElementById('communicationHistory');
if (historyContainer) {
historyContainer.innerHTML = `
<div class="communication-message">
<div class="communication-message-header">
<span>张三 - 技术支持</span>
<span>2024-01-15 10:35</span>
</div>
<div class="communication-message-content">
收到工单,正在检查服务器状态。
</div>
</div>
<div class="communication-message">
<div class="communication-message-header">
<span>李四 - 客户代表</span>
<span>2024-01-15 11:00</span>
</div>
<div class="communication-message-content">
服务器突然无法启动,影响了生产线,请尽快处理。
</div>
</div>
`;
}
}
function sendMessage(ticketId) {
const messageInput = document.getElementById('messageInput');
const message = messageInput.value.trim();
if (message) {
// 发送消息的逻辑
console.log('Sending message for ticket:', ticketId, 'Message:', message);
messageInput.value = '';
// 可以在这里添加实际的消息发送逻辑
alert('消息已发送!');
}
}
// 删除工单函数
function deleteTicket(ticketId) {
if (confirm('确定要删除工单 #' + ticketId + ' 吗?此操作不可撤销。')) {
console.log('Deleting ticket:', ticketId);
// 这里可以添加实际的删除逻辑
alert('工单 #' + ticketId + ' 已删除');
// 可以刷新工单列表或移除行
initTickets();
}
}
// 点击弹窗外部关闭 // 点击弹窗外部关闭
document.getElementById('newTicketModal').addEventListener('click', function(e) { document.getElementById('newTicketModal').addEventListener('click', function(e) {
if (e.target === this) { if (e.target === this) {
......
<!DOCTYPE html>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>工单</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
:root {
--primary-color: #1B64F3;
--primary-hover: #1554D3;
--primary-light: #e6f7ff;
--bg-color: #F5F6FA;
--card-bg: #FFFFFF;
--sidebar-bg: #0F172A;
--text-primary: #1A1F36;
--text-secondary: #64748B;
--text-tertiary: #94A3B8;
--text-light: #CBD5E1;
--border-color: #E2E8F0;
--shadow-sm: 0 2px 8px rgba(0, 0, 0, 0.06);
--shadow-md: 0 4px 12px rgba(0, 0, 0, 0.08);
--success-color: #22C55E;
--warning-color: #EAB308;
--error-color: #EF4444;
--sidebar-width: 260px;
--header-height: 64px;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: "PingFang SC", "Microsoft YaHei", sans-serif;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Helvetica Neue', Arial, 'PingFang SC', 'Microsoft YaHei', sans-serif;
background-color: var(--bg-color);
color: var(--text-primary);
line-height: 1.6;
overflow-x: hidden;
}
.app-container {
display: flex;
min-height: 100vh;
}
/* 左侧导航栏 */
.sidebar {
position: fixed;
left: 0;
top: 0;
width: var(--sidebar-width);
height: 100vh;
background: var(--sidebar-bg);
border-right: 1px solid rgba(255, 255, 255, 0.1);
overflow-y: auto;
z-index: 1000;
}
.sidebar-logo {
padding: 20px;
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
display: flex;
align-items: center;
gap: 12px;
}
.logo-icon {
width: 36px;
height: 36px;
background: var(--primary-color);
border-radius: 8px;
display: flex;
align-items: center;
justify-content: center;
color: white;
font-weight: 700;
font-size: 18px;
}
.logo-text {
color: white;
font-size: 16px;
font-weight: 600;
}
.sidebar-menu {
padding: 16px 0;
}
.nav-group-title {
padding: 12px 20px 8px;
font-size: 11px;
font-weight: 600;
color: var(--text-tertiary);
text-transform: uppercase;
letter-spacing: 0.5px;
}
.menu-item, .nav-item {
display: flex;
align-items: center;
gap: 12px;
padding: 12px 20px;
color: var(--text-light);
text-decoration: none;
font-size: 14px;
font-weight: 500;
transition: all 0.2s;
position: relative;
cursor: pointer;
border: none;
background: none;
width: 100%;
text-align: left;
}
.menu-item:hover, .nav-item:hover {
background: rgba(27, 100, 243, 0.15);
color: white;
}
.menu-item.active, .nav-item.active {
background: rgba(27, 100, 243, 0.2);
color: white;
}
.nav-item.active::before {
content: '';
position: absolute;
left: 0;
top: 0;
bottom: 0;
width: 3px;
background: var(--primary-color);
}
.nav-item.has-submenu {
justify-content: space-between;
}
.nav-arrow {
width: 14px;
height: 14px;
transition: transform 0.2s;
margin-left: auto;
}
.nav-item.expanded .nav-arrow {
transform: rotate(90deg);
}
.nav-submenu {
display: none;
background: rgba(0, 0, 0, 0.1);
}
.nav-item.expanded + .nav-submenu {
display: block;
}
.nav-subitem {
display: flex;
align-items: center;
gap: 12px;
padding: 10px 20px 10px 48px;
color: var(--text-light);
text-decoration: none;
font-size: 13px;
font-weight: 500;
transition: all 0.2s;
position: relative;
}
.nav-subitem:hover {
background: rgba(27, 100, 243, 0.15);
color: white;
}
.nav-subitem.active {
background: rgba(27, 100, 243, 0.2);
color: white;
}
.nav-icon {
width: 18px;
height: 18px;
stroke: currentColor;
stroke-width: 2;
fill: none;
stroke-linecap: round;
stroke-linejoin: round;
}
/* 顶部工具栏 */
.header, .top-header {
position: fixed;
top: 0;
left: var(--sidebar-width);
right: 0;
height: var(--header-height);
background: var(--card-bg);
border-bottom: 1px solid var(--border-color);
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 32px;
z-index: 999;
box-shadow: var(--shadow-sm);
}
.header-left {
display: flex;
align-items: center;
gap: 24px;
}
.breadcrumb {
display: flex;
align-items: center;
gap: 8px;
font-size: 14px;
color: var(--text-secondary);
}
.breadcrumb-separator {
color: var(--text-tertiary);
}
.breadcrumb-current {
color: var(--text-primary);
font-weight: 500;
}
.header-right {
display: flex;
align-items: center;
gap: 16px;
}
.header-icon-btn {
position: relative;
width: 36px;
height: 36px;
border-radius: 8px;
border: none;
background: transparent;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
color: var(--text-secondary);
transition: all 0.2s;
}
.header-icon-btn:hover {
background: var(--bg-color);
color: var(--primary-color);
}
.notification-badge {
position: absolute;
top: 6px;
right: 6px;
width: 8px;
height: 8px;
background: var(--error-color);
border-radius: 50%;
border: 2px solid var(--card-bg);
}
.lang-switcher {
display: flex;
gap: 6px;
align-items: center;
}
.lang-btn {
padding: 6px 12px;
background: transparent;
border: 1px solid var(--border-color);
border-radius: 6px;
color: var(--text-secondary);
font-size: 13px;
cursor: pointer;
transition: all 0.2s;
}
.lang-btn:hover {
border-color: var(--primary-color);
color: var(--primary-color);
background: rgba(27, 100, 243, 0.05);
}
.lang-btn.active {
background: var(--primary-color);
border-color: var(--primary-color);
color: white;
}
.user-avatar {
width: 36px;
height: 36px;
border-radius: 8px;
background: var(--primary-color);
color: white;
display: flex;
align-items: center;
justify-content: center;
font-weight: 600;
font-size: 14px;
cursor: pointer;
}
.page-title {
font-size: 20px;
font-weight: 600;
color: var(--text-primary);
}
.user-info {
display: flex;
align-items: center;
gap: 16px;
}
.notification {
position: relative;
cursor: pointer;
color: var(--text-secondary);
}
/* 主内容区域 - 已调整左右内边距 */
.main-content {
flex: 1;
padding: 24px;
overflow-y: auto;
min-height: 100vh;
margin-left: 260px;
margin-left: var(--sidebar-width);
margin-top: var(--header-height);
/* 调整左右内边距,从 8px 增加到 32px,以利用更多空间 */
/* padding: 4px 32px;
min-height: calc(100vh - var(--header-height));
.main-content { } */
}
.content-area {
padding: 0;
}
/* 页面标题区域 */
.page-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 24px;
}
.page-title-section {
display: flex;
flex-direction: column;
gap: 4px;
}
.page-title-main {
font-size: 24px;
font-weight: 600;
color: var(--text-primary);
letter-spacing: -0.3px;
}
.page-title-sub {
font-size: 14px;
color: var(--text-secondary);
}
/* 表格数据优化 */
.table-cell-number {
font-weight: 600;
color: var(--text-primary);
}
.table-cell-date {
color: var(--text-secondary);
font-size: 13px;
}
/* 表格内容样式增强 */
td strong {
color: var(--text-primary);
font-weight: 600;
}
td code {
font-size: 12px;
font-weight: 500;
}
/* 空状态 */
.empty-state {
text-align: center;
padding: 60px 20px;
color: var(--text-secondary);
}
.empty-state-icon {
font-size: 48px;
color: var(--text-tertiary);
margin-bottom: 16px;
}
.empty-state-text {
font-size: 14px;
color: var(--text-secondary);
}
/* 响应式表格优化 */
@media (max-width: 1200px) {
.table-container {
overflow-x: auto;
}
table {
min-width: 1000px;
}
}
@media (max-width: 768px) {
.card-body {
padding: 16px;
}
th, td {
padding: 12px 16px;
}
.action-buttons {
flex-direction: column;
gap: 6px;
}
.action-btn {
width: 100%;
justify-content: center;
}
}
/* 卡片样式 */
.card {
background: var(--card-bg);
border-radius: 12px;
box-shadow: var(--shadow-sm);
margin-bottom: 24px;
border: 1px solid var(--border-color);
}
.card-header {
padding: 18px 20px;
border-bottom: 1px solid var(--border-color);
display: flex;
align-items: center;
justify-content: space-between;
background: var(--bg-color);
}
.card-title {
font-size: 18px;
font-weight: 600;
color: var(--text-primary);
letter-spacing: -0.2px;
}
.card-body {
padding: 20px 16px;
}
/* 按钮样式 */
.btn {
padding: 10px 20px;
border: none;
border-radius: 8px;
cursor: pointer;
font-size: 14px;
font-weight: 500;
transition: all 0.2s;
display: inline-flex;
align-items: center;
gap: 8px;
}
.btn-primary {
background: var(--primary-color);
color: white;
}
.btn-primary:hover {
background: var(--primary-hover);
transform: translateY(-1px);
box-shadow: 0 4px 12px rgba(27, 100, 243, 0.3);
}
.btn-secondary {
background: #f0f0f0;
color: var(--text-light);
}
.btn-secondary:hover {
background: #e0e0e0;
}
.btn-success {
background: var(--success-color);
color: white;
}
.btn-success:hover {
background: #389e0d;
}
.btn-danger {
background: var(--error-color);
color: white;
}
.btn-danger:hover {
background: #cf1322;
}
/* 标签页样式 */
.tabs {
display: flex;
gap: 16px;
margin-bottom: 20px;
border-bottom: 1px solid var(--border-color);
}
.tab {
padding: 10px 0;
color: var(--text-light);
cursor: pointer;
border-bottom: 2px solid transparent;
transition: all 0.3s ease;
font-size: 14px;
}
.tab:hover {
color: var(--primary-color);
}
.tab.active {
color: var(--primary-color);
border-bottom-color: var(--primary-color);
}
/* 表格样式 */
.table-container {
overflow-x: auto;
border-radius: 8px;
width: 100%;
}
table {
width: 100%;
border-collapse: collapse;
background: var(--card-bg);
}
th, td {
padding: 16px 20px;
text-align: left;
border-bottom: 1px solid var(--border-color);
}
th {
background: var(--bg-color);
font-weight: 600;
color: var(--text-secondary);
font-size: 13px;
text-transform: uppercase;
letter-spacing: 0.5px;
white-space: nowrap;
}
tbody tr {
transition: all 0.2s;
}
tbody tr:hover {
background: rgba(27, 100, 243, 0.04);
}
tbody tr:last-child td {
border-bottom: none;
}
td {
color: var(--text-primary);
font-size: 14px;
vertical-align: middle;
}
.status {
padding: 4px 8px;
border-radius: 4px;
font-size: 12px;
font-weight: 500;
}
.status.active {
background: #f6ffed;
color: var(--success-color);
}
.status.inactive {
background: #fff2e8;
color: var(--warning-color);
}
.action-buttons {
display: flex;
gap: 8px;
flex-wrap: wrap;
}
.action-btn {
padding: 6px 14px;
border: none;
border-radius: 6px;
cursor: pointer;
font-size: 13px;
font-weight: 500;
transition: all 0.2s;
display: inline-flex;
align-items: center;
gap: 6px;
white-space: nowrap;
}
.action-btn i {
font-size: 12px;
}
.action-btn.edit-btn {
background: rgba(27, 100, 243, 0.1);
color: var(--primary-color);
}
.action-btn.edit-btn:hover {
background: rgba(27, 100, 243, 0.2);
transform: translateY(-1px);
box-shadow: 0 2px 8px rgba(27, 100, 243, 0.2);
}
.action-btn.delete-btn {
background: rgba(239, 68, 68, 0.1);
color: var(--error-color);
}
.action-btn.delete-btn:hover {
background: rgba(239, 68, 68, 0.2);
transform: translateY(-1px);
box-shadow: 0 2px 8px rgba(239, 68, 68, 0.2);
}
.action-btn.view-btn {
background: rgba(27, 100, 243, 0.08);
color: var(--primary-color);
}
.action-btn.view-btn:hover {
background: rgba(27, 100, 243, 0.15);
transform: translateY(-1px);
box-shadow: 0 2px 8px rgba(27, 100, 243, 0.2);
}
.action-btn.copy-btn {
background: rgba(34, 197, 94, 0.1);
color: var(--success-color);
}
.action-btn.copy-btn:hover {
background: rgba(34, 197, 94, 0.2);
transform: translateY(-1px);
box-shadow: 0 2px 8px rgba(34, 197, 94, 0.2);
}
/* 模态框样式 */
.modal {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5);
z-index: 2000;
align-items: center;
justify-content: center;
}
.modal.show {
display: flex;
}
.modal-content {
background: white;
border-radius: 8px;
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
width: 90%;
max-width: 600px;
max-height: 80vh;
overflow-y: auto;
}
.add-modal-content {
background: white;
border-radius: 8px;
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
width: 90%;
max-width: 800px;
max-height: 85vh;
overflow-y: auto;
}
.modal-header {
padding: 16px 24px;
border-bottom: 1px solid var(--border-color);
display: flex;
align-items: center;
justify-content: space-between;
}
.modal-title {
font-size: 16px;
font-weight: 600;
color: var(--text-color);
}
.close-modal {
background: none;
border: none;
font-size: 20px;
color: var(--text-light);
cursor: pointer;
padding: 0;
width: 30px;
height: 30px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 4px;
transition: all 0.3s;
}
.close-modal:hover {
background: var(--secondary-color);
color: var(--text-color);
}
.modal-body {
padding: 24px;
}
.modal-footer {
padding: 16px 24px;
border-top: 1px solid var(--border-color);
display: flex;
align-items: center;
justify-content: flex-end;
gap: 12px;
}
/* 新增表单模态框样式 */
.add-modal-form .form-group {
margin-bottom: 20px;
}
.add-modal-form .form-row {
display: flex;
gap: 15px;
margin-bottom: 15px;
}
.add-modal-form .form-row .form-group {
flex: 1;
margin-bottom: 0;
}
.add-modal-form label {
display: block;
margin-bottom: 6px;
font-weight: 500;
color: var(--text-secondary);
font-size: 14px;
}
.add-modal-form input,
.add-modal-form select,
.add-modal-form textarea {
width: 100%;
padding: 8px 12px;
border: 1px solid var(--border-color);
border-radius: 6px;
font-size: 14px;
transition: border-color 0.3s;
}
.add-modal-form input:focus,
.add-modal-form select:focus,
.add-modal-form textarea:focus {
outline: none;
border-color: var(--primary-color);
}
.add-modal-form .section-title {
font-size: 16px;
font-weight: 600;
color: var(--text-primary);
margin: 20px 0 15px 0;
padding-bottom: 8px;
border-bottom: 1px solid var(--border-color);
}
.upload-box {
border: 2px dashed var(--border-color);
border-radius: 8px;
padding: 20px;
text-align: center;
cursor: pointer;
transition: all 0.3s;
background-color: var(--bg-color);
}
.upload-box:hover {
border-color: var(--primary-color);
background-color: rgba(27, 100, 243, 0.05);
}
.upload-icon {
font-size: 24px;
color: var(--primary-color);
margin-bottom: 10px;
}
.upload-info {
color: var(--text-secondary);
font-size: 13px;
}
.file-name {
margin-top: 10px;
font-weight: 500;
color: var(--primary-color);
font-size: 13px;
}
.param-table {
width: 100%;
border-collapse: collapse;
margin-top: 10px;
}
.param-table th, .param-table td {
border: 1px solid var(--border-color);
padding: 8px;
text-align: left;
}
.param-table th {
background-color: var(--bg-color);
font-weight: 600;
}
.add-param-btn {
background: var(--primary-color);
color: white;
border: none;
padding: 8px 15px;
border-radius: 6px;
cursor: pointer;
margin-top: 10px;
font-size: 14px;
}
.add-param-btn:hover {
background: var(--primary-hover);
}
/* 二维码预览样式 */
.qrcode-preview-large {
display: flex;
flex-direction: column;
align-items: center;
padding: 20px;
background: var(--primary-light);
border-radius: 8px;
margin-bottom: 20px;
}
.qrcode-image {
width: 200px;
height: 200px;
background: white;
padding: 10px;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 15px;
}
.qrcode-image img {
max-width: 100%;
max-height: 100%;
}
/* 详情信息样式 */
.detail-info {
margin-top: 20px;
}
.detail-item {
display: flex;
margin-bottom: 12px;
font-size: 14px;
}
.detail-label {
width: 100px;
color: var(--text-light);
flex-shrink: 0;
}
.detail-value {
color: var(--text-color);
font-weight: 500;
}
/* 响应式设计 */
@media (max-width: 768px) {
.sidebar {
transform: translateX(-100%);
}
.sidebar.show-mobile {
transform: translateX(0);
}
.main-content {
margin-left: 0;
margin-top: 0;
padding: 16px; /* 在移动端保持较小的内边距 */
}
.header, .top-header {
left: 0;
}
.tabs {
flex-wrap: wrap;
}
}
/* 批量上传相关样式 */
.batch-upload-modal .modal-content {
max-width: 800px;
}
.template-selector {
margin-bottom: 20px;
}
.template-selector label {
display: block;
margin-bottom: 8px;
font-weight: 500;
color: var(--text-primary);
}
.template-selector select {
width: 100%;
padding: 10px 15px;
border: 1px solid var(--border-color);
border-radius: 6px;
font-size: 14px;
background: white;
}
.template-download-btn {
margin-top: 10px;
padding: 8px 16px;
background: var(--primary-color);
color: white;
border: none;
border-radius: 6px;
cursor: pointer;
font-size: 14px;
display: inline-flex;
align-items: center;
gap: 6px;
}
.template-download-btn:hover {
background: var(--primary-hover);
}
.upload-area {
border: 2px dashed var(--border-color);
border-radius: 8px;
padding: 40px 20px;
text-align: center;
margin-bottom: 20px;
cursor: pointer;
transition: all 0.3s;
background: var(--bg-color);
}
.upload-area:hover {
border-color: var(--primary-color);
background: rgba(27, 100, 243, 0.05);
}
.upload-area.dragover {
border-color: var(--primary-color);
background: rgba(27, 100, 243, 0.1);
}
.upload-icon-large {
font-size: 48px;
color: var(--primary-color);
margin-bottom: 12px;
}
.upload-text {
font-size: 14px;
color: var(--text-secondary);
margin-bottom: 8px;
}
.upload-hint {
font-size: 12px;
color: var(--text-tertiary);
}
.progress-section {
margin-top: 20px;
padding-top: 20px;
border-top: 1px solid var(--border-color);
}
.progress-info {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 12px;
font-size: 14px;
}
.progress-stats {
display: flex;
gap: 20px;
}
.stat-item {
display: flex;
align-items: center;
gap: 6px;
}
.stat-label {
color: var(--text-secondary);
}
.stat-value {
font-weight: 600;
color: var(--text-primary);
}
.stat-value.success {
color: var(--success-color);
}
.stat-value.error {
color: var(--error-color);
}
.progress-bar-container {
width: 100%;
height: 8px;
background: var(--bg-color);
border-radius: 4px;
overflow: hidden;
margin-bottom: 12px;
}
.progress-bar {
height: 100%;
background: var(--primary-color);
transition: width 0.3s ease;
border-radius: 4px;
}
.error-list {
margin-top: 16px;
max-height: 200px;
overflow-y: auto;
border: 1px solid var(--border-color);
border-radius: 6px;
padding: 12px;
background: #fff5f5;
}
.error-item {
padding: 8px;
margin-bottom: 6px;
background: white;
border-left: 3px solid var(--error-color);
border-radius: 4px;
font-size: 13px;
}
.error-item:last-child {
margin-bottom: 0;
}
.error-row {
display: flex;
justify-content: space-between;
align-items: center;
}
.error-reason {
color: var(--error-color);
font-weight: 500;
}
.download-error-btn {
margin-top: 12px;
padding: 8px 16px;
background: var(--error-color);
color: white;
border: none;
border-radius: 6px;
cursor: pointer;
font-size: 13px;
display: inline-flex;
align-items: center;
gap: 6px;
}
.download-error-btn:hover {
background: #cf1322;
}
.validation-table {
width: 100%;
border-collapse: collapse;
margin-top: 16px;
font-size: 13px;
table-layout: fixed;
}
.validation-table th,
.validation-table td {
padding: 10px;
text-align: left;
border-bottom: 1px solid var(--border-color);
white-space: normal;
word-break: normal;
overflow: visible;
vertical-align: middle;
}
.validation-table th {
background: var(--bg-color);
font-weight: 600;
color: var(--text-secondary);
white-space: nowrap;
}
.validation-table td {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.validation-table td:nth-child(5) {
white-space: normal;
word-break: break-word;
}
.validation-table th:nth-child(1),
.validation-table td:nth-child(1) {
width: 60px;
min-width: 60px;
text-align: center;
}
.validation-table th:nth-child(2),
.validation-table td:nth-child(2) {
width: 120px;
min-width: 120px;
}
.validation-table th:nth-child(3),
.validation-table td:nth-child(3) {
width: 120px;
min-width: 120px;
}
.validation-table th:nth-child(4),
.validation-table td:nth-child(4) {
width: 100px;
min-width: 100px;
text-align: center;
}
.validation-table th:nth-child(5),
.validation-table td:nth-child(5) {
width: auto;
min-width: 200px;
}
.validation-table tr.error-row {
background: #fff5f5;
}
.validation-table tr.error-row td {
color: var(--error-color);
}
#validation-table-container {
overflow-x: auto;
max-width: 100%;
width: 100%;
}
#validation-table-container table {
min-width: 600px;
}
.file-name-display {
margin-top: 12px;
padding: 10px;
background: var(--bg-color);
border-radius: 6px;
font-size: 13px;
color: var(--text-secondary);
}
table {
width: 100%;
border-collapse: collapse;
}
th {
background-color: #01337a;
color: #fff;
padding: 10px;
text-align: left;
border: 1px solid #ddd;
}
td {
padding: 10px;
border: 1px solid #ddd;
}
tr:nth-child(even) {
background-color: #f2f2f2;
}
/* 在主页面CSS中添加 */
.sidebar-iframe {
position: fixed;
left: 0;
top: 0;
width: var(--sidebar-width);
height: 100vh;
border: none;
z-index: 999;
}
/* 为main-content和header添加左边距以避开iframe */
.main-content {
margin-left: var(--sidebar-width);
margin-top: var(--header-height);
}
.top-header {
left: var(--sidebar-width);
}
</style>
</head>
<body>
<div class="app-container">
<div id="sidebar-container"></div>
<header class="top-header">
<div class="header-left">
<div class="breadcrumb">
<span>首页</span>
<span class="breadcrumb-separator">/</span>
<span class="breadcrumb-current">工单</span>
</div>
</div>
<div class="header-right">
<button class="header-icon-btn" title="通知">
<svg class="nav-icon" viewBox="0 0 20 20">
<path d="M10 2a6 6 0 00-6 6v3.586l-.707.707A1 1 0 004 14h12a1 1 0 00.707-1.707L16 11.586V8a6 6 0 00-6-6zM10 18a3 3 0 01-3-3h6a3 3 0 01-3 3z"/>
</svg>
<span class="notification-badge"></span>
</button>
<div class="lang-switcher">
<button class="lang-btn active">中文</button>
<button class="lang-btn">EN</button>
</div>
<div class="user-avatar"></div>
</div>
</header>
<div class="main-content" style="position: relative;">
<img src="./img_6.png" alt="" style="width: 100%;">
</div>
<!-- 批量上传模态框 -->
</div>
</body>
<script src="./js.js"></script>
<script>
let importstr = document.getElementById('import')
let uploadstr = document.getElementById('batch-upload-modal')
let close = document.getElementById('close-batch-upload-modal')
let cancel = document.getElementById('cancel-batch-upload-btn')
uploadstr.style.display = 'none'
importstr.addEventListener('click', function () {
uploadstr.style.display = 'flex'
})
uploadstr.addEventListener('click', function (e) {
// 阻止事件冒泡,只有点击模态框背景时才关闭
if (e.target === uploadstr) {
uploadstr.style.display = 'none'
}
})
close.addEventListener('click', function () {
uploadstr.style.display = 'none'
})
cancel.addEventListener('click', function () {
uploadstr.style.display = 'none'
})
</script>
</html>
\ No newline at end of file
<!DOCTYPE html> <!DOCTYPE html>
...@@ -1785,7 +1785,7 @@ ...@@ -1785,7 +1785,7 @@
<table class="detail-table"> <table class="detail-table">
<thead> <thead>
<tr> <tr>
<th>件名称</th> <th>件名称</th>
<th>型号规格</th> <th>型号规格</th>
<th>数量</th> <th>数量</th>
<th>单价</th> <th>单价</th>
......
<!DOCTYPE html> <!DOCTYPE html>
...@@ -1684,7 +1684,7 @@ ...@@ -1684,7 +1684,7 @@
<thead> <thead>
<tr> <tr>
<th>序号</th> <th>序号</th>
<th>件名称</th> <th>件名称</th>
<th>型号规格</th> <th>型号规格</th>
<th>数量</th> <th>数量</th>
<th>单价</th> <th>单价</th>
......
<!DOCTYPE html> <!DOCTYPE html>
...@@ -1353,7 +1353,7 @@ ...@@ -1353,7 +1353,7 @@
<thead> <thead>
<tr> <tr>
<th>零件编号</th> <th>零件编号</th>
<th>件名称</th> <th>件名称</th>
<th>型号规格</th> <th>型号规格</th>
<!-- <th>标准单价</th>--> <!-- <th>标准单价</th>-->
<th>单位</th> <th>单位</th>
......
<!DOCTYPE html> <!DOCTYPE html>
...@@ -1525,12 +1525,12 @@ ...@@ -1525,12 +1525,12 @@
/> />
</div> </div>
<div class="form-group"> <div class="form-group">
<label class="form-label">件名称 <span class="required">*</span></label> <label class="form-label">件名称 <span class="required">*</span></label>
<input <input
type="text" type="text"
v-model="form.partName" v-model="form.partName"
class="form-control" class="form-control"
placeholder="请输入件名称" placeholder="请输入件名称"
required required
/> />
</div> </div>
......
<!DOCTYPE html> <!DOCTYPE html>
...@@ -1344,8 +1344,8 @@ ...@@ -1344,8 +1344,8 @@
<h1 class="page-title" data-i18n="title">配件报价</h1> <h1 class="page-title" data-i18n="title">配件报价</h1>
</div> </div>
<div class="toolbar" style="display:flex;justify-content: end;margin-bottom: 20px;"> <div class="toolbar" style="display:flex;justify-content: end;margin-bottom: 20px;">
<button class="btn btn-primary" style="text-align: right;padding: 8px 28px;margin-right: 4px;" @click="handleAdd">批量导入</button> <!-- <button class="btn btn-primary" style="text-align: right;padding: 8px 28px;margin-right: 4px;" @click="handleAdd">批量导入</button>-->
<button class="btn btn-primary" style="text-align: right;padding: 8px 28px;" @click="handleAdd">+ 新增配件</button> <!-- <button class="btn btn-primary" style="text-align: right;padding: 8px 28px;" @click="handleAdd">+ 新增配件</button>-->
</div> </div>
</div> </div>
...@@ -1353,7 +1353,7 @@ ...@@ -1353,7 +1353,7 @@
<thead> <thead>
<tr> <tr>
<th>零件编号</th> <th>零件编号</th>
<th>件名称</th> <th>件名称</th>
<th>型号规格</th> <th>型号规格</th>
<th>标准单价</th> <th>标准单价</th>
<th>单位</th> <th>单位</th>
......
<!DOCTYPE html> <!DOCTYPE html>
...@@ -1525,12 +1525,12 @@ ...@@ -1525,12 +1525,12 @@
/> />
</div> </div>
<div class="form-group"> <div class="form-group">
<label class="form-label">件名称 <span class="required">*</span></label> <label class="form-label">件名称 <span class="required">*</span></label>
<input <input
type="text" type="text"
v-model="form.partName" v-model="form.partName"
class="form-control" class="form-control"
placeholder="请输入件名称" placeholder="请输入件名称"
required required
/> />
</div> </div>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment