2025-12-25 11:20:56 +08:00
|
|
|
|
<template>
|
2025-12-26 17:29:17 +08:00
|
|
|
|
<div class="page-container">
|
2025-12-25 17:41:36 +08:00
|
|
|
|
<van-nav-bar title="设置" placeholder/>
|
2025-12-26 17:29:17 +08:00
|
|
|
|
<div class="detail-header" style="padding-bottom: 5px;">
|
2025-12-25 11:20:56 +08:00
|
|
|
|
<p>账单导入</p>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<van-cell-group inset>
|
|
|
|
|
|
<van-cell title="从支付宝导入" is-link @click="handleImportClick('Alipay')" />
|
|
|
|
|
|
<van-cell title="从微信导入" is-link @click="handleImportClick('WeChat')" />
|
|
|
|
|
|
</van-cell-group>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 隐藏的文件选择器 -->
|
|
|
|
|
|
<input ref="fileInputRef" type="file" accept=".csv,.xlsx,.xls" style="display: none" @change="handleFileChange" />
|
|
|
|
|
|
|
2025-12-26 17:29:17 +08:00
|
|
|
|
<div class="detail-header" style="padding-bottom: 5px;">
|
2025-12-25 18:49:19 +08:00
|
|
|
|
<p>分类处理</p>
|
2025-12-25 11:20:56 +08:00
|
|
|
|
</div>
|
2025-12-25 18:49:19 +08:00
|
|
|
|
<van-cell-group inset>
|
2025-12-26 15:21:31 +08:00
|
|
|
|
<van-cell title="分类管理" is-link @click="handleEditClassification" />
|
2025-12-25 18:49:19 +08:00
|
|
|
|
<van-cell title="批量分类" is-link @click="handleBatchClassification" />
|
2025-12-25 15:40:50 +08:00
|
|
|
|
<van-cell title="智能分类" is-link @click="handleSmartClassification" />
|
2025-12-26 15:21:31 +08:00
|
|
|
|
<van-cell title="自然语言分类" is-link @click="handleNaturalLanguageClassification" />
|
2025-12-25 11:20:56 +08:00
|
|
|
|
</van-cell-group>
|
2025-12-26 17:29:17 +08:00
|
|
|
|
<div class="detail-header" style="padding-bottom: 5px;">
|
2025-12-25 13:27:23 +08:00
|
|
|
|
<p>账户</p>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<van-cell-group inset>
|
|
|
|
|
|
<van-cell title="退出登录" is-link @click="handleLogout" />
|
|
|
|
|
|
</van-cell-group>
|
2025-12-25 11:20:56 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<script setup>
|
|
|
|
|
|
import { ref } from 'vue'
|
2025-12-25 13:27:23 +08:00
|
|
|
|
import { useRouter } from 'vue-router'
|
|
|
|
|
|
import { showLoadingToast, showSuccessToast, showToast, closeToast, showConfirmDialog } from 'vant'
|
2025-12-25 11:20:56 +08:00
|
|
|
|
import { uploadBillFile } from '@/api/billImport'
|
2025-12-25 13:27:23 +08:00
|
|
|
|
import { useAuthStore } from '@/stores/auth'
|
2025-12-25 11:20:56 +08:00
|
|
|
|
|
2025-12-25 13:27:23 +08:00
|
|
|
|
const router = useRouter()
|
|
|
|
|
|
const authStore = useAuthStore()
|
2025-12-25 11:20:56 +08:00
|
|
|
|
const fileInputRef = ref(null)
|
|
|
|
|
|
const currentType = ref('')
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 处理导入按钮点击
|
|
|
|
|
|
*/
|
|
|
|
|
|
const handleImportClick = (type) => {
|
|
|
|
|
|
currentType.value = type
|
|
|
|
|
|
// 触发文件选择
|
|
|
|
|
|
fileInputRef.value?.click()
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 处理文件选择
|
|
|
|
|
|
*/
|
|
|
|
|
|
const handleFileChange = async (event) => {
|
|
|
|
|
|
const file = event.target.files?.[0]
|
|
|
|
|
|
if (!file) {
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 验证文件类型
|
|
|
|
|
|
const validTypes = ['text/csv', 'application/vnd.ms-excel', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet']
|
|
|
|
|
|
if (!validTypes.includes(file.type)) {
|
|
|
|
|
|
showToast('请选择 CSV 或 Excel 文件')
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 验证文件大小(限制为 10MB)
|
|
|
|
|
|
const maxSize = 10 * 1024 * 1024
|
|
|
|
|
|
if (file.size > maxSize) {
|
|
|
|
|
|
showToast('文件大小不能超过 10MB')
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
// 显示加载提示
|
|
|
|
|
|
showLoadingToast({
|
|
|
|
|
|
message: '上传中...',
|
|
|
|
|
|
forbidClick: true,
|
|
|
|
|
|
duration: 0
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
// 上传文件
|
|
|
|
|
|
const typeName = currentType.value === 'Alipay' ? '支付宝' : '微信'
|
|
|
|
|
|
const { success, message } = await uploadBillFile(file, currentType.value)
|
|
|
|
|
|
|
|
|
|
|
|
if (!success) {
|
|
|
|
|
|
showToast(message || `${typeName}账单导入失败`)
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
showSuccessToast(message || `${typeName}账单导入成功`)
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('上传失败:', error)
|
|
|
|
|
|
showToast('上传失败: ' + (error.message || '未知错误'))
|
|
|
|
|
|
}
|
|
|
|
|
|
finally {
|
|
|
|
|
|
closeToast()
|
|
|
|
|
|
// 清空文件输入,允许重复选择同一文件
|
|
|
|
|
|
event.target.value = ''
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-12-25 13:27:23 +08:00
|
|
|
|
|
2025-12-26 15:21:31 +08:00
|
|
|
|
const handleEditClassification = () => {
|
|
|
|
|
|
router.push({ name: 'classification-edit' })
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const handleBatchClassification = () => {
|
|
|
|
|
|
router.push({ name: 'classification-batch' })
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-25 15:40:50 +08:00
|
|
|
|
const handleSmartClassification = () => {
|
|
|
|
|
|
router.push({ name: 'smart-classification' })
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-26 15:21:31 +08:00
|
|
|
|
const handleNaturalLanguageClassification = () => {
|
|
|
|
|
|
router.push({ name: 'classification-nlp' })
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-25 13:27:23 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 处理退出登录
|
|
|
|
|
|
*/
|
|
|
|
|
|
const handleLogout = async () => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
await showConfirmDialog({
|
|
|
|
|
|
title: '提示',
|
|
|
|
|
|
message: '确定要退出登录吗?',
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
authStore.logout()
|
|
|
|
|
|
showSuccessToast('已退出登录')
|
|
|
|
|
|
router.push({ name: 'login' })
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('取消退出登录:', error)
|
|
|
|
|
|
showToast('已取消退出登录')
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-12-25 11:20:56 +08:00
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<style scoped>
|
|
|
|
|
|
/* 页面背景色 */
|
|
|
|
|
|
:deep(body) {
|
|
|
|
|
|
background-color: #f5f5f5;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@media (prefers-color-scheme: dark) {
|
|
|
|
|
|
:deep(body) {
|
|
|
|
|
|
background-color: #1a1a1a;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 增加卡片对比度 */
|
|
|
|
|
|
:deep(.van-cell-group--inset) {
|
|
|
|
|
|
background-color: #ffffff;
|
|
|
|
|
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@media (prefers-color-scheme: dark) {
|
|
|
|
|
|
:deep(.van-cell-group--inset) {
|
|
|
|
|
|
background-color: #2c2c2c;
|
|
|
|
|
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.detail-header {
|
|
|
|
|
|
padding: 16px 16px 5px 16px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.detail-header p {
|
|
|
|
|
|
margin: 0;
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
color: #969799;
|
|
|
|
|
|
font-weight: normal;
|
|
|
|
|
|
}
|
|
|
|
|
|
</style>
|