样式调整
This commit is contained in:
@@ -6,14 +6,14 @@
|
||||
<van-tabbar-item name="ccalendar" icon="notes" to="/calendar">
|
||||
日历
|
||||
</van-tabbar-item>
|
||||
<van-tabbar-item name="statistics" icon="chart-trending-o" to="/statistics">
|
||||
<van-tabbar-item name="statistics" icon="chart-trending-o" to="/" @click="handleTabClick('/statistics')">
|
||||
统计
|
||||
</van-tabbar-item>
|
||||
<van-tabbar-item name="balance" icon="balance-list" to="/" @click="handleTabClick('/')">
|
||||
<van-tabbar-item name="balance" icon="balance-list" to="/balance" @click="handleTabClick('/balance')">
|
||||
账单
|
||||
</van-tabbar-item>
|
||||
<van-tabbar-item name="email" icon="records" to="/email" @click="handleTabClick('/email')">
|
||||
邮件
|
||||
<van-tabbar-item name="message" icon="comment" to="/message" @click="handleTabClick('/message')">
|
||||
消息
|
||||
</van-tabbar-item>
|
||||
<van-tabbar-item name="setting" icon="setting" to="/setting">
|
||||
设置
|
||||
@@ -56,9 +56,9 @@ const route = useRoute()
|
||||
const showTabbar = computed(() => {
|
||||
return route.path === '/' ||
|
||||
route.path === '/calendar' ||
|
||||
route.path === '/email' ||
|
||||
route.path === '/message' ||
|
||||
route.path === '/setting' ||
|
||||
route.path === '/statistics'
|
||||
route.path === '/balance'
|
||||
})
|
||||
|
||||
const active = ref('')
|
||||
@@ -89,14 +89,14 @@ const setActive = (path) => {
|
||||
switch (path) {
|
||||
case '/calendar':
|
||||
return 'ccalendar'
|
||||
case '/statistics':
|
||||
return 'statistics'
|
||||
case '/email':
|
||||
return 'email'
|
||||
case '/balance':
|
||||
return 'balance'
|
||||
case '/message':
|
||||
return 'message'
|
||||
case '/setting':
|
||||
return 'setting'
|
||||
default:
|
||||
return 'balance'
|
||||
return 'statistics'
|
||||
}
|
||||
})()
|
||||
console.log(active.value, path)
|
||||
|
||||
@@ -11,9 +11,9 @@ const router = createRouter({
|
||||
meta: { requiresAuth: false },
|
||||
},
|
||||
{
|
||||
path: '/',
|
||||
name: 'transactions',
|
||||
component: () => import('../views/TransactionsRecord.vue'),
|
||||
path: '/balance',
|
||||
name: 'balance',
|
||||
component: () => import('../views/BalanceView.vue'),
|
||||
meta: { requiresAuth: true },
|
||||
},
|
||||
{
|
||||
@@ -59,7 +59,7 @@ const router = createRouter({
|
||||
meta: { requiresAuth: true },
|
||||
},
|
||||
{
|
||||
path: '/statistics',
|
||||
path: '/',
|
||||
name: 'statistics',
|
||||
component: () => import('../views/StatisticsView.vue'),
|
||||
meta: { requiresAuth: true },
|
||||
@@ -69,6 +69,12 @@ const router = createRouter({
|
||||
name: 'bill-analysis',
|
||||
component: () => import('../views/BillAnalysisView.vue'),
|
||||
meta: { requiresAuth: true },
|
||||
},
|
||||
{
|
||||
path: '/message',
|
||||
name: 'message',
|
||||
component: () => import('../views/MessageView.vue'),
|
||||
meta: { requiresAuth: true },
|
||||
}
|
||||
],
|
||||
})
|
||||
|
||||
@@ -189,7 +189,7 @@
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
padding: 16px 0 0 0;
|
||||
padding: 0 0 0 0;
|
||||
}
|
||||
|
||||
/* ===== 粘性顶部元素样式 ===== */
|
||||
|
||||
57
Web/src/views/BalanceView.vue
Normal file
57
Web/src/views/BalanceView.vue
Normal file
@@ -0,0 +1,57 @@
|
||||
<template>
|
||||
<div class="page-container-flex">
|
||||
<!-- 顶部导航栏 -->
|
||||
<van-nav-bar title="交易记录" placeholder>
|
||||
<template #right>
|
||||
<van-button
|
||||
v-if="tabActive === 'balance'"
|
||||
type="primary"
|
||||
size="small"
|
||||
@click="transactionsRecordRef.openAddDialog()"
|
||||
>
|
||||
手动录账
|
||||
</van-button>
|
||||
<van-button
|
||||
v-if="tabActive === 'email'"
|
||||
size="small"
|
||||
type="primary"
|
||||
:loading="syncing"
|
||||
@click="emailRecordRef.handleSync()"
|
||||
>
|
||||
立即同步
|
||||
</van-button>
|
||||
</template>
|
||||
</van-nav-bar>
|
||||
<van-tabs v-model:active="tabActive" animated>
|
||||
<van-tab title="账单记录" name="balance" />
|
||||
<van-tab title="邮件记录" name="email" />
|
||||
</van-tabs>
|
||||
|
||||
<TransactionsRecord v-if="tabActive === 'balance'" ref="transactionsRecordRef"/>
|
||||
<EmailRecord v-else-if="tabActive === 'email'" ref="emailRecordRef" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue';
|
||||
import TransactionsRecord from './TransactionsRecord.vue';
|
||||
import EmailRecord from './EmailRecord.vue';
|
||||
const tabActive = ref('balance');
|
||||
|
||||
const transactionsRecordRef = ref(null);
|
||||
const emailRecordRef = ref(null);
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
:deep(.van-pull-refresh) {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
||||
/* 设置页面容器背景色 */
|
||||
:deep(.van-nav-bar) {
|
||||
background: transparent !important;
|
||||
}
|
||||
</style>
|
||||
@@ -263,7 +263,8 @@ fetchDailyStatistics(now.getFullYear(), now.getMonth() + 1);
|
||||
}
|
||||
|
||||
/* 设置页面容器背景色 */
|
||||
:deep(.van-nav-bar) {
|
||||
:deep(.van-calendar__header-title) {
|
||||
background: transparent !important;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
@@ -52,18 +52,18 @@
|
||||
</template>
|
||||
</van-swipe-cell>
|
||||
</van-cell-group>
|
||||
</div>
|
||||
|
||||
<div class="action-bar">
|
||||
<!-- 新增分类按钮 -->
|
||||
<div class="add-button-container">
|
||||
<van-button
|
||||
type="primary"
|
||||
size="large"
|
||||
block
|
||||
@click="handleAddCategory"
|
||||
>
|
||||
新增分类
|
||||
</van-button>
|
||||
</div>
|
||||
<van-button
|
||||
type="primary"
|
||||
size="large"
|
||||
block
|
||||
@click="handleAddCategory"
|
||||
>
|
||||
新增分类
|
||||
</van-button>
|
||||
</div>
|
||||
|
||||
<!-- 新增分类对话框 -->
|
||||
@@ -307,12 +307,11 @@ onMounted(() => {
|
||||
|
||||
<style scoped>
|
||||
.level-container {
|
||||
padding-top: 16px;
|
||||
min-height: calc(100vh - 50px);
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
.breadcrumb {
|
||||
margin-bottom: 16px;
|
||||
padding: 8px 0;
|
||||
}
|
||||
|
||||
@@ -320,15 +319,6 @@ onMounted(() => {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* 新增按钮 */
|
||||
.add-button-container {
|
||||
position: fixed;
|
||||
bottom: calc(60px + env(safe-area-inset-bottom, 0px));
|
||||
left: 16px;
|
||||
right: 16px;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
/* 深色模式 */
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.level-container {
|
||||
@@ -336,6 +326,27 @@ onMounted(() => {
|
||||
}
|
||||
}
|
||||
|
||||
/* 底部操作栏 */
|
||||
.action-bar {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
padding: 12px;
|
||||
background-color: var(--van-background-2, #fff);
|
||||
box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.08);
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.action-bar {
|
||||
background-color: var(--van-background-2, #2c2c2c);
|
||||
box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
}
|
||||
|
||||
/* 设置页面容器背景色 */
|
||||
:deep(.van-nav-bar) {
|
||||
background: transparent !important;
|
||||
|
||||
@@ -24,6 +24,9 @@
|
||||
@click="viewDetail"
|
||||
@update:selected-ids="selectedIds = $event"
|
||||
/>
|
||||
|
||||
<!-- 底部安全距离 -->
|
||||
<div style="height: calc(50px + env(safe-area-inset-bottom, 0px))"></div>
|
||||
</div>
|
||||
|
||||
<!-- 详情/编辑弹出层 -->
|
||||
|
||||
@@ -1,26 +1,11 @@
|
||||
<template>
|
||||
<div class="page-container-flex">
|
||||
<!-- 顶部导航栏 -->
|
||||
<van-nav-bar title="邮件记录" placeholder>
|
||||
<template #right>
|
||||
<van-button
|
||||
size="small"
|
||||
type="primary"
|
||||
:loading="syncing"
|
||||
@click="handleSync"
|
||||
>
|
||||
立即同步
|
||||
</van-button>
|
||||
</template>
|
||||
</van-nav-bar>
|
||||
|
||||
<!-- 下拉刷新区域 -->
|
||||
<van-pull-refresh v-model="refreshing" @refresh="onRefresh">
|
||||
<!-- 加载提示 -->
|
||||
<van-loading v-if="loading && !(emailList && emailList.length)" vertical style="padding: 50px 0">
|
||||
加载中...
|
||||
</van-loading>
|
||||
|
||||
<!-- 邮件列表 -->
|
||||
<van-list
|
||||
v-model:loading="loading"
|
||||
@@ -66,6 +51,9 @@
|
||||
description="暂无邮件记录"
|
||||
/>
|
||||
</van-list>
|
||||
|
||||
<!-- 底部安全距离 -->
|
||||
<div style="height: calc(50px + env(safe-area-inset-bottom, 0px))"></div>
|
||||
</van-pull-refresh>
|
||||
|
||||
<!-- 详情弹出层 -->
|
||||
@@ -405,6 +393,11 @@ const formatDate = (dateString) => {
|
||||
onMounted(() => {
|
||||
loadData(true)
|
||||
})
|
||||
|
||||
// 暴露给父级方法调用
|
||||
defineExpose({
|
||||
handleSync
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
9
Web/src/views/MessageView.vue
Normal file
9
Web/src/views/MessageView.vue
Normal file
@@ -0,0 +1,9 @@
|
||||
<template>
|
||||
<div>
|
||||
1
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
|
||||
</script>
|
||||
@@ -1,14 +1,5 @@
|
||||
<template>
|
||||
<div class="page-container-flex">
|
||||
<!-- 顶部导航栏 -->
|
||||
<van-nav-bar title="交易记录" placeholder>
|
||||
<template #right>
|
||||
<van-button type="primary" size="small" @click="openAddDialog">
|
||||
手动录账
|
||||
</van-button>
|
||||
</template>
|
||||
</van-nav-bar>
|
||||
|
||||
<!-- 下拉刷新区域 -->
|
||||
<van-pull-refresh v-model="refreshing" @refresh="onRefresh">
|
||||
<!-- 加载提示 -->
|
||||
@@ -25,6 +16,9 @@
|
||||
@click="viewDetail"
|
||||
@delete="handleDelete"
|
||||
/>
|
||||
|
||||
<!-- 底部安全距离 -->
|
||||
<div style="height: calc(50px + env(safe-area-inset-bottom, 0px))"></div>
|
||||
</van-pull-refresh>
|
||||
|
||||
<!-- 详情/编辑弹出层 -->
|
||||
@@ -517,6 +511,12 @@ onMounted(async () => {
|
||||
await loadClassifyList()
|
||||
// 不需要手动调用 loadData,van-list 会自动触发 onLoad
|
||||
})
|
||||
|
||||
// 暴露给父级方法调用
|
||||
defineExpose({
|
||||
openAddDialog
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
@@ -158,4 +158,89 @@ public class EmailMessageController(
|
||||
return BaseResponse.Fail($"同步邮件失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 标记邮件为已读
|
||||
/// </summary>
|
||||
[HttpPost]
|
||||
public async Task<BaseResponse> MarkAsReadAsync([FromQuery] long id)
|
||||
{
|
||||
try
|
||||
{
|
||||
var email = await emailRepository.GetByIdAsync(id);
|
||||
if (email == null)
|
||||
{
|
||||
return BaseResponse.Fail("邮件不存在");
|
||||
}
|
||||
|
||||
email.IsRead = true;
|
||||
email.UpdateTime = DateTime.Now;
|
||||
var success = await emailRepository.UpdateAsync(email);
|
||||
|
||||
if (success)
|
||||
{
|
||||
return new BaseResponse
|
||||
{
|
||||
Success = true
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
return BaseResponse.Fail("标记失败");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.LogError(ex, "标记邮件为已读失败,邮件ID: {EmailId}", id);
|
||||
return BaseResponse.Fail($"标记失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将所有邮件标记为已读
|
||||
/// </summary>
|
||||
[HttpPost]
|
||||
public async Task<BaseResponse> MarkAllAsReadAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
var emails = await emailRepository.GetAllAsync();
|
||||
var unreadEmails = emails.Where(e => !e.IsRead).ToList();
|
||||
|
||||
if (unreadEmails.Count == 0)
|
||||
{
|
||||
return new BaseResponse
|
||||
{
|
||||
Success = true,
|
||||
Message = "没有未读邮件"
|
||||
};
|
||||
}
|
||||
|
||||
foreach (var email in unreadEmails)
|
||||
{
|
||||
email.IsRead = true;
|
||||
email.UpdateTime = DateTime.Now;
|
||||
}
|
||||
|
||||
var success = await emailRepository.UpdateRangeAsync(unreadEmails);
|
||||
|
||||
if (success)
|
||||
{
|
||||
return new BaseResponse
|
||||
{
|
||||
Success = true,
|
||||
Message = $"已将 {unreadEmails.Count} 封邮件标记为已读"
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
return BaseResponse.Fail("标记失败");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.LogError(ex, "将所有邮件标记为已读失败");
|
||||
return BaseResponse.Fail($"标记失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -908,8 +908,6 @@ public class TransactionRecordController(
|
||||
_ => "未知"
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
Reference in New Issue
Block a user