mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2026-10-20 08:00:48 +00:00
fix: container list search
This commit is contained in:
@@ -266,6 +266,7 @@ func (b *BaseApi) GetLoginSetting(c *gin.Context) {
|
||||
Language: settingInfo.Language,
|
||||
MenuTabs: settingInfo.MenuTabs,
|
||||
MenuAccordion: settingInfo.MenuAccordion,
|
||||
PanelCache: settingInfo.PanelCache,
|
||||
PanelName: settingInfo.PanelName,
|
||||
Theme: settingInfo.Theme,
|
||||
NeedCaptcha: needCaptcha,
|
||||
|
||||
@@ -4,6 +4,16 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
const DefaultPanelCache = `{"tabs":true,"pagination":true,"refresh":true,"search":false,"duration":"24h"}`
|
||||
|
||||
type PanelCache struct {
|
||||
Tabs *bool `json:"tabs"`
|
||||
Pagination *bool `json:"pagination"`
|
||||
Refresh *bool `json:"refresh"`
|
||||
Search *bool `json:"search"`
|
||||
Duration string `json:"duration"`
|
||||
}
|
||||
|
||||
type SettingInfo struct {
|
||||
SystemVersion string `json:"systemVersion"`
|
||||
DeveloperMode string `json:"developerMode"`
|
||||
@@ -18,6 +28,7 @@ type SettingInfo struct {
|
||||
Theme string `json:"theme"`
|
||||
MenuTabs string `json:"menuTabs"`
|
||||
MenuAccordion string `json:"menuAccordion"`
|
||||
PanelCache string `json:"panelCache"`
|
||||
Language string `json:"language"`
|
||||
DocSource string `json:"docSource"`
|
||||
|
||||
@@ -62,6 +73,7 @@ type SettingBaseInfo struct {
|
||||
Theme string `json:"theme"`
|
||||
MenuTabs string `json:"menuTabs"`
|
||||
MenuAccordion string `json:"menuAccordion"`
|
||||
PanelCache string `json:"panelCache"`
|
||||
Language string `json:"language"`
|
||||
HideMenu string `json:"hideMenu"`
|
||||
DocSource string `json:"docSource"`
|
||||
@@ -288,6 +300,7 @@ type LoginSetting struct {
|
||||
Language string `json:"language"`
|
||||
MenuTabs string `json:"menuTabs"`
|
||||
MenuAccordion string `json:"menuAccordion"`
|
||||
PanelCache string `json:"panelCache"`
|
||||
PanelName string `json:"panelName"`
|
||||
Theme string `json:"theme"`
|
||||
NeedCaptcha bool `json:"needCaptcha"`
|
||||
|
||||
@@ -120,6 +120,9 @@ func (u *SettingService) GetSettingInfo() (*dto.SettingInfo, error) {
|
||||
for _, set := range setting {
|
||||
settingMap[set.Key] = set.Value
|
||||
}
|
||||
if settingMap["PanelCache"] == "" {
|
||||
settingMap["PanelCache"] = dto.DefaultPanelCache
|
||||
}
|
||||
repairAndSortHideMenu(settingMap)
|
||||
var info dto.SettingInfo
|
||||
arr, err := json.Marshal(settingMap)
|
||||
@@ -155,6 +158,9 @@ func (u *SettingService) GetSettingBaseInfo() (*dto.SettingBaseInfo, error) {
|
||||
for _, set := range setting {
|
||||
settingMap[set.Key] = set.Value
|
||||
}
|
||||
if settingMap["PanelCache"] == "" {
|
||||
settingMap["PanelCache"] = dto.DefaultPanelCache
|
||||
}
|
||||
repairAndSortHideMenu(settingMap)
|
||||
var info dto.SettingBaseInfo
|
||||
arr, err := json.Marshal(settingMap)
|
||||
@@ -224,6 +230,27 @@ func (u *SettingService) Update(c *gin.Context, key, value string) error {
|
||||
if auth.IsAPICredentialSetting(key) {
|
||||
return buserr.New("ErrInvalidParams")
|
||||
}
|
||||
if key == "PanelCache" {
|
||||
var config dto.PanelCache
|
||||
decoder := json.NewDecoder(strings.NewReader(value))
|
||||
decoder.DisallowUnknownFields()
|
||||
if err := decoder.Decode(&config); err != nil {
|
||||
return buserr.New("ErrInvalidParams")
|
||||
}
|
||||
if err := decoder.Decode(new(any)); err != io.EOF {
|
||||
return buserr.New("ErrInvalidParams")
|
||||
}
|
||||
if config.Tabs == nil || config.Pagination == nil || config.Refresh == nil || config.Search == nil {
|
||||
return buserr.New("ErrInvalidParams")
|
||||
}
|
||||
switch config.Duration {
|
||||
case "24h", "week", "month", "forever":
|
||||
default:
|
||||
return buserr.New("ErrInvalidParams")
|
||||
}
|
||||
data, _ := json.Marshal(config)
|
||||
return settingRepo.UpdateOrCreate(key, string(data))
|
||||
}
|
||||
oldVal, err := settingRepo.Get(repo.WithByKey(key))
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -26,6 +26,7 @@ func Init() {
|
||||
}
|
||||
|
||||
var baseSettingKeys = map[string]struct{}{
|
||||
"PanelCache": {},
|
||||
"PanelName": {},
|
||||
"Theme": {},
|
||||
"MenuTabs": {},
|
||||
|
||||
@@ -77,6 +77,7 @@ export namespace Login {
|
||||
language: string;
|
||||
menuTabs: string;
|
||||
menuAccordion: string;
|
||||
panelCache: string;
|
||||
panelName: string;
|
||||
theme: string;
|
||||
isOffline: boolean;
|
||||
|
||||
@@ -41,6 +41,7 @@ export namespace Setting {
|
||||
theme: string;
|
||||
menuTabs: string;
|
||||
menuAccordion: string;
|
||||
panelCache: string;
|
||||
language: string;
|
||||
docSource: string;
|
||||
|
||||
@@ -86,6 +87,7 @@ export namespace Setting {
|
||||
theme: string;
|
||||
menuTabs: string;
|
||||
menuAccordion: string;
|
||||
panelCache: string;
|
||||
language: string;
|
||||
hideMenu: string;
|
||||
docSource: string;
|
||||
|
||||
@@ -20,57 +20,55 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onMounted, onUnmounted, ref } from 'vue';
|
||||
import { onActivated, onDeactivated, onMounted, onUnmounted, ref, watch } from 'vue';
|
||||
import { useRoute } from 'vue-router';
|
||||
import { panelCacheKey, readPanelCache, writePanelCache } from '@/utils/panel-cache';
|
||||
|
||||
defineOptions({ name: 'TableSetting' });
|
||||
|
||||
const refreshRateUnit = ref<number>(0);
|
||||
const refreshRateUnit = ref(0);
|
||||
const emit = defineEmits(['search']);
|
||||
const props = defineProps({
|
||||
title: String,
|
||||
rate: Number,
|
||||
});
|
||||
|
||||
let timer: NodeJS.Timer | null = null;
|
||||
|
||||
const changeRefresh = (command: number) => {
|
||||
refreshRateUnit.value = command || 0;
|
||||
if (refreshRateUnit.value !== 0) {
|
||||
if (timer) {
|
||||
clearInterval(Number(timer));
|
||||
timer = null;
|
||||
}
|
||||
timer = setInterval(() => {
|
||||
emit('search');
|
||||
}, 1000 * refreshRateUnit.value);
|
||||
} else {
|
||||
if (timer) {
|
||||
clearInterval(Number(timer));
|
||||
timer = null;
|
||||
}
|
||||
}
|
||||
localStorage.setItem(props.title, refreshRateUnit.value + '');
|
||||
const props = defineProps({ title: String, rate: Number });
|
||||
const route = useRoute();
|
||||
// Capture the owning page; useRoute continues to change while a page is deactivated.
|
||||
const pagePath = route.path;
|
||||
const cacheKey = () => panelCacheKey(`refresh:${pagePath}:${props.title || ''}`);
|
||||
let timer: ReturnType<typeof setInterval> | undefined;
|
||||
let active = false;
|
||||
const stopTimer = () => {
|
||||
clearInterval(timer);
|
||||
timer = undefined;
|
||||
};
|
||||
|
||||
onUnmounted(() => {
|
||||
clearInterval(Number(timer));
|
||||
timer = null;
|
||||
if (props.title) {
|
||||
localStorage.setItem(props.title, refreshRateUnit.value + '');
|
||||
const startTimer = () => {
|
||||
stopTimer();
|
||||
if (active && refreshRateUnit.value > 0) {
|
||||
timer = setInterval(() => emit('search'), 1000 * refreshRateUnit.value);
|
||||
}
|
||||
};
|
||||
const restore = () => {
|
||||
const rate = readPanelCache<number>('refresh', cacheKey());
|
||||
refreshRateUnit.value = Number.isFinite(rate) && rate >= 0 ? rate : props.rate || 0;
|
||||
startTimer();
|
||||
};
|
||||
const changeRefresh = (rate: number) => {
|
||||
refreshRateUnit.value = rate;
|
||||
writePanelCache('refresh', cacheKey(), rate);
|
||||
startTimer();
|
||||
};
|
||||
const activate = () => {
|
||||
if (active) return;
|
||||
active = true;
|
||||
restore();
|
||||
};
|
||||
watch(cacheKey, () => {
|
||||
if (active) restore();
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
if (props.title && localStorage.getItem(props.title) != null) {
|
||||
let rate = Number(localStorage.getItem(props.title));
|
||||
refreshRateUnit.value = rate ? Number(rate) : 0;
|
||||
changeRefresh(refreshRateUnit.value);
|
||||
return;
|
||||
}
|
||||
if (props.rate) {
|
||||
refreshRateUnit.value = props.rate;
|
||||
changeRefresh(refreshRateUnit.value);
|
||||
}
|
||||
onMounted(activate);
|
||||
onActivated(activate);
|
||||
onDeactivated(() => {
|
||||
active = false;
|
||||
stopTimer();
|
||||
});
|
||||
onUnmounted(stopTimer);
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@@ -167,6 +167,7 @@
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { panelCacheKey, writePanelCache } from '@/utils/panel-cache';
|
||||
import { computed, onDeactivated, onMounted, ref, useAttrs } from 'vue';
|
||||
import { useGlobalStore } from '@/composables/useGlobalStore';
|
||||
import { flattenVNodes, type FuTableOperationButton } from '@/components/table/shared';
|
||||
@@ -341,13 +342,33 @@ const handleRightClick = (row, column, event) => {
|
||||
openContextMenu(row, event);
|
||||
};
|
||||
|
||||
watch(
|
||||
() => props.data,
|
||||
() => {
|
||||
const pagination = props.paginationConfig;
|
||||
if (!pagination || !pagination.pageSize) return;
|
||||
const lastPage = Math.max(1, Math.ceil(pagination.total / pagination.pageSize));
|
||||
if (pagination.currentPage > lastPage) {
|
||||
pagination.currentPage = lastPage;
|
||||
emit('search');
|
||||
}
|
||||
},
|
||||
{ flush: 'post' },
|
||||
);
|
||||
|
||||
function currentChange() {
|
||||
emit('search');
|
||||
}
|
||||
|
||||
function sizeChange() {
|
||||
if (props.paginationConfig.cacheSizeKey) {
|
||||
writePanelCache(
|
||||
'pagination',
|
||||
panelCacheKey(`size:${props.paginationConfig.cacheSizeKey}`),
|
||||
props.paginationConfig.pageSize,
|
||||
);
|
||||
}
|
||||
props.paginationConfig.currentPage = 1;
|
||||
localStorage.setItem(props.paginationConfig.cacheSizeKey, props.paginationConfig.pageSize);
|
||||
emit('search');
|
||||
}
|
||||
|
||||
|
||||
@@ -52,6 +52,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { readCachedPageSize } from '@/utils/panel-cache';
|
||||
import TaskLog from '@/components/log/task/index.vue';
|
||||
import NodeSelect from '@/components/node-select/index.vue';
|
||||
|
||||
@@ -73,7 +74,7 @@ const data = ref();
|
||||
const paginationConfig = reactive({
|
||||
cacheSizeKey: 'task-list-page-size',
|
||||
currentPage: 1,
|
||||
pageSize: Number(localStorage.getItem('task-list-page-size')) || 20,
|
||||
pageSize: readCachedPageSize('task-list-page-size') || 20,
|
||||
total: 0,
|
||||
small: true,
|
||||
});
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { onActivated, onDeactivated } from 'vue';
|
||||
import GlobalStore from '@/store/modules/global';
|
||||
import { bindSearchReset, type SearchFields } from '@/utils/search-reset';
|
||||
|
||||
interface SearchResetOptions {
|
||||
scope?: () => string | number | undefined;
|
||||
onRevisit: () => unknown;
|
||||
}
|
||||
|
||||
export const useSearchReset = (fields: SearchFields, options: SearchResetOptions) => {
|
||||
const { currentNode } = storeToRefs(GlobalStore());
|
||||
const reset = bindSearchReset(options.scope ? [currentNode, options.scope] : [currentNode], fields);
|
||||
let deactivated = false;
|
||||
onDeactivated(() => {
|
||||
deactivated = true;
|
||||
});
|
||||
onActivated(() => {
|
||||
if (!deactivated) return;
|
||||
deactivated = false;
|
||||
reset();
|
||||
return options.onRevisit();
|
||||
});
|
||||
};
|
||||
@@ -2962,6 +2962,20 @@ const message = {
|
||||
remote: 'Remote SSH',
|
||||
},
|
||||
setting: {
|
||||
panelCache: {
|
||||
title: 'Cache settings',
|
||||
tabs: 'Tab cache',
|
||||
pagination: 'Pagination cache',
|
||||
refresh: 'Refresh interval cache',
|
||||
search: 'Search input cache',
|
||||
duration: 'Cache duration',
|
||||
'24h': '24h',
|
||||
week: 'One week',
|
||||
month: 'One month',
|
||||
forever: 'Forever',
|
||||
helper: 'Expires after the last state change. Expired values return to page defaults.',
|
||||
},
|
||||
|
||||
panel: 'Panel',
|
||||
user: 'Panel user',
|
||||
userChange: 'Change panel user',
|
||||
|
||||
@@ -3007,6 +3007,20 @@ const message = {
|
||||
remote: 'SSH remoto',
|
||||
},
|
||||
setting: {
|
||||
panelCache: {
|
||||
title: 'Configuración de caché',
|
||||
tabs: 'Caché de pestañas',
|
||||
pagination: 'Caché de paginación',
|
||||
refresh: 'Caché del intervalo de actualización',
|
||||
search: 'Caché del campo de búsqueda',
|
||||
duration: 'Duración de la caché',
|
||||
'24h': '24 horas',
|
||||
week: 'Una semana',
|
||||
month: 'Un mes',
|
||||
forever: 'Permanente',
|
||||
helper: 'El plazo se calcula desde el último cambio de estado. Al caducar, se restablecen los valores predeterminados.',
|
||||
},
|
||||
|
||||
panel: 'Panel',
|
||||
user: 'Usuario del panel',
|
||||
userChange: 'Cambiar usuario del panel',
|
||||
|
||||
@@ -2932,6 +2932,20 @@ const message = {
|
||||
remote: 'SSH از راه دور',
|
||||
},
|
||||
setting: {
|
||||
panelCache: {
|
||||
title: 'تنظیمات حافظهٔ نهان',
|
||||
tabs: 'حافظهٔ نهان زبانهها',
|
||||
pagination: 'حافظهٔ نهان صفحهبندی',
|
||||
refresh: 'حافظهٔ نهان فاصلهٔ بازخوانی',
|
||||
search: 'حافظهٔ نهان ورودی جستجو',
|
||||
duration: 'مدت نگهداری حافظهٔ نهان',
|
||||
'24h': '۲۴ ساعت',
|
||||
week: 'یک هفته',
|
||||
month: 'یک ماه',
|
||||
forever: 'دائمی',
|
||||
helper: 'مدت اعتبار از آخرین تغییر وضعیت محاسبه میشود. پس از انقضا، مقادیر پیشفرض بازیابی میشوند.',
|
||||
},
|
||||
|
||||
panel: 'پنل',
|
||||
user: 'کاربر پنل',
|
||||
userChange: 'تغییر کاربر پنل',
|
||||
|
||||
@@ -2937,6 +2937,20 @@ const message = {
|
||||
remote: 'リモートSSH',
|
||||
},
|
||||
setting: {
|
||||
panelCache: {
|
||||
title: 'キャッシュ設定',
|
||||
tabs: 'タブのキャッシュ',
|
||||
pagination: 'ページネーションのキャッシュ',
|
||||
refresh: '更新間隔のキャッシュ',
|
||||
search: '検索入力のキャッシュ',
|
||||
duration: 'キャッシュ期間',
|
||||
'24h': '24時間',
|
||||
week: '1週間',
|
||||
month: '1か月',
|
||||
forever: '無期限',
|
||||
helper: '有効期間は状態を最後に変更した時点から計算されます。期限が切れると既定値に戻ります。',
|
||||
},
|
||||
|
||||
panel: 'パネル',
|
||||
user: 'パネルユーザー',
|
||||
userChange: 'パネルユーザーを変更します',
|
||||
|
||||
@@ -2898,6 +2898,20 @@ const message = {
|
||||
remote: '원격 SSH',
|
||||
},
|
||||
setting: {
|
||||
panelCache: {
|
||||
title: '캐시 설정',
|
||||
tabs: '탭 캐시',
|
||||
pagination: '페이지 이동 캐시',
|
||||
refresh: '새로 고침 간격 캐시',
|
||||
search: '검색 입력 캐시',
|
||||
duration: '캐시 유지 기간',
|
||||
'24h': '24시간',
|
||||
week: '1주',
|
||||
month: '1개월',
|
||||
forever: '무기한',
|
||||
helper: '유효 기간은 상태를 마지막으로 변경한 시점부터 계산됩니다. 만료되면 기본값으로 돌아갑니다.',
|
||||
},
|
||||
|
||||
panel: '패널',
|
||||
user: '패널 사용자',
|
||||
userChange: '패널 사용자 변경',
|
||||
|
||||
@@ -2879,6 +2879,20 @@ const message = {
|
||||
remote: 'SSH ທາງໄກ',
|
||||
},
|
||||
setting: {
|
||||
panelCache: {
|
||||
title: 'ການຕັ້ງຄ່າແຄດ',
|
||||
tabs: 'ແຄດແຖບ',
|
||||
pagination: 'ແຄດການແບ່ງໜ້າ',
|
||||
refresh: 'ແຄດຊ່ວງເວລາຣີເຟຣຊ',
|
||||
search: 'ແຄດຂໍ້ຄວາມຄົ້ນຫາ',
|
||||
duration: 'ໄລຍະເວລາເກັບແຄດ',
|
||||
'24h': '24 ຊົ່ວໂມງ',
|
||||
week: 'ໜຶ່ງອາທິດ',
|
||||
month: 'ໜຶ່ງເດືອນ',
|
||||
forever: 'ຖາວອນ',
|
||||
helper: 'ໄລຍະເວລາຈະນັບຈາກການປ່ຽນສະຖານະຄັ້ງຫຼ້າສຸດ. ເມື່ອໝົດອາຍຸ ຈະກັບຄືນເປັນຄ່າເລີ່ມຕົ້ນ.',
|
||||
},
|
||||
|
||||
panel: 'ພາເນລ',
|
||||
user: 'ຜູ້ໃຊ້ພາເນລ',
|
||||
userChange: 'ປ່ຽນຜູ້ໃຊ້ພາເນລ',
|
||||
|
||||
@@ -3005,6 +3005,20 @@ const message = {
|
||||
remote: 'SSH jauh',
|
||||
},
|
||||
setting: {
|
||||
panelCache: {
|
||||
title: 'Tetapan cache',
|
||||
tabs: 'Cache tab',
|
||||
pagination: 'Cache halaman',
|
||||
refresh: 'Cache sela penyegaran',
|
||||
search: 'Cache input carian',
|
||||
duration: 'Tempoh cache',
|
||||
'24h': '24 jam',
|
||||
week: 'Satu minggu',
|
||||
month: 'Satu bulan',
|
||||
forever: 'Kekal',
|
||||
helper: 'Tempoh sah dikira dari perubahan keadaan terakhir. Selepas tamat tempoh, nilai lalai dipulihkan.',
|
||||
},
|
||||
|
||||
panel: 'Panel',
|
||||
user: 'Pengguna panel',
|
||||
userChange: 'Tukar pengguna panel',
|
||||
|
||||
@@ -3004,6 +3004,20 @@ const message = {
|
||||
remote: 'SSH remoto',
|
||||
},
|
||||
setting: {
|
||||
panelCache: {
|
||||
title: 'Configurações de cache',
|
||||
tabs: 'Cache de abas',
|
||||
pagination: 'Cache de paginação',
|
||||
refresh: 'Cache do intervalo de atualização',
|
||||
search: 'Cache do campo de pesquisa',
|
||||
duration: 'Duração do cache',
|
||||
'24h': '24 horas',
|
||||
week: 'Uma semana',
|
||||
month: 'Um mês',
|
||||
forever: 'Permanente',
|
||||
helper: 'O prazo é contado a partir da última alteração de estado. Após a expiração, os valores padrão são restaurados.',
|
||||
},
|
||||
|
||||
panel: 'Painel',
|
||||
user: 'Usuário do painel',
|
||||
userChange: 'Alterar usuário do painel',
|
||||
|
||||
@@ -2977,6 +2977,20 @@ const message = {
|
||||
remote: 'Удаленный SSH',
|
||||
},
|
||||
setting: {
|
||||
panelCache: {
|
||||
title: 'Настройки кэша',
|
||||
tabs: 'Кэш вкладок',
|
||||
pagination: 'Кэш пагинации',
|
||||
refresh: 'Кэш интервала обновления',
|
||||
search: 'Кэш поискового запроса',
|
||||
duration: 'Срок хранения кэша',
|
||||
'24h': '24 часа',
|
||||
week: 'Одна неделя',
|
||||
month: 'Один месяц',
|
||||
forever: 'Бессрочно',
|
||||
helper: 'Срок хранения отсчитывается с последнего изменения состояния. После его истечения восстанавливаются значения по умолчанию.',
|
||||
},
|
||||
|
||||
panel: 'Панель',
|
||||
user: 'Пользователь панели',
|
||||
userChange: 'Изменить пользователя панели',
|
||||
|
||||
@@ -2995,6 +2995,20 @@ const message = {
|
||||
remote: 'Uzak SSH',
|
||||
},
|
||||
setting: {
|
||||
panelCache: {
|
||||
title: 'Önbellek ayarları',
|
||||
tabs: 'Sekme önbelleği',
|
||||
pagination: 'Sayfalama önbelleği',
|
||||
refresh: 'Yenileme aralığı önbelleği',
|
||||
search: 'Arama alanı önbelleği',
|
||||
duration: 'Önbellek süresi',
|
||||
'24h': '24 saat',
|
||||
week: 'Bir hafta',
|
||||
month: 'Bir ay',
|
||||
forever: 'Süresiz',
|
||||
helper: 'Geçerlilik süresi son durum değişikliğinden itibaren hesaplanır. Süre dolduğunda varsayılan değerler geri yüklenir.',
|
||||
},
|
||||
|
||||
panel: 'Panel',
|
||||
user: 'Panel kullanıcısı',
|
||||
userChange: 'Panel kullanıcısını değiştir',
|
||||
|
||||
@@ -2786,6 +2786,20 @@ const message = {
|
||||
stopSSHWarn: '是否斷開此SSH連接',
|
||||
},
|
||||
setting: {
|
||||
panelCache: {
|
||||
title: '快取設定',
|
||||
tabs: '標籤頁快取',
|
||||
pagination: '分頁快取',
|
||||
refresh: '重新整理頻率快取',
|
||||
search: '搜尋輸入框快取',
|
||||
duration: '快取時間',
|
||||
'24h': '24h',
|
||||
week: '一週',
|
||||
month: '一個月',
|
||||
forever: '永久',
|
||||
helper: '有效期從狀態最後一次修改開始計算;過期後恢復預設值。',
|
||||
},
|
||||
|
||||
panel: '面板',
|
||||
user: '面板使用者',
|
||||
userChange: '修改面板使用者',
|
||||
|
||||
@@ -2817,6 +2817,20 @@ const message = {
|
||||
stopSSHWarn: '是否断开此SSH连接',
|
||||
},
|
||||
setting: {
|
||||
panelCache: {
|
||||
title: '缓存设置',
|
||||
tabs: '标签页缓存',
|
||||
pagination: '翻页缓存',
|
||||
refresh: '刷新频率缓存',
|
||||
search: '搜索输入框缓存',
|
||||
duration: '缓存时间',
|
||||
'24h': '24h',
|
||||
week: '一周',
|
||||
month: '一月',
|
||||
forever: '永久',
|
||||
helper: '有效期从状态最后一次修改开始计算;过期后恢复默认值。',
|
||||
},
|
||||
|
||||
panel: '面板',
|
||||
user: '面板用户',
|
||||
userChange: '修改面板用户',
|
||||
|
||||
@@ -55,6 +55,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { applyPanelCacheSettings } from '@/utils/panel-cache';
|
||||
import { ref, computed, onBeforeUnmount, onMounted, watch } from 'vue';
|
||||
import { RouteRecordRaw, useRoute, useRouter } from 'vue-router';
|
||||
import { loadingSvg } from '@/utils/svg';
|
||||
@@ -141,6 +142,7 @@ const search = async () => {
|
||||
settingInfo = res.data;
|
||||
version.value = res.data.systemVersion;
|
||||
menuAccordion.value = res.data.menuAccordion === 'Enable';
|
||||
applyPanelCacheSettings(res.data.panelCache);
|
||||
} catch (error) {
|
||||
version.value = '';
|
||||
}
|
||||
|
||||
@@ -54,6 +54,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { prunePanelCache } from '@/utils/panel-cache';
|
||||
import { onMounted, computed, ref, watch, onBeforeUnmount } from 'vue';
|
||||
import { Sidebar, Footer, AppMain, MobileHeader, Tabs } from './components';
|
||||
import TerminalHost from '@/components/terminal/host.vue';
|
||||
@@ -106,6 +107,7 @@ const loadingText = computed(() =>
|
||||
);
|
||||
|
||||
let timer: NodeJS.Timer | null = null;
|
||||
let cacheCleanupTimer: ReturnType<typeof setInterval> | undefined;
|
||||
|
||||
const classObj = computed(() => {
|
||||
return {
|
||||
@@ -186,10 +188,12 @@ const loadStatus = async () => {
|
||||
}
|
||||
};
|
||||
onBeforeUnmount(() => {
|
||||
clearInterval(cacheCleanupTimer);
|
||||
clearInterval(Number(timer));
|
||||
timer = null;
|
||||
});
|
||||
onMounted(() => {
|
||||
cacheCleanupTimer = setInterval(() => prunePanelCache(), 300000);
|
||||
if (openMenuTabs.value && !tabsStore.activeTabPath) {
|
||||
handleMenuClick('/');
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { panelCacheKey, readPanelCache, writePanelCache, removePanelCache, prunePanelCache } from '@/utils/panel-cache';
|
||||
import router from '@/routers/router';
|
||||
import NProgress from '@/config/nprogress';
|
||||
import { useGlobalStore } from '@/composables/useGlobalStore';
|
||||
@@ -102,29 +103,34 @@ router.beforeEach(async (to, from) => {
|
||||
if (to.name === 'Expired') {
|
||||
return true;
|
||||
}
|
||||
const activeMenuKey = 'cachedRoute' + (to.meta.activeMenu || '');
|
||||
const activeMenuKey = panelCacheKey(String(to.meta.activeMenu || ''));
|
||||
if (to.query.uncached != undefined) {
|
||||
const query = { ...to.query };
|
||||
delete query.uncached;
|
||||
localStorage.removeItem(activeMenuKey);
|
||||
removePanelCache('tabs', activeMenuKey);
|
||||
return { path: to.path, query };
|
||||
}
|
||||
|
||||
const cachedRoute = localStorage.getItem(activeMenuKey);
|
||||
const cachedRoute = readPanelCache<string>('tabs', activeMenuKey);
|
||||
if (
|
||||
to.meta.activeMenu &&
|
||||
to.meta.activeMenu != from.meta.activeMenu &&
|
||||
typeof cachedRoute === 'string' &&
|
||||
cachedRoute &&
|
||||
cachedRoute !== to.path &&
|
||||
!isRedirecting
|
||||
) {
|
||||
const cachedRouteInfo = router.resolve(cachedRoute);
|
||||
if (cachedRouteInfo.matched.length > 0 && hasRouteAccess(cachedRouteInfo)) {
|
||||
if (
|
||||
cachedRouteInfo.matched.length > 0 &&
|
||||
cachedRouteInfo.meta.activeMenu === to.meta.activeMenu &&
|
||||
hasRouteAccess(cachedRouteInfo)
|
||||
) {
|
||||
isRedirecting = true;
|
||||
NProgress.done();
|
||||
return cachedRoute;
|
||||
}
|
||||
localStorage.removeItem(activeMenuKey);
|
||||
removePanelCache('tabs', activeMenuKey);
|
||||
}
|
||||
|
||||
if (!hasRouteAccess(to)) {
|
||||
@@ -135,7 +141,13 @@ router.beforeEach(async (to, from) => {
|
||||
return true;
|
||||
});
|
||||
|
||||
router.afterEach((to) => {
|
||||
router.afterEach((to, _from, failure) => {
|
||||
prunePanelCache();
|
||||
if (failure) {
|
||||
isRedirecting = false;
|
||||
NProgress.done();
|
||||
return;
|
||||
}
|
||||
if (to.meta.activeMenu && !to.meta.ignoreTab && !isRedirecting) {
|
||||
let notMathParam = true;
|
||||
if (to.matched.some((record) => record.path.includes(':'))) {
|
||||
@@ -143,13 +155,13 @@ router.afterEach((to) => {
|
||||
}
|
||||
if (notMathParam) {
|
||||
if (to.meta.activeMenu === '/cronjobs' && to.path === '/cronjobs/cronjob/operate') {
|
||||
localStorage.setItem('cachedRoute' + to.meta.activeMenu, '/cronjobs/cronjob');
|
||||
writePanelCache('tabs', panelCacheKey(String(to.meta.activeMenu)), '/cronjobs/cronjob');
|
||||
} else if (to.meta.activeMenu === '/containers' && to.path === '/containers/container/operate') {
|
||||
localStorage.setItem('cachedRoute' + to.meta.activeMenu, '/containers/container');
|
||||
writePanelCache('tabs', panelCacheKey(String(to.meta.activeMenu)), '/containers/container');
|
||||
} else if (to.meta.activeMenu === '/toolbox' && to.path === '/toolbox/clam/setting') {
|
||||
localStorage.setItem('cachedRoute' + to.meta.activeMenu, '/toolbox/clam');
|
||||
writePanelCache('tabs', panelCacheKey(String(to.meta.activeMenu)), '/toolbox/clam');
|
||||
} else {
|
||||
localStorage.setItem('cachedRoute' + to.meta.activeMenu, to.path);
|
||||
writePanelCache('tabs', panelCacheKey(String(to.meta.activeMenu)), to.path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { RouteRecordRaw } from 'vue-router';
|
||||
import { DeviceType } from '@/enums/app';
|
||||
import type { PanelCacheSettings } from '@/utils/panel-cache';
|
||||
export interface ThemeConfigProp {
|
||||
panelName: string;
|
||||
primary: string;
|
||||
@@ -34,6 +35,8 @@ export interface GlobalState {
|
||||
isFullScreen: boolean;
|
||||
openMenuTabs: boolean;
|
||||
menuAccordion: boolean;
|
||||
panelCache: PanelCacheSettings;
|
||||
cacheUserID: string;
|
||||
watermark: Watermark | null;
|
||||
watermarkShow: boolean;
|
||||
isLoading: boolean;
|
||||
|
||||
@@ -6,6 +6,7 @@ import { DeviceType } from '@/enums/app';
|
||||
import i18n, { setActiveLocale } from '@/lang';
|
||||
import { isMasterOnlyPermissionCode, setMasterOnlyPermissionCodes, toManageCode } from '@/utils/permission-codes';
|
||||
import { clearPageStateCache } from '@/utils/page-state-cache';
|
||||
import { defaultPanelCache } from '@/utils/panel-cache';
|
||||
|
||||
const CN_DOCS_URL = 'https://docs.fit2cloud.com/1panel';
|
||||
const INTL_DOCS_URL = 'https://1panel.pro/docs/v2';
|
||||
@@ -33,6 +34,8 @@ const GlobalStore = defineStore('GlobalState', {
|
||||
isFullScreen: false,
|
||||
openMenuTabs: false,
|
||||
menuAccordion: false,
|
||||
panelCache: { ...defaultPanelCache },
|
||||
cacheUserID: '',
|
||||
watermark: null,
|
||||
watermarkShow: false,
|
||||
isLoading: false,
|
||||
@@ -123,6 +126,7 @@ const GlobalStore = defineStore('GlobalState', {
|
||||
},
|
||||
clearAuthInfo() {
|
||||
clearPageStateCache();
|
||||
this.cacheUserID = '';
|
||||
this.permissions = [];
|
||||
this.masterOnlyPermissions = [];
|
||||
this.nodeRoles = [];
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { bindSearchReset } from '@/utils/search-reset';
|
||||
import router from '@/routers/router';
|
||||
import { useGlobalStore } from '@/composables/useGlobalStore';
|
||||
import { bindSearchState } from '@/utils/search-reset';
|
||||
import { panelCacheKey } from '@/utils/panel-cache';
|
||||
import { defineStore } from 'pinia';
|
||||
import { ref, reactive, toRef } from 'vue';
|
||||
import { MsgError } from '@/utils/message';
|
||||
@@ -49,8 +48,7 @@ export const ProcessStore = defineStore('ProcessStore', () => {
|
||||
port: undefined,
|
||||
});
|
||||
|
||||
const { currentNode } = useGlobalStore();
|
||||
bindSearchReset([() => router.currentRoute.value.path, currentNode], {
|
||||
const searchState = bindSearchState(() => panelCacheKey('host/process'), {
|
||||
pid: toRef(psSearch, 'pid'),
|
||||
name: toRef(psSearch, 'name'),
|
||||
username: toRef(psSearch, 'username'),
|
||||
@@ -321,6 +319,7 @@ export const ProcessStore = defineStore('ProcessStore', () => {
|
||||
};
|
||||
|
||||
return {
|
||||
restoreSearchState: searchState.restore,
|
||||
isConnected,
|
||||
isConnecting,
|
||||
psData,
|
||||
|
||||
@@ -0,0 +1,130 @@
|
||||
import GlobalStore from '@/store/modules/global';
|
||||
|
||||
export type CacheCategory = 'tabs' | 'pagination' | 'refresh' | 'search';
|
||||
export interface PanelCacheSettings {
|
||||
tabs: boolean;
|
||||
pagination: boolean;
|
||||
refresh: boolean;
|
||||
search: boolean;
|
||||
duration: '24h' | 'week' | 'month' | 'forever';
|
||||
}
|
||||
export const defaultPanelCache: PanelCacheSettings = {
|
||||
tabs: true,
|
||||
pagination: true,
|
||||
refresh: true,
|
||||
search: false,
|
||||
duration: '24h',
|
||||
};
|
||||
const categories: CacheCategory[] = ['tabs', 'pagination', 'refresh', 'search'];
|
||||
const durations = { '24h': 86400000, week: 604800000, month: 2592000000, forever: Infinity };
|
||||
const prefix = '1panel:page-cache:v1:';
|
||||
interface CacheEntry {
|
||||
category: CacheCategory;
|
||||
updatedAt: number;
|
||||
value: unknown;
|
||||
}
|
||||
|
||||
export const applyPanelCacheSettings = (raw: string) => {
|
||||
let value: Partial<PanelCacheSettings> = {};
|
||||
try {
|
||||
value = JSON.parse(raw) || {};
|
||||
} catch {
|
||||
// Older servers do not return this setting yet.
|
||||
}
|
||||
const settings = { ...defaultPanelCache };
|
||||
for (const category of categories) {
|
||||
if (typeof value[category] === 'boolean') settings[category] = value[category];
|
||||
}
|
||||
if (Object.hasOwn(durations, value.duration || '')) settings.duration = value.duration;
|
||||
const store = GlobalStore();
|
||||
const changed =
|
||||
settings.duration !== store.panelCache.duration ||
|
||||
categories.some((category) => settings[category] !== store.panelCache[category]);
|
||||
if (changed) store.panelCache = settings;
|
||||
// Repeated settings loads share the normal cleanup interval.
|
||||
prunePanelCache(changed);
|
||||
};
|
||||
|
||||
export const panelCacheKey = (key: string): string => {
|
||||
const { cacheUserID, currentNode } = GlobalStore();
|
||||
return JSON.stringify([cacheUserID, currentNode, key]);
|
||||
};
|
||||
const storageKey = (category: CacheCategory, key: string) => prefix + JSON.stringify([category, key]);
|
||||
const validEntry = (entry: CacheEntry, settings: PanelCacheSettings, now: number) => {
|
||||
return (
|
||||
entry &&
|
||||
categories.includes(entry.category) &&
|
||||
settings[entry.category] &&
|
||||
Number.isFinite(entry.updatedAt) &&
|
||||
entry.updatedAt <= now &&
|
||||
now - entry.updatedAt < durations[settings.duration]
|
||||
);
|
||||
};
|
||||
|
||||
export const readPanelCache = <T>(category: CacheCategory, key: string): T | undefined => {
|
||||
const store = GlobalStore();
|
||||
if (!store.cacheUserID || !store.panelCache[category]) return;
|
||||
try {
|
||||
const target = storageKey(category, key);
|
||||
const raw = localStorage.getItem(target);
|
||||
if (!raw) return;
|
||||
const entry: CacheEntry = JSON.parse(raw);
|
||||
if (entry.category === category && validEntry(entry, store.panelCache, Date.now())) return entry.value as T;
|
||||
localStorage.removeItem(target);
|
||||
} catch {
|
||||
// Storage can be unavailable or contain invalid data; use page defaults.
|
||||
}
|
||||
};
|
||||
|
||||
export const writePanelCache = (category: CacheCategory, key: string, value: unknown) => {
|
||||
const store = GlobalStore();
|
||||
if (!store.cacheUserID || !store.panelCache[category]) return;
|
||||
try {
|
||||
// Repeated visits and unchanged values must not extend the expiration time.
|
||||
const previous = readPanelCache(category, key);
|
||||
if (previous !== undefined && JSON.stringify(previous) === JSON.stringify(value)) return;
|
||||
localStorage.setItem(storageKey(category, key), JSON.stringify({ category, updatedAt: Date.now(), value }));
|
||||
} catch {
|
||||
// A full or disabled localStorage must not block page interactions.
|
||||
}
|
||||
};
|
||||
|
||||
export const removePanelCache = (category: CacheCategory, key: string) => {
|
||||
try {
|
||||
localStorage.removeItem(storageKey(category, key));
|
||||
} catch {
|
||||
/* Storage is optional. */
|
||||
}
|
||||
};
|
||||
|
||||
let lastPruned = 0;
|
||||
export const prunePanelCache = (force = false) => {
|
||||
const now = Date.now();
|
||||
if (!force && now - lastPruned < 300000) return;
|
||||
lastPruned = now;
|
||||
const settings = GlobalStore().panelCache;
|
||||
try {
|
||||
for (let index = localStorage.length - 1; index >= 0; index--) {
|
||||
const key = localStorage.key(index);
|
||||
if (!key) continue;
|
||||
if (key.startsWith('1panel:search-state:v2:') || key.startsWith('cachedRoute')) {
|
||||
// Legacy entries have neither ownership nor timestamps and cannot be safely restored.
|
||||
localStorage.removeItem(key);
|
||||
} else if (key.startsWith(prefix)) {
|
||||
try {
|
||||
if (validEntry(JSON.parse(localStorage.getItem(key)), settings, now)) continue;
|
||||
} catch {
|
||||
/* Remove malformed entries too. */
|
||||
}
|
||||
localStorage.removeItem(key);
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
/* Storage is optional. */
|
||||
}
|
||||
};
|
||||
|
||||
export const readCachedPageSize = (key: string): number | undefined => {
|
||||
const value = readPanelCache<number>('pagination', panelCacheKey(`size:${key}`));
|
||||
return Number.isInteger(value) && value > 0 ? value : undefined;
|
||||
};
|
||||
@@ -22,6 +22,7 @@ export const syncAuthInfo = async (currentNode?: string) => {
|
||||
const storeCurrentNode = globalStore.currentNode;
|
||||
if (!globalStore.isEnterprise) {
|
||||
const res = await getUserInfo();
|
||||
globalStore.cacheUserID = `community:${res.data.id}`;
|
||||
globalStore.setAuthInfo({
|
||||
isAdmin: res.data.role === 'ADMIN',
|
||||
permissions: res.data.permissions || [],
|
||||
@@ -31,6 +32,7 @@ export const syncAuthInfo = async (currentNode?: string) => {
|
||||
return res.data;
|
||||
}
|
||||
const res = await getEnterpriseUserInfo(currentNode ?? storeCurrentNode);
|
||||
globalStore.cacheUserID = `enterprise:${res.data.id}`;
|
||||
globalStore.setAuthInfo({
|
||||
isAdmin: res.data.role === 'ADMIN',
|
||||
permissions: res.data.permissions || [],
|
||||
|
||||
@@ -1,12 +1,165 @@
|
||||
import { watch, type Ref, type WatchSource } from 'vue';
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { nextTick, onActivated, onDeactivated, onScopeDispose, watch, type Ref } from 'vue';
|
||||
import { panelCacheKey, readPanelCache, writePanelCache } from '@/utils/panel-cache';
|
||||
import GlobalStore from '@/store/modules/global';
|
||||
|
||||
export type SearchFields = Record<string, Ref<string | number | undefined>>;
|
||||
type SearchValues = Record<string, string | number | undefined>;
|
||||
|
||||
export const bindSearchReset = (sources: WatchSource[], fields: SearchFields) => {
|
||||
const defaults = Object.values(fields).map((field) => ({ field, value: field.value }));
|
||||
const reset = () => {
|
||||
for (const { field, value } of defaults) field.value = value;
|
||||
// Keep categories separate so changing search text does not renew pagination's lifetime.
|
||||
const searchStorage = {
|
||||
save(key: string, values: SearchValues) {
|
||||
for (const category of ['search', 'pagination'] as const) {
|
||||
const entries = Object.entries(values).filter(
|
||||
([name]) => (name === 'page' || name === 'pageSize') === (category === 'pagination'),
|
||||
);
|
||||
if (entries.length) {
|
||||
writePanelCache(
|
||||
category,
|
||||
key,
|
||||
Object.fromEntries(entries.map(([name, value]) => [name, value ?? null])),
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
read(key: string): SearchValues {
|
||||
const values = {
|
||||
...readPanelCache<SearchValues>('search', key),
|
||||
...readPanelCache<SearchValues>('pagination', key),
|
||||
};
|
||||
return Object.fromEntries(
|
||||
Object.entries(values)
|
||||
.filter(
|
||||
([, value]) =>
|
||||
value === null ||
|
||||
typeof value === 'string' ||
|
||||
(typeof value === 'number' && Number.isFinite(value)),
|
||||
)
|
||||
.map(([name, value]) => [name, value === null ? undefined : value]),
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
export const bindSearchState = (key: () => string | undefined, fields: SearchFields, storage = searchStorage) => {
|
||||
const defaults = Object.fromEntries(Object.entries(fields).map(([name, field]) => [name, field.value]));
|
||||
const names = Object.keys(fields).sort((left, right) => Number(left === 'page') - Number(right === 'page'));
|
||||
let pending: { key: string; values: SearchValues } | undefined;
|
||||
let queued = false;
|
||||
const flush = () => {
|
||||
if (!pending) return;
|
||||
const snapshot = pending;
|
||||
pending = undefined;
|
||||
storage.save(snapshot.key, snapshot.values);
|
||||
};
|
||||
watch(sources, reset, { flush: 'sync' });
|
||||
return reset;
|
||||
let restoring = false;
|
||||
let activeKey: string | undefined;
|
||||
let active = true;
|
||||
let resuming = false;
|
||||
let resumeVersion = 0;
|
||||
const pause = () => {
|
||||
flush();
|
||||
active = false;
|
||||
resuming = false;
|
||||
resumeVersion++;
|
||||
};
|
||||
onScopeDispose(pause);
|
||||
const restore = () => {
|
||||
// Commit the previous node/resource before restoring another one.
|
||||
flush();
|
||||
activeKey = key();
|
||||
if (!activeKey) return;
|
||||
const saved = storage.read(activeKey) || defaults;
|
||||
restoring = true;
|
||||
try {
|
||||
// Restore pagination last: search/filter watchers may reset it to page one.
|
||||
for (const name of names) {
|
||||
const value = Object.hasOwn(saved, name) ? saved[name] : defaults[name];
|
||||
const initial = defaults[name];
|
||||
const invalidPage =
|
||||
(name === 'page' || name === 'pageSize') &&
|
||||
(typeof value !== 'number' || !Number.isInteger(value) || value < 1);
|
||||
fields[name].value =
|
||||
invalidPage || (initial !== undefined && value !== undefined && typeof value !== typeof initial)
|
||||
? initial
|
||||
: value;
|
||||
}
|
||||
} finally {
|
||||
restoring = false;
|
||||
}
|
||||
};
|
||||
watch(
|
||||
key,
|
||||
() => {
|
||||
if (active || resuming) restore();
|
||||
},
|
||||
{ immediate: true, flush: 'sync' },
|
||||
);
|
||||
watch(
|
||||
() => Object.fromEntries(Object.entries(fields).map(([name, field]) => [name, field.value])),
|
||||
(values, previous) => {
|
||||
if (restoring || !active || !activeKey) return;
|
||||
const changed = Object.entries(values).filter(([name, value]) => value !== previous[name]);
|
||||
const paginationChanged = changed.some(([name]) => name === 'page' || name === 'pageSize');
|
||||
const searchChanged = changed.some(([name]) => name !== 'page' && name !== 'pageSize');
|
||||
const snapshot = Object.fromEntries(
|
||||
Object.entries(values).filter(([name]) =>
|
||||
name === 'page' || name === 'pageSize' ? paginationChanged : searchChanged,
|
||||
),
|
||||
);
|
||||
pending = { key: activeKey, values: { ...pending?.values, ...snapshot } };
|
||||
if (queued) return;
|
||||
queued = true;
|
||||
queueMicrotask(() => {
|
||||
queued = false;
|
||||
flush();
|
||||
});
|
||||
},
|
||||
{ flush: 'sync' },
|
||||
);
|
||||
return {
|
||||
restore,
|
||||
pause,
|
||||
resume: async () => {
|
||||
const version = ++resumeVersion;
|
||||
resuming = true;
|
||||
active = false;
|
||||
restore();
|
||||
const restoredKey = activeKey;
|
||||
const page = fields.page?.value;
|
||||
await nextTick();
|
||||
if (version !== resumeVersion) return false;
|
||||
// Search watchers may reset the page while restoring a changed query.
|
||||
if (activeKey === restoredKey && fields.page && page !== undefined) fields.page.value = page;
|
||||
active = true;
|
||||
resuming = false;
|
||||
return true;
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
interface SearchStateOptions {
|
||||
scope?: () => string | number | undefined;
|
||||
onRevisit: () => unknown;
|
||||
}
|
||||
|
||||
/** Keep queries across page visits and reload data when a cached page becomes active. */
|
||||
export const useSearchState = (page: string, fields: SearchFields, options: SearchStateOptions) => {
|
||||
const { cacheUserID } = storeToRefs(GlobalStore());
|
||||
const binding = bindSearchState(() => {
|
||||
const scope = options.scope?.();
|
||||
if (options.scope && scope === undefined) return undefined;
|
||||
// Track account and node changes, including initial auth synchronisation.
|
||||
if (!cacheUserID.value) return undefined;
|
||||
return panelCacheKey(JSON.stringify([page, scope ?? '']));
|
||||
}, fields);
|
||||
let deactivated = false;
|
||||
onDeactivated(() => {
|
||||
deactivated = true;
|
||||
binding.pause();
|
||||
});
|
||||
onActivated(async () => {
|
||||
if (!deactivated) return;
|
||||
deactivated = false;
|
||||
if (await binding.resume()) return options.onRevisit();
|
||||
});
|
||||
};
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { applyPanelCacheSettings } from '@/utils/panel-cache';
|
||||
import {
|
||||
getLicenseStatus,
|
||||
getMasterLicenseStatus,
|
||||
@@ -86,6 +87,7 @@ const loadDataFromDB = async () => {
|
||||
globalStore.entrance = res.data.securityEntrance;
|
||||
globalStore.openMenuTabs = res.data.menuTabs === 'Enable';
|
||||
globalStore.menuAccordion = res.data.menuAccordion === 'Enable';
|
||||
applyPanelCacheSettings(res.data.panelCache);
|
||||
};
|
||||
|
||||
export async function loadProductProFromDB() {
|
||||
|
||||
@@ -172,7 +172,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useSearchReset } from '@/composables/useSearchReset';
|
||||
import { useSearchState } from '@/utils/search-reset';
|
||||
import { computed, ref, watch } from 'vue';
|
||||
import { Refresh, Search } from '@element-plus/icons-vue';
|
||||
import { ElMessageBox } from 'element-plus';
|
||||
@@ -193,7 +193,8 @@ const searching = ref(false);
|
||||
const operating = ref('');
|
||||
const keyword = ref('');
|
||||
const marketKeyword = ref('');
|
||||
useSearchReset(
|
||||
useSearchState(
|
||||
'ai/agents/agent/config/tabs/plugins',
|
||||
{ keyword, marketKeyword },
|
||||
{
|
||||
scope: () => agentId.value || undefined,
|
||||
|
||||
@@ -138,7 +138,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useSearchReset } from '@/composables/useSearchReset';
|
||||
import { useSearchState } from '@/utils/search-reset';
|
||||
import { computed, ref, watch } from 'vue';
|
||||
import { Refresh, Search } from '@element-plus/icons-vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
@@ -169,7 +169,8 @@ const getDefaultMarketSource = (): HermesSkillMarketSource => {
|
||||
const marketSource = ref<HermesSkillMarketSource>(getDefaultMarketSource());
|
||||
const marketSearched = ref(false);
|
||||
const agentId = ref(0);
|
||||
useSearchReset(
|
||||
useSearchState(
|
||||
'ai/agents/agent/config/tabs/skills/hermes',
|
||||
{ installedKeyword, marketKeyword },
|
||||
{
|
||||
scope: () => agentId.value || undefined,
|
||||
|
||||
@@ -142,7 +142,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useSearchReset } from '@/composables/useSearchReset';
|
||||
import { useSearchState } from '@/utils/search-reset';
|
||||
import { computed, ref, watch } from 'vue';
|
||||
import { Refresh, Search } from '@element-plus/icons-vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
@@ -181,7 +181,8 @@ const getDefaultMarketSource = (): SkillMarketSource => {
|
||||
const marketSource = ref<SkillMarketSource>(getDefaultMarketSource());
|
||||
const marketSearched = ref(false);
|
||||
const agentId = ref(0);
|
||||
useSearchReset(
|
||||
useSearchState(
|
||||
'ai/agents/agent/config/tabs/skills/openclaw',
|
||||
{ installedKeyword, marketKeyword },
|
||||
{
|
||||
scope: () => agentId.value || undefined,
|
||||
|
||||
@@ -272,7 +272,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useSearchReset } from '@/composables/useSearchReset';
|
||||
import { useSearchState } from '@/utils/search-reset';
|
||||
import { toRef, defineAsyncComponent, onMounted, reactive, ref } from 'vue';
|
||||
import { useRoute, useRouter } from 'vue-router';
|
||||
import { deleteAgentCheck, pageAgents, resetAgentToken, unbindAgentWebsite, updateAgentRemark } from '@/api/modules/ai';
|
||||
@@ -400,7 +400,11 @@ const paginationConfig = reactive({
|
||||
pageSize: 10,
|
||||
total: 0,
|
||||
});
|
||||
useSearchReset({ search: searchName, page: toRef(paginationConfig, 'currentPage') }, { onRevisit: () => search() });
|
||||
useSearchState(
|
||||
'ai/agents/agent/index',
|
||||
{ search: searchName, page: toRef(paginationConfig, 'currentPage'), pageSize: toRef(paginationConfig, 'pageSize') },
|
||||
{ onRevisit: () => search() },
|
||||
);
|
||||
|
||||
const checkNoApp = async () => {
|
||||
try {
|
||||
|
||||
@@ -69,7 +69,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useSearchReset } from '@/composables/useSearchReset';
|
||||
import { useSearchState } from '@/utils/search-reset';
|
||||
import { toRef, onMounted, reactive, ref } from 'vue';
|
||||
import { deleteAgentAccount, getAgentProviders, pageAgentAccounts } from '@/api/modules/ai';
|
||||
import { AI } from '@/api/interface/ai';
|
||||
@@ -111,7 +111,11 @@ const paginationConfig = reactive({
|
||||
pageSize: 10,
|
||||
total: 0,
|
||||
});
|
||||
useSearchReset({ search: searchName, page: toRef(paginationConfig, 'currentPage') }, { onRevisit: () => search() });
|
||||
useSearchState(
|
||||
'ai/agents/model/index',
|
||||
{ search: searchName, page: toRef(paginationConfig, 'currentPage'), pageSize: toRef(paginationConfig, 'pageSize') },
|
||||
{ onRevisit: () => search() },
|
||||
);
|
||||
|
||||
const search = async () => {
|
||||
const req: AI.AgentAccountSearch = {
|
||||
|
||||
@@ -98,6 +98,8 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { toRef } from 'vue';
|
||||
import { useSearchState } from '@/utils/search-reset';
|
||||
import { AI } from '@/api/interface/ai';
|
||||
import {
|
||||
deleteMcpServer,
|
||||
@@ -129,11 +131,18 @@ const bindDomainRef = ref();
|
||||
const configRef = ref();
|
||||
const items = ref<AI.McpServer[]>([]);
|
||||
const paginationConfig = reactive({
|
||||
cacheSizeKey: 'mcp-server-page-size',
|
||||
currentPage: 1,
|
||||
pageSize: Number(localStorage.getItem('mcp-server-page-size')) || 20,
|
||||
pageSize: 20,
|
||||
total: 0,
|
||||
});
|
||||
useSearchState(
|
||||
'ai/mcp/server/index',
|
||||
{
|
||||
page: toRef(paginationConfig, 'currentPage'),
|
||||
pageSize: toRef(paginationConfig, 'pageSize'),
|
||||
},
|
||||
{ onRevisit: () => search() },
|
||||
);
|
||||
|
||||
const getUrl = (row: AI.McpServer) => {
|
||||
if (row.outputTransport == 'sse') {
|
||||
|
||||
@@ -186,7 +186,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { useSearchReset } from '@/composables/useSearchReset';
|
||||
import { useSearchState } from '@/utils/search-reset';
|
||||
import AppStatus from '@/components/app-status/index.vue';
|
||||
import AddDialog from '@/views/ai/model/ollama/add/index.vue';
|
||||
import Conn from '@/views/ai/model/ollama/conn/index.vue';
|
||||
@@ -231,13 +231,16 @@ const bindDomainRef = ref();
|
||||
const taskLogRef = ref();
|
||||
const data = ref();
|
||||
const paginationConfig = reactive({
|
||||
cacheSizeKey: 'model-page-size',
|
||||
currentPage: 1,
|
||||
pageSize: Number(localStorage.getItem('page-size')) || 20,
|
||||
pageSize: 20,
|
||||
total: 0,
|
||||
});
|
||||
const searchName = ref();
|
||||
useSearchReset({ search: searchName, page: toRef(paginationConfig, 'currentPage') }, { onRevisit: () => search() });
|
||||
useSearchState(
|
||||
'ai/model/ollama/index',
|
||||
{ search: searchName, page: toRef(paginationConfig, 'currentPage'), pageSize: toRef(paginationConfig, 'pageSize') },
|
||||
{ onRevisit: () => search() },
|
||||
);
|
||||
const appInstallID = ref(0);
|
||||
|
||||
const opRef = ref();
|
||||
|
||||
@@ -77,6 +77,8 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { toRef } from 'vue';
|
||||
import { useSearchState } from '@/utils/search-reset';
|
||||
import OperateDialog from './operate/index.vue';
|
||||
import ComposeLogs from '@/components/log/compose/index.vue';
|
||||
import PortJumpDialog from '@/components/port-jump/index.vue';
|
||||
@@ -101,6 +103,14 @@ const paginationConfig = reactive({
|
||||
pageSize: 10,
|
||||
total: 0,
|
||||
});
|
||||
useSearchState(
|
||||
'ai/model/tensorrt/index',
|
||||
{
|
||||
page: toRef(paginationConfig, 'currentPage'),
|
||||
pageSize: toRef(paginationConfig, 'pageSize'),
|
||||
},
|
||||
{ onRevisit: () => search() },
|
||||
);
|
||||
const searchName = ref();
|
||||
const opRef = ref();
|
||||
const dialogRef = ref();
|
||||
|
||||
@@ -70,7 +70,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { useSearchReset } from '@/composables/useSearchReset';
|
||||
import { useSearchState } from '@/utils/search-reset';
|
||||
import { App } from '@/api/interface/app';
|
||||
import { toRef, onMounted, reactive, ref } from 'vue';
|
||||
import { searchApp, syncApp, syncCutomAppStore, syncLocalApp, getCurrentNodeCustomAppConfig } from '@/api/modules/app';
|
||||
@@ -91,9 +91,8 @@ import { useGlobalStore } from '@/composables/useGlobalStore';
|
||||
const { isProductPro, isOffline, isMobile, isEnterprise } = useGlobalStore();
|
||||
|
||||
const paginationConfig = reactive({
|
||||
cacheSizeKey: 'app-page-size',
|
||||
currentPage: 1,
|
||||
pageSize: Number(localStorage.getItem('app-page-size')) || 60,
|
||||
pageSize: 60,
|
||||
total: 0,
|
||||
});
|
||||
|
||||
@@ -105,8 +104,13 @@ const req = reactive({
|
||||
resource: 'all',
|
||||
showCurrentArch: false,
|
||||
});
|
||||
useSearchReset(
|
||||
{ search: toRef(req, 'name'), page: toRef(paginationConfig, 'currentPage') },
|
||||
useSearchState(
|
||||
'app-store/apps/index',
|
||||
{
|
||||
search: toRef(req, 'name'),
|
||||
page: toRef(paginationConfig, 'currentPage'),
|
||||
pageSize: toRef(paginationConfig, 'pageSize'),
|
||||
},
|
||||
{ onRevisit: () => search(req) },
|
||||
);
|
||||
|
||||
@@ -133,7 +137,6 @@ const search = async (req: App.AppReq) => {
|
||||
loading.value = true;
|
||||
req.pageSize = paginationConfig.pageSize;
|
||||
req.page = paginationConfig.currentPage;
|
||||
localStorage.setItem('app-page-size', req.pageSize + '');
|
||||
|
||||
const customReq = {
|
||||
page: req.page,
|
||||
|
||||
@@ -139,7 +139,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { useSearchReset } from '@/composables/useSearchReset';
|
||||
import { useSearchState } from '@/utils/search-reset';
|
||||
import AppCard from '@/views/app-store/installed/app/card.vue';
|
||||
import Backups from '@/components/backup/index.vue';
|
||||
import Uploads from '@/components/upload/index.vue';
|
||||
@@ -181,9 +181,8 @@ const sortContainer = ref();
|
||||
let sortableInstance: Sortable | null = null;
|
||||
let timer: NodeJS.Timer | null = null;
|
||||
const paginationConfig = reactive({
|
||||
cacheSizeKey: 'app-installed-page-size',
|
||||
currentPage: 1,
|
||||
pageSize: Number(localStorage.getItem('app-installed-page-size')) || 20,
|
||||
pageSize: 20,
|
||||
total: 0,
|
||||
});
|
||||
const open = ref(false);
|
||||
@@ -211,8 +210,13 @@ const searchReq = reactive({
|
||||
update: false,
|
||||
sync: false,
|
||||
});
|
||||
useSearchReset(
|
||||
{ search: toRef(searchReq, 'name'), page: toRef(paginationConfig, 'currentPage') },
|
||||
useSearchState(
|
||||
'app-store/installed/index',
|
||||
{
|
||||
search: toRef(searchReq, 'name'),
|
||||
page: toRef(paginationConfig, 'currentPage'),
|
||||
pageSize: toRef(paginationConfig, 'pageSize'),
|
||||
},
|
||||
{ onRevisit: () => search() },
|
||||
);
|
||||
const router = useRouter();
|
||||
@@ -238,8 +242,6 @@ const search = async () => {
|
||||
searchReq.page = paginationConfig.currentPage;
|
||||
searchReq.pageSize = paginationConfig.pageSize;
|
||||
|
||||
localStorage.setItem('app-installed-page-size', String(searchReq.pageSize));
|
||||
|
||||
const res = await searchAppInstalled(searchReq);
|
||||
data.value = res.data.items;
|
||||
paginationConfig.total = res.data.total;
|
||||
|
||||
@@ -522,7 +522,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { useSearchReset } from '@/composables/useSearchReset';
|
||||
import { useSearchState } from '@/utils/search-reset';
|
||||
import { computed, h, ref } from 'vue';
|
||||
import CodemirrorPro from '@/components/codemirror-pro/index.vue';
|
||||
import ContainerLog from '@/components/log/container/index.vue';
|
||||
@@ -577,7 +577,7 @@ const dialogBackupRef = ref();
|
||||
const uploadRef = ref();
|
||||
|
||||
const searchName = ref('');
|
||||
useSearchReset({ search: searchName }, { onRevisit: () => search() });
|
||||
useSearchState('container/compose/index', { search: searchName }, { onRevisit: () => search() });
|
||||
const includeAppStore = ref(localStorage.getItem('includeAppStore') !== 'false');
|
||||
const showType = ref('compose');
|
||||
const containerStats = ref<any[]>([]);
|
||||
|
||||
@@ -474,7 +474,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { useSearchReset } from '@/composables/useSearchReset';
|
||||
import { useSearchState } from '@/utils/search-reset';
|
||||
import PruneDialog from '@/views/container/container/prune/index.vue';
|
||||
import RenameDialog from '@/views/container/container/rename/index.vue';
|
||||
import UpgradeDialog from '@/views/container/container/upgrade/index.vue';
|
||||
@@ -527,16 +527,14 @@ const portFilter = ref('');
|
||||
const showIPv6Ports = ref(true);
|
||||
const selects = ref<any>([]);
|
||||
const paginationConfig = reactive({
|
||||
cacheSizeKey: 'container-page-size',
|
||||
currentPage: 1,
|
||||
pageSize: Number(localStorage.getItem('container-page-size')) || 20,
|
||||
pageSize: 20,
|
||||
total: 0,
|
||||
state: 'all',
|
||||
orderBy: 'name',
|
||||
order: 'ascending',
|
||||
});
|
||||
const searchName = ref();
|
||||
useSearchReset({ search: searchName, page: toRef(paginationConfig, 'currentPage') }, { onRevisit: () => search() });
|
||||
const dialogUpgradeRef = ref();
|
||||
const dialogCommitRef = ref();
|
||||
const dialogPortJumpRef = ref();
|
||||
@@ -552,6 +550,19 @@ const taskLogRef = ref();
|
||||
|
||||
const tags = ref([]);
|
||||
const activeTag = ref('all');
|
||||
useSearchState(
|
||||
'container/container/index',
|
||||
{
|
||||
search: searchName,
|
||||
page: toRef(paginationConfig, 'currentPage'),
|
||||
pageSize: toRef(paginationConfig, 'pageSize'),
|
||||
state: toRef(paginationConfig, 'state'),
|
||||
activeTag,
|
||||
orderBy: toRef(paginationConfig, 'orderBy'),
|
||||
order: toRef(paginationConfig, 'order'),
|
||||
},
|
||||
{ onRevisit: () => search() },
|
||||
);
|
||||
|
||||
const activeDropdownContainerId = ref('');
|
||||
const statFields = [
|
||||
|
||||
@@ -157,7 +157,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { useSearchReset } from '@/composables/useSearchReset';
|
||||
import { useSearchState } from '@/utils/search-reset';
|
||||
import { toRef, reactive, ref, computed } from 'vue';
|
||||
import { dateFormat } from '@/utils/date';
|
||||
import { newUUID } from '@/utils/id';
|
||||
@@ -192,16 +192,20 @@ const data = ref();
|
||||
const names = ref();
|
||||
const repos = ref();
|
||||
const paginationConfig = reactive({
|
||||
cacheSizeKey: 'container-image-page-size',
|
||||
currentPage: 1,
|
||||
pageSize: Number(localStorage.getItem('container-image-page-size')) || 20,
|
||||
pageSize: 20,
|
||||
total: 0,
|
||||
name: '',
|
||||
orderBy: 'createdAt',
|
||||
order: 'null',
|
||||
});
|
||||
useSearchReset(
|
||||
{ search: toRef(paginationConfig, 'name'), page: toRef(paginationConfig, 'currentPage') },
|
||||
useSearchState(
|
||||
'container/image/index',
|
||||
{
|
||||
search: toRef(paginationConfig, 'name'),
|
||||
page: toRef(paginationConfig, 'currentPage'),
|
||||
pageSize: toRef(paginationConfig, 'pageSize'),
|
||||
},
|
||||
{ onRevisit: () => search() },
|
||||
);
|
||||
const columns = ref([]);
|
||||
|
||||
@@ -95,7 +95,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { useSearchReset } from '@/composables/useSearchReset';
|
||||
import { useSearchState } from '@/utils/search-reset';
|
||||
import CreateDialog from '@/views/container/network/create/index.vue';
|
||||
import DetailDrawer from '@/views/container/network/detail/index.vue';
|
||||
import { toRef, reactive, ref } from 'vue';
|
||||
@@ -115,13 +115,16 @@ const taskLogRef = ref();
|
||||
const data = ref();
|
||||
const selects = ref<any>([]);
|
||||
const paginationConfig = reactive({
|
||||
cacheSizeKey: 'container-network-page-size',
|
||||
currentPage: 1,
|
||||
pageSize: Number(localStorage.getItem('container-network-page-size')) || 20,
|
||||
pageSize: 20,
|
||||
total: 0,
|
||||
});
|
||||
const searchName = ref();
|
||||
useSearchReset({ search: searchName, page: toRef(paginationConfig, 'currentPage') }, { onRevisit: () => search() });
|
||||
useSearchState(
|
||||
'container/network/index',
|
||||
{ search: searchName, page: toRef(paginationConfig, 'currentPage'), pageSize: toRef(paginationConfig, 'pageSize') },
|
||||
{ onRevisit: () => search() },
|
||||
);
|
||||
|
||||
const opRef = ref();
|
||||
const isActive = ref(false);
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { useSearchReset } from '@/composables/useSearchReset';
|
||||
import { useSearchState } from '@/utils/search-reset';
|
||||
import OperatorDialog from '@/views/container/repo/operator/index.vue';
|
||||
import { toRef, reactive, ref } from 'vue';
|
||||
import { dateFormat } from '@/utils/date';
|
||||
@@ -72,13 +72,16 @@ const loading = ref();
|
||||
const data = ref();
|
||||
const selects = ref<any>([]);
|
||||
const paginationConfig = reactive({
|
||||
cacheSizeKey: 'image-repo-page-size',
|
||||
currentPage: 1,
|
||||
pageSize: Number(localStorage.getItem('image-repo-page-size')) || 20,
|
||||
pageSize: 20,
|
||||
total: 0,
|
||||
});
|
||||
const searchName = ref();
|
||||
useSearchReset({ search: searchName, page: toRef(paginationConfig, 'currentPage') }, { onRevisit: () => search() });
|
||||
useSearchState(
|
||||
'container/repo/index',
|
||||
{ search: searchName, page: toRef(paginationConfig, 'currentPage'), pageSize: toRef(paginationConfig, 'pageSize') },
|
||||
{ onRevisit: () => search() },
|
||||
);
|
||||
|
||||
const opRef = ref();
|
||||
const confirmDialog = ref();
|
||||
|
||||
@@ -81,7 +81,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { useSearchReset } from '@/composables/useSearchReset';
|
||||
import { useSearchState } from '@/utils/search-reset';
|
||||
import { toRef, reactive, ref } from 'vue';
|
||||
import { dateFormat, getCurrentDateFormatted } from '@/utils/date';
|
||||
import { downloadWithContent } from '@/utils/file';
|
||||
@@ -105,13 +105,16 @@ const isActive = ref(false);
|
||||
const isExist = ref(false);
|
||||
|
||||
const paginationConfig = reactive({
|
||||
cacheSizeKey: 'compose-template-page-size',
|
||||
currentPage: 1,
|
||||
pageSize: Number(localStorage.getItem('compose-template-page-size')) || 20,
|
||||
pageSize: 20,
|
||||
total: 0,
|
||||
});
|
||||
const searchName = ref();
|
||||
useSearchReset({ search: searchName, page: toRef(paginationConfig, 'currentPage') }, { onRevisit: () => search() });
|
||||
useSearchState(
|
||||
'container/template/index',
|
||||
{ search: searchName, page: toRef(paginationConfig, 'currentPage'), pageSize: toRef(paginationConfig, 'pageSize') },
|
||||
{ onRevisit: () => search() },
|
||||
);
|
||||
|
||||
const search = async () => {
|
||||
if (!isActive.value || !isExist.value) {
|
||||
|
||||
@@ -124,7 +124,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { useSearchReset } from '@/composables/useSearchReset';
|
||||
import { useSearchState } from '@/utils/search-reset';
|
||||
import CreateDialog from '@/views/container/volume/create/index.vue';
|
||||
import CodemirrorDrawer from '@/components/codemirror-pro/drawer.vue';
|
||||
import DockerStatus from '@/views/container/docker-status/index.vue';
|
||||
@@ -152,13 +152,16 @@ const opRef = ref();
|
||||
const data = ref();
|
||||
const selects = ref<any>([]);
|
||||
const paginationConfig = reactive({
|
||||
cacheSizeKey: 'container-volume-page-size',
|
||||
currentPage: 1,
|
||||
pageSize: Number(localStorage.getItem('container-volume-page-size')) || 20,
|
||||
pageSize: 20,
|
||||
total: 0,
|
||||
});
|
||||
const searchName = ref();
|
||||
useSearchReset({ search: searchName, page: toRef(paginationConfig, 'currentPage') }, { onRevisit: () => search() });
|
||||
useSearchState(
|
||||
'container/volume/index',
|
||||
{ search: searchName, page: toRef(paginationConfig, 'currentPage'), pageSize: toRef(paginationConfig, 'pageSize') },
|
||||
{ onRevisit: () => search() },
|
||||
);
|
||||
const isActive = ref(false);
|
||||
const isExist = ref(false);
|
||||
|
||||
|
||||
@@ -263,7 +263,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { useSearchReset } from '@/composables/useSearchReset';
|
||||
import { useSearchState } from '@/utils/search-reset';
|
||||
import Records from '@/views/cronjob/cronjob/record/index.vue';
|
||||
import Backups from '@/views/cronjob/cronjob/backup/index.vue';
|
||||
import Import from '@/views/cronjob/cronjob/import/index.vue';
|
||||
@@ -310,9 +310,8 @@ const groupOptions = ref();
|
||||
const dialogGroupRef = ref();
|
||||
const pageState = usePageState(() => ({
|
||||
paginationConfig: {
|
||||
cacheSizeKey: 'cronjob-page-size',
|
||||
currentPage: 1,
|
||||
pageSize: Number(localStorage.getItem('cronjob-page-size')) || 20,
|
||||
pageSize: 20,
|
||||
total: 0,
|
||||
orderBy: 'createdAt',
|
||||
order: 'null',
|
||||
@@ -323,7 +322,11 @@ const pageState = usePageState(() => ({
|
||||
}));
|
||||
const paginationConfig = pageState.paginationConfig;
|
||||
const { defaultGroupID, searchName, searchGroupID } = toRefs(pageState);
|
||||
useSearchReset({ search: searchName, page: toRef(paginationConfig, 'currentPage') }, { onRevisit: () => search() });
|
||||
useSearchState(
|
||||
'cronjob/cronjob/index',
|
||||
{ search: searchName, page: toRef(paginationConfig, 'currentPage'), pageSize: toRef(paginationConfig, 'pageSize') },
|
||||
{ onRevisit: () => search() },
|
||||
);
|
||||
|
||||
const search = async (column?: any) => {
|
||||
if (column) {
|
||||
|
||||
@@ -256,6 +256,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { panelCacheKey, writePanelCache, readCachedPageSize } from '@/utils/panel-cache';
|
||||
import { reactive, ref } from 'vue';
|
||||
import { useMediaQuery } from '@vueuse/core';
|
||||
import { Cronjob } from '@/api/interface/cronjob';
|
||||
@@ -309,7 +310,7 @@ const formatInterval = (interval?: number) => {
|
||||
};
|
||||
|
||||
const acceptParams = async (params: DialogProps): Promise<void> => {
|
||||
let itemSize = Number(localStorage.getItem(searchInfo.cacheSizeKey));
|
||||
let itemSize = readCachedPageSize(searchInfo.cacheSizeKey);
|
||||
if (itemSize) {
|
||||
searchInfo.pageSize = itemSize;
|
||||
}
|
||||
@@ -341,7 +342,7 @@ const acceptParams = async (params: DialogProps): Promise<void> => {
|
||||
|
||||
const handleSizeChange = (val: number) => {
|
||||
searchInfo.pageSize = val;
|
||||
localStorage.setItem(searchInfo.cacheSizeKey, val + '');
|
||||
writePanelCache('pagination', panelCacheKey(`size:${searchInfo.cacheSizeKey}`), val);
|
||||
search(true);
|
||||
};
|
||||
const handleCurrentChange = (val: number) => {
|
||||
|
||||
@@ -124,7 +124,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useSearchReset } from '@/composables/useSearchReset';
|
||||
import { useSearchState } from '@/utils/search-reset';
|
||||
import { dateFormat, getCurrentDateFormatted } from '@/utils/date';
|
||||
import { deepCopy } from '@/utils/misc';
|
||||
import { newUUID } from '@/utils/id';
|
||||
@@ -156,13 +156,16 @@ const scriptSync = ref();
|
||||
|
||||
const data = ref();
|
||||
const paginationConfig = reactive({
|
||||
cacheSizeKey: 'script-page-size',
|
||||
currentPage: 1,
|
||||
pageSize: Number(localStorage.getItem('script-page-size')) || 20,
|
||||
pageSize: 20,
|
||||
total: 0,
|
||||
});
|
||||
const searchInfo = ref<string>('');
|
||||
useSearchReset({ search: searchInfo, page: toRef(paginationConfig, 'currentPage') }, { onRevisit: () => search() });
|
||||
useSearchState(
|
||||
'cronjob/library/index',
|
||||
{ search: searchInfo, page: toRef(paginationConfig, 'currentPage'), pageSize: toRef(paginationConfig, 'pageSize') },
|
||||
{ onRevisit: () => search() },
|
||||
);
|
||||
const group = ref<string>('');
|
||||
const groupOptions = ref();
|
||||
|
||||
|
||||
@@ -323,7 +323,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { useSearchReset } from '@/composables/useSearchReset';
|
||||
import { useSearchState } from '@/utils/search-reset';
|
||||
import { toRef, nextTick, onMounted, reactive, ref } from 'vue';
|
||||
import { dateFormat } from '@/utils/date';
|
||||
import { getRandomStr } from '@/utils/id';
|
||||
@@ -392,14 +392,17 @@ const dbOptionsRemote = ref<Array<Database.DatabaseOption>>([]);
|
||||
|
||||
const tableRows = ref<Array<Database.MongodbDBInfo>>([]);
|
||||
const paginationConfig = reactive({
|
||||
cacheSizeKey: 'mongodb-page-size',
|
||||
currentPage: 1,
|
||||
pageSize: Number(localStorage.getItem('mongodb-page-size')) || 20,
|
||||
pageSize: 20,
|
||||
total: 0,
|
||||
orderBy: 'createdAt',
|
||||
order: 'null',
|
||||
});
|
||||
useSearchReset({ search: searchName, page: toRef(paginationConfig, 'currentPage') }, { onRevisit: () => search() });
|
||||
useSearchState(
|
||||
'database/mongodb/index',
|
||||
{ search: searchName, page: toRef(paginationConfig, 'currentPage'), pageSize: toRef(paginationConfig, 'pageSize') },
|
||||
{ onRevisit: () => search() },
|
||||
);
|
||||
|
||||
type FormInstance = InstanceType<typeof ElForm>;
|
||||
const formRef = ref<FormInstance>();
|
||||
|
||||
@@ -75,7 +75,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { useSearchReset } from '@/composables/useSearchReset';
|
||||
import { useSearchState } from '@/utils/search-reset';
|
||||
import { dateFormat } from '@/utils/date';
|
||||
import { toRef, onMounted, reactive, ref } from 'vue';
|
||||
import { deleteCheckDatabase, searchDatabases } from '@/api/modules/database';
|
||||
@@ -93,15 +93,18 @@ const deleteRef = ref();
|
||||
|
||||
const data = ref();
|
||||
const paginationConfig = reactive({
|
||||
cacheSizeKey: 'mongodb-remote-page-size',
|
||||
currentPage: 1,
|
||||
pageSize: Number(localStorage.getItem('mongodb-remote-page-size')) || 20,
|
||||
pageSize: 20,
|
||||
total: 0,
|
||||
orderBy: 'createdAt',
|
||||
order: 'null',
|
||||
});
|
||||
const searchName = ref();
|
||||
useSearchReset({ search: searchName, page: toRef(paginationConfig, 'currentPage') }, { onRevisit: () => search() });
|
||||
useSearchState(
|
||||
'database/mongodb/remote/index',
|
||||
{ search: searchName, page: toRef(paginationConfig, 'currentPage'), pageSize: toRef(paginationConfig, 'pageSize') },
|
||||
{ onRevisit: () => search() },
|
||||
);
|
||||
|
||||
const search = async (column?: any) => {
|
||||
paginationConfig.orderBy = column?.order ? column.prop : paginationConfig.orderBy;
|
||||
|
||||
@@ -226,7 +226,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { useSearchReset } from '@/composables/useSearchReset';
|
||||
import { useSearchState } from '@/utils/search-reset';
|
||||
import BindDialog from '@/views/database/mysql/bind/index.vue';
|
||||
import UserDialog from '@/views/database/mysql/user/index.vue';
|
||||
import OperateDialog from '@/views/database/mysql/create/index.vue';
|
||||
@@ -293,15 +293,18 @@ const dialogPortJumpRef = ref();
|
||||
const data = ref<Database.MysqlDBInfo[]>([]);
|
||||
let grantSummaryRequestID = 0;
|
||||
const paginationConfig = reactive({
|
||||
cacheSizeKey: 'mysql-page-size',
|
||||
currentPage: 1,
|
||||
pageSize: Number(localStorage.getItem('mysql-page-size')) || 20,
|
||||
pageSize: 20,
|
||||
total: 0,
|
||||
orderBy: 'createdAt',
|
||||
order: 'null',
|
||||
});
|
||||
const searchName = ref();
|
||||
useSearchReset({ search: searchName, page: toRef(paginationConfig, 'currentPage') }, { onRevisit: () => search() });
|
||||
useSearchState(
|
||||
'database/mysql/index',
|
||||
{ search: searchName, page: toRef(paginationConfig, 'currentPage'), pageSize: toRef(paginationConfig, 'pageSize') },
|
||||
{ onRevisit: () => search() },
|
||||
);
|
||||
|
||||
const mysqlContainer = ref();
|
||||
const mysqlStatus = ref();
|
||||
|
||||
@@ -74,7 +74,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { useSearchReset } from '@/composables/useSearchReset';
|
||||
import { useSearchState } from '@/utils/search-reset';
|
||||
import { dateFormat } from '@/utils/date';
|
||||
import { toRef, onMounted, reactive, ref } from 'vue';
|
||||
import { deleteCheckDatabase, searchDatabases } from '@/api/modules/database';
|
||||
@@ -92,15 +92,18 @@ const deleteRef = ref();
|
||||
|
||||
const data = ref();
|
||||
const paginationConfig = reactive({
|
||||
cacheSizeKey: 'mysql-remote-page-size',
|
||||
currentPage: 1,
|
||||
pageSize: Number(localStorage.getItem('mysql-remote-page-size')) || 20,
|
||||
pageSize: 20,
|
||||
total: 0,
|
||||
orderBy: 'createdAt',
|
||||
order: 'null',
|
||||
});
|
||||
const searchName = ref();
|
||||
useSearchReset({ search: searchName, page: toRef(paginationConfig, 'currentPage') }, { onRevisit: () => search() });
|
||||
useSearchState(
|
||||
'database/mysql/remote/index',
|
||||
{ search: searchName, page: toRef(paginationConfig, 'currentPage'), pageSize: toRef(paginationConfig, 'pageSize') },
|
||||
{ onRevisit: () => search() },
|
||||
);
|
||||
|
||||
const search = async (column?: any) => {
|
||||
paginationConfig.orderBy = column?.order ? column.prop : paginationConfig.orderBy;
|
||||
|
||||
@@ -241,7 +241,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { useSearchReset } from '@/composables/useSearchReset';
|
||||
import { useSearchState } from '@/utils/search-reset';
|
||||
import BindDialog from '@/views/database/postgresql/bind/index.vue';
|
||||
import OperateDialog from '@/views/database/postgresql/create/index.vue';
|
||||
import DeleteDialog from '@/views/database/postgresql/delete/index.vue';
|
||||
@@ -305,15 +305,18 @@ const dialogPortJumpRef = ref();
|
||||
|
||||
const data = ref();
|
||||
const paginationConfig = reactive({
|
||||
cacheSizeKey: 'postgresql-page-size',
|
||||
currentPage: 1,
|
||||
pageSize: Number(localStorage.getItem('postgresql-page-size')) || 20,
|
||||
pageSize: 20,
|
||||
total: 0,
|
||||
orderBy: 'createdAt',
|
||||
order: 'null',
|
||||
});
|
||||
const searchName = ref();
|
||||
useSearchReset({ search: searchName, page: toRef(paginationConfig, 'currentPage') }, { onRevisit: () => search() });
|
||||
useSearchState(
|
||||
'database/postgresql/index',
|
||||
{ search: searchName, page: toRef(paginationConfig, 'currentPage'), pageSize: toRef(paginationConfig, 'pageSize') },
|
||||
{ onRevisit: () => search() },
|
||||
);
|
||||
|
||||
const postgresqlContainer = ref();
|
||||
const postgresqlStatus = ref();
|
||||
|
||||
@@ -74,7 +74,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { useSearchReset } from '@/composables/useSearchReset';
|
||||
import { useSearchState } from '@/utils/search-reset';
|
||||
import { dateFormat } from '@/utils/date';
|
||||
import { toRef, onMounted, reactive, ref } from 'vue';
|
||||
import { deleteCheckDatabase, searchDatabases } from '@/api/modules/database';
|
||||
@@ -92,15 +92,18 @@ const deleteRef = ref();
|
||||
|
||||
const data = ref();
|
||||
const paginationConfig = reactive({
|
||||
cacheSizeKey: 'postgresql-remote-page-size',
|
||||
currentPage: 1,
|
||||
pageSize: Number(localStorage.getItem('postgresql-remote-page-size')) || 20,
|
||||
pageSize: 20,
|
||||
total: 0,
|
||||
orderBy: 'createdAt',
|
||||
order: 'null',
|
||||
});
|
||||
const searchName = ref();
|
||||
useSearchReset({ search: searchName, page: toRef(paginationConfig, 'currentPage') }, { onRevisit: () => search() });
|
||||
useSearchState(
|
||||
'database/postgresql/remote/index',
|
||||
{ search: searchName, page: toRef(paginationConfig, 'currentPage'), pageSize: toRef(paginationConfig, 'pageSize') },
|
||||
{ onRevisit: () => search() },
|
||||
);
|
||||
|
||||
const search = async (column?: any) => {
|
||||
paginationConfig.orderBy = column?.order ? column.prop : paginationConfig.orderBy;
|
||||
|
||||
@@ -73,7 +73,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { useSearchReset } from '@/composables/useSearchReset';
|
||||
import { useSearchState } from '@/utils/search-reset';
|
||||
import { dateFormat } from '@/utils/date';
|
||||
import { toRef, onMounted, reactive, ref } from 'vue';
|
||||
import { deleteCheckDatabase, searchDatabases } from '@/api/modules/database';
|
||||
@@ -91,15 +91,18 @@ const deleteRef = ref();
|
||||
|
||||
const data = ref();
|
||||
const paginationConfig = reactive({
|
||||
cacheSizeKey: 'redis-remote-page-size',
|
||||
currentPage: 1,
|
||||
pageSize: Number(localStorage.getItem('redis-remote-page-size')) || 20,
|
||||
pageSize: 20,
|
||||
total: 0,
|
||||
orderBy: 'createdAt',
|
||||
order: 'null',
|
||||
});
|
||||
const searchName = ref();
|
||||
useSearchReset({ search: searchName, page: toRef(paginationConfig, 'currentPage') }, { onRevisit: () => search() });
|
||||
useSearchState(
|
||||
'database/redis/remote/index',
|
||||
{ search: searchName, page: toRef(paginationConfig, 'currentPage'), pageSize: toRef(paginationConfig, 'pageSize') },
|
||||
{ onRevisit: () => search() },
|
||||
);
|
||||
|
||||
const search = async (column?: any) => {
|
||||
paginationConfig.orderBy = column?.order ? column.prop : paginationConfig.orderBy;
|
||||
|
||||
@@ -133,6 +133,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { readCachedPageSize } from '@/utils/panel-cache';
|
||||
import ConfirmDialog from '@/components/confirm-dialog/index.vue';
|
||||
import { Database } from '@/api/interface/database';
|
||||
import { redisPersistenceConf, updateRedisPersistenceConf } from '@/api/modules/database';
|
||||
@@ -188,7 +189,7 @@ const confirmDialogRef = ref();
|
||||
const paginationConfig = reactive({
|
||||
cacheSizeKey: 'redis-backup-page-size',
|
||||
currentPage: 1,
|
||||
pageSize: Number(localStorage.getItem('redis-backup-page-size')) || 20,
|
||||
pageSize: readCachedPageSize('redis-backup-page-size') || 20,
|
||||
total: 0,
|
||||
});
|
||||
|
||||
|
||||
@@ -223,6 +223,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { readCachedPageSize } from '@/utils/panel-cache';
|
||||
import { computed, nextTick, onBeforeUnmount, onMounted, onUnmounted, reactive, ref } from 'vue';
|
||||
import { dateFormatSimpleWithSecond } from '@/utils/date';
|
||||
import { computeSize } from '@/utils/size';
|
||||
@@ -261,7 +262,7 @@ const activeCollapse = ref([]);
|
||||
const paginationConfig = reactive({
|
||||
cacheSizeKey: 'file-history-page-size',
|
||||
currentPage: 1,
|
||||
pageSize: Number(localStorage.getItem('file-history-page-size')) || 20,
|
||||
pageSize: readCachedPageSize('file-history-page-size') || 20,
|
||||
total: 0,
|
||||
small: false,
|
||||
});
|
||||
|
||||
@@ -132,6 +132,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { readCachedPageSize } from '@/utils/panel-cache';
|
||||
import i18n from '@/lang';
|
||||
import { reactive, ref } from 'vue';
|
||||
import { File } from '@/api/interface/file';
|
||||
@@ -226,7 +227,7 @@ const addFile = () => {
|
||||
const paginationConfig = reactive({
|
||||
cacheSizeKey: 'file-convert-log-page-size',
|
||||
currentPage: 1,
|
||||
pageSize: Number(localStorage.getItem('file-convert-log-page-size')) || 20,
|
||||
pageSize: readCachedPageSize('file-convert-log-page-size') || 20,
|
||||
total: 0,
|
||||
});
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { readCachedPageSize } from '@/utils/panel-cache';
|
||||
import { searchFavorite, removeFavorite } from '@/api/modules/files';
|
||||
import i18n from '@/lang';
|
||||
import { reactive, ref } from 'vue';
|
||||
@@ -28,7 +29,7 @@ import { File } from '@/api/interface/file';
|
||||
const paginationConfig = reactive({
|
||||
cacheSizeKey: 'favorite-page-size',
|
||||
currentPage: 1,
|
||||
pageSize: Number(localStorage.getItem('favorite-page-size')) || 20,
|
||||
pageSize: readCachedPageSize('favorite-page-size') || 20,
|
||||
total: 0,
|
||||
});
|
||||
const req = reactive({
|
||||
|
||||
@@ -739,7 +739,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useSearchReset } from '@/composables/useSearchReset';
|
||||
import { useSearchState } from '@/utils/search-reset';
|
||||
import { toRef, computed, nextTick, onBeforeUnmount, onMounted, reactive, ref } from 'vue';
|
||||
import {
|
||||
addFavorite,
|
||||
@@ -980,13 +980,17 @@ const getCurrentPath = () => pathRefs.value[editableTabsKey.value];
|
||||
const { searchableStatus, searchablePath, setSearchableInputRef, searchableInputBlur } = useMultipleSearchable(paths);
|
||||
|
||||
const paginationConfig = reactive({
|
||||
cacheSizeKey: 'file-page-size',
|
||||
currentPage: 1,
|
||||
pageSize: Number(localStorage.getItem('file-page-size')) || 100,
|
||||
pageSize: 100,
|
||||
total: 0,
|
||||
});
|
||||
useSearchReset(
|
||||
{ search: toRef(req, 'search'), page: toRef(paginationConfig, 'currentPage') },
|
||||
useSearchState(
|
||||
'host/file-management/index',
|
||||
{
|
||||
search: toRef(req, 'search'),
|
||||
page: toRef(paginationConfig, 'currentPage'),
|
||||
pageSize: toRef(paginationConfig, 'pageSize'),
|
||||
},
|
||||
{ onRevisit: () => search() },
|
||||
);
|
||||
|
||||
|
||||
@@ -82,6 +82,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { readCachedPageSize } from '@/utils/panel-cache';
|
||||
import { getRecycleStatus, clearRecycle, getRecycleList, reduceFile } from '@/api/modules/files';
|
||||
import { reactive, ref } from 'vue';
|
||||
import { dateFormat } from '@/utils/date';
|
||||
@@ -107,7 +108,7 @@ const status = ref('Enable');
|
||||
const paginationConfig = reactive({
|
||||
cacheSizeKey: 'recycle-page-size',
|
||||
currentPage: 1,
|
||||
pageSize: Number(localStorage.getItem('recycle-page-size')) || 20,
|
||||
pageSize: readCachedPageSize('recycle-page-size') || 20,
|
||||
total: 0,
|
||||
});
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { readCachedPageSize } from '@/utils/panel-cache';
|
||||
import { removeFileShare, searchFileShare } from '@/api/modules/files';
|
||||
import { File } from '@/api/interface/file';
|
||||
import i18n from '@/lang';
|
||||
@@ -33,7 +34,7 @@ import { computed, reactive, ref } from 'vue';
|
||||
const paginationConfig = reactive({
|
||||
cacheSizeKey: 'share-page-size',
|
||||
currentPage: 1,
|
||||
pageSize: Number(localStorage.getItem('share-page-size')) || 20,
|
||||
pageSize: readCachedPageSize('share-page-size') || 20,
|
||||
total: 0,
|
||||
});
|
||||
const req = reactive({
|
||||
|
||||
@@ -219,7 +219,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { useSearchReset } from '@/composables/useSearchReset';
|
||||
import { useSearchState } from '@/utils/search-reset';
|
||||
import { computed, reactive, ref, watch } from 'vue';
|
||||
import FireRouter from '@/views/host/firewall/index.vue';
|
||||
import DockerGuardStatus from '@/views/host/firewall/docker/status/index.vue';
|
||||
@@ -263,7 +263,8 @@ const openRuleTask = (taskID: string) => taskLogRef.value?.openWithTaskID(taskID
|
||||
const orphanDrawerVisible = ref(false);
|
||||
const orphanSearchName = ref('');
|
||||
const searchName = ref('');
|
||||
useSearchReset(
|
||||
useSearchState(
|
||||
'host/firewall/docker/index',
|
||||
{ search: searchName },
|
||||
{
|
||||
onRevisit: () => {
|
||||
|
||||
@@ -117,7 +117,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { useSearchReset } from '@/composables/useSearchReset';
|
||||
import { useSearchState } from '@/utils/search-reset';
|
||||
import OperateDialog from './operate/index.vue';
|
||||
import ImportDialog from './import/index.vue';
|
||||
import FireRouter from '@/views/host/firewall/index.vue';
|
||||
@@ -183,12 +183,15 @@ const operateRules = ref();
|
||||
|
||||
const data = ref();
|
||||
const paginationConfig = reactive({
|
||||
cacheSizeKey: 'firewall-forward-page-size',
|
||||
currentPage: 1,
|
||||
pageSize: Number(localStorage.getItem('firewall-forward-page-size')) || 20,
|
||||
pageSize: 20,
|
||||
total: 0,
|
||||
});
|
||||
useSearchReset({ search: searchName, page: toRef(paginationConfig, 'currentPage') }, { onRevisit: () => search() });
|
||||
useSearchState(
|
||||
'host/firewall/forward/index',
|
||||
{ search: searchName, page: toRef(paginationConfig, 'currentPage'), pageSize: toRef(paginationConfig, 'pageSize') },
|
||||
{ onRevisit: () => search() },
|
||||
);
|
||||
|
||||
const search = async () => {
|
||||
if (!isInit.value || !isBind.value || fireName.value === '-') {
|
||||
|
||||
@@ -302,7 +302,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { useSearchReset } from '@/composables/useSearchReset';
|
||||
import { useSearchState } from '@/utils/search-reset';
|
||||
import { Firewall } from '@/api/interface/firewall';
|
||||
import type { FuTableOperationButton } from '@/components/table/shared';
|
||||
import { buildHostRuleExport } from './transfer';
|
||||
@@ -427,12 +427,15 @@ const supportsFirewalldPriority = computed(() => {
|
||||
return major > 0 || minor >= 7;
|
||||
});
|
||||
const paginationConfig = reactive({
|
||||
cacheSizeKey: 'firewall-rule-page-size',
|
||||
currentPage: 1,
|
||||
pageSize: Number(localStorage.getItem('firewall-rule-page-size')) || 20,
|
||||
pageSize: 20,
|
||||
total: 0,
|
||||
});
|
||||
useSearchReset({ search: searchName, page: toRef(paginationConfig, 'currentPage') }, { onRevisit: () => search() });
|
||||
useSearchState(
|
||||
'host/firewall/rule/index',
|
||||
{ search: searchName, page: toRef(paginationConfig, 'currentPage'), pageSize: toRef(paginationConfig, 'pageSize') },
|
||||
{ onRevisit: () => search() },
|
||||
);
|
||||
|
||||
const providerScopes = (): Firewall.Scope[] => {
|
||||
if (provider.value === 'iptables' || provider.value === 'nftables') {
|
||||
|
||||
@@ -86,6 +86,8 @@ const statusOptions = [
|
||||
const { currentNode } = useGlobalStore();
|
||||
const isCompactTable = useMediaQuery('(max-width: 1024px)');
|
||||
const processStore = ProcessStore();
|
||||
processStore.restoreSearchState();
|
||||
onActivated(() => processStore.restoreSearchState());
|
||||
|
||||
const quickSearchName = (name: string) => {
|
||||
processStore.netSearch.processID = undefined;
|
||||
|
||||
@@ -83,6 +83,8 @@ import { useMediaQuery } from '@vueuse/core';
|
||||
const { currentNode } = useGlobalStore();
|
||||
const isCompactTable = useMediaQuery('(max-width: 1024px)');
|
||||
const processStore = ProcessStore();
|
||||
processStore.restoreSearchState();
|
||||
onActivated(() => processStore.restoreSearchState());
|
||||
const permissionDirective = resolveDirective('permission');
|
||||
|
||||
const statusOptions = computed(() => [
|
||||
|
||||
@@ -93,7 +93,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useSearchReset } from '@/composables/useSearchReset';
|
||||
import { useSearchState } from '@/utils/search-reset';
|
||||
import ConfirmDialog from '@/components/confirm-dialog/index.vue';
|
||||
import { dateFormatServerTimezone } from '@/utils/date';
|
||||
import { downloadFile } from '@/utils/file';
|
||||
@@ -108,9 +108,8 @@ const loading = ref();
|
||||
const data = ref();
|
||||
const confirmDialogRef = ref();
|
||||
const paginationConfig = reactive({
|
||||
cacheSizeKey: 'ssh-log-page-size',
|
||||
currentPage: 1,
|
||||
pageSize: Number(localStorage.getItem('ssh-log-page-size')) || 20,
|
||||
pageSize: 20,
|
||||
total: 0,
|
||||
});
|
||||
|
||||
@@ -120,7 +119,11 @@ const exportConfig = reactive({
|
||||
status: 'All',
|
||||
});
|
||||
const searchInfo = ref();
|
||||
useSearchReset({ search: searchInfo, page: toRef(paginationConfig, 'currentPage') }, { onRevisit: () => search() });
|
||||
useSearchState(
|
||||
'host/ssh/log/log',
|
||||
{ search: searchInfo, page: toRef(paginationConfig, 'currentPage'), pageSize: toRef(paginationConfig, 'pageSize') },
|
||||
{ onRevisit: () => search() },
|
||||
);
|
||||
const searchStatus = ref('All');
|
||||
|
||||
const search = async () => {
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useSearchReset } from '@/composables/useSearchReset';
|
||||
import { useSearchState } from '@/utils/search-reset';
|
||||
import FireRouter from '@/views/host/ssh/index.vue';
|
||||
import { toRef, ref, onMounted, onUnmounted, reactive } from 'vue';
|
||||
import i18n from '@/lang';
|
||||
@@ -38,7 +38,7 @@ const sshSearch = reactive({
|
||||
type: 'ssh',
|
||||
loginUser: '',
|
||||
});
|
||||
useSearchReset({ search: toRef(sshSearch, 'loginUser') }, { onRevisit: () => search() });
|
||||
useSearchState('host/ssh/session/index', { search: toRef(sshSearch, 'loginUser') }, { onRevisit: () => search() });
|
||||
|
||||
const buttons = [
|
||||
{
|
||||
|
||||
@@ -93,6 +93,7 @@
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { readCachedPageSize } from '@/utils/panel-cache';
|
||||
import { Host } from '@/api/interface/host';
|
||||
import { deleteCert, searchCert, syncCert } from '@/api/modules/host';
|
||||
import i18n from '@/lang';
|
||||
@@ -109,7 +110,7 @@ const selects = ref<any>([]);
|
||||
const paginationConfig = reactive({
|
||||
cacheSizeKey: 'login-log-page-size',
|
||||
currentPage: 1,
|
||||
pageSize: Number(localStorage.getItem('login-log-page-size')) || 20,
|
||||
pageSize: readCachedPageSize('login-log-page-size') || 20,
|
||||
total: 0,
|
||||
small: true,
|
||||
});
|
||||
|
||||
@@ -101,7 +101,8 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useSearchReset } from '@/composables/useSearchReset';
|
||||
import { panelCacheKey, writePanelCache, readCachedPageSize } from '@/utils/panel-cache';
|
||||
import { useSearchState } from '@/utils/search-reset';
|
||||
import { onMounted, onUnmounted, reactive, ref, watch } from 'vue';
|
||||
import { Log } from '@/api/interface/log';
|
||||
import { getSystemLogStatus, listRunningServices, readSystemLogs } from '@/api/modules/log';
|
||||
@@ -114,7 +115,7 @@ const logs = ref<Log.SystemLogItem[]>([]);
|
||||
const loading = ref(false);
|
||||
const watching = ref(false);
|
||||
const keyword = ref('');
|
||||
useSearchReset({ keyword }, { onRevisit: () => scheduleFilterSearch() });
|
||||
useSearchState('log/host-system/index', { keyword }, { onRevisit: () => scheduleFilterSearch() });
|
||||
const priority = ref('');
|
||||
const service = ref('');
|
||||
const services = ref<string[]>([]);
|
||||
@@ -194,7 +195,7 @@ const loadPreviousPage = () => {
|
||||
};
|
||||
|
||||
const changePageSize = () => {
|
||||
localStorage.setItem(paginationConfig.cacheSizeKey, String(paginationConfig.pageSize));
|
||||
writePanelCache('pagination', panelCacheKey(`size:${paginationConfig.cacheSizeKey}`), paginationConfig.pageSize);
|
||||
resetAndLoadLogs();
|
||||
};
|
||||
|
||||
@@ -263,7 +264,7 @@ const priorityType = (value: string) => {
|
||||
};
|
||||
|
||||
onMounted(async () => {
|
||||
const cachedPageSize = Number(localStorage.getItem(paginationConfig.cacheSizeKey));
|
||||
const cachedPageSize = readCachedPageSize(paginationConfig.cacheSizeKey);
|
||||
if (pageSizes.includes(cachedPageSize)) {
|
||||
paginationConfig.pageSize = cachedPageSize;
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useSearchReset } from '@/composables/useSearchReset';
|
||||
import { useSearchState } from '@/utils/search-reset';
|
||||
import ConfirmDialog from '@/components/confirm-dialog/index.vue';
|
||||
import LogRouter from '@/views/log/router/index.vue';
|
||||
import { dateFormat } from '@/utils/date';
|
||||
@@ -61,13 +61,16 @@ const loading = ref();
|
||||
const data = ref();
|
||||
const confirmDialogRef = ref();
|
||||
const paginationConfig = reactive({
|
||||
cacheSizeKey: 'login-log-page-size',
|
||||
currentPage: 1,
|
||||
pageSize: Number(localStorage.getItem('login-log-page-size')) || 20,
|
||||
pageSize: 20,
|
||||
total: 0,
|
||||
});
|
||||
const searchInfo = ref<string>('');
|
||||
useSearchReset({ search: searchInfo, page: toRef(paginationConfig, 'currentPage') }, { onRevisit: () => search() });
|
||||
useSearchState(
|
||||
'log/login/index',
|
||||
{ search: searchInfo, page: toRef(paginationConfig, 'currentPage'), pageSize: toRef(paginationConfig, 'pageSize') },
|
||||
{ onRevisit: () => search() },
|
||||
);
|
||||
const searchStatus = ref<string>('');
|
||||
|
||||
const search = async () => {
|
||||
|
||||
@@ -139,7 +139,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useSearchReset } from '@/composables/useSearchReset';
|
||||
import { useSearchState } from '@/utils/search-reset';
|
||||
import ConfirmDialog from '@/components/confirm-dialog/index.vue';
|
||||
import LogRouter from '@/views/log/router/index.vue';
|
||||
import { dateFormat } from '@/utils/date';
|
||||
@@ -154,13 +154,16 @@ const loading = ref();
|
||||
const data = ref();
|
||||
const confirmDialogRef = ref();
|
||||
const paginationConfig = reactive({
|
||||
cacheSizeKey: 'operation-log-page-size',
|
||||
currentPage: 1,
|
||||
pageSize: Number(localStorage.getItem('operation-log-page-size')) || 20,
|
||||
pageSize: 20,
|
||||
total: 0,
|
||||
});
|
||||
const searchName = ref<string>('');
|
||||
useSearchReset({ search: searchName, page: toRef(paginationConfig, 'currentPage') }, { onRevisit: () => search() });
|
||||
useSearchState(
|
||||
'log/operation/index',
|
||||
{ search: searchName, page: toRef(paginationConfig, 'currentPage'), pageSize: toRef(paginationConfig, 'pageSize') },
|
||||
{ onRevisit: () => search() },
|
||||
);
|
||||
const searchGroup = ref<string>('');
|
||||
const searchStatus = ref<string>('');
|
||||
const searchNode = ref<string>('');
|
||||
|
||||
@@ -49,6 +49,8 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { toRef } from 'vue';
|
||||
import { useSearchState } from '@/utils/search-reset';
|
||||
import LogRouter from '@/views/log/router/index.vue';
|
||||
import { dateFormat } from '@/utils/date';
|
||||
import { searchTasks } from '@/api/modules/log';
|
||||
@@ -61,11 +63,18 @@ import { translateTaskText } from '@/utils/task';
|
||||
const loading = ref();
|
||||
const data = ref();
|
||||
const paginationConfig = reactive({
|
||||
cacheSizeKey: 'task-page-size',
|
||||
currentPage: 1,
|
||||
pageSize: Number(localStorage.getItem('task-page-size')) || 20,
|
||||
pageSize: 20,
|
||||
total: 0,
|
||||
});
|
||||
useSearchState(
|
||||
'log/task/index',
|
||||
{
|
||||
page: toRef(paginationConfig, 'currentPage'),
|
||||
pageSize: toRef(paginationConfig, 'pageSize'),
|
||||
},
|
||||
{ onRevisit: () => search() },
|
||||
);
|
||||
const taskLogRef = ref();
|
||||
const req = reactive({
|
||||
type: '',
|
||||
|
||||
@@ -357,6 +357,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { applyPanelCacheSettings } from '@/utils/panel-cache';
|
||||
import { ref, reactive, onMounted, onBeforeUnmount, computed, nextTick } from 'vue';
|
||||
import type { ElForm } from 'element-plus';
|
||||
import {
|
||||
@@ -926,6 +927,7 @@ const getSetting = async () => {
|
||||
i18n.warnHtmlMessage = false;
|
||||
openMenuTabs.value = res.data.menuTabs === 'Enable';
|
||||
menuAccordion.value = res.data.menuAccordion === 'Enable';
|
||||
applyPanelCacheSettings(res.data.panelCache);
|
||||
themeConfig.value = { ...themeConfig.value, theme: res.data.theme, panelName: res.data.panelName };
|
||||
|
||||
if (res.data.passkeySetting && !isIntl.value && !isFxplay.value) {
|
||||
|
||||
@@ -159,6 +159,8 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { toRef } from 'vue';
|
||||
import { useSearchState } from '@/utils/search-reset';
|
||||
import { onMounted, reactive, ref } from 'vue';
|
||||
import { useGlobalStore } from '@/composables/useGlobalStore';
|
||||
import { getAlertConfigDisplayName } from '@/views/setting/alert/setting/drawer/secret-field';
|
||||
@@ -191,13 +193,20 @@ const req = reactive({
|
||||
});
|
||||
|
||||
const paginationConfig = reactive({
|
||||
cacheSizeKey: 'alert-list-page-size',
|
||||
currentPage: 1,
|
||||
pageSize: Number(localStorage.getItem('alert-list-page-size')) || 20,
|
||||
pageSize: 20,
|
||||
total: 0,
|
||||
orderBy: 'created_at',
|
||||
order: 'null',
|
||||
});
|
||||
useSearchState(
|
||||
'setting/alert/dash/index',
|
||||
{
|
||||
page: toRef(paginationConfig, 'currentPage'),
|
||||
pageSize: toRef(paginationConfig, 'pageSize'),
|
||||
},
|
||||
{ onRevisit: () => search() },
|
||||
);
|
||||
const data = ref();
|
||||
|
||||
const buttons = [
|
||||
|
||||
@@ -82,6 +82,8 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { toRef } from 'vue';
|
||||
import { useSearchState } from '@/utils/search-reset';
|
||||
import { onMounted, reactive, ref } from 'vue';
|
||||
import { dateFormat } from '@/utils/date';
|
||||
import { MsgSuccess } from '@/utils/message';
|
||||
@@ -131,11 +133,18 @@ const resourceTypes = [
|
||||
'sshIpLogin',
|
||||
];
|
||||
const paginationConfig = reactive({
|
||||
cacheSizeKey: 'alert-log-page-size',
|
||||
currentPage: 1,
|
||||
pageSize: Number(localStorage.getItem('alert-log-page-size')) || 20,
|
||||
pageSize: 20,
|
||||
total: 0,
|
||||
});
|
||||
useSearchState(
|
||||
'setting/alert/log/index',
|
||||
{
|
||||
page: toRef(paginationConfig, 'currentPage'),
|
||||
pageSize: toRef(paginationConfig, 'pageSize'),
|
||||
},
|
||||
{ onRevisit: () => search() },
|
||||
);
|
||||
const req = reactive({
|
||||
page: 1,
|
||||
pageSize: 10,
|
||||
|
||||
@@ -149,6 +149,8 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { toRef } from 'vue';
|
||||
import { useSearchState } from '@/utils/search-reset';
|
||||
import { computed, onMounted, reactive, ref } from 'vue';
|
||||
import { useGlobalStore } from '@/composables/useGlobalStore';
|
||||
import {
|
||||
@@ -219,11 +221,18 @@ const config = ref<Alert.AlertConfigUpdateReq>({
|
||||
});
|
||||
|
||||
const paginationConfig = reactive({
|
||||
cacheSizeKey: 'alert-config-page-size',
|
||||
currentPage: 1,
|
||||
pageSize: Number(localStorage.getItem('alert-config-page-size')) || 20,
|
||||
pageSize: 20,
|
||||
total: 0,
|
||||
});
|
||||
useSearchState(
|
||||
'setting/alert/setting/index',
|
||||
{
|
||||
page: toRef(paginationConfig, 'currentPage'),
|
||||
pageSize: toRef(paginationConfig, 'pageSize'),
|
||||
},
|
||||
{ onRevisit: () => search() },
|
||||
);
|
||||
|
||||
const parseConfig = <T extends object>(raw: Alert.AlertConfigInfo, fallback: T): T => {
|
||||
try {
|
||||
|
||||
@@ -120,7 +120,7 @@
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { useSearchReset } from '@/composables/useSearchReset';
|
||||
import { useSearchState } from '@/utils/search-reset';
|
||||
import { dateFormat } from '@/utils/date';
|
||||
import { toRef, onMounted, ref } from 'vue';
|
||||
import { searchBackup, deleteBackup, refreshToken } from '@/api/modules/backup';
|
||||
@@ -136,15 +136,19 @@ const { isProductPro, isFxplay, docsUrl, isMobile } = useGlobalStore();
|
||||
const loading = ref();
|
||||
const data = ref();
|
||||
const paginationConfig = reactive({
|
||||
cacheSizeKey: 'backup-account-size',
|
||||
currentPage: 1,
|
||||
pageSize: Number(localStorage.getItem('backup-account-size')) || 20,
|
||||
pageSize: 20,
|
||||
total: 0,
|
||||
type: '',
|
||||
name: '',
|
||||
});
|
||||
useSearchReset(
|
||||
{ search: toRef(paginationConfig, 'name'), page: toRef(paginationConfig, 'currentPage') },
|
||||
useSearchState(
|
||||
'setting/backup-account/index',
|
||||
{
|
||||
search: toRef(paginationConfig, 'name'),
|
||||
page: toRef(paginationConfig, 'currentPage'),
|
||||
pageSize: toRef(paginationConfig, 'pageSize'),
|
||||
},
|
||||
{ onRevisit: () => search() },
|
||||
);
|
||||
const opRef = ref();
|
||||
|
||||
@@ -99,6 +99,8 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { toRef } from 'vue';
|
||||
import { useSearchState } from '@/utils/search-reset';
|
||||
import { ref, reactive, onMounted } from 'vue';
|
||||
import { deleteLicense, searchLicense, syncLicense, unbindLicense } from '@/api/modules/setting';
|
||||
import LicenseImport from '@/components/license-import/index.vue';
|
||||
@@ -125,13 +127,20 @@ const withDockerRestart = ref();
|
||||
|
||||
const data = ref();
|
||||
const paginationConfig = reactive({
|
||||
cacheSizeKey: 'license-page-size',
|
||||
currentPage: 1,
|
||||
pageSize: Number(localStorage.getItem('license-page-size')) || 20,
|
||||
pageSize: 20,
|
||||
total: 0,
|
||||
type: '',
|
||||
name: '',
|
||||
});
|
||||
useSearchState(
|
||||
'setting/license/index',
|
||||
{
|
||||
page: toRef(paginationConfig, 'currentPage'),
|
||||
pageSize: toRef(paginationConfig, 'pageSize'),
|
||||
},
|
||||
{ onRevisit: () => search() },
|
||||
);
|
||||
|
||||
const loadMsg = (row: any) => {
|
||||
if (row.status === 'Exceptional') {
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
<template>
|
||||
<DrawerPro v-model="visible" :header="$t('setting.panelCache.title')" size="normal">
|
||||
<el-card shadow="never">
|
||||
<div v-for="key in categories" :key="key" class="flex items-center justify-between py-3">
|
||||
<span>{{ $t(`setting.panelCache.${key}`) }}</span>
|
||||
<el-switch v-model="form[key]" :aria-label="$t(`setting.panelCache.${key}`)" />
|
||||
</div>
|
||||
<div class="flex items-center justify-between gap-4 mt-4">
|
||||
<div class="flex items-center gap-2 shrink-0">
|
||||
<span>{{ $t('setting.panelCache.duration') }}</span>
|
||||
<el-tooltip
|
||||
:content="$t('setting.panelCache.helper')"
|
||||
placement="top"
|
||||
:trigger="isMobile ? 'click' : 'hover'"
|
||||
:popper-style="{ maxWidth: 'min(360px, calc(100vw - 32px))' }"
|
||||
>
|
||||
<el-button
|
||||
link
|
||||
type="info"
|
||||
icon="InfoFilled"
|
||||
class="!ml-0 shrink-0"
|
||||
:aria-label="$t('setting.panelCache.helper')"
|
||||
@click.stop
|
||||
/>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
<el-select
|
||||
v-model="form.duration"
|
||||
class="!w-40 min-w-0"
|
||||
:aria-label="$t('setting.panelCache.duration')"
|
||||
>
|
||||
<el-option
|
||||
v-for="value in durations"
|
||||
:key="value"
|
||||
:value="value"
|
||||
:label="$t(`setting.panelCache.${value}`)"
|
||||
/>
|
||||
</el-select>
|
||||
</div>
|
||||
</el-card>
|
||||
<template #footer>
|
||||
<el-button :disabled="loading" @click="Object.assign(form, defaultPanelCache)">
|
||||
{{ $t('commons.button.setDefault') }}
|
||||
</el-button>
|
||||
<el-button :disabled="loading" @click="visible = false">{{ $t('commons.button.cancel') }}</el-button>
|
||||
<el-button :loading="loading" type="primary" @click="save">{{ $t('commons.button.confirm') }}</el-button>
|
||||
</template>
|
||||
</DrawerPro>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { reactive, ref } from 'vue';
|
||||
import { updateSetting } from '@/api/modules/setting';
|
||||
import { useGlobalStore } from '@/composables/useGlobalStore';
|
||||
import { applyPanelCacheSettings, defaultPanelCache } from '@/utils/panel-cache';
|
||||
import { MsgSuccess } from '@/utils/message';
|
||||
import i18n from '@/lang';
|
||||
|
||||
const { panelCache, isMobile } = useGlobalStore();
|
||||
const visible = ref(false);
|
||||
const loading = ref(false);
|
||||
const form = reactive({ ...defaultPanelCache });
|
||||
const categories = ['tabs', 'pagination', 'refresh', 'search'] as const;
|
||||
const durations = ['24h', 'week', 'month', 'forever'] as const;
|
||||
const acceptParams = () => {
|
||||
Object.assign(form, panelCache.value);
|
||||
visible.value = true;
|
||||
};
|
||||
const save = async () => {
|
||||
loading.value = true;
|
||||
try {
|
||||
const value = JSON.stringify(form);
|
||||
await updateSetting({ key: 'PanelCache', value });
|
||||
applyPanelCacheSettings(value);
|
||||
visible.value = false;
|
||||
MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
defineExpose({ acceptParams });
|
||||
</script>
|
||||
@@ -170,6 +170,12 @@
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="$t('setting.panelCache.title')">
|
||||
<el-button v-show="!show" @click="cacheRef.acceptParams()" icon="Setting">
|
||||
{{ $t('commons.button.set') }}
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="$t('setting.runtimeEnv')" prop="edition">
|
||||
<el-button icon="Setting" @click="onChangeRegion">
|
||||
{{ runtimeEnvLabel() }}
|
||||
@@ -186,6 +192,7 @@
|
||||
<Proxy ref="proxyRef" @search="search()" />
|
||||
<Timeout ref="timeoutRef" @search="search()" />
|
||||
<HideMenu ref="hideMenuRef" @search="search()" />
|
||||
<CacheSettings ref="cacheRef" />
|
||||
<ThemeColor ref="themeColorRef" />
|
||||
<Watermark ref="watermarkRef" @search="search()" />
|
||||
<Edition ref="editionRef" @search="search()" />
|
||||
@@ -193,6 +200,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { applyPanelCacheSettings } from '@/utils/panel-cache';
|
||||
import { ref, reactive, onMounted } from 'vue';
|
||||
import { ElForm, ElMessageBox } from 'element-plus';
|
||||
import { getSettingInfo, updateSetting, getSystemAvailable, getAgentSettingInfo } from '@/api/modules/setting';
|
||||
@@ -206,6 +214,7 @@ import Timeout from '@/views/setting/panel/timeout/index.vue';
|
||||
import PanelName from '@/views/setting/panel/name/index.vue';
|
||||
import SystemIP from '@/views/setting/panel/systemip/index.vue';
|
||||
import Proxy from '@/views/setting/panel/proxy/index.vue';
|
||||
import CacheSettings from '@/views/setting/panel/cache/index.vue';
|
||||
import HideMenu from '@/views/setting/panel/hidemenu/index.vue';
|
||||
import { getXpackProxyDocker } from '@/extensions/xpack';
|
||||
import { getXpackSetting, updateXpackSettingByKey } from '@/utils/xpack';
|
||||
@@ -274,6 +283,7 @@ const systemIPRef = ref();
|
||||
const proxyRef = ref();
|
||||
const timeoutRef = ref();
|
||||
const hideMenuRef = ref();
|
||||
const cacheRef = ref();
|
||||
const watermarkRef = ref();
|
||||
const themeColorRef = ref();
|
||||
const editionRef = ref();
|
||||
@@ -307,6 +317,7 @@ const search = async () => {
|
||||
form.menuTabs = res.data.menuTabs;
|
||||
form.menuAccordion = res.data.menuAccordion || 'Disable';
|
||||
menuAccordion.value = form.menuAccordion === 'Enable';
|
||||
applyPanelCacheSettings(res.data.panelCache);
|
||||
form.panelName = res.data.panelName;
|
||||
form.language = res.data.language;
|
||||
form.sessionTimeout = Number(res.data.sessionTimeout || 0);
|
||||
|
||||
@@ -225,7 +225,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useSearchReset } from '@/composables/useSearchReset';
|
||||
import { useSearchState } from '@/utils/search-reset';
|
||||
import {
|
||||
searchSnapshotPage,
|
||||
snapshotDelete,
|
||||
@@ -253,15 +253,18 @@ const loading = ref(false);
|
||||
const data = ref();
|
||||
const selects = ref<any>([]);
|
||||
const paginationConfig = reactive({
|
||||
cacheSizeKey: 'snapshot-page-size',
|
||||
currentPage: 1,
|
||||
pageSize: Number(localStorage.getItem('snapshot-page-size')) || 20,
|
||||
pageSize: 20,
|
||||
total: 0,
|
||||
orderBy: 'createdAt',
|
||||
order: 'null',
|
||||
});
|
||||
const searchName = ref();
|
||||
useSearchReset({ search: searchName, page: toRef(paginationConfig, 'currentPage') }, { onRevisit: () => search() });
|
||||
useSearchState(
|
||||
'setting/snapshot/index',
|
||||
{ search: searchName, page: toRef(paginationConfig, 'currentPage'), pageSize: toRef(paginationConfig, 'pageSize') },
|
||||
{ onRevisit: () => search() },
|
||||
);
|
||||
|
||||
const opRef = ref();
|
||||
|
||||
|
||||
@@ -91,7 +91,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useSearchReset } from '@/composables/useSearchReset';
|
||||
import { useSearchState } from '@/utils/search-reset';
|
||||
import { Command } from '@/api/interface/command';
|
||||
import GroupDialog from '@/components/group/index.vue';
|
||||
import OperateDialog from '@/views/terminal/command/operate/index.vue';
|
||||
@@ -107,15 +107,18 @@ const data = ref();
|
||||
const selects = ref<any>([]);
|
||||
const groupList = ref();
|
||||
const paginationConfig = reactive({
|
||||
cacheSizeKey: 'terminal-command-page-size',
|
||||
currentPage: 1,
|
||||
pageSize: Number(localStorage.getItem('terminal-command-page-size')) || 20,
|
||||
pageSize: 20,
|
||||
total: 0,
|
||||
orderBy: 'name',
|
||||
order: 'ascending',
|
||||
});
|
||||
const info = ref();
|
||||
useSearchReset({ search: info, page: toRef(paginationConfig, 'currentPage') }, { onRevisit: () => search() });
|
||||
useSearchState(
|
||||
'terminal/command/index',
|
||||
{ search: info, page: toRef(paginationConfig, 'currentPage'), pageSize: toRef(paginationConfig, 'pageSize') },
|
||||
{ onRevisit: () => search() },
|
||||
);
|
||||
const group = ref<string>('');
|
||||
const dialogRef = ref();
|
||||
const opRef = ref();
|
||||
|
||||
@@ -70,7 +70,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useSearchReset } from '@/composables/useSearchReset';
|
||||
import { useSearchState } from '@/utils/search-reset';
|
||||
import GroupDialog from '@/components/agent-group/index.vue';
|
||||
import OperateDialog from '@/views/terminal/host/operate/index.vue';
|
||||
import { deleteHost, editHostGroup, searchHosts } from '@/api/modules/terminal';
|
||||
@@ -85,13 +85,16 @@ const data = ref();
|
||||
const groupList = ref();
|
||||
const selects = ref<any>([]);
|
||||
const paginationConfig = reactive({
|
||||
cacheSizeKey: 'terminal-host-page-size',
|
||||
currentPage: 1,
|
||||
pageSize: Number(localStorage.getItem('terminal-host-page-size')) || 20,
|
||||
pageSize: 20,
|
||||
total: 0,
|
||||
});
|
||||
const info = ref();
|
||||
useSearchReset({ search: info, page: toRef(paginationConfig, 'currentPage') }, { onRevisit: () => search() });
|
||||
useSearchState(
|
||||
'terminal/host/index',
|
||||
{ search: info, page: toRef(paginationConfig, 'currentPage'), pageSize: toRef(paginationConfig, 'pageSize') },
|
||||
{ onRevisit: () => search() },
|
||||
);
|
||||
const group = ref<string>('');
|
||||
|
||||
const opRef = ref();
|
||||
|
||||
@@ -190,7 +190,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { useSearchReset } from '@/composables/useSearchReset';
|
||||
import { useSearchState } from '@/utils/search-reset';
|
||||
import { toRef, onMounted, reactive, ref } from 'vue';
|
||||
import i18n from '@/lang';
|
||||
import { MsgSuccess } from '@/utils/message';
|
||||
@@ -210,15 +210,18 @@ const selects = ref<any>([]);
|
||||
const { docsUrl, isFxplay, isProductPro, isMobile } = useGlobalStore();
|
||||
const data = ref();
|
||||
const paginationConfig = reactive({
|
||||
cacheSizeKey: 'clam-page-size',
|
||||
currentPage: 1,
|
||||
pageSize: Number(localStorage.getItem('clam-page-size')) || 20,
|
||||
pageSize: 20,
|
||||
total: 0,
|
||||
orderBy: 'createdAt',
|
||||
order: 'null',
|
||||
});
|
||||
const searchName = ref();
|
||||
useSearchReset({ search: searchName, page: toRef(paginationConfig, 'currentPage') }, { onRevisit: () => search() });
|
||||
useSearchState(
|
||||
'toolbox/clam/index',
|
||||
{ search: searchName, page: toRef(paginationConfig, 'currentPage'), pageSize: toRef(paginationConfig, 'pageSize') },
|
||||
{ onRevisit: () => search() },
|
||||
);
|
||||
|
||||
const opRef = ref();
|
||||
const dialogRef = ref();
|
||||
|
||||
@@ -193,6 +193,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { panelCacheKey, writePanelCache, readCachedPageSize } from '@/utils/panel-cache';
|
||||
import { reactive, ref } from 'vue';
|
||||
import { useMediaQuery } from '@vueuse/core';
|
||||
import i18n from '@/lang';
|
||||
@@ -220,7 +221,7 @@ const records = ref<Array<Toolbox.ClamRecord>>([]);
|
||||
const currentRecord = ref<Toolbox.ClamRecord>();
|
||||
|
||||
const acceptParams = async (params: DialogProps): Promise<void> => {
|
||||
let itemSize = Number(localStorage.getItem(searchInfo.cacheSizeKey));
|
||||
let itemSize = readCachedPageSize(searchInfo.cacheSizeKey);
|
||||
if (itemSize) {
|
||||
searchInfo.pageSize = itemSize;
|
||||
}
|
||||
@@ -232,7 +233,7 @@ const acceptParams = async (params: DialogProps): Promise<void> => {
|
||||
|
||||
const handleSizeChange = (val: number) => {
|
||||
searchInfo.pageSize = val;
|
||||
localStorage.setItem(searchInfo.cacheSizeKey, val + '');
|
||||
writePanelCache('pagination', panelCacheKey(`size:${searchInfo.cacheSizeKey}`), val);
|
||||
search(true);
|
||||
};
|
||||
const handleCurrentChange = (val: number) => {
|
||||
|
||||
@@ -174,7 +174,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { useSearchReset } from '@/composables/useSearchReset';
|
||||
import { useSearchState } from '@/utils/search-reset';
|
||||
import { toRef, onMounted, reactive, ref } from 'vue';
|
||||
import i18n from '@/lang';
|
||||
import { MsgError, MsgSuccess } from '@/utils/message';
|
||||
@@ -193,15 +193,18 @@ const selects = ref<any>([]);
|
||||
|
||||
const data = ref();
|
||||
const paginationConfig = reactive({
|
||||
cacheSizeKey: 'ftp-page-size',
|
||||
currentPage: 1,
|
||||
pageSize: Number(localStorage.getItem('ftp-page-size')) || 20,
|
||||
pageSize: 20,
|
||||
total: 0,
|
||||
orderBy: 'createdAt',
|
||||
order: 'null',
|
||||
});
|
||||
const searchName = ref();
|
||||
useSearchReset({ search: searchName, page: toRef(paginationConfig, 'currentPage') }, { onRevisit: () => search() });
|
||||
useSearchState(
|
||||
'toolbox/ftp/index',
|
||||
{ search: searchName, page: toRef(paginationConfig, 'currentPage'), pageSize: toRef(paginationConfig, 'pageSize') },
|
||||
{ onRevisit: () => search() },
|
||||
);
|
||||
|
||||
const form = reactive({
|
||||
isActive: true,
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { readCachedPageSize } from '@/utils/panel-cache';
|
||||
import { reactive, ref } from 'vue';
|
||||
import { searchFtpLog } from '@/api/modules/toolbox';
|
||||
import { computeSizeFromByte } from '@/utils/size';
|
||||
@@ -46,7 +47,7 @@ import i18n from '@/lang';
|
||||
const paginationConfig = reactive({
|
||||
cacheSizeKey: 'ftp-log-page-size',
|
||||
currentPage: 1,
|
||||
pageSize: Number(localStorage.getItem('ftp-log-page-size')) || 20,
|
||||
pageSize: readCachedPageSize('ftp-log-page-size') || 20,
|
||||
total: 0,
|
||||
user: '',
|
||||
operation: '',
|
||||
|
||||
@@ -102,6 +102,8 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { toRef } from 'vue';
|
||||
import { useSearchState } from '@/utils/search-reset';
|
||||
import { onMounted, reactive, ref } from 'vue';
|
||||
import { Runtime } from '@/api/interface/runtime';
|
||||
import { RuntimeDeleteCheck, SearchRuntimes, SyncRuntime } from '@/api/modules/runtime';
|
||||
@@ -138,11 +140,18 @@ const isActive = ref(false);
|
||||
const isExist = ref(false);
|
||||
|
||||
const paginationConfig = reactive({
|
||||
cacheSizeKey: 'runtime-page-size',
|
||||
currentPage: 1,
|
||||
pageSize: Number(localStorage.getItem('runtime-page-size')) || 20,
|
||||
pageSize: 20,
|
||||
total: 0,
|
||||
});
|
||||
useSearchState(
|
||||
'website/runtime/dotnet/index',
|
||||
{
|
||||
page: toRef(paginationConfig, 'currentPage'),
|
||||
pageSize: toRef(paginationConfig, 'pageSize'),
|
||||
},
|
||||
{ onRevisit: () => search() },
|
||||
);
|
||||
const req = reactive<Runtime.RuntimeReq>({
|
||||
name: '',
|
||||
page: 1,
|
||||
|
||||
@@ -102,6 +102,8 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { toRef } from 'vue';
|
||||
import { useSearchState } from '@/utils/search-reset';
|
||||
import { onMounted, reactive, ref } from 'vue';
|
||||
import { Runtime } from '@/api/interface/runtime';
|
||||
import { RuntimeDeleteCheck, SearchRuntimes, SyncRuntime } from '@/api/modules/runtime';
|
||||
@@ -138,11 +140,18 @@ const isActive = ref(false);
|
||||
const isExist = ref(false);
|
||||
|
||||
const paginationConfig = reactive({
|
||||
cacheSizeKey: 'runtime-page-size',
|
||||
currentPage: 1,
|
||||
pageSize: Number(localStorage.getItem('runtime-page-size')) || 20,
|
||||
pageSize: 20,
|
||||
total: 0,
|
||||
});
|
||||
useSearchState(
|
||||
'website/runtime/go/index',
|
||||
{
|
||||
page: toRef(paginationConfig, 'currentPage'),
|
||||
pageSize: toRef(paginationConfig, 'pageSize'),
|
||||
},
|
||||
{ onRevisit: () => search() },
|
||||
);
|
||||
const req = reactive<Runtime.RuntimeReq>({
|
||||
name: '',
|
||||
page: 1,
|
||||
|
||||
@@ -102,6 +102,8 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { toRef } from 'vue';
|
||||
import { useSearchState } from '@/utils/search-reset';
|
||||
import { onMounted, reactive, ref } from 'vue';
|
||||
import { Runtime } from '@/api/interface/runtime';
|
||||
import { RuntimeDeleteCheck, SearchRuntimes, SyncRuntime } from '@/api/modules/runtime';
|
||||
@@ -138,11 +140,18 @@ const isActive = ref(false);
|
||||
const isExist = ref(false);
|
||||
|
||||
const paginationConfig = reactive({
|
||||
cacheSizeKey: 'runtime-page-size',
|
||||
currentPage: 1,
|
||||
pageSize: Number(localStorage.getItem('runtime-page-size')) || 20,
|
||||
pageSize: 20,
|
||||
total: 0,
|
||||
});
|
||||
useSearchState(
|
||||
'website/runtime/java/index',
|
||||
{
|
||||
page: toRef(paginationConfig, 'currentPage'),
|
||||
pageSize: toRef(paginationConfig, 'pageSize'),
|
||||
},
|
||||
{ onRevisit: () => search() },
|
||||
);
|
||||
const req = reactive<Runtime.RuntimeReq>({
|
||||
name: '',
|
||||
page: 1,
|
||||
|
||||
@@ -103,6 +103,8 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { toRef } from 'vue';
|
||||
import { useSearchState } from '@/utils/search-reset';
|
||||
import { onMounted, reactive, ref } from 'vue';
|
||||
import { Runtime } from '@/api/interface/runtime';
|
||||
import { RuntimeDeleteCheck, SearchRuntimes, SyncRuntime } from '@/api/modules/runtime';
|
||||
@@ -141,11 +143,18 @@ const isActive = ref(false);
|
||||
const isExist = ref(false);
|
||||
|
||||
const paginationConfig = reactive({
|
||||
cacheSizeKey: 'runtime-page-size',
|
||||
currentPage: 1,
|
||||
pageSize: Number(localStorage.getItem('runtime-page-size')) || 20,
|
||||
pageSize: 20,
|
||||
total: 0,
|
||||
});
|
||||
useSearchState(
|
||||
'website/runtime/node/index',
|
||||
{
|
||||
page: toRef(paginationConfig, 'currentPage'),
|
||||
pageSize: toRef(paginationConfig, 'pageSize'),
|
||||
},
|
||||
{ onRevisit: () => search() },
|
||||
);
|
||||
const req = reactive<Runtime.RuntimeReq>({
|
||||
name: '',
|
||||
page: 1,
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useSearchReset } from '@/composables/useSearchReset';
|
||||
import { useSearchState } from '@/utils/search-reset';
|
||||
import { Runtime } from '@/api/interface/runtime';
|
||||
import { GetPHPExtensions, InstallPHPExtension, UnInstallPHPExtension } from '@/api/modules/runtime';
|
||||
import i18n from '@/lang';
|
||||
@@ -49,7 +49,11 @@ const supportExtensions = ref([]);
|
||||
const loading = ref(false);
|
||||
const taskLogRef = ref();
|
||||
const searchName = ref('');
|
||||
useSearchReset({ search: searchName }, { onRevisit: () => searchByName() });
|
||||
useSearchState(
|
||||
'website/runtime/php/extension-management/index',
|
||||
{ search: searchName },
|
||||
{ onRevisit: () => searchByName() },
|
||||
);
|
||||
const data = ref([]);
|
||||
|
||||
const handleClose = () => {
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
</DrawerPro>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { readCachedPageSize } from '@/utils/panel-cache';
|
||||
import { DeletePHPExtensions, SearchPHPExtensions } from '@/api/modules/runtime';
|
||||
import { reactive, ref } from 'vue';
|
||||
import Create from './operate/index.vue';
|
||||
@@ -38,7 +39,7 @@ const opRef = ref();
|
||||
const paginationConfig = reactive({
|
||||
cacheSizeKey: 'website-page-size',
|
||||
currentPage: 1,
|
||||
pageSize: Number(localStorage.getItem('website-page-size')) || 20,
|
||||
pageSize: readCachedPageSize('website-page-size') || 20,
|
||||
total: 0,
|
||||
});
|
||||
|
||||
|
||||
@@ -135,6 +135,8 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { toRef } from 'vue';
|
||||
import { useSearchState } from '@/utils/search-reset';
|
||||
import { onMounted, reactive, ref } from 'vue';
|
||||
import { Runtime } from '@/api/interface/runtime';
|
||||
import { RuntimeDeleteCheck, SearchRuntimes } from '@/api/modules/runtime';
|
||||
@@ -165,11 +167,18 @@ const { isMobile } = useGlobalStore();
|
||||
|
||||
const taskLogRef = ref();
|
||||
const paginationConfig = reactive({
|
||||
cacheSizeKey: 'runtime-page-size',
|
||||
currentPage: 1,
|
||||
pageSize: Number(localStorage.getItem('runtime-page-size')) || 20,
|
||||
pageSize: 20,
|
||||
total: 0,
|
||||
});
|
||||
useSearchState(
|
||||
'website/runtime/php/index',
|
||||
{
|
||||
page: toRef(paginationConfig, 'currentPage'),
|
||||
pageSize: toRef(paginationConfig, 'pageSize'),
|
||||
},
|
||||
{ onRevisit: () => search() },
|
||||
);
|
||||
let req = reactive<Runtime.RuntimeReq>({
|
||||
name: '',
|
||||
page: 1,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user