index.tsx 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  1. import { useState, useEffect } from 'react';
  2. import { Tabs, Table, Button, message } from "antd";
  3. import type { TableProps } from 'antd';
  4. import { DownloadOutlined } from '@ant-design/icons';
  5. import http from '@src/http';
  6. import { gzhDataList, gzhDataExport } from '@src/http/api.ts';
  7. interface GzhDataItem {
  8. dateStr: string;
  9. fansIncreaseCount: number;
  10. firstLevel: number;
  11. name: string;
  12. openRate: number;
  13. score: number;
  14. }
  15. interface GzhDataResponse {
  16. curPageFirstRecNum: number;
  17. curPageLastRecNum: number;
  18. currentPage: number;
  19. nextPage: number;
  20. obj: GzhDataItem;
  21. objs: GzhDataItem[];
  22. offset: number;
  23. pageSize: number;
  24. prePage: number;
  25. totalPage: number;
  26. totalSize: number;
  27. }
  28. const Gzh: React.FC = () => {
  29. const [allDataSource, setAllDataSource] = useState<GzhDataItem[]>([]);
  30. const [separateDataSource, setSeparateDataSource] = useState<GzhDataItem[]>([]);
  31. const [loading, setLoading] = useState<boolean>(false);
  32. const [downloadLoading, setDownloadLoading] = useState<boolean>(false);
  33. const [pagination, setPagination] = useState({
  34. current: 1,
  35. pageSize: 10,
  36. total: 0
  37. });
  38. const [activeKey, setActiveKey] = useState("0");
  39. const columns:TableProps['columns'] = [
  40. {
  41. title: '日期',
  42. dataIndex: 'dateStr',
  43. key: 'dateStr',
  44. },
  45. {
  46. title: '新增粉丝',
  47. dataIndex: 'fansIncreaseCount',
  48. key: 'fansIncreaseCount',
  49. },
  50. {
  51. title: '小程序访问人数',
  52. dataIndex: 'firstLevel',
  53. key: 'firstLevel',
  54. },
  55. {
  56. title: '打开率',
  57. dataIndex: 'openRate',
  58. key: 'openRate',
  59. render: (text) => `${(Number(text) * 100).toFixed(2)}%`
  60. },
  61. {
  62. title: '本渠道裂变率',
  63. dataIndex: 'score',
  64. key: 'score',
  65. },
  66. {
  67. title: '预估单价',
  68. dataIndex: 'unitPrice',
  69. key: 'unitPrice',
  70. },
  71. {
  72. title: '建议结算金额',
  73. dataIndex: 'settlementAmount',
  74. key: 'settlementAmount',
  75. },
  76. ];
  77. const separateColumns:TableProps['columns'] = [
  78. {
  79. title: '日期',
  80. dataIndex: 'dateStr',
  81. key: 'dateStr',
  82. },
  83. {
  84. title: '公众号',
  85. dataIndex: 'name',
  86. key: 'name',
  87. },
  88. {
  89. title: '新增粉丝',
  90. dataIndex: 'fansIncreaseCount',
  91. key: 'fansIncreaseCount',
  92. },
  93. {
  94. title: '小程序访问人数',
  95. dataIndex: 'firstLevel',
  96. key: 'firstLevel',
  97. },
  98. {
  99. title: '打开率',
  100. dataIndex: 'openRate',
  101. key: 'openRate',
  102. render: (text) => `${(Number(text) * 100).toFixed(2)}%`
  103. },
  104. {
  105. title: '本渠道裂变率',
  106. dataIndex: 'score',
  107. key: 'score',
  108. },
  109. ];
  110. const separateVideoColumns:TableProps['columns'] = [
  111. {
  112. title: '日期',
  113. dataIndex: 'dateStr',
  114. key: 'dateStr',
  115. },
  116. {
  117. title: '公众号',
  118. dataIndex: 'name',
  119. key: 'name',
  120. },
  121. {
  122. title: '视频ID',
  123. dataIndex: 'videoId',
  124. key: 'videoId',
  125. },
  126. {
  127. title: '视频标题',
  128. dataIndex: 'title',
  129. key: 'title',
  130. },
  131. {
  132. title: '小程序访问人数',
  133. dataIndex: 'firstLevel',
  134. key: 'firstLevel',
  135. },
  136. {
  137. title: '本渠道裂变率',
  138. dataIndex: 'score',
  139. key: 'score',
  140. },
  141. ];
  142. const fetchGzhData = async (page = 1, pageSize = 10, type = 0) => {
  143. setAllDataSource([]);
  144. setSeparateDataSource([]);
  145. try {
  146. setLoading(true);
  147. const res = await http.post<GzhDataResponse>(gzhDataList, {
  148. pageNum: page,
  149. pageSize: pageSize,
  150. type: type
  151. });
  152. if (res.success && res.data) {
  153. if (type === 0 || type === 2) {
  154. setAllDataSource(res.data.objs || []);
  155. } else {
  156. setSeparateDataSource(res.data.objs || []);
  157. }
  158. setPagination({
  159. current: res.data.currentPage,
  160. pageSize: res.data.pageSize,
  161. total: res.data.totalSize
  162. });
  163. }
  164. } catch (error) {
  165. console.error('获取公众号数据失败:', error);
  166. } finally {
  167. setLoading(false);
  168. }
  169. };
  170. useEffect(() => {
  171. fetchGzhData(1, 10, 0);
  172. }, []);
  173. const onChange = (key: string) => {
  174. console.log(key);
  175. fetchGzhData(1, 10, Number(key));
  176. };
  177. const handleTableChange = (pagination: any) => {
  178. const { current, pageSize } = pagination;
  179. fetchGzhData(current, pageSize, Number(activeKey));
  180. };
  181. const handleDownload = async () => {
  182. try {
  183. setDownloadLoading(true);
  184. // 根据当前选中的标签页设置type参数
  185. const type = Number(activeKey);
  186. // 使用当前分页信息
  187. const response = await http.post(gzhDataExport, {
  188. pageNum: pagination.current,
  189. pageSize: pagination.pageSize,
  190. type: type
  191. });
  192. if (response.success && response.data) {
  193. window.open(response.data as string);
  194. } else {
  195. message.error('下载失败');
  196. }
  197. } catch {
  198. message.error('下载失败');
  199. } finally {
  200. setDownloadLoading(false);
  201. }
  202. };
  203. return (
  204. <>
  205. <div className={"flex mb-[10px]"}>
  206. <div className={"flex-1 leading-[32px]"}>公众号数据统计</div>
  207. </div>
  208. <Tabs
  209. defaultActiveKey="0"
  210. type="card"
  211. tabBarExtraContent={{
  212. right: <Button
  213. type="link"
  214. icon={<DownloadOutlined />}
  215. loading={downloadLoading}
  216. onClick={handleDownload}
  217. >
  218. 下载数据
  219. </Button>
  220. }}
  221. onChange={(key) => {
  222. setActiveKey(key);
  223. onChange(key);
  224. }}
  225. items={[
  226. {
  227. key: "0",
  228. label: "自动回复总计",
  229. children: (
  230. <Table
  231. dataSource={allDataSource}
  232. columns={columns}
  233. rowKey={(record, idx) => record.dateStr + record.ghId + idx}
  234. loading={loading}
  235. pagination={{
  236. current: pagination.current,
  237. pageSize: pagination.pageSize,
  238. total: pagination.total,
  239. showSizeChanger: true,
  240. showTotal: (total) => `共 ${total} 条`,
  241. }}
  242. onChange={handleTableChange}
  243. />
  244. ),
  245. },
  246. {
  247. key: "1",
  248. label: "自动回复分账号",
  249. children: (
  250. <Table
  251. dataSource={separateDataSource}
  252. columns={separateColumns}
  253. rowKey={(record, idx) => record.dateStr + record.ghId + idx}
  254. loading={loading}
  255. pagination={{
  256. current: pagination.current,
  257. pageSize: pagination.pageSize,
  258. total: pagination.total,
  259. showSizeChanger: true,
  260. showTotal: (total) => `共 ${total} 条`,
  261. }}
  262. onChange={handleTableChange}
  263. />
  264. ),
  265. },
  266. {
  267. key: "4",
  268. label: "自动回复分账号分视频",
  269. children: (
  270. <Table
  271. dataSource={separateDataSource}
  272. columns={separateVideoColumns}
  273. rowKey={(record, idx) => record.dateStr + record.ghId + idx}
  274. loading={loading}
  275. pagination={{
  276. current: pagination.current,
  277. pageSize: pagination.pageSize,
  278. total: pagination.total,
  279. showSizeChanger: true,
  280. showTotal: (total) => `共 ${total} 条`,
  281. }}
  282. onChange={handleTableChange}
  283. />
  284. ),
  285. },
  286. {
  287. key: "2",
  288. label: "服务号总计",
  289. children: (
  290. <Table
  291. dataSource={allDataSource}
  292. columns={columns}
  293. rowKey={(record, idx) => record.dateStr + record.ghId + idx}
  294. loading={loading}
  295. pagination={{
  296. current: pagination.current,
  297. pageSize: pagination.pageSize,
  298. total: pagination.total,
  299. showSizeChanger: true,
  300. showTotal: (total) => `共 ${total} 条`,
  301. }}
  302. onChange={handleTableChange}
  303. />
  304. ),
  305. },
  306. {
  307. key: "3",
  308. label: "服务号分账号",
  309. children: (
  310. <Table
  311. dataSource={separateDataSource}
  312. columns={separateColumns}
  313. rowKey={(record, idx) => record.dateStr + record.ghId + idx}
  314. loading={loading}
  315. pagination={{
  316. current: pagination.current,
  317. pageSize: pagination.pageSize,
  318. total: pagination.total,
  319. showSizeChanger: true,
  320. showTotal: (total) => `共 ${total} 条`,
  321. }}
  322. onChange={handleTableChange}
  323. />
  324. ),
  325. },
  326. ]}
  327. />
  328. </>
  329. )
  330. }
  331. export default Gzh