Skip to content

Commit

Permalink
后台卡类型管理
Browse files Browse the repository at this point in the history
  • Loading branch information
Yurunsoft committed Aug 29, 2023
1 parent 7da6198 commit 5d1d3e7
Show file tree
Hide file tree
Showing 12 changed files with 598 additions and 16 deletions.
13 changes: 12 additions & 1 deletion admin/src/router/modules/card.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,16 @@ const card: AuthRoute.Route = {
path: '/card',
component: 'basic',
children: [
{
name: 'card_type_list',
path: '/card/type/list',
component: 'self',
meta: {
title: '卡类型管理',
requiresAuth: true,
icon: 'ic:round-manage-accounts'
}
},
{
name: 'card_memberCardDetails',
path: '/card/memberCardDetails',
Expand Down Expand Up @@ -30,7 +40,8 @@ const card: AuthRoute.Route = {
meta: {
title: '卡交易明细',
requiresAuth: true,
icon: 'ic:round-manage-accounts'
icon: 'ic:round-manage-accounts',
hide: true
}
}
],
Expand Down
33 changes: 33 additions & 0 deletions admin/src/service/api/card.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,3 +69,36 @@ export const fetchCardDetails = async (
}
});
};

export const fetchCardTypeList = async (enable: boolean | undefined = undefined, page = 1, limit = 15) => {
let enableParam;
if (enable !== undefined) {
enableParam = enable ? '1' : '0';
}
return request.get<Card.CardTypeListResponse>('/admin/card/type/list', {
params: {
enable: enableParam,
page,
limit
}
});
};

export const createCardType = async (name: string, amount: number, expireSeconds: number, enable = true) => {
return request.post<Api.BaseResponse>('/admin/card/type/create', {
name,
amount,
expireSeconds,
enable
});
};

export const updateCardType = async (
id: number,
data: { name?: string; amount?: number; expireSeconds?: number; enable?: boolean }
) => {
return request.post<Api.BaseResponse>('/admin/card/type/update', {
id,
...data
});
};
15 changes: 15 additions & 0 deletions admin/src/typings/card.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,4 +82,19 @@ declare namespace Card {
list: CardDetail[];
} & Api.BaseResponse &
Api.PaginationResponse;

interface CardType {
id: number;
name: string;
amount: number;
expireSeconds: number;
enable: boolean;
system: boolean;
createTime: number;
}

type CardTypeListResponse = {
list: CardType[];
} & Api.BaseResponse &
Api.PaginationResponse;
}
3 changes: 3 additions & 0 deletions admin/src/typings/page-route.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ declare namespace PageRoute {
| 'card_details'
| 'card_list'
| 'card_memberCardDetails'
| 'card_type'
| 'card_type_list'
| 'chat'
| 'chat_list'
| 'chat_message'
Expand Down Expand Up @@ -69,6 +71,7 @@ declare namespace PageRoute {
| 'card_details'
| 'card_list'
| 'card_memberCardDetails'
| 'card_type_list'
| 'chat_list'
| 'chat_message_list'
| 'dashboard_analysis'
Expand Down
2 changes: 1 addition & 1 deletion admin/src/views/card/list/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
class="!w-[140px]"
:options="[
{
text: '不限',
text: '全部',
value: undefined
},
{
Expand Down
178 changes: 178 additions & 0 deletions admin/src/views/card/type_list/components/edit-type-modal.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
<template>
<n-modal v-model:show="modalVisible" preset="card" :title="title" class="w-700px max-w-full">
<n-form ref="formRef" label-placement="left" :label-width="80" :model="formModel" :rules="rules">
<n-grid cols="1 s:2" :x-gap="18" item-responsive responsive="screen">
<n-form-item-grid-item label="名称" path="name">
<n-input v-model:value="formModel.name" />
</n-form-item-grid-item>
<n-form-item-grid-item label="初始余额" path="amount">
<n-input-number v-model:value="formModel.amount" :precision="0" />
</n-form-item-grid-item>
<n-form-item-grid-item label="有效期(秒)" path="expireSeconds">
<n-input-number
v-model:value="formModel.expireSeconds"
:min="0"
:precision="0"
:disabled="expireSecondsDisable"
@update:value="
value => {
if (formModel.expireSeconds == 0) {
expireSecondsDisable = true;
}
}
"
/>
</n-form-item-grid-item>
<n-form-item-grid-item label="永久">
<n-checkbox
v-model:checked="expireSecondsDisable"
@update:checked="
value => {
if (expireSecondsDisable) {
formModel.expireSeconds = 0;
}
}
"
></n-checkbox>
</n-form-item-grid-item>
<n-form-item-grid-item label="状态" path="password">
<n-switch v-model:value="formModel.enable">
<template #checked>启用</template>
<template #unchecked>禁用</template>
</n-switch>
</n-form-item-grid-item>
</n-grid>
<n-space class="w-full pt-16px" :size="24" justify="end">
<n-button class="w-72px" @click="closeModal">取消</n-button>
<n-button class="w-72px" type="primary" @click="handleSubmit">确定</n-button>
</n-space>
</n-form>
</n-modal>
</template>

<script setup lang="ts">
import { ref, computed, reactive, watch } from 'vue';
import type { FormInst, FormItemRule } from 'naive-ui';
import { createRequiredFormRule } from '@/utils';
import { createCardType, updateCardType } from '~/src/service';
export interface Props {
/** 弹窗可见性 */
visible: boolean;
/**
* 弹窗类型
* add: 新增
* edit: 编辑
*/
type?: 'add' | 'edit';
/** 编辑的表格行数据 */
editData?: Card.CardType | null;
}
export type ModalType = NonNullable<Props['type']>;
defineOptions({ name: 'TableActionModal' });
const props = withDefaults(defineProps<Props>(), {
type: 'add',
editData: null
});
interface Emits {
(e: 'update:visible', visible: boolean): void;
}
const emit = defineEmits<Emits>();
const expireSecondsDisable = ref(false);
const modalVisible = computed({
get() {
return props.visible;
},
set(visible) {
emit('update:visible', visible);
}
});
const closeModal = () => {
modalVisible.value = false;
};
const title = computed(() => {
const titles: Record<ModalType, string> = {
add: '新建卡类型',
edit: '编辑卡类型'
};
return titles[props.type];
});
const formRef = ref<HTMLElement & FormInst>();
type FormModel = Pick<Card.CardType, 'name' | 'amount' | 'expireSeconds' | 'enable'>;
const formModel = reactive<FormModel>(createDefaultFormModel());
const constRules: Record<string, FormItemRule | FormItemRule[]> = {
account: createRequiredFormRule('请输入用户名'),
nickname: createRequiredFormRule('请输入昵称')
};
const rules = computed(() => {
const result = { ...constRules };
return result;
});
function createDefaultFormModel(): FormModel {
return {
name: '',
amount: 0,
expireSeconds: 0,
enable: true
};
}
function handleUpdateFormModel(model: Partial<FormModel>) {
Object.assign(formModel, { ...createDefaultFormModel(), ...model });
expireSecondsDisable.value = formModel.expireSeconds === 0;
}
function handleUpdateFormModelByModalType() {
const handlers: Record<ModalType, () => void> = {
add: () => {
const defaultFormModel = createDefaultFormModel();
handleUpdateFormModel(defaultFormModel);
},
edit: () => {
if (props.editData) {
handleUpdateFormModel(props.editData);
}
}
};
handlers[props.type]();
}
async function handleSubmit() {
await formRef.value?.validate();
let response;
if (props.type === 'add') {
response = await createCardType(formModel.name, formModel.amount, formModel.expireSeconds, formModel.enable);
} else if (props.editData) {
response = await updateCardType(props.editData.id, formModel);
} else {
throw new Error('未知错误');
}
const { data } = response;
if (data?.code === 0) closeModal();
}
watch(
() => props.visible,
newValue => {
if (newValue) {
handleUpdateFormModelByModalType();
}
}
);
</script>

<style scoped></style>
Loading

0 comments on commit 5d1d3e7

Please sign in to comment.