feat: update VSCode settings for ESLint and Prettier integration
chore: refactor ESLint configuration for improved linting rules and performance fix: handle push event data parsing in service worker style: adjust tabbar item properties for better readability in App.vue refactor: remove unused functions and improve code clarity in TransactionDetail.vue fix: ensure consistent event handling in CalendarView.vue style: clean up component structure and formatting in various Vue files chore: update launch script for better command execution feat: add ESLint configuration file for consistent code style across the project fix: resolve issues with button click events in multiple components
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
<template>
|
||||
<div class="page-container-flex">
|
||||
<!-- eslint-disable vue/no-v-html -->
|
||||
<template>
|
||||
<div class="page-container-flex">
|
||||
<!-- 顶部导航栏 -->
|
||||
<van-nav-bar
|
||||
title="智能分析"
|
||||
@@ -11,8 +12,8 @@
|
||||
<van-icon
|
||||
name="question-o"
|
||||
size="20"
|
||||
@click="onClickPrompt"
|
||||
style="cursor: pointer; padding-right: 12px;"
|
||||
@click="onClickPrompt"
|
||||
/>
|
||||
</template>
|
||||
</van-nav-bar>
|
||||
@@ -39,8 +40,8 @@
|
||||
type="primary"
|
||||
plain
|
||||
size="medium"
|
||||
@click="selectQuestion(q)"
|
||||
class="quick-tag"
|
||||
@click="selectQuestion(q)"
|
||||
>
|
||||
{{ q }}
|
||||
</van-tag>
|
||||
@@ -52,26 +53,26 @@
|
||||
round
|
||||
:loading="analyzing"
|
||||
loading-text="分析中..."
|
||||
@click="startAnalysis"
|
||||
:disabled="!userInput.trim()"
|
||||
@click="startAnalysis"
|
||||
>
|
||||
开始分析
|
||||
</van-button>
|
||||
</div>
|
||||
|
||||
<!-- 结果区域 -->
|
||||
<div class="result-section" v-if="showResult">
|
||||
<div v-if="showResult" class="result-section">
|
||||
<div class="result-header">
|
||||
<h3>分析结果</h3>
|
||||
<van-icon
|
||||
v-if="!analyzing"
|
||||
name="delete-o"
|
||||
size="18"
|
||||
size="18"
|
||||
@click="clearResult"
|
||||
v-if="!analyzing"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="result-content" ref="resultContainer">
|
||||
<div ref="resultContainer" class="result-content">
|
||||
<div v-html="resultHtml"></div>
|
||||
<van-loading v-if="analyzing" class="result-loading">
|
||||
AI正在分析中...
|
||||
@@ -202,7 +203,7 @@ const startAnalysis = async () => {
|
||||
resultHtml.value = ''
|
||||
|
||||
try {
|
||||
var baseUrl = import.meta.env.VITE_API_BASE_URL || ''
|
||||
const baseUrl = import.meta.env.VITE_API_BASE_URL || ''
|
||||
const response = await fetch(`${baseUrl}/TransactionRecord/AnalyzeBill`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
<van-tag v-else type="success" size="small" plain>进行中</van-tag>
|
||||
</div>
|
||||
<div class="header-actions">
|
||||
<van-button icon="replay" size="mini" plain @click="handleSync(budget)" :loading="budget.syncing" />
|
||||
<van-button icon="replay" size="mini" plain :loading="budget.syncing" @click="handleSync(budget)" />
|
||||
<van-button :icon="budget.isStopped ? 'play' : 'pause'" size="mini" plain @click="handleToggleStop(budget)" />
|
||||
</div>
|
||||
</div>
|
||||
@@ -139,7 +139,7 @@
|
||||
<van-tag v-else type="success" size="small" plain>进行中</van-tag>
|
||||
</div>
|
||||
<div class="header-actions">
|
||||
<van-button icon="replay" size="mini" plain round @click="handleSync(budget)" :loading="budget.syncing" />
|
||||
<van-button icon="replay" size="mini" plain round :loading="budget.syncing" @click="handleSync(budget)" />
|
||||
<van-button :icon="budget.isStopped ? 'play' : 'pause'" size="mini" plain round @click="handleToggleStop(budget)" />
|
||||
</div>
|
||||
</div>
|
||||
@@ -233,7 +233,7 @@
|
||||
<van-tag v-else type="success" size="small" plain>积累中</van-tag>
|
||||
</div>
|
||||
<div class="header-actions">
|
||||
<van-button icon="replay" size="mini" plain round @click="handleSync(budget)" :loading="budget.syncing" />
|
||||
<van-button icon="replay" size="mini" plain round :loading="budget.syncing" @click="handleSync(budget)" />
|
||||
<van-button :icon="budget.isStopped ? 'play' : 'pause'" size="mini" plain round @click="handleToggleStop(budget)" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -260,7 +260,7 @@ const now = new Date();
|
||||
fetchDailyStatistics(now.getFullYear(), now.getMonth() + 1);
|
||||
|
||||
// 全局删除事件监听,确保日历页面数据一致
|
||||
const onGlobalTransactionDeleted = (e) => {
|
||||
const onGlobalTransactionDeleted = () => {
|
||||
if (selectedDate.value) {
|
||||
fetchDateTransactions(selectedDate.value)
|
||||
}
|
||||
@@ -275,7 +275,7 @@ onBeforeUnmount(() => {
|
||||
})
|
||||
|
||||
// 当有交易被新增/修改/批量更新时刷新
|
||||
const onGlobalTransactionsChanged = (e) => {
|
||||
const onGlobalTransactionsChanged = () => {
|
||||
if (selectedDate.value) {
|
||||
fetchDateTransactions(selectedDate.value)
|
||||
}
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
title="批量分类"
|
||||
left-text="返回"
|
||||
left-arrow
|
||||
@click-left="handleBack"
|
||||
placeholder
|
||||
placeholder
|
||||
@click-left="handleBack"
|
||||
/>
|
||||
|
||||
<div class="scroll-content">
|
||||
@@ -65,7 +65,7 @@ const loadUnclassifiedCount = async () => {
|
||||
}
|
||||
|
||||
// 处理数据加载完成
|
||||
const handleDataLoaded = ({ groups, total, finished: isFinished }) => {
|
||||
const handleDataLoaded = ({ groups, finished: isFinished }) => {
|
||||
hasData.value = groups.length > 0
|
||||
finished.value = isFinished
|
||||
}
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
:title="navTitle"
|
||||
left-text="返回"
|
||||
left-arrow
|
||||
@click-left="handleBack"
|
||||
placeholder
|
||||
placeholder
|
||||
@click-left="handleBack"
|
||||
/>
|
||||
|
||||
<div class="scroll-content">
|
||||
@@ -29,8 +29,8 @@
|
||||
<van-tag
|
||||
type="primary"
|
||||
closeable
|
||||
@close="handleBackToRoot"
|
||||
style="margin-left: 16px;"
|
||||
@close="handleBackToRoot"
|
||||
>
|
||||
{{ currentTypeName }}
|
||||
</van-tag>
|
||||
|
||||
@@ -102,9 +102,9 @@
|
||||
:finished="true"
|
||||
:show-checkbox="true"
|
||||
:selected-ids="selectedIds"
|
||||
:show-delete="false"
|
||||
@update:selected-ids="updateSelectedIds"
|
||||
@click="handleRecordClick"
|
||||
:show-delete="false"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -33,8 +33,8 @@
|
||||
:loading="classifying"
|
||||
:disabled="selectedCount === 0"
|
||||
round
|
||||
@click="startClassify"
|
||||
class="action-btn"
|
||||
@click="startClassify"
|
||||
>
|
||||
{{ classifying ? '分类中...' : `开始分类 (${selectedCount}组)` }}
|
||||
</van-button>
|
||||
@@ -43,8 +43,8 @@
|
||||
type="success"
|
||||
:disabled="!hasChanges || classifying"
|
||||
round
|
||||
@click="saveClassifications"
|
||||
class="action-btn"
|
||||
@click="saveClassifications"
|
||||
>
|
||||
保存分类
|
||||
</van-button>
|
||||
@@ -91,7 +91,7 @@ const loadUnclassifiedCount = async () => {
|
||||
}
|
||||
|
||||
// 处理数据加载完成
|
||||
const handleDataLoaded = ({ groups, total }) => {
|
||||
const handleDataLoaded = ({ total }) => {
|
||||
totalGroups.value = total
|
||||
// 默认全选所有分组
|
||||
if (groupListRef.value) {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<template>
|
||||
<!-- eslint-disable vue/no-v-html -->
|
||||
<template>
|
||||
<div class="page-container-flex">
|
||||
<!-- 下拉刷新区域 -->
|
||||
<van-pull-refresh v-model="refreshing" @refresh="onRefresh">
|
||||
@@ -27,7 +28,7 @@
|
||||
<template #value>
|
||||
<div class="email-info">
|
||||
<div class="email-date">{{ formatDate(email.receivedDate) }}</div>
|
||||
<div class="bill-count" v-if="email.transactionCount > 0">
|
||||
<div v-if="email.transactionCount > 0" class="bill-count">
|
||||
<span style="font-size: 12px;">已解析{{ email.transactionCount }}条账单</span>
|
||||
</div>
|
||||
|
||||
@@ -79,19 +80,19 @@
|
||||
<van-cell title="接收时间" :value="formatDate(currentEmail.ReceivedDate || currentEmail.receivedDate)" />
|
||||
<van-cell title="记录时间" :value="formatDate(currentEmail.CreateTime || currentEmail.createTime)" />
|
||||
<van-cell
|
||||
v-if="(currentEmail.TransactionCount || currentEmail.transactionCount || 0) > 0"
|
||||
title="已解析账单数"
|
||||
:value="`${currentEmail.TransactionCount || currentEmail.transactionCount || 0}条`"
|
||||
:value="`${currentEmail.TransactionCount || currentEmail.transactionCount || 0}条`"
|
||||
is-link
|
||||
@click="viewTransactions"
|
||||
v-if="(currentEmail.TransactionCount || currentEmail.transactionCount || 0) > 0"
|
||||
/>
|
||||
</van-cell-group>
|
||||
<div class="email-content">
|
||||
<h4 style="margin-left: 10px;">邮件内容</h4>
|
||||
<div
|
||||
v-if="currentEmail.htmlBody"
|
||||
v-html="currentEmail.htmlBody"
|
||||
class="content-body html-content"
|
||||
class="content-body html-content"
|
||||
v-html="currentEmail.htmlBody"
|
||||
></div>
|
||||
<div
|
||||
v-else-if="currentEmail.body"
|
||||
@@ -453,6 +454,8 @@ const formatDate = (dateString) => {
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
|
||||
onMounted(() => {
|
||||
loadData(true)
|
||||
})
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
title="查看日志"
|
||||
left-text="返回"
|
||||
left-arrow
|
||||
@click-left="handleBack"
|
||||
placeholder
|
||||
placeholder
|
||||
@click-left="handleBack"
|
||||
/>
|
||||
|
||||
<div class="scroll-content">
|
||||
@@ -38,8 +38,8 @@
|
||||
v-model:loading="loading"
|
||||
:finished="finished"
|
||||
finished-text="没有更多了"
|
||||
@load="onLoad"
|
||||
class="log-list"
|
||||
@load="onLoad"
|
||||
>
|
||||
<div
|
||||
v-for="(log, index) in logList"
|
||||
|
||||
@@ -21,8 +21,8 @@
|
||||
block
|
||||
round
|
||||
:loading="loading"
|
||||
@click="handleLogin"
|
||||
class="login-button"
|
||||
@click="handleLogin"
|
||||
>
|
||||
登录
|
||||
</van-button>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<template>
|
||||
<!-- eslint-disable vue/no-v-html -->
|
||||
<template>
|
||||
<div class="page-container-flex">
|
||||
<van-nav-bar v-if="!isComponent" title="消息中心">
|
||||
<template #right>
|
||||
@@ -49,7 +50,11 @@
|
||||
height="50%"
|
||||
:closeable="true"
|
||||
>
|
||||
<div v-if="currentMessage.messageType === 2" class="detail-content" v-html="currentMessage.content">
|
||||
<div
|
||||
v-if="currentMessage.messageType === 2"
|
||||
class="detail-content"
|
||||
v-html="currentMessage.content"
|
||||
>
|
||||
</div>
|
||||
<div v-else class="detail-content">
|
||||
{{ currentMessage.content }}
|
||||
@@ -207,12 +212,6 @@ const handleMarkAllRead = () => {
|
||||
onMounted(() => {
|
||||
// onLoad 会由 van-list 自动触发
|
||||
});
|
||||
const props = defineProps({
|
||||
isComponent: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
});
|
||||
|
||||
defineExpose({
|
||||
handleMarkAllRead
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
:title="navTitle"
|
||||
left-text="返回"
|
||||
left-arrow
|
||||
@click-left="handleBack"
|
||||
placeholder
|
||||
placeholder
|
||||
@click-left="handleBack"
|
||||
/>
|
||||
|
||||
<!-- 下拉刷新区域 -->
|
||||
@@ -20,10 +20,10 @@
|
||||
v-model:loading="loading"
|
||||
:finished="finished"
|
||||
finished-text="没有更多了"
|
||||
@load="onLoad"
|
||||
class="periodic-list"
|
||||
@load="onLoad"
|
||||
>
|
||||
<van-cell-group inset v-for="item in periodicList" :key="item.id" class="periodic-item">
|
||||
<van-cell-group v-for="item in periodicList" :key="item.id" inset class="periodic-item">
|
||||
<van-swipe-cell>
|
||||
<div @click="editPeriodic(item)">
|
||||
<van-cell :title="item.reason || '无摘要'" :label="getPeriodicTypeText(item)">
|
||||
@@ -99,8 +99,8 @@
|
||||
name="periodicType"
|
||||
label="周期"
|
||||
placeholder="请选择周期类型"
|
||||
@click="showPeriodicTypePicker = true"
|
||||
:rules="[{ required: true, message: '请选择周期类型' }]"
|
||||
@click="showPeriodicTypePicker = true"
|
||||
/>
|
||||
|
||||
<!-- 每周配置 -->
|
||||
@@ -112,8 +112,8 @@
|
||||
name="weekdays"
|
||||
label="星期"
|
||||
placeholder="请选择星期几"
|
||||
@click="showWeekdaysPicker = true"
|
||||
:rules="[{ required: true, message: '请选择星期几' }]"
|
||||
@click="showWeekdaysPicker = true"
|
||||
/>
|
||||
|
||||
<!-- 每月配置 -->
|
||||
@@ -125,8 +125,8 @@
|
||||
name="monthDays"
|
||||
label="日期"
|
||||
placeholder="请选择每月的日期"
|
||||
@click="showMonthDaysPicker = true"
|
||||
:rules="[{ required: true, message: '请选择日期' }]"
|
||||
@click="showMonthDaysPicker = true"
|
||||
/>
|
||||
|
||||
<!-- 每季度配置 -->
|
||||
@@ -225,7 +225,7 @@
|
||||
</van-cell-group>
|
||||
</van-form>
|
||||
<template #footer>
|
||||
<van-button round block type="primary" @click="submit" :loading="submitting">
|
||||
<van-button round block type="primary" :loading="submitting" @click="submit">
|
||||
{{ isEdit ? '更新' : '确认添加' }}
|
||||
</van-button>
|
||||
</template>
|
||||
@@ -267,13 +267,11 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive, onMounted } from 'vue'
|
||||
import { ref, reactive } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { showToast, showConfirmDialog } from 'vant'
|
||||
import {
|
||||
getPeriodicList,
|
||||
createPeriodic,
|
||||
updatePeriodic,
|
||||
deletePeriodic as deletePeriodicApi,
|
||||
togglePeriodicEnabled
|
||||
} from '@/api/transactionPeriodic'
|
||||
@@ -643,80 +641,6 @@ const handleAddClassify = async (categoryName) => {
|
||||
}
|
||||
}
|
||||
|
||||
// 提交表单
|
||||
const onSubmit = async () => {
|
||||
try {
|
||||
submitting.value = true
|
||||
|
||||
// 构建周期配置
|
||||
let periodicConfig = ''
|
||||
switch (form.periodicType) {
|
||||
case 1: // 每周
|
||||
if (!form.weekdays.length) {
|
||||
showToast('请选择星期几')
|
||||
return
|
||||
}
|
||||
periodicConfig = form.weekdays.join(',')
|
||||
break
|
||||
case 2: // 每月
|
||||
if (!form.monthDays.length) {
|
||||
showToast('请选择日期')
|
||||
return
|
||||
}
|
||||
periodicConfig = form.monthDays.join(',')
|
||||
break
|
||||
case 3: // 每季度
|
||||
if (!form.quarterDay) {
|
||||
showToast('请输入季度开始后第几天')
|
||||
return
|
||||
}
|
||||
periodicConfig = form.quarterDay
|
||||
break
|
||||
case 4: // 每年
|
||||
if (!form.yearDay) {
|
||||
showToast('请输入年开始后第几天')
|
||||
return
|
||||
}
|
||||
periodicConfig = form.yearDay
|
||||
break
|
||||
}
|
||||
|
||||
const data = {
|
||||
periodicType: form.periodicType,
|
||||
periodicConfig: periodicConfig,
|
||||
amount: parseFloat(form.amount),
|
||||
type: form.type,
|
||||
classify: form.classify || '',
|
||||
reason: form.reason || ''
|
||||
}
|
||||
|
||||
let response
|
||||
if (isEdit.value) {
|
||||
data.id = form.id
|
||||
data.isEnabled = true
|
||||
response = await updatePeriodic(data)
|
||||
} else {
|
||||
response = await createPeriodic(data)
|
||||
}
|
||||
|
||||
if (response.success) {
|
||||
showToast(isEdit.value ? '更新成功' : '添加成功')
|
||||
dialogVisible.value = false
|
||||
loadData(true)
|
||||
} else {
|
||||
showToast(response.message || (isEdit.value ? '更新失败' : '添加失败'))
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('提交出错:', error)
|
||||
showToast((isEdit.value ? '更新' : '添加') + '失败')
|
||||
} finally {
|
||||
submitting.value = false
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
// van-list 会自动触发 onLoad
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
@@ -30,10 +30,10 @@
|
||||
<van-cell-group inset>
|
||||
<van-cell title="开启消息通知">
|
||||
<template #right-icon>
|
||||
<van-switch v-model="notificationEnabled" @change="handleNotificationToggle" size="24" :loading="notificationLoading" />
|
||||
<van-switch v-model="notificationEnabled" size="24" :loading="notificationLoading" @change="handleNotificationToggle" />
|
||||
</template>
|
||||
</van-cell>
|
||||
<van-cell title="测试通知" is-link @click="handleTestNotification" v-if="notificationEnabled" />
|
||||
<van-cell v-if="notificationEnabled" title="测试通知" is-link @click="handleTestNotification" />
|
||||
</van-cell-group>
|
||||
|
||||
<div class="detail-header" style="padding-bottom: 5px;">
|
||||
|
||||
@@ -23,8 +23,8 @@
|
||||
icon="arrow"
|
||||
plain
|
||||
size="small"
|
||||
@click="changeMonth(1)"
|
||||
:disabled="isCurrentMonth"
|
||||
@click="changeMonth(1)"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -69,7 +69,7 @@
|
||||
</div>
|
||||
|
||||
<!-- 环形图区域 -->
|
||||
<div class="chart-container" v-if="expenseCategoriesView.length > 0">
|
||||
<div v-if="expenseCategoriesView.length > 0" class="chart-container">
|
||||
<div class="ring-chart">
|
||||
<svg viewBox="0 0 200 200" class="ring-svg">
|
||||
<circle
|
||||
@@ -95,7 +95,7 @@
|
||||
</div>
|
||||
|
||||
<!-- 分类列表 -->
|
||||
<div class="category-list" v-if="expenseCategoriesView.length > 0">
|
||||
<div v-if="expenseCategoriesView.length > 0" class="category-list">
|
||||
<div
|
||||
v-for="(category) in expenseCategoriesView"
|
||||
:key="category.classify"
|
||||
@@ -125,7 +125,7 @@
|
||||
</div>
|
||||
|
||||
<!-- 收入分类统计 -->
|
||||
<div class="common-card" v-if="incomeCategoriesView.length > 0">
|
||||
<div v-if="incomeCategoriesView.length > 0" class="common-card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">收入分类统计</h3>
|
||||
<van-tag type="success" size="medium">{{ incomeCategoriesView.length }}类</van-tag>
|
||||
@@ -155,7 +155,7 @@
|
||||
</div>
|
||||
|
||||
<!-- 不计收支分类统计 -->
|
||||
<div class="common-card" v-if="noneCategoriesView.length > 0">
|
||||
<div v-if="noneCategoriesView.length > 0" class="common-card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">不计收支分类统计</h3>
|
||||
<van-tag type="info" size="medium">{{ noneCategoriesView.length }}类</van-tag>
|
||||
@@ -202,7 +202,7 @@
|
||||
class="bar expense-bar"
|
||||
:style="{ height: getBarHeight(item.expense, maxTrendValue) }"
|
||||
>
|
||||
<div class="bar-value" v-if="item.expense > 0">
|
||||
<div v-if="item.expense > 0" class="bar-value">
|
||||
{{ formatShortMoney(item.expense) }}
|
||||
</div>
|
||||
</div>
|
||||
@@ -210,7 +210,7 @@
|
||||
class="bar income-bar"
|
||||
:style="{ height: getBarHeight(item.income, maxTrendValue) }"
|
||||
>
|
||||
<div class="bar-value" v-if="item.income > 0">
|
||||
<div v-if="item.income > 0" class="bar-value">
|
||||
{{ formatShortMoney(item.income) }}
|
||||
</div>
|
||||
</div>
|
||||
@@ -285,10 +285,10 @@
|
||||
>
|
||||
<template #header-actions>
|
||||
<SmartClassifyButton
|
||||
ref="smartClassifyButtonRef"
|
||||
v-if="isUnclassified"
|
||||
ref="smartClassifyButtonRef"
|
||||
:transactions="categoryBills"
|
||||
:onBeforeClassify="beforeSmartClassify"
|
||||
:on-before-classify="beforeSmartClassify"
|
||||
@save="onSmartClassifySave"
|
||||
@notify-doned-transaction-id="handleNotifiedTransactionId"
|
||||
/>
|
||||
|
||||
@@ -41,9 +41,9 @@
|
||||
<van-search
|
||||
v-model="searchKeyword"
|
||||
placeholder="搜索交易摘要、来源、卡号、分类"
|
||||
shape="round"
|
||||
@update:model-value="onSearchChange"
|
||||
@clear="onSearchClear"
|
||||
shape="round"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user