diff --git a/src/pages-aigc/recharge/components/CustomAmountCard/index.vue b/src/pages-aigc/recharge/components/CustomAmountCard/index.vue
new file mode 100644
index 0000000..5b31776
--- /dev/null
+++ b/src/pages-aigc/recharge/components/CustomAmountCard/index.vue
@@ -0,0 +1,53 @@
+
+
+ 自选金额
+
+
+
+
+ 请输入整数金额
+
+
+
+
+
+
+
diff --git a/src/pages-aigc/recharge/components/RechargeFooter/index.vue b/src/pages-aigc/recharge/components/RechargeFooter/index.vue
new file mode 100644
index 0000000..7f789af
--- /dev/null
+++ b/src/pages-aigc/recharge/components/RechargeFooter/index.vue
@@ -0,0 +1,85 @@
+
+
+
+
+
+
+
diff --git a/src/pages-aigc/recharge/components/RechargePackageList/index.vue b/src/pages-aigc/recharge/components/RechargePackageList/index.vue
new file mode 100644
index 0000000..a73a21d
--- /dev/null
+++ b/src/pages-aigc/recharge/components/RechargePackageList/index.vue
@@ -0,0 +1,46 @@
+
+
+ 优惠充值
+
+
+
+
+ {{ item.rechargePoints }}积分
+ 充值金额
+
+
+ ¥{{ formatPrice(item.expectedAmountFen) }}
+
+
+
+
+
+
+
+
diff --git a/src/pages-aigc/recharge/recharge.vue b/src/pages-aigc/recharge/recharge.vue
new file mode 100644
index 0000000..36f9e72
--- /dev/null
+++ b/src/pages-aigc/recharge/recharge.vue
@@ -0,0 +1,463 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/pages-aigc/recharge/services/pendingVirtualRecharge.js b/src/pages-aigc/recharge/services/pendingVirtualRecharge.js
new file mode 100644
index 0000000..cb6cce0
--- /dev/null
+++ b/src/pages-aigc/recharge/services/pendingVirtualRecharge.js
@@ -0,0 +1,26 @@
+import { currentClientType } from "@/constant/base.js";
+
+const PENDING_VIRTUAL_RECHARGE_ORDER_KEY = `${currentClientType()}_AIGC_PENDING_VIRTUAL_RECHARGE_ORDER`;
+
+const getStorageApi = () => (typeof uni !== "undefined" ? uni : null);
+
+export function getPendingVirtualRechargeOrderNo(storage = getStorageApi()) {
+ const orderNo = storage?.getStorageSync?.(PENDING_VIRTUAL_RECHARGE_ORDER_KEY);
+ return typeof orderNo === "string" ? orderNo.trim() : "";
+}
+
+export function setPendingVirtualRechargeOrderNo(orderNo, storage = getStorageApi()) {
+ const normalizedOrderNo = String(orderNo || "").trim();
+ if (!normalizedOrderNo) {
+ throw new Error("待确认充值订单号不能为空");
+ }
+
+ return storage?.setStorageSync?.(
+ PENDING_VIRTUAL_RECHARGE_ORDER_KEY,
+ normalizedOrderNo
+ );
+}
+
+export function removePendingVirtualRechargeOrderNo(storage = getStorageApi()) {
+ return storage?.removeStorageSync?.(PENDING_VIRTUAL_RECHARGE_ORDER_KEY);
+}
diff --git a/src/pages-aigc/recharge/services/wechatVirtualPayment.js b/src/pages-aigc/recharge/services/wechatVirtualPayment.js
new file mode 100644
index 0000000..6249eb6
--- /dev/null
+++ b/src/pages-aigc/recharge/services/wechatVirtualPayment.js
@@ -0,0 +1,102 @@
+import {
+ normalizeVirtualPaymentOrder,
+ normalizeWechatClientPlatform,
+} from "../utils/virtualRecharge.js";
+
+const MIN_VIRTUAL_PAYMENT_SDK_VERSION = "2.19.2";
+
+const getWechatApi = () => {
+ // #ifdef MP-WEIXIN
+ if (typeof wx !== "undefined") return wx;
+ // #endif
+ return null;
+};
+
+export function compareVersion(versionA, versionB) {
+ const versionsA = String(versionA || "").split(".");
+ const versionsB = String(versionB || "").split(".");
+ const length = Math.max(versionsA.length, versionsB.length);
+
+ while (versionsA.length < length) versionsA.push("0");
+ while (versionsB.length < length) versionsB.push("0");
+
+ for (let index = 0; index < length; index += 1) {
+ const numberA = Number.parseInt(versionsA[index], 10) || 0;
+ const numberB = Number.parseInt(versionsB[index], 10) || 0;
+ if (numberA > numberB) return 1;
+ if (numberA < numberB) return -1;
+ }
+
+ return 0;
+}
+
+export function assertWechatVirtualPaymentCapability(wechatApi = getWechatApi()) {
+ if (!wechatApi) {
+ throw new Error("当前环境不支持微信虚拟支付");
+ }
+
+ const appBaseInfo =
+ typeof wechatApi.getAppBaseInfo === "function"
+ ? wechatApi.getAppBaseInfo()
+ : wechatApi.getSystemInfoSync?.() || {};
+ const versionSupported =
+ compareVersion(appBaseInfo?.SDKVersion, MIN_VIRTUAL_PAYMENT_SDK_VERSION) >= 0;
+ const apiSupported =
+ typeof wechatApi.requestVirtualPayment === "function" &&
+ (versionSupported || wechatApi.canIUse?.("requestVirtualPayment"));
+
+ if (!apiSupported) {
+ throw new Error("当前微信版本不支持微信虚拟支付");
+ }
+}
+
+export function getWechatClientPlatform(wechatApi = getWechatApi()) {
+ assertWechatVirtualPaymentCapability(wechatApi);
+ const deviceInfo =
+ typeof wechatApi.getDeviceInfo === "function"
+ ? wechatApi.getDeviceInfo()
+ : wechatApi.getSystemInfoSync?.() || {};
+ const clientPlatform = normalizeWechatClientPlatform(deviceInfo?.platform);
+
+ if (!clientPlatform) {
+ throw new Error("当前客户端平台不支持微信虚拟支付");
+ }
+
+ return clientPlatform;
+}
+
+export function getWechatLoginCode(wechatApi = getWechatApi()) {
+ if (!wechatApi || typeof wechatApi.login !== "function") {
+ return Promise.reject(new Error("当前环境无法获取微信登录凭证"));
+ }
+
+ return new Promise((resolve, reject) => {
+ wechatApi.login({
+ success: (result) => {
+ const code = String(result?.code || "").trim();
+ if (code) {
+ resolve(code);
+ return;
+ }
+ reject(new Error("微信登录凭证获取失败"));
+ },
+ fail: () => reject(new Error("微信登录凭证获取失败")),
+ });
+ });
+}
+
+export function requestWechatVirtualPayment(paymentData, wechatApi = getWechatApi()) {
+ assertWechatVirtualPaymentCapability(wechatApi);
+ const order = normalizeVirtualPaymentOrder(paymentData);
+
+ return new Promise((resolve, reject) => {
+ wechatApi.requestVirtualPayment({
+ signData: order.signData,
+ paySig: order.paySig,
+ signature: order.signature,
+ mode: order.mode,
+ success: resolve,
+ fail: reject,
+ });
+ });
+}
diff --git a/src/pages-aigc/recharge/utils/virtualRecharge.js b/src/pages-aigc/recharge/utils/virtualRecharge.js
new file mode 100644
index 0000000..9673319
--- /dev/null
+++ b/src/pages-aigc/recharge/utils/virtualRecharge.js
@@ -0,0 +1,136 @@
+const ALLOWED_CLIENT_PLATFORMS = new Set([
+ "ANDROID",
+ "HARMONY",
+ "WINDOWS",
+ "IOS",
+]);
+
+const REQUIRED_PAYMENT_ORDER_FIELDS = [
+ "rechargeOrderNo",
+ "paymentOrderNo",
+ "signData",
+ "paySig",
+ "signature",
+];
+
+export const VIRTUAL_RECHARGE_STATUS_KIND = Object.freeze({
+ PAID: "paid",
+ REFUNDED: "refunded",
+ FAILED: "failed",
+ PENDING: "pending",
+ UNKNOWN: "unknown",
+});
+
+export function normalizeWechatClientPlatform(platform) {
+ const normalizedPlatform = String(platform || "").toLowerCase();
+ const platformMap = {
+ android: "ANDROID",
+ ios: "IOS",
+ ohos: "HARMONY",
+ ohos_pc: "HARMONY",
+ windows: "WINDOWS",
+ };
+
+ return platformMap[normalizedPlatform] || "";
+}
+
+export function buildVirtualRechargeOrderPayload({
+ mode,
+ rechargeOptionCode,
+ rechargeAmount,
+ wxLoginCode,
+ clientPlatform,
+} = {}) {
+ const normalizedLoginCode = String(wxLoginCode || "").trim();
+ const normalizedPlatform = String(clientPlatform || "").trim().toUpperCase();
+
+ if (!normalizedLoginCode) {
+ throw new Error("微信登录凭证无效");
+ }
+
+ if (!ALLOWED_CLIENT_PLATFORMS.has(normalizedPlatform)) {
+ throw new Error("当前客户端平台不支持微信虚拟支付");
+ }
+
+ const commonPayload = {
+ wxLoginCode: normalizedLoginCode,
+ clientPlatform: normalizedPlatform,
+ };
+
+ if (mode === "package") {
+ const normalizedOptionCode = String(rechargeOptionCode || "").trim();
+ if (!normalizedOptionCode) {
+ throw new Error("请选择充值档位");
+ }
+
+ return {
+ rechargeOptionCode: normalizedOptionCode,
+ ...commonPayload,
+ };
+ }
+
+ if (mode === "custom") {
+ const amountText = String(rechargeAmount ?? "").trim();
+ if (!/^\d{1,6}$/.test(amountText)) {
+ throw new Error("充值金额必须为1至999999的整数");
+ }
+
+ const normalizedAmount = Number(amountText);
+ if (normalizedAmount < 1 || normalizedAmount > 999999) {
+ throw new Error("充值金额必须为1至999999的整数");
+ }
+
+ return {
+ rechargeAmount: normalizedAmount,
+ ...commonPayload,
+ };
+ }
+
+ throw new Error("请选择充值方式");
+}
+
+export function normalizeVirtualPaymentOrder(orderData) {
+ const normalizedOrder = orderData && typeof orderData === "object" ? orderData : {};
+ const hasRequiredFields = REQUIRED_PAYMENT_ORDER_FIELDS.every((field) => {
+ return typeof normalizedOrder[field] === "string" && normalizedOrder[field].trim();
+ });
+
+ if (!hasRequiredFields || normalizedOrder.mode !== "short_series_coin") {
+ throw new Error("虚拟支付订单参数错误");
+ }
+
+ return {
+ rechargeOrderNo: normalizedOrder.rechargeOrderNo,
+ paymentOrderNo: normalizedOrder.paymentOrderNo,
+ mode: normalizedOrder.mode,
+ signData: normalizedOrder.signData,
+ paySig: normalizedOrder.paySig,
+ signature: normalizedOrder.signature,
+ };
+}
+
+export function classifyVirtualRechargeStatus(status) {
+ switch (status) {
+ case "PAID":
+ return VIRTUAL_RECHARGE_STATUS_KIND.PAID;
+ case "REFUNDED":
+ return VIRTUAL_RECHARGE_STATUS_KIND.REFUNDED;
+ case "CREATE_FAILED":
+ case "PAYMENT_ABNORMAL":
+ return VIRTUAL_RECHARGE_STATUS_KIND.FAILED;
+ case "CREATING":
+ case "UNPAID":
+ return VIRTUAL_RECHARGE_STATUS_KIND.PENDING;
+ default:
+ return VIRTUAL_RECHARGE_STATUS_KIND.UNKNOWN;
+ }
+}
+
+export function formatFenAmount(amountFen) {
+ const normalizedAmount = Number(amountFen);
+ if (!Number.isInteger(normalizedAmount) || normalizedAmount < 0) {
+ return "0.00";
+ }
+
+ return (normalizedAmount / 100).toFixed(2);
+}
diff --git a/src/pages-aigc/useTemplate/assets/xiaoqi-avatar.png b/src/pages-aigc/useTemplate/assets/xiaoqi-avatar.png
deleted file mode 100644
index 4ba612e..0000000
Binary files a/src/pages-aigc/useTemplate/assets/xiaoqi-avatar.png and /dev/null differ
diff --git a/src/pages-aigc/useTemplate/components/PhotoConfirmDrawer/index.vue b/src/pages-aigc/useTemplate/components/PhotoConfirmDrawer/index.vue
index 34ef169..b87639b 100644
--- a/src/pages-aigc/useTemplate/components/PhotoConfirmDrawer/index.vue
+++ b/src/pages-aigc/useTemplate/components/PhotoConfirmDrawer/index.vue
@@ -1,12 +1,6 @@
-
+
@@ -33,12 +27,11 @@