Compare commits
25 Commits
f842dcaf14
...
wuxichen
| Author | SHA1 | Date | |
|---|---|---|---|
| a2c5711d43 | |||
| 945f795f81 | |||
| bf7d0b3bc5 | |||
| cb7b22bca3 | |||
| d5a795de77 | |||
| 6a3aa3bf5d | |||
| 4ad3706dfa | |||
| 44426d8812 | |||
| c970931954 | |||
| ba1a7f392b | |||
| 16bb5afaa7 | |||
| 22ef893529 | |||
| 066cee46b0 | |||
| b4017597f9 | |||
| f27fc56fd4 | |||
| 47623d6b1e | |||
| 7426746239 | |||
| ecbd4eefd7 | |||
| 448531f9d3 | |||
| 4facb02777 | |||
| 929cb1966b | |||
| aa2f07de41 | |||
| 5c8cb3bc88 | |||
| bbdcef9d56 | |||
| c4f3235fcf |
46
.gitea/workflows/deploy.yml
Normal file
46
.gitea/workflows/deploy.yml
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
name: Auto Deploy
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- wuxichen # 当前分支
|
||||||
|
- main
|
||||||
|
- master
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-and-deploy:
|
||||||
|
runs-on: self-hosted
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Build and Deploy
|
||||||
|
run: |
|
||||||
|
# 使用持久化工作目录,避免每次重新克隆
|
||||||
|
WORK_DIR="/root/tashow-deploy"
|
||||||
|
|
||||||
|
# 首次运行时克隆代码
|
||||||
|
if [ ! -d "$WORK_DIR" ]; then
|
||||||
|
echo "首次部署,克隆代码..."
|
||||||
|
git clone http://gitea.tashowz.com/tashow/tashow-manager.git $WORK_DIR
|
||||||
|
fi
|
||||||
|
|
||||||
|
cd $WORK_DIR
|
||||||
|
|
||||||
|
# 更新代码到最新版本
|
||||||
|
echo "更新代码..."
|
||||||
|
git fetch origin
|
||||||
|
git checkout ${{ github.ref_name }}
|
||||||
|
git reset --hard origin/${{ github.ref_name }}
|
||||||
|
|
||||||
|
# 安装依赖
|
||||||
|
echo "安装依赖..."
|
||||||
|
pnpm install
|
||||||
|
|
||||||
|
# 构建项目
|
||||||
|
echo "构建项目..."
|
||||||
|
pnpm build
|
||||||
|
|
||||||
|
# 部署到服务器
|
||||||
|
echo "部署到服务器..."
|
||||||
|
rsync -av --delete dist/ /home/1panel/www/sites/admin.petshy.tashowz.com/index/
|
||||||
|
|
||||||
|
echo "部署成功!"
|
||||||
2
public/test.txt
Normal file
2
public/test.txt
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
CI/CD Test - Deployed at 2026-03-02 16:23
|
||||||
|
This file is used to verify automatic deployment is working.
|
||||||
@@ -112,7 +112,7 @@ export const layout: RunTimeLayoutConfig = ({
|
|||||||
waterMarkProps: {
|
waterMarkProps: {
|
||||||
content: initialState?.currentUser?.user.nickname,
|
content: initialState?.currentUser?.user.nickname,
|
||||||
},
|
},
|
||||||
footerRender: () => <Footer />,
|
// footerRender: () => <Footer />,
|
||||||
onPageChange: () => {
|
onPageChange: () => {
|
||||||
const { location } = history;
|
const { location } = history;
|
||||||
// 如果没有登录,重定向到 login
|
// 如果没有登录,重定向到 login
|
||||||
|
|||||||
@@ -41,8 +41,8 @@ export const baseDeptColumns: ProColumns<AiModelRespVO>[] = [
|
|||||||
) => (
|
) => (
|
||||||
<Switch
|
<Switch
|
||||||
checked={record.status === 1}
|
checked={record.status === 1}
|
||||||
checkedChildren="禁用"
|
checkedChildren="启用"
|
||||||
unCheckedChildren="启用"
|
unCheckedChildren="禁用"
|
||||||
onChange={(checked) => {
|
onChange={(checked) => {
|
||||||
Modal.confirm({
|
Modal.confirm({
|
||||||
title: '确认操作',
|
title: '确认操作',
|
||||||
|
|||||||
@@ -20,21 +20,49 @@ export const baseTenantColumns: ProColumns<AiSampleRespVO>[] = [
|
|||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '文件格式',
|
title: '枚举标签',
|
||||||
width: 100,
|
dataIndex: 'enumTags',
|
||||||
dataIndex: 'sampleMineType',
|
width: 120,
|
||||||
|
ellipsis: true,
|
||||||
|
render: (_, record) => {
|
||||||
|
return (
|
||||||
|
record.enumTags?.map((tag) => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{tag.enumValue}:<Tag key={tag.id}>{tag.tagName}</Tag>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}) || '-'
|
||||||
|
);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
title: '标签',
|
title: '个性标签',
|
||||||
dataIndex: 'tags',
|
dataIndex: 'tags',
|
||||||
width: 200,
|
width: 200,
|
||||||
hideInSearch: true,
|
hideInSearch: true,
|
||||||
render: (_, record) => {
|
render: (_, record) => {
|
||||||
return record.tags?.map((tag) => {
|
return record.tags?.map((tag) => {
|
||||||
return <Tag key={tag.id}>{tag.tagName}</Tag>;
|
return (
|
||||||
|
<Tag key={tag.id} style={{ marginBottom: 5, marginTop: 5 }}>
|
||||||
|
{tag.tagName}
|
||||||
|
</Tag>
|
||||||
|
);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: '关联模型',
|
||||||
|
width: 100,
|
||||||
|
dataIndex: 'relatedModels',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '文件格式',
|
||||||
|
width: 100,
|
||||||
|
dataIndex: 'sampleMineType',
|
||||||
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
title: '注释',
|
title: '注释',
|
||||||
width: 100,
|
width: 100,
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { ProForm, ProFormGroup, ProFormText } from '@ant-design/pro-components';
|
import { ProForm, ProFormGroup, ProFormText } from '@ant-design/pro-components';
|
||||||
import { Button, message, Space, Tag } from 'antd';
|
import { Button, Empty, Input, message, Space, Tag } from 'antd';
|
||||||
|
import FormItem from 'antd/es/form/FormItem';
|
||||||
import type { RowSelectionType } from 'antd/es/table/interface';
|
import type { RowSelectionType } from 'antd/es/table/interface';
|
||||||
import type { FormInstance } from 'antd/lib';
|
import type { FormInstance } from 'antd/lib';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
@@ -13,6 +14,7 @@ import React, {
|
|||||||
import GroupTagModal from '@/components/GroupTag/GroupTagModal';
|
import GroupTagModal from '@/components/GroupTag/GroupTagModal';
|
||||||
import type { TagItem } from '@/components/GroupTag/types';
|
import type { TagItem } from '@/components/GroupTag/types';
|
||||||
import type { FileItem } from '@/components/RenameRule';
|
import type { FileItem } from '@/components/RenameRule';
|
||||||
|
import TagEditor from '@/components/TagEditor';
|
||||||
import {
|
import {
|
||||||
createSampleTag,
|
createSampleTag,
|
||||||
createSampleTagGroup,
|
createSampleTagGroup,
|
||||||
@@ -177,28 +179,50 @@ const SampleTagDetail = <T extends Record<string, any>>(
|
|||||||
<>
|
<>
|
||||||
{data!.length > 0 ? (
|
{data!.length > 0 ? (
|
||||||
<>
|
<>
|
||||||
<ProForm name="validate_other" formRef={formRef} submitter={false}>
|
<div className="sample-tag-detail">
|
||||||
{type === 'radio' && (
|
<ProForm name="validate_other" formRef={formRef} submitter={false}>
|
||||||
<ProFormGroup title="预览">
|
|
||||||
{data?.[0].sampleFilePath && (
|
|
||||||
<audio
|
|
||||||
controls
|
|
||||||
preload="true"
|
|
||||||
crossOrigin="anonymous"
|
|
||||||
style={{ marginBottom: 24 }}
|
|
||||||
>
|
|
||||||
<source src={data[0].sampleFilePath} />
|
|
||||||
<track kind="captions" />
|
|
||||||
</audio>
|
|
||||||
)}
|
|
||||||
</ProFormGroup>
|
|
||||||
)}
|
|
||||||
<ProFormGroup title="基本信息">
|
|
||||||
{type === 'radio' && (
|
{type === 'radio' && (
|
||||||
|
<ProFormGroup title="预览">
|
||||||
|
{data?.[0].sampleFilePath && (
|
||||||
|
<audio
|
||||||
|
controls
|
||||||
|
preload="true"
|
||||||
|
crossOrigin="anonymous"
|
||||||
|
style={{ marginBottom: 24 }}
|
||||||
|
>
|
||||||
|
<source src={data[0].sampleFilePath} />
|
||||||
|
<track kind="captions" />
|
||||||
|
</audio>
|
||||||
|
)}
|
||||||
|
</ProFormGroup>
|
||||||
|
)}
|
||||||
|
<ProFormGroup title="基本信息">
|
||||||
|
{type === 'radio' && (
|
||||||
|
<ProFormText
|
||||||
|
width="md"
|
||||||
|
name="sampleName"
|
||||||
|
placeholder="请输入样本名称"
|
||||||
|
fieldProps={{
|
||||||
|
onBlur: async (e) => {
|
||||||
|
if (e.target.value) {
|
||||||
|
const newData =
|
||||||
|
data?.map((sample) => {
|
||||||
|
return {
|
||||||
|
id: sample.id,
|
||||||
|
sampleName: e.target.value,
|
||||||
|
};
|
||||||
|
}) || [];
|
||||||
|
await updateSamples(newData);
|
||||||
|
props?.onRefresh?.();
|
||||||
|
message.success('更新样本名称成功');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
rules={[{ required: true, message: '样本名称不能为空' }]}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
<ProFormText
|
<ProFormText
|
||||||
width="md"
|
width="md"
|
||||||
name="sampleName"
|
|
||||||
placeholder="请输入样本名称"
|
|
||||||
fieldProps={{
|
fieldProps={{
|
||||||
onBlur: async (e) => {
|
onBlur: async (e) => {
|
||||||
if (e.target.value) {
|
if (e.target.value) {
|
||||||
@@ -206,136 +230,96 @@ const SampleTagDetail = <T extends Record<string, any>>(
|
|||||||
data?.map((sample) => {
|
data?.map((sample) => {
|
||||||
return {
|
return {
|
||||||
id: sample.id,
|
id: sample.id,
|
||||||
sampleName: e.target.value,
|
remark: e.target.value,
|
||||||
};
|
};
|
||||||
}) || [];
|
}) || [];
|
||||||
await updateSamples(newData);
|
await updateSamples(newData);
|
||||||
props?.onRefresh?.();
|
props?.onRefresh?.();
|
||||||
message.success('更新样本名称成功');
|
message.success('更新注释成功');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
rules={[{ required: true, message: '样本名称不能为空' }]}
|
name="remark"
|
||||||
|
placeholder="请输入注释"
|
||||||
/>
|
/>
|
||||||
)}
|
</ProFormGroup>
|
||||||
<ProFormText
|
<ProFormGroup title="枚举标签" block></ProFormGroup>
|
||||||
width="md"
|
<ProForm.Item name="tag1" label="物种">
|
||||||
fieldProps={{
|
<TagEditor maxCount={1} />
|
||||||
onBlur: async (e) => {
|
</ProForm.Item>
|
||||||
if (e.target.value) {
|
<ProForm.Item name="tag2" label="情绪">
|
||||||
const newData =
|
<TagEditor maxCount={1} />
|
||||||
data?.map((sample) => {
|
</ProForm.Item>
|
||||||
return {
|
<ProFormGroup title="个性标签">
|
||||||
id: sample.id,
|
{/* <Form.Item name="tag"> */}
|
||||||
remark: e.target.value,
|
{forMap(value.tags || [])}
|
||||||
};
|
</ProFormGroup>
|
||||||
}) || [];
|
<Button
|
||||||
await updateSamples(newData);
|
type="dashed"
|
||||||
props?.onRefresh?.();
|
block
|
||||||
message.success('更新注释成功');
|
style={{ marginBottom: 24 }}
|
||||||
}
|
onClick={handleAddTag}
|
||||||
},
|
>
|
||||||
}}
|
添加标签
|
||||||
name="remark"
|
</Button>
|
||||||
placeholder="请输入注释"
|
<ProFormGroup title="文本信息" block></ProFormGroup>
|
||||||
/>
|
<Space size={10} style={{ width: '100%', marginBottom: 12 }}>
|
||||||
</ProFormGroup>
|
<span>添加日期: </span>
|
||||||
|
<span>
|
||||||
|
{dayjs(value.createTime).format('YYYY-MM-DD HH:mm:ss')}
|
||||||
|
</span>
|
||||||
|
</Space>
|
||||||
|
<Space size={10} style={{ width: '100%', marginBottom: 12 }}>
|
||||||
|
<span>修改日期</span>
|
||||||
|
<span>
|
||||||
|
{dayjs(value.updateTime).format('YYYY-MM-DD HH:mm:ss')}
|
||||||
|
</span>
|
||||||
|
</Space>
|
||||||
|
<Space size={10} style={{ width: '100%', marginBottom: 12 }}>
|
||||||
|
<span>文件大小: </span>
|
||||||
|
<span>{value.sampleSize}</span>
|
||||||
|
</Space>
|
||||||
|
<Space size={10} style={{ width: '100%', marginBottom: 12 }}>
|
||||||
|
<span>格式: </span>
|
||||||
|
<span>{value.sampleMineType}</span>
|
||||||
|
</Space>
|
||||||
|
</ProForm>
|
||||||
|
<GroupTagModal
|
||||||
|
visible={modalVisible}
|
||||||
|
onCancel={() => setModalVisible(false)}
|
||||||
|
onChange={onListAddTag}
|
||||||
|
editable={false}
|
||||||
|
value={value?.tags}
|
||||||
|
request={{
|
||||||
|
groupsApi: {
|
||||||
|
get: getSampleTagGroup,
|
||||||
|
create: createSampleTagGroup,
|
||||||
|
delete: deleteSampleTagGroup,
|
||||||
|
update: updateSampleTagGroup,
|
||||||
|
},
|
||||||
|
tagsApi: {
|
||||||
|
get: getSampleTagPage,
|
||||||
|
create: createSampleTag,
|
||||||
|
delete: deleteSampleTag,
|
||||||
|
update: updateSampleTag,
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
title="管理技术标签"
|
||||||
|
width={800}
|
||||||
|
height={500}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
<ProFormGroup title="标签">
|
|
||||||
{/* <Form.Item name="tag"> */}
|
|
||||||
{forMap(value.tags || [])}
|
|
||||||
</ProFormGroup>
|
|
||||||
<Button
|
|
||||||
type="dashed"
|
|
||||||
block
|
|
||||||
style={{ marginBottom: 24 }}
|
|
||||||
onClick={handleAddTag}
|
|
||||||
>
|
|
||||||
添加标签
|
|
||||||
</Button>
|
|
||||||
<ProFormGroup title="文本信息" block></ProFormGroup>
|
|
||||||
<Space size={10} style={{ width: '100%', marginBottom: 12 }}>
|
|
||||||
<span>添加日期: </span>
|
|
||||||
<span>
|
|
||||||
{dayjs(value.createTime).format('YYYY-MM-DD HH:mm:ss')}
|
|
||||||
</span>
|
|
||||||
</Space>
|
|
||||||
<Space size={10} style={{ width: '100%', marginBottom: 12 }}>
|
|
||||||
<span>修改日期</span>
|
|
||||||
<span>
|
|
||||||
{dayjs(value.updateTime).format('YYYY-MM-DD HH:mm:ss')}
|
|
||||||
</span>
|
|
||||||
</Space>
|
|
||||||
<Space size={10} style={{ width: '100%', marginBottom: 12 }}>
|
|
||||||
<span>文件大小: </span>
|
|
||||||
<span>{value.sampleSize}</span>
|
|
||||||
</Space>
|
|
||||||
<Space size={10} style={{ width: '100%', marginBottom: 12 }}>
|
|
||||||
<span>格式: </span>
|
|
||||||
<span>{value.sampleMineType}</span>
|
|
||||||
</Space>
|
|
||||||
|
|
||||||
{type === 'checkbox' && (
|
|
||||||
<>
|
|
||||||
<ProFormGroup title="其他"></ProFormGroup>
|
|
||||||
<Button
|
|
||||||
block
|
|
||||||
style={{ marginBottom: 24 }}
|
|
||||||
onClick={handleTagManager}
|
|
||||||
>
|
|
||||||
批量重命名
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
block
|
|
||||||
style={{ marginBottom: 24 }}
|
|
||||||
onClick={handleDownloadAll}
|
|
||||||
>
|
|
||||||
下载到本地
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
block
|
|
||||||
color="danger"
|
|
||||||
style={{ marginBottom: 24 }}
|
|
||||||
onClick={handleDeleteAll}
|
|
||||||
>
|
|
||||||
删除样本
|
|
||||||
</Button>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</ProForm>
|
|
||||||
<GroupTagModal
|
|
||||||
visible={modalVisible}
|
|
||||||
onCancel={() => setModalVisible(false)}
|
|
||||||
onChange={onListAddTag}
|
|
||||||
editable={false}
|
|
||||||
value={value?.tags}
|
|
||||||
request={{
|
|
||||||
groupsApi: {
|
|
||||||
get: getSampleTagGroup,
|
|
||||||
create: createSampleTagGroup,
|
|
||||||
delete: deleteSampleTagGroup,
|
|
||||||
update: updateSampleTagGroup,
|
|
||||||
},
|
|
||||||
tagsApi: {
|
|
||||||
get: getSampleTagPage,
|
|
||||||
create: createSampleTag,
|
|
||||||
delete: deleteSampleTag,
|
|
||||||
update: updateSampleTag,
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
title="管理技术标签"
|
|
||||||
width={800}
|
|
||||||
height={500}
|
|
||||||
/>
|
|
||||||
<TagManager
|
<TagManager
|
||||||
visible={tagManagerVisible}
|
visible={tagManagerVisible}
|
||||||
files={tagNames}
|
files={tagNames}
|
||||||
onOk={onRename}
|
onOk={onRename}
|
||||||
onCancel={() => setTagManagerVisible(false)}
|
onCancel={() => setTagManagerVisible(false)}
|
||||||
></TagManager>
|
></TagManager>
|
||||||
{type === 'radio' && (
|
{type === 'radio' ? (
|
||||||
<Space
|
<Space
|
||||||
style={{ width: '100%', justifyContent: 'center', padding: 12 }}
|
style={{ width: '100%', justifyContent: 'center', padding: 12 }}
|
||||||
|
className="tag-manager-btns"
|
||||||
>
|
>
|
||||||
<Button color="danger" onClick={onDownload}>
|
<Button color="danger" onClick={onDownload}>
|
||||||
下载
|
下载
|
||||||
@@ -344,10 +328,31 @@ const SampleTagDetail = <T extends Record<string, any>>(
|
|||||||
删除
|
删除
|
||||||
</Button>
|
</Button>
|
||||||
</Space>
|
</Space>
|
||||||
|
) : (
|
||||||
|
<Space
|
||||||
|
style={{
|
||||||
|
width: '100%',
|
||||||
|
justifyContent: 'center',
|
||||||
|
padding: 12,
|
||||||
|
flexWrap: 'wrap',
|
||||||
|
flexDirection: 'column',
|
||||||
|
}}
|
||||||
|
className="tag-manager-btns"
|
||||||
|
>
|
||||||
|
<Button block onClick={handleTagManager}>
|
||||||
|
批量重命名
|
||||||
|
</Button>
|
||||||
|
<Button block onClick={handleDownloadAll}>
|
||||||
|
下载到本地
|
||||||
|
</Button>
|
||||||
|
<Button block color="danger" onClick={handleDeleteAll}>
|
||||||
|
删除样本
|
||||||
|
</Button>
|
||||||
|
</Space>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
'暂无数据-请选择样本'
|
<Empty description="未选择样本" />
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,28 +1,38 @@
|
|||||||
.tag-content {
|
.tag-content {
|
||||||
background: #fff;
|
background: #fff;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
overflow: auto;
|
height: calc(100vh - 90px);
|
||||||
|
display: flex;
|
||||||
|
overflow: hidden;
|
||||||
:global {
|
:global {
|
||||||
.left {
|
.left {
|
||||||
padding-right: 385px;
|
background: #fff;
|
||||||
|
overflow: auto;
|
||||||
|
flex: 1;
|
||||||
}
|
}
|
||||||
.uploader-card {
|
|
||||||
padding-right: 400px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.detail {
|
.detail {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
border-left: 1px solid #e8e8e8;
|
border-left: 1px solid #e8e8e8;
|
||||||
border-top: 1px solid #e8e8e8;
|
width: 360px;
|
||||||
width: 400px;
|
|
||||||
padding: 16px;
|
|
||||||
top: 74px;
|
|
||||||
height: calc(100vh - 80px);
|
height: calc(100vh - 80px);
|
||||||
overflow: auto;
|
overflow-y: auto;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
position: fixed;
|
overflow-x: hidden;
|
||||||
right: 0;
|
position: relative;
|
||||||
|
.ant-pro-form-group-title {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
.sample-tag-detail {
|
||||||
|
padding: 16px;
|
||||||
|
}
|
||||||
|
.tag-manager-btns {
|
||||||
|
position: sticky;
|
||||||
|
bottom: 10px;
|
||||||
|
background: #fff;
|
||||||
|
box-shadow: 0 0 10px #e8e8e8;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
form {
|
form {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -87,6 +87,7 @@ export interface AiSampleRespVO {
|
|||||||
*/
|
*/
|
||||||
sampleTime?: string;
|
sampleTime?: string;
|
||||||
tags?: { tagName?: string; id?: number }[];
|
tags?: { tagName?: string; id?: number }[];
|
||||||
|
enumTags?: { tagName?: string; id?: number; enumValue?: string }[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SampleReqVo extends PageParam {
|
export interface SampleReqVo extends PageParam {
|
||||||
|
|||||||
Reference in New Issue
Block a user