feat(system): ✨ 增加分布式兼容和语音视频通话、移动端部分兼容 (#311)
* fix(config): 🐛 修复ios因Cargo.toml中系统限制条件排序问题导致无法启动 * feat(common): ✨ tauri 登录命令 存储 token * feat(common): ✨ tauri 存储 room 信息 * feat(common): ✨ sqlite 存储房间信息,群成员信息 * feat(common): ✨ 修改我的群的信息 * feat(common): ✨ 游标分页查询群组成员 * style(login): 💄 完善登录页面和图标 * feat(common): ✨ 查询全部群成员;优化前端显示逻辑 * feat(common): ✨ 更新 gitignore * feat(common): ✨ 使用缓存检测是否强制更新本地数据,或采取静默更新 * fix(hook): 🐛 枚举使用错误修复 * fix(Android): 🐛 修改Android中的安全距离和启动页面 * fix(style): 🐛 修改pc登录按钮的样式 修复计时器worker计时问题 修改一些样式 移除修改ip地址的测试功能 修复刷新接口时候判断的群聊问题 * feat(system): ✨ 增加获取系统盘的信息和文件磁盘占用情况功能 优化一些重要提示的样式 * feat(common): ✨ sqlite 存储会话 * feat(common): ✨ sqlite 存储聊天信息 * fix(common): 🐛 sqlite需要根据登录的用户 id 进行数据隔离 * fix(mac): 🐛 修复mac上点击系统托盘图标和程序坞图标不展示主窗口的问题 * fix(windows): 🐛 修复win上右键任务栏图标关闭应用后无法再打开主窗口的问题 closed #IBQB1H * fix(common): 🐛 添加 sqlite数据库迁移代码 * fix(view): 🐛 会话接口新增detailId;sqlite 数据结构变更;登录保存用户 id bug 修复; * feat(util): ✨ 增强录音音频响度 * feat(common): ✨ sqlite 存储消息 * fix(common): 🐛 sqlite 存储消息体异常 * feat(setting): ✨ 增加应用占用磁盘空间计算功能和可视化 * fix(hook): 🐛 修复音频文件命名不一致问题 * feat(common): ✨ 添加 tauri 日志插件 * feat(common): ✨ rust 层发送消息 * feat(view): ✨ 新增自动下载音频功能,优先播放本地音频,修复音频频谱波形异常问题 * fix(component): 🐛 群成员监听显示问题;tauri 事件监听响应多次问题;消息列表显示顺序问题; * fix(view): 🐛 修复发送语音后无法播放本地音频问题 * fix(common): 🐛 im_message 表关闭 nickname 非空限制 * fix(common): 🐛 设置账号第一次在客户端登录,设置is_init 为 true,进行初始化获取近期所有消息 * fix(common): 🐛 配置 tauri 的环境变量,用于 migration 启动 * fix(common): 🐛 登录之后,聊天页面初始化,未显示聊天记录 bug * feat(system): ✨ 合并master * style(common): 💄 引入 tauri websocket; 格式化 rust 代码; * fix(mac): 🐛 修复mac语音播放问题 增加机器人样式和类型 * fix(common): 🐛 ws 接收消息存储本地 * fix(common): 🐛 rust 报错没有在前端提示问题修复 * fix(common): 🐛 修复登录页面请求接口 bug,以及首屏骨架屏问题; * build(system): 📦 移除一些依赖,更新图标 * fix(view): 🐛 修复系统托盘在自动登录时不显示退出问题 优化在其他不需要显示window.$message提示的窗口可禁用 * perf(voice): ⚡ 优化录音组件的样式 * fix(store): 🐛 修复安卓无法获取安全区域问题 * fix(common): 🐛 token 更新bug修复 * feat(mobile): ✨ 新增和优化消息页面布局 * feat(common): ✨ 离线消息同步 * build(system): 📦 修改项目一些样式和图标 修复判断安卓的方法异步问题导致mac release版本页面不加载问题 * build(icon): 📦 更新除了mac系统的图标 * fix(common): 🐛 将数据库迁移 crate 集成到主进程中 * style(common): 💄 修改 tauri 日志配置,输出日志到 logs 目录下;并对日志级别添加颜色; * feat(mobile): ✨ 新增联系人页面 * feat(common): ✨ 引入 tauri-devtools * feat(mobile): ✨ 新增点击加号图标的小弹窗页面 * docs(common): 📝 env文件修改 * fix(router): 🐛 补充提交路由文件,前一次提交缺少更新的路由文件 * fix(common): 🐛 rust 依赖调整;配置调整; * build(config): 📦 修改配置 * fix(common): 🐛 rust .env 文件读取问题修复 * fix(layout): 🐛 修复主页布局漏洞 * build(system): 📦 拉取master的内容 * refactor(view): ♻️ 对接登录参数 * fix(common): 🐛 在线消息保存修复; * fix(common): 🐛 sqlite 保存消息 mark * fix(common): 🐛 消息标记同步问题 * feat(mobile): ✨ 新增通讯录页面内容 * fix(common): 🐛 项目启动之后,还在登录页面时,还会请求房间消息数据等 * fix(common): 🐛 windows启动造成 panic: 去掉 main 的运行时 * fix(common): 🐛 清除缓存,程序卡死 * fix(config): 🐛 更改sqlite configuration配置 修复windows启动控制台打印报错问题 * fix(common): 🐛 修复清除缓存,系统崩溃问题; * fix(common): 🐛 群成员角色判定 bug 修复 * fix(common): 🐛 修复群成员搜索 bug * fix(rust): 🐛 修复字段类型的字节数量 * feat(mobile): ✨ 联系人页面中移植客户端的好友组件 * fix(common): 🐛 修复动态窗口,邮件窗口,AI 插件窗口关闭 bug * fix(common): 🐛 修复会话列表最新消息显示问题 * fix(common): 🐛 左侧功能窗口打开之后,鼠标划上显示问题 * perf(system): ⚡ 适配cloud * perf(centext): ⚡ 优化切换会话时候卡顿问题 修复data.list[0]报错问题 * fix(common): 🐛 重构 Tauri事件的监听器释放逻辑; * refactor(common): ♻️ 重构 Tauri 的事件监听相关代码;增加日志记录; * feat(util): ✨ 新增DOM计算函数,完善社区页面和功能 * refactor(common): ♻️ 重构 useTauriListener * fix(common): 🐛 监听 home 窗口关闭的时候,把 home 窗口隐藏 * perf(ws): ⚡ 移除ws重连次数限制 * fix(common): 🐛 ios 窗口关闭弹窗 bug;修改群屏蔽状态导致消息错乱 bug; * feat(util): ✨ 新增小屏安全区域页面适配,优化多次监听resize导致的性能问题 * fix(common): 🐛 初始化消息发送时的消息状态为发送中 * fix(ios): 🐛 修复rust依赖问题导致ios启动失败 * chore(format): 🔨 使用biome替换eslint * perf(rust): ⚡ 添加超时机制和错误处理优化 优化数据库连接池配置,调整连接参数和日志级别 新增全局超时配置模块 改进 IM 客户端锁机制,避免跨 await 持有锁 增强命令函数错误处理,返回 Result 类型 优化托盘图标创建逻辑,添加默认图标检查 重构应用初始化流程,使用异步任务避免阻塞 * fix(scanner): 🐛 修复存储扫描导致程序崩溃(扫描中关闭未解决) * fix(configuration): 🐛 修复release打包后初始化应用数据失败问题 * perf(rust): ⚡ 优化未处理的unwrap() * fix(hide_notify): 🐛 修复hide_notify事件无限循环导致程序崩溃问题 * fix(voice): 🐛 修复输入框切换录音组件后选择表情包导致错位问题 * fix(view): 🐛 windwos notify和tray导致系统卡死 * fix(style): 🐛 修复样式错乱问题 * fix(common): 🐛 windows 接收消息 打开主窗口卡死 * fix(style): 🐛 修改图标样式 * fix(common): 🐛 windows接收群消息卡死 * build(sqlite): 📦 合并sqlite分支代码 * fix(common): 🐛 mac docker 计数 * fix(common): 🐛 添加macos编译;解决rust警告 * fix(common): 🐛 mac badge 计数 * fix(common): 🐛 修复自动登录问题;修复watch 的异步问题导致的数据竞态问题 * fix(common): 🐛 删除会话功能; * build(ios): 📦 增加移动端所需的配置 * fix(common): 🐛 ios 启动 tauri 插件和命令适配 * fix(common): 🐛 查询消息根据 id 排序时,将 id 转为数值进行排序 * refactor(common): ♻️ 使用 tracing 作为日志框架 * fix(unreadCount): 🐛 修复标记重复问题 * style(lint): 💄 优化了biome的配置 按照新的biome配置格式化代码 * style(biome): 💄 完善biome规则配置 * style(biome): 💄 增加自动移除未使用的导入 * feat(mobile): ✨ 新增“我的”页面内容及动画,修复安全边距问题 * fix(common): 🐛 修改AnnouncementBody类型 * fix(common): 🐛 修改 ApiResult 类型 * feat(mobile): ✨ 新增聊天室页面 * fix(ios): 🐛 添加log依赖 * fix(common): 🐛 去掉 home 窗口的重复监听 * fix(common): 🐛 发送消息接口,用channel 代替 event,解决系统卡死; * fix(common): 🐛 android启动问题 * fix(rust): 🐛 修复ios签名问题 修复ios底部栏不显示问题|移除冗余的权限配置 * refactor(common): ♻️ 将 db.sqlite 设置为resource,通过 tauri api 进行读取 * test(common): ✅ 新增视频通话局部代码 * fix(rust): 🐛 修复移动端无法启动并且无法创建对应文件的问题 * test(common): ✅ 优化通话逻辑 * feat(mobile): ✨ 新增客户端对象,修复加载页载入问题 * chore(common): 🔨 修改 tauri 配置文件 * ci(log): 🎡 修改日志打印的级别和语言都为英文 * fix(common): 🐛 notify_cotent事件修改 * feat(common): ✨ 初步实现 webrtc * fix(common): 🐛 发送视频通话请求 * fix(common): 🐛 webrtc实现-待测试 * fix(common): 🐛 webrtc-测试 * style(common): 💄 webrtc 页面 ui调整 * fix(common): 🐛 rtc 页面头像显示 * fix(common): 🐛 rtc 第一次切换摄像头未显示远程 * fix(common): 🐛 webrtc 挂断 * fix(common): 🐛 rtc 通话结束 * fix(common): 🐛 ws监听挂断消息 * fix(common): 🐛 rtc 设备检查 * fix(common): 🐛 检查audiooutput * fix(common): 🐛 检查音量来判断用户是否开启 audio * fix(common): 🐛 检查音量判断声音设备 * fix(agreement): 🐛 前端对接cloud的刷新token * fix(common): 🐛 重构 webrtc * fix(common): 🐛 webrtc 异常 * fix(common): 🐛 rtc 异常 * fix(common): 🐛 rtc candidate * fix(common): 🐛 通知窗口 * fix(common): 🐛 rtc 通话时间显示 * fix(common): 🐛 关闭扬声器功能 * fix(common): 🐛 关闭麦克风 * fix(common): 🐛 win 通知窗口显示问题 * fix(common): 🐛 rtc调整设置通知通知栏的高度 * feat(common): ✨ 新增处理进群审核接口、音视频处理约定逻辑 * fix(common): 🐛 前端刷新 token 之后调用 command 更新 rust 部分的 token * fix(common): 🐛 显示视频通话消息 * fix(common): 🐛 webrtc 语音通话调用 * fix(common): 🐛 查询所有会话 bug * build(build): 📦 升级一些依赖版本 * refactor(common): ♻️ rust 重构ws * style(avatar): 💄 优化头像加载失败时候展示的图片 * fix(common): 🐛 rust ws * fix(common): 🐛 修复群聊状态显示、同步后端打电话逻辑 * fix(common): 🐛 查询群成员报错 异步问题 * fix(common): 🐛 群成员 异步问题 * refactor(common): ♻️ rust 异常处理 * fix(common): 🐛 消息 骨架屏 异常 * fix(common): 🐛 删除无用代码 * fix(common): 🐛 win 图标闪烁问题 * fix(common): 🐛 ws 保活 * feat(ChatFooter): ✨ 增加输入框和ChatFooter组件的拖拽效果 优化私聊在线状态 * fix(common): 🐛 webrtc 切换视频关闭远程视频流 * fix(common): 🐛 message mark issue resolve * fix(common): 🐛 message mark issue resolve * refactor(common): ♻️ delete useless code * fix(common): 🐛 save_room_member_batch cause database lock * fix(common): 🐛 show the system messgage of join group * fix(common): 🐛 message sound * build(img): 📦 压缩一些图片为webp 修改一下代码的逻辑 * perf(global): ⚡ 优化群成员排序、输入框发送事件为form表单的提交事件 优化chatfooter输入框高度拖拽和home窗口拖拽时性能问题 优化home窗口拖拽会持续触发当前会话选中后对应房间已读触发问题 * chore(lint): 🔨 优化lint的配置 * perf(rtcCall): ⚡ 优化通话窗口的样式和关闭窗口会挂断的功能 * fix(common): 🐛 ws reconnect in backend reboot * fix(common): 🐛 webrtc relate message show * fix(common): 🐛 ws delete useless code * fix(common): 🐛 resolve ws multi connection * docs(config): 📝 更新群二维码和赞助榜 * fix(common): 🐛 ws setAppBackGroundState * fix(common): 🐛 env config modify * fix(common): 🐛 webrtc on CANCEL * fix(common): 🐛 group announcement update * fix(common): 🐛 announcement issuce * fix(common): 🐛 webrtc windows dragable * fix(system): 🐛 fix location of call component and some page styles * fix(common): 🐛 webrtc issue * ci(common): 🎡 .env.dev modify * fix(common): 🐛 gET_ROOM_MEMBERS command issue * fix(common): 🐛 update my group info * fix(common): 🐛 webrtc audio call issue * fix(common): 🐛 webrtc video or audio status switch issue * fix(group): 🐛 fixed some logic and restrictions on inviting members into groups Optimize Create Script * style(style): 💄 remove some styles and comments * fix(common): 🐛 fix WebRTC audio cannot be heard * fix(common): 🐛 info import error * fix(common): 🐛 fix #ICT1BO group info update * fix(common): 🐛 fix "不是好友关系" issue * fix(common): 🐛 add group apply list * fix(common): 🐛 webrtc if can't acquire device then hang up * fix(common): 🐛 mute local video ele * fix(common): 🐛 同步最新申请接口 * fix(common): 🐛 change isSpeakerOn and mute the bell * fix(common): 🐛 group apply invite dom * style(style): 💄 change the style of language statistics and incoming call notifications --------- Co-authored-by: ql <254693270@qq.com> Co-authored-by: 卡仔 <1271013637@qq.com> Co-authored-by: 乾乾 <1046762075@qq.com>
@@ -8,4 +8,37 @@ registry = "sparse+https://rsproxy.cn/index/"
|
||||
[registries.rsproxy]
|
||||
index = "https://rsproxy.cn/crates.io-index"
|
||||
[net]
|
||||
git-fetch-with-cli = true
|
||||
git-fetch-with-cli = true
|
||||
|
||||
# Android NDK 链接配置
|
||||
[target.aarch64-linux-android]
|
||||
linker = "aarch64-linux-android-clang"
|
||||
rustflags = [
|
||||
"-C", "link-arg=-lc++_shared",
|
||||
"-C", "link-arg=-llog",
|
||||
"-C", "link-arg=-landroid",
|
||||
]
|
||||
|
||||
[target.armv7-linux-androideabi]
|
||||
linker = "armv7a-linux-androideabi-clang"
|
||||
rustflags = [
|
||||
"-C", "link-arg=-lc++_shared",
|
||||
"-C", "link-arg=-llog",
|
||||
"-C", "link-arg=-landroid",
|
||||
]
|
||||
|
||||
[target.i686-linux-android]
|
||||
linker = "i686-linux-android-clang"
|
||||
rustflags = [
|
||||
"-C", "link-arg=-lc++_shared",
|
||||
"-C", "link-arg=-llog",
|
||||
"-C", "link-arg=-landroid",
|
||||
]
|
||||
|
||||
[target.x86_64-linux-android]
|
||||
linker = "x86_64-linux-android-clang"
|
||||
rustflags = [
|
||||
"-C", "link-arg=-lc++_shared",
|
||||
"-C", "link-arg=-llog",
|
||||
"-C", "link-arg=-landroid",
|
||||
]
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
root = true
|
||||
|
||||
[*] # 表示所有文件适用
|
||||
charset = utf-8 # 设置文件字符集为 utf-8
|
||||
indent_size = 2 # 缩进大小
|
||||
end_of_line = lf # 控制换行类型(lf | cr | crlf)
|
||||
trim_trailing_whitespace = true # 末尾空格修剪
|
||||
insert_final_newline = true # 始终在文件末尾插入一个新行
|
||||
[*]
|
||||
charset = utf-8
|
||||
indent_size = 2
|
||||
end_of_line = lf
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# 后端服务地址
|
||||
VITE_SERVICE_URL="https://hulaspark.com/api"
|
||||
# # websocket服务地址
|
||||
VITE_WEBSOCKET_URL="wss://hulaspark.com/websocket"
|
||||
# websocket服务地址
|
||||
VITE_WEBSOCKET_URL="wss://hulaspark.com/api/ws/ws"
|
||||
# 项目标题
|
||||
VITE_APP_TITLE="HuLa—IM"
|
||||
# 项目名称
|
||||
@@ -9,6 +9,11 @@ VITE_APP_NAME="HuLa"
|
||||
# gitee token
|
||||
VITE_GITEE_TOKEN="a9029798336825cea39ac9e4413b8579"
|
||||
|
||||
# 启用本地的服务地址,先要注释掉上面的服务地址
|
||||
# VITE_SERVICE_URL="http://192.168.1.24:9190"
|
||||
# VITE_WEBSOCKET_URL="ws://192.168.1.24:8090/websocket"
|
||||
# TURN信令服务器
|
||||
VITE_TURN_SERVER_URL=
|
||||
VITE_TURN_SERVER_USER=
|
||||
VITE_TURN_SERVER_PWD=
|
||||
|
||||
VITE_USE_RUST_WEBSOCKET=true
|
||||
RUST_BACKTRACE=1
|
||||
APP_ENVIRONMENT=local
|
||||
|
||||
@@ -1,10 +1,19 @@
|
||||
# 后端服务地址
|
||||
VITE_SERVICE_URL="https://hulaspark.com/api"
|
||||
# websocket服务地址
|
||||
VITE_WEBSOCKET_URL="wss://hulaspark.com/websocket"
|
||||
VITE_WEBSOCKET_URL="wss://hulaspark.com/api/ws/ws"
|
||||
# 项目标题
|
||||
VITE_APP_TITLE="HuLa—IM"
|
||||
# 项目名称
|
||||
VITE_APP_NAME="HuLa"
|
||||
# gitee token
|
||||
VITE_GITEE_TOKEN="a9029798336825cea39ac9e4413b8579"
|
||||
|
||||
# TURN信令服务器
|
||||
VITE_TURN_SERVER_URL=
|
||||
VITE_TURN_SERVER_USER=
|
||||
VITE_TURN_SERVER_PWD=
|
||||
|
||||
VITE_USE_RUST_WEBSOCKET=true
|
||||
RUST_BACKTRACE=1
|
||||
APP_ENVIRONMENT=production
|
||||
@@ -1,14 +0,0 @@
|
||||
node_modules
|
||||
*.md
|
||||
*.scss
|
||||
.vscode
|
||||
.idea
|
||||
dist
|
||||
public
|
||||
index.html
|
||||
src/assets
|
||||
.eslintrc.cjs
|
||||
**/config
|
||||
src-tauri/**
|
||||
commitlint.config.cjs
|
||||
auto-imports.d.ts
|
||||
57
.eslintrc.cjs
vendored
@@ -1,57 +0,0 @@
|
||||
module.exports = {
|
||||
// 运行环境
|
||||
env: {
|
||||
browser: true, // 浏览器
|
||||
es6: true, // es6语法
|
||||
jest: true
|
||||
},
|
||||
parser: 'vue-eslint-parser',
|
||||
parserOptions: {
|
||||
ecmaVersion: 'latest',
|
||||
parser: '@typescript-eslint/parser',
|
||||
sourceType: 'module',
|
||||
jsxPragma: 'React',
|
||||
ecmaFeatures: {
|
||||
jsx: true
|
||||
}
|
||||
},
|
||||
extends: [
|
||||
'eslint:recommended',
|
||||
'plugin:@typescript-eslint/recommended',
|
||||
'plugin:vue/vue3-essential',
|
||||
'plugin:prettier/recommended'
|
||||
],
|
||||
overrides: [
|
||||
{
|
||||
env: {
|
||||
node: true
|
||||
},
|
||||
files: ['.eslintrc.{js,cjs}'],
|
||||
parserOptions: {
|
||||
sourceType: 'script'
|
||||
}
|
||||
}
|
||||
],
|
||||
plugins: ['@typescript-eslint', 'vue'],
|
||||
rules: {
|
||||
'@typescript-eslint/no-non-null-assertion': 'off',
|
||||
/** 允许ts使用命名空间 */
|
||||
'@typescript-eslint/no-namespace': 'off',
|
||||
/**
|
||||
* 使用新vue3.3的defineProps解构语法需要关闭这个校验
|
||||
* eslint-plugin-vue新版本已废弃 vue/no-setup-props-destructure,如果新版本eslint-plugin-vue
|
||||
* 需要改成vue/no-setup-props-reactivity-loss规则
|
||||
* */
|
||||
'vue/no-setup-props-destructure': 'off',
|
||||
'no-undef': 'off',
|
||||
'no-var': 'error', // 不能使用var
|
||||
'no-multiple-empty-lines': ['warn', { max: 2 }], // 不允许多个空行
|
||||
quotes: [1, 'single'], //引号类型 `` "" ''
|
||||
semi: ['error', 'never'], // 不允许在末尾加分号
|
||||
'vue/multi-word-component-names': 'off', //关闭组件命名规则
|
||||
'@typescript-eslint/no-explicit-any': 'off', // 关闭any校验
|
||||
'no-redeclare': 2, //禁止重复声明变量
|
||||
'eol-last': 'off', // 关闭行尾符(linebreak-style)的校验
|
||||
'vue/use-v-on-exact': 'off', // 如果使用了键盘事件,这个规则必须添加 exact,例如 `@keydown.exact`。该事件对 chat-editor 存在影响
|
||||
}
|
||||
}
|
||||
34
.gitattributes
vendored
@@ -1,5 +1,7 @@
|
||||
# Auto detect text files and perform LF normalization
|
||||
* text=auto eol=lf
|
||||
|
||||
# 行尾符设置
|
||||
"*.rs" eol=lf
|
||||
"Cargo.toml" eol=lf
|
||||
"Cargo.lock" eol=lf
|
||||
@@ -20,3 +22,35 @@
|
||||
"*.sass" eol=lf
|
||||
"*.styl" eol=lf
|
||||
"*.md" eol=lf
|
||||
|
||||
# 代码统计设置 - 只统计 Vue、TypeScript 和 Rust 文件
|
||||
# 排除 JavaScript 文件
|
||||
"*.js" linguist-vendored
|
||||
"*.jsx" linguist-vendored
|
||||
"*.cjs" linguist-vendored
|
||||
"*.mjs" linguist-vendored
|
||||
|
||||
# 排除样式文件
|
||||
"*.css" linguist-vendored
|
||||
"*.scss" linguist-vendored
|
||||
"*.sass" linguist-vendored
|
||||
"*.less" linguist-vendored
|
||||
"*.styl" linguist-vendored
|
||||
|
||||
# 排除配置和文档文件
|
||||
"*.json" linguist-vendored
|
||||
"*.html" linguist-vendored
|
||||
"*.md" linguist-documentation
|
||||
"*.yml" linguist-vendored
|
||||
"*.yaml" linguist-vendored
|
||||
|
||||
# 排除其他语言文件
|
||||
"*.kt" linguist-vendored
|
||||
"*.java" linguist-vendored
|
||||
"*.py" linguist-vendored
|
||||
|
||||
# 确保构建目录和依赖目录不被统计
|
||||
"**/target/**" linguist-vendored
|
||||
"/node_modules/**" linguist-vendored
|
||||
"/scripts/**" linguist-vendored
|
||||
"/build/**" linguist-vendored
|
||||
|
||||
1
.gitignore
vendored
@@ -33,3 +33,4 @@ target
|
||||
.claude/
|
||||
*.sqlite
|
||||
db.sqlite
|
||||
.idea
|
||||
|
||||
19
.lintstagedrc.mjs
vendored
@@ -5,11 +5,18 @@ function createCommand(prefix, join) {
|
||||
}
|
||||
|
||||
export default {
|
||||
'*.{js,jsx,ts,tsx,vue}': [
|
||||
'oxlint src',
|
||||
createCommand('pnpm eslint --fix', ''),
|
||||
createCommand('prettier --write', '--write'),
|
||||
// () => 'pnpm test:run',
|
||||
() => 'vue-tsc --noEmit'
|
||||
// JavaScript/TypeScript 文件使用 Biome (排除 .d.ts 文件)
|
||||
'*.{js,jsx,ts,tsx,json}': [
|
||||
(filenames) => {
|
||||
const filteredFiles = filenames.filter((f) => !f.includes('src-tauri/') && !f.endsWith('.d.ts'))
|
||||
return filteredFiles.length > 0
|
||||
? `biome check --write --unsafe ${filteredFiles.map((f) => path.relative(process.cwd(), f)).join(' ')}`
|
||||
: 'echo "No files to check"'
|
||||
}
|
||||
],
|
||||
// Vue 文件:使用 Biome 检查和修复,然后用 Prettier 格式化
|
||||
'*.vue': [
|
||||
createCommand('biome check --write --unsafe', ''),
|
||||
createCommand('prettier --write', '')
|
||||
]
|
||||
}
|
||||
|
||||
@@ -4,11 +4,11 @@
|
||||
"printWidth": 120,
|
||||
"useTabs": false,
|
||||
"tabWidth": 2,
|
||||
"jsxSingleQuote": false,
|
||||
"trailingComma": "none",
|
||||
"bracketSpacing": true,
|
||||
"arrowParens": "always",
|
||||
"bracketSameLine": true,
|
||||
"jsxBracketSameLine": true,
|
||||
"endOfLine": "lf"
|
||||
}
|
||||
"endOfLine": "lf",
|
||||
"vueIndentScriptAndStyle": false,
|
||||
"htmlWhitespaceSensitivity": "ignore"
|
||||
}
|
||||
8
.vscode/settings.json
vendored
@@ -1,7 +1,5 @@
|
||||
{
|
||||
"css.customData": [
|
||||
".vscode/tailwindcss.json"
|
||||
],
|
||||
"java.configuration.updateBuildConfiguration": "disabled",
|
||||
"typescript.tsdk": "node_modules/typescript/lib",
|
||||
"css.customData": [".vscode/tailwindcss.json"],
|
||||
"java.configuration.updateBuildConfiguration": "disabled",
|
||||
"typescript.tsdk": "node_modules/typescript/lib"
|
||||
}
|
||||
|
||||
@@ -348,7 +348,7 @@ Execute **pnpm run commit** to invoke _git commit_ interaction, complete informa
|
||||
| 2025-05-27 | **临安居士** | `¥188` |  |
|
||||
| 2025-04-20 | **姜兴(Simon)** | `¥188` |  |
|
||||
| 2025-02-17 | **禾硕** | `¥168` |  |
|
||||
| 2025-07-15 | **zhongjing** | `¥100` |  |
|
||||
| 2025-08-13 | **zhongjing** | `¥100` |  |
|
||||
| 2025-07-15 | **粉兔** | `¥100` |  |
|
||||
| 2025-02-8 | **Boom....** | `¥100` |  |
|
||||
|
||||
@@ -366,7 +366,7 @@ Execute **pnpm run commit** to invoke _git commit_ interaction, complete informa
|
||||
### 🥉 Bronze Sponsors ($3-7)
|
||||
| 💝 Date | 👤 Sponsor | 💰 Amount | 🏷️ Platform |
|
||||
|---------|----------|--------|---------|
|
||||
| 2025-06-03 | ***持** | `¥20` |  |
|
||||
| 2025-08-12 | ***持** | `¥20` |  |
|
||||
| 2025-06-03 | **洪流** | `¥20` |  |
|
||||
| 2025-05-27 | **刘启成** | `¥20` |  |
|
||||
| 2025-05-20 | **匿名赞助者** | `¥20` |  |
|
||||
|
||||
@@ -349,7 +349,7 @@ sudo xattr -r -d com.apple.quarantine /Applications/应用名称.app
|
||||
| 2025-05-27 | **临安居士** | `¥188` |  |
|
||||
| 2025-04-20 | **姜兴(Simon)** | `¥188` |  |
|
||||
| 2025-02-17 | **禾硕** | `¥168` |  |
|
||||
| 2025-07-15 | **zhongjing** | `¥100` |  |
|
||||
| 2025-08-13 | **zhongjing** | `¥100` |  |
|
||||
| 2025-07-15 | **粉兔** | `¥100` |  |
|
||||
| 2025-02-8 | **Boom....** | `¥100` |  |
|
||||
|
||||
@@ -367,7 +367,7 @@ sudo xattr -r -d com.apple.quarantine /Applications/应用名称.app
|
||||
### 🥉 铜牌赞助者 (¥20-49)
|
||||
| 💝 日期 | 👤 赞助者 | 💰 金额 | 🏷️ 平台 |
|
||||
|---------|----------|--------|---------|
|
||||
| 2025-06-03 | ***持** | `¥20` |  |
|
||||
| 2025-08-12 | ***持** | `¥20` |  |
|
||||
| 2025-06-03 | **洪流** | `¥20` |  |
|
||||
| 2025-05-27 | **刘启成** | `¥20` |  |
|
||||
| 2025-05-20 | **匿名赞助者** | `¥20` |  |
|
||||
|
||||
112
biome.json
vendored
Normal file
@@ -0,0 +1,112 @@
|
||||
{
|
||||
"$schema": "https://biomejs.dev/schemas/latest/schema.json",
|
||||
"vcs": { "enabled": false, "clientKind": "git", "useIgnoreFile": false },
|
||||
"files": {
|
||||
"ignoreUnknown": false,
|
||||
"includes": [
|
||||
"**/*.{js,jsx,ts,tsx,vue,json}",
|
||||
"!.*/**",
|
||||
"!public/**",
|
||||
"!src/typings/*.d.ts",
|
||||
"!src-tauri/**",
|
||||
"!node_modules/**",
|
||||
"!dist/**"
|
||||
]
|
||||
},
|
||||
"formatter": {
|
||||
"enabled": true,
|
||||
"formatWithErrors": false,
|
||||
"indentStyle": "space",
|
||||
"indentWidth": 2,
|
||||
"lineEnding": "lf",
|
||||
"lineWidth": 120,
|
||||
"attributePosition": "auto",
|
||||
"bracketSameLine": true,
|
||||
"bracketSpacing": true,
|
||||
"expand": "auto",
|
||||
"useEditorconfig": true
|
||||
},
|
||||
"linter": {
|
||||
"enabled": true,
|
||||
"rules": {
|
||||
"recommended": true,
|
||||
"a11y": {
|
||||
"noStaticElementInteractions": "off",
|
||||
"useKeyWithClickEvents": "off",
|
||||
"noSvgWithoutTitle": "off",
|
||||
"useAltText": "off"
|
||||
},
|
||||
"complexity": {
|
||||
"useOptionalChain": "off",
|
||||
"useLiteralKeys": "off",
|
||||
"useDateNow": "off",
|
||||
"noStaticOnlyClass": "off"
|
||||
},
|
||||
"correctness": {
|
||||
"noUnusedVariables": "warn",
|
||||
"noUnusedImports": "warn"
|
||||
},
|
||||
"style": {
|
||||
"useNodejsImportProtocol": "off",
|
||||
"noNonNullAssertion": "off",
|
||||
"useNamingConvention": "off",
|
||||
"useTemplate": "off"
|
||||
},
|
||||
"suspicious": {
|
||||
"noGlobalIsNan": "off",
|
||||
"noExplicitAny": "off",
|
||||
"noAssignInExpressions": "off",
|
||||
"noImplicitAnyLet": "off",
|
||||
"noConfusingVoidType": "off",
|
||||
"noArrayIndexKey": "off"
|
||||
}
|
||||
}
|
||||
},
|
||||
"javascript": {
|
||||
"formatter": {
|
||||
"jsxQuoteStyle": "double",
|
||||
"quoteProperties": "asNeeded",
|
||||
"trailingCommas": "none",
|
||||
"semicolons": "asNeeded",
|
||||
"arrowParentheses": "always",
|
||||
"bracketSameLine": true,
|
||||
"quoteStyle": "single",
|
||||
"attributePosition": "auto",
|
||||
"bracketSpacing": true
|
||||
}
|
||||
},
|
||||
"json": {
|
||||
"formatter": {
|
||||
"trailingCommas": "none"
|
||||
}
|
||||
},
|
||||
"assist": {
|
||||
"enabled": true,
|
||||
"actions": { "source": { "organizeImports": "on" } }
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"includes": ["**/*.vue"],
|
||||
"linter": {
|
||||
"rules": {
|
||||
"correctness": {
|
||||
"noUnusedVariables": "off",
|
||||
"noUnusedImports": "off"
|
||||
},
|
||||
"style": {
|
||||
"useNamingConvention": "off",
|
||||
"useTemplate": "off"
|
||||
},
|
||||
"suspicious": {
|
||||
"noExplicitAny": "off",
|
||||
"noAssignInExpressions": "off",
|
||||
"noImplicitAnyLet": "off"
|
||||
}
|
||||
}
|
||||
},
|
||||
"formatter": {
|
||||
"enabled": true
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
2
build/config/getPath.ts
vendored
@@ -1,5 +1,5 @@
|
||||
//使用path需要按照@types/node依赖
|
||||
import path from 'path'
|
||||
import path from 'node:path'
|
||||
|
||||
/**
|
||||
* 获取项目根路径
|
||||
|
||||
123
index.html
vendored
@@ -2,16 +2,131 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no viewport-fit=cover" />
|
||||
<title>HuLa</title>
|
||||
<meta
|
||||
name="viewport"
|
||||
content="width=device-width, initial-scale=1, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no viewport-fit=cover" />
|
||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||
|
||||
<!--引入iconpark图标库-->
|
||||
<script defer src="/icon.js"></script>
|
||||
<!-- 🎯 预加载图片资源(仅移动端) -->
|
||||
<script>
|
||||
if (/Mobi|Android|iPhone/i.test(navigator.userAgent)) {
|
||||
const preloadImages = ['/Mobile/1.png', '/Mobile/2.png', '/Mobile/3.png', '/Mobile/4.png']
|
||||
preloadImages.forEach(src => {
|
||||
const link = document.createElement('link')
|
||||
link.rel = 'preload'
|
||||
link.as = 'image'
|
||||
link.href = src
|
||||
document.head.appendChild(link)
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- iconpark图标库 -->
|
||||
<script async src="/icon.js"></script>
|
||||
|
||||
<!-- 🧩 加载页样式 -->
|
||||
<style id="loading-css">
|
||||
#loading-page {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
z-index: 9999;
|
||||
background-image: url('/Mobile/2.png');
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding-top: env(safe-area-inset-top);
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
transition: opacity 0.4s ease-out;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.bottom-bar {
|
||||
position: absolute;
|
||||
bottom: 40px;
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.rounded-14px {
|
||||
border-radius: 14px;
|
||||
}
|
||||
|
||||
.size-50px {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
}
|
||||
|
||||
.w-300px {
|
||||
width: 300px;
|
||||
}
|
||||
|
||||
.h-200px {
|
||||
height: 200px;
|
||||
}
|
||||
|
||||
.w-78px {
|
||||
width: 78px;
|
||||
}
|
||||
|
||||
.h-40px {
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
.mb-140px {
|
||||
margin-bottom: 140px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<!-- 🚀 加载页 DOM -->
|
||||
<div id="loading-page">
|
||||
<img src="/Mobile/4.png" alt="hula" class="w-300px h-200px mb-140px" />
|
||||
<div class="bottom-bar">
|
||||
<img src="/Mobile/3.png" alt="hula" class="size-50px rounded-14px" />
|
||||
<img src="/Mobile/1.png" alt="hula" class="w-78px h-40px" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Vue 应用挂载点 -->
|
||||
<div id="app"></div>
|
||||
|
||||
<!-- 🎯 加载页逻辑控制(淡出 + 清理) -->
|
||||
<script>
|
||||
function isMobileDevice() {
|
||||
return /Mobi|Android|iPhone/i.test(navigator.userAgent)
|
||||
}
|
||||
|
||||
if (!isMobileDevice()) {
|
||||
document.getElementById('loading-page')?.remove()
|
||||
document.getElementById('loading-css')?.remove()
|
||||
}
|
||||
|
||||
window.addEventListener('DOMContentLoaded', () => {
|
||||
const interval = setInterval(() => {
|
||||
const isMounted = document.getElementById('app')?.children.length > 0
|
||||
if (isMounted) {
|
||||
const loader = document.getElementById('loading-page')
|
||||
if (loader) {
|
||||
loader.style.opacity = '0'
|
||||
setTimeout(() => {
|
||||
loader.remove()
|
||||
document.getElementById('loading-css')?.remove()
|
||||
}, 450) // 等待 transition 完成后再移除
|
||||
}
|
||||
clearInterval(interval)
|
||||
}
|
||||
}, 100)
|
||||
})
|
||||
</script>
|
||||
|
||||
<!-- 🚀 Vue 应用入口 -->
|
||||
<script type="module" src="/src/main.ts"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
72
package.json
vendored
@@ -22,6 +22,7 @@
|
||||
"build": "vue-tsc --noEmit && vite build",
|
||||
"========= 启动HuLa桌面应用程序 =========": "",
|
||||
"tauri:dev": "tauri dev",
|
||||
"td": "tauri dev",
|
||||
"========= 打包桌面应用程序 =========": "",
|
||||
"tauri:build": "tauri build",
|
||||
"========= 打包后可调试并且可以弹出控制台 =========": "",
|
||||
@@ -42,7 +43,15 @@
|
||||
"preinstall": "npx only-allow pnpm && node scripts/check-all.js",
|
||||
"========= 使用commit来进行代码提交 =========": "",
|
||||
"commit": "git add . && git-cz",
|
||||
"========= 校验代码规范 =========": "",
|
||||
"========= 只检查代码问题和格式(不修复) =========": "",
|
||||
"check": "biome check",
|
||||
"========= 修复代码问题和格式并且检查 =========": "",
|
||||
"check:write": "biome check --write --unsafe",
|
||||
"========= 格式化Vue文件模板 =========": "",
|
||||
"format:vue": "npx prettier --write \"src/**/*.vue\"",
|
||||
"========= 完整格式化(JS+Vue) =========": "",
|
||||
"format:all": "pnpm check:write && pnpm format:vue",
|
||||
"========= Git提交前的代码检查 =========": "",
|
||||
"lint:staged": "lint-staged && vue-tsc --noEmit",
|
||||
"========= 安装husky =========": "",
|
||||
"prepare": "husky",
|
||||
@@ -63,12 +72,12 @@
|
||||
"@actions/github": "^6.0.0",
|
||||
"@breezystack/lamejs": "^1.2.7",
|
||||
"@fingerprintjs/fingerprintjs": "^4.6.2",
|
||||
"@tauri-apps/api": "2.6.0",
|
||||
"@tauri-apps/api": "2.7.0",
|
||||
"@tauri-apps/plugin-autostart": "2.5.0",
|
||||
"@tauri-apps/plugin-clipboard-manager": "2.3.0",
|
||||
"@tauri-apps/plugin-dialog": "^2.3.0",
|
||||
"@tauri-apps/plugin-fs": "^2.4.0",
|
||||
"@tauri-apps/plugin-http": "2.5.0",
|
||||
"@tauri-apps/plugin-dialog": "^2.3.2",
|
||||
"@tauri-apps/plugin-fs": "^2.4.1",
|
||||
"@tauri-apps/plugin-http": "2.5.1",
|
||||
"@tauri-apps/plugin-log": "^2.6.0",
|
||||
"@tauri-apps/plugin-notification": "^2.3.0",
|
||||
"@tauri-apps/plugin-opener": "^2.4.0",
|
||||
@@ -81,7 +90,6 @@
|
||||
"@vue-office/excel": "^1.7.14",
|
||||
"@vue-office/pdf": "^2.0.10",
|
||||
"@vue-office/pptx": "^1.0.1",
|
||||
"base64url": "^3.0.1",
|
||||
"colorthief": "^2.6.0",
|
||||
"crypto-js": "^4.2.0",
|
||||
"dayjs": "^1.11.11",
|
||||
@@ -99,57 +107,50 @@
|
||||
"seemly": "^0.3.10",
|
||||
"tauri-plugin-mic-recorder-api": "^2.0.0",
|
||||
"tauri-plugin-safe-area-insets": "^0.1.0",
|
||||
"vue": "^3.5.17",
|
||||
"vue": "^3.5.18",
|
||||
"vue-cropper": "1.1.4",
|
||||
"vue-demi": "0.14.6",
|
||||
"vue-router": "^4.5.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/eslint-parser": "^7.25.9",
|
||||
"@biomejs/biome": "^2.1.4",
|
||||
"@commitlint/cli": "^19.6.0",
|
||||
"@commitlint/config-conventional": "^19.6.0",
|
||||
"@iconify/vue": "^5.0.0",
|
||||
"@release-it/bumper": "^6.0.1",
|
||||
"@release-it/conventional-changelog": "8.0.2",
|
||||
"@rollup/plugin-terser": "^0.4.4",
|
||||
"@tauri-apps/cli": "2.6.2",
|
||||
"@tauri-apps/cli": "2.7.1",
|
||||
"@types/crypto-js": "^4.2.2",
|
||||
"@types/lodash-es": "^4.17.12",
|
||||
"@types/node": "^24.0.10",
|
||||
"@typescript-eslint/eslint-plugin": "7.1.0",
|
||||
"@typescript-eslint/parser": "^7.15.0",
|
||||
"@unocss/preset-wind3": "^66.3.3",
|
||||
"@unocss/reset": "^66.3.3",
|
||||
"@unocss/transformer-directives": "^66.3.3",
|
||||
"@unocss/transformer-variant-group": "^66.3.3",
|
||||
"@unocss/vite": "^66.3.3",
|
||||
"@vitejs/plugin-vue": "^6.0.0",
|
||||
"@unocss/preset-wind3": "^66.4.2",
|
||||
"@unocss/reset": "^66.4.2",
|
||||
"@unocss/transformer-directives": "^66.4.2",
|
||||
"@unocss/transformer-variant-group": "^66.4.2",
|
||||
"@unocss/vite": "^66.4.2",
|
||||
"@vitejs/plugin-vue": "^6.0.1",
|
||||
"@vitejs/plugin-vue-jsx": "^5.0.1",
|
||||
"@vitest/coverage-v8": "^3.0.5",
|
||||
"@vitest/ui": "^3.0.5",
|
||||
"@vitest/coverage-v8": "^3.2.4",
|
||||
"@vitest/ui": "^3.2.4",
|
||||
"@vue/test-utils": "^2.4.6",
|
||||
"@vueuse/core": "^13.5.0",
|
||||
"chalk": "^5.3.0",
|
||||
"commitizen": "^4.3.1",
|
||||
"cz-git": "^1.11.0",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"eslint-plugin-import": "^2.29.1",
|
||||
"eslint-plugin-prettier": "^5.1.3",
|
||||
"eslint-plugin-vue": "^9.27.0",
|
||||
"happy-dom": "^15.11.7",
|
||||
"husky": "^9.0.11",
|
||||
"husky": "^9.1.7",
|
||||
"lint-staged": "^15.2.7",
|
||||
"oxlint": "^0.2.18",
|
||||
"prettier": "^3.3.2",
|
||||
"prettier": "^3.6.2",
|
||||
"release-it": "^17.11.0",
|
||||
"sass": "1.89.2",
|
||||
"typescript": "^5.8.3",
|
||||
"sass": "1.90.0",
|
||||
"typescript": "^5.9.2",
|
||||
"unplugin-auto-import": "^19.3.0",
|
||||
"unplugin-vue-components": "^28.8.0",
|
||||
"vite": "7.0.5",
|
||||
"vite": "7.1.1",
|
||||
"vite-plugin-vue-setup-extend": "^0.4.0",
|
||||
"vitest": "^3.0.5",
|
||||
"vue-tsc": "^3.0.1"
|
||||
"vitest": "^3.2.4",
|
||||
"vue-tsc": "^3.0.5"
|
||||
},
|
||||
"config": {
|
||||
"commitizen": {
|
||||
@@ -157,11 +158,6 @@
|
||||
}
|
||||
},
|
||||
"pnpm": {
|
||||
"ignoredBuiltDependencies": [
|
||||
"esbuild",
|
||||
"vue-demi",
|
||||
"@parcel/watcher",
|
||||
"sharp"
|
||||
]
|
||||
"ignoredBuiltDependencies": ["esbuild", "vue-demi", "@parcel/watcher", "sharp"]
|
||||
}
|
||||
}
|
||||
|
||||
3609
pnpm-lock.yaml
generated
vendored
|
Before Width: | Height: | Size: 3.9 KiB |
BIN
public/Mobile/1.webp
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 903 KiB |
BIN
public/Mobile/2.webp
Normal file
|
After Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 2.8 KiB |
BIN
public/Mobile/3.webp
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 95 KiB |
BIN
public/Mobile/4.webp
Normal file
|
After Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 201 KiB |
BIN
public/avatar/001.webp
Normal file
|
After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 207 KiB |
BIN
public/avatar/002.webp
Normal file
|
After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 186 KiB |
BIN
public/avatar/003.webp
Normal file
|
After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 206 KiB |
BIN
public/avatar/004.webp
Normal file
|
After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 227 KiB |
BIN
public/avatar/005.webp
Normal file
|
After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 204 KiB |
BIN
public/avatar/006.webp
Normal file
|
After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 191 KiB |
BIN
public/avatar/007.webp
Normal file
|
After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 204 KiB |
BIN
public/avatar/008.webp
Normal file
|
After Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 200 KiB |
BIN
public/avatar/009.webp
Normal file
|
After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 210 KiB |
BIN
public/avatar/010.webp
Normal file
|
After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 193 KiB |
BIN
public/avatar/011.webp
Normal file
|
After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 181 KiB |
BIN
public/avatar/012.webp
Normal file
|
After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 212 KiB |
BIN
public/avatar/013.webp
Normal file
|
After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 209 KiB |
BIN
public/avatar/014.webp
Normal file
|
After Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 192 KiB |
BIN
public/avatar/015.webp
Normal file
|
After Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 188 KiB |
BIN
public/avatar/016.webp
Normal file
|
After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 212 KiB |
BIN
public/avatar/017.webp
Normal file
|
After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 208 KiB |
BIN
public/avatar/018.webp
Normal file
|
After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 202 KiB |
BIN
public/avatar/019.webp
Normal file
|
After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 210 KiB |
BIN
public/avatar/020.webp
Normal file
|
After Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 211 KiB |
BIN
public/avatar/021.webp
Normal file
|
After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 12 KiB |
BIN
public/avatar/022.webp
Normal file
|
After Width: | Height: | Size: 14 KiB |
2
public/icon.js
vendored
BIN
public/logoD.png
Normal file
|
After Width: | Height: | Size: 5.4 KiB |
BIN
public/logoL.png
Normal file
|
After Width: | Height: | Size: 6.4 KiB |
BIN
public/sound/hula_bell.mp3
Normal file
BIN
public/sound/message.mp3
Normal file
6
scripts/check-all.js
vendored
@@ -1,7 +1,7 @@
|
||||
import { execSync } from 'child_process'
|
||||
import chalk from 'chalk'
|
||||
import { fileURLToPath } from 'url'
|
||||
import { execSync } from 'child_process'
|
||||
import { dirname, join } from 'path'
|
||||
import { fileURLToPath } from 'url'
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url)
|
||||
const __dirname = dirname(__filename)
|
||||
@@ -20,7 +20,7 @@ async function runScript(scriptPath, description) {
|
||||
const duration = ((performance.now() - startTime) / 1000).toFixed(2)
|
||||
console.log(chalk.green(`\n✅ ${description}完成 (${duration}s)\n`))
|
||||
return true
|
||||
} catch (error) {
|
||||
} catch (_error) {
|
||||
console.error(chalk.red(`\n❌ ${description}失败`))
|
||||
return false
|
||||
}
|
||||
|
||||
4
scripts/check-dependencies.js
vendored
@@ -1,7 +1,7 @@
|
||||
import { execSync } from 'child_process'
|
||||
import chalk from 'chalk'
|
||||
import { platform } from 'os'
|
||||
import { execSync } from 'child_process'
|
||||
import { existsSync } from 'fs'
|
||||
import { platform } from 'os'
|
||||
|
||||
// 环境安装指南
|
||||
const INSTALL_GUIDES = {
|
||||
|
||||
40
scripts/check-env.js
vendored
@@ -1,12 +1,12 @@
|
||||
import { existsSync, writeFileSync } from 'fs'
|
||||
import { join } from 'path'
|
||||
import chalk from 'chalk'
|
||||
import { existsSync, readFileSync, writeFileSync } from 'fs'
|
||||
import { join } from 'path'
|
||||
|
||||
// 用于写入.env.local配置文件,该文件默认不会被git管理,所以不必担心会提交到远程仓库
|
||||
const envPath = join(process.cwd(), '.env.local')
|
||||
// 用于写入 .env.development.local 配置文件
|
||||
const devEnvPath = join(process.cwd(), '.env.development')
|
||||
const devLocalEnvPath = join(process.cwd(), '.env.development.local')
|
||||
|
||||
if (!existsSync(envPath)) {
|
||||
const defaultEnvContent = `# 有道云翻译key
|
||||
const defaultEnvContent = `# 有道云翻译key
|
||||
VITE_YOUDAO_APP_KEY=
|
||||
VITE_YOUDAO_APP_SECRET=
|
||||
# 腾讯云翻译key
|
||||
@@ -14,13 +14,25 @@ VITE_TENCENT_API_KEY=
|
||||
VITE_TENCENT_SECRET_ID=
|
||||
`
|
||||
|
||||
try {
|
||||
writeFileSync(envPath, defaultEnvContent, 'utf8')
|
||||
console.log(chalk.green('✨ 成功创建.env.local文件'))
|
||||
} catch (error) {
|
||||
console.log(chalk.red('\n❌ 创建.env.local文件失败。'))
|
||||
process.exit(1)
|
||||
try {
|
||||
if (existsSync(devLocalEnvPath)) {
|
||||
console.log(chalk.green('✅ 检测到 .env.development.local 已存在,跳过创建'))
|
||||
process.exit(0)
|
||||
}
|
||||
} else {
|
||||
console.log(chalk.green('✅ .env.local文件已创建'))
|
||||
|
||||
let content = defaultEnvContent
|
||||
if (existsSync(devEnvPath)) {
|
||||
const devContent = readFileSync(devEnvPath, 'utf8')
|
||||
content += (content.endsWith('\n') ? '' : '\n') + devContent
|
||||
}
|
||||
|
||||
writeFileSync(devLocalEnvPath, content, 'utf8')
|
||||
if (existsSync(devEnvPath)) {
|
||||
console.log(chalk.green('✨ 已创建 .env.development.local'))
|
||||
} else {
|
||||
console.log(chalk.yellow('⚠️ 未找到 .env.development,仅创建默认模板的 .env.development.local'))
|
||||
}
|
||||
} catch (_error) {
|
||||
console.log(chalk.red('\n❌ 处理 .env.development.local 文件失败。'))
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
RUST_BACKTRACE=1
|
||||
DATABASE_URL=sqlite:../db.sqlite?mode=rwc
|
||||
703
src-tauri/Cargo.lock
generated
@@ -31,11 +31,11 @@ name = "hula_app_lib"
|
||||
crate-type = ["staticlib", "cdylib", "rlib"]
|
||||
|
||||
[build-dependencies]
|
||||
tauri-build = { version = "2.3.0", features = [] }
|
||||
tauri-build = { version = "2.3.1", features = [] }
|
||||
|
||||
[dependencies]
|
||||
# Tauri 官方依赖
|
||||
tauri = { version = "2.6.2", features = [
|
||||
tauri = { version = "2.7.0", features = [
|
||||
"protocol-asset",
|
||||
"macos-private-api",
|
||||
"tray-icon",
|
||||
@@ -57,6 +57,10 @@ tauri-plugin-clipboard-manager = "2"
|
||||
tauri-plugin-sql = { version = "2", features = ["sqlite"] }
|
||||
tauri-plugin-notification = "2"
|
||||
tauri-plugin-opener = "2"
|
||||
# tauri-plugin-devtools = "2"
|
||||
tauri-plugin-log = { version = "2", features = ["colored"] }
|
||||
tracing = "0.1"
|
||||
tracing-subscriber = "0.3.0"
|
||||
|
||||
# Tauri 非官方依赖
|
||||
tauri-plugin-mic-recorder = "2"
|
||||
@@ -66,9 +70,8 @@ async-walkdir = "2.0.0"
|
||||
moka = { version = "0.12.10", features = ["future"] }
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
tokio = { version = "1.0.0", features = ["rt", "rt-multi-thread", "macros"] }
|
||||
tauri-plugin-devtools = "2.0.0"
|
||||
|
||||
sea-orm = { version = "1.1.0", features = [ "sqlx-sqlite", "runtime-tokio-rustls", "macros" ] }
|
||||
sea-orm = { version = "1.1.0", features = [ "sqlx-sqlite", "runtime-tokio-rustls", "macros", "debug-print" ] }
|
||||
chrono = "0.4.41"
|
||||
|
||||
entity = { path = "entity" }
|
||||
@@ -77,23 +80,28 @@ anyhow = "1.0.98"
|
||||
thiserror = "2.0.12"
|
||||
config = { version = "0.15.11", default-features = false, features = ["yaml"] }
|
||||
http = "0.2"
|
||||
tauri-plugin-log = { version = "2.6.0", features = ["colored"] }
|
||||
log = "0.4" # 基础日志接口
|
||||
lazy_static = "1.4"
|
||||
mime_guess = "2.0.5"
|
||||
base64 = "0.22.1"
|
||||
rodio = "0.17.3"
|
||||
image = { version = "0.25", features = ["jpeg", "png"] }
|
||||
reqwest = { version = "0.11", features = [
|
||||
reqwest = { version = "0.11", default-features = false, features = [
|
||||
"json",
|
||||
"socks",
|
||||
"rustls-tls",
|
||||
"blocking",
|
||||
] }
|
||||
futures = "0.3"
|
||||
dotenv = "0.15.0"
|
||||
|
||||
# 安卓的依赖
|
||||
[target."cfg(target_os = \"android\")".dependencies]
|
||||
# WebSocket 相关依赖
|
||||
tokio-tungstenite = { version = "0.23", features = ["rustls-tls-webpki-roots"] }
|
||||
futures-util = "0.3"
|
||||
url = "2.5"
|
||||
uuid = { version = "1.10", features = ["v4"] }
|
||||
|
||||
# 移动端的依赖 (iOS 和 Android)
|
||||
[target."cfg(any(target_os = \"android\", target_os = \"ios\"))".dependencies]
|
||||
tauri-plugin-safe-area-insets = "0.1.0"
|
||||
|
||||
# 不兼容移动端的依赖
|
||||
|
||||
10
src-tauri/Info.plist
Normal file
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>NSCameraUsageDescription</key>
|
||||
<string>Request camera access for WebRTC</string>
|
||||
<key>NSMicrophoneUsageDescription</key>
|
||||
<string>Request microphone access for WebRTC</string>
|
||||
</dict>
|
||||
</plist>
|
||||
49
src-tauri/capabilities/default.json
vendored
@@ -96,6 +96,7 @@
|
||||
"opener:allow-open-path",
|
||||
"mic-recorder:default",
|
||||
"log:default",
|
||||
"log:allow-log",
|
||||
{
|
||||
"identifier": "shell:allow-execute",
|
||||
"allow": [
|
||||
@@ -180,54 +181,6 @@
|
||||
"url": "https://*:*"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"identifier": "fs:write-files",
|
||||
"allow": [
|
||||
{
|
||||
"path": "**"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"identifier": "fs:allow-mkdir",
|
||||
"allow": [
|
||||
{
|
||||
"path": "**"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"identifier": "fs:read-dirs",
|
||||
"allow": [
|
||||
{
|
||||
"path": "**"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"identifier": "fs:read-files",
|
||||
"allow": [
|
||||
{
|
||||
"path": "**"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"identifier": "fs:allow-copy-file",
|
||||
"allow": [
|
||||
{
|
||||
"path": "**"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"identifier": "fs:allow-read-text-file",
|
||||
"allow": [
|
||||
{
|
||||
"path": "**"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
51
src-tauri/capabilities/mobile.json
vendored
@@ -6,6 +6,7 @@
|
||||
"windows": ["*"],
|
||||
"permissions": [
|
||||
"core:default",
|
||||
"core:webview:allow-internal-toggle-devtools",
|
||||
"http:allow-fetch",
|
||||
"http:allow-fetch-cancel",
|
||||
"http:allow-fetch-read-body",
|
||||
@@ -36,6 +37,8 @@
|
||||
"notification:allow-create-channel",
|
||||
"notification:allow-permission-state",
|
||||
"safe-area-insets:default",
|
||||
"log:default",
|
||||
"log:allow-log",
|
||||
{
|
||||
"identifier": "shell:allow-execute",
|
||||
"allow": [
|
||||
@@ -120,54 +123,6 @@
|
||||
"url": "https://*:*"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"identifier": "fs:write-files",
|
||||
"allow": [
|
||||
{
|
||||
"path": "**"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"identifier": "fs:allow-mkdir",
|
||||
"allow": [
|
||||
{
|
||||
"path": "**"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"identifier": "fs:read-dirs",
|
||||
"allow": [
|
||||
{
|
||||
"path": "**"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"identifier": "fs:read-files",
|
||||
"allow": [
|
||||
{
|
||||
"path": "**"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"identifier": "fs:allow-copy-file",
|
||||
"allow": [
|
||||
{
|
||||
"path": "**"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"identifier": "fs:allow-read-text-file",
|
||||
"allow": [
|
||||
{
|
||||
"path": "**"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
11
src-tauri/configuration/local.yaml
vendored
@@ -1,7 +1,4 @@
|
||||
# application:
|
||||
# host: 127.0.0.1
|
||||
# base_url: "http://127.0.0.1"
|
||||
# database:
|
||||
# require_ssl: false
|
||||
# backend:
|
||||
# base_url: http://localhost:9190
|
||||
database:
|
||||
sqlite_file: db.sqlite
|
||||
backend:
|
||||
base_url: https://hulaspark.com/api
|
||||
|
||||
8
src-tauri/configuration/production.yaml
vendored
@@ -1,4 +1,4 @@
|
||||
# application:
|
||||
# host: 127.0.0.1
|
||||
# backend:
|
||||
# base_url: http://localhost:9190
|
||||
database:
|
||||
sqlite_file: db.sqlite
|
||||
backend:
|
||||
base_url: https://hulaspark.com/api
|
||||
|
||||
@@ -4,6 +4,6 @@ version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
sea-orm = { version = "1.1.0" }
|
||||
sea-orm = { version = "1.1.14" }
|
||||
serde = { version = "1.0.219", features = ["derive"] }
|
||||
serde_json = "1.0.140"
|
||||
serde_json = "1.0.141"
|
||||
|
||||
@@ -10,15 +10,15 @@ pub struct Model {
|
||||
pub detail_id: String,
|
||||
pub room_id: String,
|
||||
#[serde(rename = "type")]
|
||||
pub contact_type: Option<u8>,
|
||||
pub hot_flag: Option<u8>,
|
||||
pub contact_type: Option<u32>,
|
||||
pub hot_flag: Option<u32>,
|
||||
pub top: Option<bool>,
|
||||
pub account: Option<String>,
|
||||
pub operate: Option<u8>,
|
||||
pub operate: Option<u32>,
|
||||
pub remark: Option<String>,
|
||||
pub my_name: Option<String>,
|
||||
// "通知类型 0 -> 允许接受消息 1 -> 接收但不提醒[免打扰] 4 -> 已退出群聊"
|
||||
pub mute_notification: Option<u8>,
|
||||
pub mute_notification: Option<u32>,
|
||||
// 删除会话
|
||||
pub hide: Option<bool>,
|
||||
pub active_time: Option<i64>,
|
||||
@@ -28,7 +28,7 @@ pub struct Model {
|
||||
#[serde(rename = "name")]
|
||||
pub contact_name: Option<String>,
|
||||
pub text: Option<String>,
|
||||
pub unread_count: Option<u8>,
|
||||
pub unread_count: Option<u32>,
|
||||
pub create_time: Option<i64>,
|
||||
pub update_time: Option<i64>,
|
||||
#[serde(skip)]
|
||||
|
||||
@@ -24,7 +24,8 @@ pub struct Model {
|
||||
pub send_status: String,
|
||||
}
|
||||
|
||||
impl ActiveModelBehavior for ActiveModel {}
|
||||
|
||||
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
||||
pub enum Relation {}
|
||||
|
||||
impl ActiveModelBehavior for ActiveModel {}
|
||||
|
||||
@@ -13,6 +13,7 @@ pub struct Model {
|
||||
pub account: Option<String>,
|
||||
pub my_name: Option<String>,
|
||||
pub active_status: Option<u8>,
|
||||
#[serde(rename = "roleId")]
|
||||
pub group_role: Option<i64>,
|
||||
pub loc_place: Option<String>,
|
||||
pub last_opt_time: i64,
|
||||
|
||||
2
src-tauri/gen/android/app/.gitignore
vendored
@@ -1,4 +1,4 @@
|
||||
/src/main/java/com/hula_app/app/generated
|
||||
/src/main/java/com/hula_ios/app/generated
|
||||
/src/main/jniLibs/**/*.so
|
||||
/src/main/assets/tauri.conf.json
|
||||
/tauri.build.gradle.kts
|
||||
|
||||
@@ -15,14 +15,21 @@ val tauriProperties = Properties().apply {
|
||||
|
||||
android {
|
||||
compileSdk = 34
|
||||
namespace = "com.hula_app.app"
|
||||
namespace = "com.hula_ios.app"
|
||||
|
||||
ndkVersion = "25.1.8937393"
|
||||
|
||||
defaultConfig {
|
||||
manifestPlaceholders["usesCleartextTraffic"] = "false"
|
||||
applicationId = "com.hula_app.app"
|
||||
applicationId = "com.hula_ios.app"
|
||||
minSdk = 24
|
||||
targetSdk = 34
|
||||
versionCode = tauriProperties.getProperty("tauri.android.versionCode", "1").toInt()
|
||||
versionName = tauriProperties.getProperty("tauri.android.versionName", "1.0")
|
||||
|
||||
ndk {
|
||||
abiFilters += listOf("arm64-v8a", "armeabi-v7a", "x86", "x86_64")
|
||||
}
|
||||
}
|
||||
buildTypes {
|
||||
getByName("debug") {
|
||||
|
||||
4
src-tauri/gen/android/app/src/main/assets/configuration/base.yaml
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
database:
|
||||
sqlite_file: db.sqlite
|
||||
backend:
|
||||
base_url: http://192.168.1.37:18760
|
||||
4
src-tauri/gen/android/app/src/main/assets/configuration/local.yaml
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
database:
|
||||
sqlite_file: db.sqlite
|
||||
backend:
|
||||
base_url: http://192.168.1.37:18760
|
||||
4
src-tauri/gen/android/app/src/main/assets/configuration/production.yaml
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
database:
|
||||
sqlite_file: db.sqlite
|
||||
backend:
|
||||
base_url: http://192.168.1.37:18760
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.hula_app.app
|
||||
package com.hula_ios.app
|
||||
|
||||
import android.os.Bundle
|
||||
import android.webkit.WebView
|
||||
0
src-tauri/gen/android/gradlew
vendored
Normal file → Executable file
4
src-tauri/gen/apple/assets/configuration/base.yaml
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
database:
|
||||
sqlite_file: db.sqlite
|
||||
backend:
|
||||
base_url: http://192.168.1.37:18760
|
||||