From 2208346bff099670f2ab8608f2f774caa76d867e Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期二, 16 九月 2025 14:12:06 +0800
Subject: [PATCH] 标准作业指导
---
src/pages/index.vue | 10
src/pages.json | 7
src/pages/equipmentManagement/sop/index.vue | 1380 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 1,397 insertions(+), 0 deletions(-)
diff --git a/src/pages.json b/src/pages.json
index 8eda358..cccffcb 100644
--- a/src/pages.json
+++ b/src/pages.json
@@ -371,6 +371,13 @@
"navigationBarTitleText": "鏅鸿兘娲惧崟",
"navigationStyle": "custom"
}
+ },
+ {
+ "path": "pages/equipmentManagement/sop/index",
+ "style": {
+ "navigationBarTitleText": "鏍囧噯浣滀笟鎸囧",
+ "navigationStyle": "custom"
+ }
}
],
"subPackages": [
diff --git a/src/pages/equipmentManagement/sop/index.vue b/src/pages/equipmentManagement/sop/index.vue
new file mode 100644
index 0000000..c577d3b
--- /dev/null
+++ b/src/pages/equipmentManagement/sop/index.vue
@@ -0,0 +1,1380 @@
+<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">鎴戝凡浠旂粏闃呰骞剁悊瑙d互涓婂畨鍏ㄦ彁绀猴紝灏嗕弗鏍兼寜鐓у畨鍏ㄨ绋嬭繘琛屼綔涓�</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: [
+ '蹇呴』纭璁惧瀹屽叏鏂數鍚庢墠鑳借繘琛屽悗缁搷浣�',
+ '鎸備笂"姝e湪缁翠慨锛岀姝㈡搷浣�"鐨勫畨鍏ㄦ爣璇嗙墝',
+ '妫�鏌ュ懆鍥存槸鍚︽湁鍏朵粬浜哄憳锛岀‘淇濆畨鍏ㄨ窛绂�'
+ ],
+ 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: [
+ '瀹夎鏃惰纭繚鎵�鏈夊瘑灏佷欢姝g‘灏变綅',
+ '娑︽粦娌瑰姞娉ㄩ噺瑕佺鍚堣瀹氳姹�',
+ '璇曡繍杞椂瑕佸瘑鍒囪瀵熻澶囩姸鎬�'
+ ],
+ 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: '闃叉琛g墿琚満姊板嵎鍏�',
+ checked: false
+ }
+ ],
+ warnings: [
+ '缁翠慨鍓嶅繀椤荤‘璁よ澶囧畬鍏ㄦ柇鐢碉紝骞舵寕涓婂畨鍏ㄦ爣璇嗙墝',
+ '浣跨敤宸ュ叿鍓嶈妫�鏌ュ伐鍏风姸鎬侊紝纭繚瀹屽ソ鏃犳崯',
+ '鎷嗗嵏閲嶅瀷閮ㄤ欢鏃惰浣跨敤璧烽噸璁惧锛屼笉寰楀緬鎵嬫搷浣�',
+ '宸ヤ綔鍖哄煙瑕佷繚鎸佹暣娲侊紝鍙婃椂娓呯悊娌规薄鍜屾潅鐗�',
+ '鍙戠幇寮傚父鎯呭喌瑕佺珛鍗冲仠姝綔涓氾紝鎶ュ憡鐜板満璐熻矗浜�',
+ '涓ョ鍦ㄧ柌鍔崇姸鎬佷笅杩涜绮惧瘑鎿嶄綔',
+ '澶氫汉鍗忎綔鏃惰鏄庣‘鍒嗗伐锛屽姞寮烘矡閫氬崗璋�'
+ ],
+ emergencyProcedures: [
+ {
+ situation: '浜哄憳鍙椾激',
+ steps: [
+ '绔嬪嵆鍋滄鎵�鏈変綔涓氭椿鍔�',
+ '璇勪及浼ゆ儏涓ラ噸绋嬪害',
+ '杞讳激杩涜鐜板満鎬ユ晳澶勭悊',
+ '閲嶄激绔嬪嵆鎷ㄦ墦120鎬ユ晳鐢佃瘽',
+ '閫氱煡瀹夊叏绠$悊浜哄憳鍜岄」鐩礋璐d汉',
+ '淇濇姢鐜板満锛岄厤鍚堜簨鏁呰皟鏌�'
+ ]
+ },
+ {
+ 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('璇疯嚦灏戝畬鎴愪竴涓猄OP姝ラ')
+ return
+ }
+
+ uni.showModal({
+ title: '寮�濮嬩綔涓�',
+ content: '纭寮�濮嬫寮忎綔涓氾紵',
+ confirmText: '寮�濮�',
+ cancelText: '鍙栨秷',
+ success: (res) => {
+ if (res.confirm) {
+ currentTask.value.status = 'in_progress'
+ showToast('浣滀笟宸插紑濮嬶紝璇锋寜鐓OP鎵ц')
+ }
+ }
+ })
+}
+
+// 淇濆瓨杩涘害
+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鍔犺浇瀵瑰簲鐨凷OP銆侀厤浠舵竻鍗曞拰瀹夊叏鎻愮ず
+})
+
+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>
\ No newline at end of file
diff --git a/src/pages/index.vue b/src/pages/index.vue
index 05398bd..e931c3f 100644
--- a/src/pages/index.vue
+++ b/src/pages/index.vue
@@ -275,6 +275,11 @@
icon: 'flash',
label: '鏅鸿兘娲惧崟',
bgColor: '#ff6b35'
+ },
+ {
+ icon: 'file-text',
+ label: '浣滀笟鎸囧',
+ bgColor: '#4caf50'
}
]);
@@ -377,6 +382,11 @@
url: '/pages/equipmentManagement/smartDispatch/index'
});
break;
+ case '浣滀笟鎸囧':
+ uni.navigateTo({
+ url: '/pages/equipmentManagement/sop/index'
+ });
+ break;
default:
uni.showToast({
title: `鐐瑰嚮浜�${item.label}`,
--
Gitblit v1.9.3