@airalogy/aimd-editor 1.8.0 → 1.9.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/dist/AimdEditorTopBar.vue_vue_type_script_setup_true_lang-DUzstO_i.js +1145 -0
- package/dist/{AimdWysiwygEditor.vue_vue_type_script_setup_true_lang-tRm4S2Nv.js → AimdWysiwygEditor.vue_vue_type_script_setup_true_lang-BYUea59a.js} +13 -6
- package/dist/aimd-editor.css +1 -1
- package/dist/embedded.js +1 -1
- package/dist/index.js +2 -2
- package/dist/vue.js +2 -2
- package/dist/wysiwyg.js +1 -1
- package/package.json +1 -1
- package/src/vue/AimdEditor.vue +7 -0
- package/src/vue/AimdFieldDialog.vue +58 -15
- package/src/vue/locales.ts +3 -0
- package/src/vue/types.ts +21 -11
- package/src/vue/useEditorContent.ts +7 -1
- package/dist/AimdEditorTopBar.vue_vue_type_script_setup_true_lang-yYY-Yq1g.js +0 -1131
|
@@ -118,6 +118,7 @@ const jy = {
|
|
|
118
118
|
dragToReorder: "Drag to reorder",
|
|
119
119
|
answer: "Answer",
|
|
120
120
|
correct: "Correct",
|
|
121
|
+
correctAnswer: "Correct Answer",
|
|
121
122
|
optionsHint: "Use unique keys (A/B/C), then mark answer directly in each row.",
|
|
122
123
|
blanks: "Blanks",
|
|
123
124
|
blanksHint: "Use keys like b1, b2 and refer to them in stem as [[b1]], [[b2]].",
|
|
@@ -312,6 +313,7 @@ const jy = {
|
|
|
312
313
|
dragToReorder: "拖拽排序",
|
|
313
314
|
answer: "答案",
|
|
314
315
|
correct: "正确",
|
|
316
|
+
correctAnswer: "正确答案",
|
|
315
317
|
optionsHint: "请使用唯一键(A/B/C),并直接在每一行标记答案。",
|
|
316
318
|
blanks: "填空项",
|
|
317
319
|
blanksHint: "请使用 b1、b2 这样的键,并在题干中写成 [[b1]]、[[b2]]。",
|
|
@@ -560,7 +562,7 @@ function n1(t, e) {
|
|
|
560
562
|
}
|
|
561
563
|
function r1(t) {
|
|
562
564
|
const e = t.split(",").map((n) => n.trim()).filter(Boolean);
|
|
563
|
-
return e.length === 0 ? [{ key: "b1", answer: "
|
|
565
|
+
return e.length === 0 ? [{ key: "b1", answer: "" }] : e.map((n, r) => {
|
|
564
566
|
const i = n.indexOf(":");
|
|
565
567
|
if (i > 0) {
|
|
566
568
|
const o = n.slice(0, i).trim() || `b${r + 1}`, s = n.slice(i + 1).trim() || "";
|
|
@@ -576,24 +578,29 @@ function i1(t) {
|
|
|
576
578
|
const n = Number(e);
|
|
577
579
|
return Number.isNaN(n) || n < 0 ? null : String(n);
|
|
578
580
|
}
|
|
579
|
-
function dI(t, e) {
|
|
581
|
+
function dI(t, e, n) {
|
|
580
582
|
switch (t) {
|
|
581
583
|
case "var":
|
|
582
584
|
return { name: "", type: "str", default: "", title: "" };
|
|
583
585
|
case "var_table":
|
|
584
586
|
return { name: "", subvars: "" };
|
|
585
|
-
case "quiz":
|
|
587
|
+
case "quiz": {
|
|
588
|
+
const r = "choice", i = `quiz_${r}`;
|
|
589
|
+
let o = 1;
|
|
590
|
+
for (; n?.has(`${i}_${o}`); )
|
|
591
|
+
o += 1;
|
|
586
592
|
return {
|
|
587
|
-
id:
|
|
588
|
-
quizType:
|
|
593
|
+
id: `${i}_${o}`,
|
|
594
|
+
quizType: r,
|
|
589
595
|
mode: "single",
|
|
590
596
|
stem: e?.defaults.questionStem || hn.defaults.questionStem,
|
|
591
597
|
options: `A:${tr("A", e)}, B:${tr("B", e)}`,
|
|
592
598
|
answer: "A",
|
|
593
|
-
blanks: "b1:
|
|
599
|
+
blanks: "b1:",
|
|
594
600
|
rubric: "",
|
|
595
601
|
score: ""
|
|
596
602
|
};
|
|
603
|
+
}
|
|
597
604
|
case "step":
|
|
598
605
|
return { name: "", level: "1" };
|
|
599
606
|
case "check":
|
package/dist/aimd-editor.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
.ProseMirror .tableWrapper{overflow-x:auto}.ProseMirror table{border-collapse:collapse;table-layout:fixed;width:100%;overflow:hidden}.ProseMirror td,.ProseMirror th{vertical-align:top;box-sizing:border-box;position:relative}.ProseMirror td:not([data-colwidth]):not(.column-resize-dragging),.ProseMirror th:not([data-colwidth]):not(.column-resize-dragging){min-width:var(--default-cell-min-width)}.ProseMirror .column-resize-handle{position:absolute;right:-2px;top:0;bottom:0;width:4px;z-index:20;background-color:#adf;pointer-events:none}.ProseMirror.resize-cursor{cursor:ew-resize;cursor:col-resize}.ProseMirror .selectedCell:after{z-index:2;position:absolute;content:"";inset:0;background:#c8c8ff66;pointer-events:none}.aimd-dialog-overlay{position:fixed;inset:0;background:#00000059;display:flex;align-items:center;justify-content:center;z-index:10000;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px)}.aimd-dialog{background:#fff;border-radius:12px;box-shadow:0 20px 60px #0003;width:520px;max-width:90vw;max-height:85vh;display:flex;flex-direction:column;overflow:hidden}.aimd-dialog-header{display:flex;align-items:center;justify-content:space-between;padding:16px 20px;border-bottom:1px solid #f0f0f0}.aimd-dialog-title{font-size:16px;font-weight:600;color:#1a1a2e;display:flex;align-items:center;gap:8px}.aimd-dialog-icon{display:flex;align-items:center}.aimd-dialog-icon svg{width:20px;height:20px}.aimd-dialog-close{width:32px;height:32px;border:none;background:transparent;cursor:pointer;font-size:22px;color:#999;border-radius:6px;display:flex;align-items:center;justify-content:center}.aimd-dialog-close:hover{background:#f0f2f5;color:#333}.aimd-dialog-type-tabs{display:flex;flex-wrap:wrap;align-items:center;border-bottom:1px solid #f0f0f0;padding:10px 12px;gap:8px}.aimd-type-tab{display:inline-flex;align-items:center;gap:6px;padding:7px 10px;border:1px solid #e5e7eb;border-radius:999px;background:#fff;cursor:pointer;font-size:12px;color:#6b7280;white-space:nowrap;transition:all .15s}.aimd-type-tab:hover{color:#374151;border-color:#d1d5db;background:#f8fafc}.aimd-type-tab-icon{display:inline-flex;align-items:center;vertical-align:middle}.aimd-type-tab-icon svg{width:14px;height:14px}.aimd-type-tab.active{font-weight:600}.aimd-dialog-body{padding:20px;display:flex;flex-direction:column;gap:14px;overflow-y:auto}.aimd-field-row{display:flex;flex-direction:column;gap:4px}.aimd-field-label{font-size:13px;font-weight:500;color:#444}.aimd-field-label em{color:#dc2626;font-style:normal}.aimd-field-input{padding:8px 12px;border:1px solid #e0e0e0;border-radius:6px;font-size:14px;outline:none;transition:border-color .2s;font-family:inherit}.aimd-field-input:focus{border-color:#1a73e8;box-shadow:0 0 0 2px #1a73e81a}.aimd-field-textarea{min-height:72px;resize:vertical}.aimd-field-hint{font-size:11px;color:#999}.aimd-var-type-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:8px}.aimd-var-type-card{display:flex;flex-direction:column;align-items:flex-start;gap:4px;padding:10px 12px;border:1px solid #e5e7eb;border-radius:10px;background:#fff;cursor:pointer;text-align:left;transition:border-color .15s,box-shadow .15s,background .15s,transform .15s}.aimd-var-type-card:hover{border-color:#93c5fd;background:#f8fbff;transform:translateY(-1px)}.aimd-var-type-card:focus-visible{outline:none;border-color:#2563eb;box-shadow:0 0 0 3px #2563eb26}.aimd-var-type-card.active{border-color:#2563eb;background:#eff6ff;box-shadow:0 0 0 2px #2563eb1f}.aimd-var-type-card-title{font-size:13px;font-weight:600;color:#1f2937}.aimd-var-type-card-desc{font-size:12px;line-height:1.4;color:#6b7280}.aimd-collection-editor{display:flex;flex-direction:column;gap:8px}.aimd-collection-row{display:grid;grid-template-columns:90px 1fr auto;gap:8px;align-items:center}.aimd-option-row{grid-template-columns:26px 96px 90px 1fr auto}.aimd-option-row-dragover{background:#eff6ff;border-radius:6px}.aimd-option-answer-toggle{display:flex;align-items:center;gap:6px;color:#4b5563;font-size:12px;-webkit-user-select:none;user-select:none}.aimd-option-answer-toggle input{margin:0}.aimd-drag-handle{color:#9ca3af;cursor:grab;-webkit-user-select:none;user-select:none;text-align:center;font-size:14px;line-height:1}.aimd-drag-handle:active{cursor:grabbing}.aimd-mini-btn{border:1px solid #d8dee8;background:#fff;color:#4b5563;border-radius:6px;padding:6px 10px;font-size:12px;cursor:pointer}.aimd-mini-btn:hover{background:#f8fafc}.aimd-mini-btn:disabled{opacity:.5;cursor:not-allowed}.aimd-mini-btn-add{align-self:flex-start}.aimd-dialog-preview{padding:12px 14px;background:#f8f9fa;border-radius:6px;border:1px solid #e8e8e8;display:flex;flex-direction:column;align-items:stretch;gap:10px}.aimd-preview-header{display:block;font-size:12px;color:#6b7280;font-weight:600;letter-spacing:.04em}.aimd-preview-panel{display:block;width:100%;margin:0;padding:10px 12px;border-radius:6px;border:1px solid #dbe3ef;background:#fff;overflow:auto;max-height:280px;line-height:1.5}.aimd-preview-code{display:block;font-family:SF Mono,Fira Code,monospace;font-size:13px;color:#2563eb;word-break:break-word;white-space:pre-wrap}.aimd-dialog-error{padding:10px 12px;border:1px solid #fecaca;background:#fef2f2;color:#b91c1c;border-radius:6px;font-size:12px;line-height:1.5}.aimd-dialog-footer{display:flex;justify-content:flex-end;gap:8px;padding:14px 20px;border-top:1px solid #f0f0f0}.aimd-btn{padding:8px 20px;border-radius:6px;font-size:13px;font-weight:500;cursor:pointer;transition:all .15s}.aimd-btn-cancel{border:1px solid #e0e0e0;background:#fff;color:#666}.aimd-btn-cancel:hover{background:#f5f5f5}.aimd-btn-primary{border:none;background:#1a73e8;color:#fff}.aimd-btn-primary:hover{background:#1557b0}.aimd-editor{display:flex;flex-direction:column;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif;border:1px solid #e0e0e0;border-radius:8px;overflow:hidden}.aimd-editor-toolbar{display:flex;align-items:center;gap:2px;padding:4px 8px;background:#fafbfc;border-bottom:1px solid #e0e0e0;overflow-x:auto;flex-wrap:wrap}.aimd-editor-mode-switch{display:flex;background:#eceef1;border-radius:5px;padding:2px;gap:1px;flex-shrink:0}.aimd-editor-mode-btn{display:flex;align-items:center;gap:4px;padding:4px 10px;border:none;border-radius:4px;background:transparent;cursor:pointer;font-size:12px;font-weight:500;color:#777;transition:all .15s;white-space:nowrap}.aimd-editor-mode-btn:hover{color:#444;background:#ffffff80}.aimd-editor-mode-btn.active{background:#fff;color:#1a73e8;box-shadow:0 1px 2px #00000014}.aimd-editor-mode-icon{display:flex;align-items:center}.aimd-editor-toolbar-sep{width:1px;height:20px;background:#ddd;margin:0 4px;flex-shrink:0}.aimd-editor-toolbar-divider{width:1px;height:22px;background:#ccc;margin:0 6px;flex-shrink:0}.aimd-editor-fmt-btn{width:28px;height:28px;border:1px solid transparent;border-radius:4px;background:transparent;cursor:pointer;color:#555;display:flex;align-items:center;justify-content:center;transition:all .12s;padding:0;flex-shrink:0}.aimd-editor-fmt-btn:hover{background:#eceef1;color:#222}.aimd-editor-fmt-btn:active{background:#dfe1e5}.aimd-editor-fmt-btn svg{width:16px;height:16px;display:block}.aimd-editor-aimd-btn{width:auto;gap:3px;padding:0 7px;border:1px solid color-mix(in srgb,var(--aimd-color, #2563eb) 18%,transparent);background:color-mix(in srgb,var(--aimd-color, #2563eb) 4%,transparent);border-radius:4px}.aimd-editor-aimd-btn:hover{background:color-mix(in srgb,var(--aimd-color, #2563eb) 12%,transparent);border-color:color-mix(in srgb,var(--aimd-color, #2563eb) 35%,transparent);color:var(--aimd-color, #2563eb)}.aimd-editor-aimd-btn-icon{display:flex;align-items:center}.aimd-editor-aimd-btn-icon svg{width:13px;height:13px}.aimd-editor-aimd-btn-label{font-size:11px;font-weight:500}.aimd-editor-panel{background:#fff;overflow:hidden}.aimd-editor-source-mode{overflow:hidden}.aimd-editor-container{height:100%}.aimd-editor-loading{padding:40px;text-align:center;color:#888}.aimd-editor-wysiwyg-mode .milkdown{height:100%}.aimd-editor-wysiwyg-mode .milkdown-editor-content{padding:0 20px 6px;min-height:100%;outline:none;font-size:15px;line-height:1.8}.aimd-editor-wysiwyg-mode .milkdown-editor-content .ProseMirror{outline:none}.aimd-editor-wysiwyg-mode h1{font-size:1.8em;margin:.6em 0 .3em;font-weight:700}.aimd-editor-wysiwyg-mode h2{font-size:1.4em;margin:.5em 0 .3em;color:#333;font-weight:600;border-bottom:1px solid #eee;padding-bottom:.2em}.aimd-editor-wysiwyg-mode h3{font-size:1.2em;margin:.4em 0 .2em;font-weight:600}.aimd-editor-wysiwyg-mode p{margin:.5em 0}.aimd-editor-wysiwyg-mode blockquote{border-left:4px solid #dfe2e5;padding:8px 16px;margin:8px 0;color:#666;background:#fafafa;border-radius:0 4px 4px 0}.aimd-editor-wysiwyg-mode ul,.aimd-editor-wysiwyg-mode ol{padding-left:24px;margin:4px 0}.aimd-editor-wysiwyg-mode code{background:#f0f2f5;padding:2px 6px;border-radius:3px;font-size:.9em;font-family:SF Mono,Fira Code,monospace}.aimd-editor-wysiwyg-mode pre{background:#1e1e2e;color:#cdd6f4;padding:16px;border-radius:8px;overflow-x:auto}.aimd-editor-wysiwyg-mode pre code{background:none;padding:0;color:inherit}.aimd-editor-wysiwyg-mode hr{border:none;border-top:2px solid #e8e8e8;margin:16px 0}.aimd-editor-wysiwyg-mode img{max-width:100%;border-radius:4px}.aimd-editor-wysiwyg-mode a{color:#1a73e8;text-decoration:none}.aimd-editor-wysiwyg-mode a:hover{text-decoration:underline}.aimd-editor-wysiwyg-mode li{margin:2px 0}.aimd-editor-wysiwyg-mode .tableWrapper{overflow-x:auto;margin:12px 0}.aimd-block-handle{position:absolute;z-index:10;transition:top .15s ease,left .15s ease}.aimd-block-handle[data-show=false]{opacity:0;pointer-events:none}.aimd-block-handle-btn{width:24px;height:24px;display:flex;align-items:center;justify-content:center;border-radius:4px;background:#fff;border:1px solid #e0e0e0;color:#aaa;cursor:pointer;transition:all .15s;box-shadow:0 1px 2px #0000000d}.aimd-block-handle-btn:hover{background:#f0f2f5;border-color:silver;color:#555}.aimd-block-add-menu{position:fixed;z-index:10000;background:#fff;border:1px solid #e0e0e0;border-radius:8px;box-shadow:0 4px 16px #0000001f;padding:4px;min-width:200px;max-height:400px;overflow-y:auto}.aimd-block-add-menu-group-label{padding:6px 12px 2px;font-size:11px;font-weight:600;color:#999;text-transform:uppercase;letter-spacing:.5px}.aimd-block-add-menu-divider{height:1px;background:#eee;margin:4px 8px}.aimd-block-add-menu-item{display:flex;align-items:center;gap:10px;width:100%;padding:8px 12px;border:none;background:none;border-radius:5px;cursor:pointer;font-size:13px;color:#333;text-align:left;transition:background .1s}.aimd-block-add-menu-item:hover{background:#f0f2f5}.aimd-block-add-menu-icon{width:24px;height:24px;display:flex;align-items:center;justify-content:center;border-radius:4px;background:#f0f2f5;color:#666;flex-shrink:0}.aimd-block-add-menu-icon svg{width:14px;height:14px}.milkdown-table-block{display:block;margin:4px 0}.milkdown-table-block table{margin:0!important;border-radius:0!important}.milkdown-table-block .handle{position:absolute;z-index:50;cursor:grab;font-size:14px}.milkdown-table-block .cell-handle{left:-999px;top:-999px;z-index:100;height:24px;transition:opacity .2s ease .2s;background-color:#a8d4ff;padding:0 8px;border-radius:8px;position:absolute}.milkdown-table-block .cell-handle[data-role=col-drag-handle]{transform:translateY(50%)}.milkdown-table-block .cell-handle[data-role=row-drag-handle]{transform:translate(50%)}.milkdown-table-block .cell-handle[data-show=false],.milkdown-table-block .line-handle[data-show=false]{opacity:0}.milkdown-table-block .handle:hover{opacity:1}.milkdown-table-block .cell-handle .button-group{position:absolute;height:30px;top:-32px;display:flex;transform:translate(-50%);left:50%;background-color:#fff;border:1px solid #ccc;border-radius:4px}.milkdown-table-block .cell-handle .button-group[data-show=false]{display:none}.milkdown-table-block .cell-handle .button-group button{padding-left:8px;padding-right:8px;width:max-content;border:none;background:none;cursor:pointer}.milkdown-table-block .cell-handle .button-group button:hover{background-color:#f0f0f0}.milkdown-table-block .line-handle{background-color:#a8d4ff;transition:opacity .2s ease-in-out}.milkdown-table-block .line-handle[data-role=x-line-drag-handle]{height:2px}.milkdown-table-block .line-handle[data-role=y-line-drag-handle]{width:2px}.milkdown-table-block .line-handle .add-button{color:#1a73e8;border:1px solid #a8d4ff;padding:0 4px;border-radius:8px;width:max-content;background:#fff;cursor:pointer}.milkdown-table-block .line-handle[data-role=x-line-drag-handle] .add-button{position:absolute;transform:translate(-100%);top:-12px;height:24px}.milkdown-table-block .line-handle[data-role=y-line-drag-handle] .add-button{position:absolute;transform:translate(-50%);top:-24px;height:24px}.milkdown-table-block .line-handle[data-display-type=indicator] .add-button{display:none}.milkdown-table-block .drag-preview{position:absolute;z-index:100;border:1px solid #ccc;opacity:.5;display:flex;flex-direction:column}.milkdown-table-block .drag-preview table{margin:0}.milkdown-table-block .drag-preview[data-show=false]{display:none}.aimd-editor-wysiwyg-mode th,.aimd-editor-wysiwyg-mode td{border:1px solid #ddd;padding:4px 16px;position:relative}.aimd-editor-wysiwyg-mode th{background:#f5f7fa;font-weight:600}.aimd-editor-wysiwyg-mode .ProseMirror-selectednode{outline:none!important}.milkdown-table-block .ProseMirror-selectednode{outline:none!important;background-color:transparent!important}.aimd-editor-wysiwyg-mode td:has(.ProseMirror-selectednode),.aimd-editor-wysiwyg-mode th:has(.ProseMirror-selectednode){outline:1px solid #a8a8a8;outline-offset:-1px}.aimd-editor-wysiwyg-mode .selectedCell{position:relative}.aimd-editor-wysiwyg-mode .selectedCell:after{content:"";position:absolute;inset:0;background-color:#d5d5d5;opacity:.4;pointer-events:none}.aimd-editor-wysiwyg-mode .selectedCell::selection{background:transparent}.milkdown-table-block .cell-handle .button-group button svg{width:18px;height:18px;fill:currentColor}.milkdown-table-block .cell-handle svg{width:14px;height:14px;fill:currentColor}.milkdown-table-block .line-handle .add-button svg{width:16px;height:16px;fill:currentColor}.aimd-placeholder{position:relative}.aimd-placeholder:before{content:attr(data-placeholder);position:absolute;color:#aaa;pointer-events:none;font-style:italic}.aimd-editor-wysiwyg-mode aimd-field{display:inline-flex;align-items:center;gap:3px;padding:1px 8px 1px 6px;border-radius:4px;font-size:13px;font-family:SF Mono,Fira Code,Consolas,monospace;line-height:1.6;vertical-align:baseline;border:1px solid rgba(37,99,235,.2);background:#2563eb0d;color:#2563eb}
|
|
1
|
+
.ProseMirror .tableWrapper{overflow-x:auto}.ProseMirror table{border-collapse:collapse;table-layout:fixed;width:100%;overflow:hidden}.ProseMirror td,.ProseMirror th{vertical-align:top;box-sizing:border-box;position:relative}.ProseMirror td:not([data-colwidth]):not(.column-resize-dragging),.ProseMirror th:not([data-colwidth]):not(.column-resize-dragging){min-width:var(--default-cell-min-width)}.ProseMirror .column-resize-handle{position:absolute;right:-2px;top:0;bottom:0;width:4px;z-index:20;background-color:#adf;pointer-events:none}.ProseMirror.resize-cursor{cursor:ew-resize;cursor:col-resize}.ProseMirror .selectedCell:after{z-index:2;position:absolute;content:"";inset:0;background:#c8c8ff66;pointer-events:none}.aimd-dialog-overlay{position:fixed;inset:0;background:#00000059;display:flex;align-items:center;justify-content:center;z-index:10000;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px)}.aimd-dialog{background:#fff;border-radius:12px;box-shadow:0 20px 60px #0003;width:520px;max-width:90vw;max-height:85vh;display:flex;flex-direction:column;overflow:hidden}.aimd-dialog-header{display:flex;align-items:center;justify-content:space-between;padding:16px 20px;border-bottom:1px solid #f0f0f0}.aimd-dialog-title{font-size:16px;font-weight:600;color:#1a1a2e;display:flex;align-items:center;gap:8px}.aimd-dialog-icon{display:flex;align-items:center}.aimd-dialog-icon svg{width:20px;height:20px}.aimd-dialog-close{width:32px;height:32px;border:none;background:transparent;cursor:pointer;font-size:22px;color:#999;border-radius:6px;display:flex;align-items:center;justify-content:center}.aimd-dialog-close:hover{background:#f0f2f5;color:#333}.aimd-dialog-type-tabs{display:flex;flex-wrap:wrap;align-items:center;border-bottom:1px solid #f0f0f0;padding:10px 12px;gap:8px}.aimd-type-tab{display:inline-flex;align-items:center;gap:6px;padding:7px 10px;border:1px solid #e5e7eb;border-radius:999px;background:#fff;cursor:pointer;font-size:12px;color:#6b7280;white-space:nowrap;transition:all .15s}.aimd-type-tab:hover{color:#374151;border-color:#d1d5db;background:#f8fafc}.aimd-type-tab-icon{display:inline-flex;align-items:center;vertical-align:middle}.aimd-type-tab-icon svg{width:14px;height:14px}.aimd-type-tab.active{font-weight:600}.aimd-dialog-body{padding:20px;display:flex;flex-direction:column;gap:14px;overflow-y:auto}.aimd-field-row{display:flex;flex-direction:column;gap:4px}.aimd-field-label{font-size:13px;font-weight:500;color:#444}.aimd-field-label em{color:#dc2626;font-style:normal}.aimd-field-input{padding:8px 12px;border:1px solid #e0e0e0;border-radius:6px;font-size:14px;outline:none;transition:border-color .2s;font-family:inherit}.aimd-field-input:focus{border-color:#1a73e8;box-shadow:0 0 0 2px #1a73e81a}.aimd-field-textarea{min-height:72px;resize:vertical}.aimd-field-hint{font-size:11px;color:#999}.aimd-var-type-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:8px}.aimd-var-type-card{display:flex;flex-direction:column;align-items:flex-start;gap:4px;padding:10px 12px;border:1px solid #e5e7eb;border-radius:10px;background:#fff;cursor:pointer;text-align:left;transition:border-color .15s,box-shadow .15s,background .15s,transform .15s}.aimd-var-type-card:hover{border-color:#93c5fd;background:#f8fbff;transform:translateY(-1px)}.aimd-var-type-card:focus-visible{outline:none;border-color:#2563eb;box-shadow:0 0 0 3px #2563eb26}.aimd-var-type-card.active{border-color:#2563eb;background:#eff6ff;box-shadow:0 0 0 2px #2563eb1f}.aimd-var-type-card-title{font-size:13px;font-weight:600;color:#1f2937}.aimd-var-type-card-desc{font-size:12px;line-height:1.4;color:#6b7280}.aimd-collection-editor{display:flex;flex-direction:column;gap:8px}.aimd-collection-row{display:grid;grid-template-columns:90px 1fr auto;gap:8px;align-items:center}.aimd-option-row{grid-template-columns:26px 60px 1fr 80px auto}.aimd-option-row-dragover{background:#eff6ff;border-radius:6px}.aimd-option-answer-toggle{display:flex;align-items:center;gap:6px;color:#4b5563;font-size:12px;-webkit-user-select:none;user-select:none}.aimd-option-answer-toggle input{margin:0}.aimd-drag-handle{color:#9ca3af;cursor:grab;-webkit-user-select:none;user-select:none;text-align:center;font-size:14px;line-height:1}.aimd-drag-handle:active{cursor:grabbing}.aimd-mini-btn{border:1px solid #d8dee8;background:#fff;color:#4b5563;border-radius:6px;padding:6px 10px;font-size:12px;cursor:pointer}.aimd-mini-btn:hover{background:#f8fafc}.aimd-mini-btn:disabled{opacity:.5;cursor:not-allowed}.aimd-mini-btn-add{align-self:flex-start}.aimd-dialog-preview{padding:12px 14px;background:#f8f9fa;border-radius:6px;border:1px solid #e8e8e8;display:flex;flex-direction:column;align-items:stretch;gap:10px}.aimd-preview-header{display:block;font-size:12px;color:#6b7280;font-weight:600;letter-spacing:.04em}.aimd-preview-panel{display:block;width:100%;margin:0;padding:10px 12px;border-radius:6px;border:1px solid #dbe3ef;background:#fff;overflow:auto;max-height:280px;line-height:1.5}.aimd-preview-code{display:block;font-family:SF Mono,Fira Code,monospace;font-size:13px;color:#2563eb;word-break:break-word;white-space:pre-wrap}.aimd-dialog-error{padding:10px 12px;border:1px solid #fecaca;background:#fef2f2;color:#b91c1c;border-radius:6px;font-size:12px;line-height:1.5}.aimd-dialog-footer{display:flex;justify-content:flex-end;gap:8px;padding:14px 20px;border-top:1px solid #f0f0f0}.aimd-btn{padding:8px 20px;border-radius:6px;font-size:13px;font-weight:500;cursor:pointer;transition:all .15s}.aimd-btn-cancel{border:1px solid #e0e0e0;background:#fff;color:#666}.aimd-btn-cancel:hover{background:#f5f5f5}.aimd-btn-primary{border:none;background:#1a73e8;color:#fff}.aimd-btn-primary:hover{background:#1557b0}.aimd-editor{display:flex;flex-direction:column;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif;border:1px solid #e0e0e0;border-radius:8px;overflow:hidden}.aimd-editor-toolbar{display:flex;align-items:center;gap:2px;padding:4px 8px;background:#fafbfc;border-bottom:1px solid #e0e0e0;overflow-x:auto;flex-wrap:wrap}.aimd-editor-mode-switch{display:flex;background:#eceef1;border-radius:5px;padding:2px;gap:1px;flex-shrink:0}.aimd-editor-mode-btn{display:flex;align-items:center;gap:4px;padding:4px 10px;border:none;border-radius:4px;background:transparent;cursor:pointer;font-size:12px;font-weight:500;color:#777;transition:all .15s;white-space:nowrap}.aimd-editor-mode-btn:hover{color:#444;background:#ffffff80}.aimd-editor-mode-btn.active{background:#fff;color:#1a73e8;box-shadow:0 1px 2px #00000014}.aimd-editor-mode-icon{display:flex;align-items:center}.aimd-editor-toolbar-sep{width:1px;height:20px;background:#ddd;margin:0 4px;flex-shrink:0}.aimd-editor-toolbar-divider{width:1px;height:22px;background:#ccc;margin:0 6px;flex-shrink:0}.aimd-editor-fmt-btn{width:28px;height:28px;border:1px solid transparent;border-radius:4px;background:transparent;cursor:pointer;color:#555;display:flex;align-items:center;justify-content:center;transition:all .12s;padding:0;flex-shrink:0}.aimd-editor-fmt-btn:hover{background:#eceef1;color:#222}.aimd-editor-fmt-btn:active{background:#dfe1e5}.aimd-editor-fmt-btn svg{width:16px;height:16px;display:block}.aimd-editor-aimd-btn{width:auto;gap:3px;padding:0 7px;border:1px solid color-mix(in srgb,var(--aimd-color, #2563eb) 18%,transparent);background:color-mix(in srgb,var(--aimd-color, #2563eb) 4%,transparent);border-radius:4px}.aimd-editor-aimd-btn:hover{background:color-mix(in srgb,var(--aimd-color, #2563eb) 12%,transparent);border-color:color-mix(in srgb,var(--aimd-color, #2563eb) 35%,transparent);color:var(--aimd-color, #2563eb)}.aimd-editor-aimd-btn-icon{display:flex;align-items:center}.aimd-editor-aimd-btn-icon svg{width:13px;height:13px}.aimd-editor-aimd-btn-label{font-size:11px;font-weight:500}.aimd-editor-panel{background:#fff;overflow:hidden}.aimd-editor-source-mode{overflow:hidden}.aimd-editor-container{height:100%}.aimd-editor-loading{padding:40px;text-align:center;color:#888}.aimd-editor-wysiwyg-mode .milkdown{height:100%}.aimd-editor-wysiwyg-mode .milkdown-editor-content{padding:0 20px 6px;min-height:100%;outline:none;font-size:15px;line-height:1.8}.aimd-editor-wysiwyg-mode .milkdown-editor-content .ProseMirror{outline:none}.aimd-editor-wysiwyg-mode h1{font-size:1.8em;margin:.6em 0 .3em;font-weight:700}.aimd-editor-wysiwyg-mode h2{font-size:1.4em;margin:.5em 0 .3em;color:#333;font-weight:600;border-bottom:1px solid #eee;padding-bottom:.2em}.aimd-editor-wysiwyg-mode h3{font-size:1.2em;margin:.4em 0 .2em;font-weight:600}.aimd-editor-wysiwyg-mode p{margin:.5em 0}.aimd-editor-wysiwyg-mode blockquote{border-left:4px solid #dfe2e5;padding:8px 16px;margin:8px 0;color:#666;background:#fafafa;border-radius:0 4px 4px 0}.aimd-editor-wysiwyg-mode ul,.aimd-editor-wysiwyg-mode ol{padding-left:24px;margin:4px 0}.aimd-editor-wysiwyg-mode code{background:#f0f2f5;padding:2px 6px;border-radius:3px;font-size:.9em;font-family:SF Mono,Fira Code,monospace}.aimd-editor-wysiwyg-mode pre{background:#1e1e2e;color:#cdd6f4;padding:16px;border-radius:8px;overflow-x:auto}.aimd-editor-wysiwyg-mode pre code{background:none;padding:0;color:inherit}.aimd-editor-wysiwyg-mode hr{border:none;border-top:2px solid #e8e8e8;margin:16px 0}.aimd-editor-wysiwyg-mode img{max-width:100%;border-radius:4px}.aimd-editor-wysiwyg-mode a{color:#1a73e8;text-decoration:none}.aimd-editor-wysiwyg-mode a:hover{text-decoration:underline}.aimd-editor-wysiwyg-mode li{margin:2px 0}.aimd-editor-wysiwyg-mode .tableWrapper{overflow-x:auto;margin:12px 0}.aimd-block-handle{position:absolute;z-index:10;transition:top .15s ease,left .15s ease}.aimd-block-handle[data-show=false]{opacity:0;pointer-events:none}.aimd-block-handle-btn{width:24px;height:24px;display:flex;align-items:center;justify-content:center;border-radius:4px;background:#fff;border:1px solid #e0e0e0;color:#aaa;cursor:pointer;transition:all .15s;box-shadow:0 1px 2px #0000000d}.aimd-block-handle-btn:hover{background:#f0f2f5;border-color:silver;color:#555}.aimd-block-add-menu{position:fixed;z-index:10000;background:#fff;border:1px solid #e0e0e0;border-radius:8px;box-shadow:0 4px 16px #0000001f;padding:4px;min-width:200px;max-height:400px;overflow-y:auto}.aimd-block-add-menu-group-label{padding:6px 12px 2px;font-size:11px;font-weight:600;color:#999;text-transform:uppercase;letter-spacing:.5px}.aimd-block-add-menu-divider{height:1px;background:#eee;margin:4px 8px}.aimd-block-add-menu-item{display:flex;align-items:center;gap:10px;width:100%;padding:8px 12px;border:none;background:none;border-radius:5px;cursor:pointer;font-size:13px;color:#333;text-align:left;transition:background .1s}.aimd-block-add-menu-item:hover{background:#f0f2f5}.aimd-block-add-menu-icon{width:24px;height:24px;display:flex;align-items:center;justify-content:center;border-radius:4px;background:#f0f2f5;color:#666;flex-shrink:0}.aimd-block-add-menu-icon svg{width:14px;height:14px}.milkdown-table-block{display:block;margin:4px 0}.milkdown-table-block table{margin:0!important;border-radius:0!important}.milkdown-table-block .handle{position:absolute;z-index:50;cursor:grab;font-size:14px}.milkdown-table-block .cell-handle{left:-999px;top:-999px;z-index:100;height:24px;transition:opacity .2s ease .2s;background-color:#a8d4ff;padding:0 8px;border-radius:8px;position:absolute}.milkdown-table-block .cell-handle[data-role=col-drag-handle]{transform:translateY(50%)}.milkdown-table-block .cell-handle[data-role=row-drag-handle]{transform:translate(50%)}.milkdown-table-block .cell-handle[data-show=false],.milkdown-table-block .line-handle[data-show=false]{opacity:0}.milkdown-table-block .handle:hover{opacity:1}.milkdown-table-block .cell-handle .button-group{position:absolute;height:30px;top:-32px;display:flex;transform:translate(-50%);left:50%;background-color:#fff;border:1px solid #ccc;border-radius:4px}.milkdown-table-block .cell-handle .button-group[data-show=false]{display:none}.milkdown-table-block .cell-handle .button-group button{padding-left:8px;padding-right:8px;width:max-content;border:none;background:none;cursor:pointer}.milkdown-table-block .cell-handle .button-group button:hover{background-color:#f0f0f0}.milkdown-table-block .line-handle{background-color:#a8d4ff;transition:opacity .2s ease-in-out}.milkdown-table-block .line-handle[data-role=x-line-drag-handle]{height:2px}.milkdown-table-block .line-handle[data-role=y-line-drag-handle]{width:2px}.milkdown-table-block .line-handle .add-button{color:#1a73e8;border:1px solid #a8d4ff;padding:0 4px;border-radius:8px;width:max-content;background:#fff;cursor:pointer}.milkdown-table-block .line-handle[data-role=x-line-drag-handle] .add-button{position:absolute;transform:translate(-100%);top:-12px;height:24px}.milkdown-table-block .line-handle[data-role=y-line-drag-handle] .add-button{position:absolute;transform:translate(-50%);top:-24px;height:24px}.milkdown-table-block .line-handle[data-display-type=indicator] .add-button{display:none}.milkdown-table-block .drag-preview{position:absolute;z-index:100;border:1px solid #ccc;opacity:.5;display:flex;flex-direction:column}.milkdown-table-block .drag-preview table{margin:0}.milkdown-table-block .drag-preview[data-show=false]{display:none}.aimd-editor-wysiwyg-mode th,.aimd-editor-wysiwyg-mode td{border:1px solid #ddd;padding:4px 16px;position:relative}.aimd-editor-wysiwyg-mode th{background:#f5f7fa;font-weight:600}.aimd-editor-wysiwyg-mode .ProseMirror-selectednode{outline:none!important}.milkdown-table-block .ProseMirror-selectednode{outline:none!important;background-color:transparent!important}.aimd-editor-wysiwyg-mode td:has(.ProseMirror-selectednode),.aimd-editor-wysiwyg-mode th:has(.ProseMirror-selectednode){outline:1px solid #a8a8a8;outline-offset:-1px}.aimd-editor-wysiwyg-mode .selectedCell{position:relative}.aimd-editor-wysiwyg-mode .selectedCell:after{content:"";position:absolute;inset:0;background-color:#d5d5d5;opacity:.4;pointer-events:none}.aimd-editor-wysiwyg-mode .selectedCell::selection{background:transparent}.milkdown-table-block .cell-handle .button-group button svg{width:18px;height:18px;fill:currentColor}.milkdown-table-block .cell-handle svg{width:14px;height:14px;fill:currentColor}.milkdown-table-block .line-handle .add-button svg{width:16px;height:16px;fill:currentColor}.aimd-placeholder{position:relative}.aimd-placeholder:before{content:attr(data-placeholder);position:absolute;color:#aaa;pointer-events:none;font-style:italic}.aimd-editor-wysiwyg-mode aimd-field{display:inline-flex;align-items:center;gap:3px;padding:1px 8px 1px 6px;border-radius:4px;font-size:13px;font-family:SF Mono,Fira Code,Consolas,monospace;line-height:1.6;vertical-align:baseline;border:1px solid rgba(37,99,235,.2);background:#2563eb0d;color:#2563eb}
|
package/dist/embedded.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { _ as s } from "./AimdSourceEditor.vue_vue_type_script_setup_true_lang-ttzw5IdG.js";
|
|
2
|
-
import { _ as i, D as d, i as o, j as t, k as A, r as m } from "./AimdWysiwygEditor.vue_vue_type_script_setup_true_lang-
|
|
2
|
+
import { _ as i, D as d, i as o, j as t, k as A, r as m } from "./AimdWysiwygEditor.vue_vue_type_script_setup_true_lang-BYUea59a.js";
|
|
3
3
|
export {
|
|
4
4
|
s as AimdSourceEditor,
|
|
5
5
|
i as AimdWysiwygEditor,
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { A as i, a as s, b as d, D as o, K as m, M as r, c as t, d as A, e as n, f as l, g as D, l as E, s as T } from "./theme-B8dCnOx-.js";
|
|
2
|
-
import { _, a as c, b as f, c as u, u as M } from "./AimdEditorTopBar.vue_vue_type_script_setup_true_lang-
|
|
2
|
+
import { _, a as c, b as f, c as u, u as M } from "./AimdEditorTopBar.vue_vue_type_script_setup_true_lang-DUzstO_i.js";
|
|
3
3
|
import { _ as p } from "./AimdSourceEditor.vue_vue_type_script_setup_true_lang-ttzw5IdG.js";
|
|
4
|
-
import { A as k, a as x, _ as L, D as O, M as S, b as y, c as b, d as N, e as P, f as R, g as w, h, i as B, j as C, k as v, l as K, m as V, n as Y, r as j } from "./AimdWysiwygEditor.vue_vue_type_script_setup_true_lang-
|
|
4
|
+
import { A as k, a as x, _ as L, D as O, M as S, b as y, c as b, d as N, e as P, f as R, g as w, h, i as B, j as C, k as v, l as K, m as V, n as Y, r as j } from "./AimdWysiwygEditor.vue_vue_type_script_setup_true_lang-BYUea59a.js";
|
|
5
5
|
export {
|
|
6
6
|
k as AIMD_FIELD_TYPES,
|
|
7
7
|
x as AIMD_FIELD_TYPE_DEFINITIONS,
|
package/dist/vue.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { _ as e, a as d, b as s, c as r, u as o } from "./AimdEditorTopBar.vue_vue_type_script_setup_true_lang-
|
|
1
|
+
import { _ as e, a as d, b as s, c as r, u as o } from "./AimdEditorTopBar.vue_vue_type_script_setup_true_lang-DUzstO_i.js";
|
|
2
2
|
import { _ as m } from "./AimdSourceEditor.vue_vue_type_script_setup_true_lang-ttzw5IdG.js";
|
|
3
|
-
import { A as E, a as l, _ as I, D as _, M as T, b as D, c as F, d as M, e as u, f as c, g as n, h as g, i as L, j as O, k as p, l as S, m as y, n as b, r as f } from "./AimdWysiwygEditor.vue_vue_type_script_setup_true_lang-
|
|
3
|
+
import { A as E, a as l, _ as I, D as _, M as T, b as D, c as F, d as M, e as u, f as c, g as n, h as g, i as L, j as O, k as p, l as S, m as y, n as b, r as f } from "./AimdWysiwygEditor.vue_vue_type_script_setup_true_lang-BYUea59a.js";
|
|
4
4
|
export {
|
|
5
5
|
E as AIMD_FIELD_TYPES,
|
|
6
6
|
l as AIMD_FIELD_TYPE_DEFINITIONS,
|
package/dist/wysiwyg.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { _ as a, D as r, i, j as d, k as t, r as A } from "./AimdWysiwygEditor.vue_vue_type_script_setup_true_lang-
|
|
1
|
+
import { _ as a, D as r, i, j as d, k as t, r as A } from "./AimdWysiwygEditor.vue_vue_type_script_setup_true_lang-BYUea59a.js";
|
|
2
2
|
export {
|
|
3
3
|
a as AimdWysiwygEditor,
|
|
4
4
|
r as DEFAULT_AIMD_EDITOR_LOCALE,
|
package/package.json
CHANGED
package/src/vue/AimdEditor.vue
CHANGED
|
@@ -107,6 +107,12 @@ const refSuggestions = computed(() => {
|
|
|
107
107
|
return []
|
|
108
108
|
})
|
|
109
109
|
|
|
110
|
+
const existingQuizIds = computed(() => {
|
|
111
|
+
const fields = extractedFields.value
|
|
112
|
+
if (!fields?.quiz) return []
|
|
113
|
+
return fields.quiz.map(q => q.id)
|
|
114
|
+
})
|
|
115
|
+
|
|
110
116
|
function openAimdDialog(type: string) {
|
|
111
117
|
aimdDialogType.value = type
|
|
112
118
|
showAimdDialog.value = true
|
|
@@ -221,6 +227,7 @@ defineExpose({
|
|
|
221
227
|
:messages="resolvedMessages"
|
|
222
228
|
:ref-suggestions="refSuggestions"
|
|
223
229
|
:var-type-plugins="varTypePlugins"
|
|
230
|
+
:existing-quiz-ids="existingQuizIds"
|
|
224
231
|
@update:visible="showAimdDialog = $event"
|
|
225
232
|
@insert="onDialogInsert"
|
|
226
233
|
/>
|
|
@@ -17,6 +17,7 @@ const props = defineProps<{
|
|
|
17
17
|
refSuggestions?: string[]
|
|
18
18
|
varTypePlugins?: AimdVarTypePresetOption[]
|
|
19
19
|
allowedTypes?: string[]
|
|
20
|
+
existingQuizIds?: string[]
|
|
20
21
|
}>()
|
|
21
22
|
|
|
22
23
|
const emit = defineEmits<{
|
|
@@ -42,8 +43,12 @@ function resolveDialogType(type?: string): string {
|
|
|
42
43
|
return localizedFieldTypes.value[0]?.type ?? type ?? 'var'
|
|
43
44
|
}
|
|
44
45
|
|
|
46
|
+
const existingQuizIdsSet = computed(() => {
|
|
47
|
+
return new Set(props.existingQuizIds || [])
|
|
48
|
+
})
|
|
49
|
+
|
|
45
50
|
const dialogType = ref(resolveDialogType(props.initialType))
|
|
46
|
-
const fields = ref<Record<string, string>>(getDefaultAimdFields(dialogType.value, props.messages))
|
|
51
|
+
const fields = ref<Record<string, string>>(getDefaultAimdFields(dialogType.value, props.messages, existingQuizIdsSet.value))
|
|
47
52
|
|
|
48
53
|
interface ChoiceOptionItem {
|
|
49
54
|
key: string
|
|
@@ -77,12 +82,21 @@ function selectVarTypePreset(value: string) {
|
|
|
77
82
|
fields.value.type = value
|
|
78
83
|
}
|
|
79
84
|
|
|
85
|
+
function generateUniqueQuizId(quizType: string, existingIds: Set<string>): string {
|
|
86
|
+
const base = `quiz_${quizType}`
|
|
87
|
+
let suffix = 1
|
|
88
|
+
while (existingIds.has(`${base}_${suffix}`)) {
|
|
89
|
+
suffix += 1
|
|
90
|
+
}
|
|
91
|
+
return `${base}_${suffix}`
|
|
92
|
+
}
|
|
93
|
+
|
|
80
94
|
function parseChoiceOptions(input: string): ChoiceOptionItem[] {
|
|
81
95
|
const parts = input.split(',').map(s => s.trim()).filter(Boolean)
|
|
82
96
|
if (parts.length === 0) {
|
|
83
97
|
return [
|
|
84
|
-
{ key: 'A', text:
|
|
85
|
-
{ key: 'B', text:
|
|
98
|
+
{ key: 'A', text: '' },
|
|
99
|
+
{ key: 'B', text: '' },
|
|
86
100
|
]
|
|
87
101
|
}
|
|
88
102
|
|
|
@@ -104,7 +118,7 @@ function serializeChoiceOptions(items: ChoiceOptionItem[]): string {
|
|
|
104
118
|
.filter(item => item.key && item.text)
|
|
105
119
|
|
|
106
120
|
if (normalized.length === 0) {
|
|
107
|
-
return
|
|
121
|
+
return 'A:, B:'
|
|
108
122
|
}
|
|
109
123
|
|
|
110
124
|
return normalized.map(item => `${item.key}:${item.text}`).join(', ')
|
|
@@ -113,7 +127,7 @@ function serializeChoiceOptions(items: ChoiceOptionItem[]): string {
|
|
|
113
127
|
function parseBlankItems(input: string): BlankItem[] {
|
|
114
128
|
const parts = input.split(',').map(s => s.trim()).filter(Boolean)
|
|
115
129
|
if (parts.length === 0) {
|
|
116
|
-
return [{ key: 'b1', answer: '
|
|
130
|
+
return [{ key: 'b1', answer: '' }]
|
|
117
131
|
}
|
|
118
132
|
|
|
119
133
|
return parts.map((part, index) => {
|
|
@@ -133,7 +147,7 @@ function serializeBlankItems(items: BlankItem[]): string {
|
|
|
133
147
|
.filter(item => item.key)
|
|
134
148
|
|
|
135
149
|
if (normalized.length === 0) {
|
|
136
|
-
return 'b1:
|
|
150
|
+
return 'b1:'
|
|
137
151
|
}
|
|
138
152
|
|
|
139
153
|
return normalized.map(item => `${item.key}:${item.answer}`).join(', ')
|
|
@@ -199,7 +213,7 @@ function nextChoiceKey(): string {
|
|
|
199
213
|
|
|
200
214
|
function addChoiceOption() {
|
|
201
215
|
const key = nextChoiceKey()
|
|
202
|
-
quizChoiceOptions.value.push({ key, text:
|
|
216
|
+
quizChoiceOptions.value.push({ key, text: '' })
|
|
203
217
|
}
|
|
204
218
|
|
|
205
219
|
function removeChoiceOption(index: number) {
|
|
@@ -327,7 +341,7 @@ function validateBeforeInsert(): string | null {
|
|
|
327
341
|
watch(() => props.initialType, (t) => {
|
|
328
342
|
const resolvedType = resolveDialogType(t)
|
|
329
343
|
dialogType.value = resolvedType
|
|
330
|
-
fields.value = getDefaultAimdFields(resolvedType, props.messages)
|
|
344
|
+
fields.value = getDefaultAimdFields(resolvedType, props.messages, existingQuizIdsSet.value)
|
|
331
345
|
hydrateQuizDraftsFromFields()
|
|
332
346
|
formError.value = ''
|
|
333
347
|
})
|
|
@@ -339,14 +353,14 @@ watch(localizedFieldTypes, () => {
|
|
|
339
353
|
}
|
|
340
354
|
|
|
341
355
|
dialogType.value = resolvedType
|
|
342
|
-
fields.value = getDefaultAimdFields(resolvedType, props.messages)
|
|
356
|
+
fields.value = getDefaultAimdFields(resolvedType, props.messages, existingQuizIdsSet.value)
|
|
343
357
|
hydrateQuizDraftsFromFields()
|
|
344
358
|
formError.value = ''
|
|
345
359
|
})
|
|
346
360
|
|
|
347
361
|
watch(() => props.visible, (v) => {
|
|
348
362
|
if (v) {
|
|
349
|
-
fields.value = getDefaultAimdFields(dialogType.value, props.messages)
|
|
363
|
+
fields.value = getDefaultAimdFields(dialogType.value, props.messages, existingQuizIdsSet.value)
|
|
350
364
|
hydrateQuizDraftsFromFields()
|
|
351
365
|
formError.value = ''
|
|
352
366
|
}
|
|
@@ -355,7 +369,7 @@ watch(() => props.visible, (v) => {
|
|
|
355
369
|
function switchType(type: string) {
|
|
356
370
|
const resolvedType = resolveDialogType(type)
|
|
357
371
|
dialogType.value = resolvedType
|
|
358
|
-
fields.value = getDefaultAimdFields(resolvedType, props.messages)
|
|
372
|
+
fields.value = getDefaultAimdFields(resolvedType, props.messages, existingQuizIdsSet.value)
|
|
359
373
|
hydrateQuizDraftsFromFields()
|
|
360
374
|
formError.value = ''
|
|
361
375
|
}
|
|
@@ -388,6 +402,35 @@ const referencedPlaceholder = computed(() => {
|
|
|
388
402
|
watch(() => [dialogType.value, fields.value.quizType], ([type, quizType], [prevType, prevQuizType]) => {
|
|
389
403
|
if (type !== 'quiz') return
|
|
390
404
|
if (type !== prevType || quizType !== prevQuizType) {
|
|
405
|
+
if (quizType !== prevQuizType && prevQuizType) {
|
|
406
|
+
fields.value.id = generateUniqueQuizId(quizType, existingQuizIdsSet.value)
|
|
407
|
+
|
|
408
|
+
if (quizType === 'choice') {
|
|
409
|
+
fields.value.stem = props.messages.defaults.questionStem
|
|
410
|
+
fields.value.mode = 'single'
|
|
411
|
+
fields.value.options = 'A:, B:'
|
|
412
|
+
fields.value.answer = 'A'
|
|
413
|
+
fields.value.blanks = ''
|
|
414
|
+
fields.value.rubric = ''
|
|
415
|
+
}
|
|
416
|
+
else if (quizType === 'blank') {
|
|
417
|
+
fields.value.stem = props.messages.defaults.fillQuestionStem
|
|
418
|
+
fields.value.blanks = 'b1:'
|
|
419
|
+
fields.value.options = ''
|
|
420
|
+
fields.value.answer = ''
|
|
421
|
+
fields.value.mode = ''
|
|
422
|
+
fields.value.rubric = ''
|
|
423
|
+
quizBlankItems.value = [{ key: 'b1', answer: '' }]
|
|
424
|
+
}
|
|
425
|
+
else if (quizType === 'open') {
|
|
426
|
+
fields.value.stem = props.messages.defaults.fillQuestionStem
|
|
427
|
+
fields.value.rubric = ''
|
|
428
|
+
fields.value.options = ''
|
|
429
|
+
fields.value.answer = ''
|
|
430
|
+
fields.value.blanks = ''
|
|
431
|
+
fields.value.mode = ''
|
|
432
|
+
}
|
|
433
|
+
}
|
|
391
434
|
hydrateQuizDraftsFromFields()
|
|
392
435
|
}
|
|
393
436
|
})
|
|
@@ -598,6 +641,8 @@ function close() {
|
|
|
598
641
|
>
|
|
599
642
|
⋮⋮
|
|
600
643
|
</span>
|
|
644
|
+
<input v-model="option.key" :placeholder="props.messages.placeholders.optionKey" class="aimd-field-input" />
|
|
645
|
+
<input v-model="option.text" :placeholder="props.messages.placeholders.optionText" class="aimd-field-input" />
|
|
601
646
|
<label class="aimd-option-answer-toggle">
|
|
602
647
|
<input
|
|
603
648
|
v-if="fields.mode === 'single'"
|
|
@@ -614,10 +659,8 @@ function close() {
|
|
|
614
659
|
:value="option.key.trim()"
|
|
615
660
|
:disabled="!option.key.trim()"
|
|
616
661
|
/>
|
|
617
|
-
<span>{{
|
|
662
|
+
<span>{{ props.messages.dialog.correctAnswer }}</span>
|
|
618
663
|
</label>
|
|
619
|
-
<input v-model="option.key" :placeholder="props.messages.placeholders.optionKey" class="aimd-field-input" />
|
|
620
|
-
<input v-model="option.text" :placeholder="props.messages.placeholders.optionText" class="aimd-field-input" />
|
|
621
664
|
<button
|
|
622
665
|
type="button"
|
|
623
666
|
class="aimd-mini-btn"
|
|
@@ -955,7 +998,7 @@ function close() {
|
|
|
955
998
|
}
|
|
956
999
|
|
|
957
1000
|
.aimd-option-row {
|
|
958
|
-
grid-template-columns: 26px
|
|
1001
|
+
grid-template-columns: 26px 60px 1fr 80px auto;
|
|
959
1002
|
}
|
|
960
1003
|
|
|
961
1004
|
.aimd-option-row-dragover {
|
package/src/vue/locales.ts
CHANGED
|
@@ -104,6 +104,7 @@ export interface AimdEditorMessages {
|
|
|
104
104
|
dragToReorder: string
|
|
105
105
|
answer: string
|
|
106
106
|
correct: string
|
|
107
|
+
correctAnswer: string
|
|
107
108
|
optionsHint: string
|
|
108
109
|
blanks: string
|
|
109
110
|
blanksHint: string
|
|
@@ -318,6 +319,7 @@ const EN_US_MESSAGES: AimdEditorMessages = {
|
|
|
318
319
|
dragToReorder: 'Drag to reorder',
|
|
319
320
|
answer: 'Answer',
|
|
320
321
|
correct: 'Correct',
|
|
322
|
+
correctAnswer: 'Correct Answer',
|
|
321
323
|
optionsHint: 'Use unique keys (A/B/C), then mark answer directly in each row.',
|
|
322
324
|
blanks: 'Blanks',
|
|
323
325
|
blanksHint: 'Use keys like b1, b2 and refer to them in stem as [[b1]], [[b2]].',
|
|
@@ -514,6 +516,7 @@ const ZH_CN_MESSAGES: AimdEditorMessages = {
|
|
|
514
516
|
dragToReorder: '拖拽排序',
|
|
515
517
|
answer: '答案',
|
|
516
518
|
correct: '正确',
|
|
519
|
+
correctAnswer: '正确答案',
|
|
517
520
|
optionsHint: '请使用唯一键(A/B/C),并直接在每一行标记答案。',
|
|
518
521
|
blanks: '填空项',
|
|
519
522
|
blanksHint: '请使用 b1、b2 这样的键,并在题干中写成 [[b1]]、[[b2]]。',
|
package/src/vue/types.ts
CHANGED
|
@@ -261,7 +261,7 @@ function parseQuizOptions(
|
|
|
261
261
|
function parseBlankItems(input: string): Array<{ key: string, answer: string }> {
|
|
262
262
|
const parts = input.split(',').map(s => s.trim()).filter(Boolean)
|
|
263
263
|
if (parts.length === 0) {
|
|
264
|
-
return [{ key: 'b1', answer: '
|
|
264
|
+
return [{ key: 'b1', answer: '' }]
|
|
265
265
|
}
|
|
266
266
|
|
|
267
267
|
return parts.map((part, index) => {
|
|
@@ -288,20 +288,30 @@ function parseOptionalScore(value: string): string | null {
|
|
|
288
288
|
export function getDefaultAimdFields(
|
|
289
289
|
type: string,
|
|
290
290
|
messages?: Pick<AimdEditorMessages, 'defaults'>,
|
|
291
|
+
existingQuizIds?: Set<string>,
|
|
291
292
|
): Record<string, string> {
|
|
292
293
|
switch (type) {
|
|
293
294
|
case 'var': return { name: '', type: 'str', default: '', title: '' }
|
|
294
295
|
case 'var_table': return { name: '', subvars: '' }
|
|
295
|
-
case 'quiz':
|
|
296
|
-
|
|
297
|
-
quizType
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
296
|
+
case 'quiz': {
|
|
297
|
+
const quizType = 'choice'
|
|
298
|
+
const base = `quiz_${quizType}`
|
|
299
|
+
let suffix = 1
|
|
300
|
+
while (existingQuizIds?.has(`${base}_${suffix}`)) {
|
|
301
|
+
suffix += 1
|
|
302
|
+
}
|
|
303
|
+
const id = `${base}_${suffix}`
|
|
304
|
+
return {
|
|
305
|
+
id,
|
|
306
|
+
quizType,
|
|
307
|
+
mode: 'single',
|
|
308
|
+
stem: messages?.defaults.questionStem || DEFAULT_EDITOR_MESSAGES.defaults.questionStem,
|
|
309
|
+
options: `A:${getDefaultOptionText('A', messages)}, B:${getDefaultOptionText('B', messages)}`,
|
|
310
|
+
answer: 'A',
|
|
311
|
+
blanks: 'b1:',
|
|
312
|
+
rubric: '',
|
|
313
|
+
score: '',
|
|
314
|
+
}
|
|
305
315
|
}
|
|
306
316
|
case 'step': return { name: '', level: '1' }
|
|
307
317
|
case 'check': return { name: '' }
|
|
@@ -139,9 +139,15 @@ export function useEditorContent(options: UseEditorContentOptions) {
|
|
|
139
139
|
function insertTextIntoActiveEditor(text: string) {
|
|
140
140
|
if (editorMode.value === 'source' && monacoEditor.value) {
|
|
141
141
|
const selection = monacoEditor.value.getSelection()
|
|
142
|
+
const model = monacoEditor.value.getModel()
|
|
143
|
+
const position = monacoEditor.value.getPosition()
|
|
144
|
+
const lineContent = model.getLineContent(position.lineNumber)
|
|
145
|
+
const beforeCursor = lineContent.substring(0, position.column - 1)
|
|
146
|
+
const needsLeadingNewline = beforeCursor.trim() !== '' && !text.startsWith('\n')
|
|
147
|
+
const finalText = needsLeadingNewline ? '\n' + text : text
|
|
142
148
|
monacoEditor.value.executeEdits('toolbar', [{
|
|
143
149
|
range: selection,
|
|
144
|
-
text,
|
|
150
|
+
text: finalText,
|
|
145
151
|
forceMoveMarkers: true,
|
|
146
152
|
}])
|
|
147
153
|
monacoEditor.value.focus()
|