From 44b740de5c783d4755de556bbddda1b89858f3b0 Mon Sep 17 00:00:00 2001 From: fofolee Date: Sat, 11 Jan 2025 01:14:13 +0800 Subject: [PATCH] =?UTF-8?q?=E6=95=B0=E6=8D=AE=E5=A4=84=E7=90=86=E5=88=86?= =?UTF-8?q?=E7=B1=BB=E6=96=B0=E5=A2=9E=E6=95=B0=E7=BB=84=E5=A4=84=E7=90=86?= =?UTF-8?q?=E3=80=81=E6=97=B6=E9=97=B4=E5=A4=84=E7=90=86=E3=80=81=E5=AD=97?= =?UTF-8?q?=E7=AC=A6=E4=B8=B2=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- plugin/lib/quickcomposer/data/array.js | 238 ++++ plugin/lib/quickcomposer/data/index.js | 10 +- plugin/lib/quickcomposer/data/string.js | 189 ++- plugin/lib/quickcomposer/data/time.js | 350 +++++ src/components/composer/CommandComposer.vue | 13 +- .../composer/common/ArrayEditor.vue | 13 +- .../composer/common/CheckButton.vue | 145 ++ .../composer/common/OperationCard.vue | 20 +- .../composer/common/OptionEditor.vue | 3 +- src/components/composer/common/ParamInput.vue | 2 + .../composer/ui/SelectListEditor.vue | 3 +- src/js/composer/commands/dataCommands.js | 1202 ++++++++++++++++- src/js/composer/commands/networkCommands.js | 2 +- src/js/composer/commands/systemCommands.js | 2 +- src/js/composer/commands/uiCommands.js | 2 + src/js/composer/commands/userdataCommands.js | 2 +- src/js/composer/commands/utoolsCommand.js | 22 +- src/js/composer/composerConfig.js | 6 +- 18 files changed, 2116 insertions(+), 108 deletions(-) create mode 100644 plugin/lib/quickcomposer/data/array.js create mode 100644 plugin/lib/quickcomposer/data/time.js create mode 100644 src/components/composer/common/CheckButton.vue diff --git a/plugin/lib/quickcomposer/data/array.js b/plugin/lib/quickcomposer/data/array.js new file mode 100644 index 0000000..42a3c66 --- /dev/null +++ b/plugin/lib/quickcomposer/data/array.js @@ -0,0 +1,238 @@ +const array = { + // 安全的条件解析器 + _parseCondition: function (item, condition) { + // 支持的操作符 + const operators = { + "===": (a, b) => a === b, + "!==": (a, b) => a !== b, + ">=": (a, b) => a >= b, + "<=": (a, b) => a <= b, + ">": (a, b) => a > b, + "<": (a, b) => a < b, + "&&": (a, b) => a && b, + "||": (a, b) => a || b, + includes: (a, b) => String(a).includes(b), + startsWith: (a, b) => String(a).startsWith(b), + endsWith: (a, b) => String(a).endsWith(b), + }; + + try { + // 简单属性访问 + if (/^[a-zA-Z0-9_]+$/.test(condition)) { + return item[condition]; + } + + // 解析复杂条件 + for (const [op, func] of Object.entries(operators)) { + if (condition.includes(op)) { + const [left, right] = condition.split(op).map((s) => s.trim()); + const leftValue = left.includes(".") + ? left.split(".").reduce((obj, key) => obj[key], item) + : /^[a-zA-Z0-9_]+$/.test(left) + ? item[left] + : this._parseValue(left); + const rightValue = right.includes(".") + ? right.split(".").reduce((obj, key) => obj[key], item) + : /^[a-zA-Z0-9_]+$/.test(right) + ? item[right] + : this._parseValue(right); + return func(leftValue, rightValue); + } + } + return false; + } catch (error) { + return false; + } + }, + + // 解析值 + _parseValue: function (value) { + if (value === "true") return true; + if (value === "false") return false; + if (value === "null") return null; + if (value === "undefined") return undefined; + if (value.startsWith("'") && value.endsWith("'")) return value.slice(1, -1); + if (value.startsWith('"') && value.endsWith('"')) return value.slice(1, -1); + if (!isNaN(value)) return Number(value); + return value; + }, + + // 数组过滤 + filter: function (array, condition) { + if (!Array.isArray(array)) return []; + return array.filter((item) => this._parseCondition(item, condition)); + }, + + // 查找元素 + find: function (array, condition) { + if (!Array.isArray(array)) return null; + return array.find((item) => this._parseCondition(item, condition)); + }, + + // 数组映射 + map: function (array, transform) { + if (!Array.isArray(array)) return []; + return array.map((item) => { + if (/^[a-zA-Z0-9_.]+$/.test(transform)) { + return transform.split(".").reduce((obj, key) => obj?.[key], item); + } + return item; + }); + }, + + // 数组排序 + sort: function (array, key, order = "asc") { + if (!Array.isArray(array)) return []; + return [...array].sort((a, b) => { + const valueA = key ? a[key] : a; + const valueB = key ? b[key] : b; + + if (typeof valueA === "string" && typeof valueB === "string") { + return order === "asc" + ? valueA.localeCompare(valueB) + : valueB.localeCompare(valueA); + } + + return order === "asc" ? valueA - valueB : valueB - valueA; + }); + }, + + // 数组分组 + group: function (array, key) { + if (!Array.isArray(array) || !key) return {}; + return array.reduce((groups, item) => { + const value = key.split(".").reduce((obj, k) => obj?.[k], item); + if (value !== undefined) { + if (!groups[value]) { + groups[value] = []; + } + groups[value].push(item); + } + return groups; + }, {}); + }, + + // 数组去重 + unique: function (array, key) { + if (!Array.isArray(array)) return []; + if (!key) { + return [...new Set(array)]; + } + const seen = new Set(); + return array.filter((item) => { + const value = key.split(".").reduce((obj, k) => obj?.[k], item); + if (value === undefined || seen.has(value)) { + return false; + } + seen.add(value); + return true; + }); + }, + + // 数组聚合 + aggregate: function (array, operation, key) { + if (!Array.isArray(array)) return null; + const values = key + ? array.map((item) => key.split(".").reduce((obj, k) => obj?.[k], item)) + : array; + const validNumbers = values.filter((v) => !isNaN(v)); + + switch (operation) { + case "sum": + return validNumbers.reduce((sum, val) => sum + val, 0); + case "avg": + return validNumbers.length + ? validNumbers.reduce((sum, val) => sum + val, 0) / + validNumbers.length + : 0; + case "max": + return validNumbers.length ? Math.max(...validNumbers) : null; + case "min": + return validNumbers.length ? Math.min(...validNumbers) : null; + case "count": + return array.length; + default: + return null; + } + }, + + // 数组切片 + slice: function (array, start, end) { + if (!Array.isArray(array)) return []; + return array.slice(start, end); + }, + + // 数组扁平化 + flatten: function (array, depth = 1) { + if (!Array.isArray(array)) return []; + return array.flat(depth); + }, + + // 数组差集 + diff: function (array1, array2, key) { + if (!Array.isArray(array1) || !Array.isArray(array2)) return []; + if (!key) { + return array1.filter((item) => !array2.includes(item)); + } + const set2 = new Set( + array2.map((item) => key.split(".").reduce((obj, k) => obj?.[k], item)) + ); + return array1.filter( + (item) => !set2.has(key.split(".").reduce((obj, k) => obj?.[k], item)) + ); + }, + + // 数组交集 + intersect: function (array1, array2, key) { + if (!Array.isArray(array1) || !Array.isArray(array2)) return []; + if (!key) { + return array1.filter((item) => array2.includes(item)); + } + const set2 = new Set( + array2.map((item) => key.split(".").reduce((obj, k) => obj?.[k], item)) + ); + return array1.filter((item) => + set2.has(key.split(".").reduce((obj, k) => obj?.[k], item)) + ); + }, + + // 数组并集 + union: function (array1, array2, key) { + if (!Array.isArray(array1) || !Array.isArray(array2)) return []; + if (!key) { + return [...new Set([...array1, ...array2])]; + } + const seen = new Set(); + return [...array1, ...array2].filter((item) => { + const value = key.split(".").reduce((obj, k) => obj?.[k], item); + if (value === undefined || seen.has(value)) { + return false; + } + seen.add(value); + return true; + }); + }, + + // 数组分块 + chunk: function (array, size = 1) { + if (!Array.isArray(array) || size < 1) return []; + const chunks = []; + for (let i = 0; i < array.length; i += size) { + chunks.push(array.slice(i, i + size)); + } + return chunks; + }, + + // 数组随机排序 + shuffle: function (array) { + if (!Array.isArray(array)) return []; + const result = [...array]; + for (let i = result.length - 1; i > 0; i--) { + const j = Math.floor(Math.random() * (i + 1)); + [result[i], result[j]] = [result[j], result[i]]; + } + return result; + }, +}; + +module.exports = array; diff --git a/plugin/lib/quickcomposer/data/index.js b/plugin/lib/quickcomposer/data/index.js index 6241c92..469db08 100644 --- a/plugin/lib/quickcomposer/data/index.js +++ b/plugin/lib/quickcomposer/data/index.js @@ -1,11 +1,15 @@ const string = require("./string"); const buffer = require("./buffer"); const zlib = require("./zlib"); -const htmlParser = require("./htmlParser"); +const { htmlParser } = require("./htmlParser"); +const array = require("./array"); +const time = require("./time"); module.exports = { - ...string, - ...htmlParser, + htmlParser, + string, buffer, zlib, + array, + time, }; diff --git a/plugin/lib/quickcomposer/data/string.js b/plugin/lib/quickcomposer/data/string.js index 3992091..f9050b9 100644 --- a/plugin/lib/quickcomposer/data/string.js +++ b/plugin/lib/quickcomposer/data/string.js @@ -1,25 +1,196 @@ const string = { // 字符串反转 - reverseString: function (text) { + reverse: function (text) { return text.split("").reverse().join(""); }, + // 字符串替换 - replaceString: function (text, oldStr, newStr) { + replace: function (text, oldStr, newStr) { return text.replaceAll(oldStr, newStr); }, + // 字符串截取 substring: function (text, start, end) { return text.substring(start, end); }, - // 正则处理 - regexTransform: function (text, regex, replace) { - try { - if (replace === undefined) return text.match(regex); - return text.replace(regex, replace); - } catch (e) { - throw "正则表达式格式错误"; + + // 去除空白 + trim: function (text, mode = "both") { + switch (mode) { + case "start": + return text.trimStart(); + case "end": + return text.trimEnd(); + default: + return text.trim(); } }, + + // 大小写转换 + case: function (text, mode = "upper") { + switch (mode) { + case "upper": + return text.toUpperCase(); + case "lower": + return text.toLowerCase(); + case "capitalize": + return text + .toLowerCase() + .split(" ") + .map((word) => word.charAt(0).toUpperCase() + word.slice(1)) + .join(" "); + case "camel": + return text + .toLowerCase() + .split(/[^a-zA-Z0-9]+/) + .map((word, index) => + index === 0 ? word : word.charAt(0).toUpperCase() + word.slice(1) + ) + .join(""); + case "snake": + return text + .toLowerCase() + .replace(/[^a-zA-Z0-9]+/g, "_") + .replace(/([A-Z])/g, "_$1") + .replace(/^_/, ""); + case "kebab": + return text + .toLowerCase() + .replace(/[^a-zA-Z0-9]+/g, "-") + .replace(/([A-Z])/g, "-$1") + .replace(/^-/, ""); + case "constant": + return text + .toUpperCase() + .replace(/[^A-Z0-9]+/g, "_") + .replace(/^_/, ""); + default: + return text; + } + }, + + // 字符串填充 + pad: function (text, length, padString = " ", mode = "end") { + const totalPadding = Math.max(0, length - text.length); + switch (mode) { + case "start": + return text.padStart(length, padString); + case "end": + return text.padEnd(length, padString); + case "both": + const leftPadding = Math.floor(totalPadding / 2); + const rightPadding = totalPadding - leftPadding; + return text + .padStart(text.length + leftPadding, padString) + .padEnd(length, padString); + default: + return text; + } + }, + + // 字符串分割 + split: function (text, separator = ",") { + return text.split(separator); + }, + + // 数组合并 + join: function (array, separator = ",") { + return Array.isArray(array) ? array.join(separator) : String(array); + }, + + // 字符串重复 + repeat: function (text, count = 1) { + return text.repeat(Math.max(0, count)); + }, + + // 提取字符 + extract: function (text, mode = "number") { + const patterns = { + number: /\d+/g, + letter: /[a-zA-Z]+/g, + chinese: /[\u4e00-\u9fa5]+/g, + punctuation: /[^\w\s\u4e00-\u9fa5]+/g, + whitespace: /\s+/g, + }; + const matches = text.match(patterns[mode] || patterns.number); + return matches ? matches : []; + }, + + // 字符统计 + count: function (text, mode = "char") { + switch (mode) { + case "char": + return text.length; + case "word": + return text.trim().split(/\s+/).length; + case "line": + return text.split(/\r\n|\r|\n/).length; + case "number": + return (text.match(/\d/g) || []).length; + case "letter": + return (text.match(/[a-zA-Z]/g) || []).length; + case "chinese": + return (text.match(/[\u4e00-\u9fa5]/g) || []).length; + case "whitespace": + return (text.match(/\s/g) || []).length; + default: + return 0; + } + }, + + // 文本换行 + wrap: function (text, width = 80) { + const words = text.split(/(\s+)/); + let line = ""; + let result = ""; + + for (const word of words) { + if (line.length + word.length > width) { + result += line.trimEnd() + "\n"; + line = ""; + } + line += word; + } + + return result + line.trimEnd(); + }, + + // 文本对齐 + align: function (text, mode = "left", width = 80) { + const lines = text.split("\n"); + return lines + .map((line) => { + const spaces = width - line.length; + if (spaces <= 0) return line; + + switch (mode) { + case "right": + return " ".repeat(spaces) + line; + case "center": + const leftSpaces = Math.floor(spaces / 2); + return ( + " ".repeat(leftSpaces) + line + " ".repeat(spaces - leftSpaces) + ); + case "justify": + if (line.trim() === "") return line; + const words = line.trim().split(/\s+/); + if (words.length === 1) return line; + const totalSpaces = width - words.join("").length; + const spaceBetween = Math.floor(totalSpaces / (words.length - 1)); + const extraSpaces = totalSpaces % (words.length - 1); + return words + .map((word, i) => + i < words.length - 1 + ? word + " ".repeat(spaceBetween + (i < extraSpaces ? 1 : 0)) + : word + ) + .join(""); + default: + return line; + } + }) + .join("\n"); + }, }; module.exports = string; diff --git a/plugin/lib/quickcomposer/data/time.js b/plugin/lib/quickcomposer/data/time.js new file mode 100644 index 0000000..7db96aa --- /dev/null +++ b/plugin/lib/quickcomposer/data/time.js @@ -0,0 +1,350 @@ +const time = { + // 解析时间字符串或时间戳为 Date 对象 + _parseTime: function (time) { + if (!time || time === "now") { + return new Date(); + } + if (typeof time === "number") { + return new Date(time.toString().length === 10 ? time * 1000 : time); + } + return new Date(time); + }, + + // 格式化数字为两位数 + _pad: function (number) { + return number.toString().padStart(2, "0"); + }, + + // 格式化时间 + format: function (time, format) { + const date = this._parseTime(time); + if (!date.getTime()) return ""; + + const year = date.getFullYear(); + const month = this._pad(date.getMonth() + 1); + const day = this._pad(date.getDate()); + const hours = this._pad(date.getHours()); + const minutes = this._pad(date.getMinutes()); + const seconds = this._pad(date.getSeconds()); + + switch (format) { + case "YYYY-MM-DD": + return `${year}-${month}-${day}`; + case "YYYY-MM-DD HH:mm:ss": + return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`; + case "YYYY年MM月DD日": + return `${year}年${month}月${day}日`; + case "MM/DD/YYYY": + return `${month}/${day}/${year}`; + case "DD/MM/YYYY": + return `${day}/${month}/${year}`; + case "HH:mm:ss": + return `${hours}:${minutes}:${seconds}`; + case "YYYY-MM-DD HH:mm": + return `${year}-${month}-${day} ${hours}:${minutes}`; + case "timestamp": + return Math.floor(date.getTime() / 1000); + case "timestamp_ms": + return date.getTime(); + case "relative": + return this._getRelativeTime(date); + default: + return date.toLocaleString(); + } + }, + + // 获取相对时间描述 + _getRelativeTime: function (date) { + const now = new Date(); + const diff = now - date; + const seconds = Math.floor(diff / 1000); + const minutes = Math.floor(seconds / 60); + const hours = Math.floor(minutes / 60); + const days = Math.floor(hours / 24); + const months = Math.floor(days / 30); + const years = Math.floor(days / 365); + + if (seconds < 60) return "刚刚"; + if (minutes < 60) return `${minutes}分钟前`; + if (hours < 24) return `${hours}小时前`; + if (days < 30) return `${days}天前`; + if (months < 12) return `${months}个月前`; + return `${years}年前`; + }, + + // 解析时间 + parse: function (time, format) { + if (!time) return null; + + // 处理时间戳 + if (format === "timestamp") { + return new Date(Number(time) * 1000); + } + if (format === "timestamp_ms") { + return new Date(Number(time)); + } + + // 处理标准格式 + const now = new Date(); + const year = now.getFullYear(); + let result; + + switch (format) { + case "YYYY-MM-DD": + case "YYYY-MM-DD HH:mm:ss": + case "YYYY-MM-DD HH:mm": + result = new Date(time); + break; + case "YYYY年MM月DD日": + time = time.replace(/[年月日]/g, (match) => { + return { 年: "-", 月: "-", 日: "" }[match]; + }); + result = new Date(time); + break; + case "MM/DD/YYYY": + const [month, day, yyyy] = time.split("/"); + result = new Date(yyyy, month - 1, day); + break; + case "DD/MM/YYYY": + const [dd, mm, yy] = time.split("/"); + result = new Date(yy, mm - 1, dd); + break; + default: + result = new Date(time); + } + + return result.getTime() ? result : null; + }, + + // 时间加减 + add: function (time, value, unit) { + const date = this._parseTime(time); + if (!date.getTime()) return null; + + const unitMap = { + years: "FullYear", + months: "Month", + weeks: "Date", + days: "Date", + hours: "Hours", + minutes: "Minutes", + seconds: "Seconds", + }; + + const methodName = `set${unitMap[unit]}`; + const getValue = `get${unitMap[unit]}`; + + if (unit === "weeks") { + value *= 7; + } + + date[methodName](date[getValue]() + value); + return date; + }, + + // 时间差值 + diff: function (time1, time2, unit = "days", absolute = true) { + const date1 = this._parseTime(time1); + const date2 = this._parseTime(time2); + + if (!date1.getTime() || !date2.getTime()) return null; + + const milliseconds = date2 - date1; + let result; + + switch (unit) { + case "years": + result = date2.getFullYear() - date1.getFullYear(); + break; + case "months": + result = + (date2.getFullYear() - date1.getFullYear()) * 12 + + (date2.getMonth() - date1.getMonth()); + break; + case "weeks": + result = milliseconds / (7 * 24 * 60 * 60 * 1000); + break; + case "days": + result = milliseconds / (24 * 60 * 60 * 1000); + break; + case "hours": + result = milliseconds / (60 * 60 * 1000); + break; + case "minutes": + result = milliseconds / (60 * 1000); + break; + case "seconds": + result = milliseconds / 1000; + break; + case "milliseconds": + result = milliseconds; + break; + default: + result = milliseconds / (24 * 60 * 60 * 1000); + } + + return absolute ? Math.abs(result) : result; + }, + + // 时间边界 + startOf: function (time, unit, type = "start") { + const date = this._parseTime(time); + if (!date.getTime()) return null; + + const isEnd = type === "end"; + + switch (unit) { + case "year": + date.setMonth(isEnd ? 11 : 0, 1); + date.setHours( + isEnd ? 23 : 0, + isEnd ? 59 : 0, + isEnd ? 59 : 0, + isEnd ? 999 : 0 + ); + break; + case "month": + date.setDate(1); + if (isEnd) { + date.setMonth(date.getMonth() + 1, 0); + date.setHours(23, 59, 59, 999); + } else { + date.setHours(0, 0, 0, 0); + } + break; + case "week": + const day = date.getDay(); + const diff = date.getDate() - day + (day === 0 ? -6 : 1); + date.setDate(diff); + if (isEnd) { + date.setDate(date.getDate() + 6); + date.setHours(23, 59, 59, 999); + } else { + date.setHours(0, 0, 0, 0); + } + break; + case "day": + date.setHours( + isEnd ? 23 : 0, + isEnd ? 59 : 0, + isEnd ? 59 : 0, + isEnd ? 999 : 0 + ); + break; + case "hour": + date.setMinutes(isEnd ? 59 : 0, isEnd ? 59 : 0, isEnd ? 999 : 0); + break; + case "minute": + date.setSeconds(isEnd ? 59 : 0, isEnd ? 999 : 0); + break; + case "second": + date.setMilliseconds(isEnd ? 999 : 0); + break; + } + + return date; + }, + + // 时间验证 + isValid: function (time, format) { + if (!time) return false; + const date = this.parse(time, format); + return date && date.getTime() > 0; + }, + + // 日历信息 + calendar: function (time) { + const date = this._parseTime(time); + if (!date.getTime()) return null; + + const year = date.getFullYear(); + const month = date.getMonth() + 1; + const day = date.getDate(); + const week = date.getDay(); + const weekText = ["日", "一", "二", "三", "四", "五", "六"][week]; + + // 星座计算 + const constellation = this._getConstellation(month, day); + + return { + year, + month, + day, + week, + weekText: `星期${weekText}`, + constellation, + isWeekend: week === 0 || week === 6, + isLeapYear: (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0, + daysInMonth: new Date(year, month, 0).getDate(), + timestamp: Math.floor(date.getTime() / 1000), + timestamp_ms: date.getTime(), + }; + }, + + // 获取星座 + _getConstellation: function (month, day) { + const constellations = [ + "魔羯", + "水瓶", + "双鱼", + "白羊", + "金牛", + "双子", + "巨蟹", + "狮子", + "处女", + "天秤", + "天蝎", + "射手", + "魔羯", + ]; + const dates = [20, 19, 21, 20, 21, 22, 23, 23, 23, 24, 23, 22]; + return day < dates[month - 1] + ? constellations[month - 1] + : constellations[month]; + }, + + // 工作日计算 + workday: function (startTime, days, weekends = false, holidays = []) { + const date = this._parseTime(startTime); + if (!date.getTime()) return null; + + let currentDate = new Date(date); + let remainingDays = Math.abs(days); + const direction = days >= 0 ? 1 : -1; + const holidaySet = new Set( + holidays.map((h) => this.format(h, "YYYY-MM-DD")) + ); + + while (remainingDays > 0) { + currentDate.setDate(currentDate.getDate() + direction); + const isWeekend = + currentDate.getDay() === 0 || currentDate.getDay() === 6; + const isHoliday = holidaySet.has(this.format(currentDate, "YYYY-MM-DD")); + + if ((!isWeekend || weekends) && !isHoliday) { + remainingDays--; + } + } + + return currentDate; + }, + + // 时间范围判断 + between: function (time, startTime, endTime, inclusive = true) { + const date = this._parseTime(time); + const start = this._parseTime(startTime); + const end = this._parseTime(endTime); + + if (!date.getTime() || !start.getTime() || !end.getTime()) { + return false; + } + + if (inclusive) { + return date >= start && date <= end; + } + return date > start && date < end; + }, +}; + +module.exports = time; diff --git a/src/components/composer/CommandComposer.vue b/src/components/composer/CommandComposer.vue index 54e85d5..65bba2b 100644 --- a/src/components/composer/CommandComposer.vue +++ b/src/components/composer/CommandComposer.vue @@ -96,7 +96,18 @@ export default defineComponent({ }, saveFlow() { const flow = window.lodashM.cloneDeep(this.commandFlow); - const uselessProps = ["config", "argvs", "label", "component", "subCommands", "options", "defaultValue"]; + const uselessProps = [ + "config", + "argvs", + "label", + "component", + "subCommands", + "options", + "defaultValue", + "icon", + "width", + "placeholder", + ]; // 移除不必要属性 flow.forEach((cmd) => { for (const props of uselessProps) { diff --git a/src/components/composer/common/ArrayEditor.vue b/src/components/composer/common/ArrayEditor.vue index 7cecbd8..1af1207 100644 --- a/src/components/composer/common/ArrayEditor.vue +++ b/src/components/composer/common/ArrayEditor.vue @@ -6,15 +6,16 @@ :model-value="isCollapse" >
-
-