index.vue 39 KB

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