fix
All checks were successful
Docker Build & Deploy / Build Docker Image (push) Successful in 16s
Docker Build & Deploy / Deploy to Production (push) Successful in 6s
Docker Build & Deploy / Cleanup Dangling Images (push) Successful in 1s
Docker Build & Deploy / WeChat Notification (push) Successful in 1s
All checks were successful
Docker Build & Deploy / Build Docker Image (push) Successful in 16s
Docker Build & Deploy / Deploy to Production (push) Successful in 6s
Docker Build & Deploy / Cleanup Dangling Images (push) Successful in 1s
Docker Build & Deploy / WeChat Notification (push) Successful in 1s
This commit is contained in:
@@ -94,26 +94,41 @@
|
||||
</div>
|
||||
|
||||
<!-- 提示词设置弹窗 -->
|
||||
<PopupContainer
|
||||
<PopupContainerV2
|
||||
v-model:show="showPromptDialog"
|
||||
title="编辑分析提示词"
|
||||
show-cancel-button
|
||||
show-confirm-button
|
||||
confirm-text="保存"
|
||||
cancel-text="取消"
|
||||
@confirm="confirmPrompt"
|
||||
@cancel="showPromptDialog = false"
|
||||
:height="'75%'"
|
||||
>
|
||||
<van-field
|
||||
v-model="promptValue"
|
||||
rows="4"
|
||||
autosize
|
||||
type="textarea"
|
||||
maxlength="2000"
|
||||
placeholder="输入自定义的分析提示词..."
|
||||
show-word-limit
|
||||
/>
|
||||
</PopupContainer>
|
||||
<div style="padding: 16px">
|
||||
<van-field
|
||||
v-model="promptValue"
|
||||
rows="4"
|
||||
autosize
|
||||
type="textarea"
|
||||
maxlength="2000"
|
||||
placeholder="输入自定义的分析提示词..."
|
||||
show-word-limit
|
||||
/>
|
||||
</div>
|
||||
<template #footer>
|
||||
<div style="display: flex; gap: 12px">
|
||||
<van-button
|
||||
plain
|
||||
style="flex: 1"
|
||||
@click="showPromptDialog = false"
|
||||
>
|
||||
取消
|
||||
</van-button>
|
||||
<van-button
|
||||
type="primary"
|
||||
style="flex: 1"
|
||||
@click="confirmPrompt"
|
||||
>
|
||||
保存
|
||||
</van-button>
|
||||
</div>
|
||||
</template>
|
||||
</PopupContainerV2>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -122,7 +137,7 @@ import { ref, nextTick } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { showToast, showLoadingToast, closeToast } from 'vant'
|
||||
import { getConfig, setConfig } from '@/api/config'
|
||||
import PopupContainer from '@/components/PopupContainer.vue'
|
||||
import PopupContainerV2 from '@/components/PopupContainerV2.vue'
|
||||
|
||||
const router = useRouter()
|
||||
const userInput = ref('')
|
||||
|
||||
@@ -112,64 +112,107 @@
|
||||
</div>
|
||||
|
||||
<!-- 新增分类对话框 -->
|
||||
<PopupContainer
|
||||
<PopupContainerV2
|
||||
v-model:show="showAddDialog"
|
||||
title="新增分类"
|
||||
show-cancel-button
|
||||
show-confirm-button
|
||||
confirm-text="确认"
|
||||
cancel-text="取消"
|
||||
@confirm="handleConfirmAdd"
|
||||
@cancel="resetAddForm"
|
||||
:height="'auto'"
|
||||
>
|
||||
<van-form ref="addFormRef">
|
||||
<van-field
|
||||
v-model="addForm.name"
|
||||
name="name"
|
||||
label="分类名称"
|
||||
placeholder="请输入分类名称"
|
||||
:rules="[{ required: true, message: '请输入分类名称' }]"
|
||||
/>
|
||||
</van-form>
|
||||
</PopupContainer>
|
||||
<div style="padding: 16px">
|
||||
<van-form ref="addFormRef">
|
||||
<van-field
|
||||
v-model="addForm.name"
|
||||
name="name"
|
||||
label="分类名称"
|
||||
placeholder="请输入分类名称"
|
||||
:rules="[{ required: true, message: '请输入分类名称' }]"
|
||||
/>
|
||||
</van-form>
|
||||
</div>
|
||||
<template #footer>
|
||||
<div style="display: flex; gap: 12px">
|
||||
<van-button
|
||||
plain
|
||||
style="flex: 1"
|
||||
@click="resetAddForm"
|
||||
>
|
||||
取消
|
||||
</van-button>
|
||||
<van-button
|
||||
type="primary"
|
||||
style="flex: 1"
|
||||
@click="handleConfirmAdd"
|
||||
>
|
||||
确认
|
||||
</van-button>
|
||||
</div>
|
||||
</template>
|
||||
</PopupContainerV2>
|
||||
|
||||
<!-- 编辑分类对话框 -->
|
||||
<PopupContainer
|
||||
<PopupContainerV2
|
||||
v-model:show="showEditDialog"
|
||||
title="编辑分类"
|
||||
show-cancel-button
|
||||
show-confirm-button
|
||||
confirm-text="保存"
|
||||
cancel-text="取消"
|
||||
@confirm="handleConfirmEdit"
|
||||
@cancel="showEditDialog = false"
|
||||
:height="'auto'"
|
||||
>
|
||||
<van-form ref="editFormRef">
|
||||
<van-field
|
||||
v-model="editForm.name"
|
||||
name="name"
|
||||
label="分类名称"
|
||||
placeholder="请输入分类名称"
|
||||
:rules="[{ required: true, message: '请输入分类名称' }]"
|
||||
/>
|
||||
</van-form>
|
||||
</PopupContainer>
|
||||
<div style="padding: 16px">
|
||||
<van-form ref="editFormRef">
|
||||
<van-field
|
||||
v-model="editForm.name"
|
||||
name="name"
|
||||
label="分类名称"
|
||||
placeholder="请输入分类名称"
|
||||
:rules="[{ required: true, message: '请输入分类名称' }]"
|
||||
/>
|
||||
</van-form>
|
||||
</div>
|
||||
<template #footer>
|
||||
<div style="display: flex; gap: 12px">
|
||||
<van-button
|
||||
plain
|
||||
style="flex: 1"
|
||||
@click="showEditDialog = false"
|
||||
>
|
||||
取消
|
||||
</van-button>
|
||||
<van-button
|
||||
type="primary"
|
||||
style="flex: 1"
|
||||
@click="handleConfirmEdit"
|
||||
>
|
||||
保存
|
||||
</van-button>
|
||||
</div>
|
||||
</template>
|
||||
</PopupContainerV2>
|
||||
|
||||
<!-- 删除确认对话框 -->
|
||||
<PopupContainer
|
||||
<PopupContainerV2
|
||||
v-model:show="showDeleteConfirm"
|
||||
title="删除分类"
|
||||
show-cancel-button
|
||||
show-confirm-button
|
||||
confirm-text="确定"
|
||||
cancel-text="取消"
|
||||
@confirm="handleConfirmDelete"
|
||||
@cancel="showDeleteConfirm = false"
|
||||
:height="'auto'"
|
||||
>
|
||||
<p style="text-align: center; padding: 20px; color: var(--van-text-color-2)">
|
||||
删除后无法恢复,确定要删除吗?
|
||||
</p>
|
||||
</PopupContainer>
|
||||
<template #footer>
|
||||
<div style="display: flex; gap: 12px">
|
||||
<van-button
|
||||
plain
|
||||
style="flex: 1"
|
||||
@click="showDeleteConfirm = false"
|
||||
>
|
||||
取消
|
||||
</van-button>
|
||||
<van-button
|
||||
type="primary"
|
||||
style="flex: 1"
|
||||
@click="handleConfirmDelete"
|
||||
>
|
||||
确定
|
||||
</van-button>
|
||||
</div>
|
||||
</template>
|
||||
</PopupContainerV2>
|
||||
|
||||
<!-- 图标选择对话框 -->
|
||||
<IconSelector
|
||||
@@ -189,7 +232,7 @@ import { useRouter } from 'vue-router'
|
||||
import { showSuccessToast, showToast, showLoadingToast, closeToast } from 'vant'
|
||||
import Icon from '@/components/Icon.vue'
|
||||
import IconSelector from '@/components/IconSelector.vue'
|
||||
import PopupContainer from '@/components/PopupContainer.vue'
|
||||
import PopupContainerV2 from '@/components/PopupContainerV2.vue'
|
||||
import {
|
||||
getCategoryList,
|
||||
createCategory,
|
||||
|
||||
@@ -71,12 +71,12 @@
|
||||
/>
|
||||
|
||||
<!-- 记录列表弹窗 -->
|
||||
<PopupContainer
|
||||
v-model="showRecordsList"
|
||||
<PopupContainerV2
|
||||
v-model:show="showRecordsList"
|
||||
title="交易记录列表"
|
||||
height="75%"
|
||||
:height="'75%'"
|
||||
>
|
||||
<div style="background: var(--van-background)">
|
||||
<div style="background: var(--van-background); padding: 0">
|
||||
<!-- 批量操作按钮 -->
|
||||
<div class="batch-actions">
|
||||
<van-button
|
||||
@@ -122,7 +122,7 @@
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</PopupContainer>
|
||||
</PopupContainerV2>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -133,7 +133,7 @@ import { showToast, showConfirmDialog } from 'vant'
|
||||
import { nlpAnalysis, batchUpdateClassify } from '@/api/transactionRecord'
|
||||
import BillListComponent from '@/components/Bill/BillListComponent.vue'
|
||||
import TransactionDetail from '@/components/TransactionDetail.vue'
|
||||
import PopupContainer from '@/components/PopupContainer.vue'
|
||||
import PopupContainerV2 from '@/components/PopupContainerV2.vue'
|
||||
|
||||
const router = useRouter()
|
||||
const userInput = ref('')
|
||||
|
||||
@@ -73,23 +73,24 @@
|
||||
</van-pull-refresh>
|
||||
|
||||
<!-- 详情弹出层 -->
|
||||
<PopupContainer
|
||||
v-model="detailVisible"
|
||||
<PopupContainerV2
|
||||
v-model:show="detailVisible"
|
||||
:title="currentEmail ? currentEmail.Subject || currentEmail.subject || '(无主题)' : ''"
|
||||
height="75%"
|
||||
:height="'75%'"
|
||||
>
|
||||
<template #header-actions>
|
||||
<van-button
|
||||
size="small"
|
||||
type="primary"
|
||||
:loading="refreshingAnalysis"
|
||||
@click="handleRefreshAnalysis"
|
||||
>
|
||||
重新分析
|
||||
</van-button>
|
||||
</template>
|
||||
|
||||
<div v-if="currentEmail">
|
||||
<!-- 操作按钮栏 -->
|
||||
<div style="padding: 12px 16px; text-align: right; border-bottom: 1px solid var(--van-border-color)">
|
||||
<van-button
|
||||
size="small"
|
||||
type="primary"
|
||||
:loading="refreshingAnalysis"
|
||||
@click="handleRefreshAnalysis"
|
||||
>
|
||||
重新分析
|
||||
</van-button>
|
||||
</div>
|
||||
|
||||
<van-cell-group
|
||||
inset
|
||||
style="margin-top: 12px"
|
||||
@@ -140,13 +141,13 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</PopupContainer>
|
||||
</PopupContainerV2>
|
||||
|
||||
<!-- 账单列表弹出层 -->
|
||||
<PopupContainer
|
||||
v-model="transactionListVisible"
|
||||
<PopupContainerV2
|
||||
v-model:show="transactionListVisible"
|
||||
title="关联账单列表"
|
||||
height="75%"
|
||||
:height="'75%'"
|
||||
>
|
||||
<BillListComponent
|
||||
data-source="custom"
|
||||
@@ -158,7 +159,7 @@
|
||||
@click="handleTransactionClick"
|
||||
@delete="handleTransactionDelete"
|
||||
/>
|
||||
</PopupContainer>
|
||||
</PopupContainerV2>
|
||||
|
||||
<!-- 账单详情编辑弹出层 -->
|
||||
<TransactionDetail
|
||||
@@ -184,7 +185,7 @@ import {
|
||||
import { getTransactionDetail } from '@/api/transactionRecord'
|
||||
import BillListComponent from '@/components/Bill/BillListComponent.vue'
|
||||
import TransactionDetail from '@/components/TransactionDetail.vue'
|
||||
import PopupContainer from '@/components/PopupContainer.vue'
|
||||
import PopupContainerV2 from '@/components/PopupContainerV2.vue'
|
||||
|
||||
const emailList = ref([])
|
||||
const loading = ref(false)
|
||||
|
||||
@@ -71,22 +71,27 @@
|
||||
</van-pull-refresh>
|
||||
|
||||
<!-- 详情弹出层 -->
|
||||
<PopupContainer
|
||||
v-model="detailVisible"
|
||||
<PopupContainerV2
|
||||
v-model:show="detailVisible"
|
||||
:title="currentMessage.title"
|
||||
:subtitle="currentMessage.createTime"
|
||||
height="75%"
|
||||
:height="'75%'"
|
||||
>
|
||||
<div
|
||||
v-if="currentMessage.messageType === 2"
|
||||
class="detail-content rich-html-content"
|
||||
v-html="currentMessage.content"
|
||||
/>
|
||||
<div
|
||||
v-else
|
||||
class="detail-content"
|
||||
>
|
||||
{{ currentMessage.content }}
|
||||
<div style="padding: 16px">
|
||||
<p style="color: #999; font-size: 14px; margin-bottom: 12px; margin-top: 0">
|
||||
{{ currentMessage.createTime }}
|
||||
</p>
|
||||
<div
|
||||
v-if="currentMessage.messageType === 2"
|
||||
class="rich-html-content"
|
||||
style="font-size: 14px; line-height: 1.6"
|
||||
v-html="currentMessage.content"
|
||||
/>
|
||||
<div
|
||||
v-else
|
||||
style="font-size: 14px; line-height: 1.6; white-space: pre-wrap"
|
||||
>
|
||||
{{ currentMessage.content }}
|
||||
</div>
|
||||
</div>
|
||||
<template
|
||||
v-if="currentMessage.url && currentMessage.messageType === 1"
|
||||
@@ -101,7 +106,7 @@
|
||||
查看详情
|
||||
</van-button>
|
||||
</template>
|
||||
</PopupContainer>
|
||||
</PopupContainerV2>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -111,7 +116,7 @@ import { useRouter } from 'vue-router'
|
||||
import { showToast, showDialog } from 'vant'
|
||||
import { getMessageList, markAsRead, deleteMessage, markAllAsRead } from '@/api/message'
|
||||
import { useMessageStore } from '@/stores/message'
|
||||
import PopupContainer from '@/components/PopupContainer.vue'
|
||||
import PopupContainerV2 from '@/components/PopupContainerV2.vue'
|
||||
|
||||
const messageStore = useMessageStore()
|
||||
const router = useRouter()
|
||||
@@ -325,22 +330,6 @@ defineExpose({
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.detail-time {
|
||||
color: var(--van-text-color-2);
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.detail-content {
|
||||
padding: 16px;
|
||||
font-size: 14px;
|
||||
line-height: 1.6;
|
||||
color: var(--van-text-color);
|
||||
}
|
||||
|
||||
.detail-content:not(.rich-html-content) {
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
:deep(.van-pull-refresh) {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
|
||||
@@ -107,141 +107,143 @@
|
||||
</div>
|
||||
|
||||
<!-- 新增/编辑弹窗 -->
|
||||
<PopupContainer
|
||||
v-model="dialogVisible"
|
||||
<PopupContainerV2
|
||||
v-model:show="dialogVisible"
|
||||
:title="isEdit ? '编辑周期账单' : '新增周期账单'"
|
||||
height="75%"
|
||||
:height="'75%'"
|
||||
>
|
||||
<van-form>
|
||||
<van-cell-group
|
||||
inset
|
||||
title="周期设置"
|
||||
>
|
||||
<van-field
|
||||
v-model="form.periodicTypeText"
|
||||
is-link
|
||||
readonly
|
||||
name="periodicType"
|
||||
label="周期"
|
||||
placeholder="请选择周期类型"
|
||||
:rules="[{ required: true, message: '请选择周期类型' }]"
|
||||
@click="showPeriodicTypePicker = true"
|
||||
/>
|
||||
|
||||
<!-- 每周配置 -->
|
||||
<van-field
|
||||
v-if="form.periodicType === 1"
|
||||
v-model="form.weekdaysText"
|
||||
is-link
|
||||
readonly
|
||||
name="weekdays"
|
||||
label="星期"
|
||||
placeholder="请选择星期几"
|
||||
:rules="[{ required: true, message: '请选择星期几' }]"
|
||||
@click="showWeekdaysPicker = true"
|
||||
/>
|
||||
|
||||
<!-- 每月配置 -->
|
||||
<van-field
|
||||
v-if="form.periodicType === 2"
|
||||
v-model="form.monthDaysText"
|
||||
is-link
|
||||
readonly
|
||||
name="monthDays"
|
||||
label="日期"
|
||||
placeholder="请选择每月的日期"
|
||||
:rules="[{ required: true, message: '请选择日期' }]"
|
||||
@click="showMonthDaysPicker = true"
|
||||
/>
|
||||
|
||||
<!-- 每季度配置 -->
|
||||
<van-field
|
||||
v-if="form.periodicType === 3"
|
||||
v-model="form.quarterDay"
|
||||
name="quarterDay"
|
||||
label="季度第几天"
|
||||
placeholder="请输入季度开始后第几天"
|
||||
type="number"
|
||||
:rules="[{ required: true, message: '请输入季度开始后第几天' }]"
|
||||
/>
|
||||
|
||||
<!-- 每年配置 -->
|
||||
<van-field
|
||||
v-if="form.periodicType === 4"
|
||||
v-model="form.yearDay"
|
||||
name="yearDay"
|
||||
label="年第几天"
|
||||
placeholder="请输入年开始后第几天"
|
||||
type="number"
|
||||
:rules="[{ required: true, message: '请输入年开始后第几天' }]"
|
||||
/>
|
||||
</van-cell-group>
|
||||
|
||||
<van-cell-group
|
||||
inset
|
||||
title="基本信息"
|
||||
>
|
||||
<van-field
|
||||
v-model="form.reason"
|
||||
name="reason"
|
||||
label="摘要"
|
||||
placeholder="请输入交易摘要"
|
||||
type="textarea"
|
||||
rows="2"
|
||||
autosize
|
||||
maxlength="200"
|
||||
show-word-limit
|
||||
/>
|
||||
<van-field
|
||||
v-model="form.amount"
|
||||
name="amount"
|
||||
label="金额"
|
||||
placeholder="请输入金额"
|
||||
type="number"
|
||||
:rules="[{ required: true, message: '请输入金额' }]"
|
||||
/>
|
||||
<van-field
|
||||
v-model="form.type"
|
||||
name="type"
|
||||
label="类型"
|
||||
<div style="padding: 0">
|
||||
<van-form>
|
||||
<van-cell-group
|
||||
inset
|
||||
title="周期设置"
|
||||
>
|
||||
<template #input>
|
||||
<van-radio-group
|
||||
v-model="form.type"
|
||||
direction="horizontal"
|
||||
>
|
||||
<van-radio :value="0">
|
||||
支出
|
||||
</van-radio>
|
||||
<van-radio :value="1">
|
||||
收入
|
||||
</van-radio>
|
||||
<van-radio :value="2">
|
||||
不计
|
||||
</van-radio>
|
||||
</van-radio-group>
|
||||
</template>
|
||||
</van-field>
|
||||
<van-field
|
||||
name="classify"
|
||||
label="分类"
|
||||
>
|
||||
<template #input>
|
||||
<span
|
||||
v-if="!form.classify"
|
||||
style="color: var(--van-gray-5)"
|
||||
>请选择交易分类</span>
|
||||
<span v-else>{{ form.classify }}</span>
|
||||
</template>
|
||||
</van-field>
|
||||
<van-field
|
||||
v-model="form.periodicTypeText"
|
||||
is-link
|
||||
readonly
|
||||
name="periodicType"
|
||||
label="周期"
|
||||
placeholder="请选择周期类型"
|
||||
:rules="[{ required: true, message: '请选择周期类型' }]"
|
||||
@click="showPeriodicTypePicker = true"
|
||||
/>
|
||||
|
||||
<!-- 分类选择组件 -->
|
||||
<ClassifySelector
|
||||
v-model="form.classify"
|
||||
:type="form.type"
|
||||
/>
|
||||
</van-cell-group>
|
||||
</van-form>
|
||||
<!-- 每周配置 -->
|
||||
<van-field
|
||||
v-if="form.periodicType === 1"
|
||||
v-model="form.weekdaysText"
|
||||
is-link
|
||||
readonly
|
||||
name="weekdays"
|
||||
label="星期"
|
||||
placeholder="请选择星期几"
|
||||
:rules="[{ required: true, message: '请选择星期几' }]"
|
||||
@click="showWeekdaysPicker = true"
|
||||
/>
|
||||
|
||||
<!-- 每月配置 -->
|
||||
<van-field
|
||||
v-if="form.periodicType === 2"
|
||||
v-model="form.monthDaysText"
|
||||
is-link
|
||||
readonly
|
||||
name="monthDays"
|
||||
label="日期"
|
||||
placeholder="请选择每月的日期"
|
||||
:rules="[{ required: true, message: '请选择日期' }]"
|
||||
@click="showMonthDaysPicker = true"
|
||||
/>
|
||||
|
||||
<!-- 每季度配置 -->
|
||||
<van-field
|
||||
v-if="form.periodicType === 3"
|
||||
v-model="form.quarterDay"
|
||||
name="quarterDay"
|
||||
label="季度第几天"
|
||||
placeholder="请输入季度开始后第几天"
|
||||
type="number"
|
||||
:rules="[{ required: true, message: '请输入季度开始后第几天' }]"
|
||||
/>
|
||||
|
||||
<!-- 每年配置 -->
|
||||
<van-field
|
||||
v-if="form.periodicType === 4"
|
||||
v-model="form.yearDay"
|
||||
name="yearDay"
|
||||
label="年第几天"
|
||||
placeholder="请输入年开始后第几天"
|
||||
type="number"
|
||||
:rules="[{ required: true, message: '请输入年开始后第几天' }]"
|
||||
/>
|
||||
</van-cell-group>
|
||||
|
||||
<van-cell-group
|
||||
inset
|
||||
title="基本信息"
|
||||
>
|
||||
<van-field
|
||||
v-model="form.reason"
|
||||
name="reason"
|
||||
label="摘要"
|
||||
placeholder="请输入交易摘要"
|
||||
type="textarea"
|
||||
rows="2"
|
||||
autosize
|
||||
maxlength="200"
|
||||
show-word-limit
|
||||
/>
|
||||
<van-field
|
||||
v-model="form.amount"
|
||||
name="amount"
|
||||
label="金额"
|
||||
placeholder="请输入金额"
|
||||
type="number"
|
||||
:rules="[{ required: true, message: '请输入金额' }]"
|
||||
/>
|
||||
<van-field
|
||||
v-model="form.type"
|
||||
name="type"
|
||||
label="类型"
|
||||
>
|
||||
<template #input>
|
||||
<van-radio-group
|
||||
v-model="form.type"
|
||||
direction="horizontal"
|
||||
>
|
||||
<van-radio :value="0">
|
||||
支出
|
||||
</van-radio>
|
||||
<van-radio :value="1">
|
||||
收入
|
||||
</van-radio>
|
||||
<van-radio :value="2">
|
||||
不计
|
||||
</van-radio>
|
||||
</van-radio-group>
|
||||
</template>
|
||||
</van-field>
|
||||
<van-field
|
||||
name="classify"
|
||||
label="分类"
|
||||
>
|
||||
<template #input>
|
||||
<span
|
||||
v-if="!form.classify"
|
||||
style="color: var(--van-gray-5)"
|
||||
>请选择交易分类</span>
|
||||
<span v-else>{{ form.classify }}</span>
|
||||
</template>
|
||||
</van-field>
|
||||
|
||||
<!-- 分类选择组件 -->
|
||||
<ClassifySelector
|
||||
v-model="form.classify"
|
||||
:type="form.type"
|
||||
/>
|
||||
</van-cell-group>
|
||||
</van-form>
|
||||
</div>
|
||||
<template #footer>
|
||||
<van-button
|
||||
round
|
||||
@@ -253,7 +255,7 @@
|
||||
{{ isEdit ? '更新' : '确认添加' }}
|
||||
</van-button>
|
||||
</template>
|
||||
</PopupContainer>
|
||||
</PopupContainerV2>
|
||||
|
||||
<!-- 周期类型选择器 -->
|
||||
<van-popup
|
||||
@@ -310,7 +312,7 @@ import {
|
||||
createPeriodic,
|
||||
updatePeriodic
|
||||
} from '@/api/transactionPeriodic'
|
||||
import PopupContainer from '@/components/PopupContainer.vue'
|
||||
import PopupContainerV2 from '@/components/PopupContainerV2.vue'
|
||||
import ClassifySelector from '@/components/ClassifySelector.vue'
|
||||
import dayjs from 'dayjs'
|
||||
|
||||
|
||||
@@ -151,183 +151,43 @@
|
||||
<!-- 储蓄配置弹窗 -->
|
||||
<SavingsConfigPopup
|
||||
ref="savingsConfigRef"
|
||||
@success="loadBudgetData"
|
||||
@change="loadBudgetData"
|
||||
/>
|
||||
|
||||
<!-- 预算明细列表弹窗 -->
|
||||
<PopupContainer
|
||||
v-model="showListPopup"
|
||||
:title="popupTitle"
|
||||
height="80%"
|
||||
>
|
||||
<template #header-actions>
|
||||
<van-icon
|
||||
name="plus"
|
||||
size="20"
|
||||
title="添加预算"
|
||||
@click="budgetEditRef.open({ category: activeTab })"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<van-pull-refresh
|
||||
v-model="refreshing"
|
||||
style="min-height: 100%"
|
||||
@refresh="onRefresh"
|
||||
>
|
||||
<div class="budget-list">
|
||||
<!-- 支出列表 -->
|
||||
<template v-if="activeTab === BudgetCategory.Expense && expenseBudgets?.length > 0">
|
||||
<van-swipe-cell
|
||||
v-for="budget in expenseBudgets"
|
||||
:key="budget.id"
|
||||
>
|
||||
<BudgetCard
|
||||
:budget="budget"
|
||||
:progress-color="getProgressColor(budget)"
|
||||
:percent-class="{ warning: budget.current / budget.limit > 0.8 }"
|
||||
:period-label="getPeriodLabel(budget.type)"
|
||||
@click="handleEdit(budget)"
|
||||
>
|
||||
<template #amount-info>
|
||||
<div class="info-item">
|
||||
<div class="label">
|
||||
已支出
|
||||
</div>
|
||||
<div class="value expense">
|
||||
¥{{ formatMoney(budget.current) }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<div class="label">
|
||||
预算
|
||||
</div>
|
||||
<div class="value">
|
||||
¥{{ formatMoney(budget.limit) }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<div class="label">
|
||||
余额
|
||||
</div>
|
||||
<div
|
||||
class="value"
|
||||
:class="budget.limit - budget.current >= 0 ? 'income' : 'expense'"
|
||||
>
|
||||
¥{{ formatMoney(budget.limit - budget.current) }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</BudgetCard>
|
||||
<template #right>
|
||||
<van-button
|
||||
square
|
||||
text="删除"
|
||||
type="danger"
|
||||
class="delete-button"
|
||||
@click="handleDelete(budget)"
|
||||
/>
|
||||
</template>
|
||||
</van-swipe-cell>
|
||||
</template>
|
||||
|
||||
<!-- 收入列表 -->
|
||||
<template v-if="activeTab === BudgetCategory.Income && incomeBudgets?.length > 0">
|
||||
<van-swipe-cell
|
||||
v-for="budget in incomeBudgets"
|
||||
:key="budget.id"
|
||||
>
|
||||
<BudgetCard
|
||||
:budget="budget"
|
||||
:progress-color="getProgressColor(budget)"
|
||||
:percent-class="{ income: budget.current / budget.limit >= 1 }"
|
||||
:period-label="getPeriodLabel(budget.type)"
|
||||
@click="handleEdit(budget)"
|
||||
>
|
||||
<template #amount-info>
|
||||
<div class="info-item">
|
||||
<div class="label">
|
||||
已收入
|
||||
</div>
|
||||
<div class="value income">
|
||||
¥{{ formatMoney(budget.current) }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<div class="label">
|
||||
目标
|
||||
</div>
|
||||
<div class="value">
|
||||
¥{{ formatMoney(budget.limit) }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<div class="label">
|
||||
差额
|
||||
</div>
|
||||
<div
|
||||
class="value"
|
||||
:class="budget.current >= budget.limit ? 'income' : 'expense'"
|
||||
>
|
||||
¥{{ formatMoney(Math.abs(budget.limit - budget.current)) }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</BudgetCard>
|
||||
<template #right>
|
||||
<van-button
|
||||
square
|
||||
text="删除"
|
||||
type="danger"
|
||||
class="delete-button"
|
||||
@click="handleDelete(budget)"
|
||||
/>
|
||||
</template>
|
||||
</van-swipe-cell>
|
||||
</template>
|
||||
|
||||
<!-- 空状态 -->
|
||||
<van-empty
|
||||
v-if="
|
||||
activeTab !== BudgetCategory.Savings &&
|
||||
!loading &&
|
||||
!hasError &&
|
||||
((activeTab === BudgetCategory.Expense && expenseBudgets?.length === 0) ||
|
||||
(activeTab === BudgetCategory.Income && incomeBudgets?.length === 0))
|
||||
"
|
||||
:description="`暂无${activeTab === BudgetCategory.Expense ? '支出' : '收入'}预算`"
|
||||
/>
|
||||
</div>
|
||||
<div style="height: calc(95px + env(safe-area-inset-bottom, 0px))" />
|
||||
</van-pull-refresh>
|
||||
</PopupContainer>
|
||||
|
||||
<!-- 未覆盖分类弹窗 -->
|
||||
<PopupContainer
|
||||
v-model="showUncoveredDetails"
|
||||
<PopupContainerV2
|
||||
v-model:show="showUncoveredDetails"
|
||||
title="未覆盖预算的分类"
|
||||
:subtitle="`本月共 <b style='color:var(--van-primary-color)'>${uncoveredCategories.length}</b> 个分类未设置预算`"
|
||||
height="60%"
|
||||
:height="'60%'"
|
||||
>
|
||||
<div class="uncovered-list">
|
||||
<div style="padding: 0">
|
||||
<!-- subtitle 作为内容区域顶部 -->
|
||||
<div
|
||||
v-for="item in uncoveredCategories"
|
||||
:key="item.category"
|
||||
class="uncovered-item"
|
||||
>
|
||||
<div class="item-left">
|
||||
<div class="category-name">
|
||||
{{ item.category }}
|
||||
style="padding: 12px 16px; text-align: center; color: #999; font-size: 14px; border-bottom: 1px solid var(--van-border-color)"
|
||||
v-html="`本月共 <b style='color:var(--van-primary-color)'>${uncoveredCategories.length}</b> 个分类未设置预算`"
|
||||
/>
|
||||
|
||||
<div class="uncovered-list">
|
||||
<div
|
||||
v-for="item in uncoveredCategories"
|
||||
:key="item.category"
|
||||
class="uncovered-item"
|
||||
>
|
||||
<div class="item-left">
|
||||
<div class="category-name">
|
||||
{{ item.category }}
|
||||
</div>
|
||||
<div class="transaction-count">
|
||||
{{ item.transactionCount }} 笔记录
|
||||
</div>
|
||||
</div>
|
||||
<div class="transaction-count">
|
||||
{{ item.transactionCount }} 笔记录
|
||||
</div>
|
||||
</div>
|
||||
<div class="item-right">
|
||||
<div
|
||||
class="item-amount"
|
||||
:class="activeTab === BudgetCategory.Expense ? 'expense' : 'income'"
|
||||
>
|
||||
¥{{ formatMoney(item.totalAmount) }}
|
||||
<div class="item-right">
|
||||
<div
|
||||
class="item-amount"
|
||||
:class="activeTab === BudgetCategory.Expense ? 'expense' : 'income'"
|
||||
>
|
||||
¥{{ formatMoney(item.totalAmount) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -343,25 +203,31 @@
|
||||
我知道了
|
||||
</van-button>
|
||||
</template>
|
||||
</PopupContainer>
|
||||
</PopupContainerV2>
|
||||
|
||||
<!-- 归档总结弹窗 -->
|
||||
<PopupContainer
|
||||
v-model="showSummaryPopup"
|
||||
<PopupContainerV2
|
||||
v-model:show="showSummaryPopup"
|
||||
title="月份归档总结"
|
||||
:subtitle="`${selectedDate.getFullYear()}年${selectedDate.getMonth() + 1}月`"
|
||||
height="70%"
|
||||
:height="'70%'"
|
||||
>
|
||||
<div style="padding: 16px">
|
||||
<div
|
||||
class="rich-html-content"
|
||||
v-html="
|
||||
archiveSummary ||
|
||||
'<p style=\'text-align:center;color:var(--van-text-color-3)\'>暂无总结</p>'
|
||||
"
|
||||
/>
|
||||
<div style="padding: 0">
|
||||
<!-- subtitle -->
|
||||
<div style="padding: 12px 16px; text-align: center; color: #999; font-size: 14px; border-bottom: 1px solid var(--van-border-color)">
|
||||
{{ selectedDate.getFullYear() }}年{{ selectedDate.getMonth() + 1 }}月
|
||||
</div>
|
||||
|
||||
<div style="padding: 16px">
|
||||
<div
|
||||
class="rich-html-content"
|
||||
v-html="
|
||||
archiveSummary ||
|
||||
'<p style=\'text-align:center;color:var(--van-text-color-3)\'>暂无总结</p>'
|
||||
"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</PopupContainer>
|
||||
</PopupContainerV2>
|
||||
|
||||
<!-- 日期选择器 -->
|
||||
<van-popup
|
||||
@@ -401,7 +267,7 @@ import BudgetTypeTabs from '@/components/BudgetTypeTabs.vue'
|
||||
import BudgetCard from '@/components/Budget/BudgetCard.vue'
|
||||
import BudgetEditPopup from '@/components/Budget/BudgetEditPopup.vue'
|
||||
import SavingsConfigPopup from '@/components/Budget/SavingsConfigPopup.vue'
|
||||
import PopupContainer from '@/components/PopupContainer.vue'
|
||||
import PopupContainerV2 from '@/components/PopupContainerV2.vue'
|
||||
import ExpenseBudgetContent from './modules/ExpenseBudgetContent.vue'
|
||||
import IncomeBudgetContent from './modules/IncomeBudgetContent.vue'
|
||||
import SavingsBudgetContent from './modules/SavingsBudgetContent.vue'
|
||||
|
||||
@@ -71,10 +71,10 @@
|
||||
</div>
|
||||
|
||||
<!-- 计划存款明细弹窗 -->
|
||||
<PopupContainer
|
||||
v-model="showDetailPopup"
|
||||
<PopupContainerV2
|
||||
v-model:show="showDetailPopup"
|
||||
title="计划存款明细"
|
||||
height="80%"
|
||||
:height="'80%'"
|
||||
>
|
||||
<div class="popup-body">
|
||||
<div
|
||||
@@ -169,14 +169,14 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</PopupContainer>
|
||||
</PopupContainerV2>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed } from 'vue'
|
||||
import BudgetCard from '@/components/Budget/BudgetCard.vue'
|
||||
import { BudgetPeriodType } from '@/constants/enums'
|
||||
import PopupContainer from '@/components/PopupContainer.vue'
|
||||
import PopupContainerV2 from '@/components/PopupContainerV2.vue'
|
||||
|
||||
// Props
|
||||
const props = defineProps({
|
||||
|
||||
Reference in New Issue
Block a user