蒙天致远OA-UI
// ==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(/\<br\/?\>/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()