Align console behavior with operator routing and image workflow expectations

Constraint: Must preserve current exchange-rate logic, same-group routing boundary, and temporary image-file behavior while fixing UX-visible inconsistencies.
Rejected: Large frontend chunk refactor | introduced risky circular chunking and did not improve deliverability for this rollout.
Confidence: medium
Scope-risk: moderate
Directive: Keep channel failover constrained to the selected group and preserve Beijing-day semantics for user cache dashboard metrics.
Tested: go test ./controller ./model ./service ./common -count=1; npm run build; remote smoke on source deployment at http://38.76.218.56:18081/ plus /api/status and /api/image-studio/settings.
Not-tested: Browser-driven end-to-end verification of every console page interaction.
This commit is contained in:
ikmkj
2026-05-05 15:27:51 +08:00
parent 92ee465a41
commit 8ee89478a9
46 changed files with 1341 additions and 289 deletions

View File

@@ -17,7 +17,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
For commercial licensing, please contact support@quantumnous.com
*/
import React, { useEffect, useRef, useState } from 'react';
import React, { useEffect, useMemo, useRef, useState } from 'react';
import {
Avatar,
Typography,
@@ -105,6 +105,21 @@ const RechargeCard = ({
const [activeTab, setActiveTab] = useState('topup');
const shouldShowSubscription =
!subscriptionLoading && subscriptionPlans.length > 0;
const nonWaffoPayMethods = useMemo(
() => (payMethods || []).filter((method) => method.type !== 'waffo'),
[payMethods],
);
const currencyConfig = useMemo(() => getCurrencyConfig(), []);
const usdExchangeRate = useMemo(() => {
const statusStr = localStorage.getItem('status');
try {
if (statusStr) {
const status = JSON.parse(statusStr);
return status?.usd_exchange_rate || 7;
}
} catch (e) {}
return 7;
}, []);
useEffect(() => {
if (initialTabSetRef.current) return;
@@ -291,11 +306,11 @@ const RechargeCard = ({
style={{ width: '100%' }}
/>
</Col>
{payMethods && payMethods.filter(m => m.type !== 'waffo').length > 0 && (
{nonWaffoPayMethods.length > 0 && (
<Col xs={24} sm={24} md={24} lg={14} xl={14}>
<Form.Slot label={t('选择支付方式')}>
<Space wrap>
{payMethods.filter(m => m.type !== 'waffo').map((payMethod) => {
{nonWaffoPayMethods.map((payMethod) => {
const minTopupVal = Number(payMethod.min_topup) || 0;
const isStripe = payMethod.type === 'stripe';
const disabled =
@@ -366,22 +381,18 @@ const RechargeCard = ({
label={
<div className='flex items-center gap-2'>
<span>{t('选择充值额度')}</span>
{(() => {
const { symbol, rate, type } = getCurrencyConfig();
if (type === 'USD') return null;
return (
<span
style={{
color: 'var(--semi-color-text-2)',
fontSize: '12px',
fontWeight: 'normal',
}}
>
(1 $ = {rate.toFixed(2)} {symbol})
</span>
);
})()}
{currencyConfig.type !== 'USD' && (
<span
style={{
color: 'var(--semi-color-text-2)',
fontSize: '12px',
fontWeight: 'normal',
}}
>
(1 = {currencyConfig.rate.toFixed(2)}{' '}
{currencyConfig.symbol})
</span>
)}
</div>
}
>
@@ -396,15 +407,7 @@ const RechargeCard = ({
const save = originalPrice - discountedPrice;
// 根据当前货币类型换算显示金额和数量
const { symbol, rate, type } = getCurrencyConfig();
const statusStr = localStorage.getItem('status');
let usdRate = 7; // 默认CNY汇率
try {
if (statusStr) {
const s = JSON.parse(statusStr);
usdRate = s?.usd_exchange_rate || 7;
}
} catch (e) { }
const { symbol, rate, type } = currencyConfig;
let displayValue = preset.value; // 显示的数量
let displayActualPay = actualPay;
@@ -412,16 +415,16 @@ const RechargeCard = ({
if (type === 'USD') {
// 数量保持USD价格从CNY转USD
displayActualPay = actualPay / usdRate;
displaySave = save / usdRate;
displayActualPay = actualPay / usdExchangeRate;
displaySave = save / usdExchangeRate;
} else if (type === 'CNY') {
// 数量转CNY价格已是CNY
displayValue = preset.value * usdRate;
displayValue = preset.value * usdExchangeRate;
} else if (type === 'CUSTOM') {
// 数量和价格都转自定义货币
displayValue = preset.value * rate;
displayActualPay = (actualPay / usdRate) * rate;
displaySave = (save / usdRate) * rate;
displayActualPay = (actualPay / usdExchangeRate) * rate;
displaySave = (save / usdExchangeRate) * rate;
}
return (
@@ -540,7 +543,7 @@ const RechargeCard = ({
{t('充值额度')}: {product.quota}
</div>
<div className='text-lg font-semibold text-blue-600'>
{product.currency === 'EUR' ? '€' : '$'}
{product.currency === 'EUR' ? '€' : ''}
{product.price}
</div>
</Card>