init
4
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
build/bin
|
||||
node_modules
|
||||
frontend/dist
|
||||
|
||||
44
README.md
|
|
@ -1,39 +1,19 @@
|
|||
# godoos
|
||||
# README
|
||||
|
||||
#### 介绍
|
||||
{**以下是 Gitee 平台说明,您可以替换此简介**
|
||||
Gitee 是 OSCHINA 推出的基于 Git 的代码托管平台(同时支持 SVN)。专为开发者提供稳定、高效、安全的云端软件开发协作平台
|
||||
无论是个人、团队、或是企业,都能够用 Gitee 实现代码托管、项目管理、协作开发。企业项目请看 [https://gitee.com/enterprises](https://gitee.com/enterprises)}
|
||||
## About
|
||||
|
||||
#### 软件架构
|
||||
软件架构说明
|
||||
This is the official Wails Vue-TS template.
|
||||
|
||||
You can configure the project by editing `wails.json`. More information about the project settings can be found
|
||||
here: https://wails.io/docs/reference/project-config
|
||||
|
||||
#### 安装教程
|
||||
## Live Development
|
||||
|
||||
1. xxxx
|
||||
2. xxxx
|
||||
3. xxxx
|
||||
To run in live development mode, run `wails dev` in the project directory. This will run a Vite development
|
||||
server that will provide very fast hot reload of your frontend changes. If you want to develop in a browser
|
||||
and have access to your Go methods, there is also a dev server that runs on http://localhost:34115. Connect
|
||||
to this in your browser, and you can call your Go code from devtools.
|
||||
|
||||
#### 使用说明
|
||||
## Building
|
||||
|
||||
1. xxxx
|
||||
2. xxxx
|
||||
3. xxxx
|
||||
|
||||
#### 参与贡献
|
||||
|
||||
1. Fork 本仓库
|
||||
2. 新建 Feat_xxx 分支
|
||||
3. 提交代码
|
||||
4. 新建 Pull Request
|
||||
|
||||
|
||||
#### 特技
|
||||
|
||||
1. 使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md
|
||||
2. Gitee 官方博客 [blog.gitee.com](https://blog.gitee.com)
|
||||
3. 你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解 Gitee 上的优秀开源项目
|
||||
4. [GVP](https://gitee.com/gvp) 全称是 Gitee 最有价值开源项目,是综合评定出的优秀开源项目
|
||||
5. Gitee 官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help)
|
||||
6. Gitee 封面人物是一档用来展示 Gitee 会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)
|
||||
To build a redistributable, production mode package, use `wails build`.
|
||||
|
|
|
|||
42
app.go
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"godoos/cmd"
|
||||
|
||||
"github.com/wailsapp/wails/v2/pkg/runtime"
|
||||
)
|
||||
|
||||
// App struct
|
||||
type App struct {
|
||||
ctx context.Context
|
||||
}
|
||||
|
||||
// NewApp creates a new App application struct
|
||||
func NewApp() *App {
|
||||
return &App{}
|
||||
}
|
||||
|
||||
// startup is called when the app starts. The context is saved
|
||||
// so we can call the runtime methods
|
||||
func (a *App) startup(ctx context.Context) {
|
||||
a.ctx = ctx
|
||||
go cmd.OsStart()
|
||||
}
|
||||
func (a *App) shutdown(ctx context.Context) {
|
||||
cmd.OsStop()
|
||||
}
|
||||
func (a *App) OpenDirDialog() string {
|
||||
path, err := runtime.OpenDirectoryDialog(a.ctx, runtime.OpenDialogOptions{
|
||||
Title: "Select Folder",
|
||||
})
|
||||
if err != nil {
|
||||
runtime.LogErrorf(a.ctx, "Error: %+v\n", err)
|
||||
}
|
||||
return path
|
||||
}
|
||||
|
||||
// Greet returns a greeting for the given name
|
||||
// func (a *App) Greet(name string) string {
|
||||
// return fmt.Sprintf("Hello %s, It's show time!", name)
|
||||
// }
|
||||
35
build/README.md
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
# Build Directory
|
||||
|
||||
The build directory is used to house all the build files and assets for your application.
|
||||
|
||||
The structure is:
|
||||
|
||||
* bin - Output directory
|
||||
* darwin - macOS specific files
|
||||
* windows - Windows specific files
|
||||
|
||||
## Mac
|
||||
|
||||
The `darwin` directory holds files specific to Mac builds.
|
||||
These may be customised and used as part of the build. To return these files to the default state, simply delete them
|
||||
and
|
||||
build with `wails build`.
|
||||
|
||||
The directory contains the following files:
|
||||
|
||||
- `Info.plist` - the main plist file used for Mac builds. It is used when building using `wails build`.
|
||||
- `Info.dev.plist` - same as the main plist file but used when building using `wails dev`.
|
||||
|
||||
## Windows
|
||||
|
||||
The `windows` directory contains the manifest and rc files used when building with `wails build`.
|
||||
These may be customised for your application. To return these files to the default state, simply delete them and
|
||||
build with `wails build`.
|
||||
|
||||
- `icon.ico` - The icon used for the application. This is used when building using `wails build`. If you wish to
|
||||
use a different icon, simply replace this file with your own. If it is missing, a new `icon.ico` file
|
||||
will be created using the `appicon.png` file in the build directory.
|
||||
- `installer/*` - The files used to create the Windows installer. These are used when building using `wails build`.
|
||||
- `info.json` - Application details used for Windows builds. The data here will be used by the Windows installer,
|
||||
as well as the application itself (right click the exe -> properties -> details)
|
||||
- `wails.exe.manifest` - The main application manifest file.
|
||||
BIN
build/appicon.png
Normal file
|
After Width: | Height: | Size: 67 KiB |
68
build/darwin/Info.dev.plist
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>{{.Info.ProductName}}</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>{{.Name}}</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.wails.{{.Name}}</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>{{.Info.ProductVersion}}</string>
|
||||
<key>CFBundleGetInfoString</key>
|
||||
<string>{{.Info.Comments}}</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>{{.Info.ProductVersion}}</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>iconfile</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>10.13.0</string>
|
||||
<key>NSHighResolutionCapable</key>
|
||||
<string>true</string>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string>{{.Info.Copyright}}</string>
|
||||
{{if .Info.FileAssociations}}
|
||||
<key>CFBundleDocumentTypes</key>
|
||||
<array>
|
||||
{{range .Info.FileAssociations}}
|
||||
<dict>
|
||||
<key>CFBundleTypeExtensions</key>
|
||||
<array>
|
||||
<string>{{.Ext}}</string>
|
||||
</array>
|
||||
<key>CFBundleTypeName</key>
|
||||
<string>{{.Name}}</string>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>{{.Role}}</string>
|
||||
<key>CFBundleTypeIconFile</key>
|
||||
<string>{{.IconName}}</string>
|
||||
</dict>
|
||||
{{end}}
|
||||
</array>
|
||||
{{end}}
|
||||
{{if .Info.Protocols}}
|
||||
<key>CFBundleURLTypes</key>
|
||||
<array>
|
||||
{{range .Info.Protocols}}
|
||||
<dict>
|
||||
<key>CFBundleURLName</key>
|
||||
<string>com.wails.{{.Scheme}}</string>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>{{.Scheme}}</string>
|
||||
</array>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>{{.Role}}</string>
|
||||
</dict>
|
||||
{{end}}
|
||||
</array>
|
||||
{{end}}
|
||||
<key>NSAppTransportSecurity</key>
|
||||
<dict>
|
||||
<key>NSAllowsLocalNetworking</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
||||
63
build/darwin/Info.plist
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>{{.Info.ProductName}}</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>{{.Name}}</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.wails.{{.Name}}</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>{{.Info.ProductVersion}}</string>
|
||||
<key>CFBundleGetInfoString</key>
|
||||
<string>{{.Info.Comments}}</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>{{.Info.ProductVersion}}</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>iconfile</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>10.13.0</string>
|
||||
<key>NSHighResolutionCapable</key>
|
||||
<string>true</string>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string>{{.Info.Copyright}}</string>
|
||||
{{if .Info.FileAssociations}}
|
||||
<key>CFBundleDocumentTypes</key>
|
||||
<array>
|
||||
{{range .Info.FileAssociations}}
|
||||
<dict>
|
||||
<key>CFBundleTypeExtensions</key>
|
||||
<array>
|
||||
<string>{{.Ext}}</string>
|
||||
</array>
|
||||
<key>CFBundleTypeName</key>
|
||||
<string>{{.Name}}</string>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>{{.Role}}</string>
|
||||
<key>CFBundleTypeIconFile</key>
|
||||
<string>{{.IconName}}</string>
|
||||
</dict>
|
||||
{{end}}
|
||||
</array>
|
||||
{{end}}
|
||||
{{if .Info.Protocols}}
|
||||
<key>CFBundleURLTypes</key>
|
||||
<array>
|
||||
{{range .Info.Protocols}}
|
||||
<dict>
|
||||
<key>CFBundleURLName</key>
|
||||
<string>com.wails.{{.Scheme}}</string>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>{{.Scheme}}</string>
|
||||
</array>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>{{.Role}}</string>
|
||||
</dict>
|
||||
{{end}}
|
||||
</array>
|
||||
{{end}}
|
||||
</dict>
|
||||
</plist>
|
||||
BIN
build/windows/icon.ico
Normal file
|
After Width: | Height: | Size: 4.2 KiB |
15
build/windows/info.json
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"fixed": {
|
||||
"file_version": "{{.Info.ProductVersion}}"
|
||||
},
|
||||
"info": {
|
||||
"0000": {
|
||||
"ProductVersion": "{{.Info.ProductVersion}}",
|
||||
"CompanyName": "{{.Info.CompanyName}}",
|
||||
"FileDescription": "{{.Info.ProductName}}",
|
||||
"LegalCopyright": "{{.Info.Copyright}}",
|
||||
"ProductName": "{{.Info.ProductName}}",
|
||||
"Comments": "{{.Info.Comments}}"
|
||||
}
|
||||
}
|
||||
}
|
||||
114
build/windows/installer/project.nsi
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
Unicode true
|
||||
|
||||
####
|
||||
## Please note: Template replacements don't work in this file. They are provided with default defines like
|
||||
## mentioned underneath.
|
||||
## If the keyword is not defined, "wails_tools.nsh" will populate them with the values from ProjectInfo.
|
||||
## If they are defined here, "wails_tools.nsh" will not touch them. This allows to use this project.nsi manually
|
||||
## from outside of Wails for debugging and development of the installer.
|
||||
##
|
||||
## For development first make a wails nsis build to populate the "wails_tools.nsh":
|
||||
## > wails build --target windows/amd64 --nsis
|
||||
## Then you can call makensis on this file with specifying the path to your binary:
|
||||
## For a AMD64 only installer:
|
||||
## > makensis -DARG_WAILS_AMD64_BINARY=..\..\bin\app.exe
|
||||
## For a ARM64 only installer:
|
||||
## > makensis -DARG_WAILS_ARM64_BINARY=..\..\bin\app.exe
|
||||
## For a installer with both architectures:
|
||||
## > makensis -DARG_WAILS_AMD64_BINARY=..\..\bin\app-amd64.exe -DARG_WAILS_ARM64_BINARY=..\..\bin\app-arm64.exe
|
||||
####
|
||||
## The following information is taken from the ProjectInfo file, but they can be overwritten here.
|
||||
####
|
||||
## !define INFO_PROJECTNAME "MyProject" # Default "{{.Name}}"
|
||||
## !define INFO_COMPANYNAME "MyCompany" # Default "{{.Info.CompanyName}}"
|
||||
## !define INFO_PRODUCTNAME "MyProduct" # Default "{{.Info.ProductName}}"
|
||||
## !define INFO_PRODUCTVERSION "1.0.0" # Default "{{.Info.ProductVersion}}"
|
||||
## !define INFO_COPYRIGHT "Copyright" # Default "{{.Info.Copyright}}"
|
||||
###
|
||||
## !define PRODUCT_EXECUTABLE "Application.exe" # Default "${INFO_PROJECTNAME}.exe"
|
||||
## !define UNINST_KEY_NAME "UninstKeyInRegistry" # Default "${INFO_COMPANYNAME}${INFO_PRODUCTNAME}"
|
||||
####
|
||||
## !define REQUEST_EXECUTION_LEVEL "admin" # Default "admin" see also https://nsis.sourceforge.io/Docs/Chapter4.html
|
||||
####
|
||||
## Include the wails tools
|
||||
####
|
||||
!include "wails_tools.nsh"
|
||||
|
||||
# The version information for this two must consist of 4 parts
|
||||
VIProductVersion "${INFO_PRODUCTVERSION}.0"
|
||||
VIFileVersion "${INFO_PRODUCTVERSION}.0"
|
||||
|
||||
VIAddVersionKey "CompanyName" "${INFO_COMPANYNAME}"
|
||||
VIAddVersionKey "FileDescription" "${INFO_PRODUCTNAME} Installer"
|
||||
VIAddVersionKey "ProductVersion" "${INFO_PRODUCTVERSION}"
|
||||
VIAddVersionKey "FileVersion" "${INFO_PRODUCTVERSION}"
|
||||
VIAddVersionKey "LegalCopyright" "${INFO_COPYRIGHT}"
|
||||
VIAddVersionKey "ProductName" "${INFO_PRODUCTNAME}"
|
||||
|
||||
# Enable HiDPI support. https://nsis.sourceforge.io/Reference/ManifestDPIAware
|
||||
ManifestDPIAware true
|
||||
|
||||
!include "MUI.nsh"
|
||||
|
||||
!define MUI_ICON "..\icon.ico"
|
||||
!define MUI_UNICON "..\icon.ico"
|
||||
# !define MUI_WELCOMEFINISHPAGE_BITMAP "resources\leftimage.bmp" #Include this to add a bitmap on the left side of the Welcome Page. Must be a size of 164x314
|
||||
!define MUI_FINISHPAGE_NOAUTOCLOSE # Wait on the INSTFILES page so the user can take a look into the details of the installation steps
|
||||
!define MUI_ABORTWARNING # This will warn the user if they exit from the installer.
|
||||
|
||||
!insertmacro MUI_PAGE_WELCOME # Welcome to the installer page.
|
||||
# !insertmacro MUI_PAGE_LICENSE "resources\eula.txt" # Adds a EULA page to the installer
|
||||
!insertmacro MUI_PAGE_DIRECTORY # In which folder install page.
|
||||
!insertmacro MUI_PAGE_INSTFILES # Installing page.
|
||||
!insertmacro MUI_PAGE_FINISH # Finished installation page.
|
||||
|
||||
!insertmacro MUI_UNPAGE_INSTFILES # Uinstalling page
|
||||
|
||||
!insertmacro MUI_LANGUAGE "English" # Set the Language of the installer
|
||||
|
||||
## The following two statements can be used to sign the installer and the uninstaller. The path to the binaries are provided in %1
|
||||
#!uninstfinalize 'signtool --file "%1"'
|
||||
#!finalize 'signtool --file "%1"'
|
||||
|
||||
Name "${INFO_PRODUCTNAME}"
|
||||
OutFile "..\..\bin\${INFO_PROJECTNAME}-${ARCH}-installer.exe" # Name of the installer's file.
|
||||
InstallDir "$PROGRAMFILES64\${INFO_COMPANYNAME}\${INFO_PRODUCTNAME}" # Default installing folder ($PROGRAMFILES is Program Files folder).
|
||||
ShowInstDetails show # This will always show the installation details.
|
||||
|
||||
Function .onInit
|
||||
!insertmacro wails.checkArchitecture
|
||||
FunctionEnd
|
||||
|
||||
Section
|
||||
!insertmacro wails.setShellContext
|
||||
|
||||
!insertmacro wails.webview2runtime
|
||||
|
||||
SetOutPath $INSTDIR
|
||||
|
||||
!insertmacro wails.files
|
||||
|
||||
CreateShortcut "$SMPROGRAMS\${INFO_PRODUCTNAME}.lnk" "$INSTDIR\${PRODUCT_EXECUTABLE}"
|
||||
CreateShortCut "$DESKTOP\${INFO_PRODUCTNAME}.lnk" "$INSTDIR\${PRODUCT_EXECUTABLE}"
|
||||
|
||||
!insertmacro wails.associateFiles
|
||||
!insertmacro wails.associateCustomProtocols
|
||||
|
||||
!insertmacro wails.writeUninstaller
|
||||
SectionEnd
|
||||
|
||||
Section "uninstall"
|
||||
!insertmacro wails.setShellContext
|
||||
|
||||
RMDir /r "$AppData\${PRODUCT_EXECUTABLE}" # Remove the WebView2 DataPath
|
||||
|
||||
RMDir /r $INSTDIR
|
||||
|
||||
Delete "$SMPROGRAMS\${INFO_PRODUCTNAME}.lnk"
|
||||
Delete "$DESKTOP\${INFO_PRODUCTNAME}.lnk"
|
||||
|
||||
!insertmacro wails.unassociateFiles
|
||||
!insertmacro wails.unassociateCustomProtocols
|
||||
|
||||
!insertmacro wails.deleteUninstaller
|
||||
SectionEnd
|
||||
249
build/windows/installer/wails_tools.nsh
Normal file
|
|
@ -0,0 +1,249 @@
|
|||
# DO NOT EDIT - Generated automatically by `wails build`
|
||||
|
||||
!include "x64.nsh"
|
||||
!include "WinVer.nsh"
|
||||
!include "FileFunc.nsh"
|
||||
|
||||
!ifndef INFO_PROJECTNAME
|
||||
!define INFO_PROJECTNAME "{{.Name}}"
|
||||
!endif
|
||||
!ifndef INFO_COMPANYNAME
|
||||
!define INFO_COMPANYNAME "{{.Info.CompanyName}}"
|
||||
!endif
|
||||
!ifndef INFO_PRODUCTNAME
|
||||
!define INFO_PRODUCTNAME "{{.Info.ProductName}}"
|
||||
!endif
|
||||
!ifndef INFO_PRODUCTVERSION
|
||||
!define INFO_PRODUCTVERSION "{{.Info.ProductVersion}}"
|
||||
!endif
|
||||
!ifndef INFO_COPYRIGHT
|
||||
!define INFO_COPYRIGHT "{{.Info.Copyright}}"
|
||||
!endif
|
||||
!ifndef PRODUCT_EXECUTABLE
|
||||
!define PRODUCT_EXECUTABLE "${INFO_PROJECTNAME}.exe"
|
||||
!endif
|
||||
!ifndef UNINST_KEY_NAME
|
||||
!define UNINST_KEY_NAME "${INFO_COMPANYNAME}${INFO_PRODUCTNAME}"
|
||||
!endif
|
||||
!define UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${UNINST_KEY_NAME}"
|
||||
|
||||
!ifndef REQUEST_EXECUTION_LEVEL
|
||||
!define REQUEST_EXECUTION_LEVEL "admin"
|
||||
!endif
|
||||
|
||||
RequestExecutionLevel "${REQUEST_EXECUTION_LEVEL}"
|
||||
|
||||
!ifdef ARG_WAILS_AMD64_BINARY
|
||||
!define SUPPORTS_AMD64
|
||||
!endif
|
||||
|
||||
!ifdef ARG_WAILS_ARM64_BINARY
|
||||
!define SUPPORTS_ARM64
|
||||
!endif
|
||||
|
||||
!ifdef SUPPORTS_AMD64
|
||||
!ifdef SUPPORTS_ARM64
|
||||
!define ARCH "amd64_arm64"
|
||||
!else
|
||||
!define ARCH "amd64"
|
||||
!endif
|
||||
!else
|
||||
!ifdef SUPPORTS_ARM64
|
||||
!define ARCH "arm64"
|
||||
!else
|
||||
!error "Wails: Undefined ARCH, please provide at least one of ARG_WAILS_AMD64_BINARY or ARG_WAILS_ARM64_BINARY"
|
||||
!endif
|
||||
!endif
|
||||
|
||||
!macro wails.checkArchitecture
|
||||
!ifndef WAILS_WIN10_REQUIRED
|
||||
!define WAILS_WIN10_REQUIRED "This product is only supported on Windows 10 (Server 2016) and later."
|
||||
!endif
|
||||
|
||||
!ifndef WAILS_ARCHITECTURE_NOT_SUPPORTED
|
||||
!define WAILS_ARCHITECTURE_NOT_SUPPORTED "This product can't be installed on the current Windows architecture. Supports: ${ARCH}"
|
||||
!endif
|
||||
|
||||
${If} ${AtLeastWin10}
|
||||
!ifdef SUPPORTS_AMD64
|
||||
${if} ${IsNativeAMD64}
|
||||
Goto ok
|
||||
${EndIf}
|
||||
!endif
|
||||
|
||||
!ifdef SUPPORTS_ARM64
|
||||
${if} ${IsNativeARM64}
|
||||
Goto ok
|
||||
${EndIf}
|
||||
!endif
|
||||
|
||||
IfSilent silentArch notSilentArch
|
||||
silentArch:
|
||||
SetErrorLevel 65
|
||||
Abort
|
||||
notSilentArch:
|
||||
MessageBox MB_OK "${WAILS_ARCHITECTURE_NOT_SUPPORTED}"
|
||||
Quit
|
||||
${else}
|
||||
IfSilent silentWin notSilentWin
|
||||
silentWin:
|
||||
SetErrorLevel 64
|
||||
Abort
|
||||
notSilentWin:
|
||||
MessageBox MB_OK "${WAILS_WIN10_REQUIRED}"
|
||||
Quit
|
||||
${EndIf}
|
||||
|
||||
ok:
|
||||
!macroend
|
||||
|
||||
!macro wails.files
|
||||
!ifdef SUPPORTS_AMD64
|
||||
${if} ${IsNativeAMD64}
|
||||
File "/oname=${PRODUCT_EXECUTABLE}" "${ARG_WAILS_AMD64_BINARY}"
|
||||
${EndIf}
|
||||
!endif
|
||||
|
||||
!ifdef SUPPORTS_ARM64
|
||||
${if} ${IsNativeARM64}
|
||||
File "/oname=${PRODUCT_EXECUTABLE}" "${ARG_WAILS_ARM64_BINARY}"
|
||||
${EndIf}
|
||||
!endif
|
||||
!macroend
|
||||
|
||||
!macro wails.writeUninstaller
|
||||
WriteUninstaller "$INSTDIR\uninstall.exe"
|
||||
|
||||
SetRegView 64
|
||||
WriteRegStr HKLM "${UNINST_KEY}" "Publisher" "${INFO_COMPANYNAME}"
|
||||
WriteRegStr HKLM "${UNINST_KEY}" "DisplayName" "${INFO_PRODUCTNAME}"
|
||||
WriteRegStr HKLM "${UNINST_KEY}" "DisplayVersion" "${INFO_PRODUCTVERSION}"
|
||||
WriteRegStr HKLM "${UNINST_KEY}" "DisplayIcon" "$INSTDIR\${PRODUCT_EXECUTABLE}"
|
||||
WriteRegStr HKLM "${UNINST_KEY}" "UninstallString" "$\"$INSTDIR\uninstall.exe$\""
|
||||
WriteRegStr HKLM "${UNINST_KEY}" "QuietUninstallString" "$\"$INSTDIR\uninstall.exe$\" /S"
|
||||
|
||||
${GetSize} "$INSTDIR" "/S=0K" $0 $1 $2
|
||||
IntFmt $0 "0x%08X" $0
|
||||
WriteRegDWORD HKLM "${UNINST_KEY}" "EstimatedSize" "$0"
|
||||
!macroend
|
||||
|
||||
!macro wails.deleteUninstaller
|
||||
Delete "$INSTDIR\uninstall.exe"
|
||||
|
||||
SetRegView 64
|
||||
DeleteRegKey HKLM "${UNINST_KEY}"
|
||||
!macroend
|
||||
|
||||
!macro wails.setShellContext
|
||||
${If} ${REQUEST_EXECUTION_LEVEL} == "admin"
|
||||
SetShellVarContext all
|
||||
${else}
|
||||
SetShellVarContext current
|
||||
${EndIf}
|
||||
!macroend
|
||||
|
||||
# Install webview2 by launching the bootstrapper
|
||||
# See https://docs.microsoft.com/en-us/microsoft-edge/webview2/concepts/distribution#online-only-deployment
|
||||
!macro wails.webview2runtime
|
||||
!ifndef WAILS_INSTALL_WEBVIEW_DETAILPRINT
|
||||
!define WAILS_INSTALL_WEBVIEW_DETAILPRINT "Installing: WebView2 Runtime"
|
||||
!endif
|
||||
|
||||
SetRegView 64
|
||||
# If the admin key exists and is not empty then webview2 is already installed
|
||||
ReadRegStr $0 HKLM "SOFTWARE\WOW6432Node\Microsoft\EdgeUpdate\Clients\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}" "pv"
|
||||
${If} $0 != ""
|
||||
Goto ok
|
||||
${EndIf}
|
||||
|
||||
${If} ${REQUEST_EXECUTION_LEVEL} == "user"
|
||||
# If the installer is run in user level, check the user specific key exists and is not empty then webview2 is already installed
|
||||
ReadRegStr $0 HKCU "Software\Microsoft\EdgeUpdate\Clients{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}" "pv"
|
||||
${If} $0 != ""
|
||||
Goto ok
|
||||
${EndIf}
|
||||
${EndIf}
|
||||
|
||||
SetDetailsPrint both
|
||||
DetailPrint "${WAILS_INSTALL_WEBVIEW_DETAILPRINT}"
|
||||
SetDetailsPrint listonly
|
||||
|
||||
InitPluginsDir
|
||||
CreateDirectory "$pluginsdir\webview2bootstrapper"
|
||||
SetOutPath "$pluginsdir\webview2bootstrapper"
|
||||
File "tmp\MicrosoftEdgeWebview2Setup.exe"
|
||||
ExecWait '"$pluginsdir\webview2bootstrapper\MicrosoftEdgeWebview2Setup.exe" /silent /install'
|
||||
|
||||
SetDetailsPrint both
|
||||
ok:
|
||||
!macroend
|
||||
|
||||
# Copy of APP_ASSOCIATE and APP_UNASSOCIATE macros from here https://gist.github.com/nikku/281d0ef126dbc215dd58bfd5b3a5cd5b
|
||||
!macro APP_ASSOCIATE EXT FILECLASS DESCRIPTION ICON COMMANDTEXT COMMAND
|
||||
; Backup the previously associated file class
|
||||
ReadRegStr $R0 SHELL_CONTEXT "Software\Classes\.${EXT}" ""
|
||||
WriteRegStr SHELL_CONTEXT "Software\Classes\.${EXT}" "${FILECLASS}_backup" "$R0"
|
||||
|
||||
WriteRegStr SHELL_CONTEXT "Software\Classes\.${EXT}" "" "${FILECLASS}"
|
||||
|
||||
WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}" "" `${DESCRIPTION}`
|
||||
WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\DefaultIcon" "" `${ICON}`
|
||||
WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\shell" "" "open"
|
||||
WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\shell\open" "" `${COMMANDTEXT}`
|
||||
WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\shell\open\command" "" `${COMMAND}`
|
||||
!macroend
|
||||
|
||||
!macro APP_UNASSOCIATE EXT FILECLASS
|
||||
; Backup the previously associated file class
|
||||
ReadRegStr $R0 SHELL_CONTEXT "Software\Classes\.${EXT}" `${FILECLASS}_backup`
|
||||
WriteRegStr SHELL_CONTEXT "Software\Classes\.${EXT}" "" "$R0"
|
||||
|
||||
DeleteRegKey SHELL_CONTEXT `Software\Classes\${FILECLASS}`
|
||||
!macroend
|
||||
|
||||
!macro wails.associateFiles
|
||||
; Create file associations
|
||||
{{range .Info.FileAssociations}}
|
||||
!insertmacro APP_ASSOCIATE "{{.Ext}}" "{{.Name}}" "{{.Description}}" "$INSTDIR\{{.IconName}}.ico" "Open with ${INFO_PRODUCTNAME}" "$INSTDIR\${PRODUCT_EXECUTABLE} $\"%1$\""
|
||||
|
||||
File "..\{{.IconName}}.ico"
|
||||
{{end}}
|
||||
!macroend
|
||||
|
||||
!macro wails.unassociateFiles
|
||||
; Delete app associations
|
||||
{{range .Info.FileAssociations}}
|
||||
!insertmacro APP_UNASSOCIATE "{{.Ext}}" "{{.Name}}"
|
||||
|
||||
Delete "$INSTDIR\{{.IconName}}.ico"
|
||||
{{end}}
|
||||
!macroend
|
||||
|
||||
!macro CUSTOM_PROTOCOL_ASSOCIATE PROTOCOL DESCRIPTION ICON COMMAND
|
||||
DeleteRegKey SHELL_CONTEXT "Software\Classes\${PROTOCOL}"
|
||||
WriteRegStr SHELL_CONTEXT "Software\Classes\${PROTOCOL}" "" "${DESCRIPTION}"
|
||||
WriteRegStr SHELL_CONTEXT "Software\Classes\${PROTOCOL}" "URL Protocol" ""
|
||||
WriteRegStr SHELL_CONTEXT "Software\Classes\${PROTOCOL}\DefaultIcon" "" "${ICON}"
|
||||
WriteRegStr SHELL_CONTEXT "Software\Classes\${PROTOCOL}\shell" "" ""
|
||||
WriteRegStr SHELL_CONTEXT "Software\Classes\${PROTOCOL}\shell\open" "" ""
|
||||
WriteRegStr SHELL_CONTEXT "Software\Classes\${PROTOCOL}\shell\open\command" "" "${COMMAND}"
|
||||
!macroend
|
||||
|
||||
!macro CUSTOM_PROTOCOL_UNASSOCIATE PROTOCOL
|
||||
DeleteRegKey SHELL_CONTEXT "Software\Classes\${PROTOCOL}"
|
||||
!macroend
|
||||
|
||||
!macro wails.associateCustomProtocols
|
||||
; Create custom protocols associations
|
||||
{{range .Info.Protocols}}
|
||||
!insertmacro CUSTOM_PROTOCOL_ASSOCIATE "{{.Scheme}}" "{{.Description}}" "$INSTDIR\${PRODUCT_EXECUTABLE},0" "$INSTDIR\${PRODUCT_EXECUTABLE} $\"%1$\""
|
||||
|
||||
{{end}}
|
||||
!macroend
|
||||
|
||||
!macro wails.unassociateCustomProtocols
|
||||
; Delete app custom protocol associations
|
||||
{{range .Info.Protocols}}
|
||||
!insertmacro CUSTOM_PROTOCOL_UNASSOCIATE "{{.Scheme}}"
|
||||
{{end}}
|
||||
!macroend
|
||||
15
build/windows/wails.exe.manifest
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
|
||||
<assemblyIdentity type="win32" name="com.wails.{{.Name}}" version="{{.Info.ProductVersion}}.0" processorArchitecture="*"/>
|
||||
<dependency>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*"/>
|
||||
</dependentAssembly>
|
||||
</dependency>
|
||||
<asmv3:application>
|
||||
<asmv3:windowsSettings>
|
||||
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/pm</dpiAware> <!-- fallback for Windows 7 and 8 -->
|
||||
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">permonitorv2,permonitor</dpiAwareness> <!-- falls back to per-monitor if per-monitor v2 is not supported -->
|
||||
</asmv3:windowsSettings>
|
||||
</asmv3:application>
|
||||
</assembly>
|
||||
45
cmd/config.go
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"godoos/libs"
|
||||
"net/http"
|
||||
"os"
|
||||
)
|
||||
|
||||
func HandleSetConfig(w http.ResponseWriter, r *http.Request) {
|
||||
var req libs.ReqBody
|
||||
err := json.NewDecoder(r.Body).Decode(&req)
|
||||
if err != nil {
|
||||
ErrorMsg(w, "The params is error!")
|
||||
return
|
||||
}
|
||||
if req.Name == "osInfo" {
|
||||
osInfo, _ := libs.GetConfig("osInfo")
|
||||
if req.Value != "" {
|
||||
if !libs.PathExists(req.Value) {
|
||||
ErrorMsg(w, "The Path is not exists!")
|
||||
return
|
||||
}
|
||||
err = os.Chmod(req.Value, 0755)
|
||||
if err != nil {
|
||||
ErrorMsg(w, "The Path chmod is error!")
|
||||
return
|
||||
}
|
||||
osInfo.Value = req.Value
|
||||
}
|
||||
|
||||
osInfo.Type = req.Type
|
||||
libs.SetConfig(osInfo)
|
||||
}
|
||||
if req.Name == "userInfo" ||
|
||||
req.Name == "dbInfo" {
|
||||
libs.SetConfig(req)
|
||||
}
|
||||
err = libs.LoadConfig()
|
||||
if err != nil {
|
||||
ErrorMsg(w, "The config load error!")
|
||||
return
|
||||
}
|
||||
SuccessMsg(w, "success", "The config set success!")
|
||||
}
|
||||
409
cmd/fs.go
Normal file
|
|
@ -0,0 +1,409 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"godoos/libs"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func HandleSystemInfo(w http.ResponseWriter, r *http.Request) {
|
||||
info := libs.GetSystemInfo()
|
||||
|
||||
// res := APIResponse{
|
||||
// Message: "File information retrieved successfully.",
|
||||
// Data: info,
|
||||
// }
|
||||
//json.NewEncoder(w).Encode(res)
|
||||
SuccessMsg(w, info, "File information retrieved successfully.")
|
||||
}
|
||||
|
||||
// HandleReadDir handles reading a directory
|
||||
func HandleReadDir(w http.ResponseWriter, r *http.Request) {
|
||||
path := r.URL.Query().Get("path")
|
||||
basePath, err := libs.GetOsDir()
|
||||
if err != nil {
|
||||
HTTPError(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
files, err := ReadDir(basePath, path)
|
||||
if err != nil {
|
||||
HTTPError(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
var osFileInfos []OsFileInfo
|
||||
for _, entry := range files {
|
||||
// 过滤掉以.开头的文件(隐藏文件)
|
||||
if strings.HasPrefix(entry.Name(), ".") {
|
||||
continue
|
||||
}
|
||||
osFileInfo, err := GetFileInfo(entry, basePath, path)
|
||||
if err != nil {
|
||||
HTTPError(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// 如果是文件,读取内容
|
||||
if osFileInfo.IsFile {
|
||||
file, err := os.Open(filepath.Join(basePath, osFileInfo.Path))
|
||||
if err != nil {
|
||||
HTTPError(w, http.StatusInternalServerError, fmt.Sprintf("Failed to open file: %v", err))
|
||||
return
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
content, err := io.ReadAll(file)
|
||||
if err != nil {
|
||||
HTTPError(w, http.StatusInternalServerError, fmt.Sprintf("Failed to read file content: %v", err))
|
||||
return
|
||||
}
|
||||
osFileInfo.Content = string(content)
|
||||
|
||||
// 检查文件内容是否以"link::"开头
|
||||
if strings.HasPrefix(osFileInfo.Content, "link::") {
|
||||
osFileInfo.IsSymlink = true
|
||||
} else {
|
||||
osFileInfo.Content = ""
|
||||
}
|
||||
}
|
||||
|
||||
osFileInfos = append(osFileInfos, *osFileInfo)
|
||||
}
|
||||
// 按照 ModTime 进行降序排序
|
||||
sort.Slice(osFileInfos, func(i, j int) bool {
|
||||
return osFileInfos[i].ModTime.Before(osFileInfos[j].ModTime)
|
||||
})
|
||||
res := APIResponse{
|
||||
Message: "Directory read successfully.",
|
||||
Data: osFileInfos,
|
||||
}
|
||||
json.NewEncoder(w).Encode(res)
|
||||
}
|
||||
|
||||
// HandleStat retrieves file information
|
||||
func HandleStat(w http.ResponseWriter, r *http.Request) {
|
||||
path := r.URL.Query().Get("path")
|
||||
if err := validateFilePath(path); err != nil {
|
||||
HTTPError(w, http.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
basePath, err := libs.GetOsDir()
|
||||
if err != nil {
|
||||
HTTPError(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// 调用GetFileInfo,传入路径而不是fs.DirEntry
|
||||
osFileInfo, err := GetFileInfo(path, basePath, "")
|
||||
if err != nil {
|
||||
HTTPError(w, http.StatusNotFound, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
res := APIResponse{
|
||||
Message: "File information retrieved successfully.",
|
||||
Data: osFileInfo,
|
||||
}
|
||||
json.NewEncoder(w).Encode(res)
|
||||
}
|
||||
|
||||
// HandleExists checks if a file or directory exists
|
||||
func HandleExists(w http.ResponseWriter, r *http.Request) {
|
||||
path := r.URL.Query().Get("path")
|
||||
if err := validateFilePath(path); err != nil {
|
||||
HTTPError(w, http.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
basePath, err := libs.GetOsDir()
|
||||
if err != nil {
|
||||
HTTPError(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
exists := Exists(basePath, path)
|
||||
message := "File does not exist."
|
||||
if exists {
|
||||
message = "File exists."
|
||||
}
|
||||
res := APIResponse{
|
||||
Message: message,
|
||||
Data: exists,
|
||||
}
|
||||
json.NewEncoder(w).Encode(res)
|
||||
}
|
||||
|
||||
// HandleReadFile reads a file's content
|
||||
func HandleReadFile(w http.ResponseWriter, r *http.Request) {
|
||||
path := r.URL.Query().Get("path")
|
||||
if err := validateFilePath(path); err != nil {
|
||||
HTTPError(w, http.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
basePath, err := libs.GetOsDir()
|
||||
if err != nil {
|
||||
HTTPError(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
fileContent, err := ReadFile(basePath, path)
|
||||
if err != nil {
|
||||
HTTPError(w, http.StatusNotFound, err.Error())
|
||||
return
|
||||
}
|
||||
content := string(fileContent)
|
||||
// 检查文件内容是否以"link::"开头
|
||||
if !strings.HasPrefix(content, "link::") {
|
||||
content = base64.StdEncoding.EncodeToString(fileContent)
|
||||
}
|
||||
res := APIResponse{
|
||||
Message: fmt.Sprintf("File '%s' read successfully.", path),
|
||||
Data: content, // Optionally, encode content as base64 for transmission
|
||||
//Data: string(fileContent),
|
||||
}
|
||||
json.NewEncoder(w).Encode(res)
|
||||
}
|
||||
|
||||
// HandleUnlink removes a file
|
||||
func HandleUnlink(w http.ResponseWriter, r *http.Request) {
|
||||
path := r.URL.Query().Get("path")
|
||||
if err := validateFilePath(path); err != nil {
|
||||
HTTPError(w, http.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
basePath, err := libs.GetOsDir()
|
||||
if err != nil {
|
||||
HTTPError(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
err = Unlink(basePath, path)
|
||||
if err != nil {
|
||||
HTTPError(w, http.StatusConflict, err.Error())
|
||||
return
|
||||
}
|
||||
res := APIResponse{Message: fmt.Sprintf("File '%s' successfully removed.", path)}
|
||||
json.NewEncoder(w).Encode(res)
|
||||
}
|
||||
|
||||
// HandleClear removes the entire filesystem (Caution: Use with care!)
|
||||
func HandleClear(w http.ResponseWriter, r *http.Request) {
|
||||
basePath, err := libs.GetOsDir()
|
||||
if err != nil {
|
||||
HTTPError(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
err = Clear(basePath)
|
||||
if err != nil {
|
||||
HTTPError(w, http.StatusConflict, err.Error())
|
||||
return
|
||||
}
|
||||
res := APIResponse{Message: "FileSystem successfully cleared."}
|
||||
json.NewEncoder(w).Encode(res)
|
||||
}
|
||||
|
||||
// HandleRename renames a file
|
||||
func HandleRename(w http.ResponseWriter, r *http.Request) {
|
||||
oldPath := r.URL.Query().Get("oldPath")
|
||||
newPath := r.URL.Query().Get("newPath")
|
||||
if err := validateFilePathPair(oldPath, newPath); err != nil {
|
||||
HTTPError(w, http.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
basePath, err := libs.GetOsDir()
|
||||
if err != nil {
|
||||
HTTPError(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
err = Rename(basePath, oldPath, newPath)
|
||||
if err != nil {
|
||||
log.Printf("Error renaming file: %s", err.Error())
|
||||
HTTPError(w, http.StatusConflict, err.Error())
|
||||
return
|
||||
}
|
||||
res := APIResponse{Message: fmt.Sprintf("File '%s' successfully renamed to '%s'.", oldPath, newPath)}
|
||||
json.NewEncoder(w).Encode(res)
|
||||
}
|
||||
|
||||
// HandleMkdir creates a directory
|
||||
func HandleMkdir(w http.ResponseWriter, r *http.Request) {
|
||||
dirPath := r.URL.Query().Get("dirPath")
|
||||
if err := validateFilePath(dirPath); err != nil {
|
||||
HTTPError(w, http.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
basePath, err := libs.GetOsDir()
|
||||
if err != nil {
|
||||
HTTPError(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
err = Mkdir(basePath, dirPath)
|
||||
if err != nil {
|
||||
HTTPError(w, http.StatusConflict, err.Error())
|
||||
return
|
||||
}
|
||||
res := APIResponse{Message: fmt.Sprintf("Directory '%s' created successfully.", dirPath)}
|
||||
json.NewEncoder(w).Encode(res)
|
||||
}
|
||||
|
||||
// HandleRmdir removes a directory
|
||||
func HandleRmdir(w http.ResponseWriter, r *http.Request) {
|
||||
dirPath := r.URL.Query().Get("dirPath")
|
||||
if err := validateFilePath(dirPath); err != nil {
|
||||
HTTPError(w, http.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
basePath, err := libs.GetOsDir()
|
||||
if err != nil {
|
||||
HTTPError(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
err = Rmdir(basePath, dirPath)
|
||||
if err != nil {
|
||||
HTTPError(w, http.StatusConflict, err.Error())
|
||||
return
|
||||
}
|
||||
res := APIResponse{Message: fmt.Sprintf("Directory '%s' successfully removed.", dirPath)}
|
||||
json.NewEncoder(w).Encode(res)
|
||||
}
|
||||
|
||||
// HandleCopyFile copies a file
|
||||
func HandleCopyFile(w http.ResponseWriter, r *http.Request) {
|
||||
srcPath := r.URL.Query().Get("srcPath")
|
||||
dstPath := r.URL.Query().Get("dstPath")
|
||||
if err := validateFilePathPair(srcPath, dstPath); err != nil {
|
||||
HTTPError(w, http.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
basePath, err := libs.GetOsDir()
|
||||
if err != nil {
|
||||
HTTPError(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
err = CopyFile(filepath.Join(basePath, srcPath), filepath.Join(basePath, dstPath))
|
||||
if err != nil {
|
||||
HTTPError(w, http.StatusConflict, err.Error())
|
||||
return
|
||||
}
|
||||
res := APIResponse{Message: fmt.Sprintf("File '%s' successfully copied to '%s'.", srcPath, dstPath)}
|
||||
json.NewEncoder(w).Encode(res)
|
||||
}
|
||||
|
||||
// HandleWriteFile writes content to a file
|
||||
func HandleWriteFile(w http.ResponseWriter, r *http.Request) {
|
||||
filePath := r.URL.Query().Get("filePath")
|
||||
basePath, err := libs.GetOsDir()
|
||||
if err != nil {
|
||||
HTTPError(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
// 获取文件内容
|
||||
fileContent, _, err := r.FormFile("content")
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
defer fileContent.Close()
|
||||
// 输出到控制台进行调试
|
||||
fmt.Printf("Body content: %v\n", fileContent)
|
||||
file, err := os.Create(filepath.Join(basePath, filePath))
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
_, err = io.Copy(file, fileContent)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusConflict)
|
||||
return
|
||||
}
|
||||
res := APIResponse{Message: fmt.Sprintf("File '%s' successfully written.", filePath)}
|
||||
json.NewEncoder(w).Encode(res)
|
||||
}
|
||||
|
||||
// HandleAppendFile appends content to a file
|
||||
func HandleAppendFile(w http.ResponseWriter, r *http.Request) {
|
||||
filePath := r.URL.Query().Get("filePath")
|
||||
if err := validateFilePath(filePath); err != nil {
|
||||
HTTPError(w, http.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
content, _, err := r.FormFile("content")
|
||||
if err != nil {
|
||||
HTTPError(w, http.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
basePath, err := libs.GetOsDir()
|
||||
if err != nil {
|
||||
HTTPError(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
err = AppendToFile(filepath.Join(basePath, filePath), content)
|
||||
if err != nil {
|
||||
HTTPError(w, http.StatusConflict, err.Error())
|
||||
return
|
||||
}
|
||||
res := APIResponse{Message: fmt.Sprintf("Content appended to file '%s'.", filePath)}
|
||||
json.NewEncoder(w).Encode(res)
|
||||
}
|
||||
|
||||
// HandleChmod changes the permissions of a file
|
||||
func HandleChmod(w http.ResponseWriter, r *http.Request) {
|
||||
var reqData struct {
|
||||
Path string `json:"path"`
|
||||
Mode string `json:"mode"`
|
||||
}
|
||||
|
||||
// 解析请求体
|
||||
err := json.NewDecoder(r.Body).Decode(&reqData)
|
||||
if err != nil {
|
||||
HTTPError(w, http.StatusBadRequest, "Failed to parse request body")
|
||||
return
|
||||
}
|
||||
|
||||
// 使用解码后的数据
|
||||
path := reqData.Path
|
||||
modeStr := reqData.Mode
|
||||
|
||||
if err := validateFilePath(path); err != nil {
|
||||
HTTPError(w, http.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
mode, err := parseMode(modeStr)
|
||||
if err != nil {
|
||||
HTTPError(w, http.StatusBadRequest, fmt.Sprintf("Invalid mode: %s", err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
basePath, err := libs.GetOsDir()
|
||||
if err != nil {
|
||||
HTTPError(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
err = Chmod(basePath, path, mode)
|
||||
if err != nil {
|
||||
HTTPError(w, http.StatusConflict, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
res := APIResponse{Message: fmt.Sprintf("Permissions of file '%s' successfully changed to %o.", path, mode)}
|
||||
json.NewEncoder(w).Encode(res)
|
||||
}
|
||||
|
||||
// parseMode converts a string representation of a mode to an os.FileMode
|
||||
func parseMode(modeStr string) (os.FileMode, error) {
|
||||
mode, err := strconv.ParseUint(modeStr, 8, 32)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return os.FileMode(mode), nil
|
||||
}
|
||||
70
cmd/main.go
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"godoos/libs"
|
||||
"godoos/progress"
|
||||
"log"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
const serverAddress = ":56710"
|
||||
|
||||
var srv *http.Server
|
||||
|
||||
func OsStart() {
|
||||
libs.Initdir()
|
||||
router := mux.NewRouter()
|
||||
router.Use(corsMiddleware())
|
||||
// 使用带有日志装饰的处理器注册路由
|
||||
router.Use(loggingMiddleware{}.Middleware)
|
||||
progressRouter := router.PathPrefix("/progress").Subrouter()
|
||||
progressRouter.HandleFunc("/start/{name}", progress.StartProcess).Methods(http.MethodGet)
|
||||
progressRouter.HandleFunc("/stop/{name}", progress.StopProcess).Methods(http.MethodGet)
|
||||
progressRouter.HandleFunc("/startall", progress.StartAll).Methods(http.MethodGet)
|
||||
progressRouter.HandleFunc("/stopall", progress.StopAll).Methods(http.MethodGet)
|
||||
progressRouter.HandleFunc("/restart/{name}", progress.ReStartProcess).Methods(http.MethodGet)
|
||||
progressRouter.HandleFunc("/list", progress.Status).Methods(http.MethodGet)
|
||||
progressRouter.HandleFunc("/listport", progress.ListPortsHandler).Methods(http.MethodGet)
|
||||
progressRouter.HandleFunc("/killport", progress.KillPortHandler).Methods(http.MethodGet)
|
||||
progressRouter.HandleFunc("/app/{name}", progress.ForwardRequest).Methods(http.MethodGet, http.MethodPost)
|
||||
progressRouter.HandleFunc("/app/{name}/{subpath:.*}", progress.ForwardRequest).Methods(http.MethodGet, http.MethodPost)
|
||||
router.HandleFunc("/ping", progress.Ping).Methods(http.MethodGet)
|
||||
router.HandleFunc("/", progress.Ping).Methods(http.MethodGet)
|
||||
router.HandleFunc("/system/info", HandleSystemInfo).Methods(http.MethodGet)
|
||||
router.HandleFunc("/system/setting", HandleSetConfig).Methods(http.MethodPost)
|
||||
router.HandleFunc("/file/read", HandleReadDir).Methods(http.MethodGet)
|
||||
router.HandleFunc("/file/stat", HandleStat).Methods(http.MethodGet)
|
||||
router.HandleFunc("/file/chmod", HandleChmod).Methods(http.MethodPost)
|
||||
router.HandleFunc("/file/exists", HandleExists).Methods(http.MethodGet)
|
||||
router.HandleFunc("/file/readfile", HandleReadFile).Methods(http.MethodGet)
|
||||
router.HandleFunc("/file/unlink", HandleUnlink).Methods(http.MethodGet)
|
||||
router.HandleFunc("/file/clear", HandleClear).Methods(http.MethodGet)
|
||||
router.HandleFunc("/file/rename", HandleRename).Methods(http.MethodGet)
|
||||
router.HandleFunc("/file/mkdir", HandleMkdir).Methods(http.MethodPost)
|
||||
router.HandleFunc("/file/rmdir", HandleRmdir).Methods(http.MethodGet)
|
||||
router.HandleFunc("/file/copyfile", HandleCopyFile).Methods(http.MethodGet)
|
||||
router.HandleFunc("/file/writefile", HandleWriteFile).Methods(http.MethodPost)
|
||||
router.HandleFunc("/file/appendfile", HandleAppendFile).Methods(http.MethodPost)
|
||||
router.HandleFunc("/file/watch", WatchHandler).Methods(http.MethodGet)
|
||||
|
||||
go progress.CheckActive(context.Background())
|
||||
log.Printf("Listening on port: %v", serverAddress)
|
||||
srv = &http.Server{Addr: serverAddress, Handler: router}
|
||||
Serve(srv)
|
||||
}
|
||||
func OsStop() {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
|
||||
defer cancel()
|
||||
err := progress.StopAllHandler()
|
||||
if err != nil {
|
||||
log.Fatalf("Servers forced to shutdown error: %v", err)
|
||||
}
|
||||
if err := srv.Shutdown(ctx); err != nil {
|
||||
log.Fatalf("Server forced to shutdown: %v", err)
|
||||
}
|
||||
log.Println("Server stopped.")
|
||||
}
|
||||
235
cmd/os.go
Normal file
|
|
@ -0,0 +1,235 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"godoos/libs"
|
||||
"io"
|
||||
"io/fs"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Common response structure
|
||||
type APIResponse struct {
|
||||
Message string `json:"message"`
|
||||
Code int `json:"code"`
|
||||
Data any `json:"data,omitempty"`
|
||||
Error string `json:"error,omitempty"`
|
||||
}
|
||||
|
||||
type OsFileInfo struct {
|
||||
IsFile bool `json:"isFile"`
|
||||
IsDir bool `json:"isDirectory"`
|
||||
IsSymlink bool `json:"isSymlink"`
|
||||
Size int64 `json:"size"`
|
||||
ModTime time.Time `json:"modTime"`
|
||||
AccessTime time.Time `json:"atime"`
|
||||
CreateTime time.Time `json:"birthtime"`
|
||||
Mode os.FileMode `json:"mode"`
|
||||
Name string `json:"name"` // 文件名
|
||||
Path string `json:"path"` // 文件路径
|
||||
OldPath string `json:"oldPath"` // 旧的文件路径
|
||||
ParentPath string `json:"parentPath"` // 父目录路径
|
||||
Content string `json:"content"` // 文件内容
|
||||
Ext string `json:"ext"` // 文件扩展名
|
||||
Title string `json:"title"` // 文件名(不包含扩展名)
|
||||
ID int `json:"id,omitempty"` // 文件ID(可选)
|
||||
}
|
||||
|
||||
func writeJSONResponse(w http.ResponseWriter, res APIResponse, status int) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(status)
|
||||
json.NewEncoder(w).Encode(res)
|
||||
}
|
||||
|
||||
// HTTPError 返回带有JSON错误消息的HTTP错误
|
||||
func HTTPError(w http.ResponseWriter, status int, message string) {
|
||||
writeJSONResponse(w, APIResponse{Message: message, Code: -1}, status)
|
||||
}
|
||||
func ErrorMsg(w http.ResponseWriter, message string) {
|
||||
writeJSONResponse(w, APIResponse{Message: message, Code: -1}, 200)
|
||||
}
|
||||
func SuccessMsg(w http.ResponseWriter, data any, message string) {
|
||||
writeJSONResponse(w, APIResponse{Message: message, Data: data, Code: 0}, 200)
|
||||
}
|
||||
|
||||
// validateFilePath 验证路径不为空
|
||||
func validateFilePath(path string) error {
|
||||
if path == "" {
|
||||
return fmt.Errorf("empty path")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// validateFilePathPair 验证源路径和目标路径不为空
|
||||
func validateFilePathPair(src, dst string) error {
|
||||
if err := validateFilePath(src); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := validateFilePath(dst); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ReadDir reads a directory and returns a list of files
|
||||
func ReadDir(basePath, path string) ([]os.DirEntry, error) {
|
||||
fullPath := filepath.Join(basePath, path)
|
||||
return os.ReadDir(fullPath)
|
||||
}
|
||||
|
||||
// Stat retrieves file information
|
||||
func Stat(basePath, path string) (os.FileInfo, error) {
|
||||
fullPath := filepath.Join(basePath, path)
|
||||
return os.Stat(fullPath)
|
||||
}
|
||||
|
||||
// Exists checks if a file or directory exists
|
||||
func Exists(basePath, path string) bool {
|
||||
fullPath := filepath.Join(basePath, path)
|
||||
// _, err := os.Stat(fullPath)
|
||||
// return err == nil
|
||||
return libs.PathExists(fullPath)
|
||||
}
|
||||
|
||||
// ReadFile reads a file's content
|
||||
func ReadFile(basePath, path string) ([]byte, error) {
|
||||
fullPath := filepath.Join(basePath, path)
|
||||
return os.ReadFile(fullPath)
|
||||
}
|
||||
|
||||
// Unlink removes a file
|
||||
func Unlink(basePath, path string) error {
|
||||
fullPath := filepath.Join(basePath, path)
|
||||
return os.Remove(fullPath)
|
||||
}
|
||||
|
||||
// Clear removes the entire filesystem
|
||||
func Clear(basePath string) error {
|
||||
return os.RemoveAll(basePath)
|
||||
}
|
||||
|
||||
// Rename renames a file
|
||||
func Rename(basePath, oldPath, newPath string) error {
|
||||
return os.Rename(filepath.Join(basePath, oldPath), filepath.Join(basePath, newPath))
|
||||
}
|
||||
|
||||
// Mkdir creates a directory
|
||||
func Mkdir(basePath, dirPath string) error {
|
||||
fullPath := filepath.Join(basePath, dirPath)
|
||||
return os.MkdirAll(fullPath, 0755)
|
||||
}
|
||||
|
||||
// Rmdir removes a directory
|
||||
func Rmdir(basePath, dirPath string) error {
|
||||
fullPath := filepath.Join(basePath, dirPath)
|
||||
return os.RemoveAll(fullPath)
|
||||
}
|
||||
|
||||
// CopyFile copies a file
|
||||
func CopyFile(src, dst string) error {
|
||||
sf, err := os.Open(src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer sf.Close()
|
||||
|
||||
df, err := os.Create(dst)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer df.Close()
|
||||
|
||||
_, err = io.Copy(df, sf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = df.Sync()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return df.Close()
|
||||
}
|
||||
|
||||
// WriteFile writes content to a file
|
||||
func WriteFile(filePath string, content []byte, perm os.FileMode) error {
|
||||
return os.WriteFile(filePath, content, perm)
|
||||
}
|
||||
|
||||
// AppendToFile appends content to a file
|
||||
// AppendToFile appends the given content to the specified file.
|
||||
// It assumes that 'content' is an io.Reader representing the data to append.
|
||||
func AppendToFile(filePath string, content io.Reader) error {
|
||||
file, err := os.OpenFile(filePath, os.O_APPEND|os.O_WRONLY, 0644)
|
||||
if err != nil {
|
||||
// 文件不存在或打开时发生其他错误
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
// 将内容写入文件
|
||||
if _, err := io.Copy(file, content); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
func Chmod(basePath string, path string, mode os.FileMode) error {
|
||||
fullPath := filepath.Join(basePath, path)
|
||||
return os.Chmod(fullPath, mode)
|
||||
}
|
||||
|
||||
// GetFileInfo 从fs.DirEntry或路径获取文件信息
|
||||
func GetFileInfo(entry interface{}, basePath, parentPath string) (*OsFileInfo, error) {
|
||||
var fileInfo os.FileInfo
|
||||
var err error
|
||||
var filePath string
|
||||
|
||||
switch v := entry.(type) {
|
||||
case fs.DirEntry:
|
||||
// 如果传入的是fs.DirEntry
|
||||
fileInfo, err = v.Info()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get file info from DirEntry: %v", err)
|
||||
}
|
||||
filePath = filepath.Join(basePath, parentPath, fileInfo.Name())
|
||||
case string:
|
||||
// 如果传入的是路径字符串
|
||||
filePath = filepath.Join(basePath, parentPath, v)
|
||||
fileInfo, err = os.Stat(filePath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to stat file from path: %v", err)
|
||||
}
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported type provided to GetFileInfo, expected fs.DirEntry or string")
|
||||
}
|
||||
|
||||
osFileInfo := &OsFileInfo{
|
||||
Name: fileInfo.Name(),
|
||||
Path: filePath, // 根据实际情况调整,可能需要使用之前构造的完整路径filePath
|
||||
}
|
||||
|
||||
// 初始化其他字段,如IsFile, IsDir, Size等
|
||||
osFileInfo.ID = 0
|
||||
osFileInfo.IsFile = !fileInfo.IsDir()
|
||||
osFileInfo.IsDir = fileInfo.IsDir()
|
||||
osFileInfo.Size = fileInfo.Size()
|
||||
osFileInfo.ModTime = fileInfo.ModTime()
|
||||
osFileInfo.AccessTime = fileInfo.ModTime() // 注意:os.FileInfo没有直接提供访问时间,这里用修改时间代替
|
||||
osFileInfo.CreateTime = fileInfo.ModTime() // 同上,仅作示例
|
||||
osFileInfo.Mode = fileInfo.Mode()
|
||||
|
||||
osFileInfo.Path = strings.TrimPrefix(filePath, basePath)
|
||||
osFileInfo.OldPath = osFileInfo.Path
|
||||
osFileInfo.ParentPath = parentPath
|
||||
osFileInfo.Title = strings.TrimSuffix(osFileInfo.Name, filepath.Ext(osFileInfo.Name))
|
||||
osFileInfo.Ext = strings.TrimPrefix(filepath.Ext(osFileInfo.Name), ".")
|
||||
|
||||
return osFileInfo, nil
|
||||
}
|
||||
84
cmd/serve.go
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"sync"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
func Serve(srv *http.Server) {
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(1)
|
||||
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
|
||||
log.Fatalf("Error starting server: %v\n", err)
|
||||
}
|
||||
}()
|
||||
// 监听退出信号
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
go func() {
|
||||
c := make(chan os.Signal, 1)
|
||||
signal.Notify(c, syscall.SIGINT, syscall.SIGTERM)
|
||||
<-c
|
||||
log.Println("Received signal, gracefully shutting down...")
|
||||
cancel()
|
||||
}()
|
||||
|
||||
<-ctx.Done()
|
||||
shutdownCtx, shutdownCancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer shutdownCancel()
|
||||
if err := srv.Shutdown(shutdownCtx); err != nil {
|
||||
log.Printf("Error during server shutdown: %v\n", err)
|
||||
}
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
type loggingMiddleware struct {
|
||||
}
|
||||
|
||||
func (l loggingMiddleware) Middleware(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
startTime := time.Now()
|
||||
defer func() {
|
||||
log.Printf(
|
||||
"%s %s %s %v",
|
||||
r.Method,
|
||||
r.URL.Path,
|
||||
r.Proto,
|
||||
time.Since(startTime),
|
||||
)
|
||||
}()
|
||||
next.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
|
||||
// CORS 中间件
|
||||
func corsMiddleware() mux.MiddlewareFunc {
|
||||
allowHeaders := "Content-Type, Accept, Authorization, Origin"
|
||||
allowMethods := "GET, POST, PUT, DELETE, OPTIONS"
|
||||
|
||||
return func(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Access-Control-Allow-Origin", "*")
|
||||
w.Header().Set("Access-Control-Allow-Methods", allowMethods)
|
||||
w.Header().Set("Access-Control-Allow-Headers", allowHeaders)
|
||||
|
||||
// 如果是预检请求(OPTIONS),直接返回 200 OK
|
||||
// if r.Method == http.MethodOptions {
|
||||
// w.WriteHeader(http.StatusOK)
|
||||
// return
|
||||
// }
|
||||
|
||||
next.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
}
|
||||
184
cmd/watch.go
Normal file
|
|
@ -0,0 +1,184 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"godoos/libs"
|
||||
"log"
|
||||
"net/http"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/fsnotify/fsnotify"
|
||||
)
|
||||
|
||||
// FileChangeEvent 封装文件系统变更事件为可序列化的结构体
|
||||
type FileChangeEvent struct {
|
||||
Action string `json:"action"` // create, modify, delete, rename
|
||||
Path string `json:"path"` // 文件或目录的路径
|
||||
}
|
||||
|
||||
// sseStream 结构体用于维护SSE连接和事件发送
|
||||
type sseStream struct {
|
||||
conn http.ResponseWriter
|
||||
mu sync.Mutex
|
||||
ctx context.Context
|
||||
cancel context.CancelFunc
|
||||
eventChannel chan FileChangeEvent
|
||||
}
|
||||
|
||||
func newSSEStream(w http.ResponseWriter) *sseStream {
|
||||
stream := &sseStream{
|
||||
conn: w,
|
||||
eventChannel: make(chan FileChangeEvent),
|
||||
}
|
||||
stream.ctx, stream.cancel = context.WithCancel(context.Background())
|
||||
return stream
|
||||
}
|
||||
|
||||
// sendEvent 向SSE连接发送事件
|
||||
func (s *sseStream) sendEvent(event FileChangeEvent) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
if s.conn == nil {
|
||||
return
|
||||
}
|
||||
|
||||
data, err := json.Marshal(event)
|
||||
if err != nil {
|
||||
log.Printf("Error marshaling event: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Fprintf(s.conn, "id: %d\n", time.Now().UnixNano())
|
||||
fmt.Fprintf(s.conn, "event: change\n")
|
||||
fmt.Fprintf(s.conn, "data: %s\n\n", data)
|
||||
}
|
||||
|
||||
// WatchFileSystem watches for changes in a directory and returns a channel for events
|
||||
func WatchFileSystem(dirPath string) (<-chan fsnotify.Event, <-chan error, context.CancelFunc) {
|
||||
watcher, err := fsnotify.NewWatcher()
|
||||
if err != nil {
|
||||
errChan := make(chan error, 1)
|
||||
errChan <- err
|
||||
close(errChan)
|
||||
return nil, errChan, func() {}
|
||||
}
|
||||
|
||||
events := make(chan fsnotify.Event)
|
||||
errors := make(chan error, 1)
|
||||
|
||||
var wg sync.WaitGroup
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
|
||||
// Start watching for events
|
||||
go func() {
|
||||
defer func() {
|
||||
wg.Wait()
|
||||
close(events)
|
||||
close(errors)
|
||||
}()
|
||||
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
if err := watcher.Add(dirPath); err != nil {
|
||||
errors <- fmt.Errorf("failed to watch directory %q: %v", dirPath, err)
|
||||
cancel()
|
||||
return
|
||||
}
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
case event, ok := <-watcher.Events:
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
events <- event
|
||||
case err := <-watcher.Errors:
|
||||
errors <- err
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
// Handle context cancellation
|
||||
<-ctx.Done()
|
||||
if err := watcher.Close(); err != nil {
|
||||
log.Printf("Error closing watcher: %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
return events, errors, cancel
|
||||
}
|
||||
func WatchHandler(w http.ResponseWriter, r *http.Request) {
|
||||
dirToWatch := r.URL.Query().Get("filePath")
|
||||
basePath, err := libs.GetOsDir()
|
||||
if err != nil {
|
||||
HTTPError(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
filePath := filepath.Join(basePath, dirToWatch)
|
||||
if !libs.PathExists(filePath) {
|
||||
HTTPError(w, http.StatusNotFound, "filepath is not exist!")
|
||||
return
|
||||
}
|
||||
StartSSEStream(w, r, filePath)
|
||||
}
|
||||
|
||||
// StartSSEStream 处理SSE连接,持续监听并发送事件
|
||||
func StartSSEStream(w http.ResponseWriter, r *http.Request, dirPath string) {
|
||||
stream := newSSEStream(w)
|
||||
defer stream.cancel()
|
||||
|
||||
setupSSEHeaders(w)
|
||||
|
||||
events, errors, cancel := WatchFileSystem(dirPath)
|
||||
defer cancel()
|
||||
|
||||
go handleEvents(stream, events, errors)
|
||||
|
||||
// 等待客户端断开连接或请求上下文结束
|
||||
<-r.Context().Done()
|
||||
}
|
||||
|
||||
// setupSSEHeaders 设置SSE响应头
|
||||
func setupSSEHeaders(w http.ResponseWriter) {
|
||||
w.Header().Set("Content-Type", "text/event-stream")
|
||||
w.Header().Set("Cache-Control", "no-cache")
|
||||
w.Header().Set("Connection", "keep-alive")
|
||||
}
|
||||
|
||||
// handleEvents 处理接收到的文件系统事件和错误
|
||||
func handleEvents(stream *sseStream, events <-chan fsnotify.Event, errors <-chan error) {
|
||||
for {
|
||||
select {
|
||||
case <-stream.ctx.Done():
|
||||
return
|
||||
case event := <-events:
|
||||
stream.sendEvent(convertEvent(event))
|
||||
case err := <-errors:
|
||||
log.Printf("Error from fsnotify: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// convertEvent 将fsnotify.Event转换为FileChangeEvent
|
||||
func convertEvent(fsEvent fsnotify.Event) FileChangeEvent {
|
||||
var action string
|
||||
switch fsEvent.Op {
|
||||
case fsnotify.Create:
|
||||
action = "create"
|
||||
case fsnotify.Write:
|
||||
action = "modify"
|
||||
case fsnotify.Remove:
|
||||
action = "delete"
|
||||
case fsnotify.Rename:
|
||||
action = "rename"
|
||||
default:
|
||||
action = "unknown"
|
||||
}
|
||||
return FileChangeEvent{Action: action, Path: fsEvent.Name}
|
||||
}
|
||||
24
frontend/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
|
||||
node_modules
|
||||
dist
|
||||
dist-ssr
|
||||
*.local
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
.idea
|
||||
.DS_Store
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
7
frontend/.vscode/extensions.json
vendored
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"recommendations": [
|
||||
"Vue.volar",
|
||||
"tauri-apps.tauri-vscode",
|
||||
"rust-lang.rust-analyzer"
|
||||
]
|
||||
}
|
||||
16
frontend/README.md
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
# Tauri + Vue + TypeScript
|
||||
|
||||
This template should help get you started developing with Vue 3 and TypeScript in Vite. The template uses Vue 3 `<script setup>` SFCs, check out the [script setup docs](https://v3.vuejs.org/api/sfc-script-setup.html#sfc-script-setup) to learn more.
|
||||
|
||||
## Recommended IDE Setup
|
||||
|
||||
- [VS Code](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) + [Tauri](https://marketplace.visualstudio.com/items?itemName=tauri-apps.tauri-vscode) + [rust-analyzer](https://marketplace.visualstudio.com/items?itemName=rust-lang.rust-analyzer)
|
||||
|
||||
## Type Support For `.vue` Imports in TS
|
||||
|
||||
Since TypeScript cannot handle type information for `.vue` imports, they are shimmed to be a generic Vue component type by default. In most cases this is fine if you don't really care about component prop types outside of templates. However, if you wish to get actual prop types in `.vue` imports (for example to get props validation when using manual `h(...)` calls), you can enable Volar's Take Over mode by following these steps:
|
||||
|
||||
1. Run `Extensions: Show Built-in Extensions` from VS Code's command palette, look for `TypeScript and JavaScript Language Features`, then right click and select `Disable (Workspace)`. By default, Take Over mode will enable itself if the default TypeScript extension is disabled.
|
||||
2. Reload the VS Code window by running `Developer: Reload Window` from the command palette.
|
||||
|
||||
You can learn more about Take Over mode [here](https://github.com/johnsoncodehk/volar/discussions/471).
|
||||
71
frontend/auto-imports.d.ts
vendored
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
/* eslint-disable */
|
||||
/* prettier-ignore */
|
||||
// @ts-nocheck
|
||||
// noinspection JSUnusedGlobalSymbols
|
||||
// Generated by unplugin-auto-import
|
||||
export {}
|
||||
declare global {
|
||||
const EffectScope: typeof import('vue')['EffectScope']
|
||||
const computed: typeof import('vue')['computed']
|
||||
const createApp: typeof import('vue')['createApp']
|
||||
const customRef: typeof import('vue')['customRef']
|
||||
const defineAsyncComponent: typeof import('vue')['defineAsyncComponent']
|
||||
const defineComponent: typeof import('vue')['defineComponent']
|
||||
const effectScope: typeof import('vue')['effectScope']
|
||||
const getCurrentInstance: typeof import('vue')['getCurrentInstance']
|
||||
const getCurrentScope: typeof import('vue')['getCurrentScope']
|
||||
const h: typeof import('vue')['h']
|
||||
const inject: typeof import('vue')['inject']
|
||||
const isProxy: typeof import('vue')['isProxy']
|
||||
const isReactive: typeof import('vue')['isReactive']
|
||||
const isReadonly: typeof import('vue')['isReadonly']
|
||||
const isRef: typeof import('vue')['isRef']
|
||||
const markRaw: typeof import('vue')['markRaw']
|
||||
const nextTick: typeof import('vue')['nextTick']
|
||||
const onActivated: typeof import('vue')['onActivated']
|
||||
const onBeforeMount: typeof import('vue')['onBeforeMount']
|
||||
const onBeforeRouteLeave: typeof import('vue-router')['onBeforeRouteLeave']
|
||||
const onBeforeRouteUpdate: typeof import('vue-router')['onBeforeRouteUpdate']
|
||||
const onBeforeUnmount: typeof import('vue')['onBeforeUnmount']
|
||||
const onBeforeUpdate: typeof import('vue')['onBeforeUpdate']
|
||||
const onDeactivated: typeof import('vue')['onDeactivated']
|
||||
const onErrorCaptured: typeof import('vue')['onErrorCaptured']
|
||||
const onMounted: typeof import('vue')['onMounted']
|
||||
const onRenderTracked: typeof import('vue')['onRenderTracked']
|
||||
const onRenderTriggered: typeof import('vue')['onRenderTriggered']
|
||||
const onScopeDispose: typeof import('vue')['onScopeDispose']
|
||||
const onServerPrefetch: typeof import('vue')['onServerPrefetch']
|
||||
const onUnmounted: typeof import('vue')['onUnmounted']
|
||||
const onUpdated: typeof import('vue')['onUpdated']
|
||||
const provide: typeof import('vue')['provide']
|
||||
const reactive: typeof import('vue')['reactive']
|
||||
const readonly: typeof import('vue')['readonly']
|
||||
const ref: typeof import('vue')['ref']
|
||||
const resolveComponent: typeof import('vue')['resolveComponent']
|
||||
const shallowReactive: typeof import('vue')['shallowReactive']
|
||||
const shallowReadonly: typeof import('vue')['shallowReadonly']
|
||||
const shallowRef: typeof import('vue')['shallowRef']
|
||||
const toRaw: typeof import('vue')['toRaw']
|
||||
const toRef: typeof import('vue')['toRef']
|
||||
const toRefs: typeof import('vue')['toRefs']
|
||||
const toValue: typeof import('vue')['toValue']
|
||||
const triggerRef: typeof import('vue')['triggerRef']
|
||||
const unref: typeof import('vue')['unref']
|
||||
const useAttrs: typeof import('vue')['useAttrs']
|
||||
const useCssModule: typeof import('vue')['useCssModule']
|
||||
const useCssVars: typeof import('vue')['useCssVars']
|
||||
const useLink: typeof import('vue-router')['useLink']
|
||||
const useRoute: typeof import('vue-router')['useRoute']
|
||||
const useRouter: typeof import('vue-router')['useRouter']
|
||||
const useSlots: typeof import('vue')['useSlots']
|
||||
const watch: typeof import('vue')['watch']
|
||||
const watchEffect: typeof import('vue')['watchEffect']
|
||||
const watchPostEffect: typeof import('vue')['watchPostEffect']
|
||||
const watchSyncEffect: typeof import('vue')['watchSyncEffect']
|
||||
}
|
||||
// for type re-export
|
||||
declare global {
|
||||
// @ts-ignore
|
||||
export type { Component, ComponentPublicInstance, ComputedRef, ExtractDefaultPropTypes, ExtractPropTypes, ExtractPublicPropTypes, InjectionKey, PropType, Ref, VNode, WritableComputedRef } from 'vue'
|
||||
import('vue')
|
||||
}
|
||||
121
frontend/components.d.ts
vendored
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
/* eslint-disable */
|
||||
// @ts-nocheck
|
||||
// Generated by unplugin-vue-components
|
||||
// Read more: https://github.com/vuejs/core/pull/3399
|
||||
export {}
|
||||
|
||||
/* prettier-ignore */
|
||||
declare module 'vue' {
|
||||
export interface GlobalComponents {
|
||||
AppIcon: typeof import('./src/components/taskbar/AppIcon.vue')['default']
|
||||
AppIconGroup: typeof import('./src/components/taskbar/AppIconGroup.vue')['default']
|
||||
AppItem: typeof import('./src/components/builtin/AppItem.vue')['default']
|
||||
Battery: typeof import('./src/components/taskbar/Battery.vue')['default']
|
||||
BatteryPop: typeof import('./src/components/taskbar/BatteryPop.vue')['default']
|
||||
Browser: typeof import('./src/components/builtin/Browser.vue')['default']
|
||||
Calendar: typeof import('./src/components/builtin/Calendar.vue')['default']
|
||||
CloseButton: typeof import('./src/components/ui/CloseButton.vue')['default']
|
||||
CloseDesktop: typeof import('./src/components/desktop/CloseDesktop.vue')['default']
|
||||
ColorPicker: typeof import('./src/components/setting/ColorPicker.vue')['default']
|
||||
Compony: typeof import('./src/components/install/compony.vue')['default']
|
||||
Computer: typeof import('./src/components/computer/Computer.vue')['default']
|
||||
ComputerNavBar: typeof import('./src/components/computer/ComputerNavBar.vue')['default']
|
||||
ContextMenu: typeof import('./src/components/builtin/ContextMenu.vue')['default']
|
||||
CreateUrl: typeof import('./src/components/builtin/CreateUrl.vue')['default']
|
||||
CustomIcon: typeof import('./src/components/taskbar/CustomIcon.vue')['default']
|
||||
DateNote: typeof import('./src/components/builtin/DateNote.vue')['default']
|
||||
DateTime: typeof import('./src/components/taskbar/DateTime.vue')['default']
|
||||
DateTimePop: typeof import('./src/components/taskbar/DateTimePop.vue')['default']
|
||||
DeskItem: typeof import('./src/components/desktop/DeskItem.vue')['default']
|
||||
Desktop: typeof import('./src/components/desktop/Desktop.vue')['default']
|
||||
DesktopBackground: typeof import('./src/components/desktop/DesktopBackground.vue')['default']
|
||||
DialogProcess: typeof import('./src/components/window/DialogProcess.vue')['default']
|
||||
DialogTemp: typeof import('./src/components/window/DialogTemp.vue')['default']
|
||||
EditFileName: typeof import('./src/components/builtin/EditFileName.vue')['default']
|
||||
EditType: typeof import('./src/components/builtin/EditType.vue')['default']
|
||||
ElButton: typeof import('element-plus/es')['ElButton']
|
||||
ElCard: typeof import('element-plus/es')['ElCard']
|
||||
ElCol: typeof import('element-plus/es')['ElCol']
|
||||
ElColorPicker: typeof import('element-plus/es')['ElColorPicker']
|
||||
ElDrawer: typeof import('element-plus/es')['ElDrawer']
|
||||
ElForm: typeof import('element-plus/es')['ElForm']
|
||||
ElFormItem: typeof import('element-plus/es')['ElFormItem']
|
||||
ElIcon: typeof import('element-plus/es')['ElIcon']
|
||||
ElInput: typeof import('element-plus/es')['ElInput']
|
||||
ElOption: typeof import('element-plus/es')['ElOption']
|
||||
ElRow: typeof import('element-plus/es')['ElRow']
|
||||
ElSelect: typeof import('element-plus/es')['ElSelect']
|
||||
ElText: typeof import('element-plus/es')['ElText']
|
||||
ElTooltip: typeof import('element-plus/es')['ElTooltip']
|
||||
Error: typeof import('./src/components/taskbar/Error.vue')['default']
|
||||
FileIcon: typeof import('./src/components/builtin/FileIcon.vue')['default']
|
||||
FileIconImg: typeof import('./src/components/builtin/FileIconImg.vue')['default']
|
||||
FileIconIs: typeof import('./src/components/builtin/FileIconIs.vue')['default']
|
||||
FileList: typeof import('./src/components/builtin/FileList.vue')['default']
|
||||
FileProps: typeof import('./src/components/builtin/FileProps.vue')['default']
|
||||
FileTree: typeof import('./src/components/builtin/FileTree.vue')['default']
|
||||
FileViewer: typeof import('./src/components/builtin/FileViewer.vue')['default']
|
||||
IframeFile: typeof import('./src/components/window/IframeFile.vue')['default']
|
||||
ImageViewer: typeof import('./src/components/builtin/ImageViewer.vue')['default']
|
||||
Install: typeof import('./src/components/install/Install.vue')['default']
|
||||
InstallCompony: typeof import('./src/components/install/InstallCompony.vue')['default']
|
||||
InstallMember: typeof import('./src/components/install/InstallMember.vue')['default']
|
||||
INstallMember: typeof import('./src/components/install/INstallMember.vue')['default']
|
||||
InstallPerson: typeof import('./src/components/install/InstallPerson.vue')['default']
|
||||
LockDesktop: typeof import('./src/components/desktop/LockDesktop.vue')['default']
|
||||
Magnet: typeof import('./src/components/taskbar/Magnet.vue')['default']
|
||||
MarkDown: typeof import('./src/components/builtin/MarkDown.vue')['default']
|
||||
Member: typeof import('./src/components/install/member.vue')['default']
|
||||
MenuBar: typeof import('./src/components/window/MenuBar.vue')['default']
|
||||
MenuList: typeof import('./src/components/taskbar/MenuList.vue')['default']
|
||||
MessageCenterPop: typeof import('./src/components/taskbar/MessageCenterPop.vue')['default']
|
||||
MessageIcon: typeof import('./src/components/taskbar/MessageIcon.vue')['default']
|
||||
MusicStore: typeof import('./src/components/builtin/MusicStore.vue')['default']
|
||||
MusicViewer: typeof import('./src/components/builtin/MusicViewer.vue')['default']
|
||||
NetWork: typeof import('./src/components/taskbar/NetWork.vue')['default']
|
||||
NetworkPop: typeof import('./src/components/taskbar/NetworkPop.vue')['default']
|
||||
NotFound: typeof import('./src/components/window/NotFound.vue')['default']
|
||||
NotifyGroup: typeof import('./src/components/builtin/NotifyGroup.vue')['default']
|
||||
OpeningDesktop: typeof import('./src/components/desktop/OpeningDesktop.vue')['default']
|
||||
OpenWiteDialog: typeof import('./src/components/builtin/OpenWiteDialog.vue')['default']
|
||||
OsImage: typeof import('./src/components/builtin/OsImage.vue')['default']
|
||||
PdfViewer: typeof import('./src/components/builtin/PdfViewer.vue')['default']
|
||||
Person: typeof import('./src/components/install/person.vue')['default']
|
||||
PictureStore: typeof import('./src/components/builtin/PictureStore.vue')['default']
|
||||
QuickLink: typeof import('./src/components/computer/QuickLink.vue')['default']
|
||||
RectChosen: typeof import('./src/components/builtin/RectChosen.vue')['default']
|
||||
RouterLink: typeof import('vue-router')['RouterLink']
|
||||
RouterView: typeof import('vue-router')['RouterView']
|
||||
Screen: typeof import('./src/components/desktop/Screen.vue')['default']
|
||||
ScreenContent: typeof import('./src/components/desktop/ScreenContent.vue')['default']
|
||||
ScreenRecorder: typeof import('./src/components/taskbar/ScreenRecorder.vue')['default']
|
||||
Screenshort: typeof import('./src/components/taskbar/Screenshort.vue')['default']
|
||||
SetAccount: typeof import('./src/components/setting/SetAccount.vue')['default']
|
||||
SetCustom: typeof import('./src/components/setting/SetCustom.vue')['default']
|
||||
SetLang: typeof import('./src/components/setting/SetLang.vue')['default']
|
||||
SetSystem: typeof import('./src/components/setting/SetSystem.vue')['default']
|
||||
Setting: typeof import('./src/components/setting/Setting.vue')['default']
|
||||
SetUpdate: typeof import('./src/components/setting/SetUpdate.vue')['default']
|
||||
StartMenu: typeof import('./src/components/taskbar/StartMenu.vue')['default']
|
||||
StartOption: typeof import('./src/components/taskbar/StartOption.vue')['default']
|
||||
StateIcon: typeof import('./src/components/taskbar/StateIcon.vue')['default']
|
||||
Store: typeof import('./src/components/builtin/Store.vue')['default']
|
||||
Taskbar: typeof import('./src/components/taskbar/Taskbar.vue')['default']
|
||||
UpPopover: typeof import('./src/components/computer/UpPopover.vue')['default']
|
||||
UrlBrowser: typeof import('./src/components/builtin/UrlBrowser.vue')['default']
|
||||
Version: typeof import('./src/components/builtin/Version.vue')['default']
|
||||
VideoViewer: typeof import('./src/components/builtin/VideoViewer.vue')['default']
|
||||
WinButton: typeof import('./src/components/ui/WinButton.vue')['default']
|
||||
WinCheckBox: typeof import('./src/components/ui/WinCheckBox.vue')['default']
|
||||
WindowGroup: typeof import('./src/components/window/WindowGroup.vue')['default']
|
||||
WindowInner: typeof import('./src/components/window/WindowInner.vue')['default']
|
||||
WindowNode: typeof import('./src/components/window/WindowNode.vue')['default']
|
||||
WindowTemplate: typeof import('./src/components/window/WindowTemplate.vue')['default']
|
||||
WinInput: typeof import('./src/components/ui/WinInput.vue')['default']
|
||||
WinLoading: typeof import('./src/components/ui/WinLoading.vue')['default']
|
||||
WinLogo: typeof import('./src/components/ui/WinLogo.vue')['default']
|
||||
WinProcess: typeof import('./src/components/ui/WinProcess.vue')['default']
|
||||
WinSelect: typeof import('./src/components/ui/WinSelect.vue')['default']
|
||||
WinUpButtonGroup: typeof import('./src/components/ui/WinUpButtonGroup.vue')['default']
|
||||
}
|
||||
}
|
||||
7
frontend/env.d.ts
vendored
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
declare module '*.vue' {
|
||||
import type { DefineComponent } from 'vue'
|
||||
const component: DefineComponent<{}, {}, any>
|
||||
export default component
|
||||
}
|
||||
declare module '*.png';
|
||||
declare module '*.ts';
|
||||
25
frontend/index.html
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/icon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>GodoOS</title>
|
||||
<script src="/font/iconfont.js"></script>
|
||||
<style>
|
||||
.icon {
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
vertical-align: -0.15em;
|
||||
fill: currentColor;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.ts"></script>
|
||||
</body>
|
||||
</html>
|
||||
38
frontend/package.json
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
{
|
||||
"name": "godoos",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vue-tsc --noEmit && vite build",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"@element-plus/icons-vue": "^2.3.1",
|
||||
"@liripeng/vue-audio-player": "^1.6.2",
|
||||
"element-plus": "^2.7.7",
|
||||
"file-saver": "^2.0.5",
|
||||
"jszip": "^3.10.1",
|
||||
"lunar-typescript": "^1.7.5",
|
||||
"moment": "^2.30.1",
|
||||
"pinia": "^2.1.7",
|
||||
"pinia-plugin-persist": "^1.0.0",
|
||||
"vditor": "^3.10.4",
|
||||
"vue": "^3.4.31",
|
||||
"vue-router": "^4.4.0",
|
||||
"vue-web-screen-shot": "^1.5.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/file-saver": "^2.0.7",
|
||||
"@types/node": "^20.14.10",
|
||||
"@vitejs/plugin-vue": "^5.0.5",
|
||||
"sass": "^1.77.8",
|
||||
"terser": "^5.31.3",
|
||||
"typescript": "^5.5.3",
|
||||
"unplugin-auto-import": "^0.18.0",
|
||||
"unplugin-vue-components": "^0.27.2",
|
||||
"vite": "^5.3.3",
|
||||
"vue-tsc": "^2.0.26"
|
||||
}
|
||||
}
|
||||
1
frontend/package.json.md5
Executable file
|
|
@ -0,0 +1 @@
|
|||
46b0e0f4287bf8042cfe0a66114c4afc
|
||||
1617
frontend/pnpm-lock.yaml
Normal file
345
frontend/public/baiban/assets/index-BBuZupZQ.js
Normal file
345
frontend/public/baiban/assets/index-C7Nv1nqD.js
Normal file
345
frontend/public/baiban/assets/index-CB2-j8Sp.js
Normal file
1
frontend/public/baiban/assets/index-CbiYJP60.css
Normal file
345
frontend/public/baiban/assets/index-CdI7WPm4.js
Normal file
345
frontend/public/baiban/assets/index-D7I3m8ha.js
Normal file
337
frontend/public/baiban/assets/index-DQ-zJgK-.js
Normal file
1
frontend/public/baiban/assets/index-DQ5iesJJ.css
Normal file
1
frontend/public/baiban/assets/index-e9sqCFI7.css
Normal file
345
frontend/public/baiban/assets/index-kFFNEmpN.js
Normal file
14
frontend/public/baiban/index.html
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
<!doctype html>
|
||||
<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.0" />
|
||||
<title>draw</title>
|
||||
<script type="module" crossorigin src="./assets/index-DQ-zJgK-.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="./assets/index-e9sqCFI7.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
</body>
|
||||
</html>
|
||||
1
frontend/public/baiban/save.svg
Executable file
|
|
@ -0,0 +1 @@
|
|||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1717909582361" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4272" width="32" height="32" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M931.882 259.882l-167.764-167.764A96 96 0 0 0 696.236 64H160C106.98 64 64 106.98 64 160v704c0 53.02 42.98 96 96 96h704c53.02 0 96-42.98 96-96V327.764a96 96 0 0 0-28.118-67.882zM512 832c-70.692 0-128-57.308-128-128 0-70.692 57.308-128 128-128s128 57.308 128 128c0 70.692-57.308 128-128 128z m192-609.04V424c0 13.254-10.746 24-24 24H216c-13.254 0-24-10.746-24-24V216c0-13.254 10.746-24 24-24h457.04c6.366 0 12.47 2.528 16.97 7.03l6.96 6.96A23.992 23.992 0 0 1 704 222.96z" p-id="4273"></path></svg>
|
||||
|
After Width: | Height: | Size: 827 B |
BIN
frontend/public/baiban/static/card-repo.png
Executable file
|
After Width: | Height: | Size: 8.3 KiB |
26
frontend/public/baiban/static/card_repo.svg
Executable file
|
|
@ -0,0 +1,26 @@
|
|||
<svg width="1080" height="160" viewBox="0 0 1080 160" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<mask id="path-1-outside-1_3296_32770" maskUnits="userSpaceOnUse" x="364" y="27" width="342" height="106" fill="black">
|
||||
<rect fill="white" x="364" y="27" width="342" height="106"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M377 48.7912C377 43.936 380.798 40 385.482 40H449.098C453.783 40 457.58 43.936 457.58 48.7912V111.209C457.58 116.064 453.783 120 449.098 120H385.482C380.798 120 377 116.064 377 111.209V48.7912ZM424.571 62.8801C424.571 64.8134 423.905 66.4539 422.574 67.8014C421.243 69.1489 419.622 69.8226 417.712 69.8226C415.744 69.8226 414.095 69.1489 412.764 67.8014C411.433 66.4539 410.767 64.8134 410.767 62.8801C410.767 60.9467 411.433 59.3063 412.764 57.9588C414.095 56.6113 415.744 55.9375 417.712 55.9375C419.622 55.9375 421.243 56.6113 422.574 57.9588C423.905 59.3063 424.571 60.9467 424.571 62.8801ZM410.68 87.2107C410.68 85.2774 411.346 83.6369 412.677 82.2894C414.066 80.8833 415.744 80.1803 417.712 80.1803C419.564 80.1803 421.185 80.8833 422.574 82.2894C423.963 83.6369 424.774 85.1602 425.005 86.8592C425.468 90.0229 424.889 93.1573 423.269 96.2624C421.706 99.3675 419.449 101.74 416.497 103.381C414.876 104.318 413.545 104.289 412.503 103.293C411.519 102.355 411.809 101.242 413.371 99.9534C414.24 99.309 414.963 98.4887 415.542 97.4928C416.121 96.4968 416.497 95.4715 416.671 94.4169C416.728 93.9482 416.526 93.7139 416.063 93.7139C414.905 93.6553 413.719 93.0108 412.503 91.7805C411.288 90.5502 410.68 89.0269 410.68 87.2107Z"/>
|
||||
<path d="M529.906 104.783C530.387 104.783 530.628 104.543 530.628 104.065V94.3261C530.628 93.3656 529.844 92.587 528.877 92.587H527.607C527.212 92.587 526.906 92.4783 526.687 92.2609C526.512 92.087 526.424 91.8261 526.424 91.4783V56.587C526.424 56.1087 526.183 55.8696 525.701 55.8696H514.644C513.676 55.8696 512.892 56.6482 512.892 57.6087V95.3913C512.892 98.5217 513.79 100.87 515.585 102.435C517.381 104 519.68 104.783 522.483 104.783H529.906Z"/>
|
||||
<path d="M507.242 94.2609C507.242 93.3004 506.458 92.5217 505.491 92.5217H500.87C499.381 92.5217 498.374 92.2609 497.849 91.7391C497.192 91.1304 496.863 90.1522 496.863 88.8043V83.0435C496.863 82.083 497.648 81.3043 498.615 81.3043H505.491C506.458 81.3043 507.242 80.5257 507.242 79.5652V69.8261C507.242 69.3478 507.002 69.1087 506.52 69.1087H498.615C497.648 69.1087 496.863 68.3301 496.863 67.3696V59.8478C496.863 59.3696 496.622 59.1304 496.141 59.1304H485.477C484.51 59.1304 483.725 59.9091 483.725 60.8696V67.3696C483.725 68.3301 482.941 69.1087 481.973 69.1087H480.353C479.386 69.1087 478.601 69.8873 478.601 70.8478V80.587C478.601 81.0652 478.842 81.3043 479.324 81.3043H481.973C482.941 81.3043 483.725 82.083 483.725 83.0435V89.7826C483.725 94.8261 485.061 98.587 487.732 101.065C490.404 103.543 494.28 104.783 499.36 104.783H506.52C507.002 104.783 507.242 104.543 507.242 104.065V94.2609Z"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M545.711 68.4565C547.726 68.4565 549.456 68.9565 550.901 69.9565C552.262 70.8705 553.385 72.0568 554.27 73.5156C554.426 73.7713 554.701 73.9348 555.001 73.9348C555.458 73.9348 555.828 73.5675 555.828 73.1144V57.6087C555.828 56.6482 556.612 55.8696 557.58 55.8696H568.243C568.725 55.8696 568.966 56.1087 568.966 56.587V103.043C568.966 104.004 568.182 104.783 567.214 104.783H556.55C556.069 104.783 555.828 104.543 555.828 104.065V100.148C555.828 99.6821 555.447 99.3043 554.978 99.3043C554.689 99.3043 554.42 99.4511 554.259 99.6893C553.14 101.339 551.89 102.689 550.507 103.739C549.018 104.87 547.157 105.435 544.923 105.435C541.901 105.435 539.515 104.413 537.763 102.37C536.011 100.326 535.135 97.587 535.135 94.1522V80.4565C535.135 76.7174 536.033 73.7826 537.829 71.6522C539.668 69.5217 542.296 68.4565 545.711 68.4565ZM548.996 93.0435C549.478 93.5652 550.332 93.8261 551.558 93.8261C552.797 93.8261 553.886 93.6774 554.825 93.3801C555.457 93.18 555.828 92.5622 555.828 91.9034V81.5829C555.828 81.0014 555.542 80.4427 555.014 80.1911C554.6 79.9938 554.171 79.8431 553.726 79.7391C552.981 79.5217 552.259 79.413 551.558 79.413C549.324 79.413 548.208 80.5217 548.208 82.7391V90.5652C548.208 91.7391 548.47 92.5652 548.996 93.0435Z"/>
|
||||
<path d="M588.228 104.783C589.195 104.783 589.98 104.004 589.98 103.043V84.6928C589.98 84.0869 590.292 83.5143 590.842 83.2503C591.381 82.9911 591.947 82.7772 592.542 82.6087C593.461 82.3044 594.49 82.1522 595.629 82.1522C596.461 82.1522 597.249 82.2174 597.994 82.3478C598.726 82.469 599.44 82.6277 600.134 82.8239C600.24 82.8537 600.349 82.8696 600.458 82.8696C601.093 82.8696 601.607 82.3591 601.607 81.7294V69.8261C601.607 69.5217 601.497 69.2609 601.278 69.0435C601.147 68.913 600.906 68.7826 600.556 68.6522C600.205 68.5217 599.68 68.4565 598.979 68.4565C596.921 68.4565 595.279 69.087 594.052 70.3478C592.966 71.4664 592.12 73.0989 591.514 75.2453C591.418 75.5851 591.11 75.8261 590.754 75.8261C590.326 75.8261 589.98 75.4818 589.98 75.057V69.8261C589.98 69.3478 589.739 69.1087 589.257 69.1087H578.396C577.429 69.1087 576.644 69.8873 576.644 70.8478V104.065C576.644 104.543 576.885 104.783 577.367 104.783H588.228Z"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M638.295 81.8261V92.3913C638.295 92.9268 638.482 93.2772 638.855 93.4425C638.96 93.4893 639.069 93.5295 639.178 93.5672C639.3 93.6094 639.422 93.6304 639.544 93.6304H639.631C640.599 93.6304 641.383 94.4091 641.383 95.3696V104.065C641.383 104.543 641.142 104.783 640.66 104.783H636.259C634.113 104.783 632.142 104.348 630.347 103.478C628.788 102.705 627.594 101.587 626.763 100.124C626.573 99.7893 626.224 99.5652 625.837 99.5652C625.46 99.5652 625.118 99.7765 624.931 100.101C624 101.715 622.783 102.993 621.282 103.935C619.661 104.935 617.581 105.435 615.041 105.435C611.975 105.435 609.545 104.609 607.749 102.957C605.954 101.304 605.056 99.0652 605.056 96.2391V93.6957C605.056 90.6522 605.954 88.2609 607.749 86.5217C609.589 84.7826 612.172 83.913 615.501 83.913H624.697C625.205 83.913 625.617 83.5043 625.617 83C625.617 81.4783 625.201 80.4565 624.369 79.9348C623.581 79.3696 622.048 79.087 619.771 79.087C615.972 79.087 612.216 79.6361 608.503 80.7343C608.395 80.7661 608.284 80.7826 608.171 80.7826C607.539 80.7826 607.027 80.2739 607.027 79.6463V71.2609C607.027 70.9565 607.092 70.7391 607.224 70.6087C607.53 70.3043 608.362 69.9783 609.72 69.6304C611.121 69.2826 612.808 68.9783 614.778 68.7174C616.793 68.413 618.851 68.2609 620.953 68.2609C626.953 68.2609 631.332 69.3478 634.091 71.5217C636.894 73.6522 638.295 77.087 638.295 81.8261ZM619.442 96.0435C621.348 96.0435 623.127 95.6161 624.777 94.7612C625.312 94.4845 625.617 93.9194 625.617 93.3211V91.9783C625.617 91.0178 624.833 90.2391 623.865 90.2391H619.574C618.829 90.2391 618.26 90.4348 617.866 90.8261C617.515 91.2609 617.34 91.7826 617.34 92.3913V93.9565C617.34 95.3478 618.041 96.0435 619.442 96.0435Z"/>
|
||||
<path d="M664.776 69.1087C663.958 69.1087 663.25 69.6696 663.068 70.4605C662.137 74.5177 661.277 78.3279 660.489 81.8913C659.711 85.5887 659.125 89.0962 658.73 92.4139C658.682 92.8093 658.346 93.1087 657.945 93.1087C657.503 93.1087 657.147 92.7472 657.154 92.3083C657.205 88.9664 657.069 85.6245 656.744 82.2826C656.438 78.6739 656.044 74.6522 655.562 70.2174C655.518 69.7391 655.43 69.4348 655.299 69.3043C655.168 69.1739 654.971 69.1087 654.708 69.1087H645.295C644.208 69.1087 643.383 70.0825 643.568 71.1467C644.447 76.2065 645.292 81.2663 646.102 86.3261C647.066 92.0652 648.029 97.587 648.993 102.891C649.143 103.562 649.309 104.041 649.491 104.328C649.548 104.417 649.623 104.493 649.711 104.552C649.938 104.706 650.18 104.783 650.438 104.783H662.158C662.955 104.783 663.651 104.249 663.852 103.484C664.192 102.194 664.494 101.039 664.758 100.022C665.109 98.6739 665.415 97.3478 665.678 96.0435C665.941 94.7391 666.204 93.3043 666.466 91.7391C666.743 90.2865 667.038 88.5325 667.35 86.4772C667.409 86.0907 667.743 85.8043 668.137 85.8043C668.535 85.8043 668.871 86.0965 668.924 86.4877C669.191 88.4532 669.423 90.1385 669.62 91.5435C669.882 93.0652 670.123 94.413 670.342 95.587C670.605 96.7174 670.868 97.8696 671.13 99.0435C671.393 100.174 671.7 101.478 672.05 102.957C672.238 103.59 672.425 104.047 672.613 104.329C672.671 104.417 672.746 104.493 672.834 104.552C673.061 104.706 673.303 104.783 673.561 104.783H685.485C686.338 104.783 687.067 104.172 687.212 103.338L689.984 87.3043C690.991 81.4783 691.976 75.6957 692.94 69.9565C692.983 69.3913 692.786 69.1087 692.349 69.1087H682.245C681.344 69.1087 680.589 69.7887 680.503 70.68C680.125 74.5767 679.782 78.2703 679.473 81.7609C679.189 85.3908 679.055 88.9084 679.072 92.3138C679.074 92.7513 678.719 93.1087 678.278 93.1087C677.874 93.1087 677.535 92.8065 677.489 92.4081C677.091 89.0194 676.482 85.5355 675.663 81.9565C674.831 78.1304 673.911 74.087 672.904 69.8261C672.773 69.3478 672.51 69.1087 672.116 69.1087H664.776Z"/>
|
||||
</mask>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M377 48.7912C377 43.936 380.798 40 385.482 40H449.098C453.783 40 457.58 43.936 457.58 48.7912V111.209C457.58 116.064 453.783 120 449.098 120H385.482C380.798 120 377 116.064 377 111.209V48.7912ZM424.571 62.8801C424.571 64.8134 423.905 66.4539 422.574 67.8014C421.243 69.1489 419.622 69.8226 417.712 69.8226C415.744 69.8226 414.095 69.1489 412.764 67.8014C411.433 66.4539 410.767 64.8134 410.767 62.8801C410.767 60.9467 411.433 59.3063 412.764 57.9588C414.095 56.6113 415.744 55.9375 417.712 55.9375C419.622 55.9375 421.243 56.6113 422.574 57.9588C423.905 59.3063 424.571 60.9467 424.571 62.8801ZM410.68 87.2107C410.68 85.2774 411.346 83.6369 412.677 82.2894C414.066 80.8833 415.744 80.1803 417.712 80.1803C419.564 80.1803 421.185 80.8833 422.574 82.2894C423.963 83.6369 424.774 85.1602 425.005 86.8592C425.468 90.0229 424.889 93.1573 423.269 96.2624C421.706 99.3675 419.449 101.74 416.497 103.381C414.876 104.318 413.545 104.289 412.503 103.293C411.519 102.355 411.809 101.242 413.371 99.9534C414.24 99.309 414.963 98.4887 415.542 97.4928C416.121 96.4968 416.497 95.4715 416.671 94.4169C416.728 93.9482 416.526 93.7139 416.063 93.7139C414.905 93.6553 413.719 93.0108 412.503 91.7805C411.288 90.5502 410.68 89.0269 410.68 87.2107Z" fill="black"/>
|
||||
<path d="M529.906 104.783C530.387 104.783 530.628 104.543 530.628 104.065V94.3261C530.628 93.3656 529.844 92.587 528.877 92.587H527.607C527.212 92.587 526.906 92.4783 526.687 92.2609C526.512 92.087 526.424 91.8261 526.424 91.4783V56.587C526.424 56.1087 526.183 55.8696 525.701 55.8696H514.644C513.676 55.8696 512.892 56.6482 512.892 57.6087V95.3913C512.892 98.5217 513.79 100.87 515.585 102.435C517.381 104 519.68 104.783 522.483 104.783H529.906Z" fill="black"/>
|
||||
<path d="M507.242 94.2609C507.242 93.3004 506.458 92.5217 505.491 92.5217H500.87C499.381 92.5217 498.374 92.2609 497.849 91.7391C497.192 91.1304 496.863 90.1522 496.863 88.8043V83.0435C496.863 82.083 497.648 81.3043 498.615 81.3043H505.491C506.458 81.3043 507.242 80.5257 507.242 79.5652V69.8261C507.242 69.3478 507.002 69.1087 506.52 69.1087H498.615C497.648 69.1087 496.863 68.3301 496.863 67.3696V59.8478C496.863 59.3696 496.622 59.1304 496.141 59.1304H485.477C484.51 59.1304 483.725 59.9091 483.725 60.8696V67.3696C483.725 68.3301 482.941 69.1087 481.973 69.1087H480.353C479.386 69.1087 478.601 69.8873 478.601 70.8478V80.587C478.601 81.0652 478.842 81.3043 479.324 81.3043H481.973C482.941 81.3043 483.725 82.083 483.725 83.0435V89.7826C483.725 94.8261 485.061 98.587 487.732 101.065C490.404 103.543 494.28 104.783 499.36 104.783H506.52C507.002 104.783 507.242 104.543 507.242 104.065V94.2609Z" fill="black"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M545.711 68.4565C547.726 68.4565 549.456 68.9565 550.901 69.9565C552.262 70.8705 553.385 72.0568 554.27 73.5156C554.426 73.7713 554.701 73.9348 555.001 73.9348C555.458 73.9348 555.828 73.5675 555.828 73.1144V57.6087C555.828 56.6482 556.612 55.8696 557.58 55.8696H568.243C568.725 55.8696 568.966 56.1087 568.966 56.587V103.043C568.966 104.004 568.182 104.783 567.214 104.783H556.55C556.069 104.783 555.828 104.543 555.828 104.065V100.148C555.828 99.6821 555.447 99.3043 554.978 99.3043C554.689 99.3043 554.42 99.4511 554.259 99.6893C553.14 101.339 551.89 102.689 550.507 103.739C549.018 104.87 547.157 105.435 544.923 105.435C541.901 105.435 539.515 104.413 537.763 102.37C536.011 100.326 535.135 97.587 535.135 94.1522V80.4565C535.135 76.7174 536.033 73.7826 537.829 71.6522C539.668 69.5217 542.296 68.4565 545.711 68.4565ZM548.996 93.0435C549.478 93.5652 550.332 93.8261 551.558 93.8261C552.797 93.8261 553.886 93.6774 554.825 93.3801C555.457 93.18 555.828 92.5622 555.828 91.9034V81.5829C555.828 81.0014 555.542 80.4427 555.014 80.1911C554.6 79.9938 554.171 79.8431 553.726 79.7391C552.981 79.5217 552.259 79.413 551.558 79.413C549.324 79.413 548.208 80.5217 548.208 82.7391V90.5652C548.208 91.7391 548.47 92.5652 548.996 93.0435Z" fill="black"/>
|
||||
<path d="M588.228 104.783C589.195 104.783 589.98 104.004 589.98 103.043V84.6928C589.98 84.0869 590.292 83.5143 590.842 83.2503C591.381 82.9911 591.947 82.7772 592.542 82.6087C593.461 82.3044 594.49 82.1522 595.629 82.1522C596.461 82.1522 597.249 82.2174 597.994 82.3478C598.726 82.469 599.44 82.6277 600.134 82.8239C600.24 82.8537 600.349 82.8696 600.458 82.8696C601.093 82.8696 601.607 82.3591 601.607 81.7294V69.8261C601.607 69.5217 601.497 69.2609 601.278 69.0435C601.147 68.913 600.906 68.7826 600.556 68.6522C600.205 68.5217 599.68 68.4565 598.979 68.4565C596.921 68.4565 595.279 69.087 594.052 70.3478C592.966 71.4664 592.12 73.0989 591.514 75.2453C591.418 75.5851 591.11 75.8261 590.754 75.8261C590.326 75.8261 589.98 75.4818 589.98 75.057V69.8261C589.98 69.3478 589.739 69.1087 589.257 69.1087H578.396C577.429 69.1087 576.644 69.8873 576.644 70.8478V104.065C576.644 104.543 576.885 104.783 577.367 104.783H588.228Z" fill="black"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M638.295 81.8261V92.3913C638.295 92.9268 638.482 93.2772 638.855 93.4425C638.96 93.4893 639.069 93.5295 639.178 93.5672C639.3 93.6094 639.422 93.6304 639.544 93.6304H639.631C640.599 93.6304 641.383 94.4091 641.383 95.3696V104.065C641.383 104.543 641.142 104.783 640.66 104.783H636.259C634.113 104.783 632.142 104.348 630.347 103.478C628.788 102.705 627.594 101.587 626.763 100.124C626.573 99.7893 626.224 99.5652 625.837 99.5652C625.46 99.5652 625.118 99.7765 624.931 100.101C624 101.715 622.783 102.993 621.282 103.935C619.661 104.935 617.581 105.435 615.041 105.435C611.975 105.435 609.545 104.609 607.749 102.957C605.954 101.304 605.056 99.0652 605.056 96.2391V93.6957C605.056 90.6522 605.954 88.2609 607.749 86.5217C609.589 84.7826 612.172 83.913 615.501 83.913H624.697C625.205 83.913 625.617 83.5043 625.617 83C625.617 81.4783 625.201 80.4565 624.369 79.9348C623.581 79.3696 622.048 79.087 619.771 79.087C615.972 79.087 612.216 79.6361 608.503 80.7343C608.395 80.7661 608.284 80.7826 608.171 80.7826C607.539 80.7826 607.027 80.2739 607.027 79.6463V71.2609C607.027 70.9565 607.092 70.7391 607.224 70.6087C607.53 70.3043 608.362 69.9783 609.72 69.6304C611.121 69.2826 612.808 68.9783 614.778 68.7174C616.793 68.413 618.851 68.2609 620.953 68.2609C626.953 68.2609 631.332 69.3478 634.091 71.5217C636.894 73.6522 638.295 77.087 638.295 81.8261ZM619.442 96.0435C621.348 96.0435 623.127 95.6161 624.777 94.7612C625.312 94.4845 625.617 93.9194 625.617 93.3211V91.9783C625.617 91.0178 624.833 90.2391 623.865 90.2391H619.574C618.829 90.2391 618.26 90.4348 617.866 90.8261C617.515 91.2609 617.34 91.7826 617.34 92.3913V93.9565C617.34 95.3478 618.041 96.0435 619.442 96.0435Z" fill="black"/>
|
||||
<path d="M664.776 69.1087C663.958 69.1087 663.25 69.6696 663.068 70.4605C662.137 74.5177 661.277 78.3279 660.489 81.8913C659.711 85.5887 659.125 89.0962 658.73 92.4139C658.682 92.8093 658.346 93.1087 657.945 93.1087C657.503 93.1087 657.147 92.7472 657.154 92.3083C657.205 88.9664 657.069 85.6245 656.744 82.2826C656.438 78.6739 656.044 74.6522 655.562 70.2174C655.518 69.7391 655.43 69.4348 655.299 69.3043C655.168 69.1739 654.971 69.1087 654.708 69.1087H645.295C644.208 69.1087 643.383 70.0825 643.568 71.1467C644.447 76.2065 645.292 81.2663 646.102 86.3261C647.066 92.0652 648.029 97.587 648.993 102.891C649.143 103.562 649.309 104.041 649.491 104.328C649.548 104.417 649.623 104.493 649.711 104.552C649.938 104.706 650.18 104.783 650.438 104.783H662.158C662.955 104.783 663.651 104.249 663.852 103.484C664.192 102.194 664.494 101.039 664.758 100.022C665.109 98.6739 665.415 97.3478 665.678 96.0435C665.941 94.7391 666.204 93.3043 666.466 91.7391C666.743 90.2865 667.038 88.5325 667.35 86.4772C667.409 86.0907 667.743 85.8043 668.137 85.8043C668.535 85.8043 668.871 86.0965 668.924 86.4877C669.191 88.4532 669.423 90.1385 669.62 91.5435C669.882 93.0652 670.123 94.413 670.342 95.587C670.605 96.7174 670.868 97.8696 671.13 99.0435C671.393 100.174 671.7 101.478 672.05 102.957C672.238 103.59 672.425 104.047 672.613 104.329C672.671 104.417 672.746 104.493 672.834 104.552C673.061 104.706 673.303 104.783 673.561 104.783H685.485C686.338 104.783 687.067 104.172 687.212 103.338L689.984 87.3043C690.991 81.4783 691.976 75.6957 692.94 69.9565C692.983 69.3913 692.786 69.1087 692.349 69.1087H682.245C681.344 69.1087 680.589 69.7887 680.503 70.68C680.125 74.5767 679.782 78.2703 679.473 81.7609C679.189 85.3908 679.055 88.9084 679.072 92.3138C679.074 92.7513 678.719 93.1087 678.278 93.1087C677.874 93.1087 677.535 92.8065 677.489 92.4081C677.091 89.0194 676.482 85.5355 675.663 81.9565C674.831 78.1304 673.911 74.087 672.904 69.8261C672.773 69.3478 672.51 69.1087 672.116 69.1087H664.776Z" fill="black"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M377 48.7912C377 43.936 380.798 40 385.482 40H449.098C453.783 40 457.58 43.936 457.58 48.7912V111.209C457.58 116.064 453.783 120 449.098 120H385.482C380.798 120 377 116.064 377 111.209V48.7912ZM424.571 62.8801C424.571 64.8134 423.905 66.4539 422.574 67.8014C421.243 69.1489 419.622 69.8226 417.712 69.8226C415.744 69.8226 414.095 69.1489 412.764 67.8014C411.433 66.4539 410.767 64.8134 410.767 62.8801C410.767 60.9467 411.433 59.3063 412.764 57.9588C414.095 56.6113 415.744 55.9375 417.712 55.9375C419.622 55.9375 421.243 56.6113 422.574 57.9588C423.905 59.3063 424.571 60.9467 424.571 62.8801ZM410.68 87.2107C410.68 85.2774 411.346 83.6369 412.677 82.2894C414.066 80.8833 415.744 80.1803 417.712 80.1803C419.564 80.1803 421.185 80.8833 422.574 82.2894C423.963 83.6369 424.774 85.1602 425.005 86.8592C425.468 90.0229 424.889 93.1573 423.269 96.2624C421.706 99.3675 419.449 101.74 416.497 103.381C414.876 104.318 413.545 104.289 412.503 103.293C411.519 102.355 411.809 101.242 413.371 99.9534C414.24 99.309 414.963 98.4887 415.542 97.4928C416.121 96.4968 416.497 95.4715 416.671 94.4169C416.728 93.9482 416.526 93.7139 416.063 93.7139C414.905 93.6553 413.719 93.0108 412.503 91.7805C411.288 90.5502 410.68 89.0269 410.68 87.2107Z" stroke="white" stroke-width="26" mask="url(#path-1-outside-1_3296_32770)"/>
|
||||
<path d="M529.906 104.783C530.387 104.783 530.628 104.543 530.628 104.065V94.3261C530.628 93.3656 529.844 92.587 528.877 92.587H527.607C527.212 92.587 526.906 92.4783 526.687 92.2609C526.512 92.087 526.424 91.8261 526.424 91.4783V56.587C526.424 56.1087 526.183 55.8696 525.701 55.8696H514.644C513.676 55.8696 512.892 56.6482 512.892 57.6087V95.3913C512.892 98.5217 513.79 100.87 515.585 102.435C517.381 104 519.68 104.783 522.483 104.783H529.906Z" stroke="white" stroke-width="26" mask="url(#path-1-outside-1_3296_32770)"/>
|
||||
<path d="M507.242 94.2609C507.242 93.3004 506.458 92.5217 505.491 92.5217H500.87C499.381 92.5217 498.374 92.2609 497.849 91.7391C497.192 91.1304 496.863 90.1522 496.863 88.8043V83.0435C496.863 82.083 497.648 81.3043 498.615 81.3043H505.491C506.458 81.3043 507.242 80.5257 507.242 79.5652V69.8261C507.242 69.3478 507.002 69.1087 506.52 69.1087H498.615C497.648 69.1087 496.863 68.3301 496.863 67.3696V59.8478C496.863 59.3696 496.622 59.1304 496.141 59.1304H485.477C484.51 59.1304 483.725 59.9091 483.725 60.8696V67.3696C483.725 68.3301 482.941 69.1087 481.973 69.1087H480.353C479.386 69.1087 478.601 69.8873 478.601 70.8478V80.587C478.601 81.0652 478.842 81.3043 479.324 81.3043H481.973C482.941 81.3043 483.725 82.083 483.725 83.0435V89.7826C483.725 94.8261 485.061 98.587 487.732 101.065C490.404 103.543 494.28 104.783 499.36 104.783H506.52C507.002 104.783 507.242 104.543 507.242 104.065V94.2609Z" stroke="white" stroke-width="26" mask="url(#path-1-outside-1_3296_32770)"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M545.711 68.4565C547.726 68.4565 549.456 68.9565 550.901 69.9565C552.262 70.8705 553.385 72.0568 554.27 73.5156C554.426 73.7713 554.701 73.9348 555.001 73.9348C555.458 73.9348 555.828 73.5675 555.828 73.1144V57.6087C555.828 56.6482 556.612 55.8696 557.58 55.8696H568.243C568.725 55.8696 568.966 56.1087 568.966 56.587V103.043C568.966 104.004 568.182 104.783 567.214 104.783H556.55C556.069 104.783 555.828 104.543 555.828 104.065V100.148C555.828 99.6821 555.447 99.3043 554.978 99.3043C554.689 99.3043 554.42 99.4511 554.259 99.6893C553.14 101.339 551.89 102.689 550.507 103.739C549.018 104.87 547.157 105.435 544.923 105.435C541.901 105.435 539.515 104.413 537.763 102.37C536.011 100.326 535.135 97.587 535.135 94.1522V80.4565C535.135 76.7174 536.033 73.7826 537.829 71.6522C539.668 69.5217 542.296 68.4565 545.711 68.4565ZM548.996 93.0435C549.478 93.5652 550.332 93.8261 551.558 93.8261C552.797 93.8261 553.886 93.6774 554.825 93.3801C555.457 93.18 555.828 92.5622 555.828 91.9034V81.5829C555.828 81.0014 555.542 80.4427 555.014 80.1911C554.6 79.9938 554.171 79.8431 553.726 79.7391C552.981 79.5217 552.259 79.413 551.558 79.413C549.324 79.413 548.208 80.5217 548.208 82.7391V90.5652C548.208 91.7391 548.47 92.5652 548.996 93.0435Z" stroke="white" stroke-width="26" mask="url(#path-1-outside-1_3296_32770)"/>
|
||||
<path d="M588.228 104.783C589.195 104.783 589.98 104.004 589.98 103.043V84.6928C589.98 84.0869 590.292 83.5143 590.842 83.2503C591.381 82.9911 591.947 82.7772 592.542 82.6087C593.461 82.3044 594.49 82.1522 595.629 82.1522C596.461 82.1522 597.249 82.2174 597.994 82.3478C598.726 82.469 599.44 82.6277 600.134 82.8239C600.24 82.8537 600.349 82.8696 600.458 82.8696C601.093 82.8696 601.607 82.3591 601.607 81.7294V69.8261C601.607 69.5217 601.497 69.2609 601.278 69.0435C601.147 68.913 600.906 68.7826 600.556 68.6522C600.205 68.5217 599.68 68.4565 598.979 68.4565C596.921 68.4565 595.279 69.087 594.052 70.3478C592.966 71.4664 592.12 73.0989 591.514 75.2453C591.418 75.5851 591.11 75.8261 590.754 75.8261C590.326 75.8261 589.98 75.4818 589.98 75.057V69.8261C589.98 69.3478 589.739 69.1087 589.257 69.1087H578.396C577.429 69.1087 576.644 69.8873 576.644 70.8478V104.065C576.644 104.543 576.885 104.783 577.367 104.783H588.228Z" stroke="white" stroke-width="26" mask="url(#path-1-outside-1_3296_32770)"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M638.295 81.8261V92.3913C638.295 92.9268 638.482 93.2772 638.855 93.4425C638.96 93.4893 639.069 93.5295 639.178 93.5672C639.3 93.6094 639.422 93.6304 639.544 93.6304H639.631C640.599 93.6304 641.383 94.4091 641.383 95.3696V104.065C641.383 104.543 641.142 104.783 640.66 104.783H636.259C634.113 104.783 632.142 104.348 630.347 103.478C628.788 102.705 627.594 101.587 626.763 100.124C626.573 99.7893 626.224 99.5652 625.837 99.5652C625.46 99.5652 625.118 99.7765 624.931 100.101C624 101.715 622.783 102.993 621.282 103.935C619.661 104.935 617.581 105.435 615.041 105.435C611.975 105.435 609.545 104.609 607.749 102.957C605.954 101.304 605.056 99.0652 605.056 96.2391V93.6957C605.056 90.6522 605.954 88.2609 607.749 86.5217C609.589 84.7826 612.172 83.913 615.501 83.913H624.697C625.205 83.913 625.617 83.5043 625.617 83C625.617 81.4783 625.201 80.4565 624.369 79.9348C623.581 79.3696 622.048 79.087 619.771 79.087C615.972 79.087 612.216 79.6361 608.503 80.7343C608.395 80.7661 608.284 80.7826 608.171 80.7826C607.539 80.7826 607.027 80.2739 607.027 79.6463V71.2609C607.027 70.9565 607.092 70.7391 607.224 70.6087C607.53 70.3043 608.362 69.9783 609.72 69.6304C611.121 69.2826 612.808 68.9783 614.778 68.7174C616.793 68.413 618.851 68.2609 620.953 68.2609C626.953 68.2609 631.332 69.3478 634.091 71.5217C636.894 73.6522 638.295 77.087 638.295 81.8261ZM619.442 96.0435C621.348 96.0435 623.127 95.6161 624.777 94.7612C625.312 94.4845 625.617 93.9194 625.617 93.3211V91.9783C625.617 91.0178 624.833 90.2391 623.865 90.2391H619.574C618.829 90.2391 618.26 90.4348 617.866 90.8261C617.515 91.2609 617.34 91.7826 617.34 92.3913V93.9565C617.34 95.3478 618.041 96.0435 619.442 96.0435Z" stroke="white" stroke-width="26" mask="url(#path-1-outside-1_3296_32770)"/>
|
||||
<path d="M664.776 69.1087C663.958 69.1087 663.25 69.6696 663.068 70.4605C662.137 74.5177 661.277 78.3279 660.489 81.8913C659.711 85.5887 659.125 89.0962 658.73 92.4139C658.682 92.8093 658.346 93.1087 657.945 93.1087C657.503 93.1087 657.147 92.7472 657.154 92.3083C657.205 88.9664 657.069 85.6245 656.744 82.2826C656.438 78.6739 656.044 74.6522 655.562 70.2174C655.518 69.7391 655.43 69.4348 655.299 69.3043C655.168 69.1739 654.971 69.1087 654.708 69.1087H645.295C644.208 69.1087 643.383 70.0825 643.568 71.1467C644.447 76.2065 645.292 81.2663 646.102 86.3261C647.066 92.0652 648.029 97.587 648.993 102.891C649.143 103.562 649.309 104.041 649.491 104.328C649.548 104.417 649.623 104.493 649.711 104.552C649.938 104.706 650.18 104.783 650.438 104.783H662.158C662.955 104.783 663.651 104.249 663.852 103.484C664.192 102.194 664.494 101.039 664.758 100.022C665.109 98.6739 665.415 97.3478 665.678 96.0435C665.941 94.7391 666.204 93.3043 666.466 91.7391C666.743 90.2865 667.038 88.5325 667.35 86.4772C667.409 86.0907 667.743 85.8043 668.137 85.8043C668.535 85.8043 668.871 86.0965 668.924 86.4877C669.191 88.4532 669.423 90.1385 669.62 91.5435C669.882 93.0652 670.123 94.413 670.342 95.587C670.605 96.7174 670.868 97.8696 671.13 99.0435C671.393 100.174 671.7 101.478 672.05 102.957C672.238 103.59 672.425 104.047 672.613 104.329C672.671 104.417 672.746 104.493 672.834 104.552C673.061 104.706 673.303 104.783 673.561 104.783H685.485C686.338 104.783 687.067 104.172 687.212 103.338L689.984 87.3043C690.991 81.4783 691.976 75.6957 692.94 69.9565C692.983 69.3913 692.786 69.1087 692.349 69.1087H682.245C681.344 69.1087 680.589 69.7887 680.503 70.68C680.125 74.5767 679.782 78.2703 679.473 81.7609C679.189 85.3908 679.055 88.9084 679.072 92.3138C679.074 92.7513 678.719 93.1087 678.278 93.1087C677.874 93.1087 677.535 92.8065 677.489 92.4081C677.091 89.0194 676.482 85.5355 675.663 81.9565C674.831 78.1304 673.911 74.087 672.904 69.8261C672.773 69.3478 672.51 69.1087 672.116 69.1087H664.776Z" stroke="white" stroke-width="26" mask="url(#path-1-outside-1_3296_32770)"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 26 KiB |
BIN
frontend/public/baiban/static/embed-icons/codepen.png
Executable file
|
After Width: | Height: | Size: 2.1 KiB |
BIN
frontend/public/baiban/static/embed-icons/codesandbox.png
Executable file
|
After Width: | Height: | Size: 237 B |
BIN
frontend/public/baiban/static/embed-icons/desmos.png
Executable file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
frontend/public/baiban/static/embed-icons/excalidraw.png
Executable file
|
After Width: | Height: | Size: 846 B |
BIN
frontend/public/baiban/static/embed-icons/felt.png
Executable file
|
After Width: | Height: | Size: 977 B |
BIN
frontend/public/baiban/static/embed-icons/figma.png
Executable file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
frontend/public/baiban/static/embed-icons/github_gist.png
Executable file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
frontend/public/baiban/static/embed-icons/google_calendar.png
Executable file
|
After Width: | Height: | Size: 962 B |
BIN
frontend/public/baiban/static/embed-icons/google_maps.png
Executable file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
frontend/public/baiban/static/embed-icons/google_slides.png
Executable file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
frontend/public/baiban/static/embed-icons/observable.png
Executable file
|
After Width: | Height: | Size: 769 B |
BIN
frontend/public/baiban/static/embed-icons/replit.png
Executable file
|
After Width: | Height: | Size: 526 B |
BIN
frontend/public/baiban/static/embed-icons/scratch.png
Executable file
|
After Width: | Height: | Size: 3.6 KiB |
BIN
frontend/public/baiban/static/embed-icons/spotify.png
Executable file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
frontend/public/baiban/static/embed-icons/tldraw.png
Executable file
|
After Width: | Height: | Size: 625 B |
BIN
frontend/public/baiban/static/embed-icons/val_town.png
Executable file
|
After Width: | Height: | Size: 540 B |
BIN
frontend/public/baiban/static/embed-icons/vimeo.png
Executable file
|
After Width: | Height: | Size: 864 B |
BIN
frontend/public/baiban/static/embed-icons/youtube.png
Executable file
|
After Width: | Height: | Size: 846 B |
BIN
frontend/public/baiban/static/fonts/IBMPlexMono-Medium.woff2
Executable file
BIN
frontend/public/baiban/static/fonts/IBMPlexSans-Medium.woff2
Executable file
BIN
frontend/public/baiban/static/fonts/IBMPlexSerif-Medium.woff2
Executable file
BIN
frontend/public/baiban/static/fonts/Shantell_Sans-Tldrawish.woff2
Executable file
BIN
frontend/public/baiban/static/github-hero-dark-draw.png
Executable file
|
After Width: | Height: | Size: 395 KiB |
BIN
frontend/public/baiban/static/github-hero-dark.png
Executable file
|
After Width: | Height: | Size: 387 KiB |
BIN
frontend/public/baiban/static/github-hero-light-2.png
Executable file
|
After Width: | Height: | Size: 63 KiB |
BIN
frontend/public/baiban/static/github-hero-light-draw.png
Executable file
|
After Width: | Height: | Size: 396 KiB |
BIN
frontend/public/baiban/static/github-hero-light.png
Executable file
|
After Width: | Height: | Size: 388 KiB |
BIN
frontend/public/baiban/static/github-hero_dark-2.png
Executable file
|
After Width: | Height: | Size: 63 KiB |
3
frontend/public/baiban/static/icons/icon/align-bottom.svg
Executable file
|
|
@ -0,0 +1,3 @@
|
|||
<svg width="30" height="30" viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M18 5C18 4.44772 17.5523 4 17 4H13C12.4477 4 12 4.44772 12 5L12 28H3C2.44772 28 2 28.4477 2 29C2 29.5523 2.44772 30 3 30L27 30C27.5523 30 28 29.5523 28 29C28 28.4477 27.5523 28 27 28H18L18 5Z" fill="black"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 320 B |
4
frontend/public/baiban/static/icons/icon/align-center-horizontal.svg
Executable file
|
|
@ -0,0 +1,4 @@
|
|||
<svg width="30" height="30" viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M1.99976 13C1.99976 12.4477 2.44747 12 2.99976 12H26.9998C27.552 12 27.9998 12.4477 27.9998 13V17C27.9998 17.5523 27.552 18 26.9998 18H2.99976C2.44747 18 1.99976 17.5523 1.99976 17V13Z" fill="black"/>
|
||||
<path d="M13.9998 3C13.9998 2.44772 14.4475 2 14.9998 2C15.552 2 15.9998 2.44772 15.9998 3V27C15.9998 27.5523 15.552 28 14.9998 28C14.4475 28 13.9998 27.5523 13.9998 27V3Z" fill="black"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 501 B |
3
frontend/public/baiban/static/icons/icon/align-center-vertical.svg
Executable file
|
|
@ -0,0 +1,3 @@
|
|||
<svg width="30" height="30" viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M12.9998 2C12.4475 2 11.9998 2.44772 11.9998 3V14H2.99976C2.44747 14 1.99976 14.4477 1.99976 15C1.99976 15.5523 2.44747 16 2.99976 16H11.9998V27C11.9998 27.5523 12.4475 28 12.9998 28H16.9998C17.552 28 17.9998 27.5523 17.9998 27V16H26.9998C27.552 16 27.9998 15.5523 27.9998 15C27.9998 14.4477 27.552 14 26.9998 14H17.9998V3C17.9998 2.44772 17.552 2 16.9998 2H12.9998Z" fill="black"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 495 B |
4
frontend/public/baiban/static/icons/icon/align-left.svg
Executable file
|
|
@ -0,0 +1,4 @@
|
|||
<svg width="30" height="30" viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M0 3C0 2.44772 0.447715 2 1 2C1.55228 2 2 2.44772 2 3V27C2 27.5523 1.55228 28 1 28C0.447715 28 0 27.5523 0 27V3Z" fill="black"/>
|
||||
<path d="M0 12H25C25.5523 12 26 12.4477 26 13V17C26 17.5523 25.5523 18 25 18H0V12Z" fill="black"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 340 B |
4
frontend/public/baiban/static/icons/icon/align-right.svg
Executable file
|
|
@ -0,0 +1,4 @@
|
|||
<svg width="30" height="30" viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M3.99976 13C3.99976 12.4477 4.44747 12 4.99976 12H29.9998V18H4.99976C4.44747 18 3.99976 17.5523 3.99976 17V13Z" fill="black"/>
|
||||
<path d="M27.9998 3C27.9998 2.44772 28.4475 2 28.9998 2C29.552 2 29.9998 2.44772 29.9998 3V27C29.9998 27.5523 29.552 28 28.9998 28C28.4475 28 27.9998 27.5523 27.9998 27V3Z" fill="black"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 427 B |
3
frontend/public/baiban/static/icons/icon/align-top.svg
Executable file
|
|
@ -0,0 +1,3 @@
|
|||
<svg width="30" height="30" viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M2.99988 1.52588e-05C2.44759 1.52588e-05 1.99988 0.447731 1.99988 1.00002C1.99988 1.5523 2.44759 2.00002 2.99988 2.00002H11.9999V25C11.9999 25.5523 12.4476 26 12.9999 26H16.9999C17.5522 26 17.9999 25.5523 17.9999 25V2.00002H26.9999C27.5522 2.00002 27.9999 1.5523 27.9999 1.00002C27.9999 0.447731 27.5522 1.52588e-05 26.9999 1.52588e-05H2.99988Z" fill="black"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 473 B |
3
frontend/public/baiban/static/icons/icon/arrow-left.svg
Executable file
|
|
@ -0,0 +1,3 @@
|
|||
<svg width="30" height="30" viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M12.4996 21.5001L5.99963 15.0001M5.99963 15.0001L12.4996 8.50012M5.99963 15.0001L23.9999 15.0001" stroke="black" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 291 B |
3
frontend/public/baiban/static/icons/icon/arrowhead-arrow.svg
Executable file
|
|
@ -0,0 +1,3 @@
|
|||
<svg width="30" height="30" viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M1 15L27 15M13 26L29 15L13 4" stroke="black" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 223 B |
3
frontend/public/baiban/static/icons/icon/arrowhead-bar.svg
Executable file
|
|
@ -0,0 +1,3 @@
|
|||
<svg width="30" height="30" viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M1 15L29 15M29 15V2M29 15V28" stroke="black" stroke-width="2" stroke-linecap="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 199 B |
4
frontend/public/baiban/static/icons/icon/arrowhead-diamond.svg
Executable file
|
|
@ -0,0 +1,4 @@
|
|||
<svg width="30" height="30" viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M18.4142 3.82822L28.3137 13.7277C29.0948 14.5088 29.0948 15.7751 28.3137 16.5561L18.4142 26.4556C17.6332 27.2367 16.3669 27.2367 15.5858 26.4556L5.68631 16.5561C4.90526 15.7751 4.90526 14.5088 5.68631 13.7277L15.5858 3.82822C16.3669 3.04717 17.6332 3.04717 18.4142 3.82822Z" stroke="black" stroke-width="2"/>
|
||||
<path d="M1 15H5" stroke="black" stroke-width="2" stroke-linecap="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 496 B |
4
frontend/public/baiban/static/icons/icon/arrowhead-dot.svg
Executable file
|
|
@ -0,0 +1,4 @@
|
|||
<svg width="30" height="30" viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M29 15C29 21.0751 24.0751 26 18 26C11.9249 26 7 21.0751 7 15C7 8.92487 11.9249 4 18 4C24.0751 4 29 8.92487 29 15Z" stroke="black" stroke-width="2"/>
|
||||
<path d="M1 15H6" stroke="black" stroke-width="2" stroke-linecap="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 336 B |
3
frontend/public/baiban/static/icons/icon/arrowhead-none.svg
Executable file
|
|
@ -0,0 +1,3 @@
|
|||
<svg width="30" height="30" viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M1 15L29 15" stroke="black" stroke-width="2" stroke-linecap="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 182 B |
3
frontend/public/baiban/static/icons/icon/arrowhead-square.svg
Executable file
|
|
@ -0,0 +1,3 @@
|
|||
<svg width="30" height="30" viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M1 15L5 15M8 27H26C27.6569 27 29 25.6569 29 24V6C29 4.34315 27.6569 3 26 3H8C6.34315 3 5 4.34315 5 6V24C5 25.6569 6.34315 27 8 27Z" stroke="black" stroke-width="2" stroke-linecap="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 301 B |
3
frontend/public/baiban/static/icons/icon/arrowhead-triangle-inverted.svg
Executable file
|
|
@ -0,0 +1,3 @@
|
|||
<svg width="30" height="30" viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M1 14C0.447715 14 0 14.4477 0 15C5.96046e-08 15.5523 0.447715 16 1 16L1 14ZM29 2H30C30 1.62447 29.7896 1.2806 29.4553 1.10964C29.1209 0.938677 28.7189 0.969452 28.4145 1.18932L29 2ZM29 28L28.4145 28.8107C28.7189 29.0305 29.1209 29.0613 29.4553 28.8904C29.7896 28.7194 30 28.3755 30 28H29ZM1 16L11 16V14L1 14L1 16ZM28 2V28H30V2H28ZM29.5855 27.1893L11.5855 14.1893L10.4145 15.8107L28.4145 28.8107L29.5855 27.1893ZM11.5855 15.8107L29.5855 2.81068L28.4145 1.18932L10.4145 14.1893L11.5855 15.8107Z" fill="black"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 621 B |
3
frontend/public/baiban/static/icons/icon/arrowhead-triangle.svg
Executable file
|
|
@ -0,0 +1,3 @@
|
|||
<svg width="30" height="30" viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M1 15.1539L11.6923 15.1539M12.6923 3.46155V26.5385L28.8462 15L12.6923 3.46155Z" stroke="black" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 273 B |
3
frontend/public/baiban/static/icons/icon/blob.svg
Executable file
|
|
@ -0,0 +1,3 @@
|
|||
<svg width="30" height="30" viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M1.98125 12.4723C1.83836 12.6938 2.09551 13.0008 2.33213 12.8846C3.14685 12.4842 3.93568 12.0619 4.70733 11.5967C4.93448 11.4598 5.18303 11.7046 5.0359 11.9253C3.13151 14.7818 -1.59634 21.7981 3.60918 22.2578C6.76899 22.5368 9.93894 19.9616 12.9133 17.2735C13.1318 17.0759 13.4376 17.335 13.2743 17.5802C10.8537 21.2143 6.41515 28.636 12.2493 28.99C17.3234 29.298 16.1533 24.5977 27.679 18.2524C28.5169 17.7911 28.7805 16.8396 28.5707 15.9125C28.1988 13.9184 24.4364 13.9496 22.3466 14.4984C22.0925 14.5651 21.8477 14.245 22.0182 14.045C24.5643 11.0592 31.8711 3.60414 27.2697 1.27741C23.219 -0.770836 13.918 8.89819 9.96535 12.5406C9.75706 12.7325 9.52989 12.5192 9.69793 12.2912C11.6423 9.65308 14.1864 6.73192 14.6429 3.69364C14.7073 3.26555 14.628 2.86103 14.4053 2.48008C14.1825 2.09913 13.8587 1.8145 13.4339 1.6262C9.1247 -0.284007 4.20268 9.02761 1.98125 12.4723Z" fill="black"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1,000 B |
3
frontend/public/baiban/static/icons/icon/bring-forward.svg
Executable file
|
|
@ -0,0 +1,3 @@
|
|||
<svg width="30" height="30" viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M8.50024 12.6388L15.0002 6.5M15.0002 6.5L21.5002 12.6388M15.0002 6.5L15.0002 23.5" stroke="black" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 276 B |
3
frontend/public/baiban/static/icons/icon/bring-to-front.svg
Executable file
|
|
@ -0,0 +1,3 @@
|
|||
<svg width="30" height="30" viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M8.50024 15.4998L15.0002 8.99976M15.0002 8.99976L21.5002 15.4998M15.0002 8.99976L15.0002 27M3 3L27 3" stroke="black" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 295 B |
5
frontend/public/baiban/static/icons/icon/broken.svg
Executable file
|
|
@ -0,0 +1,5 @@
|
|||
<svg width="30" height="30" viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M28.0001 12C28.0001 11.4477 27.5524 11 27.0001 11C26.4478 11 26.0001 11.4477 26.0001 12V26H12C11.4477 26 11 26.4477 11 27C11 27.5523 11.4477 28 12 28H26.9C27.4523 28 28.0001 27.4522 28.0001 26.8999V12Z" fill="black"/>
|
||||
<path d="M2 18C2 18.5523 2.44769 19 2.99997 19C3.55225 19 4 18.5523 4 18L4 4L18 4C18.5523 4 19 3.55228 19 3C19 2.44772 18.5523 2 18 2L3.10007 2C2.54779 2 2 2.54781 2 3.10009L2 18Z" fill="black"/>
|
||||
<rect x="1.58411" y="27.0018" width="35.9461" height="2" rx="1" transform="rotate(-45 1.58411 27.0018)" fill="black"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 645 B |
4
frontend/public/baiban/static/icons/icon/check-circle.svg
Executable file
|
|
@ -0,0 +1,4 @@
|
|||
<svg width="30" height="30" viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M14.9998 27.2949C21.7904 27.2949 27.2954 21.7899 27.2954 14.9993C27.2954 8.20858 21.7904 2.70361 14.9998 2.70361C8.20907 2.70361 2.7041 8.20858 2.7041 14.9993C2.7041 21.7899 8.20907 27.2949 14.9998 27.2949Z" stroke="black" stroke-width="2"/>
|
||||
<path d="M20.7075 9.39489C21.1367 9.67551 21.2572 10.2509 20.9765 10.6801L14.6629 20.3363C14.5141 20.5639 14.273 20.7148 14.0033 20.7492C13.7336 20.7836 13.4624 20.6981 13.2612 20.5152L9.17587 16.8013C8.79644 16.4564 8.76848 15.8691 9.11342 15.4897C9.45835 15.1103 10.0456 15.0823 10.425 15.4273L13.7046 18.4087L19.4223 9.66389C19.7029 9.2347 20.2784 9.11426 20.7075 9.39489Z" fill="black"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 746 B |
3
frontend/public/baiban/static/icons/icon/check.svg
Executable file
|
|
@ -0,0 +1,3 @@
|
|||
<svg width="30" height="30" viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M22.9339 7.45369C23.5118 7.83148 23.6739 8.60615 23.2961 9.18396L14.7961 22.184C14.5958 22.4903 14.2712 22.6935 13.9082 22.7398C13.5451 22.7862 13.1799 22.6711 12.909 22.4248L7.40905 17.4248C6.89822 16.9604 6.86058 16.1699 7.32496 15.6591C7.78935 15.1482 8.57991 15.1106 9.09073 15.575L13.506 19.5888L21.2037 7.81584C21.5815 7.23803 22.3561 7.07589 22.9339 7.45369Z" fill="black"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 494 B |
3
frontend/public/baiban/static/icons/icon/chevron-down.svg
Executable file
|
|
@ -0,0 +1,3 @@
|
|||
<svg width="30" height="30" viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M6.27047 12.3161C6.6482 11.9131 7.28103 11.8927 7.68394 12.2705L15 19.1293L22.3161 12.2705C22.719 11.8927 23.3518 11.9131 23.7295 12.3161C24.1073 12.719 24.0869 13.3518 23.6839 13.7295L15.6839 21.2295C15.2993 21.5902 14.7007 21.5902 14.3161 21.2295L6.31606 13.7295C5.91315 13.3518 5.89274 12.719 6.27047 12.3161Z" fill="black"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 481 B |
3
frontend/public/baiban/static/icons/icon/chevron-left.svg
Executable file
|
|
@ -0,0 +1,3 @@
|
|||
<svg width="30" height="30" viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M17.6836 6.27028C18.0865 6.64801 18.1069 7.28085 17.7292 7.68376L10.8704 14.9998L17.7292 22.3159C18.1069 22.7188 18.0865 23.3516 17.6836 23.7294C17.2807 24.1071 16.6478 24.0867 16.2701 23.6838L8.7701 15.6838C8.40948 15.2991 8.40948 14.7005 8.7701 14.3159L16.2701 6.31588C16.6478 5.91297 17.2807 5.89255 17.6836 6.27028Z" fill="black"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 488 B |