PriceCalendar.vue 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  1. <template>
  2. <el-dialog
  3. :visible.sync="visible"
  4. title="价格方案"
  5. width="980px"
  6. append-to-body
  7. @close="handleCancel"
  8. >
  9. <div
  10. class="wrap">
  11. <el-alert type="warning" :closable="false" title="当前价格优先级:特定日期 > 周期性规则 > 日常价格" />
  12. <!-- <div v-loading="loading">
  13. <div class="block-title">
  14. 基础价格
  15. </div>
  16. <el-input
  17. placeholder="请输入内容"
  18. v-model="basicPrice"
  19. style="width: 160px">
  20. </el-input>
  21. </div> -->
  22. <div v-loading="weekLoading">
  23. <div class="block-title">
  24. 周价格
  25. </div>
  26. <div
  27. class="weekWrap"
  28. style="margin-bottom:30px"
  29. >
  30. <div
  31. class="weekItem"
  32. v-for="(item,index) in weekDayPriceList"
  33. :key="index"
  34. >
  35. <label>{{ item.label }}</label>
  36. <el-input
  37. oninput="value=value.replace(/[^\d.]/g,'')"
  38. class="priceInput"
  39. v-model="item.value"
  40. />
  41. <el-switch
  42. style="margin-top: 10px"
  43. v-model="item.isSale"
  44. :inactive-value="0"
  45. :active-value="1"
  46. active-text="在售"
  47. inactive-text="禁售">
  48. </el-switch>
  49. </div>
  50. </div>
  51. </div>
  52. <div v-loading="loading">
  53. <div class="block-title">
  54. 日期段价格(时间不可重叠)
  55. <el-button
  56. class="addBtn"
  57. type="primary"
  58. icon="el-icon-plus"
  59. @click="handleAdd"
  60. size="small"
  61. >
  62. 新增
  63. </el-button>
  64. </div>
  65. <div
  66. class="noData"
  67. v-if="priceList.length===0"
  68. >
  69. 暂无
  70. </div>
  71. <ul class="price-list">
  72. <li
  73. v-for="(item,index) in priceList"
  74. :key="index"
  75. >
  76. <el-date-picker
  77. class="calendarPicker"
  78. type="daterange"
  79. v-model="item.dateRange"
  80. @change="handleChange($event,item)"
  81. />
  82. <el-input-number
  83. class="priceInput"
  84. :controls="false"
  85. v-model="item.price"
  86. />
  87. <el-switch
  88. style="margin-top: 10px"
  89. v-model="item.isSale"
  90. :inactive-value="0"
  91. :active-value="1"
  92. active-text="在售"
  93. inactive-text="禁售">
  94. </el-switch>
  95. <el-button
  96. type="danger"
  97. icon="el-icon-close"
  98. size="small"
  99. @click="handleDelete(index)"
  100. ></el-button>
  101. </li>
  102. </ul>
  103. </div>
  104. <div
  105. class="btn-wrap"
  106. slot="footer">
  107. <el-button
  108. size="small"
  109. @click="visible=false">
  110. 取 消
  111. </el-button>
  112. <el-button
  113. size="small"
  114. type="primary"
  115. @click="handleOk">
  116. 保 存
  117. </el-button>
  118. </div>
  119. </div>
  120. </el-dialog>
  121. </template>
  122. <script>
  123. import moment from 'moment'
  124. import { getPricePlan, addTicketPricePlan } from '@/api/ticketPricePlan'
  125. const week = ['周一', '周二', '周三', '周四', '周五', '周六', '周日']
  126. const weekMap = {
  127. '周日': 1,
  128. '周一': 2,
  129. '周二': 3,
  130. '周三': 4,
  131. '周四': 5,
  132. '周五': 6,
  133. '周六': 7
  134. }
  135. const stragegiesMap = {
  136. PERIOD: '日期段价格',
  137. WEEKDAY: '周价格',
  138. BASIC: '日常价格'
  139. }
  140. export default {
  141. data () {
  142. return {
  143. week,
  144. stragegiesMap,
  145. ticketTypeId: '',
  146. loading: false,
  147. visible: false,
  148. weekLoading: false,
  149. confirmLoading: false,
  150. basicPrice: '',
  151. ticketPricePlanList: [],
  152. priceList: [],
  153. weekDayPriceList: [],
  154. ticketInfo: {}
  155. }
  156. },
  157. methods: {
  158. show (ticket) {
  159. this.ticketInfo = ticket
  160. this.weekDayPriceList = week.map((val, index) => {
  161. return {
  162. label: val,
  163. value: null,
  164. isSale: 1
  165. }
  166. })
  167. getPricePlan({
  168. ticketTypeId: ticket.id,
  169. pageSize: 10,
  170. pageNum: 0
  171. }).then(res => {
  172. if (res.code === '200') {
  173. const list = res.data || []
  174. list.filter(l => l.weekdays).forEach(l => {
  175. this.weekDayPriceList.forEach(w => {
  176. if (l.weekdays.includes(weekMap[w.label])) {
  177. w.value = l.price
  178. }
  179. })
  180. })
  181. this.priceList = list.filter(l => !l.weekdays).map(l => {
  182. const { startDate, endDate, specificDate, price, isSale } = l
  183. return {
  184. dateRange: [moment(specificDate || startDate), moment(specificDate || endDate)],
  185. price,
  186. isSale
  187. }
  188. }).reverse()
  189. }
  190. })
  191. this.visible = true
  192. this.ticketTypeId = ticket.id
  193. },
  194. handleCancel () {
  195. this.visible = false
  196. },
  197. handleChange (event, item) {
  198. this.$set(item, 'start', moment(event[0]).format('YYYY-MM-DD'))
  199. this.$set(item, 'end', moment(event[1]).format('YYYY-MM-DD'))
  200. },
  201. handleDelete (index) {
  202. this.$confirm('确定删除吗', '提示', {
  203. confirmButtonText: '确定',
  204. cancelButtonText: '取消',
  205. type: 'warning'
  206. }).then(() => {
  207. this.priceList.splice(index, 1)
  208. }).catch(() => {})
  209. },
  210. handleAdd () {
  211. let lastPrice
  212. if (this.priceList.length > 0) {
  213. lastPrice = JSON.parse(JSON.stringify(this.priceList[this.priceList.length - 1]))
  214. } else {
  215. lastPrice = { start: new Date(), end: new Date(), price: '' }
  216. }
  217. lastPrice.dateRange = [moment(lastPrice.start), moment(lastPrice.end)]
  218. this.priceList.push({
  219. ...lastPrice,
  220. isEdit: true,
  221. isSale: 1
  222. })
  223. },
  224. handleOk () {
  225. this.confirmLoading = true
  226. const { id } = this.ticketInfo
  227. const planList = []
  228. const weekPriceList = []
  229. let priority = 0
  230. const wpList = this.weekDayPriceList.filter(wp => wp.value !== null && wp.value !== undefined)
  231. wpList.forEach(wp => {
  232. const hasPrice = weekPriceList.find(item => wp.value === item.price && wp.isSale === item.isSale)
  233. if (hasPrice) {
  234. hasPrice.weekdays += `,${weekMap[wp.label]}`
  235. } else {
  236. weekPriceList.push({
  237. ticketTypeId: id,
  238. isSale: wp.isSale,
  239. priority,
  240. price: wp.value,
  241. weekdays: weekMap[wp.label]
  242. })
  243. }
  244. })
  245. planList.push(...weekPriceList)
  246. this.priceList.forEach(item => {
  247. priority--
  248. const { start, end, price, isSale } = item
  249. const startDate = moment(start).format('YYYY-MM-DD')
  250. const endDate = moment(end).format('YYYY-MM-DD')
  251. if (startDate === endDate) {
  252. planList.push({
  253. ticketTypeId: id,
  254. isSale,
  255. priority,
  256. price,
  257. specificDate: startDate
  258. })
  259. } else {
  260. planList.push({
  261. ticketTypeId: id,
  262. isSale,
  263. priority,
  264. price,
  265. startDate,
  266. endDate
  267. })
  268. }
  269. })
  270. addTicketPricePlan(planList).then(res => {
  271. if (res.code === '200') {
  272. this.$message.success('设置成功')
  273. this.handleCancel()
  274. }
  275. }).finally(() => {
  276. this.loading = false
  277. })
  278. }
  279. }
  280. }
  281. </script>
  282. <style lang="scss" scoped>
  283. .wrap{
  284. padding: 20px;
  285. }
  286. .btn-wrap{
  287. text-align: right; margin-top: 20px;
  288. }
  289. .price-list {
  290. font-variant: tabular-nums;
  291. li {
  292. margin-bottom: 15px;
  293. display: flex;
  294. justify-content: space-around;
  295. }
  296. .calendarTxt {
  297. display: inline-block; width: 332px; box-sizing: border-box; padding-right: 30px;margin-right: 20px;text-align: center;
  298. span {
  299. display: inline-block; width: 135px;
  300. }
  301. }
  302. .priceTxt {
  303. display: inline-block; width: 200px; box-sizing: border-box; padding-left: 10px;margin-right: 20px;
  304. span {
  305. margin-right: 5px;
  306. }
  307. }
  308. .calendarPicker {
  309. margin-right: 20px;
  310. }
  311. .priceInput {
  312. display: inline-block; width: 200px; margin-right: 20px;
  313. }
  314. }
  315. .weekWrap {
  316. display: flex; justify-content: space-between;
  317. .weekItem{
  318. label{
  319. display: block; text-align: center; margin-bottom: 5px; font-weight: bold;
  320. }
  321. }
  322. .weekItem + .weekItem {
  323. margin-left: 10px;
  324. }
  325. .priceTxt{
  326. width: 88px; padding: 0 11px; display: inline-block;
  327. i{
  328. font-style: normal;
  329. }
  330. }
  331. }
  332. .addBtn {
  333. float: right; margin-bottom: 5px;
  334. }
  335. .noData {padding: 10px;
  336. text-align: center; border: 1px dashed #ddd;
  337. }
  338. </style>