MS-CIAZDCOIXVRW\Administrator 3 лет назад
Сommit
413673d9ca
16 измененных файлов с 9237 добавлено и 0 удалено
  1. 23 0
      .gitignore
  2. 24 0
      README.md
  3. 5 0
      babel.config.js
  4. 19 0
      jsconfig.json
  5. 8533 0
      package-lock.json
  6. 50 0
      package.json
  7. BIN
      public/favicon.ico
  8. 17 0
      public/index.html
  9. 25 0
      src/App.vue
  10. BIN
      src/assets/logo.jpg
  11. BIN
      src/assets/set.png
  12. 50 0
      src/components/Form/index.vue
  13. 429 0
      src/components/Home/index.vue
  14. 26 0
      src/main.js
  15. 16 0
      src/router/index.js
  16. 20 0
      vue.config.js

+ 23 - 0
.gitignore

@@ -0,0 +1,23 @@
+.DS_Store
+node_modules
+/dist
+
+
+# local env files
+.env.local
+.env.*.local
+
+# Log files
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+
+# Editor directories and files
+.idea
+.vscode
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?

+ 24 - 0
README.md

@@ -0,0 +1,24 @@
+# file-parse
+
+## Project setup
+```
+npm install
+```
+
+### Compiles and hot-reloads for development
+```
+npm run serve
+```
+
+### Compiles and minifies for production
+```
+npm run build
+```
+
+### Lints and fixes files
+```
+npm run lint
+```
+
+### Customize configuration
+See [Configuration Reference](https://cli.vuejs.org/config/).

+ 5 - 0
babel.config.js

@@ -0,0 +1,5 @@
+module.exports = {
+  presets: [
+    '@vue/cli-plugin-babel/preset'
+  ]
+}

+ 19 - 0
jsconfig.json

@@ -0,0 +1,19 @@
+{
+  "compilerOptions": {
+    "target": "es5",
+    "module": "esnext",
+    "baseUrl": "./",
+    "moduleResolution": "node",
+    "paths": {
+      "@/*": [
+        "src/*"
+      ]
+    },
+    "lib": [
+      "esnext",
+      "dom",
+      "dom.iterable",
+      "scripthost"
+    ]
+  }
+}

Разница между файлами не показана из-за своего большого размера
+ 8533 - 0
package-lock.json


+ 50 - 0
package.json

@@ -0,0 +1,50 @@
+{
+  "name": "file-parse",
+  "version": "0.1.0",
+  "private": true,
+  "scripts": {
+    "dev": "vue-cli-service serve",
+    "build": "vue-cli-service build",
+    "lint": "vue-cli-service lint"
+  },
+  "dependencies": {
+    "axios": "^0.27.2",
+    "core-js": "^3.8.3",
+    "element-ui": "^2.15.10",
+    "sass": "^1.54.9",
+    "sass-loader": "^13.0.2",
+    "vue": "^2.6.14",
+    "vue-router": "^3.6.5",
+    "xlsx": "^0.18.5"
+  },
+  "devDependencies": {
+    "@babel/core": "^7.12.16",
+    "@babel/eslint-parser": "^7.12.16",
+    "@vue/cli-plugin-babel": "~5.0.0",
+    "@vue/cli-plugin-eslint": "~5.0.0",
+    "@vue/cli-service": "~5.0.0",
+    "babel-plugin-component": "^1.1.1",
+    "eslint": "^7.32.0",
+    "eslint-plugin-vue": "^8.0.3",
+    "vue-template-compiler": "^2.6.14"
+  },
+  "eslintConfig": {
+    "root": true,
+    "env": {
+      "node": true
+    },
+    "extends": [
+      "plugin:vue/essential",
+      "eslint:recommended"
+    ],
+    "parserOptions": {
+      "parser": "@babel/eslint-parser"
+    },
+    "rules": {}
+  },
+  "browserslist": [
+    "> 1%",
+    "last 2 versions",
+    "not dead"
+  ]
+}

BIN
public/favicon.ico


+ 17 - 0
public/index.html

@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html lang="">
+  <head>
+    <meta charset="utf-8">
+    <meta http-equiv="X-UA-Compatible" content="IE=edge">
+    <meta name="viewport" content="width=device-width,initial-scale=1.0">
+    <link rel="icon" href="<%= BASE_URL %>favicon.ico">
+    <title><%= htmlWebpackPlugin.options.title %></title>
+  </head>
+  <body>
+    <noscript>
+      <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
+    </noscript>
+    <div id="app"></div>
+    <!-- built files will be auto injected -->
+  </body>
+</html>

+ 25 - 0
src/App.vue

@@ -0,0 +1,25 @@
+<template>
+  <div id="app">
+    <router-view>
+      <Home />
+    </router-view>
+  </div>
+</template>
+
+<script>
+import Home from "./components/Home";
+
+export default {
+  name: "App",
+  components: {
+    Home,
+  },
+};
+</script>
+
+<style>
+* {
+  margin: 0;
+  padding: 0;
+}
+</style>

BIN
src/assets/logo.jpg


BIN
src/assets/set.png


+ 50 - 0
src/components/Form/index.vue

@@ -0,0 +1,50 @@
+<template>
+  <div class="form">
+    <div class="box" v-html="tableau"></div>
+  </div>
+</template>
+
+<script>
+import XLSX from "xlsx";
+export default {
+  name: "Form",
+  data() {
+    return {
+      tableau: null,
+    };
+  },
+  mounted() {
+    // this.getForm();
+  },
+  methods: {
+    // 预览表格
+    getForm() {
+      this.$axios
+        .get("/xlsx", {
+          responseType: "arraybuffer", // 设置响应体类型为arraybuffer
+        })
+        .then(({ data }) => {
+          console.log(data);
+          // 解析数据
+          let workbook = XLSX.read(new Uint8Array(data), { type: "array" });
+          // workbook.SheetNames 下存的是该文件每个工作表名字,这里取出第一个工作表
+          var worksheet = workbook.Sheets[workbook.SheetNames[0]];
+          // 渲染
+          this.tableau = XLSX.utils.sheet_to_html(worksheet);
+        });
+    },
+  },
+};
+</script>
+
+
+<style lang="scss" scoped>
+.form {
+  .box {
+    margin: 0 auto;
+    width: 1540px;
+    height: 800px;
+    background-color: skyblue;
+  }
+}
+</style>

+ 429 - 0
src/components/Home/index.vue

@@ -0,0 +1,429 @@
+<template>
+  <div class="body">
+    <div class="content">
+      <!-- 头部内容 -->
+      <div class="header">
+        <div class="img"></div>
+      </div>
+      <!-- 分割盒子 -->
+      <div class="line"></div>
+      <!-- 文件解析内容区域 -->
+      <div class="box">
+        <div class="box_header">文件解析</div>
+        <div class="box_info">智能解析钉钉考勤表的工具</div>
+        <div class="box_info2">快速、在线、无限制</div>
+        <div class="form">
+          <!-- 上传文件区域 -->
+          <!-- 默认展示页面区域 -->
+          <el-upload
+            class="upload-demo"
+            v-if="showPage == 1"
+            :drag="hasDrag"
+            action="none"
+            :auto-upload="false"
+            :limit="1"
+            accept=".xls,.xlsx"
+            :on-change="handleUpload"
+            :on-exceed="handleExceed"
+          >
+            <div class="choose">选择文件</div>
+            <div class="message">或拖放文件到这</div>
+            <div class="tips">tips:只能上传xls/xlsx文件</div>
+          </el-upload>
+
+          <!-- 上传时展示的页面区域 -->
+          <div class="upload-demo" v-if="showPage == 2">
+            <div class="choose2">{{ info }}</div>
+            <div class="message2">
+              <el-progress
+                type="line"
+                text-inside
+                :stroke-width="26"
+                :percentage="percentage"
+              ></el-progress>
+            </div>
+            <div class="form_name">
+              <span>{{ form_name }}</span>
+              <i class="el-icon-close" @click="handleRemove"></i>
+            </div>
+          </div>
+
+          <!-- 解析时展示的页面区域 -->
+          <div class="upload-demo" v-if="showPage == 3">
+            <div class="choose2">您的任务正在处理,请稍等</div>
+            <div class="message2">
+              <el-progress
+                type="line"
+                text-inside
+                :stroke-width="26"
+                :percentage="parsePercentage"
+              ></el-progress>
+            </div>
+            <div class="form_name">{{ form_name }}</div>
+          </div>
+
+          <!-- 解析完成时展示的区域 -->
+          <div class="upload-demo" v-if="showPage == 4">
+            <div class="choose2">您的任务处理完成,用时:{{ time_s }}秒</div>
+            <div class="form_name">{{ form_name }}</div>
+            <div class="handle">
+              <el-button type="primary" icon="el-icon-download">下载</el-button>
+              <el-button
+                type="success"
+                icon="el-icon-view"
+                @click="handlePreview"
+                >预览</el-button
+              >
+              <el-button type="danger" @click="handleRestart"
+                >重新开始</el-button
+              >
+            </div>
+          </div>
+
+          <!-- 开始按钮 -->
+          <div class="start" @click="handleStart">开始</div>
+        </div>
+        <!-- 设置按钮区域 -->
+        <div class="button" @click="handleSet"></div>
+      </div>
+
+      <!-- 弹窗区域 -->
+      <el-drawer
+        :visible.sync="drawer"
+        :with-header="false"
+        :wrapperClosable="false"
+        size="20%"
+      >
+        <div class="drawer_title">设置</div>
+        <div class="drawer_body">
+          <div class="drawer_item">
+            墨轩湖每日打卡次数为<input v-model="clockIn_mo" type="text" />次
+          </div>
+          <div class="drawer_item">
+            黄家湖每日打卡次数为<input v-model="clockIn_huang" type="text" />次
+          </div>
+        </div>
+        <div class="drawer_foot">
+          <el-button class="foot_button" @click="handleClose">取消</el-button>
+          <el-button class="foot_button" type="primary">保存</el-button>
+        </div>
+      </el-drawer>
+
+      <!-- 预览表格弹窗 -->
+      <el-dialog title="预览" :visible.sync="dialogVisible" fullscreen center>
+        <Form />
+      </el-dialog>
+    </div>
+  </div>
+</template>
+
+<script>
+import Form from "../Form";
+export default {
+  name: "Home",
+  components: { Form },
+  data() {
+    return {
+      // 控制页面的切换
+      showPage: 1,
+      // 控制弹窗显示隐藏
+      drawer: false,
+      // 是否支持拖拽文件上传
+      hasDrag: true,
+      // 上传时显示的文字
+      info: "上传中,请稍等",
+      // 上传文件进度条数据
+      percentage: 0,
+      // 解析文件进度条数据
+      parsePercentage: 0,
+      // 定时器
+      timer: null,
+      // 文件名称
+      form_name: "考勤表",
+      // 墨轩湖打卡次数
+      clockIn_mo: 4,
+      // 黄家湖打卡次数
+      clockIn_huang: 3,
+      time_s: 1,
+      // 预览表格弹窗
+      dialogVisible: false,
+    };
+  },
+  methods: {
+    // 点击设置按钮回调
+    handleSet() {
+      this.drawer = true;
+    },
+    // 点击开始按钮回调
+    handleStart() {
+      if (this.showPage == 2 && this.percentage == 100) {
+        this.showPage = 3;
+        this.timer = setInterval(() => {
+          this.parsePercentage += 20;
+          this.time_s += 1;
+          if (this.parsePercentage >= 100) {
+            this.parsePercentage = 100;
+            clearInterval(this.timer);
+            this.showPage = 4;
+          }
+        }, 1000);
+      } else if (this.showPage == 3) {
+        this.$message.error("解析中,请勿重复点击");
+      } else {
+        this.$message.error("请先上传文件");
+      }
+    },
+    // 文件上传回调
+    async handleUpload(file) {
+      if (file) {
+        this.form_name = file.name;
+        this.hasDrag = false;
+        this.showPage = 2;
+        let formData = new FormData();
+        formData.append("file", file.raw);
+
+        let config = {
+          onUploadProgress: (progressEvent) => {
+            // 计算出当前进度
+            this.percentage =
+              (progressEvent.loaded / progressEvent.total).toFixed(2) * 100;
+          },
+          headers: {
+            "Content-Type": "multipart/form-data",
+            "admin_token":
+              "eyJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOjMsImlhdCI6MTY2Mzc0MjY3OCwiZXhwIjoxNjY0OTUyMjc4fQ.tRT4VbTcITCIEp1LfZgXuQpXG9gbK0tq1ljvUI7nW-4",
+          },
+        };
+
+        let res = await this.$axios.post(
+          "/api/tuitionpayment/payableinfo/importByExcel",
+          formData,
+          config
+        );
+        // console.log(res);
+        if (res.data.success) {
+          this.info = "上传完成,请点击开始按钮开始解析";
+        } else {
+          this.$message.error(res.data.message);
+          this.percentage = 0;
+          this.info = res.data.message;
+        }
+      } else {
+        this.$message.error("请先导入文件");
+        return false;
+      }
+    },
+    // 删除列表文件时的回调
+    handleRemove() {
+      this.hasDrag = true;
+      this.showPage = 1;
+      this.info = "上传中,请稍等";
+      this.percentage = 0;
+    },
+    // 预览按钮回调
+    handlePreview() {
+      this.dialogVisible = true;
+    },
+    // 重新开始按钮回调
+    handleRestart() {
+      this.hasDrag = true;
+      this.showPage = 1;
+      this.info = "上传中,请稍等";
+      this.percentage = 0;
+      this.parsePercentage = 0;
+    },
+    // 文件超出个数限制时的钩子
+    handleExceed() {
+      this.$message.error("只能同时上传一个文件");
+    },
+    // 关闭弹窗回调
+    handleClose() {
+      this.drawer = false;
+    },
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.body {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  width: 100vw;
+  height: 100vh;
+  background-color: #eee;
+  .content {
+    width: 1540px;
+    height: 870px;
+    background-color: #fff;
+    .header {
+      display: flex;
+      align-items: center;
+      height: 125px;
+      .img {
+        margin-left: 115px;
+        width: 280px;
+        height: 80px;
+        background: url(@/assets/logo.jpg) no-repeat center;
+        background-size: 80% 80%;
+      }
+    }
+    .line {
+      height: 5px;
+      border: 1px solid #949494;
+    }
+    .box {
+      position: relative;
+      height: 740px;
+      .box_header {
+        height: 100px;
+        line-height: 100px;
+        text-align: center;
+        font-size: 28px;
+        font-weight: bold;
+      }
+      .box_info {
+        height: 30px;
+        text-align: center;
+      }
+      .box_info2 {
+        height: 60px;
+        line-height: 60px;
+        text-align: center;
+      }
+      .form {
+        height: 550px;
+        .upload-demo {
+          display: flex;
+          flex-direction: column;
+          align-items: center;
+          margin: 0 auto;
+          width: 1214px;
+          height: 358px;
+          border: 2px dashed #0040ff;
+          .choose {
+            margin: 0 auto;
+            margin-top: 80px;
+            width: 110px;
+            height: 45px;
+            line-height: 45px;
+            text-align: center;
+            border-radius: 5px;
+            color: #fff;
+            background-color: #0040ff;
+          }
+          .choose2 {
+            margin: 0 auto;
+            margin-top: 80px;
+            height: 45px;
+            line-height: 45px;
+            text-align: center;
+            font-size: 30px;
+            font-weight: bold;
+            color: #000;
+          }
+          .message {
+            margin: 0 auto;
+            margin-top: 45px;
+            width: 200px;
+            height: 45px;
+            line-height: 45px;
+            text-align: center;
+            color: #000;
+          }
+          .message2 {
+            margin: 0 auto;
+            margin-top: 45px;
+            width: 330px;
+          }
+          .tips {
+            margin-top: 10px;
+            color: #606266;
+          }
+          .form_name {
+            margin-top: 45px;
+            font-size: 10px;
+            color: #606266;
+            span {
+              margin-right: 5px;
+            }
+            i {
+              cursor: pointer;
+            }
+          }
+          .handle {
+            display: flex;
+            justify-content: space-evenly;
+            margin-top: 45px;
+            width: 400px;
+            height: 45px;
+            line-height: 45px;
+          }
+        }
+        .start {
+          margin-top: 15px;
+          margin-left: 1270px;
+          width: 110px;
+          height: 45px;
+          line-height: 45px;
+          text-align: center;
+          border-radius: 15px;
+          color: #fff;
+          font-weight: bold;
+          background-color: #ff6900;
+          cursor: pointer;
+        }
+      }
+      .button {
+        position: absolute;
+        top: 60px;
+        right: 0;
+        width: 40px;
+        height: 40px;
+        border-radius: 5px;
+        background: #1890ff url(@/assets/set.png) no-repeat center;
+        background-size: 60% 60%;
+        cursor: pointer;
+      }
+    }
+    .drawer_title {
+      flex: 1;
+      margin-left: 10px;
+      font-size: 20px;
+      font-weight: bold;
+      line-height: 200%;
+    }
+    .drawer_body {
+      flex: 15;
+      .drawer_item {
+        margin: 10px 0 10px 10px;
+        input {
+          margin: 0 5px;
+          width: 20px;
+          text-align: center;
+        }
+      }
+    }
+    .drawer_foot {
+      flex: 2;
+      text-align: center;
+      border-top: 1px solid #000;
+      .foot_button {
+        margin-top: 25px;
+      }
+    }
+  }
+}
+
+// 调整文件拖拽区域的大小
+::v-deep .el-upload-dragger {
+  width: 1214px;
+  height: 358px;
+  border: none;
+}
+
+::v-deep .el-drawer__body {
+  display: flex;
+  flex-direction: column;
+}
+</style>

+ 26 - 0
src/main.js

@@ -0,0 +1,26 @@
+import Vue from 'vue'
+import App from './App.vue'
+import router from './router'
+import axios from 'axios'
+
+import { Upload, Button, Message, Drawer, MessageBox, Progress, Dialog } from 'element-ui';
+import 'element-ui/lib/theme-chalk/index.css';
+
+Vue.use(Upload)
+Vue.use(Button)
+Vue.use(Drawer)
+Vue.use(Progress)
+Vue.use(Dialog)
+
+Vue.prototype.$message = Message;
+Vue.prototype.$confirm = MessageBox.confirm;
+
+Vue.prototype.$axios = axios;
+
+
+Vue.config.productionTip = false
+
+new Vue({
+  router,
+  render: h => h(App),
+}).$mount('#app')

+ 16 - 0
src/router/index.js

@@ -0,0 +1,16 @@
+import Vue from 'vue'
+import Router from 'vue-router'
+import Home from '@/components/Home'
+
+Vue.use(Router)
+
+export default new Router({
+    routes: [{
+        path: '/',
+        name: 'Home',
+        component: Home
+    }],
+    scrollBehavior(to, from, savedPosition) {
+        return { x: 0, y: 0 }
+    },
+})

+ 20 - 0
vue.config.js

@@ -0,0 +1,20 @@
+const { defineConfig } = require('@vue/cli-service')
+module.exports = defineConfig({
+  transpileDependencies: true,
+  lintOnSave: false,
+  devServer: {
+    // 跨域配置
+    proxy: {
+      '/api': {
+        // 线上地址
+        // target: 'https://chtech.ncjti.edu.cn/jiaofei/jiaofei-api',
+        // 本地开发地址
+        target: 'http://192.168.161.34:9999',
+        changeOrigin: true,
+        pathRewrite: {
+          '/api': ''
+        }
+      }
+    },
+  },
+})