mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-02-08 01:20:07 +08:00
style: 增加进度条
This commit is contained in:
parent
8e55e8e6ef
commit
8ad37807d5
@ -6,7 +6,10 @@ import (
|
|||||||
"github.com/1Panel-dev/1Panel/app/dto"
|
"github.com/1Panel-dev/1Panel/app/dto"
|
||||||
"github.com/1Panel-dev/1Panel/constant"
|
"github.com/1Panel-dev/1Panel/constant"
|
||||||
"github.com/1Panel-dev/1Panel/global"
|
"github.com/1Panel-dev/1Panel/global"
|
||||||
|
websocket2 "github.com/1Panel-dev/1Panel/utils/websocket"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/gorilla/websocket"
|
||||||
|
"net/http"
|
||||||
"path"
|
"path"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -174,11 +177,14 @@ func (b *BaseApi) WgetFile(c *gin.Context) {
|
|||||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err := fileService.Wget(req); err != nil {
|
key, err := fileService.Wget(req)
|
||||||
|
if err != nil {
|
||||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
helper.SuccessWithData(c, nil)
|
helper.SuccessWithData(c, dto.FileWgetRes{
|
||||||
|
Key: key,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *BaseApi) MoveFile(c *gin.Context) {
|
func (b *BaseApi) MoveFile(c *gin.Context) {
|
||||||
@ -221,3 +227,37 @@ func (b *BaseApi) Size(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
helper.SuccessWithData(c, res)
|
helper.SuccessWithData(c, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var wsUpgrade = websocket.Upgrader{
|
||||||
|
CheckOrigin: func(r *http.Request) bool {
|
||||||
|
return true
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
var WsManager = websocket2.Manager{
|
||||||
|
Group: make(map[string]*websocket2.Client),
|
||||||
|
Register: make(chan *websocket2.Client, 128),
|
||||||
|
UnRegister: make(chan *websocket2.Client, 128),
|
||||||
|
ClientCount: 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *BaseApi) Ws(c *gin.Context) {
|
||||||
|
ws, err := wsUpgrade.Upgrade(c.Writer, c.Request, nil)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
wsClient := websocket2.NewWsClient("13232", ws)
|
||||||
|
go wsClient.Read()
|
||||||
|
go wsClient.Write()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *BaseApi) Keys(c *gin.Context) {
|
||||||
|
res := &dto.FileProcessKeys{}
|
||||||
|
keys, err := global.CACHE.PrefixScanKey("file-wget-")
|
||||||
|
if err != nil {
|
||||||
|
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
res.Keys = keys
|
||||||
|
helper.SuccessWithData(c, res)
|
||||||
|
}
|
||||||
|
@ -83,3 +83,22 @@ type DirSizeReq struct {
|
|||||||
type DirSizeRes struct {
|
type DirSizeRes struct {
|
||||||
Size float64 `json:"size" validate:"required"`
|
Size float64 `json:"size" validate:"required"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type FileProcess struct {
|
||||||
|
Total uint64 `json:"total"`
|
||||||
|
Written uint64 `json:"written"`
|
||||||
|
Percent float64 `json:"percent"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type FileProcessReq struct {
|
||||||
|
Key string
|
||||||
|
}
|
||||||
|
|
||||||
|
type FileProcessKeys struct {
|
||||||
|
Keys []string `json:"keys"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type FileWgetRes struct {
|
||||||
|
Key string
|
||||||
|
}
|
||||||
|
@ -7,6 +7,7 @@ import (
|
|||||||
"github.com/1Panel-dev/1Panel/global"
|
"github.com/1Panel-dev/1Panel/global"
|
||||||
"github.com/1Panel-dev/1Panel/utils/files"
|
"github.com/1Panel-dev/1Panel/utils/files"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
uuid "github.com/satori/go.uuid"
|
||||||
"io"
|
"io"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
"os"
|
"os"
|
||||||
@ -123,9 +124,10 @@ func (f FileService) ChangeName(re dto.FileRename) error {
|
|||||||
return fo.Rename(re.OldName, re.NewName)
|
return fo.Rename(re.OldName, re.NewName)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f FileService) Wget(w dto.FileWget) error {
|
func (f FileService) Wget(w dto.FileWget) (string, error) {
|
||||||
fo := files.NewFileOp()
|
fo := files.NewFileOp()
|
||||||
return fo.DownloadFile(w.Url, filepath.Join(w.Path, w.Name))
|
key := "file-wget-" + uuid.NewV4().String()
|
||||||
|
return key, fo.DownloadFile(w.Url, filepath.Join(w.Path, w.Name), key)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f FileService) MvFile(m dto.FileMove) error {
|
func (f FileService) MvFile(m dto.FileMove) error {
|
||||||
|
17
backend/init/cache/badger_db/badger_db.go
vendored
17
backend/init/cache/badger_db/badger_db.go
vendored
@ -68,3 +68,20 @@ func (c *Cache) SetWithTTL(key string, value interface{}, duration time.Duration
|
|||||||
})
|
})
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Cache) PrefixScanKey(prefixStr string) ([]string, error) {
|
||||||
|
var res []string
|
||||||
|
err := c.db.View(func(txn *badger.Txn) error {
|
||||||
|
it := txn.NewIterator(badger.DefaultIteratorOptions)
|
||||||
|
defer it.Close()
|
||||||
|
prefix := []byte(prefixStr)
|
||||||
|
for it.Seek(prefix); it.ValidForPrefix(prefix); it.Next() {
|
||||||
|
item := it.Item()
|
||||||
|
k := item.Key()
|
||||||
|
res = append(res, string(k))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
@ -30,6 +30,8 @@ func (f *FileRouter) InitFileRouter(Router *gin.RouterGroup) {
|
|||||||
fileRouter.POST("/move", baseApi.MoveFile)
|
fileRouter.POST("/move", baseApi.MoveFile)
|
||||||
fileRouter.POST("/download", baseApi.Download)
|
fileRouter.POST("/download", baseApi.Download)
|
||||||
fileRouter.POST("/size", baseApi.Size)
|
fileRouter.POST("/size", baseApi.Size)
|
||||||
|
fileRouter.GET("/ws", baseApi.Ws)
|
||||||
|
fileRouter.GET("/keys", baseApi.Keys)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,8 @@ package files
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
"github.com/1Panel-dev/1Panel/global"
|
"github.com/1Panel-dev/1Panel/global"
|
||||||
"github.com/mholt/archiver/v4"
|
"github.com/mholt/archiver/v4"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
@ -12,7 +14,9 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strconv"
|
||||||
"sync"
|
"sync"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type FileOp struct {
|
type FileOp struct {
|
||||||
@ -83,23 +87,77 @@ func (f FileOp) Rename(oldName string, newName string) error {
|
|||||||
return f.Fs.Rename(oldName, newName)
|
return f.Fs.Rename(oldName, newName)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f FileOp) DownloadFile(url, dst string) error {
|
type WriteCounter struct {
|
||||||
|
Total uint64
|
||||||
|
Written uint64
|
||||||
|
Key string
|
||||||
|
Name string
|
||||||
|
}
|
||||||
|
|
||||||
|
type Process struct {
|
||||||
|
Total uint64 `json:"total"`
|
||||||
|
Written uint64 `json:"written"`
|
||||||
|
Percent float64 `json:"percent"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *WriteCounter) Write(p []byte) (n int, err error) {
|
||||||
|
n = len(p)
|
||||||
|
w.Written += uint64(n)
|
||||||
|
w.SaveProcess()
|
||||||
|
return n, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *WriteCounter) SaveProcess() {
|
||||||
|
percent := float64(w.Written) / float64(w.Total) * 100
|
||||||
|
percentValue, _ := strconv.ParseFloat(fmt.Sprintf("%.2f", percent), 64)
|
||||||
|
|
||||||
|
process := Process{
|
||||||
|
Total: w.Total,
|
||||||
|
Written: w.Written,
|
||||||
|
Percent: percentValue,
|
||||||
|
Name: w.Name,
|
||||||
|
}
|
||||||
|
|
||||||
|
by, _ := json.Marshal(process)
|
||||||
|
|
||||||
|
if percentValue < 100 {
|
||||||
|
if err := global.CACHE.Set(w.Key, string(by)); err != nil {
|
||||||
|
global.LOG.Errorf("save cache error, err %s", err.Error())
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if err := global.CACHE.SetWithTTL(w.Key, string(by), time.Second*time.Duration(10)); err != nil {
|
||||||
|
global.LOG.Errorf("save cache error, err %s", err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f FileOp) DownloadFile(url, dst, key string) error {
|
||||||
resp, err := http.Get(url)
|
resp, err := http.Get(url)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
global.LOG.Errorf("get download file [%s] error, err %s", dst, err.Error())
|
||||||
|
}
|
||||||
|
header, err := http.Head(url)
|
||||||
|
if err != nil {
|
||||||
|
global.LOG.Errorf("get download file [%s] error, err %s", dst, err.Error())
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
out, err := os.Create(dst)
|
out, err := os.Create(dst)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
global.LOG.Errorf("create download file [%s] error, err %s", dst, err.Error())
|
||||||
}
|
}
|
||||||
defer out.Close()
|
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
if _, err = io.Copy(out, resp.Body); err != nil {
|
counter := &WriteCounter{}
|
||||||
|
counter.Key = key
|
||||||
|
counter.Total = uint64(header.ContentLength)
|
||||||
|
counter.Name = filepath.Base(dst)
|
||||||
|
if _, err = io.Copy(out, io.TeeReader(resp.Body, counter)); err != nil {
|
||||||
global.LOG.Errorf("save download file [%s] error, err %s", dst, err.Error())
|
global.LOG.Errorf("save download file [%s] error, err %s", dst, err.Error())
|
||||||
}
|
}
|
||||||
|
out.Close()
|
||||||
|
resp.Body.Close()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
79
backend/utils/websocket/client.go
Normal file
79
backend/utils/websocket/client.go
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
package websocket
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"github.com/1Panel-dev/1Panel/global"
|
||||||
|
"github.com/1Panel-dev/1Panel/utils/files"
|
||||||
|
"github.com/gorilla/websocket"
|
||||||
|
)
|
||||||
|
|
||||||
|
type WsMsg struct {
|
||||||
|
Type string
|
||||||
|
Keys []string
|
||||||
|
}
|
||||||
|
|
||||||
|
type Client struct {
|
||||||
|
ID string
|
||||||
|
Socket *websocket.Conn
|
||||||
|
Msg chan []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewWsClient(ID string, socket *websocket.Conn) *Client {
|
||||||
|
return &Client{
|
||||||
|
ID: ID,
|
||||||
|
Socket: socket,
|
||||||
|
Msg: make(chan []byte, 100),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) Read() {
|
||||||
|
defer func() {
|
||||||
|
close(c.Msg)
|
||||||
|
}()
|
||||||
|
|
||||||
|
for {
|
||||||
|
_, message, err := c.Socket.ReadMessage()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
msg := &WsMsg{}
|
||||||
|
_ = json.Unmarshal(message, msg)
|
||||||
|
ProcessData(c, msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) Write() {
|
||||||
|
defer func() {
|
||||||
|
c.Socket.Close()
|
||||||
|
}()
|
||||||
|
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case message, ok := <-c.Msg:
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
_ = c.Socket.WriteMessage(websocket.TextMessage, message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func ProcessData(c *Client, msg *WsMsg) {
|
||||||
|
|
||||||
|
if msg.Type == "wget" {
|
||||||
|
var res []files.Process
|
||||||
|
for _, k := range msg.Keys {
|
||||||
|
value, err := global.CACHE.Get(k)
|
||||||
|
if err != nil {
|
||||||
|
global.LOG.Errorf("get cache error,err %s", err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
process := &files.Process{}
|
||||||
|
json.Unmarshal(value, process)
|
||||||
|
res = append(res, *process)
|
||||||
|
}
|
||||||
|
reByte, _ := json.Marshal(res)
|
||||||
|
c.Msg <- reByte
|
||||||
|
}
|
||||||
|
}
|
38
backend/utils/websocket/client_manager.go
Normal file
38
backend/utils/websocket/client_manager.go
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
package websocket
|
||||||
|
|
||||||
|
import "sync"
|
||||||
|
|
||||||
|
type Manager struct {
|
||||||
|
Group map[string]*Client
|
||||||
|
Lock sync.Mutex
|
||||||
|
Register, UnRegister chan *Client
|
||||||
|
ClientCount uint
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Manager) Start() {
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case client := <-m.Register:
|
||||||
|
m.Lock.Lock()
|
||||||
|
m.Group[client.ID] = client
|
||||||
|
m.ClientCount++
|
||||||
|
m.Lock.Unlock()
|
||||||
|
case client := <-m.UnRegister:
|
||||||
|
m.Lock.Lock()
|
||||||
|
if _, ok := m.Group[client.ID]; ok {
|
||||||
|
close(client.Msg)
|
||||||
|
delete(m.Group, client.ID)
|
||||||
|
m.ClientCount--
|
||||||
|
}
|
||||||
|
m.Lock.Unlock()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Manager) RegisterClient(client *Client) {
|
||||||
|
m.Register <- client
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Manager) UnRegisterClient(client *Client) {
|
||||||
|
m.UnRegister <- client
|
||||||
|
}
|
@ -80,6 +80,14 @@ export namespace File {
|
|||||||
url: string;
|
url: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface FileWgetRes {
|
||||||
|
key: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface FileKeys {
|
||||||
|
keys: string[];
|
||||||
|
}
|
||||||
|
|
||||||
export interface FileMove {
|
export interface FileMove {
|
||||||
oldPaths: string[];
|
oldPaths: string[];
|
||||||
newPath: string;
|
newPath: string;
|
||||||
|
@ -47,7 +47,7 @@ export const RenameRile = (params: File.FileRename) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const WgetFile = (params: File.FileWget) => {
|
export const WgetFile = (params: File.FileWget) => {
|
||||||
return http.post<File.File>('files/wget', params);
|
return http.post<File.FileWgetRes>('files/wget', params);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const MoveFile = (params: File.FileMove) => {
|
export const MoveFile = (params: File.FileMove) => {
|
||||||
@ -61,3 +61,7 @@ export const DownloadFile = (params: File.FileDownload) => {
|
|||||||
export const ComputeDirSize = (params: File.DirSizeReq) => {
|
export const ComputeDirSize = (params: File.DirSizeReq) => {
|
||||||
return http.post<File.DirSizeRes>('files/size', params);
|
return http.post<File.DirSizeRes>('files/size', params);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const FileKeys = () => {
|
||||||
|
return http.get<File.FileKeys>('files/keys');
|
||||||
|
};
|
||||||
|
@ -245,5 +245,6 @@ export default {
|
|||||||
calculate: 'Calculate',
|
calculate: 'Calculate',
|
||||||
canNotDeCompress: 'Can not DeCompress this File',
|
canNotDeCompress: 'Can not DeCompress this File',
|
||||||
uploadSuccess: 'Upload Success!',
|
uploadSuccess: 'Upload Success!',
|
||||||
|
downloadProcess: 'Download Process',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -245,5 +245,6 @@ export default {
|
|||||||
calculate: '计算',
|
calculate: '计算',
|
||||||
canNotDeCompress: '无法解压此文件',
|
canNotDeCompress: '无法解压此文件',
|
||||||
uploadSuccess: '上传成功!',
|
uploadSuccess: '上传成功!',
|
||||||
|
downloadProcess: '下载进度',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -172,6 +172,7 @@
|
|||||||
:name="downloadPage.name"
|
:name="downloadPage.name"
|
||||||
@close="closeDownload"
|
@close="closeDownload"
|
||||||
></Download>
|
></Download>
|
||||||
|
<Process :open="processPage.open" @close="closeProcess"></Process>
|
||||||
</el-row>
|
</el-row>
|
||||||
</LayoutContent>
|
</LayoutContent>
|
||||||
</template>
|
</template>
|
||||||
@ -206,6 +207,7 @@ import Wget from './wget/index.vue';
|
|||||||
import Move from './move/index.vue';
|
import Move from './move/index.vue';
|
||||||
import Download from './download/index.vue';
|
import Download from './download/index.vue';
|
||||||
import { Mimetypes } from '@/global/mimetype';
|
import { Mimetypes } from '@/global/mimetype';
|
||||||
|
import Process from './process/index.vue';
|
||||||
|
|
||||||
const data = ref();
|
const data = ref();
|
||||||
let selects = ref<any>([]);
|
let selects = ref<any>([]);
|
||||||
@ -227,6 +229,7 @@ const renamePage = reactive({ open: false, path: '', oldName: '' });
|
|||||||
const wgetPage = reactive({ open: false, path: '' });
|
const wgetPage = reactive({ open: false, path: '' });
|
||||||
const movePage = reactive({ open: false, oldPaths: [''], type: '' });
|
const movePage = reactive({ open: false, oldPaths: [''], type: '' });
|
||||||
const downloadPage = reactive({ open: false, paths: [''], name: '' });
|
const downloadPage = reactive({ open: false, paths: [''], name: '' });
|
||||||
|
const processPage = reactive({ open: false });
|
||||||
|
|
||||||
const defaultProps = {
|
const defaultProps = {
|
||||||
children: 'children',
|
children: 'children',
|
||||||
@ -445,9 +448,21 @@ const openWget = () => {
|
|||||||
wgetPage.path = req.path;
|
wgetPage.path = req.path;
|
||||||
};
|
};
|
||||||
|
|
||||||
const closeWget = () => {
|
const closeWget = (submit: any) => {
|
||||||
|
console.log(submit);
|
||||||
wgetPage.open = false;
|
wgetPage.open = false;
|
||||||
search(req);
|
search(req);
|
||||||
|
if (submit) {
|
||||||
|
openProcess();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const openProcess = () => {
|
||||||
|
processPage.open = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
const closeProcess = () => {
|
||||||
|
processPage.open = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
const openRename = (item: File.File) => {
|
const openRename = (item: File.File) => {
|
||||||
@ -490,7 +505,6 @@ const closeDownload = () => {
|
|||||||
downloadPage.open = false;
|
downloadPage.open = false;
|
||||||
search(req);
|
search(req);
|
||||||
};
|
};
|
||||||
|
|
||||||
const saveContent = (content: string) => {
|
const saveContent = (content: string) => {
|
||||||
editorPage.loading = true;
|
editorPage.loading = true;
|
||||||
SaveFileContent({ path: codeReq.path, content: content }).finally(() => {
|
SaveFileContent({ path: codeReq.path, content: content }).finally(() => {
|
||||||
|
94
frontend/src/views/host/file-management/process/index.vue
Normal file
94
frontend/src/views/host/file-management/process/index.vue
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
<template>
|
||||||
|
<el-dialog
|
||||||
|
width="30%"
|
||||||
|
:title="$t('file.downloadProcess')"
|
||||||
|
v-model="open"
|
||||||
|
@open="onOpen"
|
||||||
|
:before-close="handleClose"
|
||||||
|
>
|
||||||
|
<div v-for="(value, index) in res" :key="index">
|
||||||
|
<span>{{ value['name'] }}</span>
|
||||||
|
<el-progress :text-inside="true" :stroke-width="15" :percentage="value['percent']"></el-progress>
|
||||||
|
<span>{{ value['written'] }}/{{ value['total'] }}</span>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { FileKeys } from '@/api/modules/files';
|
||||||
|
import { onBeforeUnmount, ref, toRefs } from 'vue';
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
open: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const { open } = toRefs(props);
|
||||||
|
let processSocket = ref(null) as unknown as WebSocket;
|
||||||
|
const res = ref([]);
|
||||||
|
const keys = ref(['']);
|
||||||
|
|
||||||
|
const em = defineEmits(['close']);
|
||||||
|
const handleClose = () => {
|
||||||
|
closeSocket();
|
||||||
|
em('close', open);
|
||||||
|
};
|
||||||
|
|
||||||
|
const closeSocket = () => {
|
||||||
|
processSocket && processSocket.close();
|
||||||
|
};
|
||||||
|
|
||||||
|
const isWsOpen = () => {
|
||||||
|
const readyState = processSocket && processSocket.readyState;
|
||||||
|
return readyState === 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
const onOpenProcess = () => {};
|
||||||
|
const onMessage = (message: any) => {
|
||||||
|
res.value = JSON.parse(message.data);
|
||||||
|
};
|
||||||
|
const onerror = () => {};
|
||||||
|
const onClose = () => {};
|
||||||
|
|
||||||
|
const initProcess = () => {
|
||||||
|
processSocket = new WebSocket(`ws://localhost:9999/api/v1/files/ws`);
|
||||||
|
processSocket.onopen = onOpenProcess;
|
||||||
|
processSocket.onmessage = onMessage;
|
||||||
|
processSocket.onerror = onerror;
|
||||||
|
processSocket.onclose = onClose;
|
||||||
|
sendMsg();
|
||||||
|
};
|
||||||
|
|
||||||
|
const getKeys = () => {
|
||||||
|
FileKeys().then((res) => {
|
||||||
|
console.log(res);
|
||||||
|
if (res.data.keys.length > 0) {
|
||||||
|
keys.value = res.data.keys;
|
||||||
|
initProcess();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const sendMsg = () => {
|
||||||
|
setInterval(() => {
|
||||||
|
if (isWsOpen()) {
|
||||||
|
processSocket.send(
|
||||||
|
JSON.stringify({
|
||||||
|
type: 'wget',
|
||||||
|
keys: keys.value,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}, 1000);
|
||||||
|
};
|
||||||
|
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
closeSocket();
|
||||||
|
});
|
||||||
|
|
||||||
|
const onOpen = () => {
|
||||||
|
getKeys();
|
||||||
|
};
|
||||||
|
</script>
|
@ -22,7 +22,7 @@
|
|||||||
</el-form>
|
</el-form>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<span class="dialog-footer">
|
<span class="dialog-footer">
|
||||||
<el-button @click="handleClose" :disabled="loading">{{ $t('commons.button.cancel') }}</el-button>
|
<el-button @click="handleClose(false)" :disabled="loading">{{ $t('commons.button.cancel') }}</el-button>
|
||||||
<el-button type="primary" @click="submit(fileForm)" :disabled="loading">
|
<el-button type="primary" @click="submit(fileForm)" :disabled="loading">
|
||||||
{{ $t('commons.button.confirm') }}
|
{{ $t('commons.button.confirm') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
@ -67,21 +67,21 @@ const addForm = reactive({
|
|||||||
|
|
||||||
const em = defineEmits(['close']);
|
const em = defineEmits(['close']);
|
||||||
|
|
||||||
const handleClose = () => {
|
const handleClose = (submit: boolean) => {
|
||||||
if (fileForm.value) {
|
if (fileForm.value) {
|
||||||
fileForm.value.resetFields();
|
fileForm.value.resetFields();
|
||||||
}
|
}
|
||||||
em('close', open);
|
if (submit != true) {
|
||||||
|
em('close', false);
|
||||||
|
} else {
|
||||||
|
em('close', true);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const getPath = (path: string) => {
|
const getPath = (path: string) => {
|
||||||
addForm.path = path;
|
addForm.path = path;
|
||||||
};
|
};
|
||||||
|
|
||||||
const onOpen = () => {
|
|
||||||
addForm.path = props.path;
|
|
||||||
};
|
|
||||||
|
|
||||||
const submit = async (formEl: FormInstance | undefined) => {
|
const submit = async (formEl: FormInstance | undefined) => {
|
||||||
if (!formEl) return;
|
if (!formEl) return;
|
||||||
await formEl.validate((valid) => {
|
await formEl.validate((valid) => {
|
||||||
@ -92,11 +92,15 @@ const submit = async (formEl: FormInstance | undefined) => {
|
|||||||
WgetFile(addForm)
|
WgetFile(addForm)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
ElMessage.success(i18n.global.t('file.downloadStart'));
|
ElMessage.success(i18n.global.t('file.downloadStart'));
|
||||||
handleClose();
|
handleClose(true);
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const onOpen = () => {
|
||||||
|
addForm.path = props.path;
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
@ -36,11 +36,11 @@ export default defineConfig(({ mode }: ConfigEnv): UserConfig => {
|
|||||||
server: {
|
server: {
|
||||||
port: viteEnv.VITE_PORT,
|
port: viteEnv.VITE_PORT,
|
||||||
open: viteEnv.VITE_OPEN,
|
open: viteEnv.VITE_OPEN,
|
||||||
host: '0.0.0.0',
|
// host: '0.0.0.0',
|
||||||
// https: false,
|
// https: false,
|
||||||
proxy: {
|
proxy: {
|
||||||
'/api/v1': {
|
'/api/v1': {
|
||||||
target: 'http://localhost:9999',
|
target: 'http://127.0.0.1:9999',
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
// rewrite: (path) => path.replace(/^\/api/, ''),
|
// rewrite: (path) => path.replace(/^\/api/, ''),
|
||||||
},
|
},
|
||||||
|
Loading…
x
Reference in New Issue
Block a user