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