shenwu 8 månader sedan
förälder
incheckning
76da225eb7

+ 8 - 1
config/routes.tsx

@@ -101,7 +101,14 @@ const newMenu = [
         component: './MiniApp/Consume',
       }
     ],
-  }
+  },
+  {
+    name: 'miniApp.adBack',
+    icon: 'icon-guanggaohuichuan-wx',
+    path: '/miniApp/adBack',
+    access: "isShow",
+    component: './MiniApp/AdBack',
+  },
 ]
 export default [
   {

+ 12 - 0
src/Hook/useApi.tsx

@@ -0,0 +1,12 @@
+import { longBookInfoList, shortBookInfoList } from "@/services/miniApp/bookManage"
+
+function useApi(appCategory: 2 | 1) {
+    //判断是长篇
+    let isLong = appCategory === 1
+    return {
+        /**获取小说列表*/
+        getBookPageList: isLong ? longBookInfoList : shortBookInfoList,
+    }
+
+}
+export default useApi

+ 13 - 10
src/components/bookSelect/index.tsx

@@ -1,4 +1,5 @@
 import { useAjax } from "@/Hook/useAjax"
+import useApi from "@/Hook/useApi"
 import { longBookInfoList, shortBookInfoList } from "@/services/miniApp/bookManage"
 import { useModel } from "@umijs/max"
 import { Button, Divider, Pagination, Select, Space, Tag } from "antd"
@@ -7,17 +8,19 @@ import { useCallback, useEffect, useMemo, useRef, useState } from "react"
 const BookSelect = (props: { value?: any, onChange?: (value: any) => void }) => {
     let { value, onChange } = props
     let { initialState } = useModel("@@initialState")
+    let {state} = useModel("appPageConifg")
     let publicData = useMemo(() => {
         return {
             appId: initialState?.selectApp?.id || "",
             distributorId: initialState?.currentUser?.distributorId,
-            appType: initialState?.selectApp?.appType || ""
+            appType: initialState?.selectApp?.appType || "",
+            workDirection:state.tabs 
         }
-    }, [initialState?.selectApp, initialState?.currentUser?.distributorId])
-    let getShortList = useAjax((params) => shortBookInfoList(params))//获取书列表
-    let getLongtList = useAjax((params) => longBookInfoList(params))//获取书列表
+    }, [initialState?.selectApp, initialState?.currentUser?.distributorId,state.index])
+    let apiobj = useApi(initialState?.selectApp?.appCategory || 1)
+    let getList = useAjax((params) => apiobj.getBookPageList(params))
     let api = useMemo(() => {
-        return initialState?.selectApp?.appCategory === 1 ? getLongtList : getShortList
+        return getList
     }, [initialState?.selectApp])
     let timeOut = useRef<any>()
     let [params, setParmas] = useState({
@@ -38,7 +41,7 @@ const BookSelect = (props: { value?: any, onChange?: (value: any) => void }) =>
     useEffect(() => {
         if (params.bookName) {
             api.run({ ...params, ...publicData }).then(res => {
-                if (res.data.total > 0) {
+                if (res?.data?.total > 0) {
                     setData({ records: res.data.records, total: res.data.total })
                 } else {
                     setData({ records: [], total: 0 })
@@ -54,10 +57,10 @@ const BookSelect = (props: { value?: any, onChange?: (value: any) => void }) =>
             onSearch={(value) => {
                 debounce(() => { setParmas({ ...params, bookName: value }) }, 500)
             }}
-            onChange={(value) => {
-                onChange?.(value)
+            onChange={(value,option) => {
+                onChange?.(option?.longBookInfo)
             }}
-            value={value}
+            value={value?.id || value}
             dropdownRender={(menu) => {
                 return <>
                     {menu}
@@ -76,7 +79,7 @@ const BookSelect = (props: { value?: any, onChange?: (value: any) => void }) =>
                     />
                 </>
             }}
-            options={data?.records?.map(item => ({ label: item.longBookInfo.bookName, value: item.bookId }))}
+            options={data?.records?.map(item => ({ label: item.longBookInfo.bookName, value: item.bookId,...item }))}
         />
     </div>
 

+ 1 - 1
src/global.tsx

@@ -5,7 +5,7 @@ import { createFromIconfontCN } from '@ant-design/icons';
 import nocover from '../public/nocover.jpg'
 const { pwa } = defaultSettings;
 const isHttps = document.location.protocol === 'https:';
-export let scriptUrl = "//at.alicdn.com/t/c/font_4644725_v9fyft7xju9.js"//线上icon
+export let scriptUrl = "//at.alicdn.com/t/c/font_4644725_kdi2stcj9z.js"//线上icon
 // 自定义icon组件用于线上icon
 export const MyIcon = createFromIconfontCN({
   scriptUrl// 在 iconfont.cn 上生成

+ 2 - 0
src/locales/zh-CN/menu.ts

@@ -63,4 +63,6 @@ export default {
   "menu.miniApp.dataManage.payLog":"充值记录",
   "menu.miniApp.dataManage.readLog":"阅读记录",
   "menu.miniApp.dataManage.consume":"书币消耗记录",
+  // 授权
+  "menu.miniApp.adBack":"广告回传",
 };

+ 30 - 11
src/models/appPageConifg.tsx

@@ -1,17 +1,34 @@
 import { useReducer } from "react"
 
-type Component = {
-    appComponentId: number,//组件ID
-    componentType:string,//
-    pageUrl:string,
-    configs:any[],//组件配置
+export type Config = {
+    bannerType?: number,//banner类型; 0:小说 1:页面路径 banners组件使用
+    activityPagePath?: string,//banner类型 1的时候使用页面路径
+    bannerImage?: string,//banner图片
+    bookId?: string,//小说ID
+    categoryId?: string,//分类ID
+    bookIds?: any[],//用于分类自义定书籍的参数
 }
 type State = {
     tabs: 0 | 1,//男生女生选项
+    isWorkDirection: boolean,//当前页面是否存在男频女频
     compAc: string,//当前选中的组件,切换tabs请0
-    manList: Component[]//男生配置
-    womanList: Component[]//女生配置
-    index:number,//每次操作修改数据都递增,为了检测到数据变动
+    index: number,//每次操作修改数据都递增,为了检测到数据变动
+    activePage: string,//当前选中的页面
+    pageConfigList: {
+        pageUrl: string,//组件所在页面地址
+        workDirectionListDTOS: {
+            workDirection?: 0 | 1,//作品方向;0-男频 1-女频
+            componentConfigList: {
+                appComponentId: number | string,//组件ID
+                componentType: string,//组件类型
+                showRightButton?: boolean,//是否展示左侧按钮
+                componentName?: string,//组件名称
+                remark?: string,//备注
+                configs?: Config[],//组件内的配置
+            }[]
+        }[]
+    }[],
+    
 }
 type Action = {
     params?: any,
@@ -29,11 +46,13 @@ export function reducer(state: State, action: Action) {
 export default (): { state: State, dispatch: React.Dispatch<Action> } => {
     const [state, dispatch] = useReducer(reducer, {
         tabs: 0,
+        isWorkDirection: false,
         compAc: "",
-        manList: [],
-        womanList: [],
-        index:0
+        index: 0,
+        activePage: "",
+        pageConfigList: []
     })
+    console.log("state", state)
     return {
         state,
         dispatch

+ 99 - 0
src/pages/MiniApp/AdBack/index.tsx

@@ -0,0 +1,99 @@
+import { useAjax } from "@/Hook/useAjax"
+import { tencentAdAccountDoAuth, tencentAdAccountToAuth } from "@/services/miniApp/adBack"
+import { PageContainer, ProCard, ProForm, ProFormRadio, ProFormSelect, ProFormText } from "@ant-design/pro-components"
+import { Button, Divider, Space } from "antd"
+import { useEffect, useRef, useState } from "react"
+
+function Auth() {
+    let [key, setKey] = useState<any>()
+    let [isEdit, setIsEdit] = useState(false)
+    let formRef = useRef()
+    let TencentAdAccountToAuth = useAjax((params) => tencentAdAccountToAuth(params))//获取授权地址
+    let TencentAdAccountDoAuth = useAjax((params) => tencentAdAccountDoAuth(params))//开始授权
+    // 获取广告回传列表
+    useEffect(() => {
+
+    }, [key])
+    // 授权
+    const auth = () => {
+        console.log("授权")
+    }
+    return <PageContainer
+        tabList={[
+            {
+                tab: '基本信息',
+                key: 'base',
+            },
+            {
+                tab: '详细信息',
+                key: 'info',
+            },
+            {
+                tab: '详细信息',
+                key: 'info1',
+            }
+        ]}
+        tabProps={{
+            type: 'card',
+            hideAdd: true,
+            onChange: (e) => setKey(e),
+        }}
+    >
+        <ProCard direction="column" ghost gutter={8} >
+            <ProCard
+                bordered
+                title="归因设置"
+                actions={
+                    <Space style={{ margin: 20 }}> <Button type="primary" onClick={auth}>授权</Button></Space>
+                }
+            >
+                <ProForm
+                    readonly={true}
+                    submitter={false}
+                    colProps={{ span: 2 }}
+                    labelCol={{ span: 1 }}
+                    layout="horizontal"
+                >
+                    <ProFormText label={"归因方式"} formItemProps={{ style: { marginBottom: 10 } }} />
+                    <ProFormText label={"数据源类型"} formItemProps={{ style: { marginBottom: 10 } }} />
+                    <ProFormText label={"数据源ID"} formItemProps={{ style: { marginBottom: 10 } }} />
+                    <ProFormText label={"已授权账号ID"} formItemProps={{ style: { marginBottom: 10 } }} />
+                </ProForm>
+
+            </ProCard>
+            <ProCard
+                bordered
+                title="回传设置"
+                tooltip="回传“下单”“付费”两个行为事件,直投小程序链路额外支持“注册”(纯新+染色回流用户进入小程序)事件回传。"
+                actions={<Space style={{ margin: 20 }}>
+                    {
+                        !isEdit ? <>
+                            <Button type="primary" onClick={() => { setIsEdit(true) }}>编辑</Button>
+                            <Button>取消回传</Button>
+                        </> : <>
+                            <Button type="primary" onClick={() => { setIsEdit(true) }}>保存</Button>
+                            <Button onClick={() => { setIsEdit(false) }}>取消</Button>
+                        </>
+                    }
+                </Space>}
+            >
+                <ProForm
+                    readonly={!isEdit}
+                    formRef={formRef}
+                    submitter={false}
+                    colProps={{ span: 2 }}
+                    labelCol={{ span: 1 }}
+                    layout="horizontal"
+                >
+                    <ProFormText label={"投放场景"} formItemProps={{ style: { marginBottom: 10 } }} />
+                    <ProFormRadio.Group label={"回传口径"} formItemProps={{ style: { marginBottom: 10 } }} />
+                    <ProFormSelect label={"回传用户"} formItemProps={{ style: { marginBottom: 10 } }} />
+                    <ProFormRadio.Group label={"部分回传"} formItemProps={{ style: { marginBottom: 10 } }} />
+                    <ProFormRadio.Group label={"ROI 投放"} formItemProps={{ style: { marginBottom: 10 } }} />
+                </ProForm>
+            </ProCard>
+        </ProCard>
+    </PageContainer>
+}
+
+export default Auth

+ 123 - 21
src/pages/MiniApp/CompConfig/DrawerBox/compConfig.tsx

@@ -1,21 +1,128 @@
 import { BetaSchemaForm, ProFormInstance } from "@ant-design/pro-components";
 import { useEffect, useMemo, useRef } from "react";
-import { bannersConfig } from "./compFormConfig";
+import { bannersConfig, hotBooksConfig, hotCategoryConfig } from "./compFormConfig";
 import { useModel } from "@umijs/max";
+import { Button, Popconfirm } from "antd";
+import { useAjax } from "@/Hook/useAjax";
+import { queryCategoryList } from "@/services/global";
+import { Config } from "@/models/appPageConifg";
 
-export function BannersConfig() {
+type Props = {
+    pageList?: any[]
+    compName: "banners" | "hot_books" | "hot_category",
+}
+export function CompConfig(props: Props) {
+    let { pageList = [], compName } = props
     let { state, dispatch } = useModel('appPageConifg')
+    let QueryCategoryList = useAjax((params) => queryCategoryList(params))
+
+    // 获取分类列表
+    useEffect(() => {
+        if (compName === 'hot_category') {
+            QueryCategoryList.run({ workDirection: state.tabs })
+        }
+    }, [state.tabs, compName])
+    // 获取对应from设置
+    let columns = useMemo(() => {
+        switch (compName) {
+            case 'banners':
+                return bannersConfig(pageList);
+            case "hot_books":
+                return hotBooksConfig();
+            case "hot_category":
+                return hotCategoryConfig(QueryCategoryList?.data?.data);
+        }
+    }, [compName, pageList, QueryCategoryList?.data?.data])
+
+    // 获取当前页面配置表
     const list = useMemo(() => {
-        return state.tabs === 0 ? state.manList : state.womanList
+        let pageConfig = state.pageConfigList.find(page => page.pageUrl === state.activePage)
+        let list: {
+            appComponentId: number | string;
+            componentType: string;
+            showRightButton?: boolean;
+            componentName?: string;
+            remark?: string;
+            configs?: Config[];
+        }[] = []
+        if (state.isWorkDirection) {
+            let thePage = pageConfig?.workDirectionListDTOS?.find(page => page.workDirection == state.tabs)
+            list = thePage?.componentConfigList || []
+        } else {
+            list = pageConfig?.workDirectionListDTOS?.[0].componentConfigList || []
+        }
+        return list
     }, [state])
     const formRef = useRef<ProFormInstance>();
     // 提交表单
     const submit = async (values: any) => {
     }
+    // 初始化内容
     useEffect(() => {
-        let thatConfig = list.find(item => item.componentType === "banners")
+        let thatConfig = list.find(item => item.componentType === compName)
         formRef.current?.setFieldsValue(thatConfig)
     }, [list])
+    // 值变化
+    const handelValues = (values: any, isDel?: boolean) => {
+        // 处理分类 书籍 需要的完整数据
+        if(values){
+            for (let config of values?.configs) {
+                if (config?.bookId) {
+                    config.bookInfo = config.bookId
+                    config.bookId = config.bookInfo.id
+                }
+                if (config?.categoryId) {
+                    config.categoryInfo = QueryCategoryList?.data?.data?.find((item: { id: any; })=>item.id === config.categoryId) 
+                    config.categoryId = config.categoryInfo.id
+                }
+                if (config?.bookIds) {
+                    config.bookInfos = config.bookIds
+                    config.bookIds = config.bookInfos.map((item: { id: any; }) => item.id)
+                }
+            }
+        }
+        // 找到当前的页面
+        let pageConfig = state.pageConfigList.find(page => page.pageUrl === state.activePage)
+        //找到当前选中的组件    
+        let thatConfig = list.find(item => item.componentType === compName)
+        // 修改组件的内容
+        if (thatConfig) {
+            thatConfig.configs = values ? values.configs : []
+            if(values?.componentName){
+                thatConfig.componentName = values?.componentName
+                thatConfig.showRightButton = values?.showRightButton
+            }
+        }
+        // 判断当前页面是否存在男女频,获取对应的页面配置列表
+        if (state.isWorkDirection) {
+            let thePage = pageConfig?.workDirectionListDTOS?.find(page => page.workDirection == state.tabs)
+            if (thePage) {
+                // 删除的判断
+                if (isDel) {
+                    thePage.componentConfigList = list?.filter(item => item.componentType !== compName)
+                } else {
+                    thePage.componentConfigList = list
+                }
+            }
+        } else {
+            if (pageConfig) {
+                if (isDel) {
+                    pageConfig.workDirectionListDTOS[0].componentConfigList = list?.filter(item => item.componentType !== compName)
+                } else {
+                    pageConfig.workDirectionListDTOS[0].componentConfigList = list
+                }
+            }
+            pageConfig && (pageConfig.workDirectionListDTOS[0].componentConfigList = list)
+        }
+        // 修改保存数据到状态管理
+        dispatch({
+            type: 'setAll', params: {
+                pageConfigList: state.pageConfigList,
+                index: state.index + 1,
+                compAc: isDel ? "" : state.compAc
+            }
+        })
+    }
     return <BetaSchemaForm<any>
         formRef={formRef}
         layoutType={"Form"}
@@ -24,25 +131,20 @@ export function BannersConfig() {
             span: 12,
         }}
         grid={true}
+        submitter={{
+            render: (props, doms) => {
+                return [<Popconfirm key={compName + "del"} title="确定要删除此组件?" onConfirm={() => {
+                    handelValues(null, true)
+                }}><Button danger>删除</Button></Popconfirm>, ...doms];
+            },
+        }}
         onFinish={submit}
-        columns={bannersConfig()}
+        onReset={() => {
+            handelValues(null)
+        }}
+        columns={columns}
         onValuesChange={(changedValues: any, values: any) => {
-            console.log("valuonValuesChangees", values, list)
-            let thatConfig = list.find(item => item.componentType === "banners")
-            if (thatConfig) {
-                thatConfig.configs = values.configs
-            }
-            console.log(1111)
-            dispatch({
-                type: 'setAll', params: state.tabs === 0 ? {
-                    manList: list,
-                    index:state.index+1
-                } : {
-                    womanList: list,
-                    index:state.index+1
-                }
-            })
-            console.log(2222,state)
+            handelValues(values)
         }}
     />
 }

+ 179 - 23
src/pages/MiniApp/CompConfig/DrawerBox/compFormConfig.tsx

@@ -4,7 +4,8 @@ import { ProFormColumnsType } from "@ant-design/pro-components";
 import styles from './index.less'
 import { Select, Tooltip } from "antd";
 import BookSelect from "@/components/bookSelect";
-export function bannersConfig(): ProFormColumnsType<any>[] {
+
+export function bannersConfig(pageList: any[]): ProFormColumnsType<any>[] {
     return [
         {
             valueType: 'formList',
@@ -19,8 +20,8 @@ export function bannersConfig(): ProFormColumnsType<any>[] {
                 alwaysShowItemLabel: true,//全部展示title
                 actionRender: (field: any, action: any, defaultActionDom: any, count: any) => {//自定义按钮
                     return [...defaultActionDom,
-                    field.name < count - 1 && <Tooltip title="向下移动"><ArrowDownOutlined className={styles.upDownBtn} onClick={() => { action.move(field.name + 1, field.name) }} /></Tooltip>,
-                    field.name > 0 && <Tooltip title="向上移动"><ArrowUpOutlined className={styles.upDownBtn} onClick={() => { action.move(field.name - 1, field.name) }} /></Tooltip>]
+                    field.name < count - 1 && <Tooltip title="向下移动" key={`move-down-${field.name}`}><ArrowDownOutlined className={styles.upDownBtn} onClick={() => { action.move(field.name + 1, field.name) }} /></Tooltip>,
+                    field.name > 0 && <Tooltip title="向上移动" key={`move-up-${field.name}`}><ArrowUpOutlined className={styles.upDownBtn} onClick={() => { action.move(field.name - 1, field.name) }} /></Tooltip>]
                 }
             },
             columns: [
@@ -30,25 +31,6 @@ export function bannersConfig(): ProFormColumnsType<any>[] {
                         span: 24
                     },
                     columns: [
-                        {
-                            title: 'banner名称',
-                            dataIndex: 'templateName',
-                            colProps: {
-                                span: 24
-                            },
-                            fieldProps: {
-                                placeholder: '请输入banner名称'
-                            },
-                            formItemProps: {
-                                style: { marginBottom: 10 },
-                                rules: [
-                                    {
-                                        required: true,
-                                        message: '此项为必填项',
-                                    },
-                                ],
-                            }
-                        },
                         {
                             title: 'banner类型',
                             dataIndex: 'bannerType',
@@ -113,7 +95,8 @@ export function bannersConfig(): ProFormColumnsType<any>[] {
                                                     message: '此项为必填项',
                                                 },
                                             ],
-                                        }
+                                        },
+                                        valueEnum: new Map(pageList?.map(({ pagePath, pageName }) => [pagePath, pageName])),
                                     }
                                 ]
                             }
@@ -159,3 +142,176 @@ export function bannersConfig(): ProFormColumnsType<any>[] {
 
     ]
 }
+
+export function hotBooksConfig(): ProFormColumnsType<any>[] {
+    return [
+        {
+            title: '标题名称',
+            dataIndex: 'componentName',
+            colProps: {
+                span: 12
+            },
+            fieldProps: {
+                allowClear: true,
+                placeholder: '请输入名称'
+            },
+            formItemProps: {
+                style: { marginBottom: 10 },
+            }
+        },
+        {
+            title: '显示右侧按钮',
+            dataIndex: 'showRightButton',
+            valueType: "radio",
+            valueEnum: new Map([{ value: true, text: "是" }, { value: false, text: "否" }].map(item => [item.value, item.text])),
+            formItemProps: {
+                style: { marginBottom: 10 },
+            },
+            colProps: {
+                span: 12
+            },
+        },
+        {
+            valueType: 'divider',
+        },
+        {
+            valueType: 'formList',
+            dataIndex: "configs",
+            colProps: {
+                span: 24
+            },
+            fieldProps: {
+                max: 5,
+                min: 5,
+                creatorButtonProps: {
+                    creatorButtonText: "添加一本书",
+                },
+                alwaysShowItemLabel: true,//全部展示title
+                actionRender: (field: any, action: any, defaultActionDom: any, count: any) => {//自定义按钮
+                    return [...defaultActionDom,
+                    field.name < count - 1 && <Tooltip title="向下移动" key={`move-down-${field.name}`}><ArrowDownOutlined className={styles.upDownBtn} onClick={() => { action.move(field.name + 1, field.name) }} /></Tooltip>,
+                    field.name > 0 && <Tooltip title="向上移动" key={`move-up-${field.name}`}><ArrowUpOutlined className={styles.upDownBtn} onClick={() => { action.move(field.name - 1, field.name) }} /></Tooltip>]
+                }
+            },
+            columns: [
+                {
+                    valueType: 'group',
+                    colProps: {
+                        span: 24
+                    },
+                    columns: [
+                        {
+                            dataIndex: "bookId",
+                            title: '小说',
+                            colProps: {
+                                span: 12
+                            },
+                            formItemProps: {
+                                style: { marginBottom: 10 },
+                                rules: [
+                                    {
+                                        required: true,
+                                        message: '此项为必填项',
+                                    },
+                                ],
+                            },
+                            renderFormItem(schema, config, form, action) {
+                                return <BookSelect />
+                            },
+                        },
+                        {
+                            valueType: 'divider',
+                        }
+                    ]
+                }
+            ]
+        },
+
+    ]
+}
+export function hotCategoryConfig(tags: any[]): ProFormColumnsType<any>[] {
+    return [
+        {
+            title: '标题名称',
+            dataIndex: 'componentName',
+            colProps: {
+                span: 12
+            },
+            fieldProps: {
+                allowClear: true,
+                placeholder: '请输入名称'
+            },
+            formItemProps: {
+                style: { marginBottom: 10 },
+            }
+        },
+        {
+            title: '显示右侧按钮',
+            dataIndex: 'showRightButton',
+            valueType: "radio",
+            valueEnum: new Map([{ value: true, text: "是" }, { value: false, text: "否" }].map(item => [item.value, item.text])),
+            formItemProps: {
+                style: { marginBottom: 10 },
+            },
+            colProps: {
+                span: 12
+            },
+        },
+        {
+            valueType: 'divider',
+        },
+        {
+            valueType: 'formList',
+            dataIndex: "configs",
+            colProps: {
+                span: 24
+            },
+            fieldProps: {
+                creatorButtonProps: {
+                    creatorButtonText: "添加一个标签",
+                },
+                alwaysShowItemLabel: true,//全部展示title
+                actionRender: (field: any, action: any, defaultActionDom: any, count: any) => {//自定义按钮
+                    return [...defaultActionDom,
+                    field.name < count - 1 && <Tooltip title="向下移动" key={`move-down-${field.name}`}><ArrowDownOutlined className={styles.upDownBtn} onClick={() => { action.move(field.name + 1, field.name) }} /></Tooltip>,
+                    field.name > 0 && <Tooltip title="向上移动" key={`move-up-${field.name}`}><ArrowUpOutlined className={styles.upDownBtn} onClick={() => { action.move(field.name - 1, field.name) }} /></Tooltip>]
+                }
+            },
+            columns: [
+                {
+                    valueType: 'group',
+                    colProps: {
+                        span: 24
+                    },
+                    columns: [
+                        {
+                            dataIndex: "categoryId",
+                            title: '标签',
+                            valueType:'select',
+                            colProps: {
+                                span: 12
+                            },
+                            formItemProps: {
+                                style: { marginBottom: 10 },
+                                rules: [
+                                    {
+                                        required: true,
+                                        message: '此项为必填项',
+                                    },
+                                ],
+                            },
+                            fieldProps: {
+                                showSearch: true
+                            },
+                            valueEnum: new Map(tags?.map(item => [item.id, item.name]))
+                        },
+                        {
+                            valueType: 'divider',
+                        }
+                    ]
+                }
+            ]
+        },
+
+    ]
+}

+ 95 - 23
src/pages/MiniApp/CompConfig/DrawerBox/content.tsx

@@ -4,6 +4,9 @@ import React, { useState, useImperativeHandle, forwardRef, useRef, useMemo } fro
 import styles from './index.less'
 import { Banners } from "../components/banners";
 import { useModel } from "@umijs/max";
+import { HotBooks } from "../components/hot_books";
+import { HotCategory } from "../components/hot_category";
+import { Config } from "@/models/appPageConifg";
 
 // 使用 forwardRef 以支持传递 ref
 const DragItem = () => {
@@ -11,32 +14,87 @@ const DragItem = () => {
     const [isHovering, setIsHovering] = useState(false);
     const dropRef = useRef(null);
     const list = useMemo(() => {
-        return state.tabs === 0 ? state.manList : state.womanList
+        let pageConfig = state.pageConfigList.find(page => page.pageUrl === state.activePage)
+        let list: {
+            appComponentId: number | string;
+            componentType: string;
+            showRightButton?: boolean;
+            componentName?: string;
+            remark?: string;
+            configs?: Config[];
+        }[] = []
+        if (state.isWorkDirection) {
+            let thePage = pageConfig?.workDirectionListDTOS?.find(page => page.workDirection == state.tabs)
+            list = thePage?.componentConfigList || []
+        } else {
+            list = pageConfig?.workDirectionListDTOS?.[0].componentConfigList || []
+        }
+        return list
     }, [state])
     useDrop(dropRef, {
         // 接收到组件拖拽到手机内容内,添加进入数据
         onDom: (content: string, e) => {
-            console.log(11111)
-            let arr = content?.split('_')
+            let arr = content?.split('-')
             let appComponentId = arr[0]
             let componentType = arr[1]
-            let pageUrl = arr[2]
-            let newConfig = { appComponentId, componentType, pageUrl, configs: [] }
-            let { tabs, manList, womanList } = state
+            let newConfig: {
+                appComponentId: number | string,//组件ID
+                componentType: string,//组件类型
+                showRightButton?: boolean,//是否展示左侧按钮
+                componentName?: string,//组件名称
+                remark?: string,//备注
+                configs?: Config[],//组件内的配置
+            } = { appComponentId, componentType, configs: [] }
             switch (componentType) {
-                case "banners":
-                    dispatch({
-                        type: 'setAll', params: tabs === 0 ? {
-                            manList: [...state.manList, newConfig]
-                        } : {
-                            womanList: [...state.womanList, newConfig]
+                case 'hot_books':
+                    newConfig.configs = [
+                        {}, {}, {}, {}, {}
+                    ]
+                    newConfig.componentName = "今日热书"
+                    newConfig.showRightButton = true
+                    break;
+                case "hot_category":
+                    newConfig.configs = []
+                    newConfig.componentName = "热门分类"
+                    newConfig.showRightButton = true
+                    break;
+            }
+            let { tabs, pageConfigList, activePage, isWorkDirection } = state
+            let pageConfig = pageConfigList.find(page => page.pageUrl === activePage)
+            // 首次添加页面基础数据
+            if (!pageConfig) {
+                pageConfigList.push({
+                    pageUrl: activePage,
+                    workDirectionListDTOS: isWorkDirection ? [
+                        {
+                            workDirection: 0,
+                            componentConfigList: []
+                        },
+                        {
+                            workDirection: 1,
+                            componentConfigList: []
+                        },
+                    ] : [
+                        {
+                            componentConfigList: []
                         }
-                    })
-                    break
-                default:
-                    break
+                    ]
+                })
+                pageConfig = pageConfigList.find(page => page.pageUrl === activePage)
             }
-            console.log(`custom: ${content} dropped`);
+            // 存在男女频页面
+            if (isWorkDirection && pageConfig?.workDirectionListDTOS) {
+                for (let page of pageConfig?.workDirectionListDTOS) {
+                    if (page.workDirection == tabs) {
+                        page.componentConfigList = [...page.componentConfigList, newConfig]
+                    }
+                }
+            } else if (pageConfig?.workDirectionListDTOS) {// 不存在男女频页面
+                pageConfig.workDirectionListDTOS[0].componentConfigList = [...pageConfig.workDirectionListDTOS[0].componentConfigList, newConfig]
+            }
+            dispatch({
+                type: 'setAll', params: { pageConfigList, index: state.index + 1 }
+            })
         },
         onDragOver: (e) => {
             // console.log("拖拽中",e)
@@ -47,9 +105,20 @@ const DragItem = () => {
     return <div ref={dropRef} style={{ minHeight: '100%' }} >
         {
             list?.map(item => {
-                return <div key={item.appComponentId} className={`${styles.comp} ${state.compAc === item.componentType ? styles.ac : ""}`} onClick={() => { dispatch({ type: "setAll", params: { compAc: item.componentType } }) }}>
-                    <Banners data={item.configs} />
-                </div>
+                return <React.Fragment key={item.appComponentId}>
+                    <div
+                        className={`${styles.comp}  ${state.compAc === item.componentType ? styles.ac : ""}`}
+                        onClick={() => { dispatch({ type: "setAll", params: { compAc: item.componentType } }) }}
+                    >
+                        {/* banners */}
+                        {item.componentType === 'banners' && <Banners data={item.configs || []} />}
+                        {/* 热门书籍*/}
+                        {item.componentType === "hot_books" && <HotBooks data={item} />}
+                        {/* 热门分类 */}
+                        {item.componentType === "hot_category" && <HotCategory data={item} />}
+                    </div>
+                    <div className={styles.compBoxM} />
+                </React.Fragment>
             })
         }
 
@@ -60,7 +129,7 @@ interface Props {
 }
 const Content = forwardRef((props: Props, ref) => {
     const { state, dispatch } = useModel("appPageConifg")
-     // 使用 useImperativeHandle 暴露方法给父组件
+    // 使用 useImperativeHandle 暴露方法给父组件
     useImperativeHandle(ref, () => ({
     }));
     return <div className={styles.phone}>
@@ -82,8 +151,11 @@ const Content = forwardRef((props: Props, ref) => {
                 }
 
             </Space>
-            {/* 内容 */}
-            <DragItem />
+            <div className={styles.content_box}>
+                {/* 内容 */}
+                <DragItem />
+            </div>
+
         </div>
     </div>
 })

+ 19 - 4
src/pages/MiniApp/CompConfig/DrawerBox/index.less

@@ -1,10 +1,16 @@
 // 左侧组件列表
 .pageList {
-    .banners {
-        width: 12vw;
-        height: calc(12vw / 3);
+    display:flex;
+    flex-flow: column;
+    .box {
+        width: 5vw;
+        height: 4vw;
         border: 1px solid #f3f3f3;
         border-radius: 5px;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        font-size:calc(100vw / 150) ;
     }
 }
 
@@ -54,6 +60,13 @@
                 }
             }
         }
+        .content_box{
+            height: calc(18vw *2); /* 根据比例缩放高度 */
+            overflow-y: auto;
+            &::-webkit-scrollbar{
+                display: none;  /* 隐藏滚动条 */
+            }
+        }
         .comp{
             cursor: pointer;
             box-sizing: border-box;
@@ -68,7 +81,9 @@
         }
     }
 }
-
+.compBoxM {
+    height: calc(100vw / 102);
+ }
 
 // 右侧参数设置
 .set {

+ 27 - 7
src/pages/MiniApp/CompConfig/DrawerBox/index.tsx

@@ -1,17 +1,20 @@
 import { Button, Col, Drawer, Row } from "antd";
-import React, { useState, useImperativeHandle, forwardRef, useRef } from "react";
+import React, { useState, useImperativeHandle, forwardRef, useRef, useEffect, useMemo } from "react";
 import PageList from "./pageList";
 import Content from "./content";
 import SetData from "./set";
 import { useToken } from "@ant-design/pro-components";
 import { useSize } from "ahooks";
 import { useModel } from "@umijs/max";
+import { useAjax } from "@/Hook/useAjax";
+import { appComponentConfigGetAppPageList } from "@/services/miniApp/compConfig";
 // 定义组件的 Props 类型
 interface Props {
 }
 
 // 使用 forwardRef 以支持传递 ref
 const ModalForm = forwardRef((props: Props, ref) => {
+    let { initialState } = useModel("@@initialState")
     let { state, dispatch } = useModel('appPageConifg')
     const [open, setOpen] = useState(false);
     const headerSize = useSize(document.querySelector('.ant-drawer-header'));
@@ -19,6 +22,23 @@ const ModalForm = forwardRef((props: Props, ref) => {
     const PageListRef = useRef<any>(null);
     const ContentRef = useRef<any>(null);
     const SetDataRef = useRef<any>(null);
+    const AppComponentConfigGetAppPageList = useAjax((params) => appComponentConfigGetAppPageList(params))
+
+    // 接口公共参数
+    let publicData = useMemo(() => {
+        return {
+            appId: initialState?.selectApp?.id || "",
+            appType: initialState?.selectApp?.appType || ""
+        }
+    }, [initialState?.selectApp])
+    // 获取当前小程序可配置的页面和组件
+    useEffect(() => {
+        AppComponentConfigGetAppPageList.run(publicData).then(res => {
+            let page = res?.data?.find((page: { enabledComponent: any; }) => page.enabledComponent)
+            page && dispatch({ type: "setAll", params: { activePage: page?.pagePath, isWorkDirection: true } })
+        })
+    }, [publicData])
+
     // close 方法,用于关闭 Drawer
     const close = () => {
         setOpen(false); // 将 open 设置为 false,关闭 Drawer
@@ -43,18 +63,18 @@ const ModalForm = forwardRef((props: Props, ref) => {
             extra={<Button type='primary'>保存配置</Button>}
             maskClosable={false}
         >
-            <Row wrap style={{height:`calc(100vh - ${(headerSize?.height || 0) + 50}px)`}}>
+            <Row wrap style={{ height: `calc(100vh - ${(headerSize?.height || 0) + 50}px)` }}>
                 {/* 左侧页面列表 pageList*/}
-                <Col  xl={5} xs={24}>
-                    <PageList ref={PageListRef}/>
+                <Col xl={5} xs={24}>
+                    <PageList ref={PageListRef} data={AppComponentConfigGetAppPageList?.data?.data} />
                 </Col>
                 {/* 中间展示 content*/}
-                <Col xl={14}  xs={24} style={{ background: token.colorBgContainerDisabled,display:'flex',alignItems:'center',justifyContent:'center' }}>
-                    <Content ref={ContentRef}/>
+                <Col xl={14} xs={24} style={{ background: token.colorBgContainerDisabled, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
+                    <Content ref={ContentRef} />
                 </Col>
                 {/* 右侧参数设置 set*/}
                 <Col xl={5} xs={24}>
-                    <SetData ref={SetDataRef}/>
+                    <SetData ref={SetDataRef} pageList={AppComponentConfigGetAppPageList?.data?.data} />
                 </Col>
             </Row>
         </Drawer>

+ 80 - 18
src/pages/MiniApp/CompConfig/DrawerBox/pageList.tsx

@@ -1,7 +1,9 @@
 import { useDrag } from "ahooks";
-import { Col, Row, Space, Typography } from "antd";
-import React, { useState, useImperativeHandle, forwardRef, useRef } from "react";
+import { Col, Row, Space, Tabs, Typography } from "antd";
+import React, { useState, useImperativeHandle, forwardRef, useRef, useCallback } from "react";
 import styles from './index.less'
+import { useModel } from "@umijs/max";
+import { useToken } from "@ant-design/pro-components";
 const DragItem = ({ children }: any) => {
     const dragRef = useRef(null);
     const [dragging, setDragging] = useState(false);
@@ -19,35 +21,95 @@ const DragItem = ({ children }: any) => {
     return (
         <div
             ref={dragRef}
-            style={{display:'inline-block'}}
+            style={{ display: 'inline-block' }}
         >
             {children}
         </div>
     );
 };
+type Item = {
+    componentName: string,//组件名称 也是type
+    defaultComponentConfigList: any[],//组件配置
+    enabled: boolean,//是否可编辑
+    enabledAppTypes: number[]//支持的小程序
+    id: number,//组件id
+    remark: string,//备注 一般为中文名称
+    pagePath: string,//所在页面地址
+    disabled: boolean,//是否看使用,在已经添加进页面后禁止使用
+}
+
+const Comp = ({ item }: { item: Item }) => {
+    let { token } = useToken()
+    return item.disabled ? <div key={`${item.id}-${item.componentName}-${item.pagePath}`} className={styles.box} style={{ background: token.colorBgContainerDisabled, cursor: 'no-drop' }}>
+        {item.remark || item.componentName}
+    </div> : <DragItem >
+        <div key={`${item.id}-${item.componentName}-${item.pagePath}`} className={styles.box} style={{ cursor: "copy" }}>
+            {item.remark || item.componentName}
+        </div>
+    </DragItem>
+}
+
+
 // 定义组件的 Props 类型
 interface Props {
+    data: any[]
 }
 // 使用 forwardRef 以支持传递 ref
 const PageList = forwardRef((props: Props, ref) => {
-
+    let { initialState } = useModel("@@initialState")
+    let { state, dispatch } = useModel('appPageConifg')
+    let { data } = props
     // 使用 useImperativeHandle 暴露方法给父组件
     useImperativeHandle(ref, () => ({
     }));
-
-    return <Row gutter={[20, 20]} className={styles.pageList}>
-        <Col span={24}>
-            <Typography.Title level={4} >顶部组件</Typography.Title>
-            <DragItem ><div key="6_banners_pages/index/index"  className={styles.banners}>banners</div></DragItem>
-        </Col>
-        <Col span={24}>
-            <Typography.Title level={4} >内容组件</Typography.Title>
-            <Space>
-                <DragItem ><div key="hot_books">热门书籍</div></DragItem>
-                <DragItem ><div key="hot_category">热门分类</div></DragItem>
-            </Space>
-        </Col>
-    </Row>
+    return <Tabs
+        onChange={(activeKey) => {
+            dispatch({ type: "setAll", params: { activePage: activeKey } })
+        }}
+        activeKey={state.activePage}
+        items={data?.map(item => {
+            return {
+                label: item.pageName,
+                key: item.pagePath,
+                disabled: !item.enabledComponent,
+                children: item.pagePath === state.activePage ? <Row gutter={[20, 20]} className={styles.pageList} >
+                    <Col span={24} style={{ order: 0 }}>
+                        <Typography.Title level={4} >顶部组件</Typography.Title>
+                        {
+                            item?.appComponentList?.filter((i: Item) => i.componentName === 'banners')?.map((comp: Item) => {
+                                let newComp = { ...comp, pagePath: item.pagePath }
+                                let appType = initialState?.selectApp?.appType || 0
+                                let pageConfig = state.pageConfigList.find(page => page.pageUrl === item.pagePath)
+                                let thePage = pageConfig?.workDirectionListDTOS?.find(page => page.workDirection == state.tabs)
+                                let list = thePage?.componentConfigList || []
+                                newComp.disabled = !!list.find(i => i.appComponentId == newComp.id)
+                                if (newComp.enabledAppTypes.includes(appType)) {
+                                    return <Comp item={newComp} key={item.id} />
+                                }
+                            })
+                        }
+                    </Col>
+                    <Col span={24}>
+                        <Typography.Title level={4} >内容组件</Typography.Title>
+                        <Space wrap>
+                            {
+                                item?.appComponentList?.filter((i: Item) => i.componentName !== 'banners')?.map((comp: Item) => {
+                                    let newComp = { ...comp, pagePath: item.pagePath }
+                                    let appType = initialState?.selectApp?.appType || 0
+                                    let pageConfig = state.pageConfigList.find((page: { pageUrl: any; }) => page.pageUrl === item.pagePath)
+                                    let thePage = pageConfig?.workDirectionListDTOS?.find(page => page.workDirection == state.tabs)
+                                    let list = thePage?.componentConfigList || []
+                                    newComp.disabled = !!list.find(i => i.appComponentId == newComp.id)
+                                    if (newComp.enabledAppTypes.includes(appType)) {
+                                        return <Comp item={newComp} key={comp.id} />
+                                    }
+                                })
+                            }
+                        </Space>
+                    </Col>
+                </Row> : <>无组件</>,
+            }
+        })} />
 });
 
 export default PageList;

+ 11 - 6
src/pages/MiniApp/CompConfig/DrawerBox/set.tsx

@@ -1,24 +1,29 @@
 import React, { useState, useImperativeHandle, forwardRef } from "react";
 import { useModel } from "@umijs/max";
-import { BannersConfig } from "./compConfig";
+import { CompConfig } from "./compConfig";
 import styles from './index.less'
 import { useSize } from "ahooks";
 // 定义组件的 Props 类型
 interface Props {
+    pageList: any[]
 }
 
 // 使用 forwardRef 以支持传递 ref
 const SetData = forwardRef((props: Props, ref) => {
+    let { pageList } = props
     const { state, dispatch } = useModel("appPageConifg")
     const size = useSize(document.querySelector(".ant-drawer-body"))
     // 使用 useImperativeHandle 暴露方法给父组件
     useImperativeHandle(ref, () => ({
     }));
-
-    return <div className={styles.set} style={{ height: size?.height ? size.height - 50 : 'auto' }}>
-        {state.compAc === 'banners' && <div> <BannersConfig /></div>}
-        {state.compAc === '' && <div>选中组件可设置内容</div>}
-    </div>
+    return <>
+        <div className={styles.set} style={{ height: size?.height ? size.height - 50 : 'auto' }}>
+            {state.compAc === 'banners' && <div> <CompConfig compName="banners" pageList={pageList} /></div>}
+            {state.compAc === 'hot_books' && <div> <CompConfig compName="hot_books" /></div>}
+            {state.compAc === 'hot_category' && <div> <CompConfig compName="hot_category" /></div>}
+            {!state.compAc && <div>选中组件可设置内容</div>}
+        </div>
+    </>
 });
 
 export default SetData;

+ 3 - 3
src/pages/MiniApp/CompConfig/components/banners.tsx

@@ -1,5 +1,5 @@
 import { BetaSchemaForm, useToken } from "@ant-design/pro-components";
-import { Carousel } from "antd";
+import { Carousel, Empty } from "antd";
 import styles from './index.less'
 export function Banners(props: { data: any[] }) {
     const { token } = useToken()
@@ -7,8 +7,8 @@ export function Banners(props: { data: any[] }) {
     return <Carousel autoplay autoplaySpeed={5000} className={styles.banners}>
         {
             data?.length === 0 ? <div style={{ borderRadius: "10px" }}>
-                <div className={styles.banners_box} style={{ background: token.colorBgBase, display: "flex", alignItems: 'center', justifyContent: 'center' }}>
-                    选中我在右侧配置内容
+                <div className={styles.banners_box} style={{ display: "flex", alignItems: 'center', justifyContent: 'center' }}>
+                    <div style={{ justifyContent: 'center', display: 'flex', width: '100%' }}><Empty image={Empty.PRESENTED_IMAGE_SIMPLE} description="暂无数据请选中后设置" /></div>
                 </div>
             </div> : data?.map((item: any, index: number) => {
                 return <div key={index} style={{ borderRadius: "10px" }}>

+ 9 - 0
src/pages/MiniApp/CompConfig/components/header.tsx

@@ -0,0 +1,9 @@
+import styles from './index.less'
+function Header(props?: { title: string, btnText?: string, showBtn?: boolean }) {
+    return <div className={styles.header}>
+        <strong>{props?.title}</strong>
+        {props?.showBtn && <span>{props?.btnText || "更多"}</span>}
+    </div>
+}
+
+export default Header

+ 56 - 0
src/pages/MiniApp/CompConfig/components/hot_books.tsx

@@ -0,0 +1,56 @@
+import { useToken } from "@ant-design/pro-components";
+import styles from './index.less'
+import Header from "./header";
+import { Empty, Tag } from "antd";
+import { useModel } from "@umijs/max";
+import { ReactElement, JSXElementConstructor, ReactNode, ReactPortal, Key } from "react";
+import { Config } from "@/models/appPageConifg";
+// 热门书
+export function HotBooks(props: {
+    data: {
+        appComponentId: number | string;
+        componentType: string;
+        showRightButton?: boolean;
+        componentName?: string;
+        remark?: string;
+        configs?: any[];
+    }
+}) {
+    const { token } = useToken()
+    let { initialState } = useModel("@@initialState")
+    const { data: { configs, componentName, showRightButton } } = props
+    return <div className={`${styles.hot_books}`}>
+        <Header title={componentName || "今日热书"} showBtn={showRightButton} />
+        {configs?.[0]?.bookInfo ? <>
+            <div className={styles.top}>
+                <img src={configs?.[0]?.bookInfo?.picUrl} onError={(e: any) => {
+                    e.target.src = localStorage.getItem("nocover")
+                }} />
+                <div>
+                    <strong>{configs?.[0]?.bookInfo?.bookName || "书名"}</strong>
+                    <span>{configs?.[0]?.bookInfo?.bookDesc || "描述"}</span>
+                    <div>
+                        <span>{configs?.[0]?.bookInfo?.authorInfo?.authorName}·{configs?.[0]?.bookInfo?.wordCount}万字·{configs?.[0]?.bookInfo?.bookStatus == 0 ? "连载中" : "完结"}</span>
+                        <Tag >{configs?.[0]?.bookInfo?.labelInfoList?.[0]?.name}</Tag>
+                    </div>
+                </div>
+            </div>
+            <div className={styles.list}>
+                {
+                    configs?.filter((i: any, eq: number) => eq != 0)?.map((item: { bookInfo: { picUrl: string | undefined; bookName: string | number | boolean | ReactElement<any, string | JSXElementConstructor<any>> | Iterable<ReactNode> | ReactPortal | null | undefined; }; }, index: Key | null | undefined) => {
+                        return <div key={index} className={styles.box}>
+                            <img src={item?.bookInfo?.picUrl} onError={(e: any) => {
+                                e.target.src = localStorage.getItem("nocover")
+                            }} />
+                            <span>{item?.bookInfo?.bookName}</span>
+                        </div>
+                    })
+                }
+            </div>
+        </> : <div className={styles.banners_box} style={{ display: "flex", alignItems: 'center', justifyContent: 'center', minHeight: 'calc(100vw / 10)', }}>
+            <div style={{ justifyContent: 'center', display: 'flex', width: '100%' }}><Empty image={Empty.PRESENTED_IMAGE_SIMPLE} description="暂无数据请选中后设置" /></div>
+        </div>
+        }
+    </div>
+}
+

+ 101 - 0
src/pages/MiniApp/CompConfig/components/hot_category.tsx

@@ -0,0 +1,101 @@
+import { BetaSchemaForm, useToken } from "@ant-design/pro-components";
+import styles from './index.less'
+import Header from "./header";
+import { useModel } from "@umijs/max";
+import { Key, useEffect, useMemo, useState } from "react";
+import { Config } from "@/models/appPageConifg";
+import { useAjax } from "@/Hook/useAjax";
+import useApi from "@/Hook/useApi";
+import { Empty } from "antd";
+// 热门书
+export function HotCategory(props: {
+    data: {
+        appComponentId: number | string;
+        componentType: string;
+        showRightButton?: boolean;
+        componentName?: string;
+        remark?: string;
+        configs?: any[];
+    }
+}) {
+    const { token } = useToken()
+    const [tag, setTag] = useState<any>(null)
+    let { initialState } = useModel("@@initialState")
+    let { state } = useModel("appPageConifg")
+    const { data: { configs, componentName, showRightButton } } = props
+    const [bookData, setBookData] = useState([])
+    let publicData = useMemo(() => {
+        return {
+            appId: initialState?.selectApp?.id || "",
+            distributorId: initialState?.currentUser?.distributorId,
+            appType: initialState?.selectApp?.appType || "",
+            workDirection: state.tabs
+        }
+    }, [initialState?.selectApp, initialState?.currentUser?.distributorId, state.index])
+    let apiobj = useApi(initialState?.selectApp?.appCategory || 1)
+    let getList = useAjax((params) => apiobj.getBookPageList(params))
+    useEffect(() => {
+        if (!tag) {
+            setTag(configs?.[0]?.categoryId)
+        }
+        if (tag) {
+            console.log("tag", tag)
+            getList.run({ ...publicData, categoryId: tag, pageNum: 1, pageSize: 8 }).then(res => {
+                if (res.code === 200) {
+                    setBookData(res?.data?.records)
+                }
+            })
+        }
+        if (configs) {
+            console.log("configs", configs)
+            let isExist = configs?.find(i => i.categoryId == tag)
+            if (!isExist) {
+                setTag(configs?.[0]?.categoryId)
+            }
+            if (configs.length === 0) {
+                console.log("nullconfigs", configs)
+                setTag(null)
+                setBookData([])
+            }
+        }
+    }, [tag, configs, publicData])
+    console.log("tag1", tag)
+    return <div className={`${styles.hot_category}`}>
+        <Header title={componentName || "热门分类"} btnText={"全部分类"} showBtn={showRightButton} />
+        <div className={styles.tags}>
+            {
+                configs?.map(item => {
+                    return <div
+                        className={`${styles.tag} ${tag === item.categoryId ? styles.tag_ac : ""}`}
+                        key={item.categoryId}
+                        onClick={() => {
+                            setTag(item.categoryId || "")
+                        }}
+                    >
+                        {item?.categoryInfo?.name}
+                    </div>
+                })
+            }
+        </div>
+        <div className={styles.list}>
+            {
+                configs?.find(i => i.categoryId == tag)?.bookIds ? configs?.find(i => i.categoryId == tag)?.bookInfos?.map((item: any) => {
+                    return <div key={item.id} className={styles.box}>
+                        <img src={item?.picUrl} onError={(e: any) => {
+                            e.target.src = localStorage.getItem("nocover")
+                        }} />
+                        <span>{item?.bookName}</span>
+                    </div>
+                }) : bookData?.length > 0 ? bookData?.map((item: any) => {
+                    return <div key={item} className={styles.box}>
+                        <img src={item?.longBookInfo?.picUrl || item?.shortBookInfo?.picUrl} onError={(e: any) => {
+                            e.target.src = localStorage.getItem("nocover")
+                        }} />
+                        <span>{item?.longBookInfo?.bookName || item?.shortBookInfo?.bookName}</span>
+                    </div>
+                }) : <div style={{justifyContent:'center',display:'flex',width:'100%'}}><Empty image={Empty.PRESENTED_IMAGE_SIMPLE} description="暂无数据请选中后设置"/></div>
+            }
+        </div>
+    </div>
+}
+

+ 231 - 0
src/pages/MiniApp/CompConfig/components/index.less

@@ -1,3 +1,4 @@
+// 轮播
 .banners {
     .banners_box {
         width: 100%;
@@ -6,4 +7,234 @@
         border-radius: 10px;
         font-size: calc(100vw / 150);
     }
+}
+
+// 标题
+.header {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    font-size: calc(100vw / 120);
+
+    span {
+        color: #949BAB;
+        font-size: calc(100vw / 170);
+        display: flex;
+        align-items: center;
+        margin-right: calc(100vw / 500);
+
+        &:after {
+            content: "";
+            width: calc(100vw / 320);
+            height: calc(100vw / 320);
+            border-top: 1px solid #949BAB;
+            border-right: 1px solid #949BAB;
+            margin-left: calc(100vw / 500);
+            display: inline-block;
+            transform: rotate(45deg);
+        }
+    }
+}
+
+
+// 今日热书
+.hot_books {
+    .top {
+        margin-top: calc(100vw / 170);
+        display: flex;
+
+        img {
+            width: calc(100vw / 30);
+            height: calc(100vw / 22.4);
+            background: #D8D8D8;
+            border-radius: calc(100vw / 500);
+            margin-right: calc(100vw / 170);
+            float: left;
+        }
+
+        >div {
+            float: left;
+            display: flex;
+            flex-flow: column;
+            width: calc(100vw / 8);
+
+            strong {
+                height: calc(100vw / 100);
+                font-family: PingFangSC, PingFang SC;
+                font-weight: 500;
+                font-size: calc(100vw / 140);
+                color: #333333;
+                line-height: calc(100vw / 100);
+                text-align: left;
+                font-style: normal;
+                white-space: nowrap;
+                /* 强制文本在一行内显示 */
+                overflow: hidden;
+                /* 隐藏溢出内容 */
+                text-overflow: ellipsis;
+                /* 显示省略号 */
+            }
+
+            >span {
+                height: calc(100vw / 65);
+                font-family: PingFangSC, PingFang SC;
+                font-weight: 400;
+                font-size: calc(100vw / 180);
+                color: #666666;
+                line-height: calc(100vw / 130);
+                text-align: left;
+                font-style: normal;
+                margin-top: calc(100vw / 320);
+                display: -webkit-box;
+                /* 创建弹性盒子模型 */
+                -webkit-box-orient: vertical;
+                /* 设置盒子方向为垂直 */
+                -webkit-line-clamp: 2;
+                /* 限制显示两行 */
+                overflow: hidden;
+                /* 超出部分隐藏 */
+                text-overflow: ellipsis;
+                /* 溢出显示省略号 */
+                white-space: normal;
+                /* 允许文本换行 */
+            }
+
+            >div {
+                display: flex;
+                justify-content: space-between;
+                margin-top: calc(100vw / 320);
+
+                span {
+                    height: calc(100vw / 140);
+                    font-family: PingFangSC, PingFang SC;
+                    font-weight: 400;
+                    font-size: calc(100vw / 210);
+                    color: #949BAB;
+                    line-height: calc(100vw / 140);
+                    text-align: left;
+                    font-style: normal;
+                }
+            }
+        }
+    }
+
+    .list {
+        margin-top: calc(100vw / 170);
+        display: flex;
+        justify-content: space-between;
+
+        .box {
+            display: flex;
+            flex-flow: column;
+
+            img {
+                width: calc(100vw / 30);
+                height: calc(100vw / 22.4);
+                background: #D8D8D8;
+                border-radius: calc(100vw / 500);
+                margin-right: calc(100vw / 170);
+                margin-bottom: calc(100vw / 420);
+            }
+
+            span {
+                width: calc(100vw / 30);
+                height: calc(100vw / 60);
+                font-family: PingFangSC, PingFang SC;
+                font-weight: 400;
+                font-size: calc(100vw / 170);
+                color: #333333;
+                line-height: calc(100vw / 120);
+                text-align: left;
+                font-style: normal;
+                display: -webkit-box;
+                /* 创建弹性盒子模型 */
+                -webkit-box-orient: vertical;
+                /* 设置盒子方向为垂直 */
+                -webkit-line-clamp: 2;
+                /* 限制显示两行 */
+                overflow: hidden;
+                /* 超出部分隐藏 */
+                text-overflow: ellipsis;
+                /* 溢出显示省略号 */
+                white-space: normal;
+                /* 允许文本换行 */
+            }
+        }
+    }
+}
+
+// 热门分类
+.hot_category {
+    .tags {
+        display: flex;
+        height: calc(100vw / 75);
+        overflow-x: auto;
+        overflow-y: hidden;
+        flex-flow: row nowrap;
+        margin: calc(100vw / 150) 0;
+        .tag {
+            height: calc(100vw / 75);
+            background: #e8e7e7;
+            border-radius:  calc(100vw / 128);;
+            font-size: calc(100vw / 160);
+            float: left;
+            margin-right:  calc(100vw / 213);
+            padding: calc(100vw / 155) calc(100vw / 155);
+            display: flex;
+            align-items: center;
+            justify-content: center;
+        }
+        .tag_ac{
+            background: #E5EBFA;
+        }
+        &::-webkit-scrollbar{
+            display: none;  /* 隐藏滚动条 */
+        }
+    }
+
+    .list {
+        margin-top: calc(100vw / 170);
+        display: flex;
+        justify-content: space-between;
+        flex-flow: row wrap;
+
+        .box {
+            display: flex;
+            flex-flow: column;
+            margin-bottom: calc(100vw / 150);
+
+            img {
+                width: calc(100vw / 30);
+                height: calc(100vw / 22.4);
+                background: #D8D8D8;
+                border-radius: calc(100vw / 500);
+                margin-right: calc(100vw / 170);
+                margin-bottom: calc(100vw / 420);
+            }
+
+            span {
+                width: calc(100vw / 30);
+                height: calc(100vw / 60);
+                font-family: PingFangSC, PingFang SC;
+                font-weight: 400;
+                font-size: calc(100vw / 170);
+                color: #333333;
+                line-height: calc(100vw / 120);
+                text-align: left;
+                font-style: normal;
+                display: -webkit-box;
+                /* 创建弹性盒子模型 */
+                -webkit-box-orient: vertical;
+                /* 设置盒子方向为垂直 */
+                -webkit-line-clamp: 2;
+                /* 限制显示两行 */
+                overflow: hidden;
+                /* 超出部分隐藏 */
+                text-overflow: ellipsis;
+                /* 溢出显示省略号 */
+                white-space: normal;
+                /* 允许文本换行 */
+            }
+        }
+    }
 }

+ 2 - 2
src/pages/MiniApp/CompConfig/index.tsx

@@ -171,7 +171,7 @@ const Page: React.FC = () => {
     >
         {/* 模板列表 */}
         <Row gutter={[20, 20]}>
-            {
+            {/* {
                 getList?.data?.data?.map((item: { id: Key | null | undefined; templateName: string | number | boolean | ReactElement<any, string | JSXElementConstructor<any>> | Iterable<ReactNode> | ReactPortal | null | undefined; rechargeConfigs: any[]; templateType: number; templateDescription: string | number | boolean | ReactElement<any, string | JSXElementConstructor<any>> | Iterable<ReactNode> | ReactPortal | null | undefined }) => {
                     return <Col key={item.id} style={{ cursor: 'pointer' }} onClick={() => { switchTemplate(item.id) }} xs={{ span: 24 }} sm={{ span: 8 }}>
                         <Card className={activeT === item.id ? styles.active : ""} style={{ background: activeT === item.id ? token.colorPrimaryBgHover : token.colorFillAlter }} hoverable>
@@ -193,7 +193,7 @@ const Page: React.FC = () => {
                         </Card>
                     </Col>
                 })
-            }
+            } */}
             {
                 getList?.data?.data?.length === 0 && <div style={{ width: "100%", height: "100%", marginTop: "10%" }}><Empty description={<Space direction='vertical'><div>暂无模板数据</div><Button type="primary" onClick={() => { closeForm(true) }}><PlusOutlined />新增模板</Button></Space>} /></div>
             }

+ 28 - 0
src/services/miniApp/adBack/index.ts

@@ -0,0 +1,28 @@
+import { api } from '@/services/api';
+import { request } from '@umijs/max';
+
+type ToAuthData = {
+    "appId": number,//应用id
+    "appType": number,//应用类型
+    "advertisingChannel": number,//广告投放渠道
+    "callbackPage": string//回调地址
+}
+/**获取授权地址*/
+export async function tencentAdAccountToAuth(data:ToAuthData ) {
+    return request(api + '/admin/tencentAdAccount/toAuth', {
+        method: 'POST',
+        data
+    });
+}
+type DoAuthData = {
+    "state": string,
+    "authorizationCode": string,
+    "callbackPage": string//回调地址
+}
+/**广告账号授权*/
+export async function tencentAdAccountDoAuth(data:DoAuthData ) {
+    return request(api + '/admin/tencentAdAccount/doAuth', {
+        method: 'POST',
+        data
+    });
+}

+ 0 - 1
src/services/miniApp/compConfig/index.tsx

@@ -34,4 +34,3 @@ export async function appComponentConfigGetAppPageList(params: Params) {
     });
 }
 
-