feat: 新增在线机器页面

This commit is contained in:
xlsea 2024-03-30 17:07:04 +08:00
parent 20c28daa66
commit 1d26eb3482
25 changed files with 381 additions and 365 deletions

View File

@ -1,90 +0,0 @@
name: Bug提交
description: 在使用软件或功能的过程中遇到了错误
title: '[Bug]: '
labels: [ "bug?" ]
body:
- type: markdown
attributes:
value: |
## 请按照以下要求进行提交
### 1. 提交后需要指定标签和截止时间。
---
- type: markdown
attributes:
value: |
## 环境信息
请根据实际使用环境修改以下信息。
- type: input
id: env-program-ver
attributes:
label: 软件版本
validations:
required: true
- type: dropdown
id: env-vm-ver
attributes:
label: 运行环境
description: 选择运行软件的系统版本
options:
- Windows (64)
- Windows (32/x84)
- MacOS
- Linux
- Ubuntu
- CentOS
- ArchLinux
- UNIX (Android)
- 其它(请在下方说明)
validations:
required: true
- type: dropdown
id: env-vm-arch
attributes:
label: 运行架构
description: (可选) 选择运行软件的系统架构
options:
- AMD64
- x86
- ARM [32] (别名AArch32 / ARMv7
- ARM [64] (别名AArch64 / ARMv8
- 其它
- type: textarea
id: reproduce-steps
attributes:
label: 重现步骤
description: |
我们需要执行哪些操作才能让 bug 出现?
简洁清晰的重现步骤能够帮助我们更迅速地定位问题所在。
validations:
required: true
- type: textarea
id: expected
attributes:
label: 期望的结果是什么?
validations:
required: true
- type: textarea
id: actual
attributes:
label: 实际的结果是什么?
validations:
required: true
- type: textarea
id: logging
attributes:
label: 日志记录(可选)
render: golang
- type: textarea
id: extra-desc
attributes:
label: 补充说明(可选)

View File

@ -1,90 +0,0 @@
name: Bug Report
description: Encountered an error while using the software or feature
title: '[Bug]: '
labels: [ "bug?" ]
body:
- type: markdown
attributes:
value: |
## Please submit according to the following requirements
### 1. After submission, you need to specify the label and deadline.
---
- type: markdown
attributes:
value: |
## Environment Information
Please modify the following information according to the actual usage environment.
- type: input
id: env-program-ver
attributes:
label: Software Version
validations:
required: true
- type: dropdown
id: env-vm-ver
attributes:
label: Operating Environment
description: Select the system version on which the software is running
options:
- Windows (64)
- Windows (32/x84)
- MacOS
- Linux
- Ubuntu
- CentOS
- ArchLinux
- UNIX (Android)
- Other (please specify below)
validations:
required: true
- type: dropdown
id: env-vm-arch
attributes:
label: Operating Architecture
description: (Optional) Select the system architecture on which the software is running
options:
- AMD64
- x86
- ARM [32] (AliasAArch32 / ARMv7
- ARM [64] (AliasAArch64 / ARMv8
- Other
- type: textarea
id: reproduce-steps
attributes:
label: Reproduce Steps
description: |
What operations do we need to perform to make the bug appear?
The concise and clear reproduction steps can help us locate the problem more quickly.
validations:
required: true
- type: textarea
id: expected
attributes:
label: What is the expected result?
validations:
required: true
- type: textarea
id: actual
attributes:
label: What is the actual result?
validations:
required: true
- type: textarea
id: logging
attributes:
label: Logging (Optional)
render: golang
- type: textarea
id: extra-desc
attributes:
label: Additional Description (Optional)

View File

@ -1,50 +0,0 @@
首先,感谢你的贡献! 😄
新特性请提交至 feature 分支,其余可提交至 main 分支。在一个维护者审核通过后合并。请确保填写以下 pull request 的信息,谢谢!~
[[English Template / 英文模板](./pr_en.md)]
### 这个变动的性质是
- [ ] 新特性提交
- [ ] 日常 bug 修复
- [ ] 站点、文档改进
- [ ] 组件样式改进
- [ ] TypeScript 定义更新
- [ ] 重构
- [ ] 代码风格优化
- [ ] 分支合并
- [ ] 其他改动(是关于什么的改动?)
### 需求背景
> 1. 描述相关需求的来源。
> 2. 要解决的问题。
> 3. 相关的 issue 讨论链接。
### 实现方案和 API非新功能可选
> 1. 基本的解决思路和其他可选方案。
> 2. 列出最终的 API 实现和用法。
> 3. 涉及 UI/交互变动需要有截图或 GIF。
### 对用户的影响和可能的风险(非新功能可选)
> 1. 这个改动对用户端是否有影响?影响的方面有哪些?
> 2. 是否有可能隐含的 break change 和其他风险?
### Changelog 描述(非新功能可选)
> 1. 英文描述
> 2. 中文描述(可选)
### 请求合并前的自查清单
- [ ] 文档已补充或无须补充
- [ ] 代码演示已提供或无须提供
- [ ] TypeScript 定义已补充或无须补充
- [ ] Changelog 已提供或无须提供
### 后续计划(非新功能可选)
> 如果这个提交后面还有相关的其他提交和跟进信息,可以写在这里。

View File

@ -1,51 +0,0 @@
First of all, thank you for your contribution! 😄
New feature please send pull request to feature branch, and rest to main branch. Pull request will be merged after one of collaborators approve. Please makes sure that these form are filled before submitting your pull request, thank you!
[[中文版模板 / Chinese template](./pr_cn.md)]
### This is a ...
- [ ] New feature
- [ ] Bug fix
- [ ] Site / document update
- [ ] Component style update
- [ ] TypeScript definition update
- [ ] Refactoring
- [ ] Code style optimization
- [ ] Branch merge
- [ ] Other (about what?)
### What's the background?
> 1. Describe the source of requirement.
> 2. Resolve what problem.
> 3. Related issue link.
### API Realization (Optional if not new feature)
> 1. Basic thought of solution and other optional proposal.
> 2. List final API realization and usage sample.
> 3. GIF or snapshot should be provided if includes UI/interactive modification.
### What's the effect? (Optional if not new feature)
> 1. Does this PR affect user? Which part will be affected?
> 2. What will say in changelog?
> 3. Does this PR contains potential break change or other risk?
### Changelog description (Optional if not new feature)
> 1. English description
> 2. Chinese description (optional)
### Self Check before Merge
- [ ] Doc is updated/provided or not needed
- [ ] Demo is updated/provided or not needed
- [ ] TypeScript definition is updated/provided or not needed
- [ ] Changelog is provided or not needed
### Additional Plan? (Optional if not new feature)
> If this PR related with other PR or following info. You can type here.

View File

@ -1,30 +0,0 @@
---
name: Lint Code
permissions:
contents: write
on:
pull_request:
branches: [main]
jobs:
lint:
name: Lint All Code
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Lint Code Base
uses: github/super-linter@v4
env:
VALIDATE_ALL_CODEBASE: false
DEFAULT_BRANCH: main
# To change branch master or main
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
FILTER_REGEX_EXCLUDE: (docs|.github)
VALIDATE_MARKDOWN: false

View File

@ -1,25 +0,0 @@
name: Release
permissions:
contents: write
on:
push:
tags:
- "v*"
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- uses: actions/setup-node@v3
with:
node-version: 18.x
- run: npx githublogen
env:
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}

View File

@ -7,9 +7,14 @@ interface Props {
itemAlign?: NaiveUI.Align;
disabledDelete?: boolean;
loading?: boolean;
showDelete: boolean;
showAdd: boolean;
}
defineProps<Props>();
withDefaults(defineProps<Props>(), {
showDelete: true,
showAdd: true
});
interface Emits {
(e: 'add'): void;
@ -40,13 +45,13 @@ function refresh() {
<NSpace :align="itemAlign" wrap justify="end" class="lt-sm:w-200px">
<slot name="prefix"></slot>
<slot name="default">
<NButton size="small" ghost type="primary" @click="add">
<NButton v-if="showAdd" size="small" ghost type="primary" @click="add">
<template #icon>
<icon-ic-round-plus class="text-icon" />
</template>
{{ $t('common.add') }}
</NButton>
<NPopconfirm @positive-click="batchDelete">
<NPopconfirm v-if="showDelete" @positive-click="batchDelete">
<template #trigger>
<NButton size="small" ghost type="error" :disabled="disabledDelete">
<template #icon>

View File

@ -27,3 +27,8 @@ export const menuIconTypeRecord: Record<Api.SystemManage.IconType, App.I18n.I18n
};
export const menuIconTypeOptions = transformRecordToOption(menuIconTypeRecord);
export const podsType: Record<Api.Dashboard.DashboardPodsType, App.I18n.I18nKey> = {
1: 'page.pods.type.client',
2: 'page.pods.type.server'
};

View File

@ -33,8 +33,7 @@ export function useTable<A extends NaiveUI.TableApiFn>(config: NaiveUI.NaiveTabl
apiParams,
columns: config.columns,
transformer: res => {
const { records = [], current = 1, size = 10, total = 0 } = res.data || {};
const { data: records = [], page: current = 1, size = 10, total = 0 } = res.data || {};
const recordsWithIndex = records.map((item, index) => {
return {
...item,
@ -108,7 +107,7 @@ export function useTable<A extends NaiveUI.TableApiFn>(config: NaiveUI.NaiveTabl
pagination.page = page;
updateSearchParams({
current: page,
page,
size: pagination.pageSize!
});
@ -119,7 +118,7 @@ export function useTable<A extends NaiveUI.TableApiFn>(config: NaiveUI.NaiveTabl
pagination.page = 1;
updateSearchParams({
current: pagination.page,
page: pagination.page,
size: pageSize
});

View File

@ -155,6 +155,7 @@ const local: App.I18n.Schema = {
function_request: 'Request',
'function_toggle-auth': 'Toggle Auth',
'function_super-page': 'Super Admin Visible',
pods: 'Online Machine',
manage: 'System Manage',
manage_user: 'User Manage',
'manage_user-detail': 'User Detail',
@ -281,6 +282,24 @@ const local: App.I18n.Schema = {
},
creativity: 'Creativity'
},
pods: {
title: 'Online Machine',
nodeType: 'Node Type',
groupName: 'Group Name',
hostId: 'Pod ID',
hostIp: 'IP',
hostPort: 'Port',
consumerBuckets: 'Path/Buckets',
updateDt: 'Update Time',
contextPath: 'Path/Buckets',
form: {
groupName: 'Please enter group name'
},
type: {
client: 'Client',
server: 'Server'
}
},
function: {
tab: {
tabOperate: {

View File

@ -155,6 +155,7 @@ const local: App.I18n.Schema = {
function_request: '请求',
'function_toggle-auth': '切换权限',
'function_super-page': '超级管理员可见',
pods: '在线机器',
manage: '系统管理',
manage_user: '用户管理',
'manage_user-detail': '用户详情',
@ -277,6 +278,24 @@ const local: App.I18n.Schema = {
},
creativity: '创意'
},
pods: {
title: '在线机器',
nodeType: '类型',
groupName: '组名称',
hostId: 'Pod ID',
hostIp: 'IP',
hostPort: 'Port',
consumerBuckets: '路径/组',
updateDt: '更新时间',
contextPath: '路径/组',
form: {
groupName: '请输入组名称'
},
type: {
client: '客户端',
server: '服务端'
}
},
function: {
tab: {
tabOperate: {

View File

@ -35,5 +35,6 @@ export const views: Record<LastLevelRouteKey, RouteComponent | (() => Promise<Ro
manage_user: () => import("@/views/manage/user/index.vue"),
"multi-menu_first_child": () => import("@/views/multi-menu/first_child/index.vue"),
"multi-menu_second_child_home": () => import("@/views/multi-menu/second_child_home/index.vue"),
pods: () => import("@/views/pods/index.vue"),
"user-center": () => import("@/views/user-center/index.vue"),
};

View File

@ -317,6 +317,17 @@ export const generatedRoutes: GeneratedRoute[] = [
}
]
},
{
name: 'pods',
path: '/pods',
component: 'layout.base$view.pods',
meta: {
title: 'pods',
i18nKey: 'route.pods',
icon: 'ant-design:database-outlined',
order: 1
}
},
{
name: 'user-center',
path: '/user-center',

View File

@ -174,6 +174,7 @@ const routeMap: RouteMap = {
"multi-menu_second": "/multi-menu/second",
"multi-menu_second_child": "/multi-menu/second/child",
"multi-menu_second_child_home": "/multi-menu/second/child/home",
"pods": "/pods",
"user-center": "/user-center"
};

View File

@ -25,3 +25,12 @@ export function fetchJobLine(params?: Api.Dashboard.DashboardLineParams) {
params
});
}
/** Pods */
export function fetchPods(params?: Api.Dashboard.DashboardPodsParams) {
return request<Api.Dashboard.DashboardPodList>({
url: '/dashboard/pods',
method: 'get',
params
});
}

View File

@ -107,7 +107,7 @@ export const request = createFlatRequest<App.Service.Response, InstanceState>(
return null;
},
transformBackendResponse(response) {
return response.data.data;
return response.data.total ? response.data : response.data.data;
},
onError(error) {
// when the request is fail, you can show error message

65
src/typings/api.d.ts vendored
View File

@ -7,19 +7,29 @@ declare namespace Api {
namespace Common {
/** common params of paginating */
interface PaginatingCommonParams {
/** current page number */
current: number;
/** page size */
size: number;
/** total count */
total: number;
/** current page number */
page: number;
}
/** common params of paginating query list data */
interface PaginatingQueryRecord<T = any> extends PaginatingCommonParams {
records: T[];
data: T[];
status: number;
}
/** common page record */
type CommonPageRecord<T> = {
data: T[];
page: number;
size: number;
status: number;
total: number;
};
/**
* enable status
*
@ -31,17 +41,17 @@ declare namespace Api {
/** common record */
type CommonRecord<T = any> = {
/** record id */
id: number;
id?: number;
/** record creator */
createBy: string;
createBy?: string;
/** record create time */
createTime: string;
createTime?: string;
/** record updater */
updateBy: string;
updateBy?: string;
/** record update time */
updateTime: string;
updateTime?: string;
/** record status */
status: EnableStatus | null;
status?: EnableStatus | null;
} & T;
}
@ -104,6 +114,8 @@ declare namespace Api {
* backend api module: "dashboard"
*/
namespace Dashboard {
type CommonSearchParams = Pick<Common.PaginatingCommonParams, 'page' | 'size'>;
/** Task Retry Job */
type CardCount = {
jobTask: JobTask;
@ -198,6 +210,37 @@ declare namespace Api {
startTime?: string;
endTime?: string;
};
type DashboardPodsType = 1 | 2;
type DashboardPodList = Common.PaginatingQueryRecord<DashboardPod>;
type DashboardPod = {
/** 路径/组 */
consumerBuckets: number[];
/** context path */
contextPath: string;
/** 创建时间 */
createDt: string;
/** ext attrs */
extAttrs: string;
/** 组名称 */
groupName: string;
/** host id */
hostId: string;
/** host IP */
hostIp: string;
/** host port */
hostPort: string;
/** 类型 */
nodeType: DashboardPodsType;
/** 更新时间 */
updateDt: string;
};
type DashboardPodsParams = CommonType.RecordNullable<
Pick<Api.Dashboard.DashboardPod, 'groupName'> & CommonSearchParams
>;
}
/**
@ -206,10 +249,11 @@ declare namespace Api {
* backend api module: "systemManage"
*/
namespace SystemManage {
type CommonSearchParams = Pick<Common.PaginatingCommonParams, 'current' | 'size'>;
type CommonSearchParams = Pick<Common.PaginatingCommonParams, 'page' | 'size'>;
/** role */
type Role = Common.CommonRecord<{
id: number;
/** role name */
roleName: string;
/** role code */
@ -290,6 +334,7 @@ declare namespace Api {
type IconType = '1' | '2';
type Menu = Common.CommonRecord<{
id: number;
/** parent menu id */
parentId: number;
/** menu type */

21
src/typings/app.d.ts vendored
View File

@ -457,6 +457,24 @@ declare namespace App {
};
creativity: string;
};
pods: {
title: string;
nodeType: string;
groupName: string;
hostId: string;
hostIp: string;
hostPort: string;
consumerBuckets: string;
updateDt: string;
contextPath: string;
form: {
groupName: string;
};
type: {
client: string;
server: string;
};
};
function: {
tab: {
tabOperate: {
@ -697,6 +715,9 @@ declare namespace App {
message: string;
/** The backend service response data */
data: T;
page?: number;
size?: number;
total?: number;
};
/** The demo backend service response data */

View File

@ -48,6 +48,7 @@ declare module "@elegant-router/types" {
"multi-menu_second": "/multi-menu/second";
"multi-menu_second_child": "/multi-menu/second/child";
"multi-menu_second_child_home": "/multi-menu/second/child/home";
"pods": "/pods";
"user-center": "/user-center";
};
@ -93,6 +94,7 @@ declare module "@elegant-router/types" {
| "login"
| "manage"
| "multi-menu"
| "pods"
| "user-center"
>;
@ -131,6 +133,7 @@ declare module "@elegant-router/types" {
| "manage_user"
| "multi-menu_first_child"
| "multi-menu_second_child_home"
| "pods"
| "user-center"
>;

View File

@ -1,9 +1,12 @@
<script setup lang="ts">
import { computed } from 'vue';
import { createReusableTemplate } from '@vueuse/core';
import { useRouter } from 'vue-router';
import { $t } from '@/locales';
import DardRetryChart from './card-retry-chart.vue';
const router = useRouter();
defineOptions({
name: 'CardData'
});
@ -189,7 +192,12 @@ function getGradientColor(color: CardData['color']) {
<NGrid cols="s:1 m:2 l:4" responsive="screen" :x-gap="16" :y-gap="16">
<NGi v-for="item in cardData" :key="item.key">
<NSpin :show="false">
<GradientBg :gradient-color="getGradientColor(item.color)" class="h-165px flex-1">
<GradientBg
:gradient-color="getGradientColor(item.color)"
class="h-165px flex-1"
:class="item.key === 'onlineServiceCount' ? 'cursor-pointer' : ''"
@click="() => (item.key === 'onlineServiceCount' ? router.push('pods') : null)"
>
<div class="flex justify-between">
<div class="align-center flex">
<SvgIcon :icon="item.icon" class="text-26px" />

View File

@ -104,9 +104,9 @@ const { columns, columnChecks, data, loading, pagination, getData } = useTable({
2: 'warning'
};
const label = $t(enableStatusRecord[row.status]);
const label = $t(enableStatusRecord[row.status!]);
return <NTag type={tagMap[row.status]}>{label}</NTag>;
return <NTag type={tagMap[row.status!]}>{label}</NTag>;
}
},
{

View File

@ -13,7 +13,7 @@ const appStore = useAppStore();
const { columns, columnChecks, data, loading, getData, mobilePagination, searchParams, resetSearchParams } = useTable({
apiFn: fetchGetRoleList,
apiParams: {
current: 1,
page: 1,
size: 10,
// if you want to use the searchParams in Form, you need to define the following properties, and the value is null
// the value can not be undefined, otherwise the property in Form will not be reactive
@ -65,9 +65,9 @@ const { columns, columnChecks, data, loading, getData, mobilePagination, searchP
2: 'warning'
};
const label = $t(enableStatusRecord[row.status]);
const label = $t(enableStatusRecord[row.status!]);
return <NTag type={tagMap[row.status]}>{label}</NTag>;
return <NTag type={tagMap[row.status!]}>{label}</NTag>;
}
},
{

View File

@ -13,7 +13,7 @@ const appStore = useAppStore();
const { columns, columnChecks, data, getData, loading, mobilePagination, searchParams, resetSearchParams } = useTable({
apiFn: fetchGetUserList,
apiParams: {
current: 1,
page: 1,
size: 10,
// if you want to use the searchParams in Form, you need to define the following properties, and the value is null
// the value can not be undefined, otherwise the property in Form will not be reactive
@ -95,9 +95,9 @@ const { columns, columnChecks, data, getData, loading, mobilePagination, searchP
2: 'warning'
};
const label = $t(enableStatusRecord[row.status]);
const label = $t(enableStatusRecord[row.status!]);
return <NTag type={tagMap[row.status]}>{label}</NTag>;
return <NTag type={tagMap[row.status!]}>{label}</NTag>;
}
},
{
@ -107,10 +107,10 @@ const { columns, columnChecks, data, getData, loading, mobilePagination, searchP
width: 130,
render: row => (
<div class="flex-center gap-8px">
<NButton type="primary" ghost size="small" onClick={() => edit(row.id)}>
<NButton type="primary" ghost size="small" onClick={() => edit(row.id!)}>
{$t('common.edit')}
</NButton>
<NPopconfirm onPositiveClick={() => handleDelete(row.id)}>
<NPopconfirm onPositiveClick={() => handleDelete(row.id!)}>
{{
default: () => $t('common.confirmDelete'),
trigger: () => (

147
src/views/pods/index.vue Normal file
View File

@ -0,0 +1,147 @@
<script setup lang="tsx">
import { NTag } from 'naive-ui';
import { useAppStore } from '@/store/modules/app';
import { fetchPods } from '@/service/api';
import { $t } from '@/locales';
import { podsType } from '@/constants/business';
import { useTable, useTableOperate } from '@/hooks/common/table';
import PodsSearch from './modules/pods-search.vue';
const appStore = useAppStore();
const { columns, columnChecks, data, getData, loading, mobilePagination, searchParams, resetSearchParams } = useTable({
apiFn: fetchPods,
apiParams: {
page: 1,
size: 10,
groupName: null
},
columns: () => [
{
key: 'hostId',
title: $t('page.pods.hostId'),
align: 'left',
width: 120
},
{
key: 'nodeType',
title: $t('page.pods.nodeType'),
align: 'center',
width: 100,
render: row => {
if (row.nodeType === null) {
return null;
}
const tagMap: Record<Api.Dashboard.DashboardPodsType, NaiveUI.ThemeColor> = {
1: 'info',
2: 'primary'
};
const label = $t(podsType[row.nodeType]);
return <NTag type={tagMap[row.nodeType]}>{label}</NTag>;
}
},
{
key: 'groupName',
title: $t('page.pods.groupName'),
align: 'left',
width: 180
},
{
key: 'hostIp',
title: $t('page.pods.hostIp'),
align: 'left',
width: 120
},
{
key: 'hostPort',
title: $t('page.pods.hostPort'),
align: 'left',
width: 120
},
{
key: 'consumerBuckets',
title: $t('page.pods.consumerBuckets'),
align: 'left',
width: 360,
render: row => {
if (row.nodeType === null) {
return null;
}
const buckets = (slice?: number) => {
const consumerBuckets = slice ? row.consumerBuckets?.slice(0, slice) : row.consumerBuckets;
return consumerBuckets?.map(bucket => (
<NTag type="error" key={bucket} class="mr-8px">
{bucket}
</NTag>
));
};
const path = () => {
return <NTag type="info">{row.contextPath}</NTag>;
};
return row.nodeType === 1 ? (
<>path: {path()}</>
) : (
<>
<span>Bucket: </span>
{buckets(10)}
<n-popover trigger="hover">
{{
trigger: () => <NTag type="error">...</NTag>,
default: () => {
return <div class="w-600px">{buckets()}</div>;
}
}}
</n-popover>
</>
);
}
},
{
key: 'updateDt',
title: $t('page.pods.updateDt'),
align: 'left',
width: 130
}
]
});
const { checkedRowKeys } = useTableOperate(data, getData);
</script>
<template>
<div class="min-h-500px flex-col-stretch gap-16px overflow-hidden lt-sm:overflow-auto">
<PodsSearch v-model:model="searchParams" @reset="resetSearchParams" @search="getData" />
<NCard :title="$t('page.pods.title')" :bordered="false" size="small" class="sm:flex-1-hidden card-wrapper">
<template #header-extra>
<TableHeaderOperation
v-model:columns="columnChecks"
:disabled-delete="checkedRowKeys.length === 0"
:loading="loading"
:show-add="false"
:show-delete="false"
@refresh="getData"
/>
</template>
<NDataTable
v-model:checked-row-keys="checkedRowKeys"
:columns="columns"
:data="data"
:flex-height="!appStore.isMobile"
:scroll-x="962"
:loading="loading"
remote
:row-key="row => row.hostId"
:pagination="mobilePagination"
class="sm:h-full"
/>
</NCard>
</div>
</template>
<style scoped></style>

View File

@ -0,0 +1,59 @@
<script setup lang="ts">
import { $t } from '@/locales';
import { useNaiveForm } from '@/hooks/common/form';
defineOptions({
name: 'PodsSearch'
});
interface Emits {
(e: 'reset'): void;
(e: 'search'): void;
}
const emit = defineEmits<Emits>();
const { formRef, validate, restoreValidation } = useNaiveForm();
const model = defineModel<Api.Dashboard.DashboardPodsParams>('model', { required: true });
async function reset() {
await restoreValidation();
emit('reset');
}
async function search() {
await validate();
emit('search');
}
</script>
<template>
<NCard :bordered="false" size="small" class="card-wrapper">
<NForm ref="formRef" :model="model" label-placement="left" :label-width="60" :show-feedback="false">
<NGrid responsive="screen" item-responsive>
<NFormItemGi span="24 s:12 m:6" :label="$t('page.pods.groupName')" path="groupName" class="pr-24px">
<NInput v-model:value="model.groupName" :placeholder="$t('page.pods.form.groupName')" />
</NFormItemGi>
<NFormItemGi span="24 m:12" class="pr-24px">
<NSpace class="w-full">
<NButton @click="reset">
<template #icon>
<icon-ic-round-refresh class="text-icon" />
</template>
{{ $t('common.reset') }}
</NButton>
<NButton type="primary" ghost @click="search">
<template #icon>
<icon-ic-round-search class="text-icon" />
</template>
{{ $t('common.search') }}
</NButton>
</NSpace>
</NFormItemGi>
</NGrid>
</NForm>
</NCard>
</template>
<style scoped></style>