admin_web/apps/web-antd/src/views/operation/activity/activity-table.vue
hahwu a6427daaab
Some checks failed
CI / Test (ubuntu-latest) (push) Has been cancelled
CI / Test (windows-latest) (push) Has been cancelled
CI / Lint (ubuntu-latest) (push) Has been cancelled
CI / Lint (windows-latest) (push) Has been cancelled
CI / Check (ubuntu-latest) (push) Has been cancelled
CI / Check (windows-latest) (push) Has been cancelled
CodeQL / Analyze (${{ matrix.language }}) (none, javascript-typescript) (push) Has been cancelled
Deploy Website on push / Deploy Push Playground Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Docs Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Antd Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Element Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Naive Ftp (push) Has been cancelled
Release Drafter / update_release_draft (push) Has been cancelled
CI / CI OK (push) Has been cancelled
apk包下载链接调整
2026-05-08 16:40:05 +08:00

288 lines
8.8 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.

<script setup lang="ts">
import { Page, VbenIcon } from '@vben/common-ui';
import { Button, Card, Space, Tag } from 'ant-design-vue';
import { useVbenVxeGrid } from '#/adapter/vxe-table';
import type { VxeGridListeners, VxeGridProps } from '#/adapter/vxe-table';
import type { VbenFormProps } from '#/adapter/form';
import type { ActivityData } from '#/api/core/activity';
import { getServerListApi, getAppListApi } from '#/api/core/server';
import { getActivityListApi } from '#/api/core/activity';
import type { AppData, ServerData } from '#/api/core/server';
import { useVbenModal } from '@vben/common-ui';
import { onMounted, ref } from 'vue';
import AddActivityModal from './activity-add.vue';
import DetailActivityModal from './activity-detail.vue';
import SyncActivityModal from './activity-sync.vue';
import { formatUTC8Time } from '#/store/util';
import { activityTypeData } from '#/store/order';
import { parseNumber } from '#/store/util';
import { $t } from '#/locales'
const activityList = ref<string[]>([]);
const appList = ref<AppData[]>([]);
const ServerList = ref<ServerData[]>([]);
const formOptions: VbenFormProps = {
// 默认展开
collapsed: false,
schema: [
{
component: 'Select',
defaultValue: 1,
componentProps: {
filterOption: true,
options: [],
placeholder: '请选择',
showSearch: true,
},
fieldName: 'AppId',
label: 'APP',
},
{
component: 'Select',
defaultValue: "不限",
componentProps: {
filterOption: true,
options: activityTypeData ? Object.entries(activityTypeData).map(([key, value]) => ({
label: value,
value: key,
})) : [],
placeholder: '请选择',
showSearch: true,
},
fieldName: 'activityType',
label: '活动类型:',
},
],
// 控制表单是否显示折叠按钮
showCollapseButton: true,
submitButtonOptions: {
content: '查询',
},
// 是否在字段值改变时提交表单
submitOnChange: false,
// 按下回车时是否提交表单
submitOnEnter: false,
};
const gridOptions: VxeGridProps<ActivityData> = {
columns: [
{ field: 'id', title: 'id' },
{ field: 'type', title: '活动类型', formatter: ({ cellValue }) => activityTypeData[cellValue] || cellValue },
{ field: 'level', title: '开启等级', },
{ field: 'now_start_time', title: '开启时间', formatter: ({ cellValue }) => formatUTC8Time(cellValue), slots: { header: 'start_time_header' } },
{ field: 'now_end_time', title: '结束时间', formatter: ({ cellValue }) => formatUTC8Time(cellValue), slots: { header: 'end_time_header' } },
{ field: 'interval', title: '活动循环间隔从上次开始时间开始计算0表示不循环', },
{ field: 'tag', title: '状态', slots: { default: 'tag' } },
],
minHeight: '650px',
pagerConfig: {},
proxyConfig: {
response: {
total: 'total',
result: 'data',
},
ajax: {
query: async ({ page }, formValues) => {
let AppId = parseNumber(formValues.AppId);
let activityType = parseNumber(formValues.activityType);
const response = await getActivityListApi({
AppId: AppId,
ServerId: formValues.ServerId,
PageSize: page.pageSize,
CurrentPage: page.currentPage,
activityType: activityType,
});
if (!response || !response.data) {
activityList.value = [];
return response;
}
const now = Math.floor(Date.now() / 1000);
activityList.value = [];
for (let item of response.data) {
const interval = item.interval || 0;
if (interval == 0) {
item.now_start_time = item.start_time;
item.now_end_time = item.end_time;
} else {
if (now < item.start_time) {
item.now_start_time = item.start_time;
item.now_end_time = item.end_time;
} else {
const cycle = Math.floor((now - item.start_time) / interval);
item.now_start_time = item.start_time + cycle * interval;
item.now_end_time = item.end_time + cycle * interval;
if (item.now_end_time < now) {
item.now_start_time += interval;
item.now_end_time += interval;
}
}
}
if (item.now_end_time < now) {
item.tag = '已结束';
} else if (item.now_start_time > now) {
item.tag = '未开始';
} else {
activityList.value = Array.from(new Set([...activityList.value, activityTypeData[item.type]])).filter((v): v is string => v !== undefined);
item.tag = '生效中';
}
}
console.log(response);
return response;
},
},
},
showOverflow: false,
rowConfig: {
isHover: true,
},
};
const gridEvents: VxeGridListeners<ActivityData> = {
cellClick: async ({ row }) => {
const Value = await GridApi.formApi.getValues();
DetailActivityApi.setData({ AppId: Value.AppId, cfg: row });
DetailActivityApi.open();
// message.info(`cell-click: ${row.title}`);
},
};
const [Grid, GridApi] = useVbenVxeGrid({
gridEvents,
formOptions,
gridOptions,
});
const [AddActivityM, AddActivityApi] = useVbenModal({
connectedComponent: AddActivityModal,
onClosed: async () => {
AddActivityApi.close();
GridApi.query();
//console.log("close")
},
});
const [DetailActivityM, DetailActivityApi] = useVbenModal({
connectedComponent: DetailActivityModal,
onClosed: async () => {
DetailActivityApi.close();
GridApi.query();
//console.log("close")
}
});
const [SyncActivityM, SyncActivityApi] = useVbenModal({
connectedComponent: SyncActivityModal,
onClosed: async () => {
SyncActivityApi.close();
GridApi.query();
//console.log("close")
}
});
onMounted(async () => {
try {
const response = await getAppListApi();
appList.value = Array.isArray(response) ? response : [];
const app = appList.value[0];
if (!app) return;
GridApi.formApi.updateSchema([
{
component: 'Select',
componentProps: {
options: appList.value.map((item) => ({
label: $t('page.server.' + item.AppName),
value: item.AppId,
})),
},
fieldName: 'AppId',
},
]);
const serverResponse = await getServerListApi({
AppId: app.AppId,
Type: 1,
});
ServerList.value = Array.isArray(serverResponse) ? serverResponse : [];
GridApi.formApi.updateSchema([
{
component: 'Select',
componentProps: {
options: ServerList.value.map((item) => ({
label: item.ServerName,
value: item.ServerId,
})),
},
fieldName: 'ServerId',
},
]);
} catch (e) {
appList.value = [];
//console.log(e);
}
});
function getTagColor(tag: string) {
switch (tag) {
case '未开始':
return 'blue';
case '生效中':
return 'green';
case '已结束':
return 'red';
default:
return 'brown';
}
}
async function addActivity() {
//console.log('addActivity');
const Value = await GridApi.formApi.getValues();
AddActivityApi.setData({ AppId: Value.AppId, ServerId: Value.ServerId });
AddActivityApi.open();
}
async function syncCfg(){
const Value = await GridApi.formApi.getValues();
SyncActivityApi.setData({ AppList: appList.value, AppId: Value.AppId, ServerId: Value.ServerId });
SyncActivityApi.open();
}
</script>
<template>
<Page auto-content-height>
<AddActivityM class="w-[50%]" />
<DetailActivityM class="w-[50%]" />
<SyncActivityM class="w-[50%]" />
<Card class="mb-5" title="活动操作">
<div class="mb-5">
<Space>
<template v-for="value in activityList" :key="value">
<Tag color="green" class="asset-log-change-tag"> <VbenIcon icon="material-symbols:av-timer" class="mr-1" />{{ value }}</Tag>
</template>
</Space>
</div>
<Space>
<Button type="primary" @click="addActivity">新增活动</Button>
</Space>
<Space class="ml-5">
<Button type="primary" @click="syncCfg">同步活动</Button>
</Space>
</Card>
<Grid>
<template #start_time_header>
开启时间 <span style="color: red">(UTC+8)</span>
</template>
<template #end_time_header>
结束时间 <span style="color: red">(UTC+8)</span>
</template>
<template #tag="{ row }">
<Tag :color=getTagColor(row.tag) class="asset-log-change-tag"> <VbenIcon icon="solar:user-id-bold" class="mr-1" />{{ row.tag }}</Tag>
</template>
</Grid>
</Page>
</template>
<style lang="css">
.asset-log-change-tag {
display: inline-flex;
align-items: center;
border-radius: 999px;
font-weight: 700;
}
</style>