Files
mom-web/src/views/erp/aftersale/aftersaleprocess/AfterSaleProcessForm.vue
2026-03-14 13:51:02 +08:00

408 lines
13 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.

<template>
<Dialog :title="dialogTitle" v-model="dialogVisible">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="100px"
v-loading="formLoading"
>
<el-form-item label="售后登记" prop="afterSaleId">
<el-input
v-model="selectedRegisterLabel"
placeholder="请选择已审核通过的售后登记"
readonly
@click="openRegisterSelector"
style="cursor: pointer"
>
<template #append>
<el-button :icon="Search" @click="openRegisterSelector" />
</template>
</el-input>
</el-form-item>
<el-form-item label="处理类型" prop="processType">
<el-select v-model="formData.processType" placeholder="请选择处理类型" filterable>
<el-option
v-for="item in processTypeOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item label="处理数量" prop="processCount">
<el-input-number v-model="formData.processCount" :min="0" class="!w-full" />
</el-form-item>
<el-form-item label="处理结果" prop="processResult">
<el-input v-model="formData.processResult" placeholder="请输入处理结果" />
</el-form-item>
<el-form-item label="处理凭证" prop="processEvidence">
<UploadImgs v-model="processEvidenceList" :limit="5" />
</el-form-item>
<el-form-item label="业务订单" prop="relatedOrderId">
<el-input v-model="formData.relatedOrderId" placeholder="请输入业务订单" />
</el-form-item>
<el-form-item label="处理人" prop="processUser">
<el-input v-model="formData.processUser" placeholder="请输入处理人" />
</el-form-item>
<el-form-item label="时间" prop="processTime">
<el-date-picker
v-model="formData.processTime as any"
type="datetime"
value-format="YYYY-MM-DD HH:mm:ss"
placeholder="选择时间"
/>
</el-form-item>
<el-form-item v-if="formData.processStatus === 2" label="处理完成时间" prop="finishTime">
<el-date-picker
v-model="formData.finishTime as any"
type="datetime"
value-format="YYYY-MM-DD HH:mm:ss"
placeholder="选择处理完成时间"
/>
</el-form-item>
<el-form-item label="评价" prop="userRating">
<el-rate
v-model="formData.userRating"
:max="10"
class="!w-full"
/>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
<!-- 售后登记选择弹窗 -->
<Dialog v-model="registerSelectorVisible" title="选择售后登记" width="70%" :appendToBody="true">
<ContentWrap>
<el-form
ref="registerQueryFormRef"
:inline="true"
:model="registerQueryParams"
class="-mb-15px"
label-width="100px"
>
<el-form-item label="售后类型" prop="afterSaleType">
<el-select
v-model="registerQueryParams.afterSaleType"
placeholder="请选择售后类型"
clearable
class="!w-200px"
>
<el-option
v-for="item in afterSaleTypeOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item label="销售订单ID" prop="orderId">
<el-input
v-model="registerQueryParams.orderId"
class="!w-200px"
clearable
placeholder="请输入销售订单ID"
@keyup.enter="handleRegisterQuery"
/>
</el-form-item>
<el-form-item>
<el-button @click="handleRegisterQuery">
<Icon class="mr-5px" icon="ep:search" />
搜索
</el-button>
<el-button @click="resetRegisterQuery">
<Icon class="mr-5px" icon="ep:refresh" />
重置
</el-button>
</el-form-item>
</el-form>
<el-table v-loading="registerLoading" :data="registerList" show-overflow-tooltip>
<el-table-column label="#" width="55">
<template #default="{ row }">
<el-radio :value="row.id" v-model="selectedRegisterId" @change="handleRegisterSelected(row)">
&nbsp;
</el-radio>
</template>
</el-table-column>
<el-table-column label="登记ID" align="center" prop="id" width="100" />
<el-table-column label="销售订单ID" align="center" prop="orderId" width="120" />
<el-table-column label="售后类型" align="center" prop="afterSaleType" width="120">
<template #default="{ row }">
{{ formatAfterSaleType(row.afterSaleType) }}
</template>
</el-table-column>
<el-table-column label="申请原因" align="center" prop="applyReason" min-width="150" />
<el-table-column label="申请人" align="center" prop="applicant" width="100" />
<el-table-column
label="创建时间"
align="center"
prop="createTime"
:formatter="dateFormatter"
width="160px"
/>
</el-table>
<Pagination
v-model:limit="registerQueryParams.pageSize"
v-model:page="registerQueryParams.pageNo"
:total="registerTotal"
@pagination="getRegisterList"
/>
</ContentWrap>
</Dialog>
</template>
<script setup lang="ts">
import { Search } from '@element-plus/icons-vue'
import dayjs from 'dayjs'
import { dateFormatter } from '@/utils/formatTime'
import { AfterSaleProcessApi, AfterSaleProcess } from '@/api/erp/aftersale/aftersaleprocess'
import { AfterSaleRegisterApi, AfterSaleRegister } from '@/api/erp/aftersale/aftersaleregister'
import { useUserStoreWithOut } from '@/store/modules/user'
/** ERP 售后处理 表单 */
defineOptions({ name: 'AfterSaleProcessForm' })
const processTypeOptions = [
{ label: '退货入库', value: 1 },
{ label: '换货出库', value: 2 },
{ label: '维修处理', value: 3 },
{ label: '退款处理', value: 4 },
{ label: '取消处理', value: 5 },
{ label: '其他', value: 6 }
]
const processStatusOptions = [
{ label: '退换货', value: 1 },
{ label: '维修申请', value: 2 },
{ label: '售后评价', value: 3 }
]
const processEvidenceList = ref<string[]>([])
// 售后登记选择器相关
const registerSelectorVisible = ref(false)
const selectedRegisterId = ref<number>()
const selectedRegisterLabel = ref<string>('')
const registerLoading = ref(false)
const registerList = ref<AfterSaleRegister[]>([])
const registerTotal = ref(0)
const registerQueryParams = ref({
pageNo: 1,
pageSize: 10,
applyStatus: 2, // 仅已审核通过
afterSaleType: undefined,
orderId: undefined
})
const registerQueryFormRef = ref()
const afterSaleTypeOptions = [
{ label: '退货', value: 1 },
{ label: '换货', value: 2 },
{ label: '维修', value: 3 },
{ label: '退款', value: 4 }
]
/** 打开售后登记选择器 */
const openRegisterSelector = () => {
registerSelectorVisible.value = true
registerQueryParams.value = {
pageNo: 1,
pageSize: 10,
applyStatus: 2,
afterSaleType: undefined,
orderId: undefined
}
getRegisterList()
}
/** 查询售后登记列表 */
const getRegisterList = async () => {
registerLoading.value = true
try {
const data = await AfterSaleRegisterApi.getAfterSaleRegisterPage(registerQueryParams.value)
registerList.value = data.list
registerTotal.value = data.total
} finally {
registerLoading.value = false
}
}
/** 搜索售后登记 */
const handleRegisterQuery = () => {
registerQueryParams.value.pageNo = 1
getRegisterList()
}
/** 重置售后登记查询 */
const resetRegisterQuery = () => {
registerQueryParams.value = {
pageNo: 1,
pageSize: 10,
applyStatus: 2,
afterSaleType: undefined,
orderId: undefined
}
getRegisterList()
}
/** 选中售后登记 */
const handleRegisterSelected = (row: AfterSaleRegister) => {
formData.value.afterSaleId = row.id
selectedRegisterLabel.value = `登记 #${row.id}(订单 ${row.orderId || '-'}`
selectedRegisterId.value = row.id
registerSelectorVisible.value = false
}
/** 格式化售后类型 */
const formatAfterSaleType = (value?: number) => {
if (!value) return '-'
const match = afterSaleTypeOptions.find(item => item.value === value)
return match?.label || String(value)
}
const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗
const userStore = useUserStoreWithOut()
const currentUserNickname = computed(() => userStore.getUser?.nickname || '')
const nowString = () => dayjs().format('YYYY-MM-DD HH:mm:ss')
const dialogVisible = ref(false) // 弹窗的是否展示
const dialogTitle = ref('') // 弹窗的标题
const formLoading = ref(false) // 表单的加载中1修改时的数据加载2提交的按钮禁用
const formType = ref('') // 表单的类型create - 新增update - 修改
const formData = ref<Partial<AfterSaleProcess>>({
id: undefined,
afterSaleId: undefined,
processType: undefined,
processCount: undefined,
processResult: undefined,
processEvidence: '',
relatedOrderId: undefined,
processStatus: undefined,
processFailReason: undefined,
processUser: undefined,
processTime: undefined,
finishTime: undefined,
userRating: undefined
})
const formRules = reactive({
afterSaleId: [{ required: true, message: '售后登记不能为空', trigger: 'change' }],
processType: [{ required: true, message: '处理类型不能为空', trigger: 'change' }],
processResult: [{ required: true, message: '处理结果不能为空', trigger: 'blur' }]
})
const formRef = ref() // 表单 Ref
// 同步处理凭证列表和表单数据
watch(
() => formData.value.processEvidence,
(newVal: string) => {
processEvidenceList.value = newVal ? newVal.split(',').filter(url => url.trim()) : []
},
{ immediate: true }
)
watch(
processEvidenceList,
(newList: string[]) => {
formData.value.processEvidence = newList?.length ? newList.join(',') : ''
},
{ deep: true }
)
/** 打开弹窗 */
const open = async (type: string, id?: number) => {
dialogVisible.value = true
dialogTitle.value = t('action.' + type)
formType.value = type
resetForm()
// 修改时,设置数据
if (id) {
formLoading.value = true
try {
formData.value = await AfterSaleProcessApi.getAfterSaleProcess(id)
// 如果有售后登记ID获取登记信息显示
if (formData.value.afterSaleId) {
const register = await AfterSaleRegisterApi.getAfterSaleRegister(formData.value.afterSaleId)
selectedRegisterLabel.value = `登记 #${register.id}(订单 ${register.orderId || '-'}`
selectedRegisterId.value = register.id
}
ensureDefaultsForExisting()
} finally {
formLoading.value = false
}
}
}
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
/** 提交表单 */
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
const submitForm = async () => {
// 校验表单
await formRef.value.validate()
// 提交请求
formLoading.value = true
try {
let data = formData.value as unknown as AfterSaleProcess
// 如果上传了处理凭证,自动设置为处理完成状态
if (data.processEvidence && data.processEvidence.trim() !== '') {
data = {
...data,
processStatus: 2, // 处理完成
finishTime: nowString()
}
}
if (formType.value === 'create') {
await AfterSaleProcessApi.createAfterSaleProcess(data)
message.success(t('common.createSuccess'))
} else {
await AfterSaleProcessApi.updateAfterSaleProcess(data)
message.success(t('common.updateSuccess'))
}
dialogVisible.value = false
// 发送操作成功的事件
emit('success')
} finally {
formLoading.value = false
}
}
/** 重置表单 */
const resetForm = () => {
formData.value = {
id: undefined,
afterSaleId: undefined,
processType: undefined,
processCount: undefined,
processResult: undefined,
processEvidence: '',
relatedOrderId: undefined,
processStatus: 1, // 新增时默认为处理中状态
processFailReason: undefined,
processUser: currentUserNickname.value || undefined,
processTime: nowString(),
finishTime: undefined,
userRating: undefined
}
selectedRegisterLabel.value = ''
selectedRegisterId.value = undefined
formRef.value?.resetFields()
}
const ensureDefaultsForExisting = () => {
if (!formData.value.processUser) {
formData.value.processUser = currentUserNickname.value || undefined
}
if (!formData.value.processTime) {
formData.value.processTime = nowString()
}
if (formData.value.processStatus === 2 && !formData.value.finishTime) {
formData.value.finishTime = nowString()
}
}
</script>