xiatian %!s(int64=4) %!d(string=hai) anos
pai
achega
4a4c506225

+ 2 - 0
src/main.js

@@ -3,6 +3,8 @@ import App from "./App.vue";
 import router from "./router";
 import store from "./store";
 // import "./registerServiceWorker";
+import "./components/registerComponents";
+import "./modules/questions/component/registerComponents";
 import "./plugins/element.js";
 import "./plugins/axios";
 import "./plugins/vueAwesome";

+ 4 - 8
src/modules/portal/views/home/HomeSide.vue

@@ -105,22 +105,18 @@ export default {
   },
   async created() {
     this.group = routesToMenu.find((v) => this.$route.path.startsWith(v.path));
-    const groupCode = this.group && this.group.groupCode;
-    if (groupCode) {
-      this.menuList = await this.getUserPrivileges(groupCode);
-      this.UPDATE_MENU_LIST(this.menuList);
-      this.updatePath();
-    }
+    this.menuList = await this.getUserPrivileges();
+    this.UPDATE_MENU_LIST(this.menuList);
+    this.updatePath();
   },
   methods: {
     ...mapMutations([UPDATE_CURRENT_PATHS, UPDATE_MENU_LIST]),
     toggoleSidebar() {
       this.isCollapse = !this.isCollapse;
     },
-    async getUserPrivileges(groupCode) {
+    async getUserPrivileges() {
       var url = QUESTION_API + "/rolePrivilege/getUserPrivileges";
       const params = new URLSearchParams();
-      params.append("groupCode", groupCode);
       params.append("full", false);
       const res = await this.$httpWithMsg.post(url, params, {
         headers: { "content-type": "application/x-www-form-urlencoded" },

+ 2 - 3
src/modules/portal/views/home/main/HomeMain.vue

@@ -70,13 +70,12 @@ export default {
     ...mapState({ user: (state) => state.user }),
   },
   async created() {
-    this.menuList = await this.getUserPrivileges("PORTAL_MENUS");
+    this.menuList = await this.getUserPrivileges();
   },
   methods: {
-    async getUserPrivileges(groupCode) {
+    async getUserPrivileges() {
       var url = QUESTION_API + "/rolePrivilege/getUserPrivileges";
       const params = new URLSearchParams();
-      params.append("groupCode", groupCode);
       params.append("full", false);
       const res = await this.$httpWithMsg.post(url, params, {
         headers: { "content-type": "application/x-www-form-urlencoded" },

+ 38 - 0
src/modules/questions/component/registerComponents.js

@@ -0,0 +1,38 @@
+import Vue from "vue";
+// import upperFirst from "lodash/upperFirst";
+// import camelCase from "lodash/camelCase";
+
+const requireComponent = require.context(
+  // The relative path of the components folder
+  "./",
+  // Whether or not to look in subfolders
+  false,
+  // The regular expression used to match base component filenames
+  /[A-Z]\w+\.(vue|js)$/
+);
+
+requireComponent.keys().forEach((fileName) => {
+  // Get component config
+  const componentConfig = requireComponent(fileName);
+
+  // Get PascalCase name of component
+  const componentName =
+    // upperFirst(
+    //   camelCase(
+    // Gets the file name regardless of folder depth
+    fileName
+      .split("/")
+      .pop()
+      .replace(/\.\w+$/, "");
+  //   )
+  // );
+
+  // Register component globally
+  Vue.component(
+    componentName,
+    // Look for the component options on `.default`, which will
+    // exist if the component was exported with `export default`,
+    // otherwise fall back to module's root.
+    componentConfig.default || componentConfig
+  );
+});

+ 12 - 0
src/modules/questions/routes/routes.js

@@ -22,6 +22,8 @@ import Tips from "../../portal/views/tips/Tips.vue";
 import ExportTemplate from "../views/ExportTemplate.vue";
 import School from "../views/School.vue";
 import Course from "../views/Course.vue";
+import user from "../views/user.vue";
+import data_previllege from "../views/data_previllege.vue";
 
 export default [
   {
@@ -38,6 +40,16 @@ export default [
         meta: { privilegeCodes: "index_school" },
         component: School,
       },
+      {
+        path: "user", //用户管理
+        meta: { privilegeCodes: "index_user" },
+        component: user,
+      },
+      {
+        path: "user/data_previllege/:userId", //用户管理
+        meta: { privilegeCodes: "index_user" },
+        component: data_previllege,
+      },
       {
         path: "course", //课程管理
         meta: { privilegeCodes: "index_course" },

+ 298 - 0
src/modules/questions/views/data_previllege.vue

@@ -0,0 +1,298 @@
+<template>
+  <div>
+    <LinkTitlesCustom :current-paths="['用户管理', '关联课程']" />
+    <section class="content">
+      <div v-loading.body="loading" class="box box-info">
+        <!-- 正文信息 -->
+        <div class="box-body">
+          <el-form
+            ref="form"
+            :inline="true"
+            :model="form"
+            inline-message
+            label-position="right"
+          >
+            <div style="margin-bottom: 10px">
+              <!-- <el-button type="primary" size="small">保 存</el-button> -->
+              <el-button
+                type="primary"
+                size="small"
+                icon="el-icon-arrow-left"
+                @click="back"
+                >返 回</el-button
+              >
+            </div>
+            <el-tabs v-model="activeName" type="border-card">
+              <el-tab-pane label="关联课程" name="tab1">
+                <el-row class="mb-2">
+                  <el-switch
+                    v-model="form.defaultStatusCourse"
+                    active-text="全部课程"
+                    @change="(enabled) => saveDefaultStatus('Course', enabled)"
+                  ></el-switch>
+                  <div v-if="!form.defaultStatusCourse" class="float-right">
+                    <el-button
+                      size="small"
+                      type="danger"
+                      icon="el-icon-delete"
+                      :disabled="noBatchSelectedCourse"
+                      @click="deleteBatch('Course')"
+                      >删除</el-button
+                    >
+                    <el-button
+                      size="small"
+                      type="primary"
+                      icon="el-icon-plus"
+                      @click="addCourse"
+                      >添加</el-button
+                    >
+                  </div>
+                </el-row>
+                <el-row v-if="!form.defaultStatusCourse">
+                  <div>
+                    <el-table
+                      ref="tableCourse"
+                      :data="tableDataCourse"
+                      border
+                      resizable
+                      stripe
+                      style="width: 100%"
+                      @selection-change="selectChange"
+                    >
+                      <el-table-column type="selection" width="40" />
+                      <el-table-column width="85" label="课程ID">
+                        <span slot-scope="scope">{{ scope.row.courseId }}</span>
+                      </el-table-column>
+                      <el-table-column width="200" label="课程代码">
+                        <span slot-scope="scope">{{
+                          scope.row.courseCode
+                        }}</span>
+                      </el-table-column>
+                      <el-table-column label="课程名称">
+                        <span slot-scope="scope">{{
+                          scope.row.courseName
+                        }}</span>
+                      </el-table-column>
+                      <el-table-column width="100" label="层次">
+                        <span slot-scope="scope">{{
+                          scope.row.courseLevel
+                        }}</span
+                        >>
+                      </el-table-column>
+                    </el-table>
+                    <div class="page pull-right">
+                      <el-pagination
+                        v-if="paginationShow"
+                        :current-page="currentPageCourse"
+                        :page-size="pageSizeCourse"
+                        :page-sizes="[10, 20, 50, 100, 200, 300]"
+                        layout="total, sizes, prev, pager, next, jumper"
+                        :total="totalCourse"
+                        @current-change="handleCurrentChangeCourse"
+                        @size-change="handleSizeChangeCourse"
+                      />
+                    </div>
+                  </div>
+                </el-row>
+              </el-tab-pane>
+            </el-tabs>
+          </el-form>
+        </div>
+      </div>
+    </section>
+    <DataPrevillegeAddCourseDialog
+      ref="addCourseDialog"
+      :user-id="userId"
+      @reload="init"
+    />
+  </div>
+</template>
+
+<script>
+import { mapState } from "vuex";
+import { QUESTION_API } from "@/constants/constants.js";
+import LinkTitlesCustom from "@/components/LinkTitlesCustom.vue";
+import { object2QueryString } from "@/utils/utils";
+import DataPrevillegeAddCourseDialog from "./data_previllege_add_course";
+
+export default {
+  name: "DataPrevillege",
+  components: {
+    LinkTitlesCustom,
+    DataPrevillegeAddCourseDialog,
+  },
+  data() {
+    return {
+      rolePrivileges: {
+        user_data_rule_setting: false,
+      },
+      loading: false,
+      style: {
+        label_width_tab1: "160px",
+        label_width_tab2: "160px",
+        label_width_tab3: "160px",
+      },
+      activeName: "tab1",
+      toActiveName: null,
+      form: {
+        defaultStatusCourse: false,
+      },
+      userId: "",
+      paginationShow: false,
+      selectedChanged: false,
+      tableDataCourse: [],
+      noBatchSelectedCourse: true,
+      currentPageCourse: 1,
+      pageSizeCourse: 10,
+      totalCourse: 10,
+    };
+  },
+  computed: {
+    ...mapState({ user: (state) => state.user }),
+  },
+  async created() {
+    await this.initPrivileges();
+    if (!this.rolePrivileges.user_data_rule_setting) {
+      this.$alert("没有权限访问!", "提示", {
+        confirmButtonText: "确定",
+        callback: () => {
+          this.back();
+        },
+      });
+      return;
+    }
+
+    this.userId = this.$route.params.userId;
+    await this.init();
+    this.$nextTick(function () {
+      this.paginationShow = true;
+    });
+  },
+  methods: {
+    async init() {
+      const reqs = [];
+      const defaultPrevilleges = ["COURSE"];
+      for (const defP of defaultPrevilleges) {
+        let url =
+          QUESTION_API +
+          "/user/data/rule/default/status?" +
+          `userId=${this.userId}&type=${defP}`;
+        reqs.push(this.$httpWithMsg.post(url));
+      }
+
+      const preVillegeList = ["Course"];
+
+      for (const defP of preVillegeList) {
+        let url =
+          QUESTION_API + "/user/data/rule/list/for/" + defP.toLowerCase();
+        const pageNo = this.$data["currentPage" + defP];
+        const pageSize = this.$data["pageSize" + defP];
+        reqs.push(
+          this.$httpWithMsg.post(url, {
+            userId: this.userId,
+            pageNo,
+            pageSize,
+          })
+        );
+      }
+
+      try {
+        this.loading = true;
+
+        const promiseAll = await Promise.all(reqs);
+        // console.log(promiseAll);
+        this.form.defaultStatusCourse = promiseAll[0].data;
+        this.tableDataCourse = promiseAll[1].data.content;
+        this.totalCourse = promiseAll[1].data.totalElements;
+      } finally {
+        this.loading = false;
+      }
+    },
+    noBatchSelected(type) {
+      if (!this.$refs[type + "Table"]) return false;
+      console.log(this.$refs[type + "Table"].selection.length);
+      return this.$refs[type + "Table"].selection.length;
+    },
+    selectChange() {
+      this.noBatchSelectedCourse =
+        this.$refs.tableCourse && !this.$refs.tableCourse.selection.length;
+    },
+    handleSizeChangeCourse(val) {
+      this.pageSizeCourse = val;
+      this.currentPageCourse = 1;
+      this.init();
+    },
+    handleCurrentChangeCourse(val) {
+      this.currentPageCourse = val;
+      this.init();
+    },
+    back() {
+      this.$router.back();
+    },
+    async saveDefaultStatus(type, enabled) {
+      try {
+        await this.$httpWithMsg.post(
+          QUESTION_API +
+            "/user/data/rule/default/status/update?" +
+            object2QueryString({
+              enabled,
+              type: type.toUpperCase(),
+              userId: this.userId,
+            })
+        );
+        this.$notify({
+          type: "success",
+          message: "更新成功",
+        });
+      } catch (error) {
+        this.form["defaultStatus" + type] = !enabled;
+      }
+    },
+    async deleteBatch(type) {
+      const refIds = this.$refs["table" + type].selection.map((v) => v.refId);
+
+      try {
+        await this.$httpWithMsg.post(QUESTION_API + "/user/data/rule/delete", {
+          refIds,
+          type: type.toUpperCase(),
+          userId: this.userId,
+        });
+
+        this.$notify({
+          type: "success",
+          message: "删除成功",
+        });
+        await this.init();
+      } catch (error) {
+        console.log(error);
+      }
+    },
+    addCourse() {
+      this.$refs.addCourseDialog.openDialog();
+    },
+    async initPrivileges() {
+      let params = new URLSearchParams();
+      params.append(
+        "privilegeCodes",
+        Object.keys(this.rolePrivileges).toString()
+      );
+      var url = QUESTION_API + "/rolePrivilege/checkPrivileges?" + params;
+      await this.$httpWithMsg.post(url).then((response) => {
+        this.rolePrivileges = response.data;
+      });
+    },
+  },
+};
+</script>
+<style scoped>
+.content {
+  width: 800px;
+}
+
+.input {
+  width: 440px;
+}
+.input >>> .el-input__inner {
+  -webkit-appearance: button;
+}
+</style>

+ 186 - 0
src/modules/questions/views/data_previllege_add_course.vue

@@ -0,0 +1,186 @@
+<template>
+  <el-dialog
+    ref="dialog"
+    title="添加课程"
+    width="700px"
+    :visible.sync="visible"
+    @close="closeDialog"
+  >
+    <el-form
+      ref="form"
+      :model="form"
+      :rules="rules"
+      :inline="true"
+      label-position="right"
+      label-width="80px"
+    >
+      <el-row>
+        <el-form-item label="课程名称">
+          <el-input v-model="form.name" placeholder="请输入课程名称" />
+        </el-form-item>
+        <el-form-item label="课程层次">
+          <LevelTypeSelect v-model="form.levelType"></LevelTypeSelect>
+        </el-form-item>
+        <el-form-item>
+          <el-button
+            size="small"
+            type="primary"
+            icon="el-icon-search"
+            @click="search"
+          >
+            查询
+          </el-button>
+        </el-form-item>
+      </el-row>
+
+      <el-row>
+        <div>
+          <el-table
+            ref="table"
+            :data="tableData"
+            border
+            resizable
+            stripe
+            style="width: 100%"
+          >
+            <el-table-column type="selection" width="40" />
+            <el-table-column width="85" label="课程ID">
+              <span slot-scope="scope">{{ scope.row.id }}</span>
+            </el-table-column>
+            <el-table-column width="200" label="课程代码">
+              <span slot-scope="scope">{{ scope.row.code }}</span>
+            </el-table-column>
+            <el-table-column label="课程名称">
+              <span slot-scope="scope">{{ scope.row.name }}</span>
+            </el-table-column>
+            <el-table-column width="100" label="课程层次">
+              <span slot-scope="scope">{{
+                scope.row.level | levelTypeFilter
+              }}</span>
+            </el-table-column>
+          </el-table>
+          <div class="page pull-right">
+            <el-pagination
+              v-if="paginationShow"
+              :current-page="currentPage"
+              :page-size="pageSize"
+              :page-sizes="[10, 20, 50, 100, 200, 300]"
+              layout="total, sizes, prev, pager, next, jumper"
+              :total="total"
+              @current-change="handleCurrentChange"
+              @size-change="handleSizeChange"
+            />
+          </div>
+        </div>
+        <div style="margin-bottom: 20px"></div>
+      </el-row>
+
+      <el-row class="d-flex justify-content-center mt-2">
+        <el-button type="primary" :loading="loading" @click="submitForm"
+          >确 定</el-button
+        >
+        <el-button @click="closeDialog">取 消</el-button>
+      </el-row>
+    </el-form>
+  </el-dialog>
+</template>
+
+<script>
+import { QUESTION_API } from "@/constants/constants";
+export default {
+  name: "DataPrevillegeAddCourseDialog",
+  props: {
+    userId: { type: String, default: "" },
+  },
+  data() {
+    return {
+      visible: false,
+      form: {
+        name: "",
+        levelType: "",
+      },
+      rules: {},
+      loading: false,
+      paginationShow: false,
+      tableData: [],
+      noBatchSelected: true,
+      currentPage: 1,
+      pageSize: 10,
+      total: 10,
+    };
+  },
+  methods: {
+    async search() {
+      var param = new URLSearchParams(this.form);
+      var url =
+        QUESTION_API +
+        "/course/coursePage/" +
+        (this.currentPage - 1) +
+        "/" +
+        this.pageSize +
+        "?" +
+        param;
+      this.loading = true;
+      return this.$httpWithMsg.get(url).then((response) => {
+        this.tableData = response.data.content;
+        this.total = response.data.totalElements;
+        this.loading = false;
+        this.paginationShow = true;
+      });
+    },
+    async openDialog() {
+      this.visible = true;
+      try {
+        await this.search();
+      } catch (error) {
+        console.log(error);
+        this.$notify({ type: "error", title: "获取课程列表失败" });
+      }
+    },
+    closeDialog() {
+      this.visible = false;
+    },
+    handleSizeChange(val) {
+      this.pageSize = val;
+      this.currentPage = 1;
+      this.search();
+    },
+    handleCurrentChange(val) {
+      this.currentPage = val;
+      this.search();
+    },
+    async submitForm() {
+      try {
+        await this.$refs.form.validate();
+      } catch (error) {
+        console.log("校验失败", error);
+        return;
+      }
+
+      const refIds = this.$refs.table.selection.map((v) => v.id);
+      console.log(refIds);
+      if (refIds.length === 0) {
+        this.$notify({ type: "warning", message: "请先选择一行或多行" });
+        return;
+      }
+
+      try {
+        this.loading = true;
+        // await saveActivity(data);
+        await this.$httpWithMsg.post(QUESTION_API + "/user/data/rule/add", {
+          refIds,
+          type: "COURSE",
+          userId: this.userId,
+        });
+        this.$emit("reload");
+        this.$notify({ title: "保存成功", type: "success" });
+        this.closeDialog();
+      } finally {
+        this.loading = false;
+      }
+    },
+  },
+};
+</script>
+
+<style></style>

+ 1068 - 0
src/modules/questions/views/user.vue

@@ -0,0 +1,1068 @@
+<template>
+  <section class="content">
+    <div class="box box-info">
+      <div
+        v-loading.fullscreen="loading"
+        class="box-body"
+        element-loading-text="请稍后..."
+      >
+        <!-- 搜索 -->
+        <el-form inline :model="searchForm">
+          <el-form-item v-if="isSuperAdmin" label="学校">
+            <el-select
+              v-model="searchForm.rootOrgId"
+              placeholder="请选择"
+              :disabled="!isSuperAdmin"
+              class="input_width"
+              filterable
+              @change="rootOrgChanged4Search"
+            >
+              <el-option
+                v-for="item in rootSchoolSelect"
+                :key="item.id"
+                :label="item.name"
+                :value="item.id"
+              />
+            </el-select>
+          </el-form-item>
+          <el-form-item label="角色">
+            <el-select
+              v-model="searchForm.roleId"
+              clearable
+              placeholder="请选择"
+              class="input_width"
+            >
+              <el-option
+                v-for="item in roleList4Search"
+                :key="item.roleId"
+                :label="item.roleName"
+                :value="item.roleId"
+              />
+            </el-select>
+          </el-form-item>
+          <el-form-item label="课程">
+            <el-select
+              v-model="searchForm.courseId"
+              class="input"
+              :remote-method="getCourses4Search"
+              :loading="courseLoading4Search"
+              remote
+              filterable
+              clearable
+              placeholder="请选择"
+            >
+              <el-option
+                v-for="item in courseList4Search"
+                :key="item.id"
+                :label="item.name + ' - ' + item.code"
+                :value="item.id"
+              ></el-option>
+            </el-select>
+          </el-form-item>
+          <el-form-item label="登录名">
+            <el-input
+              v-model="searchForm.loginName"
+              placeholder="请输入登录名"
+              class="input_width"
+            />
+          </el-form-item>
+          <el-form-item label="姓名">
+            <el-input
+              v-model="searchForm.name"
+              placeholder="请输入姓名"
+              class="input_width"
+            />
+          </el-form-item>
+
+          <el-form-item label="状态">
+            <el-select v-model="searchForm.enable" class="input">
+              <el-option label="未选择" value=""></el-option>
+              <el-option label="已启用" value="true"></el-option>
+              <el-option label="已禁用" value="false"></el-option>
+            </el-select>
+          </el-form-item>
+
+          <el-form-item>
+            <el-button
+              size="small"
+              type="primary"
+              icon="el-icon-search"
+              @click="handleSearchBtn"
+            >
+              查询
+            </el-button>
+
+            <el-button
+              size="small"
+              icon="el-icon-refresh"
+              @click="resetEcsFormSearch"
+            >
+              重置
+            </el-button>
+
+            <el-button
+              size="small"
+              type="primary"
+              icon="el-icon-plus"
+              @click="openAddingDialog"
+            >
+              新增
+            </el-button>
+          </el-form-item>
+        </el-form>
+
+        <div class="block-seperator"></div>
+        <span>批量操作:</span>
+
+        <el-button
+          size="small"
+          type="success"
+          icon="el-icon-check"
+          :disabled="noBatchSelected"
+          @click="enableByIds"
+          >启用
+        </el-button>
+        <el-button
+          size="small"
+          type="danger"
+          icon="el-icon-close"
+          :disabled="noBatchSelected"
+          @click="disableByIds"
+          >禁用
+        </el-button>
+
+        <div class="block-seperator"></div>
+        <!-- 添加用户信息弹出框 -->
+        <el-dialog title="新增用户" width="450px" :visible.sync="addingDialog">
+          <el-form
+            ref="addingForm"
+            :inline="true"
+            inline-message
+            :model="userForm"
+            :rules="rules"
+            label-position="right"
+            label-width="120px"
+          >
+            <el-row>
+              <el-form-item label="姓名" prop="name">
+                <el-input
+                  v-model="userForm.name"
+                  class="input_width_lg"
+                  auto-complete="off"
+                  placeholder="请输入姓名"
+                />
+              </el-form-item>
+            </el-row>
+            <el-row>
+              <el-form-item label="登录名" prop="loginName">
+                <el-input
+                  v-model="userForm.loginName"
+                  class="input_width_lg"
+                  auto-complete="off"
+                  placeholder="请输入登录名"
+                />
+              </el-form-item>
+            </el-row>
+            <el-row>
+              <el-form-item label="密码" prop="password">
+                <el-input
+                  v-model="userForm.password"
+                  class="input_width_lg"
+                  auto-complete="off"
+                  placeholder="请输入密码"
+                />
+              </el-form-item>
+            </el-row>
+            <el-row>
+              <el-form-item v-if="isSuperAdmin" label="学校" prop="rootOrgId">
+                <el-select
+                  v-model="userForm.rootOrgId"
+                  class="input_width_lg"
+                  placeholder="请选择"
+                  :disabled="!isSuperAdmin"
+                  filterable
+                  @change="rootOrgChanged4InsertOrUpdate"
+                >
+                  <el-option
+                    v-for="item in rootSchoolSelect"
+                    :key="item.id"
+                    :label="item.name"
+                    :value="item.id"
+                  >
+                  </el-option>
+                </el-select>
+              </el-form-item>
+            </el-row>
+            <el-row>
+              <el-form-item label="角色" prop="roleId">
+                <el-select
+                  v-model="userForm.roleId"
+                  class="input_width_lg"
+                  placeholder="请选择"
+                >
+                  <el-option
+                    v-for="item in roleList4InsertOrUpdateWithoutSuperAdmin"
+                    :key="item.roleId"
+                    :label="item.roleName"
+                    :value="item.roleId"
+                  >
+                  </el-option>
+                </el-select>
+              </el-form-item>
+            </el-row>
+            <el-row>
+              <el-form-item label="状态">
+                <el-radio-group v-model="enableStr" class="pull_right_sm">
+                  <el-radio label="true">启用</el-radio>
+                  <el-radio label="false">禁用</el-radio>
+                </el-radio-group>
+              </el-form-item>
+            </el-row>
+            <el-row class="d-flex justify-content-center">
+              <el-button type="primary" @click="add">保 存</el-button>
+              <el-button @click="addingDialog = false">取 消</el-button>
+            </el-row>
+          </el-form>
+        </el-dialog>
+
+        <!-- 修改用户信息弹出框 -->
+        <el-dialog title="编辑用户" width="450px" :visible.sync="updateDialog">
+          <el-form
+            ref="updateForm"
+            :inline="true"
+            inline-message
+            :model="userForm"
+            :rules="rules"
+            label-position="right"
+            label-width="120px"
+          >
+            <el-row>
+              <el-form-item label="ID">
+                <el-input
+                  v-model="userForm.id"
+                  class="input_width_lg"
+                  :disabled="true"
+                />
+              </el-form-item>
+            </el-row>
+            <el-row>
+              <el-form-item label="姓名" prop="name">
+                <el-input
+                  v-model="userForm.name"
+                  class="input_width_lg"
+                  auto-complete="off"
+                  placeholder="请输入姓名"
+                />
+              </el-form-item>
+            </el-row>
+            <el-row>
+              <el-form-item label="登录名" prop="loginName">
+                <el-input
+                  v-model="userForm.loginName"
+                  class="input_width_lg"
+                  auto-complete="off"
+                  placeholder="请输入登录名"
+                />
+              </el-form-item>
+            </el-row>
+            <el-row>
+              <el-form-item v-if="isSuperAdmin" label="学校" prop="rootOrgId">
+                <el-select
+                  v-model="userForm.rootOrgId"
+                  class="input_width_lg"
+                  placeholder="请选择"
+                  :disabled="true"
+                >
+                  <el-option
+                    v-for="item in rootSchoolSelect"
+                    :key="item.id"
+                    :label="item.name"
+                    :value="item.id"
+                  >
+                  </el-option>
+                </el-select>
+              </el-form-item>
+            </el-row>
+            <el-row>
+              <el-form-item label="角色" prop="roleId">
+                <el-select
+                  v-model="userForm.roleId"
+                  class="input_width_lg"
+                  placeholder="请选择"
+                  :disabled="rowIsSuperAdmin"
+                >
+                  <el-option
+                    v-for="item in roleList4InsertOrUpdate"
+                    :key="item.roleId"
+                    :label="item.roleName"
+                    :disabled="item.roleCode == 'SUPER_ADMIN'"
+                    :value="item.roleId"
+                  >
+                  </el-option>
+                </el-select>
+              </el-form-item>
+            </el-row>
+            <el-row>
+              <el-form-item label="状态">
+                <el-radio-group
+                  v-model="enableStr"
+                  class="pull_right_sm"
+                  :disabled="rowIsSuperAdmin"
+                >
+                  <el-radio label="true">启用</el-radio>
+                  <el-radio label="false">禁用</el-radio>
+                </el-radio-group>
+              </el-form-item>
+            </el-row>
+            <el-row class="d-flex justify-content-center">
+              <el-button type="primary" @click="update">保 存</el-button>
+              <el-button @click="updateDialog = false">取 消</el-button>
+            </el-row>
+          </el-form>
+        </el-dialog>
+
+        <!-- 页面列表 -->
+        <el-table
+          ref="table"
+          :data="tableData"
+          border
+          resizable
+          stripe
+          style="width: 100%"
+          @selection-change="selectChange"
+        >
+          <el-table-column type="selection" width="50"></el-table-column>
+          <el-table-column prop="id" width="80" label="ID" />
+          <el-table-column prop="name" width="120" label="姓名" />
+          <el-table-column prop="loginName" width="100" label="登录名" />
+          <el-table-column prop="rootOrgName" label="顶级机构" />
+          <!-- <el-table-column prop="roleNamesStr" width="110" label="角色" /> -->
+          <el-table-column width="120" label="角色">
+            <span
+              slot-scope="scope"
+              v-html="scope.row.roleNamesStr.replace(/,/g, '<br />')"
+            >
+            </span>
+          </el-table-column>
+          <el-table-column width="120" label="关联课程">
+            <span
+              slot-scope="scope"
+              v-html="
+                scope.row.courseNamesStr &&
+                scope.row.courseNamesStr.replace(/,/g, '<br />')
+              "
+            >
+            </span>
+          </el-table-column>
+          <el-table-column
+            sortable
+            prop="updateTime"
+            width="160"
+            label="更新时间"
+          />
+          <el-table-column width="50" label="状态">
+            <span slot-scope="scope">
+              <span v-if="scope.row.enable">
+                <el-tooltip
+                  class="item"
+                  effect="dark"
+                  content="启用"
+                  placement="left"
+                >
+                  <i class="el-icon-success" style="color: green"></i>
+                </el-tooltip>
+              </span>
+              <span v-else>
+                <el-tooltip
+                  class="item"
+                  effect="dark"
+                  content="禁用"
+                  placement="left"
+                >
+                  <i class="el-icon-error" style="color: red"></i>
+                </el-tooltip>
+              </span>
+            </span>
+          </el-table-column>
+          <el-table-column width="190" label="操作">
+            <div slot-scope="scope">
+              <div v-if="!userIsSuperAdmin(scope.row)">
+                <el-button
+                  v-if="!scope.row.enable"
+                  size="mini"
+                  type="primary"
+                  plain
+                  icon="el-icon-check"
+                  @click="enableById(scope.row)"
+                >
+                  启用
+                </el-button>
+                <el-button
+                  v-if="scope.row.enable"
+                  size="mini"
+                  type="danger"
+                  icon="el-icon-close"
+                  @click="disableById(scope.row)"
+                >
+                  禁用
+                </el-button>
+                &nbsp;
+                <el-dropdown>
+                  <el-button type="primary" plain size="mini">
+                    更多<i class="el-icon-arrow-down el-icon--right"></i>
+                  </el-button>
+                  <el-dropdown-menu slot="dropdown">
+                    <el-dropdown-item>
+                      <el-button
+                        v-if="showUserDataRuleSetting(scope.row)"
+                        size="mini"
+                        type="primary"
+                        plain
+                        icon="el-icon-edit"
+                        @click="
+                          () =>
+                            $router.push(
+                              `./user/data_previllege/${scope.row.id}`
+                            )
+                        "
+                        >关联课程
+                      </el-button>
+                    </el-dropdown-item>
+                    <el-dropdown-item>
+                      <el-button
+                        size="mini"
+                        type="primary"
+                        plain
+                        icon="el-icon-edit"
+                        @click="openUpdateDialog(scope.row)"
+                        >编辑
+                      </el-button>
+                    </el-dropdown-item>
+                    <el-dropdown-item>
+                      <el-button
+                        v-if="false"
+                        size="mini"
+                        type="danger"
+                        icon="el-icon-delete"
+                        @click="deleteById(scope.row)"
+                        >删除
+                      </el-button>
+                    </el-dropdown-item>
+                    <el-dropdown-item>
+                      <el-button
+                        size="mini"
+                        type="danger"
+                        @click="resetPass(scope.row)"
+                      >
+                        <v-icon name="lock" scale="0.7" /> 重置密码
+                      </el-button>
+                    </el-dropdown-item>
+                  </el-dropdown-menu>
+                </el-dropdown>
+              </div>
+            </div>
+          </el-table-column>
+        </el-table>
+        <div class="page pull-right">
+          <el-pagination
+            :current-page="currentPage"
+            :page-size="10"
+            :page-sizes="[10, 20, 50, 100, 200, 300]"
+            layout="total, sizes, prev, pager, next, jumper"
+            :total="total"
+            @current-change="handleCurrentChange"
+            @size-change="handleSizeChange"
+          />
+        </div>
+      </div>
+    </div>
+  </section>
+</template>
+
+<script>
+import { QUESTION_API } from "@/constants/constants.js";
+import { mapState } from "vuex";
+
+export default {
+  name: "User",
+  data() {
+    var validateRootOrg = (rule, value, callback) => {
+      if (0 != value && !value) {
+        callback(new Error("请选择学校"));
+      } else {
+        callback();
+      }
+    };
+    var validateRoles = (rule, value, callback) => {
+      if (0 != value && !value) {
+        callback(new Error("请选择角色"));
+      } else {
+        callback();
+      }
+    };
+    return {
+      courseList4Search: [],
+      courseLoading4Search: false,
+      rolePrivileges: {
+        user_data_rule_setting: false,
+      },
+      loading: false,
+      orgLoading4InsertOrUpdate: false,
+      roleList4Search: [],
+      roleList4InsertOrUpdate: [],
+      rootOrgList: [],
+      orgList4InsertOrUpdate: [],
+      searchForm: {
+        courseId: "",
+        name: "",
+        loginName: "",
+        enable: "",
+        rootOrgId: "",
+        roleId: "",
+      },
+      userForm: {
+        id: null,
+        name: "",
+        loginName: "",
+        password: "",
+        phoneNumber: "",
+        enable: true,
+        rootOrgId: null,
+        orgId: null,
+        roleId: null,
+      },
+      enableStr: "true",
+
+      tempOrgList: [],
+      userId: "",
+      selectedUserIds: [],
+      selectedUserToCopy: null,
+      tableData: [],
+      currentPage: 1,
+      pageSize: 10,
+      total: 10,
+      addingDialog: false,
+      updateDialog: false,
+      rowIsSuperAdmin: false,
+      rules: {
+        name: [
+          {
+            required: true,
+            message: "请输入姓名",
+            trigger: "blur",
+          },
+        ],
+        loginName: [
+          {
+            required: true,
+            message: "请输入登录名",
+            trigger: "blur",
+          },
+        ],
+        password: [
+          {
+            required: true,
+            message: "请输入密码",
+            trigger: "blur",
+          },
+        ],
+        phoneNumber: [
+          // {
+          //   message: "请输入联系方式",
+          //   trigger: "blur"
+          // }
+        ],
+        rootOrgId: [
+          {
+            validator: validateRootOrg,
+            trigger: "blur",
+          },
+        ],
+        orgId: [],
+        roleId: [
+          {
+            required: true,
+            validator: validateRoles,
+            trigger: ["blur", "change"],
+          },
+        ],
+      },
+    };
+  },
+  computed: {
+    ...mapState({
+      user: (state) => state.user,
+    }),
+    userIds() {
+      var userIds = "";
+      for (let userId of this.selectedUserIds) {
+        if (!userIds) {
+          userIds += userId;
+        } else {
+          userIds += "," + userId;
+        }
+      }
+      return userIds;
+    },
+    noBatchSelected() {
+      return this.selectedUserIds.length === 0;
+    },
+    roleList4InsertOrUpdateWithoutSuperAdmin() {
+      return this.roleList4InsertOrUpdate.filter(
+        (item) => item.roleCode != "SUPER_ADMIN"
+      );
+    },
+    isSuperAdmin() {
+      return this.user.roleList.some((role) => role.roleCode == "SUPER_ADMIN");
+    },
+    rootSchoolSelect() {
+      let rootSchools = [];
+      for (let i = 0; i < this.rootOrgList.length; i++) {
+        let info = {
+          name: this.rootOrgList[i].name + "(" + this.rootOrgList[i].id + ")",
+          id: this.rootOrgList[i].id,
+        };
+        rootSchools.push(info);
+      }
+      return rootSchools;
+    },
+  },
+  //初始化查询
+  created() {
+    this.initPrivileges();
+    this.init();
+  },
+  methods: {
+    getCourses4Search(query) {
+      this.courseLoading4Search = true;
+      this.$httpWithMsg
+        .get(QUESTION_API + "/course/query?name=" + query)
+        .then((response) => {
+          this.courseList4Search = response.data;
+          this.courseLoading4Search = false;
+        });
+    },
+    resetEcsFormSearch() {
+      this.searchForm = Object.assign(this.searchForm, {
+        roleId: "",
+        loginName: "",
+        name: "",
+        enable: "",
+      });
+    },
+    handleSizeChange(val) {
+      this.currentPage = 1;
+      this.pageSize = val;
+      this.search();
+    },
+    validateOrg(rule, value, callback) {
+      if (0 != value && !value) {
+        callback(new Error("请选择子机构"));
+      } else {
+        callback();
+      }
+    },
+    rootOrgChanged4Search() {
+      var url =
+        QUESTION_API +
+        "/rolePrivilege/getRoles?includeSuperAdmin=" +
+        true +
+        "&rootOrgId=" +
+        this.searchForm.rootOrgId;
+      this.$httpWithMsg.post(url).then((response) => {
+        this.roleList4Search = response.data;
+      });
+    },
+    rootOrgChanged4InsertOrUpdate() {
+      this.orgList4InsertOrUpdate = [];
+
+      var url =
+        QUESTION_API +
+        "/rolePrivilege/getRoles?rootOrgId=" +
+        this.userForm.rootOrgId;
+      this.$httpWithMsg.post(url).then((response) => {
+        this.roleList4InsertOrUpdate = response.data;
+      });
+    },
+    getOrgList4InsertOrUpdate(query) {
+      this.orgLoading4InsertOrUpdate = true;
+      var url =
+        QUESTION_API +
+        "/org/query?" +
+        new URLSearchParams({
+          name: query,
+          rootOrgId: this.userForm.rootOrgId,
+        });
+      this.$httpWithMsg
+        .get(url)
+        .then((response) => {
+          this.orgList4InsertOrUpdate = response.data;
+          this.orgLoading4InsertOrUpdate = false;
+        })
+        .catch(() => {
+          this.orgLoading4InsertOrUpdate = false;
+        });
+    },
+    getTag(status) {
+      if (status == true) {
+        return "success";
+      } else if (status == false) {
+        return "danger";
+      }
+      return status;
+    },
+    getLevel(level) {
+      if (level == "ZSB") {
+        return "专升本";
+      } else if (level == "GQZ") {
+        return "高起专";
+      }
+      return level;
+    },
+    handleSearchBtn() {
+      this.currentPage = 1;
+      this.search();
+    },
+    search() {
+      let searchLock = true;
+      setTimeout(() => {
+        if (searchLock) {
+          this.loading = true;
+        }
+      }, 500);
+      var param = new URLSearchParams(this.searchForm);
+      var url =
+        QUESTION_API +
+        "/user/all/" +
+        this.currentPage +
+        "/" +
+        this.pageSize +
+        "?" +
+        param;
+      this.$httpWithMsg
+        .get(url)
+        .then((response) => {
+          // console.log(response);
+          this.tableData = response.data.list;
+          this.total = response.data.total;
+          this.loading = false;
+        })
+        .finally(() => {
+          searchLock = false;
+          this.loading = false;
+        });
+    },
+    handleCurrentChange(val) {
+      this.currentPage = val;
+      this.search();
+    },
+    selectChange(row) {
+      this.selectedUserIds = [];
+      row.forEach((element) => {
+        this.selectedUserIds.push(element.id);
+      });
+    },
+    //新增
+    openAddingDialog() {
+      if (this.$refs.addingForm) {
+        this.$refs.addingForm.resetFields();
+      }
+      if (this.$refs.updateForm) {
+        this.$refs.updateForm.resetFields();
+      }
+      this.addingDialog = true;
+      this.userForm.name = "";
+      this.userForm.loginName = "";
+      this.userForm.password = "";
+      this.userForm.phoneNumber = "";
+      this.userForm.roleId = null;
+      this.userForm.orgId = null;
+      this.enableStr = "true";
+      this.orgList4InsertOrUpdate = [];
+    },
+    //修改
+    openUpdateDialog(row) {
+      if (this.$refs.updateForm) {
+        this.$refs.updateForm.resetFields();
+      }
+      if (this.$refs.addingForm) {
+        this.$refs.addingForm.resetFields();
+      }
+
+      this.updateDialog = true;
+      this.userForm.id = row.id;
+      this.userForm.roleId = row.roleIds[0];
+      this.userForm.name = row.name;
+      this.userForm.loginName = row.loginName;
+      this.enableStr = row.enable ? "true" : "false";
+      this.userForm.phoneNumber = row.phoneNumber;
+      this.userForm.password = null;
+      this.userForm.rootOrgId = row.rootOrgId;
+      this.rowIsSuperAdmin = false;
+      for (let roleCode of row.roleCodes) {
+        if (roleCode == "SUPER_ADMIN") {
+          this.rowIsSuperAdmin = true;
+          break;
+        }
+      }
+
+      this.rootOrgChanged4InsertOrUpdate();
+      this.orgList4InsertOrUpdate = [{ id: row.orgId, name: row.orgName }];
+      this.userForm.orgId = row.orgId;
+    },
+    exportUser() {
+      var param = new URLSearchParams(this.searchForm);
+      window.open(QUESTION_API + "/user/export?" + param);
+    },
+    //保存
+    add() {
+      var url = QUESTION_API + "/user";
+      this.$refs.addingForm.validate((valid) => {
+        if (valid) {
+          this.userForm.enable = this.enableStr == "true";
+          this.$httpWithMsg.post(url, this.userForm).then(() => {
+            this.$notify({
+              type: "success",
+              message: "添加成功",
+            });
+            this.search();
+            this.addingDialog = false;
+          });
+        } else {
+          return false;
+        }
+      });
+    },
+    //保存
+    update() {
+      var url = QUESTION_API + "/user";
+      this.$refs.updateForm.validate((valid) => {
+        if (valid) {
+          this.userForm.enable = this.enableStr == "true";
+          this.$httpWithMsg.put(url, this.userForm).then(() => {
+            this.$notify({
+              type: "success",
+              message: "添加成功",
+            });
+            this.search();
+            this.updateDialog = false;
+          });
+        } else {
+          return false;
+        }
+      });
+    },
+    //重置密码
+    resetPass(row) {
+      this.$confirm("是否重置密码?", "提示", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning",
+      })
+        .then(() => {
+          var url = QUESTION_API + "/user/resetPass/" + row.id;
+          this.$httpWithMsg.put(url).then(() => {
+            this.$notify({
+              type: "success",
+              message: "重置成功!",
+            });
+            return this.search();
+          });
+        })
+        .catch((e) => console.log(e));
+    },
+    //删除单个数据
+    deleteById(row) {
+      this.$confirm("是否删除该用户?", "提示", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning",
+      }).then(() => {
+        var url = QUESTION_API + "/user/" + row.id;
+        this.$httpWithMsg.delete(url).then(() => {
+          this.$notify({
+            type: "success",
+            message: "删除成功!",
+          });
+          return this.search();
+        });
+      });
+    },
+    //删除多条数据
+    deleteByIds() {
+      if (this.selectedUserIds.length === 0) {
+        this.$notify({
+          type: "warning",
+          message: "请选择要删除的用户",
+        });
+      } else {
+        this.$confirm("是否删除这些用户?", "提示", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "error",
+        }).then(() => {
+          var url = QUESTION_API + "/user/" + this.userIds;
+          this.$httpWithMsg.delete(url).then(() => {
+            this.$notify({
+              type: "success",
+              message: "删除成功!",
+            });
+            this.search();
+          });
+        });
+      }
+    },
+    //启用
+    enableByIds() {
+      if (this.selectedUserIds.length === 0) {
+        this.$notify({
+          type: "warning",
+          message: "请选择要启用的用户",
+        });
+      } else {
+        this.$confirm("是否启用这些用户?", "提示", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning",
+        }).then(() => {
+          var url = QUESTION_API + "/user/enable/" + this.userIds;
+          this.$httpWithMsg.put(url, {}).then(() => {
+            this.$notify({
+              type: "success",
+              message: "启用成功!",
+            });
+            return this.search();
+          });
+        });
+      }
+    },
+    enableById(row) {
+      this.$confirm("是否启用该用户?", "提示", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning",
+      }).then(() => {
+        var url = QUESTION_API + "/user/enable/" + row.id;
+        this.$httpWithMsg.put(url, {}).then(() => {
+          this.$notify({
+            type: "success",
+            message: "启用成功!",
+          });
+          this.search();
+        });
+      });
+    },
+    //禁用
+    disableByIds() {
+      if (this.selectedUserIds.length === 0) {
+        this.$notify({
+          type: "warning",
+          message: "请选择要禁用的用户",
+        });
+      } else {
+        this.$confirm("是否禁用这些用户?", "提示", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "error",
+        }).then(() => {
+          var url = QUESTION_API + "/user/disable/" + this.userIds;
+          this.$httpWithMsg.put(url, {}).then(() => {
+            this.$notify({
+              type: "success",
+              message: "禁用成功!",
+            });
+            this.search();
+          });
+        });
+      }
+    },
+    //禁用
+    disableById(row) {
+      this.$confirm("是否禁用该用户?", "提示", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "error",
+      }).then(() => {
+        var url = QUESTION_API + "/user/disable/" + row.id;
+        this.$httpWithMsg.put(url, {}).then(() => {
+          this.$notify({
+            type: "success",
+            message: "禁用成功!",
+          });
+          this.search();
+        });
+      });
+    },
+    /*初始化*/
+    init() {
+      this.searchForm.rootOrgId = this.user.rootOrgId;
+      this.userForm.rootOrgId = this.user.rootOrgId;
+
+      var url1 = QUESTION_API + "/org/getRootOrgList";
+      var url2 =
+        QUESTION_API +
+        "/rolePrivilege/getRoles?includeSuperAdmin=true&rootOrgId=" +
+        this.user.rootOrgId;
+
+      Promise.all([
+        this.$httpWithMsg.get(url1),
+        this.$httpWithMsg.post(url2),
+      ]).then(([resp1, resp2]) => {
+        this.rootOrgList = resp1.data;
+        this.roleList4Search = resp2.data;
+        this.roleList4InsertOrUpdate = resp2.data;
+        this.search();
+      });
+    },
+    initPrivileges() {
+      let params = new URLSearchParams();
+      params.append(
+        "privilegeCodes",
+        Object.keys(this.rolePrivileges).toString()
+      );
+      var url = QUESTION_API + "/rolePrivilege/checkPrivileges?" + params;
+      this.$httpWithMsg.post(url).then((response) => {
+        this.rolePrivileges = response.data;
+      });
+      this.getCourses4Search("");
+    },
+    showUserDataRuleSetting(row) {
+      let roleCodes = row.roleCodes;
+
+      for (let n = 0; n < roleCodes.length; n++) {
+        let roleCode = roleCodes[n];
+        if (roleCode == "SUPER_ADMIN" || roleCode == "ADMIN") {
+          return false;
+        }
+      }
+
+      return true;
+    },
+    userIsSuperAdmin(row) {
+      let roleCodes = row.roleCodes;
+
+      for (let n = 0; n < roleCodes.length; n++) {
+        let roleCode = roleCodes[n];
+        if (roleCode == "SUPER_ADMIN") {
+          return true;
+        }
+      }
+
+      return false;
+    },
+  },
+};
+</script>
+
+<style scoped>
+.page {
+  margin-top: 10px;
+}
+
+.input_width_lg {
+  width: 180px;
+}
+.input_width {
+  width: 150px;
+}
+</style>