mirror of
https://github.com/MCSManager/MCSManager.git
synced 2025-01-12 14:54:34 +08:00
commit
cfd16fdf8a
1
frontend/components.d.ts
vendored
1
frontend/components.d.ts
vendored
@ -26,7 +26,6 @@ declare module 'vue' {
|
||||
AInput: typeof import('ant-design-vue/es')['Input']
|
||||
AInputGroup: typeof import('ant-design-vue/es')['InputGroup']
|
||||
AInputPassword: typeof import('ant-design-vue/es')['InputPassword']
|
||||
AInputSearch: typeof import('ant-design-vue/es')['InputSearch']
|
||||
AList: typeof import('ant-design-vue/es')['List']
|
||||
AListItem: typeof import('ant-design-vue/es')['ListItem']
|
||||
AListItemMeta: typeof import('ant-design-vue/es')['ListItemMeta']
|
||||
|
@ -182,7 +182,7 @@ const appMenus = computed(() => {
|
||||
setTheme(key as THEME);
|
||||
},
|
||||
conditions: !containerState.isDesignMode,
|
||||
onlyPC: true,
|
||||
onlyPC: false,
|
||||
menus: [
|
||||
{
|
||||
title: $t("TXT_CODE_673eac8e"),
|
||||
@ -300,7 +300,11 @@ const openPhoneMenu = (b = false) => {
|
||||
@click="openPhoneMenu(true)"
|
||||
></a-button>
|
||||
<div v-for="(item, index) in appMenus" :key="index">
|
||||
<a-dropdown v-if="item.menus && item.conditions && !item.onlyPC" placement="bottom">
|
||||
<a-dropdown
|
||||
v-if="item.menus && item.conditions && !item.onlyPC"
|
||||
class="phone-nav-button"
|
||||
placement="bottom"
|
||||
>
|
||||
<a-button type="text" :icon="h(item.icon)" size="small" @click.prevent></a-button>
|
||||
<template #overlay>
|
||||
<a-menu @click="(e: any) => item.click(String(e.key))">
|
||||
|
@ -1,5 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, computed } from "vue";
|
||||
import BetweenMenus from "../BetweenMenus.vue";
|
||||
import type { MountComponent, NodeStatus } from "@/types";
|
||||
import type { UserInstance } from "@/types/user";
|
||||
import { t } from "@/lang/i18n";
|
||||
@ -53,6 +54,7 @@ const instancesList = computed(() => {
|
||||
|
||||
const initNodes = async () => {
|
||||
await getNodes();
|
||||
nodes?.value?.sort((a, b) => (a.available === b.available ? 0 : a.available ? -1 : 1));
|
||||
if (!nodes.value?.length) {
|
||||
return message.error(t("TXT_CODE_e3d96a26"));
|
||||
}
|
||||
@ -125,6 +127,7 @@ const handleQueryInstance = throttle(async () => {
|
||||
|
||||
const handleChangeNode = async (item: NodeStatus) => {
|
||||
try {
|
||||
operationForm.value.currentPage = 1;
|
||||
currentRemoteNode.value = item;
|
||||
await initInstancesData();
|
||||
localStorage.setItem("pageSelectedRemote", JSON.stringify(item));
|
||||
@ -152,46 +155,55 @@ const handleChangeNode = async (item: NodeStatus) => {
|
||||
</a-typography-paragraph>
|
||||
<a-row :gutter="[24, 24]" style="height: 100%">
|
||||
<a-col :span="24">
|
||||
<div class="flex-between flex-wrap align-center">
|
||||
<a-dropdown>
|
||||
<template #overlay>
|
||||
<a-menu>
|
||||
<a-menu-item v-for="item in nodes" :key="item.uuid" @click="handleChangeNode(item)">
|
||||
<DatabaseOutlined v-if="item.available" />
|
||||
<FrownOutlined v-else />
|
||||
{{ computeNodeName(item.ip, item.available, item.remarks) }}
|
||||
</a-menu-item>
|
||||
<a-menu-divider />
|
||||
<a-menu-item key="toNodesPage">
|
||||
<FormOutlined />
|
||||
{{ t("TXT_CODE_28e53fed") }}
|
||||
</a-menu-item>
|
||||
</a-menu>
|
||||
</template>
|
||||
<a-button :class="isPhone && 'mb-10 w-100'">
|
||||
{{
|
||||
computeNodeName(
|
||||
currentRemoteNode?.ip || "",
|
||||
currentRemoteNode?.available || true,
|
||||
currentRemoteNode?.remarks
|
||||
)
|
||||
}}
|
||||
<DownOutlined />
|
||||
</a-button>
|
||||
</a-dropdown>
|
||||
<div class="search-input" :class="isPhone && 'w-100'">
|
||||
<a-input
|
||||
v-model:value="operationForm.instanceName"
|
||||
:placeholder="t('TXT_CODE_ce132192')"
|
||||
@press-enter="handleQueryInstance"
|
||||
@change="handleQueryInstance"
|
||||
>
|
||||
<template #prefix>
|
||||
<search-outlined />
|
||||
<BetweenMenus>
|
||||
<template #left>
|
||||
<a-dropdown>
|
||||
<template #overlay>
|
||||
<a-menu>
|
||||
<a-menu-item
|
||||
v-for="item in nodes"
|
||||
:key="item.uuid"
|
||||
:disabled="!item.available"
|
||||
@click="handleChangeNode(item)"
|
||||
>
|
||||
<DatabaseOutlined v-if="item.available" />
|
||||
<FrownOutlined v-else />
|
||||
{{ computeNodeName(item.ip, item.available, item.remarks) }}
|
||||
</a-menu-item>
|
||||
<a-menu-divider />
|
||||
<a-menu-item key="toNodesPage">
|
||||
<FormOutlined />
|
||||
{{ t("TXT_CODE_28e53fed") }}
|
||||
</a-menu-item>
|
||||
</a-menu>
|
||||
</template>
|
||||
</a-input>
|
||||
</div>
|
||||
</div>
|
||||
<a-button :class="isPhone && 'mb-10 w-100'">
|
||||
{{
|
||||
computeNodeName(
|
||||
currentRemoteNode?.ip || "",
|
||||
currentRemoteNode?.available || true,
|
||||
currentRemoteNode?.remarks
|
||||
)
|
||||
}}
|
||||
<DownOutlined />
|
||||
</a-button>
|
||||
</a-dropdown>
|
||||
</template>
|
||||
<template #right>
|
||||
<div class="search-input" :class="isPhone && 'w-100'">
|
||||
<a-input
|
||||
v-model:value="operationForm.instanceName"
|
||||
:placeholder="t('TXT_CODE_ce132192')"
|
||||
@press-enter="handleQueryInstance"
|
||||
@change="handleQueryInstance"
|
||||
>
|
||||
<template #prefix>
|
||||
<search-outlined />
|
||||
</template>
|
||||
</a-input>
|
||||
</div>
|
||||
</template>
|
||||
</BetweenMenus>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<div v-if="instances" class="flex-between align-center">
|
||||
|
@ -16,7 +16,8 @@ import {
|
||||
ExclamationCircleOutlined,
|
||||
DeleteOutlined,
|
||||
WarningOutlined,
|
||||
InfoCircleOutlined
|
||||
InfoCircleOutlined,
|
||||
FrownOutlined
|
||||
} from "@ant-design/icons-vue";
|
||||
import BetweenMenus from "@/components/BetweenMenus.vue";
|
||||
import { router } from "@/config/router";
|
||||
@ -294,7 +295,8 @@ onMounted(async () => {
|
||||
:disabled="!item.available"
|
||||
@click="handleChangeNode(item)"
|
||||
>
|
||||
<DatabaseOutlined />
|
||||
<DatabaseOutlined v-if="item.available" />
|
||||
<FrownOutlined v-else />
|
||||
{{ computeNodeName(item.ip, item.available, item.remarks) }}
|
||||
</a-menu-item>
|
||||
<a-menu-divider />
|
||||
|
@ -223,7 +223,7 @@ const formData = ref<EditUserInfo>(_.cloneDeep(formDataOrigin));
|
||||
const baseRules: Record<string, Rule[]> = {
|
||||
userName: [
|
||||
{ required: true, message: t("TXT_CODE_2695488c") },
|
||||
{ min: 3, max: 12, message: t("TXT_CODE_3f477ec"), trigger: "blur" }
|
||||
{ min: 3, max: 20, message: t("TXT_CODE_3f477ec"), trigger: "blur" }
|
||||
],
|
||||
permission: [{ required: true, message: t("TXT_CODE_3bb646e4") }]
|
||||
};
|
||||
@ -279,6 +279,11 @@ const handleEditUser = (user: BaseUserInfo) => {
|
||||
userDialog.value.show();
|
||||
};
|
||||
|
||||
const search = throttle(async () => {
|
||||
operationForm.value.currentPage = 1;
|
||||
await fetchData();
|
||||
}, 600);
|
||||
|
||||
onMounted(async () => {
|
||||
fetchData();
|
||||
});
|
||||
@ -364,7 +369,7 @@ onMounted(async () => {
|
||||
</a-typography-title>
|
||||
</template>
|
||||
<template #right>
|
||||
<a-button class="mr-8" type="default" :loading="getUserInfoLoading" @click="fetchData">
|
||||
<a-button class="mr-8" type="default" :loading="getUserInfoLoading" @click="reload">
|
||||
{{ t("TXT_CODE_b76d94e0") }}
|
||||
</a-button>
|
||||
<a-dropdown>
|
||||
@ -387,7 +392,7 @@ onMounted(async () => {
|
||||
<template #center>
|
||||
<div class="search-input">
|
||||
<a-input-group compact>
|
||||
<a-select v-model:value="currentRole" style="width: 100px" @change="reload()">
|
||||
<a-select v-model:value="currentRole" style="width: 100px" @change="search()">
|
||||
<a-select-option value="">
|
||||
{{ t("TXT_CODE_c48f6f64") }}
|
||||
</a-select-option>
|
||||
@ -399,7 +404,7 @@ onMounted(async () => {
|
||||
v-model:value.trim="operationForm.name"
|
||||
:placeholder="t('TXT_CODE_2471b9c')"
|
||||
style="width: calc(100% - 100px)"
|
||||
@change="reload()"
|
||||
@change="search()"
|
||||
>
|
||||
<template #suffix>
|
||||
<search-outlined />
|
||||
|
@ -1663,7 +1663,7 @@
|
||||
"TXT_CODE_c1320e08": "你可以通过 “重置布局” 来清空你上传的所有文件",
|
||||
"TXT_CODE_ba42d467": "网络URL",
|
||||
"TXT_CODE_27efac3b": "编辑成功",
|
||||
"TXT_CODE_3f477ec": "长度只能 3 ~ 12 个字符",
|
||||
"TXT_CODE_3f477ec": "长度只能 3 ~ 20 个字符",
|
||||
"TXT_CODE_25c895d5": "请输入密码",
|
||||
"TXT_CODE_6032f5a3": "9 到 36 个字符,必须包含大小写字母和数字",
|
||||
"TXT_CODE_79f9a172": "编辑用户",
|
||||
|
@ -45,15 +45,17 @@ router.get(
|
||||
permission({ level: ROLE.ADMIN }),
|
||||
validator({ query: { page: Number, page_size: Number } }),
|
||||
async (ctx: Koa.ParameterizedContext) => {
|
||||
const userName = ctx.query.userName as string;
|
||||
const userName = ctx.query.userName;
|
||||
const role = ctx.query.role;
|
||||
const page = Number(ctx.query.page);
|
||||
const pageSize = Number(ctx.query.page_size);
|
||||
const condition: any = {};
|
||||
if (userName) condition["userName"] = `%${userName}%`;
|
||||
if (role) condition["permission"] = Number(role);
|
||||
let resultPage = userSystem.getQueryWrapper().selectPage(condition, page, pageSize);
|
||||
// make a copy, delete redundant
|
||||
resultPage = JSON.parse(JSON.stringify(resultPage));
|
||||
resultPage.data.forEach((v: any) => {
|
||||
resultPage.data.forEach((v) => {
|
||||
delete v.passWord;
|
||||
delete v.salt;
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user