index.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441
  1. <template>
  2. <div class="l-flex--col">
  3. <template v-if="isExact">
  4. <el-tabs
  5. v-model="active"
  6. class="c-tabs"
  7. @tab-click="onTabClick"
  8. >
  9. <el-tab-pane
  10. label="节目排期"
  11. name="normal"
  12. />
  13. <el-tab-pane
  14. label="默认排期"
  15. name="defaults"
  16. />
  17. </el-tabs>
  18. <c-table
  19. class="has-padding"
  20. :curr="currObj"
  21. @pagination="getList"
  22. >
  23. <template #header>
  24. <div class="l-flex__auto c-sibling-item">
  25. <button
  26. v-if="isNormal"
  27. class="o-button"
  28. @click="toAdd"
  29. >
  30. <i class="o-button__icon el-icon-circle-plus-outline" />
  31. 新增
  32. </button>
  33. </div>
  34. <el-select
  35. v-model="currObj.params.type"
  36. class="l-flex__none c-sibling-item o-select"
  37. placeholder="请选择类型"
  38. @change="search"
  39. >
  40. <el-option
  41. v-for="item in scheduleOptions"
  42. :key="item.label"
  43. :label="item.label"
  44. :value="item.value"
  45. />
  46. </el-select>
  47. <el-select
  48. v-model="currObj.params.status"
  49. class="l-flex__none c-sibling-item o-select"
  50. placeholder="请选择状态"
  51. @change="search"
  52. >
  53. <el-option
  54. v-for="item in statusOptions"
  55. :key="item.label"
  56. :label="item.label"
  57. :value="item.value"
  58. />
  59. </el-select>
  60. <search-input
  61. v-model.trim="currObj.params.name"
  62. class="l-flex__none c-sibling-item"
  63. placeholder="排期名称"
  64. @search="search"
  65. />
  66. <button
  67. class="l-flex__none c-sibling-item o-button"
  68. @click="search"
  69. >
  70. 搜索
  71. </button>
  72. </template>
  73. <el-table-column
  74. prop="name"
  75. label="排期名称"
  76. align="center"
  77. show-overflow-tooltip
  78. />
  79. <el-table-column
  80. prop="typeName"
  81. label="类型"
  82. align="center"
  83. show-overflow-tooltip
  84. />
  85. <el-table-column
  86. prop="resolutionRatio"
  87. label="分辨率"
  88. align="center"
  89. show-overflow-tooltip
  90. />
  91. <el-table-column
  92. label="审核状态"
  93. align="center"
  94. min-width="100"
  95. >
  96. <template v-slot="scope">
  97. <el-tag
  98. v-if="scope.row.status === 1"
  99. class="o-tag u-readonly"
  100. type="warning"
  101. size="medium"
  102. >
  103. 未审核
  104. </el-tag>
  105. <el-tag
  106. v-else-if="scope.row.status === 2"
  107. class="o-tag u-readonly"
  108. type="success"
  109. size="medium"
  110. >
  111. 已审核
  112. </el-tag>
  113. <el-tag
  114. v-else
  115. class="o-tag u-readonly"
  116. size="medium"
  117. >
  118. 待提交
  119. </el-tag>
  120. </template>
  121. </el-table-column>
  122. <el-table-column
  123. prop="createTime"
  124. label="创建时间"
  125. align="center"
  126. show-overflow-tooltip
  127. />
  128. <el-table-column
  129. label="操作"
  130. align="center"
  131. width="180"
  132. >
  133. <template v-slot="scope">
  134. <template v-if="scope.row.status === 0">
  135. <div
  136. class="c-table__btn u-pointer"
  137. @click="toDesign(scope.row.id)"
  138. >
  139. 编辑
  140. </div>
  141. <div
  142. class="c-table__btn u-pointer"
  143. @click="toSubmit(scope.row)"
  144. >
  145. 提交
  146. </div>
  147. <div
  148. class="c-table__btn u-pointer"
  149. @click="toDel(scope.row)"
  150. >
  151. 删除
  152. </div>
  153. </template>
  154. <div
  155. v-else
  156. class="c-table__btn u-pointer"
  157. @click="toView(scope.row.id)"
  158. >
  159. 预览
  160. </div>
  161. </template>
  162. </el-table-column>
  163. </c-table>
  164. <el-dialog
  165. title="新增排期"
  166. :visible.sync="adding"
  167. custom-class="c-dialog"
  168. :close-on-click-modal="false"
  169. >
  170. <div class="c-form">
  171. <div class="c-form__section">
  172. <span class="c-form__label">名称:</span>
  173. <el-input
  174. v-model.trim="schedule.name"
  175. class="c-form__item"
  176. placeholder="请输入名称"
  177. maxlength="50"
  178. show-word-limit
  179. />
  180. </div>
  181. <div class="c-form__section">
  182. <span class="c-form__label">类型:</span>
  183. <el-select
  184. v-model="schedule.type"
  185. class="c-form__item"
  186. placeholder="请选择"
  187. >
  188. <el-option
  189. v-for="type in typeOptions"
  190. :key="type.value"
  191. :label="type.label"
  192. :value="type.value"
  193. />
  194. </el-select>
  195. </div>
  196. <div class="c-form__section">
  197. <span class="c-form__label">分辨率:</span>
  198. <el-select
  199. v-model="schedule.resolutionRatio"
  200. class="c-form__item"
  201. placeholder="请选择"
  202. popper-class="o-select-option"
  203. :loading="fetching"
  204. >
  205. <el-option
  206. v-for="ratio in ratios"
  207. :key="ratio.value"
  208. :label="ratio.label"
  209. :value="ratio.value"
  210. />
  211. </el-select>
  212. </div>
  213. </div>
  214. <template #footer>
  215. <button
  216. class="o-button"
  217. @click="add"
  218. >
  219. 确定
  220. </button>
  221. <button
  222. class="o-button cancel"
  223. @click="handleCloseAddDialog"
  224. >
  225. 取消
  226. </button>
  227. </template>
  228. </el-dialog>
  229. <el-dialog
  230. :visible.sync="isPreview"
  231. custom-class="c-preview schedule"
  232. :before-close="handleCloseScheduleDialog"
  233. >
  234. <schedule
  235. v-if="scheduleId"
  236. class="l-flex__auto has-padding"
  237. :schedule="scheduleId"
  238. />
  239. </el-dialog>
  240. </template>
  241. <router-view class="has-padding" />
  242. </div>
  243. </template>
  244. <script>
  245. import { getRatios } from '@/api/device'
  246. import {
  247. getSchedules,
  248. addSchedule,
  249. deleteSchedule,
  250. submitSchedule
  251. } from '@/api/calendar'
  252. import { State } from '@/constant'
  253. import { createListOptions } from '@/utils'
  254. import { ScheduleType } from '@/constant'
  255. import Schedule from '@/components/Schedule'
  256. export default {
  257. name: 'ScheduleList',
  258. components: {
  259. Schedule
  260. },
  261. data () {
  262. return {
  263. scheduleOptions: [
  264. { value: void 0, label: '全部类型' },
  265. { value: ScheduleType.CALENDAR, label: '日程' },
  266. { value: ScheduleType.RECUR, label: '轮播' }
  267. ],
  268. statusOptions: [
  269. { value: void 0, label: '全部状态' },
  270. { value: State.READY, label: '待提交' },
  271. { value: State.SUBMITTED, label: '未审核' },
  272. { value: State.RESOLVED, label: '已审核' }
  273. ],
  274. typeOptions: [
  275. { value: ScheduleType.CALENDAR, label: '日程' },
  276. { value: ScheduleType.RECUR, label: '轮播' }
  277. ],
  278. active: 'normal',
  279. normal: createListOptions({
  280. type: void 0,
  281. status: void 0,
  282. name: ''
  283. }),
  284. defaults: createListOptions(),
  285. adding: false,
  286. schedule: {},
  287. scheduleId: null,
  288. fetching: false,
  289. ratios: [],
  290. isPreview: false
  291. }
  292. },
  293. computed: {
  294. isExact () {
  295. return this.$route.name === 'schedule'
  296. },
  297. currObj () {
  298. return this[this.active]
  299. },
  300. isNormal () {
  301. return this.active === 'normal'
  302. },
  303. proxy () {
  304. return this.isNormal ? {
  305. list: getSchedules,
  306. add: addSchedule,
  307. del: deleteSchedule
  308. } : {
  309. list: () => Promise.resolve({ data: [], totalCount: 0 })
  310. }
  311. }
  312. },
  313. created () {
  314. this.isExact && this.getList()
  315. },
  316. methods: {
  317. search () {
  318. const currObj = this.currObj
  319. currObj.list = []
  320. currObj.totalCount = 0
  321. currObj.params.pageNum = 1
  322. this.getList()
  323. },
  324. onTabClick () {
  325. this.getList()
  326. },
  327. transform (schedule) {
  328. let typeName
  329. switch (schedule.type) {
  330. case ScheduleType.RECUR:
  331. typeName = '轮播'
  332. break
  333. default:
  334. typeName = '日程'
  335. break
  336. }
  337. schedule.typeName = typeName
  338. return schedule
  339. },
  340. getList () {
  341. const currObj = this.currObj
  342. if (!currObj.loading) {
  343. currObj.error = false
  344. currObj.loading = true
  345. this.proxy.list(currObj.params).then(({ data, totalCount }) => {
  346. currObj.list = data.map(this.transform)
  347. currObj.totalCount = totalCount
  348. }, () => {
  349. currObj.error = true
  350. currObj.list = []
  351. }).finally(() => {
  352. currObj.loading = false
  353. })
  354. }
  355. },
  356. getRatios () {
  357. if (!this.fetching && this.ratios.length === 0) {
  358. this.fetching = true
  359. getRatios().then(ratios => {
  360. this.ratios = ratios
  361. }).finally(() => {
  362. this.fetching = false
  363. })
  364. }
  365. },
  366. toAdd () {
  367. this.schedule = {
  368. name: '',
  369. type: 1,
  370. resolutionRatio: ''
  371. }
  372. this.adding = true
  373. this.getRatios()
  374. },
  375. handleCloseAddDialog () {
  376. this.adding = false
  377. },
  378. add () {
  379. if (!this.schedule.name) {
  380. this.$message({
  381. type: 'warning',
  382. message: '名称不能为空'
  383. })
  384. return
  385. }
  386. if (!this.schedule.resolutionRatio) {
  387. this.$message({
  388. type: 'warning',
  389. message: '请选择分辨率'
  390. })
  391. return
  392. }
  393. this.proxy.add(this.schedule).then(({ data: id }) => {
  394. this.handleCloseAddDialog()
  395. const params = this.currObj.params
  396. if (params.status && params.status !== State.READY) {
  397. params.status = void 0
  398. }
  399. if (params.name && !(new RegExp(params.name).test(this.schedule.name))) {
  400. params.name = ''
  401. }
  402. this.search()
  403. this.toDesign(id)
  404. })
  405. },
  406. toView (id) {
  407. this.scheduleId = id
  408. this.isPreview = true
  409. },
  410. handleCloseScheduleDialog () {
  411. this.scheduleId = null
  412. this.isPreview = false
  413. },
  414. toDesign (id) {
  415. this.$router.push({
  416. name: 'schedule-design',
  417. params: { id: `${id}` }
  418. })
  419. },
  420. toSubmit (item) {
  421. submitSchedule(item).then(() => {
  422. this.search()
  423. })
  424. },
  425. toDel (item) {
  426. const currObj = this.currObj
  427. this.proxy.del(item).then(() => {
  428. if (currObj.list.length === 1 && currObj.params.pageNum > 1) {
  429. currObj.params.pageNum -= 1
  430. }
  431. this.getList()
  432. })
  433. }
  434. }
  435. }
  436. </script>
  437. <style lang="scss" scoped>
  438. </style>