Files

634 lines
25 KiB
Vue
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<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>