霖雨寺
This commit is contained in:
@@ -0,0 +1,223 @@
|
||||
<script setup lang="ts">
|
||||
import { DeleteOutlined, EditOutlined, PlusOutlined, ReloadOutlined } from '@ant-design/icons-vue';
|
||||
import { Modal, message } from 'ant-design-vue';
|
||||
import type { Rule } from 'ant-design-vue/es/form';
|
||||
import type { ColumnsType } from 'ant-design-vue/es/table';
|
||||
import { computed, onMounted, reactive, ref } from 'vue';
|
||||
|
||||
import {
|
||||
createRitualService,
|
||||
deleteRitualService,
|
||||
listRitualServices,
|
||||
updateRitualService,
|
||||
type RitualService,
|
||||
} from '@/api/rituals';
|
||||
|
||||
type RitualFormState = {
|
||||
id?: number;
|
||||
name: string;
|
||||
description: string;
|
||||
price: number;
|
||||
is_active: boolean;
|
||||
};
|
||||
|
||||
const rituals = ref<RitualService[]>([]);
|
||||
const loading = ref(false);
|
||||
const saving = ref(false);
|
||||
const modalOpen = ref(false);
|
||||
const formRef = ref();
|
||||
|
||||
const formState = reactive<RitualFormState>({
|
||||
name: '',
|
||||
description: '',
|
||||
price: 0,
|
||||
is_active: true,
|
||||
});
|
||||
|
||||
const isEditing = computed(() => formState.id !== undefined);
|
||||
const modalTitle = computed(() => (isEditing.value ? '编辑法事' : '新建法事'));
|
||||
|
||||
const columns: ColumnsType<RitualService> = [
|
||||
{ title: 'ID', dataIndex: 'id', width: 72 },
|
||||
{ title: '法事名称', dataIndex: 'name', width: 180 },
|
||||
{ title: '价格', dataIndex: 'price', width: 140 },
|
||||
{ title: '状态', dataIndex: 'is_active', width: 100 },
|
||||
{ title: '说明', dataIndex: 'description' },
|
||||
{ title: '操作', key: 'actions', width: 140, fixed: 'right' },
|
||||
];
|
||||
|
||||
const rules: Record<string, Rule[]> = {
|
||||
name: [{ required: true, message: '请输入法事名称', trigger: 'blur' }],
|
||||
price: [{ type: 'number', min: 0, message: '价格不能小于 0', trigger: 'change' }],
|
||||
};
|
||||
|
||||
function formatMoney(value: number) {
|
||||
return new Intl.NumberFormat('zh-CN', {
|
||||
currency: 'CNY',
|
||||
style: 'currency',
|
||||
}).format(value);
|
||||
}
|
||||
|
||||
function resetForm() {
|
||||
formState.id = undefined;
|
||||
formState.name = '';
|
||||
formState.description = '';
|
||||
formState.price = 0;
|
||||
formState.is_active = true;
|
||||
formRef.value?.clearValidate?.();
|
||||
}
|
||||
|
||||
async function fetchRituals() {
|
||||
loading.value = true;
|
||||
try {
|
||||
rituals.value = await listRitualServices();
|
||||
} catch (error) {
|
||||
message.error(error instanceof Error ? error.message : '加载法事失败,请先选择寺院');
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
function openCreateModal() {
|
||||
resetForm();
|
||||
modalOpen.value = true;
|
||||
}
|
||||
|
||||
function openEditModal(ritual: RitualService) {
|
||||
formState.id = ritual.id;
|
||||
formState.name = ritual.name;
|
||||
formState.description = ritual.description || '';
|
||||
formState.price = ritual.price;
|
||||
formState.is_active = ritual.is_active;
|
||||
modalOpen.value = true;
|
||||
}
|
||||
|
||||
async function submitForm() {
|
||||
await formRef.value?.validate?.();
|
||||
saving.value = true;
|
||||
try {
|
||||
const payload = {
|
||||
name: formState.name,
|
||||
description: formState.description || null,
|
||||
price: formState.price,
|
||||
is_active: formState.is_active,
|
||||
};
|
||||
|
||||
if (isEditing.value && formState.id !== undefined) {
|
||||
await updateRitualService(formState.id, payload);
|
||||
message.success('法事已更新');
|
||||
} else {
|
||||
await createRitualService(payload);
|
||||
message.success('法事已创建');
|
||||
}
|
||||
|
||||
modalOpen.value = false;
|
||||
resetForm();
|
||||
await fetchRituals();
|
||||
} catch (error) {
|
||||
message.error(error instanceof Error ? error.message : '保存法事失败');
|
||||
} finally {
|
||||
saving.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
function confirmDelete(ritual: RitualService) {
|
||||
Modal.confirm({
|
||||
title: '删除法事',
|
||||
content: `确认删除法事 ${ritual.name}?`,
|
||||
okText: '删除',
|
||||
okType: 'danger',
|
||||
cancelText: '取消',
|
||||
async onOk() {
|
||||
await deleteRitualService(ritual.id);
|
||||
message.success('法事已删除');
|
||||
await fetchRituals();
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
onMounted(fetchRituals);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<section class="workspace">
|
||||
<div class="page-heading">
|
||||
<h1>法事管理</h1>
|
||||
<a-space>
|
||||
<a-button :loading="loading" @click="fetchRituals">
|
||||
<template #icon><ReloadOutlined /></template>
|
||||
刷新
|
||||
</a-button>
|
||||
<a-button type="primary" @click="openCreateModal">
|
||||
<template #icon><PlusOutlined /></template>
|
||||
新建法事
|
||||
</a-button>
|
||||
</a-space>
|
||||
</div>
|
||||
|
||||
<a-table
|
||||
:columns="columns"
|
||||
:data-source="rituals"
|
||||
:loading="loading"
|
||||
:pagination="{ pageSize: 8, showSizeChanger: false }"
|
||||
bordered
|
||||
row-key="id"
|
||||
size="middle"
|
||||
>
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.dataIndex === 'price'">
|
||||
{{ formatMoney(record.price) }}
|
||||
</template>
|
||||
|
||||
<template v-if="column.dataIndex === 'description'">
|
||||
{{ record.description || '-' }}
|
||||
</template>
|
||||
|
||||
<template v-if="column.dataIndex === 'is_active'">
|
||||
<a-tag :color="record.is_active ? 'green' : 'default'">
|
||||
{{ record.is_active ? '启用' : '停用' }}
|
||||
</a-tag>
|
||||
</template>
|
||||
|
||||
<template v-if="column.key === 'actions'">
|
||||
<a-space>
|
||||
<a-tooltip title="编辑">
|
||||
<a-button type="text" @click="openEditModal(record)">
|
||||
<template #icon><EditOutlined /></template>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
<a-tooltip title="删除">
|
||||
<a-button type="text" danger @click="confirmDelete(record)">
|
||||
<template #icon><DeleteOutlined /></template>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
</a-space>
|
||||
</template>
|
||||
</template>
|
||||
</a-table>
|
||||
</section>
|
||||
|
||||
<a-modal
|
||||
v-model:open="modalOpen"
|
||||
:confirm-loading="saving"
|
||||
:title="modalTitle"
|
||||
ok-text="保存"
|
||||
cancel-text="取消"
|
||||
@ok="submitForm"
|
||||
>
|
||||
<a-form ref="formRef" :model="formState" :rules="rules" layout="vertical">
|
||||
<a-form-item label="法事名称" name="name">
|
||||
<a-input v-model:value="formState.name" placeholder="祈福法会" />
|
||||
</a-form-item>
|
||||
<a-form-item label="价格" name="price">
|
||||
<a-input-number v-model:value="formState.price" :min="0" :precision="2" addon-before="¥" class="full-width-control" />
|
||||
</a-form-item>
|
||||
<a-form-item label="说明" name="description">
|
||||
<a-textarea v-model:value="formState.description" :rows="3" />
|
||||
</a-form-item>
|
||||
<a-form-item label="状态" name="is_active">
|
||||
<a-switch v-model:checked="formState.is_active" checked-children="启用" un-checked-children="停用" />
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
</template>
|
||||
Reference in New Issue
Block a user