精华内容
下载资源
问答
  • 图片来源:developer.apple.comSwiftUI 更好应用,更少代码。 SwiftUI是一种创新、简单iOS开发中界面布局方案,可以通过Swift语言强大... 仅使用一组工具和API为任何Apple设备构建用户界面。 SwiftUI具...

    源码地址:https://github.com/fzhlee/SwiftUI-Guide


    图片来源:developer.apple.com 

    SwiftUI
    更好的应用,更少的代码。
    SwiftUI是一种创新、简单的iOS开发中的界面布局方案,可以通过Swift语言的强大功能,在所有的Apple平台上快速构建用户界面。 仅使用一组工具和API为任何Apple设备构建用户界面。 
    SwiftUI具有易于阅读和自然编写的声明式Swift语法,可与新的Xcode设计工具无缝协作,使您的代码和设计完美同步。 
    自动支持动态类型、暗黑模式、本地化和可访问性,意味着您的第一行SwiftUI代码已经是您编写过的最强大的UI代码了。
     


    SwiftUI开发实用快捷键
    Command + Option + Enter : 打开或关闭预览窗口
    Command + Option + P : 刷新预览窗口

    SwiftUI的85节教程及源码
    所有课程基于Xcode 11 beta5,并在Xcode 11 beta5上编译通过。
    Xcode 11 beta版本下载地址:https://developer.apple.com/download/ 
    当Xcode11正式版发布之后,会更新所有源码,以适配Xcode 11正式版。

     


    图片来源:developer.apple.com

     

    第一章 常用的Views

    第1节:SwiftUI空白项目的创建步骤:

    1、打开Xcode,然后使用菜单命令:File > New > Project命令,打开项目创建窗口。
    2、在项目模板选择窗口中,选择Single View App模板,然后点击Next按钮,进入下一步设置窗口。
    3、在项目配置窗口中,需要勾选Use SwiftUI复选框,然后填写其它的配置选项,点击Next按钮,完成项目的创建。
    4、SwiftUI项目创建完成之后,其项目结构和代码功能如下图所示:

     


    5、项目导航区:

    文件名称 说明
    AppDelegate.swift 提供didFinishLaunchingWithOptions等方法,用来处理程序启动之后的事件,或者响应来自外部的事件。
    SceneDelegate.swift 设置应用程序窗口的rootViewController,并指定使用哪个ContentView作为rootViewController的rootView。
    ContentView.swift 项目的初始界面,用户界面上的可视控件可以放置在此文件中。
    Assets.xcassets 项目的资源文件,您可以在此处放置项目中所需的图片、颜色等资源。
    LaunchScreen.storyboard 用来配置项目启动过程中所显示的内容。
    Info.plist 项目的配置属性文件,配置产品名称、版本号、Build号、Bundle Identifier等项目。

    6、代码编辑器:

    • SwiftUI使用声明性语法,因此开发者可以简单地说明用户界面应该做什么。
    • 例如,您可以编写需要包含文本字段的项目列表,然后描述每个字段的对齐方式,字体和颜色。
    • 您的代码比以前更简单,更易于阅读,从而节省您的时间和维护。


    7、ContentView.swift代码说明:

    //导入SwiftUI框架
    import SwiftUI 		             
    
    //定义一个名为ContentView的结构体,该结构体遵循View协议,遵循View协议的元素才可以在SwiftUI框架中。就像在UIKit中,所见皆UIView一样,在SwiftUI中,所见皆是View。
    struct ContentView: View {		 
    //添加View协议中的body属性,在body属性中通过SwiftUI提供的各种布局控件,完成界面元素的搭建。关键词some表示返回的是某种View,但是SwiftUI不需要在意是具体的哪种View
        var body: some View {
        	//在屏幕上显示一个标签,标签的内容位于双引号之内
            Text("Hello World")
        }
    }
    
    //当处于Debug模式时,允许执行下方的代码
    #if DEBUG
    //定义一个遵循PreviewProvider的结构体,用于设置在右侧预览区需要实时预览的内容
    struct ContentView_Previews: PreviewProvider {
    //添加PreviewProvider协议中的previews属性,用来设置在实时预览区显示的内容
        static var previews: some View {
        	//设置在实时预览区显示ContentView结构体中的内容,您还可以在此设置预览的模拟器尺寸、是否Dark Mode等选项。
            ContentView()
        }
    }
    #endif

    8、SceneDelegate.swift代码说明:

    //使用此方法可以选择性地配置UIWindow窗口,并将其附加到提供的UIWindowScene
    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
    
            if let windowScene = scene as? UIWindowScene {
    	    //初始化一个UIWindow窗口对象
                let window = UIWindow(windowScene: windowScene)
    	    // 使用一个UIHostingController实例,作为该窗口的根 view controller
                window.rootViewController = UIHostingController(rootView: ContentView())
    	    // 将新建的窗口作为当前程序的窗口对象
                self.window = window
    	    // 将窗口作为主窗口并显示
                window.makeKeyAndVisible()
            }
        }

     

    SwiftUI课程章节导航区:

     

     

    iOS开发相关互动课程列表,手把手学习iOS开发,App Store免费下载:
    1、互动教程合集:https://apps.apple.com/cn/app/id1392811165
    2、Xcode互动教程免费下载地址:https://itunes.apple.com/cn/app/id1063100471
    3、Swift语言入门实例互动教程免费下载地址:https://itunes.apple.com/cn/app/id1320746678
    4、app开发中的神兵利器免费下载地址:https://itunes.apple.com/cn/app/id1209739676
    5、Objective-C语言应用开发互动教程免费下载地址:https://apps.apple.com/cn/app/id838877136 

     

    展开全文
  • [图片说明](https://img-ask.csdn.net/upload/201908/13/1565687289_915229.png)最后想导出json想是每个红框里是一组,然后是存在一个json数组里 想把在一个form表单里N个input输入框分为几个组 可以在导出...
  • 导读:UIScrollPicture 模块是一个图片轮播模块,只需传入一组图片地址,即可实现图片轮播效果。同时演示了如何使用UIScrollPicture实现APP引导页功能 使用模块前需在控制台添加UIScrollPicture模块和UIButton模块...

    导读:UIScrollPicture 模块是一个图片轮播模块,只需传入一组图片地址,即可实现图片轮播效果。同时演示了如何使用UIScrollPicture实现APP引导页功能

    使用模块前需在控制台添加UIScrollPicture模块和UIButton模块。

    • 方法1:点击引导页最后一个页面任意位置,进入主页面
    • 方法2:在引导页最后一个页面添加UIButton,通过点击UIButton按钮进入主页面
    • 页面逻辑写在在index.html中

     

     项目结构:

    config.xml

     <widget id="A6947174729052"  version="0.0.1">
    
        <name>轮播</name>
    
        <description>
    
            Example For 轮播 UIScrollPicture Module Demo.
    
        </description>
    
        <author email="1978195254@qq.com" href="http://https://blog.csdn.net/weixin_41937552">
    
            SDJ
    
        </author>
    
        <content src="index.html" />
    
        <access origin="*" />
    
        <preference name="pageBounce" value="false"/>
    
    	<preference name="appBackground" value="rgba(0,0,0,0.0)"/>
    
    	<preference name="windowBackground" value="rgba(0,0,0,0.0)"/>
    
    	<preference name="frameBackgroundColor" value="rgba(0,0,0,0.0)"/>
    
    	<preference name="hScrollBarEnabled" value="false"/>
    
    	<preference name="vScrollBarEnabled" value="false"/>
    
    	<preference name="autoLaunch" value="true"/>
    
    	<preference name="fullScreen" value="false"/>
    
    	<preference name="autoUpdate" value="true" />
    
    	<preference name="smartUpdate" value="true" />
    
    	<preference name="debug" value="false"/>
    
    	<preference name="statusBarAppearance" value="true"/>
    
    	<permission name="readPhoneState" />
    
    	<permission name="camera" />
    
    	<permission name="record" />
    
    	<permission name="location" />
    
    	<permission name="fileSystem" />
    
    	<permission name="internet" />
    
    	<permission name="bootCompleted" />
    
    	<permission name="hardware" />
    
    </widget>
    
    

    index,html

    <!doctype html>
    <html>
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="maximum-scale=1.0,minimum-scale=1.0,user-scalable=0,initial-scale=1.0,width=device-width"/>
        <meta name="format-detection" content="telephone=no,email=no,date=no,address=no">
        <title>轮播</title>
        <link rel="stylesheet" type="text/css" href="./css/api.css" />
        <style type="text/css">
    
        </style>
    </head>
    <body>
    </body>
    <script type="text/javascript" src="./script/api.js"></script>
    <script type="text/javascript">
        var UIScrollPicture;   //轮播图模块对象
        var UIButton;          //按钮模块对象
        var vButtonId;         //按钮模块对象索引对象
    
        //程序启动入口
        apiready = function(){
          //引导页显示判断
          var isFirst = api.getPrefs({
              key: 'isFirst',
              sync: true,
          });
          // isFirst=false;
          if (!isFirst) {
              //启动引导页面
              fnStartGuidePage();
          } else {
              fnStartMainPage();
          }
        };
    
        function fnStartGuidePage() {
            //设置页面默认图片;
            var tData = [
                'widget://res/guide1.jpg',
                'widget://res/guide2.jpg',
                'widget://res/guide3.jpg',
            ];
            UIScrollPicture = api.require('UIScrollPicture');
            UIScrollPicture.open({
                rect: {
                    x: 0,
                    y: 0,
                    w: 'auto',
                    h: 'auto'          //此处用'auto'是为了适应某些机型页面底部虚拟键的显示/隐藏 切换
                },
                data: {
                    paths: tData,
                },
                styles: {
                    indicator: {
                        align: 'center',
                        color: 'rgba(255,255,255,0.4)',
                        activeColor: '#FFFFFF'
                    }
                },
                contentMode: 'scaleToFill',
                auto: false,          //禁止自动滚动
                loop: false,          //禁止循环播放
            }, function(ret, err) {
                if (ret) {
                  /*
                    //方法1  点击末页任意位置进入主页面
                    if('click' == ret.eventType){
                       if(ret.index==3){
                         //关闭页面,进入主页面
                         fnStartMainPage();
                       }
                    }
                  */
    
                    //方法2  点击末页按钮进入主页面(使用前,需在控制台添加UIButton模块)
                    //设计思路:添加一个UIButton模块,在UIScrollPicture页面滑动到末页时显示UIButton模块,其余页面隐藏按钮模块,在按钮模块添加点事件点击模块进入主页面
    
                    //添加末页点击进入主页面方法
                    if ('show' == ret.eventType) {
                        UIScrollPicture.addEventListener({
                            name: 'scroll'
                        }, function(ret, err) {
                            if (ret.status) {
                                if (ret.index == (tData.length - 1)) {
                                    //显示进入按钮
                                    fnShowStartBtn();
                                } else {
                                    //隐藏进入按钮
                                    fnHideStartBtn();
                                }
                            }
                        });
                    }
    
                }
            });
        }
    
        //启动程序主页面
        function fnStartMainPage() {
            if(UIScrollPicture){
              //缓存App启动信息
              api.setPrefs({
                  key: 'isFirst',
                  value: '1'
              });
              //关闭引导页模块
              UIScrollPicture.close();
              //关闭方法2使用按钮模块
              if(UIButton){
                UIButton.close({
                    id: vButtonId
                });
              }
            }
            //启动主页面
            api.openWin({
                name: 'main',
                url: 'html/main.html',
                bounces: false,
                vScrollBarEnabled: false,
                hScrollBarEnabled: false,
                slidBackEnabled: false,
                rect: {
                    x: 0,
                    y: 0,
                    w: 'auto',
                    h: 'auto'
                }
            });
        }
    
    
        //显示进入APP按钮
        function fnShowStartBtn() {
            if (!vButtonId && vButtonId != 0) {
                //初始化按钮模块
                UIButton = api.require('UIButton');
                UIButton.open({
                    rect: {
                        x: api.winWidth / 2 - 50,
                        y: api.winHeight - 60,
                        w: 100,
                        h: 30
                    },
                    corner: 5,
                    bg: {
                        normal: 'rgba(255,255,255,50)',
                        highlight: 'rgba(255,255,255,90)',
                        active: 'rgba(255,255,255,90)'
                    },
                    title: {
                        size: 20,
                        normal: '立即开启',
                        highlightColor: '#000000',
                        activeColor: '#000adf',
                        normalColor: '#FFFFFF',
                        alignment: 'center'
                    },
                    fixed: true,
                    move: false
                }, function(ret, err) {
                    if ('show' == ret.eventType) {
                        vButtonId = ret.id;
                    }
                    if ('click' == ret.eventType) {
                        //关闭引导页,进入主页面
                        fnStartMainPage();
                    }
                });
            } else {
                //模块已初始化过,直接显示
                UIButton.show({
                    id: vButtonId
                });
            }
        }
    
        //隐藏进入按钮
        function fnHideStartBtn() {
            if (UIButton) {
                UIButton.hide({
                    id: vButtonId
                });
            }
        }
    
    
    
    
    </script>
    </html>
    

    main.html

    <!DOCTYPE HTML>
    <html>
    
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="maximum-scale=1.0, minimum-scale=1.0, user-scalable=0, initial-scale=1.0, width=device-width" />
        <meta name="format-detection" content="telephone=no, email=no, date=no, address=no">
        <title>Hello APP</title>
        <link rel="stylesheet" type="text/css" href="../css/api.css" />
        <style>
            html,
            body {
                height: 100%;
                display: flex;
                display: -webkit-flex;
                display: -webkit-box;
                flex-flow: column;
                -webkit-flex-flow: column;
                -webkit-box-orient: vertical;
            }
    
            .header {
                width: 100%;
                height: 44px;
                line-height: 44px;
                color: #FFFFFF;
                background-color: rgb(48,130,226);
                text-align: center;
                font-size: 14px;
                text-shadow: 1px 1px 1px rgba(55,55,55,0.6);
            }
    
            section {
                background-color: #f1f3f7;
                -webkit-box-flex: 1;
                -webkit-flex: 1;
                flex: 1;
                overflow: auto;
            }
    
            .scrollPicture {
                width: 100%;
                height: 225px;
            }
    
            .content {
                padding: 10px;
                word-wrap: break-word;
                word-break: normal;
            }
    
            .footer {
                width: 100%;
                height: 49px;
                line-height: 49px;
                color: #009af0;
                background-color: #EFEFEF;
                text-align: center;
                font-size: 14px;
            }
        </style>
    </head>
    
    <body>
        <div class="header">UIScrollPicture模块Demo</div>
        <section class="content">
            <div class="scrollPicture"></div>
            <div class="content">
                UIScrollPicture 是一个图片轮播模块,只需传入一组图片地址,即可实现图片轮播效果。<br /> open 接口内的 rect 参数,可控制图片轮播区域的位置和大小。styles 参数可以设置轮播视图底部的标题文字大小及颜色,亦可设置底部页面控制器(几个小圆点)的位置和样式。<br /> 有些应用的头条新闻或广告轮播展示都是无限循环自动播放的,本模块亦可以实现相同的功能,可通过open 接口内的 loop 和 auto 参数控制。每张图片自动轮播时的时间间隔也可自定义,用
                interval 即可。为了让原生模块真正的嵌入的网页内,让开发者像使用 js 库一样使用原生模块,APICloud 平台特开放了 fixedOn、fixed 参数。通过配置以上两个参数,可实现让轮播视图随 html 页面上下滚动的功能。<br /> 本图片轮播器是由原生代码开发,对于网络图片的展示更加人性化。模块内部会做缓存处理,第一次加载网络图片时,模块会根据其路径生成一个 md5 加密的图片名,并缓存在缓存文件夹里。当用户下次打开同路径的图片时,模块直接从缓存文件内读取该图片,从而大大节省了用户流量。开发者可以通过调用
                clearCache 接口清楚本模块在本地缓存的图片资源,调用 api.clearCache 接口会清除本 APP 在本地缓存的所有文件。由于原生代码相对前端代码的高效性,本模块相对于前端实现的图片轮播功能更加流畅,内存管理更加优化。当用户需要展示多张图片时,其内存只保留三张图片的地址,然后来回切换图片内容,从而降低了整个 app 内存占用率。具体模块功能请参考模块接口。
            </div>
        </section>
        <div class="footer" tapmode onclick="fnClearCache();">清除引导页缓存数据</div>
    </body>
    <script type="text/javascript" src="../script/api.js"></script>
    <script type="text/javascript">
        var vHeaderHeight;
        apiready = function() {
            fnInitPage();
            fnInitScrollPicture();
        };
    
        //页面初始化
        function fnInitPage() {
            //设置安卓keyBack键双击返回 
            api.addEventListener({
                name: 'keyback'
            }, function(ret, err){
                api.toast({
                        msg: '再按一次返回键退出'+api.appName,
                        duration:2000,
                        location: 'bottom'
                    });
                   
                    api.addEventListener({
                        name: 'keyback'
                    }, function(ret, err){
                        api.closeWidget({
                                id: 'A6947174729052',     //这里改成自己的应用ID
                                retData: {name:'closeWidget'},
                                silent:true
                            });
                    });
                   
                    setTimeout(function(){
                            exitApp();
                    },3000)
            });
    
            //开启沉浸式效果
            var header = $api.dom('.header');
            $api.fixStatusBar(header);
            vHeaderHeight = $api.offset(header).h;
    
    
        }
    
        //初始化轮播图模块
        function fnInitScrollPicture() {
            var UIScrollPicture = api.require('UIScrollPicture');
            UIScrollPicture.open({
                rect: {
                    x: 0,
                    y: vHeaderHeight,
                    w: api.winWidth,
                    h: 225
                },
                data: {
                    paths: [
                        'widget://res/pic1.jpg',
                        'widget://res/pic1.jpg',
                        'widget://res/pic1.jpg',
                        'widget://res/pic1.jpg'
                    ],
                    // captions: ['apicloud1', 'apicloud2', 'apicloud3', 'apicloud4']
                },
                styles: {
                    caption: {
                        height: 35,
                        color: '#E0FFFF',
                        size: 13,
                        bgColor: '#696969',
                        position: 'bottom'
                    },
                    indicator: {
                        align: 'center',
                        color: '#BFBFBF',
                        activeColor: 'rgb(48,130,226)'
                    }
                },
                placeholderImg: 'widget://res/slide1.jpg',
                contentMode: 'scaleToFill',
                interval: 3,
                fixedOn: api.frameName,
                loop: true,
                fixed: false
            }, function(ret, err) {
                // if (ret) {
                //     alert(JSON.stringify(ret));
                // } else {
                //     alert(JSON.stringify(err));
                // }
            });
        }
    
        //清除记录引导页状态的本地缓存数据
        function fnClearCache(){
            api.removePrefs({
                key: 'isFirst'
            });
            api.toast({
                msg: '引导页缓存数据清除成功!',
                duration: 2000,
                location: 'middle'
            });
        }
    </script>
    
    </html>
    

    api.css

    html{
    	font-family: sans-serif;
    }
    html,body,header,section,footer,div,ul,ol,li,img,a,span,em,del,legend,center,strong,var,fieldset,form,label,dl,dt,dd,cite,input,hr,time,mark,code,figcaption,figure,textarea,h1,h2,h3,h4,h5,h6,p{
    	margin:0;
    	border:0;
    	padding:0;
    	font-style:normal;
    }
    html,body {
    	-webkit-touch-callout:none;
    	-webkit-text-size-adjust:none;
    	-webkit-tap-highlight-color:rgba(0, 0, 0, 0);
    	-webkit-user-select:none;
    	background-color: #fff;
    }
    nav,article,aside,details,main,header,footer,section,fieldset,figcaption,figure{
    	display: block;
    }
    img,a,button,em,del,strong,var,label,cite,small,time,mark,code,textarea{
    	display:inline-block;
    }
    header,section,footer {
    	position:relative;
    }
    ol,ul{
    	list-style:none;
    }
    input,button,textarea {
    	border:0;
    	margin:0;
    	padding:0;
    	font-size:1em;
    	line-height:1em;
    	/*-webkit-appearance:none;*/
    	background-color:rgba(0, 0, 0, 0);
    }
    span{
    	display:inline-block;
    }
    a:active, a:hover {
      outline: 0;
    }
    a, a:visited{
    	text-decoration:none;
    }
    
    label, .wordWrap{
        word-wrap: break-word;
        word-break: break-all;
    }
    table {
      border-collapse: collapse;
      border-spacing: 0;
    }
    td,th {
      padding: 0;
    }
    .clearfix:after{
    	content: ' ';
    	display: block;
    	clear: both;
    	visibility:hidden;
    	line-height: 0;
    	height:0;
    }
    .loading_more{
    	display: block;
    	height: 1.5em;
    	width: 100%;
    }
    .loading_more:before {
    	display: inline-block; vertical-align: text-bottom;
    	content: ' '; height: 16px; width: 16px; margin-right: 6px;
    	background: url(../image/loading_more.gif) no-repeat center;
    	-webkit-background-size: contain;
    	background-size: contain;
    } 
    .loading_more:after {
    	content: '加载更多';	
    }

    api.js

    /*
     * APICloud JavaScript Library
     * Copyright (c) 2021 sunjiaoshou
     */
    (function(window){
        var u = {};
        var isAndroid = (/android/gi).test(navigator.appVersion);
        var uzStorage = function(){
            var ls = window.localStorage;
            if(isAndroid){
               ls = os.localStorage();
            }
            return ls;
        };
        function parseArguments(url, data, fnSuc, dataType) {
            if (typeof(data) == 'function') {
                dataType = fnSuc;
                fnSuc = data;
                data = undefined;
            }
            if (typeof(fnSuc) != 'function') {
                dataType = fnSuc;
                fnSuc = undefined;
            }
            return {
                url: url,
                data: data,
                fnSuc: fnSuc,
                dataType: dataType
            };
        }
        u.trim = function(str){
            if(String.prototype.trim){
                return str == null ? "" : String.prototype.trim.call(str);
            }else{
                return str.replace(/(^\s*)|(\s*$)/g, "");
            }
        };
        u.trimAll = function(str){
            return str.replace(/\s*/g,'');
        };
        u.isElement = function(obj){
            return !!(obj && obj.nodeType == 1);
        };
        u.isArray = function(obj){
            if(Array.isArray){
                return Array.isArray(obj);
            }else{
                return obj instanceof Array;
            }
        };
        u.isEmptyObject = function(obj){
            if(JSON.stringify(obj) === '{}'){
                return true;
            }
            return false;
        };
        u.addEvt = function(el, name, fn, useCapture){
            if(!u.isElement(el)){
                console.warn('$api.addEvt Function need el param, el param must be DOM Element');
                return;
            }
            useCapture = useCapture || false;
            if(el.addEventListener) {
                el.addEventListener(name, fn, useCapture);
            }
        };
        u.rmEvt = function(el, name, fn, useCapture){
            if(!u.isElement(el)){
                console.warn('$api.rmEvt Function need el param, el param must be DOM Element');
                return;
            }
            useCapture = useCapture || false;
            if (el.removeEventListener) {
                el.removeEventListener(name, fn, useCapture);
            }
        };
        u.one = function(el, name, fn, useCapture){
            if(!u.isElement(el)){
                console.warn('$api.one Function need el param, el param must be DOM Element');
                return;
            }
            useCapture = useCapture || false;
            var that = this;
            var cb = function(){
                fn && fn();
                that.rmEvt(el, name, cb, useCapture);
            };
            that.addEvt(el, name, cb, useCapture);
        };
        u.dom = function(el, selector){
            if(arguments.length === 1 && typeof arguments[0] == 'string'){
                if(document.querySelector){
                    return document.querySelector(arguments[0]);
                }
            }else if(arguments.length === 2){
                if(el.querySelector){
                    return el.querySelector(selector);
                }
            }
        };
        u.domAll = function(el, selector){
            if(arguments.length === 1 && typeof arguments[0] == 'string'){
                if(document.querySelectorAll){
                    return document.querySelectorAll(arguments[0]);
                }
            }else if(arguments.length === 2){
                if(el.querySelectorAll){
                    return el.querySelectorAll(selector);
                }
            }
        };
        u.byId = function(id){
            return document.getElementById(id);
        };
        u.first = function(el, selector){
            if(arguments.length === 1){
                if(!u.isElement(el)){
                    console.warn('$api.first Function need el param, el param must be DOM Element');
                    return;
                }
                return el.children[0];
            }
            if(arguments.length === 2){
                return this.dom(el, selector+':first-child');
            }
        };
        u.last = function(el, selector){
            if(arguments.length === 1){
                if(!u.isElement(el)){
                    console.warn('$api.last Function need el param, el param must be DOM Element');
                    return;
                }
                var children = el.children;
                return children[children.length - 1];
            }
            if(arguments.length === 2){
                return this.dom(el, selector+':last-child');
            }
        };
        u.eq = function(el, index){
            return this.dom(el, ':nth-child('+ index +')');
        };
        u.not = function(el, selector){
            return this.domAll(el, ':not('+ selector +')');
        };
        u.prev = function(el){
            if(!u.isElement(el)){
                console.warn('$api.prev Function need el param, el param must be DOM Element');
                return;
            }
            var node = el.previousSibling;
            if(node.nodeType && node.nodeType === 3){
                node = node.previousSibling;
                return node;
            }
        };
        u.next = function(el){
            if(!u.isElement(el)){
                console.warn('$api.next Function need el param, el param must be DOM Element');
                return;
            }
            var node = el.nextSibling;
            if(node.nodeType && node.nodeType === 3){
                node = node.nextSibling;
                return node;
            }
        };
        u.closest = function(el, selector){
            if(!u.isElement(el)){
                console.warn('$api.closest Function need el param, el param must be DOM Element');
                return;
            }
            var doms, targetDom;
            var isSame = function(doms, el){
                var i = 0, len = doms.length;
                for(i; i<len; i++){
                    if(doms[i].isEqualNode(el)){
                        return doms[i];
                    }
                }
                return false;
            };
            var traversal = function(el, selector){
                doms = u.domAll(el.parentNode, selector);
                targetDom = isSame(doms, el);
                while(!targetDom){
                    el = el.parentNode;
                    if(el != null && el.nodeType == el.DOCUMENT_NODE){
                        return false;
                    }
                    traversal(el, selector);
                }
    
                return targetDom;
            };
    
            return traversal(el, selector);
        };
        u.contains = function(parent,el){
            var mark = false;
            if(el === parent){
                mark = true;
                return mark;
            }else{
                do{
                    el = el.parentNode;
                    if(el === parent){
                        mark = true;
                        return mark;
                    }
                }while(el === document.body || el === document.documentElement);
    
                return mark;
            }
            
        };
        u.remove = function(el){
            if(el && el.parentNode){
                el.parentNode.removeChild(el);
            }
        };
        u.attr = function(el, name, value){
            if(!u.isElement(el)){
                console.warn('$api.attr Function need el param, el param must be DOM Element');
                return;
            }
            if(arguments.length == 2){
                return el.getAttribute(name);
            }else if(arguments.length == 3){
                el.setAttribute(name, value);
                return el;
            }
        };
        u.removeAttr = function(el, name){
            if(!u.isElement(el)){
                console.warn('$api.removeAttr Function need el param, el param must be DOM Element');
                return;
            }
            if(arguments.length === 2){
                el.removeAttribute(name);
            }
        };
        u.hasCls = function(el, cls){
            if(!u.isElement(el)){
                console.warn('$api.hasCls Function need el param, el param must be DOM Element');
                return;
            }
            if(el.className.indexOf(cls) > -1){
                return true;
            }else{
                return false;
            }
        };
        u.addCls = function(el, cls){
            if(!u.isElement(el)){
                console.warn('$api.addCls Function need el param, el param must be DOM Element');
                return;
            }
            if('classList' in el){
                el.classList.add(cls);
            }else{
                var preCls = el.className;
                var newCls = preCls +' '+ cls;
                el.className = newCls;
            }
            return el;
        };
        u.removeCls = function(el, cls){
            if(!u.isElement(el)){
                console.warn('$api.removeCls Function need el param, el param must be DOM Element');
                return;
            }
            if('classList' in el){
                el.classList.remove(cls);
            }else{
                var preCls = el.className;
                var newCls = preCls.replace(cls, '');
                el.className = newCls;
            }
            return el;
        };
        u.toggleCls = function(el, cls){
            if(!u.isElement(el)){
                console.warn('$api.toggleCls Function need el param, el param must be DOM Element');
                return;
            }
           if('classList' in el){
                el.classList.toggle(cls);
            }else{
                if(u.hasCls(el, cls)){
                    u.removeCls(el, cls);
                }else{
                    u.addCls(el, cls);
                }
            }
            return el;
        };
        u.val = function(el, val){
            if(!u.isElement(el)){
                console.warn('$api.val Function need el param, el param must be DOM Element');
                return;
            }
            if(arguments.length === 1){
                switch(el.tagName){
                    case 'SELECT':
                        var value = el.options[el.selectedIndex].value;
                        return value;
                        break;
                    case 'INPUT':
                        return el.value;
                        break;
                    case 'TEXTAREA':
                        return el.value;
                        break;
                }
            }
            if(arguments.length === 2){
                switch(el.tagName){
                    case 'SELECT':
                        el.options[el.selectedIndex].value = val;
                        return el;
                        break;
                    case 'INPUT':
                        el.value = val;
                        return el;
                        break;
                    case 'TEXTAREA':
                        el.value = val;
                        return el;
                        break;
                }
            }
            
        };
        u.prepend = function(el, html){
            if(!u.isElement(el)){
                console.warn('$api.prepend Function need el param, el param must be DOM Element');
                return;
            }
            el.insertAdjacentHTML('afterbegin', html);
            return el;
        };
        u.append = function(el, html){
            if(!u.isElement(el)){
                console.warn('$api.append Function need el param, el param must be DOM Element');
                return;
            }
            el.insertAdjacentHTML('beforeend', html);
            return el;
        };
        u.before = function(el, html){
            if(!u.isElement(el)){
                console.warn('$api.before Function need el param, el param must be DOM Element');
                return;
            }
            el.insertAdjacentHTML('beforebegin', html);
            return el;
        };
        u.after = function(el, html){
            if(!u.isElement(el)){
                console.warn('$api.after Function need el param, el param must be DOM Element');
                return;
            }
            el.insertAdjacentHTML('afterend', html);
            return el;
        };
        u.html = function(el, html){
            if(!u.isElement(el)){
                console.warn('$api.html Function need el param, el param must be DOM Element');
                return;
            }
            if(arguments.length === 1){
                return el.innerHTML;
            }else if(arguments.length === 2){
                el.innerHTML = html;
                return el;
            }
        };
        u.text = function(el, txt){
            if(!u.isElement(el)){
                console.warn('$api.text Function need el param, el param must be DOM Element');
                return;
            }
            if(arguments.length === 1){
                return el.textContent;
            }else if(arguments.length === 2){
                el.textContent = txt;
                return el;
            }
        };
        u.offset = function(el){
            if(!u.isElement(el)){
                console.warn('$api.offset Function need el param, el param must be DOM Element');
                return;
            }
            var sl = Math.max(document.documentElement.scrollLeft, document.body.scrollLeft);
            var st = Math.max(document.documentElement.scrollTop, document.body.scrollTop);
    
            var rect = el.getBoundingClientRect();
            return {
                l: rect.left + sl,
                t: rect.top + st,
                w: el.offsetWidth,
                h: el.offsetHeight
            };
        };
        u.css = function(el, css){
            if(!u.isElement(el)){
                console.warn('$api.css Function need el param, el param must be DOM Element');
                return;
            }
            if(typeof css == 'string' && css.indexOf(':') > 0){
                el.style && (el.style.cssText += ';' + css);
            }
        };
        u.cssVal = function(el, prop){
            if(!u.isElement(el)){
                console.warn('$api.cssVal Function need el param, el param must be DOM Element');
                return;
            }
            if(arguments.length === 2){
                var computedStyle = window.getComputedStyle(el, null);
                return computedStyle.getPropertyValue(prop);
            }
        };
        u.jsonToStr = function(json){
            if(typeof json === 'object'){
                return JSON && JSON.stringify(json);
            }
        };
        u.strToJson = function(str){
            if(typeof str === 'string'){
                return JSON && JSON.parse(str);
            }
        };
        u.setStorage = function(key, value){
            if(arguments.length === 2){
                var v = value;
                if(typeof v == 'object'){
                    v = JSON.stringify(v);
                    v = 'obj-'+ v;
                }else{
                    v = 'str-'+ v;
                }
                var ls = uzStorage();
                if(ls){
                    ls.setItem(key, v);
                }
            }
        };
        u.getStorage = function(key){
            var ls = uzStorage();
            if(ls){
                var v = ls.getItem(key);
                if(!v){return;}
                if(v.indexOf('obj-') === 0){
                    v = v.slice(4);
                    return JSON.parse(v);
                }else if(v.indexOf('str-') === 0){
                    return v.slice(4);
                }
            }
        };
        u.rmStorage = function(key){
            var ls = uzStorage();
            if(ls && key){
                ls.removeItem(key);
            }
        };
        u.clearStorage = function(){
            var ls = uzStorage();
            if(ls){
                ls.clear();
            }
        };
    
       
        /*by king*/
        u.fixIos7Bar = function(el){
            if(!u.isElement(el)){
                console.warn('$api.fixIos7Bar Function need el param, el param must be DOM Element');
                return;
            }
            var strDM = api.systemType;
            if (strDM == 'ios') {
                var strSV = api.systemVersion;
                var numSV = parseInt(strSV,10);
                var fullScreen = api.fullScreen;
                var iOS7StatusBarAppearance = api.iOS7StatusBarAppearance;
                if (numSV >= 7 && !fullScreen && iOS7StatusBarAppearance) {
                    el.style.paddingTop = '20px';
                }
            }
        };
        u.fixStatusBar = function(el){
            if(!u.isElement(el)){
                console.warn('$api.fixStatusBar Function need el param, el param must be DOM Element');
                return;
            }
            var sysType = api.systemType;
            if(sysType == 'ios'){
                u.fixIos7Bar(el);
            }else if(sysType == 'android'){
                var ver = api.systemVersion;
                ver = parseFloat(ver);
                if(ver >= 4.4){
                    el.style.paddingTop = '25px';
                }
            }
        };
        u.toast = function(title, text, time){
            var opts = {};
            var show = function(opts, time){
                api.showProgress(opts);
                setTimeout(function(){
                    api.hideProgress();
                },time);
            };
            if(arguments.length === 1){
                var time = time || 500;
                if(typeof title === 'number'){
                    time = title;
                }else{
                    opts.title = title+'';
                }
                show(opts, time);
            }else if(arguments.length === 2){
                var time = time || 500;
                var text = text;
                if(typeof text === "number"){
                    var tmp = text;
                    time = tmp;
                    text = null;
                }
                if(title){
                    opts.title = title;
                }
                if(text){
                    opts.text = text;
                }
                show(opts, time);
            }
            if(title){
                opts.title = title;
            }
            if(text){
                opts.text = text;
            }
            time = time || 500;
            show(opts, time);
        };
        u.post = function(/*url,data,fnSuc,dataType*/){
            var argsToJson = parseArguments.apply(null, arguments);
            var json = {};
            var fnSuc = argsToJson.fnSuc;
            argsToJson.url && (json.url = argsToJson.url);
            argsToJson.data && (json.data = argsToJson.data);
            if(argsToJson.dataType){
                var type = argsToJson.dataType.toLowerCase();
                if (type == 'text'||type == 'json') {
                    json.dataType = type;
                }
            }else{
                json.dataType = 'json';
            }
            json.method = 'post';
            api.ajax(json,
                function(ret,err){
                    if (ret) {
                        fnSuc && fnSuc(ret);
                    }
                }
            );
        };
        u.get = function(/*url,fnSuc,dataType*/){
            var argsToJson = parseArguments.apply(null, arguments);
            var json = {};
            var fnSuc = argsToJson.fnSuc;
            argsToJson.url && (json.url = argsToJson.url);
            //argsToJson.data && (json.data = argsToJson.data);
            if(argsToJson.dataType){
                var type = argsToJson.dataType.toLowerCase();
                if (type == 'text'||type == 'json') {
                    json.dataType = type;
                }
            }else{
                json.dataType = 'text';
            }
            json.method = 'get';
            api.ajax(json,
                function(ret,err){
                    if (ret) {
                        fnSuc && fnSuc(ret);
                    }
                }
            );
        };
    
    /*end*/
        
    
        window.$api = u;
    
    })(window);
    
    
    

    完整下载地址:https://download.csdn.net/download/weixin_41937552/13990960

    展开全文
  • 续上一个文章(晨曦CZB) 后台代码: #region 局部变量 public Form1() { InitializeComponent(); this.Load += (s, e) => { DataShow(); ...

    续上一个文章(晨曦CZB)

    后台代码:

     #region 局部变量
    
            public Form1()
            {
                InitializeComponent();
                this.Load += (s, e) =>
                {
                    DataShow();
                    ControlEvent();
                };
            }
            #endregion
    
            #region 绑定数据
            /// <summary>
            /// 绑定数据
            /// </summary>
            private void DataShow()
            {
                var path = Application.StartupPath + @"\Image";
                var files = new DirectoryInfo(path).GetFiles();
                var data = files.Select(d =>
                  {
                      this.imageSlider1.Images.Add(Image.FromFile(d.FullName));
                      return new { Name = d.Name, Image = Image.FromFile(d.FullName), Paths = d.FullName };
                  });
                this.gridControl1.BeginUpdate();
                this.gridControl1.DataSource = data;
                this.gridControl1.EndUpdate();
            }
            #endregion
    
            #region 控件的委托事件
            /// <summary>
            /// 控件的委托事件
            /// </summary>
            private void ControlEvent()
            {
                /*卡片的点击事件*/
                this.layoutView1.CardClick += (s, e) =>
                {
                    if (e.Button == MouseButtons.Left)
                        this.imageSlider1.CurrentImageIndex = e.Card.RowHandle;
                };
    
                this.sbtnFirst.Click += (s, e) =>
                {
                    this.imageSlider1.SlideFirst();
                };
                this.sbtnPrev.Click += (s, e) =>
                {
                    this.imageSlider1.SlidePrev();
                };
                this.sbtnNext.Click += (s, e) =>
                {
                    this.imageSlider1.SlideNext();
                };
                this.sbtnLast.Click += (s, e) =>
                {
                    this.imageSlider1.SlideLast();
                };
                this.sbtnClose.Click += (s, e) =>
                {
                    this.Close();
                };
    
                this.sbtnDownload.Click += (s, e) =>
                {
                    var path = (string)this.layoutView1.GetRowCellValue(this.imageSlider1.CurrentImageIndex, "Paths");
                    var name = this.layoutView1.GetRowCellValue(this.imageSlider1.CurrentImageIndex, "Name");
    
                    SaveFileDialog sf = new SaveFileDialog();
                    sf.Title = "选择保存文件路径";
                    sf.Filter = "图像文件(*.jpg)|*.jpg;";
                    sf.FileName = name.ToString();
                    sf.AddExtension = true;/*自动添加扩展名*/
                    if (sf.ShowDialog() == DialogResult.OK)
                    {
                        File.Copy(path, sf.FileName, true);//目录重命名见下面代码
                    }
                };
            }
            #endregion

     

    展开全文
  • 今天有一个坑,同时要上传图片和文件,而且图片要展示缩略图,文件要展示列表。 我思路是: 首先,只上传附件照片,这个直接看ele官方例子就行,不仅仅上传附件照片,还同时上传其他参数。 然后,再做上传...

    今天有一个坑,同时要上传图片和文件,而且图片要展示缩略图,文件要展示列表。

    我的思路是:

    首先,只上传附件照片,这个直接看ele的官方例子就行,不仅仅上传附件照片,还同时上传其他参数。

    然后,再做上传照片和文件,上传其他参数,其实也就是文件合并。

     

    一、上传照片和其他参数

    页面样式大约就是这样的,参数有优先级,发生时间,服务单名称,服务单描述,图片附件上传。


    (一)视图部分代码:

    <el-form-item prop="image" label="图片附件上传">
              <el-upload
                ref="upload"
                :action="uploadAction"
                :beforeUpload="beforeUploadPicture"
                :on-change="imageChange"
                list-type="picture-card"
                name="files"
                :data="paramsData"
                :limit="3"
                multiple
                :auto-upload="false"
                :on-preview="handlePictureCardPreview"
                :on-remove="handleRemovePicture">
                <i class="el-icon-plus"></i>
              </el-upload>
              <el-dialog :visible.sync="dialogVisible">
                <img width="100%" :src="dialogImageUrl" alt="">
              </el-dialog>
         </el-form-item>
    
     <el-button size="mini" type="primary" @click="confirm()">确 定</el-button>

    说明:

    1、action变量为后端图片接口的地址

    2、beforeUpload方法是指的上传之前触发的函数,可以用来做前端文件格式判断,文件大小判断

    3、on-change方法是指每次选择文件都会触发函数,可以用来前端删除和添加照片

    4、list-type属性指的是照片picture-card展示的方式

    5、name指的是上传的文件字段名,这是后端确认文件流的字段名,可以随便写

    6、data属性指的是上传时附带的额外参数,这是指的其他参数

    7、limit属性指的是上传文件的个数极限。

    8、multiple属性指的是可以每次多选文件,true为多选,false为单选

    9、auto-upload属性指的是自动上传的,true为可以自动上传,false为不可以自动上传

    10、on-preview方法指的是查看缩略图的方法

    11、on-remove方法指的是删除文件的方法

    12、ref绑定dom元素

     

    (二)data部分代码

    data () {
        return {
          selectedCategorySpe: this.selectedCategory,
          serviceForm: {
            title: '',
            desc: '',
            priority: '',
            occurDate: ''
          },
           dialogImageUrl: '',
           dialogVisible: false,
          uploadAction: "/inner/event/order/submit/submit" + "&accessToken=" + this.$store.getters.token
        }
      },



    (三)computed部分代码

    computed: {
        ...mapGetters([
          'constConfig'
        ]),
        paramsData: function () {
          let params = {
            eventCategory: this.selectedCategorySpe.categoryId,
              priority: this.serviceForm.priority,
              title: this.serviceForm.title,
              dsc: this.serviceForm.desc,
              occurDate: this.serviceForm.occurDate
          }
          return params
        }
      },

    使用computed实现实时监测paramsData的值,只要selectedCategorySpe.categoryId,serviceForm.priority,serviceForm.title

    ,serviceForm.desc,serviceForm.occurDate中只有一个变化,都会重新计算paramsData的值。

     

    (四)methods部分方法

    beforeUploadPicture(file){
          const isImage = file.type == 'image/png' || file.type == 'image/jpg' ||  file.type == 'image/jpeg' || file.type == 'image/bmp' || file.type == 'image/gif' || file.type == 'image/webp';
          const isLt2M = file.size <  1024 * 1024 * 2;
          if (!isImage) {
            this.$message.error('上传只能是png,jpg,jpeg,bmp,gif,webp格式!');
          }
          if (!isLt2M) {
            this.$message.error('上传图片大小不能超过 2MB!');
          }
          return isImage && isLt2M;
        },
        handlePictureCardPreview(file) {
          this.dialogImageUrl = file.url;
          this.dialogVisible = true;
        },
        handleRemovePicture(file, fileList) {
          console.log(file, fileList);
        },
        imageChange(file, fileList, name) {
          console.log(file, fileList);
        },
    
     confirm(){
        this.$refs.upload.submit();
        }

    说明:confirm使用ref的绑定的upload,紧接着调用form的表单的submit方法。这个vue已经封装好了,这时候传的参数可以看到post传递的文件对象。





    二、同时上传图片和文件,并且图片可以看缩略图文件显示成列表

    但是当你出现这样的需求的时候,一脸蒙蔽


    (一)视图部分代码

    <el-form-item prop="image" label="图片附件上传">
              <el-upload
                ref="uploadImage"
                :action="uploadAction"
                :beforeUpload="beforeUploadPicture"
                :on-change="imageChange"
                list-type="picture-card"
                name="files"
                :limit="3"
                multiple
                :auto-upload="false"
                :on-preview="handlePictureCardPreview"
                :on-remove="handleRemovePicture">
                <i class="el-icon-plus"></i>
              </el-upload>
              <el-dialog :visible.sync="dialogVisible">
                <img width="100%" :src="dialogImageUrl" alt="">
              </el-dialog>
            </el-form-item>
            <el-form-item prop="image" label="文件附件上传">
              <el-upload
                ref="uploadFile"
                class="upload-demo"
                name="files"
                :on-change="fileChange"
                :action="uploadAction"
                :on-preview="handlePreviewFile"
                :on-remove="handleRemoveFile"
                :before-remove="beforeRemoveFile"
                multiple
                :auto-upload="false"
                :limit="3"
                :on-exceed="handleExceedFile"
                :file-list="fileList">
                <el-button size="small" type="primary">点击上传</el-button>
                <!--<div slot="tip" class="el-upload__tip">只能上传文件,且不超过2M</div>-->
              </el-upload>
            </el-form-item>
    
     <el-button size="mini" type="primary" @click="confirm()">确 定</el-button>

     

    (2)data部分数据

    data () {
        return { 
          selectedCategorySpe: this.selectedCategory,
          serviceForm: {
            title: '',
            desc: '',
            priority: '',
            occurDate: '',
          },
          images: {},
          files: {},
          dialogImageUrl: '',
          dialogVisible: false
        }
      },

     

    (3)method部分数据

    beforeUploadPicture(file){
         const isImage = file.type == 'image/png' || file.type == 'image/jpg' ||  file.type == 'image/jpeg' || file.type == 'image/bmp' || file.type == 'image/gif' || file.type == 'image/webp';
          const isLt2M = file.size <  1024 * 1024 * 2;
          if (!isImage) {
            this.$message.error('上传只能是png,jpg,jpeg,bmp,gif,webp格式!');
          }
          if (!isLt2M) {
            this.$message.error('上传图片大小不能超过 2MB!');
          }
          return isImage && isLt2M;
        },
        handlePictureCardPreview(file) {
          this.dialogImageUrl = file.url;
          this.dialogVisible = true;
        },
        handleRemovePicture(file, fileList) {
          console.log(file, fileList);
        },
        imageChange(file, fileList, name) {
          console.log(file, fileList);
          this.imageList = fileList;
          this.images['images'] = fileList;
        },
    
        handleRemoveFile(file, fileList) {
          console.log(file, fileList);
        },
        handlePreviewFile(file) {
          console.log(file);
        },
        handleExceedFile(files, fileList) {
          this.$message.warning(`当前限制选择 3 个文件,本次选择了 ${files.length} 个文件,共选择了 ${files.length + fileList.length} 个文件`);
        },
        beforeRemoveFile(file, fileList) {
          return this.$confirm(`确定移除 ${ file.name }?`);
        },
        fileChange(file,fileList) {
          console.log(file, fileList);
          this.fileList = fileList;
          this.files['files'] = fileList;
     },
        confirm(){
              let wfForm = new FormData();
              wfForm.append( 'eventCategory',this.selectedCategorySpe.categoryId)
              wfForm.append( 'priority',this.serviceForm.priority)
              wfForm.append( 'title',this.serviceForm.title)
              wfForm.append( 'dsc',this.serviceForm.desc)
              wfForm.append( 'occurDate',this.serviceForm.occurDate)
              Object.entries(this.images).forEach(file => {
                file[0].forEach(item => {
                  // 下面的“images”,对应后端需要接收的name,这样对图片和文件做一个区分,name为images为图片
                  wfForm.append('images', item.raw)
                  // wfForm.append(item.name, file[0])
                })
              })
              Object.entries(this.files).forEach(file => {
                file[0].forEach(item => {
                  // 下面的“files”,对应后端需要接收的name,name为files为文件
                  wfForm.append('files', item.raw)
                  //wfForm.append(item.name, file[0])
                })
              })
              createEventOrder(wfForm).then( res => {
                console.log(res, 'res')
                if(res.retValue === 1){
                  this.$message.success( '成功创建服务单' );
                  this.handleClose()
                }else{
    
                }
              })
    
        }

    说明一下,新建了this.files存文件列表,this.images存图片列表。在confirm中新建一个FormData对象,使用append方法将参数变量加到数据对象中,和文件对象。最后将FormData对象传给后端。

    传递的参数截图如下:

    这回对images和files,图片和文件做区分,后端也需要做个判断,其他的参数不需要的参数可以选择不传,需要增加新的参数,使用append的方法添加。

    2019.07.11【说明】

    根据评论中提到的问题

     this.files[''] = fileList;

    意义不大,这个就是想用一个对象存那个文件对象,对象需要一个name,自己取一个,也可以为空。改成这样也行:

     this.files['files'] = fileList;

    这样做的目的是如果你的文件上传和图片上传用一个this.fileImage对象的话,在最后包装formData的时候可以通过对象的name区分,哪个是文件,哪个是图片,用一次

    Object.entries(this.images).forEach 

    就可以把formData包装好,更符合前端的高复用,低代码的思想。

    我怕有人理解不了这个,我还是补充一下代码:

    (2)data部分数据(新增一个fileImage)

    fileImage: {},

    (3)methods中修改这块

    1、图片上传的这块修改为

    if(isImage && isLt2M){  
        this.imageList = fileList;  
        this.fileImage['images'] = fileList;}else{  
        fileList.splice(-1,1);
    }

    2、文件上传的这块修改为

    if(!isImage && isLt2M){  
        this.fileList = fileList;  
        this.fileImage['files'] = fileList;}else{  
        fileList.splice(-1,1);
    }

    3、提交那块,把两个forEach合并成一个,然后直接取对象的name最为formData的name。

    Object.entries(this.fileImage).forEach(file => {      file[1].forEach(item => {    
            wfForm.append(file[0], item.raw)    
        })
    })
    
    
    最后也可以看到,也是ok的

     

    【欢迎关注,有什么问题,欢迎提出,我看到有空就回答】

     

    转载于:https://www.cnblogs.com/chengxs/p/10047376.html

    展开全文
  • 人脑将作为一个变化的场景的映像。 在电影中,使用记录许多照片或帧,每秒的照相机创建这种错觉。 当播放帧的投影仪时,观众看到的是运动的图片。 在计算机上的动画与此类似。 例如,可使矩形淡出视野之外的绘图...
  • 通过一系列的插件等组装出一套比较好看的页面交互效果; 开始的lodings层;是真是存在的;不是虚假的 是通过img的加载数量来判断,。同时考虑了本地缓存等情况; 如果本地缓存的话就虚假1000秒来显示lodings效果; ...
  • 这是一组线描彩绘系列边框PPT背景图片,第一PPT模板网提供幻灯片背景图片免费下载; PPT背景图片是边框PPT背景图片,采用了线描、彩绘设计方式,绘制了一个带有花卉PPT文本边框,里面可以填写PPT文本内容;本组...
  • 下图为CSDN的一个web工具栏效果:    Delphi制作效果如图: 制作步骤如下: 1.放置一个Panel,如图设置:  2.再放置一个Panel,为P_tools   3.放一个图片List   4.放置一个GpButton: 属性...
  • 前言: BOSS系列的日志,建议在看了前面的...例如子弹、飞机、爆炸效果(一连串动态图片)……等都可以是一个精灵,所有的精灵默认都在同一个层 0 层里。文档里说明:You can set the default layer through kwarg...
  • 图片涂鸦和水印其实是一个功能,实现方式是一样,就是一张大图片和一张小点图片叠加即可。前面在android图像处理系列之六--给图片添加边框(下)-图片叠加中也讲到了图片叠加,里面实现原理是直接操作像素点...
  • 举例说,一个视频游戏不但只包含程序本身,也包括图片、声音以及其他创造虚拟游戏环境数据内容。在零售市场,在一部计算机上某个应用程序只是一个面向大量用户软件的一个副本。这里老生常谈例子当然还是微软...
  • 今日一个需求,就是反馈用户产品信息,要求用户可以既能上传图片,又能上传文字。查询了一系列资料,巴拉巴拉一堆信息后,终于理出了一条上传方案,然后跟后台商量好数据传递方式: @Multipart @POST...
  • 以下是一个老设师亲自设计去100张海报图片,可以说不管排版还是字体设计,都非常棒,分享给大家,希望给在学习UI设计路上同学一些帮助。能从优秀作品中发现更多设计理念,能不断提升自己设计能力。 ...
  • 1.放置一个SplitView 2.设置属性: Placement:scsvLeft Opened:False OpenWidth:200 CompactWidth:50 BorderStyle:None Color:$001B1A14 3.放置一个TImageList  Name:ImageList24 添加若干图片 4.在...
  • 图片涂鸦和水印其实是一个功能,实现方式是一样,就是一张大图片和一张小点图片叠加即可。前面在android图像处理系列之六--给图片添加边框(下)-图片叠加中也讲到了图片叠加,里面实现原理是直接操作像素...
  • 【3】C++基础系列(类组合)

    千次阅读 2018-09-19 13:50:41
    1、组合概念:类中成员是另外一个对象。可以在已有抽象基础上实现更加复杂抽象。新对象不能访问源类私有成员。 无论定义了多少个构造函数,一定要再写一个不要参数默认构造函数。当类组合以对象...
  • //从指定的索引源开始,复制receiveData中的一系列数据到result中(从指定目标的索引开始) return result; } #endregion ``` ``` internal class ModbusSocketWrapper : IDisposable { private static int ...
  • 本篇主要讲解如何实现一个简易选择上传图片展示控件,该自定义控件继承自ViewGroup,支持网格排列,以及横向排列。最终效果如下图: 网格布局 水平布局 自定义View 上图中每个ImageView右上角都有一个删除...
  • 如果我们要手写一个字符画,首先要有扎实美术基础,其次还要花费大量时间和精力。对于零基础小白而言,困难可想而知。 但是不要发愁,我们可以使用Python,只需要几行代码,就能够将一张图片轻而易举地转化为...
  • 搜集到一些关于网站提速资料,做一个系列,一些文章可能转或摘自网络。(一)、 网页加速之图形处理篇 在维护网站过程用,可能遇到过这样情况:辛辛苦苦做出来页面,但图片过多,网页结构、表格结构复杂,...
  • 在传统Web应用模式中每当用户触发一个页面切换或刷新HTTP请求时,就需要服务器返回一个页面。即便在网页中所有格和图片都资源没有发生改变仅仅只有少量数据发生变化情况下依然要从服务器重新加载整个网页...
  • 这一章,我创建了一系列的对象,并且用代码将他们组合起来,每个对象可以响应鼠标事件。 ...这一章的实例是一个家庭图片一个project。  创建一个矩形对象function Rect(x,y,w,h,c){ this.x = x
  • 将边框图片裁剪成八张小图片(图片大小最好一致,不然后面处理会很麻烦),分别对应左上角,左边,左下角,下边,右下角,右边,右上角,上边,其中左右上下只需要一个有效长度,就像重写水平进度条一样,只需要一个...
  • 将边框图片裁剪成八张小图片(图片大小最好一致,不然后面处理会很麻烦),分别对应左上角,左边,左下角,下边,右下角,右边,右上角,上边,其中左右上下只需要一个有效长度,就像重写水平进度条一样,只需要一个...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 650
精华内容 260
关键字:

一个系列的一组的图片