- // ==UserScript==
- // @name EDRI OA
- // @namespace bsn
- // @version 1.1.5
- // @description OA小助手
- // @author 不死鸟
- // @require https://unpkg.com/vue@3.5.13/dist/vue.global.prod.js
- // @require data:application/javascript,unsafeWindow.Vue%3DVue%2Cthis.Vue%3DVue%3B
- // @require https://unpkg.com/naive-ui@2.40.3/dist/index.js
- // @require https://unpkg.com/lscache@1.3.2/lscache.js
- // @require https://unpkg.com/moment@2.30.1/moment.js
- // @require https://unpkg.com/moment@2.30.1/locale/zh-cn.js
- // @require https://unpkg.com/html2canvas@1.4.1/dist/html2canvas.js
- // @require https://update.greasyfork.org/scripts/520145/1500083/bsn-libs.js
- // @match https://oa.edri.cn/Portal/Main/Index*
- // @grant unsafeWindow
- // @grant GM_addStyle
- // @license GPL version 3
- // ==/UserScript==
-
- (function() {
- GM_addStyle(``);
-
- const COM = {
- template: `
- <n-form label-placement="left" label-width="auto" size="small" :show-feedback="false">
- <n-form-item>
- <n-button type="info" style="width: 100%" @click="fillContractInvoice">填写合同发票</n-button>
- </n-form-item>
- </n-form>
- `,
- props: {},
- emits: ['closeDrawer'],
- setup(props, { emit }) {
- const message = naive.useMessage();
- const dialog = window.createNaiveDialog();
- const testing = false;
- const data = Vue.reactive({
- contractInvoice: '',
- async fillContractInvoice() {
- data.contractInvoice = testing
- ? `发票开票申请资料填写
- 序号 类别 内容 备注
- 一、基本信息
- 1 合同名称\t苏州xx公司疫苗项目\t
- 2 合同编号\t2025-xx-xxx\t
- 3 发票内容\t设计费\t
- 4 发票金额\t10000\t
- 5 发票类型\t专用发票\t
- 6 预计收款日期\t2025/1/1\t
- 7 项目负责人\t李洪群\t
- 二、我公司开票资料(如果选择基本户,不用填写开户行及帐号)
- 1 是否为基本户\t是\t
- 2 开户行\t\t
- 3 账号\t\t
- 三、客户开票资料
- 1 客户开票名称\t苏州xx公司\t
- 2 税号\t123456789012345678\t
- 3 单位地址\t江苏苏州工业园区\t
- 4 电话号码\t0512-12345678\t
- 5 开户银行\t中国银行\t
- 6 银行账户\t123456789012\t
- 四、其他信息
- 1 备注\t\t
- `
- : '';
- let isOk = await dialog.successAsync({
- title: '合同发票',
- showIcon: false,
- content: () =>
- Vue.h(naive.NInputGroup, {}, () => [
- Vue.h(naive.NInput, {
- value: data.contractInvoice,
- type: 'textarea',
- placeholder: '请输入合同发票信息',
- rows: 15,
- ['onUpdate:value']: v => {
- data.contractInvoice = v;
- }
- }),
- Vue.h(
- naive.NButton,
- {
- type: 'info',
- onclick: async () => (data.contractInvoice = await window.getClipboardText())
- },
- () => '粘贴板'
- )
- ]),
- positiveText: '下一步',
- negativeText: '取消'
- });
- if (!isOk) return;
- const infos = {
- basic: {
- contractName: { titles: ['合同名称'], value: '', remark: '' },
- contractNo: { titles: ['合同编号'], value: '', remark: '' },
- invoiceContent: { titles: ['发票内容'], value: '', remark: '' },
- invoiceAmount: { titles: ['发票金额'], value: '', remark: '' },
- invoiceType: { titles: ['发票类型'], value: '', remark: '' },
- estimatedCollectionDate: { titles: ['预计收款日期'], value: '', remark: '' },
- projectLeader: { titles: ['项目负责人'], value: '', remark: '' }
- },
- company: {
- baseAccounts: { titles: ['是否为基本户'], value: '', remark: '' },
- bankOfDeposit: { titles: ['开户行'], value: '', remark: '' },
- accounts: { titles: ['账号'], value: '', remark: '' }
- },
- customer: {
- customerName: { titles: ['客户开票名称'], value: '', remark: '' },
- dutyParagraph: { titles: ['税号'], value: '', remark: '' },
- customerAddress: { titles: ['单位地址'], value: '', remark: '' },
- telephone: { titles: ['电话号码'], value: '', remark: '' },
- customerbank: { titles: ['开户银行'], value: '', remark: '' },
- bankAccounts: { titles: ['银行账户'], value: '', remark: '' }
- },
- other: {
- remarks: { titles: ['备注'], value: '', remark: '' }
- }
- };
- const patterns = [];
- Object.keys(infos).forEach(key => {
- const o = infos[key];
- Object.keys(o).forEach(key2 => {
- const o2 = o[key2];
- o2.titles.forEach(title => {
- const matches = new RegExp(`(${title}\\s{0,})\\t(.{0,})\\t(.{0,})`).exec(
- data.contractInvoice
- );
- if (matches) {
- const [_, head, content, remark] = matches;
- const v = content.trim();
- const r = remark.trim();
- o2.value = v;
- o2.remark = r;
- patterns.push(head + '\t');
- if (v) patterns.push(v);
- if (r) patterns.push('\t' + remark);
- }
- });
- });
- });
- await sleep(300);
- isOk = await dialog.successAsync({
- title: '匹配结果',
- showIcon: false,
- content: () =>
- Vue.h(naive.NScrollbar, { style: 'max-height: calc(100vh - 200px)' }, () =>
- Vue.h(naive.NHighlight, {
- text: data.contractInvoice,
- patterns: patterns,
- style: 'word-break: normal;white-space: pre-wrap'
- })
- ),
- positiveText: '下一步',
- negativeText: '取消'
- });
- if (!isOk) return;
- emit('closeDrawer');
- const iframe = window.findAll({ selectors: 'iframe' }).find(el => {
- const srcAttr = Array.from(el.attributes).find(x => x.name === 'src');
- return srcAttr && srcAttr.nodeValue.startsWith('/MvcConfig/UI/Form');
- });
- window.simulateOperate([
- {
- type: 'input',
- parent: iframe,
- selectors: '[name="ContractName"]',
- value: infos.basic.contractName.value
- },
- {
- type: 'input',
- parent: iframe,
- selectors: '[name="ContractNo"]',
- value: infos.basic.contractNo.value
- },
- {
- type: 'input',
- parent: iframe,
- selectors: '[name="InvoiceContent"]',
- value: infos.basic.invoiceContent.value
- },
- {
- type: 'input',
- parent: iframe,
- selectors: '[name="InvoiceAmount"]',
- value: infos.basic.invoiceAmount.value,
- findTarget: el => {
- const parentEl = el.parentElement;
- return parentEl.getElementsByClassName('mini-buttonedit-input')[0];
- }
- },
- {
- type: 'click',
- parent: iframe,
- selectors: '[name="InvoiceType"]',
- focusable: true,
- waiting: 500,
- findTarget: el => {
- return el.parentElement.querySelector('.mini-buttonedit-input');
- }
- },
- {
- type: 'click',
- parent: iframe,
- selectors: '.mini-popup table tr',
- focusable: true,
- waiting: 1000,
- findTarget: el => {
- return el.innerText.includes(infos.basic.invoiceType.value) &&
- el.innerText.includes('电子')
- ? el
- : undefined;
- }
- },
- {
- type: 'input',
- parent: iframe,
- selectors: '[name="EstimatedCollectionDate"]',
- value: infos.basic.estimatedCollectionDate.value,
- waiting: 500,
- findTarget: el => {
- const parentEl = el.parentElement;
- return parentEl.getElementsByClassName('mini-buttonedit-input')[0];
- }
- },
- {
- type: 'input',
- parent: iframe,
- selectors: '[name="ProjectLeaderName"]',
- value: infos.basic.projectLeader.value,
- focusable: true,
- waiting: 500
- },
- {
- type: 'click',
- parent: iframe,
- selectors: '[name="BaseAccounts"]',
- findTarget: el => {
- const parentEl = el.parentElement;
- return Array.from(parentEl.querySelectorAll('label')).find(
- x => x.innerText === infos.company.baseAccounts.value
- );
- }
- },
- {
- type: 'input',
- parent: iframe,
- selectors: '[name="BankOfDeposit"]',
- value: infos.company.bankOfDeposit.value
- },
- {
- type: 'input',
- parent: iframe,
- selectors: '[name="Accounts"]',
- value: infos.company.accounts.value
- },
- {
- type: 'input',
- parent: iframe,
- selectors: '[name="CustomerName"]',
- value: infos.customer.customerName.value
- },
- {
- type: 'input',
- parent: iframe,
- selectors: '[name="Dutyparagraph"]',
- value: infos.customer.dutyParagraph.value
- },
- {
- type: 'input',
- parent: iframe,
- selectors: '[name="CustomerAddress"]',
- value: infos.customer.customerAddress.value
- },
- {
- type: 'input',
- parent: iframe,
- selectors: '[name="Telephone"]',
- value: infos.customer.telephone.value
- },
- {
- type: 'input',
- parent: iframe,
- selectors: '[name="Customerbank"]',
- value: infos.customer.customerbank.value
- },
- {
- type: 'input',
- parent: iframe,
- selectors: '[name="BankAccounts"]',
- value: infos.customer.bankAccounts.value
- },
- {
- type: 'input',
- parent: iframe,
- selectors: '[name="Remarks"]',
- value: infos.other.remarks.value
- }
- ]);
- }
- });
- return data;
- }
- };
- window.initVue3(COM);
- })();