qgt преди 4 месеца
родител
ревизия
8832e3e1e4
променени са 36 файла, в които са добавени 4705 реда и са изтрити 506 реда
  1. 4 0
      dist/index.html
  2. 1 0
      dist/static/css/app.67b4aa427ac00b4004f04b86cf2b22f3.css
  3. 1 0
      dist/static/css/app.67b4aa427ac00b4004f04b86cf2b22f3.css.map
  4. 1 0
      dist/static/css/app.d182a4214829adce4b569fc71fa22b88.css
  5. 0 0
      dist/static/css/app.d182a4214829adce4b569fc71fa22b88.css.map
  6. 0 0
      dist/static/js/0.4f3b05586c3acc102a54.js.map
  7. 0 0
      dist/static/js/0.df8814bab917ab2583e0.js
  8. 0 0
      dist/static/js/0.df8814bab917ab2583e0.js.map
  9. 1 0
      dist/static/js/app.3aa9b2d97024443dc1a1.js
  10. 1 0
      dist/static/js/app.3aa9b2d97024443dc1a1.js.map
  11. 1 0
      dist/static/js/app.4318aaba24aef03bb034.js
  12. 0 0
      dist/static/js/app.4318aaba24aef03bb034.js.map
  13. 0 0
      dist/static/js/manifest.161e82026ac2ae03ab6f.js.map
  14. 2 2
      dist/static/js/manifest.9811ebe9d5c4458a1b2a.js
  15. 1 0
      dist/static/js/manifest.9811ebe9d5c4458a1b2a.js.map
  16. 0 0
      dist/static/js/vendor.bb486323f0fa002ba2e7.js
  17. 0 0
      dist/static/js/vendor.bb486323f0fa002ba2e7.js.map
  18. 3 0
      src/assets/icon/workPage/start_icon.svg
  19. 4 0
      src/assets/icon/workPage/status_icon.svg
  20. 3 0
      src/assets/icon/workPage/stop_icon.svg
  21. 692 0
      src/components/pages/PersonnelManagement/components/classL.vue
  22. 340 0
      src/components/pages/PersonnelManagement/components/grade.vue
  23. 969 0
      src/components/pages/PersonnelManagement/components/student.vue
  24. 381 0
      src/components/pages/PersonnelManagement/index.vue
  25. 488 409
      src/components/pages/classroomObservation/components/chatArea.vue
  26. 146 84
      src/components/pages/classroomObservation/tools/mixin.js
  27. 11 4
      src/components/pages/inviteLoginST/inviteLogin.vue
  28. 52 3
      src/components/pages/inviteLoginSZ/inviteLogin.vue
  29. 2 2
      src/components/pages/liyuan/aiOffice.vue
  30. 1 1
      src/components/pages/liyuan/page/teadTest.vue
  31. 1 1
      src/components/pages/sassPlatform/index.vue
  32. 415 0
      src/components/pages/workPage/components/choiceQuestion.vue
  33. 32 0
      src/components/pages/workPage/components/questionsAndAnswers.vue
  34. 343 0
      src/components/pages/workPage/components/wangEnduit.vue
  35. 791 0
      src/components/pages/workPage/index_new.vue
  36. 18 0
      src/router/index.js

+ 4 - 0
dist/index.html

@@ -32,7 +32,11 @@
       width: 100%;
       background: #e6eaf0;
       font-family: '黑体';
+<<<<<<< HEAD
     }</style><link href=./static/css/app.d182a4214829adce4b569fc71fa22b88.css rel=stylesheet></head><body><div id=app></div><script type=text/javascript src=./static/js/manifest.161e82026ac2ae03ab6f.js></script><script type=text/javascript src=./static/js/vendor.b7212920b6e58d14a873.js></script><script type=text/javascript src=./static/js/app.4318aaba24aef03bb034.js></script></body></html><script>function stopSafari() {
+=======
+    }</style><link href=./static/css/app.67b4aa427ac00b4004f04b86cf2b22f3.css rel=stylesheet></head><body><div id=app></div><script type=text/javascript src=./static/js/manifest.9811ebe9d5c4458a1b2a.js></script><script type=text/javascript src=./static/js/vendor.bb486323f0fa002ba2e7.js></script><script type=text/javascript src=./static/js/app.3aa9b2d97024443dc1a1.js></script></body></html><script>function stopSafari() {
+>>>>>>> beta
     //阻止safari浏览器双击放大功能
     let lastTouchEnd = 0  //更新手指弹起的时间
     document.documentElement.addEventListener("touchstart", function (event) {

Файловите разлики са ограничени, защото са твърде много
+ 1 - 0
dist/static/css/app.67b4aa427ac00b4004f04b86cf2b22f3.css


Файловите разлики са ограничени, защото са твърде много
+ 1 - 0
dist/static/css/app.67b4aa427ac00b4004f04b86cf2b22f3.css.map


Файловите разлики са ограничени, защото са твърде много
+ 1 - 0
dist/static/css/app.d182a4214829adce4b569fc71fa22b88.css


Файловите разлики са ограничени, защото са твърде много
+ 0 - 0
dist/static/css/app.d182a4214829adce4b569fc71fa22b88.css.map


Файловите разлики са ограничени, защото са твърде много
+ 0 - 0
dist/static/js/0.4f3b05586c3acc102a54.js.map


Файловите разлики са ограничени, защото са твърде много
+ 0 - 0
dist/static/js/0.df8814bab917ab2583e0.js


Файловите разлики са ограничени, защото са твърде много
+ 0 - 0
dist/static/js/0.df8814bab917ab2583e0.js.map


Файловите разлики са ограничени, защото са твърде много
+ 1 - 0
dist/static/js/app.3aa9b2d97024443dc1a1.js


Файловите разлики са ограничени, защото са твърде много
+ 1 - 0
dist/static/js/app.3aa9b2d97024443dc1a1.js.map


Файловите разлики са ограничени, защото са твърде много
+ 1 - 0
dist/static/js/app.4318aaba24aef03bb034.js


Файловите разлики са ограничени, защото са твърде много
+ 0 - 0
dist/static/js/app.4318aaba24aef03bb034.js.map


Файловите разлики са ограничени, защото са твърде много
+ 0 - 0
dist/static/js/manifest.161e82026ac2ae03ab6f.js.map


+ 2 - 2
dist/static/js/manifest.161e82026ac2ae03ab6f.js → dist/static/js/manifest.9811ebe9d5c4458a1b2a.js

@@ -1,2 +1,2 @@
-!function(e){var n=window.webpackJsonp;window.webpackJsonp=function(r,c,a){for(var i,u,f,s=0,l=[];s<r.length;s++)u=r[s],t[u]&&l.push(t[u][0]),t[u]=0;for(i in c)Object.prototype.hasOwnProperty.call(c,i)&&(e[i]=c[i]);for(n&&n(r,c,a);l.length;)l.shift()();if(a)for(s=0;s<a.length;s++)f=o(o.s=a[s]);return f};var r={},t={6:0};function o(n){if(r[n])return r[n].exports;var t=r[n]={i:n,l:!1,exports:{}};return e[n].call(t.exports,t,t.exports,o),t.l=!0,t.exports}o.e=function(e){var n=t[e];if(0===n)return new Promise(function(e){e()});if(n)return n[2];var r=new Promise(function(r,o){n=t[e]=[r,o]});n[2]=r;var c=document.getElementsByTagName("head")[0],a=document.createElement("script");a.type="text/javascript",a.charset="utf-8",a.async=!0,a.timeout=12e4,o.nc&&a.setAttribute("nonce",o.nc),a.src=o.p+"static/js/"+e+"."+{0:"4f3b05586c3acc102a54",1:"14e8e8c7e44fc858e4a6",2:"94e1427bfc7ef0b4c685",3:"3a9f53a78da16650e6b8"}[e]+".js";var i=setTimeout(u,12e4);function u(){a.onerror=a.onload=null,clearTimeout(i);var n=t[e];0!==n&&(n&&n[1](new Error("Loading chunk "+e+" failed.")),t[e]=void 0)}return a.onerror=a.onload=u,c.appendChild(a),r},o.m=e,o.c=r,o.d=function(e,n,r){o.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:r})},o.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return o.d(n,"a",n),n},o.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},o.p="./",o.oe=function(e){throw console.error(e),e}}([]);
-//# sourceMappingURL=manifest.161e82026ac2ae03ab6f.js.map
+!function(e){var n=window.webpackJsonp;window.webpackJsonp=function(r,a,c){for(var i,u,f,s=0,l=[];s<r.length;s++)u=r[s],t[u]&&l.push(t[u][0]),t[u]=0;for(i in a)Object.prototype.hasOwnProperty.call(a,i)&&(e[i]=a[i]);for(n&&n(r,a,c);l.length;)l.shift()();if(c)for(s=0;s<c.length;s++)f=o(o.s=c[s]);return f};var r={},t={6:0};function o(n){if(r[n])return r[n].exports;var t=r[n]={i:n,l:!1,exports:{}};return e[n].call(t.exports,t,t.exports,o),t.l=!0,t.exports}o.e=function(e){var n=t[e];if(0===n)return new Promise(function(e){e()});if(n)return n[2];var r=new Promise(function(r,o){n=t[e]=[r,o]});n[2]=r;var a=document.getElementsByTagName("head")[0],c=document.createElement("script");c.type="text/javascript",c.charset="utf-8",c.async=!0,c.timeout=12e4,o.nc&&c.setAttribute("nonce",o.nc),c.src=o.p+"static/js/"+e+"."+{0:"df8814bab917ab2583e0",1:"14e8e8c7e44fc858e4a6",2:"94e1427bfc7ef0b4c685",3:"3a9f53a78da16650e6b8"}[e]+".js";var i=setTimeout(u,12e4);function u(){c.onerror=c.onload=null,clearTimeout(i);var n=t[e];0!==n&&(n&&n[1](new Error("Loading chunk "+e+" failed.")),t[e]=void 0)}return c.onerror=c.onload=u,a.appendChild(c),r},o.m=e,o.c=r,o.d=function(e,n,r){o.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:r})},o.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return o.d(n,"a",n),n},o.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},o.p="./",o.oe=function(e){throw console.error(e),e}}([]);
+//# sourceMappingURL=manifest.9811ebe9d5c4458a1b2a.js.map

Файловите разлики са ограничени, защото са твърде много
+ 1 - 0
dist/static/js/manifest.9811ebe9d5c4458a1b2a.js.map


Файловите разлики са ограничени, защото са твърде много
+ 0 - 0
dist/static/js/vendor.bb486323f0fa002ba2e7.js


Файловите разлики са ограничени, защото са твърде много
+ 0 - 0
dist/static/js/vendor.bb486323f0fa002ba2e7.js.map


+ 3 - 0
src/assets/icon/workPage/start_icon.svg

@@ -0,0 +1,3 @@
+<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M5.43945 4.13574C5.74868 3.95725 6.13016 3.9574 6.43945 4.13574L18.5605 11.1338C18.8697 11.3124 19.0605 11.6429 19.0605 12C19.0605 12.3571 18.8698 12.6876 18.5605 12.8662L12.5 16.3652L6.43945 19.8633C6.13009 20.0418 5.74878 20.0419 5.43945 19.8633C5.1305 19.6846 4.93956 19.355 4.93945 18.998V5.00195C4.93952 4.64485 5.13024 4.31437 5.43945 4.13574Z" fill="black" fill-opacity="0.9"/>
+</svg>

+ 4 - 0
src/assets/icon/workPage/status_icon.svg

@@ -0,0 +1,4 @@
+<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
+<circle cx="10" cy="10" r="10" fill="#E7E7E7"/>
+<circle cx="9.99993" cy="9.99944" r="5.71429" fill="#86909C"/>
+</svg>

+ 3 - 0
src/assets/icon/workPage/stop_icon.svg

@@ -0,0 +1,3 @@
+<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M12 1C18.0751 1 23 5.92487 23 12C23 18.0751 18.0751 23 12 23C5.92487 23 1 18.0751 1 12C1 5.92487 5.92487 1 12 1ZM12 3C7.02943 3 3 7.02943 3 12C3 16.9706 7.02943 21 12 21C16.9706 21 21 16.9706 21 12C21 7.02943 16.9706 3 12 3ZM14.5 8.5C15.0523 8.5 15.5 8.94772 15.5 9.5V14.5C15.5 15.0523 15.0523 15.5 14.5 15.5H9.5C8.94772 15.5 8.5 15.0523 8.5 14.5V9.5C8.5 8.94772 8.94772 8.5 9.5 8.5H14.5Z" fill="#F53F3F"/>
+</svg>

+ 692 - 0
src/components/pages/PersonnelManagement/components/classL.vue

@@ -0,0 +1,692 @@
+<template>
+  <div>
+    <el-table
+      ref="table"
+      :key="1"
+      :data="tableData"
+      :fit="true"
+      v-loading="isLoading"
+      style="width: 100%; height: 60%"
+      :header-cell-style="{ background: '#f1f1f1' }"
+    >
+      <el-table-column prop="name" label="班级名称" align="center">
+      </el-table-column>
+      <el-table-column label="所属年级" align="center" v-if="!gidL">
+        <template slot-scope="{ row }">
+          {{ getGrade(row.pid) }}
+        </template>
+      </el-table-column>
+      <el-table-column prop="pnum" label="人数" align="center">
+      </el-table-column>
+      <el-table-column label="操作" width="280px">
+        <template slot-scope="scope">
+          <div class="classButtonBox" v-if="gidL">
+            <span @click="deleteClassStudent(scope.row.id)">移除</span>
+          </div>
+          <div class="classButtonBox" v-else>
+            <!-- getStudent() -->
+            <span @click="lookStudent(scope.row.id)">查看学生</span>
+            <span @click="updateG(scope.row.pid, scope.row.id)">修改年级</span>
+            <span @click="openUpdate(scope.row.id, scope.row.name)"
+              >修改名称</span
+            >
+            <span @click="deleteClass(scope.row.id)">删除</span>
+          </div>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <div class="fontPage">
+      <el-pagination
+        background
+        layout="prev, pager, next"
+        :page-size="10"
+        :total="total"
+        :current-page="currentPage"
+        @current-change="handleCurrentChange"
+      ></el-pagination>
+    </div>
+    <!-- 添加班级  -->
+    <el-dialog
+      title="添加班级"
+      :visible.sync="dialogVisible"
+      :append-to-body="true"
+      width="500px"
+      :before-close="handleClose"
+      class="add_student"
+    >
+      <el-form>
+        <el-form-item label="班级名称">
+          <el-input
+            v-model="className"
+            auto-complete="off"
+            placeholder="请输入班级..."
+          ></el-input>
+        </el-form-item>
+      </el-form>
+      <span slot="footer" class="dialog-footer">
+        <el-button @click="dialogVisible = false">取 消</el-button>
+        <el-button type="primary" @click="insertClass">确 定</el-button>
+      </span>
+    </el-dialog>
+
+    <!-- 选择班级添加到年级  -->
+    <el-dialog
+      title="选择班级"
+      :visible.sync="dialogVisibleMember"
+      :append-to-body="true"
+      width="500px"
+      height="80%"
+      :before-close="handleClose"
+      class="addNewPP"
+    >
+      <div class="people">
+        <div class="people_top">
+          <div class="people_top_right">
+            <div class="people_search">
+              <el-input
+                placeholder="搜索班级名称"
+                v-model="searchTN"
+                @keyup.enter.native="handleCurrentChange3(1)"
+              ></el-input>
+              <div class="search_img" @click="handleCurrentChange3(1)">
+                <img src="../../../../assets/icon/search.png" alt />
+              </div>
+            </div>
+          </div>
+          <div class="people_nav">选择班级</div>
+        </div>
+        <el-checkbox-group
+          v-model="checkboxList3"
+          class="people_name"
+          v-if="teacherJuri.length"
+          v-loading="isLoading2"
+        >
+          <el-checkbox
+            v-for="item in teacherJuri"
+            :key="item.id"
+            :label="item.id"
+          >
+            <div class="t_j_box">
+              <span>{{ item.name }}</span>
+            </div>
+          </el-checkbox>
+        </el-checkbox-group>
+        <div style="text-align: center; margin-top: 10px" v-else>暂无数据</div>
+      </div>
+      <div style="margin-top: 10px">
+        <el-pagination
+          background
+          layout="prev, pager, next"
+          :page-size="10"
+          :total="total3"
+          v-if="page3 && teacherJuri.length"
+          style="padding-bottom: 20px"
+          :current-page="SelectClasscurrentPage"
+          @current-change="handleCurrentChange3"
+        ></el-pagination>
+      </div>
+      <span slot="footer" class="dialog-footer">
+        <el-button @click="dialogVisibleMember = false">取 消</el-button>
+        <el-button type="primary" @click="addClassStudent">确定</el-button>
+      </span>
+    </el-dialog>
+
+    <!-- 修改年级 -->
+    <el-dialog
+      title="修改年级"
+      :visible.sync="dialogVisibleGrade"
+      :append-to-body="true"
+      width="500px"
+      :before-close="handleClose"
+      class="add_student"
+    >
+      <el-form>
+        <el-form-item label="选择年级">
+          <el-select
+            v-model="gid"
+            placeholder="请选择班级"
+            class="student_input"
+            clearable
+          >
+            <el-option
+              v-for="(item, index) in grade"
+              :key="index"
+              :label="item.name"
+              :value="item.id"
+            ></el-option>
+          </el-select>
+        </el-form-item>
+      </el-form>
+      <span slot="footer" class="dialog-footer">
+        <el-button @click="dialogVisibleGrade = false">取 消</el-button>
+        <el-button type="primary" @click="updateGrade">确 定</el-button>
+      </span>
+    </el-dialog>
+
+    <!-- 修改班级 -->
+    <el-dialog
+      title="修改班级名称"
+      :visible.sync="dialogVisible1"
+      :append-to-body="true"
+      width="500px"
+      :before-close="handleClose"
+      class="add_student"
+    >
+      <el-form>
+        <el-form-item label="班级名称">
+          <el-input
+            v-model="className1"
+            auto-complete="off"
+            placeholder="请输入班级..."
+          ></el-input>
+        </el-form-item>
+      </el-form>
+      <span slot="footer" class="dialog-footer">
+        <el-button @click="dialogVisible1 = false">取 消</el-button>
+        <el-button type="primary" @click="updateClass">确 定</el-button>
+      </span>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import student from "./student.vue";
+export default {
+  props: ["userid", "oid", "org", "role", "searhValue", "gidL"],
+  components: {
+    student
+  },
+  data() {
+    return {
+      currentPage: 1,//table 分页数据
+      tableData: [],//班级table数据
+      isLoading: false,//班级tableLoading
+      total: 0,//班级table数据total
+
+
+      // 选择添加班级添加到年级 
+        dialogVisibleMember: false,
+        teacherJuri: [], //选择班级数据
+        searchTN: "", //搜索框
+        total3: 0,//选择班级数据总数
+        page3: 1, //页数
+        isLoading2:false,
+        SelectClasscurrentPage:1, //选择年级弹框分页
+        checkboxList3: [],// 选择班级弹框已选择数据 
+
+      // 修改年级
+        dialogVisibleGrade: false, //修改年级弹框
+        gid: "",// 修改年级选择的id
+        classid: "", //查看,修改班级学生,班级id
+        grade: [], //年级数据
+
+      // 添加班级弹框 
+        dialogVisible: false, //添加班级
+        className: "",//添加班级名称
+
+      // 修改班级名称 
+        dialogVisible1: false,//修改班级名称
+        className1: ""
+
+
+    };
+  },
+  computed: {
+    getGrade() {
+      // 展示所属年级
+      return function(gid) {
+        let name = "";
+        this.grade.forEach(element => {
+          if (element.id == gid) {
+            name = element.name;
+          }
+        });
+        return name ? name : "暂无";
+      };
+    }
+  },
+  mounted() {
+    this.selectGrage();
+  },
+  methods: {
+
+    //获取班级table数据 gidL包含两个接口
+    getClass() {
+      this.isLoading = true;
+
+      let params = {};
+      if (this.gidL) {
+        params = {
+          cid: this.gidL,
+          oid: this.oid,
+          cn: this.searhValue,
+          page: this.currentPage
+        };
+      } else {
+        params = {
+          cu: "",
+          oid: this.oid,
+          cn: this.searhValue,
+          page: this.currentPage
+        };
+      }
+
+      this.ajax
+        .get(
+          this.$store.state.api + (this.gidL ? "selectClass2" : "selectClass"),
+          params
+        )
+        .then(res => {
+          this.isLoading = false;
+          this.total = res.data[0].length > 0 ? res.data[0][0].num : 0;
+          this.tableData = res.data[0];
+        })
+        .catch(err => {
+          this.isLoading = false;
+          console.error(err);
+        });
+    },
+    //获取班级列表
+    selectGrage() {
+      let params = {
+        oid: this.oid
+      };
+      this.ajax
+        .get(this.$store.state.api + "selectGrageBySchool", params)
+        .then(res => {
+          this.grade = res.data[0];
+        })
+        .catch(err => {
+          console.error(err);
+        });
+    },
+    //删除班级
+    deleteClass(id) {
+      let params = {
+        id: id
+      };
+      if (this.time()) {
+        this.$confirm("确定删除此班级吗?", "提示", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        })
+          .then(() => {
+            this.ajax
+              .get(this.$store.state.api + "deleteClass", params)
+              .then(res => {
+                this.$message({
+                  message: "删除成功",
+                  type: "success"
+                });
+                this.getClass();
+              })
+              .catch(err => {
+                this.$message.error("删除失败");
+                console.error(err);
+              });
+          })
+          .catch(() => {});
+      }
+    },
+    time() {
+      if (!this.now) {
+        this.now = new Date().getTime();
+        return true;
+      } else {
+        let time = new Date().getTime();
+        if (time - this.now > 3000) {
+          this.now = time;
+          return true;
+        } else {
+          return false;
+        }
+      }
+    },
+    // table分页
+    handleCurrentChange(val) {
+      this.currentPage = val;
+      this.getClass();
+    },
+
+    // 年级视图函数调用
+      // 移除班级
+      deleteClassStudent(id) {
+        // uid班级id   cid年级id
+        let params = [{ uid: id, cid: this.gidL }];
+        this.$confirm("确定在本年级移除此班级吗?", "提示", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        })
+          .then(() => {
+            this.ajax
+              .post(this.$store.state.api + "deleteGradeClass", params)
+              .then(res => {
+                this.$message({
+                  message: "操作成功",
+                  type: "success"
+                });
+                this.getClass()
+              })
+              .catch(err => {
+                this.$message.error("操作失败");
+                console.error(err);
+              });
+          })
+          .catch(() => {});
+      },
+
+    // 选择添加班级弹框
+      // 打开选择添加班级
+      addStudent() {
+        this.dialogVisibleMember = true;
+        this.searchTN = "";
+        this.SelectClasscurrentPage = 1;
+        this.getClassStudent();
+      },
+      // 选择班级弹框数据
+      getClassStudent() {
+        this.isLoading2 = true;
+        let params = {
+          oid: this.oid,
+          cid: this.gidL,
+          cn: this.searchTN,
+          page: this.SelectClasscurrentPage,
+          num: 10
+        };
+        this.ajax
+          .get(this.$store.state.api + "getGradeClass", params)
+          .then(res => {
+            this.isLoading2 = false;
+            this.total3 = res.data[0].length > 0 ? res.data[0][0].num : 0;
+            this.teacherJuri = res.data[0];
+          })
+          .catch(err => {
+            this.isLoading2 = false;
+            console.error(err);
+          });
+      },
+      // 选择班级弹框确定添加
+      addClassStudent() {
+        if (!this.checkboxList3.length) {
+          this.$message.error("请选择要添加的班级");
+          return;
+        }
+        let params = [
+          {
+            cid: this.gidL,
+            student: JSON.stringify(this.checkboxList3)
+          }
+        ];
+        this.ajax
+          .post(this.$store.state.api + "addGradeClass", params)
+          .then(res => {
+            this.checkboxList3 = [];
+            this.dialogVisibleMember = false;
+            this.getClass()
+          })
+          .catch(err => {
+            console.error(err);
+          });
+      },
+      // 选择班级弹框分页查询数据
+      handleCurrentChange3(val) {
+        this.SelectClasscurrentPage = val;
+        this.getClassStudent();
+      },
+
+    // 学生视图函数调用
+      // 查看班级学生
+      lookStudent(cid) {
+        this.$emit("lookstudentL", cid);
+      },
+
+    // 关闭弹框
+    handleClose(done) {
+      done();
+    },
+
+    //首页调用新增班级
+    insertClass() {
+      let params = {
+        name: this.className,
+        oid: this.oid,
+        uid: this.userid
+      };
+      this.ajax
+        .get(this.$store.state.api + "insertClass", params)
+        .then(res => {
+          if (res.data[0] && res.data[0][0].classname == 1) {
+            this.$message({
+              message: "不能与其他班级名称相同!",
+              type: "error"
+            });
+          } else {
+            this.$message({
+              message: "新增成功",
+              type: "success"
+            });
+            this.dialogVisible = false;
+            this.getClass();
+            this.className = "";
+          }
+        })
+        .catch(err => {
+          this.$message({
+            message: "新增失败",
+            type: "error"
+          });
+          console.error(err);
+        });
+    },
+
+
+    // 修改年级弹框
+        // 打开修改年级弹框
+        updateG(gid, id) {
+          this.gid = gid;
+          this.classid = id;
+          this.dialogVisibleGrade = true;
+        },
+        // 确定修改年级
+        updateGrade() {
+          this.$confirm("确定修改吗?", "提示", {
+            confirmButtonText: "确定",
+            cancelButtonText: "取消",
+            type: "warning"
+          })
+            .then(() => {
+              let params = [
+                {
+                  cid: this.gid,
+                  student: JSON.stringify([this.classid])
+                }
+              ];
+              this.ajax
+                .post(this.$store.state.api + "addGradeClass", params)
+                .then(res => {
+                  this.gid = "";
+                  this.classid = "";
+                  this.dialogVisibleGrade = false;
+                  this.getClass();
+                })
+                .catch(err => {
+                  console.error(err);
+                });
+            })
+            .catch(() => {});
+        },
+
+
+    // 修改班级名称弹框
+        // 打开修改班级名称弹框
+        openUpdate(id, n) {
+          this.classid = id;
+          this.className1 = n;
+          this.dialogVisible1 = true;
+        },
+        //确定修改班级名称弹框
+        updateClass() {
+          let params = {
+            id: this.classid,
+            n: this.className1,
+            oid: this.oid
+          };
+          this.ajax
+            .get(this.$store.state.api + "updateClass", params)
+            .then(res => {
+              if (res.data[0] && res.data[0][0].classname == 1) {
+                this.$message({
+                  message: "不能与其他班级名称相同!",
+                  type: "error"
+                });
+              } else {
+                this.$message({
+                  message: "修改成功",
+                  type: "success"
+                });
+                this.dialogVisible1 = false;
+                this.getClass();
+                this.classid = "";
+                this.className1 = "";
+              }
+            })
+            .catch(err => {
+              this.$message({
+                message: "修改失败",
+                type: "error"
+              });
+              console.error(err);
+            });
+        },
+
+  }
+};
+</script>
+
+<style scoped>
+.fontPage {
+  height: 70px;
+  display: flex;
+  justify-content: end;
+  align-content: center;
+  box-sizing: border-box;
+  padding: 15px 0;
+}
+.classButtonBox span {
+  color: #6b6b6b;
+  font-size: 14px;
+  cursor: pointer;
+}
+.add_student >>> .el-dialog__header {
+  padding: 20px 20px 10px;
+  text-align: center;
+  background: #32455b;
+}
+
+.add_student >>> .el-dialog__title {
+  font-size: 14px !important;
+  color: #fff !important;
+}
+
+.add_student >>> .el-dialog__headerbtn {
+  font-size: 20px !important;
+}
+
+.add_student >>> .el-form-item {
+  display: flex;
+}
+
+.add_student >>> .el-form-item__content {
+  margin: 0 !important;
+}
+
+.add_student >>> .el-dialog__footer {
+  text-align: center !important;
+}
+.header-title {
+  display: flex;
+}
+
+
+.addNewPP >>> .el-dialog {
+  margin-top: 5vh !important;
+}
+
+.addNewPP >>> .el-dialog__body {
+  padding: 5px 20px; 
+}
+.people {
+  border: 1px solid rgb(229 229 229);
+  height: 450px;
+  border-radius: 5px;
+  width: 100%;
+  overflow: auto;
+}
+
+.people_top {
+  display: flex;
+  width: 100%;
+  /* justify-content: space-between; */
+  /* align-items: center; */
+  flex-direction: column;
+  padding: 10px 25px 0;
+  box-sizing: border-box;
+}
+
+.people_top_right {
+  height: 40px;
+  margin-bottom: 10px;
+}
+
+.people_search {
+  display: flex;
+  position: relative;
+}
+
+.people_search >>> .el-input__inner {
+  /* height: 25px; */
+  width: 95%;
+}
+
+.search_img {
+  width: 20px;
+  height: 20px;
+  position: absolute;
+  right: 30px;
+  top: 50%;
+  transform: translateY(-50%);
+}
+
+.search_img > img {
+  width: 100%;
+  height: 100%;
+}
+
+.people_name {
+  display: flex;
+  justify-content: flex-start;
+  padding: 10px 0 0 25px;
+  flex-direction: column;
+  flex-wrap: nowrap;
+  height: calc(100% - 140px);
+  overflow-y: auto;
+  overflow-x: hidden;
+  flex-direction: column;
+}
+
+.people_name >>> .el-checkbox {
+  width: 100%;
+  display: flex;
+  align-items: center;
+  margin-bottom: 10px;
+}
+
+.people_name >>> .el-checkbox__label {
+  text-overflow: ellipsis;
+  overflow: hidden;
+  width: 100%;
+}
+</style>

+ 340 - 0
src/components/pages/PersonnelManagement/components/grade.vue

@@ -0,0 +1,340 @@
+<template>
+  <div>
+    <el-table
+      ref="table"
+      :key="1"
+      :data="tableData"
+      :fit="true"
+      v-loading="isLoading"
+      :header-cell-style="{ background: '#f1f1f1' }"
+    >
+      <el-table-column
+        prop="name"
+        label="年级名称"
+        min-width="40%"
+        align="center"
+      >
+      </el-table-column>
+      <el-table-column
+        prop="pnum"
+        label="班级数"
+        min-width="40%"
+        align="center"
+      >
+      </el-table-column>
+      <el-table-column label="操作" width="250px">
+        <template slot-scope="scope">
+          <div class="baseFlex">
+            <span @click="getStudent(scope.row.id)">查看班级</span>
+            <span @click="openUpdate(scope.row.id, scope.row.name)">修改</span>
+            <span @click="deleteGrade(scope.row.id)">删除</span>
+          </div>
+        </template>
+      </el-table-column>
+    </el-table>
+    <div class="fontPage">
+      <el-pagination
+        background
+        layout="prev, pager, next"
+        :page-size="10"
+        :total="total"
+        :current-page="currentPage"
+        @current-change="handleCurrentChange"
+      ></el-pagination>
+    </div>
+
+    <el-dialog
+      title="添加年级"
+      :visible.sync="dialogVisible"
+      :append-to-body="true"
+      width="500px"
+      :before-close="handleClose"
+      class="add_student"
+    >
+      <el-form>
+        <el-form-item label="添加年级" >
+          <el-input
+            v-model="className"
+            auto-complete="off"
+            placeholder="请输入年级..."
+          ></el-input>
+        </el-form-item>
+      </el-form>
+      <span slot="footer" class="dialog-footer">
+        <el-button @click="dialogVisible = false">取 消</el-button>
+        <el-button type="primary" @click="insertGrade">确 定</el-button>
+      </span>
+    </el-dialog>
+    <el-dialog
+      title="修改年级名称"
+      :visible.sync="dialogVisible1"
+      :append-to-body="true"
+      width="500px"
+      :before-close="handleClose"
+      class="add_student"
+    >
+      <el-form>
+        <el-form-item label="年级名称" >
+          <el-input
+            v-model="className1"
+            auto-complete="off"
+            placeholder="请输入年级..."
+          ></el-input>
+        </el-form-item>
+      </el-form>
+      <span slot="footer" class="dialog-footer">
+        <el-button @click="dialogVisible1 = false">取 消</el-button>
+        <el-button type="primary" @click="updateGrade">确 定</el-button>
+      </span>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+export default {
+  props: ["userid", "oid", "org", "role", "searhValue"],
+
+  data() {
+    return {
+      tableData: [],
+      isLoading: false,
+      total: 0,
+      currentPage: 1,
+
+      // 修改年级名称
+      dialogVisible1: false,
+      className1: "",
+
+      // 添加年级
+      dialogVisible: false,
+      className: ""
+    };
+  },
+  methods: {
+    //获取年级table列表
+    getClass() {
+      this.isLoading = true;
+      let params = {
+        // username: this.$store.state.userInfo.userid,
+        cu: "",
+        oid: this.oid,
+        cn: this.searhValue,
+        page: this.currentPage
+      };
+      this.ajax
+        .get(this.$store.state.api + "selectGrade", params)
+        .then(res => {
+          this.isLoading = false;
+          this.total = res.data[0].length > 0 ? res.data[0][0].num : 0;
+          this.tableData = res.data[0];
+        })
+        .catch(err => {
+          this.isLoading = false;
+          console.error(err);
+        });
+    },
+    handleClose(done) {
+      done();
+    },
+    //删除年级
+    deleteGrade(id) {
+      let params = {
+        id: id,
+      };
+      if (this.time()) {
+        this.$confirm("确定删除此年级吗?", "提示", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning",
+        })
+          .then(() => {
+            this.ajax
+              .get(this.$store.state.api + "deleteGrade", params)
+              .then((res) => {
+                this.$message({
+                  message: "删除成功",
+                  type: "success",
+                });
+                if (this.currentPage != 1 && this.tableData.length == 1) {
+                  this.currentPage - 1;
+                }
+                this.getClass();
+              })
+              .catch((err) => {
+                this.$message.error("删除失败");
+                console.error(err);
+              });
+          })
+          .catch(() => { });
+      }
+    },
+    time() {
+      if (!this.now) {
+        this.now = new Date().getTime();
+        return true;
+      } else {
+        let time = new Date().getTime();
+        if (time - this.now > 3000) {
+          this.now = time;
+          return true;
+        } else {
+          return false;
+        }
+      }
+    },
+    // 修改年级
+      openUpdate(id, n) {
+        this.classid = id;
+        this.className1 = n;
+        this.dialogVisible1 = true;
+      },
+      //修改年级
+      updateGrade() {
+        let params = {
+          id: this.classid,
+          n: this.className1,
+          oid: this.oid
+        };
+        this.ajax
+          .get(this.$store.state.api + "updateGrade", params)
+          .then(res => {
+            if (res.data[0] && res.data[0][0].classname == 1) {
+              this.$message({
+                message: "不能与其他年级名称相同!",
+                type: "error"
+              });
+            } else {
+              this.$message({
+                message: "修改成功",
+                type: "success"
+              });
+              this.dialogVisible1 = false;
+              this.getClass();
+              this.classid = "";
+              this.className1 = "";
+            }
+          })
+          .catch(err => {
+            this.$message({
+              message: "修改失败",
+              type: "error"
+            });
+            console.error(err);
+          });
+      },
+
+    // 查看班级
+    getStudent(cid) {
+      this.$emit('lookgradeL',cid)
+    },
+
+
+    //首页调用新增年级
+    insertGrade() {
+      let params = {
+        name: this.className,
+        oid: this.oid,
+        uid: this.userid
+      };
+      this.ajax
+        .get(this.$store.state.api + "insertGrade", params)
+        .then(res => {
+          if (res.data[0] && res.data[0][0].classname == 1) {
+            this.$message({
+              message: "不能与其他年级名称相同!",
+              type: "error"
+            });
+          } else {
+            this.$message({
+              message: "新增成功",
+              type: "success"
+            });
+            this.dialogVisible = false;
+            this.sClassName = "";
+            this.getClass();
+            this.className = "";
+          }
+        })
+        .catch(err => {
+          this.$message({
+            message: "新增失败",
+            type: "error"
+          });
+          console.error(err);
+        });
+    },
+
+    handleCurrentChange(val) {
+      this.page = val;
+      this.getClass();
+    }
+  }
+};
+</script>
+
+<style scoped>
+.fontPage {
+  height: 70px;
+  display: flex;
+  justify-content: end;
+  align-content: center;
+  box-sizing: border-box;
+  padding: 15px 0;
+}
+.baseFlex > span {
+  color: #6b6b6b;
+  font-size: 14px;
+  cursor: pointer;
+}
+.add_student >>> .el-dialog__header {
+  padding: 20px 20px 10px;
+  text-align: center;
+  background: #32455b;
+}
+
+.add_student >>> .el-dialog__title {
+  font-size: 14px !important;
+  color: #fff !important;
+}
+
+.add_student >>> .el-dialog__headerbtn {
+  font-size: 20px !important;
+}
+
+.add_student >>> .el-form-item__label {
+  margin-left: 65px;
+}
+
+.add_student >>> .el-form-item {
+  display: flex;
+}
+
+.add_student >>> .el-form-item__content {
+  margin: 0 !important;
+}
+
+.add_input {
+  width: 365px;
+}
+
+.add_student >>> .el-dialog__footer {
+  text-align: center !important;
+}
+.header-title {
+  display: flex;
+}
+
+.logoImg {
+  width: 30px;
+}
+
+.logoImg > img {
+  width: 100%;
+  height: 100%;
+}
+
+.title_add_student {
+  margin: 0 auto;
+  color: #fff;
+}
+</style>

+ 969 - 0
src/components/pages/PersonnelManagement/components/student.vue

@@ -0,0 +1,969 @@
+<template>
+  <div>
+    <div class="fontlist" v-loading="isLoading">
+      <div class="listA" v-for="i in tableData" :key="i.userid">
+        <div class="baseFlex">
+          <img :src="i.headportrait ? i.headportrait : tx" alt />
+          <div
+            style="display: flex;flex-direction: column;justify-content: space-between;color: #666666;height: 100%;"
+          >
+            <div style="font-size: 16px;color: #000;">{{ i.username }}</div>
+            <div>{{ i.acc }}</div>
+          </div>
+        </div>
+        <div class="baseFlex">
+          <el-tag size="mini" v-if="i.gname">{{ i.gname }}</el-tag>
+          <el-tag size="mini" v-else type="danger">无年级</el-tag>
+
+          <el-tag size="mini" v-if="i.classname" type="success">{{
+            i.classname
+          }}</el-tag>
+          <el-tag size="mini" v-else type="danger">无班级</el-tag>
+
+         
+            <span @click="iniPassword(i.userid)">初始化密码</span>
+            <span @click="updateStudentA(i)">编辑</span>
+            <template v-if="cidL">
+                <span @click="deleteClassStudent(i.userid)">移出</span>
+            </template>
+            <span v-else @click="deleteStudent(i.userid, i.state)">删除</span>
+
+          
+        </div>
+      </div>
+    </div>
+    <div class="fontPage">
+      <el-pagination
+        @size-change="handleSizeChange"
+        @current-change="handleCurrentChange"
+        :current-page="currentPage"
+        :page-sizes="[10, 20, 50, 100]"
+        :page-size="pageSize"
+        layout="total, sizes, prev, pager, next, jumper"
+        :total="total"
+      >
+      </el-pagination>
+    </div>
+    <!-- 添加学生  -->
+    <el-dialog
+      :visible.sync="dialogVisible"
+      :append-to-body="true"
+      width="600px"
+      :before-close="handleClose"
+      class="add_student"
+    >
+      <div slot="title" class="header-title">
+        <div class="logoImg">
+          <img src="../../../../assets/logo.png" alt />
+        </div>
+        <div class="title_add_student">添加学生</div>
+      </div>
+      <el-form>
+        <el-form-item label="学生姓名" label-width="100px">
+          <span>
+            <el-input
+              placeholder="请输入学生姓名"
+              clearable
+              v-model="sName"
+              class="add_input"
+            ></el-input>
+          </span>
+        </el-form-item>
+        <el-form-item label="学生账号" label-width="100px">
+          <span>
+            <el-input
+              placeholder="请输入学生账号"
+              clearable
+              v-model="sMail"
+              class="add_input"
+            ></el-input>
+          </span>
+        </el-form-item>
+        <el-form-item label="所属学校" label-width="100px">
+          <el-input
+            disabled
+            style="width: 300px"
+            v-model="schoolName"
+          ></el-input>
+        </el-form-item>
+        <el-form-item label="班级" label-width="100px">
+          <el-select
+            multiple
+            collapse-tags
+            v-model="sByClass"
+            placeholder="请选择班级"
+            filterable
+          >
+            <el-option
+              v-for="(item, index) in classJuri"
+              :key="index"
+              :label="item.name"
+              :value="item.id"
+            ></el-option>
+          </el-select>
+        </el-form-item>
+        <div style="text-align: center; color: #adb3b7">
+          注:添加学生的账号密码为Coco1234
+        </div>
+      </el-form>
+      <span slot="footer" class="dialog-footer flex">
+        <el-button class="right" @click="insertStudent">确认</el-button>
+      </span>
+    </el-dialog>
+
+    <!-- 修改学生  -->
+    <el-dialog
+      :visible.sync="dialogVisibleUpdate"
+      :append-to-body="true"
+      width="600px"
+      :before-close="handleClose"
+      class="add_student"
+    >
+      <div slot="title" class="header-title">
+        <div class="logoImg">
+          <img src="../../../../assets/logo.png" alt />
+        </div>
+        <div class="title_add_student">修改学生</div>
+      </div>
+      <el-form>
+        <el-form-item label="学生名称" label-width="100px">
+          <span>
+            <el-input
+              placeholder="请输入学生姓名"
+              clearable
+              v-model="userinfo.username"
+              class="add_input"
+            ></el-input>
+          </span>
+        </el-form-item>
+        <el-form-item label="学生账号" label-width="100px">
+          <span>
+            <el-input
+              placeholder="请输入学生账号"
+              clearable
+              v-model="userinfo.acc"
+              class="add_input"
+            ></el-input>
+          </span>
+        </el-form-item>
+        <el-form-item label="所属学校" label-width="100px">
+          <el-input
+            disabled
+            style="width: 300px"
+            v-model="schoolName"
+          ></el-input>
+        </el-form-item>
+        <el-form-item label="班级" label-width="100px">
+          <el-select
+            multiple
+            collapse-tags
+            v-model="userinfo.classid"
+            v-loading="optionLoading"
+            placeholder="请选择班级"
+          >
+            <el-option
+              v-for="(item, index) in classJuri"
+              :key="index"
+              :label="item.name"
+              :value="item.id"
+            ></el-option>
+          </el-select>
+        </el-form-item>
+        <div style="text-align: center; color: #adb3b7">
+          注:添加学生的账号密码为Coco1234
+        </div>
+      </el-form>
+      <span slot="footer" class="dialog-footer flex">
+        <el-button class="right" @click="updateStudent">修改</el-button>
+      </span>
+    </el-dialog>
+
+    <!-- 添加学生到班级  -->
+     <el-dialog
+      title="添加学生"
+      :visible.sync="dialogVisibleMember"
+      :append-to-body="true"
+      width="600px"
+      height="80%"
+      :before-close="handleClose"
+      class="addNewPP"
+    >
+      <div class="people">
+        <div class="people_top">
+          <div class="people_top_right">
+            <div class="people_search">
+              <el-input
+                placeholder="搜索学生姓名"
+                v-model="searchTN"
+                @keyup.enter.native="getClassStudent"
+              ></el-input>
+              <div class="search_img" @click="getClassStudent">
+                <img src="../../../../assets/icon/search.png" alt />
+              </div>
+            </div>
+          </div>
+          <div class="people_nav">选择成员</div>
+        </div>
+        <div
+          class="t_j_box"
+          style="
+            padding: 20px 0 0 25px;
+            width: calc(100% - 55px);
+            margin-left: 25px;
+          "
+        >
+          <span>姓名</span>
+          <span>账号</span>
+        </div>
+        <el-checkbox-group
+          v-model="checkboxList3"
+          class="people_name"
+          v-if="teacherJuri.length"
+          v-loading="isLoading2"
+        >
+          <el-checkbox
+            v-for="item in teacherJuri"
+            :key="item.userid"
+            :label="item.userid"
+          >
+            <div class="t_j_box">
+              <el-tooltip
+                placement="top"
+                :content="item.name ? item.name : '暂无姓名'"
+              >
+                <span>{{ item.name ? item.name : "暂无姓名" }}</span>
+              </el-tooltip>
+              <el-tooltip placement="top" :content="item.username">
+                <span>{{ item.username }}</span>
+              </el-tooltip>
+            </div>
+          </el-checkbox>
+        </el-checkbox-group>
+        <div style="text-align: center; margin-top: 10px" v-else>暂无数据</div>
+      </div>
+      <div style="margin-top: 10px">
+        <el-pagination
+          background
+          layout="prev, pager, next"
+          :page-size="10"
+          :total="total3"
+          v-if="page3 && teacherJuri.length"
+          style="padding-bottom: 20px"
+          @current-change="handleCurrentChange3"
+        ></el-pagination>
+      </div>
+      <span slot="footer" class="dialog-footer">
+        <el-button @click="dialogVisibleMember = false">取 消</el-button>
+        <el-button type="primary" @click="addClassStudent">确定</el-button>
+      </span>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import pinyin from "../../../../../node_modules/js-pinyin/index";
+
+export default {
+  props: ["userid", "oid", "org", "role", "searhValue","cid","cidL"],
+  data() {
+    return {
+      // 学生视图
+        tableData: [], //学生视图数据
+        tx: require("../../../../assets/avatar.png"),
+        isLoading: false,
+        total: 0,
+        currentPage: 1,
+        pageSize: 10,
+
+      // 班级添加学生弹框
+        dialogVisibleMember:false,
+        isLoading2:false,
+        teacherJuri:[], //数据
+        total3: 0, //学生总数
+        checkboxList3:[], //勾选中的学生
+        page3: 1, //页数
+        searchTN:'', //搜索框
+
+      // 修改学生弹框
+        dialogVisibleUpdate: false,
+        userinfo: {},
+        userinfoA: {},
+        classJuri: [], //班级列表
+        optionLoading: false, //班级列表loading
+
+      // 添加学生弹框
+        dialogVisible: false,
+        sName: "", 
+        sByClass: "", //班级
+        sMail: "", //学生账号
+        sPhone: "",
+        userSuffix: "", //后缀
+        sId: "",
+
+      schoolName: "",//学校名称
+      schoolChar: "",
+
+
+    };
+  },
+  methods: {
+
+
+    // 获取table获取学生
+    getStudent() {
+      this.isLoading = true;
+      let params = {
+        oid: this.oid,
+        cid: this.cid,
+        inp: this.searhValue,
+        page: this.currentPage,
+        num: this.pageSize
+      };
+      this.ajax
+        .get(this.$store.state.api + "selectStudentManage", params)
+        .then(res => {
+          this.isLoading = false;
+          this.total = res.data[0].length > 0 ? res.data[0][0].num : 0;
+          this.tableData = res.data[0];
+        })
+        .catch(err => {
+          this.isLoading = false;
+          console.error(err);
+        });
+    },
+    // 获取创建学生用户后缀
+    getUser() {
+      let params = {
+        userid: this.userid
+      };
+      this.ajax
+        .get(this.$store.state.api + "selectUser", params)
+        .then(res => {
+          this.userSuffix = res.data[0][0].accountNumber.split("@")[1];
+        })
+        .catch(err => {
+          console.error(err);
+        });
+    },
+    // 获取学校名称
+    getSchoolName() {
+      let params = {
+        oid: this.oid
+      };
+      this.ajax
+        .get(this.$store.state.api + "selectSchoolName2", params)
+        .then(res => {
+          this.schoolName = res.data[0][0].name;
+          const cleanedSchoolName = res.data[0][0].name.replace(
+            /[,。;:!“”‘’()()]/g,
+            ""
+          ); // 去掉标点符号
+          // console.log(pinyin);
+          // console.log(pinyin.getFullChars(cleanedSchoolName));
+          // console.log(pinyin.getCamelChars(cleanedSchoolName));
+          this.schoolChar = pinyin
+            .getCamelChars(cleanedSchoolName)
+            .toLowerCase();
+        })
+        .catch(err => {
+          console.error(err);
+        });
+    },
+    //获取班级列表
+    getClass() {
+      this.optionLoading = true;
+      let params = {
+        oid: this.oid
+      };
+      this.ajax
+        .get(this.$store.state.api + "selectClassBySchool", params)
+        .then(res => {
+          this.optionLoading = false;
+          this.classJuri = res.data[0];
+        })
+        .catch(err => {
+          this.optionLoading = false;
+          console.error(err);
+        });
+    },
+    // 初始化密码
+    iniPassword(id) {
+      this.$confirm("确定" + "初始化" + "此学生的密码吗?", "提示", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      })
+        .then(() => {
+          let params = [
+            {
+              uid: id,
+              pa: "Coco1234"
+            }
+          ];
+          this.ajax
+            .post(this.$store.state.api + "iniPassword", params)
+            .then(res => {
+              this.$message({
+                message: "初始化密码成功!",
+                type: "success"
+              });
+            })
+            .catch(err => {
+              console.error(err);
+            });
+        })
+        .catch(() => {});
+    },
+    // 删除学生
+    deleteStudent(id, state) {
+      state = 0;
+      let params = [{ uid: id, state: state }];
+      this.$confirm("确定删除此学生吗?", "提示", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      })
+        .then(() => {
+          this.ajax
+            .post(this.$store.state.api + "deleteStudent", params)
+            .then(res => {
+              this.$message({
+                message: "操作成功",
+                type: "success"
+              });
+              this.getStudent();
+            })
+            .catch(err => {
+              this.$message.error("操作失败");
+              console.error(err);
+            });
+        })
+        .catch(() => {});
+    },
+    // 修改每页获取个数
+    handleSizeChange(val) {
+      this.pageSize = val;
+      this.currentPage = 1;
+      this.getStudent();
+      console.log(`每页 ${val} 条`);
+    },
+    // 跳转页数
+    handleCurrentChange(val) {
+      this.currentPage = val;
+      this.getStudent();
+      console.log(`当前页: ${val}`);
+    },
+    // 关闭弹框
+    handleClose(done) {
+      done();
+    },
+    time() {
+      if (!this.now) {
+        this.now = new Date().getTime();
+        return true;
+      } else {
+        let time = new Date().getTime();
+        if (time - this.now > 3000) {
+          this.now = time;
+          return true;
+        } else {
+          return false;
+        }
+      }
+    },
+
+    // 班级添加学生弹框
+        // 首页调用打开班级添加学生弹框
+        diaAdd(){
+          this.dialogVisibleMember = true;
+          this.searchTN = "";
+          this.getClassStudent();
+        },
+        // 添加学生弹框获取数据
+        getClassStudent() {
+          this.isLoading2 = true;
+          let params = {
+            oid: this.oid,
+            cid: this.cid,
+            cn: this.searchTN,
+            page: this.page3,
+            num: 10
+          };
+          this.ajax
+            .get(this.$store.state.api + "getClassStudent", params)
+            .then(res => {
+              this.isLoading2 = false;
+              this.total3 = res.data[0].length > 0 ? res.data[0][0].num : 0;
+              this.teacherJuri = res.data[0];
+            })
+            .catch(err => {
+              this.isLoading2 = false;
+              console.error(err);
+            });
+        },
+        // 确定将学生加入班级
+        addClassStudent() {
+          if (!this.checkboxList3.length) {
+            this.$message.error("请选择要添加班级的学生");
+            return;
+          }
+          let params = [
+            {
+              cid: this.cid,
+              student: JSON.stringify(this.checkboxList3)
+            }
+          ];
+          this.ajax
+            .post(this.$store.state.api + "addClassStudent", params)
+            .then(res => {
+              this.checkboxList3 = [];
+              this.dialogVisibleMember = false;
+              this.getStudent();
+            })
+            .catch(err => {
+              console.error(err);
+            });
+        },
+      
+       
+    //添加学生弹框
+        addStudent() {
+          this.dialogVisible = true;
+          this.sName = "";
+          this.sPhone = "";
+          this.sByClass = "" ;
+          this.sMail='';
+          // this.getClass();
+        },
+        //确认添加学生新增学生前判断是否被注册以及格式问题
+        insertStudent() {
+          this.dialogVisible = true;
+          if (this.sName === "") {
+            this.$message.error("学生姓名不能为空");
+            return;
+          } else if (this.sByClass === "") {
+            this.$message.error("请为学生选择班级");
+            return;
+          } else if (
+            this.sPhone != "" &&
+            !/^[1][3,4,5,7,8][0-9]{9}$/.test(this.sPhone)
+          ) {
+            this.$message.error("手机号格式不正确");
+            return;
+          } else if (this.sMail === "") {
+            this.$message.error("学生账号不能为空");
+            return;
+          }
+
+          let mail = "";
+          if (
+            /^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+(\.[a-zA-Z0-9_-])+/.test(this.sMail)
+          ) {
+            mail = this.sMail;
+          } else {
+            if (
+              this.org != "" &&
+              this.org != "null" &&
+              this.org != undefined &&
+              this.org &&
+              this.schoolChar
+            ) {
+              mail = this.sMail + "@" + this.schoolChar + "." + this.userSuffix;
+            } else {
+              mail = this.sMail + "@" + this.userSuffix;
+            }
+          }
+          if (this.time()) {
+            let params = { un: mail };
+            this.ajax
+              .get(this.$store.state.api + "findMail", params)
+              .then(res => {
+                if (res.data[0].length > 0) {
+                  this.$message.error("此学生账号已被注册");
+                } else {
+                  this.comfirmAddStudent();
+                }
+              })
+              .catch(err => {
+                console.error(err);
+              });
+          }
+        },
+        // 最终添加学生函数
+        comfirmAddStudent() {
+          let mail = "";
+          if (
+            /^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+(\.[a-zA-Z0-9_-])+/.test(this.sMail)
+          ) {
+            mail = this.sMail;
+          } else {
+            if (
+              this.org != "" &&
+              this.org != "null" &&
+              this.org != undefined &&
+              this.org &&
+              this.schoolChar
+            ) {
+              mail = this.sMail + "@" + this.schoolChar + "." + this.userSuffix;
+            } else {
+              mail = this.sMail + "@" + this.userSuffix;
+            }
+          }
+          let params = [
+            {
+              username: mail,
+              userpassword: "Coco1234",
+              alias: this.sName,
+              oid: this.oid,
+              ph: this.sPhone,
+              sid: this.sId,
+              cid: this.sByClass.join(","),
+              org: this.org
+            }
+          ];
+          console.log("params", params);
+
+          this.ajax
+            .post(this.$store.state.api + "batchRegistrationOrg", params)
+            .then(res => {
+              this.$message({
+                message: "新增成功",
+                type: "success"
+              });
+
+              this.dialogVisible = false;
+              this.sPhone = "";
+              this.sName = "";
+              // this.sBySchool = [];
+              this.sByClass = [];
+              this.sMail = "";
+              this.getStudent();
+              this.addOp3("1", "", { type: "student_user_add" }, "success");
+            })
+            .catch(err => {
+              this.isLoading = false;
+              this.addOp3("1", "", { type: "student_user_add" }, err);
+
+              this.$message({
+                message: "新增失败",
+                type: "error"
+              });
+              console.error(err);
+            });
+        },
+        // 控制添加学生分页
+        handleCurrentChange3(val) {
+          this.page3 = val;
+          this.getClassStudent();
+        },
+
+
+    // 修改,编辑学生弹框(班级视图的与学生视图的学生编辑修改共用一个修改函数)
+        // 打开编辑学生弹框
+        updateStudentA(res) {
+          this.userinfo = JSON.parse(JSON.stringify(res));
+          this.userinfoA = JSON.parse(JSON.stringify(res));
+          this.userinfo.classid = this.userinfo.classid.split(",");
+
+          this.dialogVisibleUpdate = true;
+        },
+        // 修改学生
+        updateStudent() {
+          if (this.userinfo.username === "") {
+            this.$message.error("学生姓名不能为空");
+            return;
+          } else if (!this.userinfo.classid) {
+            this.$message.error("请为学生选择班级");
+            return;
+          } else if (
+            !/^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+(\.[a-zA-Z0-9_-])+/.test(
+              this.userinfo.acc
+            )
+          ) {
+            this.$message.error("邮箱格式不正确");
+            return;
+          }
+
+          if (this.time()) {
+            if (this.userinfoA.acc != this.userinfo.acc) {
+              let params = { un: this.userinfo.acc };
+              this.ajax
+                .get(this.$store.state.api + "findMail", params)
+                .then(res => {
+                  if (res.data[0].length > 0) {
+                    this.$message.error("此学生账号已被注册");
+                  } else {
+                    this.update_Student();
+                  }
+                })
+                .catch(err => {
+                  console.error(err);
+                });
+            } else {
+              this.update_Student();
+            }
+          }
+        },
+        // 确定修改学生
+        update_Student() {
+          let params = [
+            {
+              userid: this.userinfo.userid,
+              username: this.userinfo.acc,
+              alias: this.userinfo.username,
+              ph: this.userinfo.phonenumber,
+              sid: this.userinfo.studentid,
+              cid: this.userinfo.classid.join(",")
+            }
+          ];
+          console.log("params", params);
+
+          this.ajax
+            .post(this.$store.state.api + "updateStudentInfo", params)
+            .then(res => {
+              this.$message({
+                message: "修改成功",
+                type: "success"
+              });
+              this.dialogVisibleUpdate = false;
+              this.getStudent();
+            })
+            .catch(err => {
+              this.isLoading = false;
+              this.$message({
+                message: "修改失败",
+                type: "error"
+              });
+              console.error(err);
+            });
+        },
+
+    // 班级视图调用学生视图方法 
+        // 将学生移除班级
+        deleteClassStudent(id) {
+          let params = [{ uid: id, cid: this.cidL }];
+          this.$confirm("确定移除此学生在本班级吗?", "提示", {
+            confirmButtonText: "确定",
+            cancelButtonText: "取消",
+            type: "warning",
+          })
+            .then(() => {
+              this.ajax
+                .post(this.$store.state.api + "deleteClassStudent", params)
+                .then((res) => {
+                  this.$message({
+                    message: "操作成功",
+                    type: "success",
+                  });
+                  this.getStudent();
+                })
+                .catch((err) => {
+                  this.$message.error("操作失败");
+                  console.error(err);
+                });
+            })
+            .catch(() => { });
+        },
+
+
+  },
+  mounted() {
+    this.getUser();
+    this.getSchoolName();
+    this.getClass();
+    // this.getStudent();
+  }
+};
+</script>
+
+<style scoped>
+
+.baseFlex {
+  display: flex;
+  align-items: center;
+  gap: 10px;
+  height: 100%;
+}
+.baseFlex > img {
+  /* width: 50px; */
+  height: 100%;
+  object-fit: cover;
+}
+.baseFlex > span {
+  color: #6b6b6b;
+  font-size: 14px;
+  cursor: pointer;
+}
+.fontlist {
+  border-radius: 10px;
+  overflow: auto;
+  background: #fff;
+  flex: 1;
+  min-height: 250px;
+}
+.listA {
+  display: flex;
+  justify-content: space-between;
+  border-bottom: 1px #e7e7e7 solid;
+  height: 70px;
+  align-items: center;
+  box-sizing: border-box;
+  padding: 15px;
+  /* background: #fff; */
+}
+.fontPage {
+  height: 70px;
+  display: flex;
+  justify-content: end;
+  align-content: center;
+  box-sizing: border-box;
+  padding: 15px 0;
+}
+.add_student >>> .el-dialog__header {
+  padding: 20px 20px 10px;
+  text-align: center;
+  background: #32455b;
+}
+
+.add_student >>> .el-dialog__title {
+  font-size: 14px !important;
+  color: #fff !important;
+}
+
+.add_student >>> .el-dialog__headerbtn {
+  font-size: 20px !important;
+}
+
+.add_student >>> .el-form-item__label {
+  margin-left: 65px;
+}
+
+.add_student >>> .el-form-item {
+  display: flex;
+}
+
+.add_student >>> .el-form-item__content {
+  margin: 0 !important;
+}
+
+.add_input {
+  width: 365px;
+}
+
+.add_student >>> .el-dialog__footer {
+  text-align: center !important;
+}
+.header-title {
+  display: flex;
+}
+
+.logoImg {
+  width: 30px;
+}
+
+.logoImg > img {
+  width: 100%;
+  height: 100%;
+}
+
+.title_add_student {
+  margin: 0 auto;
+  color: #fff;
+}
+.people {
+  border: 1px solid rgb(229 229 229);
+  height: 495px;
+  border-radius: 5px;
+  width: 100%;
+  overflow: auto;
+}
+
+.people_top {
+  display: flex;
+  width: 100%;
+  /* justify-content: space-between; */
+  /* align-items: center; */
+  flex-direction: column;
+  padding: 10px 25px 0;
+  box-sizing: border-box;
+}
+
+.people_top_right {
+  height: 40px;
+  margin-bottom: 10px;
+}
+
+.people_search {
+  display: flex;
+  position: relative;
+}
+
+.people_search>>>.el-input__inner {
+  /* height: 25px; */
+  width: 95%;
+}
+
+.search_img {
+  width: 20px;
+  height: 20px;
+  position: absolute;
+  right: 30px;
+  top: 50%;
+  transform: translateY(-50%);
+}
+
+.search_img>img {
+  width: 100%;
+  height: 100%;
+}
+
+.people_name {
+  display: flex;
+  justify-content: flex-start;
+  padding: 10px 0 0 25px;
+  flex-direction: column;
+  flex-wrap: nowrap;
+  height: calc(100% - 140px);
+  overflow-y: auto;
+  overflow-x: hidden;
+  flex-direction: column;
+}
+
+.people_name>>>.el-checkbox {
+  width: 100%;
+  display: flex;
+  align-items: center;
+  margin-bottom: 10px;
+}
+
+.people_name>>>.el-checkbox__label {
+  text-overflow: ellipsis;
+  overflow: hidden;
+  width: 100%;
+}
+
+.addNewPP>>>.el-dialog__body {
+  padding: 5px 20px;
+}
+
+.t_j_box {
+  display: flex;
+}
+
+.t_j_box span:nth-child(1) {
+  width: 50%;
+  overflow: hidden;
+  margin-right: 10px;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+}
+
+.t_j_box span:nth-child(2) {
+  width: 50%;
+  overflow: hidden;
+  margin-right: 10px;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+}
+
+</style>

+ 381 - 0
src/components/pages/PersonnelManagement/index.vue

@@ -0,0 +1,381 @@
+<template>
+  <div class="manageper" style="background-color: #FAFAFA;min-height: 100%;">
+    <div class="topTit">
+      <div style="font-size: 22px;font-weight: bold;">
+        <span>学生管理</span>
+        <!-- <span v-if="isCollapse == 0">学生管理</span>
+        <span v-if="isCollapse == 1">班级管理</span>
+        <span v-if="isCollapse == 2">年级管理</span> -->
+      </div>
+      <div></div>
+    </div>
+    <div class="manageper" style="padding: 0 12%;flex: 1;overflow: auto;">
+      <div class="midcon">
+        <el-button size="small" @click="addviewData(0)" type="primary"
+          >添加学生</el-button
+        >
+        <el-button size="small" @click="addviewData(1)" type="primary"
+          >添加班级</el-button
+        >
+        <el-button size="small" @click="addviewData(2)" type="primary"
+          >添加年级</el-button
+        >
+      </div>
+      <div class="viewCut" style="justify-content: space-between;">
+        <div class="viewCut">
+          <el-radio-group @change="cutList()" v-model="isCollapse">
+            <el-radio-button :label="0">学生视图</el-radio-button>
+            <el-radio-button :label="1">班级视图</el-radio-button>
+            <el-radio-button :label="2">年级视图</el-radio-button>
+          </el-radio-group>
+          <el-input
+            @blur="getinpData()"
+            style="width: 200px;"
+            placeholder="搜索学生、班级或年级…"
+            v-model.trim="searhValue"
+          >
+          </el-input>
+          <div style="width: 120px;">
+            <el-select
+              v-if="isCollapse == 0"
+              style="width: 120px;"
+              v-model="cid"
+              clearable
+              :disabled="classLcid ? true : false"
+              @change="changeCid"
+              placeholder="请选择"
+            >
+              <el-option label="显示全部" value=""> </el-option>
+              <el-option
+                v-for="item in classJuri"
+                :key="item.id"
+                :label="item.name"
+                :value="item.id"
+              >
+              </el-option>
+            </el-select>
+          </div>
+        </div>
+        <div class="viewCut" v-if="classLcid">
+          <span
+            >班级:{{ classJuri.filter(e => e.id == classLcid)[0].name }}</span
+          >
+          <el-button size="small" @click="addclassStu" type="primary"
+            >添加学生</el-button
+          >
+          <el-button
+            size="small"
+            type="primary"
+            @click="(classLcid = ''), getData()"
+            >返回</el-button
+          >
+        </div>
+
+        <div class="viewCut" v-if="gidL">
+          <span>年级:{{ gradeJuri.filter(e => e.id == gidL)[0].name }}</span>
+          <el-button size="small" @click="addgid" type="primary"
+            >添加年级</el-button
+          >
+          <el-button size="small" type="primary" @click="(gidL = ''), getData()"
+            >返回</el-button
+          >
+        </div>
+      </div>
+
+      <student
+        ref="studentref"
+        v-if="isCollapse == 0 || classLcid"
+        :userid="userid"
+        :oid="oid"
+        :org="org"
+        :role="role"
+        :cid="cid"
+        :cidL="classLcid"
+        :searhValue="searhValue"
+      />
+
+      <classL
+        ref="classLref"
+        v-else-if="isCollapse == 1 || gidL"
+        :userid="userid"
+        :oid="oid"
+        :org="org"
+        :role="role"
+        :gidL="gidL"
+        :searhValue="searhValue"
+        @lookstudentL="lookstudentL"
+      />
+
+      <grade
+        ref="graderef"
+        v-else
+        :userid="userid"
+        :oid="oid"
+        :org="org"
+        :role="role"
+        :searhValue="searhValue"
+        @lookgradeL="lookgradeL"
+      />
+    </div>
+  </div>
+</template>
+
+<script>
+import pinyin from "../../../../node_modules/js-pinyin/index";
+import student from "./components/student.vue";
+import classL from "./components/classL";
+import grade from "./components/grade.vue";
+import Class from "../studentManage/class.vue";
+
+export default {
+  components: {
+    student,
+    classL,
+    grade,
+    Class
+  },
+  data() {
+    return {
+      searhValue: "", //搜索框
+      isCollapse: 0, //展示视图
+      cid: "", //班级id
+      classLcid: "", //班级id防止与使用cid时冲突
+      gidL: "", //年级视图点击查看班级存储的数据
+      userid: this.$route.query.userid,
+      oid: this.$route.query.oid,
+      org: this.$route.query.org,
+      role: this.$route.query.role,
+      classJuri: [], //班级列表
+      gradeJuri: "", //年级列表
+      tableData: [] //学生视图数据
+    };
+  },
+  methods: {
+    // 学生视图函数调用
+      // 筛选年级学生
+      changeCid() {
+        // console.log("cid", this.cid);
+        this.$nextTick(() => {
+          this.$refs.studentref.getStudent();
+        });
+      },
+      // 添加学生到班级
+      addclassStu() {
+        this.$refs.studentref.diaAdd();
+      },
+
+    // 班级视图函数调用
+      // 年级添加班级
+      addgid() {
+        this.$refs.classLref.addStudent();
+      },
+      // 查看班级学生
+      lookstudentL(val) {
+        this.classLcid = val;
+        this.cid = val;
+        // this.$nextTick(() => {
+        this.getData();
+        // });
+      },
+
+    //年级视图函数调用
+      // 查看年级班级
+      lookgradeL(val) {
+        this.gidL = val;
+        console.log('this.gidL',this.gidL);
+        
+        this.$nextTick(() => {
+          this.$refs.classLref.getClass();
+        });
+      },
+
+    //获取年级列表
+    getgradeData() {
+      let params = {
+        oid: this.oid
+      };
+      this.ajax
+        .get(this.$store.state.api + "selectGrageBySchool", params)
+        .then(res => {
+          this.gradeJuri = res.data[0];
+        })
+        .catch(err => {
+          console.error(err);
+        });
+    },
+
+    //获取班级列表
+    getClassdata() {
+      let params = {
+        oid: this.oid
+      };
+      this.ajax
+        .get(this.$store.state.api + "selectClassBySchool", params)
+        .then(res => {
+          this.classJuri = res.data[0];
+        })
+        .catch(err => {
+          console.error(err);
+        });
+    },
+
+    // 添加学生,班级,年级弹框
+    addviewData(val) {
+      this.isCollapse = val;
+      this.gidL = "";
+      this.classLcid = "";
+
+      if (this.isCollapse == 0) {
+        this.$nextTick(() => {
+          this.$refs.studentref.getStudent();
+
+          this.$refs.studentref.addStudent();
+        });
+      } else if (this.isCollapse == 1) {
+        this.$nextTick(() => {
+          this.$refs.classLref.dialogVisible = true;
+          this.$refs.classLref.getClass();
+        });
+      } else {
+        this.$nextTick(() => {
+          this.$refs.graderef.getClass();
+          this.$refs.graderef.dialogVisible = true;
+        });
+      }
+    },
+
+    // 搜索框查询数据
+    getinpData() {
+      // if (!this.searhValue) return;
+      if (this.isCollapse == 0 || this.classLcid) {
+        this.$nextTick(() => {
+          this.$refs.studentref.getStudent();
+        });
+      } else if (this.isCollapse == 1 || this.gidL) {
+        this.$nextTick(() => {
+          this.$refs.classLref.getClass();
+        });
+      } else {
+        this.$nextTick(() => {
+          this.$refs.graderef.getClass();
+        });
+      }
+    },
+    
+    // 搜索框与监听调用获取视图数据
+    getData() {
+      if (this.isCollapse == 0 || this.classLcid) {
+        this.$nextTick(() => {
+          this.$refs.studentref.getStudent();
+        });
+      } else if (this.isCollapse == 1) {
+        this.$nextTick(() => {
+          this.$refs.classLref.getClass();
+        });
+      } else {
+        this.$nextTick(() => {
+          this.$refs.graderef.getClass();
+        });
+      }
+    },
+    // 切换列表
+    cutList() {
+      this.searhValue = "";
+      this.classLcid = "";
+      this.gidL = "";
+      this.cid = "";
+      if (this.isCollapse == 0) {
+        this.$nextTick(() => {
+          this.$refs.studentref.getStudent();
+        });
+      } else if (this.isCollapse == 1) {
+        this.$nextTick(() => {
+          this.$refs.classLref.getClass();
+        });
+      } else {
+        this.$nextTick(() => {
+          this.$refs.graderef.getClass();
+        });
+      }
+    }
+  },
+  mounted() {
+    this.getData();
+    this.getClassdata();
+    this.getgradeData();
+  }
+};
+</script>
+
+<style scoped>
+.manageper {
+  display: flex;
+  flex-direction: column;
+  gap: 20px;
+  box-sizing: border-box;
+}
+.topTit {
+  display: flex;
+  width: 100%;
+  background: #fff;
+  justify-content: space-between;
+  box-sizing: border-box;
+  padding: 0 10%;
+  align-items: center;
+  height: 85px;
+}
+.midcon {
+  height: 85px;
+  display: flex;
+  align-items: center;
+  background: #fff;
+  border-radius: 10px;
+  padding: 0 20px;
+  border: 1px#e7e7e7 solid;
+}
+.viewCut {
+  height: 70px;
+  display: flex;
+  gap: 15px;
+  align-items: center;
+  border-bottom: 1px #e7e7e7 solid;
+}
+.baseFlex {
+  display: flex;
+  align-items: center;
+  gap: 10px;
+  height: 100%;
+}
+.baseFlex > img {
+  /* width: 50px; */
+  height: 100%;
+  object-fit: cover;
+}
+.baseFlex > span {
+  color: #6b6b6b;
+  font-size: 14px;
+  cursor: pointer;
+}
+.fontlist {
+  border-radius: 10px;
+  overflow: auto;
+  background: #fff;
+  flex: 1;
+  min-height: 250px;
+}
+.listA {
+  display: flex;
+  justify-content: space-between;
+  border-bottom: 1px #e7e7e7 solid;
+  height: 70px;
+  align-items: center;
+  box-sizing: border-box;
+  padding: 15px;
+  /* background: #fff; */
+}
+.fontPage {
+  height: 70px;
+  display: flex;
+  justify-content: end;
+}
+</style>

+ 488 - 409
src/components/pages/classroomObservation/components/chatArea.vue

@@ -1637,25 +1637,14 @@ ${JSON.stringify(_list)}
       try {
         let iiframe = this.$refs["iiframe"];
         let _this = this;
-        this.wavGetTextLoading = true;
-        iiframe.contentWindow.window.document.getElementById(
-          "languageOptions"
-        ).selectedIndex = this.languageRadio;
+        // iiframe.contentWindow.window.document.getElementById(
+        //   "languageOptions"
+        // ).selectedIndex = this.languageRadio;
         _this.transcriptionData.content = "";
-        iiframe.contentWindow.window.onRecognizedResult = function(e) {
-          if (flag) {
-            // 这里上传文件
-            // _this.uploadWavFile(audioFile);
-            _this.controlsStatus = 2;
-            _this.showIndexPage = false;
-            _this.pageStatus = 2;
-            _this.editorBarData.type = "0";
-            flag = false;
-            _this.uploadFileLoading = false;
-            _this.transcriptionData.content = "";
-            _this.editorBarData.content = "";
-            textList = [];
-          }
+
+        this.showGetTextLoading = true;
+        this.wavGetTextLoading = true;
+        let _timer = setInterval(() => {
           if (_this.wavGetTextProgress <= 70) {
             _TimeProgress = 6000; //六秒
           } else if (_this.wavGetTextProgress <= 80) {
@@ -1674,396 +1663,485 @@ ${JSON.stringify(_list)}
           _this.wavGetTextProgress = ((_totalTime / _duration) * 100).toFixed(
             0
           );
-          _this.wavGetTextLoading = true;
-          _this.showGetTextLoading = true;
-          let privText = e.privText;
-          let privSpeakerId = e.privSpeakerId;
-          let _copyPrivSpeakerId = privSpeakerId;
-          let privDuration = e.privDuration;
-          let privOffset = e.privOffset;
-          console.log("👉转译对象👉", e);
-          console.log("👉转译结果👉", privText);
-          if (!privText || !privSpeakerId || privSpeakerId == "Unknown") {
-            return;
-          }
-
-          if (_roleList[privSpeakerId]) {
-            privSpeakerId = _roleList[privSpeakerId];
-          } else {
-            _getRoleList.push({
-              role: privSpeakerId,
-              content: privText
-            });
-          }
-
-          _behavioralCodingList.push({
-            index: textList.length,
-            role: privSpeakerId,
-            content: privText,
-            code: ""
-          });
-
-          console.log("roleList", _roleList);
-          console.log("getRoleList", _getRoleList);
-          console.log("behavioralCodingList", _behavioralCodingList);
-          if (_getRoleList.length >= 10 && !_getRoleLoading) {
-            try {
-              let params = {
-                inputs: {
-                  options: "老师,学生",
-                  rows: JSON.stringify(
-                    _getRoleList.map(i => {
-                      return { content: i.content, role: i.role };
-                    })
-                  )
-                },
-                response_mode: "blocking",
-                user: _this.userId
-              };
-              _getRoleLoading = true;
-              _this
-                .getWavRoleList(params)
-                .then(res => {
-                  let _runData = res.data.data;
-                  let _runResult = _runData.outputs.result;
-                  let _numRole = [];
-
-                  _runResult.forEach((txt, index) => {
-                    let _oldRole = _getRoleList[index].role;
-                    if (_numRole.map(i => i.role).includes(_oldRole)) {
-                      let _findIndex = _numRole.findIndex(
-                        i => i.role == _oldRole
-                      );
-                      if (txt == "学生") {
-                        _numRole[_findIndex].s += 1;
-                      } else if (txt == "老师") {
-                        _numRole[_findIndex].t += 1;
-                      }
-                    } else {
-                      if (txt == "学生") {
-                        _numRole.push({ role: _oldRole, t: 0, s: 1 });
-                      } else if (txt == "老师") {
-                        _numRole.push({ role: _oldRole, t: 1, s: 0 });
-                      }
-                    }
-                  });
-
-                  //根据数量判断是老师还是学生
-                  _numRole.forEach(i => {
-                    if (i.t > i.s) {
-                      _roleList[i.role] = "老师";
-                    } else if (i.t < i.s) {
-                      _roleList[i.role] = "学生";
-                    }
-                  });
-                  //已经有的role
-                  let roleKeys = Object.keys(_roleList);
-
-                  textList.forEach(i => {
-                    if (roleKeys.includes(i.role)) {
-                      i.role = _roleList[i.role];
-                    }
-                  });
-
-                  //同时更新
-                  _behavioralCodingList.forEach(i=>{
-                    if(roleKeys.includes(i.role)){
-                      i.role = _roleList[i.role]
-                    }
-                  })
-
-                  _getRoleList = _getRoleList.filter(
-                    i => !roleKeys.includes(i.role)
-                  );
-                  _getRoleLoading = false;
-                })
-                .catch(err => {
-                  console.log("获取说话人编码失败", err);
-                  _getRoleLoading = false;
-                });
-            } catch (error) {
-              console.log("说话人编码失败", error);
-            }
-          }
-          console.log("behavioralCodingListIf", (_behavioralCodingList.filter(
-              i => (i.role.indexOf("Guest") == -1 && i.code == "")
-            )));
-          if (
-            _behavioralCodingList.filter(
-              i => i.role.indexOf("Guest") === -1 && i.code === ""
-            ).length >= 10 &&
-            !_getBehavioralCodingLoading
-          ) {
-            try {
-              const _behavioralCodingListTemp = _behavioralCodingList
-                .filter(i => i.role.indexOf("Guest") == -1 && i.code == "")
-                .slice(0, 10);
-
-              console.log("behavioralCodingListTemp", _behavioralCodingListTemp);
-              const params = {
-                inputs: {
-                  rows: JSON.stringify(
-                    _behavioralCodingListTemp.map(i => ({
-                      content: i.content,
-                      role: i.role
-                    }))
-                  ),
-                  options: "老师讲课,老师提问或点名,老师板书或操作,老师评价或反馈,老师其他,学生发言,学生小组活动,学生自主学习,学生汇报分享,学生其他",
-                  attention: "- 先根据说话人角色判断,再在对应角色的选项中选择选项\n- 如果没有合适的选项,默认使用`老师其他`或者`学生其他`"
-                },
-                response_mode: "blocking",
-                user: _this.userId
-              };
-
-              _getBehavioralCodingLoading = true;
-              _this
-                .getBehavioralCoding(params)
-                .then(res => {
-                  const _runResult = res.data.data.outputs.result;
-                  _behavioralCodingListTemp.forEach((item, index) => {
-                    const foundItem = _behavioralCodingList.find(i => i.index === item.index);
-                    if (foundItem) {
-                      foundItem.code = _runResult[index];
-                      textList[item.index].code = foundItem.code;
-                    }
-                  });
-                  _getBehavioralCodingLoading = false;
-                })
-                .catch(err => {
-                  console.log("获取行为编码错误", err);
-                  _getBehavioralCodingLoading = false;
-                });
-            } catch (error) {
-              console.log("获取行为编码错误", error);
-              _getBehavioralCodingLoading = false;
-            }
-          }
-
-          _endTime = (privOffset + privDuration) / 10000000;
-          textList.push({
-            value: privText,
-            startTime: _this.updateRecordedTime({ duration: _startTime }),
-            endTime: _this.updateRecordedTime({ duration: _endTime }),
-            time: _this.updateRecordedTime({ duration: _endTime - _startTime }),
-            role: privSpeakerId,
-            code: ""
-          });
-
-          _startTime = _endTime;
-
-          _this.transcriptionData.content += _copyPrivSpeakerId + ":" + privText +"\n";
-
-          // console.log(textList);
-
-          let _result = `
-				<table
-						border="0"
-						width="100%"
-						cellpadding="0"
-						cellspacing="0"
-						style="text-align: center"
-					>
-						<tbody>
-							<tr>
-								<th>序号</th>
-								<th>开始时间</th>
-								<th>结束时间</th>
-								<th>发言内容</th>
-								<th>时长</th>
-								<th>说话人身份</th>
-								<th>行为编码</th>
-						</tr>
-				`;
-          textList.forEach((item, index) => {
-            _result += `<tr>
-							<td>${index + 1}</td>
-							<td>${item.startTime}</td>
-							<td>${item.endTime}</td>
-							<td>${item.value}</td>
-							<td>${item.time}</td>
-							<td>${item.role}</td>
-							<td>${item.code}</td>
-						</tr>`;
-          });
-          _result += `
-				<tr>
-							<td></td>
-							<td></td>
-							<td></td>
-							<td></td>
-							<td></td>
-							<td></td>
-							<td></td>
-						</tr>
-					</tbody>
-				</table>`;
-          _this.editorBarData.content = _result;
-          this.$forceUpdate();
-          // _this.editorBarData.content += privText;
-        };
-
-        iiframe.contentWindow.onSessionStopped = async function(e) {
-          let _flag = false;
-          if (_getRoleList.length > 0) {
-            _flag = true;
-            await _this
-              .getWavRoleList({
-                inputs: {
-                  options: "老师,学生",
-                  rows: JSON.stringify(
-                    _getRoleList.map(i => {
-                      return { content: i.content, role: i.role };
-                    })
-                  )
-                },
-                response_mode: "blocking",
-                user: _this.userId
-              })
-              .then(res => {
-                let _runData = res.data.data;
-                let _runResult = _runData.outputs.result;
-                let _numRole = [];
-
-                _runResult.forEach((txt, index) => {
-                  let _oldRole = _getRoleList[index].role;
-                  if (_numRole.map(i => i.role).includes(_oldRole)) {
-                    let _findIndex = _numRole.findIndex(
-                      i => i.role == _oldRole
-                    );
-                    if (txt == "学生") {
-                      _numRole[_findIndex].s += 1;
-                    } else if (txt == "老师") {
-                      _numRole[_findIndex].t += 1;
-                    }
-                  } else {
-                    if (txt == "学生") {
-                      _numRole.push({ role: _oldRole, t: 0, s: 1 });
-                    } else if (txt == "老师") {
-                      _numRole.push({ role: _oldRole, t: 1, s: 0 });
-                    }
-                  }
-                });
-
-                //根据数量判断是老师还是学生
-                _numRole.forEach(i => {
-                  if (i.t > i.s) {
-                    _roleList[i.role] = "老师";
-                  } else if (i.t < i.s) {
-                    _roleList[i.role] = "学生";
-                  }
-                });
-                //已经有的role
-                let roleKeys = Object.keys(_roleList);
-
-                textList.forEach(i => {
-                  if (roleKeys.includes(i.role)) {
-                    i.role = _roleList[i.role];
-                  }
-                });
+        }, 1000);
+        this.transcriptionData.content = "";
+        this.editorBarData.content = "";
 
-                _getRoleList = _getRoleList.filter(
-                  i => !roleKeys.includes(i.role)
-                );
-                _getRoleLoading = false;
-              })
-              .catch(err => {
-                console.log("最后的获取说话人身份失败", err);
+        iiframe.contentWindow.window
+          .doConversationTranscriber({ files: [_file] })
+          .then(res => {
+            console.log("转录内容", res);
+
+            let _data = res.phrases;
+
+            _data.forEach(i => {
+              let _privSpeakerId = `Guest-${i.speaker}`;
+              let _privText = i.text;
+              let privOffset = i.offsetMilliseconds;
+              let privDuration = i.durationMilliseconds;
+
+              _endTime = (privOffset + privDuration) / 1000;
+              textList.push({
+                value: _privText,
+                startTime: this.updateRecordedTime({ duration: _startTime }),
+                endTime: this.updateRecordedTime({ duration: _endTime }),
+                time: this.updateRecordedTime({
+                  duration: _endTime - _startTime
+                }),
+                role: _privSpeakerId,
+                code: ""
               });
-          }
-          if (
-            _behavioralCodingList.some(
-              i => i.role.indexOf("Guest") === -1 && i.code === ""
-            )
-          ) {
-            _flag = true;
-            const _behavioralCodingListTemp = _behavioralCodingList
-                .filter(i => i.role.indexOf("Guest") == -1 && i.code == "")
-              const params = {
-                inputs: {
-                  rows: JSON.stringify(
-                    _behavioralCodingListTemp.map(i => ({
-                      content: i.content,
-                      role: i.role
-                    }))
-                  ),
-                  options: "老师讲课,老师提问或点名,老师板书或操作,老师评价或反馈,老师其他,学生发言,学生小组活动,学生自主学习,学生汇报分享,学生其他",
-                  attention: "- 先根据说话人角色判断,再在对应角色的选项中选择选项\n- 如果没有合适的选项,默认使用`老师其他`或者`学生其他`"
-                },
-                response_mode: "blocking",
-                user: _this.userId
-              };
-              await _this
-                .getBehavioralCoding(params)
-                .then(res => {
-                  const _runResult = res.data.data.outputs.result;
-                  _behavioralCodingListTemp.forEach((item, index) => {
-                    const foundItem = _behavioralCodingList.find(i => i.index === item.index);
-                    if (foundItem) {
-                      foundItem.code = _runResult[index];
-                      textList[item.index].code = foundItem.code;
-                    }
-                  });
-                })
-                .catch(err => {
-                  console.log("获取行为编码错误", err);
-                });
-          }
-
-          if (_flag) {
-            let _result = `
-				<table
-						border="0"
-						width="100%"
-						cellpadding="0"
-						cellspacing="0"
-						style="text-align: center"
-					>
-						<tbody>
-							<tr>
-								<th>序号</th>
-								<th>开始时间</th>
-								<th>结束时间</th>
-								<th>发言内容</th>
-								<th>时长</th>
-								<th>说话人身份</th>
-								<th>行为编码</th>
-						</tr>
-				`;
+              _startTime = _endTime;
+              this.transcriptionData.content +=
+                _privSpeakerId + ":" + _privText + "\n";
+            });
+            let _result = `<table border="0" width="100%" cellpadding="0" cellspacing="0" style="text-align: center"><tbody><tr><th>序号</th><th>开始时间</th><th>结束时间</th><th>发言内容</th><th>时长</th><th>说话人身份</th><th>行为编码</th></tr>`;
             textList.forEach((item, index) => {
-              _result += `<tr>
-							<td>${index + 1}</td>
-							<td>${item.startTime}</td>
-							<td>${item.endTime}</td>
-							<td>${item.value}</td>
-							<td>${item.time}</td>
-							<td>${item.role}</td>
-							<td>${item.code}</td>
-						</tr>`;
+              _result += `<tr><td>${index + 1}</td><td>${item.startTime}</td><td>${item.endTime}</td><td>${item.value}</td><td>${item.time}</td><td>${item.role}</td><td>${item.code}</td></tr>`;
             });
-            _result += `
-				<tr>
-							<td></td>
-							<td></td>
-							<td></td>
-							<td></td>
-							<td></td>
-							<td></td>
-							<td></td>
-						</tr>
-					</tbody>
-				</table>`;
-            _this.editorBarData.content = _result;
-          }
-          _this.wavGetTextProgress = 100;
-          if (_this.wavFileGetTextLoading) _this.$message.success("转译完成");
-          _this.showGetTextLoading = false;
-          _this.wavGetTextLoading = false;
-          _this.saveEditorBar();
-        };
-
-        iiframe.contentWindow.ConversationTranscriber({
-          files: [_file]
-        });
+            _result += `</tbody></table>`;
+            this.editorBarData.content = _result;
+            this.$forceUpdate();
+            this.wavGetTextProgress = 100;
+            if (this.wavFileGetTextLoading) this.$message.success("转译完成");
+            // _this.editorBarData.content += privText;
+
+            this.showGetTextLoading = false;
+            this.wavGetTextLoading = false;
+            this.uploadFileLoading = false;
+            // this.uploadWavFile(audioFile);
+            if (_timer) {
+              clearInterval(_timer);
+            }
+            this.saveEditorBar();
+          })
+          .catch(err => {
+            console.log(err)
+            this.wavGetTextLoading = false;
+        this.showGetTextLoading = false;
+          });
+        //iiframe.contentWindow.window.onRecognizedResult = function(e) {
+        //  if (flag) {
+        //    // 这里上传文件
+        //    // _this.uploadWavFile(audioFile);
+        //    _this.controlsStatus = 2;
+        //    _this.showIndexPage = false;
+        //    _this.pageStatus = 2;
+        //    _this.editorBarData.type = "0";
+        //    flag = false;
+        //    _this.uploadFileLoading = false;
+        //    _this.transcriptionData.content = "";
+        //    _this.editorBarData.content = "";
+        //    textList = [];
+        //  }
+        //  if (_this.wavGetTextProgress <= 70) {
+        //    _TimeProgress = 6000; //六秒
+        //  } else if (_this.wavGetTextProgress <= 80) {
+        //    _TimeProgress = 4000; //改为三秒
+        //  } else if (_this.wavGetTextProgress <= 90) {
+        //    _TimeProgress = 2000; //改为一秒
+        //  } else if (_this.wavGetTextProgress < 95) {
+        //    _TimeProgress = 1000; //改为0.5秒
+        //  } else if (_this.wavGetTextProgress < 99) {
+        //    _TimeProgress = 500; //改为0.1秒
+        //  } else {
+        //    _TimeProgress = 0; //改为0秒不动
+        //  }
+        //
+        //  _totalTime += _TimeProgress;
+        //  _this.wavGetTextProgress = ((_totalTime / _duration) * 100).toFixed(
+        //    0
+        //  );
+        //  _this.wavGetTextLoading = true;
+        //  _this.showGetTextLoading = true;
+        //  let privText = e.privText;
+        //  let privSpeakerId = e.privSpeakerId;
+        //  let _copyPrivSpeakerId = privSpeakerId;
+        //  let privDuration = e.privDuration;
+        //  let privOffset = e.privOffset;
+        //  console.log("👉转译对象👉", e);
+        //  console.log("👉转译结果👉", privText);
+        //  if (!privText || !privSpeakerId || privSpeakerId == "Unknown") {
+        //    return;
+        //  }
+        //
+        //  if (_roleList[privSpeakerId]) {
+        //    privSpeakerId = _roleList[privSpeakerId];
+        //  } else {
+        //    _getRoleList.push({
+        //      role: privSpeakerId,
+        //      content: privText
+        //    });
+        //  }
+        //
+        //  _behavioralCodingList.push({
+        //    index: textList.length,
+        //    role: privSpeakerId,
+        //    content: privText,
+        //    code: ""
+        //  });
+        //
+        //  console.log("roleList", _roleList);
+        //  console.log("getRoleList", _getRoleList);
+        //  console.log("behavioralCodingList", _behavioralCodingList);
+        //  if (_getRoleList.length >= 10 && !_getRoleLoading) {
+        //    try {
+        //      let params = {
+        //        inputs: {
+        //          options: "老师,学生",
+        //          rows: JSON.stringify(
+        //            _getRoleList.map(i => {
+        //              return { content: i.content, role: i.role };
+        //            })
+        //          )
+        //        },
+        //        response_mode: "blocking",
+        //        user: _this.userId
+        //      };
+        //      _getRoleLoading = true;
+        //      _this
+        //        .getWavRoleList(params)
+        //        .then(res => {
+        //          let _runData = res.data.data;
+        //          let _runResult = _runData.outputs.result;
+        //          let _numRole = [];
+        //
+        //          _runResult.forEach((txt, index) => {
+        //            let _oldRole = _getRoleList[index].role;
+        //            if (_numRole.map(i => i.role).includes(_oldRole)) {
+        //              let _findIndex = _numRole.findIndex(
+        //                i => i.role == _oldRole
+        //              );
+        //              if (txt == "学生") {
+        //                _numRole[_findIndex].s += 1;
+        //              } else if (txt == "老师") {
+        //                _numRole[_findIndex].t += 1;
+        //              }
+        //            } else {
+        //              if (txt == "学生") {
+        //                _numRole.push({ role: _oldRole, t: 0, s: 1 });
+        //              } else if (txt == "老师") {
+        //                _numRole.push({ role: _oldRole, t: 1, s: 0 });
+        //              }
+        //            }
+        //          });
+        //
+        //          //根据数量判断是老师还是学生
+        //          _numRole.forEach(i => {
+        //            if (i.t > i.s) {
+        //              _roleList[i.role] = "老师";
+        //            } else if (i.t < i.s) {
+        //              _roleList[i.role] = "学生";
+        //            }
+        //          });
+        //          //已经有的role
+        //          let roleKeys = Object.keys(_roleList);
+        //
+        //          textList.forEach(i => {
+        //            if (roleKeys.includes(i.role)) {
+        //              i.role = _roleList[i.role];
+        //            }
+        //          });
+        //
+        //          //同时更新
+        //          _behavioralCodingList.forEach(i=>{
+        //            if(roleKeys.includes(i.role)){
+        //              i.role = _roleList[i.role]
+        //            }
+        //          })
+        //
+        //          _getRoleList = _getRoleList.filter(
+        //            i => !roleKeys.includes(i.role)
+        //          );
+        //          _getRoleLoading = false;
+        //        })
+        //        .catch(err => {
+        //          console.log("获取说话人编码失败", err);
+        //          _getRoleLoading = false;
+        //        });
+        //    } catch (error) {
+        //      console.log("说话人编码失败", error);
+        //    }
+        //  }
+        //  console.log("behavioralCodingListIf", (_behavioralCodingList.filter(
+        //      i => (i.role.indexOf("Guest") == -1 && i.code == "")
+        //    )));
+        //  if (
+        //    _behavioralCodingList.filter(
+        //      i => i.role.indexOf("Guest") === -1 && i.code === ""
+        //    ).length >= 10 &&
+        //    !_getBehavioralCodingLoading
+        //  ) {
+        //    try {
+        //      const _behavioralCodingListTemp = _behavioralCodingList
+        //        .filter(i => i.role.indexOf("Guest") == -1 && i.code == "")
+        //        .slice(0, 10);
+        //
+        //      console.log("behavioralCodingListTemp", _behavioralCodingListTemp);
+        //      const params = {
+        //        inputs: {
+        //          rows: JSON.stringify(
+        //            _behavioralCodingListTemp.map(i => ({
+        //              content: i.content,
+        //              role: i.role
+        //            }))
+        //          ),
+        //          options: "老师讲课,老师提问或点名,老师板书或操作,老师评价或反馈,老师其他,学生发言,学生小组活动,学生自主学习,学生汇报分享,学生其他",
+        //          attention: "- 先根据说话人角色判断,再在对应角色的选项中选择选项\n- 如果没有合适的选项,默认使用`老师其他`或者`学生其他`"
+        //        },
+        //        response_mode: "blocking",
+        //        user: _this.userId
+        //      };
+        //
+        //      _getBehavioralCodingLoading = true;
+        //      _this
+        //        .getBehavioralCoding(params)
+        //        .then(res => {
+        //          const _runResult = res.data.data.outputs.result;
+        //          _behavioralCodingListTemp.forEach((item, index) => {
+        //            const foundItem = _behavioralCodingList.find(i => i.index === item.index);
+        //            if (foundItem) {
+        //              foundItem.code = _runResult[index];
+        //              textList[item.index].code = foundItem.code;
+        //            }
+        //          });
+        //          _getBehavioralCodingLoading = false;
+        //        })
+        //        .catch(err => {
+        //          console.log("获取行为编码错误", err);
+        //          _getBehavioralCodingLoading = false;
+        //        });
+        //    } catch (error) {
+        //      console.log("获取行为编码错误", error);
+        //      _getBehavioralCodingLoading = false;
+        //    }
+        //  }
+        //
+        //  _endTime = (privOffset + privDuration) / 10000000;
+        //  textList.push({
+        //    value: privText,
+        //    startTime: _this.updateRecordedTime({ duration: _startTime }),
+        //    endTime: _this.updateRecordedTime({ duration: _endTime }),
+        //    time: _this.updateRecordedTime({ duration: _endTime - _startTime }),
+        //    role: privSpeakerId,
+        //    code: ""
+        //  });
+        //
+        //  _startTime = _endTime;
+        //
+        //  _this.transcriptionData.content += _copyPrivSpeakerId + ":" + privText +"\n";
+        //
+        //  // console.log(textList);
+        //
+        //  let _result = `
+        //<table
+        //		border="0"
+        //		width="100%"
+        //		cellpadding="0"
+        //		cellspacing="0"
+        //		style="text-align: center"
+        //	>
+        //		<tbody>
+        //			<tr>
+        //				<th>序号</th>
+        //				<th>开始时间</th>
+        //				<th>结束时间</th>
+        //				<th>发言内容</th>
+        //				<th>时长</th>
+        //				<th>说话人身份</th>
+        //				<th>行为编码</th>
+        //		</tr>
+        //`;
+        //  textList.forEach((item, index) => {
+        //    _result += `<tr>
+        //			<td>${index + 1}</td>
+        //			<td>${item.startTime}</td>
+        //			<td>${item.endTime}</td>
+        //			<td>${item.value}</td>
+        //			<td>${item.time}</td>
+        //			<td>${item.role}</td>
+        //			<td>${item.code}</td>
+        //		</tr>`;
+        //  });
+        //  _result += `
+        //<tr>
+        //			<td></td>
+        //			<td></td>
+        //			<td></td>
+        //			<td></td>
+        //			<td></td>
+        //			<td></td>
+        //			<td></td>
+        //		</tr>
+        //	</tbody>
+        //</table>`;
+        //  _this.editorBarData.content = _result;
+        //  this.$forceUpdate();
+        //  // _this.editorBarData.content += privText;
+        //};
+        //
+        //iiframe.contentWindow.onSessionStopped = async function(e) {
+        //  let _flag = false;
+        //  if (_getRoleList.length > 0) {
+        //    _flag = true;
+        //    await _this
+        //      .getWavRoleList({
+        //        inputs: {
+        //          options: "老师,学生",
+        //          rows: JSON.stringify(
+        //            _getRoleList.map(i => {
+        //              return { content: i.content, role: i.role };
+        //            })
+        //          )
+        //        },
+        //        response_mode: "blocking",
+        //        user: _this.userId
+        //      })
+        //      .then(res => {
+        //        let _runData = res.data.data;
+        //        let _runResult = _runData.outputs.result;
+        //        let _numRole = [];
+        //
+        //        _runResult.forEach((txt, index) => {
+        //          let _oldRole = _getRoleList[index].role;
+        //          if (_numRole.map(i => i.role).includes(_oldRole)) {
+        //            let _findIndex = _numRole.findIndex(
+        //              i => i.role == _oldRole
+        //            );
+        //            if (txt == "学生") {
+        //              _numRole[_findIndex].s += 1;
+        //            } else if (txt == "老师") {
+        //              _numRole[_findIndex].t += 1;
+        //            }
+        //          } else {
+        //            if (txt == "学生") {
+        //              _numRole.push({ role: _oldRole, t: 0, s: 1 });
+        //            } else if (txt == "老师") {
+        //              _numRole.push({ role: _oldRole, t: 1, s: 0 });
+        //            }
+        //          }
+        //        });
+        //
+        //        //根据数量判断是老师还是学生
+        //        _numRole.forEach(i => {
+        //          if (i.t > i.s) {
+        //            _roleList[i.role] = "老师";
+        //          } else if (i.t < i.s) {
+        //            _roleList[i.role] = "学生";
+        //          }
+        //        });
+        //        //已经有的role
+        //        let roleKeys = Object.keys(_roleList);
+        //
+        //        textList.forEach(i => {
+        //          if (roleKeys.includes(i.role)) {
+        //            i.role = _roleList[i.role];
+        //          }
+        //        });
+        //
+        //        _getRoleList = _getRoleList.filter(
+        //          i => !roleKeys.includes(i.role)
+        //        );
+        //        _getRoleLoading = false;
+        //      })
+        //      .catch(err => {
+        //        console.log("最后的获取说话人身份失败", err);
+        //      });
+        //  }
+        //  if (
+        //    _behavioralCodingList.some(
+        //      i => i.role.indexOf("Guest") === -1 && i.code === ""
+        //    )
+        //  ) {
+        //    _flag = true;
+        //    const _behavioralCodingListTemp = _behavioralCodingList
+        //        .filter(i => i.role.indexOf("Guest") == -1 && i.code == "")
+        //      const params = {
+        //        inputs: {
+        //          rows: JSON.stringify(
+        //            _behavioralCodingListTemp.map(i => ({
+        //              content: i.content,
+        //              role: i.role
+        //            }))
+        //          ),
+        //          options: "老师讲课,老师提问或点名,老师板书或操作,老师评价或反馈,老师其他,学生发言,学生小组活动,学生自主学习,学生汇报分享,学生其他",
+        //          attention: "- 先根据说话人角色判断,再在对应角色的选项中选择选项\n- 如果没有合适的选项,默认使用`老师其他`或者`学生其他`"
+        //        },
+        //        response_mode: "blocking",
+        //        user: _this.userId
+        //      };
+        //      await _this
+        //        .getBehavioralCoding(params)
+        //        .then(res => {
+        //          const _runResult = res.data.data.outputs.result;
+        //          _behavioralCodingListTemp.forEach((item, index) => {
+        //            const foundItem = _behavioralCodingList.find(i => i.index === item.index);
+        //            if (foundItem) {
+        //              foundItem.code = _runResult[index];
+        //              textList[item.index].code = foundItem.code;
+        //            }
+        //          });
+        //        })
+        //        .catch(err => {
+        //          console.log("获取行为编码错误", err);
+        //        });
+        //  }
+        //
+        //  if (_flag) {
+        //    let _result = `
+        //<table
+        //		border="0"
+        //		width="100%"
+        //		cellpadding="0"
+        //		cellspacing="0"
+        //		style="text-align: center"
+        //	>
+        //		<tbody>
+        //			<tr>
+        //				<th>序号</th>
+        //				<th>开始时间</th>
+        //				<th>结束时间</th>
+        //				<th>发言内容</th>
+        //				<th>时长</th>
+        //				<th>说话人身份</th>
+        //				<th>行为编码</th>
+        //		</tr>
+        //`;
+        //    textList.forEach((item, index) => {
+        //      _result += `<tr>
+        //			<td>${index + 1}</td>
+        //			<td>${item.startTime}</td>
+        //			<td>${item.endTime}</td>
+        //			<td>${item.value}</td>
+        //			<td>${item.time}</td>
+        //			<td>${item.role}</td>
+        //			<td>${item.code}</td>
+        //		</tr>`;
+        //    });
+        //    _result += `
+        //<tr>
+        //			<td></td>
+        //			<td></td>
+        //			<td></td>
+        //			<td></td>
+        //			<td></td>
+        //			<td></td>
+        //			<td></td>
+        //		</tr>
+        //	</tbody>
+        //</table>`;
+        //    _this.editorBarData.content = _result;
+        //  }
+        //  _this.wavGetTextProgress = 100;
+        //  if (_this.wavFileGetTextLoading) _this.$message.success("转译完成");
+        //  _this.showGetTextLoading = false;
+        //  _this.wavGetTextLoading = false;
+        //  _this.saveEditorBar();
+        //};
+
+        //iiframe.contentWindow.ConversationTranscriber({
+        //  files: [_file]
+        //});
       } catch (error) {
         console.log(error);
         this.wavGetTextLoading = false;
@@ -3116,9 +3194,9 @@ ${JSON.stringify(_list)}
 
       // 录音开始
       let flag = true;
-      console.log("开始录音",iiframe)
+      console.log("开始录音", iiframe);
       iiframe.contentWindow.window.onRecognizedResult = e => {
-        console.log("onRecognizedResult",e)
+        console.log("onRecognizedResult", e);
         // let e = {
         // 	privText:"测试测试"
         // }
@@ -3143,8 +3221,8 @@ ${JSON.stringify(_list)}
         console.log("👇转译结果👇");
         console.log(privText);
         if (!privText || !privSpeakerId || privSpeakerId == "Unknown") {
-            return;
-          }
+          return;
+        }
 
         const newItem = {
           value: privText,
@@ -3161,7 +3239,8 @@ ${JSON.stringify(_list)}
         };
         this.recordedForm.textList.push(newItem);
         this.recordedForm.startTime = this.recordedForm.timeDuration + 1;
-        this.transcriptionData.content += _copyPrivSpeakerId + ":" + privText + "\n";
+        this.transcriptionData.content +=
+          _copyPrivSpeakerId + ":" + privText + "\n";
         this.onRecordAddLine(newItem);
       };
 

+ 146 - 84
src/components/pages/classroomObservation/tools/mixin.js

@@ -245,7 +245,7 @@ ${arr.map(row => `<tr>
 
               console.log("需要上传的文件", audioFile)
               this.uploadFileMixin(audioFile).then(upload => {
-                console.log("upload=>",upload)
+                console.log("upload=>", upload)
                 resolve({ audioUrl: upload, fileObj: audioFile })
               })
             } catch (error) {
@@ -1250,97 +1250,159 @@ CH:${_CH}
         let transcriptionContent = "";
         let tableContent = "";
         let tableList = [];
+        let textList  = [];
         let _startTime = 0;
         let _endTime = 0;
 
         let timer = null;
 
-        timer = setTimeout(() => {//五分钟无响应就算报错
-          resolve({ data: 1, transcriptionContent: null, editorBarData: null, err: "转录超时" })
-        }, 180000)
 
-        // 转录中
-        iframeRef.contentWindow.onRecognizedResult = (e) => {
-          let privText = e.privText;
-          let privSpeakerId = e.privSpeakerId;
-          let copySpeakerId = e.copySpeakerId;
-          let privDuration = e.privDuration;
-          let privOffset = e.privOffset;
-
-          console.log("转录内容",e)
-          if (timer) {
-            clearTimeout(timer)
-            timer = setTimeout(() => {//五分钟无响应就算报错
-              resolve({ data: 1, transcriptionContent: null, editorBarData: null, err: "转录超时" })
-            }, 180000)
-          }
-          if (!privText || !privSpeakerId || privSpeakerId == "Unknown") {//不记录
-            return;
-          }
-
-          _endTime = (privOffset + privDuration) / 10000000;
-
-          tableList.push({
-            value: privText,
-            startTime: this.updateRecordedTimeMixin({ duration: _startTime }),
-            endTime: this.updateRecordedTimeMixin({ duration: _endTime }),
-            time: this.updateRecordedTimeMixin({ duration: _endTime - _startTime }),
-            role: privSpeakerId,
-            code: ""
-          });
-
-          _startTime = _endTime;
-          transcriptionContent += copySpeakerId + ":" + privText + "\n";
-        };
-
-        //转录结束
-        iframeRef.contentWindow.onSessionStopped = async (e) => {
-          if (timer) {
-            clearTimeout(timer)
-          }
-          tableContent = `<table
-	border="0"
-	width="100%"
-	cellpadding="0"
-	cellspacing="0"
-	style="text-align: center"
->
-	<tbody>
-		<tr>
-			<th>序号</th>
-			<th>开始时间</th>
-			<th>结束时间</th>
-			<th>发言内容</th>
-			<th>时长</th>
-			<th>说话人身份</th>
-			<th>行为编码</th>
-	</tr>`;
-          tableList.forEach((item, index) => {
-            tableContent += `<tr>
-							<td>${index + 1}</td>
-							<td>${item.startTime}</td>
-							<td>${item.endTime}</td>
-							<td>${item.value}</td>
-							<td>${item.time}</td>
-							<td>${item.role}</td>
-							<td>${item.code}</td>
-						</tr>`
-          })
-
-          // tableContent += `<tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr></tbody></table>`
-
-          var blob = new Blob([tableContent], { type: "text/plain;charset=utf-8" });
-          blob.lastModifiedDate = new Date();
-          blob.name = `classroomObservation.txt`;
-          this.uploadFileMixin(blob).then(upload => {
-            resolve({ transcriptionContent: transcriptionContent, editorBarData: { type: "0", url: upload.Location, content: tableContent, tableList: tableList } })
+        iframeRef.contentWindow.window
+          .doConversationTranscriber({ files: [file] })
+          .then(res => {
+            console.log("转录内容", res);
+
+            let _data = res.phrases;
+
+            _data.forEach(i => {
+              let _privSpeakerId = `Guest-${i.speaker}`;
+              let _privText = i.text;
+              let privOffset = i.offsetMilliseconds;
+              let privDuration = i.durationMilliseconds;
+
+              _endTime = (privOffset + privDuration) / 1000;
+              textList.push({
+                value: _privText,
+                startTime: this.updateRecordedTimeMixin({ duration: _startTime }),
+                endTime: this.updateRecordedTimeMixin({ duration: _endTime }),
+                time: this.updateRecordedTimeMixin({
+                  duration: _endTime - _startTime
+                }),
+                role: _privSpeakerId,
+                code: ""
+              });
+              _startTime = _endTime;
+              transcriptionContent +=
+                _privSpeakerId + ":" + _privText + "\n";
+            });
+            let _result = `<table border="0" width="100%" cellpadding="0" cellspacing="0" style="text-align: center"><tbody><tr><th>序号</th><th>开始时间</th><th>结束时间</th><th>发言内容</th><th>时长</th><th>说话人身份</th><th>行为编码</th></tr>`;
+            textList.forEach((item, index) => {
+              _result += `<tr><td>${index + 1}</td><td>${item.startTime}</td><td>${item.endTime}</td><td>${item.value}</td><td>${item.time}</td><td>${item.role}</td><td>${item.code}</td></tr>`;
+            });
+            _result += `</tbody></table>`;
+            var blob = new Blob([_result], { type: "text/plain;charset=utf-8" });
+            blob.lastModifiedDate = new Date();
+            blob.name = `classroomObservation.txt`;
+            this.uploadFileMixin(blob).then(upload => {
+              console.log("上传成功并resolve",{transcriptionContent: transcriptionContent, editorBarData: { type: "0", url: upload.Location, content: _result, tableList: textList } })
+              resolve({transcriptionContent: transcriptionContent, editorBarData: { type: "0", url: upload.Location, content: _result, tableList: textList } })
+            })
+            // this.wavGetTextProgress = 100;
+            // if (this.wavFileGetTextLoading) this.$message.success("转译完成");
+            // // _this.editorBarData.content += privText;
+
+            // this.showGetTextLoading = false;
+            // this.wavGetTextLoading = false;
+            // this.uploadFileLoading = false;
+            // // this.uploadWavFile(audioFile);
+            // if (_timer) {
+            //   clearInterval(_timer);
+            // }
+            // this.saveEditorBar();
           })
-        };
+          .catch(err => {
+            console.log("转录error",err)
+            resolve({ data: 1, transcriptionContent: null, editorBarData: null, err: err })
+            //     console.log(err)
+            //     this.wavGetTextLoading = false;
+            // this.showGetTextLoading = false;
+          });
+        // timer = setTimeout(() => {//五分钟无响应就算报错
+        //   resolve({ data: 1, transcriptionContent: null, editorBarData: null, err: "转录超时" })
+        // }, 180000)
 
-        //开始转录
-        iframeRef.contentWindow.ConversationTranscriber({
-          files: [file]
-        });
+        // 转录中
+        //         iframeRef.contentWindow.onRecognizedResult = (e) => {
+        //           let privText = e.privText;
+        //           let privSpeakerId = e.privSpeakerId;
+        //           let copySpeakerId = e.copySpeakerId;
+        //           let privDuration = e.privDuration;
+        //           let privOffset = e.privOffset;
+
+        //           console.log("转录内容",e)
+        //           if (timer) {
+        //             clearTimeout(timer)
+        //             timer = setTimeout(() => {//五分钟无响应就算报错
+        //               resolve({ data: 1, transcriptionContent: null, editorBarData: null, err: "转录超时" })
+        //             }, 180000)
+        //           }
+        //           if (!privText || !privSpeakerId || privSpeakerId == "Unknown") {//不记录
+        //             return;
+        //           }
+
+        //           _endTime = (privOffset + privDuration) / 10000000;
+
+        //           tableList.push({
+        //             value: privText,
+        //             startTime: this.updateRecordedTimeMixin({ duration: _startTime }),
+        //             endTime: this.updateRecordedTimeMixin({ duration: _endTime }),
+        //             time: this.updateRecordedTimeMixin({ duration: _endTime - _startTime }),
+        //             role: privSpeakerId,
+        //             code: ""
+        //           });
+
+        //           _startTime = _endTime;
+        //           transcriptionContent += copySpeakerId + ":" + privText + "\n";
+        //         };
+
+        //         //转录结束
+        //         iframeRef.contentWindow.onSessionStopped = async (e) => {
+        //           if (timer) {
+        //             clearTimeout(timer)
+        //           }
+        //           tableContent = `<table
+        // 	border="0"
+        // 	width="100%"
+        // 	cellpadding="0"
+        // 	cellspacing="0"
+        // 	style="text-align: center"
+        // >
+        // 	<tbody>
+        // 		<tr>
+        // 			<th>序号</th>
+        // 			<th>开始时间</th>
+        // 			<th>结束时间</th>
+        // 			<th>发言内容</th>
+        // 			<th>时长</th>
+        // 			<th>说话人身份</th>
+        // 			<th>行为编码</th>
+        // 	</tr>`;
+        //           tableList.forEach((item, index) => {
+        //             tableContent += `<tr>
+        // 							<td>${index + 1}</td>
+        // 							<td>${item.startTime}</td>
+        // 							<td>${item.endTime}</td>
+        // 							<td>${item.value}</td>
+        // 							<td>${item.time}</td>
+        // 							<td>${item.role}</td>
+        // 							<td>${item.code}</td>
+        // 						</tr>`
+        //           })
+
+        //           // tableContent += `<tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr></tbody></table>`
+
+        //           var blob = new Blob([tableContent], { type: "text/plain;charset=utf-8" });
+        //           blob.lastModifiedDate = new Date();
+        //           blob.name = `classroomObservation.txt`;
+        //           this.uploadFileMixin(blob).then(upload => {
+        //             resolve({ transcriptionContent: transcriptionContent, editorBarData: { type: "0", url: upload.Location, content: tableContent, tableList: tableList } })
+        //           })
+        //         };
+
+        //         //开始转录
+        //         iframeRef.contentWindow.ConversationTranscriber({
+        //           files: [file]
+        //         });
       })
 
     },

+ 11 - 4
src/components/pages/inviteLoginST/inviteLogin.vue

@@ -13,12 +13,12 @@
 							<div class="c-b-r-m-title">欢迎登录!</div>
 							<div class="c-b-r-m-smallTitle">请选择登录角色</div>
 							<div class="c-b-r-m-identity">
-								<div class="c-b-r-m-i-item" @click.stop="clickIdentity(0)">
+								<!-- <div class="c-b-r-m-i-item" @click.stop="clickIdentity(0)">
 									<div class="c-b-r-m-i-itemSvg">
 										<svg width="48" height="48" viewBox="0 0 48 48" xmlns="http://www.w3.org/2000/svg" fill="currentColor"><path d="M20.2969 5.57812C26.3288 5.57812 31.2188 10.468 31.2188 16.5C31.2188 20.3947 29.1802 23.8133 26.1118 25.7469V25.7464C29.8475 27.3133 32.8847 30.2153 34.6266 33.8555L41.5929 23.8744C42.0671 23.1951 43.0021 23.0288 43.6815 23.5028C44.354 23.9722 44.5238 24.8934 44.067 25.571L44.053 25.5914L36.0582 37.046C35.9913 37.1419 35.9136 37.2297 35.8264 37.3075C36.0935 38.485 36.2344 39.7104 36.2344 40.9688C36.2344 41.7972 35.5628 42.4688 34.7344 42.4688C33.9142 42.4688 33.2478 41.8105 33.2346 40.9936L33.2344 40.9688C33.2344 33.5129 27.1902 27.4688 19.7344 27.4688C12.3531 27.4688 6.35541 33.3926 6.2362 40.7455L6.23438 40.9688C6.23438 41.7972 5.5628 42.4688 4.73438 42.4688C3.90595 42.4688 3.23438 41.7972 3.23438 40.9688C3.23438 33.8485 7.74441 27.7817 14.0636 25.4691L14.0634 25.4695C11.2296 23.4965 9.375 20.2148 9.375 16.5C9.375 10.468 14.2649 5.57812 20.2969 5.57812ZM20.2969 8.57812C15.9218 8.57812 12.375 12.1249 12.375 16.5C12.375 20.8751 15.9218 24.4219 20.2969 24.4219C24.672 24.4219 28.2188 20.8751 28.2188 16.5C28.2188 12.1249 24.672 8.57812 20.2969 8.57812ZM43.2188 13.1719C44.0472 13.1719 44.7188 13.8435 44.7188 14.6719C44.7188 15.492 44.0605 16.1584 43.2436 16.1717L43.2188 16.1719H37.5938C36.7653 16.1719 36.0938 15.5003 36.0938 14.6719C36.0938 13.8518 36.752 13.1853 37.5689 13.1721L37.5938 13.1719H43.2188ZM43.2188 6.5625C44.0472 6.5625 44.7188 7.23408 44.7188 8.0625C44.7188 8.88263 44.0605 9.54905 43.2436 9.56231L43.2188 9.5625H33.6562C32.8278 9.5625 32.1562 8.89092 32.1562 8.0625C32.1562 7.24238 32.8145 6.57595 33.6314 6.56269L33.6562 6.5625H43.2188Z"></path></svg>
 									</div>
 									<span>教师</span>
-								</div>
+								</div> -->
 
 								<div class="c-b-r-m-i-item" @click.stop="clickIdentity(1)">
 									<div class="c-b-r-m-i-itemSvg">
@@ -74,6 +74,12 @@ export default {
 			},
 		},
 		mounted() {
+      this.$router.push({
+				name:"inviteLoginSZ",
+        query:{
+          code:this.code,
+        }
+			})
 			setInterval(() => {
 				 window.topU.postMessage({
 					tools:"getLogin"
@@ -91,6 +97,7 @@ export default {
 					}
 				}
 			})
+
 		},
 }
 </script>
@@ -161,7 +168,7 @@ export default {
 	top: -45px;
 	border-radius: 50%;
 	background-color: #3681FC;
-	
+
 }
 
 .c-b-r-ca-btn{
@@ -226,4 +233,4 @@ export default {
 	font-size: 18px;
 }
 
-</style>
+</style>

+ 52 - 3
src/components/pages/inviteLoginSZ/inviteLogin.vue

@@ -1,5 +1,8 @@
 <template>
     <div class="container" v-loading="loading">
+      <div class="loginOut" v-show="showLoadingOut">
+					<span @click="loginOut">退出登录</span>
+				</div>
         <!-- <div class="i_box" v-if="steps == 1">
             <div class="i_box_top">
                 <div><span>请输入随机码进入项目课程</span></div>
@@ -60,6 +63,7 @@
 								<div v-if="!classJuri.length" class="c-b-r-m-cna-none">此班级暂无学生</div>
 								<div v-for="item in classJuri" :class="['c-b-r-m-cna-item',chooseData.userid==item.userid?'c-b-r-m-cna-itemActive':'']" @click="choose(item.userid,(item.name ? item.name : item.username))" :key="item.userid">{{ item.name ? item.name :item.username }}</div>
 							</div>
+							<!--  -->
 							<el-button class="c-b-r-m-loginBtn" type="primary" v-if="classJuri.length" @click.stop="login(chooseData.userid,chooseData.username)">确认登录</el-button>
 						</div>
 					</div>
@@ -82,7 +86,8 @@ export default {
             courseId:"",
 						showErrMsg:false,
 						errMsg:"",
-						chooseData:{}
+						chooseData:{},
+            showLoadingOut:false,
         }
     },
 		computed:{
@@ -179,8 +184,32 @@ export default {
 				setErrMsg(msg){
 					this.showErrMsg = true;
 					this.errMsg = msg;
-				}
+				},
+        loginOut(){
+				 window.topU.postMessage({
+					tools:"logout"
+				},"*")
+			},
     },
+    mounted(){
+      setInterval(() => {
+				 window.topU.postMessage({
+					tools:"getLogin"
+				},"*")
+				console.log("获取getLogin")
+			}, 2000);
+			window.addEventListener("message",(e)=>{
+				let data = e.data;
+				console.log("message",e)
+				if(data.tools && data.tools=='getLogin'){
+					if(data.type===2){
+						this.showLoadingOut = false;
+					}else if(data.type===1){
+						this.showLoadingOut = true;
+					}
+				}
+			})
+    }
 }
 </script>
 
@@ -248,6 +277,7 @@ export default {
 .c-b-r-main{
 	width: 80%;
 	height: 80%;
+	overflow: auto;;
 }
 
 .c-b-r-m-title{
@@ -318,8 +348,9 @@ export default {
 
 .c-b-r-m-chooseNameArea{
 	width: 100%;
+	max-height: 70%;
 	height: auto;
-	max-height: 300px;
+	/* max-height: 300px; */
 	margin-top: 20px;
 	display: flex;
 	flex-wrap: wrap;
@@ -458,4 +489,22 @@ export default {
     justify-content: center !important;
     margin: 0 !important;
 } */
+
+.loginOut{
+	position: absolute;
+	right: 30px;
+	top: 30px;
+	width: auto;
+	height: auto;
+	display: flex;
+	justify-content: center;
+	align-items: center;
+}
+
+.loginOut>span{
+	font-size: 24px;
+	color: #fff;
+	font-weight: bold;
+	cursor: pointer;
+}
 </style>

+ 2 - 2
src/components/pages/liyuan/aiOffice.vue

@@ -26,13 +26,13 @@ export default {
     return {
       role: this.$route.query.role,
       cardArray: [
-        { title: '资料收集', icon: require('../../../assets/icon/liyuan/zlsj.svg'), type: 1, to: "/teadTest",role:0,sortId:'e18d88b3-e828-11ef-b508-005056924926'},
+        { title: '资料收集', icon: require('../../../assets/icon/liyuan/zlsj.svg'), type: 1, to: "/teadTest",role:0,sortId:'cd006687-8a00-11f0-9c7b-005056924926'},
         { title: '会议妙记', icon: require('../../../assets/icon/liyuan/hymj.svg'), type: 2, to: `/aigpt/#/cocoFlowConferenceTrick?userid=${this.$route.query.userid}&oid=${this.$route.query.oid}&role=${this.$route.query.role}&tType=${this.$route.query.tType}&org=${this.$route.query.org}&gotype=1`,role:0 },
         { title: '教师管理', icon: require('../../../assets/icon/liyuan/teamange.svg'), type: 1, to: "/teacher",role:1 },
         { title: '学生管理', icon: require('../../../assets/icon/liyuan/stumange.svg'), type: 1, to: "/Listudent",role:0 },
         { title: '办公表单', icon: require('../../../assets/icon/liyuan/workTest.svg'), type: 1, to: "/sassPlatform",role:1,sassPlatFormTypeId:"cd006687-8a00-11f0-9c7b-005056924926"},
         { title: '教研室管理', icon: require('../../../assets/icon/liyuan/workTest.svg'), type: 1, to: "/teacherOffice",role:1 },
-        { title: '数据看板', icon: require('../../../assets/icon/liyuan/workTest.svg'), type: 3, to: `https://liyuan.cocorobo.cn/#/dataBoardNew?userid=${this.$route.query.userid}&oid=${this.$route.query.oid}&org=${this.$route.query.org}`,role:1 },
+        { title: '数据看板', icon: require('../../../assets/icon/liyuan/workTest.svg'), type: 3, to: `https://liyuan.cocorobo.cn/#/dataBoardNew?userid=${this.$route.query.userid}&oid=${this.$route.query.oid}&org=${this.$route.query.org}&gotype=aiOffice`,role:1 },
       ]
     }
   },

+ 1 - 1
src/components/pages/liyuan/page/teadTest.vue

@@ -294,7 +294,7 @@ export default {
             let params = {
                 oid: "",//this.oid
             };
-            let inte = (this.sortId == 'eefb7195-8ee7-11f0-9c7b-005056924926') ? 'selectTestType_liYuan' : 'selectTestType'
+            let inte = (['eefb7195-8ee7-11f0-9c7b-005056924926','cd006687-8a00-11f0-9c7b-005056924926'].includes(this.sortId)) ? 'selectTestType_liYuan' : 'selectTestType'
             this.ajax
                 .get(this.$store.state.api + inte, params)
                 .then(res => {

+ 1 - 1
src/components/pages/sassPlatform/index.vue

@@ -242,7 +242,7 @@ export default {
 
 .sp_bottom{
   width: 100%;
-  height: calc(100% - 70px);
+  /* height: calc(100% - 70px); */
   display: flex;
 }
 

+ 415 - 0
src/components/pages/workPage/components/choiceQuestion.vue

@@ -0,0 +1,415 @@
+<template>
+  <div class="choiceQuestion">
+    <div class="cq_title" v-if="work.testJson[showIndex]">
+      <span>{{ work.testJson[showIndex].teststitle }}</span>
+
+      <div class="cq_changeBtnArea" v-if="work.testJson.length>1">
+        <span :class="{cq_cba_disabled: showIndex == 0}" @click="changeQuestion('prev')">上一题</span>
+        <span :class="{cq_cba_disabled: showIndex == work.testJson.length - 1}" @click="changeQuestion('next')">下一题</span>
+      </div>
+    </div>
+
+
+    <img class="cq_image" v-if="work.testJson[showIndex].timuList.length>0" :src="work.testJson[showIndex].timuList[0].src" @click="$hevueImgPreview(work.testJson[showIndex].timuList[0].src)">
+
+    <div class="cq_type" v-if="work.testJson[showIndex]">
+      {{ work.testJson[showIndex].type == 1 ? "单选题" : "多选题" }}
+      <span v-if="work.testJson.length>1">({{showIndex+1}}/{{work.testJson.length}})</span>
+
+    </div>
+    <div class="cq_checkListArea">
+      <div
+        class="cq_ca_type1"
+        v-if="
+          work.testJson[showIndex] && work.testJson[showIndex].showType == '1'
+        "
+      >
+        <div
+          class="cq_ca_t1_item"
+          :class="{
+            cq_ca_t1_item_active:
+              work.testJson[showIndex].type == '1'
+                ? work.testJson[showIndex].userAnswer === index
+                : work.testJson[showIndex].userAnswer.includes(index)
+          }"
+          v-for="(item, index) in work.testJson[showIndex].checkList"
+          :key="showIndex + '_' + index"
+          @click="choiceAnswer(index)"
+        >
+          <div>
+            <span>{{ options[index] }}</span>
+          </div>
+          <img v-if="item.imgType && item.imgType=='1'" :src="item.src" @click="$hevueImgPreview(item.src)">
+          <span v-else>{{ item }}</span>
+        </div>
+      </div>
+
+      <div class="cq_ca_type2" v-if="
+          work.testJson[showIndex] && work.testJson[showIndex].showType == '2'
+        ">
+        <div
+          class="cq_ca_t2_item"
+          :class="{
+            cq_ca_t2_item_active:
+              work.testJson[showIndex].type == '1'
+                ? work.testJson[showIndex].userAnswer === index
+                : work.testJson[showIndex].userAnswer.includes(index)
+          }"
+          v-for="(item, index) in work.testJson[showIndex].checkList"
+          :key="showIndex + '_' + index"
+          @click="choiceAnswer(index)"
+        >
+          <div>
+            <span>{{ options[index] }}</span>
+          </div>
+          <img v-if="item.imgType && item.imgType=='1'" :src="item.src" @click="$hevueImgPreview(item.src)">
+          <span v-else>{{ item }}</span>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  props: {
+    workData: {
+      type: Object,
+      default: () => {
+        return {};
+      }
+    }
+  },
+
+  data() {
+    return {
+      work: {
+        testJson: []
+      },
+      showIndex: 0,
+      options: [
+        "A",
+        "B",
+        "C",
+        "D",
+        "E",
+        "F",
+        "G",
+        "H",
+        "I",
+        "J",
+        "K",
+        "L",
+        "M",
+        "N",
+        "O",
+        "P",
+        "Q",
+        "R",
+        "S",
+        "T",
+        "U",
+        "V",
+        "W",
+        "X",
+        "Y",
+        "Z"
+      ]
+    };
+  },
+  watch: {
+    work: {
+      handler(newValue) {
+        if (JSON.stringify(newValue) != JSON.stringify(this.workData.json)) {
+          this.changeWorkData(newValue);
+        }
+      },
+      deep: true
+    }
+  },
+  methods: {
+    changeWorkData(newValue) {
+      this.$emit("changeWorkData", JSON.stringify(newValue));
+    },
+    //选择题目
+    choiceAnswer(index) {
+      if (this.work.testJson[this.showIndex].type == "1") {
+        this.work.testJson[this.showIndex].userAnswer = index;
+      } else {
+        if (this.work.testJson[this.showIndex].userAnswer.includes(index)) {
+          this.work.testJson[this.showIndex].userAnswer = this.work.testJson[
+            this.showIndex
+          ].userAnswer.filter(i => i != index);
+        } else {
+          this.work.testJson[this.showIndex].userAnswer.push(index);
+        }
+      }
+    },
+    //切换题目
+    changeQuestion(type){
+      if(type == 'prev'){
+        if(this.showIndex == 0) return;
+        this.showIndex--;
+      }else{
+        if(this.showIndex == this.work.testJson.length - 1) return;
+        this.showIndex++;
+      }
+    }
+
+  },
+  mounted() {
+    this.work = JSON.parse(JSON.stringify(this.workData.json));
+    this.work.testJson.forEach(i => {
+      let maxLength = i.checkList.reduce((pre, cur) => {
+        if (pre < cur.length) return cur.length;
+        return pre;
+      }, 0);
+
+      if (maxLength <= 6 && i.checkList.length <= 4) {
+        i.showType = "1";
+      } else {
+        i.showType = "2";
+      }
+    });
+  }
+};
+</script>
+
+<style scoped>
+
+
+.choiceQuestion {
+  width: 100%;
+  height: 100%;
+  display: flex;
+  align-items: center;
+  /* justify-content: center; */
+  flex-direction: column;
+  box-sizing: border-box;
+  padding: 50px 10%;
+  overflow: auto;
+  position: relative;
+}
+
+.cq_title {
+  font-size: 35px;
+  font-weight: bold;
+  text-align: center;
+  width: 70%;
+  position: relative;
+}
+
+.cq_image{
+  width: auto;
+  height: 300px;
+  object-fit: cover;
+  margin: 20px 0;
+  cursor: pointer;
+}
+
+.cq_changeBtnArea {
+  position: absolute;
+  top: 0px;
+  right: -200px;
+  width: 200px;
+  height: auto;
+  display: flex;
+  justify-content: flex-end;
+  align-items: flex-start;
+}
+
+.cq_changeBtnArea > span{
+  width: 100px;
+  height: 40px;
+  background: #3681FC;
+  border-radius: 8px;
+  color: #fff;
+  font-size: 16px;
+  text-align: center;
+  font-weight: 500;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  cursor: pointer;
+  margin-left: 20px;
+  transition: .2s;
+}
+
+.cq_changeBtnArea > span:hover{
+  background: #5893FF;
+}
+
+.cq_cba_disabled{
+  background: #D9D9D9 !important;
+  cursor: not-allowed !important;
+}
+
+.cq_type {
+  margin: 20px 0 40px 0;
+  font-size: 22px;
+  color: #808080;
+}
+
+.cq_checkListArea {
+  width: 100%;
+  height: auto;
+  box-sizing: border-box;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+}
+
+.cq_ca_type1 {
+  width: auto;
+  height: auto;
+  display: grid;
+  grid-template-columns: repeat(2, 1fr);
+  grid-template-rows: repeat(2, 1fr);
+  gap: 30px; /* 可根据需要调整间距 */
+  justify-content: center;
+  align-items: center;
+  margin: 40px 20px;
+}
+
+.cq_ca_t1_item {
+  width: 100%;
+  max-width: 400px;
+  min-width: 300px;
+  height: 100px;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+
+  background: #fff;
+  box-shadow: 2px 4px 20px 0px rgba(0, 0, 0, 0.2);
+  border-radius: 12px;
+  margin: auto;
+  cursor: pointer;
+  transition: 0.3s;
+  font-size: 20px;
+  color: #000;
+  user-select: none;
+  /* 不可选中 */
+  /* box-sizing: border-box;
+  padding: 20px 40px; */
+}
+
+.cq_ca_t1_item_active {
+  box-shadow: 4px 4px 14px 0px rgba(252, 207, 0, 0.5);
+}
+
+.cq_ca_t1_item > div {
+  color: #fff;
+  position: relative;
+  margin-right: 20px;
+}
+
+.cq_ca_t1_item>img{
+  width: 80px;
+  height: 80px;
+  cursor: pointer;
+  object-fit: cover;
+}
+
+.cq_ca_t1_item > div > span {
+  position: relative;
+  z-index: 2;
+  color: #fff;
+  font-size: 20px;
+}
+
+.cq_ca_t1_item > div::after {
+  content: "";
+  width: 25px;
+  height: 25px;
+  background: rgba(252, 207, 0, 1);
+  border-radius: 50%;
+  position: absolute;
+  left: 50%;
+  top: 50%;
+  transform: translate(-50%, -50%);
+  z-index: 1; /* after在内容下方 */
+  pointer-events: none;
+}
+
+.cq_ca_type2{
+  width: 100%;
+  height: auto;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  flex-direction: column;
+}
+
+.cq_ca_t2_item{
+  width: 100%;
+  height: 72px;
+  display: flex;
+  align-items: center;
+  justify-content: flex-start;
+  box-sizing: border-box;
+  padding-left: 40px;
+  padding-right: 20px;
+  margin-bottom: 20px;
+  background: #fff;
+  box-shadow: 2px 4px 20px 0px rgba(0, 0, 0, 0.2);
+  border-radius: 12px;
+  cursor: pointer;
+  transition: 0.3s;
+  font-size: 20px;
+  color: #000;
+  user-select: none;
+  overflow: auto;
+  overflow-y: hidden;
+}
+
+.cq_ca_t2_item>div{
+  color: #fff;
+  position: relative;
+  margin-right: 20px;
+}
+
+.cq_ca_t2_item>span{
+  display: flex;
+  align-items: center;
+  white-space: nowrap;
+}
+
+.cq_ca_t2_item>img{
+  width: 70px;
+  height: 70px;
+  cursor: pointer;
+  object-fit: cover;
+}
+
+
+.cq_ca_t2_item_active {
+  box-shadow: 4px 4px 14px 0px rgba(252, 207, 0, 0.5);
+}
+
+.cq_ca_t2_item > div {
+  color: #fff;
+  position: relative;
+  margin-right: 20px;
+}
+.cq_ca_t2_item > div > span {
+  position: relative;
+  z-index: 2;
+  color: #fff;
+  font-size: 20px;
+}
+
+.cq_ca_t2_item > div::after {
+  content: "";
+  width: 25px;
+  height: 25px;
+  background: rgba(252, 207, 0, 1);
+  border-radius: 50%;
+  position: absolute;
+  left: 50%;
+  top: 50%;
+  transform: translate(-50%, -50%);
+  z-index: 1; /* after在内容下方 */
+  pointer-events: none;
+}
+</style>

Файловите разлики са ограничени, защото са твърде много
+ 32 - 0
src/components/pages/workPage/components/questionsAndAnswers.vue


+ 343 - 0
src/components/pages/workPage/components/wangEnduit.vue

@@ -0,0 +1,343 @@
+<template lang="html">
+  <div class="editor cont">
+    <div ref="toolbar" class="toolbar">
+    </div>
+    <div ref="editor" class="text">
+    </div>
+		<slot></slot>
+    <div v-if="proVisible" class="mask">
+      <div class="progressBox">
+        <div class="lbox">
+          <img src="../../../../assets/loading.gif" />上传中,请稍后
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import E from "wangeditor";
+import "../../../../common/aws-sdk-2.235.1.min";
+// import 'wangeditor/release/wangEditor.min.css'
+export default {
+  name: "editoritem",
+  data() {
+    return {
+      // uploadPath,
+      editor: null,
+      info_: null,
+      proVisible:false,
+      progress:0
+    };
+  },
+  model: {
+    prop: "value",
+    event: "change",
+  },
+  props: {
+    value: {
+      type: String,
+      default: "",
+    },
+    isClear: {
+      type: Boolean,
+      default: false,
+    },
+    placeholder: {
+      type: String,
+      default: "请输入正文"
+    },
+		showGetTextLoading:{
+			type:Boolean,
+			default:false,
+		}
+  },
+  watch: {
+    isClear(val) {
+      // 触发清除文本域内容
+      if (val) {
+        this.editor.txt.clear();
+        this.info_ = null;
+      }
+    },
+    value: function (value) {
+      if (value !== this.editor.txt.html()) {
+        this.editor.txt.html(this.value);
+      }
+    },
+    //value为编辑框输入的内容,这里我监听了一下值,当父组件调用得时候,如果给value赋值了,子组件将会显示父组件赋给的值
+  },
+  mounted() {
+    this.seteditor();
+    this.editor.txt.html(this.value);
+  },
+  methods: {
+    seteditor() {
+      this.editor = new E(this.$refs.toolbar, this.$refs.editor);
+      // 关闭菜单栏fixed
+      this.editor.config.menuFixed = false;
+      // 普通的自定义菜单
+      this.editor.config.menus = [
+        "head", //标题
+        "bold", //加粗
+        "fontSize", //字体大小
+        // "fontName", //字体
+        // "italic", //斜体
+        // "underline", //下划线
+        // "strikeThrough", //删除线
+        "indent", //缩进
+        // "lineHeight", //行高
+        // "foreColor",
+        // "backColor",
+        // "link",
+        // "list",
+        // "todo",
+        "justify",
+        // "quote",
+        // "emoticon",
+        "image",
+        // "video",
+        "table",
+        // "code",
+        // "splitLine",
+        "undo",
+        "redo",
+      ];
+      // 带格式粘贴
+      this.editor.config.pasteFilterStyle = false;
+      //忽略粘贴内容中的图片
+      this.editor.config.pasteIgnoreImg = false;
+      this.editor.config.showLinkImg = false;
+      this.editor.config.placeholder = this.placeholder;
+      var that = this;
+      this.editor.config.customUploadImg = function (files, insert) {
+        // const loading = Loading.service({
+        //   lock: true,
+        //   background: 'rgba(0, 0, 0, 0.7)'
+        // });
+        // 图片自定义上传方法
+        var kk = 0
+        for (var i = 0; i < files.length; i++) {
+          var file = files[i];
+          var credentials = {
+            accessKeyId: "AKIATLPEDU37QV5CHLMH",
+            secretAccessKey: "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",
+          }; //秘钥形式的登录上传
+          window.AWS.config.update(credentials);
+          window.AWS.config.region = "cn-northwest-1"; //设置区域
+
+          var bucket = new window.AWS.S3({ params: { Bucket: "ccrb" } }); //选择桶
+          that.proVisible = true
+          if (file) {
+            var params = {
+              Key:
+                file.name.split(".")[0] +
+                new Date().getTime() +
+                "." +
+                file.name.split(".")[file.name.split(".").length - 1],
+              ContentType: file.type,
+              Body: file,
+              "Access-Control-Allow-Credentials": "*",
+              ACL: "public-read",
+            }; //key可以设置为桶的相抵路径,Body为文件, ACL最好要设置
+            var options = {
+              partSize: 2048 * 1024 * 1024,
+              queueSize: 2,
+              leavePartsOnError: true,
+            };
+            bucket
+              .upload(params, options)
+              .on("httpUploadProgress", function (evt) {
+                //这里可以写进度条
+                // console.log("Uploaded : " + parseInt((evt.loaded * 80) / evt.total) + '%');
+              })
+              .send(function (err, data) {
+                kk++
+                if(kk == files.length - 1 || kk > files.length - 1){
+                  that.proVisible = false
+                }
+                // loading.close();
+                if (err) {
+                  that.$message.error("上传失败");
+                } else {
+                  //上传成功处理
+                  insert(data.Location);
+                }
+              });
+          }
+        }
+      };
+      //配置 自定义处理粘贴的文本内容
+      this.editor.config.pasteTextHandle = function (content) {
+        if (content == '' && !content) return ''
+        var str = content
+        str = str.replace(/<xml>[\s\S]*?<\/xml>/ig, '')
+        str = str.replace(/<style>[\s\S]*?<\/style>/ig, '')
+        str = str.replace(/<\/?[^>]*>/g, '')
+        str = str.replace(/[ | ]*\n/g, '\n')
+        str = str.replace(/&nbsp;/ig, '')
+        // console.log('****', content)
+        // console.log('****', str)
+        return str
+      };
+      this.editor.config.onchange = (html) => {
+        this.info_ = html; // 绑定当前逐渐地值
+        this.$emit("change", this.info_); // 将内容同步到父组件中
+      };
+      // 创建富文本编辑器
+      this.editor.create();
+    },
+  },
+};
+</script>
+
+<style lang="css" scoped>
+.editor {
+   width: 100%;
+   height: calc(100%);
+   margin: 0px auto;
+   position: relative;
+   z-index: 0;
+ }
+
+ .toolbar {
+   /* border: 1px solid #ccc; */
+   border-radius: 12px 12px 0 0;
+   border-bottom: solid 2px #E7E7E7;
+   background: none;
+ }
+
+ .toolbar /deep/ .w-e-toolbar{
+  border-radius: 12px 12px 0 0;
+  background: none;
+ }
+
+ .text {
+   /* border: 1px solid #ccc; */
+   height: calc(100% - 42px);
+   overflow: auto;
+ }
+
+ .text /deep/ .w-e-text-container{
+  background: none;
+  border-radius: 0 0 12px 12px;
+ }
+
+
+ /* table 样式 */
+ .cont>>>table {
+  border-top: 1px solid #ccc;
+  border-left: 1px solid #ccc;
+}
+
+.cont>>>table td,
+.cont>>>table th {
+  border-bottom: 1px solid #ccc;
+  border-right: 1px solid #ccc;
+  /* padding: 20px 5px; */
+  padding: 5px 10px;
+  max-width: 0px;
+  height: 30px;
+  vertical-align: baseline;
+}
+
+.cont>>>table th {
+  border-bottom: 2px solid #ccc;
+  text-align: center;
+}
+
+ /* blockquote 样式 */
+ .cont>>>blockquote {
+   display: block;
+   border-left: 8px solid #d0e5f2;
+   padding: 5px 10px;
+   margin: 10px 0;
+   line-height: 1.4;
+   font-size: 100%;
+   background-color: #f1f1f1;
+ }
+
+ /* code 样式 */
+ .cont>>>code {
+   display: inline-block;
+   *display: inline;
+   *zoom: 1;
+   background-color: #f1f1f1;
+   border-radius: 3px;
+   padding: 3px 5px;
+   margin: 0 3px;
+ }
+
+ .cont>>>pre code {
+   display: block;
+ }
+
+ /* ul ol 样式 */
+ .cont>>>ul,
+ ol {
+   margin: 0 !important;
+ }
+
+ /* .cont>>>.w-e-droplist{
+  width: 80px !important;
+ } */
+
+ .mask {
+  background-color: rgb(0 0 0 / 30%);
+  /* position: fixed; */
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  z-index: 99999;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+}
+
+.mask2 {
+  position: fixed !important;
+  z-index: 999999;
+}
+
+.progressBox {
+  width: 300px;
+  height: 150px;
+  background: #fff;
+  border-radius: 10px;
+  box-shadow: 0 0 6px 1px #bfbfbf;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  flex-direction: column;
+}
+
+.progressBox .lbox {
+  height: 100px;
+  font-size: 16px;
+  display: flex;
+  align-items: center;
+}
+
+.progressBox .lbox img {
+  width: 40px;
+  margin-right: 20px;
+}
+
+.progressBox>>>.el-progress-bar__outer {
+  background-color: #d1dfff !important;
+}
+
+.progressBox .lbox {
+  height: 100px;
+  font-size: 19px;
+  display: flex;
+  align-items: center;
+}
+
+.progressBox .lbox img {
+  width: 40px;
+  margin-right: 20px;
+}
+</style>

+ 791 - 0
src/components/pages/workPage/index_new.vue

@@ -0,0 +1,791 @@
+<template>
+  <div class="workPage" v-loading="loading">
+    <!-- <div class="wp_tool wp_tool15" v-if="workData && workData.type == 15">
+      <div class="wp_t15_title">{{ workData.json.answerQ }}</div>
+      <span class="wp_type">问答题</span>
+      <div class="wp_tl15_inputArea">
+        <el-input
+          type="textarea"
+          :rows="7"
+          placeholder="请在此输入您的答案..."
+          resize="none"
+          v-model="workData.json.answer"
+        >
+        </el-input>
+      </div>
+      <div class="wp_tl15_uploadFileArea">
+        <div
+          class="wp_tl_btn"
+          @click="uploadImage()"
+          v-loading="loadingUploadFile"
+        >
+          <svg
+            t="1755158440992"
+            class="icon"
+            viewBox="0 0 1024 1024"
+            version="1.1"
+            xmlns="http://www.w3.org/2000/svg"
+            p-id="8270"
+            width="200"
+            height="200"
+          >
+            <path
+              d="M924 1024H100A100 100 0 0 1 0 924V638a40 40 0 0 1 80 0v286a20 20 0 0 0 20 20h824a20 20 0 0 0 20-20V638a40 40 0 0 1 80 0v286a100 100 0 0 1-100 100zM784 352a40 40 0 0 1-28-12L512 97 268 340a40 40 0 0 1-57-57L484 12a40 40 0 0 1 57 0l271 272a40 40 0 0 1-28 68z"
+              fill="#474747"
+              p-id="8271"
+            ></path>
+            <path
+              d="M512 788a40 40 0 0 1-40-40V57a40 40 0 0 1 80 0v691a40 40 0 0 1-40 40z"
+              fill="#474747"
+              p-id="8272"
+            ></path>
+          </svg>
+          <span>上传图片</span>
+        </div>
+        <span>支持JPG、PNG格式,最大5MB</span>
+      </div>
+
+      <div class="wp_tl15_fileList">
+        <div
+          class="wp_tl15_fileList_item"
+          v-for="(item, index) in workData.json.fileList"
+          :key="index"
+        >
+          <img :src="item.url" alt="" @click="previewImage(item)" />
+          <svg
+            @click="deleteFile(index)"
+            t="1755162206922"
+            class="icon"
+            viewBox="0 0 1024 1024"
+            version="1.1"
+            xmlns="http://www.w3.org/2000/svg"
+            p-id="9357"
+            width="200"
+            height="200"
+          >
+            <path
+              d="M512 883.2A371.2 371.2 0 1 0 140.8 512 371.2 371.2 0 0 0 512 883.2z m0 64a435.2 435.2 0 1 1 435.2-435.2 435.2 435.2 0 0 1-435.2 435.2z"
+              fill="#d81e06"
+              p-id="9358"
+            ></path>
+            <path
+              d="M557.056 512l122.368 122.368a31.744 31.744 0 1 1-45.056 45.056L512 557.056l-122.368 122.368a31.744 31.744 0 1 1-45.056-45.056L466.944 512 344.576 389.632a31.744 31.744 0 1 1 45.056-45.056L512 466.944l122.368-122.368a31.744 31.744 0 1 1 45.056 45.056z"
+              fill="#d81e06"
+              p-id="9359"
+            ></path>
+          </svg>
+        </div>
+      </div>
+    </div>
+
+    <div class="wp_tool wp_tool45" v-if="workData && workData.type == 45">
+      <div class="wp_t45_title">练一练</div>
+      <div
+        class="s_b_m_toolItem"
+        v-for="(item, index) in workData.json.testJson"
+        :key="index + '_' + workData.id"
+      >
+        <div class="s_b_m_ti_title">
+          <span>{{ index + 1 }}</span>
+          <svg
+            width="16"
+            height="16"
+            viewBox="0 0 16 16"
+            fill="none"
+            xmlns="http://www.w3.org/2000/svg"
+          >
+            <path
+              d="M15.3536 8.35355C15.5488 8.15829 15.5488 7.84171 15.3536 7.64645L12.1716 4.46447C11.9763 4.2692 11.6597 4.2692 11.4645 4.46447C11.2692 4.65973 11.2692 4.97631 11.4645 5.17157L14.2929 8L11.4645 10.8284C11.2692 11.0237 11.2692 11.3403 11.4645 11.5355C11.6597 11.7308 11.9763 11.7308 12.1716 11.5355L15.3536 8.35355ZM1 8.5H15V7.5H1V8.5Z"
+              fill="#3681FC"
+            />
+          </svg>
+
+          <span
+            ><span
+              v-html="
+                renderedFormula(
+                  `<span style='color: #3681FC;''>${
+                    item.type == 1 ? '(单选题):' : '(多选题):'
+                  }</span>${item.teststitle}`
+                )
+              "
+            ></span>
+          </span>
+        </div>
+        <div
+          class="s_b_m_ti_option"
+          v-for="(item2, index2) in item.checkList"
+          @click="chooseAnswer(index, index2)"
+          :key="index + '_' + index2 + 'index2T'"
+          :class="{
+            s_b_m_ti_o_choice:
+              item.type == '1'
+                ? workData.json.testJson[index].userAnswer === index2
+                : workData.json.testJson[index].userAnswer.includes(index2)
+          }"
+        >
+          <div class="s_b_m_ti_o_btn">
+            <span class="s_b_m_ti_o_btn1" v-if="item.type == 1">
+              <span
+                v-if="workData.json.testJson[index].userAnswer === index2"
+              ></span>
+            </span>
+            <span class="s_b_m_ti_o_btn2" v-else>
+              <span
+                v-if="workData.json.testJson[index].userAnswer.includes(index2)"
+              >
+              </span>
+            </span>
+          </div>
+          <span>
+            <img
+              v-if="item2.imgType && item2.imgType === 1"
+              :src="item2.src"
+              alt=""
+              @click.stop="$hevueImgPreview(item2.src)"
+            />
+            <span v-else>{{ item2 }}</span>
+          </span>
+        </div>
+      </div>
+    </div> -->
+  <questionsAndAnswers ref="questionsAndAnswersRef" v-if="workData.type === '15'" :workData="workData" @changeWorkData="changeWorkData"/>
+  <choiceQuestion ref="choiceQuestionRef" v-if="workData.type === '45'" :workData="workData" @changeWorkData="changeWorkData"/>
+  </div>
+</template>
+
+<script>
+import katex from "katex";
+import "katex/dist/katex.min.css";
+import questionsAndAnswers from "./components/questionsAndAnswers.vue";
+import choiceQuestion from "./components/choiceQuestion.vue";
+export default {
+  components:{
+    questionsAndAnswers,
+    choiceQuestion
+  },
+  data() {
+    return {
+      id: this.$route.query.id,
+      courseid: this.$route.query.courseid,
+      userid: this.$route.query.userid,
+      oid: this.$route.query.oid,
+      org: this.$route.query.org,
+      role: this.$route.query.role,
+      stage: this.$route.query.stage,
+      task: this.$route.query.task,
+      tool: this.$route.query.tool,
+      type: "",
+      cid: this.$route.query.cid,
+      workData: {},
+      loadingUploadFile: false,
+      studentWork: null,
+      loading: false
+    };
+  },
+  watch: {
+    workData: {
+      deep: true,
+      handler(newValue) {
+        if (newValue) {
+          this.setWorkDataToWindow();
+        }
+      }
+    }
+  },
+  computed: {
+    renderedFormula() {
+      return function(val) {
+        try {
+          // 判断是否含有HTML标签,<tag ...>...</tag>
+          const hasTag = /<([a-zA-Z][\w\-]*)([^>]*)>([\s\S]*?)<\/\1>/g.test(
+            val
+          );
+          if (!hasTag) {
+            val = val.trim().replace(/[\u200B-\u200D\uFEFF]/g, "");
+
+            // 纯文本,整体渲染
+            try {
+              return katex.renderToString(val.trim(), {
+                throwOnError: false,
+                strict: false,
+                output: "htmlAndMathml"
+              });
+            } catch (e) {
+              return val; // 渲染失败原样输出
+            }
+          } else {
+            // 有标签,对每个标签内容渲染
+            return val.replace(
+              /<([a-zA-Z][\w\-]*)([^>]*)>([\s\S]*?)<\/\1>/g,
+              (match, tag, attrs, inner) => {
+                let html;
+                val = val.trim().replace(/[\u200B-\u200D\uFEFF]/g, "");
+                try {
+                  html = katex.renderToString(inner.trim(), {
+                    throwOnError: false,
+                    strict: false,
+                    output: "htmlAndMathml"
+                  });
+                } catch (e) {
+                  html = inner;
+                }
+                return `<${tag}${attrs}>${html}</${tag}>`;
+              }
+            );
+          }
+        } catch (e) {
+          console.error("KaTeX渲染错误:", e);
+          return val;
+        }
+      };
+    }
+  },
+  methods: {
+    getWorkData() {
+      if (!this.id) return console.log("无作业id");
+      let params = {
+        id: this.id
+      };
+      this.ajax
+        .get(this.$store.state.api + "select_workPageById", params)
+        .then(res => {
+          let _data = res.data[0];
+          if (_data.length) {
+            _data = _data[0];
+            _data.json = JSON.parse(_data.json);
+            if (_data.type == 15) {
+              _data.json.answer = "";
+              _data.json.fileList = [];
+            } else if (_data.type == 45) {
+              _data.json.testJson.forEach(item => {
+                if (item.type == "2") {
+                  item.userAnswer = [];
+                } else if (item.type == "1") {
+                  item.userAnswer = "";
+                }
+              });
+            }
+
+            this.workData = _data;
+            this.studentWorkToWorkData();
+          }
+        });
+    },
+    setWorkDataToWindow() {
+      if (this.workData.json) {
+        window.workData = JSON.parse(JSON.stringify(this.workData));
+      }
+    },
+    uploadImage() {
+      if (this.loadingUploadFile) return;
+      let input = document.createElement("input");
+      input.type = "file";
+      input.accept = "image/jpeg,image/png";
+      input.click();
+      input.onchange = e => {
+        let file = e.target.files[0];
+        if (file) {
+          if (file.size > 5 * 1024 * 1024) {
+            // 5MB
+            return this.$message.error("图片大小不能超过5MB");
+          }
+          let _type = file.type;
+          let _size = file.size;
+          this.loadingUploadFile = true;
+          this.uploadFile(file).then(res => {
+            let _file = {
+              name: file.name,
+              url: res.Location,
+              type: _type,
+              size: _size,
+              uploadTime: new Date().getTime()
+            };
+            if (["15"].includes(this.workData.type)) {
+              this.workData.json.fileList.push(_file);
+            }
+            this.$forceUpdate();
+            this.loadingUploadFile = false;
+          });
+        }
+      };
+    },
+    uploadFile(file) {
+      return new Promise(resolve => {
+        var credentials = {
+          accessKeyId: "AKIATLPEDU37QV5CHLMH",
+          secretAccessKey: "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"
+        }; //秘钥形式的登录上传
+        window.AWS.config.update(credentials);
+        window.AWS.config.region = "cn-northwest-1"; //设置区域
+
+        var bucket = new window.AWS.S3({ params: { Bucket: "ccrb" } }); //选择桶
+        var _this = this;
+
+        if (file) {
+          var params = {
+            Key:
+              file.name.split(".")[0] +
+              new Date().getTime() +
+              "." +
+              file.name.split(".")[file.name.split(".").length - 1],
+            ContentType: file.type,
+            Body: file,
+            "Access-Control-Allow-Credentials": "*",
+            ACL: "public-read"
+          }; //key可以设置为桶的相抵路径,Body为文件, ACL最好要设置
+          var options = {
+            partSize: 2048 * 1024 * 1024,
+            queueSize: 2,
+            leavePartsOnError: true
+          };
+          bucket
+            .upload(params, options)
+            .on("httpUploadProgress", function(evt) {
+              //这里可以写进度条
+              // console.log("Uploaded : " + parseInt((evt.loaded * 80) / evt.total) + '%');
+            })
+            .send(function(err, data) {
+              if (err) {
+                _this.$message.error("上传失败");
+                resolve(null);
+              } else {
+                resolve(data);
+              }
+            });
+        }
+      });
+    },
+    //预览图片
+    previewImage(url) {
+      this.$hevueImgPreview(url);
+    },
+    deleteFile(index) {
+      this.workData.json.fileList.splice(index, 1);
+      this.$forceUpdate();
+    },
+    submitWork(task) {
+      return new Promise(resolve => {
+        let params = [];
+        if (this.workData.type == "15") {
+          //问答题
+          params.push({
+            uid: this.userid,
+            cid: this.courseid,
+            stage: 0,
+            task: task,
+            tool: 0,
+            atool: "15",
+            content: encodeURIComponent(JSON.stringify(this.workData.json)),
+            type: "3"
+          });
+        } else if (this.workData.type == "45") {
+          //选择题
+          params.push({
+            uid: this.userid,
+            cid: this.courseid,
+            stage: 0,
+            task: task,
+            tool: 0,
+            atool: "45",
+            content: encodeURIComponent(JSON.stringify(this.workData.json)),
+            type: "8"
+          });
+        }
+        if (
+          ["3", "8"].includes(params[0].type) &&
+          params[0].uid &&
+          params[0].cid
+        ) {
+          this.loading = true;
+          this.ajax
+            .post(this.$store.state.api + "addCourseWorks_workPage", params)
+            .then(res => {
+              let _data = res.data[0];
+              this.loading = false;
+              if (_data.length > 0) {
+                let _id = _data[0].id;
+                resolve(_id);
+              } else {
+                resolve("");
+              }
+            })
+            .catch(err => {
+              console.log(err);
+              resolve("");
+              this.loading = false;
+            });
+        }
+      });
+    },
+    //选择题选择
+    chooseAnswer(index, index2) {
+      if (this.workData.json.testJson[index].type == "1") {
+        this.workData.json.testJson[index].userAnswer = index2;
+      } else if (this.workData.json.testJson[index].type == "2") {
+        if (this.workData.json.testJson[index].userAnswer.includes(index2)) {
+          this.workData.json.testJson[index].userAnswer.splice(
+            this.workData.json.testJson[index].userAnswer.indexOf(index2),
+            1
+          );
+        } else {
+          this.workData.json.testJson[index].userAnswer.push(index2);
+        }
+      }
+    },
+    //获取已经提交的作业
+    getSubmitWork() {
+      if (
+        this.userid &&
+        this.courseid &&
+        this.stage &&
+        this.task &&
+        this.tool
+      ) {
+        let params = {
+          uid: this.userid,
+          cid: this.courseid,
+          stage: this.stage,
+          task: this.task,
+          tool: this.tool
+        };
+        this.loading = true;
+        this.ajax
+          .get(
+            this.$store.state.api + "select_courseWorks_workPageData",
+            params
+          )
+          .then(res => {
+            let _data = res.data[0];
+            this.loading = false;
+            if (_data.length) {
+              _data = _data[0];
+              if (["15", "45"].includes(_data.atool)) {
+                let _work = JSON.parse(decodeURIComponent(_data.content));
+                this.studentWork = _work;
+                this.studentWorkToWorkData();
+              }else{
+                console.log("工具不一致")
+              }
+            }
+          })
+          .catch(err => {
+            this.loading = false;
+            console.error(err);
+          });
+      }
+    },
+    studentWorkToWorkData() {
+      if (this.studentWork && this.workData) {
+        console.log("studentWork", this.studentWork);
+        console.log("workData", this.workData);
+
+        let _work = JSON.parse(JSON.stringify(this.studentWork));
+        if (this.workData.type == "15") {
+          this.workData.json.answer = _work.answer;
+          this.workData.json.fileList = _work.fileList;
+        } else if (this.workData.type == "45") {
+          this.workData.json.testJson.forEach((item, index) => {
+            if (
+              item.type == _work.testJson[index].type &&
+              item.teststitle == _work.testJson[index].teststitle &&
+              JSON.stringify(item.checkList) ==
+                JSON.stringify(_work.testJson[index].checkList)
+            ) {
+              this.workData.json.testJson[index].userAnswer =
+                _work.testJson[index].userAnswer;
+            }
+          });
+        }
+        this.$forceUpdate();
+      }
+    },
+
+    //更新workData
+    changeWorkData(newValue){
+      console.log("changeWorkData",newValue)
+      this.workData.json = JSON.parse(newValue)
+    }
+  },
+  mounted() {
+    this.getWorkData();
+    this.getSubmitWork();
+    window.submitWork = this.submitWork;
+  }
+};
+</script>
+
+<style scoped>
+.workPage {
+  width: 100%;
+  height: 100%;
+  min-height: 100%;
+
+  background-color: #fff;
+  overflow: auto;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+}
+
+.wp_tool {
+  width: 100%;
+  height: auto;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  padding: 40px 0;
+}
+
+.wp_t15_title {
+  font-size: 40px;
+  font-weight: 300;
+  margin: 20px 0;
+  max-width: 50%;
+  min-width: 300px;
+  text-align: left;
+}
+
+.wp_type {
+  margin: 20px 0;
+  font-size: 1em;
+  color: #7b7b7b;
+}
+
+.wp_tl15_inputArea {
+  width: 50%;
+  min-width: 300px;
+  margin: 20px 0;
+}
+
+.wp_tl15_inputArea >>> textarea {
+  border-color: #ececec;
+  border-radius: 10px;
+  padding: 10px 20px;
+  box-shadow: 0 0 10px #ececec;
+}
+
+.wp_tl15_inputArea >>> textarea::placeholder {
+  color: #7f7f7f;
+}
+
+.wp_tl15_uploadFileArea {
+  width: 50%;
+  min-width: 300px;
+  height: auto;
+  display: flex;
+  align-items: center;
+  margin-bottom: 10px;
+}
+
+.wp_tl_btn {
+  width: auto;
+  height: auto;
+  padding: 12px 16px;
+  background-color: #f9f9f9;
+  border-radius: 10px;
+  border: 1px dashed #e5e5e5;
+  font-size: 14px;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  color: #474747;
+  cursor: pointer;
+  margin-right: 10px;
+  transition: 0.3s;
+}
+
+.wp_tl_btn:hover {
+  background-color: #ececec;
+}
+
+.wp_tl_btn > svg {
+  width: 15px;
+  height: 15px;
+  margin-right: 5px;
+}
+
+.wp_tl15_uploadFileArea > span {
+  font-size: 14px;
+  color: #686868;
+}
+
+.wp_tl15_fileList {
+  width: 50%;
+  min-width: 300px;
+  height: auto;
+  display: flex;
+  align-items: center;
+  flex-wrap: wrap;
+}
+
+.wp_tl15_fileList_item {
+  width: 150px;
+  height: 100px;
+  border-radius: 10px;
+  position: relative;
+  margin-right: 20px;
+}
+
+.wp_tl15_fileList_item:hover > svg {
+  display: block;
+}
+
+.wp_tl15_fileList_item > img {
+  width: 100%;
+  height: 100%;
+  object-fit: cover;
+  border-radius: 10px;
+  box-shadow: 0 0 10px #ececec;
+  margin: 10px;
+  cursor: pointer;
+}
+
+.wp_tl15_fileList_item > svg {
+  width: 20px;
+  height: 20px;
+  position: absolute;
+  right: -20px;
+  top: 1px;
+  cursor: pointer;
+  display: none;
+}
+
+/* 选择题 */
+
+.wp_tool45 {
+  width: 60%;
+  height: auto;
+}
+
+.wp_t45_title {
+  font-size: 3em;
+  font-weight: 300;
+  margin: 20px 0 40px 0;
+}
+
+.s_b_m_toolItem {
+  width: 100%;
+  height: auto;
+  margin-bottom: 40px;
+}
+
+.s_b_m_ti_option {
+  width: 100%;
+  height: auto;
+  padding: 15px 15px 15px 15px;
+  display: flex;
+  /* flex-wrap: wrap; */
+  background-color: #f3f7fd;
+  border-radius: 30px;
+  margin: 10px 0 10px 0px;
+  box-sizing: border-box;
+  cursor: pointer;
+}
+
+.s_b_m_ti_option > span > img {
+  max-height: 150px;
+  border-radius: 2px;
+  cursor: pointer;
+}
+
+.s_b_m_ti_o_btn {
+  width: 20px;
+  height: 100%;
+  min-height: 20px;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  margin-right: 10px;
+}
+
+.s_b_m_ti_o_btn > span {
+  width: 20px;
+  height: 20px;
+  display: block;
+  box-sizing: border-box;
+  border: solid 1px #3681fc;
+  overflow: hidden;
+}
+
+.s_b_m_ti_o_btn > span > span {
+  width: 100%;
+  height: 100%;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  background-color: #3681fc;
+  position: relative;
+}
+
+.s_b_m_ti_o_btn1 {
+  border-radius: 50%;
+}
+
+.s_b_m_ti_o_btn1 > span::after {
+  content: "";
+  width: 8px;
+  height: 8px;
+  position: absolute;
+  background-color: #fff;
+  border-radius: 50%;
+}
+
+.s_b_m_ti_o_btn2 {
+  border-radius: 2px;
+}
+
+.s_b_m_ti_o_btn2 > span::after {
+  content: "";
+  width: 8px;
+  height: 8px;
+  position: absolute;
+  background-color: #fff;
+}
+
+.s_b_m_ti_o_choice {
+  border: solid 1px #3681fc;
+}
+
+.s_b_m_ti_title {
+  display: flex;
+  align-items: flex-start;
+}
+
+.s_b_m_ti_title > span:nth-of-type(1) {
+  font-size: 30px;
+  font-weight: bold;
+  color: #3681fc;
+  min-height: 30px;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  margin-top: -3px;
+}
+
+.s_b_m_ti_title > svg {
+  width: 30px;
+  height: 30px;
+  min-width: 30px;
+  min-height: 30px;
+  margin: 0 10px 0 0px;
+}
+
+.s_b_m_ti_title > span:nth-of-type(2) {
+  font-size: 20px;
+  font-weight: bold;
+  display: flex;
+  flex-wrap: wrap;
+  align-items: center;
+  min-height: 30px;
+  line-height: 30px;
+  color: #1f1f1f;
+}
+
+.s_b_m_ti_title > div {
+  font-size: 30px;
+  font-weight: bold;
+}
+
+/* 选择题 */
+</style>

+ 18 - 0
src/router/index.js

@@ -159,8 +159,10 @@ import teadTest from '@/components/pages/liyuan/page/teadTest'
 import Listudent from '@/components/pages/liyuan/page/student'
 import safeTest from '@/components/pages/liyuan/page/safeTest'
 import workPage from '@/components/pages/workPage/index'
+import workPageNew from '@/components/pages/workPage/index_new'
 import pptEasy from '@/components/pages/pptEasy/addCourse'
 import noticeCenter from '@/components/pages/noticeCenter/index'
+import PersonnelManagement from "@/components/pages/PersonnelManagement";
 
 // 全局修改默认配置,点击空白处不能关闭弹窗
 ElementUI.Dialog.props.closeOnClickModal.default = false
@@ -893,6 +895,14 @@ export default new Router({
       requireAuth: '' // 不需要鉴权
     }
   },
+    {
+      path: "/PersonnelManagement",
+      name: "PersonnelManagement",
+      component: PersonnelManagement,
+      meta: {
+        requireAuth: "" // 不需要鉴权
+      }
+    },
   {
     path: '/learnAna',
     name: 'learnAna',
@@ -1383,6 +1393,14 @@ export default new Router({
       requireAuth: '' // 是否需要判断是否登录,这里是需要判断
     }
   },
+  {
+    path: '/workPageNew',
+    name: 'workPageNew',
+    component: workPageNew,
+    meta: {
+      requireAuth: '' // 是否需要判断是否登录,这里是需要判断
+    }
+  },
   {
     path:"/pptEasy",
     name:"pptEasy",

Някои файлове не бяха показани, защото твърде много файлове са промени