feat(crmMailingApply): 新增邮寄申请功能模块

- 新增邮寄申请编辑页,包含邮寄申请编号生成、表单填写及验证
- 实现邮寄申请列表页,支持新增、修改、查看、删除、搜索和导出
- 新增审批相关功能,包含审批按钮、审批记录、提交及流程启动
- 支持上传附件图片及关联项目选取
- 支持签收时间更新及签收时间弹窗交互
- 更新枚举及接口定义,增加邮寄申请相关常量和接口
- 优化物流信息相关字段,修正物流明细代码字段匹配
- 调整参数和权限控制,确保查看及审批模式下表单禁用
dev
zangch@mesnac.com 13 hours ago
parent f21e0e77a5
commit c068395757

@ -0,0 +1,100 @@
import request from '@/utils/request';
import { AxiosPromise } from 'axios';
import { CrmMailingApplyForm, CrmMailingApplyQuery, CrmMailingApplyVO } from '@/api/oa/crm/crmMailingApply/types';
/**
*
* @param query
* @returns {*}
*/
export const listCrmMailingApply = (query?: CrmMailingApplyQuery): AxiosPromise<CrmMailingApplyVO[]> => {
return request({
url: '/oa/crm/crmMailingApply/list',
method: 'get',
params: query
});
};
/**
*
* @param mailingApplyId
*/
export const getCrmMailingApply = (mailingApplyId: string | number): AxiosPromise<CrmMailingApplyVO> => {
return request({
url: '/oa/crm/crmMailingApply/' + mailingApplyId,
method: 'get'
});
};
/**
*
* @param data
*/
export const addCrmMailingApply = (data: CrmMailingApplyForm) => {
return request({
url: '/oa/crm/crmMailingApply',
method: 'post',
data: data
});
};
/**
*
* @param data
*/
export const updateCrmMailingApply = (data: CrmMailingApplyForm) => {
return request({
url: '/oa/crm/crmMailingApply',
method: 'put',
data: data
});
};
/**
*
* @param mailingApplyId
*/
export const delCrmMailingApply = (mailingApplyId: string | number | Array<string | number>) => {
return request({
url: '/oa/crm/crmMailingApply/' + mailingApplyId,
method: 'delete'
});
};
/**
*
* @param query
* @returns {*}
*/
export function getCrmMailingApplyList(query) {
return request({
url: '/oa/crm/crmMailingApply/getCrmMailingApplyList',
method: 'get',
params: query
});
}
/**
*
* @param data
*/
export const mailingApplySubmitAndFlowStart = (data: CrmMailingApplyForm): AxiosPromise<CrmMailingApplyVO> => {
return request({
url: '/oa/crm/crmMailingApply/submitAndFlowStart',
method: 'post',
data: data
});
};
/**
*
* @param data
*/
export const updateCrmMailingApplySignTime = (data: Pick<CrmMailingApplyForm, 'mailingApplyId' | 'signTime'>): AxiosPromise<CrmMailingApplyVO> => {
return request({
url: '/oa/crm/crmMailingApply/signTime',
method: 'put',
data: data
});
};

@ -0,0 +1,359 @@
export interface CrmMailingApplyVO {
/**
* ID
*/
mailingApplyId: string | number;
/**
*
*/
mailingApplyCode: string;
/**
*
*/
applicationDate: string;
/**
* ID
*/
handlerId: string | number;
/**
*
*/
handlerName: string;
/**
* ID
*/
deptId: string | number;
/**
*
*/
province: string;
/**
* kg
*/
weight: number;
/**
* 1-80 2- 3 4
*/
mailingType: string;
/**
*
*/
mailingFee: number;
/**
*
*/
expressNo: string;
/**
*
*/
itemInfo: string;
/**
* ID
*/
projectId: string | number;
/**
*
*/
projectCode: string;
/**
*
*/
projectName: string;
/**
* ID
*/
ossId: string | number;
/**
* 1 2 3 4
*/
mailingApplyStatus: string;
/**
*
*/
flowStatus: string;
/**
* 1 2 3
*/
logisticsStatus: string;
/**
*
*/
mailingTime: string;
/**
*
*/
signTime: string;
/**
*
*/
remark: string;
/**
*
*/
deptName?: string;
}
export interface CrmMailingApplyForm extends BaseEntity {
/**
* ID
*/
mailingApplyId?: string | number;
/**
*
*/
mailingApplyCode?: string;
/**
*
*/
applicationDate?: string;
/**
* ID
*/
handlerId?: string | number;
/**
*
*/
handlerName?: string;
/**
* ID
*/
deptId?: string | number;
/**
*
*/
province?: string;
/**
* kg
*/
weight?: number;
/**
* 1-80 2- 3 4
*/
mailingType?: string;
/**
*
*/
mailingFee?: number;
/**
*
*/
expressNo?: string;
/**
*
*/
itemInfo?: string;
/**
* ID
*/
projectId?: string | number;
/**
*
*/
projectCode?: string;
/**
*
*/
projectName?: string;
/**
* ID
*/
ossId?: string | number;
/**
* 1 2 3 4
*/
mailingApplyStatus?: string;
/**
*
*/
flowStatus?: string;
/**
* 1 2 3
*/
logisticsStatus?: string;
/**
*
*/
mailingTime?: string;
/**
*
*/
signTime?: string;
/**
*
*/
remark?: string;
/**
*
*/
deptName?: string;
/**
*
*/
flowCode?: string;
/**
*
*/
variables?: any;
/**
*
*/
bizExt?: any;
}
export interface CrmMailingApplyQuery extends PageQuery {
/**
*
*/
mailingApplyCode?: string;
/**
*
*/
applicationDate?: string;
/**
* ID
*/
handlerId?: string | number;
/**
*
*/
handlerName?: string;
/**
* ID
*/
deptId?: string | number;
/**
*
*/
province?: string;
/**
* kg
*/
weight?: number;
/**
* 1-80 2- 3 4
*/
mailingType?: string;
/**
*
*/
mailingFee?: number;
/**
*
*/
expressNo?: string;
/**
*
*/
itemInfo?: string;
/**
* ID
*/
projectId?: string | number;
/**
*
*/
projectCode?: string;
/**
*
*/
projectName?: string;
/**
* ID
*/
ossId?: string | number;
/**
* 1 2 3 4
*/
mailingApplyStatus?: string;
/**
*
*/
flowStatus?: string;
/**
* 1 2 3
*/
logisticsStatus?: string;
/**
*
*/
mailingTime?: string;
/**
*
*/
signTime?: string;
/**
*
*/
params?: any;
}

@ -33,7 +33,11 @@ export enum CodeRuleEnum {
*
*/
SHIPPING_BILL = '1014',
/**
*
*/
MAILING_APPLY = '1016',
}
/**
@ -123,5 +127,10 @@ export enum FlowCodeEnum {
/**
* KEY
*/
SHIPPING_BILL_CODE = 'WMSSP'
SHIPPING_BILL_CODE = 'WMSSP',
/**
* KEY
*/
MAILING_APPLY_CODE = 'CRMMA'
}

@ -0,0 +1,555 @@
<template>
<div class="p-2">
<el-card shadow="never" style="margin-top: 0">
<!-- 审批按钮组件 -->
<approvalButton
@submitForm="submitForm"
@approvalVerifyOpen="approvalVerifyOpen"
@handleApprovalRecord="handleApprovalRecord"
:buttonLoading="buttonLoading"
:id="form.mailingApplyId"
:status="form.flowStatus"
:pageType="routeParams.type"
:mode="false"
>
<el-button
v-if="form.mailingApplyId && routeParams.type !== 'approval'"
v-hasPermi="['oa/crm:crmMailingApply:edit']"
type="success"
@click="openSignTimeDialog"
>更新签收时间</el-button
>
</approvalButton>
</el-card>
<el-card shadow="never" style="margin-top: 0">
<el-form ref="mailingApplyFormRef" :model="form" :loading="buttonLoading" :disabled="!isFormEditable" :rules="rules" label-width="130px">
<el-divider content-position="left">基本信息</el-divider>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="邮寄申请编号" prop="mailingApplyCode">
<el-input v-model="form.mailingApplyCode" placeholder="自动生成邮寄申请编号" readonly>
<template #append>
<el-button type="primary" @click="generateMailingApplyCode" :disabled="isCodeGenerated">生成邮寄申请编号</el-button>
</template>
</el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="日期" prop="applicationDate">
<el-date-picker
clearable
v-model="form.applicationDate"
type="date"
value-format="YYYY-MM-DD"
placeholder="请选择日期"
style="width: 100%"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="经手人" prop="handlerId">
<el-select v-model="form.handlerId" placeholder="选择经手人" filterable @change="onHandlerChange" style="width: 100%">
<el-option v-for="item in userList" :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="province">
<el-input v-model="form.province" placeholder="请输入省份" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="重量" prop="weight">
<el-input-number v-model="form.weight" :precision="2" :step="0.1" :min="0" placeholder="请输入重量" style="width: 100%">
<template #append>kg</template>
</el-input-number>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="发起邮寄类型" prop="mailingType">
<el-select v-model="form.mailingType" placeholder="请选择邮寄类型" style="width: 100%">
<el-option v-for="dict in mailing_type" :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="mailingFee">
<el-input-number v-model="form.mailingFee" :precision="2" :step="1" :min="0" placeholder="请输入邮寄费用" style="width: 100%">
<template #append></template>
</el-input-number>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="快递单号" prop="expressNo">
<el-input v-model="form.expressNo" placeholder="请输入快递单号" />
</el-form-item>
</el-col>
</el-row>
<el-divider content-position="left">邮寄物品及事由</el-divider>
<el-row :gutter="20">
<el-col :span="24">
<el-form-item label="邮寄物品信息及申请事由" prop="itemInfo" label-width="180px">
<el-input v-model="form.itemInfo" type="textarea" :rows="4" placeholder="请输入邮寄物品信息及申请事由" />
</el-form-item>
</el-col>
</el-row>
<el-divider content-position="left">附件及关联项目</el-divider>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="附件图片" prop="ossId">
<file-upload
v-model="ossFileModel"
:limit="5"
:file-type="['png', 'jpg', 'jpeg', 'gif']"
:disabled="routeParams.type === 'view' || routeParams.type === 'approval'"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="项目名称" prop="projectId">
<el-input v-model="form.projectName" placeholder="点击选择项目" readonly @click="openProjectSelect">
<template #append>
<el-button icon="Search" @click="openProjectSelect" />
</template>
</el-input>
<el-button
v-if="form.projectId && !(routeParams.type === 'view' || routeParams.type === 'approval')"
link
type="danger"
@click="clearProjectSelect"
style="margin-left: 8px"
>
清空
</el-button>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="项目号" prop="projectCode">
<el-input v-model="form.projectCode" placeholder="自动填充" disabled />
</el-form-item>
</el-col>
</el-row>
<el-divider content-position="left">物流信息</el-divider>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="物流状态" prop="logisticsStatus">
<el-select v-model="form.logisticsStatus" placeholder="请选择物流状态" style="width: 100%">
<el-option v-for="dict in logistics_status" :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="mailingTime">
<el-date-picker
clearable
v-model="form.mailingTime"
type="datetime"
value-format="YYYY-MM-DD HH:mm:ss"
placeholder="请选择邮寄时间"
style="width: 100%"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="签收时间" prop="signTime">
<el-date-picker
clearable
v-model="form.signTime"
type="datetime"
value-format="YYYY-MM-DD HH:mm:ss"
placeholder="请选择签收时间"
style="width: 100%"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="备注" prop="remark">
<el-input v-model="form.remark" placeholder="请输入备注" />
</el-form-item>
</el-col>
</el-row>
</el-form>
</el-card>
<!-- 审批验证组件 -->
<SubmitVerify ref="submitVerifyRef" :task-variables="taskVariables" @submit-callback="submitCallback" />
<!-- 审批记录组件 -->
<ApprovalRecord ref="approvalRecordRef" />
<!-- 更新签收时间弹窗 -->
<el-dialog title="更新签收时间" v-model="signTimeDialog.visible" width="420px" append-to-body>
<el-form label-width="100px">
<el-form-item label="签收时间">
<el-date-picker
clearable
v-model="signTimeForm.signTime"
type="datetime"
value-format="YYYY-MM-DD HH:mm:ss"
placeholder="请选择签收时间"
style="width: 100%"
/>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button @click="signTimeDialog.visible = false">取消</el-button>
<el-button type="primary" :loading="signTimeDialog.loading" @click="submitSignTime"></el-button>
</div>
</template>
</el-dialog>
<!-- 项目选择弹窗 -->
<ProjectSelect ref="projectSelectRef" :multiple="false" @confirm-call-back="projectSelectCallback" />
</div>
</template>
<script setup name="CrmMailingApplyEdit" lang="ts">
import {
addCrmMailingApply,
getCrmMailingApply,
mailingApplySubmitAndFlowStart,
updateCrmMailingApply,
updateCrmMailingApplySignTime
} from '@/api/oa/crm/crmMailingApply';
import { CrmMailingApplyForm } from '@/api/oa/crm/crmMailingApply/types';
import { getUserList } from '@/api/system/user';
import ProjectSelect from '@/components/ProjectSelect/index.vue';
import { getRuleGenerateCode } from '@/api/system/codeRule';
import { CodeRuleEnum, FlowCodeEnum } from '@/enums/OAEnum';
import { getInfo } from '@/api/login';
import SubmitVerify from '@/components/Process/submitVerify.vue';
import ApprovalRecord from '@/components/Process/approvalRecord.vue';
import approvalButton from '@/components/Process/approvalButton.vue';
import { useUserStore } from '@/store/modules/user';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const { mailing_type, logistics_status, mailing_apply_status, wf_business_status } = toRefs<any>(
proxy?.useDict('mailing_type', 'logistics_status', 'mailing_apply_status', 'wf_business_status')
);
const router = useRouter();
const route = useRoute();
const userStore = useUserStore();
const mailingApplyFormRef = ref<ElFormInstance>();
const submitVerifyRef = ref<InstanceType<typeof SubmitVerify>>();
const approvalRecordRef = ref<InstanceType<typeof ApprovalRecord>>();
const projectSelectRef = ref<InstanceType<typeof ProjectSelect>>();
const buttonLoading = ref(false);
const isCodeGenerated = ref(false);
// P0稿update
const isFormEditable = computed(() => {
//
if (routeParams.value.type === 'view' || routeParams.value.type === 'approval') {
return false;
}
//
if (routeParams.value.type === 'add' || !form.value.mailingApplyId) {
return true;
}
// 稿
return form.value.mailingApplyStatus === '1';
});
const signTimeDialog = reactive({ visible: false, loading: false });
const signTimeForm = reactive<{ signTime: string | undefined }>({ signTime: undefined });
// 使queryprojectInfo
const routeParams = ref<Record<string, any>>({});
//
const taskVariables = ref<any>({});
//
const userList = ref<any[]>([]);
// OSS v-model form TS
const ossFileModel = ref<string | string[] | undefined>(undefined);
const initFormData: CrmMailingApplyForm = {
mailingApplyId: undefined,
mailingApplyCode: undefined,
applicationDate: undefined,
handlerId: undefined,
handlerName: undefined,
deptId: undefined,
province: undefined,
weight: undefined,
mailingType: undefined,
mailingFee: undefined,
expressNo: undefined,
itemInfo: undefined,
projectId: undefined,
projectCode: undefined,
projectName: undefined,
ossId: undefined,
mailingApplyStatus: '1',
flowStatus: undefined,
logisticsStatus: undefined,
mailingTime: undefined,
signTime: undefined,
remark: undefined,
flowCode: undefined,
variables: undefined,
bizExt: undefined
};
const data = reactive<{ form: CrmMailingApplyForm; rules: any }>({
form: { ...initFormData },
rules: {
applicationDate: [{ required: true, message: '申请日期不能为空', trigger: 'blur' }],
handlerId: [{ required: true, message: '经手人不能为空', trigger: 'change' }],
province: [{ required: true, message: '省份不能为空', trigger: 'blur' }],
weight: [{ required: true, message: '重量不能为空', trigger: 'blur' }],
mailingType: [{ required: true, message: '邮寄类型不能为空', trigger: 'change' }],
mailingFee: [{ required: true, message: '邮寄费用不能为空', trigger: 'blur' }],
itemInfo: [{ required: true, message: '邮寄物品信息及申请事由不能为空', trigger: 'blur' }],
expressNo: [{ required: true, message: '快递单号不能为空', trigger: 'blur' }],
logisticsStatus: [{ required: true, message: '物流状态不能为空', trigger: 'change' }],
mailingTime: [{ required: true, message: '邮寄时间不能为空', trigger: 'change' }]
}
});
const { form, rules } = toRefs(data);
/** 加载用户列表 */
const loadUserList = async () => {
try {
const res = await getUserList({} as any);
userList.value = res.data;
} catch (e) {
userList.value = [];
}
};
/** 打开项目选择弹窗 */
const openProjectSelect = () => {
if (routeParams.value.type === 'view' || routeParams.value.type === 'approval') {
return;
}
projectSelectRef.value?.open();
};
/** 项目选择回调 */
const projectSelectCallback = (selectedProjects: any[]) => {
if (selectedProjects && selectedProjects.length > 0) {
const project = selectedProjects[0];
form.value.projectId = project.projectId;
form.value.projectCode = project.projectCode;
form.value.projectName = project.projectName;
}
};
/** 清空项目选择 */
const clearProjectSelect = () => {
if (routeParams.value.type === 'view' || routeParams.value.type === 'approval') {
return;
}
form.value.projectId = undefined;
form.value.projectCode = undefined;
form.value.projectName = undefined;
};
watch(
() => form.value.ossId,
(val) => {
ossFileModel.value = val as any;
},
{ immediate: true }
);
watch(
() => ossFileModel.value,
(val) => {
form.value.ossId = val as any;
}
);
/** 经手人变更时自动填充姓名和部门 */
const onHandlerChange = (userId: number) => {
const user = userList.value.find((u) => u.userId === userId);
if (user) {
form.value.handlerName = user.nickName;
form.value.deptId = user.deptId;
}
};
/** 生成邮寄申请编号 */
const generateMailingApplyCode = async () => {
if (isCodeGenerated.value) return;
try {
const params = { codeRuleCode: CodeRuleEnum.MAILING_APPLY } as any;
const res = await getRuleGenerateCode(params);
form.value.mailingApplyCode = res.msg;
if (form.value.mailingApplyCode) {
isCodeGenerated.value = true;
proxy?.$modal.msgSuccess('邮寄申请编号生成成功');
}
} catch (error) {
console.error('生成邮寄申请编号失败:', error);
proxy?.$modal.msgError('生成邮寄申请编号失败');
}
};
/** 加载表单数据 */
const loadFormData = async () => {
//
const id = (route.query.id as string | number) || (route.params.mailingApplyId as string | number);
const type = (route.query.type as string) || (id && id !== '0' ? 'update' : 'add');
routeParams.value = { ...route.query, id, type } as any;
if (id && id !== '0' && (routeParams.value.type === 'update' || routeParams.value.type === 'view' || routeParams.value.type === 'approval')) {
const res = await getCrmMailingApply(id);
Object.assign(form.value, res.data);
if (form.value.mailingApplyCode) {
isCodeGenerated.value = true;
}
} else {
//
await generateMailingApplyCode();
form.value.applicationDate = new Date().toISOString().split('T')[0];
// getUserList使getInfo
form.value.handlerId = userStore.userId;
form.value.handlerName = userStore.nickname as any;
try {
const userInfoRes = await getInfo();
const userVO = userInfoRes.data?.user;
if (userVO) {
form.value.handlerName = userVO.nickName;
form.value.deptId = userVO.deptId;
}
} catch (e) {
// /
}
onHandlerChange(userStore.userId as number);
}
};
/** 审批验证组件打开 */
const approvalVerifyOpen = () => {
submitVerifyRef.value?.openDialog(routeParams.value.taskId as any);
};
/** 审批记录 */
const handleApprovalRecord = () => {
approvalRecordRef.value?.init(form.value.mailingApplyId);
};
/** 审批回调 */
const submitCallback = () => {
proxy?.$modal.msgSuccess('操作成功');
proxy?.$tab.closePage();
router.go(-1);
};
const openSignTimeDialog = () => {
signTimeForm.signTime = form.value.signTime as any;
signTimeDialog.visible = true;
};
const submitSignTime = async () => {
if (!form.value.mailingApplyId) {
proxy?.$modal.msgError('请先保存单据');
return;
}
signTimeDialog.loading = true;
try {
const res = await updateCrmMailingApplySignTime({ mailingApplyId: form.value.mailingApplyId, signTime: signTimeForm.signTime } as any);
form.value = res.data;
proxy?.$modal.msgSuccess('签收时间更新成功');
signTimeDialog.visible = false;
} finally {
signTimeDialog.loading = false;
}
};
/** 提交表单 */
const submitForm = async (status: string, mode: boolean) => {
if (!mailingApplyFormRef.value) {
return;
}
if (routeParams.value.type !== 'view' && routeParams.value.type !== 'approval' && !form.value.mailingApplyCode) {
await generateMailingApplyCode();
if (!form.value.mailingApplyCode) {
proxy?.$modal.msgError('邮寄申请编号生成失败,请稍后重试');
return;
}
}
try {
if (status === 'draft') {
await mailingApplyFormRef.value.validateField(['applicationDate', 'handlerId', 'province', 'weight', 'mailingType', 'mailingFee', 'itemInfo']);
} else {
await mailingApplyFormRef.value.validate();
}
} catch (e) {
return;
}
buttonLoading.value = true;
try {
if (status !== 'draft') {
form.value.flowCode = FlowCodeEnum.MAILING_APPLY_CODE;
form.value.variables = {
mailingApplyId: form.value.mailingApplyId,
mailingApplyCode: form.value.mailingApplyCode,
applicationDate: form.value.applicationDate,
handlerId: form.value.handlerId,
handlerName: form.value.handlerName,
deptId: form.value.deptId,
province: form.value.province,
weight: form.value.weight,
mailingType: form.value.mailingType,
mailingFee: form.value.mailingFee,
expressNo: form.value.expressNo,
itemInfo: form.value.itemInfo,
projectId: form.value.projectId,
projectCode: form.value.projectCode,
projectName: form.value.projectName,
logisticsStatus: form.value.logisticsStatus,
mailingTime: form.value.mailingTime,
signTime: form.value.signTime,
remark: form.value.remark,
entity: { ...form.value }
};
form.value.bizExt = {
businessTitle: '邮寄申请',
businessCode: form.value.mailingApplyCode
};
const res = await mailingApplySubmitAndFlowStart(form.value);
form.value = res.data;
proxy?.$modal.msgSuccess('提交成功');
proxy?.$tab.closePage();
router.go(-1);
} else {
form.value.mailingApplyStatus = '1';
form.value.flowStatus = 'draft';
if (form.value.mailingApplyId) {
await updateCrmMailingApply(form.value);
} else {
const res = await addCrmMailingApply(form.value);
form.value = res.data;
}
proxy?.$modal.msgSuccess('暂存成功');
// P1tabprojectInfo
proxy?.$tab.closePage();
router.go(-1);
}
} finally {
buttonLoading.value = false;
}
};
onMounted(async () => {
nextTick(async () => {
proxy?.$modal.loading('正在加载数据,请稍后...');
await loadUserList();
await loadFormData();
proxy?.$modal.closeLoading();
});
});
</script>

@ -0,0 +1,283 @@
<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="mailingApplyCode">
<el-input v-model="queryParams.mailingApplyCode" placeholder="请输入" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="经手人" prop="handlerName">
<el-input v-model="queryParams.handlerName" placeholder="请输入" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="邮寄类型" prop="mailingType">
<el-select v-model="queryParams.mailingType" placeholder="请选择" clearable>
<el-option v-for="dict in mailing_type" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
<el-form-item label="申请状态" prop="mailingApplyStatus">
<el-select v-model="queryParams.mailingApplyStatus" placeholder="请选择" clearable>
<el-option v-for="dict in mailing_apply_status" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
<el-form-item label="物流状态" prop="logisticsStatus">
<el-select v-model="queryParams.logisticsStatus" placeholder="请选择" clearable>
<el-option v-for="dict in logistics_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-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['oa/crm:crmMailingApply:add']"></el-button>
</el-col>
<el-col :span="1.5">
<el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['oa/crm:crmMailingApply: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:crmMailingApply:remove']"
>删除</el-button
>
</el-col>
<el-col :span="1.5">
<el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['oa/crm:crmMailingApply: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="crmMailingApplyList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="序号" type="index" width="60" align="center" />
<el-table-column label="申请编号" align="center" prop="mailingApplyCode" min-width="140" />
<el-table-column label="申请日期" align="center" prop="applicationDate" width="120">
<template #default="scope">
<span>{{ parseTime(scope.row.applicationDate, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="经手人" align="center" prop="handlerName" width="100" />
<el-table-column label="部门" align="center" prop="deptName" width="120" />
<el-table-column label="省份" align="center" prop="province" width="80" />
<el-table-column label="重量(kg)" align="center" prop="weight" width="80" />
<el-table-column label="邮寄类型" align="center" prop="mailingType" width="140">
<template #default="scope">
<dict-tag :options="mailing_type" :value="scope.row.mailingType" />
</template>
</el-table-column>
<el-table-column label="邮寄费用" align="center" prop="mailingFee" width="90" />
<el-table-column label="快递单号" align="center" prop="expressNo" width="140" />
<el-table-column label="项目名称" align="center" prop="projectName" min-width="150" show-overflow-tooltip />
<el-table-column label="申请状态" align="center" prop="mailingApplyStatus" width="100">
<template #default="scope">
<dict-tag :options="mailing_apply_status" :value="scope.row.mailingApplyStatus" />
</template>
</el-table-column>
<el-table-column label="物流状态" align="center" prop="logisticsStatus" width="90">
<template #default="scope">
<dict-tag :options="logistics_status" :value="scope.row.logisticsStatus" />
</template>
</el-table-column>
<el-table-column label="操作" align="center" fixed="right" width="200" class-name="small-padding fixed-width">
<template #default="scope">
<!-- 查看按钮非草稿状态显示 -->
<el-tooltip content="查看" placement="top" v-if="scope.row.mailingApplyStatus !== '1'">
<el-button link type="primary" icon="View" @click="handleView(scope.row)" v-hasPermi="['oa/crm:crmMailingApply:query']"></el-button>
</el-tooltip>
<!-- 修改按钮仅草稿状态显示 -->
<el-tooltip content="修改" placement="top" v-if="scope.row.mailingApplyStatus === '1'">
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['oa/crm:crmMailingApply:edit']"></el-button>
</el-tooltip>
<!-- 审批记录按钮审批中或已审批状态显示 -->
<el-tooltip content="审批记录" placement="top" v-if="scope.row.mailingApplyStatus === '2' || scope.row.mailingApplyStatus === '3'">
<el-button
link
type="primary"
icon="Tickets"
@click="handleApprovalRecord(scope.row)"
v-hasPermi="['oa/crm:crmMailingApply:query']"
></el-button>
</el-tooltip>
<!-- 删除按钮仅草稿状态显示 -->
<el-tooltip content="删除" placement="top" v-if="scope.row.mailingApplyStatus === '1'">
<el-button
link
type="primary"
icon="Delete"
@click="handleDelete(scope.row)"
v-hasPermi="['oa/crm:crmMailingApply: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>
<!-- 审批记录组件 -->
<ApprovalRecord ref="approvalRecordRef" />
</div>
</template>
<script setup name="CrmMailingApply" lang="ts">
import { delCrmMailingApply, listCrmMailingApply } from '@/api/oa/crm/crmMailingApply';
import { CrmMailingApplyQuery, CrmMailingApplyVO } from '@/api/oa/crm/crmMailingApply/types';
import ApprovalRecord from '@/components/Process/approvalRecord.vue';
import { parseTime } from '@/utils/ruoyi';
const router = useRouter();
const route = useRoute();
const approvalRecordRef = ref<InstanceType<typeof ApprovalRecord>>();
const { proxy } = getCurrentInstance() as any;
const { mailing_apply_status, wf_business_status, logistics_status, mailing_type } = toRefs<any>(
proxy?.useDict('mailing_apply_status', 'wf_business_status', 'logistics_status', 'mailing_type')
);
const crmMailingApplyList = ref<CrmMailingApplyVO[]>([]);
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 queryFormRef = ref<ElFormInstance>();
//
const columns = ref<FieldOption[]>([
{ key: 0, label: `申请编号`, visible: true },
{ key: 1, label: `申请日期`, visible: true },
{ key: 2, label: `经手人`, visible: true },
{ key: 3, label: `部门`, visible: true },
{ key: 4, label: `省份`, visible: true },
{ key: 5, label: `重量`, visible: true },
{ key: 6, label: `邮寄类型`, visible: true },
{ 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 }
]);
const queryParams = ref<CrmMailingApplyQuery>({
pageNum: 1,
pageSize: 10,
mailingApplyCode: undefined,
handlerName: undefined,
mailingType: undefined,
mailingApplyStatus: undefined,
logisticsStatus: undefined,
params: {}
});
/** 获取编辑页路由地址(兼容动态菜单路由与静态路由) */
const getEditPath = () => {
const currentPath = route.path || '';
if (currentPath.startsWith('/mailing/')) {
return '/mailing/crmMailingApply/edit';
}
return '/oa/crm/crmMailingApply/edit';
};
/** 查询邮寄申请列表 */
const getList = async () => {
loading.value = true;
const res = await listCrmMailingApply(queryParams.value);
crmMailingApplyList.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: CrmMailingApplyVO[]) => {
ids.value = selection.map((item) => item.mailingApplyId);
single.value = selection.length != 1;
multiple.value = !selection.length;
};
/** 新增按钮操作 - 跳转到编辑页 */
const handleAdd = () => {
proxy.$tab.closePage(route);
router.push({
path: getEditPath(),
query: { type: 'add' }
});
};
/** 修改按钮操作 - 跳转到编辑页 */
const handleUpdate = async (row?: CrmMailingApplyVO) => {
const _mailingApplyId = row?.mailingApplyId || ids.value[0];
proxy.$tab.closePage(route);
router.push({
path: getEditPath(),
query: {
id: _mailingApplyId,
type: 'update'
}
});
};
/** 查看按钮操作 - 跳转到查看页 */
const handleView = (row: CrmMailingApplyVO) => {
proxy.$tab.closePage(route);
router.push({
path: getEditPath(),
query: {
id: row.mailingApplyId,
type: 'view'
}
});
};
/** 审批记录按钮操作 */
const handleApprovalRecord = (row: CrmMailingApplyVO) => {
approvalRecordRef.value?.init(row.mailingApplyId);
};
/** 删除按钮操作 */
const handleDelete = async (row?: CrmMailingApplyVO) => {
const _mailingApplyIds = row?.mailingApplyId || ids.value;
await proxy?.$modal.confirm('是否确认删除邮寄申请编号为"' + _mailingApplyIds + '"的数据项?').finally(() => (loading.value = false));
await delCrmMailingApply(_mailingApplyIds);
proxy?.$modal.msgSuccess('删除成功');
await getList();
};
/** 导出按钮操作 */
const handleExport = () => {
proxy?.download(
'oa/crm/crmMailingApply/export',
{
...queryParams.value
},
`crmMailingApply_${new Date().getTime()}.xlsx`
);
};
onMounted(() => {
getList();
});
</script>

@ -171,7 +171,7 @@
</el-card>
<!-- 物流信息区域 -->
<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: 18px">物流信息</div>
</template>
@ -194,7 +194,7 @@
</el-col>
</el-row>
</el-form>
</el-card>
</el-card>-->
<!-- 发货明细区域 -->
<el-card shadow="never" style="margin-top: 0">
@ -211,7 +211,7 @@
@change="handleMaterialSourceChange"
:disabled="routeParams.type === 'view' || routeParams.type === 'approval'"
>
<el-radio-button value="1">ERP物料</el-radio-button>
<!-- <el-radio-button value="1">ERP物料</el-radio-button>-->
<el-radio-button value="2">WMS物料</el-radio-button>
</el-radio-group>
</el-col>
@ -784,12 +784,12 @@ const confirmWmsMaterialSelect = () => {
materielId: material.materielId,
materialCode: material.productCode,
materialName: material.productName,
materielSpecification: material.materialModel,
materielSpecification: material.productSpe,
batchNumber: material.batchNumber,
unitPrice: material.unitPrice || 0,
shippingStockAmount: 1,
unitId: undefined,
unitName: undefined,
unitId: material.unitId,
unitName: material.unitName,
totalPrice: material.unitPrice || 0,
remark: undefined
});

Loading…
Cancel
Save