2026-01-01 14:43:43 +08:00
|
|
|
|
<template>
|
|
|
|
|
|
<div>
|
2026-01-07 14:33:30 +08:00
|
|
|
|
<div v-if="!parseResult" class="input-section" style="margin: 12px 12px 0 16px;">
|
2026-01-01 14:43:43 +08:00
|
|
|
|
<van-field
|
|
|
|
|
|
v-model="text"
|
|
|
|
|
|
type="textarea"
|
|
|
|
|
|
rows="4"
|
|
|
|
|
|
placeholder="例如:1月3日 晚餐 45.5 美团"
|
|
|
|
|
|
class="bill-input"
|
|
|
|
|
|
:disabled="parsing || saving"
|
|
|
|
|
|
/>
|
|
|
|
|
|
<div class="actions">
|
|
|
|
|
|
<van-button
|
|
|
|
|
|
type="primary"
|
|
|
|
|
|
round
|
|
|
|
|
|
block
|
2026-01-07 14:33:30 +08:00
|
|
|
|
:loading="parsing"
|
2026-01-01 14:43:43 +08:00
|
|
|
|
:disabled="!text.trim()"
|
2026-01-07 14:33:30 +08:00
|
|
|
|
@click="handleParse"
|
2026-01-01 14:43:43 +08:00
|
|
|
|
>
|
|
|
|
|
|
智能解析
|
|
|
|
|
|
</van-button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div v-if="parseResult" class="result-section">
|
|
|
|
|
|
<BillForm
|
|
|
|
|
|
:initial-data="parseResult"
|
|
|
|
|
|
:loading="saving"
|
|
|
|
|
|
submit-text="确认保存"
|
|
|
|
|
|
@submit="handleSave"
|
|
|
|
|
|
>
|
|
|
|
|
|
<template #actions>
|
|
|
|
|
|
<van-button
|
|
|
|
|
|
plain
|
|
|
|
|
|
round
|
|
|
|
|
|
block
|
2026-01-07 14:33:30 +08:00
|
|
|
|
class="mt-2"
|
|
|
|
|
|
@click="parseResult = null"
|
2026-01-01 14:43:43 +08:00
|
|
|
|
>
|
|
|
|
|
|
重新输入
|
|
|
|
|
|
</van-button>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
</BillForm>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<script setup>
|
|
|
|
|
|
import { ref } from 'vue'
|
|
|
|
|
|
import { showToast } from 'vant'
|
|
|
|
|
|
import BillForm from './BillForm.vue'
|
|
|
|
|
|
import { createTransaction, parseOneLine } from '@/api/transactionRecord'
|
|
|
|
|
|
|
|
|
|
|
|
const emit = defineEmits(['success'])
|
|
|
|
|
|
|
|
|
|
|
|
const text = ref('')
|
|
|
|
|
|
const parsing = ref(false)
|
|
|
|
|
|
const saving = ref(false)
|
|
|
|
|
|
const parseResult = ref(null)
|
|
|
|
|
|
|
|
|
|
|
|
const handleParse = async () => {
|
|
|
|
|
|
if (!text.value.trim()) return
|
|
|
|
|
|
|
|
|
|
|
|
parsing.value = true
|
|
|
|
|
|
parseResult.value = null
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
const res = await parseOneLine(text.value)
|
|
|
|
|
|
if(!res.success){
|
|
|
|
|
|
throw new Error(res.message || '解析失败')
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
parseResult.value = res.data
|
|
|
|
|
|
} catch (err) {
|
|
|
|
|
|
console.error(err)
|
|
|
|
|
|
showToast('解析失败:' + err.message)
|
|
|
|
|
|
} finally {
|
|
|
|
|
|
parsing.value = false
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const handleSave = async (payload) => {
|
|
|
|
|
|
saving.value = true
|
|
|
|
|
|
try {
|
|
|
|
|
|
const res = await createTransaction(payload)
|
|
|
|
|
|
|
|
|
|
|
|
if (!res.success) {
|
|
|
|
|
|
throw new Error(res.message || '保存失败')
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
showToast('保存成功')
|
|
|
|
|
|
text.value = ''
|
|
|
|
|
|
parseResult.value = null
|
|
|
|
|
|
emit('success')
|
|
|
|
|
|
} catch (err) {
|
|
|
|
|
|
console.error(err)
|
|
|
|
|
|
showToast('保存失败:' + err.message)
|
|
|
|
|
|
} finally {
|
|
|
|
|
|
saving.value = false
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<style scoped>
|
|
|
|
|
|
.bill-input {
|
|
|
|
|
|
background-color: var(--van-background-2);
|
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
|
margin-bottom: 16px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.actions {
|
|
|
|
|
|
margin-top: 16px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.mt-2 {
|
|
|
|
|
|
margin-top: 8px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.preview-card {
|
|
|
|
|
|
margin-bottom: 16px;
|
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
border: 1px solid #ebedf0;
|
|
|
|
|
|
}
|
|
|
|
|
|
</style>
|