104-sourcing
npx skills add https://github.com/kevin-shu/104-sourcing --skill 104-sourcing
Agent 安装分布
Skill 文档
104 HR 人ææå°
æ¦è¦½
æ¬ Skill ä½¿ç¨ agent-browser CLI æ§å¶ç覽å¨ï¼èªåç»å ¥ 104 æå管çå¹³å°ä¸¦æå°åé©äººé¸ãå·è¡æµç¨åä¸åéæ®µï¼éæ±è¨ªè« â ç»å ¥ â ç´ API æå°ç¯©é¸ã
ä¾è³´å·¥å ·ï¼æ¬ Skill éè¦
agent-browserCLIï¼å®è£æ¹å¼è¦ frontmatter çcompatibilityæ¬ä½ã æä»¤åèï¼references/agent-browser.md
æ¶æ§ååï¼éè¦ï¼
- ç»å ¥ç¨ browserï¼å ¶é¤å ¨ç¨ APIï¼ç覽å¨åªç¨ä¾å»ºç« session cookieï¼æå°/篩é¸/è©ä¼°å ¨é¨èµ° APIï¼é度快 100 å以ä¸
- ææ fetch å¿ é å¨ä¸» sessionï¼104-sourcingï¼å §å¼å«ï¼Subagent çç¨ç« session ç¡æ³å ±ç¨ç»å ¥ cookie
- eval åªè½ç¨ ES5 èªæ³ï¼
varä¸è½ç¨const/letï¼ä¸è½ç¨ arrow functionï¼å¦å eval æå ±é¯
第ä¸é段ï¼éæ±è¨ªè«
å¨éåç覽å¨åï¼å¿ é å éé訪è«äºè§£æåéæ±ï¼ä¸å¾åè¨æè·³éã訪è«åå ©å±¤ï¼
åºæ¬æ¢ä»¶ï¼ç¡¬æ§ç¯©é¸ç¨ï¼
- è·ä½å稱ï¼è¦æå°ä»éº¼è·åï¼ï¼ä¾ï¼é»é·ãæ¥åãå·¥ç¨å¸«ï¼
- å·¥ä½å°é»ï¼åé¸äººå¯æ¥åçå·¥ä½å°é»ï¼ï¼ä¾ï¼å°åå¸ãæ°å叿¿æ©åï¼
- 硬æ§è¦æ±ï¼æåªäºå¿ è¦æ¢ä»¶ï¼ï¼ä¾ï¼å·¥ä½å¹´è³ã叿·ãç¹å®æè½æèç §ï¼
- å¾
æ¥çæ³ï¼æ¯å¦åªçç¹å®å°±æ¥çæ
çæ±è·è
ï¼ï¼é è¨ä¸éï¼
- ä¸éï¼
empStatus=0 - å¨è·ä¸ï¼æ³è·³æ§½ï¼ï¼
empStatus=1 - å¾
æ¥ä¸ï¼å³å¯ä¸çï¼ï¼
empStatus=2
- ä¸éï¼
è³ªæ§æ¢ä»¶ï¼ç¯©é¸å¾è©ä¼°ç¨ï¼
- çæ³åé¸äººæ¨£è²ï¼éåè·ä½æéè¦ä»éº¼ç¹è³ªæèæ¯ï¼æåªäºéå¾ç¶æ·ç¹å¥å åï¼
- å°é·ï¼æåªäºçæ³è¦æé¤ï¼ï¼ä¾ï¼é »ç¹æå·¥ä½ãç¹å®ç¢æ¥èæ¯ãå·¥ä½ç©ºçªéé·ï¼
- å åé ç®ï¼å ¶ä» nice-to-haveï¼ï¼ä¾ï¼å ·åç¹å®è»é«æä½ç¶é©ãèªè¨è½åï¼
訪è«çµæå¾ï¼æ´ç並åè¦ãæå°çç¥ç¢ºèªãï¼
- æå°ééµåï¼ç¨æ¼ API ç
kws忏 - 硬æ§ç¯©é¸æ¢ä»¶ï¼JS éæ¿¾é輯ç便
- 質æ§è©ä¼°æ¨æºï¼çå®åé¸äººè³æå¾æåç便
ç¨æ¶ç¢ºèªå¾ï¼åé²å ¥ç¬¬äºé段ã
第äºé段ï¼ååç覽å¨ä¸¦ç¢ºèªç»å ¥çæ
ç覽å¨åªéç»å ¥ï¼ä¸éè¦ç¨ UI æä½æå°æç¯©é¸æ¢ä»¶ã
æ¥é©
-
ç´æ¥éåæå管çå¹³å°ï¼å¸¶ç¾æ sessionï¼çæ¯å¦å·²ç»å ¥ï¼
agent-browser --session-name 104-sourcing open https://vip.104.com.tw/rms/index -
åå¾ç®åçæ
agent-browser --session-name 104-sourcing snapshot -iè§£è® snapshot 輸åºï¼å¤æ·ç®åé é¢çæ ï¼
-
è¥å·²å¨ vip.104.com.twï¼æå管çå¹³å°ï¼â ç´æ¥é²å ¥ç¬¬ä¸é段ï¼ä¸éè¦ç»å ¥
-
è¥è¢«å°åç»å ¥é â åç¨æ¶ç´¢å帳èå¯ç¢¼ï¼æ³¨æå ©ç¨®æ æ³ï¼
- 宿´ç»å ¥ï¼snapshot æ email + password å ©åè¼¸å ¥æ¬ï¼ï¼è¼¸å ¥å¸³èèå¯ç¢¼
- å¯ç¢¼éæ°é©èï¼snapshot åªæ password è¼¸å ¥æ¬ï¼ç¡ email æ¬ï¼ï¼104 å¨ session éææææåªè¦æ±åè¼¸å ¥å¯ç¢¼ï¼ä¸ééæ°è¼¸å ¥ email
agent-browser --session-name 104-sourcing fill @eX "{ç¨æ¶æä¾ç email}" # å 宿´ç»å ¥æ agent-browser --session-name 104-sourcing fill @eX "{ç¨æ¶æä¾çå¯ç¢¼}" agent-browser --session-name 104-sourcing click @eX # ç»å ¥æé agent-browser --session-name 104-sourcing snapshot -i -
è¥åºç¾ MFAï¼snapshot 䏿 OTP è¼¸å ¥ï¼
- åç¨æ¶ç´¢å 6 使¸ Email é©è碼
agent-browser --session-name 104-sourcing fill @eX "é©è碼"agent-browser --session-name 104-sourcing press Enter
-
確èªå·²é²å ¥ vip.104.com.tw
- è¥åºç¾éè¤ç»å ¥å°è©±æ¡ï¼snapshot æ¾ãå°ç®å帳èç»åºãâ click
- è¥åºç¾å»£åå½çªï¼screenshot ä¸çå°ãå å¼·æå ãçä¿é·æåï¼ï¼snapshot æ¾ééæé â click
第ä¸é段ï¼ç´ API æå°è篩é¸
ç»å ¥å®æå¾ï¼å ¨ç¨ç¨ eval + fetch APIï¼ä¸åæä½çè¦½å¨ UIã
å·²ç¥ API 端é»
| ç¨é | ç«¯é» |
|---|---|
| æå°åé¸äººå表ï¼å«å·¥ä½ç¶æ·ï¼ | GET https://auth.vip.104.com.tw/api/search/searchResult |
| åå¾å®ä¸åé¸äººå®æ´å±¥æ· | GET https://auth.vip.104.com.tw/vipapi/resume/search/{idNo}?path_for_log=list_search |
| åå¾å²åè³æå¤¾å表ï¼å« folderNoï¼ | GET https://auth.vip.104.com.tw/api/resumeTools/getFolderList?source=search&ec=105 |
| å²ååé¸äººå°è³æå¤¾ï¼æ¯æ´æ¹æ¬¡ï¼ | POST https://auth.vip.104.com.tw/api/resumeTools/saveResume |
å°±æ¥çæ 代碼ï¼empStatus 忏ï¼
| å¼ | 說æ |
|---|---|
0 |
ä¸é |
1 |
å¨è·ä¸ï¼æ³è·³æ§½ï¼expJobArr[0].expEndDesc é常çºãä»å¨è·ãï¼ |
2 |
å¾
æ¥ä¸ï¼å·²é¢è·ï¼å³å¯ä¸çï¼expEndDesc 顯示é¢è·æé·ï¼ |
åå¸ä»£ç¢¼
宿´ä»£ç¢¼æ¸
å®è¦ references/area.jsonï¼æ¯æ´å°ç£ã大é¸ãæµ·å¤å°åã縣å¸å±¤ä»£ç¢¼æ«ä¸ä½çº 000ï¼è¡æ¿å層æ«ä¸ä½çºæµæ°´èã
常ç¨ç¸£å¸å¿«æ¥ï¼
| å°é» | city åæ¸å¼ |
|---|---|
| å°åå¸ | 6001001000 |
| æ°åå¸ | 6001002000 |
| åºéå¸ | 6001004000 |
| æ¡åå¸ | 6001005000 |
| æ°ç«¹ç¸£å¸ | 6001006000 |
| å°ä¸å¸ | 6001008000 |
| å°åå¸ | 6001014000 |
| é«éå¸ | 6001016000 |
æ¥é© 1ï¼å¼å«æå° API 第 1 é ï¼åå¾ç¸½é æ¸è fixedUpdateDate
agent-browser --session-name 104-sourcing eval "
fetch('https://auth.vip.104.com.tw/api/search/searchResult?contactPrivacy=0&kws=%E9%9B%BB%E9%8A%B7%E4%BA%BA%E6%89%8D&city=6001001000&workExpTimeType=all&sex=2&empStatus={0|1|2}&updateDateType=1&sortType=RANK&readStatus=all&plastActionDateType=1&page=1&ec=105', {credentials:'include'})
.then(function(r){return r.json()})
.then(function(d){
window._fixedDate = d.result.fixedUpdateDate;
window._totalPages = d.result.pageInfo.total_page;
window._allCandidates = d.result.data;
window._p1done = true;
});
'fetching page 1...'
"
çå¾ å¾ç¢ºèªï¼
sleep 3 && agent-browser --session-name 104-sourcing eval "JSON.stringify({done:window._p1done, fixedDate:window._fixedDate, totalPages:window._totalPages, count:window._allCandidates&&window._allCandidates.length})"
éè¦ï¼
fixedUpdateDateå¿ é å¾ç¬¬ 1 é åæåå¾ï¼å¾çºææåé é½è¦å¸¶éåå¼ï¼ç¢ºä¿çµæä¸è´æ§ã
æ¥é© 2ï¼ä¸¦ç¼æåææå©é¤é
agent-browser --session-name 104-sourcing eval "
var baseUrl = 'https://auth.vip.104.com.tw/api/search/searchResult?contactPrivacy=0&kws=%E9%9B%BB%E9%8A%B7%E4%BA%BA%E6%89%8D&city=6001001000&workExpTimeType=all&sex=2&empStatus={0|1|2}&updateDateType=1&sortType=RANK&readStatus=all&plastActionDateType=1&ec=105&fixed_update_date=';
var pages = [];
for(var i=2; i<=window._totalPages; i++) pages.push(i);
Promise.all(pages.map(function(p){
return fetch(baseUrl+window._fixedDate+'&page='+p, {credentials:'include'})
.then(function(r){return r.json()})
.then(function(d){ window._allCandidates = window._allCandidates.concat(d.result.data); });
})).then(function(){ window._allDone = true; });
'fetching remaining pages...'
"
çå¾ å¾ç¢ºèªï¼
sleep 8 && agent-browser --session-name 104-sourcing eval "JSON.stringify({done:window._allDone, total:window._allCandidates.length})"
æ¥é© 3ï¼å¨ JS ä¸ç´æ¥ç¯©é¸ï¼ä¸éè¦å¼å«åå¥å±¥æ· API
æå°çµæçæ¯çè³æå·²å
å«å®æ´ expJobArrï¼å¯ç´æ¥å¨è¨æ¶é«ä¸ç¯©é¸ï¼
agent-browser --session-name 104-sourcing eval "
# ç¯ä¾ï¼ç¯©é¸è·ç¨±å«ãé»é·ãä¸å¹´è³ >= 1 å¹´çåé¸äºº
var qualified = window._allCandidates.filter(function(c){
return c.expJobArr && c.expJobArr.some(function(e){
if((e.expTitle||'').indexOf('é»é·') === -1) return false;
var desc = e.expEndDesc || '';
if(desc.indexOf('ä»å¨è·') > -1) return true;
var yr = desc.match(/(\d+)å¹´/);
return yr && parseInt(yr[1]) >= 1;
});
});
window._qualified = qualified;
JSON.stringify({
totalSearched: window._allCandidates.length,
qualified: qualified.length,
list: qualified.map(function(c){
return {
idNo: c.idNo,
name: c.userName,
age: c.age,
edu: c.eduDesc.split(' ')[0],
city: c.wcityNoDesc,
totalExp: c.expPeriodDesc,
teleSalesJobs: c.expJobArr.filter(function(e){
return (e.expTitle||'').indexOf('é»é·')>-1;
}).map(function(e){ return e.expTitle+'@'+e.expFirm+'('+e.expEndDesc+')'; })
};
})
})"
æå° API åå³çåé¸äººæ¬ä½åè
| æ¬ä½ | 說æ |
|---|---|
idNo |
åé¸äºº IDï¼ç¨æ¼å¼å«åå¥å±¥æ· APIï¼ |
userName |
å§å |
age |
年齡 |
sexDesc |
æ§å¥ |
eduDesc |
叿·ï¼å«å¸æ ¡åï¼å¯ç¨ .split(' ')[0] åç°¡ç¨±ï¼ |
wcityNoDesc |
叿工ä½å°é»ï¼å¤å以ãããåéï¼ |
expPeriodDesc |
總工ä½å¹´è³æè¿° |
titleCatDesc |
叿è·ç¨±é¡å¥ |
expJobArr |
å·¥ä½ç¶æ·é£åï¼å« expTitle, expFirm, expJobNote, expEndDesc, expPeriodï¼ |
æ¥é© 4ï¼æ¹æ¬¡å²ååæ ¼åé¸äººå°è³æå¤¾
篩é¸å®æå¾ï¼ä¸æ¬¡ API å¼å«å³å¯æ¹æ¬¡å²åææåæ ¼åé¸äººï¼ä¸éè¦ UI æä½ã
å åå¾è³æå¤¾å表ï¼è®ç¨æ¶é¸æ
agent-browser --session-name 104-sourcing eval "fetch('https://auth.vip.104.com.tw/api/resumeTools/getFolderList?source=search&ec=105',{credentials:'include'}).then(function(r){return r.json()}).then(function(d){window._folders=JSON.stringify(d.result.folderList.map(function(f){return {name:f.name,folderNo:f.folderNo}}))});'fetching'"
sleep 2 && agent-browser --session-name 104-sourcing eval "window._folders"
åå¾çµæå¾ï¼ä»¥è¡¨æ ¼åç¾çµ¦ç¨æ¶ï¼
| # | è³æå¤¾å稱 | folderNo |
|---|---|---|
| 1 | ï¼ä¾ API åæå¡«å ¥ï¼ | … |
è©¢åç¨æ¶ï¼ãè«åè¦å° N ä½åé¸äººåå
¥åªåè³æå¤¾ï¼ãï¼çç¨æ¶é¸æå¾ï¼ä»¥é¸å®ç folderNo å·è¡ä¸ä¸æ¥ã
æ¹æ¬¡å²åææåæ ¼åé¸äºº
éè¦ï¼æ¯æ¬¡ API å¼å«æå¤æåå²å 50 çï¼è¶ éçæéé»å¤±æï¼å¨
params.failä¸ï¼ã å¿ é 以 50 ççºå®ä½åæ¹éåºï¼ä¸¦ä½¿ç¨åæ¥ XHR åå¾å³æçµæï¼async fetch + window è®æ¸å¨é é¢å°èªå¾ææ¶å¤±ï¼ã
# ä»¥æ¯æ¹ 50 ççºå®ä½ï¼ç¨åæ¥ XHR å²åï¼ç´æ¥åå¾çµæ
agent-browser --session-name 104-sourcing eval "
var folderNo = '{ç¨æ¶é¸æç folderNo}';
var batch = window._qualified.slice(0, 50).map(function(c){return c.idNo});
var body = 'rc=11012313&docNo='+folderNo+'&pageSource=search&isDuplicate=0&contentInfo%5Bsnapshot%5D=&contentInfo%5BsearchEngine%5D='+batch.join('%2C');
var xhr = new XMLHttpRequest();
xhr.open('POST','https://auth.vip.104.com.tw/api/resumeTools/saveResume',false);
xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
xhr.withCredentials = true;
xhr.send(body);
xhr.responseText;
"
å° slice(0, 50) æ¹çº slice(50, 100)ãslice(100, 150)… 便¤é¡æ¨å®ææææ¹æ¬¡ã
åææ ¼å¼èªªæï¼
code: 0â å ¨é¨å²åæåcode: 6, type: dataDuplicatedâ ä½¿ç¨ isDuplicate=-1 æææåºç¾ï¼params.idæ¯æåå²åç IDï¼ééè¤ï¼ï¼å ¶é¤å ¨è¢«å¸³è層ç´çéè¤æª¢æ¥è·³écode: 7, type: partialFailâ é¨å失æï¼params.success.searchEngine[]æ¯æåçï¼params.fail.searchEngine[]æ¯å¤±æçcode: 4, type: overStorageâ è³æå¤¾å·²æ»¿ï¼ä¸é 300 çï¼code: 5, type: overViewâ 宿¬¡è«æ±åé¸äººæ¸éè¶ éå¹³å°ä¸é
saveResume POST åæ¸èªªæï¼
| 忏 | å¼ | 說æ |
|---|---|---|
rc |
11012313 |
æä½é¡åç¢¼ï¼æå°é å²åï¼åºå®å¼ï¼ |
docNo |
{folderNo} |
ç®æ¨è³æå¤¾ ID |
pageSource |
search |
便ºé é¢ï¼åºå®å¼ï¼ |
isDuplicate |
0 |
åå¿
ç¨ 0ï¼-1 æè·³é帳èå
§ä»»ä½è³æå¤¾å·²åéçåé¸äººï¼å°è´å¤§éæ¼å |
contentInfo[searchEngine] |
{idNo1},{idNo2},... |
åé¸äºº idNoï¼éèåéï¼æ¯æ¹æå¤ 50 ç |
contentInfo[snapshot] |
空 | å¿«ç § IDï¼æå°é åºå®çç©ºï¼ |
åé¸äººè©ä¼°å ±åæ ¼å¼ï¼åºæ¬çï¼
## 篩é¸çµæï¼å
± N ä½ç¬¦åæ¢ä»¶ï¼
| # | å§å | 年齡 | 叿· | 叿å°é» | å·¥ä½å¹´è³ | ç¸éç¶æ· |
|---|------|------|------|----------|----------|----------|
| 1 | çå°æ | 35 | å¤§å¸ | å°åå¸ | 8~9å¹´ | é»é·ä¸»ç®¡@XXå
¬å¸(3å¹´) |
...
**建è°è¯çµ¡**ï¼#1 çå°æã#3 ...
**建è°ç¥é**ï¼#2 ...ï¼åå ï¼å°é»ä¸ç¬¦ï¼
æ¥é© 3.5ï¼é¸ç¨ï¼ï¼æ·±åº¦å±¥æ·åæ
é¡¯ç¤ºåºæ¬ç¯©é¸çµæå¾ï¼è©¢åç¨æ¶æ¯å¦é²è¡æ·±åº¦åæï¼
ãç®åæ ¹ææå°åè¡¨è³æç¯©åº N ä½åé¸äººãæ¯å¦é²è¡æ·±åº¦å±¥æ·åæï¼ï¼é¡å¤è®åèªæä»ç´¹ã叿èªè³ãç¢æ¥å¹´è³ï¼èæè¼é·ä½è©ä¼°æ´ç²¾æºï¼ã
ç¨æ¶é¸æãæ¯ãå¾ï¼ä¾åºå·è¡ï¼
åæ¹ fetch åå¥å±¥æ·ï¼æ¯æ¹ 50 çï¼
以 50 ççºä¸æ¹ï¼æ¹æ¬¡é sleep 5 ç§ï¼é¿å rate limitã主 session æ¶éæ¯æ¹ JSONï¼
# 第 1 æ¹ï¼idNo 0~49ï¼
agent-browser --session-name 104-sourcing eval "
var ids = window._qualified.slice(0, 50).map(function(c){return c.idNo});
var results = {};
Promise.all(ids.map(function(id){
return fetch('https://auth.vip.104.com.tw/vipapi/resume/search/'+id+'?path_for_log=list_search',{credentials:'include'})
.then(function(r){return r.json()})
.then(function(d){
var res = d.data ? d.data.resume : null;
if(!res) return;
results[id] = {
intro: res.intro ? res.intro.replace(/<[^>]+>/g,'') : '',
hopeSalary: res.hopeSalaryDesc || '',
expCats: res.expCatTimeDesc ? res.expCatTimeDesc.map(function(e){return e.expCatDesc+':'+e.expTimeDesc}).join(', ') : ''
};
});
})).then(function(){ window._resumeBatch = JSON.stringify(results); });
'fetching batch 1...'
"
sleep 10 && agent-browser --session-name 104-sourcing eval "window._resumeBatch"
æ¯æ¹åå JSON å¾ï¼ç´¯ç©å°ä¸» session çç©ä»¶ä¸ï¼let allDetails = {...allDetails, ...JSON.parse(batchJson)}ï¼ã
å° slice(0,50) æ¹çº slice(50,100), slice(100,150) … å®ææææ¹æ¬¡ã
æ¹æ¬¡æ¸é =
Math.ceil(qualified.length / 50)ï¼æ¯æ¹ sleep 10 ç§ã
åä½µè³æä¸¦å¯«å ¥æ«åæª
æææ¹æ¬¡å®æå¾ï¼å° window._qualifiedï¼åºæ¬è³æï¼èç´¯ç©çåå¥å±¥æ·åä½µï¼å¯«å
¥æ«åæªï¼
# 主 session ä¸ååº _qualified åºæ¬è³æ
agent-browser --session-name 104-sourcing eval "JSON.stringify(window._qualified)"
å°å ©ä»½è³æåä½µçºï¼
[
{
"idNo": "...",
"name": "...",
"age": 28,
"expJobArr": [...],
"intro": "...",
"hopeSalary": "35,000~45,000",
"expCats": "æè²æ¥:2å¹´, éèæ¥:1å¹´"
},
...
]
寫å
¥ /tmp/104_resumes.jsonã
並ç¼åå Sub-agents åæ
å°åé¸äººåçµï¼æ¯çµ 50 çï¼ç¨ Task tool åæååå¤å sub-agentsï¼subagent_type: general-purposeï¼ï¼
Task prompt ç¯ä¾ï¼æ¯å sub-agentï¼ï¼
è«è®å /tmp/104_resumes.jsonï¼åæç¬¬ {start} å°ç¬¬ {end} çåé¸äººï¼0-indexedï¼ã
æåæ¢ä»¶ï¼
- è·ä½ï¼{è·ä½}
- 硬æ§è¦æ±ï¼{æ¢ä»¶}
- çæ³åé¸äººï¼{æè¿°}
- å°é·ï¼{æé¤æ¢ä»¶}
- å åï¼{nice-to-have}
è«éå°æ¯ä½åé¸äººï¼
1. è©åï¼1-5ï¼
2. æ¨è¦åå ï¼ä¸å¥è©±ï¼
3. çæ
®ï¼è¥æï¼
å峿 ¼å¼ï¼JSON arrayï¼ï¼
[{"idNo":"...","score":4,"reason":"...","concern":"..."}]
主 session çææ sub-agents åå³å¾ï¼å½æ´ææè©åçµæï¼ä»¥åæ¸æåºå¾åç¾æ·±åº¦çè©ä¼°å ±åï¼
## 深度篩é¸çµæï¼å
± N ä½ï¼ææ¨è¦åæ¸æåºï¼
| # | å§å | è©å | 年齡 | 叿èªè³ | ç¢æ¥èæ¯ | æ¨è¦åå | çæ
® |
|---|------|------|------|----------|----------|----------|------|
| 1 | çå°æ | â
â
â
â
â
| 28 | 4~5è¬ | æè²æ¥2å¹´ | 符åçæ³èæ¯ | ç¡ |
...
注æäºé
- eval åªè½ç¨ ES5ï¼ä¸å¯ç¨
const/letãarrow functionãtemplate literalï¼å¦åå ± SyntaxError - API fetch å¿ é å¨ä¸» sessionï¼104-sourcingï¼å §å¼å«ï¼Subagent çç¨ç« session æ²æç»å ¥ cookie
expJobNoteå« HTML æ¨ç±¤ï¼åæåç¨.replace(/<[^>]+>/g, '')æ¸ é¤fixedUpdateDateå¿ é å¾ç¬¬ 1 é åæåå¾å¾ï¼ç¨æ¼ææå¾çºåé è«æ±- è¥ session 失æï¼fetch åå³ãå°æªç»å ¥ãï¼ï¼éæ°å·è¡ç¬¬äºé段ç»å ¥æµç¨
- æå°ééµåä¸è¦å ã人æãå ©åï¼104 æå°æ©å¶ä¸å¤ ç²¾æºï¼å äºã人æãå¾å®¹ææå°ã人æå°å¡ãã人æé¡§åãç人è³è·ç¼ºï¼åèå¹²æ¾çµæãç´æ¥ç¨è·ä½å稱å³å¯ï¼ä¾å¦ï¼é»é·ãæ¥åãå·¥ç¨å¸«ï¼
- saveResume å¿
é ç¨ isDuplicate=0ï¼
-1æ¯å¸³è層ç´çéè¤æª¢æ¥ï¼åªè¦æ¾åéä»»ä½è³æå¤¾å°±ç®éè¤ï¼ï¼æå°è´å¤§éåé¸äººè¢«éé»è·³éï¼0ææå¼·å¶å²åå°ç®æ¨è³æå¤¾ - æ¯æ¹æå¤ 50 çï¼saveResume æ¯æ¬¡è«æ±å¯¦éæåå²åä¸éçº 50 çï¼è¶
éçæåå¨
params.failä½ä¸å ±é¯ï¼åå¿ ä»¥ 50 çºå®ä½åæ¹ - saveResume ç¨åæ¥ XHRï¼ä¸ç¨ async fetchï¼async fetch éè¦é¡å¤ç sleep + è®å window è®æ¸ï¼ä¸æ¦ä¸éå°èªé é¢å°±æéºå¤±ï¼åæ¥ XHR ç´æ¥åå³çµæï¼æ´å¯é
- é é¢å°èªææ¸
ç©ºææ window è®æ¸ï¼åªè¦å·è¡
openåæé é¢ï¼window._qualifiedãwindow._allCandidatesçå ¨é¨æ¶å¤±ï¼ééæ°æå篩é¸