This commit is contained in:
devezhao-corp 2018-10-10 22:32:25 +08:00
parent ebad4335cf
commit dae6ff0a03
14 changed files with 19953 additions and 163 deletions

View file

@ -137,7 +137,12 @@ public class AccessibleMeta implements BaseMeta {
return dt; return dt;
} }
Type ft = ((Field) baseMeta).getType(); Field field = (Field) baseMeta;
if (field.getOwnEntity().getEntityCode() == EntityHelper.User && "email".equals(field.getName())) {
return DisplayType.EMAIL;
}
Type ft = field.getType();
if (ft == FieldType.PRIMARY) { if (ft == FieldType.PRIMARY) {
return DisplayType.ID; return DisplayType.ID;
} else if (ft == FieldType.REFERENCE) { } else if (ft == FieldType.REFERENCE) {

View file

@ -77,8 +77,8 @@ public class FormManager extends LayoutManager {
* @param entity * @param entity
* @return * @return
*/ */
public static JSON getFormModal(String entity, ID user) { public static JSON getFormModel(String entity, ID user) {
return getFormModal(entity, user, null); return getFormModel(entity, user, null);
} }
/** /**
@ -89,7 +89,7 @@ public class FormManager extends LayoutManager {
* @param recordId * @param recordId
* @return * @return
*/ */
public static JSON getFormModal(String entity, ID user, ID recordId) { public static JSON getFormModel(String entity, ID user, ID recordId) {
Assert.notNull(entity, "[entity] not be null"); Assert.notNull(entity, "[entity] not be null");
Assert.notNull(user, "[user] not be null"); Assert.notNull(user, "[user] not be null");
@ -102,7 +102,7 @@ public class FormManager extends LayoutManager {
Record record = null; Record record = null;
if (!elements.isEmpty() && recordId != null) { if (!elements.isEmpty() && recordId != null) {
record = record(recordId, elements); record = queryRecord(recordId, elements);
} }
for (Object element : elements) { for (Object element : elements) {
@ -178,9 +178,9 @@ public class FormManager extends LayoutManager {
* @param recordId * @param recordId
* @return * @return
*/ */
public static JSON getViewModal(String entity, ID user, ID recordId) { public static JSON getViewModel(String entity, ID user, ID recordId) {
Assert.notNull(recordId, "[recordId] not be null"); Assert.notNull(recordId, "[recordId] not be null");
return getFormModal(entity, user, recordId); return getFormModel(entity, user, recordId);
} }
/** /**
@ -188,7 +188,7 @@ public class FormManager extends LayoutManager {
* @param elements * @param elements
* @return * @return
*/ */
protected static Record record(ID id, JSONArray elements) { protected static Record queryRecord(ID id, JSONArray elements) {
if (elements.isEmpty()) { if (elements.isEmpty()) {
return null; return null;
} }

View file

@ -24,6 +24,7 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.ModelAndView;
@ -44,10 +45,9 @@ import cn.devezhao.persist4j.engine.ID;
* @since 10/08/2018 * @since 10/08/2018
*/ */
@Controller @Controller
@RequestMapping("/admin/bizuser/")
public class UserControll extends BaseControll { public class UserControll extends BaseControll {
@RequestMapping("users") @RequestMapping("/admin/bizuser/users")
public ModelAndView pageList(HttpServletRequest request) throws IOException { public ModelAndView pageList(HttpServletRequest request) throws IOException {
ModelAndView mv = createModelAndView("/admin/bizuser/user-list.jsp", "User"); ModelAndView mv = createModelAndView("/admin/bizuser/user-list.jsp", "User");
JSON cfg = DataListManager.getColumnLayout("User"); JSON cfg = DataListManager.getColumnLayout("User");
@ -55,7 +55,15 @@ public class UserControll extends BaseControll {
return mv; return mv;
} }
@RequestMapping("dept-tree") @RequestMapping("/app/User/view/{id}")
public ModelAndView pageView(@PathVariable String id, HttpServletRequest request) throws IOException {
ID recordId = ID.valueOf(id);
ModelAndView mv = createModelAndView("/admin/bizuser/user-view.jsp", "User");
mv.getModel().put("id", recordId);
return mv;
}
@RequestMapping("/admin/bizuser/dept-tree")
public void deptTreeGet(HttpServletRequest request, HttpServletResponse response) throws IOException { public void deptTreeGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
Object[][] firstDepts = Application.createQuery( Object[][] firstDepts = Application.createQuery(
"select deptId from Department where parentDept is null") "select deptId from Department where parentDept is null")

View file

@ -52,21 +52,21 @@ public class GeneralEntityControll extends BaseControll {
return mv; return mv;
} }
@RequestMapping("{entity}/form-modal") @RequestMapping("{entity}/form-model")
public void entityForm(@PathVariable String entity, public void entityForm(@PathVariable String entity,
HttpServletRequest request, HttpServletResponse response) throws IOException { HttpServletRequest request, HttpServletResponse response) throws IOException {
ID recordId = getIdParameter(request, "id"); ID recordId = getIdParameter(request, "id");
JSON fc = FormManager.getFormModal(entity, getRequestUser(request), recordId); JSON fc = FormManager.getFormModel(entity, getRequestUser(request), recordId);
writeSuccess(response, fc); writeSuccess(response, fc);
} }
@RequestMapping("{entity}/view-modal") @RequestMapping("{entity}/view-model")
public void entityView(@PathVariable String entity, public void entityView(@PathVariable String entity,
HttpServletRequest request, HttpServletResponse response) throws IOException { HttpServletRequest request, HttpServletResponse response) throws IOException {
ID user = getRequestUser(request); ID user = getRequestUser(request);
ID recordId = getIdParameterNotNull(request, "id"); ID recordId = getIdParameterNotNull(request, "id");
JSON modal = FormManager.getViewModal(entity, user, recordId); JSON modal = FormManager.getViewModel(entity, user, recordId);
writeSuccess(response, modal); writeSuccess(response, modal);
} }
} }

View file

@ -11,6 +11,6 @@
<script src="${baseUrl}/assets/js/rb-base.js"></script> <script src="${baseUrl}/assets/js/rb-base.js"></script>
<script src="${baseUrl}/assets/js/rb-page.js"></script> <script src="${baseUrl}/assets/js/rb-page.js"></script>
<script src="${baseUrl}/assets/lib/react/babel.min.js"></script> <script src="${baseUrl}/assets/lib/react/babel.min.js"></script>
<script src="${baseUrl}/assets/lib/react/react.production.min.js"></script> <script src="${baseUrl}/assets/lib/react/react.development.js"></script>
<script src="${baseUrl}/assets/lib/react/react-dom.production.min.js"></script> <script src="${baseUrl}/assets/lib/react/react-dom.development.js"></script>
<script src="${baseUrl}/assets/js/rb-components.jsx" type="text/babel"></script> <script src="${baseUrl}/assets/js/rb-components.jsx" type="text/babel"></script>

View file

@ -0,0 +1,57 @@
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<%@ include file="/_include/Head.jsp"%>
<title>${entityLabel}视图</title>
<style type="text/css">
html,body{overflow:auto;height:100%;}
.main-content{margin-top:62px;}
.tab-container{margin-top:-8px}
.tab-content{padding:0;margin:0;padding-top:13px}
.view-header{padding:15px 20px;height:62px;border-bottom:1px solid #e3e3e3;position:absolute;top:0;left:0;width:100%;z-index:101;background-color:#fff}
.view-header .header-icon{float:left;}
.view-header .title{line-height:1.428571;display:inline-block;margin:0;font-weight:300;font-size:1.538rem}
.view-oper{}
.view-oper .btns{padding-bottom:15px;}
.view-oper .btns .btn{width:100%;}
.view-oper .btns .btn+.btn{margin-top:6px}
</style>
</head>
<body class="dialog">
<div class="view-header">
<span class="header-icon zmdi zmdi-${entityIcon}"></span>
<h3 class="title">${entityLabel}视图</h3>
</div>
<div class="main-content container-fluid invisible">
<div class="row">
<div class="col-sm-10">
<div id="tab-rbview"></div>
</div>
<div class="col-sm-2">
<div class="view-oper">
<div class="btns">
<button class="btn btn-secondary J_edit" type="button">编辑</button>
</div>
</div>
</div>
</div>
</div>
<%@ include file="/_include/Foot.jsp"%>
<script src="${baseUrl}/assets/js/rb-forms.jsx" type="text/babel"></script>
<script src="${baseUrl}/assets/js/rb-forms-ext.jsx" type="text/babel"></script>
<script src="${baseUrl}/assets/js/rb-view.jsx" type="text/babel"></script>
<script type="text/babel">
var rbFromView
$(document).ready(function(){
const recordId = '${id}'
rbFromView = renderRbcomp(<RbViewForm entity="${entityName}" id={recordId} />, 'tab-rbview')
$('.J_edit').click(function(){
renderRbFormModal(recordId, '编辑记录', '${entityName}', '${entityIcon}')
});
});
</script>
</body>
</html>

View file

@ -277,10 +277,11 @@ a {
width: 100%; width: 100%;
height: 100%; height: 100%;
} }
.img-field.avatar label.img-upload { .img-field.avatar .img-upload {
border-radius: 50%; border-radius: 50%;
overflow: hidden; overflow: hidden;
padding: 0; padding: 0;
border: 0 none;
} }
.img-field.avatar label.img-upload:hover{ .img-field.avatar label.img-upload:hover{
border: 0 none; border: 0 none;

View file

@ -14,7 +14,7 @@ class RbModal extends React.Component {
<button className="close" type="button" onClick={()=>this.hide()}><span className="zmdi zmdi-close"></span></button> <button className="close" type="button" onClick={()=>this.hide()}><span className="zmdi zmdi-close"></span></button>
</div> </div>
<div className={'modal-body rb-loading ' + (this.state.inLoad == true && ' rb-loading-active') + ' ' + (this.state.url && ' iframe')}> <div className={'modal-body rb-loading ' + (this.state.inLoad == true && ' rb-loading-active') + ' ' + (this.state.url && ' iframe')}>
{this.props.children || <iframe src={this.state.url || 'about:blank'} frameborder="0" scrolling="no" onLoad={()=>this.resize()} onResize={()=>this.resize()}></iframe>} {this.props.children || <iframe src={this.state.url || 'about:blank'} frameBorder="0" scrolling="no" onLoad={()=>this.resize()} onResize={()=>this.resize()}></iframe>}
<RbSpinner /> <RbSpinner />
</div> </div>
</div> </div>
@ -77,7 +77,7 @@ class RbAlter extends React.Component {
<h4>{this.props.title || '提示'}</h4> <h4>{this.props.title || '提示'}</h4>
{content} {content}
<div className="mt-6 mb-4"> <div className="mt-6 mb-4">
<button class="btn btn-space btn-secondary" type="button" onClick={()=>this.hide()}>取消</button> <button className="btn btn-space btn-secondary" type="button" onClick={()=>this.hide()}>取消</button>
<button className={'btn btn-space btn-' + type} type="button" onClick={confirm}>确定</button> <button className={'btn btn-space btn-' + type} type="button" onClick={confirm}>确定</button>
</div> </div>
</div> </div>
@ -136,7 +136,7 @@ class RbNotice extends React.Component {
function RbSpinner(props) { function RbSpinner(props) {
return <div className="rb-spinner"> return <div className="rb-spinner">
<svg width="40px" height="40px" viewBox="0 0 66 66" xmlns="http://-www.w3.org/2000/svg"> <svg width="40px" height="40px" viewBox="0 0 66 66" xmlns="http://-www.w3.org/2000/svg">
<circle fill="none" stroke-width="4" stroke-linecap="round" cx="33" cy="33" r="30" class="circle"></circle> <circle fill="none" strokeWidth="4" strokeLinecap="round" cx="33" cy="33" r="30" className="circle"></circle>
</svg> </svg>
</div> </div>
} }

View file

@ -13,11 +13,13 @@ class RbFormBool extends RbFormElement {
renderElement() { renderElement() {
return ( return (
<div> <div>
<label className="custom-control custom-radio custom-control-inline" onClick={this.changeValue.bind(this, 'T')}> <label className="custom-control custom-radio custom-control-inline">
<input className="custom-control-input" name="radio-inline" type="radio" value="F" checked={this.state.value == 'T'}/><span className="custom-control-label"></span> <input className="custom-control-input" name={'radio-' + this.props.field} type="radio" checked={this.state.value == 'T'} onChange={this.changeValue.bind(this, 'T')} />
<span className="custom-control-label"></span>
</label> </label>
<label className="custom-control custom-radio custom-control-inline" onClick={this.changeValue.bind(this, 'F')}> <label className="custom-control custom-radio custom-control-inline">
<input className="custom-control-input" name="radio-inline" type="radio" value="T" checked={this.state.value == 'F'}/><span className="custom-control-label"></span> <input className="custom-control-input" name={'radio-' + this.props.field} type="radio" checked={this.state.value == 'F'} onChange={this.changeValue.bind(this, 'F')} />
<span className="custom-control-label"></span>
</label> </label>
</div> </div>
) )
@ -33,14 +35,26 @@ class RbFormAvatar extends RbFormElement {
super(props) super(props)
} }
renderElement() { renderElement() {
let avatarUrl = rb.storageUrl + (this.state.value || 'rebuild/20181010/041046550__avatar.png') + '?imageView2/2/w/100/interlace/1/q/100'
return ( return (
<div className="img-field avatar"> <div className="img-field avatar">
<span title="选择头像图片"> <span title="选择头像图片">
<input type="file" className="inputfile" ref="upload-input" id={this.props.field + '-input'} accept="image/*" /> <input type="file" className="inputfile" ref="upload-input" id={this.props.field + '-input'} accept="image/*" />
<label for={this.props.field + '-input'} class="img-thumbnail img-upload"><img src={avatarUrl}/></label> <label htmlFor={this.props.field + '-input'} className="img-thumbnail img-upload">
<img src={rb.storageUrl + (this.state.value || 'rebuild/20181010/041046550__avatar.png') + '?imageView2/2/w/100/interlace/1/q/100'}/>
</label>
</span> </span>
</div>) </div>
)
}
renderViewElement() {
let avatarUrl = rb.storageUrl + (this.props.value || 'rebuild/20181010/041046550__avatar.png') + '?imageView2/2/w/100/interlace/1/q/100'
return (
<div className="img-field avatar">
<a className="img-thumbnail img-upload">
<img src={rb.storageUrl + (this.state.value || 'rebuild/20181010/041046550__avatar.png') + '?imageView2/2/w/100/interlace/1/q/100'}/>
</a>
</div>
)
} }
componentDidMount() { componentDidMount() {
super.componentDidMount() super.componentDidMount()
@ -50,15 +64,15 @@ class RbFormAvatar extends RbFormElement {
postUrl: rb.baseUrl + '/filex/upload?cloud=auto&type=image', postUrl: rb.baseUrl + '/filex/upload?cloud=auto&type=image',
onClientLoad: function(e, file){ onClientLoad: function(e, file){
if (file.type.substr(0, 5) != 'image'){ if (file.type.substr(0, 5) != 'image'){
that.props.$$$parent.showNotice('请上传图片') rb.notice('请上传图片')
return false return false
} }
}, },
onSuccess:function(d){ onSuccess:function(d){
d = JSON.parse(d.currentTarget.response) d = JSON.parse(d.currentTarget.response)
if (d.error_code == 0){ if (d.error_code == 0){
that.handleChange({ target:{ value: d.data } }, false) that.handleChange({ target:{ value: d.data } }, true)
} else that.showNotice(d.error_msg || '上传失败,请稍后重试') } else rb.notice(d.error_msg || '上传失败,请稍后重试', 'danger')
} }
}) })
} }

View file

@ -28,14 +28,15 @@ class RbFormModal extends React.Component {
} }
componentDidMount() { componentDidMount() {
this.show() this.show()
if (!!!this.state.id) this.__getFormModal() if (!!!this.state.id) this.getFormModel()
} }
// //
__getFormModal() { getFormModel() {
let that = this let that = this
const entity = this.state.entity const entity = this.state.entity
const id = this.state.id || '' const id = this.state.id || ''
$.get(rb.baseUrl + '/app/' + entity + '/form-modal?entity=' + entity + '&id=' + id, function(res){ $.get(rb.baseUrl + '/app/' + entity + '/form-model?entity=' + entity + '&id=' + id, function(res){
let elements = res.data.elements let elements = res.data.elements
const FORM = <RbForm entity={entity} id={id} $$$parent={that}> const FORM = <RbForm entity={entity} id={id} $$$parent={that}>
{elements.map((item) => { {elements.map((item) => {
@ -47,36 +48,35 @@ class RbFormModal extends React.Component {
}) })
}) })
} }
show(state) { show(state) {
state = state || {} state = state || {}
let that = this let that = this
if (state.id != this.state.id || state.entity != this.state.entity) { if (state.id != this.state.id || state.entity != this.state.entity) {
state = { ...state, isDestroy: true, formComponent: null, inLoad: true } state = { ...state, isDestroy: true, formComponent: null, inLoad: true }
this.setState(state, function(){ this.setState(state, function(){
that.__show({ ...state, isDestroy: false }, true) that.showAfter({ ...state, isDestroy: false }, true)
}) })
} else { } else {
this.__show({ ...state, isDestroy: false }) this.showAfter({ ...state, isDestroy: false })
} }
} }
__show(state, idChanged) { showAfter(state, modelChanged) {
let that = this let that = this
this.setState(state, function(){ this.setState(state, function(){
$(that.refs['rbmodal']).modal({ show: true, backdrop: 'static' }) $(that.refs['rbmodal']).modal({ show: true, backdrop: 'static' })
if (idChanged == true) { if (modelChanged == true) {
that.__getFormModal() that.getFormModel()
} }
}) })
} }
hide(destroy) { hide(destroy) {
$(this.refs['rbmodal']).modal('hide') $(this.refs['rbmodal']).modal('hide')
let state = { noticeMessage: null, isDestroy: false } let state = { isDestroy: false }
if (destroy == true) state = { ...state, isDestroy: true, id: null } if (destroy === true) state = { ...state, isDestroy: true, id: null }
this.setState(state) this.setState(state)
} }
showNotice(message, type) {
rb.notice(message, type, { html: true })
}
} }
// ~~ // ~~
@ -87,7 +87,6 @@ class RbForm extends React.Component {
this.__FormData = {} this.__FormData = {}
this.setFieldValue = this.setFieldValue.bind(this) this.setFieldValue = this.setFieldValue.bind(this)
this.showNotice = this.showNotice.bind(this)
} }
render() { render() {
let that = this let that = this
@ -95,68 +94,73 @@ class RbForm extends React.Component {
<div className="rbform"> <div className="rbform">
<form> <form>
{this.props.children.map((child) => { {this.props.children.map((child) => {
child.props.$$$parent = that return React.cloneElement(child, { $$$parent: that })
return child // strict mode have error
// child.$$$parent = that
// return child
})} })}
{this.props.children.length == 0 ? this.__renderFormError() : {this.props.children.length == 0 ? this.renderFormError() : this.renderFormAction()}
(<div className="form-group row footer">
<div className="col-12 col-sm-8 offset-sm-3" ref="rbform-action">
<button className="btn btn-primary btn-space" type="button" onClick={()=>this.post()}>保存</button>
&nbsp;
<button className="btn btn-secondary btn-space" type="button" onClick={()=>this.props.$$$parent.hide()}>取消</button>
</div>
</div>)
}
</form> </form>
</div> </div>
) )
} }
__renderFormError(message) {
let fdUrl = rb.baseUrl + '/admin/entity/' + this.props.entity + '/form-design' renderFormAction() {
message = message || `布局尚未配置,请 <a href="${fdUrl}">配置</a> 后使用` return (
<div className="form-group row footer">
<div className="col-12 col-sm-8 offset-sm-3" ref="rbform-action">
<button className="btn btn-primary btn-space" type="button" onClick={()=>this.post()}>保存</button>
&nbsp;
<button className="btn btn-secondary btn-space" type="button" onClick={()=>this.props.$$$parent.hide()}>取消</button>
</div>
</div>
)
}
renderFormError(message) {
let adminUrl = rb.baseUrl + '/admin/entity/' + this.props.entity + '/form-design'
message = message || `布局尚未配置,请 <a href="${adminUrl}">配置</a> 后使用`
message = { __html: '<strong>错误! </strong> ' + message } message = { __html: '<strong>错误! </strong> ' + message }
return <div class="alert alert-contrast alert-warning"> return <div className="alert alert-contrast alert-warning">
<div class="icon"><span class="zmdi zmdi-alert-triangle"></span></div> <div className="icon"><span className="zmdi zmdi-alert-triangle"></span></div>
<div class="message" dangerouslySetInnerHTML={message}></div> <div className="message" dangerouslySetInnerHTML={message}></div>
</div> </div>
} }
componentDidMount() {
}
setFieldValue(field, value, error) { setFieldValue(field, value, error) {
this.__FormData[field] = { value:value, error:error } this.__FormData[field] = { value: value, error: error }
console.log('Set data ... ' + JSON.stringify(this.__FormData)) console.log('Sets field-value ... ' + JSON.stringify(this.__FormData))
} }
showNotice(message, type) { setFieldUnchanged(field) {
this.props.$$$parent.showNotice(message, type) delete this.__FormData[field]
console.log('Unchanged field-value ... ' + JSON.stringify(this.__FormData))
} }
post() { post() {
console.log('Post data ... ' + JSON.stringify(this.__FormData))
// Check Error
let _data = {} let _data = {}
for (let k in this.__FormData) { for (let k in this.__FormData) {
let err = this.__FormData[k].error let err = this.__FormData[k].error
if (err){ this.showNotice(err); return } if (err){ rb.notice(err); return }
else _data[k] = this.__FormData[k].value else _data[k] = this.__FormData[k].value
} }
_data.metadata = { entity: this.state.entity, id: this.state.id } _data.metadata = { entity: this.state.entity, id: this.state.id }
let actions = $(this.refs['rbform-action']).find('.btn').button('loading') let btns = $(this.refs['rbform-action']).find('.btn').button('loading')
let that = this let that = this
$.post(rb.baseUrl + '/app/entity/record-save', JSON.stringify(_data), function(res){ $.post(rb.baseUrl + '/app/entity/record-save', JSON.stringify(_data), function(res){
actions.button('reset') btns.button('reset')
if (res.error_code == 0){ if (res.error_code == 0){
that.showNotice('保存成功', 'success') rb.notice('保存成功', 'success')
that.props.$$$parent.hide(true) that.props.$$$parent.hide(true)
if (window.formPostAfterCall) window.formPostAfterCall() if (window.formPostAfterCall) window.formPostAfterCall()
}else{ }else{
that.showNotice(res.error_msg || '保存失败,请稍后重试', 'danger') rb.notice(res.error_msg || '保存失败,请稍后重试', 'danger')
} }
}) })
} }
} }
// //
class RbFormElement extends React.Component { class RbFormElement extends React.Component {
constructor(props) { constructor(props) {
super(props) super(props)
@ -165,46 +169,62 @@ class RbFormElement extends React.Component {
this.handleChange = this.handleChange.bind(this) this.handleChange = this.handleChange.bind(this)
this.checkError = this.checkError.bind(this) this.checkError = this.checkError.bind(this)
} }
render() { render() {
let colWidths = [3, 8] let colWidths = [3, 8]
if (this.props.onView) { if (this.props.onView) {
colWidths[0] = 4 colWidths[0] = 4
if (this.props.isFull) colWidths = [2, 10] if (this.props.isFull == true) colWidths = [2, 10]
} }
return ( return (
<div className={'form-group row type-' + this.props.type}> <div className={'form-group row type-' + this.props.type}>
<label className={'col-12 col-form-label text-sm-right col-sm-' + colWidths[0]} title={this.props.nullable ? '' : '必填项'}>{this.props.label}{!this.props.nullable && <em/>}</label> <label className={'col-12 col-form-label text-sm-right col-sm-' + colWidths[0]} title={this.props.nullable ? '' : '必填项'}>{this.props.label}{!this.props.nullable && <em/>}</label>
<div className={'col-12 col-sm-' + colWidths[1]}> <div className={'col-12 col-sm-' + colWidths[1]}>
{this.state.editMode === false ? this.renderViewElement() : this.renderElement()} {this.state.viewMode === true ? this.renderViewElement() : this.renderElement()}
</div> </div>
</div> </div>
) )
} }
componentDidMount(e) {
let props = this.props
if (props.nullable == false && props.readonly == false) {
if (props.onView === true) {
} else {
this.props.$$$parent.setFieldValue(this.props.field, null, this.props.label + '不能为空')
}
}
}
renderViewElement() { renderViewElement() {
return <div className="form-control-plaintext">{this.state.value || (<span className="text-muted"></span>)}</div> return <div className="form-control-plaintext">{this.state.value || (<span className="text-muted"></span>)}</div>
} }
renderElement() { renderElement() {
return '子类复写此方法' return '子类复写此方法'
} }
handleChange(event, fireCheckError) { componentDidMount(e) {
let props = this.props
//
if (props.nullable == false && props.readonly == false && props.onView != true) {
if (!props.value) {
props.$$$parent.setFieldValue(props.field, null, props.label + '不能为空')
}
}
}
//
handleChange(event, checkError) {
let val = event.target.value let val = event.target.value
let that = this let that = this
this.setState({ value: val }, fireCheckError && function(){ that.checkError() }) this.setState({ value: val }, function(){ checkError == true && that.checkError() } )
} }
checkError() { checkError() {
// Unchanged Uncheck
if (this.state.value && this.props.value == this.state.value) {
if (this.__lastValue != this.props.value) {
this.props.$$$parent.setFieldUnchanged(this.props.field)
this.__lastValue = this.props.value
}
return
}
if (this.__lastValue && this.__lastValue == this.state.value) {
return
}
this.__lastValue = this.state.value
let err = this.checkHasError() let err = this.checkHasError()
this.setState({ hasError: err }) this.setState({ hasError: err })
let errTips = !!err ? (this.props.label + err) : null let errMsg = !!err ? (this.props.label + err) : null
this.props.$$$parent.setFieldValue(this.props.field, this.state.value, errTips) this.props.$$$parent.setFieldValue(this.props.field, this.state.value, errMsg)
} }
checkHasError(){ checkHasError(){
if (this.props.nullable == false) { if (this.props.nullable == false) {
@ -233,7 +253,7 @@ class RbFormText extends RbFormElement {
} }
renderElement() { renderElement() {
return ( return (
<input ref="field-value" className={'form-control form-control-sm ' + (this.state.hasError ? 'is-invalid' : '')} title={this.state.hasError} type="text" value={this.state.value} data-nullable={this.props.nullable} onChange={this.handleChange} onBlur={this.checkError} /> <input ref="field-value" className={'form-control form-control-sm ' + (this.state.hasError ? 'is-invalid' : '')} title={this.state.hasError} type="text" value={this.state.value} onChange={this.handleChange} onBlur={this.checkError} />
) )
} }
} }
@ -245,14 +265,13 @@ class RbFormUrl extends RbFormText {
} }
renderViewElement() { renderViewElement() {
if (!!!this.state.value) return super.renderViewElement() if (!!!this.state.value) return super.renderViewElement()
let link = rb.baseUrl + '/commons/url-safe?url=' + encodeURIComponent(this.state.value) let clickUrl = rb.baseUrl + '/commons/url-safe?url=' + encodeURIComponent(this.state.value)
return (<div className="form-control-plaintext"><a href={link} className="link" target="_blank">{this.state.value}</a></div>) return (<div className="form-control-plaintext"><a href={clickUrl} className="link" target="_blank">{this.state.value}</a></div>)
} }
checkHasError() { checkHasError() {
let err = super.checkHasError() let err = super.checkHasError()
if (err) return err if (err) return err
let val = this.state.value return (!!this.state.value && $regex.isUrl(this.state.value) == false) ? '链接格式不正确' : null
return (!!val && $regex.isUrl(val) == false) ? '链接格式不正确' : null
} }
} }
@ -268,8 +287,7 @@ class RbFormEMail extends RbFormText {
checkHasError() { checkHasError() {
let err = super.checkHasError() let err = super.checkHasError()
if (err) return err if (err) return err
let val = this.state.value return (!!this.state.value && $regex.isMail(this.state.value) == false) ? '邮箱格式不正确' : null
return (!!val && $regex.isMail(val) == false) ? '邮箱格式不正确' : null
} }
} }
@ -281,8 +299,7 @@ class RbFormPhone extends RbFormText {
checkHasError() { checkHasError() {
let err = super.checkHasError() let err = super.checkHasError()
if (err) return err if (err) return err
let val = this.state.value return (!!this.state.value && $regex.isTel(this.state.value) == false) ? '电话/手机格式不正确' : null
return (!!val && $regex.isTel(val) == false) ? '电话/手机格式不正确' : null
} }
} }
@ -294,8 +311,7 @@ class RbFormNumber extends RbFormText {
checkHasError() { checkHasError() {
let err = super.checkHasError() let err = super.checkHasError()
if (err) return err if (err) return err
let val = this.state.value return (!!this.state.value && $regex.isNumber(this.state.value) == false) ? '整数格式不正确' : null
return (!!val && $regex.isNumber(val) == false) ? '整数格式不正确' : null
} }
} }
@ -307,8 +323,7 @@ class RbFormDecimal extends RbFormText {
checkHasError() { checkHasError() {
let err = super.checkHasError() let err = super.checkHasError()
if (err) return err if (err) return err
let val = this.state.value return (!!this.state.value && $regex.isDecimal(this.state.value) == false) ? '货币格式不正确' : null
return (!!val && $regex.isDecimal(val) == false) ? '货币格式不正确' : null
} }
} }
@ -319,7 +334,7 @@ class RbFormTextarea extends RbFormElement {
} }
renderElement() { renderElement() {
return ( return (
<textarea ref="field-value" className={'form-control form-control-sm row3x ' + (this.state.hasError ? 'is-invalid' : '')} title={this.state.hasError} value={this.state.value} data-nullable={this.props.nullable} onChange={this.handleChange} onBlur={this.checkError} /> <textarea ref="field-value" className={'form-control form-control-sm row3x ' + (this.state.hasError ? 'is-invalid' : '')} title={this.state.hasError} value={this.state.value} onChange={this.handleChange} onBlur={this.checkError} />
) )
} }
} }
@ -333,7 +348,7 @@ class RbFormDateTime extends RbFormElement {
renderElement() { renderElement() {
return ( return (
<div className="input-group datetime-field"> <div className="input-group datetime-field">
<input ref="field-value" className={'form-control form-control-sm ' + (this.state.hasError ? 'is-invalid' : '')} title={this.state.hasError} type="text" value={this.state.value} data-nullable={this.props.nullable} /> <input ref="field-value" className={'form-control form-control-sm ' + (this.state.hasError ? 'is-invalid' : '')} title={this.state.hasError} type="text" value={this.state.value}/>
<span className={'zmdi zmdi-close clean ' + (this.state.value ? '' : 'hide')} onClick={this.cleanValue}></span> <span className={'zmdi zmdi-close clean ' + (this.state.value ? '' : 'hide')} onClick={this.cleanValue}></span>
<div className="input-group-append"> <div className="input-group-append">
<button className="btn btn-primary" type="button" ref="field-value-icon"><i className="icon zmdi zmdi-calendar"></i></button> <button className="btn btn-primary" type="button" ref="field-value-icon"><i className="icon zmdi zmdi-calendar"></i></button>
@ -371,14 +386,14 @@ class RbFormDateTime extends RbFormElement {
keyboardNavigation: false, keyboardNavigation: false,
}).on('changeDate', function(event){ }).on('changeDate', function(event){
let val = $(this).val() let val = $(this).val()
that.handleChange({ target: { value:val } }, true) that.handleChange({ target: { value: val } }, true)
}) })
$(this.refs['field-value-icon']).click(()=>{ $(this.refs['field-value-icon']).click(()=>{
dtp.datetimepicker('show') dtp.datetimepicker('show')
}) })
} }
cleanValue() { cleanValue() {
this.handleChange({ target: { value:'' } }, true) this.handleChange({ target: { value: '' } }, true)
} }
} }
@ -392,11 +407,11 @@ class RbFormImage extends RbFormElement {
return ( return (
<div className="img-field"> <div className="img-field">
{this.state.value.map((item) => { {this.state.value.map((item) => {
return (<span><a class="img-thumbnail img-upload"><img src={rb.storageUrl + item}/><b title="移除" onClick={()=>this.removeItem(item)}><span className="zmdi zmdi-delete"></span></b></a></span>) return (<span><a className="img-thumbnail img-upload"><img src={rb.storageUrl + item + '?imageView2/2/w/100/interlace/1/q/100'}/><b title="移除" onClick={()=>this.removeItem(item)}><span className="zmdi zmdi-delete"></span></b></a></span>)
})} })}
<span title="选择图片"> <span title="选择图片">
<input type="file" className="inputfile" ref="upload-input" id={this.props.field + '-input'} accept="image/*" /> <input type="file" className="inputfile" ref="upload-input" id={this.props.field + '-input'} accept="image/*" />
<label for={this.props.field + '-input'} className="img-thumbnail img-upload"><span className="zmdi zmdi-image-alt"></span></label> <label htmlFor={this.props.field + '-input'} className="img-thumbnail img-upload"><span className="zmdi zmdi-image-alt"></span></label>
</span> </span>
<input ref="field-value" type="hidden" value={this.state.value} /> <input ref="field-value" type="hidden" value={this.state.value} />
</div> </div>
@ -418,7 +433,7 @@ class RbFormImage extends RbFormElement {
postUrl: rb.baseUrl + '/filex/upload?cloud=auto&type=image', postUrl: rb.baseUrl + '/filex/upload?cloud=auto&type=image',
onClientLoad: function(e, file){ onClientLoad: function(e, file){
if (file.type.substr(0, 5) != 'image'){ if (file.type.substr(0, 5) != 'image'){
that.props.$$$parent.showNotice('请上传图片') rb.notice('请上传图片')
return false return false
} }
mprogress = new Mprogress({ template:3 }) mprogress = new Mprogress({ template:3 })
@ -429,17 +444,17 @@ class RbFormImage extends RbFormElement {
mprogress.end() mprogress.end()
d = JSON.parse(d.currentTarget.response) d = JSON.parse(d.currentTarget.response)
if (d.error_code == 0){ if (d.error_code == 0){
let path = that.state.value let paths = that.state.value
path.push(d.data) paths.push(d.data)
that.handleChange({ target:{ value:path } }, true) that.handleChange({ target:{ value: paths } }, true)
} else that.showNotice(d.error_msg || '上传失败,请稍后重试') } else rb.notice(d.error_msg || '上传失败,请稍后重试', 'danger')
} }
}) })
} }
removeItem(item) { removeItem(item) {
let path = this.state.value let paths = this.state.value
path.remove(item) paths.remove(item)
this.handleChange({ target:{ value:path } }, true) this.handleChange({ target:{ value: paths } }, true)
} }
clickPreview() { clickPreview() {
} }
@ -460,7 +475,7 @@ class RbFormFile extends RbFormElement {
})} })}
<div className="file-select"> <div className="file-select">
<input type="file" className="inputfile" ref="upload-input" id={this.props.field + '-input'} /> <input type="file" className="inputfile" ref="upload-input" id={this.props.field + '-input'} />
<label for={this.props.field + '-input'} className="btn-secondary"><i className="zmdi zmdi-upload"></i><span>选择文件</span></label> <label htmlFor={this.props.field + '-input'} className="btn-secondary"><i className="zmdi zmdi-upload"></i><span>选择文件</span></label>
</div> </div>
<input ref="field-value" type="hidden" value={this.state.value} /> <input ref="field-value" type="hidden" value={this.state.value} />
</div> </div>
@ -489,17 +504,17 @@ class RbFormFile extends RbFormElement {
mprogress.end() mprogress.end()
d = JSON.parse(d.currentTarget.response) d = JSON.parse(d.currentTarget.response)
if (d.error_code == 0){ if (d.error_code == 0){
let path = that.state.value let paths = that.state.value
path.push(d.data) paths.push(d.data)
that.handleChange({ target:{ value:path } }, true) that.handleChange({ target:{ value: paths } }, true)
} else that.showNotice(d.error_msg || '上传失败,请稍后重试') } else rb.notice(d.error_msg || '上传失败,请稍后重试', 'danger')
} }
}) })
} }
removeItem(item) { removeItem(item) {
let path = this.state.value let paths = this.state.value
path.remove(item) paths.remove(item)
this.handleChange({ target:{ value:path } }, true) this.handleChange({ target:{ value: paths } }, true)
} }
clickPreview() { clickPreview() {
} }
@ -510,7 +525,7 @@ class RbFormPickList extends RbFormElement {
constructor(props) { constructor(props) {
super(props) super(props)
let options = this.props.options let options = props.options
for (let i = 0; i < options.length; i++){ for (let i = 0; i < options.length; i++){
if (options[i]['default'] === true) { if (options[i]['default'] === true) {
this.state.value = options[i]['id'] this.state.value = options[i]['id']
@ -538,9 +553,7 @@ class RbFormPickList extends RbFormElement {
let value = e.target.value let value = e.target.value
that.handleChange({ target:{ value:value } }, true) that.handleChange({ target:{ value:value } }, true)
}) })
$setTimeout(function() { $setTimeout(function() { select2.trigger("change") }, 100)
select2.trigger("change")
}, 100)
} }
componentWillUnmount() { componentWillUnmount() {
$(this.refs['field-value']).select2('destroy') $(this.refs['field-value']).select2('destroy')
@ -554,22 +567,21 @@ class RbFormReference extends RbFormElement {
} }
renderElement() { renderElement() {
return ( return (
<select ref="field-value" className="form-control form-control-sm" value={this.state.value} onChange={this.handleChange} multiple="multiple" style={{width:'100%'}} /> <select ref="field-value" className="form-control form-control-sm" onChange={this.handleChange} multiple="multiple" style={{width:'100%'}} />
) )
} }
renderViewElement() { renderViewElement() {
if (!!!this.state.value) return super.renderViewElement() if (!!!this.state.value) return super.renderViewElement()
return (<div className="form-control-plaintext"><a href="javascript:;" onClick={()=>this.clickView()}>{this.state.value[1]}</a></div>) return <div className="form-control-plaintext"><a href="javascript:;" onClick={()=>this.clickView()}>{this.state.value[1]}</a></div>
} }
componentDidMount() { componentDidMount() {
console.log('fire componentDidMount ... ')
super.componentDidMount() super.componentDidMount()
let that = this let that = this
let select2 = $(this.refs['field-value']).select2({ let select2 = $(this.refs['field-value']).select2({
language: 'zh-CN', language: 'zh-CN',
placeholder: '选择' + that.props.label, placeholder: '选择' + that.props.label,
allowClear: true, allowClear: true,
minimumInputLength: 1, minimumInputLength: 2,
ajax: { ajax: {
url: rb.baseUrl + '/app/commons/search', url: rb.baseUrl + '/app/commons/search',
delay: 300, delay: 300,
@ -585,17 +597,22 @@ class RbFormReference extends RbFormElement {
let rs = data.data.map((item) => { let rs = data.data.map((item) => {
return item return item
}) })
return { return { results: rs }
results: rs
}
} }
} }
}).on('change.select2', function(e){
let value = e.target.value
that.handleChange({ target:{ value:value } }, true)
}) })
let val = this.state.value
$setTimeout(function() { $setTimeout(function() {
select2.trigger("change") if (val) {
let option = new Option(val[1], val[0], true, true)
select2.append(option)
}
select2.trigger('change')
select2.on('change.select2', function(e){
that.handleChange({ target:{ value: e.target.value } }, true)
})
}, 100) }, 100)
} }
componentWillUnmount() { componentWillUnmount() {
@ -696,7 +713,7 @@ class RbViewModal extends React.Component {
<button className="close" type="button" onClick={()=>this.hide()}><span className="zmdi zmdi-close"></span></button> <button className="close" type="button" onClick={()=>this.hide()}><span className="zmdi zmdi-close"></span></button>
</div> </div>
<div className={'modal-body iframe rb-loading ' + (this.state.inLoad == true && 'rb-loading-active')}> <div className={'modal-body iframe rb-loading ' + (this.state.inLoad == true && 'rb-loading-active')}>
<iframe src={this.state.showAfterUrl || 'about:blank'} frameborder="0" scrolling="no"></iframe> <iframe src={this.state.showAfterUrl || 'about:blank'} frameBorder="0" scrolling="no"></iframe>
<RbSpinner /> <RbSpinner />
</div> </div>
</div> </div>

View file

@ -29,22 +29,22 @@ class RbList extends React.Component {
</th> </th>
{this.state.fields.map((item, index) =>{ {this.state.fields.map((item, index) =>{
let columnWidth = (item.width || that.__defaultColumnWidth) + 'px' let columnWidth = (item.width || that.__defaultColumnWidth) + 'px'
let styles = { width:columnWidth } let styles = { width: columnWidth }
let haveSort = item.sort || '' let sortClazz = item.sort || ''
return (<th data-field={item.field} style={styles} className="sortable unselect" onClick={this.fieldSort.bind(this,item.field)}><div style={styles}>{item.label}<i className={'zmdi ' + haveSort}></i><i className="split"></i></div></th>) return (<th key={'field-' + item.field} style={styles} className="sortable unselect" onClick={this.fieldSort.bind(this, item.field)}><div style={styles}>{item.label}<i className={'zmdi ' + sortClazz}></i><i className="split"></i></div></th>)
})} })}
<th className="column-empty"></th> <th className="column-empty"></th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{this.state.rowData.map((item, index) => { {this.state.rowData.map((item, index) => {
let lastGhost = item[lastIndex]; let lastGhost = item[lastIndex]
return (<tr className={lastGhost[3] && 'table-active'} data-id={lastGhost[0]} onClick={this.clickRow.bind(this, index, false)}> return (<tr key={'row-' + lastGhost[0]} className={lastGhost[3] ? 'table-active' : ''} onClick={this.clickRow.bind(this, index, false)}>
<td className="column-checkbox"> <td className="column-checkbox">
<div><label className="custom-control custom-control-sm custom-checkbox"><input className="custom-control-input" type="checkbox" checked={lastGhost[3]} onClick={this.clickRow.bind(this, index, true)} /><span className="custom-control-label"></span></label></div> <div><label className="custom-control custom-control-sm custom-checkbox"><input className="custom-control-input" type="checkbox" checked={lastGhost[3]} onClick={this.clickRow.bind(this, index, true)} /><span className="custom-control-label"></span></label></div>
</td> </td>
{item.map((cell, index) => { {item.map((cell, index) => {
return that.__renderCell(cell, index, lastGhost) return that.renderCell(cell, index, lastGhost)
})} })}
<td className="column-empty"></td> <td className="column-empty"></td>
</tr>) </tr>)
@ -60,6 +60,7 @@ class RbList extends React.Component {
componentDidMount() { componentDidMount() {
const scroller = $(this.refs['rblist-scroller']) const scroller = $(this.refs['rblist-scroller'])
scroller.perfectScrollbar() scroller.perfectScrollbar()
let that = this let that = this
scroller.find('th .split').draggable({ containment: '.rb-datatable-body', axis: 'x', helper: 'clone', stop: function(event, ui){ scroller.find('th .split').draggable({ containment: '.rb-datatable-body', axis: 'x', helper: 'clone', stop: function(event, ui){
let field = $(event.target).parent().parent().data('field') let field = $(event.target).parent().parent().data('field')
@ -73,7 +74,6 @@ class RbList extends React.Component {
} }
} }
that.setState({ fields: fields }, function(){ that.setState({ fields: fields }, function(){
// scroller.perfectScrollbar('update')
}) })
}}) }})
this.fetchList() this.fetchList()
@ -87,9 +87,9 @@ class RbList extends React.Component {
}) })
$('.J_delete, .J_view, .J_edit').attr('disabled', true) $('.J_delete, .J_view, .J_edit').attr('disabled', true)
let sLen = this.__selectedRows.length let len = this.__selectedRows.length
if (sLen > 0) $('.J_delete').attr('disabled', false) if (len > 0) $('.J_delete').attr('disabled', false)
if (sLen == 1) $('.J_view, .J_edit').attr('disabled', false) if (len == 1) $('.J_view, .J_edit').attr('disabled', false)
} }
fetchList(filter) { fetchList(filter) {
@ -132,7 +132,7 @@ class RbList extends React.Component {
// //
__renderCell(cellVal, index, lastGhost) { renderCell(cellVal, index, lastGhost) {
if (this.state.fields.length == index) return null if (this.state.fields.length == index) return null
if (!!!cellVal) return <td><div></div></td> if (!!!cellVal) return <td><div></div></td>
@ -162,6 +162,7 @@ class RbList extends React.Component {
return <td><div style={styles}>{cellVal}</div></td> return <td><div style={styles}>{cellVal}</div></td>
} }
} }
toggleAllRow(e) { toggleAllRow(e) {
let checked = this.state.checkedAll == false let checked = this.state.checkedAll == false
let _rowData = this.state.rowData let _rowData = this.state.rowData
@ -192,6 +193,7 @@ class RbList extends React.Component {
this.setState({ rowData: _rowData }) this.setState({ rowData: _rowData })
return false return false
} }
clickView(cellVal) { clickView(cellVal) {
renderRbViewModal(cellVal[0], cellVal[2][0]) renderRbViewModal(cellVal[0], cellVal[2][0])
return false; return false;

View file

@ -5,17 +5,18 @@ class RbViewForm extends React.Component {
this.state = { ...props } this.state = { ...props }
} }
render() { render() {
let that = this return (
return (<div className="rbview-form" ref="reviewForm"> <div className="rbview-form" ref="reviewForm">
{this.state.formComponent} {this.state.formComponent}
</div>) </div>
)
} }
componentDidMount() { componentDidMount() {
let that = this let that = this
$.get(rb.baseUrl + '/app/' + this.props.entity + '/view-modal?id=' + this.props.id, function(res){ $.get(rb.baseUrl + '/app/' + this.props.entity + '/view-model?id=' + this.props.id, function(res){
let elements = res.data.elements let elements = res.data.elements
const FORM = <div class="row">{elements.map((item) => { const FORM = <div className="row">{elements.map((item) => {
return __detectViewElement(item) return detectViewElement(item)
})}</div> })}</div>
that.setState({ formComponent: FORM }, function(){ that.setState({ formComponent: FORM }, function(){
$('.invisible').removeClass('invisible') $('.invisible').removeClass('invisible')
@ -29,8 +30,8 @@ class RbViewForm extends React.Component {
} }
} }
const __detectViewElement = function(item){ const detectViewElement = function(item){
item.onView = true item.onView = true
item.editMode = false // viewMode and editMode item.viewMode = true
return (<div className={'col-12 col-sm-' + (item.isFull ? 12 : 6)}>{__detectElement(item)}</div>) return (<div className={'col-12 col-sm-' + (item.isFull ? 12 : 6)}>{detectElement(item)}</div>)
} }

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff