bsn-utilities

工具箱

当前为 2024-05-02 提交的版本,查看 最新版本

此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.cn-greasyfork.org/scripts/486039/1370033/bsn-utilities.js

  1. // 随眠
  2. function sleep(time) {
  3. return new Promise(resolve => setTimeout(resolve, time))
  4. }
  5. // 修改输入框的值(模拟键盘输入)
  6. function setInputValue(input, value) {
  7. input.value = value;
  8. input.dispatchEvent(new InputEvent('input'));
  9. }
  10. // 获取粘贴板文字
  11. async function getClipboardText() {
  12. if (navigator.clipboard && navigator.clipboard.readText) {
  13. const text = await navigator.clipboard.readText();
  14. return text;
  15. }
  16. return "";
  17. }
  18. // 在HTML_ELEMENT中查找所有满足条件的元素,参数innerText可以是字符串(判断innerText是否相等)或REG
  19. function findAllIn(ele, selectors, innerText) {
  20. const arr = Array.from(ele.querySelectorAll(selectors));
  21. return innerText === undefined
  22. ? arr
  23. : typeof innerText === "string"
  24. ? arr.filter(x => x.innerText.trim() === innerText.trim())
  25. : arr.filter(x => x.innerText.trim().match(innerText));
  26. }
  27. // 在HTML_ELEMENT中查找第一个满足条件的元素,参数innerText可以是字符串(判断innerText是否相等)或REG
  28. function findIn(ele, selectors, innerText) {
  29. const arr = findAllIn(ele, selectors, innerText);
  30. return arr.length > 0 ? arr[0] : null;
  31. }
  32. // 在HTML_ELEMENT中查找最后一个满足条件的元素,参数innerText可以是字符串(判断innerText是否相等)或REG
  33. function findLastIn(ele, selectors, innerText) {
  34. const arr = findAllIn(ele, selectors, innerText);
  35. return arr.length > 0 ? arr[arr.length - 1] : null;
  36. }
  37. // 在document中查找所有满足条件的元素,参数innerText可以是字符串(判断innerText是否相等)或REG
  38. function findAll(selectors, innerText) {
  39. return findAllIn(document, selectors, innerText);
  40. }
  41. // 在document中查找第一个满足条件的元素,参数innerText可以是字符串(判断innerText是否相等)或REG
  42. function find(selectors, innerText) {
  43. return findIn(document, selectors, innerText);
  44. }
  45. // 在document中查找最后一个满足条件的元素,参数innerText可以是字符串(判断innerText是否相等)或REG
  46. function findLast(selectors, innerText) {
  47. return findLastIn(document, selectors, innerText);
  48. }
  49. // 选择下拉选项,input为下拉选项元素,wait为等待时间,optionParentSelectors为选项父元素的选择器,optionSelectors为选项的选择器,matchFunc为匹配函数(满足条件后触发点击操作)
  50. async function selectOptionIn(input, wait, optionParentSelectors, optionSelectors, matchFunc) {
  51. input.click();
  52. await sleep(wait);
  53. const optionParent = optionParentSelectors ? Array.from(findAll(optionParentSelectors)).find(x => x.style.display !== 'none') : document;
  54. const optionEles = findAllIn(optionParent, optionSelectors);
  55. const option = optionEles.find((x, i) => matchFunc(x.innerText, i));
  56. if (option) {
  57. option.click();
  58. }
  59. }
  60. // 选择下拉选项,input为下拉选项元素,wait为等待时间,optionSelectors为选项的选择器,matchFunc为匹配函数(满足条件后触发点击操作)
  61. async function selectOption(input, wait, optionSelectors, matchFunc) {
  62. await selectOptionIn(input, wait, null, optionSelectors, matchFunc);
  63. }
  64. // 创建naive对话框,增加异步功能,只能在组件的setup函数里调用
  65. function createNaiveDialog() {
  66. const dialog = naive.useDialog();
  67. ["create", "error", "info", "success", "warning"].forEach(x => {
  68. dialog[x + "Async"] = options => {
  69. return new Promise((resolve,reject) => {
  70. dialog[x]({
  71. ...options,
  72. onNegativeClick: () => resolve(false),
  73. onPositiveClick: () => resolve(true)
  74. });
  75. });
  76. }
  77. });
  78. return dialog;
  79. }
  80. // 初始化Vue3,包括naive及自定义BTable组件
  81. function initVue3(Com) {
  82. const style = document.createElement('style');
  83. style.type = 'text/css';
  84. style.innerHTML=`
  85. .app-wrapper .btn-toggle {
  86. position: fixed;
  87. top: 50vh;
  88. right: 0;
  89. padding-left: 12px;
  90. padding-bottom: 4px;
  91. transform: translateX(calc(100% - 32px)) translateY(-50%);
  92. }
  93. .drawer-wrapper .n-form {
  94. margin: 0 8px;
  95. }
  96. .drawer-wrapper .n-form .n-form-item {
  97. margin: 8px 0;
  98. }
  99. .drawer-wrapper .n-form .n-form-item .n-space {
  100. flex: 1;
  101. }
  102. .drawer-wrapper .n-form .n-form-item .n-input-number {
  103. width: 100%;
  104. }
  105. `;
  106. document.getElementsByTagName('head').item(0).appendChild(style);
  107. const el = document.createElement("div");
  108. el.innerHTML = `
  109. <div id="app" class="app-wrapper"></div>`;
  110. document.body.append(el);
  111.  
  112. const BTable = {
  113. template: `
  114. <table cellspacing="0" cellpadding="0">
  115. <tr v-for="(row, rowIndex) in rows">
  116. <td v-for="cell in row" :rowspan="cell.rowspan" :colspan="cell.colspan" :width="cell.width" :class="cell.class">
  117. <slot :cell="cell">{{cell.value}}</slot>
  118. </td>
  119. </tr>
  120. </table>
  121. `,
  122. props: {
  123. rowCount: Number,
  124. columns: Array, // [{ key: "", label: "", width: "100px", unit: "", editable: false }]
  125. cells: Array // [{ row: 0, col: 0, rowspan: 1, colspan: 1, value: "", useColumnLabel: false }]
  126. },
  127. setup(props) {
  128. const data = Vue.reactive({
  129. rows: Vue.computed(() => {
  130. const arr1 = [];
  131. for(let i = 0; i < props.rowCount; i++) {
  132. const arr2 = [];
  133. for (let j = 0; j < props.columns.length; j++) {
  134. const column = props.columns[j];
  135. const cell = props.cells.find(x => x.row === i && x.col === j);
  136. if (cell) {
  137. const colspan = cell.colspan ?? 1;
  138. arr2.push({
  139. ...cell,
  140. rowspan: cell.rowspan ?? 1,
  141. colspan: colspan,
  142. value: cell.useColumnLabel ? column.label : cell.value,
  143. width: colspan > 1 ? undefined : column.width,
  144. column: column
  145. });
  146. }
  147. }
  148. arr1.push(arr2);
  149. }
  150. return arr1;
  151. })
  152. });
  153. return data;
  154. }
  155. }
  156. const app = Vue.createApp({
  157. template: `
  158. <n-dialog-provider>
  159. <n-message-provider>
  160. <n-button class="btn-toggle" type="primary" round @click="showDrawer=true">
  161. <template #icon>⇆</template>
  162. </n-button>
  163. <n-drawer v-model:show="showDrawer" display-directive="show" resizable class="drawer-wrapper">
  164. <com @closeDrawer="showDrawer=false"/>
  165. </n-drawer>
  166. </n-message-provider>
  167. </n-dialog-provider>
  168. `,
  169. setup() {
  170. const data = Vue.reactive({
  171. showDrawer: false
  172. });
  173. return data;
  174. }
  175. });
  176. app.use(naive);
  177. app.component('b-table', BTable);
  178. app.component('com', Com);
  179. app.mount("#app");
  180. }