@xia-sc/dsh-cc-studio 0.9.1 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/client.js CHANGED
@@ -236,6 +236,8 @@ window.__ModuleLoader__.load({
236
236
  "workshop.rel.rendered":"已把 {n} 条关系写进当前卡(记得「保存当前」才会落库)",
237
237
  "workshop.rel.checkResult":"体检:{n} 个问题",
238
238
  "workshop.rel.checkOk":"体检通过:没有结构性问题",
239
+ "workshop.rel.checkStats":"体检:{e} 个错误 · {w} 个警告",
240
+ "workshop.rel.checkPass":"体检通过:没有发现问题",
239
241
  "workshop.rel.saved":"关系已更新(rev {rev})",
240
242
  "workshop.rel.needLoad":"先在左侧「载入」一张卡:渲染要知道写进哪张卡",
241
243
  "workshop.rel.hint":"关系只存在插件侧,不写进 CCv3 字段;「渲染到当前卡」会把它们写进 description 的【关系】段,让分享出去的卡自包含。",
@@ -551,6 +553,8 @@ window.__ModuleLoader__.load({
551
553
  "workshop.rel.rendered":"Wrote {n} relations into the current card (remember to “Save current”)",
552
554
  "workshop.rel.checkResult":"Check: {n} issue(s)",
553
555
  "workshop.rel.checkOk":"Check passed: no structural issues",
556
+ "workshop.rel.checkStats":"Check: {e} error(s) · {w} warning(s)",
557
+ "workshop.rel.checkPass":"Check passed: no issues",
554
558
  "workshop.rel.saved":"Relations updated (rev {rev})",
555
559
  "workshop.rel.needLoad":"Load a card on the left first: rendering needs to know which card to write into",
556
560
  "workshop.rel.hint":"Relations live on the plugin side only and are never written into CCv3 fields; “Render into current card” writes them into the 【关系】 block of description so a shared card stays self-contained.",
@@ -707,7 +711,7 @@ window.__ModuleLoader__.load({
707
711
  var _saved = loadSettings();
708
712
  // 兼容旧开关:poll=false 视为 0 秒
709
713
  if(_saved.poll===false) _saved.pollInterval = 0;
710
- var state={ draft: draft, draftStatus: null, cur:0, panelOpen:false, sideExpanded:false, isCcMode:false, currentSessionId:null, slotWarn:null, alternateSlots:null, world:{ timeline:"", factions:"", geo:"", power:"", daily:"" }, busy:null, valid:{valid:true,errors:[],warnings:[]}, lastMsg:null, library:[], libraryQuery:"", libraryCollapsed:false, libraryBusy:null, groups:[], currentGroupId:"", relations:null, relBusy:null, currentLibraryId:null, book:null, bookBusy:null, bookMerge:false, editingWorld:null, editingWorldRevert:null, editingText:null, pollEnabled:_saved.poll, pollInterval:_saved.pollInterval, autoValidate:_saved.autoValidate, autoSaveOnImport:_saved.autoSaveOnImport };
714
+ var state={ draft: draft, draftStatus: null, cur:0, panelOpen:false, sideExpanded:false, isCcMode:false, currentSessionId:null, slotWarn:null, alternateSlots:null, world:{ timeline:"", factions:"", geo:"", power:"", daily:"" }, busy:null, valid:{valid:true,errors:[],warnings:[]}, lastMsg:null, library:[], libraryQuery:"", libraryCollapsed:false, libraryBusy:null, groups:[], currentGroupId:"", relations:null, relBusy:null, relIssues:null, relByCheck:null, currentLibraryId:null, book:null, bookBusy:null, bookMerge:false, editingWorld:null, editingWorldRevert:null, editingText:null, pollEnabled:_saved.poll, pollInterval:_saved.pollInterval, autoValidate:_saved.autoValidate, autoSaveOnImport:_saved.autoSaveOnImport };
711
715
  var listeners=new Set();
712
716
  function emit(){ listeners.forEach(function(fn){ try{fn();}catch(e){console.error(e);} }); }
713
717
  function getSnapshot(){ return state; }
@@ -1104,12 +1108,13 @@ window.__ModuleLoader__.load({
1104
1108
  }
1105
1109
  async function loadGroup(id){
1106
1110
  var gid = String(id || state.currentGroupId || "");
1107
- if(!gid){ set({relations:null}); return; }
1111
+ if(!gid){ set({relations:null, relIssues:null}); return; }
1108
1112
  set({relBusy:"load"});
1109
1113
  try{
1110
1114
  var res = await rpc("cc_getGroup", {id: gid});
1111
- if(res && res.ok && res.value) set({relations: res.value});
1112
- else set({relations:null, lastMsg:String((res && res.error && res.error.message) || "")});
1115
+ // 换了组就把上一次的体检清单清掉:留着会让用户以为新组也有那些问题(0.10.0)
1116
+ if(res && res.ok && res.value) set({relations: res.value, relIssues:null, relByCheck:null});
1117
+ else set({relations:null, relIssues:null, relByCheck:null, lastMsg:String((res && res.error && res.error.message) || "")});
1113
1118
  }catch(e){ set({lastMsg:String(e && e.message || e)}); }
1114
1119
  set({relBusy:null});
1115
1120
  }
@@ -1436,9 +1441,10 @@ window.__ModuleLoader__.load({
1436
1441
  var res = await rpc("cc_groupCheck", {id: gid});
1437
1442
  if(res && res.ok && res.value){
1438
1443
  var issues = res.value.issues || [];
1439
- set({lastMsg: issues.length
1440
- ? t("workshop.rel.checkResult", {n: String(issues.length)}) + " — " + issues.map(function(i){ return i.message; }).join(";")
1441
- : t("workshop.rel.checkOk")});
1444
+ // 0.10.0:清单存进 state 由下面分组渲染(不再把十来个问题挤成一行 lastMsg —— 加了跨卡一致性检查以后
1445
+ // 一行文本会长到没法读);lastMsg 只留一句计数,兼容旧观感。
1446
+ set({relIssues: issues, relByCheck: res.value.byCheck || null,
1447
+ lastMsg: issues.length ? t("workshop.rel.checkResult", {n: String(issues.length)}) : t("workshop.rel.checkOk")});
1442
1448
  } else set({lastMsg:String((res && res.error && res.error.message) || "")});
1443
1449
  }catch(e){ set({lastMsg:String(e && e.message || e)}); }
1444
1450
  set({relBusy:null});
@@ -2383,6 +2389,25 @@ window.__ModuleLoader__.load({
2383
2389
  h("button",{type:"button", style:Object.assign({}, S.btnGhost, {border:"1px solid var(--dsw-alias-border-l1)", background:"transparent", color:"var(--dsw-alias-label-primary)", borderRadius:8, padding:"4px 12px", fontSize:12}), onClick:function(){ store.checkGroupNow(); }, disabled: s.relBusy==="check"}, s.relBusy==="check" ? "…" : t("workshop.rel.check")),
2384
2390
  h("button",{type:"button", style:Object.assign({}, S.btnGhost, {border:"1px solid var(--dsw-alias-border-l1)", background:"transparent", color:"var(--dsw-alias-label-secondary)", borderRadius:8, padding:"4px 12px", fontSize:12}), onClick:function(){ store.loadGroup(gid); }}, t("action.refresh")),
2385
2391
  h("button",{type:"button", style:Object.assign({}, S.btnGhost, {border:"1px solid #3a2a2a", background:"transparent", color:"#e8a6a6", borderRadius:8, padding:"4px 12px", fontSize:12}), onClick:function(){ store.deleteGroup(gid); }}, t("common.delete")))),
2392
+ // —— 体检清单(0.10.0):按 error / warn 分组显示,每条前面挂检查类别 ——
2393
+ // 界面上原本只有一行拼接文本;加上跨卡一致性检查以后问题可能十来条,一行会糊成一片。
2394
+ // 这里只负责**显示**宿主返回的 issues / byCheck,不参与任何统计口径(数字都在卡组层算好了)。
2395
+ (function(){
2396
+ var issues = s.relIssues;
2397
+ if(!issues || !issues.length) return null;
2398
+ var errs = issues.filter(function(i){ return i.level === "error"; });
2399
+ var warns = issues.filter(function(i){ return i.level !== "error"; });
2400
+ function row(i, key){
2401
+ return h("div",{key:key, style:{display:"flex", gap:6, alignItems:"flex-start", padding:"2px 0", lineHeight:1.6}},
2402
+ h("span",{style:Object.assign({}, S.badge, {flexShrink:0, fontSize:10, opacity:0.85})}, String(i.check || "")),
2403
+ h("span",{style:{fontSize:11.5, color: i.level === "error" ? "#e8a6a6" : "var(--dsw-alias-label-secondary)"}}, String(i.message || "")));
2404
+ }
2405
+ return h("div",{style:{marginTop:12, borderTop:"1px solid var(--dsw-alias-border-l1)", paddingTop:10}},
2406
+ h("div",{style:{fontSize:12, fontWeight:600, marginBottom:4}},
2407
+ t("workshop.rel.checkStats", {e: String(errs.length), w: String(warns.length)})),
2408
+ errs.map(function(i, idx){ return row(i, "ce" + idx); }),
2409
+ warns.map(function(i, idx){ return row(i, "cw" + idx); }));
2410
+ })(),
2386
2411
  s.lastMsg ? h("div",{style:{marginTop:10, fontSize:12, color:"var(--dsw-alias-label-secondary)", lineHeight:1.7}}, s.lastMsg) : null,
2387
2412
  // —— 二级弹窗:改一条关系 / 加一条关系(列表只读,动作都在这里)——
2388
2413
  relEdit ? relDialog("workshop.rel.editTitle", relEdit, setRelEdit,