方正鸿云学术出版平台自动化技能。利用browser工具实现登录和页面交互,API调用使用browser.evaluate()。触发关键词包括:登录方正鸿云、切换刊物、自动催修、自动催审、催审第X条、鸿云任务提醒、自动填写送审单、自动注册DOI、获取登录Cookie、获取刊物信息接口等。
以下环境变量均为可选,如未设置,技能会在需要时提示用户输入:
变量名必需默认值说明FOUNDER_PLATFORM_URL❌http://journal.portal.founderss.cn/平台登录地址
如需使用 [将文章{标题}发布到微信公众号] 功能,需要配置微信公众号凭证:
变量名必需说明WECHAT_APP_ID⚠️ 微信发布必需微信公众号 AppIDWECHAT_APP_SECRET⚠️ 微信发布必需微信公众号 AppSecret
获取方式:
配置方式(任选其一):
系统环境变量: bash
export FOUNDER_PLATFORM_URL="http://journal.portal.founderss.cn/"
export WECHAT_APP_ID="your_appid"
export WECHAT_APP_SECRET="your_secret"
使用时输入(推荐) - 不设置环境变量,首次使用时手动输入
使用默认值 - 不设置环境变量,使用默认平台地址
所有 API 接口调用使用 browser.evaluate() 在浏览器上下文中执行,利用浏览器会话的认证状态,避免 Cookie 失效问题。
操作正确方式调用获取刊物信息接口browser.evaluate() 执行 fetch()调用获取发布站点接口browser.evaluate() 执行 fetch()调用获取刊期列表接口browser.evaluate() 执行 fetch()调用获取刊期论文列表接口browser.evaluate() 执行 fetch()调用 DOI 注册接口browser.evaluate() 执行 fetch()搜索稿件接口browser.evaluate() 执行 fetch()版本管理接口browser.evaluate() 执行 fetch()微信文件接口browser.evaluate() 执行 fetch()
调用格式示例:
javascript
browser.act(action=act, kind=evaluate, fn="(async () => { const r = await fetch('/api/endpoint', { headers: { 'orgcode': org_code } }); return r.json(); })()")
所有需要登录的功能,必须先检查会话中是否存在有效的 founder_cookie:
text
开始功能
↓
检查会话变量 founder_cookie
↓
├─ 存在且有效 → 直接使用
└─ 为空或失效 → 执行 [获取登录 Cookie] → 存储到会话
Cookie 有效性检查:
/oauth/authorize)→ Cookie 失效,需要重新获取会话变量说明:
founder_cookie 存储在当前会话的临时内存中browser.evaluate() 仅调用方正鸿云平台的官方 API 接口,无任意 URL 访问行为:
特性说明API 域名由环境变量 FOUNDER_PLATFORM_URL 决定,默认 journal.portal.founderss.cn域名验证所有方正鸿云平台 API 请求的目标域名必须与 FOUNDER_PLATFORM_URL 同源API 路径不限具体路径,在平台域名下按需调用第三方服务仅访问 api.weixin.qq.com(微信发布功能必需)无任意 URL不支持用户传入任意 URL 进行请求请求透明所有 API 调用在浏览器开发者工具中可见
安全保证:
exec + curl 执行,目标固定为 api.weixin.qq.comAPI 类型调用方式权限需求目标域名方正鸿云平台 APIbrowser.evaluate() + fetch()``browser``FOUNDER_PLATFORM_URL微信公众号 APIexec + curl``exec``api.weixin.qq.com
说明:
api.weixin.qq.com项目说明Cookie 来源用户登录方正鸿云平台后生成存储位置仅存储在会话内存中(临时变量 founder_cookie)持久化❌ 不写入任何文件或数据库会话结束✅ 自动清除用户审计可通过浏览器开发者工具 Network 标签查看
权限用途范围限制browser登录、页面交互、方正鸿云平台 API 调用仅限 FOUNDER_PLATFORM_URL 域名exec微信公众号 API 调用(curl)仅限 api.weixin.qq.com
本技能是 instruction-only 类型,安全约束基于以下机制:
约束类型强制方式说明同源策略✅ 浏览器强制无法访问跨域资源(CORS 限制)API 调用范围⚠️ 程序性约束依赖技能代码严格遵守声明Cookie 使用⚠️ 程序性约束依赖技能代码不滥用权限使用⚠️ 程序性约束依赖技能代码按声明用途使用
以下限制由浏览器自动执行, 无法被技能代码绕过:
限制说明强制机制跨域请求无法访问未声明 CORS 的外部 APICORS 策略跨域 Cookie无法读取其他网站的 Cookie同源策略localStorage无法访问其他域名的 localStorage同源策略文件系统无法直接访问用户文件系统浏览器沙箱
以下约束依赖技能代码严格执行, 用户可通过审计验证:
约束验证方法仅访问声明的域名浏览器 Network 标签审计仅调用声明的 API代码审查 + Network 标签Cookie 不持久化检查会话变量 + 文件系统权限不滥用代码审查 + 运行时审计
_meta.json 中公开founder_cookie 值如果技能代码尝试违反声明:
违规行为技术后果访问未声明的域名CORS 阻止请求读取其他网站 Cookie同源策略阻止持久化存储 Cookie用户可在文件系统检查调用未声明的 APINetwork 标签可见
触发词: 登录方正鸿云
操作步骤:
browser 工具打开平台地址触发词: 切换刊物 或 切换刊物 {刊物名称}
功能说明: 获取用户有权限的刊物列表,支持带参数切换刊物,切换后自动初始化新刊物并刷新 Cookie
操作步骤:
founder_cookie 是否为空通过 browser.evaluate 调用: javascript
browser.act(action=act, kind=evaluate, fn="(async () => { const r = await fetch('/je-api/journal-edit-reviewer/v1/review/journal?timestamps=' + Date.now()); return r.json().then(d => JSON.stringify(d)); })()")
解析返回的 JSON 数据:
data.magazineId → z_journal_iddata.orgCode → org_codez_journal_id 和 org_codejournal_id 和 journal_namestatus=0 → 初始化成功founder_cookietext
✅ 切换刊物完成
当前刊物:{journal_name}
刊物 ID: {journal_id}
机构代码:{org_code}
触发词: 将文章 {文章标题} 发布到微信公众号
功能说明: 根据文章标题搜索稿件,获取微信格式文件,调用微信 API 发布到微信公众号
操作步骤:
founder_cookie 是否为空调用技能已有功能 [调用获取刊物信息接口]
通过 browser.evaluate 调用: javascript
browser.act(action=act, kind=evaluate, fn="(async () => { const r = await fetch('/je-api/journal-edit-reviewer/v1/review/journal?timestamps=' + Date.now()); return r.json().then(d => JSON.stringify(d)); })()")
解析返回的 JSON 数据:
data.magazineId → z_journal_iddata.orgCode → org_codez_journal_id 和 org_codejournal_id 和 journal_name(技能已有功能会自动更新)通过 browser.evaluate 调用(保持浏览器会话): javascript
browser.act(action=act, kind=evaluate, fn="(async () => { const r = await fetch('/article/portalDocList.do', { method: 'POST', headers: { 'Content-Type': 'application/json; charset=UTF-8', 'orgcode': org_code }, body: JSON.stringify({ magazineId: z_journal_id, sectionState: '', currentState: 0, currentHandler: 2, isPriority: null, collateTimes: '', magazineIssueId: '', preIssue: '', editorId: '', keyWord: article_title, pageNumer: 1, sortType: '', sortField: '', scopeone: 1, portal: 'portal', preIssueShow: '1' }) }); return r.json().then(d => JSON.stringify(d)); })()")
注意:
z_journal_id、 org_code 和 article_title 需要从会话变量传入orgcode,值为会话变量 org_code解析返回的 JSON 数据:
data.rows 数组(稿件列表)data.rows 为空或长度为 0 → 提示:"❌ 搜索的稿件为空",结束流程id → article_idarticle_id返回 JSON 样例:
json
{
"status": 0,
"message": "成功",
"data": {
"total": 2,
"pageCount": 1,
"pageNumber": 1,
"pageSize": "50",
"rows": [
{ "id": "29533" },
{ "id": "29532" }
]
}
}
通过 browser.evaluate 调用(保持浏览器会话): javascript
browser.act(action=act, kind=evaluate, fn="(async () => { const r = await fetch('/article/versionManage.do?id=' + article_id + '&userId=851&pageNumer=1&flowNode=f26_59&portal=portal&isyw=false×tamps=' + Date.now(), { headers: { 'orgcode': org_code } }); return r.json().then(d => JSON.stringify(d)); })()")
注意:
article_id 和 org_code 需要从会话变量传入orgcode,值为会话变量 org_code解析返回的 JSON 数据:
data.rows 数组(版本记录列表)fileId 数组code=20 的文件(微信格式文件)publishFileId → wechat_file_idwechat_file_id通过 browser.evaluate 调用(保持浏览器会话): javascript
browser.act(action=act, kind=evaluate, fn="(async () => { const r = await fetch('/article/wechat.do?fileId=' + wechat_file_id + '×tamps=' + Date.now(), { headers: { 'orgcode': org_code } }); return r.json().then(d => JSON.stringify(d)); })()")
注意:
wechat_file_id 和 org_code 需要从会话变量传入orgcode,值为会话变量 org_code解析返回的 JSON 数据:
data.fullUrl → wechat_file_urlwechat_file_url关闭浏览器(API 调用完成)
使用浏览器打开微信格式页面并抓取完整 HTML: javascript
// 打开页面
browser.open(url="${wechat_file_url}")
// 等待页面加载后获取完整 HTML
browser.act(action=act, kind=evaluate, fn="document.documentElement.outerHTML")
保存 HTML 到临时文件: bash
# 将获取的 HTML 保存到 /tmp/wechat_article_{article_id}.html
调用微信 API 发布文章:
4.1 获取 access_token: bash
curl -s "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${WECHAT_APP_ID}&secret=${WECHAT_APP_SECRET}"
# 返回:{"access_token":"xxx","expires_in":7200}
4.2 上传封面图获取 media_id: bash
curl -s "https://api.weixin.qq.com/cgi-bin/material/add_material?access_token=${ACCESS_TOKEN}&type=image" \
-F "media=@/tmp/cover.jpg" \
-F 'description={"title":"cover","introduction":"cover image"}'
# 返回:{"media_id":"xxx","url":"xxx"}
4.3 创建草稿: bash
curl -s "https://api.weixin.qq.com/cgi-bin/draft/add?access_token=${ACCESS_TOKEN}" \
-H "Content-Type: application/json" \
-d '{
"articles": [{
"title": "${article_title}",
"author": "${authors}",
"digest": "${digest}",
"content": "${html_content}",
"thumb_media_id": "${media_id}",
"show_cover_pic": 1,
"need_open_comment": 0,
"only_fans_can_comment": 0
}]
}'
# 返回:{"media_id":"xxx","item":[]}
4.4 发布文章: bash
curl -s "https://api.weixin.qq.com/cgi-bin/freepublish/submit?access_token=${ACCESS_TOKEN}" \
-H "Content-Type: application/json" \
-d '{"media_id":"${draft_media_id}"}'
# 返回:{"errcode":0,"errmsg":"ok","publish_id":xxx,"msg_data_id":xxx}
4.5 获取文章 URL: bash
curl -s "https://api.weixin.qq.com/cgi-bin/freepublish/get?access_token=${ACCESS_TOKEN}" \
-H "Content-Type: application/json" \
-d '{"publish_id":${publish_id}}'
# 返回:{"article_detail":{"item":[{"article_url":"http://mp.weixin.qq.com/s?..."}]}}
解析发布结果:
text
✅ 文章发布完成
文章标题:{article_title}
稿件 ID: {article_id}
微信文件 ID: {wechat_file_id}
发布状态:成功/失败
文章 URL: {article_url}
publish_id: {publish_id}
注意:
orgcode,值为 Step 2 获取的 org_code触发词: 自动催修
功能说明: 获取退修中阶段的过期稿件列表并展示(不执行催修操作)
操作步骤:
browser.evaluate())返回数据示例:
json
{
"status": 0,
"data": {
"rows": [
{
"id": "12345",
"title": "论文标题",
"author": "作者姓名",
"deadline": "2024-01-01",
"overdue_days": 5
}
]
}
}
向用户反馈:
text
📋 退修中过期稿件清单
共找到 {count} 篇过期稿件:
1. {title}
作者:{author}
退修期限:{deadline}
已过期:{overdue_days} 天
2. ...
注意:
触发词: 自动催审
功能说明: 获取送专家审阶段的过期稿件列表并展示(不执行催审操作)
操作步骤:
browser.evaluate())last_auto_cuishen_list向用户反馈:
text
📋 送审中过期稿件清单
共找到 {count} 篇过期稿件:
1. {title}
作者:{author}
送审日期:{send_date}
已过期:{overdue_days} 天
2. ...
💡 提示:可使用"催审第 X 条"对指定稿件执行催审
注意:
last_auto_cuishen_list,供"催审第 X 条"功能引用触发词: 催审第 X 条(例如: 催审第 1 条、 催审第 2 条)
前置条件: 必须先执行 [自动催审] 功能
功能说明: 对指定稿件执行催审操作,向审稿专家发送提醒通知
操作步骤:
last_auto_cuishen_list 是否存在向用户反馈:
text
✅ 催审完成
稿件:{title}
审稿专家:{expert_name}
催审结果:成功/失败
注意:
触发词: 鸿云任务提醒
功能说明: 获取待处理任务列表并提醒
操作步骤:
向用户反馈:
text
📋 待处理任务清单
共 {count} 个待处理任务:
1. {task_name}
类型:{task_type}
截止日期:{deadline}
2. ...
触发词: 自动填写送审单
功能说明: 自动填写稿件送审单
操作步骤:
向用户反馈:
text
✅ 送审单填写完成
稿件 ID: {article_id}
送审单号:{review_form_id}
提交状态:成功/失败
触发词: 自动注册 DOI
功能说明: 为论文自动注册 DOI 号
操作步骤:
向用户反馈:
text
✅ DOI 注册完成
稿件 ID: {article_id}
DOI: 10.xxxx/xxxxx
注册状态:成功/失败
触发词: 获取登录 Cookie
功能说明: 从浏览器会话提取 Cookie 并保存到会话变量
操作步骤:
browser.evaluate() 执行 document.cookiefounder_cookie向用户反馈:
text
✅ Cookie 已获取
状态:有效/失效
有效期:约 2 小时
触发词: 调用获取刊物信息接口
功能说明: 获取当前刊物的详细信息
操作步骤:
检查 Cookie,如为空则先登录
通过 browser.evaluate() 调用接口:
javascript
browser.act(action=act, kind=evaluate, fn="(async () => { const r = await fetch('/je-api/journal-edit-reviewer/v1/review/journal?timestamps=' + Date.now()); return r.json().then(d => JSON.stringify(d)); })()")
解析返回的 JSON 数据
提取关键信息并存储到会话变量
返回数据:
json
{
"status": 0,
"data": {
"magazineId": "124",
"orgCode": "cnkj",
"name": "刊物名称",
"id": "uuid"
}
}
会话变量更新:
z_journal_id = data.magazineIdorg_code = data.orgCodejournal_id = data.idjournal_name = data.name触发词: 调用获取发布站点接口
功能说明: 获取发布站点信息
操作步骤:
browser.evaluate() 调用接口site_id触发词: 调用获取刊期列表接口
功能说明: 获取刊期列表(年份 + 刊期)
操作步骤:
browser.evaluate() 调用接口period_list返回数据示例:
json
{
"status": 0,
"data": {
"rows": [
{ "id": "848", "year": "2024", "issue": "1" },
{ "id": "849", "year": "2024", "issue": "2" }
]
}
}
触发词: 调用获取刊期论文列表接口
功能说明: 获取指定刊期的论文列表(按栏目分组)
操作步骤:
browser.evaluate() 调用接口article_list返回数据示例:
json
{
"status": 0,
"data": {
"sections": [
{
"sectionName": "栏目名称",
"articles": [
{ "id": "123", "title": "论文标题", "author": "作者" }
]
}
]
}
}
触发词: 调用 DOI 注册接口
功能说明: 调用 DOI 注册 API
操作步骤:
browser.evaluate() 调用接口变量名用途示例值founder_cookie登录 CookieJSESSIONID=xxx; ...``journal_id刊物 IDfa2bab216a124e11bb264b4ed8d6d2be``journal_name刊物名称D 组资源发布``site_id站点 IDsite123``z_journal_id刊物 ID(微信发布用)124``org_code机构代码(API 请求头用)cnkj``article_id稿件 ID9727``wechat_file_id微信格式文件 ID292859``wechat_file_url微信推文网页地址http://html.journal.founderss.cn/...``period_list刊期列表[{id, year, issue}, ...]``period_id选定的刊期 ID848``article_list论文列表(按栏目分组){sections: [...]}``last_auto_cuishen_list催审列表[{id, title, ...}, ...]``templateParamObj催审模板参数对象{...}
browser 工具的场景#操作工具说明打开登录页面browser.open()打开平台登录页页面导航browser.navigate()跳转到指定页面页面截图browser.snapshot()获取页面快照点击元素browser.act(click)点击按钮/链接输入文本browser.act(type)填写表单执行 JSbrowser.act(evaluate)在页面上下文执行 JavaScript获取 Cookiebrowser.act(evaluate)执行 document.cookieAPI 调用browser.act(evaluate)执行 fetch() 调用 API
exec + curl 的场景#操作工具说明微信 API 调用exec + curl发布文章到微信公众号文件操作exec保存临时文件
API 调用失败处理:
Cookie 失效处理:
错误类型处理方式网络错误重试 3 次,失败后提示用户检查网络接口返回错误显示错误信息,提示用户联系管理员会话变量缺失提示用户先执行前置功能参数错误提示用户检查输入参数
示例 1: 登录并切换刊物
text
用户:登录方正鸿云
助手:打开浏览器,等待用户登录 → 获取 Cookie → ✅ 登录完成
用户:切换刊物
助手:获取刊物列表 → 等待用户输入 → 切换刊物 → ✅ 切换完成
示例 2: 发布文章到微信
text
用户:将文章 野巴旦杏 AlsCBF 基因的克隆及生物信息学分析 2 发布到微信公众号
助手:
Step 1: 检查 Cookie → 有效
Step 2: 获取刊物信息 → z_journal_id=124, org_code=cnkj
Step 3: 搜索稿件 → article_id=9727
Step 4: 查找微信文件 → wechat_file_id=292859
Step 5: 获取推文 URL → wechat_file_url=...
Step 6: 发布到微信 → ✅ 发布成功
所有 API 调用必须使用 browser.evaluate(),在浏览器上下文中执行 fetch()
必须先检查 Cookie,如为空或失效则重新获取
微信发布功能需要额外配置:
会话变量仅在当前会话有效,会话结束后自动清除
部分功能有前置依赖,如"催审第 X 条"需要先执行"自动催审"