batchCreationClassDialog.vue 46 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500
  1. <template>
  2. <div class="batchCreationClassDialog">
  3. <el-dialog
  4. :visible.sync="show"
  5. width="100%"
  6. height="100%"
  7. fullscreen
  8. :modal="false"
  9. :close-on-click-modal="true"
  10. :show-close="false"
  11. >
  12. <div class="box">
  13. <div class="b_back">
  14. <div class="b_b_left" @click="close()">
  15. <img src="../../../../assets/icon/classroomObservation/right.svg" />
  16. <span>返回</span>
  17. </div>
  18. <div class="b_b_right">
  19. <el-button type="primary" size="small" @click="uploadFile"
  20. >上传文件</el-button
  21. >
  22. </div>
  23. </div>
  24. <div class="b_head">
  25. <span>已上传的课堂实录</span>
  26. </div>
  27. <div class="b_nav">
  28. <div class="b_n_left">
  29. <span
  30. :class="{ b_n_l_active: selectStatus == item.value }"
  31. v-for="item in statusList"
  32. :key="item.value"
  33. @click="changeStatus(item.value)"
  34. >{{ item.label }}</span
  35. >
  36. </div>
  37. <div class="b_n_right">
  38. <span @click="test">总计{{ dataList.length }}个</span>
  39. </div>
  40. </div>
  41. <div class="b_bottom">
  42. <div class="b_b_operation">
  43. <div class="b_b_o_left">
  44. <span
  45. >当前进度 {{ progress }}/{{
  46. dataList.filter(
  47. i =>
  48. selectStatus == "99" ||
  49. statusList
  50. .find(i => i.value == selectStatus)
  51. .allow.includes(i.status)
  52. ).length
  53. }}</span
  54. >
  55. </div>
  56. <div class="b_b_o_right">
  57. <div>
  58. <el-checkbox v-model="selectAll" :indeterminate="indeterminate"
  59. >全选</el-checkbox
  60. >
  61. </div>
  62. <span>
  63. <span @click="exportDoc" style="color:#409EFF">批量导出doc</span>
  64. </span>
  65. <span>
  66. <span @click="delSelectBtn" style="color: red;">删除</span>
  67. <!-- <img
  68. @click="delSelectBtn"
  69. src="../../../../assets/icon/classroomObservation/del2.svg"
  70. /> -->
  71. </span>
  72. </div>
  73. </div>
  74. <div class="b_b_list">
  75. <batchClassCard
  76. v-for="item in dataList"
  77. :data="item"
  78. :isSelect="selectList.includes(item.id)"
  79. :key="item.id"
  80. v-show="
  81. selectStatus === '99' ||
  82. statusList
  83. .find(i => i.value === selectStatus)
  84. .allow.includes(item.status)
  85. "
  86. @changeChecked="changeCardChecked"
  87. @editBaseMessage="editBaseMessage"
  88. @changeData="changeData"
  89. @taskBtn="taskBtn"
  90. @goToEdit="goToEdit"
  91. />
  92. </div>
  93. </div>
  94. </div>
  95. <uploadFileToCreateClassDialog
  96. ref="uploadFileToCreateClassDialogRef"
  97. @success="uploadFileSuccess"
  98. />
  99. <editBaseMessageDialog
  100. ref="editBaseMessageDialogRef"
  101. @success="editBaseMessageSuccess"
  102. />
  103. </el-dialog>
  104. <!-- 录音转文字 -->
  105. <iframe
  106. allow="camera *; microphone *;display-capture;midi;encrypted-media;"
  107. src="https://beta.cloud.cocorobo.cn/browser/public/index.html"
  108. ref="iframeRef"
  109. v-show="false"
  110. ></iframe>
  111. </div>
  112. </template>
  113. <script>
  114. import batchClassCard from "../newComponents/batchClassCard.vue";
  115. import uploadFileToCreateClassDialog from "./uploadFileToCreateClassDialog.vue";
  116. import editBaseMessageDialog from "./editBaseMessageDialog.vue";
  117. import { v4 as uuidv4 } from "uuid";
  118. import { toolMixin } from "../tools/mixin";
  119. import JSZip from "jszip";
  120. export default {
  121. mixins: [toolMixin],
  122. components: {
  123. batchClassCard,
  124. uploadFileToCreateClassDialog,
  125. editBaseMessageDialog
  126. },
  127. data() {
  128. return {
  129. statusList: [
  130. { label: "全部", value: "99", allow: [] },
  131. { label: "已完成", value: "2", allow: ["2"] },
  132. { label: "处理中", value: "1", allow: ["1"] },
  133. { label: "等待处理", value: "0", allow: ["0"] },
  134. { label: "待开始", value: "3", allow: ["3"] }
  135. ],
  136. userId: this.$route.query["userid"],
  137. selectStatus: "99",
  138. show: false,
  139. selectList: [],
  140. dataList: [],
  141. nowDoTaskId: [],
  142. dialogTagDataList: []
  143. };
  144. },
  145. computed: {
  146. selectAll: {
  147. get() {
  148. let _result = false;
  149. let _data = this.dataList.filter(
  150. i =>
  151. this.selectStatus === "99" ||
  152. this.statusList
  153. .find(i2 => i2.value === this.selectStatus)
  154. .allow.includes(i.status)
  155. );
  156. if (_data.length > 0 && _data.length === this.selectList.length) {
  157. _result = true;
  158. }
  159. return _result;
  160. },
  161. set(value) {
  162. if (value) {
  163. this.selectList = this.dataList
  164. .filter(
  165. i =>
  166. this.selectStatus === "99" ||
  167. this.statusList
  168. .find(i2 => i2.value === this.selectStatus)
  169. .allow.includes(i.status)
  170. )
  171. .map(i => i.id);
  172. this.$forceUpdate();
  173. } else {
  174. this.selectList = [];
  175. }
  176. }
  177. },
  178. indeterminate() {
  179. let _result = false;
  180. let _data = this.dataList.filter(
  181. i =>
  182. this.selectStatus === "99" ||
  183. this.statusList
  184. .find(i2 => i2.value === this.selectStatus)
  185. .allow.includes(i.status)
  186. );
  187. if (_data.length > this.selectList.length && this.selectList.length > 0) {
  188. _result = true;
  189. }
  190. return _result;
  191. },
  192. progress() {
  193. return this.dataList.filter(
  194. i =>
  195. i.status == "2" &&
  196. (this.selectStatus == "99" ||
  197. this.statusList
  198. .find(i2 => i2.value == this.selectStatus)
  199. .allow.includes(i.status))
  200. ).length;
  201. }
  202. },
  203. methods: {
  204. open() {
  205. this.show = true;
  206. },
  207. close() {
  208. this.show = false;
  209. },
  210. init() {},
  211. changeStatus(newValue) {
  212. this.selectStatus = newValue;
  213. this.selectList = [];
  214. },
  215. uploadFile() {
  216. this.$refs.uploadFileToCreateClassDialogRef.open();
  217. },
  218. //批量上传文件成功
  219. async uploadFileSuccess(data) {
  220. this.$refs.uploadFileToCreateClassDialogRef.close();
  221. let { fileList, automaticCoding, analysisTemplate } = data;
  222. this.loading = true;
  223. let fileDataList = fileList.map(i => i.successData);
  224. let _tempData = await this.getTemplateData(analysisTemplate[1]);
  225. let _analysisList = JSON.parse(_tempData.tips);
  226. let tagList = _analysisList.find(i => i.isOtherData);
  227. if (!tagList) {
  228. tagList = [
  229. { value: 0, name: "通用课堂分析", loading: false },
  230. { value: 1, name: "学科课堂分析", loading: false },
  231. { value: 2, name: "扩展分析", loading: false }
  232. ];
  233. } else {
  234. tagList = tagList.dialogTagList;
  235. }
  236. let batch = uuidv4();
  237. _analysisList = _analysisList.filter(
  238. i => !i.isOtherData && i.jsonData.name != "词频词汇分析"
  239. );
  240. let promiseList = [];
  241. fileDataList.forEach(i => {
  242. let data = {
  243. id: uuidv4(),
  244. create_at: "2025-05-07 16.05.03",
  245. remarks: "",
  246. batch: batch,
  247. status: "0",
  248. createId: "",
  249. jsonData: {
  250. file_ids: "",
  251. baseMessage: {
  252. courseName: i.name,
  253. teacherName: "老师",
  254. time: this.getFileLastUpdateTime(i.fileObj),
  255. grade: "小学五年级",
  256. subject: "科学",
  257. textbook: "教科版",
  258. studentNum: 45,
  259. imageList: {
  260. fileList: [],
  261. fileList1: [],
  262. fileList2: [],
  263. fileList3: [],
  264. name: "课堂记录",
  265. NephogramList: [],
  266. videoList: []
  267. }
  268. },
  269. tagList: tagList,
  270. steps: [],
  271. analysisList: _analysisList,
  272. fileData: i,
  273. automaticCoding: automaticCoding
  274. }
  275. };
  276. if (i.type == "text/plain") {
  277. data.jsonData.steps = [
  278. {
  279. type: "uploadFile",
  280. text: "上传文件",
  281. status: "1"
  282. },
  283. {
  284. type: "transcription",
  285. text: "文本转录",
  286. status: "0",
  287. progress: "0"
  288. },
  289. {
  290. type: "getFileIds",
  291. text: "获取文件fileid",
  292. status: "0"
  293. },
  294. {
  295. type:"getWordCloudMap",
  296. text:"获取词云图",
  297. status:"0"
  298. },
  299. {
  300. type: "generateReport",
  301. text: "生成报告",
  302. status: "0",
  303. progress: "0"
  304. },
  305. {
  306. type: "createClass",
  307. text: "创建课堂",
  308. status: "0",
  309. progress: "0"
  310. }
  311. ];
  312. } else if (["audio/wav",'audio/x-m4a','audio/mpeg'].includes(i.type) ) {
  313. data.jsonData.baseMessage.imageList.fileList = [
  314. {
  315. name: i.name,
  316. status: "success",
  317. url: i.url,
  318. uid: "1"
  319. }
  320. ];
  321. data.jsonData.steps = [
  322. {
  323. type: "uploadFile",
  324. text: "上传文件",
  325. status: "1"
  326. },
  327. {
  328. type: "transcription",
  329. text: "文本转录",
  330. status: "0",
  331. progress: "0"
  332. }
  333. ];
  334. if (data.jsonData.automaticCoding) {
  335. data.jsonData.steps.push({
  336. type: "automaticCoding",
  337. text: "自动编码",
  338. status: "0",
  339. progress: "0"
  340. });
  341. }
  342. data.jsonData.steps.push(
  343. ...[
  344. {
  345. type: "getFileIds",
  346. text: "获取文件fileid",
  347. status: "0"
  348. },
  349. {
  350. type:"getWordCloudMap",
  351. text:"获取词云图",
  352. status:"0"
  353. },
  354. {
  355. type: "generateReport",
  356. text: "生成报告",
  357. status: "0",
  358. progress: "0"
  359. },
  360. {
  361. type: "createClass",
  362. text: "创建课堂",
  363. status: "0",
  364. progress: "0"
  365. }
  366. ]
  367. );
  368. } else if (i.type == "video/mp4") {
  369. data.jsonData.baseMessage.imageList.videoList = [
  370. {
  371. name: i.name,
  372. status: "success",
  373. url: i.url,
  374. uid: "1"
  375. }
  376. ];
  377. data.jsonData.steps = [
  378. {
  379. type: "uploadFile",
  380. text: "上传文件",
  381. status: "1"
  382. },
  383. {
  384. type: "getVideoVoice",
  385. text: "视频提取音频",
  386. status: "0",
  387. progress: "0"
  388. },
  389. {
  390. type: "transcription",
  391. text: "文本转录",
  392. status: "0",
  393. progress: "0"
  394. }
  395. ];
  396. if (data.jsonData.automaticCoding) {
  397. data.jsonData.steps.push({
  398. type: "automaticCoding",
  399. text: "自动编码",
  400. status: "0",
  401. progress: "0"
  402. });
  403. }
  404. data.jsonData.steps.push(
  405. ...[
  406. {
  407. type: "getFileIds",
  408. text: "获取文件fileid",
  409. status: "0"
  410. },
  411. {
  412. type:"getWordCloudMap",
  413. text:"获取词云图",
  414. status:"0"
  415. },
  416. {
  417. type: "generateReport",
  418. text: "生成报告",
  419. status: "0",
  420. progress: "0"
  421. },
  422. {
  423. type: "createClass",
  424. text: "创建课堂",
  425. status: "0",
  426. progress: "0"
  427. }
  428. ]
  429. );
  430. }
  431. promiseList.push(
  432. new Promise((resolve, reject) => {
  433. // 本地保存fileObj
  434. const fileObj = data.jsonData.fileData.fileObj;
  435. delete data.jsonData.fileData.fileObj;
  436. const params = [
  437. {
  438. remarks: data.remarks,
  439. status: "3",
  440. json: JSON.stringify(data.jsonData),
  441. batch: data.batch,
  442. createId: data.createId,
  443. userId: this.userId
  444. }
  445. ];
  446. console.log(params);
  447. this.ajax
  448. .post(this.$store.state.api + "insert_classroomTask", params)
  449. .then(res => {
  450. const _data = res.data[0][0];
  451. if (_data.id) {
  452. data.jsonData.fileData.fileObj = fileObj;
  453. data.id = _data.id;
  454. this.dataList.push(data);
  455. }
  456. resolve();
  457. })
  458. .catch(err => {
  459. console.error(err);
  460. reject(err);
  461. });
  462. })
  463. );
  464. });
  465. console.log(promiseList);
  466. Promise.all(promiseList)
  467. .then(res => {
  468. this.$message.success("创建成功");
  469. if(!this.dataList.find(i =>i.status == 1)){
  470. this.startTask(this.dataList.find(i =>i.status === "0").id);
  471. }
  472. })
  473. .catch(err => {
  474. console.log("创建出错", err);
  475. });
  476. },
  477. //获取模板的数据
  478. getTemplateData(tid) {
  479. return new Promise(resolve => {
  480. let params = {
  481. uid: this.userId,
  482. cid: tid,
  483. st: 0
  484. };
  485. this.ajax
  486. .get(this.$store.state.api + "selectClassroomTemplateDetail", params)
  487. .then(res => {
  488. let _data = res.data[0][0];
  489. resolve(_data);
  490. });
  491. });
  492. },
  493. changeCardChecked({ type = 0, id }) {
  494. if (type === 0 && !this.selectList.includes(id)) {
  495. this.selectList.push(id);
  496. } else if (type === 1 && this.selectList.push(id)) {
  497. this.selectList = this.selectList.filter(i => i != id);
  498. }
  499. },
  500. //修改课堂的baseMessage按钮
  501. editBaseMessage(id) {
  502. let _data = this.dataList.find(i => i.id === id);
  503. if (_data) {
  504. this.$refs.editBaseMessageDialogRef.open({
  505. editId: _data.id,
  506. message: _data.jsonData.baseMessage
  507. });
  508. } else {
  509. this.$message.error("未查询到该数据");
  510. }
  511. },
  512. //修改课堂的baseMessage
  513. editBaseMessageSuccess({ editId, message }) {
  514. if (editId) {
  515. let _editorBarData = null
  516. let _transcriptionData = null;
  517. if(this.dataList.find(i=>i.id===editId).jsonData.baseMessage.editorBarData){
  518. _editorBarData = this.dataList.find(i=>i.id===editId).jsonData.baseMessage.editorBarData;
  519. }
  520. if(this.dataList.find(i=>i.id===editId).jsonData.baseMessage.transcriptionData){
  521. _transcriptionData = this.dataList.find(i=>i.id===editId).jsonData.baseMessage.transcriptionData;
  522. }
  523. this.dataList.find(i => i.id === editId).jsonData.baseMessage = message;
  524. if(_editorBarData){
  525. this.dataList.find(i=>i.id===editId).jsonData.baseMessage.editorBarData = _editorBarData;
  526. }
  527. if(_transcriptionData){
  528. this.dataList.find(i=>i.id===editId).jsonData.baseMessage.transcriptionData = _transcriptionData;
  529. }
  530. this.$forceUpdate();
  531. this.$refs.editBaseMessageDialogRef.close();
  532. this.updateTask(editId);
  533. }
  534. },
  535. // 删除选择的数据
  536. delSelectBtn() {
  537. let _delList = this.dataList.filter(
  538. i =>
  539. this.selectList.includes(i.id) &&
  540. (this.selectStatus === "99" ||
  541. this.statusList
  542. .find(i2 => i2.value === this.selectStatus)
  543. .allow.includes(i.status))
  544. );
  545. if (_delList.length <= 0) return this.$message.info("请先选择列表");
  546. this.$confirm("您确定要删除选中的数据吗?", "提示", {
  547. confirmButtonText: "确定",
  548. cancelButtonText: "取消",
  549. type: "warning"
  550. })
  551. .then(() => {
  552. // 确定删除
  553. let params = [
  554. {
  555. idList: _delList.map(i => i.id).join(","),
  556. userId: this.userId
  557. }
  558. ];
  559. this.ajax
  560. .post(this.$store.state.api + "delete_classroomTask", params)
  561. .then(res => {
  562. if (res.data > 0) {
  563. this.$message.success("删除成功");
  564. this.dataList = this.dataList.filter(
  565. i => !_delList.find(del => del.id === i.id)
  566. );
  567. this.selectList = [];
  568. }
  569. })
  570. .catch(err => {
  571. console.log(err);
  572. this.$message.error("删除失败");
  573. });
  574. })
  575. .catch(() => {
  576. // 取消删除
  577. });
  578. },
  579. //获取任务列表
  580. getTaskList() {
  581. let params = {
  582. userId: this.userId
  583. };
  584. this.ajax
  585. .get(this.$store.state.api + "select_classroomTask", params)
  586. .then(res => {
  587. let _data = res.data[0];
  588. if (_data.length > 0) {
  589. _data.forEach(i => (i.jsonData = JSON.parse(i.jsonData)));
  590. this.dataList = _data;
  591. }
  592. });
  593. },
  594. //获取所有的模块分析
  595. getDialogTagDataList() {
  596. let params = {
  597. uid: this.userId
  598. };
  599. this.ajax
  600. .get(this.$store.state.api + "select_smodel", params)
  601. .then(res => {
  602. let _result = res.data[0];
  603. this.dialogTagDataList = _result;
  604. })
  605. .catch(e => {
  606. console.log(e);
  607. this.$message.error("获取模块分析列表失败");
  608. });
  609. },
  610. updateTask(id) {
  611. return new Promise((resolve, reject) => {
  612. let _data = this.dataList.find(i => i.id === id);
  613. if (_data) {
  614. const dataCopy = JSON.parse(JSON.stringify(_data));
  615. if (dataCopy.jsonData.fileData.fileObj) {
  616. delete dataCopy.jsonData.fileData.fileObj;
  617. }
  618. if (
  619. dataCopy.jsonData.baseMessage.editorBarData &&
  620. dataCopy.jsonData.baseMessage.editorBarData.content
  621. ) {
  622. delete dataCopy.jsonData.baseMessage.editorBarData.content;
  623. }
  624. if (
  625. dataCopy.jsonData.baseMessage.editorBarData &&
  626. dataCopy.jsonData.baseMessage.editorBarData.tableList
  627. ) {
  628. delete dataCopy.jsonData.baseMessage.editorBarData.tableList;
  629. }
  630. if(dataCopy.jsonData.errorMessage){
  631. delete dataCopy.jsonData.errorMessage;
  632. }
  633. console.log("dataCopy", dataCopy);
  634. let params = [
  635. {
  636. id: dataCopy.id,
  637. userId: this.userId,
  638. remarks: dataCopy.remarks,
  639. status: ["0", "1"].includes(dataCopy.status)
  640. ? "3"
  641. : dataCopy.status,
  642. json: JSON.stringify(dataCopy.jsonData),
  643. createId: dataCopy.createId,
  644. batch: dataCopy.batch
  645. }
  646. ];
  647. this.ajax
  648. .post(this.$store.state.api + "update_classroomTask", params)
  649. .then(res => {
  650. if (res.data == 1) {
  651. console.log("修改任务成功");
  652. resolve();
  653. } else {
  654. reject();
  655. this.$message.error("修改任务失败");
  656. }
  657. })
  658. .catch(err => {
  659. console.log(err);
  660. this.$message.error("修改任务失败");
  661. reject();
  662. });
  663. }
  664. });
  665. },
  666. changeData({ field, data }) {
  667. let _index = this.dataList.findIndex(i => i.id === data.id);
  668. if (_index != -1) {
  669. if (this.dataList[_index][field] != data[field]) {
  670. this.dataList[_index][field] = data[field];
  671. this.updateTask(this.dataList[_index].id);
  672. }
  673. }
  674. },
  675. taskBtn(obj) {
  676. let { type, id } = obj;
  677. if (type === "startTask" && id) {
  678. // this.startTask(id);
  679. if (
  680. this.dataList.some(i => i.status === "1") &&
  681. this.dataList.find(i => i.id === id).status === "0"
  682. ) {
  683. this.$confirm(
  684. "您确定要开始该任务嘛?其他已开始的任务会暂停。",
  685. "提示",
  686. {
  687. confirmButtonText: "确定",
  688. cancelButtonText: "取消",
  689. type: "warning"
  690. }
  691. )
  692. .then(() => {
  693. this.startTask(id);
  694. })
  695. .catch(() => {
  696. console.log("不暂停");
  697. });
  698. } else {
  699. this.startTask(id);
  700. }
  701. } else if (type === "stopTask" && id) {
  702. this.$confirm("您确定要停止该任务吗?", "提示", {
  703. confirmButtonText: "确定",
  704. cancelButtonText: "取消",
  705. type: "warning"
  706. })
  707. .then(() => {
  708. this.stopTask(id);
  709. })
  710. .catch(() => {
  711. console.log("不暂停");
  712. });
  713. } else if (type === "pauseTask" && id) {
  714. this.$confirm("您确定要暂停该任务吗?", "提示", {
  715. confirmButtonText: "确定",
  716. cancelButtonText: "取消",
  717. type: "warning"
  718. })
  719. .then(() => {
  720. this.pauseTask(id);
  721. })
  722. .catch(() => {
  723. console.log("不暂停");
  724. });
  725. }
  726. },
  727. async startTask(id) {
  728. let _isStartTaskIndex = this.dataList.findIndex(i => i.status === "1");
  729. let _needStartTaskIndex = this.dataList.findIndex(i => i.id === id);
  730. if (_isStartTaskIndex === -1) {
  731. //没有任务在进行,直接开始处理
  732. this.dataList[_needStartTaskIndex].status = "1"; //处理中
  733. } else if (
  734. this.dataList[_needStartTaskIndex].status === "3" &&
  735. _isStartTaskIndex !== -1
  736. ) {
  737. //有任务在进行,且这个任务是从待开始状态到开始状态,等待处理
  738. this.dataList[_needStartTaskIndex].status = "0";
  739. } else if (
  740. _isStartTaskIndex !== -1 &&
  741. this.dataList[_needStartTaskIndex].status === "0"
  742. ) {
  743. //有任务在进行,且这个任务是从等待状态到开始状态,停止现任务,开始新任务
  744. this.nowDoTaskId = this.nowDoTaskId.filter(
  745. i => i !== this.dataList[_isStartTaskIndex].id
  746. );
  747. this.dataList[_isStartTaskIndex].status = "0"; //
  748. this.dataList[_needStartTaskIndex].status = "1"; //处理中
  749. }
  750. if (
  751. !this.nowDoTaskId.includes(this.dataList.find(i => i.status === "1").id)
  752. ) {
  753. let _startData = JSON.parse(
  754. JSON.stringify(this.dataList.find(i => i.status === "1"))
  755. );
  756. if (
  757. this.dataList.find(i => i.id === _startData.id).jsonData.fileData
  758. .fileObj
  759. ) {
  760. _startData.jsonData.fileData.fileObj = this.dataList.find(
  761. i => i.id === _startData.id
  762. ).jsonData.fileData.fileObj;
  763. }
  764. this.nowDoTaskId.push(_startData.id);
  765. let _stepList = _startData.jsonData.steps;
  766. for (let i = 0; i < _stepList.length; i++) {
  767. //按顺序处理任务
  768. let _step = _stepList[i];
  769. console.log(_step);
  770. if(!this.nowDoTaskId.includes(_startData.id))break;
  771. if (_step.status === "1") continue;
  772. if (_step.type === "uploadFile") continue;
  773. if (_step.type === "getVideoVoice") {
  774. //视频提取音频
  775. _stepList[i].status = "2";
  776. this.dataList.find(
  777. i => i.id === _startData.id
  778. ).jsonData.steps = _stepList;
  779. let _fileData = _startData.jsonData.fileData;
  780. let audioFile = await this.getVideoToVoiceAndUploadMixin(_fileData);
  781. if(audioFile.data==3){
  782. this.dataList.find(
  783. i => i.id === _startData.id
  784. ).jsonData.errorMessage = {content:"视频提取音频失败",err:audioFile.err};
  785. this.dataList.find(
  786. i => i.id === _startData.id
  787. ).status = "3"
  788. break;
  789. }
  790. if(!this.nowDoTaskId.includes(_startData.id))break;
  791. _startData.jsonData.fileData.videoUrl = _fileData.url;
  792. _startData.jsonData.fileData.fileObj = audioFile.fileObj;
  793. _startData.jsonData.fileData.url = audioFile.audioUrl.Location;
  794. _startData.jsonData.baseMessage.imageList.fileList = [
  795. {
  796. name: _fileData.name,
  797. status: "success",
  798. url: audioFile.Location,
  799. uid: "1"
  800. }
  801. ];
  802. _stepList[i].status = "1";
  803. this.dataList.find(i => i.id === _startData.id).jsonData =
  804. _startData.jsonData;
  805. this.updateTask(_startData.id);
  806. _startData.jsonData = JSON.parse(
  807. JSON.stringify(
  808. this.dataList.find(i => i.id === _startData.id).jsonData
  809. )
  810. );
  811. _startData.jsonData.fileData.fileObj = audioFile.fileObj;//防止文件因为json失效
  812. console.log("data👉",JSON.parse(JSON.stringify(_startData)))
  813. console.log(`${_startData.id}:已完成视频转音频`);
  814. } else if (_step.type === "transcription") {
  815. //文本转录
  816. const fileData = _startData.jsonData.fileData;
  817. if (fileData.type === "text/plain") {
  818. //txt文件
  819. _stepList[i].status = "2";
  820. this.dataList.find(
  821. i => i.id === _startData.id
  822. ).jsonData.steps = _stepList;
  823. let { editorBarData } = await this.getTextContentMixin(fileData);
  824. if(!this.nowDoTaskId.includes(_startData.id))break;
  825. this.dataList.find(
  826. i => i.id === _startData.id
  827. ).jsonData.baseMessage.editorBarData = editorBarData;
  828. _stepList[i].status = "1";
  829. this.dataList.find(
  830. i => i.id === _startData.id
  831. ).jsonData.steps = _stepList;
  832. this.updateTask(_startData.id);
  833. _startData.jsonData = JSON.parse(
  834. JSON.stringify(
  835. this.dataList.find(i => i.id === _startData.id).jsonData
  836. )
  837. );
  838. console.log(`${_startData.id}:已获取转录文稿(txt)`);
  839. console.log("data👉",JSON.parse(JSON.stringify(_startData)))
  840. } else if (
  841. ['video/mp4','audio/wav','audio/x-m4a','audio/mpeg'].includes(fileData.type)
  842. ) {
  843. //mp4与wav文件
  844. _stepList[i].status = "2";
  845. this.dataList.find(
  846. i => i.id === _startData.id
  847. ).jsonData.steps = _stepList;
  848. let _file = _startData.jsonData.fileData.fileObj;
  849. if(!_file && JSON.stringify(_file)!="{}"){
  850. let fileBody = await this.getFileBody(_startData.jsonData.fileData.url);
  851. let _type = _startData.jsonData.fileData.type.split('/')[1];
  852. if(_type=='x-m4a'){
  853. _type="m4a"
  854. }else if(_type=="mpeg"){
  855. _type = "mp3"
  856. }
  857. _file = new File([fileBody.data], `audio.${_type}`, { type: _startData.jsonData.fileData.type });
  858. }
  859. if (["audio/x-m4a","audio/mpeg"].includes(_file.type)) {
  860. let _data = await this.audioToWavMixin(_file);
  861. if(_data!==1){
  862. _file = _data.data;
  863. }else{
  864. console.log("报错👉",_data)
  865. }
  866. }
  867. console.log("转录文件",_file)
  868. let {
  869. transcriptionContent,
  870. editorBarData
  871. } = await this.wavAudioToTextAndObjMixin(_file);
  872. this.dataList.find(
  873. i => i.id === _startData.id
  874. ).jsonData.baseMessage.transcriptionData = transcriptionContent;
  875. this.dataList.find(
  876. i => i.id === _startData.id
  877. ).jsonData.baseMessage.editorBarData = editorBarData;
  878. _stepList[i].status = "1";
  879. this.dataList.find(
  880. i => i.id === _startData.id
  881. ).jsonData.steps = _stepList;
  882. this.updateTask(_startData.id);
  883. _startData.jsonData = JSON.parse(
  884. JSON.stringify(
  885. this.dataList.find(i => i.id === _startData.id).jsonData
  886. )
  887. );
  888. console.log(`${_startData.id}:已获取转录文稿(mp4/wav)`);
  889. }
  890. } else if (_step.type === "automaticCoding") {
  891. if (_startData.jsonData.automaticCoding) {
  892. _stepList[i].status = "2";
  893. this.dataList.find(
  894. i => i.id === _startData.id
  895. ).jsonData.steps = _stepList;
  896. //选择了字段编码
  897. let _content =
  898. _startData.jsonData.baseMessage.editorBarData.content;
  899. let _tableList =
  900. _startData.jsonData.baseMessage.editorBarData.table;
  901. if (!_content) {
  902. _content = await this.getFile(
  903. _startData.jsonData.baseMessage.editorBarData.url
  904. );
  905. _content = _content.data;
  906. this.dataList.find(
  907. i => i.id === _startData.id
  908. ).jsonData.baseMessage.editorBarData.content = _content;
  909. }
  910. if(!_tableList){
  911. let _result = [];
  912. let _data = _content;
  913. let _div = document.createElement("div");
  914. _div.innerHTML = _data;
  915. let _tableRows = _div.querySelectorAll(`table tbody tr`);
  916. _tableRows.forEach((i, index) => {
  917. if (index == 0) return;
  918. let obj = {
  919. index: i.cells[0].textContent,
  920. startTime: i.cells[1].textContent,
  921. endTime: i.cells[2].textContent,
  922. value: i.cells[3].textContent,
  923. time: i.cells[4].textContent,
  924. role: i.cells[5] ? i.cells[5].textContent : "",
  925. code: i.cells[6] ? i.cells[6].textContent : ""
  926. };
  927. _result.push(obj);
  928. });
  929. _tableList = _result;
  930. }
  931. let { editorBarData} = await this.automaticCodingMixin({ tableList: _tableList});
  932. if(!this.nowDoTaskId.includes(_startData.id))break;
  933. _stepList[i].status = "1";
  934. this.dataList.find(i => i.id === _startData.id).jsonData = _startData.jsonData;
  935. this.dataList.find(
  936. i => i.id === _startData.id
  937. ).jsonData.baseMessage.editorBarData = editorBarData;
  938. this.dataList.find(
  939. i => i.id === _startData.id
  940. ).jsonData.steps = _stepList;
  941. this.updateTask(_startData.id);
  942. _startData.jsonData = JSON.parse(
  943. JSON.stringify(
  944. this.dataList.find(i => i.id === _startData.id).jsonData
  945. )
  946. );
  947. console.log("data👉",JSON.parse(JSON.stringify(_startData)))
  948. console.log(`${_startData.id}:已获完成自动编码`);
  949. } else {
  950. _stepList[i].status = "1";
  951. this.dataList.find(
  952. i => i.id === _startData.id
  953. ).jsonData.steps = _stepList;
  954. this.updateTask(_startData.id);
  955. _startData.jsonData = JSON.parse(
  956. JSON.stringify(
  957. this.dataList.find(i => i.id === _startData.id).jsonData
  958. )
  959. );
  960. }
  961. } else if (_step.type === "getFileIds") {
  962. //文件获取fileId
  963. _stepList[i].status = "2";
  964. this.dataList.find(
  965. i => i.id === _startData.id
  966. ).jsonData.steps = _stepList;
  967. let _fileData = _startData.jsonData.baseMessage.editorBarData;
  968. let { fileId } = await this.getFileIdMixin(_fileData.url);
  969. if(!this.nowDoTaskId.includes(_startData.id))break;
  970. this.dataList.find(
  971. i => i.id === _startData.id
  972. ).jsonData.file_ids = fileId;
  973. _stepList[i].status = "1";
  974. this.dataList.find(
  975. i => i.id === _startData.id
  976. ).jsonData.steps = _stepList;
  977. this.updateTask(_startData.id);
  978. _startData.jsonData = JSON.parse(
  979. JSON.stringify(
  980. this.dataList.find(i => i.id === _startData.id).jsonData
  981. )
  982. );
  983. console.log("data👉",JSON.parse(JSON.stringify(_startData)))
  984. console.log(`${_startData.id}:已获取fileId`);
  985. }else if(_step.type=="getWordCloudMap"){
  986. //文件获取fileId
  987. _stepList[i].status = "2";
  988. this.dataList.find(
  989. i => i.id === _startData.id
  990. ).jsonData.steps = _stepList;
  991. let _fileData = _startData.jsonData.baseMessage.editorBarData;
  992. let _content = await this.getFile(_fileData.url);
  993. let _result = await this.getWordCloudMapMixin( _content.data);
  994. this.dataList.find(
  995. i => i.id === _startData.id
  996. ).jsonData.baseMessage.imageList.NephogramList.push(_result);
  997. _stepList[i].status = "1";
  998. this.dataList.find(
  999. i => i.id === _startData.id
  1000. ).jsonData.steps = _stepList;
  1001. this.updateTask(_startData.id);
  1002. _startData.jsonData = JSON.parse(
  1003. JSON.stringify(
  1004. this.dataList.find(i => i.id === _startData.id).jsonData
  1005. )
  1006. );
  1007. } else if (_step.type === "generateReport") {
  1008. //生成报告
  1009. _stepList[i].status = "2";
  1010. this.dataList.find(
  1011. i => i.id === _startData.id
  1012. ).jsonData.steps = _stepList;
  1013. let _analysisList = _startData.jsonData.analysisList;
  1014. let promises = [];
  1015. let _content =
  1016. _startData.jsonData.baseMessage.editorBarData.content;
  1017. if (!_content) {
  1018. _content = await this.getFile(
  1019. _startData.jsonData.baseMessage.editorBarData.url
  1020. );
  1021. _content = _content.data;
  1022. _startData.jsonData.baseMessage.editorBarData.content = _content;
  1023. }
  1024. promises = _analysisList.map((i, index) => {
  1025. return new Promise(async resolve => {
  1026. _startData.jsonData.analysisList[index].status = "default"; //默认状态
  1027. let _num = 0;
  1028. let _maxNum = 5;
  1029. const getAnalysis = async () => {
  1030. if (
  1031. ["tryAgainMax", "noAgentData"].includes(
  1032. _startData.jsonData.analysisList[index].status
  1033. )
  1034. ) {
  1035. return resolve(_startData.jsonData.analysisList[index]);
  1036. }
  1037. if (_num >= _maxNum) {
  1038. _startData.jsonData.analysisList[index].status =
  1039. "tryAgainMax"; //超过尝试次数
  1040. return resolve();
  1041. }
  1042. _num += 1;
  1043. let _assistantData =
  1044. this.dialogTagDataList.find(
  1045. i2 => i2.id == i.jsonData.mId
  1046. ) ||
  1047. this.dialogTagDataList.find(
  1048. i2 => i2.name == i.jsonData.name
  1049. );
  1050. if (!_assistantData) {
  1051. _startData.jsonData.analysisList[index].status =
  1052. "noAgentData"; //无对应的智能体
  1053. return resolve();
  1054. }
  1055. let data = await this.getAnalysisMixin({
  1056. fileId: _startData.jsonData.file_ids,
  1057. content: _content,
  1058. analysisData: i.jsonData,
  1059. assistantData: _assistantData,
  1060. baseMessage: _startData.jsonData.baseMessage
  1061. });
  1062. if(!this.nowDoTaskId.includes(_startData.id))return resolve();
  1063. if (data.data == 1) {
  1064. if (_num < _maxNum) {
  1065. //重试
  1066. getAnalysis();
  1067. }
  1068. } else {
  1069. _startData.jsonData.analysisList[index].status = "success";
  1070. _startData.jsonData.analysisList[index].jsonData =
  1071. data.data;
  1072. resolve();
  1073. }
  1074. };
  1075. getAnalysis();
  1076. });
  1077. });
  1078. await Promise.all(promises).then(() => {
  1079. console.log(`${_startData.id}:已完成分析获取`);
  1080. if(!this.nowDoTaskId.includes(_startData.id))return;
  1081. console.log("data👉",JSON.parse(JSON.stringify(_startData)))
  1082. console.log(_startData.jsonData.analysisList);
  1083. _stepList[i].status = "1";
  1084. this.dataList.find(
  1085. i => i.id === _startData.id
  1086. ).jsonData.steps = _stepList;
  1087. this.dataList.find(
  1088. i => i.id === _startData.id
  1089. ).jsonData = _startData.jsonData
  1090. this.updateTask(_startData.id);
  1091. _startData.jsonData = JSON.parse(
  1092. JSON.stringify(
  1093. this.dataList.find(i => i.id === _startData.id).jsonData
  1094. )
  1095. );
  1096. });
  1097. if(!this.nowDoTaskId.includes(_startData.id))break;
  1098. } else if (_step.type === "createClass") {
  1099. //创建课堂
  1100. _stepList[i].status = "2";
  1101. this.dataList.find(
  1102. i => i.id === _startData.id
  1103. ).jsonData.steps = _stepList;
  1104. //创建课堂 赋值好fileid 替换创建后课堂的基础数据 继续下一个任务
  1105. let newOption = await this.createClassMixin(_startData.jsonData);
  1106. if([1,2,3].includes(newOption.data)){
  1107. this.dataList.find(
  1108. i => i.id === _startData.id
  1109. ).jsonData.errorMessage = {content:"创建课堂失败",err:data.err};
  1110. this.dataList.find(
  1111. i => i.id === _startData.id
  1112. ).status = "3"
  1113. break;
  1114. }
  1115. if(!this.nowDoTaskId.includes(_startData.id))break;
  1116. this.$emit("addNewCourseOption", newOption.data);
  1117. this.dataList.find(i => i.id === _startData.id).jsonData.createId =
  1118. newOption.tid;
  1119. _stepList[i].status = "1";
  1120. this.dataList.find(
  1121. i => i.id === _startData.id
  1122. ).jsonData.steps = _stepList;
  1123. this.dataList.find(i => i.id === _startData.id).status = "2";
  1124. this.updateTask(_startData.id);
  1125. _startData.jsonData = JSON.parse(
  1126. JSON.stringify(
  1127. this.dataList.find(i => i.id === _startData.id).jsonData
  1128. )
  1129. );
  1130. console.log(`${_startData.id}:已创建课堂`);
  1131. // 查看是否有需要开启的任务
  1132. if (this.dataList.find(i => i.status == "0")) {
  1133. let id = this.dataList.find(i => i.status == "0").id;
  1134. this.startTask(id);
  1135. }
  1136. }
  1137. }
  1138. }
  1139. },
  1140. // 暂停任务
  1141. pauseTask(id) {
  1142. let _waitTask = this.dataList.find(i => i.status === "0");
  1143. if (_waitTask) {
  1144. //暂停这个任务,
  1145. this.dataList.find(i => i.id === id).status = "0";
  1146. this.nowDoTaskId = this.nowDoTaskId.filter(i=>i!==id);
  1147. // 开始另一个任务
  1148. this.startTask(_waitTask.id);
  1149. } else {
  1150. //没有任务了,所以改为待开始(停止)
  1151. this.dataList.find(i => i.id === id).status = "3";
  1152. }
  1153. },
  1154. //停止任务
  1155. stopTask(id) {
  1156. let stopTask = this.dataList.find(i=>i.id===id);
  1157. if(stopTask.status==='0'){
  1158. this.dataList.find(i => i.id === id).status = "3";
  1159. }if(stopTask.status==='1'){
  1160. this.dataList.find(i => i.id === id).status = "3";
  1161. this.nowDoTaskId = this.nowDoTaskId.filter(i=>i!==id);
  1162. }
  1163. console.log(stopTask)
  1164. let _waitTask = this.dataList.find(i => i.status === "0");
  1165. console.log(_waitTask)
  1166. if(_waitTask){
  1167. // 开始另一个任务
  1168. this.startTask(_waitTask.id);
  1169. }
  1170. // let _waitTask = this.dataList.find(i => i.status === "0" && i.id===id);
  1171. // if (_waitTask) {
  1172. // //停止这个任务,
  1173. // this.dataList.find(i => i.id === id).status = "3";
  1174. // this.nowDoTaskId = this.nowDoTaskId.filter(i=>i!==id);
  1175. // // 开始另一个任务
  1176. // this.startTask(_waitTask.id);
  1177. // } else {
  1178. // //只停止这个任务
  1179. // this.dataList.find(i => i.id === id).status = "3";
  1180. // }
  1181. },
  1182. goToEdit(id){
  1183. let _data = this.dataList.find(i=>i.id===id);
  1184. if(_data){
  1185. let createId = _data.jsonData.createId;
  1186. this.$emit("changeClass",createId);
  1187. this.close();
  1188. }
  1189. },
  1190. test() {
  1191. this.testMixin();
  1192. },
  1193. exportDoc(){
  1194. let _exportList = this.dataList.filter(
  1195. i =>
  1196. this.selectList.includes(i.id) &&
  1197. (this.selectStatus === "99" ||
  1198. this.statusList
  1199. .find(i2 => i2.value === this.selectStatus)
  1200. .allow.includes(i.status)) && i.status == "2"
  1201. );
  1202. if (_exportList.length <= 0) return this.$message.info("请先选择已经完成的任务列表");
  1203. let promise = [];
  1204. let _notify = this.$notify.info({
  1205. title: '提示',
  1206. message: '正在批量导出word中,请稍等...',
  1207. duration: 0,
  1208. showClose: false,
  1209. });
  1210. _exportList.forEach((i,index)=>{
  1211. i.jsonData.baseMessage.courseName = i.jsonData.baseMessage.courseName+"_"+index;
  1212. promise.push(this.getDocFnPromise(i))
  1213. })
  1214. Promise.all(promise).then(res=>{
  1215. _notify.close();
  1216. console.log(res)
  1217. if(res.length==1){
  1218. saveAs(res[0], `${res[0].name}`);
  1219. this.$message.success("导出报告成功")
  1220. }else if(res.length>1){
  1221. const zip = new JSZip();
  1222. res.forEach(i=>{
  1223. zip.file(`${i.name}`, i, { binary: true });
  1224. })
  1225. zip.generateAsync({ type: "blob" }).then(content => {
  1226. // 生成二进制流
  1227. saveAs(content, `课堂观察报告.zip`); // 利用file-saver保存文件 自定义文件名
  1228. });
  1229. this.$message.success("导出报告成功")
  1230. }
  1231. }).catch(err=>{
  1232. console.log("err",err)
  1233. })
  1234. },
  1235. },
  1236. mounted() {
  1237. this.getTaskList();
  1238. this.getDialogTagDataList();
  1239. }
  1240. };
  1241. </script>
  1242. <style scoped>
  1243. .batchCreationClassDialog {
  1244. width: 100vw;
  1245. height: 100vh;
  1246. }
  1247. .batchCreationClassDialog >>> .el-dialog__header,
  1248. .batchCreationClassDialog >>> .el-dialog__footer {
  1249. display: none; /* 隐藏头部和底部 */
  1250. }
  1251. .batchCreationClassDialog >>> .el-dialog__body {
  1252. padding: 0;
  1253. margin: 0;
  1254. height: 100vh;
  1255. width: 100vw;
  1256. overflow: auto;
  1257. display: flex;
  1258. justify-content: center;
  1259. }
  1260. .box {
  1261. width: 70%;
  1262. min-width: 500px;
  1263. height: 100%;
  1264. box-sizing: border-box;
  1265. border-left: solid 1px #e1e1e1;
  1266. border-right: solid 1px #e1e1e1;
  1267. padding: 0 40px;
  1268. }
  1269. .b_back {
  1270. height: 50px;
  1271. width: 100%;
  1272. display: flex;
  1273. align-items: center;
  1274. justify-content: space-between;
  1275. margin-top: 20px;
  1276. }
  1277. .b_b_left {
  1278. display: flex;
  1279. align-items: center;
  1280. cursor: pointer;
  1281. }
  1282. .b_b_left > img {
  1283. width: 25px;
  1284. height: 25px;
  1285. transform: rotate(180deg);
  1286. }
  1287. .b_b_left > span {
  1288. font-size: 16px;
  1289. font-weight: bold;
  1290. margin-left: 5px;
  1291. }
  1292. .b_head {
  1293. width: 100%;
  1294. height: 50px;
  1295. margin: 20px 0 0px 0;
  1296. box-sizing: border-box;
  1297. }
  1298. .b_head > span {
  1299. font-size: 18px;
  1300. font-weight: bold;
  1301. color: #000;
  1302. }
  1303. .b_nav {
  1304. width: 100%;
  1305. height: 50px;
  1306. display: flex;
  1307. align-items: center;
  1308. justify-content: space-between;
  1309. box-sizing: border-box;
  1310. border-bottom: solid 1px rgba(150, 155, 163, 1);
  1311. }
  1312. .b_n_left {
  1313. flex: 1;
  1314. /* width: calc(100% - 60px); */
  1315. height: 100%;
  1316. display: flex;
  1317. align-items: center;
  1318. overflow-y: hidden;
  1319. }
  1320. .b_n_left > span {
  1321. height: 100%;
  1322. padding: 0 20px;
  1323. display: flex;
  1324. align-items: center;
  1325. justify-content: center;
  1326. position: relative;
  1327. cursor: pointer;
  1328. transition: 0.3s;
  1329. font-size: 16px;
  1330. white-space: nowrap;
  1331. }
  1332. .b_n_left > span:hover {
  1333. color: rgba(5, 96, 253, 1);
  1334. }
  1335. .b_n_left > .b_n_l_active {
  1336. color: rgba(5, 96, 253, 1);
  1337. }
  1338. .b_n_left > .b_n_l_active::after {
  1339. content: "";
  1340. position: absolute;
  1341. width: 70%;
  1342. height: 4px;
  1343. border-radius: 4px;
  1344. bottom: -1px;
  1345. left: 50%;
  1346. transform: translateX(-50%);
  1347. background-color: rgba(5, 96, 253, 1);
  1348. }
  1349. .b_n_right {
  1350. width: auto;
  1351. height: 100%;
  1352. display: flex;
  1353. align-items: center;
  1354. justify-content: flex-end;
  1355. color: rgba(150, 155, 163, 1);
  1356. font-size: 16px;
  1357. white-space: nowrap;
  1358. }
  1359. .b_bottom {
  1360. width: 100%;
  1361. height: auto;
  1362. min-height: calc(100% - 210px);
  1363. /* height: calc(100% - 200px); */
  1364. }
  1365. .b_b_operation {
  1366. width: 100%;
  1367. height: 40px;
  1368. display: flex;
  1369. align-items: center;
  1370. justify-content: space-between;
  1371. margin-top: 10px;
  1372. }
  1373. .b_b_o_left {
  1374. width: calc(100% - 100px);
  1375. height: 100%;
  1376. display: flex;
  1377. align-items: center;
  1378. font-size: 16px;
  1379. }
  1380. .b_b_o_right {
  1381. width: fit-content;
  1382. height: 100%;
  1383. display: flex;
  1384. align-items: center;
  1385. justify-content: space-between;
  1386. }
  1387. .b_b_o_right > div {
  1388. margin-right: 10px;
  1389. font-size: 16px;
  1390. }
  1391. .b_b_o_right > div >>> .el-checkbox {
  1392. display: flex;
  1393. align-items: center;
  1394. }
  1395. .b_b_o_right > span {
  1396. width: fit-content;
  1397. height: 20px;
  1398. cursor: pointer;
  1399. display: flex;
  1400. align-items: center;
  1401. margin: 0 10px;
  1402. white-space: nowrap;
  1403. }
  1404. .b_b_o_right > span > img {
  1405. width: 100%;
  1406. height: 100%;
  1407. }
  1408. .b_b_list {
  1409. width: 100%;
  1410. height: auto;
  1411. padding-bottom: 40px;
  1412. }
  1413. </style>