1.项目周报界面完善:表单填写界面以及列表展示中的附件控件修改,新增界面增加开始日期、结束日期。

2.项目周报导出功能完善。
3.机票预订代码导入
dev
lh 2 months ago
parent 7c2af05f01
commit e507dd312b

@ -1,6 +1,6 @@
import request from '@/utils/request'; import request from '@/utils/request';
import { AxiosPromise } from 'axios'; import { AxiosPromise } from 'axios';
import { FlightBookingVO, FlightBookingForm, FlightBookingQuery } from '@/api/oa/flightBooking/types'; import { FlightBookingVO, FlightBookingForm, FlightBookingQuery } from '@/api/oa/crm/flightBooking/types';
/** /**
* *
@ -33,7 +33,7 @@ export const getFlightBooking = (bookingId: string | number): AxiosPromise<Fligh
*/ */
export const addFlightBooking = (data: FlightBookingForm) => { export const addFlightBooking = (data: FlightBookingForm) => {
return request({ return request({
url: '/oa//crm/flightBooking', url: '/oa/crm/flightBooking',
method: 'post', method: 'post',
data: data data: data
}); });
@ -45,7 +45,7 @@ export const addFlightBooking = (data: FlightBookingForm) => {
*/ */
export const updateFlightBooking = (data: FlightBookingForm) => { export const updateFlightBooking = (data: FlightBookingForm) => {
return request({ return request({
url: '/oa//crm/flightBooking', url: '/oa/crm/flightBooking',
method: 'put', method: 'put',
data: data data: data
}); });
@ -57,7 +57,7 @@ export const updateFlightBooking = (data: FlightBookingForm) => {
*/ */
export const delFlightBooking = (bookingId: string | number | Array<string | number>) => { export const delFlightBooking = (bookingId: string | number | Array<string | number>) => {
return request({ return request({
url: '/oa//crm/flightBooking/' + bookingId, url: '/oa/crm/flightBooking/' + bookingId,
method: 'delete' method: 'delete'
}); });
}; };
@ -69,8 +69,19 @@ export const delFlightBooking = (bookingId: string | number | Array<string | num
*/ */
export function getCrmFlightBookingList(query) { export function getCrmFlightBookingList(query) {
return request({ return request({
url: '/oa//crm/flightBooking/getCrmFlightBookingList', url: '/oa/crm/flightBooking/getCrmFlightBookingList',
method: 'get', method: 'get',
params: query params: query
}); });
} }
/**
*
* @param data
*/
export const submitAndFlowStart = (data: any) => {
return request({
url: '/oa/crm/flightBooking/submitAndFlowStart',
method: 'post',
data: data
});
};

@ -323,8 +323,11 @@ export interface extraInfo {
chargeName?: string; chargeName?: string;
deputyName?: string; deputyName?: string;
}
beginDate?: string;
endDate?: string;
}
// 扩展的项目周报明细表单类型(包含流程相关字段) // 扩展的项目周报明细表单类型(包含流程相关字段)
export type ProjectReportDetailFormEx = ProjectReportDetailForm & { export type ProjectReportDetailFormEx = ProjectReportDetailForm & {
flowCode?: string; flowCode?: string;

@ -138,4 +138,8 @@ export enum FlowCodeEnum {
* KEY * KEY
*/ */
CONTRACT_ORDER_KEY = 'htdd', CONTRACT_ORDER_KEY = 'htdd',
/**
* KEY
*/
FLIGHT_BOOKING_CODE = 'JPYD'
} }

@ -1,9 +1,6 @@
<template> <template>
<div class="p-2"> <div class="p-2">
<el-card shadow="never" style="margin-top: 0"> <el-card shadow="never" style="margin-top: 0">
<!-- <template #header>-->
<!-- <div style="text-align: left; font-weight: bold; font-size: 24px">合同{{ form.contractId ? ' - 修改' : ' - 新增' }}</div>-->
<!-- </template>-->
<!-- 审批按钮组件 --> <!-- 审批按钮组件 -->
<approvalButton <approvalButton
@submitForm="submitForm" @submitForm="submitForm"
@ -17,11 +14,11 @@
/> />
</el-card> </el-card>
<el-card shadow="never" style="margin-top: 0"> <el-card shadow="never" style="margin-top: 0">
<el-form ref="flightBookingFormRef" :model="form" :loading="buttonLoading" :rules="rules" label-width="120px"> <el-form ref="flightBookingFormRef" :model="form" :loading="buttonLoading" :rules="rules" label-width="120px" :disabled="isFormDisabled">
<el-row :gutter="20"> <el-row :gutter="20">
<el-col :span="12"> <el-col :span="12">
<el-form-item label="机票预订编号" prop="applyCode"> <el-form-item label="机票预订编号" prop="applyCode">
<el-input v-model="form.applyCode" placeholder="请输入机票预订编号" :disabled="isFormDisabled"> <el-input v-model="form.applyCode" placeholder="请输入机票预订编号">
<template #append> <template #append>
<el-button type="primary" @click="generateContractCode" :disabled="isCodeGenerated">生成机票预订编号 </el-button> <el-button type="primary" @click="generateContractCode" :disabled="isCodeGenerated">生成机票预订编号 </el-button>
</template> </template>
@ -32,9 +29,9 @@
<!-- <el-form-item label="乘机人姓名" prop="passengerName"> <!-- <el-form-item label="乘机人姓名" prop="passengerName">
<el-input v-model="form.passengerName" placeholder="请输入乘机人姓名" /> <el-input v-model="form.passengerName" placeholder="请输入乘机人姓名" />
</el-form-item> --> </el-form-item> -->
<el-form-item label="乘机人姓名" prop="passengerName"> <el-form-item label="乘机人" prop="passengerId">
<el-select v-model="queryParams.passengerName" placeholder="请选择乘机人" filterable> <el-select v-model="form.passengerId" placeholder="请选择乘机人" filterable>
<el-option v-for="item in userInfoList" :key="item.userId" :label="item.nickName" :value="item.nickName" /> <el-option v-for="item in userInfoList" :key="item.userId" :label="item.nickName" :value="item.userId" />
</el-select> </el-select>
</el-form-item> </el-form-item>
</el-col> </el-col>
@ -104,9 +101,7 @@
</div> </div>
</template> </template>
<script setup name="ContractInfoEdit" lang="ts"> <script setup name="flightBooking" lang="ts">
import { addContractInfo, contractSubmitAndFlowStart, getContractInfo, updateContractInfo } from '@/api/oa/erp/contractInfo';
import { ContractInfoForm } from '@/api/oa/erp/contractInfo/types';
import { getRuleGenerateCode } from '@/api/system/codeRule'; import { getRuleGenerateCode } from '@/api/system/codeRule';
import { startWorkFlow } from '@/api/workflow/task'; import { startWorkFlow } from '@/api/workflow/task';
import { StartProcessBo } from '@/api/workflow/workflowCommon/types'; import { StartProcessBo } from '@/api/workflow/workflowCommon/types';
@ -118,7 +113,7 @@ import { getUserList } from '@/api/system/user';
import { CodeRuleEnum, FlowCodeEnum } from '@/enums/OAEnum'; import { CodeRuleEnum, FlowCodeEnum } from '@/enums/OAEnum';
import { getInfo } from '@/api/login'; import { getInfo } from '@/api/login';
import FileUpload from '@/components/FileUpload/index.vue'; import FileUpload from '@/components/FileUpload/index.vue';
import { listFlightBooking, getFlightBooking, delFlightBooking, addFlightBooking, updateFlightBooking } from '@/api/oa/crm/flightBooking'; import { getFlightBooking, delFlightBooking, addFlightBooking, updateFlightBooking, submitAndFlowStart } from '@/api/oa/crm/flightBooking';
import { FlightBookingVO, FlightBookingQuery, FlightBookingForm } from '@/api/oa/crm/flightBooking/types'; import { FlightBookingVO, FlightBookingQuery, FlightBookingForm } from '@/api/oa/crm/flightBooking/types';
const { proxy } = getCurrentInstance() as ComponentInternalInstance; const { proxy } = getCurrentInstance() as ComponentInternalInstance;
@ -208,8 +203,8 @@ const data = reactive<PageData<FlightBookingForm, FlightBookingQuery>>({
params: {} params: {}
}, },
rules: { rules: {
bookingId: [{ required: true, message: '机票预订ID不能为空', trigger: 'blur' }],
passengerId: [{ required: true, message: '乘机人ID不能为空', trigger: 'blur' }], passengerId: [{ required: true, message: '乘机人ID不能为空', trigger: 'blur' }],
applyCode: [{ required: true, message: '机票编码不能为空', trigger: 'blur' }],
travelDate: [{ required: true, message: '出行日期不能为空', trigger: 'blur' }], travelDate: [{ required: true, message: '出行日期不能为空', trigger: 'blur' }],
departureLocation: [{ required: true, message: '出发地点不能为空', trigger: 'blur' }], departureLocation: [{ required: true, message: '出发地点不能为空', trigger: 'blur' }],
arrivalLocation: [{ required: true, message: '到达地点不能为空', trigger: 'blur' }], arrivalLocation: [{ required: true, message: '到达地点不能为空', trigger: 'blur' }],
@ -225,17 +220,33 @@ const flightBookingFormRef = ref<ElFormInstance>();
const generateContractCode = async () => { const generateContractCode = async () => {
if (isCodeGenerated.value) return; // if (isCodeGenerated.value) return; //
try { try {
const params = { codeRuleCode: CodeRuleEnum.CONTRACT } as any; const params = { codeRuleCode: 1016 } as any;
const res = await getRuleGenerateCode(params); const res = await getRuleGenerateCode(params);
form.value.applyCode = res.msg; form.value.applyCode = res.msg;
isCodeGenerated.value = true; // isCodeGenerated.value = true; //
proxy?.$modal.msgSuccess('合同编号生成成功'); proxy?.$modal.msgSuccess('机票编号生成成功');
} catch (error) { } catch (error) {
console.error('生成合同编号失败:', error); console.error('生成机票编号失败:', error);
proxy?.$modal.msgError('生成合同编号失败'); 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;
}
} else {
// passengerId passengerName
form.value.passengerName = '';
}
},
{ immediate: true } //
);
/** 提交按钮 */ /** 提交按钮 */
const submitForm = (status: string, mode: boolean) => { const submitForm = (status: string, mode: boolean) => {
try { try {
@ -248,33 +259,30 @@ const submitForm = (status: string, mode: boolean) => {
form.value.flowCode = FlowCodeEnum.FLIGHT_BOOKING_CODE; form.value.flowCode = FlowCodeEnum.FLIGHT_BOOKING_CODE;
// //
form.value.variables = { form.value.variables = {
contractName: form.value.contractName, flightDiscount: form.value.flightDiscount
totalPrice: form.value.totalPrice,
businessDirection: form.value.businessDirection,
contractCode: form.value.contractCode
}; };
// //
form.value.bizExt = { form.value.bizExt = {
businessTitle: '合同审批', businessTitle: '机票预订',
businessCode: form.value.contractCode businessCode: form.value.applyCode
}; };
form.value.contractStatus = '2';
form.value.flowStatus = 'waiting'; form.value.flowStatus = 'waiting';
const res = await contractSubmitAndFlowStart(form.value).finally(() => (buttonLoading.value = false)); form.value.bookingStatus = '2';
const res = await submitAndFlowStart(form.value).finally(() => (buttonLoading.value = false));
form.value = res.data; form.value = res.data;
proxy?.$modal.msgSuccess('操作成功'); proxy?.$modal.msgSuccess('操作成功');
proxy?.$tab.closePage(); proxy?.$tab.closePage();
router.go(-1); router.go(-1);
} else { } else {
if (status === 'draft') { form.value.flowStatus = 'draft';
form.value.contractStatus = '1'; form.value.bookingStatus = '1';
form.value.flowStatus = 'draft';
} if (form.value.bookingId) {
if (form.value.contractId) { await updateFlightBooking(form.value).finally(() => (buttonLoading.value = false));
await updateContractInfo(form.value).finally(() => (buttonLoading.value = false));
} else { } else {
await addContractInfo(form.value).finally(() => (buttonLoading.value = false)); await addFlightBooking(form.value).finally(() => (buttonLoading.value = false));
} }
proxy?.$modal.msgSuccess('暂存成功'); proxy?.$modal.msgSuccess('暂存成功');
proxy?.$tab.closePage(); proxy?.$tab.closePage();
router.go(-1); router.go(-1);
@ -286,42 +294,6 @@ const submitForm = (status: string, mode: boolean) => {
} }
}; };
//
const handleStartWorkFlow = async (data: ContractInfoForm) => {
try {
submitFormData.value.flowCode = 'OAC';
submitFormData.value.businessId = data.contractId;
//
taskVariables.value = {
contractId: data.contractId,
contractName: data.contractName,
totalPrice: data.totalPrice,
businessDirection: data.businessDirection,
contractCode: data.contractCode
};
//
flowInstanceBizExtBo.value = {
businessTitle: '合同审批',
businessCode: data.contractCode
};
submitFormData.value.variables = taskVariables.value;
submitFormData.value.bizExt = flowInstanceBizExtBo.value;
const resp = await startWorkFlow(submitFormData.value);
if (submitVerifyRef.value) {
buttonLoading.value = false;
await submitVerifyRef.value.openDialog(resp.data.taskId);
}
} finally {
buttonLoading.value = false;
router.go(-1);
}
};
onMounted(async () => { onMounted(async () => {
nextTick(async () => { nextTick(async () => {
// //
@ -330,36 +302,34 @@ onMounted(async () => {
const id = routeParams.value.id as string | number; const id = routeParams.value.id as string | number;
if (id && (routeParams.value.type === 'update' || routeParams.value.type === 'view' || routeParams.value.type === 'approval')) { if (id && (routeParams.value.type === 'update' || routeParams.value.type === 'view' || routeParams.value.type === 'approval')) {
proxy?.$modal.loading('正在加载数据,请稍后...'); proxy?.$modal.loading('正在加载数据,请稍后...');
const res = await getContractInfo(id); const res = await getFlightBooking(id);
Object.assign(form.value, res.data); Object.assign(form.value, res.data);
proxy?.$modal.closeLoading(); proxy?.$modal.closeLoading();
// //
if (form.value.contractCode) { if (form.value.applyCode) {
isCodeGenerated.value = true; isCodeGenerated.value = true;
} else if (form.value.contractFlag === '1') { } else {
//
isCodeGenerated.value = false; isCodeGenerated.value = false;
} }
} else { } else {
// ID // ID
try { // try {
const userInfoRes = await getInfo(); // const userInfoRes = await getInfo();
if (userInfoRes.data?.user?.deptId && !form.value.contractDeptId) { // if (userInfoRes.data?.user?.deptId && !form.value.contractDeptId) {
form.value.contractDeptId = userInfoRes.data.user.deptId; // form.value.contractDeptId = userInfoRes.data.user.deptId;
} // }
form.value.contractCategory = routeParams.value.contractCategory as string; // form.value.contractCategory = routeParams.value.contractCategory as string;
} catch (error) { // } catch (error) {
console.error('获取用户信息失败:', error); // console.error(':', error);
} // }
// //
// // if (form.value.contractCode) {
if (form.value.contractCode) { // isCodeGenerated.value = true;``
isCodeGenerated.value = true; // } else if (form.value.contractFlag === '1') {
} else if (form.value.contractFlag === '1') { // //
// // isCodeGenerated.value = false;
isCodeGenerated.value = false; // }
}
} }
}); });
}); });

@ -48,11 +48,11 @@
<el-col :span="1.5"> <el-col :span="1.5">
<el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['oa/crm:flightBooking:add']"></el-button> <el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['oa/crm:flightBooking:add']"></el-button>
</el-col> </el-col>
<el-col :span="1.5"> <!-- <el-col :span="1.5">
<el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['oa/crm:flightBooking:edit']" <el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['oa/crm:flightBooking:edit']"
>修改</el-button >修改</el-button
> >
</el-col> </el-col> -->
<el-col :span="1.5"> <el-col :span="1.5">
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['oa/crm:flightBooking:remove']" <el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['oa/crm:flightBooking:remove']"
>删除</el-button >删除</el-button
@ -78,24 +78,32 @@
</el-table-column> </el-table-column>
<el-table-column label="出发地点" align="center" prop="departureLocation" v-if="columns[6].visible" /> <el-table-column label="出发地点" align="center" prop="departureLocation" v-if="columns[6].visible" />
<el-table-column label="到达地点" align="center" prop="arrivalLocation" v-if="columns[7].visible" /> <el-table-column label="到达地点" align="center" prop="arrivalLocation" v-if="columns[7].visible" />
<!-- <el-table-column label="机票折扣" align="center" prop="flightDiscount" v-if="columns[8].visible" /> -->
<el-table-column label="机票折扣" align="center" prop="flightDiscount" v-if="columns[8].visible"> <el-table-column label="机票折扣" align="center" prop="flightDiscount" v-if="columns[8].visible">
<template #default="scope"> <template #default="scope">
<dict-tag :options="flight_discount" :value="scope.row.flightDiscount" /> <dict-tag :options="flight_discount" :value="scope.row.flightDiscount" />
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="机票金额" align="center" prop="flightAmount" v-if="columns[9].visible" /> <el-table-column label="机票金额" align="center" prop="flightAmount" v-if="columns[9].visible" />
<el-table-column label="附件ID" align="center" prop="ossId" v-if="columns[10].visible" /> <el-table-column label="附件ID" align="center" prop="ossId" width="100" v-if="columns[10].visible">
<el-table-column label="申请状态" align="center" prop="bookingStatus" v-if="columns[11].visible" /> <template #default="scope">
<el-button v-if="scope.row.ossId" link type="primary" icon="Download" @click="downloadOss(scope.row.ossId)"> </el-button>
<span v-else style="color: #999">未上传</span>
</template>
</el-table-column>
<el-table-column label="申请状态" align="center" prop="bookingStatus" v-if="columns[11].visible">
<template #default="scope">
<dict-tag :options="booking_status" :value="scope.row.bookingStatus" />
</template>
</el-table-column>
<el-table-column label="流程状态" align="center" prop="flowStatus" v-if="columns[12].visible" /> <el-table-column label="流程状态" align="center" prop="flowStatus" v-if="columns[12].visible" />
<el-table-column label="备注" align="center" prop="remark" v-if="columns[13].visible" /> <el-table-column label="备注" align="center" prop="remark" v-if="columns[13].visible" />
<el-table-column label="操作" align="center" fixed="right" class-name="small-padding fixed-width"> <el-table-column label="操作" align="center" fixed="right" class-name="small-padding fixed-width">
<template #default="scope"> <template #default="scope">
<el-tooltip content="修改" placement="top"> <el-tooltip content="查看详情" placement="top" v-if="scope.row.flowStatus !== 'draft'">
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['oa:flightBooking:edit']"></el-button> <el-button link type="info" icon="DocumentChecked" @click="handleView(scope.row)"></el-button>
</el-tooltip> </el-tooltip>
<el-tooltip content="删除" placement="top"> <el-tooltip content="修改" placement="top" v-if="scope.row.flowStatus === 'draft' || scope.row.flowStatus === 'back'">
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['oa:flightBooking:remove']"></el-button> <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['oa/crm:flightBooking:edit']"></el-button>
</el-tooltip> </el-tooltip>
</template> </template>
</el-table-column> </el-table-column>
@ -165,11 +173,13 @@ import { listFlightBooking, getFlightBooking, delFlightBooking, addFlightBooking
import { FlightBookingVO, FlightBookingQuery, FlightBookingForm } from '@/api/oa/crm/flightBooking/types'; import { FlightBookingVO, FlightBookingQuery, FlightBookingForm } from '@/api/oa/crm/flightBooking/types';
import FileUpload from '@/components/FileUpload/index.vue'; import FileUpload from '@/components/FileUpload/index.vue';
import { getUserList } from '@/api/system/user'; import { getUserList } from '@/api/system/user';
import download from '@/plugins/download';
import ApprovalRecord from '@/components/Process/approvalRecord.vue';
const { proxy } = getCurrentInstance() as ComponentInternalInstance; const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const route = useRoute(); const route = useRoute();
const router = useRouter(); const router = useRouter();
const { flight_discount } = toRefs<any>(proxy?.useDict('flight_discount')); const { flight_discount, booking_status } = toRefs<any>(proxy?.useDict('flight_discount', 'booking_status'));
const flightBookingList = ref<FlightBookingVO[]>([]); const flightBookingList = ref<FlightBookingVO[]>([]);
const buttonLoading = ref(false); const buttonLoading = ref(false);
@ -267,7 +277,10 @@ const ossIdString = computed({
form.value.ossId = val || (undefined as any); form.value.ossId = val || (undefined as any);
} }
}); });
//
const downloadOss = (ossId: string | number) => {
download.oss(ossId);
};
/** 查询用户信息下拉框结构 */ /** 查询用户信息下拉框结构 */
const userInfoList = ref([]); const userInfoList = ref([]);
const getUserInfoListSelect = async () => { const getUserInfoListSelect = async () => {
@ -314,12 +327,6 @@ const handleSelectionChange = (selection: FlightBookingVO[]) => {
multiple.value = !selection.length; multiple.value = !selection.length;
}; };
// /** */
// const handleAdd = () => {
// reset();
// dialog.visible = true;
// dialog.title = '';
// };
/** 新增按钮操作 */ /** 新增按钮操作 */
const handleAdd = () => { const handleAdd = () => {
proxy.$tab.closePage(route); proxy.$tab.closePage(route);
@ -330,15 +337,37 @@ const handleAdd = () => {
} }
}); });
}; };
/** 查看按钮操作 */
const handleView = (row?: FlightBookingVO) => {
const _bookingId = row?.bookingId || ids.value[0];
proxy.$tab.closePage(route);
router.push({
path: '/crm/flightBooking/edit',
query: {
id: _bookingId,
type: 'view'
}
});
};
/** 修改按钮操作 */ /** 修改按钮操作 */
const handleUpdate = async (row?: FlightBookingVO) => { const handleUpdate = async (row?: FlightBookingVO) => {
reset();
const _bookingId = row?.bookingId || ids.value[0]; const _bookingId = row?.bookingId || ids.value[0];
const res = await getFlightBooking(_bookingId); proxy.$tab.closePage(route);
Object.assign(form.value, res.data); router.push({
dialog.visible = true; path: '/crm/flightBooking/edit',
dialog.title = '修改机票预订'; query: {
id: _bookingId,
type: 'update'
}
});
};
const approvalRecordRef = ref<InstanceType<typeof ApprovalRecord>>();
//
const handleApprovalRecord = (row?: FlightBookingVO) => {
if (row) {
approvalRecordRef.value.init(row?.bookingId);
}
}; };
/** 提交按钮 */ /** 提交按钮 */

@ -180,6 +180,16 @@
<span>{{ parseTime(scope.row.fillTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</span> <span>{{ parseTime(scope.row.fillTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="开始时间" align="center" prop="beginDate" width="180" v-if="columns[23].visible">
<template #default="scope">
<span>{{ parseTime(scope.row.beginDate, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="结束时间" align="center" prop="endDate" width="180" v-if="columns[24].visible">
<template #default="scope">
<span>{{ parseTime(scope.row.endDate, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="所在的工作周" align="center" prop="currentWorkWeek" width="100" v-if="columns[4].visible" /> <el-table-column label="所在的工作周" align="center" prop="currentWorkWeek" width="100" v-if="columns[4].visible" />
<el-table-column label="所属里程碑" align="center" prop="milestonePlan" width="100" v-if="columns[5].visible" /> <el-table-column label="所属里程碑" align="center" prop="milestonePlan" width="100" v-if="columns[5].visible" />
<el-table-column label="二级进度阶段" align="center" prop="secondaryPhase" width="100" v-if="columns[6].visible" /> <el-table-column label="二级进度阶段" align="center" prop="secondaryPhase" width="100" v-if="columns[6].visible" />
@ -255,20 +265,30 @@
<el-form-item label="填写日期" prop="fillTime"> <el-form-item label="填写日期" prop="fillTime">
<el-date-picker <el-date-picker
clearable clearable
v-model="datePart" v-model="projectReportForm.fillTime"
type="date" type="datetime"
format="YYYY-MM-DD" value-format="YYYY-MM-DD HH:mm:ss"
value-format="YYYY-MM-DD"
placeholder="请选择填写日期" placeholder="请选择填写日期"
@change="handleDateChange" :disabled="true"
/> />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <!-- <el-col :span="12">
<el-form-item label="所在的工作周" prop="currentWorkWeek"> <el-form-item label="所在的工作周" prop="currentWorkWeek">
<el-input v-model="projectReportForm.currentWorkWeek" placeholder="请输入所在的工作周" clearable /> <el-input v-model="projectReportForm.currentWorkWeek" placeholder="请输入所在的工作周" clearable />
</el-form-item> </el-form-item>
</el-col> </el-col> -->
<el-form-item label="起始时间">
<el-date-picker
v-model="dateRange"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
range-separator="-"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="[new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 1, 1, 23, 59, 59)]"
></el-date-picker>
</el-form-item>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="所属里程碑" prop="milestonePlan"> <el-form-item label="所属里程碑" prop="milestonePlan">
<el-input v-model="projectReportForm.milestonePlan" placeholder="请输入所属里程碑" clearable /> <el-input v-model="projectReportForm.milestonePlan" placeholder="请输入所属里程碑" clearable />
@ -569,13 +589,13 @@ import {
ProjectReportDetailFormEx ProjectReportDetailFormEx
} from '@/api/oa/erp/projectReportDetail/types'; } from '@/api/oa/erp/projectReportDetail/types';
import ProjectSelect from '@/components/ProjectSelect/index.vue'; import ProjectSelect from '@/components/ProjectSelect/index.vue';
// FileUpload
import FileUpload from '@/components/FileUpload/index.vue'; import FileUpload from '@/components/FileUpload/index.vue';
import download from '@/plugins/download'; import download from '@/plugins/download';
const { proxy } = getCurrentInstance() as ComponentInternalInstance; const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const route = useRoute(); const route = useRoute();
const router = useRouter(); const router = useRouter();
const dateRange = ref<[DateModelType, DateModelType]>(['', '']);
const modifiedPageType = computed(() => { const modifiedPageType = computed(() => {
// pageType 'view' // pageType 'view'
if (routeParams.value.type === 'add' && projectReportForm.value.flowStatus === 'waiting') { if (routeParams.value.type === 'add' && projectReportForm.value.flowStatus === 'waiting') {
@ -733,7 +753,9 @@ const initProjectReportFormData: ProjectReportDetailFormEx = {
bizExt: undefined, bizExt: undefined,
variables: undefined, variables: undefined,
createTime: undefined, createTime: undefined,
updateTime: undefined updateTime: undefined,
beginDate: undefined,
endDate: undefined
} as any; } as any;
const projectReportForm = ref<ProjectReportDetailFormEx>({ ...initProjectReportFormData }); const projectReportForm = ref<ProjectReportDetailFormEx>({ ...initProjectReportFormData });
// //
@ -798,7 +820,9 @@ const initProjectReportDetailFormData: ProjectReportDetailForm = {
contractId: undefined, contractId: undefined,
ossId: undefined, ossId: undefined,
remark: undefined, remark: undefined,
activeFlag: undefined activeFlag: undefined,
beginDate: undefined,
endDate: undefined
}; };
const projectReportDetailData = reactive<PageData<ProjectReportDetailForm, ProjectReportDetailQuery>>({ const projectReportDetailData = reactive<PageData<ProjectReportDetailForm, ProjectReportDetailQuery>>({
form: { ...initProjectReportDetailFormData }, form: { ...initProjectReportDetailFormData },
@ -824,6 +848,8 @@ const projectReportDetailData = reactive<PageData<ProjectReportDetailForm, Proje
contractId: undefined, contractId: undefined,
ossId: undefined, ossId: undefined,
activeFlag: undefined, activeFlag: undefined,
beginDate: undefined,
endDate: undefined,
params: {} params: {}
}, },
rules: { rules: {
@ -975,7 +1001,7 @@ const columns = ref<FieldOption[]>([
{ key: 1, label: `项目周报ID`, visible: false }, { key: 1, label: `项目周报ID`, visible: false },
{ key: 2, label: `项目ID`, visible: false }, { key: 2, label: `项目ID`, visible: false },
{ key: 3, label: `填写日期`, visible: true }, { key: 3, label: `填写日期`, visible: true },
{ key: 4, label: `所在的工作周`, visible: true }, { key: 4, label: `所在的工作周`, visible: false },
{ key: 5, label: `所属里程碑`, visible: true }, { key: 5, label: `所属里程碑`, visible: true },
{ key: 6, label: `二级进度阶段`, visible: true }, { key: 6, label: `二级进度阶段`, visible: true },
{ key: 7, label: `本周完成工作`, visible: true }, { key: 7, label: `本周完成工作`, visible: true },
@ -993,11 +1019,11 @@ const columns = ref<FieldOption[]>([
{ key: 19, label: `备注`, visible: false }, { key: 19, label: `备注`, visible: false },
{ key: 20, label: `激活标识`, visible: false }, { key: 20, label: `激活标识`, visible: false },
{ key: 21, label: `创建时间`, visible: true }, { key: 21, label: `创建时间`, visible: true },
{ key: 22, label: `更新时间`, visible: true } { key: 22, label: `更新时间`, visible: true },
// { key: 21, label: ``, visible: true }, // { key: 21, label: ``, visible: true },
// { key: 22, label: ``, visible: true }, // { key: 22, label: ``, visible: true },
// { key: 23, label: ``, visible: true }, { key: 23, label: `开始时间`, visible: true },
// { key: 24, label: ``, visible: true }, { key: 24, label: `结束时间`, visible: true }
// { key: 25, label: ``, visible: true }, // { key: 25, label: ``, visible: true },
// { key: 26, label: ``, visible: true } // { key: 26, label: ``, visible: true }
]); ]);
@ -1126,185 +1152,6 @@ const submitProjectReportForm = () => {
} }
}); });
}; };
//
const datePart = ref(''); // YYYY-MM-DD
//
const formatDateTime = (dateStr?: string, includeTime: boolean = true): string => {
if (!dateStr) {
const now = new Date();
const year = now.getFullYear();
const month = String(now.getMonth() + 1).padStart(2, '0');
const day = String(now.getDate()).padStart(2, '0');
if (includeTime) {
const hours = String(now.getHours()).padStart(2, '0');
const minutes = String(now.getMinutes()).padStart(2, '0');
const seconds = String(now.getSeconds()).padStart(2, '0');
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
}
return `${year}-${month}-${day}`;
}
//
if (dateStr.includes(' ')) {
return dateStr;
}
//
if (includeTime) {
const now = new Date();
const hours = String(now.getHours()).padStart(2, '0');
const minutes = String(now.getMinutes()).padStart(2, '0');
const seconds = String(now.getSeconds()).padStart(2, '0');
return `${dateStr} ${hours}:${minutes}:${seconds}`;
}
return dateStr;
};
//
const parseDatePart = (dateTimeStr?: string): string => {
if (!dateTimeStr) return '';
const [date] = dateTimeStr.split(' ');
return date || '';
};
// -
const getWorkWeek = (dateString: string): string => {
if (!dateString) return '';
try {
//
const [datePart] = dateString.split(' ');
const date = new Date(datePart);
if (isNaN(date.getTime())) {
console.warn('无效的日期格式:', dateString);
return '';
}
const year = date.getFullYear();
const firstDayOfYear = new Date(year, 0, 1);
// 使
const timeDiff = date.getTime() - firstDayOfYear.getTime();
const days = Math.floor(timeDiff / (24 * 60 * 60 * 1000)) + 1;
//
const firstDayWeek = firstDayOfYear.getDay();
const isoFirstDayWeek = firstDayWeek === 0 ? 7 : firstDayWeek;
const weekNumber = Math.ceil((days + isoFirstDayWeek - 1) / 7);
// 0-1-...6-
const weekday = date.getDay();
const weekdays = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'];
return `${weekdays[weekday]}`;
} catch (error) {
console.error('计算工作周失败:', error);
return '';
}
};
//
const initDefaultDate = () => {
if (routeParams.value.type === 'add') {
// fillTime
if (!projectReportForm.value.fillTime) {
projectReportForm.value.fillTime = formatDateTime();
} else {
// fillTime
projectReportForm.value.fillTime = formatDateTime(projectReportForm.value.fillTime, true);
}
// fillTime datePart
datePart.value = parseDatePart(projectReportForm.value.fillTime);
//
if (datePart.value) {
projectReportForm.value.currentWorkWeek = getWorkWeek(datePart.value);
}
}
};
// -
const handleDateChange = (selectedDate: string) => {
if (selectedDate) {
// fillTime 使
let timeStr = '00:00:00'; //
if (projectReportForm.value.fillTime && projectReportForm.value.fillTime.includes(' ')) {
const [, existingTime] = projectReportForm.value.fillTime.split(' ');
if (existingTime) {
timeStr = existingTime;
} else {
const now = new Date();
const hours = String(now.getHours()).padStart(2, '0');
const minutes = String(now.getMinutes()).padStart(2, '0');
const seconds = String(now.getSeconds()).padStart(2, '0');
timeStr = `${hours}:${minutes}:${seconds}`;
}
} else {
const now = new Date();
const hours = String(now.getHours()).padStart(2, '0');
const minutes = String(now.getMinutes()).padStart(2, '0');
const seconds = String(now.getSeconds()).padStart(2, '0');
timeStr = `${hours}:${minutes}:${seconds}`;
}
//
projectReportForm.value.fillTime = `${selectedDate} ${timeStr}`;
//
projectReportForm.value.currentWorkWeek = getWorkWeek(selectedDate);
} else {
//
projectReportForm.value.fillTime = '';
projectReportForm.value.currentWorkWeek = '';
}
};
//
const modifyDatePart = ref('');
//
const handleModifyDateChange = (selectedDate: string) => {
if (selectedDate) {
// fillTime
let timeStr = '00:00:00'; //
if (detailForm.value.fillTime && detailForm.value.fillTime.includes(' ')) {
const [, existingTime] = detailForm.value.fillTime.split(' ');
if (existingTime) {
timeStr = existingTime;
} else {
const now = new Date();
const hours = String(now.getHours()).padStart(2, '0');
const minutes = String(now.getMinutes()).padStart(2, '0');
const seconds = String(now.getSeconds()).padStart(2, '0');
timeStr = `${hours}:${minutes}:${seconds}`;
}
} else {
const now = new Date();
const hours = String(now.getHours()).padStart(2, '0');
const minutes = String(now.getMinutes()).padStart(2, '0');
const seconds = String(now.getSeconds()).padStart(2, '0');
timeStr = `${hours}:${minutes}:${seconds}`;
}
//
detailForm.value.fillTime = `${selectedDate} ${timeStr}`;
//
detailForm.value.currentWorkWeek = getWorkWeek(selectedDate);
} else {
//
detailForm.value.fillTime = '';
detailForm.value.currentWorkWeek = '';
}
};
// //
const handleApprovalRecord = (row?: ProjectReportDetailVO) => { const handleApprovalRecord = (row?: ProjectReportDetailVO) => {
if (row) { if (row) {
@ -1349,11 +1196,6 @@ const getProjectDetail = async () => {
reportId: form.value.reportId reportId: form.value.reportId
}); });
projectReportDetailList.value = res.rows; projectReportDetailList.value = res.rows;
// fillTime
projectReportDetailList.value = res.rows.map((item) => ({
...item,
fillTime: formatDateTime(item.fillTime, true)
}));
total.value = res.total; total.value = res.total;
loading.value = false; loading.value = false;
}; };
@ -1370,8 +1212,8 @@ const isDetailFormDisabled = computed(() => {
const shouldCheckApprovalData = computed(() => { const shouldCheckApprovalData = computed(() => {
return (routeParams.value.type === 'add' || routeParams.value.type === 'update') && routeParams.value.reportData; return (routeParams.value.type === 'add' || routeParams.value.type === 'update') && routeParams.value.reportData;
}); });
// //
// checkApprovalData
const checkApprovalData = async () => { const checkApprovalData = async () => {
try { try {
if (!shouldCheckApprovalData.value) return; if (!shouldCheckApprovalData.value) return;
@ -1396,14 +1238,12 @@ const checkApprovalData = async () => {
const approvalData = res.rows[0]; const approvalData = res.rows[0];
Object.assign(projectReportForm.value, approvalData); Object.assign(projectReportForm.value, approvalData);
// fillTime
projectReportForm.value.fillTime = formatDateTime(approvalData.fillTime, true);
//
datePart.value = parseDatePart(projectReportForm.value.fillTime);
// flowStatus 'waiting' // flowStatus 'waiting'
projectReportForm.value.flowStatus = 'waiting'; projectReportForm.value.flowStatus = 'waiting';
//
if (approvalData.beginDate && approvalData.endDate) {
dateRange.value = [approvalData.beginDate, approvalData.endDate];
}
} else { } else {
hasApprovalData.value = false; hasApprovalData.value = false;
} }
@ -1433,6 +1273,15 @@ watch(
const submitForm = async (status: string, mode: boolean) => { const submitForm = async (status: string, mode: boolean) => {
try { try {
buttonLoading.value = true; buttonLoading.value = true;
//
if (dateRange.value && dateRange.value.length === 2) {
// beginDate endDate
projectReportForm.value.beginDate = String(dateRange.value[0]);
projectReportForm.value.endDate = String(dateRange.value[1]);
} else if (projectReportForm.value.beginDate && projectReportForm.value.endDate) {
// beginDate endDate dateRange
dateRange.value = [projectReportForm.value.beginDate, projectReportForm.value.endDate];
}
// //
let formValid = false; let formValid = false;
let detailFormValid = false; let detailFormValid = false;
@ -1484,11 +1333,9 @@ const submitForm = async (status: string, mode: boolean) => {
businessTitle: '项目周报明细', businessTitle: '项目周报明细',
businessCode: msg businessCode: msg
}; };
form.value.status = '0';
// 使 // 使
projectReportForm.value.projectId = form.value.projectId; projectReportForm.value.projectId = form.value.projectId;
projectReportForm.value.flowStatus = 'waiting'; projectReportForm.value.flowStatus = 'waiting';
// projectReportForm.value.projectPhases = String(form.value.reportId);
const requestData = { const requestData = {
projectReport: form.value, // projectReport: form.value, //
@ -1497,8 +1344,6 @@ const submitForm = async (status: string, mode: boolean) => {
const res = await projectReportSubmitAndFlowStart(requestData).finally(() => (buttonLoading.value = false)); const res = await projectReportSubmitAndFlowStart(requestData).finally(() => (buttonLoading.value = false));
projectReportForm.value = { ...projectReportForm.value, ...res.data }; projectReportForm.value = { ...projectReportForm.value, ...res.data };
// //
// clearDraftCache();
proxy?.$modal.msgSuccess('操作成功'); proxy?.$modal.msgSuccess('操作成功');
proxy?.$tab.closePage(); proxy?.$tab.closePage();
router.go(-1); router.go(-1);
@ -1545,14 +1390,19 @@ onMounted(async () => {
if (routeParams.value.type === 'add') { if (routeParams.value.type === 'add') {
// add // add
initDefaultDate();
if (shouldCheckApprovalData.value) { if (shouldCheckApprovalData.value) {
await checkApprovalData(); await checkApprovalData();
} else { } else {
Object.assign(projectReportForm.value, reportData); Object.assign(projectReportForm.value, reportData);
// //
projectReportForm.value.fillTime = formatDateTime(projectReportForm.value.fillTime, true); const now = new Date();
datePart.value = parseDatePart(projectReportForm.value.fillTime); const year = now.getFullYear();
const month = String(now.getMonth() + 1).padStart(2, '0');
const day = String(now.getDate()).padStart(2, '0');
const hours = String(now.getHours()).padStart(2, '0');
const minutes = String(now.getMinutes()).padStart(2, '0');
const seconds = String(now.getSeconds()).padStart(2, '0');
projectReportForm.value.fillTime = `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
projectReportForm.value.informationNote = undefined; projectReportForm.value.informationNote = undefined;
projectReportForm.value.remark = undefined; projectReportForm.value.remark = undefined;
projectReportForm.value.ossId = undefined; projectReportForm.value.ossId = undefined;
@ -1570,18 +1420,25 @@ onMounted(async () => {
const res = await listProjectReportDetail({ pageNum: 1, pageSize: 10, reportId: reportId }); const res = await listProjectReportDetail({ pageNum: 1, pageSize: 10, reportId: reportId });
if (res.rows && res.rows.length > 0) { if (res.rows && res.rows.length > 0) {
const detailData = res.rows[0]; const detailData = res.rows[0];
//
detailData.fillTime = formatDateTime(detailData.fillTime, true);
Object.assign(projectReportForm.value, detailData); Object.assign(projectReportForm.value, detailData);
datePart.value = parseDatePart(projectReportForm.value.fillTime);
} }
Object.assign(projectReportForm.value, res.rows[0]); // view
if (projectReportForm.value.beginDate && projectReportForm.value.endDate) {
dateRange.value = [projectReportForm.value.beginDate, projectReportForm.value.endDate];
}
} }
proxy?.$modal.closeLoading(); proxy?.$modal.closeLoading();
} else if (routeParams.value.type === 'add') { } else if (routeParams.value.type === 'add') {
// //
initDefaultDate(); const now = new Date();
} else if (routeParams.value.type === 'approval' || routeParams.value.type === 'view') { const year = now.getFullYear();
const month = String(now.getMonth() + 1).padStart(2, '0');
const day = String(now.getDate()).padStart(2, '0');
const hours = String(now.getHours()).padStart(2, '0');
const minutes = String(now.getMinutes()).padStart(2, '0');
const seconds = String(now.getSeconds()).padStart(2, '0');
projectReportForm.value.fillTime = `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
} else if (routeParams.value.type === 'approval' || routeParams.value.type === 'view' || routeParams.value.type === 'update') {
// //
const projectDetailReportId = routeParams.value.id; const projectDetailReportId = routeParams.value.id;
if (projectDetailReportId) { if (projectDetailReportId) {
@ -1591,24 +1448,24 @@ onMounted(async () => {
if (reportId && routeParams.value.type === 'view') { if (reportId && routeParams.value.type === 'view') {
const reportRes = await getProjectReport(reportId); const reportRes = await getProjectReport(reportId);
Object.assign(form.value, reportRes.data); Object.assign(form.value, reportRes.data);
//
reportDetailRes.data.fillTime = formatDateTime(reportDetailRes.data.fillTime, true);
Object.assign(projectReportForm.value, reportDetailRes.data); Object.assign(projectReportForm.value, reportDetailRes.data);
//
datePart.value = parseDatePart(projectReportForm.value.fillTime);
projectReportDetailList.value = [reportDetailRes.data]; projectReportDetailList.value = [reportDetailRes.data];
} }
if (reportId && routeParams.value.type === 'approval') { if (reportId && routeParams.value.type === 'approval') {
const reportRes = await getProjectReport(reportId); const reportRes = await getProjectReport(reportId);
Object.assign(form.value, reportRes.data); Object.assign(form.value, reportRes.data);
//
reportDetailRes.data.fillTime = formatDateTime(reportDetailRes.data.fillTime, true);
Object.assign(projectReportForm.value, reportDetailRes.data); Object.assign(projectReportForm.value, reportDetailRes.data);
//
datePart.value = parseDatePart(projectReportForm.value.fillTime);
} }
// view
if (projectReportForm.value.beginDate && projectReportForm.value.endDate) {
dateRange.value = [projectReportForm.value.beginDate, projectReportForm.value.endDate];
}
if (reportId && routeParams.value.type === 'update') {
const reportRes = await getProjectReport(reportId);
Object.assign(form.value, reportRes.data);
Object.assign(projectReportForm.value, reportDetailRes.data);
}
proxy?.$modal.closeLoading(); proxy?.$modal.closeLoading();
} }
} }

@ -131,7 +131,7 @@
<el-table-column label="更新时间" align="center" prop="updateTime" width="100" v-if="columns[15].visible" /> <el-table-column label="更新时间" align="center" prop="updateTime" width="100" v-if="columns[15].visible" />
<el-table-column label="操作" align="center" width="150" fixed="right" class-name="small-padding fixed-width"> <el-table-column label="操作" align="center" width="150" fixed="right" class-name="small-padding fixed-width">
<template #default="scope"> <template #default="scope">
<el-tooltip content="新增已有周报明细" placement="top" v-if="scope.row.status === '0'"> <el-tooltip content="新增已有周报明细" placement="top" v-if="scope.row.status !== '1'">
<el-button link type="primary" icon="Plus" @click="handleAdd(scope.row)" v-hasPermi="['oa/erp:projectReport:add']"></el-button> <el-button link type="primary" icon="Plus" @click="handleAdd(scope.row)" v-hasPermi="['oa/erp:projectReport:add']"></el-button>
</el-tooltip> </el-tooltip>
<el-tooltip content="修改" placement="top" v-if="scope.row.status === '1'"> <el-tooltip content="修改" placement="top" v-if="scope.row.status === '1'">
@ -143,7 +143,7 @@
v-hasPermi="['oa/erp:projectReport:edit']" v-hasPermi="['oa/erp:projectReport:edit']"
></el-button> ></el-button>
</el-tooltip> </el-tooltip>
<el-tooltip content="查看详情" placement="top"> <el-tooltip content="查看详情" placement="top" v-if="scope.row.status !== '1'">
<el-button link type="info" icon="DocumentChecked" @click="handleView(scope.row)"></el-button> <el-button link type="info" icon="DocumentChecked" @click="handleView(scope.row)"></el-button>
</el-tooltip> </el-tooltip>
<!-- <el-tooltip content="删除" placement="top"> <!-- <el-tooltip content="删除" placement="top">

Loading…
Cancel
Save