浏览代码

1. 新增排期

MONSTER-ygh 2 月之前
父节点
当前提交
a39586a2b3

+ 78 - 0
src/api/ticketMr/schedulingConfiguration.js

@@ -0,0 +1,78 @@
+import request from '@/utils/request'
+// 日历排期
+export const calendarList = (query) => {
+    return request({
+      url: '/merchant/merchantPerformTime/selectPerformTimeByDate',
+      method: 'get',
+      params: query
+    })
+  }
+
+// 排期列表
+export const pageList = (query) => {
+  return request({
+    url: '/merchant/timePlan/pageList',
+    method: 'get',
+    params: query
+  })
+}
+
+
+// 新增/修改
+export const saveAndEdit = (data) => {
+  return request({
+    url: '/merchant/timePlan/insert',
+    method: 'post',
+    data: data
+  })
+}
+
+
+// 演出场次详情
+export const getPerformTimeById = (params) => {
+  return request({
+    url: '/merchant/merchantPerformTime/getById',
+    method: 'get',
+    params
+  })
+}
+
+// 删除排期配置
+export const deleteById = (params) => {
+  return request({
+    url: '/merchant/timePlan/deleteById',
+    method: 'delete',
+    params
+  })
+}
+
+
+/**  启用和禁用  */
+export function releaseById(data) {
+  return request({
+    url: '/merchant/merchantPerformTime/updateStatus',
+    method: 'put',
+    data
+  })
+}
+
+// 票务查询
+
+export const goodsPageList = (query) => {
+  return request({
+    url: '/goods/goods/listByPerformId',
+    method: 'get',
+    params: query
+  })
+}
+
+// 销售信息
+
+export const seatTypeTmpSaleCount = (query) => {
+  return request({
+    url: '/merchant/merchantPerformTime/seatTypeTmpSaleCount',
+    method: 'get',
+    params: query
+  })
+}
+

+ 553 - 0
src/views/ticket/schedulingConfiguration/dialog/addAndEdit.vue

@@ -0,0 +1,553 @@
+<!--
+ * @Description: 新增/编辑弹框
+ * @Author: Sugar.
+ * @Date: 2023-11-24 13:55:00
+ * @LastEditors: Sugar.
+ * @LastEditTime: 2023-11-24 13:55:00
+ * @FilePath: \cattle_webui\src\views\venue\schedulingMr\dialog\AddOrEditDialog.vue
+ * @Copyright: Copyright (c) 2016~2023 by Sugar., All Rights Reserved.
+-->
+<template>
+  <el-dialog
+    :title="title"
+    :visible.sync="open"
+    width="70%"
+    class="text-dia-log-class"
+    append-to-body
+    :close-on-click-modal="false"
+    @close="cancel"
+  >
+    <div class="dialog">
+      <el-form :model="form" ref="form" :rules="rules" label-width="120px">
+        <el-form-item label="日期范围:"  prop="performDate">
+          <el-date-picker
+            v-model="form.performDate"
+            type="daterange"
+            range-separator="至"
+            value-format="yyyy-MM-dd"
+            start-placeholder="开始日期"
+            end-placeholder="结束日期">
+          </el-date-picker>
+        </el-form-item>
+        <el-form-item label="星期:" prop="weekType">
+          <div>
+            <el-button 
+            @click="selectWeekType()"
+            :type="form.weekType == 1 ?'':'primary'">不限</el-button>
+            <el-button 
+            v-for="(item,index) in weekDayList"
+            :key="index"
+            @click="selectWeekDay(item)"
+            :type="form.weekDay.includes(item.key)?'primary':''">{{ item.name }}</el-button>
+          </div>
+          <div style="font-size: 12px;">指定在选定区间内的周几价格进行调整,列如区间选择2018-01-01至2018-01-20,星期选择星期一,则这个区间内的星期一价格都进行调整</div>
+        </el-form-item>
+        <el-form-item label="选择演出厅:" prop="auditoriumId">
+          <el-select
+            v-model="form.auditoriumId"
+            placeholder="选择演出厅"
+            clearable
+            style="width: 100%"
+          >
+            <el-option
+              v-for="dict in merchantList"
+              :key="dict.id"
+              :label="dict.name"
+              :value="dict.id"
+            />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="选择剧目:" prop="performId">
+          <el-select
+            v-model="form.performId"
+            placeholder="选择剧目"
+            clearable
+            @change="changePerform"
+            style="width: 100%"
+          >
+            <el-option
+              v-for="dict in goodsList"
+              :key="dict.id"
+              :label="dict.name"
+              :value="dict.id"
+            />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="票务绑定:" prop="goodsIds">
+          <el-select
+            v-model="form.goodsIds"
+            placeholder="票务绑定"
+            clearable
+            multiple
+            style="width: 100%"
+          >
+            <el-option
+              v-for="dict in goodsPageListS"
+              :key="dict.id"
+              :value="dict.id"
+              :label="dict.status == 1 ? dict.goodsName + '(被禁用)': dict.goodsName"
+              :disabled="dict.status != 0"
+            >
+            </el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="场次排期:" prop="planSessionList" v-if="!editType">
+          <el-button type="primary" size="small" @click="addTable">添加</el-button>
+        </el-form-item>
+
+        <el-form-item label="" v-if="form.planSessionList && form.planSessionList.length > 0">
+          <el-table ref="tables" v-loading="loading" :data="form.planSessionList" border>
+            <el-table-column label="序号" align="center" type="index" width="50"></el-table-column>
+            <el-table-column label="场次名称" align="center">
+              <template slot-scope="scope">
+                <el-input v-model="scope.row.name" placeholder="请输入内容"></el-input>
+              </template>
+            </el-table-column>
+            <el-table-column label="开始时间" align="center">
+              <template slot-scope="scope">
+                <el-time-picker
+                  v-model="scope.row.startInterval"
+                  style="width: 100%"
+                  value-format="HH:mm"
+                  format="HH:mm"
+                  @change="changValue(scope.row, 'start', scope.$index)"
+                  :picker-options="{ selectableRange: '00:00:00 - 23:59:59'}"
+                  placeholder="选择时间">
+                </el-time-picker>
+              </template>
+            </el-table-column>
+            <el-table-column label="结束时间" align="center">
+              <template slot-scope="scope">
+                <el-time-picker
+                  v-model="scope.row.endInterval"
+                  style="width: 100%"
+                  value-format="HH:mm"
+                  format="HH:mm"
+                  @change="changValue(scope.row, 'end', scope.$index)"
+                  :picker-options="{ selectableRange: '00:00:00 - 23:59:59'}"
+                  placeholder="选择时间">
+                </el-time-picker>
+              </template>
+            </el-table-column>
+            <el-table-column label="库存模板">
+              <template slot-scope="scope">
+                <el-select
+                  v-model="scope.row.stockTmpId"
+                  placeholder="选择库存模板"
+                  clearable
+                  style="width: 100%"
+                >
+                  <el-option
+                    v-for="dict in inventoryTemplateList"
+                    :key="dict.id"
+                    :label="dict.name"
+                    :value="dict.id"
+                    :disabled="dict.status != 1"
+                  />
+                </el-select>
+              </template>
+            </el-table-column>
+            <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+              <template slot-scope="scope">
+                <el-button
+                  size="mini"
+                  type="text"
+                  @click="handleDelete(scope.row,scope.$index)"
+                >删除</el-button>
+              </template>
+            </el-table-column>
+          </el-table>
+        </el-form-item>
+      </el-form>
+    </div>
+    <span slot="footer" class="dialog-footer">
+      <el-button @click="cancel">取消</el-button>
+      <el-button
+        type="primary"
+        @click="submitForm"
+        v-loading.fullscreen.lock="loading"
+        element-loading-text="提交中..."
+        element-loading-spinner="el-icon-loading"
+        element-loading-background="rgba(0, 0, 0, 0.8)"
+      >
+        <span v-if="loading">提交中...</span>
+        <span v-else>保存</span>
+      </el-button>
+    </span>
+  </el-dialog>
+</template>
+
+<script>
+import { saveAndEdit, goodsPageList as goodsPageListApi, } from "@/api/ticketMr/schedulingConfiguration";
+import { goodsPageList } from '@/api/programmeMr/programmeMr'
+import { merchantPageList } from '@/api/performanceHallMr/performanceHallMr'
+import { pageList as getInventoryTemplateApi } from '@/api/ticketMr/InventoryTemplate'
+import { getToken } from "@/utils/auth";
+import moment from "moment"
+export default {
+  name: "addAndEdit",
+  data() {
+    return {
+      title: "编辑",
+      model: "EDIT",
+      open: false,
+      loading: false,
+      tableType: false,
+      form: {
+        id: undefined,
+        planSessionList: [],
+        insertType: '1',
+        useStock: 0,
+        weekDay: [],
+        weekType: 0
+      },
+      rules: {
+        auditoriumId: [{ required: true, message: "请选择演出厅", trigger: ["change","blur"] }],
+        performId: [{ required: true, message: "请选择剧目", trigger: ["change","blur"] }],
+        performDate: [{ required: true, message: "请选择日期", trigger: ["change","blur"] }],
+        planSessionList: [{ required: true, message: "请添加场次", trigger: ["change","blur"] }],
+        goodsIds: [{ required: true, message: "请选择票务", trigger: ["change","blur"] }],
+        weekType: [{ required: true, message: "请选择星期", trigger: ["change","blur"] }],
+      },
+      uploadObj: {
+        url: process.env.VUE_APP_UPLOAD_FILE_API + "/upload/single/minio",
+        Headers: { Authorization: "Bearer " + getToken() },
+      },
+      theatreList: [],
+      goodsList: [],
+      merchantList: [],
+      editType: false,
+      selectPerform: {},
+
+      goodsPageListS: [], // 票务
+
+      weekDayList: [
+        {name: "星期一",key: "1"},
+        {name: "星期二",key: "2"},
+        {name: "星期三",key: "3"},
+        {name: "星期四",key: "4"},
+        {name: "星期五",key: "5"},
+        {name: "星期六",key: "6"},
+        {name: "星期七",key: "7"},
+      ],
+      inventoryTemplateList: []
+    };
+  },
+  created() {
+    /**  获取票务  */
+    this.goodsPageList(); // 剧目列表
+    this.merchantPageList('') // 演出厅
+    this.getInventoryTemplate()
+  },
+  methods: {
+    /**
+     * 打开弹框
+     * @date 2023-11-22
+     * @param {any} obj
+     * @returns {any}
+     */
+    async openDialog(title, obj, type) {
+      this.open = true;
+      this.editType = false;
+      if (obj){
+        this.title = "编辑排期";
+        if(obj.performId) {
+          await this.goodsPageListFun(obj.performId);
+        }
+        this.form = {
+          ...obj,
+          performDate: [obj.dateStart,obj.dateEnd],
+          goodsIds: obj.goodsIds ? obj.goodsIds.split(','):[],
+          weekDay: obj.weekDay ? obj.weekDay.split(','):[],
+          planSessionList: obj.planSessionList ? obj.planSessionList:[],
+        }
+        this.editType = true;
+        console.log("form====",this.form)
+      }else{
+        this.title = "新增排期";
+        this.form = {
+            planSessionList: [],
+            weekDay: [],
+            weekType: 0
+        };
+      }
+      this.$nextTick(() => {
+        this.$refs["form"].clearValidate();
+      });
+    },
+    /** 剧目选择 */
+    changePerform(id) {
+      this.goodsList.forEach(item => {
+        if(id == item.id){
+          this.selectPerform = item;
+        }
+      })
+      this.goodsPageListS = []
+      if(id) {
+        this.goodsPageListFun(id);
+      }
+      //this.$set(this.form, 'performDate' , '')
+      this.$set(this.form, 'goodsIds' , [])
+    },
+    // yyyy-mm-dd 转时时间戳
+    dateToTimestamp(year, month, day) {
+      const date = new Date(year, month - 1, day);
+      return date.getTime();
+    },
+    // 时间选择
+    performDateEven(key) {
+      if(!this.form.performId){
+        this.$message.error("请选择剧目!");
+        this.$set(this.form, 'performDate', '');
+        return false;
+      }
+      let newTime = ''
+      if(key == 'list'){
+        newTime = this.form.performDate[0]
+      } else {
+        newTime = this.form.performDate;
+      }
+      let newTimeArr = newTime.split('-');
+      let letTiemArr = this.selectPerform.releaseDate.split('-');
+      if(this.dateToTimestamp(newTimeArr[0], newTimeArr[1], newTimeArr[2]) < this.dateToTimestamp(letTiemArr[0], letTiemArr[1], letTiemArr[2])){
+        this.$message.error("开始时间不能小于剧目上映时间" + this.selectPerform.releaseDate);
+        this.$set(this.form, 'performDate' , '')
+        return false
+      }
+    },
+    /** 剧目列表查询 */
+    goodsPageList() {
+      goodsPageList(this.addDateRange({pageNum: 1, pageSize: 100, status: 1}))
+        .then(response => {
+            this.goodsList = response.data.rows;
+        });
+    },
+    /** 演出厅列表查询 */
+    merchantPageList(id) {
+      merchantPageList(this.addDateRange({theatreId: id, pageNum: 1, pageSize: 100}))
+        .then(response => {
+            this.merchantList = response.data.rows;
+        });
+    },
+    /**  票务信息  */
+    async goodsPageListFun(value){
+      try {
+        let res = await goodsPageListApi({
+          performId: value
+        })
+        if(res.code == 200){
+          this.goodsPageListS = res.data
+        }
+      } catch (error) {      
+      }
+    },
+    /**  获取模板  */
+    async getInventoryTemplate(){
+      try {
+        let res = await getInventoryTemplateApi({
+        pageNum: 1,
+        pageSize: 1000,
+      })
+        if(res.code == 200){
+          this.inventoryTemplateList = res.data.rows
+        }
+      } catch (error) {      
+      }
+    },
+    /**
+     * 保存
+     * @date 2023-11-22
+     * @returns {any}
+     */
+    submitForm() {
+      this.$refs["form"].validate(async (valid) => {
+        if (valid) {
+          try {
+            let postEdit = JSON.parse(JSON.stringify(this.form))
+            postEdit['dateStart'] = moment(postEdit.performDate[0]).format('YYYY-MM-DD hh:mm:ss')
+            postEdit['dateEnd'] = moment(postEdit.performDate[1]).format('YYYY-MM-DD hh:mm:ss')
+            postEdit.goodsIds = postEdit.goodsIds.join(',')
+            postEdit.weekDay = postEdit.weekDay.join(','),
+            delete postEdit.performDate
+            this.loading = true;
+            const { code } = await saveAndEdit({ ...postEdit });
+            if (code === 200) {
+              this.$message.success("操作成功!");
+              this.$emit("getList");
+              this.cancel();
+            }
+          } catch (error) {
+            console.error("error====",error)
+          } finally {
+            this.loading = false;
+          }
+        }
+      });
+    },
+    /**
+     * 重置
+     * @date 2023-11-22
+     * @returns {any}
+     */
+    reset() {
+      
+    },
+    /**
+     * 关闭弹框
+     * @date 2023-11-22
+     * @returns {any}
+     */
+    cancel() {
+      this.reset();
+      this.open = false;
+    },
+
+    /** 点击添加排期 */
+    addTable() {
+      if(!this.form.performId){
+        this.$message.error("请选择剧目!");
+        return false;
+      }
+      let map = {
+        name: '',
+        startInterval: '',
+        startM: '',
+        endInterval: '',
+        endM: '',
+        err: false,
+      }
+      this.form.planSessionList.push(map)
+    },
+
+    /** 开始时间和结束时间大小判断 */
+    changValue(row, key, $index) {
+      let start = '', startTime = '',  end = '', endTime;
+      if(row.startInterval && row.startInterval.length > 0) {
+        start = row.startInterval.split(":");
+        startTime = (start[0] * 3600) + (start[1] * 60);
+        row.startM = startTime;
+      }
+      if(row.endInterval && row.endInterval.length > 0) {
+        // if(this.selectPerform)
+        end = row.endInterval.split(":");
+        endTime = (end[0] * 3600) + (end[1] * 60);
+        let showDuration = this.selectPerform.showDuration * 60;
+        if(endTime - row.startM < showDuration) {
+          this.$message.error("选择时间不能小于剧目时长," + this.selectPerform.showDuration + "分钟!");
+          row.endInterval = ""
+          return false
+        }
+        row.endM = endTime;
+      }
+
+      // 判断场次时间段是否存在冲突
+      let status = false;
+      this.form.planSessionList.forEach((item, index) => {
+        if($index != index) {
+          if(key == 'start') {
+            if(item.startM <= startTime && startTime <= item.endM) {
+              status = true;
+            }
+          }
+          if (key == 'end') {
+            if(item.startM <= endTime && endTime <= item.endM) {
+              status = true;
+            }
+          }
+        }
+      })
+
+      if(status) {
+        this.$message.error("该场次的时间和其它场次时间段冲突!");
+        if(key == 'start') {
+          row.startInterval = ""
+          row.startM = ""
+        } else if (key == 'end') {
+          row.endInterval = ""
+          row.endM = ""
+        }
+        return false;
+      }
+
+      if(key == 'start') {
+        if(endTime && startTime >= endTime) {
+          row.startTime = ""
+          row.startM = ""
+        }
+      } else if (key == 'end') {
+        if(startTime && startTime >= endTime) {
+          row.endTime = ""
+          row.endM = ""
+        }
+      }
+    },
+
+    /** 删除按钮操作 */
+    handleDelete(row, index) {
+      if(this.form.planSessionList && this.form.planSessionList.length == 1){
+        this.$message.error("只剩一场次, 不能删除!");
+        return false;
+      }
+      this.$confirm('是否确认删除数据场次名称为"' + row.name + '"的数据项?', '提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+        this.form.planSessionList.splice(index, 1)
+      }).catch(() => {
+
+      });
+    },
+    selectWeekDay(item){
+      let index = -1
+      this.form.weekDay.forEach((item1,index1)=>{
+        if(item.key == item1) {
+          index = index1
+        }
+      })
+      if(index != -1) {
+        this.form.weekDay.splice(index,1)
+      }else {
+        this.form.weekDay.push(item.key)
+      }
+      if(this.form.weekDay.length>0) {
+        this.form.weekType = 1
+      }else {
+        this.form.weekType = 0
+      }
+    },
+    selectWeekType() {
+      this.form.weekType = this.form.weekType == 1 ? 0 : 1
+      if(!this.form.weekType) {
+        this.form.weekDay = []
+      }
+    }
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.dialog {
+  height: 65vh;
+  overflow-y: auto;
+}
+.dialog {
+  .upload-btn {
+    width: 100px;
+    height: 100px;
+    background-color: #fbfdff;
+    border: dashed 1px #c0ccda;
+    border-radius: 5px;
+    i {
+      font-size: 30px;
+      margin-top: 20px;
+    }
+    &-text {
+      margin-top: -10px;
+    }
+  }
+  .avatar {
+    cursor: pointer;
+  }
+}
+</style>

+ 236 - 0
src/views/ticket/schedulingConfiguration/dialog/calendarBox.vue

@@ -0,0 +1,236 @@
+<template>
+    <div class="plan-zone">
+        <div class="btn-group">
+            <div class="left-btn">
+                <el-button-group>
+                    <el-button @click="prevMonth" type="primary">上一个月</el-button>
+                    <el-button type="primary" @click="goToCurrentMonth">{{
+                        getCurDate()
+                        }}</el-button>
+                    <el-button @click="nextMonth" type="primary">下一个月</el-button>
+                </el-button-group>
+                <el-button type="primary" @click="goToCurrentDay">回到今天</el-button>
+            </div>
+            <div class="right-btn">
+                <button class="new">新安排</button>
+                <button class="ing">进行中</button>
+                <button class="finish">已完成</button>
+            </div>
+        </div>
+        <!-- <el-calendar v-model="value"> </el-calendar> -->
+        <table class="parent-table">
+            <thead>
+                <th>周一</th>
+                <th>周二</th>
+                <th>周三</th>
+                <th>周四</th>
+                <th>周五</th>
+                <th>周六</th>
+                <th>周日</th>
+            </thead>
+            <tbody>
+                <tr v-for="(week, windex) in weeks" :key="windex">
+                    <td v-for="(day, dindex) in week" :class="{ highlight: isToday(day.date) }" :key="dindex">
+                        <div class="content" :class="{
+                            faded: !isCurrentMonth(day.date),
+                        }">
+                            <div class="top-day">{{ day.date.getDate() }}日</div>
+                            <div class="middle-event"></div>
+                            <div class="bottom-event"></div>
+                        </div>
+                    </td>
+                </tr>
+            </tbody>
+        </table>
+    </div>
+</template>
+<script>
+export default {
+    name: "CalendarBox",
+  data() {
+    return {
+      current: new Date(),
+      today: new Date(),
+    };
+  },
+  computed: {
+    weeks() {
+      return this.getMonthData(
+        this.current.getFullYear(),
+        this.current.getMonth() + 1
+      );
+    },
+  },
+  methods: {
+    getCurDate() {
+      var date = new Date();
+      var year = date.getFullYear();
+      var month = date.getMonth() + 1; // getMonth() returns a zero-based value (0-11)
+      if (month < 10) {
+        month = "0" + month; // add a leading zero if the month is a single digit
+      }
+      return year + "-" + month;
+    },
+    isToday(date) {
+      let today = new Date();
+      return (
+        date.getDate() === today.getDate() &&
+        date.getMonth() === today.getMonth() &&
+        date.getFullYear() === today.getFullYear()
+      );
+    },
+    goToCurrentDay() {
+      this.current = new Date(this.today);
+    },
+    isCurrentMonth(date) {
+      return date.getMonth() === this.current.getMonth();
+    },
+    prevMonth() {
+      this.current.setMonth(this.current.getMonth() - 1);
+      this.current = new Date(this.current);
+      // console.log(this.current.getFullYear(), 'dedede')
+    },
+    nextMonth() {
+      this.current.setMonth(this.current.getMonth() + 1);
+      this.current = new Date(this.current);
+    },
+    goToCurrentMonth() {
+      this.current = new Date(this.today);
+    },
+    getMonthData(year, month) {
+      let weeks = [];
+      let firstDay = new Date(year, month - 1, 1); // 这个月的第一天
+      let lastDayOfCurrentMonth = new Date(year, month, 0); // 这个月的最后一天
+      let lastDayOfPrevMonth = new Date(year, month - 1, 0); // 上个月的最后一天
+
+      //这里的0有一个特殊的意义,它可以返回上个月的最后一天。也就是说,如果你想知道某个月有多少天,你可以创建一个日期对象,年份和月份设置为你想知道的月份,日期设置为0,然后调用getDate()方法,返回的就是那个月的天数。
+      // new Date(year, month - 1, 0) 最后一个参数,超过当月天数重新排序,比如1月31天,最后一个参数为33返回2
+      let startDayOfWeek = firstDay.getDay() === 0 ? 7 : firstDay.getDay(); // 开始是周几
+      let dayCount = 1; // 当前日期的变量,初始值为1
+      // 上一个月的天数
+      let prevMonthDayCount = lastDayOfPrevMonth.getDate() - startDayOfWeek + 2; // 这是为了在日历中填充上个月的日期。
+      // console.log(lastDayOfPrevMonth.getDate(), startDayOfWeek, prevMonthDayCount)
+      for (let i = 0; i < 6; i++) {
+        let week = [];
+        for (let j = 0; j < 7; j++) {
+         // 日期为上个月的日期,然后将这个日期对象添加到`week`数组中,同时`prevMonthDayCount`加1。
+          if (i === 0 && j < startDayOfWeek - 1) {
+
+            week.push({ date: new Date(year, month - 2, prevMonthDayCount++) });
+            // 日期为下个月的日期,然后将这个日期对象添加到`week`数组中,同时`dayCount`加1
+          } else if (dayCount > lastDayOfCurrentMonth.getDate()) {
+            week.push({
+              date: new Date(
+                year,
+                month,
+                dayCount++ - lastDayOfCurrentMonth.getDate()
+              ),
+            });
+           // 日期为这个月的日期,然后将这个日期对象添加到`week`数组中,同时`dayCount`加1
+          } else {
+            week.push({ date: new Date(year, month - 1, dayCount++) });
+          }
+        }
+        weeks.push(week);
+      }
+      return weeks;
+    }
+
+  },
+};
+</script>
+<style scoped lang="scss">
+.faded {
+  opacity: 0.3;
+}
+.highlight {
+  background: rgba(255, 220, 40, 0.15);
+}
+.plan-zone {
+  margin-top: 10px;
+  .btn-group {
+    display: flex;
+    justify-content: space-between;
+    .right-btn {
+      button.new {
+        background-color: #fff;
+        border: 1px solid #fff;
+        color: #409eef;
+        position: relative;
+        &::before {
+          content: "";
+          width: 8px;
+          height: 8px;
+          border-radius: 50%;
+          position: absolute;
+          top: 7px;
+          left: -3px;
+          background-color: #409eef;
+        }
+      }
+      button.ing {
+        background-color: #fff;
+        border: 1px solid #fff;
+        color: #ff974a;
+        position: relative;
+        &::before {
+          content: "";
+          width: 8px;
+          height: 8px;
+          border-radius: 50%;
+          position: absolute;
+          top: 7px;
+          left: -3px;
+          background-color: #ff974a;
+        }
+      }
+      button.finish {
+        background-color: #fff;
+        border: 1px solid #fff;
+        color: #3dd599;
+        position: relative;
+        &::before {
+          content: "";
+          width: 8px;
+          height: 8px;
+          border-radius: 50%;
+          position: absolute;
+          top: 7px;
+          left: -3px;
+          background-color: #3dd599;
+        }
+      }
+    }
+  }
+}
+.parent-table {
+  border-collapse: collapse;
+  table-layout: fixed;
+  width: 100%;
+  margin-top: 20px;
+  th,
+  td {
+    width: 14.4%;
+    border: 1px solid #ddd;
+  }
+  td {
+    padding: 2px 3px;
+
+    .content {
+      position: relative;
+      min-height: 80px;
+    }
+    vertical-align: top;
+    .top-day {
+      text-align: right;
+      font-size: 13px;
+    }
+  }
+}
+.table-date {
+  display: flex;
+  > div {
+    flex: 1;
+  }
+}
+</style>

+ 290 - 0
src/views/ticket/schedulingConfiguration/dialog/perFormDeatils.vue

@@ -0,0 +1,290 @@
+<template>
+    <el-dialog 
+    :title="title" 
+    :visible.sync="open" 
+    width="90%" 
+    class="text-dia-log-class" 
+    append-to-body
+    center
+    :close-on-click-modal="false" 
+    @close="cancel">
+        <div class="dialog" v-loading="loading">
+            <div>
+                <el-radio-group v-model="radio1" @input="getData">
+                    <el-radio-button :label="1">基本信息</el-radio-button>
+                    <el-radio-button :label="2">销售信息</el-radio-button>
+                </el-radio-group>
+            </div>
+            <div v-if="radio1 == 1">
+                <el-form :model="form" ref="form" label-width="120px">
+                    <el-form-item label="票务名称:">
+                        <span>{{ form.goodsNames }}</span>
+                    </el-form-item>
+                    <el-form-item label="库存模板:">
+                        <span>{{ form.stockTmpName }}</span>
+                    </el-form-item>
+                    <el-form-item label="最后修改人:">
+                        <span>{{ form.updateBy }}</span>
+                    </el-form-item>
+                    <el-form-item label="最后修改时间:">
+                        <span>{{ form.updateTime }}</span>
+                    </el-form-item>
+                </el-form>
+            </div>
+            <div v-if="radio1 == 2">
+                <div style="display: flex;align-items: center;padding-bottom: 10px;">
+                    <span>票务名称:</span>
+                    <div style="width: 300px;">
+                        <el-select
+                            v-model="goodsIds"
+                            placeholder="请选择票务名称"
+                            clearable
+                            style="width: 100%"
+                            @change="getPerformTimeDataFun"
+                            >
+                            <el-option
+                                v-for="dict in goodsPageListS"
+                                :key="dict.id"
+                                :value="dict.id"
+                                :label="dict.status == 1 ? dict.goodsName + '(被禁用)': dict.goodsName"
+                                :disabled="dict.status != 0"
+                                >
+                            </el-option>
+                        </el-select>
+                    </div>
+                </div>
+                
+                <el-table ref="tables" v-loading="loading" :data="timeList" border>
+                    <el-table-column label="票档名称" align="center" prop="seatTypeName" />
+                    <el-table-column label="小程序已售(个)" align="center" prop="microAppTotal">
+                        <template slot-scope="scope">
+                            <span>{{ scope.row.microAppTotal }} / {{ scope.row.total }}</span>
+                        </template>
+                    </el-table-column>
+                    <el-table-column label="团购已售(个)" align="center" prop="groupBuyTotal">
+                        <template slot-scope="scope">
+                            <span>{{ scope.row.groupBuyTotal }} / {{ scope.row.total }}</span>
+                        </template>
+                    </el-table-column>
+                    <el-table-column label="窗口已售(个)" align="center" prop="winTotal">
+                        <template slot-scope="scope">
+                            <span>{{ scope.row.winTotal }} / {{ scope.row.total }}</span>
+                        </template>
+                    </el-table-column>
+                    <el-table-column label="美团已售(个)" align="center" prop="meituanTotal">
+                        <template slot-scope="scope">
+                            <span>{{ scope.row.meituanTotal }} / {{ scope.row.total }}</span>
+                        </template>
+                    </el-table-column>
+                    <el-table-column label="携程已售(个)" align="center" prop="xiechenTotal">
+                        <template slot-scope="scope">
+                            <span>{{ scope.row.xiechenTotal }} / {{ scope.row.total }}</span>
+                        </template>
+                    </el-table-column>
+                    <el-table-column label="猫眼已售(个)" align="center" prop="maoyanTotal">
+                        <template slot-scope="scope">
+                            <span>{{ scope.row.maoyanTotal }} / {{ scope.row.total }}</span>
+                        </template>
+                    </el-table-column>
+                    <el-table-column label="抖音已售(个)" align="center" prop="duoyinTotal">
+                        <template slot-scope="scope">
+                            <span>{{ scope.row.duoyinTotal }} / {{ scope.row.total }}</span>
+                        </template>
+                    </el-table-column>
+                    <el-table-column label="其他已售(个)" align="center" prop="otherTotal">
+                        <template slot-scope="scope">
+                            <span>{{ scope.row.otherTotal }} / {{ scope.row.total }}</span>
+                        </template>
+                    </el-table-column>
+                    <el-table-column label="合计已售(个)" align="center" prop="saleTotal">
+                        <template slot-scope="scope">
+                            <span>{{ scope.row.saleTotal }} / {{ scope.row.total }}</span>
+                        </template>
+                    </el-table-column>
+                    <el-table-column label="剩余(个)" align="center" prop="name">
+                        <template slot-scope="scope">
+                            <span>{{ scope.row.noSaleTotal }} / {{ scope.row.total }}</span>
+                        </template>
+                    </el-table-column>
+                </el-table>
+            </div>
+        </div>
+        <span slot="footer" class="dialog-footer">
+            <el-button 
+            :type="this.form.status == 2 ? 'primary': 'danger'" 
+            @click="releaseFun" 
+            :loading="loading">
+                <span>{{ this.form.status == 2 ? '启用本场次': '禁用本场次' }}</span>
+            </el-button>
+        </span>
+    </el-dialog>
+</template>
+
+<script>
+import { releaseById, getPerformTimeById,seatTypeTmpSaleCount } from "@/api/ticketMr/schedulingConfiguration";
+import { goodsPageList as goodsPageListApi } from "@/api/ticketMr/schedulingConfiguration";
+import moment from "moment"
+export default {
+    name: "PerFormDeatils",
+    data() {
+        return {
+            title: "编辑",
+            model: "EDIT",
+            open: false,
+            loading: false,
+            timeList: [],
+            form: {
+                id: undefined,
+                timeList: [],
+                insertType: '1',
+                useStock: 0
+            },
+            radio1: 1,
+            goodsIds: null,
+            goodsPageListS: []
+        };
+    },
+    methods: {
+        /**
+         * 打开弹框
+         * @date 2023-11-22
+         * @param {any} obj
+         * @returns {any}
+         */
+        async openDialog(title, obj, type) {
+            this.open = true;
+            this.radio1 == 0
+            this.goodsIds = []
+            let list = ["星期天","星期一","星期二","星期三","星期四","星期五","星期六"]
+            this.title = obj.performDate + "  " + list[moment(obj.performDate).day()] +"  "+ obj.performTimeStart + "-" + obj.performTimeEnd 
+            this.form = {}
+            console.log("boj===",obj)
+            this.goodsPageListFun(obj.performId)
+            if(this.radio1 == 1) {
+                this.getPerformTimeByIdFun(obj.id)
+            }else if(this.radio1 == 2){
+                this.getPerformTimeDataFun(obj)
+            }
+        },
+        /**  票务信息  */
+        async goodsPageListFun(value){
+            try {
+                let res = await goodsPageListApi({
+                    performId: value
+                })
+                if(res.code == 200){
+                this.goodsPageListS = res.data
+                }
+            } catch (error) {      
+            }
+        },
+        getData(value) {
+            if(value == 1) {
+                this.getPerformTimeByIdFun(this.form.id)
+            }else if(value == 2){
+                this.getPerformTimeDataFun(this.form)
+            }
+        },
+         /**  基本信息  */
+        async getPerformTimeByIdFun(id){
+            try {
+                this.loading = true
+                let res = await getPerformTimeById({
+                    id: id
+                })
+                if(res.code == 200){
+                    this.form = res.data
+                }
+                this.loading = false
+            } catch (error) {   
+                this.loading = false
+                console.error("error====",error)   
+            }
+        },
+         /**  统计  */
+        async getPerformTimeDataFun(){
+            try {
+                this.loading = true
+                let res = await seatTypeTmpSaleCount({
+                    id: this.form.id,
+                    goodsId: this.goodsId
+                })
+                if(res.code == 200){
+                this.timeList = res.data.rows.filter((item)=>{
+                        if(item.performDate == this.form.performDate) {
+                            return item
+                        }
+                    })
+                }
+                this.loading = false
+            } catch (error) {     
+                this.loading = false 
+            }
+        },
+        releaseFun(){
+            let srt = this.form.status == 1?`确定要启用该场次进行售卖吗?`:`确定要禁用该场次进行售卖吗?`
+            this.$modal.confirm(srt).then(()=> {
+                this.submitForm()
+            }).catch(() => {});
+        },
+        /**
+         * 保存
+         * @date 2023-11-22
+         * @returns {any}
+         */
+        async submitForm() {
+            try {
+                this.loading = true
+                let res = await releaseById({
+                    id: this.form.id,
+                    status: this.form.status == 1 ? 2 : 1
+                })
+                if(res.code == 200){
+                    this.$message.success("操作成功");
+                    this.$emit("getList")
+                    this.cancel()
+                }
+                this.loading = false
+            } catch (error) {    
+                console.error("error===",error) 
+                this.loading = false 
+            }
+        },
+        /**
+         * 关闭弹框
+         * @date 2023-11-22
+         * @returns {any}
+         */
+        cancel() {
+            this.open = false;
+        },
+    },
+};
+</script>
+
+<style lang="scss" scoped>
+.dialog {
+    height: 65vh;
+    overflow-y: auto;
+    .upload-btn {
+        width: 100px;
+        height: 100px;
+        background-color: #fbfdff;
+        border: dashed 1px #c0ccda;
+        border-radius: 5px;
+
+        i {
+            font-size: 30px;
+            margin-top: 20px;
+        }
+
+        &-text {
+            margin-top: -10px;
+        }
+    }
+
+    .avatar {
+        cursor: pointer;
+    }
+}
+</style>

+ 223 - 0
src/views/ticket/schedulingConfiguration/dialog/perFormListBox.vue

@@ -0,0 +1,223 @@
+<template>
+    <el-dialog :title="title" :visible.sync="open" width="90%" class="text-dia-log-class" append-to-body center
+        :close-on-click-modal="false" @close="cancel">
+        <div class="dialog">
+            <div>
+                <el-button type="primary" @click="handleAdd('ADD')">新增</el-button>
+            </div>
+            <el-table ref="tables" v-loading="loading" :data="timeList" border>
+                <el-table-column label="序号" align="center" type="index" />
+                <el-table-column label="编号ID" align="center" prop="planNo" />
+                <el-table-column label="日期范围" align="center" prop="dateStart">
+                    <template slot-scope="scope">
+                        {{ scope.row.dateStart }} - {{ scope.row.dateEnd }}
+                    </template>
+                </el-table-column>
+                <el-table-column label="星期" align="center" prop="weekType">
+                    <template slot-scope="scope">
+                        <span>{{ weekList[scope.row.weekType] }}</span>
+                    </template>
+                </el-table-column>
+                <el-table-column label="票务" align="center" prop="goodsNames" />
+                <el-table-column label="场次信息" align="center" prop="planSessionList">
+                    <template slot-scope="scope">
+                        <div v-if="scope.row.planSessionList">
+                            <span 
+                            v-for="(item,index) in scope.row.planSessionList"
+                            :key="index"
+                            style="margin-right: 10px;"
+                            >{{ item.startInterval }} - {{ item.endInterval }}</span>
+                        </div>
+                    </template>
+                </el-table-column>
+                <el-table-column label="最后修改时间" align="center" prop="updateTime" />
+                <el-table-column label="最后修改人" align="center" prop="updateBy" />
+                <el-table-column label="操作" align="center" prop="name">
+                    <template slot-scope="scope">
+                        <el-button
+                            size="mini"
+                            type="text"
+                            @click="copyAdd(scope.row)"
+                        >复刻</el-button>
+                        <el-button
+                            size="mini"
+                            type="text"
+                            style="margin-left: 10px;"
+                            @click="deleteFun(scope.row)"
+                            >删除</el-button>
+                    </template>
+                </el-table-column>
+            </el-table>
+        </div>
+        <span slot="footer" class="dialog-footer">
+            <pagination
+            v-show="total>0"
+            :total="total"
+            :page.sync="queryParams.pageNum"
+            :limit.sync="queryParams.pageSize"
+            @pagination="getPerformTimeByIdFun"
+            />
+        </span>
+        <!-- 新增/编辑弹框 -->
+        <add-and-edit
+        ref="addAndEdit"
+        @getList="getPerformTimeByIdFun"
+        />
+    </el-dialog>
+</template>
+
+<script>
+import { deleteById,pageList, getPerformTimeById } from "@/api/ticketMr/schedulingConfiguration";
+import moment from "moment"
+import addAndEdit from "./addAndEdit";
+export default {
+    name: "PerFormListBox",
+    components: { addAndEdit },
+    data() {
+        return {
+            title: "编辑",
+            model: "EDIT",
+            open: false,
+            loading: false,
+            timeList: [],
+            weekList: ["星期一","星期二","星期三","星期四","星期五","星期六","星期天"],
+            form: {
+                id: undefined,
+                timeList: [],
+                insertType: '1',
+                useStock: 0
+            },
+            radio1: 1,
+            total: 0,
+            queryParams: {
+                pageNum: 1,
+                pageSize: 10,
+            },
+        };
+    },
+    methods: {
+        /**
+         * 打开弹框
+         * @date 2023-11-22
+         * @param {any} obj
+         * @returns {any}
+         */
+        async openDialog(title, obj, type) {
+            this.open = true;
+            this.title = title
+            this.form = {}
+            this.queryParams.pageNum = 1
+            this.getPerformTimeByIdFun()
+        },
+        /**  票务信息  */
+        async getPerformTimeByIdFun() {
+            try {
+                this.loading = true
+                let res = await pageList({
+                    ...this.queryParams
+                })
+                if (res.code == 200) {
+                    this.timeList = res.data.rows
+                    this.total = res.data.total
+                }
+                this.loading = false
+            } catch (error) {
+                this.loading = false
+                console.error("error====", error)
+            }
+        },
+        /** 新增按钮操作 */
+        handleAdd(type) {
+            this.$refs["addAndEdit"].openDialog("新增数据", null, type);
+        },
+        /** 复刻 */
+        copyAdd(row) {
+            this.$refs["addAndEdit"].openDialog("新增数据", row, "ADD");
+        },
+        /**
+         * 保存
+         * @date 2023-11-22
+         * @returns {any}
+         */
+        async submitForm() {
+            try {
+                this.loading = true
+                let res = await releaseById({
+                    id: this.form.id,
+                    status: this.form.status == 1 ? 2 : 1
+                })
+                if (res.code == 200) {
+                    this.$message.success("操作成功!");
+                    this.$emit("getList")
+                    this.cancel()
+                }
+                this.loading = false
+            } catch (error) {
+                console.error("error===", error)
+                this.loading = false
+            }
+        },
+        /**
+         * 关闭弹框
+         * @date 2023-11-22
+         * @returns {any}
+         */
+        cancel() {
+            this.open = false;
+        },
+        deleteFun(row){
+            this.$modal.confirm(`您确定要删除此次排期计划吗?`).then(()=> {
+                this.handleDelete(row)
+            }).catch(() => {});
+        },
+        /**  删除  */
+        async handleDelete(row) {
+            try {
+                this.loading = true
+                let res = await deleteById({
+                    id: row.id
+                })
+                if (res.code == 200) {
+                    this.$message.success("删除成功");
+                    this.getPerformTimeByIdFun()
+                }
+                this.loading = false
+            } catch (error) {
+                this.loading = false
+                console.error("error====", error)
+            }
+        },
+        openDetails() {
+
+        }
+    },
+};
+</script>
+
+<style lang="scss" scoped>
+.dialog {
+    height: 65vh;
+    overflow-y: auto;
+
+    .upload-btn {
+        width: 100px;
+        height: 100px;
+        background-color: #fbfdff;
+        border: dashed 1px #c0ccda;
+        border-radius: 5px;
+
+        i {
+            font-size: 30px;
+            margin-top: 20px;
+        }
+
+        &-text {
+            margin-top: -10px;
+        }
+    }
+
+    .avatar {
+        cursor: pointer;
+    }
+}
+</style>

+ 199 - 0
src/views/ticket/schedulingConfiguration/index.vue

@@ -0,0 +1,199 @@
+<template>
+  <div class="app-container app-calendar-container">
+    <div>
+      <el-button type="primary" @click="handlePerFormList('ADD')">排期配置</el-button>
+    </div>
+    <div v-loading="loading">
+      <el-calendar v-model="timeValue" v-if="showCalendar">
+        <template
+          slot="dateCell"
+          slot-scope="{date, data}">
+          <div @click.stop="selectTime(data.day)" :class="data.isSelected ? 'is-selected' : ''">
+            <span>{{ data.day.split('-').slice(1).join('-') }}</span>
+            <div style="width: 100%; display: flex;flex-wrap: wrap;" >
+              <div 
+              :key="index"
+              :style="{marginLeft: index%2 == 0?'':'20px'}"
+              v-for="(item,index) in getPerFormList(data)"
+              @click.stop="handlePerFormDeatils(item)"
+              >
+              {{ item.performTimeStart }}-{{ item.performTimeEnd }}
+              </div>
+            </div>
+            
+          </div>
+          
+        </template>
+      </el-calendar>
+      <!-- <calendarBox /> -->
+    </div>
+    <!-- 排期详情  -->
+    <perFormDeatils ref="perFormDeatils" @getList="getList" />
+
+    <!-- 排期列表 -->
+    <perFormListBox ref="perFormListBox" @getList="getList" />
+  </div>
+</template>
+
+<script>
+
+import { calendarList } from '@/api/ticketMr/schedulingConfiguration'
+
+import moment from "moment"
+import calendarBox from './dialog/calendarBox.vue';
+import perFormDeatils from './dialog/perFormDeatils.vue';
+import perFormListBox from './dialog/perFormListBox.vue';
+export default {
+  name: "SchedulingConfiguration",
+  dicts: [],
+  components: { calendarBox,perFormDeatils,perFormListBox },
+  data() {
+    return {
+      // 遮罩层
+      loading: true,
+      // 弹出层标题
+      title: "",
+      // 查询参数
+      queryParams: {
+        startDate: null,
+        endDate: null,
+      },
+      timeValue: new Date(),
+      perFormList: [],
+      showCalendar: false,
+    };
+  },
+  created() {
+    this.showCalendar = false
+    this.queryParams = {
+        startDate: moment(this.timeValue).startOf('month').format("YYYY-MM-DD"),
+        endDate: moment(this.timeValue).endOf('month').format("YYYY-MM-DD"),
+      }
+    this.getList();
+  },
+  methods: {
+    /** 查询列表 */
+    getList() {
+      this.loading = true;
+      let params = JSON.parse(JSON.stringify(this.queryParams))
+      calendarList(this.addDateRange({...params}, this.dateRange))
+      .then(response => {
+          console.log(response)
+          this.perFormList = response.data.rows
+          this.showCalendar = true
+          this.loading = false;
+        }
+      ).catch(() => {
+        this.loading = false;
+      });
+    },
+    getPerFormList(data) {
+      let list = []
+      this.perFormList.forEach((item,index)=>{
+        if(item.performDate == data.day) {
+          console.log("dsfsdfdsfdsf")
+          list = item.list
+        }
+      })
+      return list
+    },
+    selectTime(value){
+      console.log("value====",value)
+      // this.queryParams = {
+      //   startDate: moment(value).startOf('month').format("YYYY-MM-DD"),
+      //   endDate: moment(value).endOf('month').format("YYYY-MM-DD"),
+      // }
+      // this.getList();
+    },
+    
+    /** 修改按钮操作 */
+    handleUpdate(row) {
+      this.$refs["addAndEdit"].openDialog("修改数据", row);
+    },
+
+    /** 排期详情  */
+    handlePerFormDeatils(row) {
+      this.$refs["perFormDeatils"].openDialog("排期详情", row);
+    },
+
+    /** 排期列表 */
+    handlePerFormList() {
+      this.$refs["perFormListBox"].openDialog("排期详情", null);
+    },
+    // 获取日历显示时间范围
+    getRange(date){
+      // 日历第一天
+      let firstDay = '';
+      // 日历最后一天
+      let lastDay = '';
+      // 今天
+      const today = date ? date : new Date()
+      // 上月
+      const m = today.getMonth()
+      // 本月
+      const cm = m + 1
+      // 下月
+      const lm = m + 2 > 12 ? 1 : m + 2
+      // 要显示的本月
+      const currentMonth = cm < 10 ? '0' + cm : cm
+      // 要显示的本本年
+      const currentYear = today.getFullYear()
+      // 要显示的上个月的年份,m = 0 则当前1月,上月则是去年12月
+      const prevYear = m == 0 ? currentYear - 1 : currentYear
+      const prevMonth = m == 0 ? 12 : m < 10 ? '0' + m : m
+      // 上个月天数
+      const pmd = new Date(prevYear, m, 0).getDate()
+      // 下个月的年份,当前12月,则需要加一年
+      const lastYear = cm + 1 > 12 ? currentYear + 1 : currentYear
+      const lastMonth = lm < 10 ? '0' + lm : lm
+      // 1号是周几
+      const firstWeek = new Date(today.setDate(1)).getDay()
+      // 如果是周日,则不需要显示上个月
+      if (firstWeek == 0) {
+        firstDay = `${currentYear}-${currentMonth}-01`
+      }
+      // 其他周几,对应用上个月的天数往前推算
+      else {
+        firstDay = `${prevYear}-${prevMonth}-${pmd - (firstWeek - 1)}`
+      }
+      // 这个月天数
+      const currentMonthDate = new Date(currentYear, cm, 0).getDate()
+      // 最后一天是周几
+      const lastWeek = new Date(today.setDate(currentMonthDate)).getDay()
+      // 周六显示当月最后一天
+      if (lastWeek == 6) {
+        lastDay = `${currentYear}-${currentMonth}-${currentMonthDate}`
+      }
+      // 其他周几,对应往后推算
+      else {
+        const day = ['06', '05', '04', '03', '02', '01']
+        lastDay = `${lastYear}-${lastMonth}-${day[lastWeek]}`
+      }
+      console.log('第一天', firstDay)
+      console.log('最后一天', lastDay)
+      this.queryParams = {
+        startDate: firstDay,
+        endDate: lastDay,
+      }
+      this.getList();
+    }
+  },
+  watch:{
+    timeValue(newValue,oldValue){
+      let time = moment(newValue).format("YYYY-DD-MM")
+      if (newValue.getFullYear() !== oldValue.getFullYear() || newValue.getMonth() !== oldValue.getMonth()) {
+        this.getRange(newValue)
+      }
+    }
+  }
+};
+</script>
+<style scoped lang="scss">
+.is-selected {
+  color: #1989FA;
+}
+.app-calendar-container ::v-deep .el-calendar-table .el-calendar-day {
+    height: auto;
+    min-height: 86px;
+}
+</style>