diff --git a/logs/infra-server.log.2025-07-25.0.gz b/logs/infra-server.log.2025-07-25.0.gz
deleted file mode 100644
index 16fd04f..0000000
Binary files a/logs/infra-server.log.2025-07-25.0.gz and /dev/null differ
diff --git a/logs/infra-server.log.2025-07-28.0.gz b/logs/infra-server.log.2025-07-28.0.gz
deleted file mode 100644
index 1aa7573..0000000
Binary files a/logs/infra-server.log.2025-07-28.0.gz and /dev/null differ
diff --git a/logs/system-server.log.2025-07-28.0.gz b/logs/system-server.log.2025-07-28.0.gz
deleted file mode 100644
index 1f4fd79..0000000
Binary files a/logs/system-server.log.2025-07-28.0.gz and /dev/null differ
diff --git a/sql/db2/README.md b/sql/db2/README.md
deleted file mode 100644
index d9a95a8..0000000
--- a/sql/db2/README.md
+++ /dev/null
@@ -1,3 +0,0 @@
-暂未适配 IBM DB2 数据库,如果你有需要,可以微信联系 wangwenbin-server 一起建设。
-
-你需要把表结构与数据导入到 DM 数据库,我a来测试与适配代码。
diff --git a/sql/mysql/ai-manage.sql b/sql/mysql/ai-manage.sql
new file mode 100644
index 0000000..b160e05
--- /dev/null
+++ b/sql/mysql/ai-manage.sql
@@ -0,0 +1,72 @@
+DROP TABLE IF EXISTS `tz_ai_sample`;
+CREATE TABLE `tz_ai_sample`
+(
+ `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
+ `sample_file_id` bigint NOT NULL COMMENT '样本文件id',
+ `sample_name` varchar(64) NULL DEFAULT '' COMMENT '样本名称',
+ `sample_time` varchar(16) NULL DEFAULT '' COMMENT '样本时长',
+ `sample_mine_type` varchar(16) NULL DEFAULT '' COMMENT '样本格式',
+ `sample_size` varchar(16) NULL DEFAULT '' COMMENT '样本大小',
+ `remark` varchar(255) NULL DEFAULT '' COMMENT '样本注释',
+ `creator` varchar(64) NULL DEFAULT '' COMMENT '创建者',
+ `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ `updater` varchar(64) NULL DEFAULT '' COMMENT '更新者',
+ `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
+ `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
+ `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
+ PRIMARY KEY (`id`) USING BTREE,
+ INDEX `idx_create_time` (`create_time` ASC) USING BTREE
+) ENGINE = InnoDB COMMENT = '样本库';
+
+
+DROP TABLE IF EXISTS `tz_ai_sample_tag_relate`;
+CREATE TABLE `tz_ai_sample_tag_relate`
+(
+ `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
+ `sample_id` bigint NOT NULL COMMENT '样本id',
+ `sample_tag_id` bigint NOT NULL COMMENT '样本标签id',
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB COMMENT = '样本-标签关联表';
+
+
+
+DROP TABLE IF EXISTS `tz_ai_sample_tag`;
+CREATE TABLE `tz_ai_sample_tag`
+(
+ `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
+ `tag_name` varchar(64) NULL DEFAULT '' COMMENT '标签名称',
+ `creator` varchar(64) NULL DEFAULT '' COMMENT '创建者',
+ `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ `updater` varchar(64) NULL DEFAULT '' COMMENT '更新者',
+ `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
+ `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
+ `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
+ PRIMARY KEY (`id`) USING BTREE,
+ INDEX `idx_create_time` (`create_time` ASC) USING BTREE
+) ENGINE = InnoDB COMMENT = '样本标签库';
+
+DROP TABLE IF EXISTS `tz_ai_sample_tag_group`;
+CREATE TABLE `tz_ai_sample_tag_group`
+(
+ `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
+ `group_name` varchar(64) NULL DEFAULT '' COMMENT '分组名称',
+ `creator` varchar(64) NULL DEFAULT '' COMMENT '创建者',
+ `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ `updater` varchar(64) NULL DEFAULT '' COMMENT '更新者',
+ `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
+ `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
+ `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
+ PRIMARY KEY (`id`) USING BTREE,
+ INDEX `idx_create_time` (`create_time` ASC) USING BTREE
+) ENGINE = InnoDB COMMENT = '样本标签分组库';
+
+
+
+DROP TABLE IF EXISTS `tz_ai_sample_tag_group_relate`;
+CREATE TABLE `tz_ai_sample_tag_group_relate`
+(
+ `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
+ `sample_tag_id` bigint NOT NULL COMMENT '样本标签id',
+ `sample_tag_group_id` bigint NOT NULL COMMENT '样本标签分组id',
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB COMMENT = '样本标签-分组关联表';
diff --git a/sql/mysql/ruoyi-vue-pro.sql b/sql/mysql/tashow-base.sql
similarity index 100%
rename from sql/mysql/ruoyi-vue-pro.sql
rename to sql/mysql/tashow-base.sql
diff --git a/sql/tools/.gitignore b/sql/tools/.gitignore
deleted file mode 100644
index e00c3e7..0000000
--- a/sql/tools/.gitignore
+++ /dev/null
@@ -1,8 +0,0 @@
-# 忽略python虚拟环境
-.env
-.venv
-env/
-venv/
-ENV/
-env.bak/
-venv.bak/
diff --git a/sql/tools/README.md b/sql/tools/README.md
deleted file mode 100644
index 94c5300..0000000
--- a/sql/tools/README.md
+++ /dev/null
@@ -1,130 +0,0 @@
-## 0. 友情提示
-
-在 `sql/tools` 目录下,我们提供一些数据库相关的工具,包括测试数据库的快速启动、MySQL 转换其它数据库等等。
-
-注意!所有的操作,必须在 `sql/tools` 目录下执行。
-
-## 1. 测试数据库的快速启动
-
-基于 Docker Compose,快速启动 MySQL、Oracle、PostgreSQL、SQL Server 等数据库。
-
-注意!使用 Docker Compose 启动完测试数据后,因为会自动导入项目的 SQL 脚本,所以可能需要等待 1-2 分钟。
-
-### 1.1 MySQL
-
-```Bash
-docker compose up -d mysql
-```
-
-#### 1.2 Oracle
-
-```Bash
-## x86 版本
-docker compose up -d oracle
-
-## MacBook Apple Silicon
-docker compose up -d oracle_m1
-```
-
-> 注意:如果使用 MacBook Apple Silicon 版本,它的 ORACLE_SID 不是 XE,而是 FREE!!!
-
-### 1.3 PostgreSQL
-
-```Bash
-docker compose up -d postgres
-```
-
-### 1.4 SQL Server
-
-```Bash
-docker compose up -d sqlserver
-# 注意:启动完 sqlserver 后,需要手动再执行如下命令,因为 SQL Server 不支持初始化脚本
-docker compose exec sqlserver bash /tmp/create_schema.sh
-```
-
-### 1.5 DM 达梦
-
-① 下载达梦 Docker 镜像: 地址,点击“Docker 镜像”选项,进行下载。
-
-② 加载镜像文件,在镜像 tar 文件所在目录运行:
-
-```Bash
-docker load -i dm8_20240715_x86_rh6_rq_single.tar
-```
-
-③ 在项目 `sql/tools` 目录下运行:
-
-```Bash
-docker compose up -d dm8
-# 注意:启动完 dm 后,需要手动再执行如下命令,因为 dm 不支持初始化脚本
-docker compose exec dm8 bash -c '/opt/dmdbms/bin/disql SYSDBA/SYSDBA001 \`/tmp/schema.sql'
-exit
-```
-
-### 1.6 KingbaseES 人大金仓
-
-① 下载人大金仓 Docker 镜像:
-
-* [x86_64 版本](https://kingbase.oss-cn-beijing.aliyuncs.com/KESV8R3/V009R001C001B0025-安装包-docker/x86_64/kdb_x86_64_V009R001C001B0025.tar) 【Windows 选择这个】
-* [aarch64 版本](https://kingbase.oss-cn-beijing.aliyuncs.com/KESV8R3/V009R001C001B0025-安装包-docker/aarch64/kdb_aarch64_V009R001C001B0025.tar) 【MacBook Apple Silicon 选择这个】
-
-② 加载镜像文件,在镜像 tar 文件所在目录运行:
-
-```Bash
-docker load -i kdb_x86_64_V009R001C001B0025.tar
-```
-
-③ 在项目 `sql/tools` 目录下运行:
-
-```Bash
-docker compose up -d kingbase
-# 注意:启动完 kingbase 后,需要手动再执行如下命令
-docker compose exec kingbase bash -c 'ksql -U $DB_USER -d test -f /tmp/schema.sql'
-```
-
-### 1.7 华为 OpenGauss
-
-```Bash
-docker compose up -d opengauss
-# 注意:启动完 opengauss 后,需要手动再执行如下命令
-docker compose exec opengauss bash -c '/usr/local/opengauss/bin/gsql -U $GS_USERNAME -W $GS_PASSWORD -d postgres -f /tmp/schema.sql'
-```
-
-## 1.X 容器的销毁重建
-
-开发测试过程中,有时候需要创建全新干净的数据库。由于测试数据 Docker 容器采用数据卷 Volume 挂载数据库实例的数据目录,因此销毁数据需要停止容器后,删除数据卷,然后再重新创建容器。
-
-以 postgres 为例,操作如下:
-
-```Bash
-docker compose down postgres
-docker volume rm ruoyi-vue-pro_postgres
-```
-
-## 2. MySQL 转换其它数据库
-
-项目提供了 `sql/tools/convertor.py` 脚本,支持将 MySQL 转换为 Oracle、PostgreSQL、SQL Server、达梦、人大金仓、OpenGauss 等数据库的脚本。
-
-### 2.1 实现原理
-
-通过读取 MySQL 的 `sql/mysql/ruoyi-vue-pro.sql` 数据库文件,转换成对应的数据库脚本。
-
-### 2.2 使用方法
-
-① 安装依赖库 `simple-ddl-parser`
-
-```bash
-pip install simple-ddl-parser
-# pip3 install simple-ddl-parser
-```
-
-② 在 `sql/tools/` 目录下,执行如下命令打印生成 postgres 的脚本内容,其他可选参数有:`oracle`、`sqlserver`、`dm8`、`kingbase`、`opengauss`:
-
-```Bash
-python3 convertor.py postgres
-# python3 convertor.py postgres > tmp.sql
-```
-
-程序将 SQL 脚本打印到终端,可以重定向到临时文件 `tmp.sql`。
-
-确认无误后,可以利用 IDEA 进行格式化。当然,也可以直接导入到数据库中。
diff --git a/sql/tools/convertor.py b/sql/tools/convertor.py
deleted file mode 100644
index f672cd7..0000000
--- a/sql/tools/convertor.py
+++ /dev/null
@@ -1,844 +0,0 @@
-# encoding=utf8
-"""芋道系统数据库迁移工具
-
-Author: dhb52 (https://gitee.com/dhb52)
-
-pip install simple-ddl-parser
-"""
-
-import argparse
-import pathlib
-import re
-import time
-from abc import ABC, abstractmethod
-from typing import Dict, Generator, Optional, Tuple, Union
-
-from simple_ddl_parser import DDLParser
-
-PREAMBLE = """/*
- Yudao Database Transfer Tool
-
- Source Server Type : MySQL
-
- Target Server Type : {db_type}
-
- Date: {date}
-*/
-
-"""
-
-
-def load_and_clean(sql_file: str) -> str:
- """加载源 SQL 文件,并清理内容方便下一步 ddl 解析
-
- Args:
- sql_file (str): sql文件路径
-
- Returns:
- str: 清理后的sql文件内容
- """
- REPLACE_PAIR_LIST = (
- (" CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci ", " "),
- (" KEY `", " INDEX `"),
- ("UNIQUE INDEX", "UNIQUE KEY"),
- ("b'0'", "'0'"),
- ("b'1'", "'1'"),
- )
-
- content = open(sql_file).read()
- for replace_pair in REPLACE_PAIR_LIST:
- content = content.replace(*replace_pair)
- content = re.sub(r"ENGINE.*COMMENT", "COMMENT", content)
- content = re.sub(r"ENGINE.*;", ";", content)
- return content
-
-
-class Convertor(ABC):
- def __init__(self, src: str, db_type) -> None:
- self.src = src
- self.db_type = db_type
- self.content = load_and_clean(self.src)
- self.table_script_list = re.findall(r"CREATE TABLE [^;]*;", self.content)
-
- @abstractmethod
- def translate_type(self, type: str, size: Optional[Union[int, Tuple[int]]]) -> str:
- """字段类型转换
-
- Args:
- type (str): 字段类型
- size (Optional[Union[int, Tuple[int]]]): 字段长度描述, 如varchar(255), decimal(10,2)
-
- Returns:
- str: 类型定义
- """
- pass
-
- @abstractmethod
- def gen_create(self, table_ddl: Dict) -> str:
- """生成 create 脚本
-
- Args:
- table_ddl (Dict): 表DDL
-
- Returns:
- str: 生成脚本
- """
- pass
-
- @abstractmethod
- def gen_pk(self, table_name: str) -> str:
- """生成主键定义
-
- Args:
- table_name (str): 表名
-
- Returns:
- str: 生成脚本
- """
- pass
-
- @abstractmethod
- def gen_index(self, ddl: Dict) -> str:
- """生成索引定义
-
- Args:
- table_ddl (Dict): 表DDL
-
- Returns:
- str: 生成脚本
- """
- pass
-
- @abstractmethod
- def gen_comment(self, table_sql: str, table_name: str) -> str:
- """生成字段/表注释
-
- Args:
- table_sql (str): 原始表SQL
- table_name (str): 表名
-
- Returns:
- str: 生成脚本
- """
- pass
-
- @abstractmethod
- def gen_insert(self, table_name: str) -> str:
- """生成 insert 语句块
-
- Args:
- table_name (str): 表名
-
- Returns:
- str: 生成脚本
- """
- pass
-
- def gen_dual(self) -> str:
- """生成虚拟 dual 表
-
- Returns:
- str: 生成脚本, 默认返回空脚本, 表示当前数据库无需手工创建
- """
- return ""
-
- @staticmethod
- def inserts(table_name: str, script_content: str) -> Generator:
- PREFIX = f"INSERT INTO `{table_name}`"
-
- # 收集 `table_name` 对应的 insert 语句
- for line in script_content.split("\n"):
- if line.startswith(PREFIX):
- head, tail = line.replace(PREFIX, "").split(" VALUES ", maxsplit=1)
- head = head.strip().replace("`", "").lower()
- tail = tail.strip().replace(r"\"", '"')
- # tail = tail.replace("b'0'", "'0'").replace("b'1'", "'1'")
- yield f"INSERT INTO {table_name.lower()} {head} VALUES {tail}"
-
- @staticmethod
- def index(ddl: Dict) -> Generator:
- """生成索引定义
-
- Args:
- ddl (Dict): 表DDL
-
- Yields:
- Generator[str]: create index 语句
- """
-
- def generate_columns(columns):
- keys = [
- f"{col['name'].lower()}{' ' + col['order'].lower() if col['order'] != 'ASC' else ''}"
- for col in columns[0]
- ]
- return ", ".join(keys)
-
- for no, index in enumerate(ddl["index"], 1):
- columns = generate_columns(index["columns"])
- table_name = ddl["table_name"].lower()
- yield f"CREATE INDEX idx_{table_name}_{no:02d} ON {table_name} ({columns})"
-
- @staticmethod
- def filed_comments(table_sql: str) -> Generator:
- for line in table_sql.split("\n"):
- match = re.match(r"^`([^`]+)`.* COMMENT '([^']+)'", line.strip())
- if match:
- field = match.group(1)
- comment_string = match.group(2).replace("\\n", "\n")
- yield field, comment_string
-
- def table_comment(self, table_sql: str) -> str:
- match = re.search(r"COMMENT \= '([^']+)';", table_sql)
- return match.group(1) if match else None
-
- def print(self):
- """打印转换后的sql脚本到终端"""
- print(
- PREAMBLE.format(
- db_type=self.db_type,
- date=time.strftime("%Y-%m-%d %H:%M:%S"),
- )
- )
-
- dual = self.gen_dual()
- if dual:
- print(
- f"""-- ----------------------------
--- Table structure for dual
--- ----------------------------
-{dual}
-"""
- )
-
- error_scripts = []
- for table_sql in self.table_script_list:
- ddl = DDLParser(table_sql.replace("`", "")).run()
-
- # 如果parse失败, 需要跟进
- if len(ddl) == 0:
- error_scripts.append(table_sql)
- continue
-
- table_ddl = ddl[0]
- table_name = table_ddl["table_name"]
-
- # 忽略 quartz 的内容
- if table_name.lower().startswith("qrtz"):
- continue
-
- # 为每个表生成个5个基本部分
- create = self.gen_create(table_ddl)
- pk = self.gen_pk(table_name)
- index = self.gen_index(table_ddl)
- comment = self.gen_comment(table_sql, table_name)
- inserts = self.gen_insert(table_name)
-
- # 组合当前表的DDL脚本
- script = f"""{create}
-
-{pk}
-
-{index}
-
-{comment}
-
-{inserts}
-"""
-
- # 清理
- script = re.sub("\n{3,}", "\n\n", script).strip() + "\n"
-
- print(script)
-
- # 将parse失败的脚本打印出来
- if error_scripts:
- for script in error_scripts:
- print(script)
-
-
-class PostgreSQLConvertor(Convertor):
- def __init__(self, src):
- super().__init__(src, "PostgreSQL")
-
- def translate_type(self, type: str, size: Optional[Union[int, Tuple[int]]]):
- """类型转换"""
-
- type = type.lower()
-
- if type == "varchar":
- return f"varchar({size})"
- if type == "int":
- return "int4"
- if type == "bigint" or type == "bigint unsigned":
- return "int8"
- if type == "datetime":
- return "timestamp"
- if type == "bit":
- return "bool"
- if type in ("tinyint", "smallint"):
- return "int2"
- if type == "text":
- return "text"
- if type in ("blob", "mediumblob"):
- return "bytea"
- if type == "decimal":
- return (
- f"numeric({','.join(str(s) for s in size)})" if len(size) else "numeric"
- )
-
- def gen_create(self, ddl: Dict) -> str:
- """生成 create"""
-
- def _generate_column(col):
- name = col["name"].lower()
- if name == "deleted":
- return "deleted int2 NOT NULL DEFAULT 0"
-
- type = col["type"].lower()
- full_type = self.translate_type(type, col["size"])
- nullable = "NULL" if col["nullable"] else "NOT NULL"
- default = f"DEFAULT {col['default']}" if col["default"] is not None else ""
- return f"{name} {full_type} {nullable} {default}"
-
- table_name = ddl["table_name"].lower()
- columns = [f"{_generate_column(col).strip()}" for col in ddl["columns"]]
- filed_def_list = ",\n ".join(columns)
- script = f"""-- ----------------------------
--- Table structure for {table_name}
--- ----------------------------
-DROP TABLE IF EXISTS {table_name};
-CREATE TABLE {table_name} (
- {filed_def_list}
-);"""
-
- return script
-
- def gen_index(self, ddl: Dict) -> str:
- return "\n".join(f"{script};" for script in self.index(ddl))
-
- def gen_comment(self, table_sql: str, table_name: str) -> str:
- """生成字段及表的注释"""
-
- script = ""
- for field, comment_string in self.filed_comments(table_sql):
- script += (
- f"COMMENT ON COLUMN {table_name}.{field} IS '{comment_string}';" + "\n"
- )
-
- table_comment = self.table_comment(table_sql)
- if table_comment:
- script += f"COMMENT ON TABLE {table_name} IS '{table_comment}';\n"
-
- return script
-
- def gen_pk(self, table_name) -> str:
- """生成主键定义"""
- return f"ALTER TABLE {table_name} ADD CONSTRAINT pk_{table_name} PRIMARY KEY (id);\n"
-
- def gen_insert(self, table_name: str) -> str:
- """生成 insert 语句,以及根据最后的 insert id+1 生成 Sequence"""
-
- inserts = list(Convertor.inserts(table_name, self.content))
- ## 生成 insert 脚本
- script = ""
- last_id = 0
- if inserts:
- inserts_lines = "\n".join(inserts)
- script += f"""\n\n-- ----------------------------
--- Records of {table_name.lower()}
--- ----------------------------
--- @formatter:off
-BEGIN;
-{inserts_lines}
-COMMIT;
--- @formatter:on"""
- match = re.search(r"VALUES \((\d+),", inserts[-1])
- if match:
- last_id = int(match.group(1))
-
- # 生成 Sequence
- script += (
- "\n\n"
- + f"""DROP SEQUENCE IF EXISTS {table_name}_seq;
-CREATE SEQUENCE {table_name}_seq
- START {last_id + 1};"""
- )
-
- return script
-
- def gen_dual(self) -> str:
- return """DROP TABLE IF EXISTS dual;
-CREATE TABLE dual
-(
- id int2
-);
-
-COMMENT ON TABLE dual IS '数据库连接的表';
-
--- ----------------------------
--- Records of dual
--- ----------------------------
--- @formatter:off
-INSERT INTO dual VALUES (1);
--- @formatter:on"""
-
-
-class OracleConvertor(Convertor):
- def __init__(self, src):
- super().__init__(src, "Oracle")
-
- def translate_type(self, type: str, size: Optional[Union[int, Tuple[int]]]):
- """类型转换"""
- type = type.lower()
-
- if type == "varchar":
- return f"varchar2({size if size < 4000 else 4000})"
- if type == "int":
- return "number"
- if type == "bigint" or type == "bigint unsigned":
- return "number"
- if type == "datetime":
- return "date"
- if type == "bit":
- return "number(1,0)"
- if type in ("tinyint", "smallint"):
- return "smallint"
- if type == "text":
- return "clob"
- if type in ("blob", "mediumblob"):
- return "blob"
- if type == "decimal":
- return (
- f"number({','.join(str(s) for s in size)})" if len(size) else "number"
- )
-
- def gen_create(self, ddl) -> str:
- """生成 CREATE 语句"""
-
- def generate_column(col):
- name = col["name"].lower()
- if name == "deleted":
- return "deleted number(1,0) DEFAULT 0 NOT NULL"
-
- type = col["type"].lower()
- full_type = self.translate_type(type, col["size"])
- nullable = "NULL" if col["nullable"] else "NOT NULL"
- default = f"DEFAULT {col['default']}" if col["default"] is not None else ""
- # Oracle 中 size 不能作为字段名
- field_name = '"size"' if name == "size" else name
- # Oracle DEFAULT 定义在 NULLABLE 之前
- return f"{field_name} {full_type} {default} {nullable}"
-
- table_name = ddl["table_name"].lower()
- columns = [f"{generate_column(col).strip()}" for col in ddl["columns"]]
- field_def_list = ",\n ".join(columns)
- script = f"""-- ----------------------------
--- Table structure for {table_name}
--- ----------------------------
-CREATE TABLE {table_name} (
- {field_def_list}
-);"""
-
- # oracle INSERT '' 不能通过 NOT NULL 校验
- script = script.replace("DEFAULT '' NOT NULL", "DEFAULT '' NULL")
-
- return script
-
- def gen_index(self, ddl: Dict) -> str:
- return "\n".join(f"{script};" for script in self.index(ddl))
-
- def gen_comment(self, table_sql: str, table_name: str) -> str:
- script = ""
- for field, comment_string in self.filed_comments(table_sql):
- script += (
- f"COMMENT ON COLUMN {table_name}.{field} IS '{comment_string}';" + "\n"
- )
-
- table_comment = self.table_comment(table_sql)
- if table_comment:
- script += f"COMMENT ON TABLE {table_name} IS '{table_comment}';\n"
-
- return script
-
- def gen_pk(self, table_name: str) -> str:
- """生成主键定义"""
- return f"ALTER TABLE {table_name} ADD CONSTRAINT pk_{table_name} PRIMARY KEY (id);\n"
-
- def gen_index(self, ddl: Dict) -> str:
- return "\n".join(f"{script};" for script in self.index(ddl))
-
- def gen_insert(self, table_name: str) -> str:
- """拷贝 INSERT 语句"""
- inserts = []
- for insert_script in Convertor.inserts(table_name, self.content):
- # 对日期数据添加 TO_DATE 转换
- insert_script = re.sub(
- r"('\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}')",
- r"to_date(\g<1>, 'SYYYY-MM-DD HH24:MI:SS')",
- insert_script,
- )
- inserts.append(insert_script)
-
- ## 生成 insert 脚本
- script = ""
- last_id = 0
- if inserts:
- inserts_lines = "\n".join(inserts)
- script += f"""\n\n-- ----------------------------
--- Records of {table_name.lower()}
--- ----------------------------
--- @formatter:off
-{inserts_lines}
-COMMIT;
--- @formatter:on"""
- match = re.search(r"VALUES \((\d+),", inserts[-1])
- if match:
- last_id = int(match.group(1))
-
- # 生成 Sequence
- script += f"""
-
-CREATE SEQUENCE {table_name}_seq
- START WITH {last_id + 1};"""
-
- return script
-
-
-class SQLServerConvertor(Convertor):
- """_summary_
-
- Args:
- Convertor (_type_): _description_
- """
-
- def __init__(self, src):
- super().__init__(src, "Microsoft SQL Server")
-
- def translate_type(self, type: str, size: Optional[Union[int, Tuple[int]]]):
- """类型转换"""
-
- type = type.lower()
-
- if type == "varchar":
- return f"nvarchar({size if size < 4000 else 4000})"
- if type == "int":
- return "int"
- if type == "bigint" or type == "bigint unsigned":
- return "bigint"
- if type == "datetime":
- return "datetime2"
- if type == "bit":
- return "varchar(1)"
- if type in ("tinyint", "smallint"):
- return "tinyint"
- if type == "text":
- return "nvarchar(max)"
- if type in ("blob", "mediumblob"):
- return "varbinary(max)"
- if type == "decimal":
- return (
- f"numeric({','.join(str(s) for s in size)})" if len(size) else "numeric"
- )
-
- def gen_create(self, ddl: Dict) -> str:
- """生成 create"""
-
- def _generate_column(col):
- name = col["name"].lower()
- if name == "id":
- return "id bigint NOT NULL PRIMARY KEY IDENTITY"
- if name == "deleted":
- return "deleted bit DEFAULT 0 NOT NULL"
-
- type = col["type"].lower()
- full_type = self.translate_type(type, col["size"])
- nullable = "NULL" if col["nullable"] else "NOT NULL"
- default = f"DEFAULT {col['default']}" if col["default"] is not None else ""
- return f"{name} {full_type} {default} {nullable}"
-
- table_name = ddl["table_name"].lower()
- columns = [f"{_generate_column(col).strip()}" for col in ddl["columns"]]
- filed_def_list = ",\n ".join(columns)
- script = f"""-- ----------------------------
--- Table structure for {table_name}
--- ----------------------------
-DROP TABLE IF EXISTS {table_name}
-GO
-CREATE TABLE {table_name} (
- {filed_def_list}
-)
-GO"""
-
- return script
-
- def gen_comment(self, table_sql: str, table_name: str) -> str:
- """生成字段及表的注释"""
-
- script = ""
-
- for field, comment_string in self.filed_comments(table_sql):
- script += f"""EXEC sp_addextendedproperty
- 'MS_Description', N'{comment_string}',
- 'SCHEMA', N'dbo',
- 'TABLE', N'{table_name}',
- 'COLUMN', N'{field}'
-GO
-
-"""
-
- table_comment = self.table_comment(table_sql)
- if table_comment:
- script += f"""EXEC sp_addextendedproperty
- 'MS_Description', N'{table_comment}',
- 'SCHEMA', N'dbo',
- 'TABLE', N'{table_name}'
-GO
-
-"""
- return script
-
- def gen_pk(self, table_name: str) -> str:
- """生成主键定义"""
- return ""
-
- def gen_index(self, ddl: Dict) -> str:
- """生成 index"""
- return "\n".join(f"{script}\nGO" for script in self.index(ddl))
-
- def gen_insert(self, table_name: str) -> str:
- """生成 insert 语句"""
-
- # 收集 `table_name` 对应的 insert 语句
- inserts = []
- for insert_script in Convertor.inserts(table_name, self.content):
- # SQLServer: 字符串前加N,hack,是否存在替换字符串内容的风险
- insert_script = insert_script.replace(", '", ", N'").replace(
- "VALUES ('", "VALUES (N')"
- )
- # 删除 insert 的结尾分号
- insert_script = re.sub(";$", r"\nGO", insert_script)
- inserts.append(insert_script)
-
- ## 生成 insert 脚本
- script = ""
- if inserts:
- inserts_lines = "\n".join(inserts)
- script += f"""\n\n-- ----------------------------
--- Records of {table_name.lower()}
--- ----------------------------
--- @formatter:off
-BEGIN TRANSACTION
-GO
-SET IDENTITY_INSERT {table_name.lower()} ON
-GO
-{inserts_lines}
-SET IDENTITY_INSERT {table_name.lower()} OFF
-GO
-COMMIT
-GO
--- @formatter:on"""
-
- return script
-
- def gen_dual(self) -> str:
- return """DROP TABLE IF EXISTS dual
-GO
-CREATE TABLE dual
-(
- id int
-)
-GO
-
-EXEC sp_addextendedproperty
- 'MS_Description', N'数据库连接的表',
- 'SCHEMA', N'dbo',
- 'TABLE', N'dual'
-GO
-
--- ----------------------------
--- Records of dual
--- ----------------------------
--- @formatter:off
-INSERT INTO dual VALUES (1)
-GO
--- @formatter:on"""
-
-
-class DM8Convertor(Convertor):
- def __init__(self, src):
- super().__init__(src, "DM8")
-
- def translate_type(self, type: str, size: Optional[Union[int, Tuple[int]]]):
- """类型转换"""
- type = type.lower()
-
- if type == "varchar":
- return f"varchar({size})"
- if type == "int":
- return "int"
- if type == "bigint" or type == "bigint unsigned":
- return "bigint"
- if type == "datetime":
- return "datetime"
- if type == "bit":
- return "bit"
- if type in ("tinyint", "smallint"):
- return "smallint"
- if type == "text":
- return "text"
- if type == "blob":
- return "blob"
- if type == "mediumblob":
- return "varchar(10240)"
- if type == "decimal":
- return (
- f"decimal({','.join(str(s) for s in size)})" if len(size) else "decimal"
- )
-
- def gen_create(self, ddl) -> str:
- """生成 CREATE 语句"""
-
- def generate_column(col):
- name = col["name"].lower()
- if name == "id":
- return "id bigint NOT NULL PRIMARY KEY IDENTITY"
-
- type = col["type"].lower()
- full_type = self.translate_type(type, col["size"])
- nullable = "NULL" if col["nullable"] else "NOT NULL"
- default = f"DEFAULT {col['default']}" if col["default"] is not None else ""
- return f"{name} {full_type} {default} {nullable}"
-
- table_name = ddl["table_name"].lower()
- columns = [f"{generate_column(col).strip()}" for col in ddl["columns"]]
- field_def_list = ",\n ".join(columns)
- script = f"""-- ----------------------------
--- Table structure for {table_name}
--- ----------------------------
-CREATE TABLE {table_name} (
- {field_def_list}
-);"""
-
- # oracle INSERT '' 不能通过 NOT NULL 校验
- script = script.replace("DEFAULT '' NOT NULL", "DEFAULT '' NULL")
-
- return script
-
- def gen_index(self, ddl: Dict) -> str:
- return "\n".join(f"{script};" for script in self.index(ddl))
-
- def gen_comment(self, table_sql: str, table_name: str) -> str:
- script = ""
- for field, comment_string in self.filed_comments(table_sql):
- script += (
- f"COMMENT ON COLUMN {table_name}.{field} IS '{comment_string}';" + "\n"
- )
-
- table_comment = self.table_comment(table_sql)
- if table_comment:
- script += f"COMMENT ON TABLE {table_name} IS '{table_comment}';\n"
-
- return script
-
- def gen_pk(self, table_name: str) -> str:
- """生成主键定义"""
- return ""
-
- def gen_index(self, ddl: Dict) -> str:
- return "\n".join(f"{script};" for script in self.index(ddl))
-
- def gen_insert(self, table_name: str) -> str:
- """拷贝 INSERT 语句"""
- inserts = list(Convertor.inserts(table_name, self.content))
-
- ## 生成 insert 脚本
- script = ""
- if inserts:
- inserts_lines = "\n".join(inserts)
- script += f"""\n\n-- ----------------------------
--- Records of {table_name.lower()}
--- ----------------------------
--- @formatter:off
-SET IDENTITY_INSERT {table_name.lower()} ON;
-{inserts_lines}
-COMMIT;
-SET IDENTITY_INSERT {table_name.lower()} OFF;
--- @formatter:on"""
-
- return script
-
-
-class KingbaseConvertor(PostgreSQLConvertor):
- def __init__(self, src):
- super().__init__(src)
- self.db_type = "Kingbase"
-
- def gen_create(self, ddl: Dict) -> str:
- """生成 create"""
-
- def _generate_column(col):
- name = col["name"].lower()
- if name == "deleted":
- return "deleted int2 NOT NULL DEFAULT 0"
-
- type = col["type"].lower()
- full_type = self.translate_type(type, col["size"])
- nullable = "NULL" if col["nullable"] else "NOT NULL"
- default = f"DEFAULT {col['default']}" if col["default"] is not None else ""
- return f"{name} {full_type} {nullable} {default}"
-
- table_name = ddl["table_name"].lower()
- columns = [f"{_generate_column(col).strip()}" for col in ddl["columns"]]
- filed_def_list = ",\n ".join(columns)
- script = f"""-- ----------------------------
--- Table structure for {table_name}
--- ----------------------------
-DROP TABLE IF EXISTS {table_name};
-CREATE TABLE {table_name} (
- {filed_def_list}
-);"""
-
- # Kingbase INSERT '' 不能通过 NOT NULL 校验
- script = script.replace("NOT NULL DEFAULT ''", "NULL DEFAULT ''")
-
- return script
-
-
-class OpengaussConvertor(KingbaseConvertor):
- def __init__(self, src):
- super().__init__(src)
- self.db_type = "OpenGauss"
-
-
-def main():
- parser = argparse.ArgumentParser(description="芋道系统数据库转换工具")
- parser.add_argument(
- "type",
- type=str,
- help="目标数据库类型",
- choices=["postgres", "oracle", "sqlserver", "dm8", "kingbase", "opengauss"],
- )
- args = parser.parse_args()
-
- sql_file = pathlib.Path("../mysql/ruoyi-vue-pro.sql").resolve().as_posix()
- convertor = None
- if args.type == "postgres":
- convertor = PostgreSQLConvertor(sql_file)
- elif args.type == "oracle":
- convertor = OracleConvertor(sql_file)
- elif args.type == "sqlserver":
- convertor = SQLServerConvertor(sql_file)
- elif args.type == "dm8":
- convertor = DM8Convertor(sql_file)
- elif args.type == "kingbase":
- convertor = KingbaseConvertor(sql_file)
- elif args.type == "opengauss":
- convertor = OpengaussConvertor(sql_file)
- else:
- raise NotImplementedError(f"不支持目标数据库类型: {args.type}")
-
- convertor.print()
-
-
-if __name__ == "__main__":
- main()
diff --git a/sql/tools/docker-compose.yaml b/sql/tools/docker-compose.yaml
deleted file mode 100644
index 0fa9513..0000000
--- a/sql/tools/docker-compose.yaml
+++ /dev/null
@@ -1,134 +0,0 @@
-name: ruoyi-vue-pro
-
-volumes:
- mysql: { }
- postgres: { }
- sqlserver: { }
- dm8: { }
- kingbase: { }
- opengauss: { }
-
-services:
- mysql:
- image: mysql:8.0.33
- restart: unless-stopped
- environment:
- TZ: Asia/Shanghai
- MYSQL_ROOT_PASSWORD: 123456
- MYSQL_DATABASE: ruoyi-vue-pro
- ports:
- - "3306:3306"
- volumes:
- - mysql:/var/lib/mysql/
- # 注入初始化脚本
- - ./mysql/ruoyi-vue-pro.sql:/docker-entrypoint-initdb.d/init.sql:ro
- command:
- --default-authentication-plugin=mysql_native_password
- --character-set-server=utf8mb4
- --collation-server=utf8mb4_general_ci
- --explicit_defaults_for_timestamp=true
- --lower_case_table_names=1
-
- postgres:
- image: postgres:14.2
- restart: unless-stopped
- environment:
- POSTGRES_USER: root
- POSTGRES_PASSWORD: 123456
- POSTGRES_DB: ruoyi-vue-pro
- ports:
- - "5432:5432"
- volumes:
- - postgres:/var/lib/postgresql/data
- # 注入初始化脚本
- - ../postgresql/quartz.sql:/docker-entrypoint-initdb.d/quartz.sql:ro
- - ../postgresql/ruoyi-vue-pro.sql:/docker-entrypoint-initdb.d/ruoyi-vue-pro.sql:ro
-
- oracle:
- image: gvenzl/oracle-xe:18-slim-faststart
- restart: unless-stopped
- environment:
- ## 登录信息 SID: XE user: system password: oracle
- ORACLE_PASSWORD: oracle
- ports:
- - "1521:1521"
- volumes:
- - ../oracle/ruoyi-vue-pro.sql:/tmp/schema.sql:ro
- # 创建app用户: ROOT/123456@//localhost/XEPDB1
- - ./oracle/1_create_user.sql:/docker-entrypoint-initdb.d/1_create_user.sql:ro
- - ./oracle/2_create_schema.sh:/docker-entrypoint-initdb.d/2_create_schema.sh:ro
-
- oracle_m1:
- image: einslib/oracle-19c:19.3.0-ee-slim-faststart
- restart: unless-stopped
- environment:
- ## 登录信息 SID: FREE user: system password: oracle
- ORACLE_PASSWORD: oracle
- ports:
- - "1521:1521"
- volumes:
- - ../oracle/ruoyi-vue-pro.sql:/tmp/schema.sql:ro
- # 创建app用户: ROOT/123456@//localhost/XEPDB1
- - ./oracle/1_create_user.sql:/docker-entrypoint-initdb.d/1_create_user.sql:ro
- - ./oracle/2_create_schema.sh:/docker-entrypoint-initdb.d/2_create_schema.sh:ro
-
- sqlserver:
- image: mcr.microsoft.com/mssql/server:2017-latest
- restart: unless-stopped
- environment:
- TZ: Asia/Shanghai
- ACCEPT_EULA: "Y"
- SA_PASSWORD: "Yudao@2024"
- ports:
- - "1433:1433"
- volumes:
- - sqlserver:/var/opt/mssql
- - ../sqlserver/ruoyi-vue-pro.sql:/tmp/schema.sql:ro
- # docker compose exec sqlserver bash /tmp/create_schema.sh
- - ./sqlserver/create_schema.sh:/tmp/create_schema.sh:ro
-
- dm8:
- # docker load -i dm8_20240715_x86_rh6_rq_single.tar
- image: dm8_single:dm8_20240715_rev232765_x86_rh6_64
- restart: unless-stopped
- environment:
- PAGE_SIZE: 16
- LD_LIBRARY_PATH: /opt/dmdbms/bin
- EXTENT_SIZE: 32
- BLANK_PAD_MODE: 1
- LOG_SIZE: 1024
- UNICODE_FLAG: 1
- LENGTH_IN_CHAR: 1
- INSTANCE_NAME: dm8_test
- ports:
- - "5236:5236"
- volumes:
- - dm8:/opt/dmdbms/data
- - ../dm/ruoyi-vue-pro-dm8.sql:/tmp/schema.sql:ro
-
- kingbase:
- image: kingbase_v009r001c001b0025_single_x86:v1
-# image: kingbase_v009r001c001b0025_single_arm:v1
- restart: unless-stopped
- environment:
- DB_USER: root
- DB_PASSWORD: 123456
- ports:
- - "54321:54321"
- volumes:
- - kingbase:/home/kingbase/userdata
- - ../kingbase/ruoyi-vue-pro.sql:/tmp/schema.sql:ro
-
- opengauss:
- image: opengauss/opengauss:5.0.0
- restart: unless-stopped
- environment:
- GS_USERNAME: root
- GS_PASSWORD: Yudao@2024
- LD_LIBRARY_PATH: /usr/local/opengauss/lib:/usr/lib
- ports:
- - "5432:5432"
- volumes:
- - opengauss:/var/lib/opengauss
- - ../opengauss/ruoyi-vue-pro.sql:/tmp/schema.sql:ro
- # docker compose exec opengauss bash -c '/usr/local/opengauss/bin/gsql -U $GS_USERNAME -W $GS_PASSWORD -d postgres -f /tmp/schema.sql'
\ No newline at end of file
diff --git a/sql/tools/oracle/1_create_user.sql b/sql/tools/oracle/1_create_user.sql
deleted file mode 100644
index 58c9658..0000000
--- a/sql/tools/oracle/1_create_user.sql
+++ /dev/null
@@ -1,3 +0,0 @@
-ALTER SESSION SET CONTAINER=XEPDB1;
-CREATE USER ROOT IDENTIFIED BY 123456 QUOTA UNLIMITED ON USERS;
-GRANT CONNECT, RESOURCE TO ROOT;
diff --git a/sql/tools/oracle/2_create_schema.sh b/sql/tools/oracle/2_create_schema.sh
deleted file mode 100644
index ce7955d..0000000
--- a/sql/tools/oracle/2_create_schema.sh
+++ /dev/null
@@ -1 +0,0 @@
-sqlplus -s ROOT/123456@//localhost/XEPDB1 @/tmp/schema.sql
diff --git a/sql/tools/sqlserver/create_schema.sh b/sql/tools/sqlserver/create_schema.sh
deleted file mode 100644
index 172650b..0000000
--- a/sql/tools/sqlserver/create_schema.sh
+++ /dev/null
@@ -1,5 +0,0 @@
-#!/usr/bin/env bash
-
-/opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P ${SA_PASSWORD} -Q "CREATE DATABASE [ruoyi-vue-pro];
-GO"
-/opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P ${SA_PASSWORD} -d 'ruoyi-vue-pro' -i /tmp/schema.sql
diff --git a/tashow-dependencies/pom.xml b/tashow-dependencies/pom.xml
index c427091..a1f0ce2 100644
--- a/tashow-dependencies/pom.xml
+++ b/tashow-dependencies/pom.xml
@@ -34,6 +34,8 @@
2.3.1
+ 2.7.0
+ 4.6.0
2.4.0
@@ -150,6 +152,11 @@
tashow-data-permission
${revision}
+
+ com.tashow.cloud
+ tashow-sdk-file
+ ${revision}
+
@@ -397,6 +404,22 @@
${spring-boot-admin.version}
+
+
+ com.github.xingfudeshi
+ knife4j-openapi3-jakarta-spring-boot-starter
+ ${knife4j.version}
+
+
+ org.springdoc
+ springdoc-openapi-starter-webmvc-api
+ ${springdoc.version}
+
+
+ com.github.xiaoymin
+ knife4j-gateway-spring-boot-starter
+ 4.5.0
+
org.mockito
diff --git a/tashow-feign/tashow-infra-api/src/main/java/com/tashow/cloud/infraapi/api/file/FileApi.java b/tashow-feign/tashow-infra-api/src/main/java/com/tashow/cloud/infraapi/api/file/FileApi.java
index 2ecf928..cbbcd25 100644
--- a/tashow-feign/tashow-infra-api/src/main/java/com/tashow/cloud/infraapi/api/file/FileApi.java
+++ b/tashow-feign/tashow-infra-api/src/main/java/com/tashow/cloud/infraapi/api/file/FileApi.java
@@ -9,50 +9,54 @@ import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
+/**
+ * RPC 服务 - 文件
+ */
@FeignClient(name = ApiConstants.NAME) // TODO 芋艿:fallbackFactory =
-/** RPC 服务 - 文件 */
public interface FileApi {
- String PREFIX = ApiConstants.PREFIX + "/file";
+ String PREFIX = ApiConstants.PREFIX + "/file";
- /**
- * 保存文件,并返回文件的访问路径
- *
- * @param content 文件内容
- * @return 文件路径
- */
- default String createFile(byte[] content) {
- return createFile(null, null, content);
- }
+ /**
+ * 保存文件,并返回文件的访问路径
+ *
+ * @param content 文件内容
+ * @return 文件路径
+ */
+ default String createFile(byte[] content) {
+ return createFile(null, null, content);
+ }
- /**
- * 保存文件,并返回文件的访问路径
- *
- * @param path 文件路径
- * @param content 文件内容
- * @return 文件路径
- */
- default String createFile(String path, byte[] content) {
- return createFile(null, path, content);
- }
+ /**
+ * 保存文件,并返回文件的访问路径
+ *
+ * @param path 文件路径
+ * @param content 文件内容
+ * @return 文件路径
+ */
+ default String createFile(String path, byte[] content) {
+ return createFile(null, path, content);
+ }
- /**
- * 保存文件,并返回文件的访问路径
- *
- * @param name 原文件名称
- * @param path 文件路径
- * @param content 文件内容
- * @return 文件路径
- */
- default String createFile(
- @RequestParam("name") String name,
- @RequestParam("path") String path,
- @RequestParam("content") byte[] content) {
- return createFile(new FileCreateReqDTO().setName(name).setPath(path).setContent(content))
- .getCheckedData();
- }
+ /**
+ * 保存文件,并返回文件的访问路径
+ *
+ * @param name 原文件名称
+ * @param path 文件路径
+ * @param content 文件内容
+ * @return 文件路径
+ */
+ default String createFile(
+ @RequestParam("name") String name,
+ @RequestParam("path") String path,
+ @RequestParam("content") byte[] content) {
+ return createFile(new FileCreateReqDTO().setName(name).setPath(path).setContent(content))
+ .getCheckedData();
+ }
- @PostMapping(PREFIX + "/create")
- /** 保存文件,并返回文件的访问路径 */
- CommonResult createFile(@Valid @RequestBody FileCreateReqDTO createReqDTO);
+ /**
+ * 保存文件,并返回文件的访问路径
+ */
+ @PostMapping(PREFIX + "/create")
+ CommonResult createFile(@Valid @RequestBody FileCreateReqDTO createReqDTO);
}
diff --git a/tashow-framework/tashow-framework-web/pom.xml b/tashow-framework/tashow-framework-web/pom.xml
index cbe0fa2..0c14595 100644
--- a/tashow-framework/tashow-framework-web/pom.xml
+++ b/tashow-framework/tashow-framework-web/pom.xml
@@ -27,6 +27,15 @@
true
+
+ com.github.xingfudeshi
+ knife4j-openapi3-jakarta-spring-boot-starter
+
+
+ org.springdoc
+ springdoc-openapi-starter-webmvc-api
+
+
org.springframework.boot
diff --git a/tashow-gateway/src/main/resources/application-local.yaml b/tashow-gateway/src/main/resources/application-local.yaml
index 8756703..59b8b16 100644
--- a/tashow-gateway/src/main/resources/application-local.yaml
+++ b/tashow-gateway/src/main/resources/application-local.yaml
@@ -7,10 +7,10 @@ spring:
username: nacos # Nacos 账号
password: nacos # Nacos 密码
discovery: # 【配置中心】配置项
- namespace: 16bd40df-7cc7-4c2c-82c2-6186ade7bb08 # 命名空间。这里使用 dev 开发环境
+ namespace: dev # 命名空间。这里使用 dev 开发环境
group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP
config: # 【注册中心】配置项
- namespace: 16bd40df-7cc7-4c2c-82c2-6186ade7bb08 # 命名空间。这里使用 dev 开发环境
+ namespace: dev # 命名空间。这里使用 dev 开发环境
group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP
# 日志文件配置
diff --git a/tashow-module/pom.xml b/tashow-module/pom.xml
index ffdb6c5..0f3180f 100644
--- a/tashow-module/pom.xml
+++ b/tashow-module/pom.xml
@@ -15,6 +15,7 @@
tashow-module-infra
tashow-module-app
tashow-module-product
+ tashow-module-ai
diff --git a/tashow-module/tashow-module-translate/pom.xml b/tashow-module/tashow-module-ai/pom.xml
similarity index 86%
rename from tashow-module/tashow-module-translate/pom.xml
rename to tashow-module/tashow-module-ai/pom.xml
index 05580eb..d45ca14 100644
--- a/tashow-module/tashow-module-translate/pom.xml
+++ b/tashow-module/tashow-module-ai/pom.xml
@@ -7,7 +7,7 @@
${revision}
- tashow-module-translate
+ tashow-module-ai
jar
@@ -23,6 +23,11 @@
spring-cloud-starter-alibaba-nacos-config
+
+
+ com.tashow.cloud
+ tashow-infra-api
+
com.tashow.cloud
@@ -40,11 +45,6 @@
com.tashow.cloud
tashow-framework-env
-
- com.tashow.cloud
- tashow-infra-api
-
-
com.tashow.cloud
tashow-framework-websocket
@@ -53,6 +53,10 @@
com.tashow.cloud
tashow-data-redis
+
+ com.tashow.cloud
+ tashow-data-excel
+
com.tashow.cloud
tashow-framework-security
@@ -61,5 +65,11 @@
org.springframework.boot
spring-boot-starter-actuator
+
+ com.tashow.cloud
+ tashow-sdk-file
+
+
+
diff --git a/tashow-module/tashow-module-translate/src/main/java/com/tashow/cloud/translate/TranslateServerApplication.java b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/TranslateServerApplication.java
similarity index 92%
rename from tashow-module/tashow-module-translate/src/main/java/com/tashow/cloud/translate/TranslateServerApplication.java
rename to tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/TranslateServerApplication.java
index 8d2c05c..fc775be 100644
--- a/tashow-module/tashow-module-translate/src/main/java/com/tashow/cloud/translate/TranslateServerApplication.java
+++ b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/TranslateServerApplication.java
@@ -1,4 +1,4 @@
-package com.tashow.cloud.translate;
+package com.tashow.cloud.ai;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
diff --git a/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/controller/admin/aisample/AiSampleController.java b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/controller/admin/aisample/AiSampleController.java
new file mode 100644
index 0000000..a99c39d
--- /dev/null
+++ b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/controller/admin/aisample/AiSampleController.java
@@ -0,0 +1,78 @@
+package com.tashow.cloud.ai.controller.admin.aisample;
+
+import com.tashow.cloud.ai.controller.admin.aisample.vo.*;
+import com.tashow.cloud.ai.dal.dataobject.aisample.AiSampleDO;
+import com.tashow.cloud.ai.service.aisample.AiSampleService;
+import com.tashow.cloud.common.pojo.CommonResult;
+import com.tashow.cloud.common.pojo.PageResult;
+import com.tashow.cloud.common.util.object.BeanUtils;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.annotation.Resource;
+import jakarta.validation.Valid;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+import static com.tashow.cloud.common.pojo.CommonResult.success;
+
+@Tag(name = "管理后台 - 样本库")
+@RestController
+@RequestMapping("/ai/sample")
+@Validated
+public class AiSampleController {
+
+ @Resource
+ private AiSampleService aiSampleService;
+
+ @PostMapping("/create")
+ @Operation(summary = "创建样本库-上传文件")
+ @PreAuthorize("@ss.hasPermission('ai:sample:create')")
+ public CommonResult> createAiSample(FileUploadReqVO uploadReqVO) {
+ return success(aiSampleService.createAiSample(uploadReqVO));
+ }
+
+ @PutMapping("/updates")
+ @Operation(summary = "更新样本库")
+ @PreAuthorize("@ss.hasPermission('ai:sample:update')")
+ public CommonResult updateAiSample(@Valid @RequestBody List updateReqVO) {
+ aiSampleService.updateAiSamples(updateReqVO);
+ return success(true);
+ }
+
+ @PutMapping("/relate")
+ @Operation(summary = "添加关联标签")
+ @PreAuthorize("@ss.hasPermission('ai:sample:update')")
+ public CommonResult relate(@Valid @RequestBody AiSampleRelateTagVO relateTagVO) {
+ aiSampleService.relate(relateTagVO);
+ return success(true);
+ }
+
+ @DeleteMapping("/deleteRelate")
+ @Operation(summary = "删除关联标签")
+ @PreAuthorize("@ss.hasPermission('ai:sample:delete')")
+ public CommonResult deleteRelate(@Valid @RequestBody AiSampleRelateTagVO relateTagVO) {
+ aiSampleService.deleteRelate(relateTagVO);
+ return success(true);
+ }
+
+ @DeleteMapping("/delete")
+ @Operation(summary = "删除样本库")
+ @Parameter(name = "id", description = "编号", required = true)
+ @PreAuthorize("@ss.hasPermission('ai:sample:delete')")
+ public CommonResult deleteAiSample(@RequestParam("id") Long id) {
+ aiSampleService.deleteAiSample(id);
+ return success(true);
+ }
+
+ @GetMapping("/page")
+ @Operation(summary = "获得样本库分页")
+ @PreAuthorize("@ss.hasPermission('ai:sample:query')")
+ public CommonResult> getAiSamplePage(@Valid AiSamplePageReqVO pageReqVO) {
+ PageResult pageResult = aiSampleService.getAiSamplePage(pageReqVO);
+ return success(BeanUtils.toBean(pageResult, AiSampleRespVO.class));
+ }
+}
\ No newline at end of file
diff --git a/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/controller/admin/aisample/AiSampleTagController.java b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/controller/admin/aisample/AiSampleTagController.java
new file mode 100644
index 0000000..8281f67
--- /dev/null
+++ b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/controller/admin/aisample/AiSampleTagController.java
@@ -0,0 +1,74 @@
+package com.tashow.cloud.ai.controller.admin.aisample;
+
+import com.tashow.cloud.ai.controller.admin.aisample.vo.AiSampleTagListRespVO;
+import com.tashow.cloud.ai.controller.admin.aisample.vo.AiSampleTagPageReqVO;
+import com.tashow.cloud.ai.controller.admin.aisample.vo.AiSampleTagRespVO;
+import com.tashow.cloud.ai.controller.admin.aisample.vo.AiSampleTagSaveReqVO;
+import com.tashow.cloud.ai.dal.dataobject.aisample.AiSampleTagDO;
+import com.tashow.cloud.ai.service.aisample.AiSampleTagService;
+import com.tashow.cloud.common.pojo.CommonResult;
+import com.tashow.cloud.common.pojo.PageResult;
+import com.tashow.cloud.common.util.object.BeanUtils;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.annotation.Resource;
+import jakarta.validation.Valid;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+import static com.tashow.cloud.common.pojo.CommonResult.success;
+
+
+@Tag(name = "管理后台 - 样本标签库")
+@RestController
+@RequestMapping("/ai/sampleTag")
+@Validated
+public class AiSampleTagController {
+
+ @Resource
+ private AiSampleTagService aiSampleTagService;
+
+ @PostMapping("/create")
+ @Operation(summary = "创建样本标签库")
+ @PreAuthorize("@ss.hasPermission('ai:sampleTag:create')")
+ public CommonResult createAiSampleTag(@Valid @RequestBody AiSampleTagSaveReqVO createReqVO) {
+ return success(aiSampleTagService.createAiSampleTag(createReqVO));
+ }
+
+ @PutMapping("/update")
+ @Operation(summary = "更新样本标签库")
+ @PreAuthorize("@ss.hasPermission('ai:sampleTag:update')")
+ public CommonResult updateAiSampleTag(@Valid @RequestBody AiSampleTagSaveReqVO updateReqVO) {
+ aiSampleTagService.updateAiSampleTag(updateReqVO);
+ return success(true);
+ }
+
+ @DeleteMapping("/delete")
+ @Operation(summary = "删除样本标签库")
+ @Parameter(name = "id", description = "编号", required = true)
+ @PreAuthorize("@ss.hasPermission('ai:sampleTag:delete')")
+ public CommonResult deleteAiSampleTag(@RequestParam("id") Long id) {
+ aiSampleTagService.deleteAiSampleTag(id);
+ return success(true);
+ }
+
+ @GetMapping("/list")
+ @Operation(summary = "获得样本标签库列表")
+ @PreAuthorize("@ss.hasPermission('ai:sampleTag:query')")
+ public CommonResult> getAiSampleTagList() {
+ return success(BeanUtils.toBean(aiSampleTagService.getAiSampleTagList(), AiSampleTagListRespVO.class));
+ }
+
+ @GetMapping("/page")
+ @Operation(summary = "获得样本标签库分页")
+ @PreAuthorize("@ss.hasPermission('ai:sampleTag:query')")
+ public CommonResult> getAiSampleTagPage(@Valid AiSampleTagPageReqVO pageReqVO) {
+ PageResult pageResult = aiSampleTagService.getAiSampleTagPage(pageReqVO);
+ return success(BeanUtils.toBean(pageResult, AiSampleTagRespVO.class));
+ }
+
+}
\ No newline at end of file
diff --git a/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/controller/admin/aisample/AiSampleTagGroupController.java b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/controller/admin/aisample/AiSampleTagGroupController.java
new file mode 100644
index 0000000..1d04f00
--- /dev/null
+++ b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/controller/admin/aisample/AiSampleTagGroupController.java
@@ -0,0 +1,64 @@
+package com.tashow.cloud.ai.controller.admin.aisample;
+
+import com.tashow.cloud.ai.controller.admin.aisample.vo.AiSampleTagGroupRespVO;
+import com.tashow.cloud.ai.controller.admin.aisample.vo.AiSampleTagGroupSaveReqVO;
+import com.tashow.cloud.ai.dal.dataobject.aisample.AiSampleTagGroupDO;
+import com.tashow.cloud.ai.service.aisample.AiSampleTagGroupService;
+import com.tashow.cloud.common.pojo.CommonResult;
+import com.tashow.cloud.common.util.object.BeanUtils;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.annotation.Resource;
+import jakarta.validation.Valid;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+import static com.tashow.cloud.common.pojo.CommonResult.success;
+
+
+@Tag(name = "管理后台 - 样本标签分组库")
+@RestController
+@RequestMapping("/ai/sampleTagGroup")
+@Validated
+public class AiSampleTagGroupController {
+
+ @Resource
+ private AiSampleTagGroupService aiSampleTagGroupService;
+
+ @PostMapping("/create")
+ @Operation(summary = "创建样本标签分组库")
+ @PreAuthorize("@ss.hasPermission('ai:sampleTagGroup:create')")
+ public CommonResult createAiSampleTagGroup(@Valid @RequestBody AiSampleTagGroupSaveReqVO createReqVO) {
+ return success(aiSampleTagGroupService.createAiSampleTagGroup(createReqVO));
+ }
+
+ @PutMapping("/update")
+ @Operation(summary = "更新样本标签分组库")
+ @PreAuthorize("@ss.hasPermission('ai:sampleTagGroup:update')")
+ public CommonResult updateAiSampleTagGroup(@Valid @RequestBody AiSampleTagGroupSaveReqVO updateReqVO) {
+ aiSampleTagGroupService.updateAiSampleTagGroup(updateReqVO);
+ return success(true);
+ }
+
+ @DeleteMapping("/delete")
+ @Operation(summary = "删除样本标签分组库")
+ @Parameter(name = "id", description = "编号", required = true)
+ @PreAuthorize("@ss.hasPermission('ai:sampleTagGroup:delete')")
+ public CommonResult deleteAiSampleTagGroup(@RequestParam("id") Long id) {
+ aiSampleTagGroupService.deleteAiSampleTagGroup(id);
+ return success(true);
+ }
+
+ @GetMapping("/list")
+ @Operation(summary = "获得样本标签分组库列表")
+ @PreAuthorize("@ss.hasPermission('ai:sampleTagGroup:query')")
+ public CommonResult> getAiSampleTagGroupPage() {
+ List aiSampleTagGroupList = aiSampleTagGroupService.getAiSampleTagGroupList();
+ return success(BeanUtils.toBean(aiSampleTagGroupList, AiSampleTagGroupRespVO.class));
+ }
+
+}
\ No newline at end of file
diff --git a/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/controller/admin/aisample/vo/AiSamplePageReqVO.java b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/controller/admin/aisample/vo/AiSamplePageReqVO.java
new file mode 100644
index 0000000..d0459cc
--- /dev/null
+++ b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/controller/admin/aisample/vo/AiSamplePageReqVO.java
@@ -0,0 +1,33 @@
+package com.tashow.cloud.ai.controller.admin.aisample.vo;
+
+import com.tashow.cloud.common.pojo.PageParam;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.time.LocalDateTime;
+
+import static com.tashow.cloud.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+@Schema(description = "管理后台 - 样本库分页 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class AiSamplePageReqVO extends PageParam {
+
+ @Schema(description = "标签id", example = "25839")
+ private Long tagId;
+
+ @Schema(description = "样本名称", example = "张三")
+ private String sampleName;
+
+ @Schema(description = "样本格式", example = "1")
+ private String sampleMineType;
+
+ @Schema(description = "排序", example = "正序:asc,倒序:desc")
+ private String sort;
+
+
+}
\ No newline at end of file
diff --git a/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/controller/admin/aisample/vo/AiSampleRelateTagVO.java b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/controller/admin/aisample/vo/AiSampleRelateTagVO.java
new file mode 100644
index 0000000..cf0d422
--- /dev/null
+++ b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/controller/admin/aisample/vo/AiSampleRelateTagVO.java
@@ -0,0 +1,17 @@
+package com.tashow.cloud.ai.controller.admin.aisample.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.util.List;
+
+@Schema(description = "管理后台 - 样本库新增/修改 Request VO")
+@Data
+public class AiSampleRelateTagVO {
+
+ @Schema(description = "标签id")
+ private Long tagId;
+
+ @Schema(description = "样本ids")
+ private List sampleIds;
+}
\ No newline at end of file
diff --git a/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/controller/admin/aisample/vo/AiSampleRespVO.java b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/controller/admin/aisample/vo/AiSampleRespVO.java
new file mode 100644
index 0000000..5adcaa1
--- /dev/null
+++ b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/controller/admin/aisample/vo/AiSampleRespVO.java
@@ -0,0 +1,45 @@
+package com.tashow.cloud.ai.controller.admin.aisample.vo;
+
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import com.tashow.cloud.ai.dal.dataobject.aisample.AiSampleTagDO;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+import java.util.List;
+
+@Schema(description = "管理后台 - 样本库 Response VO")
+@Data
+@ExcelIgnoreUnannotated
+public class AiSampleRespVO {
+
+ @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "7701")
+ private Long id;
+
+ @Schema(description = "标签列表")
+ private List tags;
+
+ @Schema(description = "样本文件地址")
+ private String sampleFilePath;
+
+ @Schema(description = "样本名称", example = "张三")
+ private String sampleName;
+
+ @Schema(description = "样本时长")
+ private String sampleTime;
+
+ @Schema(description = "样本格式", example = "1")
+ private String sampleMineType;
+
+ @Schema(description = "样本大小")
+ private String sampleSize;
+
+ @Schema(description = "样本注释", example = "随便")
+ private String remark;
+
+ @Schema(description = "创建时间")
+ private LocalDateTime createTime;
+ @Schema(description = "修改时间")
+ private LocalDateTime updateTime;
+
+}
\ No newline at end of file
diff --git a/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/controller/admin/aisample/vo/AiSampleSaveReqVO.java b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/controller/admin/aisample/vo/AiSampleSaveReqVO.java
new file mode 100644
index 0000000..e764e90
--- /dev/null
+++ b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/controller/admin/aisample/vo/AiSampleSaveReqVO.java
@@ -0,0 +1,19 @@
+package com.tashow.cloud.ai.controller.admin.aisample.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+@Schema(description = "管理后台 - 样本库新增/修改 Request VO")
+@Data
+public class AiSampleSaveReqVO {
+
+ @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "7701")
+ private Long id;
+
+ @Schema(description = "样本名称", example = "张三")
+ private String sampleName;
+
+ @Schema(description = "样本注释", example = "随便")
+ private String remark;
+
+}
\ No newline at end of file
diff --git a/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/controller/admin/aisample/vo/AiSampleTagGroupPageReqVO.java b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/controller/admin/aisample/vo/AiSampleTagGroupPageReqVO.java
new file mode 100644
index 0000000..bc14d11
--- /dev/null
+++ b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/controller/admin/aisample/vo/AiSampleTagGroupPageReqVO.java
@@ -0,0 +1,27 @@
+package com.tashow.cloud.ai.controller.admin.aisample.vo;
+
+import com.tashow.cloud.common.pojo.PageParam;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.time.LocalDateTime;
+
+import static com.tashow.cloud.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+@Schema(description = "管理后台 - 样本标签分组库分页 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class AiSampleTagGroupPageReqVO extends PageParam {
+
+ @Schema(description = "分组名称", example = "张三")
+ private String groupName;
+
+ @Schema(description = "创建时间")
+ @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+ private LocalDateTime[] createTime;
+
+}
\ No newline at end of file
diff --git a/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/controller/admin/aisample/vo/AiSampleTagGroupRespVO.java b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/controller/admin/aisample/vo/AiSampleTagGroupRespVO.java
new file mode 100644
index 0000000..5b332fe
--- /dev/null
+++ b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/controller/admin/aisample/vo/AiSampleTagGroupRespVO.java
@@ -0,0 +1,26 @@
+package com.tashow.cloud.ai.controller.admin.aisample.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.*;
+
+import java.time.LocalDateTime;
+import com.alibaba.excel.annotation.*;
+
+@Schema(description = "管理后台 - 样本标签分组库 Response VO")
+@Data
+@ExcelIgnoreUnannotated
+public class AiSampleTagGroupRespVO {
+
+ @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "18784")
+ @ExcelProperty("主键")
+ private Long id;
+
+ @Schema(description = "分组名称", example = "张三")
+ @ExcelProperty("分组名称")
+ private String groupName;
+
+ @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
+ @ExcelProperty("创建时间")
+ private LocalDateTime createTime;
+
+}
\ No newline at end of file
diff --git a/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/controller/admin/aisample/vo/AiSampleTagGroupSaveReqVO.java b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/controller/admin/aisample/vo/AiSampleTagGroupSaveReqVO.java
new file mode 100644
index 0000000..ef4da7a
--- /dev/null
+++ b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/controller/admin/aisample/vo/AiSampleTagGroupSaveReqVO.java
@@ -0,0 +1,16 @@
+package com.tashow.cloud.ai.controller.admin.aisample.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.*;
+
+@Schema(description = "管理后台 - 样本标签分组库新增/修改 Request VO")
+@Data
+public class AiSampleTagGroupSaveReqVO {
+
+ @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "18784")
+ private Long id;
+
+ @Schema(description = "分组名称", example = "张三")
+ private String groupName;
+
+}
\ No newline at end of file
diff --git a/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/controller/admin/aisample/vo/AiSampleTagListRespVO.java b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/controller/admin/aisample/vo/AiSampleTagListRespVO.java
new file mode 100644
index 0000000..47c452a
--- /dev/null
+++ b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/controller/admin/aisample/vo/AiSampleTagListRespVO.java
@@ -0,0 +1,16 @@
+package com.tashow.cloud.ai.controller.admin.aisample.vo;
+
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+@Schema(description = "管理后台 - 样本标签库 Response VO")
+@Data
+@ExcelIgnoreUnannotated
+public class AiSampleTagListRespVO {
+
+ @Schema(description = "标签id")
+ private Long id;
+ @Schema(description = "标签名称")
+ private String tagName;
+}
\ No newline at end of file
diff --git a/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/controller/admin/aisample/vo/AiSampleTagPageReqVO.java b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/controller/admin/aisample/vo/AiSampleTagPageReqVO.java
new file mode 100644
index 0000000..153087b
--- /dev/null
+++ b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/controller/admin/aisample/vo/AiSampleTagPageReqVO.java
@@ -0,0 +1,18 @@
+package com.tashow.cloud.ai.controller.admin.aisample.vo;
+
+import com.tashow.cloud.common.pojo.PageParam;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+
+@Schema(description = "管理后台 - 样本标签库分页 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class AiSampleTagPageReqVO extends PageParam {
+
+ @Schema(description = "分组id", example = "张三")
+ private Long groupId;
+
+}
\ No newline at end of file
diff --git a/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/controller/admin/aisample/vo/AiSampleTagRespVO.java b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/controller/admin/aisample/vo/AiSampleTagRespVO.java
new file mode 100644
index 0000000..db35832
--- /dev/null
+++ b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/controller/admin/aisample/vo/AiSampleTagRespVO.java
@@ -0,0 +1,20 @@
+package com.tashow.cloud.ai.controller.admin.aisample.vo;
+
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import com.tashow.cloud.ai.dal.dataobject.aisample.AiSampleTagDO;
+import com.tashow.cloud.ai.dal.dataobject.aisample.AiSampleTagGroupDO;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.util.List;
+
+@Schema(description = "管理后台 - 样本标签库 Response VO")
+@Data
+@ExcelIgnoreUnannotated
+public class AiSampleTagRespVO {
+
+ @Schema(description = "标签列表")
+ List tags;
+ @Schema(description = "分组列表")
+ List tagGroupDOS;
+}
\ No newline at end of file
diff --git a/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/controller/admin/aisample/vo/AiSampleTagSaveReqVO.java b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/controller/admin/aisample/vo/AiSampleTagSaveReqVO.java
new file mode 100644
index 0000000..4fba8a1
--- /dev/null
+++ b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/controller/admin/aisample/vo/AiSampleTagSaveReqVO.java
@@ -0,0 +1,21 @@
+package com.tashow.cloud.ai.controller.admin.aisample.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.util.List;
+
+@Schema(description = "管理后台 - 样本标签库新增/修改 Request VO")
+@Data
+public class AiSampleTagSaveReqVO {
+
+ @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "32538")
+ private Long id;
+
+ @Schema(description = "分组ids")
+ private List groupIds;
+
+ @Schema(description = "标签名称", example = "张三")
+ private String tagName;
+
+}
\ No newline at end of file
diff --git a/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/controller/admin/aisample/vo/FileUploadReqVO.java b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/controller/admin/aisample/vo/FileUploadReqVO.java
new file mode 100644
index 0000000..233bfca
--- /dev/null
+++ b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/controller/admin/aisample/vo/FileUploadReqVO.java
@@ -0,0 +1,15 @@
+package com.tashow.cloud.ai.controller.admin.aisample.vo;
+
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+import org.springframework.web.multipart.MultipartFile;
+
+/** 管理后台 - 上传文件 Request VO */
+@Data
+public class FileUploadReqVO {
+
+ /** 文件附件 */
+ @NotNull(message = "文件附件不能为空")
+ private MultipartFile[] files;
+
+}
diff --git a/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/controller/admin/package-info.java b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/controller/admin/package-info.java
new file mode 100644
index 0000000..15f00f8
--- /dev/null
+++ b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/controller/admin/package-info.java
@@ -0,0 +1 @@
+package com.tashow.cloud.ai.controller.admin;
\ No newline at end of file
diff --git a/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/controller/app/package-info.java b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/controller/app/package-info.java
new file mode 100644
index 0000000..80d118b
--- /dev/null
+++ b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/controller/app/package-info.java
@@ -0,0 +1 @@
+package com.tashow.cloud.ai.controller.app;
\ No newline at end of file
diff --git a/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/controller/app/translate/TranslateController.java b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/controller/app/translate/TranslateController.java
new file mode 100644
index 0000000..3849fda
--- /dev/null
+++ b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/controller/app/translate/TranslateController.java
@@ -0,0 +1,17 @@
+package com.tashow.cloud.ai.controller.app.translate;
+
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@RequestMapping("/ai/sample")
+@Validated
+@Slf4j
+public class TranslateController {
+
+
+
+}
diff --git a/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/controller/package-info.java b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/controller/package-info.java
new file mode 100644
index 0000000..4a424d2
--- /dev/null
+++ b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/controller/package-info.java
@@ -0,0 +1 @@
+package com.tashow.cloud.ai.controller;
\ No newline at end of file
diff --git a/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/dal/dataobject/aisample/AiSampleDO.java b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/dal/dataobject/aisample/AiSampleDO.java
new file mode 100644
index 0000000..ae22fe3
--- /dev/null
+++ b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/dal/dataobject/aisample/AiSampleDO.java
@@ -0,0 +1,61 @@
+package com.tashow.cloud.ai.dal.dataobject.aisample;
+
+import com.baomidou.mybatisplus.annotation.KeySequence;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.tashow.cloud.mybatis.mybatis.core.dataobject.BaseDO;
+import lombok.*;
+
+import java.util.List;
+
+/**
+ * 样本库 DO
+ *
+ * @author 芋道源码
+ */
+@TableName("tz_ai_sample")
+@KeySequence("tz_ai_sample_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class AiSampleDO extends BaseDO {
+
+ /**
+ * 主键
+ */
+ @TableId
+ private Long id;
+
+ @TableField(exist = false)
+ private List tags;
+
+ /**
+ * 样本文件id
+ */
+ private String sampleFilePath;
+ /**
+ * 样本名称
+ */
+ private String sampleName;
+ /**
+ * 样本时长
+ */
+ private String sampleTime;
+ /**
+ * 样本格式
+ */
+ private String sampleMineType;
+ /**
+ * 样本大小
+ */
+ private Long sampleSize;
+ /**
+ * 样本注释
+ */
+ private String remark;
+
+}
\ No newline at end of file
diff --git a/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/dal/dataobject/aisample/AiSampleTagDO.java b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/dal/dataobject/aisample/AiSampleTagDO.java
new file mode 100644
index 0000000..721a716
--- /dev/null
+++ b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/dal/dataobject/aisample/AiSampleTagDO.java
@@ -0,0 +1,34 @@
+package com.tashow.cloud.ai.dal.dataobject.aisample;
+
+import lombok.*;
+import com.baomidou.mybatisplus.annotation.*;
+import com.tashow.cloud.mybatis.mybatis.core.dataobject.BaseDO;
+
+/**
+ * 样本标签库 DO
+ *
+ * @author 芋道源码
+ */
+@TableName("tz_ai_sample_tag")
+@KeySequence("tz_ai_sample_tag_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class AiSampleTagDO extends BaseDO {
+
+ /**
+ * 主键
+ */
+ @TableId
+ private Long id;
+
+ /**
+ * 标签名称
+ */
+ private String tagName;
+
+
+}
\ No newline at end of file
diff --git a/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/dal/dataobject/aisample/AiSampleTagGroupDO.java b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/dal/dataobject/aisample/AiSampleTagGroupDO.java
new file mode 100644
index 0000000..ecf0b47
--- /dev/null
+++ b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/dal/dataobject/aisample/AiSampleTagGroupDO.java
@@ -0,0 +1,34 @@
+package com.tashow.cloud.ai.dal.dataobject.aisample;
+
+import com.baomidou.mybatisplus.annotation.KeySequence;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.tashow.cloud.mybatis.mybatis.core.dataobject.BaseDO;
+import lombok.*;
+
+/**
+ * 样本标签分组库 DO
+ *
+ * @author 芋道源码
+ */
+@TableName("tz_ai_sample_tag_group")
+@KeySequence("tz_ai_sample_tag_group_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class AiSampleTagGroupDO extends BaseDO {
+
+ /**
+ * 主键
+ */
+ @TableId
+ private Long id;
+ /**
+ * 分组名称
+ */
+ private String groupName;
+
+}
\ No newline at end of file
diff --git a/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/dal/dataobject/aisample/AiSampleTagGroupRelateDO.java b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/dal/dataobject/aisample/AiSampleTagGroupRelateDO.java
new file mode 100644
index 0000000..7a7f5f5
--- /dev/null
+++ b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/dal/dataobject/aisample/AiSampleTagGroupRelateDO.java
@@ -0,0 +1,38 @@
+package com.tashow.cloud.ai.dal.dataobject.aisample;
+
+import com.baomidou.mybatisplus.annotation.KeySequence;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.tashow.cloud.mybatis.mybatis.core.dataobject.BaseDO;
+import lombok.*;
+
+/**
+ * 样本标签-分组关联 DO
+ *
+ * @author 芋道源码
+ */
+@TableName("tz_ai_sample_tag_group_relate")
+@KeySequence("tz_ai_sample_tag_group_relate_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class AiSampleTagGroupRelateDO extends BaseDO {
+
+ /**
+ * 主键
+ */
+ @TableId
+ private Long id;
+ /**
+ * 样本标签id
+ */
+ private Long sampleTagId;
+ /**
+ * 样本标签分组id
+ */
+ private Long sampleTagGroupId;
+
+}
\ No newline at end of file
diff --git a/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/dal/dataobject/aisample/AiSampleTagRelateDO.java b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/dal/dataobject/aisample/AiSampleTagRelateDO.java
new file mode 100644
index 0000000..72bf179
--- /dev/null
+++ b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/dal/dataobject/aisample/AiSampleTagRelateDO.java
@@ -0,0 +1,36 @@
+package com.tashow.cloud.ai.dal.dataobject.aisample;
+
+import lombok.*;
+import com.baomidou.mybatisplus.annotation.*;
+import com.tashow.cloud.mybatis.mybatis.core.dataobject.BaseDO;
+
+/**
+ * 样本-标签关联 DO
+ *
+ * @author 芋道源码
+ */
+@TableName("tz_ai_sample_tag_relate")
+@KeySequence("tz_ai_sample_tag_relate_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class AiSampleTagRelateDO extends BaseDO {
+
+ /**
+ * 主键
+ */
+ @TableId
+ private Long id;
+ /**
+ * 样本id
+ */
+ private Long sampleId;
+ /**
+ * 样本标签id
+ */
+ private Long sampleTagId;
+
+}
\ No newline at end of file
diff --git a/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/dal/dataobject/package-info.java b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/dal/dataobject/package-info.java
new file mode 100644
index 0000000..0a55678
--- /dev/null
+++ b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/dal/dataobject/package-info.java
@@ -0,0 +1,2 @@
+package com.tashow.cloud.ai.dal.dataobject;
+// 数据库对象
\ No newline at end of file
diff --git a/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/dal/mysql/aisample/AiSampleMapper.java b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/dal/mysql/aisample/AiSampleMapper.java
new file mode 100644
index 0000000..082ae0e
--- /dev/null
+++ b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/dal/mysql/aisample/AiSampleMapper.java
@@ -0,0 +1,29 @@
+package com.tashow.cloud.ai.dal.mysql.aisample;
+
+import com.tashow.cloud.ai.controller.admin.aisample.vo.AiSamplePageReqVO;
+import com.tashow.cloud.ai.dal.dataobject.aisample.AiSampleDO;
+import com.tashow.cloud.common.pojo.PageResult;
+import com.tashow.cloud.mybatis.mybatis.core.mapper.BaseMapperX;
+import com.tashow.cloud.mybatis.mybatis.core.query.LambdaQueryWrapperX;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * 样本库 Mapper
+ *
+ * @author 芋道源码
+ */
+@Mapper
+public interface AiSampleMapper extends BaseMapperX {
+
+ default PageResult selectPage(AiSamplePageReqVO reqVO) {
+ return selectPage(reqVO, new LambdaQueryWrapperX()
+ .eqIfPresent(AiSampleDO::getSampleFilePath, reqVO.getSampleFilePath())
+ .likeIfPresent(AiSampleDO::getSampleName, reqVO.getSampleName())
+ .betweenIfPresent(AiSampleDO::getSampleTime, reqVO.getSampleTime())
+ .eqIfPresent(AiSampleDO::getSampleMineType, reqVO.getSampleMineType())
+ .eqIfPresent(AiSampleDO::getSampleSize, reqVO.getSampleSize())
+ .eqIfPresent(AiSampleDO::getRemark, reqVO.getRemark())
+ .betweenIfPresent(AiSampleDO::getCreateTime, reqVO.getCreateTime())
+ .orderByDesc(AiSampleDO::getId));
+ }
+}
\ No newline at end of file
diff --git a/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/dal/mysql/aisample/AiSampleTagGroupMapper.java b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/dal/mysql/aisample/AiSampleTagGroupMapper.java
new file mode 100644
index 0000000..9f0404a
--- /dev/null
+++ b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/dal/mysql/aisample/AiSampleTagGroupMapper.java
@@ -0,0 +1,25 @@
+package com.tashow.cloud.ai.dal.mysql.aisample;
+
+import com.tashow.cloud.ai.controller.admin.aisample.vo.AiSampleTagGroupPageReqVO;
+import com.tashow.cloud.ai.dal.dataobject.aisample.AiSampleTagGroupDO;
+import com.tashow.cloud.common.pojo.PageResult;
+import com.tashow.cloud.mybatis.mybatis.core.mapper.BaseMapperX;
+import com.tashow.cloud.mybatis.mybatis.core.query.LambdaQueryWrapperX;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * 样本标签分组库 Mapper
+ *
+ * @author 芋道源码
+ */
+@Mapper
+public interface AiSampleTagGroupMapper extends BaseMapperX {
+
+ default PageResult selectPage(AiSampleTagGroupPageReqVO reqVO) {
+ return selectPage(reqVO, new LambdaQueryWrapperX()
+ .likeIfPresent(AiSampleTagGroupDO::getGroupName, reqVO.getGroupName())
+ .betweenIfPresent(AiSampleTagGroupDO::getCreateTime, reqVO.getCreateTime())
+ .orderByDesc(AiSampleTagGroupDO::getId));
+ }
+
+}
\ No newline at end of file
diff --git a/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/dal/mysql/aisample/AiSampleTagGroupRelateMapper.java b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/dal/mysql/aisample/AiSampleTagGroupRelateMapper.java
new file mode 100644
index 0000000..cdf2216
--- /dev/null
+++ b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/dal/mysql/aisample/AiSampleTagGroupRelateMapper.java
@@ -0,0 +1,15 @@
+package com.tashow.cloud.ai.dal.mysql.aisample;
+
+import com.tashow.cloud.ai.dal.dataobject.aisample.AiSampleTagGroupRelateDO;
+import com.tashow.cloud.mybatis.mybatis.core.mapper.BaseMapperX;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * 样本标签-分组关联 Mapper
+ *
+ * @author 芋道源码
+ */
+@Mapper
+public interface AiSampleTagGroupRelateMapper extends BaseMapperX {
+
+}
\ No newline at end of file
diff --git a/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/dal/mysql/aisample/AiSampleTagMapper.java b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/dal/mysql/aisample/AiSampleTagMapper.java
new file mode 100644
index 0000000..98fa0de
--- /dev/null
+++ b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/dal/mysql/aisample/AiSampleTagMapper.java
@@ -0,0 +1,32 @@
+package com.tashow.cloud.ai.dal.mysql.aisample;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.tashow.cloud.ai.controller.admin.aisample.vo.AiSampleTagPageReqVO;
+import com.tashow.cloud.ai.dal.dataobject.aisample.AiSampleTagDO;
+import com.tashow.cloud.common.pojo.PageResult;
+import com.tashow.cloud.mybatis.mybatis.core.mapper.BaseMapperX;
+import com.tashow.cloud.mybatis.mybatis.core.query.LambdaQueryWrapperX;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Select;
+
+/**
+ * 样本标签库 Mapper
+ *
+ * @author 芋道源码
+ */
+@Mapper
+public interface AiSampleTagMapper extends BaseMapperX {
+
+ default PageResult selectPage(AiSampleTagPageReqVO reqVO) {
+ return selectPage(reqVO, new LambdaQueryWrapperX()
+ .likeIfPresent(AiSampleTagDO::getTagName, reqVO.getTagName())
+ .betweenIfPresent(AiSampleTagDO::getCreateTime, reqVO.getCreateTime())
+ .orderByDesc(AiSampleTagDO::getId));
+ }
+
+ @Select("SELECT t.* FROM tz_ai_sample_tag t INNER JOIN tz_ai_sample_tag_group_relate r ON t.id = r.sample_tag_id \n" +
+ " WHERE r.sample_tag_group_id = #{groupId} ")
+ IPage getAiSampleTagPage(Page page, AiSampleTagPageReqVO pageReqVO);
+
+}
\ No newline at end of file
diff --git a/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/dal/mysql/aisample/AiSampleTagRelateMapper.java b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/dal/mysql/aisample/AiSampleTagRelateMapper.java
new file mode 100644
index 0000000..90e0336
--- /dev/null
+++ b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/dal/mysql/aisample/AiSampleTagRelateMapper.java
@@ -0,0 +1,16 @@
+package com.tashow.cloud.ai.dal.mysql.aisample;
+
+import com.tashow.cloud.ai.dal.dataobject.aisample.AiSampleTagRelateDO;
+import com.tashow.cloud.mybatis.mybatis.core.mapper.BaseMapperX;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * 样本-标签关联 Mapper
+ *
+ * @author 芋道源码
+ */
+@Mapper
+public interface AiSampleTagRelateMapper extends BaseMapperX {
+
+
+}
\ No newline at end of file
diff --git a/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/dal/mysql/package-info.java b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/dal/mysql/package-info.java
new file mode 100644
index 0000000..dc66f15
--- /dev/null
+++ b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/dal/mysql/package-info.java
@@ -0,0 +1 @@
+package com.tashow.cloud.ai.dal.mysql;
\ No newline at end of file
diff --git a/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/dal/package-info.java b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/dal/package-info.java
new file mode 100644
index 0000000..91dc35a
--- /dev/null
+++ b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/dal/package-info.java
@@ -0,0 +1 @@
+package com.tashow.cloud.ai.dal;
\ No newline at end of file
diff --git a/tashow-module/tashow-module-translate/src/main/java/com/tashow/cloud/translate/security/config/SecurityConfiguration.java b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/security/config/SecurityConfiguration.java
similarity index 97%
rename from tashow-module/tashow-module-translate/src/main/java/com/tashow/cloud/translate/security/config/SecurityConfiguration.java
rename to tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/security/config/SecurityConfiguration.java
index 006dcbe..eb8b20d 100644
--- a/tashow-module/tashow-module-translate/src/main/java/com/tashow/cloud/translate/security/config/SecurityConfiguration.java
+++ b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/security/config/SecurityConfiguration.java
@@ -1,4 +1,4 @@
-package com.tashow.cloud.translate.security.config;
+package com.tashow.cloud.ai.security.config;
import com.tashow.cloud.infraapi.enums.ApiConstants;
import com.tashow.cloud.security.security.config.AuthorizeRequestsCustomizer;
diff --git a/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/security/core/package-info.java b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/security/core/package-info.java
new file mode 100644
index 0000000..66da3e4
--- /dev/null
+++ b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/security/core/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * 占位
+ */
+package com.tashow.cloud.ai.security.core;
diff --git a/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/service/aisample/AiSampleService.java b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/service/aisample/AiSampleService.java
new file mode 100644
index 0000000..c2f788e
--- /dev/null
+++ b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/service/aisample/AiSampleService.java
@@ -0,0 +1,73 @@
+package com.tashow.cloud.ai.service.aisample;
+
+import com.tashow.cloud.ai.controller.admin.aisample.vo.*;
+import com.tashow.cloud.ai.dal.dataobject.aisample.AiSampleDO;
+import com.tashow.cloud.common.pojo.PageResult;
+import jakarta.validation.Valid;
+
+import java.util.List;
+
+/**
+ * 样本库 Service 接口
+ *
+ * @author 芋道源码
+ */
+public interface AiSampleService {
+
+ /**
+ * 创建样本库
+ *
+ * @param createReqVO 创建信息
+ * @return 编号
+ */
+ List createAiSample(@Valid FileUploadReqVO createReqVO);
+
+ /**
+ * 更新样本库
+ *
+ * @param updateReqVO 更新信息
+ */
+ void updateAiSample(@Valid AiSampleSaveReqVO updateReqVO);
+
+ /**
+ * 批量更新
+ * @param updateReqVO
+ */
+ void updateAiSamples(@Valid List updateReqVO);
+
+ /**
+ * 关联标签
+ * @param relateTagVO
+ */
+ void relate(@Valid AiSampleRelateTagVO relateTagVO);
+ /**
+ * 删除样本库
+ *
+ * @param id 编号
+ */
+ void deleteAiSample(Long id);
+
+ /**
+ * 删除样本库
+ * @param relateTagVO 编号
+ */
+ void deleteRelate(AiSampleRelateTagVO relateTagVO);
+
+ /**
+ * 获得样本库
+ *
+ * @param id 编号
+ * @return 样本库
+ */
+ AiSampleDO getAiSample(Long id);
+
+ /**
+ * 获得样本库分页
+ *
+ * @param pageReqVO 分页查询
+ * @return 样本库分页
+ */
+ PageResult getAiSamplePage(AiSamplePageReqVO pageReqVO);
+
+
+}
\ No newline at end of file
diff --git a/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/service/aisample/AiSampleServiceImpl.java b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/service/aisample/AiSampleServiceImpl.java
new file mode 100644
index 0000000..de8739a
--- /dev/null
+++ b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/service/aisample/AiSampleServiceImpl.java
@@ -0,0 +1,156 @@
+package com.tashow.cloud.ai.service.aisample;
+
+import cn.hutool.core.util.ArrayUtil;
+import cn.hutool.core.util.ObjectUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.tashow.cloud.ai.controller.admin.aisample.vo.AiSamplePageReqVO;
+import com.tashow.cloud.ai.controller.admin.aisample.vo.AiSampleRelateTagVO;
+import com.tashow.cloud.ai.controller.admin.aisample.vo.AiSampleSaveReqVO;
+import com.tashow.cloud.ai.controller.admin.aisample.vo.FileUploadReqVO;
+import com.tashow.cloud.ai.dal.dataobject.aisample.AiSampleDO;
+import com.tashow.cloud.ai.dal.dataobject.aisample.AiSampleTagDO;
+import com.tashow.cloud.ai.dal.dataobject.aisample.AiSampleTagRelateDO;
+import com.tashow.cloud.ai.dal.mysql.aisample.AiSampleMapper;
+import com.tashow.cloud.ai.dal.mysql.aisample.AiSampleTagMapper;
+import com.tashow.cloud.ai.dal.mysql.aisample.AiSampleTagRelateMapper;
+import com.tashow.cloud.common.pojo.PageResult;
+import com.tashow.cloud.common.util.object.BeanUtils;
+import com.tashow.cloud.infraapi.api.file.FileApi;
+import jakarta.annotation.Resource;
+import lombok.SneakyThrows;
+import org.springframework.stereotype.Service;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 样本库 Service 实现类
+ *
+ * @author 芋道源码
+ */
+@Service
+@Validated
+public class AiSampleServiceImpl implements AiSampleService {
+
+ @Resource
+ private AiSampleMapper aiSampleMapper;
+ @Resource
+ private AiSampleTagMapper aiSampleTagMapper;
+ @Resource
+ private AiSampleTagRelateMapper aiSampleTagRelateMapper;
+ @Resource
+ private FileApi fileApi;
+
+ @Override
+ @SneakyThrows
+ public List createAiSample(FileUploadReqVO uploadReqVO) {
+ //返回图片路径
+ List urls = new ArrayList<>();
+ /* 调用文件上传服务*/
+ for (MultipartFile file : uploadReqVO.getFiles()) {
+ //返回上传结果
+ String file1 ="http://192.168.1.231:48080"+ fileApi.createFile(file.getBytes());
+ //保存样本信息
+ AiSampleDO aiSampleDO = new AiSampleDO();
+ aiSampleDO.setSampleFilePath(file1);
+ aiSampleDO.setSampleName(file.getOriginalFilename());
+ aiSampleDO.setSampleMineType(file.getContentType());
+ aiSampleDO.setSampleSize(file.getSize());
+ aiSampleMapper.insert(aiSampleDO);
+ urls.add(file1);
+ }
+ // 返回
+ return urls;
+ }
+
+ @Override
+ public void updateAiSample(AiSampleSaveReqVO updateReqVO) {
+ // 校验存在
+ validateAiSampleExists(updateReqVO.getId());
+ // 更新
+ AiSampleDO updateObj = BeanUtils.toBean(updateReqVO, AiSampleDO.class);
+ aiSampleMapper.updateById(updateObj);
+ }
+
+ @Override
+ public void updateAiSamples(List updateReqVO) {
+ aiSampleMapper.updateBatch( BeanUtils.toBean(updateReqVO, AiSampleDO.class));
+ }
+
+ @Override
+ public void relate(AiSampleRelateTagVO relateTagVO) {
+ List tagRelateDOS = new ArrayList<>();
+ for (Long sampleId : relateTagVO.getSampleIds()) {
+ AiSampleTagRelateDO relateDO = new AiSampleTagRelateDO();
+ relateDO.setSampleId(sampleId);
+ relateDO.setSampleTagId(relateTagVO.getTagId());
+ tagRelateDOS.add(relateDO);
+ }
+ aiSampleTagRelateMapper.insertBatch(tagRelateDOS);
+ }
+
+ @Override
+ public void deleteRelate(AiSampleRelateTagVO relateTagVO) {
+ List tagRelateIds = new ArrayList<>();
+ for (Long sampleId : relateTagVO.getSampleIds()) {
+ AiSampleTagRelateDO relateDO = aiSampleTagRelateMapper.selectOne(
+ new LambdaQueryWrapper()
+ .eq(AiSampleTagRelateDO::getSampleId, sampleId)
+ .eq(AiSampleTagRelateDO::getSampleTagId, relateTagVO.getTagId())
+ );
+ tagRelateIds.add(relateDO.getId());
+ }
+ aiSampleTagRelateMapper.deleteBatchIds(tagRelateIds);
+ }
+
+ @Override
+ public void deleteAiSample(Long id) {
+ // 校验存在
+ validateAiSampleExists(id);
+ // 删除
+ aiSampleMapper.deleteById(id);
+ }
+
+ private void validateAiSampleExists(Long id) {
+ if (aiSampleMapper.selectById(id) == null) {
+// throw exception(AI_SAMPLE_NOT_EXISTS);
+ }
+ }
+
+ @Override
+ public AiSampleDO getAiSample(Long id) {
+ AiSampleDO aiSampleDO = aiSampleMapper.selectById(id);
+ aiSampleDO.setSampleFilePath("http://192.168.1.231:48080"+aiSampleDO.getSampleFilePath());
+ //先获取关联的标签id
+ List tagRelateDOS = aiSampleTagRelateMapper.selectList(new LambdaQueryWrapper().eq(AiSampleTagRelateDO::getSampleId, id));
+ List tagIds = tagRelateDOS.stream().map(AiSampleTagRelateDO::getSampleTagId).toList();
+ aiSampleDO.setTags(aiSampleTagMapper.selectList(new LambdaQueryWrapper().in(AiSampleTagDO::getId,tagIds)));
+ return aiSampleDO;
+ }
+
+ @Override
+ public PageResult getAiSamplePage(AiSamplePageReqVO pageReqVO) {
+ PageResult aiSampleDOPageResult = aiSampleMapper.selectPage(pageReqVO);
+ //根据样本id获取关联的标签id
+ List sampleIds = aiSampleDOPageResult.getList().stream().map(AiSampleDO::getId).toList();
+ List tagRelateDOS = aiSampleTagRelateMapper.selectList(new LambdaQueryWrapper().in(AiSampleTagRelateDO::getSampleId, sampleIds));
+ List tagIds = tagRelateDOS.stream().map(AiSampleTagRelateDO::getSampleTagId).toList();
+ //获取标签信息
+ List aiSampleTagDOS = aiSampleTagMapper.selectList(new LambdaQueryWrapper().in(AiSampleTagDO::getId, tagIds));
+
+ //封装标签信息
+ for (AiSampleDO aiSampleDO : aiSampleDOPageResult.getList()) {
+ List list = tagRelateDOS.stream()
+ .filter(a -> ObjectUtil.equals(aiSampleDO.getId(), a.getSampleId()))
+ .toList();
+ Object[] tagsId = list.stream().map(AiSampleTagRelateDO::getSampleTagId).toArray();
+ List list1 = aiSampleTagDOS.stream().filter(a -> ArrayUtil.containsAny(tagsId, a.getId())).toList();
+ aiSampleDO.setTags(list1);
+ aiSampleDO.setSampleFilePath("http://192.168.1.231:48080"+aiSampleDO.getSampleFilePath());
+ }
+ return aiSampleDOPageResult;
+ }
+
+}
\ No newline at end of file
diff --git a/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/service/aisample/AiSampleTagGroupRelateService.java b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/service/aisample/AiSampleTagGroupRelateService.java
new file mode 100644
index 0000000..82081a0
--- /dev/null
+++ b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/service/aisample/AiSampleTagGroupRelateService.java
@@ -0,0 +1,11 @@
+package com.tashow.cloud.ai.service.aisample;
+
+/**
+ * 样本标签-分组关联 Service 接口
+ *
+ * @author 芋道源码
+ */
+public interface AiSampleTagGroupRelateService {
+
+
+}
\ No newline at end of file
diff --git a/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/service/aisample/AiSampleTagGroupRelateServiceImpl.java b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/service/aisample/AiSampleTagGroupRelateServiceImpl.java
new file mode 100644
index 0000000..4b88f1e
--- /dev/null
+++ b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/service/aisample/AiSampleTagGroupRelateServiceImpl.java
@@ -0,0 +1,16 @@
+package com.tashow.cloud.ai.service.aisample;
+
+import org.springframework.stereotype.Service;
+import org.springframework.validation.annotation.Validated;
+
+/**
+ * 样本标签-分组关联 Service 实现类
+ *
+ * @author 芋道源码
+ */
+@Service
+@Validated
+public class AiSampleTagGroupRelateServiceImpl implements AiSampleTagGroupRelateService {
+
+
+}
\ No newline at end of file
diff --git a/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/service/aisample/AiSampleTagGroupService.java b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/service/aisample/AiSampleTagGroupService.java
new file mode 100644
index 0000000..fa37ae6
--- /dev/null
+++ b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/service/aisample/AiSampleTagGroupService.java
@@ -0,0 +1,62 @@
+package com.tashow.cloud.ai.service.aisample;
+
+import com.tashow.cloud.ai.controller.admin.aisample.vo.AiSampleTagGroupPageReqVO;
+import com.tashow.cloud.ai.controller.admin.aisample.vo.AiSampleTagGroupRespVO;
+import com.tashow.cloud.ai.controller.admin.aisample.vo.AiSampleTagGroupSaveReqVO;
+import com.tashow.cloud.ai.dal.dataobject.aisample.AiSampleTagGroupDO;
+import com.tashow.cloud.common.pojo.PageResult;
+import jakarta.validation.Valid;
+
+import java.util.List;
+
+/**
+ * 样本标签分组库 Service 接口
+ *
+ * @author 芋道源码
+ */
+public interface AiSampleTagGroupService {
+
+ /**
+ * 创建样本标签分组库
+ *
+ * @param createReqVO 创建信息
+ * @return 编号
+ */
+ Long createAiSampleTagGroup(@Valid AiSampleTagGroupSaveReqVO createReqVO);
+
+ /**
+ * 更新样本标签分组库
+ *
+ * @param updateReqVO 更新信息
+ */
+ void updateAiSampleTagGroup(@Valid AiSampleTagGroupSaveReqVO updateReqVO);
+
+ /**
+ * 删除样本标签分组库
+ *
+ * @param id 编号
+ */
+ void deleteAiSampleTagGroup(Long id);
+
+ /**
+ * 获得样本标签分组库
+ *
+ * @param id 编号
+ * @return 样本标签分组库
+ */
+ AiSampleTagGroupDO getAiSampleTagGroup(Long id);
+
+ /**
+ * 获得样本标签分组库分页
+ *
+ * @param pageReqVO 分页查询
+ * @return 样本标签分组库分页
+ */
+ PageResult getAiSampleTagGroupPage(AiSampleTagGroupPageReqVO pageReqVO);
+
+ /**
+ * 获取标签分组列表
+ * @return
+ */
+ List getAiSampleTagGroupList();
+}
\ No newline at end of file
diff --git a/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/service/aisample/AiSampleTagGroupServiceImpl.java b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/service/aisample/AiSampleTagGroupServiceImpl.java
new file mode 100644
index 0000000..21ee295
--- /dev/null
+++ b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/service/aisample/AiSampleTagGroupServiceImpl.java
@@ -0,0 +1,74 @@
+package com.tashow.cloud.ai.service.aisample;
+
+import com.tashow.cloud.ai.controller.admin.aisample.vo.AiSampleTagGroupPageReqVO;
+import com.tashow.cloud.ai.controller.admin.aisample.vo.AiSampleTagGroupRespVO;
+import com.tashow.cloud.ai.controller.admin.aisample.vo.AiSampleTagGroupSaveReqVO;
+import com.tashow.cloud.ai.dal.dataobject.aisample.AiSampleTagGroupDO;
+import com.tashow.cloud.ai.dal.mysql.aisample.AiSampleTagGroupMapper;
+import com.tashow.cloud.common.pojo.PageResult;
+import com.tashow.cloud.common.util.object.BeanUtils;
+import jakarta.annotation.Resource;
+import org.springframework.stereotype.Service;
+import org.springframework.validation.annotation.Validated;
+
+import java.util.List;
+
+/**
+ * 样本标签分组库 Service 实现类
+ *
+ * @author 芋道源码
+ */
+@Service
+@Validated
+public class AiSampleTagGroupServiceImpl implements AiSampleTagGroupService {
+
+ @Resource
+ private AiSampleTagGroupMapper aiSampleTagGroupMapper;
+
+ @Override
+ public Long createAiSampleTagGroup(AiSampleTagGroupSaveReqVO createReqVO) {
+ // 插入
+ AiSampleTagGroupDO aiSampleTagGroup = BeanUtils.toBean(createReqVO, AiSampleTagGroupDO.class);
+ aiSampleTagGroupMapper.insert(aiSampleTagGroup);
+ // 返回
+ return aiSampleTagGroup.getId();
+ }
+
+ @Override
+ public void updateAiSampleTagGroup(AiSampleTagGroupSaveReqVO updateReqVO) {
+ // 校验存在
+ validateAiSampleTagGroupExists(updateReqVO.getId());
+ // 更新
+ AiSampleTagGroupDO updateObj = BeanUtils.toBean(updateReqVO, AiSampleTagGroupDO.class);
+ aiSampleTagGroupMapper.updateById(updateObj);
+ }
+
+ @Override
+ public void deleteAiSampleTagGroup(Long id) {
+ // 校验存在
+ validateAiSampleTagGroupExists(id);
+ // 删除
+ aiSampleTagGroupMapper.deleteById(id);
+ }
+
+ private void validateAiSampleTagGroupExists(Long id) {
+ if (aiSampleTagGroupMapper.selectById(id) == null) {
+// throw exception(AI_SAMPLE_TAG_GROUP_NOT_EXISTS);
+ }
+ }
+
+ @Override
+ public AiSampleTagGroupDO getAiSampleTagGroup(Long id) {
+ return aiSampleTagGroupMapper.selectById(id);
+ }
+
+ @Override
+ public PageResult getAiSampleTagGroupPage(AiSampleTagGroupPageReqVO pageReqVO) {
+ return aiSampleTagGroupMapper.selectPage(pageReqVO);
+ }
+
+ @Override
+ public List getAiSampleTagGroupList() {
+ return aiSampleTagGroupMapper.selectList();
+ }
+}
\ No newline at end of file
diff --git a/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/service/aisample/AiSampleTagRelateService.java b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/service/aisample/AiSampleTagRelateService.java
new file mode 100644
index 0000000..d0432d0
--- /dev/null
+++ b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/service/aisample/AiSampleTagRelateService.java
@@ -0,0 +1,11 @@
+package com.tashow.cloud.ai.service.aisample;
+
+/**
+ * 样本-标签关联 Service 接口
+ *
+ * @author 芋道源码
+ */
+public interface AiSampleTagRelateService {
+
+
+}
\ No newline at end of file
diff --git a/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/service/aisample/AiSampleTagRelateServiceImpl.java b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/service/aisample/AiSampleTagRelateServiceImpl.java
new file mode 100644
index 0000000..29f7360
--- /dev/null
+++ b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/service/aisample/AiSampleTagRelateServiceImpl.java
@@ -0,0 +1,16 @@
+package com.tashow.cloud.ai.service.aisample;
+
+import org.springframework.stereotype.Service;
+import org.springframework.validation.annotation.Validated;
+
+/**
+ * 样本-标签关联 Service 实现类
+ *
+ * @author 芋道源码
+ */
+@Service
+@Validated
+public class AiSampleTagRelateServiceImpl implements AiSampleTagRelateService {
+
+
+}
\ No newline at end of file
diff --git a/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/service/aisample/AiSampleTagService.java b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/service/aisample/AiSampleTagService.java
new file mode 100644
index 0000000..2e2a48c
--- /dev/null
+++ b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/service/aisample/AiSampleTagService.java
@@ -0,0 +1,61 @@
+package com.tashow.cloud.ai.service.aisample;
+
+import com.tashow.cloud.ai.controller.admin.aisample.vo.AiSampleTagPageReqVO;
+import com.tashow.cloud.ai.controller.admin.aisample.vo.AiSampleTagSaveReqVO;
+import com.tashow.cloud.ai.dal.dataobject.aisample.AiSampleTagDO;
+import com.tashow.cloud.common.pojo.PageResult;
+import jakarta.validation.Valid;
+
+import java.util.List;
+
+/**
+ * 样本标签库 Service 接口
+ *
+ * @author 芋道源码
+ */
+public interface AiSampleTagService {
+
+ /**
+ * 创建样本标签库
+ *
+ * @param createReqVO 创建信息
+ * @return 编号
+ */
+ Long createAiSampleTag(@Valid AiSampleTagSaveReqVO createReqVO);
+
+ /**
+ * 更新样本标签库
+ *
+ * @param updateReqVO 更新信息
+ */
+ void updateAiSampleTag(@Valid AiSampleTagSaveReqVO updateReqVO);
+
+ /**
+ * 删除样本标签库
+ *
+ * @param id 编号
+ */
+ void deleteAiSampleTag(Long id);
+
+ /**
+ * 获得样本标签库
+ *
+ * @param id 编号
+ * @return 样本标签库
+ */
+ AiSampleTagDO getAiSampleTag(Long id);
+
+ /**
+ * 获得样本标签库分页
+ *
+ * @param pageReqVO 分页查询
+ * @return 样本标签库分页
+ */
+ PageResult getAiSampleTagPage(AiSampleTagPageReqVO pageReqVO);
+
+ /**
+ * 获取样本标签列表
+ * @return
+ */
+ List getAiSampleTagList();
+}
\ No newline at end of file
diff --git a/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/service/aisample/AiSampleTagServiceImpl.java b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/service/aisample/AiSampleTagServiceImpl.java
new file mode 100644
index 0000000..d36eece
--- /dev/null
+++ b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/service/aisample/AiSampleTagServiceImpl.java
@@ -0,0 +1,102 @@
+package com.tashow.cloud.ai.service.aisample;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.tashow.cloud.ai.controller.admin.aisample.vo.AiSampleTagPageReqVO;
+import com.tashow.cloud.ai.controller.admin.aisample.vo.AiSampleTagSaveReqVO;
+import com.tashow.cloud.ai.dal.dataobject.aisample.AiSampleTagDO;
+import com.tashow.cloud.ai.dal.dataobject.aisample.AiSampleTagGroupRelateDO;
+import com.tashow.cloud.ai.dal.mysql.aisample.AiSampleTagGroupRelateMapper;
+import com.tashow.cloud.ai.dal.mysql.aisample.AiSampleTagMapper;
+import com.tashow.cloud.common.pojo.PageResult;
+import com.tashow.cloud.common.util.object.BeanUtils;
+import com.tashow.cloud.mybatis.mybatis.core.util.MyBatisUtils;
+import jakarta.annotation.Resource;
+import org.springframework.stereotype.Service;
+import org.springframework.validation.annotation.Validated;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 样本标签库 Service 实现类
+ *
+ * @author 芋道源码
+ */
+@Service
+@Validated
+public class AiSampleTagServiceImpl implements AiSampleTagService {
+
+ @Resource
+ private AiSampleTagMapper aiSampleTagMapper;
+ @Resource
+ private AiSampleTagGroupRelateMapper tagGroupRelateMapper;
+
+ @Override
+ public Long createAiSampleTag(AiSampleTagSaveReqVO createReqVO) {
+ // 插入
+ AiSampleTagDO aiSampleTag = BeanUtils.toBean(createReqVO, AiSampleTagDO.class);
+ aiSampleTagMapper.insert(aiSampleTag);
+ //插入关联
+ List tagGroupRelateDOS = new ArrayList<>();
+ for (Long groupId : createReqVO.getGroupIds()) {
+ AiSampleTagGroupRelateDO tagGroupRelateDO = new AiSampleTagGroupRelateDO();
+ tagGroupRelateDO.setSampleTagId(createReqVO.getId());
+ tagGroupRelateDO.setSampleTagGroupId(groupId);
+ tagGroupRelateDOS.add(tagGroupRelateDO);
+ }
+ tagGroupRelateMapper.insertBatch(tagGroupRelateDOS);
+ // 返回
+ return aiSampleTag.getId();
+ }
+
+ @Override
+ public void updateAiSampleTag(AiSampleTagSaveReqVO updateReqVO) {
+ // 校验存在
+ validateAiSampleTagExists(updateReqVO.getId());
+ // 更新
+ AiSampleTagDO updateObj = BeanUtils.toBean(updateReqVO, AiSampleTagDO.class);
+ aiSampleTagMapper.updateById(updateObj);
+ //删除所有关联
+ tagGroupRelateMapper.delete(new LambdaQueryWrapper().eq(AiSampleTagGroupRelateDO::getSampleTagId, updateReqVO.getId()));
+ //插入关联
+ List tagGroupRelateDOS = new ArrayList<>();
+ for (Long groupId : updateReqVO.getGroupIds()) {
+ AiSampleTagGroupRelateDO tagGroupRelateDO = new AiSampleTagGroupRelateDO();
+ tagGroupRelateDO.setSampleTagId(updateReqVO.getId());
+ tagGroupRelateDO.setSampleTagGroupId(groupId);
+ tagGroupRelateDOS.add(tagGroupRelateDO);
+ }
+ tagGroupRelateMapper.insertBatch(tagGroupRelateDOS);
+ }
+
+ @Override
+ public void deleteAiSampleTag(Long id) {
+ // 校验存在
+ validateAiSampleTagExists(id);
+ // 删除
+ aiSampleTagMapper.deleteById(id);
+ }
+
+ private void validateAiSampleTagExists(Long id) {
+ if (aiSampleTagMapper.selectById(id) == null) {
+// throw exception(AI_SAMPLE_TAG_NOT_EXISTS);
+ }
+ }
+
+ @Override
+ public AiSampleTagDO getAiSampleTag(Long id) {
+ return aiSampleTagMapper.selectById(id);
+ }
+
+ @Override
+ public PageResult getAiSampleTagPage(AiSampleTagPageReqVO pageReqVO) {
+ IPage prodPageList = aiSampleTagMapper.getAiSampleTagPage(MyBatisUtils.buildPage(pageReqVO),pageReqVO);
+ return new PageResult<>(prodPageList.getRecords(), prodPageList.getTotal());
+ }
+
+ @Override
+ public List getAiSampleTagList() {
+ return aiSampleTagMapper.selectList();
+ }
+}
\ No newline at end of file
diff --git a/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/service/package-info.java b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/service/package-info.java
new file mode 100644
index 0000000..72ec8fd
--- /dev/null
+++ b/tashow-module/tashow-module-ai/src/main/java/com/tashow/cloud/ai/service/package-info.java
@@ -0,0 +1 @@
+package com.tashow.cloud.ai.service;
\ No newline at end of file
diff --git a/tashow-module/tashow-module-translate/src/main/resources/application-local.yaml b/tashow-module/tashow-module-ai/src/main/resources/application-local.yaml
similarity index 74%
rename from tashow-module/tashow-module-translate/src/main/resources/application-local.yaml
rename to tashow-module/tashow-module-ai/src/main/resources/application-local.yaml
index 79777cb..4f2c22e 100644
--- a/tashow-module/tashow-module-translate/src/main/resources/application-local.yaml
+++ b/tashow-module/tashow-module-ai/src/main/resources/application-local.yaml
@@ -7,10 +7,14 @@ spring:
username: nacos # Nacos 账号
password: nacos # Nacos 密码
discovery: # 【配置中心】配置项
- namespace: 5c8b8fe6-9a89-4ae3-975e-ef3bf560ff82 # 命名空间。这里使用 dev 开发环境
+ namespace: dev # 命名空间。这里使用 dev 开发环境
group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP
metadata:
version: 1.0.0 # 服务实例的版本号,可用于灰度发布
config: # 【注册中心】配置项
- namespace: 5c8b8fe6-9a89-4ae3-975e-ef3bf560ff82 # 命名空间。这里使用 dev 开发环境
+ namespace: dev # 命名空间。这里使用 dev 开发环境
group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP
+
+ufop:
+ storage-type: 0
+ local-storage-path: D://test
\ No newline at end of file
diff --git a/tashow-module/tashow-module-translate/src/main/resources/application.yaml b/tashow-module/tashow-module-ai/src/main/resources/application.yaml
similarity index 100%
rename from tashow-module/tashow-module-translate/src/main/resources/application.yaml
rename to tashow-module/tashow-module-ai/src/main/resources/application.yaml
diff --git a/tashow-module/tashow-module-ai/src/main/resources/mapper/demo.xml b/tashow-module/tashow-module-ai/src/main/resources/mapper/demo.xml
new file mode 100644
index 0000000..e69de29
diff --git a/tashow-module/tashow-module-infra/src/main/java/com/tashow/cloud/infra/framework/file/core/client/local/LocalFileClient.java b/tashow-module/tashow-module-infra/src/main/java/com/tashow/cloud/infra/framework/file/core/client/local/LocalFileClient.java
index aa99e0a..422e27a 100644
--- a/tashow-module/tashow-module-infra/src/main/java/com/tashow/cloud/infra/framework/file/core/client/local/LocalFileClient.java
+++ b/tashow-module/tashow-module-infra/src/main/java/com/tashow/cloud/infra/framework/file/core/client/local/LocalFileClient.java
@@ -30,7 +30,7 @@ public class LocalFileClient extends AbstractFileClient {
String filePath = getFilePath(path);
FileUtil.writeBytes(content, filePath);
// 拼接返回路径
- return super.formatFileUrl(config.getDomain(), path);
+ return super.formatFileUrl("", path);
}
@Override
diff --git a/tashow-module/tashow-module-infra/src/main/resources/application-local.yaml b/tashow-module/tashow-module-infra/src/main/resources/application-local.yaml
index 15b2156..a781954 100644
--- a/tashow-module/tashow-module-infra/src/main/resources/application-local.yaml
+++ b/tashow-module/tashow-module-infra/src/main/resources/application-local.yaml
@@ -7,11 +7,11 @@ spring:
username: nacos # Nacos 账号
password: nacos # Nacos 密码
discovery: # 【配置中心】配置项
- namespace: 76667956-2ac2-4e05-906b-4bca4ebcc5f0 # 命名空间。这里使用 dev 开发环境
+ namespace: dev # 命名空间。这里使用 dev 开发环境
group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP
metadata:
version: 1.0.0 # 服务实例的版本号,可用于灰度发布
config: # 【注册中心】配置项
- namespace: 76667956-2ac2-4e05-906b-4bca4ebcc5f0 # 命名空间。这里使用 dev 开发环境
+ namespace: dev # 命名空间。这里使用 dev 开发环境
group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP
diff --git a/tashow-module/tashow-module-system/src/main/resources/application-local.yaml b/tashow-module/tashow-module-system/src/main/resources/application-local.yaml
index a4d2d57..03bada2 100644
--- a/tashow-module/tashow-module-system/src/main/resources/application-local.yaml
+++ b/tashow-module/tashow-module-system/src/main/resources/application-local.yaml
@@ -5,11 +5,11 @@ spring:
username: nacos # Nacos 账号
password: nacos # Nacos 密码
discovery: # 【配置中心】配置项
- namespace: 16bd40df-7cc7-4c2c-82c2-6186ade7bb08 # 命名空间。这里使用 dev 开发环境
+ namespace: dev # 命名空间。这里使用 dev 开发环境
group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP
metadata:
version: 1.0.0 # 服务实例的版本号,可用于灰度发布
config: # 【注册中心】配置项
- namespace: 16bd40df-7cc7-4c2c-82c2-6186ade7bb08 # 命名空间。这里使用 dev 开发环境
+ namespace: dev # 命名空间。这里使用 dev 开发环境
group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP
diff --git a/tashow-module/tashow-module-translate/src/main/java/com/tashow/cloud/translate/controller/package-info.java b/tashow-module/tashow-module-translate/src/main/java/com/tashow/cloud/translate/controller/package-info.java
deleted file mode 100644
index ae958ed..0000000
--- a/tashow-module/tashow-module-translate/src/main/java/com/tashow/cloud/translate/controller/package-info.java
+++ /dev/null
@@ -1 +0,0 @@
-package com.tashow.cloud.translate.controller;
\ No newline at end of file
diff --git a/tashow-module/tashow-module-translate/src/main/java/com/tashow/cloud/translate/dal/dataobject/package-info.java b/tashow-module/tashow-module-translate/src/main/java/com/tashow/cloud/translate/dal/dataobject/package-info.java
deleted file mode 100644
index 0a104a6..0000000
--- a/tashow-module/tashow-module-translate/src/main/java/com/tashow/cloud/translate/dal/dataobject/package-info.java
+++ /dev/null
@@ -1,2 +0,0 @@
-package com.tashow.cloud.translate.dal.dataobject;
-// 数据库对象
\ No newline at end of file
diff --git a/tashow-module/tashow-module-translate/src/main/java/com/tashow/cloud/translate/dal/package-info.java b/tashow-module/tashow-module-translate/src/main/java/com/tashow/cloud/translate/dal/package-info.java
deleted file mode 100644
index 270fb32..0000000
--- a/tashow-module/tashow-module-translate/src/main/java/com/tashow/cloud/translate/dal/package-info.java
+++ /dev/null
@@ -1 +0,0 @@
-package com.tashow.cloud.translate.dal;
\ No newline at end of file
diff --git a/tashow-module/tashow-module-translate/src/main/java/com/tashow/cloud/translate/security/core/package-info.java b/tashow-module/tashow-module-translate/src/main/java/com/tashow/cloud/translate/security/core/package-info.java
deleted file mode 100644
index 1f91ce3..0000000
--- a/tashow-module/tashow-module-translate/src/main/java/com/tashow/cloud/translate/security/core/package-info.java
+++ /dev/null
@@ -1,4 +0,0 @@
-/**
- * 占位
- */
-package com.tashow.cloud.translate.security.core;
diff --git a/tashow-module/tashow-module-translate/src/main/java/com/tashow/cloud/translate/service/feishu/package-info.java b/tashow-module/tashow-module-translate/src/main/java/com/tashow/cloud/translate/service/feishu/package-info.java
deleted file mode 100644
index b53383d..0000000
--- a/tashow-module/tashow-module-translate/src/main/java/com/tashow/cloud/translate/service/feishu/package-info.java
+++ /dev/null
@@ -1 +0,0 @@
-package com.tashow.cloud.translate.service.feishu;
\ No newline at end of file
diff --git a/tashow-module/tashow-module-translate/src/main/java/com/tashow/cloud/translate/service/package-info.java b/tashow-module/tashow-module-translate/src/main/java/com/tashow/cloud/translate/service/package-info.java
deleted file mode 100644
index 591023a..0000000
--- a/tashow-module/tashow-module-translate/src/main/java/com/tashow/cloud/translate/service/package-info.java
+++ /dev/null
@@ -1 +0,0 @@
-package com.tashow.cloud.translate.service;
\ No newline at end of file
diff --git a/tashow-sdk/pom.xml b/tashow-sdk/pom.xml
index 58ee94c..258e341 100644
--- a/tashow-sdk/pom.xml
+++ b/tashow-sdk/pom.xml
@@ -12,6 +12,7 @@
tashow-sdk-payment
+ tashow-sdk-file
tashow-feishu-sdk