616 lines
24 KiB
TypeScript
616 lines
24 KiB
TypeScript
// 注册留存分析 用户行为记录分析
|
||
|
||
import { connect, Link } from "umi";
|
||
import type { CurrentUser } from "umi";
|
||
import type { ConnectState } from "@/models/connect";
|
||
import React, { useEffect, useRef, useState } from "react";
|
||
import ProCard from "@ant-design/pro-card";
|
||
import { MenuFoldOutlined } from "@ant-design/icons";
|
||
import { FormInstance, Tooltip } from "antd";
|
||
import { Button, message, Space, Spin, Tree } from "antd";
|
||
import useRequest from "@ahooksjs/use-request";
|
||
import { getServerpartTree } from "@/services/options";
|
||
import type { ActionType } from "@ant-design/pro-table";
|
||
import ProTable from "@ant-design/pro-table";
|
||
import ReactHTMLTableToExcel from "react-html-table-to-excel";
|
||
import moment from 'moment'
|
||
import PageTitleBox from "@/components/PageTitleBox";
|
||
import { handleGetBEHAVIORRECORDList, handleGetBEHAVIORRECORDListCloud } from "@/pages/Setting/OperationLog/service";
|
||
import MemberDetail from "../memberInfor/component/memberDetail";
|
||
import { handleSetlogSave } from "@/utils/format";
|
||
import { handeGetNestingFIELDENUMListNoEncryption } from "../service";
|
||
import { highlightText } from "@/utils/highlightText";
|
||
|
||
|
||
const RegistrationRetentionAnalysis: React.FC<{ currentUser: CurrentUser, isComponent?: Boolean, parentDetail?: any }> = (props) => {
|
||
const { dispatch, children, currentUser, isComponent, parentDetail } = props
|
||
const downloadBtnRef = useRef<any>()
|
||
const actionRef = useRef<ActionType>();
|
||
const formRef = useRef<FormInstance>();
|
||
const [reqDetailList, setReqDetailList] = useState<any>(); // 合计项数据源
|
||
const [printOut, setPrintOut] = useState<any>(); // 打印数据的内容
|
||
const [printIndex, setPrintIndex] = useState<number>(new Date().getTime())
|
||
|
||
|
||
// 树相关的属性和方法
|
||
const [selectedId, setSelectedId] = useState<string>()
|
||
// 导出的加载效果
|
||
const [showLoading, setShowLoading] = useState<boolean>(false)
|
||
// 是否显示打印的表格
|
||
const [showExportTable, setShowExportTable] = useState<boolean>(false)
|
||
// 查询的条件
|
||
const [searchParams, setSearchParams] = useState<any>()
|
||
// 表格数据
|
||
const [tableData, setTableData] = useState<any>()
|
||
// 表格加载效果
|
||
const [tableLoading, setTableLoading] = useState<boolean>(false)
|
||
// 判断是否是第一次
|
||
const [isFirst, setIsFirst] = useState<boolean>(true)
|
||
// 当前查询的文字
|
||
const [currentSearchText, setCurrentSearchText] = useState<string>('')
|
||
|
||
const [columnsStateMap, setColumnsStateMap] = useState<any>({
|
||
BEHAVIORRECORD_ID: { show: false },
|
||
OPERATING_SYSTEM: { show: false },
|
||
BROWSER_VERSION: { show: false },
|
||
});
|
||
|
||
// 改变panes
|
||
const handleTabsPanes = (payload: any): void => {
|
||
if (dispatch) {
|
||
dispatch({
|
||
type: 'global/changeTabsRoutes',
|
||
payload: { data: payload, action: 'add' },
|
||
});
|
||
}
|
||
};
|
||
// 显示详情抽屉
|
||
const [showDetailDrawer, setShowDetailDrawer] = useState<boolean>(false)
|
||
// 当前行数据
|
||
const [currentRow, setCurrentRow] = useState<any>()
|
||
|
||
const columns: any = [
|
||
{
|
||
title: '查询内容',
|
||
hideInTable: true,
|
||
dataIndex: 'searchValue',
|
||
fieldProps: {
|
||
placeholder: '请输入操作人员/访问页面'
|
||
}
|
||
},
|
||
{
|
||
title: '查询时间',
|
||
dataIndex: 'search_date',
|
||
valueType: 'dateRange',
|
||
hideInTable: true,
|
||
hideInDescriptions: true,
|
||
search: {
|
||
transform: (value) => {
|
||
return {
|
||
BEHAVIORRECORD_TIME_Start: value[0],
|
||
BEHAVIORRECORD_TIME_End: value[1],
|
||
};
|
||
},
|
||
},
|
||
fieldProps: {
|
||
ranges: {
|
||
"当日": [moment(), moment()],
|
||
"本月": [moment().startOf('M'), moment()],
|
||
}
|
||
},
|
||
initialValue: [moment(), moment()],
|
||
// initialValue: [moment().format('YYYY-MM-DD'), moment().format('YYYY-MM-DD')],
|
||
},
|
||
{
|
||
title: '日志编号',
|
||
width: 120,
|
||
hideInSearch: true,
|
||
dataIndex: 'BEHAVIORRECORD_ID'
|
||
},
|
||
|
||
{
|
||
title: '访问页面',
|
||
width: 150,
|
||
hideInSearch: true,
|
||
ellipsis: true,
|
||
dataIndex: 'BEHAVIORRECORD_ROUTNAME',
|
||
render: (_, record) => {
|
||
return highlightText(record?.BEHAVIORRECORD_ROUTNAME, currentSearchText)
|
||
}
|
||
// render: (_, record) => {
|
||
// return record?.BEHAVIORRECORD_ROUTNAME ? <a onClick={() => {
|
||
// console.log('record', record);
|
||
// const req: any = {
|
||
// key: record.BEHAVIORRECORD_ROUT,
|
||
// path: record.BEHAVIORRECORD_ROUT,
|
||
// title: record.BEHAVIORRECORD_ROUTNAME,
|
||
// children: children
|
||
// }
|
||
// console.log('req', req);
|
||
// handleTabsPanes(req)
|
||
// }}>
|
||
// {record?.BEHAVIORRECORD_ROUTNAME || ""}
|
||
// </a> : "-"
|
||
// return record?.BEHAVIORRECORD_ROUTNAME ? <Link to={record.BEHAVIORRECORD_ROUT}>
|
||
// {record?.BEHAVIORRECORD_ROUTNAME}
|
||
// </Link> : ""
|
||
// }
|
||
},
|
||
{
|
||
title: '操作类型',
|
||
dataIndex: 'BEHAVIORRECORD_TYPE',
|
||
// hideInSearch: true,
|
||
width: 100,
|
||
valueType: 'treeSelect',
|
||
align: 'center',
|
||
request: async () => {
|
||
const req = {
|
||
FIELDEXPLAIN_FIELD: 'BEHAVIORRECORD_TYPE',
|
||
FIELDEXPLAIN_ID: "",
|
||
FIELDENUM_PID: "",
|
||
FIELDENUM_STATUS: 1,
|
||
SearchKey: ""
|
||
}
|
||
const data = await handeGetNestingFIELDENUMListNoEncryption(req);
|
||
console.log('djskadjsaivbsjavbcv', data);
|
||
|
||
return data
|
||
},
|
||
// valueEnum: {
|
||
// "1000": '操作',
|
||
// "1001": '编辑',
|
||
// "1002": '删除',
|
||
// "2000": '查询'
|
||
// },
|
||
// initialValue: 1000,
|
||
fieldProps: {
|
||
fieldNames: {
|
||
label: 'FIELDENUM_NAME',
|
||
value: 'FIELDENUM_VALUE',
|
||
children: 'children'
|
||
},
|
||
treeDefaultExpandAll: true,
|
||
}
|
||
},
|
||
{
|
||
title: '操作人员',
|
||
hideInSearch: true,
|
||
align: 'center',
|
||
dataIndex: 'USER_NAME',
|
||
ellipsis: true,
|
||
width: 120,
|
||
render: (_, record) => {
|
||
return isComponent ? record?.USER_NAME : <a onClick={() => {
|
||
setCurrentRow(record)
|
||
setShowDetailDrawer(true)
|
||
handleSetlogSave(`查看${record?.MEMBERSHIP_NAME}【${record?.MEMBERSHIP_ID}】会员信息`)
|
||
}}>
|
||
{/* {record?.USER_NAME || '-'} */}
|
||
{highlightText(record?.USER_NAME, currentSearchText)}
|
||
</a>
|
||
}
|
||
},
|
||
{
|
||
title: '操作地址',
|
||
hideInSearch: true,
|
||
// hideInTable: isComponent,
|
||
hideInTable: true,
|
||
dataIndex: 'USER_LOGINIP',
|
||
align: 'center',
|
||
width: 150,
|
||
},
|
||
{
|
||
title: '操作地点',
|
||
hideInSearch: true,
|
||
dataIndex: 'USER_LOGINPLACE',
|
||
align: 'center',
|
||
width: 160,
|
||
ellipsis: true,
|
||
},
|
||
// {
|
||
// title: '响应时间(s)',
|
||
// hideInSearch: true,
|
||
// dataIndex: 'BEHAVIORRECORD_DURATION',
|
||
// width: 120,
|
||
// align: 'center',
|
||
// sorter: (a, b) => a.BEHAVIORRECORD_DURATION - b.BEHAVIORRECORD_DURATION,
|
||
// render: (_, record) => {
|
||
// return `${record?.BEHAVIORRECORD_DURATION ? record?.BEHAVIORRECORD_DURATION : ""}`
|
||
// }
|
||
// },
|
||
{
|
||
title: <div style={{ textAlign: 'center' }}>操作内容</div>,
|
||
hideInSearch: true,
|
||
dataIndex: 'BEHAVIORRECORD_EXPLAIN',
|
||
width: 250,
|
||
align: 'left',
|
||
ellipsis: true,
|
||
},
|
||
// {
|
||
// title: '操作状态',
|
||
// dataIndex: 'status',
|
||
// hideInSearch: true,
|
||
// width: 100,
|
||
// render: (_, record) => {
|
||
// return '成功'
|
||
// }
|
||
// },
|
||
{
|
||
title: '操作日期',
|
||
width: 160,
|
||
valueType: 'date',
|
||
align: 'center',
|
||
dataIndex: 'BEHAVIORRECORD_TIME',
|
||
hideInSearch: true,
|
||
sorter: true,
|
||
render: (_, record) => {
|
||
return record?.BEHAVIORRECORD_TIME
|
||
}
|
||
},
|
||
{
|
||
title: '操作平台',
|
||
width: 160,
|
||
dataIndex: 'SOURCE_PLATFORM',
|
||
valueType: 'select',
|
||
align: 'center',
|
||
valueEnum: {
|
||
"出行平台": "出行平台",
|
||
// "数智化看板": "数智化看板",
|
||
// "驿行畅旅": "驿行畅旅",
|
||
// "驿付商家版": "驿付商家版",
|
||
// "微信公众号": "微信公众号",
|
||
// "驿商云客户端": "驿商云客户端",
|
||
"彩云驿出行": "彩云驿出行",
|
||
},
|
||
initialValue: '彩云驿出行'
|
||
},
|
||
{
|
||
title: '操作系统',
|
||
width: 150,
|
||
hideInSearch: true,
|
||
dataIndex: 'OPERATING_SYSTEM',
|
||
},
|
||
{
|
||
title: '浏览器版本',
|
||
width: 150,
|
||
hideInSearch: true,
|
||
dataIndex: 'BROWSER_VERSION',
|
||
},
|
||
// {
|
||
// title: '接口信息',
|
||
// width: 150,
|
||
// hideInSearch: true,
|
||
// dataIndex: 'REQUEST_INFO',
|
||
// ellipsis: true,
|
||
// },
|
||
// {
|
||
// title: '调用入参',
|
||
// width: 150,
|
||
// hideInSearch: true,
|
||
// dataIndex: 'BEHAVIORRECORD_DESC',
|
||
// ellipsis: true,
|
||
// },
|
||
// {
|
||
// title: '操作',
|
||
// width: 120,
|
||
// dataIndex: 'options'
|
||
// }
|
||
]
|
||
|
||
const exportTable = (e) => {
|
||
e.stopPropagation(); // 防止Collapse组件收起
|
||
const main = document.getElementsByClassName(`saleReportHideBox${printIndex}`)[0]
|
||
const thead = main.querySelector('thead').cloneNode(true); // 深克隆DOM节点
|
||
const tbody = main.querySelector('tbody').cloneNode(true); // 深克隆DOM节点
|
||
const container = document.querySelector('#hiddenBox');
|
||
|
||
const tempTable = document.createElement('table');
|
||
tempTable.appendChild(thead);
|
||
tempTable.appendChild(tbody);
|
||
|
||
tempTable.setAttribute('id', 'table-to-xls-saleRankReport'); // 给table添加id,值与按钮上的table字段对应
|
||
|
||
container.appendChild(tempTable); // 把创建的节点添加到页面容器中
|
||
|
||
setShowLoading(false)
|
||
|
||
downloadBtnRef.current.handleDownload();
|
||
setShowExportTable(false)
|
||
tempTable.remove() // 防止重复打印一个内容
|
||
}
|
||
|
||
const handleGetTableData = async (paramsObj?: any) => {
|
||
let result: any = {}
|
||
|
||
const res: any = formRef ? formRef?.current?.getFieldsValue() : {}
|
||
console.log('resresres', res);
|
||
let [start, end] = ['', '']
|
||
// let [start, end] = res?.search_date
|
||
let params: any = {}
|
||
if (res) {
|
||
[start, end] = res?.search_date
|
||
params = {
|
||
BEHAVIORRECORD_TIME: res && res.BEHAVIORRECORD_TIME ? moment(res.BEHAVIORRECORD_TIME._d).format('YYYY-MM-DD') : "",
|
||
SOURCE_PLATFORM: res && res.SOURCE_PLATFORM ? res.SOURCE_PLATFORM : "",
|
||
BEHAVIORRECORD_TYPE: res && res.BEHAVIORRECORD_TYPE ? res.BEHAVIORRECORD_TYPE : "",
|
||
start: start,
|
||
end: end,
|
||
...res
|
||
}
|
||
}
|
||
|
||
|
||
setTableLoading(true)
|
||
console.log('isComponentisComponent', isComponent);
|
||
console.log('paramsparamsparamsparamsparams', params);
|
||
|
||
const req: any = isComponent ? {
|
||
SearchParameter: {
|
||
SOURCE_PLATFORMS: '彩云驿出行',
|
||
USER_MOBILEPHONE: parentDetail?.MEMBERSHIP_MOBILEPHONE
|
||
},
|
||
SortStr: 'BEHAVIORRECORD_TIME desc',
|
||
PageIndex: paramsObj.current || 1,
|
||
PageSize: paramsObj?.pageSize || 999999
|
||
} : {
|
||
SearchParameter: {
|
||
BEHAVIORRECORD_TIME_Start: moment(params?.start).format('YYYY-MM-DD'),
|
||
BEHAVIORRECORD_TIME_End: moment(params?.end).format('YYYY-MM-DD'),
|
||
SOURCE_PLATFORMS: params?.SOURCE_PLATFORM,
|
||
// BEHAVIORRECORD_TYPE: params?.BEHAVIORRECORD_TYPE
|
||
},
|
||
SortStr: 'BEHAVIORRECORD_TIME desc',
|
||
KeyWord: {
|
||
Key: 'BEHAVIORRECORD_ROUTNAME,USER_NAME,VISIT_CHANNELS,BEHAVIORRECORD_PREROUT',
|
||
Value: params?.searchValue || ''
|
||
},
|
||
PageIndex: paramsObj.current || 1,
|
||
PageSize: paramsObj?.pageSize || 999999
|
||
}
|
||
console.log('reqreqreqreq', req);
|
||
|
||
setSearchParams(params)
|
||
const data = await handleGetBEHAVIORRECORDList(req)
|
||
console.log('dhsjdhasjdhs', data);
|
||
|
||
setReqDetailList(data.List)
|
||
setTableData(data.List)
|
||
setTableLoading(false)
|
||
result = { data: data.List, success: true, total: data.TotalCount }
|
||
|
||
// if (isComponent) {
|
||
|
||
// } else {
|
||
// const allReq: any = {
|
||
// SearchParameter: {
|
||
// BEHAVIORRECORD_TIME_Start: moment(params?.start).format('YYYY-MM-DD'),
|
||
// BEHAVIORRECORD_TIME_End: moment(params?.end).format('YYYY-MM-DD'),
|
||
// SOURCE_PLATFORMS: params?.SOURCE_PLATFORM,
|
||
// // BEHAVIORRECORD_TYPE: params?.BEHAVIORRECORD_TYPE
|
||
// },
|
||
// SortStr: 'BEHAVIORRECORD_TIME desc',
|
||
// KeyWord: {
|
||
// Key: 'BEHAVIORRECORD_ROUTNAME,USER_NAME,VISIT_CHANNELS,BEHAVIORRECORD_PREROUT',
|
||
// Value: params?.searchValue || ''
|
||
// },
|
||
// PageIndex: 1,
|
||
// PageSize: 999999
|
||
// }
|
||
// const allData = await handleGetBEHAVIORRECORDList(allReq)
|
||
// setReqDetailList(data)
|
||
// setTableData(allData)
|
||
// setIsFirst(false)
|
||
// }
|
||
}
|
||
|
||
// 悬浮框的关闭方法
|
||
const handleCloseModal = () => {
|
||
setShowDetailDrawer(false)
|
||
setCurrentRow(undefined);
|
||
}
|
||
|
||
// useEffect(async () => {
|
||
// handleGetTableData()
|
||
// }, [])
|
||
|
||
return (
|
||
<div ref={(el) => {
|
||
// 打印报表
|
||
if (!reqDetailList || reqDetailList.length === 0) return;
|
||
setPrintOut(el);
|
||
}} >
|
||
|
||
{
|
||
showLoading ?
|
||
<div
|
||
style={{
|
||
width: '100%',
|
||
height: '100%',
|
||
background: 'rgba(0,0,0,0.1)',
|
||
position: 'fixed',
|
||
zIndex: 5,
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
justifyContent: 'center'
|
||
}}
|
||
>
|
||
<div style={{
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
justifyContent: 'center',
|
||
padding: '15px 20px 10px',
|
||
background: '#fff',
|
||
borderRadius: '8px',
|
||
width: '200px'
|
||
}}>
|
||
<Spin />
|
||
<span style={{ marginLeft: '5px' }}>数据导出中...</span>
|
||
</div>
|
||
</div> : ''
|
||
}
|
||
|
||
<div className={`saleReportHideBox${printIndex}`} style={{ position: 'fixed', zIndex: -1, top: 0, left: 0 }}>
|
||
{
|
||
showExportTable && reqDetailList && reqDetailList.length > 0 ?
|
||
<ProTable
|
||
columns={columns}
|
||
dataSource={reqDetailList}
|
||
pagination={false}
|
||
expandable={{
|
||
defaultExpandAllRows: true
|
||
}}
|
||
/> : ''
|
||
}
|
||
</div>
|
||
<div id='hiddenBox' style={{ position: 'fixed', zIndex: -1, top: 0, left: 0 }} />
|
||
|
||
<div style={{ backgroundColor: '#fff', display: 'flex' }}>
|
||
<div style={{
|
||
width: '100%',
|
||
paddingTop: 0,
|
||
paddingBottom: 0,
|
||
paddingRight: 0
|
||
}}>
|
||
<ProTable
|
||
actionRef={actionRef}
|
||
formRef={formRef}
|
||
columns={columns}
|
||
bordered
|
||
expandable={{
|
||
expandRowByClick: true
|
||
}}
|
||
scroll={{ x: '100%', y: isComponent ? '300px' : 'calc(100vh - 470px)' }}
|
||
search={isComponent ? false : { span: 6, defaultCollapsed: false }}
|
||
// dataSource={tableData}
|
||
// loading={tableLoading}
|
||
options={isComponent ? false : {
|
||
density: true,
|
||
reload: true,
|
||
setting: true
|
||
}}
|
||
request={async (params) => {
|
||
console.log('paramsparamsparamsparams', params);
|
||
|
||
const req: any = isComponent ? {
|
||
SearchParameter: {
|
||
SOURCE_PLATFORMS: '彩云驿出行',
|
||
USER_MOBILEPHONE: parentDetail?.MEMBERSHIP_MOBILEPHONE,
|
||
USER_ID: parentDetail?.MEMBERSHIP_ID
|
||
},
|
||
SortStr: 'BEHAVIORRECORD_TIME desc',
|
||
PageIndex: params?.current || 1,
|
||
PageSize: params?.pageSize || 999999
|
||
} : {
|
||
SearchParameter: {
|
||
BEHAVIORRECORD_TIME_Start: moment(params?.BEHAVIORRECORD_TIME_Start).format('YYYY-MM-DD'),
|
||
BEHAVIORRECORD_TIME_End: moment(params?.BEHAVIORRECORD_TIME_End).format('YYYY-MM-DD'),
|
||
SOURCE_PLATFORMS: params?.SOURCE_PLATFORM,
|
||
BEHAVIORRECORD_TYPE: params?.BEHAVIORRECORD_TYPE
|
||
},
|
||
SortStr: 'BEHAVIORRECORD_TIME desc',
|
||
KeyWord: {
|
||
Key: 'BEHAVIORRECORD_ROUTNAME,USER_NAME,VISIT_CHANNELS,BEHAVIORRECORD_PREROUT',
|
||
Value: params?.searchValue || ''
|
||
},
|
||
PageIndex: 1,
|
||
PageSize: 999999
|
||
}
|
||
|
||
setSearchParams(params)
|
||
let data = []
|
||
if (isComponent) {
|
||
data = await handleGetBEHAVIORRECORDList(req)
|
||
} else {
|
||
if (params?.SOURCE_PLATFORM === '出行平台') {
|
||
data = await handleGetBEHAVIORRECORDList(req)
|
||
} else if (params?.SOURCE_PLATFORM === '彩云驿出行') {
|
||
data = await handleGetBEHAVIORRECORDListCloud(req)
|
||
}
|
||
}
|
||
|
||
|
||
setCurrentSearchText(params?.searchValue || "")
|
||
|
||
setReqDetailList(data.List)
|
||
setTableData(data.List)
|
||
setTableLoading(false)
|
||
|
||
|
||
if (data.List && data.List.length > 0) {
|
||
return { data: data.List, success: true, total: data.TotalCount }
|
||
}
|
||
return { data: [], success: true }
|
||
// const data = await handleGetTableData(params)
|
||
// return data
|
||
|
||
|
||
// if (!isFirst) {
|
||
// handleGetTableData()
|
||
// }
|
||
|
||
// console.log('data', data);
|
||
// if (data && data.length > 0) {
|
||
// setReqDetailList(data)
|
||
// return { data, success: true }
|
||
// }
|
||
// return { data: [], success: true }
|
||
}}
|
||
toolbar={{
|
||
actions: isComponent ? [] : [
|
||
<span style={{ visibility: 'hidden' }}>
|
||
<ReactHTMLTableToExcel
|
||
buttonText={'导出excel'}
|
||
ref={downloadBtnRef}
|
||
table="table-to-xls-saleRankReport"
|
||
filename={`操作日志列表`}
|
||
sheet="sheet1"
|
||
/>
|
||
</span>,
|
||
<Button
|
||
key="new"
|
||
type="primary"
|
||
onClick={(e) => {
|
||
if (reqDetailList && reqDetailList.length > 0) {
|
||
setShowLoading(true)
|
||
setTimeout(() => {
|
||
setShowExportTable(true)
|
||
setTimeout(() => {
|
||
exportTable(e)
|
||
}, 100)
|
||
}, 100)
|
||
} else {
|
||
message.error('暂无数据可导出!')
|
||
}
|
||
}}
|
||
>
|
||
导出excel
|
||
</Button>
|
||
]
|
||
}}
|
||
columnsState={{
|
||
value: columnsStateMap,
|
||
onChange: setColumnsStateMap,
|
||
}}
|
||
onChange={(pagination, filters, sorter, extra) => {
|
||
if (extra.action === 'sort') {
|
||
return;
|
||
}
|
||
}}
|
||
/>
|
||
</div>
|
||
</div>
|
||
|
||
|
||
{/* 会员详情 */}
|
||
<MemberDetail showDetailDrawer={showDetailDrawer}
|
||
currentRow={currentRow}
|
||
handleCloseModal={handleCloseModal}
|
||
currentUser={currentUser} />
|
||
</div>
|
||
)
|
||
}
|
||
|
||
export default connect(({ user }: ConnectState) => ({
|
||
currentUser: user.currentUser
|
||
}))(RegistrationRetentionAnalysis);
|