Files

664 lines
22 KiB
Vue

<script>
/**
* 配置页右侧结算摘要:父级负责报价和真正提交,本组件负责按钮状态、登录跳转及限购提示。
* cart/buy/recalc/retry 是交给父级处理的意图事件;展示价格不是可直接信任的最终成交金额。
*/
import "~/assets/styles/PromoCodeField.qFEkB6Hm.css";
import { toDisplayString } from "vue";
import { renderList } from "vue";
import { onMounted } from "vue";
import { useId } from "vue";
import { onBeforeUnmount } from "vue";
import { renderSlot } from "vue";
import { watch } from "vue";
import { createBlock } from "vue";
import { withCtx } from "vue";
import { createCommentVNode } from "vue";
import { computed } from "vue";
import { createElementBlock } from "vue";
import { Fragment } 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 { navigateTo } from "#app";
import { NuxtLink } from "#components";
import { useApi } from "~/lib/auth.js";
import { useAuth } from "~/lib/auth.js";
import button from "primevue/button";
import message from "primevue/message";
import PromoCodeField from "~/components/config/PromoCodeField.vue";
import { t as purchase_limit_state_t } from "~/lib/purchase-limit-state.js";
var O = {
class: `config-summary-wrap`,
},
k = {
class: `config-summary`,
},
ee = {
class: `buy-bar`,
},
te = [`aria-busy`],
ne = {
key: 0,
class: `price-value`,
},
A = {
key: 1,
class: `price-pending`,
},
j = {
key: 0,
class: `pi pi-spin pi-spinner`,
"aria-hidden": `true`,
},
M = {
key: 2,
class: `level-hint`,
},
N = {
key: 1,
class: `cart-confirmation`,
role: `status`,
},
P = {
class: `cart-confirmation-message`,
},
F = {
key: 2,
class: `quote-status`,
},
I = {
key: 3,
class: `quote-status`,
role: `status`,
},
L = {
class: `buy-actions`,
},
R = {
key: 6,
class: `quote-status`,
role: `status`,
},
z = [`href`],
B = {
class: `config-mobile-label`,
},
V = Object.assign(
defineComponent({
__name: `ConfigCheckout`,
props: {
productId: {},
quantity: {},
editPosition: {},
summary: {},
price: {},
quoteReady: {
type: Boolean,
},
priceLoading: {
type: Boolean,
},
canSubmit: {
type: Boolean,
},
activeAction: {
default: null,
},
disabled: {
type: Boolean,
default: !1,
},
promoCode: {
default: ``,
},
promoDiscount: {
default: 0,
},
levelDiscount: {
default: 0,
},
error: {
default: ``,
},
actionError: {
default: ``,
},
cartTip: {
default: ``,
},
showCart: {
type: Boolean,
default: !0,
},
showPromo: {
type: Boolean,
default: !0,
},
editing: {
type: Boolean,
default: !1,
},
loginRedirect: {},
},
emits: [`update:promoCode`, `recalc`, `retry`, `cart`, `buy`],
setup(g, { emit: V }) {
let H = g,
U = V,
W = `configuration-${useId()}`,
G = useAuth(),
K = useRoute(),
q = computed(() => H.disabled || H.activeAction !== null),
J = purchase_limit_state_t((e) =>
useApi().post(`/purchase_limit/check`, e, !1, {
timeoutMs: 15e3,
}),
),
Y = computed(() => H.productId !== void 0 && G.isLoggedIn),
X = computed(() => Y.value && (!J.checked.value || !J.allowed.value)),
Z;
function Q() {
// 编辑购物车需要携带 position;商品、数量或账号变化时重新验证对应购买场景。
if (!Y.value) {
J.reset();
return;
}
let e = {
product_id: Number(H.productId),
qty: H.quantity ?? 1,
};
return J.check(
H.editPosition === void 0
? {
mode: `single`,
...e,
}
: {
mode: `cart_update`,
...e,
position: H.editPosition,
},
);
}
(onMounted(() => {
Z = watch(
() => [
G.token,
G.isLoggedIn,
H.productId,
H.quantity,
H.editPosition,
],
Q,
{
immediate: !0,
flush: `sync`,
},
);
}),
onBeforeUnmount(() => {
(Z?.(), J.reset());
}));
function $(e) {
// 报价未就绪、请求进行中或限购未通过时均不触发提交;未登录保留当前配置页跳转目标。
if (H.canSubmit && H.quoteReady && !H.priceLoading && !q.value) {
if (!G.isLoggedIn)
return navigateTo({
path: `/login`,
query: {
redirect: H.loginRedirect || K.fullPath,
},
});
X.value ||
(e === `cart` ? H.showCart && U(`cart`) : H.editing || U(`buy`));
}
}
return (n, r) => {
let i = PromoCodeField,
o = NuxtLink,
u = message,
y = button;
return (
openBlock(),
createElementBlock(`div`, O, [
(r[13] ||= createElementVNode(
`h2`,
{
class: `config-column-title`,
},
`所选配置`,
-1,
)),
createElementVNode(
`aside`,
{
id: W,
class: `panel config-checkout`,
"aria-label": `订单确认`,
},
[
(r[10] ||= createElementVNode(
`h3`,
{
class: `section-title`,
},
`配置详情`,
-1,
)),
createElementVNode(`dl`, k, [
(openBlock(!0),
createElementBlock(
Fragment,
null,
renderList(
g.summary,
(t, n) => (
openBlock(),
createElementBlock(
`div`,
{
key: `${t.label}-${n}`,
class: `config-summary-row`,
},
[
createElementVNode(
`dt`,
null,
toDisplayString(t.label),
1,
),
createElementVNode(
`dd`,
null,
toDisplayString(t.value),
1,
),
],
)
),
),
128,
)),
renderSlot(n.$slots, `summary`),
]),
n.$slots.default
? (openBlock(),
createElementBlock(
Fragment,
{
key: 0,
},
[
(r[5] ||= createElementVNode(
`div`,
{
class: `checkout-divider`,
},
null,
-1,
)),
renderSlot(n.$slots, `default`),
],
64,
))
: createCommentVNode(``, !0),
createElementVNode(`div`, ee, [
createElementVNode(
`div`,
{
class: `price-area`,
"aria-live": `polite`,
"aria-busy": g.priceLoading,
},
[
(r[6] ||= createElementVNode(
`span`,
{
class: `price-label`,
},
`配置费用`,
-1,
)),
g.quoteReady
? (openBlock(),
createElementBlock(
`span`,
ne,
`¥ ` + toDisplayString(g.price),
1,
))
: (openBlock(),
createElementBlock(`span`, A, [
g.priceLoading
? (openBlock(), createElementBlock(`i`, j))
: createCommentVNode(``, !0),
createTextVNode(
` ` +
toDisplayString(
g.priceLoading ? `正在计算…` : `待确认`,
),
1,
),
])),
g.quoteReady && g.levelDiscount > 0
? (openBlock(),
createElementBlock(
`span`,
M,
`已享会员折扣 -¥` +
toDisplayString(g.levelDiscount.toFixed(2)),
1,
))
: createCommentVNode(``, !0),
],
8,
te,
),
g.showPromo
? (openBlock(),
createBlock(
i,
{
key: 0,
"model-value": g.promoCode,
discount: g.quoteReady ? g.promoDiscount : 0,
loading: g.priceLoading,
disabled: unref(q),
"onUpdate:modelValue": (r[0] ||= (e) =>
U(`update:promoCode`, e)),
onRecalc: (r[1] ||= (e) => U(`recalc`)),
},
null,
8,
[`model-value`, `discount`, `loading`, `disabled`],
))
: createCommentVNode(``, !0),
g.cartTip
? (openBlock(),
createElementBlock(`div`, N, [
createElementVNode(`span`, P, [
(r[7] ||= createElementVNode(
`i`,
{
class: `pi pi-check-circle`,
"aria-hidden": `true`,
},
null,
-1,
)),
createTextVNode(toDisplayString(g.cartTip), 1),
]),
createVNode(
o,
{
to: `/cart`,
class: `cart-confirmation-link`,
},
{
default: withCtx(() => [
...(r[8] ||= [
createTextVNode(`查看购物车`, -1),
createElementVNode(
`i`,
{
class: `pi pi-arrow-right`,
"aria-hidden": `true`,
},
null,
-1,
),
]),
]),
_: 1,
},
),
]))
: createCommentVNode(``, !0),
renderSlot(n.$slots, `agreement`),
unref(G).isLoggedIn
? createCommentVNode(``, !0)
: (openBlock(),
createElementBlock(
`p`,
F,
`登录后可加入购物车或购买,登录完成后返回当前产品页面。`,
)),
unref(J).pending.value
? (openBlock(),
createElementBlock(`p`, I, `正在检查购买限制…`))
: createCommentVNode(``, !0),
unref(J).message.value
? (openBlock(),
createBlock(
u,
{
key: 4,
severity: `warn`,
closable: !1,
role: `alert`,
},
{
default: withCtx(() => [
createTextVNode(
toDisplayString(unref(J).message.value),
1,
),
]),
_: 1,
},
))
: createCommentVNode(``, !0),
unref(J).message.value
? (openBlock(),
createBlock(
y,
{
key: 5,
label: `重新检查购买限制`,
icon: `pi pi-refresh`,
severity: `secondary`,
size: `small`,
outlined: ``,
disabled: unref(q) || unref(J).pending.value,
onClick: Q,
},
null,
8,
[`disabled`],
))
: createCommentVNode(``, !0),
createElementVNode(`div`, L, [
g.showCart
? (openBlock(),
createBlock(
y,
{
key: 0,
label: g.editing ? `保存配置` : `加入购物车`,
icon: g.editing
? `pi pi-check`
: `pi pi-shopping-cart`,
severity: `secondary`,
outlined: ``,
loading: g.activeAction === `cart`,
disabled:
!g.canSubmit ||
!g.quoteReady ||
g.priceLoading ||
unref(q) ||
unref(X),
onClick: (r[2] ||= (e) => $(`cart`)),
},
null,
8,
[`label`, `icon`, `loading`, `disabled`],
))
: createCommentVNode(``, !0),
g.editing && !unref(q)
? (openBlock(),
createBlock(
o,
{
key: 1,
to: `/cart`,
class: `cart-confirmation-link`,
},
{
default: withCtx(() => [
...(r[9] ||= [createTextVNode(`取消`, -1)]),
]),
_: 1,
},
))
: g.editing
? createCommentVNode(``, !0)
: (openBlock(),
createBlock(
y,
{
key: 2,
label: `立即购买`,
loading: g.activeAction === `buy`,
disabled:
!g.canSubmit ||
!g.quoteReady ||
g.priceLoading ||
unref(q) ||
unref(X),
onClick: (r[3] ||= (e) => $(`buy`)),
},
null,
8,
[`loading`, `disabled`],
)),
]),
!g.quoteReady && !g.priceLoading
? (openBlock(),
createElementBlock(`div`, R, [
createElementVNode(
`p`,
null,
toDisplayString(
g.error
? `报价未能完成,请重试后再提交。`
: `请选择完整配置并计算报价后继续。`,
),
1,
),
createVNode(
y,
{
label: g.error ? `重新获取报价` : `计算报价`,
icon: `pi pi-refresh`,
severity: `secondary`,
size: `small`,
outlined: ``,
disabled: unref(q),
onClick: (r[4] ||= (e) => U(`retry`)),
},
null,
8,
[`label`, `disabled`],
),
]))
: createCommentVNode(``, !0),
g.error
? (openBlock(),
createBlock(
u,
{
key: 7,
severity: `error`,
closable: !1,
},
{
default: withCtx(() => [
createTextVNode(toDisplayString(g.error), 1),
]),
_: 1,
},
))
: createCommentVNode(``, !0),
g.actionError
? (openBlock(),
createBlock(
u,
{
key: 8,
severity: `error`,
closable: !1,
},
{
default: withCtx(() => [
createTextVNode(
toDisplayString(g.actionError),
1,
),
]),
_: 1,
},
))
: createCommentVNode(``, !0),
]),
],
),
createElementVNode(
`a`,
{
href: `#${W}`,
class: `config-mobile-total`,
},
[
createElementVNode(`span`, null, [
(r[11] ||= createTextVNode(`配置费用`, -1)),
createElementVNode(
`strong`,
null,
toDisplayString(
g.quoteReady
? `¥ ${g.price}`
: g.priceLoading
? `正在计算…`
: `待确认`,
),
1,
),
]),
createElementVNode(`span`, B, [
createTextVNode(
toDisplayString(
g.editing ? `查看配置与保存` : `查看配置与购买`,
),
1,
),
(r[12] ||= createElementVNode(
`i`,
{
class: `pi pi-angle-up`,
"aria-hidden": `true`,
},
null,
-1,
)),
]),
],
8,
z,
),
])
);
};
},
}),
{
__name: `ConfigCheckout`,
},
);
export {};
export default V;
</script>