634 lines
25 KiB
Vue
634 lines
25 KiB
Vue
<script>
|
||
/**
|
||
* 发票详情:按查询 ID 加载发票,区分历史登记与正式电子文件;下载链接必须通过协议与字符校验。
|
||
*/
|
||
import { definePageMeta } from "#imports";
|
||
import "~/assets/styles/invoice.B6sYFYlb.css";
|
||
definePageMeta({
|
||
key: (e) => e.fullPath,
|
||
});
|
||
import { toDisplayString } from "vue";
|
||
import { onMounted } from "vue";
|
||
import { normalizeClass } from "vue";
|
||
import { createBlock } from "vue";
|
||
import { ref } from "vue";
|
||
import { withCtx } from "vue";
|
||
import { createCommentVNode } from "vue";
|
||
import { computed } from "vue";
|
||
import { createElementBlock } from "vue";
|
||
import { createElementVNode } from "vue";
|
||
import { createTextVNode } from "vue";
|
||
import { unref } from "vue";
|
||
import { defineComponent } from "vue";
|
||
import { createVNode } from "vue";
|
||
import { openBlock } from "vue";
|
||
import { useRoute } from "#app";
|
||
import { NuxtLink } from "#components";
|
||
import { sanitizeMessage } from "~/lib/auth.js";
|
||
import { useApi } from "~/lib/auth.js";
|
||
import button from "openvue/button";
|
||
import { t as _plugin_vue_export_helper_t } from "~/lib/_plugin-vue_export-helper.js";
|
||
import message from "openvue/message";
|
||
import { n as dict_n } from "~/lib/dict.js";
|
||
import skeleton from "openvue/skeleton";
|
||
import { t as composables_t } from "~/lib/composables-2.js";
|
||
var T = {
|
||
class: `invoice-detail-page`,
|
||
},
|
||
E = {
|
||
key: 1,
|
||
class: `invoice-error`,
|
||
},
|
||
D = {
|
||
key: 2,
|
||
class: `invoice-paper`,
|
||
},
|
||
O = {
|
||
class: `invoice-number`,
|
||
},
|
||
k = {
|
||
key: 0,
|
||
},
|
||
A = {
|
||
key: 1,
|
||
},
|
||
j = {
|
||
key: 2,
|
||
},
|
||
M = {
|
||
key: 3,
|
||
},
|
||
N = {
|
||
key: 4,
|
||
},
|
||
P = {
|
||
class: `invoice-total`,
|
||
},
|
||
F = {
|
||
class: `invoice-actions`,
|
||
},
|
||
I = [`href`],
|
||
L = {
|
||
key: 2,
|
||
class: `invoice-file-hint`,
|
||
},
|
||
R = _plugin_vue_export_helper_t(
|
||
defineComponent({
|
||
__name: `invoice`,
|
||
setup(f) {
|
||
composables_t({
|
||
key: (e) => e.fullPath,
|
||
});
|
||
let b = useRoute(),
|
||
R = useApi(),
|
||
z = ref(null),
|
||
B = ref(!0),
|
||
V = ref(``),
|
||
H = ref(!1),
|
||
U = ref(``),
|
||
W = {
|
||
pending: `待审核`,
|
||
unpaid: `待支付`,
|
||
wait_create: `待开具`,
|
||
creating: `开具中`,
|
||
create_fail: `开具失败`,
|
||
approved: `已审核`,
|
||
reject: `已驳回`,
|
||
rejected: `已驳回`,
|
||
issued: `已开具`,
|
||
wait_send: `待寄出`,
|
||
sent: `已寄出`,
|
||
cancel: `已取消`,
|
||
flushed: `已冲红`,
|
||
},
|
||
G = computed(() => z.value?.invoice_project === `历史已开票登记`),
|
||
K = computed(() =>
|
||
G.value
|
||
? `历史已开票登记`
|
||
: W[String(z.value?.status || ``).toLowerCase()] ||
|
||
String(z.value?.status || `—`),
|
||
);
|
||
// 下载地址仅允许 HTTP(S) 或站内绝对路径,拒绝反斜杠、空白控制字符和协议相对地址。
|
||
function q(e) {
|
||
// eslint-disable-next-line no-control-regex -- 安全边界:拒绝发票下载地址中的控制字符。
|
||
return typeof e != `string` || /[\u0000-\u0020\\]/.test(e)
|
||
? ``
|
||
: /^https?:\/\//i.test(e) || /^\/(?!\/)/.test(e)
|
||
? e
|
||
: ``;
|
||
}
|
||
// 从详情的候选字段中选择第一个非空值,用于兼容不同发票字段展示。
|
||
function J(...e) {
|
||
for (let t of e) {
|
||
let e = z.value?.[t];
|
||
if (e != null && String(e) !== ``) return e;
|
||
}
|
||
return ``;
|
||
}
|
||
// 普通发票尚无有效下载地址时单独请求文件地址;历史已开票登记不伪造下载文件。
|
||
async function Y(e) {
|
||
if (!(G.value || q(z.value?.invoice_url))) {
|
||
((H.value = !0), (U.value = ``));
|
||
try {
|
||
let t = await R.get(`/invoice/${e}/invoice_filename`),
|
||
n = t.data && typeof t.data == `object` ? t.data : t,
|
||
r = q(n.url ?? n.invoice_url);
|
||
if (r && z.value)
|
||
z.value = {
|
||
...z.value,
|
||
invoice_url: r,
|
||
};
|
||
else throw Error(`正式发票文件尚未提供`);
|
||
} catch (e) {
|
||
U.value = e instanceof Error ? e.message : `获取发票下载地址失败`;
|
||
} finally {
|
||
H.value = !1;
|
||
}
|
||
}
|
||
}
|
||
// 校验查询 ID 并确认响应含发票资料,再按需要获取正式文件地址。
|
||
async function X() {
|
||
((B.value = !0), (V.value = ``));
|
||
try {
|
||
let e = String(b.query.id || ``);
|
||
if (!/^\d+$/.test(e)) throw Error(`请选择要查看的发票`);
|
||
let t = await R.get(`/invoice/${e}`),
|
||
n = t.invoice && typeof t.invoice == `object` ? t.invoice : t;
|
||
if (!n.id && !n.title && !n.invoice_project)
|
||
throw Error(`发票不存在或暂不可用`);
|
||
((z.value = n), G.value || Y(String(n.id || e)));
|
||
} catch (e) {
|
||
V.value = e instanceof Error ? e.message : `加载发票失败`;
|
||
} finally {
|
||
B.value = !1;
|
||
}
|
||
}
|
||
let Z = computed(() => q(z.value?.invoice_url));
|
||
return (
|
||
onMounted(X),
|
||
// 历史开票登记与正式文件下载分开展示,仅使用经过 q 校验的 URL 作为下载入口。
|
||
(t, i) => {
|
||
let s = message,
|
||
f = skeleton,
|
||
h = button,
|
||
v = NuxtLink;
|
||
return (
|
||
openBlock(),
|
||
createElementBlock(`div`, T, [
|
||
createVNode(
|
||
s,
|
||
{
|
||
severity: `info`,
|
||
closable: !1,
|
||
},
|
||
{
|
||
default: withCtx(() => [
|
||
...(i[1] ||= [
|
||
createTextVNode(
|
||
`发票内容以开票机构出具的正式文件为准,请下载后查看完整票面信息。`,
|
||
-1,
|
||
),
|
||
]),
|
||
]),
|
||
_: 1,
|
||
},
|
||
),
|
||
unref(B)
|
||
? (openBlock(),
|
||
createBlock(f, {
|
||
key: 0,
|
||
height: `480px`,
|
||
}))
|
||
: unref(V)
|
||
? (openBlock(),
|
||
createElementBlock(`div`, E, [
|
||
createVNode(
|
||
s,
|
||
{
|
||
severity: `error`,
|
||
closable: !1,
|
||
},
|
||
{
|
||
default: withCtx(() => [
|
||
createTextVNode(toDisplayString(unref(V)), 1),
|
||
]),
|
||
_: 1,
|
||
},
|
||
),
|
||
createVNode(h, {
|
||
label: `重新加载`,
|
||
icon: `pi pi-refresh`,
|
||
severity: `secondary`,
|
||
outlined: ``,
|
||
onClick: X,
|
||
}),
|
||
]))
|
||
: unref(z)
|
||
? (openBlock(),
|
||
createElementBlock(`article`, D, [
|
||
(i[16] ||= createElementVNode(
|
||
`h1`,
|
||
null,
|
||
`发票详情`,
|
||
-1,
|
||
)),
|
||
createElementVNode(
|
||
`p`,
|
||
O,
|
||
`发票 ID:` +
|
||
toDisplayString(unref(z).id || unref(b).query.id),
|
||
1,
|
||
),
|
||
createElementVNode(`dl`, null, [
|
||
createElementVNode(`div`, null, [
|
||
(i[2] ||= createElementVNode(
|
||
`dt`,
|
||
null,
|
||
`发票抬头`,
|
||
-1,
|
||
)),
|
||
createElementVNode(
|
||
`dd`,
|
||
null,
|
||
toDisplayString(unref(z).title || `—`),
|
||
1,
|
||
),
|
||
]),
|
||
createElementVNode(`div`, null, [
|
||
(i[3] ||= createElementVNode(
|
||
`dt`,
|
||
null,
|
||
`开票项目`,
|
||
-1,
|
||
)),
|
||
createElementVNode(
|
||
`dd`,
|
||
null,
|
||
toDisplayString(
|
||
unref(z).invoice_project || `—`,
|
||
),
|
||
1,
|
||
),
|
||
]),
|
||
createElementVNode(`div`, null, [
|
||
(i[4] ||= createElementVNode(
|
||
`dt`,
|
||
null,
|
||
`收件地址`,
|
||
-1,
|
||
)),
|
||
createElementVNode(
|
||
`dd`,
|
||
null,
|
||
toDisplayString(
|
||
unref(z).email || unref(z).address || `—`,
|
||
),
|
||
1,
|
||
),
|
||
]),
|
||
createElementVNode(`div`, null, [
|
||
(i[5] ||= createElementVNode(
|
||
`dt`,
|
||
null,
|
||
`申请日期`,
|
||
-1,
|
||
)),
|
||
createElementVNode(
|
||
`dd`,
|
||
null,
|
||
toDisplayString(
|
||
unref(z).create_time
|
||
? (`formatDate` in t
|
||
? t.formatDate
|
||
: unref(dict_n))(
|
||
Number(unref(z).create_time),
|
||
)
|
||
: `—`,
|
||
),
|
||
1,
|
||
),
|
||
]),
|
||
createElementVNode(`div`, null, [
|
||
(i[6] ||= createElementVNode(
|
||
`dt`,
|
||
null,
|
||
`格式`,
|
||
-1,
|
||
)),
|
||
createElementVNode(
|
||
`dd`,
|
||
null,
|
||
toDisplayString(unref(z).invoice_format || `—`),
|
||
1,
|
||
),
|
||
]),
|
||
createElementVNode(`div`, null, [
|
||
(i[7] ||= createElementVNode(
|
||
`dt`,
|
||
null,
|
||
`状态`,
|
||
-1,
|
||
)),
|
||
createElementVNode(
|
||
`dd`,
|
||
null,
|
||
toDisplayString(unref(K)),
|
||
1,
|
||
),
|
||
]),
|
||
J(`tax_price`, `tax_amount`) === ``
|
||
? createCommentVNode(``, !0)
|
||
: (openBlock(),
|
||
createElementBlock(`div`, k, [
|
||
(i[8] ||= createElementVNode(
|
||
`dt`,
|
||
null,
|
||
`税费`,
|
||
-1,
|
||
)),
|
||
createElementVNode(
|
||
`dd`,
|
||
null,
|
||
`¥` +
|
||
toDisplayString(
|
||
J(`tax_price`, `tax_amount`),
|
||
),
|
||
1,
|
||
),
|
||
])),
|
||
J(`parcel_price`, `shipping_fee`, `express_fee`) ===
|
||
``
|
||
? createCommentVNode(``, !0)
|
||
: (openBlock(),
|
||
createElementBlock(`div`, A, [
|
||
(i[9] ||= createElementVNode(
|
||
`dt`,
|
||
null,
|
||
`快递费`,
|
||
-1,
|
||
)),
|
||
createElementVNode(
|
||
`dd`,
|
||
null,
|
||
`¥` +
|
||
toDisplayString(
|
||
J(
|
||
`parcel_price`,
|
||
`shipping_fee`,
|
||
`express_fee`,
|
||
),
|
||
),
|
||
1,
|
||
),
|
||
])),
|
||
J(
|
||
`express_company`,
|
||
`logistics_company`,
|
||
`parcel_name`,
|
||
) === ``
|
||
? createCommentVNode(``, !0)
|
||
: (openBlock(),
|
||
createElementBlock(`div`, j, [
|
||
(i[10] ||= createElementVNode(
|
||
`dt`,
|
||
null,
|
||
`物流公司`,
|
||
-1,
|
||
)),
|
||
createElementVNode(
|
||
`dd`,
|
||
null,
|
||
toDisplayString(
|
||
J(
|
||
`express_company`,
|
||
`logistics_company`,
|
||
`parcel_name`,
|
||
),
|
||
),
|
||
1,
|
||
),
|
||
])),
|
||
J(
|
||
`express_number`,
|
||
`tracking_number`,
|
||
`parcel_number`,
|
||
) === ``
|
||
? createCommentVNode(``, !0)
|
||
: (openBlock(),
|
||
createElementBlock(`div`, M, [
|
||
(i[11] ||= createElementVNode(
|
||
`dt`,
|
||
null,
|
||
`物流单号`,
|
||
-1,
|
||
)),
|
||
createElementVNode(
|
||
`dd`,
|
||
null,
|
||
toDisplayString(
|
||
J(
|
||
`express_number`,
|
||
`tracking_number`,
|
||
`parcel_number`,
|
||
),
|
||
),
|
||
1,
|
||
),
|
||
])),
|
||
J(`invoice_order_id`, `fee_order_id`) === ``
|
||
? createCommentVNode(``, !0)
|
||
: (openBlock(),
|
||
createElementBlock(`div`, N, [
|
||
(i[12] ||= createElementVNode(
|
||
`dt`,
|
||
null,
|
||
`费用订单`,
|
||
-1,
|
||
)),
|
||
createElementVNode(
|
||
`dd`,
|
||
null,
|
||
`#` +
|
||
toDisplayString(
|
||
J(`invoice_order_id`, `fee_order_id`),
|
||
),
|
||
1,
|
||
),
|
||
])),
|
||
]),
|
||
createElementVNode(`div`, P, [
|
||
(i[13] ||= createElementVNode(
|
||
`span`,
|
||
null,
|
||
`价税合计`,
|
||
-1,
|
||
)),
|
||
createElementVNode(
|
||
`strong`,
|
||
null,
|
||
`¥` + toDisplayString(unref(z).price ?? `—`),
|
||
1,
|
||
),
|
||
]),
|
||
unref(z).reject_reason
|
||
? (openBlock(),
|
||
createBlock(
|
||
s,
|
||
{
|
||
key: 0,
|
||
severity: `warn`,
|
||
closable: !1,
|
||
},
|
||
{
|
||
default: withCtx(() => [
|
||
createTextVNode(
|
||
toDisplayString(
|
||
unref(sanitizeMessage)(
|
||
unref(z).reject_reason,
|
||
),
|
||
),
|
||
1,
|
||
),
|
||
]),
|
||
_: 1,
|
||
},
|
||
))
|
||
: createCommentVNode(``, !0),
|
||
createElementVNode(`div`, F, [
|
||
createVNode(
|
||
h,
|
||
{
|
||
"as-child": ``,
|
||
severity: `secondary`,
|
||
outlined: ``,
|
||
},
|
||
{
|
||
default: withCtx((e) => [
|
||
createVNode(
|
||
v,
|
||
{
|
||
to: `/invoices`,
|
||
class: normalizeClass(e.class),
|
||
},
|
||
{
|
||
default: withCtx(() => [
|
||
...(i[14] ||= [
|
||
createTextVNode(`返回发票列表`, -1),
|
||
]),
|
||
]),
|
||
_: 1,
|
||
},
|
||
8,
|
||
[`class`],
|
||
),
|
||
]),
|
||
_: 1,
|
||
},
|
||
),
|
||
unref(Z)
|
||
? (openBlock(),
|
||
createBlock(
|
||
h,
|
||
{
|
||
key: 0,
|
||
"as-child": ``,
|
||
},
|
||
{
|
||
default: withCtx((e) => [
|
||
createElementVNode(
|
||
`a`,
|
||
{
|
||
href: unref(Z),
|
||
class: normalizeClass(e.class),
|
||
target: `_blank`,
|
||
rel: `noopener noreferrer`,
|
||
},
|
||
[
|
||
...(i[15] ||= [
|
||
createElementVNode(
|
||
`i`,
|
||
{
|
||
class: `pi pi-download`,
|
||
},
|
||
null,
|
||
-1,
|
||
),
|
||
createTextVNode(` 下载发票`, -1),
|
||
]),
|
||
],
|
||
10,
|
||
I,
|
||
),
|
||
]),
|
||
_: 1,
|
||
},
|
||
))
|
||
: unref(G)
|
||
? createCommentVNode(``, !0)
|
||
: (openBlock(),
|
||
createBlock(
|
||
h,
|
||
{
|
||
key: 1,
|
||
label: `获取发票文件`,
|
||
icon: `pi pi-download`,
|
||
severity: `secondary`,
|
||
outlined: ``,
|
||
loading: unref(H),
|
||
disabled: unref(H),
|
||
onClick: (i[0] ||= (e) =>
|
||
Y(
|
||
String(
|
||
unref(z).id ||
|
||
unref(b).query.id ||
|
||
``,
|
||
),
|
||
)),
|
||
},
|
||
null,
|
||
8,
|
||
[`loading`, `disabled`],
|
||
)),
|
||
]),
|
||
unref(U)
|
||
? (openBlock(),
|
||
createBlock(
|
||
s,
|
||
{
|
||
key: 1,
|
||
severity: `warn`,
|
||
closable: !1,
|
||
},
|
||
{
|
||
default: withCtx(() => [
|
||
createTextVNode(
|
||
toDisplayString(unref(U)) +
|
||
`。可稍后重试获取。`,
|
||
1,
|
||
),
|
||
]),
|
||
_: 1,
|
||
},
|
||
))
|
||
: !unref(Z) && !unref(G)
|
||
? (openBlock(),
|
||
createElementBlock(
|
||
`p`,
|
||
L,
|
||
`正式发票文件尚未提供,可在交付后查看或下载。`,
|
||
))
|
||
: createCommentVNode(``, !0),
|
||
]))
|
||
: createCommentVNode(``, !0),
|
||
])
|
||
);
|
||
}
|
||
);
|
||
},
|
||
}),
|
||
[[`__scopeId`, `data-v-3b8f6704`]],
|
||
);
|
||
export {};
|
||
export default R;
|
||
</script>
|