admin-vue3/src/views/crm/customer-suggestion/create.vue

280 lines
9.5 KiB
Vue
Raw Blame History

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>
<el-row :gutter="20">
<el-col :span="16">
<ContentWrap title="新增客户建议">
<el-form
ref="formRef"
v-loading="formLoading"
:model="formData"
:rules="formRules"
label-width="100px"
>
<el-form-item label="客户" prop="customerId">
<SelectComponent :customerList="customerList" v-model="formData.customerId" />
<!-- <el-select
v-model="formData.customerId"
clearable
filterable
lable-key="name"
placeholder="请选择客户"
value-key="id"
>
<el-option
v-for="item in customerList"
:key="item.id"
:label="item.name"
:value="item.id!"
/>
</el-select> -->
</el-form-item>
<el-form-item label="反馈部门" prop="feedbackDeptId">
<el-tree-select
v-model="formData.feedbackDeptId"
:data="deptList"
:props="defaultProps"
check-strictly
node-key="id"
placeholder="请选择部门"
@change="getSimpleUserList"
/>
</el-form-item>
<el-form-item label="反馈人" prop="feedbackUserId">
<el-select
v-model="formData.feedbackUserId"
clearable
filterable
lable-key="name"
placeholder="请选择反馈人"
value-key="id"
>
<el-option
v-for="item in userList"
:key="item.id"
:label="item.nickname"
:value="item.id!"
/>
</el-select>
</el-form-item>
<el-form-item label="反馈问题" prop="feedbackProblem">
<el-input v-model="formData.feedbackProblem" placeholder="请输入反馈问题" type="textarea" :rows="3"/>
</el-form-item>
<el-form-item label="建议" prop="suggestion">
<el-input v-model="formData.suggestion" placeholder="请输入建议" type="textarea" :rows="3"/>
</el-form-item>
<el-form-item>
<el-button :disabled="formLoading" type="primary" @click="submitForm">
确 定
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
</el-col>
<!-- 审批相关:流程信息 -->
<el-col :span="8">
<ContentWrap title="审批流程" :bodyStyle="{ padding: '0 20px 0' }">
<ProcessInstanceTimeline
ref="timelineRef"
:activity-nodes="activityNodes"
:show-status-icon="false"
@select-user-confirm="selectUserConfirm"
/>
</ContentWrap>
</el-col>
</el-row>
</template>
<script lang="ts" setup>
import { useTagsViewStore } from '@/store/modules/tagsView'
import * as CustomerSuggestionApi from '@/api/crm/customer-suggestion'
import * as CustomerApi from '@/api/crm/customer'
import * as DeptApi from '@/api/system/dept'
import * as UserApi from '@/api/system/user'
// 审批相关import
import * as DefinitionApi from '@/api/bpm/definition'
import ProcessInstanceTimeline from '@/views/bpm/processInstance/detail/ProcessInstanceTimeline.vue'
import * as ProcessInstanceApi from '@/api/bpm/processInstance'
import { CandidateStrategy, NodeId } from '@/components/SimpleProcessDesignerV2/src/consts'
import { ApprovalNodeInfo } from '@/api/bpm/processInstance'
import {defaultProps, handleTree} from "@/utils/tree";
import {getSelfCustomerSimpleList} from "@/api/crm/customer";
defineOptions({ name: 'CustomerSuggestionCreate' })
const message = useMessage() // 消息弹窗
const { delView } = useTagsViewStore() // 视图操作
const { push, currentRoute } = useRouter() // 路由
const customerList = ref([] as CustomerApi.CustomerVO[]) // 客户列表
const deptList = ref([] as DeptApi.DeptVO[]) //部门列表
const userList = ref([] as UserApi.UserVO[]) //用户列表
const formLoading = ref(false) // 表单的加载中1修改时的数据加载2提交的按钮禁用
const formData = ref({ //表单数据
customerId:undefined,
feedbackDeptId:undefined,
feedbackUserId:undefined,
feedbackProblem:undefined,
suggestion:undefined
})
const formRules = reactive({ //表单验证规则
customerId: [{ required: true, message: '客户不能为空', trigger: 'blur' }],
feedbackDeptId: [{ required: true, message: '反馈部门不能为空', trigger: 'blur' }],
feedbackUserId: [{ required: true, message: '反馈人不能为空', trigger: 'blur' }],
feedbackProblem: [{ required: true, message: '反馈问题不能为空', trigger: 'change' }],
suggestion: [{ required: true, message: '建议不能为空', trigger: 'change' }]
})
const formRef = ref() // 表单 Ref
// 审批相关:变量
const processDefineKey = 'crm_suggestion' // 流程定义 Key
const startUserSelectTasks = ref([]) // 发起人需要选择审批人的用户任务列表
const startUserSelectAssignees = ref({}) // 发起人选择审批人的数据
const tempStartUserSelectAssignees = ref({}) // 历史发起人选择审批人的数据,用于每次表单变更时,临时保存
const activityNodes = ref<ProcessInstanceApi.ApprovalNodeInfo[]>([]) // 审批节点信息
const processDefinitionId = ref('')
/** 提交表单 */
const submitForm = async () => {
// 1.1 校验表单
if (!formRef) return
const valid = await formRef.value.validate()
if (!valid) return
// 1.2 审批相关:校验指定审批人
if (startUserSelectTasks.value?.length > 0) {
for (const userTask of startUserSelectTasks.value) {
if (
Array.isArray(startUserSelectAssignees.value[userTask.id]) &&
startUserSelectAssignees.value[userTask.id].length === 0
) {
return message.warning(`请选择${userTask.name}的审批人`)
}
}
}
// 2. 提交请求
formLoading.value = true
try {
const data = { ...formData.value } as unknown as CustomerSuggestionApi.CustomerSuggestionVO
// 审批相关:设置指定审批人
if (startUserSelectTasks.value?.length > 0) {
data.startUserSelectAssignees = startUserSelectAssignees.value
}
await CustomerSuggestionApi.createCustomerSuggestion(data)
message.success('发起成功')
// 关闭当前 Tab
delView(unref(currentRoute))
await push({ name: 'CustomerSuggestion' })
} finally {
formLoading.value = false
}
}
/** 审批相关:获取审批详情 */
const getApprovalDetail = async () => {
try {
const data = await ProcessInstanceApi.getApprovalDetail({
processDefinitionId: processDefinitionId.value,
// TODO 小北:可以支持 processDefinitionKey 查询
activityId: NodeId.START_USER_NODE_ID
})
if (!data) {
message.error('查询不到审批详情信息!')
return
}
// 获取审批节点,显示 Timeline 的数据
activityNodes.value = data.activityNodes
// 获取发起人自选的任务
startUserSelectTasks.value = data.activityNodes?.filter(
(node: ApprovalNodeInfo) => CandidateStrategy.START_USER_SELECT === node.candidateStrategy
)
// 恢复之前的选择审批人
if (startUserSelectTasks.value?.length > 0) {
for (const node of startUserSelectTasks.value) {
if (
tempStartUserSelectAssignees.value[node.id] &&
tempStartUserSelectAssignees.value[node.id].length > 0
) {
startUserSelectAssignees.value[node.id] = tempStartUserSelectAssignees.value[node.id]
} else {
startUserSelectAssignees.value[node.id] = []
}
}
}
} finally {
}
}
/** 审批相关:选择发起人 */
const selectUserConfirm = (id: string, userList: any[]) => {
startUserSelectAssignees.value[id] = userList?.map((item: any) => item.id)
}
/** 选择部门后,查询用户列表 */
const getSimpleUserList = async () => {
// 清空 feedbackUserId 的值
formData.value.feedbackUserId = undefined;
const feedbackDeptId = formData.value.feedbackDeptId;
if (feedbackDeptId) {
// 加载用户
userList.value = await UserApi.getSimpleUserList(feedbackDeptId);
} else {
userList.value = [];
}
}
/** 初始化 */
onMounted(async () => {
// TODO @小北:这里可以简化,统一通过 getApprovalDetail 处理么?
const processDefinitionDetail = await DefinitionApi.getProcessDefinition(
undefined,
processDefineKey
)
if (!processDefinitionDetail) {
message.error('流程模型未配置,请检查!')
return
}
processDefinitionId.value = processDefinitionDetail.id
startUserSelectTasks.value = processDefinitionDetail.startUserSelectTasks
// 审批相关:加载最新的审批详情,主要用于节点预测
await getApprovalDetail()
// 查询客户列表
customerList.value = await CustomerApi.getSelfCustomerSimpleList()
// 加载部门树
deptList.value = handleTree(await DeptApi.getSimpleDeptList())
})
/** 审批相关:预测流程节点会因为输入的参数值而产生新的预测结果值,所以需重新预测一次, formData.value可改成实际业务中的特定字段 */
watch(
formData.value,
(newValue, oldValue) => {
if (!oldValue) {
return
}
if (newValue && Object.keys(newValue).length > 0) {
// 记录之前的节点审批人
tempStartUserSelectAssignees.value = startUserSelectAssignees.value
startUserSelectAssignees.value = {}
// 加载最新的审批详情,主要用于节点预测
getApprovalDetail()
}
},
{
immediate: true
}
)
</script>