feature: drag support in sort panel.
This commit is contained in:
parent
f676ec76db
commit
a946012a33
20
README.md
20
README.md
@ -1,3 +1,21 @@
|
||||
# [ui-lib].Grid
|
||||
|
||||
UI Mordern Gridview Library
|
||||
UI Mordern Gridview Library
|
||||
|
||||
## 1.0.3
|
||||
* 调整: [showSortPanel(callback?: Function, layout?: boolean)](Grid.html#showSortPanel) 现支持输入搜索列,已添加的列不会重复显示在下拉数据源中,增加回调函数与 layout 更新复选框。
|
||||
* 新增: [onRowChanged(action: "update" | "add" | "remove", items: GridRowItem[], indexes: number | number[])](Grid.html#onRowChanged) - 行发生变化时触发的事件
|
||||
### bugs
|
||||
* 修复: 清空多列排序后列头箭头没有清除的异常。
|
||||
|
||||
## 1.0.2
|
||||
* 新增: [export(compressed: string | boolean, module?: string) : Promise<GridExportData>](Grid.html#export) - 导出已压缩的数据源
|
||||
|
||||
## 1.0.1
|
||||
* 新增: [total: GridRowItem](Grid.html#total) - 获取或设置合计行数据
|
||||
* 新增: [showSortPanel()](Grid.html#showSortPanel) - 显示多列排序设置面板
|
||||
* 新增: [setItem(index: number, item: GridRowItem)](Grid.html#setItem) - 设置单行数据
|
||||
* 新增: [addItem(item: GridRowItem, index?: number): GridRowItem](Grid.html#addItem) - 添加行数据
|
||||
* 新增: [addItems(array: GridRowItem[], index?: number) : GridRowItem[]](Grid.html#addItems) - 批量添加行数据
|
||||
* 新增: [removeItem(index: number) : GridRowItem](Grid.html#removeItem) - 删除行数据
|
||||
* 新增: [removeItems(indexes?: number[]): GridRowItem[]](Grid.html#removeItems) - 批量删除行数据
|
||||
|
@ -2,9 +2,11 @@ import "./app/communications/style.scss";
|
||||
import CustomerCommunication from "./app/communications/customer";
|
||||
import InternalComment from "./app/communications/internal";
|
||||
import CustomerRecordComment from "./app/communications/comments";
|
||||
import { createHideMessageTitleButton } from "./app/communications/lib";
|
||||
|
||||
export {
|
||||
CustomerCommunication,
|
||||
InternalComment,
|
||||
CustomerRecordComment
|
||||
CustomerRecordComment,
|
||||
createHideMessageTitleButton
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
import { createElement, setTooltip, createIcon } from "../../ui";
|
||||
import { r as lang, nullOrEmpty, escapeHtml, escapeEmoji } from "../../utility";
|
||||
import { createBox, appendMedia } from "./lib";
|
||||
import { createBox, appendMedia, createHideMessageTitleButton, createHideMessageCommentTail } from "./lib";
|
||||
|
||||
let r = lang;
|
||||
|
||||
@ -25,7 +25,9 @@ export default class CustomerRecordComment {
|
||||
}
|
||||
}
|
||||
|
||||
get messageHidden() { return this._var.option.showCommentHidden }
|
||||
/**
|
||||
* @param {boolean} flag
|
||||
*/
|
||||
set messageHidden(flag) {
|
||||
const el = this._var.container.querySelector('.msgadminsetting');
|
||||
if (el == null) {
|
||||
@ -62,34 +64,14 @@ export default class CustomerRecordComment {
|
||||
}
|
||||
|
||||
create() {
|
||||
const option = this._var.option;
|
||||
const readonly = this._var.option.readonly;
|
||||
const spanv = createElement('span');
|
||||
if (option.userIsAdmin) {
|
||||
spanv.className = 'msgadminsetting sbutton iconnotview';
|
||||
spanv.style.padding = '0px 0px 0px 5px';
|
||||
spanv.addEventListener('click', function () {
|
||||
if (!option.showCommentHidden) {
|
||||
this.classList.remove('iconnotview');
|
||||
this.classList.add('iconview');
|
||||
option.showCommentHidden = true;
|
||||
container.querySelectorAll('.msgsetting').forEach(x => x.style.display = '');
|
||||
} else {
|
||||
this.classList.remove('iconview');
|
||||
this.classList.add('iconnotview');
|
||||
option.showCommentHidden = false;
|
||||
container.querySelectorAll('.msgsetting').forEach(x => x.style.display = 'none');
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
const container = createBox(
|
||||
createElement('div', null,
|
||||
createElement('div', div => {
|
||||
div.className = 'title-module';
|
||||
div.innerText = r('P_CR_COMMENTS', 'Comments');
|
||||
},
|
||||
spanv
|
||||
createHideMessageTitleButton(this, 'showCommentHidden')
|
||||
)
|
||||
),
|
||||
[
|
||||
@ -154,11 +136,18 @@ export default class CustomerRecordComment {
|
||||
return this._var.container = container;
|
||||
}
|
||||
|
||||
load(data, func) {
|
||||
load(data, func, hisFunc, keep) {
|
||||
const children = [];
|
||||
if (data?.length > 0) {
|
||||
const lastVisible = this._var.option.showCommentHidden;
|
||||
for (let comment of data) {
|
||||
const div = createElement('div', 'item-div');
|
||||
if (comment.Hidden) {
|
||||
div.classList.add('hidden-content');
|
||||
if (!lastVisible) {
|
||||
div.style.display = 'none';
|
||||
}
|
||||
}
|
||||
// if (sendto !== '') {
|
||||
// sendto = r('P_CU_SENDTO_COLON', 'Sent To :') + `\n${sendto}`;
|
||||
// }
|
||||
@ -177,37 +166,19 @@ export default class CustomerRecordComment {
|
||||
}
|
||||
div.append(
|
||||
content,
|
||||
createElement('div', div => {
|
||||
div.className = 'item-time';
|
||||
},
|
||||
createElement('span', span => {
|
||||
span.className = 'msgsetting sbutton ' + (comment.Hidden ? 'iconnotview' : 'iconview');
|
||||
span.style.padding = '0px 0px 0px 5px';
|
||||
span.style.fontSize = '12px';
|
||||
span.style.display = this._var.option.showCommentHidden ? '' : 'none';
|
||||
span.addEventListener('click', function () {
|
||||
if (this.classList.contains('iconview')) {
|
||||
func(comment.Id, true);
|
||||
this.classList.remove('iconview');
|
||||
this.classList.add('iconnotview');
|
||||
} else {
|
||||
func(comment.Id, false);
|
||||
this.classList.remove('iconnotview');
|
||||
this.classList.add('iconview');
|
||||
}
|
||||
});
|
||||
}),
|
||||
createElement('span', span => {
|
||||
span.innerText = comment.SubmitLocalDateStr;
|
||||
})
|
||||
)
|
||||
createHideMessageCommentTail(
|
||||
this, 'showCommentHidden',
|
||||
comment, 'SubmitLocalDateStr',
|
||||
func, hisFunc)
|
||||
);
|
||||
children.push(div);
|
||||
}
|
||||
children[0].style.marginTop = '0';
|
||||
}
|
||||
if (this._var.message.children.length > 0) {
|
||||
this._var.lastTop = this._var.message.scrollTop;
|
||||
}
|
||||
this._var.message.replaceChildren(...children);
|
||||
this._var.message.scrollTop = this._var.message.scrollHeight
|
||||
// setTimeout(() => this._var.message.scrollTop = this._var.message.scrollHeight, 0);
|
||||
setTimeout(() => this._var.message.scrollTop = keep ? this._var.lastTop : this._var.message.scrollHeight, 0);
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
import { Grid, GridColumn, createElement, setTooltip, createIcon, createCheckbox, createRadiobox, showAlert, showConfirm, Popup } from "../../ui";
|
||||
import { r as lang, nullOrEmpty, formatUrl, escapeEmoji, isEmail, isPhone } from "../../utility";
|
||||
import { createBox, appendMedia, fileSupported, insertFile, getMessageSendTo, getMessageStatus, updateCustomerName } from "./lib";
|
||||
import { createBox, appendMedia, fileSupported, insertFile, getMessageSendTo, getMessageStatus, updateCustomerName, createHideMessageTitleButton, createHideMessageCommentTail } from "./lib";
|
||||
import { Contact, CustomerRecordContact } from "./contact";
|
||||
import Follower from "./follower";
|
||||
|
||||
@ -69,7 +69,9 @@ export default class CustomerCommunication {
|
||||
element.dispatchEvent(new Event('change'));
|
||||
}
|
||||
|
||||
get messageHidden() { return this._var.option.showMessageHidden }
|
||||
/**
|
||||
* @param {boolean} flag
|
||||
*/
|
||||
set messageHidden(flag) {
|
||||
const el = this._var.container.querySelector('.msgadminsetting');
|
||||
if (el == null) {
|
||||
@ -425,24 +427,6 @@ export default class CustomerCommunication {
|
||||
if (option.statusLinkVisible === false) {
|
||||
checkLink.style.display = 'none';
|
||||
}
|
||||
const spanv = createElement('span');
|
||||
if (option.userIsAdmin) {
|
||||
spanv.className = 'msgadminsetting sbutton iconnotview';
|
||||
spanv.style.padding = '0px 0px 0px 5px';
|
||||
spanv.addEventListener('click', function () {
|
||||
if (!option.showMessageHidden) {
|
||||
this.classList.remove('iconnotview');
|
||||
this.classList.add('iconview');
|
||||
option.showMessageHidden = true;
|
||||
container.querySelectorAll('.msgsetting').forEach(x => x.style.display = '');
|
||||
} else {
|
||||
this.classList.remove('iconview');
|
||||
this.classList.add('iconnotview');
|
||||
option.showMessageHidden = false;
|
||||
container.querySelectorAll('.msgsetting').forEach(x => x.style.display = 'none');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const container = createBox(
|
||||
createElement('div', null,
|
||||
@ -450,7 +434,7 @@ export default class CustomerCommunication {
|
||||
div.className = 'title-module';
|
||||
div.innerText = option.title ?? r('P_WO_CUSTOMERCOMMUNICATION', 'Customer Communication');
|
||||
},
|
||||
spanv
|
||||
createHideMessageTitleButton(this, 'showMessageHidden')
|
||||
),
|
||||
createElement('div', div => {
|
||||
div.className = 'title-company';
|
||||
@ -1179,7 +1163,7 @@ export default class CustomerCommunication {
|
||||
return followers;
|
||||
}
|
||||
|
||||
load(data, contacts, followers, func) {
|
||||
load(data, contacts, followers, func, hisFunc, keep) {
|
||||
const children = [];
|
||||
if (data?.length > 0) {
|
||||
contacts ??= this._var.data.contacts;
|
||||
@ -1192,45 +1176,52 @@ export default class CustomerCommunication {
|
||||
this._var.contactsUpdated = true;
|
||||
}
|
||||
}
|
||||
for (let comm of data) {
|
||||
const lastVisible = this._var.option.showMessageHidden;
|
||||
for (let comment of data) {
|
||||
const div = createElement('div', 'item-div');
|
||||
if (comment.Hidden) {
|
||||
div.classList.add('hidden-content');
|
||||
if (!lastVisible) {
|
||||
div.style.display = 'none';
|
||||
}
|
||||
}
|
||||
let name;
|
||||
if (comm.IsReply && contacts?.length > 0) {
|
||||
const c = isEmail(comm.Sender) ?
|
||||
contacts.find(c => c.Email === comm.Sender) :
|
||||
contacts.find(c => c.MobilePhone === comm.Sender);
|
||||
if (comment.IsReply && contacts?.length > 0) {
|
||||
const c = isEmail(comment.Sender) ?
|
||||
contacts.find(c => c.Email === comment.Sender) :
|
||||
contacts.find(c => c.MobilePhone === comment.Sender);
|
||||
name = c?.Name;
|
||||
}
|
||||
name ??= comm.IsReply && String(comm.FormatSender) !== '' ? comm.FormatSender : comm.Sender;
|
||||
const sendto = getMessageSendTo(comm, contacts, followers, r)
|
||||
name ??= comment.IsReply && String(comment.FormatSender) !== '' ? comment.FormatSender : comment.Sender;
|
||||
const sendto = getMessageSendTo(comment, contacts, followers, r)
|
||||
div.appendChild(createElement('div', div => {
|
||||
div.className = 'item-poster';
|
||||
div.innerText = name;
|
||||
if (!comm.IsReply && sendto?.length > 0) {
|
||||
if (!comment.IsReply && sendto?.length > 0) {
|
||||
setTooltip(div, sendto);
|
||||
}
|
||||
}));
|
||||
const content = createElement('div', 'item-content');
|
||||
const mmsParts = createElement('div', div => div.style.display = 'none');
|
||||
content.appendChild(createElement('span', span => {
|
||||
if (/https?:\/\//i.test(comm.Message)) {
|
||||
span.innerHTML = formatUrl(escapeEmoji(comm.Message));
|
||||
if (/https?:\/\//i.test(comment.Message)) {
|
||||
span.innerHTML = formatUrl(escapeEmoji(comment.Message));
|
||||
} else {
|
||||
span.innerText = escapeEmoji(comm.Message);
|
||||
span.innerText = escapeEmoji(comment.Message);
|
||||
}
|
||||
span.appendChild(mmsParts);
|
||||
}));
|
||||
if (comm.MMSParts?.length > 0) {
|
||||
if (comment.MMSParts?.length > 0) {
|
||||
mmsParts.style.display = '';
|
||||
for (let kv of comm.MMSParts) {
|
||||
for (let kv of comment.MMSParts) {
|
||||
appendMedia(mmsParts, kv.Key, kv.Value);
|
||||
}
|
||||
}
|
||||
if (comm.IsReply) {
|
||||
if (comment.IsReply) {
|
||||
div.classList.add('item-other');
|
||||
} else {
|
||||
div.classList.add('item-self');
|
||||
const [status, text, color, tips] = getMessageStatus(comm, r, this._var);
|
||||
const [status, text, color, tips] = getMessageStatus(comment, r, this._var);
|
||||
if (status !== -100) {
|
||||
if (color != null) {
|
||||
content.style.backgroundColor = color;
|
||||
@ -1247,37 +1238,19 @@ export default class CustomerCommunication {
|
||||
}
|
||||
div.append(
|
||||
content,
|
||||
createElement('div', div => {
|
||||
div.className = 'item-time';
|
||||
},
|
||||
createElement('span', span => {
|
||||
span.className = 'msgsetting sbutton ' + (comm.Hidden ? 'iconnotview' : 'iconview');
|
||||
span.style.padding = '0px 0px 0px 5px';
|
||||
span.style.fontSize = '12px';
|
||||
span.style.display = this._var.option.showMessageHidden ? '' : 'none';
|
||||
span.addEventListener('click', function () {
|
||||
if (this.classList.contains('iconview')) {
|
||||
func(comm.Id, true);
|
||||
this.classList.remove('iconview');
|
||||
this.classList.add('iconnotview');
|
||||
} else {
|
||||
func(comm.Id, false);
|
||||
this.classList.remove('iconnotview');
|
||||
this.classList.add('iconview');
|
||||
}
|
||||
});
|
||||
}),
|
||||
createElement('span', span => {
|
||||
span.innerText = comm.TimeStr;
|
||||
})
|
||||
)
|
||||
createHideMessageCommentTail(
|
||||
this, 'showMessageHidden',
|
||||
comment, 'TimeStr',
|
||||
func, hisFunc)
|
||||
);
|
||||
children.push(div);
|
||||
}
|
||||
children[0].style.marginTop = '0';
|
||||
}
|
||||
if (this._var.message.children.length > 0) {
|
||||
this._var.lastTop = this._var.message.scrollTop;
|
||||
}
|
||||
this._var.message.replaceChildren(...children);
|
||||
this._var.message.scrollTop = this._var.message.scrollHeight
|
||||
// setTimeout(() => this._var.message.scrollTop = this._var.message.scrollHeight, 0);
|
||||
setTimeout(() => this._var.message.scrollTop = keep ? this._var.lastTop : this._var.message.scrollHeight, 0);
|
||||
}
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
import { createElement, setTooltip, createIcon } from "../../ui";
|
||||
import { r as lang, nullOrEmpty, escapeHtml, escapeEmoji } from "../../utility";
|
||||
import { createBox, appendMedia } from "./lib";
|
||||
import { fileSupported, insertFile, getMessageSendTo, getMessageStatus, updateCustomerName } from "./lib";
|
||||
import { fileSupported, insertFile, getMessageSendTo, getMessageStatus, updateCustomerName, createHideMessageTitleButton, createHideMessageCommentTail } from "./lib";
|
||||
|
||||
let r = lang;
|
||||
|
||||
@ -32,7 +32,9 @@ export default class InternalComment {
|
||||
}
|
||||
}
|
||||
|
||||
get messageHidden() { return this._var.option.showCommentHidden }
|
||||
/**
|
||||
* @param {boolean} flag
|
||||
*/
|
||||
set messageHidden(flag) {
|
||||
const el = this._var.container.querySelector('.msgadminsetting');
|
||||
if (el == null) {
|
||||
@ -123,26 +125,7 @@ export default class InternalComment {
|
||||
div.className = 'title-module';
|
||||
div.innerText = r('P_WO_INTERNALCOMMENTS', 'Internal Comments');
|
||||
},
|
||||
createElement('span', span => {
|
||||
if (option.userIsAdmin) {
|
||||
span.className = 'msgadminsetting sbutton iconnotview';
|
||||
span.style.padding = '0px 0px 0px 5px';
|
||||
span.addEventListener('click', function () {
|
||||
if (!option.showMessageHidden) {
|
||||
this.classList.remove('iconnotview');
|
||||
this.classList.add('iconview');
|
||||
option.showMessageHidden = true;
|
||||
container.querySelectorAll('.msgsetting').forEach(x => x.style.display = '');
|
||||
}
|
||||
else {
|
||||
this.classList.remove('iconview');
|
||||
this.classList.add('iconnotview');
|
||||
option.showMessageHidden = false;
|
||||
container.querySelectorAll('.msgsetting').forEach(x => x.style.display = 'none');
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
createHideMessageTitleButton(this, 'showMessageHidden')
|
||||
)
|
||||
), []
|
||||
);
|
||||
@ -278,7 +261,7 @@ export default class InternalComment {
|
||||
return this._var.container = container;
|
||||
}
|
||||
|
||||
load(data, func) {
|
||||
load(data, func, hisFunc, keep) {
|
||||
const children = [];
|
||||
if (data?.length > 0) {
|
||||
this._var.comments = data;
|
||||
@ -289,8 +272,15 @@ export default class InternalComment {
|
||||
this._var.contactsUpdated = true;
|
||||
}
|
||||
}
|
||||
const lastVisible = this._var.option.showMessageHidden;
|
||||
for (let comment of data) {
|
||||
const div = createElement('div', 'item-div');
|
||||
if (comment.Hidden) {
|
||||
div.classList.add('hidden-content');
|
||||
if (!lastVisible) {
|
||||
div.style.display = 'none';
|
||||
}
|
||||
}
|
||||
const sendto = getMessageSendTo(comment, null, null, r)
|
||||
div.appendChild(createElement('div', div => {
|
||||
div.className = 'item-poster';
|
||||
@ -333,37 +323,19 @@ export default class InternalComment {
|
||||
}
|
||||
div.append(
|
||||
content,
|
||||
createElement('div', div => {
|
||||
div.className = 'item-time';
|
||||
},
|
||||
createElement('span', span => {
|
||||
span.className = 'msgsetting sbutton ' + (comment.Hidden ? 'iconnotview' : 'iconview');
|
||||
span.style.padding = '0px 0px 0px 5px';
|
||||
span.style.fontSize = '12px';
|
||||
span.style.display = this._var.option.showMessageHidden ? '' : 'none';
|
||||
span.addEventListener('click', function () {
|
||||
if (this.classList.contains('iconview')) {
|
||||
func(comment.Id, true);
|
||||
this.classList.remove('iconview');
|
||||
this.classList.add('iconnotview');
|
||||
} else {
|
||||
func(comment.Id, false);
|
||||
this.classList.remove('iconnotview');
|
||||
this.classList.add('iconview');
|
||||
}
|
||||
});
|
||||
}),
|
||||
createElement('span', span => {
|
||||
span.innerText = comment.TimeStr;
|
||||
})
|
||||
)
|
||||
createHideMessageCommentTail(
|
||||
this, 'showMessageHidden',
|
||||
comment, 'TimeStr',
|
||||
func, hisFunc)
|
||||
);
|
||||
children.push(div);
|
||||
}
|
||||
children[0].style.marginTop = '0';
|
||||
}
|
||||
if (this._var.message.children.length > 0) {
|
||||
this._var.lastTop = this._var.message.scrollTop;
|
||||
}
|
||||
this._var.message.replaceChildren(...children);
|
||||
this._var.message.scrollTop = this._var.message.scrollHeight
|
||||
// setTimeout(() => this._var.message.scrollTop = this._var.message.scrollHeight, 0);
|
||||
setTimeout(() => this._var.message.scrollTop = keep ? this._var.lastTop : this._var.message.scrollHeight, 0);
|
||||
}
|
||||
}
|
@ -420,4 +420,99 @@ export function updateCustomerName(messages, contacts) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function createHideMessageTitleButton(This, optionName) {
|
||||
const option = This._var.option;
|
||||
return createElement('span', span => {
|
||||
if (option.userIsAdmin) {
|
||||
if (option[optionName]) {
|
||||
span.className = 'msgadminsetting sbutton iconview';
|
||||
} else {
|
||||
span.className = 'msgadminsetting sbutton iconnotview';
|
||||
}
|
||||
span.style.padding = '0px 0px 0px 5px';
|
||||
setTooltip(span, option?.getText('P_WO_MESSAGEHISTORY_MANAGE', 'Manage Messages'));
|
||||
span.addEventListener('click', function () {
|
||||
const container = This._var.container;
|
||||
if (!option[optionName]) {
|
||||
this.classList.remove('iconnotview');
|
||||
this.classList.add('iconview');
|
||||
option[optionName] = true;
|
||||
container.querySelectorAll('.msgsetting').forEach(x => x.style.display = '');
|
||||
container.querySelectorAll('.msgHistory').forEach(h => h.style.display = h.getAttribute('ModifyCount') > 0 ? '' : 'none');
|
||||
container.querySelectorAll('.hidden-content').forEach(c => c.style.display = '');
|
||||
} else {
|
||||
this.classList.remove('iconview');
|
||||
this.classList.add('iconnotview');
|
||||
option[optionName] = false;
|
||||
container.querySelectorAll('.msgsetting').forEach(x => x.style.display = 'none');
|
||||
container.querySelectorAll('.msgHistory').forEach(h => h.style.display = 'none');
|
||||
container.querySelectorAll('.hidden-content').forEach(c => c.style.display = 'none');
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export function createHideMessageCommentTail(This, optionName, comment, commentTime, func, hisFunc) {
|
||||
const option = This._var.option;
|
||||
const showTooltip = option?.getText('P_WO_MESSAGEHISTORY_VISIBLE', 'Visible');
|
||||
const notShowTooltip = option?.getText('P_WO_MESSAGEHISTORY_NOTVISIBLE', 'Not Visible');
|
||||
return createElement('div', div => {
|
||||
div.className = 'item-time';
|
||||
div.style.display = 'flex';
|
||||
div.style.alignItems = 'center';
|
||||
},
|
||||
createElement('span', span => {
|
||||
span.className = 'msgsetting sbutton ' + (comment.Hidden ? 'iconnotview' : 'iconview');
|
||||
span.style.padding = '0';
|
||||
span.style.fontSize = '12px';
|
||||
setTooltip(span, comment.Hidden ? notShowTooltip : showTooltip);
|
||||
span.style.display = option[optionName] ? '' : 'none';
|
||||
span.addEventListener('click', function () {
|
||||
if (this.classList.contains('iconview')) {
|
||||
func(comment.Id, true);
|
||||
this.classList.remove('iconview');
|
||||
this.classList.add('iconnotview');
|
||||
setTooltip(this, notShowTooltip);
|
||||
} else {
|
||||
func(comment.Id, false);
|
||||
this.classList.remove('iconnotview');
|
||||
this.classList.add('iconview');
|
||||
setTooltip(this, showTooltip);
|
||||
}
|
||||
if (isNaN(comment.ModifyCount)) {
|
||||
comment.ModifyCount = 1;
|
||||
} else {
|
||||
comment.ModifyCount += 1;
|
||||
}
|
||||
const x = This._var.container.querySelector('.history-span-' + comment.Id);
|
||||
if (x != null) {
|
||||
x.setAttribute('ModifyCount', comment.ModifyCount);
|
||||
x.style.display = (option[optionName] && comment.ModifyCount > 0) ? '' : 'none';
|
||||
}
|
||||
});
|
||||
}),
|
||||
createElement('span', span => {
|
||||
span.className = 'msgHistory history-span-' + comment.Id;
|
||||
span.setAttribute('ModifyCount', comment.ModifyCount ?? 0);
|
||||
span.style.display = (option[optionName] && comment.ModifyCount > 0) ? '' : 'none';
|
||||
setTooltip(span, option?.getText('P_WO_MESSAGEHISTORY_HEADER', 'Hidden History'));
|
||||
const icon = createIcon('fa-light', 'wave-sine');
|
||||
icon.style.height = '12px';
|
||||
icon.style.width = '12px';
|
||||
icon.style.margin = '0 5px 0 0';
|
||||
icon.style.cursor = 'pointer';
|
||||
icon.style.border = '1px solid';
|
||||
icon.style.borderRadius = '6px';
|
||||
icon.style.borderColor = '#000';
|
||||
icon.style.display = 'block';
|
||||
span.appendChild(icon);
|
||||
span.addEventListener('click', () => hisFunc(comment.Id));
|
||||
}),
|
||||
createElement('span', span => {
|
||||
span.innerText = comment[commentTime];
|
||||
})
|
||||
);
|
||||
}
|
@ -26,7 +26,9 @@ function fillCheckbox(container, type = 'fa-regular', label, tabindex = -1, char
|
||||
container.appendChild(
|
||||
createElement('span', span => {
|
||||
span.innerText = label;
|
||||
span.title = title;
|
||||
if (title != null) {
|
||||
span.title = title;
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
|
@ -705,6 +705,12 @@
|
||||
}
|
||||
}
|
||||
|
||||
.ui-popup-mask .ui-popup-container .ui-popup-footer {
|
||||
>.ui-sort-layout {
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
}
|
||||
|
||||
/*@media (prefers-color-scheme: dark) {
|
||||
.ui-grid {
|
||||
--cell-hover-bg-color: yellow;
|
||||
|
@ -76,43 +76,47 @@
|
||||
|
||||
--icon-size: 16px;
|
||||
|
||||
>.ui-video-wrapper {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
>.ui-video-content {
|
||||
height: 100%;
|
||||
|
||||
>video {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
>.ui-video-wrapper {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
|
||||
>.ui-video-waiting {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgba(0, 0, 0, .3);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
transition: opacity .2s;
|
||||
|
||||
>svg {
|
||||
fill: #eee;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
top: calc(50% - 15px);
|
||||
left: calc(50% - 15px);
|
||||
animation: spinner 1.2s infinite linear;
|
||||
>video {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
@keyframes spinner {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
>.ui-video-waiting {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgba(0, 0, 0, .3);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
transition: opacity .2s;
|
||||
|
||||
>svg {
|
||||
fill: #eee;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
top: calc(50% - 15px);
|
||||
left: calc(50% - 15px);
|
||||
animation: spinner 1.2s infinite linear;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: rotate(359deg);
|
||||
@keyframes spinner {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: rotate(359deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -120,12 +124,13 @@
|
||||
|
||||
>.ui-video-control {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
height: 70px;
|
||||
bottom: 0;
|
||||
opacity: 0;
|
||||
background: linear-gradient(transparent calc(100% - 100px), rgba(50, 50, 50, .7) calc(100% - 65px), #000);
|
||||
background: linear-gradient(transparent, #000);
|
||||
// calc(100% - 100px), rgba(50, 50, 50, .7) calc(100% - 65px)
|
||||
transition: opacity .5s;
|
||||
|
||||
&:hover,
|
||||
|
@ -204,7 +204,8 @@ export class Dropdown {
|
||||
let label;
|
||||
if (options.input) {
|
||||
label = createElement('input', 'ui-drop-text');
|
||||
label.setAttribute('type', 'text');
|
||||
label.type = 'text';
|
||||
label.draggable = false;
|
||||
options.placeholder && label.setAttribute('placeholder', options.placeholder);
|
||||
isPositive(options.maxLength) && label.setAttribute('maxlength', options.maxLength);
|
||||
isPositive(options.tabIndex) && label.setAttribute('tabindex', options.tabIndex);
|
||||
@ -383,7 +384,7 @@ export class Dropdown {
|
||||
if (!options.input && options.search) {
|
||||
const search = createElement('div', 'ui-drop-search');
|
||||
const input = createElement('input');
|
||||
input.setAttribute('type', 'text');
|
||||
input.type = 'text';
|
||||
isPositive(options.tabIndex) && input.setAttribute('tabindex', options.tabIndex);
|
||||
!nullOrEmpty(options.searchPlaceholder) && input.setAttribute('placeholder', options.searchPlaceholder);
|
||||
input.addEventListener('input', e => {
|
||||
@ -503,7 +504,7 @@ export class Dropdown {
|
||||
}
|
||||
const li = createElement('li');
|
||||
li.dataset.value = val;
|
||||
li.setAttribute('title', item[textkey]);
|
||||
li.title = item[textkey];
|
||||
let label;
|
||||
const html = item[htmlkey];
|
||||
if (html instanceof HTMLElement) {
|
||||
|
@ -71,13 +71,13 @@ let r = lang;
|
||||
/**
|
||||
* 键值字典
|
||||
* @template T
|
||||
* @typedef {Map<string, T>} KeyMap
|
||||
* @typedef {{[key: string]: T}} KeyMap
|
||||
*/
|
||||
|
||||
/**
|
||||
* 索引字典
|
||||
* @template T
|
||||
* @typedef {Map<number, T>} IndexMap
|
||||
* @typedef {{[index: number]: T}} IndexMap
|
||||
*/
|
||||
|
||||
/**
|
||||
@ -134,6 +134,7 @@ let r = lang;
|
||||
* @param {GridRowItem} item - 行数据对象
|
||||
* @param {boolean} editing - 是否处于编辑状态
|
||||
* @param {HTMLElement} [body] - Grid 控件的 `<tbody>` 部分
|
||||
* @param {number} [index] - 所在行索引(不可依赖此值,除了呈现时,其他时候该值不会传递)
|
||||
* @returns {ValueItem} - 返回过滤后的显示或编辑值
|
||||
* @this GridColumnDefinition
|
||||
*/
|
||||
@ -455,6 +456,9 @@ const GridColumnDirection = {
|
||||
* @property {string} [addLevel] - Add Level
|
||||
* @property {string} [deleteLevel] - Delete Level
|
||||
* @property {string} [copyLevel] - Copy Level
|
||||
* @property {string} [sortBy] - Sort by
|
||||
* @property {string} [thenBy] - Then by
|
||||
* @property {string} [updateLayout] - Update Layout
|
||||
* @property {string} [asc] - Ascending
|
||||
* @property {string} [desc] - Descending
|
||||
* @property {string} [column] - Column
|
||||
@ -939,6 +943,13 @@ export class Grid {
|
||||
* @ignore
|
||||
*/
|
||||
headerWrap = true;
|
||||
/**
|
||||
* 是否允许行间拖拽
|
||||
* @type {boolean}
|
||||
* @default false
|
||||
* @ignore
|
||||
*/
|
||||
rowDraggable = false;
|
||||
/**
|
||||
* 监听事件的窗口载体
|
||||
* @type {(Window | HTMLElement)}
|
||||
@ -1060,6 +1071,16 @@ export class Grid {
|
||||
* @this Grid
|
||||
*/
|
||||
onRowCollapsed;
|
||||
/**
|
||||
* 行发生变化时触发的事件
|
||||
* @event
|
||||
* @param {("update" | "add" | "remove")} action - 变动类型
|
||||
* @param {GridRowItem[]} items - 发生变动的行对象
|
||||
* @param {(number | number[])} indexes - 变动的索引集合
|
||||
* @this Grid
|
||||
* @since 1.0.3
|
||||
*/
|
||||
onRowChanged;
|
||||
|
||||
/**
|
||||
* 列类型枚举
|
||||
@ -1099,6 +1120,7 @@ export class Grid {
|
||||
* @property {boolean} [tooltipDisabled=false] - 单元格 tooltip 是否禁用
|
||||
* @property {boolean} [headerVisible=true] - 列头是否显示
|
||||
* @property {boolean} [headerWrap=true] - 列头是否允许换行
|
||||
* @property {boolean} [rowDraggable=false] - 是否允许行间拖拽 @since 1.0.3
|
||||
* @property {(Window | HTMLElement)} [window=global] - 监听事件的窗口载体
|
||||
* @property {number} [sortIndex=-1] - 排序列的索引
|
||||
* @property {GridColumnDirection} [sortDirection=GridColumnDirection.Ascending] - 排序方式,正数升序,负数倒序
|
||||
@ -1332,6 +1354,9 @@ export class Grid {
|
||||
addLevel: r('addLevel', 'Add level'),
|
||||
deleteLevel: r('deleteLevel', 'Delete level'),
|
||||
copyLevel: r('copyLevel', 'Copy level'),
|
||||
sortBy: r('sortBy', 'Sort by'),
|
||||
thenBy: r('thenBy', 'Then by'),
|
||||
updateLayout: r('updateLayout', 'Update Layout'),
|
||||
asc: r('asc', 'Ascending'),
|
||||
desc: r('desc', 'Descending'),
|
||||
column: r('column', 'Column'),
|
||||
@ -1408,6 +1433,30 @@ export class Grid {
|
||||
}
|
||||
this._onRowClicked(e, rowIndex, colIndex);
|
||||
});
|
||||
if (this.rowDraggable) {
|
||||
grid.addEventListener('dragover', e => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
e.dataTransfer.dropEffect = e.ctrlKey ? 'copy' : 'move';
|
||||
});
|
||||
grid.addEventListener('drop', e => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
const src = Number(e.dataTransfer.getData('text'));
|
||||
if (isNaN(src) || src < 0) {
|
||||
return;
|
||||
}
|
||||
const target = this._var.currentSource?.length ?? 0;
|
||||
if (target == null || src === target) {
|
||||
return;
|
||||
}
|
||||
const row = e.ctrlKey ?
|
||||
Object.assign({}, this._var.currentSource[src]?.values) :
|
||||
this.removeItem(src);
|
||||
this.addItem(row, target);
|
||||
this.selectedIndexes = [e.ctrlKey ? target : target - 1];
|
||||
});
|
||||
}
|
||||
container.replaceChildren(grid);
|
||||
const sizer = createElement('span', 'ui-grid-sizer');
|
||||
grid.appendChild(sizer);
|
||||
@ -1719,24 +1768,35 @@ export class Grid {
|
||||
|
||||
/**
|
||||
* 显示多列排序设置面板
|
||||
* @param {Function} [callback] - 更新回调函数 @since 1.0.3
|
||||
* @param {boolean} [layout] - 是否显示更新 layout 复选框 @since 1.0.3
|
||||
* @since 1.0.1
|
||||
*/
|
||||
showSortPanel() {
|
||||
showSortPanel(callback, layout) {
|
||||
const content = createElement('div', 'ui-sort-panel-content');
|
||||
const buttonWrapper = createElement('div', 'ui-sort-panel-buttons');
|
||||
const grid = new Grid(null, r);
|
||||
grid.rowDraggable = true;
|
||||
grid.langs = this.langs;
|
||||
const rowChanged = index => {
|
||||
buttonWrapper.querySelector('.ui-button-delete').disabled = index < 0;
|
||||
buttonWrapper.querySelector('.ui-button-copy').disabled = index < 0;
|
||||
buttonWrapper.querySelector('.ui-button-move-up').disabled = index < 1;
|
||||
buttonWrapper.querySelector('.ui-button-move-down').disabled = index >= grid.source.length - 1;
|
||||
// buttonWrapper.querySelector('.ui-button-move-up').disabled = index < 1;
|
||||
// buttonWrapper.querySelector('.ui-button-move-down').disabled = index >= grid.source.length - 1;
|
||||
};
|
||||
grid.onSelectedRowChanged = rowChanged;
|
||||
grid.onRowChanged = () => {
|
||||
const layout = pop.container.querySelector('.ui-sort-layout');
|
||||
if (layout != null) {
|
||||
layout.classList.remove('disabled');
|
||||
layout.querySelector('input').disabled = false;
|
||||
}
|
||||
};
|
||||
const reload = index => {
|
||||
grid.selectedIndexes = [index];
|
||||
grid.scrollTop = index * (grid.rowHeight + 1);
|
||||
rowChanged(index);
|
||||
grid.onRowChanged();
|
||||
}
|
||||
buttonWrapper.append(
|
||||
createElement('span', 'button',
|
||||
@ -1793,6 +1853,7 @@ export class Grid {
|
||||
});
|
||||
})
|
||||
),
|
||||
/*
|
||||
createElement('span', button => {
|
||||
button.className = 'button ui-button-move-up';
|
||||
const icon = createIcon('fa-light', 'chevron-up');
|
||||
@ -1829,23 +1890,43 @@ export class Grid {
|
||||
});
|
||||
button.appendChild(icon);
|
||||
})
|
||||
//*/
|
||||
);
|
||||
const gridWrapper = createElement('div', 'ui-sort-panel-grid');
|
||||
content.append(buttonWrapper, gridWrapper);
|
||||
const columnSource = this.columns.filter(c => c.sortable !== false && c.visible !== false);
|
||||
const columnSource = this.columns.filter(c => c.sortable !== false); // ticket 56389, && c.visible !== false
|
||||
columnSource.sort((a, b) => a.caption > b.caption ? 1 : -1);
|
||||
grid.columns = [
|
||||
{
|
||||
key: 'column',
|
||||
width: 80,
|
||||
sortable: false,
|
||||
orderable: false,
|
||||
resizable: false,
|
||||
filter: (_item, _editing, _body, index) => index === 0 ? this.langs.sortBy : this.langs.thenBy
|
||||
},
|
||||
{
|
||||
key: 'caption',
|
||||
caption: this.langs.column,
|
||||
width: 270,
|
||||
type: GridColumnTypeEnum.Dropdown,
|
||||
dropOptions: {
|
||||
textKey: 'caption',
|
||||
valueKey: 'key'
|
||||
valueKey: 'caption',
|
||||
input: true
|
||||
},
|
||||
source: columnSource,
|
||||
dropRestrictCase: true,
|
||||
sourceCache: false,
|
||||
source: () => columnSource.filter(c => grid.source?.find(s => s.column === c.key) == null),
|
||||
sortable: false,
|
||||
orderable: false
|
||||
orderable: false,
|
||||
onChanged: (item, _value, _oldValue, e) => {
|
||||
item.column = e.key;
|
||||
const layout = pop.container.querySelector('.ui-sort-layout');
|
||||
if (layout != null) {
|
||||
layout.classList.remove('disabled');
|
||||
layout.querySelector('input').disabled = false;
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'order',
|
||||
@ -1857,7 +1938,14 @@ export class Grid {
|
||||
{ value: 'desc', text: this.langs.desc }
|
||||
],
|
||||
sortable: false,
|
||||
orderable: false
|
||||
orderable: false,
|
||||
onChanged: () => {
|
||||
const layout = pop.container.querySelector('.ui-sort-layout');
|
||||
if (layout != null) {
|
||||
layout.classList.remove('disabled');
|
||||
layout.querySelector('input').disabled = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
];
|
||||
const pop = new Popup({
|
||||
@ -1871,6 +1959,14 @@ export class Grid {
|
||||
const source = grid.source;
|
||||
if (source == null || source.length === 0) {
|
||||
this.sortArray = null;
|
||||
// arrow icon
|
||||
[...this._headerCells].forEach((th, i) => {
|
||||
const arrow = th.querySelector('.arrow');
|
||||
if (arrow == null) {
|
||||
return;
|
||||
}
|
||||
arrow.className = 'arrow';
|
||||
});
|
||||
} else {
|
||||
const dict = {};
|
||||
for (let i = 0; i < source.length; ++i) {
|
||||
@ -1895,12 +1991,12 @@ export class Grid {
|
||||
}
|
||||
dict[it.column] = true;
|
||||
}
|
||||
this.sortArray = source;
|
||||
this.sortArray = source.map(s => ({ column: s.column, order: s.order }));
|
||||
this.sortDirection = 1;
|
||||
this.sort();
|
||||
}
|
||||
if (typeof this.onSorted === 'function') {
|
||||
this.onSorted(this.sortArray);
|
||||
if (typeof callback === 'function') {
|
||||
callback.call(this, this.sortArray, pop.container.querySelector('.ui-sort-layout>input')?.checked);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -1909,11 +2005,29 @@ export class Grid {
|
||||
],
|
||||
onResizeEnded: () => grid.resize()
|
||||
});
|
||||
const source = this.sortArray || [{ column: '', order: 'asc' }];
|
||||
let source = this.sortArray;
|
||||
if (source == null && this.sortIndex >= 0) {
|
||||
const col = this.columns[this.sortIndex];
|
||||
if (col != null) {
|
||||
source = [{ column: col.key, order: this.sortDirection > 0 ? 'asc' : 'desc' }];
|
||||
}
|
||||
}
|
||||
source ??= [{ column: '', order: 'asc' }];
|
||||
pop.show(this._var.el).then(() => {
|
||||
pop.container.style.cssText += 'width: 520px; height: 400px';
|
||||
pop.container.style.cssText += 'width: 600px; height: 460px';
|
||||
if (layout) {
|
||||
const footer = pop.container.querySelector('.ui-popup-footer');
|
||||
footer.insertBefore(createCheckbox({
|
||||
label: this.langs.updateLayout,
|
||||
className: 'ui-sort-layout',
|
||||
enabled: false
|
||||
}), footer.children[0]);
|
||||
}
|
||||
grid.init(gridWrapper);
|
||||
grid.source = source.filter(s => s.column === '' || columnSource.find(c => c.key === s.column) != null);
|
||||
grid.source = source
|
||||
.map(s => (s.c = columnSource.find(c => c.key === s.column), s))
|
||||
.filter(s => s.column === '' || s.c != null)
|
||||
.map(s => ({ column: s.column, caption: s.c?.caption ?? '', order: s.order }));
|
||||
grid.selectedIndexes = [0];
|
||||
grid.refresh();
|
||||
rowChanged(0);
|
||||
@ -1942,6 +2056,9 @@ export class Grid {
|
||||
} else {
|
||||
this.refresh();
|
||||
}
|
||||
if (typeof this.onRowChanged === 'function') {
|
||||
this.onRowChanged('update', [item], index);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1980,6 +2097,9 @@ export class Grid {
|
||||
} else {
|
||||
this.reload();
|
||||
}
|
||||
if (typeof this.onRowChanged === 'function') {
|
||||
this.onRowChanged('add', [item], index);
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
@ -2024,6 +2144,9 @@ export class Grid {
|
||||
} else {
|
||||
this.reload();
|
||||
}
|
||||
if (typeof this.onRowChanged === 'function') {
|
||||
this.onRowChanged('add', array, index);
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
@ -2053,6 +2176,9 @@ export class Grid {
|
||||
this._var.selectedIndexes = [];
|
||||
}
|
||||
this.reload();
|
||||
if (typeof this.onRowChanged === 'function') {
|
||||
this.onRowChanged('remove', [it.values], index);
|
||||
}
|
||||
return it.values;
|
||||
}
|
||||
|
||||
@ -2098,11 +2224,14 @@ export class Grid {
|
||||
it.__index -= offset;
|
||||
}
|
||||
const index = indexes[0];
|
||||
if (index < 1) {
|
||||
if (index > 0) {
|
||||
this._var.selectedIndexes = [index - 1];
|
||||
} else {
|
||||
this._var.selectedIndexes = [];
|
||||
}
|
||||
if (typeof this.onRowChanged === 'function') {
|
||||
this.onRowChanged('remove', array, indexes);
|
||||
}
|
||||
this.reload();
|
||||
return array;
|
||||
}
|
||||
@ -2144,7 +2273,7 @@ export class Grid {
|
||||
align: c.align,
|
||||
visible: c.visible
|
||||
})),
|
||||
source: this.source?.map(s => {
|
||||
source: this.source?.map((s, i) => {
|
||||
const item = Object.create(null);
|
||||
for (let c of this.columns) {
|
||||
if (c.key == null) {
|
||||
@ -2154,7 +2283,7 @@ export class Grid {
|
||||
if (c.text != null) {
|
||||
val = c.text;
|
||||
} else if (typeof c.filter === 'function') {
|
||||
val = c.filter(s, false, this._var.refs.body);
|
||||
val = c.filter(s, false, this._var.refs.body, i);
|
||||
} else {
|
||||
val = s[c.key];
|
||||
if (val != null) {
|
||||
@ -2676,6 +2805,34 @@ export class Grid {
|
||||
const readonly = this.readonly;
|
||||
for (let i = 0; i < count; ++i) {
|
||||
const row = createElement('tr', 'ui-grid-row');
|
||||
if (this.rowDraggable) {
|
||||
row.draggable = true;
|
||||
row.addEventListener('dragstart', e => {
|
||||
e.dataTransfer.setData('text', String(this._var.startIndex + exists + i));
|
||||
});
|
||||
row.addEventListener('dragover', e => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
e.dataTransfer.dropEffect = e.ctrlKey ? 'copy' : 'move';
|
||||
});
|
||||
row.addEventListener('drop', e => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
const src = Number(e.dataTransfer.getData('text'));
|
||||
if (isNaN(src) || src < 0) {
|
||||
return;
|
||||
}
|
||||
const target = this._var.startIndex + exists + i;
|
||||
if (src === target) {
|
||||
return;
|
||||
}
|
||||
const row = e.ctrlKey ?
|
||||
Object.assign({}, this._var.currentSource[src]?.values) :
|
||||
this.removeItem(src);
|
||||
this.addItem(row, target);
|
||||
this.selectedIndexes = [target];
|
||||
});
|
||||
}
|
||||
const virtualRow = { cells: {} };
|
||||
this._var.virtualRows[exists + i] = virtualRow;
|
||||
let left = this.expandable ? ExpandableWidth : 0;
|
||||
@ -2852,7 +3009,7 @@ export class Grid {
|
||||
if (col.text != null) {
|
||||
val = col.text;
|
||||
} else if (typeof col.filter === 'function') {
|
||||
val = col.filter(item, selected, this._var.refs.body);
|
||||
val = col.filter(item, selected, this._var.refs.body, startIndex + i);
|
||||
} else {
|
||||
val = item[col.key];
|
||||
if (val != null) {
|
||||
|
@ -158,6 +158,7 @@ export function createFile(url, icon = 'file-alt') {
|
||||
* @param {boolean} options.[autoPlay] - 是否自动播放
|
||||
* @param {boolean} options.[autoFullScreen] - 是否自动全屏
|
||||
* @param {boolean} options.[autoLoop] - 是否循环播放
|
||||
* @param {Function} options.[onLoaded] - 视频加载完成回调
|
||||
* @param {Function} [callback] - 视频元素处理回调函数
|
||||
* @returns {HTMLDivElement} 返回联动视频元素
|
||||
*/
|
||||
@ -330,6 +331,9 @@ export function createVideoList(urls, options, callback) {
|
||||
controller.classList.add('no-fullscreen');
|
||||
}
|
||||
|
||||
const content = createElement('div', 'ui-video-content');
|
||||
container.append(content, controller);
|
||||
|
||||
urls.forEach((url, i) => {
|
||||
const video = createElement('video');
|
||||
videos[i] = video;
|
||||
@ -349,17 +353,22 @@ export function createVideoList(urls, options, callback) {
|
||||
video.volume = 0;
|
||||
}
|
||||
prepared += 1;
|
||||
if (options?.autoPlay && prepared >= length) {
|
||||
// auto play
|
||||
videos.forEach(v => v.play().catch(() => { }));
|
||||
if (options?.autoFullScreen && length === 1 && document.fullscreenElement == null) {
|
||||
video.requestFullscreen().catch(() => { });
|
||||
if (prepared >= length) {
|
||||
if (options?.autoPlay) {
|
||||
// auto play
|
||||
videos.forEach(v => v.play().catch(() => { }));
|
||||
if (options?.autoFullScreen && length === 1 && document.fullscreenElement == null) {
|
||||
video.requestFullscreen().catch(() => { });
|
||||
}
|
||||
}
|
||||
if (typeof options?.onLoaded === 'function') {
|
||||
options.onLoaded();
|
||||
}
|
||||
}
|
||||
});
|
||||
video.addEventListener('progress', () => {
|
||||
const buffered = video.buffered;
|
||||
for (let i = 0; i < buffered.length; i += 1) {
|
||||
for (let i = 0; i < buffered.length; ++i) {
|
||||
let buffer = seekBufferBar.children[i];
|
||||
if (buffer == null) {
|
||||
seekBufferBar.append(buffer = createElement('div', 'ui-video-buffer'));
|
||||
@ -435,9 +444,8 @@ export function createVideoList(urls, options, callback) {
|
||||
if (typeof callback === 'function') {
|
||||
callback(wrapper);
|
||||
}
|
||||
container.append(wrapper);
|
||||
content.append(wrapper);
|
||||
});
|
||||
container.append(controller);
|
||||
|
||||
return container;
|
||||
}
|
661
package-lock.json
generated
661
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
10
package.json
10
package.json
@ -29,13 +29,13 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@mxssfd/typedoc-theme": "^1.1.3",
|
||||
"clean-jsdoc-theme": "^4.2.18",
|
||||
"clean-jsdoc-theme": "^4.3.0",
|
||||
"docdash": "^2.0.2",
|
||||
"jsdoc": "^4.0.2",
|
||||
"postcss-preset-env": "^9.5.9",
|
||||
"sass": "^1.75.0",
|
||||
"jsdoc": "^4.0.3",
|
||||
"postcss-preset-env": "^9.5.12",
|
||||
"sass": "^1.77.1",
|
||||
"typedoc": "^0.25.13",
|
||||
"vite": "^5.2.10",
|
||||
"vite": "^5.2.11",
|
||||
"vite-plugin-externals": "^0.6.2"
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user