169 lines
5.2 KiB
Vue
169 lines
5.2 KiB
Vue
<template>
|
|
<div v-can="permissionCodes.salesOrder.cancel" class="sales-order-operation">
|
|
<t-notice-bar
|
|
theme="warning"
|
|
visible
|
|
content="取消订单会立即撤销本单有效消费;受影响的订单积分和签到消费条件积分将由系统自动追加撤销流水。退款仍需按资金流程处理。"
|
|
/>
|
|
<t-cell-group
|
|
v-if="order"
|
|
title="销售订单"
|
|
theme="card"
|
|
v-entrance-transition
|
|
>
|
|
<t-cell title="订单号" :note="order.orderNo || order.id"/>
|
|
<t-cell title="当前状态" :note="getSalesOrderStatusText(order.status)"/>
|
|
<t-cell v-if="hasPendingFulfillment" title="履约提示" note="存在待处理履约,暂不能取消订单"/>
|
|
</t-cell-group>
|
|
<t-form
|
|
v-if="order"
|
|
class="form"
|
|
label-width="6rem"
|
|
v-entrance-transition="70"
|
|
>
|
|
<t-form-item label="取消原因" required-mark>
|
|
<div class="reason">
|
|
<t-textarea
|
|
v-model="reason"
|
|
borderless
|
|
autosize
|
|
maxlength="500"
|
|
placeholder="请输入取消原因"
|
|
/>
|
|
<t-button
|
|
size="extra-small"
|
|
theme="primary"
|
|
variant="outline"
|
|
@click="openCancelReasonPicker"
|
|
>选择</t-button>
|
|
</div>
|
|
</t-form-item>
|
|
</t-form>
|
|
<t-empty v-if="!order" :description="loading ? '正在加载订单' : '订单不存在'"/>
|
|
<t-popup v-model="cancelReasonPickerVisible" placement="bottom">
|
|
<t-picker
|
|
v-if="cancelReasonPickerVisible"
|
|
v-model="cancelReasonPickerDraft"
|
|
:columns="cancelReasonPickerColumns"
|
|
title="选择取消原因"
|
|
@cancel="cancelReasonPickerVisible = false"
|
|
@confirm="confirmCancelReason"
|
|
/>
|
|
</t-popup>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { useUserStore } from "timi-web-api";
|
|
import FulfillmentAPI from "@/api/FulfillmentAPI";
|
|
import SalesOrderAPI from "@/api/SalesOrderAPI";
|
|
import { useNavBarStore } from "@/store/navBarStore";
|
|
import type { SalesOrder } from "@/types/SalesOrder";
|
|
import { getErrorMessage } from "@/utils/error";
|
|
import { emitListDataChanged, listDataEventKeys } from "@/utils/listDataEvents";
|
|
import { Message } from "@/utils/message";
|
|
import { permissionCodes } from "@/utils/permission";
|
|
import { getSalesOrderStatusText } from "@/utils/salesOrder";
|
|
|
|
defineOptions({ name: "SalesOrderCancel" });
|
|
const route = useRoute();
|
|
const router = useRouter();
|
|
const navBarStore = useNavBarStore();
|
|
const userStore = useUserStore();
|
|
const order = ref<SalesOrder>();
|
|
const loading = ref(false);
|
|
const saving = ref(false);
|
|
const reason = ref("");
|
|
const cancelReasonPickerDraft = ref<string[]>([]);
|
|
const cancelReasonPickerVisible = ref(false);
|
|
const hasPendingFulfillment = ref(false);
|
|
const cancelReasonOptions = [
|
|
"客户主动取消订单",
|
|
"客户重复下单",
|
|
"商品缺货,无法履约",
|
|
"订单信息有误",
|
|
"价格或优惠配置错误",
|
|
"客户需求变更",
|
|
"其他原因"
|
|
];
|
|
const cancelReasonPickerColumns = cancelReasonOptions.map(item => ({ label: item, value: item }));
|
|
|
|
function openCancelReasonPicker(): void {
|
|
const currentReason = cancelReasonOptions.includes(reason.value) ? reason.value : cancelReasonOptions[0];
|
|
cancelReasonPickerDraft.value = [currentReason];
|
|
cancelReasonPickerVisible.value = true;
|
|
}
|
|
|
|
function confirmCancelReason(value: Array<string | number>): void {
|
|
reason.value = String(value[0] || cancelReasonPickerDraft.value[0] || "");
|
|
cancelReasonPickerVisible.value = false;
|
|
}
|
|
|
|
async function loadData(): Promise<void> {
|
|
const id = String(route.params.id || "");
|
|
if (!id) return;
|
|
loading.value = true;
|
|
try {
|
|
order.value = await SalesOrderAPI.detail(id);
|
|
if (userStore.hasPermissions(permissionCodes.orderFulfillment.read)) {
|
|
const [pendingResult, waitingStockResult] = await Promise.all([
|
|
FulfillmentAPI.list({ salesOrderId: id, status: "PENDING", index: 0, size: 1 }),
|
|
FulfillmentAPI.list({ salesOrderId: id, status: "WAITING_STOCK", index: 0, size: 1 })
|
|
]);
|
|
hasPendingFulfillment.value = !!pendingResult.list?.length || !!waitingStockResult.list?.length;
|
|
}
|
|
} catch (error) {
|
|
Message.error(getErrorMessage(error, "订单加载失败"));
|
|
} finally {
|
|
loading.value = false;
|
|
}
|
|
}
|
|
|
|
async function save(): Promise<void> {
|
|
if (!order.value?.id || !reason.value || saving.value) return;
|
|
if (order.value.status !== "ACTIVE") {
|
|
Message.warning("只有进行中的订单可以取消");
|
|
return;
|
|
}
|
|
if (hasPendingFulfillment.value) {
|
|
Message.warning("存在待处理履约,暂不能取消订单");
|
|
return;
|
|
}
|
|
saving.value = true;
|
|
try {
|
|
await SalesOrderAPI.cancel({ salesOrderId: order.value.id, reason: reason.value.trim() });
|
|
emitListDataChanged(listDataEventKeys.salesOrderChanged, order.value.id);
|
|
Message.success("订单已取消");
|
|
await router.replace(`/management/sales-orders/${order.value.id}`);
|
|
} catch (error) {
|
|
Message.error(getErrorMessage(error, "订单取消失败"));
|
|
} finally {
|
|
saving.value = false;
|
|
}
|
|
}
|
|
|
|
onMounted(async () => {
|
|
if (!userStore.hasPermissions(permissionCodes.salesOrder.cancel)) return;
|
|
navBarStore.setRightText("确认", "var(--td-error-color)", save);
|
|
await loadData();
|
|
});
|
|
onUnmounted(() => navBarStore.clearRight());
|
|
</script>
|
|
|
|
<style scoped lang="less">
|
|
.sales-order-operation {
|
|
gap: 1rem;
|
|
padding: var(--app-nav-height) 0 2rem;
|
|
display: flex;
|
|
flex-direction: column;
|
|
|
|
.form {
|
|
|
|
.reason {
|
|
gap: .5rem;
|
|
display: flex;
|
|
}
|
|
}
|
|
}
|
|
</style>
|