<template>
|
<view class="sales-account">
|
<!-- 使用通用页面头部组件 -->
|
<PageHeader title="标准作业指导" @back="goBack" />
|
|
<!-- 任务信息卡片 -->
|
<view class="task-info-card">
|
<view class="task-header">
|
<view class="task-left">
|
<view class="task-icon">
|
<up-icon name="file-text" size="20" color="#ffffff"></up-icon>
|
</view>
|
<view class="task-details">
|
<text class="task-title">{{ currentTask.deviceName }}</text>
|
<text class="task-subtitle">{{ currentTask.taskType }} - {{ currentTask.priority }}</text>
|
</view>
|
</view>
|
<view class="task-status">
|
<u-tag :type="getStatusType(currentTask.status)" size="small">
|
{{ getStatusText(currentTask.status) }}
|
</u-tag>
|
</view>
|
</view>
|
|
<view class="task-meta">
|
<view class="meta-item">
|
<text class="meta-label">设备编号:</text>
|
<text class="meta-value">{{ currentTask.deviceCode }}</text>
|
</view>
|
<view class="meta-item">
|
<text class="meta-label">故障描述:</text>
|
<text class="meta-value">{{ currentTask.faultDescription }}</text>
|
</view>
|
<view class="meta-item">
|
<text class="meta-label">预计工时:</text>
|
<text class="meta-value">{{ currentTask.estimatedHours }}小时</text>
|
</view>
|
</view>
|
</view>
|
|
<!-- 功能导航 -->
|
<view class="nav-tabs">
|
<view
|
v-for="(tab, index) in tabs"
|
:key="index"
|
class="nav-tab"
|
:class="{ active: activeTab === tab.key }"
|
@click="switchTab(tab.key)"
|
>
|
<up-icon :name="tab.icon" size="18" :color="activeTab === tab.key ? '#2979ff' : '#666'"></up-icon>
|
<text class="tab-text" :class="{ active: activeTab === tab.key }">{{ tab.label }}</text>
|
</view>
|
</view>
|
|
<!-- SOP标准作业程序 -->
|
<view v-if="activeTab === 'sop'" class="content-section">
|
<view class="section-header">
|
<text class="section-title">标准作业程序</text>
|
<view class="progress-info">
|
<text class="progress-text">{{ completedSteps }}/{{ sopSteps.length }}</text>
|
<up-icon name="checkmark-circle" size="16" color="#4caf50" v-if="completedSteps === sopSteps.length"></up-icon>
|
</view>
|
</view>
|
|
<view class="sop-steps">
|
<view
|
v-for="(step, index) in sopSteps"
|
:key="step.id"
|
class="sop-step"
|
:class="{ completed: step.completed, current: currentStepIndex === index }"
|
>
|
<view class="step-header" @click="toggleStep(index)">
|
<view class="step-number">
|
<text v-if="!step.completed" class="step-num">{{ index + 1 }}</text>
|
<up-icon v-else name="checkmark" size="14" color="#ffffff"></up-icon>
|
</view>
|
<view class="step-content">
|
<text class="step-title">{{ step.title }}</text>
|
<text class="step-duration">预计{{ step.duration }}分钟</text>
|
</view>
|
<view class="step-toggle">
|
<up-icon
|
:name="step.expanded ? 'arrow-up' : 'arrow-down'"
|
size="16"
|
color="#999"
|
></up-icon>
|
</view>
|
</view>
|
|
<view v-if="step.expanded" class="step-details">
|
<view class="step-description">
|
<text class="desc-text">{{ step.description }}</text>
|
</view>
|
|
<view v-if="step.warnings.length > 0" class="step-warnings">
|
<text class="warning-title">⚠️ 注意事项</text>
|
<view v-for="warning in step.warnings" :key="warning" class="warning-item">
|
<text class="warning-text">• {{ warning }}</text>
|
</view>
|
</view>
|
|
<view v-if="step.tools.length > 0" class="step-tools">
|
<text class="tools-title">🔧 所需工具</text>
|
<view class="tools-list">
|
<u-tag
|
v-for="tool in step.tools"
|
:key="tool"
|
type="info"
|
size="mini"
|
class="tool-tag"
|
>
|
{{ tool }}
|
</u-tag>
|
</view>
|
</view>
|
|
<view class="step-actions">
|
<u-button
|
v-if="!step.completed"
|
type="success"
|
size="small"
|
@click="completeStep(index)"
|
>
|
完成此步骤
|
</u-button>
|
<u-button
|
v-else
|
type="info"
|
size="small"
|
plain
|
@click="uncompleteStep(index)"
|
>
|
取消完成
|
</u-button>
|
</view>
|
</view>
|
</view>
|
</view>
|
</view>
|
|
<!-- 配件清单 -->
|
<view v-if="activeTab === 'parts'" class="content-section">
|
<view class="section-header">
|
<text class="section-title">配件清单</text>
|
<view class="parts-summary">
|
<text class="summary-text">共{{ partsList.length }}项配件</text>
|
</view>
|
</view>
|
|
<view class="parts-list">
|
<view v-for="part in partsList" :key="part.id" class="part-item">
|
<view class="part-header">
|
<view class="part-info">
|
<text class="part-name">{{ part.name }}</text>
|
<text class="part-spec">{{ part.specification }}</text>
|
</view>
|
<view class="part-status">
|
<u-tag
|
:type="part.available ? 'success' : 'error'"
|
size="mini"
|
>
|
{{ part.available ? '库存充足' : '库存不足' }}
|
</u-tag>
|
</view>
|
</view>
|
|
<view class="part-details">
|
<view class="detail-row">
|
<text class="detail-label">配件编号:</text>
|
<text class="detail-value">{{ part.partNumber }}</text>
|
</view>
|
<view class="detail-row">
|
<text class="detail-label">需要数量:</text>
|
<text class="detail-value">{{ part.requiredQuantity }}{{ part.unit }}</text>
|
</view>
|
<view class="detail-row">
|
<text class="detail-label">库存数量:</text>
|
<text class="detail-value" :class="{ danger: !part.available }">
|
{{ part.stockQuantity }}{{ part.unit }}
|
</text>
|
</view>
|
<view class="detail-row">
|
<text class="detail-label">存放位置:</text>
|
<text class="detail-value">{{ part.location }}</text>
|
</view>
|
</view>
|
|
<view class="part-actions">
|
<u-button
|
type="primary"
|
size="small"
|
plain
|
@click="requestPart(part)"
|
:disabled="part.available"
|
>
|
申请配件
|
</u-button>
|
<u-button
|
type="info"
|
size="small"
|
plain
|
@click="viewPartDetail(part)"
|
>
|
查看详情
|
</u-button>
|
</view>
|
</view>
|
</view>
|
</view>
|
|
<!-- 安全提示 -->
|
<view v-if="activeTab === 'safety'" class="content-section">
|
<view class="section-header">
|
<text class="section-title">安全提示</text>
|
<view class="safety-level">
|
<u-tag :type="getSafetyLevelType(safetyInfo.level)" size="small">
|
{{ safetyInfo.level }}
|
</u-tag>
|
</view>
|
</view>
|
|
<!-- 安全等级说明 -->
|
<view class="safety-overview">
|
<view class="safety-icon">
|
<up-icon name="warning" size="24" color="#ff6b35"></up-icon>
|
</view>
|
<view class="safety-content">
|
<text class="safety-title">{{ safetyInfo.title }}</text>
|
<text class="safety-desc">{{ safetyInfo.description }}</text>
|
</view>
|
</view>
|
|
<!-- 个人防护设备 -->
|
<view class="safety-section">
|
<text class="safety-section-title">🛡️ 个人防护设备</text>
|
<view class="ppe-list">
|
<view v-for="ppe in safetyInfo.ppe" :key="ppe.name" class="ppe-item">
|
<view class="ppe-icon">
|
<text class="ppe-emoji">{{ ppe.icon }}</text>
|
</view>
|
<view class="ppe-info">
|
<text class="ppe-name">{{ ppe.name }}</text>
|
<text class="ppe-desc">{{ ppe.description }}</text>
|
</view>
|
<view class="ppe-status">
|
<up-icon
|
:name="ppe.checked ? 'checkmark-circle' : 'close-circle'"
|
:color="ppe.checked ? '#4caf50' : '#ccc'"
|
size="20"
|
@click="togglePPE(ppe)"
|
></up-icon>
|
</view>
|
</view>
|
</view>
|
</view>
|
|
<!-- 安全注意事项 -->
|
<view class="safety-section">
|
<text class="safety-section-title">⚠️ 安全注意事项</text>
|
<view class="safety-warnings">
|
<view v-for="(warning, index) in safetyInfo.warnings" :key="index" class="safety-warning">
|
<view class="warning-icon">
|
<up-icon name="info-circle" size="16" color="#ff6b35"></up-icon>
|
</view>
|
<text class="warning-content">{{ warning }}</text>
|
</view>
|
</view>
|
</view>
|
|
<!-- 应急处理 -->
|
<view class="safety-section">
|
<text class="safety-section-title">🚨 应急处理</text>
|
<view class="emergency-procedures">
|
<view v-for="(procedure, index) in safetyInfo.emergencyProcedures" :key="index" class="emergency-item">
|
<view class="emergency-header">
|
<text class="emergency-title">{{ procedure.situation }}</text>
|
</view>
|
<view class="emergency-steps">
|
<view v-for="(step, stepIndex) in procedure.steps" :key="stepIndex" class="emergency-step">
|
<text class="step-number">{{ stepIndex + 1 }}.</text>
|
<text class="step-content">{{ step }}</text>
|
</view>
|
</view>
|
</view>
|
</view>
|
</view>
|
|
<!-- 安全确认 -->
|
<view class="safety-confirmation">
|
<view class="confirmation-header">
|
<up-icon name="checkmark-circle" size="20" color="#4caf50"></up-icon>
|
<text class="confirmation-title">安全确认</text>
|
</view>
|
<view class="confirmation-content">
|
<text class="confirmation-text">我已仔细阅读并理解以上安全提示,将严格按照安全规程进行作业</text>
|
</view>
|
<view class="confirmation-actions">
|
<u-button
|
type="success"
|
@click="confirmSafety"
|
:disabled="safetyConfirmed"
|
>
|
{{ safetyConfirmed ? '已确认' : '确认并开始作业' }}
|
</u-button>
|
</view>
|
</view>
|
</view>
|
|
<!-- 底部操作按钮 -->
|
<view class="bottom-actions">
|
<u-button
|
type="primary"
|
size="large"
|
@click="startWork"
|
:disabled="!canStartWork"
|
>
|
开始作业
|
</u-button>
|
<u-button
|
type="info"
|
size="large"
|
plain
|
@click="saveProgress"
|
>
|
保存进度
|
</u-button>
|
</view>
|
</view>
|
</template>
|
|
<script setup>
|
import { ref, computed, onMounted } from 'vue'
|
import { onShow } from '@dcloudio/uni-app'
|
import PageHeader from '@/components/PageHeader.vue'
|
|
const showToast = (message) => {
|
uni.showToast({
|
title: message,
|
icon: 'none'
|
})
|
}
|
|
// 当前任务信息
|
const currentTask = ref({
|
id: 1,
|
deviceName: '数控车床CK6140',
|
deviceCode: 'CNC-001',
|
taskType: '设备维修',
|
priority: '紧急',
|
status: 'in_progress',
|
faultDescription: '主轴异响,切削精度下降',
|
estimatedHours: 4,
|
assignedTechnician: '李师傅',
|
startTime: '2024-01-15 09:00:00'
|
})
|
|
// 导航标签
|
const tabs = ref([
|
{ key: 'sop', label: 'SOP', icon: 'list' },
|
{ key: 'parts', label: '配件', icon: 'grid' },
|
{ key: 'safety', label: '安全', icon: 'info' }
|
])
|
|
const activeTab = ref('sop')
|
|
// SOP步骤数据
|
const sopSteps = ref([
|
{
|
id: 1,
|
title: '安全准备与设备断电',
|
description: '确保设备完全断电,挂上安全标识牌,穿戴好个人防护设备,检查工作环境安全。',
|
duration: 10,
|
completed: false,
|
expanded: false,
|
warnings: [
|
'必须确认设备完全断电后才能进行后续操作',
|
'挂上"正在维修,禁止操作"的安全标识牌',
|
'检查周围是否有其他人员,确保安全距离'
|
],
|
tools: ['万用表', '安全标识牌', '个人防护设备']
|
},
|
{
|
id: 2,
|
title: '拆卸主轴防护罩',
|
description: '使用专用工具小心拆卸主轴防护罩,注意保护罩的完整性,避免损坏密封件。',
|
duration: 15,
|
completed: false,
|
expanded: false,
|
warnings: [
|
'拆卸时注意防护罩重量,避免掉落砸伤',
|
'密封件容易老化,拆卸时要格外小心',
|
'记录拆卸顺序,便于后续安装'
|
],
|
tools: ['内六角扳手', '橡胶锤', '密封胶']
|
},
|
{
|
id: 3,
|
title: '检查主轴轴承状态',
|
description: '仔细检查主轴轴承的磨损情况,测量轴承间隙,检查润滑油状态和轴承座的配合情况。',
|
duration: 25,
|
completed: false,
|
expanded: false,
|
warnings: [
|
'轴承检查时避免用力过大,防止进一步损坏',
|
'注意观察轴承表面是否有裂纹或异常磨损',
|
'测量数据要准确记录,作为更换依据'
|
],
|
tools: ['游标卡尺', '千分尺', '内窥镜', '润滑油检测仪']
|
},
|
{
|
id: 4,
|
title: '更换损坏轴承',
|
description: '使用专用拉拔器拆卸损坏轴承,清洁轴承座,安装新轴承时确保配合精度。',
|
duration: 45,
|
completed: false,
|
expanded: false,
|
warnings: [
|
'轴承拆卸时必须使用专用工具,避免损坏轴颈',
|
'新轴承安装前要检查型号规格是否正确',
|
'安装时要均匀用力,确保轴承完全就位'
|
],
|
tools: ['轴承拉拔器', '轴承加热器', '专用安装工具', '润滑脂']
|
},
|
{
|
id: 5,
|
title: '调整主轴间隙',
|
description: '根据技术要求调整主轴轴向和径向间隙,确保主轴运转平稳,精度符合标准。',
|
duration: 30,
|
completed: false,
|
expanded: false,
|
warnings: [
|
'间隙调整要严格按照技术标准执行',
|
'调整过程中要多次测量确认',
|
'调整完成后要进行试运转检验'
|
],
|
tools: ['百分表', '塞尺', '扭力扳手']
|
},
|
{
|
id: 6,
|
title: '安装防护罩并测试',
|
description: '按照拆卸的逆序安装防护罩,加注润滑油,进行低速试运转,检查运转状态。',
|
duration: 20,
|
completed: false,
|
expanded: false,
|
warnings: [
|
'安装时要确保所有密封件正确就位',
|
'润滑油加注量要符合规定要求',
|
'试运转时要密切观察设备状态'
|
],
|
tools: ['润滑油', '密封胶', '清洁布']
|
}
|
])
|
|
const currentStepIndex = ref(0)
|
|
// 配件清单数据
|
const partsList = ref([
|
{
|
id: 1,
|
name: '主轴轴承',
|
specification: 'NSK 7020C',
|
partNumber: 'BRG-7020C-001',
|
requiredQuantity: 2,
|
stockQuantity: 5,
|
unit: '个',
|
available: true,
|
location: '仓库A区-03货架',
|
supplier: '日本NSK公司',
|
price: 1250.00
|
},
|
{
|
id: 2,
|
name: '密封圈',
|
specification: 'O型圈 φ45×3',
|
partNumber: 'SEAL-045-003',
|
requiredQuantity: 4,
|
stockQuantity: 2,
|
unit: '个',
|
available: false,
|
location: '仓库B区-12货架',
|
supplier: '德国费斯托',
|
price: 25.50
|
},
|
{
|
id: 3,
|
name: '润滑脂',
|
specification: '高温轴承润滑脂 2#',
|
partNumber: 'LUB-HT-002',
|
requiredQuantity: 1,
|
stockQuantity: 8,
|
unit: '支',
|
available: true,
|
location: '仓库C区-05货架',
|
supplier: '美孚石油',
|
price: 180.00
|
},
|
{
|
id: 4,
|
name: '螺栓',
|
specification: 'M8×25 内六角螺栓',
|
partNumber: 'BOLT-M8-025',
|
requiredQuantity: 8,
|
stockQuantity: 50,
|
unit: '个',
|
available: true,
|
location: '仓库A区-01货架',
|
supplier: '标准件厂',
|
price: 2.50
|
},
|
{
|
id: 5,
|
name: '垫片',
|
specification: '调整垫片 φ40×0.1',
|
partNumber: 'SHIM-040-01',
|
requiredQuantity: 6,
|
stockQuantity: 0,
|
unit: '片',
|
available: false,
|
location: '仓库A区-08货架',
|
supplier: '精密加工厂',
|
price: 15.00
|
}
|
])
|
|
// 安全信息数据
|
const safetyInfo = ref({
|
level: '高风险',
|
title: '机械设备维修安全规程',
|
description: '本次维修涉及重型机械设备,存在机械伤害、电击等风险,请严格遵守安全操作规程。',
|
ppe: [
|
{
|
name: '安全帽',
|
icon: '⛑️',
|
description: '防止头部受到撞击伤害',
|
checked: false
|
},
|
{
|
name: '安全眼镜',
|
icon: '🥽',
|
description: '防止金属屑飞溅伤眼',
|
checked: false
|
},
|
{
|
name: '防护手套',
|
icon: '🧤',
|
description: '防止手部割伤和烫伤',
|
checked: false
|
},
|
{
|
name: '安全鞋',
|
icon: '👢',
|
description: '防止足部被重物砸伤',
|
checked: false
|
},
|
{
|
name: '工作服',
|
icon: '🦺',
|
description: '防止衣物被机械卷入',
|
checked: false
|
}
|
],
|
warnings: [
|
'维修前必须确认设备完全断电,并挂上安全标识牌',
|
'使用工具前要检查工具状态,确保完好无损',
|
'拆卸重型部件时要使用起重设备,不得徒手操作',
|
'工作区域要保持整洁,及时清理油污和杂物',
|
'发现异常情况要立即停止作业,报告现场负责人',
|
'严禁在疲劳状态下进行精密操作',
|
'多人协作时要明确分工,加强沟通协调'
|
],
|
emergencyProcedures: [
|
{
|
situation: '人员受伤',
|
steps: [
|
'立即停止所有作业活动',
|
'评估伤情严重程度',
|
'轻伤进行现场急救处理',
|
'重伤立即拨打120急救电话',
|
'通知安全管理人员和项目负责人',
|
'保护现场,配合事故调查'
|
]
|
},
|
{
|
situation: '设备故障',
|
steps: [
|
'立即按下急停按钮',
|
'切断设备电源',
|
'疏散周围人员到安全区域',
|
'通知设备管理人员',
|
'记录故障现象和时间',
|
'等待专业人员处理'
|
]
|
},
|
{
|
situation: '火灾事故',
|
steps: [
|
'立即切断电源',
|
'使用适当的灭火器材',
|
'疏散现场人员',
|
'拨打119火警电话',
|
'通知消防安全管理人员',
|
'配合消防部门救援'
|
]
|
}
|
]
|
})
|
|
const safetyConfirmed = ref(false)
|
|
// 计算属性
|
const completedSteps = computed(() => {
|
return sopSteps.value.filter(step => step.completed).length
|
})
|
|
const canStartWork = computed(() => {
|
return safetyConfirmed.value && completedSteps.value > 0
|
})
|
|
// 返回上一页
|
const goBack = () => {
|
uni.navigateBack()
|
}
|
|
// 获取任务状态类型
|
const getStatusType = (status) => {
|
const statusMap = {
|
'pending': 'warning',
|
'in_progress': 'primary',
|
'completed': 'success',
|
'paused': 'info'
|
}
|
return statusMap[status] || 'info'
|
}
|
|
// 获取任务状态文本
|
const getStatusText = (status) => {
|
const statusMap = {
|
'pending': '待开始',
|
'in_progress': '进行中',
|
'completed': '已完成',
|
'paused': '已暂停'
|
}
|
return statusMap[status] || '未知'
|
}
|
|
// 切换标签
|
const switchTab = (tabKey) => {
|
activeTab.value = tabKey
|
}
|
|
// 切换步骤展开状态
|
const toggleStep = (index) => {
|
sopSteps.value[index].expanded = !sopSteps.value[index].expanded
|
}
|
|
// 完成步骤
|
const completeStep = (index) => {
|
sopSteps.value[index].completed = true
|
showToast('步骤已完成')
|
|
// 自动展开下一步
|
if (index < sopSteps.value.length - 1) {
|
currentStepIndex.value = index + 1
|
sopSteps.value[index + 1].expanded = true
|
}
|
}
|
|
// 取消完成步骤
|
const uncompleteStep = (index) => {
|
sopSteps.value[index].completed = false
|
showToast('已取消完成状态')
|
}
|
|
// 申请配件
|
const requestPart = (part) => {
|
uni.showModal({
|
title: '申请配件',
|
content: `确认申请配件"${part.name}"?`,
|
confirmText: '确认',
|
cancelText: '取消',
|
success: (res) => {
|
if (res.confirm) {
|
showToast('配件申请已提交')
|
// 这里可以调用API提交申请
|
}
|
}
|
})
|
}
|
|
// 查看配件详情
|
const viewPartDetail = (part) => {
|
uni.showModal({
|
title: part.name,
|
content: `配件编号: ${part.partNumber}\n规格: ${part.specification}\n供应商: ${part.supplier}\n单价: ¥${part.price}`,
|
showCancel: false,
|
confirmText: '知道了'
|
})
|
}
|
|
// 获取安全等级类型
|
const getSafetyLevelType = (level) => {
|
const levelMap = {
|
'低风险': 'success',
|
'中风险': 'warning',
|
'高风险': 'error'
|
}
|
return levelMap[level] || 'info'
|
}
|
|
// 切换PPE状态
|
const togglePPE = (ppe) => {
|
ppe.checked = !ppe.checked
|
if (ppe.checked) {
|
showToast(`已确认佩戴${ppe.name}`)
|
}
|
}
|
|
// 确认安全
|
const confirmSafety = () => {
|
const uncheckedPPE = safetyInfo.value.ppe.filter(ppe => !ppe.checked)
|
if (uncheckedPPE.length > 0) {
|
showToast('请确认已佩戴所有个人防护设备')
|
return
|
}
|
|
safetyConfirmed.value = true
|
showToast('安全确认完成,可以开始作业')
|
}
|
|
// 开始作业
|
const startWork = () => {
|
if (!safetyConfirmed.value) {
|
showToast('请先完成安全确认')
|
return
|
}
|
|
if (completedSteps.value === 0) {
|
showToast('请至少完成一个SOP步骤')
|
return
|
}
|
|
uni.showModal({
|
title: '开始作业',
|
content: '确认开始正式作业?',
|
confirmText: '开始',
|
cancelText: '取消',
|
success: (res) => {
|
if (res.confirm) {
|
currentTask.value.status = 'in_progress'
|
showToast('作业已开始,请按照SOP执行')
|
}
|
}
|
})
|
}
|
|
// 保存进度
|
const saveProgress = () => {
|
const progress = {
|
taskId: currentTask.value.id,
|
completedSteps: completedSteps.value,
|
safetyConfirmed: safetyConfirmed.value,
|
timestamp: new Date().toISOString()
|
}
|
|
// 这里可以调用API保存进度
|
showToast('进度已保存')
|
console.log('保存的进度:', progress)
|
}
|
|
onMounted(() => {
|
// 页面加载时的初始化逻辑
|
// 可以根据任务ID加载对应的SOP、配件清单和安全提示
|
})
|
|
onShow(() => {
|
// 页面显示时的逻辑
|
})
|
</script>
|
|
<style scoped lang="scss">
|
@import '@/styles/sales-common.scss';
|
|
// 标准作业指导特有样式
|
.sales-account {
|
padding-bottom: 100px;
|
}
|
|
// 任务信息卡片
|
.task-info-card {
|
margin: 20px;
|
background: #ffffff;
|
border-radius: 12px;
|
padding: 16px;
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
|
}
|
|
.task-header {
|
display: flex;
|
justify-content: space-between;
|
align-items: center;
|
margin-bottom: 12px;
|
}
|
|
.task-left {
|
display: flex;
|
align-items: center;
|
gap: 12px;
|
}
|
|
.task-icon {
|
width: 40px;
|
height: 40px;
|
background: #2979ff;
|
border-radius: 8px;
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
}
|
|
.task-details {
|
display: flex;
|
flex-direction: column;
|
gap: 4px;
|
}
|
|
.task-title {
|
font-size: 16px;
|
font-weight: 500;
|
color: #333;
|
}
|
|
.task-subtitle {
|
font-size: 12px;
|
color: #666;
|
}
|
|
.task-meta {
|
display: flex;
|
flex-direction: column;
|
gap: 8px;
|
}
|
|
.meta-item {
|
display: flex;
|
justify-content: space-between;
|
align-items: center;
|
}
|
|
.meta-label {
|
font-size: 12px;
|
color: #777;
|
min-width: 70px;
|
}
|
|
.meta-value {
|
font-size: 12px;
|
color: #333;
|
flex: 1;
|
text-align: right;
|
}
|
|
// 导航标签
|
.nav-tabs {
|
display: flex;
|
background: #ffffff;
|
margin: 0 20px;
|
border-radius: 12px;
|
padding: 4px;
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
|
}
|
|
.nav-tab {
|
flex: 1;
|
display: flex;
|
flex-direction: column;
|
align-items: center;
|
gap: 4px;
|
padding: 12px 8px;
|
border-radius: 8px;
|
transition: all 0.3s ease;
|
|
&.active {
|
background: #f3f7ff;
|
}
|
}
|
|
.tab-text {
|
font-size: 12px;
|
color: #666;
|
|
&.active {
|
color: #2979ff;
|
font-weight: 500;
|
}
|
}
|
|
// 内容区域
|
.content-section {
|
margin: 20px;
|
}
|
|
.section-header {
|
display: flex;
|
justify-content: space-between;
|
align-items: center;
|
margin-bottom: 16px;
|
}
|
|
.section-title {
|
font-size: 16px;
|
font-weight: 500;
|
color: #333;
|
}
|
|
.progress-info {
|
display: flex;
|
align-items: center;
|
gap: 4px;
|
}
|
|
.progress-text {
|
font-size: 12px;
|
color: #666;
|
}
|
|
// SOP步骤样式
|
.sop-steps {
|
display: flex;
|
flex-direction: column;
|
gap: 12px;
|
}
|
|
.sop-step {
|
background: #ffffff;
|
border-radius: 12px;
|
border: 1px solid #f0f0f0;
|
overflow: hidden;
|
transition: all 0.3s ease;
|
|
&.completed {
|
border-color: #4caf50;
|
background: #f8fff8;
|
}
|
|
&.current {
|
border-color: #2979ff;
|
box-shadow: 0 2px 8px rgba(41, 121, 255, 0.1);
|
}
|
}
|
|
.step-header {
|
display: flex;
|
align-items: center;
|
padding: 16px;
|
cursor: pointer;
|
}
|
|
.step-number {
|
width: 28px;
|
height: 28px;
|
border-radius: 50%;
|
background: #f5f5f5;
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
margin-right: 12px;
|
|
.sop-step.completed & {
|
background: #4caf50;
|
}
|
}
|
|
.step-num {
|
font-size: 12px;
|
font-weight: 500;
|
color: #666;
|
|
.sop-step.completed & {
|
color: #ffffff;
|
}
|
}
|
|
.step-content {
|
flex: 1;
|
display: flex;
|
flex-direction: column;
|
gap: 4px;
|
}
|
|
.step-title {
|
font-size: 14px;
|
font-weight: 500;
|
color: #333;
|
}
|
|
.step-duration {
|
font-size: 12px;
|
color: #666;
|
}
|
|
.step-details {
|
padding: 0 16px 16px 16px;
|
border-top: 1px solid #f0f0f0;
|
}
|
|
.step-description {
|
margin: 16px 0;
|
}
|
|
.desc-text {
|
font-size: 13px;
|
color: #555;
|
line-height: 1.5;
|
}
|
|
.step-warnings {
|
margin: 16px 0;
|
padding: 12px;
|
background: #fff3e0;
|
border-radius: 8px;
|
border-left: 4px solid #ff9800;
|
}
|
|
.warning-title {
|
font-size: 13px;
|
font-weight: 500;
|
color: #e65100;
|
margin-bottom: 8px;
|
}
|
|
.warning-item {
|
margin-bottom: 4px;
|
}
|
|
.warning-text {
|
font-size: 12px;
|
color: #bf360c;
|
line-height: 1.4;
|
}
|
|
.step-tools {
|
margin: 16px 0;
|
}
|
|
.tools-title {
|
font-size: 13px;
|
font-weight: 500;
|
color: #333;
|
margin-bottom: 8px;
|
}
|
|
.tools-list {
|
display: flex;
|
flex-wrap: wrap;
|
gap: 6px;
|
}
|
|
.tool-tag {
|
margin: 0;
|
}
|
|
.step-actions {
|
margin-top: 16px;
|
display: flex;
|
gap: 8px;
|
}
|
|
// 配件清单样式
|
.parts-summary {
|
display: flex;
|
align-items: center;
|
}
|
|
.summary-text {
|
font-size: 12px;
|
color: #666;
|
}
|
|
.parts-list {
|
display: flex;
|
flex-direction: column;
|
gap: 12px;
|
}
|
|
.part-item {
|
background: #ffffff;
|
border-radius: 12px;
|
padding: 16px;
|
border: 1px solid #f0f0f0;
|
}
|
|
.part-header {
|
display: flex;
|
justify-content: space-between;
|
align-items: flex-start;
|
margin-bottom: 12px;
|
}
|
|
.part-info {
|
flex: 1;
|
}
|
|
.part-name {
|
font-size: 14px;
|
font-weight: 500;
|
color: #333;
|
display: block;
|
margin-bottom: 4px;
|
}
|
|
.part-spec {
|
font-size: 12px;
|
color: #666;
|
}
|
|
.part-details {
|
display: flex;
|
flex-direction: column;
|
gap: 6px;
|
margin-bottom: 12px;
|
}
|
|
.detail-row {
|
display: flex;
|
justify-content: space-between;
|
align-items: center;
|
}
|
|
.detail-label {
|
font-size: 12px;
|
color: #777;
|
min-width: 70px;
|
}
|
|
.detail-value {
|
font-size: 12px;
|
color: #333;
|
|
&.danger {
|
color: #f44336;
|
font-weight: 500;
|
}
|
}
|
|
.part-actions {
|
display: flex;
|
gap: 8px;
|
}
|
|
// 安全提示样式
|
.safety-level {
|
display: flex;
|
align-items: center;
|
}
|
|
.safety-overview {
|
display: flex;
|
align-items: flex-start;
|
gap: 12px;
|
padding: 16px;
|
background: #fff3e0;
|
border-radius: 12px;
|
margin-bottom: 20px;
|
border-left: 4px solid #ff6b35;
|
}
|
|
.safety-icon {
|
margin-top: 2px;
|
}
|
|
.safety-content {
|
flex: 1;
|
}
|
|
.safety-title {
|
font-size: 14px;
|
font-weight: 500;
|
color: #e65100;
|
display: block;
|
margin-bottom: 4px;
|
}
|
|
.safety-desc {
|
font-size: 12px;
|
color: #bf360c;
|
line-height: 1.4;
|
}
|
|
.safety-section {
|
margin-bottom: 20px;
|
background: #ffffff;
|
border-radius: 12px;
|
padding: 16px;
|
border: 1px solid #f0f0f0;
|
}
|
|
.safety-section-title {
|
font-size: 14px;
|
font-weight: 500;
|
color: #333;
|
margin-bottom: 12px;
|
}
|
|
// PPE列表
|
.ppe-list {
|
display: flex;
|
flex-direction: column;
|
gap: 12px;
|
}
|
|
.ppe-item {
|
display: flex;
|
align-items: center;
|
gap: 12px;
|
padding: 12px;
|
background: #f8f9fa;
|
border-radius: 8px;
|
}
|
|
.ppe-icon {
|
width: 32px;
|
height: 32px;
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
}
|
|
.ppe-emoji {
|
font-size: 20px;
|
}
|
|
.ppe-info {
|
flex: 1;
|
}
|
|
.ppe-name {
|
font-size: 13px;
|
font-weight: 500;
|
color: #333;
|
display: block;
|
margin-bottom: 2px;
|
}
|
|
.ppe-desc {
|
font-size: 11px;
|
color: #666;
|
}
|
|
// 安全警告
|
.safety-warnings {
|
display: flex;
|
flex-direction: column;
|
gap: 8px;
|
}
|
|
.safety-warning {
|
display: flex;
|
align-items: flex-start;
|
gap: 8px;
|
padding: 8px 0;
|
}
|
|
.warning-icon {
|
margin-top: 2px;
|
}
|
|
.warning-content {
|
flex: 1;
|
font-size: 12px;
|
color: #555;
|
line-height: 1.4;
|
}
|
|
// 应急处理
|
.emergency-procedures {
|
display: flex;
|
flex-direction: column;
|
gap: 16px;
|
}
|
|
.emergency-item {
|
border: 1px solid #ffcdd2;
|
border-radius: 8px;
|
overflow: hidden;
|
}
|
|
.emergency-header {
|
background: #ffebee;
|
padding: 12px 16px;
|
border-bottom: 1px solid #ffcdd2;
|
}
|
|
.emergency-title {
|
font-size: 13px;
|
font-weight: 500;
|
color: #c62828;
|
}
|
|
.emergency-steps {
|
padding: 12px 16px;
|
}
|
|
.emergency-step {
|
display: flex;
|
align-items: flex-start;
|
gap: 8px;
|
margin-bottom: 8px;
|
|
&:last-child {
|
margin-bottom: 0;
|
}
|
}
|
|
.step-number {
|
font-size: 12px;
|
font-weight: 500;
|
color: #d32f2f;
|
min-width: 16px;
|
}
|
|
.step-content {
|
font-size: 12px;
|
color: #555;
|
line-height: 1.4;
|
}
|
|
// 安全确认
|
.safety-confirmation {
|
background: #e8f5e8;
|
border-radius: 12px;
|
padding: 16px;
|
border: 1px solid #c8e6c9;
|
}
|
|
.confirmation-header {
|
display: flex;
|
align-items: center;
|
gap: 8px;
|
margin-bottom: 8px;
|
}
|
|
.confirmation-title {
|
font-size: 14px;
|
font-weight: 500;
|
color: #2e7d32;
|
}
|
|
.confirmation-content {
|
margin-bottom: 16px;
|
}
|
|
.confirmation-text {
|
font-size: 12px;
|
color: #388e3c;
|
line-height: 1.4;
|
}
|
|
.confirmation-actions {
|
display: flex;
|
justify-content: center;
|
}
|
|
// 底部操作按钮
|
.bottom-actions {
|
position: fixed;
|
bottom: 0;
|
left: 0;
|
right: 0;
|
background: #ffffff;
|
padding: 16px 20px;
|
border-top: 1px solid #f0f0f0;
|
display: flex;
|
gap: 12px;
|
z-index: 100;
|
}
|
|
.bottom-actions .u-button {
|
flex: 1;
|
}
|
</style>
|