客户端集成简历生成器
Some checks failed
Node CI / build (14.x, macOS-latest) (push) Has been cancelled
Node CI / build (14.x, ubuntu-latest) (push) Has been cancelled
Node CI / build (14.x, windows-latest) (push) Has been cancelled
Node CI / build (16.x, macOS-latest) (push) Has been cancelled
Node CI / build (16.x, ubuntu-latest) (push) Has been cancelled
Node CI / build (16.x, windows-latest) (push) Has been cancelled
coverage CI / build (push) Has been cancelled
Node pnpm CI / build (16.x, macOS-latest) (push) Has been cancelled
Node pnpm CI / build (16.x, ubuntu-latest) (push) Has been cancelled
Node pnpm CI / build (16.x, windows-latest) (push) Has been cancelled

This commit is contained in:
francis-fh
2026-07-24 19:28:10 +08:00
parent 0b90547ceb
commit 279011e652
5 changed files with 566 additions and 1053 deletions

View File

@@ -1,5 +1,5 @@
import React, { useCallback, useEffect, useRef, useState } from 'react';
import { useParams, useNavigate, useSearchParams } from '@umijs/max';
import { useModel, useParams, useNavigate, useSearchParams } from '@umijs/max';
import { Button, Card, message, Space, Switch, Typography } from 'antd';
import { ArrowLeftOutlined, EyeOutlined } from '@ant-design/icons';
import Iframe from 'iframe-js';
@@ -253,6 +253,60 @@ function AppUserResume() {
const iframeRef = useRef<HTMLIFrameElement>(null);
const resumeDataRef = useRef<API.CmsAppUser.ResumeData | null>(null);
// 行为上报:记录浏览时长和浏览次数
const { initialState } = useModel('@@initialState');
const enterTimeRef = useRef<number>(0);
const reportedRef = useRef<boolean>(false);
const actorIdRef = useRef<string | undefined>('');
const targetIdRef = useRef<number>(0);
actorIdRef.current = initialState?.currentUser?.userId;
targetIdRef.current = userId;
// 页面进入/离开时上报浏览行为
useEffect(() => {
enterTimeRef.current = Date.now();
reportedRef.current = false;
const doReport = (durationSeconds: number) => {
if (reportedRef.current) return;
reportedRef.current = true;
const actorId = actorIdRef.current;
const targetId = targetIdRef.current;
if (!actorId || !targetId || durationSeconds <= 0) return;
const payload = {
actorType: '2',
actorId: String(actorId),
targetType: '1',
targetId: String(targetId),
viewDuration: String(durationSeconds),
};
fetch('/api/cms/behavior/report', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload),
keepalive: true,
}).catch(() => {});
};
const calcDuration = () =>
Math.max(1, Math.floor((Date.now() - enterTimeRef.current) / 1000));
const handleBeforeUnload = () => {
doReport(calcDuration());
};
window.addEventListener('beforeunload', handleBeforeUnload);
return () => {
window.removeEventListener('beforeunload', handleBeforeUnload);
doReport(calcDuration());
};
}, []);
// 字典数据code → 汉字)
const [sexDict, setSexDict] = useState<DictMap>({});
const [educationDict, setEducationDict] = useState<DictMap>({});