feat:更改页面

This commit is contained in:
dzc committed 2026-09-08 15:25:06 +08:00
1 parent b422df5b76
commit 44b2df144c
84 files changed
+11701 -2114

No files matched your search

@@ -0,0 +1,147 @@
<template>
<el-dialog v-model="visible" :title="title" width="520px" draggable :close-on-click-modal="false">
<el-form ref="formRef" :model="form" :rules="rules" label-width="110px" v-loading="loading">
<el-form-item label="订单号">
<el-input :model-value="orderLabel" disabled />
</el-form-item>
<el-form-item label="凭证类型">
<el-tag :type="options.printType === '2' ? 'warning' : 'primary'">
{{ options.printType === "2" ? "兑换券" : "发票" }}
</el-tag>
</el-form-item>
<el-form-item v-if="showSourceSelection" label="来源终端" prop="sourceHardId">
<el-select v-model="form.sourceHardId" class="w-full" filterable placeholder="请选择已绑定尔印打印机的业务终端">
<el-option v-for="source in sources" :key="source.id" :label="source.name" :value="String(source.id)" />
</el-select>
<div v-if="sources.length === 0" class="mt-1 text-xs text-[var(--el-color-danger)]">
该商户没有已绑定尔印打印机的业务终端,请先在设备管理完成绑定。
</div>
</el-form-item>
<el-form-item v-if="requiresReason" label="重打原因" prop="reprintReason">
<el-input v-model="form.reprintReason" type="textarea" :rows="3" maxlength="200" show-word-limit
placeholder="请填写本次人工重打原因" />
</el-form-item>
<el-alert v-if="options.action === 'retry'" type="info" :closable="false" show-icon
title="重试原任务不会增加打印序号;终端只处理新的重试版本。" />
</el-form>
<template #footer>
<el-button @click="visible = false">取消</el-button>
<el-button type="primary" :loading="submitting" :disabled="sourceUnavailable" @click="submit">
提交打印任务
</el-button>
</template>
</el-dialog>
</template>
<script setup lang="ts" name="HardPrintTaskDialog">
import * as hardInvoiceApi from "/@/api/hard/hard-invoice"
import * as printerApi from "/@/api/hard/hard-printer"
import { useMessage, useMessageBox } from "/@/hooks/message"
type PrintAction = "create" | "retry" | "reprint"
interface PrintDialogOptions {
action: PrintAction
printType: "1" | "2"
orderId: string | number
merchantId?: string | number
taskId?: string | number
sourceHardId?: string | number | null
orderNo?: string
printNo?: string | number | null
}
const emit = defineEmits(["submitted"])
const visible = ref(false)
const loading = ref(false)
const submitting = ref(false)
const formRef = ref()
const sources = ref<any[]>([])
const options = reactive<PrintDialogOptions>({ action: "create", printType: "1", orderId: "" })
/** 来源设备使用字符串保存,避免选择或自动回填时破坏后端 Long 主键精度。 */
const form = reactive<{ sourceHardId: printerApi.HardwareId | null; reprintReason: string }>({
sourceHardId: null,
reprintReason: "",
})
/** 已打印任务再次出纸必须记录原因;失败任务重试不改变打印次数。 */
const requiresReason = computed(() => options.action === "reprint" || Boolean(options.printNo && options.action === "create"))
const showSourceSelection = computed(() => options.action !== "reprint" && !(options.action === "retry" && options.sourceHardId))
const sourceUnavailable = computed(() => showSourceSelection.value && !loading.value && sources.value.length === 0)
const orderLabel = computed(() => options.orderNo || String(options.orderId || "--"))
const title = computed(() => {
if (options.action === "retry") return "重试失败打印任务"
if (options.action === "reprint") return `重打${options.printType === "2" ? "兑换券" : "发票"}`
return `${requiresReason.value ? "再次打印" : "打印"}${options.printType === "2" ? "兑换券" : "发票"}`
})
const rules = computed(() => ({
sourceHardId: showSourceSelection.value ? [{ required: true, message: "请选择来源业务终端", trigger: "change" }] : [],
reprintReason: requiresReason.value ? [{ required: true, message: "请填写重打原因", trigger: "blur" }] : [],
}))
/** 打开任务弹窗,并根据商户的有效绑定自动选择唯一来源终端。 */
const open = async (input: PrintDialogOptions) => {
Object.assign(options, input)
form.sourceHardId = null
form.reprintReason = ""
sources.value = []
visible.value = true
await nextTick()
formRef.value?.clearValidate?.()
if (!showSourceSelection.value) return
if (!input.merchantId) {
useMessage().error("订单缺少商户信息,无法选择打印终端")
return
}
loading.value = true
try {
const response: any = await printerApi.listBoundSources(String(input.merchantId))
sources.value = response.data || []
const preferred = sources.value.find((source) => input.sourceHardId != null
&& String(source.id) === String(input.sourceHardId))
if (preferred) form.sourceHardId = String(preferred.id)
else if (sources.value.length === 1) form.sourceHardId = String(sources.value[0].id)
} catch (error: any) {
useMessage().error(error?.msg || "读取可用打印终端失败")
} finally {
loading.value = false
}
}
/** 校验、二次确认并提交任务;响应只代表任务受理,不代表打印机已经出纸。 */
const submit = async () => {
const valid = await formRef.value?.validate?.().catch(() => false)
if (valid === false) return
if (requiresReason.value) {
try {
await useMessageBox().confirm(`确认提交第 ${Number(options.printNo || 0) + 1} 次打印?提交后将保留操作原因。`)
} catch {
return
}
}
submitting.value = true
try {
if (options.action === "retry") {
await hardInvoiceApi.retry({ historyId: options.taskId, sourceHardId: form.sourceHardId || undefined })
} else if (options.action === "reprint") {
await hardInvoiceApi.reprint({ historyId: options.taskId, reprintReason: form.reprintReason.trim() })
} else {
await hardInvoiceApi.print({
orderId: options.orderId,
printType: options.printType,
sourceHardId: form.sourceHardId || undefined,
reprintReason: form.reprintReason.trim() || undefined,
})
}
visible.value = false
useMessage().success("打印任务已提交")
emit("submitted")
} catch (error: any) {
useMessage().error(error?.msg || "打印任务提交失败")
} finally {
submitting.value = false
}
}
defineExpose({ open })
</script>