@@ -26,6 +26,7 @@ import type { MapPlaybackFrame, MapPlaybackState, MapSceneData, MapTimeWindow, M
type StateSetter < T > = ( next : T | ( ( previous : T ) = > T ) ) = > void ;
type InputEvent = { target ? : { value? : string ; checked? : boolean ; open? : boolean } ; currentTarget ? : { open? : boolean } ; stopPropagation ? : ( ) = > void } ;
type GiftTab = "definitions" | "claims" | "deliveries" | "timed" ;
type GiftDialogState = { mode : "closed" } | { mode : "view" | "edit" ; gift? : RecordMap } ;
type MapLayer = "players" | "vehicles" | "flags" | "regions" | "other" ;
type MapVehicleFilter = "all" | "land" | "water" | "air" | "other" ;
type ScumMapLayer = "terrain" | "topo" | "night" ;
@@ -145,7 +146,7 @@ export function renderSCUMFeaturePage(react: ReactLike, input: SCUMPageContext)
const mapFollowRef = react . useRef ? react . useRef ( true ) : { current : true } ;
const [ eventEditorOpen , setEventEditorOpen ] = usePluginState ( react , false ) ;
const [ produceEditorOpen , setProduceEditorOpen ] = usePluginState ( react , false ) ;
const [ giftEditorOpen , setGiftEditorOpen ] = usePluginState ( react , false ) ;
const [ giftDialog , setGiftDialog ] = usePluginState < GiftDialogState > ( react , { mode : "closed" } ) ;
const [ mapBaseLayer , setMapBaseLayer ] = usePluginState < ScumMapLayer | undefined > ( react , undefined ) ;
const [ mapZonesOverlay , setMapZonesOverlay ] = usePluginState < boolean | undefined > ( react , undefined ) ;
const [ catalogSearch , setCatalogSearch ] = usePluginState ( react , "" ) ;
@@ -218,11 +219,11 @@ export function renderSCUMFeaturePage(react: ReactLike, input: SCUMPageContext)
setSelectedMapPoint ( "" ) ;
} , [ input . serverInstanceId , pageKey , mapUsers , mapTimeFrom , mapTimeTo ] ) ;
if ( react . useEffect ) react . useEffect ( ( ) = > {
if ( ! giftEditorOpen || typeof document === "undefined" ) return ;
const onKeyDown = ( event : KeyboardEvent ) = > { if ( event . key === "Escape" ) setGiftEditorOpen ( false ) ; } ;
if ( giftDialog . mode === "closed" || typeof document === "undefined" ) return ;
const onKeyDown = ( event : KeyboardEvent ) = > { if ( event . key === "Escape" ) setGiftDialog ( { mode : "closed" } ) ; } ;
document . addEventListener ( "keydown" , onKeyDown ) ;
return ( ) = > document . removeEventListener ( "keydown" , onKeyDown ) ;
} , [ giftEditorOpen ] ) ;
} , [ giftDialog . mode ] ) ;
if ( react . useEffect ) react . useEffect ( ( ) = > {
if ( pageKey !== "live-map" ) return ;
if ( ! focusUser ) {
@@ -263,7 +264,7 @@ export function renderSCUMFeaturePage(react: ReactLike, input: SCUMPageContext)
hoverMapPoint , setHoverMapPoint ,
mapView , setMapView , mapViewportRef , mapPlaybackFrameRef , mapFollowRef , mapTimePreset , setMapTimePreset , mapTimeFrom , setMapTimeFrom , mapTimeTo , setMapTimeTo ,
mapUsers , setMapUsers , mapTrackKey , setMapTrackKey , mapPlayback , setMapPlayback ,
eventEditorOpen , setEventEditorOpen , produceEditorOpen , setProduceEditorOpen , giftEditorOpen , setGiftEditorOpen ,
eventEditorOpen , setEventEditorOpen , produceEditorOpen , setProduceEditorOpen , giftDialog , setGiftDialog ,
mapBaseLayer , setMapBaseLayer , mapZonesOverlay , setMapZonesOverlay , catalogSearch , setCatalogSearch , catalogKind , setCatalogKind , catalogOpen , setCatalogOpen ,
setAction , refresh : ( ) = > setRefreshSignal ( ( value ) = > value + 1 ) ,
mapData , mapSceneContents : null , mapStaticContents : null , mapSelectedTrails : [ ] , mapSelectedLocks : [ ]
@@ -285,7 +286,7 @@ export function renderSCUMFeaturePage(react: ReactLike, input: SCUMPageContext)
const renderMapScene = ( ) = > mapData ? mapSceneContents ( e , data , view , mapData ) : null ;
// Pan/zoom only changes the parent transform. Keep the geometry and marker elements stable.
view . mapSceneContents = react . useMemo ? react . useMemo ( renderMapScene , [ mapData , mapLayers , mapPlayback . value , mapPlayback . startedAt , hoverMapPoint ] ) : renderMapScene ( ) ;
return e ( "section" , { className : " console-panel scum-workbench" , "aria-label" : input . pageTitle ? ? surfaceTitle ( pageKey ) } ,
return e ( "section" , { className : ` console-panel scum-workbench ${ giftDialog . mode === "closed" ? "" : " has-management-dialog" } ` , "aria-label" : input . pageTitle ? ? surfaceTitle ( pageKey ) } ,
action . status !== "idle" ? e ( "p" , { className : "page-status" , "data-state" : action . status } , action . message ) : null ,
state . status === "loading" ? e ( "p" , { className : "page-status" } , "正在读取平台 SCUM 用户与载具表…" ) : null ,
state . status === "error" ? e ( "p" , { className : "page-status" , "data-state" : "error" } , state . reason ) : null ,
@@ -318,7 +319,7 @@ type ViewState = {
mapFollowRef : { current : boolean } ;
mapTimePreset : string ; setMapTimePreset : StateSetter < string > ; mapTimeFrom : string ; setMapTimeFrom : StateSetter < string > ; mapTimeTo : string ; setMapTimeTo : StateSetter < string > ;
mapUsers : string [ ] | undefined ; setMapUsers : StateSetter < string [ ] | undefined > ; mapTrackKey : string ; setMapTrackKey : StateSetter < string > ; mapPlayback : MapPlaybackState ; setMapPlayback : StateSetter < MapPlaybackState > ;
eventEditorOpen : boolean ; setEventEditorOpen : StateSetter < boolean > ; produceEditorOpen : boolean ; setProduceEditorOpen : StateSetter < boolean > ; giftEditorOpen : boolean ; setGiftEditorOpen : StateSetter < boolean > ;
eventEditorOpen : boolean ; setEventEditorOpen : StateSetter < boolean > ; produceEditorOpen : boolean ; setProduceEditorOpen : StateSetter < boolean > ; giftDialog : GiftDialogState ; setGiftDialog : StateSetter < GiftDialogState > ;
mapBaseLayer : ScumMapLayer | undefined ; setMapBaseLayer : StateSetter < ScumMapLayer | undefined > ; mapZonesOverlay : boolean | undefined ; setMapZonesOverlay : StateSetter < boolean | undefined > ;
catalogSearch : string ; setCatalogSearch : StateSetter < string > ; catalogKind : string ; setCatalogKind : StateSetter < string > ; catalogOpen : boolean ; setCatalogOpen : StateSetter < boolean > ;
} ;
@@ -601,10 +602,10 @@ function activitiesSurface(e: ReactLike["createElement"], data: SCUMSurfaceData,
function giftsSurface ( e : ReactLike [ "createElement" ] , data : SCUMSurfaceData , input : SCUMPageContext , view : ViewState ) {
const actions = input . workspaceActions ;
const openNewGift = ( ) = > {
view . setGiftRecordKey ( "" ) ; view . setGiftCode ( "" ) ; view . setGiftName ( "" ) ; view . setGiftItems ( "" ) ; view . setGiftCommands ( "" ) ; view . setGiftClass ( "5" ) ; view . setGiftAudience ( "all" ) ; view . setGiftNumber ( "1" ) ; view . setGiftAchievement ( "0" ) ; view . setGiftAchievementNumber ( "0" ) ; view . setGiftEditorOpen ( true ) ;
view . setGiftRecordKey ( "" ) ; view . setGiftCode ( "" ) ; view . setGiftName ( "" ) ; view . setGiftItems ( "" ) ; view . setGiftCommands ( "" ) ; view . setGiftClass ( "5" ) ; view . setGiftAudience ( "all" ) ; view . setGiftNumber ( "1" ) ; view . setGiftAchievement ( "0" ) ; view . setGiftAchievementNumber ( "0" ) ; view . setGiftDialog ( { mode : "edit" } ) ;
} ;
const openGiftEditor = ( gift : RecordMap ) = > {
view . setGiftRecordKey ( textField ( gift , "_recordKey" , "code" , "id" ) ) ; view . setGiftCode ( textField ( gift , "code" ) ) ; view . setGiftName ( textField ( gift , "name" ) ) ; view . setGiftClass ( numField ( gift , "class" ) ) ; view . setGiftAudience ( textField ( gift , "audience" ) || "all" ) ; view . setGiftNumber ( numField ( gift , "number" ) ) ; view . setGiftAchievement ( numField ( gift , "achievement" ) ) ; view . setGiftAchievementNumber ( numField ( gift , "achievementNumber" , "achievement_number" ) ) ; view . setGiftItems ( giftItemsInput ( gift ) ) ; view . setGiftCommands ( giftCommandsInput ( gift ) ) ; view . setGiftEditorOpen ( true ) ;
const openGiftDialog = ( gift : RecordMap , mode : "view" | "edit" ) = > {
view . setGiftRecordKey ( textField ( gift , "_recordKey" , "code" , "id" ) ) ; view . setGiftCode ( textField ( gift , "code" ) ) ; view . setGiftName ( textField ( gift , "name" ) ) ; view . setGiftClass ( numField ( gift , "class" ) ) ; view . setGiftAudience ( textField ( gift , "audience" ) || "all" ) ; view . setGiftNumber ( numField ( gift , "number" ) ) ; view . setGiftAchievement ( numField ( gift , "achievement" ) ) ; view . setGiftAchievementNumber ( numField ( gift , "achievementNumber" , "achievement_number" ) ) ; view . setGiftItems ( giftItemsInput ( gift ) ) ; view . setGiftCommands ( giftCommandsInput ( gift ) ) ; view . setGiftDialog ( { mode , gift } ) ;
} ;
const saveGift = ( ) = > runAction ( view . setAction , "正在保存礼包定义…" , async ( ) = > {
const code = view . giftCode . trim ( ) ;
@@ -623,10 +624,11 @@ function giftsSurface(e: ReactLike["createElement"], data: SCUMSurfaceData, inpu
status : "active" , updatedAt : new Date ( ) . toISOString ( )
} ) ;
if ( view . giftRecordKey && view . giftRecordKey !== code ) await deleteGiftDefinition ( actions ? ? { } , view . giftRecordKey ) ;
view . setGiftEditorOpen ( false ) ; view . setGiftRecordKey ( "" ) ;
view . setGiftDialog ( { mode : "closed" } ) ; view . setGiftRecordKey ( "" ) ;
view . refresh ( ) ;
return ` 礼包 ${ name } 已保存。 ` ;
} ) ;
const selectedGift = view . giftDialog . mode === "closed" ? undefined : view . giftDialog . gift ;
const queueDelivery = ( ) = > runAction ( view . setAction , "正在创建发放记录…" , async ( ) = > {
const giftCode = view . deliveryGift || textField ( data . gifts [ 0 ] , "code" , "id" ) ;
const playerId = view . deliveryPlayer || textField ( data . players [ 0 ] , "gamePlayerId" , "steamId" , "id" ) ;
@@ -644,7 +646,7 @@ function giftsSurface(e: ReactLike["createElement"], data: SCUMSurfaceData, inpu
return matchesText ( gift , search , "code" , "name" , "audience" , "status" ) && ( view . giftStatus === "all" || statusFilter === view . giftStatus ) ;
} ) ;
return e ( "div" , { className : "console-record-list" } ,
statsStrip ( e , [ [ "礼包定义" , data . gifts . length ] , [ "领取/待领" , data . giftClaims . length + data . pendingGifts . length ] , [ "发放记录" , data . giftDeliveries . length ] , [ "物品列表" , data . tradeGoods . length ] ] ) ,
statsStrip ( e , [ [ "礼包定义" , data . gifts . length ] , [ "领取/待领" , data . giftClaims . length + data . pendingGifts . length ] , [ "发放记录" , data . giftDeliveries . length ] ] ) ,
e ( "div" , { className : "console-row-actions" , role : "tablist" , "aria-label" : "礼包视图" } ,
giftTabButton ( e , view , "definitions" , "礼包定义" ) , giftTabButton ( e , view , "claims" , "领取/待领" ) , giftTabButton ( e , view , "deliveries" , "发放记录" ) , giftTabButton ( e , view , "timed" , "游戏定时记录" )
) ,
@@ -669,10 +671,11 @@ function giftsSurface(e: ReactLike["createElement"], data: SCUMSurfaceData, inpu
e ( "td" , null , e ( "span" , { className : ` status-pill ${ activeStatus ( status ) ? "status-active" : "status-disabled" } ` } , giftStatusLabel ( status ) ) ) ,
e ( "td" , null , e ( "span" , { className : "provider-id" } , dateField ( gift , "updatedAt" , "createdAt" ) ) ) ,
e ( "td" , { className : "provider-actions-cell" } , e ( "div" , { className : "scum-gift-table-actions" } ,
e ( "button" , { type : "button" , className : "icon-command" , onClick : ( ) = > openGiftEditor ( gift ) } , "编辑 " ) ,
e ( "button" , { type : "button" , className : "icon-command" , onClick : ( ) = > openGiftDialog ( gift , "view" ) } , "查看配置 " ) ,
e ( "details" , { className : "inline-action-control" } ,
e ( "summary" , { className : "icon-command" , "aria-label" : ` 打开 ${ textField ( gift , "name" ) || key } 更多操作 ` } , "更多" ) ,
e ( "div" , { className : "inline-action-menu" , role : "menu" , "aria-label" : "礼包操作" } ,
e ( "button" , { type : "button" , className : "runtime-action-item" , role : "menuitem" , onClick : ( ) = > openGiftDialog ( gift , "edit" ) } , "编辑礼包" ) ,
e ( "button" , { type : "button" , className : "runtime-action-item" , role : "menuitem" , onClick : ( ) = > { view . setDeliveryGift ( key ) ; view . setGiftTab ( "deliveries" ) ; } } , "选择发放" ) ,
e ( "button" , { type : "button" , className : "runtime-action-item danger-command" , role : "menuitem" , disabled : ! actions ? . pluginData , onClick : ( ) = > runAction ( view . setAction , "正在删除礼包…" , async ( ) = > { await deleteGiftDefinition ( actions ? ? { } , key ) ; view . refresh ( ) ; return "礼包定义已删除。" ; } ) } , "删除" )
)
@@ -683,7 +686,6 @@ function giftsSurface(e: ReactLike["createElement"], data: SCUMSurfaceData, inpu
)
) ,
) : null ,
view . giftTab === "definitions" ? itemCatalogPanel ( e , data . tradeGoods ) : null ,
view . giftTab === "claims" ? e ( "div" , { className : "overview-two-col" } ,
resettableGiftPanel ( e , "领取记录" , data . giftClaims , "重置领取" , ( claim ) = > runAction ( view . setAction , "正在重置领取记录…" , async ( ) = > { await resetGiftClaim ( actions ? ? { } , claim ) ; view . refresh ( ) ; return "领取记录已重置。" ; } ) , actions ) ,
resettableGiftPanel ( e , "待领礼包" , data . pendingGifts , "重置待领" , ( pending ) = > runAction ( view . setAction , "正在重置待领记录…" , async ( ) = > { await resetPendingGift ( actions ? ? { } , pending ) ; view . refresh ( ) ; return "待领状态已重置。" ; } ) , actions )
@@ -700,15 +702,47 @@ function giftsSurface(e: ReactLike["createElement"], data: SCUMSurfaceData, inpu
e ( "p" , { className : "page-status" } , "这里是 SCUM 原生 finished_timed_gift_spawner 完成记录,不是插件运营礼包定义。" ) ,
tablePanel ( e , "游戏原生定时礼包" , data . timedGiftEvents , ( event ) = > [ textField ( event , "userProfileId" ) || "unknown" , textField ( event , "mapId" ) || "unknown" , textField ( event , "spawnTime" ) || "unknown" , dateField ( event , "spawnAt" ) ] )
) : null ,
view . giftEditorOpen ? giftEditorDialog ( e , view , actions , saveGift ) : null
view . giftDialog . mode === "view" && selectedGift ? giftDetailsDialog ( e , selectedGift , view , ( ) = > openGiftDialog ( selectedGift , "edit" ) ) : null ,
view . giftDialog . mode === "edit" ? giftEditorDialog ( e , view , actions , saveGift ) : null
) ;
}
function giftDetailsDialog ( e : ReactLike [ "createElement" ] , gift : RecordMap , view : ViewState , editGift : ( ) = > void ) {
const items = giftItemRecords ( gift ) ;
const commands = giftCommandValues ( gift ) ;
const status = textField ( gift , "status" ) . toLowerCase ( ) || "active" ;
return e ( "div" , { className : "confirm-backdrop management-dialog-backdrop gift-dialog-backdrop" , role : "presentation" , onClick : ( ) = > view . setGiftDialog ( { mode : "closed" } ) } ,
e ( "div" , { className : "drawer-panel management-dialog-panel management-dialog-wide" , role : "dialog" , "aria-modal" : "true" , "aria-label" : "查看礼包配置" , onClick : ( event : InputEvent ) = > event . stopPropagation ? . ( ) } ,
e ( "div" , { className : "panel-header dialog-panel-header" } , e ( "div" , { className : "gift-dialog-heading" } , e ( "h2" , null , textField ( gift , "name" ) || textField ( gift , "code" ) || "礼包配置" ) , e ( "span" , { className : "page-status" } , "礼包配置详情" ) ) , e ( "button" , { type : "button" , className : "theme-upload drawer-close" , "aria-label" : "关闭礼包配置" , onClick : ( ) = > view . setGiftDialog ( { mode : "closed" } ) } , "关闭" ) ) ,
e ( "div" , { className : "gift-config-details dialog-form" } ,
e ( "dl" , { className : "gift-config-grid" } ,
giftConfigEntry ( e , "礼包编号" , textField ( gift , "code" , "id" ) || "未配置" ) ,
giftConfigEntry ( e , "状态" , giftStatusLabel ( status ) ) ,
giftConfigEntry ( e , "领取周期" , giftClassLabel ( numField ( gift , "class" ) ) ) ,
giftConfigEntry ( e , "适用玩家" , giftAudienceLabel ( textField ( gift , "audience" ) ) ) ,
giftConfigEntry ( e , "发放次数" , numField ( gift , "number" ) ) ,
giftConfigEntry ( e , "成就门槛" , ` ${ numField ( gift , "achievement" ) } / ${ numField ( gift , "achievementNumber" , "achievement_number" ) } ` )
) ,
e ( "section" , { className : "gift-form-section gift-config-section" , "aria-label" : "礼包内容" } ,
e ( "div" , { className : "gift-form-section-title" } , e ( "strong" , null , "礼包内容" ) , e ( "span" , null , ` ${ items . length } 项物品, ${ commands . length } 条命令 ` ) ) ,
items . length ? e ( "div" , { className : "gift-config-list" } , items . map ( ( item , index ) = > {
const code = textField ( item , "catalogCode" , "catalogItemKey" , "key" , "className" ) ;
const entry = scumCatalogEntryFor ( code ) ;
return e ( "div" , { key : ` ${ code } - ${ index } ` , className : "gift-config-row" } , catalogIconStrip ( e , catalogIconsForValue ( code ) ) , e ( "span" , null , entry ? . name || textField ( item , "label" ) || code || "未命名物品" ) , e ( "code" , null , code || "unknown" ) , e ( "strong" , null , ` × ${ numField ( item , "quantity" ) } ` ) ) ;
} ) ) : e ( "p" , { className : "page-status" } , "未配置物品。" ) ,
commands . length ? e ( "div" , { className : "gift-command-list" , "aria-label" : "礼包命令" } , commands . map ( ( command , index ) = > e ( "code" , { key : ` ${ command } - ${ index } ` } , command ) ) ) : e ( "p" , { className : "page-status" } , "未配置附加命令。" )
) ,
e ( "div" , { className : "confirm-actions gift-dialog-actions" } , e ( "button" , { type : "button" , onClick : ( ) = > view . setGiftDialog ( { mode : "closed" } ) } , "关闭" ) , e ( "button" , { type : "button" , className : "confirm-primary" , onClick : editGift } , "编辑礼包" ) )
)
)
) ;
}
function giftEditorDialog ( e : ReactLike [ "createElement" ] , view : ViewState , actions : SCUMWorkspaceActions | undefined , saveGift : ( ) = > void ) {
const editing = Boolean ( view . giftRecordKey ) ;
return e ( "div" , { className : "confirm-backdrop management-dialog-backdrop gift-dialog-backdrop" , role : "presentation" , onClick : ( ) = > view . setGiftEditorOpen ( false ) } ,
return e ( "div" , { className : "confirm-backdrop management-dialog-backdrop gift-dialog-backdrop" , role : "presentation" , onClick : ( ) = > view . setGiftDialog ( { mode : "closed" } ) } ,
e ( "div" , { className : "drawer-panel management-dialog-panel management-dialog-wide" , role : "dialog" , "aria-modal" : "true" , "aria-label" : editing ? "编辑礼包" : "新建礼包" , onClick : ( event : InputEvent ) = > event . stopPropagation ? . ( ) } ,
e ( "div" , { className : "panel-header dialog-panel-header" } , e ( "div" , { className : "gift-dialog-heading" } , e ( "h2" , null , editing ? "编辑礼包" : "新建礼包" ) , e ( "span" , { className : "page-status" } , editing ? "更新现有礼包定义" : "创建可领取的运营礼包" ) ) , e ( "button" , { type : "button" , className : "theme-upload drawer-close" , "aria-label" : "关闭礼包编辑器" , onClick : ( ) = > view . setGiftEditorOpen ( false ) } , "关闭" ) ) ,
e ( "div" , { className : "panel-header dialog-panel-header" } , e ( "div" , { className : "gift-dialog-heading" } , e ( "h2" , null , editing ? "编辑礼包" : "新建礼包" ) , e ( "span" , { className : "page-status" } , editing ? "更新现有礼包定义" : "创建可领取的运营礼包" ) ) , e ( "button" , { type : "button" , className : "theme-upload drawer-close" , "aria-label" : "关闭礼包编辑器" , onClick : ( ) = > view . setGiftDialog ( { mode : "closed" } ) } , "关闭" ) ) ,
e ( "div" , { className : "gift-form dialog-form management-form" } ,
e ( "div" , { className : "form-guidance management-form-wide" } , e ( "strong" , null , "先定义规则,再配置内容" ) , e ( "span" , null , "礼包编号用于数据主键,只支持字母、数字、点、下划线和短横线;礼包至少要包含一项物品或一条命令。" ) ) ,
labeledField ( e , "礼包编号" , e ( "input" , { value : view.giftCode , "aria-label" : "礼包编号" , placeholder : "例如 welcome_pack" , onChange : ( event : InputEvent ) = > view . setGiftCode ( inputValue ( event ) ) } ) ) ,
@@ -720,7 +754,7 @@ function giftEditorDialog(e: ReactLike["createElement"], view: ViewState, action
labeledField ( e , "成就值" , e ( "input" , { value : view.giftAchievementNumber , "aria-label" : "成就值" , type : "number" , min : "0" , placeholder : "0" , onChange : ( event : InputEvent ) = > view . setGiftAchievementNumber ( inputValue ( event ) ) } ) ) ,
e ( "div" , { className : "gift-form-wide gift-form-section" } , e ( "div" , { className : "gift-form-section-title" } , e ( "strong" , null , "礼包物品" ) , e ( "span" , null , "可用目录选择器快速加入,格式为 目录代码:数量" ) ) , labeledField ( e , "物品清单" , e ( "input" , { value : view.giftItems , "aria-label" : "礼包物品" , placeholder : "例如 BP_Cash_01:2, Water-Bottle.01:1" , onChange : ( event : InputEvent ) = > view . setGiftItems ( inputValue ( event ) ) } ) ) , catalogPicker ( e , view , "gift-items" ) ) ,
e ( "div" , { className : "gift-form-wide gift-form-section" } , e ( "div" , { className : "gift-form-section-title" } , e ( "strong" , null , "礼包命令" ) , e ( "span" , null , "每行一条 SCUM RCON 命令,可选" ) ) , labeledField ( e , "命令清单" , e ( "textarea" , { value : view.giftCommands , "aria-label" : "礼包命令" , placeholder : "例如 #announce Welcome\n每行一条命令" , onChange : ( event : InputEvent ) = > view . setGiftCommands ( inputValue ( event ) ) } ) ) ) ,
e ( "div" , { className : "confirm-actions gift-dialog-actions" } , e ( "button" , { type : "button" , onClick : ( ) = > view . setGiftEditorOpen ( false ) } , "取消" ) , e ( "button" , { type : "button" , className : "confirm-primary" , disabled : ! actions ? . pluginData , onClick : saveGift } , "保存礼包" ) )
e ( "div" , { className : "confirm-actions gift-dialog-actions" } , e ( "button" , { type : "button" , onClick : ( ) = > view . setGiftDialog ( { mode : "closed" } ) } , "取消" ) , e ( "button" , { type : "button" , className : "confirm-primary" , disabled : ! actions ? . pluginData , onClick : saveGift } , "保存礼包" ) )
)
)
) ;
@@ -1500,6 +1534,9 @@ function giftItemsSummary(gift: RecordMap): string { const items = field(gift, "
function giftCommandsSummary ( gift : RecordMap ) : string { const commands = field ( gift , "commands" ) ; return Array . isArray ( commands ) && commands . length ? ` ${ commands . length } 条命令 ` : "无命令" ; }
function giftItemsInput ( gift : RecordMap ) : string { const items = field ( gift , "items" ) ; return Array . isArray ( items ) ? items . map ( ( item ) = > isRecord ( item ) ? ` ${ textField ( item , "catalogCode" , "catalogItemKey" , "key" ) } : ${ numField ( item , "quantity" ) } ` : "" ) . filter ( Boolean ) . join ( ", " ) : "" ; }
function giftCommandsInput ( gift : RecordMap ) : string { const commands = field ( gift , "commands" ) ; return Array . isArray ( commands ) ? commands . map ( ( item ) = > isRecord ( item ) ? textField ( item , "command" , "value" ) : String ( item ) ) . filter ( Boolean ) . join ( "\n" ) : "" ; }
function giftItemRecords ( gift : RecordMap ) : RecordMap [ ] { const items = field ( gift , "items" ) ; return Array . isArray ( items ) ? items . filter ( isRecord ) : [ ] ; }
function giftCommandValues ( gift : RecordMap ) : string [ ] { const commands = field ( gift , "commands" ) ; return Array . isArray ( commands ) ? commands . map ( ( item ) = > isRecord ( item ) ? textField ( item , "command" , "value" ) : String ( item ) ) . filter ( Boolean ) : [ ] ; }
function giftConfigEntry ( e : ReactLike [ "createElement" ] , label : string , value : string ) { return e ( "div" , { className : "gift-config-entry" } , e ( "dt" , null , label ) , e ( "dd" , null , value ) ) ; }
function giftClassLabel ( value : string ) : string { return ( { "1" : "每日" , "2" : "每周" , "3" : "每月" , "4" : "每年" , "5" : "一次" , "6" : "每日五次" } as Record < string , string > ) [ value ] ? ? value ; }
function giftAudienceLabel ( value : string ) : string { return ( ( { all : "全部玩家" , pve : "PVE 玩家" , pvp : "PVP 玩家" } as Record < string , string > ) [ value ] ? ? value ) || "全部玩家" ; }
function giftStatusLabel ( value : string ) : string { return ( ( { active : "启用" , enabled : "启用" , running : "启用" , scheduled : "启用" , queued : "启用" , disabled : "停用" , inactive : "停用" } as Record < string , string > ) [ value ] ? ? value ) || "启用" ; }