本案例是实现某系统的PropertyStaff表中的个人照片的上传

一、根据ftp服务器搭建文档创建一个新用户

用户为:user1,密码为root,为其共享D盘(后面将图片保存至D盘)

springboot连接ftp上传下载文件 springboot ftp_javascript

二、 后台

1.在后台上传FtpUtils工具类

springboot连接ftp上传下载文件 springboot ftp_java_02

代码:

package com.ruoyi.wxapp.utils;


import com.ruoyi.common.exception.file.FileSizeLimitExceededException;
import com.ruoyi.common.exception.file.InvalidExtensionException;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.file.MimeTypeUtils;
import com.ruoyi.common.utils.uuid.IdUtils;
import com.ruoyi.wxapp.config.FtpConfig;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPReply;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.PostConstruct;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

@Component
public class FtpUtils {

    /**
     * 默认大小 50M
     */
    public static final long DEFAULT_MAX_SIZE = 50 * 1024 * 1024;
    /** 此处静态方法不能用注入的方式初始化 否则为null 因为@Atuowire在初始化此对象之后执行 而调用静态方法不会初始化对象*/
    static FtpConfig ftpConfig;

    @Autowired
    FtpConfig ftp;

    @PostConstruct
    public void init(){
        ftpConfig=this.ftp;
    }

    /**
     * @param baseDir 上传的路径 为相对路径
     * @param  file 要上传到ftp服务器的文件
     */
    public static String upLoad(String baseDir, MultipartFile file) throws Exception {
        FTPClient ftp = new FTPClient();
        try {
            /** 1. 检查文件大小和扩展名是否符合要求*/
            assertFile(file);
            /** 2. 产生新的文件名,目的使得文件名统一为英文字符加数字;fileName包含文件后缀名*/
            String fileName=reBuildFileName(file);
            /** 3. 连接ftp服务器*/
            ftp.connect(ftpConfig.getIp(),ftpConfig.getPort());
            ftp.login(ftpConfig.getUsername(),ftpConfig.getPassword());
            if (!FTPReply.isPositiveCompletion(ftp.getReplyCode())) {
                // 不合法时断开连接
                ftp.disconnect();
                throw  new IOException("ftp连接异常,异常码为:"+ftp.getReplyCode());
            }
            String path=ftpConfig.getUploadPath()+baseDir;
            String[] dirs=path.split("/");
            ftp.changeWorkingDirectory("/");
            /** 4. 判断ftp服务器目录是否存在  不存在则创建*/
            for(int i=0; i<dirs.length && dirs != null;i++){
                if(! ftp.changeWorkingDirectory(dirs[i])){
                    if(ftp.makeDirectory(dirs[i])){
                        if(! ftp.changeWorkingDirectory(dirs[i]))
                            throw  new Exception("打开文件夹"+dirs[i]+"失败");
                    }else{
                        throw  new Exception("创建文件夹"+dirs[i]+"失败");
                    }
                }
            }
            /** 5.切换ftp文件操作目录*/
            ftp.changeWorkingDirectory(path);
            /** 6.上传文件*/
            // 设置文件类型,二进制
            ftp.setFileType(FTPClient.BINARY_FILE_TYPE);
            // 设置缓冲区大小
            ftp.setBufferSize(3072);
            // 上传文件
            ftp.storeFile(fileName, file.getInputStream());
            // 登出服务器
            ftp.logout();
            return baseDir+"/"+fileName;
        }catch (Exception e){
            throw  new Exception(e.getMessage(), e);
        }finally {
            /** 关闭*/
            // 判断连接是否存在
            if (ftp.isConnected()) {
                // 断开连接
                ftp.disconnect();
            }
        }

    }
    /**
     * @description: 从ftp服务器上下载文件到本地
     * @param baseDir ftp服务器文件路径 为相对路径 使用数据库中的url路径(ftp存在共享文件夹)
     * @param fileName 文件名
     * @param localDir web服务器本地存储路径 为相对路径 使用数据库中的url路径
     * */
    public static boolean downLoad(String localDir,String baseDir,String fileName){
        boolean result = false;
        String localPath=ftpConfig.getDownPath()+localDir;
        String ftpPath=ftpConfig.getUploadPath()+baseDir;
        FTPClient ftp = new FTPClient();
        OutputStream os = null;
        try {
            // 连接至服务器,端口默认为21时,可直接通过URL连接
            ftp.connect(ftpConfig.getIp(), ftpConfig.getPort());
            // 登录服务器
            ftp.login(ftpConfig.getUsername(), ftpConfig.getPassword());
            // 判断返回码是否合法
            if (!FTPReply.isPositiveCompletion(ftp.getReplyCode())) {
                // 不合法时断开连接
                ftp.disconnect();
                // 结束程序
                return result;
            }
            // 设置文件操作目录
            ftp.changeWorkingDirectory(ftpPath);
            // 设置文件类型,二进制
            ftp.setFileType(FTPClient.BINARY_FILE_TYPE);
            // 设置缓冲区大小
            ftp.setBufferSize(3072);
            // 设置字符编码
            ftp.setControlEncoding("UTF-8");
            // 构造本地文件夹
            File localFilePath = new File(localPath);
            if (!localFilePath.exists()) {
                localFilePath.mkdirs();
            }
            // 构造本地文件对象
            File localFile = new File(localPath + "/" + fileName);
            // 获取文件操作目录下所有文件名称
            String[] remoteNames = ftp.listNames();
            // 循环比对文件名称,判断是否含有当前要下载的文件名
            for (String remoteName : remoteNames) {
                if (fileName.equals(remoteName)) {
                    result = true;
                }
            }
            // 文件名称比对成功时,进入下载流程
            if (result) {
                // 构造文件输出流
                os = new FileOutputStream(localFile);
                // 下载文件 写入到输出流中
                result = ftp.retrieveFile(fileName, os);
                // 关闭输出流
                os.close();
            }
            // 登出服务器
            ftp.logout();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                // 判断输出流是否存在
                if (null != os) {
                    // 关闭输出流
                    os.close();
                }
                // 判断连接是否存在
                if (ftp.isConnected()) {
                    // 断开连接
                    ftp.disconnect();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return result;
    }
    /**
     * @desecription: 删除web服务器本地文件
     * @param realFile: web服务器本地文件
     * */
    public static boolean  delrealFile(String realFile){
        File file =new File(realFile);
        if( file.exists()&&file.isFile()){
            if(file.delete()){
                //System.out.println("删除成功");
                return true;
            }else {
                System.out.println("删除失败");
                return  false;
            }
        }else {
            System.out.println("删除"+realFile+"文件不存在或者不是一个文件类型");
            return  false;
        }
    }
        /**
         * @Description: 判断文件大小是否超过50M 以及判断文件扩展名是否是image类型
         * */
    public static void  assertFile(MultipartFile file)throws FileSizeLimitExceededException,InvalidExtensionException{
        long size=file.getSize();
        if(size>DEFAULT_MAX_SIZE){
            throw new FileSizeLimitExceededException(DEFAULT_MAX_SIZE/1024/1024);
        }
        String fileName=file.getOriginalFilename();
        String extension=getExtension(file);
        if(! isAllowedExtension(extension)){
            throw new InvalidExtensionException.InvalidImageExtensionException(MimeTypeUtils.IMAGE_EXTENSION, extension,
                    fileName);
        }
    }
    /**
     * 编码文件名
     */
    public static final String reBuildFileName(MultipartFile file)
    {
        String fileName = file.getOriginalFilename();
        String extension = getExtension(file);
        fileName =  IdUtils.fastUUID() + "." + extension;
        return fileName;
    }
    /**
     * 获取文件名的后缀
     *
     * @param file 表单文件
     * @return 后缀名
     */
    public static final String getExtension(MultipartFile file)
    {
        String extension = FilenameUtils.getExtension(file.getOriginalFilename());
        if (StringUtils.isEmpty(extension))
        {
            extension = MimeTypeUtils.getExtension(file.getContentType());
        }
        return extension;
    }
    /**
     * 判断MIME类型是否是允许的Image类型
     *
     * @param extension
     * @return
     */
    public static final boolean isAllowedExtension(String extension)
    {
        for (String str : MimeTypeUtils.IMAGE_EXTENSION)
        {
            if (str.equalsIgnoreCase(extension))
            {
                return true;
            }
        }
        return false;
    }
}

2.在yml文件中进行配置

springboot连接ftp上传下载文件 springboot ftp_idea_03

 

3.添加配置文件FtpConfig

springboot连接ftp上传下载文件 springboot ftp_javascript_04

代码:

package com.ruoyi.wxapp.config;

import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
@Data
public class FtpConfig {
    @Value("${ftpServer.ip}")
      String ip;
    @Value("${ftpServer.port}")
     int port;
    @Value("${ftpServer.username}")
     String username;
    @Value("${ftpServer.password}")
      String password;
    @Value("${ftpServer.uploadPath}")
      String uploadPath;
    @Value("${ftpServer.downPath}")
     String downPath;

    //在Controller中用于第二层与第三层路径的拼接
    public  static String getPropertyStaffDir(){
        return  "/propertyStaffImage";
    }
}

4.显示接口(共用一个显示接口),用来在前端预览上传图片

springboot连接ftp上传下载文件 springboot ftp_javascript_05

代码:

package com.ruoyi.wxapp.common;

import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.wxapp.config.FtpConfig;
import com.ruoyi.wxapp.utils.FtpUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;

@Controller
@RequestMapping("/common")
public class ImageController {

    @Autowired
    FtpConfig ftpConfig;
    /**
     * 从ftp服务器上查找到图片,然后存储到本地,将本地图片转化为字节流,返回到前端,最后删除本地图片
     * */
    @RequestMapping("/getImage")
    public void  getImageBinary(@RequestParam(value = "url", required = true) String url,
                                HttpServletResponse response)throws IOException {
        if(! StringUtils.isNotEmpty(url)){
            return;
        }
        //url对应的路径
        String urlPath=url.substring(0,url.lastIndexOf("/"));
        String fileName = url.substring(url.lastIndexOf("/")+1);
        if(FtpUtils.downLoad(urlPath,urlPath,fileName)){
            String realFile=ftpConfig.getDownPath()+urlPath+"/"+fileName;
            FileInputStream fis = null;
            OutputStream os = null;
            try {
                fis = new FileInputStream(realFile);
                os = response.getOutputStream();
                int count = 0;
                byte[] buffer = new byte[1024 * 3];
                while ((count = fis.read(buffer)) != -1) {
                    os.write(buffer, 0, count);
                    os.flush();
                }
            } catch (Exception e) {
                System.out.println("读取下载的图片失败!");
                e.printStackTrace();
            } finally {
                try {
                    fis.close();
                    os.close();
                    //关闭流之后才能删除下载的文件
			        FtpUtils.delrealFile(realFile);


                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }else{
            System.out.println("下载图片失败");
            return;
        }

    }
}

 

5. Controller添加方法

代码:

@RequestMapping("/uploadimage")
    public AjaxResult uploadPropertyStaffImage(@RequestParam("file") MultipartFile file) throws Exception {
        if(!file.isEmpty()){
            //此处拼接第三层路径:D:/zhihui/propertyStaffImage/物业人员信息
            String baseDir=ftpConfig.getPropertyStaffDir()+ "/" + "物业人员信息";
            String url= FtpUtils.upLoad(baseDir,file);
            AjaxResult ajaxResult=AjaxResult.success();
            ajaxResult.put("url",url);
            return ajaxResult;
        }
        return  AjaxResult.error("图片上传失败联系管理员");
    }

三、前端 

1.上传对话框

<el-form-item label="个人照片" prop="image">
          <el-upload
            action=""
            list-type="picture-card" 
            accept="image/*" 
            :limit=1 
            :file-list="imagelist"
            :on-preview="handlePictureCardPreview" 
            :on-remove="handleRemove" 
            :before-upload="beforeAvatarUpload" 
            :on-error="imgUploadError"
            :on-change="selectImageChange" 
            :http-request="upload"
            class="avatar-uploader"
            :class="{ disabled: uploadDisabled }"
            :auto-upload="false"
          >
            <i class="el-icon-plus"></i>
          </el-upload>
          <el-dialog :visible.sync="dialogVisible">
            <img width="100%" :src="dialogImageUrl" alt="" />
          </el-dialog>
        </el-form-item>

分析

springboot连接ftp上传下载文件 springboot ftp_java_06

2.添加限制,可解决当上传一个图片后又出现上传框的情况。在method方法上添加computed方法

//只显示一个上传框 返回Boolean值
  computed: {
    uploadDisabled: function () {
      return this.imagelist.length > 0;
    },
  },

3.添加disable的样式(在最底部)

<style >
.disabled .el-upload--picture-card {
  display: none;
}
/*去除upload组件过渡效果*/
.el-upload-list__item {
  transition: none !important;
}
</style>

4.添加配置,写在computed方法下即可

async mounted() {
    this.VUE_APP_BASE_API = process.env.VUE_APP_BASE_API;
  },

作用:

springboot连接ftp上传下载文件 springboot ftp_java_07

5.一些钩子函数(在methods:中添加下列方法)

methods: {
   /** 图片上传失败调用 */
    imgUploadError(err, file, fileList) {
      this.$message.error("上传图片失败!");
    },
      /** 文件上传之前调用做一些拦截限制 */
    beforeAvatarUpload(file) {
      console.log("before");
      const isLt2M = file.size / 1024 / 1024 < 2;
      if (!isLt2M) {
        this.$message.error("上传图片大小不能超过2MB!");
      }
      return isLt2M;
    },
    /** 取消默认上传操作 */
    upload() {},
    /** 移除图片时调用 */
    handleRemove(file, fileList) {
      this.imagelist = [];
    },
     /** 上传表单中预览图片时调用*/
    handlePictureCardPreview(file) {
      this.dialogImageUrl = file.url;
      this.dialogVisible = true;
    },
      /** 选择的图片列表变化时调用(增加) */
    async selectImageChange(file, fileList) {
      if (fileList.length >= 1 && this.imagelist.length == 0) {
        this.imagelist.push(file);
      }
      this.fd = new FormData();
      this.fd.append("file", file.raw); //传文件
      console.log("file:"+file.raw);
    },
      /** table中预览图片 */
    previewImg(row) {
      this.imgSrc =
        //"http://localhost" +
        this.VUE_APP_BASE_API +
        "/common/getImage?url=" +
        row.image;
      this.tableDialogVisible = true;
    },

6. 显示区域

<el-table-column
            label="个人照片"
            align="center"
            prop="image"
          >
            <template slot-scope="scope">
              <div v-if="scope.row.image != null && scope.row.image != ''">
                <el-image
                  style="width: 80px; height: 100px"
                  :src="VUE_APP_BASE_API+'/common/getImage?url='+scope.row.image"
                  @click="previewImg(scope.row)"
                  fit="cover"
                >
                </el-image>
                <el-dialog :visible.sync="tableDialogVisible">
                  <img
                    width="100%"
                    :src="imgSrc"
                    alt="点击可预览" 
                  />
                </el-dialog>
              </div>
              <div v-else>暂未提供</div>
            </template>
          </el-table-column>

7.在handleUpdate函数中为el-upload标签中的file-list的属性值imagelist数组填充图片url信息用于回显

springboot连接ftp上传下载文件 springboot ftp_javascript_08

代码:

var imageurl=this.VUE_APP_BASE_API+"common/getImage?url="+
        this.form.image;
        //修改图片时的回显
        let obj=new Object();
        obj.url=imageurl;
        this.imagelist.push(obj);

8.在api中添加addImgData函数请求后端的接口

代码:

export function addImgData(data) {
  return request({
    url: '/wxapp/property_staff/uploadimage',
    method: 'post',  
    headers: {
      'Content-Type': 'multipart/form-data',
    },
    data: data    // 参数需要是单一的formData形式
  })
}

9.在propertystaff对应的index.vue中导入函数,并在导出中填写默认值

springboot连接ftp上传下载文件 springboot ftp_javascript_09

10.提交按钮

springboot连接ftp上传下载文件 springboot ftp_spring_10

 

三、index.vue整体代码(-----之间的代码为添加的新代码)

<template>
  <div class="app-container">
    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
      <!-- <el-form-item label="物业编号" prop="wyid">
        <el-input
          v-model="queryParams.wyid"
          placeholder="请输入物业编号"
          clearable
          size="small"
          @keyup.enter.native="handleQuery"
        />
      </el-form-item> -->
      <el-form-item label="姓名" prop="name">
        <el-input
          v-model="queryParams.name"
          placeholder="请输入姓名"
          clearable
          size="small"
          @keyup.enter.native="handleQuery"
        />
      </el-form-item>
      <el-form-item label="性别" prop="gender">
        <el-select v-model="queryParams.gender" placeholder="请选择性别" clearable size="small">
          <el-option
            v-for="dict in genderOptions"
            :key="dict.dictValue"
            :label="dict.dictLabel"
            :value="dict.dictValue"
          />
        </el-select>
      </el-form-item>
      <el-form-item label="职位" prop="job">
        <el-input
          v-model="queryParams.job"
          placeholder="请输入职位"
          clearable
          size="small"
          @keyup.enter.native="handleQuery"
        />
      </el-form-item>

      <el-form-item label="类型" prop="type">
        <el-input
          v-model="queryParams.type"
          placeholder="请输入类型"
          clearable
          size="small"
          @keyup.enter.native="handleQuery"
        />
      </el-form-item>

      <el-form-item label="联系方式" prop="phone">
        <el-input
          v-model="queryParams.phone"
          placeholder="请输入联系方式"
          clearable
          size="small"
          @keyup.enter.native="handleQuery"
        />
      </el-form-item>

      <el-form-item label="入职时间" prop="creatTime">
        <el-date-picker clearable size="small" style="width: 200px"
          v-model="queryParams.creatTime"
          type="date"
          value-format="yyyy-MM-dd"
          placeholder="选择入职时间">
        </el-date-picker>
      </el-form-item>
      <!-- <el-form-item label="用户头像" prop="image">
        <el-input
          v-model="queryParams.image"
          placeholder="请输入用户头像"
          clearable
          size="small"
          @keyup.enter.native="handleQuery"
        />
      </el-form-item> -->
      <el-form-item label="备注" prop="comment">
        <el-input
          v-model="queryParams.comment"
          placeholder="请输入备注"
          clearable
          size="small"
          @keyup.enter.native="handleQuery"
        />
      </el-form-item>
      <!-- <el-form-item label="个人照片" prop="picture">
        <el-input
          v-model="queryParams.picture"
          placeholder="请输入个人照片"
          clearable
          size="small"
          @keyup.enter.native="handleQuery"
        />
      </el-form-item> -->
      <el-form-item label="微信号" prop="wxid">
        <el-input
          v-model="queryParams.wxid"
          placeholder="请输入微信号"
          clearable
          size="small"
          @keyup.enter.native="handleQuery"
        />
      </el-form-item>
      <!-- <el-form-item label="是否删除,删除为1,未删除为0" prop="isDelete">
        <el-input
          v-model="queryParams.isDelete"
          placeholder="请输入是否删除,删除为1,未删除为0"
          clearable
          size="small"
          @keyup.enter.native="handleQuery"
        />
      </el-form-item> -->
      <el-form-item>
        <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
      </el-form-item>
    </el-form>

    <el-row :gutter="10" class="mb8">
      <el-col :span="1.5">
        <el-button
          type="primary"
          icon="el-icon-plus"
          size="mini"
          @click="handleAdd"
          v-hasPermi="['wxapp:property_staff:add']"
        >新增</el-button>
      </el-col>
      <el-col :span="1.5">
        <el-button
          type="success"
          icon="el-icon-edit"
          size="mini"
          :disabled="single"
          @click="handleUpdate"
          v-hasPermi="['wxapp:property_staff:edit']"
        >修改</el-button>
      </el-col>
      <el-col :span="1.5">
        <el-button
          type="danger"
          icon="el-icon-delete"
          size="mini"
          :disabled="multiple"
          @click="handleDelete"
          v-hasPermi="['wxapp:property_staff:remove']"
        >删除</el-button>
      </el-col>
      <el-col :span="1.5">
        <el-button
          type="warning"
          icon="el-icon-download"
          size="mini"
          @click="handleExport"
          v-hasPermi="['wxapp:property_staff:export']"
        >导出</el-button>
      </el-col>
	  <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
    </el-row>

    <el-table v-loading="loading" :data="property_staffList" @selection-change="handleSelectionChange">
      <el-table-column type="selection" width="55" align="center" />
      <!-- <el-table-column label="物业编号" align="center" prop="wyid" /> -->
      <el-table-column label="姓名" align="center" prop="name" />
      <el-table-column label="性别" align="center" prop="gender" :formatter="genderFormat" />
      <el-table-column label="职位" align="center" prop="job" />
      <el-table-column label="类型" align="center" prop="type" />
      <el-table-column label="联系方式" align="center" prop="phone" />
      <el-table-column label="入职时间" align="center" prop="creatTime" width="180">
        <template slot-scope="scope">
          <span>{{ parseTime(scope.row.creatTime, '{y}-{m}-{d}') }}</span>
        </template>
      </el-table-column>
      <el-table-column label="备注" align="center" prop="comment" />
      <!-- ------------------------------------------------------------------------ -->
      <el-table-column
            label="个人照片"
            align="center"
            prop="image"
          >
            <template slot-scope="scope">
              <div v-if="scope.row.image != null && scope.row.image != ''">
                <el-image
                  style="width: 80px; height: 100px"
                  :src="VUE_APP_BASE_API+'/common/getImage?url='+scope.row.image"
                  @click="previewImg(scope.row)"
                  fit="cover"
                >
                </el-image>
                <el-dialog :visible.sync="tableDialogVisible">
                  <img
                    width="100%"
                    :src="imgSrc"
                    alt="点击可预览" 
                  />
                </el-dialog>
              </div>
              <div v-else>暂未提供</div>
            </template>
          </el-table-column>
      <!-- ------------------------------------------------------------------------ -->
      <el-table-column label="微信号" align="center" prop="wxid" />
      <!-- <el-table-column label="是否删除,删除为1,未删除为0" align="center" prop="isDelete" /> -->
      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
        <template slot-scope="scope">
          <el-button
            size="mini"
            type="text"
            icon="el-icon-edit"
            @click="handleUpdate(scope.row)"
            v-hasPermi="['wxapp:property_staff:edit']"
          >修改</el-button>
          <el-button
            size="mini"
            type="text"
            icon="el-icon-delete"
            @click="handleDelete(scope.row)"
            v-hasPermi="['wxapp:property_staff:remove']"
          >删除</el-button>
        </template>
      </el-table-column>
    </el-table>
    
    <pagination
      v-show="total>0"
      :total="total"
      :page.sync="queryParams.pageNum"
      :limit.sync="queryParams.pageSize"
      @pagination="getList"
    />

    <!-- 添加或修改物业人员信息对话框 -->
    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
        <el-form-item label="姓名" prop="name">
          <el-input v-model="form.name" placeholder="请输入姓名" />
        </el-form-item>
        <el-form-item label="性别" prop="gender">
          <el-select v-model="form.gender" placeholder="请选择性别">
            <el-option
              v-for="dict in genderOptions"
              :key="dict.dictValue"
              :label="dict.dictLabel"
              :value="parseInt(dict.dictValue)"
            ></el-option>
          </el-select>
        </el-form-item>
       <el-form-item label="职位" prop="job">
          <el-input v-model="form.job" placeholder="请输入职位" />
        </el-form-item>
       <el-form-item label="类型" prop="type">
          <el-input v-model="form.type" placeholder="请输入类型" />
        </el-form-item>
        <el-form-item label="联系方式" prop="phone">
          <el-input v-model="form.phone" placeholder="请输入联系方式" />
        </el-form-item>
        <el-form-item label="入职时间" prop="creatTime">
          <el-date-picker clearable size="small" style="width: 200px"
            v-model="form.creatTime"
            type="date"
            value-format="yyyy-MM-dd"
            placeholder="选择入职时间">
          </el-date-picker>
        </el-form-item>
        <el-form-item label="地址编号" prop="id">
          <el-input v-model="form.id" placeholder="请输入地址编号" />
        </el-form-item>
        <el-form-item label="备注" prop="comment">
          <el-input v-model="form.comment" placeholder="请输入备注" />
        </el-form-item>
       <!-- ------------------------------------------- -->
         <el-form-item label="个人照片" prop="image">
          <el-upload
            action=""
            list-type="picture-card" 
            accept="image/*" 
            :limit=1 
            :file-list="imagelist"
            :on-preview="handlePictureCardPreview" 
            :on-remove="handleRemove" 
            :before-upload="beforeAvatarUpload" 
            :on-error="imgUploadError"
            :on-change="selectImageChange" 
            :http-request="upload"
            class="avatar-uploader"
            :class="{ disabled: uploadDisabled }"
            :auto-upload="false"
          >
            <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 label="微信号" prop="wxid">
          <el-input v-model="form.wxid" placeholder="请输入微信号" />
        </el-form-item>
        <!-- <el-form-item label="是否删除,删除为1,未删除为0" prop="isDelete">
          <el-input v-model="form.isDelete" placeholder="请输入是否删除,删除为1,未删除为0" />
        </el-form-item> -->
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button type="primary" @click="submitForm">确 定</el-button>
        <el-button @click="cancel">取 消</el-button>
      </div>
    </el-dialog>
  </div>
</template>

<script>
import { listProperty_staff, getProperty_staff, delProperty_staff, addProperty_staff, updateProperty_staff, exportProperty_staff,addImgData } from "@/api/wxapp/property_staff";

export default {
  name: "Property_staff",
  data() {
    return {
      // 遮罩层
      loading: true,
      // 选中数组
        // form用于图像显示的数组
      // --------------------------------------- 
      imagelist: [],
      // form的图像预览url
      dialogImageUrl: "",
      // form的图像预览控制
      dialogVisible: false,
      // table的图像预览url
      imgSrc : null,
      //table的图像预览控制
      tableDialogVisible: false,
      //上传图片的对象
      fd :null,
      // -----------------------------------
      ids: [],
      // 非单个禁用
      single: true,
      // 非多个禁用
      multiple: true,
      // 显示搜索条件
      showSearch: true,
      // 总条数
      total: 0,
      // 物业人员信息表格数据
      property_staffList: [],
      // 弹出层标题
      title: "",
      // 是否显示弹出层
      open: false,
      // 性别字典
      genderOptions: [],
      // // 类型字典
      // typeOptions: [],
      // 查询参数
      queryParams: {
        pageNum: 1,
        pageSize: 10,
        wyid: null,
        name: null,
        gender: null,
        job: null,
        type: null,
        phone: null,
        creatTime: null,
        // image: null,
        comment: null,
        picture: null,
        wxid: null,
        isDelete: null
      },
      // 表单参数
      form: {},
      // 表单校验
      rules: {
        wyid: [
          { required: true, message: "物业编号不能为空", trigger: "blur" }
        ],
        name: [
          { required: true, message: "姓名不能为空", trigger: "blur" }
        ],
        gender: [
          { required: true, message: "性别不能为空", trigger: "change" }
        ],
        job: [
          { required: true, message: "职位不能为空", trigger: "blur" }
        ],
        type: [
          { required: true, message: "类型不能为空", trigger: "change" }
        ],
        phone: [
          { required: true, message: "联系方式不能为空", trigger: "blur" }
        ],
        creatTime: [
          { required: true, message: "入值时间不能为空", trigger: "blur" }
        ],
        id: [
          { required: true, message: "地址编号不能为空", trigger: "blur" }
        ],
        wxid: [
          { required: true, message: "微信号不能为空", trigger: "blur" }
        ],
        isDelete: [
          { required: true, message: "是否删除,删除为1,未删除为0不能为空", trigger: "blur" }
        ]
      }
    };
  },
  created() {
    this.getList();
    this.getDicts("sys_user_sex").then(response => {
      this.genderOptions = response.data;
    });
    // this.getDicts("db_property_staff_type").then(response => {
    //   this.typeOptions = response.data;
    // });
  },
  // ----------------------------------------------------
    //只显示一个上传框 返回Boolean值
  computed: {
    uploadDisabled: function () {
      return this.imagelist.length > 0;
    },
  },
  async mounted() {
    this.VUE_APP_BASE_API = process.env.VUE_APP_BASE_API;
   
  },
  // -----------------------------------------------------
  methods: {
     // ------------------------------------------------
   /** 图片上传失败调用 */
    imgUploadError(err, file, fileList) {
      this.$message.error("上传图片失败!");
    },
      /** 文件上传之前调用做一些拦截限制 */
    beforeAvatarUpload(file) {
      console.log("before");
      const isLt2M = file.size / 1024 / 1024 < 2;
      if (!isLt2M) {
        this.$message.error("上传图片大小不能超过2MB!");
      }
      return isLt2M;
    },
    /** 取消默认上传操作 */
    upload() {},
    /** 移除图片时调用 */
    handleRemove(file, fileList) {
      this.imagelist = [];
    },
     /** 上传表单中预览图片时调用*/
    handlePictureCardPreview(file) {
      this.dialogImageUrl = file.url;
      this.dialogVisible = true;
    },
      /** 选择的图片列表变化时调用(增加) */
    async selectImageChange(file, fileList) {
      if (fileList.length >= 1 && this.imagelist.length == 0) {
        this.imagelist.push(file);
      }
      this.fd = new FormData();
      this.fd.append("file", file.raw); //传文件
      console.log("file:"+file.raw);
    },
      /** table中预览图片 */
    previewImg(row) {
      this.imgSrc =
        //"http://localhost" +
        this.VUE_APP_BASE_API +
        "/common/getImage?url=" +
        row.image;
      this.tableDialogVisible = true;
    },
    // ----------------------------------------------------------

    /** 查询物业人员信息列表 */
    getList() {
      this.loading = true;
      listProperty_staff(this.queryParams).then(response => {
        this.property_staffList = response.rows;
        this.total = response.total;
        this.loading = false;
      });
    },
    // 性别字典翻译
    genderFormat(row, column) {
      return this.selectDictLabel(this.genderOptions, row.gender);
    },
    // 类型字典翻译
    // typeFormat(row, column) {
    //   return this.selectDictLabel(this.typeOptions, row.type);
    // },
    // 取消按钮
    cancel() {
      this.open = false;
      this.reset();
    },
    // 表单重置
    reset() {
      this.form = {
        wyid: null,
        name: null,
        gender: null,
        job: null,
        type: null,
        phone: null,
        creatTime: null,
        updateTime: null,
        // image: null,
        id: null,
        comment: null,
        picture: null,
        wxid: null,
        isDelete: null
      };
      this.resetForm("form");
    },
    /** 搜索按钮操作 */
    handleQuery() {
      this.queryParams.pageNum = 1;
      this.getList();
    },
    /** 重置按钮操作 */
    resetQuery() {
      this.resetForm("queryForm");
      this.handleQuery();
    },
    // 多选框选中数据
    handleSelectionChange(selection) {
      this.ids = selection.map(item => item.wyid)
      this.single = selection.length!==1
      this.multiple = !selection.length
    },
    /** 新增按钮操作 */
    handleAdd() {
      this.reset();
      this.open = true;
      this.title = "添加物业人员信息";
    },
    /** 修改按钮操作 */
    handleUpdate(row) {
      this.reset();
      const wyid = row.wyid || this.ids
      getProperty_staff(wyid).then(response => {
        this.form = response.data;
        // ------------------------------------------------------
        var imageurl=this.VUE_APP_BASE_API+"common/getImage?url="+
        this.form.image;
        //修改图片时的回显
        let obj=new Object();
        obj.url=imageurl;
        this.imagelist.push(obj);
        // ----------------------------------------------------
        this.open = true;
        this.title = "修改物业人员信息";
      });
    },
    /** 提交按钮 */
    submitForm() {
     this.$refs["form"].validate(async (valid )=> {
        if (valid) {
           // ------------------------------------
          if (this.fd != null && this.fd != undefined) {
            await addImgData(this.fd).then((res)=>{
              this.form.image = res.url;
              //console.log(this.form.image)
            });
          }
          //----------------------------------
          if (this.form.wyid != null) {
            updateProperty_staff(this.form).then(response => {
              if (response.code === 200) {
                this.msgSuccess("修改成功");
                this.open = false;
                this.getList();
              }
            });
          } else {
            addProperty_staff(this.form).then(response => {
              if (response.code === 200) {
                this.msgSuccess("新增成功");
                this.open = false;
                this.getList();
              }
            });
          }
        }
      });
    },
    /** 删除按钮操作 */
    handleDelete(row) {
      const wyids = row.wyid || this.ids;
      this.$confirm('是否确认删除物业人员信息编号为"' + wyids + '"的数据项?', "警告", {
          confirmButtonText: "确定",
          cancelButtonText: "取消",
          type: "warning"
        }).then(function() {
          return delProperty_staff(wyids);
        }).then(() => {
          this.getList();
          this.msgSuccess("删除成功");
        }).catch(function() {});
    },
    /** 导出按钮操作 */
    handleExport() {
      const queryParams = this.queryParams;
      this.$confirm('是否确认导出所有物业人员信息数据项?', "警告", {
          confirmButtonText: "确定",
          cancelButtonText: "取消",
          type: "warning"
        }).then(function() {
          return exportProperty_staff(queryParams);
        }).then(response => {
          this.download(response.msg);
        }).catch(function() {});
    }
  }
};
</script>
<style >
/****************************************************************/
.disabled .el-upload--picture-card {
  display: none;
}
/*去除upload组件过渡效果*/
.el-upload-list__item {
  transition: none !important;
}
</style>