You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

837 lines
26 KiB
TypeScript

import { BadRequestException, Body, Controller, Delete, Get, NotFoundException, Param, Post, Put, Query, Req, Res } from '@nestjs/common';
import { AppService } from './app.service';
import * as fs from 'fs';
import { ApiBearerAuth, ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
import { IsArray, IsBoolean, IsDateString, IsNotEmpty, IsOptional, IsString } from 'class-validator';
import { NodeVisitorEntity } from './node-visitor.entity';
import { Between, DataSource, IsNull, LessThan, Not, Repository } from 'typeorm';
import * as bluebird from 'bluebird';
import { NodeOtherVisitorEntity } from './node-other-visitor.entity';
import * as moment from 'moment';
import { CommonPageArgs } from './common';
import { InjectRepository } from '@nestjs/typeorm';
import axios from 'axios';
import { v4 as uuid } from 'uuid';
import { verificationService } from './lib/face';
import { join } from 'path';
import { AreaEntity } from './area.entity';
export class Electronics {
@ApiProperty({ description: "电子产品名称" })
@IsString()
@IsNotEmpty()
public name: string;
}
export class VisitorList {
@ApiProperty({ description: "访客姓名" })
@IsString()
@IsNotEmpty()
public name: string;
@ApiProperty({ description: "访客身份证号" })
@IsString()
@IsNotEmpty()
public identity_card_no: string;
@ApiProperty({ description: "证件类型" })
@IsString()
@IsNotEmpty()
public id_type: string;
@ApiProperty({ description: "国籍(中国/其他国籍)" })
@IsString()
@IsNotEmpty()
public nationality_type: string;
@ApiProperty({ description: "国籍名称" })
@IsString()
@IsNotEmpty()
public nationality: string;
}
export class UpdateVisitorNumber {
@ApiProperty({ description: "id" })
@IsString()
@IsNotEmpty()
public id: string;
@ApiProperty({ description: "card_number" })
@IsString()
@IsNotEmpty()
public card_number: string;
}
export class UpdateVisitorEnd {
@ApiProperty({ description: "id" })
@IsString()
@IsNotEmpty()
public id: string;
@ApiProperty({ description: "area_code" })
@IsString()
@IsOptional()
public area_code: string;
}
export class CreateVisitor {
@ApiProperty({ description: "申请人" })
@IsString()
@IsNotEmpty()
public applicant: string;
@ApiProperty({ description: "申请人部门" })
@IsString()
@IsNotEmpty()
public applicant_department: string;
@ApiProperty({ description: "申请日期" })
@IsDateString()
@IsNotEmpty()
public apply_date: string;
@ApiProperty({ description: "申请单号" })
@IsString()
@IsNotEmpty()
public code: string;
// TODO 确定访客类型
@ApiProperty({ description: "来访类型" })
@IsString()
@IsNotEmpty()
public visitor_type: string;
@ApiProperty({ description: "来访区域" })
@IsString()
@IsNotEmpty()
public area: string;
@ApiProperty({ description: "来访单位" })
@IsString()
@IsNotEmpty()
public visitor_unit: string;
@ApiProperty({ description: "访客人数" })
@IsString()
@IsNotEmpty()
public visitor_number: string;
@ApiProperty({ description: "交通方式" })
@IsString()
@IsNotEmpty()
public transport: string;
@ApiProperty({ description: "车牌号" })
@IsString()
@IsNotEmpty()
public plate_no: string;
@ApiProperty({ description: "起始日期" })
@IsDateString()
@IsNotEmpty()
public start_date: string;
@ApiProperty({ description: "截止日期" })
@IsDateString()
@IsNotEmpty()
public end_date: string;
@ApiProperty({ description: "被访人" })
@IsString()
@IsNotEmpty()
public visited_staff: string;
@ApiProperty({ description: "被访部门" })
@IsString()
@IsNotEmpty()
public visited_department: string;
@ApiProperty({ description: "被访部门" })
@IsString()
@IsNotEmpty()
public purpose: string;
@ApiProperty({ description: "携带的电子产品" })
// @ApiProperty({ description: "携带的电子产品", type: [Electronics] })
@IsArray()
@IsNotEmpty()
public electronics: string;
// public electronics: Electronics[];
@ApiProperty({ description: "携带电子产品人员" })
@IsArray()
@IsOptional()
public personnel_carrying_electronics: string;
@ApiProperty({ description: "是否上E1楼洽谈" })
@IsArray()
@IsOptional()
public sfslqt: string;
@ApiProperty({ description: "访客清单", type: [VisitorList] })
@IsArray()
@IsNotEmpty()
public visitor_list: VisitorList[];
@ApiProperty({ description: "访客是否有可能接触受控设备" })
@IsString()
@IsNotEmpty()
public may_access_sensitive_info: string;
}
export class QueryVisitorDto extends CommonPageArgs {
// @ApiPropertyOptional({ description: '真实姓名' })
// @IsString()
// @IsOptional()
// true_name: string
@ApiPropertyOptional({ description: "根据名称模糊搜索", required: false })
@IsString()
@IsOptional()
search?: string
@ApiPropertyOptional({ description: "厂区标识", required: false })
@IsString()
@IsOptional()
area_code?: string
@ApiPropertyOptional({ description: "申请人", required: false })
@IsString()
@IsOptional()
applicant?: string
@ApiPropertyOptional({ description: "被访人", required: false })
@IsString()
@IsOptional()
visited_staff?: string
@ApiPropertyOptional({ description: "", required: false })
@IsString()
@IsOptional()
start_date?: string
@ApiPropertyOptional({ description: "", required: false })
@IsString()
@IsOptional()
end_date?: string
}
export class AreaDto extends CommonPageArgs {
@ApiPropertyOptional({ description: "根据名称模糊搜索", required: false })
@IsString()
@IsOptional()
search?: string
}
export class CreateArea {
@ApiProperty({ description: "" })
@IsString()
@IsNotEmpty()
public name: string;
@ApiProperty({ description: "" })
@IsString()
@IsNotEmpty()
public code: string;
}
export class UpdateArea {
@ApiProperty({ description: "" })
@IsString()
@IsNotEmpty()
public name: string;
@ApiProperty({ description: "" })
@IsString()
@IsNotEmpty()
public code: string;
}
export class DeleteArea {
@ApiProperty({ description: "" })
@IsString()
@IsNotEmpty()
public id: string;
}
export class QueryVisitorByNumberDto {
@ApiPropertyOptional({ description: "身份证号", required: true })
@IsString()
@IsNotEmpty()
identity_card_no: string
@ApiPropertyOptional({ description: "", required: false })
@IsString()
@IsOptional()
area_code?: string
}
@Controller()
export class AppController {
constructor(
private readonly appService: AppService,
private readonly dataSource: DataSource,
@InjectRepository(NodeVisitorEntity)
private readonly nodeVisitorRepository: Repository<NodeVisitorEntity>,
@InjectRepository(AreaEntity)
private readonly areaRepository: Repository<AreaEntity>,
@InjectRepository(NodeOtherVisitorEntity)
private readonly nodeOtherVisitorRepository: Repository<NodeOtherVisitorEntity>,
) { }
@Get()
getHello(): string {
return this.appService.getHello();
}
// @Get("/doc/json")
// getDoc(): string {
// const json = fs.readFileSync("swagger-spec.json", "utf-8");
// return JSON.parse(json);
// }
// @Get("/app.config")
// appConfig() {
// return {
// app_id: process.env.QUNSENSE_SUITE_ID
// }
// }
// @Get("/WW_verify_n9zX2u8E9ShFgYmx.txt")
// config(): string {
// return "n9zX2u8E9ShFgYmx";
// }
@Get("/visitor")
@ApiBearerAuth()
async getVisiotr(@Query() { identity_card_no, area_code }: QueryVisitorByNumberDto, @Req() req: any) {
let date = new Date().toDateString();
let node_other_visitor;
const where: any = { identity_card_no, end_time: IsNull() };
if (area_code) {
where.to_area_code = area_code;
}
// console.log("where", where)
const node_other_visitors: any = await this.nodeOtherVisitorRepository.find({
where,
order: {
created_date: "DESC"
}
});
// console.log("node_other_visitors", node_other_visitors)
await bluebird.each(node_other_visitors, async (item) => {
const node_visitor = await this.nodeVisitorRepository.findOne({
where: { id: item.node_visitor_id }
})
// console.log("node_visitor", node_visitor)
// console.log('node_visitor', node_visitor)
// console.log('new Date(node_visitor.start_date)', new Date(node_visitor.start_date))
// console.log('new Date(node_visitor.end_date)', new Date(node_visitor.end_date))
// console.log('new Date(date)', new Date(date))
if (node_visitor && new Date(node_visitor.start_date) <= new Date(date) && new Date(node_visitor.end_date) >= new Date(date)) {
item.info = node_visitor;
node_other_visitor = item;
}
})
// console.log('node_other_visitor', node_other_visitor)
// const node_other_visitor: any = await this.nodeOtherVisitorRepository.findOne({
// where: { identity_card_no, end_time: IsNull() },
// order: {
// created_date: "DESC"
// }
// });
// // console.log('node_other_visitor', node_other_visitor)
// if (node_other_visitor) {
// const node_visitor = await this.nodeVisitorRepository.findOne({
// where: { id: node_other_visitor.node_visitor_id }
// })
// // console.log('node_visitor', node_visitor)
// // console.log('new Date(node_visitor.start_date)', new Date(node_visitor.start_date))
// // console.log('new Date(node_visitor.end_date)', new Date(node_visitor.end_date))
// // console.log('new Date(date)', new Date(date))
// if (node_visitor && new Date(node_visitor.start_date) <= new Date(date) && new Date(node_visitor.end_date) >= new Date(date)) {
// node_other_visitor.info = node_visitor;
// } else {
// return null;
// }
// }
return node_other_visitor
}
@Get("/visitors")
@ApiBearerAuth()
async get(@Query() query_data: QueryVisitorDto, @Req() req: any) {
// console.log("req", req.headers)
if (!req.headers.authorization) {
throw new BadRequestException("无权限")
}
try {
// console.log(`${process.env.RUST_URI}/api/viewer`)
const result = await axios.get(`${process.env.RUST_URI}/api/viewer`, {
headers: {
authorization: req.headers.authorization
}
})
// console.log("result", result)
} catch (e) {
// console.log(e)
throw new BadRequestException("无权限, 请联系管理员")
}
const where: any = {};
if (query_data.applicant) {
where.applicant = query_data.applicant
}
if (query_data.area_code) {
where.to_area_code = query_data.area_code
}
if (query_data.visited_staff) {
where.visited_staff = query_data.visited_staff
}
if (query_data.start_date) {
// where.start_date = query_data.start_date
where.start_date = Between(query_data.start_date, query_data.end_date)
}
// if (query_data.end_date) {
// where.end_date = query_data.end_date
// }
const query = this.nodeVisitorRepository.createQueryBuilder('node-visitor');
query.where(where);
// if (organization_name) {
// query
// .leftJoin(OrganizationEntity, 'organization', `organization.id = bill.organization_id`)
// .andWhere(`organization.full_name like "%${organization_name}%"`)
// }
if (query_data.search) {
const string = `%${query_data.search}%`;
const fields = ['applicant', 'applicant_department', 'code', 'visitor_unit', 'plate_no', 'visited_staff', 'visited_department'];
const searchString = fields.join(' like :search OR node-visitor.');
query.where(`node-visitor.${searchString} like :search`, {
search: string,
});
}
const order_key = 'node-visitor.created_date';
let order_value: any = 'DESC';
const [list, count] = await query
.skip(query_data.skip)
.take(query_data.take)
.orderBy(order_key, order_value)
.getManyAndCount();
// const [list, count] = await this.nodeVisitorRepository.findAndCount({
// skip: query.skip,
// take: query.take,
// order: {
// created_date: "DESC"
// }
// })
const new_list = await bluebird.map(list, async (item) => {
const visitor_list = await this.nodeOtherVisitorRepository.find({
where: { node_visitor_id: item.id },
order: {
created_date: "DESC"
}
})
return {
...item,
visitor_list
}
})
return { list: new_list, count }
}
@Get("/visitor-records")
@ApiBearerAuth()
async getRecord(@Query() query_data: QueryVisitorDto, @Req() req: any) {
// console.log("req", req.headers)
if (!req.headers.authorization) {
throw new BadRequestException("无权限")
}
try {
// console.log(`${process.env.RUST_URI}/api/viewer`)
const result = await axios.get(`${process.env.RUST_URI}/api/viewer`, {
headers: {
authorization: req.headers.authorization
}
})
// console.log("result", result)
} catch (e) {
// console.log(e)
throw new BadRequestException("无权限, 请联系管理员")
}
const where: any = {
start_time: Not(IsNull())
};
if (query_data.start_date) {
where.start_date = query_data.start_date
}
if (query_data.end_date) {
where.end_date = query_data.end_date
}
if (query_data.area_code) {
where.to_area_code = query_data.area_code
}
const query = this.nodeOtherVisitorRepository.createQueryBuilder('node-other-visitor');
query.where(where);
// if (organization_name) {
// query
// .leftJoin(OrganizationEntity, 'organization', `organization.id = bill.organization_id`)
// .andWhere(`organization.full_name like "%${organization_name}%"`)
// }
if (query_data.search) {
const string = `%${query_data.search}%`;
const fields = ['name', 'identity_card_no', 'nationality', 'card_number'];
const searchString = fields.join(' like :search OR node-other-visitor.');
query.where(`node-other-visitor.${searchString} like :search`, {
search: string,
});
}
const order_key = 'node-other-visitor.created_date';
let order_value: any = 'DESC';
const [list, count] = await query
.skip(query_data.skip)
.take(query_data.take)
.orderBy(order_key, order_value)
.getManyAndCount();
// const [list, count] = await this.nodeVisitorRepository.findAndCount({
// skip: query.skip,
// take: query.take,
// order: {
// created_date: "DESC"
// }
// })
// const new_list = await bluebird.map(list, async (item) => {
// const visitor_list = await this.nodeOtherVisitorRepository.find({
// where: { node_visitor_id: item.id },
// order: {
// created_date: "DESC"
// }
// })
// return {
// ...item,
// visitor_list
// }
// })
return { list, count }
}
@Post("/visitor")
async create(@Body() data: CreateVisitor) {
if (new Date(data.apply_date).toString() == "Invalid Date") {
throw new BadRequestException("apply_date 格式不正确")
}
if (new Date(data.start_date).toString() == "Invalid Date") {
throw new BadRequestException("start_date 格式不正确")
}
if (new Date(data.end_date).toString() == "Invalid Date") {
throw new BadRequestException("end_date 格式不正确")
}
const new_code = data.code.split("-")[0];
const area = await this.areaRepository.findOne({ where: { code: new_code } })
if (!area) {
throw new BadRequestException("区域不存在");
}
return await this.dataSource.transaction(async transactionalEntityManager => {
const new_node_visitor = new NodeVisitorEntity();
new_node_visitor.applicant = data.applicant;
new_node_visitor.to_area = area.name;
new_node_visitor.to_area_code = area.code;
new_node_visitor.applicant_department = data.applicant_department;
new_node_visitor.apply_date = moment(data.apply_date).format("YYYY-MM-DD");
// new_node_visitor.apply_date = new Date(data.apply_date).toLocaleDateString();
new_node_visitor.code = data.code;
new_node_visitor.visitor_type = data.visitor_type;
new_node_visitor.area = data.area;
new_node_visitor.visitor_unit = data.visitor_unit;
new_node_visitor.visitor_number = data.visitor_number;
new_node_visitor.transport = data.transport;
new_node_visitor.plate_no = data.plate_no;
// new_node_visitor.start_date = new Date(data.start_date).toLocaleDateString();
new_node_visitor.start_date = moment(data.start_date).format("YYYY-MM-DD");
// new_node_visitor.end_date = new Date(data.end_date).toLocaleDateString();
new_node_visitor.end_date = moment(data.end_date).format("YYYY-MM-DD");
new_node_visitor.visited_staff = data.visited_staff;
new_node_visitor.visited_department = data.visited_department;
new_node_visitor.purpose = data.purpose;
new_node_visitor.electronics = data.electronics;
new_node_visitor.personnel_carrying_electronics = data.personnel_carrying_electronics;
new_node_visitor.sfslqt = data.sfslqt;
// new_node_visitor.electronics = JSON.stringify(data.electronics);
// new_node_visitor.visitor_list = data.visitor_list;
new_node_visitor.may_access_sensitive_info = data.may_access_sensitive_info;
const result = await transactionalEntityManager.save(new_node_visitor);
await bluebird.each(data.visitor_list, async (item) => {
const new_node_other_visitor = new NodeOtherVisitorEntity();
new_node_other_visitor.name = item.name;
new_node_other_visitor.identity_card_no = item.identity_card_no;
new_node_other_visitor.nationality_type = item.nationality_type;
new_node_other_visitor.nationality = item.nationality;
new_node_other_visitor.node_visitor_id = result.id;
new_node_other_visitor.id_type = item.id_type;
new_node_other_visitor.to_area = area.name;
new_node_other_visitor.to_area_code = area.code;
await transactionalEntityManager.save(new_node_other_visitor);
})
return { statusCode: 201, data: result };
});
}
@Post("/area")
async createArea(@Body() data: CreateArea, @Req() req: any) {
if (!req.headers.authorization) {
throw new BadRequestException("无权限")
}
try {
// console.log(`${process.env.RUST_URI}/api/viewer`)
const result = await axios.get(`${process.env.RUST_URI}/api/viewer`, {
headers: {
authorization: req.headers.authorization
}
})
// console.log("result", result)
} catch (e) {
// console.log(e)
throw new BadRequestException("无权限, 请联系管理员")
}
return await this.dataSource.transaction(async transactionalEntityManager => {
const area = new AreaEntity();
area.name = data.name;
area.code = data.code;
const result = await transactionalEntityManager.save(area);
return { statusCode: 201, data: result };
});
}
@Put("/area/:id")
async updateArea(@Param() { id }: any, @Body() data: UpdateArea, @Req() req: any) {
if (!req.headers.authorization) {
throw new BadRequestException("无权限")
}
try {
// console.log(`${process.env.RUST_URI}/api/viewer`)
const result = await axios.get(`${process.env.RUST_URI}/api/viewer`, {
headers: {
authorization: req.headers.authorization
}
})
// console.log("result", result)
} catch (e) {
// console.log(e)
throw new BadRequestException("无权限, 请联系管理员")
}
const area = await this.areaRepository.findOne({ where: { id } });
if (!area) {
throw new NotFoundException("area not found");
}
area.name = data.name;
area.code = data.code;
const result = await this.areaRepository.save(area);
return result;
}
@Delete("/area/:id")
async deleteArea(@Param() { id }: any, @Req() req: any) {
if (!req.headers.authorization) {
throw new BadRequestException("无权限")
}
try {
// console.log(`${process.env.RUST_URI}/api/viewer`)
const result = await axios.get(`${process.env.RUST_URI}/api/viewer`, {
headers: {
authorization: req.headers.authorization
}
})
// console.log("result", result)
} catch (e) {
// console.log(e)
throw new BadRequestException("无权限, 请联系管理员")
}
const result = await this.areaRepository.findOne({ where: { id } });
if (!result) {
throw new NotFoundException("area not found");
}
await this.areaRepository.delete(id);
return result;
}
@Get("/areas")
@ApiBearerAuth()
async areas(@Query() query_data: AreaDto, @Req() req: any) {
// console.log("req", req.headers)
// if (!req.headers.authorization) {
// throw new BadRequestException("无权限")
// }
// try {
// // console.log(`${process.env.RUST_URI}/api/viewer`)
// const result = await axios.get(`${process.env.RUST_URI}/api/viewer`, {
// headers: {
// authorization: req.headers.authorization
// }
// })
// // console.log("result", result)
// } catch (e) {
// // console.log(e)
// throw new BadRequestException("无权限, 请联系管理员")
// }
const where: any = {};
const query = this.areaRepository.createQueryBuilder('area');
query.where(where);
if (query_data.search) {
const string = `%${query_data.search}%`;
const fields = ['name'];
const searchString = fields.join(' like :search OR area.');
query.where(`area.${searchString} like :search`, {
search: string,
});
}
const order_key = 'area.created_date';
let order_value: any = 'DESC';
const [list, count] = await query
.skip(query_data.skip)
.take(query_data.take)
.orderBy(order_key, order_value)
.getManyAndCount();
return { list, count }
}
@Put("/visitor/number")
async updateVisitor(@Body() data: UpdateVisitorNumber) {
const node_other_visitor = await this.nodeOtherVisitorRepository.findOne({ where: { id: data.id } })
if (!node_other_visitor) {
throw new BadRequestException("数据不存在")
}
node_other_visitor.card_number = data.card_number;
const result = await this.nodeOtherVisitorRepository.save(node_other_visitor);
return result;
}
@Put("/visitor/end")
async updateVisitorEnd(@Body() data: UpdateVisitorEnd) {
const node_other_visitor = await this.nodeOtherVisitorRepository.findOne({ where: { id: data.id } })
if (!node_other_visitor) {
throw new BadRequestException("数据不存在")
}
if (data.area_code) {
const area = await this.areaRepository.findOne({ where: { code: data.area_code } });
if (!area) {
throw new NotFoundException("area not found");
}
if (node_other_visitor.to_area != area.name) {
throw new NotFoundException("厂区错误");
}
}
if (node_other_visitor.end_time) {
// throw new BadRequestException("拜访已结束")
return {
code: 400,
message: "拜访已结束"
}
}
node_other_visitor.end_time = new Date();
const result = await this.nodeOtherVisitorRepository.save(node_other_visitor);
return result;
}
@Put("/visitor/start")
async updateVisitorStart(@Body() data: UpdateVisitorEnd) {
const node_other_visitor = await this.nodeOtherVisitorRepository.findOne({ where: { id: data.id } })
if (!node_other_visitor) {
throw new BadRequestException("数据不存在")
}
if (data.area_code) {
const area = await this.areaRepository.findOne({ where: { code: data.area_code } });
if (!area) {
throw new NotFoundException("area not found");
}
if (node_other_visitor.to_area != area.name) {
throw new NotFoundException("厂区错误");
}
}
node_other_visitor.start_time = new Date();
const result = await this.nodeOtherVisitorRepository.save(node_other_visitor);
return result;
}
@Post('upload/base64')
async louploadBase64Filegin(
@Body() input: any,
@Req() req: any,
): Promise<any> {
try {
const file_name = uuid() + '.jpg';
const id_file_name = uuid() + '.id.jpg';
//过滤data:URL
const base64Data = input.image1.replace(/^data:image\/\w+;base64,/, '');
const base64Data2 = input.image2.replace(/^data:image\/\w+;base64,/, '');
const dataBuffer = new Buffer(base64Data, 'base64');
const first = './upload/' + file_name;
fs.writeFileSync(first, dataBuffer);
const second = './upload/' + id_file_name;
const dataBuffer2 = new Buffer(base64Data2, 'base64');
fs.writeFileSync(second, dataBuffer2);
fs.writeFileSync(
'./upload/' + uuid() + '-log.log',
JSON.stringify(input),
);
const { result } = await verificationService.verify(first, second, null);
if (
result &&
result.length > 0 &&
result[0].face_matches &&
result[0].face_matches.length > 0
) {
console.log('result[0].face_matches[0]', result[0].face_matches[0]);
return {
code: 0,
data: { score: result[0].face_matches[0].similarity * 100 },
msg: '成功',
};
}
// console.log('dd', JSON.stringify(result));
return {
code: -1,
msg: '失败',
data: result,
};
} catch (e) {
console.log("e", e)
return {
code: -2,
msg: e.message,
};
}
}
@Get('version.json')
async version(
@Req() req: any,
): Promise<any> {
return {
"versionName": "1.2.0",
"apkUrl": `http://${process.env.LOCAL_IP}/app.apk`,
"forceUpdate": false,
"whatsNew": "新版本更新"
};
}
@Get('app.apk')
async file(
@Res() res: any,
): Promise<any> {
const file_path = join(__dirname, "./apk/app.apk")
res.sendFile(file_path)
}
}