后台,日历面板自定义

实现效果

业务需求:

1.查看当前人员每个月的排班信息

2.通过二次弹窗调整排班

主要实现方法:

1.需要根据后端返回数据渲染面板,eleui没有提供方法,需要自己手动更新面板,这里我是通过getCurTime(获取当前面板月份)和resetHtml(配合v-if重新渲染)实现的。

2.月份只显示当月,通过样式把不是当月的隐藏掉

完整代码:vue3+ts

1.弹窗代码

<template>
  <!-- 弹窗 -->
  <el-dialog v-model="props.dialogVisible" v-if="props.dialogVisible" width="60%" @close="cancel"
    :close-on-click-modal="false">
    <!-- 标题 -->
    <template #header>
      <div class="report-title">
        <span>查看排班</span>
      </div>
    </template>
    <!-- 日历面板 -->
    <el-calendar ref="calendar" v-model="data.value" class="calendar-box">
      <!-- 头部 -->
      <template #header="{ date }">
        <div class="calendar-title">
          <el-button size="small" @click="selectDate('prev-month')">
            上个月
          </el-button>
          <span>{{ getCurTime(date) }}</span>
          <el-button size="small" @click="selectDate('next-month')">
            下个月
          </el-button>
        </div>
      </template>
      <!-- 主要区域 -->
      <template #date-cell="{ data }" v-if="data.resetHtml">
        <!-- 自定义格式显示日期01-31 -->
        <p>{{ data.day.split('-').slice(2).join('-') }}</p>
        <!-- 当前账号 -->
        <p>{{ getCurAccount(data.day) }}</p>
        <el-button :disabled="disabledHandle(data)" link size="small"
          @click="editSchedule(getCurAccount(data.day), data)">
          编辑排班
        </el-button>
      </template>
    </el-calendar>
    <!--编辑排班弹窗 -->
    <el-dialog class="modify-box" v-model="data.innerVisible" append-to-body width="500" title="编辑排班" @close="cancelInner">
      <el-form :model="data.formData" ref="formRef" :rules="data.rules" label-width="130px" label-suffix=":">
        <el-form-item label="账号" prop="userOmsAccount">
          <el-select class="select-box" v-model="data.formData.userOmsAccount" placeholder="请选择" style="width: 100%;"
            :disabled="props.dialogItem.type === 'view'">
            <el-option v-for="item in data.accounList" :label="item.username" :value="item.userId" />
          </el-select>
        </el-form-item>
        <el-form-item label="调整排班" prop="workingStatus">
          <el-switch active-text="上班" inactive-text="下班" :active-value="1" :inactive-value="0"
            v-model="data.formData.workingStatus" />
        </el-form-item>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="cancelInner">返 回</el-button>
          <el-button type="primary" @click="submitInner(formRef)">保 存</el-button>
        </span>
      </template>
    </el-dialog>
  </el-dialog>
</template>

<script lang="ts" setup>
import { ElMessage } from 'element-plus'
import { filterDate } from '@/utils/filter';
import { useRoute } from 'vue-router'
import { reactive, onMounted, watch, ref, computed } from 'vue'
import { getScheduleInfo, getAccounListApi, updateScheduleInfo } from '@/api/taskConfig'
import type { CalendarDateType, CalendarInstance } from 'element-plus'
const calendar = ref<CalendarInstance>()
const formRef = ref(null);

const route = useRoute()
const props = defineProps({
  dialogVisible: { // 表格数据
    type: Boolean,
    default: false
  },
  dialogItem: {
    type: Object,
    default: () => { }
  }
})
const data = reactive({
  resetHtml: false,//面板区域重新渲染标识
  accounList: [],
  formData: {} as any,
  innerVisible: false,
  scheduleList: [],
  curTime: '',
  value: new Date(),
  rules: {
    userOmsAccount: [
      {
        required: true,
        message: '请选择',
        trigger: ['blur', 'change'],
      },
    ],
  }
})
onMounted(() => {
})

watch(() => props.dialogVisible, (newVal) => {
  if (newVal) {
    getAccounList()
  }
})

const emit = defineEmits(['submit'])
const getAccounList = async () => {
  let res: any = await getAccounListApi(route.query.id)
  if (res && res.data.code === "200") {
    data.accounList = res.data.data.centerUserList
  }
}
const save = async () => {
  let params = {
    ...data.formData,
    userOmsAccount: data.accounList.find((item: any) => item.userId === data.formData.userOmsAccount)?.username || ''
  }
  let res: any = await updateScheduleInfo(params)
  if (res && res.data.code === "200") {
    ElMessage.success('编辑排班成功')
    data.innerVisible = false
    initData()
  }
}
const submitInner = (formEl: any | undefined) => {
  if (!formEl) return
  formEl.validate((valid: any) => {
    if (valid) {
      save()
    } else {
      return false
    }
  })

}
const cancelInner = () => {
  data.innerVisible = false
}
const editSchedule = (val: any, time: any) => {
  // 当前账户信息
  let accountObj: any = data.accounList.find((item: any) => item.username === val)
  data.formData.workingDate = time.day
  data.formData.reportInterpretCenterId = route.query.id
  data.formData.temporaryId = props.dialogItem.temporaryId
  if (accountObj) {
    data.formData.userOmsAccount = accountObj.userId
    data.formData.workingStatus = 1
  } else {
    data.formData.userOmsAccount = ''
    data.formData.workingStatus = 1
  }
  data.innerVisible = true
}

const disabledHandle = (date: any) => {
  // 当天禁止
  let curDate = filterDate(new Date())
  if (curDate === date.day) {
    return true
  } else {
    return false
  }
}
const getCurAccount = (date: any) => {
  if (data.scheduleList.length) {
    let userOmsAccountObj: any = data.scheduleList.find((item: any) => item.workingDate === date)
    if (userOmsAccountObj) {
      return userOmsAccountObj.userOmsAccount
    } else {
      return ''
    }
  }

}
// 根据当前显示月份 获取面板数据
const getCurTime = (date: any) => {
  if (data.curTime !== date) {
    data.curTime = date
    initData()
  }
  return date
}
const selectDate = (val: CalendarDateType) => {
  if (!calendar.value) return
  calendar.value.selectDate(val)
}

const initData = async () => {
  data.resetHtml = false
  let params = {
    monthYear: formatMonthYear(data.curTime),
    reportInterpretCenterId: route.query.id,
    temporaryId: props.dialogItem.temporaryId,
  }
  let res: any = await getScheduleInfo(params)
  if (res && res.data.code === "200") {
    data.scheduleList = res.data.data
    data.resetHtml = true
  }
}
//  2025 年 4 月转换为2025-04
const formatMonthYear = (dateStr: string): string => {
  const date = dateStr.split(' ');
  const formattedMonth = date[2].padStart(2, '0'); // 确保月份是两位数
  return `${date[0]}-${formattedMonth}`;
}

const cancel = () => {
  resetForm()
  emit('submit')
}
// 重置弹窗数据
const resetForm = () => {
  data.resetHtml = false
  data.curTime = ''
  data.scheduleList = []
  data.value = new Date()
}
</script>
<style lang="scss" scoped>
::v-deep(.el-calendar-table td.is-today) {
  color: rgb(221, 96, 7);
  // color: rgb(51, 255, 102);
}

.edit-btn {
  padding: 5px 0;

}

// 非本月数据不显示
::v-deep .el-calendar-table:not(.is-range) td.prev,
::v-deep .el-calendar-table:not(.is-range) td.next {
  cursor: not-allowed;
  pointer-events: none;
}

.prev>.el-calendar-day>p {
  display: none;
}

.prev>.el-calendar-day>button {
  display: none;

}

.next>.el-calendar-day>p {
  display: none;
}

.next>.el-calendar-day>button {
  display: none;
}

.calendar-title {
  width: 100%;
  display: flex;
  justify-content: space-between;
}

.el-button--primary {
  background: #ff8833 !important;
}
</style>

2.使用弹窗

html,ts

<el-button link type="primary" @click="openDialog(scope.row, 'dialogVisibleView')">
  查看排班
</el-button>

<!-- 查看排班弹窗 -->
<ViewDialog :dialogVisible="data.dialogVisibleView" :dialogItem="data.dialogItem"
@cancel="cancel('dialogVisibleView')" @submit="submit('dialogVisibleView')">
</ViewDialog>
import ViewDialog from './components/ViewDialog.vue';

const data = reactive({
  dialogVisibleView: false,
  dialogItem: {} as any,

})

//间隔...

const openDialog = (val: Object, type: string) => {
  data.dialogItem = val
  data[type] = true
}
const cancel = (type: string) => {
  data[type] = false
}
const submit = (type: string) => {
  data[type] = false
  // data.pageData.pageNum = 1
  // searchHandle()
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值