build(frontend): Vite 4.3.1 -> 7.3.6 и уборка мёртвых редакторов конфига

Решение «Vite не трогать» пересмотрено по данным, а не по желанию обновиться.
`pnpm audit --prod` (то, на что смотрит gate сборки) был чист, но полный audit
показывал в build-цепочке два critical и rollup GHSA DOM clobbering — а он
затрагивает ГЕНЕРИРУЕМЫЙ bundle, то есть уезжает в production. Vite 4.3.1 тянул
rollup 3 без исправления.

Взята 7.3.6 — последняя линия до Rolldown. Vite 8 по-прежнему не берётся: это
смена бандлера, отдельная работа с собственной приёмкой.

Вместе с Vite обновлена цепочка плагинов (@vitejs/plugin-vue 4 -> 6,
unplugin-* и unocss с версий 2022-2023 годов) и линтеры (@typescript-eslint
5 -> 8, prettier 2 -> 3, stylelint 15 -> 17). Новый @typescript-eslint нашёл 7
настоящих замечаний — исправлены по существу, а не подавлением правил; среди
них подавление несуществующего правила ban-types и `{}` вместо `object`.

Отдельно — три мёртвых редактора. Outbounds уже был разобран, здесь то же
самое для ImputMultiple (ACME-домены, inline ACL) и MapAdd (параметры ACME DNS,
заголовки masquerade): оба редактировали конфиг Hysteria в форме с
:disabled="true", получали значения без v-model и эмитили события, которых
никто не слушает, на странице без единого маршрута записи.

Цена ImputMultiple была измеримой. vuedraggable поставляется UMD-сборкой,
поэтому её require("vue") разрешался в vue/dist/vue.cjs.prod.js — полную сборку
Vue с рантайм-компилятором шаблонов. В бандл уезжало ~500 КБ исходников
(vuedraggable + sortablejs + compiler-core + compiler-dom) ради перетаскивания
тегов в недоступной для редактирования форме.

Разбор bundle через sourcemap нашёл и вторую потерю: @vueuse/core собирался
дважды — наш 13.9.0 и 14.4.0 из element-plus. Версии сведены.

bundle: 2 813 525 против 2 404 202 на исходной базовой линии (+17% за Vue 3.5,
Element Plus 2.14, echarts 6 и rollup 4). Промежуточное состояние без этих двух
исправлений было 3 046 172.

pnpm audit --prod: чисто. typecheck/eslint/stylelint: 0. go build с dist: OK.
This commit is contained in:
2026-08-30 07:29:53 +05:00
parent 7f4cc10d25
commit ddd1020a3a
22 changed files with 2393 additions and 2702 deletions
+24 -1
View File
@@ -1,9 +1,26 @@
{ {
"globals": { "globals": {
"Component": true,
"ComponentPublicInstance": true,
"ComputedRef": true,
"DirectiveBinding": true,
"EffectScope": true, "EffectScope": true,
"ElForm": true, "ElForm": true,
"ElMessage": true, "ElMessage": true,
"ElMessageBox": true, "ElMessageBox": true,
"ExtractDefaultPropTypes": true,
"ExtractPropTypes": true,
"ExtractPublicPropTypes": true,
"InjectionKey": true,
"MaybeRef": true,
"MaybeRefOrGetter": true,
"PropType": true,
"Ref": true,
"ShallowRef": true,
"Slot": true,
"Slots": true,
"VNode": true,
"WritableComputedRef": true,
"computed": true, "computed": true,
"createApp": true, "createApp": true,
"customRef": true, "customRef": true,
@@ -12,12 +29,14 @@
"effectScope": true, "effectScope": true,
"getCurrentInstance": true, "getCurrentInstance": true,
"getCurrentScope": true, "getCurrentScope": true,
"getCurrentWatcher": true,
"h": true, "h": true,
"inject": true, "inject": true,
"isProxy": true, "isProxy": true,
"isReactive": true, "isReactive": true,
"isReadonly": true, "isReadonly": true,
"isRef": true, "isRef": true,
"isShallow": true,
"markRaw": true, "markRaw": true,
"nextTick": true, "nextTick": true,
"onActivated": true, "onActivated": true,
@@ -33,25 +52,29 @@
"onServerPrefetch": true, "onServerPrefetch": true,
"onUnmounted": true, "onUnmounted": true,
"onUpdated": true, "onUpdated": true,
"onWatcherCleanup": true,
"provide": true, "provide": true,
"reactive": true, "reactive": true,
"readonly": true, "readonly": true,
"ref": true, "ref": true,
"resolveComponent": true, "resolveComponent": true,
"resolveDirective": true,
"shallowReactive": true, "shallowReactive": true,
"shallowReadonly": true, "shallowReadonly": true,
"shallowRef": true, "shallowRef": true,
"toRaw": true, "toRaw": true,
"toRef": true, "toRef": true,
"toRefs": true, "toRefs": true,
"toValue": true,
"triggerRef": true, "triggerRef": true,
"unref": true, "unref": true,
"useAttrs": true, "useAttrs": true,
"useCssModule": true, "useCssModule": true,
"useCssVars": true, "useCssVars": true,
"useFullscreen": true, "useFullscreen": true,
"useId": true,
"useModel": true,
"useSlots": true, "useSlots": true,
"useTemplateRef": true,
"useVModel": true, "useVModel": true,
"watch": true, "watch": true,
"watchEffect": true, "watchEffect": true,
+6
View File
@@ -25,6 +25,12 @@ module.exports = {
"custom-property-pattern": null, // Custom property naming rule "custom-property-pattern": null, // Custom property naming rule
"keyframes-name-pattern": null, // Keyframe naming rule "keyframes-name-pattern": null, // Keyframe naming rule
"no-descending-specificity": null, // Allow non-descending specificity "no-descending-specificity": null, // Allow non-descending specificity
// Пустая строка `//` внутри блока комментария — абзацный разделитель, а не
// забытый комментарий. Правило появилось в stylelint-config-recommended-scss
// 17 и требует либо склеивать абзацы, либо разрывать блок пустой строкой;
// и то и другое ухудшает читаемость объяснений, ради которых эти
// комментарии написаны.
"scss/comment-no-empty": null,
// Allow global, export and deep pseudo classes // Allow global, export and deep pseudo classes
"selector-pseudo-class-no-unknown": [ "selector-pseudo-class-no-unknown": [
true, true,
+1 -1
View File
@@ -1,4 +1,4 @@
<!DOCTYPE html> <!doctype html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
+27 -27
View File
@@ -17,7 +17,7 @@
}, },
"dependencies": { "dependencies": {
"@element-plus/icons-vue": "^2.3.2", "@element-plus/icons-vue": "^2.3.2",
"@vueuse/core": "^13.9.0", "@vueuse/core": "^14.4.0",
"axios": "^1.20.0", "axios": "^1.20.0",
"copy-to-clipboard": "^3.3.3", "copy-to-clipboard": "^3.3.3",
"echarts": "^6.1.0", "echarts": "^6.1.0",
@@ -29,39 +29,39 @@
"vue": "^3.5.42", "vue": "^3.5.42",
"vue-echarts": "^8.1.0", "vue-echarts": "^8.1.0",
"vue-i18n": "^9.14.5", "vue-i18n": "^9.14.5",
"vue-router": "^4.6.4", "vue-router": "^4.6.4"
"vuedraggable": "^4.1.0"
}, },
"devDependencies": { "devDependencies": {
"@iconify-json/ep": "^1.1.8", "@iconify-json/ep": "^1.2.4",
"@types/nprogress": "^0.2.0", "@types/nprogress": "^0.2.0",
"@types/path-browserify": "^1.0.0", "@types/path-browserify": "^1.0.0",
"@typescript-eslint/eslint-plugin": "^5.51.0", "@typescript-eslint/eslint-plugin": "^8.68.0",
"@typescript-eslint/parser": "^5.51.0", "@typescript-eslint/parser": "^8.68.0",
"@vitejs/plugin-vue": "^4.0.0", "@vitejs/plugin-vue": "^6.0.8",
"autoprefixer": "^10.4.13", "autoprefixer": "^10.4.13",
"eslint": "^8.34.0", "eslint": "^8.57.1",
"eslint-config-prettier": "^8.8.0", "eslint-config-prettier": "^9.1.0",
"eslint-plugin-prettier": "^4.2.1", "eslint-plugin-prettier": "^5.5.6",
"eslint-plugin-vue": "^9.9.0", "eslint-plugin-vue": "^9.33.0",
"postcss": "^8.5.26", "postcss": "^8.5.26",
"postcss-html": "^1.5.0", "postcss-html": "^2.0.0",
"postcss-scss": "^4.0.6", "postcss-scss": "^4.0.9",
"prettier": "^2.8.7", "prettier": "^3.9.6",
"sass": "^1.103.1", "sass": "^1.103.1",
"stylelint": "^15.5.0", "stylelint": "^17.14.1",
"stylelint-config-html": "^1.1.0", "stylelint-config-html": "^2.0.0",
"stylelint-config-recess-order": "^4.0.0", "stylelint-config-recess-order": "^7.8.0",
"stylelint-config-recommended-scss": "^9.0.1", "stylelint-config-recommended-scss": "^17.0.1",
"stylelint-config-recommended-vue": "^1.4.0", "stylelint-config-recommended-vue": "^2.0.0",
"stylelint-config-standard": "^32.0.0", "stylelint-config-standard": "^40.0.0",
"stylelint-config-standard-scss": "^8.0.0", "stylelint-config-standard-scss": "^17.0.0",
"stylelint-order": "8.0.0",
"typescript": "^5.9.3", "typescript": "^5.9.3",
"unocss": "^0.50.1", "unocss": "^66.8.1",
"unplugin-auto-import": "^0.13.0", "unplugin-auto-import": "^21.1.0",
"unplugin-icons": "^0.15.1", "unplugin-icons": "^23.0.1",
"unplugin-vue-components": "^0.23.0", "unplugin-vue-components": "^32.1.0",
"vite": "^4.3.1", "vite": "^7.3.6",
"vite-plugin-svg-icons": "^2.0.1", "vite-plugin-svg-icons": "^2.0.1",
"vue-tsc": "^3.3.11" "vue-tsc": "^3.3.11"
}, },
@@ -72,6 +72,6 @@
} }
}, },
"engines": { "engines": {
"node": ">=18.12.0" "node": "^20.19.0 || >=22.12.0"
} }
} }
+2039 -2229
View File
File diff suppressed because it is too large Load Diff
@@ -50,8 +50,8 @@ import type {
type DeepRequired<T> = T extends (infer U)[] type DeepRequired<T> = T extends (infer U)[]
? DeepRequired<U>[] ? DeepRequired<U>[]
: T extends object : T extends object
? { [K in keyof T]-?: DeepRequired<NonNullable<T[K]>> } ? { [K in keyof T]-?: DeepRequired<NonNullable<T[K]>> }
: T; : T;
/** Конфиг Hysteria в том виде, в котором его показывает панель. */ /** Конфиг Hysteria в том виде, в котором его показывает панель. */
export type Hysteria2ServerConfigView = DeepRequired<Hysteria2ServerConfig>; export type Hysteria2ServerConfigView = DeepRequired<Hysteria2ServerConfig>;
@@ -1,29 +1,40 @@
<template> <template>
<draggable class="flex gap-2" :list="tags" item-key="id" animation="200"> <div class="flex gap-2">
<template #item="{ element }"> <el-tag v-for="item in tags" :key="item" size="large">
<el-tag closable @close="handleClose(element)" size="large"> {{ item }}
{{ element }} </el-tag>
</el-tag> <el-text v-if="!tags.length" type="info"></el-text>
</template> </div>
<template #footer>
<el-input
v-if="inputVisible"
ref="inputRef"
v-model="tag"
class="w-50"
@keyup.enter="handleConfirm"
@blur="handleConfirm"
/>
<el-button v-else @click="showInput">+</el-button>
</template>
</draggable>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import draggable from "vuedraggable";
import { ElInput } from "element-plus";
import { PropType } from "vue"; import { PropType } from "vue";
/**
* Список строковых значений конфигурации: ACME-домены, inline-правила ACL.
*
* Компонент только показывает список, и это приведение UI в соответствие с тем,
* что продукт умеет, а не сокращение возможностей.
*
* Что было. Здесь жил редактор на `vuedraggable`: перетаскивание тегов,
* closable-теги с удалением, поле ввода нового значения и
* `emit("update:tags")`. Сохранить он ничего не мог — единственное место
* использования — форма конфига Hysteria, отрисованная с `:disabled="true"`,
* причём значения передаются как `:tags="dataForm.acme.domains"`, без v-model,
* то есть слушателя у события не существует. Маршрутов записи серверного
* конфига в API нет.
*
* Цена этого редактора была измеримой. `vuedraggable` поставляется UMD-сборкой,
* поэтому её `require("vue")` разрешался в `vue/dist/vue.cjs.prod.js` — полную
* сборку Vue вместе с рантайм-компилятором шаблонов. В бандл уезжало:
*
* vuedraggable ~155 КБ
* sortablejs ~115 КБ
* @vue/compiler-core + compiler-dom ~230 КБ
*
* то есть около полумегабайта исходников ради перетаскивания тегов в форме,
* которая недоступна для редактирования.
*/
const props = defineProps({ const props = defineProps({
tags: { tags: {
required: false, required: false,
@@ -32,42 +43,7 @@ const props = defineProps({
}, },
}); });
const emit = defineEmits<{ const tags = computed(() => props.tags ?? []);
(event: "update:tags", value: string[]): void;
}>();
const tags = useVModel(props, "tags", emit);
const inputRef = ref(ElInput);
const state = reactive({
tag: "",
inputVisible: false,
});
const { tag, inputVisible } = toRefs(state);
const showInput = () => {
state.inputVisible = true;
nextTick(() => {
inputRef.value!.input!.focus();
});
};
const handleConfirm = (): void => {
const newTag = state.tag.trim();
if (newTag && !tags.value?.includes(newTag)) {
tags.value?.push(newTag);
state.tag = "";
}
state.inputVisible = false;
};
const handleClose = (tag: string): void => {
const index = tags.value?.indexOf(tag.trim());
if (index !== -1) {
tags.value?.splice(index, 1);
}
};
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
+21 -152
View File
@@ -1,71 +1,9 @@
<template> <template>
<div class="flex gap-2"> <div class="flex gap-2">
<el-tag <el-tag v-for="entry in entries" :key="entry.key" size="large">
:key="key" {{ entry.key }}: {{ entry.value }}
v-for="(value, key) in mapObject"
@close="handleClose(key)"
@click="handleInfo(key)"
size="large"
closable
>
{{ key }}
</el-tag> </el-tag>
<el-text v-if="!entries.length" type="info"></el-text>
<el-button @click="handleAdd">+</el-button>
<el-dialog
:title="dialog.title"
v-model="dialog.visible"
width="600px"
append-to-body
@close="closeDialog"
>
<el-form
ref="dataFormRef"
:rules="dataFormRules"
label-position="top"
:model="dataForm"
>
<el-form-item label="key" prop="key">
<el-input v-model="dataForm.key" clearable />
</el-form-item>
<el-form-item label="value" prop="value">
<el-input v-model="dataForm.value" clearable />
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="submitForm"
>{{ $t("common.confirm") }}
</el-button>
<el-button @click="closeDialog">{{ $t("common.cancel") }}</el-button>
</div>
</template>
</el-dialog>
<el-dialog
:title="infoDialog.title"
v-model="infoDialog.visible"
width="600px"
append-to-body
@close="infoDialog.visible = false"
>
<el-form label-position="top">
<el-form-item label="key" prop="key">
<el-tag>{{ dataInfo.key }}</el-tag>
</el-form-item>
<el-form-item label="value" prop="value">
<el-tag>{{ dataInfo.value }}</el-tag>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button @click="infoDialog.visible = false"
>{{ $t("common.cancel") }}
</el-button>
</div>
</template>
</el-dialog>
</div> </div>
</template> </template>
@@ -77,13 +15,22 @@ export default {
<script setup lang="ts"> <script setup lang="ts">
import { PropType } from "vue"; import { PropType } from "vue";
import { useI18n } from "vue-i18n";
interface Form {
key: string;
value: string;
}
/**
* Словарь «ключ — значение» из конфигурации: параметры ACME DNS-провайдера,
* заголовки masquerade.
*
* Как и ImputMultiple, компонент только показывает содержимое. Здесь был
* редактор с диалогом добавления, closable-тегами и `emit("update:mapObject")`,
* и он ничего не сохранял по тем же трём причинам: форма конфига Hysteria
* отрисована с `:disabled="true"`, значения передаются как
* `:map-object="dataForm.acme.dns.config"` без v-model, маршрутов записи
* серверного конфига в API нет.
*
* Значение показывается рядом с ключом: прежний вариант прятал его во второй
* диалог по клику на тег, что для read-only страницы лишний шаг — увидеть
* настройку сервера нужно сразу.
*/
const props = defineProps({ const props = defineProps({
mapObject: { mapObject: {
required: false, required: false,
@@ -92,87 +39,9 @@ const props = defineProps({
}, },
}); });
const emit = defineEmits<{ const entries = computed(() =>
(event: "update:mapObject", value: { [key: string]: string }): void; Object.entries(props.mapObject ?? {}).map(([key, value]) => ({ key, value }))
}>(); );
const mapObject = useVModel(props, "mapObject", emit);
const { t } = useI18n();
const dataFormRef = ref(ElForm);
const dataFormRules = {
key: [
{
required: true,
message: t("common.required"),
trigger: ["change", "blur"],
},
],
value: [
{
required: true,
message: t("common.required"),
trigger: ["change", "blur"],
},
],
};
const state = reactive({
dataForm: {
key: "",
value: "",
} as Form,
dialog: {
title: "Add",
visible: false,
} as DialogType,
infoDialog: {
title: "Info",
visible: false,
},
dataInfo: {
key: "",
value: "",
} as Form,
});
const { dataForm, dialog, infoDialog, dataInfo } = toRefs(state);
const handleAdd = () => {
state.dialog.visible = true;
};
const handleClose = (key: string): void => {
delete mapObject.value[key];
};
const handleInfo = (key: string) => {
state.dataInfo = {
key: key,
value: mapObject.value[key] || "",
};
state.infoDialog.visible = true;
};
const submitForm = () => {
dataFormRef.value.validate((valid: any) => {
if (valid) {
if (mapObject.value[state.dataForm.key]) {
ElMessage.error(t("common.invalid"));
return;
}
mapObject.value[state.dataForm.key] = state.dataForm.value;
closeDialog();
}
});
};
const closeDialog = (): void => {
state.dialog.visible = false;
dataFormRef.value.resetFields();
dataFormRef.value.clearValidate();
};
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
@@ -16,7 +16,7 @@ export const hasRole: Directive = {
}); });
if (!hasRole) { if (!hasRole) {
el.parentNode && el.parentNode.removeChild(el); el.parentNode?.removeChild(el);
} }
} else { } else {
throw new Error("need roles! Like v-has-role=\"['admin', 'user']\""); throw new Error("need roles! Like v-has-role=\"['admin', 'user']\"");
+1 -1
View File
@@ -72,8 +72,8 @@ function handleOutsideClick() {
<style lang="scss" scoped> <style lang="scss" scoped>
.app-wrapper { .app-wrapper {
&::after { &::after {
display: table;
clear: both; clear: both;
display: table;
content: ""; content: "";
} }
+6 -2
View File
@@ -36,7 +36,11 @@ router.beforeEach(async (to, from, next) => {
} }
// Если маршрут не найден, перейти на 404 // Если маршрут не найден, перейти на 404
if (to.matched.length === 0) { if (to.matched.length === 0) {
from.name ? next({ name: from.name }) : next("/404"); if (from.name) {
next({ name: from.name });
} else {
next("/404");
}
} else { } else {
next(); next();
} }
@@ -58,7 +62,7 @@ router.beforeEach(async (to, from, next) => {
return; return;
} }
next({ ...to, replace: true }); next({ ...to, replace: true });
} catch (error) { } catch {
// Удалить token и перейти на страницу входа // Удалить token и перейти на страницу входа
await adminStore.resetToken(); await adminStore.resetToken();
next(`/login?redirect=${to.path}`); next(`/login?redirect=${to.path}`);
+2 -1
View File
@@ -13,7 +13,8 @@
} }
.peg { .peg {
box-shadow: 0 0 10px var(--el-color-primary), box-shadow:
0 0 10px var(--el-color-primary),
0 0 5px var(--el-color-primary); 0 0 5px var(--el-color-primary);
} }
+2 -1
View File
@@ -25,7 +25,8 @@ body {
width: 100%; width: 100%;
height: 100%; height: 100%;
margin: 0; margin: 0;
font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", font-family:
"Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB",
"Microsoft YaHei", Arial, sans-serif; "Microsoft YaHei", Arial, sans-serif;
line-height: inherit; line-height: inherit;
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;
+5 -3
View File
@@ -20,7 +20,9 @@
// reset element-ui css // reset element-ui css
.horizontal-collapse-transition { .horizontal-collapse-transition {
transition: 0s width ease-in-out, 0s padding-left ease-in-out, transition:
0s width ease-in-out,
0s padding-left ease-in-out,
0s padding-right ease-in-out; 0s padding-right ease-in-out;
} }
@@ -178,10 +180,10 @@
& > .el-sub-menu__title { & > .el-sub-menu__title {
& > span { & > span {
display: inline-block; display: inline-block;
visibility: hidden;
width: 0; width: 0;
height: 0; height: 0;
overflow: hidden; overflow: hidden;
visibility: hidden;
} }
} }
} }
@@ -206,8 +208,8 @@
&.hideSidebar { &.hideSidebar {
.sidebar-container { .sidebar-container {
pointer-events: none; pointer-events: none;
transition-duration: 0.3s;
transform: translate3d(-$sideBarWidth, 0, 0); transform: translate3d(-$sideBarWidth, 0, 0);
transition-duration: 0.3s;
} }
} }
} }
+146 -155
View File
@@ -1,160 +1,151 @@
// Generated by 'unplugin-auto-import' /* eslint-disable */
export {}; /* prettier-ignore */
/* oxlint-disable */
/* oxfmt-ignore */
// @ts-nocheck
// noinspection JSUnusedGlobalSymbols
// Generated by unplugin-auto-import
// biome-ignore lint: disable
export {}
declare global { declare global {
const EffectScope: typeof import("vue")["EffectScope"]; const EffectScope: typeof import('vue').EffectScope
const ElForm: typeof import("element-plus/es")["ElForm"]; const ElForm: typeof import('element-plus/es').ElForm
const ElMessage: typeof import("element-plus/es")["ElMessage"]; const ElMessage: typeof import('element-plus/es').ElMessage
const ElMessageBox: typeof import("element-plus/es")["ElMessageBox"]; const ElMessageBox: typeof import('element-plus/es').ElMessageBox
const computed: typeof import("vue")["computed"]; const computed: typeof import('vue').computed
const createApp: typeof import("vue")["createApp"]; const createApp: typeof import('vue').createApp
const customRef: typeof import("vue")["customRef"]; const customRef: typeof import('vue').customRef
const defineAsyncComponent: typeof import("vue")["defineAsyncComponent"]; const defineAsyncComponent: typeof import('vue').defineAsyncComponent
const defineComponent: typeof import("vue")["defineComponent"]; const defineComponent: typeof import('vue').defineComponent
const effectScope: typeof import("vue")["effectScope"]; const effectScope: typeof import('vue').effectScope
const getCurrentInstance: typeof import("vue")["getCurrentInstance"]; const getCurrentInstance: typeof import('vue').getCurrentInstance
const getCurrentScope: typeof import("vue")["getCurrentScope"]; const getCurrentScope: typeof import('vue').getCurrentScope
const h: typeof import("vue")["h"]; const getCurrentWatcher: typeof import('vue').getCurrentWatcher
const inject: typeof import("vue")["inject"]; const h: typeof import('vue').h
const isProxy: typeof import("vue")["isProxy"]; const inject: typeof import('vue').inject
const isReactive: typeof import("vue")["isReactive"]; const isProxy: typeof import('vue').isProxy
const isReadonly: typeof import("vue")["isReadonly"]; const isReactive: typeof import('vue').isReactive
const isRef: typeof import("vue")["isRef"]; const isReadonly: typeof import('vue').isReadonly
const markRaw: typeof import("vue")["markRaw"]; const isRef: typeof import('vue').isRef
const nextTick: typeof import("vue")["nextTick"]; const isShallow: typeof import('vue').isShallow
const onActivated: typeof import("vue")["onActivated"]; const markRaw: typeof import('vue').markRaw
const onBeforeMount: typeof import("vue")["onBeforeMount"]; const nextTick: typeof import('vue').nextTick
const onBeforeUnmount: typeof import("vue")["onBeforeUnmount"]; const onActivated: typeof import('vue').onActivated
const onBeforeUpdate: typeof import("vue")["onBeforeUpdate"]; const onBeforeMount: typeof import('vue').onBeforeMount
const onDeactivated: typeof import("vue")["onDeactivated"]; const onBeforeUnmount: typeof import('vue').onBeforeUnmount
const onErrorCaptured: typeof import("vue")["onErrorCaptured"]; const onBeforeUpdate: typeof import('vue').onBeforeUpdate
const onMounted: typeof import("vue")["onMounted"]; const onDeactivated: typeof import('vue').onDeactivated
const onRenderTracked: typeof import("vue")["onRenderTracked"]; const onErrorCaptured: typeof import('vue').onErrorCaptured
const onRenderTriggered: typeof import("vue")["onRenderTriggered"]; const onMounted: typeof import('vue').onMounted
const onScopeDispose: typeof import("vue")["onScopeDispose"]; const onRenderTracked: typeof import('vue').onRenderTracked
const onServerPrefetch: typeof import("vue")["onServerPrefetch"]; const onRenderTriggered: typeof import('vue').onRenderTriggered
const onUnmounted: typeof import("vue")["onUnmounted"]; const onScopeDispose: typeof import('vue').onScopeDispose
const onUpdated: typeof import("vue")["onUpdated"]; const onServerPrefetch: typeof import('vue').onServerPrefetch
const provide: typeof import("vue")["provide"]; const onUnmounted: typeof import('vue').onUnmounted
const reactive: typeof import("vue")["reactive"]; const onUpdated: typeof import('vue').onUpdated
const readonly: typeof import("vue")["readonly"]; const onWatcherCleanup: typeof import('vue').onWatcherCleanup
const ref: typeof import("vue")["ref"]; const provide: typeof import('vue').provide
const resolveComponent: typeof import("vue")["resolveComponent"]; const reactive: typeof import('vue').reactive
const resolveDirective: typeof import("vue")["resolveDirective"]; const readonly: typeof import('vue').readonly
const shallowReactive: typeof import("vue")["shallowReactive"]; const ref: typeof import('vue').ref
const shallowReadonly: typeof import("vue")["shallowReadonly"]; const resolveComponent: typeof import('vue').resolveComponent
const shallowRef: typeof import("vue")["shallowRef"]; const shallowReactive: typeof import('vue').shallowReactive
const toRaw: typeof import("vue")["toRaw"]; const shallowReadonly: typeof import('vue').shallowReadonly
const toRef: typeof import("vue")["toRef"]; const shallowRef: typeof import('vue').shallowRef
const toRefs: typeof import("vue")["toRefs"]; const toRaw: typeof import('vue').toRaw
const triggerRef: typeof import("vue")["triggerRef"]; const toRef: typeof import('vue').toRef
const unref: typeof import("vue")["unref"]; const toRefs: typeof import('vue').toRefs
const useAttrs: typeof import("vue")["useAttrs"]; const toValue: typeof import('vue').toValue
const useCssModule: typeof import("vue")["useCssModule"]; const triggerRef: typeof import('vue').triggerRef
const useCssVars: typeof import("vue")["useCssVars"]; const unref: typeof import('vue').unref
const useFullscreen: typeof import("@vueuse/core")["useFullscreen"]; const useAttrs: typeof import('vue').useAttrs
const useSlots: typeof import("vue")["useSlots"]; const useCssModule: typeof import('vue').useCssModule
const useVModel: typeof import("@vueuse/core")["useVModel"]; const useCssVars: typeof import('vue').useCssVars
const watch: typeof import("vue")["watch"]; const useFullscreen: typeof import('@vueuse/core').useFullscreen
const watchEffect: typeof import("vue")["watchEffect"]; const useId: typeof import('vue').useId
const watchPostEffect: typeof import("vue")["watchPostEffect"]; const useModel: typeof import('vue').useModel
const watchSyncEffect: typeof import("vue")["watchSyncEffect"]; const useSlots: typeof import('vue').useSlots
const useTemplateRef: typeof import('vue').useTemplateRef
const useVModel: typeof import('@vueuse/core').useVModel
const watch: typeof import('vue').watch
const watchEffect: typeof import('vue').watchEffect
const watchPostEffect: typeof import('vue').watchPostEffect
const watchSyncEffect: typeof import('vue').watchSyncEffect
} }
// for type re-export
declare global {
// @ts-ignore
export type { Component, Slot, Slots, ComponentPublicInstance, ComputedRef, DirectiveBinding, ExtractDefaultPropTypes, ExtractPropTypes, ExtractPublicPropTypes, InjectionKey, PropType, Ref, ShallowRef, MaybeRef, MaybeRefOrGetter, VNode, WritableComputedRef } from 'vue'
import('vue')
}
// for vue template auto import // for vue template auto import
import { UnwrapRef } from "vue"; import { UnwrapRef } from 'vue'
declare module "vue" { declare module 'vue' {
interface GlobalComponents {}
interface ComponentCustomProperties { interface ComponentCustomProperties {
readonly EffectScope: UnwrapRef<typeof import("vue")["EffectScope"]>; readonly EffectScope: UnwrapRef<typeof import('vue')['EffectScope']>
readonly ElForm: UnwrapRef<typeof import("element-plus/es")["ElForm"]>; readonly ElForm: UnwrapRef<typeof import('element-plus/es')['ElForm']>
readonly ElMessage: UnwrapRef< readonly ElMessage: UnwrapRef<typeof import('element-plus/es')['ElMessage']>
typeof import("element-plus/es")["ElMessage"] readonly ElMessageBox: UnwrapRef<typeof import('element-plus/es')['ElMessageBox']>
>; readonly computed: UnwrapRef<typeof import('vue')['computed']>
readonly ElMessageBox: UnwrapRef< readonly createApp: UnwrapRef<typeof import('vue')['createApp']>
typeof import("element-plus/es")["ElMessageBox"] readonly customRef: UnwrapRef<typeof import('vue')['customRef']>
>; readonly defineAsyncComponent: UnwrapRef<typeof import('vue')['defineAsyncComponent']>
readonly computed: UnwrapRef<typeof import("vue")["computed"]>; readonly defineComponent: UnwrapRef<typeof import('vue')['defineComponent']>
readonly createApp: UnwrapRef<typeof import("vue")["createApp"]>; readonly effectScope: UnwrapRef<typeof import('vue')['effectScope']>
readonly customRef: UnwrapRef<typeof import("vue")["customRef"]>; readonly getCurrentInstance: UnwrapRef<typeof import('vue')['getCurrentInstance']>
readonly defineAsyncComponent: UnwrapRef< readonly getCurrentScope: UnwrapRef<typeof import('vue')['getCurrentScope']>
typeof import("vue")["defineAsyncComponent"] readonly getCurrentWatcher: UnwrapRef<typeof import('vue')['getCurrentWatcher']>
>; readonly h: UnwrapRef<typeof import('vue')['h']>
readonly defineComponent: UnwrapRef< readonly inject: UnwrapRef<typeof import('vue')['inject']>
typeof import("vue")["defineComponent"] readonly isProxy: UnwrapRef<typeof import('vue')['isProxy']>
>; readonly isReactive: UnwrapRef<typeof import('vue')['isReactive']>
readonly effectScope: UnwrapRef<typeof import("vue")["effectScope"]>; readonly isReadonly: UnwrapRef<typeof import('vue')['isReadonly']>
readonly getCurrentInstance: UnwrapRef< readonly isRef: UnwrapRef<typeof import('vue')['isRef']>
typeof import("vue")["getCurrentInstance"] readonly isShallow: UnwrapRef<typeof import('vue')['isShallow']>
>; readonly markRaw: UnwrapRef<typeof import('vue')['markRaw']>
readonly getCurrentScope: UnwrapRef< readonly nextTick: UnwrapRef<typeof import('vue')['nextTick']>
typeof import("vue")["getCurrentScope"] readonly onActivated: UnwrapRef<typeof import('vue')['onActivated']>
>; readonly onBeforeMount: UnwrapRef<typeof import('vue')['onBeforeMount']>
readonly h: UnwrapRef<typeof import("vue")["h"]>; readonly onBeforeUnmount: UnwrapRef<typeof import('vue')['onBeforeUnmount']>
readonly inject: UnwrapRef<typeof import("vue")["inject"]>; readonly onBeforeUpdate: UnwrapRef<typeof import('vue')['onBeforeUpdate']>
readonly isProxy: UnwrapRef<typeof import("vue")["isProxy"]>; readonly onDeactivated: UnwrapRef<typeof import('vue')['onDeactivated']>
readonly isReactive: UnwrapRef<typeof import("vue")["isReactive"]>; readonly onErrorCaptured: UnwrapRef<typeof import('vue')['onErrorCaptured']>
readonly isReadonly: UnwrapRef<typeof import("vue")["isReadonly"]>; readonly onMounted: UnwrapRef<typeof import('vue')['onMounted']>
readonly isRef: UnwrapRef<typeof import("vue")["isRef"]>; readonly onRenderTracked: UnwrapRef<typeof import('vue')['onRenderTracked']>
readonly markRaw: UnwrapRef<typeof import("vue")["markRaw"]>; readonly onRenderTriggered: UnwrapRef<typeof import('vue')['onRenderTriggered']>
readonly nextTick: UnwrapRef<typeof import("vue")["nextTick"]>; readonly onScopeDispose: UnwrapRef<typeof import('vue')['onScopeDispose']>
readonly onActivated: UnwrapRef<typeof import("vue")["onActivated"]>; readonly onServerPrefetch: UnwrapRef<typeof import('vue')['onServerPrefetch']>
readonly onBeforeMount: UnwrapRef<typeof import("vue")["onBeforeMount"]>; readonly onUnmounted: UnwrapRef<typeof import('vue')['onUnmounted']>
readonly onBeforeUnmount: UnwrapRef< readonly onUpdated: UnwrapRef<typeof import('vue')['onUpdated']>
typeof import("vue")["onBeforeUnmount"] readonly onWatcherCleanup: UnwrapRef<typeof import('vue')['onWatcherCleanup']>
>; readonly provide: UnwrapRef<typeof import('vue')['provide']>
readonly onBeforeUpdate: UnwrapRef<typeof import("vue")["onBeforeUpdate"]>; readonly reactive: UnwrapRef<typeof import('vue')['reactive']>
readonly onDeactivated: UnwrapRef<typeof import("vue")["onDeactivated"]>; readonly readonly: UnwrapRef<typeof import('vue')['readonly']>
readonly onErrorCaptured: UnwrapRef< readonly ref: UnwrapRef<typeof import('vue')['ref']>
typeof import("vue")["onErrorCaptured"] readonly resolveComponent: UnwrapRef<typeof import('vue')['resolveComponent']>
>; readonly shallowReactive: UnwrapRef<typeof import('vue')['shallowReactive']>
readonly onMounted: UnwrapRef<typeof import("vue")["onMounted"]>; readonly shallowReadonly: UnwrapRef<typeof import('vue')['shallowReadonly']>
readonly onRenderTracked: UnwrapRef< readonly shallowRef: UnwrapRef<typeof import('vue')['shallowRef']>
typeof import("vue")["onRenderTracked"] readonly toRaw: UnwrapRef<typeof import('vue')['toRaw']>
>; readonly toRef: UnwrapRef<typeof import('vue')['toRef']>
readonly onRenderTriggered: UnwrapRef< readonly toRefs: UnwrapRef<typeof import('vue')['toRefs']>
typeof import("vue")["onRenderTriggered"] readonly toValue: UnwrapRef<typeof import('vue')['toValue']>
>; readonly triggerRef: UnwrapRef<typeof import('vue')['triggerRef']>
readonly onScopeDispose: UnwrapRef<typeof import("vue")["onScopeDispose"]>; readonly unref: UnwrapRef<typeof import('vue')['unref']>
readonly onServerPrefetch: UnwrapRef< readonly useAttrs: UnwrapRef<typeof import('vue')['useAttrs']>
typeof import("vue")["onServerPrefetch"] readonly useCssModule: UnwrapRef<typeof import('vue')['useCssModule']>
>; readonly useCssVars: UnwrapRef<typeof import('vue')['useCssVars']>
readonly onUnmounted: UnwrapRef<typeof import("vue")["onUnmounted"]>; readonly useFullscreen: UnwrapRef<typeof import('@vueuse/core')['useFullscreen']>
readonly onUpdated: UnwrapRef<typeof import("vue")["onUpdated"]>; readonly useId: UnwrapRef<typeof import('vue')['useId']>
readonly provide: UnwrapRef<typeof import("vue")["provide"]>; readonly useModel: UnwrapRef<typeof import('vue')['useModel']>
readonly reactive: UnwrapRef<typeof import("vue")["reactive"]>; readonly useSlots: UnwrapRef<typeof import('vue')['useSlots']>
readonly readonly: UnwrapRef<typeof import("vue")["readonly"]>; readonly useTemplateRef: UnwrapRef<typeof import('vue')['useTemplateRef']>
readonly ref: UnwrapRef<typeof import("vue")["ref"]>; readonly useVModel: UnwrapRef<typeof import('@vueuse/core')['useVModel']>
readonly resolveComponent: UnwrapRef< readonly watch: UnwrapRef<typeof import('vue')['watch']>
typeof import("vue")["resolveComponent"] readonly watchEffect: UnwrapRef<typeof import('vue')['watchEffect']>
>; readonly watchPostEffect: UnwrapRef<typeof import('vue')['watchPostEffect']>
readonly resolveDirective: UnwrapRef< readonly watchSyncEffect: UnwrapRef<typeof import('vue')['watchSyncEffect']>
typeof import("vue")["resolveDirective"]
>;
readonly shallowReactive: UnwrapRef<
typeof import("vue")["shallowReactive"]
>;
readonly shallowReadonly: UnwrapRef<
typeof import("vue")["shallowReadonly"]
>;
readonly shallowRef: UnwrapRef<typeof import("vue")["shallowRef"]>;
readonly toRaw: UnwrapRef<typeof import("vue")["toRaw"]>;
readonly toRef: UnwrapRef<typeof import("vue")["toRef"]>;
readonly toRefs: UnwrapRef<typeof import("vue")["toRefs"]>;
readonly triggerRef: UnwrapRef<typeof import("vue")["triggerRef"]>;
readonly unref: UnwrapRef<typeof import("vue")["unref"]>;
readonly useAttrs: UnwrapRef<typeof import("vue")["useAttrs"]>;
readonly useCssModule: UnwrapRef<typeof import("vue")["useCssModule"]>;
readonly useCssVars: UnwrapRef<typeof import("vue")["useCssVars"]>;
readonly useFullscreen: UnwrapRef<
typeof import("@vueuse/core")["useFullscreen"]
>;
readonly useSlots: UnwrapRef<typeof import("vue")["useSlots"]>;
readonly useVModel: UnwrapRef<typeof import("@vueuse/core")["useVModel"]>;
readonly watch: UnwrapRef<typeof import("vue")["watch"]>;
readonly watchEffect: UnwrapRef<typeof import("vue")["watchEffect"]>;
readonly watchPostEffect: UnwrapRef<
typeof import("vue")["watchPostEffect"]
>;
readonly watchSyncEffect: UnwrapRef<
typeof import("vue")["watchSyncEffect"]
>;
} }
} }
+61 -57
View File
@@ -1,64 +1,68 @@
// generated by unplugin-vue-components /* eslint-disable */
// We suggest you to commit this file into source control // @ts-nocheck
// biome-ignore lint: disable
// oxlint-disable
// ------
// Generated by unplugin-vue-components
// Read more: https://github.com/vuejs/core/pull/3399 // Read more: https://github.com/vuejs/core/pull/3399
import "@vue/runtime-core";
export {}; export {}
declare module "@vue/runtime-core" { /* prettier-ignore */
declare module 'vue' {
export interface GlobalComponents { export interface GlobalComponents {
ElAlert: typeof import("element-plus/es")["ElAlert"]; ElAlert: typeof import('element-plus/es')['ElAlert']
ElAvatar: typeof import("element-plus/es")["ElAvatar"]; ElAvatar: typeof import('element-plus/es')['ElAvatar']
ElButton: typeof import("element-plus/es")["ElButton"]; ElButton: typeof import('element-plus/es')['ElButton']
ElCard: typeof import("element-plus/es")["ElCard"]; ElCard: typeof import('element-plus/es')['ElCard']
ElCol: typeof import("element-plus/es")["ElCol"]; ElCol: typeof import('element-plus/es')['ElCol']
ElDatePicker: typeof import("element-plus/es")["ElDatePicker"]; ElDatePicker: typeof import('element-plus/es')['ElDatePicker']
ElDialog: typeof import("element-plus/es")["ElDialog"]; ElDialog: typeof import('element-plus/es')['ElDialog']
ElDrawer: typeof import("element-plus/es")["ElDrawer"]; ElDrawer: typeof import('element-plus/es')['ElDrawer']
ElDropdown: typeof import("element-plus/es")["ElDropdown"]; ElDropdown: typeof import('element-plus/es')['ElDropdown']
ElDropdownItem: typeof import("element-plus/es")["ElDropdownItem"]; ElDropdownItem: typeof import('element-plus/es')['ElDropdownItem']
ElDropdownMenu: typeof import("element-plus/es")["ElDropdownMenu"]; ElDropdownMenu: typeof import('element-plus/es')['ElDropdownMenu']
ElEmpty: typeof import("element-plus/es")["ElEmpty"]; ElEmpty: typeof import('element-plus/es')['ElEmpty']
ElForm: typeof import("element-plus/es")["ElForm"]; ElForm: typeof import('element-plus/es')['ElForm']
ElFormItem: typeof import("element-plus/es")["ElFormItem"]; ElFormItem: typeof import('element-plus/es')['ElFormItem']
ElInput: typeof import("element-plus/es")["ElInput"]; ElInput: typeof import('element-plus/es')['ElInput']
ElInputNumber: typeof import("element-plus/es")["ElInputNumber"]; ElInputNumber: typeof import('element-plus/es')['ElInputNumber']
ElMenu: typeof import("element-plus/es")["ElMenu"]; ElMenu: typeof import('element-plus/es')['ElMenu']
ElMenuItem: typeof import("element-plus/es")["ElMenuItem"]; ElMenuItem: typeof import('element-plus/es')['ElMenuItem']
ElOption: typeof import("element-plus/es")["ElOption"]; ElOption: typeof import('element-plus/es')['ElOption']
ElPagination: typeof import("element-plus/es")["ElPagination"]; ElPagination: typeof import('element-plus/es')['ElPagination']
ElProgress: typeof import("element-plus/es")["ElProgress"]; ElProgress: typeof import('element-plus/es')['ElProgress']
ElRadioButton: typeof import("element-plus/es")["ElRadioButton"]; ElRadioButton: typeof import('element-plus/es')['ElRadioButton']
ElRadioGroup: typeof import("element-plus/es")["ElRadioGroup"]; ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup']
ElRow: typeof import("element-plus/es")["ElRow"]; ElRow: typeof import('element-plus/es')['ElRow']
ElScrollbar: typeof import("element-plus/es")["ElScrollbar"]; ElScrollbar: typeof import('element-plus/es')['ElScrollbar']
ElSelect: typeof import("element-plus/es")["ElSelect"]; ElSelect: typeof import('element-plus/es')['ElSelect']
ElSubMenu: typeof import("element-plus/es")["ElSubMenu"]; ElSubMenu: typeof import('element-plus/es')['ElSubMenu']
ElSwitch: typeof import("element-plus/es")["ElSwitch"]; ElSwitch: typeof import('element-plus/es')['ElSwitch']
ElTable: typeof import("element-plus/es")["ElTable"]; ElTable: typeof import('element-plus/es')['ElTable']
ElTableColumn: typeof import("element-plus/es")["ElTableColumn"]; ElTableColumn: typeof import('element-plus/es')['ElTableColumn']
ElTabPane: typeof import("element-plus/es")["ElTabPane"]; ElTabPane: typeof import('element-plus/es')['ElTabPane']
ElTabs: typeof import("element-plus/es")["ElTabs"]; ElTabs: typeof import('element-plus/es')['ElTabs']
ElTag: typeof import("element-plus/es")["ElTag"]; ElTag: typeof import('element-plus/es')['ElTag']
ElText: typeof import("element-plus/es")["ElText"]; ElText: typeof import('element-plus/es')['ElText']
ElTooltip: typeof import("element-plus/es")["ElTooltip"]; ElTooltip: typeof import('element-plus/es')['ElTooltip']
ElUpload: typeof import("element-plus/es")["ElUpload"]; ElUpload: typeof import('element-plus/es')['ElUpload']
Hamburger: typeof import("./../components/Hamburger/index.vue")["default"]; Hamburger: typeof import('./../components/Hamburger/index.vue')['default']
IEpCaretBottom: typeof import("~icons/ep/caret-bottom")["default"]; IEpCaretBottom: typeof import('~icons/ep/caret-bottom')['default']
IEpDownload: typeof import("~icons/ep/download")["default"]; IEpDownload: typeof import('~icons/ep/download')['default']
IEpMoreFilled: typeof import("~icons/ep/more-filled")["default"]; IEpMoreFilled: typeof import('~icons/ep/more-filled')['default']
IEpRefresh: typeof import("~icons/ep/refresh")["default"]; IEpRefresh: typeof import('~icons/ep/refresh')['default']
IEpUserFilled: typeof import("~icons/ep/user-filled")["default"]; IEpUserFilled: typeof import('~icons/ep/user-filled')['default']
ImputMultiple: typeof import("./../components/ImputMultiple/index.vue")["default"]; ImputMultiple: typeof import('./../components/ImputMultiple/index.vue')['default']
LangSelect: typeof import("./../components/LangSelect/index.vue")["default"]; LangSelect: typeof import('./../components/LangSelect/index.vue')['default']
MapAdd: typeof import("./../components/MapAdd/index.vue")["default"]; MapAdd: typeof import('./../components/MapAdd/index.vue')['default']
Pagination: typeof import("./../components/Pagination/index.vue")["default"]; Pagination: typeof import('./../components/Pagination/index.vue')['default']
RouterLink: typeof import("vue-router")["RouterLink"]; RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import("vue-router")["RouterView"]; RouterView: typeof import('vue-router')['RouterView']
SvgIcon: typeof import("./../components/SvgIcon/index.vue")["default"]; SvgIcon: typeof import('./../components/SvgIcon/index.vue')['default']
UnitSelect: typeof import("./../components/UnitSelect/index.vue")["default"]; UnitSelect: typeof import('./../components/UnitSelect/index.vue')['default']
} }
export interface ComponentCustomProperties { export interface GlobalDirectives {
vLoading: typeof import("element-plus/es")["ElLoadingDirective"]; vLoading: typeof import('element-plus/es')['ElLoadingDirective']
} }
} }
+6 -2
View File
@@ -2,8 +2,12 @@
declare module "*.vue" { declare module "*.vue" {
import { DefineComponent } from "vue"; import { DefineComponent } from "vue";
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/ban-types // `object` вместо `{}`: последний допускает любое ненулевое значение,
const component: DefineComponent<{}, {}, any>; // включая 0 и "", то есть не ограничивает ничего. Правило ban-types, под
// которое здесь стояло подавление, в @typescript-eslint 8 удалено и
// разделено на точечные — само подавление ссылалось на несуществующее имя.
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const component: DefineComponent<object, object, any>;
export default component; export default component;
} }
+3 -3
View File
@@ -29,8 +29,8 @@
risk.severity === 'critical' risk.severity === 'critical'
? 'error' ? 'error'
: risk.severity === 'warning' : risk.severity === 'warning'
? 'warning' ? 'warning'
: 'info' : 'info'
" "
:closable="risk.dismissible" :closable="risk.dismissible"
class="mb-2" class="mb-2"
@@ -247,7 +247,7 @@ const loadDashboard = async () => {
securityRisks.value = secRes.data; securityRisks.value = secRes.data;
lastSuccessAt.value = Date.now(); lastSuccessAt.value = Date.now();
loadError.value = ""; loadError.value = "";
} catch (error) { } catch {
loadError.value = t("dashboard.refreshFailed"); loadError.value = t("dashboard.refreshFailed");
} finally { } finally {
loading.value = false; loading.value = false;
+1 -1
View File
@@ -242,8 +242,8 @@ function message() {
} }
&__return-home { &__return-home {
display: block;
float: left; float: left;
display: block;
width: 110px; width: 110px;
height: 36px; height: 36px;
font-size: 14px; font-size: 14px;
+4 -2
View File
@@ -222,10 +222,10 @@ const handleLogin = () => {
.el-input__inner { .el-input__inner {
color: #fff; color: #fff;
caret-color: #fff;
background: transparent; background: transparent;
border: 0; border: 0;
border-radius: 0; border-radius: 0;
caret-color: #fff;
&:-webkit-autofill { &:-webkit-autofill {
box-shadow: 0 0 0 1000px transparent inset !important; box-shadow: 0 0 0 1000px transparent inset !important;
@@ -237,7 +237,9 @@ const handleLogin = () => {
&:-webkit-autofill:hover, &:-webkit-autofill:hover,
&:-webkit-autofill:focus, &:-webkit-autofill:focus,
&:-webkit-autofill:active { &:-webkit-autofill:active {
transition: color 99999s ease-out, background-color 99999s ease-out; transition:
color 99999s ease-out,
background-color 99999s ease-out;
transition-delay: 99999s; transition-delay: 99999s;
} }
} }
+2 -2
View File
@@ -84,8 +84,8 @@
scope.row.quotaBytes < 0 scope.row.quotaBytes < 0
? undefined ? undefined
: trafficPercent(peerRow(scope.row)) >= 90 : trafficPercent(peerRow(scope.row)) >= 90
? 'exception' ? 'exception'
: undefined : undefined
" "
:show-text="false" :show-text="false"
/> />
+1 -3
View File
@@ -58,9 +58,7 @@ export default defineConfig((): UserConfig => {
}, },
plugins: [ plugins: [
vue(), vue(),
UnoCSS({ UnoCSS({/* options */}),
/* options */
}),
AutoImport({ AutoImport({
// Auto import Vue helpers: ref, reactive, toRef, etc. // Auto import Vue helpers: ref, reactive, toRef, etc.
// //