Browse Source

附件组件/服务端逻辑调整

zhuth 5 years ago
parent
commit
51b3f96185

+ 2 - 0
.gitignore

@@ -4,4 +4,6 @@ classic.json*
 modern.json*
 .sencha
 *.log
+.vscode/*
+/server/node_modules
 

+ 2 - 1
app.json

@@ -19,7 +19,8 @@
         "font-awesome",
         "ux",
         "modern-locale",
-        "exporter"
+        "exporter",
+        "font-uas"
     ],
     "locale":"zh_CN",
 

+ 2 - 2
app/controller/Global.js

@@ -33,11 +33,11 @@ Ext.define('uas.controller.Global', {
 
     beforeHandleRoute: function(target, action) {
         let me = this,
+            store = Ext.StoreMgr.get('Navigation'),
             className = Ext.ClassManager.getNameByAlias('widget.' + target),
             ViewClass = Ext.ClassManager.get(className);
 
-        if(!!ViewClass) {
-            //resume action
+        if(!!ViewClass && store.getCount() > 0) {
             action.resume();
         }else {
             Ext.Msg.alert(

+ 30 - 0
app/util/State.js

@@ -0,0 +1,30 @@
+Ext.define('uas.util.State', {
+
+    singleton: true,
+
+    requires: [
+        'Ext.util.LocalStorage'
+    ],
+
+    store: new Ext.util.LocalStorage({
+        session: true,
+        id: 'app-state'
+    }),
+
+    get: function(key, defaultValue) {
+        var value = this.store.getItem(key);
+        return value === undefined? defaultValue : Ext.decode(value);
+    },
+
+    set: function(key, value) {
+        if (value == null) {    // !== undefined && !== null
+            this.store.removeItem(key);
+        } else {
+            this.store.setItem(key, Ext.encode(value));
+        }
+    },
+
+    clear: function(key) {
+        this.set(key, null);
+    }
+});

+ 73 - 0
app/view/form/basic/Panel.js

@@ -0,0 +1,73 @@
+Ext.define('uas.view.form.basic.Panel', {
+    extend: 'Ext.form.Panel',
+    xtype: 'basic-form',
+
+    bodyPadding: 12,
+    layout: 'form',
+
+    items: [{
+        xtype: 'textfield',
+        name: 'textfield1',
+        fieldLabel: 'Text field',
+        value: 'Text field value'
+    }, {
+        xtype: 'hiddenfield',
+        name: 'hidden1',
+        value: 'Hidden field value'
+    },{
+        xtype: 'textfield',
+        name: 'password1',
+        inputType: 'password',
+        fieldLabel: 'Password field'
+    }, {
+        xtype: 'filefield',
+        name: 'file1',
+        fieldLabel: 'File upload'
+    }, {
+        xtype: 'textareafield',
+        name: 'textarea1',
+        fieldLabel: 'TextArea',
+        value: 'Textarea value'
+    }, {
+        xtype: 'displayfield',
+        name: 'displayfield1',
+        fieldLabel: 'Display field',
+        value: 'Display field <span style="color: "green";">value</span>'
+    }, {
+        xtype: 'numberfield',
+        name: 'numberfield1',
+        fieldLabel: 'Number field',
+        value: 5,
+        minValue: 0,
+        maxValue: 50
+    }, {
+        xtype: 'checkboxfield',
+        name: 'checkbox1',
+        fieldLabel: 'Checkbox',
+        boxLabel: 'box label'
+    }, {
+        xtype: 'radiofield',
+        name: 'radio1',
+        value: 'radiovalue1',
+        fieldLabel: 'Radio buttons',
+        boxLabel: 'radio 1'
+    }, {
+        xtype: 'radiofield',
+        name: 'radio1',
+        value: 'radiovalue2',
+        fieldLabel: '',
+        labelSeparator: '',
+        hideEmptyLabel: false,
+        boxLabel: 'radio 2'
+    }, {
+        xtype: 'datefield',
+        name: 'date1',
+        fieldLabel: 'Date Field'
+    }, {
+        xtype: 'timefield',
+        name: 'time1',
+        fieldLabel: 'Time Field',
+        minValue: '1:30 AM',
+        maxValue: '9:15 PM'
+    }]
+});

+ 13 - 0
app/view/form/mfilefield/Panel.js

@@ -0,0 +1,13 @@
+Ext.define('uas.view.form.mfilefield.Panel', {
+    extend: 'Ext.form.Panel',
+    xtype: 'form-mfilefield',
+
+    id: 'mmf',
+
+    bodyPadding: 12,
+
+    items: [{
+        xtype: 'mfilefield',
+        value: '1001'
+    }]
+});

+ 1 - 0
packages/font-uas/Readme.md

@@ -0,0 +1 @@
+# font-school

+ 37 - 0
packages/font-uas/build.xml

@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<project name="font-ios" default=".help">
+    <!--
+    The build-impl.xml file imported here contains the guts of the build process. It is
+    a great idea to read that file to understand how the process works, but it is best to
+    limit your changes to this file.
+    -->
+    <import file="${basedir}/.sencha/package/build-impl.xml"/>
+
+    <!--
+    The following targets can be provided to inject logic before and/or after key steps
+    of the build process:
+
+        The "init-local" target is used to initialize properties that may be personalized
+        for the local machine.
+
+            <target name="-before-init-local"/>
+            <target name="-after-init-local"/>
+
+        The "clean" target is used to clean build output from the build.dir.
+
+            <target name="-before-clean"/>
+            <target name="-after-clean"/>
+
+        The general "init" target is used to initialize all other properties, including
+        those provided by Sencha Cmd.
+
+            <target name="-before-init"/>
+            <target name="-after-init"/>
+        
+        The "build" target performs the call to Sencha Cmd to build the application.
+
+            <target name="-before-build"/>
+            <target name="-after-build"/>
+    -->
+
+</project>

+ 2 - 0
packages/font-uas/index.js

@@ -0,0 +1,2 @@
+// This file was intentionally left blank.
+// This file is used by require.resolve to property locate this module.

+ 32 - 0
packages/font-uas/package.json

@@ -0,0 +1,32 @@
+{
+    "name": "@extjs/ext-font-uas",
+    "ext-react-name": "@extjs/ext-react-font-uas",
+    "ext-name": "@extjs/ext-font-uas",
+    "SenchaExtName": "@sencha/ext-font-uas",
+    "SenchaExtReactName": "@sencha/ext-react-font-uas",
+    "version": "6.6.0.258",
+    "sencha": {
+        "name": "font-uas",
+        "namespace": "Ext",
+        "type": "code",
+        "creator": "Sencha",
+        "summary": "uas iconfont",
+        "detailedDescription": "uas iconfont from https://www.iconfont.cn/manage/index?manage_type=myprojects&projectId=1373469",
+        "version": "6.6.0.258",
+        "compatVersion": "6.2.0",
+        "format": "1",
+        "output": "${framework.dir}/build/packages/${package.name}",
+        "local": true,
+        "sass" : {
+            "namespace": "Ext",
+            "etc": "${package.dir}/sass/etc/all.scss",
+            "var": "${package.dir}/sass/var",
+            "src": [
+                "${package.dir}/sass/src",
+                "${package.dir}/sass/src/all.scss"
+            ]
+        },
+        "classpath": "${package.dir}/src",
+        "overrides": "${package.dir}/overrides"
+    }
+}

BIN
packages/font-uas/resources/fonts/iconfont.eot


File diff suppressed because it is too large
+ 0 - 0
packages/font-uas/resources/fonts/iconfont.js


+ 32 - 0
packages/font-uas/resources/fonts/iconfont.svg

@@ -0,0 +1,32 @@
+<?xml version="1.0" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
+<!--
+2013-9-30: Created.
+-->
+<svg>
+<metadata>
+Created by iconfont
+</metadata>
+<defs>
+
+<font id="font-uas" horiz-adv-x="1024" >
+  <font-face
+    font-family="font-uas"
+    font-weight="500"
+    font-stretch="normal"
+    units-per-em="1024"
+    ascent="896"
+    descent="-128"
+  />
+    <missing-glyph />
+    
+    <glyph glyph-name="download" unicode="&#59650;" d="M853.333333 270.222222v-284.444444H170.666667v284.444444H56.888889v-398.222222h910.222222v398.222222h-113.777778zM568.888889 896H455.111111v-455.111111H239.502222a28.444444 28.444444 0 0 1-19.911111-48.355556l272.497778-272.497777a28.444444 28.444444 0 0 1 40.391111 0l272.497778 272.497777a28.444444 28.444444 0 0 1-20.48 48.355556H568.888889z"  horiz-adv-x="1024" />
+
+    
+    <glyph glyph-name="delete" unicode="&#59649;" d="M520.192 896C408.429714 896 317.44 813.129143 313.563429 709.266286H52.736c-29.037714 0-52.662857-21.942857-52.662857-49.078857 0-27.136 23.625143-49.152 52.662857-49.152h58.075429v-550.473143c0-103.350857 75.117714-187.757714 167.716571-187.757715h472.429714c92.598857 0 167.716571 83.894857 167.716572 187.757715V610.5234290000001h52.589714c29.037714 0 52.589714 21.942857 52.662857 49.078857-0.073143 27.136-23.625143 49.152-52.662857 49.152h-245.028571C723.236571 812.982857 631.954286 896 520.192 896zM404.845714 718.0434290000001c3.803429 50.029714 50.176 89.014857 107.446857 89.014857 57.197714 0 103.570286-38.985143 106.788572-89.014857H404.918857zM284.379429-37.66857100000004c-33.353143 0-69.997714 39.350857-69.997715 95.524571V606.866286h619.008v-549.522286c0-56.246857-36.644571-95.524571-69.997714-95.524571H284.379429v0.512zM357.229714 95.30514300000004a48.274286 48.274286 0 0 1 47.616 49.005714V424.301714a48.274286 48.274286 0 0 1-47.542857 49.078857 48.274286 48.274286 0 0 1-47.689143-49.005714v-280.064c0-27.282286 20.845714-49.005714 47.616-49.005714z m166.619429 0a48.274286 48.274286 0 0 1 47.689143 49.005714V424.301714a48.274286 48.274286 0 0 1-47.689143 49.078857 48.274286 48.274286 0 0 1-47.542857-49.005714v-280.064c0-27.282286 21.430857-49.005714 47.542857-49.005714z m142.921143 0a48.274286 48.274286 0 0 1 47.542857 49.005714V424.301714a48.274286 48.274286 0 0 1-47.542857 49.078857 48.274286 48.274286 0 0 1-47.616-49.005714v-280.064c0-27.282286 20.772571-49.005714 47.542857-49.005714z"  horiz-adv-x="1024" />
+
+    
+
+
+  </font>
+</defs></svg>

BIN
packages/font-uas/resources/fonts/iconfont.ttf


BIN
packages/font-uas/resources/fonts/iconfont.woff


BIN
packages/font-uas/resources/fonts/iconfont.woff2


+ 7 - 0
packages/font-uas/sass/etc/icons.scss

@@ -0,0 +1,7 @@
+.u-download:before {
+  content: "\e902";
+}
+
+.u-delete:before {
+  content: "\e901";
+}

+ 19 - 0
packages/font-uas/sass/src/all.scss

@@ -0,0 +1,19 @@
+$ext-font-path: get-resource-path('fonts');
+@import "../etc/icons.scss";
+
+@font-face {font-family: "font-uas";
+  src: url('#{$ext-font-path}/iconfont.eot?t=1566956918817'); /* IE9 */
+  src: url('#{$ext-font-path}/iconfont.eot?t=1566956918817#iefix') format('embedded-opentype'), /* IE6-IE8 */
+  url('data:application/x-font-woff2;charset=utf-8;base64,d09GMgABAAAAAANgAAsAAAAAB3gAAAMUAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHEIGVgCCfgqCZII5ATYCJAMMCwgABCAFhG0HOxt8BhEVlMtkHwm5Kc2bGHN9NKFqzAQR6spZrewocoAY/CGEFphrwjbn22/asY2KMEzJefBdnvE+7HD5gbbn63SVqpAVsv9zOb3VskQ+SapzTDvqJRyFgY2xaUzxRBJMxBvGbiJ4gJshgCcXJZAGjVp0wGEBvQSQEUMH98UV3FisE3MIYcNEi6wiwJnF5h4LVvLPyxdCcWAIFLBVm0ENB1Dnk3wyGidiemhMvJwRcKaBAiUAC9Kp0dwGleESKD4KWwrAsVoJfDKJBHwS+o+HYAGDgISA7BQAFDEiBj4JZmdcnfvEGykAIeCAkcACgDzD1MTQpckZRin1wukmlXqTVoeR3+H3bcs4cP3SzIM37ijkpz971iHFkkPx4YKRff68Y8qXLzsH0dKjSUcK+RcvOux8uvRxziEHruQKUtttlwqk6HzwqGjSkSWHMPHhjjkWmwsqtk2V40iOcSuMtywfO+7myzyP76VOszDz5DRpzj3O8xKaG3eUcUNs6yDz3WJ3+lQrJK17Dm0srxpJr6HSulCFhvMUvdvnn7YeP+TWyYq7u5wu2OrPqrXZCg4v5Nfs+thkXpmzGbJkOFfkGPVmPHKGAnKOaY/sQY/ix0ZsoQ8AiVhvacwZlm8IIHCw9s+ZvVPX+OciC8Drpf9njTssExwGBnP+P2dghY15QKM2ZGN26lE68p9DBvCxnoRuT8eH6fKM7xkVHBkzMCQjJyiOAqillICAiAoQ4uzUBk9xkukR6RHWiE0OFOOtgZCGDxhScRGUNHxRS/lBQCb+EJJG1uDpJOkXjCgk9am+IFUUlL2oznkwSKUn0suZUntGOXWp5Hm81x1iax4ocP1yLMEAWWKInctQ1ZAR7inu3A5dxzQKN8jVrVTHyPNM043cnPvFifoIIEUBBUTGC6Imhxkw1K6cZHOHiRTLGVC69TtSpIO0WH4HCJa6qXEiwMUfgCbiYRDpUZaxzJSEKIqBMIgW7SHi6UbQwTBDjM3tGkCO4lJNCI5EeEY1M1TsXlLa/98awANOUDGiYnED+DF0nBa7AeigWCwA') format('woff2'),
+  url('#{$ext-font-path}/iconfont.woff?t=1566956918817') format('woff'),
+  url('#{$ext-font-path}/iconfont.ttf?t=1566956918817') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */
+  url('#{$ext-font-path}/iconfont.svg?t=1566956918817#font-uas') format('svg'); /* iOS 4.1- */
+}
+
+.font-uas:before {
+  font-family: "font-uas" !important;
+  font-size: 16px;
+  font-style: normal;
+  -webkit-font-smoothing: antialiased;
+  -moz-osx-font-smoothing: grayscale;
+}

+ 13 - 2
resources/json/navigation.json

@@ -4,8 +4,19 @@
     "iconCls": "x-fa fa-podcast",
     "children": [{
         "text": "表单",
-        "leaf": true,
-        "iconCls": "x-fa fa-book"
+        "leaf": false,
+        "iconCls": "x-fa fa-book",
+        "children": [{
+            "text": "基础表单",
+            "target": "basic-form",
+            "leaf": true,
+            "iconCls": "x-fa fa-smile-o"
+        }, {
+            "text": "附件",
+            "target": "form-mfilefield",
+            "leaf": true,
+            "iconCls": "x-fa fa-smile-o"
+        }]
     },
     {
         "text": "列表",

+ 1 - 1
server/Readme.md

@@ -10,7 +10,7 @@ server
 ```
 
 启动服务指令:
-```cmd
+```powershell
 node ./server.js --port 24002
 // node <path of server file> [ -p | --port ] <port number>
 ```

+ 1 - 1
server/data/SearchPlanTree.js → server/action/SearchPlanTree.js

@@ -29,6 +29,6 @@ var searchPlanTree = (function(){
     }]
 })();
 
-module.exports = function(query){
+module.exports = function(request, response){
     return searchPlanTree;
 }

+ 2 - 1
server/data/bigData.js → server/action/bigData.js

@@ -38,7 +38,8 @@ var func = function(min, max){
 
 var data = func(1, 100);
 
-module.exports = function(query){
+module.exports = function(request, response){
+    var query = request.query;
     var page = query.page || 1;
     var start = query.start || 0;
     var limit = query.limit || 0;

+ 2 - 1
server/data/comanies.js → server/action/comanies.js

@@ -1020,7 +1020,8 @@ const getSummaryValue = (datas, property, type) => {
     return val;
 }
 
-module.exports = function(query) {
+module.exports = function(request, response) {
+    let query = request.query;
     let page = query.page ? Number(query.page) : 1;
     let start = query.start ? Number(query.start) : 0;
     let limit = query.limit ? Number(query.limit) : 0;

+ 2 - 2
server/data/dataList.js → server/action/dataList.js

@@ -17,8 +17,8 @@ var dataLists = (function(){
     return arr;
 })();
 
-module.exports = function(query){
-    console.log(query);
+module.exports = function(request, response){
+    var query = request.query;
     var page = Number(query.page) || 1;
     var start = Number(query.start) || 0;
     var limit = Number(query.limit) || 0;

+ 11 - 0
server/action/file-download.js

@@ -0,0 +1,11 @@
+var fs = require("fs");
+var path = require("path");
+const filePath = path.resolve(__dirname, '..' + path.sep + 'upload');
+
+module.exports = function(request, response) {
+    var filename = request.query.filename;
+    var oldname = request.query.oldname;
+    var file = filePath + path.sep + filename;
+    
+    return fs.createReadStream(file);//得到文件输入流
+};

+ 18 - 0
server/action/file-info.js

@@ -0,0 +1,18 @@
+var path = require("path");
+const filePath = path.resolve(__dirname, '..' + path.sep + 'upload');
+
+module.exports = function(request, response) {
+    var query = request.query;
+    console.log(query);
+    return [{
+        id: 'jztnl975x6tqwjxnra',
+        name: '$9O$UF[1[(@FQ)DM~)VRO8E.png',
+        path: filePath + path.sep + "$9O$UF[1[(@FQ)DM~)VRO8E.png",
+        size: 5629
+    }, {
+        id: 'jztnlw2rgdhqcfscoa',
+        name: '$%Z(E8G$S%DJHA6G`XJEVK4.png',
+        path: filePath + path.sep + "$%Z(E8G$S%DJHA6G`XJEVK4.png",
+        size: 86213
+    }];
+};

+ 33 - 0
server/action/file-upload.js

@@ -0,0 +1,33 @@
+const formidable = require('formidable');
+const fs = require('fs');
+const path = require('path');
+const Entities = require('html-entities').XmlEntities;
+const entities = new Entities();
+const filePath = path.resolve(__dirname, '..' + path.sep + 'upload');
+
+module.exports = function(request, response){
+    const form = new formidable.IncomingForm();
+    return new Promise((resolve, reject) => {
+        form.parse(request, (err, fields, files) => {
+            const file = files.file;
+            const oldpath = file.path;
+            const filename = file.name;
+            const size = file.size;
+            const id = Date.now().toString(36) + Math.random().toString(36).substr(3);
+    
+            const newpath = filePath + path.sep + entities.decode(filename);
+            fs.rename(oldpath, newpath, err => {
+                if (err) {
+                    reject(err);
+                }else {
+                    resolve({
+                        id: id,
+                        name: filename,
+                        path: newpath,
+                        size: size
+                    })
+                }
+            })
+        })
+    });
+}

+ 6 - 0
server/data/index.js → server/action/index.js

@@ -2,10 +2,16 @@ var bigData = require('./bigData');
 var comanies = require('./comanies');
 var dataList = require('./dataList');
 var searchPlanTree = require('./searchPlanTree');
+var upload = require('./file-upload');
+var download = require('./file-download');
+var fileInfo = require('./file-info');
 
 module.exports = {
     '/bigData': bigData,
     '/comanies': comanies,
     '/dataList': dataList,
     '/searchPlanTree': searchPlanTree,
+    '/file/upload': upload,
+    '/file/download': download,
+    '/file/info': fileInfo
 }

+ 73 - 9
server/getData.js

@@ -1,19 +1,83 @@
-var datas = require("./data/index");
+var actions = require("./action/index");
 
 module.exports = function(request, response) {
     var pathname = request.pathname;
-    if(datas.hasOwnProperty(pathname)) {
-        response.write(JSON.stringify({
-            code: 200,
-            success: true,
-            data: datas[pathname](request.query)
-        }));
+    
+    if(request.method === 'OPTIONS') {
+        response.end();
+    }else if(actions.hasOwnProperty(pathname)) {
+        if(pathname === '/file/upload') {
+            response.writeHead(200, {
+                "Content-Type": "application/json;charset=UTF-8"
+            });
+
+            var pr = actions[pathname](request, response);
+            pr.then(data => {
+                response.write(JSON.stringify({
+                    code: 200,
+                    success: true,
+                    data: data
+                }));
+                response.end();
+            }).catch((err) => {
+                response.write(JSON.stringify({
+                    code: 200,
+                    success: false,
+                    data: null,
+                    msg: err
+                }));
+                response.end();
+            });
+        }else if(pathname === '/file/download') {
+            var filename = request.query.filename;
+            var arr = [];
+            
+            var readStream = actions[pathname](request, response);
+            
+            readStream.on('data', chunk => {
+                arr.push(Buffer.from(chunk));
+            });
+
+            readStream.on('error', err => {
+                response.writeHead(200, {
+                    "Content-Type": "application/json;charset=UTF-8"
+                });
+                response.write(JSON.stringify({
+                    code: 200,
+                    success: false,
+                    msg: err,
+                    data: null
+                }));
+                response.end();
+            });
+
+            readStream.on('end', () => {
+                response.writeHead(200, {
+                    "Content-Type": "application/octet-stream",
+                    'Content-Disposition': 'attachment; filename=' + encodeURI(filename)
+                });
+                response.write(Buffer.from(...arr), 'binary');//文档内容以二进制的格式写到response的输出流
+                response.end();
+            })
+        }else {
+            response.writeHead(200, {
+                "Content-Type": "application/json;charset=UTF-8"
+            });
+
+            response.write(JSON.stringify({
+                code: 200,
+                success: true,
+                data: actions[pathname](request, response)
+            }));
+            response.end();
+        }
     }else {
         response.write(JSON.stringify({
             code: 200,
             success: false,
-            data: []
+            msg: 'no matches.',
+            data: null
         }));
+        response.end();
     }
-    response.end();
 }

+ 16 - 0
server/package-lock.json

@@ -0,0 +1,16 @@
+{
+  "requires": true,
+  "lockfileVersion": 1,
+  "dependencies": {
+    "formidable": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.1.tgz",
+      "integrity": "sha512-Fs9VRguL0gqGHkXS5GQiMCr1VhZBxz0JnJs4JmMp/2jL18Fmbzvv7vOFRU+U8TBkHEE/CX1qDXzJplVULgsLeg=="
+    },
+    "html-entities": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.2.1.tgz",
+      "integrity": "sha1-DfKTUfByEWNRXfueVUPl9u7VFi8="
+    }
+  }
+}

+ 6 - 0
server/package.json

@@ -0,0 +1,6 @@
+{
+  "dependencies": {
+    "formidable": "^1.2.1",
+    "html-entities": "^1.2.1"
+  }
+}

+ 2 - 4
server/server.js

@@ -29,10 +29,8 @@ function onRequest(request, response) {
 
 
     response.setHeader("Access-Control-Allow-Origin", "*"); // 设置可访问的源
-    response.setHeader("Access-Control-Allow-Headers", "x-requested-with,Authorization,Content-Type"); // 设置允许的响应头
-    response.writeHead(200, {
-        "Content-Type": "application/json;charset=UTF-8"
-    });
+    response.setHeader("Access-Control-Allow-Headers", "x-requested-with,Authorization,Content-Type,Access-Control-Allow-Origin"); // 设置允许的响应头
+    
     getData(request, response);
 }
 

+ 1 - 0
server/start_server.bat

@@ -0,0 +1 @@
+node server.js --port 24002

BIN
server/upload/$%Z(E8G$S%DJHA6G`XJEVK4.png


BIN
server/upload/$9O$UF[1[(@FQ)DM~)VRO8E.png


+ 103 - 0
ux/form/field/FileTag.js

@@ -0,0 +1,103 @@
+/**
+ * 显示附件名称、大小;
+ * 附件删除、下载、显示
+ */
+Ext.define('Ext.ux.form.field.FileTag', {
+	extend : 'Ext.form.field.Trigger',
+	alias : 'widget.filetag',
+	trigger1Cls: 'font-uas u-download',
+    trigger2Cls: 'font-uas u-delete',
+    style:'margin:5px 5px 0 0',
+    autoShow: true,
+	initComponent : function() {
+		this.callParent(arguments);
+	},
+	onTrigger1Click: function(e){
+        this.download();
+	},
+	onTrigger2Click: function(){
+		var me = this;
+		console.log('delete...');
+		// saas.util.BaseUtil.warnMsg('确定删除' + me.value, function(btn){
+		// 	if(btn == 'yes'){
+        //         var v = me.ownerCt.value.replace(me._id+';','')
+        //         me.ownerCt.setValue(v);
+        //         me.ownerCt.remove(me)
+		// 		// var v = me.ownerCt.down('hidden').value.replace(me.filepath + ';', '');
+		// 		// me.updateAttachField(v, '删除附件', function(){
+		// 		// 	me.ownerCt.down('hidden').setValue(v);
+		// 		// 	me.ownerCt.filesize -= me.filesize;
+		// 		// 	me.ownerCt.setTitle('<img src="' + basePath + 'resource/images/icon/clip.png" width=20 height=20/>附件' + 
+		// 		// 			'(总大小:' + Ext.util.Format.fileSize(me.ownerCt.filesize) + ")");
+		// 		// });
+		// 	}
+		// });
+	},
+	download : function() {
+        var me = this;
+		var serverOptions = Ext.manifest.server;
+		window.open((serverOptions.basePath.https?serverOptions.basePath.https:serverOptions.basePath) + '/file/download?filename='+me.fileName);
+	},
+
+	
+	showAttach : function() {
+		var me = this,src = basePath + 'common/download.action?path=' + me.realpath.replace(/\+/g, '%2B')+"&size="+me.filesize+"&fileName="+me.fileName;
+		var img = document.createElement("img");
+		img.src = src;		 		
+		myWindow=window.open(); 
+		myWindow.document.body.appendChild(img);
+		myWindow.focus();
+	},
+	isImage : function(path) {
+		if (Ext.isEmpty(path)) {
+			return false;
+		}
+		if (!/\.(gif|jpg|jpeg|png|GIF|JPG|PNG)$/.test(path)) {
+			return false;
+		}
+		return true;
+	},
+	resetField:function(bool){		
+	    var me=this;
+		if(bool)
+		me.getEl().down("." + me.trigger2Cls).applyStyles({visibility: 'hidden'});
+		else{
+			 me.getEl().down("." + me.trigger2Cls).applyStyles({visibility: 'visible'});
+		}
+	},
+	updateAttachField: function(value, type, fn) {
+		var form = this.ownerCt.ownerCt;
+		if(form.keyField){
+			var field = this.ownerCt.name,me = this, val = Ext.getCmp(form.keyField).value;
+			if(!Ext.isEmpty(val)&&!(caller.indexOf("$")!=-1 && form.keyField=="cl_id")) {//通用变更单上的附件字段,删除附件时后台不删除
+				Ext.Ajax.request({
+					url: basePath + 'common/attach/update.action',
+					params: {
+						caller: caller,
+						table: form.tablename.toUpperCase().split("LEFT")[0],
+						update: field + '=\'' + value + '\'',
+						condition: form.keyField + "='" + val+"'",
+						type: type
+					},
+					callback: function(opt, s, r) {
+						var res = Ext.decode(r.responseText);
+						if(res.success) {
+							if(fn) {
+								fn.call();
+								me.destroy();
+							}
+						} else {
+							showError(res.exceptionInfo);
+						}
+					}
+				});
+			} else {
+				fn && fn.call();
+				this.destroy();
+			}
+		} else{
+				fn && fn.call();
+				this.destroy();
+		}
+	}
+});

+ 312 - 0
ux/form/field/MFileField.js

@@ -0,0 +1,312 @@
+/**
+ * 多文件上传下载
+ */
+Ext.define('Ext.ux.form.field.MFileField', {
+	extend: 'Ext.form.FieldSet',
+	alias: 'widget.mfilefield',
+
+	defaultBindProperty: 'value',
+	
+	isFormField:true,
+	
+	columnWidth: 1,
+	cls: 'multi-file-field',
+	minHeight: 22,
+	collapsible: true,
+
+	layout:'column',
+
+	files: [],
+
+	initComponent: function() {
+		var me = this;
+		this.title = this.fieldLabel;
+		
+		if(this.value || this.defalutValue) {
+			me.getFilesInfo(this.value || this.defalutValue).then(function(res) {
+				var filesInfo = res.data;
+				me.addFiles(filesInfo);
+			});
+		}
+
+		Ext.apply(me, {
+			items: [{
+				xtype: 'hidden',
+				name: 'fileIds'
+			}, {
+				xtype: 'filefield',
+				name: 'file',
+				buttonText: '浏览文件(≤20MB)',
+				buttonOnly: true,
+				hideLabel: true,
+				columnWidth: 1,
+				float: 'left',
+				buttonConfig:{
+					cls:'x-filefield-button',
+					style: {
+						float: 'left',
+						margin: '0 0 5px 0'
+					}
+				},
+				createFileInput : function() {
+					this.fileInputEl = this.button.el.createChild({
+						name: this.getName(),
+						cls: Ext.baseCSSPrefix + 'form-file-input',
+						tag: 'input',
+						type: 'file',
+						multiple:'multiple',
+						size: 1
+					}).on('change', this.onFileChange, this);
+				},
+				listeners: {
+					change: function(field){
+						if(field.value){
+							me.upload(field);
+						}
+					}
+				}
+			}, {
+				xtype: 'form',
+				layout: 'column',
+				cls: 'form-file-tags',
+				columnWidth: 1,
+				bodyPadding:'0 0 5px 5px',
+				items: [],
+			}],
+			listeners: {
+				change: function() {
+					console.log('field value change', arguments);
+				}
+			}
+		});
+
+		this.callParent(arguments);
+	},
+
+	setValue: function(v){
+		var me = this,
+			items = me.items.items,
+			files = me.files,
+			newValue = '',
+			filesInfo;
+		
+		me.getFilesInfo(v).then(function(res) {
+			var filesInfo = res.data;
+			me.addFiles(filesInfo);
+		});
+	},
+
+	getValue: function (){
+		return this.items.items[0].value;
+	},
+
+	getValueField: function () {
+        return this.items.items[0];
+	},
+
+	getFileForm: function() {
+		return this.items.items[2];
+	},
+	
+	isValid: function () {
+        return this.getValueField().isValid();
+    },
+
+    isDirty: function () {
+        return this.getValueField().isDirty();
+	},
+	
+	setReadOnly: function (val) {
+        var me = this,
+        	items = me.items.items,
+			fileIdsField = items[0],
+			fileField = items[1];
+
+		fileIdsField.setReadOnly(val);
+        fileField.button.setDisabled(val);
+    },
+
+    resetOriginalValue: function() {
+		this.getValueField().resetOriginalValue();
+	},
+
+	addFiles: function(fileInfos) {
+		var me = this,
+			items = me.items.items,
+			value = me.getValue(),
+			id,
+			oldValue = value,
+			newValue = value;
+
+		Ext.Array.forEach(fileInfos, function(fileInfo) {
+			if(!me.contains(fileInfo)) {
+				newValue = (newValue || '') + fileInfo.id + ';';
+				me.files.push(fileInfo);
+				me.insertFileTag(fileInfo);
+			}
+		});
+
+		items[0].setValue(newValue);
+		this.publishState('value', newValue);
+		this.fireEvent('change', this, newValue, oldValue);
+	},
+
+	addFile: function(fileInfo) {
+		var me = this,
+			items = me.items.items,
+			value = me.getValue(),
+			oldValue = value,
+			newValue = value;
+		
+		if(!me.contains(fileInfo)) {
+			newValue = (newValue || '') + fileInfo.id + ';';
+			items[0].setValue(newValue);
+			this.files.push(fileInfo);
+			this.insertFileTag(fileInfo);
+	
+			this.publishState('value', newValue);
+			this.fireEvent('change', this, newValue, oldValue);
+		}
+	},
+
+	insertFileTag: function(fileInfo) {
+		var me = this,
+			fileForm = me.getFileForm(),
+			id = fileInfo.id,
+			name = fileInfo.name,
+			path = fileInfo.fullName,
+			size = fileInfo.size,
+			fileText, fieldWidth, newFileTag;
+
+		if(!id) {
+			return;
+		}
+		fileText = name + "  (" + Ext.util.Format.fileSize(size) + ")";
+		fieldWidth = Math.min((me.getStrLength(fileText) + 25) / 200, .8);
+
+		newFileTag = Ext.create('Ext.ux.form.field.FileTag', {
+			fileName: name,
+			value: name,
+			columnWidth: fieldWidth,
+			readOnly: false,
+			editable: false,
+			filepath: path,
+			filesize: size,
+			_id: id,
+			fieldStyle: 'background:#E0EEEE;'
+		});
+		fileForm.add(newFileTag);
+	},
+
+	/**
+	 * 上传附件
+	 */
+	upload: function(fileField){
+		var me = this;
+		var fileEl = fileField.fileInputEl.dom;
+		var fd = new FormData();
+		fd.append('file', fileEl.files[0]);
+		fd.append('folderId', 0);
+		me.setLoading(true);
+		Ext.Ajax.request({
+			url: '/api/file/upload',//这里是填写需要跨域访问的URL
+			cors: true,
+			useDefaultXhrHeader: false,
+			method: 'post',
+			rawData: fd,
+			headers: {
+				// 'Access-Control-Allow-Origin': '*',
+				// 'Authorization':  uas.util.State.get('session').token,
+				//"Content-Type": 'multipart/form-data'  //文件上传的格式, 
+				"Content-Type":null
+			},
+			success: function (response, opts) {
+				me.setLoading(false);
+				var res = Ext.decode(response.responseText);
+				if(res.success){
+					console.log('success');
+					var data = res.data;
+					me.addFile(data);
+				}else{
+					console.error('failure');
+				}
+			},
+			failure: function (response, opts) {
+				me.setLoading(false);
+				console.error('failure');
+			}
+		});
+	},
+
+	getFilesInfo: function(value){
+		var me = this;
+
+		me.setLoading(true);
+		return new Ext.Promise(function (resolve, reject) {
+			Ext.Ajax.request({
+				url : '/api/file/info',
+				params: {
+					ids:  value
+				},
+				method : 'GET',
+				success: function (response, opts) {
+					me.setLoading(false);
+					var res = Ext.decode(response.responseText);
+					if(res.success){
+						resolve(res);
+						// if(me.contains()) {
+							
+						// }
+						// me.addFiles(res.data);
+					}else{
+						reject(res);
+					}
+				},
+				failure: function (response, opts) {
+					me.setLoading(false);
+					reject(response);
+				}
+			});
+		})
+	},
+
+	contains: function(fileInfo) {
+		if(typeof fileInfo === 'string') { // 可能直接传id
+			fileInfo = { id: fileInfo };
+		}
+		return !!Ext.Array.findBy(this.files, function(f) {
+			return f.id === fileInfo.id;
+		});
+	},
+	
+	clearAll: function() {
+		this.getFileForm().removeAll();
+		this.setValue('');
+		this.files.length = 0;
+	},
+
+	getStrLength: function(str) {
+		for (var len = str.length, c = 0, i = 0; i < len; i++) 
+        	str.charCodeAt(i) < 27 || str.charCodeAt(i) > 126 ? c += 2 : c++;
+        return c;
+	},
+
+	// checkUploadAmount:function(form){
+	// 	var files = form.getEl().down('input[type=file]').dom.files;
+	// 	var amounts = 0;
+	// 	for (var i = 0; i < files.length; i++) {
+	// 		amounts = amounts + files[i].size
+	// 	}
+	// 	if (amounts>104857600) {
+	// 		Ext.MessageBox.alert("警告","对不起,上传文件总大小超过100m");
+	// 		return false
+	// 	}
+	// 	return true;
+	// },
+
+	// checkFile:function(fileName){
+	// 	var arr=['php','php2','php3', 'php5', 'phtml', 'asp', 'aspx', 'ascx', 'jsp', 'cfm', 'cfc', 'pl','pl','bat',  'dll', 'reg', 'cgi','war'];
+	//     var suffix=fileName.substring(fileName.lastIndexOf(".")+1);
+	//     return Ext.Array.contains(arr,suffix);
+	// },
+});

Some files were not shown because too many files changed in this diff