feat:审批

This commit is contained in:
dzc committed 2025-01-12 20:49:49 +08:00
1 parent f5c3e0b0ea
commit cd86ae5521
18 files changed
+2025 -1658

No files matched your search

+251 -232
View File
@@ -1,284 +1,303 @@
<template>
<div class="layout-padding">
<div v-loading="loading" class="layout-padding-auto layout-padding-view" style="overflow: scroll !important;">
<el-descriptions :column="3" border title="订单信息">
<el-descriptions-item :span="3" label="订单号: ">
{{ globalData.detail.id }}
</el-descriptions-item>
<el-descriptions-item label="订单类型: ">
<dict-tag :options="hard_order_type" :value="globalData.detail.orderType" />
</el-descriptions-item>
<el-descriptions-item label="付款方式: ">
<dict-tag :options="hard_pay_type" :value="globalData.detail.payType" />
</el-descriptions-item>
<el-descriptions-item label="订单状态: ">
<dict-tag :options="hard_order_status" :value="globalData.detail.orderStatus" />
</el-descriptions-item>
<el-descriptions-item label="商户: ">
<span> {{ globalData.detail.merchantName }}</span>
</el-descriptions-item>
<el-descriptions-item label="设备名: ">
<span> {{ globalData.detail.hardName }}</span>
</el-descriptions-item>
<el-descriptions-item label="设备类型: ">
<span> {{ globalData.detail.hardType }}</span>
</el-descriptions-item>
<el-descriptions-item label="商品总价: ">
<span class="color-success">
{{ displayPrice(globalData.detail.totalPrice) }}
</span>
</el-descriptions-item>
<el-descriptions-item label="额外支付: ">
<span class="color-danger">
{{ displayPrice(globalData.detail.extraPrice) }}
</span>
</el-descriptions-item>
<el-descriptions-item label="实际支付: ">
<span class="color-primary">
{{ displayPrice(globalData.detail.payPrice) }}
</span>
</el-descriptions-item>
</el-descriptions>
<el-descriptions :column="1" title="商品信息">
<el-descriptions-item labelClassName="no-colon">
<el-table :data="state.dataList" v-loading="state.loading" border :cell-style="tableStyle.cellStyle"
:header-cell-style="tableStyle.headerCellStyle" @sort-change="sortChangeHandle">
<el-table-column label="商品名" align="center" prop="productName" />
<el-table-column label="商品图片" align="center" prop="code">
<template #default="{ row }">
<preview-image v-if="row.productPic" :src="row.productPic" />
</template>
</el-table-column>
<el-table-column label="商品价格" align="center" prop="ticketId">
<template #default="{ row }">
<span>{{ displayPrice(row.productPrice) }}</span>
</template>
</el-table-column>
<el-table-column label="商品数量" align="center" prop="productCount" />
<el-table-column label="商品总额" align="center" prop="totalPrice">
<template #default="{ row }">
<span>{{ displayPrice(row.totalPrice) }}</span>
</template>
</el-table-column>
</el-table>
</el-descriptions-item>
</el-descriptions>
<div class="layout-padding">
<div v-loading="loading" class="layout-padding-auto layout-padding-view" style="overflow: scroll !important">
<el-descriptions :column="3" border title="订单信息">
<el-descriptions-item :span="3" label="订单号: ">
{{ globalData.detail.id }}
</el-descriptions-item>
<el-descriptions-item label="订单类型: ">
<dict-tag :options="hard_order_type" :value="globalData.detail.orderType" />
</el-descriptions-item>
<el-descriptions-item label="付款方式: ">
<dict-tag :options="hard_pay_type" :value="globalData.detail.payType" />
</el-descriptions-item>
<el-descriptions-item label="订单状态: ">
<dict-tag :options="hard_order_status" :value="globalData.detail.orderStatus" />
</el-descriptions-item>
<el-descriptions-item label="商户: ">
<span> {{ globalData.detail.merchantName }}</span>
</el-descriptions-item>
<el-descriptions-item label="设备名: ">
<span> {{ globalData.detail.hardName }}</span>
</el-descriptions-item>
<el-descriptions-item label="设备类型: ">
<span> {{ globalData.detail.hardType }}</span>
</el-descriptions-item>
<el-descriptions-item label="商品总价: ">
<span class="color-success">
{{ displayPrice(globalData.detail.totalPrice) }}
</span>
</el-descriptions-item>
<el-descriptions-item label="额外支付: ">
<span class="color-danger">
{{ displayPrice(globalData.detail.extraPrice) }}
</span>
</el-descriptions-item>
<el-descriptions-item label="实际支付: ">
<span class="color-primary">
{{ displayPrice(globalData.detail.payPrice) }}
</span>
</el-descriptions-item>
</el-descriptions>
<el-descriptions :column="1" title="商品信息">
<el-descriptions-item labelClassName="no-colon">
<el-table
:data="state.dataList"
v-loading="state.loading"
border
:cell-style="tableStyle.cellStyle"
:header-cell-style="tableStyle.headerCellStyle"
@sort-change="sortChangeHandle"
>
<el-table-column label="商品名" align="center" prop="productName" />
<el-table-column label="商品图片" align="center" prop="code">
<template #default="{ row }">
<preview-image v-if="row.productPic" :src="row.productPic" />
</template>
</el-table-column>
<el-table-column label="商品价格" align="center" prop="ticketId">
<template #default="{ row }">
<span>{{ displayPrice(row.productPrice) }}</span>
</template>
</el-table-column>
<el-table-column label="商品数量" align="center" prop="productCount" />
<el-table-column label="商品总额" align="center" prop="totalPrice">
<template #default="{ row }">
<span>{{ displayPrice(row.totalPrice) }}</span>
</template>
</el-table-column>
</el-table>
</el-descriptions-item>
</el-descriptions>
<!-- 退款状态 -->
<el-descriptions v-if="globalData.afterSaleData.id" :column="2" border title="退款状态">
<el-descriptions-item :column="1" label="退款状态: ">
<dict-tag :options="hard_sale_status" :value="globalData.afterSaleData.status" />
</el-descriptions-item>
<el-descriptions-item :column="1"
v-if="globalData.type == 'apply' && globalData.afterSaleData.status == 10" label="操作: "
label-class-name="no-colon">
<div class="flex justify-evenly">
<el-button type="primary" @click="agree">
同意售后
</el-button>
<el-button type="danger" @click="refundRejectRef.openDialog(globalData.detail.id)">
拒绝售后
</el-button>
</div>
</el-descriptions-item>
</el-descriptions>
<!-- 退款状态 -->
<el-descriptions v-if="globalData.afterSaleData.id" :column="2" border title="退款状态">
<el-descriptions-item :column="1" label="退款状态: ">
<dict-tag :options="hard_sale_status" :value="globalData.afterSaleData.status" />
</el-descriptions-item>
<el-descriptions-item
:column="1"
v-if="globalData.type == 'apply' && globalData.afterSaleData.status == 10"
label="操作: "
label-class-name="no-colon"
>
<div class="flex justify-evenly">
<el-button type="primary" @click="agree"> 同意售后 </el-button>
<el-button type="danger" @click="refundRejectRef.openDialog(globalData.detail.id)"> 拒绝售后 </el-button>
</div>
</el-descriptions-item>
</el-descriptions>
<el-descriptions v-if="globalData.afterSaleData.id" border title="售后信息">
<el-descriptions-item :span="3" label="退款编号: ">
{{ globalData.afterSaleData.no }}
</el-descriptions-item>
<el-descriptions-item label="售后类型: ">
<dict-tag :options="hard_after_sale_type" :value="globalData.afterSaleData.type" />
</el-descriptions-item>
<el-descriptions-item label="售后方式: ">
<dict-tag :options="hard_after_sale_way" :value="globalData.afterSaleData.way" />
</el-descriptions-item>
<el-descriptions-item label="退款金额: ">
{{ displayPrice(globalData.afterSaleData.refundPrice) }}
</el-descriptions-item>
<el-descriptions-item label="退款原因: ">
{{ globalData.afterSaleData.applyReason }}
</el-descriptions-item>
<el-descriptions-item label="补充描述: ">
{{ globalData.afterSaleData.applyDescription }}
</el-descriptions-item>
</el-descriptions>
<el-descriptions v-if="globalData.afterSaleData.id" border title="售后信息">
<el-descriptions-item :span="3" label="退款编号: ">
{{ globalData.afterSaleData.no }}
</el-descriptions-item>
<el-descriptions-item label="售后类型: ">
<dict-tag :options="hard_after_sale_type" :value="globalData.afterSaleData.type" />
</el-descriptions-item>
<el-descriptions-item label="售后方式: ">
<dict-tag :options="hard_after_sale_way" :value="globalData.afterSaleData.way" />
</el-descriptions-item>
<el-descriptions-item label="退款金额: ">
{{ displayPrice(globalData.afterSaleData.refundPrice) }}
</el-descriptions-item>
<el-descriptions-item label="退款原因: ">
{{ globalData.afterSaleData.applyReason }}
</el-descriptions-item>
<el-descriptions-item label="补充描述: ">
{{ globalData.afterSaleData.applyDescription }}
</el-descriptions-item>
</el-descriptions>
<el-descriptions v-if="globalData.log && globalData.log.length" title="售后日志">
<el-descriptions-item labelClassName="no-colon">
<el-timeline>
<el-timeline-item v-for="v in globalData.log" :key="v.id" :timestamp="v.createTime"
placement="top">
<div class="el-timeline-right-content">
<span>{{ v.content }}</span>
</div>
</el-timeline-item>
</el-timeline>
</el-descriptions-item>
</el-descriptions>
</div>
<el-descriptions v-if="globalData.log && globalData.log.length" title="售后日志">
<el-descriptions-item labelClassName="no-colon">
<el-timeline>
<el-timeline-item v-for="v in globalData.log" :key="v.id" :timestamp="v.createTime" placement="top">
<div class="el-timeline-right-content">
<span>{{ v.content }}</span>
</div>
</el-timeline-item>
</el-timeline>
</el-descriptions-item>
</el-descriptions>
</div>
<refund-reject-form ref="refundRejectRef" @refresh="getDetail" />
</div>
<refund-reject-form ref="refundRejectRef" @refresh="getDetail" />
</div>
</template>
<script setup lang="ts" name="order-refund">
import { BasicTableProps, useTable } from "/@/hooks/table";
import { useMessage, useMessageBox } from "/@/hooks/message";
import { useDict } from '/@/hooks/dict';
import * as hardOrder from "/@/api/hard/hard-order";
import * as hardCar from "/@/api/hard/hard-car";
import * as hardAfterSaleApi from '/@/api/hard/hard-after-sale'
import { BasicTableProps, useTable } from "/@/hooks/table"
import { useMessage, useMessageBox } from "/@/hooks/message"
import { useDict } from "/@/hooks/dict"
import * as hardOrder from "/@/api/hard/hard-order"
import * as hardCar from "/@/api/hard/hard-car"
import * as hardAfterSaleApi from "/@/api/hard/hard-after-sale"
import { displayPrice } from "/@/utils/formatMoney"
import { ElLoading } from 'element-plus'
import { ElLoading } from "element-plus"
// 引入组件
const RefundRejectForm = defineAsyncComponent(() => import('./refund-reject.vue'));
const RefundRejectForm = defineAsyncComponent(() => import("./refund-reject.vue"))
// 定义查询字典
const { hard_pay_type, hard_order_type, hard_order_status, hard_after_sale_way, hard_after_sale_type, hard_sale_status } = useDict("hard_pay_type", "hard_order_type", "hard_order_status", "hard_after_sale_way", "hard_after_sale_type", "hard_sale_status")
const {
hard_pay_type,
hard_order_type,
hard_order_status,
hard_after_sale_way,
hard_after_sale_type,
hard_sale_status,
} = useDict(
"hard_pay_type",
"hard_order_type",
"hard_order_status",
"hard_after_sale_way",
"hard_after_sale_type",
"hard_sale_status",
)
const { query } = useRoute()
const refundRejectRef = ref()
const loading = ref(false)
const globalData = reactive<any>({
type: "",
detail: {},
afterSaleData: {},
log: []
type: "",
detail: {},
afterSaleData: {},
log: [],
})
const state: BasicTableProps = reactive<BasicTableProps>({
createdIsNeed: false,
queryForm: {},
pagination: {
size: 100,
},
pageList: hardCar.getCarByOrderId
createdIsNeed: false,
queryForm: {},
pagination: {
size: 100,
},
pageList: hardCar.getCarByOrderId,
})
// table hook
const { getDataList, currentChangeHandle, sizeChangeHandle, sortChangeHandle, downBlobFile, tableStyle } = useTable(state)
const { getDataList, currentChangeHandle, sizeChangeHandle, sortChangeHandle, downBlobFile, tableStyle } =
useTable(state)
onMounted(async () => {
const type = query.type as unknown as any
if (type) {
globalData.type = type
}
await getDetail()
const type = query.type as unknown as any
if (type) {
globalData.type = type
}
await getDetail()
})
const agree = async () => {
let loading: any = null
try {
await useMessage().delConfirm("是否同意售后?")
loading = ElLoading.service({
lock: true,
text: '提交中',
background: 'rgba(0, 0, 0, 0.7)',
})
await hardAfterSaleApi.agree({ id: globalData.afterSaleData.id })
await getDetail()
} finally {
setTimeout(() => loading.close(), 1000)
}
let loading: any = null
try {
await useMessage().delConfirm("是否同意售后?")
loading = ElLoading.service({
lock: true,
text: "提交中",
background: "rgba(0, 0, 0, 0.7)",
})
await hardAfterSaleApi.agree({ id: globalData.afterSaleData.id })
await getDetail()
} finally {
setTimeout(() => loading.close(), 1000)
}
}
const getDetail = async () => {
const id = query.id as unknown as any
if (!id) return
state.queryForm.orderId = id
const { data: orderData } = await hardOrder.getObj(id)
globalData.detail = orderData
getDataList()
const { data: afterSaleData } = await hardAfterSaleApi.detailByOrderId({ orderId: id })
if (afterSaleData && afterSaleData.id) {
globalData.afterSaleData = afterSaleData
const { data: log } = await hardAfterSaleApi.history({ id: afterSaleData.id })
globalData.log = log
}
const id = query.id as unknown as any
if (!id) return
state.queryForm.orderId = id
const { data: orderData } = await hardOrder.getObj(id)
globalData.detail = orderData
getDataList()
const { data: afterSaleData } = await hardAfterSaleApi.detailByOrderId({ orderId: id })
if (afterSaleData && afterSaleData.id) {
globalData.afterSaleData = afterSaleData
const { data: log } = await hardAfterSaleApi.history({ id: afterSaleData.id })
globalData.log = log
}
}
</script>
<style lang="scss" scoped>
:deep(.el-descriptions) {
&:not(:nth-child(1)) {
margin-top: 20px;
}
&:not(:nth-child(1)) {
margin-top: 20px;
}
.el-descriptions__title {
display: flex;
align-items: center;
.el-descriptions__title {
display: flex;
align-items: center;
&::before {
display: inline-block;
width: 3px;
height: 20px;
margin-right: 10px;
background-color: #409eff;
content: '';
}
}
&::before {
display: inline-block;
width: 3px;
height: 20px;
margin-right: 10px;
background-color: #409eff;
content: "";
}
}
.el-descriptions-item__container {
margin: 0 10px;
.el-descriptions-item__container {
margin: 0 10px;
.no-colon {
margin: 0;
.no-colon {
margin: 0;
&::after {
content: '';
}
}
}
&::after {
content: "";
}
}
}
}
// 时间线样式调整
:deep(.el-timeline) {
margin: 10px 0 0 160px;
margin: 10px 0 0 160px;
.el-timeline-item__wrapper {
position: relative;
top: -20px;
.el-timeline-item__wrapper {
position: relative;
top: -20px;
.el-timeline-item__timestamp {
position: absolute !important;
top: 10px;
left: -150px;
}
}
.el-timeline-item__timestamp {
position: absolute !important;
top: 10px;
left: -150px;
}
}
.el-timeline-right-content {
display: flex;
align-items: center;
min-height: 30px;
padding: 10px;
background-color: #409eff;
.el-timeline-right-content {
display: flex;
align-items: center;
min-height: 30px;
padding: 10px;
background-color: #409eff;
&::before {
position: absolute;
top: 10px;
left: 13px;
border-color: transparent #409eff transparent transparent;
border-style: solid;
border-width: 8px;
content: '';
}
}
&::before {
position: absolute;
top: 10px;
left: 13px;
border-color: transparent #409eff transparent transparent;
border-style: solid;
border-width: 8px;
content: "";
}
}
.el-timeline-item__node {
position: absolute;
left: -5px;
top: -50%;
transform: translateY(100%);
display: flex;
width: 20px;
height: 20px;
font-size: 10px;
background: #409eff;
border-radius: 50%;
justify-content: center;
align-items: center;
}
.el-timeline-item__node {
position: absolute;
left: -5px;
top: -50%;
transform: translateY(100%);
display: flex;
width: 20px;
height: 20px;
font-size: 10px;
background: #409eff;
border-radius: 50%;
justify-content: center;
align-items: center;
}
}
</style>
</style>
+1 -1
View File
@@ -167,7 +167,7 @@
</div>
</template>
</el-table-column>
<el-table-column label="操作" width="200">
<el-table-column fixed="right" label="操作" width="200">
<template #default="{ row }">
<el-button icon="ShoppingCartFull" text type="primary" @click="shopCarDialogRef.openDialog(row.id)"
>购物车</el-button