23 Commits

Author SHA1 Message Date
a2c5711d43 feat: 样本标签增加枚举标签
All checks were successful
Auto Deploy / build-and-deploy (push) Successful in 36s
2026-03-05 17:03:12 +08:00
945f795f81 Merge branch 'wuxichen' of http://gitea.tashowz.com/tashow/tashow-manager into wuxichen
All checks were successful
Auto Deploy / build-and-deploy (push) Successful in 31s
2026-03-04 10:11:59 +08:00
bf7d0b3bc5 feat: 修改状态名称 2026-03-04 10:11:04 +08:00
cb7b22bca3 chore(docs): 删除 CLAUDE.md 文件并清理登录页面临时文本
All checks were successful
Auto Deploy / build-and-deploy (push) Successful in 33s
- 移除整个 CLAUDE.md 项目指导文件
- 清理登录页面中的临时调试文本 "111"
2026-03-04 09:57:06 +08:00
d5a795de77 feat: 更新登录页面和项目文档
All checks were successful
Auto Deploy / build-and-deploy (push) Successful in 32s
- 添加 CLAUDE.md 项目文档
- 添加自动部署脚本
- 修改登录页面"其他登录方式"文本

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 09:25:22 +08:00
6a3aa3bf5d chore(login): 更新登录页面其他登录方式文本
All checks were successful
Auto Deploy / build-and-deploy (push) Successful in 33s
- 将"其他登录方式"修改为"其他登录方式111111"
2026-03-02 17:52:06 +08:00
4ad3706dfa chore(login): 更新登录页面其他登录方式文本
All checks were successful
Auto Deploy / build-and-deploy (push) Successful in 38s
- 将"其他登录方式"修改为"其他登录方式111111"
2026-03-02 17:44:23 +08:00
44426d8812 chore(ci): 更新部署工作流注释
All checks were successful
Auto Deploy / build-and-deploy (push) Successful in 33s
- 移除 pnpm 缓存相关注释内容
2026-03-02 17:40:20 +08:00
c970931954 chore(login): 更新登录页面其他登录方式文本
All checks were successful
Auto Deploy / build-and-deploy (push) Successful in 32s
- 将"其他登录方式"修改为"其他登录方式1111"
2026-03-02 17:35:31 +08:00
ba1a7f392b chore(login): 更新登录页面其他登录方式文本
All checks were successful
Auto Deploy / build-and-deploy (push) Successful in 35s
- 将"其他登录方式"修改为"其他登录方式1111"
2026-03-02 17:33:26 +08:00
16bb5afaa7 chore(login): 更新登录页面其他登录方式文本
All checks were successful
Auto Deploy / build-and-deploy (push) Successful in 34s
- 将"其他登录方式"修改为"其他登录方式1111"
2026-03-02 17:32:10 +08:00
22ef893529 chore(login): 更新登录页面其他登录方式文本
All checks were successful
Auto Deploy / build-and-deploy (push) Successful in 2m7s
- 将"其他登录方式"修改为"其他登录方式1111"
2026-03-02 17:28:50 +08:00
066cee46b0 chore(login): 更新登录页面其他登录方式文本
Some checks failed
Auto Deploy / build-and-deploy (push) Has been cancelled
- 将"其他登录方式"修改为"其他登录方式1111"
2026-03-02 17:27:58 +08:00
b4017597f9 fix: 移除 frozen-lockfile 标志以兼容服务器环境 2026-03-02 17:27:36 +08:00
f27fc56fd4 chore(login): 更新登录页面其他登录方式文本
Some checks failed
Auto Deploy / build-and-deploy (push) Failing after 1s
- 将"其他登录方式"修改为"其他登录方式1111"
2026-03-02 17:22:51 +08:00
47623d6b1e perf: 优化 CI/CD 流程,使用持久化目录和缓存加速部署
Some checks failed
Auto Deploy / build-and-deploy (push) Failing after 6s
2026-03-02 17:21:08 +08:00
7426746239 chore(login): 更新登录页面其他登录方式文本
All checks were successful
Auto Deploy / build-and-deploy (push) Successful in 2m19s
- 将"其他登录方式"修改为"其他登录方式1111"
2026-03-02 17:12:56 +08:00
ecbd4eefd7 chore(login): 更新登录页面其他登录方式文本
All checks were successful
Auto Deploy / build-and-deploy (push) Successful in 1m52s
- 将"其他登录方式"修改为"其他登录方式1111"
2026-03-02 17:08:43 +08:00
448531f9d3 test: trigger CI/CD after installing Node.js and pnpm
All checks were successful
Auto Deploy / build-and-deploy (push) Successful in 4m25s
2026-03-02 16:55:07 +08:00
4facb02777 test: trigger CI/CD with self-hosted runner
Some checks failed
Auto Deploy / build-and-deploy (push) Failing after 6s
2026-03-02 16:47:33 +08:00
929cb1966b fix: use self-hosted runner for CI/CD
Some checks failed
Auto Deploy / build-and-deploy (push) Failing after 6s
2026-03-02 16:39:21 +08:00
aa2f07de41 test: add test file for CI/CD verification
Some checks failed
Auto Deploy / build-and-deploy (push) Failing after 11m8s
2026-03-02 16:23:28 +08:00
5c8cb3bc88 feat: update workflow for self-hosted runner
Some checks failed
Auto Deploy / build-and-deploy (push) Failing after 13m48s
2026-03-02 16:08:31 +08:00
8 changed files with 229 additions and 179 deletions

View File

@@ -9,34 +9,38 @@ on:
jobs:
build-and-deploy:
runs-on: ubuntu-latest
runs-on: self-hosted
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Build and Deploy
run: |
# 使用持久化工作目录,避免每次重新克隆
WORK_DIR="/root/tashow-deploy"
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '20'
# 首次运行时克隆代码
if [ ! -d "$WORK_DIR" ]; then
echo "首次部署,克隆代码..."
git clone http://gitea.tashowz.com/tashow/tashow-manager.git $WORK_DIR
fi
- name: Setup pnpm
uses: pnpm/action-setup@v2
with:
version: 8
cd $WORK_DIR
- name: Install dependencies
run: pnpm install
# 更新代码到最新版本
echo "更新代码..."
git fetch origin
git checkout ${{ github.ref_name }}
git reset --hard origin/${{ github.ref_name }}
- name: Build project
run: pnpm build
# 安装依赖
echo "安装依赖..."
pnpm install
- name: Deploy to server
uses: appleboy/scp-action@master
with:
host: ${{ secrets.SSH_HOST }}
username: ${{ secrets.SSH_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
source: "dist/*"
target: ${{ secrets.DEPLOY_PATH }}
strip_components: 1
# 构建项目
echo "构建项目..."
pnpm build
# 部署到服务器
echo "部署到服务器..."
rsync -av --delete dist/ /home/1panel/www/sites/admin.petshy.tashowz.com/index/
echo "部署成功!"

2
public/test.txt Normal file
View 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.

View File

@@ -112,7 +112,7 @@ export const layout: RunTimeLayoutConfig = ({
waterMarkProps: {
content: initialState?.currentUser?.user.nickname,
},
footerRender: () => <Footer />,
// footerRender: () => <Footer />,
onPageChange: () => {
const { location } = history;
// 如果没有登录,重定向到 login

View File

@@ -41,8 +41,8 @@ export const baseDeptColumns: ProColumns<AiModelRespVO>[] = [
) => (
<Switch
checked={record.status === 1}
checkedChildren="用"
unCheckedChildren="用"
checkedChildren="用"
unCheckedChildren="用"
onChange={(checked) => {
Modal.confirm({
title: '确认操作',

View File

@@ -20,21 +20,49 @@ export const baseTenantColumns: ProColumns<AiSampleRespVO>[] = [
ellipsis: true,
},
{
title: '文件格式',
width: 100,
dataIndex: 'sampleMineType',
title: '枚举标签',
dataIndex: 'enumTags',
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',
width: 200,
hideInSearch: true,
render: (_, record) => {
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: '注释',
width: 100,

View File

@@ -1,5 +1,6 @@
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 { FormInstance } from 'antd/lib';
import dayjs from 'dayjs';
@@ -13,6 +14,7 @@ import React, {
import GroupTagModal from '@/components/GroupTag/GroupTagModal';
import type { TagItem } from '@/components/GroupTag/types';
import type { FileItem } from '@/components/RenameRule';
import TagEditor from '@/components/TagEditor';
import {
createSampleTag,
createSampleTagGroup,
@@ -177,28 +179,50 @@ const SampleTagDetail = <T extends Record<string, any>>(
<>
{data!.length > 0 ? (
<>
<ProForm name="validate_other" formRef={formRef} submitter={false}>
{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="基本信息">
<div className="sample-tag-detail">
<ProForm name="validate_other" formRef={formRef} submitter={false}>
{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
width="md"
name="sampleName"
placeholder="请输入样本名称"
fieldProps={{
onBlur: async (e) => {
if (e.target.value) {
@@ -206,136 +230,96 @@ const SampleTagDetail = <T extends Record<string, any>>(
data?.map((sample) => {
return {
id: sample.id,
sampleName: e.target.value,
remark: e.target.value,
};
}) || [];
await updateSamples(newData);
props?.onRefresh?.();
message.success('更新样本名称成功');
message.success('更新注释成功');
}
},
}}
rules={[{ required: true, message: '样本名称不能为空' }]}
name="remark"
placeholder="请输入注释"
/>
)}
<ProFormText
width="md"
fieldProps={{
onBlur: async (e) => {
if (e.target.value) {
const newData =
data?.map((sample) => {
return {
id: sample.id,
remark: e.target.value,
};
}) || [];
await updateSamples(newData);
props?.onRefresh?.();
message.success('更新注释成功');
}
},
}}
name="remark"
placeholder="请输入注释"
/>
</ProFormGroup>
</ProFormGroup>
<ProFormGroup title="枚举标签" block></ProFormGroup>
<ProForm.Item name="tag1" label="物种">
<TagEditor maxCount={1} />
</ProForm.Item>
<ProForm.Item name="tag2" label="情绪">
<TagEditor maxCount={1} />
</ProForm.Item>
<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>
</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
visible={tagManagerVisible}
files={tagNames}
onOk={onRename}
onCancel={() => setTagManagerVisible(false)}
></TagManager>
{type === 'radio' && (
{type === 'radio' ? (
<Space
style={{ width: '100%', justifyContent: 'center', padding: 12 }}
className="tag-manager-btns"
>
<Button color="danger" onClick={onDownload}>
@@ -344,10 +328,31 @@ const SampleTagDetail = <T extends Record<string, any>>(
</Button>
</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="未选择样本" />
)}
</>
);

View File

@@ -1,28 +1,38 @@
.tag-content {
background: #fff;
width: 100%;
overflow: auto;
height: calc(100vh - 90px);
display: flex;
overflow: hidden;
:global {
.left {
padding-right: 385px;
background: #fff;
overflow: auto;
flex: 1;
}
.uploader-card {
padding-right: 400px;
}
.detail {
display: flex;
flex-direction: column;
border-left: 1px solid #e8e8e8;
border-top: 1px solid #e8e8e8;
width: 400px;
padding: 16px;
top: 74px;
width: 360px;
height: calc(100vh - 80px);
overflow: auto;
overflow-y: auto;
background: #fff;
position: fixed;
right: 0;
overflow-x: hidden;
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 {
flex: 1;
}

View File

@@ -87,6 +87,7 @@ export interface AiSampleRespVO {
*/
sampleTime?: string;
tags?: { tagName?: string; id?: number }[];
enumTags?: { tagName?: string; id?: number; enumValue?: string }[];
}
export interface SampleReqVo extends PageParam {