initial commit

This commit is contained in:
2025-04-29 18:09:00 +08:00
commit 4faed52de5
690 changed files with 13481 additions and 0 deletions

0
apps/dict/__init__.py Normal file
View File

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

2
apps/dict/admin.py Normal file
View File

@@ -0,0 +1,2 @@
from django.contrib import admin
# Register your models here.

5
apps/dict/apps.py Normal file
View File

@@ -0,0 +1,5 @@
from django.apps import AppConfig
class DictConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'apps.dict'

View File

@@ -0,0 +1,7 @@
from apps.dict.controllers.abbreviation import AbbreviationController
from apps.dict.controllers.common import CommonController
from apps.dict.controllers.contact import ContactController
from apps.dict.controllers.dict import DictController
from apps.dict.controllers.fragment import UserFiledController
__all__ = ['AbbreviationController', 'CommonController', 'ContactController', 'DictController', 'UserFiledController']

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,71 @@
from ninja_extra import api_controller, ControllerBase, route
from ninja import Query
from apps.project.models import Abbreviation
from ninja_jwt.authentication import JWTAuth
from ninja_extra.permissions import IsAuthenticated
from ninja.pagination import paginate
from utils.chen_pagination import MyPagination
from django.db import transaction
from django.contrib.auth import get_user_model
from typing import List
from utils.chen_crud import multi_delete
from utils.chen_response import ChenResponse
from apps.dict.schema import DeleteSchema, AbbreviationOut, AbbreviationListInputSchema
Users = get_user_model()
@api_controller("/system", tags=['缩略语接口'], auth=JWTAuth(), permissions=[IsAuthenticated])
class AbbreviationController(ControllerBase):
@route.get("/abbreviation/getlist", response=List[AbbreviationOut], url_name="abbreviation-search")
@transaction.atomic
@paginate(MyPagination)
def get_abbreviation_list(self, payload: AbbreviationListInputSchema = Query(...)):
for attr, value in payload.__dict__.items():
if getattr(payload, attr) is None:
setattr(payload, attr, '')
qs = Abbreviation.objects.filter(title__icontains=payload.title, des__icontains=payload.des)
return qs
# 单独获取
@route.get("/abbreviation/index", response=List[AbbreviationOut], url_name="abbreviation-all")
@transaction.atomic
def get_contact_index(self):
qs = Abbreviation.objects.all()
return qs
@route.post("/abbreviation/save", response=AbbreviationOut, url_name='abbreviation-create')
@transaction.atomic
def create_abbreviation(self, data: AbbreviationListInputSchema):
for attr, value in data.__dict__.items():
if getattr(data, attr) is None:
setattr(data, attr, '')
# 判重key
assert_dict = data.dict()
key_qs = Abbreviation.objects.filter(title=data.title)
if len(key_qs) > 0:
return ChenResponse(code=400, status=400, message="缩略语重复,请修改...")
# 正常添加
qs = Abbreviation.objects.create(**assert_dict)
return qs
@route.put("/abbreviation/update/{id}", response=AbbreviationOut, url_name='abbreviation-update')
@transaction.atomic
def update_contact(self, id: int, data: AbbreviationListInputSchema):
for attr, value in data.__dict__.items():
if getattr(data, attr) is None:
setattr(data, attr, '')
key_qs = Abbreviation.objects.filter(title=data.title)
if len(key_qs) > 1:
return ChenResponse(code=400, status=400, message="缩略语重复,请修改...")
# 查询id
qs = Abbreviation.objects.get(id=id)
for attr, value in data.__dict__.items():
setattr(qs, attr, value)
qs.save()
return qs
@route.delete('/abbreviation/delete', url_name='abbreviation-delete')
@transaction.atomic
def delete_contact(self, data: DeleteSchema):
multi_delete(data.ids, Abbreviation)
return ChenResponse(message='单位或公司删除成功')

View File

@@ -0,0 +1,53 @@
from datetime import date
from ninja_extra import api_controller, ControllerBase, route
from apps.project.models import Project
from django.db import transaction
from django.contrib.auth import get_user_model
from utils.chen_response import ChenResponse
from django.db.models import Q
Users = get_user_model()
# 这是其他common内容接口
@api_controller("/system", tags=['通用接口'])
class CommonController(ControllerBase):
"""通用接口类:工作台内的信息"""
@route.get("/getNoticeList")
def get_notice(self, pageSize, orderBy, orderType):
item_list = []
item1 = {"title": "测试管理平台V0.0.2测试发布", "created_at": "2023-09-23",
"content": "测试管理平台V0.0.2发布,正在进行内部测试.."}
item_list.append(item1)
item2 = {"title": "测试管理平台更新公共", "created_at": "2024-06-17", "content": "<p>1.修改大纲和报告模版<p><p>2.修复多个bug<p>"}
item_list.append(item2)
return item_list
@route.get('/workplace/statistics')
@transaction.atomic
def get_statistics(self):
# 查询用户数量,进行的项目,项目总数,已完成项目数
user_count = Users.objects.count()
project_qs = Project.objects.all()
project_count = project_qs.count()
project_done_count = project_qs.filter(step='3').count()
project_processing_count = project_qs.filter(Q(step='1') | Q(step='2')).count()
return ChenResponse(data={'pcount': project_count, 'ucount': user_count,
'pdcount': project_done_count, 'ppcount': project_processing_count})
@route.get('/statistics/chart')
@transaction.atomic
def get_chart(self):
"""该接口返回当前年份下每月的项目统计返回横坐标12个月的字符串以及12个月数据"""
current_year = date.today().year
month_list = []
# 构造数组,里面是字典
for i in range(12):
month_dict = {'month': i + 1, 'count': 0}
month_list.append(month_dict)
project_qs = Project.objects.all()
for project in project_qs:
for m in month_list:
if m['month'] == project.beginTime.month and project.beginTime.year == current_year:
m['count'] += 1
return ChenResponse(status=200, code=200, data=month_list)

View File

@@ -0,0 +1,91 @@
from ninja_extra import api_controller, ControllerBase, route
from ninja import Query
from apps.project.models import Contact
from ninja_jwt.authentication import JWTAuth
from ninja_extra.permissions import IsAuthenticated
from ninja.pagination import paginate
from utils.chen_pagination import MyPagination
from django.db import transaction
from typing import List
from utils.chen_crud import multi_delete
from utils.chen_response import ChenResponse
from apps.dict.schema import DeleteSchema, ContactListInputSchema, ContactOut
# 公司信息处理接口
@api_controller("/system", tags=['公司信息相关'], auth=JWTAuth(), permissions=[IsAuthenticated])
class ContactController(ControllerBase):
@route.get("/contact/getlist", response=List[ContactOut], url_name="contact-search")
@transaction.atomic
@paginate(MyPagination)
def get_contact_list(self, payload: ContactListInputSchema = Query(...)):
for attr, value in payload.__dict__.items():
if getattr(payload, attr) is None:
setattr(payload, attr, '')
if payload.key == '':
qs = Contact.objects.filter(name__icontains=payload.name, entrust_person__icontains=payload.entrust_person,
addr__icontains=payload.addr)
else:
qs = Contact.objects.filter(name__icontains=payload.name, entrust_person__icontains=payload.entrust_person,
key=int(payload.key), addr__icontains=payload.addr)
return qs
# 单独获取
@route.get("/contact/index", response=List[ContactOut], url_name="contact-all")
@transaction.atomic
def get_contact_index(self):
qs = Contact.objects.all()
return qs
@route.post("/contact/save", response=ContactOut, url_name='contact-create')
@transaction.atomic
def create_contact(self, data: ContactListInputSchema):
for attr, value in data.__dict__.items():
if getattr(data, attr) is None:
setattr(data, attr, '')
# 判重key -> key可能为空
if data.key == '':
data.key = 0
assert_dict = data.dict()
key_qs = Contact.objects.filter(key=str(data.key))
if len(key_qs) > 0:
return ChenResponse(code=400, status=400, message="公司或单位的编号重复,请修改")
# 全称判重
name_qs = Contact.objects.filter(name=data.name)
if len(name_qs) > 0:
return ChenResponse(code=400, status=400, message="全称重复,请修改")
# 去掉key
assert_dict.pop("key")
assert_dict['key'] = 999999
qs = Contact.objects.create(**assert_dict)
qs.key = qs.id
qs.save()
return qs
@route.put("/contact/update/{id}", response=ContactOut, url_name='contact-update')
@transaction.atomic
def update_contact(self, id: int, data: ContactListInputSchema):
for attr, value in data.__dict__.items():
if getattr(data, attr) is None:
setattr(data, attr, '')
qs = Contact.objects.filter(id=id).first()
if qs:
if qs.key != data.key:
key_qs = Contact.objects.filter(key=str(data.key))
if len(key_qs) > 0:
return ChenResponse(code=400, status=400, message="公司或单位的编号重复,请修改")
if qs.name != data.name:
name_qs = Contact.objects.filter(name=data.name)
if len(name_qs) > 0:
return ChenResponse(code=400, status=400, message="全称重复,请修改")
# 更新联系人数据
for attr, value in data.__dict__.items():
setattr(qs, attr, value)
qs.save()
return qs
@route.delete('/contact/delete', url_name='contact-delete')
@transaction.atomic
def delete_contact(self, data: DeleteSchema):
multi_delete(data.ids, Contact)
return ChenResponse(message='单位或公司删除成功')

View File

@@ -0,0 +1,171 @@
from ninja_extra import api_controller, ControllerBase, route
from ninja import Query
from apps.dict.models import Dict, DictItem
from ninja_jwt.authentication import JWTAuth
from ninja_extra.permissions import IsAuthenticated, IsAdminUser
from ninja.pagination import paginate
from ninja.errors import HttpError
from utils.chen_pagination import MyPagination
from django.db import transaction
from typing import List
from utils.chen_crud import multi_delete
from utils.chen_response import ChenResponse
from apps.dict.schema import DictOut, DictIndexInput, ChangeStautsSchemaInput, DictItemInput, DictItemOut, \
DictItemChangeSrotInput, DictItemCreateInputSchema, DictItemUpdateInputSchema, DeleteSchema, \
DictItemFastCreateInputSchema, DictStdItemCreateInputSchema
@api_controller("/system", tags=['字典相关'], auth=JWTAuth(), permissions=[IsAuthenticated])
class DictController(ControllerBase):
@route.get("/dataDict/list", response=List[DictItemOut], url_name="dict-list")
def get_dict(self, code: str):
"""传入code类型例如testType返回字典Item信息"""
dict_qs = Dict.objects.get(code=code)
items = dict_qs.dictItem.filter(status='1')
return items
@route.get("/dataDict/index", response=List[DictOut], url_name="dict-index")
@transaction.atomic
@paginate(MyPagination)
def get_dict_index(self, payload: DictIndexInput = Query(...)):
for attr, value in payload.__dict__.items():
if getattr(payload, attr) is None:
setattr(payload, attr, '')
# 处理时间
if payload.update_datetime_start == '':
payload.update_datetime_start = "2000-01-01"
if payload.update_datetime_end == '':
payload.update_datetime_end = '5000-01-01'
date_list = [payload.update_datetime_start, payload.update_datetime_end]
qs = Dict.objects.filter(name__icontains=payload.name, remark__icontains=payload.remark,
code__icontains=payload.code, status__icontains=payload.status,
update_datetime__range=date_list)
return qs
@route.put("/dataDict/changeStatus", url_name="dict-changeStatus", permissions=[IsAdminUser])
@transaction.atomic
def change_dict_status(self, data: ChangeStautsSchemaInput):
qs = Dict.objects.get(id=data.id)
qs.status = data.status
qs.save()
return ChenResponse(code=200, status=200, message="修改状态成功")
@route.put("/dataDict/changeItemStatus", url_name="dict-changeItemStatus", permissions=[IsAdminUser])
@transaction.atomic
def change_dict_item_status(self, data: ChangeStautsSchemaInput):
qs = DictItem.objects.get(id=data.id)
qs.status = data.status
qs.save()
return ChenResponse(code=200, status=200, message="修改状态成功")
# 有dict的id查询其中的dictItem数据
@route.get("/dataDict/dictItemAll", response=List[DictItemOut], url_name='dictitem-list')
@transaction.atomic
@paginate(MyPagination)
def get_dictItem_list(self, payload: DictItemInput = Query(...)):
for attr, value in payload.__dict__.items():
if getattr(payload, attr) is None:
setattr(payload, attr, '')
# 处理时间
if payload.update_datetime_start == '':
payload.update_datetime_start = "2000-01-01"
if payload.update_datetime_end == '':
payload.update_datetime_end = '5000-01-01'
date_list = [payload.update_datetime_start, payload.update_datetime_end]
# 先对dict_id进行查询
dict_qs = Dict.objects.get(id=payload.dict_id)
# 反向连接
qs = dict_qs.dictItem.filter(update_datetime__range=date_list, status__icontains=payload.status,
key__icontains=payload.key, title__icontains=payload.title,
show_title__icontains=payload.show_title).order_by('sort')
return qs
# 更改dictItem的sort字段接口
@route.put("/dataDict/numberOperation", url_name="dictitem-changesort")
@transaction.atomic
def change_item_sort(self, data: DictItemChangeSrotInput):
qs = DictItem.objects.get(id=data.id)
qs.sort = data.numberValue
qs.save()
return ChenResponse(code=200, status=200, message='排序序号更新成功')
# 新增dictItem
@route.post("/dataDict/saveitem", response=DictItemOut, url_name="dictitem-save")
@transaction.atomic
def save_item(self, payload: DictItemCreateInputSchema):
# 先根据dict_id查询出dict
dict_qs = Dict.objects.get(id=payload.dict_id)
qs1 = dict_qs.dictItem.filter(title=payload.title)
if len(qs1) > 0:
return ChenResponse(code=400, status=400, message='字典标签重复,请检查')
# 计算key值应该为多少
key_number = str(len(dict_qs.dictItem.all()) + 1)
asert_dict = payload.dict(exclude_none=True)
asert_dict.pop('dict_id')
asert_dict.update({'dict': dict_qs, 'key': key_number})
qs = DictItem.objects.create(**asert_dict)
return qs
# 更新dictitem数据
@route.put("/dataDict/update/{id}", response=DictItemOut, url_name='dictitem-update')
@transaction.atomic
def update(self, id: int, payload: DictItemUpdateInputSchema):
dictitem_qs = DictItem.objects.get(id=id)
for attr, value in payload.dict().items():
setattr(dictitem_qs, attr, value)
dictitem_qs.save()
return dictitem_qs
# 删除dictItem数据
@route.delete("/dictType/realDeleteItem", url_name="dictitem-delete", permissions=[IsAdminUser])
@transaction.atomic
def delete_dictitem(self, data: DeleteSchema):
# 根据其中一个id查询出dict的id
dictItem_single = DictItem.objects.filter(id=data.ids[0])[0]
dict_id = dictItem_single.dict.id
multi_delete(data.ids, DictItem)
index = 1
qs = Dict.objects.get(id=dict_id).dictItem.all()
for qs_item in qs:
qs_item.key = str(index)
index = index + 1
qs_item.save()
return ChenResponse(message="字典条目删除成功!")
# 快速新增dictItem数据
@route.post("/dataDict/fastSave", url_name="dictitem-save-fast", permissions=[IsAuthenticated])
@transaction.atomic
def save_fast_dictitem(self, data: DictItemFastCreateInputSchema):
# 首先根据data.code查询出是哪个Dict
dict_single = Dict.objects.filter(code=data.code).first()
# 判断是否有该dict
if dict_single:
# 再判断是否dictItem重复
qs = dict_single.dictItem.filter(title=data.title)
if len(qs) > 0:
return ChenResponse(code=400, status=400, message='字典标签重复,请检查')
# 查看key值应该为多少了
key_number = str(len(dict_single.dictItem.all()) + 1)
DictItem.objects.create(title=data.title,
key=key_number,
show_title=data.title,
dict=dict_single)
else:
raise HttpError(404, "未查询到字典,请创建字典数据后进行")
return ChenResponse(message="新增成功")
# 快速新增依据标准dictItem数据 - 输入更变为code
@route.post("/dataDict/saveStdItem", response=DictItemOut, url_name="dictitem-save")
@transaction.atomic
def save(self, payload: DictStdItemCreateInputSchema):
# 先根据dict_id查询出dict
dict_qs = Dict.objects.get(code=payload.code)
qs1 = dict_qs.dictItem.filter(title=payload.title)
if len(qs1) > 0:
return ChenResponse(code=400, status=400, message='字典标签重复,请检查')
# 计算key值应该为多少
key_number = str(len(dict_qs.dictItem.all()) + 1)
asert_dict = payload.dict(exclude_none=True)
asert_dict.pop('code')
asert_dict.update({'dict': dict_qs, 'key': key_number})
qs=DictItem.objects.create(**asert_dict)
return qs

View File

@@ -0,0 +1,96 @@
from typing import List,Optional
from ninja_extra import api_controller, ControllerBase, route
from ninja import Schema, Field, Query, ModelSchema
from ninja.errors import HttpError
from ninja_jwt.authentication import JWTAuth
from ninja_extra.permissions import IsAuthenticated
from pydantic import model_validator
# 小工具函数
from utils.smallTools.interfaceTools import model_retrieve
from ninja.pagination import paginate
from utils.chen_pagination import MyPagination
from utils.chen_crud import updateWithoutRequestParam, multi_delete, createWithOutRequestParam
# ORM模型
from apps.dict.models import Fragment
# Schemas
## 查询fragment的输入
class FragementListSchema(Schema):
name: Optional[str] = None # 片段名称
is_main: Optional[bool] = None # 是否替换磁盘的片段
project_id: int = Field(None, alias='projectId')
## 查询结果
class FragmentOutSchema(ModelSchema):
class Meta:
model = Fragment
fields = ['id', 'name', 'project', 'is_main', 'content']
## 新增
class FragmentAddSchema(Schema):
name: str # 必填
is_main: bool = False # 后端直接设置为False
project_id: int = Field(None, alias='projectId')
content: str = ""
# username判重
@model_validator(mode='after')
def unique_name(self):
if Fragment.objects.filter(name=self.name, project_id=self.project_id).exists():
raise HttpError(400, "文档片段名称重复")
return self
## 更新文档片段
class FragmentUpdateSchema(Schema):
name: Optional[str] = None
is_main: Optional[bool] = None
project_id: int = Field(None, alias='projectId')
content: str = Field(None, alias='content')
def validate_unique_update_fragName(self, id: int):
frag_filters = Fragment.objects.filter(name=self.name)
if len(frag_filters) > 1:
raise HttpError(400, "文档片段名称重复")
elif len(frag_filters) == 1:
if frag_filters[0].id == id:
return
else:
raise HttpError(400, "文档片段名称重复")
else:
return
# 删除schema
class FragmentDeleteSchema(Schema):
ids: List[int]
# 全局静态变量
PIC_URL_PREFIX = "/uploads/"
# Controller
@api_controller("/system/userField", tags=['文档片段'], auth=JWTAuth(), permissions=[IsAuthenticated])
class UserFiledController(ControllerBase):
@route.get("/getFragment", response=List[FragmentOutSchema], url_name='fragment-list')
@paginate(MyPagination)
def get_fragement(self, condition: Query[FragementListSchema]):
fragment_qs = Fragment.objects.filter(project_id=condition.project_id)
res_qs = model_retrieve(condition, fragment_qs, ['project_id', 'is_main'])
res_qs = res_qs.filter(project_id=condition.project_id)
return res_qs
@route.post("/add", url_name='fragment-add', response=FragmentOutSchema)
def add_fragement(self, data: FragmentAddSchema):
return createWithOutRequestParam(data, Fragment)
@route.delete("/delete", url_name="fragment-delete")
def delete_fragment(self, data: FragmentDeleteSchema):
try:
multi_delete(data.ids, Fragment)
except Exception:
raise HttpError(500, "删除失败")
@route.put("/update/{int:id}", url_name='fragment-update')
def update_fragment(self, id: int, data: FragmentUpdateSchema):
update_obj = updateWithoutRequestParam(id, data, Fragment)
if update_obj:
return '更新成功'
raise HttpError(500, "设置替换磁盘文件渲染失败")

View File

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,16 @@
from enum import Enum, unique
# 产品文档名称
@unique
class DocNameEnum(Enum):
dg = 1
sm = 2
jl = 3
hsm = 4
hjl = 5
bg = 6
wtd = 7
if __name__ == '__main__':
print(DocNameEnum.dg)
print(DocNameEnum.dg.value)

View File

@@ -0,0 +1,12 @@
# 该类主要传入文档片段列表,对列表进行数据组装等工作
from django.db.models import QuerySet
# Models
from apps.dict.models import Fragment
class FragmentOperation(object):
def __init__(self, fragments: QuerySet[Fragment] = None):
self.__fragments = fragments # 初始化必须传入Fragment-Model对象
@property
def fragment(self):
return self.__fragments

View File

@@ -0,0 +1,58 @@
# Generated by Django 4.2.13 on 2024-07-03 10:38
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='Dict',
fields=[
('id', models.BigAutoField(help_text='Id', primary_key=True, serialize=False, verbose_name='Id')),
('update_datetime', models.DateField(auto_now=True, help_text='修改时间', null=True, verbose_name='修改时间')),
('create_datetime', models.DateField(auto_now_add=True, help_text='创建时间', null=True, verbose_name='创建时间')),
('sort', models.IntegerField(blank=True, default=1, help_text='显示排序', null=True, verbose_name='显示排序')),
('name', models.CharField(blank=True, help_text='字典名称', max_length=100, null=True, verbose_name='字典名称')),
('code', models.CharField(blank=True, help_text='编码', max_length=100, null=True, verbose_name='编码')),
('status', models.CharField(blank=True, default='1', help_text='状态', max_length=8, null=True, verbose_name='状态')),
('remark', models.CharField(blank=True, help_text='备注', max_length=2000, null=True, verbose_name='备注')),
],
options={
'verbose_name': '字典表',
'verbose_name_plural': '字典表',
'db_table': 'system_dict',
'ordering': ('-create_datetime',),
},
),
migrations.CreateModel(
name='DictItem',
fields=[
('id', models.BigAutoField(help_text='Id', primary_key=True, serialize=False, verbose_name='Id')),
('update_datetime', models.DateField(auto_now=True, help_text='修改时间', null=True, verbose_name='修改时间')),
('create_datetime', models.DateField(auto_now_add=True, help_text='创建时间', null=True, verbose_name='创建时间')),
('sort', models.IntegerField(blank=True, default=1, help_text='显示排序', null=True, verbose_name='显示排序')),
('title', models.CharField(blank=True, help_text='显示名称', max_length=100, null=True, verbose_name='显示名称')),
('key', models.CharField(blank=True, help_text='实际值', max_length=100, null=True, verbose_name='实际值')),
('show_title', models.CharField(blank=True, help_text='类型转文字', max_length=64, verbose_name='类型转文字')),
('status', models.CharField(blank=True, default='1', help_text='状态', max_length=8, null=True, verbose_name='状态')),
('remark', models.CharField(blank=True, help_text='备注', max_length=2000, null=True, verbose_name='备注')),
('doc_name', models.CharField(blank=True, help_text='文档名称', max_length=64, null=True, verbose_name='文档名称')),
('publish_date', models.CharField(blank=True, help_text='发布日期', max_length=64, null=True, verbose_name='发布日期')),
('source', models.CharField(blank=True, help_text='来源', max_length=32, null=True, verbose_name='来源')),
('dict', models.ForeignKey(db_constraint=False, help_text='字典', on_delete=django.db.models.deletion.CASCADE, related_name='dictItem', to='dict.dict')),
],
options={
'verbose_name': '字典表item表',
'verbose_name_plural': '字典表item表',
'db_table': 'system_dict_item',
'ordering': ('-create_datetime',),
},
),
]

View File

@@ -0,0 +1,35 @@
# Generated by Django 4.2.13 on 2024-07-23 11:02
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('dict', '0001_initial'),
]
operations = [
migrations.CreateModel(
name='UserDictField',
fields=[
('id', models.BigAutoField(help_text='Id', primary_key=True, serialize=False, verbose_name='Id')),
('remark', models.CharField(blank=True, help_text='描述', max_length=255, null=True, verbose_name='描述')),
('update_datetime', models.DateField(auto_now=True, help_text='修改时间', null=True, verbose_name='修改时间')),
('create_datetime', models.DateField(auto_now_add=True, help_text='创建时间', null=True, verbose_name='创建时间')),
('sort', models.IntegerField(blank=True, default=1, help_text='显示排序', null=True, verbose_name='显示排序')),
('name', models.CharField(max_length=64, verbose_name='字段名称')),
('type', models.PositiveIntegerField(choices=[(1, '文字'), (2, '段落'), (3, '多段段落'), (4, '图片')], verbose_name='字段类型')),
('ident', models.CharField(max_length=64, verbose_name='字段标识')),
('status', models.BooleanField(default=False, verbose_name='字段启用状态')),
('text', models.TextField(blank=True, null=True, verbose_name='字段的值')),
('pic', models.ImageField(blank=True, null=True, upload_to='field_images', verbose_name='图片信息')),
],
options={
'verbose_name': '用户字段表',
'verbose_name_plural': '用户字段表',
'db_table': 'user_dict_for_generate_doc',
'ordering': ('-create_datetime', '-id'),
},
),
]

View File

@@ -0,0 +1,121 @@
# Generated by Django 4.2.13 on 2024-07-24 14:43
import apps.dict.fragment.enums
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('project', '0003_alter_design_protocal'),
('dict', '0002_userdictfield'),
]
operations = [
migrations.CreateModel(
name='Fragment',
fields=[
('id', models.BigAutoField(help_text='Id', primary_key=True, serialize=False, verbose_name='Id')),
('remark', models.CharField(blank=True, help_text='描述', max_length=255, null=True, verbose_name='描述')),
('update_datetime', models.DateField(auto_now=True, help_text='修改时间', null=True, verbose_name='修改时间')),
('create_datetime', models.DateField(auto_now_add=True, help_text='创建时间', null=True, verbose_name='创建时间')),
('sort', models.IntegerField(blank=True, default=1, help_text='显示排序', null=True, verbose_name='显示排序')),
('name', models.CharField(max_length=128, verbose_name='片段名称-必须和文件名一致')),
('belong_doc', models.PositiveSmallIntegerField(choices=[(1, apps.dict.fragment.enums.DocNameEnum['dg']), (2, apps.dict.fragment.enums.DocNameEnum['sm']), (3, apps.dict.fragment.enums.DocNameEnum['jl']), (4, apps.dict.fragment.enums.DocNameEnum['hsm']), (5, apps.dict.fragment.enums.DocNameEnum['hjl']), (6, apps.dict.fragment.enums.DocNameEnum['bg']), (7, apps.dict.fragment.enums.DocNameEnum['wtd'])], verbose_name='所属文档')),
('field_seq', models.CharField(max_length=64, verbose_name='用户字段表的顺序')),
('is_main', models.BooleanField(default=False, verbose_name='是否替换磁盘的片段')),
('project', models.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, related_name='frag', related_query_name='qFrag', to='project.project')),
],
options={
'verbose_name': '文档片段',
'verbose_name_plural': '文档片段',
'db_table': 'fragment_core',
'ordering': ('-create_datetime', '-id'),
},
),
migrations.CreateModel(
name='PictureField',
fields=[
('id', models.BigAutoField(help_text='Id', primary_key=True, serialize=False, verbose_name='Id')),
('remark', models.CharField(blank=True, help_text='描述', max_length=255, null=True, verbose_name='描述')),
('update_datetime', models.DateField(auto_now=True, help_text='修改时间', null=True, verbose_name='修改时间')),
('create_datetime', models.DateField(auto_now_add=True, help_text='创建时间', null=True, verbose_name='创建时间')),
('sort', models.IntegerField(blank=True, default=1, help_text='显示排序', null=True, verbose_name='显示排序')),
('name', models.CharField(max_length=64, verbose_name='字段名称-字母')),
('img', models.ImageField(upload_to='field_images', verbose_name='图片')),
('frag', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='uPFeild', related_query_name='uPQField', to='dict.fragment')),
],
options={
'verbose_name': '图片',
'verbose_name_plural': '图片',
'db_table': 'fragment_field_picture',
'ordering': ('-create_datetime', '-id'),
},
),
migrations.CreateModel(
name='TableField',
fields=[
('id', models.BigAutoField(help_text='Id', primary_key=True, serialize=False, verbose_name='Id')),
('remark', models.CharField(blank=True, help_text='描述', max_length=255, null=True, verbose_name='描述')),
('update_datetime', models.DateField(auto_now=True, help_text='修改时间', null=True, verbose_name='修改时间')),
('create_datetime', models.DateField(auto_now_add=True, help_text='创建时间', null=True, verbose_name='创建时间')),
('sort', models.IntegerField(blank=True, default=1, help_text='显示排序', null=True, verbose_name='显示排序')),
('name', models.CharField(max_length=64, verbose_name='字段名称-字母')),
('headers', models.CharField(blank=True, max_length=1024, null=True, verbose_name='表头')),
('text', models.TextField(blank=True, null=True)),
('frag', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='uBFeild', related_query_name='uBQField', to='dict.fragment')),
],
options={
'verbose_name': '图片',
'verbose_name_plural': '图片',
'db_table': 'fragment_field_table',
'ordering': ('-create_datetime', '-id'),
},
),
migrations.CreateModel(
name='TextField',
fields=[
('id', models.BigAutoField(help_text='Id', primary_key=True, serialize=False, verbose_name='Id')),
('remark', models.CharField(blank=True, help_text='描述', max_length=255, null=True, verbose_name='描述')),
('update_datetime', models.DateField(auto_now=True, help_text='修改时间', null=True, verbose_name='修改时间')),
('create_datetime', models.DateField(auto_now_add=True, help_text='创建时间', null=True, verbose_name='创建时间')),
('sort', models.IntegerField(blank=True, default=1, help_text='显示排序', null=True, verbose_name='显示排序')),
('name', models.CharField(max_length=64, verbose_name='字段名称-字母')),
('text', models.TextField(verbose_name='多行文本段落')),
('frag', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='uTFeild', related_query_name='uTQField', to='dict.fragment')),
],
options={
'verbose_name': '储存当行文本',
'verbose_name_plural': '储存当行文本',
'db_table': 'fragment_field_text',
'ordering': ('-create_datetime', '-id'),
},
),
migrations.CreateModel(
name='WordField',
fields=[
('id', models.BigAutoField(help_text='Id', primary_key=True, serialize=False, verbose_name='Id')),
('remark', models.CharField(blank=True, help_text='描述', max_length=255, null=True, verbose_name='描述')),
('update_datetime', models.DateField(auto_now=True, help_text='修改时间', null=True, verbose_name='修改时间')),
('create_datetime', models.DateField(auto_now_add=True, help_text='创建时间', null=True, verbose_name='创建时间')),
('sort', models.IntegerField(blank=True, default=1, help_text='显示排序', null=True, verbose_name='显示排序')),
('name', models.CharField(max_length=64, verbose_name='字段名称-字母')),
('word', models.CharField(max_length=1024, verbose_name='单行文本')),
('frag', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='uWFeild', related_query_name='uWQField', to='dict.fragment')),
],
options={
'verbose_name': '储存当行文本',
'verbose_name_plural': '储存当行文本',
'db_table': 'fragment_field_word',
'ordering': ('-create_datetime', '-id'),
},
),
migrations.DeleteModel(
name='UserDictField',
),
migrations.AddConstraint(
model_name='fragment',
constraint=models.UniqueConstraint(fields=('name', 'belong_doc'), name='unique_name_belong_doc'),
),
]

View File

@@ -0,0 +1,59 @@
# Generated by Django 4.2.13 on 2024-07-25 18:21
from django.db import migrations, models
import django.db.models.deletion
import tinymce.models
class Migration(migrations.Migration):
dependencies = [
('project', '0003_alter_design_protocal'),
('dict', '0003_fragment_picturefield_tablefield_textfield_wordfield_and_more'),
]
operations = [
migrations.RemoveField(
model_name='tablefield',
name='frag',
),
migrations.RemoveField(
model_name='textfield',
name='frag',
),
migrations.RemoveField(
model_name='wordfield',
name='frag',
),
migrations.RemoveField(
model_name='fragment',
name='field_seq',
),
migrations.AddField(
model_name='fragment',
name='content',
field=tinymce.models.HTMLField(blank=True, help_text='文档片段的富文本', null=True, verbose_name='片段富文本'),
),
migrations.AlterField(
model_name='fragment',
name='belong_doc',
field=models.PositiveSmallIntegerField(choices=[(1, 'dg'), (2, 'sm'), (3, 'jl'), (4, 'hsm'), (5, 'hjl'), (6, 'bg'), (7, 'wtd')], verbose_name='所属文档'),
),
migrations.AlterField(
model_name='fragment',
name='project',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='frag', related_query_name='qFrag', to='project.project'),
),
migrations.DeleteModel(
name='PictureField',
),
migrations.DeleteModel(
name='TableField',
),
migrations.DeleteModel(
name='TextField',
),
migrations.DeleteModel(
name='WordField',
),
]

View File

@@ -0,0 +1,21 @@
# Generated by Django 4.2.16 on 2024-10-16 14:13
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('dict', '0004_remove_tablefield_frag_remove_textfield_frag_and_more'),
]
operations = [
migrations.RemoveConstraint(
model_name='fragment',
name='unique_name_belong_doc',
),
migrations.AddConstraint(
model_name='fragment',
constraint=models.UniqueConstraint(fields=('name', 'belong_doc', 'project_id'), name='unique_name_belong_doc'),
),
]

View File

@@ -0,0 +1,25 @@
# Generated by Django 4.2.17 on 2024-12-13 17:52
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('dict', '0005_remove_fragment_unique_name_belong_doc_and_more'),
]
operations = [
migrations.RemoveConstraint(
model_name='fragment',
name='unique_name_belong_doc',
),
migrations.RemoveField(
model_name='fragment',
name='belong_doc',
),
migrations.AddConstraint(
model_name='fragment',
constraint=models.UniqueConstraint(fields=('name', 'project_id'), name='unique_name'),
),
]

View File

63
apps/dict/models.py Normal file
View File

@@ -0,0 +1,63 @@
from django.db import models
from utils.models import CoreModel
from apps.project.models import Project
from tinymce.models import HTMLField
# ~~~~~~~~~~~~~字典以及字典item~~~~~~~~~~~~~
class Dict(CoreModel):
objects = models.Manager()
name = models.CharField(max_length=100, blank=True, null=True, verbose_name="字典名称", help_text="字典名称")
code = models.CharField(max_length=100, blank=True, null=True, verbose_name="编码", help_text="编码")
status = models.CharField(max_length=8, blank=True, null=True, verbose_name="状态", help_text="状态", default='1')
remark = models.CharField(max_length=2000, blank=True, null=True, verbose_name="备注", help_text="备注")
def __str__(self):
return f'字典名称:{self.name}-字典类码:{self.code}'
class Meta:
db_table = 'system_dict'
verbose_name = "字典表"
verbose_name_plural = verbose_name
ordering = ('-create_datetime',)
class DictItem(CoreModel):
objects = models.Manager()
title = models.CharField(max_length=100, blank=True, null=True, verbose_name="显示名称", help_text="显示名称")
key = models.CharField(max_length=100, blank=True, null=True, verbose_name="实际值", help_text="实际值")
show_title = models.CharField(max_length=64, blank=True, verbose_name="类型转文字", help_text="类型转文字")
status = models.CharField(max_length=8, blank=True, null=True, verbose_name="状态", help_text="状态", default='1')
dict = models.ForeignKey(to="Dict", db_constraint=False, related_name="dictItem", on_delete=models.CASCADE,
help_text="字典")
remark = models.CharField(max_length=2000, blank=True, null=True, verbose_name="备注", help_text="备注")
# 针对依据文件的字段
doc_name = models.CharField(max_length=64, blank=True, null=True, verbose_name="文档名称", help_text="文档名称")
publish_date = models.CharField(max_length=64, blank=True, null=True, verbose_name="发布日期", help_text="发布日期")
source = models.CharField(max_length=32, blank=True, null=True, verbose_name='来源', help_text="来源")
def __str__(self):
return f'字典项名称:{self.title}-字典项显示名称:{self.show_title}'
class Meta:
db_table = 'system_dict_item'
verbose_name = "字典表item表"
verbose_name_plural = verbose_name
ordering = ('-create_datetime',)
# ~~~~~~~~~~~~~用户文档片段~~~~~~~~~~~~~
# fragment表
class Fragment(CoreModel):
name = models.CharField(verbose_name='片段名称-必须和文件名一致', max_length=128)
is_main = models.BooleanField(default=False, verbose_name='是否替换磁盘的片段')
content = HTMLField(null=True, blank=True, verbose_name='片段富文本', help_text='文档片段的富文本')
# 关联的项目
project = models.ForeignKey(Project, related_name='frag', related_query_name='qFrag', on_delete=models.CASCADE)
class Meta:
db_table = 'fragment_core'
verbose_name = '文档片段'
verbose_name_plural = verbose_name
ordering = ('-create_datetime', '-id')
# 片段名称name和所属产品文档联合唯一
constraints = [
models.UniqueConstraint(fields=['name', 'project_id'], name='unique_name')
]

109
apps/dict/schema.py Normal file
View File

@@ -0,0 +1,109 @@
from ninja_schema import ModelSchema
from apps.dict.models import Dict, DictItem
from apps.project.models import Contact, Abbreviation
from ninja import Field, Schema
from typing import List, Union
class DictOut(ModelSchema):
class Config:
model = Dict
include = ('id', 'code', 'name', 'remark', 'status', 'update_datetime')
class DictItemOut(ModelSchema):
class Config:
model = DictItem
include = (
'id', 'update_datetime', 'sort', 'title', 'key', 'status', 'remark', 'show_title', 'doc_name',
'publish_date',
'source')
class DictIndexInput(Schema):
name: str = Field(None, alias='name')
remark: str = Field(None, alias='remark')
code: str = Field(None, alias='code')
status: str = Field(None, alias='status')
update_datetime_start: str = Field(None, alias='update_datetime[0]')
update_datetime_end: str = Field(None, alias='update_datetime[1]')
class ChangeStautsSchemaInput(Schema):
id: int = Field(None, alias='id')
status: Union[str, int] = Field(None, alias='status')
class DictItemInput(Schema):
dict_id: int = Field(None, alias='id')
title: str = Field(None, alias='title')
key: str = Field(None, alias='key')
status: str = Field(None, alias='status')
show_title: str = Field(None, alias='show_title')
update_datetime_start: str = Field(None, alias='update_datetime[0]')
update_datetime_end: str = Field(None, alias='update_datetime[1]')
class DictItemChangeSrotInput(Schema):
id: int = Field(None, alias='id')
numberName: str = Field(None, alias='numberName')
numberValue: int = Field(None, alias='numberValue')
class DictItemCreateInputSchema(Schema):
dict_id: int = Field(None, alias='id')
remark: str = Field(None, alias='remark')
sort: int = Field(None, alias='sort')
status: str = Field(None, alias='status')
title: str = Field(None, alias='title')
show_title: str = Field(None, alias='show_title')
doc_name: str = Field(None, alias='doc_name')
publish_date: str = Field(None, alias='publish_date')
source: str = Field(None, alias='source')
# 定义快速新增依据标注接口
class DictStdItemCreateInputSchema(Schema):
code: str = Field(None, alias='code')
remark: str = Field(None, alias='remark')
sort: int = Field(None, alias='sort')
status: str = Field(None, alias='status')
title: str = Field(None, alias='title')
show_title: str = Field(None, alias='show_title')
doc_name: str = Field(None, alias='doc_name')
publish_date: str = Field(None, alias='publish_date')
source: str = Field(None, alias='source')
# 定义快速新增DictItem的接口
class DictItemFastCreateInputSchema(Schema):
code: str = Field(alias='code') # Dict的code字段
title: str = Field("", alias='title')
class DictItemUpdateInputSchema(Schema):
remark: str = Field(None, alias='remark')
sort: int = Field(None, alias='sort')
status: str = Field(None, alias='status')
title: str = Field(None, alias='title')
show_title: str = Field(None, alias='show_title')
doc_name: str = Field(None, alias='doc_name')
publish_date: str = Field(None, alias='publish_date')
source: str = Field(None, alias='source')
# 删除schema
class DeleteSchema(Schema):
ids: List[int]
#############公司信息处理##############
class ContactOut(ModelSchema):
class Config:
model = Contact
include = ('id', 'entrust_person', 'name', 'refer_name', 'key', 'update_datetime', 'addr')
class ContactListInputSchema(Schema):
key: Union[str, int] = Field(None, alias='key')
name: str = Field(None, alias='name')
refer_name: str = Field(None, alias='refer_name')
entrust_person: str = Field(None, alias='entrust_person')
addr: str = Field(None, alias='addr')
#############缩略语处理##############
class AbbreviationOut(ModelSchema):
class Config:
model = Abbreviation
include = ('id', 'title', 'des')
class AbbreviationListInputSchema(Schema):
title: str = Field(None, alias='title')
des: str = Field(None, alias='des')

3
apps/dict/tests.py Normal file
View File

@@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

6
apps/dict/throttle.py Normal file
View File

@@ -0,0 +1,6 @@
from ninja_extra.throttling import UserRateThrottle
# ~~~~~~~~~~~注意当前只对缩略语添加1分钟一次用于Jmeter测试记得删除~~~~~~~~~~~
# 限流类 - 只能一分钟请求5次
class User60MinRateThrottle(UserRateThrottle):
rate = '60/min'
scope = 'minutes'

3
apps/dict/views.py Normal file
View File

@@ -0,0 +1,3 @@
from django.shortcuts import render
# Create your views here.