2025-04-07 15:50:12 +08:00
|
|
|
<script setup lang="ts">
|
2025-04-08 09:22:21 +08:00
|
|
|
import { ref, watch } from 'vue'
|
2025-04-19 11:12:02 +08:00
|
|
|
import Compressor from 'compressorjs'
|
2025-04-08 09:22:21 +08:00
|
|
|
import { showConfirmDialog, showSuccessToast, showToast, UploaderFileListItem } from 'vant'
|
|
|
|
import axios from "axios"
|
2025-04-07 15:50:12 +08:00
|
|
|
import { submitApprovalApi } from '@/common/apis/approval'
|
|
|
|
import type { SubmitApprovalRequestData } from '@/common/apis/approval/type'
|
|
|
|
import { useRouter } from 'vue-router'
|
2025-04-14 16:53:44 +08:00
|
|
|
import { useOrderStore } from '@/pinia/stores/order'
|
|
|
|
import { useWxStoreOutside } from '@/pinia/stores/wx'
|
2025-04-08 09:22:21 +08:00
|
|
|
const { VITE_APP_BASE_API } = import.meta.env;
|
2025-04-07 15:50:12 +08:00
|
|
|
|
|
|
|
const router = useRouter()
|
|
|
|
const route = useRoute()
|
2025-04-14 16:53:44 +08:00
|
|
|
const orderStore = useOrderStore()
|
|
|
|
const wxStore = useWxStoreOutside()
|
2025-04-07 15:50:12 +08:00
|
|
|
|
|
|
|
const formData = ref<SubmitApprovalRequestData>({
|
2025-04-08 09:22:21 +08:00
|
|
|
orderGoodsId: Number(route.query.orderGoodsId),
|
|
|
|
returnQuantity: 1,
|
2025-04-09 10:28:48 +08:00
|
|
|
returnImages: '',
|
2025-06-10 10:11:49 +08:00
|
|
|
returnRemark: '',
|
|
|
|
corpid: wxStore.corpid,
|
2025-04-08 09:22:21 +08:00
|
|
|
})
|
|
|
|
|
|
|
|
watch(() => route.query.orderGoodsId, (newVal) => {
|
|
|
|
formData.value.orderGoodsId = newVal ? Number(newVal) : NaN
|
|
|
|
})
|
|
|
|
|
|
|
|
const orderId = ref(Number(route.query.orderId))
|
|
|
|
console.log('orderId: ', orderId.value)
|
|
|
|
watch(() => route.query.orderId, (newVal) => {
|
|
|
|
orderId.value = newVal? Number(newVal) : NaN
|
|
|
|
console.log('orderId: ', orderId.value)
|
2025-04-07 15:50:12 +08:00
|
|
|
})
|
|
|
|
|
|
|
|
const submitting = ref(false)
|
2025-04-08 09:22:21 +08:00
|
|
|
const fileList = ref<UploaderFileListItem[]>([])
|
|
|
|
const uploading = ref(false)
|
2025-04-07 15:50:12 +08:00
|
|
|
|
|
|
|
const validateForm = () => {
|
2025-04-08 09:22:21 +08:00
|
|
|
if (!formData.value.orderGoodsId || isNaN(formData.value.orderGoodsId)) {
|
|
|
|
showConfirmDialog({ title: '错误', message: '订单ID参数错误' })
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
if (formData.value.returnQuantity < 1) {
|
|
|
|
showConfirmDialog({ title: '提示', message: '退还数量至少为1' })
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
const handleFileUpload = async (items: UploaderFileListItem | UploaderFileListItem[]) => {
|
|
|
|
const files = Array.isArray(items) ? items : [items]
|
|
|
|
uploading.value = true
|
|
|
|
try {
|
|
|
|
const uploadPromises = files.map(async (item) => {
|
|
|
|
item.status = 'uploading'
|
2025-04-19 11:12:02 +08:00
|
|
|
item.message = '上传中...';
|
|
|
|
const file = item.file as File;
|
|
|
|
let compressedFile = file;
|
|
|
|
try {
|
|
|
|
compressedFile = await new Promise<File>((resolve, reject) => {
|
|
|
|
new Compressor(file, {
|
|
|
|
quality: 0.8,
|
|
|
|
maxWidth: 1280,
|
|
|
|
maxHeight: 1280,
|
|
|
|
success(result) {
|
|
|
|
resolve(new File([result], file.name, {
|
|
|
|
type: 'image/jpeg',
|
|
|
|
lastModified: Date.now()
|
|
|
|
}))
|
|
|
|
},
|
|
|
|
error(err) {
|
|
|
|
reject(err)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
})
|
|
|
|
} catch (error) {
|
|
|
|
console.error('压缩失败:', error)
|
|
|
|
}
|
|
|
|
|
|
|
|
const formData = new FormData();
|
|
|
|
formData.append('file', compressedFile);
|
2025-04-08 09:22:21 +08:00
|
|
|
|
|
|
|
const { data } = await axios.post<{
|
|
|
|
code: number
|
|
|
|
data: { url: string }
|
|
|
|
message?: string
|
|
|
|
}>(VITE_APP_BASE_API + '/file/upload', formData, {
|
|
|
|
headers: { 'Content-Type': 'multipart/form-data' }
|
|
|
|
})
|
|
|
|
|
|
|
|
if (data.code !== 0) {
|
|
|
|
throw new Error(data.message || '文件上传失败')
|
|
|
|
}
|
|
|
|
return { url: data.data.url }
|
|
|
|
})
|
|
|
|
|
|
|
|
const urls = await Promise.all(uploadPromises)
|
|
|
|
files.forEach((item, index) => {
|
|
|
|
item.status = 'done'
|
2025-04-09 10:28:48 +08:00
|
|
|
item.message = '上传成功'
|
2025-04-08 09:22:21 +08:00
|
|
|
item.url = urls[index].url
|
|
|
|
})
|
|
|
|
} catch (error) {
|
|
|
|
showConfirmDialog({
|
|
|
|
title: '上传失败',
|
|
|
|
message: error instanceof Error ? error.message : '未知错误'
|
|
|
|
})
|
|
|
|
} finally {
|
|
|
|
uploading.value = false
|
|
|
|
}
|
2025-04-07 15:50:12 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
const handleSubmit = async () => {
|
2025-04-08 09:22:21 +08:00
|
|
|
if (!validateForm()) return
|
|
|
|
|
|
|
|
submitting.value = true
|
|
|
|
try {
|
2025-06-10 10:11:49 +08:00
|
|
|
formData.value.returnImages = fileList.value.map(item => item.url).join(',');
|
|
|
|
formData.value.corpid = wxStore.corpid;
|
2025-04-08 09:22:21 +08:00
|
|
|
|
|
|
|
const { code, data } = await submitApprovalApi(formData.value)
|
|
|
|
|
|
|
|
if (code === 0) {
|
2025-04-14 16:53:44 +08:00
|
|
|
orderStore.getOrders(wxStore.openid);
|
2025-04-09 10:28:48 +08:00
|
|
|
try {
|
|
|
|
await showConfirmDialog({
|
|
|
|
title: "提交成功",
|
|
|
|
message: `退货申请已提交,等待管理员审核`
|
|
|
|
})
|
|
|
|
} catch (error) { }
|
|
|
|
router.push('/order/' + orderId.value)
|
2025-04-08 09:22:21 +08:00
|
|
|
}
|
|
|
|
} catch (error) {
|
|
|
|
console.error('提交失败:', error)
|
|
|
|
showConfirmDialog({
|
|
|
|
title: '提交失败',
|
2025-06-11 10:02:57 +08:00
|
|
|
message: error instanceof Error ? error.name + error.message + error.cause + error.stack : '网络请求异常'
|
2025-04-08 09:22:21 +08:00
|
|
|
})
|
|
|
|
} finally {
|
|
|
|
submitting.value = false
|
2025-04-07 15:50:12 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
</script>
|
|
|
|
|
|
|
|
<template>
|
2025-04-08 09:22:21 +08:00
|
|
|
<div class="approval-container">
|
|
|
|
<van-nav-bar title="退货审批" left-text="返回" left-arrow fixed @click-left="() => router.go(-1)" />
|
|
|
|
|
|
|
|
<div class="content-wrapper">
|
|
|
|
<van-cell-group>
|
|
|
|
<!-- 移除订单ID和商品ID的输入框 -->
|
|
|
|
<van-field v-model="formData.returnQuantity" label="退还数量" type="number" :min="1" />
|
2025-04-09 10:28:48 +08:00
|
|
|
<van-field v-model="formData.returnRemark" label="退货备注" type="textarea" rows="2" autosize />
|
2025-04-08 09:22:21 +08:00
|
|
|
</van-cell-group>
|
|
|
|
|
|
|
|
<van-cell-group class="upload-section">
|
|
|
|
<van-cell title="凭证图片">
|
|
|
|
<template #extra>
|
|
|
|
<van-uploader v-model="fileList" multiple max-count="3" :after-read="handleFileUpload" />
|
|
|
|
</template>
|
|
|
|
</van-cell>
|
|
|
|
</van-cell-group>
|
|
|
|
|
|
|
|
<div class="submit-bar">
|
|
|
|
<van-button type="primary" block :loading="submitting" loading-text="提交中..." @click="handleSubmit">
|
|
|
|
提交申请
|
|
|
|
</van-button>
|
|
|
|
</div>
|
|
|
|
</div>
|
2025-04-07 15:50:12 +08:00
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
|
|
|
|
<style scoped>
|
|
|
|
.approval-container {
|
2025-04-08 09:22:21 +08:00
|
|
|
padding: 12px 16px;
|
2025-04-07 15:50:12 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
.content-wrapper {
|
2025-04-08 09:22:21 +08:00
|
|
|
padding-top: 46px;
|
2025-04-07 15:50:12 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
.upload-section {
|
2025-04-08 09:22:21 +08:00
|
|
|
margin: 20px 0;
|
2025-04-07 15:50:12 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
.submit-bar {
|
2025-04-08 09:22:21 +08:00
|
|
|
position: fixed;
|
|
|
|
bottom: 0;
|
|
|
|
left: 0;
|
|
|
|
right: 0;
|
|
|
|
padding: 16px;
|
|
|
|
background: #fff;
|
|
|
|
box-shadow: 0 -2px 12px rgba(0, 0, 0, 0.1);
|
2025-04-07 15:50:12 +08:00
|
|
|
}
|
|
|
|
</style>
|