@reconcrap/boss-recommend-mcp 2.1.23 → 2.1.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/README.md +5 -0
  2. package/bin/boss-recommend-mcp.js +4 -4
  3. package/package.json +6 -1
  4. package/scripts/install-macos.sh +280 -280
  5. package/scripts/postinstall.cjs +44 -44
  6. package/skills/boss-chat/README.md +43 -42
  7. package/skills/boss-chat/SKILL.md +107 -106
  8. package/skills/boss-recommend-pipeline/README.md +13 -13
  9. package/skills/boss-recommend-pipeline/SKILL.md +47 -47
  10. package/skills/boss-recruit-pipeline/README.md +19 -19
  11. package/skills/boss-recruit-pipeline/SKILL.md +89 -89
  12. package/src/chat-mcp.js +301 -127
  13. package/src/chat-runtime-config.js +7 -5
  14. package/src/core/boss-cards/index.js +199 -199
  15. package/src/core/browser/index.js +302 -145
  16. package/src/core/capture/index.js +2930 -1201
  17. package/src/core/cv-acquisition/index.js +512 -238
  18. package/src/core/cv-capture-target/index.js +513 -299
  19. package/src/core/greet-quota/index.js +71 -71
  20. package/src/core/infinite-list/index.js +31 -31
  21. package/src/core/reporting/legacy-csv.js +12 -12
  22. package/src/core/run/detached-launcher.js +305 -0
  23. package/src/core/run/index.js +109 -55
  24. package/src/core/run/timing.js +33 -33
  25. package/src/core/run/windows-detached-worker.ps1 +106 -0
  26. package/src/core/screening/index.js +2400 -2135
  27. package/src/core/self-heal/index.js +989 -973
  28. package/src/core/self-heal/viewport.js +1505 -564
  29. package/src/detached-worker.js +99 -99
  30. package/src/domains/chat/action-journal.js +536 -0
  31. package/src/domains/chat/cards.js +137 -137
  32. package/src/domains/chat/constants.js +9 -9
  33. package/src/domains/chat/detail.js +1684 -401
  34. package/src/domains/chat/index.js +8 -7
  35. package/src/domains/chat/jobs.js +620 -620
  36. package/src/domains/chat/page-guard.js +157 -122
  37. package/src/domains/chat/roots.js +56 -56
  38. package/src/domains/chat/run-service.js +1801 -760
  39. package/src/domains/common/account-rights-panel.js +314 -314
  40. package/src/domains/common/recovery-settle.js +159 -159
  41. package/src/domains/recommend/actions.js +1219 -472
  42. package/src/domains/recommend/cards.js +243 -243
  43. package/src/domains/recommend/colleague-contact.js +1079 -333
  44. package/src/domains/recommend/constants.js +92 -92
  45. package/src/domains/recommend/detail.js +4037 -136
  46. package/src/domains/recommend/filters.js +608 -590
  47. package/src/domains/recommend/index.js +9 -9
  48. package/src/domains/recommend/jobs.js +571 -542
  49. package/src/domains/recommend/location.js +754 -707
  50. package/src/domains/recommend/refresh.js +677 -392
  51. package/src/domains/recommend/roots.js +80 -80
  52. package/src/domains/recommend/run-service.js +4048 -1447
  53. package/src/domains/recommend/scopes.js +246 -246
  54. package/src/domains/recruit/actions.js +277 -277
  55. package/src/domains/recruit/cards.js +74 -74
  56. package/src/domains/recruit/constants.js +236 -236
  57. package/src/domains/recruit/detail.js +588 -588
  58. package/src/domains/recruit/index.js +9 -9
  59. package/src/domains/recruit/instruction-parser.js +866 -866
  60. package/src/domains/recruit/refresh.js +45 -45
  61. package/src/domains/recruit/roots.js +68 -68
  62. package/src/domains/recruit/run-service.js +1817 -1620
  63. package/src/domains/recruit/search.js +3229 -3229
  64. package/src/index.js +16 -1
  65. package/src/parser.js +1296 -1296
  66. package/src/recommend-mcp.js +1061 -450
  67. package/src/recommend-scheduler.js +75 -75
@@ -1,74 +1,74 @@
1
- import {
2
- getAttributesMap,
3
- getOuterHTML,
4
- querySelectorAll,
5
- sleep
6
- } from "../../core/browser/index.js";
7
- import { mergeBossCandidateCardFields } from "../../core/boss-cards/index.js";
8
- import { normalizeCandidateFromHtml } from "../../core/screening/index.js";
9
- import { RECRUIT_CARD_SELECTOR } from "./constants.js";
10
-
11
- function mergeRecruitCardFields(candidate, outerHTML = "") {
12
- return mergeBossCandidateCardFields(candidate, outerHTML, {
13
- metadataKey: "search_card_fields"
14
- });
15
- }
16
-
17
- export async function findRecruitCardNodeIds(client, frameNodeId, {
18
- selector = RECRUIT_CARD_SELECTOR
19
- } = {}) {
20
- return querySelectorAll(client, frameNodeId, selector);
21
- }
22
-
23
- export async function waitForRecruitCardNodeIds(client, frameNodeId, {
24
- selector = RECRUIT_CARD_SELECTOR,
25
- timeoutMs = 12000,
26
- intervalMs = 300
27
- } = {}) {
28
- const started = Date.now();
29
- let nodeIds = [];
30
- while (Date.now() - started <= timeoutMs) {
31
- nodeIds = await findRecruitCardNodeIds(client, frameNodeId, { selector });
32
- if (nodeIds.length) return nodeIds;
33
- await sleep(intervalMs);
34
- }
35
- return nodeIds;
36
- }
37
-
38
- export async function readRecruitCardCandidate(client, cardNodeId, {
39
- targetUrl = "",
40
- source = "recruit-domain-card",
41
- metadata = {}
42
- } = {}) {
43
- const [attributes, outerHTML] = await Promise.all([
44
- getAttributesMap(client, cardNodeId),
45
- getOuterHTML(client, cardNodeId)
46
- ]);
47
- const candidate = normalizeCandidateFromHtml({
48
- domain: "recruit",
49
- source,
50
- html: outerHTML,
51
- attributes,
52
- metadata: {
53
- target_url: targetUrl,
54
- card_node_id: cardNodeId,
55
- ...metadata
56
- }
57
- });
58
- return mergeRecruitCardFields(candidate, outerHTML);
59
- }
60
-
61
- export async function readFirstRecruitCardCandidate(client, frameNodeId, options = {}) {
62
- const cardNodeIds = await findRecruitCardNodeIds(client, frameNodeId, options);
63
- if (!cardNodeIds.length) {
64
- throw new Error("No recruit/search candidate cards found");
65
- }
66
-
67
- const candidate = await readRecruitCardCandidate(client, cardNodeIds[0], options);
68
- return {
69
- card_count: cardNodeIds.length,
70
- first_card_node_id: cardNodeIds[0],
71
- card_node_ids: cardNodeIds,
72
- candidate
73
- };
74
- }
1
+ import {
2
+ getAttributesMap,
3
+ getOuterHTML,
4
+ querySelectorAll,
5
+ sleep
6
+ } from "../../core/browser/index.js";
7
+ import { mergeBossCandidateCardFields } from "../../core/boss-cards/index.js";
8
+ import { normalizeCandidateFromHtml } from "../../core/screening/index.js";
9
+ import { RECRUIT_CARD_SELECTOR } from "./constants.js";
10
+
11
+ function mergeRecruitCardFields(candidate, outerHTML = "") {
12
+ return mergeBossCandidateCardFields(candidate, outerHTML, {
13
+ metadataKey: "search_card_fields"
14
+ });
15
+ }
16
+
17
+ export async function findRecruitCardNodeIds(client, frameNodeId, {
18
+ selector = RECRUIT_CARD_SELECTOR
19
+ } = {}) {
20
+ return querySelectorAll(client, frameNodeId, selector);
21
+ }
22
+
23
+ export async function waitForRecruitCardNodeIds(client, frameNodeId, {
24
+ selector = RECRUIT_CARD_SELECTOR,
25
+ timeoutMs = 12000,
26
+ intervalMs = 300
27
+ } = {}) {
28
+ const started = Date.now();
29
+ let nodeIds = [];
30
+ while (Date.now() - started <= timeoutMs) {
31
+ nodeIds = await findRecruitCardNodeIds(client, frameNodeId, { selector });
32
+ if (nodeIds.length) return nodeIds;
33
+ await sleep(intervalMs);
34
+ }
35
+ return nodeIds;
36
+ }
37
+
38
+ export async function readRecruitCardCandidate(client, cardNodeId, {
39
+ targetUrl = "",
40
+ source = "recruit-domain-card",
41
+ metadata = {}
42
+ } = {}) {
43
+ const [attributes, outerHTML] = await Promise.all([
44
+ getAttributesMap(client, cardNodeId),
45
+ getOuterHTML(client, cardNodeId)
46
+ ]);
47
+ const candidate = normalizeCandidateFromHtml({
48
+ domain: "recruit",
49
+ source,
50
+ html: outerHTML,
51
+ attributes,
52
+ metadata: {
53
+ target_url: targetUrl,
54
+ card_node_id: cardNodeId,
55
+ ...metadata
56
+ }
57
+ });
58
+ return mergeRecruitCardFields(candidate, outerHTML);
59
+ }
60
+
61
+ export async function readFirstRecruitCardCandidate(client, frameNodeId, options = {}) {
62
+ const cardNodeIds = await findRecruitCardNodeIds(client, frameNodeId, options);
63
+ if (!cardNodeIds.length) {
64
+ throw new Error("No recruit/search candidate cards found");
65
+ }
66
+
67
+ const candidate = await readRecruitCardCandidate(client, cardNodeIds[0], options);
68
+ return {
69
+ card_count: cardNodeIds.length,
70
+ first_card_node_id: cardNodeIds[0],
71
+ card_node_ids: cardNodeIds,
72
+ candidate
73
+ };
74
+ }
@@ -1,236 +1,236 @@
1
- export const RECRUIT_TARGET_URL = "https://www.zhipin.com/web/chat/search";
2
-
3
- export const RECRUIT_IFRAME_SELECTORS = Object.freeze([
4
- 'iframe[name="searchFrame"]',
5
- 'iframe[src*="/web/frame/search/"]',
6
- "iframe"
7
- ]);
8
-
9
- export const RECRUIT_CARD_SELECTOR = [
10
- "li.geek-info-card a[data-jid]",
11
- "li.geek-info-card a[data-geekid]",
12
- ".geek-info-card a[data-jid]",
13
- ".geek-info-card a[data-geekid]",
14
- ".geek-info-card a",
15
- "a[data-jid]",
16
- "a[data-geekid]"
17
- ].join(", ");
18
-
19
- export const RECRUIT_LIST_CONTAINER_SELECTORS = Object.freeze([
20
- ".search-list",
21
- ".search-result-list",
22
- ".candidate-list",
23
- ".geek-list",
24
- ".geek-list-wrap",
25
- ".card-list",
26
- ".list-wrap",
27
- ".search-content",
28
- ".search-container"
29
- ]);
30
-
31
- export const RECRUIT_NO_DATA_SELECTORS = Object.freeze([
32
- "i.tip-nodata",
33
- ".tip-nodata",
34
- ".empty-tip",
35
- ".empty-text",
36
- '[class*="empty"]'
37
- ]);
38
-
39
- export const RECRUIT_BOTTOM_MARKER_SELECTORS = Object.freeze([
40
- ".finished-wrap",
41
- ".loadmore",
42
- ".load-tips",
43
- ".tip-nodata",
44
- ".empty-tip",
45
- ".empty-text",
46
- ".no-data",
47
- "[class*=\"finished\"]",
48
- "[class*=\"loadmore\"]",
49
- "[class*=\"load-tips\"]",
50
- "[class*=\"empty\"]"
51
- ]);
52
-
53
- export const RECRUIT_BOTTOM_REFRESH_SELECTORS = Object.freeze([
54
- ".finished-wrap .btn-refresh",
55
- ".finished-wrap .btn",
56
- ".no-data-refresh .btn-refresh",
57
- ".no-data-refresh .btn",
58
- "[class*=\"refresh\"]",
59
- "[ka*=\"refresh\"]",
60
- "button",
61
- "a"
62
- ]);
63
-
64
- export const RECRUIT_SEARCH_SELECTORS = Object.freeze({
65
- keywordInput: [
66
- "input.search-input",
67
- ".search-box input",
68
- ".search-wrap input",
69
- 'input[placeholder*="搜索"]',
70
- "input"
71
- ],
72
- searchButton: [
73
- ".icon-search",
74
- ".search-btn",
75
- 'button[ka*="search"]',
76
- '[class*="search"][class*="btn"]'
77
- ],
78
- jobTitleTrigger: [
79
- ".search-job-list-C .ui-dropmenu",
80
- ".search-job-list-C .ui-dropmenu-label",
81
- ".search-job-list-C .search-current-job",
82
- ".search-job-list-C"
83
- ],
84
- jobTitleOption: [
85
- '.search-job-list-C li[ka="search_select_job"]',
86
- ".search-job-list-C li",
87
- '[ka="search_select_job"]'
88
- ],
89
- degreeOption: [
90
- ".degree-list-C .degree-item",
91
- ".degree-list-C li",
92
- ".degree-item",
93
- '[ka*="degree"]'
94
- ],
95
- schoolItem: [
96
- ".school-item",
97
- ".school-list-C .school-item",
98
- ".school-list-C li",
99
- '[class*="school"][class*="item"]'
100
- ],
101
- schoolClickable: [
102
- "label.checkbox",
103
- "label",
104
- ".checkbox",
105
- ".checkbox-text"
106
- ],
107
- recentViewedLabel: [
108
- 'label.checkbox.high_search_checkbox[ka="search_change_view_resume"]',
109
- "label.checkbox.high_search_checkbox",
110
- "label.checkbox",
111
- '[ka="search_change_view_resume"]'
112
- ],
113
- exchangeResumeLabel: [
114
- 'label.checkbox.high_search_checkbox[ka="search_change_exchange_resume"]',
115
- '[ka="search_change_exchange_resume"]'
116
- ],
117
- experienceOption: [
118
- ".experience-select .exp-item",
119
- ".experience-select li",
120
- ".exp-list-ui .exp-item",
121
- '[class*="experience"] [class*="exp-item"]'
122
- ],
123
- experienceCustom: [
124
- ".experience-select .custom",
125
- ".experience-select .custom-wrap",
126
- ".experience-select-custom-slider",
127
- '[class*="experience"] [class*="custom"]'
128
- ],
129
- experienceCustomSlider: [
130
- ".experience-select .experience-select-custom-slider .ui-slider-wrap",
131
- ".experience-select .ui-slider-wrap",
132
- ".experience-select-custom-slider .ui-slider-wrap"
133
- ],
134
- experienceCustomSliderHandle: [
135
- ".experience-select .experience-select-custom-slider .ui-slider-button-wrap",
136
- ".experience-select .ui-slider-button-wrap",
137
- ".experience-select-custom-slider .ui-slider-button-wrap"
138
- ],
139
- experienceCustomHiddenInput: [
140
- ".experience-select .experience-select-custom-slider input[type='hidden']",
141
- ".experience-select input[type='hidden']",
142
- ".experience-select-custom-slider input[type='hidden']"
143
- ],
144
- ageOption: [
145
- ".age-select .age-item",
146
- ".age-list-ui .age-item",
147
- '[class*="age"] [class*="age-item"]'
148
- ],
149
- ageCustom: [
150
- ".age-select .custom",
151
- ".age-select .age-custom",
152
- '[class*="age"] [class*="custom"]'
153
- ],
154
- ageCustomDropdown: [
155
- ".age-select .age-custom .dropdown-wrap.select"
156
- ],
157
- ageCustomOption: [
158
- ".age-select .age-custom li",
159
- ".age-select .age-custom .dropdown-menu li"
160
- ],
161
- ageCustomInput: [
162
- ".age-select .age-custom input"
163
- ],
164
- genderDropdown: [
165
- ".gender-select"
166
- ],
167
- genderOption: [
168
- ".gender-select.dropdown-menu-open li",
169
- ".gender-select .dropdown-menu li"
170
- ],
171
- cityTrigger: [
172
- ".city-wrap .city",
173
- ".city-wrap",
174
- ".search-wrap .city-wrap"
175
- ],
176
- cityInput: [
177
- ".city-wrap .search-city-kw input",
178
- ".search-city-kw input",
179
- ".city-wrap input",
180
- 'input[placeholder*="城市"]'
181
- ],
182
- citySearchResult: [
183
- ".city-box .search-result-C .search-result-item",
184
- ".search-result-C .search-result-item",
185
- ".city-box li",
186
- ".dropdown-city li"
187
- ],
188
- cityProvinceItem: [
189
- ".dropdown-province li"
190
- ],
191
- cityDropdownItem: [
192
- ".dropdown-city li"
193
- ]
194
- });
195
-
196
- export const RECRUIT_DETAIL_POPUP_SELECTORS = Object.freeze([
197
- ".dialog-wrap.active",
198
- ".boss-popup__wrapper",
199
- ".boss-popup_wrapper",
200
- ".boss-dialog_wrapper",
201
- ".boss-dialog",
202
- ".resume-item-detail",
203
- ".geek-detail-modal",
204
- ".resume-container",
205
- '[class*="popup"][class*="wrapper"]',
206
- '[class*="dialog"][class*="wrapper"]'
207
- ]);
208
-
209
- export const RECRUIT_DETAIL_RESUME_IFRAME_SELECTORS = Object.freeze([
210
- 'iframe[src*="/web/frame/c-resume/"]',
211
- 'iframe[name*="resume"]'
212
- ]);
213
-
214
- export const RECRUIT_DETAIL_CLOSE_SELECTORS = Object.freeze([
215
- ".boss-popup__close",
216
- ".popup-close",
217
- ".modal-close",
218
- ".dialog-close",
219
- ".close-btn",
220
- 'button[aria-label*="关闭"]',
221
- 'button[title*="关闭"]',
222
- ".icon-close",
223
- '[aria-label*="关闭"]',
224
- '[title*="关闭"]',
225
- '[class*="close"]'
226
- ]);
227
-
228
- export const RECRUIT_DETAIL_NETWORK_PATTERNS = Object.freeze([
229
- /\/wapi\/zpitem\/web\/boss\/search\/geek\/info\b/i,
230
- /\/wapi\/zpjob\/view\/geek\/info(?:\/v2)?\b/i,
231
- /\/wapi\/zpitem\/web\/boss\/[^?#]*\/geek\/info\b/i,
232
- /\/boss\/[^?#]*\/geek\/info\b/i,
233
- /\/geek\/info\b/i,
234
- /\/web\/frame\/c-resume\//i,
235
- /resume/i
236
- ]);
1
+ export const RECRUIT_TARGET_URL = "https://www.zhipin.com/web/chat/search";
2
+
3
+ export const RECRUIT_IFRAME_SELECTORS = Object.freeze([
4
+ 'iframe[name="searchFrame"]',
5
+ 'iframe[src*="/web/frame/search/"]',
6
+ "iframe"
7
+ ]);
8
+
9
+ export const RECRUIT_CARD_SELECTOR = [
10
+ "li.geek-info-card a[data-jid]",
11
+ "li.geek-info-card a[data-geekid]",
12
+ ".geek-info-card a[data-jid]",
13
+ ".geek-info-card a[data-geekid]",
14
+ ".geek-info-card a",
15
+ "a[data-jid]",
16
+ "a[data-geekid]"
17
+ ].join(", ");
18
+
19
+ export const RECRUIT_LIST_CONTAINER_SELECTORS = Object.freeze([
20
+ ".search-list",
21
+ ".search-result-list",
22
+ ".candidate-list",
23
+ ".geek-list",
24
+ ".geek-list-wrap",
25
+ ".card-list",
26
+ ".list-wrap",
27
+ ".search-content",
28
+ ".search-container"
29
+ ]);
30
+
31
+ export const RECRUIT_NO_DATA_SELECTORS = Object.freeze([
32
+ "i.tip-nodata",
33
+ ".tip-nodata",
34
+ ".empty-tip",
35
+ ".empty-text",
36
+ '[class*="empty"]'
37
+ ]);
38
+
39
+ export const RECRUIT_BOTTOM_MARKER_SELECTORS = Object.freeze([
40
+ ".finished-wrap",
41
+ ".loadmore",
42
+ ".load-tips",
43
+ ".tip-nodata",
44
+ ".empty-tip",
45
+ ".empty-text",
46
+ ".no-data",
47
+ "[class*=\"finished\"]",
48
+ "[class*=\"loadmore\"]",
49
+ "[class*=\"load-tips\"]",
50
+ "[class*=\"empty\"]"
51
+ ]);
52
+
53
+ export const RECRUIT_BOTTOM_REFRESH_SELECTORS = Object.freeze([
54
+ ".finished-wrap .btn-refresh",
55
+ ".finished-wrap .btn",
56
+ ".no-data-refresh .btn-refresh",
57
+ ".no-data-refresh .btn",
58
+ "[class*=\"refresh\"]",
59
+ "[ka*=\"refresh\"]",
60
+ "button",
61
+ "a"
62
+ ]);
63
+
64
+ export const RECRUIT_SEARCH_SELECTORS = Object.freeze({
65
+ keywordInput: [
66
+ "input.search-input",
67
+ ".search-box input",
68
+ ".search-wrap input",
69
+ 'input[placeholder*="搜索"]',
70
+ "input"
71
+ ],
72
+ searchButton: [
73
+ ".icon-search",
74
+ ".search-btn",
75
+ 'button[ka*="search"]',
76
+ '[class*="search"][class*="btn"]'
77
+ ],
78
+ jobTitleTrigger: [
79
+ ".search-job-list-C .ui-dropmenu",
80
+ ".search-job-list-C .ui-dropmenu-label",
81
+ ".search-job-list-C .search-current-job",
82
+ ".search-job-list-C"
83
+ ],
84
+ jobTitleOption: [
85
+ '.search-job-list-C li[ka="search_select_job"]',
86
+ ".search-job-list-C li",
87
+ '[ka="search_select_job"]'
88
+ ],
89
+ degreeOption: [
90
+ ".degree-list-C .degree-item",
91
+ ".degree-list-C li",
92
+ ".degree-item",
93
+ '[ka*="degree"]'
94
+ ],
95
+ schoolItem: [
96
+ ".school-item",
97
+ ".school-list-C .school-item",
98
+ ".school-list-C li",
99
+ '[class*="school"][class*="item"]'
100
+ ],
101
+ schoolClickable: [
102
+ "label.checkbox",
103
+ "label",
104
+ ".checkbox",
105
+ ".checkbox-text"
106
+ ],
107
+ recentViewedLabel: [
108
+ 'label.checkbox.high_search_checkbox[ka="search_change_view_resume"]',
109
+ "label.checkbox.high_search_checkbox",
110
+ "label.checkbox",
111
+ '[ka="search_change_view_resume"]'
112
+ ],
113
+ exchangeResumeLabel: [
114
+ 'label.checkbox.high_search_checkbox[ka="search_change_exchange_resume"]',
115
+ '[ka="search_change_exchange_resume"]'
116
+ ],
117
+ experienceOption: [
118
+ ".experience-select .exp-item",
119
+ ".experience-select li",
120
+ ".exp-list-ui .exp-item",
121
+ '[class*="experience"] [class*="exp-item"]'
122
+ ],
123
+ experienceCustom: [
124
+ ".experience-select .custom",
125
+ ".experience-select .custom-wrap",
126
+ ".experience-select-custom-slider",
127
+ '[class*="experience"] [class*="custom"]'
128
+ ],
129
+ experienceCustomSlider: [
130
+ ".experience-select .experience-select-custom-slider .ui-slider-wrap",
131
+ ".experience-select .ui-slider-wrap",
132
+ ".experience-select-custom-slider .ui-slider-wrap"
133
+ ],
134
+ experienceCustomSliderHandle: [
135
+ ".experience-select .experience-select-custom-slider .ui-slider-button-wrap",
136
+ ".experience-select .ui-slider-button-wrap",
137
+ ".experience-select-custom-slider .ui-slider-button-wrap"
138
+ ],
139
+ experienceCustomHiddenInput: [
140
+ ".experience-select .experience-select-custom-slider input[type='hidden']",
141
+ ".experience-select input[type='hidden']",
142
+ ".experience-select-custom-slider input[type='hidden']"
143
+ ],
144
+ ageOption: [
145
+ ".age-select .age-item",
146
+ ".age-list-ui .age-item",
147
+ '[class*="age"] [class*="age-item"]'
148
+ ],
149
+ ageCustom: [
150
+ ".age-select .custom",
151
+ ".age-select .age-custom",
152
+ '[class*="age"] [class*="custom"]'
153
+ ],
154
+ ageCustomDropdown: [
155
+ ".age-select .age-custom .dropdown-wrap.select"
156
+ ],
157
+ ageCustomOption: [
158
+ ".age-select .age-custom li",
159
+ ".age-select .age-custom .dropdown-menu li"
160
+ ],
161
+ ageCustomInput: [
162
+ ".age-select .age-custom input"
163
+ ],
164
+ genderDropdown: [
165
+ ".gender-select"
166
+ ],
167
+ genderOption: [
168
+ ".gender-select.dropdown-menu-open li",
169
+ ".gender-select .dropdown-menu li"
170
+ ],
171
+ cityTrigger: [
172
+ ".city-wrap .city",
173
+ ".city-wrap",
174
+ ".search-wrap .city-wrap"
175
+ ],
176
+ cityInput: [
177
+ ".city-wrap .search-city-kw input",
178
+ ".search-city-kw input",
179
+ ".city-wrap input",
180
+ 'input[placeholder*="城市"]'
181
+ ],
182
+ citySearchResult: [
183
+ ".city-box .search-result-C .search-result-item",
184
+ ".search-result-C .search-result-item",
185
+ ".city-box li",
186
+ ".dropdown-city li"
187
+ ],
188
+ cityProvinceItem: [
189
+ ".dropdown-province li"
190
+ ],
191
+ cityDropdownItem: [
192
+ ".dropdown-city li"
193
+ ]
194
+ });
195
+
196
+ export const RECRUIT_DETAIL_POPUP_SELECTORS = Object.freeze([
197
+ ".dialog-wrap.active",
198
+ ".boss-popup__wrapper",
199
+ ".boss-popup_wrapper",
200
+ ".boss-dialog_wrapper",
201
+ ".boss-dialog",
202
+ ".resume-item-detail",
203
+ ".geek-detail-modal",
204
+ ".resume-container",
205
+ '[class*="popup"][class*="wrapper"]',
206
+ '[class*="dialog"][class*="wrapper"]'
207
+ ]);
208
+
209
+ export const RECRUIT_DETAIL_RESUME_IFRAME_SELECTORS = Object.freeze([
210
+ 'iframe[src*="/web/frame/c-resume/"]',
211
+ 'iframe[name*="resume"]'
212
+ ]);
213
+
214
+ export const RECRUIT_DETAIL_CLOSE_SELECTORS = Object.freeze([
215
+ ".boss-popup__close",
216
+ ".popup-close",
217
+ ".modal-close",
218
+ ".dialog-close",
219
+ ".close-btn",
220
+ 'button[aria-label*="关闭"]',
221
+ 'button[title*="关闭"]',
222
+ ".icon-close",
223
+ '[aria-label*="关闭"]',
224
+ '[title*="关闭"]',
225
+ '[class*="close"]'
226
+ ]);
227
+
228
+ export const RECRUIT_DETAIL_NETWORK_PATTERNS = Object.freeze([
229
+ /\/wapi\/zpitem\/web\/boss\/search\/geek\/info\b/i,
230
+ /\/wapi\/zpjob\/view\/geek\/info(?:\/v2)?\b/i,
231
+ /\/wapi\/zpitem\/web\/boss\/[^?#]*\/geek\/info\b/i,
232
+ /\/boss\/[^?#]*\/geek\/info\b/i,
233
+ /\/geek\/info\b/i,
234
+ /\/web\/frame\/c-resume\//i,
235
+ /resume/i
236
+ ]);