* fix bug

* updata UI

* 0.3.2

### Added

- [Files] Files can now be selected multiple files and downloaded, deleted, moved, etc.
- [Apps] Support to modify the application opening address.([#204](https://github.com/IceWhaleTech/CasaOS/issues/204))

### Changed

- [Apps] Hide the display of non-essential environment variables in the application.
- [System] Network, disk, cpu, memory, etc. information is modified to be pushed via socket.
- [System] Optimize opening speed.([#214](https://github.com/IceWhaleTech/CasaOS/issues/214))
### Fixed

- [System] Fixed the problem that sync data cannot submit the device ID ([#68](https://github.com/IceWhaleTech/CasaOS/issues/68))
- [Files] Fixed the code editor center alignment display problem.([#210](https://github.com/IceWhaleTech/CasaOS/issues/210))
- [Files] Fixed the problem of wrong name when downloading files.([#240](https://github.com/IceWhaleTech/CasaOS/issues/240))
- [System] Fixed the network display as a negative number problem.([#224](https://github.com/IceWhaleTech/CasaOS/issues/224))

* Modify log help class

* Fix some bugs in 0.3.2

* Solve the operation file queue problem

* Exclude web folders

* update UI

* add cancel file operate

* Update UI

* Merge sockets to transfer data

* Conflict Resolution
This commit is contained in:
link 2022-06-10 13:33:53 +08:00 committed by GitHub
parent c7b7a30210
commit 9d47874ae3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 496 additions and 315 deletions

11
main.go
View File

@ -102,11 +102,12 @@ func main() {
} }
err = cron2.AddFunc("0/3 * * * * *", func() { err = cron2.AddFunc("0/3 * * * * *", func() {
if service.ClientCount > 0 { if service.ClientCount > 0 {
route.SendNetINfoBySocket() // route.SendNetINfoBySocket()
route.SendCPUBySocket() // route.SendCPUBySocket()
route.SendMemBySocket() // route.SendMemBySocket()
route.SendDiskBySocket() // route.SendDiskBySocket()
route.SendUSBBySocket() // route.SendUSBBySocket()
route.SendAllHardwareStatusBySocket()
} }
}) })
if err != nil { if err != nil {

View File

@ -2,7 +2,7 @@
* @Author: LinkLeong link@icewhale.com * @Author: LinkLeong link@icewhale.com
* @Date: 2022-05-20 16:27:12 * @Date: 2022-05-20 16:27:12
* @LastEditors: LinkLeong * @LastEditors: LinkLeong
* @LastEditTime: 2022-06-08 15:40:33 * @LastEditTime: 2022-06-09 18:18:46
* @FilePath: /CasaOS/model/file.go * @FilePath: /CasaOS/model/file.go
* @Description: * @Description:
* @Website: https://www.casaos.io * @Website: https://www.casaos.io
@ -16,6 +16,8 @@ type FileOperate struct {
TotalSize int64 `json:"total_size"` TotalSize int64 `json:"total_size"`
ProcessedSize int64 `json:"processed_size"` ProcessedSize int64 `json:"processed_size"`
To string `json:"to" binding:"required"` To string `json:"to" binding:"required"`
Style string `json:"style"`
Finished bool `json:"finished"`
} }
type FileItem struct { type FileItem struct {

View File

@ -186,7 +186,7 @@ func ReadFullFile(path string) []byte {
} }
// File copies a single file from src to dst // File copies a single file from src to dst
func CopyFile(src, dst string) error { func CopyFile(src, dst, style string) error {
var err error var err error
var srcfd *os.File var srcfd *os.File
var dstfd *os.File var dstfd *os.File
@ -197,20 +197,13 @@ func CopyFile(src, dst string) error {
if !strings.HasSuffix(dst, "/") { if !strings.HasSuffix(dst, "/") {
dst += "/" dst += "/"
} }
dstPath := dst
dst += lastPath dst += lastPath
for i := 0; Exists(dst); i++ { if Exists(dst) {
name := strings.Split(lastPath, ".") if style == "skip" {
nameIndex := 0 return nil
if len(name) > 2 { } else {
nameIndex = len(name) - 2 os.Remove(dst)
} }
name[nameIndex] = name[nameIndex] + "(Copy)"
dst = dstPath
for _, v := range name {
dst += v + "."
}
dst = strings.TrimSuffix(dst, ".")
} }
if srcfd, err = os.Open(src); err != nil { if srcfd, err = os.Open(src); err != nil {
@ -244,7 +237,7 @@ func GetNoDuplicateFileName(fullPath string) string {
} }
// Dir copies a whole directory recursively // Dir copies a whole directory recursively
func CopyDir(src string, dst string) error { func CopyDir(src string, dst string, style string) error {
var err error var err error
var fds []os.FileInfo var fds []os.FileInfo
var srcinfo os.FileInfo var srcinfo os.FileInfo
@ -253,16 +246,23 @@ func CopyDir(src string, dst string) error {
return err return err
} }
if !srcinfo.IsDir() { if !srcinfo.IsDir() {
if err = CopyFile(src, dst); err != nil { if err = CopyFile(src, dst, style); err != nil {
fmt.Println(err) fmt.Println(err)
} }
return nil return nil
} }
dstPath := dst //dstPath := dst
lastPath := src[strings.LastIndex(src, "/")+1:] lastPath := src[strings.LastIndex(src, "/")+1:]
dst += "/" + lastPath dst += "/" + lastPath
for i := 0; Exists(dst); i++ { // for i := 0; Exists(dst); i++ {
dst = dstPath + "/" + lastPath + strconv.Itoa(i+1) // dst = dstPath + "/" + lastPath + strconv.Itoa(i+1)
// }
if Exists(dst) {
if style == "skip" {
return nil
} else {
os.Remove(dst)
}
} }
if err = os.MkdirAll(dst, srcinfo.Mode()); err != nil { if err = os.MkdirAll(dst, srcinfo.Mode()); err != nil {
return err return err
@ -275,11 +275,11 @@ func CopyDir(src string, dst string) error {
dstfp := dst //path.Join(dst, fd.Name()) dstfp := dst //path.Join(dst, fd.Name())
if fd.IsDir() { if fd.IsDir() {
if err = CopyDir(srcfp, dstfp); err != nil { if err = CopyDir(srcfp, dstfp, style); err != nil {
fmt.Println(err) fmt.Println(err)
} }
} else { } else {
if err = CopyFile(srcfp, dstfp); err != nil { if err = CopyFile(srcfp, dstfp, style); err != nil {
fmt.Println(err) fmt.Println(err)
} }
} }

View File

@ -40,6 +40,7 @@ const (
FILE_READ_ERROR = 60002 FILE_READ_ERROR = 60002
FILE_DELETE_ERROR = 60003 FILE_DELETE_ERROR = 60003
DIR_NOT_EXISTS = 60004 DIR_NOT_EXISTS = 60004
SOURCE_DES_SAME = 60005
//shortcuts //shortcuts
SHORTCUTS_URL_ERROR = 70001 SHORTCUTS_URL_ERROR = 70001
@ -88,6 +89,7 @@ var MsgFlags = map[int]string{
FORMAT_ERROR: "Formatting failed, please check if the directory is occupied", FORMAT_ERROR: "Formatting failed, please check if the directory is occupied",
// //
SOURCE_DES_SAME: "Source and destination cannot be the same.",
FILE_DOES_NOT_EXIST: "File does not exist", FILE_DOES_NOT_EXIST: "File does not exist",
DIR_NOT_EXISTS: "Directory does not exist", DIR_NOT_EXISTS: "Directory does not exist",

View File

@ -2,7 +2,7 @@
* @Author: LinkLeong link@icewhale.com * @Author: LinkLeong link@icewhale.com
* @Date: 2022-05-27 15:55:36 * @Date: 2022-05-27 15:55:36
* @LastEditors: LinkLeong * @LastEditors: LinkLeong
* @LastEditTime: 2022-05-27 18:57:40 * @LastEditTime: 2022-06-10 12:17:59
* @FilePath: /CasaOS/route/periodical.go * @FilePath: /CasaOS/route/periodical.go
* @Description: * @Description:
* @Website: https://www.casaos.io * @Website: https://www.casaos.io
@ -153,3 +153,133 @@ func SendUSBBySocket() {
} }
service.MyService.Notify().SendUSBInfoBySocket(usb) service.MyService.Notify().SendUSBInfoBySocket(usb)
} }
func SendAllHardwareStatusBySocket() {
netList := service.MyService.System().GetNetInfo()
newNet := []model.IOCountersStat{}
nets := service.MyService.System().GetNet(true)
for _, n := range netList {
for _, netCardName := range nets {
if n.Name == netCardName {
item := *(*model.IOCountersStat)(unsafe.Pointer(&n))
item.State = strings.TrimSpace(service.MyService.ZiMa().GetNetState(n.Name))
item.Time = time.Now().Unix()
newNet = append(newNet, item)
break
}
}
}
cpu := service.MyService.System().GetCpuPercent()
num := service.MyService.System().GetCpuCoreNum()
cpuData := make(map[string]interface{})
cpuData["percent"] = cpu
cpuData["num"] = num
list := service.MyService.Disk().LSBLK(true)
summary := model.Summary{}
healthy := true
findSystem := 0
for i := 0; i < len(list); i++ {
if len(list[i].Children) > 0 && findSystem == 0 {
for j := 0; j < len(list[i].Children); j++ {
if len(list[i].Children[j].Children) > 0 {
for _, v := range list[i].Children[j].Children {
if v.MountPoint == "/" {
s, _ := strconv.ParseUint(v.FSSize, 10, 64)
a, _ := strconv.ParseUint(v.FSAvail, 10, 64)
u, _ := strconv.ParseUint(v.FSUsed, 10, 64)
summary.Size += s
summary.Avail += a
summary.Used += u
findSystem = 1
break
}
}
} else {
if list[i].Children[j].MountPoint == "/" {
s, _ := strconv.ParseUint(list[i].Children[j].FSSize, 10, 64)
a, _ := strconv.ParseUint(list[i].Children[j].FSAvail, 10, 64)
u, _ := strconv.ParseUint(list[i].Children[j].FSUsed, 10, 64)
summary.Size += s
summary.Avail += a
summary.Used += u
findSystem = 1
break
}
}
}
}
if findSystem == 1 {
findSystem += 1
continue
}
if list[i].Tran == "sata" || list[i].Tran == "nvme" || list[i].Tran == "spi" || list[i].Tran == "sas" {
temp := service.MyService.Disk().SmartCTL(list[i].Path)
if reflect.DeepEqual(temp, model.SmartctlA{}) {
continue
}
//list[i].Temperature = temp.Temperature.Current
if !temp.SmartStatus.Passed {
healthy = false
}
if len(list[i].Children) > 0 {
for _, v := range list[i].Children {
s, _ := strconv.ParseUint(v.FSSize, 10, 64)
a, _ := strconv.ParseUint(v.FSAvail, 10, 64)
u, _ := strconv.ParseUint(v.FSUsed, 10, 64)
summary.Size += s
summary.Avail += a
summary.Used += u
}
}
}
}
summary.Health = healthy
usbList := service.MyService.Disk().LSBLK(false)
usb := []model.DriveUSB{}
for _, v := range usbList {
if v.Tran == "usb" {
temp := model.DriveUSB{}
temp.Model = v.Model
temp.Name = v.Name
temp.Size = v.Size
mountTemp := true
if len(v.Children) == 0 {
mountTemp = false
}
for _, child := range v.Children {
if len(child.MountPoint) > 0 {
avail, _ := strconv.ParseUint(child.FSAvail, 10, 64)
temp.Avail += avail
used, _ := strconv.ParseUint(child.FSUsed, 10, 64)
temp.Used += used
} else {
mountTemp = false
}
}
temp.Mount = mountTemp
usb = append(usb, temp)
}
}
memInfo := service.MyService.System().GetMemInfo()
memData := make(map[string]interface{})
memData["total"] = memInfo.Total
memData["available"] = memInfo.Available
memData["used"] = memInfo.Used
memData["free"] = memInfo.Free
memData["usedPercent"] = memInfo.UsedPercent
service.MyService.Notify().SendAllHardwareStatusBySocket(summary, usb, memData, cpuData, newNet)
}

View File

@ -2,7 +2,7 @@
* @Author: LinkLeong link@icewhale.com * @Author: LinkLeong link@icewhale.com
* @Date: 2022-05-23 17:18:56 * @Date: 2022-05-23 17:18:56
* @LastEditors: LinkLeong * @LastEditors: LinkLeong
* @LastEditTime: 2022-06-08 16:31:24 * @LastEditTime: 2022-06-09 21:48:10
* @FilePath: /CasaOS/route/socket.go * @FilePath: /CasaOS/route/socket.go
* @Description: * @Description:
* @Website: https://www.casaos.io * @Website: https://www.casaos.io
@ -49,7 +49,7 @@ func SocketInit(msg chan notify.Message) {
go func(msg chan notify.Message) { go func(msg chan notify.Message) {
for v := range msg { for v := range msg {
f.Broadcast("", v.Path, &v.Msg) f.Broadcast("", v.Path, &v.Msg)
time.Sleep(time.Millisecond * 300) time.Sleep(time.Millisecond * 100)
} }
}(msg) }(msg)

View File

@ -495,6 +495,11 @@ func PostOperateFileOrDir(c *gin.Context) {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)}) c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
return return
} }
if list.To == list.Item[0].From[:strings.LastIndex(list.Item[0].From, "/")] {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SOURCE_DES_SAME, Message: oasis_err2.GetMsg(oasis_err2.SOURCE_DES_SAME)})
return
}
var total int64 = 0 var total int64 = 0
for i := 0; i < len(list.Item); i++ { for i := 0; i < len(list.Item); i++ {

View File

@ -2,7 +2,7 @@
* @Author: LinkLeong link@icewhale.com * @Author: LinkLeong link@icewhale.com
* @Date: 2021-12-20 14:15:46 * @Date: 2021-12-20 14:15:46
* @LastEditors: LinkLeong * @LastEditors: LinkLeong
* @LastEditTime: 2022-06-08 15:46:36 * @LastEditTime: 2022-06-09 18:15:54
* @FilePath: /CasaOS/service/file.go * @FilePath: /CasaOS/service/file.go
* @Description: * @Description:
* @Website: https://www.casaos.io * @Website: https://www.casaos.io
@ -21,6 +21,8 @@ import (
"github.com/IceWhaleTech/CasaOS/model" "github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/pkg/utils/file" "github.com/IceWhaleTech/CasaOS/pkg/utils/file"
"github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
"go.uber.org/zap"
) )
var FileQueue sync.Map var FileQueue sync.Map
@ -87,26 +89,37 @@ func FileOperate(k string) {
if temp.ProcessedSize > 0 { if temp.ProcessedSize > 0 {
return return
} }
for _, v := range temp.Item { for i := 0; i < len(temp.Item); i++ {
v := temp.Item[i]
if temp.Type == "move" { if temp.Type == "move" {
lastPath := v.From[strings.LastIndex(v.From, "/")+1:] lastPath := v.From[strings.LastIndex(v.From, "/")+1:]
if !file.CheckNotExist(temp.To + "/" + lastPath) { if !file.CheckNotExist(temp.To + "/" + lastPath) {
continue if temp.Style == "skip" {
temp.Item[i].Finished = true
continue
} else {
os.Remove(temp.To + "/" + lastPath)
}
} }
err := os.Rename(v.From, temp.To+"/"+lastPath) err := os.Rename(v.From, temp.To+"/"+lastPath)
if err != nil { if err != nil {
loger.Debug("file move error", zap.Any("err", err))
continue continue
} }
} else if temp.Type == "copy" { } else if temp.Type == "copy" {
err := file.CopyDir(v.From, temp.To) err := file.CopyDir(v.From, temp.To, temp.Style)
if err != nil { if err != nil {
continue continue
} }
} else { } else {
continue continue
} }
}
}
temp.Finished = true
FileQueue.Store(k, temp)
} }
func ExecOpFile() { func ExecOpFile() {

View File

@ -37,12 +37,39 @@ type NotifyServer interface {
SendPersonStatusBySocket(status notify.Person) SendPersonStatusBySocket(status notify.Person)
SendFileOperateNotify(nowSend bool) SendFileOperateNotify(nowSend bool)
SendInstallAppBySocket(app notify.Application) SendInstallAppBySocket(app notify.Application)
SendAllHardwareStatusBySocket(disk model2.Summary, list []model2.DriveUSB, mem map[string]interface{}, cpu map[string]interface{}, netList []model2.IOCountersStat)
} }
type notifyServer struct { type notifyServer struct {
db *gorm.DB db *gorm.DB
} }
func (i *notifyServer) SendAllHardwareStatusBySocket(disk model2.Summary, list []model2.DriveUSB, mem map[string]interface{}, cpu map[string]interface{}, netList []model2.IOCountersStat) {
body := make(map[string]interface{})
body["sys_disk"] = disk
body["sys_usb"] = list
body["sys_mem"] = mem
body["sys_cpu"] = cpu
body["sys_net"] = netList
msg := gosf.Message{}
msg.Body = body
msg.Success = true
msg.Text = "sys_hardware_status"
notify := notify.Message{}
notify.Path = "sys_hardware_status"
notify.Msg = msg
NotifyMsg <- notify
}
// Send periodic broadcast messages // Send periodic broadcast messages
func (i *notifyServer) SendFileOperateNotify(nowSend bool) { func (i *notifyServer) SendFileOperateNotify(nowSend bool) {
@ -94,7 +121,7 @@ func (i *notifyServer) SendFileOperateNotify(nowSend bool) {
task.Status = "PROCESSING" task.Status = "PROCESSING"
} }
if temp.ProcessedSize >= temp.TotalSize { if temp.Finished || temp.ProcessedSize >= temp.TotalSize {
task.Finished = true task.Finished = true
task.Status = "FINISHED" task.Status = "FINISHED"
@ -160,7 +187,8 @@ func (i *notifyServer) SendFileOperateNotify(nowSend bool) {
} else { } else {
task.Status = "PROCESSING" task.Status = "PROCESSING"
} }
if temp.ProcessedSize >= temp.TotalSize { if temp.Finished || temp.ProcessedSize >= temp.TotalSize {
task.Finished = true task.Finished = true
task.Status = "FINISHED" task.Status = "FINISHED"
FileQueue.Delete(v) FileQueue.Delete(v)

View File

@ -20,7 +20,7 @@
<title> <title>
CasaOS CasaOS
</title> </title>
<link href="/ui/css/10.32be8789.css" rel="prefetch"><link href="/ui/css/11.dc77452d.css" rel="prefetch"><link href="/ui/css/16.1f93b660.css" rel="prefetch"><link href="/ui/css/17.046fd3d8.css" rel="prefetch"><link href="/ui/css/8.eb842258.css" rel="prefetch"><link href="/ui/css/9.e1b97a16.css" rel="prefetch"><link href="/ui/js/0.js" rel="prefetch"><link href="/ui/js/1.js" rel="prefetch"><link href="/ui/js/10.js" rel="prefetch"><link href="/ui/js/11.js" rel="prefetch"><link href="/ui/js/12.js" rel="prefetch"><link href="/ui/js/13.js" rel="prefetch"><link href="/ui/js/14.js" rel="prefetch"><link href="/ui/js/15.js" rel="prefetch"><link href="/ui/js/16.js" rel="prefetch"><link href="/ui/js/17.js" rel="prefetch"><link href="/ui/js/18.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/5.js" rel="prefetch"><link href="/ui/js/6.js" rel="prefetch"><link href="/ui/js/7.js" rel="prefetch"><link href="/ui/js/8.js" rel="prefetch"><link href="/ui/js/9.js" rel="prefetch"><link href="/ui/css/app.87502768.css" rel="preload" as="style"><link href="/ui/css/vendors~app.a048753d.css" rel="preload" as="style"><link href="/ui/js/app.js" rel="preload" as="script"><link href="/ui/js/vendors~app.js" rel="preload" as="script"><link href="/ui/css/vendors~app.a048753d.css" rel="stylesheet"><link href="/ui/css/app.87502768.css" rel="stylesheet"></head> <link href="/ui/css/10.32be8789.css" rel="prefetch"><link href="/ui/css/11.dc77452d.css" rel="prefetch"><link href="/ui/css/16.1f93b660.css" rel="prefetch"><link href="/ui/css/17.046fd3d8.css" rel="prefetch"><link href="/ui/css/8.eb842258.css" rel="prefetch"><link href="/ui/css/9.e1b97a16.css" rel="prefetch"><link href="/ui/js/0.js" rel="prefetch"><link href="/ui/js/1.js" rel="prefetch"><link href="/ui/js/10.js" rel="prefetch"><link href="/ui/js/11.js" rel="prefetch"><link href="/ui/js/12.js" rel="prefetch"><link href="/ui/js/13.js" rel="prefetch"><link href="/ui/js/14.js" rel="prefetch"><link href="/ui/js/15.js" rel="prefetch"><link href="/ui/js/16.js" rel="prefetch"><link href="/ui/js/17.js" rel="prefetch"><link href="/ui/js/18.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/5.js" rel="prefetch"><link href="/ui/js/6.js" rel="prefetch"><link href="/ui/js/7.js" rel="prefetch"><link href="/ui/js/8.js" rel="prefetch"><link href="/ui/js/9.js" rel="prefetch"><link href="/ui/css/app.08addc01.css" rel="preload" as="style"><link href="/ui/css/vendors~app.a048753d.css" rel="preload" as="style"><link href="/ui/js/app.js" rel="preload" as="script"><link href="/ui/js/vendors~app.js" rel="preload" as="script"><link href="/ui/css/vendors~app.a048753d.css" rel="stylesheet"><link href="/ui/css/app.08addc01.css" rel="stylesheet"></head>
<body> <body>
<noscript> <noscript>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long