add.vue 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441
  1. <template>
  2. <div class="subPage">
  3. <form class="mainForm">
  4. <ul>
  5. <li class="flex-h">
  6. <span>课程主图:<em>*</em></span>
  7. <div class="flex-item">
  8. <div>
  9. <el-upload
  10. class="avatar-uploader"
  11. action='string'
  12. :http-request="toolClass.upload"
  13. :show-file-list="false"
  14. :on-success="handleAvatarSuccess">
  15. <img v-if="detail.CourseImg" :src="detail.CourseImg" class="avatar">
  16. <i v-else class="el-icon-plus avatar-uploader-icon"></i>
  17. </el-upload>
  18. </div>
  19. </div>
  20. </li>
  21. <li class="flex-h">
  22. <span>课程名称:<em>*</em></span>
  23. <div class="flex-item">
  24. <div style="width: 50%;">
  25. <el-input
  26. placeholder="请输入课程名称"
  27. v-model="detail.CourseName"
  28. clearable
  29. >
  30. </el-input>
  31. </div>
  32. </div>
  33. </li>
  34. <li class="flex-h">
  35. <span>课程类型:<em>*</em></span>
  36. <div class="flex-item">
  37. <div style="width: 50%;">
  38. <el-select v-model="detail.LocationId" placeholder="请选择">
  39. <el-option
  40. v-for="item in location"
  41. :key="item.LocationId"
  42. :label="item.LocationName"
  43. :value="item.LocationId">
  44. </el-option>
  45. </el-select>
  46. </div>
  47. </div>
  48. </li>
  49. <li class="flex-h">
  50. <span>课程价格:<em>*</em></span>
  51. <div class="flex-item">
  52. <div style="width: 200px;">
  53. <el-input
  54. placeholder="请输入课程价格"
  55. v-model="detail.Price"
  56. clearable
  57. >
  58. </el-input>
  59. </div>
  60. </div>
  61. </li>
  62. <li class="flex-h">
  63. <span>案场:<em>*</em></span>
  64. <div class="flex-item">
  65. <div style="width: 50%;">
  66. <el-select v-model="CaseId" placeholder="请选择">
  67. <el-option
  68. v-for="item in cases"
  69. :key="item.CaseId"
  70. :label="item.CaseName"
  71. :value="item.CaseId">
  72. </el-option>
  73. </el-select>
  74. </div>
  75. </div>
  76. </li>
  77. <li class="flex-h">
  78. <span>开课人数:<em>*</em></span>
  79. <div class="flex-item">
  80. <div style="width: 200px;">
  81. <el-input
  82. placeholder="请输入开课人数"
  83. v-model="detail.MaxNum"
  84. clearable
  85. >
  86. </el-input>
  87. </div>
  88. </div>
  89. </li>
  90. <li class="flex-h">
  91. <span>最小开课人数:<em>*</em></span>
  92. <div class="flex-item">
  93. <div style="width: 200px;">
  94. <el-input
  95. placeholder="请输入开课人数"
  96. v-model="detail.MinNum"
  97. clearable
  98. >
  99. </el-input>
  100. </div>
  101. </div>
  102. </li>
  103. <li class="flex-h">
  104. <span>课时数:<em>*</em></span>
  105. <div class="flex-item">
  106. <div style="width: 200px;">
  107. <el-input
  108. placeholder="请输入课时数"
  109. v-model="detail.CourseNum"
  110. clearable
  111. >
  112. </el-input>
  113. </div>
  114. </div>
  115. </li>
  116. <li class="flex-h">
  117. <span>课程时间:<em>*</em></span>
  118. <div class="flex-item">
  119. <div>
  120. <el-date-picker
  121. value-format="yyyy-MM-ddT00:00:00Z"
  122. :picker-options="pickerOptions"
  123. v-model="detail.BeginDate"
  124. type="date"
  125. placeholder="选择起始日期">
  126. </el-date-picker>
  127. <span style="line-height:40px;">至</span>
  128. <el-date-picker
  129. value-format="yyyy-MM-ddT23:59:59Z"
  130. :picker-options="pickerOptions"
  131. v-model="detail.EndDate"
  132. type="date"
  133. placeholder="选择截止日期">
  134. </el-date-picker>
  135. <!-- <el-date-picker
  136. v-model="courseDate"
  137. type="daterange"
  138. align="right"
  139. unlink-panels
  140. range-separator="至"
  141. start-placeholder="开始日期"
  142. end-placeholder="结束日期"
  143. :default-time="['00:00:00', '23:59:59']"
  144. :picker-options="pickerOptions">
  145. </el-date-picker> -->
  146. </div>
  147. </div>
  148. </li>
  149. <li class="flex-h">
  150. <span>课程计划备注:</span>
  151. <div class="flex-item">
  152. <div style="width: 50%;">
  153. <el-input
  154. type="textarea"
  155. maxlength="10"
  156. autosize
  157. placeholder="请输入备注"
  158. v-model="detail.Remark"
  159. clearable
  160. >
  161. </el-input>
  162. </div>
  163. </div>
  164. </li>
  165. <li class="flex-h">
  166. <span>课程标签:</span>
  167. <div class="flex-item">
  168. <div style="width: 50%;">
  169. <el-select
  170. style="width:100%"
  171. v-model="tags"
  172. multiple
  173. filterable
  174. allow-create
  175. default-first-option
  176. placeholder="请选择课程标签">
  177. <el-option
  178. v-for="item in tagList.list"
  179. :key="item.TagId"
  180. :label="item.TagName"
  181. :value="item.TagId"
  182. :value-key="item.TagId"
  183. >
  184. </el-option>
  185. </el-select>
  186. </div>
  187. </div>
  188. </li>
  189. <li class="flex-h">
  190. <span>课程简介:</span>
  191. <div class="flex-item">
  192. <div style="width: 50%;">
  193. <el-input
  194. type="textarea"
  195. autosize
  196. placeholder="请输入课程简介"
  197. v-model="detail.CourseDesc"
  198. clearable
  199. >
  200. </el-input>
  201. </div>
  202. </div>
  203. </li>
  204. <li class="flex-h">
  205. <span>是否精选课程:<em>*</em></span>
  206. <div class="flex-item">
  207. <div>
  208. <el-radio v-model="detail.IsSelect" :label="1">是</el-radio>
  209. <el-radio v-model="detail.IsSelect" :label="0">否</el-radio>
  210. </div>
  211. </div>
  212. </li>
  213. <li style="text-align:center">
  214. <el-button type="primary" size="mini" @click="submit">保存</el-button>
  215. <el-button type="danger" size="mini" @click="cancel">取消</el-button>
  216. </li>
  217. </ul>
  218. </form>
  219. </div>
  220. </template>
  221. <script>
  222. import { createNamespacedHelpers, mapState } from 'vuex'
  223. const { mapState: mapCourseState, mapActions: mapCourseActions } = createNamespacedHelpers('course')
  224. const { mapState: mapLocationState, mapActions: mapLocationActions } = createNamespacedHelpers('cms')
  225. const { mapState: mapTagState, mapActions: mapTagActions } = createNamespacedHelpers('coursetag')
  226. export default {
  227. name: '',
  228. data () {
  229. return {
  230. // pickerOptions: {
  231. // shortcuts: [{
  232. // text: '最近一周',
  233. // onClick (picker) {
  234. // const end = new Date()
  235. // const start = new Date()
  236. // start.setTime(start.getTime() - 3600 * 1000 * 24 * 7)
  237. // picker.$emit('pick', [start, end])
  238. // }
  239. // }, {
  240. // text: '最近一个月',
  241. // onClick (picker) {
  242. // const end = new Date()
  243. // const start = new Date()
  244. // start.setTime(start.getTime() - 3600 * 1000 * 24 * 30)
  245. // picker.$emit('pick', [start, end])
  246. // }
  247. // }, {
  248. // text: '最近三个月',
  249. // onClick (picker) {
  250. // const end = new Date()
  251. // const start = new Date()
  252. // start.setTime(start.getTime() - 3600 * 1000 * 24 * 90)
  253. // picker.$emit('pick', [start, end])
  254. // }
  255. // }]
  256. // },
  257. }
  258. },
  259. computed: {
  260. ...mapLocationState({
  261. location: x => x.location
  262. }),
  263. ...mapCourseState({
  264. detail: x => x.courseInfo
  265. }),
  266. ...mapState({
  267. cases: x => x.app.cases.list,
  268. caseid: x => x.app.cases.default,
  269. orgid: x => x.app.user.OrgId,
  270. }),
  271. ...mapTagState({
  272. tagList: x => x.tagList
  273. }),
  274. CaseId: {
  275. get () {
  276. return this.detail.CaseId || this.caseid
  277. },
  278. set (val) {
  279. this.UpdateInfo({ ...this.detail, CaseId: val })
  280. }
  281. },
  282. pickerOptions () {
  283. var beginDate = Date.now() - 24 * 60 * 60 * 1000
  284. return {
  285. disabledDate (time) {
  286. return time.getTime() < beginDate
  287. }
  288. }
  289. },
  290. courseDate: {
  291. get () {
  292. return this.detail.BeginDate && this.detail.EndDate ? [this.detail.BeginDate, this.detail.EndDate] : []
  293. },
  294. set (val) {
  295. this.UpdateInfo({ ...this.detail, BeginDate: val[0], EndDate: val[1] })
  296. },
  297. },
  298. tags: {
  299. get () {
  300. return (this.detail.CourseTags || []).map(x => x.TagId)
  301. },
  302. set (val) {
  303. let v = val.map(x => {
  304. return {
  305. TagId: x,
  306. }
  307. })
  308. this.UpdateInfo({ ...this.detail, CourseTags: v })
  309. }
  310. },
  311. },
  312. components: {},
  313. methods: {
  314. ...mapCourseActions([
  315. 'GetCourseByID',
  316. 'AddCourse',
  317. 'UpdateCourse',
  318. 'UpdateInfo',
  319. ]),
  320. ...mapLocationActions([
  321. 'updateLocationInfo',
  322. ]),
  323. ...mapTagActions([
  324. 'GetCourseTagList',
  325. ]),
  326. handleAvatarSuccess (res, file) {
  327. this.UpdateInfo({ ...this.detail, CourseImg: res.result.url })
  328. },
  329. upLoad (item) {
  330. this.toolClass.upload(item).then((res) => { this.handleAvatarSuccess(res, item.file) })
  331. },
  332. checkFn (arr) {
  333. for (var n = 0; n < arr.length; n++) {
  334. if (arr[n].type === 'isNull' && !arr[n].target) {
  335. this.$message({
  336. message: arr[n].errorMsg,
  337. type: 'error'
  338. })
  339. return false
  340. }
  341. }
  342. return true
  343. },
  344. submit () { // 提交数据
  345. var checkOff = this.checkFn([{
  346. target: Boolean(this.detail.CourseImg || ''),
  347. errorMsg: '课程主图不能为空',
  348. type: 'isNull'
  349. }, {
  350. target: Boolean(this.detail.CourseName || ''),
  351. errorMsg: '课程名称不能为空',
  352. type: 'isNull'
  353. }, {
  354. target: Boolean(this.detail.LocationId || ''),
  355. errorMsg: '课程类型不能为空',
  356. type: 'isNull'
  357. }, {
  358. target: Boolean(this.detail.Price || ''),
  359. errorMsg: '课程价格不能为空',
  360. type: 'isNull'
  361. }, {
  362. target: Boolean(this.detail.MaxNum || ''),
  363. errorMsg: '开课人数不能为空',
  364. type: 'isNull'
  365. }, {
  366. target: Boolean(this.detail.MinNum || ''),
  367. errorMsg: '最小开课人数不能为空',
  368. type: 'isNull'
  369. }, {
  370. target: Boolean(this.detail.CourseNum || ''),
  371. errorMsg: '课时数不能为空',
  372. type: 'isNull'
  373. }, {
  374. target: Boolean(this.detail.BeginDate || ''),
  375. errorMsg: '起始日期不能为空',
  376. type: 'isNull'
  377. }, {
  378. target: Boolean(this.detail.EndDate || ''),
  379. errorMsg: '截止日期不能为空',
  380. type: 'isNull'
  381. }, {
  382. target: Boolean(String(this.detail.IsSelect) || ''),
  383. errorMsg: '是否精选课程不能为空',
  384. type: 'isNull'
  385. }])
  386. if (!checkOff) {
  387. return false
  388. }
  389. const { id } = this.$route.query
  390. if (!id || id === '') {
  391. this.UpdateInfo({ ...this.detail, CourseId: '' })
  392. }
  393. const _that = this
  394. this.detail.tagids = this.tags.map(x => {
  395. let tagfilter = (_that.tagList.list || []).filter(tag => tag.TagId === x)
  396. if (tagfilter.length > 0) {
  397. return tagfilter[0].TagName + ':' + tagfilter[0].TagId
  398. } else {
  399. return x
  400. }
  401. }).join(',')
  402. if ((this.detail.CourseId || '') === '') {
  403. this.detail.OrgId = this.orgid
  404. if (!this.detail.CaseId || this.detail.CaseId === '') {
  405. this.detail.CaseId = this.caseid
  406. }
  407. this.AddCourse({ ...this.detail, callback: _that.afterSave })
  408. } else {
  409. this.UpdateCourse({ ...this.detail, callback: _that.afterSave })
  410. }
  411. },
  412. afterSave () {
  413. this.$message({
  414. type: 'success',
  415. message: '操作成功'
  416. })
  417. this.$router.push({ name: 'courseList' })
  418. },
  419. cancel () {
  420. this.$router.push({ name: 'courseList' })
  421. }
  422. },
  423. mounted () {
  424. this.updateLocationInfo(false)
  425. this.GetCourseTagList({ pagesize: 100 })
  426. const { id } = this.$route.query
  427. if (id && id !== '') {
  428. this.GetCourseByID({ id: id })
  429. } else {
  430. // this.SetNull()
  431. }
  432. }
  433. }
  434. </script>
  435. <!-- Add "scoped" attribute to limit CSS to this component only -->
  436. <style lang="scss" scoped>
  437. </style>