fix(后台本地预览): 会员档位保存按请求体回显
- 假后台读取 POST 请求体,把提交字段覆盖到对应档位行再回显,保存非 starter 档不再把表单与列表重置成 starter。 - 抽出 UNLIMITED_CONCURRENCY_THRESHOLD 常量,列表与回显共用同一哨兵。
This commit is contained in:
@@ -4,6 +4,9 @@ import http from 'node:http';
|
||||
|
||||
const port = Number(process.argv[2] ?? 8099);
|
||||
|
||||
/** 与后端 `MEMBERSHIP_UNLIMITED_CONCURRENCY` 一致的假数据哨兵。 */
|
||||
const UNLIMITED_CONCURRENCY_THRESHOLD = 128;
|
||||
|
||||
const admin = {
|
||||
subject: 'admin:local',
|
||||
username: 'owner',
|
||||
@@ -473,7 +476,15 @@ const userDetail = {
|
||||
tags: ['vip', '内测'],
|
||||
};
|
||||
|
||||
function route(pathname, method, url) {
|
||||
function parseJsonBody(requestBody) {
|
||||
try {
|
||||
return JSON.parse(requestBody);
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function route(pathname, method, url, requestBody = '') {
|
||||
if (pathname === '/admin/api/login' && method === 'POST') {
|
||||
return { token: 'local-fake-token', admin };
|
||||
}
|
||||
@@ -756,7 +767,8 @@ function route(pathname, method, url) {
|
||||
periodPoints,
|
||||
modelAccess,
|
||||
concurrentJobLimit,
|
||||
unlimitedConcurrency: concurrentJobLimit >= 128,
|
||||
unlimitedConcurrency:
|
||||
concurrentJobLimit >= UNLIMITED_CONCURRENCY_THRESHOLD,
|
||||
enabled,
|
||||
});
|
||||
const plans = [
|
||||
@@ -766,10 +778,22 @@ function route(pathname, method, url) {
|
||||
plan('pro', '专业会员', 3, 29_900, 299_000, 3_650, 'full', 5, true),
|
||||
plan('max', '旗舰会员', 4, 69_900, 699_000, 8_650, 'full', 128, true),
|
||||
];
|
||||
// 本地预览不解析请求体:POST 统一回显 starter,仅用于页面回填。
|
||||
return method === 'POST'
|
||||
? plans[1]
|
||||
: { entries: plans, unlimitedConcurrencyThreshold: 128 };
|
||||
// 本地预览按请求体回显被保存的档位:把提交字段覆盖到对应档位行,避免保存非 starter 档后表单被回填成 starter。
|
||||
if (method === 'POST') {
|
||||
const submitted = parseJsonBody(requestBody);
|
||||
const target =
|
||||
plans.find((entry) => entry.plan === submitted?.plan) ?? plans[1];
|
||||
const merged = { ...target, ...(submitted ?? {}) };
|
||||
return {
|
||||
...merged,
|
||||
unlimitedConcurrency:
|
||||
Number(merged.concurrentJobLimit) >= UNLIMITED_CONCURRENCY_THRESHOLD,
|
||||
};
|
||||
}
|
||||
return {
|
||||
entries: plans,
|
||||
unlimitedConcurrencyThreshold: UNLIMITED_CONCURRENCY_THRESHOLD,
|
||||
};
|
||||
}
|
||||
if (pathname === '/admin/api/profile/recharge-products') {
|
||||
const product = (
|
||||
@@ -1152,13 +1176,25 @@ function route(pathname, method, url) {
|
||||
|
||||
const server = http.createServer((request, response) => {
|
||||
const url = new URL(request.url ?? '/', `http://127.0.0.1:${port}`);
|
||||
const payload = route(url.pathname, request.method ?? 'GET', url);
|
||||
const body = JSON.stringify({ data: payload });
|
||||
response.writeHead(200, {
|
||||
'Content-Type': 'application/json; charset=utf-8',
|
||||
'x-genarrative-response-envelope': 'v1',
|
||||
const chunks = [];
|
||||
request.on('data', (chunk) => {
|
||||
chunks.push(chunk);
|
||||
});
|
||||
request.on('end', () => {
|
||||
const requestBody = Buffer.concat(chunks).toString('utf8');
|
||||
const payload = route(
|
||||
url.pathname,
|
||||
request.method ?? 'GET',
|
||||
url,
|
||||
requestBody,
|
||||
);
|
||||
const body = JSON.stringify({ data: payload });
|
||||
response.writeHead(200, {
|
||||
'Content-Type': 'application/json; charset=utf-8',
|
||||
'x-genarrative-response-envelope': 'v1',
|
||||
});
|
||||
response.end(body);
|
||||
});
|
||||
response.end(body);
|
||||
});
|
||||
|
||||
server.listen(port, '127.0.0.1', () => {
|
||||
|
||||
Reference in New Issue
Block a user