wjx 1 年間 前
コミット
1999dc8ada

+ 18 - 0
config/routerConfig.ts

@@ -135,6 +135,24 @@ const gameDataStatistics = {
                     access: 'roleFightingRanking',
                     component: './gameDataStatistics/roleOperate/roleFightingRanking',
                 },
+                {
+                    path: '/gameDataStatistics/roleOperate/gameServer',
+                    name: '游戏区服',
+                    access: 'gameServer',
+                    component: './gameDataStatistics/roleOperate/gameServer',
+                },
+                {
+                    path: '/gameDataStatistics/roleOperate/pack',
+                    name: '礼包',
+                    access: 'pack',
+                    component: './gameDataStatistics/roleOperate/pack',
+                },
+                {
+                    path: '/gameDataStatistics/roleOperate/createRoleConfig',
+                    name: '有效创角配置',
+                    access: 'createRoleConfig',
+                    component: './gameDataStatistics/roleOperate/createRoleConfig',
+                }
             ]
         },
         {

+ 74 - 0
src/pages/gameDataStatistics/roleOperate/createRoleConfig/editModal.tsx

@@ -0,0 +1,74 @@
+import { useAjax } from "@/Hook/useAjax"
+import { aeGameUserConfigApi } from "@/services/gameData/roleOperate"
+import { Form, InputNumber, Modal, Select, message } from "antd"
+import React from "react"
+
+
+interface Props {
+    gameList: any[]
+    initialValues?: any
+    visible?: boolean
+    onClose?: () => void
+    onChange?: () => void
+}
+/**
+ * 新增 修改 有效创角配置
+ * @param param0 
+ * @returns 
+ */
+const EditModal: React.FC<Props> = ({ gameList, initialValues = {}, visible, onClose, onChange }) => {
+
+    /******************************/
+    const [form] = Form.useForm()
+
+    const aeGameUserConfig = useAjax((params) => aeGameUserConfigApi(params))
+    /******************************/
+
+    const handleOk = async () => {
+        form.submit()
+        let data = await form.validateFields()
+        if (initialValues?.id) {
+            data.id = initialValues?.id
+        }
+        aeGameUserConfig.run(data).then(res => {
+            if (res) {
+                if (initialValues?.id) {
+                    message.success('修改成功')
+                } else {
+                    message.success('新增成功')
+                }
+                onChange?.()
+            }
+        })
+    }
+
+    return <Modal title={`${initialValues?.id ? '修改' : '新增'}有效创角配置`} visible={visible} onCancel={onClose} onOk={handleOk} confirmLoading={aeGameUserConfig.loading}>
+        <Form
+            name="basicCreateRole"
+            labelCol={{ span: 4 }}
+            wrapperCol={{ span: 20 }}
+            form={form}
+            autoComplete="off"
+            initialValues={{ ...initialValues }}
+        >
+            <Form.Item label="游戏" name="gameId" rules={[{ required: true, message: '请选择游戏!' }]}>
+                <Select
+                    showSearch
+                    style={{ minWidth: 180 }}
+                    allowClear
+                    placeholder="选择游戏"
+                    filterOption={(input, option) =>
+                        (option?.children as any)?.toLowerCase().indexOf(input.toLowerCase()) >= 0
+                    }
+                >
+                    {gameList?.map((item: any) => <Select.Option value={item.id} key={item.id}>{item.name}</Select.Option>)}
+                </Select>
+            </Form.Item>
+            <Form.Item label="角色等级" name="roleLevel" rules={[{ required: true, message: '请输入角色等级!' }]}>
+                <InputNumber min={0} placeholder="请输入角色等级" style={{ width: '100%' }}/>
+            </Form.Item>
+        </Form>
+    </Modal>
+}
+
+export default React.memo(EditModal)

+ 141 - 0
src/pages/gameDataStatistics/roleOperate/createRoleConfig/index.tsx

@@ -0,0 +1,141 @@
+import { useAjax } from "@/Hook/useAjax"
+import Tables from "@/components/Tables"
+import { getGameChoiceListApi } from "@/services/gameData"
+import { CreateRoleConfigProps, delGameUserConfigApi, getCreateRoleConfigListApi } from "@/services/gameData/roleOperate"
+import { PlusOutlined } from "@ant-design/icons"
+import { Button, Card, Col, Form, Row, Select, Space, message } from "antd"
+import React, { useEffect, useState } from "react"
+import style from '../../components/TableData/index.less'
+import columnsPos from "./tableConfig"
+import EditModal from "./editModal"
+
+/**
+ * 有效创角配置
+ * @returns 
+ */
+const CreateRoleConfig: React.FC = () => {
+
+    /**************************/
+    const [form] = Form.useForm()
+    const [initialValues, setInitialValues] = useState<any>({})
+    const [queryFrom, setQueryForm] = useState<CreateRoleConfigProps>({ pageNum: 1, pageSize: 20 })
+    const [visible, setVisible] = useState<boolean>(false)
+    const getGameChoiceList = useAjax(() => getGameChoiceListApi())
+    const getCreateRoleConfigList = useAjax((params) => getCreateRoleConfigListApi(params))
+    const delGameUserConfig = useAjax((params) => delGameUserConfigApi(params))
+    /**************************/
+    useEffect(() => {
+        getCreateRoleConfigList.run(queryFrom)
+    }, [queryFrom])
+
+    useEffect(() => {
+        getGameChoiceList.run()
+    }, [])
+
+    const onFinish = (data: any) => {
+        let oldQueryFrom = JSON.parse(JSON.stringify(queryFrom))
+        setQueryForm({ ...oldQueryFrom, ...data, pageNum: 1 })
+    }
+
+    const editGameServer = (data: any) => {
+        setVisible(true)
+        const { id, gameId, roleLevel } = data
+        setInitialValues({ id, gameId, roleLevel })
+    }
+
+    const del = (id: number) => {
+        delGameUserConfig.run({ id }).then(res => {
+            if (res) {
+                message.success('删除成功')
+                getCreateRoleConfigList.refresh()
+            }
+        })
+    }
+
+    return <Card
+        style={{ borderRadius: 8 }}
+        headStyle={{ textAlign: 'left' }}
+        bodyStyle={{ padding: '5px 10px' }}
+    >
+        <div style={{ textAlign: 'center', fontWeight: 'bold', padding: '4px 6px 6px', fontSize: 16, marginBottom: 4, position: 'relative' }}>
+            有效创角配置
+        </div>
+
+        <Space style={{ width: '100%' }} direction="vertical" size={10}>
+            <Form layout="inline" className='queryForm' initialValues={initialValues} name="basicGameServer" form={form} onFinish={onFinish}>
+                <Row gutter={[0, 6]}>
+                    <Col><Form.Item name='gameId'>
+                        <Select
+                            maxTagCount={1}
+                            showSearch
+                            style={{ minWidth: 140 }}
+                            allowClear
+                            placeholder={'请选择游戏'}
+                            filterOption={(input, option) =>
+                                (option?.children as any)?.toLowerCase().indexOf(input.toLowerCase()) >= 0
+                            }
+                        >
+                            {getGameChoiceList?.data?.map((item: any) => <Select.Option value={item.id} key={item.id}>{item.name}</Select.Option>)}
+                        </Select>
+                    </Form.Item></Col>
+
+                    <Col>
+                        <Space>
+                            <Button type="primary" htmlType="submit">搜索</Button>
+                            <Button onClick={() => form.resetFields()}>重置</Button>
+                        </Space>
+                    </Col>
+                </Row>
+            </Form>
+
+            <Space wrap>
+                <Button icon={<PlusOutlined />} type="primary" onClick={() => { setVisible(true); setInitialValues({}) }}>新增有效创角配置</Button>
+            </Space>
+
+
+            <div className={`${style['small']}`}>
+                <Tables
+                    className={`all_table content_table_body`}
+                    bordered
+                    sortDirections={['ascend', 'descend', null]}
+                    current={queryFrom.pageNum}
+                    pageSize={queryFrom.pageSize}
+                    columns={columnsPos(editGameServer, del)}
+                    dataSource={getCreateRoleConfigList?.data?.records}
+                    scroll={{ x: 1000, y: 600 }}
+                    onChange={(pagination: any, filters: any, sortData: any) => {
+                        let { current, pageSize } = pagination
+                        let newQueryForm = JSON.parse(JSON.stringify(queryFrom))
+                        if (sortData && sortData?.order) {
+                            newQueryForm['sortType'] = sortData?.order === 'ascend' ? 'asc' : 'desc'
+                            newQueryForm['sortFiled'] = sortData?.field
+                        } else {
+                            delete newQueryForm['sortType']
+                            delete newQueryForm['sortFiled']
+                        }
+                        newQueryForm.pageNum = current
+                        newQueryForm.pageSize = pageSize
+                        setQueryForm({ ...newQueryForm })
+                    }}
+                    size="small"
+                    total={getCreateRoleConfigList?.data?.total}
+                    loading={getCreateRoleConfigList?.loading}
+                    defaultPageSize={20}
+                />
+            </div>
+        </Space>
+
+        {visible && <EditModal
+            visible={visible}
+            initialValues={initialValues}
+            gameList={getGameChoiceList?.data}
+            onClose={() => { setVisible(false); }}
+            onChange={() => {
+                getCreateRoleConfigList.refresh()
+                setVisible(false);
+            }}
+        />}
+    </Card>
+}
+
+export default CreateRoleConfig

+ 68 - 0
src/pages/gameDataStatistics/roleOperate/createRoleConfig/tableConfig.tsx

@@ -0,0 +1,68 @@
+
+
+import { Row, Col, Popconfirm } from "antd"
+import { DeleteOutlined, EditOutlined } from "@ant-design/icons"
+import WidthEllipsis from "@/components/widthEllipsis"
+import React from "react"
+
+function columnsPos(editGameServer: (data: any) => void, del: (id: number) => void) {
+
+    let newArr: any = [
+        {
+            title: '游戏名称',
+            dataIndex: 'gameName',
+            key: 'gameName',
+            align: 'center',
+            width: 90,
+            render: (a: string, b: any) => (<WidthEllipsis value={a} />)
+        },
+        {
+            title: '角色等级',
+            dataIndex: 'roleLevel',
+            key: 'roleLevel',
+            align: 'center',
+            width: 100
+        },
+        {
+            title: '创建时间',
+            dataIndex: 'createTime',
+            key: 'createTime',
+            align: 'center',
+            width: 135,
+            render: (a: string, b: any) => (<WidthEllipsis value={a} />)
+        },
+        {
+            title: '更新时间',
+            dataIndex: 'updateTime',
+            key: 'updateTime',
+            align: 'center',
+            width: 135,
+            render: (a: string, b: any) => (<WidthEllipsis value={a} />)
+        },
+        {
+            title: '操作',
+            dataIndex: 'cz',
+            key: 'cz',
+            align: 'center',
+            width: 100,
+            fixed: 'right',
+            render: (a: string, b: any) => (
+                <Row justify='center' gutter={[10, 0]}>
+                    <Col><a style={{ fontSize: "12px" }} onClick={() => { editGameServer(b) }}><EditOutlined /> 修改</a></Col>
+                    <Col><Popconfirm
+                        title="确定删除?"
+                        onConfirm={() => { del(b.id) }}
+                        okText="是"
+                        cancelText="否"
+                    >
+                        <a style={{ fontSize: "12px", color: 'red' }}><DeleteOutlined /> 删除</a>
+                    </Popconfirm></Col>
+                </Row>
+            )
+        }
+    ]
+    return newArr
+}
+
+
+export default columnsPos

+ 85 - 0
src/pages/gameDataStatistics/roleOperate/gameServer/editModal.tsx

@@ -0,0 +1,85 @@
+import { useAjax } from "@/Hook/useAjax"
+import { aeGameServerApi } from "@/services/gameData/roleOperate"
+import { DatePicker, Form, Input, Modal, Select, message } from "antd"
+import dayjs from "dayjs"
+import React from "react"
+
+
+interface Props {
+    gameList: any[]
+    initialValues?: any
+    visible?: boolean
+    onClose?: () => void
+    onChange?: () => void
+}
+/**
+ * 新增 修改 游戏区服
+ * @param param0 
+ * @returns 
+ */
+const EditModal: React.FC<Props> = ({ gameList, initialValues = {}, visible, onClose, onChange }) => {
+
+    /******************************/
+    const [form] = Form.useForm()
+
+    const aeGameServer = useAjax((params) => aeGameServerApi(params))
+    /******************************/
+
+    const handleOk = async () => {
+        form.submit()
+        let data = await form.validateFields()
+        if (initialValues?.id) {
+            data.id = initialValues?.id
+        }
+        data.startTime = dayjs(data.startTime).format('YYYY-MM-DD HH:mm:ss')
+        aeGameServer.run(data).then(res => {
+            if (res) {
+                if (initialValues?.id) {
+                    message.success('修改成功')
+                } else {
+                    message.success('新增成功')
+                }
+                onChange && onChange()
+            }
+        })
+    }
+
+    return <Modal title={`${initialValues?.id ? '修改' : '新增'}游戏区服`} visible={visible} onCancel={onClose} onOk={handleOk} confirmLoading={aeGameServer.loading}>
+        <Form
+            name="basicGameServer"
+            labelCol={{ span: 4 }}
+            wrapperCol={{ span: 20 }}
+            form={form}
+            autoComplete="off"
+            initialValues={{ ...initialValues }}
+        >
+            <Form.Item label="游戏" name="gameId" rules={[{ required: true, message: '请选择游戏!' }]}>
+                <Select
+                    showSearch
+                    style={{ minWidth: 180 }}
+                    allowClear
+                    placeholder="选择游戏"
+                    filterOption={(input, option) =>
+                        (option?.children as any)?.toLowerCase().indexOf(input.toLowerCase()) >= 0
+                    }
+                >
+                    {gameList?.map((item: any) => <Select.Option value={item.id} key={item.id}>{item.name}</Select.Option>)}
+                </Select>
+            </Form.Item>
+            <Form.Item label="区服名称" name="serverName" rules={[{ required: true, message: '请输入区服名称!' }]}>
+                <Input placeholder="请输入区服名称" />
+            </Form.Item>
+            <Form.Item label="区服ID" name="serverId" rules={[{ required: true, message: '请输入区服ID!' }]}>
+                <Input placeholder="请输入区服ID" />
+            </Form.Item>
+            <Form.Item label="开服时间" name="startTime" rules={[{ required: true, message: '请选择开服时间!' }]}>
+                <DatePicker showTime />
+            </Form.Item>
+            <Form.Item label="区服冠名" name="nickName">
+                <Input placeholder="请输入区服冠名" />
+            </Form.Item>
+        </Form>
+    </Modal>
+}
+
+export default React.memo(EditModal)

+ 305 - 0
src/pages/gameDataStatistics/roleOperate/gameServer/index.tsx

@@ -0,0 +1,305 @@
+import { useAjax } from "@/Hook/useAjax"
+import { GameServerListProps, delGameServerApi, gameSupperListApi, getGameServerListApi, mergeAddOrUpdateApi, unMergeServerListApi } from "@/services/gameData/roleOperate"
+import { Button, Card, Col, DatePicker, Form, Input, Modal, Radio, Row, Select, Space, message } from "antd"
+import React, { useCallback, useEffect, useState } from "react"
+import moment from "moment"
+import { getGameChoiceListApi } from "@/services/gameData"
+import { getPresets } from "@/components/QueryForm/const"
+import Tables from "@/components/Tables"
+import columnsPos from "./tableConfig"
+import style from '../../components/TableData/index.less'
+import { PlusOutlined } from "@ant-design/icons"
+import EditModal from "./editModal"
+import UploadExcel from "./uploadExcel"
+
+let hfParmasInit = {
+    gameId: "",//超父游戏id
+    mainServerId: "",//合服的主服id
+    serverIdList: [],//合并的区服id列表
+    serverName: "",//合服区服名称
+    mergeTime: "",//合服时间
+}
+
+/**
+ * 游戏区服
+ * @returns 
+ */
+const GameServer: React.FC = () => {
+
+    /********************************/
+    const [form] = Form.useForm()
+    const [queryFrom, setQueryForm] = useState<GameServerListProps>({ pageNum: 1, pageSize: 20 })
+    const [hfParmas, set_hfParams] = useState<any>(hfParmasInit)
+    const [visible, setVisible] = useState<boolean>(false)
+    const [initialValues, setInitialValues] = useState<any>({})
+    const [show, set_show] = useState(false)
+    const getGameServerList = useAjax((params) => getGameServerListApi(params))
+    const delGameServer = useAjax((params) => delGameServerApi(params))
+    const game_supper_list_api = useAjax(() => gameSupperListApi())//获取合服超父游戏列表
+    const un_merge_server_list_api = useAjax((params) => unMergeServerListApi(params))//获取合服超父游戏列表
+    const merge_add_or_update_api = useAjax((params) => mergeAddOrUpdateApi(params))//新增合服
+    const getGameChoiceList = useAjax(() => getGameChoiceListApi())
+    /********************************/
+
+    useEffect(() => {
+        game_supper_list_api.run()
+        getGameChoiceList.run()
+    }, [])
+    
+    useEffect(() => {
+        getGameServerList.run(queryFrom)
+    }, [queryFrom])
+
+    const editGameServer = (data: any) => {
+        setVisible(true)
+        const { id, gameId, serverId, serverName, startTime, nickName } = data
+        setInitialValues({ id, gameId, serverId, serverName, startTime: moment(startTime), nickName })
+    }
+
+    const del = (id: number) => {
+        delGameServer.run({ id }).then(res => {
+            if (res) {
+                message.success('删除成功')
+                getGameServerList.refresh()
+            }
+        })
+    }
+
+    // 合服确认
+    const hf_OK = useCallback(() => {
+        let isOk = true
+        for (let key of Object.keys(hfParmas)) {
+            if (!hfParmas[key]) {
+                message.error("缺少参数所有选项必填!!!!")
+                isOk = false
+                break
+            }
+        }
+        if (isOk) {
+            merge_add_or_update_api.run({ ...hfParmas, serverIdList: hfParmas.serverIdList?.map((item: { value: any; }) => item.value) }).then(res => {
+                if (res) {
+                    message.success('新增成功')
+                    set_show(false)
+                    getGameServerList.refresh()
+                }
+            })
+        }
+    }, [hfParmas, getGameServerList])
+
+
+    const onFinish = (data: any) => {
+        console.log('更新了字段---->', data);
+        let oldQueryFrom = JSON.parse(JSON.stringify(queryFrom))
+        if (data?.date) {
+            oldQueryFrom['startTime'] = moment(data.date[0]).format('YYYY-MM-DD')
+            oldQueryFrom['endTime'] = moment(data.date[1]).format('YYYY-MM-DD')
+        } else {
+            delete oldQueryFrom['startTime']
+            delete oldQueryFrom['endTime']
+        }
+        delete data['date']
+        setQueryForm({ ...oldQueryFrom, ...data, pageNum: 1 })
+    }
+
+    return <Card
+        style={{ borderRadius: 8 }}
+        headStyle={{ textAlign: 'left' }}
+        bodyStyle={{ padding: '5px 10px' }}
+    >
+        <div style={{ textAlign: 'center', fontWeight: 'bold', padding: '4px 6px 6px', fontSize: 16, marginBottom: 4, position: 'relative' }}>
+            游戏区服
+        </div>
+
+        <Space style={{ width: '100%' }} direction="vertical" size={10}>
+            <Form layout="inline" className='queryForm' initialValues={initialValues} name="basicGameServer" form={form} onFinish={onFinish}>
+                <Row gutter={[0, 6]}>
+                    <Col><Form.Item name='serverName'>
+                        <Input placeholder="区服名称" allowClear style={{ width: 140 }} />
+                    </Form.Item></Col>
+                    <Col><Form.Item name='serverId'>
+                        <Input placeholder="区服ID" allowClear style={{ width: 140 }} />
+                    </Form.Item></Col>
+                    <Col><Form.Item name='nickName'>
+                        <Input placeholder="冠名名称" allowClear style={{ width: 140 }} />
+                    </Form.Item></Col>
+                    <Col><Form.Item name='gameId'>
+                        <Select
+                            maxTagCount={1}
+                            showSearch
+                            style={{ minWidth: 140 }}
+                            allowClear
+                            placeholder={'请选择游戏'}
+                            filterOption={(input, option) =>
+                                (option?.children as any)?.toLowerCase().indexOf(input.toLowerCase()) >= 0
+                            }
+                        >
+                            {getGameChoiceList?.data?.map((item: any) => <Select.Option value={item.id} key={item.id}>{item.name}</Select.Option>)}
+                        </Select>
+                    </Form.Item></Col>
+                    <Col><Form.Item name='isSourceServer'>
+                        <Select
+                            maxTagCount={1}
+                            showSearch
+                            style={{ width: 100 }}
+                            allowClear
+                            placeholder={'是否原始区服'}
+                            filterOption={(input, option) =>
+                                (option?.children as any)?.toLowerCase().indexOf(input.toLowerCase()) >= 0
+                            }
+                        >
+                            <Select.Option value={false}>否</Select.Option>
+                            <Select.Option value={true}>是</Select.Option>
+                        </Select>
+                    </Form.Item></Col>
+                    <Col><Form.Item name='date'>
+                        <DatePicker.RangePicker placeholder={['开服开始日期', '开服结束日期']} ranges={getPresets() as any} />
+                    </Form.Item></Col>
+
+                    <Col>
+                        <Space>
+                            <Button type="primary" htmlType="submit">搜索</Button>
+                            <Button onClick={() => form.resetFields()}>重置</Button>
+                        </Space>
+                    </Col>
+                </Row>
+            </Form>
+
+            <Space wrap>
+                <Button icon={<PlusOutlined />} type="primary" onClick={() => { setVisible(true); setInitialValues({ startTime: moment().add(90, 'd') }) }}>新增游戏区服</Button>
+                <Button icon={<PlusOutlined />} type="primary" onClick={() => { set_show(true) }}>新增合服</Button>
+                <UploadExcel gameList={game_supper_list_api?.data?.data} onChange={() => getGameServerList.refresh()}/>
+            </Space>
+
+            <div className={`${style['small']}`}>
+                <Tables
+                    className={`all_table content_table_body`}
+                    bordered
+                    sortDirections={['ascend', 'descend', null]}
+                    current={queryFrom.pageNum}
+                    pageSize={queryFrom.pageSize}
+                    columns={columnsPos(editGameServer, del)}
+                    dataSource={getGameServerList?.data?.records}
+                    scroll={{ x: 1000, y: 600 }}
+                    onChange={(pagination: any, filters: any, sortData: any) => {
+                        let { current, pageSize } = pagination
+                        let newQueryForm = JSON.parse(JSON.stringify(queryFrom))
+                        if (sortData && sortData?.order) {
+                            newQueryForm['sortType'] = sortData?.order === 'ascend' ? 'asc' : 'desc'
+                            newQueryForm['sortFiled'] = sortData?.field
+                        } else {
+                            delete newQueryForm['sortType']
+                            delete newQueryForm['sortFiled']
+                        }
+                        newQueryForm.pageNum = current
+                        newQueryForm.pageSize = pageSize
+                        setQueryForm({ ...newQueryForm })
+                    }}
+                    size="small"
+                    total={getGameServerList?.data?.total}
+                    loading={getGameServerList?.loading}
+                    defaultPageSize={20}
+                />
+            </div>
+        </Space>
+
+        {visible && <EditModal
+            visible={visible}
+            initialValues={initialValues}
+            gameList={game_supper_list_api?.data?.data}
+            onClose={() => { setVisible(false); setInitialValues({}) }}
+            onChange={() => {
+                setVisible(false);
+                setInitialValues({})
+                getGameServerList.refresh()
+            }}
+        />}
+
+        {/* 合服弹窗 */}
+        {show && <Modal title={`${hfParmas?.id ? '修改' : '新增'}合服`}
+            visible={show}
+            onCancel={() => set_show(false)}
+            onOk={hf_OK}
+            confirmLoading={merge_add_or_update_api?.loading}
+        >
+            <Row gutter={[20, 20]}>
+                <Col span={24}>
+                    <Space>
+                        <div style={{ width: 140, textAlign: 'right' }}><span style={{ color: 'red' }}>*</span>超父游戏:</div>
+                        <Select
+                            showSearch
+                            style={{ minWidth: 300 }}
+                            allowClear
+                            placeholder="选择游戏"
+                            filterOption={(input, option) =>
+                                (option?.children as any)?.toLowerCase().indexOf(input.toLowerCase()) >= 0
+                            }
+                            onChange={(value) => {
+                                if (value) {
+                                    un_merge_server_list_api.run({ gameId: value })
+                                }
+                                set_hfParams({ ...hfParmas, gameId: value })
+                            }}
+                        >
+                            {game_supper_list_api?.data?.data?.map((item: any) => <Select.Option value={item.id} key={item.id}>{item.name}</Select.Option>)}
+                        </Select>
+                    </Space>
+                </Col>
+                <Col span={24}>
+                    <Space>
+                        <div style={{ width: 140, textAlign: 'right' }}><span style={{ color: 'red' }}>*</span>合服区服名称:</div>
+                        <Input placeholder="请输入合服区服名称" style={{ width: 300 }} onChange={(e) => {
+                            let value = e.target.value
+                            set_hfParams({ ...hfParmas, serverName: value })
+                        }} />
+                    </Space>
+                </Col>
+                <Col span={24}>
+                    <Space>
+                        <div style={{ width: 140, textAlign: 'right' }}><span style={{ color: 'red' }}>*</span>选择要合区服:</div>
+                        <Select
+                            mode="multiple"
+                            showSearch
+                            style={{ minWidth: 300 }}
+                            allowClear
+                            placeholder="选择区服"
+                            filterOption={(input, option) =>
+                                (option?.children as any)?.toLowerCase().indexOf(input.toLowerCase()) >= 0
+                            }
+                            onChange={(value, option) => {
+                                console.log(value, option)
+                                set_hfParams({ ...hfParmas, serverIdList: option })
+                            }}
+                        >
+                            {un_merge_server_list_api?.data?.data?.map((item: any) => <Select.Option value={item.serverId} key={item.serverId}>{item.serverName}</Select.Option>)}
+                        </Select>
+                    </Space>
+                </Col>
+                <Col span={24}>
+                    <Space>
+                        <div style={{ width: 140, textAlign: 'right' }}><span style={{ color: 'red' }}>*</span>选择合服主服:</div>
+                        <Radio.Group onChange={(e) => {
+                            let value = e.target.value
+                            set_hfParams({ ...hfParmas, mainServerId: value })
+                        }}>
+                            {
+                                hfParmas?.serverIdList?.map((item: any) => {
+                                    return <Radio value={item.value} key={item.value}>{item.children}</Radio>
+                                })
+                            }
+                        </Radio.Group>
+                    </Space>
+                </Col>
+                <Col span={24}>
+                    <Space>
+                        <div style={{ width: 140, textAlign: 'right' }}><span style={{ color: 'red' }}>*</span>合服时间:</div>
+                        <DatePicker showTime onChange={(d, str) => {
+                            set_hfParams({ ...hfParmas, mergeTime: str })
+                        }} />
+                    </Space>
+                </Col>
+            </Row>
+        </Modal>}
+    </Card>
+}
+
+export default GameServer

+ 155 - 0
src/pages/gameDataStatistics/roleOperate/gameServer/tableConfig.tsx

@@ -0,0 +1,155 @@
+
+
+import { Row, Col, Popconfirm } from "antd"
+import { DeleteOutlined, EditOutlined } from "@ant-design/icons"
+import WidthEllipsis from "@/components/widthEllipsis"
+import React from "react"
+
+function columnsPos(editGameServer: (data: any) => void, del: (id: number) => void) {
+
+    let newArr: any[] = [
+        {
+            title: '游戏名称',
+            dataIndex: 'gameName',
+            key: 'gameName',
+            align: 'center',
+            width: 90,
+            render: (a: string, b: any) => (<WidthEllipsis value={a} />)
+        },
+        {
+            title: '区服名称',
+            dataIndex: 'serverName',
+            key: 'serverName',
+            align: 'center',
+            width: 100,
+            render: (a: string, b: any) => (<WidthEllipsis value={a} />)
+        },
+        {
+            title: '区服ID',
+            dataIndex: 'serverId',
+            key: 'serverId',
+            align: 'center',
+            width: 100,
+            render: (a: string, b: any) => (<WidthEllipsis isCopy value={a} />)
+        },
+        {
+            title: '区服冠名',
+            dataIndex: 'nickName',
+            key: 'nickName',
+            align: 'center',
+            width: 100,
+            render: (a: string, b: any) => (<WidthEllipsis value={a} />)
+        },
+        {
+            title: '开服时间',
+            dataIndex: 'startTime',
+            key: 'startTime',
+            align: 'center',
+            width: 135,
+            render: (a: string, b: any) => (<WidthEllipsis value={a} />)
+        },
+        {
+            title: '创建时间',
+            dataIndex: 'createTime',
+            key: 'createTime',
+            align: 'center',
+            width: 135,
+            render: (a: string, b: any) => (<WidthEllipsis value={a} />)
+        },
+        {
+            title: '更新时间',
+            dataIndex: 'updateTime',
+            key: 'updateTime',
+            align: 'center',
+            width: 135,
+            render: (a: string, b: any) => (<WidthEllipsis value={a} />)
+        },
+        {
+            title: '是否参与过合服',
+            dataIndex: 'isMerge',
+            key: 'isMerge',
+            align: 'center',
+            width: 100,
+            render: (a: string, b: any) => (<WidthEllipsis value={a ? "是" : "否"} />)
+        },
+        {
+            title: '是否原始服',
+            dataIndex: 'isSourceServer',
+            key: 'isSourceServer',
+            align: 'center',
+            width: 100,
+            render: (a: string, b: any) => (<WidthEllipsis value={a ? "是" : "否"} />)
+        },
+        {
+            title: '合服时间',
+            dataIndex: 'mergeTime',
+            key: 'mergeTime',
+            align: 'center',
+            width: 100,
+            render: (a: string, b: any) => (<WidthEllipsis value={a} />)
+        },
+        {
+            title: '合服的主服名称',
+            dataIndex: 'mainServerName',
+            key: 'mainServerName',
+            align: 'center',
+            width: 100,
+            render: (a: string, b: any) => (<WidthEllipsis value={a} />)
+        },
+        {
+            title: '合服包含的子服',
+            dataIndex: 'sonServerList',
+            key: 'sonServerList',
+            align: 'center',
+            width: 100,
+            render: (a: any) => {
+                let arr = a?.map((item: { serverName: any }) => {
+                    return item.serverName
+                })
+                return <WidthEllipsis value={arr?.join()} />
+            }
+        },
+        {
+            title: '合服包含的原始服',
+            dataIndex: 'sourceServerList',
+            key: 'sourceServerList',
+            align: 'center',
+            width: 100,
+            render: (a: any) => {
+                let arr = a?.map((item: { serverName: any }) => {
+                    return item.serverName
+                })
+                return <WidthEllipsis value={arr?.join()} />
+            }
+        },
+        {
+            title: '操作',
+            dataIndex: 'cz',
+            key: 'cz',
+            align: 'center',
+            width: 100,
+            fixed: 'right',
+            render: (a: string, b: any) => (
+                <Row justify='center' gutter={[10, 0]}>
+                    {b?.isSourceServer ? <>
+                        <Col><a style={{ fontSize: "12px" }} onClick={() => { editGameServer(b) }}><EditOutlined /> 修改</a></Col>
+                        <Col>
+                            <Popconfirm
+                                title="确定删除?"
+                                onConfirm={() => { del(b.id) }}
+                                okText="是"
+                                cancelText="否"
+                            >
+                                <a style={{ fontSize: "12px", color: 'red' }}><DeleteOutlined /> 删除</a>
+                            </Popconfirm>
+                        </Col>
+                    </> : <>--</>}
+                </Row>
+            )
+        }
+    ]
+    return newArr
+}
+
+
+export default columnsPos

+ 96 - 0
src/pages/gameDataStatistics/roleOperate/gameServer/uploadExcel.tsx

@@ -0,0 +1,96 @@
+import { useAjax } from "@/Hook/useAjax"
+import { uploadExcelServerApi } from "@/services/gameData/roleOperate"
+import { CloudUploadOutlined, UploadOutlined } from "@ant-design/icons"
+import { Button, Form, Modal, Radio, Select, Upload, message } from "antd"
+import React, { useState } from "react"
+
+interface Props {
+    gameList: any[]
+    onChange?: () => void
+}
+/**
+ * 游戏区服上传Excel
+ * @returns 
+ */
+const UploadExcel: React.FC<Props> = ({ gameList, onChange }) => {
+
+    /***********************************/
+    const [visible, setVisible] = useState<boolean>(false)
+    const [form] = Form.useForm()
+    const uploadExcelServer = useAjax((params) => uploadExcelServerApi(params))//获取合服超父游戏列表
+    /***********************************/
+
+    const handleOk = async () => {
+        form.submit()
+        let data = await form.validateFields()
+        const { multipartFile, ...params } = data
+        let formData = new FormData();
+        formData.append('multipartFile', multipartFile[0]?.originFileObj)
+        uploadExcelServer.run({ ...params, formData }).then(res => {
+            if (res) {
+                message.success('上传成功')
+                form.setFieldsValue({})
+                setVisible(false)
+                onChange && onChange()
+            }
+        })
+    }
+
+    const normFile = (e: any) => {
+        if (Array.isArray(e)) {
+            return e;
+        }
+        return e?.fileList;
+    };
+
+    return <>
+        <Button icon={<CloudUploadOutlined />} type="primary" onClick={() => { setVisible(true); }}>上传Excel</Button>
+
+        {visible && <Modal
+            title="上传Excel"
+            visible={visible}
+            onCancel={() => { form.setFieldsValue({}); setVisible(false) }}
+            onOk={handleOk}
+        >
+            <Form
+                name="basicGameServerUpload"
+                labelCol={{ span: 4 }}
+                wrapperCol={{ span: 20 }}
+                form={form}
+                autoComplete="off"
+                initialValues={{ gameServerExcelEnum: 'SERVER_ADD' }}
+            >
+                <Form.Item label="游戏" name="gameId" rules={[{ required: true, message: '请选择游戏!' }]}>
+                    <Select
+                        showSearch
+                        allowClear
+                        placeholder="选择游戏"
+                        filterOption={(input, option) =>
+                            (option?.children as any)?.toLowerCase().indexOf(input.toLowerCase()) >= 0
+                        }
+                    >
+                        {gameList?.map((item: any) => <Select.Option value={item.id} key={item.id}>{item.name}</Select.Option>)}
+                    </Select>
+                </Form.Item>
+                <Form.Item label="文件类型" name="gameServerExcelEnum" rules={[{ required: true, message: '请选择文件类型!' }]}>
+                    <Radio.Group>
+                        <Radio value={'SERVER_ADD'}>添加区服</Radio>
+                        <Radio value={'SERVER_MERGE'}>合并区服</Radio>
+                    </Radio.Group>
+                </Form.Item>
+                <Form.Item label="选择文件" name="multipartFile" getValueFromEvent={normFile} rules={[{ required: true, message: '请选择文件!' }]} valuePropName="fileList">
+                    <Upload
+                        name="avatar"
+                        accept=".xlsx,.xls"
+                        maxCount={1}
+                        beforeUpload={() => { return false }}
+                    >
+                        <Button icon={<UploadOutlined />}>上传Excel</Button>
+                    </Upload>
+                </Form.Item>
+            </Form>
+        </Modal>}
+    </>
+}
+
+export default React.memo(UploadExcel)

+ 161 - 0
src/pages/gameDataStatistics/roleOperate/pack/index.tsx

@@ -0,0 +1,161 @@
+import { useAjax } from "@/Hook/useAjax"
+import Tables from "@/components/Tables"
+import { getGameListApi } from "@/services/gameData"
+import { GetPackProps, delPackApi, getPackListApi } from "@/services/gameData/roleOperate"
+import { Button, Card, Col, Form, Input, Row, Select, Space, message } from "antd"
+import React, { useEffect, useState } from "react"
+import style from '../../components/TableData/index.less'
+import columnsPos from "./tableConfig"
+import StagingModal from "./stagingModal"
+import { PlusOutlined } from "@ant-design/icons"
+
+/**
+ * 礼包
+ * @returns 
+ */
+const Pack: React.FC = () => {
+
+    /******************************/
+    const [form] = Form.useForm()
+    const [initialValues, setInitialValues] = useState<any>({})
+    const [queryFrom, setQueryForm] = useState<GetPackProps>({ pageNum: 1, pageSize: 20 })
+    const [visible, setVisible] = useState<boolean>(false)
+    const [thatStoreData, setThatStoreData] = useState<{ gameList: any[] }>({ gameList: [] })
+    const [superGameList, setSuperGameList] = useState<any[]>([])
+    const getPackList = useAjax((params) => getPackListApi(params))
+    const delPack = useAjax((params) => delPackApi(params))
+    const getGameList = useAjax(() => getGameListApi())
+    /******************************/
+
+    const onFinish = (data: any) => {
+        let oldQueryFrom = JSON.parse(JSON.stringify(queryFrom))
+        setQueryForm({ ...oldQueryFrom, ...data, pageNum: 1 })
+    }
+
+    useEffect(() => {
+        getGameList.run().then(res => {
+            if (res) {
+                console.log(res)
+                const { parentGameList, superGameList } = res
+                setSuperGameList(superGameList)
+                setThatStoreData({ gameList: parentGameList?.map((item: { parent_game_name: any; super_game_id: any, parent_game_id: any }) => ({ name: item.parent_game_name, id: item.parent_game_id, superId: item.super_game_id })) })
+            }
+        })
+    }, [])
+
+    useEffect(() => {
+        getPackList.run(queryFrom)
+    }, [queryFrom])
+
+    const editPack = (data: any) => {
+        setInitialValues(data)
+        setVisible(true)
+    }
+
+    const del = (id: number) => {
+        delPack.run(id).then(res => {
+            if (res) {
+                message.success('删除成功')
+                getPackList.refresh()
+            }
+        })
+    }
+
+    const stagingModalChange = () => {
+        setInitialValues({})
+        setVisible(false)
+        getPackList.refresh()
+    }
+
+    return <Card
+        style={{ borderRadius: 8 }}
+        headStyle={{ textAlign: 'left' }}
+        bodyStyle={{ padding: '5px 10px' }}
+    >
+        <div style={{ textAlign: 'center', fontWeight: 'bold', padding: '4px 6px 6px', fontSize: 16, marginBottom: 4, position: 'relative' }}>
+            礼包
+        </div>
+        <Space style={{ width: '100%' }} direction="vertical" size={10}>
+            <Form layout="inline" className='queryForm' initialValues={initialValues} name="basicGameServer" form={form} onFinish={onFinish}>
+                <Row gutter={[0, 6]}>
+                    <Col><Form.Item name='giftName'>
+                        <Input placeholder="礼包名称" allowClear style={{ width: 140 }} />
+                    </Form.Item></Col>
+                    <Col><Form.Item name='superGameId'>
+                        <Select
+                            maxTagCount={1}
+                            showSearch
+                            style={{ minWidth: 140 }}
+                            allowClear
+                            placeholder={'请选择超父游戏'}
+                            filterOption={(input, option) =>
+                                (option?.children as any)?.toLowerCase().indexOf(input.toLowerCase()) >= 0
+                            }
+                        >
+                            {superGameList?.map((item: any) => <Select.Option value={item.super_game_id} key={item.super_game_id}>{item.super_game_name}</Select.Option>)}
+                        </Select>
+                    </Form.Item></Col>
+                    <Col><Form.Item name='parentGameId'>
+                        <Select
+                            maxTagCount={1}
+                            showSearch
+                            style={{ minWidth: 140 }}
+                            allowClear
+                            placeholder={'请选择父游戏'}
+                            filterOption={(input, option) =>
+                                (option?.children as any)?.toLowerCase().indexOf(input.toLowerCase()) >= 0
+                            }
+                        >
+                            {thatStoreData?.gameList?.map((item: any) => <Select.Option value={item.id} key={item.id}>{item.name}</Select.Option>)}
+                        </Select>
+                    </Form.Item></Col>
+                    <Col>
+                        <Space>
+                            <Button type="primary" htmlType="submit">搜索</Button>
+                            <Button onClick={() => form.resetFields()}>重置</Button>
+                        </Space>
+                    </Col>
+                </Row>
+            </Form>
+
+            <Space wrap>
+                <Button icon={<PlusOutlined />} type="primary" onClick={() => { setVisible(true); setInitialValues({}) }}>新增礼包</Button>
+            </Space>
+
+            <div className={`${style['small']}`}>
+                <Tables
+                    className={`all_table content_table_body`}
+                    bordered
+                    sortDirections={['ascend', 'descend', null]}
+                    current={queryFrom.pageNum}
+                    pageSize={queryFrom.pageSize}
+                    columns={columnsPos(editPack, del)}
+                    dataSource={getPackList?.data?.records}
+                    scroll={{ x: 1000, y: 600 }}
+                    onChange={(pagination: any, filters: any, sortData: any) => {
+                        let { current, pageSize } = pagination
+                        let newQueryForm = JSON.parse(JSON.stringify(queryFrom))
+                        if (sortData && sortData?.order) {
+                            newQueryForm['sortType'] = sortData?.order === 'ascend' ? 'asc' : 'desc'
+                            newQueryForm['sortFiled'] = sortData?.field
+                        } else {
+                            delete newQueryForm['sortType']
+                            delete newQueryForm['sortFiled']
+                        }
+                        newQueryForm.pageNum = current
+                        newQueryForm.pageSize = pageSize
+                        setQueryForm({ ...newQueryForm })
+                    }}
+                    size="small"
+                    total={getPackList?.data?.total}
+                    loading={getPackList?.loading}
+                    defaultPageSize={20}
+                />
+            </div>
+        </Space>
+
+        {visible && <StagingModal initialValues={initialValues} visible={visible} gameList={thatStoreData.gameList} onClose={() => setVisible(false)} onChange={stagingModalChange} />}
+    </Card>
+}
+
+export default Pack

+ 87 - 0
src/pages/gameDataStatistics/roleOperate/pack/stagingModal.tsx

@@ -0,0 +1,87 @@
+import { useAjax } from "@/Hook/useAjax"
+import { addOrUpDatePackApi } from "@/services/gameData/roleOperate"
+import { Form, Input, Modal, Select, message } from "antd"
+import React, { useEffect, useState } from "react"
+
+
+interface Props {
+    gameList: any[]
+    initialValues?: any
+    visible?: boolean
+    onClose?: () => void
+    onChange?: () => void
+}
+/**
+ * 礼包操作
+ * @returns 
+ */
+const StagingModal: React.FC<Props> = ({ visible, onClose, onChange, initialValues = {}, gameList = [] }) => {
+    
+    /******************************/
+    const [form] = Form.useForm()
+    const [superGameId, setSuperGameId] = useState<number>()
+    const addOrUpDatePack = useAjax((params) => addOrUpDatePackApi(params))
+    /******************************/
+
+    useEffect(() => {
+        setSuperGameId(initialValues?.superGameId)
+    }, [initialValues])
+
+    const handleOk = async () => {
+        form.submit()
+        let data = await form.validateFields()
+        data.superGameId = superGameId
+        if (initialValues?.id) {
+            data.id = initialValues?.id
+        }
+        addOrUpDatePack.run(data).then(res => {
+            if (res) {
+                if (initialValues?.id) {
+                    message.success('修改成功')
+                } else {
+                    message.success('新增成功')
+                }
+                onChange && onChange()
+            }
+        })
+    }
+
+    return <Modal
+        title={`${initialValues?.id ? '修改' : '新增'}礼包`}
+        visible={visible}
+        onCancel={onClose}
+        onOk={handleOk}
+        confirmLoading={addOrUpDatePack.loading}
+    >
+        <Form
+            name="basicPack"
+            labelCol={{ span: 4 }}
+            wrapperCol={{ span: 20 }}
+            form={form}
+            autoComplete="off"
+            initialValues={{ ...initialValues }}
+        >
+            <Form.Item label="礼包名称" name="giftName" rules={[{ required: true, message: '请输入礼包名称!' }]}>
+                <Input placeholder="请输入礼包名称"/>
+            </Form.Item>
+            <Form.Item label="游戏" name="parentGameId" rules={[{ required: true, message: '请选择游戏!' }]}>
+                <Select
+                    showSearch
+                    style={{ minWidth: 180 }}
+                    allowClear
+                    placeholder="选择游戏"
+                    filterOption={(input, option) =>
+                        (option?.children as any)?.toLowerCase().indexOf(input.toLowerCase()) >= 0
+                    }
+                    onChange={(e, option) => {
+                        setSuperGameId(option?.['data-super-id'])
+                    }}
+                >
+                    {gameList?.map((item: any) => <Select.Option value={item.id} key={item.id} data-super-id={item.superId}>{item.name}</Select.Option>)}
+                </Select>
+            </Form.Item>
+        </Form>
+    </Modal>
+}
+
+export default React.memo(StagingModal)

+ 95 - 0
src/pages/gameDataStatistics/roleOperate/pack/tableConfig.tsx

@@ -0,0 +1,95 @@
+
+
+import { Row, Col, Popconfirm } from "antd"
+import { DeleteOutlined, EditOutlined } from "@ant-design/icons"
+import WidthEllipsis from "@/components/widthEllipsis"
+import React from "react"
+
+function columnsPos(editPack: (data: any) => void, del: (id: number) => void) {
+
+    let newArr: any = [
+        {
+            title: '礼包名称',
+            dataIndex: 'giftName',
+            key: 'giftName',
+            align: 'center',
+            width: 90,
+            render: (a: string, b: any) => (<WidthEllipsis value={a} />)
+        },
+        {
+            title: '超父游戏名称',
+            dataIndex: 'superGameName',
+            key: 'superGameName',
+            align: 'center',
+            width: 90,
+            render: (a: string, b: any) => (<WidthEllipsis value={a} />)
+        },
+        {
+            title: '游戏名称',
+            dataIndex: 'parentGameName',
+            key: 'parentGameName',
+            align: 'center',
+            width: 90,
+            render: (a: string, b: any) => (<WidthEllipsis value={a} />)
+        },
+        {
+            title: '创建人',
+            dataIndex: 'createName',
+            key: 'createName',
+            align: 'center',
+            width: 100,
+            render: (a: string, b: any) => (<WidthEllipsis value={a} />)
+        },
+        {
+            title: '创建时间',
+            dataIndex: 'createTime',
+            key: 'createTime',
+            align: 'center',
+            width: 135,
+            render: (a: string, b: any) => (<WidthEllipsis value={a} />)
+        },
+        {
+            title: '更新人',
+            dataIndex: 'updateName',
+            key: 'updateName',
+            align: 'center',
+            width: 100,
+            render: (a: string, b: any) => (<WidthEllipsis value={a} />)
+        },
+        {
+            title: '更新时间',
+            dataIndex: 'updateTime',
+            key: 'updateTime',
+            align: 'center',
+            width: 135,
+            render: (a: string, b: any) => (<WidthEllipsis value={a} />)
+        },
+        {
+            title: '操作',
+            dataIndex: 'cz',
+            key: 'cz',
+            align: 'center',
+            width: 100,
+            fixed: 'right',
+            render: (a: string, b: any) => (
+                <Row justify='center' gutter={[10, 0]}>
+                    <Col><a style={{ fontSize: "12px" }} onClick={() => { editPack(b) }}><EditOutlined /> 修改</a></Col>
+                    <Col>
+                        <Popconfirm
+                            title="确定删除?"
+                            onConfirm={() => { del(b.id) }}
+                            okText="是"
+                            cancelText="否"
+                        >
+                            <a style={{ fontSize: "12px", color: 'red' }}><DeleteOutlined /> 删除</a>
+                        </Popconfirm>
+                    </Col>
+                </Row>
+            )
+        }
+    ]
+    return newArr
+}
+
+
+export default columnsPos

+ 206 - 0
src/services/gameData/roleOperate.ts

@@ -239,3 +239,209 @@ export async function getCombatRankingListApi(data: GetCombatRankingProps) {
         data
     });
 }
+
+let apiManage = api + '/manage'
+
+export interface GameServerListProps {
+    pageNum: number,
+    pageSize: number,
+    startTime?: string,
+    endTime?: string,
+    gameId?: number,
+    nickName?: string,
+    serverId?: number,
+    serverName?: string
+}
+
+/**
+ * 游戏区服列表查询
+ * @param data 
+ * @returns 
+ */
+export async function getGameServerListApi(data: GameServerListProps) {
+    return request(apiManage + '/gameServer/list', {
+        method: 'POST',
+        data
+    });
+}
+
+interface AeGameServerProps {
+    gameId: number,    // 游戏id
+    serverName: string,// 区服名称
+    serverId: string,  // 区服id, 必传
+    startTime: string, // 开服时间
+    id?: number
+    nickName?: string  // 区服冠名
+}
+/**
+ * 新增修改区服
+ * @param data 
+ * @returns 
+ */
+export async function aeGameServerApi(data: AeGameServerProps) {
+    return request(apiManage + '/gameServer/add/or/update', {
+        method: 'POST',
+        data
+    });
+}
+
+/**
+ * 删除游戏区服
+ * @param params 
+ * @returns 
+ */
+export async function delGameServerApi(params: { id: number }) {
+    return request(apiManage + '/gameServer/delete', {
+        method: 'DELETE',
+        params
+    });
+}
+
+/**
+ * 新增合服
+ * @param params 
+ * @returns 
+ */
+export async function mergeAddOrUpdateApi(data: any) {
+    return request(apiManage + '/gameServer/merge/add/or/update', {
+        method: 'POST',
+        data
+    });
+}
+
+
+export async function uploadExcelServerApi({ formData, ...params }: any) {
+    return request(apiManage + '/gameServer/add/excel', {
+        method: 'POST',
+        params,
+        data: formData
+    });
+}
+
+/**
+ * 获取合服超父游戏列表
+ * @param params 
+ * @returns 
+ */
+export async function gameSupperListApi() {
+    return request(apiManage + '/gameServer/game/supper/list', {
+        method: 'GET',
+    });
+}
+/**
+ * 获取合服超父游戏列表
+ * @param params 
+ * @returns 
+ */
+export async function unMergeServerListApi(params: any) {
+    return request(apiManage + '/gameServer/unMerge/server/list', {
+        method: 'GET',
+        params
+    });
+}
+
+
+
+
+
+
+
+export interface PackProps {
+    gameId: number,
+    giftName: string,   // 礼包名字
+    id?: number
+}
+/**
+ * 新增修改礼包
+ * @param params 
+ * @returns 
+ */
+export async function addOrUpDatePackApi(params: PackProps) {
+    return request(apiManage + '/game/gift/add/or/update', {
+        method: 'POST',
+        data: params
+    })
+}
+
+/**
+ * 删除礼包
+ * @param ids 
+ * @returns 
+ */
+export async function delPackApi(ids: string) {
+    return request(apiManage + `/game/gift/delete/${ids}`, {
+        method: 'DELETE'
+    })
+}
+
+export interface GetPackProps {
+    pageNum: number,
+    pageSize: number,
+    giftName?: string,
+    gameId?: number
+}
+/**
+ * 获取礼包列表
+ * @param data 
+ * @returns 
+ */
+export async function getPackListApi(data: GetPackProps) {
+    return request(apiManage + `/game/gift/listOfPage`, {
+        method: 'POST',
+        data
+    })
+}
+
+
+
+
+
+
+
+
+export interface CreateRoleConfigProps {
+    pageNum: number,
+    pageSize: number,
+    gameId?: number
+}
+
+/**
+ * 有效创角配置列表查询
+ * @param data 
+ * @returns 
+ */
+export async function getCreateRoleConfigListApi(data: CreateRoleConfigProps) {
+    return request(apiManage + '/gameUser/config/list', {
+        method: 'POST',
+        data
+    });
+}
+
+interface AeGameServerProps {
+    gameId: number,    // 游戏id
+    roleLevel: number, // 游戏角色等级
+    id?: number
+}
+/**
+ * 新增或修改有效创角配置
+ * @param data 
+ * @returns 
+ */
+export async function aeGameUserConfigApi(data: AeGameServerProps) {
+    return request(apiManage + '/gameUser/config/add/or/update', {
+        method: 'POST',
+        data
+    });
+}
+
+/**
+ * 有效创角配置服删除
+ * @param params 
+ * @returns 
+ */
+export async function delGameUserConfigApi(params: { id: number }) {
+    return request(apiManage + '/gameUser/config/delete', {
+        method: 'DELETE',
+        params
+    });
+}