djm-ui 0.67.4 → 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 +103 -0
- package/README.md +38 -2
- package/dist/djm-ui.cjs +1032 -347
- package/dist/djm-ui.cjs.map +4 -4
- package/dist/djm-ui.css +752 -17
- package/dist/djm-ui.esm.js +1105 -420
- package/dist/djm-ui.esm.js.map +4 -4
- package/dist/djm-ui.esm.min.js +373 -227
- package/dist/djm-ui.min.cjs +373 -227
- package/dist/djm-ui.min.css +2 -2
- package/dist/djm-ui.umd.js +944 -259
- package/dist/djm-ui.umd.min.js +373 -227
- 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/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 +326 -0
- 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",
|
|
@@ -1296,7 +1308,6 @@ var zh_CN_default = {
|
|
|
1296
1308
|
"richEditor.italic": "\u659C\u4F53",
|
|
1297
1309
|
"richEditor.underline": "\u4E0B\u5212\u7EBF",
|
|
1298
1310
|
"richEditor.strike": "\u5220\u9664\u7EBF",
|
|
1299
|
-
"richEditor.heading": "\u4E8C\u7EA7\u6807\u9898",
|
|
1300
1311
|
"richEditor.paragraph": "\u6B63\u6587",
|
|
1301
1312
|
"richEditor.bulletList": "\u65E0\u5E8F\u5217\u8868",
|
|
1302
1313
|
"richEditor.numberList": "\u6709\u5E8F\u5217\u8868",
|
|
@@ -1307,6 +1318,39 @@ var zh_CN_default = {
|
|
|
1307
1318
|
"richEditor.redo": "\u91CD\u505A",
|
|
1308
1319
|
"richEditor.source": "\u6E90\u7801",
|
|
1309
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",
|
|
1310
1354
|
"approval.start": "\u53D1\u8D77",
|
|
1311
1355
|
"approval.cc": "\u6284\u9001",
|
|
1312
1356
|
"approval.approved": "\u5DF2\u901A\u8FC7",
|
|
@@ -1515,7 +1559,6 @@ var en_US_default = {
|
|
|
1515
1559
|
"richEditor.italic": "Italic",
|
|
1516
1560
|
"richEditor.underline": "Underline",
|
|
1517
1561
|
"richEditor.strike": "Strikethrough",
|
|
1518
|
-
"richEditor.heading": "Heading 2",
|
|
1519
1562
|
"richEditor.paragraph": "Paragraph",
|
|
1520
1563
|
"richEditor.bulletList": "Bullet list",
|
|
1521
1564
|
"richEditor.numberList": "Numbered list",
|
|
@@ -1526,6 +1569,39 @@ var en_US_default = {
|
|
|
1526
1569
|
"richEditor.redo": "Redo",
|
|
1527
1570
|
"richEditor.source": "Source",
|
|
1528
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",
|
|
1529
1605
|
"approval.start": "Started",
|
|
1530
1606
|
"approval.cc": "CC",
|
|
1531
1607
|
"approval.approved": "Approved",
|
|
@@ -9344,7 +9420,199 @@ var tree_select_default = {
|
|
|
9344
9420
|
};
|
|
9345
9421
|
|
|
9346
9422
|
// src/components/rich-editor/index.js
|
|
9347
|
-
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
|
+
};
|
|
9348
9616
|
|
|
9349
9617
|
// src/utils/sanitize-html.js
|
|
9350
9618
|
var TAGS = /* @__PURE__ */ new Set([
|
|
@@ -9384,7 +9652,18 @@ var TAGS = /* @__PURE__ */ new Set([
|
|
|
9384
9652
|
"th",
|
|
9385
9653
|
"td"
|
|
9386
9654
|
]);
|
|
9387
|
-
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
|
+
]);
|
|
9388
9667
|
var TAG_ATTRS = {
|
|
9389
9668
|
a: /* @__PURE__ */ new Set(["href", "target", "rel"]),
|
|
9390
9669
|
img: /* @__PURE__ */ new Set(["src", "alt", "width", "height"]),
|
|
@@ -9392,11 +9671,29 @@ var TAG_ATTRS = {
|
|
|
9392
9671
|
th: /* @__PURE__ */ new Set(["colspan", "rowspan", "scope"]),
|
|
9393
9672
|
td: /* @__PURE__ */ new Set(["colspan", "rowspan"])
|
|
9394
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"]);
|
|
9395
9686
|
function safeUrl(value, tag) {
|
|
9396
|
-
const url = String(value || "").replace(/[\u0000-\u0020]+/g, "")
|
|
9397
|
-
|
|
9398
|
-
if (
|
|
9399
|
-
|
|
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;
|
|
9400
9697
|
}
|
|
9401
9698
|
function cleanNode(node) {
|
|
9402
9699
|
const children = [...node.childNodes];
|
|
@@ -9419,6 +9716,12 @@ function cleanNode(node) {
|
|
|
9419
9716
|
child.removeAttribute(attr.name);
|
|
9420
9717
|
return;
|
|
9421
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
|
+
}
|
|
9422
9725
|
if ((name === "href" || name === "src") && !safeUrl(attr.value, tag)) {
|
|
9423
9726
|
child.removeAttribute(attr.name);
|
|
9424
9727
|
}
|
|
@@ -9439,79 +9742,475 @@ function sanitizeHtml(html) {
|
|
|
9439
9742
|
}
|
|
9440
9743
|
|
|
9441
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
|
+
}
|
|
9442
9783
|
var rich_editor_default = {
|
|
9443
9784
|
name: "DjmRichEditor",
|
|
9444
|
-
components: { Icon: icon_default },
|
|
9785
|
+
components: { Icon: icon_default, MediaPicker: media_picker_default },
|
|
9445
9786
|
props: {
|
|
9446
9787
|
modelValue: { type: String, default: "" },
|
|
9447
9788
|
placeholder: { type: String, default: "" },
|
|
9448
9789
|
minHeight: { type: Number, default: 200 },
|
|
9449
|
-
//
|
|
9450
|
-
sanitize: { type: Boolean, default:
|
|
9451
|
-
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 }
|
|
9452
9805
|
},
|
|
9453
|
-
emits: ["update:modelValue"],
|
|
9806
|
+
emits: ["update:modelValue", "upload-error"],
|
|
9454
9807
|
setup(props, { emit }) {
|
|
9455
|
-
const editor =
|
|
9456
|
-
const
|
|
9457
|
-
const
|
|
9458
|
-
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
|
+
);
|
|
9459
9851
|
function clean(html) {
|
|
9460
9852
|
return props.sanitize ? sanitizeHtml(html) : html;
|
|
9461
9853
|
}
|
|
9854
|
+
function plainText(html) {
|
|
9855
|
+
return String(html || "").replace(/<[^>]*>/g, "").replace(/ /g, " ").replace(/&[a-z]+;/gi, " ");
|
|
9856
|
+
}
|
|
9462
9857
|
function syncFromDom() {
|
|
9463
9858
|
if (!editor.value) return;
|
|
9464
|
-
|
|
9859
|
+
const html = clean(editor.value.innerHTML);
|
|
9860
|
+
count2.value = plainText(html).trim().length;
|
|
9861
|
+
emit("update:modelValue", html);
|
|
9465
9862
|
}
|
|
9466
|
-
function
|
|
9467
|
-
const
|
|
9468
|
-
|
|
9469
|
-
|
|
9470
|
-
|
|
9471
|
-
|
|
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);
|
|
9472
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();
|
|
9473
9902
|
}
|
|
9474
9903
|
function exec(command, value = null) {
|
|
9475
|
-
if (
|
|
9904
|
+
if (!ready.value) return;
|
|
9905
|
+
if (typeof document.execCommand !== "function") return;
|
|
9906
|
+
ensureRange();
|
|
9907
|
+
document.execCommand("styleWithCSS", false, true);
|
|
9476
9908
|
document.execCommand(command, false, value);
|
|
9477
9909
|
if (editor.value) editor.value.focus();
|
|
9478
9910
|
syncFromDom();
|
|
9479
9911
|
syncFormats();
|
|
9480
9912
|
}
|
|
9481
|
-
function
|
|
9482
|
-
|
|
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();
|
|
9483
9994
|
}
|
|
9484
9995
|
function addLink() {
|
|
9996
|
+
if (!ready.value) return;
|
|
9485
9997
|
const url = window.prompt(t("richEditor.linkPrompt"), "https://");
|
|
9486
|
-
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();
|
|
10021
|
+
}
|
|
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
|
+
});
|
|
10029
|
+
}
|
|
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";
|
|
9487
10163
|
}
|
|
9488
10164
|
function syncFormats() {
|
|
9489
|
-
if (props.disabled || sourceMode.value) return;
|
|
9490
|
-
if (!editor.value
|
|
10165
|
+
if (props.disabled || sourceMode.value || !editor.value) return;
|
|
10166
|
+
if (!editor.value.contains(document.activeElement)) return;
|
|
10167
|
+
const selection = window.getSelection();
|
|
9491
10168
|
formats.value = {
|
|
9492
10169
|
bold: document.queryCommandState("bold"),
|
|
9493
10170
|
italic: document.queryCommandState("italic"),
|
|
9494
10171
|
underline: document.queryCommandState("underline"),
|
|
9495
|
-
strike: document.queryCommandState("strikeThrough")
|
|
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" : ""
|
|
9496
10177
|
};
|
|
9497
10178
|
}
|
|
9498
10179
|
function onSourceInput() {
|
|
10180
|
+
count2.value = plainText(source.value).trim().length;
|
|
9499
10181
|
emit("update:modelValue", clean(source.value));
|
|
9500
10182
|
}
|
|
9501
10183
|
function toggleSource() {
|
|
9502
10184
|
if (props.disabled) return;
|
|
10185
|
+
panel.value = "";
|
|
9503
10186
|
if (sourceMode.value) {
|
|
9504
10187
|
emit("update:modelValue", clean(source.value));
|
|
9505
10188
|
sourceMode.value = false;
|
|
9506
10189
|
requestAnimationFrame(() => {
|
|
9507
10190
|
if (editor.value) editor.value.innerHTML = clean(source.value);
|
|
10191
|
+
syncFromDom();
|
|
9508
10192
|
});
|
|
9509
10193
|
} else {
|
|
9510
10194
|
source.value = editor.value ? editor.value.innerHTML : props.modelValue;
|
|
9511
10195
|
sourceMode.value = true;
|
|
9512
10196
|
}
|
|
9513
10197
|
}
|
|
9514
|
-
|
|
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(
|
|
9515
10214
|
() => props.modelValue,
|
|
9516
10215
|
(value) => {
|
|
9517
10216
|
if (sourceMode.value) {
|
|
@@ -9520,40 +10219,117 @@ var rich_editor_default = {
|
|
|
9520
10219
|
}
|
|
9521
10220
|
const next = clean(value);
|
|
9522
10221
|
if (editor.value && editor.value.innerHTML !== next) editor.value.innerHTML = next;
|
|
10222
|
+
count2.value = plainText(next).trim().length;
|
|
9523
10223
|
}
|
|
9524
10224
|
);
|
|
9525
10225
|
onMounted15(() => {
|
|
9526
10226
|
if (editor.value) editor.value.innerHTML = clean(props.modelValue);
|
|
10227
|
+
count2.value = plainText(props.modelValue).trim().length;
|
|
9527
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);
|
|
9528
10236
|
});
|
|
9529
|
-
onBeforeUnmount23(() => document.removeEventListener("selectionchange", syncFormats));
|
|
9530
10237
|
return {
|
|
9531
10238
|
editor,
|
|
10239
|
+
fileInput,
|
|
9532
10240
|
sourceMode,
|
|
9533
10241
|
source,
|
|
10242
|
+
fullscreen,
|
|
10243
|
+
panel,
|
|
10244
|
+
uploadCount,
|
|
10245
|
+
textColor,
|
|
10246
|
+
bgColor,
|
|
10247
|
+
fontSize,
|
|
10248
|
+
count: count2,
|
|
9534
10249
|
formats,
|
|
10250
|
+
blocks: BLOCKS,
|
|
10251
|
+
sizes: SIZES,
|
|
10252
|
+
colors: COLORS,
|
|
10253
|
+
mediaLibrary,
|
|
10254
|
+
has,
|
|
9535
10255
|
exec,
|
|
9536
|
-
|
|
10256
|
+
setBlock,
|
|
10257
|
+
setFontSize,
|
|
10258
|
+
applyColor,
|
|
10259
|
+
togglePanel,
|
|
10260
|
+
toggleInlineCode,
|
|
9537
10261
|
addLink,
|
|
9538
|
-
|
|
10262
|
+
pickImage,
|
|
10263
|
+
insertMedia,
|
|
10264
|
+
onFilesChange,
|
|
9539
10265
|
onPaste,
|
|
10266
|
+
onDragOver,
|
|
10267
|
+
onDrop,
|
|
10268
|
+
rememberRange,
|
|
10269
|
+
onSourceInput,
|
|
9540
10270
|
toggleSource,
|
|
10271
|
+
toggleFullscreen,
|
|
9541
10272
|
syncFromDom,
|
|
9542
10273
|
syncFormats,
|
|
9543
10274
|
t
|
|
9544
10275
|
};
|
|
9545
10276
|
},
|
|
9546
10277
|
template: `
|
|
9547
|
-
<div
|
|
9548
|
-
|
|
9549
|
-
|
|
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')">
|
|
9550
10326
|
<button
|
|
9551
10327
|
class="djm-rich-editor-btn djm-rich-editor-btn-bold"
|
|
9552
10328
|
type="button"
|
|
9553
10329
|
:title="t('richEditor.bold')"
|
|
9554
10330
|
:aria-label="t('richEditor.bold')"
|
|
9555
10331
|
:aria-pressed="String(formats.bold)"
|
|
9556
|
-
:disabled="disabled"
|
|
10332
|
+
:disabled="disabled || sourceMode"
|
|
9557
10333
|
@mousedown.prevent
|
|
9558
10334
|
@click="exec('bold')"
|
|
9559
10335
|
>B</button>
|
|
@@ -9563,7 +10339,7 @@ var rich_editor_default = {
|
|
|
9563
10339
|
:title="t('richEditor.italic')"
|
|
9564
10340
|
:aria-label="t('richEditor.italic')"
|
|
9565
10341
|
:aria-pressed="String(formats.italic)"
|
|
9566
|
-
:disabled="disabled"
|
|
10342
|
+
:disabled="disabled || sourceMode"
|
|
9567
10343
|
@mousedown.prevent
|
|
9568
10344
|
@click="exec('italic')"
|
|
9569
10345
|
>I</button>
|
|
@@ -9573,7 +10349,7 @@ var rich_editor_default = {
|
|
|
9573
10349
|
:title="t('richEditor.underline')"
|
|
9574
10350
|
:aria-label="t('richEditor.underline')"
|
|
9575
10351
|
:aria-pressed="String(formats.underline)"
|
|
9576
|
-
:disabled="disabled"
|
|
10352
|
+
:disabled="disabled || sourceMode"
|
|
9577
10353
|
@mousedown.prevent
|
|
9578
10354
|
@click="exec('underline')"
|
|
9579
10355
|
>U</button>
|
|
@@ -9583,46 +10359,130 @@ var rich_editor_default = {
|
|
|
9583
10359
|
:title="t('richEditor.strike')"
|
|
9584
10360
|
:aria-label="t('richEditor.strike')"
|
|
9585
10361
|
:aria-pressed="String(formats.strike)"
|
|
9586
|
-
:disabled="disabled"
|
|
10362
|
+
:disabled="disabled || sourceMode"
|
|
9587
10363
|
@mousedown.prevent
|
|
9588
10364
|
@click="exec('strikeThrough')"
|
|
9589
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>
|
|
9590
10376
|
</div>
|
|
9591
10377
|
|
|
9592
|
-
<div class="djm-rich-editor-group">
|
|
9593
|
-
<button
|
|
9594
|
-
|
|
9595
|
-
|
|
9596
|
-
|
|
9597
|
-
|
|
9598
|
-
|
|
9599
|
-
|
|
9600
|
-
|
|
9601
|
-
|
|
9602
|
-
|
|
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>
|
|
9603
10390
|
</button>
|
|
9604
|
-
<button
|
|
9605
|
-
|
|
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>
|
|
9606
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>
|
|
9607
10416
|
</div>
|
|
9608
10417
|
|
|
9609
|
-
<div class="djm-rich-editor-group">
|
|
9610
|
-
<button class="djm-rich-editor-btn" type="button" :title="t('richEditor.
|
|
9611
|
-
<button class="djm-rich-editor-btn" type="button" :title="t('richEditor.
|
|
9612
|
-
<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>
|
|
9613
10423
|
</div>
|
|
9614
10424
|
|
|
9615
|
-
<div class="djm-rich-editor-
|
|
9616
|
-
|
|
9617
|
-
class="djm-rich-editor-btn"
|
|
9618
|
-
|
|
9619
|
-
type="button"
|
|
9620
|
-
|
|
9621
|
-
|
|
9622
|
-
|
|
9623
|
-
|
|
9624
|
-
<
|
|
9625
|
-
|
|
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>
|
|
9626
10486
|
</div>
|
|
9627
10487
|
|
|
9628
10488
|
<div
|
|
@@ -9638,6 +10498,8 @@ var rich_editor_default = {
|
|
|
9638
10498
|
:style="{ minHeight: minHeight + 'px' }"
|
|
9639
10499
|
@input="syncFromDom"
|
|
9640
10500
|
@paste="onPaste"
|
|
10501
|
+
@dragover="onDragOver"
|
|
10502
|
+
@drop="onDrop"
|
|
9641
10503
|
></div>
|
|
9642
10504
|
|
|
9643
10505
|
<textarea
|
|
@@ -9650,12 +10512,27 @@ var rich_editor_default = {
|
|
|
9650
10512
|
spellcheck="false"
|
|
9651
10513
|
@input="onSourceInput"
|
|
9652
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
|
+
/>
|
|
9653
10530
|
</div>
|
|
9654
10531
|
`
|
|
9655
10532
|
};
|
|
9656
10533
|
|
|
9657
10534
|
// src/components/floating-window/index.js
|
|
9658
|
-
import { ref as
|
|
10535
|
+
import { ref as ref29, onBeforeUnmount as onBeforeUnmount24 } from "vue";
|
|
9659
10536
|
function clamp(value, min, max) {
|
|
9660
10537
|
return Math.min(Math.max(value, min), Math.max(min, max));
|
|
9661
10538
|
}
|
|
@@ -9673,12 +10550,12 @@ var floating_window_default = {
|
|
|
9673
10550
|
},
|
|
9674
10551
|
emits: ["close", "focus"],
|
|
9675
10552
|
setup(props, { emit }) {
|
|
9676
|
-
const root =
|
|
9677
|
-
const pos =
|
|
9678
|
-
const size =
|
|
9679
|
-
const minimized =
|
|
9680
|
-
const maximized =
|
|
9681
|
-
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);
|
|
9682
10559
|
let drag = null;
|
|
9683
10560
|
let resize = null;
|
|
9684
10561
|
function stage() {
|
|
@@ -9814,7 +10691,7 @@ var floating_window_default = {
|
|
|
9814
10691
|
};
|
|
9815
10692
|
|
|
9816
10693
|
// src/components/upload/index.js
|
|
9817
|
-
import { reactive as reactive4, ref as
|
|
10694
|
+
import { reactive as reactive4, ref as ref30, watch as watch21, onBeforeUnmount as onBeforeUnmount25 } from "vue";
|
|
9818
10695
|
var uidSeed6 = 0;
|
|
9819
10696
|
function extension(name) {
|
|
9820
10697
|
const index = name.lastIndexOf(".");
|
|
@@ -9864,11 +10741,11 @@ var upload_default = {
|
|
|
9864
10741
|
},
|
|
9865
10742
|
emits: ["update:modelValue", "change", "success", "error", "remove", "exceed"],
|
|
9866
10743
|
setup(props, { emit }) {
|
|
9867
|
-
const files =
|
|
9868
|
-
const dragActive =
|
|
9869
|
-
const inputRef =
|
|
10744
|
+
const files = ref30([]);
|
|
10745
|
+
const dragActive = ref30(false);
|
|
10746
|
+
const inputRef = ref30(null);
|
|
9870
10747
|
const tasks = /* @__PURE__ */ new Map();
|
|
9871
|
-
|
|
10748
|
+
watch21(
|
|
9872
10749
|
() => props.modelValue,
|
|
9873
10750
|
(list) => {
|
|
9874
10751
|
const next = list || [];
|
|
@@ -10170,7 +11047,7 @@ var upload_default = {
|
|
|
10170
11047
|
};
|
|
10171
11048
|
|
|
10172
11049
|
// src/components/tree/index.js
|
|
10173
|
-
import { computed as
|
|
11050
|
+
import { computed as computed18, ref as ref31, watch as watch22 } from "vue";
|
|
10174
11051
|
var tree_default = {
|
|
10175
11052
|
name: "DjmTree",
|
|
10176
11053
|
components: { Icon: icon_default },
|
|
@@ -10202,17 +11079,17 @@ var tree_default = {
|
|
|
10202
11079
|
},
|
|
10203
11080
|
emits: ["update:checked", "update:expanded", "node-click", "check", "node-drop", "load-error"],
|
|
10204
11081
|
setup(props, { emit }) {
|
|
10205
|
-
const lazyChildren =
|
|
10206
|
-
const loadingKeys =
|
|
10207
|
-
const innerExpanded =
|
|
10208
|
-
const innerChecked =
|
|
10209
|
-
|
|
11082
|
+
const lazyChildren = ref31({});
|
|
11083
|
+
const loadingKeys = ref31([]);
|
|
11084
|
+
const innerExpanded = ref31([...props.expanded]);
|
|
11085
|
+
const innerChecked = ref31([...props.checked]);
|
|
11086
|
+
watch22(
|
|
10210
11087
|
() => props.expanded,
|
|
10211
11088
|
(value) => {
|
|
10212
11089
|
if (Array.isArray(value)) innerExpanded.value = value;
|
|
10213
11090
|
}
|
|
10214
11091
|
);
|
|
10215
|
-
|
|
11092
|
+
watch22(
|
|
10216
11093
|
() => props.checked,
|
|
10217
11094
|
(value) => {
|
|
10218
11095
|
if (Array.isArray(value)) innerChecked.value = value;
|
|
@@ -10250,7 +11127,7 @@ var tree_default = {
|
|
|
10250
11127
|
});
|
|
10251
11128
|
return out;
|
|
10252
11129
|
}
|
|
10253
|
-
|
|
11130
|
+
watch22(
|
|
10254
11131
|
() => props.data,
|
|
10255
11132
|
() => {
|
|
10256
11133
|
if (props.defaultExpandAll) innerExpanded.value = collectExpandable(props.data);
|
|
@@ -10267,7 +11144,7 @@ var tree_default = {
|
|
|
10267
11144
|
const children = childrenOf(node);
|
|
10268
11145
|
return Boolean(children && children.some((child) => matchSubtree(child)));
|
|
10269
11146
|
}
|
|
10270
|
-
const rows =
|
|
11147
|
+
const rows = computed18(() => {
|
|
10271
11148
|
const result = [];
|
|
10272
11149
|
const walk = (nodes, level) => {
|
|
10273
11150
|
nodes.forEach((node) => {
|
|
@@ -10338,8 +11215,8 @@ var tree_default = {
|
|
|
10338
11215
|
function isActive(node) {
|
|
10339
11216
|
return props.activeKey !== "" && node[props.nodeKey] === props.activeKey;
|
|
10340
11217
|
}
|
|
10341
|
-
const rootEl =
|
|
10342
|
-
const focusIndex =
|
|
11218
|
+
const rootEl = ref31(null);
|
|
11219
|
+
const focusIndex = ref31(-1);
|
|
10343
11220
|
function tabIndexOf(index) {
|
|
10344
11221
|
return (focusIndex.value === -1 ? 0 : focusIndex.value) === index ? 0 : -1;
|
|
10345
11222
|
}
|
|
@@ -10396,9 +11273,9 @@ var tree_default = {
|
|
|
10396
11273
|
function rowClassOf(node, level) {
|
|
10397
11274
|
return typeof props.rowClass === "function" ? props.rowClass(node, level) : props.rowClass;
|
|
10398
11275
|
}
|
|
10399
|
-
const dragKey =
|
|
10400
|
-
const dropKey =
|
|
10401
|
-
const dropPosition =
|
|
11276
|
+
const dragKey = ref31("");
|
|
11277
|
+
const dropKey = ref31("");
|
|
11278
|
+
const dropPosition = ref31("");
|
|
10402
11279
|
function findNodeByKey(key, nodes = props.data) {
|
|
10403
11280
|
for (const node of nodes) {
|
|
10404
11281
|
if (node[props.nodeKey] === key) return node;
|
|
@@ -10510,7 +11387,7 @@ var tree_default = {
|
|
|
10510
11387
|
onDrop,
|
|
10511
11388
|
onDragEnd,
|
|
10512
11389
|
labelOf,
|
|
10513
|
-
emptyLabel:
|
|
11390
|
+
emptyLabel: computed18(() => props.emptyText || t("tree.empty")),
|
|
10514
11391
|
t
|
|
10515
11392
|
};
|
|
10516
11393
|
},
|
|
@@ -10579,7 +11456,7 @@ var tree_default = {
|
|
|
10579
11456
|
};
|
|
10580
11457
|
|
|
10581
11458
|
// src/components/editable-table/index.js
|
|
10582
|
-
import { computed as
|
|
11459
|
+
import { computed as computed19, nextTick as nextTick14, reactive as reactive5, ref as ref32, useSlots, watch as watch23 } from "vue";
|
|
10583
11460
|
var ACTIONS_KEY = "__editable_actions";
|
|
10584
11461
|
function isEmpty(value) {
|
|
10585
11462
|
if (value === "" || value === null || value === void 0) return true;
|
|
@@ -10603,12 +11480,12 @@ var editable_table_default = {
|
|
|
10603
11480
|
emits: ["edit", "save", "cancel"],
|
|
10604
11481
|
setup(props, { emit }) {
|
|
10605
11482
|
const slots = useSlots();
|
|
10606
|
-
const editingKey =
|
|
11483
|
+
const editingKey = ref32("");
|
|
10607
11484
|
const draft = reactive5({});
|
|
10608
11485
|
const errors = reactive5({});
|
|
10609
|
-
const tableRef =
|
|
10610
|
-
const editableColumns =
|
|
10611
|
-
const renderColumns =
|
|
11486
|
+
const tableRef = ref32(null);
|
|
11487
|
+
const editableColumns = computed19(() => props.columns.filter((column) => column.editor));
|
|
11488
|
+
const renderColumns = computed19(() => {
|
|
10612
11489
|
if (!props.showActions) return props.columns;
|
|
10613
11490
|
return props.columns.concat({
|
|
10614
11491
|
key: ACTIONS_KEY,
|
|
@@ -10620,7 +11497,7 @@ var editable_table_default = {
|
|
|
10620
11497
|
exportable: false
|
|
10621
11498
|
});
|
|
10622
11499
|
});
|
|
10623
|
-
const forwardedSlotNames =
|
|
11500
|
+
const forwardedSlotNames = computed19(() => {
|
|
10624
11501
|
const taken = new Set(editableColumns.value.map((column) => "cell-" + column.key));
|
|
10625
11502
|
taken.add("cell-" + ACTIONS_KEY);
|
|
10626
11503
|
return Object.keys(slots).filter((name) => !taken.has(name));
|
|
@@ -10715,7 +11592,7 @@ var editable_table_default = {
|
|
|
10715
11592
|
clearErrors();
|
|
10716
11593
|
return true;
|
|
10717
11594
|
}
|
|
10718
|
-
|
|
11595
|
+
watch23(
|
|
10719
11596
|
() => props.rows,
|
|
10720
11597
|
() => {
|
|
10721
11598
|
if (editingKey.value && !findRow(editingKey.value)) {
|
|
@@ -10897,7 +11774,7 @@ var message_default = {
|
|
|
10897
11774
|
};
|
|
10898
11775
|
|
|
10899
11776
|
// src/components/org-picker/index.js
|
|
10900
|
-
import { computed as
|
|
11777
|
+
import { computed as computed20, onBeforeUnmount as onBeforeUnmount26, ref as ref33, watch as watch24 } from "vue";
|
|
10901
11778
|
var org_picker_default = {
|
|
10902
11779
|
name: "DjmOrgPicker",
|
|
10903
11780
|
components: { DjmIcon: icon_default },
|
|
@@ -10916,13 +11793,13 @@ var org_picker_default = {
|
|
|
10916
11793
|
},
|
|
10917
11794
|
emits: ["update:modelValue", "change", "visible-change"],
|
|
10918
11795
|
setup(props, { emit }) {
|
|
10919
|
-
const open =
|
|
10920
|
-
const root =
|
|
10921
|
-
const searchRef =
|
|
10922
|
-
const keyword =
|
|
10923
|
-
const activeDept =
|
|
10924
|
-
const temp =
|
|
10925
|
-
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());
|
|
10926
11803
|
let detachPanel = null;
|
|
10927
11804
|
function collectDeptIds(nodes, out = []) {
|
|
10928
11805
|
nodes.forEach((node) => {
|
|
@@ -10952,22 +11829,22 @@ var org_picker_default = {
|
|
|
10952
11829
|
walk([root2]);
|
|
10953
11830
|
return ids;
|
|
10954
11831
|
}
|
|
10955
|
-
const staffMap =
|
|
11832
|
+
const staffMap = computed20(() => {
|
|
10956
11833
|
const map = /* @__PURE__ */ new Map();
|
|
10957
11834
|
props.staff.forEach((item) => map.set(item.id, item));
|
|
10958
11835
|
return map;
|
|
10959
11836
|
});
|
|
10960
|
-
const appliedStaff =
|
|
11837
|
+
const appliedStaff = computed20(
|
|
10961
11838
|
() => props.modelValue.map((id) => staffMap.value.get(id)).filter(Boolean)
|
|
10962
11839
|
);
|
|
10963
|
-
const visibleTags =
|
|
11840
|
+
const visibleTags = computed20(() => {
|
|
10964
11841
|
if (props.maxTagCount <= 0) return appliedStaff.value;
|
|
10965
11842
|
return appliedStaff.value.slice(0, props.maxTagCount);
|
|
10966
11843
|
});
|
|
10967
|
-
const restTagCount =
|
|
11844
|
+
const restTagCount = computed20(
|
|
10968
11845
|
() => Math.max(0, appliedStaff.value.length - visibleTags.value.length)
|
|
10969
11846
|
);
|
|
10970
|
-
const visibleStaff =
|
|
11847
|
+
const visibleStaff = computed20(() => {
|
|
10971
11848
|
const key = keyword.value.trim().toLowerCase();
|
|
10972
11849
|
if (key) {
|
|
10973
11850
|
return props.staff.filter(
|
|
@@ -10978,7 +11855,7 @@ var org_picker_default = {
|
|
|
10978
11855
|
const scope = deptScope(activeDept.value);
|
|
10979
11856
|
return props.staff.filter((item) => scope.has(item.deptId));
|
|
10980
11857
|
});
|
|
10981
|
-
const deptRows =
|
|
11858
|
+
const deptRows = computed20(() => {
|
|
10982
11859
|
const rows = [];
|
|
10983
11860
|
const walk = (nodes, depth) => {
|
|
10984
11861
|
nodes.forEach((node) => {
|
|
@@ -10990,11 +11867,11 @@ var org_picker_default = {
|
|
|
10990
11867
|
walk(props.departments, 0);
|
|
10991
11868
|
return rows;
|
|
10992
11869
|
});
|
|
10993
|
-
const selectedCount =
|
|
10994
|
-
const placeholderText =
|
|
10995
|
-
const emptyLabel =
|
|
10996
|
-
const panel =
|
|
10997
|
-
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 });
|
|
10998
11875
|
const PANEL_HEIGHT = 342;
|
|
10999
11876
|
function updatePosition() {
|
|
11000
11877
|
if (!open.value || !root.value) return;
|
|
@@ -11011,7 +11888,7 @@ var org_picker_default = {
|
|
|
11011
11888
|
expandedIds.value = new Set(collectDeptIds(props.departments));
|
|
11012
11889
|
}
|
|
11013
11890
|
expandAll();
|
|
11014
|
-
|
|
11891
|
+
watch24(() => props.departments, () => {
|
|
11015
11892
|
expandedIds.value = /* @__PURE__ */ new Set([...expandedIds.value, ...collectDeptIds(props.departments)]);
|
|
11016
11893
|
});
|
|
11017
11894
|
function initialOf(item) {
|
|
@@ -11286,7 +12163,7 @@ var org_picker_default = {
|
|
|
11286
12163
|
};
|
|
11287
12164
|
|
|
11288
12165
|
// src/components/schema-form/index.js
|
|
11289
|
-
import { computed as
|
|
12166
|
+
import { computed as computed21, reactive as reactive7, ref as ref34, watch as watch25 } from "vue";
|
|
11290
12167
|
var CONTROL_MAP = {
|
|
11291
12168
|
input: input_default,
|
|
11292
12169
|
number: input_number_default,
|
|
@@ -11322,26 +12199,26 @@ var schema_form_default = {
|
|
|
11322
12199
|
},
|
|
11323
12200
|
emits: ["update:modelValue", "change"],
|
|
11324
12201
|
setup(props, { emit }) {
|
|
11325
|
-
const innerForm =
|
|
12202
|
+
const innerForm = ref34(null);
|
|
11326
12203
|
const model = reactive7({ ...props.modelValue });
|
|
11327
|
-
|
|
12204
|
+
watch25(() => props.fields, (fields) => {
|
|
11328
12205
|
fields.forEach((field) => {
|
|
11329
12206
|
if (model[field.key] === void 0 && field.default !== void 0) {
|
|
11330
12207
|
model[field.key] = typeof field.default === "function" ? field.default() : field.default;
|
|
11331
12208
|
}
|
|
11332
12209
|
});
|
|
11333
12210
|
}, { immediate: true, deep: true });
|
|
11334
|
-
|
|
12211
|
+
watch25(() => props.modelValue, (value) => {
|
|
11335
12212
|
if (!value) return;
|
|
11336
12213
|
Object.keys(value).forEach((key) => {
|
|
11337
12214
|
if (model[key] !== value[key]) model[key] = value[key];
|
|
11338
12215
|
});
|
|
11339
12216
|
}, { deep: true });
|
|
11340
|
-
|
|
12217
|
+
watch25(model, () => {
|
|
11341
12218
|
emit("update:modelValue", { ...model });
|
|
11342
12219
|
emit("change", { ...model });
|
|
11343
12220
|
}, { deep: true });
|
|
11344
|
-
const formRules =
|
|
12221
|
+
const formRules = computed21(() => {
|
|
11345
12222
|
const merged = { ...props.rules };
|
|
11346
12223
|
props.fields.forEach((field) => {
|
|
11347
12224
|
if (!field.required && !field.rules) return;
|
|
@@ -11354,7 +12231,7 @@ var schema_form_default = {
|
|
|
11354
12231
|
});
|
|
11355
12232
|
return merged;
|
|
11356
12233
|
});
|
|
11357
|
-
const visibleFields =
|
|
12234
|
+
const visibleFields = computed21(
|
|
11358
12235
|
() => props.fields.filter((field) => {
|
|
11359
12236
|
if (typeof field.visibleWhen !== "function") return true;
|
|
11360
12237
|
return Boolean(field.visibleWhen(model));
|
|
@@ -11548,7 +12425,7 @@ var approval_flow_default = {
|
|
|
11548
12425
|
};
|
|
11549
12426
|
|
|
11550
12427
|
// src/components/query-filter/index.js
|
|
11551
|
-
import { computed as
|
|
12428
|
+
import { computed as computed22, reactive as reactive8, ref as ref35, watch as watch26 } from "vue";
|
|
11552
12429
|
var CONTROL_MAP2 = {
|
|
11553
12430
|
input: input_default,
|
|
11554
12431
|
number: input_number_default,
|
|
@@ -11573,26 +12450,26 @@ var query_filter_default = {
|
|
|
11573
12450
|
},
|
|
11574
12451
|
emits: ["update:modelValue", "search", "reset"],
|
|
11575
12452
|
setup(props, { emit }) {
|
|
11576
|
-
const expanded =
|
|
12453
|
+
const expanded = ref35(false);
|
|
11577
12454
|
const model = reactive8({ ...props.modelValue });
|
|
11578
|
-
|
|
12455
|
+
watch26(() => props.fields, (fields) => {
|
|
11579
12456
|
fields.forEach((field) => {
|
|
11580
12457
|
if (model[field.key] === void 0 && field.default !== void 0) {
|
|
11581
12458
|
model[field.key] = typeof field.default === "function" ? field.default() : field.default;
|
|
11582
12459
|
}
|
|
11583
12460
|
});
|
|
11584
12461
|
}, { immediate: true, deep: true });
|
|
11585
|
-
|
|
12462
|
+
watch26(() => props.modelValue, (value) => {
|
|
11586
12463
|
if (!value) return;
|
|
11587
12464
|
Object.keys(value).forEach((key) => {
|
|
11588
12465
|
if (model[key] !== value[key]) model[key] = value[key];
|
|
11589
12466
|
});
|
|
11590
12467
|
}, { deep: true });
|
|
11591
|
-
|
|
12468
|
+
watch26(model, () => {
|
|
11592
12469
|
emit("update:modelValue", { ...model });
|
|
11593
12470
|
}, { deep: true });
|
|
11594
|
-
const collapsible =
|
|
11595
|
-
const visibleFields =
|
|
12471
|
+
const collapsible = computed22(() => props.fields.length > props.visibleCount);
|
|
12472
|
+
const visibleFields = computed22(() => {
|
|
11596
12473
|
if (!collapsible.value || expanded.value) return props.fields;
|
|
11597
12474
|
return props.fields.slice(0, props.visibleCount);
|
|
11598
12475
|
});
|
|
@@ -11721,198 +12598,6 @@ var filter_tags_default = {
|
|
|
11721
12598
|
`
|
|
11722
12599
|
};
|
|
11723
12600
|
|
|
11724
|
-
// src/components/media-picker/index.js
|
|
11725
|
-
import { computed as computed21, ref as ref35, watch as watch26 } from "vue";
|
|
11726
|
-
var media_picker_default = {
|
|
11727
|
-
name: "DjmMediaPicker",
|
|
11728
|
-
components: { DjmModal: modal_default, DjmPagination: pagination_default, DjmIcon: icon_default },
|
|
11729
|
-
props: {
|
|
11730
|
-
modelValue: { type: [Array, String, Number], default: "" },
|
|
11731
|
-
items: { type: Array, default: () => [] },
|
|
11732
|
-
multiple: { type: Boolean, default: false },
|
|
11733
|
-
// 最多选几个,0 表示不限
|
|
11734
|
-
limit: { type: Number, default: 0 },
|
|
11735
|
-
// image 只显示图片,file 只显示非图片,空串不过滤
|
|
11736
|
-
accept: { type: String, default: "" },
|
|
11737
|
-
title: { type: String, default: "" },
|
|
11738
|
-
triggerText: { type: String, default: "" },
|
|
11739
|
-
pageSize: { type: Number, default: 12 },
|
|
11740
|
-
disabled: { type: Boolean, default: false }
|
|
11741
|
-
},
|
|
11742
|
-
emits: ["update:modelValue", "change"],
|
|
11743
|
-
setup(props, { emit }) {
|
|
11744
|
-
const open = ref35(false);
|
|
11745
|
-
const keyword = ref35("");
|
|
11746
|
-
const page = ref35(1);
|
|
11747
|
-
const temp = ref35([]);
|
|
11748
|
-
const selectedIds = computed21(() => {
|
|
11749
|
-
if (props.multiple) return Array.isArray(props.modelValue) ? props.modelValue : [];
|
|
11750
|
-
if (props.modelValue === "" || props.modelValue === null || props.modelValue === void 0) return [];
|
|
11751
|
-
return [props.modelValue];
|
|
11752
|
-
});
|
|
11753
|
-
function isImage(item) {
|
|
11754
|
-
if (item.type) return item.type === "image";
|
|
11755
|
-
return /\.(png|jpe?g|gif|webp|svg|avif)$/i.test(item.url || "");
|
|
11756
|
-
}
|
|
11757
|
-
const filtered = computed21(() => {
|
|
11758
|
-
const key = keyword.value.trim().toLowerCase();
|
|
11759
|
-
return props.items.filter((item) => {
|
|
11760
|
-
if (props.accept === "image" && !isImage(item)) return false;
|
|
11761
|
-
if (props.accept === "file" && isImage(item)) return false;
|
|
11762
|
-
if (key && !String(item.name || "").toLowerCase().includes(key)) return false;
|
|
11763
|
-
return true;
|
|
11764
|
-
});
|
|
11765
|
-
});
|
|
11766
|
-
const paged = computed21(() => {
|
|
11767
|
-
const start = (page.value - 1) * props.pageSize;
|
|
11768
|
-
return filtered.value.slice(start, start + props.pageSize);
|
|
11769
|
-
});
|
|
11770
|
-
watch26(keyword, () => {
|
|
11771
|
-
page.value = 1;
|
|
11772
|
-
});
|
|
11773
|
-
watch26(
|
|
11774
|
-
() => filtered.value.length,
|
|
11775
|
-
() => {
|
|
11776
|
-
const max = Math.max(1, Math.ceil(filtered.value.length / props.pageSize));
|
|
11777
|
-
if (page.value > max) page.value = max;
|
|
11778
|
-
}
|
|
11779
|
-
);
|
|
11780
|
-
function isChecked(id) {
|
|
11781
|
-
return temp.value.includes(id);
|
|
11782
|
-
}
|
|
11783
|
-
function atLimit() {
|
|
11784
|
-
return props.limit > 0 && temp.value.length >= props.limit;
|
|
11785
|
-
}
|
|
11786
|
-
function toggle(item) {
|
|
11787
|
-
if (props.multiple) {
|
|
11788
|
-
if (isChecked(item.id)) {
|
|
11789
|
-
temp.value = temp.value.filter((id) => id !== item.id);
|
|
11790
|
-
return;
|
|
11791
|
-
}
|
|
11792
|
-
if (atLimit()) return;
|
|
11793
|
-
temp.value = [...temp.value, item.id];
|
|
11794
|
-
return;
|
|
11795
|
-
}
|
|
11796
|
-
temp.value = [item.id];
|
|
11797
|
-
}
|
|
11798
|
-
function openPanel() {
|
|
11799
|
-
if (props.disabled) return;
|
|
11800
|
-
temp.value = [...selectedIds.value];
|
|
11801
|
-
keyword.value = "";
|
|
11802
|
-
page.value = 1;
|
|
11803
|
-
open.value = true;
|
|
11804
|
-
}
|
|
11805
|
-
function commit() {
|
|
11806
|
-
const next = props.multiple ? [...temp.value] : temp.value[0] !== void 0 ? temp.value[0] : "";
|
|
11807
|
-
emit("update:modelValue", next);
|
|
11808
|
-
emit("change", next);
|
|
11809
|
-
open.value = false;
|
|
11810
|
-
}
|
|
11811
|
-
function cancel() {
|
|
11812
|
-
temp.value = [...selectedIds.value];
|
|
11813
|
-
open.value = false;
|
|
11814
|
-
}
|
|
11815
|
-
return {
|
|
11816
|
-
open,
|
|
11817
|
-
keyword,
|
|
11818
|
-
page,
|
|
11819
|
-
temp,
|
|
11820
|
-
selectedIds,
|
|
11821
|
-
filtered,
|
|
11822
|
-
paged,
|
|
11823
|
-
isImage,
|
|
11824
|
-
isChecked,
|
|
11825
|
-
atLimit,
|
|
11826
|
-
toggle,
|
|
11827
|
-
openPanel,
|
|
11828
|
-
commit,
|
|
11829
|
-
cancel,
|
|
11830
|
-
t
|
|
11831
|
-
};
|
|
11832
|
-
},
|
|
11833
|
-
template: `
|
|
11834
|
-
<span class="djm-media-picker">
|
|
11835
|
-
<slot name="trigger" :open="openPanel" :count="selectedIds.length">
|
|
11836
|
-
<button
|
|
11837
|
-
class="djm-btn"
|
|
11838
|
-
type="button"
|
|
11839
|
-
:disabled="disabled"
|
|
11840
|
-
@click="openPanel"
|
|
11841
|
-
>{{ triggerText || t('mediaPicker.select') }}<span v-if="selectedIds.length" class="djm-media-picker-count">{{ selectedIds.length }}</span></button>
|
|
11842
|
-
</slot>
|
|
11843
|
-
|
|
11844
|
-
<DjmModal
|
|
11845
|
-
:model-value="open"
|
|
11846
|
-
:title="title || t('mediaPicker.title')"
|
|
11847
|
-
width="760px"
|
|
11848
|
-
@update:model-value="cancel"
|
|
11849
|
-
>
|
|
11850
|
-
<div class="djm-media-toolbar">
|
|
11851
|
-
<label class="djm-media-search">
|
|
11852
|
-
<DjmIcon name="search" :size="13" />
|
|
11853
|
-
<input
|
|
11854
|
-
v-model="keyword"
|
|
11855
|
-
class="djm-media-search-input"
|
|
11856
|
-
type="text"
|
|
11857
|
-
:placeholder="t('mediaPicker.search')"
|
|
11858
|
-
:aria-label="t('mediaPicker.search')"
|
|
11859
|
-
/>
|
|
11860
|
-
</label>
|
|
11861
|
-
<span class="djm-media-toolbar-slot">
|
|
11862
|
-
<slot name="toolbar"></slot>
|
|
11863
|
-
</span>
|
|
11864
|
-
</div>
|
|
11865
|
-
|
|
11866
|
-
<div class="djm-media-grid" role="listbox" :aria-multiselectable="multiple ? 'true' : 'false'">
|
|
11867
|
-
<div
|
|
11868
|
-
v-for="item in paged"
|
|
11869
|
-
:key="item.id"
|
|
11870
|
-
class="djm-media-item"
|
|
11871
|
-
:class="{
|
|
11872
|
-
'djm-is-checked': isChecked(item.id),
|
|
11873
|
-
'djm-is-disabled': multiple && atLimit() && !isChecked(item.id)
|
|
11874
|
-
}"
|
|
11875
|
-
role="option"
|
|
11876
|
-
tabindex="0"
|
|
11877
|
-
:aria-selected="String(isChecked(item.id))"
|
|
11878
|
-
@click="toggle(item)"
|
|
11879
|
-
@keydown.enter.prevent="toggle(item)"
|
|
11880
|
-
@keydown.space.prevent="toggle(item)"
|
|
11881
|
-
>
|
|
11882
|
-
<div class="djm-media-thumb">
|
|
11883
|
-
<img v-if="isImage(item)" :src="item.url" :alt="item.name" loading="lazy" />
|
|
11884
|
-
<DjmIcon v-else name="folder" :size="26" />
|
|
11885
|
-
<span v-if="isChecked(item.id)" class="djm-media-check">
|
|
11886
|
-
<DjmIcon name="check" :size="11" />
|
|
11887
|
-
</span>
|
|
11888
|
-
</div>
|
|
11889
|
-
<div class="djm-media-name" :title="item.name">{{ item.name }}</div>
|
|
11890
|
-
</div>
|
|
11891
|
-
<div v-if="!paged.length" class="djm-media-empty">{{ t('mediaPicker.empty') }}</div>
|
|
11892
|
-
</div>
|
|
11893
|
-
|
|
11894
|
-
<div class="djm-media-foot">
|
|
11895
|
-
<span class="djm-media-total">
|
|
11896
|
-
{{ t('mediaPicker.total', { total: filtered.length }) }}
|
|
11897
|
-
<em v-if="multiple && limit > 0">{{ t('mediaPicker.limit', { limit }) }}</em>
|
|
11898
|
-
</span>
|
|
11899
|
-
<DjmPagination
|
|
11900
|
-
v-if="filtered.length > pageSize"
|
|
11901
|
-
v-model:page="page"
|
|
11902
|
-
:page-size="pageSize"
|
|
11903
|
-
:total="filtered.length"
|
|
11904
|
-
/>
|
|
11905
|
-
</div>
|
|
11906
|
-
|
|
11907
|
-
<template #footer>
|
|
11908
|
-
<button class="djm-btn" type="button" @click="cancel">{{ t('common.cancel') }}</button>
|
|
11909
|
-
<button class="djm-btn djm-btn-primary" type="button" @click="commit">{{ t('common.confirm') }}</button>
|
|
11910
|
-
</template>
|
|
11911
|
-
</DjmModal>
|
|
11912
|
-
</span>
|
|
11913
|
-
`
|
|
11914
|
-
};
|
|
11915
|
-
|
|
11916
12601
|
// src/components/kanban/index.js
|
|
11917
12602
|
import { ref as ref36, watch as watch27 } from "vue";
|
|
11918
12603
|
function cloneColumns(list) {
|
|
@@ -12102,7 +12787,7 @@ var kanban_default = {
|
|
|
12102
12787
|
};
|
|
12103
12788
|
|
|
12104
12789
|
// src/components/attachment-list/index.js
|
|
12105
|
-
import { computed as
|
|
12790
|
+
import { computed as computed23 } from "vue";
|
|
12106
12791
|
var IMAGE_EXTS = ["png", "jpg", "jpeg", "gif", "webp", "bmp", "svg"];
|
|
12107
12792
|
function extOf(file) {
|
|
12108
12793
|
if (file.ext) return String(file.ext).toLowerCase();
|
|
@@ -12126,14 +12811,14 @@ var attachment_list_default = {
|
|
|
12126
12811
|
},
|
|
12127
12812
|
emits: ["preview", "download", "remove"],
|
|
12128
12813
|
setup(props, { emit }) {
|
|
12129
|
-
const list =
|
|
12814
|
+
const list = computed23(
|
|
12130
12815
|
() => props.files.map((file, index) => {
|
|
12131
12816
|
const ext = extOf(file);
|
|
12132
12817
|
const isImage = file.type === "image" || IMAGE_EXTS.includes(ext);
|
|
12133
12818
|
return { ...file, _key: file.uid !== void 0 ? file.uid : index, _ext: ext, _isImage: isImage };
|
|
12134
12819
|
})
|
|
12135
12820
|
);
|
|
12136
|
-
const emptyLabel =
|
|
12821
|
+
const emptyLabel = computed23(() => props.emptyText || t("attachment.empty"));
|
|
12137
12822
|
function onPreview(file) {
|
|
12138
12823
|
emit("preview", file);
|
|
12139
12824
|
}
|
|
@@ -12239,7 +12924,7 @@ var attachment_list_default = {
|
|
|
12239
12924
|
};
|
|
12240
12925
|
|
|
12241
12926
|
// src/components/notification/index.js
|
|
12242
|
-
import { computed as
|
|
12927
|
+
import { computed as computed24, onBeforeUnmount as onBeforeUnmount27, ref as ref37 } from "vue";
|
|
12243
12928
|
var TYPE_MAP = {
|
|
12244
12929
|
info: { icon: "info", cls: "djm-is-info" },
|
|
12245
12930
|
success: { icon: "check", cls: "djm-is-success" },
|
|
@@ -12259,8 +12944,8 @@ var notification_default = {
|
|
|
12259
12944
|
},
|
|
12260
12945
|
emits: ["click", "read", "read-all", "remove", "clear"],
|
|
12261
12946
|
setup(props, { emit }) {
|
|
12262
|
-
const unreadCount =
|
|
12263
|
-
const emptyLabel =
|
|
12947
|
+
const unreadCount = computed24(() => props.items.filter((item) => !item.read).length);
|
|
12948
|
+
const emptyLabel = computed24(() => props.emptyText || t("notification.empty"));
|
|
12264
12949
|
function typeOf(item) {
|
|
12265
12950
|
return TYPE_MAP[item.type] || TYPE_MAP.info;
|
|
12266
12951
|
}
|
|
@@ -12392,7 +13077,7 @@ var config_provider_default = {
|
|
|
12392
13077
|
};
|
|
12393
13078
|
|
|
12394
13079
|
// src/components/date-time-picker/index.js
|
|
12395
|
-
import { ref as ref38, computed as
|
|
13080
|
+
import { ref as ref38, computed as computed25, watch as watch29, onBeforeUnmount as onBeforeUnmount28 } from "vue";
|
|
12396
13081
|
var uidSeed7 = 0;
|
|
12397
13082
|
var pad4 = (value) => String(value).padStart(2, "0");
|
|
12398
13083
|
function toDateKey(year, month, day) {
|
|
@@ -12434,22 +13119,22 @@ var date_time_picker_default = {
|
|
|
12434
13119
|
let detachPanel = null;
|
|
12435
13120
|
const today = /* @__PURE__ */ new Date();
|
|
12436
13121
|
const todayKey = toDateKey(today.getFullYear(), today.getMonth(), today.getDate());
|
|
12437
|
-
const hasSeconds =
|
|
13122
|
+
const hasSeconds = computed25(() => props.format.indexOf("ss") > -1);
|
|
12438
13123
|
const draft = ref38({ date: "", h: "00", m: "00", s: "00" });
|
|
12439
13124
|
const initial = parseDate(parseValue(props.modelValue).date);
|
|
12440
13125
|
const viewYear = ref38(initial ? initial.year : today.getFullYear());
|
|
12441
13126
|
const viewMonth = ref38(initial ? initial.month : today.getMonth());
|
|
12442
|
-
const displayText =
|
|
12443
|
-
const placeholderText =
|
|
12444
|
-
const weeks =
|
|
12445
|
-
const hours =
|
|
12446
|
-
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(() => {
|
|
12447
13132
|
const list = [];
|
|
12448
13133
|
for (let value = 0; value < 60; value += Math.max(1, props.minuteStep)) list.push(pad4(value));
|
|
12449
13134
|
return list;
|
|
12450
13135
|
});
|
|
12451
|
-
const seconds =
|
|
12452
|
-
const timeCols =
|
|
13136
|
+
const seconds = computed25(() => Array.from({ length: 60 }, (_, index) => pad4(index)));
|
|
13137
|
+
const timeCols = computed25(() => {
|
|
12453
13138
|
const cols = [
|
|
12454
13139
|
{ key: "h", list: hours.value },
|
|
12455
13140
|
{ key: "m", list: minutes.value }
|
|
@@ -12457,8 +13142,8 @@ var date_time_picker_default = {
|
|
|
12457
13142
|
if (hasSeconds.value) cols.push({ key: "s", list: seconds.value });
|
|
12458
13143
|
return cols;
|
|
12459
13144
|
});
|
|
12460
|
-
const monthLabel =
|
|
12461
|
-
const cells =
|
|
13145
|
+
const monthLabel = computed25(() => t("datePicker.title", { year: viewYear.value, month: viewMonth.value + 1 }));
|
|
13146
|
+
const cells = computed25(() => {
|
|
12462
13147
|
const first = new Date(viewYear.value, viewMonth.value, 1);
|
|
12463
13148
|
const offset = (first.getDay() + 6) % 7;
|
|
12464
13149
|
const start = new Date(viewYear.value, viewMonth.value, 1 - offset);
|
|
@@ -12719,7 +13404,7 @@ var date_time_picker_default = {
|
|
|
12719
13404
|
};
|
|
12720
13405
|
|
|
12721
13406
|
// src/components/virtual-list/index.js
|
|
12722
|
-
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";
|
|
12723
13408
|
var virtual_list_default = {
|
|
12724
13409
|
name: "DjmVirtualList",
|
|
12725
13410
|
props: {
|
|
@@ -12743,7 +13428,7 @@ var virtual_list_default = {
|
|
|
12743
13428
|
function rowHeight(item, index) {
|
|
12744
13429
|
return typeof props.itemHeight === "function" ? Math.max(1, Number(props.itemHeight(item, index)) || 1) : Math.max(1, props.itemHeight);
|
|
12745
13430
|
}
|
|
12746
|
-
const offsets =
|
|
13431
|
+
const offsets = computed26(() => {
|
|
12747
13432
|
const list = [0];
|
|
12748
13433
|
let sum = 0;
|
|
12749
13434
|
props.items.forEach((item, index) => {
|
|
@@ -12752,7 +13437,7 @@ var virtual_list_default = {
|
|
|
12752
13437
|
});
|
|
12753
13438
|
return list;
|
|
12754
13439
|
});
|
|
12755
|
-
const totalHeight =
|
|
13440
|
+
const totalHeight = computed26(() => offsets.value[offsets.value.length - 1]);
|
|
12756
13441
|
function findStart(top) {
|
|
12757
13442
|
const list = offsets.value;
|
|
12758
13443
|
let low = 0;
|
|
@@ -12764,7 +13449,7 @@ var virtual_list_default = {
|
|
|
12764
13449
|
}
|
|
12765
13450
|
return Math.max(0, low - 1);
|
|
12766
13451
|
}
|
|
12767
|
-
const range =
|
|
13452
|
+
const range = computed26(() => {
|
|
12768
13453
|
const total = props.items.length;
|
|
12769
13454
|
if (!total) return { start: 0, end: 0 };
|
|
12770
13455
|
const start = Math.max(0, findStart(scrollTop.value) - props.overscan);
|
|
@@ -12773,7 +13458,7 @@ var virtual_list_default = {
|
|
|
12773
13458
|
while (end < total && offsets.value[end] < limit) end += 1;
|
|
12774
13459
|
return { start, end: Math.min(total, end + props.overscan) };
|
|
12775
13460
|
});
|
|
12776
|
-
const visibleRows =
|
|
13461
|
+
const visibleRows = computed26(() => {
|
|
12777
13462
|
const { start, end } = range.value;
|
|
12778
13463
|
return props.items.slice(start, end).map((item, index) => {
|
|
12779
13464
|
const realIndex = start + index;
|
|
@@ -12870,7 +13555,7 @@ var virtual_list_default = {
|
|
|
12870
13555
|
};
|
|
12871
13556
|
|
|
12872
13557
|
// src/components/batch-bar/index.js
|
|
12873
|
-
import { computed as
|
|
13558
|
+
import { computed as computed27 } from "vue";
|
|
12874
13559
|
var batch_bar_default = {
|
|
12875
13560
|
name: "DjmBatchBar",
|
|
12876
13561
|
props: {
|
|
@@ -12885,8 +13570,8 @@ var batch_bar_default = {
|
|
|
12885
13570
|
},
|
|
12886
13571
|
emits: ["clear", "select-all"],
|
|
12887
13572
|
setup(props, { emit }) {
|
|
12888
|
-
const text =
|
|
12889
|
-
const canSelectAll =
|
|
13573
|
+
const text = computed27(() => props.label || t("batchBar.selected", { count: props.count }));
|
|
13574
|
+
const canSelectAll = computed27(() => props.total > props.count);
|
|
12890
13575
|
return {
|
|
12891
13576
|
text,
|
|
12892
13577
|
canSelectAll,
|
|
@@ -12914,7 +13599,7 @@ var batch_bar_default = {
|
|
|
12914
13599
|
};
|
|
12915
13600
|
|
|
12916
13601
|
// src/components/import-wizard/index.js
|
|
12917
|
-
import { ref as ref40, computed as
|
|
13602
|
+
import { ref as ref40, computed as computed28, watch as watch31 } from "vue";
|
|
12918
13603
|
function matchAccept2(name, accept) {
|
|
12919
13604
|
if (!accept) return true;
|
|
12920
13605
|
const ext = "." + String(name).split(".").pop().toLowerCase();
|
|
@@ -12964,7 +13649,7 @@ var import_wizard_default = {
|
|
|
12964
13649
|
innerStep.value = next;
|
|
12965
13650
|
emit("update:step", next);
|
|
12966
13651
|
}
|
|
12967
|
-
const steps =
|
|
13652
|
+
const steps = computed28(() => [
|
|
12968
13653
|
{ index: 1, title: t("importWizard.stepFile") },
|
|
12969
13654
|
{ index: 2, title: t("importWizard.stepMapping") },
|
|
12970
13655
|
{ index: 3, title: t("importWizard.stepResult") }
|
|
@@ -13006,7 +13691,7 @@ var import_wizard_default = {
|
|
|
13006
13691
|
mappingError.value = "";
|
|
13007
13692
|
emit("update:mapping", next);
|
|
13008
13693
|
}
|
|
13009
|
-
const missingRequired =
|
|
13694
|
+
const missingRequired = computed28(
|
|
13010
13695
|
() => props.columns.filter((col) => col.required && !innerMapping.value[col.key])
|
|
13011
13696
|
);
|
|
13012
13697
|
function submit() {
|
|
@@ -13039,7 +13724,7 @@ var import_wizard_default = {
|
|
|
13039
13724
|
emit("retry");
|
|
13040
13725
|
goStep(2);
|
|
13041
13726
|
}
|
|
13042
|
-
const stats =
|
|
13727
|
+
const stats = computed28(() => {
|
|
13043
13728
|
const data = props.result || {};
|
|
13044
13729
|
return {
|
|
13045
13730
|
total: data.total || 0,
|
|
@@ -13185,7 +13870,7 @@ var import_wizard_default = {
|
|
|
13185
13870
|
};
|
|
13186
13871
|
|
|
13187
13872
|
// src/components/diff/index.js
|
|
13188
|
-
import { ref as ref41, computed as
|
|
13873
|
+
import { ref as ref41, computed as computed29 } from "vue";
|
|
13189
13874
|
|
|
13190
13875
|
// src/utils/text-diff.js
|
|
13191
13876
|
var MAX_CELLS = 1e6;
|
|
@@ -13249,8 +13934,8 @@ var diff_default = {
|
|
|
13249
13934
|
afterLabel: { type: String, default: "" }
|
|
13250
13935
|
},
|
|
13251
13936
|
setup(props) {
|
|
13252
|
-
const rows =
|
|
13253
|
-
const stats =
|
|
13937
|
+
const rows = computed29(() => diffLines(props.before, props.after));
|
|
13938
|
+
const stats = computed29(() => {
|
|
13254
13939
|
let add = 0;
|
|
13255
13940
|
let remove = 0;
|
|
13256
13941
|
rows.value.forEach((row) => {
|
|
@@ -13263,7 +13948,7 @@ var diff_default = {
|
|
|
13263
13948
|
function expand(index) {
|
|
13264
13949
|
expandedBlocks.value = expandedBlocks.value.concat(index);
|
|
13265
13950
|
}
|
|
13266
|
-
const displayRows =
|
|
13951
|
+
const displayRows = computed29(() => {
|
|
13267
13952
|
const ctx = Math.max(0, props.context);
|
|
13268
13953
|
const list = rows.value;
|
|
13269
13954
|
if (!ctx) return list;
|
|
@@ -13294,7 +13979,7 @@ var diff_default = {
|
|
|
13294
13979
|
}
|
|
13295
13980
|
return out;
|
|
13296
13981
|
});
|
|
13297
|
-
const splitRows =
|
|
13982
|
+
const splitRows = computed29(() => {
|
|
13298
13983
|
const list = displayRows.value;
|
|
13299
13984
|
const out = [];
|
|
13300
13985
|
let i = 0;
|
|
@@ -13319,8 +14004,8 @@ var diff_default = {
|
|
|
13319
14004
|
}
|
|
13320
14005
|
return out;
|
|
13321
14006
|
});
|
|
13322
|
-
const beforeLabelText =
|
|
13323
|
-
const afterLabelText =
|
|
14007
|
+
const beforeLabelText = computed29(() => props.beforeLabel || t("diff.before"));
|
|
14008
|
+
const afterLabelText = computed29(() => props.afterLabel || t("diff.after"));
|
|
13324
14009
|
return {
|
|
13325
14010
|
stats,
|
|
13326
14011
|
displayRows,
|
|
@@ -13386,7 +14071,7 @@ var diff_default = {
|
|
|
13386
14071
|
};
|
|
13387
14072
|
|
|
13388
14073
|
// src/components/tree-table/index.js
|
|
13389
|
-
import { ref as ref42, computed as
|
|
14074
|
+
import { ref as ref42, computed as computed30, watch as watch32 } from "vue";
|
|
13390
14075
|
function keyOf(row, rowKey) {
|
|
13391
14076
|
return row && row[rowKey] !== void 0 ? row[rowKey] : row && row.id;
|
|
13392
14077
|
}
|
|
@@ -13441,7 +14126,7 @@ var tree_table_default = {
|
|
|
13441
14126
|
if (value) innerChecked.value = value.slice();
|
|
13442
14127
|
}
|
|
13443
14128
|
);
|
|
13444
|
-
const rows =
|
|
14129
|
+
const rows = computed30(() => {
|
|
13445
14130
|
const out = [];
|
|
13446
14131
|
function walk(list, level, parentKey) {
|
|
13447
14132
|
;
|
|
@@ -13456,7 +14141,7 @@ var tree_table_default = {
|
|
|
13456
14141
|
walk(props.data, 1, null);
|
|
13457
14142
|
return out;
|
|
13458
14143
|
});
|
|
13459
|
-
const descendantMap =
|
|
14144
|
+
const descendantMap = computed30(() => {
|
|
13460
14145
|
const map = {};
|
|
13461
14146
|
function collect(row) {
|
|
13462
14147
|
const key = keyOf(row, props.rowKey);
|
|
@@ -13471,16 +14156,16 @@ var tree_table_default = {
|
|
|
13471
14156
|
(props.data || []).forEach(collect);
|
|
13472
14157
|
return map;
|
|
13473
14158
|
});
|
|
13474
|
-
const leafKeys =
|
|
14159
|
+
const leafKeys = computed30(() => {
|
|
13475
14160
|
const keys = [];
|
|
13476
14161
|
eachNode(props.data, (row) => {
|
|
13477
14162
|
if (!row.children || !row.children.length) keys.push(keyOf(row, props.rowKey));
|
|
13478
14163
|
});
|
|
13479
14164
|
return keys;
|
|
13480
14165
|
});
|
|
13481
|
-
const checkedSet =
|
|
13482
|
-
const allChecked =
|
|
13483
|
-
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)));
|
|
13484
14169
|
function isIndeterminate(row) {
|
|
13485
14170
|
if (!props.selectable || props.checkStrictly) return false;
|
|
13486
14171
|
const desc = descendantMap.value[keyOf(row, props.rowKey)] || [];
|
|
@@ -13514,7 +14199,7 @@ var tree_table_default = {
|
|
|
13514
14199
|
}
|
|
13515
14200
|
emitChecked(Array.from(set));
|
|
13516
14201
|
}
|
|
13517
|
-
const nodeMap =
|
|
14202
|
+
const nodeMap = computed30(() => {
|
|
13518
14203
|
const map = {};
|
|
13519
14204
|
eachNode(props.data, (row, level, parentKey) => {
|
|
13520
14205
|
map[keyOf(row, props.rowKey)] = { row, parentKey };
|
|
@@ -13561,11 +14246,11 @@ var tree_table_default = {
|
|
|
13561
14246
|
function onRowClick(item) {
|
|
13562
14247
|
emit("row-click", item.row, item);
|
|
13563
14248
|
}
|
|
13564
|
-
const scrollStyle =
|
|
14249
|
+
const scrollStyle = computed30(() => {
|
|
13565
14250
|
if (!props.maxHeight) return null;
|
|
13566
14251
|
return { maxHeight: typeof props.maxHeight === "number" ? props.maxHeight + "px" : props.maxHeight };
|
|
13567
14252
|
});
|
|
13568
|
-
const emptyLabel =
|
|
14253
|
+
const emptyLabel = computed30(() => props.emptyText || t("treeTable.empty"));
|
|
13569
14254
|
return {
|
|
13570
14255
|
rows,
|
|
13571
14256
|
innerExpanded,
|
|
@@ -13667,7 +14352,7 @@ var tree_table_default = {
|
|
|
13667
14352
|
};
|
|
13668
14353
|
|
|
13669
14354
|
// src/components/schedule/index.js
|
|
13670
|
-
import { ref as ref43, computed as
|
|
14355
|
+
import { ref as ref43, computed as computed31, watch as watch33, onBeforeUnmount as onBeforeUnmount30 } from "vue";
|
|
13671
14356
|
var pad5 = (value) => String(value).padStart(2, "0");
|
|
13672
14357
|
function toKey3(date) {
|
|
13673
14358
|
return `${date.getFullYear()}-${pad5(date.getMonth() + 1)}-${pad5(date.getDate())}`;
|
|
@@ -13717,8 +14402,8 @@ var schedule_default = {
|
|
|
13717
14402
|
const offset = (day + 6) % 7;
|
|
13718
14403
|
return new Date(date.getFullYear(), date.getMonth(), date.getDate() - offset);
|
|
13719
14404
|
}
|
|
13720
|
-
const weekStartDate =
|
|
13721
|
-
const weekdays =
|
|
14405
|
+
const weekStartDate = computed31(() => startOfWeek(anchor.value));
|
|
14406
|
+
const weekdays = computed31(() => t("schedule.weekdays").split(","));
|
|
13722
14407
|
function layoutDay(list) {
|
|
13723
14408
|
const sorted = list.map((item) => {
|
|
13724
14409
|
const startMin = toMinutes(item.start, props.startHour * 60);
|
|
@@ -13751,7 +14436,7 @@ var schedule_default = {
|
|
|
13751
14436
|
};
|
|
13752
14437
|
});
|
|
13753
14438
|
}
|
|
13754
|
-
const days =
|
|
14439
|
+
const days = computed31(() => {
|
|
13755
14440
|
const start = weekStartDate.value;
|
|
13756
14441
|
const list = Array.from({ length: 7 }, (_, index) => {
|
|
13757
14442
|
const date = new Date(start.getFullYear(), start.getMonth(), start.getDate() + index);
|
|
@@ -13769,20 +14454,20 @@ var schedule_default = {
|
|
|
13769
14454
|
});
|
|
13770
14455
|
return props.showWeekend ? list : list.slice(0, 5);
|
|
13771
14456
|
});
|
|
13772
|
-
const hours =
|
|
14457
|
+
const hours = computed31(() => {
|
|
13773
14458
|
const list = [];
|
|
13774
14459
|
for (let hour = props.startHour; hour < props.endHour; hour++) list.push(hour);
|
|
13775
14460
|
return list;
|
|
13776
14461
|
});
|
|
13777
|
-
const bodyHeight =
|
|
13778
|
-
const gridStyle =
|
|
14462
|
+
const bodyHeight = computed31(() => (props.endHour - props.startHour) * props.hourHeight);
|
|
14463
|
+
const gridStyle = computed31(() => ({
|
|
13779
14464
|
gridTemplateColumns: "56px repeat(" + Math.max(1, days.value.length) + ", minmax(0, 1fr))"
|
|
13780
14465
|
}));
|
|
13781
|
-
const nowTop =
|
|
13782
|
-
const showNowLine =
|
|
14466
|
+
const nowTop = computed31(() => (nowMinutes.value - props.startHour * 60) / 60 * props.hourHeight);
|
|
14467
|
+
const showNowLine = computed31(
|
|
13783
14468
|
() => nowMinutes.value >= props.startHour * 60 && nowMinutes.value <= props.endHour * 60 && days.value.some((day) => day.today)
|
|
13784
14469
|
);
|
|
13785
|
-
const rangeLabel =
|
|
14470
|
+
const rangeLabel = computed31(() => {
|
|
13786
14471
|
const list = days.value;
|
|
13787
14472
|
if (!list.length) return "";
|
|
13788
14473
|
const first = list[0];
|
|
@@ -13912,7 +14597,7 @@ var schedule_default = {
|
|
|
13912
14597
|
};
|
|
13913
14598
|
|
|
13914
14599
|
// src/components/comment/index.js
|
|
13915
|
-
import { ref as ref44, computed as
|
|
14600
|
+
import { ref as ref44, computed as computed32 } from "vue";
|
|
13916
14601
|
var comment_default = {
|
|
13917
14602
|
name: "DjmComment",
|
|
13918
14603
|
components: { DjmAvatar: avatar_default, DjmIcon: icon_default },
|
|
@@ -13931,14 +14616,14 @@ var comment_default = {
|
|
|
13931
14616
|
setup(props, { emit }) {
|
|
13932
14617
|
const content = ref44("");
|
|
13933
14618
|
const replyTarget = ref44(null);
|
|
13934
|
-
const placeholderText =
|
|
14619
|
+
const placeholderText = computed32(() => {
|
|
13935
14620
|
if (replyTarget.value) return t("comment.replyPlaceholder", { name: replyTarget.value.author });
|
|
13936
14621
|
return props.placeholder || t("comment.placeholder");
|
|
13937
14622
|
});
|
|
13938
|
-
const submitLabel =
|
|
13939
|
-
const emptyLabel =
|
|
13940
|
-
const overLimit =
|
|
13941
|
-
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);
|
|
13942
14627
|
function onInput(event) {
|
|
13943
14628
|
content.value = event.target.value;
|
|
13944
14629
|
}
|
|
@@ -14253,7 +14938,7 @@ var signature_default = {
|
|
|
14253
14938
|
};
|
|
14254
14939
|
|
|
14255
14940
|
// src/components/print/index.js
|
|
14256
|
-
import { ref as ref46, computed as
|
|
14941
|
+
import { ref as ref46, computed as computed33 } from "vue";
|
|
14257
14942
|
function escapeHtml(text) {
|
|
14258
14943
|
return String(text).replace(/[&<>"]/g, (ch) => ({ "&": "&", "<": "<", ">": ">", '"': """ })[ch]);
|
|
14259
14944
|
}
|
|
@@ -14270,7 +14955,7 @@ var print_default = {
|
|
|
14270
14955
|
emits: ["before-print", "after-print"],
|
|
14271
14956
|
setup(props, { emit }) {
|
|
14272
14957
|
const content = ref46(null);
|
|
14273
|
-
const label =
|
|
14958
|
+
const label = computed33(() => props.buttonText || t("print.button"));
|
|
14274
14959
|
function collectStyles() {
|
|
14275
14960
|
return Array.from(document.querySelectorAll('link[rel="stylesheet"], style')).map((el) => el.outerHTML).join("");
|
|
14276
14961
|
}
|
|
@@ -14319,7 +15004,7 @@ var print_default = {
|
|
|
14319
15004
|
};
|
|
14320
15005
|
|
|
14321
15006
|
// src/components/gantt/index.js
|
|
14322
|
-
import { computed as
|
|
15007
|
+
import { computed as computed34 } from "vue";
|
|
14323
15008
|
var DAY = 864e5;
|
|
14324
15009
|
var pad6 = (value) => String(value).padStart(2, "0");
|
|
14325
15010
|
function parseDate3(value) {
|
|
@@ -14355,7 +15040,7 @@ var gantt_default = {
|
|
|
14355
15040
|
emits: ["task-click"],
|
|
14356
15041
|
setup(props, { emit }) {
|
|
14357
15042
|
const todayKey = toKey4(/* @__PURE__ */ new Date());
|
|
14358
|
-
const range =
|
|
15043
|
+
const range = computed34(() => {
|
|
14359
15044
|
const starts = props.tasks.map((task) => task.start).filter(Boolean).sort();
|
|
14360
15045
|
const ends = props.tasks.map((task) => task.end || task.start).filter(Boolean).sort();
|
|
14361
15046
|
let start = props.startDate || starts[0] || todayKey;
|
|
@@ -14368,7 +15053,7 @@ var gantt_default = {
|
|
|
14368
15053
|
}
|
|
14369
15054
|
return { start, end };
|
|
14370
15055
|
});
|
|
14371
|
-
const days =
|
|
15056
|
+
const days = computed34(() => {
|
|
14372
15057
|
const total = dayDiff(range.value.end, range.value.start) + 1;
|
|
14373
15058
|
const base = parseDate3(range.value.start);
|
|
14374
15059
|
return Array.from({ length: total }, (_, index) => {
|
|
@@ -14385,9 +15070,9 @@ var gantt_default = {
|
|
|
14385
15070
|
};
|
|
14386
15071
|
});
|
|
14387
15072
|
});
|
|
14388
|
-
const trackWidth =
|
|
14389
|
-
const innerWidth =
|
|
14390
|
-
const bars =
|
|
15073
|
+
const trackWidth = computed34(() => days.value.length * props.dayWidth);
|
|
15074
|
+
const innerWidth = computed34(() => props.nameWidth + trackWidth.value);
|
|
15075
|
+
const bars = computed34(
|
|
14391
15076
|
() => props.tasks.map((task, index) => {
|
|
14392
15077
|
const start = task.start || range.value.start;
|
|
14393
15078
|
const end = task.end || start;
|
|
@@ -14403,12 +15088,12 @@ var gantt_default = {
|
|
|
14403
15088
|
};
|
|
14404
15089
|
})
|
|
14405
15090
|
);
|
|
14406
|
-
const todayLeft =
|
|
15091
|
+
const todayLeft = computed34(() => {
|
|
14407
15092
|
const index = days.value.findIndex((day) => day.today);
|
|
14408
15093
|
if (index === -1) return null;
|
|
14409
15094
|
return props.nameWidth + index * props.dayWidth + props.dayWidth / 2;
|
|
14410
15095
|
});
|
|
14411
|
-
const emptyLabel =
|
|
15096
|
+
const emptyLabel = computed34(() => props.emptyText || t("gantt.empty"));
|
|
14412
15097
|
function onClick(bar) {
|
|
14413
15098
|
emit("task-click", bar.task);
|
|
14414
15099
|
}
|
|
@@ -14490,7 +15175,7 @@ var gantt_default = {
|
|
|
14490
15175
|
};
|
|
14491
15176
|
|
|
14492
15177
|
// src/components/field-list/index.js
|
|
14493
|
-
import { ref as ref47, computed as
|
|
15178
|
+
import { ref as ref47, computed as computed35, watch as watch35 } from "vue";
|
|
14494
15179
|
var uidSeed8 = 0;
|
|
14495
15180
|
var field_list_default = {
|
|
14496
15181
|
name: "DjmFieldList",
|
|
@@ -14521,10 +15206,10 @@ var field_list_default = {
|
|
|
14521
15206
|
syncUids();
|
|
14522
15207
|
watch35(() => props.modelValue.length, syncUids);
|
|
14523
15208
|
const errors = ref47({});
|
|
14524
|
-
const addLabel =
|
|
14525
|
-
const emptyLabel =
|
|
14526
|
-
const canAdd =
|
|
14527
|
-
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);
|
|
14528
15213
|
function commit(list) {
|
|
14529
15214
|
emit("update:modelValue", list);
|
|
14530
15215
|
emit("change", list);
|
|
@@ -14686,7 +15371,7 @@ var field_list_default = {
|
|
|
14686
15371
|
};
|
|
14687
15372
|
|
|
14688
15373
|
// src/components/chat/index.js
|
|
14689
|
-
import { ref as ref48, computed as
|
|
15374
|
+
import { ref as ref48, computed as computed36, watch as watch36, nextTick as nextTick15 } from "vue";
|
|
14690
15375
|
var chat_default = {
|
|
14691
15376
|
name: "DjmChat",
|
|
14692
15377
|
components: { DjmAvatar: avatar_default },
|
|
@@ -14705,10 +15390,10 @@ var chat_default = {
|
|
|
14705
15390
|
setup(props, { emit }) {
|
|
14706
15391
|
const content = ref48("");
|
|
14707
15392
|
const listRef = ref48(null);
|
|
14708
|
-
const placeholderText =
|
|
14709
|
-
const sendLabel =
|
|
14710
|
-
const emptyLabel =
|
|
14711
|
-
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);
|
|
14712
15397
|
function scrollToBottom() {
|
|
14713
15398
|
const el = listRef.value;
|
|
14714
15399
|
if (el) el.scrollTop = el.scrollHeight;
|
|
@@ -14826,7 +15511,7 @@ var chat_default = {
|
|
|
14826
15511
|
};
|
|
14827
15512
|
|
|
14828
15513
|
// src/components/org-chart/index.js
|
|
14829
|
-
import { ref as ref49, computed as
|
|
15514
|
+
import { ref as ref49, computed as computed37, watch as watch37 } from "vue";
|
|
14830
15515
|
var org_chart_default = {
|
|
14831
15516
|
name: "DjmOrgChart",
|
|
14832
15517
|
components: { DjmAvatar: avatar_default, DjmIcon: icon_default },
|
|
@@ -14863,7 +15548,7 @@ var org_chart_default = {
|
|
|
14863
15548
|
watch37(() => props.data, (data) => {
|
|
14864
15549
|
collapsed.value = props.defaultExpandAll ? [] : collapsedByDefault(data);
|
|
14865
15550
|
});
|
|
14866
|
-
const layout =
|
|
15551
|
+
const layout = computed37(() => {
|
|
14867
15552
|
if (!props.data) return { nodes: [], links: [], width: 0, height: 0 };
|
|
14868
15553
|
const rowH = props.nodeHeight + props.verticalGap;
|
|
14869
15554
|
let cursor = 0;
|
|
@@ -14928,7 +15613,7 @@ var org_chart_default = {
|
|
|
14928
15613
|
function onClick(item) {
|
|
14929
15614
|
emit("node-click", item.node);
|
|
14930
15615
|
}
|
|
14931
|
-
const emptyLabel =
|
|
15616
|
+
const emptyLabel = computed37(() => props.emptyText || t("orgChart.empty"));
|
|
14932
15617
|
return {
|
|
14933
15618
|
layout,
|
|
14934
15619
|
toggle,
|
|
@@ -14989,7 +15674,7 @@ var org_chart_default = {
|
|
|
14989
15674
|
};
|
|
14990
15675
|
|
|
14991
15676
|
// src/components/page-tabs/index.js
|
|
14992
|
-
import { computed as
|
|
15677
|
+
import { computed as computed38 } from "vue";
|
|
14993
15678
|
var page_tabs_default = {
|
|
14994
15679
|
name: "DjmPageTabs",
|
|
14995
15680
|
components: { DjmIcon: icon_default },
|
|
@@ -15000,7 +15685,7 @@ var page_tabs_default = {
|
|
|
15000
15685
|
},
|
|
15001
15686
|
emits: ["update:modelValue", "change", "close"],
|
|
15002
15687
|
setup(props, { emit }) {
|
|
15003
|
-
const label =
|
|
15688
|
+
const label = computed38(() => t("pageTabs.label"));
|
|
15004
15689
|
function canClose(tab) {
|
|
15005
15690
|
return tab.closable === void 0 ? props.closable : tab.closable;
|
|
15006
15691
|
}
|
|
@@ -15253,7 +15938,7 @@ var components = [
|
|
|
15253
15938
|
org_chart_default,
|
|
15254
15939
|
page_tabs_default
|
|
15255
15940
|
];
|
|
15256
|
-
var version = "0.
|
|
15941
|
+
var version = "0.72.0";
|
|
15257
15942
|
function install(app, options = {}) {
|
|
15258
15943
|
if (options.locale) setLocale(options.locale);
|
|
15259
15944
|
components.forEach((component) => app.component(component.name, component));
|