This commit is contained in:
sx1989827 2021-12-27 21:59:34 +08:00
parent 867d1595a6
commit 0e724bd185
41 changed files with 619 additions and 68 deletions

View File

@ -1,12 +1,10 @@
export interface ICommon_Model_Field {
id:string,
type_id:string,
system:number,
reserved:number,
description:string,
created_time:Date,
modified_time:Date,
created_by:string,
modified_by:string,
name:string
}
export const Table_Field="field"

View File

@ -2,14 +2,8 @@ import { BaseModel } from "./base"
export interface ICommon_Model_Field_Component_Field {
id:string,
type_id:string,
system:number,
description:string,
created_time:Date,
modified_time:Date,
created_by:string,
modified_by:string,
name:string
field_component_id:string,
field_id:string
}
export const Table_Field_Component_Field="field_component_field"

View File

@ -6,6 +6,6 @@ export interface ICommon_Model_Field_Solution {
modified_by: string,
name :string,
description :string,
system :number,
reserved :number,
}
export const Table_Field_Solution="field_solution"

View File

@ -1,8 +1,19 @@
import { BaseModel } from "./base"
export interface ICommon_Model_Issue_Type {
id:string,
name:string,
icon:string,
description:string,
multi:number
reserved:number,
created_time:Date,
modify_time:Date,
}
export const Table_Issue_Type="issue_type"
export const Table_Issue_Type="issue_type"
class IssueTypeModel extends BaseModel {
table=Table_Issue_Type
model=<ICommon_Model_Issue_Type>{}
}
export let issueTypeModel=new IssueTypeModel

View File

@ -1,11 +1,18 @@
import { BaseModel } from "./base"
export interface ICommon_Model_Issue_Type_Solution {
id :string ,
name :string,
description :string,
system :number,
reserved :number,
created_time :Date,
modified_time :Date,
created_by :string ,
modified_by :string ,
}
export const Table_Issue_Type_Solution="issue_type_solution"
export const Table_Issue_Type_Solution="issue_type_solution"
class IssueTypeSolutionModel extends BaseModel {
table=Table_Issue_Type_Solution
model=<ICommon_Model_Issue_Type_Solution>{}
}
export let issueTypeSolutionModel=new IssueTypeSolutionModel

View File

@ -1,6 +1,15 @@
export interface ICommon_Model_Issue_Type {
import { BaseModel } from "./base"
export interface ICommon_Model_Issue_Type_Solution_Issue_Type {
id :string ,
issue_type_id :string,
issue_type_solution_id :string,
}
export const Table_Issue_Type="issue_type"
export const Table_Issue_Type_Solution_Issue_Type="issue_type"
class IssueTypeSolutionIssueTypeModel extends BaseModel {
table=Table_Issue_Type_Solution_Issue_Type
model=<ICommon_Model_Issue_Type_Solution_Issue_Type>{}
}
export let issueTypeSolutionIssueTypeModel=new IssueTypeSolutionIssueTypeModel

View File

@ -2,10 +2,8 @@ export interface ICommon_Model_Workflow {
id :string ,
name :string,
description :string,
system :number,
reserved :number,
created_time :Date,
modified_time :Date,
created_by :string ,
modified_by :string ,
}
export const Table_Workflow="workflow"

View File

@ -1,7 +1,7 @@
export interface ICommon_Model_Workflow_Action {
id :string ,
name :string,
system :number,
reserved :number,
description :string,
source_node_id :string ,
dest_node_id :string ,

View File

@ -2,7 +2,7 @@ export interface ICommon_Model_Workflow_Node {
id :string ,
name :string,
description :string,
system :number,
reserved :number,
status :number,
workflow_id :string ,
}

View File

@ -2,9 +2,7 @@ export interface ICommon_Model_Workflow_Solution {
id :string ,
created_time :Date,
modified_time :Date,
created_by :string ,
modified_by :string,
system :number,
reserved :number,
name :string,
description :string,
}

View File

@ -0,0 +1,55 @@
import { ICommon_Model_Issue_Type } from './../model/issue_type';
import { ECommon_Services } from './../types';
import { ECommon_HttpApi_Method } from "./types";
const api={
baseUrl:"/issuetype",
service:ECommon_Services.Cooperation,
routes:{
list:{
method:ECommon_HttpApi_Method.GET,
path:"/list",
req:<{
}>{},
res:<ICommon_Model_Issue_Type[]>{}
},
info:{
method:ECommon_HttpApi_Method.GET,
path:"/item",
req:<{
issueTypeId:string
}>{},
res:<ICommon_Model_Issue_Type>{}
},
create:{
method:ECommon_HttpApi_Method.POST,
path:"/item",
req:<{
name:string,
icon?:string,
description?:string
}>{},
res:<ICommon_Model_Issue_Type>{}
},
update:{
method:ECommon_HttpApi_Method.PUT,
path:"/item",
req:<{
issueTypeId:string,
name?:string,
icon?:string,
description?:string
}>{},
res:<ICommon_Model_Issue_Type>{}
},
delete:{
method:ECommon_HttpApi_Method.DELETE,
path:"/item",
req:<{
issueTypeId:string
}>{},
res:{}
},
}
}
export=api

View File

@ -23,7 +23,7 @@ const api={
req:<{
keyword :string,
name :string,
image? :string,
photo? :string,
description? :string,
}>{},
res:<ICommon_Model_Project>{}
@ -34,7 +34,7 @@ const api={
req:<{
keyword? :string,
name? :string,
image? :string,
photo? :string,
description? :string,
projectId:string
}>{},
@ -173,7 +173,8 @@ const api={
req:<{
keyword?:string,
page:number,
size:number
size:number,
userId?:string
}>{},
res:<ICommon_Route_Res_Project_List>{},
},

View File

@ -100,6 +100,18 @@ const api={
}>{},
res:<ICommon_Route_Res_Team_List>{},
},
filterTeam:{
method:ECommon_HttpApi_Method.GET,
path:"/filter",
req:<{
name:string
}>{},
res:<{
name:string,
id:string,
photo:string
}[]>{},
}
}
}
export=api

View File

@ -133,6 +133,26 @@ const api={
userId?:string
}>{},
res:<ICommon_Route_Res_User_Profile>{},
},
infos:{
method:ECommon_HttpApi_Method.GET,
path:"/infos",
req:<{
userIds:string
}>{},
res:<Omit<ICommon_Model_User,"password"|"created_time"|"modified_time">[]>{},
},
filterUser:{
method:ECommon_HttpApi_Method.GET,
path:"/filter",
req:<{
name:string
}>{},
res:<{
name:string,
id:string,
photo:string
}[]>{},
}
}
}

View File

@ -91,6 +91,16 @@ export namespace Err {
code:3301,
msg:"member not exists"
}
},
Issue : {
issueTypeNotFound:{
code:3400,
msg:"issue type not found"
},
issueTypeForbidden:{
code:3401,
msg:"issue type forbidden"
}
}
}
export let Team = {

View File

@ -3,6 +3,12 @@ import { Err } from '../../../common/status/error';
import { EServer_Common_Event_Types } from '../event/types';
import { emitServiceEvent } from '../rpc/rpc';
import { Mapper } from './mapper';
let imagefields=[
"photo",
"image",
"img",
"icon"
]
export abstract class Entity<T extends BaseModel,M extends Mapper<T>> {
protected item:T["model"];
protected _item:T["model"];
@ -20,9 +26,9 @@ export abstract class Entity<T extends BaseModel,M extends Mapper<T>> {
setItem(item:T["model"]) {
this.item=item
}
assignItem(item:Partial<T["model"]>) {
assignItem(item:Partial<T["model"]>,clear:boolean=false) {
if(typeof(item)=="object") {
if(!this.item) {
if(!this.item || clear) {
this.item=<T>{}
}
for(let key in item) {
@ -41,9 +47,11 @@ export abstract class Entity<T extends BaseModel,M extends Mapper<T>> {
}
await this.mapper.create(this.item)
await this.loadItem();
if(this.item["photo"]) {
emitServiceEvent(EServer_Common_Event_Types.File.REF,this.item["photo"])
}
imagefields.forEach(item=>{
if(this.item[item]) {
emitServiceEvent(EServer_Common_Event_Types.File.REF,this.item[item])
}
})
return this.item;
}
async update():Promise<T["model"]>{
@ -52,14 +60,17 @@ export abstract class Entity<T extends BaseModel,M extends Mapper<T>> {
}
let ret=await this.mapper.getById(this.item.id)
await this.mapper.update(this.item)
if(!ret["photo"] && this.item["photo"]) {
emitServiceEvent(EServer_Common_Event_Types.File.REF,this.item["photo"])
} else if(ret["photo"] && ret["photo"]!=this.item["photo"]) {
if(this.item["photo"]) {
emitServiceEvent(EServer_Common_Event_Types.File.REF,this.item["photo"])
imagefields.forEach(item=>{
if(!ret[item] && this.item[item]) {
emitServiceEvent(EServer_Common_Event_Types.File.REF,this.item[item])
} else if(ret[item] && ret[item]!=this.item[item]) {
if(this.item[item]) {
emitServiceEvent(EServer_Common_Event_Types.File.REF,this.item[item])
}
emitServiceEvent(EServer_Common_Event_Types.File.UNREF,ret[item])
}
emitServiceEvent(EServer_Common_Event_Types.File.UNREF,ret["photo"])
}
})
await this.loadItem();
return this.item;
}
async delete(eventPulish?:EServer_Common_Event_Types.Types){
@ -67,9 +78,12 @@ export abstract class Entity<T extends BaseModel,M extends Mapper<T>> {
if(eventPulish) {
emitServiceEvent(eventPulish,this.item.id);
}
if(this.item["photo"]) {
emitServiceEvent(EServer_Common_Event_Types.File.UNREF,this.item["photo"])
}
imagefields.forEach(item=>{
if(this.item[item]) {
emitServiceEvent(EServer_Common_Event_Types.File.UNREF,this.item[item])
}
})
}
async loadItem():Promise<T["model"]>{
if(!this.item || !this.item.id) {

View File

@ -28,7 +28,9 @@ export abstract class Mapper<T extends BaseModel> {
return ret
}
async updateConfig(info:T["model"]){}
async update(info:T["model"]):Promise<void> {
async update(data:T["model"]):Promise<void> {
let info:T["model"]={}
Object.assign(info,data)
if(!info.id) {
throw Err.Common.itemNotFound
}

View File

@ -1,5 +1,5 @@
export namespace EServer_Common_Event_Types {
export type Types= User|Project|Team|File
export type Types= User|Project|Team|File|IssueType
export enum User {
DELETE="delete user" //userId:string
}
@ -13,4 +13,7 @@ export namespace EServer_Common_Event_Types {
REF="ref file",
UNREF="unref file" //fileId:string
}
export enum IssueType {
DELETE="delete issueType" //issueTypeId:string
}
}

View File

@ -0,0 +1,5 @@
export default interface IServer_Common_RPC_File {
getPath?(fileId:string):Promise<string>
getPaths?(fileIds:string[]):Promise<string[]>
}

View File

@ -36,9 +36,13 @@ function handleExp(key:string,value:EXPRVALUEEXP,arrExpr:string[]) {
} else if(value.exp=="is null") {
arrExpr.push(`${key} is null`)
} else if(value.exp=="in") {
arrExpr.push(`${key} in (${(<string[] | number[]>value.value).map((item)=>{
return typeof(item)=="number"?item:("'"+item+"'")
}).join(",")})`)
if(typeof(value.value)=="string") {
arrExpr.push(`${key} in (${value.value})`)
} else {
arrExpr.push(`${key} in (${(<string[] | number[]>value.value).map((item)=>{
return typeof(item)=="number"?item:("'"+item+"'")
}).join(",")})`)
}
} else if(value.exp=="is not null") {
arrExpr.push(`${key} is not null`)
} else if(value.exp=="between") {
@ -575,4 +579,19 @@ export function exculdeColumns<R1 extends keyof BaseModel["model"],R2 extends R1
})
return <any>arr;
}
}
export function generateCountSql<T extends BaseModel>(model:T,objExpr?:{
[param in keyof T["model"]]?:EXPRVALUE
},exprMode?:"and"|"or"):{
value:string,
type:{
[key in keyof T["model"]]:T["model"][key]
}
} {
let expr=generateExp(objExpr,exprMode);
return {
value:`select count(1) from ${model.table}${expr?(" where "+expr):""}`,
type:model.model
}
}

View File

@ -1,4 +1,5 @@
import Application from "../../common/app/app";
import "../http/issueType";
import "../http/module";
import "../http/project";
import "../http/tag";

View File

@ -0,0 +1,67 @@
import * as issueTypeApi from "../../../common/routes/issueType";
import { Err } from "../../../common/status/error";
import { DComponent } from "../../common/decorate/component";
import { DHttpApi, DHttpController, DHttpReqParam, DHttpReqParamRequired } from "../../common/http/http";
import IssueTypeService from "../service/issueType";
@DComponent
@DHttpController(issueTypeApi)
class IssueTypeController {
@DHttpApi(issueTypeApi.routes.list)
async list():Promise<typeof issueTypeApi.routes.list.res> {
let ret=await IssueTypeService.list()
return ret;
}
@DHttpApi(issueTypeApi.routes.info)
async info(@DHttpReqParamRequired("issueTypeId") issueTypeId:string):Promise<typeof issueTypeApi.routes.info.res> {
let ret=await IssueTypeService.getItemById(issueTypeId)
if(!ret) {
throw Err.Project.Issue.issueTypeNotFound
}
return ret.getItem();
}
@DHttpApi(issueTypeApi.routes.create)
async create(@DHttpReqParamRequired("name") name:string,@DHttpReqParam("icon") icon:string,@DHttpReqParam("description") description:string):Promise<typeof issueTypeApi.routes.create.res> {
let obj=new IssueTypeService()
obj.assignItem({
name,
icon,
description
})
let ret=await obj.create()
return ret;
}
@DHttpApi(issueTypeApi.routes.update)
async update(@DHttpReqParamRequired("issueTypeId") issueTypeId:string,@DHttpReqParam("name") name:string,@DHttpReqParam("icon") icon:string,@DHttpReqParam("description") description:string):Promise<typeof issueTypeApi.routes.update.res> {
let obj=await IssueTypeService.getItemById(issueTypeId)
if(!obj) {
throw Err.Project.Issue.issueTypeNotFound
}
if(obj.getItem().reserved) {
throw Err.Project.Issue.issueTypeForbidden
}
obj.assignItem({
id:issueTypeId,
name,
icon,
description
},true)
let ret=await obj.update()
return ret;
}
@DHttpApi(issueTypeApi.routes.delete)
async delete(@DHttpReqParamRequired("issueTypeId") issueTypeId:string,@DHttpReqParam("name") name:string,@DHttpReqParam("icon") icon:string,@DHttpReqParam("description") description:string):Promise<typeof issueTypeApi.routes.delete.res> {
let obj=await IssueTypeService.getItemById(issueTypeId)
if(!obj) {
throw Err.Project.Issue.issueTypeNotFound
}
if(obj.getItem().reserved) {
throw Err.Project.Issue.issueTypeForbidden
}
await obj.delete()
return;
}
}

View File

@ -3,6 +3,7 @@ import * as projectApi from "../../../common/routes/project";
import { Err } from "../../../common/status/error";
import { DHttpApi, DHttpController, DHttpReqParam, DHttpReqParamRequired, DHttpUser } from "../../common/http/http";
import { IUserSession } from "../../common/rpc/api/user";
import { EServer_Common_User_Type } from "../../common/types/user";
import ProjectService from "../service/project";
@DHttpController(projectApi)
@ -96,8 +97,14 @@ class ProjectController {
}
@DHttpApi(projectApi.routes.list)
async list(@DHttpReqParam("keyword") keyword:string,@DHttpReqParamRequired("page") page:number,@DHttpReqParamRequired("size") size:number) :Promise<typeof projectApi.routes.list.res>{
let list=await ProjectService.list(page,size,keyword)
async list(@DHttpReqParam("keyword") keyword:string,@DHttpReqParamRequired("page") page:number,@DHttpReqParamRequired("size") size:number,@DHttpReqParam("userId") userId:string,@DHttpUser userInfo:IUserSession) :Promise<typeof projectApi.routes.list.res>{
let user=""
if(userInfo.type==EServer_Common_User_Type.ADMIN && userId) {
user=userId
} else if(userInfo.type==EServer_Common_User_Type.USER) {
user=userInfo.userId
}
let list=await ProjectService.list(page,size,keyword,user)
return list
}

View File

@ -0,0 +1,19 @@
import { getMysqlInstance } from "../../common/db/mysql";
import { Mapper } from "../../common/entity/mapper";
import { generateQuerySql } from "../../common/util/sql";
import { ICommon_Model_Issue_Type, issueTypeModel } from './../../../common/model/issue_type';
class IssueTypeMapper extends Mapper<typeof issueTypeModel> {
constructor() {
super(issueTypeModel)
}
async list():Promise<ICommon_Model_Issue_Type[]>
{
let mysql=getMysqlInstance()
let ret=await mysql.execute(generateQuerySql(issueTypeModel,[],null,null,{
field:"name",
type:"asc"
}))
return ret;
}
}
export let issueTypeMapper=new IssueTypeMapper

View File

@ -181,7 +181,7 @@ class ProjectMapper extends Mapper<typeof projectModel>{
}))
}
async list(page:number,size:number,keyword?:string):Promise<{
async list(page:number,size:number,keyword?:string,userId?:string):Promise<{
count:number,
totalPage:number,
data:ICommon_Model_Project[]
@ -190,14 +190,36 @@ class ProjectMapper extends Mapper<typeof projectModel>{
throw Err.Common.paramError
}
var mysql=getMysqlInstance();
let count=Object.values(await mysql.executeOne<number>(`select count(1) from ${Table_Project}${keyword?` where name like '%${keyword}%'`:""}`))[0]
let str=`select count(1) from ${Table_Project}`,keywrodStr="",userIdStr=""
if(keyword) {
keywrodStr=`name like '%${keyword}%'`
}
if(userId) {
userIdStr=`id in (select project_id from ${Table_Project_Member} where member_id='${userId}')`
}
if(keywrodStr && userIdStr) {
str+=" where "+keywrodStr+" and "+userIdStr
} else if(keywrodStr) {
str+=" where "+keywrodStr
} else if(userIdStr) {
str+=" where "+userIdStr
}
let count=Object.values(await mysql.executeOne<number>(str))[0]
let totalPage=CommonUtil.pageTotal(count,size)
let ret=await mysql.execute(generateQuerySql(projectModel,[],keyword?{
name:{
exp:"%like%",
value:keyword
}
}:null,"and",{
let ret=await mysql.execute(generateQuerySql(projectModel,[],{
...(keyword && {
name:{
exp:"%like%",
value:keyword
}
}),
...(userId && {
id:{
exp:"in",
value:`select project_id from ${Table_Project_Member} where member_id='${userId}'`
}
})
},"and",{
field:"name",
type:"asc"
},page*size,size))

View File

@ -0,0 +1,12 @@
import { Entity } from "../../common/entity/entity";
import { issueTypeModel } from './../../../common/model/issue_type';
import { issueTypeMapper } from './../mapper/issueType';
export default class IssueType extends Entity<typeof issueTypeModel,typeof issueTypeMapper> {
constructor(){
super(issueTypeMapper)
}
static async list(){
let ret=await issueTypeMapper.list()
return ret;
}
}

View File

@ -36,8 +36,8 @@ export default class Project extends Entity<typeof projectModel,typeof projectMa
await projectMapper.changeRole(this.item.id,memberId,roleId)
}
static async list(page:number,size:number,keyword?:string):Promise<ICommon_Route_Res_Project_List>{
let ret=await projectMapper.list(page,size,keyword)
static async list(page:number,size:number,keyword?:string,userId?:string):Promise<ICommon_Route_Res_Project_List>{
let ret=await projectMapper.list(page,size,keyword,userId)
return {
count:ret.count,
totalPage:ret.totalPage,

View File

@ -6,6 +6,7 @@ import CommonUtil from "../../common/util/common";
import { generateDeleteSql } from "../../common/util/sql";
import "../event/file";
import "../http/file";
import "../rpc/file";
import { ECommon_Model_File_Type, fileModel, ICommon_Model_File, Table_File } from './../../../common/model/file';
import path = require("path");
export default class File extends Application {

View File

@ -15,6 +15,20 @@ class FileMapper extends Mapper<typeof fileModel> {
let ret=await mysql.executeOne(generateQuerySql(fileModel,[],{md5:md5}))
return ret
}
async getPaths(ids:string[]) {
if(!ids) {
throw Err.File.fileNotFound
}
var mysql=getMysqlInstance()
let ret=await mysql.execute(generateQuerySql(fileModel,[],{
id:{
exp:"in",
value:ids
}
}))
return ret;
}
}
export let fileMapper=new FileMapper()

View File

@ -0,0 +1,25 @@
import IServer_Common_RPC_File from "../../common/rpc/api/file";
import { DRPCRecieve } from "../../common/rpc/rpc";
import FileService from "../service/file";
class RpcFileApi implements IServer_Common_RPC_File {
@DRPCRecieve
async getPath(fileId: string): Promise<string> {
if(!fileId) {
return ""
}
let obj=await FileService.getItemById(fileId)
if(!obj) {
return ""
}
return "/file"+obj.getItem().path
}
@DRPCRecieve
async getPaths(fileIds: string[]): Promise<string[]> {
if(!fileIds || fileIds.length==0) {
return []
}
let obj=await FileService.getPaths(fileIds)
return obj;
}
}
export default new RpcFileApi;

View File

@ -30,4 +30,15 @@ export default class File extends Entity<typeof fileModel,typeof fileMapper> {
await super.create()
return this.item.id;
}
static async getPaths(ids:string[]){
let ret=await fileMapper.getPaths(ids);
return ret.map(item=>{
if(item && item.path) {
return "/file"+item.path
} else {
return ""
}
})
}
}

View File

@ -5,6 +5,7 @@ import * as koaStaticServer from "koa-static-server";
import { PassThrough } from "stream";
import { Permission_Base } from '../../../common/permission/permission';
import * as fileApi from "../../../common/routes/file";
import * as issueTypeApi from "../../../common/routes/issueType";
import * as projectApi from "../../../common/routes/project";
import * as teamApi from "../../../common/routes/team";
import { ICommon_HttpApi } from "../../../common/routes/types";
@ -22,10 +23,10 @@ import { EServer_Common_User_Type } from '../../common/types/user';
import CommonUtil from "../../common/util/common";
import { generateHttpErrorResponse, generateHttpOkResponse } from "../../common/util/http";
import userRpcApi from '../rpc/user';
import { initSystem, parseFormData } from "../util/util";
import { handleImageFields, initSystem, parseFormData } from "../util/util";
import { ICommon_Version_Config } from './../../../common/model/version';
import { CacheService } from './../cache/service';
var apis:ICommon_HttpApi[]=[userApi,projectApi,teamApi,fileApi];
var apis:ICommon_HttpApi[]=[userApi,projectApi,teamApi,fileApi,issueTypeApi];
var app = new Koa();
var config=<ICommon_Version_Config>{}
var pipe = function (from, to): Promise<Buffer> {
@ -129,10 +130,10 @@ export default class GateWay extends Application {
app.use(async function (ctx, next) {
let path = ctx.path
if(path.startsWith("/api/")) {
path = path.substr("/api".length)
path = path.substring("/api".length)
let method = ctx.req.method;
let baseUrl = path.substring(1, path.indexOf("/", 1))
let apiPath = path.substr(1 + baseUrl.length)
let apiPath = path.substring(1 + baseUrl.length)
if (apiMap[baseUrl] && apiMap[baseUrl][method + " " + apiPath]) {
let microServer = apiMap[baseUrl][method + " " + apiPath].service
let ignoreValidate = apiMap[baseUrl][method + " " + apiPath].ignoreValidate
@ -191,6 +192,9 @@ export default class GateWay extends Application {
}
if(ret.data===undefined || typeof(ret.data)=="string" || typeof(ret.data)=="number" || typeof(ret.data)=="boolean" || typeof(ret.data)=="object")
{
if(typeof(ret.data)=="object") {
await handleImageFields(ret.data);
}
ctx.body = generateHttpOkResponse(ret.data);
} else {
ctx.body = ret.data;

View File

@ -0,0 +1,10 @@
import { ECommon_Services } from '../../../common/types';
import IServer_Common_RPC_File from "../../common/rpc/api/file";
import { DRPCSend } from "../../common/rpc/rpc";
class RpcFileApi implements IServer_Common_RPC_File {
@DRPCSend(ECommon_Services.File)
async getPaths(fileIds: string[]): Promise<string[]> {
return null;
}
}
export default new RpcFileApi

View File

@ -5,6 +5,10 @@ import { Permission_Base, Permission_Types } from '../../../common/permission/pe
import { getMysqlInstance } from "../../common/db/mysql";
import { getNacosInstance } from '../../common/nacos/nacos';
import { generateSnowId } from '../../common/util/sql';
import rpcFileApi from '../rpc/file';
import { Table_Issue_Type } from './../../../common/model/issue_type';
import { Table_Issue_Type_Solution } from './../../../common/model/issue_type_solution';
import { Table_Issue_Type_Solution_Issue_Type } from './../../../common/model/issue_type_solution_issue_type';
import { Table_Permission } from './../../../common/model/permission';
import { Table_Project_Member } from './../../../common/model/project_member';
import { Table_Project_Role } from './../../../common/model/project_role';
@ -74,6 +78,41 @@ export function parseFormData(str: Buffer, boundary: string): IServer_GateWay_Fo
return ret;
}
export async function handleImageFields(data:object){
let arr=<{
object:object,
key:string|number
}[]>[]
function _clone(o){
var k, b;
if(o && ((b = (o instanceof Array)) || o instanceof Object)) {
for(k in o){
if(o.hasOwnProperty(k)){
if(["photo","image","icon","img"].includes(k) && typeof(o[k])=="string" && o[k].length>=18 && /^\d+$/.test(o[k])) {
arr.push({
object:o,
key:k
})
} else {
_clone(o[k])
}
}
}
}
}
_clone(data)
if(arr.length>0) {
let ids=arr.map(item=>{
return item.object[item.key];
})
let paths=await rpcFileApi.getPaths(ids)
for(let i=0;i<arr.length;i++)
{
arr[i].object[arr[i].key]=paths[i]
}
}
}
async function resetSystem(){
let mysql=getMysqlInstance()
await mysql.execute(`delete from ${Table_Version}`)
@ -86,6 +125,9 @@ async function resetSystem(){
await mysql.execute(`delete from ${Table_Team_Role}`)
await mysql.execute(`delete from ${Table_Team}`)
await mysql.execute(`delete from ${Table_Team_User}`)
await mysql.execute(`delete from ${Table_Issue_Type}`)
await mysql.execute(`delete from ${Table_Issue_Type_Solution}`)
await mysql.execute(`delete from ${Table_Issue_Type_Solution_Issue_Type}`)
}
export async function initSystem() {
@ -158,6 +200,9 @@ export async function initSystem() {
}
}
await mysql.execute(`insert into ${Table_Team_User} (id,role_id,team_id,user_id) values ('${await generateSnowId()}','${groupRoleUserId}','${groupId}','${userId}')`)
await mysql.execute(`insert into ${Table_Issue_Type} (id,name,reserved) values ('${await generateSnowId()}','Task',1)`)
await mysql.execute(`insert into ${Table_Issue_Type} (id,name,reserved) values ('${await generateSnowId()}','Bug',1)`)
await mysql.execute(`insert into ${Table_Issue_Type} (id,name,reserved) values ('${await generateSnowId()}','Ticket',1)`)
}
console.log("init finish")
}

View File

@ -107,4 +107,10 @@ class TeamController {
return list
}
@DHttpApi(teamApi.routes.filterTeam)
async filterTeam(@DHttpReqParamRequired("name") name:string) :Promise<typeof teamApi.routes.filterTeam.res>{
let ret=await TeamService.filter(name,10);
return ret;
}
}

View File

@ -145,4 +145,16 @@ class UserController {
let ret=await user.profile()
return ret;
}
@DHttpApi(userApi.routes.infos)
async infos(@DHttpReqParam("userIds") userIds:string) :Promise<typeof userApi.routes.infos.res>{
let ret=await UserService.userInfos(userIds)
return ret;
}
@DHttpApi(userApi.routes.filterUser)
async filterUser(@DHttpReqParamRequired("name") name:string) :Promise<typeof userApi.routes.filterUser.res>{
let ret=await UserService.filter(name,10);
return ret;
}
}

View File

@ -194,6 +194,27 @@ class TeamMapper extends Mapper<typeof teamModel> {
data:ret
};
}
async filter(name:string,size:number)
{
if(!name) {
throw Err.User.userNameNotExists
}
if(!size) {
throw Err.Common.paramError
}
let mysql=getMysqlInstance()
let ret=await mysql.execute(generateQuerySql(teamModel,["id","name","photo"],{
name:{
exp:"%like%",
value:name
}
},"and",{
field:"name",
type:"asc"
},0,size))
return ret;
}
}
export let teamMapper=new TeamMapper()

View File

@ -171,5 +171,41 @@ class UserMapper extends Mapper<typeof userModel> {
data:ret.map(item=>item.project)
};
}
async users(userIds:string[]){
if(!userIds){
throw Err.User.userIdNotExists
}
let mysql=getMysqlInstance()
let ret=await mysql.execute(generateQuerySql(userModel,[],{
id:{
exp:"in",
value:userIds
}
}))
return ret;
}
async filter(name:string,size:number)
{
if(!name) {
throw Err.User.userNameNotExists
}
if(!size) {
throw Err.Common.paramError
}
let mysql=getMysqlInstance()
let ret=await mysql.execute(generateQuerySql(userModel,["id","username","photo"],{
admin:0,
active:1,
username:{
exp:"%like%",
value:name
}
},"and",{
field:"username",
type:"asc"
},0,size))
return ret;
}
}
export let userMapper=new UserMapper()

View File

@ -0,0 +1,10 @@
import { ECommon_Services } from '../../../common/types';
import IServer_Common_RPC_File from "../../common/rpc/api/file";
import { DRPCSend } from "../../common/rpc/rpc";
class RpcFileApi implements IServer_Common_RPC_File {
@DRPCSend(ECommon_Services.File)
async getPath(fileId: string): Promise<string> {
return null;
}
}
export default new RpcFileApi

View File

@ -3,6 +3,7 @@ import { ICommon_Route_Res_Team_List } from '../../../common/routes/response';
import { Err } from '../../../common/status/error';
import { Entity } from "../../common/entity/entity";
import { teamMapper } from '../mapper/team';
import rpcFileApi from "../rpc/file";
import { teamModel } from './../../../common/model/team';
export default class Team extends Entity<typeof teamModel,typeof teamMapper> {
constructor(){
@ -61,4 +62,31 @@ export default class Team extends Entity<typeof teamModel,typeof teamMapper> {
}
}
static async filter(name:string,size:number):Promise<{
name:string,
id:string,
photo:string
}[]>{
if(!name) {
throw Err.User.userNameNotExists
}
if(!size) {
throw Err.Common.paramError
}
let ret=await teamMapper.filter(name,size);
let arr=<{
name:string,
id:string,
photo:string
}[]>[]
for(let obj of ret) {
arr.push({
name:obj.name,
id:obj.id,
photo:obj.photo?(await rpcFileApi.getPath(obj.photo)):obj.photo
})
}
return ret;
}
}

View File

@ -5,7 +5,8 @@ import { REDIS_USER } from "../../common/cache/keys/user";
import { Entity } from "../../common/entity/entity";
import { getNacosInstance } from '../../common/nacos/nacos';
import { userMapper } from '../mapper/user';
import { userModel } from './../../../common/model/user';
import rpcFileApi from "../rpc/file";
import { ICommon_Model_User, userModel } from './../../../common/model/user';
import { EServer_Common_User_Type } from './../../common/types/user';
export default class User extends Entity<typeof userModel,typeof userMapper> {
constructor(){
@ -107,4 +108,47 @@ export default class User extends Entity<typeof userModel,typeof userMapper> {
delete ret.info.password
return ret;
}
static async userInfos(userIds:string):Promise<Omit<ICommon_Model_User,"password"|"created_time"|"modified_time">[]>{
if(!userIds) {
throw Err.User.userIdNotExists
}
let ret=await userMapper.users(userIds.split(","))
for(let obj of ret) {
delete obj.password;
delete obj.created_time;
delete obj.modified_time;
if(obj.photo) {
obj.photo=await rpcFileApi.getPath(obj.photo)
}
}
return ret;
}
static async filter(name:string,size:number):Promise<{
name:string,
id:string,
photo:string
}[]>{
if(!name) {
throw Err.User.userNameNotExists
}
if(!size) {
throw Err.Common.paramError
}
let ret=await userMapper.filter(name,size);
let arr=<{
name:string,
id:string,
photo:string
}[]>[]
for(let obj of ret) {
arr.push({
name:obj.username,
id:obj.id,
photo:obj.photo?(await rpcFileApi.getPath(obj.photo)):obj.photo
})
}
return arr;
}
}