// ==UserScript== // @name 蒙天致远OA-UI // @namespace https://scriptcat.org/ // @description 尝试开放接口可能性 https://open.seeyon.com/book/ctp/restjie-kou/biao-dan-liu-cheng-ji-cheng.html // @version 1.1.1 // @author empyrealtear // @match *://oa.mengtiandairy.com:7070/* // @require https://scriptcat.org/lib/1167/1.0.0/%E8%84%9A%E6%9C%AC%E7%8C%ABUI%E5%BA%93.js // @require https://cdn.bootcdn.net/ajax/libs/axios/1.5.0/axios.min.js // @require https://scriptcat.org/lib/1620/1.4.0/json-bigint-parser-browser.js // @require https://scriptcat.org/lib/1492/1.0.0/seatable.js // @require https://cdn.bootcdn.net/ajax/libs/jszip/3.7.1/jszip.min.js // @require https://cdn.bootcdn.net/ajax/libs/nanobar/0.4.2/nanobar.min.js // @require https://cdn.sheetjs.com/xlsx-0.20.1/package/dist/xlsx.full.min.js // @require https://cdn.bootcdn.net/ajax/libs/FileSaver.js/2.0.5/FileSaver.min.js // @grant unsafeWindow // @grant GM_xmlhttpRequest // @grant GM_setClipboard // @grant GM_setValue // @grant GM_getValue // @grant GM_openInTab // @grant GM_info // @grant GM_registerMenuCommand // @grant GM_unregisterMenuCommand // @grant GM_cookie // @noframes // ==/UserScript== //暴露变量 方便调试 const ast = new CAT_UI(); // (window.unsafeWindow || window).CAT_UI = CAT_UI; // (window.unsafeWindow || window).React = React; // (window.unsafeWindow || window).ReactDOM = ReactDOM; // (window.unsafeWindow || window).jsxLoader = jsxLoader; // (window.unsafeWindow || window).ast = ast; // 综合面板 var seatable_base = null var config = { userIds: [ { label: '高(出纳)', value: '-8621888980617641168' }, { label: '郭(经理)', value: '4316820462592411342' }, { label: '晴(成本)', value: '-8049862802055871402' }, { label: '军(费用)', value: '-5164055170059383110' }, { label: '周(费用)', value: '4358742559322622933' }, { label: '红(离职经理)', value: '1689005231439299871' }, { label: '秀(离职费用)', value: '-7508643625564552124' }, { label: '姚(离职法人)', value: '-3960868405333900662' }, { label: '洪(离职工程)', value: '3445155532489703504' } ], types: [ { label: '已办', value: 'done', color: '#f4606c' }, { label: '待办', value: 'pending', color: '#19caad' }, { label: '已发', value: 'sent', color: '#165dff' }, { label: '督办', value: 'supervise', color: '#86909c' }, { label: '跟踪', value: 'track', color: '#ff7d00' }, ], data: { userId: ['-5164055170059383110'], type: ['pending'], pageable: true, min: true }, seatable: { server: 'http://26.25.156.106', APIToken: 'd206902a1d886db445d7d0c008004f962731de1b', asyncDatabase: false, skip: true, regex: false, edit: false, } } if (GM_getValue('config') != null) config = JSON.parse(GM_getValue('config')) const utils = { getValue: (key) => GM_getValue(key), setValue: (key, val) => GM_setValue(key, val), loadScript: (url, callback) => { var script = document.createElement("script") script.type = "text/javascript" if (typeof (callback) != "undefined") if (script.readyState) script.onreadystatechange = () => { if (script.readyState == "loaded" || script.readyState == "complete") { script.onreadystatechange = null callback() } } else script.onload = () => callback() script.src = url document.body.appendChild(script) }, fetchBlob: async (fetchUrl, method = "POST", body = null, header = null) => { const response = await window.fetch(fetchUrl, { method, body: body ? JSON.stringify(body) : null, headers: header ? header : {}, }) const blob = await response.blob() return blob }, downloadFile: (blob, fileName) => { const a = document.createElement('a') a.style.display = 'none' a.href = window.URL.createObjectURL(blob) // a.href = window.URL.createObjectURL(new Blob([blob], { type: 'application/zip' })) a.download = fileName document.body.appendChild(a) a.click() document.body.removeChild(a) }, generateZip: async (files, name = null) => { const zip = new JSZip() files.forEach((item) => zip.file(item.name, item.blob, { binary: true })) const content = await zip.generateAsync({ type: "blob" }) const currentDate = new Date().getTime() const fileName = name ? name : `zipped-${currentDate}.zip` return utils.downloadFile(content, fileName) }, asyncPool: async (arr, delegate, start = (v) => v, end = (v) => v, poolLimit = 5) => { const ret = [] const executing = new Set() let arr_res = new Array(arr.length) let completeCount = 0 var nanobarid = 'oa_nanober' var nanobar = new Nanobar({ id: nanobarid, target: document.body }) $(`#${nanobarid}`).css('background', '#BEE7E9') $(`#${nanobarid} .bar`).css('background', '#F4606C') arr = start(arr) for (let [index, item] of arr.entries()) { const p = Promise.resolve().then(async () => { try { var res = await delegate(item, arr) arr_res[index] = res } catch (err) { console.warn(err) arr_res[index] = err } return }).finally(() => { nanobar.go((++completeCount) / arr.length * 100) }) ret.push(p) executing.add(p) const clean = () => executing.delete(p) p.then(clean).catch(clean) if (executing.size >= poolLimit) { await Promise.race(executing) } } return Promise.all(ret).then(() => { $(`#${nanobarid}`).remove() // console.log(arr_res) // console.log(completeCount) return end(arr_res) }) }, clearDuplicate: (arr, key) => Array.from(new Set(arr.map(e => e[key]))).map(e => arr.find(x => x[key] == e)), unionDuplicate: (arr, key, union = (v) => v[0]) => Array.from(new Set(arr.map(e => e[key]))).map(e => { let items = arr.filter(x => x[key] == e) return union(items) }), s2ab: (s) => { let buf = new ArrayBuffer(s.length) let view = new Uint8Array(buf) for (let i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xff return buf } } const seeyouUtils = { // 获取表单数据 getformdata: (id) => { var res = null $.ajax({ url: `/seeyon/rest/form/getformdata/${id}`, method: "GET", async: false, dataType: 'json', dataFilter: (data, type) => { if (type == 'json') { return JSONbig.stringify(JSONbig.parse(data)) } return data } }).success((e) => { res = e }).error((e) => { console.log(`[seeyou] (flowId='${id}') Unable to get formdata. `) }) return res }, // 获取正文数据 data: (id) => { var res = null $.ajax({ url: `/seeyon/rest/flow/data/${id}?exportType=0&exportFormat=json`, method: "GET", async: false, dataType: 'json', dataFilter: (data, type) => { if (type == 'json') { return JSONbig.stringify(JSONbig.parse(data)) } return data } }).success((e) => { res = e }).error((e) => { console.log(`[seeyou] (flowId='${id}') Unable to get formdata. `) }) return res }, // 获取附件列表 attachments: (summaryId, attType = '0,2') => { var res = null $.ajax({ url: `/seeyon/rest/coll/attachments/${summaryId}/${attType}`, method: "GET", async: false, dataType: 'json', dataFilter: (data, type) => { if (type == 'json') { return JSONbig.stringify(JSONbig.parse(data)) } return data } }).success((e) => { res = $.map(e, (v) => { v['downloadUrl'] = `http://oa.mengtiandairy.com:7070/seeyon/fileDownload.do?method=doDownload&filename=${encodeURI(v.filename)}&v=${v.v}&fileId=${v.fileUrl}` return v }) }).error((e) => { console.log(`[seeyou] (flowId='${summaryId}') Unable to get attachments. `) }) return res }, // 获取流程状态 state: (summaryId) => { var res = { id: summaryId, state: null, value: null } const stateEnum = { 1: '待发', 3: '待处理', 4: '处理中', 6: '回退', 7: '取回', 5: '撤销', 15: '终止', 0: '结束' } $.ajax({ url: `/seeyon/rest/flow/state/${summaryId}`, method: "GET", async: false }).success((e) => { res.state = e res.value = stateEnum[e] }).error((e) => { console.log(`[seeyou] (flowId='${summaryId}') Unable to get state. `) }) return res }, // 获取流程待办人列表 dostaff: (summaryId) => { var res = null $.ajax({ url: `/seeyon/rest/flow/dostaff/${summaryId}`, method: "GET", async: false, dataType: 'json', dataFilter: (data, type) => { if (type == 'json') { return JSONbig.stringify(JSONbig.parse(data)) } return data } }).success((e) => { res = e }).error((e) => { console.log(`[seeyou] (flowId='${summaryId}') Unable to get dostaff. `) }) return res }, // 获取指定人员协同列表, 已办=done、待办=pending、已发=sent、督办=supervise、跟踪=track getaffairs: (id, type, pageNo = 1, pageSize = 20) => { var res = null $.ajax({ url: `/seeyon/rest/affairs/${type}?memberId=${id}&pageNo=${pageNo}&pageSize=${pageSize}`, method: "GET", async: false, dataType: 'json', dataFilter: (data, type) => { if (type == 'json') { return JSONbig.stringify(JSONbig.parse(data)) } return data } }).success((e) => { res = e res.data = res.data.map(v => { return { ...v, search: { id: id, type: type } } }) }).error((e) => { console.log(`[seeyou] (memberid='${id}') Unable to get ${type} list. `) }) return res }, // 搜索联系人 getaddressbook: (searchContent) => { var res = {} $.ajax({ url: `/seeyon/addressbook.do?method=listAllMembers&showType=list&searchContent=${encodeURIComponent(searchContent)}`, method: "GET", async: false, dataType: 'html', dataFilter: (data, type) => { if (type == 'html') return $(data).find('#bTablememberlist #bodyIDmemberlist input[type=hidden]') return data } }).success((e) => { e.each((i, v) => res[v.id.replace(/_Name$/, '')] = v.value) // console.log(res) }).error((e) => { console.log(`[seeyou] (searchContent='${searchContent}') Unable to find. `) }) return res }, // 获取成员信息 getMemberInfoById: (memberId) => { var res = null $.ajax({ url: `/seeyon/addressbook.do?method=getMemberInfoById`, method: "POST", data: { memberId: memberId }, async: false, dataType: 'json', dataFilter: (data, type) => { return data } }).success((e) => { res = e }).error((e) => { console.log(`[seeyou] (memberId='${memberId}') Unable to getMemberInfoById. `) }) return res }, // 显示审批进度 showDetailLogDialog: (summaryId) => { unsafeWindow.$.dialog({ url: `http://oa.mengtiandairy.com:7070/seeyon/detaillog/detaillog.do?method=showDealingLog&summaryId=${summaryId}`, width: 1040, height: 480, title: unsafeWindow.$.i18n('collaboration.sendGrid.findAllLog'), //查看明细日志 targetWindow: getCtpTop() }) }, // 获取审批意见 findsSummaryComments: (moduleId, affairId, page = 1, pageSize = 500) => { var res = null $.ajax({ url: 'http://oa.mengtiandairy.com:7070/seeyon/ajax.do?method=ajaxAction&managerName=colManager', method: 'POST', async: false, data: { managerMethod: 'findsSummaryComments', arguments: JSON.stringify([{ isHistory: 'false', moduleId: moduleId, affairId: affairId, page: page.toString(), pageSize: pageSize.toString(), queryType: '0' }]) } }).success((e) => { res = e }).error((e) => { console.log(`[seeyou] (moduleId='${memberId}', affairId='${affairId}') Unable to findsSummaryComments. `) }) return res }, // 转发协同 transmitColById: (data) => { var doForwardData = "" for (var i = 0; i < data.length; i++) { doForwardData += data[i]["objectId"] + "_" + data[i]["id"] + "," } var dialog = unsafeWindow.$.dialog({ id: "showForwardDialog", height: "400", width: "550", url: "/seeyon/collaboration/collaboration.do?method=showForward&data=" + doForwardData, title: $.i18n('common.toolbar.transmit.col.label'), targetWindow: unsafeWindow.getCtpTop(), isClear: false, transParams: { commentContent: "" }, buttons: [ { id: "okButton", text: $.i18n("common.button.ok.label"), btnType: 1, handler: function () { var rv = dialog.getReturnValue(); }, OKFN: () => dialog.close() }, { id: "cancelButton", text: $.i18n("common.button.cancel.label"), handler: () => dialog.close() } ] }) }, // 移交并删除原协同 transerAffair: (affairId, memberId) => { $.ajax(`/seeyon/collaboration/collaboration.do?method=colTansfer&affairId=${affairId}&transferMemberId=${memberId}`) }, selectMember: (callback, maxSize = 1) => { unsafeWindow.$.selectPeople({ type: 'selectPeople', panels: 'Department,Outworker,JoinOrganization,transferFunc,BusinessDepartment', selectType: 'Member', minSize: 1, maxSize: maxSize, text: unsafeWindow.$.i18n('common.default.selectPeople.value'), hiddenPostOfDepartment: true, hiddenRoleOfDepartment: true, returnMemberWithDept: false, returnValueNeedType: false, showFlowTypeRadio: false, showMe: true, targetWindow: getCtpTop(), callback: callback, canclecallback: function () { } }) }, addNodeCollaboration: (reciver, workitemId, changeType = '2', submitType = '0', backToMe = '0', flowType = '2') => { let data = JSON.stringify({ appName: 'collaboration', // 模块ID:("collaboration")(公文暂不支持) workitemId: workitemId, // 业务ID,对应ctp_affair表CASE_ID字段 _summaryItemId changeType: changeType, // 流程修改类型(1加签、2知会、3当前会签、5多级会签、6传阅) submitType: submitType, // 是否需要提交协同 (0:不需要,1:提交协同,2:暂存待办 默认1) data: { 'add_node_info': { 'userId': reciver, 'node_process_mode': 'all', 'formOperationPolicy': '0', 'backToMe': backToMe, // 加签处理后流程是否回到我(0:否,1:是) 'dealTerm': '', 'remindTime': '0', 'flowType': flowType // 加签类型(并发:2,串发:1,与下一节点并发:5) }, 'comment_deal': { 'attitude': '1', 'content': '抄送' } } }) $.ajax({ url: '/seeyon/rest/bpm/process/addNode', method: 'POST', dataType: 'json', contentType: 'application/json', data: data, async: false, success: (res) => { console.log(res) } }) } } const templateFields = { // 对外付款申请单 '5895142011406796749': { 'supplyName': 'field0044', 'applyAmount': 'field0054', 'account': ['field0066', 'field0065', 'field0047'], 'depositBank': 'field0046', 'payer': 'field0021', 'flowType': '往来', 'remarks': 'field0026' }, // 牧业事业部请付款审批单 '-1910116541235311711': { 'supplyName': 'field0046', 'applyAmount': 'field0039', 'account': 'field0048', 'depositBank': 'field0047', 'payer': 'field0041', 'flowType': '往来', 'remarks': 'field0049' }, // 差旅费报销单V2 '-2533668926056086008': { 'supplyName': 'field0040', 'applyAmount': 'field0039', 'payer': 'field0021', 'flowType': '往来', 'remarks': 'field0026' }, // 差旅费报销单 '-4446069144704102606': { 'supplyName': 'field0040', 'applyAmount': 'field0039', 'payer': 'field0021', 'flowType': '往来', 'remarks': 'field0026' }, // 油费报销单V2 '8076215884574836222': { 'supplyName': 'field0040', 'applyAmount': 'field0054', 'payer': 'field0021', 'flowType': '往来', 'remarks': 'field0070' }, // 油费报销单 '-7135341086229641970': { 'supplyName': 'field0040', 'applyAmount': 'field0054', 'payer': 'field0021', 'flowType': '往来', 'remarks': 'field0070' }, // 其他费用报销单V2 '4291802339177547763': { 'supplyName': 'field0044', 'applyAmount': 'field0039', 'account': 'field0046', 'depositBank': 'field0045', 'payer': 'field0021', 'flowType': '往来', 'remarks': 'field0026' }, // 借款申请单 '-629130699976915145': { 'supplyName': 'field0044', 'applyAmount': 'field0054', 'account': 'field0047', 'depositBank': 'field0046', 'payer': 'field0021', 'flowType': '往来', 'remarks': 'field0026' }, // 薪酬费用付款单 '4289674701592086231': { 'supplyName': ['field0048', 'field0049', 'field0050', 'field0051', 'field0052', 'field0067'], 'applyAmount': 'field0065', 'payer': '', 'flowType': '往来', 'remarks': 'field0063' }, // 费用报销单 '-2965283357942464048': { 'supplyName': 'field0044', 'applyAmount': 'field0039', 'payer': 'field0021', 'flowType': '往来', 'remarks': 'field0026' }, // 牧场-存货采购申请 '-3488430484073462403': { 'flowType': '申请', 'remarks': 'field0010' }, // 固定资产采购申请 '1141314162835736270': { 'flowType': '申请', 'remarks': 'field0009' }, // 低值易耗品采购申请单 '5716260486623544296': { 'flowType': '申请', 'remarks': 'field0009' }, // 招待费用申请表 '8176611886140900716': { 'flowType': '申请', 'remarks': 'field0006' }, // 印章使用审批单 '1767375867302135476': { 'flowType': '用章', 'remarks': 'field0005' }, // 蒙天乳业法律纠纷处理申请单 '-3115139038453937530': { 'flowType': '申请', 'remarks': 'field0049' }, // 办公设施维修申请单 '-632475279924901446': { 'flowType': '申请', 'remarks': 'field0020' }, // 用车申请表 '-8533694493240833303': { 'flowType': '申请', 'remarks': 'field0012' }, // 请假(调休)单 '8445585496425120712': { 'flowType': '申请', 'remarks': 'field0010' }, // 离职申请表 '-7021572671665651605': { 'flowType': '申请', 'remarks': 'field0009' }, // 出差申请单 '-8958950164829159336': { 'flowType': '申请', 'remarks': 'field0005' }, // 招聘需求申请表New '4640646536853408321': { 'flowType': '申请', 'remarks': 'field0021' }, // 人员转正申请单 '7170683882049914937': { 'flowType': '申请', 'remarks': 'field0014' }, // OA流程变更申请单 '-7984124277308504018': { 'flowType': '申请', 'remarks': 'field0003' }, // 薪酬审批流程 '-3617308359877440598': { 'flowType': '申请' }, // 合同审批单 '-6320528816474667249': { 'supplyName': 'field0007', 'payer': 'field0006', 'flowType': '合同', 'remarks': 'field0021' }, // 市场类合同审批单 '-1013128023555421549': { 'supplyName': 'field0007', 'payer': 'field0006', 'flowType': '合同', 'remarks': 'field0021' }, // 采购合同审批单(工厂) '8459265283253290318': { 'supplyName': 'field0007', 'payer': 'field0006', 'flowType': '合同', 'remarks': 'field0021' }, // 采购合同审批单(牧场) '5241894685812869986': { 'supplyName': 'field0007', 'payer': 'field0006', 'flowType': '合同', 'remarks': 'field0021' }, // 合同审批单 '1324051725902628863': { 'supplyName': 'field0007', 'payer': 'field0006', 'flowType': '合同', 'remarks': 'field0021' }, } const payerEnum = { // 费用承担公司id "-1585937216510934337": "蒙天乳业有限公司", "4663292034364819526": "山东蒙天乳业有限公司", "6596440339473514738": "蒙天乳业有限公司上海分公司", "-1528005668975521993": "江西蒙天乳业有限公司", "-1557708275488174959": "宁夏蒙天乳业有限公司", "6904505186630389404": "德州市维多利亚农牧有限公司", "8584309132117690151": "山东东君生态农业有限公司", "514582257443029538": "健康饮品事业部华东大区", "-1853804211592082200": "健康饮品事业部华北大区", "2761474216853258980": "健康饮品事业部华中大区", "1960492753753950438": "健康饮品事业部华南大区", "7445807672464326991": "健康饮品事业部西北大区", "-6923534789795690870": "蒙天乳业有限公司南昌分公司", "-7429051204531565381": "健康饮品事业部苏皖沪大区", "-8111400422124074379": "健康饮品事业部新品部", // 部门id "-3183965678221049613": "山东东君生态农业有限公司" } const loopUserAffairs = async (memberIds, types = ['pending']) => { const table_name = "流程" var arr = [], size = 800 var table = { update: [], append: [] } memberIds.forEach(memberId => { types.forEach(type => { let page = 1 do { var res = seeyouUtils.getaffairs(memberId, type, page, size) arr.push(...res.data) page += 1 } while (res.data.length >= size) }) }) arr = utils.unionDuplicate(arr, 'objectId', (items) => ({ ...items[0], search: utils.clearDuplicate(items.map(v => { return v.search }), 'id') })) if (config.seatable.skip) // 概要 return arr var databaseRes = [], listrows = [] var resdict = {} if ((!config.seatable.skip) && config.seatable.asyncDatabase) { // 明细 & 离线 seatable_base = new Base(config.seatable) await seatable_base.auth() do { listrows = await seatable_base.queryAsync(`select * from ${table_name} limit 5000 offset ${databaseRes.length}`) databaseRes.push(...listrows) } while (listrows != null && listrows.length > 0) $.each(databaseRes, (i, v) => resdict[v['ID']] = v) } return await utils.asyncPool(arr, async (val) => { let row = { 'ID': val['objectId'], '模板ID': val['templeteId'], '协同ID': val['id'], '表单ID': val['formRecordid'], '标题': val['subject'], '发起人': val['senderName'] } if (val['objectId'] in resdict) { let row_update_simplify = {} let rowpre = resdict[val['objectId']] Object.entries(row).forEach(([k, v], i) => { if (rowpre[k] != v) row_update_simplify[k] = v }) if (Object.keys(row_update_simplify).length > 0) table.update.push({ row_id: rowpre['_id'], row: row_update_simplify }) Object.entries({ 'payer': '付款方', 'supplyName': '收款账户', 'account': '银行账号', 'depositBank': '开户行', 'applyAmount': '申请金额', 'accountPayable': '应付金额', 'paidAmount': '已付金额', 'unpaidAmount': '未付金额', 'financeId': '核销凭证', 'seatableId': '_id' }).forEach(([k, v], i) => { val[k] = rowpre[v] }) } else { let formdata = seeyouUtils.getformdata(val['objectId']) if (Object.keys(formdata).length > 0) { let templete = templateFields[val['templeteId']] if (templete) { let data = formdata.DataMap Object.entries(templete).forEach(([k, v], i) => { if (v instanceof Array) { v.some(x => { if (data[x] == null || data[x] == '') return false else { val[k] = data[x] return true } }) } else if (v.startsWith('field')) { val[k] = data[v] } else { val[k] = v } }) } } else { val['applyAmount'] = 0 } val = { ...val, 'createDate': (new Date(val['createDate'])).format('yyyy-MM-dd HH:mm'), 'payer': payerEnum.hasOwnProperty(val['payer']) ? payerEnum[val['payer']] : /生态农业/.test(val['subject']) ? '山东东君生态农业有限公司' : '德州市维多利亚农牧有限公司', 'supplyName': /-?[0-9]+$/.test(val['supplyName']) ? seeyouUtils.getMemberInfoById(val['supplyName'])['memberName'] : val['supplyName'], 'accountPayable': val['applyAmount'], 'paidAmount': 0 } let rowappend = Object.assign({}, row, { '发起日期': val['createDate'], '付款方': val['payer'], '收款账户': val['supplyName'], '银行账号': val['account'], '开户行': val['depositBank'], '申请金额': val['applyAmount'], '应付金额': val['accountPayable'], '已付金额': val['paidAmount'], }) if (val['flowType'] != null) { rowappend['类型'] = val['flowType'] } table.append.push(rowappend) } return val }, (v) => v, (v) => { console.log(table) if (config.seatable.asyncDatabase) { // 同步 let batchsize = 200 let batchpage, batchrows if (table.update.length > 0) { batchpage = 1 do { batchrows = table.update.slice(batchsize * (batchpage - 1), batchsize * batchpage) seatable_base.batchUpdateRows(table_name, batchrows) batchpage += 1 } while (batchrows.length >= batchsize) } if (table.append.length > 0) { batchpage = 1 do { batchrows = table.append.slice(batchsize * (batchpage - 1), batchsize * batchpage) seatable_base.batchAppendRows(table_name, batchrows) batchpage += 1 } while (batchrows.length >= batchsize) } } // console.log(v) return v }) } const options = { menus: { minSwitch: { toStr: (x) => '窗口模式:' + (x ? '最小化' : '展开(原模式)'), register: () => { let ismin = utils.getValue('ismin') options.menus.minSwitch[!ismin ? '_new' : '_old'] = GM_registerMenuCommand(options.menus.minSwitch.toStr(ismin), () => { utils.setValue('ismin', !ismin) options.menus.minSwitch.register() }) GM_unregisterMenuCommand(options.menus.minSwitch[ismin ? '_new' : '_old']) }, _new: null, _old: null }, dangerSwitch: { toStr: (x) => '实验性功能:' + (x ? '开启' : '关闭(原模式)'), register: () => { let isdanger = utils.getValue('isdanger') options.menus.dangerSwitch[!isdanger ? '_new' : '_old'] = GM_registerMenuCommand(options.menus.dangerSwitch.toStr(isdanger), () => { utils.setValue('isdanger', !isdanger) options.menus.dangerSwitch.register() }) GM_unregisterMenuCommand(options.menus.dangerSwitch[isdanger ? '_new' : '_old']) }, _new: null, _old: null }, }, register: () => { options.menus.minSwitch.register() options.menus.dangerSwitch.register() } } options.register() unsafeWindow.seeyouUtils = seeyouUtils // 协同面板 function initTable() { document.styleSheets[0].addRule('[contenteditable]', 'outline: 1px; border: 1px; width: 100%;') let setTbConfig, tbConfig = { data: [], tbloading: false, userIds: { options: [...config.userIds], ids: config.data.userId, types: config.data.type, overwrite: () => { config.userIds = [...tbConfig.userIds.options] config.data.userId = tbConfig.userIds.ids config.data.type = tbConfig.userIds.types } }, userIdsSearch: { options: [], select: null }, selectedRowKeys: [], selectedAttrKeys: {} } let tbData let currentSelectedRows = [] let pagination = { sizeCanChange: true, showTotal: true, total: 0, pageSize: 15, current: 1, sizeOptions: [15, 20, 50, 100, 500, 1000, 5000, 100000], pageSizeChangeResetCurrent: true, sizeCanChange: true, showJumper: true, // hideOnSinglePage: true, itemRender: (page, type, originElement) => { if (type === 'prev') return CAT_UI.el('a', {}, '上一页') if (type === 'next') return CAT_UI.el('a', {}, '下一页') return originElement } } let tmp = { ids: [...tbConfig.userIds.ids], types: [...tbConfig.userIds.types] } let attrs = {} let states = {} let init = false let modal = null let tbloading = false const expandedRow_attachments = (val) => { let flowid = val['objectId'] let col_attrs = [ { title: '文件名', dataIndex: 'filename' }, { title: '操作', dataIndex: 'operation', align: 'center', render: (col, record, index) => [ CAT_UI.Button('下载', { size: 'mini', onClick: async () => { let blob = await utils.fetchBlob(record.downloadUrl, 'GET') utils.downloadFile(blob, record.filename) } }), CAT_UI.Button('预览', { size: 'mini', onClick: () => { let downloadUrl = `/seeyon/fileDownload.do?method=doDownload4Office&type=Pdf&isOpenFile=true&fileId=${record.fileUrl}&filename=${encodeURIComponent(record.filename)}&v=${record.v}` if (record.extension == 'pdf') unsafeWindow.preViewDialog(downloadUrl) else if (record.extension == 'jpg' || record.extension == 'png') unsafeWindow.preViewDialog(`/seeyon/fileUpload.do?method=showRTE&type=image&fileId=${record.fileUrl}&filename=${encodeURIComponent(record.filename)}&v=${record.v}`) else if (record.officeTransformEnable == 'enable') unsafeWindow.preViewDialog(`/seeyon/office/cache/${new Date(record.createdate).format('yyyyMMdd')}/${record.fileUrl}/${record.fileUrl}.html?v=${record.v}`) } }) ], }, { title: '大小', dataIndex: 'size', align: 'center', render: (col, record, index) => `${Math.round(record.size / 1024)}KB` }, { title: '上传日期', dataIndex: 'createdate', align: 'center', render: (col, record, index) => new Date(record.createdate).format('yyyy-MM-dd HH:mm'), }, ] return CAT_UI.Table({ columns: col_attrs, data: attrs[flowid], loading: !!!attrs[flowid], border: true, size: 'small', pagination: false, }) } CAT_UI.createPanel({ min: config.data.min, onMin: (min) => { }, point: { x: 0, y: 50 }, header: { title: () => { return CAT_UI.Space( [ CAT_UI.Icon.ScriptCat({ style: { width: "24px", verticalAlign: "middle" }, draggable: "false", }) ], { style: { marginLeft: "0px" } } ) }, style: { background: '#e5e5ff' }, }, render: () => { [tbConfig, setTbConfig] = CAT_UI.useState(tbConfig) let prevUserIds let modalConfig = { title: '编辑单选', visible: true, focusLock: false, style: { width: 1000 }, content: CAT_UI.Table({ data: tbConfig.userIds.options, columns: [ { title: '账号', dataIndex: 'label', width: 150, align: 'center' }, { title: '序列号', dataIndex: 'value', width: 200, align: 'center' }, { title: '组织', render: (col, record, index) => seeyouUtils.getMemberInfoById(record.value).deptName }, { title: '操作', width: 70, render: (col, record, index) => CAT_UI.Space([ CAT_UI.Button(null, { icon: CAT_UI.Icon.IconDelete(), size: 'small', onClick: () => setTbConfig({ ...tbConfig, userIds: { ...tbConfig.userIds, options: tbConfig.userIds.options.filter((v) => v.value != record.value) } }) }) ]) }, ], border: true, pagination: false, size: 'small' }), onOk: () => { GM_setValue('config', JSON.stringify(config)) CAT_UI.Message.success('已保存配置', { duration: 800 }) }, onCancel: () => { setTbConfig({ ...tbConfig, userIds: { ...tbConfig.userIds, options: [...prevUserIds] } }) CAT_UI.Message.success('取消修改', { duration: 800 }) } } CAT_UI.useEffect(() => { tbConfig.userIds.overwrite() if (modal != null) { modal.update(modalConfig) } }, [tbConfig]) // 表格加载 let loadFun = async (ids, types) => { ids = ids == null ? tbConfig.userIds.ids : ids types = types == null ? tbConfig.userIds.types : types tbloading = true tbData = await loopUserAffairs(ids, types) pagination.total = tbData.length let { current, pageSize } = pagination setTbConfig({ ...tbConfig, data: tbData.slice((current - 1) * pageSize, current * pageSize) }) tbloading = false } // 表格筛选 let filterDropdownFun = ({ filterKeys, setFilterKeys, confirm }) => { return ( CAT_UI.el('div', {}, CAT_UI.Input.Search({ value: filterKeys[0] || '', searchButton: true, onChange: (value) => setFilterKeys(value ? [value] : []), onSearch: () => confirm() })) ) } // 列配置 let col_affairs = [ { title: '标题', dataIndex: 'subject', key: 'subject', width: 350, ellipsis: true, fixed: 'left', filterIcon: CAT_UI.Icon.IconSearch(), filterDropdown: filterDropdownFun, onFilter: (value, row) => config.seatable.regex ? new RegExp(value).test(row.subject) : (row.subject ?? '').indexOf(value) >= 0, }, { title: '接收人', dataIndex: 'search', key: 'search', width: 90, align: 'center', render: (col, record, index, xlsx = false) => { if (xlsx) { return record.search.map(x => { let user = tbConfig.userIds.options.find(v => v.value == x.id) let type = config.types.find(v => v.value == x.type) return `${user.label}[${type.label}]` }).join(',') } let opts = record.search.map(x => { let user = tbConfig.userIds.options.find(v => v.value == x.id) let type = config.types.find(v => v.value == x.type) try { return React.createElement('div', { class: 'arco-tag arco-tag-checked arco-tag-size-small arco-tag-custom-color', style: { 'background-color': type.color, 'border-color': type.color, 'border-radius': '10px' } }, React.createElement('span', { class: 'arco-tag-content' }, user.label)) } catch (e) { return user.label } }) return opts } }, { title: '发起人', dataIndex: 'senderName', key: 'senderName', width: 100, align: 'center', ellipsis: true, fixed: 'left', filterIcon: CAT_UI.Icon.IconSearch(), filterDropdown: filterDropdownFun, onFilter: (value, row) => config.seatable.regex ? new RegExp(value).test(row.senderName) : (row.senderName ?? '').indexOf(value) >= 0, }, { title: '发起日期', dataIndex: 'createDate', key: 'createDate', width: 140, align: 'center', ellipsis: true, fixed: 'left', render: (col, record, index) => new Date(record.createDate).format('yy-MM-dd HH:mm'), }, { title: '操作', dataIndex: 'operation', align: 'center', width: 30 * (4 + (config.seatable.asyncDatabase ? 1 : 0)), render: (col, record, index, xlsx = false) => { if (xlsx) { return `http://oa.mengtiandairy.com:7070/seeyon/collaboration/collaboration.do?method=summary&openFrom=listPending&summaryId=${record.objectId}` } else { return CAT_UI.Space([ CAT_UI.Button(null, { icon: CAT_UI.Icon.IconLink(), // 打开流程 // onClick: () => window.open(`http://oa.mengtiandairy.com:7070/seeyon/collaboration/collaboration.do?method=summary&openFrom=listPending&affairId=${record.id}`), onClick: () => window.open(`http://oa.mengtiandairy.com:7070/seeyon/collaboration/collaboration.do?method=summary&openFrom=listPending&summaryId=${record.objectId}`), size: 'mini' }), CAT_UI.Button(null, { icon: CAT_UI.Icon.IconList(), // 查看审批进度 onClick: () => seeyouUtils.showDetailLogDialog(record.objectId), size: 'mini' }), CAT_UI.Button(null, { icon: CAT_UI.Icon.IconBranch(), // 查看审批意见 onClick: () => { let comments = seeyouUtils.findsSummaryComments(record.objectId, record.id) let formrecord = seeyouUtils.getformdata(record.objectId) let formdata = { ...formrecord['RowData'] } let data = { ...record } let row = {} if (Object.keys(formdata).length > 0) { let templete = templateFields[data['templeteId']] if (templete) { Object.entries(templete).forEach(([k, v], i) => { if (v instanceof Array) { v.some(x => { if (formdata[x] == null || formdata[x] == '') return false else { data[k] = formdata[x] return true } }) } else if (v.startsWith('field')) { data[k] = formdata[v] } else { data[k] = v } }) } data = { ...data, 'createDate': (new Date(data['createDate'])).format('yyyy-MM-dd HH:mm'), 'payer': payerEnum.hasOwnProperty(data['payer']) ? payerEnum[data['payer']] : /生态农业/.test(data['subject']) ? '山东东君生态农业有限公司' : '德州市维多利亚农牧有限公司', 'supplyName': /-?[0-9]+$/.test(data['supplyName']) ? seeyouUtils.getMemberInfoById(data['supplyName'])['memberName'] : data['supplyName'] } row = { 'ID': data['objectId'], '模板ID': data['templeteId'], '协同ID': data['id'], '表单ID': data['formRecordid'], '标题': data['subject'], '类型': data['flowType'], '发起人': data['senderName'], '发起日期': data['createDate'], '付款方': data['payer'], '收款账户': data['supplyName'], '银行账号': data['account'], '开户行': data['depositBank'], '申请金额': data['applyAmount'], '备注': data['remarks'] } } CAT_UI.Modal.info({ title: record.subject, visible: true, focusLock: false, style: { width: 1400 }, content: CAT_UI.Space([ ...(Object.keys(formdata).length == 0 ? [] : [CAT_UI.el('div', {}, CAT_UI.el('form', { class: 'arco-form arco-form-inline arco-form-size-default' }, ...(Object.entries(row).map(([k, v], i) => { return CAT_UI.el('div', { class: 'arco-row arco-row-align-start arco-row-justify-start arco-form-item arco-form-layout-horizontal', style: { width: 430 } }, CAT_UI.el('div', { class: 'arco-form-label-item', style: { width: 80 } }, CAT_UI.el('label', {}, k)), CAT_UI.el('div', { class: 'arco-form-item-wrapper' }, CAT_UI.el('div', { class: 'arco-form-item-control-wrapper' }, CAT_UI.el('div', { class: 'arco-form-item-control' }, CAT_UI.el('div', { class: 'arco-form-item-control-children' }, CAT_UI.Input({ value: v, style: { width: 330 } }) ) ) ) ) ) })) ) )]), CAT_UI.Table({ columns: [ { title: '节点', dataIndex: 'postName', width: 150, align: 'center' }, { title: '审批人', dataIndex: 'createName', width: 150, align: 'center' }, { title: '审批状态', width: 200, align: 'center', render: (col, record, index) => [record.extAtt1I18n, record.extAtt2I18n, record.extAtt3I18n].join('') }, { title: '处理日期', dataIndex: 'createDate', width: 200, align: 'center' }, { title: '审批意见', dataIndex: 'escapedContent', render: (col, record, index) => record.escapedContent.replace(/\/g, '\n') }, ], data: comments.commentList, border: true, pagination: false, style: { width: 1300 } }) ], { direction: 'vertical' }) }) }, size: 'mini' }), CAT_UI.Button(null, { icon: CAT_UI.Icon.IconCloudDownload(), // 批量下载附件 onClick: () => { let flowid = record['objectId'] if (!(flowid in attrs)) attrs[flowid] = seeyouUtils.attachments(flowid, '0') let files = [] utils.asyncPool(attrs[flowid], async (v, arr) => { var blob = await utils.fetchBlob(v.downloadUrl, 'GET') files.push({ name: v.filname, url: v.downloadUrl, blob: blob }) return v }, (v) => v, (v) => { utils.generateZip(files, record.subject.trim().replace(/[:/]/, "_").replaceAll(" ", " ") + ".zip") return v }, 10) }, size: 'mini' }), ...(!config.seatable.asyncDatabase ? [] : [CAT_UI.Button(null, { icon: CAT_UI.Icon.IconEdit(), // 跳转到seatable onClick: () => window.open(`${config.seatable.server}/workspace/2/dtable/流程-发票台账/?tid=0000&vid=dyTI&row-id=${record.seatableId}`), size: 'mini' })]), ], { size: 0, align: 'center' }) } } }, ...(config.seatable.skip ? [] : [ { title: '付款方', dataIndex: 'payer', key: 'payer', width: 100, ellipsis: true, editable: true, filterIcon: CAT_UI.Icon.IconSearch(), filterDropdown: filterDropdownFun, onFilter: (value, row) => config.seatable.regex ? new RegExp(value).test(row.payer) : (row.payer ?? '').indexOf(value) >= 0, }, { title: '收款账户', dataIndex: 'supplyName', key: 'supplyName', width: 200, ellipsis: true, editable: true, filterIcon: CAT_UI.Icon.IconSearch(), filterDropdown: filterDropdownFun, onFilter: (value, row) => config.seatable.regex ? new RegExp(value).test(row.supplyName) : (row.supplyName ?? '').indexOf(value) >= 0, }, ...(config.seatable.asyncDatabase ? [ { title: '应付金额', dataIndex: 'accountPayable', key: 'accountPayable', width: 120, align: 'right', ellipsis: true, editable: true, filterIcon: CAT_UI.Icon.IconSearch(), filterDropdown: filterDropdownFun, onFilter: (value, row) => eval(`${row.accountPayable}${value}`), }, { title: '已付金额', dataIndex: 'paidAmount', key: 'paidAmount', width: 120, align: 'right', ellipsis: true, editable: true, filterIcon: CAT_UI.Icon.IconSearch(), filterDropdown: filterDropdownFun, onFilter: (value, row) => eval(`${row.paidAmount}${value}`), }, { title: '未付金额', dataIndex: 'unPaidAmount', key: 'unPaidAmount', width: 120, align: 'right', ellipsis: true, render: (col, record, index) => record.accountPayable - record.paidAmount, filterIcon: CAT_UI.Icon.IconSearch(), filterDropdown: filterDropdownFun, onFilter: (value, row) => eval(`${row.accountPayable - row.paidAmount}${value}`), }, { title: '核销凭证', dataIndex: 'financeId', key: 'financeId', width: 200, ellipsis: false, editable: true, filterIcon: CAT_UI.Icon.IconSearch(), filterDropdown: filterDropdownFun, onFilter: (value, row) => config.seatable.regex ? new RegExp(value).test(row.financeId) : (row.financeId ?? '').indexOf(value) >= 0, }, ] : [ { title: '申请金额', dataIndex: 'applyAmount', key: 'applyAmount', width: 120, align: 'right', ellipsis: true, editable: true, filterIcon: CAT_UI.Icon.IconSearch(), filterDropdown: filterDropdownFun, onFilter: (value, row) => eval(`${row.applyAmount}${value}`), } ]), { title: '银行账号', dataIndex: 'account', key: 'account', width: 200, ellipsis: true, editable: true, }, { title: '开户行', dataIndex: 'depositBank', key: 'depositBank', width: 200, ellipsis: true, editable: true, }, ]) // { // title: '状态', dataIndex: 'state', width: 100, align: 'center', // render: (col, record, index) => { // let flowid = record.objectId // if (!(flowid in states)) // states[flowid] = seeyouUtils.state(flowid).value // record.state = states[flowid] // return states[flowid] // } // } ] if (!init) { loadFun() init = true } let member_selectSearch = CAT_UI.Select([], { style: { width: 180 }, autoWidth: { minWidth: 180 }, placeholder: '输入搜索', showSearch: { retainInputValue: true }, options: tbConfig.userIdsSearch.options, filterOption: false, onSearch: (val, type) => { let res = val.length == 0 ? [] : Object.entries(seeyouUtils.getaddressbook(val)).map( ([k, v], i) => { return { label: v, value: k } } ) setTbConfig({ ...tbConfig, userIdsSearch: { ...tbConfig.userIdsSearch, options: res } }) }, onChange: (val, opt) => { tbConfig.userIdsSearch.select = { label: opt.children, value: val } } }) return CAT_UI.Space([ CAT_UI.Space([ CAT_UI.Select([], { addBefore: CAT_UI.Icon.IconUser(), style: { minwidth: 180 }, autoWidth: { minWidth: 180 }, triggerProps: { autoAlignPopupWidth: false }, mode: 'multiple', defaultValue: tbConfig.userIds.ids, options: tbConfig.userIds.options, placeholder: '搜索', dragToSort: true, onChange: (val) => { tmp.ids = val }, onVisibleChange: (e) => { if (!e) { setTbConfig({ ...tbConfig, userIds: { ...tbConfig.userIds, ids: [...tmp.ids] } }) loadFun(tmp.ids) } }, showSearch: true, filterOption: (inputVal, opt) => new RegExp(inputVal).test(opt.props.children), dropdownRender: (menu) => { prevUserIds = [...tbConfig.userIds.options] return CAT_UI.Space([ menu, CAT_UI.Space([ member_selectSearch, CAT_UI.Button(null, { icon: CAT_UI.Icon.IconUserAdd(), onClick: () => setTbConfig({ ...tbConfig, userIds: { ...tbConfig.userIds, options: [...tbConfig.userIds.options, tbConfig.userIdsSearch.select] } }) }), CAT_UI.Button(null, { icon: CAT_UI.Icon.IconSettings(), onClick: () => { modal = CAT_UI.Modal.confirm(modalConfig) } }) ], { size: 0 }) ], { direction: 'vertical', size: 0 }) } }), CAT_UI.Select([], { addBefore: CAT_UI.Icon.IconCommand(), style: { minwidth: 130 }, triggerProps: { autoAlignPopupWidth: false }, mode: 'multiple', defaultValue: tbConfig.userIds.types, options: config.types, dragToSort: true, onChange: (val) => { tmp.types = val }, onVisibleChange: (e) => { if (!e) { setTbConfig({ ...tbConfig, userIds: { ...tbConfig.userIds, types: [...tmp.types] } }) loadFun(null, tmp.types) } }, renderTag: (props) => { let color = config.types.find(v => v.value == props.value).color return React.createElement('div', { class: 'arco-tag arco-tag-checked arco-tag-size-default arco-tag-custom-color', style: { 'background-color': color, 'border-color': color, 'border-radius': '10px' } }, React.createElement('span', { class: 'arco-tag-content' }, props.label)) } }), // 功能区 CAT_UI.Divider(null, { type: 'vertical' }), CAT_UI.Icon.IconTool({ size: 'mini' }), CAT_UI.Button('刷新', { icon: CAT_UI.Icon.IconSync(), shape: 'round', size: 'small', onClick: (e) => loadFun() }), CAT_UI.Button('转发', { icon: CAT_UI.Icon.IconCopy(), shape: 'round', size: 'small', onClick: (e) => seeyouUtils.transmitColById(currentSelectedRows) }), CAT_UI.moudles.Popconfirm.render({ title: '移交并删除原协同', content: '确认移交并删除原协同吗?', disabled: !utils.getValue('isdanger'), children: CAT_UI.Button('移交', { icon: CAT_UI.Icon.IconScissor(), type: 'primary', status: 'danger', shape: 'round', size: 'small', disabled: !utils.getValue('isdanger') }), onOk: () => { console.log(currentSelectedRows) if (!utils.getValue('isdanger')) return console.warn(currentSelectedRows) seeyouUtils.selectMember((e) => { currentSelectedRows.forEach((v, i) => { seeyouUtils.transerAffair(v.id, e.value) }) CAT_UI.Message.success('已完成移交', { duration: 800 }) }) }, onCancel: () => { CAT_UI.Message.success('取消移交', { duration: 800 }) } }), // 配置区 CAT_UI.Divider(null, { type: 'vertical' }), CAT_UI.moudles.Tooltip.render({ content: '是否按分页展示协同列表', children: CAT_UI.moudles.Switch.render({ defaultChecked: config.data.pageable, checkedText: '分页', uncheckedText: '单页', onChange: (val) => { config.data.pageable = val if (!config.data.pageable) setTbConfig({ ...tbConfig, data: [...tbData] }) } }) }), CAT_UI.moudles.Tooltip.render({ content: '是否使用正则表达式搜索', children: CAT_UI.moudles.Switch.render({ defaultChecked: config.seatable.regex, checkedText: '正则', uncheckedText: '包含', onChange: (val) => { config.seatable.regex = val } }) }), // 数据库区 CAT_UI.Divider(null, { type: 'vertical' }), CAT_UI.Icon.IconCloud({ size: 'mini' }), CAT_UI.moudles.Tooltip.render({ content: '是否同步到seatable数据库', children: CAT_UI.moudles.Switch.render({ defaultChecked: config.seatable.asyncDatabase, checkedText: '同步', uncheckedText: '离线', onChange: (val) => { console.log(val) config.seatable.asyncDatabase = val } }) }), CAT_UI.moudles.Tooltip.render({ content: '是否遍历请求流程表单数据', children: CAT_UI.moudles.Switch.render({ defaultChecked: config.seatable.skip, checkedText: '概要', uncheckedText: '明细', onChange: (val) => { config.seatable.skip = val } }) }), CAT_UI.moudles.Tooltip.render({ content: '启用/关闭编辑模式', children: CAT_UI.moudles.Switch.render({ defaultChecked: config.seatable.edit, checkedText: '编辑', uncheckedText: '只读', onChange: (val) => { config.seatable.edit = val } }) }), CAT_UI.Divider(null, { type: 'vertical' }), CAT_UI.Button('保存配置', { icon: CAT_UI.Icon.IconSave(), shape: 'round', size: 'small', onClick: (e) => { GM_setValue('config', JSON.stringify(config)) CAT_UI.Message.success('已保存配置', { duration: 800 }) } }), CAT_UI.Button('导出表格', { icon: CAT_UI.Icon.IconSave(), shape: 'round', size: 'small', onClick: (e) => { let workbook = XLSX.utils.book_new() let data = tbData.map((v, i) => { let row = {} col_affairs.forEach(x => { if (x.render) row[x.title] = x.render(null, v, i, true) else row[x.title] = v[x.dataIndex] }) return row }) XLSX.utils.book_append_sheet(workbook, XLSX.utils.json_to_sheet(data, { header: col_affairs.map(v => v.title) }), '流程明细') let wbout = XLSX.write(workbook, { bookType: 'xlsx', type: 'binary' }); saveAs(new Blob([utils.s2ab(wbout)], { type: 'application/octet-stream' }), '流程明细.xlsx') } }) ], { size: 'medium' }), CAT_UI.Table({ columns: col_affairs, data: config.data.pageable ? tbConfig.data : tbData, loading: tbloading, border: true, borderCell: true, size: 'small', style: { width: window.screen.availWidth - 73 }, rowKey: 'objectId', rowSelection: { selectedRowKeys: tbConfig.selectedRowKeys, onChange: (selectedRowKeys, selectedRows) => { setTbConfig({ ...tbConfig, selectedRowKeys: selectedRowKeys }) currentSelectedRows = [...selectedRows] }, type: 'checkbox', checkAll: true, }, expandedRowRender: expandedRow_attachments, onExpand: (record, expanded) => { let flowid = record['objectId'] if (!(flowid in attrs)) attrs[flowid] = seeyouUtils.attachments(flowid, '0') }, pagination: config.data.pageable ? pagination : false, fixedHeader: false, scroll: { y: window.screen.availHeight - 340 }, summary: (currentData) => { let sumField if (config.seatable.asyncDatabase) { let accountPayable = Math.round(currentData.reduce((prev, next) => prev + next.accountPayable, 0) * 100) / 100 let paidAmount = Math.round(currentData.reduce((prev, next) => prev + next.paidAmount, 0) * 100) / 100 sumField = { subject: '合计', accountPayable: accountPayable, paidAmount: paidAmount, unPaidAmount: Math.round((accountPayable - paidAmount) * 100) / 100 } } else { sumField = { subject: '合计', applyAmount: Math.round(currentData.reduce((prev, next) => prev + next.applyAmount, 0) * 100) / 100, } } return CAT_UI.moudles.Table.Summary({ children: [{}, {}, ...col_affairs].map((v) => CAT_UI.moudles.Table.Summary.Cell({ children: sumField[v.dataIndex], className: 'arco-table-td', style: { 'text-align': 'right' } })) }) }, onChange: (pageConfig) => { let { current, pageSize } = pageConfig pagination.current = current pagination.pageSize = pageSize setTbConfig({ ...tbConfig, data: tbData.slice((current - 1) * pageSize, current * pageSize) }) }, components: { body: { cell: (props) => { const { children, rowData, className, column, ...rest } = props const formatField = (val) => parseFloat(eval(`${val}`.replace(/,/g, ''))) return CAT_UI.createElement('span', { class: "arco-table-cell-wrap-value", objectId: rowData.objectId, rowid: rowData.seatableId, colname: column.title, colkey: column.dataIndex, editable: column.editable, value: rowData[column.dataIndex], contenteditable: column.editable & config.seatable.edit ? 'plaintext-only' : false, onFocus: (e) => { $(e.target).parent().parent().css('border-bottom-color', '#f4606c') }, onBlur: (e) => { let ele = $(e.target) ele.parent().parent().css('border-bottom-color', '') if (/金额/.test($(e.target).attr('colname'))) $(e.target).text(formatField($(e.target).text())) let current = /金额/.test($(e.target).attr('colname')) ? eval(ele.text()) : ele.text() if (ele.attr('value') != current) { setTbConfig({ ...tbConfig, data: tbConfig.data.map(v => { if (v.objectId == ele.attr('objectId')) { v[ele.attr('colkey')] = current } return v }) }) if (config.seatable.asyncDatabase) seatable_base.updateRow('流程', ele.attr('rowid'), { [ele.attr('colname')]: current }).then(() => { CAT_UI.Message.success('保存修改', { duration: 800 }) }) else CAT_UI.Message.warning('未连接seatable服务器', { duration: 800 }) } }, onKeyDown: (e) => { if (e.code == "Enter" || e.code == "NumpadEnter") { e.preventDefault() if (/金额/.test($(e.target).attr('colname'))) $(e.target).text(formatField($(e.target).text())) } } }, children) } } }, onRow: (record, index) => { return { onClick: (e) => { // console.log(e.target) if ($(e.target).attr('editable')) $(e.target).find('span').focus() }, } } }) ], { direction: 'vertical' }) }, }) } // 流程面板 async function initFlowPanel(x, y) { let Form = CAT_UI.moudles.Form let rowpre let row, setRow let summaryId = unsafeWindow.summaryId let table_name = '流程' let init = false const seatable_base = new Base(config.seatable) await seatable_base.auth() CAT_UI.createPanel({ min: utils.getValue('ismin'), point: { x: x, y: y }, header: { title: () => { [row, setRow] = CAT_UI.useState({}) return CAT_UI.Space([ CAT_UI.Icon.ScriptCat({ style: { width: '24px', verticalAlign: 'middle' }, draggable: 'false', }), ], { style: { marginLeft: '0px' } }) }, style: { background: 'transparent' }, }, render: () => { let loadFun = async () => { let rows = await seatable_base.queryAsync(`select * from ${table_name} where ID='${summaryId}'`) if (rows.length == 0) rows.push({ 'ID': unsafeWindow.summaryId, '标题': null, '付款方': null, '收款账户': null, '核销凭证': null, '发起人': null, '申请金额': null, '应付金额': null, '已付金额': null, '未付金额': null, '银行账号': null, '开户行': null }) rowpre = { ...rows[0] } setRow(rows[0]) console.log('[OA] success load current flow data') } if (!init) { loadFun() init = true } let formatField = (val) => parseFloat(eval(`${val}`.replace(/,/g, ''))) return CAT_UI.Space([ Form.render({ style: { width: '350px' }, children: [ 'ID', '标题', '付款方', '收款账户', '核销凭证', '发起人', '申请金额', '应付金额', '已付金额', '未付金额', '银行账号', '开户行' ].map(v => { return Form.Item.render({ label: v, children: [CAT_UI.Input({ value: v == '未付金额' ? Math.round((row['应付金额'] - row['已付金额']) * 100) / 100 : row[v], name: v, onChange: (val, e) => setRow({ ...row, [e.target.name]: val }), onPressEnter: (e) => { let key = e.target.name if (/金额/.test(key)) setRow({ ...row, [key]: formatField(e.target.value) }) } })] }) }) }), CAT_UI.Space([ CAT_UI.moudles.Popconfirm.render({ title: '移交并删除原协同', content: '确认移交并删除原协同吗?', disabled: !utils.getValue('isdanger'), children: CAT_UI.Button('移交', { type: 'primary', status: 'danger', disabled: !utils.getValue('isdanger') }), onOk: () => { if (!utils.getValue('isdanger')) return seeyouUtils.selectMember((e) => { seeyouUtils.transerAffair(unsafeWindow.affairId, e.value) CAT_UI.Message.success('已完成移交', { duration: 800 }) }) }, onCancel: () => { CAT_UI.Message.success('取消移交', { duration: 800 }) } }), CAT_UI.Button('修改', { type: 'primary', onClick: () => { console.log(rowpre) let row_update_simplify = {} Object.entries(row).forEach(([k, v], i) => { if (rowpre[k] != v) row_update_simplify[k] = v }) if (Object.keys(row_update_simplify).length > 0) { seatable_base.updateRow(table_name, rowpre['_id'], row_update_simplify) CAT_UI.Message.success('修改完毕', { duration: 800 }) setTimeout(() => loadFun(), 500) rowpre = { ...row } } } }), CAT_UI.Button('取消', { type: 'secondary', onClick: () => { CAT_UI.Message.warning('取消修改', { duration: 800 }) setRow({ ...rowpre }) } }) ], { style: { display: 'flex', 'justify-content': 'flex-end' } }) ], { direction: 'vertical' }) } }) } if (/collaboration\/collaboration\.do\?method=summary/.test(location.href)) initFlowPanel($('#dealAreaThisRihgt').length > 0 ? 1150 : 1500, 200) else if (!(/seeyon\/common\/print\/(captPrintForm|print).jsp/.test(location.href))) initTable()