index.vue 40 KB

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