Pc端OA管理系统解决方案


# 概述

OA 管理系统是公司内部使用的一个管理系统,它能够能够高效,便捷的协助公司进行管理,有通讯录模块,请加模块,公告模块,任务模块,客户模块等等。通过编写 OA 管理系统,对 ElementUI 的掌握更进一步,对 Vue 框架的使用更加熟悉,且在项目中遇到的问题总结如下。

key=value&key=value import qs from "querystring"; const res = await this.$axios.post( "api/indoor/AddAdmin", qs.stringify({ ...this.addAdmin, token: this.token }) );
  • 解决跨域问题
    在根目录新建 vue.config.js

    module.exports = {
      // cli3 代理是从指定的target后面开始匹配的,不是任意位置;配置pathRewrite可以做替换
      devServer: {
        port: "8080",
        open: true,
        proxy: {
          "/api": {
            // /api 的意义在于,声明axios中url已/api开头的请求都适用于该规则,
            // 注意是以/api开头,即:axios.post({url: '/api/xxx/xxx'})
            target: "https://oa.baixiucn.cn/",
            // 此处target的意义在于:造成跨域是因为访
            // 问的host与我们的请求头里的origin不一致,所以我们要设置成一致,这个具体请看下文
            changeOrigin: true,
            pathRewrite: { "^/api": "" },
            // 此处是大部分文章都不会明说的的地方,
            // 既然我们设置了代理,则所有请求url都已写成/api/xxx/xxx,那请求如何知道我们到底请求的是哪个服务器的数据呢
            // 因此这里的意义在于, 以 /api开头的url请求,代理都会知道实际上应该请求那里,
            // ‘我是服务器/api’,后面的/api根据实际请求地址决定,即我的请求url:/api/test/test,被代理后请求的则是
            // https://我是服务器/api/test/test
          },
        },
      },
    };
  • 上传图片问题

    • upload.js

      const BASE_URL = "https://oa.baixiucn.cn/";
      import axios from "axios";
      export default (file) =>
        new Promise((res) => {
          // 传文件必须放在 FormData 中,FormData对象会自动将这个文件处理之后发给后台
          const fromData = new FormData();
          // 给 fromData 添加一个属性
          fromData.append("file", file);
          axios({
            url: BASE_URL + "api/article/uploadsum1",
            method: "post",
            data: fromData,
            headers: {
              "Content-Type": "multipart/form-data",
            },
          })
            .then((_res) => {
              // 如果第一项(null)为真就证明失败了,第二项是我要的数据
              res([null, BASE_URL + _res]);
            })
            .catch((_err) => {
              res([_err, null]);
            });
        });
    • pathJoin.js

      export default (url) => {
        if (url.indexOf("http") !== -1) {
          return url;
        } else {
          return "https://oa.baixiucn.cn/" + url;
        }
      };
    • main.js

      import joinUrl from "@/utils/pathJoin";
      Vue.prototype.joinUrl = joinUrl;
    • case.vue

      <template>
        <div class="fileBox">
          <input type="file" @change="_input" name="file" class="file" />
          <img :src="blobURL || joinUrl(userinfoList.avatar)" />
        </div>
      </template>
      <script>
        import qs from "querystring";
        import upload from "@/utils/upload";
        export default {
          name: "datiDersonali",
          data() {
            return {
              userinfoList: [],
              editUser: {
                nickname: "",
                avatar: null,
                password: "",
                email: "",
              },
              file: null,
              blobURL: null,
            };
          },
          methods: {
            async editEvent() {
              let image_url_res = "";
              if (this.file) {
                image_url_res = await upload(this.file);
                if (image_url_res[0]) {
                  alert("头像上传失败,请重新上传!!!");
                  return;
                }
              }
              const res = await this.$axios.post(
                "api/Indoor/UpdateAdmin",
                qs.stringify({
                  ...this.editUser,
                  token: this.userinfoList.token,
                  avatar: image_url_res[1],
                })
              );
            },
            async _input(e) {
              this.file = e.target.files[0];
              this.blobURL = URL.createObjectURL(this.file);
            },
          },
        };
      </script>
  • 扁平化数组

    arr.forEach((item) => {
      this.flatArr = [...this.flatArr, ...item.data];
    });
  • ElementUI 中 select 多选问题

    看 option 中 value 绑定的是什么值,那么 select 绑定的就应该和 value 中要求的值一样
    然后将请求回来的数据,修改成 select 中要求的值的类型
    这个项目是使用 try_catch 解决的,也可以用其他方案解决
  • 省市区三级联动

    • 博客:https://blog.csdn.net/yelin042/article/details/80146437

    • 安装:npm i v-distpicker --save

    • 方法:

      • province 选择省份 (返回省份的值)
      • city 选择城市 (返回城市的值)
      • selected 选择最后一项时触发 (返回省市区的值)
    • 案例

      <template>
        <el-form-item label="地区">
          <v-distpicker
            :province="user.xtrysf"
            :city="user.xtrycs"
            hide-area
            @province="onChangeProvince"
            @city="onChangeCity"
          >
          <-distpicker>
        </el-form-item>
      </template>
      
      <script>
        import vDistpicker from "v-distpicker";
        export default {
          components: { vDistpicker },
          methods: {
            onChangeProvince(data) {
              this.user.xtrysf = data.value;
            },
            onChangeCity(data) {
              this.user.xtrycs = data.value;
            },
            // 选择省市区 onSelect
            onSelected(data) {
              this.addCompanyCustomer.address.province = data.province.value;
              this.addCompanyCustomer.address.city = data.city.value;
              this.addCompanyCustomer.address.area = data.area.value;
            },
          },
        };
      </script>
  • Tree 组件

    getCheckedNodes 若节点可被选择(即 show-checkbox 为 true),则返回目前被选中的节点所组成的数组
    getCheckedKeys 若节点可被选择(即 show-checkbox 为 true),则返回目前被选中的节点的 key 所组成的数组

    this.$refs.tree.getCheckedNodes()返回目前被选中的节点所组成的数组
    
    const a = res.data;
    let arr = [];
    function digui(a) {
      for (let i = 0; i < a.length; i++) {
        if (a[i].child.length !== 0) {
          digui(a[i].child);
        } else {
          arr.push(a[i].id);
        }
      }
    }
    digui(a);
    this.editList = arr;
  • 图片多选问题

    const BASE_URL = "https://oa.baixiucn.cn/";
    import axios from "axios";
    export default function urploadFile(pathArr) {
      return new Promise((res) => {
        let index = 0;
        const resArr = [];
        up(pathArr[index]);
        function up(file) {
          // 传文件必须放在 FormData 中,FormData对象会自动将这个文件处理之后发给后台
          const fromData = new FormData();
          // 给 fromData 添加一个属性
          fromData.append("file", file);
          axios({
            url: BASE_URL + "api/article/uploadsum1",
            method: "post",
            data: fromData,
            headers: {
              "Content-Type": "multipart/form-data",
            },
          })
            .then((_res) => {
              index++;
              resArr.push(_res);
              if (index >= pathArr.length) {
                res([0, resArr]);
                return;
              } else {
                up(pathArr[index]);
              }
            })
            .catch((err) => res([err, 0]));
        }
      });
    }
  • 打包之后的 map 文件问题

    可能很多人在做vue项目打包,打包之后js中,会自动生成一些map文件,怎么把它去掉不要呢?
    运行 cnpm run build 开始打包后会在项目目录下自动创建dist目录,打包好的文件都在其中
    解决办法:去src/config/index.js中改一个参数:
    productionSourceMap:false
    把这个改为false。不然在最终打包的文件中会出现一些map文件
    
    map文件的作用:项目打包后,代码都是经过压缩加密的,如果运行时报错,输出的错误信息无法准确得知是哪里的代码报错。
    有了map就可以像未加密的代码一样,准确的输出是哪一行哪一列有错。
  • 打包之后白屏问题

    打包之后,会出现白屏的问题
    这是因为找不到文件,需要将引用本地图片的链接改成线上的链接
    路由懒加载可能会导致缺少文件的问题,将懒加载去掉换成直接引入的方式

  • 文章作者: Mrr-cxh
    版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Mrr-cxh !
    赏
     上一篇
    React 1.0 React 1.0
    React 是一个声明式,高效且灵活的用于构建用户界面的 JavaScript 库。使用 React 可以将一些简短、独立的代码片段组合成复杂的 UI 界面,这些代码片段被称作“组件”。
    2021-09-11
    下一篇 
    uni-app uni-app
    uni-app 是一个使用 Vue.js 开发所有前端应用的框架,开发者编写一套代码,可发布到iOS、Android、Web(响应式)、以及各种小程序(微信/支付宝/百度/头条/QQ/钉钉/淘宝)、快应用等多个平台。
    2021-07-14
      目录