mirror of
https://github.com/TeaOSLab/EdgeAdmin.git
synced 2025-12-03 10:20:25 +08:00
可以设置管理界面和用户界面的浏览器图标和Logo
This commit is contained in:
@@ -65,6 +65,7 @@ func (this *IndexAction) RunGet(params struct {
|
||||
} else {
|
||||
this.Data["version"] = teaconst.Version
|
||||
}
|
||||
this.Data["faviconFileId"] = config.FaviconFileId
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
@@ -91,6 +91,7 @@ func (this *UploadPopupAction) RunPost(params struct {
|
||||
_, err = this.RPC().FileRPC().UpdateFileFinished(this.AdminContext(), &pb.UpdateFileFinishedRequest{FileId: fileId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
// 保存
|
||||
|
||||
@@ -3,7 +3,9 @@ package ui
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"io"
|
||||
)
|
||||
|
||||
type IndexAction struct {
|
||||
@@ -32,10 +34,14 @@ func (this *IndexAction) RunPost(params struct {
|
||||
ShowFinance bool
|
||||
ShowVersion bool
|
||||
Version string
|
||||
FaviconFile *actions.File
|
||||
LogoFile *actions.File
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
defer this.CreateLogInfo("修改管理界面设置")
|
||||
|
||||
params.Must.
|
||||
Field("productName", params.ProductName).
|
||||
Require("请输入产品名称").
|
||||
@@ -53,6 +59,101 @@ func (this *IndexAction) RunPost(params struct {
|
||||
config.ShowFinance = params.ShowFinance
|
||||
config.ShowVersion = params.ShowVersion
|
||||
config.Version = params.Version
|
||||
|
||||
// 上传Favicon文件
|
||||
if params.FaviconFile != nil {
|
||||
createResp, err := this.RPC().FileRPC().CreateFile(this.AdminContext(), &pb.CreateFileRequest{
|
||||
Filename: params.FaviconFile.Filename,
|
||||
Size: params.FaviconFile.Size,
|
||||
IsPublic: true,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
fileId := createResp.FileId
|
||||
|
||||
// 上传内容
|
||||
buf := make([]byte, 512*1024)
|
||||
reader, err := params.FaviconFile.OriginFile.Open()
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
for {
|
||||
n, err := reader.Read(buf)
|
||||
if n > 0 {
|
||||
_, err = this.RPC().FileChunkRPC().CreateFileChunk(this.AdminContext(), &pb.CreateFileChunkRequest{
|
||||
FileId: fileId,
|
||||
Data: buf[:n],
|
||||
})
|
||||
if err != nil {
|
||||
this.Fail("上传失败:" + err.Error())
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
this.Fail("上传失败:" + err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
// 置为已完成
|
||||
_, err = this.RPC().FileRPC().UpdateFileFinished(this.AdminContext(), &pb.UpdateFileFinishedRequest{FileId: fileId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
}
|
||||
config.FaviconFileId = fileId
|
||||
}
|
||||
|
||||
// 上传Logo文件
|
||||
if params.LogoFile != nil {
|
||||
createResp, err := this.RPC().FileRPC().CreateFile(this.AdminContext(), &pb.CreateFileRequest{
|
||||
Filename: params.LogoFile.Filename,
|
||||
Size: params.LogoFile.Size,
|
||||
IsPublic: true,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
fileId := createResp.FileId
|
||||
|
||||
// 上传内容
|
||||
buf := make([]byte, 512*1024)
|
||||
reader, err := params.LogoFile.OriginFile.Open()
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
for {
|
||||
n, err := reader.Read(buf)
|
||||
if n > 0 {
|
||||
_, err = this.RPC().FileChunkRPC().CreateFileChunk(this.AdminContext(), &pb.CreateFileChunkRequest{
|
||||
FileId: fileId,
|
||||
Data: buf[:n],
|
||||
})
|
||||
if err != nil {
|
||||
this.Fail("上传失败:" + err.Error())
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
this.Fail("上传失败:" + err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
// 置为已完成
|
||||
_, err = this.RPC().FileRPC().UpdateFileFinished(this.AdminContext(), &pb.UpdateFileFinishedRequest{FileId: fileId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
}
|
||||
config.LogoFileId = fileId
|
||||
}
|
||||
|
||||
err = configloaders.UpdateAdminUIConfig(config)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
|
||||
@@ -3,7 +3,9 @@ package userui
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"io"
|
||||
)
|
||||
|
||||
type IndexAction struct {
|
||||
@@ -32,6 +34,8 @@ func (this *IndexAction) RunPost(params struct {
|
||||
ShowVersion bool
|
||||
Version string
|
||||
ShowFinance bool
|
||||
FaviconFile *actions.File
|
||||
LogoFile *actions.File
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
@@ -53,6 +57,101 @@ func (this *IndexAction) RunPost(params struct {
|
||||
config.ShowVersion = params.ShowVersion
|
||||
config.Version = params.Version
|
||||
config.ShowFinance = params.ShowFinance
|
||||
|
||||
// 上传Favicon文件
|
||||
if params.FaviconFile != nil {
|
||||
createResp, err := this.RPC().FileRPC().CreateFile(this.AdminContext(), &pb.CreateFileRequest{
|
||||
Filename: params.FaviconFile.Filename,
|
||||
Size: params.FaviconFile.Size,
|
||||
IsPublic: true,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
fileId := createResp.FileId
|
||||
|
||||
// 上传内容
|
||||
buf := make([]byte, 512*1024)
|
||||
reader, err := params.FaviconFile.OriginFile.Open()
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
for {
|
||||
n, err := reader.Read(buf)
|
||||
if n > 0 {
|
||||
_, err = this.RPC().FileChunkRPC().CreateFileChunk(this.AdminContext(), &pb.CreateFileChunkRequest{
|
||||
FileId: fileId,
|
||||
Data: buf[:n],
|
||||
})
|
||||
if err != nil {
|
||||
this.Fail("上传失败:" + err.Error())
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
this.Fail("上传失败:" + err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
// 置为已完成
|
||||
_, err = this.RPC().FileRPC().UpdateFileFinished(this.AdminContext(), &pb.UpdateFileFinishedRequest{FileId: fileId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
}
|
||||
config.FaviconFileId = fileId
|
||||
}
|
||||
|
||||
// 上传Logo文件
|
||||
if params.LogoFile != nil {
|
||||
createResp, err := this.RPC().FileRPC().CreateFile(this.AdminContext(), &pb.CreateFileRequest{
|
||||
Filename: params.LogoFile.Filename,
|
||||
Size: params.LogoFile.Size,
|
||||
IsPublic: true,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
fileId := createResp.FileId
|
||||
|
||||
// 上传内容
|
||||
buf := make([]byte, 512*1024)
|
||||
reader, err := params.LogoFile.OriginFile.Open()
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
for {
|
||||
n, err := reader.Read(buf)
|
||||
if n > 0 {
|
||||
_, err = this.RPC().FileChunkRPC().CreateFileChunk(this.AdminContext(), &pb.CreateFileChunkRequest{
|
||||
FileId: fileId,
|
||||
Data: buf[:n],
|
||||
})
|
||||
if err != nil {
|
||||
this.Fail("上传失败:" + err.Error())
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
this.Fail("上传失败:" + err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
// 置为已完成
|
||||
_, err = this.RPC().FileRPC().UpdateFileFinished(this.AdminContext(), &pb.UpdateFileFinishedRequest{FileId: fileId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
}
|
||||
config.LogoFileId = fileId
|
||||
}
|
||||
|
||||
err = configloaders.UpdateUserUIConfig(config)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
|
||||
68
internal/web/actions/default/ui/image.go
Normal file
68
internal/web/actions/default/ui/image.go
Normal file
@@ -0,0 +1,68 @@
|
||||
package ui
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"mime"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// 公开的图片,不需要检查用户权限
|
||||
type ImageAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *ImageAction) Init() {
|
||||
this.Nav("", "", "")
|
||||
}
|
||||
|
||||
func (this *ImageAction) RunGet(params struct {
|
||||
FileId int64
|
||||
}) {
|
||||
fileResp, err := this.RPC().FileRPC().FindEnabledFile(this.AdminContext(), &pb.FindEnabledFileRequest{FileId: params.FileId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
file := fileResp.File
|
||||
if file == nil {
|
||||
this.NotFound("file", params.FileId)
|
||||
return
|
||||
}
|
||||
|
||||
if !file.IsPublic {
|
||||
this.NotFound("file", params.FileId)
|
||||
return
|
||||
}
|
||||
|
||||
chunkIdsResp, err := this.RPC().FileChunkRPC().FindAllFileChunkIds(this.AdminContext(), &pb.FindAllFileChunkIdsRequest{FileId: file.Id})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
mimeType := ""
|
||||
if len(file.Filename) > 0 {
|
||||
ext := filepath.Ext(file.Filename)
|
||||
mimeType = mime.TypeByExtension(ext)
|
||||
}
|
||||
if len(mimeType) == 0 {
|
||||
mimeType = "image/png"
|
||||
}
|
||||
|
||||
this.AddHeader("Last-Modified", "Fri, 06 Sep 2019 08:29:50 GMT")
|
||||
this.AddHeader("Content-Type", mimeType)
|
||||
this.AddHeader("Content-Length", strconv.FormatInt(file.Size, 10))
|
||||
for _, chunkId := range chunkIdsResp.FileChunkIds {
|
||||
chunkResp, err := this.RPC().FileChunkRPC().DownloadFileChunk(this.AdminContext(), &pb.DownloadFileChunkRequest{FileChunkId: chunkId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if chunkResp.FileChunk == nil {
|
||||
continue
|
||||
}
|
||||
this.Write(chunkResp.FileChunk.Data)
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,9 @@ func init() {
|
||||
server.
|
||||
Prefix("/ui").
|
||||
|
||||
// 公共可以访问的链接
|
||||
Get("/image/:fileId", new(ImageAction)).
|
||||
|
||||
// 以下的需要压缩
|
||||
Helper(&actions.Gzip{Level: gzip.BestCompression}).
|
||||
Get("/components.js", new(ComponentsAction)).
|
||||
|
||||
@@ -88,6 +88,8 @@ func (this *userMustAuth) BeforeAction(actionPtr actions.ActionWrapper, paramNam
|
||||
action.Data["teaShowVersion"] = config.ShowVersion
|
||||
action.Data["teaTitle"] = config.AdminSystemName
|
||||
action.Data["teaName"] = config.ProductName
|
||||
action.Data["teaFaviconFileId"] = config.FaviconFileId
|
||||
action.Data["teaLogoFileId"] = config.LogoFileId
|
||||
action.Data["teaUsername"] = configloaders.FindAdminFullname(adminId)
|
||||
|
||||
action.Data["teaUserAvatar"] = ""
|
||||
|
||||
@@ -4,7 +4,11 @@
|
||||
<title>{$.teaTitle}</title>
|
||||
<meta charset="UTF-8"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=0">
|
||||
{$if eq .teaFaviconFileId 0}
|
||||
<link rel="shortcut icon" href="/images/favicon.png"/>
|
||||
{$else}
|
||||
<link rel="shortcut icon" href="/ui/image/{$.teaFaviconFileId}"/>
|
||||
{$end}
|
||||
<link rel="stylesheet" type="text/css" href="/_/@default/@layout.css" media="all"/>
|
||||
{$TEA.SEMANTIC}
|
||||
<link rel="stylesheet" type="text/css" href="/_/@default/@layout_override.css" media="all"/>
|
||||
@@ -23,7 +27,7 @@
|
||||
<!-- 顶部导航 -->
|
||||
<div class="ui menu top-nav blue inverted small borderless" v-cloak="">
|
||||
<a href="/" class="item">
|
||||
<i class="ui icon leaf"></i> {{teaTitle}} <sup v-if="teaShowVersion">v{{teaVersion}}</sup>
|
||||
<i class="ui icon leaf" v-if="teaLogoFileId == 0"></i><img v-if="teaLogoFileId > 0" :src="'/ui/image/' + teaLogoFileId"/> {{teaTitle}} <sup v-if="teaShowVersion">v{{teaVersion}}</sup>
|
||||
</a>
|
||||
|
||||
<div class="right menu">
|
||||
|
||||
@@ -2,7 +2,11 @@
|
||||
<html lang="zh">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
||||
{$if eq .faviconFileId 0}
|
||||
<link rel="shortcut icon" href="/images/favicon.png"/>
|
||||
{$else}
|
||||
<link rel="shortcut icon" href="/ui/image/{$ .faviconFileId}"/>
|
||||
{$end}
|
||||
<title>登录{$.systemName}</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=0">
|
||||
{$TEA.VUE}
|
||||
|
||||
@@ -41,6 +41,36 @@
|
||||
<checkbox name="showFinance" v-model="config.showFinance"></checkbox>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>浏览器图标</td>
|
||||
<td>
|
||||
<div v-if="config.faviconFileId > 0">
|
||||
<a :href="'/ui/image/' + config.faviconFileId" target="_blank"><img :src="'/ui/image/' + config.faviconFileId" style="width:32px;border:1px #ccc solid;"/></a>
|
||||
</div>
|
||||
<div v-else>
|
||||
<span class="disabled">还没有上传。</span>
|
||||
</div>
|
||||
<div style="margin-top: 0.8em">
|
||||
<input type="file" name="faviconFile" accept=".png"/>
|
||||
</div>
|
||||
<p class="comment">在浏览器标签栏显示的图标,请使用PNG格式。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Logo</td>
|
||||
<td>
|
||||
<div v-if="config.logoFileId > 0">
|
||||
<a :href="'/ui/image/' + config.logoFileId" target="_blank"><img :src="'/ui/image/' + config.logoFileId" style="width:32px;border:1px #ccc solid;"/></a>
|
||||
</div>
|
||||
<div v-else>
|
||||
<span class="disabled">还没有上传。</span>
|
||||
</div>
|
||||
<div style="margin-top: 0.8em">
|
||||
<input type="file" name="logoFile" accept=".png"/>
|
||||
</div>
|
||||
<p class="comment">显示在系统界面上的图标,请使用PNG格式。</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<submit-btn></submit-btn>
|
||||
|
||||
@@ -41,6 +41,36 @@
|
||||
<checkbox name="showFinance" v-model="config.showFinance"></checkbox>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>浏览器图标</td>
|
||||
<td>
|
||||
<div v-if="config.faviconFileId > 0">
|
||||
<a :href="'/ui/image/' + config.faviconFileId" target="_blank"><img :src="'/ui/image/' + config.faviconFileId" style="width:32px;border:1px #ccc solid;"/></a>
|
||||
</div>
|
||||
<div v-else>
|
||||
<span class="disabled">还没有上传。</span>
|
||||
</div>
|
||||
<div style="margin-top: 0.8em">
|
||||
<input type="file" name="faviconFile" accept=".png"/>
|
||||
</div>
|
||||
<p class="comment">在浏览器标签栏显示的图标,请使用PNG格式。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Logo</td>
|
||||
<td>
|
||||
<div v-if="config.logoFileId > 0">
|
||||
<a :href="'/ui/image/' + config.logoFileId" target="_blank"><img :src="'/ui/image/' + config.logoFileId" style="width:32px;border:1px #ccc solid;"/></a>
|
||||
</div>
|
||||
<div v-else>
|
||||
<span class="disabled">还没有上传。</span>
|
||||
</div>
|
||||
<div style="margin-top: 0.8em">
|
||||
<input type="file" name="logoFile" accept=".png"/>
|
||||
</div>
|
||||
<p class="comment">显示在系统界面上的图标,请使用PNG格式。</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<p class="comment">修改后,可能需要等待数分钟才会生效。</p>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user