客户端集成简历生成器
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();
|
.jp-page-container();
|
||||||
padding: 20px 20px 40px;
|
padding: 20px 20px 40px;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.section {
|
// iframe 区域确保撑满
|
||||||
.jp-card-base();
|
#resume-generator {
|
||||||
margin-bottom: 16px;
|
display: block;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 1366px) {
|
@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 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 { Button, Card, message, Space, Switch, Typography } from 'antd';
|
||||||
import { ArrowLeftOutlined, EyeOutlined } from '@ant-design/icons';
|
import { ArrowLeftOutlined, EyeOutlined } from '@ant-design/icons';
|
||||||
import Iframe from 'iframe-js';
|
import Iframe from 'iframe-js';
|
||||||
@@ -253,6 +253,60 @@ function AppUserResume() {
|
|||||||
const iframeRef = useRef<HTMLIFrameElement>(null);
|
const iframeRef = useRef<HTMLIFrameElement>(null);
|
||||||
const resumeDataRef = useRef<API.CmsAppUser.ResumeData | null>(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 → 汉字)
|
// 字典数据(code → 汉字)
|
||||||
const [sexDict, setSexDict] = useState<DictMap>({});
|
const [sexDict, setSexDict] = useState<DictMap>({});
|
||||||
const [educationDict, setEducationDict] = useState<DictMap>({});
|
const [educationDict, setEducationDict] = useState<DictMap>({});
|
||||||
|
|||||||
@@ -160,12 +160,29 @@ function CompanyUserList() {
|
|||||||
align: 'center',
|
align: 'center',
|
||||||
width: 100,
|
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: '企业联系人',
|
title: '企业联系人',
|
||||||
dataIndex: 'companyContactList',
|
dataIndex: 'companyContactList',
|
||||||
valueType: 'text',
|
valueType: 'text',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
width: 180,
|
width: 180,
|
||||||
|
hideInSearch: true,
|
||||||
render: (_, record) => {
|
render: (_, record) => {
|
||||||
const list = record.companyContactList;
|
const list = record.companyContactList;
|
||||||
if (!list || list.length === 0) return '-';
|
if (!list || list.length === 0) return '-';
|
||||||
@@ -356,7 +373,7 @@ function CompanyUserList() {
|
|||||||
success: true,
|
success: true,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
search={{ labelWidth: 'auto' }}
|
search={{ labelWidth: 'auto', defaultCollapsed: false }}
|
||||||
scroll={{ x: 'max-content' }}
|
scroll={{ x: 'max-content' }}
|
||||||
pagination={{ defaultPageSize: 10, showSizeChanger: true }}
|
pagination={{ defaultPageSize: 10, showSizeChanger: true }}
|
||||||
headerTitle="企业用户管理"
|
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;
|
education?: string;
|
||||||
politicalAffiliation?: string | null;
|
politicalAffiliation?: string | null;
|
||||||
phone?: string;
|
phone?: string;
|
||||||
|
email?: string;
|
||||||
avatar?: string;
|
avatar?: string;
|
||||||
salaryMin?: string;
|
salaryMin?: string;
|
||||||
salaryMax?: string;
|
salaryMax?: string;
|
||||||
@@ -37,9 +38,32 @@ declare namespace API {
|
|||||||
company?: string | null;
|
company?: string | null;
|
||||||
experiencesList?: WorkExperience[];
|
experiencesList?: WorkExperience[];
|
||||||
appSkillsList?: AppSkill[];
|
appSkillsList?: AppSkill[];
|
||||||
|
educationsList?: AppUserEducation[];
|
||||||
|
trainsList?: AppUserTrain[];
|
||||||
fileList?: any[];
|
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 {
|
export interface WorkExperience {
|
||||||
createTime?: string;
|
createTime?: string;
|
||||||
updateTime?: string;
|
updateTime?: string;
|
||||||
|
|||||||
Reference in New Issue
Block a user