From 816df6ec0a43ef777e0d4cd0daff61f870626d83 Mon Sep 17 00:00:00 2001
From: baoshiwei <baoshiwei@shlanbao.cn>
Date: 星期四, 05 六月 2025 13:53:12 +0800
Subject: [PATCH] feat(system): 添加节假日管理功能- 新增 SysHolidayController、SysHoliday、SysHolidayMapper、SysHolidayServiceImpl 和 ISysHolidayService 类- 实现节假日信息的增删改查和导出功能 - 添加工作日判断方法 - 新增相关 API 接口

---
 zhitan-vue/src/api/system/holiday.js                                                    |   53 ++
 zhitan-system/src/main/java/com/zhitan/system/service/impl/SysHolidayServiceImpl.java   |  146 ++++++
 zhitan-system/src/main/resources/mapper/airconditioner/AirConditionerMapper.xml         |   95 ++++
 zhitan-system/src/main/java/com/zhitan/system/controller/SysHolidayController.java      |  102 ++++
 zhitan-system/src/main/java/com/zhitan/system/mapper/SysHolidayMapper.java              |   69 +++
 zhitan-system/src/main/resources/mapper/airconditioner/AirConditionerLogMapper.xml      |  103 ++++
 zhitan-system/src/main/java/com/zhitan/system/service/ISysHolidayService.java           |   72 +++
 zhitan-system/src/main/resources/mapper/system/SysHolidayMapper.xml                     |  149 ++++++
 zhitan-system/src/main/resources/mapper/airconditioner/AirConditionerScheduleMapper.xml |  115 +++++
 zhitan-system/src/main/java/com/zhitan/system/domain/SysHoliday.java                    |   89 +++
 zhitan-vue/src/views/system/holiday/index.vue                                           |  331 ++++++++++++++
 11 files changed, 1,324 insertions(+), 0 deletions(-)

diff --git a/zhitan-system/src/main/java/com/zhitan/system/controller/SysHolidayController.java b/zhitan-system/src/main/java/com/zhitan/system/controller/SysHolidayController.java
new file mode 100644
index 0000000..2921b62
--- /dev/null
+++ b/zhitan-system/src/main/java/com/zhitan/system/controller/SysHolidayController.java
@@ -0,0 +1,102 @@
+package com.zhitan.system.controller;
+
+import java.util.List;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.zhitan.common.annotation.Log;
+import com.zhitan.common.core.controller.BaseController;
+import com.zhitan.common.core.domain.AjaxResult;
+import com.zhitan.common.enums.BusinessType;
+import com.zhitan.system.domain.SysHoliday;
+import com.zhitan.system.service.ISysHolidayService;
+import com.zhitan.common.utils.poi.ExcelUtil;
+import com.zhitan.common.core.page.TableDataInfo;
+
+/**
+ * 鑺傚亣鏃ヤ俊鎭疌ontroller
+ * 
+ * @author zhitan
+ */
+@RestController
+@RequestMapping("/system/holiday")
+public class SysHolidayController extends BaseController
+{
+    @Autowired
+    private ISysHolidayService sysHolidayService;
+
+    /**
+     * 鏌ヨ鑺傚亣鏃ヤ俊鎭垪琛�
+     */
+    @PreAuthorize("@ss.hasPermi('system:holiday:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(SysHoliday sysHoliday)
+    {
+        startPage();
+        List<SysHoliday> list = sysHolidayService.selectSysHolidayList(sysHoliday);
+        return getDataTable(list);
+    }
+
+    /**
+     * 瀵煎嚭鑺傚亣鏃ヤ俊鎭垪琛�
+     */
+    @PreAuthorize("@ss.hasPermi('system:holiday:export')")
+    @Log(title = "鑺傚亣鏃ヤ俊鎭�", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(SysHoliday sysHoliday)
+    {
+        List<SysHoliday> list = sysHolidayService.selectSysHolidayList(sysHoliday);
+        ExcelUtil<SysHoliday> util = new ExcelUtil<SysHoliday>(SysHoliday.class);
+        return util.exportExcel(list, "鑺傚亣鏃ヤ俊鎭暟鎹�");
+    }
+
+    /**
+     * 鑾峰彇鑺傚亣鏃ヤ俊鎭缁嗕俊鎭�
+     */
+    @PreAuthorize("@ss.hasPermi('system:holiday:query')")
+    @GetMapping(value = "/{holidayId}")
+    public AjaxResult getInfo(@PathVariable("holidayId") Long holidayId)
+    {
+        return success(sysHolidayService.selectSysHolidayById(holidayId));
+    }
+
+    /**
+     * 鏂板鑺傚亣鏃ヤ俊鎭�
+     */
+    @PreAuthorize("@ss.hasPermi('system:holiday:add')")
+    @Log(title = "鑺傚亣鏃ヤ俊鎭�", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody SysHoliday sysHoliday)
+    {
+        return toAjax(sysHolidayService.insertSysHoliday(sysHoliday));
+    }
+
+    /**
+     * 淇敼鑺傚亣鏃ヤ俊鎭�
+     */
+    @PreAuthorize("@ss.hasPermi('system:holiday:edit')")
+    @Log(title = "鑺傚亣鏃ヤ俊鎭�", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody SysHoliday sysHoliday)
+    {
+        return toAjax(sysHolidayService.updateSysHoliday(sysHoliday));
+    }
+
+    /**
+     * 鍒犻櫎鑺傚亣鏃ヤ俊鎭�
+     */
+    @PreAuthorize("@ss.hasPermi('system:holiday:remove')")
+    @Log(title = "鑺傚亣鏃ヤ俊鎭�", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{holidayIds}")
+    public AjaxResult remove(@PathVariable Long[] holidayIds)
+    {
+        return toAjax(sysHolidayService.deleteSysHolidayByIds(holidayIds));
+    }
+}
\ No newline at end of file
diff --git a/zhitan-system/src/main/java/com/zhitan/system/domain/SysHoliday.java b/zhitan-system/src/main/java/com/zhitan/system/domain/SysHoliday.java
new file mode 100644
index 0000000..37f59e5
--- /dev/null
+++ b/zhitan-system/src/main/java/com/zhitan/system/domain/SysHoliday.java
@@ -0,0 +1,89 @@
+package com.zhitan.system.domain;
+
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.zhitan.common.annotation.Excel;
+import com.zhitan.common.core.domain.BaseEntity;
+
+/**
+ * 鑺傚亣鏃ヤ俊鎭璞� sys_holiday
+ * 
+ * @author zhitan
+ */
+public class SysHoliday extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 鑺傚亣鏃D */
+    private Long holidayId;
+
+    /** 鑺傚亣鏃ュ悕绉� */
+    @Excel(name = "鑺傚亣鏃ュ悕绉�")
+    private String holidayName;
+
+    /** 鑺傚亣鏃ユ棩鏈� */
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @Excel(name = "鑺傚亣鏃ユ棩鏈�", width = 30, dateFormat = "yyyy-MM-dd")
+    private Date holidayDate;
+
+    /** 鑺傚亣鏃ョ被鍨嬶紙0姝e父鍋囨棩 1宸ヤ綔鏃ヨ皟浼戯級 */
+    @Excel(name = "鑺傚亣鏃ョ被鍨�", readConverterExp = "0=姝e父鍋囨棩,1=宸ヤ綔鏃ヨ皟浼�")
+    private String holidayType;
+
+    /** 鐘舵�侊紙0姝e父 1鍋滅敤锛� */
+    @Excel(name = "鐘舵��", readConverterExp = "0=姝e父,1=鍋滅敤")
+    private String status;
+
+    /** 澶囨敞 */
+    private String remark;
+
+    public Long getHolidayId() {
+        return holidayId;
+    }
+
+    public void setHolidayId(Long holidayId) {
+        this.holidayId = holidayId;
+    }
+
+    public String getHolidayName() {
+        return holidayName;
+    }
+
+    public void setHolidayName(String holidayName) {
+        this.holidayName = holidayName;
+    }
+
+    public Date getHolidayDate() {
+        return holidayDate;
+    }
+
+    public void setHolidayDate(Date holidayDate) {
+        this.holidayDate = holidayDate;
+    }
+
+    public String getHolidayType() {
+        return holidayType;
+    }
+
+    public void setHolidayType(String holidayType) {
+        this.holidayType = holidayType;
+    }
+
+    public String getStatus() {
+        return status;
+    }
+
+    public void setStatus(String status) {
+        this.status = status;
+    }
+
+    @Override
+    public String getRemark() {
+        return remark;
+    }
+
+    @Override
+    public void setRemark(String remark) {
+        this.remark = remark;
+    }
+}
\ No newline at end of file
diff --git a/zhitan-system/src/main/java/com/zhitan/system/mapper/SysHolidayMapper.java b/zhitan-system/src/main/java/com/zhitan/system/mapper/SysHolidayMapper.java
new file mode 100644
index 0000000..1ec4fb4
--- /dev/null
+++ b/zhitan-system/src/main/java/com/zhitan/system/mapper/SysHolidayMapper.java
@@ -0,0 +1,69 @@
+package com.zhitan.system.mapper;
+
+import java.util.Date;
+import java.util.List;
+import com.zhitan.system.domain.SysHoliday;
+
+/**
+ * 鑺傚亣鏃ヤ俊鎭疢apper鎺ュ彛
+ * 
+ * @author zhitan
+ */
+public interface SysHolidayMapper 
+{
+    /**
+     * 鏌ヨ鑺傚亣鏃ヤ俊鎭�
+     * 
+     * @param holidayId 鑺傚亣鏃ヤ俊鎭疘D
+     * @return 鑺傚亣鏃ヤ俊鎭�
+     */
+    public SysHoliday selectSysHolidayById(Long holidayId);
+
+    /**
+     * 鏍规嵁鏃ユ湡鏌ヨ鑺傚亣鏃ヤ俊鎭�
+     * 
+     * @param date 鏃ユ湡
+     * @return 鑺傚亣鏃ヤ俊鎭�
+     */
+    public SysHoliday selectSysHolidayByDate(Date date);
+    
+    /**
+     * 鏌ヨ鑺傚亣鏃ヤ俊鎭垪琛�
+     * 
+     * @param sysHoliday 鑺傚亣鏃ヤ俊鎭�
+     * @return 鑺傚亣鏃ヤ俊鎭泦鍚�
+     */
+    public List<SysHoliday> selectSysHolidayList(SysHoliday sysHoliday);
+
+    /**
+     * 鏂板鑺傚亣鏃ヤ俊鎭�
+     * 
+     * @param sysHoliday 鑺傚亣鏃ヤ俊鎭�
+     * @return 缁撴灉
+     */
+    public int insertSysHoliday(SysHoliday sysHoliday);
+
+    /**
+     * 淇敼鑺傚亣鏃ヤ俊鎭�
+     * 
+     * @param sysHoliday 鑺傚亣鏃ヤ俊鎭�
+     * @return 缁撴灉
+     */
+    public int updateSysHoliday(SysHoliday sysHoliday);
+
+    /**
+     * 鍒犻櫎鑺傚亣鏃ヤ俊鎭�
+     * 
+     * @param holidayId 鑺傚亣鏃ヤ俊鎭疘D
+     * @return 缁撴灉
+     */
+    public int deleteSysHolidayById(Long holidayId);
+
+    /**
+     * 鎵归噺鍒犻櫎鑺傚亣鏃ヤ俊鎭�
+     * 
+     * @param holidayIds 闇�瑕佸垹闄ょ殑鏁版嵁ID
+     * @return 缁撴灉
+     */
+    public int deleteSysHolidayByIds(Long[] holidayIds);
+}
\ No newline at end of file
diff --git a/zhitan-system/src/main/java/com/zhitan/system/service/ISysHolidayService.java b/zhitan-system/src/main/java/com/zhitan/system/service/ISysHolidayService.java
new file mode 100644
index 0000000..6a76346
--- /dev/null
+++ b/zhitan-system/src/main/java/com/zhitan/system/service/ISysHolidayService.java
@@ -0,0 +1,72 @@
+package com.zhitan.system.service;
+
+import java.util.Date;
+import java.util.List;
+import com.zhitan.system.domain.SysHoliday;
+
+/**
+ * 鑺傚亣鏃ヤ俊鎭疭ervice鎺ュ彛
+ * 
+ * @author zhitan
+ */
+public interface ISysHolidayService 
+{
+    /**
+     * 鏌ヨ鑺傚亣鏃ヤ俊鎭�
+     * 
+     * @param holidayId 鑺傚亣鏃ヤ俊鎭疘D
+     * @return 鑺傚亣鏃ヤ俊鎭�
+     */
+    public SysHoliday selectSysHolidayById(Long holidayId);
+
+    /**
+     * 鏌ヨ鑺傚亣鏃ヤ俊鎭垪琛�
+     * 
+     * @param sysHoliday 鑺傚亣鏃ヤ俊鎭�
+     * @return 鑺傚亣鏃ヤ俊鎭泦鍚�
+     */
+    public List<SysHoliday> selectSysHolidayList(SysHoliday sysHoliday);
+
+    /**
+     * 鏂板鑺傚亣鏃ヤ俊鎭�
+     * 
+     * @param sysHoliday 鑺傚亣鏃ヤ俊鎭�
+     * @return 缁撴灉
+     */
+    public int insertSysHoliday(SysHoliday sysHoliday);
+
+    /**
+     * 淇敼鑺傚亣鏃ヤ俊鎭�
+     * 
+     * @param sysHoliday 鑺傚亣鏃ヤ俊鎭�
+     * @return 缁撴灉
+     */
+    public int updateSysHoliday(SysHoliday sysHoliday);
+
+    /**
+     * 鎵归噺鍒犻櫎鑺傚亣鏃ヤ俊鎭�
+     * 
+     * @param holidayIds 闇�瑕佸垹闄ょ殑鑺傚亣鏃ヤ俊鎭疘D
+     * @return 缁撴灉
+     */
+    public int deleteSysHolidayByIds(Long[] holidayIds);
+
+    /**
+     * 鍒犻櫎鑺傚亣鏃ヤ俊鎭俊鎭�
+     * 
+     * @param holidayId 鑺傚亣鏃ヤ俊鎭疘D
+     * @return 缁撴灉
+     */
+    public int deleteSysHolidayById(Long holidayId);
+    
+    /**
+     * 鍒ゆ柇鏃ユ湡鏄惁涓哄伐浣滄棩
+     * 宸ヤ綔鏃ュ垽鏂�昏緫锛�
+     * 1. 濡傛灉鏄懆涓�鑷冲懆浜旓紝涓斾笉鏄硶瀹氳妭鍋囨棩锛屽垯涓哄伐浣滄棩
+     * 2. 濡傛灉鏄懆鍏棩锛屼絾鏄负璋冧紤宸ヤ綔鏃ワ紝鍒欎负宸ヤ綔鏃�
+     * 
+     * @param date 闇�瑕佸垽鏂殑鏃ユ湡
+     * @return 濡傛灉鏄伐浣滄棩杩斿洖true锛屽惁鍒欒繑鍥瀎alse
+     */
+    public boolean isWorkDay(Date date);
+}
\ No newline at end of file
diff --git a/zhitan-system/src/main/java/com/zhitan/system/service/impl/SysHolidayServiceImpl.java b/zhitan-system/src/main/java/com/zhitan/system/service/impl/SysHolidayServiceImpl.java
new file mode 100644
index 0000000..0ad0216
--- /dev/null
+++ b/zhitan-system/src/main/java/com/zhitan/system/service/impl/SysHolidayServiceImpl.java
@@ -0,0 +1,146 @@
+package com.zhitan.system.service.impl;
+
+import java.util.Calendar;
+import java.util.Date;
+import java.util.List;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.zhitan.common.utils.DateUtils;
+import com.zhitan.common.utils.SecurityUtils;
+import com.zhitan.system.mapper.SysHolidayMapper;
+import com.zhitan.system.domain.SysHoliday;
+import com.zhitan.system.service.ISysHolidayService;
+
+/**
+ * 鑺傚亣鏃ヤ俊鎭疭ervice涓氬姟灞傚鐞�
+ * 
+ * @author zhitan
+ */
+@Service
+public class SysHolidayServiceImpl implements ISysHolidayService 
+{
+    @Autowired
+    private SysHolidayMapper sysHolidayMapper;
+
+    /**
+     * 鏌ヨ鑺傚亣鏃ヤ俊鎭�
+     * 
+     * @param holidayId 鑺傚亣鏃ヤ俊鎭疘D
+     * @return 鑺傚亣鏃ヤ俊鎭�
+     */
+    @Override
+    public SysHoliday selectSysHolidayById(Long holidayId)
+    {
+        return sysHolidayMapper.selectSysHolidayById(holidayId);
+    }
+
+    /**
+     * 鏌ヨ鑺傚亣鏃ヤ俊鎭垪琛�
+     * 
+     * @param sysHoliday 鑺傚亣鏃ヤ俊鎭�
+     * @return 鑺傚亣鏃ヤ俊鎭泦鍚�
+     */
+    @Override
+    public List<SysHoliday> selectSysHolidayList(SysHoliday sysHoliday)
+    {
+        return sysHolidayMapper.selectSysHolidayList(sysHoliday);
+    }
+
+    /**
+     * 鏂板鑺傚亣鏃ヤ俊鎭�
+     * 
+     * @param sysHoliday 鑺傚亣鏃ヤ俊鎭�
+     * @return 缁撴灉
+     */
+    @Override
+    public int insertSysHoliday(SysHoliday sysHoliday)
+    {
+        sysHoliday.setCreateTime(DateUtils.getNowDate());
+        sysHoliday.setCreateBy(SecurityUtils.getUsername());
+        return sysHolidayMapper.insertSysHoliday(sysHoliday);
+    }
+
+    /**
+     * 淇敼鑺傚亣鏃ヤ俊鎭�
+     * 
+     * @param sysHoliday 鑺傚亣鏃ヤ俊鎭�
+     * @return 缁撴灉
+     */
+    @Override
+    public int updateSysHoliday(SysHoliday sysHoliday)
+    {
+        sysHoliday.setUpdateTime(DateUtils.getNowDate());
+        sysHoliday.setUpdateBy(SecurityUtils.getUsername());
+        return sysHolidayMapper.updateSysHoliday(sysHoliday);
+    }
+
+    /**
+     * 鎵归噺鍒犻櫎鑺傚亣鏃ヤ俊鎭�
+     * 
+     * @param holidayIds 闇�瑕佸垹闄ょ殑鑺傚亣鏃ヤ俊鎭疘D
+     * @return 缁撴灉
+     */
+    @Override
+    public int deleteSysHolidayByIds(Long[] holidayIds)
+    {
+        return sysHolidayMapper.deleteSysHolidayByIds(holidayIds);
+    }
+
+    /**
+     * 鍒犻櫎鑺傚亣鏃ヤ俊鎭俊鎭�
+     * 
+     * @param holidayId 鑺傚亣鏃ヤ俊鎭疘D
+     * @return 缁撴灉
+     */
+    @Override
+    public int deleteSysHolidayById(Long holidayId)
+    {
+        return sysHolidayMapper.deleteSysHolidayById(holidayId);
+    }
+    
+    /**
+     * 鍒ゆ柇鏃ユ湡鏄惁涓哄伐浣滄棩
+     * 宸ヤ綔鏃ュ垽鏂�昏緫锛�
+     * 1. 濡傛灉鏄懆涓�鑷冲懆浜旓紝涓斾笉鏄硶瀹氳妭鍋囨棩锛屽垯涓哄伐浣滄棩
+     * 2. 濡傛灉鏄懆鍏棩锛屼絾鏄负璋冧紤宸ヤ綔鏃ワ紝鍒欎负宸ヤ綔鏃�
+     * 
+     * @param date 闇�瑕佸垽鏂殑鏃ユ湡
+     * @return 濡傛灉鏄伐浣滄棩杩斿洖true锛屽惁鍒欒繑鍥瀎alse
+     */
+    @Override
+    public boolean isWorkDay(Date date)
+    {
+        if (date == null)
+        {
+            return false;
+        }
+        
+        // 鏌ヨ璇ユ棩鏈熸槸鍚﹀湪鑺傚亣鏃ヨ〃涓�
+        SysHoliday holiday = sysHolidayMapper.selectSysHolidayByDate(date);
+        
+        // 濡傛灉鍦ㄨ妭鍋囨棩琛ㄤ腑鎵惧埌璁板綍
+        if (holiday != null)
+        {
+            // 濡傛灉鏄皟浼戝伐浣滄棩锛堢被鍨嬩负1锛夛紝鍒欎负宸ヤ綔鏃�
+            if ("1".equals(holiday.getHolidayType()))
+            {
+                return true;
+            }
+            // 濡傛灉鏄硶瀹氳妭鍋囨棩锛堢被鍨嬩负0锛夛紝鍒欎笉鏄伐浣滄棩
+            else if ("0".equals(holiday.getHolidayType()))
+            {
+                return false;
+            }
+        }
+        
+        // 濡傛灉涓嶅湪鑺傚亣鏃ヨ〃涓紝鍒欏垽鏂槸鍚︿负鍛ㄤ竴鑷冲懆浜�
+        Calendar cal = Calendar.getInstance();
+        cal.setTime(date);
+        
+        int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK);
+        
+        // Calendar.DAY_OF_WEEK 涓紝1浠h〃鍛ㄦ棩锛�2浠h〃鍛ㄤ竴锛�3浠h〃鍛ㄤ簩锛�4浠h〃鍛ㄤ笁锛�5浠h〃鍛ㄥ洓锛�6浠h〃鍛ㄤ簲锛�7浠h〃鍛ㄥ叚
+        // 鎵�浠ュ伐浣滄棩瀵瑰簲鐨勫�兼槸2,3,4,5,6锛堝懆涓�鑷冲懆浜旓級
+        return dayOfWeek >= Calendar.MONDAY && dayOfWeek <= Calendar.FRIDAY;
+    }
+}
\ No newline at end of file
diff --git a/zhitan-system/src/main/resources/mapper/airconditioner/AirConditionerLogMapper.xml b/zhitan-system/src/main/resources/mapper/airconditioner/AirConditionerLogMapper.xml
new file mode 100644
index 0000000..fa66e42
--- /dev/null
+++ b/zhitan-system/src/main/resources/mapper/airconditioner/AirConditionerLogMapper.xml
@@ -0,0 +1,103 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.zhitan.airconditioner.mapper.AirConditionerLogMapper">
+    
+    <resultMap type="AirConditionerLog" id="AirConditionerLogResult">
+        <id     property="id"                column="id"                />
+        <result property="airConditionerId"  column="air_conditioner_id"  />
+        <result property="airConditionerName" column="air_conditioner_name" />
+        <result property="operateType"       column="operate_type"       />
+        <result property="operateMode"       column="operate_mode"       />
+        <result property="operateTime"       column="operate_time"       />
+        <result property="operateResult"     column="operate_result"     />
+        <result property="operateMsg"        column="operate_msg"        />
+        <result property="createBy"          column="create_by"          />
+        <result property="createTime"        column="create_time"        />
+        <result property="updateBy"          column="update_by"          />
+        <result property="updateTime"        column="update_time"        />
+        <result property="remark"            column="remark"            />
+    </resultMap>
+
+    <sql id="selectAirConditionerLogVo">
+        select id, air_conditioner_id, air_conditioner_name, operate_type, operate_mode, operate_time, operate_result, operate_msg, create_by, create_time, update_by, update_time, remark from air_conditioner_log
+    </sql>
+
+    <select id="selectAirConditionerLogList" parameterType="AirConditionerLog" resultMap="AirConditionerLogResult">
+        <include refid="selectAirConditionerLogVo"/>
+        <where>  
+            <if test="airConditionerId != null "> and air_conditioner_id = #{airConditionerId}</if>
+            <if test="airConditionerName != null  and airConditionerName != ''"> and air_conditioner_name like concat('%', #{airConditionerName}, '%')</if>
+            <if test="operateType != null  and operateType != ''"> and operate_type = #{operateType}</if>
+            <if test="operateMode != null  and operateMode != ''"> and operate_mode = #{operateMode}</if>
+            <if test="operateResult != null  and operateResult != ''"> and operate_result = #{operateResult}</if>
+            <if test="params.beginTime != null and params.beginTime != ''"><!-- 寮�濮嬫椂闂存绱� -->
+                AND date_format(operate_time,'%y%m%d') &gt;= date_format(#{params.beginTime},'%y%m%d')
+            </if>
+            <if test="params.endTime != null and params.endTime != ''"><!-- 缁撴潫鏃堕棿妫�绱� -->
+                AND date_format(operate_time,'%y%m%d') &lt;= date_format(#{params.endTime},'%y%m%d')
+            </if>
+        </where>
+        order by operate_time desc
+    </select>
+    
+    <select id="selectAirConditionerLogById" parameterType="Long" resultMap="AirConditionerLogResult">
+        <include refid="selectAirConditionerLogVo"/>
+        where id = #{id}
+    </select>
+    
+    <select id="selectAirConditionerLogByAirConditionerId" parameterType="Long" resultMap="AirConditionerLogResult">
+        <include refid="selectAirConditionerLogVo"/>
+        where air_conditioner_id = #{airConditionerId}
+        order by operate_time desc
+    </select>
+         
+    <insert id="insertAirConditionerLog" parameterType="AirConditionerLog" useGeneratedKeys="true" keyProperty="id">
+        insert into air_conditioner_log
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="airConditionerId != null">air_conditioner_id,</if>
+            <if test="airConditionerName != null">air_conditioner_name,</if>
+            <if test="operateType != null">operate_type,</if>
+            <if test="operateMode != null">operate_mode,</if>
+            <if test="operateTime != null">operate_time,</if>
+            <if test="operateResult != null">operate_result,</if>
+            <if test="operateMsg != null">operate_msg,</if>
+            <if test="createBy != null">create_by,</if>
+            <if test="createTime != null">create_time,</if>
+            <if test="updateBy != null">update_by,</if>
+            <if test="updateTime != null">update_time,</if>
+            <if test="remark != null">remark,</if>
+         </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="airConditionerId != null">#{airConditionerId},</if>
+            <if test="airConditionerName != null">#{airConditionerName},</if>
+            <if test="operateType != null">#{operateType},</if>
+            <if test="operateMode != null">#{operateMode},</if>
+            <if test="operateTime != null">#{operateTime},</if>
+            <if test="operateResult != null">#{operateResult},</if>
+            <if test="operateMsg != null">#{operateMsg},</if>
+            <if test="createBy != null">#{createBy},</if>
+            <if test="createTime != null">#{createTime},</if>
+            <if test="updateBy != null">#{updateBy},</if>
+            <if test="updateTime != null">#{updateTime},</if>
+            <if test="remark != null">#{remark},</if>
+         </trim>
+    </insert>
+
+    <delete id="deleteAirConditionerLogById" parameterType="Long">
+        delete from air_conditioner_log where id = #{id}
+    </delete>
+
+    <delete id="deleteAirConditionerLogByIds" parameterType="String">
+        delete from air_conditioner_log where id in
+        <foreach item="id" collection="array" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </delete>
+    
+    <delete id="deleteAirConditionerLogByAirConditionerId" parameterType="Long">
+        delete from air_conditioner_log where air_conditioner_id = #{airConditionerId}
+    </delete>
+    
+</mapper>
\ No newline at end of file
diff --git a/zhitan-system/src/main/resources/mapper/airconditioner/AirConditionerMapper.xml b/zhitan-system/src/main/resources/mapper/airconditioner/AirConditionerMapper.xml
new file mode 100644
index 0000000..d04211d
--- /dev/null
+++ b/zhitan-system/src/main/resources/mapper/airconditioner/AirConditionerMapper.xml
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.zhitan.airconditioner.mapper.AirConditionerMapper">
+    
+    <resultMap type="AirConditioner" id="AirConditionerResult">
+        <id     property="id"                column="id"                />
+        <result property="name"              column="name"              />
+        <result property="controllerId"       column="controller_id"       />
+        <result property="location"          column="location"          />
+        <result property="status"            column="status"            />
+        <result property="createBy"          column="create_by"          />
+        <result property="createTime"        column="create_time"        />
+        <result property="updateBy"          column="update_by"          />
+        <result property="updateTime"        column="update_time"        />
+        <result property="remark"            column="remark"            />
+    </resultMap>
+
+    <sql id="selectAirConditionerVo">
+        select id, name, controller_id, location, status, create_by, create_time, update_by, update_time, remark from air_conditioner
+    </sql>
+
+    <select id="selectAirConditionerList" parameterType="AirConditioner" resultMap="AirConditionerResult">
+        <include refid="selectAirConditionerVo"/>
+        <where>  
+            <if test="name != null  and name != ''"> and name like concat('%', #{name}, '%')</if>
+            <if test="controllerId != null  and controllerId != ''"> and controller_id = #{controllerId}</if>
+            <if test="location != null  and location != ''"> and location like concat('%', #{location}, '%')</if>
+            <if test="status != null  and status != ''"> and status = #{status}</if>
+        </where>
+    </select>
+    
+    <select id="selectAirConditionerById" parameterType="Long" resultMap="AirConditionerResult">
+        <include refid="selectAirConditionerVo"/>
+        where id = #{id}
+    </select>
+    
+    <select id="selectAirConditionerByControllerId" parameterType="String" resultMap="AirConditionerResult">
+        <include refid="selectAirConditionerVo"/>
+        where controller_id = #{controllerId}
+    </select>
+        
+    <insert id="insertAirConditioner" parameterType="AirConditioner" useGeneratedKeys="true" keyProperty="id">
+        insert into air_conditioner
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="name != null">name,</if>
+            <if test="controllerId != null">controller_id,</if>
+            <if test="location != null">location,</if>
+            <if test="status != null">status,</if>
+            <if test="createBy != null">create_by,</if>
+            <if test="createTime != null">create_time,</if>
+            <if test="updateBy != null">update_by,</if>
+            <if test="updateTime != null">update_time,</if>
+            <if test="remark != null">remark,</if>
+         </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="name != null">#{name},</if>
+            <if test="controllerId != null">#{controllerId},</if>
+            <if test="location != null">#{location},</if>
+            <if test="status != null">#{status},</if>
+            <if test="createBy != null">#{createBy},</if>
+            <if test="createTime != null">#{createTime},</if>
+            <if test="updateBy != null">#{updateBy},</if>
+            <if test="updateTime != null">#{updateTime},</if>
+            <if test="remark != null">#{remark},</if>
+         </trim>
+    </insert>
+
+    <update id="updateAirConditioner" parameterType="AirConditioner">
+        update air_conditioner
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="name != null">name = #{name},</if>
+            <if test="controllerId != null">controller_id = #{controllerId},</if>
+            <if test="location != null">location = #{location},</if>
+            <if test="status != null">status = #{status},</if>
+            <if test="updateBy != null">update_by = #{updateBy},</if>
+            <if test="updateTime != null">update_time = #{updateTime},</if>
+            <if test="remark != null">remark = #{remark},</if>
+        </trim>
+        where id = #{id}
+    </update>
+
+    <delete id="deleteAirConditionerById" parameterType="Long">
+        delete from air_conditioner where id = #{id}
+    </delete>
+
+    <delete id="deleteAirConditionerByIds" parameterType="String">
+        delete from air_conditioner where id in
+        <foreach item="id" collection="array" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </delete>
+    
+</mapper>
\ No newline at end of file
diff --git a/zhitan-system/src/main/resources/mapper/airconditioner/AirConditionerScheduleMapper.xml b/zhitan-system/src/main/resources/mapper/airconditioner/AirConditionerScheduleMapper.xml
new file mode 100644
index 0000000..9d746a5
--- /dev/null
+++ b/zhitan-system/src/main/resources/mapper/airconditioner/AirConditionerScheduleMapper.xml
@@ -0,0 +1,115 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.zhitan.airconditioner.mapper.AirConditionerScheduleMapper">
+    
+    <resultMap type="AirConditionerSchedule" id="AirConditionerScheduleResult">
+        <id     property="id"                column="id"                />
+        <result property="airConditionerId"  column="air_conditioner_id"  />
+        <result property="startTime"         column="start_time"         />
+        <result property="offTime"           column="off_time"           />
+        <result property="controlMode"       column="control_mode"       />
+        <result property="status"            column="status"            />
+        <result property="createBy"          column="create_by"          />
+        <result property="createTime"        column="create_time"        />
+        <result property="updateBy"          column="update_by"          />
+        <result property="updateTime"        column="update_time"        />
+        <result property="remark"            column="remark"            />
+    </resultMap>
+
+    <sql id="selectAirConditionerScheduleVo">
+        select id, air_conditioner_id, start_time, off_time, control_mode, status, create_by, create_time, update_by, update_time, remark from air_conditioner_schedule
+    </sql>
+
+    <select id="selectAirConditionerScheduleList" parameterType="AirConditionerSchedule" resultMap="AirConditionerScheduleResult">
+        <include refid="selectAirConditionerScheduleVo"/>
+        <where>  
+            <if test="airConditionerId != null "> and air_conditioner_id = #{airConditionerId}</if>
+            <if test="startTime != null  and startTime != ''"> and start_time = #{startTime}</if>
+            <if test="offTime != null  and offTime != ''"> and off_time = #{offTime}</if>
+            <if test="controlMode != null  and controlMode != ''"> and control_mode = #{controlMode}</if>
+            <if test="status != null  and status != ''"> and status = #{status}</if>
+        </where>
+    </select>
+    
+    <select id="selectAirConditionerScheduleById" parameterType="Long" resultMap="AirConditionerScheduleResult">
+        <include refid="selectAirConditionerScheduleVo"/>
+        where id = #{id}
+    </select>
+    
+    <select id="selectAirConditionerScheduleByAirConditionerId" parameterType="Long" resultMap="AirConditionerScheduleResult">
+        <include refid="selectAirConditionerScheduleVo"/>
+        where air_conditioner_id = #{airConditionerId}
+    </select>
+    
+    <select id="selectActiveSchedules" resultMap="AirConditionerScheduleResult">
+        <include refid="selectAirConditionerScheduleVo"/>
+        where status = '0' and start_time &lt;= #{currentTime} and off_time &gt;= #{currentTime}
+    </select>
+    
+    <select id="selectSchedulesByTimePoint" resultMap="AirConditionerScheduleResult">
+        <include refid="selectAirConditionerScheduleVo"/>
+        where status = '0' and 
+        (DATE_FORMAT(start_time, '%H:%i') = #{timePoint} or DATE_FORMAT(off_time, '%H:%i') = #{timePoint})
+    </select>
+        
+    <insert id="insertAirConditionerSchedule" parameterType="AirConditionerSchedule" useGeneratedKeys="true" keyProperty="id">
+        insert into air_conditioner_schedule
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="airConditionerId != null">air_conditioner_id,</if>
+            <if test="startTime != null">start_time,</if>
+            <if test="offTime != null">off_time,</if>
+            <if test="controlMode != null">control_mode,</if>
+            <if test="status != null">status,</if>
+            <if test="createBy != null">create_by,</if>
+            <if test="createTime != null">create_time,</if>
+            <if test="updateBy != null">update_by,</if>
+            <if test="updateTime != null">update_time,</if>
+            <if test="remark != null">remark,</if>
+         </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="airConditionerId != null">#{airConditionerId},</if>
+            <if test="startTime != null">#{startTime},</if>
+            <if test="offTime != null">#{offTime},</if>
+            <if test="controlMode != null">#{controlMode},</if>
+            <if test="status != null">#{status},</if>
+            <if test="createBy != null">#{createBy},</if>
+            <if test="createTime != null">#{createTime},</if>
+            <if test="updateBy != null">#{updateBy},</if>
+            <if test="updateTime != null">#{updateTime},</if>
+            <if test="remark != null">#{remark},</if>
+         </trim>
+    </insert>
+
+    <update id="updateAirConditionerSchedule" parameterType="AirConditionerSchedule">
+        update air_conditioner_schedule
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="airConditionerId != null">air_conditioner_id = #{airConditionerId},</if>
+            <if test="startTime != null">start_time = #{startTime},</if>
+            <if test="offTime != null">off_time = #{offTime},</if>
+            <if test="controlMode != null">control_mode = #{controlMode},</if>
+            <if test="status != null">status = #{status},</if>
+            <if test="updateBy != null">update_by = #{updateBy},</if>
+            <if test="updateTime != null">update_time = #{updateTime},</if>
+            <if test="remark != null">remark = #{remark},</if>
+        </trim>
+        where id = #{id}
+    </update>
+
+    <delete id="deleteAirConditionerScheduleById" parameterType="Long">
+        delete from air_conditioner_schedule where id = #{id}
+    </delete>
+
+    <delete id="deleteAirConditionerScheduleByIds" parameterType="String">
+        delete from air_conditioner_schedule where id in
+        <foreach item="id" collection="array" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </delete>
+    
+    <delete id="deleteAirConditionerScheduleByAirConditionerId" parameterType="Long">
+        delete from air_conditioner_schedule where air_conditioner_id = #{airConditionerId}
+    </delete>
+    
+</mapper>
\ No newline at end of file
diff --git a/zhitan-system/src/main/resources/mapper/system/SysHolidayMapper.xml b/zhitan-system/src/main/resources/mapper/system/SysHolidayMapper.xml
new file mode 100644
index 0000000..04a66a0
--- /dev/null
+++ b/zhitan-system/src/main/resources/mapper/system/SysHolidayMapper.xml
@@ -0,0 +1,149 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.zhitan.system.mapper.SysHolidayMapper">
+    
+    <resultMap type="com.zhitan.system.domain.SysHoliday" id="SysHolidayResult">
+        <id     property="holidayId"      column="holiday_id"      />
+        <result property="holidayName"    column="holiday_name"    />
+        <result property="holidayDate"    column="holiday_date"    />
+        <result property="holidayType"    column="holiday_type"    />
+        <result property="status"         column="status"          />
+        <result property="createBy"       column="create_by"       />
+        <result property="createTime"     column="create_time"     />
+        <result property="updateBy"       column="update_by"       />
+        <result property="updateTime"     column="update_time"     />
+        <result property="remark"         column="remark"          />
+    </resultMap>
+
+    <sql id="selectSysHolidayVo">
+        select holiday_id, holiday_name, holiday_date, holiday_type, status, create_by, create_time, update_by, update_time, remark
+        from sys_holiday
+    </sql>
+
+    <!-- 鏌ヨ鑺傚亣鏃ヤ俊鎭� -->
+    <select id="selectSysHolidayById" parameterType="Long" resultMap="SysHolidayResult">
+        <include refid="selectSysHolidayVo"/>
+        where holiday_id = #{holidayId}
+    </select>
+    
+    <!-- 鏍规嵁鏃ユ湡鏌ヨ鑺傚亣鏃ヤ俊鎭� -->
+    <select id="selectSysHolidayByDate" parameterType="Date" resultMap="SysHolidayResult">
+        <include refid="selectSysHolidayVo"/>
+        where holiday_date = #{date}
+        and status = '0'
+    </select>
+    
+    <!-- 鏌ヨ鑺傚亣鏃ヤ俊鎭垪琛� -->
+    <select id="selectSysHolidayList" parameterType="com.zhitan.system.domain.SysHoliday" resultMap="SysHolidayResult">
+        <include refid="selectSysHolidayVo"/>
+        <where>  
+            <if test="holidayName != null  and holidayName != ''">
+                AND holiday_name like concat('%', #{holidayName}, '%')
+            </if>
+            <if test="holidayDate != null ">
+                AND holiday_date = #{holidayDate}
+            </if>
+            <if test="holidayType != null  and holidayType != ''">
+                AND holiday_type = #{holidayType}
+            </if>
+            <if test="status != null  and status != ''">
+                AND status = #{status}
+            </if>
+        </where>
+    </select>
+    
+    <!-- 鏂板鑺傚亣鏃ヤ俊鎭� -->
+    <insert id="insertSysHoliday" parameterType="com.zhitan.system.domain.SysHoliday" useGeneratedKeys="true" keyProperty="holidayId">
+        insert into sys_holiday
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="holidayName != null and holidayName != ''">
+                holiday_name,
+            </if>
+            <if test="holidayDate != null">
+                holiday_date,
+            </if>
+            <if test="holidayType != null and holidayType != ''">
+                holiday_type,
+            </if>
+            <if test="status != null and status != ''">
+                status,
+            </if>
+            <if test="createBy != null and createBy != ''">
+                create_by,
+            </if>
+            <if test="createTime != null">
+                create_time,
+            </if>
+            <if test="remark != null and remark != ''">
+                remark,
+            </if>
+        </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="holidayName != null and holidayName != ''">
+                #{holidayName},
+            </if>
+            <if test="holidayDate != null">
+                #{holidayDate},
+            </if>
+            <if test="holidayType != null and holidayType != ''">
+                #{holidayType},
+            </if>
+            <if test="status != null and status != ''">
+                #{status},
+            </if>
+            <if test="createBy != null and createBy != ''">
+                #{createBy},
+            </if>
+            <if test="createTime != null">
+                #{createTime},
+            </if>
+            <if test="remark != null and remark != ''">
+                #{remark},
+            </if>
+        </trim>
+    </insert>
+
+    <!-- 淇敼鑺傚亣鏃ヤ俊鎭� -->
+    <update id="updateSysHoliday" parameterType="com.zhitan.system.domain.SysHoliday">
+        update sys_holiday
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="holidayName != null and holidayName != ''">
+                holiday_name = #{holidayName},
+            </if>
+            <if test="holidayDate != null">
+                holiday_date = #{holidayDate},
+            </if>
+            <if test="holidayType != null and holidayType != ''">
+                holiday_type = #{holidayType},
+            </if>
+            <if test="status != null and status != ''">
+                status = #{status},
+            </if>
+            <if test="updateBy != null and updateBy != ''">
+                update_by = #{updateBy},
+            </if>
+            <if test="updateTime != null">
+                update_time = #{updateTime},
+            </if>
+            <if test="remark != null">
+                remark = #{remark},
+            </if>
+        </trim>
+        where holiday_id = #{holidayId}
+    </update>
+
+    <!-- 鍒犻櫎鑺傚亣鏃ヤ俊鎭� -->
+    <delete id="deleteSysHolidayById" parameterType="Long">
+        delete from sys_holiday where holiday_id = #{holidayId}
+    </delete>
+
+    <!-- 鎵归噺鍒犻櫎鑺傚亣鏃ヤ俊鎭� -->
+    <delete id="deleteSysHolidayByIds" parameterType="String">
+        delete from sys_holiday where holiday_id in 
+        <foreach item="holidayId" collection="array" open="(" separator="," close=")">
+            #{holidayId}
+        </foreach>
+    </delete>
+</mapper>
\ No newline at end of file
diff --git a/zhitan-vue/src/api/system/holiday.js b/zhitan-vue/src/api/system/holiday.js
new file mode 100644
index 0000000..1dc33fd
--- /dev/null
+++ b/zhitan-vue/src/api/system/holiday.js
@@ -0,0 +1,53 @@
+import request from '@/utils/request'
+
+// 鏌ヨ鑺傚亣鏃ュ垪琛�
+export function listHoliday(query) {
+  return request({
+    url: '/system/holiday/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 鏌ヨ鑺傚亣鏃ヨ缁�
+export function getHoliday(holidayId) {
+  return request({
+    url: '/system/holiday/' + holidayId,
+    method: 'get'
+  })
+}
+
+// 鏂板鑺傚亣鏃�
+export function addHoliday(data) {
+  return request({
+    url: '/system/holiday',
+    method: 'post',
+    data: data
+  })
+}
+
+// 淇敼鑺傚亣鏃�
+export function updateHoliday(data) {
+  return request({
+    url: '/system/holiday',
+    method: 'put',
+    data: data
+  })
+}
+
+// 鍒犻櫎鑺傚亣鏃�
+export function delHoliday(holidayId) {
+  return request({
+    url: '/system/holiday/' + holidayId,
+    method: 'delete'
+  })
+}
+
+// 瀵煎嚭鑺傚亣鏃�
+export function exportHoliday(query) {
+  return request({
+    url: '/system/holiday/export',
+    method: 'get',
+    params: query
+  })
+}
\ No newline at end of file
diff --git a/zhitan-vue/src/views/system/holiday/index.vue b/zhitan-vue/src/views/system/holiday/index.vue
new file mode 100644
index 0000000..8383b0c
--- /dev/null
+++ b/zhitan-vue/src/views/system/holiday/index.vue
@@ -0,0 +1,331 @@
+<template>
+  <div class="app-container page">
+    <div class="form-card">
+      <el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="80px">
+        <el-form-item label="鑺傚亣鏃ュ悕绉�" prop="holidayName">
+          <el-input
+            v-model="queryParams.holidayName"
+            placeholder="璇疯緭鍏ヨ妭鍋囨棩鍚嶇О"
+            clearable
+            style="width: 240px"
+            @keyup.enter="handleQuery"
+          />
+        </el-form-item>
+        <el-form-item label="鑺傚亣鏃ユ棩鏈�" prop="holidayDate">
+          <el-date-picker
+            v-model="queryParams.holidayDate"
+            type="date"
+            placeholder="閫夋嫨鑺傚亣鏃ユ棩鏈�"
+            value-format="YYYY-MM-DD"
+            style="width: 240px"
+          />
+        </el-form-item>
+        <el-form-item label="鑺傚亣鏃ョ被鍨�" prop="holidayType">
+          <el-select v-model="queryParams.holidayType" placeholder="鑺傚亣鏃ョ被鍨�" clearable style="width: 240px">
+            <el-option
+              v-for="dict in sys_holiday_type"
+              :key="dict.value"
+              :label="dict.label"
+              :value="dict.value"
+            />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="鐘舵��" prop="status">
+          <el-select v-model="queryParams.status" placeholder="鑺傚亣鏃ョ姸鎬�" clearable style="width: 240px">
+            <el-option
+              v-for="dict in sys_normal_disable"
+              :key="dict.value"
+              :label="dict.label"
+              :value="dict.value"
+            />
+          </el-select>
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" icon="Search" @click="handleQuery">鎼滅储</el-button>
+          <el-button icon="Refresh" @click="resetQuery">閲嶇疆</el-button>
+        </el-form-item>
+      </el-form>
+    </div>
+
+    <div class="table-bg-style">
+      <div class="table-box" style="margin-top: 0">
+        <el-row :gutter="10" class="mb8" style="margin-top: 8px">
+          <el-col :span="1.5">
+            <el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['system:holiday:add']"
+              >鏂板</el-button
+            >
+          </el-col>
+          <el-col :span="1.5">
+            <el-button
+              type="success"
+              plain
+              icon="Edit"
+              :disabled="single"
+              @click="handleUpdate"
+              v-hasPermi="['system:holiday:edit']"
+              >淇敼</el-button
+            >
+          </el-col>
+          <el-col :span="1.5">
+            <el-button
+              type="danger"
+              plain
+              icon="Delete"
+              :disabled="multiple"
+              @click="handleDelete"
+              v-hasPermi="['system:holiday:remove']"
+              >鍒犻櫎</el-button
+            >
+          </el-col>
+          <el-col :span="1.5">
+            <el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['system:holiday:export']"
+              >瀵煎嚭</el-button
+            >
+          </el-col>
+          <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
+        </el-row>
+
+        <el-table v-loading="loading" :data="holidayList" @selection-change="handleSelectionChange">
+          <el-table-column type="selection" width="55" align="center" />
+          <el-table-column label="鑺傚亣鏃D" align="center" prop="holidayId" />
+          <el-table-column label="鑺傚亣鏃ュ悕绉�" align="center" prop="holidayName" :show-overflow-tooltip="true" />
+          <el-table-column label="鑺傚亣鏃ユ棩鏈�" align="center" prop="holidayDate" width="100" />
+          <el-table-column label="鑺傚亣鏃ョ被鍨�" align="center" prop="holidayType">
+            <template #default="scope">
+              <dict-tag :options="sys_holiday_type" :value="scope.row.holidayType" />
+            </template>
+          </el-table-column>
+          <el-table-column label="鐘舵��" align="center" prop="status">
+            <template #default="scope">
+              <dict-tag :options="sys_normal_disable" :value="scope.row.status" />
+            </template>
+          </el-table-column>
+          <el-table-column label="鍒涘缓鏃堕棿" align="center" prop="createTime" width="100">
+            <template #default="scope">
+              <span>{{ parseTime(scope.row.createTime) }}</span>
+            </template>
+          </el-table-column>
+          <el-table-column label="鎿嶄綔" align="center" class-name="small-padding fixed-width">
+            <template #default="scope">
+              <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['system:holiday:edit']">淇敼</el-button>
+              <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['system:holiday:remove']">鍒犻櫎</el-button>
+            </template>
+          </el-table-column>
+        </el-table>
+
+        <pagination
+          v-show="total > 0"
+          :total="total"
+          v-model:page="queryParams.pageNum"
+          v-model:limit="queryParams.pageSize"
+          @pagination="getList"
+        />
+      </div>
+    </div>
+
+    <!-- 娣诲姞鎴栦慨鏀硅妭鍋囨棩瀵硅瘽妗� -->
+    <el-dialog :title="title" v-model="open" width="500px" append-to-body>
+      <el-form ref="holidayRef" :model="form" :rules="rules" label-width="100px">
+        <el-form-item label="鑺傚亣鏃ュ悕绉�" prop="holidayName">
+          <el-input v-model="form.holidayName" placeholder="璇疯緭鍏ヨ妭鍋囨棩鍚嶇О" />
+        </el-form-item>
+        <el-form-item label="鑺傚亣鏃ユ棩鏈�" prop="holidayDate">
+          <el-date-picker
+            v-model="form.holidayDate"
+            type="date"
+            placeholder="閫夋嫨鑺傚亣鏃ユ棩鏈�"
+            value-format="YYYY-MM-DD"
+            style="width: 100%"
+          />
+        </el-form-item>
+        <el-form-item label="鑺傚亣鏃ョ被鍨�" prop="holidayType">
+          <el-select v-model="form.holidayType" placeholder="璇烽�夋嫨鑺傚亣鏃ョ被鍨�" style="width: 100%">
+            <el-option
+              v-for="dict in sys_holiday_type"
+              :key="dict.value"
+              :label="dict.label"
+              :value="dict.value"
+            />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="鐘舵��" prop="status">
+          <el-radio-group v-model="form.status">
+            <el-radio
+              v-for="dict in sys_normal_disable"
+              :key="dict.value"
+              :label="dict.value"
+            >{{ dict.label }}</el-radio>
+          </el-radio-group>
+        </el-form-item>
+        <el-form-item label="澶囨敞" prop="remark">
+          <el-input v-model="form.remark" type="textarea" placeholder="璇疯緭鍏ュ唴瀹�" />
+        </el-form-item>
+      </el-form>
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button type="primary" @click="submitForm">纭� 瀹�</el-button>
+          <el-button @click="cancel">鍙� 娑�</el-button>
+        </div>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+
+<script setup>
+import { listHoliday, getHoliday, delHoliday, addHoliday, updateHoliday, exportHoliday } from "@/api/system/holiday";
+
+const { proxy } = getCurrentInstance();
+const { sys_normal_disable } = proxy.useDict("sys_normal_disable");
+const sys_holiday_type = ref([]);
+
+// 鍒濆鍖栬妭鍋囨棩绫诲瀷瀛楀吀
+sys_holiday_type.value = [
+  { value: "0", label: "姝e父鍋囨棩" },
+  { value: "1", label: "宸ヤ綔鏃ヨ皟浼�" }
+];
+
+const holidayList = ref([]);
+const open = ref(false);
+const loading = ref(true);
+const showSearch = ref(true);
+const ids = ref([]);
+const single = ref(true);
+const multiple = ref(true);
+const total = ref(0);
+const title = ref("");
+
+const data = reactive({
+  form: {},
+  queryParams: {
+    pageNum: 1,
+    pageSize: 10,
+    holidayName: undefined,
+    holidayDate: undefined,
+    holidayType: undefined,
+    status: undefined
+  },
+  rules: {
+    holidayName: [
+      { required: true, message: "鑺傚亣鏃ュ悕绉颁笉鑳戒负绌�", trigger: "blur" }
+    ],
+    holidayDate: [
+      { required: true, message: "鑺傚亣鏃ユ棩鏈熶笉鑳戒负绌�", trigger: "blur" }
+    ],
+    holidayType: [
+      { required: true, message: "鑺傚亣鏃ョ被鍨嬩笉鑳戒负绌�", trigger: "change" }
+    ],
+    status: [
+      { required: true, message: "鐘舵�佷笉鑳戒负绌�", trigger: "change" }
+    ]
+  }
+});
+
+const { queryParams, form, rules } = toRefs(data);
+
+/** 鏌ヨ鑺傚亣鏃ュ垪琛� */
+function getList() {
+  loading.value = true;
+  listHoliday(queryParams.value).then(response => {
+    holidayList.value = response.rows;
+    total.value = response.total;
+    loading.value = false;
+  });
+}
+
+// 鍙栨秷鎸夐挳
+function cancel() {
+  open.value = false;
+  reset();
+}
+
+// 琛ㄥ崟閲嶇疆
+function reset() {
+  form.value = {
+    holidayId: undefined,
+    holidayName: undefined,
+    holidayDate: undefined,
+    holidayType: "0",
+    status: "0",
+    remark: undefined
+  };
+  proxy.resetForm("holidayRef");
+}
+
+/** 鎼滅储鎸夐挳鎿嶄綔 */
+function handleQuery() {
+  queryParams.value.pageNum = 1;
+  getList();
+}
+
+/** 閲嶇疆鎸夐挳鎿嶄綔 */
+function resetQuery() {
+  proxy.resetForm("queryRef");
+  handleQuery();
+}
+
+/** 澶氶�夋閫変腑鏁版嵁 */
+function handleSelectionChange(selection) {
+  ids.value = selection.map(item => item.holidayId);
+  single.value = selection.length != 1;
+  multiple.value = !selection.length;
+}
+
+/** 鏂板鎸夐挳鎿嶄綔 */
+function handleAdd() {
+  reset();
+  open.value = true;
+  title.value = "娣诲姞鑺傚亣鏃�";
+}
+
+/** 淇敼鎸夐挳鎿嶄綔 */
+function handleUpdate(row) {
+  reset();
+  const holidayId = row.holidayId || ids.value[0];
+  getHoliday(holidayId).then(response => {
+    form.value = response.data;
+    open.value = true;
+    title.value = "淇敼鑺傚亣鏃�";
+  });
+}
+
+/** 鎻愪氦鎸夐挳 */
+function submitForm() {
+  proxy.$refs["holidayRef"].validate(valid => {
+    if (valid) {
+      if (form.value.holidayId != undefined) {
+        updateHoliday(form.value).then(response => {
+          proxy.$modal.msgSuccess("淇敼鎴愬姛");
+          open.value = false;
+          getList();
+        });
+      } else {
+        addHoliday(form.value).then(response => {
+          proxy.$modal.msgSuccess("鏂板鎴愬姛");
+          open.value = false;
+          getList();
+        });
+      }
+    }
+  });
+}
+
+/** 鍒犻櫎鎸夐挳鎿嶄綔 */
+function handleDelete(row) {
+  const holidayIds = row.holidayId || ids.value;
+  proxy.$modal.confirm('鏄惁纭鍒犻櫎鑺傚亣鏃ョ紪鍙蜂负"' + holidayIds + '"鐨勬暟鎹」?').then(function() {
+    return delHoliday(holidayIds);
+  }).then(() => {
+    getList();
+    proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+  }).catch(() => {});
+}
+
+/** 瀵煎嚭鎸夐挳鎿嶄綔 */
+function handleExport() {
+  proxy.download("system/holiday/export", {
+    ...queryParams.value
+  }, `holiday_${new Date().getTime()}.xlsx`);
+}
+
+getList();
+</script>
\ No newline at end of file

--
Gitblit v1.9.3