Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9057290188 | ||
|
|
5cfd44da79 | ||
|
|
49ca0af746 | ||
|
|
f020c1162d | ||
|
|
37130966cf | ||
|
|
a6ceee7bc0 | ||
|
|
a5fee0ee97 | ||
|
|
cad7af13af |
2
UI
1
main.go
@@ -32,6 +32,7 @@ func init() {
|
|||||||
//gredis.GetRedisConn(config.RedisInfo),
|
//gredis.GetRedisConn(config.RedisInfo),
|
||||||
service.MyService = service.NewService(sqliteDB, loger2.NewOLoger())
|
service.MyService = service.NewService(sqliteDB, loger2.NewOLoger())
|
||||||
service.Cache = cache.Init()
|
service.Cache = cache.Init()
|
||||||
|
route.InitFunction()
|
||||||
}
|
}
|
||||||
|
|
||||||
// @title casaOS API
|
// @title casaOS API
|
||||||
|
|||||||
11
model/app.go
@@ -15,12 +15,14 @@ type ServerAppList struct {
|
|||||||
Icon string `json:"icon"`
|
Icon string `json:"icon"`
|
||||||
ScreenshotLink Strings `gorm:"type:json" json:"screenshot_link"`
|
ScreenshotLink Strings `gorm:"type:json" json:"screenshot_link"`
|
||||||
Category string `json:"category"`
|
Category string `json:"category"`
|
||||||
TcpPort uint `json:"tcp_port"`
|
PortMap string `json:"port_map"`
|
||||||
PortMap uint `json:"port_map"`
|
|
||||||
ImageVersion string `json:"image_version"`
|
ImageVersion string `json:"image_version"`
|
||||||
Tip string `json:"tip"`
|
Tip string `json:"tip"`
|
||||||
Configures configures `gorm:"type:json" json:"configures"`
|
Envs EnvArray `json:"envs"`
|
||||||
NetworkModel string `json:"network_mode"`
|
Ports PortArray `json:"ports"`
|
||||||
|
Volumes PathArray `json:"volumes"`
|
||||||
|
Devices PathArray `json:"devices"`
|
||||||
|
NetworkModel string `json:"network_model"`
|
||||||
Image string `json:"image"`
|
Image string `json:"image"`
|
||||||
Index string `json:"index"`
|
Index string `json:"index"`
|
||||||
CreatedAt time.Time `json:"created_at"`
|
CreatedAt time.Time `json:"created_at"`
|
||||||
@@ -33,6 +35,7 @@ type ServerAppList struct {
|
|||||||
Thumbnail string `json:"thumbnail"`
|
Thumbnail string `json:"thumbnail"`
|
||||||
Healthy string `json:"healthy"`
|
Healthy string `json:"healthy"`
|
||||||
Plugins Strings `json:"plugins"`
|
Plugins Strings `json:"plugins"`
|
||||||
|
Origin string `json:"origin"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Ports struct {
|
type Ports struct {
|
||||||
|
|||||||
@@ -17,20 +17,22 @@ type UdpPorts struct {
|
|||||||
/*******************使用gorm支持json************************************/
|
/*******************使用gorm支持json************************************/
|
||||||
|
|
||||||
type PortMap struct {
|
type PortMap struct {
|
||||||
ContainerPort string `json:"container,omitempty"`
|
ContainerPort string `json:"container"`
|
||||||
CommendPort string `json:"host,omitempty"`
|
CommendPort string `json:"host"`
|
||||||
Protocol string `json:"protocol"`
|
Protocol string `json:"protocol"`
|
||||||
|
Desc string `json:"desc"`
|
||||||
|
Type int `json:"type"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type PortArrey []PortMap
|
type PortArray []PortMap
|
||||||
|
|
||||||
// Value 实现方法
|
// Value 实现方法
|
||||||
func (p PortArrey) Value() (driver.Value, error) {
|
func (p PortArray) Value() (driver.Value, error) {
|
||||||
return json.Marshal(p)
|
return json.Marshal(p)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scan 实现方法
|
// Scan 实现方法
|
||||||
func (p *PortArrey) Scan(input interface{}) error {
|
func (p *PortArray) Scan(input interface{}) error {
|
||||||
return json.Unmarshal(input.([]byte), p)
|
return json.Unmarshal(input.([]byte), p)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,20 +43,22 @@ func (p *PortArrey) Scan(input interface{}) error {
|
|||||||
type Env struct {
|
type Env struct {
|
||||||
Name string `json:"container"`
|
Name string `json:"container"`
|
||||||
Value string `json:"host"`
|
Value string `json:"host"`
|
||||||
|
Desc string `json:"desc"`
|
||||||
|
Type int `json:"type"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type JSON json.RawMessage
|
type JSON json.RawMessage
|
||||||
|
|
||||||
type EnvArrey []Env
|
type EnvArray []Env
|
||||||
|
|
||||||
// Value 实现方法
|
// Value 实现方法
|
||||||
func (p EnvArrey) Value() (driver.Value, error) {
|
func (p EnvArray) Value() (driver.Value, error) {
|
||||||
return json.Marshal(p)
|
return json.Marshal(p)
|
||||||
//return .MarshalJSON()
|
//return .MarshalJSON()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scan 实现方法
|
// Scan 实现方法
|
||||||
func (p *EnvArrey) Scan(input interface{}) error {
|
func (p *EnvArray) Scan(input interface{}) error {
|
||||||
return json.Unmarshal(input.([]byte), p)
|
return json.Unmarshal(input.([]byte), p)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,17 +69,19 @@ func (p *EnvArrey) Scan(input interface{}) error {
|
|||||||
type PathMap struct {
|
type PathMap struct {
|
||||||
ContainerPath string `json:"container"`
|
ContainerPath string `json:"container"`
|
||||||
Path string `json:"host"`
|
Path string `json:"host"`
|
||||||
|
Type int `json:"type"`
|
||||||
|
Desc string `json:"desc"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type PathArrey []PathMap
|
type PathArray []PathMap
|
||||||
|
|
||||||
// Value 实现方法
|
// Value 实现方法
|
||||||
func (p PathArrey) Value() (driver.Value, error) {
|
func (p PathArray) Value() (driver.Value, error) {
|
||||||
return json.Marshal(p)
|
return json.Marshal(p)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scan 实现方法
|
// Scan 实现方法
|
||||||
func (p *PathArrey) Scan(input interface{}) error {
|
func (p *PathArray) Scan(input interface{}) error {
|
||||||
return json.Unmarshal(input.([]byte), p)
|
return json.Unmarshal(input.([]byte), p)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,10 +109,10 @@ type CustomizationPostData struct {
|
|||||||
Index string `json:"index"`
|
Index string `json:"index"`
|
||||||
Icon string `json:"icon"`
|
Icon string `json:"icon"`
|
||||||
Image string `json:"image"`
|
Image string `json:"image"`
|
||||||
Envs EnvArrey `json:"envs"`
|
Envs EnvArray `json:"envs"`
|
||||||
Ports PortArrey `json:"ports"`
|
Ports PortArray `json:"ports"`
|
||||||
Volumes PathArrey `json:"volumes"`
|
Volumes PathArray `json:"volumes"`
|
||||||
Devices PathArrey `json:"devices"`
|
Devices PathArray `json:"devices"`
|
||||||
//Port string `json:"port,omitempty"`
|
//Port string `json:"port,omitempty"`
|
||||||
PortMap string `json:"port_map"`
|
PortMap string `json:"port_map"`
|
||||||
CpuShares int64 `json:"cpu_shares"`
|
CpuShares int64 `json:"cpu_shares"`
|
||||||
|
|||||||
@@ -64,4 +64,6 @@ type SystemConfig struct {
|
|||||||
ConfigStr string `json:"config_str"`
|
ConfigStr string `json:"config_str"`
|
||||||
WidgetList string `json:"widget_list"`
|
WidgetList string `json:"widget_list"`
|
||||||
ConfigPath string `json:"config_path"`
|
ConfigPath string `json:"config_path"`
|
||||||
|
SyncPort string `json:"sync_port"`
|
||||||
|
SyncKey string `json:"sync_key"`
|
||||||
}
|
}
|
||||||
|
|||||||
8
model/system_app/sync.go
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
package system_app
|
||||||
|
|
||||||
|
import "encoding/xml"
|
||||||
|
|
||||||
|
type SyncConfig struct {
|
||||||
|
XMLName xml.Name `xml:"configuration"`
|
||||||
|
Key string `xml:"gui>apikey"`
|
||||||
|
}
|
||||||
@@ -1,10 +1,31 @@
|
|||||||
package docker
|
package docker
|
||||||
|
|
||||||
|
import "strings"
|
||||||
|
|
||||||
func GetDir(id, envName string) string {
|
func GetDir(id, envName string) string {
|
||||||
var path string
|
var path string
|
||||||
switch envName {
|
|
||||||
case "/config":
|
if len(id) == 0 {
|
||||||
path = "/oasis/app_data/" + id + "/"
|
id = "$AppID"
|
||||||
|
}
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case strings.Contains(strings.ToLower(envName), "config") || strings.Contains(strings.ToLower(envName), "photoprism/storage") || strings.Contains(strings.ToLower(envName), "config"):
|
||||||
|
path = "/DATA/AppData/" + id + "/"
|
||||||
|
case strings.Contains(strings.ToLower(envName), "media"):
|
||||||
|
path = "/DATA/Media/"
|
||||||
|
case strings.Contains(strings.ToLower(envName), "movie"):
|
||||||
|
path = "/DATA/Media/Movies/"
|
||||||
|
case strings.Contains(strings.ToLower(envName), "music"):
|
||||||
|
path = "/DATA/Media/Music/"
|
||||||
|
case strings.Contains(strings.ToLower(envName), "photoprism/originals"):
|
||||||
|
path = "/DATA/Gallery"
|
||||||
|
case strings.Contains(strings.ToLower(envName), "download"):
|
||||||
|
path = "/DATA/Downloads/"
|
||||||
|
case strings.Contains(strings.ToLower(envName), "photo") || strings.Contains(strings.ToLower(envName), "pictures"):
|
||||||
|
path = "/DATA/Downloads/"
|
||||||
|
case strings.ToLower(envName) == "/srv":
|
||||||
|
path = "/DATA/"
|
||||||
default:
|
default:
|
||||||
//path = "/media"
|
//path = "/media"
|
||||||
}
|
}
|
||||||
|
|||||||
10
pkg/docker/volumes_test.go
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
package docker
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGetDir(t *testing.T) {
|
||||||
|
fmt.Println(GetDir("", "config"))
|
||||||
|
}
|
||||||
19
pkg/utils/env_helper/env.go
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
package env_helper
|
||||||
|
|
||||||
|
import "strings"
|
||||||
|
|
||||||
|
func ReplaceDefaultENV(key string) string {
|
||||||
|
temp := ""
|
||||||
|
switch key {
|
||||||
|
case "$DefaultPassword":
|
||||||
|
temp = "casaos"
|
||||||
|
case "$DefaultUserName":
|
||||||
|
temp = "admin"
|
||||||
|
}
|
||||||
|
return temp
|
||||||
|
}
|
||||||
|
|
||||||
|
//replace env default setting
|
||||||
|
func ReplaceStringDefaultENV(str string) string {
|
||||||
|
return strings.ReplaceAll(strings.ReplaceAll(str, "$DefaultPassword", ReplaceDefaultENV("$DefaultPassword")), "$DefaultUserName", ReplaceDefaultENV("$DefaultUserName"))
|
||||||
|
}
|
||||||
@@ -146,3 +146,16 @@ func IsNotExistCreateFile(src string) error {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ReadFullFile(path string) []byte {
|
||||||
|
file, err := os.Open(path)
|
||||||
|
if err != nil {
|
||||||
|
return []byte("")
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
content, err := ioutil.ReadAll(file)
|
||||||
|
if err != nil {
|
||||||
|
return []byte("")
|
||||||
|
}
|
||||||
|
return content
|
||||||
|
}
|
||||||
|
|||||||
@@ -53,10 +53,13 @@ func Get(url string, head map[string]string) (response string) {
|
|||||||
//发送POST请求
|
//发送POST请求
|
||||||
//url:请求地址,data:POST请求提交的数据,contentType:请求体格式,如:application/json
|
//url:请求地址,data:POST请求提交的数据,contentType:请求体格式,如:application/json
|
||||||
//content:请求放回的内容
|
//content:请求放回的内容
|
||||||
func Post(url string, data interface{}, contentType string) (content string) {
|
func Post(url string, data []byte, contentType string, head map[string]string) (content string) {
|
||||||
jsonStr, _ := json.Marshal(data)
|
|
||||||
req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonStr))
|
req, err := http.NewRequest("POST", url, bytes.NewBuffer(data))
|
||||||
req.Header.Add("content-type", contentType)
|
req.Header.Add("content-type", contentType)
|
||||||
|
for k, v := range head {
|
||||||
|
req.Header.Add(k, v)
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ func IsPortAvailable(port int, t string) bool {
|
|||||||
uc, err := net.ListenUDP("udp", sadd)
|
uc, err := net.ListenUDP("udp", sadd)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
fmt.Println(err.Error())
|
||||||
return false
|
return false
|
||||||
} else {
|
} else {
|
||||||
defer uc.Close()
|
defer uc.Close()
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
package sort
|
package sort
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/IceWhaleTech/CasaOS/model"
|
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
|
"github.com/IceWhaleTech/CasaOS/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
// 数据集类型, 与上一篇排序文章(多字段单独排序)比较, less字段的数据类型不再是 func(p1, p2 *Change) bool
|
// 数据集类型, 与上一篇排序文章(多字段单独排序)比较, less字段的数据类型不再是 func(p1, p2 *Change) bool
|
||||||
|
|||||||
188
route/init.go
Normal file
@@ -0,0 +1,188 @@
|
|||||||
|
package route
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"encoding/xml"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/IceWhaleTech/CasaOS/model"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/model/system_app"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/pkg/docker"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/env_helper"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/port"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/service"
|
||||||
|
model2 "github.com/IceWhaleTech/CasaOS/service/model"
|
||||||
|
uuid "github.com/satori/go.uuid"
|
||||||
|
)
|
||||||
|
|
||||||
|
func InitFunction() {
|
||||||
|
go checkSystemApp()
|
||||||
|
}
|
||||||
|
|
||||||
|
var syncIsExistence = false
|
||||||
|
|
||||||
|
func installSyncthing(appId string) {
|
||||||
|
|
||||||
|
var appInfo model.ServerAppList
|
||||||
|
m := model.CustomizationPostData{}
|
||||||
|
var dockerImage string
|
||||||
|
var dockerImageVersion string
|
||||||
|
|
||||||
|
appInfo = service.MyService.OAPI().GetServerAppInfo(appId)
|
||||||
|
|
||||||
|
dockerImage = appInfo.Image
|
||||||
|
|
||||||
|
if len(appInfo.ImageVersion) == 0 {
|
||||||
|
dockerImageVersion = "latest"
|
||||||
|
}
|
||||||
|
|
||||||
|
if appInfo.NetworkModel != "host" {
|
||||||
|
for i := 0; i < len(appInfo.Ports); i++ {
|
||||||
|
if p, _ := strconv.Atoi(appInfo.Ports[i].ContainerPort); port.IsPortAvailable(p, appInfo.Ports[i].Protocol) {
|
||||||
|
appInfo.Ports[i].CommendPort = strconv.Itoa(p)
|
||||||
|
} else {
|
||||||
|
if appInfo.Ports[i].Protocol == "tcp" {
|
||||||
|
if p, err := port.GetAvailablePort("tcp"); err == nil {
|
||||||
|
appInfo.Ports[i].CommendPort = strconv.Itoa(p)
|
||||||
|
}
|
||||||
|
} else if appInfo.Ports[i].Protocol == "upd" {
|
||||||
|
if p, err := port.GetAvailablePort("udp"); err == nil {
|
||||||
|
appInfo.Ports[i].CommendPort = strconv.Itoa(p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if appInfo.Ports[i].Type == 0 {
|
||||||
|
appInfo.PortMap = appInfo.Ports[i].CommendPort
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < len(appInfo.Devices); i++ {
|
||||||
|
if !file.CheckNotExist(appInfo.Devices[i].ContainerPath) {
|
||||||
|
appInfo.Devices[i].Path = appInfo.Devices[i].ContainerPath
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(appInfo.Tip) > 0 {
|
||||||
|
appInfo.Tip = env_helper.ReplaceStringDefaultENV(appInfo.Tip)
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < len(appInfo.Volumes); i++ {
|
||||||
|
appInfo.Volumes[i].Path = docker.GetDir("", appInfo.Volumes[i].ContainerPath)
|
||||||
|
}
|
||||||
|
appInfo.MaxMemory = service.MyService.ZiMa().GetMemInfo().Total >> 20
|
||||||
|
|
||||||
|
id := uuid.NewV4().String()
|
||||||
|
|
||||||
|
installLog := model2.AppNotify{}
|
||||||
|
|
||||||
|
// step:下载镜像
|
||||||
|
err := service.MyService.Docker().DockerPullImage(dockerImage+":"+dockerImageVersion, installLog)
|
||||||
|
if err != nil {
|
||||||
|
//pull image error
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for !service.MyService.Docker().IsExistImage(dockerImage + ":" + dockerImageVersion) {
|
||||||
|
time.Sleep(time.Second)
|
||||||
|
}
|
||||||
|
|
||||||
|
m.CpuShares = 50
|
||||||
|
m.Envs = appInfo.Envs
|
||||||
|
m.Memory = int64(appInfo.MaxMemory)
|
||||||
|
m.Origin = "system"
|
||||||
|
m.PortMap = appInfo.PortMap
|
||||||
|
m.Ports = appInfo.Ports
|
||||||
|
m.Restart = ""
|
||||||
|
m.Volumes = appInfo.Volumes
|
||||||
|
|
||||||
|
containerId, err := service.MyService.Docker().DockerContainerCreate(dockerImage+":"+dockerImageVersion, id, m, appInfo.NetworkModel)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
// create container error
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//step:start container
|
||||||
|
err = service.MyService.Docker().DockerContainerStart(id)
|
||||||
|
if err != nil {
|
||||||
|
//start container error
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
portsStr, _ := json.Marshal(appInfo.Ports)
|
||||||
|
envsStr, _ := json.Marshal(appInfo.Envs)
|
||||||
|
volumesStr, _ := json.Marshal(appInfo.Volumes)
|
||||||
|
devicesStr, _ := json.Marshal(appInfo.Devices)
|
||||||
|
//step: 保存数据到数据库
|
||||||
|
md := model2.AppListDBModel{
|
||||||
|
CustomId: id,
|
||||||
|
Title: appInfo.Title,
|
||||||
|
//ScreenshotLink: appInfo.ScreenshotLink,
|
||||||
|
Slogan: appInfo.Tagline,
|
||||||
|
Description: appInfo.Description,
|
||||||
|
//Tags: appInfo.Tags,
|
||||||
|
Icon: appInfo.Icon,
|
||||||
|
Version: dockerImageVersion,
|
||||||
|
ContainerId: containerId,
|
||||||
|
Image: dockerImage,
|
||||||
|
Index: appInfo.Index,
|
||||||
|
PortMap: appInfo.PortMap,
|
||||||
|
Label: appInfo.Title,
|
||||||
|
EnableUPNP: false,
|
||||||
|
Ports: string(portsStr),
|
||||||
|
Envs: string(envsStr),
|
||||||
|
Volumes: string(volumesStr),
|
||||||
|
Position: true,
|
||||||
|
NetModel: appInfo.NetworkModel,
|
||||||
|
Restart: m.Restart,
|
||||||
|
CpuShares: 50,
|
||||||
|
Memory: int64(appInfo.MaxMemory),
|
||||||
|
Devices: string(devicesStr),
|
||||||
|
Origin: m.Origin,
|
||||||
|
CreatedAt: strconv.FormatInt(time.Now().Unix(), 10),
|
||||||
|
UpdatedAt: strconv.FormatInt(time.Now().Unix(), 10),
|
||||||
|
}
|
||||||
|
service.MyService.App().SaveContainer(md)
|
||||||
|
|
||||||
|
checkSystemApp()
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if the system application is installed
|
||||||
|
func checkSystemApp() {
|
||||||
|
list := service.MyService.App().GetSystemAppList()
|
||||||
|
for _, v := range *list {
|
||||||
|
if v.Image == "linuxserver/syncthing" {
|
||||||
|
syncIsExistence = true
|
||||||
|
if config.SystemConfigInfo.SyncPort != v.Port {
|
||||||
|
config.SystemConfigInfo.SyncPort = v.Port
|
||||||
|
}
|
||||||
|
var paths []model.PathMap
|
||||||
|
json.Unmarshal([]byte(v.Volumes), &paths)
|
||||||
|
path := ""
|
||||||
|
for _, i := range paths {
|
||||||
|
if i.ContainerPath == "/config" {
|
||||||
|
path = docker.GetDir(v.CustomId, i.ContainerPath) + "config.xml"
|
||||||
|
for i := 0; i < 10; i++ {
|
||||||
|
if file.CheckNotExist(path) {
|
||||||
|
time.Sleep(1 * time.Second)
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
content := file.ReadFullFile(path)
|
||||||
|
syncConfig := &system_app.SyncConfig{}
|
||||||
|
xml.Unmarshal(content, &syncConfig)
|
||||||
|
config.SystemConfigInfo.SyncKey = syncConfig.Key
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !syncIsExistence {
|
||||||
|
installSyncthing("44")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -37,6 +37,7 @@ func InitRouter() *gin.Engine {
|
|||||||
r.POST("/v1/user/setusernamepwd", v1.Set_Name_Pwd)
|
r.POST("/v1/user/setusernamepwd", v1.Set_Name_Pwd)
|
||||||
//get user info
|
//get user info
|
||||||
r.GET("/v1/user/info", v1.UserInfo)
|
r.GET("/v1/user/info", v1.UserInfo)
|
||||||
|
|
||||||
v1Group := r.Group("/v1")
|
v1Group := r.Group("/v1")
|
||||||
|
|
||||||
v1Group.Use(jwt2.JWT(swagHandler))
|
v1Group.Use(jwt2.JWT(swagHandler))
|
||||||
@@ -174,7 +175,7 @@ func InitRouter() *gin.Engine {
|
|||||||
v1AppGroup.GET("/rely/:id/info", v1.ContainerRelyInfo)
|
v1AppGroup.GET("/rely/:id/info", v1.ContainerRelyInfo)
|
||||||
v1AppGroup.GET("/install/config", v1.GetDockerInstallConfig)
|
v1AppGroup.GET("/install/config", v1.GetDockerInstallConfig)
|
||||||
//v1AppGroup.POST("/custom/install", v1.CustomInstallApp)
|
//v1AppGroup.POST("/custom/install", v1.CustomInstallApp)
|
||||||
|
v1AppGroup.POST("/share", v1.ShareAppFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
v1SysGroup := v1Group.Group("/sys")
|
v1SysGroup := v1Group.Group("/sys")
|
||||||
@@ -265,6 +266,9 @@ func InitRouter() *gin.Engine {
|
|||||||
{
|
{
|
||||||
v1SearchGroup.GET("/search", v1.GetSearchList)
|
v1SearchGroup.GET("/search", v1.GetSearchList)
|
||||||
}
|
}
|
||||||
|
v1Group.GET("/sync/config", v1.GetSyncConfig)
|
||||||
|
v1Group.Any("/syncthing/*url", v1.SyncToSyncthing)
|
||||||
|
|
||||||
}
|
}
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,19 @@
|
|||||||
package v1
|
package v1
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
"github.com/IceWhaleTech/CasaOS/model"
|
"github.com/IceWhaleTech/CasaOS/model"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/pkg/docker"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/env_helper"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
||||||
oasis_err2 "github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
|
oasis_err2 "github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
|
||||||
port2 "github.com/IceWhaleTech/CasaOS/pkg/utils/port"
|
port2 "github.com/IceWhaleTech/CasaOS/pkg/utils/port"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/sort"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/service"
|
"github.com/IceWhaleTech/CasaOS/service"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"net/http"
|
|
||||||
"strconv"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// @Summary 获取远程列表
|
// @Summary 获取远程列表
|
||||||
@@ -110,51 +114,66 @@ func MyAppList(c *gin.Context) {
|
|||||||
func AppInfo(c *gin.Context) {
|
func AppInfo(c *gin.Context) {
|
||||||
|
|
||||||
id := c.Param("id")
|
id := c.Param("id")
|
||||||
info := service.MyService.App().GetServerAppInfo(id)
|
info := service.MyService.OAPI().GetServerAppInfo(id)
|
||||||
if info.NetworkModel != "host" {
|
if info.NetworkModel != "host" {
|
||||||
port, _ := port2.GetAvailablePort("tcp")
|
for i := 0; i < len(info.Ports); i++ {
|
||||||
info.PortMap = uint(port)
|
if p, _ := strconv.Atoi(info.Ports[i].ContainerPort); port2.IsPortAvailable(p, info.Ports[i].Protocol) {
|
||||||
for i := 0; i < len(info.Configures.TcpPorts); i++ {
|
info.Ports[i].CommendPort = strconv.Itoa(p)
|
||||||
info.Configures.TcpPorts[i].CommendPort, _ = port2.GetAvailablePort("tcp")
|
|
||||||
}
|
|
||||||
for i := 0; i < len(info.Configures.UdpPorts); i++ {
|
|
||||||
info.Configures.UdpPorts[i].CommendPort, _ = port2.GetAvailablePort("udp")
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
info.PortMap = info.TcpPort
|
if info.Ports[i].Protocol == "tcp" {
|
||||||
|
if p, err := port2.GetAvailablePort("tcp"); err == nil {
|
||||||
|
info.Ports[i].CommendPort = strconv.Itoa(p)
|
||||||
|
}
|
||||||
|
} else if info.Ports[i].Protocol == "upd" {
|
||||||
|
if p, err := port2.GetAvailablePort("udp"); err == nil {
|
||||||
|
info.Ports[i].CommendPort = strconv.Itoa(p)
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := 0; i < len(info.Configures.Devices); i++ {
|
|
||||||
if !file.CheckNotExist(info.Configures.Devices[i].ContainerPath) {
|
|
||||||
info.Configures.Devices[i].Path = info.Configures.Devices[i].ContainerPath
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
portOrder := func(c1, c2 *model.Ports) bool {
|
if info.Ports[i].Type == 0 {
|
||||||
return c1.Type < c2.Type
|
info.PortMap = info.Ports[i].CommendPort
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
envOrder := func(c1, c2 *model.Envs) bool {
|
for i := 0; i < len(info.Devices); i++ {
|
||||||
return c1.Type < c2.Type
|
if !file.CheckNotExist(info.Devices[i].ContainerPath) {
|
||||||
|
info.Devices[i].Path = info.Devices[i].ContainerPath
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(info.Tip) > 0 {
|
||||||
|
info.Tip = env_helper.ReplaceStringDefaultENV(info.Tip)
|
||||||
}
|
}
|
||||||
|
|
||||||
volOrder := func(c1, c2 *model.Volume) bool {
|
for i := 0; i < len(info.Volumes); i++ {
|
||||||
return c1.Type < c2.Type
|
info.Volumes[i].Path = docker.GetDir("", info.Volumes[i].ContainerPath)
|
||||||
}
|
}
|
||||||
|
// portOrder := func(c1, c2 *model.Ports) bool {
|
||||||
|
// return c1.Type < c2.Type
|
||||||
|
// }
|
||||||
|
|
||||||
devOrder := func(c1, c2 *model.Devices) bool {
|
// envOrder := func(c1, c2 *model.Envs) bool {
|
||||||
return c1.Type < c2.Type
|
// return c1.Type < c2.Type
|
||||||
}
|
// }
|
||||||
|
|
||||||
|
// volOrder := func(c1, c2 *model.Volume) bool {
|
||||||
|
// return c1.Type < c2.Type
|
||||||
|
// }
|
||||||
|
|
||||||
|
// devOrder := func(c1, c2 *model.Devices) bool {
|
||||||
|
// return c1.Type < c2.Type
|
||||||
|
// }
|
||||||
|
|
||||||
//sort
|
//sort
|
||||||
if info.NetworkModel != "host" {
|
// if info.NetworkModel != "host" {
|
||||||
sort.PortsSort(portOrder).Sort(info.Configures.TcpPorts)
|
// sort.PortsSort(portOrder).Sort(info.Configures.TcpPorts)
|
||||||
sort.PortsSort(portOrder).Sort(info.Configures.UdpPorts)
|
// sort.PortsSort(portOrder).Sort(info.Configures.UdpPorts)
|
||||||
}
|
// }
|
||||||
|
|
||||||
sort.EnvSort(envOrder).Sort(info.Configures.Envs)
|
// sort.EnvSort(envOrder).Sort(info.Envs)
|
||||||
sort.VolSort(volOrder).Sort(info.Configures.Volumes)
|
// sort.VolSort(volOrder).Sort(info.Volumes.([]model.PathMap))
|
||||||
sort.DevSort(devOrder).Sort(info.Configures.Devices)
|
// sort.DevSort(devOrder).Sort(info.Devices)
|
||||||
|
|
||||||
info.MaxMemory = service.MyService.ZiMa().GetMemInfo().Total >> 20
|
info.MaxMemory = service.MyService.ZiMa().GetMemInfo().Total >> 20
|
||||||
|
|
||||||
@@ -180,3 +199,16 @@ func CategoryList(c *gin.Context) {
|
|||||||
list = append(list, rear...)
|
list = append(list, rear...)
|
||||||
c.JSON(http.StatusOK, &model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: list})
|
c.JSON(http.StatusOK, &model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: list})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @Summary 分享该应用配置
|
||||||
|
// @Produce application/json
|
||||||
|
// @Accept application/json
|
||||||
|
// @Tags app
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
// @Success 200 {string} string "ok"
|
||||||
|
// @Router /app/share [post]
|
||||||
|
func ShareAppFile(c *gin.Context) {
|
||||||
|
str, _ := ioutil.ReadAll(c.Request.Body)
|
||||||
|
content := service.MyService.OAPI().ShareAppFile(str)
|
||||||
|
c.JSON(http.StatusOK, json.RawMessage(content))
|
||||||
|
}
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import (
|
|||||||
"github.com/gorilla/websocket"
|
"github.com/gorilla/websocket"
|
||||||
"github.com/jinzhu/copier"
|
"github.com/jinzhu/copier"
|
||||||
uuid "github.com/satori/go.uuid"
|
uuid "github.com/satori/go.uuid"
|
||||||
|
"github.com/tidwall/gjson"
|
||||||
"golang.org/x/crypto/ssh"
|
"golang.org/x/crypto/ssh"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -172,7 +173,7 @@ func InstallApp(c *gin.Context) {
|
|||||||
dockerImageVersion = "latest"
|
dockerImageVersion = "latest"
|
||||||
}
|
}
|
||||||
if m.Origin != "custom" {
|
if m.Origin != "custom" {
|
||||||
appInfo = service.MyService.App().GetServerAppInfo(appId)
|
appInfo = service.MyService.OAPI().GetServerAppInfo(appId)
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
@@ -239,6 +240,7 @@ func InstallApp(c *gin.Context) {
|
|||||||
go func() {
|
go func() {
|
||||||
installLog := model2.AppNotify{}
|
installLog := model2.AppNotify{}
|
||||||
installLog.State = 0
|
installLog.State = 0
|
||||||
|
installLog.CustomId = id
|
||||||
installLog.Message = "installing rely"
|
installLog.Message = "installing rely"
|
||||||
installLog.Type = types.NOTIFY_TYPE_UNIMPORTANT
|
installLog.Type = types.NOTIFY_TYPE_UNIMPORTANT
|
||||||
installLog.CreatedAt = strconv.FormatInt(time.Now().Unix(), 10)
|
installLog.CreatedAt = strconv.FormatInt(time.Now().Unix(), 10)
|
||||||
@@ -282,7 +284,6 @@ func InstallApp(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
installLog.Message = "pulling"
|
installLog.Message = "pulling"
|
||||||
@@ -333,6 +334,8 @@ func InstallApp(c *gin.Context) {
|
|||||||
service.MyService.Notify().UpdateLog(installLog)
|
service.MyService.Notify().UpdateLog(installLog)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// echo -e "hellow\nworld" >>
|
||||||
|
|
||||||
//step:启动容器
|
//step:启动容器
|
||||||
err = service.MyService.Docker().DockerContainerStart(id)
|
err = service.MyService.Docker().DockerContainerStart(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -685,7 +688,11 @@ func UnInstallApp(c *gin.Context) {
|
|||||||
if info.Origin != "custom" {
|
if info.Origin != "custom" {
|
||||||
|
|
||||||
//step: 删除文件夹
|
//step: 删除文件夹
|
||||||
service.MyService.App().DelAppConfigDir(appId)
|
vol := gjson.Get(info.Volumes, "#.host")
|
||||||
|
for _, v := range vol.Array() {
|
||||||
|
|
||||||
|
service.MyService.App().DelAppConfigDir(appId, v.String())
|
||||||
|
}
|
||||||
|
|
||||||
//step: 删除install log
|
//step: 删除install log
|
||||||
service.MyService.Notify().DelLog(appId)
|
service.MyService.Notify().DelLog(appId)
|
||||||
@@ -1119,16 +1126,20 @@ func ContainerUpdateInfo(c *gin.Context) {
|
|||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: err.Error()})
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: err.Error()})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var port model.PortArrey
|
var port model.PortArray
|
||||||
json2.Unmarshal([]byte(appInfo.Ports), &port)
|
json2.Unmarshal([]byte(appInfo.Ports), &port)
|
||||||
|
|
||||||
var envs model.EnvArrey
|
var envs model.EnvArray
|
||||||
json2.Unmarshal([]byte(appInfo.Envs), &envs)
|
json2.Unmarshal([]byte(appInfo.Envs), &envs)
|
||||||
|
|
||||||
var vol model.PathArrey
|
var vol model.PathArray
|
||||||
json2.Unmarshal([]byte(appInfo.Volumes), &vol)
|
json2.Unmarshal([]byte(appInfo.Volumes), &vol)
|
||||||
|
|
||||||
var dir model.PathArrey
|
for i := 0; i < len(vol); i++ {
|
||||||
|
vol[i].Path = strings.ReplaceAll(vol[i].Path, "$AppID", appId)
|
||||||
|
}
|
||||||
|
|
||||||
|
var dir model.PathArray
|
||||||
json2.Unmarshal([]byte(appInfo.Devices), &dir)
|
json2.Unmarshal([]byte(appInfo.Devices), &dir)
|
||||||
|
|
||||||
//volumesStr, _ := json2.Marshal(m.Volumes)
|
//volumesStr, _ := json2.Marshal(m.Volumes)
|
||||||
|
|||||||
35
route/v1/sync.go
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
package v1
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"net/http/httputil"
|
||||||
|
"net/url"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/IceWhaleTech/CasaOS/model"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func SyncToSyncthing(c *gin.Context) {
|
||||||
|
u := c.Param("url")
|
||||||
|
target := "http://" + strings.Split(c.Request.Host, ":")[0] + ":" + config.SystemConfigInfo.SyncPort
|
||||||
|
remote, err := url.Parse(target)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
proxy := httputil.NewSingleHostReverseProxy(remote)
|
||||||
|
c.Request.Header.Add("X-API-Key", config.SystemConfigInfo.SyncKey)
|
||||||
|
//c.Request.Header.Add("X-API-Key", config.SystemConfigInfo.SyncKey)
|
||||||
|
c.Request.URL.Path = u
|
||||||
|
|
||||||
|
proxy.ServeHTTP(c.Writer, c.Request)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetSyncConfig(c *gin.Context) {
|
||||||
|
data := make(map[string]string)
|
||||||
|
data["key"] = config.SystemConfigInfo.SyncKey
|
||||||
|
data["port"] = config.SystemConfigInfo.SyncPort
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS), Data: data})
|
||||||
|
}
|
||||||
109
service/app.go
@@ -2,35 +2,32 @@ package service
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
json2 "encoding/json"
|
"strings"
|
||||||
"github.com/IceWhaleTech/CasaOS/model"
|
"time"
|
||||||
|
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/docker"
|
"github.com/IceWhaleTech/CasaOS/pkg/docker"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/command"
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/command"
|
||||||
httper2 "github.com/IceWhaleTech/CasaOS/pkg/utils/httper"
|
|
||||||
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
|
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
|
||||||
model2 "github.com/IceWhaleTech/CasaOS/service/model"
|
model2 "github.com/IceWhaleTech/CasaOS/service/model"
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types"
|
||||||
"github.com/docker/docker/api/types/filters"
|
"github.com/docker/docker/api/types/filters"
|
||||||
client2 "github.com/docker/docker/client"
|
client2 "github.com/docker/docker/client"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/tidwall/gjson"
|
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type AppService interface {
|
type AppService interface {
|
||||||
GetMyList(index, size int, position bool) *[]model2.MyAppList
|
GetMyList(index, size int, position bool) *[]model2.MyAppList
|
||||||
SaveContainer(m model2.AppListDBModel)
|
SaveContainer(m model2.AppListDBModel)
|
||||||
GetServerAppInfo(id string) model.ServerAppList
|
|
||||||
GetUninstallInfo(id string) model2.AppListDBModel
|
GetUninstallInfo(id string) model2.AppListDBModel
|
||||||
RemoveContainerById(id string)
|
RemoveContainerById(id string)
|
||||||
GetContainerInfo(name string) (types.Container, error)
|
GetContainerInfo(name string) (types.Container, error)
|
||||||
GetAppDBInfo(id string) model2.AppListDBModel
|
GetAppDBInfo(id string) model2.AppListDBModel
|
||||||
UpdateApp(m model2.AppListDBModel)
|
UpdateApp(m model2.AppListDBModel)
|
||||||
GetSimpleContainerInfo(name string) (types.Container, error)
|
GetSimpleContainerInfo(name string) (types.Container, error)
|
||||||
DelAppConfigDir(id string)
|
DelAppConfigDir(id, path string)
|
||||||
|
GetSystemAppList() *[]model2.MyAppList
|
||||||
}
|
}
|
||||||
|
|
||||||
type appStruct struct {
|
type appStruct struct {
|
||||||
@@ -56,7 +53,7 @@ func (a *appStruct) GetMyList(index, size int, position bool) *[]model2.MyAppLis
|
|||||||
//获取本地数据库应用
|
//获取本地数据库应用
|
||||||
|
|
||||||
var lm []model2.AppListDBModel
|
var lm []model2.AppListDBModel
|
||||||
a.db.Table(model2.CONTAINERTABLENAME).Select("title,icon,port_map,`index`,container_id,position,label,slogan").Find(&lm)
|
a.db.Table(model2.CONTAINERTABLENAME).Select("title,icon,port_map,`index`,container_id,position,label,slogan,image").Find(&lm)
|
||||||
|
|
||||||
list := []model2.MyAppList{}
|
list := []model2.MyAppList{}
|
||||||
lMap := make(map[string]interface{})
|
lMap := make(map[string]interface{})
|
||||||
@@ -69,6 +66,67 @@ func (a *appStruct) GetMyList(index, size int, position bool) *[]model2.MyAppLis
|
|||||||
lMap[dbModel.ContainerId] = dbModel
|
lMap[dbModel.ContainerId] = dbModel
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for _, container := range containers {
|
||||||
|
|
||||||
|
if lMap[container.ID] != nil && container.Labels["origin"] != "system" {
|
||||||
|
var m model2.AppListDBModel
|
||||||
|
m = lMap[container.ID].(model2.AppListDBModel)
|
||||||
|
if len(m.Label) == 0 {
|
||||||
|
m.Label = m.Title
|
||||||
|
}
|
||||||
|
|
||||||
|
info, err := cli.ContainerInspect(context.Background(), container.ID)
|
||||||
|
var tm string
|
||||||
|
if err != nil {
|
||||||
|
tm = time.Now().String()
|
||||||
|
} else {
|
||||||
|
tm = info.State.StartedAt
|
||||||
|
}
|
||||||
|
list = append(list, model2.MyAppList{
|
||||||
|
Name: m.Label,
|
||||||
|
Icon: m.Icon,
|
||||||
|
State: container.State,
|
||||||
|
CustomId: strings.ReplaceAll(container.Names[0], "/", ""),
|
||||||
|
Port: m.PortMap,
|
||||||
|
Index: m.Index,
|
||||||
|
UpTime: tm,
|
||||||
|
Image: m.Image,
|
||||||
|
Slogan: m.Slogan,
|
||||||
|
//Rely: m.Rely,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return &list
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//system application list
|
||||||
|
func (a *appStruct) GetSystemAppList() *[]model2.MyAppList {
|
||||||
|
//获取docker应用
|
||||||
|
cli, err := client2.NewClientWithOpts(client2.FromEnv)
|
||||||
|
if err != nil {
|
||||||
|
a.log.Error("初始化client失败", "app.getmylist", "line:36", err)
|
||||||
|
}
|
||||||
|
defer cli.Close()
|
||||||
|
fts := filters.NewArgs()
|
||||||
|
fts.Add("label", "origin=system")
|
||||||
|
containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{All: true, Filters: fts})
|
||||||
|
if err != nil {
|
||||||
|
a.log.Error("获取docker容器失败", "app.getmylist", "line:42", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
//获取本地数据库应用
|
||||||
|
|
||||||
|
var lm []model2.AppListDBModel
|
||||||
|
a.db.Table(model2.CONTAINERTABLENAME).Select("title,icon,port_map,`index`,container_id,position,label,slogan,image,volumes").Find(&lm)
|
||||||
|
|
||||||
|
list := []model2.MyAppList{}
|
||||||
|
lMap := make(map[string]interface{})
|
||||||
|
for _, dbModel := range lm {
|
||||||
|
lMap[dbModel.ContainerId] = dbModel
|
||||||
|
}
|
||||||
for _, container := range containers {
|
for _, container := range containers {
|
||||||
|
|
||||||
if lMap[container.ID] != nil {
|
if lMap[container.ID] != nil {
|
||||||
@@ -93,7 +151,9 @@ func (a *appStruct) GetMyList(index, size int, position bool) *[]model2.MyAppLis
|
|||||||
Port: m.PortMap,
|
Port: m.PortMap,
|
||||||
Index: m.Index,
|
Index: m.Index,
|
||||||
UpTime: tm,
|
UpTime: tm,
|
||||||
|
Image: m.Image,
|
||||||
Slogan: m.Slogan,
|
Slogan: m.Slogan,
|
||||||
|
Volumes: m.Volumes,
|
||||||
//Rely: m.Rely,
|
//Rely: m.Rely,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -155,27 +215,6 @@ func (a *appStruct) GetUninstallInfo(id string) model2.AppListDBModel {
|
|||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *appStruct) GetServerAppInfo(id string) model.ServerAppList {
|
|
||||||
|
|
||||||
head := make(map[string]string)
|
|
||||||
|
|
||||||
t := make(chan string)
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
str := httper2.Get(config.ServerInfo.ServerApi+"/token", nil)
|
|
||||||
|
|
||||||
t <- gjson.Get(str, "data").String()
|
|
||||||
}()
|
|
||||||
head["Authorization"] = <-t
|
|
||||||
|
|
||||||
infoS := httper2.Get(config.ServerInfo.ServerApi+"/v1/app/info/"+id, head)
|
|
||||||
|
|
||||||
info := model.ServerAppList{}
|
|
||||||
json2.Unmarshal([]byte(gjson.Get(infoS, "data").String()), &info)
|
|
||||||
|
|
||||||
return info
|
|
||||||
}
|
|
||||||
|
|
||||||
//创建容器成功后保存容器
|
//创建容器成功后保存容器
|
||||||
func (a *appStruct) SaveContainer(m model2.AppListDBModel) {
|
func (a *appStruct) SaveContainer(m model2.AppListDBModel) {
|
||||||
a.db.Table(model2.CONTAINERTABLENAME).Create(&m)
|
a.db.Table(model2.CONTAINERTABLENAME).Create(&m)
|
||||||
@@ -185,14 +224,20 @@ func (a *appStruct) UpdateApp(m model2.AppListDBModel) {
|
|||||||
a.db.Table(model2.CONTAINERTABLENAME).Save(&m)
|
a.db.Table(model2.CONTAINERTABLENAME).Save(&m)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *appStruct) DelAppConfigDir(id string) {
|
func (a *appStruct) DelAppConfigDir(id, path string) {
|
||||||
command.OnlyExec("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;DelAppConfigDir " + docker.GetDir(id, "/config"))
|
command.OnlyExec("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;DelAppConfigDir " + docker.GetDir(id, path))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *appStruct) RemoveContainerById(id string) {
|
func (a *appStruct) RemoveContainerById(id string) {
|
||||||
a.db.Table(model2.CONTAINERTABLENAME).Where("custom_id = ?", id).Delete(&model2.AppListDBModel{})
|
a.db.Table(model2.CONTAINERTABLENAME).Where("custom_id = ?", id).Delete(&model2.AppListDBModel{})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// init install
|
||||||
|
func Init() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
func NewAppService(db *gorm.DB, logger loger2.OLog) AppService {
|
func NewAppService(db *gorm.DB, logger loger2.OLog) AppService {
|
||||||
|
Init()
|
||||||
return &appStruct{db: db, log: logger}
|
return &appStruct{db: db, log: logger}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,16 +11,27 @@ import (
|
|||||||
"github.com/tidwall/gjson"
|
"github.com/tidwall/gjson"
|
||||||
)
|
)
|
||||||
|
|
||||||
type OasisService interface {
|
type CasaService interface {
|
||||||
GetServerList(index, size, tp, categoryId, key string) ([]model.ServerAppList, int64)
|
GetServerList(index, size, tp, categoryId, key string) ([]model.ServerAppList, int64)
|
||||||
GetServerCategoryList() []model.ServerCategoryList
|
GetServerCategoryList() []model.ServerCategoryList
|
||||||
GetTaskList(size int) []model2.TaskDBModel
|
GetTaskList(size int) []model2.TaskDBModel
|
||||||
|
GetServerAppInfo(id string) model.ServerAppList
|
||||||
|
ShareAppFile(body []byte) string
|
||||||
}
|
}
|
||||||
|
|
||||||
type oasisService struct {
|
type casaService struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *oasisService) GetTaskList(size int) []model2.TaskDBModel {
|
func (o *casaService) ShareAppFile(body []byte) string {
|
||||||
|
head := make(map[string]string)
|
||||||
|
|
||||||
|
head["Authorization"] = GetToken()
|
||||||
|
|
||||||
|
content := httper2.Post(config.ServerInfo.ServerApi+"/v1/community/add", body, "application/json", head)
|
||||||
|
return content
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *casaService) GetTaskList(size int) []model2.TaskDBModel {
|
||||||
head := make(map[string]string)
|
head := make(map[string]string)
|
||||||
|
|
||||||
head["Authorization"] = GetToken()
|
head["Authorization"] = GetToken()
|
||||||
@@ -33,7 +44,7 @@ func (o *oasisService) GetTaskList(size int) []model2.TaskDBModel {
|
|||||||
return list
|
return list
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *oasisService) GetServerList(index, size, tp, categoryId, key string) ([]model.ServerAppList, int64) {
|
func (o *casaService) GetServerList(index, size, tp, categoryId, key string) ([]model.ServerAppList, int64) {
|
||||||
|
|
||||||
head := make(map[string]string)
|
head := make(map[string]string)
|
||||||
|
|
||||||
@@ -49,7 +60,7 @@ func (o *oasisService) GetServerList(index, size, tp, categoryId, key string) ([
|
|||||||
return list, count
|
return list, count
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *oasisService) GetServerCategoryList() []model.ServerCategoryList {
|
func (o *casaService) GetServerCategoryList() []model.ServerCategoryList {
|
||||||
|
|
||||||
head := make(map[string]string)
|
head := make(map[string]string)
|
||||||
head["Authorization"] = GetToken()
|
head["Authorization"] = GetToken()
|
||||||
@@ -62,7 +73,19 @@ func (o *oasisService) GetServerCategoryList() []model.ServerCategoryList {
|
|||||||
|
|
||||||
return list
|
return list
|
||||||
}
|
}
|
||||||
|
func (o *casaService) GetServerAppInfo(id string) model.ServerAppList {
|
||||||
|
|
||||||
|
head := make(map[string]string)
|
||||||
|
|
||||||
|
head["Authorization"] = GetToken()
|
||||||
|
|
||||||
|
infoS := httper2.Get(config.ServerInfo.ServerApi+"/v1/app/info/"+id, head)
|
||||||
|
|
||||||
|
info := model.ServerAppList{}
|
||||||
|
json2.Unmarshal([]byte(gjson.Get(infoS, "data").String()), &info)
|
||||||
|
|
||||||
|
return info
|
||||||
|
}
|
||||||
func GetToken() string {
|
func GetToken() string {
|
||||||
t := make(chan string)
|
t := make(chan string)
|
||||||
keyName := "casa_token"
|
keyName := "casa_token"
|
||||||
@@ -86,6 +109,6 @@ func GetToken() string {
|
|||||||
return auth
|
return auth
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewOasisService() OasisService {
|
func NewOasisService() CasaService {
|
||||||
return &oasisService{}
|
return &casaService{}
|
||||||
}
|
}
|
||||||
@@ -3,14 +3,15 @@ package service
|
|||||||
import (
|
import (
|
||||||
json2 "encoding/json"
|
json2 "encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/IceWhaleTech/CasaOS/model"
|
"github.com/IceWhaleTech/CasaOS/model"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||||
command2 "github.com/IceWhaleTech/CasaOS/pkg/utils/command"
|
command2 "github.com/IceWhaleTech/CasaOS/pkg/utils/command"
|
||||||
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
|
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
|
||||||
"github.com/shirou/gopsutil/v3/disk"
|
"github.com/shirou/gopsutil/v3/disk"
|
||||||
"github.com/tidwall/gjson"
|
"github.com/tidwall/gjson"
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type DiskService interface {
|
type DiskService interface {
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
json2 "encoding/json"
|
json2 "encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"reflect"
|
||||||
"regexp"
|
"regexp"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
@@ -20,6 +21,7 @@ import (
|
|||||||
"github.com/IceWhaleTech/CasaOS/model"
|
"github.com/IceWhaleTech/CasaOS/model"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/docker"
|
"github.com/IceWhaleTech/CasaOS/pkg/docker"
|
||||||
command2 "github.com/IceWhaleTech/CasaOS/pkg/utils/command"
|
command2 "github.com/IceWhaleTech/CasaOS/pkg/utils/command"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/env_helper"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
||||||
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
|
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
|
||||||
|
|
||||||
@@ -60,6 +62,7 @@ type DockerService interface {
|
|||||||
DockerNetworkModelList() []types.NetworkResource
|
DockerNetworkModelList() []types.NetworkResource
|
||||||
DockerImageInfo(image string)
|
DockerImageInfo(image string)
|
||||||
GetNetWorkNameByNetWorkID(id string) (string, error)
|
GetNetWorkNameByNetWorkID(id string) (string, error)
|
||||||
|
ContainerExecShell(container_id string) string
|
||||||
}
|
}
|
||||||
|
|
||||||
type dockerService struct {
|
type dockerService struct {
|
||||||
@@ -67,15 +70,20 @@ type dockerService struct {
|
|||||||
log loger2.OLog
|
log loger2.OLog
|
||||||
}
|
}
|
||||||
|
|
||||||
func DockerPs() {
|
func (ds *dockerService) ContainerExecShell(container_id string) string {
|
||||||
cli, _ := client2.NewClientWithOpts(client2.FromEnv)
|
cli, _ := client2.NewClientWithOpts(client2.FromEnv)
|
||||||
containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{})
|
exec, err := cli.ContainerExecCreate(context.Background(), container_id, types.ExecConfig{
|
||||||
|
User: "1000:1000",
|
||||||
|
Cmd: []string{"echo -e \"hellow\nworld\" >> /a.txt"},
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
os.Exit(5)
|
os.Exit(5)
|
||||||
}
|
}
|
||||||
for _, container := range containers {
|
err = cli.ContainerExecStart(context.Background(), exec.ID, types.ExecStartCheck{})
|
||||||
fmt.Printf("%s %s\n", container.ID[:10], container.Image)
|
if err != nil {
|
||||||
|
fmt.Println("exec script error ", err)
|
||||||
}
|
}
|
||||||
|
return exec.ID
|
||||||
}
|
}
|
||||||
|
|
||||||
//创建默认网络
|
//创建默认网络
|
||||||
@@ -325,11 +333,14 @@ func (ds *dockerService) DockerPullImage(imageName string, m model2.AppNotify) e
|
|||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
if !reflect.DeepEqual(m, model2.AppNotify{}) {
|
||||||
m.Type = types2.NOTIFY_TYPE_INSTALL_LOG
|
m.Type = types2.NOTIFY_TYPE_INSTALL_LOG
|
||||||
m.State = 0
|
m.State = 0
|
||||||
m.Message = string(buf[:n])
|
m.Message = string(buf[:n])
|
||||||
MyService.Notify().UpdateLog(m)
|
MyService.Notify().UpdateLog(m)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -401,6 +412,10 @@ func (ds *dockerService) DockerContainerCreate(imageName string, containerDbId s
|
|||||||
|
|
||||||
var envArr []string
|
var envArr []string
|
||||||
for _, e := range m.Envs {
|
for _, e := range m.Envs {
|
||||||
|
if strings.HasPrefix(e.Value, "$") {
|
||||||
|
envArr = append(envArr, e.Name+"="+env_helper.ReplaceDefaultENV(e.Value))
|
||||||
|
continue
|
||||||
|
}
|
||||||
if len(e.Value) > 0 {
|
if len(e.Value) > 0 {
|
||||||
if e.Value == "port_map" {
|
if e.Value == "port_map" {
|
||||||
envArr = append(envArr, e.Name+"="+m.PortMap)
|
envArr = append(envArr, e.Name+"="+m.PortMap)
|
||||||
@@ -433,6 +448,7 @@ func (ds *dockerService) DockerContainerCreate(imageName string, containerDbId s
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
path = strings.ReplaceAll(path, "$AppID", containerDbId)
|
||||||
reg1 := regexp.MustCompile(`([^<>/\\\|:""\*\?]+\.\w+$)`)
|
reg1 := regexp.MustCompile(`([^<>/\\\|:""\*\?]+\.\w+$)`)
|
||||||
result1 := reg1.FindAllStringSubmatch(path, -1)
|
result1 := reg1.FindAllStringSubmatch(path, -1)
|
||||||
if len(result1) == 0 {
|
if len(result1) == 0 {
|
||||||
@@ -475,11 +491,12 @@ func (ds *dockerService) DockerContainerCreate(imageName string, containerDbId s
|
|||||||
StartPeriod: 0,
|
StartPeriod: 0,
|
||||||
Retries: 1000,
|
Retries: 1000,
|
||||||
}
|
}
|
||||||
|
fmt.Print(health)
|
||||||
config := &container.Config{
|
config := &container.Config{
|
||||||
Image: imageName,
|
Image: imageName,
|
||||||
Labels: map[string]string{"origin": m.Origin, m.Origin: m.Origin},
|
Labels: map[string]string{"origin": m.Origin, m.Origin: m.Origin},
|
||||||
Env: envArr,
|
Env: envArr,
|
||||||
Healthcheck: health,
|
// Healthcheck: health,
|
||||||
}
|
}
|
||||||
hostConfig := &container.HostConfig{Resources: res, Mounts: volumes, RestartPolicy: rp, NetworkMode: container.NetworkMode(net)}
|
hostConfig := &container.HostConfig{Resources: res, Mounts: volumes, RestartPolicy: rp, NetworkMode: container.NetworkMode(net)}
|
||||||
//if net != "host" {
|
//if net != "host" {
|
||||||
@@ -816,7 +833,6 @@ func Containerd() {
|
|||||||
)
|
)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("333")
|
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
}
|
}
|
||||||
defer container.Delete(ctx, containerd.WithSnapshotCleanup)
|
defer container.Delete(ctx, containerd.WithSnapshotCleanup)
|
||||||
@@ -824,7 +840,6 @@ func Containerd() {
|
|||||||
// create a task from the container
|
// create a task from the container
|
||||||
task, err := container.NewTask(ctx, cio.NewCreator(cio.WithStdio))
|
task, err := container.NewTask(ctx, cio.NewCreator(cio.WithStdio))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("444")
|
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
}
|
}
|
||||||
defer task.Delete(ctx)
|
defer task.Delete(ctx)
|
||||||
@@ -837,7 +852,6 @@ func Containerd() {
|
|||||||
|
|
||||||
// call start on the task to execute the redis server
|
// call start on the task to execute the redis server
|
||||||
if err = task.Start(ctx); err != nil {
|
if err = task.Start(ctx); err != nil {
|
||||||
fmt.Println("555")
|
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -847,7 +861,6 @@ func Containerd() {
|
|||||||
|
|
||||||
// kill the process and get the exit status
|
// kill the process and get the exit status
|
||||||
if err = task.Kill(ctx, syscall.SIGTERM); err != nil {
|
if err = task.Kill(ctx, syscall.SIGTERM); err != nil {
|
||||||
fmt.Println("666")
|
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -856,7 +869,6 @@ func Containerd() {
|
|||||||
status := <-exitStatusC
|
status := <-exitStatusC
|
||||||
code, _, err := status.Result()
|
code, _, err := status.Result()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("777")
|
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
}
|
}
|
||||||
fmt.Printf("redis-server exited with status: %d\n", code)
|
fmt.Printf("redis-server exited with status: %d\n", code)
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package docker_base
|
|||||||
import "github.com/IceWhaleTech/CasaOS/model"
|
import "github.com/IceWhaleTech/CasaOS/model"
|
||||||
|
|
||||||
//过滤mysql关键字
|
//过滤mysql关键字
|
||||||
func MysqlFilter(c MysqlConfig, envs model.EnvArrey) model.EnvArrey {
|
func MysqlFilter(c MysqlConfig, envs model.EnvArray) model.EnvArray {
|
||||||
for i := 0; i < len(envs); i++ {
|
for i := 0; i < len(envs); i++ {
|
||||||
switch envs[i].Value {
|
switch envs[i].Value {
|
||||||
case "$MYSQL_HOST":
|
case "$MYSQL_HOST":
|
||||||
|
|||||||
@@ -61,4 +61,6 @@ type MyAppList struct {
|
|||||||
UpTime string `json:"up_time"`
|
UpTime string `json:"up_time"`
|
||||||
Slogan string `json:"slogan"`
|
Slogan string `json:"slogan"`
|
||||||
Rely model.MapStrings `json:"rely"` //[{"mysql":"id"},{"mysql":"id"}]
|
Rely model.MapStrings `json:"rely"` //[{"mysql":"id"},{"mysql":"id"}]
|
||||||
|
Image string `json:"image"`
|
||||||
|
Volumes string `json:"volumes"`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ type AppNotify struct {
|
|||||||
Type int `json:"type"` // 1:显示即为已读 2:info 3:warning 4:error 5:success
|
Type int `json:"type"` // 1:显示即为已读 2:info 3:warning 4:error 5:success
|
||||||
Icon string `json:"icon"`
|
Icon string `json:"icon"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
|
CustomId string `gorm:"column:custom_id;primary_key" json:"custom_id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *AppNotify) TableName() string {
|
func (p *AppNotify) TableName() string {
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ type Repository interface {
|
|||||||
//Redis() RedisService
|
//Redis() RedisService
|
||||||
ZeroTier() ZeroTierService
|
ZeroTier() ZeroTierService
|
||||||
ZiMa() ZiMaService
|
ZiMa() ZiMaService
|
||||||
OAPI() OasisService
|
OAPI() CasaService
|
||||||
Disk() DiskService
|
Disk() DiskService
|
||||||
Notify() NotifyServer
|
Notify() NotifyServer
|
||||||
ShareDirectory() ShareDirService
|
ShareDirectory() ShareDirService
|
||||||
@@ -30,6 +30,7 @@ type Repository interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NewService(db *gorm.DB, log loger2.OLog) Repository {
|
func NewService(db *gorm.DB, log loger2.OLog) Repository {
|
||||||
|
|
||||||
return &store{
|
return &store{
|
||||||
app: NewAppService(db, log),
|
app: NewAppService(db, log),
|
||||||
ddns: NewDDNSService(db, log),
|
ddns: NewDDNSService(db, log),
|
||||||
@@ -58,7 +59,7 @@ type store struct {
|
|||||||
docker DockerService
|
docker DockerService
|
||||||
zerotier ZeroTierService
|
zerotier ZeroTierService
|
||||||
zima ZiMaService
|
zima ZiMaService
|
||||||
oapi OasisService
|
oapi CasaService
|
||||||
disk DiskService
|
disk DiskService
|
||||||
notify NotifyServer
|
notify NotifyServer
|
||||||
shareDirectory ShareDirService
|
shareDirectory ShareDirService
|
||||||
@@ -105,7 +106,7 @@ func (c *store) ZeroTier() ZeroTierService {
|
|||||||
func (c *store) ZiMa() ZiMaService {
|
func (c *store) ZiMa() ZiMaService {
|
||||||
return c.zima
|
return c.zima
|
||||||
}
|
}
|
||||||
func (c *store) OAPI() OasisService {
|
func (c *store) OAPI() CasaService {
|
||||||
return c.oapi
|
return c.oapi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -39,7 +39,6 @@ func (s *systemService) UpSystemConfig(str string, widget string) {
|
|||||||
}
|
}
|
||||||
config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
|
config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *systemService) GetCasaOSLogs(lineNumber int) string {
|
func (s *systemService) GetCasaOSLogs(lineNumber int) string {
|
||||||
file, err := os.Open(s.log.Path())
|
file, err := os.Open(s.log.Path())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package types
|
package types
|
||||||
|
|
||||||
const CURRENTVERSION = "0.1.9"
|
const CURRENTVERSION = "0.2.0"
|
||||||
const BODY = "<li>add casaOS logs</li><li>add application terminal</li><li>add application logs</li>"
|
const BODY = "<li>add sync function</li><li>fixed some error</li>"
|
||||||
|
|||||||
BIN
web/favicon.ico
|
Before Width: | Height: | Size: 15 KiB |
14
web/favicon.svg
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 25.2.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
|
viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
|
||||||
|
<style type="text/css">
|
||||||
|
.st0{fill:none;stroke:#363636;stroke-width:2;stroke-linejoin:round;stroke-miterlimit:2;}
|
||||||
|
@media ( prefers-color-scheme: dark ) {
|
||||||
|
.st0{fill:none;stroke:#FFFFFF;stroke-width:2;stroke-linejoin:round;stroke-miterlimit:2;}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<path class="st0" d="M12,22c5.5,0,10-4.5,10-10S17.5,2,12,2S2,6.5,2,12S6.5,22,12,22z"/>
|
||||||
|
<path class="st0" d="M12,22c3.9,0,7-3.1,7-7s-3.1-7-7-7s-7,3.1-7,7S8.1,22,12,22z"/>
|
||||||
|
<path class="st0" d="M12,22c2.2,0,4-1.8,4-4s-1.8-4-4-4s-4,1.8-4,4S9.8,22,12,22z"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 863 B |
BIN
web/img/Account.1bc4a418.png
Normal file
|
After Width: | Height: | Size: 91 KiB |
72
web/img/Account.bde47fba.svg
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
<svg width="120" height="120" viewBox="0 0 120 120" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M0 60C0 26.8629 26.8629 0 60 0V0C93.1371 0 120 26.8629 120 60V60C120 93.1371 93.1371 120 60 120V120C26.8629 120 0 93.1371 0 60V60Z" fill="url(#paint0_linear_582:2091)"/>
|
||||||
|
<g filter="url(#filter0_d_582:2091)">
|
||||||
|
<g filter="url(#filter1_iiiii_582:2091)">
|
||||||
|
<path d="M75.1248 42.125C75.1248 50.4783 68.3532 57.25 59.9999 57.25C51.6465 57.25 44.8749 50.4783 44.8749 42.125C44.8749 33.7717 51.6465 27 59.9999 27C68.3532 27 75.1248 33.7717 75.1248 42.125Z" fill="url(#paint1_linear_582:2091)"/>
|
||||||
|
<path d="M34.422 71.7327C41.316 66.1301 50.2453 62.75 59.9998 62.75C69.7544 62.75 78.6837 66.1301 85.5777 71.7327C89.5123 74.9302 89.5123 80.8198 85.5777 84.0174C78.6837 89.6199 69.7544 93 59.9998 93C50.2453 93 41.316 89.6199 34.422 84.0174C30.4874 80.8198 30.4874 74.9302 34.422 71.7327Z" fill="url(#paint2_linear_582:2091)"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<defs>
|
||||||
|
<filter id="filter0_d_582:2091" x="4" y="8" width="112" height="112" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||||
|
<feOffset dy="4"/>
|
||||||
|
<feGaussianBlur stdDeviation="6"/>
|
||||||
|
<feComposite in2="hardAlpha" operator="out"/>
|
||||||
|
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
|
||||||
|
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_582:2091"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_582:2091" result="shape"/>
|
||||||
|
</filter>
|
||||||
|
<filter id="filter1_iiiii_582:2091" x="27.4711" y="23" width="63.0576" height="72" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||||
|
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||||
|
<feOffset dx="2" dy="2"/>
|
||||||
|
<feGaussianBlur stdDeviation="3"/>
|
||||||
|
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
|
||||||
|
<feColorMatrix type="matrix" values="0 0 0 0 0.495833 0 0 0 0 0.879 0 0 0 0 1 0 0 0 0.4 0"/>
|
||||||
|
<feBlend mode="normal" in2="shape" result="effect1_innerShadow_582:2091"/>
|
||||||
|
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||||
|
<feOffset dx="-4" dy="-4"/>
|
||||||
|
<feGaussianBlur stdDeviation="3"/>
|
||||||
|
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
|
||||||
|
<feColorMatrix type="matrix" values="0 0 0 0 0.0205888 0 0 0 0 0.00944442 0 0 0 0 0.566667 0 0 0 0.2 0"/>
|
||||||
|
<feBlend mode="normal" in2="effect1_innerShadow_582:2091" result="effect2_innerShadow_582:2091"/>
|
||||||
|
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||||
|
<feOffset dx="1" dy="1"/>
|
||||||
|
<feGaussianBlur stdDeviation="1"/>
|
||||||
|
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
|
||||||
|
<feColorMatrix type="matrix" values="0 0 0 0 0.816667 0 0 0 0 0.945 0 0 0 0 1 0 0 0 0.2 0"/>
|
||||||
|
<feBlend mode="normal" in2="effect2_innerShadow_582:2091" result="effect3_innerShadow_582:2091"/>
|
||||||
|
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||||
|
<feOffset dx="-2" dy="-2"/>
|
||||||
|
<feGaussianBlur stdDeviation="2"/>
|
||||||
|
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
|
||||||
|
<feColorMatrix type="matrix" values="0 0 0 0 0.00608333 0 0 0 0 0 0 0 0 0 0.304167 0 0 0 0.2 0"/>
|
||||||
|
<feBlend mode="normal" in2="effect3_innerShadow_582:2091" result="effect4_innerShadow_582:2091"/>
|
||||||
|
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||||
|
<feOffset dx="-1" dy="-1"/>
|
||||||
|
<feGaussianBlur stdDeviation="0.5"/>
|
||||||
|
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
|
||||||
|
<feColorMatrix type="matrix" values="0 0 0 0 0.075 0 0 0 0 0.778 0 0 0 0 1 0 0 0 0.2 0"/>
|
||||||
|
<feBlend mode="normal" in2="effect4_innerShadow_582:2091" result="effect5_innerShadow_582:2091"/>
|
||||||
|
</filter>
|
||||||
|
<linearGradient id="paint0_linear_582:2091" x1="60" y1="0" x2="60" y2="120" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop stop-color="#5A9CFF"/>
|
||||||
|
<stop offset="0.87897" stop-color="#2A23D5"/>
|
||||||
|
<stop offset="1" stop-color="#4A3CEC"/>
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient id="paint1_linear_582:2091" x1="60" y1="40" x2="59.9998" y2="93" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop offset="0.0350902" stop-color="white"/>
|
||||||
|
<stop offset="0.525594" stop-color="#B0D4FF"/>
|
||||||
|
<stop offset="0.837131" stop-color="#DEEDFF"/>
|
||||||
|
<stop offset="1" stop-color="#FEFEFF"/>
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient id="paint2_linear_582:2091" x1="60" y1="40" x2="59.9998" y2="93" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop offset="0.0350902" stop-color="white"/>
|
||||||
|
<stop offset="0.525594" stop-color="#B0D4FF"/>
|
||||||
|
<stop offset="0.837131" stop-color="#DEEDFF"/>
|
||||||
|
<stop offset="1" stop-color="#FEFEFF"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 4.9 KiB |
BIN
web/img/Android-DeviceID.b57fefc8.png
Normal file
|
After Width: | Height: | Size: 182 KiB |
BIN
web/img/Android-Menu.ed4df0da.png
Normal file
|
After Width: | Height: | Size: 53 KiB |
BIN
web/img/Android-NewDevice.f00af2cb.png
Normal file
|
After Width: | Height: | Size: 64 KiB |
BIN
web/img/Android-NewDeviceAdd.784d2f18.png
Normal file
|
After Width: | Height: | Size: 121 KiB |
BIN
web/img/Android-NewFolder.d71dc444.png
Normal file
|
After Width: | Height: | Size: 82 KiB |
BIN
web/img/Android-NewFolderCreate.b3521b45.png
Normal file
|
After Width: | Height: | Size: 88 KiB |
BIN
web/img/Android-ShowDeviceID.f7e46fb8.png
Normal file
|
After Width: | Height: | Size: 124 KiB |
BIN
web/img/Windows-DeviceID.2e929f75.png
Normal file
|
After Width: | Height: | Size: 156 KiB |
BIN
web/img/Windows-NewDevice.c9f2471d.png
Normal file
|
After Width: | Height: | Size: 178 KiB |
BIN
web/img/Windows-NewDeviceSave.fe1078b1.png
Normal file
|
After Width: | Height: | Size: 394 KiB |
BIN
web/img/Windows-NewFolder.5305cc41.png
Normal file
|
After Width: | Height: | Size: 115 KiB |
BIN
web/img/Windows-NewFolderSave.9ce2312f.png
Normal file
|
After Width: | Height: | Size: 468 KiB |
BIN
web/img/Windows-ShowID.1000f319.png
Normal file
|
After Width: | Height: | Size: 53 KiB |
25
web/img/android.48a6cf16.svg
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 18.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
|
viewBox="0 0 64 64" enable-background="new 0 0 64 64" xml:space="preserve">
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<path fill="#A4C639" d="M32,0c17.7,0,32,14.3,32,32S49.7,64,32,64S0,49.7,0,32S14.3,0,32,0z"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<path fill="#FFFFFF" d="M16.6,24.6c-1.4,0-2.6,1.2-2.6,2.6L14,38c0,1.4,1.2,2.6,2.6,2.6c1.5,0,2.6-1.2,2.6-2.6l0-10.9
|
||||||
|
C19.3,25.7,18.1,24.6,16.6,24.6 M37.8,14.8l1.8-3.3c0.1-0.2,0-0.4-0.1-0.5c-0.2-0.1-0.4,0-0.5,0.1l-1.9,3.3
|
||||||
|
c-1.6-0.7-3.3-1.1-5.1-1.1c-1.8,0-3.6,0.4-5.1,1.1L25,11.2C24.9,11,24.7,11,24.5,11c-0.2,0.1-0.2,0.3-0.1,0.5l1.8,3.3
|
||||||
|
c-3.6,1.8-6,5.3-6,9.3l23.6,0C43.8,20.2,41.4,16.7,37.8,14.8 M26.6,19.9c-0.5,0-1-0.4-1-1c0-0.5,0.4-1,1-1c0.5,0,1,0.4,1,1
|
||||||
|
C27.6,19.5,27.2,19.9,26.6,19.9 M37.4,19.9c-0.5,0-1-0.4-1-1c0-0.5,0.4-1,1-1c0.5,0,1,0.4,1,1C38.4,19.5,37.9,19.9,37.4,19.9
|
||||||
|
M20.3,25.1l0,16.8c0,1.5,1.3,2.8,2.8,2.8l1.9,0l0,5.7c0,1.4,1.2,2.6,2.6,2.6c1.5,0,2.6-1.2,2.6-2.6l0-5.7l3.5,0l0,5.7
|
||||||
|
c0,1.4,1.2,2.6,2.6,2.6c1.5,0,2.6-1.2,2.6-2.6l0-5.7l1.9,0c1.5,0,2.8-1.2,2.8-2.8l0-16.8L20.3,25.1z M50,27.2
|
||||||
|
c0-1.4-1.2-2.6-2.6-2.6c-1.4,0-2.6,1.2-2.6,2.6l0,10.9c0,1.4,1.2,2.6,2.6,2.6c1.4,0,2.6-1.2,2.6-2.6L50,27.2z"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 301 KiB |
BIN
web/img/bg3.1e0d0d23.jpg
Normal file
|
After Width: | Height: | Size: 449 KiB |
BIN
web/img/macOS-Config.f419628a.png
Normal file
|
After Width: | Height: | Size: 39 KiB |
BIN
web/img/macOS-DeviceID.968cc84d.png
Normal file
|
After Width: | Height: | Size: 89 KiB |
BIN
web/img/macOS-NewFolder.fa9e37d0.png
Normal file
|
After Width: | Height: | Size: 54 KiB |
BIN
web/img/macOS-NewFolderSave.6f3f247d.png
Normal file
|
After Width: | Height: | Size: 180 KiB |
BIN
web/img/macOS-ShowID.c822acc3.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
web/img/macOS-icon.ae9e0906.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
159
web/img/macos.da8469ce.svg
Normal file
@@ -0,0 +1,159 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
version="1.1"
|
||||||
|
id="Capa_1"
|
||||||
|
x="0px"
|
||||||
|
y="0px"
|
||||||
|
viewBox="0 0 407 407"
|
||||||
|
style="enable-background:new 0 0 407 407;"
|
||||||
|
xml:space="preserve"><metadata
|
||||||
|
id="metadata36"><rdf:RDF><cc:Work
|
||||||
|
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
|
||||||
|
id="defs34"><linearGradient
|
||||||
|
xlink:href="#SVGID_1_"
|
||||||
|
id="linearGradient46"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
gradientTransform="matrix(1,0,0,-1,0,407.2074)"
|
||||||
|
x1="203.7169"
|
||||||
|
y1="7.7039"
|
||||||
|
x2="203.7169"
|
||||||
|
y2="402.0255" /><linearGradient
|
||||||
|
xlink:href="#SVGID_1_"
|
||||||
|
id="linearGradient48"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
gradientTransform="matrix(1,0,0,-1,0,407.2074)"
|
||||||
|
x1="203.7169"
|
||||||
|
y1="7.7039"
|
||||||
|
x2="203.7169"
|
||||||
|
y2="402.0255" />
|
||||||
|
|
||||||
|
|
||||||
|
<linearGradient
|
||||||
|
gradientTransform="matrix(1,0,0,-1,0,407.2074)"
|
||||||
|
y2="402.02551"
|
||||||
|
x2="203.7169"
|
||||||
|
y1="7.7038999"
|
||||||
|
x1="203.7169"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
id="linearGradient120"><stop
|
||||||
|
id="stop6-9"
|
||||||
|
style="stop-color:#F2F2F2"
|
||||||
|
offset="0" /><stop
|
||||||
|
id="stop8-1"
|
||||||
|
style="stop-color:#F7F7F7"
|
||||||
|
offset="0.5963" /><stop
|
||||||
|
id="stop10-7"
|
||||||
|
style="stop-color:#FEFEFE"
|
||||||
|
offset="1" /></linearGradient><filter
|
||||||
|
style="color-interpolation-filters:sRGB"
|
||||||
|
id="filter1002"
|
||||||
|
x="-0.013201674"
|
||||||
|
width="1.0264033"
|
||||||
|
y="-0.013198327"
|
||||||
|
height="1.0263967"><feGaussianBlur
|
||||||
|
stdDeviation="2.168925"
|
||||||
|
id="feGaussianBlur1004" /></filter></defs>
|
||||||
|
<style
|
||||||
|
type="text/css"
|
||||||
|
id="style2">
|
||||||
|
.st0{fill:url(#SVGID_1_);}
|
||||||
|
.st1{fill:#515151;}
|
||||||
|
</style>
|
||||||
|
<g
|
||||||
|
transform="matrix(1,0,0,0.98477354,0,6.0829719)"
|
||||||
|
id="g15-0"
|
||||||
|
style="fill:#4d4d4d;filter:url(#filter1002)"><linearGradient
|
||||||
|
gradientTransform="matrix(1,0,0,-1,0,407.2074)"
|
||||||
|
y2="402.02551"
|
||||||
|
x2="203.7169"
|
||||||
|
y1="7.7038999"
|
||||||
|
x1="203.7169"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
id="linearGradient91"><stop
|
||||||
|
id="stop85"
|
||||||
|
style="stop-color:#F2F2F2"
|
||||||
|
offset="0" /><stop
|
||||||
|
id="stop87"
|
||||||
|
style="stop-color:#F7F7F7"
|
||||||
|
offset="0.5963" /><stop
|
||||||
|
id="stop89"
|
||||||
|
style="stop-color:#FEFEFE"
|
||||||
|
offset="1" /></linearGradient><path
|
||||||
|
style="fill:#4d4d4d"
|
||||||
|
id="path13-7"
|
||||||
|
d="M 400.9,202.3 C 400.9,92.3 313.8,5.1 203.7,5.1 93.7,5.2 6.6,92.3 6.6,202.3 c 0,110 87.1,197.2 197.2,197.2 110.1,0 197.1,-87.1 197.1,-197.2 z"
|
||||||
|
class="st0" /><path
|
||||||
|
style="fill:#4d4d4d"
|
||||||
|
class="st0"
|
||||||
|
d="M 400.9,202.3 C 400.9,92.3 313.8,5.1 203.7,5.1 93.7,5.2 6.6,92.3 6.6,202.3 c 0,110 87.1,197.2 197.2,197.2 110.1,0 197.1,-87.1 197.1,-197.2 z"
|
||||||
|
id="path40-7" /></g><g
|
||||||
|
id="g15">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<linearGradient
|
||||||
|
gradientTransform="matrix(1,0,0,-1,0,407.2074)"
|
||||||
|
y2="402.02551"
|
||||||
|
x2="203.7169"
|
||||||
|
y1="7.7038999"
|
||||||
|
x1="203.7169"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
id="SVGID_1_">
|
||||||
|
<stop
|
||||||
|
id="stop6"
|
||||||
|
style="stop-color:#F2F2F2"
|
||||||
|
offset="0" />
|
||||||
|
<stop
|
||||||
|
id="stop8"
|
||||||
|
style="stop-color:#F7F7F7"
|
||||||
|
offset="0.5963" />
|
||||||
|
<stop
|
||||||
|
id="stop10"
|
||||||
|
style="stop-color:#FEFEFE"
|
||||||
|
offset="1" />
|
||||||
|
</linearGradient>
|
||||||
|
<path
|
||||||
|
style="fill:url(#linearGradient46)"
|
||||||
|
id="path13"
|
||||||
|
d="M 400.9,202.3 C 400.9,92.3 313.8,5.1 203.7,5.1 93.7,5.2 6.6,92.3 6.6,202.3 c 0,110 87.1,197.2 197.2,197.2 110.1,0 197.1,-87.1 197.1,-197.2 z"
|
||||||
|
class="st0" />
|
||||||
|
<path
|
||||||
|
style="fill:url(#linearGradient48)"
|
||||||
|
class="st0"
|
||||||
|
d="M 400.9,202.3 C 400.9,92.3 313.8,5.1 203.7,5.1 93.7,5.2 6.6,92.3 6.6,202.3 c 0,110 87.1,197.2 197.2,197.2 110.1,0 197.1,-87.1 197.1,-197.2 z"
|
||||||
|
id="path40" /></g><g
|
||||||
|
id="g27">
|
||||||
|
<path
|
||||||
|
style="fill:#515151"
|
||||||
|
id="path17"
|
||||||
|
d="m 223.7,137.8 h 0.2 v 6.9 h 7.9 v -28.5 c 0,-2.1 -0.4,-3.9 -1.2,-5.6 -0.8,-1.7 -1.9,-3.1 -3.4,-4.3 -1.5,-1.2 -3.2,-2.1 -5.3,-2.7 -2.1,-0.6 -4.3,-1 -6.9,-1 -2.3,0 -4.5,0.3 -6.5,1 -2,0.6 -3.7,1.5 -5.2,2.7 -1.5,1.2 -2.6,2.5 -3.5,4.1 -0.9,1.6 -1.3,3.3 -1.4,5.1 h 7.8 c 0.2,-0.9 0.5,-1.7 1,-2.4 0.5,-0.7 1.1,-1.4 1.8,-1.9 0.7,-0.5 1.6,-0.9 2.6,-1.2 1,-0.3 2,-0.4 3.1,-0.4 2.8,0 4.9,0.6 6.5,1.9 1.5,1.2 2.3,3.1 2.3,5.5 v 3.2 l -11.2,0.6 c -5.2,0.3 -9.1,1.5 -11.8,3.6 -2.7,2.1 -4.1,4.9 -4.1,8.6 0,1.9 0.3,3.6 1,5.1 0.7,1.5 1.7,2.8 2.9,3.9 1.2,1.1 2.7,1.9 4.4,2.5 1.7,0.6 3.6,0.9 5.7,0.9 1.4,0 2.8,-0.2 4.1,-0.5 1.3,-0.3 2.6,-0.8 3.7,-1.5 1.1,-0.6 2.1,-1.4 3.1,-2.3 1,-1.2 1.8,-2.2 2.4,-3.3 z m -3.2,-2 c -1,0.8 -2.1,1.5 -3.4,2 -1.3,0.5 -2.8,0.7 -4.3,0.7 -2.4,0 -4.3,-0.5 -5.7,-1.6 -1.4,-1.1 -2.1,-2.5 -2.1,-4.3 0,-1.8 0.7,-3.3 2.2,-4.3 1.4,-1 3.6,-1.6 6.5,-1.8 l 10.1,-0.7 v 3.2 c 0,1.4 -0.3,2.6 -0.8,3.8 -0.8,1.2 -1.5,2.2 -2.5,3 z"
|
||||||
|
class="st1" />
|
||||||
|
<path
|
||||||
|
style="fill:#515151"
|
||||||
|
id="path19"
|
||||||
|
d="m 278.5,228.7 -13.7,-3.4 c -16.7,-4.2 -23.6,-9.7 -23.6,-18.9 0,-11.7 10.9,-19.8 26.7,-19.8 15.8,0 26.5,8 27.7,21 h 17.9 c -0.7,-21.6 -19,-36.7 -45.2,-36.7 -26.8,0 -45.7,15 -45.7,36.5 0,17.5 10.6,28.2 34.1,34 l 16.3,4 c 16.7,4.2 23.9,10.4 23.9,20.6 0,11.8 -11.9,20.4 -28.4,20.4 -17.2,0 -29.8,-8.6 -31.2,-21.7 h -18 c 1.3,22.8 20.2,37.3 47.9,37.3 29.7,0 48.4,-14.7 48.4,-38.3 -0.3,-18.4 -11,-28.7 -37.1,-35 z"
|
||||||
|
class="st1" />
|
||||||
|
<path
|
||||||
|
style="fill:#515151"
|
||||||
|
id="path21"
|
||||||
|
d="m 187.7,144.7 v -28.3 c 0,-2.1 -0.3,-4 -1,-5.6 -0.7,-1.6 -1.5,-3.1 -2.7,-4.3 -1.2,-1.2 -2.6,-2.1 -4.3,-2.8 -1.7,-0.7 -3.5,-1 -5.6,-1 -1.5,0 -2.9,0.2 -4.2,0.6 -1.3,0.4 -2.6,0.9 -3.7,1.6 -1.1,0.7 -2.1,1.6 -3,2.5 -0.9,0.9 -1.6,2.1 -2.1,3.4 h -0.2 c -0.8,-2.6 -2.3,-4.6 -4.3,-6 -2,-1.4 -4.5,-2.1 -7.4,-2.1 -1.3,0 -2.6,0.2 -3.9,0.5 -1.2,0.3 -2.3,0.8 -3.4,1.5 -1,0.7 -1.9,1.4 -2.7,2.4 -0.8,0.9 -1.4,2 -1.9,3.1 h -0.2 v -7 h -7.9 v 41.6 h 7.8 v -25.5 c 0,-1.3 0.7,-2.6 1.1,-3.7 0.4,-1.1 1,-2.1 1.8,-3 0.8,-0.8 1.7,-1.5 2.8,-2 1.1,-0.5 2.3,-0.7 3.5,-0.7 1.2,0 2.3,0.2 3.3,0.6 1,0.4 1.8,0.9 2.5,1.6 0.7,0.7 1.2,1.5 1.6,2.5 0.4,1 0.6,2.1 0.6,3.2 v 27 h 8.2 V 119 c 0,-1.3 0.2,-2.6 0.7,-3.7 0.4,-1.1 1,-2.1 1.8,-2.9 0.8,-0.8 1.7,-1.4 2.7,-1.9 1.1,-0.4 2.2,-0.7 3.5,-0.7 2.6,0 4.6,0.8 6,2.2 1.4,1.5 2.1,3.6 2.1,6.3 v 26.3 z"
|
||||||
|
class="st1" />
|
||||||
|
<path
|
||||||
|
style="fill:#515151"
|
||||||
|
id="path23"
|
||||||
|
d="m 147.4,170.9 c -36.3,0 -59.1,25.3 -59.1,65.6 0,40.3 22.8,65.6 59.1,65.6 36.3,0 59.1,-25.3 59.1,-65.6 -0.1,-40.3 -22.8,-65.6 -59.1,-65.6 z m 0,115 c -24.9,0 -40.5,-19.1 -40.5,-49.4 0,-30.4 15.6,-49.5 40.5,-49.5 24.8,0 40.5,19.1 40.5,49.5 -0.1,30.3 -15.7,49.4 -40.5,49.4 z"
|
||||||
|
class="st1" />
|
||||||
|
<path
|
||||||
|
style="fill:#515151"
|
||||||
|
id="path25"
|
||||||
|
d="m 252.1,113.5 c 1,-1.2 2.1,-2.2 3.5,-2.9 1.4,-0.7 2.9,-1 4.6,-1 1.4,0 2.7,0.2 3.8,0.6 1.1,0.4 2.1,0.9 3,1.6 0.8,0.7 1.5,1.5 2,2.5 0.5,1 0.9,2 1.1,3.1 h 7.9 c -0.2,-2 -0.7,-3.9 -1.6,-5.7 -0.9,-1.8 -2.1,-3.3 -3.6,-4.7 -1.5,-1.3 -3.4,-2.4 -5.5,-3.2 -2.1,-0.8 -4.5,-1.2 -7.2,-1.2 -2.9,0 -5.6,0.5 -8,1.5 -2.4,1 -4.4,2.4 -6.1,4.3 -1.7,1.9 -3,4.1 -3.9,6.7 -0.9,2.6 -1.4,5.5 -1.4,8.8 0,3.3 0.5,6.3 1.4,8.9 0.9,2.6 2.3,4.9 4,6.7 1.7,1.8 3.8,3.2 6.2,4.2 2.4,1 5.1,1.5 8,1.5 2.5,0 4.8,-0.4 6.9,-1 2.1,-0.6 3.9,-1.7 5.5,-2.9 1.5,-1.3 2.8,-2.8 3.8,-4.6 1,-1.8 1.6,-3.8 1.8,-5.9 h -7.9 c -0.5,2.5 -1.6,4.3 -3.3,5.6 -1.7,1.3 -3.9,1.9 -6.6,1.9 -1.7,0 -3.2,-0.3 -4.6,-1 -1.4,-0.6 -2.6,-1.6 -3.5,-2.8 -1,-1.2 -1.7,-2.7 -2.3,-4.5 -0.5,-1.8 -0.8,-3.8 -0.8,-6 0,-2.2 0.3,-4.1 0.8,-5.9 0.3,-1.9 1,-3.4 2,-4.6 z"
|
||||||
|
class="st1" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 7.3 KiB |
BIN
web/img/smart_icon.7cc8510a.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
web/img/sync_icon.ae659b01.png
Normal file
|
After Width: | Height: | Size: 9.3 KiB |
54
web/img/syncthing-logo.e6163faa.svg
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 18.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
|
viewBox="0 0 429 117.3" enable-background="new 0 0 429 117.3" xml:space="preserve">
|
||||||
|
<g>
|
||||||
|
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="58.666" y1="117.332" x2="58.666" y2="-9.094947e-13">
|
||||||
|
<stop offset="0" style="stop-color:#0882C8"/>
|
||||||
|
<stop offset="1" style="stop-color:#26B6DB"/>
|
||||||
|
</linearGradient>
|
||||||
|
<circle fill="url(#SVGID_1_)" cx="58.7" cy="58.7" r="58.7"/>
|
||||||
|
<g>
|
||||||
|
<circle fill="none" stroke="#FFFFFF" stroke-width="6" stroke-miterlimit="10" cx="58.7" cy="58.5" r="43.7"/>
|
||||||
|
<g>
|
||||||
|
<path fill="#FFFFFF" d="M94.7,47.8c4.7,1.6,9.8-0.9,11.4-5.6c1.6-4.7-0.9-9.8-5.6-11.4c-4.7-1.6-9.8,0.9-11.4,5.6
|
||||||
|
C87.5,41.1,90,46.2,94.7,47.8z"/>
|
||||||
|
<line fill="none" stroke="#FFFFFF" stroke-width="6" stroke-miterlimit="10" x1="97.6" y1="39.4" x2="67.5" y2="64.4"/>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<path fill="#FFFFFF" d="M77.6,91c-0.4,4.9,3.2,9.3,8.2,9.8c5,0.4,9.3-3.2,9.8-8.2c0.4-4.9-3.2-9.3-8.2-9.8
|
||||||
|
C82.4,82.4,78,86,77.6,91z"/>
|
||||||
|
<line fill="none" stroke="#FFFFFF" stroke-width="6" stroke-miterlimit="10" x1="86.5" y1="91.8" x2="67.5" y2="64.4"/>
|
||||||
|
</g>
|
||||||
|
<path fill="#FFFFFF" d="M60,69.3c2.7,4.2,8.3,5.4,12.4,2.7c4.2-2.7,5.4-8.3,2.7-12.4c-2.7-4.2-8.3-5.4-12.4-2.7
|
||||||
|
C58.5,59.5,57.3,65.1,60,69.3z"/>
|
||||||
|
<g>
|
||||||
|
<path fill="#FFFFFF" d="M21.2,61.4c-4.3-2.5-9.8-1.1-12.3,3.1c-2.5,4.3-1.1,9.8,3.1,12.3c4.3,2.5,9.8,1.1,12.3-3.1
|
||||||
|
C26.8,69.5,25.4,64,21.2,61.4z"/>
|
||||||
|
<line fill="none" stroke="#FFFFFF" stroke-width="6" stroke-miterlimit="10" x1="16.6" y1="69.1" x2="67.5" y2="64.4"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<path fill="#0891D1" d="M163.8,50.2c-0.6-0.7-6.3-4.1-11.4-4.1c-3.4,0-5.2,1.2-5.2,3.5c0,2.9,3.2,3.7,8.9,5.2
|
||||||
|
c8.2,2.2,13.3,5,13.3,12.9c0,9.7-7.8,13-16,13c-6.2,0-13.1-2-18.2-5.3l4.3-8.6c0.8,0.8,7.5,5,14,5c3.5,0,5.2-1.1,5.2-3.2
|
||||||
|
c0-3.2-4.4-4-10.3-5.8c-7.9-2.4-11.5-5.3-11.5-11.8c0-9,7.2-13.9,15.7-13.9c6.1,0,11.6,2.5,15.4,4.7L163.8,50.2z"/>
|
||||||
|
<path fill="#0891D1" d="M175,85.1c1.7,0.5,3.3,0.8,4.4,0.8c2,0,3.3-1.5,4.2-5.5l-11.9-31.5h9.8l7.4,23.3l6.3-23.3h8.9l-12.1,36.6
|
||||||
|
c-1.7,5.3-6.2,8.7-11.8,8.8c-1.7,0-3.5-0.2-5.3-0.9V85.1z"/>
|
||||||
|
<path fill="#0891D1" d="M239.3,80.3h-9.6V62.6c0-4.1-1.7-5.9-4.3-5.9c-2.6,0-5.8,2.3-7,5.6v18.1h-9.6V48.8h8.6v5.3
|
||||||
|
c2.3-3.7,6.8-5.9,12.2-5.9c8.2,0,9.5,6.7,9.5,11.9V80.3z"/>
|
||||||
|
<path fill="#0891D1" d="M261.6,48.2c7.2,0,12.3,3.4,14.8,8.3l-9.4,2.8c-1.2-1.9-3.1-3-5.5-3c-4,0-7,3.2-7,8.2c0,5,3.1,8.3,7,8.3
|
||||||
|
c2.4,0,4.6-1.3,5.5-3.1l9.4,2.9c-2.3,4.9-7.6,8.3-14.8,8.3c-10.6,0-16.9-7.7-16.9-16.4S250.9,48.2,261.6,48.2z"/>
|
||||||
|
<path fill="#0891D1" d="M302.1,78.7c-2.6,1.1-6.2,2.3-9.7,2.3c-4.7,0-8.8-2.3-8.8-8.4V56.1h-4v-7.3h4v-10h9.6v10h6.4v7.3h-6.4v13.1
|
||||||
|
c0,2.1,1.2,2.9,2.8,2.9c1.4,0,3-0.6,4.2-1.1L302.1,78.7z"/>
|
||||||
|
<path fill="#0891D1" d="M337.2,80.3h-9.6V62.6c0-4.1-1.8-5.9-4.6-5.9c-2.3,0-5.5,2.2-6.7,5.6v18.1h-9.6V36.5h9.6v17.6
|
||||||
|
c2.3-3.7,6.3-5.9,10.9-5.9c8.5,0,9.9,6.5,9.9,11.9V80.3z"/>
|
||||||
|
<path fill="#0891D1" d="M343.4,45.2v-8.7h9.6v8.7H343.4z M343.4,80.3V48.8h9.6v31.5H343.4z"/>
|
||||||
|
<path fill="#0891D1" d="M389.9,80.3h-9.6V62.6c0-4.1-1.7-5.9-4.3-5.9c-2.6,0-5.8,2.3-7,5.6v18.1h-9.6V48.8h8.6v5.3
|
||||||
|
c2.3-3.7,6.8-5.9,12.2-5.9c8.2,0,9.5,6.7,9.5,11.9V80.3z"/>
|
||||||
|
<path fill="#0891D1" d="M395.5,64.6c0-9.2,6-16.3,14.6-16.3c4.7,0,8.4,2.2,10.6,5.8v-5.2h8.3v29.3c0,9.6-7.5,15.5-18.2,15.5
|
||||||
|
c-6.8,0-11.5-2.3-15-6.3l5.1-5.2c2.3,2.6,6,4.3,9.9,4.3c4.6,0,8.6-2.4,8.6-8.3v-3.1c-1.9,3.5-5.9,5.3-10,5.3
|
||||||
|
C401.1,80.5,395.5,73.3,395.5,64.6z M419.4,68.5v-6.6c-1.3-3.3-4.2-5.5-7.1-5.5c-4.1,0-7,4-7,8.4c0,4.6,3.2,8,7.5,8
|
||||||
|
C415.7,72.8,418.1,71,419.4,68.5z"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 3.6 KiB |
1
web/img/syncthing.257e4f51.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 66 65" fill="#fff" fill-rule="evenodd" stroke="#000" stroke-linecap="round" stroke-linejoin="round"><style><![CDATA[.B{stroke:none}.C{fill-rule:nonzero}.D{stroke:#fff}.E{stroke-width:3.271}]]></style><use xlink:href="#B" x=".5" y=".5"/><defs><linearGradient id="A" x1="49.97%" y1="99.94%" x2="49.97%" y2="0.00%"><stop offset="0%" stop-color="#0882c8"/><stop offset="100%" stop-color="#26b6db"/></linearGradient></defs><symbol id="B" overflow="visible"><path d="M0 32C0 14.272 14.272 0 32 0s32 14.272 32 32-14.272 32-32 32S0 49.728 0 32z" fill="url(#A)" class="B C"/><path d="M8.177 31.891C8.177 18.693 18.802 8.068 32 8.068s23.823 10.625 23.823 23.823S45.198 55.714 32 55.714 8.177 45.089 8.177 31.891z" fill="none" class="D E"/><path d="M51.625 26.058c2.562.872 5.342-.491 6.215-3.053s-.491-5.342-3.053-6.215-5.342.491-6.215 3.053.491 5.342 3.053 6.215z" class="B C"/><path d="M53.206 21.479L36.797 35.108" fill="none" class="D E"/><path d="M42.304 49.608c-.218 2.671 1.745 5.07 4.47 5.342 2.726.218 5.07-1.744 5.343-4.47.218-2.671-1.745-5.07-4.47-5.343-2.726-.218-5.124 1.745-5.342 4.47z" class="B C"/><path d="M47.155 50.044L36.797 35.107" fill="none" class="D E"/><path d="M32.708 37.779c1.472 2.29 4.525 2.944 6.76 1.472 2.29-1.472 2.944-4.525 1.472-6.76-1.472-2.29-4.525-2.944-6.76-1.472-2.29 1.417-2.944 4.47-1.472 6.76zm-21.152-4.307c-2.344-1.363-5.342-.6-6.705 1.69-1.363 2.344-.6 5.342 1.69 6.705 2.344 1.363 5.342.6 6.705-1.69s.6-5.288-1.69-6.705z" class="B C"/><path d="M9.049 37.669l27.748-2.562" fill="none" class="D E"/></symbol></svg>
|
||||||
|
After Width: | Height: | Size: 1.6 KiB |
1
web/img/windows.d98029c3.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
After Width: | Height: | Size: 486 B |
1
web/img/wuji.b6d17cf2.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?><svg width="24" height="24" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg"><rect width="48" height="48" fill="white" fill-opacity="0.01"/><path d="M24 44C35.0457 44 44 35.0457 44 24C44 12.9543 35.0457 4 24 4C12.9543 4 4 12.9543 4 24C4 35.0457 12.9543 44 24 44Z" stroke="#333" stroke-width="4" stroke-linejoin="round"/><path d="M24 44C31.732 44 38 37.732 38 30C38 22.268 31.732 16 24 16C16.268 16 10 22.268 10 30C10 37.732 16.268 44 24 44Z" stroke="#333" stroke-width="4" stroke-linejoin="round"/><path d="M24 44C28.4183 44 32 40.4183 32 36C32 31.5817 28.4183 28 24 28C19.5817 28 16 31.5817 16 36C16 40.4183 19.5817 44 24 44Z" fill="none" stroke="#333" stroke-width="4" stroke-linejoin="round"/></svg>
|
||||||
|
After Width: | Height: | Size: 758 B |
@@ -11,18 +11,14 @@
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<link rel="apple-touch-icon" sizes="180x180" href="/ui/img/icon/apple-touch-icon.png">
|
<link rel="apple-touch-icon" sizes="180x180" href="/ui/img/icon/apple-touch-icon.png">
|
||||||
<link rel="icon" type="image/png" sizes="32x32" href="/ui/img/icon/favicon-32x32.png">
|
|
||||||
<link rel="icon" type="image/png" sizes="16x16" href="/ui/img/icon/favicon-16x16.png">
|
|
||||||
<link rel="manifest" href="/ui/site.webmanifest">
|
<link rel="manifest" href="/ui/site.webmanifest">
|
||||||
<link rel="mask-icon" href="/ui/img/icon/safari-pinned-tab.svg" color="#5bbad5">
|
|
||||||
<meta name="msapplication-TileColor" content="#da532c">
|
<meta name="msapplication-TileColor" content="#da532c">
|
||||||
<meta name="theme-color" content="#ffffff">
|
<meta name="theme-color" content="#ffffff">
|
||||||
<link rel="icon" href="/ui/favicon.ico">
|
<link rel="icon" href="/ui/favicon.svg" type="image/svg+xml">
|
||||||
<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/@mdi/font@6.2.95/css/materialdesignicons.min.css">
|
<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/@mdi/font@6.2.95/css/materialdesignicons.min.css">
|
||||||
<title>
|
<title>
|
||||||
CasaOS
|
CasaOS
|
||||||
</title>
|
</title>
|
||||||
|
|
||||||
<link href="/ui/js/0.js" rel="prefetch"><link href="/ui/js/1.js" rel="prefetch"><link href="/ui/js/2.js" rel="prefetch"><link href="/ui/js/3.js" rel="prefetch"><link href="/ui/js/4.js" rel="prefetch"><link href="/ui/js/app.js" rel="preload" as="script"><link href="/ui/js/chunk-vendors.js" rel="preload" as="script"></head>
|
<link href="/ui/js/0.js" rel="prefetch"><link href="/ui/js/1.js" rel="prefetch"><link href="/ui/js/2.js" rel="prefetch"><link href="/ui/js/3.js" rel="prefetch"><link href="/ui/js/4.js" rel="prefetch"><link href="/ui/js/app.js" rel="preload" as="script"><link href="/ui/js/chunk-vendors.js" rel="preload" as="script"></head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
|||||||
12
web/js/0.js
@@ -195,14 +195,14 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) *
|
|||||||
|
|
||||||
/***/ }),
|
/***/ }),
|
||||||
|
|
||||||
/***/ "./src/assets/img/user.svg":
|
/***/ "./src/assets/img/Account.png":
|
||||||
/*!*********************************!*\
|
/*!************************************!*\
|
||||||
!*** ./src/assets/img/user.svg ***!
|
!*** ./src/assets/img/Account.png ***!
|
||||||
\*********************************/
|
\************************************/
|
||||||
/*! no static exports found */
|
/*! no static exports found */
|
||||||
/***/ (function(module, exports, __webpack_require__) {
|
/***/ (function(module, exports, __webpack_require__) {
|
||||||
|
|
||||||
eval("module.exports = __webpack_require__.p + \"img/user.89095c02.svg\";\n\n//# sourceURL=webpack:///./src/assets/img/user.svg?");
|
eval("module.exports = __webpack_require__.p + \"img/Account.1bc4a418.png\";\n\n//# sourceURL=webpack:///./src/assets/img/Account.png?");
|
||||||
|
|
||||||
/***/ }),
|
/***/ }),
|
||||||
|
|
||||||
@@ -214,7 +214,7 @@ eval("module.exports = __webpack_require__.p + \"img/user.89095c02.svg\";\n\n//#
|
|||||||
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _Users_liangjianli_go_CasaOSNew_CasaOS_UI_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@babel/runtime/helpers/esm/objectSpread2 */ \"./node_modules/@babel/runtime/helpers/esm/objectSpread2.js\");\n/* harmony import */ var vee_validate_dist_rules__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! vee-validate/dist/rules */ \"./node_modules/vee-validate/dist/rules.js\");\n/* harmony import */ var vee_validate__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! vee-validate */ \"./node_modules/vee-validate/dist/vee-validate.esm.js\");\n\n\n\nObject(vee_validate__WEBPACK_IMPORTED_MODULE_2__[\"extend\"])(\"required\", Object(_Users_liangjianli_go_CasaOSNew_CasaOS_UI_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__[\"default\"])(Object(_Users_liangjianli_go_CasaOSNew_CasaOS_UI_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__[\"default\"])({}, vee_validate_dist_rules__WEBPACK_IMPORTED_MODULE_1__[\"required\"]), {}, {\n message: \"This field is required\"\n}));\nObject(vee_validate__WEBPACK_IMPORTED_MODULE_2__[\"extend\"])(\"email\", Object(_Users_liangjianli_go_CasaOSNew_CasaOS_UI_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__[\"default\"])(Object(_Users_liangjianli_go_CasaOSNew_CasaOS_UI_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__[\"default\"])({}, vee_validate_dist_rules__WEBPACK_IMPORTED_MODULE_1__[\"email\"]), {}, {\n message: \"This field must be a valid email\"\n}));\nObject(vee_validate__WEBPACK_IMPORTED_MODULE_2__[\"extend\"])(\"confirmed\", Object(_Users_liangjianli_go_CasaOSNew_CasaOS_UI_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__[\"default\"])(Object(_Users_liangjianli_go_CasaOSNew_CasaOS_UI_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__[\"default\"])({}, vee_validate_dist_rules__WEBPACK_IMPORTED_MODULE_1__[\"confirmed\"]), {}, {\n message: \"This field confirmation does not match\"\n}));\nObject(vee_validate__WEBPACK_IMPORTED_MODULE_2__[\"extend\"])(\"length\", Object(_Users_liangjianli_go_CasaOSNew_CasaOS_UI_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__[\"default\"])(Object(_Users_liangjianli_go_CasaOSNew_CasaOS_UI_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__[\"default\"])({}, vee_validate_dist_rules__WEBPACK_IMPORTED_MODULE_1__[\"length\"]), {}, {\n message: \"This field must have 2 options\"\n}));\nObject(vee_validate__WEBPACK_IMPORTED_MODULE_2__[\"extend\"])(\"min\", Object(_Users_liangjianli_go_CasaOSNew_CasaOS_UI_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__[\"default\"])(Object(_Users_liangjianli_go_CasaOSNew_CasaOS_UI_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__[\"default\"])({}, vee_validate_dist_rules__WEBPACK_IMPORTED_MODULE_1__[\"min\"]), {}, {\n message: \"This field must have more than {length} characters\"\n}));\n\n//# sourceURL=webpack:///./src/plugins/vee-validate.js?");
|
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _Users_jerry_Desktop_CasaOS_CasaOS_UI_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@babel/runtime/helpers/esm/objectSpread2 */ \"./node_modules/@babel/runtime/helpers/esm/objectSpread2.js\");\n/* harmony import */ var vee_validate_dist_rules__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! vee-validate/dist/rules */ \"./node_modules/vee-validate/dist/rules.js\");\n/* harmony import */ var vee_validate__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! vee-validate */ \"./node_modules/vee-validate/dist/vee-validate.esm.js\");\n\n\n\nObject(vee_validate__WEBPACK_IMPORTED_MODULE_2__[\"extend\"])(\"required\", Object(_Users_jerry_Desktop_CasaOS_CasaOS_UI_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__[\"default\"])(Object(_Users_jerry_Desktop_CasaOS_CasaOS_UI_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__[\"default\"])({}, vee_validate_dist_rules__WEBPACK_IMPORTED_MODULE_1__[\"required\"]), {}, {\n message: \"This field is required\"\n}));\nObject(vee_validate__WEBPACK_IMPORTED_MODULE_2__[\"extend\"])(\"email\", Object(_Users_jerry_Desktop_CasaOS_CasaOS_UI_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__[\"default\"])(Object(_Users_jerry_Desktop_CasaOS_CasaOS_UI_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__[\"default\"])({}, vee_validate_dist_rules__WEBPACK_IMPORTED_MODULE_1__[\"email\"]), {}, {\n message: \"This field must be a valid email\"\n}));\nObject(vee_validate__WEBPACK_IMPORTED_MODULE_2__[\"extend\"])(\"confirmed\", Object(_Users_jerry_Desktop_CasaOS_CasaOS_UI_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__[\"default\"])(Object(_Users_jerry_Desktop_CasaOS_CasaOS_UI_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__[\"default\"])({}, vee_validate_dist_rules__WEBPACK_IMPORTED_MODULE_1__[\"confirmed\"]), {}, {\n message: \"This field confirmation does not match\"\n}));\nObject(vee_validate__WEBPACK_IMPORTED_MODULE_2__[\"extend\"])(\"length\", Object(_Users_jerry_Desktop_CasaOS_CasaOS_UI_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__[\"default\"])(Object(_Users_jerry_Desktop_CasaOS_CasaOS_UI_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__[\"default\"])({}, vee_validate_dist_rules__WEBPACK_IMPORTED_MODULE_1__[\"length\"]), {}, {\n message: \"This field must have 2 options\"\n}));\nObject(vee_validate__WEBPACK_IMPORTED_MODULE_2__[\"extend\"])(\"min\", Object(_Users_jerry_Desktop_CasaOS_CasaOS_UI_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__[\"default\"])(Object(_Users_jerry_Desktop_CasaOS_CasaOS_UI_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__[\"default\"])({}, vee_validate_dist_rules__WEBPACK_IMPORTED_MODULE_1__[\"min\"]), {}, {\n message: \"This field must have more than {length} characters\"\n}));\n\n//# sourceURL=webpack:///./src/plugins/vee-validate.js?");
|
||||||
|
|
||||||
/***/ })
|
/***/ })
|
||||||
|
|
||||||
|
|||||||
22
web/js/1.js
1381
web/js/2.js
10
web/js/3.js
10
web/js/4.js
@@ -2,5 +2,5 @@ package web
|
|||||||
|
|
||||||
import "embed"
|
import "embed"
|
||||||
|
|
||||||
//go:embed index.html favicon.ico img js browserconfig.xml site.webmanifest
|
//go:embed index.html favicon.svg img js browserconfig.xml site.webmanifest
|
||||||
var Static embed.FS
|
var Static embed.FS
|
||||||
|
|||||||