bsn-utilities

工具箱

От 30.01.2024. Виж последната версия.

Този скрипт не може да бъде инсталиран директно. Това е библиотека за други скриптове и може да бъде използвана с мета-директива // @require https://update.greasyfork.org/scripts/486039/1319702/bsn-utilities.js

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey, Greasemonkey или Violentmonkey.

За да инсталирате този скрипт, трябва да инсталирате разширение, като например Tampermonkey .

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey или Violentmonkey.

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey или Userscripts.

За да инсталирате скрипта, трябва да инсталирате разширение като Tampermonkey.

За да инсталирате този скрипт, трябва да имате инсталиран скриптов мениджър.

(Вече имам скриптов мениджър, искам да го инсталирам!)

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

(Вече имам инсталиран мениджър на стиловете, искам да го инсталирам!)

// 随眠
function sleep(time) {
  return new Promise(resolve => setTimeout(resolve, time))
}
// 获取粘贴板文字
async function getClipboardText() {
  if (navigator.clipboard && navigator.clipboard.readText) {
    const text = await navigator.clipboard.readText();
    return text;
  }
  return "";
}
// 在HTML_ELEMENT中查找所有满足条件的元素,参数innerText可以是字符串(判断innerText是否相等)或REG
function findAllIn(ele, selectors, innerText) {
  const arr = Array.from(ele.querySelectorAll(selectors));
  return innerText === undefined
    ? arr
    : typeof innerText === "string"
      ? arr.filter(x => x.innerText.trim() === innerText.trim())
      : arr.filter(x => x.innerText.trim().match(innerText));
}
// 在HTML_ELEMENT中查找第一个满足条件的元素,参数innerText可以是字符串(判断innerText是否相等)或REG
function findIn(ele, selectors, innerText) {
  const arr = findAllIn(ele, selectors, innerText);
  return arr.length > 0 ? arr[0] : null;
}
// 在document中查找所有满足条件的元素,参数innerText可以是字符串(判断innerText是否相等)或REG
function findAll(selectors, innerText) {
  return findAllIn(document, selectors, innerText);
}
// 在document中查找第一个满足条件的元素,参数innerText可以是字符串(判断innerText是否相等)或REG
function find(selectors, innerText) {
  return findIn(document, selectors, innerText);
}
// 选择下拉选项,input为下拉选项元素,wait为等待时间,optionClass为选项的类别,matchFunc为匹配函数(满足条件后触发点击操作)
async function selectOption(input, wait, optionClass, matchFunc) {
  input.click();
  await sleep(wait);
  const optionEles = findAll(optionClass);
  const option = optionEles.find(x => matchFunc(x.innerText));
  if (option) {
    option.click();
  }
}
// 创建naive对话框,增加异步功能,只能在组件的setup函数里调用
function createNaiveDialog() {
  const dialog = naive.useDialog();
  ["create", "error", "info", "success", "warning"].forEach(x => {
    dialog[x + "Async"] = options => {
      return new Promise((resolve,reject) => {
        dialog[x]({
          ...options,
          onNegativeClick: () => resolve(false),
          onPositiveClick: () => resolve(true)
        });
      });
    }
  });
}
// 初始化Vue3,包括naive及自定义BTable组件
function initVue3(Com) {
  const style = document.createElement('style'); 
  style.type = 'text/css'; 
  style.innerHTML=`
.app-wrapper .btn-toggle {
  position: fixed;
  top: 50vh;
  right: 0;
  padding-left: 12px;
  padding-bottom: 4px;
  transform: translateX(calc(100% - 32px)) translateY(-50%);
}
.drawer-wrapper .n-form {
  margin: 0 8px;
}
.drawer-wrapper .n-form .n-form-item {
  margin: 8px 0;
}
.drawer-wrapper .n-form .n-form-item .n-space {
  flex: 1;
}
.drawer-wrapper .n-form .n-form-item .n-input-number {
  width: 100%;
}
  `; 
  document.getElementsByTagName('head').item(0).appendChild(style); 
  const el = document.createElement("div");
  el.innerHTML = `
<div id="app" class="app-wrapper">
  <n-dialog-provider>
    <n-message-provider>
      <n-button class="btn-toggle" type="primary" round @click="toggle">
        <template #icon>⇆</template>
      </n-button>
    <n-drawer v-model:show="showDrawer" resizable class="drawer-wrapper">
      <com @closeDrawer="showDrawer=false"/>
    </n-drawer>
    </n-message-provider>
  </n-dialog-provider>
</div>`;
  document.body.append(el);

const BTable = {
  template: `
<table cellspacing="0" cellpadding="0">
  <tr v-for="(row, rowIndex) in rows">
    <td v-for="cell in row" :rowspan="cell.rowspan" :colspan="cell.colspan" :width="cell.width" :class="cell.class">
      <slot :cell="cell">{{cell.value}}</slot>
    </td>
  </tr>
</table>
  `,
  props: {
    rowCount: Number,
    columns: Array, // [{ key: "", label: "", width: "100px", unit: "", editable: false }]
    cells: Array // [{ row: 0, col: 0, rowspan: 1, colspan: 1, value: "", useColumnLabel: false }]
  },
  setup(props) {
    const data = Vue.reactive({
      rows: Vue.computed(() => {
        const arr1 = [];
        for(let i = 0; i < props.rowCount; i++) {
          const arr2 = [];
          for (let j = 0; j < props.columns.length; j++) {
            const column = props.columns[j];
            const cell = props.cells.find(x => x.row === i && x.col === j);
            if (cell) {
              const colspan = cell.colspan ?? 1;
              arr2.push({
                ...cell,
                rowspan: cell.rowspan ?? 1,
                colspan: colspan,
                value: cell.useColumnLabel ? column.label : cell.value,
                width: colspan > 1 ? undefined : column.width,
                column: column
              });
            }
          }
          arr1.push(arr2);
        }
        return arr1;
      })
    });
    return data;
  }
}
  const app = Vue.createApp({});
  app.use(naive);
  app.component('b-table', BTable);
  app.component('com', Com);
  app.mount("#app");
}