mirror of
https://github.com/Teamlinker/Teamlinker.git
synced 2025-06-03 03:00:17 +00:00
aa
This commit is contained in:
parent
867d1595a6
commit
0e724bd185
@ -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"
|
@ -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"
|
||||
|
||||
|
@ -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"
|
@ -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
|
@ -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
|
@ -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
|
@ -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"
|
@ -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 ,
|
||||
|
@ -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 ,
|
||||
}
|
||||
|
@ -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,
|
||||
}
|
||||
|
55
code/common/routes/issueType.ts
Normal file
55
code/common/routes/issueType.ts
Normal 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
|
@ -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>{},
|
||||
},
|
||||
|
@ -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
|
@ -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
|
||||
}[]>{},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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 = {
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
}
|
5
code/server/common/rpc/api/file.ts
Normal file
5
code/server/common/rpc/api/file.ts
Normal file
@ -0,0 +1,5 @@
|
||||
|
||||
export default interface IServer_Common_RPC_File {
|
||||
getPath?(fileId:string):Promise<string>
|
||||
getPaths?(fileIds:string[]):Promise<string[]>
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
import Application from "../../common/app/app";
|
||||
import "../http/issueType";
|
||||
import "../http/module";
|
||||
import "../http/project";
|
||||
import "../http/tag";
|
||||
|
67
code/server/cooperation/http/issueType.ts
Normal file
67
code/server/cooperation/http/issueType.ts
Normal 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;
|
||||
}
|
||||
|
||||
}
|
@ -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
|
||||
}
|
||||
|
||||
|
19
code/server/cooperation/mapper/issueType.ts
Normal file
19
code/server/cooperation/mapper/issueType.ts
Normal 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
|
@ -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))
|
||||
|
12
code/server/cooperation/service/issueType.ts
Normal file
12
code/server/cooperation/service/issueType.ts
Normal 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;
|
||||
}
|
||||
}
|
@ -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,
|
||||
|
@ -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 {
|
||||
|
@ -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()
|
25
code/server/file/rpc/file.ts
Normal file
25
code/server/file/rpc/file.ts
Normal 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;
|
@ -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 ""
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
10
code/server/gateway/rpc/file.ts
Normal file
10
code/server/gateway/rpc/file.ts
Normal 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
|
@ -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")
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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()
|
@ -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()
|
||||
|
10
code/server/user/rpc/file.ts
Normal file
10
code/server/user/rpc/file.ts
Normal 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
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user