<template>
  <div
    class="ticket-list-wrap"
    :class="{focusFlash:isFocus}">
    <div
      v-if="!isPeriodTicket"
      class="select-date">
      <div class="choose-date d-flex">
        <div class="top-title">
          游玩日期
        </div>
        <div class="date-list">
          <el-button
            v-for="(item,index) in quickDateList"
            :key="index"
            :type="playDate === item.value ? 'primary' : 'default'"
            :class="{ active: item.value === playDate}"
            @click="handleDateChange(item.value)">
            {{ item.label }}
          </el-button>
        </div>
      </div>
      <div class="select-date d-flex" style="margin-left: 90px">
        <div class="other-title">其他日期</div>
        <el-date-picker
          :clearable="false"
          :picker-options="dateOption"
          v-model="playDate"
          type="date"
          placeholder="选择日期时间"
          @change="handleDateChange"
        >
        </el-date-picker>
      </div>
    </div>
    <div
      v-if="category === 'batch'"
      class="select-batch">
      <div class="top-title">选择场次</div>
      <!-- <div
        class="noData"
        v-if="!batchList.length">
        暂无数据
      </div>
      <div class="list-content">
        <div
          class="list-item"
          :class="{
            active: currentBatch && currentBatch.batchConfigId === item.batchConfigId,
            disabled: item && item.leftNums === 0
          }"
          v-for="(item, index) in batchList"
          :key="`batch-${index}`"
          @click="handleBatchChange(item)"
        >
          <div
            class="badge"
            v-if="item && item.leftNums === 0">
            停售
          </div>
          <div class="title">
            <span class="name">{{ item.name }}</span>
            <span class="time">{{ removeSecond(item.startTime) }}-{{ removeSecond(item.endTime) }}</span>
          </div>
          <div class="left-count">
            余票：{{ getLeftNums(item) }}
          </div>
        </div>
      </div> -->
      <el-table
        ref="singleTable"
        max-height="200px"
        :data="batchList"
        :row-key="row => row.id"
        highlight-current-row
        @current-change="handleBatchChange"
        border
        stripe>
        <el-table-column
          prop="name"
          label="场次名称"
        >
        </el-table-column>

        <el-table-column
          prop="startTime"
          label="开始时间"
          width="70px"
        >
        </el-table-column>

        <el-table-column
          prop="endTime"
          label="结束时间"
          width="70px"
        >
        </el-table-column>

        <el-table-column
          prop="leftNums"
          label="剩余数量"
          width="70px"
        >
          <template slot-scope="scope">
            <span class="num">{{ scope.row.leftNums === '-1' ? '不限' : scope.row.leftNums }}</span>
          </template>
        </el-table-column>
      </el-table>
    </div>
    <div class="select-ticket">
      <div class="search-ticket d-flex align-center">
        <div class="top-title">选择票种</div>
        <el-input
          ref="quickSearch"
          id="quick-search"
          clearable
          class="search-input"
          placeholder="按F2 快速筛选"
          v-model="keyword">
          <i
            class="el-icon-search el-input__icon"
            slot="suffix">
          </i>
        </el-input>
        <el-button
          v-if="category !== 'batch'"
          size="small"
          class="sort-btn"
          icon="el-icon-sort"
          title="票种排序"
          @click="openSortDialog">
        </el-button>
      </div>
      <div
        :class="['ticket-list', category === 'batch' && 'list-batch']"
        v-loading="loading">
        <div
          class="noData"
          v-if="!filterTableData.length">
          暂无数据
        </div>
        <div class="list-content">
          <div
            class="list-item"
            :class="{
              active: currentTicket && currentTicket.id === item.id,
              active2: item.isTop && currentTicket && currentTicket.id !== item.id,
              disabled: item && item.isSale === 0
            }"
            v-for="(item, index) in filterTableData"
            :key="`ticket-${index}`"
            @click="changeTicket(item)"
            @contextmenu.prevent="showTopBtn(item)">
            <div class="badge" v-if="item && item.isSale === 0">
              停售
            </div>
            <div class="title">
              <i class="el-icon-info" style="cursor: pointer; margin-right: 8px;" title="查看票种详情" @click.stop="showTicketInfo(item)"></i>
              <el-tooltip
                :content="getTicketTip(item)"
                placement="top"
                effect="dark">
                <span>
                  {{ item.name }}
                </span>
              </el-tooltip>
            </div>
            <span
              class="price"
              v-if="item.price">
              <span class="num">{{ item.price }}</span> 元
            </span>
            <span
              class="price"
              v-else>
              无今日价格
            </span>
          </div>
        </div>
      </div>
    </div>
    <ElDialog
      :title="ticketDetail.name"
      width="650px"
      v-model="ticketInfoVisible">
      <TicketInfo :data="ticketDetail"></TicketInfo>
    </ElDialog>

    <!-- 票种排序弹框 -->
    <native-dialog
      title="票种排序"
      :visible.sync="sortDialogVisible"
      width="600px"
      :close-on-click-modal="false">
      <div v-loading="sortLoading">
        <draggable
          v-model="sortList"
          handle=".sort-item"
          animation="200">
          <div
            class="sort-item"
            v-for="item in sortList"
            :key="item.ticketTypeId">
            <span class="sort-name">{{ item.name }}</span>
            <el-tag
              size="small"
              :type="item.isSale !== 0 ? 'success' : 'info'">
              {{ item.isSale !== 0 ? '已激活' : '已禁用' }}
            </el-tag>
          </div>
        </draggable>
      </div>
      <span
        slot="footer"
        class="dialog-footer">
        <el-button @click="sortDialogVisible = false">取 消</el-button>
        <el-button
          type="primary"
          @click="saveSortList">确 定</el-button>
      </span>
    </native-dialog>
  </div>
</template>

<script>
import { getTicketTypeList, getTicketTypeByDate, saveTicketTypeSort } from '@/api/ticketType'
import draggable from 'vuedraggable'
import { getBatchList } from '@/api/batch'
import moment from 'moment'
import ElDialog from '@/components/Dialog'
import { Dialog as NativeDialog } from 'element-ui'
import TicketInfo from './TicketInfo'
import { EventBus } from '@/utils/eventBus'
// import TagSelector from './TagSelector.vue'

export default {
  props: {
    typeId: {
      type: String,
      default: ''
    },
    value: {
      type: Object,
      default: () => {
        return {}
      }
    }
  },
  components: {
    ElDialog,
    NativeDialog,
    TicketInfo,
    draggable
  },
  data () {
    return {
      keyControl: 1, // 键盘控制：1,2,3标识选中顺序
      isFocus: false, // 组件是否是选中状态
      loading: false,
      keyword: '',
      tableData: [],
      currentTicket: {},
      playDate: moment().format('YYYY-MM-DD'),
      showTopBtnId: -1,
      ticketDetail: {},
      ticketInfoVisible: false,
      topIds: [],
      selectedScenic: [],
      ticketTagList: [],
      selectedTag: '',
      dateOption: {
        // 日历禁用日期
        disabledDate () {
          return false
        }
      },
      quickDateList: [
        { label: '今天', value: moment().format('YYYY-MM-DD') },
        { label: '明天', value: moment().add(1, 'days').format('YYYY-MM-DD') },
        { label: '后天', value: moment().add(2, 'days').format('YYYY-MM-DD') }
      ],
      allBatchList: [],
      currentBatch: {},
      sortDialogVisible: false,
      sortLoading: false,
      sortList: []
    }
  },
  computed: {
    category () {
      return this.$route.meta.category || 'ticket'
    },
    sortType () {
      const category = this.$route.meta.category || 'ticket'
      const type = this.$route.meta.type
      if (category === 'batch') return 'batch'
      if (category === 'member') return 'member'
      if (type === 'team') return 'team'
      return 'single'
    },
    userScenic () {
      return this.$store.state.app.account.managerScenicMatrix ? this.$store.state.app.account.managerScenicMatrix.map(i => i.id) : []
    },
    scenicList () {
      return this.$store.state.app.scenicList
    },
    filterTableData () {
      let result = this.tableData.filter(item => {
        if (
          ((item.name).toLowerCase().indexOf(this.keyword.toLowerCase()) > -1 ||
          (item.pinyin).toLowerCase().indexOf(this.keyword.toLowerCase()) > -1 ||
          (item.shorthand).toLowerCase().indexOf(this.keyword.toLowerCase()) > -1)
        ) {
          return true
        }
      })
      let topList = []
      for (let i = 0; i < this.topIds.length; i++) {
        let topItem = result.find(item => item.id === this.topIds[i])
        if (topItem) {
          topItem.isTop = true
          topList.push(topItem)
        }
      }
      let downList = result.filter(item => topList.indexOf(item) === -1)
        .map(item => {
          item.isTop = false
          return item
        })
      return [...topList, ...downList]
    },
    ticketType () {
      return this.$route.meta.category || 'ticket'
    },
    batchList () {
      if (this.category !== 'batch') {
        return this.currentTicket?.batchConfigList || []
      } else {
        return this.allBatchList
      }
    },
    // 是否期票
    isPeriodTicket () {
      const category = this.$route.meta.category || 'ticket'
      const { useDateType } = this.currentTicket || {}
      return category === 'ticket' && useDateType === 2
    },
    ticketListMaxHeight () {
      return this.this.category === 'batch' ? '300px' : '500px'
    },
    isTeam () {
      return this.category === 'ticket' && this.$route.meta.type === 'team'
    }
  },
  watch: {
    value: {
      handler (val) {
        if (!val || !val.id) {
          this.currentTicket = {}
          return
        }

        this.currentTicket = val
      },
      immediate: true
    },
    // 当数据变化时，默认不选择票种
    filterTableData (val) {
      // 默认不选中票种
    },
    selectedTag (val) {
      this.getTicketTypeList()
    },
    userScenic: {
      handler (val) {
        this.selectedScenic = val
      },
      immediate: true
    },
    currentTicket (val, oldVal) {
      if (val?.id && !oldVal?.id) {
        this.getTicketTypeInfo()
      }
    }
  },
  created () {
    if (this.category === 'batch') {
      this.getBatchList()
    } else {
      this.getTicketTypeList()
    }
  },
  mounted () {
    document.getElementById('quick-search').focus()
    // this.getTicketTagList()
    this.getTopIds()
    EventBus.$on('orderCreated', () => {
      if (this.category === 'batch') {
        this.getBatchList()
      } else {
        // this.changeTicket(this.currentTicket)
      }

      this.currentTicket = {}
      this.$emit('update', null)
    })
  },
  methods: {
    // 按enter,移动组件焦点
    // handleEnter (keyBind) {
    //   keyBind.currentIndex++
    //   keyBind.setFocus()
    // },
    removeSecond (time) {
      return time ? time.slice(0, 5) : ''
    },
    getTicketTip (item) {
      let tip = ''

      if (item.useDateType === 2 || item.memberUseDateType === 2) {
        tip += '有效期：' + item.useDateStart + '至' + item.useDateEnd
      } else if (item.useDateType === 1 || item.memberUseDateType === 1) {
        tip += item.useDays ? `使用天数：${item.useDays}天` : ''
      } else {
      }

      return tip
    },
    getTicketTypeList () {
      this.loading = true
      const params = {
        pageNum: 1,
        isSale: 1,
        pageSize: 1000,
        ticketTypeName: '',
        orderBy: true,
        category: this.ticketType,
        sortType: this.sortType
      }
      // 根据售票类型筛选团散票种：(散客)筛选0和1，(团队)筛选0和2
      if (this.ticketType === 'ticket') {
        params.teamIndividualList = this.isTeam ? [0, 2] : [0, 1]
      }

      getTicketTypeList(params).then(res => {
        this.tableData = res.data.records.map(item => {
          // 添加拼音首字母
          item.pinyin = pinyinUtil.getFirstLetter(item.name)
          return item
        })
      }).finally(() => {
        this.loading = false
      })
    },
    getBatchList () {
      getBatchList({
        batchDateStart: this.playDate,
        batchDateEnd: this.playDate
      }).then(res => {
        if (res.code === '200') {
          console.log('获取场次数据成功', res.data)
          this.allBatchList = (res.data || []).map(item => {
            return {
              ...item,
              name: item.batchName,
              ...(item.batchResponseList?.[0] || {})
            }
          })

          if (this.allBatchList && this.allBatchList[0]) {
            this.currentBatch = this.allBatchList[0]
            this.$refs.singleTable.setCurrentRow(this.allBatchList[0])
            this.tableData = (this.currentBatch?.ticketTypes || []).map(item => {
              return {
                ...item,
                batchConfigId: this.currentBatch.batchConfigId
              }
            })
            // this.changeTicket(this.tableData[0])
            this.$emit('set-batch', this.currentBatch)
          }
        }
      })
    },
    async handleDateChange (val) {
      this.playDate = moment(val).format('YYYY-MM-DD')

      if (this.category === 'batch') {
        this.getBatchList()
      } else {
        this.getTicketTypeInfo()
      }
    },
    async getTicketTypeInfo () {
      if (!this.currentTicket || !this.currentTicket.id) {
        this.$message.warning('未选择票种')
        return
      }
      const playDate = moment(this.playDate).format('YYYY-MM-DD')
      this.$emit('changePlayDate', playDate)
      const res = await getTicketTypeByDate({
        ticketTypeId: this.currentTicket.id,
        playDateBegin: playDate
      })

      if (res.code === '200') {
        console.log(playDate, '获取票种数据成功', res.data)
        this.currentTicket = res.data
        this.currentTicket.playDate = playDate
        this.$emit('update', this.currentTicket)
        this.$emit('input', this.currentTicket)

        this.tableData.forEach(item => {
          if (item.id === this.currentTicket.id) {
            item.price = this.currentTicket.price
            item.isSale = this.currentTicket.isSale
          }
        })
      }
    },
    async changeTicket (ticket) {
      if (!ticket) {
        return
      }

      const playDate = moment(this.playDate).format('YYYY-MM-DD')
      this.$emit('changePlayDate', playDate)
      const res = await getTicketTypeByDate({
        ticketTypeId: ticket.id,
        playDateBegin: playDate
      })

      if (res.code === '200') {
        console.log(playDate, '获取票种数据成功', res.data)
        this.currentTicket = res.data
      } else {
        this.currentTicket = ticket
      }

      this.currentTicket.playDate = playDate

      // 设置不可选日期
      this.dateOption.disabledDate = (date) => {
        let beforeToday = moment().subtract(1, 'days').isAfter(date)
        let beforeStart = moment(ticket.useDateStart).isAfter(date)
        let afterEnd = moment(ticket.useDateEnd).isBefore(date)
        return beforeToday || beforeStart || afterEnd
      }

      this.$emit('update', this.currentTicket)
      this.$emit('input', this.currentTicket)

      this.tableData.forEach(item => {
        if (item.id === this.currentTicket.id) {
          item.price = this.currentTicket.price
          item.isSale = this.currentTicket.isSale
        }
      })

      EventBus.$emit('ticketChanged', this.currentTicket)
    },
    handleBatchChange (row) {
      console.log('当前选择的场次', row)
      if (!row || this.currentBatch?.batchConfigId === row.batchConfigId) {
        return
      }

      if (row.leftNums === 0) {
        this.$message.error('该场次已售完')
        return
      }

      this.currentBatch = row
      this.tableData = (this.currentBatch?.ticketTypes || []).map(item => {
        return {
          ...item,
          batchConfigId: row.batchConfigId
        }
      })
      this.$emit('set-batch', row)
    },
    formatDate (input) {
      return moment(input).format('YYYY-MM-DD')
    },
    showTicketInfo (data) {
      data.scenics = data.ticketTypeScenic?.map(s => s.scenic)
      this.ticketInfoVisible = true
      this.ticketDetail = data
    },
    setFocus () {
      this.$refs.quickSearch.focus()
      this.keyword = ''
    },
    arrowUp () {
      this.arrowCtrl(-1)
    },
    arrowDown () {
      this.arrowCtrl(1)
    },
    arrowCtrl (n) {
      let currentIndex = this.filterTableData.findIndex(item => item.id === this.currentTicket.id)
      let i = currentIndex + n
      if (this.filterTableData[i]) {
        this.changeTicket(this.filterTableData[i])
      }
    },
    showTopBtn (item) {
      this.showTopBtnId = item.id
    },
    getTopIds () {
      let arr = this.$localStore.get('topIds')
      if (!arr) arr = []
      this.topIds = arr
      // console.log('置顶', this.topIds)
    },
    setTop (item) {
      let arr = this.$localStore.get('topIds')
      if (!arr) arr = []
      if (arr.indexOf(item.id) !== -1) {
        arr.splice(arr.indexOf(item.id), 1)
      }
      arr.unshift(item.id)
      this.$localStore.set({
        'topIds': arr
      })
      this.getTopIds()
      this.showTopBtnId = -1
    },
    cancelTop (item) {
      let arr = this.$localStore.get('topIds')
      if (!arr) arr = []
      if (arr.indexOf(item.id) !== -1) {
        arr.splice(arr.indexOf(item.id), 1)
      }
      this.$localStore.set({
        'topIds': arr
      })
      this.getTopIds()
      this.showTopBtnId = -1
    },
    getLeftNums (item) {
      return item.leftNums <= -1 ? '不限' : item.leftNums
    },
    // 打开票种排序弹框
    async openSortDialog () {
      this.sortDialogVisible = true
      this.sortLoading = true
      try {
        // const sortRes = await getTicketTypeSort(this.sortType)
        // const sortData = sortRes?.data || []
        // 用排序接口的顺序排列 tableData
        const sortMap = new Map(this.tableData.map(s => [s.ticketTypeId, s.sort]))
        this.sortList = [...this.tableData]
          .map(item => ({
            ticketTypeId: item.id,
            name: item.name,
            isSale: item.isSale,
            sort: sortMap.has(item.id) ? sortMap.get(item.id) : 9999
          }))
          .sort((a, b) => a.sort - b.sort)
      } catch (e) {
        this.sortList = this.tableData.map((item, index) => ({
          ticketTypeId: item.id,
          name: item.name,
          isSale: item.isSale,
          sort: index
        }))
      } finally {
        this.sortLoading = false
      }
    },
    // 保存票种排序
    async saveSortList () {
      const sorts = this.sortList.map((item, index) => ({
        ticketTypeId: item.ticketTypeId,
        sort: index + 1
      }))
      const data = {
        type: this.sortType,
        sorts
      }
      try {
        await saveTicketTypeSort(data)
        this.$message.success('排序保存成功')
        this.sortDialogVisible = false
        // 按新排序更新 tableData
        const sortMap = new Map(sorts.map(s => [s.ticketTypeId, s.sort]))
        this.tableData.sort((a, b) => {
          return (sortMap.get(a.id) || 9999) - (sortMap.get(b.id) || 9999)
        })
      } catch (e) {
        this.$message.error('排序保存失败')
      }
    }
  },
  beforeDestroy () {
    EventBus.$off('orderCreated')
  }
}
</script>

<style lang="scss">
.d-flex {
  display: flex;
}
.align-center {
  align-items: center;
}
.el-table tr.current-row>td {
  background-color: #ccd5de !important;
  color: #0075ff !important;
}
</style>
<style lang="scss" scoped>
.el-radio {
  margin-right: 0;
}

.noData {
  width: 100px;
  padding: 10px;
  font-size: 14px;
  color: #666;
  text-align: center;
}

.price b {
  font-weight: 600;
}

.top-title {
  display: flex;
  padding: 10px 10px;
  font-size: 16px;
  line-height: 1.4;
  color: #333;
  background: #fff;
  justify-content: space-between;
  align-items: center;
  font-weight: 600;

  .right-btn {
    display: flex;
  }
}

.ticket-list-wrap {
  display: flex;
  padding: 20px 10px;
  height: 100%;
  box-sizing: border-box;
  flex-direction: column;
  background: #fff;
  border: 1px solid #ddd;
  border-radius: 4px;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, .1);

  .select-date {
    margin-bottom: 5px;
    align-items: center;

    .date-list {
      display: inline-flex;
      align-items: center;

      .el-button {
        height: 32px;
      }

      .other-title {
        margin-left: 20px;
      }
    }

    .el-date-editor {
      margin: 0 10px;
      width: 140px;
    }
  }

  .select-ticket {
    margin-bottom: 10px;
    margin-top: 10px;
    align-items: center;

    .search-input {
      width: calc(100% - 130px);
    }

    .sort-btn {
      margin-left: 2px;
    }

    .ticket-list {
      width: 100%;

      .list-content {
        margin: 5px 10px;
        width: calc(100% - 20px);
        max-height: 650px;
        overflow-y: auto;

        .list-item {
          position: relative;
          margin-bottom: 3px;
          flex-shrink: 0;
          width: auto;
          height: 32px;
          display: flex;
          color: #333;
          cursor: pointer;
          background: #F2F6FF;
          border: 2px solid #f0f0f0;
          transition: all .3s;
          justify-content: space-between;
          align-items: center;
          border-radius: 6px;
          padding: 0 10px;

          .title {
            width: calc(100% - 80px);
            margin-top: 4px;
            line-height: 1;

            span {
              overflow: hidden;
              white-space: nowrap;
              text-overflow: ellipsis;
              display: inline-block;
              max-width: 100%;
            }
          }

          .price {
            margin-left: 10px;

            .num {
              font-size: 18px;
              font-weight: bold;
            }
          }

          &:hover {
            z-index: 1;
            background: rgba(216, 225, 253, .3);
            border: 2px solid darken($blue, 1%);

          }

          &.active {
            z-index: 2;
            background: $blue;
            color: #fff;
            border: 2px solid darken($blue, 1%);

            .price {
              color: #fff;
            }
          }

          &.disabled {
            cursor: not-allowed;
            // background: $darkgray !important;
            border: 2px solid darken($darkgray, 8%);
            overflow: hidden;

            .badge {
              position: absolute;
              background: $darkgray;
              z-index: 1;
              width: 55px;
              text-align: center;
              height: 40px;
              line-height: 50px;
              border-radius: 3px;
              color: #fff;
              font-size: 12px !important;
              padding: 2px 4px 0;
              top: -14px;
              right: -23px;
              -ms-transform: rotate(45deg);
              -webkit-transform: rotate(45deg);
              transform: rotate(45deg);
              -webkit-transition: 0 0.1s ease-in;
              -moz-transition: 0 0.1s ease-in;
              -o-transition: 0 0.1s ease-in;
              transition: transform 0.1s ease-in;
            }
          }

        }

      }

      &.list-batch {
        .list-content {
          max-height: 450px;
        }
      }
    }
  }

  .select-batch {
    // display: flex;
    align-content: top;

    .list-content {
      display: flex;

      .list-item {
        position: relative;
        color: #333;
        cursor: pointer;
        background: #F2F6FF;
        border: 2px solid #f0f0f0;
        transition: all .3s;
        justify-content: space-between;
        align-items: center;
        border-radius: 6px;
        padding: 10px;
        margin-right: 10px;
        text-align: center;

        .title {
          .name {
            margin-right: 10px;
          }
        }

        .left-count {
          margin-top : 10px;
          font-size: 16px;
        }

        &:hover {
          z-index: 1;
          background: rgba(216, 225, 253, .3);
          border: 2px solid darken($blue, 1%);

          .goTop {
            i {
              display: inline-block;
            }
          }
        }

        &.active {
          z-index: 2;
          background: $blue;
          color: #fff;
          border: 2px solid darken($blue, 1%);

          .price {
            color: #fff;
          }
        }

        &.disabled {
          cursor: not-allowed;
          // background: $darkgray !important;
          border: 2px solid darken($darkgray, 8%);
          overflow: hidden;

          .badge {
            position: absolute;
            background: $darkgray;
            z-index: 1;
            width: 55px;
            text-align: center;
            height: 40px;
            line-height: 50px;
            border-radius: 3px;
            color: #fff;
            font-size: 12px !important;
            padding: 2px 4px 0;
            top: -14px;
            right: -23px;
            -ms-transform: rotate(45deg);
            -webkit-transform: rotate(45deg);
            transform: rotate(45deg);
            -webkit-transition: 0 0.1s ease-in;
            -moz-transition: 0 0.1s ease-in;
            -o-transition: 0 0.1s ease-in;
            transition: transform 0.1s ease-in;
          }
        }

        // &.active2 {
        //   border-color: rgb(67, 125, 233);
        // }
        .top-sign {
          position: absolute;
          top: 0;
          right: 0;
          width: 0;
          height: 0;
          border: 5px solid red;
          border-bottom-color: transparent;
          border-left-color: transparent;
        }
      }
    }
  }
}

.mutipleTag {
  position: absolute;
  top: 0;
  left: 0;
  width: 0;
  height: 0;
  color: #fff;
  pointer-events: none;

  border: 14px solid rgb(255, 94, 0);
  border-right-color: transparent;
  border-bottom-color: transparent;

  i {
    position: absolute;
    font-size: 12px;
    transform: translate(-12px, -12px);
  }
}

.list-wrap-batch {
  max-height: calc(100vh - 400px);
  flex: 1;
}

.sort-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 16px;
  border-bottom: 1px solid #eee;
  cursor: grab;
  background: #fff;
  transition: background 0.2s;

  &:hover {
    background: #f5f7fa;
  }

  &:active {
    cursor: grabbing;
  }

  .sort-name {
    font-size: 14px;
    color: #333;
  }
}
</style>
