Merge remote-tracking branch 'origin/dev' into dev

dev
wanghao 2 months ago
commit 69e313b556

@ -263,6 +263,11 @@ export interface BusinessTripApplyForm extends BaseEntity {
* *
*/ */
flowCode?: string; flowCode?: string;
/**
* ID
*/
copyUserIds?: string | string[];
} }
export interface BusinessTripApplyQuery extends PageQuery { export interface BusinessTripApplyQuery extends PageQuery {

@ -91,33 +91,11 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="24"> <el-col :span="12">
<el-form-item label="交流目的" prop="exchangePurpose"> <el-form-item label="交流目的" prop="exchangePurpose">
<el-input v-model="form.exchangePurpose" placeholder="请输入交流目的" :disabled="isFormDisabled" /> <el-input v-model="form.exchangePurpose" placeholder="请输入交流目的" :disabled="isFormDisabled" />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="24">
<el-form-item label="交流过程简述" prop="exchangeProcess">
<el-input
v-model="form.exchangeProcess"
type="textarea"
placeholder="如与某某客户某某负责人交谈参观XX等"
:disabled="isFormDisabled"
:rows="3"
/>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="结果反馈" prop="feedback">
<el-input
v-model="form.feedback"
type="textarea"
placeholder="达成某种共识或初步合作意向或会议成果"
:disabled="isFormDisabled"
:rows="3"
/>
</el-form-item>
</el-col>
</template> </template>
<!-- 动态字段展会/会议 (Type 3) --> <!-- 动态字段展会/会议 (Type 3) -->
@ -132,17 +110,6 @@
<el-input v-model="form.meetingName" placeholder="请输入" :disabled="isFormDisabled" /> <el-input v-model="form.meetingName" placeholder="请输入" :disabled="isFormDisabled" />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="24">
<el-form-item label="结果反馈" prop="feedback">
<el-input
v-model="form.feedback"
type="textarea"
placeholder="达成某种共识或初步合作意向或会议成果"
:disabled="isFormDisabled"
:rows="3"
/>
</el-form-item>
</el-col>
</template> </template>
<!-- 动态字段其他 (Type 4)以及Type 1的部分复用字段 --> <!-- 动态字段其他 (Type 4)以及Type 1的部分复用字段 -->
@ -214,7 +181,7 @@
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12" v-if="!isFormDisabled">
<el-form-item label="下一步审批人" prop="variables.approverId"> <el-form-item label="下一步审批人" prop="variables.approverId">
<el-select <el-select
v-model="form.variables.approverId" v-model="form.variables.approverId"
@ -222,13 +189,19 @@
filterable filterable
clearable clearable
style="width: 100%" style="width: 100%"
:disabled="isFormDisabled"
@change="handleApproverSelectChange" @change="handleApproverSelectChange"
> >
<el-option v-for="user in userList" :key="user.userId" :label="user.nickName" :value="user.userId" /> <el-option v-for="user in userList" :key="user.userId" :label="user.nickName" :value="user.userId" />
</el-select> </el-select>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12" v-if="!isFormDisabled">
<el-form-item label="抄送人员" prop="copyUserIds">
<el-select v-model="form.copyUserIds" placeholder="请选择抄送人员" filterable clearable multiple style="width: 100%">
<el-option v-for="user in userList" :key="user.userId" :label="user.nickName" :value="String(user.userId)" />
</el-select>
</el-form-item>
</el-col>
</el-row> </el-row>
</el-form> </el-form>
</el-card> </el-card>
@ -260,6 +233,7 @@ import ProjectSelect from '@/components/ProjectSelect/index.vue';
import { CodeRuleEnum, FlowCodeEnum } from '@/enums/OAEnum'; import { CodeRuleEnum, FlowCodeEnum } from '@/enums/OAEnum';
import { getInfo } from '@/api/login'; import { getInfo } from '@/api/login';
import { listUser } from '@/api/system/user'; // API import { listUser } from '@/api/system/user'; // API
import { allListDept } from '@/api/system/dept'; // API
import { ProjectInfoVO } from '@/api/oa/erp/projectInfo/types'; import { ProjectInfoVO } from '@/api/oa/erp/projectInfo/types';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
@ -281,6 +255,10 @@ const projectSelectRef = ref<InstanceType<typeof ProjectSelect>>();
// const userSelectRef = ref<InstanceType<typeof UserSelect>>(); // ref // const userSelectRef = ref<InstanceType<typeof UserSelect>>(); // ref
const userList = ref<any[]>([]); // const userList = ref<any[]>([]); //
const deptInfoList = ref<any[]>([]); //
//
const defaultCopyUserNames = ['米兰', '于洋', '张兰艳', '张东辉', '冯俊杰'];
// //
const submitFormData = ref<StartProcessBo>({ const submitFormData = ref<StartProcessBo>({
@ -316,7 +294,8 @@ const initFormData: BusinessTripApplyForm = {
flowStatus: 'draft', flowStatus: 'draft',
remark: undefined, remark: undefined,
ossId: undefined, ossId: undefined,
variables: {} // variables variables: {}, // variables
copyUserIds: [] as string[] // ID
}; };
const data = reactive({ const data = reactive({
@ -360,15 +339,40 @@ onMounted(async () => {
routeParams.value = route.query; routeParams.value = route.query;
const id = routeParams.value.id; const id = routeParams.value.id;
// ()
const userRes = await listUser({ pageNum: 1, pageSize: 1000 });
userList.value = userRes.rows;
// ()
const deptRes = await allListDept({ deptCategory: '03' } as any);
deptInfoList.value = deptRes.data || [];
// //
if (!id) { if (!id) {
try { try {
const userRes = await getInfo(); const infoRes = await getInfo();
if (userRes.data?.user) { if (infoRes.data?.user) {
form.value.applicantId = userRes.data.user.userId; form.value.applicantId = infoRes.data.user.userId;
form.value.applicantName = userRes.data.user.nickName; form.value.applicantName = infoRes.data.user.nickName;
form.value.deptId = userRes.data.user.deptId; form.value.deptId = infoRes.data.user.deptId;
form.value.deptName = userRes.data.user.deptName; form.value.deptName = infoRes.data.user.deptName;
// ID
const deptInfo = deptInfoList.value.find((d: any) => d.deptId === infoRes.data.user.deptId);
if (deptInfo) {
const deptLeaderId = deptInfo.leader;
const vicePresidentId = deptInfo.vicePresident;
//
const deptCopyIds: string[] = [];
if (deptLeaderId) deptCopyIds.push(String(deptLeaderId));
if (vicePresidentId) deptCopyIds.push(String(vicePresidentId));
//
const defaultCopyIds = userList.value.filter((u: any) => defaultCopyUserNames.includes(u.nickName)).map((u: any) => String(u.userId));
// /()
form.value.copyUserIds = [...new Set([...defaultCopyIds, ...deptCopyIds])];
}
} }
} catch (e) { } catch (e) {
console.error('获取用户信息失败', e); console.error('获取用户信息失败', e);
@ -379,14 +383,38 @@ onMounted(async () => {
} }
} }
// ()
listUser({ pageNum: 1, pageSize: 1000 }).then((res: any) => {
userList.value = res.rows;
});
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')) {
const res = await getBusinessTripApply(id); const res = await getBusinessTripApply(id);
Object.assign(form.value, res.data); Object.assign(form.value, res.data);
//
if (form.value.copyUserIds && typeof form.value.copyUserIds === 'string') {
form.value.copyUserIds = (form.value.copyUserIds as string).split(',').filter((id) => id);
}
//
if (routeParams.value.type === 'update' && (!form.value.copyUserIds || form.value.copyUserIds.length === 0)) {
// ID
const deptInfo = deptInfoList.value.find((d: any) => d.deptId === form.value.deptId);
if (deptInfo) {
const deptLeaderId = deptInfo.leader;
const vicePresidentId = deptInfo.vicePresident;
//
const deptCopyIds: string[] = [];
if (deptLeaderId) deptCopyIds.push(String(deptLeaderId));
if (vicePresidentId) deptCopyIds.push(String(vicePresidentId));
//
const defaultCopyIds = userList.value.filter((u: any) => defaultCopyUserNames.includes(u.nickName)).map((u: any) => String(u.userId));
// /()
form.value.copyUserIds = [...new Set([...defaultCopyIds, ...deptCopyIds])];
}
}
// variables
if (!form.value.variables) {
form.value.variables = {};
}
} }
}); });
}); });
@ -459,9 +487,12 @@ const executeSubmit = async (status: string, mode: boolean) => {
// //
form.value.tripStatus = '2'; // form.value.tripStatus = '2'; //
form.value.flowStatus = 'waiting'; form.value.flowStatus = 'waiting';
// ID
const copyUserIdsStr = Array.isArray(form.value.copyUserIds) ? form.value.copyUserIds.join(',') : form.value.copyUserIds || '';
form.value.variables = { form.value.variables = {
...form.value.variables, ...form.value.variables,
tripType: form.value.tripType tripType: form.value.tripType,
businessTripCopyUsers: copyUserIdsStr
}; };
form.value.bizExt = { form.value.bizExt = {
businessTitle: '出差申请', businessTitle: '出差申请',

@ -12,11 +12,15 @@
<el-option v-for="dict in trip_type" :key="dict.value" :label="dict.label" :value="dict.value" /> <el-option v-for="dict in trip_type" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="申请人姓名" prop="applicantName"> <el-form-item label="申请人姓名" prop="applicantId">
<el-input v-model="queryParams.applicantName" placeholder="请输入申请人姓名" clearable @keyup.enter="handleQuery" /> <el-select v-model="queryParams.applicantId" placeholder="请选择申请人" clearable filterable style="width: 200px">
<el-option v-for="user in userList" :key="user.userId" :label="user.nickName" :value="user.userId" />
</el-select>
</el-form-item> </el-form-item>
<el-form-item label="申请人部门" prop="deptName"> <el-form-item label="申请人部门" prop="deptId">
<el-input v-model="queryParams.deptName" placeholder="请输入申请人部门" clearable @keyup.enter="handleQuery" /> <el-select v-model="queryParams.deptId" placeholder="请选择部门" clearable filterable style="width: 200px">
<el-option v-for="dept in deptList" :key="dept.deptId" :label="dept.deptName" :value="dept.deptId" />
</el-select>
</el-form-item> </el-form-item>
<el-form-item label="出差地点" prop="tripLocation"> <el-form-item label="出差地点" prop="tripLocation">
<el-input v-model="queryParams.tripLocation" placeholder="请输入出差地点" clearable @keyup.enter="handleQuery" /> <el-input v-model="queryParams.tripLocation" placeholder="请输入出差地点" clearable @keyup.enter="handleQuery" />
@ -28,7 +32,9 @@
<el-date-picker clearable v-model="queryParams.endTime" type="date" value-format="YYYY-MM-DD" placeholder="请选择结束日期" /> <el-date-picker clearable v-model="queryParams.endTime" type="date" value-format="YYYY-MM-DD" placeholder="请选择结束日期" />
</el-form-item> </el-form-item>
<el-form-item label="业务方向" prop="businessDirection"> <el-form-item label="业务方向" prop="businessDirection">
<el-input v-model="queryParams.businessDirection" placeholder="请输入业务方向" clearable @keyup.enter="handleQuery" /> <el-select v-model="queryParams.businessDirection" placeholder="请选择业务方向" clearable filterable style="width: 200px">
<el-option v-for="dict in business_direction" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item> </el-form-item>
<el-form-item label="申请状态" prop="tripStatus"> <el-form-item label="申请状态" prop="tripStatus">
<el-select v-model="queryParams.tripStatus" placeholder="请选择申请状态" clearable> <el-select v-model="queryParams.tripStatus" placeholder="请选择申请状态" clearable>
@ -107,7 +113,11 @@
<el-table-column label="项目ID" align="center" prop="projectId" v-if="columns[13].visible" /> <el-table-column label="项目ID" align="center" prop="projectId" v-if="columns[13].visible" />
<!-- <el-table-column label="客户ID" align="center" prop="customerId" v-if="columns[14].visible" /> --> <!-- <el-table-column label="客户ID" align="center" prop="customerId" v-if="columns[14].visible" /> -->
<el-table-column label="交流对象" align="center" prop="exchangeObject" v-if="columns[15].visible" /> <el-table-column label="交流对象" align="center" prop="exchangeObject" v-if="columns[15].visible" />
<el-table-column label="业务方向" align="center" prop="businessDirection" v-if="columns[16].visible" /> <el-table-column label="业务方向" align="center" prop="businessDirection" v-if="columns[16].visible">
<template #default="scope">
<dict-tag :options="business_direction" :value="scope.row.businessDirection" />
</template>
</el-table-column>
<el-table-column label="交流目的" align="center" prop="exchangePurpose" v-if="columns[17].visible" /> <el-table-column label="交流目的" align="center" prop="exchangePurpose" v-if="columns[17].visible" />
<el-table-column label="交流过程简述" align="center" prop="exchangeProcess" v-if="columns[18].visible" /> <el-table-column label="交流过程简述" align="center" prop="exchangeProcess" v-if="columns[18].visible" />
<el-table-column label="会议/展会名称" align="center" prop="meetingName" v-if="columns[19].visible" /> <el-table-column label="会议/展会名称" align="center" prop="meetingName" v-if="columns[19].visible" />
@ -120,7 +130,7 @@
<el-table-column label="流程状态" align="center" prop="flowStatus" v-if="columns[22].visible" /> <el-table-column label="流程状态" align="center" prop="flowStatus" v-if="columns[22].visible" />
<el-table-column label="备注" align="center" prop="remark" v-if="columns[23].visible" /> <el-table-column label="备注" align="center" prop="remark" v-if="columns[23].visible" />
<!-- <el-table-column label="附件ID" align="center" prop="ossId" v-if="columns[24].visible" /> --> <!-- <el-table-column label="附件ID" align="center" prop="ossId" v-if="columns[24].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" width="160">
<template #default="scope"> <template #default="scope">
<el-tooltip <el-tooltip
content="修改" content="修改"
@ -132,6 +142,19 @@
<el-tooltip content="查看详情" placement="top" v-if="scope.row.flowStatus !== 'draft' && scope.row.flowStatus"> <el-tooltip content="查看详情" placement="top" v-if="scope.row.flowStatus !== 'draft' && scope.row.flowStatus">
<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"
v-if="scope.row.tripStatus === '3' && (scope.row.tripType === '2' || scope.row.tripType === '3')"
>
<el-button
link
type="success"
icon="ChatDotRound"
@click="handleFeedback(scope.row)"
v-hasPermi="['oa/crm:businessTripApply:edit']"
></el-button>
</el-tooltip>
<el-tooltip content="删除" placement="top"> <el-tooltip content="删除" placement="top">
<el-button <el-button
link link
@ -147,15 +170,41 @@
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" /> <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
</el-card> </el-card>
<!-- 出差反馈对话框 -->
<el-dialog v-model="feedbackDialogVisible" title="填写出差反馈" width="600px" append-to-body>
<el-form ref="feedbackFormRef" :model="feedbackForm" :rules="feedbackRules" label-width="120px">
<el-form-item label="申请单号">
<el-input v-model="feedbackForm.applyCode" disabled />
</el-form-item>
<el-form-item label="出差类型">
<dict-tag :options="trip_type" :value="feedbackForm.tripType" />
</el-form-item>
<el-form-item label="交流过程简述" prop="exchangeProcess" v-if="feedbackForm.tripType === '2'">
<el-input v-model="feedbackForm.exchangeProcess" type="textarea" placeholder="如与某某客户某某负责人交谈参观XX等" :rows="4" />
</el-form-item>
<el-form-item label="结果反馈" prop="feedback">
<el-input v-model="feedbackForm.feedback" type="textarea" placeholder="达成某种共识或初步合作意向或会议成果" :rows="4" />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="feedbackDialogVisible = false">取消</el-button>
<el-button type="primary" @click="submitFeedback" :loading="feedbackLoading">提交</el-button>
</template>
</el-dialog>
</div> </div>
</template> </template>
<script setup name="BusinessTripApply" lang="ts"> <script setup name="BusinessTripApply" lang="ts">
import { listBusinessTripApply, delBusinessTripApply } from '@/api/oa/crm/businessTripApply'; import { listBusinessTripApply, delBusinessTripApply, updateBusinessTripApply } from '@/api/oa/crm/businessTripApply';
import { BusinessTripApplyVO, BusinessTripApplyQuery } from '@/api/oa/crm/businessTripApply/types'; import { BusinessTripApplyVO, BusinessTripApplyQuery } from '@/api/oa/crm/businessTripApply/types';
import { listUser } from '@/api/system/user';
import { UserVO } from '@/api/system/user/types';
import { listDept } from '@/api/system/dept';
import { DeptVO } from '@/api/system/dept/types';
const { proxy } = getCurrentInstance() as ComponentInternalInstance; const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const { trip_status, trip_type } = toRefs<any>(proxy?.useDict('trip_status', 'trip_type')); const { trip_status, trip_type, business_direction } = toRefs<any>(proxy?.useDict('trip_status', 'trip_type', 'business_direction'));
const businessTripApplyList = ref<BusinessTripApplyVO[]>([]); const businessTripApplyList = ref<BusinessTripApplyVO[]>([]);
const loading = ref(true); const loading = ref(true);
@ -165,6 +214,8 @@ const single = ref(true);
const multiple = ref(true); const multiple = ref(true);
const total = ref(0); const total = ref(0);
const router = useRouter(); const router = useRouter();
const userList = ref<UserVO[]>([]);
const deptList = ref<DeptVO[]>([]);
const queryFormRef = ref<ElFormInstance>(); const queryFormRef = ref<ElFormInstance>();
@ -255,7 +306,7 @@ const handleSelectionChange = (selection: BusinessTripApplyVO[]) => {
/** 新增按钮操作 */ /** 新增按钮操作 */
const handleAdd = (command: string) => { const handleAdd = (command: string) => {
router.push({ router.push({
path: '/oa/crm/businessTripApply/edit', path: '/tripapply/businessTripApply/edit',
query: { type: 'add', tripType: command } query: { type: 'add', tripType: command }
}); });
}; };
@ -264,7 +315,7 @@ const handleAdd = (command: string) => {
const handleUpdate = (row?: BusinessTripApplyVO) => { const handleUpdate = (row?: BusinessTripApplyVO) => {
const _tripId = row?.tripId || ids.value[0]; const _tripId = row?.tripId || ids.value[0];
router.push({ router.push({
path: '/oa/crm/businessTripApply/edit', path: '/tripapply/businessTripApply/edit',
query: { id: _tripId, type: 'update' } query: { id: _tripId, type: 'update' }
}); });
}; };
@ -273,7 +324,7 @@ const handleUpdate = (row?: BusinessTripApplyVO) => {
const handleView = (row: BusinessTripApplyVO) => { const handleView = (row: BusinessTripApplyVO) => {
const _tripId = row?.tripId; const _tripId = row?.tripId;
router.push({ router.push({
path: '/oa/crm/businessTripApply/edit', path: '/tripapply/businessTripApply/edit',
query: { id: _tripId, type: 'view' } query: { id: _tripId, type: 'view' }
}); });
}; };
@ -292,17 +343,89 @@ const handleExport = () => {
proxy?.download( proxy?.download(
'oa/crm/businessTripApply/export', 'oa/crm/businessTripApply/export',
{ {
...queryParams.value ...queryParams.value,
//
tripIds: ids.value.length > 0 ? ids.value.join(',') : undefined
}, },
`businessTripApply_${new Date().getTime()}.xlsx` `businessTripApply_${new Date().getTime()}.xlsx`
); );
}; };
onMounted(() => { onMounted(async () => {
//
const userRes = await listUser({ pageNum: 1, pageSize: 1000 });
userList.value = userRes.rows;
//
const deptRes = await listDept();
deptList.value = deptRes.data;
//
getList(); getList();
}); });
onActivated(() => { onActivated(() => {
getList(); getList();
}); });
// ============ ============
const feedbackDialogVisible = ref(false);
const feedbackLoading = ref(false);
const feedbackFormRef = ref<ElFormInstance>();
const feedbackForm = ref<{
tripId?: number | string;
applyCode?: string;
tripType?: string;
applicantId?: number | string;
tripLocation?: string;
startTime?: string;
endTime?: string;
durationDays?: number;
exchangeProcess?: string;
feedback?: string;
}>({});
const feedbackRules = {
feedback: [{ required: true, message: '请填写结果反馈', trigger: 'blur' }]
};
/** 填写反馈按钮操作 */
const handleFeedback = (row: BusinessTripApplyVO) => {
feedbackForm.value = {
tripId: row.tripId,
applyCode: row.applyCode,
tripType: row.tripType,
applicantId: row.applicantId,
tripLocation: row.tripLocation,
startTime: row.startTime,
endTime: row.endTime,
durationDays: row.durationDays,
exchangeProcess: row.exchangeProcess || '',
feedback: row.feedback || ''
};
feedbackDialogVisible.value = true;
};
/** 提交反馈 */
const submitFeedback = async () => {
await feedbackFormRef.value?.validate();
feedbackLoading.value = true;
try {
await updateBusinessTripApply({
tripId: String(feedbackForm.value.tripId),
tripType: feedbackForm.value.tripType,
applicantId: feedbackForm.value.applicantId,
tripLocation: feedbackForm.value.tripLocation,
startTime: feedbackForm.value.startTime,
endTime: feedbackForm.value.endTime,
durationDays: feedbackForm.value.durationDays,
exchangeProcess: feedbackForm.value.exchangeProcess,
feedback: feedbackForm.value.feedback
});
proxy?.$modal.msgSuccess('反馈提交成功');
feedbackDialogVisible.value = false;
await getList();
} catch (e) {
console.error(e);
} finally {
feedbackLoading.value = false;
}
};
</script> </script>

@ -15,7 +15,7 @@
</el-card> </el-card>
<!-- 主表信息卡片 --> <!-- 主表信息卡片 -->
<el-card shadow="never"> <el-card shadow="never" class="card-with-upload">
<template #header> <template #header>
<span class="card-title">{{ form.afterSalesId ? '修改项目售后' : '添加项目售后' }}</span> <span class="card-title">{{ form.afterSalesId ? '修改项目售后' : '添加项目售后' }}</span>
</template> </template>
@ -119,7 +119,10 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> </el-row>
<!-- 问题描述和附件使用 flexbox 并排 -->
<div class="problem-attachment-row">
<div class="problem-col">
<el-form-item label="问题描述" prop="problemDescription"> <el-form-item label="问题描述" prop="problemDescription">
<el-input <el-input
v-model="form.problemDescription" v-model="form.problemDescription"
@ -130,14 +133,25 @@
placeholder="请输入详细的问题描述" placeholder="请输入详细的问题描述"
/> />
</el-form-item> </el-form-item>
</el-col> </div>
<el-col :span="12"> <div class="attachment-col"></div>
<el-form-item label="售后问题附件" prop="ossId"> </div>
<file-upload v-model="form.ossId" :limit="5" :fileSize="20" :fileType="['rar', 'zip', 'doc', 'docx', 'pdf']" :isShowTip="true" />
</el-form-item>
</el-col>
</el-row>
</el-form> </el-form>
<!-- 附件区域放在表单外部使用负 margin 拉到与问题描述同行 -->
<div class="file-upload-row">
<el-form label-width="120px">
<el-form-item label="售后问题附件">
<file-upload
v-model="form.ossId"
:limit="5"
:fileSize="20"
:fileType="['rar', 'zip', 'doc', 'docx', 'pdf']"
:isShowTip="true"
:disabled="isReadOnly"
/>
</el-form-item>
</el-form>
</div>
</el-card> </el-card>
<!-- ========== 售后处理结果 ========== --> <!-- ========== 售后处理结果 ========== -->
@ -461,6 +475,9 @@ const editingIndex = ref<number>(-1); // 材料表编辑索引 (-1 为新增)
const checkedLabor = ref<any[]>([]); // const checkedLabor = ref<any[]>([]); //
const checkedMaterial = ref<any[]>([]); // const checkedMaterial = ref<any[]>([]); //
//
const projectMgrUserNames = ['于洋'];
// //
const submitFormData = ref<StartProcessBo>({ businessId: '', flowCode: '', variables: {}, bizExt: {} }); const submitFormData = ref<StartProcessBo>({ businessId: '', flowCode: '', variables: {}, bizExt: {} });
const taskVariables = ref<Record<string, any>>({}); const taskVariables = ref<Record<string, any>>({});
@ -929,10 +946,13 @@ const executeSubmit = async (status: string, mode: boolean) => {
if (status !== 'draft') { if (status !== 'draft') {
// --- --- // --- ---
submitData.flowCode = FlowCodeEnum.AFTER_SALES_KEY; submitData.flowCode = FlowCodeEnum.AFTER_SALES_KEY;
//
const copyUserIds = userList.value.filter((u: any) => projectMgrUserNames.includes(u.nickName)).map((u: any) => String(u.userId));
submitData.variables = { submitData.variables = {
afterSalesId: submitData.afterSalesId, afterSalesId: submitData.afterSalesId,
totalCost: submitData.totalCost || 0, totalCost: submitData.totalCost || 0,
startUserId: useUserStore().userId startUserId: useUserStore().userId,
afterSalesCopyUsers: copyUserIds.join(',')
}; };
submitData.bizExt = { submitData.bizExt = {
businessTitle: `售后申请:${submitData.afterSalesSubject}`, businessTitle: `售后申请:${submitData.afterSalesSubject}`,
@ -1001,4 +1021,34 @@ const submitCallback = async () => {
.mt-2 { .mt-2 {
margin-top: 10px; margin-top: 10px;
} }
/* 问题描述和附件区域容器 - 使用 flexbox */
.problem-attachment-row {
display: flex;
margin: 0;
}
.problem-col {
flex: 0 0 50%;
max-width: 50%;
padding-right: 10px;
}
.attachment-col {
flex: 0 0 50%;
max-width: 50%;
padding-left: 10px;
}
/* 附件区域使用负 margin 拉到问题描述同行 */
.file-upload-row {
margin-top: -95px; /* 向上拉到与问题描述同行 */
margin-left: 50%; /* 偏移到右侧,与上方表单字段对齐 */
padding-left: 10px;
padding-right: 10px;
}
.file-upload-content {
/* 无需额外样式 */
}
</style> </style>

@ -131,7 +131,7 @@
<el-tooltip content="修改" placement="top" v-if="scope.row.flowStatus === 'draft' || scope.row.flowStatus === 'back'"> <el-tooltip content="修改" placement="top" v-if="scope.row.flowStatus === 'draft' || scope.row.flowStatus === 'back'">
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['oa/erp:afterSales:edit']"></el-button> <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['oa/erp:afterSales:edit']"></el-button>
</el-tooltip> </el-tooltip>
<el-tooltip content="查看详情" placement="top" v-if="scope.row.flowStatus !== 'draft'"> <el-tooltip content="查看详情" placement="top" v-if="scope.row.flowStatus !== 'draft'">
<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>
</template> </template>
@ -382,7 +382,9 @@ const handleExport = () => {
proxy?.download( proxy?.download(
'oa/erp/afterSales/export', 'oa/erp/afterSales/export',
{ {
...queryParams.value ...queryParams.value,
//
afterSalesIds: ids.value.length > 0 ? ids.value.join(',') : undefined
}, },
`afterSales_${new Date().getTime()}.xlsx` `afterSales_${new Date().getTime()}.xlsx`
); );

@ -4,8 +4,15 @@
<div v-show="showSearch" class="mb-[10px]"> <div v-show="showSearch" class="mb-[10px]">
<el-card shadow="hover"> <el-card shadow="hover">
<el-form ref="queryFormRef" :model="queryParams" :inline="true" label-width="100px"> <el-form ref="queryFormRef" :model="queryParams" :inline="true" label-width="100px">
<el-form-item label="工时填报编号" prop="timesheetCode"> <el-form-item label="人员" prop="userId">
<el-input v-model="queryParams.timesheetCode" placeholder="请输入工时填报编号" clearable @keyup.enter="handleQuery" /> <el-select v-model="queryParams.userId" placeholder="请选择填报人" clearable filterable style="width: 200px">
<el-option v-for="user in userList" :key="user.userId" :label="user.nickName" :value="user.userId" />
</el-select>
</el-form-item>
<el-form-item label="部门" prop="deptId">
<el-select v-model="queryParams.deptId" placeholder="请选择部门" clearable filterable style="width: 200px">
<el-option v-for="dept in deptList" :key="dept.deptId" :label="dept.deptName" :value="dept.deptId" />
</el-select>
</el-form-item> </el-form-item>
<el-form-item label="起始时间" prop="startTime"> <el-form-item label="起始时间" prop="startTime">
<el-date-picker clearable v-model="queryParams.startTime" type="date" value-format="YYYY-MM-DD" placeholder="请选择起始时间" /> <el-date-picker clearable v-model="queryParams.startTime" type="date" value-format="YYYY-MM-DD" placeholder="请选择起始时间" />
@ -102,6 +109,10 @@
<script setup name="TimesheetInfo" lang="ts"> <script setup name="TimesheetInfo" lang="ts">
import { listTimesheetInfo, getTimesheetInfo, delTimesheetInfo, addTimesheetInfo, updateTimesheetInfo } from '@/api/oa/erp/timesheetInfo'; import { listTimesheetInfo, getTimesheetInfo, delTimesheetInfo, addTimesheetInfo, updateTimesheetInfo } from '@/api/oa/erp/timesheetInfo';
import { TimesheetInfoVO, TimesheetInfoQuery, TimesheetInfoForm } from '@/api/oa/erp/timesheetInfo/types'; import { TimesheetInfoVO, TimesheetInfoQuery, TimesheetInfoForm } from '@/api/oa/erp/timesheetInfo/types';
import { listUser } from '@/api/system/user';
import { UserVO } from '@/api/system/user/types';
import { listDept } from '@/api/system/dept';
import { DeptVO } from '@/api/system/dept/types';
const { proxy } = getCurrentInstance() as ComponentInternalInstance; const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const route = useRoute(); const route = useRoute();
@ -116,6 +127,8 @@ const ids = ref<Array<string | number>>([]);
const single = ref(true); const single = ref(true);
const multiple = ref(true); const multiple = ref(true);
const total = ref(0); const total = ref(0);
const userList = ref<UserVO[]>([]);
const deptList = ref<DeptVO[]>([]);
const queryFormRef = ref<ElFormInstance>(); const queryFormRef = ref<ElFormInstance>();
const timesheetInfoFormRef = ref<ElFormInstance>(); const timesheetInfoFormRef = ref<ElFormInstance>();
@ -298,13 +311,22 @@ const handleExport = () => {
proxy?.download( proxy?.download(
'oa/erp/timesheetInfo/export', 'oa/erp/timesheetInfo/export',
{ {
...queryParams.value ...queryParams.value,
//
timesheetIds: ids.value.length > 0 ? ids.value.join(',') : undefined
}, },
`timesheetInfo_${new Date().getTime()}.xlsx` `timesheetInfo_${new Date().getTime()}.xlsx`
); );
}; };
onMounted(() => { onMounted(async () => {
//
const userRes = await listUser({ pageNum: 1, pageSize: 1000 });
userList.value = userRes.rows;
//
const deptRes = await listDept();
deptList.value = deptRes.data;
//
getList(); getList();
}); });
</script> </script>

Loading…
Cancel
Save