web工单处理
This commit is contained in:
@@ -0,0 +1 @@
|
||||
export { default as WorkcaseAssign } from './workcase/WorkcaseAssign.vue'
|
||||
|
||||
@@ -0,0 +1,245 @@
|
||||
<template>
|
||||
<ElDialog
|
||||
v-model="visible"
|
||||
:title="dialogTitle"
|
||||
width="500px"
|
||||
@close="handleClose"
|
||||
>
|
||||
<div class="assign-form">
|
||||
<div class="form-item">
|
||||
<label class="form-label">选择工程师 <span class="required">*</span></label>
|
||||
<ElSelect
|
||||
v-model="form.processor"
|
||||
placeholder="请选择工程师"
|
||||
style="width: 100%;"
|
||||
filterable
|
||||
:loading="loadingEngineers"
|
||||
>
|
||||
<ElOption
|
||||
v-for="engineer in availableEngineers"
|
||||
:key="engineer.userId"
|
||||
:label="`${engineer.username} (${engineer.statusName || '未知状态'})`"
|
||||
:value="engineer.userId"
|
||||
>
|
||||
<div style="display: flex; justify-content: space-between; align-items: center;">
|
||||
<span>{{ engineer.username }}</span>
|
||||
<span style="color: #999; font-size: 12px;">
|
||||
{{ engineer.statusName }} | 当前{{ engineer.currentWorkload || 0 }}单
|
||||
</span>
|
||||
</div>
|
||||
</ElOption>
|
||||
</ElSelect>
|
||||
</div>
|
||||
<div class="form-item" style="margin-top: 16px;">
|
||||
<label class="form-label">备注说明(可选)</label>
|
||||
<ElInput
|
||||
v-model="form.message"
|
||||
type="textarea"
|
||||
:rows="3"
|
||||
placeholder="请输入指派/转派说明..."
|
||||
maxlength="200"
|
||||
/>
|
||||
</div>
|
||||
<div class="form-item" style="margin-top: 16px;">
|
||||
<label class="form-label">附件(可选)</label>
|
||||
<FileUpload
|
||||
ref="fileUploadRef"
|
||||
mode="content"
|
||||
:max-count="5"
|
||||
:max-size="10 * 1024 * 1024"
|
||||
accept="image/*,.pdf,.doc,.docx,.xls,.xlsx"
|
||||
:auto-upload="false"
|
||||
:custom-upload="handleFilesUpload"
|
||||
@upload-error="handleUploadError"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<template #footer>
|
||||
<ElButton @click="handleClose">取消</ElButton>
|
||||
<ElButton type="primary" @click="handleSubmit" :loading="submitting">确定</ElButton>
|
||||
</template>
|
||||
</ElDialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, watch } from 'vue'
|
||||
import { ElDialog, ElButton, ElInput, ElSelect, ElOption, ElMessage } from 'element-plus'
|
||||
import { FileUpload } from 'shared/components'
|
||||
import { fileAPI } from 'shared/api'
|
||||
import { workcaseAPI } from '@/api/workcase'
|
||||
import { workcaseChatAPI } from '@/api/workcase/workcaseChat'
|
||||
import type { TbWorkcaseProcessDTO } from '@/types/workcase/workcase'
|
||||
import type { CustomerServiceVO } from '@/types/workcase/customer'
|
||||
import type { TbSysFileDTO } from 'shared/types'
|
||||
|
||||
interface Props {
|
||||
/** 是否显示弹窗 */
|
||||
modelValue: boolean
|
||||
/** 工单ID */
|
||||
workcaseId: string
|
||||
/** 当前处理人ID(转派时排除) */
|
||||
currentProcessor?: string
|
||||
/** 操作类型:assign-指派,redeploy-转派 */
|
||||
action?: 'assign' | 'redeploy'
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
currentProcessor: '',
|
||||
action: 'assign'
|
||||
})
|
||||
|
||||
const emit = defineEmits<{
|
||||
'update:modelValue': [value: boolean]
|
||||
'success': []
|
||||
}>()
|
||||
|
||||
// 弹窗显示状态
|
||||
const visible = computed({
|
||||
get: () => props.modelValue,
|
||||
set: (val) => emit('update:modelValue', val)
|
||||
})
|
||||
|
||||
// 弹窗标题
|
||||
const dialogTitle = computed(() => {
|
||||
return props.action === 'assign' ? '指派工程师' : '转派工程师'
|
||||
})
|
||||
|
||||
// 表单数据
|
||||
const form = ref({
|
||||
processor: '',
|
||||
message: '',
|
||||
fileIds: [] as string[]
|
||||
})
|
||||
|
||||
// 状态
|
||||
const submitting = ref(false)
|
||||
const loadingEngineers = ref(false)
|
||||
const availableEngineers = ref<CustomerServiceVO[]>([])
|
||||
const fileUploadRef = ref<InstanceType<typeof FileUpload>>()
|
||||
|
||||
// 监听弹窗打开,加载工程师列表
|
||||
watch(visible, async (val) => {
|
||||
if (val) {
|
||||
// 重置表单
|
||||
form.value = { processor: '', message: '', fileIds: [] }
|
||||
if (fileUploadRef.value) {
|
||||
fileUploadRef.value.clearFiles()
|
||||
}
|
||||
// 加载工程师列表
|
||||
await loadAvailableEngineers()
|
||||
}
|
||||
})
|
||||
|
||||
// 加载可用工程师列表
|
||||
const loadAvailableEngineers = async () => {
|
||||
loadingEngineers.value = true
|
||||
try {
|
||||
const res = await workcaseChatAPI.getCustomerServicePage({
|
||||
filter: {},
|
||||
pageParam: { page: 1, pageSize: 100 }
|
||||
})
|
||||
if (res.success && res.dataList) {
|
||||
// 排除当前处理人
|
||||
availableEngineers.value = res.dataList.filter(
|
||||
(engineer: CustomerServiceVO) => engineer.userId !== props.currentProcessor
|
||||
)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('加载工程师列表失败:', error)
|
||||
ElMessage.error('加载工程师列表失败')
|
||||
} finally {
|
||||
loadingEngineers.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 自定义文件上传
|
||||
const handleFilesUpload = async (files: File[]): Promise<TbSysFileDTO[]> => {
|
||||
const uploadedFiles: TbSysFileDTO[] = []
|
||||
for (const file of files) {
|
||||
const result = await fileAPI.uploadFile({
|
||||
file,
|
||||
module: 'workcase',
|
||||
optsn: props.workcaseId
|
||||
})
|
||||
if (result.success && result.data) {
|
||||
uploadedFiles.push(result.data)
|
||||
if (result.data.fileId) {
|
||||
form.value.fileIds.push(result.data.fileId)
|
||||
}
|
||||
} else {
|
||||
throw new Error(`文件 ${file.name} 上传失败`)
|
||||
}
|
||||
}
|
||||
return uploadedFiles
|
||||
}
|
||||
|
||||
// 上传错误处理
|
||||
const handleUploadError = (error: string) => {
|
||||
ElMessage.error(error)
|
||||
}
|
||||
|
||||
// 提交
|
||||
const handleSubmit = async () => {
|
||||
if (!form.value.processor) {
|
||||
ElMessage.warning('请选择工程师')
|
||||
return
|
||||
}
|
||||
|
||||
if (!props.workcaseId) {
|
||||
ElMessage.error('工单ID不存在')
|
||||
return
|
||||
}
|
||||
|
||||
submitting.value = true
|
||||
try {
|
||||
// 如果有待上传的文件,先上传
|
||||
if (fileUploadRef.value?.selectedFiles?.length > 0) {
|
||||
await fileUploadRef.value.uploadFiles()
|
||||
}
|
||||
|
||||
const params: TbWorkcaseProcessDTO = {
|
||||
workcaseId: props.workcaseId,
|
||||
action: props.action,
|
||||
processor: form.value.processor,
|
||||
message: form.value.message || (props.action === 'assign' ? '工单指派' : '工单转派'),
|
||||
files: form.value.fileIds.length > 0 ? form.value.fileIds : undefined
|
||||
}
|
||||
|
||||
const res = await workcaseAPI.createWorkcaseProcess(params)
|
||||
if (res.success) {
|
||||
ElMessage.success(props.action === 'assign' ? '指派成功' : '转派成功')
|
||||
visible.value = false
|
||||
emit('success')
|
||||
} else {
|
||||
ElMessage.error(res.message || '操作失败')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('指派/转派失败:', error)
|
||||
ElMessage.error('操作失败')
|
||||
} finally {
|
||||
submitting.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 关闭弹窗
|
||||
const handleClose = () => {
|
||||
visible.value = false
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.assign-form {
|
||||
.form-item {
|
||||
.form-label {
|
||||
display: block;
|
||||
margin-bottom: 8px;
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
|
||||
.required {
|
||||
color: #f56c6c;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user