|
@@ -9,7 +9,6 @@
|
|
|
:body-style="{ padding: '20px' }"
|
|
:body-style="{ padding: '20px' }"
|
|
|
>
|
|
>
|
|
|
<el-row :gutter="20">
|
|
<el-row :gutter="20">
|
|
|
- <!-- Left Column: Form -->
|
|
|
|
|
<el-col :span="14" class="border-r border-gray-200 pr-5">
|
|
<el-col :span="14" class="border-r border-gray-200 pr-5">
|
|
|
<ProForm
|
|
<ProForm
|
|
|
ref="proFormRef"
|
|
ref="proFormRef"
|
|
@@ -24,421 +23,287 @@
|
|
|
<ImageUpload
|
|
<ImageUpload
|
|
|
v-model="proForm.model.fileList"
|
|
v-model="proForm.model.fileList"
|
|
|
:limit="5"
|
|
:limit="5"
|
|
|
|
|
+ :disabled="isReadonly"
|
|
|
/>
|
|
/>
|
|
|
</template>
|
|
</template>
|
|
|
</ProForm>
|
|
</ProForm>
|
|
|
</el-col>
|
|
</el-col>
|
|
|
-
|
|
|
|
|
- <!-- Right Column: Info & Timeline -->
|
|
|
|
|
<el-col :span="10" class="pl-2">
|
|
<el-col :span="10" class="pl-2">
|
|
|
<TrackingTimeline :logs="logs" />
|
|
<TrackingTimeline :logs="logs" />
|
|
|
</el-col>
|
|
</el-col>
|
|
|
</el-row>
|
|
</el-row>
|
|
|
-
|
|
|
|
|
<template #footer>
|
|
<template #footer>
|
|
|
<div class="flex justify-center space-x-4">
|
|
<div class="flex justify-center space-x-4">
|
|
|
- <el-button
|
|
|
|
|
- type="warning"
|
|
|
|
|
- plain
|
|
|
|
|
- @click="handleFollowUp"
|
|
|
|
|
- v-if="form.id"
|
|
|
|
|
- >待跟进</el-button
|
|
|
|
|
- >
|
|
|
|
|
- <el-button
|
|
|
|
|
- type="success"
|
|
|
|
|
- plain
|
|
|
|
|
- @click="handleFeedback"
|
|
|
|
|
- v-if="form.id"
|
|
|
|
|
- >反馈</el-button
|
|
|
|
|
- >
|
|
|
|
|
|
|
+ <template v-if="form.id && !isReadonly">
|
|
|
|
|
+ <el-button type="warning" plain @click="handleFollowUp">待跟进</el-button>
|
|
|
|
|
+ <el-button type="success" plain @click="handleFinish">完成</el-button>
|
|
|
|
|
+ <el-button type="danger" plain @click="openClaimsDialog">一键理赔</el-button>
|
|
|
|
|
+ </template>
|
|
|
<el-button @click="handleClose">取消</el-button>
|
|
<el-button @click="handleClose">取消</el-button>
|
|
|
- <el-button
|
|
|
|
|
- type="primary"
|
|
|
|
|
- @click="handleSubmit"
|
|
|
|
|
- :loading="loading"
|
|
|
|
|
- >保存</el-button
|
|
|
|
|
- >
|
|
|
|
|
|
|
+ <el-button v-if="!isReadonly" type="primary" @click="handleSubmit" :loading="loading">保存</el-button>
|
|
|
</div>
|
|
</div>
|
|
|
</template>
|
|
</template>
|
|
|
</ele-modal>
|
|
</ele-modal>
|
|
|
|
|
+
|
|
|
|
|
+ <ele-modal title="一键理赔" v-model="claimsVisible" width="480px" :close-on-click-modal="false" destroy-on-close>
|
|
|
|
|
+ <el-form ref="claimsFormRef" :model="claimsForm" :rules="claimsRules" label-width="80px">
|
|
|
|
|
+ <el-form-item label="理赔金额" prop="money">
|
|
|
|
|
+ <el-input-number v-model="claimsForm.money" :min="0" :precision="2" class="w-full" controls-position="right" />
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+ <el-form-item label="理赔原因" prop="reason">
|
|
|
|
|
+ <el-input v-model="claimsForm.reason" type="textarea" :rows="4" placeholder="请输入理赔原因" />
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+ </el-form>
|
|
|
|
|
+ <template #footer>
|
|
|
|
|
+ <el-button @click="claimsVisible = false">取消</el-button>
|
|
|
|
|
+ <el-button type="primary" :loading="claimsLoading" @click="submitClaims">确认理赔</el-button>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </ele-modal>
|
|
|
</template>
|
|
</template>
|
|
|
|
|
|
|
|
<script setup>
|
|
<script setup>
|
|
|
- import { ref, reactive, computed, watch, getCurrentInstance } from 'vue';
|
|
|
|
|
|
|
+ import { ref, reactive, computed, getCurrentInstance } from 'vue';
|
|
|
import { ElMessage } from 'element-plus';
|
|
import { ElMessage } from 'element-plus';
|
|
|
import ImageUpload from '@/components/ImageUpload/index.vue';
|
|
import ImageUpload from '@/components/ImageUpload/index.vue';
|
|
|
import ProForm from '@/components/ProForm/index.vue';
|
|
import ProForm from '@/components/ProForm/index.vue';
|
|
|
import TrackingTimeline from './tracking-timeline.vue';
|
|
import TrackingTimeline from './tracking-timeline.vue';
|
|
|
import { pageUsers } from '@/api/system/user';
|
|
import { pageUsers } from '@/api/system/user';
|
|
|
|
|
|
|
|
- const { proxy } = getCurrentInstance();
|
|
|
|
|
|
|
+ const props = defineProps({
|
|
|
|
|
+ orderType: {
|
|
|
|
|
+ type: String,
|
|
|
|
|
+ default: 'sell',
|
|
|
|
|
+ validator: (value) => ['sell', 'recycle'].includes(value)
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
|
|
|
- const emit = defineEmits(['submit', 'success']);
|
|
|
|
|
|
|
+ const defaultOrderType = computed(() => (props.orderType === 'recycle' ? 2 : 1));
|
|
|
|
|
+ const { proxy } = getCurrentInstance();
|
|
|
|
|
+ const emit = defineEmits(['success']);
|
|
|
|
|
|
|
|
const visible = ref(false);
|
|
const visible = ref(false);
|
|
|
const title = ref('工单信息');
|
|
const title = ref('工单信息');
|
|
|
const loading = ref(false);
|
|
const loading = ref(false);
|
|
|
- // Use proFormRef instead of formRef
|
|
|
|
|
|
|
+ const isReadonly = ref(false);
|
|
|
const proFormRef = ref(null);
|
|
const proFormRef = ref(null);
|
|
|
|
|
+ const claimsVisible = ref(false);
|
|
|
|
|
+ const claimsLoading = ref(false);
|
|
|
|
|
+ const claimsFormRef = ref(null);
|
|
|
|
|
+ const claimsForm = reactive({ money: undefined, reason: '' });
|
|
|
|
|
+ const claimsRules = {
|
|
|
|
|
+ money: [{ required: true, message: '请输入理赔金额', trigger: 'blur' }],
|
|
|
|
|
+ reason: [{ required: true, message: '请输入理赔原因', trigger: 'blur' }]
|
|
|
|
|
+ };
|
|
|
|
|
|
|
|
const form = reactive({
|
|
const form = reactive({
|
|
|
id: undefined,
|
|
id: undefined,
|
|
|
taskType: undefined,
|
|
taskType: undefined,
|
|
|
- handleUserId: [], // Changed from undefined to []
|
|
|
|
|
|
|
+ handleUserId: [],
|
|
|
detail: '',
|
|
detail: '',
|
|
|
|
|
+ remark: '',
|
|
|
fileList: '',
|
|
fileList: '',
|
|
|
carrierId: undefined,
|
|
carrierId: undefined,
|
|
|
waybillCode: '',
|
|
waybillCode: '',
|
|
|
inspectionStatus: undefined,
|
|
inspectionStatus: undefined,
|
|
|
orderNo: '',
|
|
orderNo: '',
|
|
|
- type: 1 // 1-卖书 2-收书
|
|
|
|
|
|
|
+ type: 1,
|
|
|
|
|
+ createUserName: '',
|
|
|
|
|
+ createTime: ''
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
const logs = ref([]);
|
|
const logs = ref([]);
|
|
|
const userList = ref([]);
|
|
const userList = ref([]);
|
|
|
const userLoading = ref(false);
|
|
const userLoading = ref(false);
|
|
|
|
|
+ const isEditMode = computed(() => !!form.id);
|
|
|
|
|
+ const fieldDisabled = computed(() => isEditMode.value || isReadonly.value);
|
|
|
|
|
|
|
|
- const rules = {
|
|
|
|
|
- taskType: [
|
|
|
|
|
- { required: true, message: '请选择任务类型', trigger: 'change' }
|
|
|
|
|
- ],
|
|
|
|
|
- handleUserId: [
|
|
|
|
|
- { required: true, message: '请选择指派人', trigger: 'change' }
|
|
|
|
|
- ],
|
|
|
|
|
- detail: [{ required: true, message: '请输入详情', trigger: 'blur' }],
|
|
|
|
|
- inspectionStatus: [
|
|
|
|
|
- { required: true, message: '请选择验货状态', trigger: 'change' }
|
|
|
|
|
- ]
|
|
|
|
|
- };
|
|
|
|
|
|
|
+ const rules = computed(() => {
|
|
|
|
|
+ const base = {
|
|
|
|
|
+ detail: [{ required: !isEditMode.value, message: '请输入详情', trigger: 'blur' }]
|
|
|
|
|
+ };
|
|
|
|
|
+ if (!isEditMode.value) {
|
|
|
|
|
+ base.taskType = [{ required: true, message: '请选择任务类型', trigger: 'change' }];
|
|
|
|
|
+ base.handleUserId = [{ required: true, message: '请选择指派人', trigger: 'change' }];
|
|
|
|
|
+ }
|
|
|
|
|
+ // 新增工单时验货状态必填(卖书/回收都传 inspectionStatus)
|
|
|
|
|
+ if (!isEditMode.value) {
|
|
|
|
|
+ base.inspectionStatus = [{ required: true, message: '请选择验货状态', trigger: 'change' }];
|
|
|
|
|
+ }
|
|
|
|
|
+ return base;
|
|
|
|
|
+ });
|
|
|
|
|
|
|
|
- // Form Items Configuration
|
|
|
|
|
- const formItems = computed(() => [
|
|
|
|
|
- {
|
|
|
|
|
- label: '任务类型',
|
|
|
|
|
- prop: 'taskType',
|
|
|
|
|
- type: 'dictSelect',
|
|
|
|
|
- props: {
|
|
|
|
|
- class: 'w-full',
|
|
|
|
|
- placeholder: '请选择任务类型',
|
|
|
|
|
- code: form.type === 1 ? 'sell_task_type' : 'task_type'
|
|
|
|
|
- }
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- label: '指派给',
|
|
|
|
|
- prop: 'handleUserId',
|
|
|
|
|
- type: 'select',
|
|
|
|
|
- options: userList.value.map((user) => ({
|
|
|
|
|
- label: user.nickName || user.userName,
|
|
|
|
|
- value: user.userId
|
|
|
|
|
- })),
|
|
|
|
|
- props: {
|
|
|
|
|
- class: 'w-full',
|
|
|
|
|
- placeholder: '请选择',
|
|
|
|
|
- filterable: true,
|
|
|
|
|
- remote: true,
|
|
|
|
|
- multiple: true, // Enable multiple selection
|
|
|
|
|
- remoteMethod: searchUsers,
|
|
|
|
|
- loading: userLoading.value
|
|
|
|
|
- }
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- label: '任务详情',
|
|
|
|
|
- prop: 'detail',
|
|
|
|
|
- type: 'textarea',
|
|
|
|
|
- props: { rows: 4, placeholder: '请输入' }
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- label: '图片/附件',
|
|
|
|
|
- prop: 'fileList',
|
|
|
|
|
- type: 'imageUpload',
|
|
|
|
|
- itemType: 'view' // Triggers the slot mechanism
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- label: '承运商',
|
|
|
|
|
- prop: 'carrierId',
|
|
|
|
|
- type: 'dictSelect',
|
|
|
|
|
- props: {
|
|
|
|
|
- class: 'w-full',
|
|
|
|
|
- placeholder: '请选择发货快递',
|
|
|
|
|
- filterable: true,
|
|
|
|
|
- code: 'shop_order_express_name'
|
|
|
|
|
- }
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- label: '发出快递单号',
|
|
|
|
|
- prop: 'waybillCode',
|
|
|
|
|
- type: 'input',
|
|
|
|
|
- props: { placeholder: '请输入' }
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- label: '验货状态',
|
|
|
|
|
- prop: 'inspectionStatus',
|
|
|
|
|
- type: 'dictSelect',
|
|
|
|
|
- props: {
|
|
|
|
|
- class: 'w-full',
|
|
|
|
|
- placeholder: '请选择验货状态',
|
|
|
|
|
- code: 'inspection_status'
|
|
|
|
|
|
|
+ const parseImgInfoToFileList = (imgInfo) => {
|
|
|
|
|
+ if (!imgInfo) return '';
|
|
|
|
|
+ if (imgInfo.imgUrlList && Array.isArray(imgInfo.imgUrlList)) {
|
|
|
|
|
+ return JSON.stringify(imgInfo.imgUrlList);
|
|
|
|
|
+ }
|
|
|
|
|
+ if (imgInfo.imgUrl) {
|
|
|
|
|
+ const raw = imgInfo.imgUrl;
|
|
|
|
|
+ if (typeof raw === 'string') {
|
|
|
|
|
+ try {
|
|
|
|
|
+ const parsed = JSON.parse(raw);
|
|
|
|
|
+ if (Array.isArray(parsed)) return JSON.stringify(parsed);
|
|
|
|
|
+ } catch (e) {}
|
|
|
|
|
+ return JSON.stringify([raw]);
|
|
|
}
|
|
}
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- label: '订单号',
|
|
|
|
|
- prop: 'orderNo',
|
|
|
|
|
- type: 'input',
|
|
|
|
|
- props: { placeholder: '请输入' }
|
|
|
|
|
|
|
+ if (Array.isArray(raw)) return JSON.stringify(raw);
|
|
|
|
|
+ }
|
|
|
|
|
+ return '';
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ const formItems = computed(() => {
|
|
|
|
|
+ const items = [];
|
|
|
|
|
+ if (isEditMode.value) {
|
|
|
|
|
+ items.push(
|
|
|
|
|
+ { label: '创建人', prop: 'createUserName', type: 'input', props: { disabled: true } },
|
|
|
|
|
+ { label: '创建时间', prop: 'createTime', type: 'input', props: { disabled: true } }
|
|
|
|
|
+ );
|
|
|
|
|
+ }
|
|
|
|
|
+ items.push({
|
|
|
|
|
+ label: '任务类型', prop: 'taskType', type: 'dictSelect',
|
|
|
|
|
+ props: { class: 'w-full', placeholder: '请选择任务类型', code: form.type === 1 ? 'sell_task_type' : 'task_type', disabled: fieldDisabled.value }
|
|
|
|
|
+ });
|
|
|
|
|
+ if (!isEditMode.value) {
|
|
|
|
|
+ items.push({
|
|
|
|
|
+ label: '指派给', prop: 'handleUserId', type: 'select',
|
|
|
|
|
+ options: userList.value.map((user) => ({ label: user.nickName || user.userName, value: user.userId })),
|
|
|
|
|
+ props: { class: 'w-full', placeholder: '请选择', filterable: true, remote: true, multiple: true, remoteMethod: searchUsers, loading: userLoading.value, disabled: isReadonly.value }
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+ items.push({ label: '任务详情', prop: 'detail', type: 'textarea', props: { rows: 4, placeholder: '请输入', disabled: fieldDisabled.value } });
|
|
|
|
|
+ if (isEditMode.value) {
|
|
|
|
|
+ items.push({ label: '备注', prop: 'remark', type: 'textarea', props: { rows: 3, placeholder: '请输入备注', disabled: isReadonly.value } });
|
|
|
}
|
|
}
|
|
|
- ]);
|
|
|
|
|
|
|
+ items.push({ label: '图片/附件', prop: 'fileList', type: 'imageUpload', itemType: 'view' });
|
|
|
|
|
+ items.push({ label: '承运商', prop: 'carrierId', type: 'dictSelect', props: { class: 'w-full', placeholder: '请选择发货快递', filterable: true, code: 'shop_order_express_name', disabled: isReadonly.value } });
|
|
|
|
|
+ items.push({ label: '发出快递单号', prop: 'waybillCode', type: 'input', props: { placeholder: '请输入', disabled: fieldDisabled.value } });
|
|
|
|
|
+ // 新增时始终展示验货状态;编辑时卖书工单展示
|
|
|
|
|
+ if (!isEditMode.value || form.type === 1) {
|
|
|
|
|
+ items.push({ label: '验货状态', prop: 'inspectionStatus', type: 'dictSelect', props: { class: 'w-full', placeholder: '请选择验货状态', code: 'inspection_status', disabled: isReadonly.value } });
|
|
|
|
|
+ }
|
|
|
|
|
+ items.push({ label: '订单号', prop: 'orderNo', type: 'input', props: { placeholder: '请输入', disabled: isReadonly.value } });
|
|
|
|
|
+ return items;
|
|
|
|
|
+ });
|
|
|
|
|
|
|
|
- // 搜索用户
|
|
|
|
|
const searchUsers = async (query = '') => {
|
|
const searchUsers = async (query = '') => {
|
|
|
userLoading.value = true;
|
|
userLoading.value = true;
|
|
|
try {
|
|
try {
|
|
|
- const res = await pageUsers({
|
|
|
|
|
- pageNum: 1,
|
|
|
|
|
- pageSize: 50,
|
|
|
|
|
- nickName: query
|
|
|
|
|
- });
|
|
|
|
|
- if (res.code === 200) {
|
|
|
|
|
- userList.value = res.rows || res.data;
|
|
|
|
|
- }
|
|
|
|
|
- } catch (e) {
|
|
|
|
|
- console.error(e);
|
|
|
|
|
- } finally {
|
|
|
|
|
- userLoading.value = false;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ const res = await pageUsers({ pageNum: 1, pageSize: 50, nickName: query });
|
|
|
|
|
+ if (res.code === 200) userList.value = res.rows || res.data;
|
|
|
|
|
+ } catch (e) { console.error(e); } finally { userLoading.value = false; }
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- const handleOpen = async (data = {}) => {
|
|
|
|
|
- visible.value = true;
|
|
|
|
|
- title.value = data.id ? '编辑工单' : '新增工单';
|
|
|
|
|
-
|
|
|
|
|
- // Initialize lists
|
|
|
|
|
- if (userList.value.length === 0) searchUsers();
|
|
|
|
|
-
|
|
|
|
|
- // Reset form
|
|
|
|
|
- Object.assign(form, {
|
|
|
|
|
- id: undefined,
|
|
|
|
|
- taskType: undefined,
|
|
|
|
|
- handleUserId: [], // Reset to empty array
|
|
|
|
|
- detail: '',
|
|
|
|
|
- fileList: '',
|
|
|
|
|
- carrierId: undefined,
|
|
|
|
|
- waybillCode: '',
|
|
|
|
|
- inspectionStatus: undefined,
|
|
|
|
|
- orderNo: '',
|
|
|
|
|
- type: 1 // 1-卖书 2-收书
|
|
|
|
|
- });
|
|
|
|
|
|
|
+ const resetForm = (type) => {
|
|
|
|
|
+ Object.assign(form, { id: undefined, taskType: undefined, handleUserId: [], detail: '', remark: '', fileList: '', carrierId: undefined, waybillCode: '', inspectionStatus: undefined, orderNo: '', type, createUserName: '', createTime: '' });
|
|
|
logs.value = [];
|
|
logs.value = [];
|
|
|
|
|
+ };
|
|
|
|
|
|
|
|
- if (data.id) {
|
|
|
|
|
- loading.value = true;
|
|
|
|
|
- try {
|
|
|
|
|
- // Fetch full details
|
|
|
|
|
- const res = await proxy.$http.get(
|
|
|
|
|
- '/workorder/workorderinfo/getInfo/' + data.id
|
|
|
|
|
- );
|
|
|
|
|
- if (res.data && res.data.code === 200) {
|
|
|
|
|
- const detail = res.data.data;
|
|
|
|
|
-
|
|
|
|
|
- // Map backend data to form
|
|
|
|
|
- form.id = detail.id;
|
|
|
|
|
- form.taskType = String(detail.taskType); // Convert to number
|
|
|
|
|
- form.inspectionStatus = String(detail.inspectionStatus); // Convert to number
|
|
|
|
|
- form.waybillCode = detail.waybillCode;
|
|
|
|
|
-
|
|
|
|
|
- // Map mismatched fields
|
|
|
|
|
- form.detail = detail.deatil; // deatil -> detail
|
|
|
|
|
- form.orderNo = detail.orderId; // orderId -> orderNo
|
|
|
|
|
- form.carrierId = detail.expressType
|
|
|
|
|
- ? String(detail.expressType)
|
|
|
|
|
- : undefined; // expressType -> carrierId (String for dict match)
|
|
|
|
|
-
|
|
|
|
|
- // handleUsers array of objects -> array of IDs
|
|
|
|
|
- if (detail.handleUsers && detail.handleUsers.length > 0) {
|
|
|
|
|
- form.handleUserId = detail.handleUsers.map((user) => {
|
|
|
|
|
- // Ensure user is in list for display
|
|
|
|
|
- if (typeof user === 'object' && user.userId) {
|
|
|
|
|
- if (
|
|
|
|
|
- !userList.value.find(
|
|
|
|
|
- (u) => u.userId === user.userId
|
|
|
|
|
- )
|
|
|
|
|
- ) {
|
|
|
|
|
- userList.value.push(user);
|
|
|
|
|
- }
|
|
|
|
|
- return user.userId;
|
|
|
|
|
- }
|
|
|
|
|
- return user;
|
|
|
|
|
- });
|
|
|
|
|
- } else {
|
|
|
|
|
- form.handleUserId = [];
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // imgInfo object -> fileList JSON string
|
|
|
|
|
- if (
|
|
|
|
|
- detail.imgInfo &&
|
|
|
|
|
- detail.imgInfo.imgUrlList &&
|
|
|
|
|
- Array.isArray(detail.imgInfo.imgUrlList)
|
|
|
|
|
- ) {
|
|
|
|
|
- form.fileList = JSON.stringify(
|
|
|
|
|
- detail.imgInfo.imgUrlList
|
|
|
|
|
- );
|
|
|
|
|
- } else {
|
|
|
|
|
- form.fileList = '';
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // Logs
|
|
|
|
|
- if (detail.changeRecords) {
|
|
|
|
|
- logs.value = detail.changeRecords.map((item) => ({
|
|
|
|
|
- createTime: item.createTime,
|
|
|
|
|
- createName: item.createUserName,
|
|
|
|
|
- content: item.remark
|
|
|
|
|
- }));
|
|
|
|
|
- } else {
|
|
|
|
|
- logs.value = [];
|
|
|
|
|
- }
|
|
|
|
|
- } else {
|
|
|
|
|
- // Fallback mapping if API fails (unlikely to work well but safe)
|
|
|
|
|
- Object.assign(form, data);
|
|
|
|
|
|
|
+ const mapDetailToForm = (detail) => {
|
|
|
|
|
+ form.id = detail.id;
|
|
|
|
|
+ form.type = detail.type ?? defaultOrderType.value;
|
|
|
|
|
+ form.taskType = detail.taskType !== undefined && detail.taskType !== null ? String(detail.taskType) : undefined;
|
|
|
|
|
+ form.inspectionStatus = detail.inspectionStatus !== undefined && detail.inspectionStatus !== null ? String(detail.inspectionStatus) : undefined;
|
|
|
|
|
+ form.waybillCode = detail.waybillCode || '';
|
|
|
|
|
+ form.detail = detail.deatil || '';
|
|
|
|
|
+ form.remark = detail.remark || '';
|
|
|
|
|
+ form.orderNo = detail.orderId || '';
|
|
|
|
|
+ form.carrierId = detail.expressType ? String(detail.expressType) : undefined;
|
|
|
|
|
+ form.createUserName = detail.createUserName || '';
|
|
|
|
|
+ form.createTime = detail.createTime || '';
|
|
|
|
|
+ form.fileList = parseImgInfoToFileList(detail.imgInfo);
|
|
|
|
|
+ if (detail.handleUsers && detail.handleUsers.length > 0) {
|
|
|
|
|
+ form.handleUserId = detail.handleUsers.map((user) => {
|
|
|
|
|
+ if (typeof user === 'object' && user.userId) {
|
|
|
|
|
+ if (!userList.value.find((u) => u.userId === user.userId)) userList.value.push(user);
|
|
|
|
|
+ return user.userId;
|
|
|
}
|
|
}
|
|
|
- } catch (e) {
|
|
|
|
|
- console.error(e);
|
|
|
|
|
- Object.assign(form, data);
|
|
|
|
|
- } finally {
|
|
|
|
|
- loading.value = false;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ return user;
|
|
|
|
|
+ });
|
|
|
|
|
+ } else { form.handleUserId = []; }
|
|
|
|
|
+ if (detail.changeRecords) {
|
|
|
|
|
+ logs.value = detail.changeRecords.map((item) => ({ createTime: item.createTime, createName: item.createUserName, oldContent: item.oldContent, newContent: item.newContent, remark: item.remark }));
|
|
|
|
|
+ } else { logs.value = []; }
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- const handleClose = () => {
|
|
|
|
|
- visible.value = false;
|
|
|
|
|
- // Use proFormRef to reset
|
|
|
|
|
- proFormRef.value?.resetFields();
|
|
|
|
|
|
|
+ const handleOpen = async (data = {}, options = {}) => {
|
|
|
|
|
+ isReadonly.value = !!options.readonly;
|
|
|
|
|
+ visible.value = true;
|
|
|
|
|
+ const orderTypeValue = data.type !== undefined && data.type !== null ? Number(data.type) : defaultOrderType.value;
|
|
|
|
|
+ title.value = isReadonly.value ? '查看工单' : data.id ? '编辑工单' : '新增工单';
|
|
|
|
|
+ if (userList.value.length === 0) searchUsers();
|
|
|
|
|
+ resetForm(orderTypeValue);
|
|
|
|
|
+ if (!data.id) return;
|
|
|
|
|
+ loading.value = true;
|
|
|
|
|
+ try {
|
|
|
|
|
+ const res = await proxy.$http.get('/workorder/workorderinfo/getInfo/' + data.id);
|
|
|
|
|
+ if (res.data && res.data.code === 200) mapDetailToForm(res.data.data);
|
|
|
|
|
+ else { Object.assign(form, data); form.type = orderTypeValue; }
|
|
|
|
|
+ } catch (e) { console.error(e); Object.assign(form, data); form.type = orderTypeValue; }
|
|
|
|
|
+ finally { loading.value = false; }
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
|
|
+ const handleClose = () => { visible.value = false; claimsVisible.value = false; proFormRef.value?.resetFields(); };
|
|
|
|
|
+ const buildHandleUsers = () => Array.isArray(form.handleUserId) ? form.handleUserId : form.handleUserId ? [form.handleUserId] : [];
|
|
|
|
|
+ const parseFileList = () => { if (!form.fileList) return []; try { return JSON.parse(form.fileList); } catch (e) { return []; } };
|
|
|
|
|
+
|
|
|
const handleSubmit = () => {
|
|
const handleSubmit = () => {
|
|
|
- // Use proFormRef to validate
|
|
|
|
|
proFormRef.value?.validate((valid) => {
|
|
proFormRef.value?.validate((valid) => {
|
|
|
- if (valid) {
|
|
|
|
|
- loading.value = true;
|
|
|
|
|
-
|
|
|
|
|
- // Map form data to API structure
|
|
|
|
|
- const submitData = {
|
|
|
|
|
- id: form.id,
|
|
|
|
|
- taskType: form.taskType,
|
|
|
|
|
- inspectionStatus: form.inspectionStatus,
|
|
|
|
|
- waybillCode: form.waybillCode,
|
|
|
|
|
-
|
|
|
|
|
- deatil: form.detail, // detail -> deatil
|
|
|
|
|
- orderId: form.orderNo, // orderNo -> orderId
|
|
|
|
|
- expressType: form.carrierId, // carrierId -> expressType
|
|
|
|
|
- type: form.type, // Fixed: 1-Sell Book
|
|
|
|
|
-
|
|
|
|
|
- // handleUserId is already an array of IDs
|
|
|
|
|
- handleUsers: Array.isArray(form.handleUserId)
|
|
|
|
|
- ? form.handleUserId
|
|
|
|
|
- : form.handleUserId
|
|
|
|
|
- ? [form.handleUserId]
|
|
|
|
|
- : [],
|
|
|
|
|
-
|
|
|
|
|
- // fileList string -> imgInfo array
|
|
|
|
|
- imgInfo: form.fileList ? JSON.parse(form.fileList) : []
|
|
|
|
|
- };
|
|
|
|
|
-
|
|
|
|
|
- const url = form.id
|
|
|
|
|
- ? '/workorder/workorderinfo/update'
|
|
|
|
|
- : '/workorder/workorderinfo/add';
|
|
|
|
|
- proxy.$http
|
|
|
|
|
- .post(url, submitData)
|
|
|
|
|
- .then((res) => {
|
|
|
|
|
- if (res.data.code === 200) {
|
|
|
|
|
- ElMessage.success(
|
|
|
|
|
- form.id ? '修改成功' : '新增成功'
|
|
|
|
|
- );
|
|
|
|
|
- emit('success');
|
|
|
|
|
- handleClose();
|
|
|
|
|
- } else {
|
|
|
|
|
- ElMessage.error(res.data.msg || '操作失败');
|
|
|
|
|
- }
|
|
|
|
|
- })
|
|
|
|
|
- .catch((e) => {
|
|
|
|
|
- console.error(e);
|
|
|
|
|
- })
|
|
|
|
|
- .finally(() => {
|
|
|
|
|
- loading.value = false;
|
|
|
|
|
- });
|
|
|
|
|
|
|
+ if (!valid) return;
|
|
|
|
|
+ loading.value = true;
|
|
|
|
|
+ const inspectionStatus =
|
|
|
|
|
+ form.inspectionStatus === undefined || form.inspectionStatus === null || form.inspectionStatus === ''
|
|
|
|
|
+ ? undefined
|
|
|
|
|
+ : Number(form.inspectionStatus);
|
|
|
|
|
+ const submitData = {
|
|
|
|
|
+ id: form.id,
|
|
|
|
|
+ taskType: form.taskType,
|
|
|
|
|
+ inspectionStatus,
|
|
|
|
|
+ waybillCode: form.waybillCode,
|
|
|
|
|
+ deatil: isEditMode.value ? form.remark || form.detail : form.detail,
|
|
|
|
|
+ remark: form.remark,
|
|
|
|
|
+ orderId: form.orderNo,
|
|
|
|
|
+ expressType: form.carrierId,
|
|
|
|
|
+ type: form.type,
|
|
|
|
|
+ handleUsers: buildHandleUsers(),
|
|
|
|
|
+ imgInfo: parseFileList()
|
|
|
|
|
+ };
|
|
|
|
|
+ // 新增时确保带上验货状态入参
|
|
|
|
|
+ if (!form.id && inspectionStatus !== undefined) {
|
|
|
|
|
+ submitData.inspectionStatus = inspectionStatus;
|
|
|
}
|
|
}
|
|
|
|
|
+ const url = form.id ? '/workorder/workorderinfo/update' : '/workorder/workorderinfo/add';
|
|
|
|
|
+ proxy.$http.post(url, submitData).then((res) => {
|
|
|
|
|
+ if (res.data.code === 200) { ElMessage.success(form.id ? '修改成功' : '新增成功'); emit('success'); handleClose(); }
|
|
|
|
|
+ else ElMessage.error(res.data.msg || '操作失败');
|
|
|
|
|
+ }).catch((e) => console.error(e)).finally(() => { loading.value = false; });
|
|
|
});
|
|
});
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
const handleFollowUp = () => {
|
|
const handleFollowUp = () => {
|
|
|
if (!form.id) return;
|
|
if (!form.id) return;
|
|
|
-
|
|
|
|
|
loading.value = true;
|
|
loading.value = true;
|
|
|
- const submitData = {
|
|
|
|
|
- id: form.id,
|
|
|
|
|
- updateType: 1, // 待跟进
|
|
|
|
|
- deatil: form.detail || '',
|
|
|
|
|
- handleUsers: Array.isArray(form.handleUserId)
|
|
|
|
|
- ? form.handleUserId
|
|
|
|
|
- : form.handleUserId
|
|
|
|
|
- ? [form.handleUserId]
|
|
|
|
|
- : [],
|
|
|
|
|
- imgInfo: form.fileList ? JSON.parse(form.fileList) : []
|
|
|
|
|
- };
|
|
|
|
|
-
|
|
|
|
|
- proxy.$http
|
|
|
|
|
- .post('/workorder/workorderinfo/update', submitData)
|
|
|
|
|
- .then((res) => {
|
|
|
|
|
- if (res.data.code === 200) {
|
|
|
|
|
- ElMessage.success('已设置为待跟进');
|
|
|
|
|
- emit('success');
|
|
|
|
|
- handleClose();
|
|
|
|
|
- } else {
|
|
|
|
|
- ElMessage.error(res.data.msg || '操作失败');
|
|
|
|
|
- }
|
|
|
|
|
- })
|
|
|
|
|
- .catch((e) => {
|
|
|
|
|
- console.error(e);
|
|
|
|
|
- ElMessage.error('操作失败');
|
|
|
|
|
- })
|
|
|
|
|
- .finally(() => {
|
|
|
|
|
- loading.value = false;
|
|
|
|
|
- });
|
|
|
|
|
|
|
+ proxy.$http.post('/workorder/workorderinfo/update', { id: form.id, updateType: 1, deatil: form.remark || form.detail || '', remark: form.remark, handleUsers: buildHandleUsers(), imgInfo: parseFileList() })
|
|
|
|
|
+ .then((res) => { if (res.data.code === 200) { ElMessage.success('已设置为待跟进'); emit('success'); handleClose(); } else ElMessage.error(res.data.msg || '操作失败'); })
|
|
|
|
|
+ .catch((e) => { console.error(e); ElMessage.error('操作失败'); }).finally(() => { loading.value = false; });
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- const handleFeedback = () => {
|
|
|
|
|
|
|
+ const handleFinish = () => {
|
|
|
if (!form.id) return;
|
|
if (!form.id) return;
|
|
|
-
|
|
|
|
|
loading.value = true;
|
|
loading.value = true;
|
|
|
- const submitData = {
|
|
|
|
|
- id: form.id,
|
|
|
|
|
- updateType: 2, // 反馈
|
|
|
|
|
- deatil: form.detail || '',
|
|
|
|
|
- handleUsers: Array.isArray(form.handleUserId)
|
|
|
|
|
- ? form.handleUserId
|
|
|
|
|
- : form.handleUserId
|
|
|
|
|
- ? [form.handleUserId]
|
|
|
|
|
- : [],
|
|
|
|
|
- imgInfo: form.fileList ? JSON.parse(form.fileList) : []
|
|
|
|
|
- };
|
|
|
|
|
|
|
+ proxy.$http.post('/workorder/workorderinfo/finish', { ids: [form.id] })
|
|
|
|
|
+ .then((res) => { if (res.data.code === 200) { ElMessage.success('工单已完成'); emit('success'); handleClose(); } else ElMessage.error(res.data.msg || '操作失败'); })
|
|
|
|
|
+ .catch((e) => { console.error(e); ElMessage.error('操作失败'); }).finally(() => { loading.value = false; });
|
|
|
|
|
+ };
|
|
|
|
|
|
|
|
- proxy.$http
|
|
|
|
|
- .post('/workorder/workorderinfo/update', submitData)
|
|
|
|
|
- .then((res) => {
|
|
|
|
|
- if (res.data.code === 200) {
|
|
|
|
|
- ElMessage.success('已提交反馈');
|
|
|
|
|
- emit('success');
|
|
|
|
|
- handleClose();
|
|
|
|
|
- } else {
|
|
|
|
|
- ElMessage.error(res.data.msg || '操作失败');
|
|
|
|
|
- }
|
|
|
|
|
- })
|
|
|
|
|
- .catch((e) => {
|
|
|
|
|
- console.error(e);
|
|
|
|
|
- ElMessage.error('操作失败');
|
|
|
|
|
- })
|
|
|
|
|
- .finally(() => {
|
|
|
|
|
- loading.value = false;
|
|
|
|
|
- });
|
|
|
|
|
|
|
+ const openClaimsDialog = () => { claimsForm.money = undefined; claimsForm.reason = ''; claimsVisible.value = true; };
|
|
|
|
|
+ const submitClaims = () => {
|
|
|
|
|
+ claimsFormRef.value?.validate((valid) => {
|
|
|
|
|
+ if (!valid || !form.id) return;
|
|
|
|
|
+ claimsLoading.value = true;
|
|
|
|
|
+ proxy.$http.post('/workorder/workorderinfo/claims', { id: form.id, money: claimsForm.money, reason: claimsForm.reason })
|
|
|
|
|
+ .then((res) => { if (res.data.code === 200) { ElMessage.success('理赔提交成功'); claimsVisible.value = false; emit('success'); handleClose(); } else ElMessage.error(res.data.msg || '操作失败'); })
|
|
|
|
|
+ .catch((e) => { console.error(e); ElMessage.error('操作失败'); }).finally(() => { claimsLoading.value = false; });
|
|
|
|
|
+ });
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
defineExpose({ handleOpen });
|
|
defineExpose({ handleOpen });
|