heimawl
2023-06-02 6e7acd5062824d5aae2ed345898d761a93879de0
组件库整理,依赖安装、excel导入导入方法整理
已添加7个文件
已修改22个文件
1317 ■■■■ 文件已修改
package.json 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/styles/variables.scss 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Breadcrumb/index.vue 55 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DictTag/index.vue 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Editor/index.vue 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/FileUpload/index.vue 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Hamburger/index.vue 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/HeaderSearch/index.vue 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/IconSelect/index.vue 88 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/ImagePreview/index.vue 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/ImageUpload/index.vue 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/PageTools/index.vue 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Pagination/index.vue 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/PanThumb/index.vue 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/RightToolbar/index.vue 40 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Screenfull/index.vue 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/SizeSelect/index.vue 53 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/SvgIcon/index.vue 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/ThemePicker/index.vue 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/TopNav/index.vue 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/UploadExcel/index.vue 169 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/UploadImg/index.vue 116 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/iFrame/index.vue 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/index.js 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/constant/employees.js 429 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/filters/index.js 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main.js 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/store/modules/settings.js 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/import/index.vue 55 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
package.json
@@ -40,9 +40,11 @@
    "axios": "0.24.0",
    "clipboard": "2.0.8",
    "core-js": "3.25.3",
    "cos-js-sdk-v5": "^1.4.18",
    "dayjs": "^1.11.7",
    "echarts": "5.4.0",
    "element-ui": "2.15.12",
    "file-saver": "2.0.5",
    "file-saver": "^2.0.5",
    "fuse.js": "6.4.3",
    "highlight.js": "9.18.5",
    "js-beautify": "1.13.0",
@@ -59,7 +61,8 @@
    "vue-meta": "2.4.0",
    "vue-router": "3.4.9",
    "vuedraggable": "2.24.3",
    "vuex": "3.6.0"
    "vuex": "3.6.0",
    "xlsx": "^0.18.5"
  },
  "devDependencies": {
    "@vue/cli-plugin-babel": "4.4.6",
@@ -77,6 +80,7 @@
    "sass": "1.32.13",
    "sass-loader": "10.1.1",
    "script-ext-html-webpack-plugin": "2.1.5",
    "script-loader": "^0.7.2",
    "svg-sprite-loader": "5.1.1",
    "vue-template-compiler": "2.6.12"
  },
src/assets/styles/variables.scss
@@ -3,7 +3,7 @@
$light-blue:#3A71A8;
$red:#C03639;
$pink: #E65D6E;
$green: #30B08F;
$green: #2ef0bf;
$tiffany: #4AB7BD;
$yellow:#FEC171;
$panGreen: #30B08F;
src/components/Breadcrumb/index.vue
@@ -1,8 +1,13 @@
<!-- é¡¶éƒ¨è·¯å¾„ -->
<template>
  <el-breadcrumb class="app-breadcrumb" separator="/">
    <transition-group name="breadcrumb">
      <el-breadcrumb-item v-for="(item,index) in levelList" :key="item.path">
        <span v-if="item.redirect === 'noRedirect' || index == levelList.length - 1" class="no-redirect">{{ item.meta.title }}</span>
      <el-breadcrumb-item v-for="(item, index) in levelList" :key="item.path">
        <span
          v-if="item.redirect === 'noRedirect' || index == levelList.length - 1"
          class="no-redirect"
          >{{ item.meta.title }}</span
        >
        <a v-else @click.prevent="handleLink(item)">{{ item.meta.title }}</a>
      </el-breadcrumb-item>
    </transition-group>
@@ -13,50 +18,54 @@
export default {
  data() {
    return {
      levelList: null
    }
      levelList: null,
    };
  },
  watch: {
    $route(route) {
      // if you go to the redirect page, do not update the breadcrumbs
      if (route.path.startsWith('/redirect/')) {
        return
      if (route.path.startsWith("/redirect/")) {
        return;
      }
      this.getBreadcrumb()
    }
      this.getBreadcrumb();
    },
  },
  created() {
    this.getBreadcrumb()
    this.getBreadcrumb();
  },
  methods: {
    getBreadcrumb() {
      // only show routes with meta.title
      let matched = this.$route.matched.filter(item => item.meta && item.meta.title)
      const first = matched[0]
      let matched = this.$route.matched.filter(
        (item) => item.meta && item.meta.title
      );
      const first = matched[0];
      if (!this.isDashboard(first)) {
        matched = [{ path: '/index', meta: { title: '首页' }}].concat(matched)
        matched = [{ path: "/index", meta: { title: "首页" } }].concat(matched);
      }
      this.levelList = matched.filter(item => item.meta && item.meta.title && item.meta.breadcrumb !== false)
      this.levelList = matched.filter(
        (item) => item.meta && item.meta.title && item.meta.breadcrumb !== false
      );
    },
    isDashboard(route) {
      const name = route && route.name
      const name = route && route.name;
      if (!name) {
        return false
        return false;
      }
      return name.trim() === 'Index'
      return name.trim() === "Index";
    },
    handleLink(item) {
      const { redirect, path } = item
      const { redirect, path } = item;
      if (redirect) {
        this.$router.push(redirect)
        return
        this.$router.push(redirect);
        return;
      }
      this.$router.push(path)
    }
  }
}
      this.$router.push(path);
    },
  },
};
</script>
<style lang="scss" scoped>
src/components/DictTag/index.vue
@@ -36,7 +36,7 @@
  },
  computed: {
    values() {
      if (this.value !== null && typeof this.value !== 'undefined') {
      if (this.value !== null && typeof this.value !== "undefined") {
        return Array.isArray(this.value) ? this.value : [String(this.value)];
      } else {
        return [];
@@ -49,4 +49,4 @@
.el-tag + .el-tag {
  margin-left: 10px;
}
</style>
</style>
src/components/Editor/index.vue
@@ -1,3 +1,4 @@
<!-- ä¸Šä¼ å›¾ç‰‡s -->
<template>
  <div>
    <el-upload
src/components/FileUpload/index.vue
@@ -1,3 +1,4 @@
<!-- ä¸Šä¼ æ–‡ä»¶ -->
<template>
  <div class="upload-file">
    <el-upload
@@ -19,20 +20,38 @@
      <!-- ä¸Šä¼ æç¤º -->
      <div class="el-upload__tip" slot="tip" v-if="showTip">
        è¯·ä¸Šä¼ 
        <template v-if="fileSize"> å¤§å°ä¸è¶…过 <b style="color: #f56c6c">{{ fileSize }}MB</b> </template>
        <template v-if="fileType"> æ ¼å¼ä¸º <b style="color: #f56c6c">{{ fileType.join("/") }}</b> </template>
        <template v-if="fileSize">
          å¤§å°ä¸è¶…过 <b style="color: #f56c6c">{{ fileSize }}MB</b>
        </template>
        <template v-if="fileType">
          æ ¼å¼ä¸º <b style="color: #f56c6c">{{ fileType.join("/") }}</b>
        </template>
        çš„æ–‡ä»¶
      </div>
    </el-upload>
    <!-- æ–‡ä»¶åˆ—表 -->
    <transition-group class="upload-file-list el-upload-list el-upload-list--text" name="el-fade-in-linear" tag="ul">
      <li :key="file.url" class="el-upload-list__item ele-upload-list__item-content" v-for="(file, index) in fileList">
        <el-link :href="`${baseUrl}${file.url}`" :underline="false" target="_blank">
    <transition-group
      class="upload-file-list el-upload-list el-upload-list--text"
      name="el-fade-in-linear"
      tag="ul"
    >
      <li
        :key="file.url"
        class="el-upload-list__item ele-upload-list__item-content"
        v-for="(file, index) in fileList"
      >
        <el-link
          :href="`${baseUrl}${file.url}`"
          :underline="false"
          target="_blank"
        >
          <span class="el-icon-document"> {{ getFileName(file.name) }} </span>
        </el-link>
        <div class="ele-upload-list__item-content-action">
          <el-link :underline="false" @click="handleDelete(index)" type="danger">删除</el-link>
          <el-link :underline="false" @click="handleDelete(index)" type="danger"
            >删除</el-link
          >
        </div>
      </li>
    </transition-group>
@@ -65,8 +84,8 @@
    // æ˜¯å¦æ˜¾ç¤ºæç¤º
    isShowTip: {
      type: Boolean,
      default: true
    }
      default: true,
    },
  },
  data() {
    return {
@@ -86,9 +105,9 @@
        if (val) {
          let temp = 1;
          // é¦–先将值转为数组
          const list = Array.isArray(val) ? val : this.value.split(',');
          const list = Array.isArray(val) ? val : this.value.split(",");
          // ç„¶åŽå°†æ•°ç»„转为对象数组
          this.fileList = list.map(item => {
          this.fileList = list.map((item) => {
            if (typeof item === "string") {
              item = { name: item, url: item };
            }
@@ -101,8 +120,8 @@
        }
      },
      deep: true,
      immediate: true
    }
      immediate: true,
    },
  },
  computed: {
    // æ˜¯å¦æ˜¾ç¤ºæç¤º
@@ -115,11 +134,13 @@
    handleBeforeUpload(file) {
      // æ ¡æ£€æ–‡ä»¶ç±»åž‹
      if (this.fileType) {
        const fileName = file.name.split('.');
        const fileName = file.name.split(".");
        const fileExt = fileName[fileName.length - 1];
        const isTypeOk = this.fileType.indexOf(fileExt) >= 0;
        if (!isTypeOk) {
          this.$modal.msgError(`文件格式不正确, è¯·ä¸Šä¼ ${this.fileType.join("/")}格式文件!`);
          this.$modal.msgError(
            `文件格式不正确, è¯·ä¸Šä¼ ${this.fileType.join("/")}格式文件!`
          );
          return false;
        }
      }
@@ -142,7 +163,7 @@
    // ä¸Šä¼ å¤±è´¥
    handleUploadError(err) {
      this.$modal.msgError("上传文件失败,请重试");
      this.$modal.closeLoading()
      this.$modal.closeLoading();
    },
    // ä¸Šä¼ æˆåŠŸå›žè°ƒ
    handleUploadSuccess(res, file) {
@@ -187,9 +208,9 @@
      for (let i in list) {
        strs += list[i].url + separator;
      }
      return strs != '' ? strs.substr(0, strs.length - 1) : '';
    }
  }
      return strs != "" ? strs.substr(0, strs.length - 1) : "";
    },
  },
};
</script>
src/components/Hamburger/index.vue
@@ -1,3 +1,4 @@
<!-- svg图标封装 -->
<template>
  <div style="padding: 0 15px;" @click="toggleClick">
    <svg
src/components/HeaderSearch/index.vue
@@ -1,3 +1,4 @@
<!-- ä½¿ç”¨å…¨å±€svgicon图标 -->
<template>
  <div :class="{'show':show}" class="header-search">
    <svg-icon class-name="search-icon" icon-class="search" @click.stop="click" />
src/components/IconSelect/index.vue
@@ -1,12 +1,24 @@
<!-- @author zhengjie -->
<!-- è‡ªå®šä¹‰å›¾æ ‡åç§°å°è£… -->
<template>
  <div class="icon-body">
    <el-input v-model="name" style="position: relative;" clearable placeholder="请输入图标名称" @clear="filterIcons" @input.native="filterIcons">
    <el-input
      v-model="name"
      style="position: relative"
      clearable
      placeholder="请输入图标名称"
      @clear="filterIcons"
      @input.native="filterIcons"
    >
      <i slot="suffix" class="el-icon-search el-input__icon" />
    </el-input>
    <div class="icon-list">
      <div v-for="(item, index) in iconList" :key="index" @click="selectedIcon(item)">
        <svg-icon :icon-class="item" style="height: 30px;width: 16px;" />
      <div
        v-for="(item, index) in iconList"
        :key="index"
        @click="selectedIcon(item)"
      >
        <svg-icon :icon-class="item" style="height: 30px; width: 16px" />
        <span>{{ item }}</span>
      </div>
    </div>
@@ -14,55 +26,57 @@
</template>
<script>
import icons from './requireIcons'
import icons from "./requireIcons";
export default {
  name: 'IconSelect',
  name: "IconSelect",
  data() {
    return {
      name: '',
      iconList: icons
    }
      name: "",
      iconList: icons,
    };
  },
  methods: {
    filterIcons() {
      this.iconList = icons
      this.iconList = icons;
      if (this.name) {
        this.iconList = this.iconList.filter(item => item.includes(this.name))
        this.iconList = this.iconList.filter((item) =>
          item.includes(this.name)
        );
      }
    },
    selectedIcon(name) {
      this.$emit('selected', name)
      document.body.click()
      this.$emit("selected", name);
      document.body.click();
    },
    reset() {
      this.name = ''
      this.iconList = icons
    }
  }
}
      this.name = "";
      this.iconList = icons;
    },
  },
};
</script>
<style rel="stylesheet/scss" lang="scss" scoped>
  .icon-body {
    width: 100%;
    padding: 10px;
    .icon-list {
      height: 200px;
      overflow-y: scroll;
      div {
        height: 30px;
        line-height: 30px;
        margin-bottom: -5px;
        cursor: pointer;
        width: 33%;
        float: left;
      }
      span {
        display: inline-block;
        vertical-align: -0.15em;
        fill: currentColor;
        overflow: hidden;
      }
.icon-body {
  width: 100%;
  padding: 10px;
  .icon-list {
    height: 200px;
    overflow-y: scroll;
    div {
      height: 30px;
      line-height: 30px;
      margin-bottom: -5px;
      cursor: pointer;
      width: 33%;
      float: left;
    }
    span {
      display: inline-block;
      vertical-align: -0.15em;
      fill: currentColor;
      overflow: hidden;
    }
  }
}
</style>
src/components/ImagePreview/index.vue
@@ -1,3 +1,4 @@
<!-- image图片容器封装 -->
<template>
  <el-image
    :src="`${realSrc}`"
src/components/ImageUpload/index.vue
@@ -1,3 +1,4 @@
<!-- ä¸Šä¼ æ–‡ä»¶å°è£… -->
<template>
  <div class="component-upload-image">
    <el-upload
@@ -15,16 +16,20 @@
      :headers="headers"
      :file-list="fileList"
      :on-preview="handlePictureCardPreview"
      :class="{hide: this.fileList.length >= this.limit}"
      :class="{ hide: this.fileList.length >= this.limit }"
    >
      <i class="el-icon-plus"></i>
    </el-upload>
    <!-- ä¸Šä¼ æç¤º -->
    <div class="el-upload__tip" slot="tip" v-if="showTip">
      è¯·ä¸Šä¼ 
      <template v-if="fileSize"> å¤§å°ä¸è¶…过 <b style="color: #f56c6c">{{ fileSize }}MB</b> </template>
      <template v-if="fileType"> æ ¼å¼ä¸º <b style="color: #f56c6c">{{ fileType.join("/") }}</b> </template>
      <template v-if="fileSize">
        å¤§å°ä¸è¶…过 <b style="color: #f56c6c">{{ fileSize }}MB</b>
      </template>
      <template v-if="fileType">
        æ ¼å¼ä¸º <b style="color: #f56c6c">{{ fileType.join("/") }}</b>
      </template>
      çš„æ–‡ä»¶
    </div>
@@ -55,7 +60,7 @@
    },
    // å¤§å°é™åˆ¶(MB)
    fileSize: {
       type: Number,
      type: Number,
      default: 5,
    },
    // æ–‡ä»¶ç±»åž‹, ä¾‹å¦‚['png', 'jpg', 'jpeg']
@@ -66,8 +71,8 @@
    // æ˜¯å¦æ˜¾ç¤ºæç¤º
    isShowTip: {
      type: Boolean,
      default: true
    }
      default: true,
    },
  },
  data() {
    return {
@@ -81,7 +86,7 @@
      headers: {
        Authorization: "Bearer " + getToken(),
      },
      fileList: []
      fileList: [],
    };
  },
  watch: {
@@ -89,14 +94,14 @@
      handler(val) {
        if (val) {
          // é¦–先将值转为数组
          const list = Array.isArray(val) ? val : this.value.split(',');
          const list = Array.isArray(val) ? val : this.value.split(",");
          // ç„¶åŽå°†æ•°ç»„转为对象数组
          this.fileList = list.map(item => {
          this.fileList = list.map((item) => {
            if (typeof item === "string") {
              if (item.indexOf(this.baseUrl) === -1) {
                  item = { name: this.baseUrl + item, url: this.baseUrl + item };
                item = { name: this.baseUrl + item, url: this.baseUrl + item };
              } else {
                  item = { name: item, url: item };
                item = { name: item, url: item };
              }
            }
            return item;
@@ -107,8 +112,8 @@
        }
      },
      deep: true,
      immediate: true
    }
      immediate: true,
    },
  },
  computed: {
    // æ˜¯å¦æ˜¾ç¤ºæç¤º
@@ -125,7 +130,7 @@
        if (file.name.lastIndexOf(".") > -1) {
          fileExtension = file.name.slice(file.name.lastIndexOf(".") + 1);
        }
        isImg = this.fileType.some(type => {
        isImg = this.fileType.some((type) => {
          if (file.type.indexOf(type) > -1) return true;
          if (fileExtension && fileExtension.indexOf(type) > -1) return true;
          return false;
@@ -135,7 +140,9 @@
      }
      if (!isImg) {
        this.$modal.msgError(`文件格式不正确, è¯·ä¸Šä¼ ${this.fileType.join("/")}图片格式文件!`);
        this.$modal.msgError(
          `文件格式不正确, è¯·ä¸Šä¼ ${this.fileType.join("/")}图片格式文件!`
        );
        return false;
      }
      if (this.fileSize) {
@@ -167,8 +174,8 @@
    },
    // åˆ é™¤å›¾ç‰‡
    handleDelete(file) {
      const findex = this.fileList.map(f => f.name).indexOf(file.name);
      if(findex > -1) {
      const findex = this.fileList.map((f) => f.name).indexOf(file.name);
      if (findex > -1) {
        this.fileList.splice(findex, 1);
        this.$emit("input", this.listToString(this.fileList));
      }
@@ -202,25 +209,25 @@
          strs += list[i].url.replace(this.baseUrl, "") + separator;
        }
      }
      return strs != '' ? strs.substr(0, strs.length - 1) : '';
    }
  }
      return strs != "" ? strs.substr(0, strs.length - 1) : "";
    },
  },
};
</script>
<style scoped lang="scss">
// .el-upload--picture-card æŽ§åˆ¶åŠ å·éƒ¨åˆ†
::v-deep.hide .el-upload--picture-card {
    display: none;
  display: none;
}
// åŽ»æŽ‰åŠ¨ç”»æ•ˆæžœ
::v-deep .el-list-enter-active,
::v-deep .el-list-leave-active {
    transition: all 0s;
  transition: all 0s;
}
::v-deep .el-list-enter, .el-list-leave-active {
    opacity: 0;
    transform: translateY(0);
::v-deep .el-list-enter,
.el-list-leave-active {
  opacity: 0;
  transform: translateY(0);
}
</style>
src/components/PageTools/index.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,42 @@
<!-- tag标签封装 -->
<template>
  <el-card class="box-card">
    <el-row type="flex">
      <el-col>
        <el-tag v-if="isShowLeft">
          <i :class="leftIon"></i>
          <slot name="left-tag" />
        </el-tag>
      </el-col>
      <el-col>
        <el-row type="flex" justify="end">
          <slot name="right" />
        </el-row>
      </el-col>
    </el-row>
  </el-card>
</template>
<script>
export default {
  name: "PageTools",
  data() {
    return {};
  },
  props: {
    leftIon: {
      type: String,
      default: "el-icon-info",
    },
    isShowLeft: {
      type: Boolean,
      default: true,
    },
  },
  created() {},
  methods: {},
};
</script>
<style lang="less" scoped></style>
src/components/Pagination/index.vue
@@ -1,3 +1,5 @@
<!-- åº•部分页组件封装 -->
<template>
  <div :class="{'hidden':hidden}" class="pagination-container">
    <el-pagination
src/components/PanThumb/index.vue
@@ -1,3 +1,4 @@
<!-- å›¾ç‰‡å±•示页面 -->
<template>
  <div :style="{zIndex:zIndex,height:height,width:width}" class="pan-item">
    <div class="pan-info">
src/components/RightToolbar/index.vue
@@ -1,14 +1,42 @@
<!-- é¼ æ ‡è§¦å‘弹出成 -->
<template>
  <div class="top-right-btn" :style="style">
    <el-row>
      <el-tooltip class="item" effect="dark" :content="showSearch ? '隐藏搜索' : '显示搜索'" placement="top" v-if="search">
        <el-button size="mini" circle icon="el-icon-search" @click="toggleSearch()" />
      <el-tooltip
        class="item"
        effect="dark"
        :content="showSearch ? '隐藏搜索' : '显示搜索'"
        placement="top"
        v-if="search"
      >
        <el-button
          size="mini"
          circle
          icon="el-icon-search"
          @click="toggleSearch()"
        />
      </el-tooltip>
      <el-tooltip class="item" effect="dark" content="刷新" placement="top">
        <el-button size="mini" circle icon="el-icon-refresh" @click="refresh()" />
        <el-button
          size="mini"
          circle
          icon="el-icon-refresh"
          @click="refresh()"
        />
      </el-tooltip>
      <el-tooltip class="item" effect="dark" content="显隐列" placement="top" v-if="columns">
        <el-button size="mini" circle icon="el-icon-menu" @click="showColumn()" />
      <el-tooltip
        class="item"
        effect="dark"
        content="显隐列"
        placement="top"
        v-if="columns"
      >
        <el-button
          size="mini"
          circle
          icon="el-icon-menu"
          @click="showColumn()"
        />
      </el-tooltip>
    </el-row>
    <el-dialog :title="title" :visible.sync="open" append-to-body>
@@ -58,7 +86,7 @@
        ret.marginRight = `${this.gutter / 2}px`;
      }
      return ret;
    }
    },
  },
  created() {
    // æ˜¾éšåˆ—初始默认隐藏列
src/components/Screenfull/index.vue
@@ -1,3 +1,4 @@
<!-- å›¾æ ‡ç‚¹å‡»æ”¾å¤§ -->
<template>
  <div>
    <svg-icon :icon-class="isFullscreen?'exit-fullscreen':'fullscreen'" @click="click" />
src/components/SizeSelect/index.vue
@@ -1,10 +1,16 @@
<!-- ä¸‹æ‹‰èœå•封装 -->
<template>
  <el-dropdown trigger="click" @command="handleSetSize">
    <div>
      <svg-icon class-name="size-icon" icon-class="size" />
    </div>
    <el-dropdown-menu slot="dropdown">
      <el-dropdown-item v-for="item of sizeOptions" :key="item.value" :disabled="size===item.value" :command="item.value">
      <el-dropdown-item
        v-for="item of sizeOptions"
        :key="item.value"
        :disabled="size === item.value"
        :command="item.value"
      >
        {{ item.label }}
      </el-dropdown-item>
    </el-dropdown-menu>
@@ -16,41 +22,40 @@
  data() {
    return {
      sizeOptions: [
        { label: 'Default', value: 'default' },
        { label: 'Medium', value: 'medium' },
        { label: 'Small', value: 'small' },
        { label: 'Mini', value: 'mini' }
      ]
    }
        { label: "Default", value: "default" },
        { label: "Medium", value: "medium" },
        { label: "Small", value: "small" },
        { label: "Mini", value: "mini" },
      ],
    };
  },
  computed: {
    size() {
      return this.$store.getters.size
    }
      return this.$store.getters.size;
    },
  },
  methods: {
    handleSetSize(size) {
      this.$ELEMENT.size = size
      this.$store.dispatch('app/setSize', size)
      this.refreshView()
      this.$ELEMENT.size = size;
      this.$store.dispatch("app/setSize", size);
      this.refreshView();
      this.$message({
        message: 'Switch Size Success',
        type: 'success'
      })
        message: "Switch Size Success",
        type: "success",
      });
    },
    refreshView() {
      // In order to make the cached page re-rendered
      this.$store.dispatch('tagsView/delAllCachedViews', this.$route)
      this.$store.dispatch("tagsView/delAllCachedViews", this.$route);
      const { fullPath } = this.$route
      const { fullPath } = this.$route;
      this.$nextTick(() => {
        this.$router.replace({
          path: '/redirect' + fullPath
        })
      })
    }
  }
}
          path: "/redirect" + fullPath,
        });
      });
    },
  },
};
</script>
src/components/SvgIcon/index.vue
@@ -1,47 +1,53 @@
<!-- svg封装 -->
<template>
  <div v-if="isExternal" :style="styleExternalIcon" class="svg-external-icon svg-icon" v-on="$listeners" />
  <div
    v-if="isExternal"
    :style="styleExternalIcon"
    class="svg-external-icon svg-icon"
    v-on="$listeners"
  />
  <svg v-else :class="svgClass" aria-hidden="true" v-on="$listeners">
    <use :xlink:href="iconName" />
  </svg>
</template>
<script>
import { isExternal } from '@/utils/validate'
import { isExternal } from "@/utils/validate";
export default {
  name: 'SvgIcon',
  name: "SvgIcon",
  props: {
    iconClass: {
      type: String,
      required: true
      required: true,
    },
    className: {
      type: String,
      default: ''
    }
      default: "",
    },
  },
  computed: {
    isExternal() {
      return isExternal(this.iconClass)
      return isExternal(this.iconClass);
    },
    iconName() {
      return `#icon-${this.iconClass}`
      return `#icon-${this.iconClass}`;
    },
    svgClass() {
      if (this.className) {
        return 'svg-icon ' + this.className
        return "svg-icon " + this.className;
      } else {
        return 'svg-icon'
        return "svg-icon";
      }
    },
    styleExternalIcon() {
      return {
        mask: `url(${this.iconClass}) no-repeat 50% 50%`,
        '-webkit-mask': `url(${this.iconClass}) no-repeat 50% 50%`
      }
    }
  }
}
        "-webkit-mask": `url(${this.iconClass}) no-repeat 50% 50%`,
      };
    },
  },
};
</script>
<style scoped>
@@ -55,7 +61,7 @@
.svg-external-icon {
  background-color: currentColor;
  mask-size: cover!important;
  mask-size: cover !important;
  display: inline-block;
}
</style>
src/components/ThemePicker/index.vue
@@ -1,3 +1,4 @@
<!-- é¢œè‰²é€‰æ‹©å™¨ -->
<template>
  <el-color-picker
    v-model="theme"
src/components/TopNav/index.vue
@@ -1,3 +1,4 @@
<!-- é¡¶éƒ¨å¯¼èˆªå°è£… -->
<template>
  <el-menu
    :default-active="activeMenu"
@@ -5,14 +6,22 @@
    @select="handleSelect"
  >
    <template v-for="(item, index) in topMenus">
      <el-menu-item :style="{'--theme': theme}" :index="item.path" :key="index" v-if="index < visibleNumber"
      <el-menu-item
        :style="{ '--theme': theme }"
        :index="item.path"
        :key="index"
        v-if="index < visibleNumber"
        ><svg-icon :icon-class="item.meta.icon" />
        {{ item.meta.title }}</el-menu-item
      >
    </template>
    <!-- é¡¶éƒ¨èœå•超出数量折叠 -->
    <el-submenu :style="{'--theme': theme}" index="more" v-if="topMenus.length > visibleNumber">
    <el-submenu
      :style="{ '--theme': theme }"
      index="more"
      v-if="topMenus.length > visibleNumber"
    >
      <template slot="title">更多菜单</template>
      <template v-for="(item, index) in topMenus">
        <el-menu-item
@@ -31,7 +40,7 @@
import { constantRoutes } from "@/router";
// éšè—ä¾§è¾¹æ è·¯ç”±
const hideList = ['/index', '/user/profile'];
const hideList = ["/index", "/user/profile"];
export default {
  data() {
@@ -39,7 +48,7 @@
      // é¡¶éƒ¨æ åˆå§‹æ•°
      visibleNumber: 5,
      // å½“前激活菜单的 index
      currentIndex: undefined
      currentIndex: undefined,
    };
  },
  computed: {
@@ -53,9 +62,9 @@
        if (menu.hidden !== true) {
          // å…¼å®¹é¡¶éƒ¨æ ä¸€çº§èœå•内部跳转
          if (menu.path === "/") {
              topMenus.push(menu.children[0]);
            topMenus.push(menu.children[0]);
          } else {
              topMenus.push(menu);
            topMenus.push(menu);
          }
        }
      });
@@ -71,11 +80,12 @@
      this.routers.map((router) => {
        for (var item in router.children) {
          if (router.children[item].parentPath === undefined) {
            if(router.path === "/") {
            if (router.path === "/") {
              router.children[item].path = "/" + router.children[item].path;
            } else {
              if(!this.ishttp(router.children[item].path)) {
                router.children[item].path = router.path + "/" + router.children[item].path;
              if (!this.ishttp(router.children[item].path)) {
                router.children[item].path =
                  router.path + "/" + router.children[item].path;
              }
            }
            router.children[item].parentPath = router.path;
@@ -89,25 +99,29 @@
    activeMenu() {
      const path = this.$route.path;
      let activePath = path;
      if (path !== undefined && path.lastIndexOf("/") > 0 && hideList.indexOf(path) === -1) {
      if (
        path !== undefined &&
        path.lastIndexOf("/") > 0 &&
        hideList.indexOf(path) === -1
      ) {
        const tmpPath = path.substring(1, path.length);
        activePath = "/" + tmpPath.substring(0, tmpPath.indexOf("/"));
        if (!this.$route.meta.link) {
          this.$store.dispatch('app/toggleSideBarHide', false);
          this.$store.dispatch("app/toggleSideBarHide", false);
        }
      } else if(!this.$route.children) {
      } else if (!this.$route.children) {
        activePath = path;
        this.$store.dispatch('app/toggleSideBarHide', true);
        this.$store.dispatch("app/toggleSideBarHide", true);
      }
      this.activeRoutes(activePath);
      return activePath;
    },
  },
  beforeMount() {
    window.addEventListener('resize', this.setVisibleNumber)
    window.addEventListener("resize", this.setVisibleNumber);
  },
  beforeDestroy() {
    window.removeEventListener('resize', this.setVisibleNumber)
    window.removeEventListener("resize", this.setVisibleNumber);
  },
  mounted() {
    this.setVisibleNumber();
@@ -121,18 +135,18 @@
    // èœå•选择事件
    handleSelect(key, keyPath) {
      this.currentIndex = key;
      const route = this.routers.find(item => item.path === key);
      const route = this.routers.find((item) => item.path === key);
      if (this.ishttp(key)) {
        // http(s):// è·¯å¾„新窗口打开
        window.open(key, "_blank");
      } else if (!route || !route.children) {
        // æ²¡æœ‰å­è·¯ç”±è·¯å¾„内部打开
        this.$router.push({ path: key });
        this.$store.dispatch('app/toggleSideBarHide', true);
        this.$store.dispatch("app/toggleSideBarHide", true);
      } else {
        // æ˜¾ç¤ºå·¦ä¾§è”动菜单
        this.activeRoutes(key);
        this.$store.dispatch('app/toggleSideBarHide', false);
        this.$store.dispatch("app/toggleSideBarHide", false);
      }
    },
    // å½“前激活的路由
@@ -145,15 +159,15 @@
          }
        });
      }
      if(routes.length > 0) {
      if (routes.length > 0) {
        this.$store.commit("SET_SIDEBAR_ROUTERS", routes);
      } else {
        this.$store.dispatch('app/toggleSideBarHide', true);
        this.$store.dispatch("app/toggleSideBarHide", true);
      }
    },
    ishttp(url) {
      return url.indexOf('http://') !== -1 || url.indexOf('https://') !== -1
    }
      return url.indexOf("http://") !== -1 || url.indexOf("https://") !== -1;
    },
  },
};
</script>
@@ -168,8 +182,9 @@
  margin: 0 10px !important;
}
.topmenu-container.el-menu--horizontal > .el-menu-item.is-active, .el-menu--horizontal > .el-submenu.is-active .el-submenu__title {
  border-bottom: 2px solid #{'var(--theme)'} !important;
.topmenu-container.el-menu--horizontal > .el-menu-item.is-active,
.el-menu--horizontal > .el-submenu.is-active .el-submenu__title {
  border-bottom: 2px solid #{"var(--theme)"} !important;
  color: #303133;
}
src/components/UploadExcel/index.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,169 @@
<!-- excel文件上传 -->
<template>
  <div class="upload-excel">
    <div class="btn-upload">
      <el-button
        :loading="loading"
        size="mini"
        type="primary"
        @click="handleUpload"
      >
        ç‚¹å‡»ä¸Šä¼ 
      </el-button>
    </div>
    <input
      ref="excel-upload-input"
      class="excel-upload-input"
      type="file"
      accept=".xlsx, .xls"
      @change="handleClick"
    />
    <div
      class="drop"
      @drop="handleDrop"
      @dragover="handleDragover"
      @dragenter="handleDragover"
    >
      <i class="el-icon-upload" />
      <span>将文件拖到此处</span>
    </div>
  </div>
</template>
<script>
import XLSX from "xlsx";
export default {
  name: "UploadExcel",
  props: {
    beforeUpload: Function, // eslint-disable-line
    onSuccess: Function, // eslint-disable-line
  },
  data() {
    return {
      loading: false,
      excelData: {
        header: null,
        results: null,
      },
    };
  },
  methods: {
    generateData({ header, results }) {
      this.excelData.header = header;
      this.excelData.results = results;
      this.onSuccess && this.onSuccess(this.excelData);
    },
    handleDrop(e) {
      e.stopPropagation();
      e.preventDefault();
      if (this.loading) return;
      const files = e.dataTransfer.files;
      if (files.length !== 1) {
        this.$message.error("Only support uploading one file!");
        return;
      }
      const rawFile = files[0]; // only use files[0]
      if (!this.isExcel(rawFile)) {
        this.$message.error(
          "Only supports upload .xlsx, .xls, .csv suffix files"
        );
        return false;
      }
      this.upload(rawFile);
      e.stopPropagation();
      e.preventDefault();
    },
    handleDragover(e) {
      e.stopPropagation();
      e.preventDefault();
      e.dataTransfer.dropEffect = "copy";
    },
    handleUpload() {
      this.$refs["excel-upload-input"].click();
    },
    handleClick(e) {
      const files = e.target.files;
      const rawFile = files[0]; // only use files[0]
      if (!rawFile) return;
      this.upload(rawFile);
    },
    upload(rawFile) {
      this.$refs["excel-upload-input"].value = null; // fix can't select the same excel
      if (!this.beforeUpload) {
        this.readerData(rawFile);
        return;
      }
      const before = this.beforeUpload(rawFile);
      if (before) {
        this.readerData(rawFile);
      }
    },
    readerData(rawFile) {
      this.loading = true;
      return new Promise((resolve, reject) => {
        const reader = new FileReader();
        reader.onload = (e) => {
          const data = e.target.result;
          const workbook = XLSX.read(data, { type: "array" });
          const firstSheetName = workbook.SheetNames[0];
          const worksheet = workbook.Sheets[firstSheetName];
          const header = this.getHeaderRow(worksheet);
          const results = XLSX.utils.sheet_to_json(worksheet);
          this.generateData({ header, results });
          this.loading = false;
          resolve();
        };
        reader.readAsArrayBuffer(rawFile);
      });
    },
    getHeaderRow(sheet) {
      const headers = [];
      const range = XLSX.utils.decode_range(sheet["!ref"]);
      let C;
      const R = range.s.r;
      /* start in the first row */
      for (C = range.s.c; C <= range.e.c; ++C) {
        /* walk every column in the range */
        const cell = sheet[XLSX.utils.encode_cell({ c: C, r: R })];
        /* find the cell in the first row */
        let hdr = "UNKNOWN " + C; // <-- replace with your desired default
        if (cell && cell.t) hdr = XLSX.utils.format_cell(cell);
        headers.push(hdr);
      }
      return headers;
    },
    isExcel(file) {
      return /\.(xlsx|xls|csv)$/.test(file.name);
    },
  },
};
</script>
<style scoped lang="scss">
.upload-excel {
  display: flex;
  justify-content: center;
  margin-top: 100px;
  .excel-upload-input {
    display: none;
    z-index: -9999;
  }
  .btn-upload,
  .drop {
    border: 1px dashed #bbb;
    width: 350px;
    height: 160px;
    text-align: center;
    line-height: 160px;
  }
  .drop {
    line-height: 80px;
    color: #bbb;
    i {
      font-size: 60px;
      display: block;
    }
  }
}
</style>
src/components/UploadImg/index.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,116 @@
<!-- å›¾ç‰‡ä¸Šä¼ å°è£… -->
<template>
  <div>
    <el-upload
      :file-list="filelist"
      v-loading="loading"
      element-loading-text="拼命加载中"
      element-loading-spinner="el-icon-loading"
      element-loading-background="rgba(0, 0, 0, 0.8)"
      action="https://jsonplaceholder.typicode.com/posts/"
      :http-request="uoloadimg"
      :on-change="onChange"
      :on-remove="onRemove"
      :on-preview="onPreview"
      :before-upload="onBeforeUpload"
      list-type="picture-card"
      :limit="1"
      :class="filelist.length === 1 ? 'father' : ''"
      class="custom-upload"
    >
      <i class="el-icon-plus"></i>
    </el-upload>
    <el-dialog :visible.sync="fileonPreview">
      <img :src="fileimg" alt="" />
    </el-dialog>
  </div>
</template>
<script>
import COS from "cos-js-sdk-v5";
var cos = new COS({
  SecretId: "AKIDxlNmyua2FDwSjmeHGVVHxNYVghSyFhus",
  SecretKey: "nPp8D5mKgomaBawHPI1avzuhJhqombCZ",
});
console.log(cos);
export default {
  name: "UploadImg",
  data() {
    return {
      filelist: [],
      fileimg: "",
      fileonPreview: false,
      loading: false,
    };
  },
  created() {},
  methods: {
    // å‘送图片上传
    uoloadimg({ file }) {
      this.loading = true;
      cos.putObject(
        {
          Bucket: "hmhr-31-1313341522" /* å¿…é¡» */,
          Region: "ap-shanghai" /* å­˜å‚¨æ¡¶æ‰€åœ¨åœ°åŸŸï¼Œå¿…须字段 */,
          Key: file.name /* å¿…é¡» */,
          StorageClass: "STANDARD",
          Body: file, // ä¸Šä¼ æ–‡ä»¶å¯¹è±¡
          onProgress: function (progressData) {
            console.log(JSON.stringify(progressData));
          },
        },
        (err, data) => {
          this.loading = false;
          if (err || data.statusCode != 200) {
            return this.$$message.error("");
          }
          this.$emit("onSuccess", {
            url: "https://" + data.Location,
          });
        }
      );
    },
    // å­˜å‚¨å›¾ç‰‡åˆ—表
    onChange(file, filelist) {
      this.filelist = filelist;
    },
    //删除
    onRemove(file, filelist) {
      this.filelist = filelist;
    },
    // é¢„览
    onPreview(file) {
      console.log(file);
      this.fileonPreview = true;
      this.fileimg = file.url;
    },
    // ä¸Šä¼ å‰åˆ¤æ–­
    onBeforeUpload(file) {
      console.log(file);
      const types = ["image/jpeg", "image/png", "image/gif"];
      if (!types.includes(file.type)) {
        this.$message.error("请选择" + types.join(", ") + "格式图片");
        return false;
      }
      const maxSize = 1024 * 1024 * 2;
      if (file.size > maxSize) {
        this.$message.error("选择图片不超过2mb");
        return false;
      }
    },
  },
};
</script>
<style lang="scss" scoped>
.father .el-upload--picture-card {
  display: none;
}
.custom-upload {
  width: 148px;
  height: 148px;
  overflow: hidden;
}
</style>
src/components/iFrame/index.vue
@@ -1,3 +1,4 @@
<!-- é¡µé¢å†…嵌入封装 -->
<template>
  <div v-loading="loading" :style="'height:' + height">
    <iframe
src/components/index.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,11 @@
import PageTools from "@/components/PageTools"
import UploadExcel from "@/components/UploadExcel"
import UploadImg from "@/components/UploadImg"
const component=[PageTools,UploadExcel,UploadImg]
export default{
    install(Vue){
        component.forEach((component)=>{
            Vue.component(component.name,component)
        })
    }
}
src/constant/employees.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,429 @@
// å‘˜å·¥
export default {
  // è˜ç”¨å½¢å¼
  hireType: [
    {
      id: 1,
      value: '正式'
    },
    {
      id: 2,
      value: '非正式'
    }
  ],
  // ç®¡ç†å½¢å¼
  subjection: [
    {
      id: '1',
      value: '总部'
    },
    {
      id: '2',
      value: '分城市'
    }
  ],
  // åœ¨èŒçŠ¶æ€
  workingState: [
    {
      id: '1',
      value: '在职'
    },
    {
      id: '2',
      value: '离职'
    }
  ],
  // ç¦»èŒç±»åž‹
  leaveType: [
    {
      id: '1',
      value: '主动离职'
    },
    {
      id: '2',
      value: '被动离职'
    },
    {
      id: '3',
      value: '退休'
    }
  ],
  // å‡å‘˜æœˆ
  attritionMonth: [
    {
      id: '1',
      value: '离职日本月'
    },
    {
      id: '2',
      value: '离职日次月'
    }
  ],
  // è˜ç”¨å½¢å¼
  informaltype: [
    {
      id: '2',
      value: '实习'
    },
    {
      id: '3',
      value: '劳务'
    },
    {
      id: '4',
      value: '顾问'
    },
    {
      id: '5',
      value: '返聘'
    },
    {
      id: '6',
      value: '外包'
    }
  ],
  // æœ€é«˜å­¦åކ
  highestDegree: [
    {
      id: '1',
      value: '初中'
    },
    {
      id: '2',
      value: '高中'
    },
    {
      id: '3',
      value: '中专'
    },
    {
      id: '4',
      value: '大专'
    },
    {
      id: '5',
      value: '本科'
    },
    {
      id: '6',
      value: '硕士'
    },
    {
      id: '7',
      value: '博士'
    },
    {
      id: '8',
      value: '其他'
    }
  ],
  // å›½å®¶/地区
  isOverseas: [
    {
      id: '1',
      value: '中国大陆'
    },
    {
      id: '2',
      value: '港澳台国外'
    }
  ],
  // æ€§åˆ«
  gender: [
    {
      id: '1',
      value: '男'
    },
    {
      id: '2',
      value: '女'
    }
  ],
  // å©šå§»çж况
  maritaStatus: [
    {
      id: '1',
      value: '未婚'
    },
    {
      id: '2',
      value: '已婚'
    },
    {
      id: '3',
      value: '离异'
    }
  ],
  // ç”Ÿè‚–
  animalSymbol: [
    {
      id: '1',
      value: 'é¼ '
    },
    {
      id: '2',
      value: '牛'
    },
    {
      id: '3',
      value: '虎'
    },
    {
      id: '4',
      value: '兔'
    },
    {
      id: '5',
      value: '龙'
    },
    {
      id: '6',
      value: '蛇'
    },
    {
      id: '7',
      value: '马'
    },
    {
      id: '8',
      value: '羊'
    },
    {
      id: '9',
      value: '猴'
    },
    {
      id: '10',
      value: '鸡'
    },
    {
      id: '11',
      value: '狗'
    },
    {
      id: '12',
      value: '猪'
    }
  ],
  // æ˜Ÿåº§
  constellation: [
    {
      code: 1,
      value: '水瓶座'
    },
    {
      code: 2,
      value: '双鱼座'
    },
    {
      code: 3,
      value: '白羊座'
    },
    {
      code: 4,
      value: '金牛座'
    },
    {
      code: 5,
      value: '双子座'
    },
    {
      code: 6,
      value: '巨蟹座'
    },
    {
      code: 7,
      value: '狮子座'
    },
    {
      code: 8,
      value: '处女座'
    },
    {
      code: 9,
      value: '天秤座'
    },
    {
      code: 10,
      value: '天蝎座'
    },
    {
      code: 11,
      value: '射手座'
    },
    {
      code: 12,
      value: '摩羯座'
    }
  ],
  // è¡€åž‹
  bloodType: [
    {
      id: '1',
      value: 'A型'
    },
    {
      id: '2',
      value: 'B型'
    },
    {
      id: '3',
      value: 'O型'
    },
    {
      id: '4',
      value: 'AB型'
    }
  ],
  // å­¦åކ
  educationType: [
    {
      id: '1',
      value: '统招'
    },
    {
      id: '2',
      value: '自考'
    },
    {
      id: '3',
      value: '成考'
    }
  ],
  // è½¬æ­£
  positiveType: [
    {
      id: '1',
      value: '已转正'
    },
    {
      id: '2',
      value: '未转正'
    }
  ],
  // åˆåŒæœŸé™
  contractPeriod: [
    {
      id: '1',
      value: '6月'
    },
    {
      id: '2',
      value: '12月'
    },
    {
      id: '3',
      value: '24月'
    },
    {
      id: '4',
      value: '36月'
    },
    {
      id: '5',
      value: '其他'
    }
  ],
  // ç­¾çº¦æ¬¡æ•°
  renewalCount: [
    {
      id: 1,
      value: '0次'
    },
    {
      id: 2,
      value: '1次'
    },
    {
      id: 3,
      value: '2次'
    },
    {
      id: 4,
      value: '3次'
    },
    {
      id: 5,
      value: '4次或以上'
    }
  ],
  // ç®€åŽ†æ¥æº
  resumeSource: [
    {
      id: '1',
      value: '智联招聘'
    },
    {
      id: '2',
      value: '拉勾网'
    },
    {
      id: '3',
      value: '前程无忧'
    },
    {
      id: '4',
      value: '猎聘网'
    },
    {
      id: '5',
      value: '校园宣讲'
    },
    {
      id: '6',
      value: '猎头'
    },
    {
      id: '7',
      value: '内部推荐'
    }
  ],
  // ç¤¾æ‹›/校招
  hireSourceType: [
    {
      id: '1',
      value: '社招'
    },
    {
      id: '2',
      value: '校招'
    }
  ],
  // æ–°åŠ 
  // éƒ¨é—¨
  departments: [
    {
      id: '1',
      value: '总裁办'
    },
    {
      id: '2',
      value: '研究院'
    }
  ],
  // èŒä½çŠ¶æ€
  stausInfos: [
    {
      id: '1',
      value: '在职'
    },
    {
      id: '2',
      value: '入职'
    },
    {
      id: '3',
      value: '离职'
    }
  ],
  // ä¸Šä¼ æ•°æ®è¡¨å¤´
  importMapKeyPath: {
    å…¥èŒæ—¥æœŸ: 'timeOfEntry',
    å§“名: "username",
    å·¥å·: "workNumber",
    æ‰‹æœºå·: "mobile",
    è½¬æ­£æ—¥æœŸ: "correctionTime"
}
}
src/filters/index.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,5 @@
import dayjs from 'dayjs';
// è¿‡æ»¤å™¨
export const formatTime=(val)=>{
    return dayjs(val).format('YYYY-MM-DD')
  }
src/main.js
@@ -37,6 +37,14 @@
import VueMeta from 'vue-meta'
// å­—典数据组件
import DictData from '@/components/DictData'
// ç»„件封装集成
import components from './components'
// æ³¨å†Œè¿‡æ»¤å™¨
import * as filters from './filters'
for(let key in filters){
Vue.filter(key, filters[key])
}
// å…¨å±€æ–¹æ³•挂载
Vue.prototype.getDicts = getDicts
@@ -62,6 +70,7 @@
Vue.use(plugins)
Vue.use(VueMeta)
DictData.install()
Vue.use(components)
/**
 * If you don't want to use mock-server
src/store/modules/settings.js
@@ -5,7 +5,7 @@
const storageSetting = JSON.parse(localStorage.getItem('layout-setting')) || ''
const state = {
  title: '',
  theme: storageSetting.theme || '#409EFF',
  theme: storageSetting.theme || '#2ef0bf',
  sideTheme: storageSetting.sideTheme || sideTheme,
  showSettings: showSettings,
  topNav: storageSetting.topNav === undefined ? topNav : storageSetting.topNav,
src/views/import/index.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,55 @@
<template>
  <div>
    <UploadExcel :deforeUpload="excelSuccess" :onSuccess="onSuccess" />
  </div>
</template>
<script>
//等待api接口
// import { importEmployee } from "@/api/index";
import employees from "@/constant/employees";
import formatTime from "@/filters/index";
const { importMapKeyPath } = employees;
export default {
  data() {
    return {};
  },
  created() {},
  methods: {
    // ä¸Šä¼ å‰è§¦å‘
    excelSuccess({ name }) {
      if (!name.endsWith(".xlsx")) {
        return this.$message("请选择xlsx文件");
      }
      return true;
    },
    // è§£æžæˆåŠŸåŽè§¦å‘
    async onSuccess({ results, header }) {
      const neWArr = results.map((item) => {
        const obj = {};
        for (let key in importMapKeyPath) {
          if (key === "入职时间" || key === "转正时间") {
            // excel时间戳
            const timestamp = item[key];
            // è½¬æ ¼å¼ï¼Œå¹¶å¯¹æ¯”效验差时间
            const date = new Date((timestamp - 1) * 24 * 3600000);
            date.setFullYear(data.setFullYear() - 70);
            obj[importMapKeyPath[key]] = formatTime(date);
          } else {
            obj[importMapKeyPath[key]] = item[key];
          }
        }
        return obj;
      });
      // await importEmployee(neWArr);
      this.$message.success("导入成功");
      this.$router.go(-1);
      console.log(neWArr);
    },
  },
};
</script>
<style lang="less" scoped></style>