init ai api key
This commit is contained in:
0
backend/ai/__init__.py
Normal file
0
backend/ai/__init__.py
Normal file
3
backend/ai/admin.py
Normal file
3
backend/ai/admin.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from django.contrib import admin
|
||||
|
||||
# Register your models here.
|
||||
6
backend/ai/apps.py
Normal file
6
backend/ai/apps.py
Normal file
@@ -0,0 +1,6 @@
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class AiConfig(AppConfig):
|
||||
default_auto_field = 'django.db.models.BigAutoField'
|
||||
name = 'ai'
|
||||
21
backend/ai/choices.py
Normal file
21
backend/ai/choices.py
Normal file
@@ -0,0 +1,21 @@
|
||||
from django.db import models
|
||||
|
||||
|
||||
class PlatformChoices(models.TextChoices):
|
||||
AZURE_OPENAI = 'AzureOpenAI', 'OpenAI 微软'
|
||||
OPENAI = 'OpenAI', 'OpenAI'
|
||||
OLLAMA = 'Ollama', 'Ollama'
|
||||
YIYAN = 'YiYan', '文心一言'
|
||||
XINGHUO = 'XingHuo', '讯飞星火'
|
||||
TONGYI = 'TongYi', '通义千问'
|
||||
STABLE_DIFFUSION = 'StableDiffusion', 'StableDiffusion'
|
||||
MIDJOURNEY = 'Midjourney', 'Midjourney'
|
||||
SUNO = 'Suno', 'Suno'
|
||||
DEEPSEEK = 'DeepSeek', 'DeepSeek'
|
||||
DOUBAO = 'DouBao', '字节豆包'
|
||||
HUNYUAN = 'HunYuan', '腾讯混元'
|
||||
SILICON_FLOW = 'SiliconFlow', '硅基流动'
|
||||
ZHIPU = 'ZhiPu', '智谱'
|
||||
MINIMAX = 'MiniMax', 'MiniMax'
|
||||
MOONSHOT = 'Moonshot', '月之暗灭'
|
||||
BAICHUAN = 'BaiChuan', '百川智能'
|
||||
214
backend/ai/migrations/0001_initial.py
Normal file
214
backend/ai/migrations/0001_initial.py
Normal file
@@ -0,0 +1,214 @@
|
||||
# Generated by Django 5.2.1 on 2025-07-10 03:03
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = []
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name="AIApiKey",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.BigAutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
(
|
||||
"remark",
|
||||
models.CharField(
|
||||
blank=True,
|
||||
db_comment="备注",
|
||||
help_text="备注",
|
||||
max_length=256,
|
||||
null=True,
|
||||
),
|
||||
),
|
||||
(
|
||||
"creator",
|
||||
models.CharField(
|
||||
blank=True,
|
||||
db_comment="创建人",
|
||||
help_text="创建人",
|
||||
max_length=64,
|
||||
null=True,
|
||||
),
|
||||
),
|
||||
(
|
||||
"modifier",
|
||||
models.CharField(
|
||||
blank=True,
|
||||
db_comment="修改人",
|
||||
help_text="修改人",
|
||||
max_length=64,
|
||||
null=True,
|
||||
),
|
||||
),
|
||||
(
|
||||
"update_time",
|
||||
models.DateTimeField(
|
||||
auto_now=True,
|
||||
db_comment="修改时间",
|
||||
help_text="修改时间",
|
||||
null=True,
|
||||
),
|
||||
),
|
||||
(
|
||||
"create_time",
|
||||
models.DateTimeField(
|
||||
auto_now_add=True,
|
||||
db_comment="创建时间",
|
||||
help_text="创建时间",
|
||||
null=True,
|
||||
),
|
||||
),
|
||||
(
|
||||
"is_deleted",
|
||||
models.BooleanField(db_comment="是否软删除", default=False),
|
||||
),
|
||||
("name", models.CharField(db_comment="名称", max_length=255)),
|
||||
("platform", models.CharField(db_comment="平台", max_length=255)),
|
||||
("api_key", models.CharField(db_comment="密钥", max_length=255)),
|
||||
(
|
||||
"url",
|
||||
models.CharField(
|
||||
blank=True,
|
||||
db_comment="自定义 API 地址",
|
||||
max_length=255,
|
||||
null=True,
|
||||
),
|
||||
),
|
||||
(
|
||||
"status",
|
||||
models.SmallIntegerField(
|
||||
choices=[(0, "禁用"), (1, "启用")],
|
||||
db_comment="状态",
|
||||
default=0,
|
||||
verbose_name="状态",
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
"verbose_name": "AI API 密钥",
|
||||
"verbose_name_plural": "AI API 密钥",
|
||||
"db_table": "ai_api_key",
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="AIModel",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.BigAutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
(
|
||||
"remark",
|
||||
models.CharField(
|
||||
blank=True,
|
||||
db_comment="备注",
|
||||
help_text="备注",
|
||||
max_length=256,
|
||||
null=True,
|
||||
),
|
||||
),
|
||||
(
|
||||
"creator",
|
||||
models.CharField(
|
||||
blank=True,
|
||||
db_comment="创建人",
|
||||
help_text="创建人",
|
||||
max_length=64,
|
||||
null=True,
|
||||
),
|
||||
),
|
||||
(
|
||||
"modifier",
|
||||
models.CharField(
|
||||
blank=True,
|
||||
db_comment="修改人",
|
||||
help_text="修改人",
|
||||
max_length=64,
|
||||
null=True,
|
||||
),
|
||||
),
|
||||
(
|
||||
"update_time",
|
||||
models.DateTimeField(
|
||||
auto_now=True,
|
||||
db_comment="修改时间",
|
||||
help_text="修改时间",
|
||||
null=True,
|
||||
),
|
||||
),
|
||||
(
|
||||
"create_time",
|
||||
models.DateTimeField(
|
||||
auto_now_add=True,
|
||||
db_comment="创建时间",
|
||||
help_text="创建时间",
|
||||
null=True,
|
||||
),
|
||||
),
|
||||
(
|
||||
"is_deleted",
|
||||
models.BooleanField(db_comment="是否软删除", default=False),
|
||||
),
|
||||
("name", models.CharField(db_comment="模型名字", max_length=64)),
|
||||
("sort", models.IntegerField(db_comment="排序", default=0)),
|
||||
(
|
||||
"status",
|
||||
models.SmallIntegerField(
|
||||
choices=[(0, "禁用"), (1, "启用")],
|
||||
db_comment="状态",
|
||||
default=0,
|
||||
verbose_name="状态",
|
||||
),
|
||||
),
|
||||
("platform", models.CharField(db_comment="模型平台", max_length=32)),
|
||||
("model", models.CharField(db_comment="模型标识", max_length=64)),
|
||||
(
|
||||
"temperature",
|
||||
models.FloatField(blank=True, db_comment="温度参数", null=True),
|
||||
),
|
||||
(
|
||||
"max_tokens",
|
||||
models.IntegerField(
|
||||
blank=True, db_comment="单条回复的最大 Token 数量", null=True
|
||||
),
|
||||
),
|
||||
(
|
||||
"max_contexts",
|
||||
models.IntegerField(
|
||||
blank=True, db_comment="上下文的最大 Message 数量", null=True
|
||||
),
|
||||
),
|
||||
(
|
||||
"key",
|
||||
models.ForeignKey(
|
||||
db_comment="API 秘钥编号",
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
to="ai.aiapikey",
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
"verbose_name": "AI 模型",
|
||||
"verbose_name_plural": "AI 模型",
|
||||
"db_table": "ai_model",
|
||||
},
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,262 @@
|
||||
# Generated by Django 5.2.1 on 2025-07-10 04:07
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("ai", "0001_initial"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name="aiapikey",
|
||||
name="api_key",
|
||||
field=models.CharField(
|
||||
db_comment="密钥", max_length=255, verbose_name="密钥"
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="aiapikey",
|
||||
name="create_time",
|
||||
field=models.DateTimeField(
|
||||
auto_now_add=True,
|
||||
db_comment="创建时间",
|
||||
help_text="创建时间",
|
||||
null=True,
|
||||
verbose_name="创建时间",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="aiapikey",
|
||||
name="creator",
|
||||
field=models.CharField(
|
||||
blank=True,
|
||||
db_comment="创建人",
|
||||
help_text="创建人",
|
||||
max_length=64,
|
||||
null=True,
|
||||
verbose_name="创建人",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="aiapikey",
|
||||
name="is_deleted",
|
||||
field=models.BooleanField(
|
||||
db_comment="是否软删除", default=False, verbose_name="是否软删除"
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="aiapikey",
|
||||
name="modifier",
|
||||
field=models.CharField(
|
||||
blank=True,
|
||||
db_comment="修改人",
|
||||
help_text="修改人",
|
||||
max_length=64,
|
||||
null=True,
|
||||
verbose_name="修改人",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="aiapikey",
|
||||
name="name",
|
||||
field=models.CharField(
|
||||
db_comment="名称", max_length=255, verbose_name="名称"
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="aiapikey",
|
||||
name="platform",
|
||||
field=models.CharField(
|
||||
choices=[
|
||||
("AzureOpenAI", "OpenAI 微软"),
|
||||
("OpenAI", "OpenAI"),
|
||||
("Ollama", "Ollama"),
|
||||
("YiYan", "文心一言"),
|
||||
("XingHuo", "讯飞星火"),
|
||||
("TongYi", "通义千问"),
|
||||
("StableDiffusion", "StableDiffusion"),
|
||||
("Midjourney", "Midjourney"),
|
||||
("Suno", "Suno"),
|
||||
("DeepSeek", "DeepSeek"),
|
||||
("DouBao", "字节豆包"),
|
||||
("HunYuan", "腾讯混元"),
|
||||
("SiliconFlow", "硅基流动"),
|
||||
("ZhiPu", "智谱"),
|
||||
("MiniMax", "MiniMax"),
|
||||
("Moonshot", "月之暗灭"),
|
||||
("BaiChuan", "百川智能"),
|
||||
],
|
||||
db_comment="平台",
|
||||
max_length=100,
|
||||
verbose_name="平台",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="aiapikey",
|
||||
name="remark",
|
||||
field=models.CharField(
|
||||
blank=True,
|
||||
db_comment="备注",
|
||||
help_text="备注",
|
||||
max_length=256,
|
||||
null=True,
|
||||
verbose_name="备注",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="aiapikey",
|
||||
name="update_time",
|
||||
field=models.DateTimeField(
|
||||
auto_now=True,
|
||||
db_comment="修改时间",
|
||||
help_text="修改时间",
|
||||
null=True,
|
||||
verbose_name="修改时间",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="aiapikey",
|
||||
name="url",
|
||||
field=models.CharField(
|
||||
blank=True,
|
||||
db_comment="自定义 API 地址",
|
||||
max_length=255,
|
||||
null=True,
|
||||
verbose_name="自定义 API 地址",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="aimodel",
|
||||
name="create_time",
|
||||
field=models.DateTimeField(
|
||||
auto_now_add=True,
|
||||
db_comment="创建时间",
|
||||
help_text="创建时间",
|
||||
null=True,
|
||||
verbose_name="创建时间",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="aimodel",
|
||||
name="creator",
|
||||
field=models.CharField(
|
||||
blank=True,
|
||||
db_comment="创建人",
|
||||
help_text="创建人",
|
||||
max_length=64,
|
||||
null=True,
|
||||
verbose_name="创建人",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="aimodel",
|
||||
name="is_deleted",
|
||||
field=models.BooleanField(
|
||||
db_comment="是否软删除", default=False, verbose_name="是否软删除"
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="aimodel",
|
||||
name="key",
|
||||
field=models.ForeignKey(
|
||||
db_comment="API 秘钥编号",
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
to="ai.aiapikey",
|
||||
verbose_name="API 秘钥编号",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="aimodel",
|
||||
name="max_contexts",
|
||||
field=models.IntegerField(
|
||||
blank=True,
|
||||
db_comment="上下文的最大 Message 数量",
|
||||
null=True,
|
||||
verbose_name="上下文的最大 Message 数量",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="aimodel",
|
||||
name="max_tokens",
|
||||
field=models.IntegerField(
|
||||
blank=True,
|
||||
db_comment="单条回复的最大 Token 数量",
|
||||
null=True,
|
||||
verbose_name="单条回复的最大 Token 数量",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="aimodel",
|
||||
name="model",
|
||||
field=models.CharField(
|
||||
db_comment="模型标识", max_length=64, verbose_name="模型标识"
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="aimodel",
|
||||
name="modifier",
|
||||
field=models.CharField(
|
||||
blank=True,
|
||||
db_comment="修改人",
|
||||
help_text="修改人",
|
||||
max_length=64,
|
||||
null=True,
|
||||
verbose_name="修改人",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="aimodel",
|
||||
name="name",
|
||||
field=models.CharField(
|
||||
db_comment="模型名字", max_length=64, verbose_name="模型名字"
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="aimodel",
|
||||
name="platform",
|
||||
field=models.CharField(
|
||||
db_comment="模型平台", max_length=32, verbose_name="模型平台"
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="aimodel",
|
||||
name="remark",
|
||||
field=models.CharField(
|
||||
blank=True,
|
||||
db_comment="备注",
|
||||
help_text="备注",
|
||||
max_length=256,
|
||||
null=True,
|
||||
verbose_name="备注",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="aimodel",
|
||||
name="sort",
|
||||
field=models.IntegerField(
|
||||
db_comment="排序", default=0, verbose_name="排序"
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="aimodel",
|
||||
name="temperature",
|
||||
field=models.FloatField(
|
||||
blank=True, db_comment="温度参数", null=True, verbose_name="温度参数"
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="aimodel",
|
||||
name="update_time",
|
||||
field=models.DateTimeField(
|
||||
auto_now=True,
|
||||
db_comment="修改时间",
|
||||
help_text="修改时间",
|
||||
null=True,
|
||||
verbose_name="修改时间",
|
||||
),
|
||||
),
|
||||
]
|
||||
0
backend/ai/migrations/__init__.py
Normal file
0
backend/ai/migrations/__init__.py
Normal file
61
backend/ai/models.py
Normal file
61
backend/ai/models.py
Normal file
@@ -0,0 +1,61 @@
|
||||
from django.db import models
|
||||
|
||||
from ai.choices import PlatformChoices
|
||||
from utils.models import CommonStatus, CoreModel
|
||||
|
||||
class AIApiKey(CoreModel):
|
||||
""" AI API 密钥表 """
|
||||
name = models.CharField(max_length=255, db_comment="名称", verbose_name="名称")
|
||||
platform = models.CharField(
|
||||
max_length=100,
|
||||
choices=PlatformChoices.choices,
|
||||
verbose_name="平台",
|
||||
db_comment="平台"
|
||||
)
|
||||
api_key = models.CharField(max_length=255, db_comment="密钥", verbose_name="密钥")
|
||||
url = models.CharField(max_length=255, null=True, blank=True, db_comment="自定义 API 地址", verbose_name="自定义 API 地址")
|
||||
status = models.SmallIntegerField(
|
||||
choices=CommonStatus.choices,
|
||||
default=CommonStatus.DISABLED,
|
||||
verbose_name="状态",
|
||||
db_comment="状态",
|
||||
)
|
||||
|
||||
class Meta:
|
||||
db_table = "ai_api_key"
|
||||
verbose_name = "AI API 密钥"
|
||||
verbose_name_plural = verbose_name
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
class AIModel(CoreModel):
|
||||
""" AI 模型 """
|
||||
name = models.CharField(max_length=64, db_comment="模型名字", verbose_name="模型名字")
|
||||
sort = models.IntegerField(db_comment="排序", default=0, verbose_name="排序")
|
||||
status = models.SmallIntegerField(
|
||||
choices=CommonStatus.choices,
|
||||
default=CommonStatus.DISABLED,
|
||||
verbose_name="状态",
|
||||
db_comment="状态",
|
||||
)
|
||||
key = models.ForeignKey(
|
||||
'AIApiKey',
|
||||
on_delete=models.CASCADE,
|
||||
db_comment='API 秘钥编号', verbose_name="API 秘钥编号"
|
||||
)
|
||||
platform = models.CharField(max_length=32, db_comment="模型平台", verbose_name="模型平台")
|
||||
model = models.CharField(max_length=64, db_comment="模型标识", verbose_name="模型标识")
|
||||
|
||||
temperature = models.FloatField(null=True, blank=True, db_comment="温度参数", verbose_name="温度参数")
|
||||
max_tokens = models.IntegerField(null=True, blank=True, db_comment="单条回复的最大 Token 数量", verbose_name="单条回复的最大 Token 数量")
|
||||
max_contexts = models.IntegerField(null=True, blank=True, db_comment="上下文的最大 Message 数量", verbose_name="上下文的最大 Message 数量")
|
||||
|
||||
class Meta:
|
||||
db_table = "ai_model"
|
||||
verbose_name = "AI 模型"
|
||||
verbose_name_plural = verbose_name
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
3
backend/ai/tests.py
Normal file
3
backend/ai/tests.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
||||
11
backend/ai/urls.py
Normal file
11
backend/ai/urls.py
Normal file
@@ -0,0 +1,11 @@
|
||||
from django.urls import include, path
|
||||
from rest_framework import routers
|
||||
|
||||
from . import views
|
||||
|
||||
router = routers.DefaultRouter()
|
||||
router.register(r'ai_api_key', views.AIApiKeyViewSet)
|
||||
urlpatterns = [
|
||||
path('', include(router.urls)),
|
||||
|
||||
]
|
||||
3
backend/ai/views.py
Normal file
3
backend/ai/views.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from django.shortcuts import render
|
||||
|
||||
# Create your views here.
|
||||
5
backend/ai/views/__init__.py
Normal file
5
backend/ai/views/__init__.py
Normal file
@@ -0,0 +1,5 @@
|
||||
__all__ = [
|
||||
'AIApiKeyViewSet'
|
||||
]
|
||||
|
||||
from ai.views.ai_api_key import AIApiKeyViewSet
|
||||
27
backend/ai/views/ai_api_key.py
Normal file
27
backend/ai/views/ai_api_key.py
Normal file
@@ -0,0 +1,27 @@
|
||||
from ai.models import AIApiKey
|
||||
from utils.serializers import CustomModelSerializer
|
||||
from utils.custom_model_viewSet import CustomModelViewSet
|
||||
|
||||
class AIApiKeySerializer(CustomModelSerializer):
|
||||
"""
|
||||
AI API 密钥 序列化器
|
||||
"""
|
||||
class Meta:
|
||||
model = AIApiKey
|
||||
fields = '__all__'
|
||||
read_only_fields = ['id', 'create_time', 'update_time']
|
||||
|
||||
|
||||
class AIApiKeyViewSet(CustomModelViewSet):
|
||||
"""
|
||||
AI API 密钥 视图集
|
||||
"""
|
||||
queryset = AIApiKey.objects.filter(is_deleted=False).order_by('-id')
|
||||
serializer_class = AIApiKeySerializer
|
||||
filterset_fields = ['id', 'remark', 'creator', 'modifier', 'is_deleted', 'name', 'platform', 'api_key', 'url', 'status']
|
||||
search_fields = ['name'] # 根据实际字段调整
|
||||
ordering_fields = ['create_time', 'id']
|
||||
ordering = ['-create_time']
|
||||
|
||||
# 移入urls中
|
||||
#
|
||||
@@ -54,6 +54,7 @@ INSTALLED_APPS = [
|
||||
'corsheaders',
|
||||
'rest_framework.authtoken',
|
||||
"system",
|
||||
"ai",
|
||||
]
|
||||
|
||||
MIDDLEWARE = [
|
||||
|
||||
@@ -20,6 +20,7 @@ from django.conf import settings
|
||||
|
||||
urlpatterns = [
|
||||
path('api/system/', include('system.urls')),
|
||||
path('api/ai/', include('ai.urls')),
|
||||
]
|
||||
|
||||
# 演示环境下禁用 admin 路由
|
||||
|
||||
@@ -7,6 +7,7 @@ import type { ${app_name_camel}${model_name}Api } from '#/models/${app_name}/${m
|
||||
import { z } from '#/adapter/form';
|
||||
import { $$t } from '#/locales';
|
||||
import { format_datetime } from '#/utils/date';
|
||||
import { op } from '#/utils/permission';
|
||||
|
||||
/**
|
||||
* 获取编辑表单的字段配置
|
||||
|
||||
@@ -0,0 +1,617 @@
|
||||
# Generated by Django 5.2.1 on 2025-07-10 04:07
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("system", "0001_initial"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name="dept",
|
||||
name="creator",
|
||||
field=models.CharField(
|
||||
blank=True,
|
||||
db_comment="创建人",
|
||||
help_text="创建人",
|
||||
max_length=64,
|
||||
null=True,
|
||||
verbose_name="创建人",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="dept",
|
||||
name="is_deleted",
|
||||
field=models.BooleanField(
|
||||
db_comment="是否软删除", default=False, verbose_name="是否软删除"
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="dept",
|
||||
name="modifier",
|
||||
field=models.CharField(
|
||||
blank=True,
|
||||
db_comment="修改人",
|
||||
help_text="修改人",
|
||||
max_length=64,
|
||||
null=True,
|
||||
verbose_name="修改人",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="dept",
|
||||
name="update_time",
|
||||
field=models.DateTimeField(
|
||||
auto_now=True,
|
||||
db_comment="修改时间",
|
||||
help_text="修改时间",
|
||||
null=True,
|
||||
verbose_name="修改时间",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="dictdata",
|
||||
name="create_time",
|
||||
field=models.DateTimeField(
|
||||
auto_now_add=True,
|
||||
db_comment="创建时间",
|
||||
help_text="创建时间",
|
||||
null=True,
|
||||
verbose_name="创建时间",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="dictdata",
|
||||
name="creator",
|
||||
field=models.CharField(
|
||||
blank=True,
|
||||
db_comment="创建人",
|
||||
help_text="创建人",
|
||||
max_length=64,
|
||||
null=True,
|
||||
verbose_name="创建人",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="dictdata",
|
||||
name="is_deleted",
|
||||
field=models.BooleanField(
|
||||
db_comment="是否软删除", default=False, verbose_name="是否软删除"
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="dictdata",
|
||||
name="modifier",
|
||||
field=models.CharField(
|
||||
blank=True,
|
||||
db_comment="修改人",
|
||||
help_text="修改人",
|
||||
max_length=64,
|
||||
null=True,
|
||||
verbose_name="修改人",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="dictdata",
|
||||
name="remark",
|
||||
field=models.CharField(
|
||||
blank=True,
|
||||
db_comment="备注",
|
||||
help_text="备注",
|
||||
max_length=256,
|
||||
null=True,
|
||||
verbose_name="备注",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="dictdata",
|
||||
name="update_time",
|
||||
field=models.DateTimeField(
|
||||
auto_now=True,
|
||||
db_comment="修改时间",
|
||||
help_text="修改时间",
|
||||
null=True,
|
||||
verbose_name="修改时间",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="dicttype",
|
||||
name="create_time",
|
||||
field=models.DateTimeField(
|
||||
auto_now_add=True,
|
||||
db_comment="创建时间",
|
||||
help_text="创建时间",
|
||||
null=True,
|
||||
verbose_name="创建时间",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="dicttype",
|
||||
name="creator",
|
||||
field=models.CharField(
|
||||
blank=True,
|
||||
db_comment="创建人",
|
||||
help_text="创建人",
|
||||
max_length=64,
|
||||
null=True,
|
||||
verbose_name="创建人",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="dicttype",
|
||||
name="is_deleted",
|
||||
field=models.BooleanField(
|
||||
db_comment="是否软删除", default=False, verbose_name="是否软删除"
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="dicttype",
|
||||
name="modifier",
|
||||
field=models.CharField(
|
||||
blank=True,
|
||||
db_comment="修改人",
|
||||
help_text="修改人",
|
||||
max_length=64,
|
||||
null=True,
|
||||
verbose_name="修改人",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="dicttype",
|
||||
name="remark",
|
||||
field=models.CharField(
|
||||
blank=True,
|
||||
db_comment="备注",
|
||||
help_text="备注",
|
||||
max_length=256,
|
||||
null=True,
|
||||
verbose_name="备注",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="dicttype",
|
||||
name="update_time",
|
||||
field=models.DateTimeField(
|
||||
auto_now=True,
|
||||
db_comment="修改时间",
|
||||
help_text="修改时间",
|
||||
null=True,
|
||||
verbose_name="修改时间",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="loginlog",
|
||||
name="create_time",
|
||||
field=models.DateTimeField(
|
||||
auto_now_add=True,
|
||||
db_comment="创建时间",
|
||||
help_text="创建时间",
|
||||
null=True,
|
||||
verbose_name="创建时间",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="loginlog",
|
||||
name="creator",
|
||||
field=models.CharField(
|
||||
blank=True,
|
||||
db_comment="创建人",
|
||||
help_text="创建人",
|
||||
max_length=64,
|
||||
null=True,
|
||||
verbose_name="创建人",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="loginlog",
|
||||
name="is_deleted",
|
||||
field=models.BooleanField(
|
||||
db_comment="是否软删除", default=False, verbose_name="是否软删除"
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="loginlog",
|
||||
name="modifier",
|
||||
field=models.CharField(
|
||||
blank=True,
|
||||
db_comment="修改人",
|
||||
help_text="修改人",
|
||||
max_length=64,
|
||||
null=True,
|
||||
verbose_name="修改人",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="loginlog",
|
||||
name="remark",
|
||||
field=models.CharField(
|
||||
blank=True,
|
||||
db_comment="备注",
|
||||
help_text="备注",
|
||||
max_length=256,
|
||||
null=True,
|
||||
verbose_name="备注",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="loginlog",
|
||||
name="update_time",
|
||||
field=models.DateTimeField(
|
||||
auto_now=True,
|
||||
db_comment="修改时间",
|
||||
help_text="修改时间",
|
||||
null=True,
|
||||
verbose_name="修改时间",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="menu",
|
||||
name="create_time",
|
||||
field=models.DateTimeField(
|
||||
auto_now_add=True,
|
||||
db_comment="创建时间",
|
||||
help_text="创建时间",
|
||||
null=True,
|
||||
verbose_name="创建时间",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="menu",
|
||||
name="creator",
|
||||
field=models.CharField(
|
||||
blank=True,
|
||||
db_comment="创建人",
|
||||
help_text="创建人",
|
||||
max_length=64,
|
||||
null=True,
|
||||
verbose_name="创建人",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="menu",
|
||||
name="is_deleted",
|
||||
field=models.BooleanField(
|
||||
db_comment="是否软删除", default=False, verbose_name="是否软删除"
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="menu",
|
||||
name="modifier",
|
||||
field=models.CharField(
|
||||
blank=True,
|
||||
db_comment="修改人",
|
||||
help_text="修改人",
|
||||
max_length=64,
|
||||
null=True,
|
||||
verbose_name="修改人",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="menu",
|
||||
name="remark",
|
||||
field=models.CharField(
|
||||
blank=True,
|
||||
db_comment="备注",
|
||||
help_text="备注",
|
||||
max_length=256,
|
||||
null=True,
|
||||
verbose_name="备注",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="menu",
|
||||
name="update_time",
|
||||
field=models.DateTimeField(
|
||||
auto_now=True,
|
||||
db_comment="修改时间",
|
||||
help_text="修改时间",
|
||||
null=True,
|
||||
verbose_name="修改时间",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="menumeta",
|
||||
name="create_time",
|
||||
field=models.DateTimeField(
|
||||
auto_now_add=True,
|
||||
db_comment="创建时间",
|
||||
help_text="创建时间",
|
||||
null=True,
|
||||
verbose_name="创建时间",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="menumeta",
|
||||
name="creator",
|
||||
field=models.CharField(
|
||||
blank=True,
|
||||
db_comment="创建人",
|
||||
help_text="创建人",
|
||||
max_length=64,
|
||||
null=True,
|
||||
verbose_name="创建人",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="menumeta",
|
||||
name="is_deleted",
|
||||
field=models.BooleanField(
|
||||
db_comment="是否软删除", default=False, verbose_name="是否软删除"
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="menumeta",
|
||||
name="modifier",
|
||||
field=models.CharField(
|
||||
blank=True,
|
||||
db_comment="修改人",
|
||||
help_text="修改人",
|
||||
max_length=64,
|
||||
null=True,
|
||||
verbose_name="修改人",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="menumeta",
|
||||
name="remark",
|
||||
field=models.CharField(
|
||||
blank=True,
|
||||
db_comment="备注",
|
||||
help_text="备注",
|
||||
max_length=256,
|
||||
null=True,
|
||||
verbose_name="备注",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="menumeta",
|
||||
name="update_time",
|
||||
field=models.DateTimeField(
|
||||
auto_now=True,
|
||||
db_comment="修改时间",
|
||||
help_text="修改时间",
|
||||
null=True,
|
||||
verbose_name="修改时间",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="post",
|
||||
name="create_time",
|
||||
field=models.DateTimeField(
|
||||
auto_now_add=True,
|
||||
db_comment="创建时间",
|
||||
help_text="创建时间",
|
||||
null=True,
|
||||
verbose_name="创建时间",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="post",
|
||||
name="creator",
|
||||
field=models.CharField(
|
||||
blank=True,
|
||||
db_comment="创建人",
|
||||
help_text="创建人",
|
||||
max_length=64,
|
||||
null=True,
|
||||
verbose_name="创建人",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="post",
|
||||
name="is_deleted",
|
||||
field=models.BooleanField(
|
||||
db_comment="是否软删除", default=False, verbose_name="是否软删除"
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="post",
|
||||
name="modifier",
|
||||
field=models.CharField(
|
||||
blank=True,
|
||||
db_comment="修改人",
|
||||
help_text="修改人",
|
||||
max_length=64,
|
||||
null=True,
|
||||
verbose_name="修改人",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="post",
|
||||
name="remark",
|
||||
field=models.CharField(
|
||||
blank=True,
|
||||
db_comment="备注",
|
||||
help_text="备注",
|
||||
max_length=256,
|
||||
null=True,
|
||||
verbose_name="备注",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="post",
|
||||
name="update_time",
|
||||
field=models.DateTimeField(
|
||||
auto_now=True,
|
||||
db_comment="修改时间",
|
||||
help_text="修改时间",
|
||||
null=True,
|
||||
verbose_name="修改时间",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="role",
|
||||
name="create_time",
|
||||
field=models.DateTimeField(
|
||||
auto_now_add=True,
|
||||
db_comment="创建时间",
|
||||
help_text="创建时间",
|
||||
null=True,
|
||||
verbose_name="创建时间",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="role",
|
||||
name="creator",
|
||||
field=models.CharField(
|
||||
blank=True,
|
||||
db_comment="创建人",
|
||||
help_text="创建人",
|
||||
max_length=64,
|
||||
null=True,
|
||||
verbose_name="创建人",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="role",
|
||||
name="is_deleted",
|
||||
field=models.BooleanField(
|
||||
db_comment="是否软删除", default=False, verbose_name="是否软删除"
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="role",
|
||||
name="modifier",
|
||||
field=models.CharField(
|
||||
blank=True,
|
||||
db_comment="修改人",
|
||||
help_text="修改人",
|
||||
max_length=64,
|
||||
null=True,
|
||||
verbose_name="修改人",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="role",
|
||||
name="update_time",
|
||||
field=models.DateTimeField(
|
||||
auto_now=True,
|
||||
db_comment="修改时间",
|
||||
help_text="修改时间",
|
||||
null=True,
|
||||
verbose_name="修改时间",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="rolepermission",
|
||||
name="creator",
|
||||
field=models.CharField(
|
||||
blank=True,
|
||||
db_comment="创建人",
|
||||
help_text="创建人",
|
||||
max_length=64,
|
||||
null=True,
|
||||
verbose_name="创建人",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="rolepermission",
|
||||
name="is_deleted",
|
||||
field=models.BooleanField(
|
||||
db_comment="是否软删除", default=False, verbose_name="是否软删除"
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="rolepermission",
|
||||
name="modifier",
|
||||
field=models.CharField(
|
||||
blank=True,
|
||||
db_comment="修改人",
|
||||
help_text="修改人",
|
||||
max_length=64,
|
||||
null=True,
|
||||
verbose_name="修改人",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="rolepermission",
|
||||
name="remark",
|
||||
field=models.CharField(
|
||||
blank=True,
|
||||
db_comment="备注",
|
||||
help_text="备注",
|
||||
max_length=256,
|
||||
null=True,
|
||||
verbose_name="备注",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="rolepermission",
|
||||
name="update_time",
|
||||
field=models.DateTimeField(
|
||||
auto_now=True,
|
||||
db_comment="修改时间",
|
||||
help_text="修改时间",
|
||||
null=True,
|
||||
verbose_name="修改时间",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="user",
|
||||
name="create_time",
|
||||
field=models.DateTimeField(
|
||||
auto_now_add=True,
|
||||
db_comment="创建时间",
|
||||
help_text="创建时间",
|
||||
null=True,
|
||||
verbose_name="创建时间",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="user",
|
||||
name="creator",
|
||||
field=models.CharField(
|
||||
blank=True,
|
||||
db_comment="创建人",
|
||||
help_text="创建人",
|
||||
max_length=64,
|
||||
null=True,
|
||||
verbose_name="创建人",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="user",
|
||||
name="is_deleted",
|
||||
field=models.BooleanField(
|
||||
db_comment="是否软删除", default=False, verbose_name="是否软删除"
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="user",
|
||||
name="modifier",
|
||||
field=models.CharField(
|
||||
blank=True,
|
||||
db_comment="修改人",
|
||||
help_text="修改人",
|
||||
max_length=64,
|
||||
null=True,
|
||||
verbose_name="修改人",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="user",
|
||||
name="remark",
|
||||
field=models.CharField(
|
||||
blank=True,
|
||||
db_comment="备注",
|
||||
help_text="备注",
|
||||
max_length=256,
|
||||
null=True,
|
||||
verbose_name="备注",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="user",
|
||||
name="update_time",
|
||||
field=models.DateTimeField(
|
||||
auto_now=True,
|
||||
db_comment="修改时间",
|
||||
help_text="修改时间",
|
||||
null=True,
|
||||
verbose_name="修改时间",
|
||||
),
|
||||
),
|
||||
]
|
||||
@@ -10,13 +10,17 @@ class CommonStatus(models.IntegerChoices):
|
||||
ENABLED = 1, '启用'
|
||||
|
||||
class CoreModel(models.Model):
|
||||
remark = models.CharField(max_length=256, db_comment="备注", null=True, blank=True, help_text="备注")
|
||||
creator = models.CharField(max_length=64, null=True, blank=True, help_text="创建人", db_comment="创建人")
|
||||
modifier = models.CharField(max_length=64, null=True, blank=True, help_text="修改人", db_comment="修改人")
|
||||
update_time = models.DateTimeField(auto_now=True, null=True, blank=True, help_text="修改时间", db_comment="修改时间")
|
||||
remark = models.CharField(max_length=256, db_comment="备注", null=True, blank=True, help_text="备注",
|
||||
verbose_name="备注")
|
||||
creator = models.CharField(max_length=64, null=True, blank=True, help_text="创建人", db_comment="创建人",
|
||||
verbose_name="创建人")
|
||||
modifier = models.CharField(max_length=64, null=True, blank=True, help_text="修改人", db_comment="修改人",
|
||||
verbose_name="修改人")
|
||||
update_time = models.DateTimeField(auto_now=True, null=True, blank=True, help_text="修改时间",
|
||||
db_comment="修改时间", verbose_name="修改时间")
|
||||
create_time = models.DateTimeField(auto_now_add=True, null=True, blank=True, help_text="创建时间",
|
||||
db_comment="创建时间")
|
||||
is_deleted = models.BooleanField(default=False, db_comment='是否软删除')
|
||||
db_comment="创建时间", verbose_name="创建时间")
|
||||
is_deleted = models.BooleanField(default=False, db_comment='是否软删除', verbose_name="是否软删除")
|
||||
|
||||
class Meta:
|
||||
abstract = True
|
||||
|
||||
137
docs/docs/essential/module_creation_guide.md
Normal file
137
docs/docs/essential/module_creation_guide.md
Normal file
@@ -0,0 +1,137 @@
|
||||
---
|
||||
sidebar_position: 10
|
||||
---
|
||||
|
||||
# 新建模块
|
||||
|
||||
本文档适用于本项目(Django + Vue3),指导如何规范地新建一个完整的功能模块(含后端与前端)。
|
||||
|
||||
---
|
||||
|
||||
## 一、后端模块新建流程(Django)
|
||||
|
||||
1. **新建Django App**
|
||||
```bash
|
||||
cd backend
|
||||
python manage.py startapp <模块名>
|
||||
# 如: python manage.py startapp ai
|
||||
```
|
||||
> 建议模块名使用小写英文,避免与已有模块重名。
|
||||
|
||||
2. **注册App**
|
||||
- 在 `backend/backend/settings.py` 的 `INSTALLED_APPS` 中添加新模块。
|
||||
```python
|
||||
INSTALLED_APPS = [
|
||||
"simpleui",
|
||||
'django.contrib.admin',
|
||||
'django.contrib.auth',
|
||||
'django.contrib.contenttypes',
|
||||
'django.contrib.sessions',
|
||||
'django.contrib.messages',
|
||||
'django.contrib.staticfiles',
|
||||
"rest_framework",
|
||||
'django_filters',
|
||||
'corsheaders',
|
||||
'rest_framework.authtoken',
|
||||
"system",
|
||||
"ai", # 新加
|
||||
]
|
||||
```
|
||||
|
||||
3. **定义模型(models.py)**
|
||||
- 继承 `CoreModel`,包含必要的审计字段(如 creator、modifier)。
|
||||
- 示例:
|
||||
```python
|
||||
from system.models import CoreModel
|
||||
class AIApiKey(CoreModel):
|
||||
""" AI API 密钥表 """
|
||||
name = models.CharField(max_length=255, db_comment="名称")
|
||||
platform = models.CharField(max_length=255, db_comment="平台")
|
||||
```
|
||||
|
||||
4. **生成迁移并迁移数据库**
|
||||
```bash
|
||||
python manage.py makemigrations <模块名>
|
||||
python manage.py migrate
|
||||
```
|
||||
|
||||
5. **注册路由(urls.py)**
|
||||
- 按照RESTful规范注册路由。 在ai文件夹下新建urls文件,并添加以下内容
|
||||
```python
|
||||
from django.urls import include, path
|
||||
from rest_framework import routers
|
||||
|
||||
from . import views
|
||||
|
||||
router = routers.DefaultRouter()
|
||||
|
||||
urlpatterns = [
|
||||
path('', include(router.urls)),
|
||||
|
||||
]
|
||||
```
|
||||
6. **修改路由(urls.py)**
|
||||
- 按照RESTful规范注册路由。 在ai文件夹下新建urls文件,并添加以下内容
|
||||
```python
|
||||
urlpatterns = [
|
||||
path('api/system/', include('system.urls')),
|
||||
path('api/ai/', include('ai.urls')), # 新加
|
||||
]
|
||||
```
|
||||
|
||||
7. **权限与菜单自动生成(推荐)**
|
||||
- 使用代码生成器:
|
||||
```bash
|
||||
python manage.py generate_crud <模块名> <模型名> --frontend
|
||||
```
|
||||
|
||||
8. **
|
||||
```python
|
||||
# 在ai/views下新建 __init__.py文件
|
||||
__all__ = [
|
||||
'AIApiKeyViewSet'
|
||||
]
|
||||
|
||||
from ai.views.ai_api_key import AIApiKeyViewSet
|
||||
```
|
||||
|
||||
|
||||
---
|
||||
|
||||
## 二、前端模块新建流程(Vue3)(代码生成器已经生成)
|
||||
1. **配置多语言**
|
||||
在web/apps/web-antd/src/locales/langs/zh-CN/ai.json 配置多语言
|
||||
```json
|
||||
{
|
||||
"title": "AI 大模型"
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
2. **新建菜单配置**
|
||||
|
||||

|
||||
|
||||
|
||||
3. **生成权限菜单**
|
||||
```shell
|
||||
cd backend
|
||||
python manage.py gen_menu_json --app ai --model AIApiKey --parent AI
|
||||
```
|
||||
|
||||
|
||||
|
||||
---
|
||||
|
||||
## 三、注意事项
|
||||
|
||||
- 模块命名规范统一,避免重复。
|
||||
- 建议优先使用代码生成器自动生成基础代码,减少重复劳动。
|
||||
- 新模块需补充单元测试和接口文档。
|
||||
- 前后端接口字段需保持一致,类型安全。
|
||||
- 权限点、菜单、路由需同步配置。
|
||||
- 代码提交前请自查并走团队代码评审流程。
|
||||
|
||||
---
|
||||
|
||||
如有疑问请联系项目负责人或查阅项目主文档。
|
||||
BIN
docs/docs/essential/new_module.png
Normal file
BIN
docs/docs/essential/new_module.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 59 KiB |
7
web/apps/web-antd/src/locales/langs/en-US/ai.json
Normal file
7
web/apps/web-antd/src/locales/langs/en-US/ai.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"title": "AI Management",
|
||||
"ai_api_key": {
|
||||
"title": "API KEY",
|
||||
"name": "API KEY"
|
||||
}
|
||||
}
|
||||
7
web/apps/web-antd/src/locales/langs/zh-CN/ai.json
Normal file
7
web/apps/web-antd/src/locales/langs/zh-CN/ai.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"title": "AI大模型",
|
||||
"ai_api_key": {
|
||||
"title": "API 密钥",
|
||||
"name": "API 密钥"
|
||||
}
|
||||
}
|
||||
24
web/apps/web-antd/src/models/ai/ai_api_key.ts
Normal file
24
web/apps/web-antd/src/models/ai/ai_api_key.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import { BaseModel } from '#/models/base';
|
||||
|
||||
export namespace AiAIApiKeyApi {
|
||||
export interface AiAIApiKey {
|
||||
id: number;
|
||||
remark: string;
|
||||
creator: string;
|
||||
modifier: string;
|
||||
update_time: string;
|
||||
create_time: string;
|
||||
is_deleted: boolean;
|
||||
name: string;
|
||||
platform: string;
|
||||
api_key: string;
|
||||
url: string;
|
||||
status: number;
|
||||
}
|
||||
}
|
||||
|
||||
export class AiAIApiKeyModel extends BaseModel<AiAIApiKeyApi.AiAIApiKey> {
|
||||
constructor() {
|
||||
super('/ai/ai_api_key/');
|
||||
}
|
||||
}
|
||||
184
web/apps/web-antd/src/views/ai/ai_api_key/data.ts
Normal file
184
web/apps/web-antd/src/views/ai/ai_api_key/data.ts
Normal file
@@ -0,0 +1,184 @@
|
||||
import type { VxeTableGridOptions } from '@vben/plugins/vxe-table';
|
||||
|
||||
import type { VbenFormSchema } from '#/adapter/form';
|
||||
import type { OnActionClickFn } from '#/adapter/vxe-table';
|
||||
import type { AiAIApiKeyApi } from '#/models/ai/ai_api_key';
|
||||
|
||||
import { z } from '#/adapter/form';
|
||||
import { $t } from '#/locales';
|
||||
import { op } from '#/utils/permission';
|
||||
|
||||
/**
|
||||
* 获取编辑表单的字段配置
|
||||
*/
|
||||
export function useSchema(): VbenFormSchema[] {
|
||||
return [
|
||||
{
|
||||
component: 'Input',
|
||||
fieldName: 'name',
|
||||
label: 'name',
|
||||
rules: z
|
||||
.string()
|
||||
.min(1, $t('ui.formRules.required', ['name']))
|
||||
.max(100, $t('ui.formRules.maxLength', ['name', 100])),
|
||||
},
|
||||
{
|
||||
component: 'Input',
|
||||
fieldName: 'platform',
|
||||
label: 'platform',
|
||||
rules: z
|
||||
.string()
|
||||
.min(1, $t('ui.formRules.required', ['platform']))
|
||||
.max(100, $t('ui.formRules.maxLength', ['platform', 100])),
|
||||
},
|
||||
{
|
||||
component: 'Input',
|
||||
fieldName: 'api_key',
|
||||
label: 'api key',
|
||||
rules: z
|
||||
.string()
|
||||
.min(1, $t('ui.formRules.required', ['api key']))
|
||||
.max(100, $t('ui.formRules.maxLength', ['api key', 100])),
|
||||
},
|
||||
{
|
||||
component: 'Input',
|
||||
fieldName: 'url',
|
||||
label: 'url',
|
||||
rules: z
|
||||
.string()
|
||||
.min(1, $t('ui.formRules.required', ['url']))
|
||||
.max(100, $t('ui.formRules.maxLength', ['url', 100])),
|
||||
},
|
||||
{
|
||||
component: 'InputNumber',
|
||||
fieldName: 'status',
|
||||
label: '状态',
|
||||
},
|
||||
{
|
||||
component: 'Input',
|
||||
fieldName: 'remark',
|
||||
label: 'remark',
|
||||
rules: z
|
||||
.string()
|
||||
.min(1, $t('ui.formRules.required', ['remark']))
|
||||
.max(100, $t('ui.formRules.maxLength', ['remark', 100])),
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取编辑表单的字段配置
|
||||
*/
|
||||
export function useGridFormSchema(): VbenFormSchema[] {
|
||||
return [
|
||||
{
|
||||
component: 'Input',
|
||||
fieldName: 'name',
|
||||
label: 'name',
|
||||
},
|
||||
{
|
||||
component: 'Input',
|
||||
fieldName: 'platform',
|
||||
label: 'platform',
|
||||
},
|
||||
{
|
||||
component: 'Input',
|
||||
fieldName: 'api_key',
|
||||
label: 'api key',
|
||||
},
|
||||
{
|
||||
component: 'Input',
|
||||
fieldName: 'url',
|
||||
label: 'url',
|
||||
},
|
||||
{
|
||||
component: 'InputNumber',
|
||||
fieldName: 'status',
|
||||
label: '状态',
|
||||
},
|
||||
{
|
||||
component: 'Input',
|
||||
fieldName: 'remark',
|
||||
label: 'remark',
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取表格列配置
|
||||
* @description 使用函数的形式返回列数据而不是直接export一个Array常量,是为了响应语言切换时重新翻译表头
|
||||
* @param onActionClick 表格操作按钮点击事件
|
||||
*/
|
||||
export function useColumns(
|
||||
onActionClick?: OnActionClickFn<AiAIApiKeyApi.AiAIApiKey>,
|
||||
): VxeTableGridOptions<AiAIApiKeyApi.AiAIApiKey>['columns'] {
|
||||
return [
|
||||
{
|
||||
field: 'id',
|
||||
title: 'ID',
|
||||
},
|
||||
{
|
||||
field: 'name',
|
||||
title: 'name',
|
||||
},
|
||||
{
|
||||
field: 'platform',
|
||||
title: 'platform',
|
||||
},
|
||||
{
|
||||
field: 'api_key',
|
||||
title: 'api key',
|
||||
},
|
||||
{
|
||||
field: 'url',
|
||||
title: 'url',
|
||||
},
|
||||
{
|
||||
field: 'status',
|
||||
title: '状态',
|
||||
},
|
||||
{
|
||||
field: 'remark',
|
||||
title: 'remark',
|
||||
},
|
||||
{
|
||||
field: 'creator',
|
||||
title: 'creator',
|
||||
},
|
||||
{
|
||||
field: 'modifier',
|
||||
title: 'modifier',
|
||||
},
|
||||
{
|
||||
field: 'update_time',
|
||||
title: 'update time',
|
||||
},
|
||||
{
|
||||
field: 'create_time',
|
||||
title: 'create time',
|
||||
},
|
||||
{
|
||||
field: 'is_deleted',
|
||||
title: 'is deleted',
|
||||
},
|
||||
{
|
||||
align: 'center',
|
||||
cellRender: {
|
||||
attrs: {
|
||||
nameField: 'name',
|
||||
nameTitle: $t('ai.ai_api_key.name'),
|
||||
onClick: onActionClick,
|
||||
},
|
||||
name: 'CellOperation',
|
||||
options: [
|
||||
op('ai:ai_api_key:edit', 'edit'),
|
||||
op('ai:ai_api_key:delete', 'delete'),
|
||||
],
|
||||
},
|
||||
field: 'action',
|
||||
fixed: 'right',
|
||||
title: '操作',
|
||||
width: 120,
|
||||
},
|
||||
];
|
||||
}
|
||||
141
web/apps/web-antd/src/views/ai/ai_api_key/list.vue
Normal file
141
web/apps/web-antd/src/views/ai/ai_api_key/list.vue
Normal file
@@ -0,0 +1,141 @@
|
||||
<script lang="ts" setup>
|
||||
import type {
|
||||
OnActionClickParams,
|
||||
VxeTableGridOptions,
|
||||
} from '#/adapter/vxe-table';
|
||||
import type { AiAIApiKeyApi } from '#/models/ai/ai_api_key';
|
||||
|
||||
import { Page, useVbenModal } from '@vben/common-ui';
|
||||
import { Plus } from '@vben/icons';
|
||||
|
||||
import { Button, message } from 'ant-design-vue';
|
||||
|
||||
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||
import { $t } from '#/locales';
|
||||
import { AiAIApiKeyModel } from '#/models/ai/ai_api_key';
|
||||
|
||||
import { useColumns, useGridFormSchema } from './data';
|
||||
import Form from './modules/form.vue';
|
||||
|
||||
const formModel = new AiAIApiKeyModel();
|
||||
|
||||
const [FormModal, formModalApi] = useVbenModal({
|
||||
connectedComponent: Form,
|
||||
destroyOnClose: true,
|
||||
});
|
||||
|
||||
/**
|
||||
* 编辑AI API 密钥
|
||||
*/
|
||||
function onEdit(row: AiAIApiKeyApi.AiAIApiKey) {
|
||||
formModalApi.setData(row).open();
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建新AI API 密钥
|
||||
*/
|
||||
function onCreate() {
|
||||
formModalApi.setData(null).open();
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除AI API 密钥
|
||||
*/
|
||||
function onDelete(row: AiAIApiKeyApi.AiAIApiKey) {
|
||||
const hideLoading = message.loading({
|
||||
content: '删除AI API 密钥',
|
||||
duration: 0,
|
||||
key: 'action_process_msg',
|
||||
});
|
||||
formModel
|
||||
.delete(row.id)
|
||||
.then(() => {
|
||||
message.success({
|
||||
content: '删除成功',
|
||||
key: 'action_process_msg',
|
||||
});
|
||||
refreshGrid();
|
||||
})
|
||||
.catch(() => {
|
||||
hideLoading();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 表格操作按钮的回调函数
|
||||
*/
|
||||
function onActionClick({
|
||||
code,
|
||||
row,
|
||||
}: OnActionClickParams<AiAIApiKeyApi.AiAIApiKey>) {
|
||||
switch (code) {
|
||||
case 'delete': {
|
||||
onDelete(row);
|
||||
break;
|
||||
}
|
||||
case 'edit': {
|
||||
onEdit(row);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const [Grid, gridApi] = useVbenVxeGrid({
|
||||
formOptions: {
|
||||
schema: useGridFormSchema(),
|
||||
submitOnChange: true,
|
||||
},
|
||||
gridEvents: {},
|
||||
gridOptions: {
|
||||
columns: useColumns(onActionClick),
|
||||
height: 'auto',
|
||||
keepSource: true,
|
||||
pagerConfig: {
|
||||
enabled: true,
|
||||
},
|
||||
proxyConfig: {
|
||||
ajax: {
|
||||
query: async ({ page }, formValues) => {
|
||||
return await formModel.list({
|
||||
page: page.currentPage,
|
||||
pageSize: page.pageSize,
|
||||
...formValues,
|
||||
});
|
||||
},
|
||||
},
|
||||
},
|
||||
toolbarConfig: {
|
||||
custom: true,
|
||||
export: false,
|
||||
refresh: { code: 'query' },
|
||||
zoom: true,
|
||||
search: true,
|
||||
},
|
||||
} as VxeTableGridOptions,
|
||||
});
|
||||
|
||||
/**
|
||||
* 刷新表格
|
||||
*/
|
||||
function refreshGrid() {
|
||||
gridApi.query();
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Page auto-content-height>
|
||||
<FormModal @success="refreshGrid" />
|
||||
<Grid table-title="AI API 密钥">
|
||||
<template #toolbar-tools>
|
||||
<Button
|
||||
type="primary"
|
||||
@click="onCreate"
|
||||
v-permission="'ai:ai_api_key:create'"
|
||||
>
|
||||
<Plus class="size-5" />
|
||||
{{ $t('ui.actionTitle.create', [$t('ai.ai_api_key.name')]) }}
|
||||
</Button>
|
||||
</template>
|
||||
</Grid>
|
||||
</Page>
|
||||
</template>
|
||||
79
web/apps/web-antd/src/views/ai/ai_api_key/modules/form.vue
Normal file
79
web/apps/web-antd/src/views/ai/ai_api_key/modules/form.vue
Normal file
@@ -0,0 +1,79 @@
|
||||
<script lang="ts" setup>
|
||||
import type { AiAIApiKeyApi } from '#/models/ai/ai_api_key';
|
||||
|
||||
import { computed, ref } from 'vue';
|
||||
|
||||
import { useVbenModal } from '@vben/common-ui';
|
||||
|
||||
import { Button } from 'ant-design-vue';
|
||||
|
||||
import { useVbenForm } from '#/adapter/form';
|
||||
import { $t } from '#/locales';
|
||||
import { AiAIApiKeyModel } from '#/models/ai/ai_api_key';
|
||||
|
||||
import { useSchema } from '../data';
|
||||
|
||||
const emit = defineEmits(['success']);
|
||||
|
||||
const formModel = new AiAIApiKeyModel();
|
||||
|
||||
const formData = ref<AiAIApiKeyApi.AiAIApiKey>();
|
||||
const getTitle = computed(() => {
|
||||
return formData.value?.id
|
||||
? $t('ui.actionTitle.edit', [$t('ai.aiapikey.name')])
|
||||
: $t('ui.actionTitle.create', [$t('ai.aiapikey.name')]);
|
||||
});
|
||||
|
||||
const [Form, formApi] = useVbenForm({
|
||||
layout: 'horizontal',
|
||||
schema: useSchema(),
|
||||
showDefaultActions: false,
|
||||
});
|
||||
|
||||
function resetForm() {
|
||||
formApi.resetForm();
|
||||
formApi.setValues(formData.value || {});
|
||||
}
|
||||
|
||||
const [Modal, modalApi] = useVbenModal({
|
||||
async onConfirm() {
|
||||
const { valid } = await formApi.validate();
|
||||
if (valid) {
|
||||
modalApi.lock();
|
||||
const data = await formApi.getValues();
|
||||
try {
|
||||
await (formData.value?.id
|
||||
? formModel.update(formData.value.id, data)
|
||||
: formModel.create(data));
|
||||
await modalApi.close();
|
||||
emit('success');
|
||||
} finally {
|
||||
modalApi.lock(false);
|
||||
}
|
||||
}
|
||||
},
|
||||
onOpenChange(isOpen) {
|
||||
if (isOpen) {
|
||||
const data = modalApi.getData<AiAIApiKeyApi.AiAIApiKey>();
|
||||
if (data) {
|
||||
formData.value = data;
|
||||
formApi.setValues(formData.value);
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Modal :title="getTitle">
|
||||
<Form />
|
||||
<template #prepend-footer>
|
||||
<div class="flex-auto">
|
||||
<Button type="primary" danger @click="resetForm">
|
||||
{{ $t('common.reset') }}
|
||||
</Button>
|
||||
</div>
|
||||
</template>
|
||||
</Modal>
|
||||
</template>
|
||||
<style lang="css" scoped></style>
|
||||
Reference in New Issue
Block a user