Explorar o código

修改了数据库表结构更新了第一版审核部分

0714Star hai 1 ano
pai
achega
6c34df6c9e
Modificáronse 47 ficheiros con 1563 adicións e 59 borrados
  1. 1 0
      .idea/compiler.xml
  2. 0 1
      .idea/misc.xml
  3. 5 0
      springboot/pom.xml
  4. 27 0
      springboot/src/main/java/com/example/common/enums/AuditState.java
  5. 5 1
      springboot/src/main/java/com/example/common/enums/ResultCodeEnum.java
  6. 10 9
      springboot/src/main/java/com/example/controller/FileController.java
  7. 14 1
      springboot/src/main/java/com/example/controller/SaleStatementController.java
  8. 157 0
      springboot/src/main/java/com/example/controller/uploadVideoController.java
  9. 30 0
      springboot/src/main/java/com/example/entity/Audits.java
  10. 126 0
      springboot/src/main/java/com/example/entity/Chunk.java
  11. 56 0
      springboot/src/main/java/com/example/entity/Video.java
  12. 36 0
      springboot/src/main/java/com/example/mapper/VideoMapper.java
  13. 1 1
      springboot/src/main/java/com/example/utils/generate/CodeGenerator.java
  14. 19 1
      springboot/src/main/resources/mapper/AuditsMapper.xml
  15. 68 0
      springboot/src/main/resources/mapper/VideoMapper.xml
  16. 25 5
      springboot/src/main/resources/sql/fruit_farmer.sql
  17. BIN=BIN
      springboot/target/classes/com/example/common/enums/AuditState.class
  18. BIN=BIN
      springboot/target/classes/com/example/common/enums/ResultCodeEnum.class
  19. BIN=BIN
      springboot/target/classes/com/example/controller/FileController.class
  20. BIN=BIN
      springboot/target/classes/com/example/controller/SaleStatementController.class
  21. BIN=BIN
      springboot/target/classes/com/example/controller/uploadVideoController.class
  22. BIN=BIN
      springboot/target/classes/com/example/entity/Audits.class
  23. BIN=BIN
      springboot/target/classes/com/example/entity/Chunk.class
  24. BIN=BIN
      springboot/target/classes/com/example/entity/Video.class
  25. BIN=BIN
      springboot/target/classes/com/example/mapper/VideoMapper.class
  26. BIN=BIN
      springboot/target/classes/com/example/utils/generate/CodeGenerator.class
  27. 19 1
      springboot/target/classes/mapper/AuditsMapper.xml
  28. 68 0
      springboot/target/classes/mapper/VideoMapper.xml
  29. 5 0
      uniapp/.idea/.gitignore
  30. 8 0
      uniapp/.idea/modules.xml
  31. 12 0
      uniapp/.idea/uniapp.iml
  32. 6 0
      uniapp/.idea/vcs.xml
  33. 343 31
      vue/package-lock.json
  34. 3 0
      vue/package.json
  35. 105 0
      vue/src/components/UploadPic.vue
  36. 81 0
      vue/src/components/UploadSlice.vue
  37. 57 0
      vue/src/components/UploadView.vue
  38. 1 1
      vue/src/router/index.js
  39. 24 0
      vue/src/utils/fileUtil/CreateChunk.js
  40. 43 0
      vue/src/utils/fileUtil/CutFile.js
  41. 13 0
      vue/src/utils/fileUtil/fileUtil.js
  42. 21 0
      vue/src/utils/fileUtil/worker.js
  43. 1 0
      vue/src/views/AdminMgr.vue
  44. 2 0
      vue/src/views/Front.vue
  45. 3 3
      vue/src/views/Manager.vue
  46. 124 0
      vue/src/views/front/ApplyForUp.vue
  47. 44 4
      vue/src/views/manager/Manager/Audit.vue

+ 1 - 0
.idea/compiler.xml

@@ -2,6 +2,7 @@
 <project version="4">
   <component name="CompilerConfiguration">
     <annotationProcessing>
+      <profile default="true" name="Default" enabled="true" />
       <profile name="Maven default annotation processors profile" enabled="true">
         <sourceOutputDir name="target/generated-sources/annotations" />
         <sourceTestOutputDir name="target/generated-test-sources/test-annotations" />

+ 0 - 1
.idea/misc.xml

@@ -1,4 +1,3 @@
-<?xml version="1.0" encoding="UTF-8"?>
 <project version="4">
   <component name="ASMSmaliIdeaPluginConfiguration">
     <asm skipDebug="true" skipFrames="true" skipCode="false" expandFrames="false" />

+ 5 - 0
springboot/pom.xml

@@ -74,6 +74,11 @@
             <groupId>org.springframework.ai</groupId>
             <artifactId>spring-ai-openai-spring-boot-starter</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+            <optional>true</optional>
+        </dependency>
     </dependencies>
 
     <build>

+ 27 - 0
springboot/src/main/java/com/example/common/enums/AuditState.java

@@ -0,0 +1,27 @@
+package com.example.common.enums;
+
+/**
+ * 功能:审核状态
+ *
+ * @author 熊浩毅
+ * @time 2024-04-19 16:34
+ * @Description
+ */
+public enum AuditState {
+    UPLOADED("已上传"),
+    CHECKING("正在审核"),
+    PASS("审核通过"),
+    FAIL("审核失败")
+    ;
+    AuditState(String state){
+
+        this.state = state;
+    }
+    String state;
+
+
+    @Override
+    public String toString(){
+        return this.state;
+    }
+}

+ 5 - 1
springboot/src/main/java/com/example/common/enums/ResultCodeEnum.java

@@ -12,12 +12,16 @@ public enum ResultCodeEnum {
     NEXT_STATUS_ERROR("4007","订单已完成,无法切换到下一个状态"),
     ACCOUNT_AUTHORITY_LIMIT("4008","用户权限不足"),
     SYSTEM_ERROR("500", "系统异常"),
+
     USER_EXIST_ERROR("5001", "用户名已存在"),
     USER_NOT_LOGIN("5002", "用户未登录"),
     USER_ACCOUNT_ERROR("5003", "账号或密码错误"),
     USER_NOT_EXIST_ERROR("5004", "用户不存在"),
     PARAM_PASSWORD_ERROR("5005", "原密码输入错误"),
-    ACCOUNT_LIMIT_ERROR("5006","余额不足");
+    ACCOUNT_LIMIT_ERROR("5006","余额不足"),
+    UPLOAD_ERROR("5007","上传失败"),
+    WRITE_ERROR("5008","文件读写出错"),
+    ;
     //
     ;
 

+ 10 - 9
springboot/src/main/java/com/example/controller/FileController.java

@@ -4,6 +4,7 @@ import cn.hutool.core.io.FileUtil;
 import cn.hutool.core.thread.ThreadUtil;
 import cn.hutool.core.util.StrUtil;
 import com.example.common.Result;
+import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.multipart.MultipartFile;
@@ -11,13 +12,13 @@ import org.springframework.web.multipart.MultipartFile;
 import javax.servlet.http.HttpServletResponse;
 import java.io.OutputStream;
 import java.net.URLEncoder;
-import java.util.List;
 
 /**
  * 文件接口
  */
 @RestController
 @RequestMapping("/files")
+@Slf4j
 public class FileController {
 
     // 文件上传存储路径
@@ -46,16 +47,16 @@ public class FileController {
             }
             // 文件存储形式:时间戳-文件名
             FileUtil.writeBytes(file.getBytes(), filePath + flag + "-" + fileName);  // ***/manager/files/1697438073596-avatar.png
-            System.out.println(fileName + "--上传成功");
-
+//            System.out.println(fileName + "--上传成功");
+            log.info(fileName + "--上传成功");
         } catch (Exception e) {
             System.err.println(fileName + "--文件上传失败");
+            log.error(fileName + "--文件上传失败");
         }
         String http = "http://" + ip + ":" + port + "/files/";
         return Result.success(http + flag + "-" + fileName);  //  http://localhost:9090/files/1697438073596-avatar.png
     }
 
-
     /**
      * 获取文件
      *
@@ -85,11 +86,11 @@ public class FileController {
      *
      * @param flag
      */
-    @DeleteMapping("/{flag}")
-    public void delFile(@PathVariable String flag) {
+    @DeleteMapping("/delete/{flag}")
+    public Result delFile(@PathVariable String flag) {
         FileUtil.del(filePath + flag);
-        System.out.println("删除文件" + flag + "成功");
+//        System.out.println("删除文件" + flag + "成功");
+        log.info("删除文件" + flag + "成功");
+        return Result.success();
     }
-
-
 }

+ 14 - 1
springboot/src/main/java/com/example/controller/SaleStatementController.java

@@ -14,7 +14,6 @@ import java.util.List;
 @RestController
 @RequestMapping("/saleStatement")
 public class SaleStatementController {
-
     @Resource
     private SaleStatementService saleStatementService;
 
@@ -83,4 +82,18 @@ public class SaleStatementController {
         return Result.success(page);
     }
 
+    /**
+     *
+     * @param id
+     * @param day
+     * @return
+     */
+    @RequestMapping(
+            path = {"/{id}/{day}"},
+            method = {RequestMethod.GET}
+    )
+    public Result selectByDay(@PathVariable Integer id ,@PathVariable Integer day){
+
+        return Result.success(id + " "+day);
+    }
 }

+ 157 - 0
springboot/src/main/java/com/example/controller/uploadVideoController.java

@@ -0,0 +1,157 @@
+package com.example.controller;
+
+
+import com.example.common.Result;
+import com.example.common.enums.ResultCodeEnum;
+import com.example.entity.Chunk;
+import com.example.entity.Video;
+import com.example.mapper.VideoMapper;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletResponse;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.RandomAccessFile;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.UUID;
+
+/**
+ * 功能:前端视频上传
+ *
+ * @author 熊浩毅
+ * @time 2024-04-17 19:31
+ * @Description
+ */
+@RestController
+@RequestMapping("/video")
+@Slf4j
+public class uploadVideoController {
+    // 文件上传存储路径
+    private static final String filePath = System.getProperty("user.dir") + "/files/videos";
+
+    @Value("${server.port:8080}")
+    private String port;
+
+    @Value("${ip:localhost}")
+    private String ip;
+    @Resource
+    private VideoMapper videoMapper;
+    /**
+     * 分片上传
+     * 处理文件上传POST请求
+     * 将上传的文件存放到服务器内
+     *
+     * @param chunk    文件块
+     * @param response 响应
+     * @return 上传响应状态
+     * * 每一个上传块都会包含如下分块信息:
+     * * chunkNumber: 当前块的次序,第一个块是 1,注意不是从 0 开始的。
+     * * totalChunks: 文件被分成块的总数。
+     * * chunkSize: 分块大小,根据 totalSize 和这个值你就可以计算出总共的块数。注意最后一块的大小可能会比这个要大。
+     * * currentChunkSize: 当前块的大小,实际大小。
+     * * totalSize: 文件总大小。
+     * * identifier: 这个就是每个文件的唯一标示。
+     * * filename: 文件名。
+     * * relativePath: 文件夹上传的时候文件的相对路径属性。
+     * * 一个分块可以被上传多次,当然这肯定不是标准行为,但是在实际上传过程中是可能发生这种事情的,这种重传也是本库的特性之一。
+     * *
+     * * 根据响应码认为成功或失败的:
+     * * 200 文件上传完成
+     * * 201 文加快上传成功
+     * * 500 第一块上传失败,取消整个文件上传
+     * * 507 服务器出错自动重试该文件块上传
+     */
+    @PostMapping("/fileUpload")
+    public Result uploadPost(@RequestBody Chunk chunk, HttpServletResponse response)
+    {
+        log.info(chunk.toString());
+        // 设置
+//        Path absolutePath = Paths.get("").toAbsolutePath().resolve(saveVideoFilePath.substring(2) + "/videos");
+//        String absoluteDiskPath = absolutePath.toString();
+        String SavePath = filePath;
+        File file = new File(SavePath, chunk.getFilename());
+        if (!file.getParentFile().exists())
+        {
+            //如果不存在,就创建一个这个路径的文件夹。
+            file.getParentFile().mkdirs();
+        }
+        //第一个块,则新建文件
+        if (chunk.getChunkNumber() == 1 && !file.exists())
+        {
+            try
+            {
+                file.createNewFile();
+            }
+            catch (IOException e)
+            {
+                response.setStatus(500);
+                return Result.error(ResultCodeEnum.UPLOAD_ERROR);
+            }
+        }
+
+        //进行写文件操作
+        try (
+                //将块文件写入文件中
+                InputStream fos = chunk.getFile().getInputStream(); RandomAccessFile raf = new RandomAccessFile(file, "rw"))
+        {
+            int len = -1;
+            byte[] buffer = new byte[1024];
+            raf.seek((chunk.getChunkNumber() - 1) * chunk.getChunkSize());
+            while ((len = fos.read(buffer)) != -1)
+            {
+                raf.write(buffer, 0, len);
+            }
+        }
+        catch (IOException e)
+        {
+            e.printStackTrace();
+            if (chunk.getChunkNumber() == 1)
+            {
+                file.delete();
+            }
+            response.setStatus(507);
+            return Result.error(ResultCodeEnum.WRITE_ERROR);
+        }
+        // 全部加载完成了数据块
+        if (chunk.getChunkNumber().equals(chunk.getTotalChunks()))
+        {
+            response.setStatus(200);
+            // TODO 向数据库中保存上传信息
+            String videoNameText = chunk.getFilename();
+            // 获取文件后缀,因此此后端代码可接收一切文件,上传格式前端限定
+            String fileExt = videoNameText.substring(videoNameText.lastIndexOf(".") + 1).toLowerCase();
+            // UUID(全局唯一标识符)randomUUID(随机生成标识符)toString(转成字符串)replaceAll(替换字符方法,因为随机生成的里面包括了 - ,这里意思是把 - 全部换成空)
+            String pikId = UUID.randomUUID().toString().replaceAll("-", "");
+            // 视频名字拼接:唯一标识符加上点,再加上上面的视频后缀也就是MP4之类的。就组成了现在的视频名字,比如这样:c7bbc1f9664947a287d35dd7cdc48a95.mp4
+            String newVideoName = pikId + "." + fileExt;
+            System.out.println("原文件名:" + videoNameText);
+            System.out.println("重构文件名防止上传同名文件:" + newVideoName);
+            // 把已保存的原文件名文件改成新文件名
+            try
+            {
+                Files.move(Paths.get(SavePath + "/" + videoNameText), Paths.get(SavePath + "/" + newVideoName));
+            }
+            catch (IOException e)
+            {
+                return Result.error();
+            }
+            //保存视频url路径地址
+            String videoUrl = SavePath + "/" + newVideoName;
+            //调用数据库接口插入数据库方法save,把视频原名,视频路径,视频的唯一标识码传进去存到数据库内
+            // TODO
+            //videoUploadMapper.save(videoNameText, videoUrl, newVideoName);
+            videoMapper.insert(new Video(newVideoName,videoUrl,newVideoName));
+            return Result.success();
+        }
+        else
+        {
+            response.setStatus(201);
+            return Result.success();
+        }
+    }
+}

+ 30 - 0
springboot/src/main/java/com/example/entity/Audits.java

@@ -10,6 +10,8 @@ public class Audits implements Serializable {
 
     /** id */
     private Integer id;
+    /** 店铺地址 */
+    private String storeAddress;
     /** 身份证 */
     private String idcard;
     /** 营业执照url */
@@ -22,6 +24,10 @@ public class Audits implements Serializable {
     private String cameraUrl;
     /** 店铺申请人id用adminstore的id */
     private Integer storeId;
+    /** 店铺主名称 */
+    private String keeperName;
+    /** 审核状态 */
+    private String state;
 
     public Integer getId() {
         return id;
@@ -31,6 +37,14 @@ public class Audits implements Serializable {
         this.id = id;
     }
 
+    public String getStoreAddress() {
+        return storeAddress;
+    }
+
+    public void setStoreAddress(String storeAddress) {
+        this.storeAddress = storeAddress;
+    }
+
     public String getIdcard() {
         return idcard;
     }
@@ -79,4 +93,20 @@ public class Audits implements Serializable {
         this.storeId = storeId;
     }
 
+    public String getKeeperName() {
+        return keeperName;
+    }
+
+    public void setKeeperName(String keeperName) {
+        this.keeperName = keeperName;
+    }
+
+    public String getState() {
+        return state;
+    }
+
+    public void setState(String state) {
+        this.state = state;
+    }
+
 }

+ 126 - 0
springboot/src/main/java/com/example/entity/Chunk.java

@@ -0,0 +1,126 @@
+package com.example.entity;
+
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.Serializable;
+
+/**
+ *  文件块 entity
+ * @author 熊浩毅
+ * @time 2024-04-17 22:16
+ * @Description
+ */
+public class Chunk implements Serializable {
+    /**
+     * 当前文件块,从1开始
+     */
+    private Integer chunkNumber;
+    /**
+     * 分块大小
+     */
+    private Long chunkSize;
+    /**
+     * 当前分块大小
+     */
+    private Long currentChunkSize;
+    /**
+     * 总大小
+     */
+    private Long totalSize;
+    /**
+     * 文件标识
+     */
+    private String identifier;
+    /**
+     * 文件名
+     */
+    private String filename;
+    /**
+     * 相对路径
+     */
+    private String relativePath;
+    /**
+     * 总块数
+     */
+    private Integer totalChunks;
+
+    /**
+     * 二进制文件
+     */
+    private MultipartFile file;
+
+    ///  GET 和  SET
+
+
+    public Integer getChunkNumber() {
+        return chunkNumber;
+    }
+
+    public void setChunkNumber(Integer chunkNumber) {
+        this.chunkNumber = chunkNumber;
+    }
+
+    public Long getChunkSize() {
+        return chunkSize;
+    }
+
+    public void setChunkSize(Long chunkSize) {
+        this.chunkSize = chunkSize;
+    }
+
+    public Long getCurrentChunkSize() {
+        return currentChunkSize;
+    }
+
+    public void setCurrentChunkSize(Long currentChunkSize) {
+        this.currentChunkSize = currentChunkSize;
+    }
+
+    public Long getTotalSize() {
+        return totalSize;
+    }
+
+    public void setTotalSize(Long totalSize) {
+        this.totalSize = totalSize;
+    }
+
+    public String getIdentifier() {
+        return identifier;
+    }
+
+    public void setIdentifier(String identifier) {
+        this.identifier = identifier;
+    }
+
+    public String getFilename() {
+        return filename;
+    }
+
+    public void setFilename(String filename) {
+        this.filename = filename;
+    }
+
+    public String getRelativePath() {
+        return relativePath;
+    }
+
+    public void setRelativePath(String relativePath) {
+        this.relativePath = relativePath;
+    }
+
+    public Integer getTotalChunks() {
+        return totalChunks;
+    }
+
+    public void setTotalChunks(Integer totalChunks) {
+        this.totalChunks = totalChunks;
+    }
+
+    public MultipartFile getFile() {
+        return file;
+    }
+
+    public void setFile(MultipartFile file) {
+        this.file = file;
+    }
+}

+ 56 - 0
springboot/src/main/java/com/example/entity/Video.java

@@ -0,0 +1,56 @@
+package com.example.entity;
+
+/**
+ * 视频数据库实体类
+ *
+ * @author 熊浩毅
+ * @time 2024-04-17 22:19
+ * @Description
+ */
+public class Video {
+    private int id;
+    private String videoName;
+    private String videoUrl;
+    private String videoUUID;
+
+    public int getId() {
+        return id;
+    }
+
+    public void setId(int id) {
+        this.id = id;
+    }
+
+    public String getVideoName() {
+        return videoName;
+    }
+
+    public void setVideoName(String videoName) {
+        this.videoName = videoName;
+    }
+
+    public String getVideoUrl() {
+        return videoUrl;
+    }
+
+    public void setVideoUrl(String videoUrl) {
+        this.videoUrl = videoUrl;
+    }
+
+    public String getVideoUUID() {
+        return videoUUID;
+    }
+
+    public void setVideoUUID(String videoUUID) {
+        this.videoUUID = videoUUID;
+    }
+
+    public Video() {
+    }
+
+    public Video(String videoName, String videoUrl, String videoUUID) {
+        this.videoName = videoName;
+        this.videoUrl = videoUrl;
+        this.videoUUID = videoUUID;
+    }
+}

+ 36 - 0
springboot/src/main/java/com/example/mapper/VideoMapper.java

@@ -0,0 +1,36 @@
+package com.example.mapper;
+
+import com.example.entity.Video;
+import java.util.List;
+
+/**
+ * 操作video相关数据接口
+*/
+public interface VideoMapper {
+
+    /**
+      * 新增
+    */
+    int insert(Video video);
+
+    /**
+      * 删除
+    */
+    int deleteById(Integer id);
+
+    /**
+      * 修改
+    */
+    int updateById(Video video);
+
+    /**
+      * 根据ID查询
+    */
+    Video selectById(Integer id);
+
+    /**
+      * 查询所有
+    */
+    List<Video> selectAll(Video video);
+
+}

+ 1 - 1
springboot/src/main/java/com/example/utils/generate/CodeGenerator.java

@@ -32,7 +32,7 @@ public class CodeGenerator {
      * 主类  生成代码
      */
     public static void main(String[] args) {
-        String tableName = "user";
+        String tableName = "audits";
         // 生成Entity
         EntityGenerator.generate(tableName);
         // 生成Mapper #

+ 19 - 1
springboot/src/main/resources/mapper/AuditsMapper.xml

@@ -5,7 +5,7 @@
 <mapper namespace="com.example.mapper.AuditsMapper">
 
     <sql id="Base_Column_List">
-        id,idcard,business_license,reason,pics_url,camera_url,store_id
+        id,store_address,idcard,business_license,reason,pics_url,camera_url,store_id,keeper_name,state
     </sql>
 
     <select id="selectAll" resultType="com.example.entity.Audits">
@@ -14,12 +14,15 @@
         from audits
         <where>
             <if test="id != null"> and id = #{id}</if>
+            <if test="storeAddress != null"> and store_address like concat('%', #{storeAddress}, '%')</if>
             <if test="idcard != null"> and idcard like concat('%', #{idcard}, '%')</if>
             <if test="businessLicense != null"> and business_license like concat('%', #{businessLicense}, '%')</if>
             <if test="reason != null"> and reason like concat('%', #{reason}, '%')</if>
             <if test="picsUrl != null"> and pics_url like concat('%', #{picsUrl}, '%')</if>
             <if test="cameraUrl != null"> and camera_url like concat('%', #{cameraUrl}, '%')</if>
             <if test="storeId != null"> and store_id = #{storeId}</if>
+            <if test="keeperName != null"> and keeper_name like concat('%', #{keeperName}, '%')</if>
+            <if test="state != null"> and state like concat('%', #{state}, '%')</if>
         </where>
         order by id desc
     </select>
@@ -40,27 +43,36 @@
         insert into audits
         <trim prefix="(" suffix=")" suffixOverrides=",">
             <if test="id != null">id,</if>
+            <if test="storeAddress != null">store_address,</if>
             <if test="idcard != null">idcard,</if>
             <if test="businessLicense != null">business_license,</if>
             <if test="reason != null">reason,</if>
             <if test="picsUrl != null">pics_url,</if>
             <if test="cameraUrl != null">camera_url,</if>
             <if test="storeId != null">store_id,</if>
+            <if test="keeperName != null">keeper_name,</if>
+            <if test="state != null">state,</if>
         </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
             <if test="id != null">#{id},</if>
+            <if test="storeAddress != null">#{storeAddress},</if>
             <if test="idcard != null">#{idcard},</if>
             <if test="businessLicense != null">#{businessLicense},</if>
             <if test="reason != null">#{reason},</if>
             <if test="picsUrl != null">#{picsUrl},</if>
             <if test="cameraUrl != null">#{cameraUrl},</if>
             <if test="storeId != null">#{storeId},</if>
+            <if test="keeperName != null">#{keeperName},</if>
+            <if test="state != null">#{state},</if>
         </trim>
     </insert>
 
     <update id="updateById" parameterType="com.example.entity.Audits">
         update audits
         <set>
+            <if test="storeAddress != null">
+                store_address = #{storeAddress},
+            </if>
             <if test="idcard != null">
                 idcard = #{idcard},
             </if>
@@ -79,6 +91,12 @@
             <if test="storeId != null">
                 store_id = #{storeId},
             </if>
+            <if test="keeperName != null">
+                keeper_name = #{keeperName},
+            </if>
+            <if test="state != null">
+                state = #{state},
+            </if>
         </set>
         where id = #{id} 
     </update>

+ 68 - 0
springboot/src/main/resources/mapper/VideoMapper.xml

@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper
+        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.example.mapper.VideoMapper">
+
+    <sql id="Base_Column_List">
+        id,video_name,video_url,video_uuid
+    </sql>
+
+    <select id="selectAll" resultType="com.example.entity.Video">
+        select
+        <include refid="Base_Column_List" />
+        from video
+        <where>
+            <if test="id != null"> and id = #{id}</if>
+            <if test="videoName != null"> and video_name like concat('%', #{videoName}, '%')</if>
+            <if test="videoUrl != null"> and video_url like concat('%', #{videoUrl}, '%')</if>
+            <if test="videoUuid != null"> and video_uuid like concat('%', #{videoUuid}, '%')</if>
+        </where>
+        order by id desc
+    </select>
+
+    <select id="selectById" resultType="com.example.entity.Video">
+        select
+        <include refid="Base_Column_List" />
+        from video
+        where id = #{id}
+    </select>
+
+    <delete id="deleteById">
+        delete from video
+        where  id = #{id}
+    </delete>
+
+    <insert id="insert" parameterType="com.example.entity.Video" useGeneratedKeys="true">
+        insert into video
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="id != null">id,</if>
+            <if test="videoName != null">video_name,</if>
+            <if test="videoUrl != null">video_url,</if>
+            <if test="videoUuid != null">video_uuid,</if>
+        </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="id != null">#{id},</if>
+            <if test="videoName != null">#{videoName},</if>
+            <if test="videoUrl != null">#{videoUrl},</if>
+            <if test="videoUuid != null">#{videoUuid},</if>
+        </trim>
+    </insert>
+
+    <update id="updateById" parameterType="com.example.entity.Video">
+        update video
+        <set>
+            <if test="videoName != null">
+                video_name = #{videoName},
+            </if>
+            <if test="videoUrl != null">
+                video_url = #{videoUrl},
+            </if>
+            <if test="videoUuid != null">
+                video_uuid = #{videoUuid},
+            </if>
+        </set>
+        where id = #{id} 
+    </update>
+
+</mapper>

+ 25 - 5
springboot/src/main/resources/sql/fruit_farmer.sql

@@ -11,7 +11,7 @@
  Target Server Version : 80033
  File Encoding         : 65001
 
- Date: 16/04/2024 16:48:46
+ Date: 19/04/2024 20:42:44
 */
 
 SET NAMES utf8mb4;
@@ -96,19 +96,23 @@ INSERT INTO `adminstore` VALUES (7, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NU
 DROP TABLE IF EXISTS `audits`;
 CREATE TABLE `audits`  (
   `id` int NOT NULL AUTO_INCREMENT COMMENT 'id',
+  `store_address` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '店铺地址',
   `idcard` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '身份证',
   `business_license` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '营业执照url',
   `reason` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '申请理由',
   `pics_url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '市区营业图片',
   `camera_url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '监控地址',
   `store_id` int NULL DEFAULT NULL COMMENT '店铺申请人id用adminstore的id',
+  `keeper_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '店铺主名称',
+  `state` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '审核状态',
   PRIMARY KEY (`id`) USING BTREE
-) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '申请审核表' ROW_FORMAT = Dynamic;
+) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '申请审核表' ROW_FORMAT = Dynamic;
 
 -- ----------------------------
 -- Records of audits
 -- ----------------------------
-INSERT INTO `audits` VALUES (1, '36012220030714xxxx', '1', '想开一个果茶店铺', NULL, NULL, NULL);
+INSERT INTO `audits` VALUES (1, NULL, '36012220030714xxxx', '1', '想开一个果茶店铺', NULL, NULL, NULL, NULL, NULL);
+INSERT INTO `audits` VALUES (2, '山西省长治市潞城区啊啊啊', '', 'http://localhost:2441/files/1713517958135-head.jpg', '我要赚米了', 'http://localhost:2441/files/1713457745729-head.jpg', NULL, NULL, '熊浩毅', '待审核');
 
 -- ----------------------------
 -- Table structure for notice
@@ -154,7 +158,7 @@ CREATE TABLE `orders`  (
   CONSTRAINT `orders_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT,
   CONSTRAINT `orders_ibfk_2` FOREIGN KEY (`address_id`) REFERENCES `address` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT,
   CONSTRAINT `orders_ibfk_3` FOREIGN KEY (`order_type_id`) REFERENCES `product_type` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT
-) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '订单表' ROW_FORMAT = Dynamic;
+) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '订单表' ROW_FORMAT = Dynamic;
 
 -- ----------------------------
 -- Records of orders
@@ -209,7 +213,7 @@ CREATE TABLE `sale_statement`  (
   `product_id` int NULL DEFAULT NULL COMMENT '商品id',
   `amount` decimal(10, 2) NULL DEFAULT NULL COMMENT '金额',
   PRIMARY KEY (`id`, `shop_id`) USING BTREE
-) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '销量表' ROW_FORMAT = Dynamic;
+) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '销量表' ROW_FORMAT = Dynamic;
 
 -- ----------------------------
 -- Records of sale_statement
@@ -261,4 +265,20 @@ INSERT INTO `user` VALUES (1, 'user', '123', '爱喝茶的小淮', NULL, 'USER',
 INSERT INTO `user` VALUES (2, 'ry', '123', '喝奶茶的瑶妹', NULL, 'USER', '男', '18779165101', 9934.00, NULL, NULL);
 INSERT INTO `user` VALUES (17, '淮小瑞1708502748', 'oYA-Q58ysBMJZymzkAQpBRx_Isc0', '淮小瑞1708502748', NULL, 'USER', NULL, NULL, 0.00, 'oYA-Q58ysBMJZymzkAQpBRx_Isc0', NULL);
 
+-- ----------------------------
+-- Table structure for video
+-- ----------------------------
+DROP TABLE IF EXISTS `video`;
+CREATE TABLE `video`  (
+  `id` int NOT NULL COMMENT 'id',
+  `video_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '视频名称',
+  `video_url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT ' 视频存储路径',
+  `video_uuid` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '视频UUID',
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '视频表' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Records of video
+-- ----------------------------
+
 SET FOREIGN_KEY_CHECKS = 1;

BIN=BIN
springboot/target/classes/com/example/common/enums/AuditState.class


BIN=BIN
springboot/target/classes/com/example/common/enums/ResultCodeEnum.class


BIN=BIN
springboot/target/classes/com/example/controller/FileController.class


BIN=BIN
springboot/target/classes/com/example/controller/SaleStatementController.class


BIN=BIN
springboot/target/classes/com/example/controller/uploadVideoController.class


BIN=BIN
springboot/target/classes/com/example/entity/Audits.class


BIN=BIN
springboot/target/classes/com/example/entity/Chunk.class


BIN=BIN
springboot/target/classes/com/example/entity/Video.class


BIN=BIN
springboot/target/classes/com/example/mapper/VideoMapper.class


BIN=BIN
springboot/target/classes/com/example/utils/generate/CodeGenerator.class


+ 19 - 1
springboot/target/classes/mapper/AuditsMapper.xml

@@ -5,7 +5,7 @@
 <mapper namespace="com.example.mapper.AuditsMapper">
 
     <sql id="Base_Column_List">
-        id,idcard,business_license,reason,pics_url,camera_url,store_id
+        id,store_address,idcard,business_license,reason,pics_url,camera_url,store_id,keeper_name,state
     </sql>
 
     <select id="selectAll" resultType="com.example.entity.Audits">
@@ -14,12 +14,15 @@
         from audits
         <where>
             <if test="id != null"> and id = #{id}</if>
+            <if test="storeAddress != null"> and store_address like concat('%', #{storeAddress}, '%')</if>
             <if test="idcard != null"> and idcard like concat('%', #{idcard}, '%')</if>
             <if test="businessLicense != null"> and business_license like concat('%', #{businessLicense}, '%')</if>
             <if test="reason != null"> and reason like concat('%', #{reason}, '%')</if>
             <if test="picsUrl != null"> and pics_url like concat('%', #{picsUrl}, '%')</if>
             <if test="cameraUrl != null"> and camera_url like concat('%', #{cameraUrl}, '%')</if>
             <if test="storeId != null"> and store_id = #{storeId}</if>
+            <if test="keeperName != null"> and keeper_name like concat('%', #{keeperName}, '%')</if>
+            <if test="state != null"> and state like concat('%', #{state}, '%')</if>
         </where>
         order by id desc
     </select>
@@ -40,27 +43,36 @@
         insert into audits
         <trim prefix="(" suffix=")" suffixOverrides=",">
             <if test="id != null">id,</if>
+            <if test="storeAddress != null">store_address,</if>
             <if test="idcard != null">idcard,</if>
             <if test="businessLicense != null">business_license,</if>
             <if test="reason != null">reason,</if>
             <if test="picsUrl != null">pics_url,</if>
             <if test="cameraUrl != null">camera_url,</if>
             <if test="storeId != null">store_id,</if>
+            <if test="keeperName != null">keeper_name,</if>
+            <if test="state != null">state,</if>
         </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
             <if test="id != null">#{id},</if>
+            <if test="storeAddress != null">#{storeAddress},</if>
             <if test="idcard != null">#{idcard},</if>
             <if test="businessLicense != null">#{businessLicense},</if>
             <if test="reason != null">#{reason},</if>
             <if test="picsUrl != null">#{picsUrl},</if>
             <if test="cameraUrl != null">#{cameraUrl},</if>
             <if test="storeId != null">#{storeId},</if>
+            <if test="keeperName != null">#{keeperName},</if>
+            <if test="state != null">#{state},</if>
         </trim>
     </insert>
 
     <update id="updateById" parameterType="com.example.entity.Audits">
         update audits
         <set>
+            <if test="storeAddress != null">
+                store_address = #{storeAddress},
+            </if>
             <if test="idcard != null">
                 idcard = #{idcard},
             </if>
@@ -79,6 +91,12 @@
             <if test="storeId != null">
                 store_id = #{storeId},
             </if>
+            <if test="keeperName != null">
+                keeper_name = #{keeperName},
+            </if>
+            <if test="state != null">
+                state = #{state},
+            </if>
         </set>
         where id = #{id} 
     </update>

+ 68 - 0
springboot/target/classes/mapper/VideoMapper.xml

@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper
+        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.example.mapper.VideoMapper">
+
+    <sql id="Base_Column_List">
+        id,video_name,video_url,video_uuid
+    </sql>
+
+    <select id="selectAll" resultType="com.example.entity.Video">
+        select
+        <include refid="Base_Column_List" />
+        from video
+        <where>
+            <if test="id != null"> and id = #{id}</if>
+            <if test="videoName != null"> and video_name like concat('%', #{videoName}, '%')</if>
+            <if test="videoUrl != null"> and video_url like concat('%', #{videoUrl}, '%')</if>
+            <if test="videoUuid != null"> and video_uuid like concat('%', #{videoUuid}, '%')</if>
+        </where>
+        order by id desc
+    </select>
+
+    <select id="selectById" resultType="com.example.entity.Video">
+        select
+        <include refid="Base_Column_List" />
+        from video
+        where id = #{id}
+    </select>
+
+    <delete id="deleteById">
+        delete from video
+        where  id = #{id}
+    </delete>
+
+    <insert id="insert" parameterType="com.example.entity.Video" useGeneratedKeys="true">
+        insert into video
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="id != null">id,</if>
+            <if test="videoName != null">video_name,</if>
+            <if test="videoUrl != null">video_url,</if>
+            <if test="videoUuid != null">video_uuid,</if>
+        </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="id != null">#{id},</if>
+            <if test="videoName != null">#{videoName},</if>
+            <if test="videoUrl != null">#{videoUrl},</if>
+            <if test="videoUuid != null">#{videoUuid},</if>
+        </trim>
+    </insert>
+
+    <update id="updateById" parameterType="com.example.entity.Video">
+        update video
+        <set>
+            <if test="videoName != null">
+                video_name = #{videoName},
+            </if>
+            <if test="videoUrl != null">
+                video_url = #{videoUrl},
+            </if>
+            <if test="videoUuid != null">
+                video_uuid = #{videoUuid},
+            </if>
+        </set>
+        where id = #{id} 
+    </update>
+
+</mapper>

+ 5 - 0
uniapp/.idea/.gitignore

@@ -0,0 +1,5 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/

+ 8 - 0
uniapp/.idea/modules.xml

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ProjectModuleManager">
+    <modules>
+      <module fileurl="file://$PROJECT_DIR$/.idea/uniapp.iml" filepath="$PROJECT_DIR$/.idea/uniapp.iml" />
+    </modules>
+  </component>
+</project>

+ 12 - 0
uniapp/.idea/uniapp.iml

@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="WEB_MODULE" version="4">
+  <component name="NewModuleRootManager">
+    <content url="file://$MODULE_DIR$">
+      <excludeFolder url="file://$MODULE_DIR$/.tmp" />
+      <excludeFolder url="file://$MODULE_DIR$/temp" />
+      <excludeFolder url="file://$MODULE_DIR$/tmp" />
+    </content>
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="sourceFolder" forTests="false" />
+  </component>
+</module>

+ 6 - 0
uniapp/.idea/vcs.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="VcsDirectoryMappings">
+    <mapping directory="$PROJECT_DIR$/.." vcs="Git" />
+  </component>
+</project>

+ 343 - 31
vue/package-lock.json

@@ -10,7 +10,10 @@
       "dependencies": {
         "axios": "^1.5.1",
         "core-js": "^3.8.3",
+        "echart": "^0.1.3",
+        "element-china-area-data": "^6.1.0",
         "element-ui": "^2.15.14",
+        "spark-md5": "^3.0.2",
         "vue": "^2.6.14",
         "vue-router": "^3.5.1"
       },
@@ -3017,7 +3020,6 @@
       "version": "1.3.8",
       "resolved": "https://registry.npmmirror.com/accepts/-/accepts-1.3.8.tgz",
       "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
-      "dev": true,
       "dependencies": {
         "mime-types": "~2.1.34",
         "negotiator": "0.6.3"
@@ -3166,8 +3168,7 @@
     "node_modules/any-promise": {
       "version": "1.3.0",
       "resolved": "https://registry.npmmirror.com/any-promise/-/any-promise-1.3.0.tgz",
-      "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==",
-      "dev": true
+      "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A=="
     },
     "node_modules/anymatch": {
       "version": "3.1.3",
@@ -3558,6 +3559,18 @@
         "node": ">= 0.8"
       }
     },
+    "node_modules/cache-content-type": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmmirror.com/cache-content-type/-/cache-content-type-1.0.1.tgz",
+      "integrity": "sha512-IKufZ1o4Ut42YUrZSo8+qnMTrFuKkvyoLXUywKz9GJ5BrhOFGhLdkx9sG4KAnVvbY6kEcSFjLQul+DVmBm2bgA==",
+      "dependencies": {
+        "mime-types": "^2.1.18",
+        "ylru": "^1.2.0"
+      },
+      "engines": {
+        "node": ">= 6.0.0"
+      }
+    },
     "node_modules/call-bind": {
       "version": "1.0.2",
       "resolved": "https://registry.npmmirror.com/call-bind/-/call-bind-1.0.2.tgz",
@@ -3637,6 +3650,11 @@
         "node": ">=4"
       }
     },
+    "node_modules/china-division": {
+      "version": "2.7.0",
+      "resolved": "https://registry.npmmirror.com/china-division/-/china-division-2.7.0.tgz",
+      "integrity": "sha512-4uUPAT+1WfqDh5jytq7omdCmHNk3j+k76zEG/2IqaGcYB90c2SwcixttcypdsZ3T/9tN1TTpBDoeZn+Yw/qBEA=="
+    },
     "node_modules/chokidar": {
       "version": "3.5.3",
       "resolved": "https://registry.npmmirror.com/chokidar/-/chokidar-3.5.3.tgz",
@@ -3857,6 +3875,15 @@
         "node": ">=0.10.0"
       }
     },
+    "node_modules/co": {
+      "version": "4.6.0",
+      "resolved": "https://registry.npmmirror.com/co/-/co-4.6.0.tgz",
+      "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==",
+      "engines": {
+        "iojs": ">= 1.0.0",
+        "node": ">= 0.12.0"
+      }
+    },
     "node_modules/color-convert": {
       "version": "1.9.3",
       "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-1.9.3.tgz",
@@ -3993,7 +4020,6 @@
       "version": "0.5.4",
       "resolved": "https://registry.npmmirror.com/content-disposition/-/content-disposition-0.5.4.tgz",
       "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==",
-      "dev": true,
       "dependencies": {
         "safe-buffer": "5.2.1"
       },
@@ -4005,7 +4031,6 @@
       "version": "1.0.5",
       "resolved": "https://registry.npmmirror.com/content-type/-/content-type-1.0.5.tgz",
       "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
-      "dev": true,
       "engines": {
         "node": ">= 0.6"
       }
@@ -4031,6 +4056,18 @@
       "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==",
       "dev": true
     },
+    "node_modules/cookies": {
+      "version": "0.9.1",
+      "resolved": "https://registry.npmmirror.com/cookies/-/cookies-0.9.1.tgz",
+      "integrity": "sha512-TG2hpqe4ELx54QER/S3HQ9SRVnQnGBtKUz5bLQWtYAQ+o6GpgMs6sYUvaiJjVxb+UXwhRhAEP3m7LbsIZ77Hmw==",
+      "dependencies": {
+        "depd": "~2.0.0",
+        "keygrip": "~1.1.0"
+      },
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
     "node_modules/copy-webpack-plugin": {
       "version": "9.1.0",
       "resolved": "https://registry.npmmirror.com/copy-webpack-plugin/-/copy-webpack-plugin-9.1.0.tgz",
@@ -4419,7 +4456,6 @@
       "version": "4.3.4",
       "resolved": "https://registry.npmmirror.com/debug/-/debug-4.3.4.tgz",
       "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
-      "dev": true,
       "dependencies": {
         "ms": "2.1.2"
       },
@@ -4432,6 +4468,11 @@
         }
       }
     },
+    "node_modules/deep-equal": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmmirror.com/deep-equal/-/deep-equal-1.0.1.tgz",
+      "integrity": "sha512-bHtC0iYvWhyaTzvV3CZgPeZQqCOBGyGsVV7v4eevpdkLHfiSrXUdBG+qAuSz4RI70sszvjQ1QSZ98An1yNwpSw=="
+    },
     "node_modules/deepmerge": {
       "version": "1.5.2",
       "resolved": "https://registry.npmmirror.com/deepmerge/-/deepmerge-1.5.2.tgz",
@@ -4615,11 +4656,15 @@
         "node": ">=0.4.0"
       }
     },
+    "node_modules/delegates": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmmirror.com/delegates/-/delegates-1.0.0.tgz",
+      "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ=="
+    },
     "node_modules/depd": {
       "version": "2.0.0",
       "resolved": "https://registry.npmmirror.com/depd/-/depd-2.0.0.tgz",
       "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
-      "dev": true,
       "engines": {
         "node": ">= 0.8"
       }
@@ -4628,7 +4673,6 @@
       "version": "1.2.0",
       "resolved": "https://registry.npmmirror.com/destroy/-/destroy-1.2.0.tgz",
       "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==",
-      "dev": true,
       "engines": {
         "node": ">= 0.8",
         "npm": "1.2.8000 || >= 1.4.16"
@@ -4759,11 +4803,22 @@
         "node": ">=6.0.0"
       }
     },
+    "node_modules/echart": {
+      "version": "0.1.3",
+      "resolved": "https://registry.npmmirror.com/echart/-/echart-0.1.3.tgz",
+      "integrity": "sha512-DbTrEjHnYrSEqzRBkLhVs0T512ZZwSDW8hIE57lY2Rwui5j6sdFoO37W0tDq/Tb7Q25MaRAwiQMkMCzOX4FjWw==",
+      "dependencies": {
+        "koa": "^2.2.0",
+        "koa-router": "^7.1.1"
+      },
+      "bin": {
+        "mock": "bin/mock"
+      }
+    },
     "node_modules/ee-first": {
       "version": "1.1.1",
       "resolved": "https://registry.npmmirror.com/ee-first/-/ee-first-1.1.1.tgz",
-      "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==",
-      "dev": true
+      "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="
     },
     "node_modules/electron-to-chromium": {
       "version": "1.4.554",
@@ -4771,6 +4826,14 @@
       "integrity": "sha512-Q0umzPJjfBrrj8unkONTgbKQXzXRrH7sVV7D9ea2yBV3Oaogz991yhbpfvo2LMNkJItmruXTEzVpP9cp7vaIiQ==",
       "dev": true
     },
+    "node_modules/element-china-area-data": {
+      "version": "6.1.0",
+      "resolved": "https://registry.npmmirror.com/element-china-area-data/-/element-china-area-data-6.1.0.tgz",
+      "integrity": "sha512-IkpcjwQv2A/2AxFiSoaISZ+oMw1rZCPUSOg5sOCwT5jKc96TaawmKZeY81xfxXsO0QbKxU5LLc6AirhG52hUmg==",
+      "dependencies": {
+        "china-division": "^2.7.0"
+      }
+    },
     "node_modules/element-ui": {
       "version": "2.15.14",
       "resolved": "https://registry.npmmirror.com/element-ui/-/element-ui-2.15.14.tgz",
@@ -4806,7 +4869,6 @@
       "version": "1.0.2",
       "resolved": "https://registry.npmmirror.com/encodeurl/-/encodeurl-1.0.2.tgz",
       "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==",
-      "dev": true,
       "engines": {
         "node": ">= 0.8"
       }
@@ -4875,8 +4937,7 @@
     "node_modules/escape-html": {
       "version": "1.0.3",
       "resolved": "https://registry.npmmirror.com/escape-html/-/escape-html-1.0.3.tgz",
-      "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
-      "dev": true
+      "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="
     },
     "node_modules/escape-string-regexp": {
       "version": "1.0.5",
@@ -5246,7 +5307,6 @@
       "version": "0.5.2",
       "resolved": "https://registry.npmmirror.com/fresh/-/fresh-0.5.2.tgz",
       "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==",
-      "dev": true,
       "engines": {
         "node": ">= 0.6"
       }
@@ -5474,7 +5534,17 @@
       "version": "1.0.3",
       "resolved": "https://registry.npmmirror.com/has-symbols/-/has-symbols-1.0.3.tgz",
       "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
-      "dev": true,
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/has-tostringtag": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmmirror.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
+      "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
+      "dependencies": {
+        "has-symbols": "^1.0.3"
+      },
       "engines": {
         "node": ">= 0.4"
       }
@@ -5618,6 +5688,49 @@
         "entities": "^2.0.0"
       }
     },
+    "node_modules/http-assert": {
+      "version": "1.5.0",
+      "resolved": "https://registry.npmmirror.com/http-assert/-/http-assert-1.5.0.tgz",
+      "integrity": "sha512-uPpH7OKX4H25hBmU6G1jWNaqJGpTXxey+YOUizJUAgu0AjLUeC8D73hTrhvDS5D+GJN1DN1+hhc/eF/wpxtp0w==",
+      "dependencies": {
+        "deep-equal": "~1.0.1",
+        "http-errors": "~1.8.0"
+      },
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/http-assert/node_modules/depd": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmmirror.com/depd/-/depd-1.1.2.tgz",
+      "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==",
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/http-assert/node_modules/http-errors": {
+      "version": "1.8.1",
+      "resolved": "https://registry.npmmirror.com/http-errors/-/http-errors-1.8.1.tgz",
+      "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==",
+      "dependencies": {
+        "depd": "~1.1.2",
+        "inherits": "2.0.4",
+        "setprototypeof": "1.2.0",
+        "statuses": ">= 1.5.0 < 2",
+        "toidentifier": "1.0.1"
+      },
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/http-assert/node_modules/statuses": {
+      "version": "1.5.0",
+      "resolved": "https://registry.npmmirror.com/statuses/-/statuses-1.5.0.tgz",
+      "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==",
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
     "node_modules/http-deceiver": {
       "version": "1.2.7",
       "resolved": "https://registry.npmmirror.com/http-deceiver/-/http-deceiver-1.2.7.tgz",
@@ -5758,8 +5871,7 @@
     "node_modules/inherits": {
       "version": "2.0.4",
       "resolved": "https://registry.npmmirror.com/inherits/-/inherits-2.0.4.tgz",
-      "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
-      "dev": true
+      "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
     },
     "node_modules/ipaddr.js": {
       "version": "2.1.0",
@@ -5836,6 +5948,17 @@
         "node": ">=8"
       }
     },
+    "node_modules/is-generator-function": {
+      "version": "1.0.10",
+      "resolved": "https://registry.npmmirror.com/is-generator-function/-/is-generator-function-1.0.10.tgz",
+      "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==",
+      "dependencies": {
+        "has-tostringtag": "^1.0.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
     "node_modules/is-glob": {
       "version": "4.0.3",
       "resolved": "https://registry.npmmirror.com/is-glob/-/is-glob-4.0.3.tgz",
@@ -6058,6 +6181,17 @@
         "graceful-fs": "^4.1.6"
       }
     },
+    "node_modules/keygrip": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmmirror.com/keygrip/-/keygrip-1.1.0.tgz",
+      "integrity": "sha512-iYSchDJ+liQ8iwbSI2QqsQOvqv58eJCEanyJPJi+Khyu8smkcKSFUCbPwzFcL7YVtZ6eONjqRX/38caJ7QjRAQ==",
+      "dependencies": {
+        "tsscmp": "1.0.6"
+      },
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
     "node_modules/kind-of": {
       "version": "6.0.3",
       "resolved": "https://registry.npmmirror.com/kind-of/-/kind-of-6.0.3.tgz",
@@ -6076,6 +6210,164 @@
         "node": ">= 8"
       }
     },
+    "node_modules/koa": {
+      "version": "2.15.3",
+      "resolved": "https://registry.npmmirror.com/koa/-/koa-2.15.3.tgz",
+      "integrity": "sha512-j/8tY9j5t+GVMLeioLaxweJiKUayFhlGqNTzf2ZGwL0ZCQijd2RLHK0SLW5Tsko8YyyqCZC2cojIb0/s62qTAg==",
+      "dependencies": {
+        "accepts": "^1.3.5",
+        "cache-content-type": "^1.0.0",
+        "content-disposition": "~0.5.2",
+        "content-type": "^1.0.4",
+        "cookies": "~0.9.0",
+        "debug": "^4.3.2",
+        "delegates": "^1.0.0",
+        "depd": "^2.0.0",
+        "destroy": "^1.0.4",
+        "encodeurl": "^1.0.2",
+        "escape-html": "^1.0.3",
+        "fresh": "~0.5.2",
+        "http-assert": "^1.3.0",
+        "http-errors": "^1.6.3",
+        "is-generator-function": "^1.0.7",
+        "koa-compose": "^4.1.0",
+        "koa-convert": "^2.0.0",
+        "on-finished": "^2.3.0",
+        "only": "~0.0.2",
+        "parseurl": "^1.3.2",
+        "statuses": "^1.5.0",
+        "type-is": "^1.6.16",
+        "vary": "^1.1.2"
+      },
+      "engines": {
+        "node": "^4.8.4 || ^6.10.1 || ^7.10.1 || >= 8.1.4"
+      }
+    },
+    "node_modules/koa-compose": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmmirror.com/koa-compose/-/koa-compose-4.1.0.tgz",
+      "integrity": "sha512-8ODW8TrDuMYvXRwra/Kh7/rJo9BtOfPc6qO8eAfC80CnCvSjSl0bkRM24X6/XBBEyj0v1nRUQ1LyOy3dbqOWXw=="
+    },
+    "node_modules/koa-convert": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmmirror.com/koa-convert/-/koa-convert-2.0.0.tgz",
+      "integrity": "sha512-asOvN6bFlSnxewce2e/DK3p4tltyfC4VM7ZwuTuepI7dEQVcvpyFuBcEARu1+Hxg8DIwytce2n7jrZtRlPrARA==",
+      "dependencies": {
+        "co": "^4.6.0",
+        "koa-compose": "^4.1.0"
+      },
+      "engines": {
+        "node": ">= 10"
+      }
+    },
+    "node_modules/koa-router": {
+      "version": "7.4.0",
+      "resolved": "https://registry.npmmirror.com/koa-router/-/koa-router-7.4.0.tgz",
+      "integrity": "sha512-IWhaDXeAnfDBEpWS6hkGdZ1ablgr6Q6pGdXCyK38RbzuH4LkUOpPqPw+3f8l8aTDrQmBQ7xJc0bs2yV4dzcO+g==",
+      "deprecated": "**IMPORTANT 10x+ PERFORMANCE UPGRADE**: Please upgrade to v12.0.1+ as we have fixed an issue with debuglog causing 10x slower router benchmark performance, see https://github.com/koajs/router/pull/173",
+      "dependencies": {
+        "debug": "^3.1.0",
+        "http-errors": "^1.3.1",
+        "koa-compose": "^3.0.0",
+        "methods": "^1.0.1",
+        "path-to-regexp": "^1.1.1",
+        "urijs": "^1.19.0"
+      },
+      "engines": {
+        "node": ">= 4"
+      }
+    },
+    "node_modules/koa-router/node_modules/debug": {
+      "version": "3.2.7",
+      "resolved": "https://registry.npmmirror.com/debug/-/debug-3.2.7.tgz",
+      "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+      "dependencies": {
+        "ms": "^2.1.1"
+      }
+    },
+    "node_modules/koa-router/node_modules/depd": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmmirror.com/depd/-/depd-1.1.2.tgz",
+      "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==",
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/koa-router/node_modules/http-errors": {
+      "version": "1.8.1",
+      "resolved": "https://registry.npmmirror.com/http-errors/-/http-errors-1.8.1.tgz",
+      "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==",
+      "dependencies": {
+        "depd": "~1.1.2",
+        "inherits": "2.0.4",
+        "setprototypeof": "1.2.0",
+        "statuses": ">= 1.5.0 < 2",
+        "toidentifier": "1.0.1"
+      },
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/koa-router/node_modules/isarray": {
+      "version": "0.0.1",
+      "resolved": "https://registry.npmmirror.com/isarray/-/isarray-0.0.1.tgz",
+      "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ=="
+    },
+    "node_modules/koa-router/node_modules/koa-compose": {
+      "version": "3.2.1",
+      "resolved": "https://registry.npmmirror.com/koa-compose/-/koa-compose-3.2.1.tgz",
+      "integrity": "sha512-8gen2cvKHIZ35eDEik5WOo8zbVp9t4cP8p4hW4uE55waxolLRexKKrqfCpwhGVppnB40jWeF8bZeTVg99eZgPw==",
+      "dependencies": {
+        "any-promise": "^1.1.0"
+      }
+    },
+    "node_modules/koa-router/node_modules/path-to-regexp": {
+      "version": "1.8.0",
+      "resolved": "https://registry.npmmirror.com/path-to-regexp/-/path-to-regexp-1.8.0.tgz",
+      "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==",
+      "dependencies": {
+        "isarray": "0.0.1"
+      }
+    },
+    "node_modules/koa-router/node_modules/statuses": {
+      "version": "1.5.0",
+      "resolved": "https://registry.npmmirror.com/statuses/-/statuses-1.5.0.tgz",
+      "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==",
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/koa/node_modules/http-errors": {
+      "version": "1.8.1",
+      "resolved": "https://registry.npmmirror.com/http-errors/-/http-errors-1.8.1.tgz",
+      "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==",
+      "dependencies": {
+        "depd": "~1.1.2",
+        "inherits": "2.0.4",
+        "setprototypeof": "1.2.0",
+        "statuses": ">= 1.5.0 < 2",
+        "toidentifier": "1.0.1"
+      },
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/koa/node_modules/http-errors/node_modules/depd": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmmirror.com/depd/-/depd-1.1.2.tgz",
+      "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==",
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/koa/node_modules/statuses": {
+      "version": "1.5.0",
+      "resolved": "https://registry.npmmirror.com/statuses/-/statuses-1.5.0.tgz",
+      "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==",
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
     "node_modules/launch-editor": {
       "version": "2.6.1",
       "resolved": "https://registry.npmmirror.com/launch-editor/-/launch-editor-2.6.1.tgz",
@@ -6462,7 +6754,6 @@
       "version": "0.3.0",
       "resolved": "https://registry.npmmirror.com/media-typer/-/media-typer-0.3.0.tgz",
       "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==",
-      "dev": true,
       "engines": {
         "node": ">= 0.6"
       }
@@ -6513,7 +6804,6 @@
       "version": "1.1.2",
       "resolved": "https://registry.npmmirror.com/methods/-/methods-1.1.2.tgz",
       "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==",
-      "dev": true,
       "engines": {
         "node": ">= 0.6"
       }
@@ -6703,8 +6993,7 @@
     "node_modules/ms": {
       "version": "2.1.2",
       "resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.2.tgz",
-      "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
-      "dev": true
+      "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
     },
     "node_modules/multicast-dns": {
       "version": "7.2.5",
@@ -6745,7 +7034,6 @@
       "version": "0.6.3",
       "resolved": "https://registry.npmmirror.com/negotiator/-/negotiator-0.6.3.tgz",
       "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
-      "dev": true,
       "engines": {
         "node": ">= 0.6"
       }
@@ -6930,7 +7218,6 @@
       "version": "2.4.1",
       "resolved": "https://registry.npmmirror.com/on-finished/-/on-finished-2.4.1.tgz",
       "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
-      "dev": true,
       "dependencies": {
         "ee-first": "1.1.1"
       },
@@ -6968,6 +7255,11 @@
         "node": ">=6"
       }
     },
+    "node_modules/only": {
+      "version": "0.0.2",
+      "resolved": "https://registry.npmmirror.com/only/-/only-0.0.2.tgz",
+      "integrity": "sha512-Fvw+Jemq5fjjyWz6CpKx6w9s7xxqo3+JCyM0WXWeCSOboZ8ABkyvP8ID4CZuChA/wxSx+XSJmdOm8rGVyJ1hdQ=="
+    },
     "node_modules/open": {
       "version": "8.4.2",
       "resolved": "https://registry.npmmirror.com/open/-/open-8.4.2.tgz",
@@ -7192,7 +7484,6 @@
       "version": "1.3.3",
       "resolved": "https://registry.npmmirror.com/parseurl/-/parseurl-1.3.3.tgz",
       "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
-      "dev": true,
       "engines": {
         "node": ">= 0.8"
       }
@@ -8274,8 +8565,7 @@
     "node_modules/safe-buffer": {
       "version": "5.2.1",
       "resolved": "https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.2.1.tgz",
-      "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
-      "dev": true
+      "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
     },
     "node_modules/safer-buffer": {
       "version": "2.1.2",
@@ -8474,8 +8764,7 @@
     "node_modules/setprototypeof": {
       "version": "1.2.0",
       "resolved": "https://registry.npmmirror.com/setprototypeof/-/setprototypeof-1.2.0.tgz",
-      "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==",
-      "dev": true
+      "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="
     },
     "node_modules/shallow-clone": {
       "version": "3.0.1",
@@ -8593,6 +8882,11 @@
         "source-map": "^0.6.0"
       }
     },
+    "node_modules/spark-md5": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmmirror.com/spark-md5/-/spark-md5-3.0.2.tgz",
+      "integrity": "sha512-wcFzz9cDfbuqe0FZzfi2or1sgyIrsDwmPwfZC4hiNidPdPINjeUwNfv5kldczoEAcjl9Y1L3SM7Uz2PUEQzxQw=="
+    },
     "node_modules/spdx-correct": {
       "version": "3.2.0",
       "resolved": "https://registry.npmmirror.com/spdx-correct/-/spdx-correct-3.2.0.tgz",
@@ -8999,7 +9293,6 @@
       "version": "1.0.1",
       "resolved": "https://registry.npmmirror.com/toidentifier/-/toidentifier-1.0.1.tgz",
       "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
-      "dev": true,
       "engines": {
         "node": ">=0.6"
       }
@@ -9025,6 +9318,14 @@
       "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==",
       "dev": true
     },
+    "node_modules/tsscmp": {
+      "version": "1.0.6",
+      "resolved": "https://registry.npmmirror.com/tsscmp/-/tsscmp-1.0.6.tgz",
+      "integrity": "sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA==",
+      "engines": {
+        "node": ">=0.6.x"
+      }
+    },
     "node_modules/type-fest": {
       "version": "0.6.0",
       "resolved": "https://registry.npmmirror.com/type-fest/-/type-fest-0.6.0.tgz",
@@ -9038,7 +9339,6 @@
       "version": "1.6.18",
       "resolved": "https://registry.npmmirror.com/type-is/-/type-is-1.6.18.tgz",
       "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
-      "dev": true,
       "dependencies": {
         "media-typer": "0.3.0",
         "mime-types": "~2.1.24"
@@ -9136,6 +9436,11 @@
         "punycode": "^2.1.0"
       }
     },
+    "node_modules/urijs": {
+      "version": "1.19.11",
+      "resolved": "https://registry.npmmirror.com/urijs/-/urijs-1.19.11.tgz",
+      "integrity": "sha512-HXgFDgDommxn5/bIv0cnQZsPhHDA90NPHD6+c/v21U5+Sx5hoP8+dP9IZXBU1gIfvdRfhG8cel9QNPeionfcCQ=="
+    },
     "node_modules/util-deprecate": {
       "version": "1.0.2",
       "resolved": "https://registry.npmmirror.com/util-deprecate/-/util-deprecate-1.0.2.tgz",
@@ -9180,7 +9485,6 @@
       "version": "1.1.2",
       "resolved": "https://registry.npmmirror.com/vary/-/vary-1.1.2.tgz",
       "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==",
-      "dev": true,
       "engines": {
         "node": ">= 0.8"
       }
@@ -9872,6 +10176,14 @@
       "engines": {
         "node": ">=10"
       }
+    },
+    "node_modules/ylru": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmmirror.com/ylru/-/ylru-1.4.0.tgz",
+      "integrity": "sha512-2OQsPNEmBCvXuFlIni/a+Rn+R2pHW9INm0BxXJ4hVDA8TirqMj+J/Rp9ItLatT/5pZqWwefVrTQcHpixsxnVlA==",
+      "engines": {
+        "node": ">= 4.0.0"
+      }
     }
   }
 }

+ 3 - 0
vue/package.json

@@ -9,7 +9,10 @@
   "dependencies": {
     "axios": "^1.5.1",
     "core-js": "^3.8.3",
+    "echart": "^0.1.3",
+    "element-china-area-data": "^6.1.0",
     "element-ui": "^2.15.14",
+    "spark-md5": "^3.0.2",
     "vue": "^2.6.14",
     "vue-router": "^3.5.1"
   },

+ 105 - 0
vue/src/components/UploadPic.vue

@@ -0,0 +1,105 @@
+<script>
+export default {
+  name: "UploadFile",
+  data(){
+    return{
+      preVisible:false,
+      dialogUrl:null, //  弹窗图片
+      preImgsUrls:[]//{url:"",id:0,}
+    }
+  },
+  props:{
+    fileType: {
+      default:"文件"
+    }
+  },
+  methods:{
+    uploadSuccessful(response, file, fileList){
+      console.log(response.data)
+      let fileSlice = file.response.data.split("/")
+      if(fileSlice){
+        let fileName = fileSlice[fileSlice.length-1] // 最后一串是文件名称
+        this.$message.success(`${fileName} 上传成功`)
+        this.preImgsUrls.push({
+          name:fileName,
+          url:response.data,
+          id:this.preImgsUrls.length+1
+        })
+        this.$emit("update:uploadFile",this.preImgsUrls); // 传递更新的信息
+      }else {
+        this.$message.success(`上传成功`)
+      }
+    },
+    onRemove(file, fileList){
+      let fileSlice = file.response.data.split("/")
+      let fileName = fileSlice[fileSlice.length-1] // 最后一串是文件名称
+      this.$request.delete(`/files/delete/${fileName}`).then(res=>{
+        if(res.code == 200){
+          this.$message.info(`${fileName} 取消上传`)
+        }
+      })
+      const deleteFileUrl =  file.response.data
+      console.log(deleteFileUrl)
+      this.preImgsUrls = this.preImgsUrls.filter(item=>item.url=!deleteFileUrl) // 删除
+      this.$emit("update:cancelUpload",this.preImgsUrls)
+    },
+    onError(err, file, fileList){
+      this.$message.error(`${err}`)
+    },
+    handlePreview(file){
+      console.log(file,"handlePreview")
+      this.dialogUrl = file.response.data;
+      this.preVisible = true;
+    },
+  }
+}
+</script>
+
+<template>
+<div>
+  <el-upload
+      class="upload-demo"
+      drag
+      :on-preview="handlePreview"
+      :action="$baseUrl+'/files/upload'"
+      :show-file-list="true"
+      :on-success="uploadSuccessful"
+      :on-remove="onRemove"
+      list-type="picture"
+      multiple
+  >
+    <i class="el-icon-upload" ></i>
+<!--    <template slot="file" slot-scope="{file}">-->
+<!--      <img-->
+<!--          class="el-upload-list__item-thumbnail"-->
+<!--          :src="file.url" :alt="file.name"-->
+<!--      >-->
+
+<!--      <span class="el-upload-list__item-actions">-->
+<!--&lt;!&ndash;      图片预览&ndash;&gt;-->
+<!--        <span-->
+<!--            class="el-upload-list__item-preview"-->
+<!--            @click="handlePreview(file)"-->
+<!--        >-->
+<!--          <i class="el-icon-zoom-in"></i>-->
+<!--        </span>-->
+<!--        <i class="el-icon-delete"></i>-->
+<!--        <span-->
+<!--            class="el-upload-list__item-delete"-->
+<!--            @click="onRemove(file)"-->
+<!--        >-->
+
+<!--        </span>-->
+<!--      </span>-->
+<!--    </template>-->
+    <div class="el-upload__text">将{{this.fileType}}拖到此处,或<em>点击上传</em></div>
+  </el-upload>
+  <el-dialog :visible.sync="preVisible" >
+    <img width="100%" :src="dialogUrl" alt="">
+  </el-dialog>
+</div>
+</template>
+
+<style scoped>
+
+</style>

+ 81 - 0
vue/src/components/UploadSlice.vue

@@ -0,0 +1,81 @@
+<script>
+import {defineComponent} from 'vue'
+// 分片上传
+export default defineComponent({
+  name: "UploadSlice",
+  methods:{
+    uploadSuccessful(response, file, fileList){
+      console.log(response.data)
+      let fileSlice = file.response.data.split("/")
+      if(fileSlice){
+        let fileName = fileSlice[fileSlice.length-1] // 最后一串是文件名称
+        this.$message.success(`${fileName} 上传成功`)
+      }else {
+        this.$message.success(`上传成功`)
+      }
+
+
+    },
+    onRemove(file, fileList){
+      let fileSlice = file.response.data.split("/")
+      let fileName = fileSlice[fileSlice.length-1] // 最后一串是文件名称
+      this.$request.delete(`/files/delete/${fileName}`).then(res=>{
+        if(res.code == 200){
+          this.$message.info(`${fileName} 取消上传`)
+        }
+      })
+    },
+    onError(err, file, fileList){
+      this.$message.error(`${err}`)
+    },
+    upload(file,fileList){
+      console.log(file,fileList)
+    }
+  }
+})
+</script>
+
+<template>
+<div>
+  <el-card>
+    <el-card>
+      第一种上传方式
+      <el-upload
+          class="upload-demo"
+          drag
+          :action="$baseUrl+'/files/upload'"
+          :show-file-list="true"
+          :on-success="uploadSuccessful"
+          :on-remove="onRemove"
+          :http-request="upload"
+          multiple
+      >
+        <i class="el-icon-upload"></i>
+        <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
+      </el-upload>
+    </el-card>
+
+    <el-card>
+      视频分块上传
+      <el-upload
+          class="upload-demo"
+          drag
+          :action="$baseUrl+'/video/fileUpload'"
+          :show-file-list="true"
+          :on-success="uploadSuccessful"
+          :on-remove="onRemove"
+          :on-error="onError"
+          multiple
+      >
+        <i class="el-icon-upload"></i>
+        <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
+      </el-upload>
+    </el-card>
+  </el-card>
+
+</div>
+</template>
+
+<style scoped>
+
+</style>

+ 57 - 0
vue/src/components/UploadView.vue

@@ -0,0 +1,57 @@
+<template>
+  <div>
+    <el-upload
+        class="upload-demo"
+        drag
+        :action="$baseUrl+'/files/upload'"
+        :show-file-list="true"
+        :on-success="uploadSuccessful"
+        :on-remove="onRemove"
+        :http-request="upload"
+        multiple
+    >
+      <i class="el-icon-upload"></i>
+      <div class="el-upload__text">将{{title}}拖到此处,或<em>点击上传</em></div>
+    </el-upload>
+  </div>
+</template>
+
+<script>
+export default {
+  name: "UploadView",
+  props:{
+    title:"文件1",
+  },
+  methods:{
+    uploadSuccessful(response, file, fileList){
+      console.log(response.data)
+      let fileSlice = file.response.data.split("/")
+      if(fileSlice){
+        let fileName = fileSlice[fileSlice.length-1] // 最后一串是文件名称
+        this.$message.success(`${fileName} 上传成功`)
+      }else {
+        this.$message.success(`上传成功`)
+      }
+    },
+    onRemove(file, fileList){
+      let fileSlice = file.response.data.split("/")
+      let fileName = fileSlice[fileSlice.length-1] // 最后一串是文件名称
+      this.$request.delete(`/files/delete/${fileName}`).then(res=>{
+        if(res.code == 200){
+          this.$message.info(`${fileName} 取消上传`)
+        }
+      })
+    },
+    onError(err, file, fileList){
+      this.$message.error(`${err}`)
+    },
+    upload(file,fileList){
+      console.log(file,fileList)
+    }
+  }
+}
+</script>
+
+<style>
+
+</style>

+ 1 - 1
vue/src/router/index.js

@@ -47,13 +47,13 @@ const routes = [
       { path: '/adminMgr/productTypeMgr', name:'productType' ,meta:{name:'产品类型管理'} ,component:()=>import('../views/manager/ShopManager/ProductType.vue')},
       { path: '/adminMgr/store', name:'Store' ,meta:{name:'店铺信息管理'} ,component:()=>import('../views/manager/ShopManager/Store.vue')},
       { path: '/adminMgr/user', name:'User' ,meta:{name:'用户信息管理'} ,component:()=>import('../views/manager/ShopManager/User.vue')},
+      { path: '/adminMgr/applyForUp', name:'ApplyForUp' ,meta:{name:'申请成为店家'} ,component:()=>import('../views/front/ApplyForUp.vue')},
     ]
   },
   {
     path:'/charts',
     name:"AI",
     component:()=>import('../views/manager/AI/Charts.vue'),
-    //redirect: '/charts',
   },
   {
     path: '/front',

+ 24 - 0
vue/src/utils/fileUtil/CreateChunk.js

@@ -0,0 +1,24 @@
+import SparkMD5 from "spark-md5"
+export function createChunk(file,index,chunkSize){
+    return new Promise((resolve, reject)=>{
+
+        const sp = new SparkMD5()
+        const start = index*chunkSize;
+        const end = start + chunkSize;
+
+        const spark = sp.ArrayBuffer();
+
+        const fileReader = new FileReader();
+        const blob = file.slice(start,end);
+        fileReader.onload = (e)=>{
+            spark.append(e.target.result);
+            resolve({
+                start,
+                end,
+                index,
+                hash:spark.end(),
+                blob,
+            })
+        }
+    } )
+}

+ 43 - 0
vue/src/utils/fileUtil/CutFile.js

@@ -0,0 +1,43 @@
+const CHUNK_SIZE = 1024*1024*5 // 5MB
+const THREAD_COUNT = 12// 线程数量设置
+/**
+ * 将文件切片
+ * @param file
+ * @returns {Promise<void>}
+ */
+export  function cutFile(file){
+    return new Promise((resolve, reject)=>{
+        const chunkCount  = Math.ceil(file.size / CHUNK_SIZE);
+        const threadChunkCount  = Math.ceil(chunkCount / THREAD_COUNT);
+        let finishedCount = 0 ;//  记录完成的线程数量
+        let result = []; // 存储分片结果
+        for(let i =  0 ; i<Math.min(THREAD_COUNT,chunkCount);i++){
+            // 创建对应数量的线程  分配任务
+            const worker = new Worker('./worker.js',{
+                type:'module'
+            })
+            let start = i*threadChunkCount
+            let end = (i+1)*threadChunkCount
+            if(end > chunkCount) end = chunkCount
+            worker.postMessage({
+                file,
+                CHUNK_SIZE,
+                startChunkIndex: start,
+                endChunkIndex:end ,// (i+1) * threadChunckCount
+            });
+            // 汇总结束
+            worker.onmessage= e=>{
+                for(let  i = start ; i<end;i++){
+                    result[i] = e.data[i-start];
+                }
+                worker.terminate(); //线程完成
+                finishedCount++; //完成一个线程数量+1
+                if(finishedCount == Math.min(THREAD_COUNT,chunkCount)){
+                    // 函数结束
+                    resolve(result)
+                }
+            }
+        }
+    })
+
+}

+ 13 - 0
vue/src/utils/fileUtil/fileUtil.js

@@ -0,0 +1,13 @@
+import axios  from "axios";
+
+
+const fileUtil = axios.create({
+    baseURL: process.env.VUE_APP_BASEURL,   // 后端的接口地址  ip:port
+    timeout: 30000                          // 30s请求超时
+})
+
+fileUtil.interceptors.request.use(config=>{
+    config.headers['Content-Type'] = 'multipart/form-data;charset=utf-8';        // 设置请求头格式
+    let user = JSON.parse(localStorage.getItem("xm-user") || '{}')  // 获取缓存的用户信息
+    config.headers['token'] = user.token  // 设置请求头
+})

+ 21 - 0
vue/src/utils/fileUtil/worker.js

@@ -0,0 +1,21 @@
+import {createChunk} from "@/utils/fileUtil/CreateChunk";
+import {proxy} from "vue/src/core/instance/state";
+import SparkMD5 from "spark-md5";
+
+onmessage = async(e)=>{
+    const {
+        file,
+        CHUNK_SIZE,
+        startChunkIndex: start,
+        endChunkIndex:end ,// (i+1) * threadChunckCount
+    } = e.data
+    const proms = []; //
+    for (let i = start; i<end;i++){
+        proms.push(createChunk(file,i,CHUNK_SIZE));
+    }
+    const chunks = await Promise.all(proms) //  所有分片结果
+    postMessage(chunks) // 返回处理结果给主线程
+    new SparkMD5()
+
+}
+export default Worker;

+ 1 - 0
vue/src/views/AdminMgr.vue

@@ -105,6 +105,7 @@ export default {
   },
   created() {
     if (!this.user.id) {
+      this.$message.error("请登陆后重试!")
       this.$router.push('/login')
     }
   },

+ 2 - 0
vue/src/views/Front.vue

@@ -49,7 +49,9 @@
 
 export default {
   name: "FrontLayout",
+  components:{
 
+  },
   data () {
     return {
       top: '',

+ 3 - 3
vue/src/views/Manager.vue

@@ -106,6 +106,7 @@ export default {
   },
   created() {
     if (!this.user.id) {
+      this.$message.error("请登陆后重试!")
       this.$router.push('/login')
     }
   },
@@ -114,13 +115,12 @@ export default {
       this.user = JSON.parse(localStorage.getItem('xm-user') || '{}')   // 重新获取下用户的最新信息
     },
     goToPerson() {
-      if (this.user.role === 'ADMIN') {
-        this.$router.push('/adminPerson')
-      }
+        this.$router.push('/adminMgr/applyForUp')
     },
     logout() {
       localStorage.removeItem('xm-user')
       this.$router.push('/login')
+      this.$message.success("成功退出登陆")
     }
   }
 }

+ 124 - 0
vue/src/views/front/ApplyForUp.vue

@@ -0,0 +1,124 @@
+<script>
+// 申请成为up的申请界面
+import UploadPic from "@/components/UploadPic.vue";
+import {provinceAndCityData,pcTextArr,regionData,pcaTextArr,codeToText,} from'element-china-area-data'
+export default {
+  name: "ApplyForUp",
+  components:{
+    UploadPic:UploadPic
+  },
+  data() {
+    return {
+      formData:{
+        keeperName :'', // 姓名
+        idCard:"", //申请人身份证
+        business_license:"", //营业许可证URL
+        reason:"", // 申请理由
+        pics_url:"", // 店铺图片
+      },
+      provinceAndCityData,
+      pcaTextArr,
+      selectedOptions:[], // 地址选项
+      placeDetail:"",
+      rules:{
+        desc:[{require:true}]
+      }
+    };
+  },
+  computed:{
+    address(){
+      let res = ""
+      console.log(this.selectedOptions)
+      for(let city in this.selectedOptions) res +=this.selectedOptions[city]
+      return res + this.placeDetail;
+    }
+  }
+  ,
+  methods: {
+    onSubmit() {
+      const requestForm = {
+        storeAddress:this.address,
+        idcard:this.formData.idCard,
+        businessLicense: this.formData.business_license,
+        reason:this.formData.reason,
+        picsUrl:this.formData.pics_url,
+        keeperName:this.formData.keeperName
+      }
+      console.log(requestForm)
+      this.$request.post("/audits/add",requestForm).then(res=>{
+        console.log(res)
+      })
+
+    },
+    updateBsCard(data){this.formData.business_license = data[0].url},
+    updateDeleBsCard(file){this.formData.business_license = null},
+    updateFarm(data){this.formData.pics_url= data[0].url},//农村图片
+    updateDeleFarm(data){this.formData.pics_url = null},//删除选中的图片
+  }
+}
+
+</script>
+
+<template>
+<div>
+  <el-card class="applyForm" style="margin-left:10%;margin-right: 10%; width: 80%">
+    <div style="text-align: center "> 申 请 店 铺 </div>
+    <el-form :rule="rules" label-position="left" ref="form" :model="formData" label-width="80px" size="mini" class="demo-ruleForm">
+      <el-form-item label="姓名" style="width: 30%">
+        <el-input v-model="formData.keeperName"></el-input>
+      </el-form-item>
+
+      <el-form-item label="营业许可证照片" :rule="[
+          {require:true,message:'请上传营业许可照片'}
+      ]">
+        <UploadPic fileType="营业许可证照片" @update:uploadFile="updateBsCard" @update:cancelUpload="updateDeleBsCard">
+        </UploadPic>
+      </el-form-item>
+      <el-form-item label="农铺照片" :rule="[
+          {require:true,message:'请上传农铺照片'}
+      ]">
+        <UploadPic fileType="农铺照片" @update:uploadFile="updateFarm" @update:cancelUpload="updateDeleFarm">
+        </UploadPic>
+      </el-form-item>
+      <el-form-item label="申请理由" prop="desc">
+        <el-input
+            type="textarea"
+            placeholder="请输入内容"
+            maxlength="300"
+            v-model="formData.reason"
+            show-word-limit
+            autosize
+            style="font-family: 'PingFang SC' "
+        >
+        </el-input>
+      </el-form-item>
+      <el-form-item label="店铺地址" >
+        <el-col :span="63">
+        <el-cascader
+            size="large"
+            :options="pcaTextArr"
+            v-model="selectedOptions">
+        </el-cascader>
+          <i> 详细地址 </i> <el-input v-model="placeDetail" style="width: 100%"></el-input>
+        </el-col>
+
+      </el-form-item>
+      <el-form-item size="large">
+        <el-button type="primary" @click="onSubmit">提交申请</el-button>
+        <el-button>取消</el-button>
+      </el-form-item>
+    </el-form>
+
+  </el-card>
+
+</div>
+</template>
+
+<style>
+// 这里把他放到居中位置
+.applyForm {
+  width: 400px; /* 设置表单的宽度 */
+  margin: 0 auto; /* 使用 margin 属性将表单水平居中 */
+}
+
+</style>

+ 44 - 4
vue/src/views/manager/Manager/Audit.vue

@@ -12,15 +12,32 @@
     </div>
 
     <div class="table">
-      <el-table :data="tableData" strip @selection-change="handleSelectionChange">
+      <el-table v-loading="isLoading" :data="tableData" strip @selection-change="handleSelectionChange">
         <el-table-column type="selection" width="55" align="center"></el-table-column>
         <el-table-column prop="id" label="序号" width="70" align="center" sortable></el-table-column>
+        <el-table-column prop="storeAddress" label="店铺地址"></el-table-column>
         <el-table-column prop="idcard" label="身份证"></el-table-column>
-        <el-table-column prop="businessLicense" label="营业执照url"></el-table-column>
+        <el-table-column prop="businessLicense" label="营业执照url">
+          <template v-slot="scope">
+            <img style="width: 100%" :src="scope.row.businessLicense" @click="print(scope)"><img/>
+          </template>
+        </el-table-column>
         <el-table-column prop="reason" label="申请理由"></el-table-column>
-        <el-table-column prop="picsUrl" label="市区营业图片"></el-table-column>
+        <el-table-column prop="picsUrl" label="市区营业图片">
+          <template v-slot="scope" >
+            <img style="width: 100%" :src="scope.row.picsUrl">
+          </template>
+        </el-table-column>
         <el-table-column prop="cameraUrl" label="监控地址"></el-table-column>
         <el-table-column prop="storeId" label="店铺申请人id用adminstore的id"></el-table-column>
+        <el-table-column prop="keeperName" label="店铺主名称"></el-table-column>
+        <el-table-column prop="state" label="审核状态">
+          <template v-slot="scope">
+            <el-tag :type="getTagType(scope.row.state)">
+              {{scope.row.state}}
+            </el-tag>
+          </template>
+        </el-table-column>
         <el-table-column label="操作" align="center" width="180">
           <template v-slot="scope">
             <el-button size="mini" type="primary" plain @click="handleEdit(scope.row)">编辑</el-button>
@@ -44,6 +61,9 @@
 
     <el-dialog title="申请审核表" :visible.sync="fromVisible" width="40%" :close-on-click-modal="false" destroy-on-close>
       <el-form :model="form" label-width="100px" style="padding-right: 50px" :rules="rules" ref="formRef">
+        <el-form-item label="店铺地址" prop="storeAddress">
+          <el-input v-model="form.storeAddress" placeholder="店铺地址"></el-input>
+        </el-form-item>
         <el-form-item label="身份证" prop="idcard">
           <el-input v-model="form.idcard" placeholder="身份证"></el-input>
         </el-form-item>
@@ -62,6 +82,12 @@
         <el-form-item label="店铺申请人id用adminstore的id" prop="storeId">
           <el-input v-model="form.storeId" placeholder="店铺申请人id用adminstore的id"></el-input>
         </el-form-item>
+        <el-form-item label="店铺主名称" prop="keeperName">
+          <el-input v-model="form.keeperName" placeholder="店铺主名称"></el-input>
+        </el-form-item>
+        <el-form-item label="审核状态" prop="state">
+          <el-input v-model="form.state" placeholder="审核状态"></el-input>
+        </el-form-item>
       </el-form>
       <div slot="footer" class="dialog-footer">
         <el-button @click="fromVisible = false">取 消</el-button>
@@ -74,9 +100,10 @@
 </template>
 <script>
 export default {
-  name: "Audit",
+  name: "Audits",
   data() {
     return {
+      isLoading: false,
       tableData: [],  // 所有的数据
       pageNum: 1,   // 当前的页码
       pageSize: 10,  // 每页显示的个数
@@ -165,6 +192,8 @@ export default {
       }).then(res => {
         this.tableData = res.data?.list
         this.total = res.data?.total
+        console.log(this.tableData)
+        this.isLoading = false;
       })
     },
     reset() {
@@ -174,6 +203,17 @@ export default {
     handleCurrentChange(pageNum) {
       this.load(pageNum)
     },
+    print(data){
+      console.log("print",data);
+    },
+    getTagType(data){
+      let result = ""
+      if(data == '正在审核') {result = "info"}
+      else if(data == '审核通过') result = 'success'
+      else if(data == '审核失败') result = 'danger'
+      return result
+      // return "success" | "info" | "warning"| "danger"
+    }
   }
 }
 </script>