index.vue 39 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180
  1. <template>
  2. <div class="app-container">
  3. <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="100px">
  4. <el-form-item label="课堂分类" prop="cateId">
  5. <el-select v-model="queryParams.cateId" placeholder="请选择" clearable size="small"
  6. @change="getQuerySubCateList(queryParams.cateId)">
  7. <el-option
  8. v-for="dict in categoryOptions"
  9. :key="dict.dictValue"
  10. :label="dict.dictLabel"
  11. :value="dict.dictValue"
  12. />
  13. </el-select>
  14. </el-form-item>
  15. <el-form-item label="课堂子分类" prop="subCateId">
  16. <el-select v-model="queryParams.subCateId" placeholder="请选择" clearable size="small">
  17. <el-option
  18. v-for="dict in querySubCateOptions"
  19. :key="dict.dictValue"
  20. :label="dict.dictLabel"
  21. :value="dict.dictValue"
  22. />
  23. </el-select>
  24. </el-form-item>
  25. <el-form-item label="课堂名称" prop="courseName">
  26. <el-input
  27. v-model="queryParams.courseName"
  28. placeholder="请输入课堂名称"
  29. clearable
  30. size="small"
  31. @keyup.enter.native="handleQuery"
  32. />
  33. </el-form-item>
  34. <el-form-item label="关联的公司" prop="companyIds">
  35. <el-select v-model="queryParams.companyIdsList" multiple placeholder="请选择公司" filterable clearable style="width: 90%;">
  36. <el-option
  37. v-for="dict in companyOptions"
  38. :key="dict.dictValue"
  39. :label="dict.dictLabel"
  40. :value="dict.dictValue"
  41. />
  42. </el-select>
  43. </el-form-item>
  44. <el-form-item label="课堂类型" prop="isPrivate" style="display: none">
  45. <el-select v-model="queryParams.isPrivate" placeholder="请选择" clearable size="small">
  46. <el-option
  47. v-for="dict in courseTypeOptions"
  48. :key="dict.dictValue"
  49. :label="dict.dictLabel"
  50. :value="dict.dictValue"
  51. />
  52. </el-select>
  53. </el-form-item>
  54. <el-form-item>
  55. <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
  56. <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
  57. </el-form-item>
  58. </el-form>
  59. <el-row :gutter="10" class="mb8">
  60. <el-col :span="1.5">
  61. <el-button
  62. type="primary"
  63. plain
  64. icon="el-icon-plus"
  65. size="mini"
  66. @click="handleAdd"
  67. v-hasPermi="['course:userCourse:add']"
  68. >新增
  69. </el-button>
  70. </el-col>
  71. <el-col :span="1.5">
  72. <el-button
  73. type="success"
  74. plain
  75. icon="el-icon-edit"
  76. size="mini"
  77. :disabled="single"
  78. @click="handleUpdate"
  79. v-hasPermi="['course:userCourse:edit']"
  80. >修改
  81. </el-button>
  82. </el-col>
  83. <el-col :span="1.5">
  84. <el-button
  85. type="danger"
  86. plain
  87. icon="el-icon-delete"
  88. size="mini"
  89. :disabled="multiple"
  90. @click="handleDelete"
  91. v-hasPermi="['course:userCourse:remove']"
  92. >删除
  93. </el-button>
  94. </el-col>
  95. <el-col :span="1.5">
  96. <el-button
  97. type="warning"
  98. plain
  99. icon="el-icon-download"
  100. size="mini"
  101. :loading="exportLoading"
  102. @click="handleExport"
  103. v-hasPermi="['course:userCourse:export']"
  104. >导出
  105. </el-button>
  106. </el-col>
  107. <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
  108. </el-row>
  109. <!-- <el-table height="600" border v-loading="loading" :data="userCourseList" @selection-change="handleSelectionChange" style="width: 100%" :fit="true">-->
  110. <el-table max-height="600" border v-loading="loading" :data="userCourseList" @selection-change="handleSelectionChange" style="width: 100%" :fit="true">
  111. <el-table-column type="selection" width="55" align="center"/>
  112. <el-table-column label="课程ID" align="center" prop="courseId" width="55"/>
  113. <el-table-column label="所属项目" align="center" prop="projectName" width="120"/>
  114. <el-table-column label="封面图片" align="center" prop="imgUrl" width="170">
  115. <template slot-scope="scope">
  116. <el-popover
  117. placement="right"
  118. title=""
  119. trigger="hover"
  120. >
  121. <img slot="reference" :src="scope.row.imgUrl" width="100">
  122. <img :src="scope.row.imgUrl" style="max-width: 300px;">
  123. </el-popover>
  124. </template>
  125. </el-table-column>
  126. <el-table-column label="课堂名称" align="center" show-overflow-tooltip prop="courseName" min-width="100"/>
  127. <el-table-column label="排序" align="center" prop="sort" width="80"/>
  128. <el-table-column label="分类名称" align="center" prop="cateName" width="120"/>
  129. <el-table-column label="子分类名称" align="center" prop="subCateName" width="120"/>
  130. <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
  131. <template slot-scope="scope">
  132. <el-button
  133. size="mini"
  134. type="text"
  135. @click="handleCatalog(scope.row)"
  136. v-hasPermi="['course:userCourse:cateMange']"
  137. >目录管理
  138. </el-button>
  139. <el-button
  140. size="mini"
  141. type="text"
  142. icon="el-icon-edit"
  143. @click="handleUpdate(scope.row)"
  144. v-hasPermi="['course:userCourse:edit']"
  145. >修改
  146. </el-button>
  147. <el-button
  148. size="mini"
  149. type="text"
  150. icon="el-icon-edit"
  151. @click="handleUpdateRedPage(scope.row)"
  152. v-hasPermi="['course:userCourse:editRedPage']"
  153. >统一修改红包金额
  154. </el-button>
  155. <el-button
  156. size="mini"
  157. type="text"
  158. icon="el-icon-edit"
  159. @click="handleCopy(scope.row)"
  160. v-hasPermi="['course:userCourse:copy']"
  161. >复制
  162. </el-button>
  163. <el-button
  164. size="mini"
  165. type="text"
  166. icon="el-icon-delete"
  167. @click="handleDelete(scope.row)"
  168. v-hasPermi="['course:userCourse:remove']"
  169. >删除
  170. </el-button>
  171. <el-button
  172. size="mini"
  173. type="text"
  174. v-if="scope.row.isPrivate === 1"
  175. v-has-permi="['course:userCourse:editConfig']"
  176. @click="configCourse(scope.row)"
  177. >过程页配置
  178. </el-button>
  179. </template>
  180. </el-table-column>
  181. </el-table>
  182. <pagination
  183. v-show="total>0"
  184. :total="total"
  185. :page.sync="queryParams.pageNum"
  186. :limit.sync="queryParams.pageSize"
  187. @pagination="getList"
  188. />
  189. <!-- 添加或修改课程对话框 -->
  190. <el-dialog :title="title" :visible.sync="open" width="1200px" append-to-body>
  191. <el-form ref="form" :model="form" :rules="rules" label-width="110px">
  192. <el-row>
  193. <el-form-item label="所属项目" prop="project">
  194. <el-select v-model="form.project" placeholder="请选择项目" filterable clearable size="small">
  195. <el-option
  196. v-for="dict in projectOptions"
  197. :key="dict.dictValue"
  198. :label="dict.dictLabel"
  199. :value="dict.dictValue"
  200. />
  201. </el-select>
  202. </el-form-item>
  203. </el-row>
  204. <el-row>
  205. <el-col :span="8">
  206. <el-form-item label="课堂名称" prop="courseName">
  207. <el-input v-model="form.courseName" placeholder="请输入课堂名称"/>
  208. </el-form-item>
  209. </el-col>
  210. <el-col :span="8">
  211. <el-form-item label="课堂分类" prop="cateId">
  212. <el-select v-model="form.cateId" placeholder="请选择" clearable size="small"
  213. @change="getSubCateList(form.cateId)">
  214. <el-option
  215. v-for="dict in categoryOptions"
  216. :key="dict.dictValue"
  217. :label="dict.dictLabel"
  218. :value="dict.dictValue"
  219. />
  220. </el-select>
  221. </el-form-item>
  222. </el-col>
  223. <el-col :span="8">
  224. <el-form-item label="课堂子分类" prop="subCateId">
  225. <el-select v-model="form.subCateId" placeholder="请选择" clearable size="small">
  226. <el-option
  227. v-for="dict in subCategoryOptions"
  228. :key="dict.dictValue"
  229. :label="dict.dictLabel"
  230. :value="dict.dictValue"
  231. />
  232. </el-select>
  233. </el-form-item>
  234. </el-col>
  235. </el-row>
  236. <el-row>
  237. <el-col :span="24">
  238. <el-form-item label="排序" prop="sort">
  239. <el-input-number v-model="form.sort" :min="0" label="排序"></el-input-number>
  240. </el-form-item>
  241. </el-col>
  242. </el-row>
  243. <el-row>
  244. <el-col :span="24">
  245. <el-form-item label="课堂简介" prop="description">
  246. <el-input v-model="form.description" type="textarea" :rows="2" placeholder="请输入课堂简介"/>
  247. </el-form-item>
  248. </el-col>
  249. </el-row>
  250. <el-form-item label="课程封面" prop="imgUrl">
  251. <ImageUpload v-model="form.imgUrl" type="image" :num="10" :width="150" :height="150"/>
  252. </el-form-item>
  253. <el-form-item label="关联公司" prop="tags">
  254. <el-select v-model="companyIds" multiple placeholder="请选择公司" filterable clearable style="width: 90%;">
  255. <el-option
  256. v-for="dict in companyOptions"
  257. :key="dict.dictValue"
  258. :label="dict.dictLabel"
  259. :value="dict.dictValue"
  260. />
  261. </el-select>
  262. </el-form-item>
  263. </el-form>
  264. <div slot="footer" class="dialog-footer">
  265. <el-button type="primary" @click="submitForm">确 定</el-button>
  266. <el-button @click="cancel">取 消</el-button>
  267. </div>
  268. </el-dialog>
  269. <el-dialog title="修改课程红包金额" :visible.sync="openRedPage.open" width="1000px" append-to-body>
  270. <el-form ref="openRedPage" :model="openRedPage" :rules="rulesRedPage" label-width="110px">
  271. <el-form-item label="红包金额" prop="redPacketMoney">
  272. <el-input-number v-model="openRedPage.redPacketMoney" :min="0.1" :max="200" :step="0.1"></el-input-number>
  273. </el-form-item>
  274. <div v-if="!!enableRandomRedPacket" style=" display: flex;
  275. flex-direction: column;">
  276. <div v-for="(rule, index) in openRedPage.rules" :key="index" class="form-row">
  277. <el-form-item
  278. label="随机红包金额区间"
  279. :prop="`rules.${index}.minAmount`"
  280. :rules="[
  281. { required: true, message: '请输入最小金额', trigger: 'blur' },
  282. { validator: validateMinAmount, trigger: 'blur', index: index }
  283. ]"
  284. class="form-item-amount"
  285. >
  286. <el-input
  287. v-model.number="rule.minAmount"
  288. type="number"
  289. :min="0.01"
  290. :precision="2"
  291. :step="0.01"
  292. placeholder="最小金额"
  293. size="small"
  294. class="amount-input"
  295. @input="handleAmountInput(rule, 'minAmount')"
  296. ></el-input>
  297. <span class="separator">-</span>
  298. <el-input
  299. v-model.number="rule.maxAmount"
  300. type="number"
  301. :min="rule.minAmount || 0.01"
  302. :precision="2"
  303. :step="0.01"
  304. placeholder="最大金额"
  305. size="small"
  306. class="amount-input"
  307. @input="handleAmountInput(rule, 'maxAmount')"
  308. ></el-input>
  309. <span class="suffix">元</span>
  310. </el-form-item>
  311. <el-form-item
  312. label="随机权重"
  313. :prop="`rules.${index}.weight`"
  314. :rules="[
  315. { required: true, message: '请输入权重', trigger: 'blur' },
  316. { type: 'integer', message: '权重必须为整数', trigger: 'blur' },
  317. ]"
  318. class="form-item-weight"
  319. >
  320. <el-input
  321. v-model.number="rule.weight"
  322. type="number"
  323. :min="1"
  324. placeholder="权重"
  325. size="small"
  326. ></el-input>
  327. </el-form-item>
  328. <el-tooltip class="item" effect="dark" content="权重越高,被随机到的概率越大" placement="top">
  329. <i class="el-icon-question"></i>
  330. </el-tooltip>
  331. <div class="action-buttons">
  332. <el-button
  333. icon="el-icon-plus"
  334. size="mini"
  335. type="text"
  336. @click="addRule(index)"
  337. class="add-btn"
  338. >
  339. 新增
  340. </el-button>
  341. <el-button
  342. icon="el-icon-delete"
  343. size="mini"
  344. type="text"
  345. @click="deleteRule(index)"
  346. :disabled="openRedPage.rules.length <= 1"
  347. class="delete-btn"
  348. >
  349. 删除
  350. </el-button>
  351. </div>
  352. </div>
  353. </div>
  354. </el-form>
  355. <div slot="footer" class="dialog-footer">
  356. <el-button type="primary" @click="submitFormRedPage">确 定</el-button>
  357. <el-button @click="cancelRedPage">取 消</el-button>
  358. </div>
  359. </el-dialog>
  360. <!-- 过程页配置 -->
  361. <el-dialog
  362. :visible.sync="configDialog.dialogVisible"
  363. title="过程页配置"
  364. append-to-body
  365. width="1200px"
  366. >
  367. <el-form :model="configDialog.form" :rules="configDialog.rules" ref="configForm" label-width="110px">
  368. <el-form-item label="过程页图片" prop="coverImg">
  369. <ImageUpload v-model="configDialog.form.coverImg" :height="150" :limit="1" :width="150" type="image"/>
  370. <i class="el-icon-warning"/>
  371. <span style="color: rgb(153, 169, 191)"> 不配置将使用课程默认图片</span>
  372. </el-form-item>
  373. <el-form-item label="首播电视台" prop="tvEnable">
  374. <el-switch v-model="configDialog.form.tvEnable" active-color="#13ce66"/>
  375. </el-form-item>
  376. <el-form-item prop="tv" v-if="configDialog.form.tvEnable">
  377. <el-input v-model="configDialog.form.tv" clearable></el-input>
  378. <i class="el-icon-warning"/>
  379. <span style="color: rgb(153, 169, 191)"> 多个首播电视台,请用英文逗号隔开</span>
  380. </el-form-item>
  381. <el-form-item label="网络播放平台" prop="networkEnable">
  382. <el-switch v-model="configDialog.form.networkEnable" active-color="#13ce66"/>
  383. </el-form-item>
  384. <el-form-item prop="network" v-if="configDialog.form.networkEnable">
  385. <el-input v-model="configDialog.form.network" clearable></el-input>
  386. <i class="el-icon-warning"/>
  387. <span style="color: rgb(153, 169, 191)"> 多个网络播放平台,请用英文逗号隔开</span>
  388. </el-form-item>
  389. <el-form-item label="制作单位" prop="unitEnable">
  390. <el-switch v-model="configDialog.form.unitEnable" active-color="#13ce66"/>
  391. </el-form-item>
  392. <el-form-item prop="unit" v-if="configDialog.form.unitEnable">
  393. <el-input v-model="configDialog.form.unit" clearable></el-input>
  394. <i class="el-icon-warning"/>
  395. <span style="color: rgb(153, 169, 191)"> 多个制作单位,请用英文逗号隔开</span>
  396. </el-form-item>
  397. <el-form-item label="专家顾问团队" prop="teamEnable">
  398. <el-switch v-model="configDialog.form.teamEnable" active-color="#13ce66"/>
  399. </el-form-item>
  400. <el-form-item prop="team" v-if="configDialog.form.teamEnable">
  401. <el-input v-model="configDialog.form.team" clearable></el-input>
  402. <i class="el-icon-warning"/>
  403. <span style="color: rgb(153, 169, 191)"> 多个专家顾问,请用英文逗号隔开</span>
  404. </el-form-item>
  405. <el-form-item label="支持单位" prop="supportEnable">
  406. <el-switch v-model="configDialog.form.supportEnable" active-color="#13ce66"/>
  407. </el-form-item>
  408. <el-form-item prop="support" v-if="configDialog.form.supportEnable">
  409. <el-input v-model="configDialog.form.support" clearable></el-input>
  410. <i class="el-icon-warning"/>
  411. <span style="color: rgb(153, 169, 191)"> 多个支持单位,请用英文逗号隔开</span>
  412. </el-form-item>
  413. </el-form>
  414. <div slot="footer" class="dialog-footer">
  415. <el-button type="primary"
  416. :loading="configDialog.updating"
  417. :disabled="configDialog.updating"
  418. @click="submitConfigForm">确 定</el-button>
  419. <el-button @click="cancelConfig">取 消</el-button>
  420. </div>
  421. </el-dialog>
  422. <el-drawer
  423. :with-header="false"
  424. size="75%"
  425. :title="show.title" :visible.sync="show.open" append-to-body>
  426. <userCourseCatalogDetails ref="userCourseCatalogDetails"/>
  427. </el-drawer>
  428. </div>
  429. </template>
  430. <script>
  431. import {
  432. listUserCourse,
  433. getUserCourse,
  434. delUserCourse,
  435. addUserCourse,
  436. updateUserCourse,
  437. exportUserCourse,
  438. updateIsShow,
  439. copyUserCourse,
  440. putOn,
  441. pullOff, updateUserCourseRedPage,
  442. editConfig
  443. } from '@/api/course/userCourse'
  444. import {getSelectableRange} from "@/api/qw/sopTemp";
  445. import Treeselect from "@riophae/vue-treeselect";
  446. import "@riophae/vue-treeselect/dist/vue-treeselect.css";
  447. import Editor from '@/components/Editor/wang';
  448. import ImageUpload from '@/components/ImageUpload/index';
  449. import {listBySearch} from "@/api/course/userTalent";
  450. import userCourseCatalogDetails from '../../components/course/userCourseCatalogDetails.vue';
  451. import {getAllCourseCategoryList, getCatePidList, getCateListByPid} from "@/api/course/userCourseCategory";
  452. import {allList} from "@/api/company/company";
  453. import VideoUpload from '@/components/VideoUpload/index.vue'
  454. import { getConfigByKey } from '@/api/system/config'
  455. export default {
  456. name: "UserCourse",
  457. components: {
  458. VideoUpload,
  459. Treeselect,
  460. Editor, ImageUpload, userCourseCatalogDetails
  461. },
  462. watch:{
  463. // 深度监听 rules 数组的变化,以更新总权重
  464. "openRedPage.rules": {
  465. handler(val) {
  466. // this.calculateTotalWeight();
  467. this.validateRules();
  468. },
  469. deep: true,
  470. },
  471. },
  472. data() {
  473. return {
  474. talentParam: {
  475. phone: null,
  476. talentId: null
  477. },
  478. talentList: [],
  479. startTimeRange: [],
  480. show: {
  481. title: "目录管理",
  482. open: false
  483. },
  484. activeName: "1",
  485. projectOptions: [],
  486. tagsOptions: [],
  487. tags: [],
  488. companyIds: [],
  489. courseTypeOptions: [],
  490. orOptions: [],
  491. specShowOptions: [],
  492. specTypeOptions: [],
  493. categoryOptions: [],
  494. subCategoryOptions: [],
  495. querySubCateOptions: [],
  496. // 遮罩层
  497. loading: true,
  498. // 导出遮罩层
  499. exportLoading: false,
  500. // 选中数组
  501. ids: [],
  502. // 非单个禁用
  503. single: true,
  504. // 非多个禁用
  505. multiple: true,
  506. // 显示搜索条件
  507. showSearch: true,
  508. // 总条数
  509. total: 0,
  510. // 课程表格数据
  511. userCourseList: [],
  512. companyOptions: [],
  513. // 弹出层标题
  514. title: "",
  515. // 是否显示弹出层
  516. open: false,
  517. openRedPage:{
  518. open:false,
  519. courseId:null,
  520. courseName:null,
  521. redPacketMoney:0.1,
  522. //随机红包配置
  523. rules:[
  524. {
  525. minAmount: 0.01,
  526. maxAmount: 0.01,
  527. weight: 100,
  528. }
  529. ]
  530. },
  531. // 查询参数
  532. queryParams: {
  533. pageNum: 1,
  534. pageSize: 10,
  535. cateId: null,
  536. subCateId: null,
  537. title: null,
  538. imgUrl: null,
  539. userId: null,
  540. sort: null,
  541. status: null,
  542. isVip: null,
  543. isHot: null,
  544. isShow: "1",
  545. views: null,
  546. duration: null,
  547. description: null,
  548. hotRanking: null,
  549. integral: null,
  550. price: null,
  551. isPrivate: 1,
  552. companyIdsList:[],
  553. },
  554. // 表单参数
  555. form: {},
  556. // 表单校验
  557. rules: {
  558. courseName: [
  559. {required: true, message: "课堂名称不能为空", trigger: "blur"}
  560. ],
  561. imgUrl: [
  562. {required: true, message: "封面图片不能为空", trigger: "blur"}
  563. ],
  564. isTui: [
  565. {required: true, message: "是否推荐不能为空", trigger: "blur"}
  566. ],
  567. isBest: [
  568. {required: true, message: "是否精选不能为空", trigger: "blur"}
  569. ],
  570. isFast: [
  571. {required: true, message: "是否允许快进不能为空", trigger: "blur"}
  572. ],
  573. isAutoPlay: [
  574. {required: true, message: "是否自动播放不能为空", trigger: "blur"}
  575. ],
  576. sort: [
  577. {required: true, message: "排序不能为空", trigger: "blur"}
  578. ],
  579. views: [
  580. {required: true, message: "播放量不能为空", trigger: "blur"}
  581. ],
  582. likes: [
  583. {required: true, message: "点赞数不能为空", trigger: "blur"}
  584. ],
  585. favoriteNum: [
  586. {required: true, message: "收藏数不能为空", trigger: "blur"}
  587. ],
  588. shares: [
  589. {required: true, message: "分享数不能为空", trigger: "blur"}
  590. ],
  591. isIntegral: [
  592. {required: true, message: "是否允许积分兑换不能为空", trigger: "blur"}
  593. ],
  594. isShow: [
  595. {required: true, message: "上架状态不能为空", trigger: "blur"}
  596. ],
  597. isPrivate: [
  598. {required: true, message: "公私域不能为空", trigger: "blur"}
  599. ],
  600. integral: [
  601. {required: true, message: "小节兑换积分不能为空", trigger: "blur"}
  602. ],
  603. },
  604. rulesRedPage:{
  605. redPacketMoney: [
  606. {required: true, message: "红包金额不能为空", trigger: "blur"}
  607. ],
  608. },
  609. configDialog: {
  610. dialogVisible: false,
  611. updating: false,
  612. form: {
  613. id: null,
  614. coverImg: null,
  615. tvEnable: 0,
  616. tv: null,
  617. networkEnable: 0,
  618. network: null,
  619. unitEnable: 0,
  620. unit: null,
  621. teamEnable: 0,
  622. team: null,
  623. supportEnable: 0,
  624. support: null
  625. },
  626. rules: {
  627. tv: [
  628. { required: true, message: '首播电视台不能为空', trigger: 'blur' }
  629. ],
  630. network: [
  631. { required: true, message: '网络播放平台不能为空', trigger: 'blur' }
  632. ],
  633. unit: [
  634. { required: true, message: '制作单位不能为空', trigger: 'blur' }
  635. ],
  636. team: [
  637. { required: true, message: '专家顾问团队不能为空', trigger: 'blur' }
  638. ],
  639. support: [
  640. { required: true, message: '支持单位不能为空', trigger: 'blur' }
  641. ],
  642. }
  643. },
  644. enableRandomRedPacket:false
  645. };
  646. },
  647. created() {
  648. this.getList();
  649. getConfigByKey('randomRedpacket:config').then(res=>{
  650. console.log("res::")
  651. console.log(res);
  652. let configData = res.data;
  653. if(!!configData && !!configData.configValue){
  654. let configValue = JSON.parse(configData.configValue);
  655. console.log(configValue);
  656. if(!!configValue.enableRandomRedpacket){
  657. this.enableRandomRedPacket = configValue.enableRandomRedpacket;
  658. }
  659. }
  660. }).catch(res=>{
  661. })
  662. getCatePidList().then(response => {
  663. this.categoryOptions = response.data;
  664. });
  665. getSelectableRange().then(e => {
  666. this.startTimeRange = e.data;
  667. })
  668. // this.getTreeselect();
  669. this.getDicts("sys_spec_show").then(response => {
  670. this.specShowOptions = response.data;
  671. });
  672. this.getDicts("sys_spec_type").then(response => {
  673. this.specTypeOptions = response.data;
  674. });
  675. this.getDicts("sys_course_type").then(response => {
  676. this.courseTypeOptions = response.data;
  677. });
  678. this.getDicts("sys_course_project").then(response => {
  679. this.projectOptions = response.data;
  680. });
  681. this.getDicts("sys_course_tags").then(response => {
  682. this.tagsOptions = response.data;
  683. });
  684. this.getDicts("sys_company_or").then(response => {
  685. this.orOptions = response.data;
  686. });
  687. allList().then(response => {
  688. this.companyOptions = response.rows;
  689. });
  690. },
  691. methods: {
  692. selectTalent() {
  693. },
  694. talentMethod(query) {
  695. if (query !== '') {
  696. this.talentParam.phone = query;
  697. listBySearch(this.talentParam).then(response => {
  698. this.talentList = response.data;
  699. });
  700. }
  701. },
  702. getSubCateList(pid) {
  703. this.form.subCateId = null;
  704. if (pid == '') {
  705. this.subCategoryOptions = [];
  706. return
  707. }
  708. getCateListByPid(pid).then(response => {
  709. this.subCategoryOptions = response.data;
  710. });
  711. },
  712. getQuerySubCateList(pid) {
  713. this.queryParams.subCateId = null;
  714. if (pid == '') {
  715. this.querySubCateOptions = [];
  716. return
  717. }
  718. this.queryParams.subCateId = null;
  719. getCateListByPid(pid).then(response => {
  720. this.querySubCateOptions = response.data;
  721. });
  722. },
  723. handleShow(row) {
  724. var isShowValue = row.isShow === 0 ? 1 : 0;
  725. var course = {courseId: row.courseId, isShow: isShowValue};
  726. updateIsShow(course).then(response => {
  727. this.msgSuccess("修改成功");
  728. this.getList();
  729. });
  730. },
  731. handleCatalog(row) {
  732. const courseId = row.courseId;
  733. this.show.open = true;
  734. setTimeout(() => {
  735. this.$refs.userCourseCatalogDetails.getDetails(courseId, row.courseName, row.isPrivate);
  736. }, 200);
  737. },
  738. /** 转换课堂分类数据结构 */
  739. normalizer(node) {
  740. if (node.children && !node.children.length) {
  741. delete node.children;
  742. }
  743. return {
  744. id: node.cateId,
  745. label: node.cateName,
  746. children: node.children
  747. };
  748. },
  749. getTreeselect() {
  750. getAllCourseCategoryList().then(response => {
  751. this.categoryOptions = [];
  752. const data = this.handleTree(response.data, "cateId", "pid");
  753. this.categoryOptions = data;
  754. });
  755. },
  756. /** 查询课程列表 */
  757. getList() {
  758. this.loading = true;
  759. listUserCourse(this.queryParams).then(response => {
  760. this.userCourseList = response.rows;
  761. this.total = response.total;
  762. this.loading = false;
  763. });
  764. },
  765. // 取消按钮
  766. cancel() {
  767. this.open = false;
  768. this.reset();
  769. },
  770. // 表单重置
  771. reset() {
  772. this.form = {
  773. courseId: null,
  774. cateId: null,
  775. subCateId: null,
  776. title: null,
  777. imgUrl: null,
  778. secondImg: null,
  779. userId: null,
  780. sort: null,
  781. createTime: null,
  782. updateTime: null,
  783. status: 0,
  784. isVip: null,
  785. isAutoPlay: "1",
  786. isIntegral: "0",
  787. isShow: "1",
  788. isFast: "1",
  789. isTui: "1",
  790. isBest: "1",
  791. isNext: "1",
  792. isPrivate: "1",
  793. views: 100000,
  794. duration: null,
  795. description: null,
  796. hotRanking: null,
  797. integral: null,
  798. price: null,
  799. likes: 100000,
  800. shares: 100000,
  801. favoriteNum: 100000,
  802. hotNum: 100000,
  803. };
  804. this.tags = [];
  805. this.subCategoryOptions = []
  806. this.companyIds = []
  807. this.resetForm("form");
  808. },
  809. /** 搜索按钮操作 */
  810. handleQuery() {
  811. this.queryParams.pageNum = 1;
  812. this.getList();
  813. },
  814. /** 重置按钮操作 */
  815. resetQuery() {
  816. this.resetForm("queryForm");
  817. this.queryParams.companyIdsList = [];
  818. this.queryParams.isShow = this.activeName
  819. this.handleQuery();
  820. },
  821. // 多选框选中数据
  822. handleSelectionChange(selection) {
  823. this.ids = selection.map(item => item.courseId)
  824. this.single = selection.length !== 1
  825. this.multiple = !selection.length
  826. },
  827. /** 新增按钮操作 */
  828. handleAdd() {
  829. this.reset();
  830. this.talentList = [];
  831. this.open = true;
  832. this.title = "添加课程";
  833. },
  834. /** 修改按钮操作 */
  835. handleUpdate(row) {
  836. this.reset();
  837. this.talentList = [];
  838. const courseId = row.courseId || this.ids
  839. getUserCourse(courseId).then(response => {
  840. this.form = response.data;
  841. // this.form.cateId = response.data.cateId.toString();
  842. if (this.form.cateId) {
  843. getCateListByPid(this.form.cateId).then(response => {
  844. this.subCategoryOptions = response.data;
  845. });
  846. }
  847. // this.form.courseType = response.data.courseType.toString();
  848. if (response.data.project != null) {
  849. this.form.project = response.data.project.toString();
  850. }
  851. if (response.data.tags != null) {
  852. this.tags = response.data.tags.split(",")
  853. }
  854. this.form.isAutoPlay = response.data.isAutoPlay.toString();
  855. this.form.isShow = response.data.isShow.toString();
  856. this.form.isBest = response.data.isBest.toString();
  857. this.form.isFast = response.data.isFast.toString();
  858. this.form.isIntegral = response.data.isIntegral.toString();
  859. this.form.isTui = response.data.isTui.toString();
  860. this.form.isNext = response.data.isNext.toString();
  861. this.form.isPrivate = response.data.isPrivate.toString();
  862. this.talentParam.talentId = response.data.talentId;
  863. if (this.form.companyIds != null) {
  864. this.companyIds = ((this.form.companyIds).split(",").map(Number))
  865. } else {
  866. this.companyIds = []
  867. }
  868. listBySearch(this.talentParam).then(response => {
  869. this.talentList = response.data;
  870. });
  871. this.open = true;
  872. this.title = "修改课程";
  873. });
  874. },
  875. handleUpdateRedPage(row){
  876. this.openRedPage.open=true;
  877. this.openRedPage.courseId=row.courseId;
  878. this.openRedPage.courseName=row.courseName;
  879. },
  880. /** 提交按钮 */
  881. submitForm() {
  882. this.$refs["form"].validate(valid => {
  883. if (valid) {
  884. this.form.companyIds = this.companyIds.toString()
  885. // 私域课程
  886. this.form.isPrivate = 1
  887. if (this.form.courseId != null) {
  888. updateUserCourse(this.form).then(response => {
  889. this.msgSuccess("修改成功");
  890. this.open = false;
  891. this.getList();
  892. });
  893. } else {
  894. addUserCourse(this.form).then(response => {
  895. this.msgSuccess("新增成功");
  896. this.open = false;
  897. this.getList();
  898. });
  899. }
  900. }
  901. });
  902. },
  903. submitFormRedPage(){
  904. const courseId = this.openRedPage.courseId;
  905. const redPacketMoney = this.openRedPage.redPacketMoney;
  906. let randomRedPacketRules = JSON.stringify( this.openRedPage.rules);
  907. console.log(randomRedPacketRules)
  908. this.$confirm('是否确认将课程id 为"' + courseId + '"的红包批量修改为:【'+redPacketMoney+'】?', "警告", {
  909. confirmButtonText: "确定",
  910. cancelButtonText: "取消",
  911. type: "warning"
  912. }).then(function () {
  913. return updateUserCourseRedPage({courseId:courseId,redPacketMoney:redPacketMoney,randomRedPacketRules:randomRedPacketRules});
  914. }).then(() => {
  915. this.getList();
  916. this.msgSuccess("修改成功");
  917. this.openRedPage.open=false;
  918. }).finally(() => {
  919. this.getList();
  920. this.openRedPage.open=false;
  921. });
  922. },
  923. cancelRedPage(){
  924. this.openRedPage.open=false;
  925. },
  926. /** 复制按钮操作 */
  927. handleCopy(row) {
  928. const courseId = row.courseId;
  929. this.$confirm('是否确认复制课程编号为"' + courseId + '"的数据项?', "警告", {
  930. confirmButtonText: "确定",
  931. cancelButtonText: "取消",
  932. type: "warning"
  933. }).then(function () {
  934. return copyUserCourse(courseId);
  935. }).then(() => {
  936. this.getList();
  937. this.msgSuccess("复制成功");
  938. }).catch(() => {
  939. });
  940. },
  941. /** 删除按钮操作 */
  942. handleDelete(row) {
  943. const courseIds = row.courseId || this.ids;
  944. this.$confirm('是否确认删除课程编号为"' + courseIds + '"的数据项?', "警告", {
  945. confirmButtonText: "确定",
  946. cancelButtonText: "取消",
  947. type: "warning"
  948. }).then(function () {
  949. return delUserCourse(courseIds);
  950. }).then(() => {
  951. this.getList();
  952. this.msgSuccess("删除成功");
  953. }).catch(() => {
  954. });
  955. },
  956. /** 导出按钮操作 */
  957. handleExport() {
  958. const queryParams = this.queryParams;
  959. this.$confirm('是否确认导出所有课程数据项?', "警告", {
  960. confirmButtonText: "确定",
  961. cancelButtonText: "取消",
  962. type: "warning"
  963. }).then(() => {
  964. this.exportLoading = true;
  965. return exportUserCourse(queryParams);
  966. }).then(response => {
  967. this.download(response.msg);
  968. this.exportLoading = false;
  969. }).catch(() => {
  970. });
  971. },
  972. putOn() {
  973. const courseIds = this.ids;
  974. if (courseIds == null || courseIds == "") {
  975. return this.$message("未选择课程");
  976. }
  977. this.$confirm('是否确认批量上架课程?', "警告", {
  978. confirmButtonText: "确定",
  979. cancelButtonText: "取消",
  980. type: "warning"
  981. }).then(function () {
  982. return putOn(courseIds);
  983. }).then(() => {
  984. this.getList();
  985. this.msgSuccess("上架成功");
  986. }).catch(function () {
  987. });
  988. },
  989. pullOff() {
  990. const courseIds = this.ids;
  991. if (courseIds == null || courseIds == "") {
  992. return this.$message("未选择课程");
  993. }
  994. this.$confirm('是否确认批量下架课程?', "警告", {
  995. confirmButtonText: "确定",
  996. cancelButtonText: "取消",
  997. type: "warning"
  998. }).then(function () {
  999. return pullOff(courseIds);
  1000. }).then(() => {
  1001. this.getList();
  1002. this.msgSuccess("下架成功");
  1003. }).catch(function () {
  1004. });
  1005. },
  1006. configCourse(row) {
  1007. if (row.configJson) {
  1008. this.configDialog.form = {
  1009. tvEnable: 0,
  1010. networkEnable: 0,
  1011. unitEnable: 0,
  1012. teamEnable: 0,
  1013. supportEnable: 0,
  1014. ...JSON.parse(row.configJson)
  1015. }
  1016. }
  1017. this.configDialog.form.id = row.courseId
  1018. this.configDialog.dialogVisible = true;
  1019. this.configDialog.updating = false
  1020. },
  1021. submitConfigForm() {
  1022. this.$refs['configForm'].validate(valid => {
  1023. if (!valid) {
  1024. this.msgError('请完善配置内容')
  1025. return
  1026. }
  1027. if (this.configDialog.updating) {
  1028. return
  1029. }
  1030. this.configDialog.updating = true
  1031. const content = {
  1032. coverImg: this.configDialog.form.coverImg,
  1033. tvEnable: this.configDialog.form.tvEnable,
  1034. tv: this.configDialog.form.tv?.replace(",",","),
  1035. networkEnable: this.configDialog.form.networkEnable,
  1036. network: this.configDialog.form.network?.replace(",",","),
  1037. unitEnable: this.configDialog.form.unitEnable,
  1038. unit: this.configDialog.form.unit?.replace(",",","),
  1039. teamEnable: this.configDialog.form.teamEnable,
  1040. team: this.configDialog.form.team?.replace(",",","),
  1041. supportEnable: this.configDialog.form.supportEnable,
  1042. support: this.configDialog.form.support?.replace(",",","),
  1043. }
  1044. const params = {
  1045. id: this.configDialog.form.id,
  1046. configJson: JSON.stringify(content)
  1047. }
  1048. editConfig(params).then(() => {
  1049. this.msgSuccess('修改成功')
  1050. this.configDialog.dialogVisible = false;
  1051. this.getList()
  1052. }).finally(() => {
  1053. setTimeout(() => {
  1054. this.configDialog.updating = false
  1055. }, 500)
  1056. })
  1057. })
  1058. },
  1059. cancelConfig() {
  1060. this.configDialog.form = {
  1061. id: null,
  1062. coverImg: null,
  1063. tvEnable: 0,
  1064. tv: null,
  1065. networkEnable: 0,
  1066. network: null,
  1067. unitEnable: 0,
  1068. unit: null,
  1069. teamEnable: 0,
  1070. team: null,
  1071. supportEnable: 0,
  1072. support: null
  1073. }
  1074. this.resetForm('configForm')
  1075. this.configDialog.dialogVisible = false;
  1076. },
  1077. // 实时过滤金额输入,只允许两位小数
  1078. handleAmountInput(rule, field) {
  1079. let value = rule[field];
  1080. if (value === null || value === undefined) return;
  1081. // 转换为字符串处理
  1082. let str = value.toString();
  1083. // 移除除数字和小数点外的所有字符
  1084. str = str.replace(/[^0-9.]/g, '');
  1085. // 只保留一个小数点
  1086. const dotIndex = str.indexOf('.');
  1087. if (dotIndex !== -1) {
  1088. str = str.substring(0, dotIndex + 1) + str.substring(dotIndex + 1).replace(/\./g, '');
  1089. }
  1090. // 限制小数点后最多两位
  1091. if (dotIndex !== -1 && str.length > dotIndex + 3) {
  1092. str = str.substring(0, dotIndex + 3);
  1093. }
  1094. // 转换回数字并更新
  1095. rule[field] = parseFloat(str) || 0;
  1096. },
  1097. deleteRule(index) {
  1098. this.$confirm("确定要删除这个区间吗?", "提示", {
  1099. confirmButtonText: "确定",
  1100. cancelButtonText: "取消",
  1101. type: "warning",
  1102. }).then(() => {
  1103. this.openRedPage.rules.splice(index, 1);
  1104. this.$message({
  1105. type: "success",
  1106. message: "删除成功!",
  1107. });
  1108. });
  1109. },
  1110. addRule(index) {
  1111. // 在当前行的后面插入一个新行
  1112. this.openRedPage.rules.splice(index + 1, 0, {
  1113. minAmount: 0.01,
  1114. maxAmount: 0.01,
  1115. weight: 100,
  1116. });
  1117. },
  1118. // 自定义校验规则:确保最大金额大于最小金额
  1119. validateMinAmount(rule, value, callback) {
  1120. // debugger;
  1121. // const maxAmount = this.form29.rules[].maxAmount
  1122. const index = rule.index;
  1123. const maxAmount = this.openRedPage.rules[index].maxAmount;
  1124. if (value > maxAmount) {
  1125. callback(new Error("最小金额不能大于最大金额"));
  1126. } else {
  1127. callback();
  1128. }
  1129. },
  1130. validateRules() {
  1131. this.openRedPage.rules.forEach((rule) => {
  1132. if (rule.minAmount === undefined || rule.minAmount < 0.01) {
  1133. rule.minAmount = 0.01;
  1134. }
  1135. if (rule.maxAmount === undefined || rule.maxAmount < rule.minAmount) {
  1136. rule.maxAmount = rule.minAmount;
  1137. }
  1138. if (rule.weight === undefined || rule.weight < 1) {
  1139. rule.weight = 1;
  1140. }
  1141. });
  1142. },
  1143. }
  1144. };
  1145. </script>