Compare commits
55 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0f546e8a57 | ||
|
|
26070919c9 | ||
|
|
bfd73c3d73 | ||
|
|
415927cd0f | ||
|
|
aa6c75e59f | ||
|
|
c31c86bd56 | ||
|
|
1ee3c35216 | ||
|
|
6676357296 | ||
|
|
3ba72969d9 | ||
|
|
c9ea10f0ef | ||
|
|
17f1b39414 | ||
|
|
70216734a3 | ||
|
|
c25bde1b7a | ||
|
|
beb457a884 | ||
|
|
1b1abb9b88 | ||
|
|
112bd3b938 | ||
|
|
55adf31613 | ||
|
|
cdddbae520 | ||
|
|
c4bd07069c | ||
|
|
71b45584e8 | ||
|
|
e343d37a01 | ||
|
|
7f5ffab2a7 | ||
|
|
d2e6d112d5 | ||
|
|
5b390d3ad1 | ||
|
|
798c4bd7d5 | ||
|
|
7e133176e5 | ||
|
|
87a345ffa7 | ||
|
|
2bafb6d491 | ||
|
|
0f278ad25e | ||
|
|
1da157abbd | ||
|
|
2fa9f88da2 | ||
|
|
9e2f91b4d4 | ||
|
|
2b15e1a351 | ||
|
|
25f95d9f90 | ||
|
|
03e33872c2 | ||
|
|
5b5f96c2d3 | ||
|
|
0005e4eb74 | ||
|
|
89d1b2c6a7 | ||
|
|
8eb1d19512 | ||
|
|
8e0bde749f | ||
|
|
93cc9d916e | ||
|
|
18bb76a2a3 | ||
|
|
06a4821888 | ||
|
|
0157ae413b | ||
|
|
cb97cddb89 | ||
|
|
90699a547e | ||
|
|
54fa04ff65 | ||
|
|
dfa9251ae9 | ||
|
|
25fdbd8444 | ||
|
|
ade05d8dab | ||
|
|
4cbd5c516a | ||
|
|
dab6faafde | ||
|
|
87ff3a1148 | ||
|
|
44d181b26a | ||
|
|
7a112f4d17 |
2
.github/workflows/build.yml
vendored
@@ -55,7 +55,7 @@ jobs:
|
||||
- name: setup pnpm
|
||||
uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: 9.15.0
|
||||
version: 10.2.0
|
||||
- name: Install frontend dependencies
|
||||
run: pnpm install
|
||||
|
||||
|
||||
161
CHANGELOG.md
@@ -2,156 +2,23 @@
|
||||
Author: 目棃
|
||||
Description: CHANGELOG
|
||||
Date: 2024-10-09
|
||||
Update: 2025-01-22
|
||||
Update: 2025-02-11
|
||||
---
|
||||
|
||||
> 本文档 [`Frontmatter`](https://github.com/BTMuli/MuCli#Frontmatter) 由 [MuCli](https://github.com/BTMuli/Mucli) 自动生成于 `2024-10-09 15:51:43`
|
||||
>
|
||||
> 更新于 `2025-01-22 10:59:31`
|
||||
> 更新于 `2025-02-11 10:57:49`
|
||||
|
||||
## [0.6.8](https://github.com/BTMuli/TeyvatGuide/releases/v0.6.8) (2025-01-22)
|
||||
## [0.7.0](https://github.com/BTMuli/TeyvatGuide/releases/v0.7.0) (025-02-28)
|
||||
|
||||
- ✨ 扫码登录
|
||||
- ✨ 调整祈愿记录图表样式,新增祈愿日历&祈愿堆叠柱状图
|
||||
- ✨ 支持配置帖子详情图像质量,默认80%
|
||||
- ✨ 支持帖子详情图像查看原图,当质量配置为100%时,该按钮不显示
|
||||
- ✨ 深渊上传支持胡桃账户设置
|
||||
- 🚸 降低祈愿全量刷新耗时
|
||||
- 🚸 加快帖子加载速度,降低内存占用
|
||||
- 💄 调整角色卡片样式
|
||||
- 💄 调整角色名片样式,增加描述清晰度
|
||||
- 💄 调整深渊Wiki队伍搭配窗口高度
|
||||
- 💄 mac下不显示分享设置
|
||||
- 💄 调整战绩页新洞天渲染样式
|
||||
- 🔥 深渊Wiki移除第10层数据
|
||||
- 🐛 修复深渊数据恢复异常
|
||||
- 🐛 修复 loading 组件 empty 状态设置异常
|
||||
- ♻️ 优化帖子加载逻辑,当刷新内容不足20条时,下次刷新数量为20-当前数量,如刷新数量为19条,则下次刷新数量为1条
|
||||
- ♻️ 动态获取分区列表&版块列表
|
||||
- ♻️ 重构部分路由处理,当话题/帖子切换分区/版块时,页面刷新不重置当前分区/版块
|
||||
|
||||
## [0.6.7](https://github.com/BTMuli/TeyvatGuide/releases/v0.6.7) (2024-12-31)
|
||||
|
||||
- 🍱 更新5.3版本游戏资源 [`#139`](https://github.com/BTMuli/TeyvatGuide/issues/139)
|
||||
- ✨ 支持嵌入B站视频的分享图渲染
|
||||
- 🐛 修复版块跳转异常
|
||||
- 🐛 修复清理日志异常
|
||||
- 🐛 修复特定帖子`link_card_ids`数据解析异常
|
||||
- 🐛 修复帖子文本居中异常
|
||||
- 🐛 修复侧边栏跳转角色/武器图鉴异常
|
||||
- ✏️ 调整分享图大小计算方式,采用1024进制而非原有的1000进制
|
||||
- 💄 调整用户等级UI,浅色深色下统一为白色文字
|
||||
- 💄 调整回复弹窗位置,上移一段距离以避免底部提示遮挡
|
||||
- 💄 首页素材日历组件只显示日期,移除具体时间
|
||||
- 💄 调整链接卡片提示文字
|
||||
- 💄 调整剧诗角色列表显示UI
|
||||
- 🚸 版块/咨讯页数据获取/刷新显示成功提示
|
||||
- 🚸 首页近期活动卡片Icon补充缺失的点击逻辑
|
||||
- 🚸 调整合集组件改版后的滚动逻辑,更加流畅
|
||||
- 👽️ 由于API变更,调整版块数据获取逻辑
|
||||
- 👽️ 由于返回数据格式变更,调整视频时长的计算逻辑
|
||||
- 👽️ 由于返回数据格式变更,处理帖子内的转义字符
|
||||
- ♻️ loading组件重构,部分页面显示更精准的进度
|
||||
- ♻️ 应用元数据格式重构,剔除冗余数据
|
||||
|
||||
## [0.6.6](https://github.com/BTMuli/TeyvatGuide/releases/v0.6.6) (2024-12-13)
|
||||
|
||||
- 🐛 修复主题切换响应异常
|
||||
- 🐛 修复增量刷新逻辑异常
|
||||
- ⚡️ 显著降低运行内存占用
|
||||
|
||||
## [0.6.5](https://github.com/BTMuli/TeyvatGuide/releases/v0.6.5) (2024-12-11)
|
||||
|
||||
- 🍱 添加下半卡池数据&部分资源
|
||||
- ✨ 帖子内容中涉及的话题链接支持应用内跳转
|
||||
- ♻️ 首页组件加载逻辑重构
|
||||
- ✨ UIGF4导入/导出浮窗,支持自选UID
|
||||
- 💄 调整剧诗部分数据缺失时的显示
|
||||
- 🐛 调整部分UI,修复切换账户后角色详情刷新异常
|
||||
|
||||
## [0.6.4](https://github.com/BTMuli/TeyvatGuide/releases/v0.6.4) (2024-12-03)
|
||||
|
||||
- 🐛 修复子回复渲染异常
|
||||
- ✏️ 祈愿记录将验证非空ID
|
||||
- 🐛 修复战绩分享图渲染异常
|
||||
- 🐛 修复`dialog`组件`input`默认值无效
|
||||
- 🎨 调整帖子查找overlay逻辑
|
||||
- ✨ 分享图生成阈值自定义
|
||||
- 👽️ 全量刷新时清理旧数据,修复由于米哈游数据异常导致的重复数据
|
||||
|
||||
## [0.6.3](https://github.com/BTMuli/TeyvatGuide/releases/v0.6.3) (2024-11-19)
|
||||
|
||||
- 🐛 修复用户战绩角色数据`undefined`
|
||||
- 🐛 修复咨讯页加载更多异常
|
||||
- 🐛 修复验证码登录提示`-100`,数据刷新后若为已登录UID则不会再提示切换
|
||||
- 🐛 修复部分公告渲染异常
|
||||
- 🐛 修复成就页面在存在搜索内容时点击左侧成就系列无响应
|
||||
- ✨ 帖子新增 UID 卡片解析&渲染
|
||||
- ✨ 帖子新增自定义表情解析&渲染
|
||||
- ✨ 真境剧诗适配,新增真境剧诗页面,支持获取&分享&上传(胡桃数据库),可通过深渊页面进入
|
||||
- ✨ 新增话题页面,可通过帖子卡片标签点击或帖子详情顶部标签点击进入
|
||||
- ✨ 更完善的`loading`显示,调整了组件UI
|
||||
- 🍱 更新5.2版本资源 [`#133`](https://github.com/BTMuli/TeyvatGuide/issues/133)
|
||||
- 💄 调整祈愿记录UP四星颜色
|
||||
- 💄 修复帖子页兑换码弹窗高度异常
|
||||
- 💄 调整帖子卡片UI,增加显示帖子话题(如存在),话题&版块支持点击跳转
|
||||
- 💄 调整帖子详情页UI,顶部话题&版块支持点击跳转
|
||||
- 💄 调整帖子显示数量,支持加载更多,默认排序改为`最新回复`,移除`默认排序`,增加`热门`排序
|
||||
- 💄 咨讯、帖子等页面刷新时自动滚动到顶部
|
||||
- 🔥 深渊数据库显示移除第9层统计数据
|
||||
- 👽️ 米游社子窗口增加`genshinnet`域名支持
|
||||
- 🎨 优化帖子详情数据加载的错误处理
|
||||
- ♻️ `snackbar`、`confirm`、`loading`组件重构
|
||||
- ♻️ 请求模块重构
|
||||
|
||||
## [0.6.2](https://github.com/BTMuli/TeyvatGuide/releases/v0.6.2) (2024-10-31)
|
||||
|
||||
- 🐛 修复用户登录状态异常 [`#132`](https://github.com/BTMuli/TeyvatGudie/issues/132)
|
||||
- 💄 帖子子回复取消保持,点击其他隐藏
|
||||
- 💄 调整未登录时的部分内容渲染
|
||||
- 💄 调整保存时图片的hint
|
||||
- 💄 `mac`:修复回顶组件宽度异常
|
||||
- 💄 `mac`:修复视频封面位置异常
|
||||
- 💄 调整角色卡片UI,维持名片比例
|
||||
- ♻️ 深渊数据库重构,概览显示差距
|
||||
- 🍱 更新下半卡池
|
||||
- 👽️ 修正咨讯Api
|
||||
|
||||
## [0.6.1](https://github.com/BTMuli/TeyvatGuide/releases/v0.6.1) (2024-10-22)
|
||||
|
||||
- 🐛 新用户数据库初始化异常 [`#131`](https://github.com/BTMuli/TeyavtGuide/issues/131)
|
||||
- 🐛 修复角色数据未即时刷新
|
||||
- 🐛 修复`openSystemBrowser`回调执行异常
|
||||
- ♻️ 公告卡片组件抽离,支持分享
|
||||
- 🎨 成就页面&名片图鉴页面采用虚拟列表优化性能
|
||||
- 🎨 调整卡片封面加载逻辑
|
||||
- 💄 处理特定情况下的内容溢出
|
||||
- 💄 适配深渊新字段,显示跳过楼层
|
||||
- 💄深渊分享显示应用信息,圣遗物详情推荐属性高亮
|
||||
- 💄调整帖子子窗口副标题样式
|
||||
- 💄调整留影叙佳期选项样式
|
||||
|
||||
## [0.6.0](https://github.com/BTMuli/TeyvatGuide/releases/v0.6.0) (2024-10-09)
|
||||
|
||||
- ✨ 应用支持多账号 [`#126`](https://github.com/BTMuli/TeyvatGuide/issues/126)
|
||||
- ✨ 支持手动输入CK&用户删除
|
||||
- ✨ 帖子卡片支持分享
|
||||
- ✨ 支持官服用户直接启动原神 [`#80`](https://github.com/BTMuli/TeyvatGuide/issues/80)
|
||||
- ♻️ 重构成就表格,支持多存档
|
||||
- ♻️ 重构深渊数据加载逻辑,适配多存档
|
||||
- ♻️ 重构用户登录逻辑及切换
|
||||
- ♻️ 重构祈愿、深渊、角色页面逻辑,支持游戏账号切换
|
||||
- ♻️ 战绩页面适配多账户
|
||||
- 💄 帖子/公告子窗口添加窗口置顶按钮
|
||||
- 💄 调整视频分享截图
|
||||
- 💄 回复分享图忽略导出图标
|
||||
- 💄 显示用户等级
|
||||
- 💄 处理特定情况下的回复内容溢出
|
||||
- 💄 兑换码支持分享,调整了兑换码浮窗UI
|
||||
- 💄 公告对列表进行缩进
|
||||
- 💄 材料Wiki样式优化,支持分类筛选&查询
|
||||
- 💄 材料详情浮窗支持分享
|
||||
- ✏️ JSBridge新增`openSystemBrowser`回调处理
|
||||
- ✏️ 修正公告正则
|
||||
- 👽️ 更新国际服公告Api
|
||||
- 📖 添加 macOS 平台门禁属性导致无法打开应用的修复指引 [`#130`](https://github.com/BTMuli/TeyvatGuide/issues/130)
|
||||
- ✨ 新增无痕浏览配置,默认开启
|
||||
- ✨ 登录状态且关闭无痕浏览时,可对帖子进行点赞操作
|
||||
- ✨ 新增实用脚本页面,支持一键完成米游币每日任务 [`#144`](https://github.com/BTMuli/TeyvatGuide/issues/144)
|
||||
- 🐛 修复公告解析异常
|
||||
- 🐛 修复角色卡片视图(详细)浮窗切换时背景图更新异常
|
||||
- 🐛 修复路由跳转不生效
|
||||
- ♻️ 重构首页素材日历组件生日计算,修复生日计算异常
|
||||
- 🚸 设置页登录二维码支持生成分享图,点击底部图标触发
|
||||
- 💄 调整首页素材日历组件可视页码
|
||||
- 💄 调整部分页面UI
|
||||
- 🍱 更新下半卡池数据
|
||||
|
||||
23
README.md
@@ -2,12 +2,12 @@
|
||||
Author: 目棃
|
||||
Description: 说明文档
|
||||
Date: 2023-03-05
|
||||
Update: 2025-01-22
|
||||
Update: 2025-02-28
|
||||
---
|
||||
|
||||
> 本文档 [`Frontmatter`](https://github.com/BTMuli/MuCli#Frontmatter) 由 [MuCli](https://github.com/BTMuli/Mucli) 自动生成于 `2023-03-05 14:41:55`
|
||||
>
|
||||
> 更新于 `2025-01-22 10:48:07`
|
||||
> 更新于 `2025-02-28 09:40:24`
|
||||
|
||||
 
|
||||
|
||||
@@ -58,14 +58,15 @@ Game Tool for Genshin Impact player, supports Windows and macOS.
|
||||
|
||||
- 登陆功能:
|
||||
|
||||
> 支持 扫码/验证码/Cookie 登陆,支持多账号管理
|
||||
> 支持 扫码/验证码/Cookie 登陆,支持多账号管理
|
||||
|
||||
- [x] 原神战绩数据获取
|
||||
- [x] 角色详情数据获取
|
||||
- [x] 螺旋深渊数据获取
|
||||
- [x] 真境剧诗数据获取
|
||||
- [x] 祈愿数据获取(近一年)
|
||||
- [x] 用户收藏帖子获取
|
||||
- [x] 原神战绩数据获取
|
||||
- [x] 角色详情数据获取
|
||||
- [x] 螺旋深渊数据获取
|
||||
- [x] 真境剧诗数据获取
|
||||
- [x] 祈愿数据获取(近一年)
|
||||
- [x] 用户收藏帖子获取
|
||||
- [x] 一键完成米游币每日任务 **需要验证码登录**
|
||||
|
||||
- Wiki 功能:
|
||||
|
||||
@@ -97,8 +98,8 @@ Game Tool for Genshin Impact player, supports Windows and macOS.
|
||||
|
||||
- Changelog: [CHANGELOG](CHANGELOG.md)
|
||||
- 资源来源:[项目资源说明](docs/项目资源说明.md)
|
||||
- UIAF:[UIAF v1.1](docs/UIAF.md)
|
||||
- UIGF:[UIGF v3.0](docs/UIGF3.md),[UIGF v4.0](docs/UIGF.md)
|
||||
- UIAF:[UIAF v1.1](docs/standards/UIAF.md)
|
||||
- UIGF:[UIGF v3.0](docs/standards/UIGF3.md),[UIGF v4.0](docs/standards/UIGF.md)
|
||||
- [macOS 平台门禁属性导致应用无法打开应用的修复指引](docs/macos-gatekeeper/README.md)
|
||||
|
||||
## 特定项目 / Special Project
|
||||
|
||||
168
docs/changelogs/CHANGELOG-v0.6.x.md
Normal file
@@ -0,0 +1,168 @@
|
||||
---
|
||||
Author: 目棃
|
||||
Description: CHANGELOG
|
||||
Date: 2024-10-09
|
||||
Update: 2025-02-11
|
||||
---
|
||||
|
||||
> 本文档 [`Frontmatter`](https://github.com/BTMuli/MuCli#Frontmatter) 由 [MuCli](https://github.com/BTMuli/Mucli) 自动生成于 `2024-10-09 15:51:43`
|
||||
>
|
||||
> 更新于 `2025-02-11 10:57:49`
|
||||
|
||||
## [0.6.9](https://github.com/BTMuli/TeyvatGuide/releases/v0.6.9) (2025-02-11)
|
||||
|
||||
- 🍱 更新5.4资源 [`#141`](https://github.com/BTMuli/TeyvatGuide/issues/141)
|
||||
- 🐛 修复米游社子窗口路径解析异常
|
||||
- 🐛 修复特定条件下真境剧诗角色元素图标渲染异常
|
||||
- 🐛 修复名片图鉴浮窗渲染异常
|
||||
- 🚸 调整兑换码入口显示判断逻辑
|
||||
- 🚸 成就导入不允许点击外部取消,调整刷新逻辑
|
||||
- 🚸 下载封面图时显示封面链接
|
||||
- 💄 调整部分UI
|
||||
|
||||
## [0.6.8](https://github.com/BTMuli/TeyvatGuide/releases/v0.6.8) (2025-01-22)
|
||||
|
||||
- ✨ 扫码登录
|
||||
- ✨ 调整祈愿记录图表样式,新增祈愿日历&祈愿堆叠柱状图
|
||||
- ✨ 支持配置帖子详情图像质量,默认80%
|
||||
- ✨ 支持帖子详情图像查看原图,当质量配置为100%时,该按钮不显示
|
||||
- ✨ 深渊上传支持胡桃账户设置
|
||||
- 🚸 降低祈愿全量刷新耗时
|
||||
- 🚸 加快帖子加载速度,降低内存占用
|
||||
- 💄 调整角色卡片样式
|
||||
- 💄 调整角色名片样式,增加描述清晰度
|
||||
- 💄 调整深渊Wiki队伍搭配窗口高度
|
||||
- 💄 mac下不显示分享设置
|
||||
- 💄 调整战绩页新洞天渲染样式
|
||||
- 🔥 深渊Wiki移除第10层数据
|
||||
- 🐛 修复深渊数据恢复异常
|
||||
- 🐛 修复 loading 组件 empty 状态设置异常
|
||||
- ♻️ 优化帖子加载逻辑,当刷新内容不足20条时,下次刷新数量为20-当前数量,如刷新数量为19条,则下次刷新数量为1条
|
||||
- ♻️ 动态获取分区列表&版块列表
|
||||
- ♻️ 重构部分路由处理,当话题/帖子切换分区/版块时,页面刷新不重置当前分区/版块
|
||||
|
||||
## [0.6.7](https://github.com/BTMuli/TeyvatGuide/releases/v0.6.7) (2024-12-31)
|
||||
|
||||
- 🍱 更新5.3版本游戏资源 [`#139`](https://github.com/BTMuli/TeyvatGuide/issues/139)
|
||||
- ✨ 支持嵌入B站视频的分享图渲染
|
||||
- 🐛 修复版块跳转异常
|
||||
- 🐛 修复清理日志异常
|
||||
- 🐛 修复特定帖子`link_card_ids`数据解析异常
|
||||
- 🐛 修复帖子文本居中异常
|
||||
- 🐛 修复侧边栏跳转角色/武器图鉴异常
|
||||
- ✏️ 调整分享图大小计算方式,采用1024进制而非原有的1000进制
|
||||
- 💄 调整用户等级UI,浅色深色下统一为白色文字
|
||||
- 💄 调整回复弹窗位置,上移一段距离以避免底部提示遮挡
|
||||
- 💄 首页素材日历组件只显示日期,移除具体时间
|
||||
- 💄 调整链接卡片提示文字
|
||||
- 💄 调整剧诗角色列表显示UI
|
||||
- 🚸 版块/咨讯页数据获取/刷新显示成功提示
|
||||
- 🚸 首页近期活动卡片Icon补充缺失的点击逻辑
|
||||
- 🚸 调整合集组件改版后的滚动逻辑,更加流畅
|
||||
- 👽️ 由于API变更,调整版块数据获取逻辑
|
||||
- 👽️ 由于返回数据格式变更,调整视频时长的计算逻辑
|
||||
- 👽️ 由于返回数据格式变更,处理帖子内的转义字符
|
||||
- ♻️ loading组件重构,部分页面显示更精准的进度
|
||||
- ♻️ 应用元数据格式重构,剔除冗余数据
|
||||
|
||||
## [0.6.6](https://github.com/BTMuli/TeyvatGuide/releases/v0.6.6) (2024-12-13)
|
||||
|
||||
- 🐛 修复主题切换响应异常
|
||||
- 🐛 修复增量刷新逻辑异常
|
||||
- ⚡️ 显著降低运行内存占用
|
||||
|
||||
## [0.6.5](https://github.com/BTMuli/TeyvatGuide/releases/v0.6.5) (2024-12-11)
|
||||
|
||||
- 🍱 添加下半卡池数据&部分资源
|
||||
- ✨ 帖子内容中涉及的话题链接支持应用内跳转
|
||||
- ♻️ 首页组件加载逻辑重构
|
||||
- ✨ UIGF4导入/导出浮窗,支持自选UID
|
||||
- 💄 调整剧诗部分数据缺失时的显示
|
||||
- 🐛 调整部分UI,修复切换账户后角色详情刷新异常
|
||||
|
||||
## [0.6.4](https://github.com/BTMuli/TeyvatGuide/releases/v0.6.4) (2024-12-03)
|
||||
|
||||
- 🐛 修复子回复渲染异常
|
||||
- ✏️ 祈愿记录将验证非空ID
|
||||
- 🐛 修复战绩分享图渲染异常
|
||||
- 🐛 修复`dialog`组件`input`默认值无效
|
||||
- 🎨 调整帖子查找overlay逻辑
|
||||
- ✨ 分享图生成阈值自定义
|
||||
- 👽️ 全量刷新时清理旧数据,修复由于米哈游数据异常导致的重复数据
|
||||
|
||||
## [0.6.3](https://github.com/BTMuli/TeyvatGuide/releases/v0.6.3) (2024-11-19)
|
||||
|
||||
- 🐛 修复用户战绩角色数据`undefined`
|
||||
- 🐛 修复咨讯页加载更多异常
|
||||
- 🐛 修复验证码登录提示`-100`,数据刷新后若为已登录UID则不会再提示切换
|
||||
- 🐛 修复部分公告渲染异常
|
||||
- 🐛 修复成就页面在存在搜索内容时点击左侧成就系列无响应
|
||||
- ✨ 帖子新增 UID 卡片解析&渲染
|
||||
- ✨ 帖子新增自定义表情解析&渲染
|
||||
- ✨ 真境剧诗适配,新增真境剧诗页面,支持获取&分享&上传(胡桃数据库),可通过深渊页面进入
|
||||
- ✨ 新增话题页面,可通过帖子卡片标签点击或帖子详情顶部标签点击进入
|
||||
- ✨ 更完善的`loading`显示,调整了组件UI
|
||||
- 🍱 更新5.2版本资源 [`#133`](https://github.com/BTMuli/TeyvatGuide/issues/133)
|
||||
- 💄 调整祈愿记录UP四星颜色
|
||||
- 💄 修复帖子页兑换码弹窗高度异常
|
||||
- 💄 调整帖子卡片UI,增加显示帖子话题(如存在),话题&版块支持点击跳转
|
||||
- 💄 调整帖子详情页UI,顶部话题&版块支持点击跳转
|
||||
- 💄 调整帖子显示数量,支持加载更多,默认排序改为`最新回复`,移除`默认排序`,增加`热门`排序
|
||||
- 💄 咨讯、帖子等页面刷新时自动滚动到顶部
|
||||
- 🔥 深渊数据库显示移除第9层统计数据
|
||||
- 👽️ 米游社子窗口增加`genshinnet`域名支持
|
||||
- 🎨 优化帖子详情数据加载的错误处理
|
||||
- ♻️ `snackbar`、`confirm`、`loading`组件重构
|
||||
- ♻️ 请求模块重构
|
||||
|
||||
## [0.6.2](https://github.com/BTMuli/TeyvatGuide/releases/v0.6.2) (2024-10-31)
|
||||
|
||||
- 🐛 修复用户登录状态异常 [`#132`](https://github.com/BTMuli/TeyvatGudie/issues/132)
|
||||
- 💄 帖子子回复取消保持,点击其他隐藏
|
||||
- 💄 调整未登录时的部分内容渲染
|
||||
- 💄 调整保存时图片的hint
|
||||
- 💄 `mac`:修复回顶组件宽度异常
|
||||
- 💄 `mac`:修复视频封面位置异常
|
||||
- 💄 调整角色卡片UI,维持名片比例
|
||||
- ♻️ 深渊数据库重构,概览显示差距
|
||||
- 🍱 更新下半卡池
|
||||
- 👽️ 修正咨讯Api
|
||||
|
||||
## [0.6.1](https://github.com/BTMuli/TeyvatGuide/releases/v0.6.1) (2024-10-22)
|
||||
|
||||
- 🐛 新用户数据库初始化异常 [`#131`](https://github.com/BTMuli/TeyavtGuide/issues/131)
|
||||
- 🐛 修复角色数据未即时刷新
|
||||
- 🐛 修复`openSystemBrowser`回调执行异常
|
||||
- ♻️ 公告卡片组件抽离,支持分享
|
||||
- 🎨 成就页面&名片图鉴页面采用虚拟列表优化性能
|
||||
- 🎨 调整卡片封面加载逻辑
|
||||
- 💄 处理特定情况下的内容溢出
|
||||
- 💄 适配深渊新字段,显示跳过楼层
|
||||
- 💄深渊分享显示应用信息,圣遗物详情推荐属性高亮
|
||||
- 💄调整帖子子窗口副标题样式
|
||||
- 💄调整留影叙佳期选项样式
|
||||
|
||||
## [0.6.0](https://github.com/BTMuli/TeyvatGuide/releases/v0.6.0) (2024-10-09)
|
||||
|
||||
- ✨ 应用支持多账号 [`#126`](https://github.com/BTMuli/TeyvatGuide/issues/126)
|
||||
- ✨ 支持手动输入CK&用户删除
|
||||
- ✨ 帖子卡片支持分享
|
||||
- ✨ 支持官服用户直接启动原神 [`#80`](https://github.com/BTMuli/TeyvatGuide/issues/80)
|
||||
- ♻️ 重构成就表格,支持多存档
|
||||
- ♻️ 重构深渊数据加载逻辑,适配多存档
|
||||
- ♻️ 重构用户登录逻辑及切换
|
||||
- ♻️ 重构祈愿、深渊、角色页面逻辑,支持游戏账号切换
|
||||
- ♻️ 战绩页面适配多账户
|
||||
- 💄 帖子/公告子窗口添加窗口置顶按钮
|
||||
- 💄 调整视频分享截图
|
||||
- 💄 回复分享图忽略导出图标
|
||||
- 💄 显示用户等级
|
||||
- 💄 处理特定情况下的回复内容溢出
|
||||
- 💄 兑换码支持分享,调整了兑换码浮窗UI
|
||||
- 💄 公告对列表进行缩进
|
||||
- 💄 材料Wiki样式优化,支持分类筛选&查询
|
||||
- 💄 材料详情浮窗支持分享
|
||||
- ✏️ JSBridge新增`openSystemBrowser`回调处理
|
||||
- ✏️ 修正公告正则
|
||||
- 👽️ 更新国际服公告Api
|
||||
- 📖 添加 macOS 平台门禁属性导致无法打开应用的修复指引 [`#130`](https://github.com/BTMuli/TeyvatGuide/issues/130)
|
||||
@@ -2,12 +2,12 @@
|
||||
Author: 目棃
|
||||
Description: 项目资源说明
|
||||
Date: 2023-03-10
|
||||
Update: 2024-09-19
|
||||
Update: 2025-02-28
|
||||
---
|
||||
|
||||
> 本文档 [`Frontmatter`](https://github.com/BTMuli/MuCli#Frontmatter) 由 [MuCli](https://github.com/BTMuli/Mucli) 自动生成于 `2023-03-10 22:05:44`
|
||||
>
|
||||
> 更新于 `2024-09-19 15:28:16`
|
||||
> 更新于 `2025-02-28 09:40:33`
|
||||
|
||||
## 说明
|
||||
|
||||
@@ -28,6 +28,7 @@ Update: 2024-09-19
|
||||
- 我的角色:Hoyolab
|
||||
- 深渊记录:Hoyolab
|
||||
- 祈愿记录:Hoyolab
|
||||
- 实用脚本:Hoyolab
|
||||
- 图鉴:Hoyolab,其子目录图标同样来源于 Hoyolab
|
||||
- 模式切换:`mdi-weather-night` `mdi-weather-sunny`
|
||||
- 设置:个人绘制 SVG
|
||||
|
||||
68
package.json
@@ -1,9 +1,9 @@
|
||||
{
|
||||
"name": "teyvatguide",
|
||||
"version": "0.6.8",
|
||||
"version": "0.7.0",
|
||||
"description": "Game Tool for GenshinImpact player",
|
||||
"private": true,
|
||||
"packageManager": "pnpm@10.0.0",
|
||||
"packageManager": "pnpm@10.5.2",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "tauri build",
|
||||
@@ -12,6 +12,7 @@
|
||||
"eslint:pre": "pnpx @eslint/config-inspector@latest",
|
||||
"lint": "concurrently \"pnpm:lint:*(!fix)\"",
|
||||
"lint:fix": "concurrently \"pnpm:lint:*:fix\"",
|
||||
"lint:vue": "vue-tsc --noEmit",
|
||||
"lint:code": "eslint .",
|
||||
"lint:code:fix": "eslint . --fix",
|
||||
"lint:style": "stylelint \"src/**/*.{vue,css,scss}\" -f verbose",
|
||||
@@ -68,12 +69,12 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@mdi/font": "7.4.47",
|
||||
"@tauri-apps/api": "^2.2.0",
|
||||
"@tauri-apps/api": "^2.3.0",
|
||||
"@tauri-apps/plugin-deep-link": "^2.2.0",
|
||||
"@tauri-apps/plugin-dialog": "^2.2.0",
|
||||
"@tauri-apps/plugin-fs": "^2.2.0",
|
||||
"@tauri-apps/plugin-http": "^2.2.0",
|
||||
"@tauri-apps/plugin-log": "^2.2.0",
|
||||
"@tauri-apps/plugin-http": "^2.3.0",
|
||||
"@tauri-apps/plugin-log": "^2.2.2",
|
||||
"@tauri-apps/plugin-os": "^2.2.0",
|
||||
"@tauri-apps/plugin-process": "^2.2.0",
|
||||
"@tauri-apps/plugin-shell": "^2.2.0",
|
||||
@@ -81,65 +82,66 @@
|
||||
"ajv": "^8.17.1",
|
||||
"artplayer": "^5.2.2",
|
||||
"clipboard": "^2.0.11",
|
||||
"color-convert": "^2.0.1",
|
||||
"color-convert": "^3.0.1",
|
||||
"echarts": "^5.6.0",
|
||||
"html2canvas": "^1.4.1",
|
||||
"js-md5": "^0.8.3",
|
||||
"jsencrypt": "^3.3.2",
|
||||
"pinia": "^2.3.1",
|
||||
"pinia": "^3.0.1",
|
||||
"pinia-plugin-persistedstate": "^4.2.0",
|
||||
"qrcode.vue": "^3.6.0",
|
||||
"sass": "^1.83.4",
|
||||
"sass-loader": "^16.0.4",
|
||||
"uuid": "^11.0.5",
|
||||
"sass": "^1.85.1",
|
||||
"sass-loader": "^16.0.5",
|
||||
"uuid": "^11.1.0",
|
||||
"vue": "^3.5.13",
|
||||
"vue-echarts": "^7.0.3",
|
||||
"vue-json-viewer": "^3.0.4",
|
||||
"vue-json-pretty": "^2.4.0",
|
||||
"vue-router": "^4.5.0",
|
||||
"vuetify": "^3.7.7",
|
||||
"vuetify": "^3.7.14",
|
||||
"wcag-color": "^1.1.1",
|
||||
"xml-js": "^1.6.11"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/eslintrc": "^3.2.0",
|
||||
"@eslint/js": "^9.18.0",
|
||||
"@tauri-apps/cli": "2.2.5",
|
||||
"@eslint/eslintrc": "^3.3.0",
|
||||
"@eslint/js": "^9.21.0",
|
||||
"@tauri-apps/cli": "2.3.0",
|
||||
"@types/color-convert": "^2.0.4",
|
||||
"@types/fs-extra": "^11.0.4",
|
||||
"@types/js-md5": "^0.7.2",
|
||||
"@types/node": "^22.10.7",
|
||||
"@types/node": "^22.13.5",
|
||||
"@types/uuid": "^10.0.0",
|
||||
"@typescript-eslint/parser": "^8.21.0",
|
||||
"@typescript-eslint/parser": "^8.25.0",
|
||||
"@vitejs/plugin-vue": "^5.2.1",
|
||||
"concurrently": "^9.1.2",
|
||||
"eslint": "^9.18.0",
|
||||
"eslint": "^9.21.0",
|
||||
"eslint-plugin-import": "^2.31.0",
|
||||
"eslint-plugin-jsonc": "^2.18.2",
|
||||
"eslint-plugin-jsonc": "^2.19.1",
|
||||
"eslint-plugin-prettier": "^5.2.3",
|
||||
"eslint-plugin-vue": "^9.32.0",
|
||||
"eslint-plugin-yml": "^1.16.0",
|
||||
"eslint-plugin-yml": "^1.17.0",
|
||||
"fs-extra": "^11.3.0",
|
||||
"globals": "^15.14.0",
|
||||
"globals": "^16.0.0",
|
||||
"husky": "^9.1.7",
|
||||
"jsonc-eslint-parser": "^2.4.0",
|
||||
"lint-staged": "^15.4.1",
|
||||
"oxlint": "^0.15.7",
|
||||
"prettier": "3.4.2",
|
||||
"stylelint": "^16.13.2",
|
||||
"lint-staged": "^15.4.3",
|
||||
"oxlint": "^0.15.12",
|
||||
"prettier": "3.5.2",
|
||||
"stylelint": "^16.14.1",
|
||||
"stylelint-config-idiomatic-order": "^10.0.0",
|
||||
"stylelint-config-standard-vue": "^1.0.0",
|
||||
"stylelint-declaration-block-no-ignored-properties": "^2.8.0",
|
||||
"stylelint-high-performance-animation": "^1.10.0",
|
||||
"stylelint-high-performance-animation": "^1.11.0",
|
||||
"stylelint-order": "^6.0.4",
|
||||
"stylelint-prettier": "^5.0.2",
|
||||
"stylelint-scss": "^6.10.1",
|
||||
"tsx": "^4.19.2",
|
||||
"stylelint-prettier": "^5.0.3",
|
||||
"stylelint-scss": "^6.11.1",
|
||||
"tsx": "^4.19.3",
|
||||
"typescript": "^5.7.3",
|
||||
"typescript-eslint": "^8.21.0",
|
||||
"vite": "^6.0.11",
|
||||
"vite-plugin-vue-devtools": "^7.7.0",
|
||||
"vite-plugin-vuetify": "^2.0.4",
|
||||
"typescript-eslint": "^8.25.0",
|
||||
"vite": "^6.2.0",
|
||||
"vite-plugin-vue-devtools": "^7.7.2",
|
||||
"vite-plugin-vuetify": "^2.1.0",
|
||||
"vue-eslint-parser": "^9.4.3",
|
||||
"vue-tsc": "^2.2.4",
|
||||
"yaml-eslint-parser": "^1.2.3"
|
||||
}
|
||||
}
|
||||
|
||||
2513
pnpm-lock.yaml
generated
BIN
public/WIKI/character/10000109.webp
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
public/WIKI/nameCard/bg/庆典·炙热.webp
Normal file
|
After Width: | Height: | Size: 29 KiB |
BIN
public/WIKI/nameCard/bg/梦见月瑞希·噩喰.webp
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
public/WIKI/nameCard/bg/纪行·绮梦.webp
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
public/WIKI/nameCard/icon/庆典·炙热.webp
Normal file
|
After Width: | Height: | Size: 6.5 KiB |
BIN
public/WIKI/nameCard/icon/梦见月瑞希·噩喰.webp
Normal file
|
After Width: | Height: | Size: 5.0 KiB |
BIN
public/WIKI/nameCard/icon/纪行·绮梦.webp
Normal file
|
After Width: | Height: | Size: 4.0 KiB |
BIN
public/WIKI/nameCard/profile/庆典·炙热.webp
Normal file
|
After Width: | Height: | Size: 36 KiB |
BIN
public/WIKI/nameCard/profile/梦见月瑞希·噩喰.webp
Normal file
|
After Width: | Height: | Size: 23 KiB |
BIN
public/WIKI/nameCard/profile/纪行·绮梦.webp
Normal file
|
After Width: | Height: | Size: 30 KiB |
BIN
public/WIKI/weapon/13432.webp
Normal file
|
After Width: | Height: | Size: 8.9 KiB |
BIN
public/WIKI/weapon/14518.webp
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
public/icon/constellations/UI_Talent_S_Mizuki_01.webp
Normal file
|
After Width: | Height: | Size: 3.0 KiB |
BIN
public/icon/constellations/UI_Talent_S_Mizuki_02.webp
Normal file
|
After Width: | Height: | Size: 3.7 KiB |
BIN
public/icon/constellations/UI_Talent_S_Mizuki_03.webp
Normal file
|
After Width: | Height: | Size: 3.9 KiB |
BIN
public/icon/constellations/UI_Talent_S_Mizuki_04.webp
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
BIN
public/icon/constellations/UI_Talent_U_Mizuki_01.webp
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
BIN
public/icon/constellations/UI_Talent_U_Mizuki_02.webp
Normal file
|
After Width: | Height: | Size: 3.0 KiB |
BIN
public/icon/talents/Skill_E_Mizuki_01.webp
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
BIN
public/icon/talents/Skill_S_Mizuki_01.webp
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
BIN
public/icon/talents/UI_Talent_S_Mizuki_05.webp
Normal file
|
After Width: | Height: | Size: 3.4 KiB |
BIN
public/icon/talents/UI_Talent_S_Mizuki_06.webp
Normal file
|
After Width: | Height: | Size: 2.6 KiB |
BIN
public/icon/talents/UI_Talent_S_Mizuki_07.webp
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
public/platforms/mhy/launcher.webp
Normal file
|
After Width: | Height: | Size: 8.5 KiB |
|
Before Width: | Height: | Size: 30 KiB |
BIN
public/source/UI/act_birthday.webp
Normal file
|
After Width: | Height: | Size: 6.2 KiB |
|
Before Width: | Height: | Size: 2.0 KiB |
BIN
public/source/UI/posts.webp
Normal file
|
After Width: | Height: | Size: 776 B |
BIN
public/source/UI/toolbox.webp
Normal file
|
After Width: | Height: | Size: 5.0 KiB |
|
Before Width: | Height: | Size: 2.9 KiB |
BIN
public/source/UI/video_play_bili.webp
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
1158
src-tauri/Cargo.lock
generated
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "TeyvatGuide"
|
||||
version = "0.6.8"
|
||||
version = "0.7.0"
|
||||
description = "Game Tool for Genshin Impact player"
|
||||
authors = ["BTMuli <bt-muli@outlook.com>"]
|
||||
license = "MIT"
|
||||
@@ -10,15 +10,15 @@ edition = "2021"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[build-dependencies]
|
||||
tauri-build = { version = "2.0.5", features = [] }
|
||||
tauri-build = { version = "2.0.6", features = [] }
|
||||
|
||||
[dependencies]
|
||||
chrono = "0.4.39"
|
||||
log = "0.4.25"
|
||||
serde = { version = "1.0.217", features = ["derive"] }
|
||||
serde_json = "1.0.137"
|
||||
tauri = { version = "2.2.3", features = [] }
|
||||
tauri-utils = "2.1.1"
|
||||
chrono = "0.4.40"
|
||||
log = "0.4.26"
|
||||
serde = { version = "1.0.218", features = ["derive"] }
|
||||
serde_json = "1.0.139"
|
||||
tauri = { version = "2.3.0", features = [] }
|
||||
tauri-utils = "2.2.0"
|
||||
url = "2.5.4"
|
||||
walkdir = "2.5.0"
|
||||
|
||||
|
||||
@@ -3644,7 +3644,7 @@
|
||||
"process": {
|
||||
"default_permission": {
|
||||
"identifier": "default",
|
||||
"description": "This permission set configures which\nprocess feeatures are by default exposed.\n\n#### Granted Permissions\n\nThis enables to quit via `allow-exit` and restart via `allow-restart`\nthe application.\n",
|
||||
"description": "This permission set configures which\nprocess features are by default exposed.\n\n#### Granted Permissions\n\nThis enables to quit via `allow-exit` and restart via `allow-restart`\nthe application.\n",
|
||||
"permissions": ["allow-exit", "allow-restart"]
|
||||
},
|
||||
"permissions": {
|
||||
|
||||
@@ -5182,7 +5182,7 @@
|
||||
"const": "os:deny-version"
|
||||
},
|
||||
{
|
||||
"description": "This permission set configures which\nprocess feeatures are by default exposed.\n\n#### Granted Permissions\n\nThis enables to quit via `allow-exit` and restart via `allow-restart`\nthe application.\n",
|
||||
"description": "This permission set configures which\nprocess features are by default exposed.\n\n#### Granted Permissions\n\nThis enables to quit via `allow-exit` and restart via `allow-restart`\nthe application.\n",
|
||||
"type": "string",
|
||||
"const": "process:default"
|
||||
},
|
||||
|
||||
@@ -5182,7 +5182,7 @@
|
||||
"const": "os:deny-version"
|
||||
},
|
||||
{
|
||||
"description": "This permission set configures which\nprocess feeatures are by default exposed.\n\n#### Granted Permissions\n\nThis enables to quit via `allow-exit` and restart via `allow-restart`\nthe application.\n",
|
||||
"description": "This permission set configures which\nprocess features are by default exposed.\n\n#### Granted Permissions\n\nThis enables to quit via `allow-exit` and restart via `allow-restart`\nthe application.\n",
|
||||
"type": "string",
|
||||
"const": "process:default"
|
||||
},
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
//! @file src/client/mod.rs
|
||||
//! @desc 客户端模块,负责操作米游社客户端
|
||||
//! @since Beta v0.6.8
|
||||
//! @since Beta v0.7.0
|
||||
|
||||
mod menu;
|
||||
mod utils;
|
||||
@@ -8,7 +8,7 @@ mod utils;
|
||||
use tauri::{AppHandle, Manager, WebviewWindowBuilder};
|
||||
use tauri_utils::config::WebviewUrl;
|
||||
|
||||
static BBS_VERSION: &'static str = "2.80.1";
|
||||
static BBS_VERSION: &'static str = "2.82.0";
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn create_mhy_client(handle: AppHandle, func: String, url: String) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"productName": "TeyvatGuide",
|
||||
"identifier": "TeyvatGuide",
|
||||
"version": "0.6.8",
|
||||
"version": "0.7.0",
|
||||
"build": {
|
||||
"beforeDevCommand": "pnpm vite:dev",
|
||||
"beforeBuildCommand": "pnpm vite:build",
|
||||
|
||||
@@ -36,9 +36,9 @@ const codeData = shallowRef<TGApp.BBS.Navigator.CodeData[]>([]);
|
||||
const showOverlay = ref<boolean>(false);
|
||||
const actId = ref<string>();
|
||||
|
||||
const hasNav = computed<boolean>(() => {
|
||||
if (props.modelValue !== 2) return false;
|
||||
return nav.value.find((item) => item.name === "前瞻直播") !== undefined;
|
||||
const hasNav = computed<TGApp.BBS.Navigator.Navigator | undefined>(() => {
|
||||
if (props.modelValue !== 2) return undefined;
|
||||
return nav.value.find((item) => item.name === "前瞻直播" || item.name === "直播兑换码");
|
||||
});
|
||||
|
||||
onMounted(async () => await loadNav());
|
||||
@@ -54,9 +54,8 @@ async function loadNav(): Promise<void> {
|
||||
|
||||
async function tryGetCode(): Promise<void> {
|
||||
if (props.modelValue !== 2) return;
|
||||
const navFind = nav.value.find((item) => item.name === "前瞻直播");
|
||||
if (!navFind) return;
|
||||
const actIdFind = new URL(navFind.app_path).searchParams.get("act_id");
|
||||
if (!hasNav.value) return;
|
||||
const actIdFind = new URL(hasNav.value.app_path).searchParams.get("act_id");
|
||||
if (!actIdFind) {
|
||||
showSnackbar.warn("未找到活动ID");
|
||||
return;
|
||||
|
||||
@@ -7,7 +7,9 @@
|
||||
<slot name="icon"><img :src="props.modelValue.icon" alt="icon" /></slot>
|
||||
</div>
|
||||
<div class="tib-cover">
|
||||
<div class="tib-lt"><img :src="props.modelValue.lt" alt="lt" /></div>
|
||||
<div class="tib-lt" v-show="props.modelValue.lt !== ''">
|
||||
<img :src="props.modelValue.lt" alt="lt" />
|
||||
</div>
|
||||
<div v-show="props.modelValue.rt" class="tib-rt">{{ props.modelValue.rt }}</div>
|
||||
<div class="tib-inner">
|
||||
<slot name="inner-icon">
|
||||
|
||||
@@ -7,7 +7,9 @@
|
||||
@click="emits('click')"
|
||||
:class="props.class"
|
||||
/>
|
||||
<v-progress-circular v-else indeterminate color="primary" size="25" />
|
||||
<div class="progress" v-else>
|
||||
<v-progress-circular indeterminate color="primary" size="25" />
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, onUnmounted, ref, watch } from "vue";
|
||||
@@ -22,9 +24,7 @@ type TMiImgProps = {
|
||||
class?: string;
|
||||
ori?: boolean;
|
||||
};
|
||||
type TMiImgEmits = {
|
||||
(e: "click"): void;
|
||||
};
|
||||
type TMiImgEmits = (e: "click") => void;
|
||||
const props = defineProps<TMiImgProps>();
|
||||
const emits = defineEmits<TMiImgEmits>();
|
||||
|
||||
@@ -42,6 +42,7 @@ watch(
|
||||
async () => {
|
||||
if (!props.src) return;
|
||||
if (localUrl.value) URL.revokeObjectURL(localUrl.value);
|
||||
localUrl.value = undefined;
|
||||
const link = props.ori ? props.src : appStore.getImageUrl(props.src);
|
||||
localUrl.value = await saveImgLocal(link);
|
||||
},
|
||||
@@ -51,3 +52,13 @@ onUnmounted(() => {
|
||||
if (localUrl.value) URL.revokeObjectURL(localUrl.value);
|
||||
});
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.progress {
|
||||
width: 25px;
|
||||
height: 25px;
|
||||
display: flex;
|
||||
position: relative;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -293,7 +293,6 @@ async function toForum(forum: TGApp.Plugins.Mys.News.RenderForum): Promise<void>
|
||||
align-items: flex-start;
|
||||
justify-content: flex-start;
|
||||
color: var(--box-text-5);
|
||||
cursor: pointer;
|
||||
font-size: 12px;
|
||||
gap: 5px;
|
||||
|
||||
@@ -310,6 +309,7 @@ async function toForum(forum: TGApp.Plugins.Mys.News.RenderForum): Promise<void>
|
||||
border: 1px solid var(--common-shadow-1);
|
||||
border-radius: 5px;
|
||||
background: var(--box-bg-2);
|
||||
cursor: pointer;
|
||||
gap: 3px;
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
<v-list-item :title.attr="'帖子'" :link="true" href="/posts/forum">
|
||||
<template #title>帖子</template>
|
||||
<template #prepend>
|
||||
<img src="/source/UI/posts.png" alt="posts" class="side-icon" />
|
||||
<img src="/source/UI/posts.webp" alt="posts" class="side-icon" />
|
||||
</template>
|
||||
</v-list-item>
|
||||
<v-list-item :title.attr="'成就'" :link="true" href="/achievements">
|
||||
@@ -62,6 +62,12 @@
|
||||
<img src="/source/UI/userGacha.webp" alt="gacha" class="side-icon" />
|
||||
</template>
|
||||
</v-list-item>
|
||||
<v-list-item :title.attr="'实用脚本'" :link="true" href="/user/scripts">
|
||||
<template #title>实用脚本</template>
|
||||
<template #prepend>
|
||||
<img src="/source/UI/toolbox.webp" alt="scripts" class="side-icon" />
|
||||
</template>
|
||||
</v-list-item>
|
||||
<v-divider />
|
||||
<v-list-item
|
||||
v-show="isDevEnv"
|
||||
@@ -114,7 +120,7 @@
|
||||
<v-list-item :title.attr="'留影叙佳期'" :link="true" href="/archive/birthday">
|
||||
<template #title>留影叙佳期</template>
|
||||
<template #prepend>
|
||||
<img src="/source/UI/act_birthday.png" alt="archive_birthday_icon" class="side-icon" />
|
||||
<img src="/source/UI/act_birthday.webp" alt="archive_birthday_icon" class="side-icon" />
|
||||
</template>
|
||||
</v-list-item>
|
||||
<div class="bottom-menu">
|
||||
@@ -145,7 +151,7 @@
|
||||
</v-list-item>
|
||||
<v-list-item class="side-item-menu" title="收藏" :link="true" href="/collection">
|
||||
<template #prepend>
|
||||
<img src="/source/UI/posts.png" alt="collect" class="side-icon-menu" />
|
||||
<img src="/source/UI/posts.webp" alt="collect" class="side-icon-menu" />
|
||||
</template>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
|
||||
@@ -1,31 +1,33 @@
|
||||
<template>
|
||||
<TOverlay v-model="visible" v-if="props.data">
|
||||
<slot name="left"></slot>
|
||||
<div class="ton-box">
|
||||
<img
|
||||
alt="bg"
|
||||
class="ton-bg"
|
||||
v-if="props.data"
|
||||
:src="`/WIKI/nameCard/profile/${props.data.name}.webp`"
|
||||
/>
|
||||
<div class="ton-content">
|
||||
<span>{{ props.data.name }}</span>
|
||||
<span>{{ parseNameCard(props.data.desc) }}</span>
|
||||
<span>获取途径:{{ props.data.source }}</span>
|
||||
<div class="ton-container">
|
||||
<slot name="left"></slot>
|
||||
<div class="ton-box">
|
||||
<img
|
||||
alt="bg"
|
||||
class="ton-bg"
|
||||
v-if="props.data"
|
||||
:src="`/WIKI/nameCard/profile/${props.data.name}.webp`"
|
||||
/>
|
||||
<div class="ton-content">
|
||||
<span>{{ props.data.name }}</span>
|
||||
<span>{{ parseNameCard(props.data.desc) }}</span>
|
||||
<span>获取途径:{{ props.data.source }}</span>
|
||||
</div>
|
||||
<div class="ton-type">{{ getType }}</div>
|
||||
<v-btn
|
||||
class="ton-share"
|
||||
@click="shareNameCard"
|
||||
variant="outlined"
|
||||
:loading="loading"
|
||||
data-html2canvas-ignore
|
||||
>
|
||||
<v-icon>mdi-share-variant</v-icon>
|
||||
<span>分享</span>
|
||||
</v-btn>
|
||||
</div>
|
||||
<div class="ton-type">{{ getType }}</div>
|
||||
<v-btn
|
||||
class="ton-share"
|
||||
@click="shareNameCard"
|
||||
variant="outlined"
|
||||
:loading="loading"
|
||||
data-html2canvas-ignore
|
||||
>
|
||||
<v-icon>mdi-share-variant</v-icon>
|
||||
<span>分享</span>
|
||||
</v-btn>
|
||||
<slot name="right"></slot>
|
||||
</div>
|
||||
<slot name="right"></slot>
|
||||
</TOverlay>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
@@ -134,6 +136,14 @@ async function shareNameCard(): Promise<void> {
|
||||
}
|
||||
</script>
|
||||
<style lang="css" scoped>
|
||||
.ton-container {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
column-gap: 8px;
|
||||
}
|
||||
|
||||
.ton-box {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<ToGameLogin v-model="showLoginQr" @success="tryGetTokens" />
|
||||
<ToGameLogin v-model="showLoginQr" @success="tryGetTokens" v-model:launcher="isLauncherQr" />
|
||||
<v-card class="tcu-box">
|
||||
<template #prepend>
|
||||
<v-avatar :image="userInfo.avatar" />
|
||||
@@ -89,7 +89,7 @@
|
||||
</v-menu>
|
||||
<v-menu location="start">
|
||||
<template v-slot:activator="{ props }">
|
||||
<v-btn variant="outlined" icon="mdi-login" title="登录" v-bind="props" />
|
||||
<v-btn variant="outlined" icon="mdi-account-plus" title="添加账户" v-bind="props" />
|
||||
</template>
|
||||
<v-list>
|
||||
<v-list-item @click="addByCookie()" append-icon="mdi-account-plus">
|
||||
@@ -100,8 +100,15 @@
|
||||
<v-list-item-title>验证码登录</v-list-item-title>
|
||||
<v-list-item-subtitle>使用手机号登录</v-list-item-subtitle>
|
||||
</v-list-item>
|
||||
<v-list-item @click="showLoginQr = true" append-icon="mdi-qrcode-scan">
|
||||
<v-list-item-title>扫码登录</v-list-item-title>
|
||||
<v-list-item @click="tryCodeLogin(true)">
|
||||
<v-list-item-title>扫码登录(启动器)</v-list-item-title>
|
||||
<v-list-item-subtitle>使用米游社扫码登录</v-list-item-subtitle>
|
||||
<template #append>
|
||||
<img src="/platforms/mhy/launcher.webp" alt="launcher" class="menu-icon" />
|
||||
</template>
|
||||
</v-list-item>
|
||||
<v-list-item @click="tryCodeLogin(false)" append-icon="mdi-qrcode-scan" v-if="false">
|
||||
<v-list-item-title>扫码登录(游戏)</v-list-item-title>
|
||||
<v-list-item-subtitle>使用米游社扫码登录</v-list-item-subtitle>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
@@ -131,6 +138,7 @@ const { isLogin } = storeToRefs(useAppStore());
|
||||
const { uid, briefInfo, cookie, account } = storeToRefs(useUserStore());
|
||||
|
||||
const showLoginQr = ref<boolean>(false);
|
||||
const isLauncherQr = ref<boolean>(true);
|
||||
const accounts = shallowRef<Array<TGApp.App.Account.User>>([]);
|
||||
const gameAccounts = shallowRef<Array<TGApp.Sqlite.Account.Game>>([]);
|
||||
const userInfo = computed<TGApp.App.Account.BriefInfo>(() => {
|
||||
@@ -247,6 +255,11 @@ async function tryCaptchaLogin(): Promise<void> {
|
||||
await tryGetTokens(ck);
|
||||
}
|
||||
|
||||
async function tryCodeLogin(isLauncher: boolean): Promise<void> {
|
||||
isLauncherQr.value = isLauncher;
|
||||
showLoginQr.value = true;
|
||||
}
|
||||
|
||||
async function refreshUser(uid: string) {
|
||||
let account = await TSUserAccount.account.getAccount(uid);
|
||||
if (!account) {
|
||||
@@ -554,4 +567,9 @@ async function clearUser(user: TGApp.App.Account.User): Promise<void> {
|
||||
.tcu-btn {
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.menu-icon {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -6,24 +6,32 @@
|
||||
</div>
|
||||
<div class="tog-mid">
|
||||
<qrcode-vue
|
||||
v-if="codeData"
|
||||
v-if="codeUrl"
|
||||
class="tog-qr"
|
||||
:value="codeData.url"
|
||||
:value="codeUrl"
|
||||
render-as="svg"
|
||||
:background="'var(--box-bg-1)'"
|
||||
foreground="var(--box-text-1)"
|
||||
/>
|
||||
</div>
|
||||
<div class="tog-bottom" @click="share()">
|
||||
<img src="/platforms/mhy/launcher.webp" alt="icon" v-if="isLauncherCode" />
|
||||
<img src="/platforms/mhy/mys.webp" alt="icon" v-else />
|
||||
</div>
|
||||
</div>
|
||||
</TOverlay>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import TOverlay from "@comp/app/t-overlay.vue";
|
||||
import showLoading from "@comp/func/loading.js";
|
||||
import showSnackbar from "@comp/func/snackbar.js";
|
||||
import QrcodeVue from "qrcode.vue";
|
||||
import { onUnmounted, shallowRef, watch } from "vue";
|
||||
import { computed, onUnmounted, ref, watch } from "vue";
|
||||
|
||||
import { generateShareImg } from "@/utils/TGShare.js";
|
||||
import hk4eReq from "@/web/request/hk4eReq.js";
|
||||
import PassportReq from "@/web/request/passportReq.js";
|
||||
import takumiReq from "@/web/request/takumiReq.js";
|
||||
|
||||
type ToGameLoginEmits = (e: "success", data: TGApp.App.Account.Cookie) => void;
|
||||
|
||||
@@ -31,8 +39,14 @@ type ToGameLoginEmits = (e: "success", data: TGApp.App.Account.Cookie) => void;
|
||||
let cycleTimer: NodeJS.Timeout | null = null;
|
||||
|
||||
const model = defineModel<boolean>({ default: false });
|
||||
const isLauncherCode = defineModel<boolean>("launcher", { default: false });
|
||||
const emits = defineEmits<ToGameLoginEmits>();
|
||||
const codeData = shallowRef<TGApp.BBS.GameLogin.GetLoginQrData>();
|
||||
const codeUrl = ref<string>();
|
||||
const codeTicket = computed<string>(() => {
|
||||
if (!codeUrl.value) return "";
|
||||
const url = new URL(codeUrl.value);
|
||||
return url.searchParams.get("ticket") || "";
|
||||
});
|
||||
|
||||
watch(model, async (value) => {
|
||||
if (value) {
|
||||
@@ -41,25 +55,43 @@ watch(model, async (value) => {
|
||||
}
|
||||
});
|
||||
|
||||
async function share(): Promise<void> {
|
||||
const shareDom = document.querySelector<HTMLDivElement>(".tog-box");
|
||||
if (shareDom === null) {
|
||||
showSnackbar.error("分享失败");
|
||||
return;
|
||||
}
|
||||
await generateShareImg(`tco-gameLogin`, shareDom);
|
||||
}
|
||||
|
||||
async function freshQr(): Promise<void> {
|
||||
const res = await PassportReq.qrLogin.create();
|
||||
let res;
|
||||
if (isLauncherCode.value) res = await PassportReq.qrLogin.create();
|
||||
else res = await hk4eReq.loginQr.create();
|
||||
console.log(res);
|
||||
if ("retcode" in res) {
|
||||
showSnackbar.error(`[${res.retcode}] ${res.message}`);
|
||||
return;
|
||||
}
|
||||
codeData.value = res;
|
||||
codeUrl.value = res.url;
|
||||
}
|
||||
|
||||
async function cycleGetData() {
|
||||
if (cycleTimer === null || !codeData.value) return;
|
||||
const res = await PassportReq.qrLogin.query(codeData.value.ticket);
|
||||
if (cycleTimer === null || codeTicket.value === "") return;
|
||||
if (isLauncherCode.value) await cycleGetDataLauncher(cycleTimer);
|
||||
else await cycleGetDataGame(cycleTimer);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-undef
|
||||
async function cycleGetDataLauncher(timer: NodeJS.Timeout): Promise<void> {
|
||||
const res = await PassportReq.qrLogin.query(codeTicket.value);
|
||||
console.log(res);
|
||||
if ("retcode" in res) {
|
||||
showSnackbar.error(`[${res.retcode}] ${res.message}`);
|
||||
if (res.retcode === -106) {
|
||||
await freshQr();
|
||||
} else {
|
||||
clearInterval(cycleTimer);
|
||||
clearInterval(timer);
|
||||
cycleTimer = null;
|
||||
model.value = false;
|
||||
}
|
||||
@@ -67,7 +99,7 @@ async function cycleGetData() {
|
||||
}
|
||||
if (res.status === "Created" || res.status === "Scanned") return;
|
||||
if (res.status === "Confirmed") {
|
||||
clearInterval(cycleTimer);
|
||||
clearInterval(timer);
|
||||
cycleTimer = null;
|
||||
const ck: TGApp.App.Account.Cookie = {
|
||||
account_id: res.user_info.aid,
|
||||
@@ -83,6 +115,54 @@ async function cycleGetData() {
|
||||
}
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-undef
|
||||
async function cycleGetDataGame(timer: NodeJS.Timeout): Promise<void> {
|
||||
const res = await hk4eReq.loginQr.state(codeTicket.value);
|
||||
console.log(res);
|
||||
if ("retcode" in res) {
|
||||
showSnackbar.error(`[${res.retcode}] ${res.message}`);
|
||||
if (res.retcode === -106) {
|
||||
await freshQr();
|
||||
} else {
|
||||
clearInterval(timer);
|
||||
cycleTimer = null;
|
||||
model.value = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (res.stat === "Init" || res.stat === "Scanned") return;
|
||||
if (res.stat === "Confirmed") {
|
||||
clearInterval(timer);
|
||||
cycleTimer = null;
|
||||
if (res.payload.proto === "Raw") {
|
||||
showSnackbar.error(`返回数据异常:${res.payload}`);
|
||||
model.value = false;
|
||||
return;
|
||||
}
|
||||
const statusRaw: TGApp.Game.Login.StatusPayloadRaw = JSON.parse(res.payload.raw);
|
||||
await showLoading.start("正在获取SToken");
|
||||
const stResp = await takumiReq.game.stoken(statusRaw);
|
||||
console.log(stResp);
|
||||
await showLoading.end();
|
||||
if ("retcode" in stResp) {
|
||||
showSnackbar.error(`[${stResp.retcode}] ${stResp.message}`);
|
||||
model.value = false;
|
||||
return;
|
||||
}
|
||||
// const ck: TGApp.App.Account.Cookie = {
|
||||
// account_id: statusRaw.uid,
|
||||
// ltuid: statusRaw.uid,
|
||||
// stuid: statusRaw.uid,
|
||||
// mid: res.user_info.mid,
|
||||
// cookie_token: "",
|
||||
// stoken: res.tokens[0].token,
|
||||
// ltoken: "",
|
||||
// };
|
||||
// emits("success", ck);
|
||||
model.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
onUnmounted(() => {
|
||||
if (cycleTimer !== null) clearInterval(cycleTimer);
|
||||
cycleTimer = null;
|
||||
@@ -126,4 +206,15 @@ onUnmounted(() => {
|
||||
width: 256px;
|
||||
height: 256px;
|
||||
}
|
||||
|
||||
.tog-bottom {
|
||||
margin: 0 auto;
|
||||
cursor: pointer;
|
||||
|
||||
img {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
<img @click="toBirth(true)" :src="i.head_icon" alt="empty" class="tcb-cur" v-else />
|
||||
</div>
|
||||
<span>的生日哦~</span>
|
||||
<img @click="toBirth(true)" src="/source/UI/act_birthday.png" alt="empty" class="active" />
|
||||
<img @click="toBirth(true)" src="/source/UI/act_birthday.webp" alt="empty" class="active" />
|
||||
</div>
|
||||
<div>即将到来:{{ next[0].role_birthday }}</div>
|
||||
<div v-for="i in next" :key="i.role_id" class="tcb-item">
|
||||
@@ -143,6 +143,7 @@ function parseDesc(intro: string): string {
|
||||
|
||||
.tcb-item img {
|
||||
height: 100px;
|
||||
border-radius: 50%;
|
||||
aspect-ratio: 1;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
{{ text.text }}
|
||||
</v-btn>
|
||||
</div>
|
||||
<v-pagination class="tc-page" v-model="page" :total-visible="visible" :length="length" />
|
||||
<v-pagination class="tc-page" v-model="page" :total-visible="9" :length="length" />
|
||||
</div>
|
||||
<div class="tc-content">
|
||||
<TCalendarBirth />
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<div class="pool-grid">
|
||||
<div v-for="pool in poolSelect" :key="pool.postId" class="pool-card">
|
||||
<div class="pool-cover" @click="createPost(pool.postId, pool.title)">
|
||||
<TMiImg :src="pool.cover" alt="cover" :ori="true" />
|
||||
<img :src="pool.cover" alt="cover" />
|
||||
</div>
|
||||
<div class="pool-bottom">
|
||||
<div class="pool-character">
|
||||
@@ -25,7 +25,7 @@
|
||||
v-if="character.info"
|
||||
:model-value="getCBox(character.info)"
|
||||
/>
|
||||
<TMiImg v-else :src="character.icon" alt="character" />
|
||||
<img v-else :src="character.icon" alt="character" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -56,7 +56,6 @@
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import TItembox, { type TItemBoxData } from "@comp/app/t-itemBox.vue";
|
||||
import TMiImg from "@comp/app/t-mi-img.vue";
|
||||
import showSnackbar from "@comp/func/snackbar.js";
|
||||
import Mys from "@Mys/index.js";
|
||||
import { storeToRefs } from "pinia";
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<div class="top">
|
||||
<div class="main">
|
||||
<div class="left" @click="openPosition(props.position)">
|
||||
<TMiImg :src="props.position.icon" alt="icon" />
|
||||
<img :src="props.position.icon" alt="icon" />
|
||||
</div>
|
||||
<div class="right">
|
||||
<div class="title">{{ props.position.title }}</div>
|
||||
@@ -38,7 +38,6 @@
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import TMiImg from "@comp/app/t-mi-img.vue";
|
||||
import showSnackbar from "@comp/func/snackbar.js";
|
||||
import type { PositionItem } from "@comp/pageHome/ph-comp-position.vue";
|
||||
|
||||
|
||||
@@ -4,10 +4,12 @@
|
||||
<slot name="left"></slot>
|
||||
<div class="tua-ao-box">
|
||||
<div class="tua-ao-top">
|
||||
<span class="tua-ao-click" @click="searchDirect(props.data.name)">
|
||||
<span class="tua-ao-click" title="查询" @click="searchDirect(props.data.name)">
|
||||
{{ props.data.name }}
|
||||
</span>
|
||||
<span>{{ props.data.description }}</span>
|
||||
<span class="tua-ao-click" title="分享" @click="share()">
|
||||
{{ props.data.description }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="tua-ao-mid-title">
|
||||
<span>所属系列:</span>
|
||||
@@ -53,11 +55,13 @@
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import TOverlay from "@comp/app/t-overlay.vue";
|
||||
import showSnackbar from "@comp/func/snackbar.js";
|
||||
import VpOverlaySearch from "@comp/viewPost/vp-overlay-search.vue";
|
||||
import { ref } from "vue";
|
||||
|
||||
import { AppAchievementSeriesData } from "@/data/index.js";
|
||||
import TGLogger from "@/utils/TGLogger.js";
|
||||
import { generateShareImg } from "@/utils/TGShare.js";
|
||||
|
||||
type ToAchiInfoProps = { data: TGApp.Sqlite.Achievement.RenderAchi };
|
||||
type ToAchiInfoEmits = (e: "select-series", v: number) => void;
|
||||
@@ -73,6 +77,16 @@ async function searchDirect(word: string): Promise<void> {
|
||||
search.value = word;
|
||||
showSearch.value = true;
|
||||
}
|
||||
|
||||
async function share(): Promise<void> {
|
||||
const achiBox = document.querySelector<HTMLElement>(".tua-ao-box");
|
||||
if (achiBox === null) {
|
||||
showSnackbar.error("未找到成就详情");
|
||||
return;
|
||||
}
|
||||
const fileName = `【成就详情】【${props.data.id}】-${props.data.name}`;
|
||||
await generateShareImg(fileName, achiBox);
|
||||
}
|
||||
</script>
|
||||
<style lang="css" scoped>
|
||||
.tua-ao-container {
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
</div>
|
||||
<div class="tua-abl-skills">
|
||||
<div v-for="skill in skills" :key="skill.skill_id" class="tua-abl-skill">
|
||||
<img :src="skill.icon" alt="skill" />
|
||||
<TMiImg :ori="true" :src="skill.icon" alt="skill" />
|
||||
<span>Lv.{{ skill.level }}</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -46,6 +46,7 @@
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import TItemBox, { type TItemBoxData } from "@comp/app/t-itemBox.vue";
|
||||
import TMiImg from "@comp/app/t-mi-img.vue";
|
||||
import TSUserAvatar from "@Sqlite/modules/userAvatar.js";
|
||||
import { computed } from "vue";
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
class="tua-dcc-item"
|
||||
:title="`${constellation.pos}命-${constellation.name}`"
|
||||
>
|
||||
<img :src="constellation.icon" alt="constellation" class="tua-dcc-icon" />
|
||||
<TMiImg :ori="true" :src="constellation.icon" alt="constellation" class="tua-dcc-icon" />
|
||||
<div v-if="!constellation.is_actived" class="tua-dcc-lock">
|
||||
<v-icon size="10px" color="var(--tgc-od-white)">mdi-lock</v-icon>
|
||||
</div>
|
||||
@@ -14,6 +14,8 @@
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import TMiImg from "@comp/app/t-mi-img.vue";
|
||||
|
||||
type TuaDcConstellationsProps = { modelValue: Array<TGApp.Game.Avatar.Constellation> };
|
||||
|
||||
const props = defineProps<TuaDcConstellationsProps>();
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
v-if="props.modelValue === false"
|
||||
class="empty"
|
||||
/>
|
||||
<img :src="props.modelValue.icon" :alt="props.modelValue.name" v-else />
|
||||
<TMiImg :ori="true" :src="props.modelValue.icon" :alt="props.modelValue.name" v-else />
|
||||
</div>
|
||||
</div>
|
||||
<div class="tua-dcr-right">
|
||||
@@ -59,6 +59,7 @@
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import TMiImg from "@comp/app/t-mi-img.vue";
|
||||
import { computed } from "vue";
|
||||
|
||||
import { useUserStore } from "@/store/modules/user.js";
|
||||
@@ -188,8 +189,11 @@ function getPropSubStyle(
|
||||
|
||||
.tua-dcr-icon {
|
||||
position: relative;
|
||||
display: flex;
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
:title="skill.name"
|
||||
class="tua-dct-item"
|
||||
>
|
||||
<img :src="skill.icon" alt="talent" class="tua-dct-icon" />
|
||||
<TMiImg :ori="true" :src="skill.icon" alt="talent" class="tua-dct-icon" />
|
||||
<div v-if="!skill.is_unlock" class="tua-dct-lock">
|
||||
<v-icon size="10px" color="var(--tgc-od-white)">mdi-lock</v-icon>
|
||||
</div>
|
||||
@@ -17,6 +17,8 @@
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import TMiImg from "@comp/app/t-mi-img.vue";
|
||||
|
||||
type TuaDcTalentsProps = { modelValue: Array<TGApp.Game.Avatar.Skill> };
|
||||
|
||||
const props = defineProps<TuaDcTalentsProps>();
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
<template>
|
||||
<div class="tua-dc-container">
|
||||
<img :src="avatar" class="tua-dc-avatar" alt="avatar" />
|
||||
<div class="tua-dc-avatar">
|
||||
<TMiImg :src="props.modelValue.avatar.image" :ori="true" alt="avatar" />
|
||||
</div>
|
||||
<v-btn
|
||||
class="tua-dc-share"
|
||||
prepend-icon="mdi-share-variant"
|
||||
@@ -73,9 +75,10 @@
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import TMiImg from "@comp/app/t-mi-img.vue";
|
||||
import showSnackbar from "@comp/func/snackbar.js";
|
||||
import TSUserAvatar from "@Sqlite/modules/userAvatar.js";
|
||||
import { computed, onMounted, onUnmounted, ref, watch } from "vue";
|
||||
import { computed, ref } from "vue";
|
||||
|
||||
import TuaDcConstellations from "./tua-dc-constellations.vue";
|
||||
import TuaDcProp from "./tua-dc-prop.vue";
|
||||
@@ -84,7 +87,7 @@ import TuaDcTalents from "./tua-dc-talents.vue";
|
||||
import TuaDcWeapon from "./tua-dc-weapon.vue";
|
||||
|
||||
import { useUserStore } from "@/store/modules/user.js";
|
||||
import { generateShareImg, saveImgLocal } from "@/utils/TGShare.js";
|
||||
import { generateShareImg } from "@/utils/TGShare.js";
|
||||
|
||||
type fixedLenArr<T, N extends number> = [T, ...Array<T>] & { length: N };
|
||||
type RelicList = fixedLenArr<TGApp.Game.Avatar.Relic | false, 5>;
|
||||
@@ -106,38 +109,11 @@ const propMain = computed<Array<TGApp.Game.Avatar.PropMapItem | false>>(() =>
|
||||
props.modelValue.propSelected.map((item) => userStore.getProp(item.property_type)),
|
||||
);
|
||||
|
||||
const bg = ref<string>("/WIKI/nameCard/profile/原神·印象.webp");
|
||||
const avatar = ref<string>(props.modelValue.avatar.image);
|
||||
const loading = ref<boolean>(false);
|
||||
|
||||
onMounted(async () => {
|
||||
await loadData();
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
if (avatar.value.startsWith("blob:")) {
|
||||
URL.revokeObjectURL(avatar.value);
|
||||
}
|
||||
});
|
||||
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
async () => {
|
||||
if (avatar.value.startsWith("blob:")) {
|
||||
URL.revokeObjectURL(avatar.value);
|
||||
}
|
||||
avatar.value = props.modelValue.avatar.image;
|
||||
await loadData();
|
||||
},
|
||||
);
|
||||
|
||||
async function loadData(): Promise<void> {
|
||||
const bg = computed<string>(() => {
|
||||
const card = TSUserAvatar.getAvatarCard(props.modelValue.cid);
|
||||
bg.value = `url("/WIKI/nameCard/profile/${card}.webp")`;
|
||||
if (!avatar.value.startsWith("blob:")) {
|
||||
avatar.value = await saveImgLocal(props.modelValue.avatar.image);
|
||||
}
|
||||
}
|
||||
return `url("/WIKI/nameCard/profile/${card}.webp")`;
|
||||
});
|
||||
const loading = ref<boolean>(false);
|
||||
|
||||
async function share(): Promise<void> {
|
||||
const shareBox = document.querySelector<HTMLElement>(".tua-dc-container");
|
||||
@@ -176,9 +152,18 @@ async function share(): Promise<void> {
|
||||
.tua-dc-avatar {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: -80px;
|
||||
left: 0;
|
||||
display: flex;
|
||||
width: 300px;
|
||||
height: 100%;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
object-fit: contain;
|
||||
|
||||
img {
|
||||
height: 100%;
|
||||
object-fit: contain;
|
||||
}
|
||||
}
|
||||
|
||||
.tua-dc-rt {
|
||||
|
||||
@@ -14,11 +14,13 @@
|
||||
v-if="props.modelValue === false"
|
||||
class="empty"
|
||||
/>
|
||||
<img :src="props.modelValue.icon" :alt="props.modelValue.name" v-else />
|
||||
<TMiImg :ori="true" :src="props.modelValue.icon" :alt="props.modelValue.name" v-else />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import TMiImg from "@comp/app/t-mi-img.vue";
|
||||
|
||||
import { useUserStore } from "@/store/modules/user.js";
|
||||
|
||||
type TuaRelicBoxProps = { modelValue: TGApp.Game.Avatar.Relic | false; position: number };
|
||||
@@ -71,8 +73,11 @@ function getRelicTitle(): string {
|
||||
|
||||
.tua-relic-icon {
|
||||
position: relative;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="duc-dolb-box">
|
||||
<div
|
||||
v-for="constellation in constellations"
|
||||
v-for="constellation in props.modelValue"
|
||||
:key="constellation.pos"
|
||||
:title="constellation.name"
|
||||
class="duc-dolb-item"
|
||||
@@ -9,48 +9,18 @@
|
||||
<div v-if="!constellation.is_actived" class="duc-dolb-lock">
|
||||
<v-icon color="white">mdi-lock</v-icon>
|
||||
</div>
|
||||
<img class="duc-dolb-icon" :src="constellation.icon" alt="constellation" />
|
||||
<div class="duc-dolb-icon">
|
||||
<TMiImg :ori="true" :src="constellation.icon" alt="constellation" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, onUnmounted, shallowRef, watch } from "vue";
|
||||
|
||||
import { saveImgLocal } from "@/utils/TGShare.js";
|
||||
import TMiImg from "@comp/app/t-mi-img.vue";
|
||||
|
||||
type DucDetailOlbProps = { modelValue: Array<TGApp.Game.Avatar.Constellation> };
|
||||
|
||||
const props = defineProps<DucDetailOlbProps>();
|
||||
const constellations = shallowRef<Array<TGApp.Game.Avatar.Constellation>>([]);
|
||||
|
||||
async function loadData() {
|
||||
const tempConstellations = JSON.parse(JSON.stringify(props.modelValue));
|
||||
for (const constellation of tempConstellations) {
|
||||
if (constellation.icon.startsWith("blob:")) return;
|
||||
constellation.icon = await saveImgLocal(constellation.icon);
|
||||
}
|
||||
constellations.value = tempConstellations;
|
||||
}
|
||||
|
||||
onMounted(async () => await loadData());
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
async () => {
|
||||
for (const constellation of constellations.value) {
|
||||
if (constellation.icon.startsWith("blob:")) {
|
||||
URL.revokeObjectURL(constellation.icon);
|
||||
}
|
||||
}
|
||||
await loadData();
|
||||
},
|
||||
);
|
||||
onUnmounted(() => {
|
||||
for (const constellation of constellations.value) {
|
||||
if (constellation.icon.startsWith("blob:")) {
|
||||
URL.revokeObjectURL(constellation.icon);
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<style>
|
||||
.duc-dolb-box {
|
||||
@@ -75,6 +45,7 @@ onUnmounted(() => {
|
||||
|
||||
.duc-dolb-lock {
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
display: flex;
|
||||
width: 54px;
|
||||
height: 54px;
|
||||
@@ -88,9 +59,20 @@ onUnmounted(() => {
|
||||
}
|
||||
|
||||
.duc-dolb-icon {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
display: flex;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 5px;
|
||||
border-radius: 50%;
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: contain;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -2,54 +2,24 @@
|
||||
<div class="duc-dort-box">
|
||||
<div
|
||||
:title="talent.name"
|
||||
v-for="talent in talents"
|
||||
v-for="talent in props.modelValue"
|
||||
:key="talent.skill_id"
|
||||
class="duc-dort-item"
|
||||
>
|
||||
<span>{{ talent.name }}</span>
|
||||
<img :src="talent.icon" alt="talent" />
|
||||
<div class="duc-dort-icon">
|
||||
<TMiImg :ori="true" :src="talent.icon" alt="talent" />
|
||||
</div>
|
||||
<span>Lv.{{ talent.level === 0 ? 1 : talent.level }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, onUnmounted, shallowRef, watch } from "vue";
|
||||
|
||||
import { saveImgLocal } from "@/utils/TGShare.js";
|
||||
import TMiImg from "@comp/app/t-mi-img.vue";
|
||||
|
||||
type DucDetailOrtProps = { modelValue: Array<TGApp.Game.Avatar.Skill> };
|
||||
|
||||
const props = defineProps<DucDetailOrtProps>();
|
||||
const talents = shallowRef<Array<TGApp.Game.Avatar.Skill>>([]);
|
||||
|
||||
async function loadData(): Promise<void> {
|
||||
const tempTalent = JSON.parse(JSON.stringify(props.modelValue));
|
||||
for (const talent of tempTalent) {
|
||||
if (talent.icon.startsWith("blob:")) return;
|
||||
talent.icon = await saveImgLocal(talent.icon);
|
||||
}
|
||||
talents.value = tempTalent;
|
||||
}
|
||||
|
||||
onMounted(async () => await loadData());
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
async () => {
|
||||
for (const talent of talents.value) {
|
||||
if (talent.icon.startsWith("blob:")) {
|
||||
URL.revokeObjectURL(talent.icon);
|
||||
}
|
||||
}
|
||||
await loadData();
|
||||
},
|
||||
);
|
||||
onUnmounted(() => {
|
||||
for (const talent of talents.value) {
|
||||
if (talent.icon.startsWith("blob:")) {
|
||||
URL.revokeObjectURL(talent.icon);
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<style lang="css" scoped>
|
||||
.duc-dort-box {
|
||||
@@ -61,17 +31,28 @@ onUnmounted(() => {
|
||||
.duc-dort-item {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
column-gap: 10px;
|
||||
column-gap: 8px;
|
||||
}
|
||||
|
||||
.duc-dort-item img {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
padding: 5px;
|
||||
.duc-dort-icon {
|
||||
position: relative;
|
||||
display: flex;
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
box-sizing: border-box;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 4px;
|
||||
border-radius: 50%;
|
||||
-webkit-backdrop-filter: blur(5px);
|
||||
backdrop-filter: blur(5px);
|
||||
background: rgba(0 0 0 /40%);
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: contain;
|
||||
}
|
||||
}
|
||||
|
||||
.duc-dort-item span {
|
||||
@@ -83,9 +64,4 @@ onUnmounted(() => {
|
||||
font-size: 16px;
|
||||
text-shadow: 0 0 5px rgba(0 0 0/40%);
|
||||
}
|
||||
|
||||
.duc-dort-item :nth-last-child(1) {
|
||||
width: 48px;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<img :src="`/icon/bg/${props.modelValue.rarity}-Star.webp`" alt="bg" />
|
||||
</div>
|
||||
<div v-if="props.modelValue" class="duc-dr-icon">
|
||||
<img :src="props.modelValue.icon" alt="relic" />
|
||||
<TMiImg :ori="true" :src="props.modelValue.icon" alt="relic" />
|
||||
</div>
|
||||
<div v-if="props.modelValue !== false" class="duc-dr-level">
|
||||
{{ props.modelValue.level }}
|
||||
@@ -15,6 +15,7 @@
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import TMiImg from "@comp/app/t-mi-img.vue";
|
||||
import { computed } from "vue";
|
||||
|
||||
type ducDetailRelicProps = { modelValue: TGApp.Game.Avatar.Relic | false; pos: number };
|
||||
@@ -61,8 +62,11 @@ const relicBg = computed<string>(() => {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.duc-dr-icon img {
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
<template>
|
||||
<div class="tuc-dc-box">
|
||||
<div v-if="!modelValue.is_actived" class="tuc-dc-lock">
|
||||
<v-icon color="white"> mdi-lock </v-icon>
|
||||
<v-icon color="white"> mdi-lock</v-icon>
|
||||
</div>
|
||||
<div class="tuc-dc-icon">
|
||||
<img :src="modelValue.icon" alt="constellation" />
|
||||
<TMiImg :ori="true" :src="modelValue.icon" alt="constellation" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import TMiImg from "@comp/app/t-mi-img.vue";
|
||||
|
||||
defineProps<{ modelValue: TGApp.Game.Avatar.Constellation }>();
|
||||
</script>
|
||||
<style lang="css" scoped>
|
||||
@@ -34,8 +36,11 @@ defineProps<{ modelValue: TGApp.Game.Avatar.Constellation }>();
|
||||
}
|
||||
|
||||
.tuc-dc-icon {
|
||||
display: flex;
|
||||
width: 54px;
|
||||
height: 54px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 3px;
|
||||
border: 1px solid rgb(0 0 0/20%);
|
||||
border-radius: 50%;
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
<template>
|
||||
<div class="tuc-do-box">
|
||||
<img :src="bg" alt="role" class="tuc-do-bg" />
|
||||
<div class="tuc-do-bg">
|
||||
<TMiImg :ori="true" :src="bg" alt="role" />
|
||||
</div>
|
||||
<div class="tuc-do-show">
|
||||
<div class="tuc-do-main">
|
||||
<div class="tuc-do-left">
|
||||
@@ -72,6 +74,7 @@
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import TMiImg from "@comp/app/t-mi-img.vue";
|
||||
import { computed, onMounted, ref, shallowRef, watch } from "vue";
|
||||
|
||||
import TucDetailConstellation from "./tuc-detail-constellation.vue";
|
||||
@@ -160,12 +163,21 @@ function switchBg(): void {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
max-height: 100%;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 5px;
|
||||
margin: 0 auto;
|
||||
object-fit: v-bind(bgFit);
|
||||
transform: translateY(v-bind(bgTransY));
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: contain;
|
||||
}
|
||||
}
|
||||
|
||||
.tuc-do-costume {
|
||||
|
||||
@@ -7,11 +7,13 @@
|
||||
<img :src="`/icon/bg/${modelValue.rarity}-Star.webp`" alt="bg" />
|
||||
</div>
|
||||
<div v-if="modelValue" class="tuc-dr-icon">
|
||||
<img :src="modelValue.icon" alt="relic" />
|
||||
<TMiImg :ori="true" :src="modelValue.icon" alt="relic" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import TMiImg from "@comp/app/t-mi-img.vue";
|
||||
|
||||
defineProps<{ modelValue: TGApp.Game.Avatar.Relic | false; pos: number }>();
|
||||
</script>
|
||||
<style lang="css" scoped>
|
||||
@@ -45,8 +47,11 @@ defineProps<{ modelValue: TGApp.Game.Avatar.Relic | false; pos: number }>();
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.tuc-dr-icon img {
|
||||
|
||||
@@ -6,22 +6,34 @@
|
||||
<script lang="ts" setup>
|
||||
import TItemBox, { type TItemBoxData } from "@comp/app/t-itemBox.vue";
|
||||
|
||||
import { getZhElement } from "@/utils/toolFunc.js";
|
||||
import { getWikiBrief, getZhElement } from "@/utils/toolFunc.js";
|
||||
|
||||
type TucAvatarsProps = { modelValue: Array<TGApp.Game.Combat.Avatar>; detail: boolean };
|
||||
|
||||
const props = defineProps<TucAvatarsProps>();
|
||||
|
||||
function getItemBox(item: TGApp.Game.Combat.Avatar): TItemBoxData {
|
||||
const findAvatar = getWikiBrief(item.avatar_id);
|
||||
let innerText = item.avatar_type === 2 ? "试用角色" : item.avatar_type === 3 ? "助演角色" : "";
|
||||
let findWeapon;
|
||||
if (findAvatar) {
|
||||
findWeapon = findAvatar.weapon;
|
||||
if (innerText === "") innerText = findAvatar.name;
|
||||
}
|
||||
return {
|
||||
bg: `/icon/bg/${item.rarity === 105 ? 5 : item.rarity}-BGC.webp`,
|
||||
clickable: false,
|
||||
display: "inner",
|
||||
height: "80px",
|
||||
icon: `/WIKI/character/${item.avatar_id}.webp`,
|
||||
innerHeight: item.avatar_type !== 1 ? 20 : 0,
|
||||
innerText: item.avatar_type === 2 ? "试用角色" : item.avatar_type === 3 ? "助演角色" : "",
|
||||
lt: `/icon/element/${getZhElement(item.element)}元素.webp`,
|
||||
innerHeight: innerText === "" ? 0 : 20,
|
||||
innerText: innerText,
|
||||
lt:
|
||||
item.element === "None"
|
||||
? findWeapon
|
||||
? `/icon/weapon/${findWeapon}.webp`
|
||||
: ""
|
||||
: `/icon/element/${getZhElement(item.element)}元素.webp`,
|
||||
ltSize: "20px",
|
||||
innerBlur: "5px",
|
||||
rt: "",
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
<script lang="ts" setup>
|
||||
// about import err,see:https://github.com/apache/echarts/issues/19992
|
||||
import showLoading from "@comp/func/loading.js";
|
||||
// @ts-expect-error no-exported-member
|
||||
import { BarChart, HeatmapChart, PieChart } from "echarts/charts.js";
|
||||
import {
|
||||
CalendarComponent,
|
||||
@@ -38,11 +37,8 @@ import {
|
||||
TooltipComponent,
|
||||
VisualMapComponent,
|
||||
} from "echarts/components.js";
|
||||
// @ts-expect-error no-exported-member
|
||||
import { use } from "echarts/core.js";
|
||||
// @ts-expect-error no-exported-member
|
||||
import { LabelLayout } from "echarts/features.js";
|
||||
// @ts-expect-error no-exported-member
|
||||
import { CanvasRenderer } from "echarts/renderers.js";
|
||||
import type { EChartsOption } from "echarts/types/dist/shared.js";
|
||||
import { storeToRefs } from "pinia";
|
||||
|
||||
@@ -1,24 +1,22 @@
|
||||
<!-- todo 优化,增加筛选功能 -->
|
||||
<template>
|
||||
<div class="ua-gt-box">
|
||||
<v-data-table
|
||||
:headers="headers"
|
||||
:items="props.modelValue"
|
||||
height="500px"
|
||||
fixed-header
|
||||
fixed-footer
|
||||
>
|
||||
<template v-slot:item="{ item }">
|
||||
<tr class="ua-gt-tr">
|
||||
<td>{{ item.time }}</td>
|
||||
<td>{{ getPool(item.uigfType) }}</td>
|
||||
<td>{{ item.type }}</td>
|
||||
<td>{{ item.name }}</td>
|
||||
<td>{{ item.rank }}</td>
|
||||
</tr>
|
||||
</template>
|
||||
</v-data-table>
|
||||
</div>
|
||||
<v-data-table
|
||||
:headers="headers"
|
||||
:items="props.modelValue"
|
||||
fixed-header
|
||||
fixed-footer
|
||||
class="ua-gt-box"
|
||||
>
|
||||
<template v-slot:item="{ item }">
|
||||
<tr class="ua-gt-tr">
|
||||
<td>{{ item.time }}</td>
|
||||
<td>{{ getPool(item.uigfType) }}</td>
|
||||
<td>{{ item.type }}</td>
|
||||
<td>{{ item.name }}</td>
|
||||
<td>{{ item.rank }}</td>
|
||||
</tr>
|
||||
</template>
|
||||
</v-data-table>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
type GroTableProps = { modelValue: Array<TGApp.Sqlite.GachaRecords.SingleTable> };
|
||||
@@ -52,8 +50,7 @@ function getPool(type: string) {
|
||||
</script>
|
||||
<style lang="css" scoped>
|
||||
.ua-gt-box {
|
||||
height: 100%;
|
||||
max-height: calc(100vh - 120px);
|
||||
height: calc(100vh - 200px);
|
||||
padding-right: 5px;
|
||||
border-radius: 5px;
|
||||
overflow-y: auto;
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
<template>
|
||||
<div class="tur-hs-box">
|
||||
<div class="bg"><img :src="data.bg" alt="bg" v-if="data.name !== '炽空境'" /></div>
|
||||
<div class="bg">
|
||||
<img :src="data.bg" alt="bg" />
|
||||
</div>
|
||||
<div class="tur-hs-top">
|
||||
<div class="tur-hs-title">
|
||||
<img :src="data.comfortIcon" alt="comfort" />
|
||||
<img :src="data.comfortIcon" alt="icon" />
|
||||
<span>{{ data.comfortName }}</span>
|
||||
</div>
|
||||
<div class="tur-hs-name">{{ data.name }}</div>
|
||||
@@ -87,6 +89,8 @@ defineProps<{ data: TGApp.Sqlite.Record.Home }>();
|
||||
}
|
||||
|
||||
.tur-hs-text-grid {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
justify-content: space-between;
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
/>
|
||||
<TurOverviewSub
|
||||
:text="modelValue.combatRole"
|
||||
icon="/icon/material/201.webp"
|
||||
icon="/source/UI/userCombat.webp"
|
||||
title="幻想真境剧诗"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
<template>
|
||||
<div class="tur-ws-box">
|
||||
<div class="tur-ws-bg"><img :src="data.bg" alt="bg" /></div>
|
||||
<div class="tur-ws-icon"><img :src="icon" alt="icon" /></div>
|
||||
<div class="tur-ws-bg">
|
||||
<img :src="data.bg" alt="bg" />
|
||||
</div>
|
||||
<div class="tur-ws-icon">
|
||||
<img :src="icon" alt="icon" />
|
||||
</div>
|
||||
<div class="tur-ws-content">
|
||||
<div class="tur-ws-title">
|
||||
<span>{{ data.name }}</span>
|
||||
<span v-if="data.offering" class="tur-ws-sub">
|
||||
<img :src="offer" alt="offer" />
|
||||
<img :src="data.offering.icon" alt="offer" />
|
||||
<span>{{ data.offering.name }}等级:</span>
|
||||
<span>{{ data.offering.level }}</span>
|
||||
<span>级</span>
|
||||
@@ -38,42 +42,24 @@
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { event } from "@tauri-apps/api";
|
||||
import type { Event, UnlistenFn } from "@tauri-apps/api/event";
|
||||
import { storeToRefs } from "pinia";
|
||||
import { computed, onMounted, onUnmounted, ref } from "vue";
|
||||
import { computed } from "vue";
|
||||
|
||||
import { useAppStore } from "@/store/modules/app.js";
|
||||
|
||||
type TurWorldSubProps = { data: TGApp.Sqlite.Record.WorldExplore };
|
||||
|
||||
let themeListener: UnlistenFn | null = null;
|
||||
const { theme } = storeToRefs(useAppStore());
|
||||
const props = defineProps<TurWorldSubProps>();
|
||||
const icon = ref<string>();
|
||||
const offer = ref<string>();
|
||||
|
||||
const imgFilter = computed<string>(() => {
|
||||
if (props.data.name !== "纳塔") return "none";
|
||||
if (theme.value === "dark") return "none";
|
||||
return "invert(0.75)";
|
||||
});
|
||||
|
||||
onMounted(async () => {
|
||||
themeListener = await event.listen<string>("readTheme", (e: Event<string>) => {
|
||||
if (e.payload === "dark") icon.value = props.data.iconLight;
|
||||
else icon.value = props.data.iconDark;
|
||||
});
|
||||
if (props.data.offering) offer.value = props.data.offering.icon;
|
||||
if (theme.value === "dark") icon.value = props.data.iconLight;
|
||||
else icon.value = props.data.iconDark;
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
if (themeListener !== null) {
|
||||
themeListener();
|
||||
themeListener = null;
|
||||
}
|
||||
const icon = computed<string>(() => {
|
||||
if (theme.value === "dark") return props.data.iconLight;
|
||||
return props.data.iconDark;
|
||||
});
|
||||
</script>
|
||||
<style lang="css" scoped>
|
||||
|
||||
356
src/components/userScripts/tus-mission.vue
Normal file
@@ -0,0 +1,356 @@
|
||||
<template>
|
||||
<div class="tusm-box">
|
||||
<div class="tusm-top">
|
||||
<div class="tusm-title">米游币任务({{ todayPoints }}/{{ totalPoints }})</div>
|
||||
<div class="tusm-acts">
|
||||
<v-btn @click="tryRefresh()" class="tusm-btn" :loading="loadState">刷新</v-btn>
|
||||
<v-btn @click="tryAuto()" class="tusm-btn" :loading="loadMission">执行</v-btn>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tusm-content">
|
||||
<div v-for="mission in parseMissions" :key="mission.id" class="mission-item">
|
||||
<div class="left">
|
||||
<v-icon v-if="!mission.status" color="var(--tgc-od-grey)">mdi-circle</v-icon>
|
||||
<v-icon v-else color="var(--tgc-od-green)">mdi-check-circle</v-icon>
|
||||
<span>{{ mission.name }} - {{ mission.reward }}米游币</span>
|
||||
</div>
|
||||
<div class="right">
|
||||
<span>
|
||||
<v-progress-linear
|
||||
rounded
|
||||
:model-value="(mission.process / mission.total) * 100"
|
||||
height="8"
|
||||
color="var(--tgc-od-blue)"
|
||||
/>
|
||||
</span>
|
||||
<span>{{ mission.process }}/{{ mission.total }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import showSnackbar from "@comp/func/snackbar.js";
|
||||
import { getRecentForumPostList } from "@Mys/request/painterReq.js";
|
||||
import { getPostFull } from "@Mys/request/postReq.js";
|
||||
import { storeToRefs } from "pinia";
|
||||
import { ref, shallowRef } from "vue";
|
||||
|
||||
import { useUserStore } from "@/store/modules/user.js";
|
||||
import TGLogger from "@/utils/TGLogger.js";
|
||||
import apiHubReq from "@/web/request/apiHubReq.js";
|
||||
|
||||
type ParseMission = {
|
||||
id: number;
|
||||
key: string;
|
||||
name: string;
|
||||
process: number;
|
||||
total: number;
|
||||
status: boolean;
|
||||
reward: number;
|
||||
};
|
||||
|
||||
const { cookie } = storeToRefs(useUserStore());
|
||||
const parseMissions = shallowRef<Array<ParseMission>>([]);
|
||||
const missionList = shallowRef<Array<TGApp.BBS.Mission.MissionItem>>([]);
|
||||
const todayPoints = ref<number>(0);
|
||||
const totalPoints = ref<number>(0);
|
||||
const loadScript = defineModel<boolean>();
|
||||
const loadState = ref<boolean>(false);
|
||||
const loadMission = ref<boolean>(false);
|
||||
|
||||
function mergeMission(
|
||||
list: Array<TGApp.BBS.Mission.MissionItem>,
|
||||
state: Array<TGApp.BBS.Mission.StateItem>,
|
||||
): void {
|
||||
const res: Array<ParseMission> = [];
|
||||
for (const item of list) {
|
||||
const stateFind = state.find((i) => i.mission_id === item.id);
|
||||
if (!stateFind) {
|
||||
res.push({
|
||||
id: item.id,
|
||||
key: item.mission_key,
|
||||
name: item.name,
|
||||
process: 0,
|
||||
total: item.threshold,
|
||||
status: false,
|
||||
reward: item.points,
|
||||
});
|
||||
continue;
|
||||
}
|
||||
res.push({
|
||||
id: item.id,
|
||||
key: item.mission_key,
|
||||
name: item.name,
|
||||
total: item.threshold,
|
||||
process: stateFind.happened_times,
|
||||
status: stateFind.process === 1,
|
||||
reward: item.points,
|
||||
});
|
||||
}
|
||||
res.sort((a, b) => a.id - b.id);
|
||||
parseMissions.value = res;
|
||||
}
|
||||
|
||||
async function tryRefresh(): Promise<void> {
|
||||
if (loadScript.value) {
|
||||
showSnackbar.warn("任务正在执行中,请稍后再试");
|
||||
return;
|
||||
}
|
||||
loadScript.value = true;
|
||||
loadState.value = true;
|
||||
await TGLogger.ScriptSep("米游币任务");
|
||||
await TGLogger.Script("[米游币任务]刷新任务状态");
|
||||
if (!cookie.value) {
|
||||
await TGLogger.Script("[米游币任务]未检测到Cookie");
|
||||
showSnackbar.warn("当前账号未登录,请先登录");
|
||||
await TGLogger.ScriptSep("米游币任务", false);
|
||||
return;
|
||||
}
|
||||
const ck = {
|
||||
stoken: cookie.value.stoken,
|
||||
stuid: cookie.value.stuid,
|
||||
mid: cookie.value.mid,
|
||||
};
|
||||
await refreshState(ck);
|
||||
await TGLogger.ScriptSep("米游币任务", false);
|
||||
loadScript.value = false;
|
||||
loadState.value = false;
|
||||
}
|
||||
|
||||
async function tryAuto(): Promise<void> {
|
||||
if (loadScript.value) {
|
||||
showSnackbar.warn("任务正在执行中,请稍后再试");
|
||||
return;
|
||||
}
|
||||
loadScript.value = true;
|
||||
loadMission.value = true;
|
||||
await TGLogger.ScriptSep("米游币任务");
|
||||
await TGLogger.Script("[米游币任务]开始执行任务");
|
||||
if (!cookie.value) {
|
||||
await TGLogger.Script("[米游币任务]未检测到Cookie");
|
||||
showSnackbar.warn("当前账号未登录,请先登录");
|
||||
await TGLogger.ScriptSep("米游币任务", false);
|
||||
return;
|
||||
}
|
||||
const ck = {
|
||||
stoken: cookie.value.stoken,
|
||||
stuid: cookie.value.stuid,
|
||||
mid: cookie.value.mid,
|
||||
};
|
||||
const ckPost = { ltoken: cookie.value.ltoken, ltuid: cookie.value.ltuid };
|
||||
await refreshState(ck);
|
||||
const signFind = parseMissions.value.find((i) => i.key === "continuous_sign");
|
||||
if (signFind && !signFind.status) {
|
||||
await autoSign(ck);
|
||||
} else {
|
||||
await TGLogger.Script("[米游币任务]未找到打卡任务或今日已打卡");
|
||||
}
|
||||
const postFilter = parseMissions.value.filter((i) => i.key !== "continuous_sign");
|
||||
if (postFilter.every((i) => i.status)) {
|
||||
await TGLogger.Script("[米游币任务]所有任务已完成");
|
||||
await TGLogger.ScriptSep("米游币任务", false);
|
||||
loadScript.value = false;
|
||||
loadMission.value = false;
|
||||
return;
|
||||
}
|
||||
let isShare = false;
|
||||
let likeCnt = 0;
|
||||
let viewCnt = 0;
|
||||
const shareFind = postFilter.find((i) => i.key === "share_post_0");
|
||||
if (shareFind) isShare = shareFind.status;
|
||||
const likeFind = postFilter.find((i) => i.key === "post_up_0");
|
||||
if (likeFind) likeCnt = likeFind.process;
|
||||
const viewFind = postFilter.find((i) => i.key === "view_post_0");
|
||||
if (viewFind) viewCnt = viewFind.process;
|
||||
await TGLogger.Script("[米游币任务]获取帖子列表");
|
||||
const listResp = await getRecentForumPostList(26, 2, 2, undefined, 20);
|
||||
for (const post of listResp.list) {
|
||||
if (!isShare) {
|
||||
await TGLogger.Script(`[米游币任务]正在分享帖子${post.post.post_id}`);
|
||||
const shareResp = await apiHubReq.post.share(post.post.post_id, ck);
|
||||
if (shareResp.retcode === 0) {
|
||||
await TGLogger.Script("[米游币任务]分享成功");
|
||||
isShare = true;
|
||||
} else {
|
||||
await TGLogger.Script(`[米游币任务]分享失败:${shareResp.retcode} ${shareResp.message}`);
|
||||
}
|
||||
}
|
||||
if (likeCnt < 5 || viewCnt < 3) {
|
||||
await TGLogger.Script(`[米游币任务]正在浏览帖子${post.post.post_id}`);
|
||||
const detailResp = await getPostFull(Number(post.post.post_id), ckPost);
|
||||
if ("retcode" in detailResp) {
|
||||
await TGLogger.Script(
|
||||
`[米游币任务]获取帖子${post.post.post_id}失败:${detailResp.retcode} ${detailResp.message}`,
|
||||
);
|
||||
continue;
|
||||
}
|
||||
viewCnt++;
|
||||
if (likeCnt < 5) {
|
||||
const isLike = detailResp.self_operation.upvote_type === 1;
|
||||
if (isLike) {
|
||||
await TGLogger.Script(`[米游币任务]帖子${post.post.post_id}已点赞,跳过`);
|
||||
continue;
|
||||
}
|
||||
await TGLogger.Script(`[米游币任务]正在点赞帖子${post.post.post_id}`);
|
||||
const likeResp = await apiHubReq.post.like(post.post.post_id, ckPost);
|
||||
if (likeResp.retcode === 0) {
|
||||
await TGLogger.Script("[米游币任务]点赞成功");
|
||||
likeCnt++;
|
||||
} else {
|
||||
await TGLogger.Script(`[米游币任务]点赞失败:${likeResp.retcode} ${likeResp.message}`);
|
||||
continue;
|
||||
}
|
||||
await TGLogger.Script(`[米游币任务]正在取消点赞帖子${post.post.post_id}`);
|
||||
await new Promise<void>((resolve) => setTimeout(resolve, 1000));
|
||||
const unlikeResp = await apiHubReq.post.like(post.post.post_id, ckPost, true);
|
||||
if (unlikeResp.retcode === 0) {
|
||||
await TGLogger.Script("[米游币任务]取消点赞成功");
|
||||
} else {
|
||||
await TGLogger.Script(
|
||||
`[米游币任务]取消点赞失败:${unlikeResp.retcode} ${unlikeResp.message}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isShare && likeCnt >= 5 && viewCnt >= 3) {
|
||||
await TGLogger.Script("[米游币任务]所有任务已完成");
|
||||
break;
|
||||
}
|
||||
}
|
||||
await TGLogger.Script("[米游币任务]任务执行完毕,即将刷新任务状态");
|
||||
await refreshState(ck);
|
||||
await TGLogger.ScriptSep("米游币任务", false);
|
||||
loadScript.value = false;
|
||||
loadMission.value = false;
|
||||
}
|
||||
|
||||
async function refreshState(ck: Record<string, string>): Promise<void> {
|
||||
await TGLogger.Script("[米游币任务]刷新任务状态");
|
||||
if (missionList.value.length === 0) {
|
||||
await TGLogger.Script("[米游币任务]未检测到任务列表,正在获取");
|
||||
const listResp = await apiHubReq.mission.list(ck);
|
||||
if (listResp.retcode !== 0) {
|
||||
await TGLogger.Script(
|
||||
`[米游币任务]获取任务列表失败:${listResp.retcode} ${listResp.message}`,
|
||||
);
|
||||
showSnackbar.error(`[${listResp.retcode}] ${listResp.message}`);
|
||||
await TGLogger.ScriptSep("米游币任务", false);
|
||||
return;
|
||||
}
|
||||
missionList.value = listResp.data.missions;
|
||||
await TGLogger.Script("[米游币任务]获取任务列表成功");
|
||||
}
|
||||
await TGLogger.Script("[米游币任务]正在获取任务状态");
|
||||
const stateResp = await apiHubReq.mission.state(ck);
|
||||
if (stateResp.retcode !== 0) {
|
||||
await TGLogger.Script(
|
||||
`[米游币任务]获取任务状态失败:${stateResp.retcode} ${stateResp.message}`,
|
||||
);
|
||||
showSnackbar.error(`[${stateResp.retcode}] ${stateResp.message}`);
|
||||
await TGLogger.ScriptSep("米游币任务", false);
|
||||
return;
|
||||
}
|
||||
await TGLogger.Script("[米游币任务]获取任务状态成功");
|
||||
todayPoints.value = stateResp.data.already_received_points;
|
||||
totalPoints.value = stateResp.data.today_total_points;
|
||||
await TGLogger.Script("[米游币任务]合并任务数据");
|
||||
mergeMission(missionList.value, stateResp.data.states);
|
||||
await TGLogger.Script("[米游币任务]任务数据合并完成");
|
||||
}
|
||||
|
||||
async function autoSign(ck: Record<string, string>): Promise<void> {
|
||||
const signFind = parseMissions.value.find((i) => i.key === "continuous_sign");
|
||||
if (!signFind) {
|
||||
await TGLogger.Script("[米游币任务]未找到打卡任务");
|
||||
return;
|
||||
}
|
||||
if (signFind.status) {
|
||||
await TGLogger.Script("[米游币任务]今日已打卡");
|
||||
return;
|
||||
}
|
||||
await TGLogger.Script("[米游币任务]正在执行打卡");
|
||||
const resp = await apiHubReq.sign(ck);
|
||||
if (resp.retcode !== 0) {
|
||||
await TGLogger.Script(`[米游币任务]打卡失败:${resp.retcode} ${resp.message}`);
|
||||
showSnackbar.error(`[${resp.retcode}] ${resp.message}`);
|
||||
return;
|
||||
}
|
||||
await TGLogger.Script("[米游币任务]打卡成功");
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.tusm-box {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
padding: 12px;
|
||||
background: var(--box-bg-1);
|
||||
border-radius: 4px;
|
||||
border: 1px solid var(--common-shadow-2);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
color: var(--box-text-1);
|
||||
}
|
||||
|
||||
.tusm-top {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.tusm-title {
|
||||
font-family: var(--font-title);
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.tusm-acts {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.tusm-btn {
|
||||
background: var(--tgc-btn-1);
|
||||
color: var(--btn-text);
|
||||
}
|
||||
|
||||
.tusm-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.mission-item {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 10px;
|
||||
background: var(--box-bg-2);
|
||||
border-radius: 4px;
|
||||
color: var(--box-text-2);
|
||||
|
||||
.left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.right {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 4px;
|
||||
|
||||
:first-child {
|
||||
width: 100px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
101
src/components/userScripts/tus-output.vue
Normal file
@@ -0,0 +1,101 @@
|
||||
<template>
|
||||
<div class="tuso-box">
|
||||
<div class="tuso-top">
|
||||
<div class="tuso-title">输出日志</div>
|
||||
<div class="tuso-top-acts">
|
||||
<v-btn class="tuso-btn" @click="clearLog()">清空</v-btn>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tuso-mid" ref="logRef">
|
||||
<div class="tuso-log" v-for="log in logs" :key="log">{{ log }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { event } from "@tauri-apps/api";
|
||||
import type { Event, UnlistenFn } from "@tauri-apps/api/event";
|
||||
import { nextTick, onMounted, onUnmounted, ref, useTemplateRef } from "vue";
|
||||
|
||||
let logListener: UnlistenFn | null = null;
|
||||
const logs = ref<Array<string>>([]);
|
||||
const logEl = useTemplateRef<HTMLDivElement>("logRef");
|
||||
|
||||
onMounted(async () => {
|
||||
logListener = await event.listen<string>("userScriptLog", async (e: Event<string>) => {
|
||||
logs.value.push(e.payload);
|
||||
await nextTick();
|
||||
logEl.value?.scrollTo({ top: logEl.value.scrollHeight, behavior: "smooth" });
|
||||
});
|
||||
});
|
||||
|
||||
function clearLog(): void {
|
||||
logs.value = [];
|
||||
}
|
||||
|
||||
onUnmounted(() => {
|
||||
if (logListener !== null) {
|
||||
logListener();
|
||||
logListener = null;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.tuso-box {
|
||||
position: relative;
|
||||
height: 100%;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
margin-left: auto;
|
||||
width: 800px;
|
||||
min-width: 800px;
|
||||
padding: 12px;
|
||||
background: var(--box-bg-1);
|
||||
border-radius: 4px;
|
||||
border: 1px solid var(--common-shadow-2);
|
||||
}
|
||||
|
||||
.tuso-top {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-end;
|
||||
}
|
||||
|
||||
.tuso-title {
|
||||
color: var(--common-text-title);
|
||||
font-family: var(--font-title);
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
.tuso-top-acts {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.tuso-btn {
|
||||
background: var(--tgc-btn-1);
|
||||
color: var(--btn-text);
|
||||
}
|
||||
|
||||
.tuso-mid {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
background: var(--box-bg-2);
|
||||
border-radius: 4px;
|
||||
padding: 8px;
|
||||
box-sizing: border-box;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.tuso-log {
|
||||
position: relative;
|
||||
height: 24px;
|
||||
min-height: 24px;
|
||||
white-space: pre;
|
||||
}
|
||||
</style>
|
||||
@@ -2,16 +2,15 @@
|
||||
<div class="tp-avatar-box">
|
||||
<div v-if="props.position === 'right'" class="tpa-text">
|
||||
<div>{{ props.data.nickname }}</div>
|
||||
<div :title="getAuthorDesc()">{{ getAuthorDesc() }}</div>
|
||||
<div :title="authorDesc">{{ authorDesc }}</div>
|
||||
</div>
|
||||
<div class="tpa-img">
|
||||
<img :src="avatarUrl" alt="avatar" class="tpa-icon" v-if="avatarUrl" />
|
||||
<img
|
||||
:src="props.data.pendant"
|
||||
alt="pendant"
|
||||
class="tpa-pendant"
|
||||
v-if="props.data.pendant !== ''"
|
||||
/>
|
||||
<div class="tpa-icon">
|
||||
<TMiImg :ori="true" :src="props.data.avatar_url" alt="avatar" />
|
||||
</div>
|
||||
<div v-if="props.data.pendant !== ''" class="tpa-pendant">
|
||||
<TMiImg :ori="true" :src="props.data.pendant" alt="pendant" />
|
||||
</div>
|
||||
<div
|
||||
:class="{
|
||||
'tpa-level-left': props.position === 'left',
|
||||
@@ -23,36 +22,22 @@
|
||||
</div>
|
||||
<div v-if="props.position === 'left'" class="tpa-text">
|
||||
<div>{{ props.data.nickname }}</div>
|
||||
<div :title="getAuthorDesc()">{{ getAuthorDesc() }}</div>
|
||||
<div :title="authorDesc">{{ authorDesc }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { computed, onMounted, onUnmounted, ref } from "vue";
|
||||
|
||||
import { useAppStore } from "@/store/modules/app.js";
|
||||
import { saveImgLocal } from "@/utils/TGShare.js";
|
||||
import TMiImg from "@comp/app/t-mi-img.vue";
|
||||
import { computed } from "vue";
|
||||
|
||||
type TpAvatarProps = { data: TGApp.Plugins.Mys.User.Post; position: "left" | "right" };
|
||||
|
||||
const props = defineProps<TpAvatarProps>();
|
||||
const appStore = useAppStore();
|
||||
const avatarUrl = ref<string>();
|
||||
const pendantUrl = ref<string>();
|
||||
|
||||
onMounted(async () => {
|
||||
avatarUrl.value = await saveImgLocal(appStore.getImageUrl(props.data.avatar_url));
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
if (avatarUrl.value) URL.revokeObjectURL(avatarUrl.value);
|
||||
if (pendantUrl.value) URL.revokeObjectURL(pendantUrl.value);
|
||||
});
|
||||
|
||||
function getAuthorDesc(): string {
|
||||
const authorDesc = computed<string>(() => {
|
||||
if (props.data.certification.label !== "") return props.data.certification.label;
|
||||
return props.data.introduce;
|
||||
}
|
||||
});
|
||||
|
||||
const levelColor = computed<string>(() => {
|
||||
const level = props.data.level_exp.level;
|
||||
@@ -110,33 +95,52 @@ const levelColor = computed<string>(() => {
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
left: 5px;
|
||||
display: flex;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 50%;
|
||||
background: var(--common-shadow-1);
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 50%;
|
||||
object-fit: contain;
|
||||
}
|
||||
}
|
||||
|
||||
.tpa-pendant {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
display: flex;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 50%;
|
||||
object-fit: contain;
|
||||
}
|
||||
}
|
||||
|
||||
.tpa-level-left,
|
||||
.tpa-level-right {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
display: flex;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 50%;
|
||||
background: v-bind(levelColor);
|
||||
color: var(--tgc-white-1);
|
||||
font-size: 10px;
|
||||
line-height: 18px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.tpa-level-right {
|
||||
|
||||
@@ -49,9 +49,7 @@ async function download(): Promise<void> {
|
||||
return;
|
||||
}
|
||||
const format = image.split(".").pop();
|
||||
const title = props.data.insert.custom_emoticon.hash;
|
||||
await saveCanvasImg(buffer.value, props.data.insert.custom_emoticon.hash, format);
|
||||
showSnackbar.success(`已保存${title}.${format}到本地,大小为${bytesToSize(size)}`);
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@@ -45,7 +45,9 @@ function getParsedData(data: SctPostDataArr): SctPostDataArr {
|
||||
res.push(cur);
|
||||
continue;
|
||||
}
|
||||
tp.insert = tp.insert.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
|
||||
if (typeof tp.insert === "string") {
|
||||
tp.insert = tp.insert.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
|
||||
}
|
||||
if (tp.insert === "\n") {
|
||||
child.push(tp);
|
||||
cur = { insert: "", attributes: tp.attributes, children: child };
|
||||
@@ -53,7 +55,7 @@ function getParsedData(data: SctPostDataArr): SctPostDataArr {
|
||||
child = [];
|
||||
continue;
|
||||
}
|
||||
const parsedText = getParsedText(tp);
|
||||
const parsedText = getParsedText(<TpTextType>tp);
|
||||
let check = 0;
|
||||
for (let i = 0; i < parsedText.length; i++) {
|
||||
const text = parsedText[i];
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
'tp-texts-header6': props.data.attributes && props.data.attributes.header === 6,
|
||||
}"
|
||||
:title="getTitle()"
|
||||
:style="{ textAlign: props.data.attributes?.align }"
|
||||
>
|
||||
<component
|
||||
:is="getComp(text)"
|
||||
@@ -27,6 +26,7 @@ import type { Component } from "vue";
|
||||
import TpImage from "./tp-image.vue";
|
||||
import TpMention, { type TpMention as TpMentionType } from "./tp-mention.vue";
|
||||
import TpText, { type TpText as TpTextType } from "./tp-text.vue";
|
||||
import TpUnknown from "./tp-unknown.vue";
|
||||
|
||||
type TpTexts = { children: Array<TpTextType | TpMentionType> } & TpTextType;
|
||||
type TpTextsProps = { data: TpTexts };
|
||||
@@ -36,7 +36,8 @@ const props = defineProps<TpTextsProps>();
|
||||
function getComp(text: TpTextType | TpMentionType): Component {
|
||||
if (typeof text.insert === "string") return TpText;
|
||||
if ("image" in text.insert) return TpImage;
|
||||
return TpMention;
|
||||
if ("mention" in text.insert) return TpMention;
|
||||
return TpUnknown;
|
||||
}
|
||||
|
||||
function getTitle(): string {
|
||||
@@ -51,6 +52,7 @@ function getTitle(): string {
|
||||
line-break: anywhere;
|
||||
white-space: pre-wrap;
|
||||
word-break: break-all;
|
||||
text-align: v-bind("props.data.attributes?.align");
|
||||
|
||||
&.tp-inline {
|
||||
display: inline;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
</div>
|
||||
<div class="tpu-main">UID {{ props.data.insert.game_user_info.game_uid }}</div>
|
||||
<div class="tpu-sub">
|
||||
<span>{{ props.data.insert.game_user_info.nickname }}</span>
|
||||
<span>{{ nickname }}</span>
|
||||
<span>|</span>
|
||||
<span>{{ props.data.insert.game_user_info.region_name }}</span>
|
||||
<span>|</span>
|
||||
@@ -19,6 +19,7 @@
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import showSnackbar from "@comp/func/snackbar.js";
|
||||
import { computed } from "vue";
|
||||
|
||||
type TpUid = {
|
||||
insert: {
|
||||
@@ -35,6 +36,9 @@ type TpUid = {
|
||||
type TpUidProps = { data: TpUid };
|
||||
|
||||
const props = defineProps<TpUidProps>();
|
||||
const nickname = computed<string>(() =>
|
||||
decodeURIComponent(props.data.insert.game_user_info.nickname),
|
||||
);
|
||||
console.log("tpUid", props.data.insert.game_user_info);
|
||||
|
||||
function copyUid(): void {
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
/>
|
||||
<div class="tp-video-share">
|
||||
<img alt="cover" :src="videoCover" class="tp-video-cover" />
|
||||
<img alt="icon" src="/source/UI/video_play_bili.png" class="tp-video-icon" />
|
||||
<img alt="icon" src="/source/UI/video_play_bili.webp" class="tp-video-icon" />
|
||||
<div class="tp-video-info">
|
||||
<span>{{ videoData.bvid }}|{{ timestampToDate(videoData.ctime * 1000) }}</span>
|
||||
<span>{{ videoData.title }}</span>
|
||||
|
||||
@@ -111,7 +111,7 @@ onMounted(async () => {
|
||||
html: `<i class="mdi mdi-download"></i>`,
|
||||
tooltip: "下载封面",
|
||||
click: async () => {
|
||||
await showLoading.start("正在下载封面");
|
||||
await showLoading.start("正在下载封面", props.data.insert.vod.cover);
|
||||
if (!coverBuffer.value) {
|
||||
coverBuffer.value = await getImageBuffer(props.data.insert.vod.cover);
|
||||
}
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
<div class="tp-vote-list">
|
||||
<div v-for="(item, index) in votes?.data" :key="index" class="tp-vote-item">
|
||||
<div class="tp-vote-item-title">
|
||||
<span>{{ item.title }}</span>
|
||||
<span>
|
||||
<span class="title">{{ item.title }}</span>
|
||||
<span class="val">
|
||||
<span>{{ item.count }}票</span>
|
||||
<span>{{ item.percent.toFixed(2) }}%</span>
|
||||
</span>
|
||||
@@ -90,25 +90,26 @@ function getWidth(item: TpVoteData): string {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.tp-vote-item-title :first-child {
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
}
|
||||
.title {
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.tp-vote-item-title :last-child {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 5px;
|
||||
}
|
||||
.val {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 5px;
|
||||
white-space: nowrap;
|
||||
|
||||
.tp-vote-item-title :last-child :first-child {
|
||||
font-size: 12px;
|
||||
}
|
||||
:first-child {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.tp-vote-item-title :last-child :last-child {
|
||||
font-size: 10px;
|
||||
:last-child {
|
||||
font-size: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tp-vote-progress {
|
||||
|
||||
@@ -29641,5 +29641,344 @@
|
||||
"Context": "就像所有的手工艺活计一样,编藤是一项依赖肢体多过依赖大脑的工作。\n每次定好型之后,蓝砚要做的就是静心,用双手认真编好每一条经纬。经过长期练习,编织的技巧与技艺不仅储存在她的头脑里,更内化成为了她双手的「记忆」。\n她的心灵也在这个过程中逐渐变得澄澈、洗练。\n蓝砚是一位藤编师,她未曾有过追逐日月一般宏大的理想,当然也不是武侠小说中里幽居的天纵奇才。\n她的生活简简单单,淳朴自然。\n编藤的时候,她的双手会循着过去每一天的记忆,熟练地织出细密的花纹和形状。\n与此同时,她的心并没有沉眠,她想着山间的雾,石崖边攀援而下的藤,光着脚踩起来绵绵软软的落叶。\n想着沉玉谷,想着她山水中的家,手下的藤也变得柔软起来。\n她希望能把这些美好的东西都用自己的双手编织出来,希望这些回忆能永远停留于自己的作品之中,或许是因为心中饱含温柔和善意,蓝砚编出的器皿总是透着一股拙朴温厚的味道。\n而在这种时候,猫儿、狗儿,还有山谷中的鸟雀、松鼠也都格外愿意亲近她。\n「就算是天上的神仙,肯定也愿意看我们蓝砚编藤哩。」爷爷曾经这样自豪地称赞她。\n没人知道是否曾经真的有神仙驻足观看蓝砚编藤,但蓝砚自己相信,既然神仙们愿意倾注自己的神力,庇护这一方清秀山水,令人安居乐业,肯定也会赞赏人类用心织出的作品,赞赏作品中的珍惜之意。\n所以当她看到自己随身携带的藤包中出现了一枚莹亮的神之眼时,一点也不惊讶,倒是拿起它,开开心心地采藤去了。"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 10000109,
|
||||
"name": "梦见月瑞希",
|
||||
"title": "绮梦缱绻",
|
||||
"description": "「秋沙钱汤」的股东,梦貘一族的心理诊疗师,致力于驱散噩梦,为人们带来安宁的心境。",
|
||||
"area": "稻妻",
|
||||
"brief": {
|
||||
"camp": "稻妻",
|
||||
"constellation": "貘枕座",
|
||||
"birth": "3月16日",
|
||||
"cv": { "cn": "浮梦若薇", "jp": "会泽纱弥", "en": "内奥米·麦克唐纳", "kr": "金曙现" }
|
||||
},
|
||||
"star": 5,
|
||||
"element": "风",
|
||||
"weapon": "法器",
|
||||
"materials": [
|
||||
{ "id": 104154, "name": "自在松石", "star": 5 },
|
||||
{ "id": 113071, "name": "谜土的护符", "star": 4 },
|
||||
{ "id": 101206, "name": "海灵芝", "star": 0 },
|
||||
{ "id": 112046, "name": "名刀镡", "star": 3 },
|
||||
{ "id": 104322, "name": "「浮世」的哲学", "star": 4 },
|
||||
{ "id": 113060, "name": "残火灯烛", "star": 5 }
|
||||
],
|
||||
"skills": [
|
||||
{
|
||||
"GroupId": 10931,
|
||||
"Id": 11091,
|
||||
"Name": "普通攻击·梦我梦心",
|
||||
"Description": "<color=#FFD780FF>普通攻击</color>\n进行至多三段攻击,造成<color=#80FFD7FF>风元素伤害</color>。\n\n<color=#FFD780FF>重击</color>\n消耗一定体力,短暂咏唱后,造成<color=#80FFD7FF>风元素范围伤害</color>。\n\n<color=#FFD780FF>下落攻击</color>\n凝聚风元素的力量,从空中下坠冲击地面,攻击下落路径上的敌人,并在落地时造成<color=#80FFD7FF>风元素范围伤害</color>。",
|
||||
"Icon": "Skill_A_Catalyst_MD"
|
||||
},
|
||||
{
|
||||
"GroupId": 10932,
|
||||
"Id": 11092,
|
||||
"Name": "秋沙歌枕巡礼",
|
||||
"Description": "编织出「美梦」的回忆,进入悬浮于地面之上的<color=#FFD780FF>梦浮</color>状态,并对周围的敌人造成一次<color=#80FFD7FF>风元素范围伤害</color>。\n\n<color=#FFD780FF>梦浮</color>\n·处于梦浮状态下时,梦见月瑞希将持续向前浮行,并将周期性对附近的敌人造成<color=#80FFD7FF>风元素范围伤害</color>;\n·期间,梦见月瑞希可以控制浮行的方向,并提升元素爆发<color=#FFD780FF>安乐秘汤疗法</color>中的<color=#FFD780FF>梦见风名物点心</color>的拾取距离;\n·基于梦见月瑞希的元素精通,提升队伍中附近的角色触发的扩散反应造成的伤害;\n·梦见月瑞希退场时,或是再次施放技能时,梦浮状态将会结束。\n\n<i>「宵宵夕月梦相逢,心曲缱绻绕意中。」</i>",
|
||||
"Icon": "Skill_S_Mizuki_01"
|
||||
},
|
||||
{
|
||||
"GroupId": 10939,
|
||||
"Id": 11095,
|
||||
"Name": "安乐秘汤疗法",
|
||||
"Description": "唤起无数「美梦」与「噩梦」的回忆,牵引附近的物体与敌人,造成<color=#80FFD7FF>风元素范围伤害</color>,并召唤出小貘来帮忙。\n\n<color=#FFD780FF>小貘</color>\n将跟随当前场上角色。每隔一段时间,小貘将在附近制造出1枚「梦见风名物点心」。队伍中自己的角色拾取梦见风名物点心后,若拾取者的生命值高于70%,梦见风名物点心便会发生爆炸并释放梦念冲击波,对周围的敌人造成一次<color=#80FFD7FF>风元素范围伤害</color>,否则会为拾取者恢复生命值,回复量受益于梦见月瑞希的元素精通。梦见月瑞希拾取梦见风名物点心并触发治疗时,治疗量还会提升100%。如果一段时间后仍未被拾取,梦见风名物点心也会发生爆炸并释放梦念冲击波,对周围的敌人造成一次<color=#80FFD7FF>风元素范围伤害</color>。\n\n<i>「晦暗的情绪要是埋藏太久,就会变成『噩梦』了喔。所以呀,不妨趁着这个机会,将它们作为『美味的点心』吃掉吧?」</i>",
|
||||
"Icon": "Skill_E_Mizuki_01"
|
||||
},
|
||||
{
|
||||
"GroupId": 10921,
|
||||
"Id": 1092101,
|
||||
"Name": "名月浮声",
|
||||
"Description": "梦见月瑞希在梦浮状态下触发扩散反应时,梦浮状态的持续时间延长2.5秒。该效果每0.3秒至多触发1次,在一次梦浮状态期间至多触发2次。",
|
||||
"Icon": "UI_Talent_S_Mizuki_05"
|
||||
},
|
||||
{
|
||||
"GroupId": 10922,
|
||||
"Id": 1092201,
|
||||
"Name": "昼想夜梦",
|
||||
"Description": "梦见月瑞希处于梦浮状态下时,队伍中附近的其他角色的元素类型为<color=#FF9999FF>火元素</color>、<color=#80C0FFFF>水元素</color>、<color=#99FFFFFF>冰元素</color>或<color=#FFACFFFF>雷元素</color>的攻击命中敌人时,梦见月瑞希的元素精通提升100点,持续4秒。",
|
||||
"Icon": "UI_Talent_S_Mizuki_06"
|
||||
},
|
||||
{
|
||||
"GroupId": 10923,
|
||||
"Id": 1092301,
|
||||
"Name": "诸病无病",
|
||||
"Description": "梦见月瑞希在队伍中时,队伍中自己的角色使用不具备复苏功能的恢复类料理时的回复量有概率提升30%,该效果的触发概率基于对应角色的好感等级(旅行者使用时,该效果将始终触发)。",
|
||||
"Icon": "UI_Talent_S_Mizuki_07"
|
||||
}
|
||||
],
|
||||
"constellation": [
|
||||
{
|
||||
"Id": 1091,
|
||||
"Name": "宿雾若水遥",
|
||||
"Description": "梦见月瑞希处于梦浮状态下时,每3.5秒将对附近的敌人施加持续3秒的「二十三夜待」效果。处于二十三夜待状态下的敌人受到风元素伤害而触发扩散反应时,将移除该效果,使此次扩散反应对该敌人造成的伤害提升,提升值相当于梦见月瑞希元素精通的1100%。",
|
||||
"Icon": "UI_Talent_S_Mizuki_01"
|
||||
},
|
||||
{
|
||||
"Id": 1092,
|
||||
"Name": "缠忆君影梦相见",
|
||||
"Description": "进入梦浮状态时,梦见月瑞希的每点元素精通,会为附近的队伍中所有其他角色提供0.04%<color=#FF9999FF>火元素</color>、<color=#80C0FFFF>水元素</color>、<color=#99FFFFFF>冰元素</color>与<color=#FFACFFFF>雷元素</color>伤害加成,效果持续至梦浮状态结束。",
|
||||
"Icon": "UI_Talent_S_Mizuki_02"
|
||||
},
|
||||
{
|
||||
"Id": 1093,
|
||||
"Name": "晓月又经宵",
|
||||
"Description": "元素战技<color=#FFD780FF>秋沙歌枕巡礼</color>的技能等级提高3级。\n至多提升至15级。",
|
||||
"Icon": "UI_Talent_U_Mizuki_01",
|
||||
"ExtraLevel": { "Index": 2, "Level": 3 }
|
||||
},
|
||||
{
|
||||
"Id": 1094,
|
||||
"Name": "泉轻流花暖",
|
||||
"Description": "拾取元素爆发<color=#FFD780FF>安乐秘汤疗法</color>中的<color=#FFD780FF>梦见风名物点心</color>时,将同时造成伤害与治疗,并为梦见月瑞希恢复5点元素能量。一次<color=#FFD780FF>安乐秘汤疗法</color>持续期间,至多通过这种方式恢复4次元素能量。",
|
||||
"Icon": "UI_Talent_S_Mizuki_03"
|
||||
},
|
||||
{
|
||||
"Id": 1095,
|
||||
"Name": "岁云暮矣待月归",
|
||||
"Description": "元素爆发<color=#FFD780FF>安乐秘汤疗法</color>的技能等级提高3级。\n至多提升至15级。",
|
||||
"Icon": "UI_Talent_U_Mizuki_02",
|
||||
"ExtraLevel": { "Index": 9, "Level": 3 }
|
||||
},
|
||||
{
|
||||
"Id": 1096,
|
||||
"Name": "慕念萦心间",
|
||||
"Description": "梦见月瑞希处于梦浮状态下时,队伍中附近的角色触发的扩散反应造成的伤害能够造成暴击,暴击率固定为30%,暴击伤害固定为100%。",
|
||||
"Icon": "UI_Talent_S_Mizuki_04"
|
||||
}
|
||||
],
|
||||
"talks": [
|
||||
{
|
||||
"Title": "初次见面…",
|
||||
"Context": "您好。我是梦见月瑞希,一名「心理诊疗师」。如果您有什么烦心事,尽可以来找我倾诉。无论是多么深沉的「噩梦」,我都会将它从您的心里驱除,绝不会留下一丝阴霾。不相信吗?那如果不耽误您的时间…现在要来我的诊室看看吗?"
|
||||
},
|
||||
{ "Title": "闲聊·心理诊疗", "Context": "昨晚的梦境…味道很美妙,感谢你与我分享。" },
|
||||
{ "Title": "闲聊·股东事务", "Context": "上个季度的财务报表还没看完…有点头疼呀。" },
|
||||
{
|
||||
"Title": "闲聊·郁结",
|
||||
"Context": "如果心里郁闷的话,就先放下手头的事,出去呼吸一下新鲜空气吧。"
|
||||
},
|
||||
{ "Title": "下雨的时候…", "Context": "阴翳的天气,容易勾起人心深处的负面情绪…" },
|
||||
{ "Title": "打雷的时候…", "Context": "莫非…将军大人今天的心情不好?" },
|
||||
{ "Title": "阳光很好…", "Context": "阳光太过耀眼,倒也不是完完全全的好事,照得我有点眩晕…" },
|
||||
{ "Title": "雨过天晴…", "Context": "天上的乌云散去了,是时候收拾心头的阴霾了。" },
|
||||
{ "Title": "刮大风了…", "Context": "嗯,风力刚好,神清气爽,心情也好。" },
|
||||
{
|
||||
"Title": "早上好…",
|
||||
"Context": "我已经把窗户打开,给房间通过风了。日出时分的清新空气、逐渐明亮的天色、还有微凉的早风,都会让人心情明朗…早上好。"
|
||||
},
|
||||
{
|
||||
"Title": "中午好…",
|
||||
"Context": "在中午时分,可以略微午睡一会补充精神…但别睡太久,会头晕的。需要我稍后叫醒你吗?"
|
||||
},
|
||||
{
|
||||
"Title": "晚上好…",
|
||||
"Context": "快到夜晚了,希望大家都能按时入睡,别熬夜玩游戏、看小说或者跳舞了…如果熬一个大夜,在凌晨才睡觉的话,睡眠的意义就大打折扣了…"
|
||||
},
|
||||
{
|
||||
"Title": "晚安…",
|
||||
"Context": "你要睡了么?正好,请把这杯牛奶喝了吧,我在里面加了一些草药,能让你睡得更好。晚安,你一定会做个好梦。"
|
||||
},
|
||||
{
|
||||
"Title": "关于梦见月瑞希自己·温泉的差别",
|
||||
"Context": "纳塔的温泉池开在了广阔的临海位置。一边享受凉快又清新的海风,一边和伙伴们玩耍的体验十分有趣。\n但想在稻妻推广的话,大家只会说:「和相熟的邻居一起泡澡倒是不错,但要和不认识的陌生人在温泉池里见面,感觉会很不好意思啊…」\n你看,就连温泉也有水土不服的说法。"
|
||||
},
|
||||
{
|
||||
"Title": "关于梦见月瑞希自己·「秋沙钱汤」",
|
||||
"Context": "你听说过稻妻的室内温泉「秋沙钱汤」么?其实,我投资它的时候正在设计一套全新的心理疗愈计划,在计划里,我想先利用加入了各种草药和香精的温泉让客人放松身体,进而放松心神,然后我再为客人进行进一步的诊疗。\n但是…「秋沙钱汤」的温泉泡起来太舒服,客人泡着泡着就容易直接睡着。醒来之后,还一个劲地夸我诊疗手段高超。\n我根本没进行任何诊疗啊,客人感觉那么好,只是单纯因为好好睡了一觉而已…\n明明是好好睡一觉就能解决的问题,为什么会拖成那么严重的疾病呢?\n唉,大家就别勉强自己了,该睡觉的时候,还是要好好睡觉呀…"
|
||||
},
|
||||
{
|
||||
"Title": "关于我们·旅程",
|
||||
"Context": "我也算是一位旅者,造访过提瓦特七国中的五国。即便如今定居稻妻,我也得时常去往纳塔,处理生意上的事务。所以,我们是同路人,可以多多结伴同行。"
|
||||
},
|
||||
{
|
||||
"Title": "关于我们·美梦",
|
||||
"Context": "食梦貘一族有条规定:未经允许,绝对不能吞食他人的美梦,那是人们珍贵的宝物,稍有损失便会催生失落的情绪。\n但你是个特例,你的美梦就像是富饶的宝库,几百年来,我还从没见过像你一样明亮的人…"
|
||||
},
|
||||
{
|
||||
"Title": "关于「神之眼」…",
|
||||
"Context": "我听人说,「神之眼」是被神明注视之人的证明。在神明的视线下,才会有如此神迹出现。但我也听那些未曾被神明注视的人说…他们也期待着拥有「神之眼」。\n渴求着不可求之物的人,就算在梦中获得了期冀的宝物,在梦醒时分,反而会更加怅然失怀吧。\n希望他们…不要为了追寻梦中的虚影,而把现实当作急于摆脱的噩梦。"
|
||||
},
|
||||
{
|
||||
"Title": "有什么想要分享…",
|
||||
"Context": "小安和小彻是我的伙伴,也是我的一部分——她们由我的妖力化形而成,分别代表着我的「智」和「灵」,是我心中理性和感性的显化。她们偶尔会协助我诊疗,在不得不战斗时,也非常下得去手呢。"
|
||||
},
|
||||
{
|
||||
"Title": "感兴趣的见闻…",
|
||||
"Context": "在「流泉之众」遇袭的前一天,我正从纳塔赶回稻妻,事后才从玛拉妮的来信中听说,你是改变局面的关键人物。这么一想,结合神子的描述,我曾在稻妻和纳塔两次错失与你见面的机会。好在如今,我总算与你这位传说中的旅者相识了。"
|
||||
},
|
||||
{
|
||||
"Title": "关于八重神子·旧事",
|
||||
"Context": "几百年前,我们曾是邻居。神子那家伙…以前可没这么沉迷于各种乐子。有时我还挺怀念的——她刚刚学会化为人形,天真单纯的那段时光…那个时候,她每天都要过来找我,让我尝尝她今天的梦是什么味道。\n我记得…有樱花、纸张、墨水、三彩团子,还有油豆腐。每次她都要抓着我化成人形,跑到城里寻找和梦里滋味对应的东西,要是被人发现了,我们就会唰地一下变成原来的模样,掉头就跑。我常常还跟不上她。"
|
||||
},
|
||||
{
|
||||
"Title": "关于八重神子·现状",
|
||||
"Context": "现在,她已经是「八重宫司」大人了,不知道她如今的梦境,还留有多少原来的气味。\n当然,我没有再尝过她的梦境。擅自吞吃他人的梦,是我们一族的绝对禁忌。就算宫司大人来找我,请我再尝尝她梦境的味道,我…恐怕也会拒绝吧。如今的我们,已经是彼此的竞争对手了。这次我必须跟上她。"
|
||||
},
|
||||
{
|
||||
"Title": "关于雷电将军…",
|
||||
"Context": "三川花祭后,我鼓起勇气邀请将军大人共浴。那时,她的一缕侧发飘进了温泉水里。我很想伸手帮她挽起来,却又担心这样的肢体接触会显得冒昧。一想到神子会面不改色地这么做,我就不由沮丧…我的修行,还需精进。"
|
||||
},
|
||||
{
|
||||
"Title": "关于珊瑚宫心海…",
|
||||
"Context": "海祇岛的那位现人神巫女举止端庄,与她交谈总是让我心情舒畅。今后,若是要在海祇岛拓展「秋沙钱汤」或其他店铺的业务,我还想与她多多合作…"
|
||||
},
|
||||
{
|
||||
"Title": "关于宵宫…",
|
||||
"Context": "你是说那位「夏祭的女王」么?嗯,我对她的印象很深。\n每隔一段时间,我都会做一次诊疗统计,看看稻妻哪里的居民最容易心力憔悴,哪里的居民心情还算开朗,哪里的居民又经常做噩梦…\n而宵宫小姐家附近的人们,几乎没有来诊疗过,我想,应该是宵宫小姐帮助了他们吧,有这么一位开朗活泼的邻居作伴,想不开心都难啊。"
|
||||
},
|
||||
{
|
||||
"Title": "关于神里绫华…",
|
||||
"Context": "绫华小姐…在我离开稻妻前,她还只是个小女孩,那时她就在练习花道和剑道了。我有一次曾经被她的兄长暗中请去,为她消解忧郁。\n她的梦境里…尽是老旧的木料味,混合着湿重的雨水气息,就像是一座摇摇欲坠的木亭,孤零零地伫立在暴雨里。我尽力为她诊疗,总算让她得以平和入睡。\n不知道绫华小姐心里的那座木亭,如今是否已经找到了支撑,能够安然呆在暴雨里了呢…"
|
||||
},
|
||||
{
|
||||
"Title": "关于九条裟罗…",
|
||||
"Context": "在之前,九条将军会定期请我去为天领奉行的人员做诊疗,其他人的心境有时候会有一些动摇,但在九条将军的梦里,我一直都只闻见了冷冷的金属味,既没有雨,也没有太阳,就像是满满堆放着「玉钢」的库房一样。\n我对九条将军这样心智刚强的人非常敬重。\n一个人,到底吃多少苦,要怎么做…才能把自己的心锻炼成如今这样呢?"
|
||||
},
|
||||
{
|
||||
"Title": "关于早柚…",
|
||||
"Context": "呵呵,除了长高的烦恼外,几乎无忧无虑的小貉…她的梦境一定很甜美。要不是她有预感般绕着我走,我还真想请她来「秋沙钱汤」工作。"
|
||||
},
|
||||
{
|
||||
"Title": "关于玛薇卡…",
|
||||
"Context": "火神玛薇卡女士?怎么说呢…她是那种,光是看一眼都会让人觉得想要戴上墨镜的人。她就像是真正的太阳那样,只要她握住你的手,你心中所有阴霾和忧郁都会在一瞬间被燃烧殆尽。\n尝、尝过梦境的味道没有?没有没有没有没有,我可不敢细致地尝,之前玛薇卡女士亲切地邀请我,但我一踏进她的梦里,就和跳进了火山一样,烫得我直咳嗽…\n可能是我的妖力还不够吧…"
|
||||
},
|
||||
{
|
||||
"Title": "关于玛拉妮…",
|
||||
"Context": "玛拉妮啊…她是我见过最热心的人了,长住纳塔期间,我定居的地方正是「流泉之众」,要是没有她的帮助,我在「流泉之众」的店铺可开不起来。当时她直接带着我去「话事处」找火神女士,确实吓了我一跳…\n不过,她的性格也像是海浪一样,有时候飞上浪尖,有时候沉在浪底,还有时候潜进暗流里,我根本捉摸不透她…\n心理?不用担心她,她是我见过心理状态最好的人之一。我可能还需要向她倾诉呢…"
|
||||
},
|
||||
{
|
||||
"Title": "关于纳西妲…",
|
||||
"Context": "我造访过须弥,在那位神明的权能范围内,我无法触及任何人的梦境,更不必谈影响和吞食。但那种感觉并非被压制,不曾令我难受,更像一种心平气和的约定…我想,她一定是位友善的神明。"
|
||||
},
|
||||
{
|
||||
"Title": "想要了解梦见月瑞希·其一",
|
||||
"Context": "「吞食梦境」是我们食梦貘一族特有的能力,无论美梦还是噩梦,都能成为我们的食粮,只是味道的好坏有别。以往,我的同族大多出于本能,将这种能力用于饱腹,但随着见闻增长,我意识到,这种能力可以帮助多愁善感的人类消解烦恼,发挥更大的价值…"
|
||||
},
|
||||
{
|
||||
"Title": "想要了解梦见月瑞希·其二",
|
||||
"Context": "其实,食梦貘一族的妖力并不强大。当年,漆黑的灾厄涌来时,我们只能惶恐地躲藏。邻家的狐斋宫姐姐在那场灾厄中牺牲了,我非常伤心,但无力改变什么…许多人也失去了重要的家人和伙伴,内心遍布疮痍…从那时起,我就有了为人们进行心理诊疗的想法,于是我出国求学,先后游历了璃月、须弥和纳塔,结合我的能力和人类的学术理论,慢慢确立了如今的诊疗之道。"
|
||||
},
|
||||
{
|
||||
"Title": "想要了解梦见月瑞希·其三",
|
||||
"Context": "这几年,我虽然不在稻妻,但好在我出资建设的温泉经营得小有名气,大家一听说我是「秋沙钱汤」的大股东,多少会给我些面子。我尽力综合了多国见闻的「心理诊疗」服务才得以推行下去。当然,遇上的挑战也不少…"
|
||||
},
|
||||
{
|
||||
"Title": "想要了解梦见月瑞希·其四",
|
||||
"Context": "于我而言,最大的挑战便是消化噩梦残留下来的负面情绪。唯有面对常规诊疗无法治愈的烦恼时,我才会直接吞食患者的噩梦,这也导致我吞下的噩梦都有着不小的烈性,令我相当困扰…以前,我会找个无人的地方缓慢「消化」它们的余威,要是被人撞见,我会非常难堪…"
|
||||
},
|
||||
{
|
||||
"Title": "想要了解梦见月瑞希·其五",
|
||||
"Context": "但作为心理诊疗师,帮助患者消解「噩梦」,就是我的职责。\n…或者说,这是我作为「食梦貘」的存在意义。\n我之前一直在想,我们「食梦貘」究竟为什么被赋予了这样的能力呢?能做到什么事情呢?如果「吞梦」只是为了饱腹,那梦境对我们来说,也只不过是以另一种形式存在的堇瓜而已,而我们,也和那些只知道叮咬堇瓜,既不知生也不知死的虫孑没有区别。\n直到做了诊疗师之后,我才找到了我能够做的事,那就是为了稻妻…不,为所有人驱除噩梦。\n呵…我本来以为,我一生都要独自面对这些「噩梦」了。但是,我却遇见了一位能够破除世间所有困境,连神明都认可,连神明的想法都能改变的人,愿意接受我脆弱的一面,与我分享近乎无尽的美梦…某种意义上,我也是你的「患者」了。"
|
||||
},
|
||||
{
|
||||
"Title": "梦见月瑞希的爱好…",
|
||||
"Context": "悠扬轻快的音乐对放松身心尤为有益,在纳塔时,我经常去「流泉之众」的科隆切广场听音乐,享受「悠可琴」那音色饱满的旋律…听说你也会许多乐器,要是有机会,能听你演奏一曲吗?"
|
||||
},
|
||||
{
|
||||
"Title": "梦见月瑞希的烦恼…",
|
||||
"Context": "太过强大的噩梦,有时会超出我的接受极限,甚至成为致命的毒物…比如,经历过漆黑灾厄的稻妻将士,在夜神之国与深渊战斗过的纳塔勇士,他们的潜意识或许刻入了绝望和恐惧的色彩,他们的噩梦也如刀割般难以下咽…我曾为一名「巡夜者战争」归来的勇士做过心理诊疗,在吞食她的噩梦后,我一连昏迷了几天…"
|
||||
},
|
||||
{
|
||||
"Title": "喜欢的食物…",
|
||||
"Context": "我最喜欢的食物?当然是完美无瑕的梦境了。开玩笑的,我可不会轻易去吃掉别人的美梦…最多,吃些甜食,弥补一下给患者治疗后的精神亏空。"
|
||||
},
|
||||
{
|
||||
"Title": "讨厌的食物…",
|
||||
"Context": "我不能接受潦草的食物,比如…干巴巴的面包、几片萝卜和卷心菜,配上冷冰冰的火腿…要知道,吃饭也是改善心境的重要环节,连一天三餐都随便应付,要如何维持心态健康呢?每个人都该对自己好一点,先从认真对待吃饭这件小事开始吧。"
|
||||
},
|
||||
{
|
||||
"Title": "收到赠礼·其一",
|
||||
"Context": "呜…这道料理的风味,是我做梦也没尝到过的味道。享受这种美味之后,今晚我肯定也能睡得香甜…"
|
||||
},
|
||||
{
|
||||
"Title": "收到赠礼·其二",
|
||||
"Context": "嗯…既平稳又美好的味道,就像我平时入睡时的梦境一样。谢谢你,我很喜欢。"
|
||||
},
|
||||
{
|
||||
"Title": "收到赠礼·其三",
|
||||
"Context": "你昨晚是不是做了糟糕的梦,没怎么睡好?这样的话…味觉确实可能稍稍失灵…菜肴我晚些再吃,请让我先为你诊疗。"
|
||||
},
|
||||
{
|
||||
"Title": "生日…",
|
||||
"Context": "今天对你我而言都相当重要,有你来到了这个世界,我才能探访无尽的美梦,见识到瑰丽美妙的天地…不如,就用只属于我们二人的梦境来庆祝吧?当然,要构筑这梦境,还需我们二人一同出力,请向我细致描述你的期望…"
|
||||
},
|
||||
{
|
||||
"Title": "突破的感受·起",
|
||||
"Context": "不止武力,我的心力也有所增进,这样一来,我便能面对更为强大的负面情绪了。"
|
||||
},
|
||||
{
|
||||
"Title": "突破的感受·承",
|
||||
"Context": "由衷感谢你,在你的支援下,我有信心承受一切诊疗残留的烦恼。"
|
||||
},
|
||||
{
|
||||
"Title": "突破的感受·转",
|
||||
"Context": "得到了你的鼓舞,我便能探究脆弱的自我,解析自己的弱点——心理诊疗师的心病,因你而走向康复,这是前所未有的创举。"
|
||||
},
|
||||
{
|
||||
"Title": "突破的感受·合",
|
||||
"Context": "负面情绪也属于「自我」的一部分。我们焦虑、躁动,以至于恐慌,究其根本是没有信心面对它们,无法在它们与积极的情绪之间找到平衡点。如今,有你在我身旁,我已将这平衡点深深刻入意识底层,再烈再毒的噩梦,我都不会畏惧。"
|
||||
},
|
||||
{ "Title": "元素战技·其一", "Context": "别皱眉呀。" },
|
||||
{ "Title": "元素战技·其二", "Context": "美梦疗法。" },
|
||||
{ "Title": "元素战技·其三", "Context": "镇定下来。" },
|
||||
{ "Title": "元素爆发·其一", "Context": "噩梦噩梦快离开…" },
|
||||
{ "Title": "元素爆发·其二", "Context": "来吧,小安,小彻。" },
|
||||
{ "Title": "元素爆发·其三", "Context": "「…晓时枕貘醒春风。」" },
|
||||
{ "Title": "打开宝箱·其一", "Context": "令人愉悦的收获。" },
|
||||
{ "Title": "打开宝箱·其二", "Context": "心情很不错,更有干劲了。" },
|
||||
{ "Title": "打开宝箱·其三", "Context": "财富是改善情绪的良药。" },
|
||||
{ "Title": "生命值低·其一", "Context": "不能逞强…" },
|
||||
{ "Title": "生命值低·其二", "Context": "似乎该让步了…" },
|
||||
{ "Title": "生命值低·其三", "Context": "不妙啊…" },
|
||||
{ "Title": "同伴生命值低·其一", "Context": "请退下。" },
|
||||
{ "Title": "同伴生命值低·其二", "Context": "请暂时避战。" },
|
||||
{ "Title": "倒下·其一", "Context": "噩梦…蔓延了。" },
|
||||
{ "Title": "倒下·其二", "Context": "无边的漆黑…" },
|
||||
{ "Title": "倒下·其三", "Context": "痛苦…没有散去。" },
|
||||
{ "Title": "普通受击·其一", "Context": "真粗鲁。" },
|
||||
{ "Title": "重受击·其一", "Context": "好失态…" },
|
||||
{ "Title": "重受击·其二", "Context": "麻烦的病患…" },
|
||||
{ "Title": "重受击·其三", "Context": "如此恶毒的一击…" },
|
||||
{ "Title": "加入队伍·其一", "Context": "有烦恼要倾诉吗?" },
|
||||
{ "Title": "加入队伍·其二", "Context": "诊疗时间到了。" },
|
||||
{ "Title": "加入队伍·其三", "Context": "周围…好像没有噩梦的味道。" }
|
||||
],
|
||||
"stories": [
|
||||
{
|
||||
"Title": "角色详细",
|
||||
"Context": "提起「秋沙钱汤」,稻妻居民们的第一印象大多是受到纳塔启发,采用了进口设备的人工温泉,称其为「放松身心的第一去处」。\n最近,这间温泉馆进行了大刀阔斧的改建,新增了名为「心理诊疗」的服务,短时间内便收获了诸多赞誉。\n重返稻妻的心理诊疗师——梦见月瑞希现身于台前,结合暖洋洋的温泉池水、悠悠然的香氛与奇妙的妖力,将困扰顾客们的不安心绪从意识深层驱离。\n人们逐渐了解到,这位食梦貘一族的女士是「秋沙钱汤」的大股东,温泉创办时的核心投资者,二次改建的话事人。\n可她完全不像个幕后的金主,反而展现出医生的专业素养与普通员工的耐心耐劳,置身于一线的工作之中,对每位客人细致问诊,从容精准地施以治疗。\n因此,在饱受噩梦之苦的人群中,瑞希很快就博取了可观的声望。\n而年事已高的老人或许会回忆起,他们曾在儿时睡前听到过几例食梦貘的故事。其中,梦见月瑞希的名号并未缺席。\n只不过,瑞希平和随性的形象,让人们很难联想到失色传说之中的妖怪。\n「秋沙钱汤」只是梦见月瑞希布局中的第一环,即便进展缓慢,梦见月瑞希计划着发展产业集团,从而提供全方位的娱乐活动,改善稻妻居民的精神状况。\n为此,她也在持续探索依靠妖力外的其他妙法,诸如有益心神的舒缓运动、释放活力的综合乐园、健康饮食的系统调控、还有令人欣然动容的传统游艺…\n对瑞希一无所知的员工看过日程安排后,都难免替她担心:这位老板远比她们劳累,她自己的心底…是否也埋藏着疲惫和焦虑?"
|
||||
},
|
||||
{
|
||||
"Title": "角色故事1",
|
||||
"Context": "相比坐拥万千传说的狐妖、形姿飒爽的天狗、或是令人生畏的鬼族,「食梦貘」的名号不至于无人听闻,但也远远谈不上响亮。\n在「百物语大会」之上,食梦貘一族只是席间不起眼的点缀,或于僻静的角落安心品茶,或同其他小妖静听大能们的状语豪言,或扮演侍者,为有乐斋这样的雅士斟酒倒茶。\n彼时,还是小小梦貘的梦见月瑞希参与宴席的全部乐趣,便在于欣赏自己的好友——幼狐身形的八重神子,一展其冰雪聪明的才智。\n看着神子趴在邻家的狐斋宫姐姐肩头,与有乐斋智辩三百回合,瑞希总能吃下平常数倍的点心;品味神子挑出对方破绽的逻辑,瑞希往往为她敏捷的思维连连点头,甚至将好友精彩的发言一一背诵。\n待到次日天明,见到轻轻打着呵欠的神子时,瑞希总会带着精心准备的油豆腐热切地凑上来,和她讨论昨晚未完的话题。\n几近崇拜的热情令神子都有些难以招架,只能摇动蓬松的尾巴,优雅地遮住半张小脸,支开话题说,「我们去吃拉面吧」。\n在乌鸦师傅的拉面摊前,在影向山南最为茁壮的樱树枝头,在夕阳映照的海滩上,幼狐和小小梦貘形影不离,无话不聊。\n甚至连梦境深处的秘密,都成了双方彼此分享的宝物。\n不过,神子毕竟贵为「白辰狐王血脉」的继承者,责任等待着她,成长二字背后的任务过于繁重。\n随着神子和瑞希先后习得化为人形的神通,她们也如凡人那般,被生活的洪流分划,送往了不同的水域。\n神子在狐斋宫的监督下修习高深莫测的妖术,在鸣神大社众巫女簇拥下攻读宫司的八百八十条守则,在众大妖之间穿行,作为白辰一脉的新星,巩固着族裔在众妖之中的地位。\n她的世界就像与瑞希一同眺望的远海,波澜壮阔,变化莫测,深藏危险和挑战,也时刻涌现着无尽的变数和机遇。\n而默默无闻的瑞希,则步入了稳定的生活:与族裔一同务农或纺织,维持生计,在固定的时间出巡,为寻求帮助的人们吞食噩梦…\n就像小溪汇入的湖泊,平静得有些无趣。\n两人共同出游的时间不断减少,最后,连一月一会的约定都难以维系。\n对此,瑞希并无遗憾。\n毕竟每天早晨,她依旧会和神子同时出门,神子接过她准备的那碗油豆腐时,依旧会对她投以「挚友限定」的真诚笑容。\n她自认为承担不了神子十分之一的重任,甚至与神子并肩前行时,都会被四面八方来的压力击垮。\n她只需要一直扮演清静的小角色,在神子需要时,为神子提供一份安宁。"
|
||||
},
|
||||
{
|
||||
"Title": "角色故事2",
|
||||
"Context": "可惜,平静的生活并非永恒。\n那一天,漆黑的灾厄如山墙倒塌般倾轧而来,妖怪与凡人在这股邪力面前并无分别,绝望的哭号响彻诸岛。\n不擅争战的食梦貘一族只能仓皇逃窜,藏匿至灾厄不屑一顾的角落。\n待到将军斩除最后的邪祟,瑞希与族裔们惊魂未定地归来时,昔日繁华的聚落已成废墟。\n瑞希心焦地四处奔走,寻找自己的朋友,所到之处,皆是生离死别的片段。\n邻家狐斋宫姐姐的身影无处可循,唯有双目黯然、面色苍白,脸颊留有隐约泪痕的神子,在临近枯萎的神樱树前低头祝祷。\n此后,瑞希熟知的神子便在做好准备前接过全部责任,成为了可敬的八重宫司。\n清晨出门时,与神子相见的时光也难以挽留——鸣神大社的善后工作堆积如山,神子不得不搬入神社,日以继夜地忙碌。\n食梦貘一族也被无尽的委托淹没,满目疮痍的稻妻,遍地都是身心皆受重创的妖怪与凡人。\n灾厄暂遭击退,但它们留下的恐怖记忆盘旋在众妖与众人心头,深深扎根在梦境深处,每夜都能唤起无尽的惊惧,击垮受害者的意志。\n这余威太过可怖,食梦貘长老的躯体难以抵御,为几位幕府武士驱散噩梦后便倒地不起,在挣扎中沉眠数月,醒转后碍于过度劳损而隐退。\n名不见经传的梦见月瑞希意外展现出她的才华,她将漆黑的猛毒从受害者的意识中抽离时,虽也如被刀割如受火刑,但终究好过动辄半年的长睡。\n于是,瑞希成为了受害者们的希望,每日帮助他们摆脱噩梦的侵扰,带着千般苦痛,蹒跚着归来,寻找僻静之地独自消解。\n那或许是瑞希最为艰难的时期,每分每秒都与受害者们感同身受,无论白昼还是午夜,眼前唯有黑中带紫的深色,流淌,弥漫,如溢出伤口的血。\n好在,意识深处依旧摹刻着挚友的身影,每当瑞希处于崩溃边缘,那抹樱色总能唤回她的理智。\n「身为宫司的神子要协助将军,为大家解决现实中的问题…我也要坚守本职,为大家解决精神上的问题!」\n如此自我鼓舞后,瑞希便能坚持下去。\n但瑞希疏忽了,这一心扎进工作,便是百年飞逝。\n待到瑞希尽力照顾诸多病患,抚平创伤后遗的杂波,她所熟知的神子,也随着宫司一职的锤炼,更为频繁地展现出笑对浮世众生的戏谑。\n难得同坐在昔时的拉面摊前,向来无话不谈的二人,居然多次交心未果,染上了陌生的沉默。\n良久的沉思后,瑞希选择了退让,说服了自己。\n那场灾厄中,神子所受的悲痛远在自己之上。鸣神大社的宫司一职带给她的劳苦,远非普通妖怪能够想象。\n或许,不以这种带刺的从容去面对滚滚涌来的事象,神子根本挺不过来?\n注视着不同风景,难免会有不同的感慨。\n至少,她们各自恪尽职守,如今的一切,都是她们做出最优选择的结果。\n若是将熟知的某人当成精神寄托,希望她永远定格于记忆中的模样,对双方而言,无疑都是枷锁。\n无论如何,都再也回不到无忧无虑的过去了。两人都有各自的路要走,不妨洒脱些,更不必苦苦纠缠。\n那些旧时光的回忆,就好好保存在意识深处吧。"
|
||||
},
|
||||
{
|
||||
"Title": "角色故事3",
|
||||
"Context": "噩梦之间亦有分别,身心健康之人偶尔会被灰暗的情愫困扰,他们的噩梦对于食梦貘而言,是正常的食粮;深受病痛侵扰,或是遭遇过严重创伤之人的噩梦,食梦貘虽能将其吞下,对外人声称,像是吃掉了无味的面包,但其中毒素般的威胁依然存在…\n饶是食梦貘中才能最为出众的瑞希,吞食后者过多时,也会被长久的病痛缠身。\n为了避免医人者先人罹患绝症,瑞希开始探索妖力之外的方法,以期为负面情绪去毒,再加以吞食。\n确认灾厄留下的阴影得到全面抑制后,瑞希便动身前往他国,开始学习人类最为前沿的医术,以建立自己独特的「心理诊疗」体系。\n在蒙德,她与冒险家协会合作,找了份「创伤后遗症诊疗顾问」的兼职,积累了宝贵的诊疗经验;\n在璃月,她跟随沉玉谷的医师,认识了多种安神定气的草药,并习得了种植与应用的细致方法;\n在须弥,她受到本地香炉的启发,结合先前探索的草药,开发出运用熏香,快速使人松弛入梦,有益治疗的辅助手段;\n在枫丹,她补充了「科学院」派系的医学理论知识,还研究了前卫的映影科学,一探图形学与人类心理的奇妙关联;\n历经多年游学后,瑞希的终点站是纳塔南域,活力奔涌的「流泉之众」。\n「温泉勇士」热情招待了瑞希,还向瑞希展现了他们面对漆黑灾厄同源之敌的豪放。\n尤其是玛拉妮,她与瑞希初见时,正和孩子们玩闹,跌跌撞撞闯进瑞希怀里,抱着瑞希一同摔进温泉,给瑞希留下了冒冒失失的印象…\n结果在面对那些可怕的敌人时,玛拉妮却将其乐观的性格转化为坚强的后盾,可靠得无可挑剔,战后也未曾留下瑞希认知中的心理创伤。\n千般好奇的瑞希深入调查后,得出了她自己的结论:除去强大的意志支撑,张弛有度的生活方式对于维持心理健康相当重要。\n平时尽情享受生活,挥洒热情与活力,将每天过得开心自在,战时不留遗憾地踏上前线,神清气爽地战斗,或许就是纳塔勇士们的诀窍?\n「玩得好、玩得尽兴,才能好好战斗,将生命中的难题当成游戏中的挑战,不紧不慢地打败。」。\n于是,瑞希萌生了建设一个「娱乐集团」的想法,要为稻妻居民引入多种休闲方式,从而显著改善人们的精神状况。\n她从「流泉之众」选中了温泉和水上运动,从「悬木人」选中了攀岩登山等相对安全的极限运动,还打算聘请「沃陆之邦」的专业人士开设健身馆,并找到了多位执行人,开始了自己的布局…"
|
||||
},
|
||||
{
|
||||
"Title": "角色故事4",
|
||||
"Context": "在稻妻居民的美谈之中,食梦貘一族始终有着「自身无欲无求,对他人有求必应」的随和形象。\n而瑞希更是其中的典例,她帮助人们抵御噩梦侵扰的资历颇为深厚,却没有依靠资深的招牌提价,收取费用的标准反而相当宽松——\n面对平民百姓,瑞希会以患者时薪的一半为基数,乘上诊疗所用的时间,严格计算自己的苦劳费,哪怕只能买下一份拉面,也没有怨言。\n按照瑞希的观点,这些患者本就饱受折磨,更不能在经济开销上为他们增加压力。\n若是患者财力可观,瑞希则会请对方自行定价,开出「以阁下的财力,这次诊疗应得的报酬」。\n无论出于对瑞希的尊重,还是为了维持自身的尊严,富裕的患者都会开出漂亮的价钱…\n这样的做法使得瑞希的诊疗服务有口皆碑,有求于她的预约源源不断,以至于她常常整周无休。\n而瑞希将病患的噩梦吞食后,就如吃下了一大碗稻米,只要杂质的毒性不强,妖力和体力都会得到补充。\n可以说,瑞希很少为自己花钱,至多为自己准备几套平民的衣物,偶尔尝尝价格宜人的甜品,生活开销相当之低。\n一位没有假期,没有消费欲望,支出近乎为零,工作尤其勤快的妖怪,究竟能在几百年里存下多少钱…这个问题很难找到参考案例。\n不管怎样估算,这笔存款都不容小觑,它正是瑞希进行投资的基础。\n虽说锁国的风波使瑞希无法及时返回稻妻,验收「秋沙钱汤」的成果,其他几个产业项目也还停留在图纸上,短时间内没有眉目…\n但这段时间,瑞希也没闲着,而是在不断跟进提瓦特前沿的风尚,以确保自己将来的集团老少皆宜,能为各种年龄段的患者排解烦忧。\n得到了新时代理论的启发后,瑞希为了减轻病人的心理负担,在努力地去除心理诊疗的医学表现,转而称病患为「客人」,用休闲活动的形式装点诊疗这一严肃行为,力求顾及每个细节,予病人以最佳的松弛感。\n返回稻妻后,瑞希更是应用了她在枫丹习得的研究成果,开始亲自录制「宣传节目」的新式映影,力求声名鹊起。\n为了能让人们尝试新的诊疗体系,尽早告别忧虑,就算自己在镜头前多次碰壁,甚至有时紧张得过度呼吸,也无比值得…\n不过,瑞希的面前还有一位极具合作潜质的同行。\n那就是好友神子执掌的艺术机构「八重堂」。"
|
||||
},
|
||||
{
|
||||
"Title": "角色故事5",
|
||||
"Context": "「辅助患者应对焦虑的手段应当偏向引导,逐步揭露其思维困境,还是偏向安慰,以消除患者的不安为第一要务?」\n「为了解决噩梦的困扰,长期运用妖力直接去除负面情绪,是否会产生连带的问题?」\n「若是无法协助患者解决现实中的问题,要怎样保证他们不会旧病复发?」\n……\n漫漫百年的羁旅结束后,瑞希与神子探讨了太多太多话题。\n彼时,她们在童年最常碰头的那颗樱树下铺开桌布,摆好点心,办了一场小小的茶会,从破晓聊至垂暮。\n与好友重逢的欢欣之外,更为理性的交流互换了双方的心声。\n神子认为,娱乐理应保持纯粹的本质。如果患者能主动追求快乐,始终以明亮的色彩填满意识,很有可能抹除负面情绪的容身之地…\n瑞希则担忧,只是以「追求快乐」为核心手段,而不去正视困扰自己的症结,或许会使情绪失衡。\n茶会平静结束时,两人都接受了对方的想法,明白对方会以不同的方式为稻妻人带来新的解忧机制。\n在瑞希的理解中,「八重堂」以轻小说为核心、发展多种文化产品的娱乐手段,会将用户引入无数的美好世界,为生活注入希望与动力…\n不过,文化产品有着基本的门槛,太过劳累或心力憔悴之人很难拿出充足的精力,或是集中注意力、进行长时间的阅读和思考。\n同时,完全沉浸在轻小说营造的幻想世界中,或许无形间也会忽略一些现实的问题。\n瑞希设想中的集团,在解决食梦貘一族的难题之余,亦可补全这块拼图——\n疗愈无暇或无力享受文化作品之人,帮他们找到新的生活乐趣;\n又将过度沉溺之人适当引导,使其目光及时聚焦于自己的心房。\n如此以来,从每日劳苦工作的普通人,到学识可观的知识分子,无论贫富和贵贱,每个稻妻人都能找到改善情绪的完整方案。\n遇见常规手段难以消解的沉重情绪,或是需要细腻处理的芥蒂时,再由食梦貘驱动妖力,抹除梦境中的污浊。\n有条不紊、严丝合缝。\n只不过,坊间的讨论时常流于表象,街坊邻居们不知听说了什么传闻,从海外归来的这位秋沙钱汤大股东带着全新的产业,向八重堂发起了挑战…\n这传说愈演愈烈,以至于有人为此创作了《我与总角之交的商战》一类的作品,短时间内搏得了相当之高的讨论度。\n这逸闻传入瑞希耳中时,瑞希先是错愕片刻,随即莞尔一笑。\n倒也不错?\n神子自然喜欢这种乐子,而瑞希也的确想在事业上发力,奋力追逐,以至于超越曾在自己前方的好友。\n在双方的默许下,两名好友也成了互有默契的「竞争对手」。"
|
||||
},
|
||||
{
|
||||
"Title": "小安与小彻",
|
||||
"Context": "瑞希的身边常有两只小小的食梦貘相伴,近乎形影不离。\n日常生活中,两只小貘就如助理女仆,会帮助瑞希调制饮品,烹饪料理,及时递上各种所需的物品;\n战斗中,两只小貘既能喝彩助威,也能亲自上阵,帮助瑞希对抗魔物…\n瑞希叫她们「小安」与「小彻」,简单直观的称呼,代表「心绪安定」与「贯彻知性」。\n她们并非瑞希的同族,而是瑞希自身妖力的具象,关联着瑞希的灵与智。\n心理诊疗师将病患的忧愁、焦虑和恐惧照单全收,她们的负面情绪却无人打理,久而久之,满是疮痍的内心极有可能彻底坍塌。\n瑞希见过完全崩溃的同行,看着她们卧床不起,甚至彻底丧失思考能力,瑞希暗暗告诫自己,绝不能重蹈覆辙。\n为此,瑞希要为自己进行诊疗。\n设想一个感性满溢的自己,能呼吸般自然地与患者共情,自身的心绪也薄如蝉翼,细腻敏感得一触即溃…\n扮演一个过于理性的自己,对一切问题施以逻辑的评判,而剥离主观的情感,以至于有些不近人情…\n凝聚着两种「瑞希」之思维的小小梦貘,有着各自不足之处,在陪伴瑞希为患者诊疗的过程中,会从最为极端的角度给出分析,也会将极端的代价完整留存。\n此后,瑞希再分别安慰两只小貘,就如映照两面性质截然相反的镜子,从而剖析自己心中易被忽视、但至关重要的问题。\n若是考虑一些问题时,过分脆弱,那就像心宽之人那样去思考,拿出一定的「无情」…\n假如与人沟通时稍显冷厉,导致对方的情绪恶化,也可以适当从「感受」出发,去配平客观的逻辑与主观的情绪。\n与小安和小彻沟通的过程,也是瑞希建立自身内在情绪之「均衡」的关键。\n历经上百年的调和,见证诸多病患后,小安和小彻的思维已不再处于感性和理性的两个极端,正如瑞希本人,大多时候都能找到一个感性与理性的平衡点。\n等到小安不易被过度共情惹得独自流泪,小彻不再对太过主观的病人锐利批判时,再为强劲的负面情绪都难以再撼动瑞希的情感。"
|
||||
},
|
||||
{
|
||||
"Title": "神之眼",
|
||||
"Context": "就算是无比可口的料理,一日三餐重复不变,吃上百遍千遍,也会令普通人难以忍受。\n而在瑞希的味觉世界中,品尝寡淡的噩梦,已是一种幸运。\n有些人的噩梦就如厨房爆炸后的产物,各种调料混杂其中,还有木炭烟熏的苦味,甚至锈味和强酸。\n那美梦呢?\n鲜有食梦貘知道美梦的味道,因为食梦貘一族有着不成文的规矩:「未经允许,不得吞食他人的美梦。」\n成为心理诊疗师后的第十年,瑞希才有幸品尝到宝贵的美梦。\n一位接受了瑞希诊疗,完美痊愈的女孩带着礼物前来感谢她。闲聊之时,女孩突发奇想,要与瑞希分享自己色彩斑斓的好梦。\n饱含童真、活力与绮灿幻想的梦境,味道实在惬意、温暖细腻的清甜令瑞希完全沉浸其中。\n从那以后,瑞希就爱上了各种甜品,心底更是萌生了一个大胆的想法。\n妙不可言的美梦或许本身就是一种解药,足以消融人们的负面情绪?\n若是能够用妖力制造美梦,作为一剂良药,对病患的情绪想来大有裨益。\n而且…也能将其作为珍藏的美食,偶尔给自己一点调剂?\n不过,食梦貘毕竟没有造物的权柄。某种程度上,美梦是愿望投影在人们心中的产物,无比明净,难以用外力重现,凭空捏造更是一种奢求…\n每个人的愿望都有所不同,自然不能用笼统的「配方」调制万能的美梦。若是为了了解人们的真实想法,探寻人们内心深处的秘密,本身又可能成为越界的行为,加重人们的紧张和不安…\n结果略有遗憾,瑞希没能参悟解药之梦的制作方法。\n好在,上万个日夜的探寻与钻研也没有白费,瑞希的心意终究得到了回应——\n某个疲惫而充实的夜里,瑞希梦见自己变回了小小的梦貘,与挚友在拉面摊前享用料理。\n这梦境呈现出轻烟与柔风般的质感,似乎隐含着诸多美梦之间富有共性的轮廓。\n脱离束缚,自由自在,悠悠哉哉…\n梦境行至此处,一枚玲珑剔透的神之眼悄然出现在瑞希的枕边…\n此后,瑞希似乎得到了启发,换了个思路。\n她要将人们引向松弛与舒然的梦,唤起人们心中对宝贵事物的回忆。\n相信人们心底珍藏的美好,必定会在关键的时刻苏醒,为梦境着色,将其装点成最瑰丽的模样。"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
@@ -1185,7 +1185,7 @@
|
||||
]
|
||||
},
|
||||
"story": [
|
||||
"\r\n就像深流巨浪中的海兽会循水声前往安息之所,\r\n一度主宰燃火之陆的巨龙亦有收拢遗殖的坟茔。\r\n那里,累累的、蛛腿般的皑骨如巨爪直摄天空。\r\n看守夜晚与死境的秘械受领谕令彻日盘桓游巡。\r\n\r\n任谁来看那都是极危险之处,机敏的信使也不愿打探那里的消息。\r\n更何况,何必去打扰,那些在用指爪细数最后残余的死期的大敌。\r\n在部族的篝火边听到关于此处的故事,万杰鲁却猛然欣喜地站起。\r\n因世上再没有比它们更可怕的仇人,想必能从它们的残躯中取得,\r\n身具奇力的万杰鲁此时无比渴求的东西。\r\n\r\n身具奇力的万杰鲁啊,即便百年的铁木在她挥动的瞬间就自正中折断,\r\n原矿在她收握的掌心中化为齑粉,拦路的巨石也不得不屈于她的臂弯,\r\n更别提那些用最坚硬的金属打造的物什,在她的指间就如失形的软泥,\r\n何处能取得一把趁手的兵器呢,万杰鲁的日思夜想,终于迎来了答案。\r\n\r\n她从图兰的山巅跃入火山,避过如蛇行进的造物,进入荒凉太久的废墟。\r\n她追随曾与巨龙鏖战的英雄留下的踪迹,那些角力者于山壁留下的巨痕,\r\n若自己出生在那个时代就好了,她想,就如那留下诸多传说故事的先人,\r\n羡慕部族先祖能与魁伟的巨龙比较身手,与元初的神灵试量武艺的短长。\r\n\r\n而那被叙事人煞有介事讲述的髑髅嶙峋之处,\r\n也不过是几具死状惨烈的巨兽,孤凉的尸骸。\r\n正要失望时,伸出手的少女于恍惚中看见张开双翼的影子向她扑来,\r\n来不及考虑那形象究竟是何物,情急中,少女大笑着与那金影缠斗。\r\n战斗的惨烈不必赘述,那是以牙还牙,以眼还眼,以力抵命的厮打,\r\n最后,终结战斗的是部族的勇士,用血淋淋的双手撕下巨龙的残翼。\r\n而那金光的影子一如曾真实存在造物,于一声哀鸣之后隐去了身形。\r\n\r\n回过神来,她仍保留着伸手时的姿态,仿佛刚才不过是短暂残梦。\r\n那真的是梦吗,战斗时碎裂的臂骨仍隐隐作痛,在她向上的手中,\r\n不知何时出现的沉甸龙骨,与战斗时她抓住的巨兽之尾一般无二。\r\n\r\n将这件事告知喜欢讲故事的友人时,「谜烟主」那位大祭司皱了皱鼻子,\r\n「图兰大火山可是禁地,普通人进都进不去,更何况,那时你才几岁」\r\n持仪式刃的男人说,「而且,你说真的?我们都没见过你抽出过那把剑」\r\n「当然是真的,不用它只是因为大多数时候都用不着,光用手就够了」\r\n在临出战前的篝火旁,已能看到岸边漆黑巨兽的轮廓,万杰鲁这样说,\r\n她握住那白色骨刃的刀柄,静静等待着那值得她再次拔出长剑的战场。"
|
||||
"\r\n就像深流巨浪中的海兽会循水声前往安息之所,\r\n一度主宰燃火之陆的巨龙亦有收拢遗殖的坟茔。\r\n那里,累累的、蛛腿般的皑骨如巨爪直摄天空。\r\n看守夜晚与死境的秘械受领谕令彻日盘桓游巡。\r\n\r\n任谁来看那都是极危险之处,机敏的信使也不愿打探那里的消息。\r\n更何况,何必去打扰,那些在用指爪细数最后残余的死期的大敌。\r\n在部族的篝火边听到关于此处的故事,万杰鲁却猛然欣喜地站起。\r\n因世上再没有比它们更可怕的仇人,想必能从它们的残躯中取得,\r\n身具奇力的万杰鲁此时无比渴求的东西。\r\n\r\n身具奇力的万杰鲁啊,即便百年的铁木在她挥动的瞬间就自正中折断,\r\n原矿在她收握的掌心中化为齑粉,拦路的巨石也不得不屈于她的臂弯,\r\n更别提那些用最坚硬的金属打造的物什,在她的指间就如失形的软泥,\r\n何处能取得一把趁手的兵器呢,万杰鲁的日思夜想,终于迎来了答案。\r\n\r\n她从图兰的山巅跃入火山,避过如蛇行进的造物,进入荒凉太久的废墟。\r\n她追随曾与巨龙鏖战的英雄留下的踪迹,那些角力者于山壁留下的巨痕,\r\n若自己出生在那个时代就好了,她想,就如那留下诸多传说故事的先人,\r\n羡慕部族先祖能与魁伟的巨龙比较身手,与元初的神灵试量武艺的短长。\r\n\r\n而那被叙事人煞有介事讲述的髑髅嶙峋之处,\r\n也不过是几具死状惨烈的巨兽,孤凉的尸骸。\r\n正要失望时,伸出手的少女于恍惚中看见张开双翼的影子向她扑来,\r\n来不及考虑那形象究竟是何物,情急中,少女大笑着与那金影缠斗。\r\n战斗的惨烈不必赘述,那是以牙还牙,以眼还眼,以力抵命的厮打,\r\n最后,终结战斗的是部族的勇士,用血淋淋的双手撕下巨龙的残翼。\r\n而那金光的影子一如曾真实存在造物,于一声哀鸣之后隐去了身形。\r\n\r\n回过神来,她仍保留着伸手时的姿态,仿佛刚才不过是短暂残梦。\r\n那真的是梦吗,战斗时碎裂的臂骨仍隐隐作痛,在她向上的手中,\r\n不知何时出现的沉甸龙骨,与战斗时她抓住的巨兽之尾一般无二。\r\n\r\n将这件事告知喜欢讲故事的友人时,「烟谜主」那位大祭司皱了皱鼻子,\r\n「图兰大火山可是禁地,普通人进都进不去,更何况,那时你才几岁」\r\n持仪式刃的男人说,「而且,你说真的?我们都没见过你抽出过那把剑」\r\n「当然是真的,不用它只是因为大多数时候都用不着,光用手就够了」\r\n在临出战前的篝火旁,已能看到岸边漆黑巨兽的轮廓,万杰鲁这样说,\r\n她握住那白色骨刃的刀柄,静静等待着那值得她再次拔出长剑的战场。"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -4207,6 +4207,46 @@
|
||||
"\r\n正如流泉之水从未有过固定的形态,人与精灵的心也会伴着夜风摇漾。\r\n直至龙主的焚火即将噬尽少年之身,她才意识到自己的目标早已变乱。\r\n只要将盲信正义之人抛弃于此就好,更何况她早已劝告过他抛弃村落,\r\n只要再找到另一个能成王之人就好,更何况他的理想从来也与她无关。\r\n\r\n既然如此,又何必要在他惊讶的瞳中,为了他的愚蠢而迎向龙之火呢?\r\n也许这便是众水之主所寻求的「交流与理解」吧,水精少女这样想着,\r\n最后一次向他投去了浅笑,覆尽了如日的火,升腾的水汽中唯余虹色。\r\n\r\n……\r\n\r\n梅兹特利自古以来流传的绘卷,则讲述了与之截然不同的另一个故事——\r\n在轻柔的月色下,英杰乌努库与流落异乡的水精少女相遇,坠入爱河,\r\n却又因一时疑心,与那名为希涅伊菈(或作伊艾涅伊菈)的恋人离散。\r\n「皆言人心如潮水易变,然而征服潮水何其容易,征服人心何其艰难」\r\n抱着悔恨,英杰乌努库的行迹踏遍了每一寸灼原,只为寻回心爱之人。\r\n数十年如一日的追寻,最终还是让水精少女刚硬的心生出了一丝怜悯,\r\n她将柔软的云朵从天穹摘下,变作彩虹,引导着英杰步向了海的彼方。\r\n在圣火的祝福下,英杰乌努库与恋人最终相聚,自此便再也未曾分离。\r\n部族中的老人相信,如今的贝壳正是在那个时候坠入海中的彩虹碎片,\r\n贝壳之所以总是成双成对的两片,也正是因为它们象征着团圆的心愿。"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 13432,
|
||||
"name": "且住亭御咄",
|
||||
"description": "过去曾有以行灯焰火为形于稻妻四处奔行的妖怪,这也是其曾经寄身的一处灯盏吧。",
|
||||
"star": 4,
|
||||
"weapon": "长柄武器",
|
||||
"materials": [
|
||||
{ "id": 114036, "name": "今昔剧画之鬼人", "star": 5 },
|
||||
{ "id": 112118, "name": "迷光的蜷叶之心", "star": 4 },
|
||||
{ "id": 112046, "name": "名刀镡", "star": 3 }
|
||||
],
|
||||
"affix": {
|
||||
"Name": "好事者奔行灯",
|
||||
"Descriptions": [
|
||||
{
|
||||
"Level": 0,
|
||||
"Description": "施放元素战技时,提高<color=#99FFFFFF>20%</color>攻击力和10%移动速度,持续10秒。"
|
||||
},
|
||||
{
|
||||
"Level": 1,
|
||||
"Description": "施放元素战技时,提高<color=#99FFFFFF>25%</color>攻击力和10%移动速度,持续10秒。"
|
||||
},
|
||||
{
|
||||
"Level": 2,
|
||||
"Description": "施放元素战技时,提高<color=#99FFFFFF>30%</color>攻击力和10%移动速度,持续10秒。"
|
||||
},
|
||||
{
|
||||
"Level": 3,
|
||||
"Description": "施放元素战技时,提高<color=#99FFFFFF>35%</color>攻击力和10%移动速度,持续10秒。"
|
||||
},
|
||||
{
|
||||
"Level": 4,
|
||||
"Description": "施放元素战技时,提高<color=#99FFFFFF>40%</color>攻击力和10%移动速度,持续10秒。"
|
||||
}
|
||||
]
|
||||
},
|
||||
"story": [
|
||||
"\r\n传说野地如磷火飘荡的鬼焰之中,也藏有稻妻古时灵体的精魄。\r\n那时喜欢听取秘密的无形妖怪借由火焰的形体穿梭围炉与火钵,\r\n在柴禾燃烧的噼啪响动中,窃取那些捧茶而谈的人述说的隐秘,\r\n而后将一切有意思的故事都在夜行者的盛宴上一一道出,毕竟,\r\n所谓「御伽众」本就为提供这些,以供诸多大人酒间消遣之乐。\r\n\r\n「啊,今宵如此欢快,希望此后岁月中亦能有如今宵之时。」\r\n身处上座,被一众妖狐簇拥着的白辰狐主带着遗憾如此感慨。\r\n「时间啊,时间若能停在此处就好了。」如是说着,端起酒碗,\r\n为台上藉藉无名且地位卑微的小妖赐予「且住亭」这一名号。\r\n\r\n只是世上大多数的事都不为人所愿,就像哀苦所祈之物往往并不可得。\r\n而白辰的主人生出一瞬的悲寂之心,也在漆黑浪潮侵蚀之中得到应验。\r\n世上再无夜行的百妖如是酣畅的时刻,而灯火之侧亦空余恸哭与哀嚎。\r\n在这场惨烈绝伦的战场之中,有昔日倚靠戏言取乐的自己存身之处吗?\r\n但一想到那位为自己赐名的大人,妖力羸弱的小妖怪亦决定放手施为。\r\n天幕受阴影遮蔽的时日,它燃烧自己的魂灵,在诸多火焰中四处奔行,\r\n昔日俱述滑稽事物的口舌,也被用于详细递说诸多战场的战况与敌情。\r\n\r\n只是长久的奔波带来的损耗积重难返,\r\n分神太多的妖怪几乎因此磨尽了神魂。\r\n行灯之中,再也无法述说精妙的言语,\r\n甚至就连过往珍贵的回忆也散落四处。\r\n\r\n而今,据说神智模糊的妖物忘却了一切,\r\n唯有在众人云集,谈天说地时才会出现。\r\n或许那述说者一一讲述幻梦奇谭的氛围,\r\n能让其稍稍想起,再无法复归的过往吧。"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 13501,
|
||||
"name": "护摩之杖",
|
||||
@@ -6196,6 +6236,46 @@
|
||||
"\r\n以灼烟熏染她的双眼,她便不会被映入瞳中的杂色所惑。\r\n以燧刃祝赐她的双踝,她便不会将她所爱的同胞们抛却。\r\n依循久远尊贵的契约,夜谕者拣选出魂质如星曜的幼童,\r\n为她戴上鹰羽的礼冠,指引失去形体的古民蛰伏于夜中。\r\n\r\n无论是沉溺于迷梦的群龙,还是幽域中争执不休的诸圣,\r\n都未能察觉称贤者的谋计。深谷之民与贵裔立定的盟约,\r\n阻隔了战酋们渴血的烽燹,也让迷烟中唯有安逸的死寂, \r\n而那深谷中最勇武的战士,竟只能为侍奉祭星者的奴仆。\r\n这并非是远大计划的一环,但堕落者的衰朽仍令他憎厌。\r\n既然如此,那便略施小计,以善念之名煽诱她反抗群龙。\r\n\r\n正如称贤者所思忖的那般,操弄人心向来便是易如反掌。\r\n于苦难之上稍稍推波助澜,为所谓的「希望」发纵巧说,\r\n那柔弱如蝼蚁、愚昧如枯木的凡人少女便对他奉令承教。\r\n毕竟,他曾指引她穿过凶险的夜域,望向那万古的迷烟,\r\n尽管以她的稚拙,面对那缥缈的烟,应当也见不到一物。\r\n接下来,只需轻轻一推,便能让可笑的幻梦土崩瓦解吧…\r\n\r\n正如称贤者所预想的那般,原本对群龙俯首听命的少女,\r\n竟以芦笛与歌声,指引他未曾见过的异乡人穿过了烟壁,\r\n又按照他完美的规划,将她沉默的侍仆丁加送出了深谷。\r\n接下来,征服与杀戮的火便会被引向这与世隔绝之地吧…\r\n\r\n直至许多年后,英杰马古汉将蛇王的金刃刺入旧主心脏,\r\n自以为掌控人心的贤者方才惊觉,背叛的火种早已种下,\r\n只是那背叛并非如他想象的那般,指向沉溺梦中的群龙,\r\n而是伴着那新诞生的大灵的歌声,在夜域至深的殿堂中,\r\n于接下来的千年,将名为「米克特兰」的部族之础锚定。\r\n不可见的七重帷幔在迷烟中封锁了旧日无序的失光之地,\r\n自夜风与冷阳中,蝼蚁窃取了称贤者亦未能妄染的秘仪。\r\n\r\n「勿将希望俱托于夜。不可依恃诸圣的仁慈,更不可轻信那称贤者的诱言」\r\n「纵然会有懦怯之色,纵然常染丑陋与恶慝,人能指靠的依然只有人自身」\r\n「然而凡人终究脆弱,即便一切如我所规划,我也只能维持边界稳固百年」\r\n「为此——你要述说。你要让诸族之民述说,述说那些英武有名的尊荣者」\r\n「要将『记忆』述说,纺过去于绵延的织卷,定础明日被称作纳塔的家园」\r\n「将这造像带在身边,我最忠诚的侍仆丁加,追随初升的晨曦踏上旅途吧」\r\n「我会永远注视着你,只属于我一人的英雄,我会如丝弦萦系在你的肩畔」\r\n「直至你我的灵魂在幽邃的安宁中永世交缠,即使死亡也无法将我们分离」"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 14518,
|
||||
"name": "寝正月初晴",
|
||||
"description": "由澄澈的紫玉锻造而成的铃灯,据说置于枕边便能唤来幸福的美梦。",
|
||||
"star": 5,
|
||||
"weapon": "法器",
|
||||
"materials": [
|
||||
{ "id": 114032, "name": "鸣神御灵的勇武", "star": 5 },
|
||||
{ "id": 112112, "name": "聚燃的游像眼", "star": 4 },
|
||||
{ "id": 112055, "name": "浮游晶化核", "star": 3 }
|
||||
],
|
||||
"affix": {
|
||||
"Name": "一汤二鹰三鸣神",
|
||||
"Descriptions": [
|
||||
{
|
||||
"Level": 0,
|
||||
"Description": "触发扩散反应后的6秒内,元素精通提升<color=#99FFFFFF>120</color>点;元素战技命中敌人后的9秒内,元素精通提升<color=#99FFFFFF>96</color>点;元素爆发命中敌人后的30秒内,元素精通提升<color=#99FFFFFF>32</color>点。"
|
||||
},
|
||||
{
|
||||
"Level": 1,
|
||||
"Description": "触发扩散反应后的6秒内,元素精通提升<color=#99FFFFFF>150</color>点;元素战技命中敌人后的9秒内,元素精通提升<color=#99FFFFFF>120</color>点;元素爆发命中敌人后的30秒内,元素精通提升<color=#99FFFFFF>40</color>点。"
|
||||
},
|
||||
{
|
||||
"Level": 2,
|
||||
"Description": "触发扩散反应后的6秒内,元素精通提升<color=#99FFFFFF>180</color>点;元素战技命中敌人后的9秒内,元素精通提升<color=#99FFFFFF>144</color>点;元素爆发命中敌人后的30秒内,元素精通提升<color=#99FFFFFF>48</color>点。"
|
||||
},
|
||||
{
|
||||
"Level": 3,
|
||||
"Description": "触发扩散反应后的6秒内,元素精通提升<color=#99FFFFFF>210</color>点;元素战技命中敌人后的9秒内,元素精通提升<color=#99FFFFFF>168</color>点;元素爆发命中敌人后的30秒内,元素精通提升<color=#99FFFFFF>56</color>点。"
|
||||
},
|
||||
{
|
||||
"Level": 4,
|
||||
"Description": "触发扩散反应后的6秒内,元素精通提升<color=#99FFFFFF>240</color>点;元素战技命中敌人后的9秒内,元素精通提升<color=#99FFFFFF>192</color>点;元素爆发命中敌人后的30秒内,元素精通提升<color=#99FFFFFF>64</color>点。"
|
||||
}
|
||||
]
|
||||
},
|
||||
"story": [
|
||||
"\r\n「因为在梦中见到了钱汤,错认为已经抵达了集合地点,所以起得稍晚了一些。」\r\n睡眼惺忪的少女以惯例的冷漠掩盖自己的羞愧,向同行的友人解释迟到的缘由,\r\n不愿坦率承认自己只是在新年的第一天睡过头,将责任推诿于梦中温暖的钱汤。\r\n\r\n「常言昼想夜梦,没想到平日如木石般的巫女小姐,居然这么期待这次的休假。」\r\n「哎呀,可惜呐,可惜,高岭大哥没空来,只有小生我和长正能陪你…疼疼疼!」\r\n「真是的,分明做了别人羡慕都羡慕不来的吉梦,别总板着脸,笑一笑也好嘛。」\r\n\r\n浮浪轻薄的少年半是戏谑半是认真地说着,却又被清籁的少女狠狠瞪了一眼。\r\n少年如求援般地将视线投向鬼人的养子,而刚直的学徒只是默默移开了视线。\r\n\r\n日后被尊为阴阳术开祖的少年所说并非戏言,稻妻确有如此风习,\r\n所谓「一汤二鹰三鸣神」,新年初梦所见的景象,常被认作吉兆,\r\n钱汤寓意着祛病延年,鹰寓意着高步云衢,鸣神则寓意心想事成。\r\n\r\n只是自那时起,巫女的梦中便再也没有出现过钱汤之景,\r\n而那无忧无虑的嬉闹岁月,那如同响铃一般的欢声笑语,\r\n终如钱汤弥漫的温存水雾,悄然消散在无数冰冷的梦中。\r\n\r\n……\r\n\r\n「这次与你赌上一把,如何?嗯——就以这把弓为赌注吧」\r\n「我要将这把天下最好的弓为赌注,赌我能活着回到这里」\r\n\r\n男人如此戏笑道,语气依然如当年那般轻佻,全然听不出半点威重之色。\r\n嗜赌如命的呆瓜,巫女想,分明已经是高名的剑豪,却还是像这般幼稚。\r\n然而——无妨,无妨。正如初梦所预示的那般,正如高岭上的鹰隼那般,\r\n矜夸于百战炼磨的武者,也一定能凭着她梦中所见的吉兆,避灾转福吧…\r\n\r\n只是自那时起,巫女的梦中便再也没有出现过振翼的鹰,\r\n唯有飘落的鹰羽,而鹰却早已失坠,再也飞不进她的梦。\r\n\r\n……\r\n\r\n「初梦?哈!巫女阿姨不会还相信那种无趣的东西吧?」\r\n「什么吉兆凶兆,说到底不都是编出来骗小孩的谎话!」\r\n\r\n也许正如曾经的友人所说,夜中之梦终究是昼日所忧。\r\n直至梦中鸣神的旗帜如连绵不绝的雷光浮于海的彼侧,\r\n巫女方才哑然失笑,讥嘲预兆与已然不知去处的前路。\r\n\r\n抱歉了,师傅,将您所传授的技艺如这般滥用,\r\n与您所效忠的旗帜为敌,以恶名玷染您的清正。\r\n但那也早已是无关紧要之事。\r\n不知我心者,尽可任意评说,\r\n我既不惜此身,亦不惜此名,\r\n只要这一次,能让他活下去…\r\n\r\n……\r\n\r\n「好好好,是小生我不该随便开玩笑,行了吧?真是的,长正你也说两句嘛!」\r\n「难得休假来一次钱汤,我们的巫女小姐该不会打算站在原地发呆到关门吧?」\r\n\r\n恍惚着回过神来,慧黠的少年依旧在插科打诨,戏谑的笑意如往常般恼人。\r\n也许浮沉终究不过是钱汤一梦,而所谓的醒转,亦不过是初晴慵暖的一眠。"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 15101,
|
||||
"name": "猎弓",
|
||||
|
||||
@@ -3569,7 +3569,7 @@
|
||||
"description": "掌握「火」的元素力。",
|
||||
"reward": 5,
|
||||
"version": "5.3",
|
||||
"trigger": { "type": "Unknown" }
|
||||
"trigger": { "type": "ELEMENT_TYPE_CHANGE" }
|
||||
},
|
||||
{
|
||||
"id": 80365,
|
||||
@@ -3579,7 +3579,7 @@
|
||||
"description": "集齐全套《灵濛山夜话》。",
|
||||
"reward": 5,
|
||||
"version": "5.3",
|
||||
"trigger": { "type": "Unknown" }
|
||||
"trigger": { "type": "COLLECT_SET_OF_READINGS" }
|
||||
},
|
||||
{
|
||||
"id": 80366,
|
||||
@@ -3589,7 +3589,7 @@
|
||||
"description": "集齐全套《哈南帕查记事》。",
|
||||
"reward": 5,
|
||||
"version": "5.3",
|
||||
"trigger": { "type": "Unknown" }
|
||||
"trigger": { "type": "COLLECT_SET_OF_READINGS" }
|
||||
},
|
||||
{
|
||||
"id": 80367,
|
||||
@@ -3599,17 +3599,17 @@
|
||||
"description": "集齐全套《隐玉之泉》。",
|
||||
"reward": 5,
|
||||
"version": "5.3",
|
||||
"trigger": { "type": "Unknown" }
|
||||
"trigger": { "type": "COLLECT_SET_OF_READINGS" }
|
||||
},
|
||||
{
|
||||
"id": 80368,
|
||||
"series": 57,
|
||||
"order": 342,
|
||||
"name": "温泉诞生之日",
|
||||
"description": "集齐全套《玛阿威和幻写灵》。",
|
||||
"description": "集齐全套《玛阿威与幻写灵》。",
|
||||
"reward": 5,
|
||||
"version": "5.3",
|
||||
"trigger": { "type": "Unknown" }
|
||||
"trigger": { "type": "COLLECT_SET_OF_READINGS" }
|
||||
},
|
||||
{
|
||||
"id": 80369,
|
||||
@@ -3619,7 +3619,7 @@
|
||||
"description": "集齐全套《火山大王与缝影针》。",
|
||||
"reward": 5,
|
||||
"version": "5.3",
|
||||
"trigger": { "type": "Unknown" }
|
||||
"trigger": { "type": "COLLECT_SET_OF_READINGS" }
|
||||
},
|
||||
{
|
||||
"id": 80370,
|
||||
@@ -3629,7 +3629,7 @@
|
||||
"description": "集齐全套《秋暮之火》。",
|
||||
"reward": 5,
|
||||
"version": "5.3",
|
||||
"trigger": { "type": "Unknown" }
|
||||
"trigger": { "type": "COLLECT_SET_OF_READINGS" }
|
||||
},
|
||||
{
|
||||
"id": 80371,
|
||||
@@ -3639,7 +3639,7 @@
|
||||
"description": "获得「千音雅集」,成为自由的音乐人。",
|
||||
"reward": 5,
|
||||
"version": "5.3",
|
||||
"trigger": { "type": "Unknown" }
|
||||
"trigger": { "type": "OBTAIN_ITEM_NUM" }
|
||||
},
|
||||
{
|
||||
"id": 80372,
|
||||
@@ -3649,7 +3649,7 @@
|
||||
"description": "完成所有「千音雅集」的「入门练习」。",
|
||||
"reward": 5,
|
||||
"version": "5.3",
|
||||
"trigger": { "type": "Unknown" }
|
||||
"trigger": { "type": "MUSIC_GAME_BOOK_FINISH_BEATMAP" }
|
||||
},
|
||||
{
|
||||
"id": 80373,
|
||||
@@ -3659,7 +3659,7 @@
|
||||
"description": "在「千音藏品」中兑换1个谱面主题。",
|
||||
"reward": 5,
|
||||
"version": "5.3",
|
||||
"trigger": { "type": "Unknown" }
|
||||
"trigger": { "type": "BUY_SHOP_GOODS_COUNT" }
|
||||
},
|
||||
{
|
||||
"id": 80374,
|
||||
@@ -3669,7 +3669,7 @@
|
||||
"description": "在「千音藏品」中兑换3个谱面主题。",
|
||||
"reward": 10,
|
||||
"version": "5.3",
|
||||
"trigger": { "type": "Unknown" }
|
||||
"trigger": { "type": "BUY_SHOP_GOODS_COUNT" }
|
||||
},
|
||||
{
|
||||
"id": 80375,
|
||||
@@ -3679,7 +3679,7 @@
|
||||
"description": "在「千音藏品」中兑换5个谱面主题。",
|
||||
"reward": 20,
|
||||
"version": "5.3",
|
||||
"trigger": { "type": "Unknown" }
|
||||
"trigger": { "type": "BUY_SHOP_GOODS_COUNT" }
|
||||
},
|
||||
{
|
||||
"id": 80376,
|
||||
@@ -3689,7 +3689,7 @@
|
||||
"description": "在官方曲谱的演奏挑战中,获得5次不同曲谱的「高遏行云」评价。",
|
||||
"reward": 5,
|
||||
"version": "5.3",
|
||||
"trigger": { "type": "Unknown" }
|
||||
"trigger": { "type": "MUSIC_GAME_BOOK_FINISH_OFFICIAL_REACH_RATE" }
|
||||
},
|
||||
{
|
||||
"id": 80377,
|
||||
@@ -3699,7 +3699,7 @@
|
||||
"description": "在官方曲谱的演奏挑战中,获得15次不同曲谱的「高遏行云」评价。",
|
||||
"reward": 10,
|
||||
"version": "5.3",
|
||||
"trigger": { "type": "Unknown" }
|
||||
"trigger": { "type": "MUSIC_GAME_BOOK_FINISH_OFFICIAL_REACH_RATE" }
|
||||
},
|
||||
{
|
||||
"id": 80378,
|
||||
@@ -3709,7 +3709,7 @@
|
||||
"description": "在官方曲谱的演奏挑战中,获得30次不同曲谱的「高遏行云」评价。",
|
||||
"reward": 20,
|
||||
"version": "5.3",
|
||||
"trigger": { "type": "Unknown" }
|
||||
"trigger": { "type": "MUSIC_GAME_BOOK_FINISH_OFFICIAL_REACH_RATE" }
|
||||
},
|
||||
{
|
||||
"id": 80379,
|
||||
@@ -3719,7 +3719,7 @@
|
||||
"description": "演奏其他玩家创作的曲谱时,获得5次不同曲谱的「高遏行云」评价。",
|
||||
"reward": 5,
|
||||
"version": "5.3",
|
||||
"trigger": { "type": "Unknown" }
|
||||
"trigger": { "type": "MUSIC_GAME_BOOK_FINISH_UGC_REACH_RATE" }
|
||||
},
|
||||
{
|
||||
"id": 80380,
|
||||
@@ -3729,7 +3729,7 @@
|
||||
"description": "演奏其他玩家创作的曲谱时,获得10次不同曲谱的「高遏行云」评价。",
|
||||
"reward": 10,
|
||||
"version": "5.3",
|
||||
"trigger": { "type": "Unknown" }
|
||||
"trigger": { "type": "MUSIC_GAME_BOOK_FINISH_UGC_REACH_RATE" }
|
||||
},
|
||||
{
|
||||
"id": 80381,
|
||||
@@ -3739,7 +3739,7 @@
|
||||
"description": "演奏其他玩家创作的曲谱时,获得20次不同曲谱的「高遏行云」评价。",
|
||||
"reward": 20,
|
||||
"version": "5.3",
|
||||
"trigger": { "type": "Unknown" }
|
||||
"trigger": { "type": "MUSIC_GAME_BOOK_FINISH_UGC_REACH_RATE" }
|
||||
},
|
||||
{
|
||||
"id": 81000,
|
||||
@@ -11792,7 +11792,7 @@
|
||||
"description": "在一次挑战中,破坏过两次金焰绒翼龙暴君发射出的「炽风翎羽」。",
|
||||
"reward": 5,
|
||||
"version": "5.3",
|
||||
"trigger": { "type": "Unknown" }
|
||||
"trigger": { "type": "COMBAT_CONFIG_COMMON" }
|
||||
},
|
||||
{
|
||||
"id": 82273,
|
||||
@@ -11802,7 +11802,7 @@
|
||||
"description": "在一次挑战中,利用火榴果的爆炸对贪食匿叶龙山王触发融化反应。",
|
||||
"reward": 5,
|
||||
"version": "5.3",
|
||||
"trigger": { "type": "Unknown" }
|
||||
"trigger": { "type": "COMBAT_CONFIG_COMMON" }
|
||||
},
|
||||
{
|
||||
"id": 82274,
|
||||
@@ -11812,7 +11812,7 @@
|
||||
"description": "利用火榴果的爆炸击败贪食匿叶龙山王。",
|
||||
"reward": 5,
|
||||
"version": "5.3",
|
||||
"trigger": { "type": "Unknown" }
|
||||
"trigger": { "type": "COMBAT_CONFIG_COMMON" }
|
||||
},
|
||||
{
|
||||
"id": 82275,
|
||||
@@ -11822,7 +11822,7 @@
|
||||
"description": "在秘源机兵·构型械处于瘫痪状态时,将其击败。",
|
||||
"reward": 5,
|
||||
"version": "5.3",
|
||||
"trigger": { "type": "Unknown" }
|
||||
"trigger": { "type": "COMBAT_CONFIG_COMMON" }
|
||||
},
|
||||
{
|
||||
"id": 82276,
|
||||
@@ -11832,7 +11832,7 @@
|
||||
"description": "分别在深邃摹结株复现古岩龙蜥、翠翎恐蕈以及千年珍珠骏麟的形象时,将其击败。",
|
||||
"reward": 5,
|
||||
"version": "5.3",
|
||||
"trigger": { "type": "Unknown" }
|
||||
"trigger": { "type": "COMBAT_MULTICOND_CONFIG_COMMON" }
|
||||
},
|
||||
{
|
||||
"id": 82277,
|
||||
@@ -11842,7 +11842,7 @@
|
||||
"description": "在一次挑战中,累计破坏过灵觉隐修的迷者制造出的8个浮彩分身。",
|
||||
"reward": 5,
|
||||
"version": "5.3",
|
||||
"trigger": { "type": "Unknown" }
|
||||
"trigger": { "type": "COMBAT_CONFIG_COMMON" }
|
||||
},
|
||||
{
|
||||
"id": 82278,
|
||||
@@ -11852,7 +11852,7 @@
|
||||
"description": "在战场被破坏至最小时,击败蚀灭的源焰之主。",
|
||||
"reward": 10,
|
||||
"version": "5.3",
|
||||
"trigger": { "type": "Unknown" }
|
||||
"trigger": { "type": "COMBAT_CONFIG_COMMON" }
|
||||
},
|
||||
{
|
||||
"id": 84000,
|
||||
@@ -14201,7 +14201,10 @@
|
||||
"description": "隐藏在梦境中的,是过去与未来的回音。",
|
||||
"reward": 5,
|
||||
"version": "5.3",
|
||||
"trigger": { "type": "Unknown" }
|
||||
"trigger": {
|
||||
"type": "FINISH_QUEST_AND",
|
||||
"task": [{ "questId": 5022, "name": "地中残景", "type": "魔神任务" }]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 84338,
|
||||
@@ -14211,7 +14214,10 @@
|
||||
"description": "还有许多要与「同伴」一起经历。",
|
||||
"reward": 5,
|
||||
"version": "5.3",
|
||||
"trigger": { "type": "Unknown" }
|
||||
"trigger": {
|
||||
"type": "FINISH_QUEST_AND",
|
||||
"task": [{ "questId": 5023, "name": "正如日出日落", "type": "魔神任务" }]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 84339,
|
||||
@@ -14221,7 +14227,10 @@
|
||||
"description": "在长夜的尽头,终现名为「希望」的曙光。",
|
||||
"reward": 5,
|
||||
"version": "5.3",
|
||||
"trigger": { "type": "Unknown" }
|
||||
"trigger": {
|
||||
"type": "FINISH_QUEST_AND",
|
||||
"task": [{ "questId": 5024, "name": "星与火的征途", "type": "魔神任务" }]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 84340,
|
||||
@@ -14231,7 +14240,10 @@
|
||||
"description": "为纳塔夺取最终的胜利。",
|
||||
"reward": 5,
|
||||
"version": "5.3",
|
||||
"trigger": { "type": "Unknown" }
|
||||
"trigger": {
|
||||
"type": "FINISH_QUEST_AND",
|
||||
"task": [{ "questId": 5029, "name": "当一切镌刻成碑", "type": "魔神任务" }]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 84341,
|
||||
@@ -14241,7 +14253,10 @@
|
||||
"description": "完成「炽烈的还魂诗」。",
|
||||
"reward": 10,
|
||||
"version": "5.3",
|
||||
"trigger": { "type": "Unknown" }
|
||||
"trigger": {
|
||||
"type": "FINISH_QUEST_AND",
|
||||
"task": [{ "questId": 5029, "name": "当一切镌刻成碑", "type": "魔神任务" }]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 84501,
|
||||
|
||||
@@ -767,6 +767,22 @@
|
||||
],
|
||||
"source": { "index": 2, "area": "璃月", "name": "焚尽之环" }
|
||||
},
|
||||
{
|
||||
"id": 10000109,
|
||||
"contentId": 504440,
|
||||
"dropDays": [1, 4, 7],
|
||||
"name": "梦见月瑞希",
|
||||
"itemType": "character",
|
||||
"star": 5,
|
||||
"weapon": "法器",
|
||||
"element": "风",
|
||||
"materials": [
|
||||
{ "id": 104320, "name": "「浮世」的教导", "star": 2 },
|
||||
{ "id": 104321, "name": "「浮世」的指引", "star": 3 },
|
||||
{ "id": 104322, "name": "「浮世」的哲学", "star": 4 }
|
||||
],
|
||||
"source": { "index": 3, "area": "稻妻", "name": "菫染之国" }
|
||||
},
|
||||
{
|
||||
"id": 10000075,
|
||||
"contentId": 5494,
|
||||
@@ -1409,7 +1425,7 @@
|
||||
},
|
||||
{
|
||||
"id": 10000108,
|
||||
"contentId": 0,
|
||||
"contentId": 503614,
|
||||
"dropDays": [2, 5, 7],
|
||||
"name": "蓝砚",
|
||||
"itemType": "character",
|
||||
@@ -1825,7 +1841,7 @@
|
||||
},
|
||||
{
|
||||
"id": 12514,
|
||||
"contentId": 0,
|
||||
"contentId": 503949,
|
||||
"dropDays": [1, 4, 7],
|
||||
"name": "焚曜千阳",
|
||||
"itemType": "weapon",
|
||||
@@ -2111,6 +2127,22 @@
|
||||
],
|
||||
"source": { "index": 3, "area": "稻妻", "name": "流沙之葬" }
|
||||
},
|
||||
{
|
||||
"id": 14518,
|
||||
"contentId": 504503,
|
||||
"dropDays": [2, 5, 7],
|
||||
"name": "寝正月初晴",
|
||||
"itemType": "weapon",
|
||||
"star": 5,
|
||||
"weapon": "法器",
|
||||
"materials": [
|
||||
{ "id": 114029, "name": "鸣神御灵的明惠", "star": 2 },
|
||||
{ "id": 114030, "name": "鸣神御灵的欢喜", "star": 3 },
|
||||
{ "id": 114031, "name": "鸣神御灵的亲爱", "star": 4 },
|
||||
{ "id": 114032, "name": "鸣神御灵的勇武", "star": 5 }
|
||||
],
|
||||
"source": { "index": 3, "area": "稻妻", "name": "砂之祭场" }
|
||||
},
|
||||
{
|
||||
"id": 14511,
|
||||
"contentId": 5110,
|
||||
@@ -2193,7 +2225,7 @@
|
||||
},
|
||||
{
|
||||
"id": 14517,
|
||||
"contentId": 0,
|
||||
"contentId": 503948,
|
||||
"dropDays": [2, 5, 7],
|
||||
"name": "祭星者之望",
|
||||
"itemType": "weapon",
|
||||
@@ -4095,6 +4127,22 @@
|
||||
],
|
||||
"source": { "index": 3, "area": "稻妻", "name": "流沙之葬" }
|
||||
},
|
||||
{
|
||||
"id": 13432,
|
||||
"contentId": 504502,
|
||||
"dropDays": [3, 6, 7],
|
||||
"name": "且住亭御咄",
|
||||
"itemType": "weapon",
|
||||
"star": 4,
|
||||
"weapon": "长柄武器",
|
||||
"materials": [
|
||||
{ "id": 114033, "name": "今昔剧画之恶尉", "star": 2 },
|
||||
{ "id": 114034, "name": "今昔剧画之虎啮", "star": 3 },
|
||||
{ "id": 114035, "name": "今昔剧画之一角", "star": 4 },
|
||||
{ "id": 114036, "name": "今昔剧画之鬼人", "star": 5 }
|
||||
],
|
||||
"source": { "index": 3, "area": "稻妻", "name": "流沙之葬" }
|
||||
},
|
||||
{
|
||||
"id": 13417,
|
||||
"contentId": 4443,
|
||||
|
||||
@@ -1,4 +1,16 @@
|
||||
[
|
||||
{
|
||||
"id": 10000109,
|
||||
"contentId": 504440,
|
||||
"name": "梦见月瑞希",
|
||||
"title": "绮梦缱绻",
|
||||
"area": "稻妻",
|
||||
"birthday": [3, 16],
|
||||
"star": 5,
|
||||
"element": "风",
|
||||
"weapon": "法器",
|
||||
"nameCard": "梦见月瑞希·噩喰"
|
||||
},
|
||||
{
|
||||
"id": 10000107,
|
||||
"contentId": 503612,
|
||||
|
||||
@@ -2454,6 +2454,18 @@
|
||||
"up5List": [10000098],
|
||||
"up4List": [10000108, 10000090, 10000045]
|
||||
},
|
||||
{
|
||||
"name": "神铸赋形",
|
||||
"version": "5.3",
|
||||
"order": 2,
|
||||
"banner": "https://sdk.hoyoverse.com/upload/ann/2024/12/19/a681299b38de36db44b1f50976a2eb93_7058438638362067935.png",
|
||||
"from": "2025-01-21T18:00:00+08:00",
|
||||
"to": "2025-02-11T14:59:00+08:00",
|
||||
"type": 302,
|
||||
"postId": "60604171",
|
||||
"up5List": [13512, 11515],
|
||||
"up4List": [13406, 11405, 12405, 14402, 15403]
|
||||
},
|
||||
{
|
||||
"name": "玉岩之忆",
|
||||
"version": "5.3",
|
||||
@@ -2472,5 +2484,77 @@
|
||||
10000023, 11405, 11403, 11402, 11401, 12410, 12405, 12403, 12402, 12401, 13407, 13406, 13401,
|
||||
14409, 14403, 14402, 14401, 15405, 15403, 15402, 15401
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "浮枕朝颜",
|
||||
"version": "5.4",
|
||||
"order": 1,
|
||||
"banner": "https://sdk.hoyoverse.com/upload/ann/2025/01/21/3767b19394d8107dd3b22518ad4383b9_5665607688511263762.jpg",
|
||||
"from": "2025-02-12T06:00:00+08:00",
|
||||
"to": "2025-03-04T17:59:00+08:00",
|
||||
"type": 301,
|
||||
"postId": "61893151",
|
||||
"up5List": [10000109],
|
||||
"up4List": [10000055, 10000053, 10000023]
|
||||
},
|
||||
{
|
||||
"name": "柔柔海露心",
|
||||
"version": "5.4",
|
||||
"order": 1,
|
||||
"banner": "https://sdk.hoyoverse.com/upload/ann/2025/01/21/b19aab83e10ab0ec2012ad0db2857f98_3011528135086310178.jpg",
|
||||
"from": "2025-02-12T06:00:00+08:00",
|
||||
"to": "2025-03-04T17:59:00+08:00",
|
||||
"type": 400,
|
||||
"postId": "61893153",
|
||||
"up5List": [10000095],
|
||||
"up4List": [10000055, 10000053, 10000023]
|
||||
},
|
||||
{
|
||||
"name": "神铸赋形",
|
||||
"version": "5.4",
|
||||
"order": 1,
|
||||
"banner": "https://sdk.hoyoverse.com/upload/ann/2025/01/21/2fbdd28e5da3828bcefb134efdbd0308_7635320279968503743.jpg",
|
||||
"from": "2025-02-12T06:00:00+08:00",
|
||||
"to": "2025-03-04T17:59:00+08:00",
|
||||
"type": 302,
|
||||
"postId": "61893154",
|
||||
"up5List": [14518, 15513],
|
||||
"up4List": [12416, 13416, 15416, 11402, 14409]
|
||||
},
|
||||
{
|
||||
"name": "众水的颂诗",
|
||||
"version": "5.4",
|
||||
"order": 2,
|
||||
"banner": "https://sdk.hoyoverse.com/upload/ann/2025/02/17/16502c6ed976ad895e0e36db251af49b_5339316421173554000.jpg",
|
||||
"from": "2025-03-04T18:00:00+08:00",
|
||||
"to": "2025-03-25T14:59:00+08:00",
|
||||
"type": 301,
|
||||
"postId": "62298070",
|
||||
"up5List": [10000089],
|
||||
"up4List": [10000088, 10000036, 10000080]
|
||||
},
|
||||
{
|
||||
"name": "劫中泛滥",
|
||||
"version": "5.4",
|
||||
"order": 2,
|
||||
"banner": "https://sdk.hoyoverse.com/upload/ann/2025/02/17/1b6cf538066209d3aa510291d351f7cb_20450832996386688.jpg",
|
||||
"from": "2025-03-04T18:00:00+08:00",
|
||||
"to": "2025-03-25T14:59:00+08:00",
|
||||
"type": 400,
|
||||
"postId": "62298071",
|
||||
"up5List": [10000086],
|
||||
"up4List": [10000088, 10000036, 10000080]
|
||||
},
|
||||
{
|
||||
"name": "神铸赋形",
|
||||
"version": "5.4",
|
||||
"order": 2,
|
||||
"banner": "https://sdk.hoyoverse.com/upload/ann/2025/02/17/f517f95eb862d8196bedcb9e44db3b5b_2023560355910093809.jpg",
|
||||
"from": "2025-03-04T18:00:00+08:00",
|
||||
"to": "2025-03-25T14:59:00+08:00",
|
||||
"type": 302,
|
||||
"postId": "62298072",
|
||||
"up5List": [11513, 14513],
|
||||
"up4List": [11401, 12403, 13401, 14403, 15405]
|
||||
}
|
||||
]
|
||||
|
||||