Files
EmailBill/Web/src/components/Budget/BudgetEditPopup.vue
孙诚 65f7316c82
All checks were successful
Docker Build & Deploy / Build Docker Image (push) Successful in 34s
Docker Build & Deploy / Deploy to Production (push) Successful in 8s
Docker Build & Deploy / Cleanup Dangling Images (push) Successful in 0s
Docker Build & Deploy / WeChat Notification (push) Successful in 3s
新增不记额收支
2026-01-15 10:53:05 +08:00

211 lines
5.5 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<PopupContainer
v-model="visible"
:title="isEdit ? `编辑${getCategoryName(form.category)}预算` : `新增${getCategoryName(form.category)}预算`"
height="75%"
>
<div class="add-budget-form">
<van-form>
<van-cell-group inset>
<van-field
v-model="form.name"
name="name"
label="预算名称"
placeholder="例如:每月餐饮、年度奖金"
:rules="[{ required: true, message: '请填写预算名称' }]"
/>
<!-- 新增不记额预算复选框 -->
<van-field label="不记额预算">
<template #input>
<van-checkbox v-model="form.noLimit" @update:model-value="onNoLimitChange">不记额预算仅限年度</van-checkbox>
</template>
</van-field>
<van-field name="type" label="统计周期">
<template #input>
<van-radio-group
v-model="form.type"
direction="horizontal"
:disabled="isEdit || form.noLimit"
>
<van-radio :name="BudgetPeriodType.Month"></van-radio>
<van-radio :name="BudgetPeriodType.Year"></van-radio>
</van-radio-group>
</template>
</van-field>
<!-- 仅当未选中"不记额预算"时显示预算金额 -->
<van-field
v-if="!form.noLimit"
v-model="form.limit"
type="number"
name="limit"
label="预算金额"
placeholder="0.00"
:rules="[{ required: true, message: '请填写预算金额' }]"
>
<template #extra>
<span></span>
</template>
</van-field>
<van-field label="相关分类">
<template #input>
<div v-if="form.selectedCategories.length === 0" style="color: var(--van-text-color-3);">可多选分类</div>
<div v-else class="selected-categories">
<span class="ellipsis-text">
{{ form.selectedCategories.join('、') }}
</span>
</div>
</template>
</van-field>
<ClassifySelector
v-model="form.selectedCategories"
:type="budgetType"
multiple
:show-add="false"
:show-clear="false"
/>
</van-cell-group>
</van-form>
</div>
<template #footer>
<van-button block round type="primary" @click="onSubmit">保存预算</van-button>
</template>
</PopupContainer>
</template>
<script setup>
import { ref, reactive, computed } from 'vue'
import { showToast } from 'vant'
import { createBudget, updateBudget } from '@/api/budget'
import { BudgetPeriodType, BudgetCategory } from '@/constants/enums'
import PopupContainer from '@/components/PopupContainer.vue'
import ClassifySelector from '@/components/ClassifySelector.vue'
const emit = defineEmits(['success'])
const visible = ref(false)
const isEdit = ref(false)
const form = reactive({
id: undefined,
name: '',
type: BudgetPeriodType.Month,
category: BudgetCategory.Expense,
limit: '',
selectedCategories: [],
noLimit: false // 新增字段
})
const open = ({
data,
isEditFlag,
category
}) => {
if(category === undefined) {
showToast('缺少必要参数category')
return
}
isEdit.value = isEditFlag
if (data) {
Object.assign(form, {
id: data.id,
name: data.name,
type: data.type,
category: category,
limit: data.limit,
selectedCategories: data.selectedCategories ? [...data.selectedCategories] : [],
noLimit: data.noLimit || false // 新增
})
} else {
Object.assign(form, {
id: undefined,
name: '',
type: BudgetPeriodType.Month,
category: category,
limit: '',
selectedCategories: [],
noLimit: false // 新增
})
}
visible.value = true
}
defineExpose({
open
})
const budgetType = computed(() => {
return form.category === BudgetCategory.Expense ? 0 : (form.category === BudgetCategory.Income ? 1 : 2)
})
const onSubmit = async () => {
try {
const data = {
...form,
limit: form.noLimit ? 0 : parseFloat(form.limit), // 不记额时金额为0
selectedCategories: form.selectedCategories,
noLimit: form.noLimit // 新增
}
const res = form.id ? await updateBudget(data) : await createBudget(data)
if (res.success) {
showToast('保存成功')
visible.value = false
emit('success')
}
} catch (err) {
showToast(err.message || '保存失败')
console.error('保存预算失败', err)
}
}
const getCategoryName = (category) => {
switch(category) {
case BudgetCategory.Expense:
return '支出'
case BudgetCategory.Income:
return '收入'
case BudgetCategory.Savings:
return '存款'
default:
return ''
}
}
const onNoLimitChange = (value) => {
if (value) {
// 选中不记额时,自动设为年度预算
form.type = BudgetPeriodType.Year
}
}
</script>
<style scoped>
.add-budget-form {
padding: 20px 0;
}
.selected-categories {
display: flex;
align-items: center;
padding: 4px 0;
width: 100%;
overflow: hidden;
}
.ellipsis-text {
font-size: 14px;
color: var(--van-text-color);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
width: 100%;
}
.no-data {
font-size: 13px;
color: var(--van-text-color-2);
padding: 8px 16px;
}
</style>