客户端集成简历生成器
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
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:
@@ -8,31 +8,11 @@
|
||||
.jp-page-container();
|
||||
padding: 20px 20px 40px;
|
||||
}
|
||||
}
|
||||
|
||||
.section {
|
||||
.jp-card-base();
|
||||
margin-bottom: 16px;
|
||||
padding: 0;
|
||||
|
||||
.ant-card-head {
|
||||
border-bottom: 1px solid @jp-border;
|
||||
|
||||
.ant-card-head-title {
|
||||
color: @jp-primary;
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.card-profile .name {
|
||||
color: @jp-text-primary;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.ant-btn-primary {
|
||||
background: @jp-primary;
|
||||
border-color: @jp-primary;
|
||||
}
|
||||
// iframe 区域确保撑满
|
||||
#resume-generator {
|
||||
display: block;
|
||||
}
|
||||
|
||||
@media (max-width: 1366px) {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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>({});
|
||||
|
||||
@@ -160,12 +160,29 @@ function CompanyUserList() {
|
||||
align: 'center',
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
title: '企业联系人',
|
||||
dataIndex: 'contactPerson',
|
||||
valueType: 'text',
|
||||
align: 'center',
|
||||
width: 180,
|
||||
hideInTable: true,
|
||||
},
|
||||
{
|
||||
title: '联系人电话',
|
||||
dataIndex: 'contactPersonPhone',
|
||||
valueType: 'text',
|
||||
align: 'center',
|
||||
width: 160,
|
||||
hideInTable: true,
|
||||
},
|
||||
{
|
||||
title: '企业联系人',
|
||||
dataIndex: 'companyContactList',
|
||||
valueType: 'text',
|
||||
align: 'center',
|
||||
width: 180,
|
||||
hideInSearch: true,
|
||||
render: (_, record) => {
|
||||
const list = record.companyContactList;
|
||||
if (!list || list.length === 0) return '-';
|
||||
@@ -356,7 +373,7 @@ function CompanyUserList() {
|
||||
success: true,
|
||||
}))
|
||||
}
|
||||
search={{ labelWidth: 'auto' }}
|
||||
search={{ labelWidth: 'auto', defaultCollapsed: false }}
|
||||
scroll={{ x: 'max-content' }}
|
||||
pagination={{ defaultPageSize: 10, showSizeChanger: true }}
|
||||
headerTitle="企业用户管理"
|
||||
|
||||
24
src/types/jobportal/user.d.ts
vendored
24
src/types/jobportal/user.d.ts
vendored
@@ -16,6 +16,7 @@ declare namespace API {
|
||||
education?: string;
|
||||
politicalAffiliation?: string | null;
|
||||
phone?: string;
|
||||
email?: string;
|
||||
avatar?: string;
|
||||
salaryMin?: string;
|
||||
salaryMax?: string;
|
||||
@@ -37,9 +38,32 @@ declare namespace API {
|
||||
company?: string | null;
|
||||
experiencesList?: WorkExperience[];
|
||||
appSkillsList?: AppSkill[];
|
||||
educationsList?: AppUserEducation[];
|
||||
trainsList?: AppUserTrain[];
|
||||
fileList?: any[];
|
||||
}
|
||||
|
||||
export interface AppUserEducation {
|
||||
id?: number;
|
||||
userId?: number;
|
||||
schoolName?: string;
|
||||
major?: string;
|
||||
degree?: string;
|
||||
startTime?: string;
|
||||
endTime?: string;
|
||||
content?: string;
|
||||
}
|
||||
|
||||
export interface AppUserTrain {
|
||||
id?: number;
|
||||
userId?: number;
|
||||
trainOrg?: string;
|
||||
trainCourse?: string;
|
||||
startTime?: string;
|
||||
endTime?: string;
|
||||
trainContent?: string;
|
||||
}
|
||||
|
||||
export interface WorkExperience {
|
||||
createTime?: string;
|
||||
updateTime?: string;
|
||||
|
||||
Reference in New Issue
Block a user