From 793391c23ba45b3dab55657ecd2448d87e17f854 Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期二, 16 九月 2025 13:49:53 +0800
Subject: [PATCH] 设备巡检、智能派单
---
src/pages/cooperativeOffice/collaborativeApproval/detail.vue | 1025 ++++++++++++++++++++++++++++++++++----------------------
1 files changed, 620 insertions(+), 405 deletions(-)
diff --git a/src/pages/cooperativeOffice/collaborativeApproval/detail.vue b/src/pages/cooperativeOffice/collaborativeApproval/detail.vue
index 362b237..a564628 100644
--- a/src/pages/cooperativeOffice/collaborativeApproval/detail.vue
+++ b/src/pages/cooperativeOffice/collaborativeApproval/detail.vue
@@ -1,359 +1,383 @@
<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-field
- v-model="taxPrice"
- name="taxPrice"
- 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"
- :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-cell-group>
- </van-form>
- </view>
+ <u-form ref="formRef" @submit="submitForm" :rules="rules" :model="form" label-width="140rpx">
+ <u-form-item prop="approveReason" label="鐢宠浜嬬敱" required>
+ <u-input
+ v-model="form.approveReason"
+ type="textarea"
+ rows="2"
+ auto-height
+ maxlength="200"
+ placeholder="璇疯緭鍏ョ敵璇蜂簨鐢�"
+ show-word-limit
+ />
+ </u-form-item>
+ <u-form-item prop="approveDeptName" label="鐢宠閮ㄩ棬" required>
+ <u-input
+ v-model="form.approveDeptName"
+ readonly
+ placeholder="璇烽�夋嫨鐢宠閮ㄩ棬"
+ @click="showPicker = true"
+ />
+ <template #right>
+ <up-icon
+ name="arrow-right"
+ @click="showPicker = true"
+ ></up-icon>
+ </template>
+ </u-form-item>
+ <u-form-item prop="approveUser" label="鐢宠浜�" required>
+ <u-input
+ v-model="form.approveUserName"
+ placeholder="璇疯緭鍏ョ敵璇蜂汉"
+ readonly
+ />
+ </u-form-item>
+ <u-form-item prop="approveTime" label="鐢宠鏃ユ湡" required>
+ <u-input
+ v-model="form.approveTime"
+ placeholder="璇烽�夋嫨"
+ readonly
+ @click="showDatePicker"
+ />
+ </u-form-item>
+ </u-form>
+
+ <!-- 閫夋嫨鍣ㄥ脊绐� -->
+ <up-action-sheet
+ :show="showPicker"
+ :actions="productOptions"
+ title="閫夋嫨閮ㄩ棬"
+ @select="onConfirm"
+ @close="showPicker = false"
+ />
+
+ <!-- 鏃ユ湡閫夋嫨鍣� -->
+ <u-popup v-model="showDate" mode="bottom">
+ <u-datetime-picker
+ v-model="currentDate"
+ title="閫夋嫨鏃ユ湡"
+ mode="date"
+ @confirm="onDateConfirm"
+ @cancel="showDate = false"
+ />
+ </u-popup>
<!-- 瀹℃牳娴佺▼鍖哄煙 -->
<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">
+ <u-button icon="plus" plain type="primary" style="width: 100%" @click="addApprovalStep">鏂板鑺傜偣</u-button>
</view>
</view>
<!-- 搴曢儴鎸夐挳 -->
<view class="footer-btns">
- <van-button class="cancel-btn" @click="goBack">鍙栨秷</van-button>
- <van-button class="save-btn" @click="submitForm">淇濆瓨</van-button>
+ <u-button class="cancel-btn" @click="goBack">鍙栨秷</u-button>
+ <u-button class="save-btn" @click="submitForm">淇濆瓨</u-button>
</view>
</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 { formatDateToYMD } from '@/utils/ruoyi'
+import {getDept, approveProcessGetInfo, approveProcessAdd, approveProcessUpdate} from "@/api/collaborativeApproval/approvalProcess";
+const showToast = (message) => {
+ uni.showToast({
+ title: message,
+ icon: 'none'
+ })
+}
+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" }],
+ 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 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,
+ name: 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();
+
+ // 浠庢湰鍦板瓨鍌ㄨ幏鍙栧弬鏁�
+ operationType.value = uni.getStorageSync('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 = (item) => {
+ // 璁剧疆閫変腑鐨勯儴闂�
+ form.value.approveDeptName = item.name;
+ // 纭繚璁剧疆鐨勬槸瀛楃涓茬被鍨嬬殑閮ㄩ棬ID
+ form.value.approveDeptId = String(item.value || '');
+ console.log('閮ㄩ棬閫夋嫨鍚庣殑鍊�:', {
+ approveDeptId: form.value.approveDeptId,
+ approveDeptName: form.value.approveDeptName
+ });
+ showPicker.value = false;
+};
+
+const goBack = () => {
+ // 娓呴櫎鏈湴瀛樺偍鐨勬暟鎹�
+ uni.removeStorageSync('operationType');
+ uni.removeStorageSync('invoiceLedgerEditRow');
+ uni.navigateBack();
+};
+
+const submitForm = () => {
+ // 妫�鏌ユ瘡涓鎵规楠ゆ槸鍚﹂兘鏈夊鎵逛汉
+ const hasEmptyStep = approverNodes.value.some(step => !step.nickName);
+ if (hasEmptyStep) {
+ showToast('璇蜂负姣忎釜瀹℃壒姝ラ閫夋嫨瀹℃壒浜�');
+ return;
+ }
+
+ // 鎵嬪姩妫�鏌ュ繀濉瓧娈碉紝闃叉鍥犳暟鎹被鍨嬮棶棰樺鑷寸殑鏍¢獙澶辫触
+ if (!form.value.approveReason || !form.value.approveReason.trim()) {
+ showToast('璇疯緭鍏ョ敵璇蜂簨鐢�');
+ return;
+ }
+
+ if (!form.value.approveDeptId || String(form.value.approveDeptId).trim() === '') {
+ showToast('璇烽�夋嫨鐢宠閮ㄩ棬');
+ return;
+ }
+
+ if (!form.value.approveTime) {
+ showToast('璇烽�夋嫨鐢宠鏃ユ湡');
+ return;
+ }
+
+ formRef.value.validate().then((valid) => {
+ if (valid) {
+ // 琛ㄥ崟鏍¢獙閫氳繃锛屽彲浠ユ彁浜ゆ暟鎹�
+ // 鏀堕泦鎵�鏈夎妭鐐圭殑瀹℃壒浜篿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 && error.errors) {
+ const firstError = error.errors[0];
+ if (firstError) {
+ uni.showToast({
+ title: firstError.message || '琛ㄥ崟鏍¢獙澶辫触锛岃妫�鏌ュ繀濉」',
+ icon: 'none'
+ });
+ return;
+ }
+ }
+ // 鏄剧ず閫氱敤閿欒淇℃伅
+ 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.setStorageSync('stepIndex', stepIndex);
+ uni.navigateTo({
+ url: "/pages/cooperativeOffice/collaborativeApproval/contactSelect"
+ });
+};
+
+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 = (e) => {
+ form.value.approveTime = formatDateToYMD(e.value)
+ currentDate.value = formatDateToYMD(e.value)
+ 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">
-.account-detail {
- min-height: 100vh;
- background: #f8f9fa;
- padding-bottom: 80px;
-}
-
-.header {
- display: flex;
- align-items: center;
- background: #fff;
- padding: 16px 20px;
- border-bottom: 1px solid #f0f0f0;
- position: sticky;
- top: 0;
- z-index: 100;
-}
-
-.title {
- flex: 1;
- text-align: center;
- font-size: 18px;
- font-weight: 600;
- color: #333;
-}
-
-.form-section {
- 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;
-}
+@import '@/static/scss/form-common.scss';
.approval-process {
background: #fff;
@@ -380,156 +404,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