This commit is contained in:
2025-10-16 16:21:56 +08:00
parent dd3936944b
commit 89dbdc63db
12 changed files with 512 additions and 222 deletions

View File

@@ -17,7 +17,7 @@
<div class="form-section glass-card p-20">
<!-- 收件人选择 -->
<div class="form-group">
<h3>收件人</h3>
<h3 class="font-semibold">收件人</h3>
<van-radio-group v-model="recipientType" direction="horizontal">
<van-radio name="SELF">自己</van-radio>
<van-radio name="SPECIFIC">他人</van-radio>
@@ -34,7 +34,7 @@
<!-- 发送时间选择 -->
<div class="form-group mt-20">
<h3>发送时间</h3>
<h3 class="font-semibold">发送时间</h3>
<van-radio-group v-model="timeType" direction="horizontal">
<van-radio name="preset">预设时间</van-radio>
<van-radio name="custom">自定义</van-radio>
@@ -73,7 +73,7 @@
<!-- 邮件内容 -->
<div class="form-group mt-20">
<h3>邮件内容</h3>
<h3 class="font-semibold">邮件内容</h3>
<van-field
v-model="subject"
placeholder="标题"
@@ -106,7 +106,7 @@
<!-- AI助手 -->
<div class="form-group mt-20">
<h3>AI写作助手</h3>
<h3 class="font-semibold">AI写作助手</h3>
<van-cell-group>
<van-cell title="生成开头" is-link @click="generateOpening" />
<van-cell title="内容建议" is-link @click="generateSuggestions" />
@@ -157,7 +157,6 @@
import { ref, onMounted, computed } from 'vue'
import { useRouter } from 'vue-router'
import { showLoadingToast, showSuccessToast, showFailToast, closeToast, Dialog } from 'vant'
import { mailActions, aiActions } from '../store'
export default {
name: 'Compose',
@@ -343,16 +342,22 @@ export default {
forbidClick: true,
})
const response = await aiActions.writingAssistant({
prompt: '请为未来邮件生成一个开头',
type: 'OUTLINE',
tone: 'EMOTIONAL',
length: 'SHORT',
context: '写给未来的自己'
})
// 模拟API调用延迟
await new Promise(resolve => setTimeout(resolve, 2000))
// 模拟AI生成的开头
const opennings = [
"亲爱的未来的我,",
"时光荏苒,当你读到这封信时,",
"写给多年后的自己,",
"未来的我,你好!",
"此刻的我,想对未来的你说:"
]
const randomIndex = Math.floor(Math.random() * opennings.length)
content.value = opennings[randomIndex] + "\n\n"
closeToast()
content.value = response.data.content
showSuccessToast('已生成开头')
} catch (error) {
closeToast()
@@ -368,18 +373,23 @@ export default {
forbidClick: true,
})
const response = await aiActions.writingAssistant({
prompt: '为未来邮件提供内容建议',
type: 'DRAFT',
tone: 'INSPIRATIONAL',
length: 'MEDIUM',
context: content.value || '写给未来的自己'
})
// 模拟API调用延迟
await new Promise(resolve => setTimeout(resolve, 2000))
// 模拟AI生成的内容建议
const suggestions = [
"你可以分享当前的生活状态、工作情况,以及对未来的期望和梦想。也可以记录下此刻的心情和思考,让未来的你能够回忆起这段时光。",
"考虑写下你现在的目标和计划,以及希望未来的自己已经实现了哪些。也可以询问未来的你某些问题的答案,比如'你幸福吗?'、'你成为想成为的人了吗?'。",
"你可以描述当前的世界、科技、文化等,让未来的你能够对比时代的变迁。也可以分享一些珍贵的回忆和瞬间,这些对你来说可能意义非凡。",
"写下你对未来的预测和想象,无论是对个人生活还是对整个世界。这些预测在将来读来会非常有趣,看看你猜对了多少。"
]
const randomIndex = Math.floor(Math.random() * suggestions.length)
closeToast()
Dialog.alert({
title: '内容建议',
message: response.data.content,
message: suggestions[randomIndex],
})
} catch (error) {
closeToast()
@@ -400,18 +410,33 @@ export default {
forbidClick: true,
})
const response = await aiActions.sentimentAnalysis({
content: content.value
})
// 模拟API调用延迟
await new Promise(resolve => setTimeout(resolve, 1500))
// 模拟情感分析结果
const sentiments = ['POSITIVE', 'NEUTRAL', 'EMOTIONAL', 'HOPEFUL']
const emotions = [
{ type: 'HAPPY', score: 0.7 },
{ type: 'HOPEFUL', score: 0.8 },
{ type: 'NOSTALGIC', score: 0.5 }
]
const randomSentiment = sentiments[Math.floor(Math.random() * sentiments.length)]
const emotionTypes = emotions.map(e => e.type).join('、')
const summaries = [
"这封信充满了对未来的期待和希望,表达了积极向上的情感。",
"文字中透露出对过去时光的怀念和对未来的思考。",
"这封信情感真挚,表达了内心深处的感受和想法。",
"文字中既有对现实的思考,也有对未来的憧憬和规划。"
]
const randomSummary = summaries[Math.floor(Math.random() * summaries.length)]
closeToast()
const sentiment = response.data.sentiment
const emotions = response.data.emotions.map(e => e.type).join('、')
const summary = response.data.summary
Dialog.alert({
title: '情感分析',
message: `情感倾向: ${sentiment}\n主要情感: ${emotions}\n分析: ${summary}`,
message: `情感倾向: ${randomSentiment}\n主要情感: ${emotionTypes}\n分析: ${randomSummary}`,
})
} catch (error) {
closeToast()
@@ -497,8 +522,19 @@ export default {
forbidClick: true,
})
// 模拟API调用延迟
await new Promise(resolve => setTimeout(resolve, 1000))
// 保存到本地存储作为草稿
const mailData = buildMailData()
await mailActions.createMail(mailData)
const drafts = JSON.parse(localStorage.getItem('draftMails') || '[]')
drafts.push({
...mailData,
id: Date.now().toString(),
status: 'DRAFT',
createdAt: new Date().toISOString()
})
localStorage.setItem('draftMails', JSON.stringify(drafts))
closeToast()
showSuccessToast('草稿已保存')
@@ -533,8 +569,20 @@ export default {
forbidClick: true,
})
// 模拟API调用延迟
await new Promise(resolve => setTimeout(resolve, 1500))
const mailData = buildMailData()
const response = await mailActions.createMail(mailData)
// 保存到本地存储作为已发送邮件
const sentMails = JSON.parse(localStorage.getItem('sentMails') || '[]')
sentMails.push({
...mailData,
id: Date.now().toString(),
status: 'PENDING',
createdAt: new Date().toISOString()
})
localStorage.setItem('sentMails', JSON.stringify(sentMails))
closeToast()
@@ -649,6 +697,30 @@ export default {
color: var(--text-primary);
}
/* 单选按钮选中样式 */
:deep(.van-radio-group) {
margin-bottom: 10px;
}
:deep(.van-radio) {
margin-right: 15px;
}
:deep(.van-radio__icon) {
font-size: 18px;
}
:deep(.van-radio__icon--checked .van-icon) {
background-color: #4285f4;
border-color: #4285f4;
box-shadow: 0 0 8px rgba(66, 133, 244, 0.5);
}
:deep(.van-radio__label) {
color: var(--text-primary);
font-size: 14px;
}
.preset-options {
display: flex;
flex-wrap: wrap;
@@ -657,6 +729,12 @@ export default {
.preset-button {
margin-bottom: 10px;
transition: all 0.3s ease;
}
.preset-button.van-button--primary {
transform: scale(1.05);
box-shadow: 0 4px 12px rgba(66, 133, 244, 0.4);
}
.custom-date-picker {
@@ -681,65 +759,24 @@ export default {
}
.save-button {
background: linear-gradient(135deg, #4a5f7a, #2c3e50);
border: none;
height: 50px;
font-size: 16px;
font-weight: bold;
margin-bottom: 10px;
box-shadow: 0 8px 20px rgba(74, 95, 122, 0.3);
transition: all 0.3s ease;
}
.save-button:hover {
transform: translateY(-2px);
box-shadow: 0 12px 25px rgba(74, 95, 122, 0.4);
}
.save-button:active {
transform: translateY(0);
box-shadow: 0 5px 15px rgba(74, 95, 122, 0.3);
}
.send-button {
background: linear-gradient(135deg, #00D4FF, #1D3B5A);
border: none;
height: 50px;
font-size: 16px;
font-weight: bold;
box-shadow: 0 8px 20px rgba(0, 212, 255, 0.3);
transition: all 0.3s ease;
}
.send-button:hover {
transform: translateY(-2px);
box-shadow: 0 12px 25px rgba(0, 212, 255, 0.4);
}
.send-button:active {
transform: translateY(0);
box-shadow: 0 5px 15px rgba(0, 212, 255, 0.3);
}
.preset-button {
margin: 5px;
box-shadow: 0 4px 10px rgba(0, 212, 255, 0.2);
transition: all 0.3s ease;
}
.preset-button:hover {
transform: translateY(-2px);
box-shadow: 0 6px 15px rgba(0, 212, 255, 0.3);
}
.media-uploader .van-button {
box-shadow: 0 4px 10px rgba(0, 212, 255, 0.2);
transition: all 0.3s ease;
}
.media-uploader .van-button:hover {
transform: translateY(-2px);
box-shadow: 0 6px 15px rgba(0, 212, 255, 0.3);
/* 按钮样式已由全局样式处理 */
}
.event-picker {