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.

432 lines
19 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">
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
<div v-show="showSearch" class="mb-[10px]">
<el-card shadow="hover">
<el-form ref="queryFormRef" :model="queryParams" :inline="true" label-width="100px">
<el-form-item label="申请单号" prop="applyCode">
<el-input v-model="queryParams.applyCode" placeholder="请输入申请单号" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="出差类型" prop="tripType">
<el-select v-model="queryParams.tripType" placeholder="请选择出差类型" clearable>
<el-option v-for="dict in trip_type" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
<el-form-item label="申请人姓名" prop="applicantId">
<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 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 label="出差地点" prop="tripLocation">
<el-input v-model="queryParams.tripLocation" placeholder="请输入出差地点" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="开始日期" prop="startTime">
<el-date-picker clearable v-model="queryParams.startTime" type="date" value-format="YYYY-MM-DD" placeholder="请选择开始日期" />
</el-form-item>
<el-form-item label="结束日期" prop="endTime">
<el-date-picker clearable v-model="queryParams.endTime" type="date" value-format="YYYY-MM-DD" placeholder="请选择结束日期" />
</el-form-item>
<el-form-item label="业务方向" prop="businessDirection">
<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 label="申请状态" prop="tripStatus">
<el-select v-model="queryParams.tripStatus" placeholder="请选择申请状态" clearable>
<el-option v-for="dict in trip_status" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
</el-card>
</div>
</transition>
<el-card shadow="never">
<template #header>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-dropdown trigger="click" @command="handleAdd">
<el-button type="primary" plain icon="Plus" v-hasPermi="['oa/crm:businessTripApply:add']">
新增<el-icon class="el-icon--right"><arrow-down /></el-icon>
</el-button>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item v-for="dict in trip_type" :key="dict.value" :command="dict.value">
{{ dict.label }}
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</el-col>
<el-col :span="1.5">
<el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['oa/crm:businessTripApply:edit']"
>修改</el-button
>
</el-col>
<el-col :span="1.5">
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['oa/crm:businessTripApply:remove']"
>删除</el-button
>
</el-col>
<el-col :span="1.5">
<el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['oa/crm:businessTripApply:export']">导出</el-button>
</el-col>
<right-toolbar v-model:showSearch="showSearch" :columns="columns" :search="true" @queryTable="getList"></right-toolbar>
</el-row>
</template>
<el-table v-loading="loading" border :data="businessTripApplyList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="申请ID" align="center" prop="tripId" v-if="columns[0].visible" />
<el-table-column label="申请单号" align="center" prop="applyCode" v-if="columns[2].visible" />
<el-table-column label="出差类型" align="center" prop="tripType" v-if="columns[3].visible">
<template #default="scope">
<dict-tag :options="trip_type" :value="scope.row.tripType" />
</template>
</el-table-column>
<el-table-column label="申请人ID" align="center" prop="applicantId" v-if="columns[4].visible" />
<el-table-column label="申请人" align="center" prop="applicantName" v-if="columns[5].visible" />
<el-table-column label="申请人部门ID" align="center" prop="deptId" v-if="columns[6].visible" />
<el-table-column label="申请人部门" align="center" prop="deptName" v-if="columns[7].visible" width="120" />
<el-table-column label="出差地点" align="center" prop="tripLocation" v-if="columns[8].visible" />
<el-table-column label="开始日期" align="center" prop="startTime" width="100" v-if="columns[9].visible">
<template #default="scope">
<span>{{ parseTime(scope.row.startTime, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="结束日期" align="center" prop="endTime" width="100" v-if="columns[10].visible">
<template #default="scope">
<span>{{ parseTime(scope.row.endTime, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="时长(天)" align="center" prop="durationDays" v-if="columns[11].visible" />
<el-table-column label="出差事由" align="center" prop="tripReason" v-if="columns[12].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="交流对象" align="center" prop="exchangeObject" v-if="columns[15].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="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="feedback" v-if="columns[20].visible" />
<el-table-column label="申请状态" align="center" prop="tripStatus" v-if="columns[21].visible">
<template #default="scope">
<dict-tag :options="trip_status" :value="scope.row.tripStatus" />
</template>
</el-table-column>
<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="附件ID" align="center" prop="ossId" v-if="columns[24].visible" /> -->
<el-table-column label="操作" align="center" fixed="right" class-name="small-padding fixed-width" width="160">
<template #default="scope">
<el-tooltip
content="修改"
placement="top"
v-if="scope.row.flowStatus === 'draft' || scope.row.flowStatus === 'back' || !scope.row.flowStatus"
>
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['oa/crm:businessTripApply:edit']"></el-button>
</el-tooltip>
<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-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-button
link
type="primary"
icon="Delete"
@click="handleDelete(scope.row)"
v-hasPermi="['oa/crm:businessTripApply:remove']"
></el-button>
</el-tooltip>
</template>
</el-table-column>
</el-table>
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
</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>
</template>
<script setup name="BusinessTripApply" lang="ts">
import { listBusinessTripApply, delBusinessTripApply, updateBusinessTripApply } from '@/api/oa/crm/businessTripApply';
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 { trip_status, trip_type, business_direction } = toRefs<any>(proxy?.useDict('trip_status', 'trip_type', 'business_direction'));
const businessTripApplyList = ref<BusinessTripApplyVO[]>([]);
const loading = ref(true);
const showSearch = ref(true);
const ids = ref<Array<string | number>>([]);
const single = ref(true);
const multiple = ref(true);
const total = ref(0);
const router = useRouter();
const userList = ref<UserVO[]>([]);
const deptList = ref<DeptVO[]>([]);
const queryFormRef = ref<ElFormInstance>();
// 列显隐信息
const columns = ref<FieldOption[]>([
{ key: 0, label: `申请ID`, visible: false },
{ key: 1, label: `租户编号`, visible: false },
{ key: 2, label: `申请单号`, visible: true },
{ key: 3, label: `出差类型`, visible: true },
{ key: 4, label: `申请人ID`, visible: false },
{ key: 5, label: `申请人姓名`, visible: true },
{ key: 6, label: `申请人部门ID`, visible: false },
{ key: 7, label: `申请人部门名称`, visible: true },
{ key: 8, label: `出差地点`, visible: true },
{ key: 9, label: `开始日期`, visible: true },
{ key: 10, label: `结束日期`, visible: true },
{ key: 11, label: `时长(天)`, visible: true },
{ key: 12, label: `出差事由`, visible: true },
{ key: 13, label: `项目ID`, visible: false },
{ key: 14, label: `客户ID`, visible: false },
{ key: 15, label: `交流对象`, visible: true },
{ key: 16, label: `业务方向`, visible: true },
{ key: 17, label: `业务方向`, visible: true },
{ key: 18, label: `交流过程简述`, visible: true },
{ key: 19, label: `会议/展会名称`, visible: true },
{ key: 20, label: `结果反馈`, visible: true },
{ key: 21, label: `申请状态`, visible: true },
{ key: 22, label: `流程状态`, visible: true },
{ key: 23, label: `备注`, visible: true },
{ key: 24, label: `附件ID`, visible: false },
{ key: 25, label: `删除标志`, visible: true },
{ key: 26, label: `创建部门`, visible: true },
{ key: 27, label: `创建者`, visible: true },
{ key: 28, label: `创建时间`, visible: true },
{ key: 29, label: `更新者`, visible: true },
{ key: 30, label: `更新时间`, visible: true }
]);
const data = reactive<PageData<any, BusinessTripApplyQuery>>({
form: {},
queryParams: {
pageNum: 1,
pageSize: 10,
applyCode: undefined,
tripType: undefined,
applicantName: undefined,
deptName: undefined,
tripLocation: undefined,
startTime: undefined,
endTime: undefined,
businessDirection: undefined,
tripStatus: undefined,
params: {}
},
rules: {}
});
const { queryParams } = toRefs(data);
/** 查询出差申请列表 */
const getList = async () => {
loading.value = true;
const res = await listBusinessTripApply(queryParams.value);
businessTripApplyList.value = res.rows;
total.value = res.total;
loading.value = false;
};
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.value.pageNum = 1;
getList();
};
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value?.resetFields();
handleQuery();
};
/** 多选框选中数据 */
const handleSelectionChange = (selection: BusinessTripApplyVO[]) => {
ids.value = selection.map((item) => item.tripId);
single.value = selection.length != 1;
multiple.value = !selection.length;
};
/** 新增按钮操作 */
const handleAdd = (command: string) => {
router.push({
path: '/tripapply/businessTripApply/edit',
query: { type: 'add', tripType: command }
});
};
/** 修改按钮操作 */
const handleUpdate = (row?: BusinessTripApplyVO) => {
const _tripId = row?.tripId || ids.value[0];
router.push({
path: '/tripapply/businessTripApply/edit',
query: { id: _tripId, type: 'update' }
});
};
/** 查看按钮操作 */
const handleView = (row: BusinessTripApplyVO) => {
const _tripId = row?.tripId;
router.push({
path: '/tripapply/businessTripApply/edit',
query: { id: _tripId, type: 'view' }
});
};
/** 删除按钮操作 */
const handleDelete = async (row?: BusinessTripApplyVO) => {
const _tripIds = row?.tripId || ids.value;
await proxy?.$modal.confirm('是否确认删除出差申请编号为"' + _tripIds + '"的数据项?').finally(() => (loading.value = false));
await delBusinessTripApply(_tripIds);
proxy?.$modal.msgSuccess('删除成功');
await getList();
};
/** 导出按钮操作 */
const handleExport = () => {
proxy?.download(
'oa/crm/businessTripApply/export',
{
...queryParams.value,
// 如果选中了数据,则只导出选中的数据
tripIds: ids.value.length > 0 ? ids.value.join(',') : undefined
},
`businessTripApply_${new Date().getTime()}.xlsx`
);
};
onMounted(async () => {
// 加载用户列表
const userRes = await listUser({ pageNum: 1, pageSize: 1000 });
userList.value = userRes.rows;
// 加载部门列表
const deptRes = await listDept();
deptList.value = deptRes.data;
// 加载数据列表
getList();
});
onActivated(() => {
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>