| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735 |
- <template>
- <!-- 单根节点(含下单/详情弹层):AppMain 的 <transition mode="out-in"> 要求组件根为元素 -->
- <div class="har-order">
- <el-card>
- <template #header>
- <div class="card-header">
- <span>订单管理</span>
- <el-button
- v-hasPerm="['module_payment:har:order:create']"
- type="primary"
- icon="Plus"
- @click="openCreate"
- >
- 创建订单
- </el-button>
- </div>
- </template>
- <div class="mb-4">
- <el-form :inline="true" :model="searchForm">
- <el-form-item label="企业">
- <el-select
- v-model="searchForm.enterprise_id"
- placeholder="全部企业"
- clearable
- filterable
- style="width: 190px"
- >
- <el-option
- v-for="e in enterpriseStore.getEnterpriseList"
- :key="e.enterprise_id"
- :label="e.name || e.enterprise_id"
- :value="e.enterprise_id"
- />
- </el-select>
- </el-form-item>
- <el-form-item label="商户编号">
- <el-input
- v-model="searchForm.merchant_code"
- placeholder="商户编号"
- clearable
- style="width: 170px"
- @keyup.enter="handleSearch"
- />
- </el-form-item>
- <el-form-item label="订单号">
- <el-input
- v-model="searchForm.order_no"
- placeholder="我方订单号"
- clearable
- style="width: 180px"
- @keyup.enter="handleSearch"
- />
- </el-form-item>
- <el-form-item label="商户订单号">
- <el-input
- v-model="searchForm.out_biz_no"
- placeholder="企业自己的订单号"
- clearable
- style="width: 180px"
- @keyup.enter="handleSearch"
- />
- </el-form-item>
- <el-form-item label="交易状态">
- <el-select
- v-model="searchForm.trade_status"
- placeholder="全部"
- clearable
- style="width: 140px"
- >
- <el-option
- v-for="(text, value) in HAR_TRADE_STATUS_TEXT"
- :key="value"
- :label="text"
- :value="value"
- />
- </el-select>
- </el-form-item>
- <el-form-item label="交易方式">
- <el-select
- v-model="searchForm.trade_type"
- placeholder="全部"
- clearable
- style="width: 140px"
- >
- <el-option
- v-for="t in HAR_TRADE_TYPE_OPTIONS"
- :key="t.value"
- :label="t.label"
- :value="t.value"
- />
- </el-select>
- </el-form-item>
- <el-form-item label="创建日期">
- <el-date-picker
- v-model="dateRange"
- type="daterange"
- range-separator="至"
- start-placeholder="开始日期"
- end-placeholder="结束日期"
- value-format="YYYY-MM-DD"
- style="width: 250px"
- @change="handleDateChange"
- />
- </el-form-item>
- <el-form-item>
- <el-button type="primary" @click="handleSearch">查询</el-button>
- <el-button @click="handleReset">重置</el-button>
- </el-form-item>
- </el-form>
- </div>
- <el-table v-loading="loading" :data="list" border stripe>
- <template #empty>
- <el-empty description="暂无数据" />
- </template>
- <el-table-column prop="order_no" label="订单号" min-width="190" show-overflow-tooltip />
- <el-table-column prop="out_biz_no" label="商户订单号" min-width="160" show-overflow-tooltip>
- <template #default="{ row }">{{ row.out_biz_no || "-" }}</template>
- </el-table-column>
- <el-table-column prop="title" label="商品名称" min-width="140" show-overflow-tooltip>
- <template #default="{ row }">{{ row.title || "-" }}</template>
- </el-table-column>
- <el-table-column label="金额(元)" width="110">
- <template #default="{ row }">¥{{ row.price }}</template>
- </el-table-column>
- <el-table-column label="实收金额(元)" width="120">
- <template #default="{ row }">{{ row.rcv_amount != null ? "¥" + row.rcv_amount : "-" }}</template>
- </el-table-column>
- <el-table-column label="手续费(元)" width="110">
- <template #default="{ row }">{{ row.fee_amount != null ? "¥" + row.fee_amount : "-" }}</template>
- </el-table-column>
- <el-table-column label="渠道成本(元)" width="120">
- <template #default="{ row }">{{ row.channel_amount != null ? "¥" + row.channel_amount : "-" }}</template>
- </el-table-column>
- <el-table-column label="交易状态" width="100">
- <template #default="{ row }">
- <el-tag :type="HAR_TRADE_STATUS_TAG[row.trade_status] || 'info'">
- {{ HAR_TRADE_STATUS_TEXT[row.trade_status] || row.trade_status }}
- </el-tag>
- </template>
- </el-table-column>
- <el-table-column label="交易方式" width="110">
- <template #default="{ row }">{{ tradeTypeText(row.trade_type) }}</template>
- </el-table-column>
- <el-table-column prop="merchant_code" label="商户编号" min-width="140">
- <template #default="{ row }">{{ row.merchant_code || "-" }}</template>
- </el-table-column>
- <el-table-column prop="third_shop_code" label="门店编码" min-width="130">
- <template #default="{ row }">{{ row.third_shop_code || "-" }}</template>
- </el-table-column>
- <el-table-column prop="platform_trade_no" label="支付宝交易号" min-width="200" show-overflow-tooltip>
- <template #default="{ row }">{{ row.platform_trade_no || "-" }}</template>
- </el-table-column>
- <el-table-column label="交易时间" width="170">
- <template #default="{ row }">
- {{ row.trade_time ? dayjs(row.trade_time).format("YYYY-MM-DD HH:mm:ss") : "-" }}
- </template>
- </el-table-column>
- <el-table-column label="退款时间" width="170">
- <template #default="{ row }">
- {{ row.refund_time ? dayjs(row.refund_time).format("YYYY-MM-DD HH:mm:ss") : "-" }}
- </template>
- </el-table-column>
- <el-table-column prop="refund_reason" label="退款原因" min-width="160" show-overflow-tooltip>
- <template #default="{ row }">{{ row.refund_reason || "-" }}</template>
- </el-table-column>
- <el-table-column label="操作" width="150" fixed="right">
- <template #default="{ row }">
- <el-button
- v-hasPerm="['module_payment:har:order:detail']"
- size="small"
- @click="openDetail(row)"
- >
- 详情
- </el-button>
- <el-button
- v-hasPerm="['module_payment:har:order:sync']"
- size="small"
- type="primary"
- :loading="syncingId === row.id"
- @click="handleSync(row)"
- >
- 同步
- </el-button>
- </template>
- </el-table-column>
- </el-table>
- <div class="mt-4 flex justify-end">
- <el-pagination
- v-model:current-page="pageNo"
- v-model:page-size="pageSize"
- :total="total"
- :page-sizes="[10, 20, 50, 100]"
- layout="total, sizes, prev, pager, next, jumper"
- @size-change="load"
- @current-change="load"
- />
- </div>
- </el-card>
- <!-- 创建订单 -->
- <el-dialog v-model="createVisible" title="创建订单" width="640px" @closed="handleCreateClosed">
- <el-alert
- class="mb-4"
- type="info"
- :closable="false"
- show-icon
- title="填写付款码即为被扫收款(用户出示付款码);留空则生成收款链接,由用户扫码支付。"
- />
- <el-form ref="formRef" :model="form" :rules="rules" label-width="120px">
- <el-form-item label="商户" prop="merchant_code">
- <!-- 可清空 + 可输入:本租户配了多个商户时这里就是「钱进哪一家」的开关;
- 列表拉不到时(未授权/接口异常)仍可手工敲编号,归属由后端按本租户校验 -->
- <el-select
- v-model="form.merchant_code"
- placeholder="留空即按企业与租户自动匹配"
- clearable
- filterable
- allow-create
- default-first-option
- style="width: 100%"
- >
- <el-option
- v-for="m in merchantOptions"
- :key="m.merchant_code"
- :label="merchantLabel(m)"
- :value="m.merchant_code"
- />
- </el-select>
- <div v-if="merchantOptions.length > 1" class="form-tip">
- 本租户配置了多个商户,请选择这笔款项收进哪一个商户
- </div>
- </el-form-item>
- <el-form-item label="企业" prop="enterprise_id">
- <el-select
- v-model="form.enterprise_id"
- placeholder="留空即按租户下单"
- clearable
- filterable
- style="width: 100%"
- >
- <el-option
- v-for="e in enterpriseStore.getEnterpriseList"
- :key="e.enterprise_id"
- :label="e.name || e.enterprise_id"
- :value="e.enterprise_id"
- />
- </el-select>
- </el-form-item>
- <el-form-item label="商户订单号" prop="out_biz_no">
- <el-input
- v-model="form.out_biz_no"
- placeholder="企业自己的订单号,便于对账,最长 64 位"
- maxlength="64"
- show-word-limit
- />
- </el-form-item>
- <el-form-item label="金额(元)" prop="price">
- <el-input-number
- v-model="form.price"
- :min="0.01"
- :precision="2"
- :step="1"
- controls-position="right"
- style="width: 200px"
- />
- </el-form-item>
- <el-form-item label="商品名称" prop="title">
- <el-input v-model="form.title" maxlength="64" show-word-limit />
- </el-form-item>
- <el-form-item label="交易方式" prop="trade_type">
- <el-select v-model="form.trade_type" style="width: 100%" @change="handleTradeTypeChange">
- <el-option
- v-for="t in HAR_TRADE_TYPE_OPTIONS"
- :key="t.value"
- :label="t.label"
- :value="t.value"
- />
- </el-select>
- </el-form-item>
- <template v-if="form.trade_type === 'alipay_stage'">
- <el-form-item label="分期数" prop="stage_num">
- <el-select v-model="form.stage_num" placeholder="请选择分期数" style="width: 100%">
- <el-option v-for="n in STAGE_NUM_OPTIONS" :key="n" :label="`${n} 期`" :value="n" />
- </el-select>
- </el-form-item>
- <el-form-item label="手续费承担方" prop="percent">
- <el-select v-model="form.percent" style="width: 100%">
- <el-option label="商户承担" value="100" />
- <el-option label="用户承担" value="0" />
- </el-select>
- </el-form-item>
- </template>
- <el-form-item label="门店编码" prop="third_shop_code">
- <el-input
- v-model="form.third_shop_code"
- placeholder="商户侧门店编码,最长 32 位"
- maxlength="32"
- show-word-limit
- />
- </el-form-item>
- <el-form-item label="平台门店编号" prop="shop_code">
- <el-input v-model="form.shop_code" placeholder="上游返回的平台门店编号" />
- </el-form-item>
- <el-form-item label="付款码" prop="auth_code">
- <el-input
- v-model="form.auth_code"
- placeholder="扫用户付款码得到,填写即走被扫收款"
- clearable
- />
- </el-form-item>
- <el-form-item label="支付超时" prop="pay_timeout">
- <el-input-number
- v-model="form.pay_timeout"
- :min="2"
- :max="60"
- controls-position="right"
- style="width: 200px"
- />
- <span class="ml-2 text-gray-400">分钟,仅主扫下单有效</span>
- </el-form-item>
- <el-form-item label="扩展参数" prop="extra_params">
- <el-input
- v-model="form.extra_params"
- type="textarea"
- :rows="2"
- placeholder="上游透传字段,原样提交"
- />
- </el-form-item>
- </el-form>
- <template #footer>
- <el-button @click="createVisible = false">取消</el-button>
- <el-button type="primary" :loading="saving" @click="handleCreate">提交</el-button>
- </template>
- </el-dialog>
- <!-- 订单详情 -->
- <el-dialog v-model="detailVisible" title="订单详情" width="720px">
- <el-descriptions v-if="detail" :column="2" border>
- <el-descriptions-item label="订单号" :span="2">{{ detail.order_no }}</el-descriptions-item>
- <el-descriptions-item label="商户订单号">
- {{ detail.out_biz_no || "-" }}
- </el-descriptions-item>
- <el-descriptions-item label="交易状态">
- <el-tag :type="HAR_TRADE_STATUS_TAG[detail.trade_status] || 'info'">
- {{ HAR_TRADE_STATUS_TEXT[detail.trade_status] || detail.trade_status }}
- </el-tag>
- </el-descriptions-item>
- <el-descriptions-item label="商品名称">{{ detail.title || "-" }}</el-descriptions-item>
- <el-descriptions-item label="交易方式">
- {{ tradeTypeText(detail.trade_type) }}
- </el-descriptions-item>
- <el-descriptions-item label="订单金额">¥{{ detail.price }}</el-descriptions-item>
- <el-descriptions-item label="实收金额">
- {{ detail.rcv_amount != null ? `¥${detail.rcv_amount}` : "-" }}
- </el-descriptions-item>
- <el-descriptions-item label="手续费">
- {{ detail.fee_amount != null ? `¥${detail.fee_amount}` : "-" }}
- </el-descriptions-item>
- <el-descriptions-item label="渠道成本">
- {{ detail.channel_amount != null ? `¥${detail.channel_amount}` : "-" }}
- </el-descriptions-item>
- <el-descriptions-item label="商户编号">
- {{ detail.merchant_code || "-" }}
- </el-descriptions-item>
- <el-descriptions-item label="门店编码">
- {{ detail.third_shop_code || "-" }}
- </el-descriptions-item>
- <el-descriptions-item label="平台门店编号">
- {{ detail.shop_code || "-" }}
- </el-descriptions-item>
- <el-descriptions-item label="上游订单号" :span="2">
- {{ detail.upstream_order_no || "-" }}
- </el-descriptions-item>
- <el-descriptions-item label="支付宝交易号" :span="2">
- {{ detail.platform_trade_no || "-" }}
- </el-descriptions-item>
- <el-descriptions-item v-if="detail.trade_type === 'alipay_stage'" label="分期数">
- {{ detail.stage_num ? `${detail.stage_num} 期` : "-" }}
- </el-descriptions-item>
- <el-descriptions-item v-if="detail.trade_type === 'alipay_stage'" label="手续费承担方">
- {{ detail.percent === "100" ? "商户承担" : detail.percent === "0" ? "用户承担" : "-" }}
- </el-descriptions-item>
- <el-descriptions-item label="支付超时">
- {{ detail.pay_timeout != null ? `${detail.pay_timeout} 分钟` : "-" }}
- </el-descriptions-item>
- <el-descriptions-item label="企业回调">
- {{ HAR_NOTIFY_STATUS_TEXT[detail.notify_status || ""] || detail.notify_status || "-" }}
- </el-descriptions-item>
- <el-descriptions-item label="下单时间">
- {{ formatTime(detail.created_time) }}
- </el-descriptions-item>
- <el-descriptions-item label="支付时间">
- {{ formatTime(detail.trade_time) }}
- </el-descriptions-item>
- <el-descriptions-item label="退款时间">
- {{ formatTime(detail.refund_time) }}
- </el-descriptions-item>
- <el-descriptions-item label="退款原因" :span="2">
- {{ detail.refund_reason || "-" }}
- </el-descriptions-item>
- <el-descriptions-item label="上游创建时间">
- {{ formatTime(detail.upstream_create_time) }}
- </el-descriptions-item>
- <el-descriptions-item v-if="detail.pay_url" label="收款链接" :span="2">
- <div class="pay-url">
- <span class="pay-url__text">{{ detail.pay_url }}</span>
- <el-button size="small" type="primary" @click="openPayUrl(detail.pay_url)">
- 打开
- </el-button>
- <el-button size="small" @click="copyPayUrl(detail.pay_url)">复制</el-button>
- </div>
- </el-descriptions-item>
- <el-descriptions-item v-if="detail.extra_params" label="扩展参数" :span="2">
- {{ detail.extra_params }}
- </el-descriptions-item>
- </el-descriptions>
- <template #footer>
- <el-button
- v-hasPerm="['module_payment:har:order:sync']"
- :loading="syncingId === detail?.id"
- @click="detail && handleSync(detail)"
- >
- 同步上游状态
- </el-button>
- <el-button @click="detailVisible = false">关闭</el-button>
- </template>
- </el-dialog>
- </div>
- </template>
- <script setup lang="ts">
- import { onMounted, reactive, ref } from "vue";
- import { ElMessage, type FormInstance, type FormRules } from "element-plus";
- import dayjs from "dayjs";
- import HarAPI, {
- HAR_BIZ_UN_STAGE,
- HAR_NOTIFY_STATUS_TEXT,
- HAR_TRADE_STATUS_TAG,
- HAR_TRADE_STATUS_TEXT,
- HAR_TRADE_TYPE_OPTIONS,
- type HarMerchantVO,
- type HarOrderCreateParams,
- type HarOrderVO,
- } from "@/api/module_payment/har";
- import { useEnterpriseStore } from "@/store/modules/enterprise.store";
- const enterpriseStore = useEnterpriseStore();
- /** 本租户可见的商户配置 —— 下单时用哪一条由这里选 */
- const merchantOptions = ref<HarMerchantVO[]>([]);
- /** 规范 5.1 给定的分期期数 */
- const STAGE_NUM_OPTIONS = ["3", "6", "12", "24"];
- const list = ref<HarOrderVO[]>([]);
- const total = ref(0);
- const pageNo = ref(1);
- const pageSize = ref(20);
- const loading = ref(false);
- const syncingId = ref<string | undefined>();
- const createVisible = ref(false);
- const saving = ref(false);
- const formRef = ref<FormInstance>();
- const detailVisible = ref(false);
- const detail = ref<HarOrderVO | null>(null);
- const dateRange = ref<string[] | null>(null);
- const searchForm = reactive({
- enterprise_id: undefined as string | undefined,
- merchant_code: "",
- order_no: "",
- out_biz_no: "",
- trade_status: "",
- trade_type: "",
- start_date: undefined as string | undefined,
- end_date: undefined as string | undefined,
- });
- /** price 在后端入参里是 BigDecimal(数字或字符串皆可),表单里固定为数字,提交时再断言 */
- type OrderForm = Omit<HarOrderCreateParams, "price"> & { price?: number };
- const defaultForm = (): OrderForm => ({
- // 用 undefined 而不是空串:空串对 enterprise_id 是有含义的(=租户级),
- // 对 merchant_code 不是 —— 留空只表示「没指定」,后端按 StrUtil.isNotBlank 分流
- merchant_code: undefined,
- enterprise_id: "",
- out_biz_no: "",
- price: undefined,
- title: "",
- trade_type: "alipay_un_stage",
- // 非分期要带业务类型(规范 260924)。后端纯透传、不推导,所以这里就得给上;
- // 分期那个取值规范没写,留空 —— 真缺了上游会点名报出来。
- biz: HAR_BIZ_UN_STAGE,
- stage_num: "",
- percent: "",
- third_shop_code: "",
- shop_code: "",
- auth_code: "",
- pay_timeout: undefined,
- extra_params: "",
- });
- const form = reactive<OrderForm>(defaultForm());
- const rules: FormRules = {
- // 企业**非必填**:留空即按租户下单(用 enterprise_id IS NULL 的那条租户级商户映射),
- // 与 HarOrderCreateDTO 上「选填」的注释、后端 HarOrderService#create 的分流一致。
- // 商户同理非必填:本租户只有一条配置时留空即为那条;有多条时后端会 400 要求指定。
- price: [{ required: true, message: "请填写金额", trigger: "blur" }],
- title: [{ required: true, message: "请填写商品名称", trigger: "blur" }],
- trade_type: [{ required: true, message: "请选择交易方式", trigger: "change" }],
- };
- const merchantLabel = (m: HarMerchantVO) =>
- m.merchant_name ? `${m.merchant_name}(${m.merchant_code})` : m.merchant_code;
- async function loadMerchantOptions() {
- try {
- const res = await HarAPI.merchantList({ page_size: 100 });
- merchantOptions.value = res.data.data?.items || res.data.data?.list || [];
- } catch {
- // 拉不到(未授权/接口异常)不阻塞下单:下拉留空,仍可手工输入编号,
- // 归属由后端按本租户校验(跨租户的会被 404 挡掉)
- merchantOptions.value = [];
- }
- }
- const tradeTypeText = (v?: string) =>
- HAR_TRADE_TYPE_OPTIONS.find((t) => t.value === v)?.label || v || "-";
- const formatTime = (v?: string) => (v ? dayjs(v).format("YYYY-MM-DD HH:mm:ss") : "-");
- async function load() {
- loading.value = true;
- try {
- const res = await HarAPI.orderList({
- enterprise_id: searchForm.enterprise_id || undefined,
- merchant_code: searchForm.merchant_code || undefined,
- order_no: searchForm.order_no || undefined,
- out_biz_no: searchForm.out_biz_no || undefined,
- trade_status: searchForm.trade_status || undefined,
- trade_type: searchForm.trade_type || undefined,
- start_date: searchForm.start_date || undefined,
- end_date: searchForm.end_date || undefined,
- page_no: pageNo.value,
- page_size: pageSize.value,
- });
- list.value = res.data.data?.items || res.data.data?.list || [];
- total.value = res.data.data?.total || 0;
- } finally {
- loading.value = false;
- }
- }
- function handleSearch() {
- pageNo.value = 1;
- load();
- }
- function handleDateChange() {
- if (dateRange.value && dateRange.value.length === 2) {
- searchForm.start_date = dateRange.value[0];
- searchForm.end_date = dateRange.value[1];
- } else {
- searchForm.start_date = undefined;
- searchForm.end_date = undefined;
- }
- }
- function handleReset() {
- searchForm.enterprise_id = undefined;
- searchForm.merchant_code = "";
- searchForm.order_no = "";
- searchForm.out_biz_no = "";
- searchForm.trade_status = "";
- searchForm.trade_type = "";
- searchForm.start_date = undefined;
- searchForm.end_date = undefined;
- dateRange.value = null;
- handleSearch();
- }
- function openCreate() {
- Object.assign(form, defaultForm());
- createVisible.value = true;
- }
- function handleCreateClosed() {
- formRef.value?.clearValidate();
- Object.assign(form, defaultForm());
- }
- function handleTradeTypeChange(v: string) {
- // 非分期时清掉分期字段,避免把无关参数透传给上游
- if (v !== "alipay_stage") {
- form.stage_num = "";
- form.percent = "";
- // 切回非分期要把业务类型补回来:清掉它再切回来仍是「非分期却不带 biz」
- form.biz = HAR_BIZ_UN_STAGE;
- } else {
- // 分期的业务类型取值规范没给,不猜
- form.biz = "";
- if (!form.percent) {
- form.percent = "100";
- }
- }
- }
- async function handleCreate() {
- if (form.trade_type === "alipay_stage" && (!form.stage_num || !form.percent)) {
- ElMessage.warning("花呗分期必须选择分期数与手续费承担方");
- return;
- }
- const valid = await formRef.value?.validate().catch(() => false);
- if (!valid) {
- return;
- }
- saving.value = true;
- try {
- const res = await HarAPI.orderCreate({
- ...form,
- // 已过表单必填校验,此处 price 必然有值
- price: form.price as number,
- out_biz_no: form.out_biz_no || undefined,
- biz: form.biz || undefined,
- stage_num: form.stage_num || undefined,
- percent: form.percent || undefined,
- third_shop_code: form.third_shop_code || undefined,
- shop_code: form.shop_code || undefined,
- auth_code: form.auth_code || undefined,
- extra_params: form.extra_params || undefined,
- });
- const created = res.data.data;
- createVisible.value = false;
- detail.value = created || null;
- detailVisible.value = true;
- ElMessage.success(
- created?.pay_url ? "下单成功,请在详情中打开收款链接" : "下单成功,等待用户付款"
- );
- load();
- } finally {
- saving.value = false;
- }
- }
- async function openDetail(row: HarOrderVO) {
- const res = await HarAPI.orderDetail(row.id as string);
- detail.value = res.data.data;
- detailVisible.value = true;
- }
- async function handleSync(row: HarOrderVO) {
- syncingId.value = row.id;
- try {
- const res = await HarAPI.orderSync(row.id as string);
- const updated = res.data.data;
- ElMessage.success(
- `已同步,当前状态:${HAR_TRADE_STATUS_TEXT[updated.trade_status] || updated.trade_status}`
- );
- // 详情打开着就同步刷新,避免弹层里看到的还是旧状态
- if (detailVisible.value && detail.value?.id === row.id) {
- detail.value = updated;
- }
- load();
- } finally {
- syncingId.value = undefined;
- }
- }
- function openPayUrl(url?: string) {
- if (!url) {
- return;
- }
- const w = window.open(url, "_blank");
- if (!w) {
- ElMessage.warning("收款链接弹窗被浏览器拦截,请允许弹窗后重试");
- }
- }
- async function copyPayUrl(url?: string) {
- if (!url) {
- return;
- }
- try {
- await navigator.clipboard.writeText(url);
- ElMessage.success("已复制收款链接");
- } catch {
- ElMessage.warning("浏览器拒绝了复制操作,请手动选中复制");
- }
- }
- onMounted(async () => {
- load();
- loadMerchantOptions();
- try {
- await enterpriseStore.loadEnterpriseList();
- } catch {
- // 企业列表加载失败不阻塞列表查询
- }
- });
- </script>
- <style lang="scss" scoped>
- .card-header {
- display: flex;
- justify-content: space-between;
- align-items: center;
- }
- .form-tip {
- font-size: 12px;
- line-height: 1.6;
- color: var(--el-text-color-secondary);
- }
- .pay-url {
- display: flex;
- align-items: center;
- gap: 8px;
- &__text {
- flex: 1;
- word-break: break-all;
- color: var(--el-text-color-regular);
- }
- }
- </style>
|