feat: add aigc record, video preview & custom recharge

- create useAigcRecordStore to centralize current AIGC generation record state
- add video media type support to ResultPreview component
- update RecordCard to only display view button for completed tasks
- implement custom recharge amount with input validation and 9999 max limit
- refactor detail page to load record from Pinia store instead of mock data
- clean up TemplateCarousel markup and remove unused badge styles
- fix minor formatting and code style issues
This commit is contained in:
duanshuwen
2026-07-13 21:25:17 +08:00
parent b5952961fe
commit 10638e0806
10 changed files with 184 additions and 112 deletions

View File

@@ -23,6 +23,12 @@
@select="handleSelectRechargeOption"
/>
<CustomAmountCard
v-model="customAmount"
:selected="rechargeMode === 'custom'"
@select="handleSelectCustomAmount"
/>
<RechargeFooter
:price="payPrice"
:loading="paying"
@@ -39,12 +45,15 @@ import TopNavBar from "@/components/TopNavBar/index.vue";
import { useCurrentCredit } from "@/pages-aigc/hooks/useCurrentCredit.js";
import { getRechargeOptions, rechargeCredit } from "@/request/api/AigcApi.js";
import BalanceCard from "./components/BalanceCard/index.vue";
import CustomAmountCard from "./components/CustomAmountCard/index.vue";
import RechargeFooter from "./components/RechargeFooter/index.vue";
import RechargePackageList from "./components/RechargePackageList/index.vue";
const { pointBalance: balancePoints, fetchCurrentCredit } = useCurrentCredit();
const rechargeOptions = ref([]);
const selectedRechargeOption = ref(null);
const customAmount = ref("");
const rechargeMode = ref("package");
const paying = ref(false);
const getRechargeOptionKey = (option) => {
@@ -53,10 +62,17 @@ const getRechargeOptionKey = (option) => {
return `${option.rechargeAmount ?? ""}-${option.rechargePoints ?? ""}`;
};
const selectedRechargeKey = computed(() => getRechargeOptionKey(selectedRechargeOption.value));
const selectedRechargeKey = computed(() => {
if (rechargeMode.value !== "package") return "";
return getRechargeOptionKey(selectedRechargeOption.value);
});
const payPrice = computed(() => {
const amount = Number(selectedRechargeOption.value?.rechargeAmount);
const amount =
rechargeMode.value === "custom"
? Number.parseInt(customAmount.value || "0", 10)
: Number(selectedRechargeOption.value?.rechargeAmount);
return Number.isFinite(amount) ? amount : 0;
});
@@ -72,7 +88,9 @@ const fetchRechargeOptions = async () => {
const res = await getRechargeOptions();
if (res?.code === 0 && Array.isArray(res.data)) {
rechargeOptions.value = res.data;
selectedRechargeOption.value = res.data[0] || null;
if (rechargeMode.value === "package") {
selectedRechargeOption.value = res.data[0] || null;
}
}
} catch (error) {
console.error("获取积分充值档位失败", error);
@@ -102,9 +120,15 @@ const handleOpenLedger = () => {
};
const handleSelectRechargeOption = (option) => {
rechargeMode.value = "package";
selectedRechargeOption.value = option;
};
const handleSelectCustomAmount = () => {
rechargeMode.value = "custom";
selectedRechargeOption.value = null;
};
const requestWechatPay = (payData) => {
const { nonceStr, packageVal, paySign, signType, timeStamp } = payData || {};
@@ -138,14 +162,15 @@ const requestWechatPay = (payData) => {
const handlePay = async () => {
if (paying.value) return;
if (!selectedRechargeOption.value) {
if (rechargeMode.value === "package" && !selectedRechargeOption.value) {
showToast("请选择充值档位");
return;
}
const rechargeAmount = payPrice.value;
if (!Number.isInteger(rechargeAmount) || rechargeAmount <= 0) {
showToast("充值档位金额错误,请重试");
const message = rechargeMode.value === "custom" ? "请输入正确的充值金额" : "充值档位金额错误,请重试";
showToast(message);
return;
}