Commit b8a578c8 by suyuchen

chore(docs): 移除停机问题处理和VIP客户服务相关文件

- 删除停机问题处理流程制定相关的文档和页面文件 - 移除VIP客户服务机制建立的HTML页面文件 - 清理相关的统计
parent 7c1743b7
状态 条件 显示效果
++ /dev/null
状态 条件 显示效果
正常 剩余时间 > 1小时 黄色背景,正常显示
警告 0 < 剩余时间 ≤ 1小时 橙色/红色背景,警告提示
超时 剩余时间 ≤ 0 红色背景,闪烁动画
方案1:新开停机问题处理模块(列表页,工单页,详情页,统计页)
方案2:延用产品工单模块功能,增加(SLA计时字段,类型增加:停机/紧急 类型,停机/紧急类型自动添加SLA计时时间)
当前业务流程: 客户电话联系服务台客服------>客服内部联系工程师----------->工程师处理问题(电话&邮件&现场)-------------->问题解决(工单完结)
\ No newline at end of file
# 停机工单 SLA 状态规则说明
++ /dev/null
# 停机工单 SLA 状态规则说明
## 一、SLA 基本规则
### 1. SLA 时间限制
- **标准时限**:2小时(120分钟)
- **计时单位**:毫秒(ms)
- **计算公式**`SLA剩余时间 = SLA时限 - (当前时间 - 工单创建时间)`
### 2. SLA 计时起点
- **开始时间**:工单创建时立即开始计时
- **记录字段**`slaStartTime`(工单创建时间戳)
- **初始值**`slaTimeRemaining = 2小时(7200000毫秒)`
### 3. SLA 计时停止条件
- 工单状态变为 `closed`(已关闭)时停止计时
- 已关闭的工单不再更新 SLA 剩余时间
---
## 二、SLA 状态分类
### 状态1:正常(Normal)
- **条件**`剩余时间 > 1小时(3600000毫秒)`
- **显示样式**:黄色背景,正常显示
- **说明**:工单在正常处理时限内
### 状态2:警告(Warning)
- **条件**`0 < 剩余时间 ≤ 1小时(3600000毫秒)`
- **显示样式**:橙色/红色背景,警告提示
- **说明**:工单即将超时,需要紧急处理
### 状态3:超时(Timeout)
- **条件**`剩余时间 ≤ 0`
- **显示样式**:红色背景,闪烁动画
- **说明**:工单已超过 SLA 时限,需要立即处理
---
## 三、SLA 状态判断逻辑
### 代码实现逻辑
```javascript
// SLA剩余时间计算
if (工单状态 !== 'closed' && slaStartTime存在) {
已用时间 = 当前时间 - slaStartTime
剩余时间 = Math.max(0, SLA时限 - 已用时间)
}
// 状态判断
if (剩余时间 <= 0) {
状态 = '超时'
} else if (剩余时间 < 1小时) {
状态 = '警告'
} else {
状态 = '正常'
}
```
### 状态更新频率
- **更新间隔**:每1秒更新一次
- **更新范围**:所有未关闭的工单
- **实时性**:页面实时显示倒计时
---
## 四、SLA 统计规则
### 1. 超时工单统计
- **统计条件**`slaTimeRemaining <= 0 && status !== 'closed'`
- **统计位置**:列表页统计卡片、统计&分析页
- **用途**:监控 SLA 达成情况
### 2. 平均响应时间
- **计算公式**`(响应时间 - 创建时间) / 工单数量`
- **单位**:分钟
- **统计范围**:所有已响应的工单
### 3. 平均解决时间
- **计算公式**`(解决时间 - 创建时间) / 工单数量`
- **单位**:分钟
- **统计范围**:所有已解决的工单
---
## 五、SLA 状态显示规则
### 1. 列表页显示
- **位置**:每个工单卡片下方
- **格式**`⏱️ SLA计时: X小时 X分钟 X秒`
- **颜色**:根据状态自动变色
### 2. 详情页显示
- **位置**:工单基本信息区域
- **格式**:大号显示,更醒目
- **动画**:超时时闪烁提醒
### 3. 统计页显示
- **位置**:核心指标统计卡片
- **内容**:SLA超时数量统计
- **图表**:响应时间分析图表
---
## 六、特殊情况处理
### 1. 工单关闭后
- **SLA计时停止**:不再更新剩余时间
- **状态保持**:保留关闭时的 SLA 状态
- **统计计入**:计入历史统计数据
### 2. 页面刷新
- **数据恢复**:从 localStorage 恢复工单数据
- **时间重算**:根据 `slaStartTime` 重新计算剩余时间
- **状态更新**:自动更新到当前状态
### 3. 跨天/跨月
- **时间计算**:基于时间戳,不受日期影响
- **精确计算**:毫秒级精度,确保准确性
---
## 七、SLA 规则配置
### 当前配置
```javascript
slaLimit: 2 * 60 * 60 * 1000 // 2小时 = 7200000毫秒
```
### 可调整参数
- **SLA时限**:可根据业务需求调整(建议范围:1-4小时)
- **警告阈值**:当前为1小时,可调整
- **更新频率**:当前为1秒,可调整
---
## 八、SLA 状态流转图
```
工单创建
SLA开始计时(2小时倒计时)
[正常状态] 剩余时间 > 1小时
[警告状态] 剩余时间 ≤ 1小时
[超时状态] 剩余时间 ≤ 0
工单关闭 → SLA计时停止
```
---
## 九、注意事项
1. **时间精度**:使用毫秒级时间戳,确保计算准确
2. **时区问题**:使用本地时间,确保显示正确
3. **性能优化**:定时器每秒更新,注意页面性能
4. **数据持久化**:SLA状态随工单数据一起保存
5. **状态一致性**:确保所有页面 SLA 状态显示一致
---
## 十、未来优化建议
1. **分级SLA**:根据客户等级设置不同的SLA时限
2. **暂停机制**:支持暂停SLA计时(如等待客户反馈)
3. **预警通知**:SLA即将超时前自动发送通知
4. **历史记录**:记录SLA状态变化历史
5. **报表导出**:SLA达成率报表导出功能
<!DOCTYPE html>
++ /dev/null
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>服务价格标准首页 - 服务价格标准化管理系统</title>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Microsoft YaHei', Arial, sans-serif;
background: #f5f7fa;
min-height: 100vh;
padding: 20px;
}
.container {
max-width: 1400px;
margin: 0 auto;
}
.header {
background: white;
padding: 20px 30px;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
margin-bottom: 20px;
}
.header h1 {
color: #333;
font-size: 24px;
font-weight: 600;
}
.card {
background: white;
border-radius: 8px;
padding: 25px;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
margin-bottom: 20px;
}
.card-title {
font-size: 18px;
font-weight: 600;
color: #333;
margin-bottom: 20px;
padding-bottom: 12px;
border-bottom: 2px solid #409eff;
}
.stats-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 20px;
margin-bottom: 30px;
}
.stat-card {
background: linear-gradient(135deg, #409eff 0%, #66b1ff 100%);
color: white;
padding: 25px;
border-radius: 8px;
text-align: center;
transition: transform 0.3s;
}
.stat-card:hover {
transform: translateY(-5px);
box-shadow: 0 4px 12px rgba(64, 158, 255, 0.3);
}
.stat-card.success {
background: linear-gradient(135deg, #67c23a 0%, #85ce61 100%);
}
.stat-card.warning {
background: linear-gradient(135deg, #e6a23c 0%, #ebb563 100%);
}
.stat-card.info {
background: linear-gradient(135deg, #909399 0%, #b1b3b8 100%);
}
.stat-value {
font-size: 36px;
font-weight: bold;
margin: 15px 0;
}
.stat-label {
font-size: 14px;
opacity: 0.9;
}
.whitebook-info {
background: linear-gradient(135deg, #f0f9ff 0%, #e0f2fe 100%);
border: 2px solid #409eff;
border-radius: 8px;
padding: 20px;
margin-bottom: 30px;
}
.whitebook-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 15px;
}
.whitebook-title {
font-size: 20px;
font-weight: 600;
color: #333;
}
.whitebook-version {
font-size: 18px;
color: #409eff;
font-weight: bold;
}
.whitebook-status {
display: inline-block;
padding: 4px 12px;
background: #67c23a;
color: white;
border-radius: 4px;
font-size: 12px;
}
.quick-actions {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 15px;
}
.action-btn {
padding: 20px;
background: white;
border: 2px solid #e4e7ed;
border-radius: 8px;
text-align: center;
cursor: pointer;
transition: all 0.3s;
text-decoration: none;
color: #333;
display: block;
}
.action-btn:hover {
border-color: #409eff;
background: #f0f9ff;
transform: translateY(-3px);
box-shadow: 0 4px 12px rgba(64, 158, 255, 0.2);
}
.action-icon {
font-size: 32px;
margin-bottom: 10px;
}
.action-title {
font-size: 16px;
font-weight: 600;
margin-bottom: 5px;
}
.action-desc {
font-size: 12px;
color: #909399;
}
</style>
</head>
<body>
<div id="app">
<div class="container">
<div class="header">
<h1>服务价格标准化管理系统</h1>
</div>
<!-- 白皮书信息 -->
<div class="whitebook-info">
<div class="whitebook-header">
<div>
<div class="whitebook-title">当前生效的服务价格白皮书</div>
<div style="margin-top: 10px; color: #666; font-size: 14px;">版本号:<span class="whitebook-version">{{ whitebook.version }}</span></div>
</div>
<span class="whitebook-status">{{ whitebook.status }}</span>
</div>
<div style="color: #666; font-size: 14px;">生效时间:{{ whitebook.effectiveDate }}</div>
</div>
<!-- 统计卡片 -->
<div class="stats-grid">
<div class="stat-card">
<div class="stat-label">人工费用标准数量</div>
<div class="stat-value">{{ stats.laborCount }}</div>
<div style="font-size: 12px; margin-top: 10px; opacity: 0.8;">已配置标准</div>
</div>
<div class="stat-card success">
<div class="stat-label">零件费用标准数量</div>
<div class="stat-value">{{ stats.partCount }}</div>
<div style="font-size: 12px; margin-top: 10px; opacity: 0.8;">已配置标准</div>
</div>
<div class="stat-card warning">
<div class="stat-label">已启用的报价规则</div>
<div class="stat-value">{{ stats.ruleCount }}</div>
<div style="font-size: 12px; margin-top: 10px; opacity: 0.8;">启用中</div>
</div>
</div>
<!-- 快捷入口 -->
<div class="card">
<div class="card-title">快捷入口</div>
<div class="quick-actions">
<a href="2-人工费用标准管理列表页.html" class="action-btn">
<div class="action-icon">👷</div>
<div class="action-title">人工费用管理</div>
<div class="action-desc">管理服务人工费用标准</div>
</a>
<a href="4-零件费用标准管理列表页.html" class="action-btn">
<div class="action-icon">🔧</div>
<div class="action-title">零件费用管理</div>
<div class="action-desc">管理零件费用标准</div>
</a>
<a href="6-报价规则配置列表页.html" class="action-btn">
<div class="action-icon">⚙️</div>
<div class="action-title">报价规则配置</div>
<div class="action-desc">配置报价规则</div>
</a>
<a href="10-服务价格白皮书查看页.html" class="action-btn">
<div class="action-icon">📄</div>
<div class="action-title">查看服务价格白皮书</div>
<div class="action-desc">查看完整价格标准文档</div>
</a>
</div>
</div>
</div>
</div>
<script>
const { createApp } = Vue;
createApp({
data() {
return {
whitebook: {
version: 'V1.0',
status: '生效中',
effectiveDate: '2024-01-01'
},
stats: {
laborCount: 12,
partCount: 156,
ruleCount: 8
}
}
}
}).mount('#app');
</script>
</body>
</html>
<!DOCTYPE html>
++ /dev/null
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>零件费用标准管理 - 服务价格标准化管理系统</title>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Microsoft YaHei', Arial, sans-serif;
background: #f5f7fa;
min-height: 100vh;
padding: 20px;
}
.container {
max-width: 1400px;
margin: 0 auto;
}
.header {
background: white;
padding: 20px 30px;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
margin-bottom: 20px;
}
.header-top {
display: flex;
justify-content: space-between;
align-items: center;
}
.header h1 {
color: #333;
font-size: 24px;
font-weight: 600;
}
.nav-menu {
display: flex;
gap: 10px;
}
.nav-item {
padding: 8px 16px;
background: #409eff;
color: white;
text-decoration: none;
border-radius: 6px;
font-size: 14px;
transition: all 0.3s;
}
.nav-item:hover {
background: #66b1ff;
}
.nav-item.active {
background: #67c23a;
}
.card {
background: white;
border-radius: 8px;
padding: 25px;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
margin-bottom: 20px;
}
.card-title {
font-size: 18px;
font-weight: 600;
color: #333;
margin-bottom: 20px;
padding-bottom: 12px;
border-bottom: 2px solid #409eff;
}
.toolbar {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
}
.btn {
padding: 10px 20px;
border: none;
border-radius: 6px;
cursor: pointer;
font-size: 14px;
transition: all 0.3s;
font-weight: 500;
}
.btn-primary {
background: #409eff;
color: white;
}
.btn-primary:hover {
background: #66b1ff;
}
.btn-success {
background: #67c23a;
color: white;
}
.btn-success:hover {
background: #85ce61;
}
.btn-small {
padding: 6px 12px;
font-size: 12px;
}
.data-table {
width: 100%;
border-collapse: collapse;
margin-top: 20px;
}
.data-table th,
.data-table td {
padding: 12px;
text-align: left;
border-bottom: 1px solid #e4e7ed;
}
.data-table th {
background: #f5f7fa;
font-weight: 600;
color: #333;
}
.data-table tr:hover {
background: #f5f7fa;
}
.badge {
display: inline-block;
padding: 4px 10px;
border-radius: 4px;
font-size: 12px;
font-weight: 500;
}
.badge-success {
background: #f0f9ff;
color: #67c23a;
border: 1px solid #67c23a;
}
.badge-danger {
background: #fef0f0;
color: #f56c6c;
border: 1px solid #f56c6c;
}
.action-btns {
display: flex;
gap: 8px;
}
</style>
</head>
<body>
<div id="app">
<div class="container">
<div class="header">
<div class="header-top">
<h1>零件费用标准管理</h1>
<div class="nav-menu">
<a href="1-服务价格标准首页.html" class="nav-item">首页</a>
<a href="2-人工费用标准管理列表页.html" class="nav-item">人工费用</a>
<a href="4-零件费用标准管理列表页.html" class="nav-item active">零件费用</a>
<a href="6-报价规则配置列表页.html" class="nav-item">报价规则</a>
</div>
</div>
</div>
<div class="card">
<div class="toolbar">
<div class="card-title">零件费用标准列表</div>
<div style="display: flex; gap: 10px;">
<button class="btn btn-success" @click="handleImport">批量导入</button>
<button class="btn btn-primary" @click="handleAdd">+ 新增零件</button>
</div>
</div>
<table class="data-table">
<thead>
<tr>
<th>零件编号</th>
<th>零件名称</th>
<th>型号规格</th>
<th>标准单价</th>
<th>单位</th>
<th>适用设备</th>
<th>状态</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr v-for="item in partList" :key="item.id">
<td>{{ item.partNo }}</td>
<td>{{ item.partName }}</td>
<td>{{ item.specification }}</td>
<td>¥{{ item.price }}</td>
<td>{{ item.unit }}</td>
<td>{{ item.applicableEquipment }}</td>
<td>
<span :class="item.status === '启用' ? 'badge badge-success' : 'badge badge-danger'">
{{ item.status }}
</span>
</td>
<td>
<div class="action-btns">
<button class="btn btn-primary btn-small" @click="handleEdit(item)">编辑</button>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<script>
const { createApp } = Vue;
createApp({
data() {
return {
partList: [
{
id: 1,
partNo: 'P001',
partName: '服务器硬盘',
specification: '2TB SATA',
price: 800,
unit: '块',
applicableEquipment: '服务器',
status: '启用'
},
{
id: 2,
partNo: 'P002',
partName: '内存条',
specification: '16GB DDR4',
price: 600,
unit: '条',
applicableEquipment: '服务器/工作站',
status: '启用'
},
{
id: 3,
partNo: 'P003',
partName: '网络交换机',
specification: '24口千兆',
price: 2000,
unit: '台',
applicableEquipment: '网络设备',
status: '启用'
},
{
id: 4,
partNo: 'P004',
partName: 'UPS电源',
specification: '3KVA',
price: 3500,
unit: '台',
applicableEquipment: '电源设备',
status: '启用'
}
]
}
},
methods: {
handleAdd() {
window.location.href = '5-零件费用标准新增编辑页.html?action=add';
},
handleEdit(item) {
window.location.href = `5-零件费用标准新增编辑页.html?action=edit&id=${item.id}`;
},
handleImport() {
alert('批量导入功能(占位)');
}
}
}).mount('#app');
</script>
</body>
</html>
<!DOCTYPE html>
++ /dev/null
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>报价规则配置 - 服务价格标准化管理系统</title>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Microsoft YaHei', Arial, sans-serif;
background: #f5f7fa;
min-height: 100vh;
padding: 20px;
}
.container {
max-width: 1400px;
margin: 0 auto;
}
.header {
background: white;
padding: 20px 30px;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
margin-bottom: 20px;
}
.header-top {
display: flex;
justify-content: space-between;
align-items: center;
}
.header h1 {
color: #333;
font-size: 24px;
font-weight: 600;
}
.nav-menu {
display: flex;
gap: 10px;
}
.nav-item {
padding: 8px 16px;
background: #409eff;
color: white;
text-decoration: none;
border-radius: 6px;
font-size: 14px;
transition: all 0.3s;
}
.nav-item:hover {
background: #66b1ff;
}
.nav-item.active {
background: #67c23a;
}
.card {
background: white;
border-radius: 8px;
padding: 25px;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
margin-bottom: 20px;
}
.card-title {
font-size: 18px;
font-weight: 600;
color: #333;
margin-bottom: 20px;
padding-bottom: 12px;
border-bottom: 2px solid #409eff;
}
.toolbar {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
}
.btn {
padding: 10px 20px;
border: none;
border-radius: 6px;
cursor: pointer;
font-size: 14px;
transition: all 0.3s;
font-weight: 500;
}
.btn-primary {
background: #409eff;
color: white;
}
.btn-primary:hover {
background: #66b1ff;
}
.btn-success {
background: #67c23a;
color: white;
}
.btn-success:hover {
background: #85ce61;
}
.btn-warning {
background: #e6a23c;
color: white;
}
.btn-warning:hover {
background: #ebb563;
}
.btn-small {
padding: 6px 12px;
font-size: 12px;
}
.data-table {
width: 100%;
border-collapse: collapse;
margin-top: 20px;
}
.data-table th,
.data-table td {
padding: 12px;
text-align: left;
border-bottom: 1px solid #e4e7ed;
}
.data-table th {
background: #f5f7fa;
font-weight: 600;
color: #333;
}
.data-table tr:hover {
background: #f5f7fa;
}
.badge {
display: inline-block;
padding: 4px 10px;
border-radius: 4px;
font-size: 12px;
font-weight: 500;
}
.badge-success {
background: #f0f9ff;
color: #67c23a;
border: 1px solid #67c23a;
}
.badge-danger {
background: #fef0f0;
color: #f56c6c;
border: 1px solid #f56c6c;
}
.action-btns {
display: flex;
gap: 8px;
}
</style>
</head>
<body>
<div id="app">
<div class="container">
<div class="header">
<div class="header-top">
<h1>报价规则配置</h1>
<div class="nav-menu">
<a href="1-服务价格标准首页.html" class="nav-item">首页</a>
<a href="2-人工费用标准管理列表页.html" class="nav-item">人工费用</a>
<a href="4-零件费用标准管理列表页.html" class="nav-item">零件费用</a>
<a href="6-报价规则配置列表页.html" class="nav-item active">报价规则</a>
</div>
</div>
</div>
<div class="card">
<div class="toolbar">
<div class="card-title">报价规则列表</div>
<button class="btn btn-primary" @click="handleAdd">+ 新增规则</button>
</div>
<table class="data-table">
<thead>
<tr>
<th>规则名称</th>
<th>适用场景</th>
<th>是否质保期外</th>
<th>状态</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr v-for="item in ruleList" :key="item.id">
<td>{{ item.ruleName }}</td>
<td>{{ item.scenario }}</td>
<td></td>
<td>
<span :class="item.status === '启用' ? 'badge badge-success' : 'badge badge-danger'">
{{ item.status }}
</span>
</td>
<td>
<div class="action-btns">
<button class="btn btn-primary btn-small" @click="handleEdit(item)">编辑</button>
<button
v-if="item.status === '启用'"
class="btn btn-warning btn-small"
@click="handleToggleStatus(item)">
停用
</button>
<button
v-else
class="btn btn-success btn-small"
@click="handleToggleStatus(item)">
启用
</button>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<script>
const { createApp } = Vue;
createApp({
data() {
return {
ruleList: [
{
id: 1,
ruleName: '停机服务标准报价规则',
scenario: '停机',
status: '启用'
},
{
id: 2,
ruleName: '非停机服务标准报价规则',
scenario: '非停机',
status: '启用'
},
{
id: 3,
ruleName: '紧急服务加急报价规则',
scenario: '停机',
status: '启用'
}
]
}
},
methods: {
handleAdd() {
window.location.href = '7-报价规则配置新增编辑页.html?action=add';
},
handleEdit(item) {
window.location.href = `7-报价规则配置新增编辑页.html?action=edit&id=${item.id}`;
},
handleToggleStatus(item) {
item.status = item.status === '启用' ? '停用' : '启用';
}
}
}).mount('#app');
</script>
</body>
</html>
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