修复下拉菜单

This commit is contained in:
ZuoZuo 2026-04-13 19:31:36 +08:00
parent d0b05d251c
commit 877f4f04fe
41 changed files with 978 additions and 962 deletions

View File

@ -19,7 +19,6 @@ import {
Modal, Modal,
Pagination, Pagination,
Select, Select,
SelectOption,
Space, Space,
Table, Table,
Tabs, Tabs,
@ -40,6 +39,10 @@ const ROLE_OPTIONS = [
{ label: '超级管理员', value: 'SUPER_ADMIN' }, { label: '超级管理员', value: 'SUPER_ADMIN' },
{ label: '经理', value: 'MANAGER' }, { label: '经理', value: 'MANAGER' },
]; ];
const STATUS_OPTIONS = [
{ label: '正常', value: 1 as any },
{ label: '禁用', value: 0 as any },
];
const GROUP_LABELS: Record<string, string> = { const GROUP_LABELS: Record<string, string> = {
OTHER: '其它', OTHER: '其它',
@ -252,34 +255,25 @@ loadResourceList();
<template v-else-if="column.key === 'status'"> <template v-else-if="column.key === 'status'">
<Select option-label-prop="label" <Select option-label-prop="label"
:value="record.status" :value="record.status"
:options="STATUS_OPTIONS"
style="width: 100px" style="width: 100px"
@change="(value) => { @change="(value) => {
record.status = value; record.status = value;
handleStatusChange(record, Number(value) === 1); handleStatusChange(record, Number(value) === 1);
}" }"
> />
<SelectOption :value="1" label="正常">正常</SelectOption>
<SelectOption :value="0" label="禁用">禁用</SelectOption>
</Select>
</template> </template>
<template v-else-if="column.key === 'roles'"> <template v-else-if="column.key === 'roles'">
<Select option-label-prop="label" <Select option-label-prop="label"
:loading="record.id === roleLoadingId" :loading="record.id === roleLoadingId"
:value="record.roles" :value="record.roles"
:options="ROLE_OPTIONS"
style="width: 130px" style="width: 130px"
@change="(value) => { @change="(value) => {
record.roles = value; record.roles = value;
handleRoleChange(record, value); handleRoleChange(record, value);
}" }"
> />
<SelectOption
v-for="item in ROLE_OPTIONS"
:key="item.value"
:value="item.value"
:label="`${item.label}`">
{{ item.label }}
</SelectOption>
</Select>
</template> </template>
<template v-else-if="column.key === 'createTime'"> <template v-else-if="column.key === 'createTime'">
{{ formatDate(record.createTime) }} {{ formatDate(record.createTime) }}

View File

@ -24,7 +24,6 @@ import {
Modal, Modal,
Pagination, Pagination,
Select, Select,
SelectOption,
Space, Space,
Table, Table,
Tabs, Tabs,
@ -469,15 +468,12 @@ watch(
@ok="handleBadgeSubmit" @ok="handleBadgeSubmit"
> >
<Space direction="vertical" style="width: 100%"> <Space direction="vertical" style="width: 100%">
<Select option-label-prop="label" v-model:value="badgeForm.type" placeholder="类型"> <Select
<SelectOption v-model:value="badgeForm.type"
v-for="item in badgeTypeOptions" :options="badgeTypeOptions"
:key="item.value" option-label-prop="label"
:value="item.value" placeholder="类型"
:label="`${item.label}`"> />
{{ item.label }}
</SelectOption>
</Select>
<Input v-model:value="badgeForm.badgeName" placeholder="徽章名称" /> <Input v-model:value="badgeForm.badgeName" placeholder="徽章名称" />
<Input v-model:value="badgeForm.badgeKey" placeholder="徽章Key" /> <Input v-model:value="badgeForm.badgeKey" placeholder="徽章Key" />
<Input v-model:value="badgeForm.badgeLevel" placeholder="等级" /> <Input v-model:value="badgeForm.badgeLevel" placeholder="等级" />

View File

@ -21,7 +21,6 @@ import {
Modal, Modal,
Pagination, Pagination,
Select, Select,
SelectOption,
Space, Space,
Table, Table,
message, message,
@ -64,6 +63,11 @@ const query = reactive<Record<string, any>>({
const form = reactive(createForm()); const form = reactive(createForm());
const beautifulNumberSaleOptions = [
{ label: '不可售卖', value: 0 as any },
{ label: '可售卖', value: 1 as any },
];
const columns = [ const columns = [
{ dataIndex: 'userAccount', key: 'userAccount', title: '靓号', width: 140 }, { dataIndex: 'userAccount', key: 'userAccount', title: '靓号', width: 140 },
{ dataIndex: 'gold', key: 'gold', title: '金币', width: 120 }, { dataIndex: 'gold', key: 'gold', title: '金币', width: 120 },
@ -302,10 +306,12 @@ void loadData(true);
/> />
</FormItem> </FormItem>
<FormItem label="售卖类型"> <FormItem label="售卖类型">
<Select option-label-prop="label" v-model:value="form.status" placeholder="请选择售卖类型"> <Select
<SelectOption :value="0" label="不可售卖">不可售卖</SelectOption> v-model:value="form.status"
<SelectOption :value="1" label="可售卖">可售卖</SelectOption> :options="beautifulNumberSaleOptions"
</Select> option-label-prop="label"
placeholder="请选择售卖类型"
/>
</FormItem> </FormItem>
<FormItem label="金币"> <FormItem label="金币">
<Input v-model:value="form.gold" placeholder="请输入金币" /> <Input v-model:value="form.gold" placeholder="请输入金币" />

View File

@ -20,7 +20,6 @@ import {
Input, Input,
Modal, Modal,
Select, Select,
SelectOption,
message, message,
} from 'antdv-next'; } from 'antdv-next';
@ -32,6 +31,11 @@ const PAY_PLATFORM_OPTIONS = [
{ disabled: true, label: 'Stripe', value: 'STRIPE' }, { disabled: true, label: 'Stripe', value: 'STRIPE' },
{ disabled: true, label: 'PayerMax', value: 'PAY_MAX' }, { disabled: true, label: 'PayerMax', value: 'PAY_MAX' },
]; ];
const payPlatformOptions = PAY_PLATFORM_OPTIONS.map((item) => ({
disabled: item.disabled,
label: item.label,
value: item.value as any,
}));
const accessStore = useAccessStore(); const accessStore = useAccessStore();
const sysOriginOptions = computed(() => { const sysOriginOptions = computed(() => {
@ -171,16 +175,12 @@ function submitCandyForm() {
></SysOriginSelect> ></SysOriginSelect>
</FormItem> </FormItem>
<FormItem label="支付方式"> <FormItem label="支付方式">
<Select option-label-prop="label" v-model:value="orderForm.platform" placeholder="请选择支付方式"> <Select
<SelectOption option-label-prop="label"
v-for="item in PAY_PLATFORM_OPTIONS" v-model:value="orderForm.platform"
:key="item.value" :options="payPlatformOptions"
:disabled="item.disabled" placeholder="请选择支付方式"
:value="item.value" />
:label="`${item.label}`">
{{ item.label }}
</SelectOption>
</Select>
</FormItem> </FormItem>
<FormItem label="产品CODE"> <FormItem label="产品CODE">
<Input v-model:value="orderForm.productCode" /> <Input v-model:value="orderForm.productCode" />

View File

@ -1,5 +1,5 @@
<script lang="ts" setup> <script lang="ts" setup>
import { reactive, ref, watch } from 'vue'; import { computed, reactive, ref, watch } from 'vue';
import { import {
addActivityConf, addActivityConf,
@ -18,7 +18,6 @@ import {
FormItem, FormItem,
Input, Input,
Select, Select,
SelectOption,
Space, Space,
Tabs, Tabs,
TabPane, TabPane,
@ -71,6 +70,18 @@ const rewardIndex = ref(-1);
const isClose = ref(false); const isClose = ref(false);
const showcaseOptions = [
{ label: '下架', value: false as any },
{ label: '上架', value: true as any },
];
const templateSelectOptions = computed(() =>
templateOptions.value.map((item) => ({
label: String(item.name || item.templateName || item.id || '-'),
value: item.id as any,
})),
);
function resetForm() { function resetForm() {
Object.assign(form, createForm()); Object.assign(form, createForm());
rangeDate.value = null; rangeDate.value = null;
@ -357,20 +368,15 @@ async function handleSubmit() {
<Input :value="sysOrigin" disabled /> <Input :value="sysOrigin" disabled />
</FormItem> </FormItem>
<FormItem label="模版"> <FormItem label="模版">
<Select option-label-prop="label" <Select
v-model:value="form.templateId" v-model:value="form.templateId"
:options="templateSelectOptions"
:disabled="isClose" :disabled="isClose"
:loading="templateLoading" :loading="templateLoading"
option-label-prop="label"
placeholder="请选择模版"
show-search show-search
> />
<SelectOption
v-for="item in templateOptions"
:key="item.id"
:value="item.id"
:label="`${item.name}`">
{{ item.name }}
</SelectOption>
</Select>
</FormItem> </FormItem>
</div> </div>
@ -386,10 +392,13 @@ async function handleSubmit() {
<div class="grid"> <div class="grid">
<FormItem label="状态"> <FormItem label="状态">
<Select option-label-prop="label" v-model:value="form.showcase" :disabled="isClose"> <Select
<SelectOption :value="false" label="下架">下架</SelectOption> v-model:value="form.showcase"
<SelectOption :value="true" label="上架">上架</SelectOption> :disabled="isClose"
</Select> :options="showcaseOptions"
option-label-prop="label"
placeholder="请选择状态"
/>
</FormItem> </FormItem>
<FormItem label="备注"> <FormItem label="备注">
<TextArea <TextArea

View File

@ -10,7 +10,6 @@ import {
Input, Input,
Modal, Modal,
Select, Select,
SelectOption,
message, message,
} from 'antdv-next'; } from 'antdv-next';
@ -93,15 +92,11 @@ async function handleSubmit() {
<Input v-model:value="form.userId" /> <Input v-model:value="form.userId" />
</FormItem> </FormItem>
<FormItem label="角色"> <FormItem label="角色">
<Select option-label-prop="label" v-model:value="form.roles"> <Select
<SelectOption v-model:value="form.roles"
v-for="item in ROLE_OPTIONS" :options="ROLE_OPTIONS"
:key="item.value" option-label-prop="label"
:value="item.value" />
:label="`${item.label}`">
{{ item.label }}
</SelectOption>
</Select>
</FormItem> </FormItem>
</Form> </Form>
</Modal> </Modal>

View File

@ -12,7 +12,6 @@ import {
Input, Input,
Modal, Modal,
Select, Select,
SelectOption,
message, message,
} from 'antdv-next'; } from 'antdv-next';
@ -112,15 +111,11 @@ async function handleSubmit() {
<Input v-model:value="form.auth" /> <Input v-model:value="form.auth" />
</FormItem> </FormItem>
<FormItem label="分组"> <FormItem label="分组">
<Select option-label-prop="label" v-model:value="form.groupName"> <Select
<SelectOption v-model:value="form.groupName"
v-for="item in GROUP_OPTIONS" :options="GROUP_OPTIONS"
:key="item.value" option-label-prop="label"
:value="item.value" />
:label="`${item.label}`">
{{ item.label }}
</SelectOption>
</Select>
</FormItem> </FormItem>
</Form> </Form>
</Modal> </Modal>

View File

@ -22,7 +22,6 @@ import {
Input, Input,
Modal, Modal,
Select, Select,
SelectOption,
TextArea, TextArea,
message, message,
} from 'antdv-next'; } from 'antdv-next';
@ -42,11 +41,11 @@ const emit = defineEmits<{
}>(); }>();
const DISPLAY_POSITION_OPTIONS = [ const DISPLAY_POSITION_OPTIONS = [
{ name: '房间内', value: 'ROOM' }, { label: '房间内', value: 'ROOM' },
{ name: '发现页', value: 'EXPLORE_PAGE' }, { label: '发现页', value: 'EXPLORE_PAGE' },
{ name: '首页弹出层', value: 'HOME_ALERT' }, { label: '首页弹出层', value: 'HOME_ALERT' },
{ name: '钱包', value: 'WALLET' }, { label: '钱包', value: 'WALLET' },
{ name: '游戏', value: 'GAME' }, { label: '游戏', value: 'GAME' },
]; ];
const APP_PLATFORMS = [ const APP_PLATFORMS = [
@ -143,6 +142,19 @@ const contentSuggestions = () => {
})); }));
}; };
function normalizeMultiValue(value: any) {
if (Array.isArray(value)) {
return value.filter((item) => item !== '' && item !== null && item !== undefined);
}
if (value === '' || value === null || value === undefined) {
return [];
}
return String(value)
.split(',')
.map((item) => item.trim())
.filter(Boolean);
}
watch( watch(
() => ({ open: props.open, row: props.row, sysOrigin: props.sysOrigin }), () => ({ open: props.open, row: props.row, sysOrigin: props.sysOrigin }),
({ open, row, sysOrigin }) => { ({ open, row, sysOrigin }) => {
@ -154,21 +166,9 @@ watch(
selectCountryCodes.value = []; selectCountryCodes.value = [];
if (row) { if (row) {
Object.assign(form, row); Object.assign(form, row);
form.displayPosition = row.displayPosition form.displayPosition = normalizeMultiValue(row.displayPosition);
? String(row.displayPosition) form.regionList = normalizeMultiValue(row.regions || row.regionList);
.split(',') selectCountryCodes.value = normalizeMultiValue(row.countryCode);
.filter(Boolean)
: [];
form.regionList = row.regions
? String(row.regions)
.split(',')
.filter(Boolean)
: [];
selectCountryCodes.value = row.countryCode
? String(row.countryCode)
.split(',')
.filter(Boolean)
: [];
if (form.content === 'ENTER_ROOM' && form.params) { if (form.content === 'ENTER_ROOM' && form.params) {
roomSearchValue.value = String(form.params); roomSearchValue.value = String(form.params);
} }
@ -467,15 +467,13 @@ async function submitForm() {
<div class="field field--full"> <div class="field field--full">
<div class="label">展示位</div> <div class="label">展示位</div>
<Select option-label-prop="label" v-model:value="form.displayPosition" mode="multiple"> <Select
<SelectOption v-model:value="form.displayPosition"
v-for="item in DISPLAY_POSITION_OPTIONS" :options="DISPLAY_POSITION_OPTIONS"
:key="item.value" mode="multiple"
:value="item.value" option-label-prop="label"
:label="`${item.name}`"> placeholder="请选择展示位"
{{ item.name }} />
</SelectOption>
</Select>
</div> </div>
<div class="field"> <div class="field">

View File

@ -1,5 +1,5 @@
<script lang="ts" setup> <script lang="ts" setup>
import { reactive, ref, watch } from 'vue'; import { computed, reactive, ref, watch } from 'vue';
import { getByGroupId } from '#/api/legacy/props'; import { getByGroupId } from '#/api/legacy/props';
import { import {
@ -22,7 +22,6 @@ import {
Modal, Modal,
Pagination, Pagination,
Select, Select,
SelectOption,
Space, Space,
Table, Table,
Tag, Tag,
@ -101,6 +100,13 @@ const columns = [
{ dataIndex: 'actions', key: 'actions', title: '操作', width: 240 }, { dataIndex: 'actions', key: 'actions', title: '操作', width: 240 },
]; ];
const gameAwardSelectOptions = computed(() =>
images.value.map((item) => ({
label: String(item.id || '-'),
value: String(item.id || ''),
})),
);
function getTaskTypeLabel(value?: string) { function getTaskTypeLabel(value?: string) {
return TASK_TYPE_OPTIONS.find((item) => item.value === value)?.label || value || '-'; return TASK_TYPE_OPTIONS.find((item) => item.value === value)?.label || value || '-';
} }
@ -358,15 +364,13 @@ function handlePageChange(page: number, pageSize: number) {
<Input :value="form.sysOrigin" disabled /> <Input :value="form.sysOrigin" disabled />
</FormItem> </FormItem>
<FormItem label="挑战的任务"> <FormItem label="挑战的任务">
<Select option-label-prop="label" v-model:value="form.taskType" allow-clear placeholder="任务类型"> <Select
<SelectOption v-model:value="form.taskType"
v-for="item in TASK_TYPE_OPTIONS" allow-clear
:key="item.value" :options="TASK_TYPE_OPTIONS"
:value="item.value" option-label-prop="label"
:label="`${item.label}`"> placeholder="任务类型"
{{ item.label }} />
</SelectOption>
</Select>
</FormItem> </FormItem>
<FormItem label="排序"> <FormItem label="排序">
<Input v-model:value="form.sort" placeholder="排序" /> <Input v-model:value="form.sort" placeholder="排序" />
@ -386,19 +390,13 @@ function handlePageChange(page: number, pageSize: number) {
v-if="['WINNING_ONE_OF_THE_PRIZES_ONE', 'WINNING_ONE_OF_THE_PRIZES_TWO'].includes(form.taskType)" v-if="['WINNING_ONE_OF_THE_PRIZES_ONE', 'WINNING_ONE_OF_THE_PRIZES_TWO'].includes(form.taskType)"
label="奖项" label="奖项"
> >
<Select option-label-prop="label" <Select
v-model:value="form.gameAwardId" v-model:value="form.gameAwardId"
:options="gameAwardSelectOptions"
mode="multiple" mode="multiple"
option-label-prop="label"
placeholder="请选择奖项" placeholder="请选择奖项"
> />
<SelectOption
v-for="item in images"
:key="item.id"
:value="String(item.id)"
:label="`${item.id}`">
{{ item.id }}
</SelectOption>
</Select>
<div v-if="form.gameAwardId.length > 0" class="award-preview"> <div v-if="form.gameAwardId.length > 0" class="award-preview">
<div <div
v-for="item in images.filter((option) => form.gameAwardId.includes(String(option.id)))" v-for="item in images.filter((option) => form.gameAwardId.includes(String(option.id)))"

View File

@ -6,7 +6,7 @@ import { useAccessStore } from '@vben/stores';
import { listRoomPk } from '#/api/legacy/game'; import { listRoomPk } from '#/api/legacy/game';
import { getAllowedSysOrigins } from '#/views/system/shared'; import { getAllowedSysOrigins } from '#/views/system/shared';
import { Alert, Button, Select, SelectOption, Table } from 'antdv-next'; import { Alert, Button, Select, Table } from 'antdv-next';
import RoomDetailsDrawer from '#/views/app-system/components/room-details-drawer.vue'; import RoomDetailsDrawer from '#/views/app-system/components/room-details-drawer.vue';
@ -26,6 +26,10 @@ const sysOriginOptions = computed(() => {
const options = getAllowedSysOrigins(accessStore.accessCodes || []); const options = getAllowedSysOrigins(accessStore.accessCodes || []);
return options.length > 0 ? options : getAllowedSysOrigins([]); return options.length > 0 ? options : getAllowedSysOrigins([]);
}); });
const pkTypeOptions = PK_TYPE_OPTIONS.map((item) => ({
label: item.label,
value: item.value as any,
}));
const loading = ref(false); const loading = ref(false);
const loadMoreLoading = ref(false); const loadMoreLoading = ref(false);
@ -179,17 +183,10 @@ function handleRecipientRoomFail() {
></SysOriginSelect> ></SysOriginSelect>
<Select option-label-prop="label" <Select option-label-prop="label"
v-model:value="query.pkType" v-model:value="query.pkType"
:options="pkTypeOptions"
style="width: 140px" style="width: 140px"
@change="handleSearch" @change="handleSearch"
> />
<SelectOption
v-for="item in PK_TYPE_OPTIONS"
:key="item.value"
:value="item.value"
:label="`${item.label}`">
{{ item.label }}
</SelectOption>
</Select>
<AccountInput <AccountInput
v-model:value="query.sponsorUserId" v-model:value="query.sponsorUserId"
:sys-origin="query.sysOrigin" :sys-origin="query.sysOrigin"

View File

@ -25,7 +25,6 @@ import {
Image, Image,
Input, Input,
Select, Select,
SelectOption,
Space, Space,
Spin, Spin,
Switch, Switch,
@ -87,10 +86,48 @@ const previousStandardId = ref<number | string>('');
const previewCover = computed(() => getAccessImgUrl(form.giftPhoto)); const previewCover = computed(() => getAccessImgUrl(form.giftPhoto));
const previewSource = computed(() => getAccessImgUrl(form.giftSourceUrl)); const previewSource = computed(() => getAccessImgUrl(form.giftSourceUrl));
const title = computed(() => (form.id ? '编辑礼物' : '新增礼物')); const title = computed(() => (form.id ? '编辑礼物' : '新增礼物'));
const regionOptions = computed(() =>
regions.value.map((item) => ({
label: String(item.regionName || item.name || item.id || '-'),
value: item.id as any,
})),
);
const giftTabOptions = GIFT_CONFIG_TAB_OPTIONS.map((item) => ({
label: item.name,
value: item.value as any,
}));
const chargeTypeOptions = [
{ label: '金币', value: 'GOLD' },
{ label: '钻石', value: 'DIAMOND' },
{ disabled: true, label: '免费', value: 'FREE' },
];
const specialOptions = GIFT_SPECIAL_OPTIONS.map((item) => ({
label: item.name,
value: item.value as any,
}));
const standardSelectOptions = computed(() =>
standardOptions.value.map((item) => ({
label: String(item.name || item.label || item.value || item.id || '-'),
value: (item.value || item.id) as any,
})),
);
const isLuckyOrMagic = computed( const isLuckyOrMagic = computed(
() => form.giftTab === 'LUCKY_GIFT' || form.giftTab === 'MAGIC', () => form.giftTab === 'LUCKY_GIFT' || form.giftTab === 'MAGIC',
); );
function normalizeMultiValue(value: any) {
if (Array.isArray(value)) {
return value.filter((item) => item !== '' && item !== null && item !== undefined);
}
if (value === '' || value === null || value === undefined) {
return [];
}
return String(value)
.split(',')
.map((item) => item.trim())
.filter(Boolean);
}
function resetForm() { function resetForm() {
Object.assign(form, createForm(props.sysOrigin)); Object.assign(form, createForm(props.sysOrigin));
previousStandardId.value = ''; previousStandardId.value = '';
@ -120,16 +157,8 @@ watch(
Object.assign(form, { Object.assign(form, {
...props.row, ...props.row,
explanationGift: Boolean(props.row.explanationGift), explanationGift: Boolean(props.row.explanationGift),
regionList: props.row.regions regionList: normalizeMultiValue(props.row.regions || props.row.regionList),
? String(props.row.regions) specialList: normalizeMultiValue(props.row.special || props.row.specialList),
.split(',')
.filter(Boolean)
: props.row.regionList || [],
specialList: props.row.special
? String(props.row.special)
.split(',')
.filter(Boolean)
: props.row.specialList || [],
sysOrigin: props.row.sysOrigin || props.sysOrigin, sysOrigin: props.row.sysOrigin || props.sysOrigin,
}); });
previousStandardId.value = props.row.standardId || ''; previousStandardId.value = props.row.standardId || '';
@ -296,17 +325,12 @@ async function handleSubmit() {
</Button> </Button>
<Select option-label-prop="label" <Select option-label-prop="label"
v-model:value="form.regionList" v-model:value="form.regionList"
:options="regionOptions"
mode="multiple" mode="multiple"
placeholder="请选择区域"
show-search
style="width: 100%" style="width: 100%"
> />
<SelectOption
v-for="item in regions"
:key="item.id"
:value="item.id"
:label="`${item.regionName}`">
{{ item.regionName }}
</SelectOption>
</Select>
</Space> </Space>
</FormItem> </FormItem>
</div> </div>
@ -331,36 +355,32 @@ async function handleSubmit() {
<div class="grid"> <div class="grid">
<FormItem label="礼物类型"> <FormItem label="礼物类型">
<Select option-label-prop="label" v-model:value="form.giftTab"> <Select
<SelectOption v-model:value="form.giftTab"
v-for="item in GIFT_CONFIG_TAB_OPTIONS" :options="giftTabOptions"
:key="item.value" option-label-prop="label"
:value="item.value" placeholder="请选择礼物类型"
:label="`${item.name}`"> />
{{ item.name }}
</SelectOption>
</Select>
</FormItem> </FormItem>
<FormItem label="收费类型"> <FormItem label="收费类型">
<Select option-label-prop="label" v-model:value="form.type"> <Select
<SelectOption value="GOLD" label="金币">金币</SelectOption> v-model:value="form.type"
<SelectOption value="DIAMOND" label="钻石">钻石</SelectOption> :options="chargeTypeOptions"
<SelectOption value="FREE" disabled label="免费">免费</SelectOption> option-label-prop="label"
</Select> placeholder="请选择收费类型"
/>
</FormItem> </FormItem>
</div> </div>
<div class="grid"> <div class="grid">
<FormItem label="特效"> <FormItem label="特效">
<Select option-label-prop="label" v-model:value="form.specialList" mode="multiple"> <Select
<SelectOption v-model:value="form.specialList"
v-for="item in GIFT_SPECIAL_OPTIONS" :options="specialOptions"
:key="item.value" mode="multiple"
:value="item.value" option-label-prop="label"
:label="`${item.name}`"> placeholder="请选择特效"
{{ item.name }} />
</SelectOption>
</Select>
</FormItem> </FormItem>
<FormItem label="排序"> <FormItem label="排序">
<Input v-model:value="form.sort" /> <Input v-model:value="form.sort" />
@ -414,15 +434,12 @@ async function handleSubmit() {
<div class="grid" v-if="isLuckyOrMagic"> <div class="grid" v-if="isLuckyOrMagic">
<FormItem label="幸运规格"> <FormItem label="幸运规格">
<Select option-label-prop="label" v-model:value="form.standardId"> <Select
<SelectOption v-model:value="form.standardId"
v-for="item in standardOptions" :options="standardSelectOptions"
:key="item.value || item.id" option-label-prop="label"
:value="item.value || item.id" placeholder="请选择幸运规格"
:label="`${item.name}`"> />
{{ item.name }}
</SelectOption>
</Select>
</FormItem> </FormItem>
</div> </div>

View File

@ -1,15 +1,12 @@
<script lang="ts" setup> <script lang="ts" setup>
import { computed, reactive, ref, watch } from 'vue'; import { computed, reactive, ref, watch } from 'vue';
import { useAccessStore } from '@vben/stores';
import { import {
OSS_FILE_BUCKETS, OSS_FILE_BUCKETS,
getAccessImgUrl, getAccessImgUrl,
simpleUploadFile, simpleUploadFile,
} from '#/api/legacy/oss'; } from '#/api/legacy/oss';
import { addMikeType, updateMikeType } from '#/api/legacy/mike'; import { addMikeType, updateMikeType } from '#/api/legacy/mike';
import { getAllowedSysOrigins } from '#/views/system/shared';
import { import {
Button, Button,
@ -19,7 +16,6 @@ import {
Input, Input,
Modal, Modal,
Select, Select,
SelectOption,
message, message,
} from 'antdv-next'; } from 'antdv-next';
@ -37,6 +33,16 @@ const MIKE_TYPE_OPTIONS = [
{ label: '尊贵麦位', value: 'HONORABLE_MIKE' }, { label: '尊贵麦位', value: 'HONORABLE_MIKE' },
]; ];
const SHOWCASE_OPTIONS = [
{ label: '上架', value: true as any },
{ label: '下架', value: false as any },
];
const CHARGE_TYPE_OPTIONS = [
{ label: '免费', value: 'FREE' as any },
{ label: '金币', value: 'GOLD' as any },
];
const props = withDefaults( const props = withDefaults(
defineProps<{ defineProps<{
open: boolean; open: boolean;
@ -54,12 +60,6 @@ const emit = defineEmits<{
success: []; success: [];
}>(); }>();
const accessStore = useAccessStore();
const sysOriginOptions = computed(() => {
const options = getAllowedSysOrigins(accessStore.accessCodes || []);
return options.length > 0 ? options : getAllowedSysOrigins([]);
});
const loading = ref(false); const loading = ref(false);
const mikeCoverLoading = ref(false); const mikeCoverLoading = ref(false);
const mikeIconLoading = ref(false); const mikeIconLoading = ref(false);
@ -228,31 +228,25 @@ async function handleSubmit() {
</div> </div>
</FormItem> </FormItem>
<FormItem label="状态"> <FormItem label="状态">
<SysOriginSelect v-model:value="form.showcase" <Select
:options="sysOriginOptions" v-model:value="form.showcase"
></SysOriginSelect> :options="SHOWCASE_OPTIONS"
option-label-prop="label"
/>
</FormItem> </FormItem>
<FormItem label="麦位名称"> <FormItem label="麦位名称">
<Select option-label-prop="label" v-model:value="form.mikeName"> <Select
<SelectOption v-model:value="form.mikeName"
v-for="item in MIKE_NAME_OPTIONS" :options="MIKE_NAME_OPTIONS"
:key="item.value" option-label-prop="label"
:value="item.value" />
:label="`${item.label}`">
{{ item.label }}
</SelectOption>
</Select>
</FormItem> </FormItem>
<FormItem label="麦位类型"> <FormItem label="麦位类型">
<Select option-label-prop="label" v-model:value="form.mikeType"> <Select
<SelectOption v-model:value="form.mikeType"
v-for="item in MIKE_TYPE_OPTIONS" :options="MIKE_TYPE_OPTIONS"
:key="item.value" option-label-prop="label"
:value="item.value" />
:label="`${item.label}`">
{{ item.label }}
</SelectOption>
</Select>
</FormItem> </FormItem>
<FormItem label="15天麦位价格"> <FormItem label="15天麦位价格">
<Input v-model:value="form.fifteenMikeCandy" /> <Input v-model:value="form.fifteenMikeCandy" />
@ -261,10 +255,11 @@ async function handleSubmit() {
<Input v-model:value="form.longMikeCandy" /> <Input v-model:value="form.longMikeCandy" />
</FormItem> </FormItem>
<FormItem label="收费类型"> <FormItem label="收费类型">
<Select option-label-prop="label" v-model:value="form.chargeType"> <Select
<SelectOption value="FREE" label="免费">免费</SelectOption> v-model:value="form.chargeType"
<SelectOption value="GOLD" label="金币">金币</SelectOption> :options="CHARGE_TYPE_OPTIONS"
</Select> option-label-prop="label"
/>
</FormItem> </FormItem>
<FormItem label="排序"> <FormItem label="排序">
<Input v-model:value="form.sort" /> <Input v-model:value="form.sort" />

View File

@ -16,7 +16,6 @@ import {
Input, Input,
Modal, Modal,
Select, Select,
SelectOption,
message, message,
} from 'antdv-next'; } from 'antdv-next';
@ -37,6 +36,11 @@ const emit = defineEmits<{
success: []; success: [];
}>(); }>();
const payChannelGroupOptions = PAY_CHANNEL_GROUP_OPTIONS.map((item) => ({
label: item.name,
value: item.value as any,
}));
const fileInputRef = ref<HTMLInputElement | null>(null); const fileInputRef = ref<HTMLInputElement | null>(null);
const loading = ref(false); const loading = ref(false);
const uploadLoading = ref(false); const uploadLoading = ref(false);
@ -136,15 +140,11 @@ async function handleSubmit() {
> >
<Form layout="vertical"> <Form layout="vertical">
<FormItem label="类型"> <FormItem label="类型">
<Select option-label-prop="label" v-model:value="form.channelType"> <Select
<SelectOption v-model:value="form.channelType"
v-for="item in PAY_CHANNEL_GROUP_OPTIONS" :options="payChannelGroupOptions"
:key="item.value" option-label-prop="label"
:value="item.value" />
:label="`${item.name}`">
{{ item.name }}
</SelectOption>
</Select>
</FormItem> </FormItem>
<FormItem label="Code"> <FormItem label="Code">
<Input v-model:value="form.channelCode" :disabled="Boolean(form.id)" /> <Input v-model:value="form.channelCode" :disabled="Boolean(form.id)" />

View File

@ -15,7 +15,6 @@ import {
Input, Input,
Modal, Modal,
Select, Select,
SelectOption,
message, message,
} from 'antdv-next'; } from 'antdv-next';
@ -44,6 +43,16 @@ const supportAmounts = ref<Array<Record<string, any>>>([]);
const computedAmount = ref(''); const computedAmount = ref('');
const amountUsdText = ref(''); const amountUsdText = ref('');
const shelfOptions = [
{ label: '上架', value: true as any },
{ label: '下架', value: false as any },
];
const webProductTypeOptions = WEB_PRODUCT_TYPE_OPTIONS.map((item) => ({
label: item.name,
value: item.value as any,
}));
const form = reactive<Record<string, any>>({ const form = reactive<Record<string, any>>({
amountUsd: '', amountUsd: '',
applicationId: '', applicationId: '',
@ -206,22 +215,19 @@ async function handleSubmit() {
</FormItem> </FormItem>
<FormItem label="状态"> <FormItem label="状态">
<Select option-label-prop="label" v-model:value="form.shelf"> <Select
<SelectOption :value="true" label="上架">上架</SelectOption> v-model:value="form.shelf"
<SelectOption :value="false" label="下架">下架</SelectOption> :options="shelfOptions"
</Select> option-label-prop="label"
/>
</FormItem> </FormItem>
<FormItem v-if="!isUpdate" label="商品类型"> <FormItem v-if="!isUpdate" label="商品类型">
<Select option-label-prop="label" v-model:value="form.type"> <Select
<SelectOption v-model:value="form.type"
v-for="item in WEB_PRODUCT_TYPE_OPTIONS" :options="webProductTypeOptions"
:key="item.value" option-label-prop="label"
:value="item.value" />
:label="`${item.name}`">
{{ item.name }}
</SelectOption>
</Select>
</FormItem> </FormItem>
<FormItem label="金币数"> <FormItem label="金币数">

View File

@ -15,7 +15,6 @@ import {
Input, Input,
Pagination, Pagination,
Select, Select,
SelectOption,
Switch, Switch,
Table, Table,
} from 'antdv-next'; } from 'antdv-next';
@ -62,6 +61,39 @@ const title = computed(() => (props.mode === 'country' ? '商品管理' : '商
const dimensionPlaceholder = computed(() => const dimensionPlaceholder = computed(() =>
props.mode === 'country' ? '国家' : '区域', props.mode === 'country' ? '国家' : '区域',
); );
const productTypeOptions = WEB_PRODUCT_TYPE_OPTIONS.map((item) => ({
label: item.name,
value: item.value as any,
}));
const applicationOptions = computed(() =>
(props.appInfo?.appList || []).map((item: Record<string, any>) => ({
label: item.appName || '-',
value: item.id as any,
})),
);
const supportOptions = computed(() =>
supportList.value.map((item) => ({
label:
props.mode === 'country'
? item.country?.aliasName || item.country?.enName || '-'
: item.regionName || '-',
value: item.id as any,
})),
);
const shelfOptions = [
{ label: '上架', value: true as any },
{ label: '下架', value: false as any },
];
const selectedDimensionId = computed({
get: () => (props.mode === 'country' ? query.payCountryId : query.regionId),
set: (value) => {
if (props.mode === 'country') {
query.payCountryId = value;
return;
}
query.regionId = value;
},
});
const columns = computed(() => { const columns = computed(() => {
const listColumns: any[] = [ const listColumns: any[] = [
@ -236,56 +268,31 @@ function openEdit(record: Record<string, any>) {
<div class="toolbar"> <div class="toolbar">
<Select option-label-prop="label" <Select option-label-prop="label"
v-model:value="query.type" v-model:value="query.type"
:options="productTypeOptions"
style="width: 180px" style="width: 180px"
@change="handleSearch" @change="handleSearch"
> />
<SelectOption
v-for="item in WEB_PRODUCT_TYPE_OPTIONS"
:key="item.value"
:value="item.value"
:label="`${item.name}`">
{{ item.name }}
</SelectOption>
</Select>
<Select option-label-prop="label" <Select option-label-prop="label"
v-model:value="query.applicationId" v-model:value="query.applicationId"
:options="applicationOptions"
placeholder="应用" placeholder="应用"
style="width: 200px" style="width: 200px"
@change="handleApplicationChange" @change="handleApplicationChange"
> />
<SelectOption
v-for="item in appInfo.appList || []"
:key="item.id"
:value="item.id"
:label="`${item.appName}`">
{{ item.appName }}
</SelectOption>
</Select>
<Select option-label-prop="label" <Select option-label-prop="label"
v-model:value="props.mode === 'country' ? query.payCountryId : query.regionId" v-model:value="selectedDimensionId"
:loading="supportLoading" :loading="supportLoading"
:options="supportOptions"
:placeholder="dimensionPlaceholder" :placeholder="dimensionPlaceholder"
style="width: 200px" style="width: 200px"
@change="handleDimensionChange" @change="handleDimensionChange"
> />
<SelectOption
v-for="item in supportList"
:key="item.id"
:value="item.id"
:label="`${props.mode === 'country' ? item.country?.aliasName || item.country?.enName || '-' : item.regionName || '-'}`">
{{ props.mode === 'country'
? item.country?.aliasName || item.country?.enName || '-'
: item.regionName || '-' }}
</SelectOption>
</Select>
<Select option-label-prop="label" <Select option-label-prop="label"
v-model:value="query.shelf" v-model:value="query.shelf"
:options="shelfOptions"
style="width: 140px" style="width: 140px"
@change="handleSearch" @change="handleSearch"
> />
<SelectOption :value="true" label="上架">上架</SelectOption>
<SelectOption :value="false" label="下架">下架</SelectOption>
</Select>
<Input <Input
v-model:value="query.id" v-model:value="query.id"
placeholder="商品ID" placeholder="商品ID"

View File

@ -14,7 +14,6 @@ import {
Empty, Empty,
Input, Input,
Select, Select,
SelectOption,
Space, Space,
Spin, Spin,
} from 'antdv-next'; } from 'antdv-next';
@ -49,6 +48,11 @@ const TYPE_OPTIONS: SourceTypeOption[] = [
{ label: '碎片', value: 'FRAGMENTS' }, { label: '碎片', value: 'FRAGMENTS' },
]; ];
const typeSelectOptions = TYPE_OPTIONS.map((item) => ({
label: item.label,
value: item.value as any,
}));
const props = withDefaults( const props = withDefaults(
defineProps<{ defineProps<{
defaultType?: string; defaultType?: string;
@ -224,19 +228,14 @@ function handleSelect(item: SourceItem) {
@close="emit('close')" @close="emit('close')"
> >
<Space class="toolbar" wrap> <Space class="toolbar" wrap>
<Select option-label-prop="label" <Select
v-model:value="query.propsType" v-model:value="query.propsType"
:options="typeSelectOptions"
option-label-prop="label"
placeholder="请选择道具类型"
style="width: 220px" style="width: 220px"
@change="handleTypeChange" @change="handleTypeChange"
> />
<SelectOption
v-for="item in TYPE_OPTIONS"
:key="item.value"
:value="item.value"
:label="`${item.label}`">
{{ item.label }}
</SelectOption>
</Select>
<Input <Input
v-model:value="keyword" v-model:value="keyword"
allow-clear allow-clear

View File

@ -11,7 +11,6 @@ import {
FormItem, FormItem,
Modal, Modal,
Select, Select,
SelectOption,
message, message,
} from 'antdv-next'; } from 'antdv-next';
@ -47,6 +46,25 @@ const form = reactive<Record<string, any>>({
sysOrigin: '', sysOrigin: '',
}); });
const regionSelectOptions = computed(() =>
props.regions.map((item) => ({
label: String(item.regionName || item.id || '-'),
value: item.id as any,
})),
);
const countrySelectOptions = computed(() =>
props.countryList.map((item) => ({
label: String(item.country?.countryName || item.country?.aliasName || item.id || '-'),
value: item.id as any,
})),
);
const showcaseOptions = PRODUCT_SHOWCASE_OPTIONS.map((item) => ({
label: item.name,
value: item.value as any,
}));
const singleRelationId = computed({ const singleRelationId = computed({
get: () => form.relationIds[0], get: () => form.relationIds[0],
set: (value) => { set: (value) => {
@ -124,53 +142,33 @@ async function handleSubmit() {
> >
<Form layout="vertical"> <Form layout="vertical">
<FormItem label="区域"> <FormItem label="区域">
<Select option-label-prop="label" v-model:value="form.regionId"> <Select
<SelectOption v-model:value="form.regionId"
v-for="item in regions" :options="regionSelectOptions"
:key="item.id" option-label-prop="label"
:value="item.id" />
:label="`${item.regionName}`">
{{ item.regionName }}
</SelectOption>
</Select>
</FormItem> </FormItem>
<FormItem label="开通国家"> <FormItem label="开通国家">
<Select option-label-prop="label" <Select
v-if="form.id" v-if="form.id"
v-model:value="singleRelationId" v-model:value="singleRelationId"
> :options="countrySelectOptions"
<SelectOption option-label-prop="label"
v-for="item in countryList" />
:key="item.id" <Select
:value="item.id"
:label="`${item.country?.countryName || item.country?.aliasName || '-'}`">
{{ item.country?.countryName || item.country?.aliasName || '-' }}
</SelectOption>
</Select>
<Select option-label-prop="label"
v-else v-else
v-model:value="form.relationIds" v-model:value="form.relationIds"
:options="countrySelectOptions"
mode="multiple" mode="multiple"
> option-label-prop="label"
<SelectOption />
v-for="item in countryList"
:key="item.id"
:value="item.id"
:label="`${item.country?.countryName || item.country?.aliasName || '-'}`">
{{ item.country?.countryName || item.country?.aliasName || '-' }}
</SelectOption>
</Select>
</FormItem> </FormItem>
<FormItem label="状态"> <FormItem label="状态">
<Select option-label-prop="label" v-model:value="form.showcase"> <Select
<SelectOption v-model:value="form.showcase"
v-for="item in PRODUCT_SHOWCASE_OPTIONS" :options="showcaseOptions"
:key="String(item.value)" option-label-prop="label"
:value="item.value" />
:label="`${item.name}`">
{{ item.name }}
</SelectOption>
</Select>
</FormItem> </FormItem>
</Form> </Form>
</Modal> </Modal>

View File

@ -9,7 +9,6 @@ import {
Drawer, Drawer,
Pagination, Pagination,
Select, Select,
SelectOption,
Space, Space,
Table, Table,
} from 'antdv-next'; } from 'antdv-next';
@ -111,17 +110,10 @@ function handlePageChange(page: number, pageSize: number) {
<Select option-label-prop="label" <Select option-label-prop="label"
v-model:value="query.roomRole" v-model:value="query.roomRole"
allow-clear allow-clear
:options="ROOM_ROLE_OPTIONS"
placeholder="角色" placeholder="角色"
style="width: 140px" style="width: 140px"
> />
<SelectOption
v-for="item in ROOM_ROLE_OPTIONS"
:key="item.value"
:value="item.value"
:label="`${item.label}`">
{{ item.label }}
</SelectOption>
</Select>
<Button :loading="loading" type="primary" @click="loadData(true)"> <Button :loading="loading" type="primary" @click="loadData(true)">
搜索 搜索
</Button> </Button>

View File

@ -10,7 +10,6 @@ import {
Empty, Empty,
Modal, Modal,
Select, Select,
SelectOption,
Space, Space,
Tag, Tag,
} from 'antdv-next'; } from 'antdv-next';
@ -30,6 +29,10 @@ const loading = ref(false);
const detailsOpen = ref(false); const detailsOpen = ref(false);
const list = ref<Array<Record<string, any>>>([]); const list = ref<Array<Record<string, any>>>([]);
const jsonText = ref(''); const jsonText = ref('');
const apiRequestLogOptions = API_REQUEST_LOGS.map((item) => ({
label: item.label,
value: item.value as any,
}));
const query = reactive({ const query = reactive({
businessCode: '', businessCode: '',
@ -87,17 +90,10 @@ function openDetails(record: Record<string, any>) {
<Select option-label-prop="label" <Select option-label-prop="label"
v-model:value="query.businessCode" v-model:value="query.businessCode"
allow-clear allow-clear
:options="apiRequestLogOptions"
placeholder="业务CODE" placeholder="业务CODE"
style="width: 260px" style="width: 260px"
> />
<SelectOption
v-for="item in API_REQUEST_LOGS"
:key="item.value"
:value="item.value"
:label="`${item.label}`">
{{ item.label }}
</SelectOption>
</Select>
<Button :loading="loading" type="primary" @click="loadData"> <Button :loading="loading" type="primary" @click="loadData">
搜索 搜索
</Button> </Button>

View File

@ -17,7 +17,6 @@ import {
Image, Image,
Modal, Modal,
Select, Select,
SelectOption,
message, message,
} from 'antdv-next'; } from 'antdv-next';
@ -36,6 +35,10 @@ const APP_START_PAGE_PLAN_TYPES = [
{ name: '游戏王', value: 'KING_GAMES' }, { name: '游戏王', value: 'KING_GAMES' },
{ name: 'CP', value: 'CP' }, { name: 'CP', value: 'CP' },
]; ];
const APP_START_PAGE_PLAN_TYPE_OPTIONS = APP_START_PAGE_PLAN_TYPES.map((item) => ({
label: item.name,
value: item.value as any,
}));
function createForm() { function createForm() {
return { return {
@ -163,15 +166,12 @@ async function submitForm() {
<div class="field"> <div class="field">
<div class="label">类型</div> <div class="label">类型</div>
<Select option-label-prop="label" v-model:value="form.type"> <Select
<SelectOption v-model:value="form.type"
v-for="item in APP_START_PAGE_PLAN_TYPES" :options="APP_START_PAGE_PLAN_TYPE_OPTIONS"
:key="item.value" option-label-prop="label"
:value="item.value" placeholder="请选择活动类型"
:label="`${item.name}`"> />
{{ item.name }}
</SelectOption>
</Select>
</div> </div>
<div class="field"> <div class="field">

View File

@ -1,9 +1,9 @@
<script lang="ts" setup> <script lang="ts" setup>
import { ref, watch } from 'vue'; import { computed, ref, watch } from 'vue';
import { regionConfigTable } from '#/api/legacy/system'; import { regionConfigTable } from '#/api/legacy/system';
import { Select, SelectOption } from 'antdv-next'; import { Select } from 'antdv-next';
const props = withDefaults( const props = withDefaults(
defineProps<{ defineProps<{
@ -33,6 +33,12 @@ const emit = defineEmits<{
const loading = ref(false); const loading = ref(false);
const list = ref<Array<Record<string, any>>>([]); const list = ref<Array<Record<string, any>>>([]);
const selectValue = ref<any>(props.value); const selectValue = ref<any>(props.value);
const regionOptions = computed(() =>
list.value.map((item) => ({
label: item.regionName || '-',
value: item.id as any,
})),
);
watch( watch(
() => props.value, () => props.value,
@ -89,17 +95,10 @@ defineExpose({
:disabled="disabled" :disabled="disabled"
:loading="loading" :loading="loading"
:mode="multiple ? 'multiple' : undefined" :mode="multiple ? 'multiple' : undefined"
:options="regionOptions"
:placeholder="placeholder" :placeholder="placeholder"
:show-search="filterable" :show-search="filterable"
style="width: 100%" style="width: 100%"
@change="handleChange" @change="handleChange"
> />
<SelectOption
v-for="item in list"
:key="item.id"
:value="item.id"
:label="`${item.regionName}`">
{{ item.regionName }}
</SelectOption>
</Select>
</template> </template>

View File

@ -17,7 +17,6 @@ import {
InputNumber, InputNumber,
Modal, Modal,
Select, Select,
SelectOption,
TextArea, TextArea,
message, message,
} from 'antdv-next'; } from 'antdv-next';
@ -41,6 +40,22 @@ const form = reactive({
reasonType: 5, reasonType: 5,
remarks: '', remarks: '',
}); });
const rewardReasonOptions = [
{ label: '奖励', value: 1 as any },
{ label: '内部', value: 2 as any },
{ label: '工资', value: 3 as any },
{ label: '充值', value: 4 as any },
{ label: '其他', value: 5 as any },
];
const deductReasonOptions = [
{ label: '违规', value: 1 as any },
{ label: '多发', value: 2 as any },
{ label: '操作错误', value: 3 as any },
{ label: '其他', value: 4 as any },
];
const reasonTypeOptions = computed(() =>
props.action === 'reward' ? rewardReasonOptions : deductReasonOptions,
);
const title = computed(() => { const title = computed(() => {
const typeName = const typeName =
@ -56,7 +71,7 @@ watch(
return; return;
} }
form.amount = undefined; form.amount = undefined;
form.reasonType = 5; form.reasonType = props.action === 'reward' ? 5 : 4;
form.remarks = ''; form.remarks = '';
}, },
{ immediate: true }, { immediate: true },
@ -141,28 +156,11 @@ async function handleSubmit() {
/> />
</FormItem> </FormItem>
<FormItem label="原因"> <FormItem label="原因">
<Select option-label-prop="label" v-model:value="form.reasonType"> <Select
<SelectOption option-label-prop="label"
v-for="item in props.action === 'reward' v-model:value="form.reasonType"
? [ :options="reasonTypeOptions"
{ label: '奖励', value: 1 }, />
{ label: '内部', value: 2 },
{ label: '工资', value: 3 },
{ label: '充值', value: 4 },
{ label: '其他', value: 5 },
]
: [
{ label: '违规', value: 1 },
{ label: '多发', value: 2 },
{ label: '操作错误', value: 3 },
{ label: '其他', value: 4 },
]"
:key="item.value"
:value="item.value"
:label="`${item.label}`">
{{ item.label }}
</SelectOption>
</Select>
</FormItem> </FormItem>
<FormItem label="备注"> <FormItem label="备注">
<TextArea v-model:value="form.remarks" :rows="4" /> <TextArea v-model:value="form.remarks" :rows="4" />

View File

@ -23,7 +23,6 @@ import {
Input, Input,
Modal, Modal,
Select, Select,
SelectOption,
Space, Space,
Table, Table,
message, message,
@ -63,6 +62,13 @@ const query = reactive({
const form = reactive(createForm()); const form = reactive(createForm());
const regionSelectOptions = computed(() =>
regions.value.map((item) => ({
label: String(item.regionName || item.id || '-'),
value: item.id as any,
})),
);
const columns = [ const columns = [
{ dataIndex: 'sysOrigin', key: 'sysOrigin', title: '来源系统', width: 120 }, { dataIndex: 'sysOrigin', key: 'sysOrigin', title: '来源系统', width: 120 },
{ dataIndex: 'userProfile', key: 'userProfile', title: '客服', width: 280 }, { dataIndex: 'userProfile', key: 'userProfile', title: '客服', width: 280 },
@ -242,8 +248,7 @@ async function submitForm() {
placeholder="区域" placeholder="区域"
style="width: 160px" style="width: 160px"
@change="handleSearch" @change="handleSearch"
:options="regionSelectOptions"
:options="regions.map((item) => ({ label: `${item.regionName}`, value: item.id as any }))"
/> />
<Button :loading="loading" type="primary" @click="handleSearch"> <Button :loading="loading" type="primary" @click="handleSearch">
搜索 搜索
@ -321,21 +326,15 @@ async function submitForm() {
</div> </div>
<div class="field"> <div class="field">
<div class="label">区域</div> <div class="label">区域</div>
<Select option-label-prop="label" <Select
v-model:value="form.regionList" v-model:value="form.regionList"
:options="regionSelectOptions"
mode="multiple" mode="multiple"
:loading="regionsLoading" :loading="regionsLoading"
option-label-prop="label"
placeholder="请选择区域" placeholder="请选择区域"
style="width: 100%" style="width: 100%"
> />
<SelectOption
v-for="item in regions"
:key="item.id"
:value="item.id"
:label="`${item.regionName}`">
{{ item.regionName }}
</SelectOption>
</Select>
</div> </div>
<div class="field"> <div class="field">
<div class="label">时间段</div> <div class="label">时间段</div>

View File

@ -24,7 +24,6 @@ import {
Modal, Modal,
Pagination, Pagination,
Select, Select,
SelectOption,
Space, Space,
Table, Table,
message, message,
@ -41,8 +40,8 @@ const CARD_OPTIONS = [
]; ];
const SHOWCASE_OPTIONS = [ const SHOWCASE_OPTIONS = [
{ label: '上架', value: true }, { label: '上架', value: true as any },
{ label: '下架', value: false }, { label: '下架', value: false as any },
]; ];
function createForm() { function createForm() {
@ -338,27 +337,21 @@ async function submitForm() {
</div> </div>
<div class="field"> <div class="field">
<div class="label">状态</div> <div class="label">状态</div>
<Select option-label-prop="label" v-model:value="form.showcase" style="width: 100%"> <Select
<SelectOption v-model:value="form.showcase"
v-for="item in SHOWCASE_OPTIONS" :options="SHOWCASE_OPTIONS"
:key="String(item.value)" option-label-prop="label"
:value="item.value" style="width: 100%"
:label="`${item.label}`"> />
{{ item.label }}
</SelectOption>
</Select>
</div> </div>
<div class="field"> <div class="field">
<div class="label">卡片</div> <div class="label">卡片</div>
<Select option-label-prop="label" v-model:value="form.cardType" style="width: 100%"> <Select
<SelectOption v-model:value="form.cardType"
v-for="item in CARD_OPTIONS" :options="CARD_OPTIONS"
:key="item.value" option-label-prop="label"
:value="item.value" style="width: 100%"
:label="`${item.label}`"> />
{{ item.label }}
</SelectOption>
</Select>
</div> </div>
<div class="field"> <div class="field">
<div class="label">金额</div> <div class="label">金额</div>

View File

@ -20,7 +20,6 @@ import {
Modal, Modal,
Pagination, Pagination,
Select, Select,
SelectOption,
Space, Space,
Table, Table,
Tag, Tag,
@ -268,19 +267,12 @@ function handlePageChange(page: number, pageSize: number) {
<Form layout="vertical"> <Form layout="vertical">
<FormItem label="关联类型"> <FormItem label="关联类型">
<Select <Select
option-label-prop="label"
v-model:value="form.bountyType" v-model:value="form.bountyType"
allow-clear allow-clear
:options="BOUNTY_TYPE_OPTIONS"
option-label-prop="label"
placeholder="类型" placeholder="类型"
> />
<SelectOption
v-for="item in BOUNTY_TYPE_OPTIONS"
:key="item.value"
:value="item.value"
:label="`${item.label}`">
{{ item.label }}
</SelectOption>
</Select>
</FormItem> </FormItem>
<FormItem label="名称"> <FormItem label="名称">
<Input v-model:value="form.name" placeholder="名称" /> <Input v-model:value="form.name" placeholder="名称" />

View File

@ -29,7 +29,6 @@ import {
Modal, Modal,
Pagination, Pagination,
Select, Select,
SelectOption,
Space, Space,
Table, Table,
message, message,
@ -93,6 +92,36 @@ const query = reactive<Record<string, any>>({
}); });
const form = reactive(createForm()); const form = reactive(createForm());
const gameOriginOptions = GAME_ORIGIN_OPTIONS.map((item) => ({
label: item.name,
value: item.value as any,
}));
const clientOriginOptions = GAME_CLIENT_ORIGIN_OPTIONS.map((item) => ({
label: item.name,
value: item.value as any,
}));
const categoryOptions = GAME_CATEGORY_OPTIONS.map((item) => ({
label: item.name,
value: item.value as any,
}));
const gameModeOptions = GAME_MODE_OPTIONS.map((item) => ({
label: item.name,
value: item.value as any,
}));
const booleanOptions = [
{ label: '是', value: true as any },
{ label: '否', value: false as any },
];
const showcaseOptions = [
{ label: '下架', value: false as any },
{ label: '上架', value: true as any },
];
const regionSelectOptions = computed(() =>
regions.value.map((item) => ({
label: String(item.regionName || item.id || '-'),
value: item.id as any,
})),
);
const columns = [ const columns = [
{ dataIndex: 'sysOrigin', key: 'sysOrigin', title: '系统', width: 100 }, { dataIndex: 'sysOrigin', key: 'sysOrigin', title: '系统', width: 100 },
@ -127,6 +156,29 @@ watch(
{ immediate: true }, { immediate: true },
); );
watch(
() => form.sysOrigin,
async (value) => {
if (!modalOpen.value || !value) {
return;
}
regions.value = await regionConfigTable({ sysOrigin: value });
},
);
function normalizeMultiValue(value: any) {
if (Array.isArray(value)) {
return value.filter((item) => item !== '' && item !== null && item !== undefined);
}
if (value === '' || value === null || value === undefined) {
return [];
}
return String(value)
.split(',')
.map((item) => item.trim())
.filter(Boolean);
}
async function loadData(reset = false) { async function loadData(reset = false) {
if (reset) { if (reset) {
query.cursor = 1; query.cursor = 1;
@ -173,11 +225,10 @@ function openEdit(record: Record<string, any>) {
gameMode: record.gameMode, gameMode: record.gameMode,
gameOrigin: record.gameOrigin || query.gameOrigin, gameOrigin: record.gameOrigin || query.gameOrigin,
id: String(record.id || ''), id: String(record.id || ''),
regionList: regionList: normalizeMultiValue(
record.regionList || record.regionList || record.regions?.map((item: Record<string, any>) => item.id),
record.regions?.map((item: Record<string, any>) => item.id) || ),
[], self: record.self === true || Boolean(record.selfGameCode),
self: record.self === true,
selfGameCode: record.selfGameCode || '', selfGameCode: record.selfGameCode || '',
showcase: record.showcase, showcase: record.showcase,
sort: Number(record.sort || 0), sort: Number(record.sort || 0),
@ -358,32 +409,29 @@ void loadData(true);
/> />
</FormItem> </FormItem>
<FormItem label="游戏源"> <FormItem label="游戏源">
<Select option-label-prop="label" v-model:value="form.gameOrigin"> <Select
<SelectOption v-model:value="form.gameOrigin"
v-for="item in GAME_ORIGIN_OPTIONS" :options="gameOriginOptions"
:key="item.value" option-label-prop="label"
:value="item.value" placeholder="请选择游戏源"
:label="`${item.name}`"> />
{{ item.name }}
</SelectOption>
</Select>
</FormItem> </FormItem>
<FormItem label="客户端"> <FormItem label="客户端">
<Select option-label-prop="label" v-model:value="form.clientOrigin"> <Select
<SelectOption v-model:value="form.clientOrigin"
v-for="item in GAME_CLIENT_ORIGIN_OPTIONS" :options="clientOriginOptions"
:key="item.value" option-label-prop="label"
:value="item.value" placeholder="请选择客户端"
:label="`${item.name}`"> />
{{ item.name }}
</SelectOption>
</Select>
</FormItem> </FormItem>
<FormItem label="是否自研"> <FormItem label="是否自研">
<Select option-label-prop="label" v-model:value="form.self" allow-clear> <Select
<SelectOption :value="true" label="是"></SelectOption> v-model:value="form.self"
<SelectOption :value="false" label="否"></SelectOption> :options="booleanOptions"
</Select> allow-clear
option-label-prop="label"
placeholder="请选择是否自研"
/>
</FormItem> </FormItem>
<FormItem v-if="form.self" label="自研游戏Code"> <FormItem v-if="form.self" label="自研游戏Code">
<Input v-model:value="form.selfGameCode" placeholder="请输入自研游戏Code" /> <Input v-model:value="form.selfGameCode" placeholder="请输入自研游戏Code" />
@ -392,15 +440,12 @@ void loadData(true);
<Input v-model:value="form.gameId" placeholder="请输入游戏ID" /> <Input v-model:value="form.gameId" placeholder="请输入游戏ID" />
</FormItem> </FormItem>
<FormItem label="游戏分类"> <FormItem label="游戏分类">
<Select option-label-prop="label" v-model:value="form.category"> <Select
<SelectOption v-model:value="form.category"
v-for="item in GAME_CATEGORY_OPTIONS" :options="categoryOptions"
:key="item.value" option-label-prop="label"
:value="item.value" placeholder="请选择游戏分类"
:label="`${item.name}`"> />
{{ item.name }}
</SelectOption>
</Select>
</FormItem> </FormItem>
<FormItem label="名称"> <FormItem label="名称">
<Input v-model:value="form.name" placeholder="请输入名称" /> <Input v-model:value="form.name" placeholder="请输入名称" />
@ -412,21 +457,22 @@ void loadData(true);
<Input v-model:value="form.amounts" placeholder="金币必须是整数多个逗号隔开" /> <Input v-model:value="form.amounts" placeholder="金币必须是整数多个逗号隔开" />
</FormItem> </FormItem>
<FormItem label="是否全屏"> <FormItem label="是否全屏">
<Select option-label-prop="label" v-model:value="form.fullScreen" allow-clear> <Select
<SelectOption :value="true" label="是"></SelectOption> v-model:value="form.fullScreen"
<SelectOption :value="false" label="否"></SelectOption> :options="booleanOptions"
</Select> allow-clear
option-label-prop="label"
placeholder="请选择是否全屏"
/>
</FormItem> </FormItem>
<FormItem label="游戏模式"> <FormItem label="游戏模式">
<Select option-label-prop="label" v-model:value="form.gameMode" allow-clear> <Select
<SelectOption v-model:value="form.gameMode"
v-for="item in GAME_MODE_OPTIONS" :options="gameModeOptions"
:key="item.value" allow-clear
:value="item.value" option-label-prop="label"
:label="`${item.name}`"> placeholder="请选择游戏模式"
{{ item.name }} />
</SelectOption>
</Select>
</FormItem> </FormItem>
<FormItem label="宽"> <FormItem label="宽">
<Input v-model:value="form.width" placeholder="宽度" /> <Input v-model:value="form.width" placeholder="宽度" />
@ -435,24 +481,25 @@ void loadData(true);
<Input v-model:value="form.height" placeholder="高度" /> <Input v-model:value="form.height" placeholder="高度" />
</FormItem> </FormItem>
<FormItem label="状态"> <FormItem label="状态">
<Select option-label-prop="label" v-model:value="form.showcase" allow-clear> <Select
<SelectOption :value="false" label="下架">下架</SelectOption> v-model:value="form.showcase"
<SelectOption :value="true" label="上架">上架</SelectOption> :options="showcaseOptions"
</Select> allow-clear
option-label-prop="label"
placeholder="请选择状态"
/>
</FormItem> </FormItem>
<FormItem label="排序"> <FormItem label="排序">
<InputNumber v-model:value="form.sort" :max="99999" :min="0" style="width: 100%" /> <InputNumber v-model:value="form.sort" :max="99999" :min="0" style="width: 100%" />
</FormItem> </FormItem>
<FormItem label="区域"> <FormItem label="区域">
<Select option-label-prop="label" v-model:value="form.regionList" mode="multiple"> <Select
<SelectOption v-model:value="form.regionList"
v-for="item in regions" :options="regionSelectOptions"
:key="item.id" mode="multiple"
:value="item.id" option-label-prop="label"
:label="`${item.regionName}`"> placeholder="请选择区域"
{{ item.regionName }} />
</SelectOption>
</Select>
</FormItem> </FormItem>
</Form> </Form>
</Modal> </Modal>

View File

@ -31,7 +31,6 @@ import {
Modal, Modal,
Pagination, Pagination,
Select, Select,
SelectOption,
Space, Space,
Switch, Switch,
Table, Table,
@ -109,6 +108,16 @@ const weekStarForm = reactive({
}); });
const weekStarGiftOptions = ref<Array<Record<string, any>>>([]); const weekStarGiftOptions = ref<Array<Record<string, any>>>([]);
function getWeekStarSelectOptions(currentValue: string) {
return weekStarGiftOptions.value.map((item) => ({
disabled:
isWeekStarGiftDisabled(item.id) &&
String(currentValue || '') !== String(item.id || ''),
label: String(item.giftName || item.id || '-'),
value: item.id as any,
}));
}
const cpLoading = ref(false); const cpLoading = ref(false);
const cpSaving = ref(false); const cpSaving = ref(false);
const cpForm = reactive({ const cpForm = reactive({
@ -541,36 +550,24 @@ async function handleCpSave() {
disabled disabled
:options="sysOriginOptions" :options="sysOriginOptions"
/> />
<Select option-label-prop="label" v-model:value="weekStarForm.giftOne" placeholder="礼物1"> <Select
<SelectOption v-model:value="weekStarForm.giftOne"
v-for="item in weekStarGiftOptions" :options="getWeekStarSelectOptions(String(weekStarForm.giftOne || ''))"
:key="item.id" option-label-prop="label"
:value="item.id" placeholder="礼物1"
:disabled="isWeekStarGiftDisabled(item.id) && String(weekStarForm.giftOne) !== String(item.id)" />
:label="`${item.giftName}`"> <Select
{{ item.giftName }} v-model:value="weekStarForm.giftTwo"
</SelectOption> :options="getWeekStarSelectOptions(String(weekStarForm.giftTwo || ''))"
</Select> option-label-prop="label"
<Select option-label-prop="label" v-model:value="weekStarForm.giftTwo" placeholder="礼物2"> placeholder="礼物2"
<SelectOption />
v-for="item in weekStarGiftOptions" <Select
:key="item.id" v-model:value="weekStarForm.giftThree"
:value="item.id" :options="getWeekStarSelectOptions(String(weekStarForm.giftThree || ''))"
:disabled="isWeekStarGiftDisabled(item.id) && String(weekStarForm.giftTwo) !== String(item.id)" option-label-prop="label"
:label="`${item.giftName}`"> placeholder="礼物3"
{{ item.giftName }} />
</SelectOption>
</Select>
<Select option-label-prop="label" v-model:value="weekStarForm.giftThree" placeholder="礼物3">
<SelectOption
v-for="item in weekStarGiftOptions"
:key="item.id"
:value="item.id"
:disabled="isWeekStarGiftDisabled(item.id) && String(weekStarForm.giftThree) !== String(item.id)"
:label="`${item.giftName}`">
{{ item.giftName }}
</SelectOption>
</Select>
</Space> </Space>
</Modal> </Modal>
</Page> </Page>

View File

@ -22,7 +22,6 @@ import {
Modal, Modal,
Pagination, Pagination,
Select, Select,
SelectOption,
Space, Space,
Table, Table,
message, message,
@ -89,6 +88,16 @@ const languageColumns = [
{ dataIndex: 'actions', key: 'actions', title: '操作', width: 150 }, { dataIndex: 'actions', key: 'actions', title: '操作', width: 150 },
]; ];
const hallFameShowcaseOptions = [
{ label: '否', value: true as any },
{ label: '是', value: false as any },
];
const languageSelectOptions = LANGUAGE_OPTIONS.map((item) => ({
label: item.name,
value: item.value as any,
}));
watch( watch(
sysOriginOptions, sysOriginOptions,
(options) => { (options) => {
@ -305,10 +314,11 @@ loadData(true);
<Input v-model:value="editForm.sort" placeholder="顺序(越大越靠前)" /> <Input v-model:value="editForm.sort" placeholder="顺序(越大越靠前)" />
</FormItem> </FormItem>
<FormItem label="上架"> <FormItem label="上架">
<Select option-label-prop="label" v-model:value="editForm.del"> <Select
<SelectOption :value="true" label="否"></SelectOption> v-model:value="editForm.del"
<SelectOption :value="false" label="是"></SelectOption> :options="hallFameShowcaseOptions"
</Select> option-label-prop="label"
/>
</FormItem> </FormItem>
</Form> </Form>
</Modal> </Modal>
@ -366,15 +376,12 @@ loadData(true);
> >
<Form layout="vertical"> <Form layout="vertical">
<FormItem label="语言"> <FormItem label="语言">
<Select option-label-prop="label" v-model:value="languageForm.language" :disabled="!!languageForm.id"> <Select
<SelectOption v-model:value="languageForm.language"
v-for="item in LANGUAGE_OPTIONS" :disabled="!!languageForm.id"
:key="item.value" :options="languageSelectOptions"
:value="item.value" option-label-prop="label"
:label="`${item.name}`"> />
{{ item.name }}
</SelectOption>
</Select>
</FormItem> </FormItem>
<FormItem label="活动名称"> <FormItem label="活动名称">
<Input <Input

View File

@ -32,7 +32,6 @@ import {
Modal, Modal,
Pagination, Pagination,
Select, Select,
SelectOption,
Switch, Switch,
Table, Table,
TextArea, TextArea,
@ -51,6 +50,11 @@ const ANNOUNCEMENT_STATUS_OPTIONS = [
{ name: '未发布', value: false }, { name: '未发布', value: false },
]; ];
const NOTICE_TYPE_OPTIONS = [
{ label: '通知', value: 'notification' as any },
{ label: '活动', value: 'activity' as any },
];
function createForm() { function createForm() {
return { return {
cover: '', cover: '',
@ -401,10 +405,11 @@ async function handleShelfChange(record: Record<string, any>, checked: boolean)
<div class="field"> <div class="field">
<div class="label">类型</div> <div class="label">类型</div>
<Select option-label-prop="label" v-model:value="form.type"> <Select
<SelectOption value="notification" label="通知">通知</SelectOption> v-model:value="form.type"
<SelectOption value="activity" label="活动">活动</SelectOption> :options="NOTICE_TYPE_OPTIONS"
</Select> option-label-prop="label"
/>
</div> </div>
<div class="field"> <div class="field">

View File

@ -24,7 +24,6 @@ import {
Modal, Modal,
Pagination, Pagination,
Select, Select,
SelectOption,
Space, Space,
TabPane, TabPane,
Table, Table,
@ -57,6 +56,35 @@ const LANGUAGE_OPTIONS = [
{ name: '其他语言', value: 'en' }, { name: '其他语言', value: 'en' },
]; ];
const appPlatformSelectOptions = APP_PLATFORM_OPTIONS.map((item) => ({
label: item.name,
value: item.value as any,
}));
const deviceTypeSelectOptions = DEVICE_TYPE_OPTIONS.map((item) => ({
label: item.name,
value: item.value as any,
}));
const pushStatusSelectOptions = PUSH_STATUS_OPTIONS.map((item) => ({
label: item.name,
value: item.value as any,
}));
const shelfStatusSelectOptions = SHELF_STATUS_OPTIONS.map((item) => ({
label: item.name,
value: item.value as any,
}));
const languageSelectOptions = LANGUAGE_OPTIONS.map((item) => ({
label: item.name,
value: item.value as any,
}));
const businessSceneOptions = [
{ label: '官方通知', value: 'OFFICIAL_MESSAGE_NOTICE' as any },
];
const accessStore = useAccessStore(); const accessStore = useAccessStore();
const sysOriginOptions = computed(() => { const sysOriginOptions = computed(() => {
const options = getAllowedSysOrigins(accessStore.accessCodes || []); const options = getAllowedSysOrigins(accessStore.accessCodes || []);
@ -354,43 +382,36 @@ watch(
/> />
</FormItem> </FormItem>
<FormItem label="客户端"> <FormItem label="客户端">
<Select option-label-prop="label" v-model:value="newPushForm.platform" allow-clear> <Select
<SelectOption v-model:value="newPushForm.platform"
v-for="item in APP_PLATFORM_OPTIONS" allow-clear
:key="item.value" :options="appPlatformSelectOptions"
:value="item.value" option-label-prop="label"
:label="`${item.name}`"> />
{{ item.name }}
</SelectOption>
</Select>
</FormItem> </FormItem>
<FormItem label="推送平台"> <FormItem label="推送平台">
<Select option-label-prop="label" v-model:value="newPushForm.deviceType" allow-clear> <Select
<SelectOption v-model:value="newPushForm.deviceType"
v-for="item in DEVICE_TYPE_OPTIONS" allow-clear
:key="item.value" :options="deviceTypeSelectOptions"
:value="item.value" option-label-prop="label"
:label="`${item.name}`"> />
{{ item.name }}
</SelectOption>
</Select>
</FormItem> </FormItem>
<FormItem label="语言"> <FormItem label="语言">
<Select option-label-prop="label" v-model:value="newPushForm.language" allow-clear> <Select
<SelectOption v-model:value="newPushForm.language"
v-for="item in LANGUAGE_OPTIONS" allow-clear
:key="item.value" :options="languageSelectOptions"
:value="item.value" option-label-prop="label"
:label="`${item.name}`"> />
{{ item.name }}
</SelectOption>
</Select>
</FormItem> </FormItem>
</div> </div>
<FormItem label="业务场景"> <FormItem label="业务场景">
<Select option-label-prop="label" v-model:value="newPushForm.businessScene"> <Select
<SelectOption value="OFFICIAL_MESSAGE_NOTICE" label="官方通知">官方通知</SelectOption> v-model:value="newPushForm.businessScene"
</Select> :options="businessSceneOptions"
option-label-prop="label"
/>
</FormItem> </FormItem>
<FormItem label="定投UID"> <FormItem label="定投UID">
<Input <Input
@ -420,8 +441,7 @@ watch(
allow-clear allow-clear
placeholder="客户端" placeholder="客户端"
style="width: 120px" style="width: 120px"
:options="appPlatformSelectOptions"
:options="APP_PLATFORM_OPTIONS.map((item) => ({ label: `${item.name}`, value: item.value as any }))"
/> />
<Select <Select
option-label-prop="label" option-label-prop="label"
@ -429,30 +449,16 @@ watch(
allow-clear allow-clear
placeholder="推送平台" placeholder="推送平台"
style="width: 120px" style="width: 120px"
> :options="deviceTypeSelectOptions"
<SelectOption />
v-for="item in DEVICE_TYPE_OPTIONS"
:key="item.value"
:value="item.value"
:label="`${item.name}`">
{{ item.name }}
</SelectOption>
</Select>
<Select <Select
option-label-prop="label" option-label-prop="label"
v-model:value="logQuery.pushStatus" v-model:value="logQuery.pushStatus"
allow-clear allow-clear
placeholder="状态" placeholder="状态"
style="width: 120px" style="width: 120px"
> :options="pushStatusSelectOptions"
<SelectOption />
v-for="item in PUSH_STATUS_OPTIONS"
:key="item.value"
:value="item.value"
:label="`${item.name}`">
{{ item.name }}
</SelectOption>
</Select>
<RangePicker <RangePicker
v-model:value="logRange" v-model:value="logRange"
show-time show-time
@ -505,15 +511,8 @@ watch(
allow-clear allow-clear
placeholder="状态" placeholder="状态"
style="width: 120px" style="width: 120px"
> :options="shelfStatusSelectOptions"
<SelectOption />
v-for="item in SHELF_STATUS_OPTIONS"
:key="String(item.value)"
:value="item.value"
:label="`${item.name}`">
{{ item.name }}
</SelectOption>
</Select>
<Button :loading="taskLoading" type="primary" @click="loadTasks(true)"> <Button :loading="taskLoading" type="primary" @click="loadTasks(true)">
搜索 搜索
</Button> </Button>
@ -580,53 +579,40 @@ watch(
</FormItem> </FormItem>
<div class="grid-two"> <div class="grid-two">
<FormItem label="客户端"> <FormItem label="客户端">
<Select option-label-prop="label" v-model:value="taskForm.platform"> <Select
<SelectOption v-model:value="taskForm.platform"
v-for="item in APP_PLATFORM_OPTIONS" :options="appPlatformSelectOptions"
:key="item.value" option-label-prop="label"
:value="item.value" />
:label="`${item.name}`">
{{ item.name }}
</SelectOption>
</Select>
</FormItem> </FormItem>
<FormItem label="推送平台"> <FormItem label="推送平台">
<Select option-label-prop="label" v-model:value="taskForm.deviceType"> <Select
<SelectOption v-model:value="taskForm.deviceType"
v-for="item in DEVICE_TYPE_OPTIONS" :options="deviceTypeSelectOptions"
:key="item.value" option-label-prop="label"
:value="item.value" />
:label="`${item.name}`">
{{ item.name }}
</SelectOption>
</Select>
</FormItem> </FormItem>
<FormItem label="语言"> <FormItem label="语言">
<Select option-label-prop="label" v-model:value="taskForm.language" allow-clear> <Select
<SelectOption v-model:value="taskForm.language"
v-for="item in LANGUAGE_OPTIONS" allow-clear
:key="item.value" :options="languageSelectOptions"
:value="item.value" option-label-prop="label"
:label="`${item.name}`"> />
{{ item.name }}
</SelectOption>
</Select>
</FormItem> </FormItem>
<FormItem label="业务场景"> <FormItem label="业务场景">
<Select option-label-prop="label" v-model:value="taskForm.businessScene"> <Select
<SelectOption value="OFFICIAL_MESSAGE_NOTICE" label="官方通知">官方通知</SelectOption> v-model:value="taskForm.businessScene"
</Select> :options="businessSceneOptions"
option-label-prop="label"
/>
</FormItem> </FormItem>
<FormItem label="状态"> <FormItem label="状态">
<Select option-label-prop="label" v-model:value="taskForm.shelfStatus"> <Select
<SelectOption v-model:value="taskForm.shelfStatus"
v-for="item in SHELF_STATUS_OPTIONS" :options="shelfStatusSelectOptions"
:key="String(item.value)" option-label-prop="label"
:value="item.value" />
:label="`${item.name}`">
{{ item.name }}
</SelectOption>
</Select>
</FormItem> </FormItem>
</div> </div>
<FormItem label="标题"> <FormItem label="标题">

View File

@ -25,7 +25,6 @@ import {
InputNumber, InputNumber,
Modal, Modal,
Select, Select,
SelectOption,
Space, Space,
Table, Table,
Tag, Tag,
@ -130,6 +129,26 @@ const columns = [
{ dataIndex: 'time', key: 'time', title: '时间', width: 220 }, { dataIndex: 'time', key: 'time', title: '时间', width: 220 },
{ dataIndex: 'actions', key: 'actions', title: '操作', width: 260 }, { dataIndex: 'actions', key: 'actions', title: '操作', width: 260 },
]; ];
const roomEventSelectOptions = ROOM_EVENT_OPTIONS.map((item) => ({
label: item.name,
value: item.value as any,
}));
const roomUserEventSelectOptions = ROOM_USER_EVENT_OPTIONS.map((item) => ({
label: item.name,
value: item.value as any,
}));
const roomRoleActionOptions = [
...ROOM_ROLE_OPTIONS.map((item) => ({
disabled: item.value === 'HOMEOWNER',
label: item.name,
value: item.value as any,
})),
{ label: '游客', value: 'TOURIST' as any },
];
const approvalStateOptions = [
{ label: '通过', value: 'PASS' as any },
{ label: '不通过', value: 'NOT_PASS' as any },
];
watch( watch(
sysOriginOptions, sysOriginOptions,
@ -561,15 +580,11 @@ async function handleCopy(value: number | string) {
/> />
</FormItem> </FormItem>
<FormItem label="状态"> <FormItem label="状态">
<Select option-label-prop="label" v-model:value="editForm.event"> <Select
<SelectOption option-label-prop="label"
v-for="item in ROOM_EVENT_OPTIONS" v-model:value="editForm.event"
:key="item.value" :options="roomEventSelectOptions"
:value="item.value" />
:label="`${item.name}`">
{{ item.name }}
</SelectOption>
</Select>
</FormItem> </FormItem>
<FormItem label="管理员数量"> <FormItem label="管理员数量">
<InputNumber <InputNumber
@ -601,15 +616,11 @@ async function handleCopy(value: number | string) {
<Input v-model:value="memberActionForm.userAccount" /> <Input v-model:value="memberActionForm.userAccount" />
</FormItem> </FormItem>
<FormItem label="事件"> <FormItem label="事件">
<Select option-label-prop="label" v-model:value="memberActionForm.event"> <Select
<SelectOption option-label-prop="label"
v-for="item in ROOM_USER_EVENT_OPTIONS" v-model:value="memberActionForm.event"
:key="item.value" :options="roomUserEventSelectOptions"
:value="item.value" />
:label="`${item.name}`">
{{ item.name }}
</SelectOption>
</Select>
</FormItem> </FormItem>
</Form> </Form>
</Modal> </Modal>
@ -633,17 +644,11 @@ async function handleCopy(value: number | string) {
<Input v-model:value="roleActionForm.userAccount" /> <Input v-model:value="roleActionForm.userAccount" />
</FormItem> </FormItem>
<FormItem label="权限"> <FormItem label="权限">
<Select option-label-prop="label" v-model:value="roleActionForm.roles"> <Select
<SelectOption option-label-prop="label"
v-for="item in ROOM_ROLE_OPTIONS" v-model:value="roleActionForm.roles"
:key="item.value" :options="roomRoleActionOptions"
:disabled="item.value === 'HOMEOWNER'" />
:value="item.value"
:label="`${item.name}`">
{{ item.name }}
</SelectOption>
<SelectOption value="TOURIST" label="游客">游客</SelectOption>
</Select>
</FormItem> </FormItem>
</Form> </Form>
</Modal> </Modal>
@ -659,10 +664,11 @@ async function handleCopy(value: number | string) {
> >
<Form layout="vertical"> <Form layout="vertical">
<FormItem label="审批状态"> <FormItem label="审批状态">
<Select option-label-prop="label" v-model:value="approvalState"> <Select
<SelectOption value="PASS" label="通过">通过</SelectOption> option-label-prop="label"
<SelectOption value="NOT_PASS" label="不通过">不通过</SelectOption> v-model:value="approvalState"
</Select> :options="approvalStateOptions"
/>
</FormItem> </FormItem>
<FormItem label="审批内容"> <FormItem label="审批内容">
<div v-if="approvalType === 'ROOM_AVATAR'" class="approval-preview"> <div v-if="approvalType === 'ROOM_AVATAR'" class="approval-preview">

View File

@ -29,7 +29,6 @@ import {
Radio, Radio,
RadioGroup, RadioGroup,
Select, Select,
SelectOption,
TextArea, TextArea,
message, message,
} from 'antdv-next'; } from 'antdv-next';
@ -123,6 +122,12 @@ const cancelRestoreForm = reactive({
}); });
const canExecuteUserSwap = computed(() => !userSwapBlocked.value); const canExecuteUserSwap = computed(() => !userSwapBlocked.value);
const countryOptions = computed(() =>
countries.value.map((item) => ({
label: `${item.aliasName || '-'} / ${item.alphaTwo || '-'}`,
value: item.id as any,
})),
);
function prettyJson(value: any) { function prettyJson(value: any) {
try { try {
@ -361,15 +366,11 @@ void loadCountries();
<Form layout="vertical"> <Form layout="vertical">
<div class="grid three"> <div class="grid three">
<FormItem label="签名平台"> <FormItem label="签名平台">
<Select option-label-prop="label" v-model:value="apiSignForm.platform"> <Select
<SelectOption option-label-prop="label"
v-for="item in ORIGIN_PLATFORM_OPTIONS" v-model:value="apiSignForm.platform"
:key="item.value" :options="ORIGIN_PLATFORM_OPTIONS"
:value="item.value" />
:label="`${item.label}`">
{{ item.label }}
</SelectOption>
</Select>
</FormItem> </FormItem>
<FormItem label="签名KEY"> <FormItem label="签名KEY">
<Input v-model:value="apiSignForm.key" /> <Input v-model:value="apiSignForm.key" />
@ -450,19 +451,11 @@ void loadCountries();
<FormItem label="国家"> <FormItem label="国家">
<Select option-label-prop="label" <Select option-label-prop="label"
v-model:value="roomRegionForm.countryId" v-model:value="roomRegionForm.countryId"
:options="countryOptions"
show-search show-search
:filter-option="filterCountry" :filter-option="filterCountry"
placeholder="请选择国家" placeholder="请选择国家"
> />
<SelectOption
v-for="item in countries"
:key="item.id"
:label="`${item.aliasName || '-'} / ${item.alphaTwo || '-'}`"
:value="item.id"
>
{{ item.aliasName || '-' }} / {{ item.alphaTwo || '-' }}
</SelectOption>
</Select>
</FormItem> </FormItem>
</div> </div>
<FormItem> <FormItem>

View File

@ -30,7 +30,6 @@ import {
Modal, Modal,
Pagination, Pagination,
Select, Select,
SelectOption,
Space, Space,
Switch, Switch,
Table, Table,
@ -82,6 +81,11 @@ const sellerWaterTotal = ref(0);
const sellerWaterLoading = ref(false); const sellerWaterLoading = ref(false);
const modalMode = ref<ModalMode>('create'); const modalMode = ref<ModalMode>('create');
const freightRechargeTypeOptions = FREIGHT_RECHARGE_TYPE_OPTIONS.map((item) => ({
label: item.name,
value: item.value as any,
}));
const query = reactive<Record<string, any>>({ const query = reactive<Record<string, any>>({
close: undefined, close: undefined,
cursor: 1, cursor: 1,
@ -506,15 +510,12 @@ void loadData(true);
<Input v-model:value="modalForm.amount" placeholder="请输入金额" /> <Input v-model:value="modalForm.amount" placeholder="请输入金额" />
</FormItem> </FormItem>
<FormItem v-if="modalMode !== 'deduct'" label="充值类型"> <FormItem v-if="modalMode !== 'deduct'" label="充值类型">
<Select option-label-prop="label" v-model:value="modalForm.rechargeType" allow-clear> <Select
<SelectOption v-model:value="modalForm.rechargeType"
v-for="item in FREIGHT_RECHARGE_TYPE_OPTIONS" allow-clear
:key="item.value" :options="freightRechargeTypeOptions"
:value="item.value" option-label-prop="label"
:label="`${item.name}`"> />
{{ item.name }}
</SelectOption>
</Select>
</FormItem> </FormItem>
<FormItem label="备注"> <FormItem label="备注">
<Input v-model:value="modalForm.remark" placeholder="请输入备注" /> <Input v-model:value="modalForm.remark" placeholder="请输入备注" />

View File

@ -9,7 +9,6 @@ import {
Input, Input,
Pagination, Pagination,
Select, Select,
SelectOption,
Space, Space,
Table, Table,
} from 'antdv-next'; } from 'antdv-next';
@ -48,6 +47,11 @@ const columns = [
{ dataIndex: 'actions', key: 'actions', title: '操作', width: 100 }, { dataIndex: 'actions', key: 'actions', title: '操作', width: 100 },
]; ];
const shelfStatusOptions = PROPS_SHELF_STATUS_OPTIONS.map((item) => ({
label: item.name,
value: item.value as any,
}));
async function loadData(reset = false) { async function loadData(reset = false) {
if (!props.open || !query.sysOrigin) { if (!props.open || !query.sysOrigin) {
return; return;
@ -96,20 +100,15 @@ watch(
@close="emit('close')" @close="emit('close')"
> >
<Space class="toolbar" wrap> <Space class="toolbar" wrap>
<Select option-label-prop="label" <Select
v-model:value="query.shelfStatus" v-model:value="query.shelfStatus"
allow-clear allow-clear
:options="shelfStatusOptions"
option-label-prop="label"
placeholder="请选择状态"
style="width: 120px" style="width: 120px"
@change="loadData(true)" @change="loadData(true)"
> />
<SelectOption
v-for="item in PROPS_SHELF_STATUS_OPTIONS"
:key="String(item.value)"
:value="item.value"
:label="`${item.name}`">
{{ item.name }}
</SelectOption>
</Select>
<Input <Input
v-model:value="query.id" v-model:value="query.id"
allow-clear allow-clear

View File

@ -18,7 +18,6 @@ import {
Image, Image,
Input, Input,
Select, Select,
SelectOption,
Space, Space,
Switch, Switch,
message, message,
@ -82,6 +81,26 @@ const luckyBoxRules = computed<Array<Record<string, any>>>(() =>
); );
const tips = computed(() => PROP_ACTIVITY_TYPE_HELP[form.activityType] || {}); const tips = computed(() => PROP_ACTIVITY_TYPE_HELP[form.activityType] || {});
const title = computed(() => (isUpdate.value ? '修改规则' : '新增规则')); const title = computed(() => (isUpdate.value ? '修改规则' : '新增规则'));
const activityTypeOptions = PROP_ACTIVITY_TYPES.map((item) => ({
label: item.name,
value: item.value as any,
}));
const productOptions = computed(() =>
products.value.map((item) => ({
label: `${item.unitPrice || '-'} / ${item.productId} / ${item.description || '-'}`,
value: item.productId as any,
})),
);
const crystalLevelOptions = [1, 2, 3, 4, 5].map((level) => ({
label: `${level}`,
value: level as any,
}));
const gameOptions = computed(() =>
games.value.map((item) => ({
label: item.name || '-',
value: item.id as any,
})),
);
function resetForm() { function resetForm() {
form.activityType = ''; form.activityType = '';
@ -327,16 +346,9 @@ async function handleSubmit() {
<Select option-label-prop="label" <Select option-label-prop="label"
v-model:value="form.activityType" v-model:value="form.activityType"
:disabled="isUpdate" :disabled="isUpdate"
:options="activityTypeOptions"
@change="handleActivityTypeChange" @change="handleActivityTypeChange"
> />
<SelectOption
v-for="item in PROP_ACTIVITY_TYPES"
:key="item.value"
:value="item.value"
:label="`${item.name}`">
{{ item.name }}
</SelectOption>
</Select>
</FormItem> </FormItem>
<template v-if="form.activityType"> <template v-if="form.activityType">
@ -349,19 +361,10 @@ async function handleSubmit() {
<Select option-label-prop="label" <Select option-label-prop="label"
v-model:value="ruleState.productId" v-model:value="ruleState.productId"
:loading="productsLoading" :loading="productsLoading"
:options="productOptions"
option-filter-prop="label" option-filter-prop="label"
show-search show-search
> />
<SelectOption
v-for="item in products"
:key="item.productId"
:label="`${item.unitPrice || '-'} ${item.productId}`"
:value="item.productId"
>
{{ item.unitPrice || '-' }} / {{ item.productId }} /
{{ item.description || '-' }}
</SelectOption>
</Select>
</FormItem> </FormItem>
</template> </template>
@ -385,11 +388,11 @@ async function handleSubmit() {
<template v-else-if="isCrystal"> <template v-else-if="isCrystal">
<FormItem :label="tips.level || '等级'"> <FormItem :label="tips.level || '等级'">
<Select option-label-prop="label" v-model:value="ruleState.level"> <Select
<SelectOption v-for="level in [1, 2, 3, 4, 5]" :key="level" :value="level" :label="`${level}`"> option-label-prop="label"
{{ level }} v-model:value="ruleState.level"
</SelectOption> :options="crystalLevelOptions"
</Select> />
</FormItem> </FormItem>
<FormItem :label="tips.milestone || '里程碑'"> <FormItem :label="tips.milestone || '里程碑'">
<Input v-model:value="ruleState.milestone" /> <Input v-model:value="ruleState.milestone" />
@ -453,18 +456,10 @@ async function handleSubmit() {
<Select option-label-prop="label" <Select option-label-prop="label"
v-model:value="ruleState.gameConfId" v-model:value="ruleState.gameConfId"
:loading="gamesLoading" :loading="gamesLoading"
:options="gameOptions"
option-filter-prop="label" option-filter-prop="label"
show-search show-search
> />
<SelectOption
v-for="item in games"
:key="item.id"
:label="item.name"
:value="item.id"
>
{{ item.name }}
</SelectOption>
</Select>
</FormItem> </FormItem>
<FormItem label="目标"> <FormItem label="目标">
<Input v-model:value="ruleState.target" /> <Input v-model:value="ruleState.target" />

View File

@ -19,7 +19,6 @@ import {
Input, Input,
Modal, Modal,
Select, Select,
SelectOption,
Switch, Switch,
message, message,
} from 'antdv-next'; } from 'antdv-next';
@ -74,6 +73,14 @@ const isSourceRequired = computed(
); );
const showExpandUpload = computed(() => form.type === 'CHAT_BUBBLE'); const showExpandUpload = computed(() => form.type === 'CHAT_BUBBLE');
const title = computed(() => (isUpdate.value ? '修改资源' : '新增资源')); const title = computed(() => (isUpdate.value ? '修改资源' : '新增资源'));
const propsTypeOptions = PROPS_TYPES.map((item) => ({
label: item.name,
value: item.value as any,
}));
const nobleVipNameOptions = NOBLE_VIP_OPTIONS.map((item) => ({
label: item.name,
value: item.value as any,
}));
function resetForm() { function resetForm() {
form.adminFree = false; form.adminFree = false;
@ -259,15 +266,11 @@ async function handleSubmit() {
></SysOriginSelect> ></SysOriginSelect>
</FormItem> </FormItem>
<FormItem label="类型"> <FormItem label="类型">
<Select option-label-prop="label" v-model:value="form.type"> <Select
<SelectOption option-label-prop="label"
v-for="item in PROPS_TYPES" v-model:value="form.type"
:key="item.value" :options="propsTypeOptions"
:value="item.value" />
:label="`${item.name}`">
{{ item.name }}
</SelectOption>
</Select>
</FormItem> </FormItem>
<FormItem label="封面"> <FormItem label="封面">
<input <input
@ -331,15 +334,12 @@ async function handleSubmit() {
</div> </div>
</FormItem> </FormItem>
<FormItem label="名称"> <FormItem label="名称">
<Select option-label-prop="label" v-if="form.type === 'NOBLE_VIP'" v-model:value="form.name"> <Select
<SelectOption v-if="form.type === 'NOBLE_VIP'"
v-for="item in NOBLE_VIP_OPTIONS" option-label-prop="label"
:key="item.value" v-model:value="form.name"
:value="item.value" :options="nobleVipNameOptions"
:label="`${item.name}`"> />
{{ item.name }}
</SelectOption>
</Select>
<Input v-else v-model:value="form.name" /> <Input v-else v-model:value="form.name" />
</FormItem> </FormItem>
<FormItem v-if="!isUpdate" label="编码"> <FormItem v-if="!isUpdate" label="编码">

View File

@ -12,7 +12,6 @@ import {
DescriptionsItem, DescriptionsItem,
Modal, Modal,
Select, Select,
SelectOption,
Space, Space,
Table, Table,
} from 'antdv-next'; } from 'antdv-next';
@ -63,6 +62,14 @@ const datePickerType = computed(
const dateValueFormat = computed( const dateValueFormat = computed(
() => ACTIVITY_DATE_TYPE_MAP[query.dateType as keyof typeof ACTIVITY_DATE_TYPE_MAP].format, () => ACTIVITY_DATE_TYPE_MAP[query.dateType as keyof typeof ACTIVITY_DATE_TYPE_MAP].format,
); );
const dateTypeOptions = ACTIVITY_DATE_TYPE_OPTIONS.map((item) => ({
label: item.label,
value: item.value as any,
}));
const propsTypeOptions = PROPS_TYPES.map((item) => ({
label: item.name,
value: item.value as any,
}));
async function loadData() { async function loadData() {
if (!props.open || !query.sysOrigin || !query.date || !query.propsType) { if (!props.open || !query.sysOrigin || !query.date || !query.propsType) {
@ -119,24 +126,20 @@ watch(
<SysOriginSelect v-model:value="query.sysOrigin" style="width: 140px" @change="loadData" <SysOriginSelect v-model:value="query.sysOrigin" style="width: 140px" @change="loadData"
:options="sysOriginOptions" :options="sysOriginOptions"
></SysOriginSelect> ></SysOriginSelect>
<Select option-label-prop="label" v-model:value="query.dateType" style="width: 120px" @change="loadData"> <Select
<SelectOption option-label-prop="label"
v-for="item in ACTIVITY_DATE_TYPE_OPTIONS" v-model:value="query.dateType"
:key="item.value" :options="dateTypeOptions"
:value="item.value" style="width: 120px"
:label="`${item.label}`"> @change="loadData"
{{ item.label }} />
</SelectOption> <Select
</Select> option-label-prop="label"
<Select option-label-prop="label" v-model:value="query.propsType" style="width: 160px" @change="loadData"> v-model:value="query.propsType"
<SelectOption :options="propsTypeOptions"
v-for="item in PROPS_TYPES" style="width: 160px"
:key="item.value" @change="loadData"
:value="item.value" />
:label="`${item.name}`">
{{ item.name }}
</SelectOption>
</Select>
<DatePicker <DatePicker
v-model:value="query.date" v-model:value="query.date"
:format="dateValueFormat" :format="dateValueFormat"

View File

@ -77,7 +77,11 @@ watch(
if (!open) { if (!open) {
return; return;
} }
query.sysOrigin = sysOriginOptions.value[0]?.value || 'LIKEI'; query.sysOrigin =
props.record?.sysOrigin ||
props.record?.commodity?.sysOrigin ||
sysOriginOptions.value[0]?.value ||
'LIKEI';
query.date = dayjs().format('YYYYMM'); query.date = dayjs().format('YYYYMM');
query.propsSourceId = String(props.record?.id || ''); query.propsSourceId = String(props.record?.id || '');
void loadData(); void loadData();

View File

@ -17,7 +17,6 @@ import {
FormItem, FormItem,
Input, Input,
Select, Select,
SelectOption,
Space, Space,
Switch, Switch,
message, message,
@ -110,6 +109,24 @@ const rewardItems = computed(() => form.rewardConfigList);
const sourceSelectOptions = computed<DraftSourceOption[]>( const sourceSelectOptions = computed<DraftSourceOption[]>(
() => sourceOptionsMap[draft.type]?.list || [], () => sourceOptionsMap[draft.type]?.list || [],
); );
const addTypeOptions = computed(() =>
PROPS_SOURCE_GROUP_ADD_TYPES.map((type) => ({
label: getAddTypeName(type),
value: type as any,
})),
);
const draftResourceOptions = computed(() =>
sourceSelectOptions.value.map((item) => ({
label: `${item.id} ${item.name}`,
value: item.id as any,
})),
);
function resetSourceOptionsMap() {
Object.keys(sourceOptionsMap).forEach((key) => {
delete sourceOptionsMap[key];
});
}
function createTypeStore(type: string) { function createTypeStore(type: string) {
if (!sourceOptionsMap[type]) { if (!sourceOptionsMap[type]) {
@ -140,6 +157,7 @@ watch(
if (!open) { if (!open) {
return; return;
} }
resetSourceOptionsMap();
const record = props.record; const record = props.record;
if (!record) { if (!record) {
resetForm(); resetForm();
@ -162,6 +180,10 @@ watch(
() => props.sysOrigin, () => props.sysOrigin,
(value) => { (value) => {
if (value) { if (value) {
if (form.sysOrigin && form.sysOrigin !== value) {
resetSourceOptionsMap();
resetDraft();
}
form.sysOrigin = value; form.sysOrigin = value;
} }
}, },
@ -443,19 +465,13 @@ async function handleSubmit() {
<div class="draft-box"> <div class="draft-box">
<div class="draft-box__title">添加配置</div> <div class="draft-box__title">添加配置</div>
<FormItem label="奖励类型"> <FormItem label="奖励类型">
<Select option-label-prop="label" <Select
v-model:value="draft.type" v-model:value="draft.type"
:options="addTypeOptions"
option-label-prop="label"
placeholder="请选择奖励类型" placeholder="请选择奖励类型"
@change="handleDraftTypeChange" @change="handleDraftTypeChange"
> />
<SelectOption
v-for="type in PROPS_SOURCE_GROUP_ADD_TYPES"
:key="type"
:value="type"
:label="`${getAddTypeName(type)}`">
{{ getAddTypeName(type) }}
</SelectOption>
</Select>
</FormItem> </FormItem>
<template v-if="draft.type === 'SPECIAL_ID'"> <template v-if="draft.type === 'SPECIAL_ID'">
@ -484,23 +500,16 @@ async function handleSubmit() {
<template v-else> <template v-else>
<FormItem label="资源"> <FormItem label="资源">
<Select option-label-prop="label" <Select
v-model:value="draft.content" v-model:value="draft.content"
:options="draftResourceOptions"
:loading="draftLoading" :loading="draftLoading"
option-filter-prop="label" option-filter-prop="label"
option-label-prop="label"
placeholder="请选择资源" placeholder="请选择资源"
show-search show-search
@change="handleDraftContentChange" @change="handleDraftContentChange"
> />
<SelectOption
v-for="item in sourceSelectOptions"
:key="item.id"
:label="`${item.id} ${item.name}`"
:value="item.id"
>
{{ item.id }} / {{ item.name }}
</SelectOption>
</Select>
</FormItem> </FormItem>
<div v-if="selectedDraftResource" class="draft-preview"> <div v-if="selectedDraftResource" class="draft-preview">

View File

@ -12,7 +12,6 @@ import {
Input, Input,
Modal, Modal,
Select, Select,
SelectOption,
Switch, Switch,
message, message,
} from 'antdv-next'; } from 'antdv-next';
@ -77,6 +76,31 @@ const form = reactive<Record<string, any>>({
const title = computed(() => (form.id ? '修改商品' : '新增商品')); const title = computed(() => (form.id ? '修改商品' : '新增商品'));
const isNobleVip = computed(() => form.propsType === 'NOBLE_VIP'); const isNobleVip = computed(() => form.propsType === 'NOBLE_VIP');
const propsStoreTypeOptions = PROPS_STORE_TYPES.map((item) => ({
label: item.name,
value: item.value as any,
}));
const currencyTypeOptions = computed(() =>
PROPS_CURRENCY_TYPES.map((item) => ({
disabled: isNobleVip.value && item.value !== 'GOLD',
label: item.name,
value: item.value as any,
})),
);
const validDayOptions = PROPS_VALID_DAYS.map((item) => ({
label: item.name,
value: item.value as any,
}));
const nobleVipOptions = NOBLE_VIP_OPTIONS.map((item) => ({
label: item.name,
value: item.value as any,
}));
function resetSourceOptionsMap() {
Object.keys(sourceOptionsMap).forEach((key) => {
delete sourceOptionsMap[key];
});
}
function createTypeStore(type: string) { function createTypeStore(type: string) {
if (!sourceOptionsMap[type]) { if (!sourceOptionsMap[type]) {
@ -130,6 +154,7 @@ watch(
if (!open) { if (!open) {
return; return;
} }
resetSourceOptionsMap();
resetSelections(); resetSelections();
const record = props.record || {}; const record = props.record || {};
const commodity = record.commodity || record; const commodity = record.commodity || record;
@ -208,6 +233,13 @@ function updateSelectedSource(type: string, id: string | number) {
} }
} }
function getSourceSelectOptions(type: string) {
return (sourceOptionsMap[type]?.list || []).map((item) => ({
label: `${item.id} / ${item.name}`,
value: item.id as any,
}));
}
function validateForm() { function validateForm() {
if (!form.sysOrigin) { if (!form.sysOrigin) {
message.warning('请选择系统'); message.warning('请选择系统');
@ -297,15 +329,12 @@ async function handleSubmit() {
></SysOriginSelect> ></SysOriginSelect>
</FormItem> </FormItem>
<FormItem label="道具类型"> <FormItem label="道具类型">
<Select option-label-prop="label" v-model:value="form.propsType" disabled> <Select
<SelectOption option-label-prop="label"
v-for="item in PROPS_STORE_TYPES" v-model:value="form.propsType"
:key="item.value" :options="propsStoreTypeOptions"
:value="item.value" disabled
:label="`${item.name}`"> />
{{ item.name }}
</SelectOption>
</Select>
</FormItem> </FormItem>
</div> </div>
@ -313,19 +342,11 @@ async function handleSubmit() {
<Select option-label-prop="label" <Select option-label-prop="label"
v-model:value="form.sourceId" v-model:value="form.sourceId"
:loading="sourceOptionsMap[form.propsType]?.loading" :loading="sourceOptionsMap[form.propsType]?.loading"
:options="getSourceSelectOptions(form.propsType)"
option-filter-prop="label" option-filter-prop="label"
show-search show-search
@change="(value: string) => updateSelectedSource(form.propsType, value)" @change="(value: string) => updateSelectedSource(form.propsType, value)"
> />
<SelectOption
v-for="item in sourceOptionsMap[form.propsType]?.list || []"
:key="item.id"
:label="`${item.id} ${item.name}`"
:value="item.id"
>
{{ item.id }} / {{ item.name }}
</SelectOption>
</Select>
<div v-if="mainSource" class="source-preview"> <div v-if="mainSource" class="source-preview">
<RewardIcon :item="mainSource" :size="56" /> <RewardIcon :item="mainSource" :size="56" />
<div class="source-preview__meta"> <div class="source-preview__meta">
@ -337,27 +358,20 @@ async function handleSubmit() {
<div class="form-grid"> <div class="form-grid">
<FormItem label="付费类型"> <FormItem label="付费类型">
<Select option-label-prop="label" v-model:value="form.tmpCurrencyTypes" mode="multiple"> <Select
<SelectOption option-label-prop="label"
v-for="item in PROPS_CURRENCY_TYPES" v-model:value="form.tmpCurrencyTypes"
:key="item.value" :options="currencyTypeOptions"
:disabled="isNobleVip && item.value !== 'GOLD'" mode="multiple"
:value="item.value" />
:label="`${item.name}`">
{{ item.name }}
</SelectOption>
</Select>
</FormItem> </FormItem>
<FormItem label="有效天数"> <FormItem label="有效天数">
<Select option-label-prop="label" v-model:value="form.tmpValidDays" mode="multiple"> <Select
<SelectOption option-label-prop="label"
v-for="item in PROPS_VALID_DAYS" v-model:value="form.tmpValidDays"
:key="item.value" :options="validDayOptions"
:value="item.value" mode="multiple"
:label="`${item.name}`"> />
{{ item.name }}
</SelectOption>
</Select>
</FormItem> </FormItem>
</div> </div>
@ -388,15 +402,11 @@ async function handleSubmit() {
<div class="form-grid"> <div class="form-grid">
<FormItem label="VIP类型"> <FormItem label="VIP类型">
<Select option-label-prop="label" v-model:value="form.propsAbility.vipType"> <Select
<SelectOption option-label-prop="label"
v-for="item in NOBLE_VIP_OPTIONS" v-model:value="form.propsAbility.vipType"
:key="item.value" :options="nobleVipOptions"
:value="item.value" />
:label="`${item.name}`">
{{ item.name }}
</SelectOption>
</Select>
</FormItem> </FormItem>
<FormItem label="VIP等级"> <FormItem label="VIP等级">
<Input v-model:value="form.propsAbility.vipLevel" /> <Input v-model:value="form.propsAbility.vipLevel" />
@ -422,19 +432,11 @@ async function handleSubmit() {
<Select option-label-prop="label" <Select option-label-prop="label"
v-model:value="form.propsAbility.carId" v-model:value="form.propsAbility.carId"
:loading="sourceOptionsMap.RIDE?.loading" :loading="sourceOptionsMap.RIDE?.loading"
:options="getSourceSelectOptions('RIDE')"
option-filter-prop="label" option-filter-prop="label"
show-search show-search
@change="(value: string) => updateSelectedSource('RIDE', value)" @change="(value: string) => updateSelectedSource('RIDE', value)"
> />
<SelectOption
v-for="item in sourceOptionsMap.RIDE?.list || []"
:key="item.id"
:label="`${item.id} ${item.name}`"
:value="item.id"
>
{{ item.id }} / {{ item.name }}
</SelectOption>
</Select>
<div v-if="rideSource" class="source-preview"> <div v-if="rideSource" class="source-preview">
<RewardIcon :item="rideSource" :size="48" /> <RewardIcon :item="rideSource" :size="48" />
<div class="source-preview__meta"> <div class="source-preview__meta">
@ -448,19 +450,11 @@ async function handleSubmit() {
<Select option-label-prop="label" <Select option-label-prop="label"
v-model:value="form.propsAbility.avatarFrameId" v-model:value="form.propsAbility.avatarFrameId"
:loading="sourceOptionsMap.AVATAR_FRAME?.loading" :loading="sourceOptionsMap.AVATAR_FRAME?.loading"
:options="getSourceSelectOptions('AVATAR_FRAME')"
option-filter-prop="label" option-filter-prop="label"
show-search show-search
@change="(value: string) => updateSelectedSource('AVATAR_FRAME', value)" @change="(value: string) => updateSelectedSource('AVATAR_FRAME', value)"
> />
<SelectOption
v-for="item in sourceOptionsMap.AVATAR_FRAME?.list || []"
:key="item.id"
:label="`${item.id} ${item.name}`"
:value="item.id"
>
{{ item.id }} / {{ item.name }}
</SelectOption>
</Select>
<div v-if="avatarSource" class="source-preview"> <div v-if="avatarSource" class="source-preview">
<RewardIcon :item="avatarSource" :size="48" /> <RewardIcon :item="avatarSource" :size="48" />
<div class="source-preview__meta"> <div class="source-preview__meta">
@ -474,19 +468,11 @@ async function handleSubmit() {
<Select option-label-prop="label" <Select option-label-prop="label"
v-model:value="form.propsAbility.dataCardId" v-model:value="form.propsAbility.dataCardId"
:loading="sourceOptionsMap.DATA_CARD?.loading" :loading="sourceOptionsMap.DATA_CARD?.loading"
:options="getSourceSelectOptions('DATA_CARD')"
option-filter-prop="label" option-filter-prop="label"
show-search show-search
@change="(value: string) => updateSelectedSource('DATA_CARD', value)" @change="(value: string) => updateSelectedSource('DATA_CARD', value)"
> />
<SelectOption
v-for="item in sourceOptionsMap.DATA_CARD?.list || []"
:key="item.id"
:label="`${item.id} ${item.name}`"
:value="item.id"
>
{{ item.id }} / {{ item.name }}
</SelectOption>
</Select>
<div v-if="dataCardSource" class="source-preview"> <div v-if="dataCardSource" class="source-preview">
<RewardIcon :item="dataCardSource" :size="48" /> <RewardIcon :item="dataCardSource" :size="48" />
<div class="source-preview__meta"> <div class="source-preview__meta">
@ -500,19 +486,11 @@ async function handleSubmit() {
<Select option-label-prop="label" <Select option-label-prop="label"
v-model:value="form.propsAbility.chatBubbleId" v-model:value="form.propsAbility.chatBubbleId"
:loading="sourceOptionsMap.CHAT_BUBBLE?.loading" :loading="sourceOptionsMap.CHAT_BUBBLE?.loading"
:options="getSourceSelectOptions('CHAT_BUBBLE')"
option-filter-prop="label" option-filter-prop="label"
show-search show-search
@change="(value: string) => updateSelectedSource('CHAT_BUBBLE', value)" @change="(value: string) => updateSelectedSource('CHAT_BUBBLE', value)"
> />
<SelectOption
v-for="item in sourceOptionsMap.CHAT_BUBBLE?.list || []"
:key="item.id"
:label="`${item.id} ${item.name}`"
:value="item.id"
>
{{ item.id }} / {{ item.name }}
</SelectOption>
</Select>
<div v-if="chatBubbleSource" class="source-preview"> <div v-if="chatBubbleSource" class="source-preview">
<RewardIcon :item="chatBubbleSource" :size="48" /> <RewardIcon :item="chatBubbleSource" :size="48" />
<div class="source-preview__meta"> <div class="source-preview__meta">

View File

@ -22,7 +22,6 @@ import {
Input, Input,
Row, Row,
Select, Select,
SelectOption,
message, message,
} from 'antdv-next'; } from 'antdv-next';
@ -46,6 +45,23 @@ const sysOriginOptions = computed(() => {
const propsTypeOptions = PROPS_TYPES.filter( const propsTypeOptions = PROPS_TYPES.filter(
(item) => item.value !== 'CUSTOMIZE' && item.value !== 'FRAGMENTS', (item) => item.value !== 'CUSTOMIZE' && item.value !== 'FRAGMENTS',
); );
const propsSecondaryTypeOptions = propsTypeOptions.map((item) => ({
label: item.name,
value: item.value as any,
}));
const badgeTypeOptions = BADGE_TYPE_OPTIONS.map((item) => ({
label: item.name,
value: item.value as any,
}));
const ticketTypeOptions = PROPS_TICKET_TYPES.map((item) => ({
label: item.name,
value: item.value as any,
}));
const vipOriginOptions = [
{ label: '系统赠送', value: 'SYSTEM_GIVE' as any },
{ label: '购买或朋友赠送', value: 'BUY_OR_GIVE' as any },
{ label: '活动奖励', value: 'ACTIVITY_AWARD' as any },
];
const propsFormLoading = ref(false); const propsFormLoading = ref(false);
const badgeFormLoading = ref(false); const badgeFormLoading = ref(false);
@ -62,6 +78,24 @@ const ticketSourceOptions = ref<Array<Record<string, any>>>([]);
const propsSelectedResource = ref<Record<string, any> | null>(null); const propsSelectedResource = ref<Record<string, any> | null>(null);
const badgeSelectedResource = ref<Record<string, any> | null>(null); const badgeSelectedResource = ref<Record<string, any> | null>(null);
const ticketSelectedResource = ref<Record<string, any> | null>(null); const ticketSelectedResource = ref<Record<string, any> | null>(null);
const propsResourceOptions = computed(() =>
propsSourceOptions.value.map((item) => ({
label: `${item.id} / ${item.name}`,
value: item.id as any,
})),
);
const badgeResourceOptions = computed(() =>
badgeSourceOptions.value.map((item) => ({
label: `${item.badgeConfigId} / ${item.name}`,
value: item.badgeConfigId as any,
})),
);
const ticketResourceOptions = computed(() =>
ticketSourceOptions.value.map((item) => ({
label: `${item.id} / ${item.name}`,
value: item.id as any,
})),
);
const propsForm = reactive({ const propsForm = reactive({
content: '', content: '',
@ -363,28 +397,19 @@ async function handleSendTicket() {
v-model:value="propsForm.secondaryType" v-model:value="propsForm.secondaryType"
placeholder="请选择类型" placeholder="请选择类型"
@change="loadPropsSources" @change="loadPropsSources"
:options="propsSecondaryTypeOptions"
:options="propsTypeOptions.map((item) => ({ label: `${item.name}`, value: item.value as any }))"
/> />
</FormItem> </FormItem>
<FormItem label="选择资源"> <FormItem label="选择资源">
<Select option-label-prop="label" <Select option-label-prop="label"
v-model:value="propsForm.content" v-model:value="propsForm.content"
:loading="propsSourceLoading" :loading="propsSourceLoading"
:options="propsResourceOptions"
option-filter-prop="label" option-filter-prop="label"
placeholder="请选择资源" placeholder="请选择资源"
show-search show-search
@change="handlePropsResourceChange" @change="handlePropsResourceChange"
> />
<SelectOption
v-for="item in propsSourceOptions"
:key="item.id"
:label="`${item.id} ${item.name}`"
:value="item.id"
>
{{ item.id }} / {{ item.name }}
</SelectOption>
</Select>
<div v-if="propsSelectedResource" class="resource-preview"> <div v-if="propsSelectedResource" class="resource-preview">
<RewardIcon :item="propsSelectedResource" :size="64" /> <RewardIcon :item="propsSelectedResource" :size="64" />
<div class="resource-preview__meta"> <div class="resource-preview__meta">
@ -399,11 +424,11 @@ async function handleSendTicket() {
v-if="propsForm.secondaryType === 'NOBLE_VIP'" v-if="propsForm.secondaryType === 'NOBLE_VIP'"
label="贵族来源" label="贵族来源"
> >
<Select option-label-prop="label" v-model:value="propsForm.vipOrigin"> <Select
<SelectOption value="SYSTEM_GIVE" label="系统赠送">系统赠送</SelectOption> option-label-prop="label"
<SelectOption value="BUY_OR_GIVE" label="购买或朋友赠送">购买或朋友赠送</SelectOption> v-model:value="propsForm.vipOrigin"
<SelectOption value="ACTIVITY_AWARD" label="活动奖励">活动奖励</SelectOption> :options="vipOriginOptions"
</Select> />
</FormItem> </FormItem>
<FormItem label="有效天数"> <FormItem label="有效天数">
<Input <Input
@ -441,8 +466,7 @@ async function handleSendTicket() {
v-model:value="badgeForm.secondaryType" v-model:value="badgeForm.secondaryType"
placeholder="请选择类型" placeholder="请选择类型"
@change="loadBadgeSources" @change="loadBadgeSources"
:options="badgeTypeOptions"
:options="BADGE_TYPE_OPTIONS.map((item) => ({ label: `${item.name}`, value: item.value as any }))"
/> />
</FormItem> </FormItem>
<FormItem label="选择资源"> <FormItem label="选择资源">
@ -450,20 +474,12 @@ async function handleSendTicket() {
option-label-prop="label" option-label-prop="label"
v-model:value="badgeForm.content" v-model:value="badgeForm.content"
:loading="badgeSourceLoading" :loading="badgeSourceLoading"
:options="badgeResourceOptions"
option-filter-prop="label" option-filter-prop="label"
placeholder="请选择资源" placeholder="请选择资源"
show-search show-search
@change="handleBadgeResourceChange" @change="handleBadgeResourceChange"
> />
<SelectOption
v-for="item in badgeSourceOptions"
:key="item.badgeConfigId"
:label="`${item.badgeConfigId} ${item.name}`"
:value="item.badgeConfigId"
>
{{ item.badgeConfigId }} / {{ item.name }}
</SelectOption>
</Select>
<div v-if="badgeSelectedResource" class="resource-preview"> <div v-if="badgeSelectedResource" class="resource-preview">
<RewardIcon :item="badgeSelectedResource" :size="64" /> <RewardIcon :item="badgeSelectedResource" :size="64" />
<div class="resource-preview__meta"> <div class="resource-preview__meta">
@ -509,28 +525,19 @@ async function handleSendTicket() {
v-model:value="ticketForm.secondaryType" v-model:value="ticketForm.secondaryType"
placeholder="请选择类型" placeholder="请选择类型"
@change="loadTicketSources" @change="loadTicketSources"
:options="ticketTypeOptions"
:options="PROPS_TICKET_TYPES.map((item) => ({ label: `${item.name}`, value: item.value as any }))"
/> />
</FormItem> </FormItem>
<FormItem label="选择资源"> <FormItem label="选择资源">
<Select option-label-prop="label" <Select option-label-prop="label"
v-model:value="ticketForm.propId" v-model:value="ticketForm.propId"
:loading="ticketSourceLoading" :loading="ticketSourceLoading"
:options="ticketResourceOptions"
option-filter-prop="label" option-filter-prop="label"
placeholder="请选择资源" placeholder="请选择资源"
show-search show-search
@change="handleTicketResourceChange" @change="handleTicketResourceChange"
> />
<SelectOption
v-for="item in ticketSourceOptions"
:key="item.id"
:label="`${item.id} ${item.name}`"
:value="item.id"
>
{{ item.id }} / {{ item.name }}
</SelectOption>
</Select>
<div v-if="ticketSelectedResource" class="resource-preview"> <div v-if="ticketSelectedResource" class="resource-preview">
<RewardIcon :item="ticketSelectedResource" :size="64" /> <RewardIcon :item="ticketSelectedResource" :size="64" />
<div class="resource-preview__meta"> <div class="resource-preview__meta">
@ -545,11 +552,11 @@ async function handleSendTicket() {
v-if="ticketForm.secondaryType === 'NOBLE_VIP'" v-if="ticketForm.secondaryType === 'NOBLE_VIP'"
label="贵族来源" label="贵族来源"
> >
<Select option-label-prop="label" v-model:value="ticketForm.vipOrigin"> <Select
<SelectOption value="SYSTEM_GIVE" label="系统赠送">系统赠送</SelectOption> option-label-prop="label"
<SelectOption value="BUY_OR_GIVE" label="购买或朋友赠送">购买或朋友赠送</SelectOption> v-model:value="ticketForm.vipOrigin"
<SelectOption value="ACTIVITY_AWARD" label="活动奖励">活动奖励</SelectOption> :options="vipOriginOptions"
</Select> />
</FormItem> </FormItem>
<FormItem label="有效天数"> <FormItem label="有效天数">
<Input <Input