修复下拉菜单

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,5 +1,5 @@
<script lang="ts" setup>
import { reactive, ref, watch } from 'vue';
import { computed, reactive, ref, watch } from 'vue';
import { getByGroupId } from '#/api/legacy/props';
import {
@ -22,7 +22,6 @@ import {
Modal,
Pagination,
Select,
SelectOption,
Space,
Table,
Tag,
@ -101,6 +100,13 @@ const columns = [
{ 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) {
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 />
</FormItem>
<FormItem label="挑战的任务">
<Select option-label-prop="label" v-model:value="form.taskType" allow-clear placeholder="任务类型">
<SelectOption
v-for="item in TASK_TYPE_OPTIONS"
:key="item.value"
:value="item.value"
:label="`${item.label}`">
{{ item.label }}
</SelectOption>
</Select>
<Select
v-model:value="form.taskType"
allow-clear
:options="TASK_TYPE_OPTIONS"
option-label-prop="label"
placeholder="任务类型"
/>
</FormItem>
<FormItem label="排序">
<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)"
label="奖项"
>
<Select option-label-prop="label"
<Select
v-model:value="form.gameAwardId"
:options="gameAwardSelectOptions"
mode="multiple"
option-label-prop="label"
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-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 { 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';
@ -26,6 +26,10 @@ const sysOriginOptions = computed(() => {
const options = getAllowedSysOrigins(accessStore.accessCodes || []);
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 loadMoreLoading = ref(false);
@ -179,17 +183,10 @@ function handleRecipientRoomFail() {
></SysOriginSelect>
<Select option-label-prop="label"
v-model:value="query.pkType"
:options="pkTypeOptions"
style="width: 140px"
@change="handleSearch"
>
<SelectOption
v-for="item in PK_TYPE_OPTIONS"
:key="item.value"
:value="item.value"
:label="`${item.label}`">
{{ item.label }}
</SelectOption>
</Select>
/>
<AccountInput
v-model:value="query.sponsorUserId"
:sys-origin="query.sysOrigin"

View File

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

View File

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

View File

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

View File

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

View File

@ -15,7 +15,6 @@ import {
Input,
Pagination,
Select,
SelectOption,
Switch,
Table,
} from 'antdv-next';
@ -62,6 +61,39 @@ const title = computed(() => (props.mode === 'country' ? '商品管理' : '商
const dimensionPlaceholder = computed(() =>
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 listColumns: any[] = [
@ -236,56 +268,31 @@ function openEdit(record: Record<string, any>) {
<div class="toolbar">
<Select option-label-prop="label"
v-model:value="query.type"
:options="productTypeOptions"
style="width: 180px"
@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"
v-model:value="query.applicationId"
:options="applicationOptions"
placeholder="应用"
style="width: 200px"
@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"
v-model:value="props.mode === 'country' ? query.payCountryId : query.regionId"
v-model:value="selectedDimensionId"
:loading="supportLoading"
:options="supportOptions"
:placeholder="dimensionPlaceholder"
style="width: 200px"
@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"
v-model:value="query.shelf"
:options="shelfOptions"
style="width: 140px"
@change="handleSearch"
>
<SelectOption :value="true" label="上架">上架</SelectOption>
<SelectOption :value="false" label="下架">下架</SelectOption>
</Select>
/>
<Input
v-model:value="query.id"
placeholder="商品ID"

View File

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

View File

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

View File

@ -9,7 +9,6 @@ import {
Drawer,
Pagination,
Select,
SelectOption,
Space,
Table,
} from 'antdv-next';
@ -111,17 +110,10 @@ function handlePageChange(page: number, pageSize: number) {
<Select option-label-prop="label"
v-model:value="query.roomRole"
allow-clear
:options="ROOM_ROLE_OPTIONS"
placeholder="角色"
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>

View File

@ -10,7 +10,6 @@ import {
Empty,
Modal,
Select,
SelectOption,
Space,
Tag,
} from 'antdv-next';
@ -30,6 +29,10 @@ const loading = ref(false);
const detailsOpen = ref(false);
const list = ref<Array<Record<string, any>>>([]);
const jsonText = ref('');
const apiRequestLogOptions = API_REQUEST_LOGS.map((item) => ({
label: item.label,
value: item.value as any,
}));
const query = reactive({
businessCode: '',
@ -87,17 +90,10 @@ function openDetails(record: Record<string, any>) {
<Select option-label-prop="label"
v-model:value="query.businessCode"
allow-clear
:options="apiRequestLogOptions"
placeholder="业务CODE"
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>

View File

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

View File

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

View File

@ -17,7 +17,6 @@ import {
InputNumber,
Modal,
Select,
SelectOption,
TextArea,
message,
} from 'antdv-next';
@ -41,6 +40,22 @@ const form = reactive({
reasonType: 5,
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 typeName =
@ -56,7 +71,7 @@ watch(
return;
}
form.amount = undefined;
form.reasonType = 5;
form.reasonType = props.action === 'reward' ? 5 : 4;
form.remarks = '';
},
{ immediate: true },
@ -141,28 +156,11 @@ async function handleSubmit() {
/>
</FormItem>
<FormItem label="原因">
<Select option-label-prop="label" v-model:value="form.reasonType">
<SelectOption
v-for="item in props.action === 'reward'
? [
{ 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>
<Select
option-label-prop="label"
v-model:value="form.reasonType"
:options="reasonTypeOptions"
/>
</FormItem>
<FormItem label="备注">
<TextArea v-model:value="form.remarks" :rows="4" />

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -9,7 +9,6 @@ import {
Input,
Pagination,
Select,
SelectOption,
Space,
Table,
} from 'antdv-next';
@ -48,6 +47,11 @@ const columns = [
{ 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) {
if (!props.open || !query.sysOrigin) {
return;
@ -96,20 +100,15 @@ watch(
@close="emit('close')"
>
<Space class="toolbar" wrap>
<Select option-label-prop="label"
<Select
v-model:value="query.shelfStatus"
allow-clear
:options="shelfStatusOptions"
option-label-prop="label"
placeholder="请选择状态"
style="width: 120px"
@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
v-model:value="query.id"
allow-clear

View File

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

View File

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

View File

@ -12,7 +12,6 @@ import {
DescriptionsItem,
Modal,
Select,
SelectOption,
Space,
Table,
} from 'antdv-next';
@ -63,6 +62,14 @@ const datePickerType = computed(
const dateValueFormat = computed(
() => 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() {
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"
:options="sysOriginOptions"
></SysOriginSelect>
<Select option-label-prop="label" v-model:value="query.dateType" style="width: 120px" @change="loadData">
<SelectOption
v-for="item in ACTIVITY_DATE_TYPE_OPTIONS"
:key="item.value"
:value="item.value"
:label="`${item.label}`">
{{ item.label }}
</SelectOption>
</Select>
<Select option-label-prop="label" v-model:value="query.propsType" style="width: 160px" @change="loadData">
<SelectOption
v-for="item in PROPS_TYPES"
:key="item.value"
:value="item.value"
:label="`${item.name}`">
{{ item.name }}
</SelectOption>
</Select>
<Select
option-label-prop="label"
v-model:value="query.dateType"
:options="dateTypeOptions"
style="width: 120px"
@change="loadData"
/>
<Select
option-label-prop="label"
v-model:value="query.propsType"
:options="propsTypeOptions"
style="width: 160px"
@change="loadData"
/>
<DatePicker
v-model:value="query.date"
:format="dateValueFormat"

View File

@ -77,7 +77,11 @@ watch(
if (!open) {
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.propsSourceId = String(props.record?.id || '');
void loadData();

View File

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

View File

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

View File

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