You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

441 lines
16 KiB
Vue

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<template>
<div class="p-2">
<el-card shadow="never" style="margin-top: 0">
<!-- 审批按钮组件 -->
<approvalButton
@submitForm="submitForm"
@approvalVerifyOpen="approvalVerifyOpen"
@handleApprovalRecord="handleApprovalRecord"
:buttonLoading="buttonLoading"
:id="form.bookingId"
:status="form.flowStatus"
:pageType="routeParams.type"
:mode="false"
/>
</el-card>
<el-card shadow="never" style="margin-top: 0">
<el-form ref="flightBookingFormRef" :model="form" :rules="rules" label-width="120px" :disabled="isFormDisabled">
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="机票预订编号" prop="applyCode">
<el-input v-model="form.applyCode" placeholder="请输入机票预订编号" :disabled="true">
<template #append>
<el-button type="primary" @click="generateContractCode" :disabled="isCodeGenerated">生成机票预订编号 </el-button>
</template>
</el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<!-- <el-form-item label="乘机人姓名" prop="passengerName">
<el-input v-model="form.passengerName" placeholder="请输入乘机人姓名" />
</el-form-item> -->
<el-form-item label="乘机人" prop="passengerId">
<el-select v-model="form.passengerId" placeholder="请选择乘机人" filterable>
<el-option v-for="item in userInfoList" :key="item.userId" :label="item.nickName" :value="item.userId" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="出行日期" prop="travelDate">
<el-date-picker clearable v-model="form.travelDate" type="date" value-format="YYYY-MM-DD" placeholder="请选择出行日期">
</el-date-picker>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="出发地点" prop="departureLocation">
<el-input v-model="form.departureLocation" placeholder="请输入出发地点" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="到达地点" prop="arrivalLocation">
<el-input v-model="form.arrivalLocation" placeholder="请输入到达地点" />
</el-form-item>
</el-col>
<el-col :span="12">
<!-- <el-form-item label="机票折扣" prop="flightDiscount">
<el-input v-model="form.flightDiscount" placeholder="请输入机票折扣" />
</el-form-item> -->
<el-form-item label="机票折扣" prop="flightDiscount">
<el-select v-model="form.flightDiscount" placeholder="请选择机票折扣">
<el-option v-for="dict in flight_discount" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="机票金额" prop="flightAmount">
<el-input v-model="form.flightAmount" placeholder="请输入机票金额" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="备注" prop="remark">
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="附件" prop="ossId">
<FileUpload
v-model="ossIdString"
:limit="5"
:fileSize="20"
:fileType="['jpg', 'jpeg', 'png', 'pdf', 'doc', 'docx', 'xls', 'xlsx']"
:isShowTip="true"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="乘机人ID" prop="passengerId" v-show="false">
<el-input v-model="form.passengerId" placeholder="请输入乘机人ID" />
</el-form-item>
<el-form-item label="机票ID" prop="bookingId" v-show="false">
<el-input v-model="form.bookingId" placeholder="请输入机票ID" />
</el-form-item>
</el-col>
</el-row>
</el-form>
</el-card>
<!-- 提交审批组件 -->
<submitVerify ref="submitVerifyRef" :task-variables="taskVariables" @submit-callback="submitCallback" />
<!-- 审批记录 -->
<approvalRecord ref="approvalRecordRef" />
</div>
</template>
<script setup name="flightBooking" lang="ts">
import { getRuleGenerateCode } from '@/api/system/codeRule';
import { startWorkFlow } from '@/api/workflow/task';
import { StartProcessBo } from '@/api/workflow/workflowCommon/types';
import SubmitVerify from '@/components/Process/submitVerify.vue';
import ApprovalRecord from '@/components/Process/approvalRecord.vue';
import ApprovalButton from '@/components/Process/approvalButton.vue';
import { ref } from 'vue';
import { getUserList } from '@/api/system/user';
import { CodeRuleEnum, FlowCodeEnum } from '@/enums/OAEnum';
import { getInfo } from '@/api/login';
import FileUpload from '@/components/FileUpload/index.vue';
import { getFlightBooking, addFlightBooking, updateFlightBooking, submitAndFlowStart } from '@/api/oa/crm/flightBooking';
import { FlightBookingVO, FlightBookingQuery, FlightBookingForm } from '@/api/oa/crm/flightBooking/types';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const route = useRoute();
const router = useRouter();
//
const routeParams = ref<Record<string, any>>({});
const { flight_discount } = toRefs<any>(proxy?.useDict('flight_discount'));
const buttonLoading = ref(false);
// 审批相关组件引用
const submitVerifyRef = ref<InstanceType<typeof SubmitVerify>>();
const approvalRecordRef = ref<InstanceType<typeof ApprovalRecord>>();
// 流程相关数据
const submitFormData = ref<StartProcessBo>({
businessId: '',
flowCode: 'JPYD',
variables: {},
bizExt: {}
});
// 任务变量
const taskVariables = ref<Record<string, any>>({});
const flowInstanceBizExtBo = ref<Record<string, any>>({});
const type = ref(0);
// 添加自定义验证函数
const validateAmount = (rule: any, value: any, callback: any) => {
if (!value) {
callback(new Error('机票金额不能为空'));
return;
}
// 检查是否为数字(包括整数、小数、负数)
const numValue = Number(value);
if (isNaN(numValue)) {
callback(new Error('请输入有效的数字'));
return;
}
// 检查是否为负数(如果需要)
if (numValue < 0) {
callback(new Error('机票金额不能为负数'));
return;
}
// 检查小数位数最多2位小数
const strValue = String(value);
const decimalPart = strValue.split('.')[1];
if (decimalPart && decimalPart.length > 2) {
callback(new Error('最多支持两位小数'));
return;
}
callback();
};
// 机票编号生成状态
const isCodeGenerated = ref(false);
/** 查询用户信息下拉框结构 */
const userInfoList = ref([]);
// 存储当前登录用户信息
const currentUser = ref<any>(null);
// 获取当前登录用户信息
const getCurrentUserInfo = async () => {
try {
const userInfo = await getInfo();
currentUser.value = userInfo.data.user;
return currentUser.value;
} catch (error) {
console.error('获取当前登录用户信息失败:', error);
return null;
}
};
// 查询所有用户列表
const getUserInfoListSelect = async () => {
try {
const res = await getUserList({ pageNum: 1, pageSize: 1000 });
userInfoList.value = res.data;
// 将当前用户添加到用户列表中(如果不在列表中)
if (currentUser.value && currentUser.value.userId) {
const userExists = userInfoList.value.some((user: any) => user.userId === currentUser.value.userId);
if (!userExists) {
// 将当前用户添加到列表开头
userInfoList.value.unshift({
userId: currentUser.value.userId,
nickName: currentUser.value.nickName
// 可以添加其他需要的字段
});
}
}
} catch (error) {
proxy?.$modal.msgError('获取用户列表失败');
}
};
// 初始化用户数据(获取当前用户并查询用户列表)
const initUserData = async () => {
// 1. 先获取当前登录用户
await getCurrentUserInfo();
// 2. 再查询所有用户列表
await getUserInfoListSelect();
// 3. 如果是新增模式,设置当前用户为默认乘机人
const id = routeParams.value.id as string | number;
if (!id && routeParams.value.type !== 'update' && routeParams.value.type !== 'view' && routeParams.value.type !== 'approval') {
// 新增模式,设置当前用户为默认乘机人
if (currentUser.value && currentUser.value.userId) {
form.value.passengerId = currentUser.value.userId;
form.value.passengerName = currentUser.value.nickName;
console.log('已设置当前登录用户为默认乘机人:', currentUser.value.nickName);
}
}
};
// 判断表单是否禁用(查看或审批模式)
const isFormDisabled = computed(() => {
return routeParams.value.type === 'view' || routeParams.value.type === 'approval';
});
// 附件ID字符串转换用于FileUpload组件
const ossIdString = computed({
get() {
const v = form.value.ossId as any;
return v === undefined || v === null ? '' : String(v);
},
set(val: string) {
form.value.ossId = val || (undefined as any);
}
});
const initFormData: FlightBookingForm = {
bookingId: undefined,
applyCode: undefined,
passengerId: undefined,
passengerName: undefined,
travelDate: undefined,
departureLocation: undefined,
arrivalLocation: undefined,
flightDiscount: undefined,
flightAmount: undefined,
ossId: undefined,
bookingStatus: undefined,
flowStatus: undefined,
remark: undefined
};
const data = reactive<PageData<FlightBookingForm, FlightBookingQuery>>({
form: { ...initFormData },
queryParams: {
pageNum: 1,
pageSize: 10,
applyCode: undefined,
passengerId: undefined,
passengerName: undefined,
travelDate: undefined,
departureLocation: undefined,
arrivalLocation: undefined,
flightDiscount: undefined,
flightAmount: undefined,
ossId: undefined,
bookingStatus: undefined,
flowStatus: undefined,
params: {}
},
rules: {
passengerId: [{ required: true, message: '乘机人ID不能为空', trigger: 'blur' }],
applyCode: [{ required: true, message: '机票编码不能为空', trigger: 'blur' }],
travelDate: [{ required: true, message: '出行日期不能为空', trigger: 'blur' }],
departureLocation: [{ required: true, message: '出发地点不能为空', trigger: 'blur' }],
arrivalLocation: [{ required: true, message: '到达地点不能为空', trigger: 'blur' }],
flightDiscount: [{ required: true, message: '机票折扣不能为空', trigger: 'blur' }],
flightAmount: [
{ required: true, message: '机票金额不能为空', trigger: 'blur' },
{ validator: validateAmount, trigger: ['blur', 'change'] } // 添加自定义验证
]
}
});
const { queryParams, form, rules } = toRefs(data);
const flightBookingFormRef = ref<ElFormInstance>();
// 生成机票编号
const generateContractCode = async () => {
if (isCodeGenerated.value) return; // 如果已经生成过,直接返回
try {
const params = { codeRuleCode: CodeRuleEnum.FLIGHT_BOOKING } as any;
const res = await getRuleGenerateCode(params);
form.value.applyCode = res.msg;
isCodeGenerated.value = true; // 标记为已生成
proxy?.$modal.msgSuccess('机票编号生成成功');
} catch (error) {
console.error('生成机票编号失败:', error);
proxy?.$modal.msgError('机票编号生成失败');
}
};
watch(
() => form.value.passengerId, // 监听 passengerId
(newPassengerId) => {
if (newPassengerId && userInfoList.value.length > 0) {
// 在用户列表中查找对应的用户
const selectedUser = userInfoList.value.find((user) => user.userId === newPassengerId);
if (selectedUser) {
// 自动设置 passengerName
form.value.passengerName = selectedUser.nickName;
}
}
},
{ immediate: true } // 立即执行一次,用于编辑模式的数据回显
);
const submitForm = (status: string, mode: boolean) => {
buttonLoading.value = true;
flightBookingFormRef.value?.validate(async (valid: boolean) => {
if (valid) {
try {
// 设置后端发起和不等于草稿状态 直接走流程发起
if (status != 'draft') {
// 后端发起流程模式
form.value.flowCode = FlowCodeEnum.FLIGHT_BOOKING_CODE;
// 流程变量
form.value.variables = {
flightDiscount: form.value.flightDiscount
};
// 流程实例业务扩展字段
form.value.bizExt = {
businessTitle: '机票预订',
businessCode: form.value.applyCode
};
form.value.flowStatus = 'waiting';
form.value.bookingStatus = '2';
const res = await submitAndFlowStart(form.value);
form.value = res.data;
proxy?.$modal.msgSuccess('操作成功');
proxy?.$tab.closePage();
router.go(-1);
} else {
form.value.flowStatus = 'draft';
form.value.bookingStatus = '1';
if (form.value.bookingId) {
await updateFlightBooking(form.value);
} else {
await addFlightBooking(form.value);
}
proxy?.$modal.msgSuccess('暂存成功');
proxy?.$tab.closePage();
router.go(-1);
}
} catch (error) {
// 错误处理
console.error('提交失败:', error);
proxy?.$modal.msgError('操作失败');
} finally {
// 只在验证通过且有请求操作时才设置加载状态为 false
buttonLoading.value = false;
}
} else {
// 验证不通过时,立即恢复按钮状态
buttonLoading.value = false;
proxy?.$modal.msgWarning('s请检查表单填写是否正确');
}
});
};
onMounted(async () => {
nextTick(async () => {
// 初始化用户数据(获取当前用户和用户列表)
proxy?.$modal.loading('正在加载数据,请稍后...');
await initUserData();
routeParams.value = route.query;
const id = routeParams.value.id as string | number;
if (id && (routeParams.value.type === 'update' || routeParams.value.type === 'view' || routeParams.value.type === 'approval')) {
const res = await getFlightBooking(id);
Object.assign(form.value, res.data);
proxy?.$modal.closeLoading();
// 编辑模式:如果已有合同编号,禁用生成按钮
if (form.value.applyCode) {
isCodeGenerated.value = true;
} else {
isCodeGenerated.value = false;
}
} else {
// 新增模式获取登录用户部门ID并自动赋值
// try {
// const userInfoRes = await getInfo();
// if (userInfoRes.data?.user?.deptId && !form.value.contractDeptId) {
// form.value.contractDeptId = userInfoRes.data.user.deptId;
// }
// form.value.contractCategory = routeParams.value.contractCategory as string;
// } catch (error) {
// console.error('获取用户信息失败:', error);
// }
// 新增模式:如果已有机票编号,禁用生成按钮
if (form.value.applyCode) {
isCodeGenerated.value = true;
} else {
// 如果有合同但没有编号,允许生成
isCodeGenerated.value = false;
}
proxy?.$modal.closeLoading();
}
});
});
// 审批记录
const handleApprovalRecord = () => {
approvalRecordRef.value.init(form.value.bookingId);
};
// 提交回调
const submitCallback = async () => {
await proxy.$tab.closePage(route);
router.go(-1);
};
// 审批
const approvalVerifyOpen = async () => {
await submitVerifyRef.value.openDialog(routeParams.value.taskId);
};
</script>