first commit

This commit is contained in:
编码猿
2024-09-27 01:15:47 +08:00
commit 8be1fcce6b
155 changed files with 9435 additions and 0 deletions

29
json-to-class/.gitignore vendored Normal file
View File

@@ -0,0 +1,29 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
test.json
笔记.txt
package-lock.json
stats.html
src-tauri/target/*
node_modules
dist
dist-ssr
*.local
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

1
json-to-class/.pydio Normal file
View File

@@ -0,0 +1 @@
2b79c44f-8eec-46bb-8888-ea29805a9038

89
json-to-class/README.md Normal file
View File

@@ -0,0 +1,89 @@
<p align="center">
<img style="width: 50px;height: 50px;" src="build/img/icon_128x128.png"/>
</p>
<p align="center">
<strong>JsonToClass</strong>
</p>
<p align="center">
帮助 TypeScript 项目为API接口数据自动生成 TypeScript 类型
</p>
<p align="center">
<a href="https://svelte.dev/">
<img src="https://img.shields.io/badge/svelte-v4.0.5-orange" alt="svelte">
</a>
<a href="https://beta.tauri.app/">
<img src="https://img.shields.io/badge/tauri-v2.0.0-brightgreen" alt="tauri">
</a>
<a href="https://www.typescriptlang.org/">
<img src="https://img.shields.io/badge/typescript-v5.0.2-blue" alt="typescript">
</a>
<a href="https://vitejs.dev/">
<img src="https://img.shields.io/badge/vite-v4.4.4-orange" alt="vitejs">
</a>
<a href="https://www.npmjs.com/package/json-class-interface">
<img src="https://img.shields.io/badge/json__class__interface-v1.1.3-brightgreen" alt="json-class-interface">
</a>
</p>
该软件是本人npm 插件 **[json-class-interface](https://www.npmjs.com/package/json-class-interface)** 的桌面端,为了方便使用所以开发!但为了学习新技术点,所以舍弃大而慢占内存的 electron谁还用 electron你用 electron 落伍了...
**`Tauri`谁用谁知道本项目打包后在Macos上可执行`app`才只有`5.5MB``dmg`可视化安装程序`3.1MB``app`还能再次优化到`2MB`
左右!!**
> 使用场景:本软件可以用在任意 TypeScript 项目中!只要你调接口了,需要为接口返回数据编写类型,那么就可以用。同时为了解耦接口数据字段 和 页面 的深度绑定,可以使用本人的另一个插件 [json-mapper-class](https://www.npmjs.com/package/json-mapper-class)
## 技术栈
- **Tauri**: 基于 `Rust` 的全新桌面端开发框架这里使用2.x版本 **注意: 2.x作者还未开发完成坑非常多慎入项目中用 1.x 即可**
- **Rust**: `Mozilla`开发的为了替代`C++`的系统级编程语言,不建议前端轻易尝试学习
- **Svelte**: 更快更高效更简单好用的 `Vue` 框架 替代者 & 竞争者!
- **Vite**: 更好用快速的 **新型前端构建工具**
- **TypeScript**: 基于 `JavaScript` 构建的强类型编程语言
- **monaco-editor**: `vscode` 的代码编辑器
- **json-class-interface**: 本人的`JSON`转换插件,强烈建议搭配我的另外一个插件 [json-mapper-class](https://www.npmjs.com/package/json-mapper-class) 一起使用
- **svelte-spa-router**: `svelte`的第三方路由
- **svelte-ui**: 唯一还能将就用的 `svelte` 第三方UI框架
## 已实现的功能
- [x] 1: `Json` 转换为 `Class`
- [x] 2: `Json` 转换为 `Interface` 接口
- [x] 3: 转换为**类**时候 自动生成 属性装饰器 `property`
- [x] 4: 转换为**类**时候,可以通过**设置**决定是否为 属性装饰器 `property` 开启默认值
- [x] 5: 可选 `Json` 数据中 `Value``null` 的类型
- [x] 6: **自动存储** 生成 的代码 到 **你指定的路径**,并**配置文件名**
- [x] 7: 手动 切换 **白天模式 & 夜间模式**,或是 **跟随操作系统自动切换**
- [x] 8: 开关 **代码行号**
- [x] 9: 开关 **代码小地图**
- [x] 10: 开关 自动粘贴代码 进入**剪贴板**
- [x] 11: 开机自启
- [x] 12: 软件升级
- [x] 13: 启动欢迎页面
## Windows & MacOs & Linux 下载
**下载地址:** [releases](https://gitee.com/bmycode/json-class-desktop/releases)
**文件说明:**
- Windows 版本JsonToClass_x.x.x_x64-setup.exe
- MacOs 版本JsonToClass_x.x.x_x64.dmg
- Linux 版本JsonToClass_x.x.x_amd64.deb
**注意事项:**
1MacOs 端由于没有`Apple`开发者账号无法进行软件签名,所以安装后打开的时候会提示风险,无法打开,具体参考这篇教程:
[https://blog.csdn.net/m0_37482190/article/details/128957808](https://blog.csdn.net/m0_37482190/article/details/128957808)
2**代码更新速度较快,所以 安装包 落后于 最新代码,有能力的推荐自己部署 Rust + Tauri 环境然后对代码进行打包即可!!!**
## 软件展示
![0](build/img/0.png)
![1](build/img/1.png)
![2](build/img/2.png)
![3](build/img/3.png)
![4](build/img/4.png)
![5](build/img/5.png)
![6](build/img/6.png)

View File

@@ -0,0 +1 @@
4408a16a-b5c1-47d5-9698-a27572ed5880

Binary file not shown.

View File

@@ -0,0 +1 @@
785daa35-f2c9-409b-ac24-288dc7e2af46

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

13
json-to-class/build/icns.sh Executable file
View File

@@ -0,0 +1,13 @@
#!/bin/bash
sips -z 16 16 JsonToClass.png --out JsonToClass.iconset/icon_16x16.png
sips -z 32 32 JsonToClass.png --out JsonToClass.iconset/icon_16x16@2x.png
sips -z 32 32 JsonToClass.png --out JsonToClass.iconset/icon_32x32.png
sips -z 64 64 JsonToClass.png --out JsonToClass.iconset/icon_32x32@2x.png
sips -z 128 128 JsonToClass.png --out JsonToClass.iconset/icon_128x128.png
sips -z 256 256 JsonToClass.png --out JsonToClass.iconset/icon_128x128@2x.png
sips -z 256 256 JsonToClass.png --out JsonToClass.iconset/icon_256x256.png
sips -z 512 512 JsonToClass.png --out JsonToClass.iconset/icon_256x256@2x.png
sips -z 512 512 JsonToClass.png --out JsonToClass.iconset/icon_512x512.png
sips -z 512 512 JsonToClass.png --out JsonToClass.iconset/icon_512x512@2x.png
iconutil -c icns JsonToClass.iconset -o JsonToClass.icns

View File

@@ -0,0 +1 @@
ee0f13d5-2393-42c0-9f2c-b24b7071070f

Binary file not shown.

After

Width:  |  Height:  |  Size: 293 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

14
json-to-class/index.html Normal file
View File

@@ -0,0 +1,14 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="./iconfont/iconfont.css">
<title></title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>

View File

@@ -0,0 +1,47 @@
{
"name": "json-to-class",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview",
"check": "svelte-check --tsconfig ./tsconfig.json",
"tauri-dev": "tauri dev",
"tauri-build": "tauri build",
"tauri": "tauri"
},
"dependencies": {
"@svelteuidev/composables": "^0.15.3",
"@svelteuidev/core": "^0.15.3",
"@tauri-apps/api": "^2.0.0-alpha.11",
"@tauri-apps/plugin-autostart": "^2.0.0-alpha.3",
"@tauri-apps/plugin-clipboard-manager": "^2.0.0-alpha.3",
"@tauri-apps/plugin-dialog": "^2.0.0-alpha.3",
"@tauri-apps/plugin-fs": "^2.0.0-alpha.3",
"@tauri-apps/plugin-notification": "^2.0.0-alpha.3",
"@tauri-apps/plugin-shell": "^2.0.0-alpha.3",
"@tauri-apps/plugin-window": "^2.0.0-alpha.1",
"json-class-interface": "^1.1.7",
"monaco-editor": "^0.43.0",
"svelte-spa-router": "^3.3.0"
},
"devDependencies": {
"@sveltejs/vite-plugin-svelte": "^2.4.2",
"@tauri-apps/cli": "^2.0.0-rc.3",
"@tsconfig/svelte": "^5.0.0",
"@types/node": "^20.9.0",
"internal-ip": "^7.0.0",
"less": "^4.2.0",
"reflect-metadata": "^0.1.13",
"rollup-plugin-visualizer": "^5.9.2",
"svelte": "^4.0.5",
"svelte-check": "^3.4.6",
"svelte-preprocess-less": "^0.4.0",
"tslib": "^2.6.0",
"typescript": "^5.0.2",
"vite": "^4.4.4",
"vite-plugin-monaco-editor": "^1.1.0"
}
}

View File

@@ -0,0 +1 @@
217a9024-c835-4293-9269-e7be2a8dd55f

View File

@@ -0,0 +1 @@
9b4a28d6-e012-4f66-bc67-f102e825d19a

View File

@@ -0,0 +1,91 @@
@font-face {
font-family: "iconfont"; /* Project id 4318577 */
src: url('./iconfont.woff2?t=1700074221843') format('woff2'),
url('./iconfont.woff?t=1700074221843') format('woff'),
url('./iconfont.ttf?t=1700074221843') format('truetype');
}
.iconfont {
font-family: "iconfont", serif !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.json-guanyu:before {
content: "\e60b";
}
.json-cuowutishi-copy:before {
content: "\e7a2";
}
.json-wenjianjia:before {
content: "\e67c";
}
.json-sucai:before {
content: "\e603";
}
.json-open-folder:before {
content: "\e677";
}
.json-json:before {
content: "\e7bd";
}
.json-cunchuqia:before {
content: "\e638";
}
.json-cunchu:before {
content: "\e602";
}
.json-gengduo:before {
content: "\ec1c";
}
.json-shezhi:before {
content: "\e628";
}
.json-gengduo1:before {
content: "\e63f";
}
.json-shezhi2:before {
content: "\e6a9";
}
.json-shezhi-xitongshezhi:before {
content: "\e600";
}
.json-moon:before {
content: "\e6c2";
}
.json-wo:before {
content: "\e60f";
}
.json-wodewo:before {
content: "\e6df";
}
.json-31shezhi:before {
content: "\e601";
}
.json-shezhi1:before {
content: "\e8b7";
}
.json-taiyang:before {
content: "\e709";
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1 @@
7809e461-c368-4067-ae5e-0f0fdcd86be9

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

View File

@@ -0,0 +1,159 @@
<!--
~ Copyright (c) 2023.
~
~ 作者bmy
~ 邮箱2271608011@qq.com
~ giteehttps://gitee.com/bmycode
~ githubhttps://github.com/helpcode
~
-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
body,ul,li,p,a{
font-family: "Al Bayan", serif;
list-style: none;
margin: 0;
padding: 0;
text-decoration: none;
}
.main {
width: 100%;
height: 100vh;
display: flex;
align-items: center;
flex-direction: column;
padding-top: 60px;
box-sizing: border-box;
}
.main img {
width: 150px;
height: 150px;
}
.main .name {
font-size: 18px;
letter-spacing: 1px;
}
.main .desc {
font-size: 13px;
color: #bdbdbd;
}
.loading,
.loading > div {
position: relative;
box-sizing: border-box;
}
.loading {
display: block;
font-size: 0;
color: #bdbdbd;
margin-top: 20px;
}
.loading.la-dark {
color: #333;
}
.loading > div {
display: inline-block;
float: none;
background-color: currentColor;
border: 0 solid currentColor;
}
.loading > div {
width: 10px;
height: 10px;
border-radius: 100%;
}
.loading > div:first-child {
transform: translateX(0%);
animation: ball-newton-cradle-left 1s 0s ease-out infinite;
}
.loading > div:last-child {
transform: translateX(0%);
animation: ball-newton-cradle-right 1s 0s ease-out infinite;
}
.loading.la-sm {
width: 20px;
height: 4px;
}
.loading.la-sm > div {
width: 4px;
height: 4px;
}
.loading.la-2x {
width: 80px;
height: 20px;
}
.loading.la-2x > div {
width: 20px;
height: 20px;
}
.loading.la-3x {
width: 120px;
height: 30px;
}
.loading.la-3x > div {
width: 30px;
height: 30px;
}
@keyframes ball-newton-cradle-left {
25% {
transform: translateX(-100%);
animation-timing-function: ease-in;
}
50% {
transform: translateX(0%);
}
}
@keyframes ball-newton-cradle-right {
50% {
transform: translateX(0%);
}
75% {
transform: translateX(100%);
animation-timing-function: ease-in;
}
100% {
transform: translateX(0%);
}
}
</style>
</head>
<body>
<div class="main" data-tauri-drag-region>
<img src="./img/JsonToClass.png" alt="">
<p class="name">Json To Class</p>
<p class="desc">帮助您更快编码</p>
<div class="loading">
<div></div>
<div></div>
<div></div>
<div></div>
</div>
</div>
</body>
</html>

4
json-to-class/src-tauri/.gitignore vendored Normal file
View File

@@ -0,0 +1,4 @@
# Generated by Cargo
# will have compiled files and executables
/target/

View File

@@ -0,0 +1 @@
66a6e945-2049-4334-8fa1-a7f788930e3e

5061
json-to-class/src-tauri/Cargo.lock generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,50 @@
[package]
name = "json-to-calss"
version = "1.0.2"
description = "json转换为类或接口的桌面端工具"
authors = ["bmy"]
license = ""
repository = ""
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[lib]
name = "tauri_app_lib"
crate-type = ["staticlib", "cdylib", "rlib"]
[build-dependencies]
tauri-build = { version = "2.0.0-alpha.11", features = [] }
[dependencies]
# devtools
tauri = { version = "2.0.0-alpha.17", features = ["macos-private-api"] }
# 窗口
tauri-plugin-window = "2.0.0-alpha.2"
# shell 命令行
tauri-plugin-shell = "2.0.0-alpha.4"
# 开机自启
tauri-plugin-autostart = "2.0.0-alpha.4"
# 通知
tauri-plugin-notification = "2.0.0-alpha.5"
# fs 文件系统
tauri-plugin-fs = "2.0.0-alpha.4"
# 剪切板插件
tauri-plugin-clipboard-manager = "2.0.0-alpha.4"
# dialog
tauri-plugin-dialog = "2.0.0-alpha.4"
serde_json = "1.0"
window-vibrancy = "0.4.3"
[profile.release]
panic = "abort" # Strip expensive panic clean-up logic
codegen-units = 1 # Compile crates one after another so the compiler can optimize better
lto = true # Enables link to optimizations
opt-level = "s" # Optimize for binary size
strip = true # Remove debug symbols
[features]
# this feature is used for production builds or when `devPath` points to the filesystem
# DO NOT REMOVE!!
custom-protocol = ["tauri/custom-protocol"]

View File

@@ -0,0 +1,3 @@
fn main() {
tauri_build::build()
}

View File

@@ -0,0 +1 @@
f9e7ed09-d338-436e-855a-9f6dc62c18fd

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View File

@@ -0,0 +1 @@
91c2e4ee-c16f-45aa-8b97-593e9240f4fe

View File

@@ -0,0 +1,76 @@
use tauri_plugin_autostart::MacosLauncher;
use std::io::Write;
use tauri::{ Manager };
use window_vibrancy::{apply_blur, apply_vibrancy, apply_acrylic, apply_mica, NSVisualEffectMaterial};
#[tauri::command]
fn greet(name: &str) -> String {
format!("Hello, {}! You've been greeted from Rust!", name)
}
// 帮助前端 将 文件保存到本地,不使用 tauri 的原因是其 fs 模块的
// 文件的访问权限控制无法实现此功能
#[tauri::command]
fn created_file(name: &str, content: &str) -> String {
let mut file = std::fs::File::create(name).expect("create file error");
file.write_all(content.as_bytes()).expect("write file error");
format!("ok")
}
#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
tauri::Builder::default()
.setup(|app|
{
let splashscreen_window = app.get_window("splashscreen").unwrap();
let main_window = app.get_window("main").unwrap();
#[cfg(target_os = "macos")]
apply_vibrancy(&main_window, NSVisualEffectMaterial::HudWindow, None, None)
.expect("Unsupported platform! 'apply_vibrancy' is only supported on macOS");
#[cfg(target_os = "windows")]
apply_blur(&main_window, Some((5, 5, 5, 0)))
.expect("Unsupported platform! 'apply_blur' is only supported on Windows");
tauri::async_runtime::spawn(async move {
std::thread::sleep(std::time::Duration::from_secs(2));
splashscreen_window.close().unwrap();
main_window.show().unwrap();
// main_window.open_devtools()
});
Ok(())
})
// .on_window_event(|event| {
// let handle = event.window().app_handle();
// let label = event.window().label();
// match event.event() {
// WindowEvent::Focused(focused) => {
// println!("WindowEvent::Focused ==> {:?} {:?}", focused, label);
// if *focused {
// #[cfg(target_os = "macos")]
// match menu::setup_menu(handle, &label) {
// Ok(()) => {}
// Err(err) => println!("Failed to setup menu, {:?}", err),
// }
// }
// }
// _ => {}
// }
// })
.plugin(tauri_plugin_clipboard_manager::init())
.plugin(tauri_plugin_window::init())
.plugin(tauri_plugin_fs::init())
.plugin(tauri_plugin_shell::init())
.plugin(tauri_plugin_notification::init())
.plugin(tauri_plugin_dialog::init())
.plugin(tauri_plugin_autostart::init(MacosLauncher::LaunchAgent, Some(vec!["--flag1", "--flag2"])))
.invoke_handler(tauri::generate_handler![greet, created_file ])
.run(tauri::generate_context!())
.expect("error while running tauri application");
}

View File

@@ -0,0 +1,6 @@
// Prevents additional console window on Windows in release, DO NOT REMOVE!!
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
fn main() {
tauri_app_lib::run()
}

View File

@@ -0,0 +1,64 @@
use tauri::{
menu::{
CheckMenuItemBuilder, MenuBuilder, MenuItemBuilder, PredefinedMenuItem,
SubmenuBuilder,
},
AppHandle,
};
pub fn setup_menu(
handle: &AppHandle,
label: &str,
) -> Result<(), Box<dyn std::error::Error>> {
let pkg_info = handle.package_info();
let app_name = &pkg_info.name.clone();
let app_menu = SubmenuBuilder::new(handle, app_name).quit().build()?;
let ab_menu = SubmenuBuilder::new(handle, "关于作者")
.items(&[
&PredefinedMenuItem::about(handle, Some("关于"), None),
]).build()?;
let native_menu = SubmenuBuilder::new(handle, "NativeMenu")
.items(&[
&PredefinedMenuItem::about(handle, Some("关于"), None),
&PredefinedMenuItem::services(handle, Some("服务")),
&PredefinedMenuItem::hide(handle, Some("隐藏")),
&PredefinedMenuItem::hide_others(handle, Some("隐藏其他")),
&PredefinedMenuItem::show_all(handle, Some("显示全部")),
&PredefinedMenuItem::quit(handle, Some("退出")),
&PredefinedMenuItem::close_window(handle, Some("关闭窗口")),
&PredefinedMenuItem::undo(handle, Some("撤销")),
&PredefinedMenuItem::redo(handle, Some("重做")),
&PredefinedMenuItem::cut(handle, Some("剪切")),
&PredefinedMenuItem::copy(handle, Some("拷贝")),
&PredefinedMenuItem::paste(handle, Some("粘贴")),
&PredefinedMenuItem::select_all(handle, Some("全选")),
&PredefinedMenuItem::fullscreen(handle, Some("切换全屏")),
&PredefinedMenuItem::minimize(handle, Some("最小化")),
&PredefinedMenuItem::maximize(handle, Some("最大化")),
])
.build()?;
// only for "win_1"
let custom_menu = SubmenuBuilder::new(handle, "Test")
.item(&MenuItemBuilder::with_id("toggle", "Toggle").build(handle))
.item(&CheckMenuItemBuilder::new("Mark").build(handle))
.build()?;
let mut menus = MenuBuilder::new(handle)
.item(&app_menu)
.item(&custom_menu)
.item(&native_menu);
if label == "win1" {
menus = menus.item(&custom_menu);
}
handle.set_menu(menus.build()?)?;
handle.on_menu_event(move |handle, event| {
println!("event id: {:?}", event.id);
});
Ok(())
}

View File

@@ -0,0 +1,105 @@
{
"build": {
"beforeDevCommand": "npm run dev",
"beforeBuildCommand": "npm run build",
"devPath": "http://localhost:1420",
"distDir": "../dist",
"withGlobalTauri": true
},
"package": {
"productName": "JsonToClass",
"version": "1.0.2"
},
"tauri": {
"macOSPrivateApi": true,
"bundle": {
"active": true,
"targets": [
"app",
"dmg",
"nsis",
"msi",
"deb"
],
"windows": {
"webviewInstallMode": {
"type": "embedBootstrapper"
}
},
"deb": {},
"identifier": "com.bmy.json.to.class",
"publisher": "bmy",
"icon": [
"icons/32x32.png",
"icons/128x128.png",
"icons/128x128@2x.png",
"icons/JsonToClass.icns",
"icons/JsonToClass.ico"
]
},
"security": {
"csp": null
},
"windows": [
{
"label": "main",
"hiddenTitle": true,
"fullscreen": false,
"resizable": true,
"center": true,
"width": 1200,
"height": 900,
"minWidth": 1000,
"minHeight": 800,
"titleBarStyle": "Overlay",
"visible": false,
"transparent": true,
"title": ""
},
{
"title": "JsonToClass - 为API接口数据自动生成 TypeScript 类型",
"width": 300,
"height": 400,
"center": true,
"titleBarStyle": "Overlay",
"resizable": false,
"hiddenTitle": true,
"url": "splashscreen.html",
"label": "splashscreen"
}
]
},
"plugins": {
"os": {
"all": true
},
"app": {
"all": true
},
"shell": {
"open": true
},
"fs": {
"createDir": true,
"exists": true,
"writeTextFile": true,
"readTextFile": true,
"scope": [
"$HOME/.jsontoclass/*",
"$HOME/.jsontoclass",
"$HOME/*"
]
},
"window": {
"all": false,
"close": true,
"hide": true,
"show": true,
"maximize": true,
"minimize": true,
"unmaximize": true,
"unminimize": true,
"startDragging": true
}
}
}

1
json-to-class/src/.pydio Normal file
View File

@@ -0,0 +1 @@
d1da14d5-0645-40a6-b16b-c49b9e0a1670

View File

@@ -0,0 +1,33 @@
<!--
- Copyright (c) 2023.
-
- 作者bmy
- 邮箱2271608011@qq.com
- giteehttps://gitee.com/bmycode
- githubhttps://github.com/helpcode
-
-->
<script lang="ts">
import { themeConfig } from '@/stores/ThemeStore';
import { onMount } from "svelte";
import Router from "svelte-spa-router";
import { SvelteUIProvider } from '@svelteuidev/core';
import routes from "./router";
import ChangeTheme from "@/utils/ChangeTheme";
onMount(async () => {
await ChangeTheme.setThemeRunCode($themeConfig,'app')
});
</script>
<div class="app">
<SvelteUIProvider themeObserver={$themeConfig.theme}>
<Router {routes} />
</SvelteUIProvider>
</div>
<style lang="less">
</style>

View File

@@ -0,0 +1 @@
436db918-fc61-410f-afaa-513f3a7ba3e1

View File

@@ -0,0 +1 @@
95bda494-978b-4aeb-b551-cd3a8dc3e99c

View File

@@ -0,0 +1,12 @@
/*
* Copyright (c) 2023.
*
* 作者bmy
* 邮箱2271608011@qq.com
* giteehttps://gitee.com/bmycode
* githubhttps://github.com/helpcode
*
*/
@import "vars.less";
@import "mixins.less";

View File

@@ -0,0 +1,410 @@
/*
* Copyright (c) 2023.
*
* 作者bmy
* 邮箱2271608011@qq.com
* giteehttps://gitee.com/bmycode
* githubhttps://github.com/helpcode
*
*/
body {
transition: all 0.5s;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
background-color: transparent;
//box-shadow: 0 2px 5px 1px rgb(54 53 53 / 30%);
}
html {
line-height: 1;
-webkit-text-size-adjust: 100%;
}
/* Sections
========================================================================== */
/**
* Remove the margin in all browsers.
*/
body,
ul,
li,
p,
h1,
h2,
h3,
h4,
h5,
h6 {
margin: 0;
padding: 0;
list-style: none;
}
::-webkit-scrollbar {
width: 0;
height: 0;
}
.content {
margin-top: 1rem;
}
/**
* Render the `main` element consistently in IE.
*/
main {
display: block;
}
/**
* Correct the font size and margin on `h1` elements within `section` and
* `article` contexts in Chrome, Firefox, and Safari.
*/
h1 {
font-size: 2em;
margin: 0.67em 0;
}
/* Grouping content
========================================================================== */
/**
* 1. Add the correct box sizing in Firefox.
* 2. Show the overflow in Edge and IE.
*/
hr {
box-sizing: content-box;
/* 1 */
height: 0;
/* 1 */
overflow: visible;
/* 2 */
}
/**
* 1. Correct the inheritance and scaling of font size in all browsers.
* 2. Correct the odd `em` font sizing in all browsers.
*/
pre {
font-family: monospace, monospace;
/* 1 */
font-size: 1em;
/* 2 */
}
/* Text-level semantics
========================================================================== */
/**
* Remove the gray background on active links in IE 10.
*/
a {
background-color: transparent;
text-decoration: none;
color: #000;
}
/**
* 1. Remove the bottom border in Chrome 57-
* 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
*/
abbr[title] {
border-bottom: none;
/* 1 */
text-decoration: underline;
/* 2 */
text-decoration: underline dotted;
/* 2 */
}
/**
* Add the correct font weight in Chrome, Edge, and Safari.
*/
b,
strong {
font-weight: bolder;
}
/**
* 1. Correct the inheritance and scaling of font size in all browsers.
* 2. Correct the odd `em` font sizing in all browsers.
*/
code,
kbd,
samp {
font-family: monospace, monospace;
/* 1 */
font-size: 1em;
/* 2 */
}
/**
* Add the correct font size in all browsers.
*/
small {
font-size: 80%;
}
/**
* Prevent `sub` and `sup` elements from affecting the line height in
* all browsers.
*/
sub,
sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
/* Embedded content
========================================================================== */
/**
* Remove the border on images inside links in IE 10.
*/
img {
border-style: none;
width: 100%;
}
/* Forms
========================================================================== */
/**
* 1. Change the font styles in all browsers.
* 2. Remove the margin in Firefox and Safari.
*/
button,
input,
optgroup,
select,
textarea {
font-family: inherit;
/* 1 */
font-size: 100%;
/* 1 */
line-height: 1.15;
/* 1 */
margin: 0;
/* 2 */
}
/**
* Show the overflow in IE.
* 1. Show the overflow in Edge.
*/
button,
input {
/* 1 */
overflow: visible;
}
/**
* Remove the inheritance of text transform in Edge, Firefox, and IE.
* 1. Remove the inheritance of text transform in Firefox.
*/
button,
select {
/* 1 */
text-transform: none;
}
/**
* Correct the inability to style clickable types in iOS and Safari.
*/
button,
[type="button"],
[type="reset"],
[type="submit"] {
-webkit-appearance: button;
}
/**
* Remove the inner border and padding in Firefox.
*/
button::-moz-focus-inner,
[type="button"]::-moz-focus-inner,
[type="reset"]::-moz-focus-inner,
[type="submit"]::-moz-focus-inner {
border-style: none;
padding: 0;
}
/**
* Restore the focus styles unset by the previous rule.
*/
button:-moz-focusring,
[type="button"]:-moz-focusring,
[type="reset"]:-moz-focusring,
[type="submit"]:-moz-focusring {
outline: 1px dotted ButtonText;
}
/**
* Correct the padding in Firefox.
*/
fieldset {
padding: 0.35em 0.75em 0.625em;
}
/**
* 1. Correct the text wrapping in Edge and IE.
* 2. Correct the color inheritance from `fieldset` elements in IE.
* 3. Remove the padding so developers are not caught out when they zero out
* `fieldset` elements in all browsers.
*/
legend {
box-sizing: border-box;
/* 1 */
color: inherit;
/* 2 */
display: table;
/* 1 */
max-width: 100%;
/* 1 */
padding: 0;
/* 3 */
white-space: normal;
/* 1 */
}
/**
* Add the correct vertical alignment in Chrome, Firefox, and Opera.
*/
progress {
vertical-align: baseline;
}
/**
* Remove the default vertical scrollbar in IE 10+.
*/
textarea {
overflow: auto;
}
/**
* 1. Add the correct box sizing in IE 10.
* 2. Remove the padding in IE 10.
*/
[type="checkbox"],
[type="radio"] {
box-sizing: border-box;
/* 1 */
padding: 0;
/* 2 */
}
/**
* Correct the cursor style of increment and decrement buttons in Chrome.
*/
[type="number"]::-webkit-inner-spin-button,
[type="number"]::-webkit-outer-spin-button {
height: auto;
}
/**
* 1. Correct the odd appearance in Chrome and Safari.
* 2. Correct the outline style in Safari.
*/
[type="search"] {
-webkit-appearance: textfield;
/* 1 */
outline-offset: -2px;
/* 2 */
}
/**
* Remove the inner padding in Chrome and Safari on macOS.
*/
[type="search"]::-webkit-search-decoration {
-webkit-appearance: none;
}
/**
* 1. Correct the inability to style clickable types in iOS and Safari.
* 2. Change font properties to `inherit` in Safari.
*/
::-webkit-file-upload-button {
-webkit-appearance: button;
/* 1 */
font: inherit;
/* 2 */
}
/* Interactive
========================================================================== */
/*
* Add the correct display in Edge, IE 10+, and Firefox.
*/
details {
display: block;
}
/*
* Add the correct display in all browsers.
*/
summary {
display: list-item;
}
/* Misc
========================================================================== */
/**
* Add the correct display in IE 10+.
*/
template {
display: none;
}
/**
* Add the correct display in IE 10.
*/
[hidden] {
display: none;
}

View File

@@ -0,0 +1,67 @@
/*
* Copyright (c) 2023.
*
* 作者bmy
* 邮箱2271608011@qq.com
* giteehttps://gitee.com/bmycode
* githubhttps://github.com/helpcode
*
*/
@import "vars";
.line (@position: left) {
border-@{position}: 1px solid @background;
}
.padding(@top: 0px, @right: 0px, @bottom: 0px, @left: 0px) {
padding: @top @right @bottom @left;
box-sizing: border-box;
}
.clearfix() {
&:after,
&:before {
content: " ";
display: table;
}
&:after {
clear: both;
}
}
// No Scrollbar
.no-scrollbar() {
&::-webkit-scrollbar {
display: none !important;
width: 0 !important;
height: 0 !important;
-webkit-appearance: none;
opacity: 0 !important;
}
}
.ellipsis() {
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
word-wrap: break-word;
}
.flex(@align: center, @justify: center) {
display: flex;
align-items: @align;
justify-content: @justify;
}
//超出显示省略号
.ellipsis() {
overflow: hidden; //超出的文本隐藏
text-overflow: ellipsis; //溢出用省略号显示
white-space: nowrap; //溢出不换行
}

View File

@@ -0,0 +1,10 @@
/*
* Copyright (c) 2023.
*
* 作者bmy
* 邮箱2271608011@qq.com
* giteehttps://gitee.com/bmycode
* githubhttps://github.com/helpcode
*
*/

View File

@@ -0,0 +1,15 @@
/*
* Copyright (c) 2023.
*
* 作者bmy
* 邮箱2271608011@qq.com
* giteehttps://gitee.com/bmycode
* githubhttps://github.com/helpcode
*
*/
@background: var(--background, #d5d0d0);
@color: var(--color, #000);
@activeBackgroundColor: var(--activeBackgroundColor, #fff);

View File

@@ -0,0 +1 @@
04b3a9f6-9b82-42fb-bec3-fe3f1e287f07

View File

@@ -0,0 +1,111 @@
<!--
- Copyright (c) 2023.
-
- 作者bmy
- 邮箱2271608011@qq.com
- giteehttps://gitee.com/bmycode
- githubhttps://github.com/helpcode
-
-->
<script lang="ts">
import { onMount } from "svelte";
import Layout from "@/component/layout.svelte";
import { Stack, Badge } from '@svelteuidev/core';
// 这个插件内部用的是 window.__TAURI_INVOKE__ 和 RUST 通讯,
// 而 __TAURI_INVOKE__ 不存在,在 tauri 1.x 中 是 window.__TAURI__.invoke
// 在 tauri 2.x 中 是 @tauri-apps/api/primitives 包中 的 invoke 方法
// 这个 __TAURI_INVOKE__ 本身就错误!! 所以 @tauri-apps/plugin-app 包无法使用
// 修改 @tauri-apps/plugin-app 包中 通讯代码 虽然可以运行,但也毫无意义,重新下载
// 依赖后还是要继续修改代码否则还是报错,所以放弃 存在问题 tauri 2.x ,使用 1.x 的
// 全局变量!!!
// import { getVersion, getName } from "@tauri-apps/plugin-app";
let { getVersion, getName, getTauriVersion } = window.__TAURI__.app
import gitee from "@/serve/gitee";
import { message } from "@tauri-apps/plugin-dialog";
import { open } from '@tauri-apps/plugin-shell';
import Notification from "@/utils/Notification";
let appName: string;
let appVersion: string;
let TauriVersion: string;
onMount(async () => {
appName = await getName();
appVersion = await getVersion();
TauriVersion = await getTauriVersion();
})
const checkUpdate = async () => {
let res = await gitee.ReleasesLatest();
// 如果新版本 大于 当前版本,提示升级
if (gitee.compare(res.tag_name, appVersion)) {
await message(res.body, {
title: `检测到新版本: v${res.tag_name}`, type: 'info',
okLabel: '升级',
});
await open(res.assets[0].browser_download_url);
} else {
await Notification.send({
title: '提示',
body: `当前 v${appVersion} 已是最新版本啦!`
})
}
}
</script>
<div class="about">
<Layout text="关于软件">
<img src="/img/JsonToClass.png" alt="">
<Stack override={{ height: 200 }} align="strech" justify="flex-start" spacing="lg">
<div class="desc">
<p><span>名称:</span>{appName}</p>
<p>
<span>版本:</span>v{appVersion}
<Badge class="update" on:click={checkUpdate} radius="lg" variant="outline">
检查更新
</Badge>
</p>
<p><span>Tauri</span>v{TauriVersion} beta </p>
<p><span>源码:</span>https://gitee.com/bmycode/json-class-desktop</p>
</div>
<div class="desc">
<p><span>作者:</span>Bmy</p>
<p><span>邮箱:</span>2271608011@qq.com</p>
<p><span>Github</span>https://github.com/helpcode</p>
<p><span>Gitee</span>https://gitee.com/bmycode</p>
</div>
</Stack>
</Layout>
</div>
<style lang="less">
@import "../assets/less/_.less";
.about {
:global(.update){
cursor: pointer;
}
img {
width: 250px;
height: 250px;
}
.desc {
margin-left: 30px;
p {
margin-bottom: 10px;
font-size: 16px;
color: @color;
span {
//font-weight: 500;
}
}
}
}
</style>

View File

@@ -0,0 +1,90 @@
<!--
- Copyright (c) 2023.
-
- 作者bmy
- 邮箱2271608011@qq.com
- giteehttps://gitee.com/bmycode
- githubhttps://github.com/helpcode
-
-->
<script lang="ts">
import { onMount } from "svelte";
import Layout from '@/component/layout.svelte';
import { NativeSelect, RadioGroup } from '@svelteuidev/core';
import config from '@/config';
import { themeConfig } from '@/stores/ThemeStore';
import JsonDatabase from "@/utils/JsonDatabase";
let JsonTypeSelect = String($themeConfig.JsonType)
let needPropertySelect = String($themeConfig.needProperty)
let needPropertyValueSelect = String($themeConfig.needPropertyValue)
let NullAliasSelect = $themeConfig.nullAlias
let NullAliasList = ['string', 'number', 'object', 'any']
onMount(() => {
});
</script>
<div class="basis">
<Layout text="基础设置">
<RadioGroup
label="JSON转化为: "
description="将json转化为 class 类 还是 interface 接口"
direction="column"
labelDirection="left"
items={config.offOrOnList(1)}
bind:value={JsonTypeSelect}
on:change={() => {
$themeConfig.JsonType = Number(JsonTypeSelect)
JsonDatabase.writeJson($themeConfig)
}}/>
<RadioGroup
label="Property 装饰器: "
description="选择 class 后,是否为类自动生成 json-mapper-class 插件的 Property 装饰器"
direction="column"
labelDirection="left"
items={config.offOrOnList()}
bind:value={needPropertySelect}
on:change={() => {
$themeConfig.needProperty = Number(needPropertySelect)
JsonDatabase.writeJson($themeConfig)
}}/>
<RadioGroup
label="Property 装饰器默认值: "
description="为 Property 装饰器自动生成默认值"
direction="column"
labelDirection="left"
items={config.offOrOnList()}
bind:value={needPropertyValueSelect}
on:change={() => {
$themeConfig.needPropertyValue = Number(needPropertyValueSelect)
JsonDatabase.writeJson($themeConfig)
}}/>
<NativeSelect data={NullAliasList}
placeholder=""
bind:value={NullAliasSelect}
label="null 默认类型: "
on:input={() => {
$themeConfig.nullAlias = NullAliasSelect
JsonDatabase.writeJson($themeConfig)
}}
description="如果JOSN中某对象的值为 null转化为 class interface 时候给这个对象key个默认类型"
/>
</Layout>
</div>
<style lang="less">
@import "../assets/less/_.less";
.basis {
}
</style>

View File

@@ -0,0 +1,157 @@
<!--
- Copyright (c) 2023.
-
- 作者bmy
- 邮箱2271608011@qq.com
- giteehttps://gitee.com/bmycode
- githubhttps://github.com/helpcode
-
-->
<script lang="ts">
import { onDestroy, onMount } from "svelte";
import { MonacoEditor } from "@/utils/MonacoEditor";
import config from "@/config";
import { toClass } from "json-class-interface";
import { themeConfig } from '@/stores/ThemeStore';
import { ToClassOptions } from "json-class-interface/dist/typing";
import Notification from "@/utils/Notification";
import { invoke } from "@tauri-apps/api/primitives";
import { writeText } from '@tauri-apps/plugin-clipboard-manager';
let JsonDom: HTMLElement;
let ClassOrInterfaceDom: HTMLElement;
let unlisten;
onMount(() => {
initEdit()
initResized()
});
/**
* 窗口尺寸变化时候,重新计算 编辑器 的两个宽高
*/
const initResized = async () => {
unlisten = await config.appWindow.onResized(({ payload: size }) => {
let reSize = size
reSize.width = reSize.width / 2 / 2 - 105
reSize.height = reSize.height / 2 / 2 - 35
config.Json.layout(reSize)
config.ClassOrInterface.layout(reSize)
})
}
const initEdit = () => {
// 创建两个编辑器
config.Json = MonacoEditor.creatMonacoEditor(JsonDom)
config.ClassOrInterface = MonacoEditor.creatMonacoEditor(ClassOrInterfaceDom)
// 对json编辑器输入内容进行监听
config.Json.onDidChangeModelContent(async e => {
if (config.Json.getValue().length != 0) {
// 使用本地存储的 toClass 配置
let toClassOptions: ToClassOptions = {
nullAlias : $themeConfig.nullAlias,
needProperty : Boolean($themeConfig.needProperty),
needPropertyValue: Boolean($themeConfig.needPropertyValue),
interfaceModel : Boolean($themeConfig.JsonType)
}
// 如果设置文件名,那么第一层类名或接口名使用文件名,否则使用默认
let className: string =
$themeConfig.saveFileName.length != 0
? $themeConfig.saveFileName
: Boolean($themeConfig.JsonType)
? 'JsonToInterface'
: 'JsonToClass'
let Result: string = toClass(className, config.Json.getValue(), toClassOptions)
Result = autoImport(Result)
config.ClassOrInterface.setValue(Result)
await isAutoClipboard(Result)
await isAutoSave(Result)
} else {
config.ClassOrInterface.setValue("")
}
})
}
/**
* 是否自动复制到粘贴板
* @param Result
*/
const isAutoClipboard = async (Result: string) => {
if ($themeConfig.autoClipboard) {
// 将内容粘贴到你的剪贴板
await writeText(Result);
await Notification.send({
title: '提示',
body: '代码已粘贴到剪贴板Ctrl + V 使用吧'
})
}
}
/**
* 如果是类,自动导包,如果开启 needProperty自动导入 property 装饰器
* @param Result
*/
const autoImport = (Result: string): string => {
if (!$themeConfig.JsonType) {
Result =`import { toClass${$themeConfig.needProperty ? ', property ' : ''} } from 'json-mapper-class';
${Result}`
}
return Result
}
/**
* 如果开启 自动存储 ,那么存储文件到路径
* @param Result
*/
const isAutoSave = async (Result: string) => {
if ($themeConfig.autoSave) {
// 调用 rust 封装的方法,进行文件存储
await invoke("created_file", {
name: `${$themeConfig.savePath}/${$themeConfig.saveFileName}.ts`,
content: Result
});
await Notification.send({
title: '提示',
body: `${$themeConfig.saveFileName}.ts 已保存在 ${$themeConfig.savePath}`
})
}
}
onDestroy(() => {
unlisten()
})
</script>
<div class="edit">
<div class="json" bind:this={JsonDom}></div>
<div class="interface" bind:this={ClassOrInterfaceDom}></div>
</div>
<style lang="less">
.edit {
display: flex;
height: 100%;
.json,
.interface {
height: 100%;
flex: 1;
}
.json {
}
.interface {
}
}
</style>

View File

@@ -0,0 +1,44 @@
<!--
- Copyright (c) 2023.
-
- 作者bmy
- 邮箱2271608011@qq.com
- giteehttps://gitee.com/bmycode
- githubhttps://github.com/helpcode
-
-->
<script lang="ts">
import { onMount } from "svelte";
export let text: string = ""
onMount(() => {
});
</script>
<div class="title" data-tauri-drag-region>{text}</div>
<div class="content">
<slot></slot>
</div>
<style lang="less">
@import "../assets/less/_.less";
.title {
font-size: 20px;
height: 45px;
line-height: 45px;
color: @color;
.line(bottom);
font-family: "Al Bayan", serif;
margin-bottom: 20px;
margin-left: 26px;
box-sizing: border-box;
}
.content {
.padding(0,0,0,26px);
}
</style>

View File

@@ -0,0 +1,182 @@
<!--
- Copyright (c) 2023.
-
- 作者bmy
- 邮箱2271608011@qq.com
- giteehttps://gitee.com/bmycode
- githubhttps://github.com/helpcode
-
-->
<script lang="ts">
import { onMount } from "svelte";
import Layout from '@/component/layout.svelte';
import { RadioGroup } from '@svelteuidev/core';
import ChangeTheme from '@/utils/ChangeTheme';
import { themeConfig } from '@/stores/ThemeStore';
import config from "@/config";
import JsonDatabase from "@/utils/JsonDatabase";
import AutoStart from "@/utils/AutoStart";
import * as monaco from 'monaco-editor';
let AutoLoginStartSelect = String($themeConfig.autoLoginStart);
let LineNumbersSelect = String($themeConfig.lineNumbers);
let MinimapSelect = String($themeConfig.minimap);
let AutoClipboardSelect = String($themeConfig.autoClipboard);
let ThemeSelect = $themeConfig.theme;
const ThemeList = [
{ label: '白天模式', value: "light", src: "/img/light.png" },
{ label: '夜间模式', value: "dark", src: "/img/dark.png" },
{ label: '跟随系统', value: "auto", src: "/img/auto.png" }
];
const SelectChangeTheme = async (index: number) => {
let ClickValue = ThemeList[index].value
if (ClickValue !== "auto") {
$themeConfig.theme = ClickValue
$themeConfig.autoThemeSystem = 0
} else {
$themeConfig.theme = await config.appWindow.theme()
$themeConfig.autoThemeSystem = 1
}
await ChangeTheme.setThemeRunCode($themeConfig)
}
const updateEdit = () => {
config.Json.updateOptions({
lineNumbers: $themeConfig.lineNumbers,
minimap: {
enabled: Boolean($themeConfig.minimap)
}
})
config.ClassOrInterface.updateOptions({
lineNumbers: $themeConfig.lineNumbers,
minimap: {
enabled: Boolean($themeConfig.minimap)
}
})
}
onMount(async () => {
});
</script>
<div class="other">
<Layout text="其他设置">
<div class="theme">
<div class="title_theme">主题设置:</div>
<ul class="select_theme">
{#each ThemeList as {label, value, src}, i}
<li>
<img
on:click={() => SelectChangeTheme(i)}
src={src}
alt={label}>
<p>{label}</p>
</li>
{/each}
</ul>
</div>
<RadioGroup
label="行号: "
description="开启后 编辑区域 将显示代码 行号"
direction="column"
labelDirection="left"
items={config.offOrOnList(2)}
bind:value={LineNumbersSelect}
on:change={() => {
monaco.editor
$themeConfig.lineNumbers = LineNumbersSelect
JsonDatabase.writeJson($themeConfig)
updateEdit()
}}/>
<RadioGroup
label="小地图: "
description="开启后 编辑区域 将显示代码 小地图"
direction="column"
labelDirection="left"
items={config.offOrOnList()}
bind:value={MinimapSelect}
on:change={() => {
$themeConfig.minimap = Number(MinimapSelect)
JsonDatabase.writeJson($themeConfig)
updateEdit()
}}/>
<RadioGroup
label="剪贴板: "
description="开启后,转换后的代码将自动复制到剪贴板"
direction="column"
labelDirection="left"
items={config.offOrOnList()}
bind:value={AutoClipboardSelect}
on:change={() => {
$themeConfig.autoClipboard = Number(AutoClipboardSelect)
JsonDatabase.writeJson($themeConfig)
updateEdit()
}}/>
<RadioGroup
label="开机自启: "
description="开启后 软件 将随着操作系统开机而自启"
direction="column"
labelDirection="left"
items={config.offOrOnList()}
bind:value={AutoLoginStartSelect}
on:change={() => {
let isStart = Number(AutoLoginStartSelect)
isStart ? AutoStart.EnableAutoStart() : AutoStart.DisableAutoStart()
$themeConfig.autoLoginStart = isStart
JsonDatabase.writeJson($themeConfig)
}}/>
</Layout>
</div>
<style lang="less">
@import "../assets/less/_.less";
.other {
.theme {
.title_theme {
font-size: 14px;
font-weight: 500;
color: @color;
margin-bottom: 15px;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
}
.select_theme {
display: flex;
margin-bottom: 25px;
li {
width: 120px;
margin-right: 20px;
text-align: center;
img {
width: 100%;
border-radius: 10px;
border: 1px solid @background;
box-sizing: border-box;
margin-bottom: 10px;
cursor: pointer;
}
p {
font-size: 13px;
color: @color;
}
}
}
}
}
</style>

View File

@@ -0,0 +1,73 @@
<!--
- Copyright (c) 2023.
-
- 作者bmy
- 邮箱2271608011@qq.com
- giteehttps://gitee.com/bmycode
- githubhttps://github.com/helpcode
-
-->
<script lang="ts">
import { onMount } from "svelte";
import Layout from '@/component/layout.svelte';
import { RadioGroup, TextInput } from '@svelteuidev/core';
import config from "@/config";
import { themeConfig } from '@/stores/ThemeStore';
import JsonDatabase from "@/utils/JsonDatabase";
let AutoSaveSelect = String($themeConfig.autoSave);
let SavePathSelect = $themeConfig.savePath
let SaveFileNameSelect = $themeConfig.saveFileName
onMount(() => {
});
</script>
<div class="storage">
<Layout text="存储设置">
<RadioGroup
label="自动存储: "
description="开启后 生成的代码 将自动存储到你指定的 路径"
direction="column"
labelDirection="left"
items={config.offOrOnList()}
bind:value={AutoSaveSelect}
on:change={() => {
$themeConfig.autoSave = Number(AutoSaveSelect)
JsonDatabase.writeJson($themeConfig)
}}/>
<TextInput
label="存储路径: "
bind:value={SavePathSelect}
description="路径需要为 磁盘上的 绝对路径"
styles:width="200px"
on:change={(e) => {
$themeConfig.savePath = SavePathSelect
JsonDatabase.writeJson($themeConfig)
}}>
</TextInput>
<TextInput
label="文件名称: "
description="保存到磁盘的 ts 文件名称,不需要后缀!"
bind:value={SaveFileNameSelect}
on:change={(e) => {
$themeConfig.saveFileName = SaveFileNameSelect
JsonDatabase.writeJson($themeConfig)
}}>
</TextInput>
</Layout>
</div>
<style lang="less">
.storage {
}
</style>

View File

@@ -0,0 +1 @@
93bb09be-1437-4b96-bb91-75f4f49fada3

View File

@@ -0,0 +1,78 @@
/*
* Copyright (c) 2023.
*
* 作者bmy
* 邮箱2271608011@qq.com
* giteehttps://gitee.com/bmycode
* githubhttps://github.com/helpcode
*
*/
import { Window } from '@tauri-apps/plugin-window';
import { editor } from "monaco-editor";
export interface themeType {
background: string;
color: string;
activeBackgroundColor: string;
}
interface configType {
giteeApi: {
releasesUrl: string;
starUser: string
};
JsonDom: editor.IStandaloneCodeEditor | null;
ClassOrInterface: editor.IStandaloneCodeEditor | null;
light: themeType;
dark: themeType;
appWindow: Window,
os: Window,
offOrOnList: (ags?: number) => Record<string, string>[]
}
const config: configType = {
giteeApi: {
releasesUrl: "https://gitee.com/api/v5/repos/bmycode/json-class-desktop/releases/latest",
starUser: "https://gitee.com/api/v5/repos/bmycode/json-class-desktop/stargazers?page=1&per_page=20"
},
JsonDom: null,
ClassOrInterface: null,
// @ts-ignore
appWindow: window.__TAURI__.window.getCurrent(),
os: window.__TAURI__.os,
light: {
// background: "#d5d0d0",
background: "rgba(213, 208, 208, 0.6)",
color: "#000",
activeBackgroundColor: "#fff"
},
dark: {
// background: "#252526",
background: "rgba(0, 0, 0, 0.6)",
color: "#bdbdbd",
activeBackgroundColor: "#1e1e1e"
},
offOrOnList: (type: number = 0) => {
switch (type) {
case 0:
return [
{ label: "开启", value: "1" },
{ label: "关闭", value: "0" }
]
case 1:
return [
{ label: "class", value: "0" },
{ label: "interface", value: "1" }
]
case 2:
return [
{ label: "开启", value: "on" },
{ label: "关闭", value: "off" }
]
}
return []
}
}
export default config

64
json-to-class/src/global.d.ts vendored Normal file
View File

@@ -0,0 +1,64 @@
/*
* Copyright (c) 2023.
*
* 作者bmy
* 邮箱2271608011@qq.com
* giteehttps://gitee.com/bmycode
* githubhttps://github.com/helpcode
*
*/
import { Window as PluginWindow } from "@tauri-apps/plugin-window";
declare module "*.jpg";
declare module "*.png";
declare module "*.woff2";
declare module "*.woff";
declare module "*.ttf";
declare module "*.scss" {
const content: Record<string, string>;
export default content;
}
declare module "*.svg";
type Platform =
| 'linux'
| 'darwin'
| 'ios'
| 'freebsd'
| 'dragonfly'
| 'netbsd'
| 'openbsd'
| 'solaris'
| 'android'
| 'win32'
declare interface Window {
__TAURI__: {
app: {
getVersion(): Promise<string>;
getName(): Promise<string>;
getTauriVersion(): Promise<string>;
},
window: {
getCurrent(): PluginWindow;
},
writeText(text: string): Promise<void>;
invoke(command: string, payload?: Record<string, unknown>): Promise<any>;
dialog: {
save(options?: Record<string, unknown>): Promise<string | null>;
};
fs: {
writeBinaryFile(path: string, data: Uint8Array): Promise<void>;
};
notification:{
requestPermission(): Promise<Permission>;
isPermissionGranted(): Promise<boolean>;
sendNotification(options: string | Options): void;
};
os: {
platform(): Promise<Platform>;
}
};
}

View File

@@ -0,0 +1 @@
b77cc2cc-7867-4666-92af-0cab7a368ad2

View File

@@ -0,0 +1,20 @@
/*
* Copyright (c) 2023.
*
* 作者bmy
* 邮箱2271608011@qq.com
* giteehttps://gitee.com/bmycode
* githubhttps://github.com/helpcode
*
*/
class Http {
public async get(url: string) {
const response = await fetch(url, {
method: "GET",
});
return await response.json()
}
}
export default new Http

21
json-to-class/src/main.ts Normal file
View File

@@ -0,0 +1,21 @@
/*
* Copyright (c) 2023.
*
* 作者bmy
* 邮箱2271608011@qq.com
* giteehttps://gitee.com/bmycode
* githubhttps://github.com/helpcode
*
*/
import "reflect-metadata";
import App from './App.svelte'
import './assets/less/clear.less'
import DataBase from "@/utils/JsonDatabase";
const app = new App({
target: <Element>document.querySelector("#app"),
})
await DataBase.CreatedJsonDataBase()
export default app

View File

@@ -0,0 +1 @@
c2159091-b0fb-432d-9c80-ce002a05e245

View File

@@ -0,0 +1 @@
38117c2b-95c0-4847-8483-a55c44769d40

View File

@@ -0,0 +1,100 @@
/*
* Copyright (c) 2023.
*
* 作者bmy
* 邮箱2271608011@qq.com
* giteehttps://gitee.com/bmycode
* githubhttps://github.com/helpcode
*
*/
@import "../../assets/less/_.less";
.home {
width: 100%;
height: 100vh;
display: flex;
.aside {
width: 70px;
background: @background;
.padding(35px,15px,25px,15px);
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: center;
i {
width: 40px;
height: 40px;
display: flex;
align-items: center;
justify-content: center;
font-size: 25px;
color: @color;
cursor: pointer;
font-weight: lighter;
border-radius: 6px ;
transition: all 0.5s;
&:hover {
background: @activeBackgroundColor;
color: @color;
}
}
.aside_top {
display: flex;
flex-direction: column;
i {
margin-bottom: 25px;
}
.json-shezhi {
font-size: 20px;
}
.active {
background: @activeBackgroundColor;
color: @color;
}
}
.aside_bottom {
font-size: 25px;
}
}
.container {
flex: 1;
display: flex;
flex-direction: column;
.drag {
width: 100%;
height: 35px;
background: @activeBackgroundColor;
}
.main {
display: flex;
flex: 1;
background: @activeBackgroundColor;
.left-drag {
width: 26px;
height: 100%;
}
.wrap {
flex: 1;
}
}
}
}
:global(.svelteui-Group-root) {
margin-top: 14px;
row-gap: 10px;
}
:global(.svelteui-InputWrapper-root) {
margin-bottom: 25px;
}
:global(.svelteui-Input-root) {
width: 350px;
}
:global(.svelteui-InputWrapper-label, .svelteui-Radio-label) {
color: @color !important;
user-select: none;
}

View File

@@ -0,0 +1,69 @@
<!--
- Copyright (c) 2023.
-
- 作者bmy
- 邮箱2271608011@qq.com
- giteehttps://gitee.com/bmycode
- githubhttps://github.com/helpcode
-
-->
<script lang="ts">
import Edit from "@/component/edit.svelte";
import Basis from "@/component/basis.svelte";
import Storage from "@/component/storage.svelte";
import Other from "@/component/other.svelte";
import About from "@/component/about.svelte";
import { themeConfig } from '@/stores/ThemeStore';
import ChangeTheme from "@/utils/ChangeTheme";
let index = 0;
let menu = [
{ id: 1, type: 'edit', title: '首页', icon: 'json-sucai', component: Edit },
{ id: 2, type: 'basis', title: '基础', icon: 'json-shezhi', component: Basis },
{ id: 3, type: 'storage', title: '存储', icon: 'json-cunchuqia', component: Storage },
{ id: 4, type: 'other', title: '其他', icon: 'json-gengduo1', component: Other },
{ id: 4, type: 'about', title: '关于', icon: 'json-guanyu', component: About },
]
const change = async () => {
$themeConfig.autoThemeSystem = 0
$themeConfig.theme = $themeConfig.theme === 'light' ? 'dark' : 'light'
await ChangeTheme.setThemeRunCode($themeConfig)
}
</script>
<div class="home">
<div class="aside" data-tauri-drag-region>
<div class="aside_top">
{#each menu as {icon, component, title}, i}
<i on:click={() => { index = i }}
class:active={i === index}
class="iconfont {icon}">
</i>
{/each}
</div>
<i class="iconfont {$themeConfig.theme === 'light' ? 'json-moon' : 'json-taiyang' } aside_bottom"
on:click={change}>
</i>
</div>
<div class="container">
<div class="drag" data-tauri-drag-region></div>
<div class="main">
{#each menu as {icon, component, title}, i}
<div class="wrap" style:display={ index === i ? '' : 'none' }
style:height="100%">
<svelte:component this={component} />
</div>
{/each}
<div class="left-drag"></div>
</div>
</div>
</div>
<style lang="less">
@import "./home.less";
</style>

View File

@@ -0,0 +1 @@
29f0b147-7c12-4045-b6da-4750f16f1545

View File

@@ -0,0 +1,17 @@
/*
* Copyright (c) 2023.
*
* 作者bmy
* 邮箱2271608011@qq.com
* giteehttps://gitee.com/bmycode
* githubhttps://github.com/helpcode
*
*/
import { wrap } from 'svelte-spa-router/wrap'
export default {
'/': wrap({
asyncComponent: () => import('../pages/home/home.svelte')
})
}

View File

@@ -0,0 +1 @@
2ec43f43-e6a7-4c3d-bf42-4b3a9bb88951

View File

@@ -0,0 +1,48 @@
/*
* Copyright (c) 2023.
*
* 作者bmy
* 邮箱2271608011@qq.com
* giteehttps://gitee.com/bmycode
* githubhttps://github.com/helpcode
*
*/
import Http from "@/http";
import config from "@/config";
import type { ReleasesLatestType } from "@/serve/types/ReleasesLatestType";
class Gitee {
public async ReleasesLatest(): Promise<ReleasesLatestType> {
return await Http.get(config.giteeApi.releasesUrl)
}
/**
*
* @param curV 新版本号
* @param reqV 当前应用的版本号
*/
public compare(curV: string, reqV: string): boolean {
if (curV && reqV) {
//将两个版本号拆成数字
let arr1 = curV.split('.'),
arr2 = reqV.split('.');
let minLength = Math.min(arr1.length, arr2.length),
position = 0,
diff = 0;
//依次比较版本号每一位大小,当对比得出结果后跳出循环(后文有简单介绍)
while (position < minLength && ((diff = parseInt(arr1[position]) - parseInt(arr2[position])) == 0)) {
position++;
}
diff = (diff != 0) ? diff : (arr1.length - arr2.length);
//若curV大于reqV则返回true
return diff > 0;
} else {
//输入为空
return false;
}
}
}
export default new Gitee

View File

@@ -0,0 +1 @@
f6adc4f0-1d33-49e7-a5af-c42808f3978a

View File

@@ -0,0 +1,68 @@
export interface Author {
id: number;
login: string;
name: string;
avatar_url: string;
url: string;
html_url: string;
remark: string;
followers_url: string;
following_url: string;
gists_url: string;
starred_url: string;
subscriptions_url: string;
organizations_url: string;
repos_url: string;
events_url: string;
received_events_url: string;
type: string;
}
export interface Assets {
browser_download_url: string;
name: string;
}
export interface ReleasesLatestType {
id: number;
tag_name: string;
target_commitish: string;
prerelease: boolean;
name: string;
body: string;
author: Author;
created_at: string;
assets: Assets[];
}

View File

@@ -0,0 +1 @@
871ad8b8-3e2f-42e2-b451-26732fceddcd

View File

@@ -0,0 +1,15 @@
/*
* Copyright (c) 2023.
*
* 作者bmy
* 邮箱2271608011@qq.com
* giteehttps://gitee.com/bmycode
* githubhttps://github.com/helpcode
*
*/
import { writable } from 'svelte/store';
import JsonDatabase from '@/utils/JsonDatabase';
// 获取本地所有主题
export const themeConfig = writable(await JsonDatabase.readJson());

View File

@@ -0,0 +1 @@
9d3f3f75-17d1-4359-87d1-0d936e220b6b

View File

@@ -0,0 +1,34 @@
/*
* Copyright (c) 2023.
*
* 作者bmy
* 邮箱2271608011@qq.com
* giteehttps://gitee.com/bmycode
* githubhttps://github.com/helpcode
*
*/
import { enable, isEnabled, disable } from "@tauri-apps/plugin-autostart";
import Notification from "./Notification";
export default class AutoStart {
/**
* 注册开机自启
*/
public static async EnableAutoStart() {
if (!await isEnabled()) {
await enable();
await Notification.send({ title: '恭喜', body: '已注册开机自启' })
}
}
/**
* 禁用开机自启
*/
public static async DisableAutoStart() {
await disable();
await Notification.send({ title: '恭喜', body: '已关闭开机自启' })
}
}

View File

@@ -0,0 +1,65 @@
/*
* Copyright (c) 2023.
*
* 作者bmy
* 邮箱2271608011@qq.com
* giteehttps://gitee.com/bmycode
* githubhttps://github.com/helpcode
*
*/
import config, { type themeType } from "@/config";
import * as monaco from "monaco-editor";
import JsonDatabase, { type DbConfig, type themeValueType } from "@/utils/JsonDatabase";
import { themeConfig } from '@/stores/ThemeStore';
import { get } from 'svelte/store';
class ChangeTheme {
constructor() {
this.onThemeChanged().then()
}
public changeStyle(obj: themeType) {
let key: keyof themeType;
for (key in obj) {
(<HTMLElement>document.querySelector("body"))
.style.setProperty(`--${ key }`, obj[key]);
}
}
public setTheme(themeName: themeValueType) {
const themeConfig = config[themeName];
this.changeStyle(themeConfig);
}
public async setThemeRunCode(conf: DbConfig, type?: string) {
const code = async () => {
this.setTheme(conf.theme)
monaco.editor.setTheme(
conf.theme == 'light' ? 'vs' : 'vs-dark'
)
await JsonDatabase.writeJson(conf);
}
// 启动时候等待1秒等 编辑器 配置完成,再设置编辑器主题,否则 会设置失效
type == "app"
? setTimeout(async () => await code(), 1000)
: await code()
}
public async onThemeChanged() {
await config.appWindow.onThemeChanged(async ({ payload: theme }) => {
let conf = get(themeConfig)
if (conf.autoThemeSystem) {
conf.theme = theme
conf.autoThemeSystem = 1
await this.setThemeRunCode(conf)
// update 更新,通知 App.svelte 的订阅,用于更新 ui框架 的 主题模式
themeConfig.update(v => conf)
}
});
}
}
export default new ChangeTheme

View File

@@ -0,0 +1,95 @@
/*
* Copyright (c) 2023.
*
* 作者bmy
* 邮箱2271608011@qq.com
* giteehttps://gitee.com/bmycode
* githubhttps://github.com/helpcode
*
*/
import { BaseDirectory, createDir, exists, writeTextFile, readTextFile } from "@tauri-apps/plugin-fs";
import { homeDir } from '@tauri-apps/api/path';
export type value = 1 | 0;
export type themeValueType = 'light' | 'dark';
export interface DbConfig {
JsonType: value;
needProperty: value;
needPropertyValue: value;
nullAlias: string;
autoSave: value;
savePath: string;
saveFileName: string
theme: themeValueType,
autoThemeSystem: value;
autoLoginStart: value;
lineNumbers: 'on' | 'off';
minimap: value;
autoClipboard: value;
}
class JsonDatabase {
// 文件夹名称
DirectoryName: string = ".jsontoclass"
// 保存配置的json文件名
JsonFileName: string = "db.json"
// 文件夹 + json 文件 .jsontoclass/db.json
DbFullPath: string = `${this.DirectoryName}/${this.JsonFileName}`
// UI框架限制RadioGroup这类UI组件的 items 中 value 和 bind:value 必须为 string所以这里
// 存储 设置项 不使用 boolean组件内 会对 number 0 进行 String
DataBaseConfig: DbConfig = {
JsonType : 0,
needProperty : 0,
needPropertyValue: 0,
nullAlias : "string",
autoSave : 0,
savePath : "",
saveFileName: "",
theme : "light",
autoThemeSystem: 0,
autoLoginStart : 0,
lineNumbers: "off",
minimap: 0,
autoClipboard: 0
}
/**
* 创建json数据库
* @constructor
*/
public async CreatedJsonDataBase() {
let rootPath = await homeDir();
let fullPath: string = `${ await homeDir() }/${ this.DbFullPath }`
if (!await exists(`${ rootPath }/${ this.DirectoryName }`)) {
await createDir(this.DirectoryName, { dir: BaseDirectory.Home })
if (!await exists(fullPath)) {
await this.writeJson(this.DataBaseConfig);
}
}
}
public async readJson(): Promise<DbConfig> {
await this.CreatedJsonDataBase();
const res = await readTextFile(this.DbFullPath, { dir: BaseDirectory.Home });
return JSON.parse(res);
}
public async writeJson(str: DbConfig) {
await writeTextFile(this.DbFullPath, JSON.stringify(str), { dir: BaseDirectory.Home });
}
}
export default new JsonDatabase

View File

@@ -0,0 +1,38 @@
/*
* Copyright (c) 2023.
*
* 作者bmy
* 邮箱2271608011@qq.com
* giteehttps://gitee.com/bmycode
* githubhttps://github.com/helpcode
*
*/
import * as monaco from 'monaco-editor';
import { themeConfig } from "@/stores/ThemeStore";
import { get } from 'svelte/store';
// 使用插件 vite-plugin-monaco-editor 简化了 MonacoEditor 的一些配置
// 原配置方法参考https://github.com/microsoft/monaco-editor/blob/main/docs/integrate-esm.md#using-vite
export class MonacoEditor {
public static conf = get(themeConfig)
public static creatMonacoEditor(el: HTMLElement) {
return monaco.editor.create(el, {
value: '',
language: 'json',
formatOnPaste: true,
formatOnType: true,
tabSize: 2,
fontSize: 16,
contextmenu: false,
automaticLayout: true,
theme: "vs",
lineNumbers: MonacoEditor.conf.lineNumbers,
minimap: {
enabled: Boolean(MonacoEditor.conf.minimap)
}
});
}
}

View File

@@ -0,0 +1,36 @@
/*
* Copyright (c) 2023.
*
* 作者bmy
* 邮箱2271608011@qq.com
* giteehttps://gitee.com/bmycode
* githubhttps://github.com/helpcode
*
*/
import { isPermissionGranted, requestPermission, sendNotification, type Options } from '@tauri-apps/plugin-notification';
export default class Notification {
/**
* 有权限,发送系统通知
*/
public static async send(options: Options) {
if (await Notification.checkisPermission()) {
sendNotification(options);
}
}
/**
* 检查是否具有通知权限,没有就请求发送通知的权限
*/
public static async checkisPermission() {
let permissionGranted = await isPermissionGranted();
if (!permissionGranted) {
const permission = await requestPermission();
permissionGranted = permission === 'granted';
}
return permissionGranted
}
}

12
json-to-class/src/vite-env.d.ts vendored Normal file
View File

@@ -0,0 +1,12 @@
/*
* Copyright (c) 2023.
*
* 作者bmy
* 邮箱2271608011@qq.com
* giteehttps://gitee.com/bmycode
* githubhttps://github.com/helpcode
*
*/
/// <reference types="svelte" />
/// <reference types="vite/client" />

View File

@@ -0,0 +1,7 @@
import { vitePreprocess } from "@sveltejs/vite-plugin-svelte";
export default {
// Consult https://svelte.dev/docs#compile-time-svelte-preprocess
// for more information about preprocessors
preprocess: vitePreprocess(),
};

View File

@@ -0,0 +1,23 @@
{
"extends": "@tsconfig/svelte/tsconfig.json",
"compilerOptions": {
"baseUrl": "./",
"target": "ESNext",
"useDefineForClassFields": true,
"module": "ESNext",
"moduleResolution": "node",
"resolveJsonModule": true,
"verbatimModuleSyntax": true,
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"allowJs": true,
"checkJs": true,
"isolatedModules": true,
"paths": {
"@/*": ["src/*"]
}
},
"include": ["src/**/*.d.ts", "src/**/*.ts", "src/**/*.js", "src/**/*.svelte"],
"files": [ "src/global.d.ts" ],
"references": [{ "path": "./tsconfig.node.json" }]
}

Some files were not shown because too many files have changed in this diff Show More