<template>
|
<view class="account-detail">
|
<PageHeader :title="operationType === 'detail' ? '详情' : '审批流程'"
|
@back="goBack" />
|
<!-- 表单区域 -->
|
<u-form ref="formRef"
|
@submit="submitForm"
|
:rules="rules"
|
:model="form"
|
label-width="140rpx">
|
<u-form-item prop="approveReason"
|
label="流程编号">
|
<u-input v-model="form.approveId"
|
disabled
|
placeholder="自动编号" />
|
</u-form-item>
|
<u-form-item prop="approveReason"
|
:label="approveType === 5 ? '采购事由' : '申请事由'"
|
required>
|
<u-input v-model="form.approveReason"
|
type="textarea"
|
rows="2"
|
auto-height
|
maxlength="200"
|
:disabled="isDetailMode"
|
:placeholder="approveType === 5 ? '请输入采购事由' : '请输入申请事由'"
|
show-word-limit />
|
</u-form-item>
|
<u-form-item prop="approveDeptName"
|
label="申请部门"
|
required>
|
<u-input v-model="form.approveDeptName"
|
readonly
|
:disabled="isDetailMode"
|
placeholder="请选择申请部门"
|
@click="isDetailMode || (showPicker = true)" />
|
<template #right>
|
<up-icon name="arrow-right"
|
@click="isDetailMode || (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"
|
readonly
|
placeholder="请选择"
|
@click="showDatePicker" />
|
<template #right>
|
<up-icon name="arrow-right"
|
@click="showDatePicker"></up-icon>
|
</template>
|
</u-form-item> -->
|
<!-- approveType=2 请假相关字段 -->
|
<u-form-item v-if="approveType === 2"
|
prop="startDate"
|
label="开始时间"
|
required>
|
<u-input v-model="form.startDate"
|
readonly
|
:disabled="isDetailMode"
|
placeholder="请假开始时间"
|
@click="showStartDatePicker" />
|
<template #right>
|
<up-icon name="arrow-right"
|
@click="showStartDatePicker"></up-icon>
|
</template>
|
</u-form-item>
|
<u-form-item v-if="approveType === 2"
|
prop="endDate"
|
label="结束时间"
|
required>
|
<u-input v-model="form.endDate"
|
readonly
|
:disabled="isDetailMode"
|
placeholder="请假结束时间"
|
@click="showEndDatePicker" />
|
<template #right>
|
<up-icon name="arrow-right"
|
@click="showEndDatePicker"></up-icon>
|
</template>
|
</u-form-item>
|
<!-- approveType=3 出差相关字段 -->
|
<u-form-item v-if="approveType === 3"
|
prop="startDateTime"
|
label="出差开始时间"
|
required>
|
<u-input v-model="form.startDateTime"
|
readonly
|
:disabled="isDetailMode"
|
placeholder="请选择开始时间"
|
@click="showStartDateTimePicker" />
|
<template #right>
|
<up-icon name="arrow-right"
|
@click="showStartDateTimePicker"></up-icon>
|
</template>
|
</u-form-item>
|
<u-form-item v-if="approveType === 3"
|
prop="endDateTime"
|
label="出差结束时间"
|
required>
|
<u-input v-model="form.endDateTime"
|
readonly
|
:disabled="isDetailMode"
|
placeholder="请选择结束时间"
|
@click="showEndDateTimePicker" />
|
<template #right>
|
<up-icon name="arrow-right"
|
@click="showEndDateTimePicker"></up-icon>
|
</template>
|
</u-form-item>
|
<u-form-item v-if="approveType === 3"
|
prop="location"
|
label="出差地点"
|
required>
|
<u-input v-model="form.location"
|
:disabled="isDetailMode"
|
placeholder="请输入出差地点"
|
clearable />
|
</u-form-item>
|
<!-- approveType=4 报销相关字段 -->
|
<u-form-item v-if="approveType === 4"
|
prop="price"
|
label="报销金额"
|
required>
|
<u-input v-model="form.price"
|
type="number"
|
:disabled="isDetailMode"
|
placeholder="请输入报销金额"
|
clearable />
|
</u-form-item>
|
<!-- 采购/报价/发货审批详情 -->
|
<ApprovalBusinessDetail :approve-type="approveType"
|
:business-no="form.approveReason" />
|
<!-- 审批流程(仅详情模式展示,与 Web 一致) -->
|
<ApproveFlowSteps v-if="isDetailMode"
|
:steps="approvalSteps"
|
show-pending-opinion />
|
<u-form-item v-if="operationType !== 'detail'"
|
label="图片附件"
|
prop="storageBlobDTOS"
|
border-bottom>
|
<CommonUpload v-model="form.storageBlobDTOS" />
|
</u-form-item>
|
</u-form>
|
<!-- 选择器弹窗 -->
|
<view v-if="operationType !== 'detail'">
|
<up-action-sheet :show="showPicker"
|
:actions="productOptions"
|
title="选择部门"
|
@select="onConfirm"
|
@close="showPicker = false" />
|
<!-- 日期选择器 -->
|
<up-popup :show="showDate"
|
mode="bottom"
|
@close="showDate = false">
|
<up-datetime-picker :show="true"
|
v-model="currentDate"
|
@confirm="onDateConfirm"
|
@cancel="showDate = false"
|
mode="date" />
|
</up-popup>
|
<!-- 请假开始时间选择器 -->
|
<up-popup :show="showStartDate"
|
mode="bottom"
|
@close="showStartDate = false">
|
<up-datetime-picker :show="true"
|
v-model="startDateValue"
|
@confirm="onStartDateConfirm"
|
@cancel="showStartDate = false"
|
mode="date" />
|
</up-popup>
|
<!-- 请假结束时间选择器 -->
|
<up-popup :show="showEndDate"
|
mode="bottom"
|
@close="showEndDate = false">
|
<up-datetime-picker :show="true"
|
v-model="endDateValue"
|
@confirm="onEndDateConfirm"
|
@cancel="showEndDate = false"
|
mode="date" />
|
</up-popup>
|
<!-- 出差开始时间选择器 -->
|
<up-popup :show="showStartDateTime"
|
mode="bottom"
|
@close="showStartDateTime = false">
|
<up-datetime-picker :show="true"
|
v-model="startDateTimeValue"
|
@confirm="onStartDateTimeConfirm"
|
@cancel="showStartDateTime = false"
|
mode="datetime" />
|
</up-popup>
|
<!-- 出差结束时间选择器 -->
|
<up-popup :show="showEndDateTime"
|
mode="bottom"
|
@close="showEndDateTime = false">
|
<up-datetime-picker :show="true"
|
v-model="endDateTimeValue"
|
@confirm="onEndDateTimeConfirm"
|
@cancel="showEndDateTime = false"
|
mode="datetime" />
|
</up-popup>
|
</view>
|
<!-- 底部按钮 -->
|
<view class="footer-btns"
|
v-if="operationType !== 'detail'">
|
<u-button class="cancel-btn"
|
@click="goBack">取消</u-button>
|
<u-button class="save-btn"
|
@click="submitForm">保存</u-button>
|
</view>
|
</view>
|
</template>
|
|
<script setup>
|
import { ref, onMounted, onUnmounted, reactive, toRefs, computed } from "vue";
|
import PageHeader from "@/components/PageHeader.vue";
|
import CommonUpload from "@/components/CommonUpload.vue";
|
import ApprovalBusinessDetail from "./_components/ApprovalBusinessDetail.vue";
|
import ApproveFlowSteps from "./_components/ApproveFlowSteps.vue";
|
import { mapApprovalSteps } from "./_utils/approveFlowSteps.js";
|
import useUserStore from "@/store/modules/user";
|
import { formatDateToYMD, parseTime } from "@/utils/ruoyi";
|
import {
|
getDept,
|
approveProcessGetInfo,
|
approveProcessAdd,
|
approveProcessUpdate,
|
approveProcessDetails,
|
} from "@/api/collaborativeApproval/approvalProcess";
|
const showToast = message => {
|
uni.showToast({
|
title: message,
|
icon: "none",
|
});
|
};
|
|
const data = reactive({
|
form: {
|
approveTime: "",
|
approveId: "",
|
approveUser: "",
|
approveUserName: "",
|
approveDeptName: "",
|
approveDeptId: "",
|
approveReason: "",
|
checkResult: "",
|
storageBlobDTOS: [],
|
startDate: "",
|
endDate: "",
|
startDateTime: "",
|
endDateTime: "",
|
location: "",
|
price: "",
|
},
|
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" }],
|
startDate: [
|
{ required: false, message: "请选择开始时间", trigger: "change" },
|
],
|
endDate: [
|
{ required: false, message: "请选择结束时间", trigger: "change" },
|
],
|
startDateTime: [
|
{ required: false, message: "请选择出差开始时间", trigger: "change" },
|
],
|
endDateTime: [
|
{ required: false, message: "请选择出差结束时间", trigger: "change" },
|
],
|
location: [{ required: false, message: "请输入出差地点", trigger: "blur" }],
|
price: [{ required: false, message: "请输入报销金额", trigger: "blur" }],
|
},
|
});
|
const { form, rules } = toRefs(data);
|
const result = ref("");
|
const showPicker = ref(false);
|
const productOptions = ref([]);
|
const operationType = ref("");
|
const isDetailMode = computed(() => operationType.value === "detail");
|
|
/** 审批流程节点(仅详情模式展示) */
|
const approvalSteps = ref([]);
|
|
const loadApprovalSteps = approveIdValue => {
|
if (!approveIdValue) return;
|
approveProcessDetails(approveIdValue)
|
.then(res => {
|
approvalSteps.value = mapApprovalSteps(res?.data);
|
})
|
.catch(() => {
|
approvalSteps.value = [];
|
});
|
};
|
const currentApproveStatus = ref("");
|
const formRef = ref(null);
|
const message = ref("");
|
const showDate = ref(false);
|
const currentDate = ref(Date.now());
|
const showStartDate = ref(false);
|
const startDateValue = ref(Date.now());
|
const showEndDate = ref(false);
|
const endDateValue = ref(Date.now());
|
const showStartDateTime = ref(false);
|
const startDateTimeValue = ref(Date.now());
|
const showEndDateTime = ref(false);
|
const endDateTimeValue = ref(Date.now());
|
const userStore = useUserStore();
|
const approveType = ref(0);
|
|
const getProductOptions = () => {
|
getDept().then(res => {
|
productOptions.value = res.data.map(item => ({
|
value: item.deptId,
|
name: item.deptName,
|
}));
|
});
|
};
|
const getCurrentinfo = () => {
|
userStore.getInfo().then(res => {
|
form.value.approveDeptId = res.user.tenantId;
|
console.log(res.user.tenantId, "res.user.tenantId");
|
});
|
};
|
|
// 显示日期选择器
|
const showDatePicker = () => {
|
if (isDetailMode.value) return;
|
showDate.value = true;
|
};
|
|
// 确认日期选择
|
const onDateConfirm = e => {
|
form.value.approveTime = formatDateToYMD(e.value);
|
currentDate.value = formatDateToYMD(e.value);
|
showDate.value = false;
|
};
|
|
// 显示请假开始时间选择器
|
const showStartDatePicker = () => {
|
if (isDetailMode.value) return;
|
showStartDate.value = true;
|
};
|
|
// 确认请假开始时间选择
|
const onStartDateConfirm = e => {
|
form.value.startDate = formatDateToYMD(e.value);
|
showStartDate.value = false;
|
};
|
|
const showEndDatePicker = () => {
|
if (isDetailMode.value) return;
|
showEndDate.value = true;
|
};
|
|
// 确认请假结束时间选择
|
const onEndDateConfirm = e => {
|
form.value.endDate = formatDateToYMD(e.value);
|
showEndDate.value = false;
|
};
|
|
// 显示出差开始时间选择器(YYYY-MM-DD HH:mm,与 Web 一致)
|
const showStartDateTimePicker = () => {
|
if (isDetailMode.value) return;
|
startDateTimeValue.value = parseTime(
|
form.value.startDateTime,
|
"{y}-{m}-{d} {h}:{i}"
|
)
|
? new Date(form.value.startDateTime).getTime()
|
: Date.now();
|
showStartDateTime.value = true;
|
};
|
|
const onStartDateTimeConfirm = e => {
|
form.value.startDateTime = parseTime(e.value, "{y}-{m}-{d} {h}:{i}");
|
showStartDateTime.value = false;
|
};
|
|
// 显示出差结束时间选择器
|
const showEndDateTimePicker = () => {
|
if (isDetailMode.value) return;
|
endDateTimeValue.value = parseTime(
|
form.value.endDateTime,
|
"{y}-{m}-{d} {h}:{i}"
|
)
|
? new Date(form.value.endDateTime).getTime()
|
: Date.now();
|
showEndDateTime.value = true;
|
};
|
|
const onEndDateTimeConfirm = e => {
|
form.value.endDateTime = parseTime(e.value, "{y}-{m}-{d} {h}:{i}");
|
showEndDateTime.value = false;
|
};
|
|
onMounted(async () => {
|
try {
|
getProductOptions();
|
form.value.approveUser = userStore.id;
|
form.value.approveUserName = userStore.nickName;
|
form.value.approveTime = getCurrentDate();
|
getCurrentinfo();
|
// 从本地存储获取参数
|
operationType.value = uni.getStorageSync("operationType") || "add";
|
approveType.value = uni.getStorageSync("approveType") || 0;
|
|
// 如果是编辑模式,从本地存储获取数据
|
if (operationType.value === "edit" || operationType.value === "detail") {
|
const storedData = uni.getStorageSync("invoiceLedgerEditRow");
|
if (storedData) {
|
const row = JSON.parse(storedData);
|
currentApproveStatus.value = row.approveStatus;
|
|
// 详情模式:拉取审批流程节点
|
if (operationType.value === "detail") {
|
loadApprovalSteps(row.approveId);
|
}
|
|
approveProcessGetInfo({ id: row.approveId, approveReason: "1" }).then(
|
res => {
|
form.value = { ...res.data };
|
// 设置图片列表显示
|
const fileData =
|
res.data.storageBlobVOS || res.data.commonFileList || [];
|
if (fileData.length > 0) {
|
form.value.storageBlobDTOS = fileData;
|
}
|
}
|
);
|
}
|
}
|
} catch (error) {
|
console.error("获取数据失败:", error);
|
}
|
});
|
|
onUnmounted(() => {});
|
|
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.removeStorageSync("approveType");
|
uni.navigateBack();
|
};
|
|
const submitForm = () => {
|
// 手动检查必填字段,防止因数据类型问题导致的校验失败
|
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) {
|
// 表单校验通过,可以提交数据
|
form.value.approveType = approveType.value;
|
form.value.approveDeptId = Number(form.value.approveDeptId);
|
|
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",
|
});
|
});
|
};
|
|
// 获取当前日期并格式化为 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">
|
@import "@/static/scss/form-common.scss";
|
.account-detail {
|
background-color: #fff;
|
}
|
.footer-btns {
|
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: 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: 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;
|
}
|
</style>
|