1. 代码块-流程&建模

1.1 流程代码块

流程节点模板插入代码

场景1:请假流程,请假结束日期不能小于请假开始日期,否则给出提示信息,提示用户重新选择,并阻止流程提交

结束日期不能小于开始日期
function bindSave() {
WfForm.registerCheckEvent(WfForm.OPER_SUBMIT, function(callback) {
var jjrksrqId = WfForm.convertFieldNameToId("jjrksrq"); // 节假日开始日期ID
var jjrjsrqId = WfForm.convertFieldNameToId("jjrjsrq"); // 节假日结束日期ID
var jjrksrqv = WfForm.getFieldValue(jjrksrqId); // 开始日期
var jjrjsrqv = WfForm.getFieldValue(jjrjsrqId); // 结束日期
if (jjrjsrqv < jjrksrqv) {
alert("结束日期不能小于开始日期!");
} else {
callback(); // 继续提交需调用callback,不调用代表阻断
}
});
}

场景2:值班信息填报流程:根据选择的节假日带出的节假日开始日期和节假日结束日期,,并自动生成对应明细行,让用户填报值班信息。

根据选择的日期自动生成明细行
function bindTBJQ() {
var tbjqid = WfForm.convertFieldNameToId("tbjq"); // 填报假期ID
var jjrksrqId = WfForm.convertFieldNameToId("jjrksrq"); // 节假日开始日期ID
var jjrjsrqId = WfForm.convertFieldNameToId("jjrjsrq"); // 节假日结束日期ID
var zbrqid_1 = WfForm.convertFieldNameToId("zbrq", "detail_1"); // 值班日期ID
WfForm.bindFieldChangeEvent(jjrjsrqId, function(obj, id, value) {
var jjrksrqv = WfForm.getFieldValue(jjrksrqId); // 开始日期
var jjrjsrqv = WfForm.getFieldValue(jjrjsrqId); // 结束日期
var ksrqDate = new Date(jjrksrqv.replace(/-/g, "/"));
var ksDate = new Date(jjrksrqv.replcace(/-/g, "/")).getTime()/1000;
var jsDate = new Date(jjrjsrqv.eplcace(/-/g, "/")).getTime()/1000;
var endTime = parseInt(jsDate) - parseInt(ksDate);
var timeDay = parseInt(endTime/86400);
for(var i=0; i<=timeDay; i++) {
var dtrow = {};
if(i > 0) {
ksrqDate.setDate(ksrqDate.getDate() + 1);
}
var rq = ksrqDate.getFullYear() + "-" + (ksrqDate.getMonth() + 1) + "-" + ksrqDate.getDate();
dtrow[zbrqid_1] = {value:rq, specialobj:[{id:rq, name:rq}]};
WfForm.addDetailRow("detail_1", dtrow);
}
});
}

上面两个函数需要放在页面初始化后绑定

JQuery().ready(function(){
pageInitFun();
});

function pageInitFun() {
bindTBJQ();
bindSave();
};

1.2 建模代码块

场景1:查询列表,启用停用台账数据

启用/停用台账数据

建模引擎->应用建模->模块->页面扩展

javascrpt:aa();
function aa() {
var ids = _xtable_CheckedCheckboxId();
alert(ids + "启用成功");
// 写请求传递到后台,把启用表示更新
}

场景2:建模保存后调用第三方接口回传数据,判断是否存在重复数据(比如供应商录入,不允许相同名称重复录入),存在则提示用户存在重复数据,不允许保存。

建模引擎->应用建模->模块->页面扩展->接口动作(涉及后端,后面再讲)

或者

建模引擎->应用建模->模块->基础->新建布局->插入->E9代码块

<script type="text/javascript">
$(function() {
var appid_id = ModeForm.convertFiledNameToId("appid");
ModeForm.bindFieldChangeEvent(appid_id, function(obj, id, value) {
console.log("值改变--", obj, id, value);
})
});

windows.checkCustomize = () => {
var flag = false;
alert("重复创建不允许保存,请检查数据");
return flag;
}
</script>

2. Ecode无侵入组件复写&重写

http://ip:port/ecode

进入Ecode页面定制开发,具体如何书写可以参考示例

书写完成后鼠标右键文件夹菜单点击发布

2.1 组件复写

参考资料:https://e-cloudstore.com/doc.html

组件库:https://e-cloudstore.com/e9/index2.html

场景1:待办流程页面,隐藏部分Tab内容

const enable = true

const getLb = (id, name) => {
const {WeaLocaleProvider} = ecCom;
const getLabel = WeaLocaleProvider.getLabel;
return getLabel(id, name);
}

// 复写Tabs,或者复写WeaTab参数处理,两种方式取其一
ecodeSDK.overwritePropsFnQueueMapSet('Tabs', {
fn:(newProps) => {
if (!enable) return;
const {hash} = window.location;
if(!hash.startsWith('#/main/workflow/listDoing')) return;
console.log(newProps);
let datas = newProps.datas;
let children = newProps.children;
let newDatas = [];
let newChildren = [];
for(let i=0;i<datas.length;i++) {
// 去掉督办
if(datas[i].groupid!="flowSup") {
newDatas.push(datas[i]);
newChildren.push(children[i]);
}
}
newProps.datas=newDatas;
newProps.children=newChildren;
return newProps;
}
});

场景2:新建流程页面复写顶部按钮

const enable = true

// 复写顶部按钮,或者复写WeaTop组件的buttons参数处理,两种方式取其一
ecodeSDK.overwritePropsFnQueueMapSet('Button', {
fn:(newProps) => {
if (!enable) return;
const {hash} = window.location;
if(!hash.startsWith('#/main/workflow/req')) return;
console.log(newProps);
if(newProps.title=="提交") {
newProps.title="发送";
newProps.children.props.children="发送";
newProps.onClick=function() {
alert("发送!");
};
}
if(newProps.title==”保存") {
newProps.disabled=true;
}
return newProps;
}
});

2.2 组件重写

注:如何找到组件的源码?

前台:/pc4mobx/[模块名]/index.js
后台:/pc4backstage/[模块名]/index.js

比如

流程表单 /pc4mobx/workflowForm/index.js
流程 /pc4mobx/workflow/index.js
流程后台 /pc4backstage/workflow/index.js

场景1:新建流程页面增加新页签newTabs

index.js

const { weaTab } = ecCom;

class NewTab extends React.Component {
getDatas = () => {
const { data = [] } => this.props;
if (!datas.find((data) => data.key === 'newTab')) {
let newTab = {
key: 'newTab',
title: '',
};
$.ajax({
url: "/api/newworkflow/getParentSubcompData",
data: {},
async: false,
dataType: "json",
success: function(res) {
if(res.api_status) {
let tabs = res.data;
for(let i=0;i<tabs.length;i++) {
let row=tabs[i];
if (i==0&&row.companyname="CCTV") {
newTab.title=row.companyname;
datas.push(newTab);
}
}
} else {
message.error(res.msg || '接口调用失败!');
}
}
});
}
return datas;
}

getStore = () => {
if (window.weaWorkfolw && window.weaWorkflow.store.wfAddStore) {
return window.weaWorkflow.store.wfAddStore;
}
return {};
}

onChange = (tabKey) => {
const { onChange } = this.props;
const wfAddStore = this.getStore();
const { lastWftypes } = wfAddStore;
if (!wfAddStore['lastWftypes'] || (wfAddStore['lastWftypes'] && wfAddStore['lastWftypes'].length === 0)){
wfAddStore['lastWftypes'] = [...wfAddStore.wftypes];
wfAddStore['compWftypes'] = [...wfAddStore.wftypes];
let compWftypes=wfAddStore['compWftypes'];
$.ajax({
url: "/api/newworkflow/getNewWorkflowTabTypeIds",
data: {},
async: false,
dataType: "json",
success: function(res) {
if(res.api_status) {
let wftype = "," + res.wftype + ",";
let nowWftypes = [];
for(let i=0;i<compWftypes.length;i++) {
let compWftypesid = ',' + compWftypes[i].id + ',';
if (wftype.indexOf(compWftypesid) >= 0) {
nowWftypes.push(nowWftypes[i]);
}
}
wfAddStore['nowWftypes'] = nowWftypes;
} else {
message.error(res.msg || '接口调用失败!');
}
}
});
}
if (tabKey === 'newTab') {
wfAddStore.wftypes = wfAddStore['nowWftypes'];
} else {
$.ajax({
url: "/api/workflow/createreq/wfinfo?needall=1&menuIds=1%2C12&tabkey=newTab&__radom__=16092080808589",
data: {},
async: false,
dataType: "json",
success: function(res) {
wfAddStore.wftypes=res.datas;
}
});
}
if (typeof onChange === 'function') onChange(tabKey);
}

render() {
let {selectedKey, isfirstselect} = this.props;
if (isfirstselect == "1") {
selectedKey = "newTab";
isfirstselect = "2";
const wfAddStore = this.getStore();
const { lastWftypes } = wfAddStore;
if (!wfAddStore['lastWftypes'] || (wfAddStore['lastWftypes'] && wfAddStore['lastWftypes'].length === 0)){
wfAddStore['lastWftypes'] = [...wfAddStore.wftypes];
wfAddStore['compWftypes'] = [...wfAddStore.wftypes];
let compWftypes=wfAddStore['compWftypes'];
$.ajax({
url: "/api/newworkflow/getNewWorkflowTabTypeIds",
data: {},
async: false,
dataType: "json",
success: function(res) {
if(res.api_status) {
let wftype = "," + res.wftype + ",";
let nowWftypes = [];
for(let i=0;i<compWftypes.length;i++) {
let compWftypesid = ',' + compWftypes[i].id + ',';
if (wftype.indexOf(compWftypesid) >= 0) {
nowWftypes.push(nowWftypes[i]);
}
}
wfAddStore['nowWftypes'] = nowWftypes;
} else {
message.error(res.msg || '接口调用失败!');
}
}
});
}
wfAddStore.wftypes = wfAddStore['nowWftypes'];
wfAddStore.tabKey = "newTab";
wfAddStore.initParams.tabkey = "newTab";
wfAddStore.changeTab("newTab");
}
return {
<div>
<WeaTab _noOverWrite {...this.props} datas={this.getDatas()} onChange={this.onChange} />
</div>
}
}
}

ecodeSDK.setCom('${appId}', 'NewTab', NewTab);

init.js

const NewTab = (props) => {
const acParams = {
appId: '${appId}',
name: 'newTab',
isPage: false,
noCss: true,
props,
}
return ecodeSDK.getAsyncCom(acParams);
}

window.addEventListener('hashchange', () => {
localStorage.setItem("isfristselect", "1");
})

localStorage.setItem("isfristselect", "1");

ecodeSDK.overwriteClassFnQueueMapSet('WeaTab', {
fn:(Com, newProps) => {
console.log(newProps);
if(newProps._noOverwrite) return;
if(windows.location.hash.indexOf('/main/workflow/add') >= 0) {
let tabs = newProps.datas;
if (tabs.length >= 3 && localStorage.getItem("isfirstselect") == "1") {
if (newProps.isfirstselect && newProps.isfirstselect == "2") {
} else {
newProps.isfirstselect = "1";
newProps.selectedKey = "newTab";
localStorage.setItem("isfristselect", "2");
window.weaWorkflow.store.wfAddStore.tabkey="newTab";
window.weaWorkflow.store.wfAddStore.initParams.tabkey="newTab";
window.weaWorkflow.store.wfAddStore.changeTab("newTab");
}
}
return {
com: newTab,
props: newProps;
}
} else {
localStorage.setItem("isfristselect", "1");
}
}
})

3. Ecode前端接口拦截

场景:新建流程页面增加按钮获取第三方数据

ecodeSDK.overwriteApiDataQueueMapSet({      
fn: (url, params, datas) => {
if (url.indexOf('/api/workflow/createreq/wfinfo') >= 0) {
$.ajax({
url: "/api/newworkflow/getParentSubcompData",
data: {},
async: false,
dataType: "json",
success: function(res) {
if(res.api_status) {
let tabs = res.data;
for(let i=0;i<tabs.length;i++) {
let row=tabs[i];
if (i==0&&row.companyname="CCTV") {
datas.tabs.push({title: row.companyname, key: "newTab"});
datas.userOperationHabit.defaultSelectedTab="newTab";
let tabdata = datas.datas;
let newtabdata = [];
for(let j=0; j<tabdata.length; j++) {
if((","+row.lcljlx+",").indexOf(","+tabdata[j].id+",")>=0) {
newtabdata.push(tabdata[j]);
}
}
datas.lastdatas=tabdata;
datas.data=newtabdata;
}
}
} else {
message.error(res.msg || '接口调用失败!');
}
}
});
}
}
}

4. Ecode自定义页面

场景:值班信息页面

值班信息页面

apis文件夹下index.js

const { WeaTools } = ecCom;

// 获取高级搜素条件
const getCondition = params => {
return WeaTools.callApi('/api/skj/abxxCondition', 'GET', params);
};

// 获取报表数据
const getDatas = params => {
return WeaTools.callApi('/api/skj/zbxxReport', 'GET', params);
};

// 生成文档
const publishDoc = params => {
return WeaTools.callApi('/api/skj/publishDoc', 'POST', params);
};

// 导出
const outExcel = params => {
return WeaTools.callApi('/api/skj/zbxxOutExcel', 'GET', params);
};

const API = {
getCondition,
getDatas,
publishDoc,
outExcel
}

ecodeSDK.exp(API);

utils文件夹index.js

const { Spin } = antd;
const { WeaLocaleProvider, WeaAlertPage } = ecCom;
const getLabel = WeaLocaleProvider.getLabel;

// 页面加载中效果处理
const renderLoading = (loading) => {
<div className="wea-demo-loading">
<Spin spinning={loading} />
</div>
}

// 无权限处理
const renderNoright = () => {
<WeaAlertPage>
<div>
{getLabel(2012, "对不起,您暂时没有权限!")}
</div>
</WeaAlertPage>
}

// 暂无数据处理
const renderNoData = () => {
<WeaAlertPage>
<div>
暂无数据
</div>
</WeaAlertPage>
}

const utils = {
renderLoading,
renderNoright,
renderNoData,
}

ecodeSDK.exp(utils);

style文件夹(右键该文件夹启用前置加载)下的report.css

.zbxx {
width: 100%;
height: 100%;
}

.zbxx .wea-tab{
padding: 0 20px;
}

.zbxx-datas {
padding: 30px 20px 0 20px;
}

.zbxx td{
border: 1px; solid;
}

.zbxx th{
border: 1px solid;
}

.zbxx table {
border-collapse: collapse;
width: 100%;
}

.zbxx td {
text-align: center
}

stores文件夹下index.js

const ReportStore = ecodeSDK.imp(ReportStore);

const allStore = {
reportStore: new ReportStore();
};

ecodeSDK.exp(allStore);

stores文件夹下report.js

const { observable, action, toJS } = mobx;
const { message } = antd;
const { WeaForm } = comsMobx;

const API = ecodeSDK.imp(API);

class ReportStore {
@observable form = new WeaForm();
@observable loading = true;
@observable hasRight = true;
@observable condition = [];
@observable datas = [];
@observable colnameArr = [];
@observable excel='';

@action
doInit = () => {
this.getCondition();
this.getDatas();
}

@action
getCondition = () => {
API.getCondition().then(action(res => {
if (res.api_status) {
this.condition = res.condition;
this.form.initFormFields(res.condition);
} else {
message.error(res.msg || '接口调用失败!');
}
}))
}

@action
getDatas = (params) => {
this.loading = true;
API.getDatas().then(action(res => {
if (res.api_status) {
this.datas = res.data;
this.colnameArr=res.colname;
this.hasRight=res.hasRight;
} else {
message.error(res.msg || '接口调用失败!');
}
}))
this.loading = false;
}
}

coms文件夹下的index.js

const { inject, observer } = mobxReact;
const { toJS } = mobx;
const { Button, message } = antd;
const { WeaSwitch } = comsMobx;
const { WeaTop, WeaTab, WeaRightMeanu, WeaReport, WeaFormItem, WeaMewScroll} = ecCom;

const { renderNoright, renderLoading } = ecodeSDK.imp(utils);

@inject('reportStore')
@observer
class Report extends React.Component {
static defaultProps = {
prefixCls: "zbxx"
};

componentWillMount() {
const { reportStore: { doInit }} = this.props;
doInit();
}

componentWillReceiveProps(nextProps) {
const { reportStore } = this.props;
if (this.props.location.key !== nextProps.location,key) { // 手动刷新,切换菜单重新初始化
reportStore.doInit();
}
}
exportExcel = () => {
const { reportStore: { outExcel, form }} = this.props;
const params = form.getFormParams();
console.log("paramsexcel", params);
outExcel(params);
}
expExcel = () => {
const { reportStore: { outExcel1, form }} = this.props;
const params = form.getFormParams();
console.log("paramsexcel", params);
outExcel(params);
}
publishDoc = () => {
const { reportStore: { publishDoc, form }} = this.props;
const params = form.getFormParams();
console.log("publishDoc", params);
publishDoc(params);
}
doSearch = () => {
const { reportStore: { getDatas, form }} = this.props;
const params = form.getFormParams();
console.log("params=", params);
if(params.jjr==""){
message.info("请先选择节假日!")
} else {
getDatas(params);
}
}
getSearchsAdQuick = () => {
const { reportStore: { form, condition }} = this.props;
const { isFormInit } = form;
const arr = [];
if(isFormInit) {
const c = toJS(condition)||[];
c.length>0&&c[0].items.map(field=>{
arr.push(
<WeaFormItem
label={`${field.label}`}
labelCol={{span: `${field.labelcol}`}}
wrapperCol={{span: `${field.fieldcol}`}}
>
<WeaSwitch fieldConfig={field} form={form} />
</WeaFormItem>
);
});
}
return arr;
}
render() {
const { reportStore, prefixCls } = this.props;
const { loading, hasRight, form, datas, colnameArr } = reportStore;

if (!hasRight && !loading) {
return renderNoRight();
}

const rightMenu = [
{
key: 'BTN_EXP',
icon: <i className='icon-coms-Restore' />
content: '导出',
onClick: this.expExcel,
},
];
const rightMenu = [
{
key: 'BTN_EXP',
icon: <i className='icon-coms-Restore' />
content: '导出',
onClick: this.expExcel,
},
];
const collectParams = {
favname: '报表型列表',
favouritetype: 1,
objid: 0,
link: 'wui/index,html#/ns_demo08/index',
};
const adBtn = [
<Button type="primary" onClick={this.doSearch}>搜索</Button>
<Button type="ghost" onClick={() => form.resetForm()}>重置</Button>
<Button type="ghost" onClick={() => setShowSearchAd(false)}>取消</Button>
];
const btns = [
<Button type="primary" onClick={this.doSearch}>搜索</Button>
<Button type="primary" onClick={this.expExcel1}>导出</Button>
<Button type="primary" onClick={this.publishDoc}>发布</Button>
];

let colname=toJS(colnameArr);
let ksdata=toJS(datas);
ksdata=JSON.parse(JSON.stringify(ksdata));
return (
<div className=(prefixCls)>
<WeaRightMenu
datas={rightMenu}
collectParams={collectParams}
>
<WeaTop
title="报表型列表"
icon={<i className='icon-coms-meeting' />}
iconBgcolor='#F14A2D'
buttons={btns}
showDropIcon={true}
dropMenuDetail={rightMenu}
dropMenuProps={{ collectParams }}
>
<WeaNewScroll height={'100%'}>
<WeaTab
searchAdQuick={this.getSearchchsAdQuick()}
buttomAdQuick={[<Bytton type="primary" style={{display:"none"}} onClick={this.doSearch}>搜索</Button>]}
/>
{
loading?renderLoading() : colname && clolname.length>0 ? (
<div className={`${prefixCls}-data`}>
<table border="1">
<tr>
<th colspan="2">值班人员</th>
{
colname.map((c, index) => { return {<th>{c}</th>}, this)
}
</tr>
{
ksdata.map((ks, index) => {
let data = ks.data;
return ( <TR ksdata={ks} ></TR>)
}, this)
}
</table>
) : (<div style={{textAlign:"center"}}>元数据</div>)
}
</WeaNewScroll>
</WeaTop>
</WeaRightMenu>
</div>
)
}
}

ecodeSDK.exp(Report);

class TR extends React.component {
render() {
const {ksdata} = this.props;
let trdata = ksdata.data;
return {
trdata.map((tr, idnex) => {
let data = tr.zbdata;
return (
<TRow data={data} trindex={index} ksmc={ksdata.ksmc} csrownum={ksdata.csrownum} rownum={tr.rownum}></TRow>
)
},this)
}
}
}

class TRow extends React.component {
render() {
const {data, trindex, ksmc, csrownum, rownum} = this.props;
return {
data.map((trow, idnex) => {
if(index==0)} {
return (
<tr>
<th rowspan=(csrownum)>{ksmc}</th>
<td>
<div>姓名</div>
<div>手机号</div>
</td>
<TD zbrArr={trow}></TD>
</tr>
)
}
},this)
}
}
}

class TD extends React.component {
render() {
const {zbrArr} = this.props;
return {
zbrArr.map((zbr, idnex) => {
let zbdh="";
if (zbr.zbdh=""){

} else {
zbdh="(" + zbr.zbdh + ")";
}
return (
<td>
<div>{zbr.zbxm}</div>
<div>{zbr.zbsjh}{zbdh}</div>
</td>
)
},this)
}
}
}

根目录下的index.js

const { Provider } = mobxReact;
const Report = ecodeSDK.imp(Report);
const allStore = ecodeSDK.imp(allStore);

class Root extends React.Component {
render() {
return {
<Provider {...allStore}>
<Report {...this.props} />
</Provider>
}
}
}

ecodeSDK.setCom('${appId}', 'report', Root);

根目录下的register.js

ecodeSDK.rewriteRouteQueue.push({
fn: (params) => {
const { Com, Route, nextState } = params;
const cpParams = {
path: 'main/css/app',
appId: '${appId}',
name: 'report',
node: 'app',
Route,
nextState
}
if (ecodeSDK.checkPath(cpParams)) {
const acParams = {
appId: cpParams.appId,
name: cpParams.name,
params: params,
isPage: true,
noCss: true,
}
return ecodeSDK.getAsyncCom(acParams);
}
return null;
},
order:2,
desc:''
});

浏览器路由地址
/wui/index.html#/main/css/app/{文件夹id}_report
/spa/custom/static/index.html#/main/css/app/{文件夹id}_report

5. Action接口动作-流程&建模

6. 定时任务

7. 后端接口拦截

8. 后端API接口发布

9. WebService接口

10. 相关文档

E9组件:https://e-cloudstore.com/e9/index.html

Ecode: https://e-cloudstore.com/doc.html

流程:https://e-cloudstore.com/doc.html

建模:参考代码块右侧说明