Skip to content

Commit

Permalink
feat(sidepanel): add some job chart,company chart for home page
Browse files Browse the repository at this point in the history
  • Loading branch information
lastsunday committed Nov 20, 2024
1 parent 168e00b commit ec59d9a
Show file tree
Hide file tree
Showing 14 changed files with 1,030 additions and 228 deletions.
18 changes: 18 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,23 @@
# CHANGELOG

## WIP

### ⭐ Added

1. (Sidepanel)首页新增统计图表
1. 职位发布时间分析(按月)
2. 职位发布时间分析(按周)
3. 职位发布时间分析(按日)
4. 职位发布时间分析(按小时)
5. 职位发布平台分析
6. 公司成立年份分段分析
7. 公司社保人数分段分析

### ✏️ Changed

1. (Sidepanel)为任务统计图表添加Data Zoom slider。
2. (Sidepanel)将最近查看职位移至个人助理-浏览历史。

## 1.31.0(2024-11-20)

### ⭐ Added
Expand Down
46 changes: 46 additions & 0 deletions src/common/api/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,29 @@ export const JobApi = {
let result = await invoke(this.jobTagStatistic.name, {});
return result.data;
},

/**
*
* @param {*} param
* @returns []
*/
jobStatisticGrouByPublishDate: async function (param, { invokeEnv } = { invokeEnv: CONTENT_SCRIPT }) {
let result = await invoke(this.jobStatisticGrouByPublishDate
.name, param, { invokeEnv: invokeEnv });
return result.data;
},

/**
*
* @param {*} param
* @returns []
*/
jobStatisticGrouByPlatform: async function (param, { invokeEnv } = { invokeEnv: CONTENT_SCRIPT }) {
let result = await invoke(this.jobStatisticGrouByPlatform
.name, param, { invokeEnv: invokeEnv });
return result.data;
},

};

export const CompanyApi = {
Expand Down Expand Up @@ -401,6 +424,29 @@ export const CompanyApi = {
deleteCompanyTagByCompanyIds: async function (param) {
return await invoke(this.deleteCompanyTagByCompanyIds.name, param);
},

/**
*
* @param {*} param
* @returns []
*/
companyStatisticGrouByStartDate: async function (param, { invokeEnv } = { invokeEnv: CONTENT_SCRIPT }) {
let result = await invoke(this.companyStatisticGrouByStartDate
.name, param, { invokeEnv: invokeEnv });
return result.data;
},

/**
*
* @param {*} param
* @returns []
*/
companyStatisticGrouByInsurance: async function (param, { invokeEnv } = { invokeEnv: CONTENT_SCRIPT }) {
let result = await invoke(this.companyStatisticGrouByInsurance
.name, param, { invokeEnv: invokeEnv });
return result.data;
},

};

export const TagApi = {
Expand Down
15 changes: 15 additions & 0 deletions src/common/data/bo/JobStatisticGrouByPublishDateBO.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
export class JobStatisticGrouByPublishDateBO{
/**
* month,week,day,hour,
*/
type;

constructor(type){
this.type = type;
}
}

export const TYPE_ENUM_MONTH = "TYPE_ENUM_MONTH";
export const TYPE_ENUM_WEEK = "TYPE_ENUM_WEEK";
export const TYPE_ENUM_DAY = "TYPE_ENUM_DAY";
export const TYPE_ENUM_HOUR = "TYPE_ENUM_HOUR";
4 changes: 4 additions & 0 deletions src/common/data/dto/chartBasicDTO.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export class ChartBasicDTO{
name;
total;
}
13 changes: 13 additions & 0 deletions src/common/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -232,4 +232,17 @@ export function paramsToObject(entries) {
result[key] = value;
}
return result;
}

// Function to convert a long number to an abbreviated string using Intl.NumberFormat
export function convertToAbbreviation(number) {
// Create a new Intl.NumberFormat object with options
const formatter = new Intl.NumberFormat('en', {
notation: 'compact',
compactDisplay: 'short',
maximumSignificantDigits: 3
});

// Format the number and return the result
return formatter.format(number);
}
126 changes: 117 additions & 9 deletions src/offscreen/service/companyService.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import { Message } from "../../common/api/message";
import { postSuccessMessage, postErrorMessage } from "../util";
import { getDb, getOne } from "../database";
import { Company } from "../../common/data/domain/company";
import { convertEmptyStringToNull, isNotEmpty,dateToStr } from "../../common/utils";
import dayjs from "dayjs";
import { Message } from "../../common/api/message";
import { CompanyBO } from "../../common/data/bo/companyBO";
import { SearchCompanyBO } from "../../common/data/bo/searchCompanyBO";
import { SearchCompanyDTO } from "../../common/data/dto/searchCompanyDTO";
import { Company } from "../../common/data/domain/company";
import { ChartBasicDTO } from "../../common/data/dto/chartBasicDTO";
import { CompanyDTO } from "../../common/data/dto/companyDTO";
import { SearchCompanyDTO } from "../../common/data/dto/searchCompanyDTO";
import { StatisticCompanyDTO } from "../../common/data/dto/statisticCompanyDTO";
import { toHump, toLine } from "../../common/utils";
import { _getAllCompanyTagDTOByCompanyIds } from "./companyTagService";
import { CompanyBO } from "../../common/data/bo/companyBO";
import { convertEmptyStringToNull, dateToStr, isNotEmpty, toHump, toLine } from "../../common/utils";
import { getDb, getOne } from "../database";
import { postErrorMessage, postSuccessMessage } from "../util";
import { BaseService } from "./baseService";
import { _getAllCompanyTagDTOByCompanyIds } from "./companyTagService";

const SERVICE_INSTANCE = new BaseService("company", "company_id",
() => {
Expand Down Expand Up @@ -246,8 +246,116 @@ export const CompanyService = {
companyGetByIds: async function (message, param) {
SERVICE_INSTANCE.getByIds(message, param);
},

/**
*
* @param {Message} message
* @param {*} param
*/
companyStatisticGrouByStartDate: async function (message, param) {
try {
let sql = `SELECT
t2.level AS name,
COUNT(t2.level) AS total
FROM
(
SELECT
(CASE
WHEN t1.offsetValue<1 THEN '<1'
WHEN t1.offsetValue >= 1
AND t1.offsetValue<3 THEN '1-3'
WHEN t1.offsetValue >= 3
AND t1.offsetValue<5 THEN '3-5'
WHEN t1.offsetValue >= 5
AND t1.offsetValue<10 THEN '5-10'
WHEN t1.offsetValue >= 10
AND t1.offsetValue<20 THEN '10-20'
ELSE '>20'
END) AS level
FROM
(
SELECT
(STRFTIME('%Y', 'now') - STRFTIME('%Y', company_start_date)) AS offsetValue
FROM
company
) AS t1
) AS t2
GROUP BY
name;`;
let result = await companyStatistic({ sql });
postSuccessMessage(message, result);
} catch (e) {
postErrorMessage(
message,
"[worker] companyStatisticGrouByStartDate error : " + e.message
);
}
},

/**
* 统计社保人数
* @param {Message} message
* @param {*} param
*/
companyStatisticGrouByInsurance: async function (message, param) {
try {
let sql = `SELECT
t2.level AS name,
COUNT(t2.level) AS total
FROM
(
SELECT
(CASE
WHEN t1.offsetValue IS NULL THEN '-'
WHEN t1.offsetValue<10 THEN '<10'
WHEN t1.offsetValue >= 10
AND t1.offsetValue<20 THEN '10-20'
WHEN t1.offsetValue >= 20
AND t1.offsetValue<50 THEN '20-50'
WHEN t1.offsetValue >= 50
AND t1.offsetValue<100 THEN '50-100'
WHEN t1.offsetValue >= 100
AND t1.offsetValue<500 THEN '100-500'
WHEN t1.offsetValue >= 500
AND t1.offsetValue<1000 THEN '500-1000'
ELSE '>1000'
END) AS level
FROM
(
SELECT
company_insurance_num AS offsetValue
FROM
company
) AS t1
) AS t2
GROUP BY
name;
`;
let result = await companyStatistic({ sql });
postSuccessMessage(message, result);
} catch (e) {
postErrorMessage(
message,
"[worker] companyStatisticGrouByInsurance error : " + e.message
);
}
},
};

async function companyStatistic({ sql }) {
let result = [];
let resultRows = [];
(await getDb()).exec({
sql,
rowMode: "object",
resultRows
});
resultRows.forEach(item => {
result.push(Object.assign(new ChartBasicDTO(), item));
});
return result;
}

/**
*
* @param {Company} param
Expand Down
67 changes: 67 additions & 0 deletions src/offscreen/service/jobService.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import { _getAllCompanyTagDTOByCompanyIds } from "./companyTagService";
import { _getCompanyDTOByIds } from "./companyService";
import { BaseService } from "./baseService";
import { _getAllJobTagDTOByJobIds } from "./jobTagService";
import { ChartBasicDTO } from "../../common/data/dto/chartBasicDTO";
import { JobStatisticGrouByPublishDateBO, TYPE_ENUM_MONTH, TYPE_ENUM_WEEK, TYPE_ENUM_DAY, TYPE_ENUM_HOUR } from "../../common/data/bo/JobStatisticGrouByPublishDateBO";

const JOB_VISIT_TYPE_SEARCH = "SEARCH";
const JOB_VISIT_TYPE_DETAIL = "DETAIL";
Expand Down Expand Up @@ -401,8 +403,73 @@ export const JobService = {
jobGetByIds: async function (message, param) {
SERVICE_INSTANCE.getByIds(message, param);
},

/**
*
* @param {Message} message
* @param {JobStatisticGrouByPublishDateBO} param
*/
jobStatisticGrouByPublishDate: async function (message, param) {
try {
let sql = `SELECT STRFTIME('${convertEnum(param.type)}', job_first_publish_datetime) AS name,COUNT(*) AS total FROM job WHERE job_first_publish_datetime NOT NULL GROUP BY name;`;
let result = await jobStatistic({ sql });
postSuccessMessage(message, result);
} catch (e) {
postErrorMessage(
message,
"[worker] jobStatisticGrouByPublishDate error : " + e.message
);
}
},

/**
*
* @param {Message} message
* @param {*} param
*/
jobStatisticGrouByPlatform: async function (message, param) {
try {
let sql = `SELECT job_platform AS name,COUNT(*) AS total FROM job GROUP BY name;`;
let result = await jobStatistic({ sql });
postSuccessMessage(message, result);
} catch (e) {
postErrorMessage(
message,
"[worker] jobStatisticGrouByPlatform error : " + e.message
);
}
},

};

const convertEnum = (value) => {
if (TYPE_ENUM_MONTH == value) {
return "%m";
} else if (TYPE_ENUM_WEEK == value) {
return "%w";
} else if (TYPE_ENUM_DAY == value) {
return "%d";
} else if (TYPE_ENUM_HOUR == value) {
return "%H";
} else {
throw `unknow type = ${value}`
}
}

async function jobStatistic({ sql }) {
let result = [];
let resultRows = [];
(await getDb()).exec({
sql,
rowMode: "object",
resultRows
});
resultRows.forEach(item => {
result.push(Object.assign(new ChartBasicDTO(), item));
});
return result;
}

export async function _getByIds(ids) {
return SERVICE_INSTANCE._getByIds(ids);
}
Expand Down
4 changes: 3 additions & 1 deletion src/sidepanel/components/JobItemCard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,8 @@
</div>
<div class="address">
<div class="label">{{ item.jobAddress }}</div>
<el-link v-if="item.jobLongitude && item.jobLatitude" type="primary" @click="emits('mapLocate')">
<el-link v-if="item.jobLongitude && item.jobLatitude && !props.hiddenLocator" type="primary"
@click="emits('mapLocate')">
<Icon icon="mdi:location" />定位
</el-link>
</div>
Expand Down Expand Up @@ -344,6 +345,7 @@ const { platformFormat, platformLogo } = useJob()
const props = defineProps({
item: JobDTO,
hiddenLocator: Boolean,
});
const emits = defineEmits(["mapLocate"]);
const item = ref({});
Expand Down
Loading

0 comments on commit ec59d9a

Please sign in to comment.