山东大学项目实训设计系统(四)管理员端

管理员界面具体代码

代码文件结构

在这里插入图片描述

1.主界面 administrate.vue

<template>
  <el-container style="height: 100%;width: 100%">
    <el-header
      height="50px"
      style="background-color: #a40002;color: white;
    margin-top: -10px;margin-left: -8px;margin-right: -8px"
    >
      <span>山东大学审计系统</span>
      <!--      <div style="float: right">-->
      <!--        <a href="./login.vue" style="margin-right: 20px">退出</a-->
      <!--        ><span>管理员</span>-->
      <!--      </div>-->
      <div class="dropdown">
        <a class="more-menu-btn" @click="open_subMenu()">
          <i class="el-icon-menu" style="color: white;"></i>
        </a>

        <div class="user-info-box" v-show="subMenu" ref="subMenu">
          <!--          <a href="#"><i class="el-icon-chat-dot-square"></i> 消息</a>-->
          <a href="#" @click="help"> <i class="el-icon-bell"></i> 帮助</a>
          <a href="#" @click="response"
            ><i class="el-icon-edit"></i> 问题反馈</a
          >
          <a href="#" @click="exit"><i class="el-icon-lock"></i> 退出登录</a>
        </div>
      </div>
    </el-header>
    <el-container style="height: 100%;width: 100%">
      <el-aside width="200px" style="height: 100%">
        <el-menu
          :default-active="activeIndex"
          @select="handleSelect"
          style="background-color: white"
          active-text-color="#409dfe"
        >
          <el-menu-item index="1" @click="open_MUser">
            <span slot="title"
              ><i class="el-icon-edit-outline"></i>用户管理</span
            >
          </el-menu-item>
          <el-menu-item index="2" @click="open_MTemplate">
            <span slot="title"><i class="el-icon-document"></i>文件模板</span>
          </el-menu-item>
          <el-menu-item index="3" @click="open_MDataAnalyze">
            <span slot="title"><i class="el-icon-document"></i>数据分析</span>
          </el-menu-item>
          <el-menu-item index="4" @click="open_MCupBoard">
            <span slot="title"><i class="el-icon-document"></i>柜子信息</span>
          </el-menu-item>
        </el-menu>
      </el-aside>
      <el-main>
        <MUser v-show="MUser" :isShow="MUser"></MUser>
        <MTemplate v-show="MTemplate" :isShow="MTemplate"></MTemplate>
        <MDataAnalyze
          v-show="MDataAnalyze"
          :isShow="MDataAnalyze"
        ></MDataAnalyze>
        <MCupBoard v-show="MCupBoard" :isShow="MCupBoard"></MCupBoard>
      </el-main>
    </el-container>
  </el-container>
</template>

<script>
import axios from "axios";
import MUser from "../components/administrate/MUser/MUser";
import MTemplate from "../components/administrate/MTemplate/MTemplate";
import MDataAnalyze from "../components/administrate/MDataAnalyze/MDataAnalyze";
import MCupBoard from "../components/administrate/CupBoard/MCupBoard";
export default {
  name: "administrator",
  components: {
    MTemplate,
    MUser,
    MDataAnalyze,
    MCupBoard
  },
  data() {
    return {
      subMenu: false,
      MUser: false,
      MTemplate: false,
      MDataAnalyze: false,
      MCupBoard: false,

      activeIndex: "1"
    };
  },
  mounted() {
    this.MUser = true;
    //点击窗口外关闭窗口
    document.addEventListener("mouseup", e => {
      let tree1 = this.$refs.subMenu;

      if (tree1) {
        if (!tree1.contains(e.target)) {
          this.subMenu = false;
        }
      }
    });
  },
  methods: {
    response() {
      let routeUrl = this.$router.resolve({
        path: "./Response"
        // path: "./login"
      });
      window.open(routeUrl.href, "_blank");
    },
    help() {
      let routeUrl = this.$router.resolve({
        path: "./AdministrateHelp"
        // path: "./login"
      });
      window.open(routeUrl.href, "_blank");
    },
    exit() {
      this.$router.push("/login");
    },
    open_subMenu() {
      if (this.subMenu == true) this.subMenu = false;
      else this.subMenu = true;
    },
    handleSelect(e) {
      this.activeIndex = e;
    },
    open_MUser() {
      this.MUser = true;
      this.MTemplate = false;
      this.MDataAnalyze = false;
      this.MCupBoard = false;
    },
    open_MTemplate() {
      this.MUser = false;
      this.MTemplate = true;
      this.MDataAnalyze = false;
      this.MCupBoard = false;
    },
    open_MDataAnalyze() {
      this.MUser = false;
      this.MTemplate = false;
      this.MDataAnalyze = true;
      this.MCupBoard = false;
    },
    open_MCupBoard() {
      this.MUser = false;
      this.MTemplate = false;
      this.MDataAnalyze = false;
      this.MCupBoard = true;
    }
  }
};
</script>
<style scoped>
/*右上角菜单栏样式*/
.dropdown {
  right: 0px;
  top: -2px;
  background-color: #a40002;
  min-height: 40px;
  border-color: #a40002;
  height: 50px;
  display: block;
  z-index: 10;
  position: absolute;
}
.dropdown:hover {
  background-color: #960001;
}
.more-menu-btn {
  margin-top: -5px;
  padding: 5px 10px;
  display: block;
  height: 40px;
  width: auto;
  color: transparent;
  text-decoration: none;
  cursor: pointer;
}
.user-info-box {
  display: block;
  z-index: 999;
  background-color: #960001;
  width: 230px;
  right: 0;
  left: auto;
  top: 48px;
  float: left;
  position: absolute;
}
.user-info-box a {
  text-decoration: none;
  color: #ffffff;
  font-size: 15px;
  line-height: 24px;
  min-height: 44px;
  display: block;
  padding: 5px 15px;
  float: left;
  width: 100%;
  cursor: pointer;
}
.user-info-box a:hover {
  background-color: #b40001;
}
/deep/ .el-header {
  background-color: #b3c0d1;
  color: #333;
  line-height: 60px;
}

/deep/ .el-aside {
  margin-left: -20px;
  margin-right: -20px;
  background-color: white;
  height: 100%;
  border: 1px solid #a40002;
  border-top: none;
}
.el-submenu__title,
/deep/ .el-menu-item {
  color: black;
  /*background-color: #2b2b2b;*/
  background-color: white;
}
/*设置悬浮时的背景颜色统一*/
/deep/ .el-menu-item-group .el-menu-item .is-active {
  color: #fff !important;
}
/*设置子菜单宽度*/
/deep/ .el-menu-item-group .el-menu-item {
  min-width: 10px !important;
}
/deep/ .el-submenu__title:hover {
  background-color: #a40002;
}
/deep/ .el-menu-item:hover {
  background-color: #a40002;
}
/deep/ .el-menu-item.is-active {
  background-color: #a40002 !important;
  color: #fff;
}
/deep/ .el-menu-item.is-active span {
  color: #fff !important;
}
</style>
<style>
::-webkit-scrollbar {
  width: 6px;
  height: 3px;
  background-color: white;
}

/*定义滑块颜色+圆角*/
::-webkit-scrollbar-thumb {
  border-radius: 10px;
  background-color: grey;
}

/*定义滚动条轨道内阴影+圆角*/
::-webkit-scrollbar-track {
  border-radius: 10px;
  background-color: white;
}
.el-message--success .el-message__icon {
  color: #a40002;
}
.el-message--success .el-message__content {
  color: #a40002;
}
.el-message--success {
  background-color: white;
  border: 1px solid #a40002;
}
</style>

2. 各组件

2.1用户管理 MUser.vue
<template>
  <div class="Muser">
    <div style="height: 50px;">
      <el-input
        type="text"
        placeholder="请输入内容"
        size="small"
        maxlength="10"
        v-model="searchContent"
        @keyup.enter.native="search(searchContent)"
        style="width: 250px;margin-left: 740.5px"
      >
      </el-input>
      <el-button type="primary" size="small" @click="search(searchContent)"
        ><i class="el-icon-search"></i>
      </el-button>
    </div>
    <div>
      <el-table
        :data="
          tableData.slice((currentPage - 1) * pageSize, currentPage * pageSize)
        "
        height="410px"
        :row-class-name="tableRowClassName"
        style="width: 1030px;margin-left: 10px;color: black;font-weight: 400;font-size: 15px"
      >
        <el-table-column prop="index" label="序号" type="index" width="100">
          <template slot-scope="scope">
            <span>{{ scope.$index + (currentPage - 1) * pageSize + 1 }}</span>
          </template>
        </el-table-column>
        <el-table-column prop="id" label="用户id" v-if="false">
        </el-table-column>
        <el-table-column prop="username" label="工号" width="300">
        </el-table-column>
        <el-table-column prop="name" label="姓名" width="230">
        </el-table-column>
        <el-table-column prop="post" label="角色" width="280">
        </el-table-column>
        <el-table-column prop="manage" label="操作">
          <template slot-scope="scope">
            <el-button
              @click="
                open_RankUser(scope.$index + (currentPage - 1) * pageSize + 1)
              "
              type="text"
              size="small"
              style="font-weight: 400;font-size: 15px"
              >设置</el-button
            >
          </template>
        </el-table-column>
      </el-table>
      <el-pagination
        background
        @current-change="handleCurrentChange"
        :current-page="currentPage"
        layout="total,jumper,prev, pager,next"
        :total="tableData.length"
        style="margin-top: 10px"
        :page-size="pageSize"
      >
      </el-pagination>
    </div>

    <!--子组件:设置角色弹窗 -->
    <RankUser
      v-show="RankUser"
      @close_RankUser="close_RankUser"
      @refresh_User="refresh_User"
      :is-show="RankUser"
    ></RankUser>
    <div class="hidebox" v-show="RankUser"></div>
  </div>
</template>

<script scoped>
import axios from "axios";
import RankUser from "./RankUser";
import { getDate } from "../../TimeFormat";
export default {
  props: {
    isShow: Boolean
  },
  watch: {
    isShow(newValue, oldValue) {
      if (newValue == true) this.refresh_User();
    }
  },
  components: {
    RankUser
  },
  data() {
    return {
      header: "false",
      tableData: [],
      searchContent: "",

      //子组件是否显示
      RankUser: false,

      //分页
      currentPage: parseInt("1"), // 当前页码
      total: "", // 总条数
      pageSize: parseInt("6") // 每页的数据条数
    };
  },
  methods: {
    search(content) {
      if (content == "") {
        this.refresh_User();
      } else {
        axios
          .get("https://baixx.site/api/all_user?name=" + content, {
            headers: {
              token: sessionStorage.getItem("token")
            }
          })
          .then(res => {
            let userList = [];
            for (let item of res.data.content) {
              let tmp = {
                id: "",
                name: "",
                username: "",
                post: ""
              };
              tmp.id = item.id;
              tmp.name = item.name;
              tmp.username = item.username;

              let post = item.post;
              if (post == 3) {
                tmp.post = "处长";
              } else if (post == 1) {
                tmp.post = "审计员";
              } else if (post == 2) {
                tmp.post = "科长";
              } else {
                tmp.post = "管理员";
              }
              if (tmp.post == "管理员") userList.push(tmp);
            }
            this.tableData = userList;
            console.log(this.tableData);
          });
      }
    },
    handleCurrentChange(val) {
      console.log(`当前页: ${val}`);
      this.currentPage = val;
    },
    //设置table中每一行的class,达到条纹背景的效果
    tableRowClassName({ row, rowIndex }) {
      if (rowIndex % 2 === 0) {
        return "white";
      } else if (rowIndex % 2 === 1) {
        return "dark";
      }
      return "white";
    },
    open_RankUser(index) {
      this.RankUser = true;
      sessionStorage.setItem("id", this.tableData[index - 1].id);
      sessionStorage.setItem("username", this.tableData[index - 1].username);
      sessionStorage.setItem("name", this.tableData[index - 1].name);
    },
    close_RankUser() {
      this.RankUser = false;
    },
    refresh_User() {
      axios
        .get("https://baixx.site/api/all_user", {
          headers: {
            token: sessionStorage.getItem("token")
          }
        })
        .then(res => {
          let userList = [];
          for (let item of res.data.content) {
            let tmp = {
              id: "",
              name: "",
              username: "",
              post: ""
            };
            tmp.id = item.id;
            tmp.name = item.name;
            tmp.username = item.username;

            let post = item.post;
            if (post == 3) {
              tmp.post = "处长";
            } else if (post == 1) {
              tmp.post = "审计员";
            } else if (post == 2) {
              tmp.post = "科长";
            } else {
              tmp.post = "管理员";
            }
            if (tmp.post != "管理员") userList.push(tmp);
          }
          this.tableData = userList;
        });
    }
  }
};
</script>

<style scoped>
.Muser {
  margin-top: -5px;
  margin-left: 20px;
  padding-top: 10px;
  top: 20px;
  left: 20px;
  height: 505px;
  width: 1050px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.12), 0 0 6px rgba(0, 0, 0, 0.04);
  border-radius: 4px;
}
.hidebox {
  position: absolute;
  left: 0px;
  top: 0px;
  background-color: #000;
  margin: 0;
  padding: 0;
  width: 100%; /*宽度设置为100%,这样才能使隐藏背景层覆盖原页面*/
  height: 100%;
  filter: alpha(opacity = 60); /*设置透明度为60%*/
  opacity: 0.6; /*非IE浏览器下设置透明度为60%*/
  z-index: 20;
}

/*去掉el-table里的所有边框*/
/deep/ .el-table td,
.el-table th {
  border: none;
}

/*奇偶相间背景色*/
/*scope里要加上/deep/ */
/deep/ .el-table .white {
  background-color: white;
}
/deep/ .el-table .dark {
  background-color: #f6f1f1;
}
</style>

2.2 设置用户权限 RankUser.vue
<template>
  <div class="RankUser">
    <div style="margin-top: 0px;margin-bottom: 10px">
      <label style="margin-left:0px;font-size: 20px;font-weight: 700;"
        >设置用户角色</label
      >
      <el-button
        type="text"
        @click="close"
        size="small"
        style="float: right;margin-right: 5px;margin-top: -7px;background-color: transparent;"
        ><i class="el-icon-close" style="color: #666666;font-size: 20px"></i>
      </el-button>
    </div>
    <div style="margin-top: 15px"></div>
    <el-form>
      <el-form-item label="工号"
        ><el-input disabled v-model="id"></el-input
      ></el-form-item>
      <el-form-item label="姓名"
        ><el-input disabled v-model="name"></el-input
      ></el-form-item>
      <el-form-item label="角色">
        <el-select
          v-model="character"
          style="width: 100%"
          @change="handleChange"
        >
          <el-option label="审计员" value="1"></el-option>
          <el-option label="科长" value="2"></el-option>
          <el-option label="处长" value="3"></el-option> </el-select
      ></el-form-item>
    </el-form>

    <div style="text-align: center;margin-top: 65px">
      <el-button type="primary" @click="set()" style="margin-top: 0px;"
        >提交设置</el-button
      >
    </div>
  </div>
</template>

<script>
import axios from "axios";

export default {
  props: {
    isShow: Boolean
  },
  data() {
    return {
      //table中的属性
      id: "",
      username: "",
      name: "",
      post: "1",
      character: "1"
    };
  },
  watch: {
    //打开设置角色时获取当前user的id和name
    isShow(newValue, oldValue) {
      if (newValue == true) {
        this.id = sessionStorage.getItem("id");
        this.username = sessionStorage.getItem("username");
        this.name = sessionStorage.getItem("name");
      }
    }
  },
  methods: {
    handleChange(v) {
      this.post = v;
      if (v == "1") {
        this.character = "审计员";
      } else if (v == "3") {
        this.character = "处长";
      } else if (v == "2") {
        this.character = "科长";
      }
    },
    close() {
      this.$emit("close_RankUser", "");
      this.character = "审计员";
    },
    set() {
      let formData = new FormData();
      formData.append("user_id", this.id);
      formData.append("post", this.post);
      axios
        .post("https://baixx.site/api/auth", formData, {
          headers: {
            token: sessionStorage.getItem("token")
          }
        })
        .then(res => {
          this.$message.success("设置成功!");
          this.$emit("refresh_Template");
          this.close();
        });
    }
  }
};
</script>

<style scoped>
.RankUser {
  height: 450px;
  width: 500px;
  margin: auto;
  padding: 10px;
  padding-top: 20px;
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.12), 0 0 6px rgba(0, 0, 0, 0.04);
  z-index: 30;
  background-color: white;
  border-radius: 4px;
}

/deep/ .el-form-item__label {
  margin-left: 5px;
  font-size: 15px;
  font-weight: 400;
  color: #666;
}
</style>

2.3 文件模板 MTemplate.vue
<template>
  <div class="MTemplate">
    <div style="height: 50px;">
      <el-button
        type="primary"
        style="margin-left: 20px;"
        size="small"
        @click="open_TemplateUpload"
        ><i class="el-icon-circle-plus"></i>上传文件模板</el-button
      >
      <el-input
        type="text"
        placeholder="请输入内容"
        size="small"
        show-word-limit
        @keyup.enter.native="search(searchContent)"
        v-model="searchContent"
        style="width: 250px;margin-left: 600px"
      >
      </el-input>
      <el-button type="primary" size="small" @click="search(searchContent)"
        ><i class="el-icon-search"></i>
      </el-button>
    </div>

    <div>
      <el-table
        :data="
          tableData.slice((currentPage - 1) * pageSize, currentPage * pageSize)
        "
        height="410px"
        :show-header="false"
        :row-class-name="tableRowClassName"
        style="width: 1030px;margin-left: 10px;color: black;font-weight: 400;font-size: 15px"
      >
        <el-table-column
          prop="name"
          label="文件名称"
          width="750"
          style="left: 100px"
        >
        </el-table-column>
        <el-table-column v-if="false" prop="id" label="文件id">
        </el-table-column>
        <el-table-column prop="uploadDate" sortable label="日期" width="150">
        </el-table-column>
        <el-table-column prop="manage" label="操作">
          <template slot-scope="scope">
            <el-button
              @click="download(scope.$index + 1)"
              type="text"
              size="small"
              style="font-weight: 400;font-size: 15px"
              >下载</el-button
            >
            <el-button
              @click="cancel(scope.$index + 1)"
              type="text"
              size="small"
              style="font-weight: 400;font-size: 15px"
              >删除</el-button
            >
          </template>
        </el-table-column>
      </el-table>
      <el-pagination
        background
        @current-change="handleCurrentChange"
        :current-page="currentPage"
        layout="total,jumper,prev, pager,next"
        :total="tableData.length"
        style="margin-top: 10px"
        :page-size="pageSize"
      >
      </el-pagination>
    </div>

    <TemplateUpload
      v-show="TemplateUpload"
      @close_TemplateUpload="close_TemplateUpload"
      @refresh_Template="refresh_Template"
    ></TemplateUpload>
    <div class="hidebox" v-show="TemplateUpload"></div>
  </div>
</template>

<script scoped>
import axios from "axios";
import TemplateUpload from "./TemplateUpload";
import { getExactTime } from "../../TimeFormat";
import { getDate } from "../../TimeFormat";

export default {
  props: {
    isShow: Boolean
  },
  watch: {
    isShow(newValue, oldValue) {
      if (newValue == true) this.refresh_Template();
    }
  },
  components: {
    TemplateUpload
  },
  data() {
    return {
      header: "false",
      tableData: [],
      searchContent: "",

      //子组件是否显示
      TemplateUpload: false,

      //分页
      currentPage: parseInt("1"), // 当前页码
      total: "", // 总条数
      pageSize: parseInt("7") // 每页的数据条数
    };
  },
  methods: {
    search(content) {
      if (content == "") {
        this.refresh_Template();
      } else {
        axios
          .get("https://baixx.site/api/template_byname/?name=" + content, {
            headers: {
              token: sessionStorage.getItem("token")
            }
          })
          .then(res => {
            let TemplateList = [];
            for (let item of res.data.content) {
              let tmp = {
                name: "",
                id: "",
                uploadDate: ""
              };
              tmp.name = item.name;
              tmp.id = item.id;
              tmp.uploadDate = getDate(item.uploadDate);
              TemplateList.push(tmp);
            }
            // console.log(affairList);
            this.tableData = TemplateList;
          });
      }
    },
    handleCurrentChange(val) {
      console.log(`当前页: ${val}`);
      this.currentPage = val;
    },
    tableRowClassName({ row, rowIndex }) {
      if (rowIndex % 2 === 0) {
        return "white";
      } else if (rowIndex % 2 === 1) {
        return "dark";
      }
      return "white";
    },
    open_TemplateUpload() {
      this.TemplateUpload = true;
    },
    close_TemplateUpload() {
      this.TemplateUpload = false;
    },
    download(index) {
      let fileId = this.tableData[index - 1].id;
      // window.open("https://baixx.site/api/download/" + fileId, "_blank");
      let link = document.createElement("a");
      link.style.display = "none";
      link.href = "https://baixx.site/api/download/" + fileId;
      // link.download = filename;
      document.body.appendChild(link);
      link.click();
    },
    cancel(index) {
      let fileId = this.tableData[index - 1].id;
      axios
        .delete("https://baixx.site/api/template/" + fileId, {
          headers: {
            token: sessionStorage.getItem("token")
          }
        })
        .then(res => {
          this.$message.success("删除成功!");
          this.refresh_Template();
        });
    },
    refresh_Template() {
      axios
        .get("https://baixx.site/api/template", {
          headers: {
            token: sessionStorage.getItem("token")
          }
        })
        .then(res => {
          let TemplateList = [];
          for (let item of res.data.content) {
            let tmp = {
              name: "",
              id: "",
              uploadDate: ""
            };
            tmp.name = item.name;
            tmp.id = item.id;
            tmp.uploadDate = getDate(item.uploadDate);
            TemplateList.push(tmp);
          }
          // console.log(affairList);
          this.tableData = TemplateList;
        });
    }
  }
};
</script>

<style scoped>
.MTemplate {
  margin-top: -5px;
  margin-left: 20px;
  padding-top: 10px;
  top: 20px;
  left: 20px;
  height: 505px;
  width: 1050px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.12), 0 0 6px rgba(0, 0, 0, 0.04);
  border-radius: 4px;
}
.hidebox {
  position: absolute;
  left: 0px;
  top: 0px;
  background-color: #000;
  margin: 0;
  padding: 0;
  width: 100%; /*宽度设置为100%,这样才能使隐藏背景层覆盖原页面*/
  height: 100%;
  filter: alpha(opacity = 60); /*设置透明度为60%*/
  opacity: 0.6; /*非IE浏览器下设置透明度为60%*/
  z-index: 20;
}
/*去掉el-table里的所有边框*/
/deep/ .el-table td,
.el-table th {
  border: none;
}
a {
  text-decoration: none;
  color: black;
  margin-left: 30px;
}
a:hover {
  color: red;
}
/*scope里要加上/deep/ */
/deep/ .el-table .white {
  background-color: white;
}
/deep/ .el-table .dark {
  background-color: #f6f1f1;
}
</style>

2.4文件模板上传 TemplateUpload.vue
<template>
  <div class="TemPlateUpload">
    <div style="margin-top: 0px;margin-bottom: 10px">
      <label
        style="margin-left:0px;font-size: 20px;font-weight: 700;margin-left: 10px"
        >上传文件模板</label
      >
      <el-button
        type="text"
        @click="close"
        size="small"
        style="float: right;margin-right: 5px;margin-top:-7px;background-color: transparent;"
        ><i class="el-icon-close" style="color: #666666;font-size: 20px"></i>
      </el-button>
    </div>
    <div>
      <el-upload
        ref="upload"
        action="/"
        :file-list="fileList"
        :auto-upload="false"
        :on-change="handleChange"
        :on-remove="handleRemove"
        accept=".doc,.docx,.pdf"
        style="height: 320px;width: 100%;overflow-y:auto;margin-left: 10px"
      >
        <el-button size="small" type="primary">点击上传</el-button>
        <div
          slot="tip"
          class="el-upload__tip"
          style="float: right;margin-right: 0px;font-size: 10px;font-weight: lighter;color: #a40002"
        >
          <!--          (选择好报告草稿上传后不可修改)-->
        </div>
      </el-upload>
    </div>

    <div style="text-align: center">
      <el-button
        type="primary"
        @click="TemplateUpload()"
        style="margin-top: 0px;"
        >上传模板</el-button
      >
    </div>
  </div>
</template>

<script>
import axios from "axios";

export default {
  data() {
    return {
      fileList: []
    };
  },
  methods: {
    //选中文件后判断文件类型,将正确文件加入fileList中等待上传
    handleChange(file) {
      // console.log(this.fileList);
      var testmsg = file.name.substring(file.name.lastIndexOf(".") + 1);
      const extension = testmsg === "docx";
      if (testmsg != "docx" && testmsg != "doc" && testmsg != "pdf") {
        this.$message({
          message: "上传文件只能是.doc/.docx/.pdf格式!",
          type: "warning"
        });
      } else {
        this.fileList.push(file);
      }
    },
    handleRemove(file) {
      this.fileList = this.fileList.filter(one => file.name !== one.name);
    },
    close() {
      this.$emit("close_TemplateUpload", "");
      this.fileList = [];
    },
    TemplateUpload() {
      if (this.fileList.length != 0) {
        this.$message.success("上传成功!");
        // alert("上传成功!");
        let formData = new FormData();
        this.fileList.forEach(file => {
          let newFile = file.raw;
          formData.append("files", newFile);
        });
        axios
          .post("https://baixx.site/api/template", formData, {
            headers: { token: sessionStorage.getItem("token") }
          })
          .then(res => {
            this.$emit("refresh_Template");
            this.close();
          });
      } else {
        this.$message.error("请选择上传的模板文件");
        // alert(his.fileList.length);
      }
    }
  }
};
</script>

<style scoped>
.TemPlateUpload {
  height: 400px;
  width: 500px;
  margin: auto;
  padding: 10px;
  padding-top: 20px;
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.12), 0 0 6px rgba(0, 0, 0, 0.04);
  z-index: 30;
  background-color: white;
  border-radius: 4px;
}
</style>

2.5数据分析 MDataAnalyze.vue
<template>
  <div class="DataAnalyze">
    <div style="height: 120px;width:100%;margin-top:20px;padding-bottom: 20px">
      <div style="display: inline-block">
        <div class="box_bottom" style="left: 250px">
          <div class="box_title">
            <span>总事务</span>
          </div>
          <div class="box_data">
            <span>{{ count_all_affair }}</span>
          </div>
        </div>
        <div class="box_top" style="background-color: #67C23A;left: 250px">
          <i class=" el-icon-files" style="display:block;line-height: 80px"></i>
        </div>
      </div>

      <div style="display: inline-block">
        <div class="box_bottom" style="left: 450px">
          <div class="box_title">
            <span>全程跟踪</span>
          </div>
          <div class="box_data">
            <span>{{ count_all_quancheng_affair }}</span>
          </div>
        </div>
        <div class="box_top" style="background-color: #E6A23C;left: 450px">
          <i class=" el-icon-edit" style="display:block;line-height: 80px"></i>
        </div>
      </div>

      <div style="display: inline-block">
        <div class="box_bottom" style="left: 650px">
          <div class="box_title">
            <span>报销</span>
          </div>
          <div class="box_data">
            <span>{{ count_all_baoxiao_affair }}</span>
          </div>
        </div>
        <div class="box_top" style="background-color: #409EFF;left: 650px">
          <i class=" el-icon-bell" style="display:block;line-height: 80px"></i>
        </div>
      </div>

      <div style="display: inline-block">
        <div class="box_bottom" style="left: 850px">
          <div class="box_title">
            <span>已完成</span>
          </div>
          <div class="box_data">
            <span>{{ count_all_finished_affair }}</span>
          </div>
        </div>
        <div class="box_top" style="background-color: #F56C6C;left: 850px">
          <i
            class=" el-icon-document-checked"
            style="display:block;line-height: 80px"
          ></i>
        </div>
      </div>

      <div style="display: inline-block">
        <div class="box_bottom" style="left: 1050px">
          <div class="box_title">
            <span>未完成</span>
          </div>
          <div class="box_data">
            <span>{{ count_all_waiting_affair }}</span>
          </div>
        </div>
        <div class="box_top" style="background-color: #909399;left: 1050px">
          <i
            class=" el-icon-document-delete"
            style="display:block;line-height: 80px"
          ></i>
        </div>
      </div>
    </div>

    <div style="height: 335px;width: 1030px;overflow-y:auto ">
      <div id="type" class="Garaph" style="margin-left: 8px"></div>
      <div id="state" class="Garaph" style="margin-left: 8px"></div>
      <div id="finished" class="Garaph" style="margin-left: 8px"></div>
      <div id="time"></div>
    </div>
  </div>
</template>

<script scoped>
import { getExactTime } from "../../TimeFormat";
import { getDate } from "../../TimeFormat";

import axios from "axios";
export default {
  components: {},
  data() {
    return {
      header: "false",

      //统计数据
      //总事务数
      count_all_affair: "",
      //全程跟踪审计项目
      count_all_quancheng_affair: "",
      //报销审计项目
      count_all_baoxiao_affair: "",
      //已完成项目
      count_all_finished_affair: "",
      //未完成项目
      count_all_waiting_affair: "",
      //提交资料状态项目
      count_all_tijiao_affair: "",
      //审批中状态项目
      count_all_shenpizhong_affair: "",
      //审批失败状态项目
      count_all_failed_affair: "",

      //所有审计员审计实务统计信息
      auditorList: [],

      //mychart全局对象
      myChart1: "",
      myChart2: "",
      myChart3: "",
      myChart4: ""
    };
  },
  props: {
    isShow: Boolean
  },
  watch: {
    isShow(newValue, oldValue) {
      if (newValue == true) {
        this.refresh_DataAnalyze();
      }
    }
  },
  methods: {
    setGaraph() {
      this.getTypeGaraph(); //事务类型饼图
      this.getStateGaraph(); //事务状态饼图
      this.getFinishedGaraph(); //已完成、未完成饼图
      this.getTimeGaraph();
    },
    refresh_DataAnalyze() {
      axios
        .get("https://baixx.site/api/draw_info", {
          headers: {
            token: sessionStorage.getItem("token")
          }
        })
        .then(res => {
          //定义临时变量,用于统计
          //总事务数
          let count_all_affair = 0;
          //全程跟踪审计项目
          let count_all_quancheng_affair = 0;
          //报销审计项目
          let count_all_baoxiao_affair = 0;
          //已完成项目
          let count_all_finished_affair = 0;
          //未完成项目
          let count_all_waiting_affair = 0;
          //提交资料状态项目
          let count_all_tijiao_affair = 0;
          //审批中状态项目
          let count_all_shenpizhong_affair = 0;
          //审批失败状态项目
          let count_all_failed_affair = 0;

          //初始化统计所有审计员审计事务的变量
          let auditorList = [];
          let n = 0;
          //-----------遍历所有审计员---------------
          for (let item of res.data.content) {
            //当前审计员的名字
            let auditorName = item.user.name;
            let post = item.user.post;

            //初始化每个审计员的统计事务类型信息
            let count_person_all_affair = 0;
            //全程跟踪审计项目
            let count_person_quancheng_affair = 0;
            //报销审计项目
            let count_person_baoxiao_affair = 0;
            //已完成项目
            let count_person_finished_affair = 0;
            //未完成项目
            let count_person_waiting_affair = 0;
            //初始化auditor对象
            let auditor = {
              auditorName: "",
              总事务: "",
              全程跟踪: "",
              报销: "",
              已完成: "",
              未完成: ""
            };

            //审计员进入循环
            if (post == 1) {
              n++;
              //---------------遍历该审计员的所有事务---------------
              for (let affair of item.affairList) {
                //统计所有事务信息
                let type = affair.kind === 20 ? "报销审计" : "全程跟踪审计";
                let state = affair.state;
                //事务具体状态
                if (state === 10) {
                  state = "提交资料中";
                  count_all_tijiao_affair++;
                } else if (state === 11) {
                  state = "审批中";
                  count_all_shenpizhong_affair++;
                } else if (state === 12) {
                  state = "审批失败";
                  count_all_failed_affair++;
                } else if (state === 13) {
                  state = "审批结束";
                }
                //总事务数加1
                count_all_affair++;
                count_person_all_affair++;
                //事务类型
                if (type == "报销审计") {
                  count_all_baoxiao_affair++;
                  count_person_baoxiao_affair++;
                } else {
                  count_all_quancheng_affair++;
                  count_person_quancheng_affair++;
                }
                //是否完成
                if (state == "审批结束") {
                  count_all_finished_affair++;
                  count_person_finished_affair++;
                } else {
                  count_all_waiting_affair++;
                  count_person_waiting_affair++;
                }
              }
              auditor.auditorName = auditorName;
              auditor.总事务 = count_person_all_affair;
              auditor.全程跟踪 = count_person_quancheng_affair;
              auditor.报销 = count_person_baoxiao_affair;
              auditor.已完成 = count_person_finished_affair;
              auditor.未完成 = count_person_waiting_affair;
              auditorList.push(auditor);
            }
          }
          this.auditorList = auditorList;

          //头部五个统计信息赋值
          //统计数据
          this.count_all_affair = count_all_affair;
          //全程跟踪审计项目
          this.count_all_quancheng_affair = count_all_quancheng_affair;
          //报销审计项目
          this.count_all_baoxiao_affair = count_all_baoxiao_affair;
          //已完成项目
          this.count_all_finished_affair = count_all_finished_affair;
          //未完成项目
          this.count_all_waiting_affair = count_all_waiting_affair;
          //提交资料状态项目
          this.count_all_tijiao_affair = count_all_tijiao_affair;
          //审批中状态项目
          this.count_all_shenpizhong_affair = count_all_shenpizhong_affair;
          //审批失败状态项目
          this.count_all_failed_affair = count_all_failed_affair;

          //加载图表
          this.setGaraph();
        });
    },
    getTimeGaraph() {
      //直接引用进来使用
      var echarts = require("echarts");
      if (
        this.myChart1 != null &&
        this.myChart1 != "" &&
        this.myChart1 != undefined
      ) {
        this.myChart1.dispose();
      }
      // 基于准备好的dom,获取main节点init初始化echarts实例
      this.myChart1 = echarts.init(document.getElementById("time"));
      // 指定图表的配置项和数据
      var option;

      option = {
        legend: {},
        tooltip: {},
        color: ["#67C23A", "#E6A23C", "#409EFF", "#F56C6C", "#909399"],
        dataset: {
          dimensions: [
            "auditorName",
            "总事务",
            "全程跟踪",
            "报销",
            "已完成",
            "未完成"
          ],
          source: this.auditorList
        },
        xAxis: { type: "category" },
        yAxis: {},
        // Declare several bar series, each will be mapped
        // to a column of dataset.source by default.
        series: [
          { type: "bar" },
          { type: "bar" },
          { type: "bar" },
          { type: "bar" },
          { type: "bar" }
        ]
      };
      // 使用刚指定的配置项和数据显示图表。
      this.myChart1.setOption(option);
    },
    getTypeGaraph() {
      var echarts = require("echarts");
      // 基于准备好的dom,初始化echarts实例
      if (
        this.myChart2 != null &&
        this.myChart2 != "" &&
        this.myChart2 != undefined
      ) {
        this.myChart2.dispose();
      }
      this.myChart2 = echarts.init(document.getElementById("type"));
      // 指定图表的配置项和数据
      var option = {
        //这里的颜色是显示在部分扇形里的,依次调用颜色
        color: [
          "#E6A23C",
          "#409EFF",
          "#ffaa00",
          "#c2c2c2",
          "#ff55ff",
          "#ffff00",
          "#ca8622",
          "#aaaaff",
          "#aaff00",
          "#aa0000",
          "#c4ccd3"
        ],
        title: {
          text: "审计项目类型情况",
          x: "center",
          textStyle: {
            color: "#666",
            fontSize: 20
          }
        },
        legend: {
          orient: "vertical",
          // left: "left",
          bottom: "bottom",
          data: ["全程跟踪审计", "报销审计"] //名称
        },
        tooltip: {},
        series: [
          {
            // name: '营收',
            type: "pie", //饼状视图
            radius: "70%",
            data: [
              {
                value: this.count_all_quancheng_affair,
                name: "全程跟踪审计"
              },
              {
                value: this.count_all_baoxiao_affair,
                name: "报销审计"
              }
            ],
            itemStyle: {
              emphasis: {
                shadowBlur: 10,
                shadowOffsetX: 0,
                shadowColor: "rgba(0, 0, 0, 0.5)"
              }
            },
            label: {
              position: "inside", //如果需要文字显示在图形里面则设置
              normal: {
                show: true,
                formatter: "{b}: {c}({d}%)", //自定义显示格式(b:name, c:value, d:百分比)
                position: "inner"
              }
            }
          }
        ]
      };
      // 使用刚指定的配置项和数据显示图表。
      this.myChart2.setOption(option);
    },
    getStateGaraph() {
      var echarts = require("echarts");
      if (
        this.myChart3 != null &&
        this.myChart3 != "" &&
        this.myChart3 != undefined
      ) {
        this.myChart3.dispose();
      }
      // 基于准备好的dom,初始化echarts实例
      this.myChart3 = echarts.init(document.getElementById("state"));
      // 指定图表的配置项和数据
      var option = {
        //这里的颜色是显示在部分扇形里的,依次调用颜色
        color: ["#9e0909", "#67C23A", "#191d1a", "#F56C6C"],
        title: {
          text: "审计项目具体状态情况",
          x: "center",
          textStyle: {
            color: "#666",
            fontSize: "20"
          }
        },
        legend: {
          orient: "vertical",
          // left: "left",
          bottom: "bottom",
          data: ["提交资料中", "审批中", "审批失败", "审批结束"] //名称
        },
        tooltip: {},
        series: [
          {
            // name: '营收',
            type: "pie", //饼状视图
            radius: "70%",
            data: [
              {
                value: this.count_all_tijiao_affair,
                name: "提交资料中"
              },
              {
                value: this.count_all_shenpizhong_affair,
                name: "审批中"
              },
              {
                value: this.count_all_failed_affair,
                name: "审批失败"
              },
              {
                value: this.count_all_finished_affair,
                name: "审批结束"
              }
            ],
            itemStyle: {
              emphasis: {
                shadowBlur: 10,
                shadowOffsetX: 0,
                shadowColor: "rgba(0, 0, 0, 0.5)"
              }
            },
            label: {
              // position: "inside", //如果需要文字显示在图形里面则设置
              normal: {
                show: true,
                formatter: "{b}: {c}({d}%)", //自定义显示格式(b:name, c:value, d:百分比)
                position: "inner"
              }
            }
          }
        ]
      };
      // 使用刚指定的配置项和数据显示图表。
      this.myChart3.setOption(option);
    },
    getFinishedGaraph() {
      var echarts = require("echarts");
      if (
        this.myChart4 != null &&
        this.myChart4 != "" &&
        this.myChart4 != undefined
      ) {
        this.myChart4.dispose();
      }
      // 基于准备好的dom,初始化echarts实例
      this.myChart4 = echarts.init(document.getElementById("finished"));
      // 指定图表的配置项和数据
      var option = {
        //这里的颜色是显示在部分扇形里的,依次调用颜色
        color: ["#F56C6C", "#909399"],
        title: {
          text: "审计项目具体状态情况",
          x: "center",
          textStyle: {
            color: "#666",
            fontSize: "20"
          }
        },
        legend: {
          orient: "vertical",
          // left: "left",
          bottom: "bottom",
          data: ["已完成", "未完成"] //名称
        },
        tooltip: {},
        series: [
          {
            // name: '营收',
            type: "pie", //饼状视图
            radius: "70%",
            data: [
              {
                value: this.count_all_finished_affair,
                name: "已完成"
              },
              {
                value: this.count_all_waiting_affair,
                name: "未完成"
              }
            ],
            itemStyle: {
              emphasis: {
                shadowBlur: 10,
                shadowOffsetX: 0,
                shadowColor: "rgba(0, 0, 0, 0.5)"
              }
            },
            label: {
              // position: "inside", //如果需要文字显示在图形里面则设置
              normal: {
                show: true,
                formatter: "{b}: {c}({d}%)", //自定义显示格式(b:name, c:value, d:百分比)
                position: "inner"
              }
            }
          }
        ]
      };
      // 使用刚指定的配置项和数据显示图表。
      this.myChart4.setOption(option);
    }
  }
};
</script>

<style scoped>
.DataAnalyze {
  /*background-color: #ededed;*/
  margin-top: -5px;
  margin-left: 20px;
  padding-top: 10px;
  top: 20px;
  left: 20px;
  height: 505px;
  width: 1050px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.12), 0 0 6px rgba(0, 0, 0, 0.04);
  border-radius: 4px;
  /*overflow-y: auto;*/
}
.box_bottom {
  margin-top: -15px;
  position: absolute;
  width: 170px;
  height: 110px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.12), 0 0 6px rgba(0, 0, 0, 0.04);
  border-radius: 10px;
  z-index: 1;
}
.box_top {
  font-size: 40px;
  text-align: center;
  color: white;
  margin-top: -20px;
  position: absolute;
  width: 80px;
  height: 80px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.12), 0 0 6px rgba(0, 0, 0, 0.04);
  border-radius: 10px;
  z-index: 2;
}
.box_title {
  clear: both;
  position: relative;
  margin-top: 10px;
  float: left;
  left: 85px;
  font-weight: 700;
  font-size: 20px;
  color: #666;
}
.box_data {
  clear: both;
  position: relative;
  margin-top: 15px;
  float: left;
  left: 100px;
  font-weight: 500;
  font-size: 20px;
  color: #666;
}
.Garaph {
  height: 325px;
  width: 330px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.12), 0 0 6px rgba(0, 0, 0, 0.04);
  border-radius: 10px;
  display: inline-block;
  margin-top: 3px;
}
#time {
  margin-top: 55px;
  margin-left: 10px;
  margin-bottom: 5px;
  height: 325px;
  width: 1010px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.12), 0 0 6px rgba(0, 0, 0, 0.04);
  border-radius: 10px;
}
/*去掉el-table里的所有边框*/
/deep/ .el-table td,
.el-table th {
  border: none;
}
a {
  text-decoration: none;
  color: black;
  margin-left: 30px;
}
a:hover {
  color: red;
}
/*scope里要加上/deep/ */
/deep/ .el-table .white {
  background-color: white;
}
/deep/ .el-table .dark {
  background-color: #f6f1f1;
}
</style>

2.6 柜子信息 MCupBoard.vue
<template>
  <div class="MCupBoard">
    <div style="height: 50px;">
      <el-input
        type="text"
        placeholder="请输入内容"
        size="small"
        v-model="searchContent"
        @keyup.enter.native="search(searchContent)"
        style="width: 250px;margin-left: 740.5px"
      >
      </el-input>
      <el-button type="primary" size="small" @click="search(searchContent)"
        ><i class="el-icon-search"></i>
      </el-button>
    </div>
    <div>
      <el-table
        :data="
          fileList.slice((currentPage - 1) * pageSize, currentPage * pageSize)
        "
        height="410px"
        :row-class-name="tableRowClassName"
        style="width: 1030px;margin-left: 10px;color: black;font-weight: 400;font-size: 15px"
      >
        <el-table-column prop="index" label="序号" type="index" width="100">
          <template slot-scope="scope">
            <span>{{ scope.$index + (currentPage - 1) * pageSize + 1 }}</span>
          </template>
        </el-table-column>
        <el-table-column prop="fileName" label="文件名" width="500">
        </el-table-column>
        <el-table-column prop="date" label="日期" width="280">
        </el-table-column>
        <el-table-column prop="boardNumber" label="柜号"> </el-table-column>
      </el-table>
      <el-pagination
        background
        @current-change="handleCurrentChange"
        :current-page="currentPage"
        layout="total,jumper,prev, pager,next"
        :total="fileList.length"
        style="margin-top: 10px"
        :page-size="pageSize"
      >
      </el-pagination>
    </div>
  </div>
</template>

<script scoped>
import axios from "axios";
import { getDate } from "../../TimeFormat";

export default {
  props: {
    isShow: Boolean
  },
  watch: {
    isShow(newValue, oldValue) {
      if (newValue == true) this.refresh_CupBoard();
    }
  },
  data() {
    return {
      header: "false",
      fileList: [],
      searchContent: "",

      //分页
      currentPage: parseInt("1"), // 当前页码
      total: "", // 总条数
      pageSize: parseInt("6") // 每页的数据条数
    };
  },
  methods: {
    search(content) {
      if (content == "") {
        this.refresh_CupBoard();
      } else {
        axios
          .get("https://baixx.site/api/cupboard/status/?name=" + content, {
            headers: {
              token: sessionStorage.getItem("token")
            }
          })
          .then(res => {
            let fileList = [];
            for (let item of res.data.content) {
              let tmp = {
                fileName: "",
                date: "",
                boardNumber: ""
              };
              tmp.fileName = item.name;
              tmp.date = getDate(item.uploadDate);
              tmp.boardNumber = item.storageId;
              fileList.push(tmp);
            }
            this.fileList = fileList;
          });
      }
    },
    handleCurrentChange(val) {
      console.log(`当前页: ${val}`);
      this.currentPage = val;
    },
    //设置table中每一行的class,达到条纹背景的效果
    tableRowClassName({ row, rowIndex }) {
      if (rowIndex % 2 === 0) {
        return "white";
      } else if (rowIndex % 2 === 1) {
        return "dark";
      }
      return "white";
    },
    refresh_CupBoard() {
      axios
        .get("https://baixx.site/api/cupboard/status", {
          headers: {
            token: sessionStorage.getItem("token")
          }
        })
        .then(res => {
          let fileList = [];
          for (let item of res.data.content) {
            let tmp = {
              fileName: "",
              date: "",
              boardNumber: ""
            };
            tmp.fileName = item.name;
            tmp.date = getDate(item.uploadDate);
            tmp.boardNumber = item.storageId;
            fileList.push(tmp);
          }
          this.fileList = fileList;
        });
    }
  }
};
</script>

<style scoped>
.MCupBoard {
  margin-top: -5px;
  margin-left: 20px;
  padding-top: 10px;
  top: 20px;
  left: 20px;
  height: 505px;
  width: 1050px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.12), 0 0 6px rgba(0, 0, 0, 0.04);
  border-radius: 4px;
}
.hidebox {
  position: absolute;
  left: 0px;
  top: 0px;
  background-color: #000;
  margin: 0;
  padding: 0;
  width: 100%; /*宽度设置为100%,这样才能使隐藏背景层覆盖原页面*/
  height: 100%;
  filter: alpha(opacity = 60); /*设置透明度为60%*/
  opacity: 0.6; /*非IE浏览器下设置透明度为60%*/
  z-index: 2;
}

/*去掉el-table里的所有边框*/
/deep/ .el-table td,
.el-table th {
  border: none;
}

/*奇偶相间背景色*/
/*scope里要加上/deep/ */
/deep/ .el-table .white {
  background-color: white;
}
/deep/ .el-table .dark {
  background-color: #f6f1f1;
}
</style>

管理员界面展示

1. 用户管理

用户管理模块呈现了当前的所有用户,可以对普通用户的角色进行修改。
在这里插入图片描述
在这里插入图片描述

2. 文件模板

文件模板模块中管理员可以对文件模板进行上传、下载、删除操作,在右上角可以根据文件名进行模糊搜索。
在这里插入图片描述在这里插入图片描述

3. 数据分析

数据分析模块呈现了了对所有审计员审计项目的统计信息,如总项目数、已完成、未完成项目数等,并且统计了具体每个审计员的审计项目情况。
在这里插入图片描述

在这里插入图片描述

4. 柜子信息

柜子信息模块呈现了存放于储物柜中的所有文件信息的储存信息,在右上角可以对文件名进行模糊搜索。
在这里插入图片描述

Python网络爬虫与推荐算法新闻推荐平台:网络爬虫:通过Python实现新浪新闻的爬取,可爬取新闻页面上的标题、文本、图片、视频链接(保留排版) 推荐算法:权重衰减+标签推荐+区域推荐+热点推荐.zip项目工程资源经过严格测试可直接运行成功且功能正常的情况才上传,可轻松复刻,拿到资料包后可轻松复现出一样的项目,本人系统开发经验充足(全领域),有任何使用问题欢迎随时与我联系,我会及时为您解惑,提供帮助。 【资源内容】:包含完整源码+工程文件+说明(如有)等。答辩评审平均分达到96分,放心下载使用!可轻松复现,设计报告也可借鉴此项目,该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的。 【提供帮助】:有任何使用问题欢迎随时与我联系,我会及时解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 下载后请首先打开README文件(如有),项目工程可直接复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值