添加消息类型枚举和相关字段,优化消息记录服务的添加方法,更新多个组件以支持新增分类对话框
This commit is contained in:
@@ -1,5 +1,24 @@
|
|||||||
namespace Entity;
|
namespace Entity;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 消息类型
|
||||||
|
/// </summary>
|
||||||
|
public enum MessageType
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 文本
|
||||||
|
/// </summary>
|
||||||
|
Text = 0,
|
||||||
|
/// <summary>
|
||||||
|
/// 跳转URL
|
||||||
|
/// </summary>
|
||||||
|
Url = 1,
|
||||||
|
/// <summary>
|
||||||
|
/// HTML内容
|
||||||
|
/// </summary>
|
||||||
|
Html = 2
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 消息实体
|
/// 消息实体
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -15,6 +34,11 @@ public class MessageRecord : BaseEntity
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public string Content { get; set; } = string.Empty;
|
public string Content { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 消息类型
|
||||||
|
/// </summary>
|
||||||
|
public MessageType MessageType { get; set; } = MessageType.Text;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 是否已读
|
/// 是否已读
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ public interface IMessageRecordService
|
|||||||
Task<(IEnumerable<MessageRecord> List, long Total)> GetPagedListAsync(int pageIndex, int pageSize);
|
Task<(IEnumerable<MessageRecord> List, long Total)> GetPagedListAsync(int pageIndex, int pageSize);
|
||||||
Task<MessageRecord?> GetByIdAsync(long id);
|
Task<MessageRecord?> GetByIdAsync(long id);
|
||||||
Task<bool> AddAsync(MessageRecord message);
|
Task<bool> AddAsync(MessageRecord message);
|
||||||
Task<bool> AddAsync(string title, string content);
|
Task<bool> AddAsync(string title, string content, MessageType type = MessageType.Text);
|
||||||
Task<bool> MarkAsReadAsync(long id);
|
Task<bool> MarkAsReadAsync(long id);
|
||||||
Task<bool> MarkAllAsReadAsync();
|
Task<bool> MarkAllAsReadAsync();
|
||||||
Task<bool> DeleteAsync(long id);
|
Task<bool> DeleteAsync(long id);
|
||||||
@@ -29,12 +29,13 @@ public class MessageRecordService(IMessageRecordRepository messageRepo, INotific
|
|||||||
return await messageRepo.AddAsync(message);
|
return await messageRepo.AddAsync(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<bool> AddAsync(string title, string content)
|
public async Task<bool> AddAsync(string title, string content, MessageType type = MessageType.Text)
|
||||||
{
|
{
|
||||||
var message = new MessageRecord
|
var message = new MessageRecord
|
||||||
{
|
{
|
||||||
Title = title,
|
Title = title,
|
||||||
Content = content,
|
Content = content,
|
||||||
|
MessageType = type,
|
||||||
IsRead = false
|
IsRead = false
|
||||||
};
|
};
|
||||||
var result = await messageRepo.AddAsync(message);
|
var result = await messageRepo.AddAsync(message);
|
||||||
|
|||||||
43
Web/src/components/AddClassifyDialog.vue
Normal file
43
Web/src/components/AddClassifyDialog.vue
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
<template>
|
||||||
|
<van-dialog
|
||||||
|
v-model:show="show"
|
||||||
|
title="新增交易分类"
|
||||||
|
show-cancel-button
|
||||||
|
@confirm="handleConfirm"
|
||||||
|
>
|
||||||
|
<van-field v-model="classifyName" placeholder="请输入新的交易分类" />
|
||||||
|
</van-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref } from 'vue'
|
||||||
|
import { showToast } from 'vant'
|
||||||
|
|
||||||
|
const emit = defineEmits(['confirm'])
|
||||||
|
|
||||||
|
const show = ref(false)
|
||||||
|
const classifyName = ref('')
|
||||||
|
|
||||||
|
// 打开弹窗
|
||||||
|
const open = () => {
|
||||||
|
classifyName.value = ''
|
||||||
|
show.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// 确认
|
||||||
|
const handleConfirm = () => {
|
||||||
|
if (!classifyName.value.trim()) {
|
||||||
|
showToast('请输入分类名称')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
emit('confirm', classifyName.value.trim())
|
||||||
|
show.value = false
|
||||||
|
classifyName.value = ''
|
||||||
|
}
|
||||||
|
|
||||||
|
// 暴露方法给父组件
|
||||||
|
defineExpose({
|
||||||
|
open
|
||||||
|
})
|
||||||
|
</script>
|
||||||
@@ -36,7 +36,7 @@
|
|||||||
<!-- 交易类型 -->
|
<!-- 交易类型 -->
|
||||||
<van-field name="type" label="类型">
|
<van-field name="type" label="类型">
|
||||||
<template #input>
|
<template #input>
|
||||||
<van-radio-group v-model="form.type" direction="horizontal">
|
<van-radio-group v-model="form.type" direction="horizontal" @change="handleTypeChange">
|
||||||
<van-radio :name="0">支出</van-radio>
|
<van-radio :name="0">支出</van-radio>
|
||||||
<van-radio :name="1">收入</van-radio>
|
<van-radio :name="1">收入</van-radio>
|
||||||
<van-radio :name="2">不计</van-radio>
|
<van-radio :name="2">不计</van-radio>
|
||||||
@@ -58,7 +58,7 @@
|
|||||||
type="success"
|
type="success"
|
||||||
size="small"
|
size="small"
|
||||||
class="classify-btn"
|
class="classify-btn"
|
||||||
@click="showAddClassify = true"
|
@click="addClassifyDialogRef.open()"
|
||||||
>
|
>
|
||||||
+ 新增
|
+ 新增
|
||||||
</van-button>
|
</van-button>
|
||||||
@@ -84,14 +84,10 @@
|
|||||||
</van-form>
|
</van-form>
|
||||||
|
|
||||||
<!-- 新增分类对话框 -->
|
<!-- 新增分类对话框 -->
|
||||||
<van-dialog
|
<AddClassifyDialog
|
||||||
v-model:show="showAddClassify"
|
ref="addClassifyDialogRef"
|
||||||
title="新增交易分类"
|
@confirm="handleAddClassify"
|
||||||
show-cancel-button
|
/>
|
||||||
@confirm="addNewClassify"
|
|
||||||
>
|
|
||||||
<van-field v-model="newClassify" placeholder="请输入新的交易分类" />
|
|
||||||
</van-dialog>
|
|
||||||
|
|
||||||
<!-- 日期选择弹窗 -->
|
<!-- 日期选择弹窗 -->
|
||||||
<van-popup v-model:show="showDatePicker" position="bottom" round>
|
<van-popup v-model:show="showDatePicker" position="bottom" round>
|
||||||
@@ -119,6 +115,7 @@
|
|||||||
import { ref, onMounted, watch } from 'vue'
|
import { ref, onMounted, watch } from 'vue'
|
||||||
import { showToast } from 'vant'
|
import { showToast } from 'vant'
|
||||||
import dayjs from 'dayjs'
|
import dayjs from 'dayjs'
|
||||||
|
import AddClassifyDialog from '@/components/AddClassifyDialog.vue'
|
||||||
import { getCategoryList, createCategory } from '@/api/transactionCategory'
|
import { getCategoryList, createCategory } from '@/api/transactionCategory'
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
@@ -138,6 +135,8 @@ const props = defineProps({
|
|||||||
|
|
||||||
const emit = defineEmits(['submit'])
|
const emit = defineEmits(['submit'])
|
||||||
|
|
||||||
|
const addClassifyDialogRef = ref()
|
||||||
|
|
||||||
// 表单数据
|
// 表单数据
|
||||||
const form = ref({
|
const form = ref({
|
||||||
type: 0, // 0: 支出, 1: 收入, 2: 不计
|
type: 0, // 0: 支出, 1: 收入, 2: 不计
|
||||||
@@ -153,8 +152,6 @@ const categoryName = ref('')
|
|||||||
// 弹窗控制
|
// 弹窗控制
|
||||||
const showDatePicker = ref(false)
|
const showDatePicker = ref(false)
|
||||||
const showTimePicker = ref(false)
|
const showTimePicker = ref(false)
|
||||||
const showAddClassify = ref(false)
|
|
||||||
const newClassify = ref('')
|
|
||||||
|
|
||||||
// 选择器数据
|
// 选择器数据
|
||||||
const categoryList = ref([])
|
const categoryList = ref([])
|
||||||
@@ -214,37 +211,6 @@ watch(() => props.initialData, () => {
|
|||||||
initForm()
|
initForm()
|
||||||
}, { deep: true })
|
}, { deep: true })
|
||||||
|
|
||||||
// 监听交易类型变化,重新加载分类
|
|
||||||
watch(() => form.value.type, (newVal) => {
|
|
||||||
// 如果是初始化过程中导致的类型变化,可能不需要清空分类(如果已经匹配好了)
|
|
||||||
// 但如果是用户手动切换,应该清空
|
|
||||||
// 这里简单处理:如果是用户切换,通常需要重新选择。
|
|
||||||
// 为了避免初始化时的冲突,可以在 initForm 里处理好。
|
|
||||||
// 这里主要响应用户操作。
|
|
||||||
|
|
||||||
// 只有当当前分类不属于新类型时才清空?或者总是清空?
|
|
||||||
// 原逻辑是总是清空。
|
|
||||||
// 但是如果是 initForm 引起的,我们不希望清空。
|
|
||||||
// 暂时保持原逻辑,但在 initForm 里调用 loadClassifyList 后再设置 categoryName
|
|
||||||
|
|
||||||
// 简单的做法:在 watch 内部判断是否正在初始化?比较麻烦。
|
|
||||||
// 或者:只在用户点击 radio 时触发?
|
|
||||||
// watch 是最稳妥的,但要注意 initForm 里的顺序。
|
|
||||||
// 在 initForm 里,我们先设置 type,这会触发 watch。
|
|
||||||
// 所以 initForm 里的 loadClassifyList 可能会被 watch 里的覆盖。
|
|
||||||
// 让我们调整一下策略:
|
|
||||||
// 不在 watch 里加载,而是由 radio change 事件触发?
|
|
||||||
// 或者在 watch 里判断,如果 categoryName 已经有值且符合当前类型(这个很难判断),就不清空。
|
|
||||||
|
|
||||||
// 实际上,initForm 里设置 type 后,watch 会执行。
|
|
||||||
// watch 会清空 categoryName。
|
|
||||||
// 所以 initForm 里设置 type 后,再设置 categoryName 是没用的,除非 watch 是异步的或者我们在 nextTick 设置。
|
|
||||||
|
|
||||||
// 让我们修改 watch 逻辑,或者在 initForm 里处理。
|
|
||||||
// 更好的方式:
|
|
||||||
// 移除 watch,改为在 radio group 上 @change="handleTypeChange"
|
|
||||||
})
|
|
||||||
|
|
||||||
const handleTypeChange = (newType) => {
|
const handleTypeChange = (newType) => {
|
||||||
categoryName.value = ''
|
categoryName.value = ''
|
||||||
form.value.categoryId = null
|
form.value.categoryId = null
|
||||||
@@ -267,15 +233,8 @@ const selectClassify = (item) => {
|
|||||||
form.value.categoryId = item.id
|
form.value.categoryId = item.id
|
||||||
}
|
}
|
||||||
|
|
||||||
const addNewClassify = async () => {
|
const handleAddClassify = async (name) => {
|
||||||
if (!newClassify.value.trim()) {
|
|
||||||
showToast('请输入分类名称')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const name = newClassify.value.trim()
|
|
||||||
|
|
||||||
// 调用API创建分类
|
// 调用API创建分类
|
||||||
const response = await createCategory({
|
const response = await createCategory({
|
||||||
name: name,
|
name: name,
|
||||||
@@ -297,9 +256,6 @@ const addNewClassify = async () => {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('创建分类出错:', error)
|
console.error('创建分类出错:', error)
|
||||||
showToast('创建分类失败')
|
showToast('创建分类失败')
|
||||||
} finally {
|
|
||||||
newClassify.value = ''
|
|
||||||
showAddClassify.value = false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -30,6 +30,11 @@
|
|||||||
<div class="popup-scroll-content">
|
<div class="popup-scroll-content">
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- 底部页脚,固定不可滚动 -->
|
||||||
|
<div v-if="slots.footer" class="popup-footer-fixed">
|
||||||
|
<slot name="footer"></slot>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</van-popup>
|
</van-popup>
|
||||||
</template>
|
</template>
|
||||||
@@ -150,4 +155,11 @@ const hasActions = computed(() => !!slots['header-actions'])
|
|||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
-webkit-overflow-scrolling: touch;
|
-webkit-overflow-scrolling: touch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.popup-footer-fixed {
|
||||||
|
flex-shrink: 0;
|
||||||
|
border-top: 1px solid var(--van-border-color, #ebedf0);
|
||||||
|
background-color: var(--van-background-2, #f7f8fa);
|
||||||
|
padding: 12px 16px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -87,12 +87,10 @@
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<!-- 批量设置对话框 -->
|
<!-- 批量设置对话框 -->
|
||||||
<van-dialog
|
<PopupContainer
|
||||||
v-model:show="showBatchDialog"
|
v-model="showBatchDialog"
|
||||||
title="批量设置分类"
|
title="批量设置分类"
|
||||||
:show-cancel-button="true"
|
height="60%"
|
||||||
@confirm="handleConfirmBatchUpdate"
|
|
||||||
@cancel="resetBatchForm"
|
|
||||||
>
|
>
|
||||||
<van-form ref="batchFormRef" class="setting-form">
|
<van-form ref="batchFormRef" class="setting-form">
|
||||||
<van-cell-group inset>
|
<van-cell-group inset>
|
||||||
@@ -137,7 +135,7 @@
|
|||||||
type="success"
|
type="success"
|
||||||
size="small"
|
size="small"
|
||||||
class="classify-btn"
|
class="classify-btn"
|
||||||
@click="showAddClassify = true"
|
@click="addClassifyDialogRef.open()"
|
||||||
>
|
>
|
||||||
+ 新增
|
+ 新增
|
||||||
</van-button>
|
</van-button>
|
||||||
@@ -163,17 +161,23 @@
|
|||||||
</div>
|
</div>
|
||||||
</van-cell-group>
|
</van-cell-group>
|
||||||
</van-form>
|
</van-form>
|
||||||
</van-dialog>
|
<template #footer>
|
||||||
|
<van-button
|
||||||
|
round
|
||||||
|
block
|
||||||
|
type="primary"
|
||||||
|
@click="handleConfirmBatchUpdate"
|
||||||
|
>
|
||||||
|
确定
|
||||||
|
</van-button>
|
||||||
|
</template>
|
||||||
|
</PopupContainer>
|
||||||
|
|
||||||
<!-- 新增分类对话框 -->
|
<!-- 新增分类对话框 -->
|
||||||
<van-dialog
|
<AddClassifyDialog
|
||||||
v-model:show="showAddClassify"
|
ref="addClassifyDialogRef"
|
||||||
title="新增交易分类"
|
@confirm="handleAddClassify"
|
||||||
show-cancel-button
|
/>
|
||||||
@confirm="addNewClassify"
|
|
||||||
>
|
|
||||||
<van-field v-model="newClassify" placeholder="请输入新的交易分类" />
|
|
||||||
</van-dialog>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -188,6 +192,7 @@ import {
|
|||||||
} from 'vant'
|
} from 'vant'
|
||||||
import { getReasonGroups, batchUpdateByReason, getTransactionList } from '@/api/transactionRecord'
|
import { getReasonGroups, batchUpdateByReason, getTransactionList } from '@/api/transactionRecord'
|
||||||
import { getCategoryList, createCategory } from '@/api/transactionCategory'
|
import { getCategoryList, createCategory } from '@/api/transactionCategory'
|
||||||
|
import AddClassifyDialog from './AddClassifyDialog.vue'
|
||||||
import TransactionList from './TransactionList.vue'
|
import TransactionList from './TransactionList.vue'
|
||||||
import TransactionDetail from './TransactionDetail.vue'
|
import TransactionDetail from './TransactionDetail.vue'
|
||||||
import PopupContainer from './PopupContainer.vue'
|
import PopupContainer from './PopupContainer.vue'
|
||||||
@@ -201,7 +206,7 @@ const props = defineProps({
|
|||||||
// 每页数量
|
// 每页数量
|
||||||
pageSize: {
|
pageSize: {
|
||||||
type: Number,
|
type: Number,
|
||||||
default: 3 // TODO 测试写小一点
|
default: 20
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -232,10 +237,9 @@ const transactionPageSize = ref(20)
|
|||||||
|
|
||||||
// 批量分类相关状态
|
// 批量分类相关状态
|
||||||
const showBatchDialog = ref(false)
|
const showBatchDialog = ref(false)
|
||||||
const showAddClassify = ref(false)
|
|
||||||
const batchFormRef = ref(null)
|
const batchFormRef = ref(null)
|
||||||
const batchGroup = ref(null)
|
const batchGroup = ref(null)
|
||||||
const newClassify = ref('')
|
const addClassifyDialogRef = ref()
|
||||||
const batchForm = ref({
|
const batchForm = ref({
|
||||||
type: null,
|
type: null,
|
||||||
typeName: '',
|
typeName: '',
|
||||||
@@ -380,20 +384,13 @@ const selectClassify = (classify) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 新增分类
|
// 新增分类
|
||||||
const addNewClassify = async () => {
|
const handleAddClassify = async (categoryName) => {
|
||||||
if (!newClassify.value.trim()) {
|
|
||||||
showToast('请输入分类名称')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (batchForm.value.type === null) {
|
if (batchForm.value.type === null) {
|
||||||
showToast('请先选择交易类型')
|
showToast('请先选择交易类型')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const categoryName = newClassify.value.trim()
|
|
||||||
|
|
||||||
// 调用API创建分类
|
// 调用API创建分类
|
||||||
const response = await createCategory({
|
const response = await createCategory({
|
||||||
name: categoryName,
|
name: categoryName,
|
||||||
@@ -411,9 +408,6 @@ const addNewClassify = async () => {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('创建分类出错:', error)
|
console.error('创建分类出错:', error)
|
||||||
showToast('创建分类失败')
|
showToast('创建分类失败')
|
||||||
} finally {
|
|
||||||
newClassify.value = ''
|
|
||||||
showAddClassify.value = false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -711,6 +705,17 @@ defineExpose({
|
|||||||
height: 28px;
|
height: 28px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.popup-actions {
|
||||||
|
display: flex;
|
||||||
|
gap: 8px;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.popup-actions .van-button {
|
||||||
|
flex: 1;
|
||||||
|
min-width: auto;
|
||||||
|
}
|
||||||
|
|
||||||
.group-info {
|
.group-info {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|||||||
@@ -9,8 +9,7 @@
|
|||||||
<van-button size="small" type="primary" plain @click="handleOffsetClick">抵账</van-button>
|
<van-button size="small" type="primary" plain @click="handleOffsetClick">抵账</van-button>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<div v-if="transaction">
|
<van-form style="margin-top: 12px;">
|
||||||
<van-form @submit="onSubmit" style="margin-top: 12px;">
|
|
||||||
<van-cell-group inset>
|
<van-cell-group inset>
|
||||||
<van-cell title="交易时间" :value="formatDate(transaction.occurredAt)" />
|
<van-cell title="交易时间" :value="formatDate(transaction.occurredAt)" />
|
||||||
<van-cell title="记录时间" :value="formatDate(transaction.createTime)" />
|
<van-cell title="记录时间" :value="formatDate(transaction.createTime)" />
|
||||||
@@ -68,7 +67,7 @@
|
|||||||
type="success"
|
type="success"
|
||||||
size="small"
|
size="small"
|
||||||
class="classify-btn"
|
class="classify-btn"
|
||||||
@click="showAddClassify = true"
|
@click="addClassifyDialogRef.open()"
|
||||||
>
|
>
|
||||||
+ 新增
|
+ 新增
|
||||||
</van-button>
|
</van-button>
|
||||||
@@ -93,25 +92,26 @@
|
|||||||
</van-button>
|
</van-button>
|
||||||
</div>
|
</div>
|
||||||
</van-cell-group>
|
</van-cell-group>
|
||||||
|
</van-form>
|
||||||
|
|
||||||
<div style="margin: 16px;">
|
<template #footer>
|
||||||
<van-button round block type="primary" native-type="submit" :loading="submitting">
|
<van-button
|
||||||
保存修改
|
round
|
||||||
</van-button>
|
block
|
||||||
</div>
|
type="primary"
|
||||||
</van-form>
|
:loading="submitting"
|
||||||
</div>
|
@click="onSubmit"
|
||||||
|
>
|
||||||
|
保存修改
|
||||||
|
</van-button>
|
||||||
|
</template>
|
||||||
</PopupContainer>
|
</PopupContainer>
|
||||||
|
|
||||||
<!-- 新增分类对话框 -->
|
<!-- 新增分类对话框 -->
|
||||||
<van-dialog
|
<AddClassifyDialog
|
||||||
v-model:show="showAddClassify"
|
ref="addClassifyDialogRef"
|
||||||
title="新增交易分类"
|
@confirm="handleAddClassify"
|
||||||
show-cancel-button
|
/>
|
||||||
@confirm="addNewClassify"
|
|
||||||
>
|
|
||||||
<van-field v-model="newClassify" placeholder="请输入新的交易分类" />
|
|
||||||
</van-dialog>
|
|
||||||
|
|
||||||
<!-- 抵账候选列表弹窗 -->
|
<!-- 抵账候选列表弹窗 -->
|
||||||
<PopupContainer
|
<PopupContainer
|
||||||
@@ -138,6 +138,7 @@
|
|||||||
import { ref, reactive, watch, defineProps, defineEmits } from 'vue'
|
import { ref, reactive, watch, defineProps, defineEmits } from 'vue'
|
||||||
import { showToast, showConfirmDialog } from 'vant'
|
import { showToast, showConfirmDialog } from 'vant'
|
||||||
import PopupContainer from '@/components/PopupContainer.vue'
|
import PopupContainer from '@/components/PopupContainer.vue'
|
||||||
|
import AddClassifyDialog from '@/components/AddClassifyDialog.vue'
|
||||||
import { updateTransaction, getCandidatesForOffset, offsetTransactions } from '@/api/transactionRecord'
|
import { updateTransaction, getCandidatesForOffset, offsetTransactions } from '@/api/transactionRecord'
|
||||||
import { getCategoryList, createCategory } from '@/api/transactionCategory'
|
import { getCategoryList, createCategory } from '@/api/transactionCategory'
|
||||||
|
|
||||||
@@ -156,11 +157,10 @@ const emit = defineEmits(['update:show', 'save'])
|
|||||||
|
|
||||||
const visible = ref(false)
|
const visible = ref(false)
|
||||||
const submitting = ref(false)
|
const submitting = ref(false)
|
||||||
|
const addClassifyDialogRef = ref()
|
||||||
|
|
||||||
// 分类相关
|
// 分类相关
|
||||||
const classifyColumns = ref([])
|
const classifyColumns = ref([])
|
||||||
const showAddClassify = ref(false)
|
|
||||||
const newClassify = ref('')
|
|
||||||
|
|
||||||
// 编辑表单
|
// 编辑表单
|
||||||
const editForm = reactive({
|
const editForm = reactive({
|
||||||
@@ -264,15 +264,8 @@ const selectClassify = (classify) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 新增分类
|
// 新增分类
|
||||||
const addNewClassify = async () => {
|
const handleAddClassify = async (categoryName) => {
|
||||||
if (!newClassify.value.trim()) {
|
|
||||||
showToast('请输入分类名称')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const categoryName = newClassify.value.trim()
|
|
||||||
|
|
||||||
// 调用API创建分类
|
// 调用API创建分类
|
||||||
const response = await createCategory({
|
const response = await createCategory({
|
||||||
name: categoryName,
|
name: categoryName,
|
||||||
@@ -290,9 +283,6 @@ const addNewClassify = async () => {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('创建分类出错:', error)
|
console.error('创建分类出错:', error)
|
||||||
showToast('创建分类失败')
|
showToast('创建分类失败')
|
||||||
} finally {
|
|
||||||
newClassify.value = ''
|
|
||||||
showAddClassify.value = false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -32,6 +32,7 @@
|
|||||||
type="primary"
|
type="primary"
|
||||||
:loading="classifying"
|
:loading="classifying"
|
||||||
:disabled="selectedCount === 0"
|
:disabled="selectedCount === 0"
|
||||||
|
round
|
||||||
@click="startClassify"
|
@click="startClassify"
|
||||||
class="action-btn"
|
class="action-btn"
|
||||||
>
|
>
|
||||||
@@ -41,6 +42,7 @@
|
|||||||
<van-button
|
<van-button
|
||||||
type="success"
|
type="success"
|
||||||
:disabled="!hasChanges || classifying"
|
:disabled="!hasChanges || classifying"
|
||||||
|
round
|
||||||
@click="saveClassifications"
|
@click="saveClassifications"
|
||||||
class="action-btn"
|
class="action-btn"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -49,7 +49,9 @@
|
|||||||
height="50%"
|
height="50%"
|
||||||
:closeable="true"
|
:closeable="true"
|
||||||
>
|
>
|
||||||
<div class="detail-content">
|
<div v-if="currentMessage.messageType === 2" class="detail-content" v-html="currentMessage.content">
|
||||||
|
</div>
|
||||||
|
<div v-else class="detail-content">
|
||||||
{{ currentMessage.content }}
|
{{ currentMessage.content }}
|
||||||
</div>
|
</div>
|
||||||
</PopupContainer>
|
</PopupContainer>
|
||||||
@@ -126,9 +128,6 @@ const onRefresh = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const viewDetail = async (item) => {
|
const viewDetail = async (item) => {
|
||||||
currentMessage.value = item;
|
|
||||||
detailVisible.value = true;
|
|
||||||
|
|
||||||
if (!item.isRead) {
|
if (!item.isRead) {
|
||||||
try {
|
try {
|
||||||
await markAsRead(item.id);
|
await markAsRead(item.id);
|
||||||
@@ -138,6 +137,18 @@ const viewDetail = async (item) => {
|
|||||||
console.error('标记已读失败', error);
|
console.error('标记已读失败', error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (item.messageType === 1) {
|
||||||
|
if (item.content.startsWith('http')) {
|
||||||
|
window.open(item.content, '_blank');
|
||||||
|
} else {
|
||||||
|
showToast('无效的URL');
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
currentMessage.value = item;
|
||||||
|
detailVisible.value = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleDelete = (item) => {
|
const handleDelete = (item) => {
|
||||||
|
|||||||
@@ -90,7 +90,7 @@
|
|||||||
:title="isEdit ? '编辑周期账单' : '新增周期账单'"
|
:title="isEdit ? '编辑周期账单' : '新增周期账单'"
|
||||||
height="85%"
|
height="85%"
|
||||||
>
|
>
|
||||||
<van-form @submit="onSubmit">
|
<van-form>
|
||||||
<van-cell-group inset title="周期设置">
|
<van-cell-group inset title="周期设置">
|
||||||
<van-field
|
<van-field
|
||||||
v-model="form.periodicTypeText"
|
v-model="form.periodicTypeText"
|
||||||
@@ -198,7 +198,7 @@
|
|||||||
type="success"
|
type="success"
|
||||||
size="small"
|
size="small"
|
||||||
class="classify-btn"
|
class="classify-btn"
|
||||||
@click="showAddClassify = true"
|
@click="addClassifyDialogRef.open()"
|
||||||
>
|
>
|
||||||
+ 新增
|
+ 新增
|
||||||
</van-button>
|
</van-button>
|
||||||
@@ -223,13 +223,12 @@
|
|||||||
</van-button>
|
</van-button>
|
||||||
</div>
|
</div>
|
||||||
</van-cell-group>
|
</van-cell-group>
|
||||||
|
|
||||||
<div style="margin: 16px;">
|
|
||||||
<van-button round block type="primary" native-type="submit" :loading="submitting">
|
|
||||||
{{ isEdit ? '更新' : '确认添加' }}
|
|
||||||
</van-button>
|
|
||||||
</div>
|
|
||||||
</van-form>
|
</van-form>
|
||||||
|
<template #footer>
|
||||||
|
<van-button round block type="primary" @click="submit" :loading="submitting">
|
||||||
|
{{ isEdit ? '更新' : '确认添加' }}
|
||||||
|
</van-button>
|
||||||
|
</template>
|
||||||
</PopupContainer>
|
</PopupContainer>
|
||||||
|
|
||||||
<!-- 周期类型选择器 -->
|
<!-- 周期类型选择器 -->
|
||||||
@@ -260,14 +259,10 @@
|
|||||||
</van-popup>
|
</van-popup>
|
||||||
|
|
||||||
<!-- 新增分类对话框 -->
|
<!-- 新增分类对话框 -->
|
||||||
<van-dialog
|
<AddClassifyDialog
|
||||||
v-model:show="showAddClassify"
|
ref="addClassifyDialogRef"
|
||||||
title="新增交易分类"
|
@confirm="handleAddClassify"
|
||||||
show-cancel-button
|
/>
|
||||||
@confirm="addNewClassify"
|
|
||||||
>
|
|
||||||
<van-field v-model="newClassify" placeholder="请输入新的交易分类" />
|
|
||||||
</van-dialog>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -284,9 +279,11 @@ import {
|
|||||||
} from '@/api/transactionPeriodic'
|
} from '@/api/transactionPeriodic'
|
||||||
import { getCategoryList, createCategory } from '@/api/transactionCategory'
|
import { getCategoryList, createCategory } from '@/api/transactionCategory'
|
||||||
import PopupContainer from '@/components/PopupContainer.vue'
|
import PopupContainer from '@/components/PopupContainer.vue'
|
||||||
|
import AddClassifyDialog from '@/components/AddClassifyDialog.vue'
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const navTitle = ref('周期账单')
|
const navTitle = ref('周期账单')
|
||||||
|
const addClassifyDialogRef = ref()
|
||||||
|
|
||||||
const periodicList = ref([])
|
const periodicList = ref([])
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
@@ -303,8 +300,6 @@ const submitting = ref(false)
|
|||||||
const showPeriodicTypePicker = ref(false)
|
const showPeriodicTypePicker = ref(false)
|
||||||
const showWeekdaysPicker = ref(false)
|
const showWeekdaysPicker = ref(false)
|
||||||
const showMonthDaysPicker = ref(false)
|
const showMonthDaysPicker = ref(false)
|
||||||
const showAddClassify = ref(false)
|
|
||||||
const newClassify = ref('')
|
|
||||||
|
|
||||||
// 分类列表
|
// 分类列表
|
||||||
const classifyColumns = ref([])
|
const classifyColumns = ref([])
|
||||||
@@ -626,15 +621,8 @@ const clearClassify = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 新增分类
|
// 新增分类
|
||||||
const addNewClassify = async () => {
|
const handleAddClassify = async (categoryName) => {
|
||||||
if (!newClassify.value.trim()) {
|
|
||||||
showToast('请输入分类名称')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const categoryName = newClassify.value.trim()
|
|
||||||
|
|
||||||
// 调用API创建分类
|
// 调用API创建分类
|
||||||
const response = await createCategory({
|
const response = await createCategory({
|
||||||
name: categoryName,
|
name: categoryName,
|
||||||
@@ -652,9 +640,6 @@ const addNewClassify = async () => {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('创建分类出错:', error)
|
console.error('创建分类出错:', error)
|
||||||
showToast('创建分类失败')
|
showToast('创建分类失败')
|
||||||
} finally {
|
|
||||||
newClassify.value = ''
|
|
||||||
showAddClassify.value = false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user