|
|
|
|
@ -17,11 +17,60 @@
|
|
|
|
|
<div class="oc-info-row"><b>关系:</b>{{ (oc.relation && oc.relation.length) ? oc.relation.join('、') : '无' }}</div>
|
|
|
|
|
<el-divider>日程表</el-divider>
|
|
|
|
|
<div class="oc-info-row schedule-area">
|
|
|
|
|
<div v-if="oc.schedule && oc.schedule.length">
|
|
|
|
|
<div v-for="(item, idx) in oc.schedule" :key="idx">{{ item }}</div>
|
|
|
|
|
</div>
|
|
|
|
|
<el-table
|
|
|
|
|
v-if="scheduleList.length"
|
|
|
|
|
:data="scheduleList"
|
|
|
|
|
border
|
|
|
|
|
size="small"
|
|
|
|
|
class="oc-schedule-table"
|
|
|
|
|
:row-class-name="scheduleRowClass"
|
|
|
|
|
>
|
|
|
|
|
<el-table-column prop="date" label="日期" width="110">
|
|
|
|
|
<template #default="scope">
|
|
|
|
|
<span>{{ formatDate(scope.row.date) }}</span>
|
|
|
|
|
</template>
|
|
|
|
|
</el-table-column>
|
|
|
|
|
<el-table-column prop="time" label="时间" width="80">
|
|
|
|
|
<template #default="scope">
|
|
|
|
|
<span>{{ formatTime(scope.row.time) }}</span>
|
|
|
|
|
</template>
|
|
|
|
|
</el-table-column>
|
|
|
|
|
<el-table-column prop="event" label="活动安排">
|
|
|
|
|
<template #default="scope">
|
|
|
|
|
<span class="event-content">{{ scope.row.event }}</span>
|
|
|
|
|
</template>
|
|
|
|
|
</el-table-column>
|
|
|
|
|
<el-table-column label="操作" width="90">
|
|
|
|
|
<template #default="scope">
|
|
|
|
|
<el-button size="small" type="text" @click="editSchedule(scope.$index)">编辑</el-button>
|
|
|
|
|
<el-button size="small" type="text" @click="deleteSchedule(scope.$index)">删除</el-button>
|
|
|
|
|
</template>
|
|
|
|
|
</el-table-column>
|
|
|
|
|
</el-table>
|
|
|
|
|
<div v-else>暂无日程安排</div>
|
|
|
|
|
<div class="schedule-actions">
|
|
|
|
|
<el-button size="small" type="primary" @click="openScheduleDialog">添加日程</el-button>
|
|
|
|
|
<el-button size="small" type="success" @click="generateScheduleAI">AI生成今日日程</el-button>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<!-- 日程编辑弹窗 -->
|
|
|
|
|
<el-dialog v-model="scheduleDialogVisible" title="编辑日程" width="340px" append-to-body>
|
|
|
|
|
<el-form :model="scheduleForm" label-width="60px">
|
|
|
|
|
<el-form-item label="日期">
|
|
|
|
|
<el-date-picker v-model="scheduleForm.date" type="date" value-format="YYYY-MM-DD" placeholder="选择日期" style="width: 100%" />
|
|
|
|
|
</el-form-item>
|
|
|
|
|
<el-form-item label="时间">
|
|
|
|
|
<el-time-picker v-model="scheduleForm.time" value-format="HH:mm" placeholder="选择时间" style="width: 100%" />
|
|
|
|
|
</el-form-item>
|
|
|
|
|
<el-form-item label="活动">
|
|
|
|
|
<el-input v-model="scheduleForm.event" placeholder="活动内容" />
|
|
|
|
|
</el-form-item>
|
|
|
|
|
</el-form>
|
|
|
|
|
<template #footer>
|
|
|
|
|
<el-button @click="scheduleDialogVisible = false">取消</el-button>
|
|
|
|
|
<el-button type="primary" @click="saveSchedule">保存</el-button>
|
|
|
|
|
</template>
|
|
|
|
|
</el-dialog>
|
|
|
|
|
</div>
|
|
|
|
|
<template #footer>
|
|
|
|
|
<el-button type="primary" @click="handleEdit">编辑</el-button>
|
|
|
|
|
@ -31,12 +80,104 @@
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<script setup>
|
|
|
|
|
import { ref, watch } from 'vue'
|
|
|
|
|
import { ref, watch, computed } from 'vue'
|
|
|
|
|
import { ElMessage } from 'element-plus'
|
|
|
|
|
import { updateOC } from '../stores/ocStore.js'
|
|
|
|
|
import { useRouter } from 'vue-router'
|
|
|
|
|
const props = defineProps({
|
|
|
|
|
modelValue: Boolean,
|
|
|
|
|
oc: Object
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// 日程表相关
|
|
|
|
|
const scheduleList = ref([])
|
|
|
|
|
const scheduleDialogVisible = ref(false)
|
|
|
|
|
const scheduleForm = ref({ date: '', time: '', event: '' })
|
|
|
|
|
const editingIndex = ref(-1)
|
|
|
|
|
|
|
|
|
|
// 监听OC变化,刷新日程
|
|
|
|
|
watch(() => props.oc, (oc) => {
|
|
|
|
|
if (oc && Array.isArray(oc.schedule)) {
|
|
|
|
|
// 排序,最新在前
|
|
|
|
|
scheduleList.value = [...oc.schedule].sort((a, b) => {
|
|
|
|
|
const t1 = new Date(a.date + 'T' + (a.time || '00:00')).getTime()
|
|
|
|
|
const t2 = new Date(b.date + 'T' + (b.time || '00:00')).getTime()
|
|
|
|
|
return t2 - t1
|
|
|
|
|
})
|
|
|
|
|
} else {
|
|
|
|
|
scheduleList.value = []
|
|
|
|
|
}
|
|
|
|
|
}, { immediate: true })
|
|
|
|
|
|
|
|
|
|
function openScheduleDialog() {
|
|
|
|
|
scheduleForm.value = { date: '', time: '', event: '' }
|
|
|
|
|
editingIndex.value = -1
|
|
|
|
|
scheduleDialogVisible.value = true
|
|
|
|
|
}
|
|
|
|
|
function editSchedule(idx) {
|
|
|
|
|
scheduleForm.value = { ...scheduleList.value[idx] }
|
|
|
|
|
editingIndex.value = idx
|
|
|
|
|
scheduleDialogVisible.value = true
|
|
|
|
|
}
|
|
|
|
|
function saveSchedule() {
|
|
|
|
|
if (!scheduleForm.value.date || !scheduleForm.value.time || !scheduleForm.value.event) {
|
|
|
|
|
ElMessage.warning('请填写完整信息')
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
if (editingIndex.value === -1) {
|
|
|
|
|
scheduleList.value.unshift({ ...scheduleForm.value })
|
|
|
|
|
} else {
|
|
|
|
|
scheduleList.value[editingIndex.value] = { ...scheduleForm.value }
|
|
|
|
|
}
|
|
|
|
|
updateScheduleToOC()
|
|
|
|
|
scheduleDialogVisible.value = false
|
|
|
|
|
}
|
|
|
|
|
function deleteSchedule(idx) {
|
|
|
|
|
scheduleList.value.splice(idx, 1)
|
|
|
|
|
updateScheduleToOC()
|
|
|
|
|
}
|
|
|
|
|
function updateScheduleToOC() {
|
|
|
|
|
// 更新到OC对象并持久化
|
|
|
|
|
if (props.oc && props.oc.id) {
|
|
|
|
|
// 排序后同步
|
|
|
|
|
updateOC(props.oc.id, { schedule: scheduleList.value })
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
function generateScheduleAI() {
|
|
|
|
|
// 更丰富的AI生成逻辑
|
|
|
|
|
if (!props.oc) return
|
|
|
|
|
const today = new Date()
|
|
|
|
|
const dateStr = today.getFullYear() + '-' + String(today.getMonth()+1).padStart(2,'0') + '-' + String(today.getDate()).padStart(2,'0')
|
|
|
|
|
const base = []
|
|
|
|
|
if (props.oc.occupation) base.push({ time: '09:00', event: `专注于${props.oc.occupation}相关工作` })
|
|
|
|
|
if (props.oc.hobbies && props.oc.hobbies.length) {
|
|
|
|
|
const hobbies = Array.isArray(props.oc.hobbies) ? props.oc.hobbies : [props.oc.hobbies]
|
|
|
|
|
hobbies.slice(0,2).forEach((h, i) => {
|
|
|
|
|
base.push({ time: i === 0 ? '14:00' : '16:00', event: `参与${h}活动` })
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
base.push({ time: '18:00', event: '与朋友社交/放松' })
|
|
|
|
|
base.push({ time: '20:00', event: '休息与自我提升' })
|
|
|
|
|
scheduleList.value = base.map(item => ({ date: dateStr, ...item }))
|
|
|
|
|
updateScheduleToOC()
|
|
|
|
|
ElMessage.success('已为该OC智能生成今日日程')
|
|
|
|
|
}
|
|
|
|
|
function formatDate(date) {
|
|
|
|
|
if (!date) return ''
|
|
|
|
|
const d = new Date(date)
|
|
|
|
|
if (isNaN(d)) return date
|
|
|
|
|
return `${d.getFullYear()}年${d.getMonth()+1}月${d.getDate()}日`
|
|
|
|
|
}
|
|
|
|
|
function formatTime(time) {
|
|
|
|
|
if (!time) return ''
|
|
|
|
|
if (/^\d{2}:\d{2}$/.test(time)) return time
|
|
|
|
|
const t = new Date('1970-01-01T'+time)
|
|
|
|
|
if (isNaN(t)) return time
|
|
|
|
|
return `${t.getHours().toString().padStart(2,'0')}:${t.getMinutes().toString().padStart(2,'0')}`
|
|
|
|
|
}
|
|
|
|
|
function scheduleRowClass({ rowIndex }) {
|
|
|
|
|
return rowIndex % 2 === 0 ? 'even-row' : 'odd-row'
|
|
|
|
|
}
|
|
|
|
|
const emit = defineEmits(['update:modelValue'])
|
|
|
|
|
const visible = ref(props.modelValue)
|
|
|
|
|
const router = useRouter()
|
|
|
|
|
@ -89,9 +230,34 @@ const onClose = () => {
|
|
|
|
|
font-size: 15px;
|
|
|
|
|
}
|
|
|
|
|
.schedule-area {
|
|
|
|
|
background: #f7f8fa;
|
|
|
|
|
.schedule-area {
|
|
|
|
|
background: linear-gradient(90deg, #f7f8fa 60%, #eaf6ff 100%);
|
|
|
|
|
border-radius: 12px;
|
|
|
|
|
padding: 12px 16px 8px 16px;
|
|
|
|
|
min-height: 40px;
|
|
|
|
|
box-shadow: 0 2px 8px 0 #eaf6ff44;
|
|
|
|
|
margin-bottom: 8px;
|
|
|
|
|
}
|
|
|
|
|
.oc-schedule-table {
|
|
|
|
|
margin-bottom: 8px;
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
padding: 8px 12px;
|
|
|
|
|
min-height: 32px;
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
}
|
|
|
|
|
.oc-schedule-table .even-row {
|
|
|
|
|
background: #f7faff;
|
|
|
|
|
}
|
|
|
|
|
.oc-schedule-table .odd-row {
|
|
|
|
|
background: #fff;
|
|
|
|
|
}
|
|
|
|
|
.event-content {
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
color: #409eff;
|
|
|
|
|
}
|
|
|
|
|
.schedule-actions {
|
|
|
|
|
display: flex;
|
|
|
|
|
gap: 10px;
|
|
|
|
|
margin-top: 8px;
|
|
|
|
|
justify-content: flex-end;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
</style>
|
|
|
|
|
|