djm-ui 0.67.3 → 0.72.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/CHANGELOG.md +108 -0
- package/README.md +38 -2
- package/dist/djm-ui.cjs +1051 -356
- package/dist/djm-ui.cjs.map +4 -4
- package/dist/djm-ui.css +752 -17
- package/dist/djm-ui.esm.js +1127 -432
- package/dist/djm-ui.esm.js.map +4 -4
- package/dist/djm-ui.esm.min.js +375 -229
- package/dist/djm-ui.min.cjs +375 -229
- package/dist/djm-ui.min.css +2 -2
- package/dist/djm-ui.umd.js +967 -272
- package/dist/djm-ui.umd.min.js +375 -229
- package/dist/mcp/manifest.json +12195 -0
- package/dist/mcp/server.js +90 -0
- package/package.json +12 -4
- package/src/components/icon/index.js +13 -1
- package/src/components/input/index.js +17 -6
- package/src/components/rich-editor/index.js +724 -61
- package/src/index.js +1 -1
- package/src/locale/en-US.js +33 -1
- package/src/locale/zh-CN.js +33 -1
- package/src/styles/base.css +2 -3
- package/src/styles/components/button.css +2 -1
- package/src/styles/components/console.css +5 -0
- package/src/styles/components/content.css +517 -0
- package/src/styles/components/form.css +5 -0
- package/src/styles/components/layout.css +327 -1
- package/src/styles/components/media-picker.css +3 -3
- package/src/styles/components/menu.css +2 -1
- package/src/styles/components/org-picker.css +1 -1
- package/src/styles/components/responsive.css +86 -0
- package/src/styles/components/rich-editor.css +206 -7
- package/src/styles/components/skin.css +54 -0
- package/src/styles/components/template.css +5 -0
- package/src/styles/index.css +1 -0
- package/src/styles/theme-dark.css +2 -0
- package/src/styles/tokens.css +8 -0
- package/src/theme/index.js +40 -0
- package/src/utils/sanitize-html.js +44 -6
- package/types/index.d.ts +8 -0
package/dist/djm-ui.esm.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! DJM UI v0.
|
|
1
|
+
/*! DJM UI v0.72.0 · MIT · 2026-10-26 */
|
|
2
2
|
var __defProp = Object.defineProperty;
|
|
3
3
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
4
|
var __esm = (fn, res, err) => function __init() {
|
|
@@ -969,7 +969,19 @@ var PATHS = {
|
|
|
969
969
|
activity: "M22 12h-4l-3 9L9 3l-3 9H2",
|
|
970
970
|
database: "M12 8c4.42 0 8-1.34 8-3s-3.58-3-8-3-8 1.34-8 3 3.58 3 8 3zM4 5v14c0 1.66 3.58 3 8 3s8-1.34 8-3V5M4 12c0 1.66 3.58 3 8 3s8-1.34 8-3",
|
|
971
971
|
sun: "M12 17a5 5 0 1 0 0-10 5 5 0 0 0 0 10zM12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42",
|
|
972
|
-
moon: "M21 12.8A9 9 0 1 1 11.2 3a7 7 0 0 0 9.8 9.8z"
|
|
972
|
+
moon: "M21 12.8A9 9 0 1 1 11.2 3a7 7 0 0 0 9.8 9.8z",
|
|
973
|
+
undo: "M3 10h11a5 5 0 1 1 0 10H8M3 10l4-4M3 10l4 4",
|
|
974
|
+
redo: "M21 10H10a5 5 0 1 0 0 10h6M21 10l-4-4M21 10l-4 4",
|
|
975
|
+
"align-left": "M4 6h16M4 12h10M4 18h13",
|
|
976
|
+
"align-center": "M4 6h16M7 12h10M6 18h12",
|
|
977
|
+
"align-right": "M4 6h16M10 12h10M7 18h13",
|
|
978
|
+
"align-justify": "M4 6h16M4 12h16M4 18h16",
|
|
979
|
+
list: "M9 6h11M9 12h11M9 18h11M4.5 6h.01M4.5 12h.01M4.5 18h.01",
|
|
980
|
+
"list-ordered": "M10 6h10M10 12h10M10 18h10M4 6h1v4M4 12h2M4 16h2v2H4",
|
|
981
|
+
outdent: "M4 6h16M10 12h10M10 18h10M8 9l-3 3 3 3",
|
|
982
|
+
indent: "M4 6h16M10 12h10M10 18h10M5 9l3 3-3 3",
|
|
983
|
+
unlink: "M10 13a5 5 0 0 0 7.5.5M14 11a5 5 0 0 0-7.5-.5M2 2l20 20",
|
|
984
|
+
images: "M8 3h12v12M4 7h12v12H4zM7 15l3-3 3 3"
|
|
973
985
|
};
|
|
974
986
|
var icon_default = {
|
|
975
987
|
name: "DjmIcon",
|
|
@@ -1099,19 +1111,29 @@ var input_default = {
|
|
|
1099
1111
|
this.focus();
|
|
1100
1112
|
},
|
|
1101
1113
|
focus() {
|
|
1114
|
+
this.clearStaleValue();
|
|
1102
1115
|
if (this.$refs.input) this.$refs.input.focus();
|
|
1103
1116
|
},
|
|
1117
|
+
onFocus(event) {
|
|
1118
|
+
this.clearStaleValue();
|
|
1119
|
+
this.$emit("focus", event);
|
|
1120
|
+
},
|
|
1104
1121
|
blur() {
|
|
1105
1122
|
if (this.$refs.input) this.$refs.input.blur();
|
|
1106
1123
|
}
|
|
1107
1124
|
},
|
|
1108
1125
|
mounted() {
|
|
1109
|
-
this.
|
|
1110
|
-
|
|
1126
|
+
this.staleTimers = [null, 200, 600, 1200, 2400].map((delay) => {
|
|
1127
|
+
if (delay === null) {
|
|
1128
|
+
this.clearStaleValue();
|
|
1129
|
+
return null;
|
|
1130
|
+
}
|
|
1131
|
+
return setTimeout(() => this.clearStaleValue(), delay);
|
|
1132
|
+
});
|
|
1111
1133
|
window.addEventListener("pageshow", this.clearStaleValue);
|
|
1112
1134
|
},
|
|
1113
1135
|
beforeUnmount() {
|
|
1114
|
-
|
|
1136
|
+
this.staleTimers.forEach((timer) => clearTimeout(timer));
|
|
1115
1137
|
window.removeEventListener("pageshow", this.clearStaleValue);
|
|
1116
1138
|
},
|
|
1117
1139
|
template: `
|
|
@@ -1131,7 +1153,7 @@ var input_default = {
|
|
|
1131
1153
|
@input="onInput"
|
|
1132
1154
|
@change="$emit('change', $event)"
|
|
1133
1155
|
@keyup.enter="$emit('enter', $event)"
|
|
1134
|
-
@focus="
|
|
1156
|
+
@focus="onFocus"
|
|
1135
1157
|
@blur="$emit('blur', $event)"
|
|
1136
1158
|
/>
|
|
1137
1159
|
<button
|
|
@@ -1161,7 +1183,7 @@ var input_default = {
|
|
|
1161
1183
|
@input="onInput"
|
|
1162
1184
|
@change="$emit('change', $event)"
|
|
1163
1185
|
@keyup.enter="$emit('enter', $event)"
|
|
1164
|
-
@focus="
|
|
1186
|
+
@focus="onFocus"
|
|
1165
1187
|
@blur="$emit('blur', $event)"
|
|
1166
1188
|
/>
|
|
1167
1189
|
`
|
|
@@ -1286,7 +1308,6 @@ var zh_CN_default = {
|
|
|
1286
1308
|
"richEditor.italic": "\u659C\u4F53",
|
|
1287
1309
|
"richEditor.underline": "\u4E0B\u5212\u7EBF",
|
|
1288
1310
|
"richEditor.strike": "\u5220\u9664\u7EBF",
|
|
1289
|
-
"richEditor.heading": "\u4E8C\u7EA7\u6807\u9898",
|
|
1290
1311
|
"richEditor.paragraph": "\u6B63\u6587",
|
|
1291
1312
|
"richEditor.bulletList": "\u65E0\u5E8F\u5217\u8868",
|
|
1292
1313
|
"richEditor.numberList": "\u6709\u5E8F\u5217\u8868",
|
|
@@ -1297,6 +1318,39 @@ var zh_CN_default = {
|
|
|
1297
1318
|
"richEditor.redo": "\u91CD\u505A",
|
|
1298
1319
|
"richEditor.source": "\u6E90\u7801",
|
|
1299
1320
|
"richEditor.visual": "\u53EF\u89C6\u5316",
|
|
1321
|
+
"richEditor.toolbar": "\u7F16\u8F91\u5DE5\u5177\u680F",
|
|
1322
|
+
"richEditor.block": "\u6BB5\u843D\u683C\u5F0F",
|
|
1323
|
+
"richEditor.heading1": "\u6807\u9898 1",
|
|
1324
|
+
"richEditor.heading2": "\u6807\u9898 2",
|
|
1325
|
+
"richEditor.heading3": "\u6807\u9898 3",
|
|
1326
|
+
"richEditor.quote": "\u5F15\u7528",
|
|
1327
|
+
"richEditor.codeBlock": "\u4EE3\u7801\u5757",
|
|
1328
|
+
"richEditor.fontSize": "\u5B57\u53F7",
|
|
1329
|
+
"richEditor.defaultSize": "\u9ED8\u8BA4",
|
|
1330
|
+
"richEditor.inlineCode": "\u884C\u5185\u4EE3\u7801",
|
|
1331
|
+
"richEditor.textColor": "\u6587\u5B57\u989C\u8272",
|
|
1332
|
+
"richEditor.bgColor": "\u80CC\u666F\u8272",
|
|
1333
|
+
"richEditor.alignLeft": "\u5DE6\u5BF9\u9F50",
|
|
1334
|
+
"richEditor.alignCenter": "\u5C45\u4E2D",
|
|
1335
|
+
"richEditor.alignRight": "\u53F3\u5BF9\u9F50",
|
|
1336
|
+
"richEditor.alignJustify": "\u4E24\u7AEF\u5BF9\u9F50",
|
|
1337
|
+
"richEditor.outdent": "\u51CF\u5C11\u7F29\u8FDB",
|
|
1338
|
+
"richEditor.indent": "\u589E\u52A0\u7F29\u8FDB",
|
|
1339
|
+
"richEditor.unlink": "\u53D6\u6D88\u94FE\u63A5",
|
|
1340
|
+
"richEditor.image": "\u63D2\u5165\u56FE\u7247",
|
|
1341
|
+
"richEditor.singleImage": "\u63D2\u5165\u5355\u56FE",
|
|
1342
|
+
"richEditor.multiImage": "\u63D2\u5165\u591A\u56FE",
|
|
1343
|
+
"richEditor.mediaLibrary": "\u4ECE\u7D20\u6750\u5E93\u9009\u62E9",
|
|
1344
|
+
"richEditor.hr": "\u5206\u5272\u7EBF",
|
|
1345
|
+
"richEditor.fullscreen": "\u5168\u5C4F",
|
|
1346
|
+
"richEditor.exitFullscreen": "\u9000\u51FA\u5168\u5C4F",
|
|
1347
|
+
"richEditor.wordCount": "\u5171 {count} \u5B57",
|
|
1348
|
+
"richEditor.uploading": "\u6B63\u5728\u4E0A\u4F20 {count} \u5F20\u56FE\u7247\u2026",
|
|
1349
|
+
"richEditor.uploadFailed": "\u56FE\u7247\u4E0A\u4F20\u5931\u8D25",
|
|
1350
|
+
"richEditor.imageTypeError": "\u53EA\u80FD\u4E0A\u4F20\u56FE\u7247\u6587\u4EF6",
|
|
1351
|
+
"richEditor.imageSizeError": "\u56FE\u7247\u4E0D\u80FD\u8D85\u8FC7 {size}MB",
|
|
1352
|
+
"richEditor.imageUrlInvalid": "\u56FE\u7247\u5730\u5740\u4E0D\u5408\u6CD5\uFF0C\u5DF2\u62D2\u7EDD\u63D2\u5165",
|
|
1353
|
+
"richEditor.linkInvalid": "\u94FE\u63A5\u53EA\u652F\u6301 http(s)\u3001mailto\u3001tel \u6216\u7AD9\u5185\u76F8\u5BF9\u5730\u5740",
|
|
1300
1354
|
"approval.start": "\u53D1\u8D77",
|
|
1301
1355
|
"approval.cc": "\u6284\u9001",
|
|
1302
1356
|
"approval.approved": "\u5DF2\u901A\u8FC7",
|
|
@@ -1505,7 +1559,6 @@ var en_US_default = {
|
|
|
1505
1559
|
"richEditor.italic": "Italic",
|
|
1506
1560
|
"richEditor.underline": "Underline",
|
|
1507
1561
|
"richEditor.strike": "Strikethrough",
|
|
1508
|
-
"richEditor.heading": "Heading 2",
|
|
1509
1562
|
"richEditor.paragraph": "Paragraph",
|
|
1510
1563
|
"richEditor.bulletList": "Bullet list",
|
|
1511
1564
|
"richEditor.numberList": "Numbered list",
|
|
@@ -1516,6 +1569,39 @@ var en_US_default = {
|
|
|
1516
1569
|
"richEditor.redo": "Redo",
|
|
1517
1570
|
"richEditor.source": "Source",
|
|
1518
1571
|
"richEditor.visual": "Visual",
|
|
1572
|
+
"richEditor.toolbar": "Formatting toolbar",
|
|
1573
|
+
"richEditor.block": "Paragraph style",
|
|
1574
|
+
"richEditor.heading1": "Heading 1",
|
|
1575
|
+
"richEditor.heading2": "Heading 2",
|
|
1576
|
+
"richEditor.heading3": "Heading 3",
|
|
1577
|
+
"richEditor.quote": "Quote",
|
|
1578
|
+
"richEditor.codeBlock": "Code block",
|
|
1579
|
+
"richEditor.fontSize": "Font size",
|
|
1580
|
+
"richEditor.defaultSize": "Default",
|
|
1581
|
+
"richEditor.inlineCode": "Inline code",
|
|
1582
|
+
"richEditor.textColor": "Text color",
|
|
1583
|
+
"richEditor.bgColor": "Background color",
|
|
1584
|
+
"richEditor.alignLeft": "Align left",
|
|
1585
|
+
"richEditor.alignCenter": "Align center",
|
|
1586
|
+
"richEditor.alignRight": "Align right",
|
|
1587
|
+
"richEditor.alignJustify": "Justify",
|
|
1588
|
+
"richEditor.outdent": "Decrease indent",
|
|
1589
|
+
"richEditor.indent": "Increase indent",
|
|
1590
|
+
"richEditor.unlink": "Remove link",
|
|
1591
|
+
"richEditor.image": "Insert image",
|
|
1592
|
+
"richEditor.singleImage": "Insert single image",
|
|
1593
|
+
"richEditor.multiImage": "Insert multiple images",
|
|
1594
|
+
"richEditor.mediaLibrary": "Choose from media library",
|
|
1595
|
+
"richEditor.hr": "Divider",
|
|
1596
|
+
"richEditor.fullscreen": "Fullscreen",
|
|
1597
|
+
"richEditor.exitFullscreen": "Exit fullscreen",
|
|
1598
|
+
"richEditor.wordCount": "{count} characters",
|
|
1599
|
+
"richEditor.uploading": "Uploading {count} image(s)\u2026",
|
|
1600
|
+
"richEditor.uploadFailed": "Image upload failed",
|
|
1601
|
+
"richEditor.imageTypeError": "Only image files are allowed",
|
|
1602
|
+
"richEditor.imageSizeError": "Image must be smaller than {size}MB",
|
|
1603
|
+
"richEditor.imageUrlInvalid": "Invalid image URL, insertion rejected",
|
|
1604
|
+
"richEditor.linkInvalid": "Only http(s), mailto, tel or relative URLs are allowed",
|
|
1519
1605
|
"approval.start": "Started",
|
|
1520
1606
|
"approval.cc": "CC",
|
|
1521
1607
|
"approval.approved": "Approved",
|
|
@@ -9334,7 +9420,199 @@ var tree_select_default = {
|
|
|
9334
9420
|
};
|
|
9335
9421
|
|
|
9336
9422
|
// src/components/rich-editor/index.js
|
|
9337
|
-
import { ref as
|
|
9423
|
+
import { ref as ref28, computed as computed17, watch as watch20, onMounted as onMounted15, onBeforeUnmount as onBeforeUnmount23 } from "vue";
|
|
9424
|
+
|
|
9425
|
+
// src/components/media-picker/index.js
|
|
9426
|
+
import { computed as computed16, ref as ref27, watch as watch19 } from "vue";
|
|
9427
|
+
var media_picker_default = {
|
|
9428
|
+
name: "DjmMediaPicker",
|
|
9429
|
+
components: { DjmModal: modal_default, DjmPagination: pagination_default, DjmIcon: icon_default },
|
|
9430
|
+
props: {
|
|
9431
|
+
modelValue: { type: [Array, String, Number], default: "" },
|
|
9432
|
+
items: { type: Array, default: () => [] },
|
|
9433
|
+
multiple: { type: Boolean, default: false },
|
|
9434
|
+
// 最多选几个,0 表示不限
|
|
9435
|
+
limit: { type: Number, default: 0 },
|
|
9436
|
+
// image 只显示图片,file 只显示非图片,空串不过滤
|
|
9437
|
+
accept: { type: String, default: "" },
|
|
9438
|
+
title: { type: String, default: "" },
|
|
9439
|
+
triggerText: { type: String, default: "" },
|
|
9440
|
+
pageSize: { type: Number, default: 12 },
|
|
9441
|
+
disabled: { type: Boolean, default: false }
|
|
9442
|
+
},
|
|
9443
|
+
emits: ["update:modelValue", "change"],
|
|
9444
|
+
setup(props, { emit }) {
|
|
9445
|
+
const open = ref27(false);
|
|
9446
|
+
const keyword = ref27("");
|
|
9447
|
+
const page = ref27(1);
|
|
9448
|
+
const temp = ref27([]);
|
|
9449
|
+
const selectedIds = computed16(() => {
|
|
9450
|
+
if (props.multiple) return Array.isArray(props.modelValue) ? props.modelValue : [];
|
|
9451
|
+
if (props.modelValue === "" || props.modelValue === null || props.modelValue === void 0) return [];
|
|
9452
|
+
return [props.modelValue];
|
|
9453
|
+
});
|
|
9454
|
+
function isImage(item) {
|
|
9455
|
+
if (item.type) return item.type === "image";
|
|
9456
|
+
return /\.(png|jpe?g|gif|webp|svg|avif)$/i.test(item.url || "");
|
|
9457
|
+
}
|
|
9458
|
+
const filtered = computed16(() => {
|
|
9459
|
+
const key = keyword.value.trim().toLowerCase();
|
|
9460
|
+
return props.items.filter((item) => {
|
|
9461
|
+
if (props.accept === "image" && !isImage(item)) return false;
|
|
9462
|
+
if (props.accept === "file" && isImage(item)) return false;
|
|
9463
|
+
if (key && !String(item.name || "").toLowerCase().includes(key)) return false;
|
|
9464
|
+
return true;
|
|
9465
|
+
});
|
|
9466
|
+
});
|
|
9467
|
+
const paged = computed16(() => {
|
|
9468
|
+
const start = (page.value - 1) * props.pageSize;
|
|
9469
|
+
return filtered.value.slice(start, start + props.pageSize);
|
|
9470
|
+
});
|
|
9471
|
+
watch19(keyword, () => {
|
|
9472
|
+
page.value = 1;
|
|
9473
|
+
});
|
|
9474
|
+
watch19(
|
|
9475
|
+
() => filtered.value.length,
|
|
9476
|
+
() => {
|
|
9477
|
+
const max = Math.max(1, Math.ceil(filtered.value.length / props.pageSize));
|
|
9478
|
+
if (page.value > max) page.value = max;
|
|
9479
|
+
}
|
|
9480
|
+
);
|
|
9481
|
+
function isChecked(id) {
|
|
9482
|
+
return temp.value.includes(id);
|
|
9483
|
+
}
|
|
9484
|
+
function atLimit() {
|
|
9485
|
+
return props.limit > 0 && temp.value.length >= props.limit;
|
|
9486
|
+
}
|
|
9487
|
+
function toggle(item) {
|
|
9488
|
+
if (props.multiple) {
|
|
9489
|
+
if (isChecked(item.id)) {
|
|
9490
|
+
temp.value = temp.value.filter((id) => id !== item.id);
|
|
9491
|
+
return;
|
|
9492
|
+
}
|
|
9493
|
+
if (atLimit()) return;
|
|
9494
|
+
temp.value = [...temp.value, item.id];
|
|
9495
|
+
return;
|
|
9496
|
+
}
|
|
9497
|
+
temp.value = [item.id];
|
|
9498
|
+
}
|
|
9499
|
+
function openPanel() {
|
|
9500
|
+
if (props.disabled) return;
|
|
9501
|
+
temp.value = [...selectedIds.value];
|
|
9502
|
+
keyword.value = "";
|
|
9503
|
+
page.value = 1;
|
|
9504
|
+
open.value = true;
|
|
9505
|
+
}
|
|
9506
|
+
function commit() {
|
|
9507
|
+
const next = props.multiple ? [...temp.value] : temp.value[0] !== void 0 ? temp.value[0] : "";
|
|
9508
|
+
emit("update:modelValue", next);
|
|
9509
|
+
emit("change", next);
|
|
9510
|
+
open.value = false;
|
|
9511
|
+
}
|
|
9512
|
+
function cancel() {
|
|
9513
|
+
temp.value = [...selectedIds.value];
|
|
9514
|
+
open.value = false;
|
|
9515
|
+
}
|
|
9516
|
+
return {
|
|
9517
|
+
open,
|
|
9518
|
+
keyword,
|
|
9519
|
+
page,
|
|
9520
|
+
temp,
|
|
9521
|
+
selectedIds,
|
|
9522
|
+
filtered,
|
|
9523
|
+
paged,
|
|
9524
|
+
isImage,
|
|
9525
|
+
isChecked,
|
|
9526
|
+
atLimit,
|
|
9527
|
+
toggle,
|
|
9528
|
+
openPanel,
|
|
9529
|
+
commit,
|
|
9530
|
+
cancel,
|
|
9531
|
+
t
|
|
9532
|
+
};
|
|
9533
|
+
},
|
|
9534
|
+
template: `
|
|
9535
|
+
<span class="djm-media-picker">
|
|
9536
|
+
<slot name="trigger" :open="openPanel" :count="selectedIds.length">
|
|
9537
|
+
<button
|
|
9538
|
+
class="djm-btn"
|
|
9539
|
+
type="button"
|
|
9540
|
+
:disabled="disabled"
|
|
9541
|
+
@click="openPanel"
|
|
9542
|
+
>{{ triggerText || t('mediaPicker.select') }}<span v-if="selectedIds.length" class="djm-media-picker-count">{{ selectedIds.length }}</span></button>
|
|
9543
|
+
</slot>
|
|
9544
|
+
|
|
9545
|
+
<DjmModal
|
|
9546
|
+
:model-value="open"
|
|
9547
|
+
:title="title || t('mediaPicker.title')"
|
|
9548
|
+
width="760px"
|
|
9549
|
+
@update:model-value="cancel"
|
|
9550
|
+
>
|
|
9551
|
+
<div class="djm-media-toolbar">
|
|
9552
|
+
<label class="djm-media-search">
|
|
9553
|
+
<DjmIcon name="search" :size="13" />
|
|
9554
|
+
<input
|
|
9555
|
+
v-model="keyword"
|
|
9556
|
+
class="djm-media-search-input"
|
|
9557
|
+
type="text"
|
|
9558
|
+
:placeholder="t('mediaPicker.search')"
|
|
9559
|
+
:aria-label="t('mediaPicker.search')"
|
|
9560
|
+
/>
|
|
9561
|
+
</label>
|
|
9562
|
+
<span class="djm-media-toolbar-slot">
|
|
9563
|
+
<slot name="toolbar"></slot>
|
|
9564
|
+
</span>
|
|
9565
|
+
</div>
|
|
9566
|
+
|
|
9567
|
+
<div class="djm-media-grid" role="listbox" :aria-multiselectable="multiple ? 'true' : 'false'">
|
|
9568
|
+
<div
|
|
9569
|
+
v-for="item in paged"
|
|
9570
|
+
:key="item.id"
|
|
9571
|
+
class="djm-media-item"
|
|
9572
|
+
:class="{
|
|
9573
|
+
'djm-is-checked': isChecked(item.id),
|
|
9574
|
+
'djm-is-disabled': multiple && atLimit() && !isChecked(item.id)
|
|
9575
|
+
}"
|
|
9576
|
+
role="option"
|
|
9577
|
+
tabindex="0"
|
|
9578
|
+
:aria-selected="String(isChecked(item.id))"
|
|
9579
|
+
@click="toggle(item)"
|
|
9580
|
+
@keydown.enter.prevent="toggle(item)"
|
|
9581
|
+
@keydown.space.prevent="toggle(item)"
|
|
9582
|
+
>
|
|
9583
|
+
<div class="djm-media-thumb">
|
|
9584
|
+
<img v-if="isImage(item)" :src="item.url" :alt="item.name" loading="lazy" />
|
|
9585
|
+
<DjmIcon v-else name="folder" :size="26" />
|
|
9586
|
+
<span v-if="isChecked(item.id)" class="djm-media-check">
|
|
9587
|
+
<DjmIcon name="check" :size="11" />
|
|
9588
|
+
</span>
|
|
9589
|
+
</div>
|
|
9590
|
+
<div class="djm-media-name" :title="item.name">{{ item.name }}</div>
|
|
9591
|
+
</div>
|
|
9592
|
+
<div v-if="!paged.length" class="djm-media-empty">{{ t('mediaPicker.empty') }}</div>
|
|
9593
|
+
</div>
|
|
9594
|
+
|
|
9595
|
+
<div class="djm-media-foot">
|
|
9596
|
+
<span class="djm-media-total">
|
|
9597
|
+
{{ t('mediaPicker.total', { total: filtered.length }) }}
|
|
9598
|
+
<em v-if="multiple && limit > 0">{{ t('mediaPicker.limit', { limit }) }}</em>
|
|
9599
|
+
</span>
|
|
9600
|
+
<DjmPagination
|
|
9601
|
+
v-if="filtered.length > pageSize"
|
|
9602
|
+
v-model:page="page"
|
|
9603
|
+
:page-size="pageSize"
|
|
9604
|
+
:total="filtered.length"
|
|
9605
|
+
/>
|
|
9606
|
+
</div>
|
|
9607
|
+
|
|
9608
|
+
<template #footer>
|
|
9609
|
+
<button class="djm-btn" type="button" @click="cancel">{{ t('common.cancel') }}</button>
|
|
9610
|
+
<button class="djm-btn djm-btn-primary" type="button" @click="commit">{{ t('common.confirm') }}</button>
|
|
9611
|
+
</template>
|
|
9612
|
+
</DjmModal>
|
|
9613
|
+
</span>
|
|
9614
|
+
`
|
|
9615
|
+
};
|
|
9338
9616
|
|
|
9339
9617
|
// src/utils/sanitize-html.js
|
|
9340
9618
|
var TAGS = /* @__PURE__ */ new Set([
|
|
@@ -9374,7 +9652,18 @@ var TAGS = /* @__PURE__ */ new Set([
|
|
|
9374
9652
|
"th",
|
|
9375
9653
|
"td"
|
|
9376
9654
|
]);
|
|
9377
|
-
var GLOBAL_ATTRS = /* @__PURE__ */ new Set(["class", "title"]);
|
|
9655
|
+
var GLOBAL_ATTRS = /* @__PURE__ */ new Set(["class", "title", "style"]);
|
|
9656
|
+
var STYLE_PROPS = /* @__PURE__ */ new Set([
|
|
9657
|
+
"color",
|
|
9658
|
+
"background-color",
|
|
9659
|
+
"font-size",
|
|
9660
|
+
"font-weight",
|
|
9661
|
+
"font-style",
|
|
9662
|
+
"text-decoration",
|
|
9663
|
+
"text-align",
|
|
9664
|
+
"text-indent",
|
|
9665
|
+
"line-height"
|
|
9666
|
+
]);
|
|
9378
9667
|
var TAG_ATTRS = {
|
|
9379
9668
|
a: /* @__PURE__ */ new Set(["href", "target", "rel"]),
|
|
9380
9669
|
img: /* @__PURE__ */ new Set(["src", "alt", "width", "height"]),
|
|
@@ -9382,11 +9671,29 @@ var TAG_ATTRS = {
|
|
|
9382
9671
|
th: /* @__PURE__ */ new Set(["colspan", "rowspan", "scope"]),
|
|
9383
9672
|
td: /* @__PURE__ */ new Set(["colspan", "rowspan"])
|
|
9384
9673
|
};
|
|
9674
|
+
function cleanStyle(value) {
|
|
9675
|
+
return String(value || "").split(";").map((item) => {
|
|
9676
|
+
const index = item.indexOf(":");
|
|
9677
|
+
if (index === -1) return "";
|
|
9678
|
+
const name = item.slice(0, index).trim().toLowerCase();
|
|
9679
|
+
const val = item.slice(index + 1).trim();
|
|
9680
|
+
if (!STYLE_PROPS.has(name)) return "";
|
|
9681
|
+
if (/url\s*\(|expression\s*\(|javascript:/i.test(val)) return "";
|
|
9682
|
+
return name + ": " + val;
|
|
9683
|
+
}).filter(Boolean).join("; ");
|
|
9684
|
+
}
|
|
9685
|
+
var SAFE_SCHEMES = /* @__PURE__ */ new Set(["http", "https", "mailto", "tel"]);
|
|
9385
9686
|
function safeUrl(value, tag) {
|
|
9386
|
-
const url = String(value || "").replace(/[\u0000-\u0020]+/g, "")
|
|
9387
|
-
|
|
9388
|
-
if (
|
|
9389
|
-
|
|
9687
|
+
const url = String(value || "").replace(/[\u0000-\u0020]+/g, "");
|
|
9688
|
+
const scheme = url.match(/^([a-z][a-z0-9+.-]*):/i);
|
|
9689
|
+
if (!scheme) return true;
|
|
9690
|
+
const name = scheme[1].toLowerCase();
|
|
9691
|
+
if (SAFE_SCHEMES.has(name)) return true;
|
|
9692
|
+
if (tag === "img") {
|
|
9693
|
+
if (name === "blob") return true;
|
|
9694
|
+
if (name === "data" && /^data:image\//i.test(url)) return true;
|
|
9695
|
+
}
|
|
9696
|
+
return false;
|
|
9390
9697
|
}
|
|
9391
9698
|
function cleanNode(node) {
|
|
9392
9699
|
const children = [...node.childNodes];
|
|
@@ -9409,6 +9716,12 @@ function cleanNode(node) {
|
|
|
9409
9716
|
child.removeAttribute(attr.name);
|
|
9410
9717
|
return;
|
|
9411
9718
|
}
|
|
9719
|
+
if (name === "style") {
|
|
9720
|
+
const style = cleanStyle(attr.value);
|
|
9721
|
+
if (style) child.setAttribute("style", style);
|
|
9722
|
+
else child.removeAttribute("style");
|
|
9723
|
+
return;
|
|
9724
|
+
}
|
|
9412
9725
|
if ((name === "href" || name === "src") && !safeUrl(attr.value, tag)) {
|
|
9413
9726
|
child.removeAttribute(attr.name);
|
|
9414
9727
|
}
|
|
@@ -9429,79 +9742,475 @@ function sanitizeHtml(html) {
|
|
|
9429
9742
|
}
|
|
9430
9743
|
|
|
9431
9744
|
// src/components/rich-editor/index.js
|
|
9745
|
+
var BLOCKS = [
|
|
9746
|
+
{ value: "p", label: "paragraph" },
|
|
9747
|
+
{ value: "h1", label: "heading1" },
|
|
9748
|
+
{ value: "h2", label: "heading2" },
|
|
9749
|
+
{ value: "h3", label: "heading3" },
|
|
9750
|
+
{ value: "blockquote", label: "quote" },
|
|
9751
|
+
{ value: "pre", label: "codeBlock" }
|
|
9752
|
+
];
|
|
9753
|
+
var SIZES = [
|
|
9754
|
+
{ value: "", label: "defaultSize" },
|
|
9755
|
+
{ value: "12px", label: "12px" },
|
|
9756
|
+
{ value: "14px", label: "14px" },
|
|
9757
|
+
{ value: "16px", label: "16px" },
|
|
9758
|
+
{ value: "18px", label: "18px" },
|
|
9759
|
+
{ value: "24px", label: "24px" }
|
|
9760
|
+
];
|
|
9761
|
+
var COLORS = ["#1f2d3d", "#5a6b7d", "#2b86d9", "#2fa36b", "#d97706", "#dc2626", "#7c3aed", "#ffffff"];
|
|
9762
|
+
var TOOLBAR_PRESETS = {
|
|
9763
|
+
simple: ["history", "inline", "list", "insert"],
|
|
9764
|
+
basic: ["history", "format", "inline", "align", "list", "insert", "view"],
|
|
9765
|
+
full: ["history", "format", "inline", "color", "align", "list", "insert", "view"]
|
|
9766
|
+
};
|
|
9767
|
+
function isSafeImageUrl(url) {
|
|
9768
|
+
const value = String(url || "").replace(/[\u0000-\u0020]+/g, "");
|
|
9769
|
+
if (!value) return false;
|
|
9770
|
+
const scheme = value.match(/^([a-z][a-z0-9+.-]*):/i);
|
|
9771
|
+
if (!scheme) return true;
|
|
9772
|
+
const name = scheme[1].toLowerCase();
|
|
9773
|
+
if (name === "http" || name === "https" || name === "blob") return true;
|
|
9774
|
+
return name === "data" && /^data:image\//i.test(value);
|
|
9775
|
+
}
|
|
9776
|
+
function isSafeLink(url) {
|
|
9777
|
+
const value = String(url || "").trim();
|
|
9778
|
+
if (!value) return false;
|
|
9779
|
+
const scheme = value.replace(/[\u0000-\u0020]+/g, "").match(/^([a-z][a-z0-9+.-]*):/i);
|
|
9780
|
+
if (!scheme) return true;
|
|
9781
|
+
return ["http", "https", "mailto", "tel"].indexOf(scheme[1].toLowerCase()) > -1;
|
|
9782
|
+
}
|
|
9432
9783
|
var rich_editor_default = {
|
|
9433
9784
|
name: "DjmRichEditor",
|
|
9434
|
-
components: { Icon: icon_default },
|
|
9785
|
+
components: { Icon: icon_default, MediaPicker: media_picker_default },
|
|
9435
9786
|
props: {
|
|
9436
9787
|
modelValue: { type: String, default: "" },
|
|
9437
9788
|
placeholder: { type: String, default: "" },
|
|
9438
9789
|
minHeight: { type: Number, default: 200 },
|
|
9439
|
-
//
|
|
9440
|
-
sanitize: { type: Boolean, default:
|
|
9441
|
-
disabled: { type: Boolean, default: false }
|
|
9790
|
+
// 默认开启:对外输出的 HTML 走白名单清洗,内容里不会带出脚本
|
|
9791
|
+
sanitize: { type: Boolean, default: true },
|
|
9792
|
+
disabled: { type: Boolean, default: false },
|
|
9793
|
+
// 工具条:simple / basic / full,或传分组数组(history / format / inline / color / align / list / insert / view)
|
|
9794
|
+
toolbar: { type: [String, Array], default: "full" },
|
|
9795
|
+
// 自定义上传:接收 File,返回图片地址(或 { url }),不传则转成 dataURL 本地预览
|
|
9796
|
+
uploadImage: { type: Function, default: null },
|
|
9797
|
+
// 已上传图片,提供后工具栏出现「从素材库选择」:字符串或 { url, name }
|
|
9798
|
+
media: { type: Array, default: () => [] },
|
|
9799
|
+
accept: { type: String, default: "image/*" },
|
|
9800
|
+
// 单张图片大小上限(MB)
|
|
9801
|
+
maxImageSize: { type: Number, default: 5 },
|
|
9802
|
+
// 是否允许一次选多张
|
|
9803
|
+
multiple: { type: Boolean, default: true },
|
|
9804
|
+
showCount: { type: Boolean, default: true }
|
|
9442
9805
|
},
|
|
9443
|
-
emits: ["update:modelValue"],
|
|
9806
|
+
emits: ["update:modelValue", "upload-error"],
|
|
9444
9807
|
setup(props, { emit }) {
|
|
9445
|
-
const editor =
|
|
9446
|
-
const
|
|
9447
|
-
const
|
|
9448
|
-
const
|
|
9808
|
+
const editor = ref28(null);
|
|
9809
|
+
const fileInput = ref28(null);
|
|
9810
|
+
const sourceMode = ref28(false);
|
|
9811
|
+
const source = ref28(props.modelValue);
|
|
9812
|
+
const fullscreen = ref28(false);
|
|
9813
|
+
const panel = ref28("");
|
|
9814
|
+
const uploadCount = ref28(0);
|
|
9815
|
+
const textColor = ref28(COLORS[0]);
|
|
9816
|
+
const bgColor = ref28("#fdf3c4");
|
|
9817
|
+
const fontSize = ref28("");
|
|
9818
|
+
const count2 = ref28(0);
|
|
9819
|
+
const formats = ref28({
|
|
9820
|
+
bold: false,
|
|
9821
|
+
italic: false,
|
|
9822
|
+
underline: false,
|
|
9823
|
+
strike: false,
|
|
9824
|
+
code: false,
|
|
9825
|
+
block: "p",
|
|
9826
|
+
align: "",
|
|
9827
|
+
list: ""
|
|
9828
|
+
});
|
|
9829
|
+
let savedRange = null;
|
|
9830
|
+
const ready = computed17(() => !props.disabled && !sourceMode.value);
|
|
9831
|
+
const toolbarGroups = computed17(() => {
|
|
9832
|
+
const list = Array.isArray(props.toolbar) ? props.toolbar : TOOLBAR_PRESETS[props.toolbar] || TOOLBAR_PRESETS.full;
|
|
9833
|
+
return new Set(list);
|
|
9834
|
+
});
|
|
9835
|
+
function has(group) {
|
|
9836
|
+
return toolbarGroups.value.has(group);
|
|
9837
|
+
}
|
|
9838
|
+
const mediaLibrary = computed17(
|
|
9839
|
+
() => (props.media || []).map((item, index) => {
|
|
9840
|
+
if (typeof item === "string") {
|
|
9841
|
+
return { id: "media-" + index, url: item, name: "", type: "image" };
|
|
9842
|
+
}
|
|
9843
|
+
return {
|
|
9844
|
+
id: item && item.id !== void 0 ? String(item.id) : "media-" + index,
|
|
9845
|
+
url: item && (item.url || item.src) || "",
|
|
9846
|
+
name: item && (item.name || item.alt) || "",
|
|
9847
|
+
type: "image"
|
|
9848
|
+
};
|
|
9849
|
+
}).filter((item) => !!item.url)
|
|
9850
|
+
);
|
|
9449
9851
|
function clean(html) {
|
|
9450
9852
|
return props.sanitize ? sanitizeHtml(html) : html;
|
|
9451
9853
|
}
|
|
9854
|
+
function plainText(html) {
|
|
9855
|
+
return String(html || "").replace(/<[^>]*>/g, "").replace(/ /g, " ").replace(/&[a-z]+;/gi, " ");
|
|
9856
|
+
}
|
|
9452
9857
|
function syncFromDom() {
|
|
9453
9858
|
if (!editor.value) return;
|
|
9454
|
-
|
|
9859
|
+
const html = clean(editor.value.innerHTML);
|
|
9860
|
+
count2.value = plainText(html).trim().length;
|
|
9861
|
+
emit("update:modelValue", html);
|
|
9455
9862
|
}
|
|
9456
|
-
function
|
|
9457
|
-
const
|
|
9458
|
-
|
|
9459
|
-
|
|
9460
|
-
|
|
9461
|
-
|
|
9863
|
+
function currentRange() {
|
|
9864
|
+
const selection = window.getSelection();
|
|
9865
|
+
if (!selection || !selection.rangeCount || !editor.value) return null;
|
|
9866
|
+
const range = selection.getRangeAt(0);
|
|
9867
|
+
return editor.value.contains(range.commonAncestorContainer) ? range : null;
|
|
9868
|
+
}
|
|
9869
|
+
function rememberRange() {
|
|
9870
|
+
const range = currentRange();
|
|
9871
|
+
savedRange = range ? range.cloneRange() : null;
|
|
9872
|
+
}
|
|
9873
|
+
function focusAt(range) {
|
|
9874
|
+
if (!editor.value) return;
|
|
9875
|
+
editor.value.focus();
|
|
9876
|
+
const selection = window.getSelection();
|
|
9877
|
+
selection.removeAllRanges();
|
|
9878
|
+
if (range) {
|
|
9879
|
+
selection.addRange(range);
|
|
9880
|
+
return;
|
|
9881
|
+
}
|
|
9882
|
+
const end = document.createRange();
|
|
9883
|
+
end.selectNodeContents(editor.value);
|
|
9884
|
+
end.collapse(false);
|
|
9885
|
+
selection.addRange(end);
|
|
9886
|
+
}
|
|
9887
|
+
function insertNodeAt(range, node) {
|
|
9888
|
+
if (!editor.value) return;
|
|
9889
|
+
focusAt(range);
|
|
9890
|
+
const selection = window.getSelection();
|
|
9891
|
+
if (selection.rangeCount) selection.getRangeAt(0).insertNode(node);
|
|
9892
|
+
else editor.value.appendChild(node);
|
|
9462
9893
|
syncFromDom();
|
|
9894
|
+
syncFormats();
|
|
9895
|
+
}
|
|
9896
|
+
function ensureRange() {
|
|
9897
|
+
const range = currentRange();
|
|
9898
|
+
if (range) return range;
|
|
9899
|
+
if (!savedRange) return null;
|
|
9900
|
+
focusAt(savedRange);
|
|
9901
|
+
return currentRange();
|
|
9463
9902
|
}
|
|
9464
9903
|
function exec(command, value = null) {
|
|
9465
|
-
if (
|
|
9904
|
+
if (!ready.value) return;
|
|
9905
|
+
if (typeof document.execCommand !== "function") return;
|
|
9906
|
+
ensureRange();
|
|
9907
|
+
document.execCommand("styleWithCSS", false, true);
|
|
9466
9908
|
document.execCommand(command, false, value);
|
|
9467
9909
|
if (editor.value) editor.value.focus();
|
|
9468
9910
|
syncFromDom();
|
|
9469
9911
|
syncFormats();
|
|
9470
9912
|
}
|
|
9471
|
-
function
|
|
9472
|
-
|
|
9913
|
+
function setBlock(value) {
|
|
9914
|
+
panel.value = "";
|
|
9915
|
+
exec("formatBlock", "<" + value + ">");
|
|
9916
|
+
}
|
|
9917
|
+
function setFontSize(size) {
|
|
9918
|
+
panel.value = "";
|
|
9919
|
+
if (!ready.value || !editor.value) return;
|
|
9920
|
+
fontSize.value = size;
|
|
9921
|
+
const range = ensureRange();
|
|
9922
|
+
if (!range || range.collapsed) return;
|
|
9923
|
+
if (!size) {
|
|
9924
|
+
const walker = document.createTreeWalker(editor.value, NodeFilter.SHOW_ELEMENT);
|
|
9925
|
+
const targets = [];
|
|
9926
|
+
while (walker.nextNode()) {
|
|
9927
|
+
const el = walker.currentNode;
|
|
9928
|
+
if (el.style && el.style.fontSize && range.intersectsNode(el)) targets.push(el);
|
|
9929
|
+
}
|
|
9930
|
+
targets.forEach((el) => {
|
|
9931
|
+
el.style.fontSize = "";
|
|
9932
|
+
});
|
|
9933
|
+
syncFromDom();
|
|
9934
|
+
return;
|
|
9935
|
+
}
|
|
9936
|
+
const span = document.createElement("span");
|
|
9937
|
+
span.style.fontSize = size;
|
|
9938
|
+
span.appendChild(range.extractContents());
|
|
9939
|
+
range.insertNode(span);
|
|
9940
|
+
const selection = window.getSelection();
|
|
9941
|
+
const after = document.createRange();
|
|
9942
|
+
after.setStartAfter(span);
|
|
9943
|
+
after.collapse(true);
|
|
9944
|
+
selection.removeAllRanges();
|
|
9945
|
+
selection.addRange(after);
|
|
9946
|
+
syncFromDom();
|
|
9947
|
+
syncFormats();
|
|
9948
|
+
}
|
|
9949
|
+
function applyColor(kind, color) {
|
|
9950
|
+
panel.value = "";
|
|
9951
|
+
if (kind === "text") textColor.value = color;
|
|
9952
|
+
else bgColor.value = color;
|
|
9953
|
+
if (!ready.value) return;
|
|
9954
|
+
if (typeof document.execCommand !== "function") return;
|
|
9955
|
+
document.execCommand("styleWithCSS", false, true);
|
|
9956
|
+
const command = kind === "text" ? "foreColor" : "hiliteColor";
|
|
9957
|
+
if (!document.execCommand(command, false, color) && kind === "bg") {
|
|
9958
|
+
document.execCommand("backColor", false, color);
|
|
9959
|
+
}
|
|
9960
|
+
if (editor.value) editor.value.focus();
|
|
9961
|
+
syncFromDom();
|
|
9962
|
+
syncFormats();
|
|
9963
|
+
}
|
|
9964
|
+
function togglePanel(name) {
|
|
9965
|
+
if (!ready.value) return;
|
|
9966
|
+
panel.value = panel.value === name ? "" : name;
|
|
9967
|
+
}
|
|
9968
|
+
function toggleInlineCode() {
|
|
9969
|
+
if (!ready.value || !editor.value) return;
|
|
9970
|
+
const range = currentRange();
|
|
9971
|
+
if (!range) return;
|
|
9972
|
+
const anchor = range.commonAncestorContainer;
|
|
9973
|
+
const node = anchor.nodeType === 1 ? anchor : anchor.parentElement;
|
|
9974
|
+
const code = node && node.closest ? node.closest("code") : null;
|
|
9975
|
+
if (code && editor.value.contains(code)) {
|
|
9976
|
+
const parent = code.parentNode;
|
|
9977
|
+
while (code.firstChild) parent.insertBefore(code.firstChild, code);
|
|
9978
|
+
parent.removeChild(code);
|
|
9979
|
+
syncFromDom();
|
|
9980
|
+
return;
|
|
9981
|
+
}
|
|
9982
|
+
if (range.collapsed) return;
|
|
9983
|
+
const wrapper = document.createElement("code");
|
|
9984
|
+
wrapper.appendChild(range.extractContents());
|
|
9985
|
+
range.insertNode(wrapper);
|
|
9986
|
+
const selection = window.getSelection();
|
|
9987
|
+
const after = document.createRange();
|
|
9988
|
+
after.setStartAfter(wrapper);
|
|
9989
|
+
after.collapse(true);
|
|
9990
|
+
selection.removeAllRanges();
|
|
9991
|
+
selection.addRange(after);
|
|
9992
|
+
syncFromDom();
|
|
9993
|
+
syncFormats();
|
|
9473
9994
|
}
|
|
9474
9995
|
function addLink() {
|
|
9996
|
+
if (!ready.value) return;
|
|
9475
9997
|
const url = window.prompt(t("richEditor.linkPrompt"), "https://");
|
|
9476
|
-
if (url)
|
|
9998
|
+
if (!url) return;
|
|
9999
|
+
if (!isSafeLink(url)) {
|
|
10000
|
+
window.alert(t("richEditor.linkInvalid"));
|
|
10001
|
+
return;
|
|
10002
|
+
}
|
|
10003
|
+
const range = currentRange();
|
|
10004
|
+
if (range && range.collapsed) {
|
|
10005
|
+
const link = document.createElement("a");
|
|
10006
|
+
link.href = url;
|
|
10007
|
+
link.target = "_blank";
|
|
10008
|
+
link.rel = "noopener noreferrer";
|
|
10009
|
+
link.textContent = url;
|
|
10010
|
+
insertNodeAt(range, link);
|
|
10011
|
+
return;
|
|
10012
|
+
}
|
|
10013
|
+
exec("createLink", url);
|
|
10014
|
+
if (editor.value) {
|
|
10015
|
+
editor.value.querySelectorAll("a[href]").forEach((link) => {
|
|
10016
|
+
if (!link.getAttribute("target")) link.setAttribute("target", "_blank");
|
|
10017
|
+
link.setAttribute("rel", "noopener noreferrer");
|
|
10018
|
+
});
|
|
10019
|
+
}
|
|
10020
|
+
syncFromDom();
|
|
9477
10021
|
}
|
|
9478
|
-
function
|
|
9479
|
-
|
|
9480
|
-
|
|
9481
|
-
|
|
9482
|
-
|
|
9483
|
-
|
|
9484
|
-
|
|
9485
|
-
strike: document.queryCommandState("strikeThrough")
|
|
9486
|
-
};
|
|
10022
|
+
function readAsDataUrl(file) {
|
|
10023
|
+
return new Promise((resolve, reject) => {
|
|
10024
|
+
const reader = new FileReader();
|
|
10025
|
+
reader.onload = () => resolve(reader.result);
|
|
10026
|
+
reader.onerror = () => reject(reader.error || new Error("read failed"));
|
|
10027
|
+
reader.readAsDataURL(file);
|
|
10028
|
+
});
|
|
9487
10029
|
}
|
|
9488
|
-
function
|
|
10030
|
+
async function uploadOne(file) {
|
|
10031
|
+
if (props.uploadImage) {
|
|
10032
|
+
const result = await props.uploadImage(file);
|
|
10033
|
+
const url = typeof result === "string" ? result : result && result.url;
|
|
10034
|
+
if (!url) throw new Error(t("richEditor.imageUrlInvalid"));
|
|
10035
|
+
if (!isSafeImageUrl(url)) throw new Error(t("richEditor.imageUrlInvalid"));
|
|
10036
|
+
return String(url).trim();
|
|
10037
|
+
}
|
|
10038
|
+
return readAsDataUrl(file);
|
|
10039
|
+
}
|
|
10040
|
+
function isImage(file) {
|
|
10041
|
+
return file && /^image\//.test(file.type);
|
|
10042
|
+
}
|
|
10043
|
+
function pickImage(allowMultiple) {
|
|
10044
|
+
if (!ready.value || !fileInput.value) return;
|
|
10045
|
+
rememberRange();
|
|
10046
|
+
fileInput.value.multiple = !!allowMultiple && props.multiple;
|
|
10047
|
+
fileInput.value.click();
|
|
10048
|
+
}
|
|
10049
|
+
function insertMedia(ids) {
|
|
10050
|
+
if (!ready.value) return;
|
|
10051
|
+
const picked = (Array.isArray(ids) ? ids : [ids]).map((id) => mediaLibrary.value.find((item) => item.id === String(id))).filter(Boolean);
|
|
10052
|
+
const safe = picked.filter((item) => {
|
|
10053
|
+
if (isSafeImageUrl(item.url)) return true;
|
|
10054
|
+
emit("upload-error", { file: null, message: t("richEditor.imageUrlInvalid") });
|
|
10055
|
+
return false;
|
|
10056
|
+
});
|
|
10057
|
+
if (!safe.length) return;
|
|
10058
|
+
focusAt(savedRange);
|
|
10059
|
+
const fragment = document.createDocumentFragment();
|
|
10060
|
+
safe.forEach((item) => {
|
|
10061
|
+
const img = document.createElement("img");
|
|
10062
|
+
img.src = item.url;
|
|
10063
|
+
img.alt = item.name || "image";
|
|
10064
|
+
img.className = "djm-rich-editor-img";
|
|
10065
|
+
fragment.appendChild(img);
|
|
10066
|
+
});
|
|
10067
|
+
const selection = window.getSelection();
|
|
10068
|
+
if (selection.rangeCount) selection.getRangeAt(0).insertNode(fragment);
|
|
10069
|
+
else editor.value.appendChild(fragment);
|
|
10070
|
+
syncFromDom();
|
|
10071
|
+
syncFormats();
|
|
10072
|
+
}
|
|
10073
|
+
function insertImages(files) {
|
|
10074
|
+
if (!files.length || !editor.value) return;
|
|
10075
|
+
uploadCount.value = files.length;
|
|
10076
|
+
const holder = document.createElement("span");
|
|
10077
|
+
holder.className = "djm-rich-editor-uploading";
|
|
10078
|
+
holder.textContent = t("richEditor.uploading", { count: files.length });
|
|
10079
|
+
const anchor = savedRange && editor.value.contains(savedRange.commonAncestorContainer) ? savedRange : null;
|
|
10080
|
+
focusAt(anchor);
|
|
10081
|
+
const selection = window.getSelection();
|
|
10082
|
+
if (selection.rangeCount) selection.getRangeAt(0).insertNode(holder);
|
|
10083
|
+
else editor.value.appendChild(holder);
|
|
10084
|
+
Promise.all(files.map(async (file) => {
|
|
10085
|
+
if (!isImage(file)) return { file, error: t("richEditor.imageTypeError") };
|
|
10086
|
+
if (props.maxImageSize > 0 && file.size > props.maxImageSize * 1024 * 1024) {
|
|
10087
|
+
return { file, error: t("richEditor.imageSizeError", { size: props.maxImageSize }) };
|
|
10088
|
+
}
|
|
10089
|
+
try {
|
|
10090
|
+
return { file, url: await uploadOne(file) };
|
|
10091
|
+
} catch (error) {
|
|
10092
|
+
return { file, error: error && error.message || t("richEditor.uploadFailed") };
|
|
10093
|
+
}
|
|
10094
|
+
})).then((results) => {
|
|
10095
|
+
uploadCount.value = 0;
|
|
10096
|
+
const done = results.filter((item) => item.url);
|
|
10097
|
+
const failed = results.filter((item) => item.error);
|
|
10098
|
+
const alive = editor.value && editor.value.contains(holder);
|
|
10099
|
+
if (done.length && editor.value) {
|
|
10100
|
+
done.forEach((item) => {
|
|
10101
|
+
const img = document.createElement("img");
|
|
10102
|
+
img.src = item.url;
|
|
10103
|
+
img.alt = item.file.name || "image";
|
|
10104
|
+
img.className = "djm-rich-editor-img";
|
|
10105
|
+
if (alive) holder.parentNode.insertBefore(img, holder);
|
|
10106
|
+
else editor.value.appendChild(img);
|
|
10107
|
+
});
|
|
10108
|
+
}
|
|
10109
|
+
if (alive) holder.remove();
|
|
10110
|
+
failed.forEach((item) => emit("upload-error", { file: item.file, message: item.error }));
|
|
10111
|
+
syncFromDom();
|
|
10112
|
+
});
|
|
10113
|
+
}
|
|
10114
|
+
function onFilesChange(event) {
|
|
10115
|
+
const files = Array.from(event.target.files || []);
|
|
10116
|
+
event.target.value = "";
|
|
10117
|
+
insertImages(files);
|
|
10118
|
+
}
|
|
10119
|
+
function onPaste(event) {
|
|
10120
|
+
const data = event.clipboardData;
|
|
10121
|
+
if (!data) return;
|
|
10122
|
+
const images = Array.from(data.files || []).filter(isImage);
|
|
10123
|
+
if (images.length) {
|
|
10124
|
+
event.preventDefault();
|
|
10125
|
+
insertImages(images);
|
|
10126
|
+
return;
|
|
10127
|
+
}
|
|
10128
|
+
const html = data.getData("text/html");
|
|
10129
|
+
if (!html) return;
|
|
10130
|
+
event.preventDefault();
|
|
10131
|
+
document.execCommand("insertHTML", false, sanitizeHtml(html));
|
|
10132
|
+
syncFromDom();
|
|
10133
|
+
}
|
|
10134
|
+
function onDragOver(event) {
|
|
10135
|
+
if (!ready.value) return;
|
|
10136
|
+
if (event.dataTransfer && Array.from(event.dataTransfer.types || []).includes("Files")) {
|
|
10137
|
+
event.preventDefault();
|
|
10138
|
+
}
|
|
10139
|
+
}
|
|
10140
|
+
function onDrop(event) {
|
|
10141
|
+
if (!ready.value) return;
|
|
10142
|
+
const files = Array.from(event.dataTransfer && event.dataTransfer.files || []).filter(isImage);
|
|
10143
|
+
if (!files.length) return;
|
|
10144
|
+
event.preventDefault();
|
|
10145
|
+
rememberRange();
|
|
10146
|
+
insertImages(files);
|
|
10147
|
+
}
|
|
10148
|
+
function closestTag(node, tag) {
|
|
10149
|
+
const el = node && (node.nodeType === 1 ? node : node.parentElement);
|
|
10150
|
+
return el && el.closest ? el.closest(tag) : null;
|
|
10151
|
+
}
|
|
10152
|
+
function detectBlock() {
|
|
10153
|
+
const selection = window.getSelection();
|
|
10154
|
+
if (!selection || !selection.anchorNode) return "p";
|
|
10155
|
+
let node = selection.anchorNode;
|
|
10156
|
+
if (node.nodeType !== 1) node = node.parentElement;
|
|
10157
|
+
while (node && node !== editor.value) {
|
|
10158
|
+
const tag = node.tagName.toLowerCase();
|
|
10159
|
+
if (["p", "h1", "h2", "h3", "blockquote", "pre"].includes(tag)) return tag;
|
|
10160
|
+
node = node.parentElement;
|
|
10161
|
+
}
|
|
10162
|
+
return "p";
|
|
10163
|
+
}
|
|
10164
|
+
function syncFormats() {
|
|
10165
|
+
if (props.disabled || sourceMode.value || !editor.value) return;
|
|
10166
|
+
if (!editor.value.contains(document.activeElement)) return;
|
|
10167
|
+
const selection = window.getSelection();
|
|
10168
|
+
formats.value = {
|
|
10169
|
+
bold: document.queryCommandState("bold"),
|
|
10170
|
+
italic: document.queryCommandState("italic"),
|
|
10171
|
+
underline: document.queryCommandState("underline"),
|
|
10172
|
+
strike: document.queryCommandState("strikeThrough"),
|
|
10173
|
+
code: !!closestTag(selection.anchorNode, "code"),
|
|
10174
|
+
block: detectBlock(),
|
|
10175
|
+
align: document.queryCommandState("justifyCenter") ? "center" : document.queryCommandState("justifyRight") ? "right" : document.queryCommandState("justifyFull") ? "justify" : "left",
|
|
10176
|
+
list: document.queryCommandState("insertOrderedList") ? "ol" : document.queryCommandState("insertUnorderedList") ? "ul" : ""
|
|
10177
|
+
};
|
|
10178
|
+
}
|
|
10179
|
+
function onSourceInput() {
|
|
10180
|
+
count2.value = plainText(source.value).trim().length;
|
|
9489
10181
|
emit("update:modelValue", clean(source.value));
|
|
9490
10182
|
}
|
|
9491
10183
|
function toggleSource() {
|
|
9492
10184
|
if (props.disabled) return;
|
|
10185
|
+
panel.value = "";
|
|
9493
10186
|
if (sourceMode.value) {
|
|
9494
10187
|
emit("update:modelValue", clean(source.value));
|
|
9495
10188
|
sourceMode.value = false;
|
|
9496
10189
|
requestAnimationFrame(() => {
|
|
9497
10190
|
if (editor.value) editor.value.innerHTML = clean(source.value);
|
|
10191
|
+
syncFromDom();
|
|
9498
10192
|
});
|
|
9499
10193
|
} else {
|
|
9500
10194
|
source.value = editor.value ? editor.value.innerHTML : props.modelValue;
|
|
9501
10195
|
sourceMode.value = true;
|
|
9502
10196
|
}
|
|
9503
10197
|
}
|
|
9504
|
-
|
|
10198
|
+
function toggleFullscreen() {
|
|
10199
|
+
if (props.disabled) return;
|
|
10200
|
+
fullscreen.value = !fullscreen.value;
|
|
10201
|
+
panel.value = "";
|
|
10202
|
+
}
|
|
10203
|
+
function onDocumentClick(event) {
|
|
10204
|
+
if (!panel.value) return;
|
|
10205
|
+
if (!(event.target.closest && event.target.closest(".djm-rich-editor-color"))) panel.value = "";
|
|
10206
|
+
}
|
|
10207
|
+
function onKeydown(event) {
|
|
10208
|
+
if (event.key === "Escape" && fullscreen.value) {
|
|
10209
|
+
fullscreen.value = false;
|
|
10210
|
+
panel.value = "";
|
|
10211
|
+
}
|
|
10212
|
+
}
|
|
10213
|
+
watch20(
|
|
9505
10214
|
() => props.modelValue,
|
|
9506
10215
|
(value) => {
|
|
9507
10216
|
if (sourceMode.value) {
|
|
@@ -9510,40 +10219,117 @@ var rich_editor_default = {
|
|
|
9510
10219
|
}
|
|
9511
10220
|
const next = clean(value);
|
|
9512
10221
|
if (editor.value && editor.value.innerHTML !== next) editor.value.innerHTML = next;
|
|
10222
|
+
count2.value = plainText(next).trim().length;
|
|
9513
10223
|
}
|
|
9514
10224
|
);
|
|
9515
10225
|
onMounted15(() => {
|
|
9516
10226
|
if (editor.value) editor.value.innerHTML = clean(props.modelValue);
|
|
10227
|
+
count2.value = plainText(props.modelValue).trim().length;
|
|
9517
10228
|
document.addEventListener("selectionchange", syncFormats);
|
|
10229
|
+
document.addEventListener("click", onDocumentClick);
|
|
10230
|
+
document.addEventListener("keydown", onKeydown);
|
|
10231
|
+
});
|
|
10232
|
+
onBeforeUnmount23(() => {
|
|
10233
|
+
document.removeEventListener("selectionchange", syncFormats);
|
|
10234
|
+
document.removeEventListener("click", onDocumentClick);
|
|
10235
|
+
document.removeEventListener("keydown", onKeydown);
|
|
9518
10236
|
});
|
|
9519
|
-
onBeforeUnmount23(() => document.removeEventListener("selectionchange", syncFormats));
|
|
9520
10237
|
return {
|
|
9521
10238
|
editor,
|
|
10239
|
+
fileInput,
|
|
9522
10240
|
sourceMode,
|
|
9523
10241
|
source,
|
|
10242
|
+
fullscreen,
|
|
10243
|
+
panel,
|
|
10244
|
+
uploadCount,
|
|
10245
|
+
textColor,
|
|
10246
|
+
bgColor,
|
|
10247
|
+
fontSize,
|
|
10248
|
+
count: count2,
|
|
9524
10249
|
formats,
|
|
10250
|
+
blocks: BLOCKS,
|
|
10251
|
+
sizes: SIZES,
|
|
10252
|
+
colors: COLORS,
|
|
10253
|
+
mediaLibrary,
|
|
10254
|
+
has,
|
|
9525
10255
|
exec,
|
|
9526
|
-
|
|
10256
|
+
setBlock,
|
|
10257
|
+
setFontSize,
|
|
10258
|
+
applyColor,
|
|
10259
|
+
togglePanel,
|
|
10260
|
+
toggleInlineCode,
|
|
9527
10261
|
addLink,
|
|
9528
|
-
|
|
10262
|
+
pickImage,
|
|
10263
|
+
insertMedia,
|
|
10264
|
+
onFilesChange,
|
|
9529
10265
|
onPaste,
|
|
10266
|
+
onDragOver,
|
|
10267
|
+
onDrop,
|
|
10268
|
+
rememberRange,
|
|
10269
|
+
onSourceInput,
|
|
9530
10270
|
toggleSource,
|
|
10271
|
+
toggleFullscreen,
|
|
9531
10272
|
syncFromDom,
|
|
9532
10273
|
syncFormats,
|
|
9533
10274
|
t
|
|
9534
10275
|
};
|
|
9535
10276
|
},
|
|
9536
10277
|
template: `
|
|
9537
|
-
<div
|
|
9538
|
-
|
|
9539
|
-
|
|
10278
|
+
<div
|
|
10279
|
+
class="djm-rich-editor"
|
|
10280
|
+
:class="{ 'djm-is-disabled': disabled, 'djm-is-fullscreen': fullscreen }"
|
|
10281
|
+
>
|
|
10282
|
+
<div class="djm-rich-editor-toolbar" role="toolbar" :aria-label="t('richEditor.toolbar')" @mousedown="rememberRange">
|
|
10283
|
+
<div class="djm-rich-editor-group" v-if="has('history')">
|
|
10284
|
+
<button
|
|
10285
|
+
class="djm-rich-editor-btn"
|
|
10286
|
+
type="button"
|
|
10287
|
+
:title="t('richEditor.undo')"
|
|
10288
|
+
:aria-label="t('richEditor.undo')"
|
|
10289
|
+
:disabled="disabled || sourceMode"
|
|
10290
|
+
@mousedown.prevent
|
|
10291
|
+
@click="exec('undo')"
|
|
10292
|
+
><Icon name="undo" :size="13" /></button>
|
|
10293
|
+
<button
|
|
10294
|
+
class="djm-rich-editor-btn"
|
|
10295
|
+
type="button"
|
|
10296
|
+
:title="t('richEditor.redo')"
|
|
10297
|
+
:aria-label="t('richEditor.redo')"
|
|
10298
|
+
:disabled="disabled || sourceMode"
|
|
10299
|
+
@mousedown.prevent
|
|
10300
|
+
@click="exec('redo')"
|
|
10301
|
+
><Icon name="redo" :size="13" /></button>
|
|
10302
|
+
</div>
|
|
10303
|
+
|
|
10304
|
+
<div class="djm-rich-editor-group" v-if="has('format')">
|
|
10305
|
+
<select
|
|
10306
|
+
class="djm-rich-editor-select"
|
|
10307
|
+
:value="formats.block"
|
|
10308
|
+
:aria-label="t('richEditor.block')"
|
|
10309
|
+
:disabled="disabled || sourceMode"
|
|
10310
|
+
@change="setBlock($event.target.value)"
|
|
10311
|
+
>
|
|
10312
|
+
<option v-for="item in blocks" :key="item.value" :value="item.value">{{ t('richEditor.' + item.label) }}</option>
|
|
10313
|
+
</select>
|
|
10314
|
+
<select
|
|
10315
|
+
class="djm-rich-editor-select djm-rich-editor-select-size"
|
|
10316
|
+
:value="fontSize"
|
|
10317
|
+
:aria-label="t('richEditor.fontSize')"
|
|
10318
|
+
:disabled="disabled || sourceMode"
|
|
10319
|
+
@change="setFontSize($event.target.value)"
|
|
10320
|
+
>
|
|
10321
|
+
<option v-for="item in sizes" :key="item.value" :value="item.value">{{ t('richEditor.' + item.label) }}</option>
|
|
10322
|
+
</select>
|
|
10323
|
+
</div>
|
|
10324
|
+
|
|
10325
|
+
<div class="djm-rich-editor-group" v-if="has('inline')">
|
|
9540
10326
|
<button
|
|
9541
10327
|
class="djm-rich-editor-btn djm-rich-editor-btn-bold"
|
|
9542
10328
|
type="button"
|
|
9543
10329
|
:title="t('richEditor.bold')"
|
|
9544
10330
|
:aria-label="t('richEditor.bold')"
|
|
9545
10331
|
:aria-pressed="String(formats.bold)"
|
|
9546
|
-
:disabled="disabled"
|
|
10332
|
+
:disabled="disabled || sourceMode"
|
|
9547
10333
|
@mousedown.prevent
|
|
9548
10334
|
@click="exec('bold')"
|
|
9549
10335
|
>B</button>
|
|
@@ -9553,7 +10339,7 @@ var rich_editor_default = {
|
|
|
9553
10339
|
:title="t('richEditor.italic')"
|
|
9554
10340
|
:aria-label="t('richEditor.italic')"
|
|
9555
10341
|
:aria-pressed="String(formats.italic)"
|
|
9556
|
-
:disabled="disabled"
|
|
10342
|
+
:disabled="disabled || sourceMode"
|
|
9557
10343
|
@mousedown.prevent
|
|
9558
10344
|
@click="exec('italic')"
|
|
9559
10345
|
>I</button>
|
|
@@ -9563,7 +10349,7 @@ var rich_editor_default = {
|
|
|
9563
10349
|
:title="t('richEditor.underline')"
|
|
9564
10350
|
:aria-label="t('richEditor.underline')"
|
|
9565
10351
|
:aria-pressed="String(formats.underline)"
|
|
9566
|
-
:disabled="disabled"
|
|
10352
|
+
:disabled="disabled || sourceMode"
|
|
9567
10353
|
@mousedown.prevent
|
|
9568
10354
|
@click="exec('underline')"
|
|
9569
10355
|
>U</button>
|
|
@@ -9573,46 +10359,130 @@ var rich_editor_default = {
|
|
|
9573
10359
|
:title="t('richEditor.strike')"
|
|
9574
10360
|
:aria-label="t('richEditor.strike')"
|
|
9575
10361
|
:aria-pressed="String(formats.strike)"
|
|
9576
|
-
:disabled="disabled"
|
|
10362
|
+
:disabled="disabled || sourceMode"
|
|
9577
10363
|
@mousedown.prevent
|
|
9578
10364
|
@click="exec('strikeThrough')"
|
|
9579
10365
|
>S</button>
|
|
10366
|
+
<button
|
|
10367
|
+
class="djm-rich-editor-btn"
|
|
10368
|
+
type="button"
|
|
10369
|
+
:title="t('richEditor.inlineCode')"
|
|
10370
|
+
:aria-label="t('richEditor.inlineCode')"
|
|
10371
|
+
:aria-pressed="String(formats.code)"
|
|
10372
|
+
:disabled="disabled || sourceMode"
|
|
10373
|
+
@mousedown.prevent
|
|
10374
|
+
@click="toggleInlineCode"
|
|
10375
|
+
><Icon name="code" :size="13" /></button>
|
|
9580
10376
|
</div>
|
|
9581
10377
|
|
|
9582
|
-
<div class="djm-rich-editor-group">
|
|
9583
|
-
<button
|
|
9584
|
-
|
|
9585
|
-
|
|
9586
|
-
|
|
9587
|
-
|
|
9588
|
-
|
|
9589
|
-
|
|
9590
|
-
|
|
9591
|
-
|
|
9592
|
-
|
|
10378
|
+
<div class="djm-rich-editor-group djm-rich-editor-color" v-if="has('color')">
|
|
10379
|
+
<button
|
|
10380
|
+
class="djm-rich-editor-btn"
|
|
10381
|
+
type="button"
|
|
10382
|
+
:title="t('richEditor.textColor')"
|
|
10383
|
+
:aria-label="t('richEditor.textColor')"
|
|
10384
|
+
:aria-expanded="String(panel === 'text')"
|
|
10385
|
+
:disabled="disabled || sourceMode"
|
|
10386
|
+
@mousedown.prevent
|
|
10387
|
+
@click.stop="togglePanel('text')"
|
|
10388
|
+
>
|
|
10389
|
+
<span class="djm-rich-editor-letter" :style="{ borderBottomColor: textColor }">A</span>
|
|
9593
10390
|
</button>
|
|
9594
|
-
<button
|
|
9595
|
-
|
|
10391
|
+
<button
|
|
10392
|
+
class="djm-rich-editor-btn"
|
|
10393
|
+
type="button"
|
|
10394
|
+
:title="t('richEditor.bgColor')"
|
|
10395
|
+
:aria-label="t('richEditor.bgColor')"
|
|
10396
|
+
:aria-expanded="String(panel === 'bg')"
|
|
10397
|
+
:disabled="disabled || sourceMode"
|
|
10398
|
+
@mousedown.prevent
|
|
10399
|
+
@click.stop="togglePanel('bg')"
|
|
10400
|
+
>
|
|
10401
|
+
<span class="djm-rich-editor-letter djm-rich-editor-letter-bg" :style="{ background: bgColor }">A</span>
|
|
9596
10402
|
</button>
|
|
10403
|
+
<div v-if="panel === 'text' || panel === 'bg'" class="djm-rich-editor-panel" role="group" :aria-label="t('richEditor.textColor')">
|
|
10404
|
+
<button
|
|
10405
|
+
v-for="color in colors"
|
|
10406
|
+
:key="color"
|
|
10407
|
+
class="djm-rich-editor-swatch"
|
|
10408
|
+
type="button"
|
|
10409
|
+
:title="color"
|
|
10410
|
+
:aria-label="color"
|
|
10411
|
+
:style="{ background: color }"
|
|
10412
|
+
@mousedown.prevent
|
|
10413
|
+
@click="applyColor(panel, color)"
|
|
10414
|
+
></button>
|
|
10415
|
+
</div>
|
|
9597
10416
|
</div>
|
|
9598
10417
|
|
|
9599
|
-
<div class="djm-rich-editor-group">
|
|
9600
|
-
<button class="djm-rich-editor-btn" type="button" :title="t('richEditor.
|
|
9601
|
-
<button class="djm-rich-editor-btn" type="button" :title="t('richEditor.
|
|
9602
|
-
<button class="djm-rich-editor-btn" type="button" :title="t('richEditor.
|
|
10418
|
+
<div class="djm-rich-editor-group" v-if="has('align')">
|
|
10419
|
+
<button class="djm-rich-editor-btn" type="button" :title="t('richEditor.alignLeft')" :aria-label="t('richEditor.alignLeft')" :aria-pressed="String(formats.align === 'left')" :disabled="disabled || sourceMode" @mousedown.prevent @click="exec('justifyLeft')"><Icon name="align-left" :size="13" /></button>
|
|
10420
|
+
<button class="djm-rich-editor-btn" type="button" :title="t('richEditor.alignCenter')" :aria-label="t('richEditor.alignCenter')" :aria-pressed="String(formats.align === 'center')" :disabled="disabled || sourceMode" @mousedown.prevent @click="exec('justifyCenter')"><Icon name="align-center" :size="13" /></button>
|
|
10421
|
+
<button class="djm-rich-editor-btn" type="button" :title="t('richEditor.alignRight')" :aria-label="t('richEditor.alignRight')" :aria-pressed="String(formats.align === 'right')" :disabled="disabled || sourceMode" @mousedown.prevent @click="exec('justifyRight')"><Icon name="align-right" :size="13" /></button>
|
|
10422
|
+
<button class="djm-rich-editor-btn" type="button" :title="t('richEditor.alignJustify')" :aria-label="t('richEditor.alignJustify')" :aria-pressed="String(formats.align === 'justify')" :disabled="disabled || sourceMode" @mousedown.prevent @click="exec('justifyFull')"><Icon name="align-justify" :size="13" /></button>
|
|
9603
10423
|
</div>
|
|
9604
10424
|
|
|
9605
|
-
<div class="djm-rich-editor-
|
|
9606
|
-
|
|
9607
|
-
class="djm-rich-editor-btn"
|
|
9608
|
-
|
|
9609
|
-
type="button"
|
|
9610
|
-
|
|
9611
|
-
|
|
9612
|
-
|
|
9613
|
-
|
|
9614
|
-
<
|
|
9615
|
-
|
|
10425
|
+
<div class="djm-rich-editor-group" v-if="has('list')">
|
|
10426
|
+
<button class="djm-rich-editor-btn" type="button" :title="t('richEditor.bulletList')" :aria-label="t('richEditor.bulletList')" :aria-pressed="String(formats.list === 'ul')" :disabled="disabled || sourceMode" @mousedown.prevent @click="exec('insertUnorderedList')"><Icon name="list" :size="13" /></button>
|
|
10427
|
+
<button class="djm-rich-editor-btn" type="button" :title="t('richEditor.numberList')" :aria-label="t('richEditor.numberList')" :aria-pressed="String(formats.list === 'ol')" :disabled="disabled || sourceMode" @mousedown.prevent @click="exec('insertOrderedList')"><Icon name="list-ordered" :size="13" /></button>
|
|
10428
|
+
<button class="djm-rich-editor-btn" type="button" :title="t('richEditor.outdent')" :aria-label="t('richEditor.outdent')" :disabled="disabled || sourceMode" @mousedown.prevent @click="exec('outdent')"><Icon name="outdent" :size="13" /></button>
|
|
10429
|
+
<button class="djm-rich-editor-btn" type="button" :title="t('richEditor.indent')" :aria-label="t('richEditor.indent')" :disabled="disabled || sourceMode" @mousedown.prevent @click="exec('indent')"><Icon name="indent" :size="13" /></button>
|
|
10430
|
+
</div>
|
|
10431
|
+
|
|
10432
|
+
<div class="djm-rich-editor-group" v-if="has('insert')">
|
|
10433
|
+
<button class="djm-rich-editor-btn" type="button" :title="t('richEditor.link')" :aria-label="t('richEditor.link')" :disabled="disabled || sourceMode" @mousedown.prevent @click="addLink"><Icon name="link" :size="13" /></button>
|
|
10434
|
+
<button class="djm-rich-editor-btn" type="button" :title="t('richEditor.unlink')" :aria-label="t('richEditor.unlink')" :disabled="disabled || sourceMode" @mousedown.prevent @click="exec('unlink')"><Icon name="unlink" :size="13" /></button>
|
|
10435
|
+
<button class="djm-rich-editor-btn" type="button" :title="t('richEditor.singleImage')" :aria-label="t('richEditor.singleImage')" :disabled="disabled || sourceMode" @mousedown.prevent @click="pickImage(false)"><Icon name="image" :size="13" /></button>
|
|
10436
|
+
<button v-if="multiple" class="djm-rich-editor-btn" type="button" :title="t('richEditor.multiImage')" :aria-label="t('richEditor.multiImage')" :disabled="disabled || sourceMode" @mousedown.prevent @click="pickImage(true)"><Icon name="images" :size="13" /></button>
|
|
10437
|
+
<MediaPicker
|
|
10438
|
+
v-if="mediaLibrary.length"
|
|
10439
|
+
class="djm-rich-editor-picker"
|
|
10440
|
+
multiple
|
|
10441
|
+
accept="image"
|
|
10442
|
+
:items="mediaLibrary"
|
|
10443
|
+
:title="t('richEditor.mediaLibrary')"
|
|
10444
|
+
:disabled="disabled || sourceMode"
|
|
10445
|
+
@change="insertMedia"
|
|
10446
|
+
>
|
|
10447
|
+
<template #trigger="{ open }">
|
|
10448
|
+
<button
|
|
10449
|
+
class="djm-rich-editor-btn"
|
|
10450
|
+
type="button"
|
|
10451
|
+
:title="t('richEditor.mediaLibrary')"
|
|
10452
|
+
:aria-label="t('richEditor.mediaLibrary')"
|
|
10453
|
+
:disabled="disabled || sourceMode"
|
|
10454
|
+
@mousedown.prevent="rememberRange"
|
|
10455
|
+
@click="open"
|
|
10456
|
+
><Icon name="grid" :size="13" /></button>
|
|
10457
|
+
</template>
|
|
10458
|
+
</MediaPicker>
|
|
10459
|
+
<button class="djm-rich-editor-btn" type="button" :title="t('richEditor.hr')" :aria-label="t('richEditor.hr')" :disabled="disabled || sourceMode" @mousedown.prevent @click="exec('insertHorizontalRule')">\u2014</button>
|
|
10460
|
+
<button class="djm-rich-editor-btn" type="button" :title="t('richEditor.clearFormat')" :aria-label="t('richEditor.clearFormat')" :disabled="disabled || sourceMode" @mousedown.prevent @click="exec('removeFormat')"><span class="djm-rich-editor-glyph">T\xD7</span></button>
|
|
10461
|
+
</div>
|
|
10462
|
+
|
|
10463
|
+
<div class="djm-rich-editor-spacer" v-if="has('view')"></div>
|
|
10464
|
+
<div class="djm-rich-editor-group djm-rich-editor-group-end" v-if="has('view')">
|
|
10465
|
+
<button
|
|
10466
|
+
class="djm-rich-editor-btn"
|
|
10467
|
+
:class="{ 'djm-is-active': sourceMode }"
|
|
10468
|
+
type="button"
|
|
10469
|
+
:title="sourceMode ? t('richEditor.visual') : t('richEditor.source')"
|
|
10470
|
+
:aria-label="sourceMode ? t('richEditor.visual') : t('richEditor.source')"
|
|
10471
|
+
:aria-pressed="String(sourceMode)"
|
|
10472
|
+
:disabled="disabled"
|
|
10473
|
+
@click="toggleSource"
|
|
10474
|
+
><Icon name="code" :size="13" /></button>
|
|
10475
|
+
<button
|
|
10476
|
+
class="djm-rich-editor-btn"
|
|
10477
|
+
:class="{ 'djm-is-active': fullscreen }"
|
|
10478
|
+
type="button"
|
|
10479
|
+
:title="fullscreen ? t('richEditor.exitFullscreen') : t('richEditor.fullscreen')"
|
|
10480
|
+
:aria-label="fullscreen ? t('richEditor.exitFullscreen') : t('richEditor.fullscreen')"
|
|
10481
|
+
:aria-pressed="String(fullscreen)"
|
|
10482
|
+
:disabled="disabled"
|
|
10483
|
+
@click="toggleFullscreen"
|
|
10484
|
+
><Icon :name="fullscreen ? 'minimize' : 'maximize'" :size="13" /></button>
|
|
10485
|
+
</div>
|
|
9616
10486
|
</div>
|
|
9617
10487
|
|
|
9618
10488
|
<div
|
|
@@ -9628,6 +10498,8 @@ var rich_editor_default = {
|
|
|
9628
10498
|
:style="{ minHeight: minHeight + 'px' }"
|
|
9629
10499
|
@input="syncFromDom"
|
|
9630
10500
|
@paste="onPaste"
|
|
10501
|
+
@dragover="onDragOver"
|
|
10502
|
+
@drop="onDrop"
|
|
9631
10503
|
></div>
|
|
9632
10504
|
|
|
9633
10505
|
<textarea
|
|
@@ -9640,12 +10512,27 @@ var rich_editor_default = {
|
|
|
9640
10512
|
spellcheck="false"
|
|
9641
10513
|
@input="onSourceInput"
|
|
9642
10514
|
></textarea>
|
|
10515
|
+
|
|
10516
|
+
<div v-if="showCount" class="djm-rich-editor-foot">
|
|
10517
|
+
<span v-if="uploadCount" class="djm-rich-editor-foot-item">{{ t('richEditor.uploading', { count: uploadCount }) }}</span>
|
|
10518
|
+
<span class="djm-rich-editor-foot-item">{{ t('richEditor.wordCount', { count }) }}</span>
|
|
10519
|
+
</div>
|
|
10520
|
+
|
|
10521
|
+
<input
|
|
10522
|
+
ref="fileInput"
|
|
10523
|
+
class="djm-rich-editor-file"
|
|
10524
|
+
type="file"
|
|
10525
|
+
:accept="accept"
|
|
10526
|
+
tabindex="-1"
|
|
10527
|
+
aria-hidden="true"
|
|
10528
|
+
@change="onFilesChange"
|
|
10529
|
+
/>
|
|
9643
10530
|
</div>
|
|
9644
10531
|
`
|
|
9645
10532
|
};
|
|
9646
10533
|
|
|
9647
10534
|
// src/components/floating-window/index.js
|
|
9648
|
-
import { ref as
|
|
10535
|
+
import { ref as ref29, onBeforeUnmount as onBeforeUnmount24 } from "vue";
|
|
9649
10536
|
function clamp(value, min, max) {
|
|
9650
10537
|
return Math.min(Math.max(value, min), Math.max(min, max));
|
|
9651
10538
|
}
|
|
@@ -9663,12 +10550,12 @@ var floating_window_default = {
|
|
|
9663
10550
|
},
|
|
9664
10551
|
emits: ["close", "focus"],
|
|
9665
10552
|
setup(props, { emit }) {
|
|
9666
|
-
const root =
|
|
9667
|
-
const pos =
|
|
9668
|
-
const size =
|
|
9669
|
-
const minimized =
|
|
9670
|
-
const maximized =
|
|
9671
|
-
const saved =
|
|
10553
|
+
const root = ref29(null);
|
|
10554
|
+
const pos = ref29({ x: props.initialX, y: props.initialY });
|
|
10555
|
+
const size = ref29({ w: props.width, h: props.height });
|
|
10556
|
+
const minimized = ref29(false);
|
|
10557
|
+
const maximized = ref29(false);
|
|
10558
|
+
const saved = ref29(null);
|
|
9672
10559
|
let drag = null;
|
|
9673
10560
|
let resize = null;
|
|
9674
10561
|
function stage() {
|
|
@@ -9804,7 +10691,7 @@ var floating_window_default = {
|
|
|
9804
10691
|
};
|
|
9805
10692
|
|
|
9806
10693
|
// src/components/upload/index.js
|
|
9807
|
-
import { reactive as reactive4, ref as
|
|
10694
|
+
import { reactive as reactive4, ref as ref30, watch as watch21, onBeforeUnmount as onBeforeUnmount25 } from "vue";
|
|
9808
10695
|
var uidSeed6 = 0;
|
|
9809
10696
|
function extension(name) {
|
|
9810
10697
|
const index = name.lastIndexOf(".");
|
|
@@ -9854,11 +10741,11 @@ var upload_default = {
|
|
|
9854
10741
|
},
|
|
9855
10742
|
emits: ["update:modelValue", "change", "success", "error", "remove", "exceed"],
|
|
9856
10743
|
setup(props, { emit }) {
|
|
9857
|
-
const files =
|
|
9858
|
-
const dragActive =
|
|
9859
|
-
const inputRef =
|
|
10744
|
+
const files = ref30([]);
|
|
10745
|
+
const dragActive = ref30(false);
|
|
10746
|
+
const inputRef = ref30(null);
|
|
9860
10747
|
const tasks = /* @__PURE__ */ new Map();
|
|
9861
|
-
|
|
10748
|
+
watch21(
|
|
9862
10749
|
() => props.modelValue,
|
|
9863
10750
|
(list) => {
|
|
9864
10751
|
const next = list || [];
|
|
@@ -10160,7 +11047,7 @@ var upload_default = {
|
|
|
10160
11047
|
};
|
|
10161
11048
|
|
|
10162
11049
|
// src/components/tree/index.js
|
|
10163
|
-
import { computed as
|
|
11050
|
+
import { computed as computed18, ref as ref31, watch as watch22 } from "vue";
|
|
10164
11051
|
var tree_default = {
|
|
10165
11052
|
name: "DjmTree",
|
|
10166
11053
|
components: { Icon: icon_default },
|
|
@@ -10192,17 +11079,17 @@ var tree_default = {
|
|
|
10192
11079
|
},
|
|
10193
11080
|
emits: ["update:checked", "update:expanded", "node-click", "check", "node-drop", "load-error"],
|
|
10194
11081
|
setup(props, { emit }) {
|
|
10195
|
-
const lazyChildren =
|
|
10196
|
-
const loadingKeys =
|
|
10197
|
-
const innerExpanded =
|
|
10198
|
-
const innerChecked =
|
|
10199
|
-
|
|
11082
|
+
const lazyChildren = ref31({});
|
|
11083
|
+
const loadingKeys = ref31([]);
|
|
11084
|
+
const innerExpanded = ref31([...props.expanded]);
|
|
11085
|
+
const innerChecked = ref31([...props.checked]);
|
|
11086
|
+
watch22(
|
|
10200
11087
|
() => props.expanded,
|
|
10201
11088
|
(value) => {
|
|
10202
11089
|
if (Array.isArray(value)) innerExpanded.value = value;
|
|
10203
11090
|
}
|
|
10204
11091
|
);
|
|
10205
|
-
|
|
11092
|
+
watch22(
|
|
10206
11093
|
() => props.checked,
|
|
10207
11094
|
(value) => {
|
|
10208
11095
|
if (Array.isArray(value)) innerChecked.value = value;
|
|
@@ -10240,7 +11127,7 @@ var tree_default = {
|
|
|
10240
11127
|
});
|
|
10241
11128
|
return out;
|
|
10242
11129
|
}
|
|
10243
|
-
|
|
11130
|
+
watch22(
|
|
10244
11131
|
() => props.data,
|
|
10245
11132
|
() => {
|
|
10246
11133
|
if (props.defaultExpandAll) innerExpanded.value = collectExpandable(props.data);
|
|
@@ -10257,7 +11144,7 @@ var tree_default = {
|
|
|
10257
11144
|
const children = childrenOf(node);
|
|
10258
11145
|
return Boolean(children && children.some((child) => matchSubtree(child)));
|
|
10259
11146
|
}
|
|
10260
|
-
const rows =
|
|
11147
|
+
const rows = computed18(() => {
|
|
10261
11148
|
const result = [];
|
|
10262
11149
|
const walk = (nodes, level) => {
|
|
10263
11150
|
nodes.forEach((node) => {
|
|
@@ -10328,8 +11215,8 @@ var tree_default = {
|
|
|
10328
11215
|
function isActive(node) {
|
|
10329
11216
|
return props.activeKey !== "" && node[props.nodeKey] === props.activeKey;
|
|
10330
11217
|
}
|
|
10331
|
-
const rootEl =
|
|
10332
|
-
const focusIndex =
|
|
11218
|
+
const rootEl = ref31(null);
|
|
11219
|
+
const focusIndex = ref31(-1);
|
|
10333
11220
|
function tabIndexOf(index) {
|
|
10334
11221
|
return (focusIndex.value === -1 ? 0 : focusIndex.value) === index ? 0 : -1;
|
|
10335
11222
|
}
|
|
@@ -10386,9 +11273,9 @@ var tree_default = {
|
|
|
10386
11273
|
function rowClassOf(node, level) {
|
|
10387
11274
|
return typeof props.rowClass === "function" ? props.rowClass(node, level) : props.rowClass;
|
|
10388
11275
|
}
|
|
10389
|
-
const dragKey =
|
|
10390
|
-
const dropKey =
|
|
10391
|
-
const dropPosition =
|
|
11276
|
+
const dragKey = ref31("");
|
|
11277
|
+
const dropKey = ref31("");
|
|
11278
|
+
const dropPosition = ref31("");
|
|
10392
11279
|
function findNodeByKey(key, nodes = props.data) {
|
|
10393
11280
|
for (const node of nodes) {
|
|
10394
11281
|
if (node[props.nodeKey] === key) return node;
|
|
@@ -10500,7 +11387,7 @@ var tree_default = {
|
|
|
10500
11387
|
onDrop,
|
|
10501
11388
|
onDragEnd,
|
|
10502
11389
|
labelOf,
|
|
10503
|
-
emptyLabel:
|
|
11390
|
+
emptyLabel: computed18(() => props.emptyText || t("tree.empty")),
|
|
10504
11391
|
t
|
|
10505
11392
|
};
|
|
10506
11393
|
},
|
|
@@ -10569,7 +11456,7 @@ var tree_default = {
|
|
|
10569
11456
|
};
|
|
10570
11457
|
|
|
10571
11458
|
// src/components/editable-table/index.js
|
|
10572
|
-
import { computed as
|
|
11459
|
+
import { computed as computed19, nextTick as nextTick14, reactive as reactive5, ref as ref32, useSlots, watch as watch23 } from "vue";
|
|
10573
11460
|
var ACTIONS_KEY = "__editable_actions";
|
|
10574
11461
|
function isEmpty(value) {
|
|
10575
11462
|
if (value === "" || value === null || value === void 0) return true;
|
|
@@ -10593,12 +11480,12 @@ var editable_table_default = {
|
|
|
10593
11480
|
emits: ["edit", "save", "cancel"],
|
|
10594
11481
|
setup(props, { emit }) {
|
|
10595
11482
|
const slots = useSlots();
|
|
10596
|
-
const editingKey =
|
|
11483
|
+
const editingKey = ref32("");
|
|
10597
11484
|
const draft = reactive5({});
|
|
10598
11485
|
const errors = reactive5({});
|
|
10599
|
-
const tableRef =
|
|
10600
|
-
const editableColumns =
|
|
10601
|
-
const renderColumns =
|
|
11486
|
+
const tableRef = ref32(null);
|
|
11487
|
+
const editableColumns = computed19(() => props.columns.filter((column) => column.editor));
|
|
11488
|
+
const renderColumns = computed19(() => {
|
|
10602
11489
|
if (!props.showActions) return props.columns;
|
|
10603
11490
|
return props.columns.concat({
|
|
10604
11491
|
key: ACTIONS_KEY,
|
|
@@ -10610,7 +11497,7 @@ var editable_table_default = {
|
|
|
10610
11497
|
exportable: false
|
|
10611
11498
|
});
|
|
10612
11499
|
});
|
|
10613
|
-
const forwardedSlotNames =
|
|
11500
|
+
const forwardedSlotNames = computed19(() => {
|
|
10614
11501
|
const taken = new Set(editableColumns.value.map((column) => "cell-" + column.key));
|
|
10615
11502
|
taken.add("cell-" + ACTIONS_KEY);
|
|
10616
11503
|
return Object.keys(slots).filter((name) => !taken.has(name));
|
|
@@ -10705,7 +11592,7 @@ var editable_table_default = {
|
|
|
10705
11592
|
clearErrors();
|
|
10706
11593
|
return true;
|
|
10707
11594
|
}
|
|
10708
|
-
|
|
11595
|
+
watch23(
|
|
10709
11596
|
() => props.rows,
|
|
10710
11597
|
() => {
|
|
10711
11598
|
if (editingKey.value && !findRow(editingKey.value)) {
|
|
@@ -10887,7 +11774,7 @@ var message_default = {
|
|
|
10887
11774
|
};
|
|
10888
11775
|
|
|
10889
11776
|
// src/components/org-picker/index.js
|
|
10890
|
-
import { computed as
|
|
11777
|
+
import { computed as computed20, onBeforeUnmount as onBeforeUnmount26, ref as ref33, watch as watch24 } from "vue";
|
|
10891
11778
|
var org_picker_default = {
|
|
10892
11779
|
name: "DjmOrgPicker",
|
|
10893
11780
|
components: { DjmIcon: icon_default },
|
|
@@ -10906,13 +11793,13 @@ var org_picker_default = {
|
|
|
10906
11793
|
},
|
|
10907
11794
|
emits: ["update:modelValue", "change", "visible-change"],
|
|
10908
11795
|
setup(props, { emit }) {
|
|
10909
|
-
const open =
|
|
10910
|
-
const root =
|
|
10911
|
-
const searchRef =
|
|
10912
|
-
const keyword =
|
|
10913
|
-
const activeDept =
|
|
10914
|
-
const temp =
|
|
10915
|
-
const expandedIds =
|
|
11796
|
+
const open = ref33(false);
|
|
11797
|
+
const root = ref33(null);
|
|
11798
|
+
const searchRef = ref33(null);
|
|
11799
|
+
const keyword = ref33("");
|
|
11800
|
+
const activeDept = ref33("");
|
|
11801
|
+
const temp = ref33([]);
|
|
11802
|
+
const expandedIds = ref33(/* @__PURE__ */ new Set());
|
|
10916
11803
|
let detachPanel = null;
|
|
10917
11804
|
function collectDeptIds(nodes, out = []) {
|
|
10918
11805
|
nodes.forEach((node) => {
|
|
@@ -10942,22 +11829,22 @@ var org_picker_default = {
|
|
|
10942
11829
|
walk([root2]);
|
|
10943
11830
|
return ids;
|
|
10944
11831
|
}
|
|
10945
|
-
const staffMap =
|
|
11832
|
+
const staffMap = computed20(() => {
|
|
10946
11833
|
const map = /* @__PURE__ */ new Map();
|
|
10947
11834
|
props.staff.forEach((item) => map.set(item.id, item));
|
|
10948
11835
|
return map;
|
|
10949
11836
|
});
|
|
10950
|
-
const appliedStaff =
|
|
11837
|
+
const appliedStaff = computed20(
|
|
10951
11838
|
() => props.modelValue.map((id) => staffMap.value.get(id)).filter(Boolean)
|
|
10952
11839
|
);
|
|
10953
|
-
const visibleTags =
|
|
11840
|
+
const visibleTags = computed20(() => {
|
|
10954
11841
|
if (props.maxTagCount <= 0) return appliedStaff.value;
|
|
10955
11842
|
return appliedStaff.value.slice(0, props.maxTagCount);
|
|
10956
11843
|
});
|
|
10957
|
-
const restTagCount =
|
|
11844
|
+
const restTagCount = computed20(
|
|
10958
11845
|
() => Math.max(0, appliedStaff.value.length - visibleTags.value.length)
|
|
10959
11846
|
);
|
|
10960
|
-
const visibleStaff =
|
|
11847
|
+
const visibleStaff = computed20(() => {
|
|
10961
11848
|
const key = keyword.value.trim().toLowerCase();
|
|
10962
11849
|
if (key) {
|
|
10963
11850
|
return props.staff.filter(
|
|
@@ -10968,7 +11855,7 @@ var org_picker_default = {
|
|
|
10968
11855
|
const scope = deptScope(activeDept.value);
|
|
10969
11856
|
return props.staff.filter((item) => scope.has(item.deptId));
|
|
10970
11857
|
});
|
|
10971
|
-
const deptRows =
|
|
11858
|
+
const deptRows = computed20(() => {
|
|
10972
11859
|
const rows = [];
|
|
10973
11860
|
const walk = (nodes, depth) => {
|
|
10974
11861
|
nodes.forEach((node) => {
|
|
@@ -10980,11 +11867,11 @@ var org_picker_default = {
|
|
|
10980
11867
|
walk(props.departments, 0);
|
|
10981
11868
|
return rows;
|
|
10982
11869
|
});
|
|
10983
|
-
const selectedCount =
|
|
10984
|
-
const placeholderText =
|
|
10985
|
-
const emptyLabel =
|
|
10986
|
-
const panel =
|
|
10987
|
-
const panelStyle =
|
|
11870
|
+
const selectedCount = computed20(() => temp.value.length);
|
|
11871
|
+
const placeholderText = computed20(() => props.placeholder || t("orgPicker.placeholder"));
|
|
11872
|
+
const emptyLabel = computed20(() => props.emptyText || t("orgPicker.empty"));
|
|
11873
|
+
const panel = ref33(null);
|
|
11874
|
+
const panelStyle = ref33({ ...PANEL_HIDDEN_STYLE });
|
|
10988
11875
|
const PANEL_HEIGHT = 342;
|
|
10989
11876
|
function updatePosition() {
|
|
10990
11877
|
if (!open.value || !root.value) return;
|
|
@@ -11001,7 +11888,7 @@ var org_picker_default = {
|
|
|
11001
11888
|
expandedIds.value = new Set(collectDeptIds(props.departments));
|
|
11002
11889
|
}
|
|
11003
11890
|
expandAll();
|
|
11004
|
-
|
|
11891
|
+
watch24(() => props.departments, () => {
|
|
11005
11892
|
expandedIds.value = /* @__PURE__ */ new Set([...expandedIds.value, ...collectDeptIds(props.departments)]);
|
|
11006
11893
|
});
|
|
11007
11894
|
function initialOf(item) {
|
|
@@ -11276,7 +12163,7 @@ var org_picker_default = {
|
|
|
11276
12163
|
};
|
|
11277
12164
|
|
|
11278
12165
|
// src/components/schema-form/index.js
|
|
11279
|
-
import { computed as
|
|
12166
|
+
import { computed as computed21, reactive as reactive7, ref as ref34, watch as watch25 } from "vue";
|
|
11280
12167
|
var CONTROL_MAP = {
|
|
11281
12168
|
input: input_default,
|
|
11282
12169
|
number: input_number_default,
|
|
@@ -11312,26 +12199,26 @@ var schema_form_default = {
|
|
|
11312
12199
|
},
|
|
11313
12200
|
emits: ["update:modelValue", "change"],
|
|
11314
12201
|
setup(props, { emit }) {
|
|
11315
|
-
const innerForm =
|
|
12202
|
+
const innerForm = ref34(null);
|
|
11316
12203
|
const model = reactive7({ ...props.modelValue });
|
|
11317
|
-
|
|
12204
|
+
watch25(() => props.fields, (fields) => {
|
|
11318
12205
|
fields.forEach((field) => {
|
|
11319
12206
|
if (model[field.key] === void 0 && field.default !== void 0) {
|
|
11320
12207
|
model[field.key] = typeof field.default === "function" ? field.default() : field.default;
|
|
11321
12208
|
}
|
|
11322
12209
|
});
|
|
11323
12210
|
}, { immediate: true, deep: true });
|
|
11324
|
-
|
|
12211
|
+
watch25(() => props.modelValue, (value) => {
|
|
11325
12212
|
if (!value) return;
|
|
11326
12213
|
Object.keys(value).forEach((key) => {
|
|
11327
12214
|
if (model[key] !== value[key]) model[key] = value[key];
|
|
11328
12215
|
});
|
|
11329
12216
|
}, { deep: true });
|
|
11330
|
-
|
|
12217
|
+
watch25(model, () => {
|
|
11331
12218
|
emit("update:modelValue", { ...model });
|
|
11332
12219
|
emit("change", { ...model });
|
|
11333
12220
|
}, { deep: true });
|
|
11334
|
-
const formRules =
|
|
12221
|
+
const formRules = computed21(() => {
|
|
11335
12222
|
const merged = { ...props.rules };
|
|
11336
12223
|
props.fields.forEach((field) => {
|
|
11337
12224
|
if (!field.required && !field.rules) return;
|
|
@@ -11344,7 +12231,7 @@ var schema_form_default = {
|
|
|
11344
12231
|
});
|
|
11345
12232
|
return merged;
|
|
11346
12233
|
});
|
|
11347
|
-
const visibleFields =
|
|
12234
|
+
const visibleFields = computed21(
|
|
11348
12235
|
() => props.fields.filter((field) => {
|
|
11349
12236
|
if (typeof field.visibleWhen !== "function") return true;
|
|
11350
12237
|
return Boolean(field.visibleWhen(model));
|
|
@@ -11538,7 +12425,7 @@ var approval_flow_default = {
|
|
|
11538
12425
|
};
|
|
11539
12426
|
|
|
11540
12427
|
// src/components/query-filter/index.js
|
|
11541
|
-
import { computed as
|
|
12428
|
+
import { computed as computed22, reactive as reactive8, ref as ref35, watch as watch26 } from "vue";
|
|
11542
12429
|
var CONTROL_MAP2 = {
|
|
11543
12430
|
input: input_default,
|
|
11544
12431
|
number: input_number_default,
|
|
@@ -11563,26 +12450,26 @@ var query_filter_default = {
|
|
|
11563
12450
|
},
|
|
11564
12451
|
emits: ["update:modelValue", "search", "reset"],
|
|
11565
12452
|
setup(props, { emit }) {
|
|
11566
|
-
const expanded =
|
|
12453
|
+
const expanded = ref35(false);
|
|
11567
12454
|
const model = reactive8({ ...props.modelValue });
|
|
11568
|
-
|
|
12455
|
+
watch26(() => props.fields, (fields) => {
|
|
11569
12456
|
fields.forEach((field) => {
|
|
11570
12457
|
if (model[field.key] === void 0 && field.default !== void 0) {
|
|
11571
12458
|
model[field.key] = typeof field.default === "function" ? field.default() : field.default;
|
|
11572
12459
|
}
|
|
11573
12460
|
});
|
|
11574
12461
|
}, { immediate: true, deep: true });
|
|
11575
|
-
|
|
12462
|
+
watch26(() => props.modelValue, (value) => {
|
|
11576
12463
|
if (!value) return;
|
|
11577
12464
|
Object.keys(value).forEach((key) => {
|
|
11578
12465
|
if (model[key] !== value[key]) model[key] = value[key];
|
|
11579
12466
|
});
|
|
11580
12467
|
}, { deep: true });
|
|
11581
|
-
|
|
12468
|
+
watch26(model, () => {
|
|
11582
12469
|
emit("update:modelValue", { ...model });
|
|
11583
12470
|
}, { deep: true });
|
|
11584
|
-
const collapsible =
|
|
11585
|
-
const visibleFields =
|
|
12471
|
+
const collapsible = computed22(() => props.fields.length > props.visibleCount);
|
|
12472
|
+
const visibleFields = computed22(() => {
|
|
11586
12473
|
if (!collapsible.value || expanded.value) return props.fields;
|
|
11587
12474
|
return props.fields.slice(0, props.visibleCount);
|
|
11588
12475
|
});
|
|
@@ -11711,198 +12598,6 @@ var filter_tags_default = {
|
|
|
11711
12598
|
`
|
|
11712
12599
|
};
|
|
11713
12600
|
|
|
11714
|
-
// src/components/media-picker/index.js
|
|
11715
|
-
import { computed as computed21, ref as ref35, watch as watch26 } from "vue";
|
|
11716
|
-
var media_picker_default = {
|
|
11717
|
-
name: "DjmMediaPicker",
|
|
11718
|
-
components: { DjmModal: modal_default, DjmPagination: pagination_default, DjmIcon: icon_default },
|
|
11719
|
-
props: {
|
|
11720
|
-
modelValue: { type: [Array, String, Number], default: "" },
|
|
11721
|
-
items: { type: Array, default: () => [] },
|
|
11722
|
-
multiple: { type: Boolean, default: false },
|
|
11723
|
-
// 最多选几个,0 表示不限
|
|
11724
|
-
limit: { type: Number, default: 0 },
|
|
11725
|
-
// image 只显示图片,file 只显示非图片,空串不过滤
|
|
11726
|
-
accept: { type: String, default: "" },
|
|
11727
|
-
title: { type: String, default: "" },
|
|
11728
|
-
triggerText: { type: String, default: "" },
|
|
11729
|
-
pageSize: { type: Number, default: 12 },
|
|
11730
|
-
disabled: { type: Boolean, default: false }
|
|
11731
|
-
},
|
|
11732
|
-
emits: ["update:modelValue", "change"],
|
|
11733
|
-
setup(props, { emit }) {
|
|
11734
|
-
const open = ref35(false);
|
|
11735
|
-
const keyword = ref35("");
|
|
11736
|
-
const page = ref35(1);
|
|
11737
|
-
const temp = ref35([]);
|
|
11738
|
-
const selectedIds = computed21(() => {
|
|
11739
|
-
if (props.multiple) return Array.isArray(props.modelValue) ? props.modelValue : [];
|
|
11740
|
-
if (props.modelValue === "" || props.modelValue === null || props.modelValue === void 0) return [];
|
|
11741
|
-
return [props.modelValue];
|
|
11742
|
-
});
|
|
11743
|
-
function isImage(item) {
|
|
11744
|
-
if (item.type) return item.type === "image";
|
|
11745
|
-
return /\.(png|jpe?g|gif|webp|svg|avif)$/i.test(item.url || "");
|
|
11746
|
-
}
|
|
11747
|
-
const filtered = computed21(() => {
|
|
11748
|
-
const key = keyword.value.trim().toLowerCase();
|
|
11749
|
-
return props.items.filter((item) => {
|
|
11750
|
-
if (props.accept === "image" && !isImage(item)) return false;
|
|
11751
|
-
if (props.accept === "file" && isImage(item)) return false;
|
|
11752
|
-
if (key && !String(item.name || "").toLowerCase().includes(key)) return false;
|
|
11753
|
-
return true;
|
|
11754
|
-
});
|
|
11755
|
-
});
|
|
11756
|
-
const paged = computed21(() => {
|
|
11757
|
-
const start = (page.value - 1) * props.pageSize;
|
|
11758
|
-
return filtered.value.slice(start, start + props.pageSize);
|
|
11759
|
-
});
|
|
11760
|
-
watch26(keyword, () => {
|
|
11761
|
-
page.value = 1;
|
|
11762
|
-
});
|
|
11763
|
-
watch26(
|
|
11764
|
-
() => filtered.value.length,
|
|
11765
|
-
() => {
|
|
11766
|
-
const max = Math.max(1, Math.ceil(filtered.value.length / props.pageSize));
|
|
11767
|
-
if (page.value > max) page.value = max;
|
|
11768
|
-
}
|
|
11769
|
-
);
|
|
11770
|
-
function isChecked(id) {
|
|
11771
|
-
return temp.value.includes(id);
|
|
11772
|
-
}
|
|
11773
|
-
function atLimit() {
|
|
11774
|
-
return props.limit > 0 && temp.value.length >= props.limit;
|
|
11775
|
-
}
|
|
11776
|
-
function toggle(item) {
|
|
11777
|
-
if (props.multiple) {
|
|
11778
|
-
if (isChecked(item.id)) {
|
|
11779
|
-
temp.value = temp.value.filter((id) => id !== item.id);
|
|
11780
|
-
return;
|
|
11781
|
-
}
|
|
11782
|
-
if (atLimit()) return;
|
|
11783
|
-
temp.value = [...temp.value, item.id];
|
|
11784
|
-
return;
|
|
11785
|
-
}
|
|
11786
|
-
temp.value = [item.id];
|
|
11787
|
-
}
|
|
11788
|
-
function openPanel() {
|
|
11789
|
-
if (props.disabled) return;
|
|
11790
|
-
temp.value = [...selectedIds.value];
|
|
11791
|
-
keyword.value = "";
|
|
11792
|
-
page.value = 1;
|
|
11793
|
-
open.value = true;
|
|
11794
|
-
}
|
|
11795
|
-
function commit() {
|
|
11796
|
-
const next = props.multiple ? [...temp.value] : temp.value[0] !== void 0 ? temp.value[0] : "";
|
|
11797
|
-
emit("update:modelValue", next);
|
|
11798
|
-
emit("change", next);
|
|
11799
|
-
open.value = false;
|
|
11800
|
-
}
|
|
11801
|
-
function cancel() {
|
|
11802
|
-
temp.value = [...selectedIds.value];
|
|
11803
|
-
open.value = false;
|
|
11804
|
-
}
|
|
11805
|
-
return {
|
|
11806
|
-
open,
|
|
11807
|
-
keyword,
|
|
11808
|
-
page,
|
|
11809
|
-
temp,
|
|
11810
|
-
selectedIds,
|
|
11811
|
-
filtered,
|
|
11812
|
-
paged,
|
|
11813
|
-
isImage,
|
|
11814
|
-
isChecked,
|
|
11815
|
-
atLimit,
|
|
11816
|
-
toggle,
|
|
11817
|
-
openPanel,
|
|
11818
|
-
commit,
|
|
11819
|
-
cancel,
|
|
11820
|
-
t
|
|
11821
|
-
};
|
|
11822
|
-
},
|
|
11823
|
-
template: `
|
|
11824
|
-
<span class="djm-media-picker">
|
|
11825
|
-
<slot name="trigger" :open="openPanel" :count="selectedIds.length">
|
|
11826
|
-
<button
|
|
11827
|
-
class="djm-btn"
|
|
11828
|
-
type="button"
|
|
11829
|
-
:disabled="disabled"
|
|
11830
|
-
@click="openPanel"
|
|
11831
|
-
>{{ triggerText || t('mediaPicker.select') }}<span v-if="selectedIds.length" class="djm-media-picker-count">{{ selectedIds.length }}</span></button>
|
|
11832
|
-
</slot>
|
|
11833
|
-
|
|
11834
|
-
<DjmModal
|
|
11835
|
-
:model-value="open"
|
|
11836
|
-
:title="title || t('mediaPicker.title')"
|
|
11837
|
-
width="760px"
|
|
11838
|
-
@update:model-value="cancel"
|
|
11839
|
-
>
|
|
11840
|
-
<div class="djm-media-toolbar">
|
|
11841
|
-
<label class="djm-media-search">
|
|
11842
|
-
<DjmIcon name="search" :size="13" />
|
|
11843
|
-
<input
|
|
11844
|
-
v-model="keyword"
|
|
11845
|
-
class="djm-media-search-input"
|
|
11846
|
-
type="text"
|
|
11847
|
-
:placeholder="t('mediaPicker.search')"
|
|
11848
|
-
:aria-label="t('mediaPicker.search')"
|
|
11849
|
-
/>
|
|
11850
|
-
</label>
|
|
11851
|
-
<span class="djm-media-toolbar-slot">
|
|
11852
|
-
<slot name="toolbar"></slot>
|
|
11853
|
-
</span>
|
|
11854
|
-
</div>
|
|
11855
|
-
|
|
11856
|
-
<div class="djm-media-grid" role="listbox" :aria-multiselectable="multiple ? 'true' : 'false'">
|
|
11857
|
-
<div
|
|
11858
|
-
v-for="item in paged"
|
|
11859
|
-
:key="item.id"
|
|
11860
|
-
class="djm-media-item"
|
|
11861
|
-
:class="{
|
|
11862
|
-
'djm-is-checked': isChecked(item.id),
|
|
11863
|
-
'djm-is-disabled': multiple && atLimit() && !isChecked(item.id)
|
|
11864
|
-
}"
|
|
11865
|
-
role="option"
|
|
11866
|
-
tabindex="0"
|
|
11867
|
-
:aria-selected="String(isChecked(item.id))"
|
|
11868
|
-
@click="toggle(item)"
|
|
11869
|
-
@keydown.enter.prevent="toggle(item)"
|
|
11870
|
-
@keydown.space.prevent="toggle(item)"
|
|
11871
|
-
>
|
|
11872
|
-
<div class="djm-media-thumb">
|
|
11873
|
-
<img v-if="isImage(item)" :src="item.url" :alt="item.name" loading="lazy" />
|
|
11874
|
-
<DjmIcon v-else name="folder" :size="26" />
|
|
11875
|
-
<span v-if="isChecked(item.id)" class="djm-media-check">
|
|
11876
|
-
<DjmIcon name="check" :size="11" />
|
|
11877
|
-
</span>
|
|
11878
|
-
</div>
|
|
11879
|
-
<div class="djm-media-name" :title="item.name">{{ item.name }}</div>
|
|
11880
|
-
</div>
|
|
11881
|
-
<div v-if="!paged.length" class="djm-media-empty">{{ t('mediaPicker.empty') }}</div>
|
|
11882
|
-
</div>
|
|
11883
|
-
|
|
11884
|
-
<div class="djm-media-foot">
|
|
11885
|
-
<span class="djm-media-total">
|
|
11886
|
-
{{ t('mediaPicker.total', { total: filtered.length }) }}
|
|
11887
|
-
<em v-if="multiple && limit > 0">{{ t('mediaPicker.limit', { limit }) }}</em>
|
|
11888
|
-
</span>
|
|
11889
|
-
<DjmPagination
|
|
11890
|
-
v-if="filtered.length > pageSize"
|
|
11891
|
-
v-model:page="page"
|
|
11892
|
-
:page-size="pageSize"
|
|
11893
|
-
:total="filtered.length"
|
|
11894
|
-
/>
|
|
11895
|
-
</div>
|
|
11896
|
-
|
|
11897
|
-
<template #footer>
|
|
11898
|
-
<button class="djm-btn" type="button" @click="cancel">{{ t('common.cancel') }}</button>
|
|
11899
|
-
<button class="djm-btn djm-btn-primary" type="button" @click="commit">{{ t('common.confirm') }}</button>
|
|
11900
|
-
</template>
|
|
11901
|
-
</DjmModal>
|
|
11902
|
-
</span>
|
|
11903
|
-
`
|
|
11904
|
-
};
|
|
11905
|
-
|
|
11906
12601
|
// src/components/kanban/index.js
|
|
11907
12602
|
import { ref as ref36, watch as watch27 } from "vue";
|
|
11908
12603
|
function cloneColumns(list) {
|
|
@@ -12092,7 +12787,7 @@ var kanban_default = {
|
|
|
12092
12787
|
};
|
|
12093
12788
|
|
|
12094
12789
|
// src/components/attachment-list/index.js
|
|
12095
|
-
import { computed as
|
|
12790
|
+
import { computed as computed23 } from "vue";
|
|
12096
12791
|
var IMAGE_EXTS = ["png", "jpg", "jpeg", "gif", "webp", "bmp", "svg"];
|
|
12097
12792
|
function extOf(file) {
|
|
12098
12793
|
if (file.ext) return String(file.ext).toLowerCase();
|
|
@@ -12116,14 +12811,14 @@ var attachment_list_default = {
|
|
|
12116
12811
|
},
|
|
12117
12812
|
emits: ["preview", "download", "remove"],
|
|
12118
12813
|
setup(props, { emit }) {
|
|
12119
|
-
const list =
|
|
12814
|
+
const list = computed23(
|
|
12120
12815
|
() => props.files.map((file, index) => {
|
|
12121
12816
|
const ext = extOf(file);
|
|
12122
12817
|
const isImage = file.type === "image" || IMAGE_EXTS.includes(ext);
|
|
12123
12818
|
return { ...file, _key: file.uid !== void 0 ? file.uid : index, _ext: ext, _isImage: isImage };
|
|
12124
12819
|
})
|
|
12125
12820
|
);
|
|
12126
|
-
const emptyLabel =
|
|
12821
|
+
const emptyLabel = computed23(() => props.emptyText || t("attachment.empty"));
|
|
12127
12822
|
function onPreview(file) {
|
|
12128
12823
|
emit("preview", file);
|
|
12129
12824
|
}
|
|
@@ -12229,7 +12924,7 @@ var attachment_list_default = {
|
|
|
12229
12924
|
};
|
|
12230
12925
|
|
|
12231
12926
|
// src/components/notification/index.js
|
|
12232
|
-
import { computed as
|
|
12927
|
+
import { computed as computed24, onBeforeUnmount as onBeforeUnmount27, ref as ref37 } from "vue";
|
|
12233
12928
|
var TYPE_MAP = {
|
|
12234
12929
|
info: { icon: "info", cls: "djm-is-info" },
|
|
12235
12930
|
success: { icon: "check", cls: "djm-is-success" },
|
|
@@ -12249,8 +12944,8 @@ var notification_default = {
|
|
|
12249
12944
|
},
|
|
12250
12945
|
emits: ["click", "read", "read-all", "remove", "clear"],
|
|
12251
12946
|
setup(props, { emit }) {
|
|
12252
|
-
const unreadCount =
|
|
12253
|
-
const emptyLabel =
|
|
12947
|
+
const unreadCount = computed24(() => props.items.filter((item) => !item.read).length);
|
|
12948
|
+
const emptyLabel = computed24(() => props.emptyText || t("notification.empty"));
|
|
12254
12949
|
function typeOf(item) {
|
|
12255
12950
|
return TYPE_MAP[item.type] || TYPE_MAP.info;
|
|
12256
12951
|
}
|
|
@@ -12382,7 +13077,7 @@ var config_provider_default = {
|
|
|
12382
13077
|
};
|
|
12383
13078
|
|
|
12384
13079
|
// src/components/date-time-picker/index.js
|
|
12385
|
-
import { ref as ref38, computed as
|
|
13080
|
+
import { ref as ref38, computed as computed25, watch as watch29, onBeforeUnmount as onBeforeUnmount28 } from "vue";
|
|
12386
13081
|
var uidSeed7 = 0;
|
|
12387
13082
|
var pad4 = (value) => String(value).padStart(2, "0");
|
|
12388
13083
|
function toDateKey(year, month, day) {
|
|
@@ -12424,22 +13119,22 @@ var date_time_picker_default = {
|
|
|
12424
13119
|
let detachPanel = null;
|
|
12425
13120
|
const today = /* @__PURE__ */ new Date();
|
|
12426
13121
|
const todayKey = toDateKey(today.getFullYear(), today.getMonth(), today.getDate());
|
|
12427
|
-
const hasSeconds =
|
|
13122
|
+
const hasSeconds = computed25(() => props.format.indexOf("ss") > -1);
|
|
12428
13123
|
const draft = ref38({ date: "", h: "00", m: "00", s: "00" });
|
|
12429
13124
|
const initial = parseDate(parseValue(props.modelValue).date);
|
|
12430
13125
|
const viewYear = ref38(initial ? initial.year : today.getFullYear());
|
|
12431
13126
|
const viewMonth = ref38(initial ? initial.month : today.getMonth());
|
|
12432
|
-
const displayText =
|
|
12433
|
-
const placeholderText =
|
|
12434
|
-
const weeks =
|
|
12435
|
-
const hours =
|
|
12436
|
-
const minutes =
|
|
13127
|
+
const displayText = computed25(() => props.modelValue || "");
|
|
13128
|
+
const placeholderText = computed25(() => props.placeholder || t("dateTimePicker.placeholder"));
|
|
13129
|
+
const weeks = computed25(() => t("datePicker.weeks").split(","));
|
|
13130
|
+
const hours = computed25(() => Array.from({ length: 24 }, (_, index) => pad4(index)));
|
|
13131
|
+
const minutes = computed25(() => {
|
|
12437
13132
|
const list = [];
|
|
12438
13133
|
for (let value = 0; value < 60; value += Math.max(1, props.minuteStep)) list.push(pad4(value));
|
|
12439
13134
|
return list;
|
|
12440
13135
|
});
|
|
12441
|
-
const seconds =
|
|
12442
|
-
const timeCols =
|
|
13136
|
+
const seconds = computed25(() => Array.from({ length: 60 }, (_, index) => pad4(index)));
|
|
13137
|
+
const timeCols = computed25(() => {
|
|
12443
13138
|
const cols = [
|
|
12444
13139
|
{ key: "h", list: hours.value },
|
|
12445
13140
|
{ key: "m", list: minutes.value }
|
|
@@ -12447,8 +13142,8 @@ var date_time_picker_default = {
|
|
|
12447
13142
|
if (hasSeconds.value) cols.push({ key: "s", list: seconds.value });
|
|
12448
13143
|
return cols;
|
|
12449
13144
|
});
|
|
12450
|
-
const monthLabel =
|
|
12451
|
-
const cells =
|
|
13145
|
+
const monthLabel = computed25(() => t("datePicker.title", { year: viewYear.value, month: viewMonth.value + 1 }));
|
|
13146
|
+
const cells = computed25(() => {
|
|
12452
13147
|
const first = new Date(viewYear.value, viewMonth.value, 1);
|
|
12453
13148
|
const offset = (first.getDay() + 6) % 7;
|
|
12454
13149
|
const start = new Date(viewYear.value, viewMonth.value, 1 - offset);
|
|
@@ -12709,7 +13404,7 @@ var date_time_picker_default = {
|
|
|
12709
13404
|
};
|
|
12710
13405
|
|
|
12711
13406
|
// src/components/virtual-list/index.js
|
|
12712
|
-
import { ref as ref39, computed as
|
|
13407
|
+
import { ref as ref39, computed as computed26, watch as watch30, onMounted as onMounted16, onBeforeUnmount as onBeforeUnmount29 } from "vue";
|
|
12713
13408
|
var virtual_list_default = {
|
|
12714
13409
|
name: "DjmVirtualList",
|
|
12715
13410
|
props: {
|
|
@@ -12733,7 +13428,7 @@ var virtual_list_default = {
|
|
|
12733
13428
|
function rowHeight(item, index) {
|
|
12734
13429
|
return typeof props.itemHeight === "function" ? Math.max(1, Number(props.itemHeight(item, index)) || 1) : Math.max(1, props.itemHeight);
|
|
12735
13430
|
}
|
|
12736
|
-
const offsets =
|
|
13431
|
+
const offsets = computed26(() => {
|
|
12737
13432
|
const list = [0];
|
|
12738
13433
|
let sum = 0;
|
|
12739
13434
|
props.items.forEach((item, index) => {
|
|
@@ -12742,7 +13437,7 @@ var virtual_list_default = {
|
|
|
12742
13437
|
});
|
|
12743
13438
|
return list;
|
|
12744
13439
|
});
|
|
12745
|
-
const totalHeight =
|
|
13440
|
+
const totalHeight = computed26(() => offsets.value[offsets.value.length - 1]);
|
|
12746
13441
|
function findStart(top) {
|
|
12747
13442
|
const list = offsets.value;
|
|
12748
13443
|
let low = 0;
|
|
@@ -12754,7 +13449,7 @@ var virtual_list_default = {
|
|
|
12754
13449
|
}
|
|
12755
13450
|
return Math.max(0, low - 1);
|
|
12756
13451
|
}
|
|
12757
|
-
const range =
|
|
13452
|
+
const range = computed26(() => {
|
|
12758
13453
|
const total = props.items.length;
|
|
12759
13454
|
if (!total) return { start: 0, end: 0 };
|
|
12760
13455
|
const start = Math.max(0, findStart(scrollTop.value) - props.overscan);
|
|
@@ -12763,7 +13458,7 @@ var virtual_list_default = {
|
|
|
12763
13458
|
while (end < total && offsets.value[end] < limit) end += 1;
|
|
12764
13459
|
return { start, end: Math.min(total, end + props.overscan) };
|
|
12765
13460
|
});
|
|
12766
|
-
const visibleRows =
|
|
13461
|
+
const visibleRows = computed26(() => {
|
|
12767
13462
|
const { start, end } = range.value;
|
|
12768
13463
|
return props.items.slice(start, end).map((item, index) => {
|
|
12769
13464
|
const realIndex = start + index;
|
|
@@ -12860,7 +13555,7 @@ var virtual_list_default = {
|
|
|
12860
13555
|
};
|
|
12861
13556
|
|
|
12862
13557
|
// src/components/batch-bar/index.js
|
|
12863
|
-
import { computed as
|
|
13558
|
+
import { computed as computed27 } from "vue";
|
|
12864
13559
|
var batch_bar_default = {
|
|
12865
13560
|
name: "DjmBatchBar",
|
|
12866
13561
|
props: {
|
|
@@ -12875,8 +13570,8 @@ var batch_bar_default = {
|
|
|
12875
13570
|
},
|
|
12876
13571
|
emits: ["clear", "select-all"],
|
|
12877
13572
|
setup(props, { emit }) {
|
|
12878
|
-
const text =
|
|
12879
|
-
const canSelectAll =
|
|
13573
|
+
const text = computed27(() => props.label || t("batchBar.selected", { count: props.count }));
|
|
13574
|
+
const canSelectAll = computed27(() => props.total > props.count);
|
|
12880
13575
|
return {
|
|
12881
13576
|
text,
|
|
12882
13577
|
canSelectAll,
|
|
@@ -12904,7 +13599,7 @@ var batch_bar_default = {
|
|
|
12904
13599
|
};
|
|
12905
13600
|
|
|
12906
13601
|
// src/components/import-wizard/index.js
|
|
12907
|
-
import { ref as ref40, computed as
|
|
13602
|
+
import { ref as ref40, computed as computed28, watch as watch31 } from "vue";
|
|
12908
13603
|
function matchAccept2(name, accept) {
|
|
12909
13604
|
if (!accept) return true;
|
|
12910
13605
|
const ext = "." + String(name).split(".").pop().toLowerCase();
|
|
@@ -12954,7 +13649,7 @@ var import_wizard_default = {
|
|
|
12954
13649
|
innerStep.value = next;
|
|
12955
13650
|
emit("update:step", next);
|
|
12956
13651
|
}
|
|
12957
|
-
const steps =
|
|
13652
|
+
const steps = computed28(() => [
|
|
12958
13653
|
{ index: 1, title: t("importWizard.stepFile") },
|
|
12959
13654
|
{ index: 2, title: t("importWizard.stepMapping") },
|
|
12960
13655
|
{ index: 3, title: t("importWizard.stepResult") }
|
|
@@ -12996,7 +13691,7 @@ var import_wizard_default = {
|
|
|
12996
13691
|
mappingError.value = "";
|
|
12997
13692
|
emit("update:mapping", next);
|
|
12998
13693
|
}
|
|
12999
|
-
const missingRequired =
|
|
13694
|
+
const missingRequired = computed28(
|
|
13000
13695
|
() => props.columns.filter((col) => col.required && !innerMapping.value[col.key])
|
|
13001
13696
|
);
|
|
13002
13697
|
function submit() {
|
|
@@ -13029,7 +13724,7 @@ var import_wizard_default = {
|
|
|
13029
13724
|
emit("retry");
|
|
13030
13725
|
goStep(2);
|
|
13031
13726
|
}
|
|
13032
|
-
const stats =
|
|
13727
|
+
const stats = computed28(() => {
|
|
13033
13728
|
const data = props.result || {};
|
|
13034
13729
|
return {
|
|
13035
13730
|
total: data.total || 0,
|
|
@@ -13175,7 +13870,7 @@ var import_wizard_default = {
|
|
|
13175
13870
|
};
|
|
13176
13871
|
|
|
13177
13872
|
// src/components/diff/index.js
|
|
13178
|
-
import { ref as ref41, computed as
|
|
13873
|
+
import { ref as ref41, computed as computed29 } from "vue";
|
|
13179
13874
|
|
|
13180
13875
|
// src/utils/text-diff.js
|
|
13181
13876
|
var MAX_CELLS = 1e6;
|
|
@@ -13239,8 +13934,8 @@ var diff_default = {
|
|
|
13239
13934
|
afterLabel: { type: String, default: "" }
|
|
13240
13935
|
},
|
|
13241
13936
|
setup(props) {
|
|
13242
|
-
const rows =
|
|
13243
|
-
const stats =
|
|
13937
|
+
const rows = computed29(() => diffLines(props.before, props.after));
|
|
13938
|
+
const stats = computed29(() => {
|
|
13244
13939
|
let add = 0;
|
|
13245
13940
|
let remove = 0;
|
|
13246
13941
|
rows.value.forEach((row) => {
|
|
@@ -13253,7 +13948,7 @@ var diff_default = {
|
|
|
13253
13948
|
function expand(index) {
|
|
13254
13949
|
expandedBlocks.value = expandedBlocks.value.concat(index);
|
|
13255
13950
|
}
|
|
13256
|
-
const displayRows =
|
|
13951
|
+
const displayRows = computed29(() => {
|
|
13257
13952
|
const ctx = Math.max(0, props.context);
|
|
13258
13953
|
const list = rows.value;
|
|
13259
13954
|
if (!ctx) return list;
|
|
@@ -13284,7 +13979,7 @@ var diff_default = {
|
|
|
13284
13979
|
}
|
|
13285
13980
|
return out;
|
|
13286
13981
|
});
|
|
13287
|
-
const splitRows =
|
|
13982
|
+
const splitRows = computed29(() => {
|
|
13288
13983
|
const list = displayRows.value;
|
|
13289
13984
|
const out = [];
|
|
13290
13985
|
let i = 0;
|
|
@@ -13309,8 +14004,8 @@ var diff_default = {
|
|
|
13309
14004
|
}
|
|
13310
14005
|
return out;
|
|
13311
14006
|
});
|
|
13312
|
-
const beforeLabelText =
|
|
13313
|
-
const afterLabelText =
|
|
14007
|
+
const beforeLabelText = computed29(() => props.beforeLabel || t("diff.before"));
|
|
14008
|
+
const afterLabelText = computed29(() => props.afterLabel || t("diff.after"));
|
|
13314
14009
|
return {
|
|
13315
14010
|
stats,
|
|
13316
14011
|
displayRows,
|
|
@@ -13376,7 +14071,7 @@ var diff_default = {
|
|
|
13376
14071
|
};
|
|
13377
14072
|
|
|
13378
14073
|
// src/components/tree-table/index.js
|
|
13379
|
-
import { ref as ref42, computed as
|
|
14074
|
+
import { ref as ref42, computed as computed30, watch as watch32 } from "vue";
|
|
13380
14075
|
function keyOf(row, rowKey) {
|
|
13381
14076
|
return row && row[rowKey] !== void 0 ? row[rowKey] : row && row.id;
|
|
13382
14077
|
}
|
|
@@ -13431,7 +14126,7 @@ var tree_table_default = {
|
|
|
13431
14126
|
if (value) innerChecked.value = value.slice();
|
|
13432
14127
|
}
|
|
13433
14128
|
);
|
|
13434
|
-
const rows =
|
|
14129
|
+
const rows = computed30(() => {
|
|
13435
14130
|
const out = [];
|
|
13436
14131
|
function walk(list, level, parentKey) {
|
|
13437
14132
|
;
|
|
@@ -13446,7 +14141,7 @@ var tree_table_default = {
|
|
|
13446
14141
|
walk(props.data, 1, null);
|
|
13447
14142
|
return out;
|
|
13448
14143
|
});
|
|
13449
|
-
const descendantMap =
|
|
14144
|
+
const descendantMap = computed30(() => {
|
|
13450
14145
|
const map = {};
|
|
13451
14146
|
function collect(row) {
|
|
13452
14147
|
const key = keyOf(row, props.rowKey);
|
|
@@ -13461,16 +14156,16 @@ var tree_table_default = {
|
|
|
13461
14156
|
(props.data || []).forEach(collect);
|
|
13462
14157
|
return map;
|
|
13463
14158
|
});
|
|
13464
|
-
const leafKeys =
|
|
14159
|
+
const leafKeys = computed30(() => {
|
|
13465
14160
|
const keys = [];
|
|
13466
14161
|
eachNode(props.data, (row) => {
|
|
13467
14162
|
if (!row.children || !row.children.length) keys.push(keyOf(row, props.rowKey));
|
|
13468
14163
|
});
|
|
13469
14164
|
return keys;
|
|
13470
14165
|
});
|
|
13471
|
-
const checkedSet =
|
|
13472
|
-
const allChecked =
|
|
13473
|
-
const someChecked =
|
|
14166
|
+
const checkedSet = computed30(() => new Set(innerChecked.value));
|
|
14167
|
+
const allChecked = computed30(() => leafKeys.value.length > 0 && leafKeys.value.every((key) => checkedSet.value.has(key)));
|
|
14168
|
+
const someChecked = computed30(() => !allChecked.value && leafKeys.value.some((key) => checkedSet.value.has(key)));
|
|
13474
14169
|
function isIndeterminate(row) {
|
|
13475
14170
|
if (!props.selectable || props.checkStrictly) return false;
|
|
13476
14171
|
const desc = descendantMap.value[keyOf(row, props.rowKey)] || [];
|
|
@@ -13504,7 +14199,7 @@ var tree_table_default = {
|
|
|
13504
14199
|
}
|
|
13505
14200
|
emitChecked(Array.from(set));
|
|
13506
14201
|
}
|
|
13507
|
-
const nodeMap =
|
|
14202
|
+
const nodeMap = computed30(() => {
|
|
13508
14203
|
const map = {};
|
|
13509
14204
|
eachNode(props.data, (row, level, parentKey) => {
|
|
13510
14205
|
map[keyOf(row, props.rowKey)] = { row, parentKey };
|
|
@@ -13551,11 +14246,11 @@ var tree_table_default = {
|
|
|
13551
14246
|
function onRowClick(item) {
|
|
13552
14247
|
emit("row-click", item.row, item);
|
|
13553
14248
|
}
|
|
13554
|
-
const scrollStyle =
|
|
14249
|
+
const scrollStyle = computed30(() => {
|
|
13555
14250
|
if (!props.maxHeight) return null;
|
|
13556
14251
|
return { maxHeight: typeof props.maxHeight === "number" ? props.maxHeight + "px" : props.maxHeight };
|
|
13557
14252
|
});
|
|
13558
|
-
const emptyLabel =
|
|
14253
|
+
const emptyLabel = computed30(() => props.emptyText || t("treeTable.empty"));
|
|
13559
14254
|
return {
|
|
13560
14255
|
rows,
|
|
13561
14256
|
innerExpanded,
|
|
@@ -13657,7 +14352,7 @@ var tree_table_default = {
|
|
|
13657
14352
|
};
|
|
13658
14353
|
|
|
13659
14354
|
// src/components/schedule/index.js
|
|
13660
|
-
import { ref as ref43, computed as
|
|
14355
|
+
import { ref as ref43, computed as computed31, watch as watch33, onBeforeUnmount as onBeforeUnmount30 } from "vue";
|
|
13661
14356
|
var pad5 = (value) => String(value).padStart(2, "0");
|
|
13662
14357
|
function toKey3(date) {
|
|
13663
14358
|
return `${date.getFullYear()}-${pad5(date.getMonth() + 1)}-${pad5(date.getDate())}`;
|
|
@@ -13707,8 +14402,8 @@ var schedule_default = {
|
|
|
13707
14402
|
const offset = (day + 6) % 7;
|
|
13708
14403
|
return new Date(date.getFullYear(), date.getMonth(), date.getDate() - offset);
|
|
13709
14404
|
}
|
|
13710
|
-
const weekStartDate =
|
|
13711
|
-
const weekdays =
|
|
14405
|
+
const weekStartDate = computed31(() => startOfWeek(anchor.value));
|
|
14406
|
+
const weekdays = computed31(() => t("schedule.weekdays").split(","));
|
|
13712
14407
|
function layoutDay(list) {
|
|
13713
14408
|
const sorted = list.map((item) => {
|
|
13714
14409
|
const startMin = toMinutes(item.start, props.startHour * 60);
|
|
@@ -13741,7 +14436,7 @@ var schedule_default = {
|
|
|
13741
14436
|
};
|
|
13742
14437
|
});
|
|
13743
14438
|
}
|
|
13744
|
-
const days =
|
|
14439
|
+
const days = computed31(() => {
|
|
13745
14440
|
const start = weekStartDate.value;
|
|
13746
14441
|
const list = Array.from({ length: 7 }, (_, index) => {
|
|
13747
14442
|
const date = new Date(start.getFullYear(), start.getMonth(), start.getDate() + index);
|
|
@@ -13759,20 +14454,20 @@ var schedule_default = {
|
|
|
13759
14454
|
});
|
|
13760
14455
|
return props.showWeekend ? list : list.slice(0, 5);
|
|
13761
14456
|
});
|
|
13762
|
-
const hours =
|
|
14457
|
+
const hours = computed31(() => {
|
|
13763
14458
|
const list = [];
|
|
13764
14459
|
for (let hour = props.startHour; hour < props.endHour; hour++) list.push(hour);
|
|
13765
14460
|
return list;
|
|
13766
14461
|
});
|
|
13767
|
-
const bodyHeight =
|
|
13768
|
-
const gridStyle =
|
|
14462
|
+
const bodyHeight = computed31(() => (props.endHour - props.startHour) * props.hourHeight);
|
|
14463
|
+
const gridStyle = computed31(() => ({
|
|
13769
14464
|
gridTemplateColumns: "56px repeat(" + Math.max(1, days.value.length) + ", minmax(0, 1fr))"
|
|
13770
14465
|
}));
|
|
13771
|
-
const nowTop =
|
|
13772
|
-
const showNowLine =
|
|
14466
|
+
const nowTop = computed31(() => (nowMinutes.value - props.startHour * 60) / 60 * props.hourHeight);
|
|
14467
|
+
const showNowLine = computed31(
|
|
13773
14468
|
() => nowMinutes.value >= props.startHour * 60 && nowMinutes.value <= props.endHour * 60 && days.value.some((day) => day.today)
|
|
13774
14469
|
);
|
|
13775
|
-
const rangeLabel =
|
|
14470
|
+
const rangeLabel = computed31(() => {
|
|
13776
14471
|
const list = days.value;
|
|
13777
14472
|
if (!list.length) return "";
|
|
13778
14473
|
const first = list[0];
|
|
@@ -13902,7 +14597,7 @@ var schedule_default = {
|
|
|
13902
14597
|
};
|
|
13903
14598
|
|
|
13904
14599
|
// src/components/comment/index.js
|
|
13905
|
-
import { ref as ref44, computed as
|
|
14600
|
+
import { ref as ref44, computed as computed32 } from "vue";
|
|
13906
14601
|
var comment_default = {
|
|
13907
14602
|
name: "DjmComment",
|
|
13908
14603
|
components: { DjmAvatar: avatar_default, DjmIcon: icon_default },
|
|
@@ -13921,14 +14616,14 @@ var comment_default = {
|
|
|
13921
14616
|
setup(props, { emit }) {
|
|
13922
14617
|
const content = ref44("");
|
|
13923
14618
|
const replyTarget = ref44(null);
|
|
13924
|
-
const placeholderText =
|
|
14619
|
+
const placeholderText = computed32(() => {
|
|
13925
14620
|
if (replyTarget.value) return t("comment.replyPlaceholder", { name: replyTarget.value.author });
|
|
13926
14621
|
return props.placeholder || t("comment.placeholder");
|
|
13927
14622
|
});
|
|
13928
|
-
const submitLabel =
|
|
13929
|
-
const emptyLabel =
|
|
13930
|
-
const overLimit =
|
|
13931
|
-
const canSubmit =
|
|
14623
|
+
const submitLabel = computed32(() => props.submitText || t("comment.submit"));
|
|
14624
|
+
const emptyLabel = computed32(() => props.emptyText || t("comment.empty"));
|
|
14625
|
+
const overLimit = computed32(() => content.value.length > props.maxLength);
|
|
14626
|
+
const canSubmit = computed32(() => content.value.trim().length > 0 && !overLimit.value && !props.disabled && !props.loading);
|
|
13932
14627
|
function onInput(event) {
|
|
13933
14628
|
content.value = event.target.value;
|
|
13934
14629
|
}
|
|
@@ -14243,7 +14938,7 @@ var signature_default = {
|
|
|
14243
14938
|
};
|
|
14244
14939
|
|
|
14245
14940
|
// src/components/print/index.js
|
|
14246
|
-
import { ref as ref46, computed as
|
|
14941
|
+
import { ref as ref46, computed as computed33 } from "vue";
|
|
14247
14942
|
function escapeHtml(text) {
|
|
14248
14943
|
return String(text).replace(/[&<>"]/g, (ch) => ({ "&": "&", "<": "<", ">": ">", '"': """ })[ch]);
|
|
14249
14944
|
}
|
|
@@ -14260,7 +14955,7 @@ var print_default = {
|
|
|
14260
14955
|
emits: ["before-print", "after-print"],
|
|
14261
14956
|
setup(props, { emit }) {
|
|
14262
14957
|
const content = ref46(null);
|
|
14263
|
-
const label =
|
|
14958
|
+
const label = computed33(() => props.buttonText || t("print.button"));
|
|
14264
14959
|
function collectStyles() {
|
|
14265
14960
|
return Array.from(document.querySelectorAll('link[rel="stylesheet"], style')).map((el) => el.outerHTML).join("");
|
|
14266
14961
|
}
|
|
@@ -14309,7 +15004,7 @@ var print_default = {
|
|
|
14309
15004
|
};
|
|
14310
15005
|
|
|
14311
15006
|
// src/components/gantt/index.js
|
|
14312
|
-
import { computed as
|
|
15007
|
+
import { computed as computed34 } from "vue";
|
|
14313
15008
|
var DAY = 864e5;
|
|
14314
15009
|
var pad6 = (value) => String(value).padStart(2, "0");
|
|
14315
15010
|
function parseDate3(value) {
|
|
@@ -14345,7 +15040,7 @@ var gantt_default = {
|
|
|
14345
15040
|
emits: ["task-click"],
|
|
14346
15041
|
setup(props, { emit }) {
|
|
14347
15042
|
const todayKey = toKey4(/* @__PURE__ */ new Date());
|
|
14348
|
-
const range =
|
|
15043
|
+
const range = computed34(() => {
|
|
14349
15044
|
const starts = props.tasks.map((task) => task.start).filter(Boolean).sort();
|
|
14350
15045
|
const ends = props.tasks.map((task) => task.end || task.start).filter(Boolean).sort();
|
|
14351
15046
|
let start = props.startDate || starts[0] || todayKey;
|
|
@@ -14358,7 +15053,7 @@ var gantt_default = {
|
|
|
14358
15053
|
}
|
|
14359
15054
|
return { start, end };
|
|
14360
15055
|
});
|
|
14361
|
-
const days =
|
|
15056
|
+
const days = computed34(() => {
|
|
14362
15057
|
const total = dayDiff(range.value.end, range.value.start) + 1;
|
|
14363
15058
|
const base = parseDate3(range.value.start);
|
|
14364
15059
|
return Array.from({ length: total }, (_, index) => {
|
|
@@ -14375,9 +15070,9 @@ var gantt_default = {
|
|
|
14375
15070
|
};
|
|
14376
15071
|
});
|
|
14377
15072
|
});
|
|
14378
|
-
const trackWidth =
|
|
14379
|
-
const innerWidth =
|
|
14380
|
-
const bars =
|
|
15073
|
+
const trackWidth = computed34(() => days.value.length * props.dayWidth);
|
|
15074
|
+
const innerWidth = computed34(() => props.nameWidth + trackWidth.value);
|
|
15075
|
+
const bars = computed34(
|
|
14381
15076
|
() => props.tasks.map((task, index) => {
|
|
14382
15077
|
const start = task.start || range.value.start;
|
|
14383
15078
|
const end = task.end || start;
|
|
@@ -14393,12 +15088,12 @@ var gantt_default = {
|
|
|
14393
15088
|
};
|
|
14394
15089
|
})
|
|
14395
15090
|
);
|
|
14396
|
-
const todayLeft =
|
|
15091
|
+
const todayLeft = computed34(() => {
|
|
14397
15092
|
const index = days.value.findIndex((day) => day.today);
|
|
14398
15093
|
if (index === -1) return null;
|
|
14399
15094
|
return props.nameWidth + index * props.dayWidth + props.dayWidth / 2;
|
|
14400
15095
|
});
|
|
14401
|
-
const emptyLabel =
|
|
15096
|
+
const emptyLabel = computed34(() => props.emptyText || t("gantt.empty"));
|
|
14402
15097
|
function onClick(bar) {
|
|
14403
15098
|
emit("task-click", bar.task);
|
|
14404
15099
|
}
|
|
@@ -14480,7 +15175,7 @@ var gantt_default = {
|
|
|
14480
15175
|
};
|
|
14481
15176
|
|
|
14482
15177
|
// src/components/field-list/index.js
|
|
14483
|
-
import { ref as ref47, computed as
|
|
15178
|
+
import { ref as ref47, computed as computed35, watch as watch35 } from "vue";
|
|
14484
15179
|
var uidSeed8 = 0;
|
|
14485
15180
|
var field_list_default = {
|
|
14486
15181
|
name: "DjmFieldList",
|
|
@@ -14511,10 +15206,10 @@ var field_list_default = {
|
|
|
14511
15206
|
syncUids();
|
|
14512
15207
|
watch35(() => props.modelValue.length, syncUids);
|
|
14513
15208
|
const errors = ref47({});
|
|
14514
|
-
const addLabel =
|
|
14515
|
-
const emptyLabel =
|
|
14516
|
-
const canAdd =
|
|
14517
|
-
const canRemove =
|
|
15209
|
+
const addLabel = computed35(() => props.addText || t("fieldList.add"));
|
|
15210
|
+
const emptyLabel = computed35(() => props.emptyText || t("fieldList.empty"));
|
|
15211
|
+
const canAdd = computed35(() => !props.disabled && (!props.max || props.modelValue.length < props.max));
|
|
15212
|
+
const canRemove = computed35(() => !props.disabled && props.modelValue.length > props.min);
|
|
14518
15213
|
function commit(list) {
|
|
14519
15214
|
emit("update:modelValue", list);
|
|
14520
15215
|
emit("change", list);
|
|
@@ -14676,7 +15371,7 @@ var field_list_default = {
|
|
|
14676
15371
|
};
|
|
14677
15372
|
|
|
14678
15373
|
// src/components/chat/index.js
|
|
14679
|
-
import { ref as ref48, computed as
|
|
15374
|
+
import { ref as ref48, computed as computed36, watch as watch36, nextTick as nextTick15 } from "vue";
|
|
14680
15375
|
var chat_default = {
|
|
14681
15376
|
name: "DjmChat",
|
|
14682
15377
|
components: { DjmAvatar: avatar_default },
|
|
@@ -14695,10 +15390,10 @@ var chat_default = {
|
|
|
14695
15390
|
setup(props, { emit }) {
|
|
14696
15391
|
const content = ref48("");
|
|
14697
15392
|
const listRef = ref48(null);
|
|
14698
|
-
const placeholderText =
|
|
14699
|
-
const sendLabel =
|
|
14700
|
-
const emptyLabel =
|
|
14701
|
-
const canSend =
|
|
15393
|
+
const placeholderText = computed36(() => props.placeholder || t("chat.placeholder"));
|
|
15394
|
+
const sendLabel = computed36(() => props.sendText || t("chat.send"));
|
|
15395
|
+
const emptyLabel = computed36(() => props.emptyText || t("chat.empty"));
|
|
15396
|
+
const canSend = computed36(() => content.value.trim().length > 0 && !props.disabled && !props.loading);
|
|
14702
15397
|
function scrollToBottom() {
|
|
14703
15398
|
const el = listRef.value;
|
|
14704
15399
|
if (el) el.scrollTop = el.scrollHeight;
|
|
@@ -14816,7 +15511,7 @@ var chat_default = {
|
|
|
14816
15511
|
};
|
|
14817
15512
|
|
|
14818
15513
|
// src/components/org-chart/index.js
|
|
14819
|
-
import { ref as ref49, computed as
|
|
15514
|
+
import { ref as ref49, computed as computed37, watch as watch37 } from "vue";
|
|
14820
15515
|
var org_chart_default = {
|
|
14821
15516
|
name: "DjmOrgChart",
|
|
14822
15517
|
components: { DjmAvatar: avatar_default, DjmIcon: icon_default },
|
|
@@ -14853,7 +15548,7 @@ var org_chart_default = {
|
|
|
14853
15548
|
watch37(() => props.data, (data) => {
|
|
14854
15549
|
collapsed.value = props.defaultExpandAll ? [] : collapsedByDefault(data);
|
|
14855
15550
|
});
|
|
14856
|
-
const layout =
|
|
15551
|
+
const layout = computed37(() => {
|
|
14857
15552
|
if (!props.data) return { nodes: [], links: [], width: 0, height: 0 };
|
|
14858
15553
|
const rowH = props.nodeHeight + props.verticalGap;
|
|
14859
15554
|
let cursor = 0;
|
|
@@ -14918,7 +15613,7 @@ var org_chart_default = {
|
|
|
14918
15613
|
function onClick(item) {
|
|
14919
15614
|
emit("node-click", item.node);
|
|
14920
15615
|
}
|
|
14921
|
-
const emptyLabel =
|
|
15616
|
+
const emptyLabel = computed37(() => props.emptyText || t("orgChart.empty"));
|
|
14922
15617
|
return {
|
|
14923
15618
|
layout,
|
|
14924
15619
|
toggle,
|
|
@@ -14979,7 +15674,7 @@ var org_chart_default = {
|
|
|
14979
15674
|
};
|
|
14980
15675
|
|
|
14981
15676
|
// src/components/page-tabs/index.js
|
|
14982
|
-
import { computed as
|
|
15677
|
+
import { computed as computed38 } from "vue";
|
|
14983
15678
|
var page_tabs_default = {
|
|
14984
15679
|
name: "DjmPageTabs",
|
|
14985
15680
|
components: { DjmIcon: icon_default },
|
|
@@ -14990,7 +15685,7 @@ var page_tabs_default = {
|
|
|
14990
15685
|
},
|
|
14991
15686
|
emits: ["update:modelValue", "change", "close"],
|
|
14992
15687
|
setup(props, { emit }) {
|
|
14993
|
-
const label =
|
|
15688
|
+
const label = computed38(() => t("pageTabs.label"));
|
|
14994
15689
|
function canClose(tab) {
|
|
14995
15690
|
return tab.closable === void 0 ? props.closable : tab.closable;
|
|
14996
15691
|
}
|
|
@@ -15243,7 +15938,7 @@ var components = [
|
|
|
15243
15938
|
org_chart_default,
|
|
15244
15939
|
page_tabs_default
|
|
15245
15940
|
];
|
|
15246
|
-
var version = "0.
|
|
15941
|
+
var version = "0.72.0";
|
|
15247
15942
|
function install(app, options = {}) {
|
|
15248
15943
|
if (options.locale) setLocale(options.locale);
|
|
15249
15944
|
components.forEach((component) => app.component(component.name, component));
|