Explorar el Código

表单提交已完成

luoyifan hace 3 años
padre
commit
5854c73b7e

+ 1 - 0
src/Defaults.ts

@@ -76,6 +76,7 @@ export const search = {
 export const text = {
     labelAlign: 'right',
     labelWidth: 70,
+    msgTarget: 'side',
 }
 
 export const toolbar = {

+ 28 - 0
src/Scope.ts

@@ -1,6 +1,7 @@
 import _ from 'lodash'
 import {invokeMethod} from "./utils"
 import {windows} from './Defaults'
+import {lookupScope} from "./lib/lib";
 
 export class Scope {
 
@@ -56,6 +57,10 @@ export class Scope {
         })
     }
 
+    get isScope() {
+        return true;
+    }
+
     /**
      * 产生一个当前模块有效的唯一id
      * @param key 唯一编号
@@ -65,6 +70,29 @@ export class Scope {
     }
 
     /**
+     * 对话框"保存"成功.
+     * 关闭对话框,并响应 success 方法
+     */
+    dialogSuccess(data) {
+        this._handle.fireEvent('success', this, data)
+        const sender = this._handle.config.animateTarget
+        if (typeof this['success'] === 'function') {
+            this['success'].call(sender, sender, data)
+        }
+        this.close()
+    }
+
+    /**
+     * 设置等待状态
+     * @param value
+     * @param msg
+     */
+    setLoading(value: boolean) {
+        const scope = this
+        scope._handle.setLoading(value)
+    }
+
+    /**
      * 以对话框模式打开当前模块
      * @param sender 发送者(按钮或Scope对象)
      * @param vjsonOption 界面覆盖选项(可以为空)

+ 10 - 3
src/controls/input/combo.js

@@ -76,7 +76,14 @@ export default function () {
 
         initComponent() {
             const that = this
-            const toggle = (e) => {
+            const toggle = function (e) {
+                // @ts-ignore
+                const config = this.config
+                const {readOnly, disabled} = config
+                if (readOnly || disabled) {
+                    return
+                }
+
                 if ($(e.target).is('.x-form-trigger')) {
                     return
                 }
@@ -98,10 +105,10 @@ export default function () {
                         dataSourceReload(this)
                     }
 
-                    $(this.el.dom).on('click', toggle)
+                    $(this.el.dom).on('click', toggle.bind(this))
                 },
                 destory() {
-                    $(this.el.dom).off('click', toggle)
+                    $(this.el.dom).off('click', toggle.bind(this))
                 },
                 // focus: {
                 //     // 获得焦点后自动下拉

+ 10 - 3
src/controls/input/datefield.js

@@ -39,7 +39,14 @@ export default function () {
 
         initComponent() {
             const that = this
-            const toggle = (e) => {
+            const toggle = function (e) {
+                // @ts-ignore
+                const config = this.config
+                const {readOnly, disabled} = config
+                if (readOnly || disabled) {
+                    return
+                }
+
                 if ($(e.target).is('.x-form-trigger')) {
                     return
                 }
@@ -54,10 +61,10 @@ export default function () {
             this.on({
                 afterrender() {
                     const {config} = this
-                    $(this.el.dom).on('click', toggle)
+                    $(this.el.dom).on('click', toggle.bind(this))
                 },
                 destory() {
-                    $(this.el.dom).off('click', toggle)
+                    $(this.el.dom).off('click', toggle.bind(this))
                 },
                 // focus: {
                 //     // 获得焦点后自动下拉

+ 18 - 4
src/controls/input/textfield.js

@@ -1,7 +1,18 @@
 import _ from 'lodash'
 import {baseConfig} from "../base";
 import {text} from "../../Defaults";
-import {PropertyDescriptionTable, YvBase, fieldLabel, value, disabled, gravity, tooltip, metaId, width, height} from "../../PropertyDescriptionTable";
+import {
+    PropertyDescriptionTable,
+    YvBase,
+    fieldLabel,
+    value,
+    disabled,
+    gravity,
+    tooltip,
+    metaId,
+    width,
+    height
+} from "../../PropertyDescriptionTable";
 import {PropertyDescription} from "../../PropertyDescription";
 
 export default function () {
@@ -40,7 +51,10 @@ export default function () {
              * 改变必填项之前加星号
              */
             if (this.allowBlank === false || this.validateBlank === true) {
-                this.beforeLabelTextTpl = [
+                // this.beforeLabelTextTpl = [
+                //     '<span style="color:red;font-weight:bold" data-qtip="必填选项">*</span>'
+                // ];
+                this.afterLabelTextTpl = [
                     '<span style="color:red;font-weight:bold" data-qtip="必填选项">*</span>'
                 ];
             }
@@ -48,8 +62,8 @@ export default function () {
             const me = this
             this.on({
                 change(sender, newVal) {
-                    const {hideTrigger, disabled, readonly} = sender
-                    if (hideTrigger || disabled || readonly) {
+                    const {hideTrigger, disabled, readOnly} = sender
+                    if (hideTrigger || disabled || readOnly) {
                         // 禁用、隐藏、只读状态下,不需要显示清空按钮
                         return
                     }

+ 2 - 0
src/init.ts

@@ -55,6 +55,8 @@ export function init() {
         loadingText: "读取中..."
     });
 
+    Ext.LoadMask.prototype.msg = '请稍后...'
+
     Ext.define("Ext.locale.zh_CN.grid.header.Container", {
         override: "Ext.grid.header.Container",
         sortAscText: "正序",

+ 26 - 3
src/lib/lib.ts

@@ -34,22 +34,45 @@ export function lookupFn(scope: Scope, event: string): Function {
     if (window["IS_DESIGN_MODE"]) {
         return Ext.emptyFn
     }
+
+    if (!_.startsWith(event, 'scope.') &&
+        !_.startsWith(event, 'system.') &&
+        !_.startsWith(event, 'format.')) {
+        console.error('无法识别的事件响应类型', event)
+        throw new TypeError('无法识别的事件响应类型')
+    }
+
     // 为 eval 准备环境
     const {system, format} = window['yvanLib']
-    const func: Function = eval(event)
+    const data = scope.viewModel.data
 
-    if (typeof func !== 'function') {
+    const keys: any[] = []
+    const values: any[] = []
+    _.forOwn(data, (value, key) => {
+        keys.push(key)
+        values.push(value)
+    })
+
+    const func: Function = //eval(event)
+        Function('scope', 'system', 'format', ...keys, 'return ' + event)
+
+    const funcResult = func(scope, system, format, ...values)
+
+    if (typeof funcResult !== 'function') {
         console.error('无法识别的事件响应类型', event, func)
         throw new TypeError('无法识别的事件响应类型')
     }
 
-    return func
+    return funcResult
 }
 
 /**
  * 从 ext.element 获取 scope 对象
  */
 export function lookupScope(extHandle: any): Scope {
+    if (extHandle.isScope) {
+        return extHandle
+    }
     const vm = extHandle.lookupViewModel()
     return vm.yvanScope
 }

+ 86 - 11
src/lib/systemLib.ts

@@ -1,6 +1,8 @@
 import _ from 'lodash'
 import {Lib, lookupScope} from './lib'
 import {ajax} from "./config";
+import {Model} from 'src/types';
+import {msg, showErrorDialog} from "../message";
 
 export const SIMPLE_RE = /^(?:\{(?:(\d+)|([a-z_][\w\.]*))\})$/i
 
@@ -396,6 +398,72 @@ export function toPlainObject(obj) {
 class SystemEventFu {
 
     @Lib({
+        title: '提交表单',
+        author: '罗一帆',
+        createAt: '2021-07-02',
+        updateAt: '2021-07-02',
+        type: 'system',
+        category: '表单',
+        args: [
+            {
+                type: 'string',
+                title: 'groovy 服务路径',
+                name: 'groovyUrl',
+            },
+            {
+                type: 'object',
+                title: '参数的 lookup 表达式, 如果不填 默认提交所有的 viewModel.data',
+                name: 'arg0',
+                allowEmpty: true,
+            }
+        ]
+    })
+    formCommit(groovyUrl: string, arg0: any) {
+        return function (sender) {
+            const scope = lookupScope(sender)
+            const valid = scope.down('form').isValid()
+            if (!valid) {
+                return
+            }
+
+            scope.setLoading(true)
+
+            let data = scope.viewModel.data
+            if (arg0) {
+                data = calcObjectFlat(data, arg0)
+            }
+
+            invokeServer(groovyUrl, data).then(res => {
+                if (res.success) {
+                    scope.dialogSuccess(res)
+                } else {
+                    showErrorDialog(res.msg || '未知错误', sender)
+                }
+
+            }).catch((e) => {
+                const msg = e.response?.data?.msg
+                showErrorDialog(msg || e.toString(), sender)
+
+            }).finally(() => {
+                scope.setLoading(false)
+            })
+        }
+    }
+
+    @Lib({
+        title: '对话框成功回调',
+        author: '罗一帆',
+        createAt: '2021-07-02',
+        updateAt: '2021-07-02',
+        type: 'system',
+        category: '对话框',
+        args: []
+    })
+    dialogSuccess() {
+        debugger
+    }
+
+    @Lib({
         title: '清空 viewModel 某个属性',
         author: '罗一帆',
         createAt: '2021-07-02',
@@ -494,23 +562,30 @@ class SystemEventFu {
             },
             {
                 type: 'object',
-                title: '参数数据',
-                name: 'dataParam',
+                title: '参数数据 lookup 表达式',
+                name: 'lookupForData',
+                allowEmpty: true,
+            },
+            {
+                type: 'event',
+                title: '成功回调',
+                name: 'successCallback',
                 allowEmpty: true,
             }
         ]
     })
-    showDialog(url: string, dataParam: any) {
+    showDialog(url: string, lookupForData: any, successCallback) {
         return function (sender) {
             const scope = lookupScope(sender)
-
-            calcObject(scope.viewModel, dataParam).then((param) => {
-                // @ts-ignore
-                require([url], (module) => {
-                    const ScopeClass = module.default
-                    const scope = new ScopeClass()
-                    scope.showDialog(sender, {}, {data: param})
-                })
+            const data = scope.viewModel.data
+
+            const param = calcObjectFlat(data, lookupForData)
+            // @ts-ignore
+            require([url], (module) => {
+                const ScopeClass = module.default
+                const scope = new ScopeClass()
+                scope.success = successCallback
+                scope.showDialog(sender, {}, {data: param})
             })
         }
     }

+ 16 - 0
src/message.ts

@@ -2,6 +2,22 @@ import $ from 'jquery'
 import _ from 'lodash'
 
 /**
+ * 显示错误异常信息
+ * @param msg 错误内容
+ * @param sender 发送者按钮(可以为空)
+ */
+export function showErrorDialog(msg, sender?) {
+    Ext.MessageBox.show({
+        title: '错误',
+        msg: msg,
+        buttons: Ext.MessageBox.OK,
+        animateTarget: sender,
+        icon: 'error',
+        cls: 'show-icon-messagebox',
+    });
+}
+
+/**
  * 中间灰底白字提示
  */
 export function msg(message: string): void {

+ 6 - 0
src/types.ts

@@ -6,6 +6,12 @@ export interface VJson {
     [propName: string]: any;
 }
 
+export interface Model {
+    success: boolean
+    msg: string
+    data: any
+}
+
 /**
  * 处理 VJson 的
  * @param this 是指 scope 对象

+ 53 - 0
src/wotu-ui.css

@@ -301,4 +301,57 @@
 
 .webix_dataview_item[role='option'] {
     padding: 2px 2px;
+}
+
+/*== extjs 提示框==*/
+.x-message-box .x-window-body {
+    background-color: #fff;
+    border-width: 0
+}
+
+.x-message-box-info,.x-message-box-warning,.x-message-box-question,.x-message-box-error {
+    background-position: left top;
+    background-repeat: no-repeat
+}
+
+.x-message-box-icon {
+    height: 44px;
+    width: 44px;
+    margin-right: 10px
+}
+
+.x-message-box-info {
+    font: 44px/1 'Font Awesome 5 Free';
+    color: grey
+}
+
+.x-message-box-info:before {
+    content: '\f05a'
+}
+
+.x-message-box-warning {
+    font: 44px/1 'Font Awesome 5 Free';
+    color: #f8d400
+}
+
+.x-message-box-warning:before {
+    content: '\f071'
+}
+
+.x-message-box-question {
+    font: 44px/1 'Font Awesome 5 Free';
+    color: grey
+}
+
+.x-message-box-question:before {
+    content: '\f059'
+}
+
+.x-message-box-error {
+    font: 44px/1 'Font Awesome 5 Free';
+    color: #ee611f
+}
+
+.x-message-box-error:before {
+    content: '\f057'
 }