增加日程提醒

This commit is contained in:
2026-08-28 16:58:17 +08:00
parent 9588ddbf31
commit d3bc1833f8
13 changed files with 2267 additions and 20 deletions
@@ -0,0 +1,273 @@
<template>
<el-drawer v-model="visible" :title="isEdit ? '编辑日程' : '新建日程'" size="460px">
<el-form ref="formRef" :model="form" :rules="rules" label-position="top">
<el-form-item label="日程标题" prop="title">
<el-input
v-model="form.title"
maxlength="80"
show-word-limit
placeholder="请输入日程标题"
/>
</el-form-item>
<el-form-item label="日程日期" prop="schedule_date">
<el-date-picker
v-model="form.schedule_date"
type="date"
value-format="YYYY-MM-DD"
placeholder="选择日期"
style="width: 100%"
/>
</el-form-item>
<el-form-item label="全天">
<el-switch
v-model="form.all_day"
active-text="全天"
inactive-text="按时段"
/>
</el-form-item>
<el-form-item v-if="!form.all_day" label="时间段">
<div class="time-range">
<el-time-select
v-model="form.start_time"
start="00:00"
step="00:15"
end="23:45"
placeholder="开始时间"
class="time-input"
/>
<span class="time-sep">至</span>
<el-time-select
v-model="form.end_time"
start="00:00"
step="00:15"
end="23:45"
placeholder="结束(可选)"
class="time-input"
/>
</div>
</el-form-item>
<el-form-item label="优先级">
<el-radio-group v-model="form.priority">
<el-radio-button :value="0">普通</el-radio-button>
<el-radio-button :value="1">重要</el-radio-button>
<el-radio-button :value="2">紧急</el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item label="标签颜色">
<div class="color-options">
<span
v-for="c in colorOptions"
:key="c"
class="color-dot"
:class="{ active: form.color === c }"
:style="{ background: c }"
@click="form.color = c"
/>
</div>
</el-form-item>
<el-form-item label="备注">
<el-input
v-model="form.content"
type="textarea"
:rows="4"
maxlength="2000"
show-word-limit
placeholder="补充说明(可选)"
/>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="visible = false">取消</el-button>
<el-button type="primary" :loading="saving" @click="handleSave"
>保存</el-button
>
</template>
</el-drawer>
</template>
<script setup>
import { computed, reactive, ref, watch } from "vue";
import { ElMessage } from "element-plus";
import { createSchedule, updateSchedule } from "@/api/oaSchedule";
const props = defineProps({
modelValue: {
type: Boolean,
default: false
},
// 编辑时传入的日程对象;null 表示新建
schedule: {
type: Object,
default: null
},
// 新建时预填的日期(YYYY-MM-DD)
defaultDate: {
type: String,
default: ""
}
});
const emit = defineEmits(["update:modelValue", "saved"]);
const visible = computed({
get: () => props.modelValue,
set: value => emit("update:modelValue", value)
});
const colorOptions = [
"#409EFF",
"#0AD18E",
"#F5A623",
"#F56C6C",
"#9B6DF3",
"#909399"
];
const formRef = ref(null);
const saving = ref(false);
const editingId = ref(0);
const form = reactive({
title: "",
schedule_date: "",
all_day: true,
start_time: "",
end_time: "",
priority: 0,
color: colorOptions[0],
content: ""
});
const rules = {
title: [{ required: true, message: "请输入日程标题", trigger: "blur" }],
schedule_date: [
{ required: true, message: "请选择日程日期", trigger: "change" }
]
};
const isEdit = computed(() => !!props.schedule);
// 打开抽屉时根据编辑对象/默认日期重建表单。
// 用 watch 替代 el-drawer 的 @open + destroy-on-close:
// open 事件早于抽屉内容挂载,时序不稳定会导致表单控件状态错乱、点击无效。
watch(
() => props.modelValue,
open => {
if (open) {
initForm();
}
}
);
function initForm() {
if (props.schedule) {
editingId.value = props.schedule.id;
form.title = props.schedule.title;
form.schedule_date = props.schedule.schedule_date;
form.all_day = props.schedule.all_day === 1;
form.start_time = props.schedule.start_time || "";
form.end_time = props.schedule.end_time || "";
form.priority = props.schedule.priority || 0;
form.color = props.schedule.color || colorOptions[0];
form.content = props.schedule.content || "";
} else {
editingId.value = 0;
form.title = "";
form.schedule_date = props.defaultDate || "";
form.all_day = true;
form.start_time = "";
form.end_time = "";
form.priority = 0;
form.color = colorOptions[0];
form.content = "";
}
}
async function handleSave() {
try {
await formRef.value.validate();
} catch {
return;
}
if (!form.all_day) {
if (!form.start_time) {
ElMessage.warning("请选择开始时间");
return;
}
if (form.end_time && form.end_time < form.start_time) {
ElMessage.warning("结束时间不能早于开始时间");
return;
}
}
saving.value = true;
try {
const payload = {
title: form.title.trim(),
content: form.content,
schedule_date: form.schedule_date,
start_time: form.all_day ? "" : form.start_time,
end_time: form.all_day ? "" : form.end_time || "",
all_day: form.all_day ? 1 : 0,
color: form.color,
priority: form.priority
};
const res =
isEdit.value
? await updateSchedule(editingId.value, payload)
: await createSchedule(payload);
if (res?.code === 200) {
ElMessage.success(isEdit.value ? "日程已更新" : "日程已创建");
emit("saved");
visible.value = false;
} else {
ElMessage.error(res?.msg || "保存失败");
}
} finally {
saving.value = false;
}
}
</script>
<style scoped>
.time-range {
display: flex;
align-items: center;
gap: 8px;
width: 100%;
}
.time-input {
flex: 1;
min-width: 0;
}
.time-sep {
color: #909399;
}
.color-options {
display: flex;
align-items: center;
gap: 12px;
}
.color-dot {
width: 22px;
height: 22px;
border-radius: 50%;
cursor: pointer;
border: 2px solid transparent;
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.15);
transition: transform 0.15s;
}
.color-dot:hover {
transform: scale(1.12);
}
.color-dot.active {
border-color: #fff;
outline: 2px solid #409eff;
}
</style>