flat: 暂存
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import { Card, Select, Spin, Empty, Row, Col } from 'antd';
|
||||
import { Line, Bar, Pie, Heatmap } from '@ant-design/charts';
|
||||
import { Card, Empty, Select, Spin } from 'antd';
|
||||
import { Bar, Heatmap, Line, Pie } from '@ant-design/charts';
|
||||
|
||||
export const IndustryTrendCard = ({
|
||||
loading,
|
||||
@@ -38,11 +38,7 @@ export const IndustryTrendCard = ({
|
||||
<Empty
|
||||
image={Empty.PRESENTED_IMAGE_SIMPLE}
|
||||
description={
|
||||
loading
|
||||
? '数据加载中...'
|
||||
: selectedIndustry
|
||||
? '当前时间段无数据'
|
||||
: '请先选择行业'
|
||||
loading ? '数据加载中...' : selectedIndustry ? '当前时间段无数据' : '请先选择行业'
|
||||
}
|
||||
/>
|
||||
)}
|
||||
@@ -192,7 +188,6 @@ export const EducationCard = ({
|
||||
placeholder="选择学历要求"
|
||||
disabled={availableEducationLevels.length === 0}
|
||||
>
|
||||
<Option value="">全部学历</Option>
|
||||
{availableEducationLevels.map((level) => (
|
||||
<Option key={level} value={level}>
|
||||
{level}
|
||||
|
||||
@@ -241,7 +241,7 @@ export const getSalaryChartConfig = (currentSalaryData: any[]): ChartConfig => (
|
||||
|
||||
export const getWorkYearPieConfig = (workYearData: any[], selectedWorkYearRange: string) => {
|
||||
const filteredData = workYearData
|
||||
.filter((item) => item.category === selectedWorkYearRange)
|
||||
.filter((item) => selectedWorkYearRange === '全部' || item.category === selectedWorkYearRange)
|
||||
.map((item) => ({
|
||||
...item,
|
||||
date: formatDateForDisplay(item.date, '月'),
|
||||
@@ -394,7 +394,7 @@ export const getEducationBarConfig = (educationData: any[], selectedEducationLev
|
||||
}
|
||||
|
||||
const timeData = cleanEducationData
|
||||
.filter((item) => item.category === selectedEducationLevel)
|
||||
.filter((item) => selectedEducationLevel === '全部' || item.category === selectedEducationLevel)
|
||||
.sort((a, b) => {
|
||||
const dateA = dayjs(a.date, 'YYYY年MM月').valueOf();
|
||||
const dateB = dayjs(b.date, 'YYYY年MM月').valueOf();
|
||||
|
||||
@@ -1,43 +1,36 @@
|
||||
import React, { useEffect, useState, useMemo, useRef } from 'react';
|
||||
import { Card, Select, Button, Space, Spin, Empty, Row, Col, message, DatePicker } from 'antd';
|
||||
import { Line, Bar, Pie, Heatmap } from '@ant-design/charts';
|
||||
import React, { useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { Button, Card, Col, DatePicker, message, Row, Select, Space } from 'antd';
|
||||
import {
|
||||
getIndustryTrend,
|
||||
getEducationTrend,
|
||||
getIndustryAreaTrend,
|
||||
getIndustryTrend,
|
||||
getSalaryTrend,
|
||||
getWorkYearTrend,
|
||||
getEducationTrend,
|
||||
} from '@/services/analysis/industry';
|
||||
import dayjs from 'dayjs';
|
||||
import { useRequest } from '@umijs/max';
|
||||
import { IndustryDataItem, IndustryTrendState, TimeDimension } from '@/types/analysis/industry';
|
||||
import {
|
||||
TimeDimension,
|
||||
AnalysisType,
|
||||
IndustryTrendState,
|
||||
IndustryDataItem,
|
||||
ChartConfig,
|
||||
} from '@/types/analysis/industry';
|
||||
import {
|
||||
formatQuarter,
|
||||
formatDateForDisplay,
|
||||
convertApiData,
|
||||
convertEducationData,
|
||||
convertSalaryData,
|
||||
convertWorkYearData,
|
||||
convertEducationData,
|
||||
formatDateForDisplay,
|
||||
formatQuarter,
|
||||
} from './utils';
|
||||
import {
|
||||
getEducationBarConfig,
|
||||
getHeatmapConfig,
|
||||
getIndustryChartConfig,
|
||||
getSalaryChartConfig,
|
||||
getWorkYearPieConfig,
|
||||
getEducationBarConfig,
|
||||
} from './components/chartconfigs';
|
||||
import {
|
||||
IndustryTrendCard,
|
||||
AreaAnalysisCard,
|
||||
EducationCard,
|
||||
IndustryTrendCard,
|
||||
SalaryTrendCard,
|
||||
WorkYearCard,
|
||||
EducationCard,
|
||||
} from './components/chartcards';
|
||||
|
||||
const { Option } = Select;
|
||||
@@ -186,7 +179,7 @@ const IndustryTrendPage: React.FC = () => {
|
||||
const extractNumber = (str: string) => parseInt(str.replace(/[^0-9]/g, '') || 0);
|
||||
return extractNumber(a) - extractNumber(b);
|
||||
});
|
||||
|
||||
ranges.unshift('全部');
|
||||
setAvailableSalaryRanges(ranges);
|
||||
|
||||
if (ranges.length > 0 && !ranges.includes(params.selectedSalaryRange)) {
|
||||
@@ -226,7 +219,7 @@ const IndustryTrendPage: React.FC = () => {
|
||||
const order = ['应届', '1-3年', '3-5年', '5年以上'];
|
||||
return order.indexOf(a) - order.indexOf(b);
|
||||
});
|
||||
|
||||
ranges.unshift('全部');
|
||||
setAvailableWorkYearRanges(ranges);
|
||||
if (ranges.length > 0 && !ranges.includes(params.selectedWorkYearRange)) {
|
||||
setParams((p) => ({ ...p, selectedWorkYearRange: ranges[0] }));
|
||||
@@ -265,7 +258,7 @@ const IndustryTrendPage: React.FC = () => {
|
||||
const order = ['不限', '初中及以下', '中专/中技', '大专', '本科', '硕士', '博士'];
|
||||
return order.indexOf(a) - order.indexOf(b);
|
||||
});
|
||||
|
||||
levels.unshift('全部');
|
||||
setAvailableEducationLevels(levels);
|
||||
if (levels.length > 0 && !levels.includes(selectedEducationLevel)) {
|
||||
setSelectedEducationLevel(levels[0]);
|
||||
@@ -326,9 +319,11 @@ const IndustryTrendPage: React.FC = () => {
|
||||
|
||||
const currentSalaryData = useMemo(() => {
|
||||
if (!params.selectedSalaryRange || salaryData.length === 0) return [];
|
||||
|
||||
return salaryData
|
||||
.filter((item) => item.category === params.selectedSalaryRange)
|
||||
.filter(
|
||||
(item) =>
|
||||
params.selectedSalaryRange === '全部' || item.category === params.selectedSalaryRange,
|
||||
)
|
||||
.map((item) => ({
|
||||
...item,
|
||||
originalDate: item.date,
|
||||
@@ -537,7 +532,6 @@ const IndustryTrendPage: React.FC = () => {
|
||||
}
|
||||
/>
|
||||
</Col>
|
||||
|
||||
{/* 工作经验和学历要求 - 中等屏幕下分成两列 */}
|
||||
<Col xs={24} md={12} lg={12}>
|
||||
<WorkYearCard
|
||||
@@ -546,9 +540,9 @@ const IndustryTrendPage: React.FC = () => {
|
||||
config={workYearPieConfig}
|
||||
availableWorkYearRanges={availableWorkYearRanges}
|
||||
selectedWorkYearRange={params.selectedWorkYearRange}
|
||||
onWorkYearRangeChange={(value) =>
|
||||
setParams((p) => ({ ...p, selectedWorkYearRange: value }))
|
||||
}
|
||||
onWorkYearRangeChange={(value) => {
|
||||
return setParams((p) => ({ ...p, selectedWorkYearRange: value }));
|
||||
}}
|
||||
/>
|
||||
</Col>
|
||||
<Col xs={24} md={12} lg={12}>
|
||||
|
||||
197
src/pages/Analysis/User/components/AreaStatics.tsx
Normal file
197
src/pages/Analysis/User/components/AreaStatics.tsx
Normal file
@@ -0,0 +1,197 @@
|
||||
import React, { useState, useEffect, useCallback } from 'react';
|
||||
import { Table, Card, Select } from 'antd';
|
||||
import { getUserStaticsByArea } from '@/services/analysis/user';
|
||||
import { Pie, Column } from '@ant-design/charts';
|
||||
export default function AreaStatics({ data }) {
|
||||
const [selectedArea, setSelectedArea] = useState('');
|
||||
const [byArea, setByArea] = useState({});
|
||||
|
||||
useEffect(() => {
|
||||
if (data.length > 0) {
|
||||
setSelectedArea(data[0].dictValue);
|
||||
fetchAreaStatics(data[0].dictValue);
|
||||
}
|
||||
}, [data]);
|
||||
|
||||
const fetchAreaStatics = async (areaCode) => {
|
||||
const resData = await getUserStaticsByArea(areaCode);
|
||||
if (resData.code === 200) {
|
||||
const data = {
|
||||
gender: transformNum(resData.data.gender),
|
||||
education: transformNum(resData.data.education),
|
||||
position: transformNum(resData.data.position),
|
||||
salary: transformNum(resData.data.salary),
|
||||
age: transformNum(resData.data.age),
|
||||
};
|
||||
console.log(data.education);
|
||||
setByArea(data);
|
||||
}
|
||||
};
|
||||
|
||||
const transformNum = useCallback((datas) => {
|
||||
return datas.map((item) => ({ ...item, data: parseInt(item.data) }));
|
||||
}, []);
|
||||
|
||||
const handleAreaChange = (value) => {
|
||||
setSelectedArea(value);
|
||||
fetchAreaStatics(value);
|
||||
};
|
||||
|
||||
const educationColumns = [
|
||||
{ title: '学历', dataIndex: 'name', key: 'name' },
|
||||
{ title: '数量', dataIndex: 'data', key: 'data' },
|
||||
];
|
||||
|
||||
const genderColumns = [
|
||||
{ title: '性别', dataIndex: 'name', key: 'name' },
|
||||
{ title: '数量', dataIndex: 'data', key: 'data' },
|
||||
];
|
||||
|
||||
const positionColumns = [
|
||||
{ title: '求职岗位', dataIndex: 'name', key: 'name' },
|
||||
{ title: '数量', dataIndex: 'data', key: 'data' },
|
||||
];
|
||||
|
||||
const salaryColumns = [
|
||||
{ title: '期望薪资', dataIndex: 'name', key: 'name' },
|
||||
{ title: '数量', dataIndex: 'data', key: 'data' },
|
||||
];
|
||||
|
||||
const ageColumns = [
|
||||
{ title: '年龄阶段', dataIndex: 'name', key: 'name' },
|
||||
{ title: '数量', dataIndex: 'data', key: 'data' },
|
||||
];
|
||||
|
||||
return (
|
||||
<div style={{ padding: '8px' }}>
|
||||
<Card title="区域用户统计" style={{ marginBottom: '8px' }}>
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
gap: '16px',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
}}
|
||||
>
|
||||
<div>
|
||||
<Select
|
||||
style={{ width: '200px', marginBottom: '8px' }}
|
||||
placeholder="选择区域"
|
||||
onChange={handleAreaChange}
|
||||
value={selectedArea}
|
||||
>
|
||||
{data.map((item) => (
|
||||
<Select.Option key={item.dictValue} value={item.dictValue}>
|
||||
{item.dictLabel}
|
||||
</Select.Option>
|
||||
))}
|
||||
</Select>
|
||||
</div>
|
||||
<div>
|
||||
{byArea.gender && byArea.gender.length > 0 ? (
|
||||
<div style={{ display: 'flex', flexWrap: 'nowrap', gap: '16px' }}>
|
||||
<div style={{ display: 'flex', flexWrap: 'nowrap' }}>
|
||||
<h4>用户数量: </h4> {byArea.gender.reduce((acc, cur) => acc + cur.data, 0)}
|
||||
</div>
|
||||
<div>男性: {byArea.gender.find((item) => item.name === '男')?.data || 0}</div>
|
||||
<div>女性: {byArea.gender.find((item) => item.name === '女')?.data || 0}</div>
|
||||
</div>
|
||||
) : (
|
||||
<div>暂无数据</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)', gap: '8px' }}>
|
||||
<Card title="学历分布" style={{ marginBottom: '8px' }}>
|
||||
<Column
|
||||
data={byArea.education}
|
||||
xField="name"
|
||||
yField="data"
|
||||
label={{
|
||||
text: (d) => `${d.data}人`,
|
||||
textBaseline: 'bottom',
|
||||
}}
|
||||
axis={{
|
||||
y: {
|
||||
label: {
|
||||
formatter: (v) => `${v}k`,
|
||||
},
|
||||
},
|
||||
}}
|
||||
style={{
|
||||
radiusTopLeft: 3,
|
||||
radiusTopRight: 3,
|
||||
columnWidthRatio: 0.6,
|
||||
inset: 0.5,
|
||||
}}
|
||||
/>
|
||||
</Card>
|
||||
|
||||
<Card
|
||||
title="求职岗位排行"
|
||||
style={{ marginBottom: '8px', height: '600px', overflowY: 'auto' }}
|
||||
>
|
||||
<Table
|
||||
columns={positionColumns}
|
||||
dataSource={byArea.position}
|
||||
pagination={false}
|
||||
rowKey="name"
|
||||
size="small"
|
||||
scroll={{ y: 440 }}
|
||||
/>
|
||||
</Card>
|
||||
|
||||
<Card title="期望薪资阶段" style={{ marginBottom: '8px' }}>
|
||||
<Column
|
||||
data={byArea.salary}
|
||||
xField="name"
|
||||
yField="data"
|
||||
label={{
|
||||
text: (d) => `${d.data}人`,
|
||||
textBaseline: 'bottom',
|
||||
}}
|
||||
axis={{
|
||||
y: {
|
||||
label: {
|
||||
formatter: (v) => `${v}k`,
|
||||
},
|
||||
},
|
||||
}}
|
||||
style={{
|
||||
radiusTopLeft: 3,
|
||||
radiusTopRight: 3,
|
||||
columnWidthRatio: 0.6,
|
||||
inset: 0.5,
|
||||
}}
|
||||
/>
|
||||
</Card>
|
||||
|
||||
<Card title="年龄阶段分布">
|
||||
<Column
|
||||
data={byArea.age}
|
||||
xField="name"
|
||||
yField="data"
|
||||
label={{
|
||||
text: (d) => `${d.data}人`,
|
||||
textBaseline: 'bottom',
|
||||
}}
|
||||
axis={{
|
||||
y: {
|
||||
label: {
|
||||
formatter: (v) => `${v}k`,
|
||||
},
|
||||
},
|
||||
}}
|
||||
style={{
|
||||
radiusTopLeft: 5,
|
||||
radiusTopRight: 5,
|
||||
columnWidthRatio: 0.3,
|
||||
inset: 0.5,
|
||||
}}
|
||||
/>
|
||||
</Card>
|
||||
</div>
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
98
src/pages/Analysis/User/components/KeywordChart.tsx
Normal file
98
src/pages/Analysis/User/components/KeywordChart.tsx
Normal file
@@ -0,0 +1,98 @@
|
||||
import React, { useCallback, useEffect, useState } from 'react';
|
||||
import { Column } from '@ant-design/charts';
|
||||
import { getKeyWordSearchRank } from '@/services/analysis/user';
|
||||
|
||||
interface KeywordChartProps {
|
||||
data?: any[];
|
||||
}
|
||||
|
||||
export default function KeywordChart({ data: initialData }: KeywordChartProps) {
|
||||
const [data, setData] = useState(initialData || []);
|
||||
|
||||
const fetchData = useCallback(
|
||||
async (params?: { searchDate?: string; searchCount?: number; searchType?: 1 | 2 | 3 }) => {
|
||||
const resData = await getKeyWordSearchRank({
|
||||
searchDate: params?.searchDate || '2025-11-03',
|
||||
// searchCount: params?.searchCount || 4,
|
||||
searchType: params?.searchType || 3,
|
||||
});
|
||||
if (resData.code === 200) {
|
||||
setData(resData.rows);
|
||||
}
|
||||
},
|
||||
[],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
fetchData();
|
||||
}, [fetchData]);
|
||||
const config = {
|
||||
data,
|
||||
xField: 'keyWord',
|
||||
yField: 'searchCount',
|
||||
height: 350,
|
||||
label: {
|
||||
position: 'middle',
|
||||
style: {
|
||||
fill: '#FFFFFF',
|
||||
opacity: 0.6,
|
||||
},
|
||||
},
|
||||
xAxis: {
|
||||
label: {
|
||||
autoHide: true,
|
||||
autoRotate: false,
|
||||
},
|
||||
},
|
||||
meta: {
|
||||
keyWord: { alias: '关键词' },
|
||||
searchCount: { alias: '搜索次数' },
|
||||
},
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<div style={{ display: 'flex', alignItems: 'center', marginBottom: 16 }}>
|
||||
<h3 style={{ marginRight: 16 }}>查询关键词搜索排行</h3>
|
||||
<select
|
||||
onChange={(e) => {
|
||||
fetchData({
|
||||
searchDate: '2025-11-03',
|
||||
searchCount: 10,
|
||||
searchType: Number(e.target.value) as 1 | 2 | 3,
|
||||
});
|
||||
}}
|
||||
defaultValue="3"
|
||||
>
|
||||
<option value="1">日</option>
|
||||
<option value="2">周</option>
|
||||
<option value="3">月</option>
|
||||
</select>
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
height: '400px',
|
||||
overflowY: 'auto',
|
||||
border: '1px solid #eee',
|
||||
borderRadius: '4px',
|
||||
padding: '8px',
|
||||
}}
|
||||
>
|
||||
{data?.map((item, index) => (
|
||||
<div
|
||||
key={index}
|
||||
style={{
|
||||
padding: '8px',
|
||||
borderBottom: '1px solid #eee',
|
||||
display: 'flex',
|
||||
justifyContent: 'space-around',
|
||||
}}
|
||||
>
|
||||
<span>关键词:{item.keyWord}</span>
|
||||
<span>搜索次数:{item.searchCount}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
84
src/pages/Analysis/User/components/WantedPositionStatics.tsx
Normal file
84
src/pages/Analysis/User/components/WantedPositionStatics.tsx
Normal file
@@ -0,0 +1,84 @@
|
||||
import React, { useState, useEffect, useCallback } from 'react';
|
||||
import { getWantedPositionStaticsCount } from '@/services/analysis/user';
|
||||
import { Card, Table } from 'antd';
|
||||
|
||||
interface PositionStatics {
|
||||
jobName: string;
|
||||
count: number;
|
||||
}
|
||||
|
||||
interface getWantedPositionStaticsCountStaticsResult {
|
||||
male: PositionStatics[];
|
||||
female: PositionStatics[];
|
||||
}
|
||||
|
||||
const WantedPositionStatics: React.FC = () => {
|
||||
const [staticsData, setStaticsData] = useState<StaticsResult>({ male: [], female: [] });
|
||||
|
||||
const fetchStatics = useCallback(async () => {
|
||||
const resData = await getWantedPositionStaticsCount({ sexCode: 0 });
|
||||
if (resData.code === 200) {
|
||||
const malePositions: Record<string, number> = {};
|
||||
const femalePositions: Record<string, number> = {};
|
||||
|
||||
resData.data.forEach((item) => {
|
||||
if (item.sexCode === '男') {
|
||||
malePositions[item.jobName] = (malePositions[item.jobName] || 0) + 1;
|
||||
} else if (item.sexCode === '女') {
|
||||
femalePositions[item.jobName] = (femalePositions[item.jobName] || 0) + 1;
|
||||
}
|
||||
});
|
||||
|
||||
const result: StaticsResult = {
|
||||
male: Object.entries(malePositions).map(([jobName, count]) => ({ jobName, count })),
|
||||
female: Object.entries(femalePositions).map(([jobName, count]) => ({ jobName, count })),
|
||||
};
|
||||
|
||||
setStaticsData(result);
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
fetchStatics();
|
||||
}, [fetchStatics]);
|
||||
|
||||
const columns = [
|
||||
{
|
||||
title: '岗位名称',
|
||||
dataIndex: 'jobName',
|
||||
key: 'jobName',
|
||||
},
|
||||
{
|
||||
title: '数量',
|
||||
dataIndex: 'count',
|
||||
key: 'count',
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<div style={{ padding: '8px', display: 'flex', width: '100%', height: '100%' }}>
|
||||
<Card title="男性用户期望岗位统计" style={{ width: '50%' }}>
|
||||
<Table
|
||||
columns={columns}
|
||||
dataSource={staticsData.male}
|
||||
pagination={false}
|
||||
rowKey="jobName"
|
||||
size="small"
|
||||
scroll={{ y: 440 }}
|
||||
/>
|
||||
</Card>
|
||||
<Card title="女性用户期望岗位统计" style={{ width: '50%' }}>
|
||||
<Table
|
||||
columns={columns}
|
||||
dataSource={staticsData.female}
|
||||
pagination={false}
|
||||
rowKey="jobName"
|
||||
size="small"
|
||||
scroll={{ y: 440 }}
|
||||
/>
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default WantedPositionStatics;
|
||||
@@ -1 +1,60 @@
|
||||
<button>111111111111</button>
|
||||
import React, { useCallback, useEffect, useState } from 'react';
|
||||
import {
|
||||
getUserLoginCountStatics,
|
||||
getWantedPositionStaticsCount,
|
||||
getUserStaticsByArea,
|
||||
getPercentOfResumeCompletionRate,
|
||||
} from '@/services/analysis/user';
|
||||
import KeywordChart from './components/KeywordChart';
|
||||
import { getDictDataList } from '@/services/system/dictdata';
|
||||
import AreaStatics from './components/AreaStatics';
|
||||
import WantedPositionStatics from './components/WantedPositionStatics';
|
||||
|
||||
export default function userAnalysis() {
|
||||
const [data, setData] = useState([]);
|
||||
|
||||
const [PofrcRate, setPofrcRate] = useState([]);
|
||||
const [areaDict, setAreaDict] = useState([]);
|
||||
|
||||
useEffect(() => {
|
||||
// loginCounts();
|
||||
dictDataList();
|
||||
percentOfResumeCompletionRate();
|
||||
}, []);
|
||||
|
||||
const loginCounts = useCallback(async () => {
|
||||
let resData = await getUserLoginCountStatics();
|
||||
console.log(resData);
|
||||
}, []);
|
||||
|
||||
const dictDataList = useCallback(async () => {
|
||||
let resData = await getDictDataList({ dictType: 'area' });
|
||||
if (resData.code === 200) {
|
||||
setAreaDict(resData.rows);
|
||||
}
|
||||
}, []);
|
||||
|
||||
const percentOfResumeCompletionRate = useCallback(async () => {
|
||||
let resData = await getPercentOfResumeCompletionRate();
|
||||
if (resData.code === 200) {
|
||||
console.log(resData.data);
|
||||
setPofrcRate(resData.data);
|
||||
}
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div style={{ padding: '16px' }}>
|
||||
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)', gap: '16px' }}>
|
||||
<div style={{ width: '100%' }}>
|
||||
<KeywordChart />
|
||||
</div>
|
||||
<div style={{ width: '100%' }}>
|
||||
<WantedPositionStatics />
|
||||
</div>
|
||||
</div>
|
||||
<div style={{ width: '100%' }}>
|
||||
<AreaStatics data={areaDict} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ const SubWayEdit: React.FC<ListFormProps> = (props) => {
|
||||
company: string;
|
||||
stationOrder: number;
|
||||
}>
|
||||
title={`${props.values ? '编辑' : '新增'}站点`}
|
||||
title={`${props.values ? '编辑' : '新增'}商圈`}
|
||||
form={form}
|
||||
// layout="inline"
|
||||
autoFocusFirstInput
|
||||
|
||||
@@ -47,7 +47,7 @@ const SubWayEdit: React.FC<ListFormProps> = (props) => {
|
||||
name: string;
|
||||
company: string;
|
||||
}>
|
||||
title={`${props.values ? '编辑' : '新增'}线路`}
|
||||
title={`${props.values ? '编辑' : '新增'}区域`}
|
||||
form={form}
|
||||
// layout="inline"
|
||||
autoFocusFirstInput
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import React, { Fragment, useEffect, useRef, useState } from 'react';
|
||||
import { FormattedMessage, useAccess } from '@umijs/max';
|
||||
import { Button, FormInstance, message, Modal, Descriptions } from 'antd';
|
||||
import { Button, Descriptions, FormInstance, message, Modal } from 'antd';
|
||||
import { ActionType, ProColumns, ProTable } from '@ant-design/pro-components';
|
||||
import { DeleteOutlined, FormOutlined, PlusOutlined, EyeOutlined, AlignLeftOutlined } from '@ant-design/icons';
|
||||
import { AlignLeftOutlined, DeleteOutlined, FormOutlined, PlusOutlined } from '@ant-design/icons';
|
||||
import EditCompanyListRow from './edit';
|
||||
import {
|
||||
addCmsCompanyList,
|
||||
@@ -19,7 +19,7 @@ const CompanyDetailModal = ({
|
||||
visible,
|
||||
onCancel,
|
||||
record,
|
||||
scaleEnum
|
||||
scaleEnum,
|
||||
}: {
|
||||
visible: boolean;
|
||||
onCancel: () => void;
|
||||
@@ -107,12 +107,13 @@ function ManagementList() {
|
||||
valueType: 'text',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
title: '公司行业',
|
||||
dataIndex: 'industry',
|
||||
valueType: 'text',
|
||||
align: 'center',
|
||||
},
|
||||
// {
|
||||
// title: '公司行业',
|
||||
// hideInSearch: true,
|
||||
// dataIndex: 'industry',
|
||||
// valueType: 'text',
|
||||
// align: 'center',
|
||||
// },
|
||||
{
|
||||
title: '公司规模',
|
||||
dataIndex: 'scale',
|
||||
|
||||
@@ -106,13 +106,13 @@ function ManagementList() {
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
title: '最小薪资',
|
||||
title: '最小薪资(元/月)',
|
||||
dataIndex: 'minSalary',
|
||||
valueType: 'text',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
title: '最大薪资',
|
||||
title: '最大薪资(元/月)',
|
||||
dataIndex: 'maxSalary',
|
||||
valueType: 'text',
|
||||
align: 'center',
|
||||
|
||||
43
src/services/analysis/user.ts
Normal file
43
src/services/analysis/user.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
import { request } from '@umijs/max';
|
||||
|
||||
// 行业
|
||||
export async function getUserLoginCountStatics(params?: API.Analysis.IndustryParams) {
|
||||
return request<API.Analysis.User>('/api/cms/statics/getUserLoginCountStatics', {
|
||||
method: 'GET',
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// 查询关键词搜索排行
|
||||
export async function getKeyWordSearchRank(params?: {
|
||||
searchDate?: string;
|
||||
searchCount?: number;
|
||||
searchType?: 1 | 2 | 3;
|
||||
}) {
|
||||
return request<API.Analysis.User>('/api/cms/statics/getKeyWordSearchRank', {
|
||||
method: 'GET',
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
// 统计男性和女性用户偏好的期望岗位
|
||||
export async function getWantedPositionStaticsCount(params?: API.Analysis.IndustryParams) {
|
||||
return request<API.Analysis.User>('/api/cms/statics/getWantedPositionStaticsCount', {
|
||||
method: 'GET',
|
||||
params,
|
||||
});
|
||||
}
|
||||
// 获取区域内的用户类别统计
|
||||
export async function getUserStaticsByArea(area: string) {
|
||||
return request<API.Analysis.User>(`/api/cms/statics/getUserStaticsByArea/${area}`, {
|
||||
method: 'GET',
|
||||
});
|
||||
}
|
||||
// 获取区域内的用户类别统计
|
||||
export async function getPercentOfResumeCompletionRate(params?: API.Analysis.IndustryParams) {
|
||||
return request<API.Analysis.User>(`/api/app/user/getPercentOfResumeCompletionRate`, {
|
||||
method: 'GET',
|
||||
params,
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user