From cd479360c1a1ec72431b41538725627737a8f926 Mon Sep 17 00:00:00 2001
From: dayezi <1372755472@qq.com>
Date: Sun, 2 Jun 2024 11:42:59 +0800
Subject: [PATCH 01/10] =?UTF-8?q?=F0=9F=93=83=20docs(welcomedocs):=20?=
=?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=90=AF=E5=8A=A8=E6=AC=A2=E8=BF=8E=E8=AF=AD?=
=?UTF-8?q?=E4=B8=AD=E7=9A=84=E6=96=87=E6=A1=A3=E9=93=BE=E6=8E=A5?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
frontend/build/info.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/frontend/build/info.ts b/frontend/build/info.ts
index 2ca6aee..4843e79 100644
--- a/frontend/build/info.ts
+++ b/frontend/build/info.ts
@@ -7,7 +7,7 @@ import boxen, { type Options as BoxenOptions } from "boxen";
dayjs.extend(duration);
const welcomeMessage = gradientString("cyan", "magenta").multiline(
- `您好! 欢迎使用 pure-admin 开源项目\n我们为您精心准备了下面两个贴心的保姆级文档\nhttps://yiming_chang.gitee.io/pure-admin-doc\nhttps://pure-admin-utils.netlify.app`
+ `您好! 欢迎使用 pure-admin 开源项目\n我们为您精心准备了下面两个贴心的保姆级文档\nhttps://pure-admin.github.io/pure-admin-doc/\nhttps://pure-admin-utils.netlify.app`
);
const boxenOptions: BoxenOptions = {
From 3fa53df09fe3f07338e90410d1c70a009e2c7bc2 Mon Sep 17 00:00:00 2001
From: dayezi <1372755472@qq.com>
Date: Mon, 3 Jun 2024 09:40:25 +0800
Subject: [PATCH 02/10] =?UTF-8?q?=F0=9F=90=9E=20fix(bug):=20=E4=BF=AE?=
=?UTF-8?q?=E5=A4=8D=E4=B8=80=E4=BA=9B=E5=B7=B2=E7=9F=A5=E9=97=AE=E9=A2=98?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
1. 修复获取refreshToken时的时间判断问题
2. 修改部分报错问题
3. 修改前端物资交接时的物资显示数据字段以及正确的判断逻辑
---
backend/app/api/v1/base/base.py | 2 +
frontend/src/types/base.ts | 1 +
frontend/src/views/admin/MaterialMeta.vue | 2 +
frontend/src/views/admin/OperationLogs.vue | 6 +-
frontend/src/views/glb/material.vue | 64 +++++++++-------------
5 files changed, 34 insertions(+), 41 deletions(-)
diff --git a/backend/app/api/v1/base/base.py b/backend/app/api/v1/base/base.py
index a7f4b87..1f9e7a2 100644
--- a/backend/app/api/v1/base/base.py
+++ b/backend/app/api/v1/base/base.py
@@ -65,6 +65,8 @@ async def login_access_token(credentials: CredentialsSchema):
async def refresh_token(refreshToken: refreshTokenSchema):
try:
payload = decode_access_token(refreshToken.refreshToken)
+ if payload.exp < datetime.now():
+ raise ExpiredSignatureError
except ExpiredSignatureError:
return FailAuth(msg="refreshToken已过期")
access_token_expires = timedelta(minutes=settings.JWT_ACCESS_TOKEN_EXPIRE_MINUTES)
diff --git a/frontend/src/types/base.ts b/frontend/src/types/base.ts
index 40bcf24..6c0e5c3 100644
--- a/frontend/src/types/base.ts
+++ b/frontend/src/types/base.ts
@@ -10,6 +10,7 @@ export type MaterialItem = {
depart?: string;
position: string;
number: number;
+ nowNumber?: number;
checking?: number;
borrowing?: number;
borrowed?: number;
diff --git a/frontend/src/views/admin/MaterialMeta.vue b/frontend/src/views/admin/MaterialMeta.vue
index 121377c..a8512b9 100644
--- a/frontend/src/views/admin/MaterialMeta.vue
+++ b/frontend/src/views/admin/MaterialMeta.vue
@@ -104,6 +104,8 @@ const columns: TableColumnList = [
{ label: "名称", prop: "name" },
{ label: "型号", prop: "model", width: "200" },
{ label: "数量", prop: "number", width: "100" },
+ { label: "借出数量", prop: "borrowed", width: "100" },
+ { label: "送检数量", prop: "checking", width: "100" },
{
label: "操作",
prop: "modify",
diff --git a/frontend/src/views/admin/OperationLogs.vue b/frontend/src/views/admin/OperationLogs.vue
index 5b1f88f..a796af4 100644
--- a/frontend/src/views/admin/OperationLogs.vue
+++ b/frontend/src/views/admin/OperationLogs.vue
@@ -117,7 +117,7 @@ const columns: TableColumnList = [
size={props.size}
style={tagStyle.value(row.number == row.nowNumber ? 1 : 0)}
>
- {row.number === row.nowNumber ? "正确" : "错误"}
+ {row.number === row.nowNumber ? "正常" : "异常"}
)
},
@@ -237,8 +237,8 @@ function handleSelectionChange(val) {
clearable
class="!w-[150px]"
>
-
-
+
+
diff --git a/frontend/src/views/glb/material.vue b/frontend/src/views/glb/material.vue
index eba3a84..9277c7e 100644
--- a/frontend/src/views/glb/material.vue
+++ b/frontend/src/views/glb/material.vue
@@ -2,7 +2,6 @@
import { ref, reactive, computed, onMounted } from "vue";
import {
getMaterialMeta,
- getGlbAttentionList,
getGlbDutyInfo,
dutyOver,
getLatestNote
@@ -11,6 +10,8 @@ import { useUserStoreHook } from "@/store/modules/user";
import { successNotification, errorNotification } from "@/utils/notification";
import formatCurrentTime from "@/utils/formatDatetime";
import { getDutyOverList } from "@/api/admin";
+import PureTable from "@pureadmin/table";
+import type { MaterialItem } from "@/types/base";
defineOptions({
name: "GlbMaterial"
@@ -24,22 +25,8 @@ enum StepStatus {
Warning = "warning",
Error = "error"
}
-interface tableDataRow {
- id?: number;
- uuid?: string;
- name: string;
- model: string;
- position: string;
- number: string;
- nowNumber?: number;
- created_at?: string;
- updated_at?: string;
- dutyPerson?: string;
- dutyPersonDepart?: string;
- depart?: string;
- dutyDate?: string;
-}
-interface tableData extends Array {}
+
+interface tableData extends Array {}
const columns: TableColumnList = [
{ label: "序号", type: "index", width: "60" },
@@ -47,18 +34,14 @@ const columns: TableColumnList = [
{ label: "名称", prop: "name" },
{ label: "型号", prop: "model", width: "200" },
{ label: "数量", prop: "number", width: "100" },
+ { label: "外借数量", prop: "borrowed", width: "100" },
+ { label: "送检数量", prop: "checking", width: "100" },
{
label: "当前数量",
width: "150",
prop: "nowNumber",
cellRenderer: ({ row }) => (
- <>
-
- >
+
)
},
{
@@ -66,16 +49,14 @@ const columns: TableColumnList = [
prop: "confirm",
width: "100",
cellRenderer: ({ row }) => (
- <>
- handleConfirm(row)}
- plain
- >
- 确认
-
- >
+ handleConfirm(row)}
+ plain
+ >
+ 确认
+
)
}
];
@@ -117,19 +98,26 @@ const confirmedData: tableData = reactive([]);
const step1Init = ref(true);
const step1Status = computed(() => {
- return confirmedData.every(item => item.nowNumber === Number(item.number))
+ return confirmedData.every(
+ item => item.nowNumber === item.number - item.borrowed - item.checking
+ )
? StepStatus.Success
: StepStatus.Error;
});
const handleConfirm = row => {
- row.nowNumber = Number(row.number);
+ row.nowNumber = Number(row.number) - row.borrowed - row.checking;
step1Init.value = false;
};
+const confirmBtnStatus = (row): "success" | "warning" => {
+ return row.nowNumber == row.number - row.borrowed - row.checking
+ ? "success"
+ : "warning";
+};
const handleConfirmAll = () => {
// 确认所有
confirmedData.forEach(row => {
- row.nowNumber = Number(row.number);
+ row.nowNumber = row.number - row.borrowed - row.checking;
step1Init.value = false;
});
};
@@ -181,7 +169,7 @@ const handoverConfirm = () => {
const handover = () => {
const date = formatCurrentTime();
let data = {
- materialData: confirmedData.map((data: tableDataRow) => {
+ materialData: confirmedData.map((data: MaterialItem) => {
return {
name: data.name,
model: data.model,
From 41f6aeed2bba8df92ee9d67a45794bd331d351c9 Mon Sep 17 00:00:00 2001
From: dayezi <1372755472@qq.com>
Date: Mon, 17 Jun 2024 22:33:42 +0800
Subject: [PATCH 03/10] =?UTF-8?q?=E2=9C=A8=20feat(key):=20=E9=92=A5?=
=?UTF-8?q?=E5=8C=99=E7=89=A9=E8=B5=84=E7=9A=84=E5=8E=9F=E6=95=B0=E6=8D=AE?=
=?UTF-8?q?=E5=B1=95=E7=A4=BA=E5=92=8C=E6=95=B0=E6=8D=AE=E6=96=B0=E5=A2=9E?=
=?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=88=A0=E9=99=A4?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
backend/app/api/v1/base/base.py | 2 +-
backend/app/api/v1/material/material.py | 29 ++--
backend/app/controllers/area.py | 16 ++
backend/app/controllers/materialType.py | 16 ++
backend/app/models/__init__.py | 2 +
backend/app/models/area.py | 18 ++
backend/app/models/borrowed.py | 1 +
backend/app/models/material.py | 13 +-
backend/app/models/materialType.py | 19 +++
backend/app/models/users.py | 2 +
backend/app/schemas/area.py | 18 ++
backend/app/schemas/materialType.py | 19 +++
frontend/src/api/material.ts | 11 +-
frontend/src/store/modules/metaArea.ts | 0
frontend/src/store/modules/metaType.ts | 0
frontend/src/types/base.ts | 3 +-
frontend/src/views/admin/MaterialMeta.vue | 191 ++++++++++++++--------
frontend/src/views/admin/utils/types.ts | 5 +
frontend/src/views/glb/material.vue | 2 +-
frontend/src/views/welcome/index.vue | 2 +-
20 files changed, 271 insertions(+), 98 deletions(-)
create mode 100644 backend/app/controllers/area.py
create mode 100644 backend/app/controllers/materialType.py
create mode 100644 backend/app/models/area.py
create mode 100644 backend/app/models/materialType.py
create mode 100644 backend/app/schemas/area.py
create mode 100644 backend/app/schemas/materialType.py
create mode 100644 frontend/src/store/modules/metaArea.ts
create mode 100644 frontend/src/store/modules/metaType.ts
diff --git a/backend/app/api/v1/base/base.py b/backend/app/api/v1/base/base.py
index 1f9e7a2..a48765f 100644
--- a/backend/app/api/v1/base/base.py
+++ b/backend/app/api/v1/base/base.py
@@ -65,7 +65,7 @@ async def login_access_token(credentials: CredentialsSchema):
async def refresh_token(refreshToken: refreshTokenSchema):
try:
payload = decode_access_token(refreshToken.refreshToken)
- if payload.exp < datetime.now():
+ if payload.exp.timestamp() < datetime.now().timestamp():
raise ExpiredSignatureError
except ExpiredSignatureError:
return FailAuth(msg="refreshToken已过期")
diff --git a/backend/app/api/v1/material/material.py b/backend/app/api/v1/material/material.py
index 8d13906..be52b39 100644
--- a/backend/app/api/v1/material/material.py
+++ b/backend/app/api/v1/material/material.py
@@ -34,12 +34,13 @@ async def duty_over(data: DutyOverInfo):
@router.get("/meta", summary="获取物资源数据")
async def get_meta(
- depart: str = Query("glb", description="物资部门"),
+ area: str = Query("glb", description="物资区域"),
+ metaType: str = Query("", description="物资类型"),
page: int = Query(1, description="页码"),
page_size: int = Query(1000, description="每页数量"),
name: str = Query("", description="物资名称"),
):
- q = Q(depart__contains=depart)
+ q = Q(Q(area__contains=area), Q(type__contains=metaType))
if name:
q &= Q(name__contains=name)
@@ -49,11 +50,11 @@ async def get_meta(
@router.get("/all_meta", summary="获取所有物资源数据")
-async def get_all_meta(depart: str = Query("glb", description="物资部门")):
- q = Q()
- if depart:
- q &= Q(depart__contains=depart)
-
+async def get_all_meta(
+ area: str = Query("glb", description="物资区域"),
+ metaType: str = Query("", description="物资类型")
+):
+ q = Q(Q(area_contains=area), Q(type__contains=metaType))
material_objs = await materialController.all(search=q)
data = [await obj.to_dict() for obj in material_objs]
return Success(data=data)
@@ -62,7 +63,7 @@ async def get_all_meta(depart: str = Query("glb", description="物资部门")):
@router.post("/add_meta", summary="添加或修改物资源数据")
async def add_meta(data: Union[MaterialCreate, MaterialUpdate]):
if hasattr(data, "id"):
- result: Material = await materialController.update(data.id, data.update_dict())
+ result: Material = await materialController.update(data.id, data)
else:
data: dict = data.model_dump()
data["uuid"] = generate_uuid(data["name"])
@@ -94,7 +95,7 @@ async def get_glb_duty_info():
@router.get("/glb_attention", summary="获取隔离办物资注意事项")
async def get_glb_attention():
- q = Q(depart__contains="glb")
+ q = Q(area__contains="glb")
total, note_objs = await materialAttentionController.list(page=1, page_size=100, search=q)
data = [await obj.to_dict() for obj in note_objs]
return Success(msg="隔离办注意事项", data=data)
@@ -102,7 +103,7 @@ async def get_glb_attention():
@router.get("/glb_latest_note", summary="获取隔离办最近一条备注")
async def get_glb_latest_note():
- q = Q(depart__contains="glb")
+ q = Q(area__contains="glb")
data = await dutyNotesController.latest(search=q)
if data:
data = await data.to_dict()
@@ -117,7 +118,7 @@ async def get_fk_list(
page_size: int = Query(1000, description="每页数量"),
name: str = Query("", description="物资名称")
):
- q = Q(depart__contains="fk")
+ q = Q(area__contains="fk")
if name:
q &= Q(name__contains=name)
@@ -132,7 +133,7 @@ async def get_fk_list(
page_size: int = Query(1000, description="每页数量"),
name: str = Query("", description="物资名称")
):
- q = Q(depart__contains="wk")
+ q = Q(area__contains="wk")
if name:
q &= Q(name__contains=name)
@@ -143,7 +144,7 @@ async def get_fk_list(
@router.get("/duty_over_list/list", summary="获取接班清单")
async def get_duty_over_list(area: str = Query("glb", description="部门")):
- q = Q(depart__contains=area)
+ q = Q(area__contains=area)
total, duty_over_list_objs = await dutyOverListController.list(page=1, page_size=1000, search=q)
data = [await obj.to_dict() for obj in duty_over_list_objs]
return SuccessExtra(msg="接班清单获取成功", data=data, total=total, page=1, pageSize=1000)
@@ -155,7 +156,7 @@ async def update_duty_over_list(data: list[dict], area: str = Query("glb", descr
if item.get("id"):
await dutyOverListController.update(item["id"], item)
else:
- item["depart"] = area
+ item["area"] = area
await dutyOverListController.create(item)
return Success(msg="更新成功")
diff --git a/backend/app/controllers/area.py b/backend/app/controllers/area.py
new file mode 100644
index 0000000..0e87a15
--- /dev/null
+++ b/backend/app/controllers/area.py
@@ -0,0 +1,16 @@
+# coding=utf-8
+# @FileName :area.py
+# @Time :2024/6/9 上午9:53
+# @Author :dayezi
+from app.core.crud import CRUDBase
+
+from app.models import MaterialArea
+from app.schemas.area import MaterialAreaCreate, MaterialAreaUpdate
+
+
+class MaterialAreaController(CRUDBase[MaterialArea, MaterialAreaCreate, MaterialAreaUpdate]):
+ def __init__(self):
+ super().__init__(model=MaterialArea)
+
+
+areaController = MaterialAreaController()
diff --git a/backend/app/controllers/materialType.py b/backend/app/controllers/materialType.py
new file mode 100644
index 0000000..cd38f7f
--- /dev/null
+++ b/backend/app/controllers/materialType.py
@@ -0,0 +1,16 @@
+# coding=utf-8
+# @FileName :materialType.py
+# @Time :2024/6/7 下午3:30
+# @Author :dayezi
+from app.core.crud import CRUDBase
+
+from app.models import MaterialType
+from app.schemas.materialType import MaterialTypeCreate, MaterialTypeUpdate
+
+
+class MaterialTypeController(CRUDBase[MaterialType, MaterialTypeCreate, MaterialTypeUpdate]):
+ def __init__(self):
+ super().__init__(model=MaterialType)
+
+
+materialTypeController = MaterialTypeController()
diff --git a/backend/app/models/__init__.py b/backend/app/models/__init__.py
index da7c5ed..441cadf 100644
--- a/backend/app/models/__init__.py
+++ b/backend/app/models/__init__.py
@@ -3,3 +3,5 @@
from .material import *
from .dutyLog import *
from .borrowed import *
+from .materialType import *
+from .area import *
diff --git a/backend/app/models/area.py b/backend/app/models/area.py
new file mode 100644
index 0000000..9d452ae
--- /dev/null
+++ b/backend/app/models/area.py
@@ -0,0 +1,18 @@
+# coding=utf-8
+# @FileName :area.py
+# @Time :2024/6/7 下午3:25
+# @Author :dayezi
+from tortoise import fields
+
+from .base import BaseModel, TimestampMixin, UUIDModel
+
+
+class MaterialArea(BaseModel, TimestampMixin, UUIDModel):
+ key = fields.CharField(max_length=20, description="物资区域关键字")
+ name = fields.CharField(max_length=50, description="物资区域名称")
+
+ class Meta:
+ table = "material_area"
+
+ class PydanticMeta:
+ exclude = "id"
diff --git a/backend/app/models/borrowed.py b/backend/app/models/borrowed.py
index 92c36b7..c8dbf9c 100644
--- a/backend/app/models/borrowed.py
+++ b/backend/app/models/borrowed.py
@@ -13,6 +13,7 @@ class Borrowed(BaseModel, UUIDModel):
uuid = fields.UUIDField(pk=False, description="借用人uuid")
phone = fields.CharField(max_length=20, description="借用人手机号")
userDepart = fields.CharField(max_length=20, description="借用人部门")
+ reason = fields.CharField(max_length=200, description="借用原因")
borrowTime = fields.DatetimeField(auto_now_add=True, description="借用时间")
borrowApproveStatus = fields.BooleanField(default=False, description="借用审批状态,False为未审批,True未已审批")
borrowApproveWhether = fields.BooleanField(null=True, description="借用通过状态,False为驳回,True为通过")
diff --git a/backend/app/models/material.py b/backend/app/models/material.py
index c1b33ed..c3d6a77 100644
--- a/backend/app/models/material.py
+++ b/backend/app/models/material.py
@@ -1,16 +1,21 @@
from tortoise import fields
from .base import BaseModel, TimestampMixin, UUIDModel
+from .borrowed import Borrowed
class Material(BaseModel, TimestampMixin, UUIDModel):
+ type = fields.CharField(max_length=20, description="物资类型")
+ area = fields.CharField(max_length=20, description="物资所属区域")
name = fields.CharField(max_length=50, unique=True, description="物资名字")
model = fields.CharField(max_length=20, null=True, description="物资型号")
position = fields.CharField(max_length=50, description="物资位置")
- number = fields.IntField(description="物资原数量")
+ number = fields.IntField(description="物资库存数量")
checking = fields.IntField(default=0, description="物资送检数量")
borrowed = fields.IntField(default=0, description="物资外借数量")
- depart = fields.CharField(max_length=20, description="物资所属部门")
+
+ # 物资被借的信息
+ borrowedInfo: fields.ManyToManyRelation["Borrowed"]
class Meta:
table = "material"
@@ -21,7 +26,7 @@ class PydanticMeta:
class AttentionNote(BaseModel, TimestampMixin, UUIDModel):
note = fields.CharField(max_length=255, description="事项")
- depart = fields.CharField(max_length=20, description="所属部门")
+ area = fields.CharField(max_length=20, description="所属区域")
class Meta:
table = "attention_note"
@@ -31,7 +36,7 @@ class PydanticMeta:
class DutyOverList(BaseModel, TimestampMixin):
- depart = fields.CharField(max_length=20, description="部门")
+ area = fields.CharField(max_length=20, description="部门")
content = fields.CharField(max_length=255, description="交接班清单内容")
class Meta:
diff --git a/backend/app/models/materialType.py b/backend/app/models/materialType.py
new file mode 100644
index 0000000..72b4c8e
--- /dev/null
+++ b/backend/app/models/materialType.py
@@ -0,0 +1,19 @@
+# coding=utf-8
+# @FileName :materialType.py
+# @Time :2024/6/7 下午3:24
+# @Author :dayezi
+from tortoise import fields
+
+from .base import BaseModel, TimestampMixin, UUIDModel
+
+
+class MaterialType(BaseModel, TimestampMixin, UUIDModel):
+ key = fields.CharField(max_length=20, description="物资类型关键字")
+ name = fields.CharField(max_length=50, description="物资类型名称")
+
+ class Meta:
+ table = "material_type"
+
+ class PydanticMeta:
+ exclude = "id"
+
diff --git a/backend/app/models/users.py b/backend/app/models/users.py
index 9ff15c4..952dbc0 100644
--- a/backend/app/models/users.py
+++ b/backend/app/models/users.py
@@ -2,6 +2,7 @@
from .base import BaseModel, TimestampMixin, UUIDModel
from .enums import MethodType
+from .borrowed import Borrowed
class User(BaseModel, TimestampMixin, UUIDModel):
@@ -23,6 +24,7 @@ class User(BaseModel, TimestampMixin, UUIDModel):
related_name="user_depart",
null=True
)
+ borrowed: fields.ManyToManyRelation["Borrowed"]
class Meta:
table = "user"
diff --git a/backend/app/schemas/area.py b/backend/app/schemas/area.py
new file mode 100644
index 0000000..2f708ff
--- /dev/null
+++ b/backend/app/schemas/area.py
@@ -0,0 +1,18 @@
+# coding=utf-8
+# @FileName :area.py
+# @Time :2024/6/9 上午9:52
+# @Author :dayezi
+from tortoise.contrib.pydantic import pydantic_model_creator
+
+from app.models import MaterialArea
+
+
+MaterialAreaSchema = pydantic_model_creator(MaterialArea)
+
+
+class MaterialAreaCreate(MaterialAreaSchema):
+ ...
+
+
+class MaterialAreaUpdate(MaterialAreaSchema):
+ id: int
diff --git a/backend/app/schemas/materialType.py b/backend/app/schemas/materialType.py
new file mode 100644
index 0000000..a21fb93
--- /dev/null
+++ b/backend/app/schemas/materialType.py
@@ -0,0 +1,19 @@
+# coding=utf-8
+# @FileName :materialType.py
+# @Time :2024/6/7 下午3:27
+# @Author :dayezi
+from tortoise.contrib.pydantic import pydantic_model_creator
+
+from app.models import MaterialType
+
+
+MaterialTypeSchema = pydantic_model_creator(MaterialType)
+
+
+class MaterialTypeCreate(MaterialTypeSchema):
+ ...
+
+
+class MaterialTypeUpdate(MaterialTypeSchema):
+ id: int
+
diff --git a/frontend/src/api/material.ts b/frontend/src/api/material.ts
index 153c9ff..e052f34 100644
--- a/frontend/src/api/material.ts
+++ b/frontend/src/api/material.ts
@@ -9,23 +9,26 @@ import type {
import type { addResult, MaterialResult } from "@/types/admin";
export const getMaterialMeta = async (
- depart: string,
+ area: string,
+ metaType: string,
page?: number,
page_size?: number
) => {
return http.request("get", baseUrlApi("/material/meta"), {
params: {
- depart,
+ area,
+ metaType,
page,
page_size
}
});
};
-export const getAllMaterialMeta = async (depart: string) => {
+export const getAllMaterialMeta = async (area: string, metaType: string) => {
return http.request("get", baseUrlApi("/material/all_meta"), {
params: {
- depart
+ area,
+ metaType
}
});
};
diff --git a/frontend/src/store/modules/metaArea.ts b/frontend/src/store/modules/metaArea.ts
new file mode 100644
index 0000000..e69de29
diff --git a/frontend/src/store/modules/metaType.ts b/frontend/src/store/modules/metaType.ts
new file mode 100644
index 0000000..e69de29
diff --git a/frontend/src/types/base.ts b/frontend/src/types/base.ts
index 6c0e5c3..6a61c83 100644
--- a/frontend/src/types/base.ts
+++ b/frontend/src/types/base.ts
@@ -7,7 +7,8 @@ export type MaterialItem = {
uuid?: string;
name: string;
model: string;
- depart?: string;
+ type: string;
+ area: string;
position: string;
number: number;
nowNumber?: number;
diff --git a/frontend/src/views/admin/MaterialMeta.vue b/frontend/src/views/admin/MaterialMeta.vue
index a8512b9..865eddb 100644
--- a/frontend/src/views/admin/MaterialMeta.vue
+++ b/frontend/src/views/admin/MaterialMeta.vue
@@ -1,5 +1,5 @@
- test
+
+
+
+
+
+
+
+ 交班
+
+
+
+
+ 值班员:{{ dutyPerson }}
+
+ 值班科值:{{ dutyPersonDepart }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 当前备注
+
+ 复制上个班
+
+
+ 上个班备注
+
+
+
+
+
+
+
+
+
+ 确认从 {{ dutyPerson }} 接班
+
+
+
+
+
-
+
diff --git a/frontend/src/views/glb/material.vue b/frontend/src/views/glb/material.vue
index aefc68b..0b07224 100644
--- a/frontend/src/views/glb/material.vue
+++ b/frontend/src/views/glb/material.vue
@@ -2,9 +2,9 @@
import { ref, reactive, computed, onMounted } from "vue";
import {
getMaterialMeta,
- getGlbDutyInfo,
dutyOver,
- getLatestNote
+ getLatestNote,
+ getDutyInfo
} from "@/api/material";
import { useUserStoreHook } from "@/store/modules/user";
import { successNotification, errorNotification } from "@/utils/notification";
@@ -79,10 +79,10 @@ const initGlb = () => {
attention.length = 0;
attention.push(...res.data);
});
- getLatestNote().then(res => {
+ getLatestNote("glb", "tool").then(res => {
lastRemark.value = res.data.note;
});
- getGlbDutyInfo().then(res => {
+ getDutyInfo("glb", "tool").then(res => {
dutyPerson.value = res.data.dutyPerson;
dutyPersonDepart.value = res.data.dutyPersonDepart;
});
@@ -187,12 +187,11 @@ const handover = () => {
depart: "glb",
dutyDate: date
},
- dutyDate: date,
dutyPerson: useUserStoreHook()?.username,
dutyPersonDepart: useUserStoreHook()?.depart
};
handleOverBtnLoading.value = true;
- dutyOver(data)
+ dutyOver("glb", "tool", data)
.then(res => {
initGlb();
handleOverBtnLoading.value = false;
@@ -207,8 +206,8 @@ const handover = () => {
-
-
+
+
From 6572363477ea01808a5b5ef5931e4239c568d38a Mon Sep 17 00:00:00 2001
From: dayezi <1372755472@qq.com>
Date: Wed, 19 Jun 2024 15:04:23 +0800
Subject: [PATCH 06/10] =?UTF-8?q?=E2=9C=A8=20feat(key):=20=E6=96=B0?=
=?UTF-8?q?=E5=A2=9E=E9=92=A5=E5=8C=99=E4=BA=A4=E6=8E=A5=E7=8F=AD=E5=8A=9F?=
=?UTF-8?q?=E8=83=BD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
1. 新增钥匙交接班功能
2. 新增钥匙交接日志审计功能
3. 修改交接班日志录入时间为服务器时间
---
backend/app/api/v1/admin/admin.py | 5 +-
backend/app/api/v1/home/home.py | 2 +-
backend/app/api/v1/material/material.py | 2 +-
backend/app/models/base.py | 1 +
backend/app/models/dutyLog.py | 4 +-
backend/app/utils/dutyInfo.ini | 12 +-
frontend/src/api/admin.ts | 6 +-
frontend/src/types/admin.ts | 21 ++-
frontend/src/types/base.ts | 18 ++
frontend/src/views/admin/MaterialMeta.vue | 2 +-
frontend/src/views/admin/OperationLogs.vue | 54 +++++-
frontend/src/views/glb/key.vue | 186 ++++++++++++++++-----
frontend/src/views/glb/material.vue | 10 +-
frontend/src/views/welcome/index.vue | 68 +++++++-
14 files changed, 323 insertions(+), 68 deletions(-)
diff --git a/backend/app/api/v1/admin/admin.py b/backend/app/api/v1/admin/admin.py
index db69142..edf6780 100644
--- a/backend/app/api/v1/admin/admin.py
+++ b/backend/app/api/v1/admin/admin.py
@@ -42,11 +42,12 @@ async def set_db_conn(data: DbInfo, request: Request):
@router.post("/dutyLogs/search", summary="查询操作日志")
async def search_operation_logs(
data: dict,
- depart: str = Query("glb", description="部门"),
+ area: str = Query("glb", description="区域"),
+ metaType: str = Query("tool", description="工具类型"),
page: int = Query(1, description="页码"),
pageSize: int = Query(10, description="每页数量"),
):
- q = Q(depart__contains=depart)
+ q = Q(Q(area__contains=area), Q(type__contains=metaType))
status = data.get("status")
operatingTime: list = data.get("operatingTime")
if status:
diff --git a/backend/app/api/v1/home/home.py b/backend/app/api/v1/home/home.py
index 2aae197..e0738a9 100644
--- a/backend/app/api/v1/home/home.py
+++ b/backend/app/api/v1/home/home.py
@@ -31,7 +31,7 @@ async def get_home_list(
else:
q = Q(Q(material__area=area), Q(borrowApproveWhether=borrowWhether), Q(returnApproveStatus=returnStatus))
total, objs = await borrowedController.list(page=page, page_size=pageSize, search=q)
- data = [await obj.to_dict(m2m=True) for obj in objs]
+ data = [await obj.to_dict(m2m=True, exclude_fields=["password"]) for obj in objs]
return SuccessExtra(data=data, total=total, currentPage=page, pageSize=pageSize)
diff --git a/backend/app/api/v1/material/material.py b/backend/app/api/v1/material/material.py
index 4335d9d..415bc47 100644
--- a/backend/app/api/v1/material/material.py
+++ b/backend/app/api/v1/material/material.py
@@ -56,7 +56,7 @@ async def get_meta(
@router.get("/all_meta", summary="获取所有物资源数据")
async def get_all_meta(
area: str = Query("glb", description="物资区域"),
- metaType: str = Query("", description="物资类型")
+ metaType: str = Query("tool", description="物资类型")
):
q = Q(Q(area__contains=area), Q(type__contains=metaType))
material_objs = await materialController.all(search=q)
diff --git a/backend/app/models/base.py b/backend/app/models/base.py
index b9f6512..3be5492 100644
--- a/backend/app/models/base.py
+++ b/backend/app/models/base.py
@@ -33,6 +33,7 @@ async def to_dict(self, m2m: bool = False, exclude_fields: list[str] | None = No
if isinstance(v, datetime)
)
value.update((k, str(v)) for k, v in value.items() if isinstance(v, UUID))
+ value.pop("password", "xxx") # 删除用户模型中的密码字段
d[field] = values
return d
diff --git a/backend/app/models/dutyLog.py b/backend/app/models/dutyLog.py
index a7bb680..8ab7fdc 100644
--- a/backend/app/models/dutyLog.py
+++ b/backend/app/models/dutyLog.py
@@ -29,7 +29,7 @@ class Meta:
table = "dutyLogs"
class PydanticMeta:
- exclude = ("id",)
+ exclude = ("id", "dutyDate")
class DutyNotes(BaseModel):
@@ -44,6 +44,6 @@ class Meta:
table = "dutyNotes"
class PydanticMeta:
- exclude = ("id",)
+ exclude = ("id", "dutyDate")
diff --git a/backend/app/utils/dutyInfo.ini b/backend/app/utils/dutyInfo.ini
index 79c517f..5a75c91 100644
--- a/backend/app/utils/dutyInfo.ini
+++ b/backend/app/utils/dutyInfo.ini
@@ -1,12 +1,12 @@
[glb.tool]
-dutyperson = test
-dutypersondepart = eee
-takeovertime = 2024-05-07 17:15:51
+dutyperson = admin
+dutypersondepart = aaaqqqwwweee
+takeovertime = 2024-06-19 14:32:26
[glb.key]
-dutyperson = test
-dutypersondepart = eee
-takeovertime = 2024-05-07 17:15:51
+dutyperson = admin
+dutypersondepart = aaaqqqwwweee
+takeovertime = 2024-06-19 14:27:16
[wk.tool]
dutyperson = admin
diff --git a/frontend/src/api/admin.ts b/frontend/src/api/admin.ts
index 7bfec57..0e7ebdc 100644
--- a/frontend/src/api/admin.ts
+++ b/frontend/src/api/admin.ts
@@ -35,7 +35,8 @@ export const deleteDutyOverList = (id: string) => {
};
export const searchDutyLogs = (
- depart: string,
+ area: string,
+ metaType: string,
page: number,
pageSize: number,
data?: object
@@ -46,7 +47,8 @@ export const searchDutyLogs = (
{
data,
params: {
- depart,
+ area,
+ metaType,
page,
pageSize
}
diff --git a/frontend/src/types/admin.ts b/frontend/src/types/admin.ts
index d7b9130..a3076e6 100644
--- a/frontend/src/types/admin.ts
+++ b/frontend/src/types/admin.ts
@@ -1,4 +1,4 @@
-import type { BaseResult, MaterialItem } from "@/types/base";
+import type { BaseResult, MaterialItem, User } from "@/types/base";
export type addResult = BaseResult & {
data: MaterialItem;
@@ -9,3 +9,22 @@ export type MaterialResult = BaseResult & {
total: number;
data: [MaterialItem];
};
+
+export type BorrowedInfo = {
+ id: number;
+ uuid: string;
+ username: string;
+ userDepart: string;
+ phone: string;
+ reason: string;
+ material: [MaterialItem];
+ borrowing: number;
+ borrowTime: string;
+ borrowApproveStatus: boolean;
+ borrowApproveTime: string;
+ borrowApproveUser: [User];
+ borrowApproveWhether: boolean;
+ returnApproveStatus: boolean;
+ returnApproveTime: string;
+ returnApproveUser: [User];
+};
diff --git a/frontend/src/types/base.ts b/frontend/src/types/base.ts
index 6a61c83..a78383a 100644
--- a/frontend/src/types/base.ts
+++ b/frontend/src/types/base.ts
@@ -18,3 +18,21 @@ export type MaterialItem = {
created_at?: string;
updated_at?: string;
};
+
+export type User = {
+ id: number;
+ uuid: string;
+ username: string;
+ nickname: string;
+ email: string;
+ phone: string;
+ avatar?: string;
+ depart_id: number;
+ is_superuser: boolean;
+ remark: string;
+ sex: number;
+ status: number;
+ created_at: string;
+ updated_at: string;
+ last_login: string;
+};
diff --git a/frontend/src/views/admin/MaterialMeta.vue b/frontend/src/views/admin/MaterialMeta.vue
index 1fd1bb5..114b168 100644
--- a/frontend/src/views/admin/MaterialMeta.vue
+++ b/frontend/src/views/admin/MaterialMeta.vue
@@ -372,7 +372,7 @@ function openDialog(area: string) {
查看注意事项
diff --git a/frontend/src/views/admin/OperationLogs.vue b/frontend/src/views/admin/OperationLogs.vue
index a796af4..1108bfa 100644
--- a/frontend/src/views/admin/OperationLogs.vue
+++ b/frontend/src/views/admin/OperationLogs.vue
@@ -1,6 +1,6 @@
@@ -137,15 +250,12 @@ const initInfo = () => {
-
+
{
-
+
@@ -173,7 +280,6 @@ const initInfo = () => {
maxlength="510"
:show-word-limit="true"
style="width: 35vw"
- @blur="burlHandle"
/>
复制上个班 {
diff --git a/frontend/src/views/glb/material.vue b/frontend/src/views/glb/material.vue
index 0b07224..8fb1e2b 100644
--- a/frontend/src/views/glb/material.vue
+++ b/frontend/src/views/glb/material.vue
@@ -8,7 +8,6 @@ import {
} from "@/api/material";
import { useUserStoreHook } from "@/store/modules/user";
import { successNotification, errorNotification } from "@/utils/notification";
-import formatCurrentTime from "@/utils/formatDatetime";
import { getDutyOverList } from "@/api/admin";
import PureTable from "@pureadmin/table";
import type { MaterialItem } from "@/types/base";
@@ -167,7 +166,6 @@ const handoverConfirm = () => {
};
const handover = () => {
- const date = formatCurrentTime();
let data = {
materialData: confirmedData.map((data: MaterialItem) => {
return {
@@ -178,14 +176,14 @@ const handover = () => {
nowNumber: data.nowNumber,
dutyPerson: useUserStoreHook()?.username,
dutyPersonDepart: useUserStoreHook()?.depart,
- depart: "glb",
- dutyDate: date
+ area: "glb",
+ type: "tool"
};
}),
materialNote: {
note: remark.value,
- depart: "glb",
- dutyDate: date
+ area: "glb",
+ type: "tool"
},
dutyPerson: useUserStoreHook()?.username,
dutyPersonDepart: useUserStoreHook()?.depart
diff --git a/frontend/src/views/welcome/index.vue b/frontend/src/views/welcome/index.vue
index 367c1d2..7258aed 100644
--- a/frontend/src/views/welcome/index.vue
+++ b/frontend/src/views/welcome/index.vue
@@ -85,7 +85,73 @@ const borrowMaterial = () => {
};
// 借用钥匙弹窗
-const borrowKey = () => {};
+const borrowKey = () => {
+ getAllMaterialMeta("glb", "key").then(res => {
+ addDialog({
+ title: "钥匙借用",
+ props: {
+ borrowInfo: {
+ uuid: 0,
+ username: "",
+ phone: "",
+ depart: "",
+ reason: "",
+ baseData: res.data
+ }
+ },
+ width: "60%",
+ draggable: true,
+ fullscreen: deviceDetection(),
+ closeOnClickModal: false,
+ contentRenderer: () => h(MaterialBorrowDialog, { ref: bMForm }),
+ footerRenderer: ({ options, index }) => (
+ <>
+ store.prevActive()}
+ >
+ 上一步
+
+ store.nextActive()}
+ >
+ 下一步
+
+ {
+ const done = () => {
+ closeDialog(options, index);
+ store.resetActive();
+ };
+ const curData = options.props.borrowInfo as borrowInfo;
+ const borrowItemList = [];
+ for (const item of curData.baseData) {
+ if (item.borrowing !== undefined && item.borrowing > 0) {
+ delete item.created_at;
+ delete item.updated_at;
+ delete item.id;
+ borrowItemList.push(item);
+ }
+ }
+ curData.baseData = borrowItemList as [MaterialItem];
+ createBorrowed(curData).then(() => {
+ successNotification("钥匙借用流程发起成功!");
+ done();
+ });
+ }}
+ >
+ 完成
+
+ >
+ )
+ });
+ });
+};
From f52c168b8e528217cf9d87731bc5dbfbe125769a Mon Sep 17 00:00:00 2001
From: dayezi <1372755472@qq.com>
Date: Wed, 19 Jun 2024 18:34:19 +0800
Subject: [PATCH 07/10] =?UTF-8?q?=F0=9F=90=9E=20fix(timeout):=20=E4=BF=AE?=
=?UTF-8?q?=E5=A4=8D=E9=83=A8=E5=88=86=E5=B7=B2=E7=9F=A5=E9=97=AE=E9=A2=98?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
1. 修改请求超时时间
2. 新增物资借用时未填写借用理由予以提示
3. 修改物资源数据页面页面数据大小改变时予以提示未选择类型和区域
---
backend/app/utils/dutyInfo.ini | 4 ++--
backend/poetry.lock | 25 +++++++++++++++++++++-
backend/pyproject.toml | 1 +
frontend/src/utils/http/index.ts | 4 ++--
frontend/src/views/admin/MaterialMeta.vue | 8 +++++--
frontend/src/views/admin/OperationLogs.vue | 2 +-
frontend/src/views/welcome/index.vue | 9 ++++++++
7 files changed, 45 insertions(+), 8 deletions(-)
diff --git a/backend/app/utils/dutyInfo.ini b/backend/app/utils/dutyInfo.ini
index 5a75c91..f43ff42 100644
--- a/backend/app/utils/dutyInfo.ini
+++ b/backend/app/utils/dutyInfo.ini
@@ -1,7 +1,7 @@
[glb.tool]
-dutyperson = admin
+dutyperson = test
dutypersondepart = aaaqqqwwweee
-takeovertime = 2024-06-19 14:32:26
+takeovertime = 2024-06-19 18:25:17
[glb.key]
dutyperson = admin
diff --git a/backend/poetry.lock b/backend/poetry.lock
index 6e399ab..934203c 100644
--- a/backend/poetry.lock
+++ b/backend/poetry.lock
@@ -1,5 +1,28 @@
# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand.
+[[package]]
+name = "aiomysql"
+version = "0.2.0"
+description = "MySQL driver for asyncio."
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "aiomysql-0.2.0-py3-none-any.whl", hash = "sha256:b7c26da0daf23a5ec5e0b133c03d20657276e4eae9b73e040b72787f6f6ade0a"},
+ {file = "aiomysql-0.2.0.tar.gz", hash = "sha256:558b9c26d580d08b8c5fd1be23c5231ce3aeff2dadad989540fee740253deb67"},
+]
+
+[package.dependencies]
+PyMySQL = ">=1.0"
+
+[package.extras]
+rsa = ["PyMySQL[rsa] (>=1.0)"]
+sa = ["sqlalchemy (>=1.3,<1.4)"]
+
+[package.source]
+type = "legacy"
+url = "https://pypi.tuna.tsinghua.edu.cn/simple"
+reference = "tsinghua"
+
[[package]]
name = "aiosqlite"
version = "0.17.0"
@@ -1179,4 +1202,4 @@ reference = "tsinghua"
[metadata]
lock-version = "2.0"
python-versions = "^3.11"
-content-hash = "8ac865e616da791d1533d4827fa849e282747b7d3e61286ab22bc35e3e912285"
+content-hash = "a7251f841f098cbaef76ae230a800e55942908a2a55a3a718434fe45db6f2d33"
diff --git a/backend/pyproject.toml b/backend/pyproject.toml
index 4480629..5733473 100644
--- a/backend/pyproject.toml
+++ b/backend/pyproject.toml
@@ -26,6 +26,7 @@ cryptography = "^42.0.5"
ruamel-yaml = "^0.18.6"
pymysql = "^1.1.0"
python-multipart = "^0.0.9"
+aiomysql = "^0.2.0"
[tool.black]
line-length = 120
diff --git a/frontend/src/utils/http/index.ts b/frontend/src/utils/http/index.ts
index 5cf4226..c5de9b2 100644
--- a/frontend/src/utils/http/index.ts
+++ b/frontend/src/utils/http/index.ts
@@ -13,7 +13,7 @@ import { stringify } from "qs";
import NProgress from "../progress";
import { getToken, formatToken, removeToken } from "@/utils/auth";
import { useUserStoreHook } from "@/store/modules/user";
-import {baseUrlApi, staticUrl} from "@/api/utils";
+import { baseUrlApi, staticUrl } from "@/api/utils";
import { router, resetRouter } from "@/router";
import { message } from "@/utils/message";
import { errorNotification } from "@/utils/notification";
@@ -21,7 +21,7 @@ import { errorNotification } from "@/utils/notification";
// 相关配置请参考:www.axios-js.com/zh-cn/docs/#axios-request-config-1
const defaultConfig: AxiosRequestConfig = {
// 请求超时时间
- timeout: 10000,
+ timeout: 20000,
headers: {
Accept: "application/json, text/plain, */*",
"Content-Type": "application/json",
diff --git a/frontend/src/views/admin/MaterialMeta.vue b/frontend/src/views/admin/MaterialMeta.vue
index 114b168..5d7715d 100644
--- a/frontend/src/views/admin/MaterialMeta.vue
+++ b/frontend/src/views/admin/MaterialMeta.vue
@@ -19,6 +19,7 @@ import attentionForm from "./utils/attentionForm.vue";
import { SelectOpt, FormItemProps } from "./utils/types";
import { getDutyOverList, updateDutyOverList } from "@/api/admin";
import Search from "@iconify-icons/ep/search";
+import { message } from "@/utils/message";
defineOptions({
name: "MaterialMeta"
@@ -98,11 +99,14 @@ const pagination = reactive({
total: 1,
pageSize: 10,
currentPage: 1,
- background: true,
- hideOnSinglePage: true
+ background: true
});
// 表格页面大小改变回调
const pageSizeChange = (size: number) => {
+ if (searchDisable.value) {
+ message("请选择类型和区域", { type: "warning" });
+ return;
+ }
pagination.pageSize = size;
onSearch();
};
diff --git a/frontend/src/views/admin/OperationLogs.vue b/frontend/src/views/admin/OperationLogs.vue
index 1108bfa..c34c9ad 100644
--- a/frontend/src/views/admin/OperationLogs.vue
+++ b/frontend/src/views/admin/OperationLogs.vue
@@ -1,6 +1,6 @@