소스 검색

商机界面

zhuth 7 년 전
부모
커밋
8d9fb90f95

+ 172 - 33
frontend/saas-web/app/view/core/base/BasePanel.js

@@ -6,9 +6,6 @@ Ext.define('saas.view.core.base.BasePanel', {
     viewModel: 'core-base-basepanel',
 
     cls:'core-base-basepanel',
-    //工具类
-    FormUtil: Ext.create('saas.util.FormUtil'),
-    BaseUtil: Ext.create('saas.util.BaseUtil'),
 
     //基础属性
     frame:false,
@@ -35,43 +32,37 @@ Ext.define('saas.view.core.base.BasePanel', {
 
         var me = this,
         gridConfig = me.gridConfig,
-        gridDataUrl = gridConfig.dataUrl,
-        gridIdField = gridConfig.idField,
-        gridCodeField = gridConfig.codeField,
-        gridStatusCodeField = gridConfig.statusCodeField,
-        gridColumns = Ext.Array.clone(gridConfig.columns),
-        deleteMsg = gridConfig.deleteMsg;
+        gridColumns = Ext.Array.clone(gridConfig.columns);
+
+        var gridcfg = {
+            layout: 'fit',
+            xtype: 'core-base-gridpanel',
+            padding: '8 12',
+            _columns: gridColumns.map(function(c) {
+                return Object.assign({}, c);
+            }),
+        };
+        Ext.apply(gridcfg ,me.gridConfig);
 
         Ext.apply(me, {
             dockedItems: [{
                 frame:false,
                 xtype: 'toolbar',
                 dock: 'top',
+                layout: 'column',
                 style: {
-                    // 'border-bottom': '1px solid #35baf6 !important',
                     margin: '0 0 12px 0',
                     padding: '10px 0 14px 8px',
                 },
                 items: me.searchField.concat([{
-                    // cls:'x-formpanel-btn-orange',
                     xtype: 'button',
                     text: '查询',
-                    handler: 'query'
+                    handler: function() {
+                        me.onQuery()
+                    }
                 }])
             }],
-            items: [{
-                layout: 'fit',
-                xtype: 'core-base-gridpanel',
-                padding: '8 12',
-                dataUrl: gridDataUrl,
-                idField: gridIdField,
-                codeField: gridCodeField,
-                _columns: gridColumns.map(function(c) {
-                    return Object.assign({}, c);
-                }),
-                statusCodeField : gridStatusCodeField,
-                deleteMsg: deleteMsg
-            }]
+            items: [gridcfg]
         });
         me.callParent(arguments);
     },
@@ -83,20 +74,168 @@ Ext.define('saas.view.core.base.BasePanel', {
             Ext.Array.each(searchField, function(f) {
                 var name = f.name;
                 var field = form.getForm().findField(name);
-                field.enableKeyEvents = true;
-                field.on && field.on({
-                    keydown: {
-                        fn: function(th, e, eOpts) {
-                            if(e.keyCode == 13) {
-                                form.getController().query()
+
+                if(field) {
+                    field.enableKeyEvents = true;
+                    field.on && field.on({
+                        keydown: {
+                            fn: function(th, e, eOpts) {
+                                if(e.keyCode == 13) {
+                                    form.onQuery()
+                                }
                             }
                         }
-                    }
-                });
+                    });
+                }
             });
         }
     },
 
+    onQuery: function() {
+        var me = this;
+        var grid = me.down('core-base-gridpanel');
+        
+        grid.store.loadPage(1);
+    },
+
+    /**
+     * 获得过滤条件
+     */
+    getConditions: function() {
+        var me = this;
+        var items = me.dockedItems.items[0].items.items;
+        var conditions = [];
+
+        for(let i = 0; i < items.length; i++) {
+            var item = items[i];
+            var field = item.name,
+            func = item.getCondition,
+            value = item.value,
+            condition;
+
+            if(value&&value!=''){
+                if(typeof func == 'function') {
+                    condition = {
+                        type: 'condition',
+                        value: func(value)
+                    }
+                }else {
+                    var type = item.fieldType || me.getDefaultFieldType(item),
+                    operation = item.operation || me.getDefaultFieldOperation(item),
+                    conditionValue = me.getConditionValue(item, value);
+        
+                    if(!conditionValue) {
+                        continue;
+                    }
+                    condition = {
+                        type: type,
+                        field: field,
+                        operation: operation,
+                        value: conditionValue
+                    }
+                }
+                conditions.push(condition);
+            }
+        }
+
+        return conditions;
+    },
+
+    /**
+     * 只要arr1和arr2中存在相同项即返回真
+     */
+    isContainsAny: function (arr1, arr2) {
+        for (var i = 0; i < arr2.length; i++) {
+            var a2 = arr2[i];
+            if (!!arr1.find(function (a1) {
+                    return a1 == a2
+                })) {
+                return true;
+            }
+        }
+        return false;
+    },
+
+    getDefaultFieldType: function (field) {
+        var me = this,
+            xtypes = field.getXTypes().split('/'),
+            type;
+
+        if (me.isContainsAny(xtypes, ['numberfield'])) {
+            type = 'number';
+        } else if (me.isContainsAny(xtypes, ['datefield', 'condatefield', 'conmonthfield'])) {
+            type = 'date';
+        } else if (me.isContainsAny(xtypes, ['dbfindtrigger'])) {
+            type = 'enum';
+        } else if (me.isContainsAny(xtypes, ['combobox', 'multicombo', 'combo', 'radiofield', 'radio'])) {
+            type = 'enum';
+        } else {
+            type = 'string';
+        }
+
+        return type;
+    },
+
+    getDefaultFieldOperation: function (field) {
+        var me = this,
+            xtypes = field.getXTypes().split('/'),
+            operation;
+
+        if (me.isContainsAny(xtypes, ['numberfield', 'datefield', 'dbfindtrigger'])) {
+            operation = '=';
+        } else if (me.isContainsAny(xtypes, ['condatefield', 'conmonthfield'])) {
+            operation = 'between';
+        } else if (me.isContainsAny(xtypes, ['multidbfindtrigger', 'combobox', 'multicombo', 'combo'])) {
+            operation = 'in';
+        } else {
+            operation = 'like';
+        }
+
+        return operation;
+    },
+
+    /**
+     * 处理部分字段值
+     */
+    getConditionValue: function (field, value) {
+        var me = this,
+            xtypes = field.getXTypes().split('/'),
+            conditionValue;
+        if (me.isContainsAny(xtypes, ['datefield'])) {
+            conditionValue = Ext.Date.format(new Date(from), 'Y-m-d H:i:s');
+        } else if (me.isContainsAny(xtypes, ['conmonthfield'])) {
+            var from = value.from,
+                to = value.to;
+
+            conditionValue = from + ',' + to;
+        } else if (me.isContainsAny(xtypes, ['condatefield'])) {
+            var from = value.from,
+                to = value.to;
+
+            conditionValue = Ext.Date.format(new Date(from), 'Y-m-d 00:00:00') + ',' + Ext.Date.format(new Date(to), 'Y-m-d 23:59:59');
+        } else if (me.isContainsAny(xtypes, ['dbfindtrigger'])) {
+            conditionValue = value;
+        } else if (me.isContainsAny(xtypes, ['combobox', 'combo'])) {
+            conditionValue = '\'' + value + '\'';
+        } else if (me.isContainsAny(xtypes, ['multicombo'])) {
+            conditionValue = value.map ? value.map(function (v) {
+                return '\'' + v.value + '\'';
+            }).join(',') : '';
+        } else {
+            conditionValue = value;
+        }
+
+        return conditionValue;
+    },
+
+    getExtraParams: function(store, op, condition) {
+        return {
+            number: store.exportNumber?store.exportNumber:op._page,
+            size: store.exportPageSize?store.exportPageSize:store.pageSize,
+            condition: JSON.stringify(condition)
+        };
+    },
+
     refresh: function () {
         this.items.items[0].store.load()
     },

+ 0 - 139
frontend/saas-web/app/view/core/base/BasePanelController.js

@@ -5,151 +5,12 @@ Ext.define('saas.view.core.base.BasePanelController', {
     BaseUtil: Ext.create('saas.util.BaseUtil'),
     FormUtil: Ext.create('saas.util.FormUtil'),
 
-    query: function() {
-        var form = this.view;
-        var grid = form.down('core-base-gridpanel');
-        
-        grid.condition = this.getConditions();
-        grid.store.loadPage(1);
-    },
-
     add: function(){
         var form = this.getView();
         var id = form.xtype + '_add';
         saas.util.BaseUtil.openTab(form.xtype,'新增' + form._title,id);
     },
 
-    /**
-     * 获得过滤条件
-     */
-    getConditions: function() {
-        var me = this;
-        var form = this.view;
-        var items = form.dockedItems.items[0].items.items;
-        var conditions = [];
-
-        for(let i = 0; i < items.length; i++) {
-            var item = items[i];
-            var field = item.name,
-            func = item.getCondition,
-            value = item.value,
-            condition;
-
-            if(value&&value!=''){
-                if(typeof func == 'function') {
-                    condition = {
-                        type: 'condition',
-                        value: func(value)
-                    }
-                }else {
-                    var type = item.fieldType || me.getDefaultFieldType(item),
-                    operation = item.operation || me.getDefaultFieldOperation(item),
-                    conditionValue = me.getConditionValue(item, value);
-        
-                    if(!conditionValue) {
-                        continue;
-                    }
-                    condition = {
-                        type: type,
-                        field: field,
-                        operation: operation,
-                        value: conditionValue
-                    }
-                }
-                conditions.push(condition);
-            }
-        }
-
-        return conditions;
-    },
-
-    /**
-     * 只要arr1和arr2中存在相同项即返回真
-     */
-    isContainsAny: function (arr1, arr2) {
-        for (var i = 0; i < arr2.length; i++) {
-            var a2 = arr2[i];
-            if (!!arr1.find(function (a1) {
-                    return a1 == a2
-                })) {
-                return true;
-            }
-        }
-        return false;
-    },
-
-    getDefaultFieldType: function (field) {
-        var me = this,
-            xtypes = field.getXTypes().split('/'),
-            type;
-
-        if (me.isContainsAny(xtypes, ['numberfield'])) {
-            type = 'number';
-        } else if (me.isContainsAny(xtypes, ['datefield', 'condatefield', 'conmonthfield'])) {
-            type = 'date';
-        } else if (me.isContainsAny(xtypes, ['dbfindtrigger'])) {
-            type = 'enum';
-        } else if (me.isContainsAny(xtypes, ['combobox', 'multicombo', 'combo', 'radiofield', 'radio'])) {
-            type = 'enum';
-        } else {
-            type = 'string';
-        }
-
-        return type;
-    },
-
-    getDefaultFieldOperation: function (field) {
-        var me = this,
-            xtypes = field.getXTypes().split('/'),
-            operation;
-
-        if (me.isContainsAny(xtypes, ['numberfield', 'datefield', 'dbfindtrigger'])) {
-            operation = '=';
-        } else if (me.isContainsAny(xtypes, ['condatefield', 'conmonthfield'])) {
-            operation = 'between';
-        } else if (me.isContainsAny(xtypes, ['multidbfindtrigger', 'combobox', 'multicombo', 'combo'])) {
-            operation = 'in';
-        } else {
-            operation = 'like';
-        }
-
-        return operation;
-    },
-
-    /**
-     * 处理部分字段值
-     */
-    getConditionValue: function (field, value) {
-        var me = this,
-            xtypes = field.getXTypes().split('/'),
-            conditionValue;
-        if (me.isContainsAny(xtypes, ['datefield'])) {
-            conditionValue = Ext.Date.format(new Date(from), 'Y-m-d H:i:s');
-        } else if (me.isContainsAny(xtypes, ['conmonthfield'])) {
-            var from = value.from,
-                to = value.to;
-
-            conditionValue = from + ',' + to;
-        } else if (me.isContainsAny(xtypes, ['condatefield'])) {
-            var from = value.from,
-                to = value.to;
-
-            conditionValue = Ext.Date.format(new Date(from), 'Y-m-d 00:00:00') + ',' + Ext.Date.format(new Date(to), 'Y-m-d 23:59:59');
-        } else if (me.isContainsAny(xtypes, ['dbfindtrigger'])) {
-            conditionValue = value;
-        } else if (me.isContainsAny(xtypes, ['combobox', 'combo'])) {
-            conditionValue = '\'' + value + '\'';
-        } else if (me.isContainsAny(xtypes, ['multicombo'])) {
-            conditionValue = value.map ? value.map(function (v) {
-                return '\'' + v.value + '\'';
-            }).join(',') : '';
-        } else {
-            conditionValue = value;
-        }
-
-        return conditionValue;
-    },
-
     onColSetting: function() {
         var me = this,
         panel = me.getView(),

+ 4 - 0
frontend/saas-web/app/view/core/base/BasePanelModel.js

@@ -1,4 +1,8 @@
 Ext.define('saas.view.core.base.BasePanelModel', {
     extend: 'Ext.app.ViewModel',
     alias: 'viewmodel.core-base-basepanel',
+
+    data: {
+        configurable: true
+    }
 });

+ 11 - 9
frontend/saas-web/app/view/core/base/GridPanel.js

@@ -23,6 +23,8 @@ Ext.define('saas.view.core.base.GridPanel', {
     dataUrl: '',
     dbSearchFields: [],
     condition:'',
+    rootProperty: 'data.list',
+    totalProperty: 'data.total',
 
     actionColumn: [{
         xtype:'actioncolumn',
@@ -71,8 +73,8 @@ Ext.define('saas.view.core.base.GridPanel', {
                     },
                     reader: {
                         type: 'json',
-                        rootProperty: 'data.list',
-                        totalProperty: 'data.total',
+                        rootProperty: me.rootProperty,
+                        totalProperty: me.totalProperty,
                     },
                     listeners: {
                         exception: function(proxy, response, operation, eOpts) {
@@ -89,15 +91,14 @@ Ext.define('saas.view.core.base.GridPanel', {
                 },
                 listeners: {
                     beforeload: function (store, op) {
-                        var condition = me.condition;
+                        var basePanel = me.up('core-base-basepanel');
+                        var condition = basePanel.getConditions();
                         if (Ext.isEmpty(condition)) {
                             condition = "";
                         }
-                        Ext.apply(store.proxy.extraParams, {
-                            number: store.exportNumber?store.exportNumber:op._page,
-                            size: store.exportPageSize?store.exportPageSize:store.pageSize,
-                            condition: JSON.stringify(condition)
-                        });
+
+                        var obj = basePanel.getExtraParams(store, op, condition);
+                        Ext.apply(store.proxy.extraParams, obj);
                     }
                 }
             });
@@ -106,6 +107,7 @@ Ext.define('saas.view.core.base.GridPanel', {
                 dockedItems:[{
                     xtype:'toolbar',
                     dock:'top',
+                    hidden: me.hiddenTools,
                     defaults: { // defaults 将会应用所有的子组件上,而不是父容器
                         listeners: {
                             'mouseover':function(){
@@ -187,7 +189,7 @@ Ext.define('saas.view.core.base.GridPanel', {
                         text: '列设置',
                         handler: 'onColSetting',
                         bind: {
-                            hidden: '{!isAdmin}'
+                            hidden: '{!configurable || !isAdmin}'
                         }
                     }]
                 }]

+ 2 - 0
frontend/saas-web/app/view/core/form/FormPanelModel.js

@@ -16,6 +16,8 @@ Ext.define('saas.view.core.form.FormPanelModel', {
         showAuditBtn: true, // 显示审核、反审核按钮
         detailBindeFields: [], // 从表绑定列
         detailStore: null, // 从表store
+
+        configurable: true
     },
 
     formulas:{

+ 1 - 1
frontend/saas-web/app/view/core/form/field/DetailGridField.js

@@ -138,7 +138,7 @@ Ext.define('saas.view.core.form.field.DetailGridField', {
             // text : "序号", 
             // text: '<div class="x-sa sa-setting" style="cursor: pointer;" title="列设置"></div>',
             bind: {
-                text: "{isAdmin ? ('<div class=\"x-sa sa-setting\" style=\"cursor: pointer;\" title=\"列设置\"></div>') : '序号'}"
+                text: "{(configurable && isAdmin) ? ('<div class=\"x-sa sa-setting\" style=\"cursor: pointer;\" title=\"列设置\"></div>') : '序号'}"
             },
             dataIndex : detnoField, 
             width : 60, 

+ 10 - 10
frontend/saas-web/app/view/core/query/QueryGridPanel.js

@@ -34,6 +34,10 @@ Ext.define('saas.view.core.query.QueryGridPanel', {
     columnWidth: 1.0,
     showRowNum: true,
     autoQuery: true,
+
+    rootProperty: 'data.list',
+    totalProperty: 'data.total',
+
     selModel: {
         checkOnly:true,
         type:'checkboxmodel',
@@ -85,8 +89,8 @@ Ext.define('saas.view.core.query.QueryGridPanel', {
                     },
                     reader: {
                         type: 'json',
-                        rootProperty: 'data.list',
-                        totalProperty: 'data.total',
+                        rootProperty: me.rootProperty,
+                        totalProperty: me.totalProperty,
                     },
                     listeners: {
                         exception: function(proxy, response, operation, eOpts) {
@@ -119,13 +123,9 @@ Ext.define('saas.view.core.query.QueryGridPanel', {
                                 value: defaultCondition
                             });
                         }
-                        Ext.apply(store.proxy.extraParams, {
-                            number: store.exportNumber?store.exportNumber:op._page,
-                            size: store.exportPageSize?store.exportPageSize:store.pageSize,
-                            mode:mode,
-                            condition: JSON.stringify(condition)
-                        });
-    
+
+                        var obj = queryPanel.getExtraParams(store, op, mode, condition);
+                        Ext.apply(store.proxy.extraParams, obj);
                     },
                     load: function(store, records, successful, operation, eOpts) {
                         var queryPanel = me.up('core-query-querypanel'),
@@ -260,7 +260,7 @@ Ext.define('saas.view.core.query.QueryGridPanel', {
                     text: '列设置',
                     handler: 'onColSetting',
                     bind: {
-                        hidden: '{!isAdmin}'
+                        hidden: '{!configurable || !isAdmin}'
                     }
                 }]
             }]

+ 9 - 0
frontend/saas-web/app/view/core/query/QueryPanel.js

@@ -313,6 +313,15 @@ Ext.define('saas.view.core.query.QueryPanel', {
 
         return detailModel ? 'DETAIL' : 'MAIN';
     },
+
+    getExtraParams: function(store, op, mode, condition) {
+       return {
+            number: store.exportNumber?store.exportNumber:op._page,
+            size: store.exportPageSize?store.exportPageSize:store.pageSize,
+            mode:mode,
+            condition: JSON.stringify(condition)
+        }
+    },
     
     refresh: function() {
         var me = this;

+ 3 - 1
frontend/saas-web/app/view/core/query/QueryPanelModel.js

@@ -10,6 +10,8 @@ Ext.define('saas.view.core.query.QueryPanelModel', {
         importEnable: true, // 显示导入按钮
         closeEnable: true, // 显示关闭按钮
         deleteEnable: true, // 显示删除按钮
-        deleteDisable:false //删除按钮是否可使用
+        deleteDisable:false, //删除按钮是否可使用
+
+        configurable: true, // 允许列设置
     }
 });

+ 87 - 87
frontend/saas-web/app/view/document/product/BasePanel.js

@@ -10,23 +10,23 @@ Ext.define('saas.view.document.product.BasePanel', {
     deleteMoreMsg: '删除的物料将不能恢复,请确认是否删除?',
     deleteOneMsg: '删除的物料将不能恢复,请确认是否删除?',
 
-    initComponent: function() {
+    initComponent: function () {
         Ext.apply(this, {
-            searchField:[{
-                xtype : "textfield", 
-                name : "pr_code", 
-                width:300, 
-                emptyText:'输入物料编号、名称、型号或品牌',
+            searchField: [{
+                xtype: "textfield",
+                name: "pr_code",
+                width: 300,
+                emptyText: '输入物料编号、名称、型号或品牌',
                 getCondition: function (v) {
                     return "(upper(CONCAT(pr_code,'#',pr_detail,'#',ifnull(pr_orispeccode,''),'#',ifnull(pr_brand,''))) like '%" + v.toUpperCase() + "%' )";
                 },
-            },{
-                editable:true,
-                hiddenBtn:true,
-                xtype : "remotecombo", 
+            }, {
+                editable: true,
+                hiddenBtn: true,
+                xtype: "remotecombo",
                 storeUrl: '/api/document/producttype/getCombo',
-                name : "pr_kind", 
-                fieldLabel : '物料类型',
+                name: "pr_kind",
+                fieldLabel: '物料类型',
                 emptyText: '全部',
             }, {
                 xtype: 'combobox',
@@ -34,123 +34,123 @@ Ext.define('saas.view.document.product.BasePanel', {
                 queryMode: 'local',
                 displayField: 'pr_status',
                 valueField: 'pr_statuscode',
-                fieldLabel : '状态',
+                fieldLabel: '状态',
                 emptyText: '全部',
-                editable:false,
-                defaultValue:'ENABLE',
+                editable: false,
+                defaultValue: 'ENABLE',
                 store: Ext.create('Ext.data.ArrayStore', {
-                fields: ['pr_statuscode', 'pr_status'],
-                data: [
-                    ["ALL", "全部"],
-                    ["ENABLE", "已启用"],
-                    ["BANNED", "已禁用"]
-                ]
+                    fields: ['pr_statuscode', 'pr_status'],
+                    data: [
+                        ["ALL", "全部"],
+                        ["ENABLE", "已启用"],
+                        ["BANNED", "已禁用"]
+                    ]
                 }),
-                getCondition: function(value) {
-                    if(value == 'ALL' || !value) {
+                getCondition: function (value) {
+                    if (value == 'ALL' || !value) {
                         return '1=1';
-                    }else {
+                    } else {
                         return 'pr_statuscode=\'' + value + '\'';
                     }
                 }
             }],
-        
+
             //字段属性
-            caller:'Product',
-            _formXtype:'document-product-formpanel',
-            _title:'物料资料',
-            _deleteUrl:'/api/document/product/delete',
-            _batchOpenUrl:'/api/document/product/batchOpen',
-            _batchCloseUrl:'/api/document/product/batchClose',
-            _batchDeleteUrl:'/api/document/product/batchDelete',
-        
+            caller: 'Product',
+            _formXtype: 'document-product-formpanel',
+            _title: '物料资料',
+            _deleteUrl: '/api/document/product/delete',
+            _batchOpenUrl: '/api/document/product/batchOpen',
+            _batchCloseUrl: '/api/document/product/batchClose',
+            _batchDeleteUrl: '/api/document/product/batchDelete',
+
             gridConfig: {
                 idField: 'id',
                 codeField: 'pr_code',
-                statusCodeField:'pr_statuscode',
+                statusCodeField: 'pr_statuscode',
                 dataUrl: '/api/document/product/list',
                 caller: 'Product',
-                columns : [{
-                    text : "id", 
-                    width : 0, 
-                    dataIndex : "id", 
-                    xtype : "numbercolumn", 
-                },{
-                    text : "物料编号", 
-                    dataIndex : "pr_code", 
-                    width : 150.0
-                },{
-                    text : "品牌", 
-                    dataIndex : "pr_brand", 
-                    width : 100.0
+                columns: [{
+                    text: "id",
+                    width: 0,
+                    dataIndex: "id",
+                    xtype: "numbercolumn",
                 }, {
-                    text : "物料名称", 
-                    dataIndex : "pr_detail", 
-                    width : 150.0
+                    text: "物料编号",
+                    dataIndex: "pr_code",
+                    width: 150.0
                 }, {
-                    text : "型号", 
-                    dataIndex : "pr_orispeccode", 
-                    width : 200.0
+                    text: "品牌",
+                    dataIndex: "pr_brand",
+                    width: 100.0
                 }, {
-                    text : "规格", 
-                    dataIndex : "pr_spec", 
-                    width : 200.0
+                    text: "物料名称",
+                    dataIndex: "pr_detail",
+                    width: 150.0
                 }, {
-                    text : "物料类型", 
-                    dataIndex : "pr_kind", 
-                    width:100
+                    text: "型",
+                    dataIndex: "pr_orispeccode",
+                    width: 200.0
                 }, {
-                    text : "库存", 
-                    dataIndex : "po_onhand",
+                    text: "规格",
+                    dataIndex: "pr_spec",
+                    width: 200.0
+                }, {
+                    text: "物料类型",
+                    dataIndex: "pr_kind",
+                    width: 100
+                }, {
+                    text: "库存",
+                    dataIndex: "po_onhand",
                     xtype: 'numbercolumn',
-                    width : 100.0,
-                    renderer : function(v, m, r) {
+                    width: 100.0,
+                    renderer: function (v, m, r) {
                         return saas.util.BaseUtil.numberFormat(v, 3, false);
                     }
                 }, {
-                    text : "单位", 
-                    dataIndex : "pr_unit", 
-                    width : 65.0 
+                    text: "单位",
+                    dataIndex: "pr_unit",
+                    width: 65.0
                 }, {
-                    text : "标准定价(元)", 
-                    dataIndex : "pr_standardprice",
+                    text: "标准定价(元)",
+                    dataIndex: "pr_standardprice",
                     xtype: 'numbercolumn',
-                    width : 110.0,
-                    renderer : function(v, m, r) {
+                    width: 110.0,
+                    renderer: function (v, m, r) {
                         return saas.util.BaseUtil.numberFormat(v, 4, true);
                     }
-                },  {
-                    text : "最新购价(元)", 
-                    dataIndex : "pr_purcprice",
+                }, {
+                    text: "最新购价(元)",
+                    dataIndex: "pr_purcprice",
                     xtype: 'numbercolumn',
-                    width : 110.0,
-                    renderer : function(v, m, r) {
+                    width: 110.0,
+                    renderer: function (v, m, r) {
                         return saas.util.BaseUtil.numberFormat(v, 4, true);
                     }
                 }, {
-                    text : "最新售价(元)", 
-                    dataIndex : "pr_saleprice",
+                    text: "最新售价(元)",
+                    dataIndex: "pr_saleprice",
                     xtype: 'numbercolumn',
-                    width : 110.0,
-                    renderer : function(v, m, r) {
+                    width: 110.0,
+                    renderer: function (v, m, r) {
                         return saas.util.BaseUtil.numberFormat(v, 4, true);
                     }
                 }, {
-                    text : "备注", 
-                    dataIndex : "pr_text1",
-                    width :250.0
+                    text: "备注",
+                    dataIndex: "pr_text1",
+                    width: 250.0
                 }, {
-                    text : "状态", 
-                    dataIndex : "pr_status",
-                    align:'center',
-                    width : 80.0
+                    text: "状态",
+                    dataIndex: "pr_status",
+                    align: 'center',
+                    width: 80.0
                 }]
             },
         });
         this.callParent(arguments);
     },
 
-    refresh:function(){
+    refresh: function () {
         this.items.items[0].store.load()
     }
 

+ 217 - 0
frontend/saas-web/app/view/sale/business/Business.js

@@ -0,0 +1,217 @@
+/**
+ * 商机-公司商机
+ */
+Ext.define('saas.view.sale.business.Business', {
+    extend: 'saas.view.core.base.BasePanel',
+    xtype: 'sale-business-business',
+
+    controller: 'sale-business-business',
+    viewModel: 'sale-business-business',
+    viewName: 'sale-business-business',
+
+
+    // dataUrl: 'http://10.1.80.23:8560/api/sale/sale/enterprise/businessChance',
+    dataUrl: '/api/sale/sale/enterprise/businessChance',
+    initComponent: function() {
+        var me = this;
+        Ext.apply(this, {
+            searchField: [{
+                xtype: 'textfield',
+                name: 'keyword',
+                columnWidth: 0.15,
+                emptyText:'请输入物料编号/名称/型号/品牌'
+            }, {
+                xtype: 'condatefield',
+                name: 'date',
+                fieldLabel: '日期',
+                labelWidth: 50,
+                columnWidth: 0.4,
+            }, {
+                xtype: 'combobox',
+                name: 'quoted',
+                fieldLabel: '报价状态',
+                queryMode: 'local',
+                displayField: 'name',
+                valueField: 'value',
+                emptyText :'全部',
+                editable:false,
+                labelWidth: 80,
+                columnWidth: 0.2,
+                store: Ext.create('Ext.data.ArrayStore', {
+                    fields: ['name', 'value'],
+                    data: [
+                        ["全部", "all"],
+                        ["未报价", "0"],
+                        ["已报价", "1"]
+                    ]
+                })
+            // }, {
+            //     xtype: 'combobox',
+            //     name: 'closed',
+            //     fieldLabel: '截止状态',
+            //     queryMode: 'local',
+            //     displayField: 'name',
+            //     valueField: 'value',
+            //     emptyText :'全部',
+            //     editable:false,
+            //     columnWidth: 0.2,
+            //     store: Ext.create('Ext.data.ArrayStore', {
+            //         fields: ['name', 'value'],
+            //         data: [
+            //             ["全部", "all"],
+            //             ["未截止", "0"],
+            //             ["已截止", "1"]
+            //         ]
+            //     })
+            }],
+        
+            caller: null,
+            _formXtype: null,
+            _title: null,
+            _deleteUrl: null,
+            _batchOpenUrl: null,
+            _batchCloseUrl: null,
+            _batchDeleteUrl: null,
+        
+            gridConfig: {
+                idField: null,
+                codeField: null,
+                statusCodeField: null,
+                dataUrl: me.dataUrl,
+                caller: null,
+                rootProperty: 'data.content',
+                totalProperty: 'data.totalElements',
+                actionColumn: [],
+                selModel: {
+                    type: 'cellmodel'
+                },
+                hiddenTools: true,
+                data: [{
+
+                }],
+                columns : [{
+                    text: '客户名称',
+                    dataIndex: 'custName',
+                    width: 200
+                }, {
+                    text: '物料品牌',
+                    dataIndex: 'prodBrand',
+                    width: 100
+                }, {
+                    text: '物料名称',
+                    dataIndex: 'prodName',
+                    width: 120
+                }, {
+                    text: '物料型号',
+                    dataIndex: 'prodOrispeccode',
+                    width: 120
+                }, {
+                    text: '物料规格',
+                    dataIndex: 'prodSpec',
+                    width: 120
+                }, {
+                    text: '物料单位',
+                    dataIndex: 'prodUnit'
+                }, {
+                    text: '采购数量',
+                    xtype: 'numbercolumn',
+                    dataIndex: 'needQty',
+                    renderer: function (v, m, r) {
+                        return saas.util.BaseUtil.numberFormat(v, 0, false);
+                    }
+                }, {
+                    text: '发布时间',
+                    xtype: 'datecolumn',
+                    dataIndex: 'startDate',
+                    format: 'Y-m-d H:i:s'
+                }, {
+                    text: '截止时间',
+                    xtype: 'datecolumn',
+                    dataIndex: 'endDate'
+                }, {
+                    text: '操作',
+                    dataIndex: 'quoted',
+                    renderer: function(v, m) {
+                        return v == 1 ? '<a style="color: green; cursor: pointer;">报价中</a>' : '<a style="color: #35BAF6; cursor: pointer;">报价</a>';
+                    },
+                    listeners: {
+                        click: function(tableView, td, rowIdx, colIdx, e, model, tr) {
+                            var dataIndex = this.dataIndex;
+                            var record = tableView.store.getAt(rowIdx);
+                            var value = record.get(dataIndex);
+                            
+                            if(value == '0') {
+                                me.getController().showQuoteWin(record);
+                            }
+                        }
+                    }
+                }]
+            },
+        });
+        this.callParent(arguments);
+    },
+
+    /**
+     * 处理部分字段值
+     */
+    getConditionValue: function (field, value) {
+        var me = this,
+            xtypes = field.getXTypes().split('/'),
+            conditionValue;
+        if (me.isContainsAny(xtypes, ['datefield'])) {
+            conditionValue = Ext.Date.format(new Date(from), 'Y-m-d H:i:s');
+        } else if (me.isContainsAny(xtypes, ['conmonthfield'])) {
+            var from = value.from,
+                to = value.to;
+
+            conditionValue = from + ',' + to;
+        } else if (me.isContainsAny(xtypes, ['condatefield'])) {
+            var from = value.from,
+                to = value.to;
+
+            conditionValue = Ext.Date.format(new Date(from), 'Y-m-d 00:00:00') + ',' + Ext.Date.format(new Date(to), 'Y-m-d 23:59:59');
+        } else if (me.isContainsAny(xtypes, ['dbfindtrigger'])) {
+            conditionValue = value;
+        } else if (me.isContainsAny(xtypes, ['combobox', 'combo'])) {
+            conditionValue = value;
+        } else if (me.isContainsAny(xtypes, ['multicombo'])) {
+            conditionValue = value.map ? value.map(function (v) {
+                return v.value;
+            }).join(',') : '';
+        } else {
+            conditionValue = value;
+        }
+
+        return conditionValue;
+    },
+
+    getExtraParams: function(store, op, condition) {
+        var temp = {};
+
+        for(let x = 0; x < condition.length; x++) {
+            let c = condition[x];
+            if(c.field == 'keyword') {
+                temp.keyword = c.value;
+            }else if(c.field == 'date') {
+                temp.fromDate = new Date(c.value.split(',')[0]).getTime();
+                temp.endDate = new Date(c.value.split(',')[1]).getTime();
+            }else if(c.field == 'quoted') {
+                temp.quoted = c.value == 'all' ? null : c.value;
+            }else if(c.field == 'closed') {
+                // temp.endDate = c.value == 'all' ? null : (
+                //     c.value == '0' ? 
+                // );
+            }
+        }
+        let obj = {
+            pageNumber: store.exportNumber?store.exportNumber:op._page,
+            pageSize: store.exportPageSize?store.exportPageSize:store.pageSize
+        };
+        for(let k in temp) {
+            if(!!temp[k]) {
+                obj[k] = temp[k];
+            }
+        }
+        return obj;
+     },
+});

+ 19 - 0
frontend/saas-web/app/view/sale/business/BusinessController.js

@@ -0,0 +1,19 @@
+Ext.define('saas.view.sale.business.BusinessController', {
+    extend: 'saas.view.core.base.BasePanelController',
+    alias: 'controller.sale-business-business',
+
+    showQuoteWin: function(record) {
+        var me = this,
+        view = me.getView();
+
+        var win = Ext.getCmp();
+        if(!win) {
+            win = Ext.create('saas.view.sale.business.QuoteWin', {
+                record: record,
+                listView: view
+            });
+            view.add(win);
+        }
+        win.show();
+    },
+});

+ 8 - 0
frontend/saas-web/app/view/sale/business/BusinessModel.js

@@ -0,0 +1,8 @@
+Ext.define('saas.view.sale.business.BusinessModel', {
+    extend: 'saas.view.core.base.BasePanelModel',
+    alias: 'viewmodel.sale-business-business',
+
+    data: {
+        configurable: false
+    }
+});

+ 12 - 0
frontend/saas-web/app/view/sale/business/MyBusiness.js

@@ -0,0 +1,12 @@
+/**
+ * 商机-我的商机
+ */
+Ext.define('saas.view.sale.business.MyBusiness', {
+    extend: 'saas.view.sale.business.Business',
+    xtype: 'sale-business-mybusiness',
+
+    viewName: 'sale-business-mybusiness',
+
+    // dataUrl: 'http://10.1.80.23:8560/api/sale/sale/personal/businessChance',
+    dataUrl: '/api/sale/sale/personal/businessChance',
+});

+ 206 - 0
frontend/saas-web/app/view/sale/business/QuoteWin.js

@@ -0,0 +1,206 @@
+Ext.define('saas.view.sale.business.QuoteWin', {
+    extend: 'Ext.window.Window',
+    xtype: 'quotewin',
+
+    title: '报价信息',
+    width: 600,
+    cls: 'x-window-dbfind',
+    closlayout: 'fit',
+    modal: true,
+    bodyPadding: 20,
+
+    initComponent: function () {
+        var me = this;
+        var record = me.record;
+        Ext.apply(me, {
+            items: [{
+                xtype: 'form',
+                layout: 'column',
+                fieldDefaults: {
+                    margin: '0 0 10 0',
+                    labelAlign: 'right',
+                    labelWidth: 90,
+                    columnWidth: 0.5,
+                },
+                isValid: function (values) {
+                    var leadtimeField = this.getForm().findField('leadtime');
+                    var taxrateField = this.getForm().findField('taxrate');
+                    var grid = this.down('grid');
+                    var gridData = grid.store.getData().items;
+                    var flag = gridData.length > 0;
+
+                    for (var x = 0; x < gridData.length; x++) {
+                        var d = gridData[x];
+                        if (!d.get('step') || !d.get('price')) {
+                            flag = false
+                        }
+                    }
+
+                    if(flag) {
+                        flag = leadtimeField.getValue() && taxrateField.getValue();
+                    }
+                    return flag;
+                },
+                items: [{
+                    xtype: 'textfield',
+                    fieldLabel: '品牌',
+                    name: 'prodBrand',
+                    readOnly: true,
+                    value: record.get('prodBrand')
+                }, {
+                    xtype: 'textfield',
+                    fieldLabel: '名称',
+                    name: 'prodName',
+                    readOnly: true,
+                    value: record.get('prodName')
+                }, {
+                    xtype: 'textfield',
+                    fieldLabel: '型号',
+                    name: 'prodOrispeccode',
+                    readOnly: true,
+                    value: record.get('prodOrispeccode')
+                }, {
+                    xtype: 'textfield',
+                    fieldLabel: '规格',
+                    name: 'prodSpec',
+                    readOnly: true,
+                    value: record.get('prodSpec')
+                }, {
+                    xtype: 'numberfield',
+                    fieldLabel: '交期(天)',
+                    name: 'leadtime',
+                    allowBlank: false,
+                    beforeLabelTextTpl: "<font color=\"red\" style=\"position:relative; top:2px;right:2px; font-weight: bolder;\">*</font>"
+                }, {
+                    xtype: 'numberfield',
+                    fieldLabel: '税率',
+                    name: 'taxrate',
+                    minValue: 0,
+                    maxValue: 100,
+                    allowBlank: false,
+                    beforeLabelTextTpl: "<font color=\"red\" style=\"position:relative; top:2px;right:2px; font-weight: bolder;\">*</font>"
+                }, {
+                    xtype: 'detailGridField',
+                    detnoColumn: 'no',
+                    minHeight: 145,
+                    emptyRows: 3,
+                    showCount: false,
+                    width: 280,
+                    store: Ext.create('Ext.data.Store', {
+                        fields: [{
+                            name: 'no',
+                            type: 'int'
+                        }, {
+                            name: 'step',
+                            type: 'int'
+                        }, {
+                            name: 'price',
+                            type: 'float'
+                        }],
+                        data: []
+                    }),
+                    columns: [{
+                        text: '梯度',
+                        dataIndex: 'step',
+                        xtype: 'numbercolumn',
+                        editor: {
+                            xtype: "numberfield",
+                            decimalPrecision: 0,
+                            minValue: 0
+                        },
+                        renderer: function (v, m, r) {
+                            return saas.util.BaseUtil.numberFormat(v, 0, false);
+                        },
+                    }, {
+                        text: '单价',
+                        dataIndex: 'price',
+                        xtype: 'numbercolumn',
+                        editor: {
+                            xtype: "numberfield",
+                            decimalPrecision: 4,
+                            minValue: 0
+                        },
+                        renderer: function (v, m, r) {
+                            return saas.util.BaseUtil.numberFormat(v, 4, true);
+                        },
+                    }]
+                }]
+            }],
+            buttonAlign: 'center',
+            buttons: [{
+                text: '确定',
+                handler: function () {
+                    var win = this.up('window'),
+                        form = win.down('form')
+                        grid = form.down('grid');
+
+                    if (form.isValid()) {
+                        var values = form.getValues();
+                        Ext.Object.mergeIf(values, record.data);
+                        values.detail = grid.store.getData().items.map(function(r) {
+                            return r.data;
+                        })
+                        me.onQuote(values);
+                    } else {
+                        saas.util.BaseUtil.showErrorToast('表单校验失败,请检查字段是否合法');
+                    }
+                }
+            }, {
+                text: '取消',
+                handler: function () {
+
+                }
+            }]
+        });
+        me.callParent(arguments);
+    },
+
+    onQuote: function (values) {
+        var view = this;
+        var params = {
+            sourceId: values.sourceId,
+            inquiry: {
+                id: values.inquiryId,
+                enUU: values.enUU,
+                recorderUU: values.recorderUU,
+                code: values.inquiryCode,
+            },
+            userUU: values.userUU,
+            userName: values.userName,
+            userTel: values.userTel,
+            currency: "RMB",
+            taxrate: values.taxrate,
+            leadtime: values.leadtime, // 交期
+            replies: values.detail.map(function(d) {
+                return {
+                    lapQty: d.step,
+                    price: d.price
+                }
+            }), // 梯度价格,
+            date: Ext.Date.format(new Date(), 'Y-m-d H:i:s'), // 当前日期
+            qutoApp: "sp", // 固定标识
+            endDate: values.endDate,
+            prodTitle: values.prodName,
+            spec: values.prodSpec,
+            cmpCode: values.prodOrispeccode,
+            inbrand: values.prodBrand,
+            isReplace: 0,
+        };
+
+        view.setLoading(true);
+        saas.util.BaseUtil.request({
+            // url: 'http://10.1.80.23:8560/api/sale/sale/businessChance/saveQuote',
+            url: '/api/sale/sale/businessChance/saveQuote',
+            params: JSON.stringify(params),
+            method: 'POST'
+        }).then(function (res) {
+            view.setLoading(false);
+            saas.util.BaseUtil.showSuccessToast('报价成功');
+            view.close();
+            view.listView.refresh();
+        }).catch(function (e) {
+            view.setLoading(false);
+            saas.util.BaseUtil.showErrorToast('报价失败: ' + e.message);
+        });
+    },
+});

+ 3 - 0
frontend/saas-web/overrides/form/field/Number.js

@@ -1,6 +1,9 @@
 Ext.define("saas.override.form.field.Number", {
     override: "Ext.form.field.Number",
     
+
+    hideTrigger: true, // 隐藏trigger
+    mouseWheelEnabled: false, // 取消滚轮事件
     /**
     * @cfg {Boolean} thousandSeparator
     */

+ 9 - 1
frontend/saas-web/resources/json/navigation.json

@@ -55,6 +55,14 @@
             "text": "销售退货单",
             "addType": "sale-salein-formpanel",
             "viewType": "sale-salein-querypanel"
+        }, {
+            "id": "sale-business-business",
+            "text": "公司商机",
+            "viewType": "sale-business-business"
+        }, {
+            "id": "sale-business-mybusiness",
+            "text": "我的商机",
+            "viewType": "sale-business-mybusiness"
         }]
     }, {
         "text": "报表",
@@ -287,7 +295,7 @@
             "leaf": true
         }]
     }]
-},{
+}, {
     "text": "设置",
     "iconCls": "x-sa sa-setting",
     "items": [{