🚀 refactor: Simplify subscription quota to total amount model

Remove per-model subscription items and switch to a single total quota per plan and user subscription. Update billing, reset, and logging flows to operate on total quota, and refactor admin/user UI to configure and display total quota consistently.
This commit is contained in:
t0ng7u
2026-02-01 00:35:08 +08:00
parent b92a4ee987
commit 6300c31d70
17 changed files with 270 additions and 999 deletions

View File

@@ -29,7 +29,6 @@ export const useSubscriptionsData = () => {
// State management
const [allPlans, setAllPlans] = useState([]);
const [loading, setLoading] = useState(true);
const [pricingModels, setPricingModels] = useState([]);
// Pagination (client-side for now)
const [activePage, setActivePage] = useState(1);
@@ -40,18 +39,6 @@ export const useSubscriptionsData = () => {
const [editingPlan, setEditingPlan] = useState(null);
const [sheetPlacement, setSheetPlacement] = useState('left'); // 'left' | 'right'
// Load pricing models for dropdown
const loadModels = async () => {
try {
const res = await API.get('/api/pricing');
if (res.data?.success) {
setPricingModels(res.data.data || []);
}
} catch (e) {
setPricingModels([]);
}
};
// Load subscription plans
const loadPlans = async () => {
setLoading(true);
@@ -133,7 +120,6 @@ export const useSubscriptionsData = () => {
// Initialize data on component mount
useEffect(() => {
loadModels();
loadPlans();
}, []);
@@ -148,7 +134,6 @@ export const useSubscriptionsData = () => {
plans,
planCount,
loading,
pricingModels,
// Modal state
showEdit,

View File

@@ -517,14 +517,11 @@ export const useLogsData = () => {
if (other?.billing_source === 'subscription') {
const planId = other?.subscription_plan_id;
const planTitle = other?.subscription_plan_title || '';
const itemId = other?.subscription_item_id;
const quotaType = other?.subscription_quota_type;
const unit = quotaType === 1 ? t('次') : t('额度');
const subscriptionId = other?.subscription_id;
const unit = t('额度');
const pre = other?.subscription_pre_consumed ?? 0;
const postDelta = other?.subscription_post_delta ?? 0;
const finalConsumed =
other?.subscription_consumed ??
(quotaType === 1 ? 1 : pre + postDelta);
const finalConsumed = other?.subscription_consumed ?? pre + postDelta;
const remain = other?.subscription_remain;
const total = other?.subscription_total;
// Use multiple Description items to avoid an overlong single line.
@@ -534,20 +531,15 @@ export const useLogsData = () => {
value: `#${planId} ${planTitle}`.trim(),
});
}
if (itemId) {
if (subscriptionId) {
expandDataLocal.push({
key: t('订阅权益'),
value:
quotaType === 1
? `${t('权益ID')} ${itemId} · ${t('按次')}1 ${t('次')}/${t('请求')}`
: `${t('权益ID')} ${itemId} · ${t('按量')}`,
key: t('订阅实例'),
value: `#${subscriptionId}`,
});
}
const settlementLines = [
`${t('预扣')}${pre} ${unit}`,
quotaType === 0
? `${t('结算差额')}${postDelta > 0 ? '+' : ''}${postDelta} ${unit}`
: null,
`${t('结算差额')}${postDelta > 0 ? '+' : ''}${postDelta} ${unit}`,
`${t('最终抵扣')}${finalConsumed} ${unit}`,
]
.filter(Boolean)