Files
iotlcm/app/src/pages/business/views/workOrderCreate/index.vue
T

253 lines
8.7 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<script lang="ts" setup>
import { createWorkOrder } from '../api/workOrder'
import RouterPath from '@/constant/RouterPath'
import { useUserStore } from '@/store/user'
import WorkOrderAttachments from '@/components/WorkOrderAttachments.vue'
import { hasAnyFeature } from '@/utils/permission'
definePage({
style: {
navigationBarTitleText: '提交工单',
},
})
const problemTypes = [
{ label: '卡片问题', value: 0 },
{ label: '模组问题', value: 1 },
{ label: '设备问题', value: 2 },
{ label: '订单问题', value: 3 },
{ label: '余额问题', value: 4 },
{ label: '提现问题', value: 5 },
]
const userStore = useUserStore()
const noPermission = ref(false)
const submitting = ref(false)
const submitted = ref(false)
const uploading = ref(false)
const attachmentUrls = ref<string[]>([])
const relatedId = ref<number>()
const typePickerOpen = ref(false)
const canCreateWorkOrder = computed(() => hasAnyFeature(userStore.userInfo, 'workorder:create'))
const formData = reactive({
woType: [0],
title: '',
content: '',
creatorPhone: userStore.userInfo?.phone || '',
})
onLoad((query) => {
const type = Number(query?.woType)
const id = Number(query?.relatedId)
if ([0, 3].includes(type) && Number.isSafeInteger(id) && id > 0) {
formData.woType = [type]
relatedId.value = id
formData.content = String(query?.context || '').slice(0, 500)
}
})
const typeText = computed(() => {
const value = Number(formData.woType[0] ?? 0)
return problemTypes.find(item => item.value === value)?.label || '卡片问题'
})
function openTypePicker() {
if (relatedId.value || submitting.value || submitted.value)
return
typePickerOpen.value = true
}
async function handleSubmit() {
if (submitting.value || submitted.value || uploading.value)
return
if (!canCreateWorkOrder.value) {
uni.showToast({ title: '暂无提交工单权限', icon: 'none' })
return
}
const title = formData.title.trim()
const content = formData.content.trim()
const creatorPhone = formData.creatorPhone.trim()
const woType = Number(formData.woType[0])
if (!problemTypes.some(item => item.value === woType)) {
uni.showToast({ title: '请选择有效的工单类型', icon: 'none' })
return
}
if (!title) {
uni.showToast({ title: '请输入工单标题', icon: 'none' })
return
}
if (!content) {
uni.showToast({ title: '请输入问题描述', icon: 'none' })
return
}
if (!/^1[3-9]\d{9}$/.test(creatorPhone)) {
uni.showToast({ title: creatorPhone ? '请输入正确的手机号' : '请输入创建人手机号', icon: 'none' })
return
}
submitting.value = true
try {
const res = await createWorkOrder({
woType,
title,
content,
creatorPhone,
attachmentUrls: attachmentUrls.value,
relatedId: relatedId.value,
})
const woNo = res.workOrder?.woNo || ''
submitted.value = true
uni.showToast({ title: '工单已提交', icon: 'success' })
setTimeout(() => {
if (woNo && hasAnyFeature(userStore.userInfo, 'workorder:detail')) {
uni.redirectTo({
url: `${RouterPath.BusinessViewsWorkOrderDetail}?woNo=${encodeURIComponent(woNo)}`,
fail: () => uni.navigateBack({ fail: () => uni.switchTab({ url: RouterPath.Business }) }),
})
}
else {
uni.navigateBack({ fail: () => uni.switchTab({ url: RouterPath.Business }) })
}
}, 500)
}
catch (error) {
uni.showToast({ title: getErrorMessage(error, '工单提交失败'), icon: 'none' })
}
finally {
submitting.value = false
}
}
function getErrorMessage(error: unknown, fallback: string) {
if (error && typeof error === 'object') {
const data = error as { msg?: unknown, message?: unknown, errMsg?: unknown }
if (typeof data.msg === 'string' && data.msg)
return data.msg
if (typeof data.message === 'string' && data.message)
return data.message
if (typeof data.errMsg === 'string' && data.errMsg)
return data.errMsg
}
if (error instanceof Error && error.message)
return error.message
return fallback
}
onMounted(async () => {
await userStore.fetchUserInfo().catch(() => undefined)
if (!formData.creatorPhone)
formData.creatorPhone = userStore.userInfo?.phone || ''
if (!canCreateWorkOrder.value) {
noPermission.value = true
uni.showToast({ title: '当前账号不能提交工单', icon: 'none' })
}
})
</script>
<template>
<view class="min-h-screen bg-#f5f7fa p-24rpx pb-48rpx">
<view class="mx-auto max-w-920rpx flex flex-col gap-20rpx">
<wd-card v-if="noPermission" custom-class="!mx-0 !mb-0">
<view class="text-26rpx text-#64748b leading-38rpx">
当前账号不能提交工单。
</view>
</wd-card>
<template v-else>
<wd-card custom-class="!mx-0 !mb-0">
<view class="flex items-start gap-16rpx">
<view class="h-64rpx w-64rpx center shrink-0 rounded-20rpx bg-#eff6ff text-#2563eb">
<view class="i-carbon-chat text-36rpx" />
</view>
<view class="min-w-0 flex-1">
<text class="block text-34rpx text-#111827 font-700">提交工单</text>
<text class="mt-8rpx block text-24rpx text-#64748b leading-36rpx">
提交后由服务部门跟进,可在工单详情查看进度
</text>
</view>
</view>
</wd-card>
<wd-form :model="formData" error-type="toast">
<view class="flex flex-col gap-20rpx">
<wd-card custom-class="!mx-0 !mb-0" custom-content-class="!p-0">
<template #title>
<view class="h-88rpx flex items-center justify-between">
<text class="text-28rpx text-#0f172a font-600">基础信息</text>
<wd-tag type="primary" variant="plain">
{{ typeText }}
</wd-tag>
</view>
</template>
<wd-cell-group :border="false">
<wd-cell
title="工单类型"
:value="typeText"
:label="relatedId ? '已关联业务,类型不可更改' : '请选择本次工单的问题分类'"
:is-link="!relatedId && !submitting && !submitted"
center
custom-title-class="!text-28rpx !text-#334155"
custom-value-class="!text-26rpx !text-#2563eb"
@click="openTypePicker"
/>
<wd-form-item title="工单标题" prop="title" required title-width="96px" custom-title-class="!text-28rpx !text-#334155">
<wd-input
v-model="formData.title"
:disabled="submitting || submitted"
placeholder="请输入简短标题"
:maxlength="100"
compact
clearable
/>
</wd-form-item>
<wd-form-item title="创建人手机号" prop="creatorPhone" required title-width="96px" custom-title-class="!text-28rpx !text-#334155">
<wd-input
v-model="formData.creatorPhone"
:disabled="submitting || submitted"
type="number"
placeholder="请输入创建人手机号"
:maxlength="11"
compact
clearable
/>
</wd-form-item>
</wd-cell-group>
</wd-card>
<wd-card custom-class="!mx-0 !mb-0">
<template #title>
<view class="h-88rpx flex items-center">
<text class="text-28rpx text-#0f172a font-600">问题描述</text>
</view>
</template>
<wd-textarea
v-model="formData.content"
:disabled="submitting || submitted"
placeholder="请描述问题现象、发生时间和已尝试的处理方式"
:maxlength="2000"
show-word-limit
/>
<view class="mt-20rpx">
<WorkOrderAttachments v-model="attachmentUrls" :disabled="submitting || submitted" @uploading="uploading = $event" />
</view>
</wd-card>
</view>
</wd-form>
<wd-button block type="primary" :round="false" :loading="submitting" :disabled="!canCreateWorkOrder || submitting || uploading || submitted" @click="handleSubmit">
提交工单
</wd-button>
</template>
</view>
<wd-picker
v-model="formData.woType"
v-model:visible="typePickerOpen"
title="选择工单类型"
:columns="[problemTypes]"
value-key="value"
label-key="label"
/>
</view>
</template>