需求
在界面添加一个【参照合同】的按钮,点击【参照合同】按钮弹出模态框,模态框分为三部分:搜索、表头、表体,点击搜索加载后端接口返回的数据到表头,点击表头行则去后台接口加载表体数据展示在表头下方。
实现方式
在界面添加按钮
在应用构建服务/构建平台/应用构建/页面建模中找到需要开发的节点,点击节点进入页面模板,从组件/按钮控件中拖拽一个按钮至按钮栏中:
点击新添加的按钮,修改按钮名称,并得到按钮编码【button21wh】
在前端脚手架中添加点击按钮的功能
在前端脚手架中添加界面对应的js文件
打开添加按钮的界面,在控制台中找到如下提示:
根据这个提示在工程中创建对应的文件:
在创建的js中写入下面的js代码:
cb.define(process.env.__DOMAINKEY__, [], function () {
let GT239AT4_59d8c469_VM_Extend = {
doAction: function (name, viewModel) {
if (this[name])
this[name](viewModel);
},
init: function (viewModel) {
console.log('GT239AT4_59d8c469_VM - 11111111111111111');
console.log('************* - 11111111111111111 - *************************');
}
}
try {
module.exports = GT239AT4_59d8c469_VM_Extend;
} catch (error) {
}
return GT239AT4_59d8c469_VM_Extend;
});
把GT239AT4_59d8c469_VM_Extend 替换为tms_sale_87721978List_VM_Extend。这样在init方法中就可以写我们自己的代码了。
在前端脚手架上创建弹窗
引入自己用的react框架
创建弹窗首先需要引用一个react框架,比如tinper、antd,博主习惯使用tinper,此处就引入了tinper。
- 首先安装ynpm
npm install ynpm-tool -g
- 在用 ynpm 来安装组件库以及组件。
ynpm install @tinper/next-ui --save
- 由于tinper依赖了corejs,因此还需要引入corejs。
查看是否安装core-jsnpm ls core-js
BIP202111版需要使用core-js@^2,不能使用core-js@^3
安装core-js:
引入tinper还需要创建src\declaration.d.ts文件,并写入:ynpm i --save core-js@2.6.10
declare module '@tinper/next-ui';
编写弹窗模态框组件
这个组件需要写到src\client\web\components\modal\下:
src\client\web\components\modal\RefSalesCont\index.js
/**
* @title 销售合同参照
* @description 在BIP的销售订单上点击销售合同,通过接口读取NC销售合同的数据,以模态框的形式展示在销售订单上,销售合同展示为主子表,点击搜索将符合条件的销售合同表头信息查询出来,点击表头自动查询出表体。
*
*/
import React, { Component } from 'react';
import { Button, Checkbox, Table, Modal, Pagination, Input, Form, DatePicker, Message, Select, Rate, Radio } from '@tinper/next-ui';
// import '@tinper/next-ui/dist/tinper-next.css';
import { HeadColumns, BodyColumns } from './constant'
import './index.less'
const moment = require('moment');
const { multiSelect } = Table;
const { YearPicker, MonthPicker, WeekPicker, RangePicker } = DatePicker;
const { Option } = Select;
let MultiSelectTable = multiSelect(Table, Checkbox);
class RefSalesCont extends Component {
constructor(props) {
super(props);
this.state = {
showModal: true,
headData: [],
bodyData: [],
current: 1,
pageSize: 10,
total: 0
};
this.form = React.createRef();
}
close = () => {
this.setState({
showModal: false
});
};
open = () => {
this.setState({
showModal: true
});
};
getHeadSelectedData = data => {
console.log('getHeadSelectedData', data);
};
getBodySelectedData = data => {
console.log('getBodySelectedData', data);
};
/**
* 表头行点击事件
*/
headRowClick = (record, index, event) => {
console.log('headRowClick', record, index, event)
let _this = this;
// 查询当前表头对应的表体信息
let proxy = cb.rest.DynamicProxy.create({
ensure: {
url: `/saleContract/searchDetail/${ record.pk_ct_sale }`,
method: 'GET',
mask: true,
}
});
proxy.ensure(null, function (err, result) {
if (err) {
console.log('查询合同详情请求遇到错误:', err);
Message.create({ content: '查询合同详情请求遇到错误,请查看控制台输出的错误信息。', color: 'danger', duration:null });
return;
}
if (result) {
console.log(result);
if (result.status === 200) {
_this.setState({
bodyData: result.data
});
// Message.create({ content: '查询销售合同详情信息成功', color: 'success' });
} else {
Message.create({ content: `查询销售合同详情信息遇到错误:${result.message}`, color: 'danger', duration:null });
return;
}
}
});
}
/**
* 表体行点击事件
*/
bodyRowClick = (record, index, event) => {
console.log('bodyRowClick', record, index, event)
}
clear = () => {
let { data } = this.state;
data.forEach(item => item._checked = false)
this.setState({
data: JSON.parse(JSON.stringify(data))
})
};
/**
* 选择销售合同,点击确定
*/
sure = (event) => {
let selectData = this.getHeadSelectedData();
console.log('selectData', selectData);
this.props.viewModel.execute("contractSure", {
selectData
});
this.close();
};
/**
* 选择分页
*/
changePage(eventKey, pageSize) {
this.setState({
headData: [],
current: eventKey,
});
}
/**
* 查询销售合同
*/
handleSearch = event => {
event.preventDefault();
let _this = this;
this.form.current
.validateFields()
.then((...val) => {
let params = {
// 'pageInfo': {
// 'currPage': _this.state.current,
// 'pageSize': _this.state.pageSize
// },
'queryInfo': {
// 'contrDateBegin': moment(val[0].contrDate[0]).format("YYYY-MM-DD"),
// 'contrDateEnd': moment(val[0].contrDate[1]).format("YYYY-MM-DD"),
'contrDateBegin': '2010-01-01',
'contrDateEnd': '2021-12-31',
'custName': val[0].custName,
'contrName': val[0].contrName
}
}
let proxy = cb.rest.DynamicProxy.create({
ensure: {
url: '/saleContract/searchList',
method: 'POST',
mask: true,
}
});
proxy.ensure(params, function (err, result) {
if (err) {
console.log('查询合同请求遇到错误:', err);
Message.create({ content: '查询合同请求遇到错误,请查看控制台输出的错误信息。', color: 'danger', duration:null });
return;
}
if (result) {
console.log(result);
if (result.status === 200) {
_this.setState({
headData: result.data.contrData,
// total: result.data.pageInfo.totalPages
});
// Message.create({ content: '查询销售合同信息成功', color: 'success' });
} else {
Message.create({ content: `查询销售合同信息遇到错误:${result.message}`, color: 'danger', duration:null });
return;
}
}
});
})
.catch(errInfo => {
console.log(errInfo);
})
}
/**
* 搜索条件改变
* @param {*} changedFields
* @param {*} allFields
*/
onFieldsChange = (changedFields, allFields) => {
console.log(changedFields, allFields);
}
render() {
const layout = {
labelCol: { span: 8 },
wrapperCol: { span: 30 },
};
let multiObj = {
type: "checkbox"
};
return (
<div>
<Modal
show={this.state.showModal}
onCancel={this.close}
size="lg"
ref={ref => this.modal = ref}
className="demo10-modal"
bodyStyle={{ padding: '16px 0' }}
width={'80%'}
height={'80%'}
// resizable={true}
// centered
>
<Modal.Header closeButton>
<Modal.Title>销售合同</Modal.Title>
</Modal.Header>
<Modal.Body>
{/* 合同搜索表单 */}
<Form
className="searchForm"
ref={this.form}
{...layout}
// layout={'inline'}
layout="inline"
onFieldsChange={this.onFieldsChange}
>
{/* <Form.Item
name='select'
label='Select'
// rules={[{ required: true, message: '请选择城市' }]}
>
<Select placeholder='请选择城市'>
<Option value='china'>中国</Option>
<Option value='usa'>英国</Option>
</Select>
</Form.Item> */}
<Form.Item
required
label='合同日期'
name='contrDate'
// validateStatus='error'
// hasFeedback
// rules={[
// {
// required: true,
// type: 'array',
// message: '请输入合同日期'
// }
// ]}
>
{/* <DatePicker /> */}
{/* <RangePicker format='YYYY-MM-DD' /> */}
<RangePicker
placeholder={'开始 ~ 结束'}
dateInputPlaceholder={['开始', '结束']}
format='YYYY-MM-DD'
// onChange={(d, dataString) => {
// console.log('change')
// console.log(d);
// console.log(dataString);
// }}
// onPanelChange={(v) => { console.log('onPanelChange', v) }}
allowClear={true}
// onStartInputBlur={(e,startValue,array) => {
// console.log('RangePicker面板 左输入框的失焦事件',startValue,array)
// }}
// onEndInputBlur={(e,endValue,array) => {
// console.log('RangePicker面板 右输入框的失焦事件',endValue,array)
// }}
/>
</Form.Item>
<Form.Item
// required
label='客户名称'
name='custName'
// validateStatus='error'
// hasFeedback
// rules={[
// {
// required: true,
// message: '请输入客户名称'
// }
// ]}
>
<Input placeholder='请输入客户名称' />
</Form.Item>
<Form.Item
// required
label='合同名称'
name='contrName'
// validateStatus='error'
// hasFeedback
// rules={[
// {
// required: true,
// message: '请输入合同名称'
// }
// ]}
>
<Input placeholder='请输入合同名称' />
</Form.Item>
<Form.Item label=' '>
<Button colors='primary' className='login' onClick={this.handleSearch}>
搜索合同
</Button>
</Form.Item>
</Form>
{/* 展示合同的表格 */}
<div className='headBox'>
<MultiSelectTable
columns={HeadColumns}
data={this.state.headData}
multiSelect={multiObj}
getSelectedDataFunc={this.getHeadSelectedData}
autoCheckedByClickRows={true} //行点击是否触发勾选动作
onRowClick={this.headRowClick}
scroll={{ y: 280 }}
/>
</div>
{/* 分页组件 */}
{/* <Pagination
showSizeChanger={false}// 是否显示页码选择框
showQuickJumper={false}// 是否显示跳页选择
pageSizeOptions={["10", "20", "30", "50", "100"]}
total={this.state.total}
defaultPageSize={10}
pageSize={this.state.pageSize}
current={this.state.current}
onChange={this.changePage.bind(this)}
onPageSizeChange={(activePage, dataNumValue) =>
console.log('onPageSizeChange', activePage, dataNumValue)
}
confirmBtn={(e1, e2) =>
console.log('confirmBtn', e1, e2)
}
/> */}
{/* 表体详情 */}
<MultiSelectTable
columns={BodyColumns}
data={this.state.bodyData}
multiSelect={multiObj}
getSelectedDataFunc={this.getBodySelectedData}
autoCheckedByClickRows={true} //行点击是否触发勾选动作
onRowClick={this.bodyRowClick}
scroll={{ y: 240 }}
/>
</Modal.Body>
<Modal.Footer>
<Button onClick={this.close} colors="secondary" style={{ marginRight: 8 }}>取消</Button>
<Button onClick={this.sure} colors='primary'>确认</Button>
</Modal.Footer>
</Modal>
</div>
)
}
}
export default Form.createForm()(RefSalesCont);
src\client\web\components\modal\RefSalesCont\index.less
.searchForm {
margin-bottom: 1em;
}
.headBox {
// background-color: aquamarine;
width: 100%;
height: 30em;
}
src\client\web\components\modal\RefSalesCont\constant.js
export const HeadColumns = [
{ title: "销售组织", dataIndex: "sale_org", key: "sale_org", width: 150, className: "rowClassName" },
{ title: "合同编码", dataIndex: "contr_code", key: "contr_code", width: 150 },
{ title: "合同名称", dataIndex: "contr_name", key: "contr_name", width: 150 },
{ title: "合同签订日期", dataIndex: "subscribedate", key: "subscribedate", width: 150 },
{ title: "计划生效日期", dataIndex: "valdate", key: "valdate", width: 150 },
{ title: "计划终止日期", dataIndex: "invallidate", key: "invallidate", width: 150 },
{ title: "客户", dataIndex: "customer", key: "customer", width: 150 },
{ title: "人员", dataIndex: "person", key: "person", width: 150 },
{ title: "部门", dataIndex: "department", key: "department", width: 150 },
{ title: "总数量", dataIndex: "total_num", key: "total_num", width: 150 },
{ title: "价税合计", dataIndex: "total_money", key: "total_money", width: 150 }
];
export const BodyColumns = [
{ title: "物料编码", dataIndex: "materialcode", key: "materialcode", width: 150, className: "rowClassName" },
{ title: "物料名称", dataIndex: "materialname", key: "materialname", width: 150 },
{ title: "规格", dataIndex: "materialspec", key: "materialspec", width: 150 },
{ title: "型号", dataIndex: "materialtype", key: "materialtype", width: 150 },
{ title: "单位", dataIndex: "castunit", key: "castunit", width: 150 },
{ title: "数量", dataIndex: "nastnum", key: "nastnum", width: 150 },
{ title: "无税单价", dataIndex: "nqtorigprice", key: "nqtorigprice", width: 150 },
{ title: "含税单价", dataIndex: "nqtorigtaxprice", key: "nqtorigtaxprice", width: 150 },
{ title: "无税金额", dataIndex: "norigmny", key: "norigmny", width: 150 },
{ title: "价税合计", dataIndex: "norigtaxmny", key: "norigtaxmny", width: 150 },
{ title: "备注", dataIndex: "vmemo", key: "vmemo", width: 150 }
];
在页面对应的js文件中调用弹窗
cb.define(process.env.__DOMAINKEY__, [], function () {
let tms_sale_87721978List_VM_Extend = {
doAction: function (name, viewModel) {
if (this[name])
this[name](viewModel);
},
init: function (viewModel) {
console.log('************* - tms_sale_87721978List_VM_Extend - *************************');
// 点击参照合同按钮弹出模态框
viewModel.get('button21wh').on('click', function (data) {
console.log('************* - enter ref button - *************************');
viewModel.communication({
type: 'modal',
payload: {
key: 'RefSalesCont',
data: {
viewModel: viewModel,
showModal: true
},
},
});
})
// 弹出模态框的确定按钮的回调事件
viewModel.on('contractSure', function(data){
console.log('进入了销售订单页面,销售合同页面传入数据为:', data)
})
}
}
try {
module.exports = tms_sale_87721978List_VM_Extend;
} catch (error) {
}
return tms_sale_87721978List_VM_Extend;
});