用户行为统计
Some checks are pending
Node CI / build (14.x, macOS-latest) (push) Waiting to run
Node CI / build (14.x, ubuntu-latest) (push) Waiting to run
Node CI / build (14.x, windows-latest) (push) Waiting to run
Node CI / build (16.x, macOS-latest) (push) Waiting to run
Node CI / build (16.x, ubuntu-latest) (push) Waiting to run
Node CI / build (16.x, windows-latest) (push) Waiting to run
coverage CI / build (push) Waiting to run
Node pnpm CI / build (16.x, macOS-latest) (push) Waiting to run
Node pnpm CI / build (16.x, ubuntu-latest) (push) Waiting to run
Node pnpm CI / build (16.x, windows-latest) (push) Waiting to run
Some checks are pending
Node CI / build (14.x, macOS-latest) (push) Waiting to run
Node CI / build (14.x, ubuntu-latest) (push) Waiting to run
Node CI / build (14.x, windows-latest) (push) Waiting to run
Node CI / build (16.x, macOS-latest) (push) Waiting to run
Node CI / build (16.x, ubuntu-latest) (push) Waiting to run
Node CI / build (16.x, windows-latest) (push) Waiting to run
coverage CI / build (push) Waiting to run
Node pnpm CI / build (16.x, macOS-latest) (push) Waiting to run
Node pnpm CI / build (16.x, ubuntu-latest) (push) Waiting to run
Node pnpm CI / build (16.x, windows-latest) (push) Waiting to run
This commit is contained in:
@@ -19,8 +19,8 @@ export type MapProps = {
|
|||||||
open: boolean;
|
open: boolean;
|
||||||
};
|
};
|
||||||
export const aMapConfig = {
|
export const aMapConfig = {
|
||||||
key: '9cfc9370bd8a941951da1cea0308e9e3',
|
key: 'b79ea14cb17704ab1a1a32c12d72f634',
|
||||||
securityJsCode: '7b16386c7f744c3ca05595965f2b037f',
|
securityJsCode: '04795ef5b20919d34cadc2e33e01d609',
|
||||||
};
|
};
|
||||||
|
|
||||||
/** 石河子市地图默认中心点与行政区划编码 */
|
/** 石河子市地图默认中心点与行政区划编码 */
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import React, { useState, useEffect, useMemo } from 'react';
|
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||||
import { useParams, history, useLocation, useSearchParams } from '@umijs/max';
|
import { useParams, history, useLocation, useSearchParams } from '@umijs/max';
|
||||||
import {
|
import {
|
||||||
Card,
|
Card,
|
||||||
@@ -206,6 +206,55 @@ const JobDetailPage: React.FC = () => {
|
|||||||
const [industryTree, setIndustryTree] = useState<any[]>([]);
|
const [industryTree, setIndustryTree] = useState<any[]>([]);
|
||||||
const [complaintVisible, setComplaintVisible] = useState(false);
|
const [complaintVisible, setComplaintVisible] = useState(false);
|
||||||
|
|
||||||
|
// 行为上报:浏览岗位时长统计
|
||||||
|
const enterTimeRef = useRef<number>(0);
|
||||||
|
const reportedRef = useRef<boolean>(false);
|
||||||
|
const jobIdRef = useRef<string>('');
|
||||||
|
|
||||||
|
// 页面进入/离开时上报浏览行为
|
||||||
|
useEffect(() => {
|
||||||
|
enterTimeRef.current = Date.now();
|
||||||
|
reportedRef.current = false;
|
||||||
|
jobIdRef.current = String(originalJobData?.jobId || originalJobData?.id || id || '');
|
||||||
|
|
||||||
|
const calcDuration = () =>
|
||||||
|
Math.max(1, Math.floor((Date.now() - enterTimeRef.current) / 1000));
|
||||||
|
|
||||||
|
const doReport = (durationSeconds: number) => {
|
||||||
|
if (reportedRef.current) return;
|
||||||
|
reportedRef.current = true;
|
||||||
|
|
||||||
|
const actorId = localStorage.getItem('appUserId');
|
||||||
|
const targetId = jobIdRef.current;
|
||||||
|
|
||||||
|
if (!actorId || !targetId || durationSeconds <= 0) return;
|
||||||
|
|
||||||
|
fetch('/api/cms/behavior/report', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify({
|
||||||
|
actorType: '1',
|
||||||
|
actorId: String(actorId),
|
||||||
|
targetType: '2',
|
||||||
|
targetId: String(targetId),
|
||||||
|
viewDuration: String(durationSeconds),
|
||||||
|
}),
|
||||||
|
keepalive: true,
|
||||||
|
}).catch(() => {});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleBeforeUnload = () => {
|
||||||
|
doReport(calcDuration());
|
||||||
|
};
|
||||||
|
|
||||||
|
window.addEventListener('beforeunload', handleBeforeUnload);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
window.removeEventListener('beforeunload', handleBeforeUnload);
|
||||||
|
doReport(calcDuration());
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
const detailTagGroups = useMemo(
|
const detailTagGroups = useMemo(
|
||||||
() => [
|
() => [
|
||||||
{ label: '薪资范围与构成', values: jobDetail.salaryComposition },
|
{ label: '薪资范围与构成', values: jobDetail.salaryComposition },
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import React, { useState, useEffect, useMemo } from 'react';
|
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||||
import {
|
import {
|
||||||
Card,
|
Card,
|
||||||
Row,
|
Row,
|
||||||
@@ -216,6 +216,70 @@ const JobListPage: React.FC = () => {
|
|||||||
const [complaintVisible, setComplaintVisible] = useState(false);
|
const [complaintVisible, setComplaintVisible] = useState(false);
|
||||||
const selectedJobId = selectedJob?.jobId || selectedJob?.id;
|
const selectedJobId = selectedJob?.jobId || selectedJob?.id;
|
||||||
|
|
||||||
|
// 行为上报:浏览岗位时长统计
|
||||||
|
const jobStartTimeRef = useRef<number>(0);
|
||||||
|
const behaviorReportedRef = useRef<boolean>(false);
|
||||||
|
const currentJobIdRef = useRef<string>('');
|
||||||
|
|
||||||
|
const reportJobBehavior = useCallback((jobId: string) => {
|
||||||
|
if (behaviorReportedRef.current) return;
|
||||||
|
behaviorReportedRef.current = true;
|
||||||
|
|
||||||
|
const actorId = localStorage.getItem('appUserId');
|
||||||
|
if (!actorId || !jobId) return;
|
||||||
|
|
||||||
|
const duration = Math.max(1, Math.floor((Date.now() - jobStartTimeRef.current) / 1000));
|
||||||
|
if (duration <= 0) return;
|
||||||
|
|
||||||
|
fetch('/api/cms/behavior/report', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify({
|
||||||
|
actorType: '1',
|
||||||
|
actorId: String(actorId),
|
||||||
|
targetType: '2',
|
||||||
|
targetId: String(jobId),
|
||||||
|
viewDuration: String(duration),
|
||||||
|
}),
|
||||||
|
keepalive: true,
|
||||||
|
}).catch(() => {});
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
// 切换岗位时上报上一个岗位的浏览时长
|
||||||
|
useEffect(() => {
|
||||||
|
if (!isJobPortalLoggedIn()) return;
|
||||||
|
|
||||||
|
const newJobId = String(selectedJobId || '');
|
||||||
|
|
||||||
|
// 如果之前有浏览中的岗位,先上报
|
||||||
|
if (currentJobIdRef.current && currentJobIdRef.current !== newJobId) {
|
||||||
|
reportJobBehavior(currentJobIdRef.current);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重置计时器,开始计时新岗位
|
||||||
|
behaviorReportedRef.current = false;
|
||||||
|
jobStartTimeRef.current = Date.now();
|
||||||
|
currentJobIdRef.current = newJobId;
|
||||||
|
}, [selectedJobId, reportJobBehavior]);
|
||||||
|
|
||||||
|
// 页面离开时上报当前岗位的浏览时长
|
||||||
|
useEffect(() => {
|
||||||
|
const handleBeforeUnload = () => {
|
||||||
|
if (currentJobIdRef.current) {
|
||||||
|
reportJobBehavior(currentJobIdRef.current);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
window.addEventListener('beforeunload', handleBeforeUnload);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
window.removeEventListener('beforeunload', handleBeforeUnload);
|
||||||
|
if (currentJobIdRef.current) {
|
||||||
|
reportJobBehavior(currentJobIdRef.current);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}, [reportJobBehavior]);
|
||||||
|
|
||||||
const selectedJobDetailTagGroups = useMemo(
|
const selectedJobDetailTagGroups = useMemo(
|
||||||
() =>
|
() =>
|
||||||
[
|
[
|
||||||
|
|||||||
@@ -66,6 +66,7 @@ export type ListFormProps = {
|
|||||||
welfareBenefitsEnum: DictValueEnumObj;
|
welfareBenefitsEnum: DictValueEnumObj;
|
||||||
workScheduleEnum: DictValueEnumObj;
|
workScheduleEnum: DictValueEnumObj;
|
||||||
keyPopulationsEnum: DictValueEnumObj;
|
keyPopulationsEnum: DictValueEnumObj;
|
||||||
|
jobFeatureEnum: DictValueEnumObj;
|
||||||
mode?: 'view' | 'edit' | 'create';
|
mode?: 'view' | 'edit' | 'create';
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -98,6 +99,7 @@ const listEdit: React.FC<ListFormProps> = (props) => {
|
|||||||
welfareBenefitsEnum,
|
welfareBenefitsEnum,
|
||||||
workScheduleEnum,
|
workScheduleEnum,
|
||||||
keyPopulationsEnum,
|
keyPopulationsEnum,
|
||||||
|
jobFeatureEnum,
|
||||||
} = props;
|
} = props;
|
||||||
const { mode = props.values ? 'edit' : 'create' } = props;
|
const { mode = props.values ? 'edit' : 'create' } = props;
|
||||||
const [showKeyPopulations, setShowKeyPopulations] = useState(false);
|
const [showKeyPopulations, setShowKeyPopulations] = useState(false);
|
||||||
@@ -269,6 +271,7 @@ const listEdit: React.FC<ListFormProps> = (props) => {
|
|||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
jobCategory: values.jobCategory,
|
jobCategory: values.jobCategory,
|
||||||
|
jobFeature: values.jobFeature,
|
||||||
isUrgent: values.isUrgent ? 1 : 0,
|
isUrgent: values.isUrgent ? 1 : 0,
|
||||||
isKeyPopulations: showKeyPopulations ? '0' : '1',
|
isKeyPopulations: showKeyPopulations ? '0' : '1',
|
||||||
keyPopulations: showKeyPopulations ? values.keyPopulations : undefined,
|
keyPopulations: showKeyPopulations ? values.keyPopulations : undefined,
|
||||||
@@ -355,6 +358,11 @@ const listEdit: React.FC<ListFormProps> = (props) => {
|
|||||||
<ProDescriptions.Item dataIndex="jobLocation" label="工作地点" />
|
<ProDescriptions.Item dataIndex="jobLocation" label="工作地点" />
|
||||||
<ProDescriptions.Item dataIndex="jobType" label="区域" valueEnum={jobTypeEnum} />
|
<ProDescriptions.Item dataIndex="jobType" label="区域" valueEnum={jobTypeEnum} />
|
||||||
<ProDescriptions.Item dataIndex="jobCategory" label="岗位标签" />
|
<ProDescriptions.Item dataIndex="jobCategory" label="岗位标签" />
|
||||||
|
<ProDescriptions.Item
|
||||||
|
dataIndex="jobFeature"
|
||||||
|
label="岗位特征"
|
||||||
|
valueEnum={jobFeatureEnum}
|
||||||
|
/>
|
||||||
<ProDescriptions.Item
|
<ProDescriptions.Item
|
||||||
dataIndex="description"
|
dataIndex="description"
|
||||||
label="岗位描述"
|
label="岗位描述"
|
||||||
@@ -689,6 +697,13 @@ const listEdit: React.FC<ListFormProps> = (props) => {
|
|||||||
style={{ width: 328 }}
|
style={{ width: 328 }}
|
||||||
/>
|
/>
|
||||||
</ProForm.Item>
|
</ProForm.Item>
|
||||||
|
<ProFormSelect
|
||||||
|
width="md"
|
||||||
|
name="jobFeature"
|
||||||
|
label="岗位特征"
|
||||||
|
valueEnum={jobFeatureEnum}
|
||||||
|
placeholder="请选择岗位特征"
|
||||||
|
/>
|
||||||
<ProFormText width="md" name="jobLocation" label="工作地点" placeholder="请输入工作地点" />
|
<ProFormText width="md" name="jobLocation" label="工作地点" placeholder="请输入工作地点" />
|
||||||
<ProForm.Item label="位置选择" colProps={{ span: 12 }}>
|
<ProForm.Item label="位置选择" colProps={{ span: 12 }}>
|
||||||
<div>
|
<div>
|
||||||
|
|||||||
@@ -98,6 +98,7 @@ function ManagementList() {
|
|||||||
const [welfareBenefitsEnum, setWelfareBenefitsEnum] = useState<any>([]);
|
const [welfareBenefitsEnum, setWelfareBenefitsEnum] = useState<any>([]);
|
||||||
const [workScheduleEnum, setWorkScheduleEnum] = useState<any>([]);
|
const [workScheduleEnum, setWorkScheduleEnum] = useState<any>([]);
|
||||||
const [keyPopulationsEnum, setKeyPopulationsEnum] = useState<any>([]);
|
const [keyPopulationsEnum, setKeyPopulationsEnum] = useState<any>([]);
|
||||||
|
const [jobFeatureEnum, setJobFeatureEnum] = useState<any>([]);
|
||||||
const [currentRow, setCurrentRow] = useState<API.ManagementList.Manage>();
|
const [currentRow, setCurrentRow] = useState<API.ManagementList.Manage>();
|
||||||
const [modalVisible, setModalVisible] = useState<boolean>(false);
|
const [modalVisible, setModalVisible] = useState<boolean>(false);
|
||||||
const [mode, setMode] = useState<'view' | 'edit' | 'create'>('create');
|
const [mode, setMode] = useState<'view' | 'edit' | 'create'>('create');
|
||||||
@@ -132,6 +133,9 @@ function ManagementList() {
|
|||||||
getDictValueEnum('kp_type', false, true).then((data) => {
|
getDictValueEnum('kp_type', false, true).then((data) => {
|
||||||
setKeyPopulationsEnum(data);
|
setKeyPopulationsEnum(data);
|
||||||
});
|
});
|
||||||
|
getDictValueEnum('job_feature', false, true).then((data) => {
|
||||||
|
setJobFeatureEnum(data);
|
||||||
|
});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
async function changeRelease(record: API.ManagementList.Manage) {
|
async function changeRelease(record: API.ManagementList.Manage) {
|
||||||
@@ -541,6 +545,7 @@ function ManagementList() {
|
|||||||
welfareBenefitsEnum={welfareBenefitsEnum}
|
welfareBenefitsEnum={welfareBenefitsEnum}
|
||||||
workScheduleEnum={workScheduleEnum}
|
workScheduleEnum={workScheduleEnum}
|
||||||
keyPopulationsEnum={keyPopulationsEnum}
|
keyPopulationsEnum={keyPopulationsEnum}
|
||||||
|
jobFeatureEnum={jobFeatureEnum}
|
||||||
></EditManageRow>
|
></EditManageRow>
|
||||||
</Fragment>
|
</Fragment>
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user