Selaa lähdekoodia

优化和完善日程功能(日程调整为时间段,增加完成状态,日历列表可以直接操作完成/取消/删除操作...)

wlndy 1 vuosi sitten
vanhempi
commit
239b5b03ef

+ 28 - 0
Admin.NET/Admin.NET.Core/Entity/FinishStatusEnum.cs

@@ -0,0 +1,28 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+
+namespace Admin.NET.Core;
+/// <summary>
+/// 完成状态枚举
+/// </summary>
+[Description("完成状态枚举")]
+public enum FinishStatusEnum
+{
+    /// <summary>
+    /// 已完成
+    /// </summary>
+    [Description("已完成")]
+    Finish = 1,
+
+    /// <summary>
+    /// 未完成
+    /// </summary>
+    [Description("未完成")]
+    UnFinish = 0,
+}
+
+

+ 17 - 3
Admin.NET/Admin.NET.Core/Entity/SysSchedule.cs

@@ -20,15 +20,29 @@ public class SysSchedule : EntityTenant
     public long UserId { get; set; }
 
     /// <summary>
-    /// 日程时间
+    /// 日程日期
     /// </summary>
-    [SugarColumn(ColumnDescription = "日程时间")]
+    [SugarColumn(ColumnDescription = "日程日期")]
     public DateTime? ScheduleTime { get; set; }
-
+    /// <summary>
+    /// 开始时间
+    /// </summary>
+    [SugarColumn(ColumnDescription = "开始时间", Length = 10)]
+    public string? StarTime { get; set; }
+    /// <summary>
+    /// 结束时间
+    /// </summary>
+    [SugarColumn(ColumnDescription = "结束时间", Length = 10)]
+    public string? EndTime { get; set; }
     /// <summary>
     /// 日程内容
     /// </summary>
     [SugarColumn(ColumnDescription = "日程内容", Length = 256)]
     [Required, MaxLength(256)]
     public virtual string Content { get; set; }
+    /// <summary>
+    /// 完成状态
+    /// </summary>
+    [SugarColumn(ColumnDescription = "完成状态")]
+    public FinishStatusEnum Status { get; set; } =  FinishStatusEnum.UnFinish;
 }

+ 8 - 1
Admin.NET/Admin.NET.Core/Service/Schedule/Dto/ScheduleInput.cs

@@ -6,7 +6,14 @@
 
 namespace Admin.NET.Core.Service;
 
-public class ScheduleInput
+public class ScheduleInput : BaseIdInput
+{
+    /// <summary>
+    /// 状态
+    /// </summary>
+    public virtual FinishStatusEnum Status { get; set; }
+}
+public class ListScheduleInput
 {
     public DateTime? StartTime { get; set; }
 

+ 18 - 2
Admin.NET/Admin.NET.Core/Service/Schedule/SysScheduleService.cs

@@ -27,13 +27,13 @@ public class SysScheduleService : IDynamicApiController, ITransient
     /// </summary>
     /// <returns></returns>
     [DisplayName("获取日程列表")]
-    public async Task<List<SysSchedule>> Page(ScheduleInput input)
+    public async Task<List<SysSchedule>> Page(ListScheduleInput input)
     {
         return await _sysSchedule.AsQueryable()
             .Where(u => u.UserId == _userManager.UserId)
             .WhereIF(!string.IsNullOrWhiteSpace(input.StartTime.ToString()), u => u.ScheduleTime >= input.StartTime)
             .WhereIF(!string.IsNullOrWhiteSpace(input.EndTime.ToString()), u => u.ScheduleTime <= input.EndTime)
-            .OrderBy(u => u.CreateTime, OrderByType.Asc)
+            .OrderBy(u => u.StarTime, OrderByType.Asc)
             .ToListAsync();
     }
 
@@ -84,4 +84,20 @@ public class SysScheduleService : IDynamicApiController, ITransient
     {
         await _sysSchedule.DeleteAsync(u => u.Id == input.Id);
     }
+    /// <summary>
+    /// 设置日程状态
+    /// </summary>
+    /// <param name="input"></param>
+    /// <returns></returns>
+    [DisplayName("设置日程状态")]
+    public async Task<int> SetStatus(ScheduleInput input)
+    {
+        if (!Enum.IsDefined(typeof(FinishStatusEnum), input.Status))
+            throw Oops.Oh(ErrorCodeEnum.D3005);
+
+        return await _sysSchedule.AsUpdateable()
+            .SetColumns(u => u.Status == input.Status)
+            .Where(u => u.Id == input.Id)
+            .ExecuteCommandAsync();
+    }
 }

+ 93 - 8
Web/src/api-services/apis/sys-schedule-api.ts

@@ -18,9 +18,11 @@ import { Configuration } from '../configuration';
 // @ts-ignore
 import { BASE_PATH, COLLECTION_FORMATS, RequestArgs, BaseAPI, RequiredError } from '../base';
 import { AddScheduleInput } from '../models';
+import { AdminResultInt32 } from '../models';
 import { AdminResultListSysSchedule } from '../models';
 import { AdminResultSysSchedule } from '../models';
 import { DeleteScheduleInput } from '../models';
+import { ListScheduleInput } from '../models';
 import { ScheduleInput } from '../models';
 import { UpdateScheduleInput } from '../models';
 /**
@@ -177,11 +179,11 @@ export const SysScheduleApiAxiosParamCreator = function (configuration?: Configu
         /**
          * 
          * @summary 获取日程列表
-         * @param {ScheduleInput} [body] 
+         * @param {ListScheduleInput} [body] 
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        apiSysSchedulePagePost: async (body?: ScheduleInput, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
+        apiSysSchedulePagePost: async (body?: ListScheduleInput, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
             const localVarPath = `/api/sysSchedule/page`;
             // use dummy base URL string because the URL constructor only accepts absolute URLs.
             const localVarUrlObj = new URL(localVarPath, 'https://example.com');
@@ -222,6 +224,54 @@ export const SysScheduleApiAxiosParamCreator = function (configuration?: Configu
                 options: localVarRequestOptions,
             };
         },
+        /**
+         * 
+         * @summary 设置日程状态
+         * @param {ScheduleInput} [body] 
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        apiSysScheduleSetStatusPost: async (body?: ScheduleInput, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
+            const localVarPath = `/api/sysSchedule/setStatus`;
+            // use dummy base URL string because the URL constructor only accepts absolute URLs.
+            const localVarUrlObj = new URL(localVarPath, 'https://example.com');
+            let baseOptions;
+            if (configuration) {
+                baseOptions = configuration.baseOptions;
+            }
+            const localVarRequestOptions :AxiosRequestConfig = { method: 'POST', ...baseOptions, ...options};
+            const localVarHeaderParameter = {} as any;
+            const localVarQueryParameter = {} as any;
+
+            // authentication Bearer required
+            // http bearer authentication required
+            if (configuration && configuration.accessToken) {
+                const accessToken = typeof configuration.accessToken === 'function'
+                    ? await configuration.accessToken()
+                    : await configuration.accessToken;
+                localVarHeaderParameter["Authorization"] = "Bearer " + accessToken;
+            }
+
+            localVarHeaderParameter['Content-Type'] = 'application/json-patch+json';
+
+            const query = new URLSearchParams(localVarUrlObj.search);
+            for (const key in localVarQueryParameter) {
+                query.set(key, localVarQueryParameter[key]);
+            }
+            for (const key in options.params) {
+                query.set(key, options.params[key]);
+            }
+            localVarUrlObj.search = (new URLSearchParams(query)).toString();
+            let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
+            localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
+            const needsSerialization = (typeof body !== "string") || localVarRequestOptions.headers['Content-Type'] === 'application/json';
+            localVarRequestOptions.data =  needsSerialization ? JSON.stringify(body !== undefined ? body : {}) : (body || "");
+
+            return {
+                url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
+                options: localVarRequestOptions,
+            };
+        },
         /**
          * 
          * @summary 更新日程
@@ -324,17 +374,31 @@ export const SysScheduleApiFp = function(configuration?: Configuration) {
         /**
          * 
          * @summary 获取日程列表
-         * @param {ScheduleInput} [body] 
+         * @param {ListScheduleInput} [body] 
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        async apiSysSchedulePagePost(body?: ScheduleInput, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminResultListSysSchedule>>> {
+        async apiSysSchedulePagePost(body?: ListScheduleInput, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminResultListSysSchedule>>> {
             const localVarAxiosArgs = await SysScheduleApiAxiosParamCreator(configuration).apiSysSchedulePagePost(body, options);
             return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
                 const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
                 return axios.request(axiosRequestArgs);
             };
         },
+        /**
+         * 
+         * @summary 设置日程状态
+         * @param {ScheduleInput} [body] 
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        async apiSysScheduleSetStatusPost(body?: ScheduleInput, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminResultInt32>>> {
+            const localVarAxiosArgs = await SysScheduleApiAxiosParamCreator(configuration).apiSysScheduleSetStatusPost(body, options);
+            return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
+                const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
+                return axios.request(axiosRequestArgs);
+            };
+        },
         /**
          * 
          * @summary 更新日程
@@ -391,13 +455,23 @@ export const SysScheduleApiFactory = function (configuration?: Configuration, ba
         /**
          * 
          * @summary 获取日程列表
-         * @param {ScheduleInput} [body] 
+         * @param {ListScheduleInput} [body] 
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        async apiSysSchedulePagePost(body?: ScheduleInput, options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultListSysSchedule>> {
+        async apiSysSchedulePagePost(body?: ListScheduleInput, options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultListSysSchedule>> {
             return SysScheduleApiFp(configuration).apiSysSchedulePagePost(body, options).then((request) => request(axios, basePath));
         },
+        /**
+         * 
+         * @summary 设置日程状态
+         * @param {ScheduleInput} [body] 
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        async apiSysScheduleSetStatusPost(body?: ScheduleInput, options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultInt32>> {
+            return SysScheduleApiFp(configuration).apiSysScheduleSetStatusPost(body, options).then((request) => request(axios, basePath));
+        },
         /**
          * 
          * @summary 更新日程
@@ -454,14 +528,25 @@ export class SysScheduleApi extends BaseAPI {
     /**
      * 
      * @summary 获取日程列表
-     * @param {ScheduleInput} [body] 
+     * @param {ListScheduleInput} [body] 
      * @param {*} [options] Override http request option.
      * @throws {RequiredError}
      * @memberof SysScheduleApi
      */
-    public async apiSysSchedulePagePost(body?: ScheduleInput, options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultListSysSchedule>> {
+    public async apiSysSchedulePagePost(body?: ListScheduleInput, options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultListSysSchedule>> {
         return SysScheduleApiFp(this.configuration).apiSysSchedulePagePost(body, options).then((request) => request(this.axios, this.basePath));
     }
+    /**
+     * 
+     * @summary 设置日程状态
+     * @param {ScheduleInput} [body] 
+     * @param {*} [options] Override http request option.
+     * @throws {RequiredError}
+     * @memberof SysScheduleApi
+     */
+    public async apiSysScheduleSetStatusPost(body?: ScheduleInput, options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultInt32>> {
+        return SysScheduleApiFp(this.configuration).apiSysScheduleSetStatusPost(body, options).then((request) => request(this.axios, this.basePath));
+    }
     /**
      * 
      * @summary 更新日程

+ 24 - 1
Web/src/api-services/models/add-schedule-input.ts

@@ -12,6 +12,7 @@
  * Do not edit the class manually.
  */
 
+import { FinishStatusEnum } from './finish-status-enum';
  /**
  * 
  *
@@ -101,13 +102,35 @@ export interface AddScheduleInput {
     userId?: number;
 
     /**
-     * 日程时间
+     * 日程日期
      *
      * @type {Date}
      * @memberof AddScheduleInput
      */
     scheduleTime?: Date | null;
 
+    /**
+     * 开始时间
+     *
+     * @type {string}
+     * @memberof AddScheduleInput
+     */
+    starTime?: string | null;
+
+    /**
+     * 结束时间
+     *
+     * @type {string}
+     * @memberof AddScheduleInput
+     */
+    endTime?: string | null;
+
+    /**
+     * @type {FinishStatusEnum}
+     * @memberof AddScheduleInput
+     */
+    status?: FinishStatusEnum;
+
     /**
      * 日程内容
      *

+ 24 - 0
Web/src/api-services/models/finish-status-enum.ts

@@ -0,0 +1,24 @@
+/* tslint:disable */
+/* eslint-disable */
+/**
+ * Admin.NET 通用权限开发平台
+ * 让 .NET 开发更简单、更通用、更流行。整合最新技术,模块插件式开发,前后端分离,开箱即用。<br/><u><b><font color='FF0000'> 👮不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!</font></b></u>
+ *
+ * OpenAPI spec version: 1.0.0
+ * 
+ *
+ * NOTE: This class is auto generated by the swagger code generator program.
+ * https://github.com/swagger-api/swagger-codegen.git
+ * Do not edit the class manually.
+ */
+
+/**
+ * 完成状态枚举<br />&nbsp;未完成 UnFinish = 0<br />&nbsp;已完成 Finish = 1<br />
+ * @export
+ * @enum {string}
+ */
+export enum FinishStatusEnum {
+    NUMBER_0 = 0,
+    NUMBER_1 = 1
+}
+

+ 34 - 0
Web/src/api-services/models/list-schedule-input.ts

@@ -0,0 +1,34 @@
+/* tslint:disable */
+/* eslint-disable */
+/**
+ * Admin.NET 通用权限开发平台
+ * 让 .NET 开发更简单、更通用、更流行。整合最新技术,模块插件式开发,前后端分离,开箱即用。<br/><u><b><font color='FF0000'> 👮不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!</font></b></u>
+ *
+ * OpenAPI spec version: 1.0.0
+ * 
+ *
+ * NOTE: This class is auto generated by the swagger code generator program.
+ * https://github.com/swagger-api/swagger-codegen.git
+ * Do not edit the class manually.
+ */
+
+ /**
+ * 
+ *
+ * @export
+ * @interface ListScheduleInput
+ */
+export interface ListScheduleInput {
+
+    /**
+     * @type {Date}
+     * @memberof ListScheduleInput
+     */
+    startTime?: Date | null;
+
+    /**
+     * @type {Date}
+     * @memberof ListScheduleInput
+     */
+    endTime?: Date | null;
+}

+ 7 - 4
Web/src/api-services/models/schedule-input.ts

@@ -12,6 +12,7 @@
  * Do not edit the class manually.
  */
 
+import { FinishStatusEnum } from './finish-status-enum';
  /**
  * 
  *
@@ -21,14 +22,16 @@
 export interface ScheduleInput {
 
     /**
-     * @type {Date}
+     * 主键Id
+     *
+     * @type {number}
      * @memberof ScheduleInput
      */
-    startTime?: Date | null;
+    id: number;
 
     /**
-     * @type {Date}
+     * @type {FinishStatusEnum}
      * @memberof ScheduleInput
      */
-    endTime?: Date | null;
+    status?: FinishStatusEnum;
 }

+ 24 - 1
Web/src/api-services/models/sys-schedule.ts

@@ -12,6 +12,7 @@
  * Do not edit the class manually.
  */
 
+import { FinishStatusEnum } from './finish-status-enum';
  /**
  * 系统日程表
  *
@@ -101,13 +102,29 @@ export interface SysSchedule {
     userId?: number;
 
     /**
-     * 日程时间
+     * 日程日期
      *
      * @type {Date}
      * @memberof SysSchedule
      */
     scheduleTime?: Date | null;
 
+    /**
+     * 开始时间
+     *
+     * @type {string}
+     * @memberof SysSchedule
+     */
+    starTime?: string | null;
+
+    /**
+     * 结束时间
+     *
+     * @type {string}
+     * @memberof SysSchedule
+     */
+    endTime?: string | null;
+
     /**
      * 日程内容
      *
@@ -115,4 +132,10 @@ export interface SysSchedule {
      * @memberof SysSchedule
      */
     content: string;
+
+    /**
+     * @type {FinishStatusEnum}
+     * @memberof SysSchedule
+     */
+    status?: FinishStatusEnum;
 }

+ 24 - 1
Web/src/api-services/models/update-schedule-input.ts

@@ -12,6 +12,7 @@
  * Do not edit the class manually.
  */
 
+import { FinishStatusEnum } from './finish-status-enum';
  /**
  * 
  *
@@ -101,13 +102,35 @@ export interface UpdateScheduleInput {
     userId?: number;
 
     /**
-     * 日程时间
+     * 日程日期
      *
      * @type {Date}
      * @memberof UpdateScheduleInput
      */
     scheduleTime?: Date | null;
 
+    /**
+     * 开始时间
+     *
+     * @type {string}
+     * @memberof UpdateScheduleInput
+     */
+    starTime?: string | null;
+
+    /**
+     * 结束时间
+     *
+     * @type {string}
+     * @memberof UpdateScheduleInput
+     */
+    endTime?: string | null;
+
+    /**
+     * @type {FinishStatusEnum}
+     * @memberof UpdateScheduleInput
+     */
+    status?: FinishStatusEnum;
+
     /**
      * 日程内容
      *

+ 289 - 192
Web/src/views/home/widgets/components/schedule.vue

@@ -23,16 +23,22 @@
 			</el-calendar>
 		</div>
 		<div class="schedule-list">
-			<div class="item" v-for="(item, index) in state.TodayScheduleData" :key="index" @click="openEditSchedule(item)">
-				<el-icon style="display: inline; vertical-align: middle"> <ele-Calendar /> </el-icon>
-				<span class="content" style="padding-left: 10px">
+			<div class="item" v-for="(item, index) in state.TodayScheduleData" :key="index">
+				<el-icon v-if="item.status==1" class="icon" @click="changeStatus(item)"> <ele-CircleCheck /> </el-icon>
+				<el-icon v-else class=" icon" @click="changeStatus(item)"> <ele-Edit /> </el-icon>
+
+				<span class="content" style="padding-left: 10px" @click="openEditSchedule(item)">
 					<span>
-						{{ item.scheduleTime }}
+						{{ item.starTime }} - {{ item.endTime }}
 					</span>
-					<span style="padding-left: 15px; font-weight: 600; color: var(--el-color-primary)">
+					<span :class="item.status==1?'finish':'no'" style="padding-left: 15px; font-weight: 600; color: var(--el-color-primary)">
 						{{ item.content }}
 					</span>
 				</span>
+				<span style="float: right;">
+					<el-icon class="icon" @click="delItem(item)"> <ele-CircleClose /> </el-icon>
+				</span>
+
 			</div>
 		</div>
 
@@ -41,206 +47,297 @@
 </template>
 
 <script lang="ts">
-export default {
-	title: '日程',
-	icon: 'ele-Odometer',
-	description: '日程演示',
-};
+	export default {
+		title: '日程',
+		icon: 'ele-Odometer',
+		description: '日程演示',
+	};
 </script>
 
 <script setup lang="ts">
-import { reactive, onMounted, ref } from 'vue';
-import { dayjs } from 'element-plus';
-import calendar from '/@/utils/calendar.js';
-
-import EditSchedule from '/@/views/home/widgets/components/scheduleEdit.vue';
-
-import { getAPI } from '/@/utils/axios-utils';
-import { SysScheduleApi } from '/@/api-services/api';
-import { SysSchedule } from '/@/api-services/models';
-
-const editScheduleRef = ref<InstanceType<typeof EditSchedule>>();
-const state = reactive({
-	ScheduleData: [] as Array<SysSchedule>, // 日程列表数据
-	TodayScheduleData: [] as Array<SysSchedule>, // 当天列表数据
-	calendarValue: new Date(),
-	queryParams: {
-		startTime: new Date(),
-		endTime: new Date(),
-	},
-	editTitle: '',
-});
-
-// 页面初始化
-onMounted(async () => {
-	await handleQuery();
-});
-
-// 查询操作
-const handleQuery = async () => {
-	state.queryParams.startTime = GetMonthFirstDay(state.calendarValue);
-	state.queryParams.endTime = GetMonthLastDay(state.calendarValue);
-
-	let params = Object.assign(state.queryParams);
-	var res = await getAPI(SysScheduleApi).apiSysSchedulePagePost(params);
-	state.ScheduleData = res.data.result ?? [];
-	if (state.ScheduleData.length > 0) {
-		state.TodayScheduleData = state.ScheduleData.filter((item) => {
-			return FormatDate(item.scheduleTime) == FormatDate(state.calendarValue);
-		});
-	}
-};
-
-// 农历转换
-const solarDate2lunar = (solarDate: any) => {
-	var solar = solarDate.split('-');
-	var lunar = calendar.solar2lunar(solar[0], solar[1], solar[2]);
-	// return solar[1] + '-' + solar[2] + '\n' + lunar.IMonthCn + lunar.IDayCn;
-	return lunar.IMonthCn + lunar.IDayCn;
-};
-
-// 按天查询
-const handleQueryByDate = async (date: any) => {
-	state.queryParams.startTime = FormatDateDelHMS(date);
-	state.queryParams.endTime = FormatDateEndHMS(date);
-	let params = Object.assign(state.queryParams);
-	var res = await getAPI(SysScheduleApi).apiSysSchedulePagePost(params);
-	state.TodayScheduleData = res.data.result ?? [];
-};
-
-// 打开新增页面
-const openAddSchedule = () => {
-	state.editTitle = '添加日程';
-	editScheduleRef.value?.openDialog({ id: undefined, status: 1, orderNo: 100 });
-};
-
-// 打开编辑页面
-const openEditSchedule = async (row: any) => {
-	state.editTitle = '编辑日程';
-	editScheduleRef.value?.openDialog(row, true);
-};
-
-// 点击日历中的日期
-async function handleClickDate(data: any) {
-	await handleQueryByDate(data.day);
-}
-
-function GetMonthFirstDay(date: any) {
-	var newDate = new Date(date);
-	newDate.setDate(1);
-	newDate.setHours(0);
-	newDate.setMinutes(0);
-	newDate.setSeconds(0);
-	return newDate;
-}
-
-function GetMonthLastDay(date: any) {
-	var newDate = new Date(date);
-	newDate.setMonth(newDate.getMonth() + 1);
-	newDate.setDate(0);
-	newDate.setHours(0);
-	newDate.setMinutes(0);
-	newDate.setSeconds(0);
-	return newDate;
-}
-
-// 去掉时分秒的日期
-function FormatDateDelHMS(date: any) {
-	var newDate = new Date(date);
-	newDate.setHours(0);
-	newDate.setMinutes(0);
-	newDate.setSeconds(0);
-	return newDate;
-}
-
-function FormatDateEndHMS(date: any) {
-	var newDate = new Date(date);
-	newDate.setHours(23);
-	newDate.setMinutes(59);
-	newDate.setSeconds(59);
-	return newDate;
-}
-
-// 格式化日期
-function FormatDate(date: any) {
-	return dayjs(date).format('YYYY-MM-DD');
-}
-</script>
+	import { reactive, onMounted, ref } from 'vue';
+	import { dayjs, ElMessage, ElMessageBox } from 'element-plus';
+	import calendar from '/@/utils/calendar.js';
 
-<style lang="scss" scoped>
-.custome-canlendar {
-	position: relative;
-	text-align: center;
-
-	:deep(.el-calendar) {
-		.el-calendar-table .el-calendar-day {
-			width: 100%;
-			height: 100%;
-		}
+	import EditSchedule from '/@/views/home/widgets/components/scheduleEdit.vue';
 
-		.el-calendar__body {
-			padding: 5px 0;
-		}
+	import { getAPI } from '/@/utils/axios-utils';
+	import { SysScheduleApi } from '/@/api-services/api';
+	import { SysSchedule } from '/@/api-services/models';
+	import { stringify } from 'querystring';
 
-		.el-calendar-table .el-calendar-day {
-			position: relative;
-		}
+	const editScheduleRef = ref<InstanceType<typeof EditSchedule>>();
+	const state = reactive({
+		ScheduleData: [] as Array<SysSchedule>, // 日程列表数据
+		TodayScheduleData: [] as Array<SysSchedule>, // 当天列表数据
+		calendarValue: new Date(),
+		queryParams: {
+			startTime: new Date(),
+			endTime: new Date(),
+		},
+		editTitle: '',
+	});
 
-		td .spandate {
-			margin: auto;
-			width: 26px;
-			height: 26px;
-			line-height: 26px;
-			border-radius: 50%;
-		}
-		td.is-selected .spandate {
-			width: 26px;
-			height: 26px;
-			line-height: 26px;
-			border-radius: 50%;
-			color: #fff;
-			background-color: var(--el-color-primary);
+	// 页面初始化
+	onMounted(async () => {
+		await handleQuery();
+	});
+
+	// 查询操作
+	const handleQuery = async () => {
+		// debugger;
+		state.queryParams.startTime = GetMonthFirstDay(state.calendarValue);
+		state.queryParams.endTime = GetMonthLastDay(state.calendarValue);
+
+		let params = Object.assign(state.queryParams);
+		var res = await getAPI(SysScheduleApi).apiSysSchedulePagePost(params);
+		state.ScheduleData = res.data.result ?? [];
+		if (state.ScheduleData.length > 0) {
+			state.TodayScheduleData = state.ScheduleData.filter((item) => {
+				return FormatDate(item.scheduleTime) == FormatDate(state.calendarValue);
+			});
 		}
-		/*小红点样式*/
-		.el-badge {
-			position: absolute;
-			left: 0;
-			bottom: -8px;
-			width: 100%;
+	};
+	// 删除
+	const delItem = (row: any) => {
+		ElMessageBox.confirm(`确定删日程:【${row.startTime}-${row.endTime}(${row.content})})】?`, '提示', {
+			confirmButtonText: '确定',
+			cancelButtonText: '取消',
+			type: 'warning',
+		})
+			.then(async () => {
+				await getAPI(SysScheduleApi).apiSysScheduleDeletePost(row);
+				await handleQuery();
+				ElMessage.success('删除成功');
+			})
+			.catch(() => {});
+	};
+	// 修改状态
+	const changeStatus = async (row: any) => {
+		await getAPI(SysScheduleApi)
+			.apiSysScheduleSetStatusPost({ id: row.id, status: row.status == 1 ? 0 : 1 })
+			.then(() => {
+				row.status = row.status == 1 ? 0 : 1;
+				ElMessage.success('日程状态设置成功');
+			})
+			.catch(() => {
+				ElMessage.success('日程状态设置异常');
+			});
+	};
+	// 农历转换
+	const solarDate2lunar = (solarDate: any) => {
+		var solar = solarDate.split('-');
+		var lunar = calendar.solar2lunar(solar[0], solar[1], solar[2]);
+		// return solar[1] + '-' + solar[2] + '\n' + lunar.IMonthCn + lunar.IDayCn;
+		return lunar.IMonthCn + lunar.IDayCn;
+	};
+
+	// 按天查询
+	const handleQueryByDate = async (date: any) => {
+		state.queryParams.startTime = FormatDateDelHMS(date);
+		state.queryParams.endTime = FormatDateEndHMS(date);
+		let params = Object.assign(state.queryParams);
+		var res = await getAPI(SysScheduleApi).apiSysSchedulePagePost(params);
+		state.TodayScheduleData = res.data.result ?? [];
+	};
+
+	// 打开新增页面
+	const openAddSchedule = () => {
+		var timerange = GetRecentTime();
+
+		state.editTitle = '添加日程';
+		editScheduleRef.value?.openDialog({ id: undefined, status: 0, orderNo: 100, starTime: timerange.starTime, endTime: timerange.endTime });
+	};
+
+	// 打开编辑页面
+	const openEditSchedule = async (row: any) => {
+		if (row.status == 1) return;
+		state.editTitle = '编辑日程';
+		editScheduleRef.value?.openDialog(row, true);
+	};
+
+	// 点击日历中的日期
+	const handleClickDate = async (data: any) => {
+		await handleQueryByDate(data.day);
+	};
+	// 获取当月第一天
+	const GetMonthFirstDay = (date: any) => {
+		var newDate = new Date(date);
+		newDate.setDate(1);
+		newDate.setHours(0);
+		newDate.setMinutes(0);
+		newDate.setSeconds(0);
+		return newDate;
+	};
+	// 获取当月最后一天
+	const GetMonthLastDay = (date: any) => {
+		var newDate = new Date(date);
+		newDate.setMonth(newDate.getMonth() + 1);
+		newDate.setDate(0);
+		newDate.setHours(0);
+		newDate.setMinutes(0);
+		newDate.setSeconds(0);
+		return newDate;
+	};
+
+	// 去掉时分秒的日期
+	const FormatDateDelHMS = (date: any) => {
+		var newDate = new Date(date);
+		newDate.setHours(0);
+		newDate.setMinutes(0);
+		newDate.setSeconds(0);
+		return newDate;
+	};
+
+	const FormatDateEndHMS = (date: any) => {
+		var newDate = new Date(date);
+		newDate.setHours(23);
+		newDate.setMinutes(59);
+		newDate.setSeconds(59);
+		return newDate;
+	};
+
+	// 格式化日期
+	const FormatDate = (date: any) => {
+		return dayjs(date).format('YYYY-MM-DD');
+	};
+	//获取最近的初始时间  EndTime默认为StarTime + 1(hour)
+	const GetRecentTime = () => {
+		var date = new Date();
+		//计算最近的开始时间
+		var currentHour = date.getHours();
+		var currentMin = date.getMinutes();
+
+		var starHour = dayjs(date).format('HH');
+		var endHour = dayjs(date).format('HH');
+		var starMin = '00';
+		var endMin = '00';
+		//如果当前时间已经23 那么starHour和endHour都是23
+		if (currentHour == 23) {
+			starHour = '23';
+			endHour = '23';
+			starMin = '00';
+			endMin = '45';
+		} else {
+			//判断分钟数属于那个层级
+			if (currentMin < 15) {
+				starMin = '15';
+				endMin = '15';
+				//计算结束时间
+				date.setHours(date.getHours() + 1);
+				endHour = dayjs(date).format('HH');
+			} else if (currentMin >= 15 && currentMin < 30) {
+				starMin = '30';
+				endMin = '30';
+
+				//计算结束时间
+				date.setHours(date.getHours() + 1);
+				endHour = dayjs(date).format('HH');
+			} else if (currentMin >= 30 && currentMin < 45) {
+				starMin = '45';
+				endMin = '45';
+				//计算结束时间
+				date.setHours(date.getHours() + 1);
+				endHour = dayjs(date).format('HH');
+			} else if (currentMin >= 45) {
+				//分钟 : 00
+				starMin = '00';
+				endMin = '00';
+
+				//开始时间+1
+				date.setHours(date.getHours() + 1);
+				starHour = dayjs(date).format('HH');
+				//计算结束时间
+				date.setHours(date.getHours() + 1);
+				endHour = dayjs(date).format('HH');
+			}
 		}
-	}
-}
+		return { starTime: starHour + ':' + starMin, endTime: endHour + ':' + endMin };
+	};
+</script>
 
-// 日程列表
-.schedule-list {
-	overflow-y: auto;
-	height: 150px;
-	.item {
+<style lang="scss" scoped>
+	.custome-canlendar {
 		position: relative;
-		margin-bottom: 5px;
-		padding: 0 11px;
-		line-height: 24px;
-		background-color: #f1f1f1;
-		cursor: pointer;
-
-		&::before {
-			position: absolute;
-			left: 0;
-			top: 0;
-			height: 100%;
-			content: '';
-			width: 3px;
-			background: var(--el-color-primary);
-		}
+		text-align: center;
+
+		:deep(.el-calendar) {
+			.el-calendar-table .el-calendar-day {
+				width: 100%;
+				height: 100%;
+			}
+
+			.el-calendar__body {
+				padding: 5px 0;
+			}
 
-		.date {
-			margin-right: 5px;
-			font-size: 14px;
+			.el-calendar-table .el-calendar-day {
+				position: relative;
+			}
+
+			td .spandate {
+				margin: auto;
+				width: 26px;
+				height: 26px;
+				line-height: 26px;
+				border-radius: 50%;
+			}
+			td.is-selected .spandate {
+				width: 26px;
+				height: 26px;
+				line-height: 26px;
+				border-radius: 50%;
+				color: #fff;
+				background-color: var(--el-color-primary);
+			}
+			/*小红点样式*/
+			.el-badge {
+				position: absolute;
+				left: 0;
+				bottom: -8px;
+				width: 100%;
+			}
 		}
-		.content {
-			color: #666;
-			font-size: 14px;
+	}
+
+	// 日程列表
+	.schedule-list {
+		overflow-y: auto;
+		height: 150px;
+		.item {
+			position: relative;
+			margin-bottom: 5px;
+			padding: 0 11px;
+			line-height: 24px;
+			background-color: #f1f1f1;
+			cursor: pointer;
+
+			&::before {
+				position: absolute;
+				left: 0;
+				top: 0;
+				height: 100%;
+				content: '';
+				width: 3px;
+				background: var(--el-color-primary);
+			}
+
+			.date {
+				margin-right: 5px;
+				font-size: 14px;
+			}
+			.content {
+				color: #666;
+				font-size: 14px;
+			}
+			.icon {
+				display: inline;
+				vertical-align: middle;
+				color: var(--el-color-primary);
+			}
+			.finish {
+				text-decoration: 3px solid line-through gray !important;
+			}
 		}
 	}
-}
 </style>

+ 111 - 64
Web/src/views/home/widgets/components/scheduleEdit.vue

@@ -9,9 +9,20 @@
 			</template>
 			<el-form :model="state.ruleForm" ref="ruleFormRef" label-width="auto">
 				<el-row :gutter="35">
-					<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
+					<el-col :xs="8" :sm="8" :md="8" :lg="8" :xl="8" class="mb20 time-padding-right">
 						<el-form-item label="日程时间" prop="scheduleTime" :rules="[{ required: true, message: '日程时间不能为空', trigger: 'blur' }]">
-							<el-date-picker v-model="state.ruleForm.scheduleTime" type="datetime" placeholder="请选择日程时间" format="YYYY-MM-DD HH:mm:ss" value-format="YYYY-MM-DD HH:mm:ss" class="w100" />
+							<el-date-picker v-model="state.ruleForm.scheduleTime" type="datetime" placeholder="请选择日程日期" format="YYYY-MM-DD" value-format="YYYY-MM-DD HH:mm:ss" class="w100" />
+						</el-form-item>
+					</el-col>
+					<el-col :xs="5" :sm="5" :md="5" :lg="5" :xl="5" class="mb20 time-padding">
+						<el-form-item prop="starTime" :rules="[{ required: true, message: '开始时间不能为空', trigger: 'blur' }]">
+							<el-time-select v-model="state.ruleForm.starTime" format="HH:mm" start="00:00" end="23:45" step="00:15" class="w100" clearable @change="ChangeEndTime()" />
+						</el-form-item>
+					</el-col>
+					<span>至</span>
+					<el-col :xs="5" :sm="5" :md="5" :lg="5" :xl="5" class="mb20 time-padding">
+						<el-form-item prop="endTime" :rules="[{ required: true, message: '结束时间不能为空', trigger: 'blur' }]">
+							<el-time-select v-model="state.ruleForm.endTime" :min-time="state.ruleForm.starTime" format="HH:mm" start="00:00" end="23:45" step="00:15" class="w100" clearable />
 						</el-form-item>
 					</el-col>
 					<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
@@ -33,77 +44,113 @@
 </template>
 
 <script lang="ts" setup name="editSchedule">
-import { onMounted, reactive, ref } from 'vue';
-import { dayjs, ElMessageBox, ElMessage, ElNotification } from 'element-plus';
+	import { onMounted, reactive, ref } from 'vue';
+	import { dayjs, ElMessageBox, ElMessage } from 'element-plus';
 
-import { getAPI } from '/@/utils/axios-utils';
-import { SysScheduleApi } from '/@/api-services/api';
-import { SysSchedule, UpdateScheduleInput } from '/@/api-services/models';
+	import { getAPI } from '/@/utils/axios-utils';
+	import { SysScheduleApi } from '/@/api-services/api';
+	import { SysSchedule, UpdateScheduleInput } from '/@/api-services/models';
 
-const props = defineProps({
-	title: String,
-	userScheduleData: Array<SysSchedule>,
-});
-const emits = defineEmits(['handleQuery']);
-const ruleFormRef = ref();
-const state = reactive({
-	isShowDialog: false,
-	showRemove: false,
-	ruleForm: {} as any,
-});
+	const props = defineProps({
+		title: String,
+		userScheduleData: Array<SysSchedule>,
+	});
+	const emits = defineEmits(['handleQuery']);
+	const ruleFormRef = ref();
+	const state = reactive({
+		isShowDialog: false,
+		showRemove: false,
+		ruleForm: {} as any,
+	});
 
-// 页面初始化
-onMounted(async () => {});
+	// 页面初始化
+	onMounted(async () => {});
 
-// 打开弹窗
-const openDialog = (row: any, showRemove: boolean = false) => {
-	ruleFormRef.value?.resetFields();
-	state.showRemove = showRemove;
+	// 打开弹窗
+	const openDialog = (row: any, showRemove: boolean = false) => {
+		ruleFormRef.value?.resetFields();
+		state.showRemove = showRemove;
 
-	state.ruleForm = JSON.parse(JSON.stringify(row));
-	state.ruleForm.scheduleTime = dayjs(state.ruleForm.scheduleTime ?? new Date()).format('YYYY-MM-DD HH:mm:ss');
-	state.isShowDialog = true;
-};
+		state.ruleForm = JSON.parse(JSON.stringify(row));
+		state.ruleForm.scheduleTime = dayjs(state.ruleForm.scheduleTime ?? new Date()).format('YYYY-MM-DD HH:mm:ss');
+		state.isShowDialog = true;
+	};
 
-// 关闭弹窗
-const closeDialog = () => {
-	emits('handleQuery', true);
-	state.isShowDialog = false;
-};
+	// 关闭弹窗
+	const closeDialog = () => {
+		emits('handleQuery', true);
+		state.isShowDialog = false;
+	};
 
-// 取消
-const cancel = () => {
-	state.isShowDialog = false;
-};
+	// 取消
+	const cancel = () => {
+		state.isShowDialog = false;
+	};
 
-// 提交
-const submit = () => {
-	ruleFormRef.value.validate(async (valid: boolean) => {
-		if (!valid) return;
-		if (state.ruleForm.id != undefined && state.ruleForm.id > 0) {
-			await getAPI(SysScheduleApi).apiSysScheduleUpdatePost(state.ruleForm);
-		} else {
-			await getAPI(SysScheduleApi).apiSysScheduleAddPost(state.ruleForm);
-		}
-		closeDialog();
-	});
-};
-
-// 删除
-const remove = () => {
-	ElMessageBox.confirm(`确定删除吗?`, '提示', {
-		confirmButtonText: '确定',
-		cancelButtonText: '取消',
-		type: 'warning',
-	})
-		.then(async () => {
-			await getAPI(SysScheduleApi).apiSysScheduleDeletePost(state.ruleForm);
+	// 提交
+	const submit = () => {
+		ruleFormRef.value.validate(async (valid: boolean) => {
+			if (!valid) return;
+			if (state.ruleForm.id != undefined && state.ruleForm.id > 0) {
+				await getAPI(SysScheduleApi).apiSysScheduleUpdatePost(state.ruleForm);
+			} else {
+				await getAPI(SysScheduleApi).apiSysScheduleAddPost(state.ruleForm);
+			}
 			closeDialog();
-			ElMessage.success('操作成功');
+		});
+	};
+
+	// 删除
+	const remove = () => {
+		ElMessageBox.confirm(`确定删除吗?`, '提示', {
+			confirmButtonText: '确定',
+			cancelButtonText: '取消',
+			type: 'warning',
 		})
-		.catch(() => {});
-};
+			.then(async () => {
+				await getAPI(SysScheduleApi).apiSysScheduleDeletePost(state.ruleForm);
+				closeDialog();
+				ElMessage.success('操作成功');
+			})
+			.catch(() => {});
+	};
+	//开始时间改变
+	const ChangeEndTime = () => {
+		//转成日期
+		var timeStr = state.ruleForm.starTime;
+		var parts = timeStr.split(':');
+		var hours = parseInt(parts[0], 10);
+		var minutes = parseInt(parts[1], 10);
+
+		var starTime = new Date();
+		starTime.setHours(hours);
+		starTime.setMinutes(minutes);
 
-// 导出对象
-defineExpose({ openDialog });
+		if (starTime.getHours() < 23) {
+			starTime.setHours(starTime.getHours() + 1);
+			state.ruleForm.endTime = dayjs(starTime).format('HH:mm');
+		} else {
+			state.ruleForm.endTime = '23:45';
+		}
+	};
+	// 导出对象
+	defineExpose({ openDialog });
 </script>
+
+<style lang="scss" scoped>
+	.editSchedule-container {
+		.no-pre-icon {
+			color: red;
+		}
+	}
+	:v-deep(.el-select__prefix) {
+		display: none !important;
+	}
+	.time-padding-right {
+		padding-right: 1px !important;
+	}
+	.time-padding {
+		padding-left: 10px !important;
+		padding-right: 10px !important;
+	}
+</style>