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 5d1d3e7 commit d582328
Show file tree
Hide file tree
Showing 13 changed files with 291 additions and 41 deletions.
21 changes: 19 additions & 2 deletions admin/src/service/api/card.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,25 @@ export const fetchMemberCardDetails = async (
export const fetchCardList = async (
memberId = 0,
type = 0,
expired: number | undefined = undefined,
activationed: boolean | undefined = undefined,
expired: boolean | undefined = undefined,
page = 1,
limit = 15
) => {
let activationedParam;
if (activationed !== undefined) {
activationedParam = activationed ? '1' : '0';
}
let expiredParam;
if (expired !== undefined) {
expiredParam = expired ? '1' : '0';
}
return request.get<Card.CardListResponse>('/admin/card/list', {
params: {
memberId,
type,
expired,
activationed: activationedParam,
expired: expiredParam,
page,
limit
}
Expand Down Expand Up @@ -102,3 +112,10 @@ export const updateCardType = async (
...data
});
};

export const generateCard = async (type: number, count: number) => {
return request.post<Card.GenerateCardResponse>('/admin/card/generate', {
type,
count
});
};
4 changes: 4 additions & 0 deletions admin/src/typings/card.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,4 +97,8 @@ declare namespace Card {
list: CardType[];
} & Api.BaseResponse &
Api.PaginationResponse;

type GenerateCardResponse = {
list: string[];
} & Api.BaseResponse;
}
94 changes: 94 additions & 0 deletions admin/src/views/card/list/components/generate-card-modal.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
<template>
<n-modal v-model:show="modalVisible" preset="card" title="批量生成卡" class="w-500px max-w-full">
<template v-if="showResult">
<n-input type="textarea" :value="result" rows="10"></n-input>
</template>
<template v-else>
<n-form ref="formRef" label-placement="left" :label-width="80" :model="formModel" :rules="rules">
<n-grid cols="1" :x-gap="18" item-responsive responsive="screen">
<n-form-item-grid-item label="生成数量" path="count">
<n-input-number v-model:value="formModel.count" :precision="0" />
</n-form-item-grid-item>
</n-grid>
</n-form>
</template>
<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-modal>
</template>

<script setup lang="ts">
import { computed, nextTick, ref, watch } from 'vue';
import type { FormInst, FormItemRule } from 'naive-ui';
import { createRequiredFormRule } from '~/src/utils';
import { generateCard } from '~/src/service';
export interface Props {
/** 弹窗可见性 */
visible: boolean;
cardType: number;
}
const props = defineProps<Props>();
interface Emits {
(e: 'update:visible', visible: boolean): void;
}
const emit = defineEmits<Emits>();
const formRef = ref<HTMLElement & FormInst>();
const modalVisible = computed({
get() {
return props.visible;
},
set(visible) {
emit('update:visible', visible);
}
});
const closeModal = () => {
modalVisible.value = false;
};
const rules: Record<string, FormItemRule | FormItemRule[]> = {
count: createRequiredFormRule('请输入数量')
};
const formModelDefault = {
count: 1
};
const formModel = ref(formModelDefault);
const showResult = ref(false);
const result = ref('');
async function handleSubmit() {
if (showResult.value) {
closeModal();
return;
}
await formRef.value?.validate();
const { data } = await generateCard(props.cardType, formModel.value.count);
if (data?.code === 0) {
nextTick(() => {
result.value = data.list.join('\r\n');
showResult.value = true;
});
window.$message?.info('生成成功');
}
}
watch(
() => props.visible,
newValue => {
if (newValue) {
showResult.value = false;
formModel.value = formModelDefault;
}
}
);
</script>
94 changes: 78 additions & 16 deletions admin/src/views/card/list/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
:options="[
{
text: '全部',
value: undefined
value: -1
},
{
text: '可用',
Expand All @@ -26,6 +26,28 @@
value-field="value"
/>
</n-form-item>
<n-form-item label="激活">
<n-select
v-model:value="listParams.activationed"
class="!w-[140px]"
:options="[
{
text: '全部',
value: -1
},
{
text: '未激活',
value: 0
},
{
text: '已激活',
value: 1
}
]"
label-field="text"
value-field="value"
/>
</n-form-item>
<n-form-item>
<n-button attr-type="submit" type="primary" @click="getTableData">
<n-icon :component="SearchSharp" size="20" />
Expand All @@ -34,6 +56,12 @@
</n-form-item>
</n-space>
</n-form>
<n-space class="py-12px" justify="space-between">
<n-button v-if="listParams.type > 0" type="primary" @click="handleGenerate">
<icon-ic-round-plus class="mr-4px text-20px" />
批量生成
</n-button>
</n-space>
<n-data-table
:columns="columns"
:data="tableData"
Expand All @@ -47,11 +75,16 @@
/>
</div>
</n-card>
<generate-card-modal
v-if="listParams.type > 0"
v-model:visible="showGenerateCardModal"
:card-type="listParams.type"
></generate-card-modal>
</div>
</template>

<script setup lang="tsx">
import { ref } from 'vue';
import { ref, watch } from 'vue';
import type { Ref } from 'vue';
import { useRoute } from 'vue-router';
import type { DataTableColumns } from 'naive-ui';
Expand All @@ -61,6 +94,7 @@ import { useLoading } from '@/hooks';
import { useEnums } from '~/src/store';
import { defaultPaginationProps } from '~/src/utils';
import { useRouterPush } from '~/src/composables';
import GenerateCardModal from './components/generate-card-modal.vue';
const { routerPush } = useRouterPush();
const route = useRoute();
Expand All @@ -70,7 +104,15 @@ const enums = ref<any>({});
const listParams = ref({
memberId: parseInt(route.query.memberId?.toString() ?? '0'),
expired: 0,
type: 0
activationed: -1,
type: parseInt(route.query.type?.toString() ?? '0')
});
const showGenerateCardModal = ref(false);
watch(showGenerateCardModal, () => {
if (!showGenerateCardModal.value) {
getTableData();
}
});
const pagination = defaultPaginationProps(getTableData);
Expand All @@ -88,7 +130,8 @@ async function getTableData() {
const { data } = await fetchCardList(
listParams.value.memberId,
listParams.value.type,
listParams.value.expired,
listParams.value.activationed >= 0 ? Boolean(listParams.value.activationed) : undefined,
listParams.value.expired >= 0 ? Boolean(listParams.value.expired) : undefined,
pagination.page,
pagination.pageSize
);
Expand Down Expand Up @@ -117,25 +160,29 @@ const columns: Ref<DataTableColumns<Card.Card>> = ref([
{
key: 'member',
title: '用户',
width: 140,
render: row => {
return (
<>
<p>
ID:{row.memberId} ({row.memberInfo.recordId})
</p>
<p>昵称:{row.memberInfo.nickname}</p>
</>
);
if (row.memberInfo)
return (
<>
<p>
ID:{row.memberId} ({row.memberInfo.recordId})
</p>
<p>昵称:{row.memberInfo.nickname}</p>
</>
);
return '';
}
},
{
title: '名称',
key: 'cardType.name'
key: 'cardType.name',
width: 100
},
{
title: '余额/面额',
key: 'amount',
minWidth: 250,
minWidth: 300,
render(row) {
if (row.type === 1) {
return row.leftAmountText;
Expand Down Expand Up @@ -164,16 +211,27 @@ const columns: Ref<DataTableColumns<Card.Card>> = ref([
);
}
},
{
title: '创建时间',
key: 'activationTime',
width: 200,
render(row) {
return new Date(row.createTime * 1000).toLocaleString();
}
},
{
title: '激活时间',
key: 'activationTime',
width: 200,
render(row) {
return new Date(row.activationTime * 1000).toLocaleString();
if (row.activationTime > 0) return new Date(row.activationTime * 1000).toLocaleString();
return '未激活';
}
},
{
title: '过期时间',
key: 'expireTime',
width: 250,
render(row) {
return row.expireTime > 0
? new Date(row.expireTime * 1000).toLocaleString() + (row.expired ? '(已过期)' : '')
Expand All @@ -183,7 +241,7 @@ const columns: Ref<DataTableColumns<Card.Card>> = ref([
{
key: 'actions',
title: '操作',
width: 160,
width: 100,
render: row => {
return (
<n-space>
Expand All @@ -204,6 +262,10 @@ function handleCardDetail(rowId: number) {
}
}
function handleGenerate() {
showGenerateCardModal.value = true;
}
async function init() {
enums.value = await useEnums(['BusinessType', 'OperationType']);
getTableData();
Expand Down
11 changes: 4 additions & 7 deletions admin/src/views/card/type_list/components/edit-type-modal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -112,14 +112,11 @@ type FormModel = Pick<Card.CardType, 'name' | 'amount' | 'expireSeconds' | 'enab
const formModel = reactive<FormModel>(createDefaultFormModel());
const constRules: Record<string, FormItemRule | FormItemRule[]> = {
account: createRequiredFormRule('请输入用户名'),
nickname: createRequiredFormRule('请输入昵称')
const rules: Record<string, FormItemRule | FormItemRule[]> = {
name: createRequiredFormRule('请输入名称'),
amount: createRequiredFormRule('请输入初始余额'),
expireSeconds: createRequiredFormRule('请输入有效期')
};
const rules = computed(() => {
const result = { ...constRules };
return result;
});
function createDefaultFormModel(): FormModel {
return {
Expand Down
Loading

0 comments on commit d582328

Please sign in to comment.