wjx 8 ore fa
parent
commit
3619dd6642

+ 3 - 2
src/layout/index.tsx

@@ -1,6 +1,6 @@
 import { SetStateAction, useCallback, useEffect, useState } from 'react'
 import { Layout, Menu, Space, ConfigProvider, Watermark, App, message } from 'antd';
-import { DesktopOutlined, MessageOutlined, SendOutlined, CloudOutlined, TeamOutlined, HomeOutlined, PaperClipOutlined, ContainerOutlined, AlipayCircleOutlined, StopOutlined, QrcodeOutlined, DatabaseOutlined, ReadOutlined, MobileOutlined, FundViewOutlined, RadarChartOutlined, BarChartOutlined, WechatOutlined, BookOutlined, FileImageOutlined, EyeOutlined, UserOutlined, AlertOutlined, FieldTimeOutlined } from '@ant-design/icons';
+import { DesktopOutlined, MessageOutlined, SendOutlined, CloudOutlined, TeamOutlined, HomeOutlined, PaperClipOutlined, ContainerOutlined, AlipayCircleOutlined, StopOutlined, QrcodeOutlined, DatabaseOutlined, ReadOutlined, MobileOutlined, FundViewOutlined, RadarChartOutlined, BarChartOutlined, WechatOutlined, BookOutlined, FileImageOutlined, EyeOutlined, UserOutlined, AlertOutlined, FieldTimeOutlined, ApiOutlined } from '@ant-design/icons';
 import { ReactComponent as LaunchSvg } from '../public/svg/launch.svg'
 import { ReactComponent as AdLaunchSvg } from '../public/svg/adLaunch.svg'
 import { ReactComponent as MaterialSvg } from '../public/svg/material.svg'
@@ -96,7 +96,8 @@ const IconMap = {
     interdiction: <StopOutlined />,
     eye: <EyeOutlined />,
     alert: <AlertOutlined />,
-    log: <ContainerOutlined />
+    log: <ContainerOutlined />,
+    apiOutlined: <ApiOutlined />
 };
 
 export const DispatchContext = React.createContext<{ config: any } | null>(null);

+ 53 - 0
src/pages/weComTask/API/weChatApiLicense/index.ts

@@ -0,0 +1,53 @@
+import request from "@/utils/request";
+const { api } = process.env.CONFIG;
+
+
+export interface GetLicenseAppListProps {
+    pageNum: number,
+    pageSize: number,
+    corpName?: string,
+    expiredStart?: string,
+    expiredEnd?: string,
+    licenseCheckStart?: string,
+    licenseCheckEnd?: string
+}
+
+/**
+ * 企业许可列表
+ * @returns 
+ */
+export function getLicenseAppListApi(data: GetLicenseAppListProps) {
+    return request({
+        url: api + `/corpOperation/license/app/listOfPage`,
+        method: 'POST',
+        data
+    })
+}
+
+
+/**
+ * 应用信息同步更新 
+ * @param params 
+ * @returns 
+ */
+export function syncByCorpAppApi(params: { corpId: string }) {
+    return request({
+        url: api + `/corpOperation/license/app/syncByCorpId`,
+        method: 'PATCH',
+        params
+    })
+}
+
+
+/**
+ * 修改应用信息更新通知人员
+ * @param data 
+ * @returns 
+ */
+export function updateCallUserAppApi(data: { corpIdList: string[], userIdList: number[] }) {
+    return request({
+        url: api + `/corpOperation/license/app/updateCallUserIds`,
+        method: 'POST',
+        data
+    })
+}

+ 2 - 2
src/pages/weComTask/page/home/groupItem.tsx

@@ -119,8 +119,8 @@ const GroupXfCorpTabls: React.FC<{ groupList: { label: string, value: number }[]
 
     /***********************************/
     const taskType = projectType === 1 ? 'TASK_STAT_GROUP_SEND_CHAT' : projectType === 2 ? 'TASK_STAT_GROUP_ROBOT' : 'TASK_STAT_GROUP_SEND'
-    const [queryParams, setQueryParams] = useState<GetSendUserListProps>({ pageNum: 1, pageSize: 20 })
-    const [oldQueryParams, setOldQueryParams] = useState<GetSendUserListProps>({ pageNum: 1, pageSize: 20 })
+    const [queryParams, setQueryParams] = useState<GetSendUserListProps>({ pageNum: 1, pageSize: 20, startDay: dayJs().format('YYYY-MM-DD') })
+    const [oldQueryParams, setOldQueryParams] = useState<GetSendUserListProps>({ pageNum: 1, pageSize: 20, startDay: dayJs().format('YYYY-MM-DD') })
     const { token } = useNewToken()
     const [modal, contextHolder] = Modal.useModal();
 

+ 77 - 0
src/pages/weComTask/page/weChatApiLicense/enterprise/editCallUser.tsx

@@ -0,0 +1,77 @@
+import { getAdAccountAllOfMember } from "@/API/global";
+import { useAjax } from "@/Hook/useAjax";
+import { updateCallUserAppApi } from "@/pages/weComTask/API/weChatApiLicense";
+import { App, Form, Modal, Select } from "antd";
+import React, { useEffect } from "react";
+
+interface EditCallUserProps {
+    selectedRows: any[]
+    visible?: boolean
+    onClose?: () => void
+    onChange?: () => void
+}
+
+
+export const EditCallUser: React.FC<EditCallUserProps> = ({ visible, onClose, onChange, selectedRows }) => {
+
+    /**************************************/
+    const [form] = Form.useForm();
+    const { message } = App.useApp();
+
+    const allOfMember = useAjax(() => getAdAccountAllOfMember())
+    const updateCallUserApp = useAjax((params) => updateCallUserAppApi(params))
+    /**************************************/
+
+    useEffect(() => {
+        allOfMember.run()
+    }, [])
+
+    const handleOk = () => {
+        form.validateFields().then((values) => { 
+            updateCallUserApp.run({
+                ...values,
+                corpIdList: selectedRows.map(item => item.corpId)
+            }).then(res => {
+                if (res?.data) {
+                    message.success('更新成功')
+                    onChange?.()
+                }
+            })
+        })
+        
+    }
+
+    return <Modal
+        title={<strong>修改应用信息更新通知人员</strong>}
+        open={visible}
+        onCancel={onClose}
+        onOk={handleOk}
+        width={600}
+        confirmLoading={updateCallUserApp.loading}
+    >
+        <Form
+            form={form}
+            labelCol={{ span: 4 }}
+            wrapperCol={{ span: 20 }}
+            labelAlign="left"
+            autoComplete="off"
+            colon={false}
+        >
+            <Form.Item label={<strong>到期通知人员</strong>} name="userIdList">
+                <Select
+                    mode="multiple"
+                    allowClear
+                    placeholder="请选择到期通知人员"
+                    showSearch
+                    options={allOfMember?.data?.data?.map((item: any) => ({ label: item.nickname, value: item.userId }))}
+                    filterOption={(input, option) =>
+                        ((option?.label ?? '') as string).toLowerCase().includes(input.toLowerCase())
+                    }
+                />
+            </Form.Item>
+        </Form>
+    </Modal>
+}
+
+
+export default React.memo(EditCallUser)

+ 210 - 0
src/pages/weComTask/page/weChatApiLicense/enterprise/index.tsx

@@ -0,0 +1,210 @@
+import { useAjax } from "@/Hook/useAjax";
+import { getLicenseAppListApi, GetLicenseAppListProps } from "@/pages/weComTask/API/weChatApiLicense";
+import SearchBox from "@/pages/weComTask/components/searchBox";
+import { Button, Card, DatePicker, Input, Table, Tag } from "antd";
+import { useEffect, useState } from "react";
+import { SearchOutlined } from "@ant-design/icons";
+import dayJs from "dayjs";
+import { copy } from "@/utils/utils";
+import SyncApp from "./syncApp";
+import EditCallUser from "./editCallUser";
+
+
+/**
+ * 企业许可状态
+ * @returns 
+ */
+const Enterprise: React.FC = () => {
+
+    /***********************************/
+    const [queryParams, setQueryParams] = useState<GetLicenseAppListProps>({ pageNum: 1, pageSize: 20 })
+    const [oldQueryParams, setOldQueryParams] = useState<GetLicenseAppListProps>({ pageNum: 1, pageSize: 20 })
+    const [selectedRows, setselectedRows] = useState<any[]>([])
+    const [visible, setVisible] = useState<boolean>(false)
+
+    const getLicenseAppList = useAjax((params) => getLicenseAppListApi(params))
+    /***********************************/
+
+    useEffect(() => {
+        getLicenseAppList.run(queryParams)
+    }, [queryParams])
+
+
+    return <Card>
+        <SearchBox
+            bodyPadding={`0 0 10px`}
+            buttons={<>
+                <Button type="primary" onClick={() => {
+                    setQueryParams({ ...oldQueryParams, pageNum: 1, pageSize: queryParams.pageSize })
+                }} loading={getLicenseAppList.loading} icon={<SearchOutlined />}>搜索</Button>
+                <Button disabled={selectedRows?.length === 0} onClick={() => setVisible(true)}>修改应用信息更新通知人员</Button>
+                <Button disabled={selectedRows?.length === 0} danger onClick={() => setselectedRows([])}>清除选择</Button>
+            </>}
+        >
+            <>
+                <Input
+                    placeholder="企业名称"
+                    style={{ width: 120 }}
+                    allowClear
+                    onChange={(e) => setOldQueryParams({ ...oldQueryParams, corpName: e.target.value })}
+                    value={oldQueryParams?.corpName}
+                />
+                <DatePicker.RangePicker
+                    placeholder={['试用到期开始日期', '试用到期结束日期']}
+                    onChange={(e, date) => { setOldQueryParams({ ...oldQueryParams, expiredStart: date[0], expiredEnd: date[1] }) }}
+                    allowClear
+                    value={oldQueryParams?.expiredStart ? [dayJs(oldQueryParams?.expiredStart), dayJs(oldQueryParams?.expiredEnd)] : undefined}
+                />
+                <DatePicker.RangePicker
+                    placeholder={['拦截校验开始日期', '拦截校验结束日期']}
+                    onChange={(e, date) => { setOldQueryParams({ ...oldQueryParams, licenseCheckStart: date[0], licenseCheckEnd: date[1] }) }}
+                    allowClear
+                    value={oldQueryParams?.licenseCheckStart ? [dayJs(oldQueryParams?.licenseCheckStart), dayJs(oldQueryParams?.licenseCheckEnd)] : undefined}
+                />
+            </>
+        </SearchBox>
+
+        {/* 表 */}
+        <Table
+            style={{ marginTop: 10 }}
+            dataSource={getLicenseAppList?.data?.data?.records}
+            loading={getLicenseAppList?.loading}
+            bordered
+            columns={[
+                {
+                    title: '操作',
+                    dataIndex: 'cz',
+                    key: 'cz',
+                    align: 'center',
+                    width: 90,
+                    render: (_, record: any) => {
+                        return <SyncApp corpId={record.corpId} onChange={getLicenseAppList?.refresh} />
+                    }
+                },
+                {
+                    title: '企业名称',
+                    dataIndex: 'corpName',
+                    key: 'corpName',
+                    width: 200,
+                    ellipsis: true,
+                    render: (text) => <a onClick={() => copy(text)}>{text}</a>
+                },
+                {
+                    title: '企业ID',
+                    dataIndex: 'corpId',
+                    key: 'corpId',
+                    width: 280,
+                    ellipsis: true,
+                },
+                {
+                    title: '状态',
+                    dataIndex: 'licenseStatus',
+                    key: 'licenseStatus',
+                    width: 120,
+                    align: 'center',
+                    render: (text) => text ? <Tag color="green">已开启状态检查</Tag> : <Tag color="red">未开启状态检查</Tag>
+                },
+                {
+                    title: '接口许可试用开始时间',
+                    dataIndex: 'startTime',
+                    key: 'startTime',
+                    width: 145,
+                    align: 'center',
+                    ellipsis: true,
+                    render: (text) => text || '--'
+                },
+                {
+                    title: '接口许可试用到期时间',
+                    dataIndex: 'endTime',
+                    key: 'endTime',
+                    width: 145,
+                    align: 'center',
+                    ellipsis: true,
+                    render: (text) => text || '--'
+                },
+                {
+                    title: '接口开启拦截校验时间',
+                    dataIndex: 'licenseCheckTime',
+                    key: 'licenseCheckTime',
+                    width: 145,
+                    align: 'center',
+                    ellipsis: true,
+                    render: (text) => text || '--'
+                },
+                {
+                    title: '到期通知人员',
+                    dataIndex: 'userList',
+                    key: 'userList',
+                    ellipsis: true,
+                    render: (text) => text?.map(item => item.name)?.join('、') || '--'
+                }
+            ]}
+            scroll={{ x: 1000 }}
+            rowKey={'corpId'}
+            size='small'
+            pagination={{
+                total: getLicenseAppList?.data?.data?.total,
+                showTotal: (total) => <Tag color="cyan">总共{total}数据</Tag>,
+                showSizeChanger: true,
+                showLessItems: true,
+                defaultCurrent: 1,
+                defaultPageSize: 20,//默认初始的每页条数
+                current: getLicenseAppList?.data?.data?.current || 1,
+                pageSize: getLicenseAppList?.data?.data?.size || 20,
+                onChange: (page, pageSize) => {
+                    setQueryParams({ ...queryParams, pageNum: page, pageSize })
+                    setOldQueryParams({ ...oldQueryParams, pageNum: page, pageSize })
+                }
+            }}
+            rowSelection={{
+                selectedRowKeys: selectedRows?.map((item: any) => item?.corpId),
+                onSelect: (record: { corpId: string }, selected: boolean) => {
+                    let newData = JSON.parse(JSON.stringify(selectedRows))
+                    if (selected) {
+                        newData.push({ ...record })
+                    } else {
+                        newData = newData.filter((item: { corpId: string }) => item.corpId !== record.corpId)
+                    }
+                    setselectedRows(newData)
+                },
+                onSelectAll: (selected: boolean, _: { corpId: string }[], changeRows: { corpId: string }[]) => {
+                    let newData = JSON.parse(JSON.stringify(selectedRows || '[]'))
+                    if (selected) {
+                        changeRows.forEach((item: { corpId: string }) => {
+                            const index = newData.findIndex((ite: { corpId: string }) => ite.corpId === item.corpId)
+                            if (index === -1) {
+                                newData.push(item)
+                            }
+                        })
+                    } else {
+                        const newSelectAccData = newData.filter((item: { corpId: string }) => {
+                            const index = changeRows.findIndex((ite: { corpId: string }) => ite.corpId === item.corpId)
+                            if (index !== -1) {
+                                return false
+                            } else {
+                                return true
+                            }
+                        })
+                        newData = newSelectAccData
+                    }
+                    setselectedRows(newData)
+                }
+            }}
+        />
+
+        {/* 编辑呼叫用户 */}
+        {visible && <EditCallUser 
+            selectedRows={selectedRows}
+            visible={visible} 
+            onClose={() => setVisible(false)} 
+            onChange={() => {
+                setselectedRows([])
+                setVisible(false)
+                getLicenseAppList.refresh()
+            }}
+        />}
+    </Card>
+}
+
+
+export default Enterprise

+ 30 - 0
src/pages/weComTask/page/weChatApiLicense/enterprise/syncApp.tsx

@@ -0,0 +1,30 @@
+import { useAjax } from "@/Hook/useAjax"
+import { syncByCorpAppApi } from "@/pages/weComTask/API/weChatApiLicense"
+import { App, Button } from "antd"
+import React from "react"
+
+/**
+ * 应用信息同步
+ * @param params 
+ * @returns 
+ */
+const SyncApp: React.FC<{ corpId: string, onChange?: () => void }> = ({ corpId, onChange }) => {
+
+    /*********************************/
+    const { message } = App.useApp()
+    const syncByCorpApp = useAjax((params) => syncByCorpAppApi(params))
+    /*********************************/
+
+    const syncHandle = () => {
+        syncByCorpApp.run({ corpId }).then((res) => {
+            if (res?.data) {
+                message.success('同步成功')
+                onChange?.()
+            }
+        })
+    }
+
+    return <Button type="link" style={{ margin: 0, padding: 0 }} loading={syncByCorpApp.loading} onClick={syncHandle}>应用信息同步</Button>
+}
+
+export default React.memo(SyncApp)