diff --git a/docs/diy/RADEME.md b/docs/diy/RADEME.md index e25d92996..4d8678fb9 100644 --- a/docs/diy/RADEME.md +++ b/docs/diy/RADEME.md @@ -40,6 +40,15 @@ create table if not exists lucky_diy_view_util ```sql insert into lucky_diy_view_util (name, title, type, value, addon_name, sort, support_diy_view, max_count, is_delete, icon, icon_type) values ('test', '测试', 'SYSTEM', '{"test": "test"}', '', 0, '', 0, 0, '', 0); + +--- 微信视频号 +-- 仅当WechatChannel不存在时添加记录 +INSERT INTO lucky_diy_view_util (`name`, `title`, `type`, `value`, `addon_name`, `sort`, `support_diy_view`, `max_count`, `is_delete`, `icon`, `icon_type`) +SELECT 'WechatChannel', '微信视频号', 'SYSTEM', '{ "list": [{ "channelName":"", "finderUserName": "", "avatarImageType": "url", "avatarUrl": "", "videoTitle": "", "coverImageType": "url", "coverUrl": "", "feedId": "", "feedToken": "", "viewCount": 0, "showViewCount": true, "embedMode": false, "channelType":"wechat" }], "rowCount": 2, "showStyle": "fixed", "aspectRatio":"16:9", "titleLineClamp": 1, "showPlayBtn": true}', '', 100110, '', 0, 0, '/public/static/img/svg/xuanxiangka.svg', 0 +WHERE NOT EXISTS ( + SELECT 1 FROM lucky_diy_view_util WHERE name = 'WechatChannel' +); + ``` diff --git a/src/app/component/view/wechat_channel/css/design.css b/src/app/component/view/wechat_channel/css/design.css index ca621147d..d5b47f7b4 100644 --- a/src/app/component/view/wechat_channel/css/design.css +++ b/src/app/component/view/wechat_channel/css/design.css @@ -1,65 +1,249 @@ -.wechat_channel-box .preview-draggable {padding: 0;} -.wechat_channel-box .video-wrap{position: relative;} -.wechat_channel-box .video-wrap .channel-preview img{width: 100%;display: block;} -.wechat_channel-box .video-wrap .channel-info { - position: absolute; - bottom: 0; - left: 0; - right: 0; - background: linear-gradient(to top, rgba(0,0,0,0.7), transparent); - padding: 20px 10px 10px; - color: #fff; - display: flex; - align-items: center; +.wechat_channel-box .preview-draggable { + padding: 15px; } -.wechat_channel-box .video-wrap .channel-avatar { + +.wechat_channel-box .video-list-wrap { + position: relative; +} + +.wechat_channel-box .video-list { + display: grid; + grid-template-columns: repeat(var(--row-count, 2), 1fr); + gap: 8px; + padding: 16px 16px 0px; +} + +.wechat_channel-box .video-item { + position: relative; + width: 100%; +} + +.wechat_channel-box .video-wrap { + position: relative; +} + +.wechat_channel-box .video-wrap .channel-preview { + position: relative; + width: 100%; + overflow: hidden; + border-radius: 5px; +} + +.wechat_channel-box .video-item .channel-preview img { + display: block; + width: 100%; + object-fit: cover; + border-radius: 5px; +} + +.wechat_channel-box .video-item .channel-preview { + position: relative; + width: 100%; + overflow: hidden; + border-radius: 5px; +} + +.wechat_channel-box .video-item .play-btn { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); width: 40px; height: 40px; + background: rgba(0, 0, 0, 0.6); border-radius: 50%; - overflow: hidden; - margin-right: 10px; - flex-shrink: 0; + display: flex; + align-items: center; + justify-content: center; + z-index: 10; } -.wechat_channel-box .video-wrap .channel-avatar img { - width: 100%; - height: 100%; - object-fit: cover; + +.wechat_channel-box .video-item .play-btn::before { + content: ''; + width: 0; + height: 0; + border-style: solid; + border-width: 10px 0 10px 16px; + border-color: transparent transparent transparent #fff; + margin-left: 2px; } -.wechat_channel-box .video-wrap .channel-text { + +.wechat_channel-box .video-item .view-count { + position: absolute; + right: 2px; + font-size: 12px; + color: #fff; + padding: 4px 4px; + /* border-radius: 16px; */ + margin-bottom: 0; + z-index: 10; + text-shadow: 2px 2px 3px rgba(0, 0, 0, 0.5); +} + +.wechat_channel-box .video-item .channel-info { + position: relative; + padding: 8px; + background: #fff; + border-radius: 0 0 8px 8px; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); + margin-top: -4px; +} + +.wechat_channel-box .video-item .channel-avatar { + display: none; +} + +.wechat_channel-box .video-item .channel-text { flex: 1; overflow: hidden; } -.wechat_channel-box .video-wrap .channel-name { - font-size: 14px; - font-weight: bold; + +.wechat_channel-box .video-item .channel-name { + display: none; +} + +.wechat_channel-box .video-item .video-title { + font-size: 13px; + font-weight: 500; + color: #333; + overflow: hidden; + margin-bottom: 3px; + text-overflow: ellipsis; + display: -webkit-box; + -webkit-box-orient: vertical; + word-break: break-all; + word-wrap: break-word; + white-space: normal; +} + +/* 1行标题 */ +.wechat_channel-box .video-item .video-title.title-max-lines-1 { + -webkit-line-clamp: 1; +} + +/* 2行标题 */ +.wechat_channel-box .video-item .video-title.title-max-lines-2 { + -webkit-line-clamp: 2; margin-bottom: 4px; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; } -.wechat_channel-box .video-wrap .video-title { - font-size: 12px; - opacity: 0.9; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; + +/* 3行标题 */ +.wechat_channel-box .video-item .video-title.title-max-lines-3 { + -webkit-line-clamp: 3; + margin-bottom: 4px; } -.wechat_channel-box .video-wrap .video-placeholder { - width: 100%; + +.wechat_channel-box .video-item .bottom-text { + font-size: 14px; + color: #666; + margin-top: 8px; + line-height: 1.4; + font-style: normal; +} + +.wechat_channel-box .video-item .video-placeholder { height: 200px; background: #f5f5f5; display: flex; align-items: center; justify-content: center; border: 1px dashed #ddd; + border-radius: 5px; } -.wechat_channel-box .video-wrap .placeholder-text { + +.wechat_channel-box .video-item .placeholder-text { color: #999; font-size: 14px; } -.wechat_channel-box .edit-attribute .attr-wrap .restore-wrap .video-add-box .img-block {width: 200px !important;height: 125px !important;margin-bottom: 30px;margin-right: 0;position: relative;} -.wechat_channel-box .edit-attribute .attr-wrap .restore-wrap .video-add-box .img-block > div {line-height: 125px;height: 125px !important;width: 100%;text-align: center;} -.wechat_channel-box .edit-attribute .attr-wrap .restore-wrap .video-add-box .img-block video {width: 100% !important;height: 125px !important;} -.wechat_channel-box .edit-attribute .attr-wrap .restore-wrap .video-add-box .img-block span{position: absolute;top: 50%;left: 50%;transform: translate(-50%, -50%);} -.wechat_channel-box .video-zhezhao {position: absolute;background: #fff;width: 61%;height: 125px;top: 1px;right: 32px;text-align: center;line-height: 105px;display: none;} -.wechat_channel-box .video-zhezhao span {position: absolute;top: 35px;left: 80px;color: #909399;} \ No newline at end of file + +/* 16:9比例下的固定高度 */ +/* 一行显示1个 */ +.wechat_channel-box[data-ratio="16:9"] { + --image-height: 212px; +} +/* 一行显示2个 */ +.wechat_channel-box[data-ratio="16:9"][data-row-count="2"] { + --image-height: 104px; +} +/* 一行显示3个 */ +.wechat_channel-box[data-ratio="16:9"][data-row-count="3"] { + --image-height: 65px; +} +/* 一行显示4个 */ +.wechat_channel-box[data-ratio="16:9"][data-row-count="4"] { + --image-height: 47px; +} + +/* 3:4比例下的固定高度 */ +/* 一行显示1个 */ +.wechat_channel-box[data-ratio="3:4"] { + --image-height: 408px; +} +/* 一行显示2个 */ +.wechat_channel-box[data-ratio="3:4"][data-row-count="2"] { + --image-height: 200px; +} +/* 一行显示3个 */ +.wechat_channel-box[data-ratio="3:4"][data-row-count="3"] { + --image-height: 130px; +} +/* 一行显示4个 */ +.wechat_channel-box[data-ratio="3:4"][data-row-count="4"] { + --image-height: 96px; +} + +.wechat_channel-box .video-item .channel-preview img { + height: var(--image-height); +} + +.wechat_channel-box .video-item .view-count { + top: calc(var(--image-height) - 32px); +} + +.wechat_channel-box .edit-attribute .attr-wrap .restore-wrap .video-add-box .img-block { + width: 200px !important; + height: 125px !important; + margin-bottom: 30px; + margin-right: 0; + position: relative; +} + +.wechat_channel-box .edit-attribute .attr-wrap .restore-wrap .video-add-box .img-block>div { + line-height: 125px; + height: 125px !important; + width: 100%; + text-align: center; +} + +.wechat_channel-box .edit-attribute .attr-wrap .restore-wrap .video-add-box .img-block video { + width: 100% !important; + height: 125px !important; +} + +.wechat_channel-box .edit-attribute .attr-wrap .restore-wrap .video-add-box .img-block span { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); +} + +.wechat_channel-box .video-zhezhao { + position: absolute; + background: #fff; + width: 61%; + height: 125px; + top: 1px; + right: 32px; + text-align: center; + line-height: 105px; + display: none; +} + +.wechat_channel-box .video-zhezhao span { + position: absolute; + top: 35px; + left: 80px; + color: #909399; +} + +/* .wechat_channel-box .layui-form-label + .layui-input-block {margin-left: 0 !important;} */ \ No newline at end of file diff --git a/src/app/component/view/wechat_channel/design.html b/src/app/component/view/wechat_channel/design.html index 1c4eae6e1..1c0949c20 100644 --- a/src/app/component/view/wechat_channel/design.html +++ b/src/app/component/view/wechat_channel/design.html @@ -1,26 +1,43 @@ - + @@ -37,7 +54,7 @@ diff --git a/src/app/component/view/wechat_channel/js/design.js b/src/app/component/view/wechat_channel/js/design.js index 8cad53a14..242ab040d 100644 --- a/src/app/component/view/wechat_channel/js/design.js +++ b/src/app/component/view/wechat_channel/js/design.js @@ -1,91 +1,508 @@ -var tpl = '
'; +Vue.component("wechat_channel-edit", { + template: `
+
+

容器设置

+ + +
+ +
+ +
+
+ + +
+ +
+ + +
+
+ + +
+ +
+ + +
+
+ + +
+ +
+ +
+
+ + +
+ +
+ +
+
+
+ +
+

视频列表

+ + +
+
+
+ 拖拽排序 +
+
+

视频 {{ index + 1 }}

+ +
+ + +
+ +
+ +
+
- tpl += '
'; - tpl += '

基础设置

'; + +
+ +
+ +
+
+ + +
+ +
+ +
+
+ + +
+ +
+ + +
+
- // 根据微信视频号组件的要求,填写视频号的标题和描述 + +
+ +
+ +
+
- // 填写视频号名称 - tpl += '
'; - tpl += ''; - tpl += '
'; - tpl += ''; - tpl += '
'; - tpl += '
'; + +
+ +
+
+
+
+ +

点击上传

+
+
+ + x +
+
+
+ + +
+ +
+ +
+
+ + +
+ +
+ +
+
+ + +
+ +
+ + +
+
+ + +
+ +
+ +
+
- // 填写视频号头像URL - tpl += '
'; - tpl += ''; - tpl += '
'; - tpl += ''; - tpl += '
'; - tpl += '
'; - - // 填写视频标题 - tpl += '
'; - tpl += ''; - tpl += '
'; - tpl += ''; - tpl += '
'; - tpl += '
'; - - // 填写视频号内容ID - tpl += '
'; - tpl += ''; - tpl += '
'; - tpl += ''; - tpl += '
'; - tpl += '
'; - - - // 视频封面支持选择类型,直接上传或选择 - tpl += '
'; - tpl += ''; - tpl += '
'; - tpl += ''; - tpl += '
'; - tpl += '
'; - - // 填写视频封面URL - tpl += '
'; - tpl += ''; - tpl += '
'; - tpl += ''; - tpl += '
'; - tpl += '
'; - - // 上传视频封面 - tpl += '
'; - tpl += ''; - tpl += ''; - tpl += '
'; - - tpl += '
'; - - tpl += '
'; - -Vue.component("wechat_channel-edit",{ + +
+ +
+
+
+
+ +

点击上传

+
+
+ + x +
+
+
推荐使用 200x200 像素的图片
+
+
+
+ + + +
+
`, data: function () { return { - data: this.$parent.data, + data: this.$parent.data }; }, - created : function(){ - if(!this.$parent.data.verify) this.$parent.data.verify = []; + created: function () { + if (!this.$parent.data.verify) this.$parent.data.verify = []; this.$parent.data.verify.push(this.verify);//加载验证方法 - this.$parent.data.ignore = ['textColor','componentBgColor','elementBgColor','elementAngle'];//加载忽略内容 -- 其他设置中的属性设置 + this.$parent.data.ignore = ['textColor', 'componentBgColor', 'elementBgColor', 'elementAngle'];//加载忽略内容 -- 其他设置中的属性设置 this.$parent.data.ignoreLoad = true; // 等待忽略数组赋值后加载 }, + mounted: function () { + console.log("wechat_channel-edit", this.data) + + // 初始化数据结构 + if (!this.data.list) { + this.data.list = []; + } + + if (!this.data.rowCount) { + this.data.rowCount = 2; + } + + if (!this.data.showStyle) { + this.data.showStyle = 'fixed'; + } + + if (!this.data.aspectRatio) { + this.data.aspectRatio = '16:9'; + } + + if (!this.data.titleLineClamp) { + this.data.titleLineClamp = 1; + } + + if (this.data.showPlayBtn === undefined) { + this.data.showPlayBtn = true; + } + + // 初始化列表项 + this.data.list.forEach((item, index) => { + if (!item.avatarImageType) { + item.avatarImageType = 'url'; + } else if (item.avatarUrl && item.avatarImageType == 'upload') { + var val = '头像'; + $("#avatarImg_" + index).html(val); + } + + if (!item.coverImageType) { + item.coverImageType = 'url'; + } else if (item.coverUrl && item.coverImageType == 'upload') { + var val = '封面'; + $("#coverImg_" + index).html(val); + } + + if (item.showViewCount === undefined) { + item.showViewCount = true; + } + }); + + layui.use(['form'], () => { + var form = layui.form; + form.render(); + + // 头像类型切换 + form.on('radio(avatarType)', (data) => { + const elem = data.elem; + const type = elem.value; + const index = elem.dataset.index; + + if (index !== undefined && this.data.list[index]) { + this.data.list[index].avatarImageType = type; + + this.$nextTick(() => { + if (type == 'upload' && this.data.list[index].avatarUrl) { + var val = '头像'; + $("#avatarImg_" + index).html(val); + } + }); + } + }); + + // 封面类型切换 + form.on('radio(coverImageType)', (data) => { + const elem = data.elem; + const type = elem.value; + const index = elem.dataset.index; + + if (index !== undefined && this.data.list[index]) { + this.data.list[index].coverImageType = type; + + this.$nextTick(() => { + if (type == 'upload' && this.data.list[index].coverUrl) { + var val = '封面'; + $("#coverImg_" + index).html(val); + } + }); + } + }); + + // 封面比例切换 + form.on('radio(aspectRatio)', (data) => { + const elem = data.elem; + const ratio = elem.value; + this.data.aspectRatio = ratio; + }); + + // 标题最多行数切换 + form.on('select(titleLineClamp)', (data) => { + const lines = parseInt(data.value); + this.data.titleLineClamp = lines; + }); + + // 每行显示数量切换 + form.on('select(rowCount)', (data) => { + const count = parseInt(data.value); + this.data.rowCount = count; + }); + + // 显示风格切换 + form.on('radio(showStyle)', (data) => { + const elem = data.elem; + const style = elem.value; + this.data.showStyle = style; + }); + + // 显示播放按钮切换 + form.on('switch(showPlayBtn)', (data) => { + const elem = data.elem; + const checked = elem.checked; + this.data.showPlayBtn = checked; + }); + + // 显示观看次数切换 + form.on('switch', (data) => { + const elem = data.elem; + const checked = elem.checked; + // 查找对应的视频号索引 + const videoItem = elem.closest('.video-item-edit'); + if (videoItem) { + const index = videoItem.dataset.index; + if (index !== undefined && this.data.list[index]) { + this.data.list[index].showViewCount = checked; + this.$forceUpdate(); + } + } + }); + }); + + // 初始化拖拽排序 + this.initSortable(); + }, methods: { - verify : function () { - var res = { code : true, message : "" }; + verify: function () { + var res = { code: true, message: "" }; // 微信视频号组件暂不需要强制验证 return res; + }, + + // 上传封面图片 + uploadCover: function (index) { + + // 从媒体库中选择 + openAlbum((data) => { + const imgUrl = data[0].pic_path; + var val = '封面'; + $("#coverImg_" + index).html(val); + + if (this.data.list[index]) { + this.data.list[index].coverUrl = imgUrl; + } + }, 1); + }, + + // 上传头像图片 + uploadAvatar: function (index) { + + // 从媒体库中选择 + openAlbum((data) => { + const imgUrl = data[0].pic_path; + var val = '头像'; + $("#avatarImg_" + index).html(val); + + if (this.data.list[index]) { + this.data.list[index].avatarUrl = imgUrl; + } + }, 1); + }, + + // 添加视频号 + addVideoItem: function () { + this.data.list.push({ + "channelType": "wechat", + "channelName": "", + "finderUserName": "", + "avatarImageType": "url", + "avatarUrl": "", + "videoTitle": "", + "coverImageType": "url", + "coverUrl": "", + "feedId": "", + "feedToken": "", + "viewCount": 0, + "showViewCount": true, + "embedMode": false + }); + this.$forceUpdate(); + this.$parent.$forceUpdate(); + + // 重新渲染表单并绑定事件 + this.$nextTick(() => { + layui.use(['form'], () => { + var form = layui.form; + form.render(); + + // 重新绑定头像类型切换事件 + form.on('radio(avatarType)', (data) => { + const elem = data.elem; + const type = elem.value; + const index = elem.dataset.index; + + if (index !== undefined && this.data.list[index]) { + this.data.list[index].avatarImageType = type; + this.$forceUpdate(); + + this.$nextTick(() => { + if (type == 'upload' && this.data.list[index].avatarUrl) { + var val = '头像'; + $("#avatarImg_" + index).html(val); + } + }); + } + }); + + // 重新绑定封面类型切换事件 + form.on('radio(coverImageType)', (data) => { + const elem = data.elem; + const type = elem.value; + const index = elem.dataset.index; + + if (index !== undefined && this.data.list[index]) { + this.data.list[index].coverImageType = type; + this.$forceUpdate(); + + this.$nextTick(() => { + if (type == 'upload' && this.data.list[index].coverUrl) { + var val = '封面'; + $("#coverImg_" + index).html(val); + } + }); + } + }); + }); + + // 重新初始化拖拽排序 + this.initSortable(); + }); + }, + + // 删除视频号 + removeVideoItem: function (index) { + this.data.list.splice(index, 1); + this.$forceUpdate(); + this.$parent.$forceUpdate(); + + // 重新初始化拖拽排序 + this.$nextTick(() => { + this.initSortable(); + }); + }, + + // 初始化拖拽排序 + initSortable: function () { + // 检查Sortable库是否已加载 + if (typeof Sortable !== 'undefined') { + const videoList = document.getElementById('videoListEdit'); + if (videoList) { + // 销毁现有实例 + if (this.sortableInstance) { + this.sortableInstance.destroy(); + } + + // 创建新的Sortable实例 + this.sortableInstance = new Sortable(videoList, { + handle: '.drag-handle', + animation: 150, + onEnd: (evt) => { + // 获取拖拽前后的索引 + const oldIndex = evt.oldIndex; + const newIndex = evt.newIndex; + + // 重新排序数组 + if (oldIndex !== newIndex) { + const [movedItem] = this.data.list.splice(oldIndex, 1); + this.data.list.splice(newIndex, 0, movedItem); + + // 强制更新视图 + this.$forceUpdate(); + this.$parent.$forceUpdate(); + + // 重新渲染表单 + layui.use(['form'], () => { + var form = layui.form; + form.render(); + }); + } + } + }); + } + } else { + // 如果Sortable库未加载,尝试动态加载 + const script = document.createElement('script'); + script.src = 'https://cdnjs.cloudflare.com/ajax/libs/Sortable/1.15.0/Sortable.min.js'; + script.onload = () => { + this.initSortable(); + }; + document.head.appendChild(script); + } } }, - template: tpl }); \ No newline at end of file diff --git a/src/app/shop/view/diy/iconfont_component.html b/src/app/shop/view/diy/iconfont_component.html index 7826692bd..3c7adc6ce 100644 --- a/src/app/shop/view/diy/iconfont_component.html +++ b/src/app/shop/view/diy/iconfont_component.html @@ -65,7 +65,7 @@ }, iconStyle(){ if (!this.value) return {}; - console.log(this.value) + // console.log(this.value) var style = { fontSize: this.value.fontSize + '%' } diff --git a/src/public/static/ext/diyview/css/diyview.css b/src/public/static/ext/diyview/css/diyview.css index 9f74cc580..55d52dcb1 100644 --- a/src/public/static/ext/diyview/css/diyview.css +++ b/src/public/static/ext/diyview/css/diyview.css @@ -149,7 +149,7 @@ /* 选中弹窗广告组件 */ .pop-window-wrap.selected .edit-attribute{display: block;} -.edit-attribute .attr-wrap {width: 392px;overflow-x: hidden;overflow-y: auto;height: 600px;} +.edit-attribute .attr-wrap {width: 392px;overflow-x: hidden;overflow-y: auto;min-height: 200px;max-height: calc(100vh - 150px);} .edit-attribute .attr-wrap .restore-wrap {width: 360px;} .edit-attribute .attr-wrap .restore-wrap .layui-form-label {color: #666 !important;} .edit-attribute .attr-wrap .restore-wrap .attr-title {padding: 10px 0 15px 10px;border-bottom: 2px solid #f2f4f6;margin-bottom: 10px;color: #303133;display: flex;justify-content: space-between;align-items: center;} diff --git a/src/public/static/ext/diyview/js/custom_template.js b/src/public/static/ext/diyview/js/custom_template.js index e0dab71f3..818a3ce41 100644 --- a/src/public/static/ext/diyview/js/custom_template.js +++ b/src/public/static/ext/diyview/js/custom_template.js @@ -476,8 +476,6 @@ var vue = new Vue({ // 如果当前编辑的组件不存在了,则选中最后一个 if (parseInt(self.currentIndex) >= self.data.length) self.currentIndex--; - $(".draggable-element[data-index=" + self.currentIndex + "] .edit-attribute .attr-wrap").css("height", ($(window).height() - 135) + "px"); - }, 50); }, @@ -630,7 +628,8 @@ function fullScreenSize(isFull) { }); $('.loading-layer').css('height', (commonHeight - 70) + "px"); // 70px是头部高度 $(".component-list nav").css("height", (commonHeight + 20 - 55) + "px");// 20px是自定义模板区域上内边距,55px是标准/第三方组件tab切换高度 - $(".edit-attribute .attr-wrap").css("height", (commonHeight - 1) + "px");// 1px是上边框 + // 设置属性编辑器的最大高度,与预览容器保持一致 + $(".edit-attribute .attr-wrap").css("max-height", (commonHeight) + "px"); $(".preview-block").css("min-height", (commonHeight - 104) + "px"); // 公式:高度 - 自定义模板区域上内边距(20px) - 自定义模板区域下外编辑(20px)- 自定义模板头部(64px) } diff --git a/src/public/static/js/Sortable.min.js b/src/public/static/js/Sortable.min.js new file mode 100644 index 000000000..17bb16c73 --- /dev/null +++ b/src/public/static/js/Sortable.min.js @@ -0,0 +1,2 @@ +/*! Sortable 1.15.0 - MIT | git://github.com/SortableJS/Sortable.git */ +!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t=t||self).Sortable=e()}(this,function(){"use strict";function e(e,t){var n,o=Object.keys(e);return Object.getOwnPropertySymbols&&(n=Object.getOwnPropertySymbols(e),t&&(n=n.filter(function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable})),o.push.apply(o,n)),o}function M(o){for(var t=1;tt.length)&&(e=t.length);for(var n=0,o=new Array(e);n"===e[0]&&(e=e.substring(1)),t))try{if(t.matches)return t.matches(e);if(t.msMatchesSelector)return t.msMatchesSelector(e);if(t.webkitMatchesSelector)return t.webkitMatchesSelector(e)}catch(t){return}}function N(t,e,n,o){if(t){n=n||document;do{if(null!=e&&(">"!==e[0]||t.parentNode===n)&&p(t,e)||o&&t===n)return t}while(t!==n&&(t=(i=t).host&&i!==document&&i.host.nodeType?i.host:i.parentNode))}var i;return null}var g,m=/\s+/g;function I(t,e,n){var o;t&&e&&(t.classList?t.classList[n?"add":"remove"](e):(o=(" "+t.className+" ").replace(m," ").replace(" "+e+" "," "),t.className=(o+(n?" "+e:"")).replace(m," ")))}function P(t,e,n){var o=t&&t.style;if(o){if(void 0===n)return document.defaultView&&document.defaultView.getComputedStyle?n=document.defaultView.getComputedStyle(t,""):t.currentStyle&&(n=t.currentStyle),void 0===e?n:n[e];o[e=!(e in o||-1!==e.indexOf("webkit"))?"-webkit-"+e:e]=n+("string"==typeof n?"":"px")}}function v(t,e){var n="";if("string"==typeof t)n=t;else do{var o=P(t,"transform")}while(o&&"none"!==o&&(n=o+" "+n),!e&&(t=t.parentNode));var i=window.DOMMatrix||window.WebKitCSSMatrix||window.CSSMatrix||window.MSCSSMatrix;return i&&new i(n)}function b(t,e,n){if(t){var o=t.getElementsByTagName(e),i=0,r=o.length;if(n)for(;i=n.left-e&&i<=n.right+e,e=r>=n.top-e&&r<=n.bottom+e;return o&&e?a=t:void 0}}),a);if(e){var n,o={};for(n in t)t.hasOwnProperty(n)&&(o[n]=t[n]);o.target=o.rootEl=e,o.preventDefault=void 0,o.stopPropagation=void 0,e[j]._onDragOver(o)}}var i,r,a}function Yt(t){q&&q.parentNode[j]._isOutsideThisEl(t.target)}function Bt(t,e){if(!t||!t.nodeType||1!==t.nodeType)throw"Sortable: `el` must be an HTMLElement, not ".concat({}.toString.call(t));this.el=t,this.options=e=a({},e),t[j]=this;var n,o,i={group:null,sort:!0,disabled:!1,store:null,handle:null,draggable:/^[uo]l$/i.test(t.nodeName)?">li":">*",swapThreshold:1,invertSwap:!1,invertedSwapThreshold:null,removeCloneOnHide:!0,direction:function(){return It(t,this.options)},ghostClass:"sortable-ghost",chosenClass:"sortable-chosen",dragClass:"sortable-drag",ignore:"a, img",filter:null,preventOnFilter:!0,animation:0,easing:null,setData:function(t,e){t.setData("Text",e.textContent)},dropBubble:!1,dragoverBubble:!1,dataIdAttr:"data-id",delay:0,delayOnTouchOnly:!1,touchStartThreshold:(Number.parseInt?Number:window).parseInt(window.devicePixelRatio,10)||1,forceFallback:!1,fallbackClass:"sortable-fallback",fallbackOnBody:!1,fallbackTolerance:0,fallbackOffset:{x:0,y:0},supportPointer:!1!==Bt.supportPointer&&"PointerEvent"in window&&!u,emptyInsertThreshold:5};for(n in K.initializePlugins(this,t,i),i)n in e||(e[n]=i[n]);for(o in Pt(e),this)"_"===o.charAt(0)&&"function"==typeof this[o]&&(this[o]=this[o].bind(this));this.nativeDraggable=!e.forceFallback&&Mt,this.nativeDraggable&&(this.options.touchStartThreshold=1),e.supportPointer?h(t,"pointerdown",this._onTapStart):(h(t,"mousedown",this._onTapStart),h(t,"touchstart",this._onTapStart)),this.nativeDraggable&&(h(t,"dragover",this),h(t,"dragenter",this)),Et.push(this.el),e.store&&e.store.get&&this.sort(e.store.get(this)||[]),a(this,x())}function Ft(t,e,n,o,i,r,a,l){var s,c,u=t[j],d=u.options.onMove;return!window.CustomEvent||y||w?(s=document.createEvent("Event")).initEvent("move",!0,!0):s=new CustomEvent("move",{bubbles:!0,cancelable:!0}),s.to=e,s.from=t,s.dragged=n,s.draggedRect=o,s.related=i||e,s.relatedRect=r||k(e),s.willInsertAfter=l,s.originalEvent=a,t.dispatchEvent(s),c=d?d.call(u,s,a):c}function jt(t){t.draggable=!1}function Ht(){Ct=!1}function Lt(t){return setTimeout(t,0)}function Kt(t){return clearTimeout(t)}Bt.prototype={constructor:Bt,_isOutsideThisEl:function(t){this.el.contains(t)||t===this.el||(gt=null)},_getDirection:function(t,e){return"function"==typeof this.options.direction?this.options.direction.call(this,t,e,q):this.options.direction},_onTapStart:function(e){if(e.cancelable){var n=this,o=this.el,t=this.options,i=t.preventOnFilter,r=e.type,a=e.touches&&e.touches[0]||e.pointerType&&"touch"===e.pointerType&&e,l=(a||e).target,s=e.target.shadowRoot&&(e.path&&e.path[0]||e.composedPath&&e.composedPath()[0])||l,c=t.filter;if(!function(t){Tt.length=0;var e=t.getElementsByTagName("input"),n=e.length;for(;n--;){var o=e[n];o.checked&&Tt.push(o)}}(o),!q&&!(/mousedown|pointerdown/.test(r)&&0!==e.button||t.disabled)&&!s.isContentEditable&&(this.nativeDraggable||!u||!l||"SELECT"!==l.tagName.toUpperCase())&&!((l=N(l,t.draggable,o,!1))&&l.animated||J===l)){if(nt=B(l),it=B(l,t.draggable),"function"==typeof c){if(c.call(this,e,l,this))return U({sortable:n,rootEl:s,name:"filter",targetEl:l,toEl:o,fromEl:o}),z("filter",n,{evt:e}),void(i&&e.cancelable&&e.preventDefault())}else if(c=c&&c.split(",").some(function(t){if(t=N(s,t.trim(),o,!1))return U({sortable:n,rootEl:t,name:"filter",targetEl:l,fromEl:o,toEl:o}),z("filter",n,{evt:e}),!0}))return void(i&&e.cancelable&&e.preventDefault());t.handle&&!N(s,t.handle,o,!1)||this._prepareDragStart(e,a,l)}}},_prepareDragStart:function(t,e,n){var o,i=this,r=i.el,a=i.options,l=r.ownerDocument;n&&!q&&n.parentNode===r&&(o=k(n),$=r,V=(q=n).parentNode,Q=q.nextSibling,J=n,at=a.group,st={target:Bt.dragged=q,clientX:(e||t).clientX,clientY:(e||t).clientY},ht=st.clientX-o.left,ft=st.clientY-o.top,this._lastX=(e||t).clientX,this._lastY=(e||t).clientY,q.style["will-change"]="all",o=function(){z("delayEnded",i,{evt:t}),Bt.eventCanceled?i._onDrop():(i._disableDelayedDragEvents(),!s&&i.nativeDraggable&&(q.draggable=!0),i._triggerDragStart(t,e),U({sortable:i,name:"choose",originalEvent:t}),I(q,a.chosenClass,!0))},a.ignore.split(",").forEach(function(t){b(q,t.trim(),jt)}),h(l,"dragover",Xt),h(l,"mousemove",Xt),h(l,"touchmove",Xt),h(l,"mouseup",i._onDrop),h(l,"touchend",i._onDrop),h(l,"touchcancel",i._onDrop),s&&this.nativeDraggable&&(this.options.touchStartThreshold=4,q.draggable=!0),z("delayStart",this,{evt:t}),!a.delay||a.delayOnTouchOnly&&!e||this.nativeDraggable&&(w||y)?o():Bt.eventCanceled?this._onDrop():(h(l,"mouseup",i._disableDelayedDrag),h(l,"touchend",i._disableDelayedDrag),h(l,"touchcancel",i._disableDelayedDrag),h(l,"mousemove",i._delayedDragTouchMoveHandler),h(l,"touchmove",i._delayedDragTouchMoveHandler),a.supportPointer&&h(l,"pointermove",i._delayedDragTouchMoveHandler),i._dragStartTimer=setTimeout(o,a.delay)))},_delayedDragTouchMoveHandler:function(t){t=t.touches?t.touches[0]:t;Math.max(Math.abs(t.clientX-this._lastX),Math.abs(t.clientY-this._lastY))>=Math.floor(this.options.touchStartThreshold/(this.nativeDraggable&&window.devicePixelRatio||1))&&this._disableDelayedDrag()},_disableDelayedDrag:function(){q&&jt(q),clearTimeout(this._dragStartTimer),this._disableDelayedDragEvents()},_disableDelayedDragEvents:function(){var t=this.el.ownerDocument;f(t,"mouseup",this._disableDelayedDrag),f(t,"touchend",this._disableDelayedDrag),f(t,"touchcancel",this._disableDelayedDrag),f(t,"mousemove",this._delayedDragTouchMoveHandler),f(t,"touchmove",this._delayedDragTouchMoveHandler),f(t,"pointermove",this._delayedDragTouchMoveHandler)},_triggerDragStart:function(t,e){e=e||"touch"==t.pointerType&&t,!this.nativeDraggable||e?this.options.supportPointer?h(document,"pointermove",this._onTouchMove):h(document,e?"touchmove":"mousemove",this._onTouchMove):(h(q,"dragend",this),h($,"dragstart",this._onDragStart));try{document.selection?Lt(function(){document.selection.empty()}):window.getSelection().removeAllRanges()}catch(t){}},_dragStarted:function(t,e){var n;yt=!1,$&&q?(z("dragStarted",this,{evt:e}),this.nativeDraggable&&h(document,"dragover",Yt),n=this.options,t||I(q,n.dragClass,!1),I(q,n.ghostClass,!0),Bt.active=this,t&&this._appendGhost(),U({sortable:this,name:"start",originalEvent:e})):this._nulling()},_emulateDragOver:function(){if(ct){this._lastX=ct.clientX,this._lastY=ct.clientY,kt();for(var t=document.elementFromPoint(ct.clientX,ct.clientY),e=t;t&&t.shadowRoot&&(t=t.shadowRoot.elementFromPoint(ct.clientX,ct.clientY))!==e;)e=t;if(q.parentNode[j]._isOutsideThisEl(t),e)do{if(e[j])if(e[j]._onDragOver({clientX:ct.clientX,clientY:ct.clientY,target:t,rootEl:e})&&!this.options.dragoverBubble)break}while(e=(t=e).parentNode);Rt()}},_onTouchMove:function(t){if(st){var e=this.options,n=e.fallbackTolerance,o=e.fallbackOffset,i=t.touches?t.touches[0]:t,r=Z&&v(Z,!0),a=Z&&r&&r.a,l=Z&&r&&r.d,e=Ot&&bt&&E(bt),a=(i.clientX-st.clientX+o.x)/(a||1)+(e?e[0]-_t[0]:0)/(a||1),l=(i.clientY-st.clientY+o.y)/(l||1)+(e?e[1]-_t[1]:0)/(l||1);if(!Bt.active&&!yt){if(n&&Math.max(Math.abs(i.clientX-this._lastX),Math.abs(i.clientY-this._lastY))n.right+10||t.clientX<=n.right&&t.clientY>n.bottom&&t.clientX>=n.left:t.clientX>n.right&&t.clientY>n.top||t.clientX<=n.right&&t.clientY>n.bottom+10}(n,r,this)&&!g.animated){if(g===q)return O(!1);if((l=g&&a===n.target?g:l)&&(w=k(l)),!1!==Ft($,a,q,o,l,w,n,!!l))return x(),g&&g.nextSibling?a.insertBefore(q,g.nextSibling):a.appendChild(q),V=a,A(),O(!0)}else if(g&&function(t,e,n){n=k(X(n.el,0,n.options,!0));return e?t.clientX