index.vue 40 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411
  1. <template>
  2. <div id="moduleManagementEdit">
  3. <el-form
  4. label-position="right"
  5. label-width="120px"
  6. :model="listData"
  7. :rules="rules"
  8. ref="listData"
  9. >
  10. <div class="boxWidth">
  11. <el-form-item label="适用业务层级" required>
  12. <el-select
  13. v-model="eduType"
  14. placeholder="请选择教育类型"
  15. @change="changeEduType"
  16. >
  17. <el-option
  18. v-for="(item, index) in eduTypeOptions"
  19. :key="index"
  20. :label="item.educationName"
  21. :value="item.id"
  22. >
  23. </el-option>
  24. </el-select>
  25. <el-select
  26. v-model="courType"
  27. placeholder="请选择业务层次"
  28. @change="changecourseType"
  29. >
  30. <el-option
  31. v-for="(item, index) in newCourTypeOptions"
  32. :key="index"
  33. :label="item.projectName + '-' + item.businessName"
  34. :value="item.id"
  35. >
  36. </el-option>
  37. </el-select>
  38. <el-popover
  39. ref="popovers"
  40. placement="bottom"
  41. trigger="click"
  42. @show="showHandle"
  43. @hide="hideHandle"
  44. :disabled="courType ? false : true"
  45. ><el-checkbox
  46. v-model="checkAll"
  47. @change="handleCheckAllChange"
  48. :indeterminate="isIndeterminate"
  49. >全选</el-checkbox
  50. >
  51. <el-checkbox-group
  52. v-model="sujectArray"
  53. class="checkboxSty"
  54. @change="handleCheckedCitiesChange"
  55. >
  56. <el-checkbox
  57. v-for="(item, index) in newSujectOption"
  58. :label="item.newId"
  59. :key="index"
  60. >{{ item.subjectName }}</el-checkbox
  61. >
  62. </el-checkbox-group>
  63. <div style="display: block; text-align: center; margin-top: 10px">
  64. <el-button size="mini" type="primary" @click="submitSujectArray"
  65. >确定</el-button
  66. >
  67. </div>
  68. <el-button
  69. slot="reference"
  70. style="margin-left: 12px"
  71. @click="getMessage"
  72. >请选择科目</el-button
  73. >
  74. </el-popover>
  75. <span style="margin-left: 10px">注:可多选</span>
  76. </el-form-item>
  77. <el-form-item label="">
  78. <div :class="changeHeight ? 'ach' : 'clh'">
  79. <div
  80. v-for="(item, index) in newSujectApis"
  81. :key="index"
  82. class="listBoxStys"
  83. >
  84. {{
  85. item.educationName +
  86. " - " +
  87. item.projectName +
  88. " - " +
  89. item.businessName +
  90. " - " +
  91. item.subjectName
  92. }}
  93. <i class="el-icon-error closeIcons" @click="closeType(index)"></i>
  94. </div>
  95. </div>
  96. <el-button
  97. size="mini"
  98. v-if="newSujectApis.length > 1"
  99. @click="changeType"
  100. >{{ changeHeight ? "展开" : "关闭" }}</el-button
  101. ><el-button
  102. size="mini"
  103. v-if="newSujectApis.length > 0"
  104. @click="sujectApis = []"
  105. >清空</el-button
  106. >
  107. <!-- <span v-if="newSujectApis.length === 0">未选项目类型</span> -->
  108. </el-form-item>
  109. <el-form-item label="标题前缀" prop="prefixName">
  110. <el-input v-model="listData.prefixName"></el-input>
  111. <div style="color: #999">注:便于检索、归类,以及区分一样的标题</div>
  112. </el-form-item>
  113. <el-form-item label="模块标题" prop="moduleName">
  114. <el-input v-model="listData.moduleName"></el-input>
  115. <div style="color: #999">
  116. 注:请尽量规范易懂,方便在课程目录表呈现给学员
  117. </div>
  118. </el-form-item>
  119. <el-form-item label="模块封面">
  120. <el-row :gutter="10" style="margin-bottom: 10px">
  121. <el-col :span="12">
  122. <div
  123. style="
  124. width: 100%;
  125. height: 150px;
  126. border: 2px dashed #999;
  127. border-radius: 28px;
  128. line-height: 150px;
  129. text-align: center;
  130. "
  131. v-if="!listData.coverUrl"
  132. >
  133. <label for="uplose">
  134. <i class="el-icon-circle-plus-outline iconStsz"></i
  135. ></label>
  136. <input
  137. ref="file"
  138. type="file"
  139. style="display: none"
  140. id="uplose"
  141. @change="getImgFile"
  142. />
  143. </div>
  144. <el-image
  145. v-else
  146. style="width: 100%"
  147. :src="$methodsTools.splitImgHost(listData.coverUrl)"
  148. :preview-src-list="[
  149. $methodsTools.splitImgHost(listData.coverUrl),
  150. ]"
  151. >
  152. </el-image>
  153. </el-col>
  154. <el-col :span="11">
  155. <span style="color: #999; font-size: 14px"
  156. >注:请上传小于300kb,尺寸为750*440的图片,支持gif、jpg、jpeg、png等类型</span
  157. >
  158. </el-col>
  159. </el-row>
  160. <el-button
  161. v-if="listData.coverUrl"
  162. type="danger"
  163. size="mini"
  164. class="margin-top: 20px;"
  165. @click="clearImgs"
  166. >删除</el-button
  167. >
  168. </el-form-item>
  169. <el-form-item label="是否发布" prop="publishStatus">
  170. <el-radio-group v-model="listData.publishStatus">
  171. <el-radio :label="1">是</el-radio>
  172. <el-radio :label="0">否</el-radio>
  173. </el-radio-group>
  174. </el-form-item>
  175. </div>
  176. <el-form-item label="管理章">
  177. <div class="dis_plays">
  178. <div>
  179. <el-button size="small" @click="openBoxs">调用已有数据</el-button>
  180. <el-button size="small" type="success" @click="dialogDRFunc"
  181. >Excel批量新增章</el-button
  182. >
  183. <el-button size="small" @click="addChapter">自定义添加章</el-button>
  184. </div>
  185. <div style="color: #f56c6c">
  186. <span style="margin-right: 10px"
  187. >章总数:{{ tableData.length }}</span
  188. >
  189. <!-- <span>总时长:{{ minTimeAll }}分钟</span> -->
  190. </div>
  191. </div>
  192. <el-table
  193. :data="tableData"
  194. border
  195. :header-cell-style="{
  196. 'background-color': '#eee',
  197. padding: '8px',
  198. color: '#333',
  199. }"
  200. :default-sort="{ prop: 'sort', order: 'ascending' }"
  201. >
  202. <el-table-column
  203. v-for="(item, index) in tableSet"
  204. :width="item.width"
  205. :key="index"
  206. :label="item.label"
  207. align="center"
  208. :show-overflow-tooltip="true"
  209. header-align="center"
  210. :sortable="item.prop === 'sort'"
  211. sort-by="sort"
  212. :prop="item.prop"
  213. >
  214. <template slot-scope="scope">
  215. <span v-if="item.scope === 'types'">{{
  216. scope.row[item.prop] === 1
  217. ? "录播"
  218. : scope.row[item.prop] === 2
  219. ? "直播"
  220. : scope.row[item.prop] === 3
  221. ? "回放"
  222. : "未知"
  223. }}</span>
  224. <span v-else-if="item.scope === 'Status'">
  225. {{
  226. scope.row[item.prop] === 1
  227. ? "发布"
  228. : scope.row[item.prop] === 0
  229. ? "未发布"
  230. : "未知"
  231. }}
  232. </span>
  233. <div v-else-if="item.scope === 'inputs'">
  234. <el-input-number
  235. style="width: 50px"
  236. size="small"
  237. :controls="false"
  238. v-model="scope.row[item.prop]"
  239. controls-position="right"
  240. :min="0"
  241. ></el-input-number>
  242. </div>
  243. <span v-else>{{ scope.row[item.prop] }}</span></template
  244. >
  245. </el-table-column>
  246. <el-table-column
  247. label="操作"
  248. align="center"
  249. fixed="right"
  250. width="180px"
  251. >
  252. <template slot-scope="scope">
  253. <el-button type="text" @click="jumpChapter(scope.row)"
  254. >章节内容</el-button
  255. >
  256. <el-button type="text" @click="delList(scope.row)"
  257. >删除</el-button
  258. >
  259. </template>
  260. </el-table-column>
  261. </el-table>
  262. </el-form-item>
  263. <el-form-item>
  264. <el-button @click="backPage">取消</el-button>
  265. <el-button
  266. :loading="disabledBtn"
  267. type="primary"
  268. @click="submit('listData')"
  269. :disabled="!noStudent"
  270. >确定</el-button
  271. >
  272. </el-form-item>
  273. </el-form>
  274. <el-dialog
  275. @closed="closedFunc"
  276. :visible.sync="dialogVisible"
  277. width="800px"
  278. :show-close="false"
  279. :close-on-click-modal="false"
  280. >
  281. <div slot="title" class="hearders">
  282. <div class="leftTitle">添加章</div>
  283. <div class="rightBoxs">
  284. <img
  285. src="@/assets/images/Close@2x.png"
  286. alt=""
  287. @click="dialogVisible = false"
  288. />
  289. </div>
  290. </div>
  291. <search-box-new
  292. ref="searchBox"
  293. :formData="formData"
  294. :formList="formList"
  295. @search="getInfos"
  296. @init="init"
  297. />
  298. <el-table
  299. ref="multipleTable"
  300. :data="boxtableData"
  301. border
  302. @select-all="selectAll"
  303. @select="select"
  304. :row-key="getRowKeys"
  305. :header-cell-style="{
  306. 'background-color': '#eee',
  307. padding: '8px',
  308. color: '#333',
  309. }"
  310. >
  311. <el-table-column
  312. align="center"
  313. type="selection"
  314. width="55"
  315. header-align="center"
  316. :selectable="checkboxT"
  317. :reserve-selection="true"
  318. >
  319. </el-table-column>
  320. <template v-for="(item, index) in tableSet">
  321. <el-table-column
  322. v-if="item.scope !== 'inputs'"
  323. :width="item.width"
  324. :key="index"
  325. :label="item.label"
  326. align="center"
  327. :show-overflow-tooltip="true"
  328. header-align="center"
  329. >
  330. <template slot-scope="scope">
  331. <span v-if="item.scope === 'types'">{{
  332. scope.row[item.prop] === 1
  333. ? "录播"
  334. : scope.row[item.prop] === 2
  335. ? "直播"
  336. : scope.row[item.prop] === 3
  337. ? "回放"
  338. : "未知"
  339. }}</span>
  340. <span v-else-if="item.scope === 'Status'">
  341. {{
  342. scope.row[item.prop] === 1
  343. ? "发布"
  344. : scope.row[item.prop] === 0
  345. ? "未发布"
  346. : "未知"
  347. }}
  348. </span>
  349. <span v-else>{{ scope.row[item.prop] }}</span></template
  350. >
  351. </el-table-column></template
  352. >
  353. </el-table>
  354. <pagination
  355. :total="total"
  356. :pageSize="formData.pageSize"
  357. :currentPage="formData.pageNum"
  358. @handleSizeChange="handleSizeChange"
  359. @handleCurrentChange="handleCurrentChange"
  360. />
  361. <span slot="footer" class="dialog-footer">
  362. <el-button @click="dialogVisible = false">取 消</el-button>
  363. <el-button
  364. type="primary"
  365. :disabled="activeLists.length === 0"
  366. @click="submitForm"
  367. >确 定</el-button
  368. >
  369. </span>
  370. </el-dialog>
  371. <el-dialog
  372. :visible.sync="loading"
  373. width="660px"
  374. :show-close="false"
  375. :close-on-click-modal="false"
  376. >
  377. <div slot="title" class="hearders">
  378. <div class="leftTitle">导入</div>
  379. <div class="rightBoxs">
  380. <img
  381. src="@/assets/images/Close@2x.png"
  382. alt=""
  383. @click="dialogDR = false"
  384. />
  385. </div>
  386. </div>
  387. <div>
  388. <div class="swq">
  389. <img
  390. style="width: 182px; height: 168px"
  391. src="@/assets/images/dr.png"
  392. alt=""
  393. />
  394. </div>
  395. <div style="padding-left: 100px">
  396. <p>第一步:下载导入模板</p>
  397. <p style="padding-left: 50px">
  398. <i class="el-icon-upload"></i
  399. ><span class="dowmStys" @click="getDowm">下载模板</span>
  400. </p>
  401. <p>第二步:(批量新增):点击“上传Excel”完成导入</p>
  402. <div
  403. v-loading="loading"
  404. element-loading-text="正在处理中"
  405. style="
  406. margin-left: 50px;
  407. padding: 10px 20px;
  408. width: 130px;
  409. height: 60px;
  410. "
  411. >
  412. <label
  413. v-show="!loading"
  414. for="mobles"
  415. class="el-button el-button--primary"
  416. >上传Excel</label
  417. ><input
  418. style="display: none"
  419. type="file"
  420. id="mobles"
  421. ref="input1"
  422. @change="importMobleadd"
  423. />
  424. </div>
  425. </div>
  426. </div>
  427. <span slot="footer" class="dialog-footer">
  428. <el-button @click="dialogDR = false">取消</el-button>
  429. <!-- <el-button type="primary" @click="submitChecksDR">确定</el-button> -->
  430. </span>
  431. </el-dialog>
  432. <batch-import-dialoga
  433. :dialogVisible.sync="dialogDR"
  434. :isShowErr.sync="dialogERROR"
  435. :errorData="errorData"
  436. temUrl="/oss/images/file/20220617/1655453121157.xlsx"
  437. apiKey="CoursemoduleimportData"
  438. :newSujectApis="newSujectApis"
  439. @success="success"
  440. ></batch-import-dialoga>
  441. <el-dialog
  442. append-to-body
  443. :visible.sync="dialogVisible"
  444. width="660px"
  445. :show-close="false"
  446. :close-on-click-modal="false"
  447. >
  448. <div slot="title" class="hearders">
  449. <div class="leftTitle">提示</div>
  450. <div class="rightBoxs">
  451. <img
  452. src="@/assets/images/Close@2x.png"
  453. alt=""
  454. @click="dialogERROR = false"
  455. />
  456. </div>
  457. </div>
  458. <div>
  459. <h4 style="margin-top: 0px; font-weight: bold; text-align: center">
  460. 导入失败原因
  461. </h4>
  462. <el-input
  463. readonly
  464. type="textarea"
  465. :autosize="{ minRows: 6, maxRows: 24 }"
  466. v-model="errorData"
  467. >
  468. </el-input>
  469. </div>
  470. <span slot="footer" class="dialog-footer">
  471. <el-button @click="dialogERROR = false">确定</el-button>
  472. </span>
  473. </el-dialog>
  474. <addChapter ref="addChapter" @backData="backData" />
  475. </div>
  476. </template>
  477. <script>
  478. import * as baseUrls from "@/utils/request.js";
  479. import searchBoxNew from "@/components/searchBoxNew";
  480. import pagination from "@/components/pagination";
  481. import addChapter from "../addChapter.vue";
  482. import batchImportDialoga from "@/components/Comon/batchImportDialog.vue";
  483. export default {
  484. name: "ModuleManagementEdit",
  485. components: { searchBoxNew, pagination, addChapter, batchImportDialoga },
  486. data() {
  487. return {
  488. disabledBtn: false,
  489. isIndeterminate: false,
  490. checkAll: false,
  491. // 弹窗数据
  492. changeHeight: true,
  493. bfImg: "oss/images/avatar/20211013/1634097664410_1397766697",
  494. listData: {
  495. recordingUrl: "",
  496. liveUrl: "",
  497. coverUrl: "oss/images/avatar/20211013/1634097664410_1397766697",
  498. },
  499. eduTypeOptions: [], //教育类型数据
  500. projectTypeOptions: [], //项目类型数据
  501. courTypeOptions: [], //业务层次数据
  502. newCourTypeOptions: [], //当前业务层次数据
  503. sujectOption: [], //科目数据
  504. newSujectOption: [], //当前科目数据数据
  505. eduType: "", //当前选中教育类型
  506. courType: "", //当前选中业务层次
  507. sujectApis: [], //当前存在的科目
  508. newSujectApis: [],
  509. sujectArray: [], //选中的科目
  510. //表单验证
  511. rules: {
  512. prefixName: [
  513. { required: false, message: "请输入标题前缀", trigger: "blur" },
  514. ],
  515. moduleName: [
  516. { required: true, message: "请输入节标题", trigger: "blur" },
  517. ],
  518. // liveDuration: [
  519. // { required: true, message: "节时长不能为空" },
  520. // { type: "number", message: "节时长必须为数字值" },
  521. // ],
  522. publishStatus: [
  523. { required: true, message: "请选择是否发布", trigger: "change" },
  524. ],
  525. },
  526. numberAll: 0, //节总数
  527. minTimeAll: 0, //总时长
  528. tableSet: [
  529. { label: "排序", prop: "sort", scope: "inputs", width: "100" },
  530. { label: "章编码", prop: "code", width: "120" },
  531. { label: "标题前缀", prop: "prefixName", width: "180" },
  532. { label: "章标题", prop: "name" },
  533. { label: "节数量", prop: "sectionNum", width: "120" },
  534. {
  535. label: "发布状态",
  536. prop: "publishStatus",
  537. scope: "Status",
  538. width: "120",
  539. },
  540. ],
  541. tableData: [],
  542. dialogVisible: false,
  543. boxtableData: [],
  544. formList: [
  545. {
  546. prop: "educationTypeId",
  547. placeholder: "教育类型",
  548. scope: "educationType",
  549. },
  550. {
  551. prop: "businessId",
  552. placeholder: "业务层次",
  553. scope: "businessLevel",
  554. edu: "educationTypeId",
  555. },
  556. {
  557. prop: "subjectId",
  558. placeholder: "科目",
  559. scope: "sujectType",
  560. edu: "educationTypeId",
  561. },
  562. // {
  563. // prop: "publishStatus",
  564. // placeholder: "发布状态",
  565. // scope: "select",
  566. // options: [
  567. // {
  568. // label: "已发布",
  569. // value: 1,
  570. // },
  571. // {
  572. // label: "未发布",
  573. // value: 0,
  574. // },
  575. // ],
  576. // },
  577. {
  578. prop: "key",
  579. placeholder: "请输入章标题/章编码/标题前缀",
  580. },
  581. ],
  582. total: 0, //一共多少条
  583. formData: {
  584. status: 1,
  585. pageSize: 10,
  586. pageNum: 1,
  587. publishStatus: 1,
  588. },
  589. disCheckList: [], //已选转禁用复选列表
  590. activeLists: [],
  591. noStudent: true,
  592. pageId: this.$route.query.id,
  593. errorData: "",
  594. dialogERROR: false,
  595. dialogDR: false,
  596. loading: false,
  597. };
  598. },
  599. watch: {
  600. sujectApis: {
  601. immediate: true,
  602. handler(newName, oldName) {
  603. this.changeTypes();
  604. },
  605. },
  606. },
  607. async mounted() {
  608. this.$modal.loading("正在导入数据,请稍后...");
  609. this.$api.gradecheckGoodsChange({ moduleId: this.pageId }).then((res) => {
  610. if (res.data > 0) {
  611. // this.noStudent = false;
  612. }
  613. });
  614. await this.getDict();
  615. this.search();
  616. },
  617. activated() {
  618. if (this.$store.getters.modulePage) {
  619. this.$api
  620. .obtainCoursechapter(this.$store.getters.modulePage.id)
  621. .then((res) => {
  622. const FIND = this.tableData.findIndex((item) => {
  623. return item.chapterId == this.$store.getters.modulePage.id;
  624. });
  625. if (FIND !== -1) {
  626. res.data.sort = this.tableData[FIND].sort;
  627. this.tableData.splice(FIND, 1, res.data);
  628. }
  629. this.$store.dispatch("changemodulePage", null);
  630. });
  631. }
  632. },
  633. methods: {
  634. /**
  635. * 下载Excel模板
  636. */
  637. getDowm() {
  638. let url =
  639. baseUrls.BASE_IMG_URL + "/oss/images/file/20220617/1655453121157.xlsx";
  640. let link = document.createElement("a");
  641. let fileName = "导入模板" + ".xlsx";
  642. document.body.appendChild(link);
  643. link.href = url;
  644. link.dowmload = fileName;
  645. link.click();
  646. link.remove();
  647. },
  648. dialogDRFunc() {
  649. if (!this.newSujectApis.length) {
  650. this.$message.error("请添加科目");
  651. return;
  652. }
  653. this.dialogDR = true;
  654. },
  655. /**
  656. *
  657. * @param {Object} e
  658. * @remards 导入逻辑
  659. */ importMobleadd(e) {
  660. if (!this.newSujectApis.length) {
  661. this.$message.error("请添加科目");
  662. return;
  663. }
  664. var self = this;
  665. var file = e.target.files[0];
  666. if (file === undefined) {
  667. e.target.value = "";
  668. return;
  669. }
  670. var type = e.target.value.toLowerCase().split(".").splice(-1);
  671. if (type[0] != "xlsx" && type[0] != "xls") {
  672. self.$message.error("请上传excel文件,且上传格式需为:.xlsx");
  673. return;
  674. }
  675. this.loading = true;
  676. let formData = new FormData();
  677. formData.append("businessJson", JSON.stringify(this.newSujectApis));
  678. formData.append("file", file);
  679. this.$api
  680. .CoursemoduleimportData(formData)
  681. .then(async (res) => {
  682. if (res.code === 200) {
  683. if (!res.data.errorLog) {
  684. await this.awaitGetFestivalList(res.data.importNo, 1)
  685. .then((result) => {
  686. self.dialogDR = false;
  687. })
  688. .catch(() => {
  689. e.target.value = "";
  690. });
  691. } else {
  692. await this.awaitGetFestivalList(res.data.importNo, 2)
  693. .then((result) => {
  694. let ary = res.data.errorLog.split("\r\n");
  695. ary = ary
  696. .filter((item) => {
  697. return item.length > 0;
  698. })
  699. .reverse();
  700. self.$message({
  701. message: `${ary.length}条数据导入失败,请查看失败原因`,
  702. customClass: "myMessageClass",
  703. });
  704. ary = ary.join("\r\n");
  705. self.errorData = ary;
  706. self.dialogERROR = true;
  707. })
  708. .catch(() => {
  709. e.target.value = "";
  710. });
  711. }
  712. }
  713. })
  714. .finally(() => {
  715. e.target.value = "";
  716. this.loading = false;
  717. });
  718. },
  719. /**
  720. *
  721. * @param {Strings} ids 查询编码
  722. * @param {Number} type 1为成功2为失败
  723. * @remards 失败时也需查询是否有成功的数据导入数据库,如存在 则加列队列同时提示
  724. */
  725. awaitGetFestivalList(ids, type) {
  726. return new Promise((resolve, reject) => {
  727. this.$api
  728. .inquireCourseListchapter({ importNo: ids })
  729. .then((res) => {
  730. if (type === 2 && res.rows.length) {
  731. this.$message({
  732. type: "success",
  733. message: `成功导入${res.rows.length}条数据,`,
  734. customClass: "myMessageClass",
  735. });
  736. }
  737. if (res.rows.length) {
  738. this.activeLists = res.rows;
  739. if (type === 1) {
  740. this.submitForm();
  741. } else {
  742. this.submitForm(1);
  743. }
  744. }
  745. resolve();
  746. })
  747. .catch(() => {
  748. reject();
  749. });
  750. });
  751. },
  752. success({ importNo, errorLog }) {
  753. console.log(importNo, errorLog)
  754. this.awaitGetFestivalList(importNo, errorLog ? 2 : 1)
  755. .then((result) => {
  756. if (!errorLog) {
  757. self.dialogDR = false;
  758. } else {
  759. let ary = errorLog.split("\r\n");
  760. ary = ary
  761. .filter((item) => {
  762. return item.length > 0;
  763. })
  764. .reverse();
  765. this.$message({
  766. message: `${ary.length}条数据导入失败,请查看失败原因`,
  767. customClass: "myMessageClass",
  768. });
  769. ary = ary.join("\r\n");
  770. this.errorData = ary;
  771. this.dialogERROR = true;
  772. }
  773. })
  774. .catch(() => {
  775. e.target.value = "";
  776. });
  777. },
  778. jumpChapter(v) {
  779. const jump = () => {
  780. this.$store.dispatch("changemodulePage", {
  781. name: "moduleManagementEdit",
  782. id: v.chapterId,
  783. });
  784. this.$router.push({
  785. path: "chapterEdit",
  786. query: {
  787. id: v.chapterId,
  788. },
  789. });
  790. };
  791. const statusPage = this.$store.state.tagsView.visitedViews.some(
  792. (item) => {
  793. return item.name == "ChapterEdit";
  794. }
  795. );
  796. if (statusPage) {
  797. this.$store
  798. .dispatch("tagsView/delCachedView", {
  799. name: "ChapterEdit",
  800. })
  801. .then((res) => {
  802. jump();
  803. });
  804. } else {
  805. jump();
  806. }
  807. },
  808. /**
  809. * 打开添加章组件
  810. */
  811. addChapter() {
  812. if (!this.newSujectApis.length) {
  813. this.$message.warning("请选择科目");
  814. return;
  815. }
  816. this.$refs.addChapter.openBoxs(this.newSujectApis);
  817. },
  818. /**
  819. * 添加章-返回数据
  820. */
  821. backData(v) {
  822. this.$api.inquireCourseListchapter({ chapterIds: v }).then((res) => {
  823. this.activeLists = res.rows;
  824. this.submitForm();
  825. });
  826. },
  827. handleCheckedCitiesChange() {
  828. let nid = this.newSujectOption.map((item) => {
  829. return item.newId;
  830. });
  831. this.checkAll = this.sujectArray.length === nid.length;
  832. this.isIndeterminate =
  833. this.sujectArray.length > 0 && this.sujectArray.length < nid.length;
  834. },
  835. setFunc(arr) {
  836. var arrays = [];
  837. for (let i = 0; i < arr.length; i++) {
  838. if (!arrays.includes(arr[i])) {
  839. arrays.push(arr[i]);
  840. }
  841. }
  842. return arrays;
  843. },
  844. handleCheckAllChange(val) {
  845. if (val) {
  846. let nid = this.newSujectOption.map((item) => {
  847. return item.newId;
  848. });
  849. let arrays = this.sujectArray.concat(nid);
  850. this.sujectArray = this.setFunc(arrays);
  851. this.isIndeterminate = false;
  852. } else {
  853. let nid = this.newSujectOption.map((item) => {
  854. return item.newId;
  855. });
  856. let newArr = [];
  857. this.sujectArray.forEach((item) => {
  858. if (!nid.includes(item)) {
  859. newArr.push(item);
  860. }
  861. });
  862. this.sujectArray = newArr;
  863. this.isIndeterminate = false;
  864. }
  865. },
  866. getMessage() {
  867. if (!this.courType) {
  868. this.$message.warning("请先选择业务层级");
  869. }
  870. },
  871. openBoxs() {
  872. var self = this;
  873. this.$api
  874. .inquireCourseListchapter({
  875. status: 1,
  876. pageNum: 1,
  877. pageSize: 10,
  878. publishStatus: 1,
  879. })
  880. .then((res) => {
  881. var aList = [];
  882. this.tableData.map((item) => {
  883. aList.push(item.chapterId);
  884. });
  885. this.disCheckList = aList;
  886. this.boxtableData = res.rows;
  887. this.total = res.total;
  888. this.dialogVisible = true;
  889. this.$nextTick(function () {
  890. self.$refs.multipleTable.clearSelection();
  891. });
  892. });
  893. },
  894. getInfosList() {
  895. this.$api.inquireCourseListmodulechapter(this.pageId).then((result) => {
  896. // this.numberAll = result.total;
  897. // this.minTimeAll = result.timeTotal;
  898. this.tableData = result.data;
  899. });
  900. },
  901. init() {
  902. this.getInfos(2);
  903. },
  904. getInfos(int) {
  905. if (int === 1) {
  906. this.formData.pageNum = 1;
  907. }
  908. if (int === 2) {
  909. this.formData = {
  910. status: 1,
  911. pageSize: 10,
  912. pageNum: 1,
  913. publishStatus: 1,
  914. };
  915. }
  916. this.$api.inquireCourseListchapter(this.formData).then((res) => {
  917. this.boxtableData = res.rows;
  918. this.total = res.total;
  919. });
  920. },
  921. search() {
  922. this.$api
  923. .obtainCoursemodule(this.pageId)
  924. .then((res) => {
  925. this.bfImg = res.data.coverUrl;
  926. this.listData = res.data;
  927. this.$api
  928. .inquireCourseListmodulebusiness(this.pageId)
  929. .then((result) => {
  930. var arrays = [];
  931. result.data.map((item) => {
  932. arrays.push(item.businessId + "-" + item.subjectId);
  933. });
  934. this.sujectApis = arrays;
  935. this.getInfosList();
  936. });
  937. })
  938. .finally(() => {
  939. this.$modal.closeLoading();
  940. });
  941. },
  942. clearImgs() {
  943. this.listData.coverUrl = "";
  944. },
  945. changeTypes() {
  946. var self = this;
  947. var arrays = [];
  948. this.sujectApis.map((item, index) => {
  949. this.courTypeOptions.map((items) => {
  950. if (items.id === item.split("-").map(Number)[0]) {
  951. var obj = {
  952. educationTypeId: items.educationId,
  953. educationName: items.educationName,
  954. projectId: items.projectId,
  955. projectName: items.projectName,
  956. businessId: items.id,
  957. businessName: items.businessName,
  958. };
  959. self.sujectOption.map((i) => {
  960. if (
  961. i.id === item.split("-").map(Number)[1] &&
  962. i.courseArrays.indexOf(items.projectId) !== -1
  963. ) {
  964. obj.subjectName = i.subjectName;
  965. obj.subjectId = i.id;
  966. }
  967. });
  968. arrays.push(obj);
  969. }
  970. });
  971. });
  972. this.newSujectApis = arrays;
  973. },
  974. changeType() {
  975. this.changeHeight = !this.changeHeight;
  976. },
  977. submitSujectArray() {
  978. var self = this;
  979. this.sujectApis = this.sujectApis.filter((item, index) => {
  980. return item.split("-").map(Number)[0] !== Number(self.courType);
  981. });
  982. for (let i = 0; i < this.sujectArray.length; i++) {
  983. this.sujectApis.push(this.sujectArray[i]);
  984. }
  985. this.$refs.popovers.doClose();
  986. },
  987. showHandle() {
  988. var array = [];
  989. for (let i = 0; i < this.sujectApis.length; i++) {
  990. if (
  991. this.sujectApis[i].split("-").map(Number)[0] === Number(this.courType)
  992. ) {
  993. array.push(this.sujectApis[i]);
  994. }
  995. }
  996. this.sujectArray = array;
  997. if (!this.newSujectOption.length) {
  998. this.$message.warning("该业务层次暂无关联科目");
  999. this.$refs.popovers.doClose();
  1000. return;
  1001. }
  1002. this.newSujectOption.map((item) => {
  1003. item.newId = this.courType + "-" + item.id;
  1004. });
  1005. this.handleCheckedCitiesChange();
  1006. },
  1007. hideHandle() {},
  1008. getDict() {
  1009. return new Promise((resolve, reject) => {
  1010. this.$api.inquireCourseEducationType({ status: 1 }).then((res) => {
  1011. this.eduTypeOptions = res.rows;
  1012. });
  1013. this.$api.inquireCourseProjectType({ status: 1 }).then((res) => {
  1014. this.projectTypeOptions = res.rows;
  1015. });
  1016. this.$api.inquirebusinessList({ status: 1 }).then((res) => {
  1017. this.courTypeOptions = res.rows;
  1018. this.newCourTypeOptions = res.rows;
  1019. });
  1020. this.$api.inquireCourseSubject({ status: 1 }).then((res) => {
  1021. res.rows.map((item, index) => {
  1022. var array = [];
  1023. item.courseProjectTypes.map((items, indexs) => {
  1024. array.push(items.id);
  1025. });
  1026. item.courseArrays = array;
  1027. });
  1028. this.sujectOption = res.rows;
  1029. resolve();
  1030. });
  1031. });
  1032. },
  1033. changeEduType() {
  1034. if (!(this.courType === undefined || this.courType === "")) {
  1035. this.courType = "";
  1036. }
  1037. var arrays = [];
  1038. this.courTypeOptions.map((item) => {
  1039. if (item.educationId === this.eduType) {
  1040. arrays.push(item);
  1041. }
  1042. });
  1043. this.newCourTypeOptions = arrays;
  1044. },
  1045. changecourseType() {
  1046. this.newCourTypeOptions.map((item, index) => {
  1047. if (item.id === this.courType) {
  1048. this.eduType = item.educationId;
  1049. var array = [];
  1050. this.sujectOption.map((items, indexs) => {
  1051. if (items.courseArrays.indexOf(item.projectId) !== -1) {
  1052. array.push(items);
  1053. }
  1054. });
  1055. this.newSujectOption = array;
  1056. }
  1057. });
  1058. var arrays = [];
  1059. this.courTypeOptions.map((item) => {
  1060. if (item.educationId === this.eduType) {
  1061. arrays.push(item);
  1062. }
  1063. });
  1064. this.newCourTypeOptions = arrays;
  1065. this.$refs.popovers.doClose();
  1066. },
  1067. submit(formName) {
  1068. this.$refs[formName].validate((valid) => {
  1069. if (valid) {
  1070. if (!this.newSujectApis.length) {
  1071. this.$message.error("请选择适用业务层级");
  1072. return;
  1073. }
  1074. // if (
  1075. // this.listData.coverUrl === "" ||
  1076. // this.listData.coverUrl === null ||
  1077. // this.listData.coverUrl === undefined
  1078. // ) {
  1079. // this.$message.error("请上传节封面");
  1080. // return false;
  1081. // }
  1082. for (let i = 0; i < this.tableData.length; i++) {
  1083. if (!this.tableData[i].sort && this.tableData[i].sort !== 0) {
  1084. this.$message.warning(`管理章第${i + 1}条请输入排序`);
  1085. return;
  1086. }
  1087. }
  1088. let arr = this.tableData.map((items) => {
  1089. return items.sort;
  1090. });
  1091. if (new Set(arr).size != arr.length) {
  1092. this.$message.warning("排序不允许有重复值");
  1093. return;
  1094. }
  1095. this.rulesTableSumbit();
  1096. } else {
  1097. return false;
  1098. }
  1099. });
  1100. },
  1101. async rulesTableSumbit() {
  1102. this.disabledBtn = true;
  1103. var chapterIdList = [];
  1104. this.tableData.map((item) => {
  1105. chapterIdList.push({
  1106. chapterId: item.chapterId,
  1107. sort: Number(item.sort),
  1108. });
  1109. });
  1110. var dataInfos = {
  1111. status: 1,
  1112. moduleId: this.pageId,
  1113. businessList: this.newSujectApis,
  1114. chapterIdList: chapterIdList,
  1115. coverUrl: this.listData.coverUrl,
  1116. moduleName: this.listData.moduleName,
  1117. prefixName: this.listData.prefixName,
  1118. publishStatus: this.listData.publishStatus,
  1119. };
  1120. this.$api
  1121. .editCoursemodule(dataInfos)
  1122. .then((res) => {
  1123. this.$message.success("修改成功");
  1124. setTimeout(() => {
  1125. this.$store
  1126. .dispatch("tagsView/exitView", this.$route)
  1127. .then((res) => {
  1128. this.$router.push({
  1129. path: "moduleManagement",
  1130. });
  1131. });
  1132. }, 500);
  1133. })
  1134. .catch(() => {
  1135. this.disabledBtn = false;
  1136. });
  1137. },
  1138. backPage() {
  1139. this.$store.dispatch("tagsView/delView", this.$route).then((res) => {
  1140. this.$router.push({
  1141. path: "moduleManagement",
  1142. });
  1143. });
  1144. },
  1145. closeType(index) {
  1146. this.sujectApis.splice(index, 1);
  1147. },
  1148. getImgFile() {
  1149. var self = this;
  1150. var file = self.$refs.file.files[0];
  1151. if (file === undefined) {
  1152. self.$set(self.listData, "coverUrl", "");
  1153. return;
  1154. }
  1155. if (file.size > 0.3 * 1024 * 1024) {
  1156. self.$message.error("图片不得大于300kb");
  1157. return;
  1158. }
  1159. var type = self.$refs.file.value.toLowerCase().split(".").splice(-1);
  1160. if (
  1161. type[0] != "jpg" &&
  1162. type[0] != "png" &&
  1163. type[0] != "jpeg" &&
  1164. type[0] != "gif"
  1165. ) {
  1166. self.$message.error("上传格式需为:.jpg/.png/.jpeg/gif");
  1167. self.$refs.file.value = "";
  1168. return;
  1169. }
  1170. this.$upload.upload(file, 0).then((res) => {
  1171. self.listData.coverUrl = res;
  1172. });
  1173. },
  1174. handleSizeChange(v) {
  1175. this.formData.pageSize = v;
  1176. this.formData.pageNum = 1;
  1177. this.getInfos();
  1178. },
  1179. handleCurrentChange(v) {
  1180. this.formData.pageNum = v;
  1181. this.getInfos();
  1182. },
  1183. selectAll(value) {
  1184. this.activeLists = value;
  1185. },
  1186. select(value) {
  1187. this.activeLists = value;
  1188. },
  1189. checkboxT(row, index) {
  1190. if (this.disCheckList.indexOf(row.chapterId) !== -1) {
  1191. return false;
  1192. } else {
  1193. return true;
  1194. }
  1195. },
  1196. getRowKeys(row) {
  1197. return row.chapterId;
  1198. },
  1199. /**
  1200. *
  1201. * @param {Number} int 导入失败标识
  1202. * @remards 合并且排列节列表数据
  1203. */
  1204. submitForm(int) {
  1205. if (this.activeLists.length === 0) {
  1206. this.dialogVisible = false;
  1207. return;
  1208. }
  1209. if (this.tableData.length) {
  1210. let maxIndex = 0;
  1211. this.tableData.forEach((item) => {
  1212. if (item.sort > maxIndex) {
  1213. maxIndex = item.sort;
  1214. }
  1215. });
  1216. this.activeLists.forEach((item, index) => {
  1217. item.sort = maxIndex + index + 1;
  1218. });
  1219. } else {
  1220. this.activeLists.forEach((item, index) => {
  1221. item.sort = index + 1;
  1222. });
  1223. }
  1224. this.tableData = this.tableData.concat(this.activeLists);
  1225. this.dialogVisible = false;
  1226. this.activeLists = [];
  1227. if (!int) {
  1228. this.$message({
  1229. type: "success",
  1230. message: `添加成功`,
  1231. customClass: "myMessageClass",
  1232. });
  1233. }
  1234. },
  1235. delList(item) {
  1236. this.tableData.map((items, indexs) => {
  1237. if (items.chapterId === item.chapterId) {
  1238. this.tableData.splice(indexs, 1);
  1239. this.$message.success("删除成功");
  1240. }
  1241. });
  1242. },
  1243. closedFunc() {
  1244. this.activeLists = [];
  1245. },
  1246. },
  1247. };
  1248. </script>
  1249. <style lang="less" scoped>
  1250. .swq {
  1251. text-align: center;
  1252. border-bottom: 1px solid #eee;
  1253. }
  1254. .dowmStys {
  1255. color: blue;
  1256. cursor: pointer;
  1257. }
  1258. .boxWidth {
  1259. width: 800px;
  1260. }
  1261. .numInputs {
  1262. width: 150px;
  1263. }
  1264. .checkboxSty {
  1265. max-height: 210px;
  1266. overflow: auto;
  1267. display: flex;
  1268. flex-direction: column;
  1269. }
  1270. .listBoxStys {
  1271. flex-shrink: 0;
  1272. padding: 0px 10px;
  1273. border-radius: 8px;
  1274. border: 1px solid #eee;
  1275. margin-right: 10px;
  1276. margin-bottom: 6px;
  1277. }
  1278. .closeIcons {
  1279. color: red;
  1280. cursor: pointer;
  1281. margin-left: 6px;
  1282. }
  1283. .ach {
  1284. display: flex;
  1285. align-items: center;
  1286. overflow: hidden;
  1287. }
  1288. .clh {
  1289. display: flex;
  1290. align-items: center;
  1291. flex-wrap: wrap;
  1292. }
  1293. .imgBoxins {
  1294. width: 375px;
  1295. height: 220px;
  1296. text-align: center;
  1297. img {
  1298. height: 100%;
  1299. }
  1300. }
  1301. .iconStsz {
  1302. font-size: 40px;
  1303. color: #67c23a;
  1304. cursor: pointer;
  1305. }
  1306. .dis_plays {
  1307. display: flex;
  1308. align-items: center;
  1309. justify-content: space-between;
  1310. margin-bottom: 10px;
  1311. }
  1312. .comInputsty {
  1313. width: 50px;
  1314. height: 24px;
  1315. text-align: center;
  1316. border: none;
  1317. }
  1318. /deep/.el-button {
  1319. border-radius: 8px;
  1320. }
  1321. /deep/.el-dialog {
  1322. border-radius: 8px;
  1323. .el-dialog__header {
  1324. padding: 0;
  1325. .hearders {
  1326. height: 40px;
  1327. display: flex;
  1328. align-items: center;
  1329. justify-content: space-between;
  1330. padding: 0px 18px 0px 20px;
  1331. border-bottom: 1px solid #e2e2e2;
  1332. .leftTitle {
  1333. font-size: 14px;
  1334. font-weight: bold;
  1335. color: #2f4378;
  1336. }
  1337. .rightBoxs {
  1338. display: flex;
  1339. align-items: center;
  1340. img {
  1341. width: 14px;
  1342. height: 14px;
  1343. margin-left: 13px;
  1344. cursor: pointer;
  1345. }
  1346. }
  1347. }
  1348. }
  1349. .el-dialog__footer {
  1350. padding: 0;
  1351. .dialog-footer {
  1352. padding: 0px 40px;
  1353. height: 70px;
  1354. border-top: 1px solid #e2e2e2;
  1355. display: flex;
  1356. align-items: center;
  1357. justify-content: flex-end;
  1358. }
  1359. }
  1360. }
  1361. .imgBox {
  1362. width: 100%;
  1363. // height: 210px;
  1364. border: 1px solid #e2e2e2;
  1365. border-radius: 8px;
  1366. padding: 8px 8px 3px;
  1367. display: flex;
  1368. flex-direction: column;
  1369. align-items: center;
  1370. .imgLabel {
  1371. flex: 1;
  1372. width: 100%;
  1373. border: 1px dotted #e2e2e2;
  1374. color: #999;
  1375. font-size: 14px;
  1376. cursor: pointer;
  1377. border-radius: 8px;
  1378. .msPhoto {
  1379. display: flex;
  1380. justify-content: center;
  1381. align-items: center;
  1382. max-width: 100%;
  1383. max-height: 270px;
  1384. img {
  1385. max-width: 100%;
  1386. max-height: 270px;
  1387. }
  1388. }
  1389. .imgbbx {
  1390. display: flex;
  1391. flex-direction: column;
  1392. align-items: center;
  1393. justify-content: center;
  1394. width: 100%;
  1395. height: 100%;
  1396. i {
  1397. font-weight: bold;
  1398. margin: 14px 0;
  1399. font-size: 24px;
  1400. }
  1401. }
  1402. }
  1403. p {
  1404. margin: 5px 0px;
  1405. }
  1406. }
  1407. </style>