add.vue 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430
  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:00+08:00"
  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:59+08:00"
  130. :picker-options="pickerOptions"
  131. v-model="detail.EndDate"
  132. type="date"
  133. placeholder="选择截止日期">
  134. </el-date-picker>
  135. </div>
  136. </div>
  137. </li>
  138. <li class="flex-h">
  139. <span>课程计划备注:</span>
  140. <div class="flex-item">
  141. <div style="width: 50%;">
  142. <el-input
  143. type="textarea"
  144. maxlength="10"
  145. autosize
  146. placeholder="请输入备注"
  147. v-model="detail.Remark"
  148. clearable
  149. >
  150. </el-input>
  151. </div>
  152. </div>
  153. </li>
  154. <li class="flex-h">
  155. <span>课程标签:</span>
  156. <div class="flex-item">
  157. <div style="width: 50%;">
  158. <el-select
  159. style="width:100%"
  160. v-model="tags"
  161. multiple
  162. filterable
  163. allow-create
  164. default-first-option
  165. placeholder="请选择课程标签">
  166. <el-option
  167. v-for="item in tagList.list"
  168. :key="item.TagId"
  169. :label="item.TagName"
  170. :value="item.TagId"
  171. :value-key="item.TagId"
  172. >
  173. </el-option>
  174. </el-select>
  175. </div>
  176. </div>
  177. </li>
  178. <li class="flex-h">
  179. <span>课程简介:</span>
  180. <div class="flex-item">
  181. <div style="width: 50%;">
  182. <el-input
  183. type="textarea"
  184. autosize
  185. placeholder="请输入课程简介"
  186. v-model="detail.CourseDesc"
  187. clearable
  188. >
  189. </el-input>
  190. </div>
  191. </div>
  192. </li>
  193. <li class="flex-h">
  194. <span>是否精选课程:<em>*</em></span>
  195. <div class="flex-item">
  196. <div>
  197. <el-radio v-model="detail.IsSelect" :label="1">是</el-radio>
  198. <el-radio v-model="detail.IsSelect" :label="0">否</el-radio>
  199. </div>
  200. </div>
  201. </li>
  202. <li style="text-align:center">
  203. <el-button type="primary" size="mini" @click="submit">保存</el-button>
  204. <el-button type="danger" size="mini" @click="cancel">取消</el-button>
  205. </li>
  206. </ul>
  207. </form>
  208. </div>
  209. </template>
  210. <script>
  211. import { createNamespacedHelpers, mapState } from 'vuex'
  212. const { mapState: mapCourseState, mapActions: mapCourseActions } = createNamespacedHelpers('course')
  213. const { mapState: mapLocationState, mapActions: mapLocationActions } = createNamespacedHelpers('cms')
  214. const { mapState: mapTagState, mapActions: mapTagActions } = createNamespacedHelpers('coursetag')
  215. export default {
  216. name: '',
  217. data () {
  218. return {
  219. // pickerOptions: {
  220. // shortcuts: [{
  221. // text: '最近一周',
  222. // onClick (picker) {
  223. // const end = new Date()
  224. // const start = new Date()
  225. // start.setTime(start.getTime() - 3600 * 1000 * 24 * 7)
  226. // picker.$emit('pick', [start, end])
  227. // }
  228. // }, {
  229. // text: '最近一个月',
  230. // onClick (picker) {
  231. // const end = new Date()
  232. // const start = new Date()
  233. // start.setTime(start.getTime() - 3600 * 1000 * 24 * 30)
  234. // picker.$emit('pick', [start, end])
  235. // }
  236. // }, {
  237. // text: '最近三个月',
  238. // onClick (picker) {
  239. // const end = new Date()
  240. // const start = new Date()
  241. // start.setTime(start.getTime() - 3600 * 1000 * 24 * 90)
  242. // picker.$emit('pick', [start, end])
  243. // }
  244. // }]
  245. // },
  246. }
  247. },
  248. computed: {
  249. ...mapLocationState({
  250. location: x => x.location
  251. }),
  252. ...mapCourseState({
  253. detail: x => x.courseInfo
  254. }),
  255. ...mapState({
  256. cases: x => x.app.cases.list,
  257. caseid: x => x.app.cases.default,
  258. orgid: x => x.app.user.OrgId,
  259. }),
  260. ...mapTagState({
  261. tagList: x => x.tagList
  262. }),
  263. CaseId: {
  264. get () {
  265. return this.detail.CaseId || this.caseid
  266. },
  267. set (val) {
  268. this.UpdateInfo({ ...this.detail, CaseId: val })
  269. }
  270. },
  271. pickerOptions () {
  272. var beginDate = Date.now() - 24 * 60 * 60 * 1000
  273. return {
  274. disabledDate (time) {
  275. return time.getTime() < beginDate
  276. }
  277. }
  278. },
  279. courseDate: {
  280. get () {
  281. return this.detail.BeginDate && this.detail.EndDate ? [this.detail.BeginDate, this.detail.EndDate] : []
  282. },
  283. set (val) {
  284. this.UpdateInfo({ ...this.detail, BeginDate: val[0], EndDate: val[1] })
  285. },
  286. },
  287. tags: {
  288. get () {
  289. return (this.detail.CourseTags || []).map(x => x.TagId)
  290. },
  291. set (val) {
  292. let v = val.map(x => {
  293. return {
  294. TagId: x,
  295. }
  296. })
  297. this.UpdateInfo({ ...this.detail, CourseTags: v })
  298. }
  299. },
  300. },
  301. components: {},
  302. methods: {
  303. ...mapCourseActions([
  304. 'GetCourseByID',
  305. 'AddCourse',
  306. 'UpdateCourse',
  307. 'UpdateInfo',
  308. ]),
  309. ...mapLocationActions([
  310. 'updateLocationInfo',
  311. ]),
  312. ...mapTagActions([
  313. 'GetCourseTagList',
  314. ]),
  315. handleAvatarSuccess (res, file) {
  316. this.UpdateInfo({ ...this.detail, CourseImg: res.result.url })
  317. },
  318. upLoad (item) {
  319. this.toolClass.upload(item).then((res) => { this.handleAvatarSuccess(res, item.file) })
  320. },
  321. checkFn (arr) {
  322. for (var n = 0; n < arr.length; n++) {
  323. if (arr[n].type === 'isNull' && !arr[n].target) {
  324. this.$message({
  325. message: arr[n].errorMsg,
  326. type: 'error'
  327. })
  328. return false
  329. }
  330. }
  331. return true
  332. },
  333. submit () { // 提交数据
  334. var checkOff = this.checkFn([{
  335. target: Boolean(this.detail.CourseImg || ''),
  336. errorMsg: '课程主图不能为空',
  337. type: 'isNull'
  338. }, {
  339. target: Boolean(this.detail.CourseName || ''),
  340. errorMsg: '课程名称不能为空',
  341. type: 'isNull'
  342. }, {
  343. target: Boolean(this.detail.LocationId || ''),
  344. errorMsg: '课程类型不能为空',
  345. type: 'isNull'
  346. }, {
  347. target: Boolean(this.detail.Price || ''),
  348. errorMsg: '课程价格不能为空',
  349. type: 'isNull'
  350. }, {
  351. target: Boolean(this.detail.MaxNum || ''),
  352. errorMsg: '开课人数不能为空',
  353. type: 'isNull'
  354. }, {
  355. target: Boolean(this.detail.MinNum || ''),
  356. errorMsg: '最小开课人数不能为空',
  357. type: 'isNull'
  358. }, {
  359. target: Boolean(this.detail.CourseNum || ''),
  360. errorMsg: '课时数不能为空',
  361. type: 'isNull'
  362. }, {
  363. target: Boolean(this.detail.BeginDate || ''),
  364. errorMsg: '起始日期不能为空',
  365. type: 'isNull'
  366. }, {
  367. target: Boolean(this.detail.EndDate || ''),
  368. errorMsg: '截止日期不能为空',
  369. type: 'isNull'
  370. }, {
  371. target: Boolean(String(this.detail.IsSelect) || ''),
  372. errorMsg: '是否精选课程不能为空',
  373. type: 'isNull'
  374. }])
  375. if (!checkOff) {
  376. return false
  377. }
  378. const { id } = this.$route.query
  379. if (!id || id === '') {
  380. this.UpdateInfo({ ...this.detail, CourseId: '' })
  381. }
  382. const _that = this
  383. this.detail.tagids = this.tags.map(x => {
  384. let tagfilter = (_that.tagList.list || []).filter(tag => tag.TagId === x)
  385. if (tagfilter.length > 0) {
  386. return tagfilter[0].TagName + ':' + tagfilter[0].TagId
  387. } else {
  388. return x
  389. }
  390. }).join(',')
  391. if ((this.detail.CourseId || '') === '') {
  392. this.detail.OrgId = this.orgid
  393. if (!this.detail.CaseId || this.detail.CaseId === '') {
  394. this.detail.CaseId = this.caseid
  395. }
  396. this.AddCourse({ ...this.detail, callback: _that.afterSave })
  397. } else {
  398. this.UpdateCourse({ ...this.detail, callback: _that.afterSave })
  399. }
  400. },
  401. afterSave () {
  402. this.$message({
  403. type: 'success',
  404. message: '操作成功'
  405. })
  406. this.$router.push({ name: 'courseList' })
  407. },
  408. cancel () {
  409. this.$router.push({ name: 'courseList' })
  410. }
  411. },
  412. mounted () {
  413. this.updateLocationInfo(false)
  414. this.GetCourseTagList({ pagesize: 100 })
  415. const { id } = this.$route.query
  416. if (id && id !== '') {
  417. this.GetCourseByID({ id: id })
  418. } else {
  419. // this.SetNull()
  420. }
  421. }
  422. }
  423. </script>
  424. <!-- Add "scoped" attribute to limit CSS to this component only -->
  425. <style lang="scss" scoped>
  426. </style>