这两批改动此前一直压在工作区未提交,本次一并归档。go build ./... 通过。
一、招聘爬虫健壮性
- 新增 internal/service/recruitment/source_config.go:
crawl_source.config(VARCHAR(1000) JSON)的源级抓取参数解析 —— 增量窗口天数、
单次详情页上限、最大翻页数、详情间隔限速、自定义标准词/排除词。
全部字段可选,JSON 解析失败即回退默认值,保证历史数据零迁移可用,
且一个源的脏配置不会拖垮整个调度。
- 新增 internal/service/recruitment/keywords.go(含 keywords_test.go 与 testdata/):
链接筛选由「URL 形态命中 AND 文本语义命中」改为评分制 —— URL 形态加分、
标准词加分、排除词大幅减分,达阈值即入选。原与逻辑会系统性漏抓
「补充工作人员的通知」「公开选调公务员简章」等标题变体,且静默无报错。
- 新增 manifest/sql/recruitment/004_crawl_source_status.sql:
crawl_source 增加「最近一次运行状态」冗余列,抓取结束时写入,
使 Sources() 查询零 JOIN 零扫描 —— 规避原实现全表扫描只增不减的 crawl_log、
随运行时间线性劣化的问题。幂等,可重复执行。
- internal/service/recruitment/crawler.go:在既有「静态两级 / SPA / curl 回退」
流程上做锚点抽取与过滤、编码回退的健壮性增强。
- internal/service/recruitment/bark.go、recruitment.go:配合上述调整。
二、通知记录增强
- api/notice、internal/controller/notice、internal/service/notice、
internal/model/{dto,entity,do}/notice.go:通知日志查询与操作扩展 ——
批次号、状态、重试次数、来源、耗时、详情、删除、清空。
- 新增 internal/model/dto/notice_meta.go(字典选项元数据,供前端筛选器取选项)。
- 新增 manifest/sql/017_notice_log_enhance.sql:notice_log 扩展列 +
删除/清空/详情/字典选项接口权限,幂等(ALTER 走 information_schema 判断,
菜单 ON DUPLICATE KEY UPDATE,角色绑定 INSERT IGNORE)。
三、仓库卫生
- .gitignore 补 rc_*.log 与 rc_verify*,挡掉本地离线验证产物
(含 30MB 的 rc_verify.exe),避免误入库。
设计依据见 docs/recruitment-crawler-design.md。
注:017 与 recruitment/004 两个 SQL 为增量迁移,DB 结构变更不自动 DDL,
生产库需手动导入。
99 lines
7.3 KiB
Go
99 lines
7.3 KiB
Go
// Package entity 定义招聘考试聚合模块的数据表结构(手写,未跑 gf gen)。
|
||
// 字段命名对齐 service 现有约定:json 用驼峰,orm 用下划线。
|
||
package entity
|
||
|
||
import "github.com/gogf/gf/v2/os/gtime"
|
||
|
||
// RecruitmentInfo 招聘考试公告主表。
|
||
type RecruitmentInfo struct {
|
||
Id uint64 `json:"id" orm:"id" description:"主键"`
|
||
Title string `json:"title" orm:"title" description:"公告标题"`
|
||
SourceId uint64 `json:"sourceId" orm:"source_id" description:"数据源ID"`
|
||
OrgId uint64 `json:"orgId" orm:"org_id" description:"发布主体ID"`
|
||
OrgName string `json:"orgName" orm:"org_name" description:"发布主体名称(冗余便于展示)"`
|
||
Category int `json:"category" orm:"category" description:"考试分类 1公务员 2事业单位 3国企 4央企 5私企 6其他"`
|
||
Region string `json:"region" orm:"region" description:"地区(贵阳/省直/其他市州)"`
|
||
PublishDate string `json:"publishDate" orm:"publish_date" description:"发布日期"`
|
||
Deadline string `json:"deadline" orm:"deadline" description:"报名/截止日期"`
|
||
ExamDate string `json:"examDate" orm:"exam_date" description:"笔试日期"`
|
||
Url string `json:"url" orm:"url" description:"原文链接"`
|
||
Content string `json:"content" orm:"content" description:"正文/摘要"`
|
||
Attachments string `json:"attachments" orm:"attachments" description:"附件链接与解析结果(JSON)"`
|
||
Status int `json:"status" orm:"status" description:"0有效 1已更正 2已失效 3已删除"`
|
||
Fingerprint string `json:"fingerprint" orm:"fingerprint" description:"去重指纹"`
|
||
GroupKey string `json:"groupKey" orm:"group_key" description:"跨源同公告聚合键"`
|
||
CreatedAt string `json:"createdAt" orm:"created_at" description:"入库时间"`
|
||
UpdatedAt string `json:"updatedAt" orm:"updated_at" description:"更新时间"`
|
||
}
|
||
|
||
// Organization 发布主体(机关/事业单位/国企/央企/私企)。
|
||
type Organization struct {
|
||
Id uint64 `json:"id" orm:"id" description:"主键"`
|
||
Name string `json:"name" orm:"name" description:"主体名称"`
|
||
Type int `json:"type" orm:"type" description:"主体类型 1机关 2事业 3国企 4央企 5私企 6其他"`
|
||
OfficialSite string `json:"officialSite" orm:"official_site" description:"官网"`
|
||
Region string `json:"region" orm:"region" description:"地区"`
|
||
CreatedAt string `json:"createdAt" orm:"created_at" description:"创建时间"`
|
||
UpdatedAt string `json:"updatedAt" orm:"updated_at" description:"更新时间"`
|
||
}
|
||
|
||
// CrawlSource 数据源配置(插件化爬虫适配器)。
|
||
type CrawlSource struct {
|
||
Id uint64 `json:"id" orm:"id" description:"主键"`
|
||
Name string `json:"name" orm:"name" description:"数据源名称"`
|
||
BaseUrl string `json:"baseUrl" orm:"base_url" description:"站点基础URL"`
|
||
SourceType int `json:"sourceType" orm:"source_type" description:"1静态列表 2SPA 3需登录 4附件型"`
|
||
Category int `json:"category" orm:"category" description:"该源默认考试分类"`
|
||
Region string `json:"region" orm:"region" description:"该源默认地区"`
|
||
ListPath string `json:"listPath" orm:"list_path" description:"列表页路径/接口"`
|
||
Config string `json:"config" orm:"config" description:"适配器扩展配置(JSON)"`
|
||
Enabled int `json:"enabled" orm:"enabled" description:"是否启用 0否 1是"`
|
||
CronExpr string `json:"cronExpr" orm:"cron_expr" description:"调度表达式(可选)"`
|
||
LastSuccessAt string `json:"lastSuccessAt" orm:"last_success_at" description:"最近成功抓取时间"`
|
||
FailCount int `json:"failCount" orm:"fail_count" description:"连续失败次数"`
|
||
LastLogAt *gtime.Time `json:"lastLogAt" orm:"last_log_at" description:"最近一次抓取时间(冗余)"`
|
||
LastLogFetched int `json:"lastLogFetched" orm:"last_log_fetched" description:"最近一次抓取条数(冗余)"`
|
||
LastLogNew int `json:"lastLogNew" orm:"last_log_new" description:"最近一次新增条数(冗余)"`
|
||
LastLogError string `json:"lastLogError" orm:"last_log_error" description:"最近一次错误信息(冗余)"`
|
||
CreatedAt string `json:"createdAt" orm:"created_at" description:"创建时间"`
|
||
UpdatedAt string `json:"updatedAt" orm:"updated_at" description:"更新时间"`
|
||
}
|
||
|
||
// CrawlLog 抓取任务运行日志。
|
||
type CrawlLog struct {
|
||
Id uint64 `json:"id" orm:"id" description:"主键"`
|
||
SourceId uint64 `json:"sourceId" orm:"source_id" description:"数据源ID"`
|
||
RunAt string `json:"runAt" orm:"run_at" description:"运行时间"`
|
||
Fetched int `json:"fetched" orm:"fetched" description:"本次抓取条数"`
|
||
NewCount int `json:"newCount" orm:"new_count" description:"新增条数"`
|
||
UpdatedCount int `json:"updatedCount" orm:"updated_count" description:"更新条数"`
|
||
Error string `json:"error" orm:"error" description:"错误信息"`
|
||
CreatedAt string `json:"createdAt" orm:"created_at" description:"创建时间"`
|
||
}
|
||
|
||
// PushSubscription Bark 推送订阅配置。
|
||
type PushSubscription struct {
|
||
Id uint64 `json:"id" orm:"id" description:"主键"`
|
||
Name string `json:"name" orm:"name" description:"订阅名称"`
|
||
DeviceKey string `json:"deviceKey" orm:"device_key" description:"Bark 设备密钥"`
|
||
Regions string `json:"regions" orm:"regions" description:"订阅地区(JSON数组)"`
|
||
Categories string `json:"categories" orm:"categories" description:"订阅分类(JSON数组)"`
|
||
OnlyNew int `json:"onlyNew" orm:"only_new" description:"仅推送新公告 0否 1是"`
|
||
PushTime string `json:"pushTime" orm:"push_time" description:"推送时间 HH:mm"`
|
||
Enabled int `json:"enabled" orm:"enabled" description:"是否启用 0否 1是"`
|
||
CreatedAt string `json:"createdAt" orm:"created_at" description:"创建时间"`
|
||
UpdatedAt string `json:"updatedAt" orm:"updated_at" description:"更新时间"`
|
||
}
|
||
|
||
// PushLog 推送记录。
|
||
type PushLog struct {
|
||
Id uint64 `json:"id" orm:"id" description:"主键"`
|
||
SubscriptionId uint64 `json:"subscriptionId" orm:"subscription_id" description:"订阅ID"`
|
||
PushAt string `json:"pushAt" orm:"push_at" description:"推送时间"`
|
||
Title string `json:"title" orm:"title" description:"推送标题"`
|
||
Body string `json:"body" orm:"body" description:"推送内容"`
|
||
Result int `json:"result" orm:"result" description:"1成功 0失败"`
|
||
Error string `json:"error" orm:"error" description:"错误信息"`
|
||
CreatedAt string `json:"createdAt" orm:"created_at" description:"创建时间"`
|
||
}
|