wjx 8 月之前
父節點
當前提交
69b3561588

+ 6 - 0
config/routerConfig.ts

@@ -153,6 +153,12 @@ const iaaData = {
                     access: 'appCashTrend',
                     component: './iaaData/tencentIaa/appCashTrend',
                 },
+                {
+                    path: '/iaaData/tencentIaa/appCashRetained',
+                    name: '应用变现留存',
+                    access: 'appCashRetained',
+                    component: './iaaData/tencentIaa/appCashRetained',
+                },
                 {
                     path: '/iaaData/tencentIaa/pitcherEveryDay',
                     name: '投手每日数据',

+ 18 - 8
src/app.tsx

@@ -1,4 +1,4 @@
-import React from 'react';
+import React, { useEffect } from 'react';
 import { BasicLayoutProps, Settings as LayoutSettings, MenuDataItem } from '@ant-design/pro-layout';
 import { Button, notification, Result } from 'antd';
 import { history } from 'umi';
@@ -20,6 +20,11 @@ import { ReactComponent as RoleManageSvg } from '@/assets/roleManage.svg'
 import { ReactComponent as SystemIaa } from '@/assets/system_iaa.svg'
 import { ReactComponent as ManageIaa } from '@/assets/manage_iaa.svg'
 import { ReactComponent as TencentAaa } from '@/assets/tencent_iaa.svg'
+import { ReactComponent as TikTokSvg } from '@/assets/tikTok.svg'
+import { ReactComponent as RetainedSvg } from '@/assets/retained.svg'
+import { ReactComponent as TrendSvg } from '@/assets/trend.svg'
+import { ReactComponent as AppEveryDataSvg } from '@/assets/appEveryData.svg'
+import { ReactComponent as AdListSvg } from '@/assets/adList.svg'
 import versions from './utils/versions';
 
 
@@ -48,7 +53,8 @@ export async function getInitialState(): Promise<{
     loading?: boolean,
     collapsed?: string,
     onCollapse?: (onCollapse: boolean) => void,
-    iaaApp?: string
+    iaaApp?: string,
+    mediaPlatform?: string
 }> {
     // 如果是登录页面,不执行
     if (localStorage.getItem('Admin-Token')) {
@@ -128,10 +134,16 @@ const IconMap = {
     system_iaa: <span role="img" aria-label="fund-view" className="anticon anticon-fund-view"><SystemIaa /></span>,
     manage_iaa: <span role="img" aria-label="fund-view" className="anticon anticon-fund-view"><ManageIaa /></span>,
     tencent_iaa: <span role="img" aria-label="fund-view" className="anticon anticon-fund-view"><TencentAaa /></span>,
+    tikTok: <span role="img" aria-label="fund-view" className="anticon anticon-fund-view"><TikTokSvg /></span>,
+    retained: <span role="img" aria-label="fund-view" className="anticon anticon-fund-view"><RetainedSvg /></span>,
+    trend: <span role="img" aria-label="fund-view" className="anticon anticon-fund-view"><TrendSvg /></span>,
+    appEveryData: <span role="img" aria-label="fund-view" className="anticon anticon-fund-view"><AppEveryDataSvg /></span>,
+    adList: <span role="img" aria-label="fund-view" className="anticon anticon-fund-view"><AdListSvg /></span>,
     eye: <EyeOutlined />
 };
+
 //处理菜单
-const loopMenuItem = (menus: MenuDataItem[],): MenuDataItem[] => {
+const loopMenuItem = (menus: MenuDataItem[]): MenuDataItem[] => {
     let menu = menus?.map(({ icon, routes, roles, ...item }) => {
         let newItem = JSON.parse(JSON.stringify(item))
         newItem.key = item?.path || item?.key
@@ -144,11 +156,8 @@ const loopMenuItem = (menus: MenuDataItem[],): MenuDataItem[] => {
     })
     return menu
 }
-export const layout = ({
-    initialState
-}: {
-    initialState: { settings?: LayoutSettings; currentUser?: CurrentUser; menu?: any; loading: boolean, collapsed: string, onCollapse: any };
-}): BasicLayoutProps => {
+
+export const layout = ({ initialState }: { initialState: { settings?: LayoutSettings; currentUser?: CurrentUser; menu?: any; loading: boolean, collapsed: string, onCollapse: any, mediaPlatform?: string }; }): BasicLayoutProps => {
     return {
         menuDataRender: () => {
             return loopMenuItem(initialState?.menu?.data || [])
@@ -160,6 +169,7 @@ export const layout = ({
         breakpoint: false,
         // footerRender: () => <Footer />,
         onPageChange: () => {
+            console.log('111111111111')
             headrRouter(initialState, history)
             let { pathname, query } = history.location
             if (query?.t) {//带token直接进入对应页面

File diff suppressed because it is too large
+ 0 - 0
src/assets/adList.svg


+ 1 - 0
src/assets/appCashTrend.svg

@@ -0,0 +1 @@
+<svg viewBox="64 64 896 896" focusable="false" data-icon="fund-view" width="1em" height="1em" fill="currentColor" aria-hidden="true"><path d="M873.411765 842.390588a60.235294 60.235294 0 0 1-60.235294 60.235294H210.823529a60.235294 60.235294 0 0 1-60.235294-60.235294v-602.352941a60.235294 60.235294 0 0 1 60.235294-60.235294h602.352942a60.235294 60.235294 0 0 1 60.235294 60.235294v602.352941z m60.235294-783.058823H90.352941a60.235294 60.235294 0 0 0-60.235294 60.235294v843.294117a60.235294 60.235294 0 0 0 60.235294 60.235295h843.294118a60.235294 60.235294 0 0 0 60.235294-60.235295v-843.294117a60.235294 60.235294 0 0 0-60.235294-60.235294z m-542.117647 421.647059a60.235294 60.235294 0 0 0 60.235294-60.235295v-120.470588a60.235294 60.235294 0 0 0-60.235294-60.235294H271.058824a60.235294 60.235294 0 0 0-60.235295 60.235294v120.470588a60.235294 60.235294 0 0 0 60.235295 60.235295h120.470588z m361.411764-240.941177h-120.470588a60.235294 60.235294 0 0 0-60.235294 60.235294v120.470588a60.235294 60.235294 0 0 0 60.235294 60.235295h120.470588a60.235294 60.235294 0 0 0 60.235295-60.235295v-120.470588a60.235294 60.235294 0 0 0-60.235295-60.235294z m-77.884235 354.123294l-67.523765 67.46353H391.529412a60.054588 60.054588 0 0 0-42.586353 17.709176l-85.172706 85.172706a60.175059 60.175059 0 1 0 85.172706 85.172706l67.523765-67.523765H632.470588a60.054588 60.054588 0 0 0 42.586353-17.648941l85.172706-85.172706a60.175059 60.175059 0 1 0-85.172706-85.172706z" fill="" p-id="13697"></path></svg>

+ 1 - 0
src/assets/appEveryData.svg

@@ -0,0 +1 @@
+<svg viewBox="64 64 896 896" focusable="false" data-icon="fund-view" width="1em" height="1em" fill="currentColor" aria-hidden="true"><path d="M986.834824 535.009882a60.717176 60.717176 0 0 0-87.04 0l-68.969412 70.174118H610.183529a60.837647 60.837647 0 0 0-43.429647 18.311529l-86.979764 88.545883a63.307294 63.307294 0 0 0 0 88.485647 60.717176 60.717176 0 0 0 86.979764 0l68.969412-70.174118h220.581647c15.721412 0 31.503059-6.083765 43.489883-18.311529l87.04-88.545883a63.307294 63.307294 0 0 0 0-88.545882z m-223.472942-319.006117h-120.470588a60.235294 60.235294 0 0 0-60.235294 60.235294v120.470588a60.235294 60.235294 0 0 0 60.235294 60.235294h120.470588a60.235294 60.235294 0 0 0 60.235294-60.235294v-120.470588a60.235294 60.235294 0 0 0-60.235294-60.235294z m-481.882353 361.411764a60.235294 60.235294 0 0 0-60.235294 60.235295v120.470588a60.235294 60.235294 0 0 0 60.235294 60.235294h60.235295a60.235294 60.235294 0 0 0 60.235294-60.235294v-120.470588a60.235294 60.235294 0 0 0-60.235294-60.235295h-60.235295z m180.705883-180.705882v-120.470588a60.235294 60.235294 0 0 0-60.235294-60.235294h-120.470589a60.235294 60.235294 0 0 0-60.235294 60.235294v120.470588a60.235294 60.235294 0 0 0 60.235294 60.235294h120.470589a60.235294 60.235294 0 0 0 60.235294-60.235294z m-301.176471 421.647059v-602.352941a60.235294 60.235294 0 0 1 60.235294-60.235294h602.172236a60.235294 60.235294 0 0 1 60.235294 60.235294v181.850353l120.470588-1.264942V95.533176a60.235294 60.235294 0 0 0-60.235294-60.235294H100.713412a60.235294 60.235294 0 0 0-60.235294 60.235294v843.294118a60.235294 60.235294 0 0 0 60.235294 60.235294h361.110588l1.566118-120.470588H221.244235a60.235294 60.235294 0 0 1-60.235294-60.235294z" fill="" p-id="13554"></path></svg>

+ 1 - 0
src/assets/retained.svg

@@ -0,0 +1 @@
+<svg viewBox="64 64 896 896" focusable="false" data-icon="fund-view" width="1em" height="1em" fill="currentColor" aria-hidden="true"><path d="M0 0h1024v1024H0z" fill="#FFFFFF" p-id="21415"></path><path d="M744.727273 325.818182a46.545455 46.545455 0 0 1 46.545454 46.545454v372.363637a46.545455 46.545455 0 0 1-46.545454 46.545454H279.272727a46.545455 46.545455 0 0 1-46.545454-46.545454V372.363636a46.545455 46.545455 0 0 1 46.545454-46.545454h465.454546z m-465.454546-46.545455a93.090909 93.090909 0 0 0-93.090909 93.090909v372.363637a93.090909 93.090909 0 0 0 93.090909 93.090909h465.454546a93.090909 93.090909 0 0 0 93.090909-93.090909V372.363636a93.090909 93.090909 0 0 0-93.090909-93.090909H279.272727z" fill="" p-id="21416"></path><path d="M349.090909 395.636364a23.272727 23.272727 0 0 1-23.272727-23.272728v-139.636363a23.272727 23.272727 0 1 1 46.545454 0v139.636363a23.272727 23.272727 0 0 1-23.272727 23.272728zM674.909091 395.636364a23.272727 23.272727 0 0 1-23.272727-23.272728v-139.636363a23.272727 23.272727 0 1 1 46.545454 0v139.636363a23.272727 23.272727 0 0 1-23.272727 23.272728z" fill="" p-id="21417"></path><path d="M666.903273 480.744727a23.272727 23.272727 0 0 0-32.837818 2.327273l-108.683637 125.184-36.002909-84.712727a46.545455 46.545455 0 0 0-78.033454-12.241455l-79.848728 92.253091a23.272727 23.272727 0 1 0 35.188364 30.440727l79.825454-92.229818 36.026182 84.689455a46.545455 46.545455 0 0 0 77.963637 12.311272l108.706909-125.207272a23.272727 23.272727 0 0 0-2.327273-32.814546z" fill="#E83743" p-id="21418"></path></svg>

+ 1 - 0
src/assets/tikTok.svg

@@ -0,0 +1 @@
+<svg viewBox="64 64 896 896" focusable="false" data-icon="fund-view" width="1em" height="1em" fill="currentColor" aria-hidden="true"><path d="M862.51879883 439.40783691c-69.21386719 0-136.53259278-22.49450684-191.90368653-64.1052246v290.28625488c0 148.23303223-114.20288086 268.28613281-255.10253905 268.28613281S160.41003418 813.82189942 160.41003418 665.58886719c0-148.23303223 114.20288086-268.28613281 255.10253907-268.28613281 14.08996583 0 27.76794434 1.23596192 41.116333 3.54309081v153.75366211c-12.77160645-5.02624512-26.3671875-7.58056641-40.04516602-7.5805664-62.8692627 0-113.87329102 53.55834961-113.87329101 119.72351074 0 66.08276367 51.00402833 119.72351075 113.87329101 119.72351075 62.78686523 0 113.79089356-53.64074708 113.79089356-119.72351075V90.125H672.67504883c0 110.82458497 85.446167 200.63781739 190.83251953 200.63781739v148.56262206l-0.98876953 0.08239747" fill="" p-id="4301"></path></svg>

File diff suppressed because it is too large
+ 0 - 0
src/assets/trend.svg


+ 144 - 140
src/components/RightContent/index.tsx

@@ -5,8 +5,6 @@ import Avatar from './AvatarDropdown';
 import styles from './index.less';
 import { exitFullScreen, requestFullScreen, isFull } from '@/utils/fullScreen'
 import { BellOutlined } from '@ant-design/icons';
-import { ReactComponent as GameSvg } from '@/assets/game.svg'
-import { ReactComponent as BiSvg } from '@/assets/bi.svg'
 import { getAppListApi } from '@/services/iaaData';
 import { useAjax } from '@/Hook/useAjax';
 
@@ -15,153 +13,159 @@ export type SiderTheme = 'light' | 'dark';
 
 const GlobalHeaderRight: React.FC<{}> = () => {
 
-  const [left, setLeft] = useState(0)
-  const { initialState, setInitialState } = useModel('@@initialState');
-  const { state: { versionsOpen }, dispatch, getversions } = useModel('useOperating.useWxGroupList')
-  if (!initialState || !initialState.settings) {
-    return null;
-  }
-  const [appList, setApplist] = useState<{ label: string, value: string, third: string; }[]>([])
-  const getAppList = useAjax(() => getAppListApi())
-  const [productTypeList, setProductTypeList] = useState<{ label: string, value: string }[]>([])
-  const [productType, setProductType] = useState<string>()
-
-  useEffect(() => {
-    if (location.hash.includes('/iaaData')) {
-      getAppList.run().then(res => {
-        if (res?.data) {
-          const thirdSet = new Set();
-          let data: { label: string, value: string, third: string; }[] = res.data.map((item: { second: any; first: string; third: string; }) => {
-            thirdSet.add(item.third)
-            return { label: item.second, value: item.first + '||' + item.third, third: item.third }
-          })
-          setProductTypeList([{ label: '游戏业务', value: 'PRODUCT_TYPE_GAME' }, { label: '小说业务', value: 'PRODUCT_TYPE_NOVEL' }, { label: '短剧业务', value: 'PRODUCT_TYPE_PLAYLET' }].filter(item => [...thirdSet].includes(item.value)))
-          let app = initialState?.iaaApp
-          let iaaApp = data.some(item => item.value === app) ? app : data?.[0].value || undefined as any
-          setProductType(iaaApp ? iaaApp.split('||')?.[1] : undefined)
-          setInitialState({ ...initialState, iaaApp })
-          setApplist(data)
-        }
-      })
+    const [left, setLeft] = useState(0)
+    const { initialState, setInitialState } = useModel('@@initialState');
+    const { state: { versionsOpen }, dispatch, getversions } = useModel('useOperating.useWxGroupList')
+    if (!initialState || !initialState.settings) {
+        return null;
     }
-  }, [location.hash])
+    const [appList, setApplist] = useState<{ label: string, value: string, productType: string; mediaPlatform: string; icon?: string }[]>([])
+    const getAppList = useAjax(() => getAppListApi())
+    const [productTypeList, setProductTypeList] = useState<{ label: string, value: string }[]>([])
+    const [mediaPlatformList, setMediaPlatformList] = useState<{ label: string, value: string }[]>([])
+    const [productType, setProductType] = useState<string>()
 
-  useEffect(() => {
-    let nav: any = document.querySelector('.top-nav-menu')
-    let navLi: any = document.querySelectorAll('.top-nav-menu > li')
-    if (nav && navLi) {
-      let l = nav.offsetLeft
-      let lw = 0
-      for (const iterator of navLi) {
-        lw += iterator.offsetWidth
-      }
-      setLeft(l + lw - 50)
-    }
-  }, [])
+    useEffect(() => {
+        if (location.hash.includes('/iaaData')) {
+            getAppList.run().then(res => {
+                if (res?.data) {
+                    const productTypeSet = new Set();
+                    const mediaPlatformSet = new Set();
+                    const data: { label: string, value: string, productType: string; mediaPlatform: string; icon?: string }[] = res.data.map((item: { name: string; id: number; productType: string; mediaPlatform: string; icon?: string }) => {
+                        productTypeSet.add(item.productType)
+                        mediaPlatformSet.add(item.mediaPlatform)
+                        return { label: item.name, value: item.id + '||' + item.productType, productType: item.productType, mediaPlatform: item.mediaPlatform, icons: item.icon }
+                    })
+                    setProductTypeList([{ label: '游戏业务', value: 'PRODUCT_TYPE_GAME' }, { label: '小说业务', value: 'PRODUCT_TYPE_NOVEL' }, { label: '短剧业务', value: 'PRODUCT_TYPE_PLAYLET' }].filter(item => [...productTypeSet].includes(item.value)))
+                    setMediaPlatformList([{ label: '腾讯', value: 'MEDIA_PLATFORM_TENCENT' }, { label: '头条', value: 'MEDIA_PLATFORM_OCENAENGINE' }].filter(item => [...mediaPlatformSet].includes(item.value)))
+                    
+                    const app = initialState?.iaaApp
+                    const iaaApp = data.some(item => item.value === app) ? app : data?.[0].value || undefined as any
+                    const productType = iaaApp ? iaaApp.split('||')?.[1] : undefined
+                    const newAppList = data.filter(item => item.productType === productType)
+                    const mediaPlatform = newAppList?.[0].mediaPlatform
+                    setProductType(productType)
+                    setInitialState({ ...initialState, iaaApp, mediaPlatform })
+                    setApplist(data)
+                }
+            })
+        }
+    }, [location.hash])
 
-  const { navTheme, layout } = initialState.settings;
-  let className = styles.right;
 
-  if ((navTheme === 'dark' && layout === 'top') || layout === 'mix') {
-    className = `${styles.right}  ${styles.dark}`;
-  }
-  let handleFullScreen = () => {
-    if (isFull()) {
-      exitFullScreen()
-    } else {
-      requestFullScreen()
-    }
-  }
-  //消息弹窗更新
-  const inform = useCallback(() => {
-    let bdVersions = localStorage.getItem('versions') //本地
-    getversions.run().then((res) => {
-      let fwqVersions = ''//服务器版本
-      let content: any = ''//版本更新内容
-      if (res) {
-        fwqVersions = res?.configValue
-        content = <div dangerouslySetInnerHTML={{ __html: res?.remark?.replace(/\n/ig, '<br/>') }}></div >
-        if (fwqVersions && bdVersions !== fwqVersions) {//不一样
-          //执行逻辑
-          Modal.confirm({
-            title: '版本更新!',
-            content,
-            keyboard: false,
-            cancelText: '稍后我自己刷新页面',
-            okText: '现在就去刷新页面',
-            onOk: () => {
-              localStorage.setItem('versions', fwqVersions)//重新设置服务器版本
-              location?.reload()
-            },
-            onCancel: () => {
-              dispatch({ type: 'versionsOpen', params: { versionsOpen: true } })
+    useEffect(() => {
+        let nav: any = document.querySelector('.top-nav-menu')
+        let navLi: any = document.querySelectorAll('.top-nav-menu > li')
+        if (nav && navLi) {
+            let l = nav.offsetLeft
+            let lw = 0
+            for (const iterator of navLi) {
+                lw += iterator.offsetWidth
             }
-          })
-          console.log('不一样')
+            setLeft(l + lw - 50)
         }
-      }
-    })
-  }, [])
+    }, [])
 
-  const open = () => {
-    let token = localStorage.getItem('Admin-Token')
-    window.open(`http://gg.84game.cn/#/login?token=${token}`)
-    return
-  }
+    const { navTheme, layout } = initialState.settings;
+    let className = styles.right;
 
-  return (
-    <div style={{ display: 'flex', justifyContent: 'space-between' }}>
+    if ((navTheme === 'dark' && layout === 'top') || layout === 'mix') {
+        className = `${styles.right}  ${styles.dark}`;
+    }
+    let handleFullScreen = () => {
+        if (isFull()) {
+            exitFullScreen()
+        } else {
+            requestFullScreen()
+        }
+    }
+    //消息弹窗更新
+    const inform = useCallback(() => {
+        let bdVersions = localStorage.getItem('versions') //本地
+        getversions.run().then((res) => {
+            let fwqVersions = ''//服务器版本
+            let content: any = ''//版本更新内容
+            if (res) {
+                fwqVersions = res?.configValue
+                content = <div dangerouslySetInnerHTML={{ __html: res?.remark?.replace(/\n/ig, '<br/>') }}></div >
+                if (fwqVersions && bdVersions !== fwqVersions) {//不一样
+                    //执行逻辑
+                    Modal.confirm({
+                        title: '版本更新!',
+                        content,
+                        keyboard: false,
+                        cancelText: '稍后我自己刷新页面',
+                        okText: '现在就去刷新页面',
+                        onOk: () => {
+                            localStorage.setItem('versions', fwqVersions)//重新设置服务器版本
+                            location?.reload()
+                        },
+                        onCancel: () => {
+                            dispatch({ type: 'versionsOpen', params: { versionsOpen: true } })
+                        }
+                    })
+                    console.log('不一样')
+                }
+            }
+        })
+    }, [])
 
-      {/* <div style={{ left: left }} className={styles.extraSys}>
-        <Space onClick={open}>
-          <span role="img" aria-label="fund-view" className="anticon anticon-fund-view"><GameSvg /></span>
-          <span style={{ color: 'rgba(255, 255, 255, 0.65)' }}>游戏SDK</span>
-        </Space>
-        <Space onClick={() => window.open(`https://bi.aliyun.com/product/view.htm?module=dashboard&productId=396f5cf7-9d50-4dde-9aaa-eb20e2590518&menuId=74f4c115-db5a-457c-b25b-94bdafc172fe`)}>
-          <span role="img" aria-label="fund-view" className="anticon anticon-fund-view"><BiSvg /></span>
-          <span style={{ color: 'rgba(255, 255, 255, 0.65)' }}>BI商业分析</span>
-        </Space>
-      </div> */}
-      {location.hash.includes('/iaaData') && <div style={{ left: left + 10, position: 'absolute' }}>
-        <Select
-          showSearch
-          style={{ width: 100 }}
-          placeholder={'请选择业务类型'}
-          filterOption={(input, option) =>
-            (option?.label as any)?.toLowerCase().indexOf(input.toLowerCase()) >= 0
-          }
-          onChange={(type) => {
-            let newApplist = appList.filter(item => item.third === type)
-            setInitialState({ ...initialState, iaaApp: newApplist?.[0]?.value })
-            setProductType(type)
-          }}
-          value={productType}
-          options={productTypeList}
-        />
-        <Select
-          showSearch
-          style={{ width: 150, marginLeft: 10 }}
-          placeholder={'请选择应用'}
-          filterOption={(input, option) =>
-            (option?.label as any)?.toLowerCase().indexOf(input.toLowerCase()) >= 0
-          }
-          value={initialState?.iaaApp}
-          onChange={(e) => setInitialState({ ...initialState, iaaApp: e })}
-          loading={getAppList.loading}
-          options={appList.filter(item => item.third === productType)}
-        />
-      </div>}
+    return (
+        <div style={{ display: 'flex', justifyContent: 'space-between' }}>
+            {location.hash.includes('/iaaData') && <div style={{ left: left + 10, position: 'absolute' }}>
+                <Select
+                    showSearch
+                    style={{ width: 100 }}
+                    placeholder={'请选择业务类型'}
+                    filterOption={(input, option) =>
+                        (option?.label as any)?.toLowerCase().indexOf(input.toLowerCase()) >= 0
+                    }
+                    onChange={(type) => {
+                        let newApplist = appList.filter(item => item.productType === type)
+                        setInitialState({ ...initialState, iaaApp: newApplist?.[0]?.value, mediaPlatform: newApplist?.[0]?.mediaPlatform })
+                        setProductType(type)
+                    }}
+                    value={productType}
+                    options={productTypeList}
+                />
+                <Select
+                    showSearch
+                    style={{ width: 100, marginLeft: 10 }}
+                    placeholder={'请选择媒体'}
+                    filterOption={(input, option) =>
+                        (option?.label as any)?.toLowerCase().indexOf(input.toLowerCase()) >= 0
+                    }
+                    onChange={(type) => {
+                        let newApplist = appList.filter(item => item.productType === productType).filter(item => item.mediaPlatform === type)
+                        setInitialState({ ...initialState, iaaApp: newApplist?.[0]?.value, mediaPlatform: type })
+                    }}
+                    value={initialState?.mediaPlatform}
+                    options={mediaPlatformList}
+                />
+                <Select
+                    showSearch
+                    style={{ width: 150, marginLeft: 10 }}
+                    placeholder={'请选择应用'}
+                    filterOption={(input, option) =>
+                        (option?.label as any)?.toLowerCase().indexOf(input.toLowerCase()) >= 0
+                    }
+                    value={initialState?.iaaApp}
+                    onChange={(e) => setInitialState({ ...initialState, iaaApp: e })}
+                    loading={getAppList.loading}
+                    options={appList.filter(item => item.productType === productType).filter(item => item.mediaPlatform === initialState?.mediaPlatform)}
+                />
+            </div>}
 
-      <Space className={className}>
-        {versionsOpen && <div onClick={versionsOpen && inform}>
-          <Badge count={versionsOpen && 1} size='small' offset={[2, 0]}>
-            <span style={{ cursor: 'pointer' }} ><BellOutlined /></span>
-          </Badge>
-        </div>}
-        <Avatar />
-        <Tag color="#87d068" onClick={handleFullScreen}>全屏模式</Tag>
-      </Space>
-    </div>
-  );
+            <Space className={className}>
+                {versionsOpen && <div onClick={versionsOpen && inform}>
+                    <Badge count={versionsOpen && 1} size='small' offset={[2, 0]}>
+                        <span style={{ cursor: 'pointer' }} ><BellOutlined /></span>
+                    </Badge>
+                </div>}
+                <Avatar />
+                <Tag color="#87d068" onClick={handleFullScreen}>全屏模式</Tag>
+            </Space>
+        </div>
+    );
 };
 export default GlobalHeaderRight;

+ 1 - 1
src/pages/iaaData/tencentIaa/adList/index.tsx

@@ -153,7 +153,7 @@ const TencentIaaAd: React.FC = () => {
             page={getGDTList?.data?.data?.current || 1}
             pageSize={getGDTList?.data?.data?.size || 20}
             total={getGDTList?.data?.data?.total || 0}
-            dataSource={getGDTList?.data?.data?.records?.map((item: any, index: number) => ({ ...item, id: Number(queryForm.pageNum.toString() + (index + '')) }))}
+            dataSource={getGDTList?.data?.data?.records?.map((item: any) => ({ ...item, id: item.promotionId }))}
             onChange={(pagination: any, _: any, sortData: any) => {
                 let { current, pageSize } = pagination
                 let newQueryForm = JSON.parse(JSON.stringify(queryForm))

+ 12 - 0
src/pages/iaaData/tencentIaa/appCashRetained/index.less

@@ -0,0 +1,12 @@
+.dbox{
+    display: flex;
+    flex-flow: column;
+    align-items: center;
+    font-size: 12px;
+    // padding: 10px;
+    >span{
+        display: flex;
+        justify-content: left;
+        width: 100%;
+    }
+}

+ 100 - 0
src/pages/iaaData/tencentIaa/appCashRetained/index.tsx

@@ -0,0 +1,100 @@
+import { getAppTrendListApi, GetAppTrendListProps, getAppTrendTotalApi } from "@/services/iaaData";
+import React, { useEffect, useState } from "react"
+import { useModel } from "umi";
+import moment from "moment";
+import { useAjax } from "@/Hook/useAjax";
+import TablePro from "@/components/TablePro";
+import QueryForm from "@/components/QueryForm";
+import columns12 from "./tableConfig";
+
+/**
+ * 应用变现留存
+ * @returns 
+ */
+const AppCashTrend: React.FC = () => {
+
+    /****************************************/
+    const { initialState } = useModel('@@initialState');
+    const [queryForm, setQueryForm] = useState<GetAppTrendListProps>({
+        pageNum: 1,
+        pageSize: 30,
+        costDayBegin: moment().subtract(1, 'days').format('YYYY-MM-DD'),
+        costDayEnd: moment().subtract(1, 'days').format('YYYY-MM-DD'),
+    })
+    const [totalData, setTotalData] = useState<any[]>([])
+
+    const getAppTrendList = useAjax((params) => getAppTrendListApi(params))
+    const getAppTrendTotal = useAjax((params) => getAppTrendTotalApi(params))
+    /****************************************/
+
+    useEffect(() => {
+        if (initialState?.iaaApp) {
+            const [appId, productType] = initialState.iaaApp.split('||')
+            getAppTrendList.run({ ...queryForm, appId, productType })
+            getAppTrendTotal.run({ ...queryForm, appId, productType }).then((res: { data: { id: number; dt: string, costDayBegin: string } }) => {
+                if (res?.data) {
+                    let data = res?.data
+                    data.id = 1
+                    data.costDayBegin = queryForm?.costDayBegin || moment().format('YYYY-MM-DD')
+                    data.dt = '总计'
+                    setTotalData([data])
+                } else {
+                    setTotalData([{ id: 1, dt: '总计' }])
+                }
+            })
+        }
+
+    }, [queryForm, initialState?.iaaApp])
+
+    return <div>
+        <TablePro
+            leftChild={<QueryForm
+                initialValues={{ day1: [moment().subtract(1, 'days'), moment().subtract(1, 'days')] }}
+                day1={{ placeholder: ['消耗日期开始', '消耗日期结束'] }}
+                onChange={(data: any) => {
+                    console.log(data)
+                    const { day1, ...params } = data
+                    let newQueryForm = JSON.parse(JSON.stringify(queryForm))
+                    newQueryForm.pageNum = 1
+                    if (day1 && day1?.length === 2) {
+                        newQueryForm['costDayBegin'] = moment(day1[0]).format('YYYY-MM-DD')
+                        newQueryForm['costDayEnd'] = moment(day1[1]).format('YYYY-MM-DD')
+                    } else {
+                        delete newQueryForm['costDayBegin']
+                        delete newQueryForm['costDayEnd']
+                    }
+                    setQueryForm({ ...newQueryForm, ...params })
+                }}
+            />}
+            isZj
+            totalData={totalData}
+            config={columns12()}
+            configName={'应用变现留存'}
+            fixed={{ left: 4, right: 0 }}
+            scroll={{ x: 1000, y: 620 }}
+            title='应用变现留存'
+            loading={getAppTrendList.loading}
+            ajax={getAppTrendList}
+            page={getAppTrendList?.data?.data?.current || 1}
+            pageSize={getAppTrendList?.data?.data?.size || 20}
+            total={getAppTrendList?.data?.data?.total || 0}
+            dataSource={getAppTrendList?.data?.data?.records?.map((item: any, index: number) => ({ ...item, id: Number(queryForm.pageNum.toString() + (index + '')) }))}
+            onChange={(pagination: any, _: any, sortData: any) => {
+                let { current, pageSize } = pagination
+                let newQueryForm = JSON.parse(JSON.stringify(queryForm))
+                if (sortData && sortData?.order) {
+                    newQueryForm['sortAsc'] = sortData?.order === 'ascend' ? true : false
+                    newQueryForm['sortFiled'] = sortData?.field
+                } else {
+                    delete newQueryForm['sortAsc']
+                    delete newQueryForm['sortFiled']
+                }
+                newQueryForm.pageNum = current || newQueryForm.pageNum
+                newQueryForm.pageSize = pageSize || newQueryForm.pageSize
+                setQueryForm({ ...newQueryForm })
+            }}
+        />
+    </div>
+}
+
+export default AppCashTrend

+ 155 - 0
src/pages/iaaData/tencentIaa/appCashRetained/tableConfig.tsx

@@ -0,0 +1,155 @@
+import WidthEllipsis from "@/components/widthEllipsis"
+import { Statistic } from "antd"
+import React from "react"
+import { PRODUCT_TYPE_ENUM } from "../../const"
+import { formatSecondsToTime } from "@/utils/utils"
+import style from './index.less'
+import moment from "moment"
+
+function columns12(): { label: string, fieldSHow?: { label: string, saveField: string, defaultValue: any[], data: any[] }, data: any[] }[] {
+
+    const defaultIndex = 26
+    const trend = [1, 2, 3, 4, 5, 6, 7, 14, 30, 45, 60, 75, 90].map((index, count) => {
+
+        const dataIndex = `d${index}`
+        return {
+            title: `D${index}`, dataIndex, label: '基本信息', default: defaultIndex + count, width: 120,
+            render: (_: any, b: any) => {
+                if (moment().subtract(1, 'days') >= moment(b.dt === '总计' ? b.costDayBegin : b.dt).add(index - 1, 'days')) {
+                    const data = b?.[dataIndex]?.split('/')
+                    return <div className={style.dbox} style={{ height: 45.84 }}>
+                        <span style={{ color: '#d81b60', fontWeight: 600 }}>人数:<span><Statistic value={data?.[0] || 0} precision={2} /></span></span>
+                        <span style={{ color: '#0f538a', fontWeight: 600 }}>留存率:<span><Statistic value={data?.[1] ? data?.[1] * 100 : 0} precision={2} valueStyle={!data?.[1] ? {} : data?.[1] >= 0.5 ? { color: 'red' } : { color: '#0f990f' }} suffix="%" /></span></span>
+                    </div>
+                }
+                return <div style={{ height: 45.84, width: '100%', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>--</div>
+            }
+        }
+
+    })
+
+    return [
+        {
+            label: '基本信息',
+            data: [
+                {
+                    title: '日期', dataIndex: 'dt', label: '基本信息', align: 'center', width: 80, default: 1,
+                    render: (a: string) => (<WidthEllipsis value={a} />)
+                },
+                {
+                    title: '应用', dataIndex: 'appName', label: '基本信息', align: 'center', width: 120, default: 2,
+                    render: (a: string) => (<WidthEllipsis value={a} />)
+                },
+                {
+                    title: '应用ID', dataIndex: 'appId', label: '基本信息', align: 'center', width: 80,
+                    render: (a: string) => (<WidthEllipsis value={a} />)
+                },
+                {
+                    title: '小程序名称', dataIndex: 'mpName', label: '基本信息', align: 'center', width: 85, default: 3,
+                    render: (a: string) => (<WidthEllipsis value={a} />)
+                },
+                {
+                    title: '小程序ID', dataIndex: 'mpId', label: '基本信息', align: 'center', width: 80,
+                    render: (a: string) => (<WidthEllipsis value={a} />)
+                },
+                {
+                    title: '业务类型', dataIndex: 'productType', label: '基本信息', align: 'center', width: 80, default: 4,
+                    render: (a: string) => (<WidthEllipsis value={PRODUCT_TYPE_ENUM[a as keyof typeof PRODUCT_TYPE_ENUM]} />)
+                },
+                // {
+                //     title: '变现广告位', dataIndex: 'realizationAdUnit', label: '基本信息', align: 'center', width: 90, default: 5,
+                //     render: (a: string) => <WidthEllipsis value={a} />
+                // },
+                {
+                    title: '总消耗', dataIndex: 'totalCost', label: '基本信息', align: 'right', width: 95, default: 6, sorter: true,
+                    render: (a: number) => <Statistic value={a || 0} style={{ fontWeight: 'bold' }} precision={2} />
+                },
+                {
+                    title: '消耗', dataIndex: 'cost', label: '基本信息', align: 'right', width: 85, default: 7, sorter: true,
+                    render: (a: number) => <Statistic value={a || 0} style={{ fontWeight: 'bold' }} precision={2} />
+                },
+                {
+                    title: '赔付金', dataIndex: 'payout', label: '基本信息', align: 'right', width: 80, default: 8, sorter: true,
+                    render: (a: number) => <Statistic value={a || 0} precision={2} />
+                },
+                {
+                    title: '注册人数', dataIndex: 'userRegCnt', label: '基本信息', align: 'center', width: 80, default: 9, sorter: true,
+                    render: (a: number) => <Statistic value={a || 0} />
+                },
+                {
+                    title: '注册成本', dataIndex: 'regPaid', label: '基本信息', align: 'center', width: 80, default: 10, sorter: true,
+                    render: (a: number) => <Statistic value={a || 0} precision={2} />
+                },
+                {
+                    title: '注册用户留存人数', dataIndex: 'userRetentionCnt', label: '基本信息', align: 'center', width: 80, default: 11, sorter: true,
+                    render: (a: number) => <Statistic value={a || 0} />
+                },
+                {
+                    title: '注册用户留存率', dataIndex: 'userRetentionRatio', label: '基本信息', align: 'center', width: 80, default: 12, sorter: true,
+                    render: (a: number) => <Statistic value={a ? a * 100 : 0} precision={2} valueStyle={!a ? {} : a >= 0.5 ? { color: 'red' } : { color: '#0f990f' }} suffix="%" />
+                },
+                {
+                    title: '广告变现人数', dataIndex: 'appAdPayingUsers', label: '基本信息', align: 'center', width: 75, default: 13, sorter: true,
+                    render: (a: number) => <Statistic value={a || 0} />
+                },
+                {
+                    title: '人均在线时长', dataIndex: 'avgDuration', label: '基本信息', align: 'center', width: 110, default: 14, sorter: true,
+                    render: (a: number) => {
+                        return formatSecondsToTime(a ? Math.round(a) : 0)
+                    }
+                },
+                {
+                    title: '人均启动次数', dataIndex: 'avgStartTimes', label: '基本信息', align: 'center', width: 70, default: 15, sorter: true,
+                    render: (a: number) => <Statistic value={a || 0} />
+                },
+                {
+                    title: '人均观看广告次数', dataIndex: 'avgAdViewTimes', label: '基本信息', align: 'center', width: 80, default: 16, sorter: true,
+                    render: (a: number) => <Statistic value={a || 0} />
+                },
+                {
+                    title: '广告变现UV', dataIndex: 'adMonetizeUv', label: '基本信息', align: 'center', width: 75, default: 17, sorter: true,
+                    render: (a: number) => <Statistic value={a || 0} precision={2} />
+                },
+                {
+                    title: 'ecpm', dataIndex: 'ecpm', label: '基本信息', align: 'center', width: 80, default: 18, sorter: true,
+                    render: (a: number) => <Statistic value={a || 0} precision={2} />
+                },
+                {
+                    title: '广告渗透率', dataIndex: 'adPermeability', label: '基本信息', align: 'center', width: 75, default: 19, sorter: true,
+                    render: (a: number) => <Statistic value={a ? a * 100 : 0} precision={2} valueStyle={!a ? {} : a >= 0.5 ? { color: 'red' } : { color: '#0f990f' }} suffix="%" />
+                },
+                {
+                    title: '广告ARPU', dataIndex: 'adArpu', label: '基本信息', align: 'center', width: 80, default: 20, sorter: true,
+                    render: (a: number) => <Statistic value={a || 0} precision={2} />
+                },
+                {
+                    title: '广告曝光量', tips: '总收入/ecpm*1000', dataIndex: 'adViewCount', label: '基本信息', align: 'center', width: 80, default: 21, sorter: true,
+                    render: (a: number) => <Statistic value={a || 0} />
+                },
+                {
+                    title: '总收入', dataIndex: 'income', label: '基本信息', align: 'right', width: 80, default: 22, sorter: true,
+                    render: (a: number) => <Statistic value={a || 0} precision={2} />
+                },
+                {
+                    title: '总回收', dataIndex: 'incomeRoi', label: '基本信息', align: 'right', width: 80, default: 23, sorter: true,
+                    render: (a: number) => <Statistic value={a ? a * 100 : 0} precision={2} valueStyle={!a ? {} : a >= 0.5 ? { color: 'red' } : { color: '#0f990f' }} suffix="%" />
+                },
+                {
+                    title: '广告变现收入', dataIndex: 'adIncome', label: '基本信息', align: 'center', width: 75, default: 24, sorter: true,
+                    render: (a: number) => <Statistic value={a || 0} precision={2} />
+                },
+                {
+                    title: '分享成功人数', dataIndex: 'shareUv', label: '基本信息', align: 'center', width: 75, default: 25, sorter: true,
+                    render: (a: number) => <Statistic value={a || 0} />
+                },
+                {
+                    title: '分享后活跃人数', dataIndex: 'shareClkUv', label: '基本信息', align: 'center', width: 80, default: 26, sorter: true,
+                    render: (a: number) => <Statistic value={a || 0} />
+                },
+                ...trend
+            ]
+        }
+    ]
+}
+
+export default columns12

+ 5 - 4
src/pages/iaaData/tencentIaa/appCashTrend/index.tsx

@@ -18,8 +18,8 @@ const AppCashTrend: React.FC = () => {
     const [queryForm, setQueryForm] = useState<GetAppTrendListProps>({
         pageNum: 1,
         pageSize: 30,
-        costDayBegin: moment().format('YYYY-MM-DD'),
-        costDayEnd: moment().format('YYYY-MM-DD'),
+        costDayBegin: moment().subtract(1, 'days').format('YYYY-MM-DD'),
+        costDayEnd: moment().subtract(1, 'days').format('YYYY-MM-DD'),
     })
     const [totalData, setTotalData] = useState<any[]>([])
 
@@ -31,10 +31,11 @@ const AppCashTrend: React.FC = () => {
         if (initialState?.iaaApp) {
             const [appId, productType] = initialState.iaaApp.split('||')
             getAppTrendList.run({ ...queryForm, appId, productType })
-            getAppTrendTotal.run({ ...queryForm, appId, productType }).then((res: { data: { id: number; dt: string } }) => {
+            getAppTrendTotal.run({ ...queryForm, appId, productType }).then((res: { data: { id: number; dt: string, costDayBegin: string } }) => {
                 if (res?.data) {
                     let data = res?.data
                     data.id = 1
+                    data.costDayBegin = queryForm?.costDayBegin || moment().format('YYYY-MM-DD')
                     data.dt = '总计'
                     setTotalData([data])
                 } else {
@@ -48,7 +49,7 @@ const AppCashTrend: React.FC = () => {
     return <div>
         <TablePro
             leftChild={<QueryForm
-                initialValues={{ day1: [moment(), moment()] }}
+                initialValues={{ day1: [moment().subtract(1, 'days'), moment().subtract(1, 'days')] }}
                 day1={{ placeholder: ['消耗日期开始', '消耗日期结束'] }}
                 onChange={(data: any) => {
                     console.log(data)

+ 65 - 52
src/pages/iaaData/tencentIaa/appCashTrend/tableConfig.tsx

@@ -4,64 +4,77 @@ import React from "react"
 import { PRODUCT_TYPE_ENUM } from "../../const"
 import { formatSecondsToTime } from "@/utils/utils"
 import style from './index.less'
-
+import moment from "moment"
 
 function columns12(): { label: string, fieldSHow?: { label: string, saveField: string, defaultValue: any[], data: any[] }, data: any[] }[] {
 
     const defaultIndex = 26
     const trend = [1, 2, 3, 4, 5, 6, 7, 14, 30, 45, 60, 75, 90].map((index, count) => {
 
-        const dataIndex = `d${index + 1}`
+        const dataIndex = `d${index}`
         return {
-            title: `D${index}`, dataIndex, label: '基本信息', default: defaultIndex + count,
-            children: [
-                {
-                    title: '留存',
-                    dataIndex: `trend${index}`,
-                    key: `trend${index}`,
-                    width: 100,
-                    align: 'center',
-                    className: count % 2 ? "redColorClass" : undefined,
-                    render: (_: any, b: any) => {
-                        const data = b?.[dataIndex]?.split('/')
-                        return <div className={style.dbox}>
-                            <span style={{ color: '#d81b60', fontWeight: 600 }}>人数:<span><Statistic value={data?.[0] || 0} /></span></span>
-                            <span style={{ color: '#0f538a', fontWeight: 600 }}>率:<span><Statistic value={data?.[1] ? data?.[1] * 100 : 0} precision={2} valueStyle={!data?.[1] ? {} : data?.[1] >= 0.5 ? { color: 'red' } : { color: '#0f990f' }} suffix="%" /></span></span>
-                        </div>
-                    },
-                },
-                {
-                    title: '收入',
-                    dataIndex: `income${index}`,
-                    key: `income${index}`,
-                    width: 110,
-                    align: 'center',
-                    className: count % 2 ? "redColorClass" : undefined,
-                    render: (_: any, b: any) => {
-                        const data = b?.[dataIndex]?.split('/')
-                        return <div className={style.dbox}>
-                            <span style={{ color: '#d81b60', fontWeight: 600 }}>新增:<span><Statistic value={data?.[2] || 0} precision={2} /></span></span>
-                            <span style={{ color: '#0f538a', fontWeight: 600 }}>累计:<span><Statistic value={data?.[3] || 0} precision={2} /></span></span>
-                        </div>
-                    }
-                },
-                {
-                    title: 'ROI',
-                    dataIndex: `roi${index}`,
-                    key: `roi${index}`,
-                    width: 100,
-                    align: 'center',
-                    className: count % 2 ? "redColorClass" : undefined,
-                    render: (_: any, b: any) => {
-                        const data = b?.[dataIndex]?.split('/')
-                        return <div className={style.dbox}>
-                            <span style={{ color: 'rgb(12,130,16)', fontWeight: 600 }}>增:<span><Statistic value={data?.[5] ? data?.[5] * 100 : 0} precision={2} valueStyle={!data?.[5] ? {} : data?.[5] >= 0.5 ? { color: 'red' } : { color: '#0f990f' }} suffix="%" /></span></span>
-                            <span style={{ color: '#ff5722', fontWeight: 600 }}>回:<span><Statistic value={data?.[6] ? data?.[6] * 100 : 0} precision={2} valueStyle={!data?.[6] ? {} : data?.[6] >= 0.5 ? { color: 'red' } : { color: '#0f990f' }} suffix="%" /></span></span>
-                            <span style={{ color: '#d81b60', fontWeight: 600 }}>倍:<span><Statistic value={data?.[7] || 0} precision={2} /></span></span>
-                        </div>
-                    }
-                },
-            ]
+            title: `D${index}`, dataIndex, label: '基本信息', default: defaultIndex + count, width: 110,
+            render: (_: any, b: any) => {
+                if (moment().subtract(1, 'days') >= moment(b.dt === '总计' ? b.costDayBegin : b.dt).add(index - 1, 'days')) {
+                    const data = b?.[dataIndex]?.split('/')
+                    return <div className={style.dbox} style={{ height: 102 }}>
+                        <span style={{ color: '#d81b60', fontWeight: 600 }}>新增:<span><Statistic value={data?.[2] || 0} precision={2} /></span></span>
+                        <span style={{ color: '#0f538a', fontWeight: 600 }}>累计:<span><Statistic value={data?.[3] || 0} precision={2} /></span></span>
+                        <span style={{ color: 'rgb(12,130,16)', fontWeight: 600 }}>增:<span><Statistic value={data?.[4] ? data?.[4] * 100 : 0} precision={2} valueStyle={!data?.[4] ? {} : data?.[4] >= 0.5 ? { color: 'red' } : { color: '#0f990f' }} suffix="%" /></span></span>
+                        <span style={{ color: '#ff5722', fontWeight: 600 }}>回:<span><Statistic value={data?.[5] ? data?.[5] * 100 : 0} precision={2} valueStyle={!data?.[5] ? {} : data?.[5] >= 0.5 ? { color: 'red' } : { color: '#0f990f' }} suffix="%" /></span></span>
+                        <span style={{ color: '#d81b60', fontWeight: 600 }}>倍:<span><Statistic value={data?.[6] || 0} precision={2} /></span></span>
+                    </div>
+                }
+                return <div style={{ height: 102, width: '100%', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>--</div>
+            }
+            // children: [
+            //     {
+            //         title: '留存',
+            //         dataIndex: `trend${index}`,
+            //         key: `trend${index}`,
+            //         width: 100,
+            //         align: 'center',
+            //         className: count % 2 ? "redColorClass" : undefined,
+            //         render: (_: any, b: any) => {
+            //             const data = b?.[dataIndex]?.split('/')
+            //             return <div className={style.dbox}>
+            //                 <span style={{ color: '#d81b60', fontWeight: 600 }}>人数:<span><Statistic value={data?.[0] || 0} /></span></span>
+            //                 <span style={{ color: '#0f538a', fontWeight: 600 }}>率:<span><Statistic value={data?.[1] ? data?.[1] * 100 : 0} precision={2} valueStyle={!data?.[1] ? {} : data?.[1] >= 0.5 ? { color: 'red' } : { color: '#0f990f' }} suffix="%" /></span></span>
+            //             </div>
+            //         },
+            //     },
+            //     {
+            //         title: '收入',
+            //         dataIndex: `income${index}`,
+            //         key: `income${index}`,
+            //         width: 110,
+            //         align: 'center',
+            //         className: count % 2 ? "redColorClass" : undefined,
+            //         render: (_: any, b: any) => {
+            //             const data = b?.[dataIndex]?.split('/')
+            //             return <div className={style.dbox}>
+            //                 <span style={{ color: '#d81b60', fontWeight: 600 }}>新增:<span><Statistic value={data?.[2] || 0} precision={2} /></span></span>
+            //                 <span style={{ color: '#0f538a', fontWeight: 600 }}>累计:<span><Statistic value={data?.[3] || 0} precision={2} /></span></span>
+            //             </div>
+            //         }
+            //     },
+            //     {
+            //         title: 'ROI',
+            //         dataIndex: `roi${index}`,
+            //         key: `roi${index}`,
+            //         width: 100,
+            //         align: 'center',
+            //         className: count % 2 ? "redColorClass" : undefined,
+            //         render: (_: any, b: any) => {
+            //             const data = b?.[dataIndex]?.split('/')
+            //             return <div className={style.dbox}>
+            //                 <span style={{ color: 'rgb(12,130,16)', fontWeight: 600 }}>增:<span><Statistic value={data?.[5] ? data?.[5] * 100 : 0} precision={2} valueStyle={!data?.[5] ? {} : data?.[5] >= 0.5 ? { color: 'red' } : { color: '#0f990f' }} suffix="%" /></span></span>
+            //                 <span style={{ color: '#ff5722', fontWeight: 600 }}>回:<span><Statistic value={data?.[6] ? data?.[6] * 100 : 0} precision={2} valueStyle={!data?.[6] ? {} : data?.[6] >= 0.5 ? { color: 'red' } : { color: '#0f990f' }} suffix="%" /></span></span>
+            //                 <span style={{ color: '#d81b60', fontWeight: 600 }}>倍:<span><Statistic value={data?.[7] || 0} precision={2} /></span></span>
+            //             </div>
+            //         }
+            //     },
+            // ]
         }
 
     })
@@ -170,7 +183,7 @@ function columns12(): { label: string, fieldSHow?: { label: string, saveField: s
                 },
                 {
                     title: '总回收', dataIndex: 'incomeRoi', label: '基本信息', align: 'right', width: 80, default: 23, sorter: true,
-                    render: (a: number) => <Statistic value={a || 0} precision={2} />
+                    render: (a: number) => <Statistic value={a ? a * 100 : 0} precision={2} valueStyle={!a ? {} : a >= 0.5 ? { color: 'red' } : { color: '#0f990f' }} suffix="%" />
                 },
                 {
                     title: '广告变现收入', dataIndex: 'adIncome', label: '基本信息', align: 'center', width: 75, default: 24, sorter: true,

+ 83 - 5
src/pages/iaaSystem/manage/useApp/tableConfig.tsx

@@ -1,34 +1,112 @@
+import { UserOutlined } from "@ant-design/icons";
 import { ProColumns } from "@ant-design/pro-table";
+import { Avatar, Space } from "antd";
 import React from "react";
 
 
 const tableConfig = () => {
 
     const columns: ProColumns<any>[] = [
+        {
+            title: 'ID',
+            dataIndex: 'id',
+            key: 'id',
+            search: false,
+            align: 'center',
+            width: 50
+        },
         {
             title: '应用',
             dataIndex: 'name',
             key: 'name',
-            search: false
+            search: false,
+            width: 250,
+            render(_, entity) {
+                return <Space>
+                    <Avatar shape="square" size="small" icon={<UserOutlined />} src={entity?.icon} />
+                    <span>{entity?.name}</span>
+                </Space>
+            },
         },
         {
             title: 'CP',
             key: 'cpName',
             dataIndex: 'cpName',
-            search: false
+            search: false,
+            align: 'center',
+            width: 80
+        },
+        {
+            title: 'CPID',
+            key: 'cpId',
+            dataIndex: 'cpId',
+            search: false,
+            align: 'center',
+            width: 60
+        },
+        {
+            title: '应用标识',
+            key: 'appKey',
+            dataIndex: 'appKey',
+            search: false,
+            width: 150
         },
         {
             title: 'MP名称',
             key: 'mpName',
             dataIndex: 'mpName',
-            search: false
+            search: false,
+            width: 150
         },
         {
             title: 'MPID',
             key: 'mpId',
             dataIndex: 'mpId',
-            search: false
-        }
+            search: false,
+            width: 160
+        },
+        {
+            title: '应用类型',
+            key: 'appType',
+            dataIndex: 'appType',
+            search: false,
+            width: 90,
+            align: 'center',
+            valueEnum: {
+                APP_TYPE_TENCENT_GAME: { text: '微信小游戏' },
+                APP_TYPE_OCENAENGINE_GAME: { text: '抖音小游戏' },
+                APP_TYPE_TENCENT_MP: { text: '微信小程序' },
+                APP_TYPE_OCENAENGINE_MP: { text: '抖音小程序' },
+                APP_TYPE_ANDROID_APP: { text: 'Android应用APP' },
+                APP_TYPE_IOS_APP: { text: 'IOS应用APP' },
+                APP_TYPE_WEB_H5: { text: '网页H5应用' }
+            }
+        },
+        {
+            title: '业务类型',
+            key: 'productType',
+            dataIndex: 'productType',
+            search: false,
+            width: 90,
+            align: 'center',
+            valueEnum: {
+                PRODUCT_TYPE_GAME: { text: '游戏业务' },
+                PRODUCT_TYPE_NOVEL: { text: '小说业务' },
+                PRODUCT_TYPE_PLAYLET: { text: '短剧业务' }
+            }
+        },
+        {
+            title: '媒体平台',
+            key: 'mediaPlatform',
+            dataIndex: 'mediaPlatform',
+            search: false,
+            width: 90,
+            align: 'center',
+            valueEnum: {
+                MEDIA_PLATFORM_TENCENT: { text: '腾讯' },
+                MEDIA_PLATFORM_OCENAENGINE: { text: '头条' },
+            }
+        },
     ];
     return columns
 }

+ 1 - 1
src/services/iaaData/index.ts

@@ -36,7 +36,7 @@ export async function getPutUserListApi() {
  * @returns 
  */
 export async function getAppListApi() {
-    return request(wapi + `/condition/appList`, {
+    return request(wapi + `/condition/get/app/list`, {
         method: 'POST'
     });
 }

Some files were not shown because too many files changed in this diff