Compare commits

...
14 Commits
Author SHA1 Message Date
zhengkunwang 1c826525e3 style: 优化中国地图显示 (#4681) 2024-04-29 14:52:56 +08:00
zhengkunwang 3f0fd48cf3 fix: 修复 WAF 地图英文模式下的显示错误 (#4704) 2024-04-29 14:27:46 +08:00
zhengkunwang 211dbfdead feat: 伪静态增加提示 (#4678) 2024-04-29 14:27:39 +08:00
zhengkunwang aafec142cc fix: 解决低版本 OpenResty 创建网站报错的问题 (#4661) 2024-04-29 14:27:25 +08:00
ssongliu 384ff57df7 style: 优化网站列表描述信息显示 (#4726) 2024-04-29 12:21:53 +08:00
zhengkunwang 01ddd203ea fix: 解决反向代理匹配规则为空之后无法删除的问题 (#4777)
Refs https://github.com/1Panel-dev/1Panel/issues/4771
2024-04-29 12:18:11 +08:00
zhengkunwang 29aed616ac fix: 解决第二次上传同名文件不显示的问题 (#4737) 2024-04-29 12:18:01 +08:00
ssongliu 83f0df9d84 style: 优化概览页 CPU 显示 (#4721) 2024-04-29 12:16:15 +08:00
ssongliu 7aa16c8142 fix: Docker 配置自动过滤空行 (#4707)
Refs #4701
2024-04-29 12:16:10 +08:00
ssongliu 3bd505954f fix: 解决计划任务本地保存份数错误的问题 (#4692)
Refs #4671
2024-04-29 12:15:53 +08:00
John Bro 275c0522a3 fix: 快速命令管理页面中增加关键词筛选 (#4679)
Refs #3525
2024-04-29 12:15:25 +08:00
John Bro 85dec6815b fix: 创建网站可以使用相同域名问题修复 (#4669)
Refs #4624
2024-04-29 12:15:19 +08:00
ssongliu 5e4e9f762e fix: 解决概览页折线图选择失败的问题 (#4656)
Refs #4647
2024-04-29 12:15:11 +08:00
John Bro 7ae3722997 fix: SSH 连接列表显示优化 (#4650)
Refs #4546
2024-04-29 12:15:00 +08:00
31 changed files with 215 additions and 1746 deletions
+4 -4
View File
@@ -61,7 +61,7 @@ func (b *BaseApi) LoadDaemonJson(c *gin.Context) {
// @Success 200
// @Security ApiKeyAuth
// @Router /containers/daemonjson/update [post]
// @x-panel-log {"bodyKeys":["key", "value"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新 docker daemon.json 配置 [key]=>[value]","formatEN":"Updated the docker daemon.json configuration [key]=>[value]"}
// @x-panel-log {"bodyKeys":["key", "value"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新配置 [key]","formatEN":"Updated configuration [key]"}
func (b *BaseApi) UpdateDaemonJson(c *gin.Context) {
var req dto.SettingUpdate
if err := helper.CheckBindAndValidate(&req, c); err != nil {
@@ -84,7 +84,7 @@ func (b *BaseApi) UpdateDaemonJson(c *gin.Context) {
// @Success 200
// @Security ApiKeyAuth
// @Router /containers/logoption/update [post]
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新 docker daemon.json 日志配置","formatEN":"Updated the docker daemon.json log option"}
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新日志配置","formatEN":"Updated the log option"}
func (b *BaseApi) UpdateLogOption(c *gin.Context) {
var req dto.LogOption
if err := helper.CheckBind(&req, c); err != nil {
@@ -107,7 +107,7 @@ func (b *BaseApi) UpdateLogOption(c *gin.Context) {
// @Success 200
// @Security ApiKeyAuth
// @Router /containers/ipv6option/update [post]
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新 docker daemon.json ipv6 配置","formatEN":"Updated the docker daemon.json ipv6 option"}
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新 ipv6 配置","formatEN":"Updated the ipv6 option"}
func (b *BaseApi) UpdateIpv6Option(c *gin.Context) {
var req dto.Ipv6Option
if err := helper.CheckBind(&req, c); err != nil {
@@ -130,7 +130,7 @@ func (b *BaseApi) UpdateIpv6Option(c *gin.Context) {
// @Success 200
// @Security ApiKeyAuth
// @Router /containers/daemonjson/update/byfile [post]
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新 docker daemon.json 配置","formatEN":"Updated the docker daemon.json configuration"}
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新配置文件","formatEN":"Updated configuration file"}
func (b *BaseApi) UpdateDaemonJsonByFile(c *gin.Context) {
var req dto.DaemonJsonUpdateByFile
if err := helper.CheckBindAndValidate(&req, c); err != nil {
+1
View File
@@ -6,6 +6,7 @@ type SearchCommandWithPage struct {
Order string `json:"order"`
GroupID uint `json:"groupID"`
Info string `json:"info"`
Name string `json:"name"`
}
type CommandOperate struct {
+1 -1
View File
@@ -178,7 +178,7 @@ type WebsiteProxyConfig struct {
CacheTime int `json:"cacheTime" `
CacheUnit string `json:"cacheUnit"`
Name string `json:"name" validate:"required"`
Modifier string `json:"modifier" validate:"required"`
Modifier string `json:"modifier"`
Match string `json:"match" validate:"required"`
ProxyPass string `json:"proxyPass" validate:"required"`
ProxyHost string `json:"proxyHost" validate:"required"`
+10
View File
@@ -16,6 +16,7 @@ type ICommandRepo interface {
Update(id uint, vars map[string]interface{}) error
Delete(opts ...DBOption) error
Get(opts ...DBOption) (model.Command, error)
WithLikeName(name string) DBOption
}
func NewICommandRepo() ICommandRepo {
@@ -79,3 +80,12 @@ func (u *CommandRepo) Delete(opts ...DBOption) error {
}
return db.Delete(&model.Command{}).Error
}
func (a CommandRepo) WithLikeName(name string) DBOption {
return func(g *gorm.DB) *gorm.DB {
if len(name) == 0 {
return g
}
return g.Where("name like ? or command like ?", "%"+name+"%", "%"+name+"%")
}
}
+1 -1
View File
@@ -65,7 +65,7 @@ func (u *CommandService) SearchForTree() ([]dto.CommandTree, error) {
}
func (u *CommandService) SearchWithPage(search dto.SearchCommandWithPage) (int64, interface{}, error) {
total, commands, err := commandRepo.Page(search.Page, search.PageSize, commonRepo.WithLikeName(search.Info), commonRepo.WithByGroupID(search.GroupID), commonRepo.WithOrderRuleBy(search.OrderBy, search.Order))
total, commands, err := commandRepo.Page(search.Page, search.PageSize, commandRepo.WithLikeName(search.Name), commonRepo.WithLikeName(search.Info), commonRepo.WithByGroupID(search.GroupID), commonRepo.WithOrderRuleBy(search.OrderBy, search.Order))
if err != nil {
return 0, nil, err
}
-16
View File
@@ -2,7 +2,6 @@ package service
import (
"context"
"encoding/json"
"fmt"
"os"
"path"
@@ -276,21 +275,6 @@ func loadClientMap(backupAccounts string) (map[string]cronjobUploadHelper, error
if account.BackupPath != "/" {
pathItem = strings.TrimPrefix(account.BackupPath, "/")
}
if target == constant.Local {
varMap := make(map[string]interface{})
if err := json.Unmarshal([]byte(account.Vars), &varMap); err != nil {
return nil, err
}
if _, ok := varMap["dir"]; !ok {
return nil, errors.New("load local backup dir failed")
}
baseDir, ok := varMap["dir"].(string)
if ok {
pathItem = baseDir
} else {
return nil, fmt.Errorf("error type dir: %T", varMap["dir"])
}
}
clients[target] = cronjobUploadHelper{
client: client,
backupPath: pathItem,
+7
View File
@@ -288,6 +288,10 @@ func createWafConfig(website *model.Website, domains []model.WebsiteDomain) erro
if err != nil {
return err
}
if !common.CompareVersion(nginxInstall.Version, "1.21.4.3-2-0") {
return nil
}
wafDataPath := path.Join(nginxInstall.GetPath(), "1pwaf", "data")
fileOp := files.NewFileOp()
if !fileOp.Stat(wafDataPath) {
@@ -419,6 +423,9 @@ func delWafConfig(website model.Website, force bool) error {
if err != nil {
return err
}
if !common.CompareVersion(nginxInstall.Version, "1.21.4.3-2-0") {
return nil
}
wafDataPath := path.Join(nginxInstall.GetPath(), "1pwaf", "data")
fileOp := files.NewFileOp()
if !fileOp.Stat(wafDataPath) {
+1 -1
View File
@@ -54,7 +54,7 @@ func (c localClient) Upload(src, target string) (bool, error) {
}
}
if err := common.CopyFile(src, target); err != nil {
if err := common.CopyFile(src, targetFilePath); err != nil {
return false, fmt.Errorf("cp file failed, err: %v", err)
}
return true, nil
+1 -2
View File
@@ -314,6 +314,7 @@ func (f FileOp) DownloadFile(url, dst string) error {
if err != nil {
return err
}
defer resp.Body.Close()
out, err := os.Create(dst)
if err != nil {
@@ -324,8 +325,6 @@ func (f FileOp) DownloadFile(url, dst string) error {
if _, err = io.Copy(out, resp.Body); err != nil {
return fmt.Errorf("save download file [%s] error, err %s", dst, err.Error())
}
out.Close()
resp.Body.Close()
return nil
}
+3 -5
View File
@@ -3,7 +3,6 @@ package files
import (
"bufio"
"fmt"
"github.com/spf13/afero"
"io"
"net/http"
"os"
@@ -12,6 +11,8 @@ import (
"strconv"
"strings"
"sync"
"github.com/spf13/afero"
)
func IsSymlink(mode os.FileMode) bool {
@@ -144,8 +145,5 @@ func GetParentMode(path string) (os.FileMode, error) {
}
func IsInvalidChar(name string) bool {
if strings.Contains(name, "&") {
return true
}
return false
return strings.Contains(name, "&")
}
+8 -8
View File
@@ -1444,8 +1444,8 @@ const docTemplate = `{
"key",
"value"
],
"formatEN": "Updated the docker daemon.json configuration [key]=\u003e[value]",
"formatZH": "更新 docker daemon.json 配置 [key]=\u003e[value]",
"formatEN": "Updated configuration [key]",
"formatZH": "更新配置 [key]",
"paramKeys": []
}
}
@@ -1484,8 +1484,8 @@ const docTemplate = `{
"x-panel-log": {
"BeforeFunctions": [],
"bodyKeys": [],
"formatEN": "Updated the docker daemon.json configuration",
"formatZH": "更新 docker daemon.json 配置",
"formatEN": "Updated configuration file",
"formatZH": "更新配置文件",
"paramKeys": []
}
}
@@ -2094,8 +2094,8 @@ const docTemplate = `{
"x-panel-log": {
"BeforeFunctions": [],
"bodyKeys": [],
"formatEN": "Updated the docker daemon.json ipv6 option",
"formatZH": "更新 docker daemon.json ipv6 配置",
"formatEN": "Updated the ipv6 option",
"formatZH": "更新 ipv6 配置",
"paramKeys": []
}
}
@@ -2233,8 +2233,8 @@ const docTemplate = `{
"x-panel-log": {
"BeforeFunctions": [],
"bodyKeys": [],
"formatEN": "Updated the docker daemon.json log option",
"formatZH": "更新 docker daemon.json 日志配置",
"formatEN": "Updated the log option",
"formatZH": "更新日志配置",
"paramKeys": []
}
}
+8 -8
View File
@@ -1437,8 +1437,8 @@
"key",
"value"
],
"formatEN": "Updated the docker daemon.json configuration [key]=\u003e[value]",
"formatZH": "更新 docker daemon.json 配置 [key]=\u003e[value]",
"formatEN": "Updated configuration [key]",
"formatZH": "更新配置 [key]",
"paramKeys": []
}
}
@@ -1477,8 +1477,8 @@
"x-panel-log": {
"BeforeFunctions": [],
"bodyKeys": [],
"formatEN": "Updated the docker daemon.json configuration",
"formatZH": "更新 docker daemon.json 配置",
"formatEN": "Updated configuration file",
"formatZH": "更新配置文件",
"paramKeys": []
}
}
@@ -2087,8 +2087,8 @@
"x-panel-log": {
"BeforeFunctions": [],
"bodyKeys": [],
"formatEN": "Updated the docker daemon.json ipv6 option",
"formatZH": "更新 docker daemon.json ipv6 配置",
"formatEN": "Updated the ipv6 option",
"formatZH": "更新 ipv6 配置",
"paramKeys": []
}
}
@@ -2226,8 +2226,8 @@
"x-panel-log": {
"BeforeFunctions": [],
"bodyKeys": [],
"formatEN": "Updated the docker daemon.json log option",
"formatZH": "更新 docker daemon.json 日志配置",
"formatEN": "Updated the log option",
"formatZH": "更新日志配置",
"paramKeys": []
}
}
+8 -8
View File
@@ -5938,8 +5938,8 @@ paths:
bodyKeys:
- key
- value
formatEN: Updated the docker daemon.json configuration [key]=>[value]
formatZH: 更新 docker daemon.json 配置 [key]=>[value]
formatEN: Updated configuration [key]
formatZH: 更新配置 [key]
paramKeys: []
/containers/daemonjson/update/byfile:
post:
@@ -5964,8 +5964,8 @@ paths:
x-panel-log:
BeforeFunctions: []
bodyKeys: []
formatEN: Updated the docker daemon.json configuration
formatZH: 更新 docker daemon.json 配置
formatEN: Updated configuration file
formatZH: 更新配置文件
paramKeys: []
/containers/docker/operate:
post:
@@ -6353,8 +6353,8 @@ paths:
x-panel-log:
BeforeFunctions: []
bodyKeys: []
formatEN: Updated the docker daemon.json ipv6 option
formatZH: 更新 docker daemon.json ipv6 配置
formatEN: Updated the ipv6 option
formatZH: 更新 ipv6 配置
paramKeys: []
/containers/limit:
get:
@@ -6438,8 +6438,8 @@ paths:
x-panel-log:
BeforeFunctions: []
bodyKeys: []
formatEN: Updated the docker daemon.json log option
formatZH: 更新 docker daemon.json 日志配置
formatEN: Updated the log option
formatZH: 更新日志配置
paramKeys: []
/containers/network:
get:
+1
View File
@@ -24,6 +24,7 @@ export interface SearchWithPage {
pageSize: number;
orderBy?: string;
order?: string;
name?: string;
}
export interface CommonModel {
id: number;
+1
View File
@@ -139,6 +139,7 @@ export namespace Setting {
upload: string;
}
export interface UpgradeInfo {
testVersion: string;
newVersion: string;
latestVersion: string;
releaseNote: string;
File diff suppressed because it is too large Load Diff
@@ -83,7 +83,8 @@ const seriesStyle = [
function initChart() {
let itemChart = echarts?.getInstanceByDom(document.getElementById(props.id) as HTMLElement);
// 如果不存在,就进行初始化
const optionItem = itemChart?.getOption();
const itemSelect = optionItem?.legend;
if (itemChart == null) {
itemChart = echarts.init(document.getElementById(props.id) as HTMLElement);
}
@@ -109,10 +110,9 @@ function initChart() {
yAxis.push({
splitLine: {
show: true,
//分隔辅助线
lineStyle: {
type: 'dashed', //线的类型 虚线0
opacity: theme === 'dark' ? 0.1 : 1, //透明度
type: 'dashed',
opacity: theme === 'dark' ? 0.1 : 1,
},
},
...item,
@@ -120,7 +120,6 @@ function initChart() {
});
}
// 把配置和数据放这里
const option = {
title: [
{
@@ -168,7 +167,7 @@ function initChart() {
},
},
grid: props.option.grid || { left: '7%', right: '7%', bottom: '20%' },
legend: {
legend: itemSelect || {
right: 10,
itemWidth: 8,
textStyle: {
+5
View File
@@ -58,6 +58,8 @@ const message = {
fullscreen: 'Fullscreen',
quitFullscreen: 'Quit Fullscreen',
update: 'Edit',
showAll: 'Show All',
hideSome: 'Hide Some',
},
search: {
timeStart: 'Time start',
@@ -1934,6 +1936,9 @@ const message = {
acmeAccountType: 'Account Type',
keyType: 'Key algorithm',
tencentCloud: 'Tencent Cloud',
containWarn: 'The domain name contains the main domain, please re-enter',
rewriteHelper2:
'Applications such as WordPress installed from the app store have pseudo-static configuration by default. Repeated configuration may result in errors',
},
php: {
short_open_tag: 'Short tag support',
+4
View File
@@ -58,6 +58,8 @@ const message = {
fullscreen: '全屏',
quitFullscreen: '退出全屏',
update: '編輯',
showAll: '顯示所有',
hideSome: '隱藏部分',
},
search: {
timeStart: '開始時間',
@@ -1810,6 +1812,8 @@ const message = {
acmeAccountType: '賬號類型',
keyType: '密鑰演算法',
tencentCloud: '騰訊雲',
containWarn: '其他域名中包含主域名,请重新輸入',
rewriteHelper2: '從應用程式商店安裝的 WordPress 等應用,預設已經配置好偽靜態,重複配置可能會報錯',
},
php: {
short_open_tag: '短標簽支持',
+4
View File
@@ -58,6 +58,8 @@ const message = {
fullscreen: '全屏',
quitFullscreen: '退出全屏',
update: '编辑',
showAll: '显示所有',
hideSome: '隐藏部分',
},
search: {
timeStart: '开始时间',
@@ -1810,6 +1812,8 @@ const message = {
acmeAccountType: '账号类型',
keyType: '密钥算法',
tencentCloud: '腾讯云',
containWarn: '其他域名中包含主域名,请重新输入',
rewriteHelper2: '从应用商店安装的 WordPress 等应用,默认已经配置好伪静态,重复配置可能会报错',
},
php: {
short_open_tag: '短标签支持',
+11
View File
@@ -518,3 +518,14 @@ export function getAction(action: string) {
export function getLanguage() {
return localStorage.getItem('lang') || 'zh';
}
export function emptyLineFilter(str: string, spilt: string) {
let list = str.split(spilt);
let results = [];
for (let i = 0; i < list.length; i++) {
if (list[i].trim() !== '') {
results.push(list[i]);
}
}
return results.join(spilt);
}
@@ -46,6 +46,7 @@ import ConfirmDialog from '@/components/confirm-dialog/index.vue';
import { updateDaemonJson } from '@/api/modules/container';
import DrawerHeader from '@/components/drawer-header/index.vue';
import { FormInstance } from 'element-plus';
import { emptyLineFilter } from '@/utils/util';
const emit = defineEmits<{ (e: 'search'): void }>();
@@ -101,7 +102,7 @@ const onSave = async (formEl: FormInstance | undefined) => {
const onSubmit = async () => {
loading.value = true;
await updateDaemonJson('Mirrors', form.mirrors.replaceAll('\n', ','))
await updateDaemonJson('Mirrors', emptyLineFilter(form.mirrors, '\n').replaceAll('\n', ','))
.then(() => {
loading.value = false;
emit('search');
@@ -46,6 +46,7 @@ import ConfirmDialog from '@/components/confirm-dialog/index.vue';
import { updateDaemonJson } from '@/api/modules/container';
import DrawerHeader from '@/components/drawer-header/index.vue';
import { FormInstance } from 'element-plus';
import { emptyLineFilter } from '@/utils/util';
const emit = defineEmits<{ (e: 'search'): void }>();
@@ -97,7 +98,7 @@ const onSave = async () => {
const onSubmit = async () => {
loading.value = true;
await updateDaemonJson('Registries', form.registries.replaceAll('\n', ','))
await updateDaemonJson('Registries', emptyLineFilter(form.registries, '\n').replaceAll('\n', ','))
.then(() => {
loading.value = false;
handleClose();
+42 -15
View File
@@ -1,12 +1,7 @@
<template>
<el-row :gutter="10">
<el-col :xs="12" :sm="12" :md="6" :lg="6" :xl="6" align="center">
<el-popover
placement="bottom"
:width="currentInfo.cpuPercent.length < 36 ? 300 : (currentInfo.cpuPercent.length / 12) * 150"
trigger="hover"
v-if="chartsOption['cpu']"
>
<el-popover placement="bottom" :width="loadWidth()" trigger="hover" v-if="chartsOption['cpu']">
<div>
<el-tooltip
effect="dark"
@@ -14,7 +9,7 @@
v-if="baseInfo.cpuModelName.length > 40"
placement="top"
>
<el-tag>
<el-tag class="cpuModeTag">
{{ baseInfo.cpuModelName.substring(0, 40) + '...' }}
</el-tag>
</el-tooltip>
@@ -22,14 +17,24 @@
{{ baseInfo.cpuModelName }}
</el-tag>
</div>
<el-tag class="tagClass">
{{ $t('home.core') }} *{{ baseInfo.cpuCores }} {{ $t('home.logicCore') }} *{{
baseInfo.cpuLogicalCores
}}
</el-tag>
<el-tag class="cpuDetailTag">{{ $t('home.core') }} *{{ baseInfo.cpuCores }}</el-tag>
<el-tag class="cpuDetailTag">{{ $t('home.logicCore') }} *{{ baseInfo.cpuLogicalCores }}</el-tag>
<br />
<div v-for="(item, index) of currentInfo.cpuPercent" :key="index">
<el-tag class="tagCPUClass">CPU-{{ index }}: {{ formatNumber(item) }}%</el-tag>
<el-tag v-if="cpuShowAll || (!cpuShowAll && index < 32)" class="tagCPUClass">
CPU-{{ index }}: {{ formatNumber(item) }}%
</el-tag>
</div>
<div v-if="currentInfo.cpuPercent.length > 32" class="mt-1 float-right">
<el-button v-if="!cpuShowAll" @click="cpuShowAll = true" link type="primary" size="small">
{{ $t('commons.button.showAll') }}
<el-icon><DArrowRight /></el-icon>
</el-button>
<el-button v-if="cpuShowAll" @click="cpuShowAll = false" link type="primary" size="small">
{{ $t('commons.button.hideSome') }}
<el-icon><DArrowLeft /></el-icon>
</el-button>
</div>
<template #reference>
<v-charts
@@ -302,6 +307,8 @@ const currentInfo = ref<Dashboard.CurrentInfo>({
shotTime: new Date(),
});
const cpuShowAll = ref();
const chartsOption = ref({ cpu: null, memory: null, load: null });
const acceptParams = (current: Dashboard.CurrentInfo, base: Dashboard.BaseInfo, isInit: boolean): void => {
@@ -359,6 +366,14 @@ const goGPU = () => {
router.push({ name: 'GPU' });
};
const loadWidth = () => {
if (!cpuShowAll.value || currentInfo.value.cpuPercent.length < 32) {
return 310;
}
let line = Math.floor(currentInfo.value.cpuPercent.length / 16);
return line * 141 + 28;
};
function formatNumber(val: number) {
return Number(val.toFixed(2));
}
@@ -369,6 +384,18 @@ defineExpose({
</script>
<style scoped lang="scss">
.cpuModeTag {
justify-content: flex-start !important;
text-align: left !important;
width: 280px;
}
.cpuDetailTag {
justify-content: flex-start !important;
text-align: left !important;
width: 140px;
margin-top: 3px;
margin-left: 1px;
}
.tagClass {
margin-top: 3px;
}
@@ -378,8 +405,8 @@ defineExpose({
text-align: left !important;
float: left;
margin-top: 3px;
margin-left: 4px;
width: 100px;
margin-left: 1px;
width: 140px;
}
.buttonClass {
@@ -111,27 +111,24 @@ let uploadHelper = ref('');
const em = defineEmits(['close']);
const handleClose = () => {
open.value = false;
uploadRef.value!.clearFiles();
clearFiles();
em('close', false);
};
const state = reactive({
uploadEle: null,
});
const uploaderFiles = ref<UploadFiles>([]);
const isUploadFolder = ref(false);
const hoverIndex = ref(null);
const uploadType = ref('file');
const tmpFiles = ref<UploadFiles>([]);
const breakFlag = ref(false);
const upload = (command: string) => {
uploadType.value = command;
if (command == 'dir') {
state.uploadEle.webkitdirectory = true;
} else {
state.uploadEle.webkitdirectory = false;
}
isUploadFolder.value = true;
uploadRef.value.$el.querySelector('input').value = '';
uploadRef.value.$el.querySelector('input').click();
};
@@ -253,10 +250,11 @@ const fileOnChange = (_uploadFile: UploadFile, uploadFiles: UploadFiles) => {
const clearFiles = () => {
uploadRef.value!.clearFiles();
uploaderFiles.value = [];
};
const handleExceed: UploadProps['onExceed'] = () => {
uploadRef.value!.clearFiles();
clearFiles();
MsgWarning(i18n.global.t('file.uploadOverLimit'));
};
@@ -339,8 +337,7 @@ const submit = async () => {
loading.value = false;
uploadHelper.value = '';
if (success == files.length) {
uploadRef.value!.clearFiles();
uploaderFiles.value = [];
clearFiles();
MsgSuccess(i18n.global.t('file.uploadSuccess'));
}
}
@@ -16,13 +16,20 @@
</el-button>
</template>
<template #search>
<el-select v-model="group" @change="search()" clearable class="p-w-200">
<template #prefix>{{ $t('terminal.group') }}</template>
<el-option :label="$t('commons.table.all')" value=""></el-option>
<div v-for="item in groupList" :key="item.name">
<el-option :value="item.id" :label="item.name" />
</div>
</el-select>
<el-row :gutter="5">
<el-col :xs="24" :sm="20" :md="20" :lg="20" :xl="20">
<el-select v-model="group" @change="search()" clearable class="p-w-200">
<template #prefix>{{ $t('terminal.group') }}</template>
<el-option :label="$t('commons.table.all')" value=""></el-option>
<div v-for="item in groupList" :key="item.name">
<el-option :value="item.id" :label="item.name" />
</div>
</el-select>
</el-col>
<el-col :xs="24" :sm="4" :md="4" :lg="4" :xl="4">
<TableSearch @search="search()" v-model:searchName="commandReq.name" />
</el-col>
</el-row>
</template>
<template #main>
<ComplexTable
@@ -160,6 +167,10 @@ let commandInfo = reactive<Command.CommandOperate>({
command: '',
});
const commandReq = reactive({
name: '',
});
const cmdVisible = ref<boolean>(false);
const loadGroups = async () => {
@@ -274,6 +285,7 @@ const search = async (column?: any) => {
info: info.value,
orderBy: paginationConfig.orderBy,
order: paginationConfig.order,
name: commandReq.name,
};
loading.value = true;
await getCommandPage(params)
@@ -105,7 +105,7 @@
<span v-if="node.label.length <= 25">
<a @click="onClickConn(node, data)">{{ node.label }}</a>
</span>
<el-tooltip v-else :content="node.label" placement="top-start">
<el-tooltip v-else :content="node.label" placement="right">
<span>
<a @click="onClickConn(node, data)">
{{ node.label.substring(0, 22) }}...
@@ -126,7 +126,6 @@ const proxyForm = ref<FormInstance>();
const rules = ref({
name: [Rules.requiredInput, Rules.appName],
match: [Rules.requiredInput],
modifier: [Rules.requiredInput],
cacheTime: [Rules.requiredInput, checkNumberRange(1, 65535)],
proxyPass: [Rules.requiredInput],
proxyHost: [Rules.requiredInput],
@@ -1,7 +1,7 @@
<template>
<div>
<el-form-item :label="$t('website.rewriteMode')">
<el-select v-model="req.name" filterable @change="getRewriteConfig(req.name)">
<el-select v-model="req.name" filterable @change="getRewriteConfig(req.name)" class="p-w-200">
<el-option :label="$t('website.current')" :value="'current'"></el-option>
<el-option
v-for="(rewrite, index) in Rewrites"
@@ -11,6 +11,7 @@
></el-option>
</el-select>
</el-form-item>
<el-text type="warning">{{ $t('website.rewriteHelper2') }}</el-text>
<Codemirror
ref="codeRef"
v-loading="loading"
@@ -26,7 +27,7 @@
:extensions="extensions"
v-model="content"
/>
<div style="margin-top: 10px">
<div class="mt-2">
<el-form-item>
<el-alert :title="$t('website.rewriteHelper')" type="info" :closable="false" />
</el-form-item>
@@ -349,7 +349,7 @@ import { ElForm, FormInstance } from 'element-plus';
import { reactive, ref } from 'vue';
import Params from '@/views/app-store/detail/params/index.vue';
import Check from '../check/index.vue';
import { MsgSuccess } from '@/utils/message';
import { MsgError, MsgSuccess } from '@/utils/message';
import { GetGroupList } from '@/api/modules/group';
import { Group } from '@/api/interface/group';
import { SearchRuntimes } from '@/api/modules/runtime';
@@ -582,6 +582,16 @@ const changeAppType = (type: string) => {
}
};
function isSubsetOfStrArray(primaryDomain: string, otherDomains: string): boolean {
const arr: string[] = otherDomains.split('\n');
for (const item of arr) {
if (primaryDomain === item) {
return false;
}
}
return true;
}
const submit = async (formEl: FormInstance | undefined) => {
if (!formEl) return;
await formEl.validate((valid) => {
@@ -589,6 +599,12 @@ const submit = async (formEl: FormInstance | undefined) => {
return;
}
loading.value = true;
const flag = isSubsetOfStrArray(website.value.primaryDomain, website.value.otherDomains);
if (!flag) {
MsgError(i18n.global.t('website.containWarn'));
loading.value = false;
return false;
}
PreCheck({})
.then((res) => {
if (res.data) {
+6 -6
View File
@@ -111,11 +111,12 @@
</el-button>
</template>
</el-table-column>
<el-table-column :label="$t('website.remark')" prop="remark" min-width="120px">
<template #default="{ row }">
<MsgInfo :info="row.remark" />
</template>
</el-table-column>
<el-table-column
:label="$t('website.remark')"
prop="remark"
show-overflow-tooltip
min-width="120px"
></el-table-column>
<el-table-column
:label="$t('commons.table.protocol')"
prop="protocol"
@@ -194,7 +195,6 @@ import { dateFormatSimple } from '@/utils/util';
import { MsgSuccess } from '@/utils/message';
import { useI18n } from 'vue-i18n';
import { VideoPlay, VideoPause } from '@element-plus/icons-vue';
import MsgInfo from '@/components/msg-info/index.vue';
import { GetGroupList } from '@/api/modules/group';
import { Group } from '@/api/interface/group';
import { GlobalStore } from '@/store';