From c58665039ce8b7c895ed4f1000ff4cf525a92085 Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期三, 27 八月 2025 16:28:21 +0800
Subject: [PATCH] 1.设备保养开发联调

---
 src/pages/cooperativeOffice/collaborativeApproval/detail.vue |  931 +++++++++++++++++++++++++++++++++++----------------------
 1 files changed, 575 insertions(+), 356 deletions(-)

diff --git a/src/pages/cooperativeOffice/collaborativeApproval/detail.vue b/src/pages/cooperativeOffice/collaborativeApproval/detail.vue
index 362b237..219b32a 100644
--- a/src/pages/cooperativeOffice/collaborativeApproval/detail.vue
+++ b/src/pages/cooperativeOffice/collaborativeApproval/detail.vue
@@ -1,58 +1,74 @@
 <template>
   <view class="account-detail">
-    <!-- 椤堕儴鏍囬鏍� -->
-    <view class="header">
-      <up-icon name="arrow-left" size="20" color="#333" @click="goBack" />
-      <text class="title">瀹℃壒娴佺▼</text>
-    </view>
+    <PageHeader title="瀹℃壒娴佺▼" @back="goBack" />
 
     <!-- 琛ㄥ崟鍖哄煙 -->
     <view class="form-section">
-      <van-form ref="formRef" @submit="submitForm" :rules="rules" input-align="right">
-        <van-cell-group inset style="height:auto">
+      <van-form ref="formRef" @submit="submitForm" :rules="rules" input-align="right" error-message-align="right" scroll-to-error scroll-to-error-position="center">
+				<van-cell-group style="margin-bottom: 16px;">
+					<van-field
+						v-model="form.approveReason"
+						name="approveReason"
+						rows="2"
+						autosize
+						label="鐢宠浜嬬敱"
+						type="textarea"
+						maxlength="200"
+						:rules="[{ required: true, message: '鐢宠浜嬬敱涓嶈兘涓虹┖' }]"
+						placeholder="璇疯緭鍏ョ敵璇蜂簨鐢�"
+						show-word-limit
+						required
+					/>
+				</van-cell-group>
+				<van-cell-group>
+					<van-field
+						v-model="form.approveDeptName"
+						readonly
+						name="picker"
+						label="鐢宠閮ㄩ棬"
+						placeholder="璇烽�夋嫨鐢宠閮ㄩ棬"
+						:rules="[{ required: true, message: '璇烽�夋嫨鐢宠閮ㄩ棬' }]"
+						@click="showPicker = true"
+						required
+					/>
           <van-field
-            v-model="taxPrice"
+            v-model="form.approveUserName"
             name="taxPrice"
-            label="濮撳悕"
-            placeholder="璇疯緭鍏ュ鍚�"
-            :rules="[{ required: true, message: '濮撳悕涓嶈兘涓虹┖' }]"
+            label="鐢宠浜�"
+            placeholder="璇疯緭鍏ョ敵璇蜂汉"
+            :rules="[{ required: true, message: '鐢宠浜轰笉鑳戒负绌�' }]"
             required
             readonly
-          />
-          <van-field
-            v-model="result"
-            readonly
-            name="picker"
-            label="鐢宠閮ㄩ棬"
-            placeholder="璇烽�夋嫨鐢宠閮ㄩ棬"
-            :rules="[{ required: true, message: '璇烽�夋嫨鐢宠閮ㄩ棬' }]"
-            @click="showPicker = true"
-            required
           />
           <van-popup
             v-model:show="showPicker"
-            destroy-on-close
             position="bottom"
           >
             <van-picker
-              :columns="columns"
+              :columns="productOptions"
               :model-value="pickerValue"
               @confirm="onConfirm"
               @cancel="showPicker = false"
             />
           </van-popup>
-          <van-field
-            v-model="message"
-            name="message"
-            rows="1"
-            autosize
-            label="鐢宠浜嬬敱"
-            type="textarea"
-            placeholder="璇疯緭鍏ョ敵璇蜂簨鐢�"
-            height="100"
-            :rules="[{ required: true, message: '鐢宠浜嬬敱涓嶈兘涓虹┖' }]"
-            required
-          />
+					<van-field
+						v-model="form.approveTime"
+						label="鐢宠鏃ユ湡"
+						placeholder="璇烽�夋嫨"
+						readonly
+						required
+						@click="showDatePicker"
+						:rules="[{ required: true, message: '璇烽�夋嫨鏉ユ鏃ユ湡' }]"
+					/>
+					<!-- 鏃ユ湡閫夋嫨鍣� -->
+					<van-popup v-model:show="showDate" position="bottom">
+						<van-date-picker
+							v-model="currentDate"
+							title="閫夋嫨鏃ユ湡"
+							@confirm="onDateConfirm"
+							@cancel="showDate = false"
+						/>
+					</van-popup>
         </van-cell-group>
       </van-form>
     </view>
@@ -60,30 +76,38 @@
     <view class="approval-process">
       <view class="approval-header">
         <text class="approval-title">瀹℃牳娴佺▼</text>
-        <text class="approval-desc">宸茬敱绠$悊鍛橀璁句笉鍙慨鏀�</text>
+        <text class="approval-desc">姣忎釜姝ラ鍙兘閫夋嫨涓�涓鎵逛汉</text>
       </view>
 
       <view class="approval-steps">
-        <view v-for="(step, stepIndex) in approvalSteps" :key="stepIndex" class="approval-step">
+        <view v-for="(step, stepIndex) in approverNodes" :key="stepIndex" class="approval-step">
+          <view class="step-dot"></view>
           <view class="step-title">
             <text>瀹℃壒浜�</text>
           </view>
-          <view class="approvers-container">
-            <view v-for="(approver, approverIndex) in step.approvers" :key="approverIndex" class="approver-item">
-              <view class="approver-avatar"></view>
-              <text class="approver-name">{{ approver.name }}</text>
-              <view class="delete-approver-btn" @click="removeApprover(stepIndex, approverIndex)">脳</view>
+          <view class="approver-container">
+            <view v-if="step.nickName" class="approver-item">
+              <view class="approver-avatar">
+                <text class="avatar-text">{{ step.nickName.charAt(0) }}</text>
+                <view class="status-dot"></view>
+              </view>
+              <view class="approver-info">
+                <text class="approver-name">{{ step.nickName }}</text>
+              </view>
+              <view class="delete-approver-btn" @click="removeApprover(stepIndex)">脳</view>
             </view>
-            <view class="add-approver-btn" @click="addApprover(stepIndex)">+
+            <view v-else class="add-approver-btn" @click="addApprover(stepIndex)">
+              <view class="add-circle">+</view>
+              <text class="add-label">閫夋嫨瀹℃壒浜�</text>
             </view>
           </view>
-          <view class="step-line" v-if="stepIndex < approvalSteps.length - 1"></view>
-          <view class="delete-step-btn" @click="removeApprovalStep(stepIndex)">鍒犻櫎鑺傜偣</view>
+          <view class="step-line" v-if="stepIndex < approverNodes.length - 1"></view>
+          <view class="delete-step-btn" v-if="approverNodes.length > 1" @click="removeApprovalStep(stepIndex)">鍒犻櫎鑺傜偣</view>
         </view>
       </view>
 
-      <view class="add-step-btn" @click="addApprovalStep">
-        <text>鏂板鑺傜偣瀹℃牳浜�</text>
+      <view class="add-step-btn">
+				<van-button icon="plus" plain type="primary" style="width: 100%" @click="addApprovalStep">鏂板鑺傜偣</van-button>
       </view>
     </view>
 
@@ -95,166 +119,238 @@
   </view>
 </template>
 
-<script>
-import { ref, onMounted } from "vue";
+<script setup>
+import { ref, onMounted, onUnmounted, reactive, toRefs } from "vue";
+import PageHeader from "@/components/PageHeader.vue";
+import useUserStore from "@/store/modules/user";
+import {getDept, approveProcessGetInfo, approveProcessAdd, approveProcessUpdate} from "@/api/collaborativeApproval/approvalProcess";
+import { showToast } from 'vant'
+import {userListNoPageByTenantId} from "@/api/system/user";
 
-export default {
-  setup() {
-    const rules = ref({
-
-  taxPrice: {
-    rules: [{ required: true, errorMessage: '濮撳悕涓嶈兘涓虹┖' }]
-  },
-  result: {
-    rules: [{ required: true, errorMessage: '璇烽�夋嫨鐢宠閮ㄩ棬' }]
-  },
-  message: {
-    rules: [{ required: true, errorMessage: '鐢宠浜嬬敱涓嶈兘涓虹┖' }]
-  },
+const data = reactive({
+	form: {
+		approveTime: "",
+		approveId: "",
+		approveUser: "",
+		approveUserName: "",
+		approveDeptName: "",
+		approveDeptId: "",
+		approveReason: "",
+		checkResult: "",
+		tempFileIds: [],
+		approverList: [] // 鏂板瀛楁锛屽瓨鍌ㄦ墍鏈夎妭鐐圭殑瀹℃壒浜篿d
+	},
+	rules: {
+		approveTime: [{ required: false, message: "璇疯緭鍏�", trigger: "change" },],
+		approveId: [{ required: false, message: "璇疯緭鍏�", trigger: "blur" }],
+		approveUser: [{ required: false, message: "璇疯緭鍏�", trigger: "blur" }],
+		approveDeptId: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+		approveReason: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+		checkResult: [{ required: false, message: "璇疯緭鍏�", trigger: "blur" }],
+	},
 });
-    const result = ref("");
-    const pickerValue = ref([]);
-    const showPicker = ref(false);
-    const columns = ref([]);
-    onMounted(async () => {
-      try {
-        // 鏇挎崲涓哄疄闄呮帴鍙e湴鍧�
-        // const response = await axios.get('/api/getDepartments');
-        columns.value = [
-          {
-            text: "鏉窞",
-            value: "Hangzhou",
-          },
-          {
-            text: "瀹佹尝",
-            value: "Ningbo",
-          },
-          {
-            text: "娓╁窞",
-            value: "Wenzhou",
-          },
-          {
-            text: "缁嶅叴",
-            value: "Shaoxing",
-          },
-          {
-            text: "婀栧窞",
-            value: "Huzhou",
-          },
-        ];
-      } catch (error) {
-        console.error("鑾峰彇閮ㄩ棬鏁版嵁澶辫触:", error);
-      }
-    });
-    const onConfirm = ({ selectedValues, selectedOptions }) => {
-      result.value = selectedOptions[0]?.text;
-      pickerValue.value = selectedValues;
-      showPicker.value = false;
-    };
-    const taxPrice = ref("");
-    const contractAmount = ref("");
-    const approvalSteps = ref([
-      { approvers: [{ name: '鍗㈠皬鏁�' }, { name: '鍗㈠皬鏁�' }] },
-      { approvers: [{ name: '鍗㈠皬鏁�' }] },
-      { approvers: [{ name: '鍗㈠皬鏁�' }] },
-      { approvers: [{ name: '鍗㈠皬鏁�' }] }
-    ]);
+const { form, rules } = toRefs(data);
+const result = ref("");
+const pickerValue = ref([]);
+const showPicker = ref(false);
+const productOptions = ref([]);
+const operationType = ref("");
+const currentApproveStatus = ref("");
+const approverNodes = ref([]);
+const userList = ref([]);
+const formRef = ref(null);
+const message = ref("");
+const showDate = ref(false)
+const currentDate = ref([new Date().getFullYear(), new Date().getMonth() + 1, new Date().getDate()])
+const userStore = useUserStore()
 
-    const goBack = () => {
-    	uni.navigateBack();
-    };
-
-    const formRef = ref(null);
-
-    const submitForm = () => {
-      formRef.value.validate().then(() => {
-        // 琛ㄥ崟鏍¢獙閫氳繃锛屽彲浠ユ彁浜ゆ暟鎹�
-        console.log("琛ㄥ崟鏁版嵁:", {
-          taxPrice: taxPrice.value,
-          department: result.value,
-          message: message.value,
-          approvalSteps: approvalSteps.value
-        });
-
-        uni.showToast({
-          title: "淇濆瓨鎴愬姛",
-          icon: "success",
-        });
-      }).catch((error) => {
-        console.error("琛ㄥ崟鏍¢獙澶辫触:", error);
-        // 鏄剧ず鍏蜂綋鐨勯敊璇俊鎭�
-        if (error.length > 0) {
-          const firstError = error[0];
-          uni.showToast({
-            title: firstError.message || '琛ㄥ崟鏍¢獙澶辫触',
-            icon: 'none'
-          });
-        } else {
-          uni.showToast({
-            title: '琛ㄥ崟鏍¢獙澶辫触锛岃妫�鏌ュ繀濉」',
-            icon: 'none'
-          });
-        }
-      });
-    };
-
-    const message = ref("");
-
-    const addApprover = (stepIndex) => {
-      // 鍦ㄦ寚瀹氬鎵规楠ゆ坊鍔犳柊鐨勫鎵逛汉
-      approvalSteps.value[stepIndex].approvers.push({ name: '鍗㈠皬鏁�' });
-    };
-
-    const addApprovalStep = () => {
-      // 娣诲姞鏂扮殑瀹℃壒姝ラ
-      approvalSteps.value.push({ approvers: [{ name: '鍗㈠皬鏁�' }] });
-    };
-
-    const removeApprover = (stepIndex, approverIndex) => {
-      // 纭繚姣忎釜姝ラ鑷冲皯淇濈暀涓�涓鎵逛汉
-      if (approvalSteps.value[stepIndex].approvers.length > 1) {
-        approvalSteps.value[stepIndex].approvers.splice(approverIndex, 1);
-      } else {
-        uni.showToast({
-          title: '姣忎釜姝ラ鑷冲皯闇�瑕佷竴涓鎵逛汉',
-          icon: 'none'
-        });
-      }
-    };
-
-    const removeApprovalStep = (stepIndex) => {
-      // 纭繚鑷冲皯淇濈暀涓�涓鎵规楠�
-      if (approvalSteps.value.length > 1) {
-        approvalSteps.value.splice(stepIndex, 1);
-      } else {
-        uni.showToast({
-          title: '鑷冲皯闇�瑕佷竴涓鎵规楠�',
-          icon: 'none'
-        });
-      }
-    };
-
-    return {
-      rules,
-      removeApprovalStep,
-    removeApprover,
-      result,
-      pickerValue,
-      columns,
-      onConfirm,
-      showPicker,
-      taxPrice,
-      contractAmount,
-      goBack,
-      submitForm,
-      approvalSteps,
-      addApprover,
-      addApprovalStep,
-      formRef,
-      message
-    };
-  },
+const getProductOptions = () => {
+	getDept().then((res) => {
+		productOptions.value = res.data.map(item => ({
+			value: item.deptId,
+			text: item.deptName
+		}))
+	});
 };
+const fileList = ref([]);
+let nextApproverId = 2;
+
+onMounted(async () => {
+  try {
+		getProductOptions()
+		userListNoPageByTenantId().then((res) => {
+			userList.value = res.data
+		})
+		form.value.approveUser = userStore.id
+		form.value.approveUserName = userStore.nickName
+		form.value.approveTime = getCurrentDate();
+		
+		// 鑾峰彇URL鍙傛暟
+		const pages = getCurrentPages();
+		const currentPage = pages[pages.length - 1];
+		operationType.value = currentPage.options.operationType || 'add';
+		
+		// 濡傛灉鏄紪杈戞ā寮忥紝浠庢湰鍦板瓨鍌ㄨ幏鍙栨暟鎹�
+		if (operationType.value === 'edit') {
+			const storedData = uni.getStorageSync('invoiceLedgerEditRow');
+			if (storedData) {
+				const row = JSON.parse(storedData);
+				fileList.value = row.commonFileList || [];
+				form.value.tempFileIds = fileList.value.map(file => file.id);
+				currentApproveStatus.value = row.approveStatus;
+				
+				approveProcessGetInfo({id: row.approveId, approveReason: '1'}).then(res => {
+					form.value = {...res.data};
+					// 鍙嶆樉瀹℃壒浜�
+					if (res.data && res.data.approveUserIds) {
+						const userIds = res.data.approveUserIds.split(',');
+						approverNodes.value = userIds.map((userId, idx) => {
+							const userIdNum = parseInt(userId.trim());
+							// 浠巙serList涓壘鍒板搴旂殑鐢ㄦ埛淇℃伅
+							const userInfo = userList.value.find(user => user.userId === userIdNum);
+							return {
+								id: idx + 1,
+								userId: userIdNum,
+								nickName: userInfo ? userInfo.nickName : null
+							};
+						});
+						nextApproverId = userIds.length + 1;
+					} else {
+						// 鏂板妯″紡锛屽垵濮嬪寲涓�涓┖鐨勫鎵硅妭鐐�
+						approverNodes.value = [{ id: 1, userId: null, nickName: null }];
+						nextApproverId = 2;
+					}
+				});
+			}
+		} else {
+			// 鏂板妯″紡锛屽垵濮嬪寲涓�涓┖鐨勫鎵硅妭鐐�
+			approverNodes.value = [{ id: 1, userId: null }];
+		}
+		
+    // 鐩戝惉鑱旂郴浜洪�夋嫨浜嬩欢
+    uni.$on('selectContact', handleSelectContact);
+  } catch (error) {
+    console.error("鑾峰彇閮ㄩ棬鏁版嵁澶辫触:", error);
+  }
+});
+
+onUnmounted(() => {
+  // 绉婚櫎浜嬩欢鐩戝惉
+  uni.$off('selectContact', handleSelectContact);
+});
+
+const onConfirm = ({ selectedValues, selectedOptions }) => {
+  form.value.approveDeptName = selectedOptions[0]?.text;
+  form.value.approveDeptId = selectedOptions[0]?.value;
+  pickerValue.value = selectedValues;
+  showPicker.value = false;
+};
+
+const goBack = () => {
+	// 娓呴櫎鏈湴瀛樺偍鐨勬暟鎹�
+	uni.removeStorageSync('invoiceLedgerEditRow');
+  uni.navigateBack();
+};
+
+const submitForm = () => {
+  // 妫�鏌ユ瘡涓鎵规楠ゆ槸鍚﹂兘鏈夊鎵逛汉
+  const hasEmptyStep = approverNodes.value.some(step => !step.nickName);
+  if (hasEmptyStep) {
+		showToast('璇蜂负姣忎釜瀹℃壒姝ラ閫夋嫨瀹℃壒浜�');
+    return;
+  }
+  
+  formRef.value.validate().then(() => {
+    // 琛ㄥ崟鏍¢獙閫氳繃锛屽彲浠ユ彁浜ゆ暟鎹�
+		// 鏀堕泦鎵�鏈夎妭鐐圭殑瀹℃壒浜篿d
+		console.log('approverNodes---', approverNodes.value)
+		form.value.approveUserIds = approverNodes.value.map(node => node.userId).join(',')
+		form.value.approveType = 0
+		if (operationType.value === "add" || currentApproveStatus.value == 3) {
+			approveProcessAdd(form.value).then(res => {
+				showToast("鎻愪氦鎴愬姛");
+				goBack()
+			})
+		} else {
+			approveProcessUpdate(form.value).then(res => {
+				showToast("鎻愪氦鎴愬姛");
+				goBack()
+			})
+		}
+  }).catch((error) => {
+    console.error("琛ㄥ崟鏍¢獙澶辫触:", error);
+    // 鏄剧ず鍏蜂綋鐨勯敊璇俊鎭�
+    if (error.length > 0) {
+      const firstError = error[0];
+      uni.showToast({
+        title: firstError.message || '琛ㄥ崟鏍¢獙澶辫触',
+        icon: 'none'
+      });
+    } else {
+      uni.showToast({
+        title: '琛ㄥ崟鏍¢獙澶辫触锛岃妫�鏌ュ繀濉」',
+        icon: 'none'
+      });
+    }
+  });
+};
+
+// 澶勭悊鑱旂郴浜洪�夋嫨缁撴灉
+const handleSelectContact = (data) => {
+  const { stepIndex, contact } = data;
+  // 灏嗛�変腑鐨勮仈绯讳汉璁剧疆涓哄搴斿鎵规楠ょ殑瀹℃壒浜�
+  approverNodes.value[stepIndex].userId = contact.userId;
+  approverNodes.value[stepIndex].nickName = contact.nickName;
+};
+
+const addApprover = (stepIndex) => {
+  // 璺宠浆鍒拌仈绯讳汉閫夋嫨椤甸潰
+  uni.navigateTo({
+    url: `/pages/cooperativeOffice/collaborativeApproval/contactSelect?stepIndex=${stepIndex}`
+  });
+};
+
+const addApprovalStep = () => {
+  // 娣诲姞鏂扮殑瀹℃壒姝ラ
+  approverNodes.value.push({ userId: null, nickName: null });
+};
+
+const removeApprover = (stepIndex) => {
+  // 绉婚櫎瀹℃壒浜�
+  approverNodes.value[stepIndex].userId = null;
+  approverNodes.value[stepIndex].nickName = null;
+};
+
+const removeApprovalStep = (stepIndex) => {
+  // 纭繚鑷冲皯淇濈暀涓�涓鎵规楠�
+  if (approverNodes.value.length > 1) {
+    approverNodes.value.splice(stepIndex, 1);
+  } else {
+    uni.showToast({
+      title: '鑷冲皯闇�瑕佷竴涓鎵规楠�',
+      icon: 'none'
+    });
+  }
+};
+// 鏄剧ず鏃ユ湡閫夋嫨鍣�
+const showDatePicker = () => {
+	showDate.value = true
+}
+
+// 纭鏃ユ湡閫夋嫨
+const onDateConfirm = ({ selectedValues }) => {
+	form.value.approveTime = selectedValues.join('-')
+	currentDate.value = selectedValues
+	showDate.value = false
+}
+// 鑾峰彇褰撳墠鏃ユ湡骞舵牸寮忓寲涓� YYYY-MM-DD
+function getCurrentDate() {
+	const today = new Date();
+	const year = today.getFullYear();
+	const month = String(today.getMonth() + 1).padStart(2, "0"); // 鏈堜唤浠�0寮�濮�
+	const day = String(today.getDate()).padStart(2, "0");
+	return `${year}-${month}-${day}`;
+}
 </script>
 
 <style scoped lang="scss">
@@ -287,74 +383,6 @@
   margin-top: 16px;
 }
 
-.van-field {
-  height: 56px;
-  line-height: 36px;
-}
-
-.product-section {
-  background: #fff;
-  margin: 16px;
-  border-radius: 16px;
-  padding: 20px 16px 8px 16px;
-  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
-}
-
-.section-header {
-  display: flex;
-  align-items: center;
-  justify-content: space-between;
-  margin-bottom: 12px;
-}
-
-.section-title {
-  font-size: 16px;
-  font-weight: 600;
-  color: #333;
-}
-
-.add-btn {
-  background: #2979ff;
-  color: #fff;
-  border-radius: 8px;
-  padding: 4px 16px;
-  font-size: 14px;
-}
-
-.product-card {
-  background: #f8f9fa;
-  border-radius: 12px;
-  padding: 12px;
-  margin-bottom: 16px;
-  box-shadow: 0 1px 4px rgba(41, 121, 255, 0.06);
-  position: relative;
-}
-
-.product-row {
-  display: flex;
-  align-items: center;
-  margin-bottom: 8px;
-}
-
-.product-label {
-  min-width: 60px;
-  color: #888;
-  font-size: 13px;
-}
-
-.del-row {
-  justify-content: flex-end;
-}
-
-.del-btn {
-  background: #ff4d4f;
-  color: #fff;
-  border-radius: 8px;
-  padding: 4px 16px;
-  font-size: 13px;
-  margin-top: 4px;
-}
-
 .approval-process {
   background: #fff;
   margin: 16px;
@@ -380,156 +408,347 @@
   color: #999;
 }
 
+/* 鏍峰紡澧炲己涓衡�滅畝娲佸皬鍦嗗湀椋庢牸鈥� */
 .approval-steps {
-  padding-left: 16px;
+  padding-left: 22px;
   position: relative;
+  
+  &::before {
+    content: '';
+    position: absolute;
+    left: 11px;
+    top: 40px;
+    bottom: 40px;
+    width: 2px;
+    background: linear-gradient(to bottom, #e6f7ff 0%, #bae7ff 50%, #91d5ff 100%);
+    border-radius: 1px;
+  }
 }
 
 .approval-step {
   position: relative;
-  margin-bottom: 20px;
+  margin-bottom: 24px;
+  
+  &::before {
+    content: '';
+    position: absolute;
+    left: -18px;
+    top: 14px; // 浠� 8px 璋冩暣涓� 14px锛屼笌鏂囧瓧涓績瀵归綈
+    width: 12px;
+    height: 12px;
+    background: #fff;
+    border: 3px solid #006cfb;
+    border-radius: 50%;
+    z-index: 2;
+    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+  }
 }
 
 .step-title {
+	top: 12px;
   margin-bottom: 12px;
+  position: relative;
+	margin-left: 6px;
 }
 
 .step-title text {
   font-size: 14px;
   color: #666;
   background: #f0f0f0;
-  padding: 2px 8px;
-  border-radius: 4px;
-}
-
-.approvers-container {
-  display: flex;
-  flex-wrap: wrap;
-  gap: 12px;
-  margin-bottom: 8px;
+  padding: 4px 12px;
+  border-radius: 12px;
+  position: relative;
+  line-height: 1.4; // 纭繚鏂囧瓧琛岄珮涓�鑷�
 }
 
 .approver-item {
   display: flex;
-  flex-direction: column;
   align-items: center;
-  width: 60px;
+  background: linear-gradient(135deg, #f8f9fa 0%, #ffffff 100%);
+  border-radius: 16px;
+  padding: 16px;
+  gap: 12px;
+  position: relative;
+  border: 1px solid #e6f7ff;
+  box-shadow: 0 4px 12px rgba(0, 108, 251, 0.08);
+  transition: all 0.3s ease;
 }
 
 .approver-avatar {
-  width: 40px;
-  height: 40px;
-  background: #e6f7ff;
+  width: 48px;
+  height: 48px;
+  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
   border-radius: 50%;
-  margin-bottom: 4px;
   display: flex;
   align-items: center;
   justify-content: center;
+  position: relative;
+  box-shadow: 0 4px 12px rgba(102, 126, 234, 0.3);
 }
 
-.approver-avatar::after {
-  content: '馃懁';
-  font-size: 20px;
+.avatar-text {
+  color: #fff;
+  font-size: 18px;
+  font-weight: 600;
+  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
+}
+
+.approver-info {
+  flex: 1;
+  position: relative;
 }
 
 .approver-name {
-  font-size: 12px;
+  display: block;
+  font-size: 16px;
   color: #333;
-  text-align: center;
-  white-space: nowrap;
-  overflow: hidden;
-  text-overflow: ellipsis;
-  margin-bottom: 2px;
+  font-weight: 500;
+  position: relative;
+}
+
+.approver-dept {
+  font-size: 12px;
+  color: #999;
+  background: rgba(0, 108, 251, 0.05);
+  padding: 2px 8px;
+  border-radius: 8px;
+  display: inline-block;
+  position: relative;
+  
+  &::before {
+    content: '';
+    position: absolute;
+    left: 4px;
+    top: 50%;
+    transform: translateY(-50%);
+    width: 2px;
+    height: 2px;
+    background: #006cfb;
+    border-radius: 50%;
+  }
 }
 
 .delete-approver-btn {
-  font-size: 12px;
+  font-size: 16px;
   color: #ff4d4f;
-  background: rgba(255, 77, 79, 0.1);
-  width: 16px;
-  height: 16px;
+  background: linear-gradient(135deg, rgba(255, 77, 79, 0.1) 0%, rgba(255, 77, 79, 0.05) 100%);
+  width: 28px;
+  height: 28px;
   border-radius: 50%;
   display: flex;
   align-items: center;
   justify-content: center;
-  margin-top: 2px;
+  transition: all 0.3s ease;
+  position: relative;
+}
+
+.add-approver-btn {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  background: linear-gradient(135deg, #f0f8ff 0%, #e6f7ff 100%);
+  border: 2px dashed #006cfb;
+  border-radius: 16px;
+  padding: 20px;
+  color: #006cfb;
+  font-size: 14px;
+  position: relative;
+  transition: all 0.3s ease;
+  
+  &::before {
+    content: '';
+    position: absolute;
+    left: 50%;
+    top: 50%;
+    transform: translate(-50%, -50%);
+    width: 32px;
+    height: 32px;
+    border: 2px solid #006cfb;
+    border-radius: 50%;
+    opacity: 0;
+    transition: all 0.3s ease;
+  }
 }
 
 .delete-step-btn {
-  margin-top: 8px;
   color: #ff4d4f;
   font-size: 12px;
-  background: rgba(255, 77, 79, 0.1);
-  padding: 2px 8px;
-  border-radius: 4px;
+  background: linear-gradient(135deg, rgba(255, 77, 79, 0.1) 0%, rgba(255, 77, 79, 0.05) 100%);
+  padding: 6px 12px;
+  border-radius: 12px;
   display: inline-block;
+  position: relative;
+  transition: all 0.3s ease;
+  
+  &::before {
+    content: '';
+    position: absolute;
+    left: 6px;
+    top: 50%;
+    transform: translateY(-50%);
+    width: 4px;
+    height: 4px;
+    background: #ff4d4f;
+    border-radius: 50%;
   }
-
-.add-approver-btn {
-  width: 40px;
-  height: 40px;
-  border: 1px dashed #ccc;
-  border-radius: 50%;
-  display: flex;
-  align-items: center;
-  justify-content: center;
-  font-size: 20px;
-  color: #999;
-  margin-top: 8px;
 }
 
 .step-line {
-  position: absolute;
-  left: 20px;
-  top: 100%;
-  width: 1px;
-  height: 30px;
-  background: #e0e0e0;
+  display: none; // 闅愯棌鍘熸潵鐨勭嚎鏉★紝浣跨敤浼厓绱犱唬鏇�
 }
 
 .add-step-btn {
   display: flex;
   align-items: center;
   justify-content: center;
-  margin-top: 16px;
-  color: #006cfb;
-  font-size: 14px;
-  padding: 8px 0;
-  border: 1px dashed #006cfb;
-  border-radius: 8px;
 }
-
 .footer-btns {
-  position: fixed;
-  left: 0;
-  right: 0;
-  bottom: 0;
-  background: #fff;
-  display: flex;
-  justify-content: space-around;
-  align-items: center;
-  padding: 12px 0;
-  box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.05);
-  z-index: 1000;
+	position: fixed;
+	left: 0;
+	right: 0;
+	bottom: 0;
+	background: #fff;
+	display: flex;
+	justify-content: space-around;
+	align-items: center;
+	padding: 0.75rem 0;
+	box-shadow: 0 -0.125rem 0.5rem rgba(0,0,0,0.05);
+	z-index: 1000;
 }
 
 .cancel-btn {
-  font-weight: 400;
-  font-size: 16px;
-  color: #ffffff;
-  width: 102px;
-  background: #c7c9cc;
-  box-shadow: 0px 4px 10px 0px rgba(3, 88, 185, 0.2);
-  border-radius: 40px 40px 40px 40px;
+	font-weight: 400;
+	font-size: 1rem;
+	color: #FFFFFF;
+	width: 6.375rem;
+	background: #C7C9CC;
+	box-shadow: 0 0.25rem 0.625rem 0 rgba(3,88,185,0.2);
+	border-radius: 2.5rem 2.5rem 2.5rem 2.5rem;
 }
 
 .save-btn {
-  font-weight: 400;
-  font-size: 16px;
-  color: #ffffff;
-  width: 224px;
-  background: linear-gradient(140deg, #00baff 0%, #006cfb 100%);
-  box-shadow: 0px 4px 10px 0px rgba(3, 88, 185, 0.2);
-  border-radius: 40px 40px 40px 40px;
+	font-weight: 400;
+	font-size: 1rem;
+	color: #FFFFFF;
+	width: 14rem;
+	background: linear-gradient( 140deg, #00BAFF 0%, #006CFB 100%);
+	box-shadow: 0 0.25rem 0.625rem 0 rgba(3,88,185,0.2);
+	border-radius: 2.5rem 2.5rem 2.5rem 2.5rem;
+}
+
+// 鍔ㄧ敾瀹氫箟
+@keyframes pulse {
+  0% {
+    transform: scale(1);
+    opacity: 1;
+  }
+  50% {
+    transform: scale(1.2);
+    opacity: 0.7;
+  }
+  100% {
+    transform: scale(1);
+    opacity: 1;
+  }
+}
+
+@keyframes rotate {
+  0% {
+    transform: rotate(0deg);
+  }
+  100% {
+    transform: rotate(360deg);
+  }
+}
+
+@keyframes ripple {
+  0% {
+    transform: translate(-50%, -50%) scale(0.8);
+    opacity: 1;
+  }
+  100% {
+    transform: translate(-50%, -50%) scale(1.6);
+    opacity: 0;
+  }
+}
+
+/* 濡傛灉宸叉湁 .step-line锛岃繖閲屾洿绮惧噯瀹氫綅鍒板乏渚т笌灏忓渾鐐瑰榻� */
+.step-line {
+  position: absolute;
+  left: 4px;
+  top: 48px;
+  width: 2px;
+  height: calc(100% - 48px);
+  background: #E5E7EB;
+}
+
+.approver-container {
+  display: flex;
+  align-items: center;
+  background: linear-gradient(135deg, #f8f9fa 0%, #ffffff 100%);
+  border-radius: 16px;
+  gap: 12px;
+  padding: 10px 0;
+  background: transparent;
+  border: none;
+  box-shadow: none;
+}
+
+.approver-item {
+  display: flex;
+  align-items: center;
+  gap: 12px;
+  padding: 8px 10px;
+  background: transparent;
+  border: none;
+  box-shadow: none;
+  border-radius: 0;
+}
+
+.approver-avatar {
+  position: relative;
+  width: 40px;
+  height: 40px;
+  border-radius: 50%;
+  background: #F3F4F6;
+  border: 2px solid #E5E7EB;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  animation: none; /* 绂佺敤鏃嬭浆绛夊姩鐢伙紝鍥炲綊绠�娲� */
+}
+
+.avatar-text {
+  font-size: 14px;
+  color: #374151;
+  font-weight: 600;
+}
+
+.add-approver-btn {
+  display: flex;
+  align-items: center;
+  gap: 8px;
+  background: transparent;
+  border: none;
+  box-shadow: none;
+  padding: 0;
+}
+
+.add-approver-btn .add-circle {
+  width: 40px;
+  height: 40px;
+  border: 2px dashed #A0AEC0;
+  border-radius: 50%;
+  color: #6B7280;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  font-size: 22px;
+  line-height: 1;
+}
+
+.add-approver-btn .add-label {
+  color: #3B82F6;
+  font-size: 14px;
 }
 </style>
\ No newline at end of file

--
Gitblit v1.9.3