fix(frontend): preserve owner profile when switching charts
This commit is contained in:
@@ -36,3 +36,34 @@ export async function DELETE(_request: Request, context: RouteContext) {
|
||||
return NextResponse.json({ error: errorMessage(error, "星盘删除失败") }, { status: 500 });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export async function PUT(request: Request, context: RouteContext) {
|
||||
try {
|
||||
const { id } = await context.params;
|
||||
const supabase = await createServerSupabaseClient();
|
||||
const { data: { user } } = await supabase.auth.getUser();
|
||||
if (!user) return NextResponse.json({ error: "请先登录" }, { status: 401 });
|
||||
|
||||
const body = await request.json().catch(() => null) as { profile?: unknown } | null;
|
||||
if (!body?.profile || typeof body.profile !== "object" || Array.isArray(body.profile)) {
|
||||
return NextResponse.json({ error: "星盘资料格式不正确" }, { status: 400 });
|
||||
}
|
||||
const { data, error } = await supabase
|
||||
.from("chart_profiles")
|
||||
.update({ profile: body.profile, updated_at: new Date().toISOString() })
|
||||
.eq("id", id)
|
||||
.eq("user_id", user.id)
|
||||
.eq("role", "other")
|
||||
.select("id, role, profile, updated_at")
|
||||
.maybeSingle();
|
||||
if (error) throw error;
|
||||
if (!data) return NextResponse.json({ error: "星盘不存在或无权更新" }, { status: 404 });
|
||||
return NextResponse.json({ profile: data });
|
||||
} catch (error) {
|
||||
if (isSupabaseConfigurationError(error)) {
|
||||
return NextResponse.json({ error: "数据库尚未配置", code: "DATABASE_NOT_CONFIGURED" }, { status: 503 });
|
||||
}
|
||||
return NextResponse.json({ error: errorMessage(error, "星盘更新失败") }, { status: 500 });
|
||||
}
|
||||
}
|
||||
|
||||
+132
-34
@@ -184,11 +184,14 @@ type Profile = BirthTimeDraft & {
|
||||
longitude: number | null;
|
||||
timezoneOffset: number | null;
|
||||
rectificationCaseId: string;
|
||||
chartRelationship?: ChartRelationship;
|
||||
};
|
||||
type ChartRelationship = "self" | "partner" | "family" | "friend" | "client" | "other";
|
||||
type ChartLibraryRecord = {
|
||||
id: string;
|
||||
role: "self" | "other";
|
||||
profile: Profile;
|
||||
relationship: ChartRelationship;
|
||||
updatedAt: number;
|
||||
};
|
||||
type SynastryRelationshipType = "romance" | "business" | "family" | "general";
|
||||
@@ -472,6 +475,9 @@ function selectedBirthPlace(profile: Profile): BirthPlace | null {
|
||||
function chartLibraryStorageKey(accountId: string) {
|
||||
return `jyotisha_chart_library:${accountId}`;
|
||||
}
|
||||
function activeChartStorageKey(accountId: string) {
|
||||
return `jyotisha_active_chart:${accountId}`;
|
||||
}
|
||||
function synastryHistoryStorageKey(accountId: string) {
|
||||
return `jyotisha_synastry_history:${accountId}`;
|
||||
}
|
||||
@@ -504,7 +510,7 @@ function profileReadyForLibrary(profile: Profile) {
|
||||
}
|
||||
|
||||
function buildSelfChartRecord(profile: Profile): ChartLibraryRecord {
|
||||
return { id: "self", role: "self", profile, updatedAt: timestamp() };
|
||||
return { id: "self", role: "self", profile: { ...profile, chartRelationship: "self" }, relationship: "self", updatedAt: timestamp() };
|
||||
}
|
||||
|
||||
function upsertSelfChart(library: ChartLibraryRecord[], profile: Profile) {
|
||||
@@ -516,7 +522,14 @@ function upsertSelfChart(library: ChartLibraryRecord[], profile: Profile) {
|
||||
function readChartLibrary(accountId: string): ChartLibraryRecord[] {
|
||||
try {
|
||||
const parsed = JSON.parse(localStorage.getItem(chartLibraryStorageKey(accountId)) || "[]") as ChartLibraryRecord[];
|
||||
return Array.isArray(parsed) ? parsed.filter((record) => record?.id && record?.profile) : [];
|
||||
return Array.isArray(parsed)
|
||||
? parsed
|
||||
.filter((record) => record?.id && record?.profile)
|
||||
.map((record) => {
|
||||
const relationship = record.role === "self" ? "self" : record.relationship || record.profile.chartRelationship || "other";
|
||||
return { ...record, profile: { ...record.profile, chartRelationship: relationship }, relationship };
|
||||
})
|
||||
: [];
|
||||
} catch {
|
||||
return [];
|
||||
}
|
||||
@@ -563,10 +576,12 @@ async function saveCloudSynastryReport(report: SynastryReportCard) {
|
||||
}
|
||||
|
||||
function normalizeChartLibraryApiRecord(record: ChartLibraryApiRecord): ChartLibraryRecord {
|
||||
const relationship = record.role === "self" ? "self" : record.profile.chartRelationship || "other";
|
||||
return {
|
||||
id: record.role === "self" ? "self" : record.id,
|
||||
role: record.role,
|
||||
profile: record.profile,
|
||||
profile: { ...record.profile, chartRelationship: relationship },
|
||||
relationship,
|
||||
updatedAt: Date.parse(record.updated_at || "") || timestamp(),
|
||||
};
|
||||
}
|
||||
@@ -592,6 +607,17 @@ async function saveCloudChartProfile(record: ChartLibraryRecord) {
|
||||
return payload?.profile ? normalizeChartLibraryApiRecord(payload.profile) : record;
|
||||
}
|
||||
|
||||
async function updateCloudChartProfile(record: ChartLibraryRecord) {
|
||||
const response = await fetch(`/api/chart-profiles/${encodeURIComponent(record.id)}`, {
|
||||
method: "PUT",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ profile: record.profile }),
|
||||
});
|
||||
const payload = await response.json().catch(() => null) as { profile?: ChartLibraryApiRecord; error?: string } | null;
|
||||
if (!response.ok) throw new Error(payload?.error || "cloud_chart_profile_update_failed");
|
||||
return payload?.profile ? normalizeChartLibraryApiRecord(payload.profile) : record;
|
||||
}
|
||||
|
||||
async function deleteCloudChartProfile(recordId: string) {
|
||||
const response = await fetch(`/api/chart-profiles/${encodeURIComponent(recordId)}`, { method: "DELETE" });
|
||||
if (!response.ok) throw new Error("cloud_chart_profile_delete_failed");
|
||||
@@ -614,6 +640,10 @@ function profileBirthTimeStatusLabel(profile: Profile) {
|
||||
return "时间待确认";
|
||||
}
|
||||
|
||||
function chartRelationshipLabel(relationship: ChartRelationship) {
|
||||
return relationship === "partner" ? "伴侣" : relationship === "family" ? "家人" : relationship === "friend" ? "朋友" : relationship === "client" ? "客户" : relationship === "self" ? "本人" : "其他";
|
||||
}
|
||||
|
||||
function formatChartUpdatedAt(updatedAt: number) {
|
||||
if (!Number.isFinite(updatedAt) || updatedAt <= 0) return "刚刚更新";
|
||||
return `更新于 ${new Intl.DateTimeFormat("zh-CN", { month: "numeric", day: "numeric" }).format(new Date(updatedAt))}`;
|
||||
@@ -724,6 +754,7 @@ function readProfile(value: unknown): Profile {
|
||||
latitude?: unknown;
|
||||
longitude?: unknown;
|
||||
timezone_offset?: unknown;
|
||||
chartRelationship?: unknown;
|
||||
};
|
||||
const date = normalizePersistedBirthDate(
|
||||
typeof profile.birth_date === "string" ? profile.birth_date : profile.date,
|
||||
@@ -770,6 +801,8 @@ function readProfile(value: unknown): Profile {
|
||||
: typeof profile.timezoneOffset === "number" && Number.isFinite(profile.timezoneOffset)
|
||||
? profile.timezoneOffset
|
||||
: null;
|
||||
const chartRelationships: readonly ChartRelationship[] = ["self", "partner", "family", "friend", "client", "other"];
|
||||
const chartRelationship = chartRelationships.find((item) => item === profile.chartRelationship);
|
||||
|
||||
return {
|
||||
name: typeof profile.name === "string" ? profile.name.slice(0, 80) : "",
|
||||
@@ -798,6 +831,7 @@ function readProfile(value: unknown): Profile {
|
||||
latitude,
|
||||
longitude,
|
||||
timezoneOffset,
|
||||
...(chartRelationship ? { chartRelationship } : {}),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1134,9 +1168,12 @@ export default function Home() {
|
||||
const [accountMenuOpen, setAccountMenuOpen] = useState(false);
|
||||
const [activeAccountDialog, setActiveAccountDialog] = useState<AccountDialog | null>(null);
|
||||
const [chartLibrary, setChartLibrary] = useState<ChartLibraryRecord[]>([]);
|
||||
const [activeChartId, setActiveChartId] = useState("self");
|
||||
const [synastryRelationshipType, setSynastryRelationshipType] = useState<SynastryRelationshipType>("romance");
|
||||
const [synastryPendingId, setSynastryPendingId] = useState<string | null>(null);
|
||||
const [otherProfileDraft, setOtherProfileDraft] = useState<Profile>(emptyProfile);
|
||||
const [otherChartRelationship, setOtherChartRelationship] = useState<Exclude<ChartRelationship, "self">>("other");
|
||||
const [editingChartId, setEditingChartId] = useState<string | null>(null);
|
||||
const [synastryReportCard, setSynastryReportCard] = useState<SynastryReportCard | null>(null);
|
||||
const [synastryHistory, setSynastryHistory] = useState<SynastryReportCard[]>([]);
|
||||
const [dailyStarlanguage, setDailyStarlanguage] = useState<DailyStarlanguageState>({ kind: "pending" });
|
||||
@@ -1346,22 +1383,29 @@ export default function Home() {
|
||||
localStorage.setItem(`${prefix}archived`, JSON.stringify(archivedSessionIds));
|
||||
}, [accountId, archivedSessionIds, hydrated, pinnedSessionIds]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!hydrated || !accountId) return;
|
||||
setActiveChartId(localStorage.getItem(activeChartStorageKey(accountId)) || "self");
|
||||
}, [accountId, hydrated]);
|
||||
|
||||
useEffect(() => {
|
||||
const branch = chartLibrarySessionBranch(accountId, chartLibraryLoadedAccount.current);
|
||||
if (branch === "clear" || !accountId) {
|
||||
setChartLibrary([]);
|
||||
setSynastryHistory([]);
|
||||
setActiveChartId("self");
|
||||
chartLibraryLoadedAccount.current = "";
|
||||
return;
|
||||
}
|
||||
const profileForLibrary: Profile = activeChartId === "self" ? profile : account ? readProfile(account.profile) : profile;
|
||||
if (branch === "hydrate-then-persist") {
|
||||
chartLibraryLoadedAccount.current = accountId;
|
||||
setChartLibrary(upsertSelfChart(readChartLibrary(accountId), profile));
|
||||
setChartLibrary(upsertSelfChart(readChartLibrary(accountId), profileForLibrary));
|
||||
setSynastryHistory(readSynastryHistory(accountId));
|
||||
void fetchCloudChartLibrary()
|
||||
.then((cloudLibrary) => {
|
||||
setChartLibrary(() => {
|
||||
const next = upsertSelfChart(cloudLibrary.filter((record) => record.role !== "self"), profile);
|
||||
const next = upsertSelfChart(cloudLibrary.filter((record) => record.role !== "self"), profileForLibrary);
|
||||
localStorage.setItem(chartLibraryStorageKey(accountId), JSON.stringify(next));
|
||||
return next;
|
||||
});
|
||||
@@ -1383,11 +1427,24 @@ export default function Home() {
|
||||
});
|
||||
}
|
||||
setChartLibrary((current) => {
|
||||
const next = upsertSelfChart(current, profile);
|
||||
const next = upsertSelfChart(current, profileForLibrary);
|
||||
localStorage.setItem(chartLibraryStorageKey(accountId), JSON.stringify(next));
|
||||
return next;
|
||||
});
|
||||
}, [accountId, profile]);
|
||||
}, [account, accountId, activeChartId, profile]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!hydrated || !accountId || chartLibrary.length === 0) return;
|
||||
const record = chartLibrary.find((item) => item.id === activeChartId)
|
||||
|| chartLibrary.find((item) => item.role === "self");
|
||||
if (!record) return;
|
||||
if (record.id !== activeChartId) {
|
||||
setActiveChartId(record.id);
|
||||
localStorage.setItem(activeChartStorageKey(accountId), record.id);
|
||||
}
|
||||
setProfile((current) => preserveShallowEqual(current, record.profile));
|
||||
if (record.role === "self") setProfileDraft((current) => preserveShallowEqual(current, record.profile));
|
||||
}, [accountId, activeChartId, chartLibrary, hydrated]);
|
||||
|
||||
const profileComplete = isProfileComplete(profile);
|
||||
const birthTimeRoute = resolveBirthTimeConsultationRoute(profile, birthTimeConsultationConsent, activeSessionId);
|
||||
@@ -2061,7 +2118,11 @@ export default function Home() {
|
||||
const latest = await fetchAccount();
|
||||
if (!accountRefreshGuard.current.isCurrent(requestIdentity)) return;
|
||||
const nextProfile = readProfile(latest.profile);
|
||||
setProfile((current) => preserveShallowEqual(current, nextProfile));
|
||||
setProfile((current) => {
|
||||
const activeOther = activeChartId !== "self" && chartLibrary.find((record) => record.id === activeChartId && record.role === "other");
|
||||
return activeOther ? current : preserveShallowEqual(current, nextProfile);
|
||||
});
|
||||
setProfileDraft(nextProfile);
|
||||
setAccount(latest);
|
||||
setAccountError("");
|
||||
} catch (caught) {
|
||||
@@ -2352,46 +2413,73 @@ export default function Home() {
|
||||
throw new Error(payload?.error || "账户资料暂时无法保存。");
|
||||
}
|
||||
const savedProfile = applyPersistedBirthTime(nextProfile, payload?.birthTime);
|
||||
setAccount((current) => current ? { ...current, profile: savedProfile } : current);
|
||||
setActiveChartId("self");
|
||||
localStorage.setItem(activeChartStorageKey(account.user.id), "self");
|
||||
await saveCloudChartProfile({ ...buildSelfChartRecord(savedProfile), updatedAt: timestamp() }).catch(() => null);
|
||||
return savedProfile;
|
||||
}
|
||||
|
||||
async function saveOtherChart(event: FormEvent<HTMLFormElement>) {
|
||||
event.preventDefault();
|
||||
const nextProfile = { ...otherProfileDraft, name: otherProfileDraft.name.trim() };
|
||||
const nextProfile = { ...otherProfileDraft, name: otherProfileDraft.name.trim(), chartRelationship: otherChartRelationship };
|
||||
|
||||
if (missingOtherProfileStep(nextProfile)) {
|
||||
setAccountError("请补全其他星盘的称呼、出生时间和出生地点。");
|
||||
return;
|
||||
}
|
||||
if (!accountId) return;
|
||||
let record: ChartLibraryRecord = {
|
||||
id: globalThis.crypto.randomUUID(),
|
||||
id: editingChartId || globalThis.crypto.randomUUID(),
|
||||
role: "other",
|
||||
profile: nextProfile,
|
||||
relationship: otherChartRelationship,
|
||||
updatedAt: timestamp(),
|
||||
};
|
||||
let cloudSaved = false;
|
||||
try {
|
||||
record = await saveCloudChartProfile(record);
|
||||
if (editingChartId) {
|
||||
record = await updateCloudChartProfile(record);
|
||||
} else {
|
||||
record = await saveCloudChartProfile(record);
|
||||
cloudSaved = true;
|
||||
}
|
||||
cloudSaved = true;
|
||||
} catch {
|
||||
setProfileNotice("已保存到本地星盘库;云端同步失败,稍后会继续使用本地记录。");
|
||||
setAccountError("");
|
||||
}
|
||||
const selfProfile = account ? readProfile(account.profile) : profile;
|
||||
setChartLibrary((current) => {
|
||||
const next = [...upsertSelfChart(current, profile), record];
|
||||
const others = editingChartId
|
||||
? current.map((item) => item.id === record.id ? record : item)
|
||||
: [...current, record];
|
||||
const next = upsertSelfChart(others, selfProfile);
|
||||
localStorage.setItem(chartLibraryStorageKey(accountId), JSON.stringify(next));
|
||||
return next;
|
||||
});
|
||||
setOtherProfileDraft(emptyProfile);
|
||||
setOtherChartRelationship("other");
|
||||
setEditingChartId(null);
|
||||
setAccountError("");
|
||||
if (cloudSaved) {
|
||||
setAccountError("");
|
||||
setProfileNotice("已保存到云端星盘库。请选择关系类型后点击“用于合盘”。");
|
||||
setProfileNotice(editingChartId ? "已更新其他人的星盘资料。" : "已保存到云端星盘库。请选择关系类型后点击“用于合盘”。");
|
||||
} else {
|
||||
setProfileNotice("已保存到本地星盘库。");
|
||||
}
|
||||
}
|
||||
|
||||
function editOtherChart(record: ChartLibraryRecord) {
|
||||
if (record.role !== "other") return;
|
||||
setOtherProfileDraft(record.profile);
|
||||
setOtherChartRelationship(record.relationship === "self" ? "other" : record.relationship);
|
||||
setEditingChartId(record.id);
|
||||
setAccountError("");
|
||||
setProfileNotice("");
|
||||
}
|
||||
|
||||
async function deleteOtherChart(recordId: string) {
|
||||
if (!accountId) return;
|
||||
if (!accountId || !window.confirm("确定删除这份其他人的星盘资料吗?删除后无法恢复。")) return;
|
||||
let cloudDeleted = false;
|
||||
try {
|
||||
await deleteCloudChartProfile(recordId);
|
||||
@@ -2401,6 +2489,10 @@ export default function Home() {
|
||||
}
|
||||
setChartLibrary((current) => {
|
||||
const next = current.filter((record) => record.id !== recordId || record.role === "self");
|
||||
if (activeChartId === recordId) {
|
||||
setActiveChartId("self");
|
||||
localStorage.setItem(activeChartStorageKey(accountId), "self");
|
||||
}
|
||||
localStorage.setItem(chartLibraryStorageKey(accountId), JSON.stringify(next));
|
||||
return next;
|
||||
});
|
||||
@@ -2410,20 +2502,12 @@ export default function Home() {
|
||||
: "已从本地星盘库删除;云端同步失败,稍后云端可能仍显示旧记录。");
|
||||
}
|
||||
|
||||
async function makeDefaultChart(record: ChartLibraryRecord) {
|
||||
if (record.role !== "other" || profileSaving) return;
|
||||
setProfileSaving(true);
|
||||
setAccountError("");
|
||||
try {
|
||||
const savedProfile = await persistProfile(record.profile);
|
||||
setProfile(savedProfile);
|
||||
setProfileDraft(savedProfile);
|
||||
setProfileNotice("已设为当前默认星盘。");
|
||||
} catch (caught) {
|
||||
setAccountError(friendlyError(caught instanceof Error ? caught.message : "默认星盘保存失败"));
|
||||
} finally {
|
||||
setProfileSaving(false);
|
||||
}
|
||||
function makeDefaultChart(record: ChartLibraryRecord) {
|
||||
if (record.role !== "other" || profileSaving || !accountId) return;
|
||||
setActiveChartId(record.id);
|
||||
localStorage.setItem(activeChartStorageKey(accountId), record.id);
|
||||
setProfile(record.profile);
|
||||
setProfileNotice("已设为当前使用资料,账户本人的出生资料未被覆盖。");
|
||||
}
|
||||
|
||||
async function assessSavedBirthTime(nextProfile: Profile) {
|
||||
@@ -3911,7 +3995,7 @@ export default function Home() {
|
||||
{chartLibrary.filter((record) => record.role === "other").map((record) => (
|
||||
<article className="chart-library-item" key={record.id}>
|
||||
<div className="chart-library-item-main">
|
||||
<div className="chart-library-item-title"><strong>{record.profile.name || "未命名"}</strong><span className="chart-role-badge">其他人</span></div>
|
||||
<div className="chart-library-item-title"><strong>{record.profile.name || "未命名"}</strong><span className="chart-role-badge">{chartRelationshipLabel(record.relationship)}</span></div>
|
||||
<small>{record.profile.date || "出生日期待补全"} · {profileBirthTimeLabel(record.profile)} · {profilePlaceLabel(record.profile)}</small>
|
||||
<small>{profileBirthTimeStatusLabel(record.profile)} · {formatChartUpdatedAt(record.updatedAt)}</small>
|
||||
</div>
|
||||
@@ -3923,8 +4007,9 @@ export default function Home() {
|
||||
<option value="general">其他关系</option>
|
||||
</select>
|
||||
<button className="button-secondary" type="button" onClick={() => void draftSynastryQuestionFromChart(record, synastryRelationshipType)} disabled={synastryPendingId !== null}>{synastryPendingId === record.id ? "正在计算合盘..." : "用于合盘"}</button>
|
||||
<button className="button-secondary" type="button" onClick={() => void makeDefaultChart(record)} disabled={profileSaving}>设为默认</button>
|
||||
<button className="button-secondary" type="button" onClick={() => deleteOtherChart(record.id)}>删除</button>
|
||||
<button className="button-secondary" type="button" onClick={() => editOtherChart(record)} disabled={profileSaving || editingChartId !== null}>编辑</button>
|
||||
<button className="button-secondary" type="button" onClick={() => makeDefaultChart(record)} disabled={profileSaving}>设为默认</button>
|
||||
<button className="button-secondary" type="button" onClick={() => void deleteOtherChart(record.id)}>删除</button>
|
||||
</div>
|
||||
</article>
|
||||
))}
|
||||
@@ -3959,9 +4044,22 @@ export default function Home() {
|
||||
</div>
|
||||
)}
|
||||
<form className="profile-form chart-library-form" onSubmit={saveOtherChart}>
|
||||
<div className="section-heading"><b>添加其他星盘</b><small>用于合盘、亲友盘或客户盘。</small></div>
|
||||
<div className="section-heading"><b>{editingChartId ? "编辑其他人的星盘" : "添加其他人的星盘"}</b><small>用于合盘、亲友盘或客户盘。</small></div>
|
||||
<label>
|
||||
<span>关系</span>
|
||||
<select value={otherChartRelationship} onChange={(event) => setOtherChartRelationship(event.target.value as Exclude<ChartRelationship, "self">)}>
|
||||
<option value="partner">伴侣</option>
|
||||
<option value="family">家人</option>
|
||||
<option value="friend">朋友</option>
|
||||
<option value="client">客户</option>
|
||||
<option value="other">其他</option>
|
||||
</select>
|
||||
</label>
|
||||
<ProfileFields value={otherProfileDraft} onChange={setOtherProfileDraft} nameInputId="other-profile-name" />
|
||||
<button className="button-primary save-profile" type="submit" disabled={!account}>添加到星盘库</button>
|
||||
<div className="dialog-actions">
|
||||
{editingChartId && <button className="button-secondary" type="button" onClick={() => { setEditingChartId(null); setOtherProfileDraft(emptyProfile); setOtherChartRelationship("other"); }}>取消编辑</button>}
|
||||
<button className="button-primary save-profile" type="submit" disabled={!account || profileSaving}>{profileSaving ? "保存中" : editingChartId ? "保存修改" : "添加到星盘库"}</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</>
|
||||
|
||||
@@ -33,7 +33,7 @@ test("adding another chart waits for the user to choose a relationship type", ()
|
||||
test("a successful cloud read replaces stale local other charts", () => {
|
||||
assert.match(
|
||||
source,
|
||||
/fetchCloudChartLibrary\(\)[\s\S]{0,800}upsertSelfChart\(cloudLibrary\.filter\(\(record\) => record\.role !== "self"\), profile\)/,
|
||||
/fetchCloudChartLibrary\(\)[\s\S]{0,800}upsertSelfChart\(cloudLibrary\.filter\(\(record\) => record\.role !== "self"\), profileForLibrary\)/,
|
||||
);
|
||||
assert.doesNotMatch(source, /fetchCloudChartLibrary\(\)[\s\S]{0,800}new Map\(\[[\s\S]{0,500}current\.filter\(\(record\) => record\.role === "other"\)/);
|
||||
});
|
||||
@@ -81,3 +81,12 @@ test("relationship intent selects domain-specific evidence instead of treating e
|
||||
assert.match(source, /基础商业合作证据筛查/);
|
||||
assert.match(source, /relationshipType === "business"/);
|
||||
});
|
||||
|
||||
|
||||
test("current chart selection is local and does not overwrite the owner's profile", () => {
|
||||
assert.match(source, /activeChartStorageKey/);
|
||||
assert.match(source, /localStorage\.setItem\(activeChartStorageKey\(accountId\), record\.id\)/);
|
||||
assert.match(source, /已设为当前使用资料,账户本人的出生资料未被覆盖/);
|
||||
assert.doesNotMatch(source, /function makeDefaultChart[\s\S]{0,500}persistProfile\(/);
|
||||
assert.match(readFileSync(new URL("../src/app/api/chart-profiles/[id]/route.ts", import.meta.url), "utf8"), /星盘不存在或无权更新/);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user