feat: feat: face admin get list
This commit is contained in:
parent
2cda4a2ecd
commit
eeccb88ebe
@ -84,7 +84,9 @@
|
|||||||
location.href = "register.html";
|
location.href = "register.html";
|
||||||
}else{
|
}else{
|
||||||
sa.closeCurrIframe();
|
sa.closeCurrIframe();
|
||||||
parent.sa.$page.openReg("register.html", false);
|
var shadeClose = parseInt(sa.p('canClose', 0)) === 1;
|
||||||
|
var shadeCloseInt = shadeClose ? 1 : 0;
|
||||||
|
parent.sa.$page.openReg("register.html?canClose=" + shadeCloseInt, shadeClose);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 点击登录按钮
|
// 点击登录按钮
|
||||||
|
@ -122,7 +122,9 @@
|
|||||||
location.href = "login.html";
|
location.href = "login.html";
|
||||||
}else{
|
}else{
|
||||||
sa.closeCurrIframe();
|
sa.closeCurrIframe();
|
||||||
parent.sa.$page.openLogin("login.html", false);
|
var shadeClose = parseInt(sa.p('canClose', 0)) === 1;
|
||||||
|
var shadeCloseInt = shadeClose ? 1 : 0;
|
||||||
|
parent.sa.$page.openLogin("login.html?canClose=" + shadeCloseInt, shadeClose);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 选择注册类型
|
// 选择注册类型
|
||||||
|
@ -175,4 +175,13 @@ var adminMenuList = [
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: '6',
|
||||||
|
name: '人脸信息管理',
|
||||||
|
icon: 'el-icon-search',
|
||||||
|
info: '人脸信息管理',
|
||||||
|
childList: [
|
||||||
|
{id: '6-1', name: '人脸信息列表', icon: 'el-icon-document-remove', url: 'sa-view/face/face-list.html'},
|
||||||
|
]
|
||||||
|
},
|
||||||
]
|
]
|
||||||
|
@ -63,7 +63,7 @@ sa_admin.dropList = [ // 头像点击处可操作的选项
|
|||||||
{
|
{
|
||||||
name: '切换账号',
|
name: '切换账号',
|
||||||
click: function() {
|
click: function() {
|
||||||
sa.$page.openLogin('login.html', true);
|
sa.$page.openLogin('login.html?canClose=1', true);
|
||||||
// layer.open({
|
// layer.open({
|
||||||
// type: 2,
|
// type: 2,
|
||||||
// title: false,
|
// title: false,
|
||||||
|
237
src/frontend/sa-view/face/face-list.html
Normal file
237
src/frontend/sa-view/face/face-list.html
Normal file
@ -0,0 +1,237 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>人脸信息列表</title>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
|
||||||
|
<!-- 所有的 css & js 资源 -->
|
||||||
|
<link rel="stylesheet" href="https://unpkg.com/element-ui@2.13.0/lib/theme-chalk/index.css">
|
||||||
|
<link rel="stylesheet" href="../../static/sa.css">
|
||||||
|
<script src="https://unpkg.com/vue@2.6.10/dist/vue.js"></script>
|
||||||
|
<script src="https://unpkg.com/element-ui@2.13.0/lib/index.js"></script>
|
||||||
|
<script src="https://unpkg.com/http-vue-loader@1.4.2/src/httpVueLoader.js"></script>
|
||||||
|
<script src="https://unpkg.com/jquery@3.4.1/dist/jquery.min.js"></script>
|
||||||
|
<script src="../../static/kj/layer/layer.js"></script>
|
||||||
|
<script src="../../static/sa.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="vue-box" style="display: none;" :style="'display: block;'">
|
||||||
|
<div class="c-panel">
|
||||||
|
<!-- ------------- 检索参数 ------------- -->
|
||||||
|
<div class="c-title">人脸列表</div>
|
||||||
|
<el-form>
|
||||||
|
<div class="c-item">
|
||||||
|
<label class="c-label">用户 ID:</label>
|
||||||
|
<el-input v-model="p.user_id" placeholder=""></el-input>
|
||||||
|
</div>
|
||||||
|
<div class="c-item">
|
||||||
|
<label class="c-label">删除状态:</label>
|
||||||
|
<el-select v-model="p.deleted">
|
||||||
|
<el-option label="所有" :value="0"></el-option>
|
||||||
|
<el-option label="已被删除" :value="1"></el-option>
|
||||||
|
<el-option label="未被删除" :value="2"></el-option>
|
||||||
|
</el-select>
|
||||||
|
</div>
|
||||||
|
<div class="c-item">
|
||||||
|
<label class="c-label">批准状态:</label>
|
||||||
|
<el-select v-model="p.approved">
|
||||||
|
<el-option label="所有" :value="0"></el-option>
|
||||||
|
<el-option label="已被批准" :value="1"></el-option>
|
||||||
|
<el-option label="未被批准" :value="2"></el-option>
|
||||||
|
</el-select>
|
||||||
|
</div>
|
||||||
|
<br />
|
||||||
|
<div class="c-item">
|
||||||
|
<label class="c-label">创建日期:</label>
|
||||||
|
<el-date-picker v-model="p.start_time" type="date" value-format="yyyy-MM-dd" placeholder="开始日期"></el-date-picker> -
|
||||||
|
<el-date-picker v-model="p.end_time" type="date" value-format="yyyy-MM-dd" placeholder="结束日期"></el-date-picker>
|
||||||
|
</div>
|
||||||
|
<div class="c-item" style="min-width: 0px;">
|
||||||
|
<el-button type="primary" icon="el-icon-search" @click="p.pageNo = 1; f5()">查询</el-button>
|
||||||
|
</div>
|
||||||
|
<br />
|
||||||
|
<div class="c-item s-radio-text">
|
||||||
|
<label class="c-label">综合排序:</label>
|
||||||
|
<el-radio-group v-model="p.sortType">
|
||||||
|
<el-radio :label="1">创建时间</el-radio>
|
||||||
|
<el-radio :label="2">用户 ID</el-radio>
|
||||||
|
<el-radio :label="3">是否批准</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</div>
|
||||||
|
</el-form>
|
||||||
|
<!-- <div class="c-title">数据列表</div> -->
|
||||||
|
<!-- ------------- 快捷按钮 ------------- -->
|
||||||
|
<div class="fast-btn">
|
||||||
|
<!-- <el-button type="primary" icon="el-icon-plus" @click="add()">新增</el-button>-->
|
||||||
|
<el-button type="success" icon="el-icon-view" @click="getBySelect()">查看</el-button>
|
||||||
|
<el-button type="success" icon="el-icon-check" @click="deleteByIds()">批准</el-button>
|
||||||
|
<el-button type="danger" icon="el-icon-delete" @click="deleteByIds()">禁用</el-button>
|
||||||
|
<el-button type="warning" icon="el-icon-download" @click="sa.exportExcel()">导出</el-button>
|
||||||
|
<el-button type="info" icon="el-icon-refresh" @click="sa.f5()">重置</el-button>
|
||||||
|
</div>
|
||||||
|
<!-- ------------- 数据列表 ------------- -->
|
||||||
|
<el-table class="data-table" ref="data-table" :data="dataList" size="small">
|
||||||
|
<el-table-column type="selection" width="45px"></el-table-column>
|
||||||
|
<el-table-column label="编号" prop="id" width="80px" > </el-table-column>
|
||||||
|
<el-table-column label="人脸" prop="username" width="220px">
|
||||||
|
<template slot-scope="s">
|
||||||
|
<img :src="sa.cfg.api_url + s.row.image" @click="sa.showImage(sa.cfg.api_url + s.row.image, '400px', '400px')"
|
||||||
|
style="width: 3em; height: 3em; float: left; margin-right: 1em; border-radius: 50%; cursor: pointer;" >
|
||||||
|
<div style="float: left; width: 130px; line-height: 40px;">
|
||||||
|
<b>UID: {{s.row.user_id}}</b>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="创建于" prop="create_time"></el-table-column>
|
||||||
|
<el-table-column label="删除状态">
|
||||||
|
<template slot-scope="s">
|
||||||
|
<el-switch v-model="s.row.status_delete" :active-value="1" :inactive-value="0" inactive-color="#ff4949"></el-switch>
|
||||||
|
<b style="color: green;" v-if="s.row.status_delete === 1">已被删除</b>
|
||||||
|
<b style="color: red;" v-if="s.row.status_delete === 0">未被删除</b>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="状态">
|
||||||
|
<template slot-scope="s">
|
||||||
|
<el-switch v-model="s.row.status" :active-value="1" :inactive-value="0" inactive-color="#ff4949"></el-switch>
|
||||||
|
<b style="color: green;" v-if="s.row.status === 1">已批准</b>
|
||||||
|
<b style="color: red;" v-if="s.row.status === 0">未批准</b>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="address" label="操作">
|
||||||
|
<template slot-scope="s">
|
||||||
|
<el-button class="c-btn" type="success" icon="el-icon-view" @click="get(s.row)">详情</el-button>
|
||||||
|
<el-button v-if="s.row.status === 1" class="c-btn" type="danger" icon="el-icon-delete" @click="del(s.row)">禁用</el-button>
|
||||||
|
<el-button v-if="s.row.status === 0" class="c-btn" type="success" icon="el-icon-check" @click="del(s.row)">批准</el-button>
|
||||||
|
<el-button v-if="s.row.status_delete === 0" class="c-btn" type="danger" icon="el-icon-delete" @click="del(s.row)">删除</el-button>
|
||||||
|
<el-button v-if="s.row.status_delete === 1" class="c-btn" type="success" icon="el-icon-check" @click="del(s.row)">撤销</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<!-- ------------- 分页 ------------- -->
|
||||||
|
<div class="page-box">
|
||||||
|
<el-pagination background
|
||||||
|
layout="total, prev, pager, next, sizes, jumper"
|
||||||
|
:current-page.sync="p.pageNo"
|
||||||
|
:page-size.sync="p.pageSize"
|
||||||
|
:total="dataCount"
|
||||||
|
:page-sizes="[1, 10, 20, 30, 40, 50, 100]"
|
||||||
|
@current-change="f5(true)"
|
||||||
|
@size-change="f5(true)">
|
||||||
|
</el-pagination>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- 给layer打一波广告 -->
|
||||||
|
<!-- <div class="c-panel" style="background-color: rgba(0,0,0,0);">
|
||||||
|
layer:<el-link type="primary" href="http://layer.layui.com/" target="_blank">
|
||||||
|
一个可以让你想到即可做到的JavaScript弹窗(层)解决方案
|
||||||
|
</el-link>
|
||||||
|
</div> -->
|
||||||
|
</div>
|
||||||
|
<script src="data-list.js"></script>
|
||||||
|
<script type="text/javascript">
|
||||||
|
sa.checkAuth('admin');
|
||||||
|
var app = new Vue({
|
||||||
|
el: '.vue-box',
|
||||||
|
data: {
|
||||||
|
p: { // 查询参数
|
||||||
|
user_id: sa.p("user_id", '0'),
|
||||||
|
deleted: 0,
|
||||||
|
approved: 0,
|
||||||
|
sortType: 1,
|
||||||
|
start_time: '',
|
||||||
|
end_time: '',
|
||||||
|
pageNo: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
},
|
||||||
|
dataCount: 0,
|
||||||
|
dataList: []
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
// 数据刷新
|
||||||
|
f5: function() {
|
||||||
|
sa.ajax('/face/admin/image/list', this.p, function(res){
|
||||||
|
this.dataList = res.data.data; // 数据
|
||||||
|
for (let i = 0; i < this.dataList.length; i++) {
|
||||||
|
this.dataList[i].image = '/face/view/' + this.dataList[i].image;
|
||||||
|
this.dataList[i].status_delete = this.dataList[i].delete_time !== null ? 1 : 0;
|
||||||
|
this.dataList[i].status = this.dataList[i].is_approved ? 1 : 0;
|
||||||
|
}
|
||||||
|
this.dataCount = res.data.count; // 分页
|
||||||
|
sa.f5TableHeight(); // 刷新表格高度
|
||||||
|
}.bind(this), {});
|
||||||
|
},
|
||||||
|
// 查看
|
||||||
|
get: function(data) {
|
||||||
|
var str = '<div>';
|
||||||
|
str += '<p>编号:' + data.id + '</p>';
|
||||||
|
str += '<p>用户 ID:' + data.user_id + '</p>';
|
||||||
|
str += '<p>当前状态:<b>' + (data.status == 1 ? '已批准' : '未批准') + '</b></p>';
|
||||||
|
str += '<p>创建时间:' + data.create_time + '</p>';
|
||||||
|
str += '<p>更新时间:' + data.update_time + '</p>';
|
||||||
|
str += '<p>删除时间:' + data.delete_time + '</p>';
|
||||||
|
str += '</div>';
|
||||||
|
sa.alert(str);
|
||||||
|
},
|
||||||
|
// 查看 - 根据选中的
|
||||||
|
getBySelect: function(data) {
|
||||||
|
var selection = this.$refs['data-table'].selection;
|
||||||
|
if(selection.length == 0) {
|
||||||
|
return sa.msg('请选择一条数据')
|
||||||
|
}
|
||||||
|
this.get(selection[0]);
|
||||||
|
},
|
||||||
|
// 删除
|
||||||
|
del: function(data) {
|
||||||
|
sa.confirm('是否修改,此操作可撤销', function() {
|
||||||
|
sa.ajax('/user/admin/change_status', {user_id: data.id, is_active: !data.is_active}, function(res) {
|
||||||
|
// sa.arrayDelete(this.dataList, data);
|
||||||
|
if (data.is_active) {
|
||||||
|
sa.ok('禁用成功');
|
||||||
|
} else {
|
||||||
|
sa.ok('启用成功');
|
||||||
|
}
|
||||||
|
this.f5();
|
||||||
|
}.bind(this), {})
|
||||||
|
}.bind(this));
|
||||||
|
},
|
||||||
|
// 重置密码
|
||||||
|
reset_pwd: function (data) {
|
||||||
|
sa.confirm('是否重置密码,此操作不可撤销', function() {
|
||||||
|
sa.ajax('/user/admin/reset_password', {user_id: data.id}, function(res) {
|
||||||
|
sa.ok('重置密码成功');
|
||||||
|
}.bind(this), {})
|
||||||
|
}.bind(this));
|
||||||
|
},
|
||||||
|
// 批量删除
|
||||||
|
deleteByIds: function() {
|
||||||
|
// 获取选中元素的id列表
|
||||||
|
let selection = this.$refs['data-table'].selection;
|
||||||
|
let ids = sa.getArrayField(selection, 'id');
|
||||||
|
if(selection.length == 0) {
|
||||||
|
return sa.msg('请至少选择一条数据')
|
||||||
|
}
|
||||||
|
// 提交删除
|
||||||
|
sa.confirm('是否批量禁用选中用户?此操作可撤销', function() {
|
||||||
|
sa.ajax2('/user/admin/change_status', {ids: ids}, function(res) {
|
||||||
|
sa.arrayDelete(this.dataList, selection);
|
||||||
|
sa.ok('删除成功');
|
||||||
|
sa.f5TableHeight(); // 刷新表格高度
|
||||||
|
}.bind(this))
|
||||||
|
}.bind(this));
|
||||||
|
},
|
||||||
|
},
|
||||||
|
created: function(){
|
||||||
|
this.f5()
|
||||||
|
sa.onInputEnter(); // 监听输入框的回车事件,执行查询
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -113,8 +113,10 @@
|
|||||||
<el-table-column prop="address" label="操作">
|
<el-table-column prop="address" label="操作">
|
||||||
<template slot-scope="s">
|
<template slot-scope="s">
|
||||||
<el-button class="c-btn" type="success" icon="el-icon-view" @click="get(s.row)">详情</el-button>
|
<el-button class="c-btn" type="success" icon="el-icon-view" @click="get(s.row)">详情</el-button>
|
||||||
|
<el-button class="c-btn" type="success" icon="el-icon-view" @click="getFace(s.row)">人脸信息</el-button>
|
||||||
<el-button class="c-btn" type="danger" icon="el-icon-delete" @click="reset_pwd(s.row)">重置密码</el-button>
|
<el-button class="c-btn" type="danger" icon="el-icon-delete" @click="reset_pwd(s.row)">重置密码</el-button>
|
||||||
<el-button class="c-btn" type="danger" icon="el-icon-delete" @click="del(s.row)">禁/启用</el-button>
|
<el-button v-if="s.row.status === 1" class="c-btn" type="danger" icon="el-icon-delete" @click="del(s.row)">禁用</el-button>
|
||||||
|
<el-button v-if="s.row.status === 0" class="c-btn" type="success" icon="el-icon-check" @click="del(s.row)">启用</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
@ -190,6 +192,10 @@
|
|||||||
str += '</div>';
|
str += '</div>';
|
||||||
sa.alert(str);
|
sa.alert(str);
|
||||||
},
|
},
|
||||||
|
// 查看人脸信息
|
||||||
|
getFace: function(data) {
|
||||||
|
sa.showIframe('人脸信息', '../face/face-list.html?user_id=' + data.id, '900px', '600px');
|
||||||
|
},
|
||||||
// 查看 - 根据选中的
|
// 查看 - 根据选中的
|
||||||
getBySelect: function(data) {
|
getBySelect: function(data) {
|
||||||
var selection = this.$refs['data-table'].selection;
|
var selection = this.$refs['data-table'].selection;
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
from fastapi import UploadFile, File
|
from fastapi import UploadFile, File
|
||||||
from fastapi_amis_admin.crud import BaseApiOut
|
from fastapi_amis_admin.crud import BaseApiOut
|
||||||
from starlette import status
|
from starlette import status
|
||||||
from starlette.exceptions import HTTPException
|
from starlette.exceptions import HTTPException
|
||||||
from starlette.requests import Request
|
from starlette.requests import Request
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
from starlette.responses import FileResponse
|
from starlette.responses import FileResponse
|
||||||
|
|
||||||
from src.plugin import handler
|
from src.plugin import handler
|
||||||
|
52
src/route/face_image_admin.py
Normal file
52
src/route/face_image_admin.py
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
from fastapi_amis_admin.crud import BaseApiOut
|
||||||
|
from starlette import status
|
||||||
|
from starlette.exceptions import HTTPException
|
||||||
|
|
||||||
|
from src.plugin import handler
|
||||||
|
from src.plugin.plugin import Plugin
|
||||||
|
from src.services.face_image.schemas import FaceList
|
||||||
|
from src.services.face_image.services import FaceImageServices
|
||||||
|
from src.services.users.services import UserRoleServices
|
||||||
|
|
||||||
|
|
||||||
|
class FaceImageAdminRoutes(Plugin):
|
||||||
|
_prefix = "/face/admin"
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
face_image_services: FaceImageServices,
|
||||||
|
user_role_services: UserRoleServices,
|
||||||
|
):
|
||||||
|
self.face_image_services = face_image_services
|
||||||
|
self.user_role_services = user_role_services
|
||||||
|
self.avatar_path = "/face/view/"
|
||||||
|
|
||||||
|
@handler.post("/image/list", student=True)
|
||||||
|
async def get_me_face_images(self, data: FaceList):
|
||||||
|
user_id = data.user_id
|
||||||
|
deleted, approved, sort_type = data.deleted, data.approved, data.sortType
|
||||||
|
start_time, end_time = data.start, data.end
|
||||||
|
page_no, page_size = data.pageNo, data.pageSize
|
||||||
|
if page_no < 1:
|
||||||
|
page_no = 1
|
||||||
|
if page_size < 0 or page_size > 100:
|
||||||
|
page_size = 10
|
||||||
|
try:
|
||||||
|
data, count = await self.face_image_services.get_image_list(
|
||||||
|
user_id,
|
||||||
|
deleted,
|
||||||
|
approved,
|
||||||
|
sort_type,
|
||||||
|
start_time,
|
||||||
|
end_time,
|
||||||
|
page_no,
|
||||||
|
page_size,
|
||||||
|
)
|
||||||
|
return BaseApiOut(
|
||||||
|
code=0, msg="请求成功", data={"data": data, "count": count}
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||||
|
detail=f"Error Execute SQL:{e}",
|
||||||
|
) from e
|
@ -1,9 +1,8 @@
|
|||||||
import datetime
|
import datetime
|
||||||
from typing import TYPE_CHECKING, Union
|
from typing import TYPE_CHECKING, Union
|
||||||
|
|
||||||
from fastapi_amis_admin.crud import BaseApiOut
|
|
||||||
|
|
||||||
from fastapi import HTTPException
|
from fastapi import HTTPException
|
||||||
|
from fastapi_amis_admin.crud import BaseApiOut
|
||||||
from starlette import status
|
from starlette import status
|
||||||
from starlette.requests import Request
|
from starlette.requests import Request
|
||||||
from starlette.responses import Response
|
from starlette.responses import Response
|
||||||
|
@ -9,7 +9,6 @@ from src.services.users.schemas import (
|
|||||||
UserList,
|
UserList,
|
||||||
DisableOrEnableUser,
|
DisableOrEnableUser,
|
||||||
UserAdminAdd,
|
UserAdminAdd,
|
||||||
UserRoleEnum,
|
|
||||||
CreateTypeEnum,
|
CreateTypeEnum,
|
||||||
)
|
)
|
||||||
from src.services.users.services import UserServices
|
from src.services.users.services import UserServices
|
||||||
|
@ -2,7 +2,6 @@ from fastapi import File, UploadFile
|
|||||||
from fastapi_amis_admin.crud import BaseApiOut
|
from fastapi_amis_admin.crud import BaseApiOut
|
||||||
from starlette import status
|
from starlette import status
|
||||||
from starlette.exceptions import HTTPException
|
from starlette.exceptions import HTTPException
|
||||||
|
|
||||||
from starlette.requests import Request
|
from starlette.requests import Request
|
||||||
from starlette.responses import FileResponse
|
from starlette.responses import FileResponse
|
||||||
|
|
||||||
|
@ -1,11 +1,14 @@
|
|||||||
from typing import Optional, Sequence
|
from datetime import datetime
|
||||||
|
from typing import Optional, Sequence, Tuple
|
||||||
|
|
||||||
from persica.factory.component import AsyncInitializingComponent
|
from persica.factory.component import AsyncInitializingComponent
|
||||||
|
from sqlalchemy import func
|
||||||
from sqlmodel.ext.asyncio.session import AsyncSession
|
from sqlmodel.ext.asyncio.session import AsyncSession
|
||||||
from sqlmodel import select, col
|
from sqlmodel import select, col
|
||||||
|
|
||||||
from src.core.database import Database
|
from src.core.database import Database
|
||||||
from src.services.face_image.models import FaceImageModel
|
from src.services.face_image.models import FaceImageModel
|
||||||
|
from src.services.face_image.schemas import TypeEnum, SortTypeEnum
|
||||||
|
|
||||||
|
|
||||||
class FaceImageRepo(AsyncInitializingComponent):
|
class FaceImageRepo(AsyncInitializingComponent):
|
||||||
@ -52,3 +55,61 @@ class FaceImageRepo(AsyncInitializingComponent):
|
|||||||
await session.commit()
|
await session.commit()
|
||||||
await session.refresh(image)
|
await session.refresh(image)
|
||||||
return image
|
return image
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
async def get_count(session, q) -> int:
|
||||||
|
count_q = (
|
||||||
|
q.with_only_columns(func.count())
|
||||||
|
.order_by(None)
|
||||||
|
.select_from(q.get_final_froms()[0])
|
||||||
|
)
|
||||||
|
iterator = await session.exec(count_q)
|
||||||
|
for count in iterator:
|
||||||
|
return count
|
||||||
|
return 0
|
||||||
|
|
||||||
|
async def get_image_list(
|
||||||
|
self,
|
||||||
|
user_id: Optional[int],
|
||||||
|
deleted: Optional[TypeEnum],
|
||||||
|
approved: Optional[TypeEnum],
|
||||||
|
sort_type: Optional[SortTypeEnum],
|
||||||
|
start_time: Optional[datetime],
|
||||||
|
end_time: Optional[datetime],
|
||||||
|
page_no: int,
|
||||||
|
page_size: int,
|
||||||
|
) -> Tuple[Sequence[FaceImageModel], int]:
|
||||||
|
async with AsyncSession(self.engine) as session:
|
||||||
|
statement = select(FaceImageModel)
|
||||||
|
if user_id:
|
||||||
|
statement = statement.where(FaceImageModel.user_id == user_id)
|
||||||
|
if deleted:
|
||||||
|
if deleted is TypeEnum.DO:
|
||||||
|
statement = statement.where(
|
||||||
|
col(FaceImageModel.delete_time).isnot(None)
|
||||||
|
)
|
||||||
|
elif deleted is TypeEnum.UNDO:
|
||||||
|
statement = statement.where(
|
||||||
|
col(FaceImageModel.delete_time).is_(None)
|
||||||
|
)
|
||||||
|
if approved:
|
||||||
|
if approved is TypeEnum.DO:
|
||||||
|
statement = statement.where(FaceImageModel.is_approved == True)
|
||||||
|
elif approved is TypeEnum.UNDO:
|
||||||
|
statement = statement.where(FaceImageModel.is_approved == False)
|
||||||
|
if start_time:
|
||||||
|
statement = statement.where(FaceImageModel.create_time >= start_time)
|
||||||
|
if end_time:
|
||||||
|
statement = statement.where(FaceImageModel.create_time <= end_time)
|
||||||
|
all_count = await self.get_count(session, statement)
|
||||||
|
if sort_type:
|
||||||
|
if sort_type.CREATE_TIME:
|
||||||
|
statement = statement.order_by(FaceImageModel.create_time)
|
||||||
|
elif sort_type.USER_ID:
|
||||||
|
statement = statement.order_by(FaceImageModel.user_id)
|
||||||
|
elif sort_type.APPROVED:
|
||||||
|
statement = statement.order_by(FaceImageModel.is_approved)
|
||||||
|
offset = (page_no - 1) * page_size
|
||||||
|
statement = statement.offset(offset).limit(page_size)
|
||||||
|
r = await session.exec(statement)
|
||||||
|
return r.all(), all_count
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
from typing import List
|
from enum import Enum
|
||||||
|
from datetime import date, datetime
|
||||||
|
from typing import List, Optional
|
||||||
|
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
|
|
||||||
@ -17,3 +19,43 @@ class FaceImageDeleteIds(BaseModel):
|
|||||||
|
|
||||||
class FaceImageUpdate(FaceImageCreate, FaceImageDelete):
|
class FaceImageUpdate(FaceImageCreate, FaceImageDelete):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class TypeEnum(int, Enum):
|
||||||
|
ALL = 0
|
||||||
|
DO = 1
|
||||||
|
UNDO = 2
|
||||||
|
|
||||||
|
|
||||||
|
class SortTypeEnum(int, Enum):
|
||||||
|
CREATE_TIME = 1
|
||||||
|
USER_ID = 2
|
||||||
|
APPROVED = 3
|
||||||
|
|
||||||
|
|
||||||
|
class FaceList(BaseModel):
|
||||||
|
user_id: Optional[int] = None
|
||||||
|
|
||||||
|
deleted: TypeEnum = TypeEnum.ALL
|
||||||
|
approved: TypeEnum = TypeEnum.ALL
|
||||||
|
sortType: SortTypeEnum = SortTypeEnum.CREATE_TIME
|
||||||
|
start_time: Optional[str] = ""
|
||||||
|
end_time: Optional[str] = ""
|
||||||
|
pageNo: int = 1
|
||||||
|
pageSize: int = 10
|
||||||
|
|
||||||
|
@property
|
||||||
|
def start(self):
|
||||||
|
if not self.start_time:
|
||||||
|
return None
|
||||||
|
y, m, d = self.start_time.split("-")
|
||||||
|
start_time = date(int(y), int(m), int(d))
|
||||||
|
return datetime.combine(start_time, datetime.min.time())
|
||||||
|
|
||||||
|
@property
|
||||||
|
def end(self):
|
||||||
|
if not self.end_time:
|
||||||
|
return None
|
||||||
|
y, m, d = self.end_time.split("-")
|
||||||
|
end_time = date(int(y), int(m), int(d))
|
||||||
|
return datetime.combine(end_time, datetime.max.time())
|
||||||
|
@ -5,6 +5,7 @@ from typing_extensions import Optional
|
|||||||
|
|
||||||
from .models import FaceImageModel
|
from .models import FaceImageModel
|
||||||
from .repositories import FaceImageRepo
|
from .repositories import FaceImageRepo
|
||||||
|
from .schemas import SortTypeEnum, TypeEnum
|
||||||
|
|
||||||
|
|
||||||
class FaceImageServices(AsyncInitializingComponent):
|
class FaceImageServices(AsyncInitializingComponent):
|
||||||
@ -53,3 +54,25 @@ class FaceImageServices(AsyncInitializingComponent):
|
|||||||
image = await self.repo.get_by(rid)
|
image = await self.repo.get_by(rid)
|
||||||
image.is_approved = True
|
image.is_approved = True
|
||||||
return await self.repo.add_face_image(image)
|
return await self.repo.add_face_image(image)
|
||||||
|
|
||||||
|
async def get_image_list(
|
||||||
|
self,
|
||||||
|
user_id: Optional[int],
|
||||||
|
deleted: Optional[TypeEnum],
|
||||||
|
approved: Optional[TypeEnum],
|
||||||
|
sort_type: Optional[SortTypeEnum],
|
||||||
|
start_time: Optional[datetime],
|
||||||
|
end_time: Optional[datetime],
|
||||||
|
page_no: int,
|
||||||
|
page_size: int,
|
||||||
|
):
|
||||||
|
return await self.repo.get_image_list(
|
||||||
|
user_id=user_id,
|
||||||
|
deleted=deleted,
|
||||||
|
approved=approved,
|
||||||
|
sort_type=sort_type,
|
||||||
|
start_time=start_time,
|
||||||
|
end_time=end_time,
|
||||||
|
page_no=page_no,
|
||||||
|
page_size=page_size,
|
||||||
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user