docs: annotate account commerce finance and content pages

This commit is contained in:
cieanyau committed 2026-11-06 00:29:13 +08:00
1 parent 60827b8bfb
commit 2be21c1c62
24 files changed
+223

No files matched your search

+12
View File
@@ -1,4 +1,7 @@
<script>
/**
* API 密钥管理:列表分页、创建、IP 白名单编辑及删除。私钥仅在创建响应中保留,关闭弹窗或离开页面即清空,不能视为可再次查询的资料。
*/
import "~/assets/styles/api-keys.Bq3Csr53.css";
import { toDisplayString } from "vue";
import { onMounted } from "vue";
@@ -33,6 +36,7 @@ import paginator from "primevue/paginator";
import checkbox from "primevue/checkbox";
import column from "primevue/column";
import textarea from "primevue/textarea";
// 集中管理列表权限、写操作忙碌态和仅本次可见的私钥;请求代次与存活标记防止旧响应更新已离开的页面。
function D() {
let e = useApi(),
t = ref([]),
@@ -60,6 +64,7 @@ function D() {
onBeforeUnmount(() => {
((v = !1), y++, b());
});
// 刷新当前页并读取服务端 create_api 权限;响应结构无效时不开放创建入口。
async function x() {
if (!v) return;
let n = ++y;
@@ -86,6 +91,7 @@ function D() {
v && n === y && (o.value = !1);
}
}
// 只在权限已加载且允许创建时提交。创建响应不完整时提示先刷新核实,避免误以为失败而重复生成密钥。
async function C() {
if (!(!v || s.value || m.value)) {
if (((d.value = ``), (f.value = ``), !l.value || o.value)) {
@@ -123,6 +129,7 @@ function D() {
}
}
}
// 打开白名单编辑器时复制行数据,未保存的输入不直接修改列表。
function w(e) {
s.value ||
((d.value = ``),
@@ -131,6 +138,7 @@ function D() {
(g.enabled = Number(e.status) === 1),
(g.ip = e.ip || ``));
}
// 开启白名单必须提供 IP;保存成功后关闭编辑器并重新读取服务端数据。
async function T() {
if (!v || s.value || !h.value) return;
if (((d.value = ``), (f.value = ``), g.enabled && !g.ip.trim())) {
@@ -155,6 +163,7 @@ function D() {
v && (s.value = !1);
}
}
// 删除成功后,若当前页只剩这一条则回退一页,再刷新列表。
async function E() {
if (v && !s.value && _.value?.id) {
((d.value = ``), (f.value = ``), (s.value = !0));
@@ -271,6 +280,7 @@ var O = {
!e && !N.value && (U.value = null);
},
});
// 复制创建时返回的私钥;剪贴板不可用时保留手动复制提示,不把私钥写入持久存储。
async function he() {
if (z.value) {
J.value = ``;
@@ -282,9 +292,11 @@ var O = {
}
}
}
// 关闭私钥展示同时清空密钥与复制反馈,避免之后再次暴露。
function Z() {
(B(), (q.value = !1), (J.value = ``));
}
// 分页器为零基页码,接口页码从 1 开始。
function ge(e) {
((S.value = e.page + 1), W());
}
+5
View File
@@ -1,4 +1,7 @@
<script>
/**
* 第三方账号关联管理:从账户资料整理 OAuth 绑定状态,通过公共 OAuth 流程发起关联,并确认后解除绑定。
*/
import "~/assets/styles/WechatConnection.DI5ko1xy.css";
import { toDisplayString } from "vue";
import { renderList } from "vue";
@@ -77,6 +80,7 @@ var D = {
onBeforeUnmount(() => {
J = !1;
});
// 读取 /account 的 OAuth 关联列表;组件卸载后的响应不再更新界面。
async function Y() {
if (!R.value) {
((R.value = !0), (z.value = ``));
@@ -91,6 +95,7 @@ var D = {
}
}
}
// 仅对已关联的提供方执行解绑;请求完成后重新加载列表,以服务端结果为准。
async function X() {
if (U.value?.linked && !H.value && !W.value && J) {
((H.value = !0), (z.value = ``), (B.value = ``));
+25
View File
@@ -1,4 +1,7 @@
<script>
/**
* 账户设置聚合页:资料、登录密码、操作密码、手机、邮箱和流量预警分别维护表单与提交状态;敏感修改可由安全验证弹窗续接原请求。
*/
import "~/assets/styles/UploadField.BbTCTv6C.css";
import "~/assets/styles/PageSteps.B5K7G9zF.css";
import "~/assets/styles/PaymentDialog.BNFKQF1U.css";
@@ -324,6 +327,7 @@ var Ce = {
label: `流量预警`,
},
];
// 为账户设置标签提供左右方向键及 Home/End 导航,并同步实际焦点。
function Xt(e, t) {
let n = t;
if (e.key === `ArrowRight`) n = (t + 1) % E.length;
@@ -336,6 +340,7 @@ var Ce = {
document.getElementById(`account-tab-${T.value}`)?.focus());
}
let Zt = ref([]);
// 加载账户并回填资料表单,同时决定手机、邮箱是否需要先验证旧联系方式。
async function Qt() {
Gt.value = !0;
try {
@@ -354,6 +359,7 @@ var Ce = {
}
}
let $t = ref(!1);
// 国家选项按需加载;失败时保留空选项,后续仍可重新尝试。
async function en() {
if (!$t.value)
try {
@@ -380,9 +386,11 @@ var Ce = {
function N(e, t) {
D.value = e instanceof Error ? e.message : t;
}
// 暂存安全挑战及原操作闭包,验证成功后以原表单快照继续提交。
function rn(e, t) {
((tn.value = e), (A.value = t), (k.value = !0));
}
// 把安全验证结果交给待续接操作;再次出现挑战时更新弹窗,不把尚未验证的结果当成功。
async function an(e) {
if (A.value && !j.value) {
((j.value = !0), (D.value = ``));
@@ -405,6 +413,7 @@ var Ce = {
country_id: null,
}),
on = ref(!1);
// 保存可编辑资料,同时保留当前账户已有的 language、notes 字段,避免更新接口覆盖它们。
async function sn() {
(M(), (on.value = !0));
try {
@@ -424,6 +433,7 @@ var Ce = {
on.value = !1;
}
}
// 取消编辑时从账户快照还原表单,不额外写入接口。
function cn() {
(M(),
S.value &&
@@ -483,6 +493,7 @@ var Ce = {
onBeforeUnmount(() => {
((U = !0), clearInterval(gn), (A.value = null));
}));
// 向已绑定手机或邮箱发送 verify 验证码;成功后启动 60 秒倒计时,离页时清理计时器。
async function vn() {
if (
!(
@@ -518,6 +529,7 @@ var Ce = {
}
}
}
// 根据旧密码或验证码验证方式选择不同接口;密码一致性通过后才提交,安全挑战保留同一份请求数据。
async function yn() {
if (I.value || j.value || k.value || w(`password`)) return;
if (
@@ -602,6 +614,7 @@ var Ce = {
G = ref({}),
Sn = ref(!1),
Cn = ref(``);
// 分别加载云服务器与独立服务器的流量预警;单个模块失败只记录该模块错误。
async function wn() {
((Sn.value = !0), (G.value = {}));
try {
@@ -643,12 +656,14 @@ var Ce = {
Sn.value = !1;
}
}
// 开启预警且未选阈值时提供初始比例;关闭状态的实际提交比例在保存时归零。
function Tn(e, t) {
let n = +!!t,
r = W.value[e];
((r.warning_switch = n),
n === 1 && !r.leave_percent && (r.leave_percent = xn[1]));
}
// 按模块保存预警开关和剩余流量比例,避免另一模块的草稿被一并提交。
async function En(e) {
let t = W.value[e];
if (t) {
@@ -673,6 +688,7 @@ var Ce = {
re_operate_password: ``,
}),
Dn = ref(!1);
// 操作密码独立于登录密码;支持安全挑战续接,成功后清空密码输入。
async function On() {
if (Dn.value || j.value || k.value) return;
if ((M(), !K.operate_password)) {
@@ -730,6 +746,7 @@ var Ce = {
update: useCaptcha_t(`update`),
},
};
// 统一联系方式 verify/update 场景的验证码请求,并由各自验证码实例处理挑战失效。
async function jn(e, t, n = {}) {
let r = An[e][t],
ee = r.validationError();
@@ -746,6 +763,7 @@ var Ce = {
throw (await r.handleError(e), e);
}
}
// 向当前绑定手机号发送旧号码验证短信。
async function Mn() {
if (!(Y.value || w(`phone`))) {
(M(), (Y.value = !0));
@@ -759,6 +777,7 @@ var Ce = {
}
}
}
// 旧手机号验证通过后才进入新号码绑定步骤。
async function Nn() {
(M(), (Y.value = !0));
try {
@@ -773,6 +792,7 @@ var Ce = {
Y.value = !1;
}
}
// 向草稿中的新手机号发送 update 场景验证码。
async function Pn() {
if (!(Y.value || w(`phone`))) {
(M(), (Y.value = !0));
@@ -790,6 +810,7 @@ var Ce = {
}
}
}
// 完成新号码绑定后重载账户,清空新旧验证码并复位步骤。
async function Fn() {
(M(), (Y.value = !0));
try {
@@ -821,6 +842,7 @@ var Ce = {
t = e === `phone` ? J.value : Z.value;
return An[e][t === 1 ? `verify` : `update`];
});
// 向当前绑定邮箱发送旧邮箱验证邮件。
async function Ln() {
if (!(Q.value || w(`email`))) {
(M(), (Q.value = !0));
@@ -834,6 +856,7 @@ var Ce = {
}
}
}
// 旧邮箱验证通过后才进入新邮箱绑定步骤。
async function Rn() {
(M(), (Q.value = !0));
try {
@@ -848,6 +871,7 @@ var Ce = {
Q.value = !1;
}
}
// 向草稿中的新邮箱发送 update 场景验证码。
async function zn() {
if (!(Q.value || w(`email`))) {
(M(), (Q.value = !0));
@@ -864,6 +888,7 @@ var Ce = {
}
}
}
// 提交新邮箱及验证码;成功后重载账户资料并清空步骤输入。
async function Bn() {
(M(), (Q.value = !0));
try {
+3
View File
@@ -1,4 +1,7 @@
<script>
/**
* 企业实名认证路由适配层:复用统一实名认证页,仅把 initial-type 设为 company;认证状态、接口与上传流程均由统一页负责。
*/
import "~/assets/styles/UploadField.BbTCTv6C.css";
import "~/assets/styles/PageSteps.B5K7G9zF.css";
import "~/assets/styles/PaymentDialog.BNFKQF1U.css";
+25
View File
@@ -1,4 +1,7 @@
<script>
/**
* 实名认证流程:个人/企业资料 → 选择渠道及动态字段 → 必要时支付认证费 → 二维码核验与状态轮询。序号将异步结果绑定到当前资料、渠道和核验会话。
*/
import "~/assets/styles/UploadField.BbTCTv6C.css";
import "~/assets/styles/PageSteps.B5K7G9zF.css";
import "~/assets/styles/PaymentDialog.BNFKQF1U.css";
@@ -46,6 +49,7 @@ import tablist from "primevue/tablist";
import tab from "primevue/tab";
var b = `#contentBox img[src^="data:image/"], #qrcode img, #qrCode img, img#qrcode, img#qrCode, .qrcode img, .qr-code img`,
x = `img[src^="data:image/png;base64,"], img[src^="data:image/jpeg;base64,"]`;
// 从认证服务返回的 HTML 中定位二维码,保留其动态更新逻辑并隐藏其余内容;无法唯一定位时拒绝展示。
function S(e) {
let t = new DOMParser().parseFromString(e, `text/html`),
n =
@@ -454,6 +458,7 @@ var xe = {
flush: `sync`,
},
);
// 只收集已上传的图片标识,空字段不随申请发送。
function At() {
let e = {};
for (let [t, n] of Object.entries(G)) n && (e[t] = n);
@@ -466,9 +471,11 @@ var xe = {
Q = null,
$ = 0,
Mt = 0;
// 结束当前核验轮询并提升会话序号,使已在途回调失效。
function Nt() {
($++, Q !== null && (clearTimeout(Q), (Q = null)), (jt.value = !1));
}
// 读取实名开关及个人/企业状态;仅最新请求可以写入当前页面。
async function Pt() {
let e = ++M;
((xt.value = !0), (z.value = ``));
@@ -483,11 +490,13 @@ var xe = {
!N && e === M && (xt.value = !1);
}
}
// 切换渠道或关闭弹窗时清理动态字段与加载标识,同时使旧字段请求失效。
function Ft() {
(j++, (_t.value = ``), (A.value = ``), (k.value = !1));
for (let e of Object.keys(O)) delete O[e];
gt.value = [];
}
// 兼容服务端布尔、数字和字符串形式的必填标识。
function It(e) {
return (
e.required === !0 ||
@@ -496,6 +505,7 @@ var xe = {
e.required === `true`
);
}
// 将数组、对象、JSON 字符串或逗号列表整理为选择项,供认证渠道动态表单使用。
function Lt(e) {
if (Array.isArray(e))
return e.map((e) => ({
@@ -521,6 +531,7 @@ var xe = {
}
return [];
}
// 加载当前认证类型与渠道的动态字段;请求结束时同时核对渠道、类型、弹窗状态和代次。
async function Rt(e) {
Ft();
let t = j,
@@ -553,6 +564,7 @@ var xe = {
i() && (k.value = !1);
}
}
// 验证个人资料及要求上传的证件后,暂存申请并进入渠道选择。
async function zt() {
if (!(W.value || C.value || Y.value || P.value || !Dt.value)) {
if (((z.value = ``), K.value))
@@ -569,6 +581,7 @@ var xe = {
});
}
}
// 企业申请额外校验企业实名开关、个人认证前置条件、营业执照和必要的委托书。
async function Bt() {
if (!(
W.value ||
@@ -597,6 +610,7 @@ var xe = {
});
}
}
// 保存待提交的资料快照;渠道选择不直接修改原始表单。
async function Vt(e, t) {
((F.value = null),
(D.value = {
@@ -607,6 +621,7 @@ var xe = {
(C.value = !0),
await Ht());
}
// 加载可用认证插件,使用独立代次隔离弹窗重开或重试。
async function Ht() {
if (!C.value || W.value) return;
let e = ++I;
@@ -625,6 +640,7 @@ var xe = {
e === I && (w.value = !1);
}
}
// 非提交期间允许关闭渠道弹窗,并使其异步加载结果失效。
function Ut() {
W.value ||
(I++,
@@ -635,6 +651,7 @@ var xe = {
Ft(),
(D.value = null));
}
// 确认动态字段与当前渠道一致后检查渠道费用;需要付费时先保存申请快照并打开支付,不提前提交认证。
async function Wt() {
if (!C.value || w.value || W.value || !D.value) return;
let e = L.value.find((e) => e.name === E.value);
@@ -720,6 +737,7 @@ var xe = {
r === I && (W.value = !1);
}
}
// 已通过个人认证的企业升级走 convert,其余申请走 person/company;渠道字段随同原资料提交。
async function Gt(e, t, n, r) {
let i =
e === `company` && Number(R.value?.person?.status) === 1
@@ -731,6 +749,7 @@ var xe = {
plugin_name: n,
});
}
// 支付回调后再次查询渠道订单,确认同一订单已 Paid 才续交认证,不能仅凭前端支付事件认定到账。
async function Kt() {
let e = F.value;
if (!e || W.value || N) return;
@@ -764,9 +783,11 @@ var xe = {
!N && t === I && (W.value = !1);
}
}
// 重新打开待支付认证订单,不重复生成申请快照。
function qt() {
!W.value && F.value && (P.value = !0);
}
// 开启新的二维码核验会话,先获取二维码,再为当前认证类型启动轮询。
async function Jt(e = V.value === 1 ? `company` : `person`) {
Nt();
let t = $;
@@ -777,6 +798,7 @@ var xe = {
await Xt(t),
t === $ && Y.value && Zt(t, e));
}
// 认证资料失效或变更时终止旧核验并刷新资料,要求用户重新提交。
async function Yt(e) {
if (![`10000`, `10001`].includes(String(e))) return !1;
Qt();
@@ -792,6 +814,7 @@ var xe = {
!0
);
}
// 按当前核验会话加载二维码,并设置刷新时间门槛;过期会话的响应不再显示。
async function Xt(e) {
if (e === $ && Y.value) {
((Z.value = !0), (Mt = Date.now() + (X.value ? 3e4 : 1e4)));
@@ -819,6 +842,7 @@ var xe = {
}
}
}
// 每两秒查询核验状态;第三方完成后仍复查本平台认证资料,区别认证成功与进入审核,关闭后停止调度。
function Zt(e, t) {
jt.value = !0;
let n = () => e === $ && Y.value;
@@ -874,6 +898,7 @@ var xe = {
}
Q = setTimeout(r, 2e3);
}
// 关闭二维码核验并清空 HTML,同时取消下一次状态查询。
function Qt() {
((Y.value = !1), Nt(), (Z.value = !1), (X.value = ``));
}
+3
View File
@@ -1,4 +1,7 @@
<script>
/**
* 个人实名认证路由适配层:复用统一实名认证页,以 person 作为初始认证类型,不单独维护一套提交逻辑。
*/
import "~/assets/styles/UploadField.BbTCTv6C.css";
import "~/assets/styles/PageSteps.B5K7G9zF.css";
import "~/assets/styles/PaymentDialog.BNFKQF1U.css";
+3
View File
@@ -1,4 +1,7 @@
<script>
/**
* 账单详情兼容路由:复用订单详情页面;以 fullPath 为组件键,保证切换账单参数时重新建立详情状态。
*/
import "~/assets/styles/PaymentDialog.BNFKQF1U.css";
import "~/assets/styles/_id_.gjoJy9S8.css";
definePageMeta({
+3
View File
@@ -1,4 +1,7 @@
<script>
/**
* 旧账单列表入口:保留原查询参数与 hash,重定向到 /finance?tab=bills;本页不维护第二份账单列表。
*/
definePageMeta({
redirect: {
redirect: (e) => ({
+26
View File
@@ -1,4 +1,7 @@
<script>
/**
* 购物车:读取服务端购物车、逐项重新报价、保留选择并结算。修改使用 revision 或 expected_cart 进行并发校验,不能把列表下标当作永久商品标识。
*/
import "~/assets/styles/PaymentDialog.BNFKQF1U.css";
import "~/assets/styles/cart.CSS2vTmS.css";
import { toDisplayString } from "vue";
@@ -40,15 +43,18 @@ import { t as purchase_limit_state_t } from "~/lib/purchase-limit-state.js";
import { a as cart_edit_a } from "~/lib/cart-edit.js";
import { i as cart_edit_i } from "~/lib/cart-edit.js";
import { t as cart_edit_t } from "~/lib/cart-edit.js";
// 只接受普通对象形状的数据,供配置摘要解析使用。
function E(e) {
return typeof e == `object` && e && !Array.isArray(e) ? e : void 0;
}
// 将可展示的配置值限制为文本;疑似 HTML 或编码标签不作为摘要内容。
function D(e) {
if (typeof e != `string` && (typeof e != `number` || !Number.isFinite(e)))
return ``;
let t = String(e).trim();
return /<\/?[a-z!]|&(?:amp;)*(?:lt|gt|quot|#0*60|#x0*3c);/i.test(t) ? `` : t;
}
// 仅在数值格式与单位明确时生成 CPU/内存/带宽等展示值。
function O(e, t) {
let n = D(e);
return n
@@ -73,10 +79,12 @@ var k = {
day: `天`,
daily: `天`,
};
// 将计费周期转换为可读名称,未识别的机器枚举不直接展示。
function A(e) {
let t = D(e);
return k[t.toLowerCase()] ?? (/^(?:[a-z_]+|\d+)$/i.test(t) ? `` : t);
}
// 归一化不同模块的配置标签,用于摘要去重和识别 CPU、内存、周期、镜像等字段。
function j(e, t = ``) {
return /^(?:cpu|cpu_num)$/i.test(t) ||
/^(?:cpu|CPU核数|处理器|核数)$/i.test(e)
@@ -93,6 +101,7 @@ function j(e, t = ``) {
? `os`
: e;
}
// 摘要排除密码、令牌、私钥及内部 ID 等字段;不能直接遍历配置对象展示所有内容。
function M(e, t = ``) {
return (
/(?:password|passwd|secret|token|private.?key|ssh.?key|credential|description|密码|口令|密钥|令牌|产品介绍|商品介绍|产品描述|商品描述)/i.test(
@@ -102,6 +111,7 @@ function M(e, t = ``) {
/(?:^|\s)id$/i.test(e)
);
}
// 当报价接口未提供 preview 时,从已知配置字段整理摘要。
function N(e, t) {
let n = [],
r = (e, t) => {
@@ -134,6 +144,7 @@ function N(e, t) {
n
);
}
// 优先使用报价 preview,过滤敏感项并合并 CPU/内存/套餐等重复信息;缺失时才使用已知配置字段。
function pe(e, t) {
let n = E(e.config_options) ?? {},
r =
@@ -391,6 +402,7 @@ var me = {
e.customfield,
e.self_defined_field,
]);
// 按商品配置签名及同签名出现次数记录选择,列表重排时不误选另一件同款商品。
function We() {
let e = new Map();
return D.value
@@ -401,6 +413,7 @@ var me = {
})
.filter(Boolean);
}
// 根据重新加载后的列表重建选择下标,避免沿用过期的位置。
function Ge(e) {
let t = new Map();
A.value = D.value.flatMap((n, r) => {
@@ -409,6 +422,7 @@ var me = {
return (t.set(i, a + 1), e.includes(`${i}:${a}`) ? [r] : []);
});
}
// 金额必须是非空且有限的非负数字;未返回报价不能当作零元。
function Ke(e) {
return (
e != null &&
@@ -417,6 +431,7 @@ var me = {
Number(e) >= 0
);
}
// 逐项请求最新报价;同时核对购物车代次、列表快照和单项请求序号,旧响应不覆盖新配置。
async function qe(e = D.value.map((e, t) => t)) {
let t = U,
n = q();
@@ -481,6 +496,7 @@ var me = {
X.value !== null &&
(!w.value || (C.checked.value && C.allowed.value)),
);
// 结算限购预检针对当前选择的位置;没有选择或仍在加载时清除旧预检。
function Ze() {
if (!w.value || k.value || !A.value.length) {
C.reset();
@@ -491,6 +507,7 @@ var me = {
positions: [...A.value],
});
}
// 刷新购物车时先废弃旧报价,再按配置签名恢复摘要与选择,最后重新报价。
async function Z(e = !1) {
let t = ++W,
n = e ? We() : [],
@@ -546,6 +563,7 @@ var me = {
let t = A.value.indexOf(e);
t === -1 ? A.value.push(e) : A.value.splice(t, 1);
}
// 遇到 409 并发冲突时重载购物车并清空选择,要求用户重新确认,避免误改已移动的下标。
async function Q(e, t) {
let n = e instanceof Error ? e.message : t;
e && typeof e == `object` && `status` in e && e.status === 409
@@ -556,6 +574,7 @@ var me = {
(M.value = N.value ? `${n};${M.value}` : n))
: (M.value = n);
}
// 先保存购物车编辑上下文,再进入对应商品页;商品页会再次确认该位置仍匹配商品。
async function et(e) {
if (!j.value && D.value[e]) {
j.value = !0;
@@ -574,6 +593,7 @@ var me = {
}
}
}
// 修改数量必须为正整数,并携带当前购物车并发校验信息。
async function tt(e, t) {
if (!(j.value || !Number.isInteger(t) || t < 1 || !D.value[e])) {
((j.value = !0), (M.value = ``));
@@ -591,6 +611,7 @@ var me = {
}
}
let $ = ref(null);
// 确认删除前记录位置与整个购物车签名,等待确认期间列表变化则不得继续使用旧位置。
function nt(e) {
let t = D.value[e];
!j.value &&
@@ -602,6 +623,7 @@ var me = {
label: `删除“${product_name_n(t.name)}”`,
});
}
// 清空操作记录当时的全部位置与签名,最终仍由统一确认函数校验。
function rt() {
!j.value &&
D.value.length &&
@@ -612,6 +634,7 @@ var me = {
label: `清空购物车`,
});
}
// 批量删除仅暂存当前选中位置,不立即发送删除请求。
function it() {
!j.value &&
A.value.length &&
@@ -622,6 +645,7 @@ var me = {
label: `删除选中的 ${A.value.length} 项商品`,
});
}
// 确认时再核对购物车签名;单项、批量、清空分别调用对应接口并携带并发校验。
async function at() {
let e = $.value;
if (e && !j.value) {
@@ -650,6 +674,7 @@ var me = {
}
}
}
// 结算要求选择项报价均已确认;服务端返回订单后打开支付并刷新购物车。
async function ot() {
if (!(j.value || P.value)) {
if (((M.value = ``), !A.value.length)) {
@@ -685,6 +710,7 @@ var me = {
}
}
}
// 支付完成后进入订单列表,订单与支付状态仍以服务端为准。
function st() {
E.push(`/orders`);
}
+3
View File
@@ -1,4 +1,7 @@
<script>
/**
* 云服务器列表入口:校验动态菜单参数 m 为正的安全整数,然后把云服务器模块组与菜单 ID 交给 HostList。错误参数显示提示,不静默展示其他分组。
*/
import "~/assets/styles/PaymentDialog.BNFKQF1U.css";
import "~/assets/styles/OsIcon.CAi4Iz2S.css";
import "~/assets/styles/HostList.B3U15sJm.css";
+3
View File
@@ -1,4 +1,7 @@
<script>
/**
* 物理服务器列表入口:复用 HostList 的物理服务器模块组;动态菜单 m 必须通过正整数校验,组件 key 随菜单变化以重置列表状态。
*/
import "~/assets/styles/PaymentDialog.BNFKQF1U.css";
import "~/assets/styles/OsIcon.CAi4Iz2S.css";
import "~/assets/styles/HostList.B3U15sJm.css";
+15
View File
@@ -1,4 +1,7 @@
<script>
/**
* 财务中心:账单、交易、余额、提现与冻结记录分开加载;钱包入口为本页别名,充值/提现能力由站点配置决定。
*/
import "~/assets/styles/orders.BflDlvVz.css";
import "~/assets/styles/WithdrawDialog.ks0wdKEK.css";
import "~/assets/styles/PaymentDialog.BNFKQF1U.css";
@@ -147,6 +150,7 @@ var je = {
et = ref(!1),
M = ref(null),
N = ref(``);
// 账户总览变化时同步余额提醒设置,仅回填本地草稿。
function tt() {
let e = S.overview;
e &&
@@ -156,6 +160,7 @@ var je = {
watch(() => S.overview, tt, {
immediate: !0,
});
// 开启余额提醒必须填写正的有限阈值;关闭时发送零阈值,成功后同步账户总览。
async function nt() {
((j.value = ``), (et.value = !1));
let e = Number(k.value ?? 0);
@@ -182,6 +187,7 @@ var je = {
A.value = !1;
}
}
// 读取待审核退款总额;接口未开放的 403/404 不作为普通页面错误展示。
async function rt() {
N.value = ``;
try {
@@ -200,6 +206,7 @@ var je = {
: `待审核退款金额加载失败`;
}
}
// 只允许已知财务标签值,其他查询参数回落到账单。
function P(e) {
return typeof e == `string` &&
[`bills`, `transaction`, `credit`, `withdraw`, `freeze`].includes(e)
@@ -207,6 +214,7 @@ var je = {
: `bills`;
}
let F = ref(P(x.query.tab));
// 切换标签时更新 URL 并保留其他查询参数,使刷新后仍能恢复位置。
function it(e) {
return navigateTo(
{
@@ -278,6 +286,7 @@ var je = {
value: `Artificial`,
},
];
// 搜索词在提交后才应用;按当前标签重置对应页码并加载。
function V() {
((B.value = z.value.trim()),
F.value === `transaction`
@@ -306,6 +315,7 @@ var je = {
G = ref(``),
K = ref(`0.00`),
q = 0;
// 交易流水使用独立请求序号,快速筛选时忽略更早的结果。
async function J() {
let e = ++q;
((ut.value = !0), (U.value = ``));
@@ -328,6 +338,7 @@ var je = {
}
}
let Y = 0;
// 余额流水与累计金额同步更新;失败时不保留旧金额冒充新结果。
async function X() {
let e = ++Y;
((pt.value = !0), (G.value = ``));
@@ -358,6 +369,7 @@ var je = {
function ht(e) {
((W.value = e.page + 1), (T.value = e.rows), X());
}
// 充值完成后刷新账户余额与相关流水,不在本地直接累加金额。
function gt() {
(S.refreshOverview(), X(), J());
}
@@ -397,6 +409,7 @@ var je = {
: Z.value;
}),
Ct = 0;
// 按服务端状态分页查询提现记录;本地关键词筛选仅作用于当前返回页。
async function Q() {
let e = ++Ct;
((bt.value = !0), (xt.value = ``));
@@ -420,6 +433,7 @@ var je = {
function wt(e) {
((yt.value = e.page + 1), (T.value = e.rows), Q());
}
// 提现完成后刷新账户总览、提现列表及余额明细。
function Tt() {
(S.refreshOverview(), Q(), X());
}
@@ -428,6 +442,7 @@ var je = {
Ot = ref(1),
kt = ref(!1),
$ = ref(``);
// 冻结余额独立分页读取;异常时清空旧列表并显示错误。
async function At() {
((kt.value = !0), ($.value = ``));
try {
+5
View File
@@ -1,4 +1,7 @@
<script>
/**
* 密码找回:手机或邮箱验证码配合验证码挑战提交重置请求,成功后返回登录并保留经处理的站内跳转参数。
*/
import "~/assets/styles/PhoneCodeField.CwyHXfML.css";
import "~/assets/styles/GeetestField.DiieTibK.css";
import "~/assets/styles/CaptchaField.BSN3ZbsD.css";
@@ -119,6 +122,7 @@ var D = {
error: W,
phoneCode: () => U.phone_code,
});
// 复用 password_reset 场景的验证码发送与倒计时,不在页面另写一套短信请求。
function fe() {
if (G.value) return;
let e = U.account.trim();
@@ -128,6 +132,7 @@ var D = {
H.value === `email` ? `请输入邮箱` : `请输入手机号`,
);
}
// 校验账号、区号、验证码和两次密码后提交重置;失败交由验证码实例处理挑战刷新。
async function pe() {
if (G.value || Q.value) return;
W.value = ``;
+7
View File
@@ -1,4 +1,7 @@
<script>
/**
* 帮助中心:支持独立文章路由和资源中心嵌入模式;目录与文章分别加载,通过请求序号防止快速切换文章时出现旧正文。
*/
import "~/assets/styles/help.BSOB30LE.css";
definePageMeta({
scrollToTop: !0,
@@ -157,11 +160,13 @@ var me = {
L.value.find((e) => e.helps?.some((e) => e.id === q.value))
?.name ?? ``,
);
// 嵌入模式使用资源中心地址,独立模式使用帮助文章地址,链接统一保留文章 ID。
function Ce(e) {
return x?.embedded
? `/resources?section=help&id=${e}`
: `/help/article?id=${e}`;
}
// 从路由校验文章 ID;未明确指定文章时选择目录首篇,无效编号不继续请求详情。
async function Z() {
if (X) return;
let e = F.query.id !== void 0 || F.path === `/help/article`,
@@ -183,6 +188,7 @@ var me = {
(K.value = !1),
(z.value = ``));
}
// 加载帮助目录后再解析当前文章;目录请求代次与文章请求代次互相独立。
async function Q() {
let e = ++Y;
((R.value = !0), (B.value = ``));
@@ -198,6 +204,7 @@ var me = {
}
!X && e === Y && (await Z());
}
// 每次切换文章先清除旧正文,再读取详情;仅当前请求且页面仍存活时更新状态。
async function $(e) {
let t = ++J;
((q.value = e), (K.value = !0), (W.value = null), (z.value = ``));
+8
View File
@@ -1,4 +1,7 @@
<script>
/**
* 会员中心首页:账户总览、登录提示及各业务概览面板的组合入口;问候语随本地时间更新,实名状态单独读取。
*/
import "~/assets/styles/WithdrawDialog.ks0wdKEK.css";
import "~/assets/styles/PaymentDialog.BNFKQF1U.css";
import "~/assets/styles/RechargeDialog.DpsMly4r.css";
@@ -43,6 +46,7 @@ import HomeReferralPanel from "~/components/home/HomeReferralPanel.vue";
import HomeServerPanel from "~/components/home/HomeServerPanel.vue";
import HomeTicketPanel from "~/components/home/HomeTicketPanel.vue";
import HomeWalletCard from "~/components/home/HomeWalletCard.vue";
// 按本地时段选择问候语,不影响服务端账户或计费时间。
function S(e) {
let t = e.getHours();
return t < 5 || t >= 22
@@ -75,6 +79,7 @@ function S(e) {
icon: `lucide:sunset`,
};
}
// 把上次登录的秒级时间戳转换为可读时间;缺失或无效时展示无历史记录。
function C(e) {
let t = e?.previous_login,
n = Number(t?.time),
@@ -175,9 +180,11 @@ var w = {
K = computed(() => S(G.value)),
q = computed(() => C(b.overview)),
J;
// 更新问候语使用的时间;定时与页面可见性事件共用此入口。
function Y() {
G.value = new Date();
}
// 复制账户 ID;剪贴板失败时只复位反馈,不影响账户数据。
async function me() {
if (b.overview)
try {
@@ -190,6 +197,7 @@ var w = {
let X = ref(null),
Z = ref(!0),
Q = ref(``);
// 刷新账户总览;会话失效由鉴权层处理,其他失败在首页单独提示。
function $() {
((Q.value = ``),
b.fetchOverview().catch((e) => {
+13
View File
@@ -1,4 +1,7 @@
<script>
/**
* 发票列表与申请入口共用页面:加载可开票订单、抬头、收票地址、项目及税费配置;报价必须匹配当前表单签名后才可提交。
*/
import "~/assets/styles/PageInfoNotice._16xRFrB.css";
import "~/assets/styles/PaymentDialog.BNFKQF1U.css";
import "~/assets/styles/invoices.t1P1GXOx.css";
@@ -397,6 +400,7 @@ var Ce = {
tax: V.tax_rate,
}),
);
// 打开申请时重置上次草稿,并完整加载所有分页选项;默认值确定后再请求报价。
async function J() {
if (!(D.value || E.value)) {
((T.value = !0),
@@ -521,6 +525,7 @@ var Ce = {
: `请选择当前抬头支持的开票项目`
: `请选择有效的发票抬头`;
});
// 报价以排序后的订单 ID 和全部开票选项作为签名;更早响应或表单已变更的结果不得用于提交。
async function Q() {
let e = ++P.value;
if (
@@ -578,6 +583,7 @@ var Ce = {
.reduce((e, t) => e + Number(t.amount || 0), 0)
.toFixed(2);
});
// 重新校验订单有效性、抬头、收票方式及最新报价后申请;返回费用订单时转入支付,不直接认定发票已开具。
async function Et() {
if (E.value || D.value || !O.value) return;
if (((k.value = ``), Z.value)) {
@@ -633,12 +639,14 @@ var Ce = {
E.value = !1;
}
}
// 只接受正整数形式的费用订单 ID,防止无效跳转或支付目标。
function Dt(e) {
return (
(typeof e == `string` || typeof e == `number`) &&
/^[1-9]\d*$/.test(String(e))
);
}
// 只有具有有效费用订单且处于可继续处理的支付状态,才展示对应入口。
function Ot(e) {
return (
Dt(e.invoice_order_id) &&
@@ -647,6 +655,7 @@ var Ce = {
)
);
}
// 未付款的发票费用订单打开支付,其余待审核凭证状态交给订单详情处理。
function kt(e) {
if (Ot(e)) {
if (e.order_status !== `Unpaid`) {
@@ -656,9 +665,11 @@ var Ce = {
((vt.value = e.invoice_order_id), (F.value = !0));
}
}
// 支付结束后退出申请专用路由或刷新列表,开票状态以服务端为准。
function At() {
((F.value = !1), S.value ? x.push(`/invoices`) : w());
}
// 申请弹窗关闭且没有有效草稿时,申请专用路由回到发票列表。
function jt(e) {
!e && S.value && !O.value && x.push(`/invoices`);
}
@@ -670,9 +681,11 @@ var Ce = {
`wait_create`,
`create_fail`,
]);
// 可删除状态集中列举,已开具、已寄出等终态不开放撤回。
function Nt(e) {
return Mt.has(String(e.status || ``).toLowerCase());
}
// 撤回需要状态允许且用户确认;删除后重新读取列表。
async function Pt(e) {
if (
Nt(e) &&
+7
View File
@@ -1,4 +1,7 @@
<script>
/**
* 发票详情:按查询 ID 加载发票,区分历史登记与正式电子文件;下载链接必须通过协议与字符校验。
*/
import "~/assets/styles/invoice.B6sYFYlb.css";
definePageMeta({
key: (e) => e.fullPath,
@@ -104,6 +107,7 @@ var T = {
: W[String(z.value?.status || ``).toLowerCase()] ||
String(z.value?.status || `—`),
);
// 下载地址仅允许 HTTP(S) 或站内绝对路径,拒绝反斜杠、空白控制字符和协议相对地址。
function q(e) {
return typeof e != `string` || /[\u0000-\u0020\\]/.test(e)
? ``
@@ -111,6 +115,7 @@ var T = {
? e
: ``;
}
// 从详情的候选字段中选择第一个非空值,用于兼容不同发票字段展示。
function J(...e) {
for (let t of e) {
let e = z.value?.[t];
@@ -118,6 +123,7 @@ var T = {
}
return ``;
}
// 普通发票尚无有效下载地址时单独请求文件地址;历史已开票登记不伪造下载文件。
async function Y(e) {
if (!(G.value || q(z.value?.invoice_url))) {
((H.value = !0), (U.value = ``));
@@ -138,6 +144,7 @@ var T = {
}
}
}
// 校验查询 ID 并确认响应含发票资料,再按需要获取正式文件地址。
async function X() {
((B.value = !0), (V.value = ``));
try {
+3
View File
@@ -1,4 +1,7 @@
<script>
/**
* 发票申请路由适配层:复用发票列表页,具体申请专用交互由该页根据当前路由决定。
*/
import "~/assets/styles/PageInfoNotice._16xRFrB.css";
import "~/assets/styles/PaymentDialog.BNFKQF1U.css";
import "~/assets/styles/invoices.t1P1GXOx.css";
+13
View File
@@ -1,4 +1,7 @@
<script>
/**
* 发票资料设置:统一维护抬头与收票地址;编辑器复制原数据,提交按新增/修改及电子/纸质地址分别组装字段。
*/
import "~/assets/styles/settings.zV3AWuRw.css";
import { toDisplayString } from "vue";
import { onMounted } from "vue";
@@ -145,6 +148,7 @@ var ue = {
M = ref([]),
N = ref(!0),
P = ref(``);
// 完整读取抬头与地址的所有分页,避免选择器仅显示第一页资料。
async function F() {
((N.value = !0), (P.value = ``));
try {
@@ -182,6 +186,7 @@ var ue = {
bank: ``,
bank_user: ``,
});
// 重置抬头草稿后回填待编辑记录,避免上次表单字段残留。
function V(e) {
((L.value = e?.id ?? null),
(z.value = ``),
@@ -205,6 +210,7 @@ var ue = {
}),
(I.value = !0));
}
// 抬头名称必填;新增与修改成功后统一重新加载资料列表。
async function We() {
if (!R.value) {
if (((z.value = ``), !B.title.trim())) {
@@ -230,6 +236,7 @@ var ue = {
}
}
}
// 删除抬头后重载列表,失败在页面保留错误提示。
async function H(e) {
try {
(await v.del(`/invoice_title/${e.id}`), await F());
@@ -249,6 +256,7 @@ var ue = {
phone: ``,
is_default: !1,
});
// 电子邮箱和纸质地址共用编辑器;打开时恢复默认字段,再复制现有资料。
function J(e) {
((W.value = e?.id ?? null),
(K.value = ``),
@@ -271,6 +279,7 @@ var ue = {
}),
(U.value = !0));
}
// 电子地址只提交邮箱,纸质地址提交收件地址与电话,避免把另一种地址的草稿字段发给接口。
async function Ge() {
if (!G.value) {
if (((K.value = ``), q.rec_type === `email` && !q.email.trim())) {
@@ -306,6 +315,7 @@ var ue = {
}
}
}
// 删除收票地址后重载资料。
async function Y(e) {
try {
(await v.del(`/invoice_address/${e.id}`), await F());
@@ -316,6 +326,7 @@ var ue = {
let X = ref(!1),
Z = ref(!1),
Q = ref(null);
// 记录待删除抬头,在确认前不发起删除。
function Ke(e) {
((Q.value = {
kind: `title`,
@@ -323,6 +334,7 @@ var ue = {
}),
(X.value = !0));
}
// 记录待删除地址,复用同一确认弹窗。
function qe(e) {
((Q.value = {
kind: `address`,
@@ -330,6 +342,7 @@ var ue = {
}),
(X.value = !0));
}
// 确认时按目标类型调用删除函数,用独立忙碌态阻止重复确认。
async function Je() {
if (Q.value && !Z.value) {
Z.value = !0;
+5
View File
@@ -1,4 +1,7 @@
<script>
/**
* 操作日志:系统/API 日志与关键词、排序通过分页接口查询;路由 type 仅接受 api,其余回落为 system。
*/
import "~/assets/styles/logbook.Y7gm684m.css";
import { toDisplayString } from "vue";
import { watch } from "vue";
@@ -84,9 +87,11 @@ var k = {
},
);
let J = computed(() => !!F.value || L.value !== `system`);
// 搜索输入在确认后复制到已应用关键词,并让分页工具重新查询。
function Y() {
((F.value = y.value.trim()), q());
}
// 清空筛选并恢复默认 ID 倒序和系统日志类型,再刷新列表。
function X() {
((y.value = ``),
(F.value = ``),
+11
View File
@@ -1,4 +1,7 @@
<script>
/**
* 站内消息:分页筛选、批量已读/删除与详情弹窗;读状态变化同时刷新公共邮箱计数,详情请求用序号隔离快速切换。
*/
import "~/assets/styles/NotificationPreferences.DcH8Noxd.css";
import "~/assets/styles/messages.asRdYcVu.css";
definePageMeta({
@@ -163,12 +166,15 @@ var ge = {
value: e.name,
})),
]);
// 类型显示优先使用服务端本地化名称,未知类型保留原标识。
function H(e) {
return E.value.find((t) => t.name === e)?.name_lang || e || `—`;
}
// 提交后才应用搜索词,避免输入每个字符都发请求。
function Le() {
((j.value = A.value.trim()), R());
}
// 清空阅读状态、类型与关键词,重新加载消息列表。
function Re() {
((A.value = ``),
(j.value = ``),
@@ -176,6 +182,7 @@ var ge = {
(k.value = ``),
R());
}
// 将指定 ID 标为已读,完成后清除选择并刷新列表与全局未读计数。
async function ze(e) {
if (!(!e.length || B.value || G.value)) {
((B.value = !0), (U.value = ``));
@@ -193,6 +200,7 @@ var ge = {
}
}
}
// 使用 all 标记请求服务端全部已读,不局限于当前可见页。
async function Be() {
if (!(B.value || G.value)) {
((B.value = !0), (U.value = ``));
@@ -213,12 +221,14 @@ var ge = {
let U = ref(``),
W = ref(!1),
G = ref(!1);
// 删除前先打开确认弹窗,读状态更新和删除期间不重复触发。
function Ve() {
!z.value.length ||
B.value ||
G.value ||
((U.value = ``), (W.value = !0));
}
// 仅提交选中消息的 ID;成功后同步列表与未读计数。
async function He() {
if (!z.value.length || G.value || B.value) return;
let e = z.value.map((e) => e.id);
@@ -244,6 +254,7 @@ var ge = {
Y = ref(``),
X = ref(null),
Z = 0;
// 详情打开时清除旧正文并递增请求序号;加载成功后尝试标读,标读失败不覆盖已加载的正文。
async function Q(e) {
let t = ++Z;
((X.value = e),
+10
View File
@@ -1,4 +1,7 @@
<script>
/**
* 新闻资讯:分类与关键词分页查询,文章可独立打开或嵌入资源中心;正文加载和列表状态分开维护。
*/
import "~/assets/styles/news.CbIzdrjt.css";
definePageMeta({
scrollToTop: !0,
@@ -131,6 +134,7 @@ var fe = {
keywords: R.value,
}),
});
// 新闻分类加载失败不阻止列表使用,保留空分类选项。
async function Ee() {
try {
let e = await F.get(`/news/type`);
@@ -139,9 +143,11 @@ var fe = {
I.value = [];
}
}
// 选择分类后应用其 ID 并重新查询列表。
function De(e) {
((L.value = e === `` || e === void 0 ? `` : Number(e)), U());
}
// 摘要先经过公共清理函数,再移除标签、尾部截断实体和多余空格;不能把摘要当可信 HTML。
function Oe(e) {
return sanitize_t(e || ``)
.replace(/<[^>]*>/g, ``)
@@ -158,11 +164,13 @@ var fe = {
J = ref(null),
Y = 0,
X = !1;
// 根据嵌入模式生成资源中心或独立新闻文章地址。
function ke(e) {
return x?.embedded
? `/resources?section=news&id=${e}`
: `/news/article?id=${e}`;
}
// 解析文章路由并校验 ID;缺失或无效时取消旧详情请求并清空正文。
async function Z() {
if (X) return;
let e = P.query.id !== void 0 || P.path === `/news/article`,
@@ -182,6 +190,7 @@ var fe = {
create_time: 0,
});
}
// 关闭详情时废弃旧请求,并移除 URL 中的文章 ID,保留其余筛选查询。
function Q() {
if (
((W.value = !1),
@@ -199,6 +208,7 @@ var fe = {
}));
}
}
// 按文章 ID 获取正文,确认新闻对象存在;只有最新请求且未卸载时才写入弹窗。
async function $(e) {
let t = ++Y;
((W.value = !0),
+9
View File
@@ -1,4 +1,7 @@
<script>
/**
* 平台公告:分类、关键词和排序分页查询;详情路由与资源中心嵌入共用加载逻辑,列表和详情分别维护请求代次。
*/
import "~/assets/styles/notices.BXNGOj-Q.css";
definePageMeta({
key: (e) => e.fullPath,
@@ -100,6 +103,7 @@ var ue = {
B = ref(``),
V = 0,
H = !1;
// 公告分类独立加载;失败单独显示分类错误,不混淆正文状态。
async function U() {
B.value = ``;
try {
@@ -110,6 +114,7 @@ var ue = {
(B.value = e instanceof Error ? e.message : `公告分类加载失败`);
}
}
// 应用搜索词并回到第一页。
function W() {
((I.value = F.value.trim()), (N.value = 1), Z());
}
@@ -119,6 +124,7 @@ var ue = {
J = ref(``),
Y = ref(null),
X = 0;
// 读取当前分页和筛选的公告;较早的响应或离页响应不再覆盖列表。
async function Z() {
let e = ++V;
((j.value = !0), (M.value = ``));
@@ -142,6 +148,7 @@ var ue = {
!H && e === V && (j.value = !1);
}
}
// 打开公告详情前清空上一条正文,只有当前详情请求可以更新弹窗。
async function Q(e) {
let t = ++X;
((G.value = !0),
@@ -162,9 +169,11 @@ var ue = {
t === X && (q.value = !1);
}
}
// 把零基分页器事件转换为接口页码,并使用事件给出的每页条数。
function _e(e) {
((N.value = e.page + 1), (P.value = e.rows), Z());
}
// 从公告详情路由解析 ID,无效编号只提示,不发送详情请求。
async function $() {
if (H) return;
let e = O.query.id !== void 0 || O.path === `/notices/notice`,
+6
View File
@@ -1,4 +1,7 @@
<script>
/**
* 资源中心:帮助、新闻和公告的可访问标签容器;支持 section 参数和后端 plugin 参数,参数解析完成后再挂载对应内容页。
*/
import "~/assets/styles/notices.BXNGOj-Q.css";
import "~/assets/styles/news.CbIzdrjt.css";
import "~/assets/styles/help.BSOB30LE.css";
@@ -79,6 +82,7 @@ var j = {
},
],
H = 0;
// 优先解析 section;只有 plugin 入口才读取插件清单,并用请求代次隔离连续路由切换。
async function U() {
let e = ++H;
((z.value = ``), (R.value = null), (B.value = !0));
@@ -98,6 +102,7 @@ var j = {
e === H && (B.value = !1);
}
}
// 切换分类同时写入 /resources 的 section 查询参数,保持刷新与分享地址可恢复。
function W(e) {
((R.value = e),
I.push({
@@ -112,6 +117,7 @@ var j = {
onBeforeUnmount(() => {
H++;
}));
// 标签按左右方向键循环切换,Home/End 跳至首尾,并同步焦点到新标签。
function G(e, t) {
let n = t;
if (e.key === `ArrowRight`) n = (t + 1) % V.length;