diff --git a/apps/src/views/operate/components/props-source-select-drawer.vue b/apps/src/views/operate/components/props-source-select-drawer.vue index 8c5f63d..4f8da3c 100644 --- a/apps/src/views/operate/components/props-source-select-drawer.vue +++ b/apps/src/views/operate/components/props-source-select-drawer.vue @@ -245,18 +245,9 @@ async function loadSource(type: string) { loading.value = true; try { switch (type) { - case 'BADGE': - case 'ROOM_BADGE': { - const badgeType = type === 'BADGE' ? 'ACTIVITY' : 'ROOM_ACHIEVEMENT'; - const result = await listBadgePictureBySysOrigin(props.sysOrigin, badgeType); - store.list = (result || []).map((item) => - normalizeSourceItem(item, type, { - coverKeys: ['selectUrl', 'cover', 'coverUrl'], - idKeys: ['badgeConfigId', 'id', 'badgeId'], - nameKeys: ['badgeName', 'name'], - sourceUrlKeys: ['animationUrl', 'sourceUrl', 'resourceUrl'], - }), - ); + case 'BADGE': { + const result = await listSysOriginTypeList(props.sysOrigin, 'BADGE'); + store.list = (result || []).map((item) => normalizeSourceItem(item, type)); break; } case 'EMOJI': { @@ -287,6 +278,21 @@ async function loadSource(type: string) { store.list = (result || []).map((item) => normalizeSourceItem(item, type)); break; } + case 'ROOM_BADGE': { + const result = await listBadgePictureBySysOrigin( + props.sysOrigin, + 'ROOM_ACHIEVEMENT', + ); + store.list = (result || []).map((item) => + normalizeSourceItem(item, type, { + coverKeys: ['selectUrl', 'cover', 'coverUrl'], + idKeys: ['badgeConfigId', 'id', 'badgeId'], + nameKeys: ['badgeName', 'name'], + sourceUrlKeys: ['animationUrl', 'sourceUrl', 'resourceUrl'], + }), + ); + break; + } default: { const result = await listSysOriginTypeList(props.sysOrigin, type); store.list = (result || []).map((item) => normalizeSourceItem(item, type)); diff --git a/apps/src/views/props/components/resource-config-modal.vue b/apps/src/views/props/components/resource-config-modal.vue index 2bcae4d..349bdbd 100644 --- a/apps/src/views/props/components/resource-config-modal.vue +++ b/apps/src/views/props/components/resource-config-modal.vue @@ -24,6 +24,7 @@ import { } from '#/api/legacy/props'; import { + BADGE_TYPE_OPTIONS, NOBLE_VIP_OPTIONS, PROPS_RESOURCE_CONFIG_TYPES, } from '../shared'; @@ -43,19 +44,26 @@ const saving = ref(false); const coverUploading = ref(false); const sourceUploading = ref(false); const expandUploading = ref(false); +const notSelectUploading = ref(false); const coverInputRef = ref(); const sourceInputRef = ref(); const expandInputRef = ref(); +const notSelectInputRef = ref(); const form = reactive>({ adminFree: false, amount: '', + badgeKey: '', + badgeLevel: '', + badgeType: 'ACTIVITY', code: '', cover: '', expand: '', id: '', + milestone: '', name: '', + notSelectUrl: '', sourceUrl: '', sysOrigin: '', type: '', @@ -76,6 +84,9 @@ const isSourceRequired = computed( ); const showExpandUpload = computed(() => form.type === 'CHAT_BUBBLE'); const sourceUploadLabel = computed(() => { + if (form.type === 'BADGE') { + return '动效资源(选填)'; + } if (showExpandUpload.value) { return 'iOS资源'; } @@ -90,15 +101,65 @@ const nobleVipNameOptions = NOBLE_VIP_OPTIONS.map((item) => ({ label: item.name, value: item.value as any, })); +const badgeTypeOptions = BADGE_TYPE_OPTIONS.filter((item) => + ['ACHIEVEMENT', 'ACTIVITY'].includes(String(item.value)), +).map((item) => ({ + label: item.name, + value: item.value as any, +})); + +function parseBadgeExpand(value: unknown) { + if (!value || typeof value !== 'string') { + return {}; + } + try { + return JSON.parse(value) as Record; + } catch { + return {}; + } +} + +function applyBadgeExpand(value: unknown) { + const expand = parseBadgeExpand(value); + form.badgeKey = expand.badgeKey ?? ''; + form.badgeLevel = expand.badgeLevel ?? ''; + form.badgeType = expand.badgeType || 'ACTIVITY'; + form.milestone = expand.milestone ?? ''; + form.notSelectUrl = expand.notSelectUrl ?? ''; +} + +function buildBadgeExpand() { + const expand: Record = { + badgeType: form.badgeType || 'ACTIVITY', + }; + if (String(form.badgeKey || '').trim()) { + expand.badgeKey = String(form.badgeKey).trim(); + } + if (String(form.badgeLevel || '').trim()) { + expand.badgeLevel = Number(form.badgeLevel); + } + if (String(form.milestone || '').trim()) { + expand.milestone = Number(form.milestone); + } + if (String(form.notSelectUrl || '').trim()) { + expand.notSelectUrl = String(form.notSelectUrl).trim(); + } + return JSON.stringify(expand); +} function resetForm() { form.adminFree = false; form.amount = ''; + form.badgeKey = ''; + form.badgeLevel = ''; + form.badgeType = 'ACTIVITY'; form.code = ''; form.cover = ''; form.expand = ''; form.id = ''; + form.milestone = ''; form.name = ''; + form.notSelectUrl = ''; form.sourceUrl = ''; form.sysOrigin = props.sysOriginOptions[0]?.value ?? 'LIKEI'; form.type = PROPS_RESOURCE_CONFIG_TYPES[0]?.value ?? ''; @@ -125,6 +186,11 @@ watch( form.sourceUrl = record.sourceUrl ?? ''; form.sysOrigin = record.sysOrigin || props.sysOriginOptions[0]?.value || 'LIKEI'; form.type = record.type ?? ''; + if (form.type === 'BADGE') { + applyBadgeExpand(record.expand); + } else { + applyBadgeExpand(''); + } }, { immediate: true }, ); @@ -143,7 +209,10 @@ watch( form.sourceUrl = ''; form.expand = ''; } - if (value !== 'CHAT_BUBBLE') { + if (value === 'BADGE' && !form.badgeType) { + form.badgeType = 'ACTIVITY'; + } + if (!['BADGE', 'CHAT_BUBBLE'].includes(value)) { form.expand = ''; } }, @@ -161,6 +230,10 @@ function openExpandPicker() { expandInputRef.value?.click(); } +function openNotSelectPicker() { + notSelectInputRef.value?.click(); +} + function handleCoverInput(event: Event) { void uploadFile(event, 'cover', coverUploading, true); } @@ -173,9 +246,13 @@ function handleExpandInput(event: Event) { void uploadFile(event, 'expand', expandUploading, true); } +function handleNotSelectInput(event: Event) { + void uploadFile(event, 'notSelectUrl', notSelectUploading, true); +} + async function uploadFile( event: Event, - targetKey: 'cover' | 'expand' | 'sourceUrl', + targetKey: 'cover' | 'expand' | 'notSelectUrl' | 'sourceUrl', loadingRef: typeof coverUploading, imageBucket = false, ) { @@ -207,6 +284,26 @@ function validateForm() { message.warning('请选择类型'); return false; } + if (form.type === 'BADGE' && !form.badgeType) { + message.warning('请选择徽章类型'); + return false; + } + if ( + form.type === 'BADGE' && + String(form.badgeLevel || '').trim() && + Number.isNaN(Number(form.badgeLevel)) + ) { + message.warning('请输入正确的徽章等级'); + return false; + } + if ( + form.type === 'BADGE' && + String(form.milestone || '').trim() && + Number.isNaN(Number(form.milestone)) + ) { + message.warning('请输入正确的成就里程碑'); + return false; + } if (!String(form.cover || '').trim()) { message.warning('请上传封面'); return false; @@ -241,8 +338,16 @@ async function handleSubmit() { saving.value = true; try { const payload = { - ...form, + adminFree: form.adminFree, amount: isAmountRequired.value ? Number(form.amount) : 0, + code: form.code, + cover: form.cover, + expand: form.type === 'BADGE' ? buildBadgeExpand() : form.expand, + id: form.id, + name: form.name, + sourceUrl: form.sourceUrl, + sysOrigin: form.sysOrigin, + type: form.type, }; await (isUpdate.value ? updatePropsSource(payload) : addPropsSource(payload)); message.success('保存成功'); @@ -278,6 +383,24 @@ async function handleSubmit() { :options="propsTypeOptions" /> + + + +
+
+ +
+
未选中图可不上传
+ +
+
import { computed, reactive, ref, watch } from 'vue'; +import { + Button, + Drawer, + Form, + FormItem, + Input, + message, + Select, + Space, + Switch, +} from 'antdv-next'; + import { listEmojiGroupsBySysOrigin } from '#/api/legacy/app-system'; import { listBadgePictureBySysOrigin } from '#/api/legacy/badge'; import { listGiftBySysOrigin } from '#/api/legacy/gift'; @@ -9,24 +21,9 @@ import { listSysOriginTypeList, saveOrUpdatePropsActivityRewardGroup, } from '#/api/legacy/props'; - -import { - Button, - Drawer, - Form, - FormItem, - Input, - Select, - Space, - Switch, - message, -} from 'antdv-next'; import { getDisplaySysOriginText } from '#/views/system/shared'; -import RewardIcon from './reward-icon.vue'; import { - PROPS_SOURCE_GROUP_ADD_TYPES, - PROPS_SOURCE_GROUP_TYPE_MAP, formatRewardText, getPropsTypeName, getRewardBadgeType, @@ -34,7 +31,10 @@ import { isCurrencyRewardType, isGameCouponType, isPropsCouponType, + PROPS_SOURCE_GROUP_ADD_TYPES, + PROPS_SOURCE_GROUP_TYPE_MAP, } from '../shared'; +import RewardIcon from './reward-icon.vue'; const props = defineProps<{ open: boolean; @@ -104,7 +104,8 @@ const selectedDraftResource = ref(null); const title = computed(() => { const sysOrigin = getDisplaySysOriginText(props.sysOrigin || form.sysOrigin); - return sysOrigin ? `${form.id ? '修改' : '添加'}(${sysOrigin})` : form.id ? '修改' : '添加'; + const action = form.id ? '修改' : '添加'; + return sysOrigin ? `${action}(${sysOrigin})` : action; }); const rewardItems = computed(() => form.rewardConfigList); @@ -194,7 +195,7 @@ watch( function needsRemoteOptions(type: string) { return !( - ['SPECIAL_ID', 'GOLD', 'DIAMOND', 'GAME_COUPON', 'PROP_COUPON'].includes(type) + ['DIAMOND', 'GAME_COUPON', 'GOLD', 'PROP_COUPON', 'SPECIAL_ID'].includes(type) ); } @@ -209,49 +210,70 @@ async function loadOptions(type: string) { store.loading = true; draftLoading.value = true; try { - if (type === 'GIFT') { - const list = await listGiftBySysOrigin(form.sysOrigin); - store.list = list.map((item) => ({ - cover: item.giftPhoto || '', - id: item.id ?? '', - name: item.giftName || '', - sourceUrl: item.giftSourceUrl || '', - })); - } else if (type === 'EMOJI') { - const list = await listEmojiGroupsBySysOrigin(form.sysOrigin); - store.list = list.map((item) => ({ - cover: item.cover || '', - id: item.id ?? '', - name: item.groupName || '', - sourceUrl: '', - })); - } else if (isBadgeRewardType(type)) { - const badgeType = getRewardBadgeType(type); - const list = await listBadgePictureBySysOrigin(form.sysOrigin, badgeType); - store.list = list.map((item) => ({ - badgeName: item.badgeName || '', - cover: item.selectUrl || '', - id: item.badgeConfigId ?? '', - name: item.badgeName || '', - sourceUrl: item.animationUrl || '', - })); - } else if (type === 'NOBLE_VIP') { - const list = await listNotFamilyBySysOriginType(form.sysOrigin, type); - store.list = list.map((item) => ({ - cover: item.cover || '', - id: item.id ?? '', - name: item.name || '', - sourceUrl: item.sourceUrl || '', - })); - } else { - const list = await listSysOriginTypeList(form.sysOrigin, type); - store.list = list.map((item) => ({ - cover: item.cover || '', - id: item.id ?? '', - name: item.name || '', - remark: item.remark || '', - sourceUrl: item.sourceUrl || '', - })); + switch (type) { + case 'BADGE': { + const list = await listSysOriginTypeList(form.sysOrigin, 'BADGE'); + store.list = list.map((item) => ({ + badgeName: item.name || '', + cover: item.cover || '', + id: item.id ?? '', + name: item.name || '', + sourceUrl: item.sourceUrl || '', + })); + break; + } + case 'EMOJI': { + const list = await listEmojiGroupsBySysOrigin(form.sysOrigin); + store.list = list.map((item) => ({ + cover: item.cover || '', + id: item.id ?? '', + name: item.groupName || '', + sourceUrl: '', + })); + break; + } + case 'GIFT': { + const list = await listGiftBySysOrigin(form.sysOrigin); + store.list = list.map((item) => ({ + cover: item.giftPhoto || '', + id: item.id ?? '', + name: item.giftName || '', + sourceUrl: item.giftSourceUrl || '', + })); + break; + } + case 'NOBLE_VIP': { + const list = await listNotFamilyBySysOriginType(form.sysOrigin, type); + store.list = list.map((item) => ({ + cover: item.cover || '', + id: item.id ?? '', + name: item.name || '', + sourceUrl: item.sourceUrl || '', + })); + break; + } + default: { + if (isBadgeRewardType(type)) { + const badgeType = getRewardBadgeType(type); + const list = await listBadgePictureBySysOrigin(form.sysOrigin, badgeType); + store.list = list.map((item) => ({ + badgeName: item.badgeName || '', + cover: item.selectUrl || '', + id: item.badgeConfigId ?? '', + name: item.badgeName || '', + sourceUrl: item.animationUrl || '', + })); + break; + } + const list = await listSysOriginTypeList(form.sysOrigin, type); + store.list = list.map((item) => ({ + cover: item.cover || '', + id: item.id ?? '', + name: item.name || '', + remark: item.remark || '', + sourceUrl: item.sourceUrl || '', + })); + } } store.loaded = true; } finally { @@ -266,7 +288,7 @@ async function handleDraftTypeChange(value: string) { await loadOptions(value); } -function handleDraftContentChange(value: string | number) { +function handleDraftContentChange(value: number | string) { if (!draft.type || !needsRemoteOptions(draft.type)) { return; } diff --git a/apps/src/views/resident-activity/components/resource-select-drawer.vue b/apps/src/views/resident-activity/components/resource-select-drawer.vue index e8ea7c1..b55ce9f 100644 --- a/apps/src/views/resident-activity/components/resource-select-drawer.vue +++ b/apps/src/views/resident-activity/components/resource-select-drawer.vue @@ -1,13 +1,6 @@