feat(aigc): fully integrate backend API and replace mock data
- Replace all static mock data with real backend API calls for templates, generation tasks, credit balance and recharge - Remove deprecated mock data files including templates.js, versionOptions.js, records.js and packages.js - Add useCurrentCredit composable for fetching and managing user credit balance - Update all components to align with new backend data shapes (e.g. templateItemId instead of id) - Add loading and disabled states for interactive UI elements - Implement full WeChat mini-program payment flow for credit recharge - Fix template and record card UI styling and media handling - Set developVersion flag to true for testing environment
This commit is contained in:
@@ -13,25 +13,17 @@
|
||||
|
||||
<view class="aigc-recharge-content">
|
||||
<BalanceCard
|
||||
:balance="balance"
|
||||
:points="balancePoints"
|
||||
@ledger="handleOpenLedger"
|
||||
/>
|
||||
|
||||
<RechargePackageList
|
||||
:packages="packages"
|
||||
:selected-id="selectedId"
|
||||
@select="handleSelectPackage"
|
||||
/>
|
||||
|
||||
<CustomAmountCard
|
||||
v-model="customAmount"
|
||||
:selected="selectedId === customId"
|
||||
@select="handleSelectCustom"
|
||||
/>
|
||||
|
||||
<RechargeFooter
|
||||
:points="payPoints"
|
||||
:price="payPrice"
|
||||
:loading="paying"
|
||||
@pay="handlePay"
|
||||
/>
|
||||
</view>
|
||||
@@ -40,51 +32,34 @@
|
||||
|
||||
<script setup>
|
||||
import { computed, ref } from "vue";
|
||||
import { onShow } from "@dcloudio/uni-app";
|
||||
import TopNavBar from "@/components/TopNavBar/index.vue";
|
||||
import { useCurrentCredit } from "@/pages-aigc/hooks/useCurrentCredit.js";
|
||||
import { 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";
|
||||
import { rechargeBalance, rechargePackages } from "./data/packages.js";
|
||||
|
||||
const customId = "custom";
|
||||
const balance = rechargeBalance;
|
||||
const packages = rechargePackages;
|
||||
const selectedId = ref("points-3000");
|
||||
const customAmount = ref("2");
|
||||
const { pointBalance: balancePoints, fetchCurrentCredit } = useCurrentCredit();
|
||||
const customAmount = ref("1");
|
||||
const paying = ref(false);
|
||||
|
||||
const selectedPackage = computed(() =>
|
||||
packages.find((item) => item.id === selectedId.value)
|
||||
);
|
||||
|
||||
const customPrice = computed(() => {
|
||||
const payPrice = computed(() => {
|
||||
const amount = Number.parseInt(customAmount.value || "0", 10);
|
||||
return Number.isNaN(amount) ? 0 : amount;
|
||||
});
|
||||
|
||||
const payPoints = computed(() => {
|
||||
if (selectedId.value === customId) {
|
||||
return customPrice.value * 100;
|
||||
}
|
||||
|
||||
return selectedPackage.value?.points || 0;
|
||||
});
|
||||
|
||||
const payPrice = computed(() => {
|
||||
if (selectedId.value === customId) {
|
||||
return customPrice.value;
|
||||
}
|
||||
|
||||
return selectedPackage.value?.price || 0;
|
||||
});
|
||||
|
||||
const showPlaceholderToast = (title) => {
|
||||
const showToast = (title) => {
|
||||
uni.showToast({
|
||||
title,
|
||||
icon: "none",
|
||||
});
|
||||
};
|
||||
|
||||
onShow(() => {
|
||||
fetchCurrentCredit();
|
||||
});
|
||||
|
||||
const handleBack = () => {
|
||||
const pages = getCurrentPages();
|
||||
if (pages.length > 1) {
|
||||
@@ -95,20 +70,74 @@ const handleBack = () => {
|
||||
const handleOpenLedger = () => {
|
||||
uni.navigateTo({
|
||||
url: "/pages-aigc/pointsDetails/pointsDetails",
|
||||
fail: () => showPlaceholderToast("积分明细"),
|
||||
fail: () => showToast("积分明细"),
|
||||
});
|
||||
};
|
||||
|
||||
const handleSelectPackage = (item) => {
|
||||
selectedId.value = item.id;
|
||||
const requestWechatPay = (payData) => {
|
||||
const { nonceStr, packageVal, paySign, signType, timeStamp } = payData || {};
|
||||
|
||||
if (!nonceStr || !packageVal || !paySign || !signType || !timeStamp) {
|
||||
showToast("支付参数错误,请重试");
|
||||
return;
|
||||
}
|
||||
|
||||
// #ifdef MP-WEIXIN
|
||||
uni.requestPayment({
|
||||
provider: "wxpay",
|
||||
timeStamp: String(timeStamp),
|
||||
nonceStr: String(nonceStr),
|
||||
package: String(packageVal),
|
||||
signType: String(signType),
|
||||
paySign: String(paySign),
|
||||
success: () => {
|
||||
uni.showToast({
|
||||
title: "支付成功",
|
||||
icon: "success",
|
||||
});
|
||||
fetchCurrentCredit();
|
||||
},
|
||||
fail: () => {
|
||||
showToast("支付失败,请重试");
|
||||
},
|
||||
});
|
||||
// #endif
|
||||
};
|
||||
|
||||
const handleSelectCustom = () => {
|
||||
selectedId.value = customId;
|
||||
};
|
||||
const handlePay = async () => {
|
||||
if (paying.value) return;
|
||||
|
||||
const handlePay = () => {
|
||||
showPlaceholderToast(`支付 ¥${payPrice.value}`);
|
||||
const rechargeAmount = payPrice.value;
|
||||
if (!Number.isInteger(rechargeAmount) || rechargeAmount <= 0) {
|
||||
showToast("请输入正确的充值金额");
|
||||
return;
|
||||
}
|
||||
|
||||
paying.value = true;
|
||||
uni.showLoading({ title: "正在发起支付..." });
|
||||
|
||||
try {
|
||||
const res = await rechargeCredit({
|
||||
rechargeAmount,
|
||||
payWay: "0",
|
||||
paySource: "1",
|
||||
});
|
||||
|
||||
uni.hideLoading();
|
||||
|
||||
if (res?.code === 0 && res.data) {
|
||||
requestWechatPay(res.data);
|
||||
return;
|
||||
}
|
||||
|
||||
showToast(res?.msg || "充值下单失败,请重试");
|
||||
} catch (error) {
|
||||
uni.hideLoading();
|
||||
console.error("充值下单失败", error);
|
||||
showToast("充值下单失败,请重试");
|
||||
} finally {
|
||||
paying.value = false;
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user