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

1238 lines
44 KiB

package com.gyf.csams
import com.gyf.csams.FileService.getFormParam
import com.gyf.csams.module.*
import io.ktor.application.*
import io.ktor.http.content.*
import io.ktor.util.*
import org.jetbrains.exposed.dao.id.EntityID
import org.jetbrains.exposed.dao.id.IntIdTable
import org.jetbrains.exposed.sql.*
import org.jetbrains.exposed.sql.transactions.transaction
import org.slf4j.Logger
import java.io.File
import java.time.LocalDateTime
import kotlin.properties.Delegates
import kotlin.system.exitProcess
interface BaseService {
fun init(environment: ApplicationEnvironment)
}
abstract class AbstractService : BaseService {
protected lateinit var log: Logger
protected lateinit var environment: ApplicationEnvironment
override fun init(environment: ApplicationEnvironment) {
this.environment = environment
this.log = environment.log
}
}
/**
* 账号服务
*/
object AccountService : AbstractService() {
/**
* 检查学号是否已注册,true=已注册
*/
fun registered(selectId: String): Boolean {
return transaction {
return@transaction !User.find { Users.studentId eq selectId }.empty()
}
}
/**
* 注册
*/
fun register(userVo: UserRegVo): UserResDto? {
try {
return transaction {
val originPassword = if (environment.developmentMode) "12345678" else randomNum(8)
User.new {
studentId = userVo.studentId
name = userVo.name
password = originPassword.md5()
}
return@transaction UserResDto(password = originPassword)
}
} catch (e: Exception) {
log.error("注册失败,发生异常:$e")
return null
}
}
fun login(vo:BaseLoginVo,ip:String):OwnInfoVo{
return when (vo) {
is UserLoginVo -> login(vo,ip)
is ManagerLoginVo -> login(vo,ip)
else -> throw IllegalArgumentException("vo:${vo::class.java}类型不合法")
}
}
/**
* 前台登录
*
*/
private fun login(userLoginVo: UserLoginVo, _ip: String): UserVo {
return transaction {
val matchUser = User.find { Users.studentId eq userLoginVo.studentId }.firstOrNull()
when {
matchUser == null -> {
log.warn("学号:${userLoginVo.studentId}不存在")
throw StudentIdError(userLoginVo.studentId)
}
userLoginVo.password.md5() != matchUser.password -> {
log.warn("密码:${userLoginVo.password}错误")
throw PasswordError(id = userLoginVo.studentId, password = userLoginVo.password)
}
else -> {
val token = UserToken.new {
user = matchUser
ip = _ip
device = userLoginVo.device
token =
listOf(matchUser.id, ip, device).joinToString(separator = ('a'..'z').random().toString())
.md5()
}
token.flush()
val associationMember =
AssociationMember.find { AssociationMembers.userId eq matchUser.id }.firstOrNull()
return@transaction UserVo(
studentId = matchUser.studentId, token =
Token(
id = matchUser.id.value, token = token.token,
createTime = token.createTime.toLong()
), name = matchUser.name,
headImg = matchUser.headImg?.filepath,
desc = matchUser.desc,
associationVo = associationMember?.let { AssociationService.toAssociationVo(it.association) },
isHead = associationMember?.isHead
)
}
}
}
}
/**
* 后台登陆
*
* @return
*/
private fun login(managerLoginVo: ManagerLoginVo, _ip: String): ManagerVo {
return transaction {
val matchManager = Manager.find { Managers.account eq managerLoginVo.account }.firstOrNull()
when {
matchManager == null -> {
log.warn("账号:${managerLoginVo.account}不存在")
throw AccountError(managerLoginVo.account)
}
managerLoginVo.password.md5() != matchManager.password -> {
log.warn("密码:${managerLoginVo.password}错误")
throw PasswordError(id = managerLoginVo.account, password = managerLoginVo.password)
}
else -> {
val token = ManagerToken.new {
manager = matchManager
ip = _ip
device = managerLoginVo.device
token =
listOf(matchManager.id, ip, device).joinToString(separator = ('a'..'z').random().toString())
.md5()
}
token.flush()
return@transaction tokenRes(token, matchManager)
}
}
}
}
fun refreshInfo(_token: OnlyToken): UserVo {
return transaction {
val matchUser = User.findById(_token.token.id) ?: throw UserIdError(_token.token.id)
val token = UserToken.find { UserTokens.userId eq matchUser.id }.firstOrNull()
?: throw IllegalArgumentException("无法根据[userId=${matchUser.id}]找到token")
val associationMember =
AssociationMember.find { AssociationMembers.userId eq matchUser.id }.firstOrNull()
UserVo(
studentId = matchUser.studentId, token =
Token(
id = matchUser.id.value, token = token.token,
createTime = token.createTime.toLong()
), name = matchUser.name,
headImg = matchUser.headImg?.filepath,
desc = matchUser.desc,
associationVo = associationMember?.let { AssociationService.toAssociationVo(it.association) },
isHead = associationMember?.isHead
)
}
}
private fun tokenRes(token: ManagerToken, matchManager: Manager): ManagerVo {
return ManagerVo(
account = matchManager.account,
token = Token(
id = matchManager.id.value, token = token.token,
createTime = token.createTime.toLong()
),
desc = matchManager.desc,
duty = Duty.valueOf(matchManager.duty),
headImg = matchManager.headImg?.filepath, name = matchManager.name
)
}
private fun tokenRes(token: UserToken, matchUser: User): UserVo {
val associationMember = AssociationMember.find { AssociationMembers.userId eq matchUser.id }.firstOrNull()
return UserVo(
studentId = matchUser.studentId, token =
Token(
id = matchUser.id.value, token = token.token,
createTime = token.createTime.toLong()
), name = matchUser.name,
headImg = matchUser.headImg?.filepath, desc = matchUser.desc,
associationVo = associationMember?.let { AssociationService.toAssociationVo(it.association) },
isHead = associationMember?.isHead
)
}
fun getManagerVo(token: Token): ManagerVo {
return transaction {
val c = ManagerToken.find {
ManagerTokens.managerId eq token.id
ManagerTokens.token eq token.token
}
if (!c.empty()) {
val manager = Manager.findById(token.id)
return@transaction tokenRes(token = c.first(), matchManager = manager!!)
} else {
throw IllegalArgumentException("token校验失败")
}
}
}
fun getUserVo(token: Token): UserVo {
return transaction {
val c = UserToken.find {
UserTokens.userId eq token.id
UserTokens.token eq token.token
}
if (!c.empty()) {
val user = User.findById(token.id)
return@transaction tokenRes(token = c.first(), matchUser = user!!)
} else {
throw IllegalArgumentException("token校验失败")
}
}
}
private fun validManagerToken(token: Token): Boolean {
return transaction {
!ManagerToken.find {
ManagerTokens.managerId eq token.id
ManagerTokens.token eq token.token
}.empty()
}
}
fun validUserToken(token: Token): Boolean {
return transaction {
!UserToken.find {
UserTokens.userId eq token.id
UserTokens.token eq token.token
}.empty()
}
}
fun <T : ClientBaseVo> validToken(vo: T): Boolean {
return if (vo.clientType == ClientType.Foreground) {
validUserToken(vo.token)
} else {
validManagerToken(vo.token)
}
}
fun logout(vo: OnlyToken): Boolean {
return transaction {
if (vo.clientType == ClientType.Foreground)
UserTokens.deleteWhere { UserTokens.userId eq vo.token.id } > 0
else
ManagerTokens.deleteWhere { ManagerTokens.managerId eq vo.token.id } > 0
}
}
fun test() {
log.info("开始测试")
transaction {
log.info("查询到个${User.count()}用户")
}
log.info("结束测试")
}
}
/**
* 主页服务
*/
object MainService : AbstractService() {
private var maxSize by Delegates.notNull<Int>()
override fun init(environment: ApplicationEnvironment) {
super.init(environment)
this.maxSize = environment.config.property("ktor.deployment.leaveMessage.maxSize").getString().toInt()
}
/**
* 创建留言信息
*
* @param leaveMessageVo
* @return
*/
fun createMessage(leaveMessageVo: LeaveMessageVo): Boolean {
return if (leaveMessageVo.message.isNotEmpty()) {
return transaction {
val count = LeaveMessage.count().toInt()
log.info("系统留言数:$count,限制数:$maxSize")
if (count >= maxSize) {
LeaveMessage.all().sortedBy { it.createTime }.subList(0, count - maxSize).forEach {
it.delete()
}
}
log.info("保存留言:${leaveMessageVo.message}")
LeaveMessage.new {
user = User.findById(leaveMessageVo.token.id) ?: throw IllegalArgumentException("非法id")
message = leaveMessageVo.message
}
log.info("留言保存成功")
return@transaction true
}
} else {
log.info("留言不能为空")
false
}
}
fun getAllLeaveMessage(): List<LeaveMessageDto> {
return transaction {
log.info("获取所有留言")
return@transaction LeaveMessage.all().toList().map {
LeaveMessageDto(
message = "${it.user.name}说:${it.message}",
user = UserInfoVo(name = it.user.name, headImg = it.user.headImg?.filepath, desc = it.user.desc)
)
}
}
}
}
/**
* 文件管理服务
*/
object FileService : AbstractService() {
private lateinit var uploadDir: String
private lateinit var filePath: String
override fun init(environment: ApplicationEnvironment) {
super.init(environment)
this.uploadDir = environment.config.property("ktor.deployment.filePath").getString()
filePath = this::class.java.classLoader.getResource(uploadDir)?.path ?: throw IllegalArgumentException("初始化资源目录失败")
File(filePath).let {
when {
it.exists() -> log.info("上传路径[${filePath}]已存在")
!it.mkdirs() -> throw IllegalArgumentException("上传路径[${filePath}]创建失败")
}
}
}
private fun save(id: String, path: String, file: File): Int {
return transaction {
return@transaction ImageFile.new {
userId = id
filepath = path
md5 = file.readBytes().md5()
}
}.id.value
}
private inline fun <reified T : PartData> getPartData(map: Map<String?, PartData>, key: String): T {
if (map.containsKey(key)) {
val obj = map[key]
if (obj is T) {
return obj
} else {
throw IllegalArgumentException("类型错误")
}
}
throw IllegalArgumentException("找不到key:${key}")
}
fun List<PartData>.getFormParam(key:String):String{
forEach {
if(it.name==key && it is PartData.FormItem){
return it.value
}
}
throw IllegalArgumentException("没有找到[key=${key}]的表单参数")
}
fun storeFile(data: List<PartData>): List<Int>? {
val userId = data.getFormParam(key="id")
val token = data.getFormParam(key="token")
val createTime = data.getFormParam(key="createTime")
val tokenVo = Token(token = token, id = userId.toInt(), createTime = createTime.toLong())
if (AccountService.validUserToken(tokenVo)) {
val fileIds = mutableListOf<Int>()
data.forEach {
if (it is PartData.FileItem) {
val fileBytes = it.streamProvider().readBytes()
val fileName = it.originalFileName ?: throw IllegalArgumentException("参数异常")
val format = fileBytes.getFormat()
val fullFileName = "${fileName}.${format.format}"
log.info("fullFileName=$fullFileName")
val file = File(filePath, fullFileName).apply {
writeBytes(fileBytes)
}
log.info("文件成功保存到${file.absolutePath}")
val fileId = save(id = userId, "/${uploadDir}/${fullFileName}", file = file)
fileIds.add(fileId)
}
}
return fileIds
} else {
return null
}
}
}
/**
* 审核资料
*
* @param T 注册实体类型
* @param E 后台注册实体类型
* @param F 前台审核进度类型
*/
abstract class AuditService<T, E, F> : AbstractService() {
abstract val dataType: String
/**
* 注册资料
*
* @param vo
*/
abstract fun register(vo: T)
// protected abstract fun load
/**
* 通知用户审核进度
*
* @param receiverId
* @param content
*/
protected fun foreground(receiverId: Int, content: String) {
Notification.new {
this.title = dataType
this.content = content
this.receiverId = receiverId
receiverClient = ClientType.Foreground.name
}.apply {
log.info("通知前台用户${dataType}处理进度")
}
}
/**
* 前台任务通知管理员处理
*
*/
protected fun background(content: String, duty: Duty) {
Manager.find { Managers.duty eq duty.name }.apply {
if (count() == 0L) {
log.warn("找不到适当的${duty.desc}处理此任务")
} else {
forEach {
Notification.new {
this.title = dataType
this.content = content
receiverId = it.id.value
receiverClient = ClientType.Background.name
}.apply {
log.info("通知${duty.desc}处理${dataType}")
}
}
}
}
}
/**
* 查找审核资料
*
* @param auditId
* @return
*/
abstract fun findEntity(auditId: Int): AbstractAudit
/**
* 更新审核结果
*
* @param vo
*/
private fun AuditLogging.update(vo: CheckVo) {
apply {
if (nextAudit != null) {
nextAudit?.apply {
cause = vo.cause
result = vo.result
auditTime = LocalDateTime.now()
}
} else {
cause = vo.cause
result = vo.result
auditTime = LocalDateTime.now()
}
}.apply {
log.info("更新审核结果")
}
}
/**
* 通过审核后
*
*/
protected abstract fun afterAudit(entity: AbstractAudit)
/**
* 资料受理
*
* @param vo
*/
fun accept(vo: AcceptVo) {
transaction {
val association = findEntity(vo.auditId)
when (val manager = Manager.findById(vo.token.id)) {
null -> throw ManagerIdError(vo.token.id)
else -> {
association.apply {
val nextAudit = audit.nextAudit
if (nextAudit == null) {
audit.manager = manager
audit.acceptTime = LocalDateTime.now()
} else {
nextAudit.manager = manager
nextAudit.acceptTime = LocalDateTime.now()
}
}
log.info("[${association.notificationName()}]${this@AuditService.dataType}已受理")
Notification.new {
title = this@AuditService.dataType
content = "您提交的[${association.notificationName()}]${this@AuditService.dataType}已受理"
receiverId = vo.token.id
receiverClient = ClientType.Foreground.name
}
}
}
}
}
/**
* 资料审核
*
* @param vo
*/
fun check(vo: CheckVo) {
transaction {
try {
val entity = findEntity(vo.auditId)
val matchUser = entity.audit.user
entity.audit.update(vo)
when {
entity.audit.nextAudit == null && vo.result -> {
entity.audit.nextAudit = AuditLogging.new {
this.user = matchUser
}.apply {
log.info("构造${this@AuditService.dataType}复审记录")
}
background(
content = "总部长上报了一份${this@AuditService.dataType}需要您进行受理",
duty = Duty.Teacher
)
foreground(
receiverId = matchUser.id.value,
content = "您提交的【${entity.notificationName()}${this@AuditService.dataType}初审通过,请耐心等待复审"
)
}
entity.audit.nextAudit == null && !vo.result -> {
foreground(
receiverId = matchUser.id.value,
content = "您提交的【${entity.notificationName()}${this@AuditService.dataType}初审不通过,可根据初审意见,重新申请\n" +
"【初审意见:${vo.cause},审核人:${entity.audit.manager?.duty ?: ""}"
)
}
entity.audit.nextAudit != null && vo.result -> {
afterAudit(entity)
foreground(
receiverId = matchUser.id.value,
content = "您提交的【${entity.notificationName()}${this@AuditService.dataType}复审通过"
)
}
else -> {
foreground(
receiverId = matchUser.id.value,
content = "您提交的【${entity.notificationName()}${this@AuditService.dataType}复审不通过,可根据复审意见,重新申请\n" +
"【复审意见:${vo.cause},审核人:${entity.audit.nextAudit?.manager?.duty ?: ""}"
)
}
}
log.info("${entity.notificationName()}${this@AuditService.dataType}审核完成")
} catch (e: Exception) {
rollback()
throw e
}
}
}
/**
* 审核进度查询
*
*/
open fun read(vo: OnlyToken, table: IntIdTable): F? {
return transaction {
table.innerJoin(AuditLeggings).innerJoin(Users)
.slice(listOf(table.id))
.select {Users.id eq vo.token.id}
.firstOrNull()
?.let { it ->
getCheckVo(id = it[table.id])
}
}
}
abstract fun getCheckVo(id: EntityID<Int>): F
protected fun toCheckVo(audit: AuditLogging): AuditCheckVo {
return AuditCheckVo(
checkStatus = when {
audit.nextAudit == null && audit.manager == null -> CheckStatus.WaitFirst
audit.nextAudit == null && audit.manager != null -> CheckStatus.AcceptFirst
audit.nextAudit != null && audit.nextAudit?.manager == null -> CheckStatus.WaitLast
audit.nextAudit != null && audit.nextAudit?.result == null -> CheckStatus.AcceptLast
else -> CheckStatus.Finish
},
applyTime = audit.applyTime.toLong(),
firstCause = audit.cause ?: "",
lastCause = audit.nextAudit?.cause,
result=audit.nextAudit?.result==true
)
}
/**
* 查看审核记录
*
* @param vo
* @return
*/
abstract fun audit(vo: OnlyToken): List<E>
protected fun toAuditLoggingVo(it: AuditLogging?): AuditLoggingVo? {
return it?.let { logging ->
val auditLogging = AuditLoggingVo(
id = logging.id.value,
user =
UserInfoVo(name = logging.user.name, headImg = logging.user.headImg?.filepath, desc = logging.user.desc),
applyTime = logging.applyTime.toLong(),
manager = logging.manager?.let {
ManagerInfoVo(
duty = Duty.valueOf(it.duty),
name = it.name,
headImg = it.headImg?.filepath,
desc = it.desc
)
},
acceptTime = logging.acceptTime?.toLong(),
cause = logging.cause,
result = logging.result,
auditTime = logging.auditTime?.toLong(),
nextAudit = toAuditLoggingVo(logging.nextAudit)
)
auditLogging
}
}
}
/**
* 社团服务
*/
object AssociationService : AuditService<AssociationRegVo, AuditAssociationVo, AssociationCheckVo>() {
override val dataType: String = "社团注册资料"
override fun findEntity(auditId: Int): AbstractAudit {
return Association.find { Associations.auditId eq auditId }.firstOrNull() ?: throw AuditIdError(auditId)
}
override fun afterAudit(entity: AbstractAudit) {
AssociationMember.new {
user = entity.audit.user
this.association = Association.find { Associations.auditId eq entity.audit.id }.firstOrNull()
?: throw IllegalArgumentException("无法根据[audit=${entity.audit.id}]找到社团信息")
isHead = true
}.apply {
this@AssociationService.log.info("初始化社团团长")
}
}
/**
* 注册社团
*
* @param vo
* @return
*/
override fun register(vo: AssociationRegVo) {
return transaction {
//再次申请
val user = User.findById(vo.token.id) ?: throw UserIdError(vo.token.id)
if (vo.associationId != null) {
log.info("再次提交【${vo.name}】注册资料")
val association = Association.findById(vo.associationId!!) ?: throw AuditIdError(vo.associationId!!)
association.apply {
name = vo.name
desc = vo.desc
logo = ImageFile.findById(vo.fileId) ?: throw FileIdError(vo.fileId)
this.audit = AuditLogging.new {
this.user = user
}
}
} else {
val associationMember = AssociationMember.find { AssociationMembers.userId eq user.id }.firstOrNull()
val association: Association? = associationMember?.association
when {
association != null && association.audit.result == true -> throw IllegalArgumentException("您是社团团长不能再创建其他社团")
association != null && association.audit.result == null -> throw IllegalArgumentException("您已经提交过${dataType},请耐心等待后台管理员处理")
association == null -> {
Association.new {
name = vo.name
desc = vo.desc
logo = ImageFile.findById(vo.fileId) ?: throw FileIdError(vo.fileId)
this.audit = AuditLogging.new {
this.user = user
}
faculty = faculty(user.studentId).name
}
}
}
}
foreground(receiverId = vo.token.id, content = "您成功提交了一份${dataType},请耐心等待后台受理")
background(content = "用户${user.name}提交了一份${dataType}需要您进行受理", duty = Duty.PamphaBhusal)
log.info("未审核社团:${vo.name}创建成功")
}
}
/**
* 社团列表加载
*
* @param vo
* @return
*/
fun load(vo: SearchAssociationVo): List<AssociationVo> {
return transaction {
log.info("社团搜索条件[name=${vo.name},desc=${vo.desc}]")
val nextAudit = AuditLeggings.alias("nextAudit")
return@transaction Associations.innerJoin(otherTable = AuditLeggings)
.innerJoin(nextAudit, { AuditLeggings.nextAudit }, { nextAudit[AuditLeggings.id] })
.slice(listOf(Associations.id))
.select {
nextAudit[AuditLeggings.result] eq true and (Associations.name like "%${vo.name}%") and (Associations.desc like "%${vo.desc}%")
}.map {
val association=Association.findById(it[Associations.id])?:throw AssociationIdError(it[Associations.id].value)
toAssociationVo(association)
}
}
}
/**
* 前台读取社团注册资料
*
*/
override fun getCheckVo(id: EntityID<Int>): AssociationCheckVo {
return (Association.findById(id) ?: throw AssociationIdError(id.value)).let {
AssociationCheckVo(
associationVo = toAssociationVo(it),
auditCheckVo = toCheckVo(it.audit), fileId = it.logo.id.value
)
}
}
/**
* 后台读取社团注册资料
*
* @param vo
* @return
*/
override fun audit(vo: OnlyToken): List<AuditAssociationVo> {
return transaction {
return@transaction Association.all().sortedBy {
//按初审受理>等待复审>复审受理>完成审核 排序
when {
it.audit.nextAudit == null && it.audit.manager == null -> 1
it.audit.nextAudit == null && it.audit.manager != null -> 2
it.audit.nextAudit != null && it.audit.nextAudit?.manager == null -> 3
it.audit.nextAudit != null && it.audit.nextAudit?.result == null -> 4
else -> 5
}
}.map {
val audit = toAuditLoggingVo(it.audit) ?: throw IllegalArgumentException("转换审核记录出错!!!!")
AuditAssociationVo(name = it.name, desc = it.desc, logo = it.logo.filepath, audit = audit)
}.apply {
log.info("找到${this.size}${dataType}")
}
}
}
fun toAssociationVo(it: Association): AssociationVo {
return AssociationVo(associationId = it.id.value, name = it.name, desc = it.desc,
logo = it.logo.filepath, faculty = AssociationFaculty.valueOf(it.faculty),
level = it.level?.let { AssociationLevel.valueOf(it) })
}
/**
*
* 查询社团详情
* @param vo
* @return
*/
fun load(vo: ShowAssociationVo): AssociationMainVo {
return transaction {
val associationVo = (Association.findById(vo.id) ?: throw AssociationIdError(vo.id)).let { it ->
AssociationVo(associationId = it.id.value, name = it.name, desc = it.desc,
logo = it.logo.filepath, faculty = AssociationFaculty.valueOf(it.faculty),
level = it.level?.let { AssociationLevel.valueOf(it) })
}
val head = Users.innerJoin(AssociationMembers)
.slice(Users.columns)
.select { AssociationMembers.isHead eq true and (AssociationMembers.associationId eq vo.id) }
.firstOrNull()?.let { it ->
UserInfoVo(
name = it[Users.name],
headImg = it[Users.imgId]?.let {
ImageFile.findById(it) ?: throw FileIdError(it.value)
}?.filepath,
desc = it[Users.desc]
)
} ?: throw IllegalArgumentException("无法找到社团[${vo.id}]")
AssociationMainVo(associationVo = associationVo, head = head)
}
}
/**
* 加载社团成员
*
* @param vo
* @return
*/
fun load(vo: QueryAssociationMembers): List<UserInfoVo> {
return transaction {
Users.innerJoin(AssociationMembers).innerJoin(Associations)
.slice(Users.columns)
.select {
vo.name.let {
if (it == null || it.isEmpty())
Associations.id eq vo.id
else
Associations.id eq vo.id and (Users.name like "%${vo.name}%")
}
}.map { it ->
UserInfoVo(
name = it[Users.name], headImg = it[Users.imgId]?.let { ImageFile.findById(it) }?.filepath,
desc = it[Users.desc]
)
}
}
}
}
object ActivityService : AuditService<ActivityApplyVo, AuditActVo,ActivityCheckVo>() {
override val dataType: String = "活动申请书"
override fun findEntity(auditId: Int): AbstractAudit {
return Activity.find { Activities.auditId eq auditId }.firstOrNull() ?: throw AuditIdError(auditId)
}
override fun afterAudit(entity: AbstractAudit) {
}
/**
* 上传照片
*
* @param data
*/
fun upload(data: List<PartData>){
val activityId=data.getFormParam("activityId")
val name=data.getFormParam("name")
transaction {
(Activity.findById(activityId.toInt())?:throw IllegalArgumentException("活动id参数有误:${activityId}")).apply {
val fileId=FileService.storeFile(data)
//保存到相册
fileId?.forEach {
PhotoAlbum.new {
activity=this@apply
photo=ImageFile.findById(it)?:throw FileIdError(it)
this.name=name
}.let {
log.info("保存照片:${it.name}")
}
}
}
}
}
/**
* 发送评论
*
* @param vo
*/
fun sendComment(vo:SendBBSVo){
transaction {
ActivityComment.new {
content=vo.content
user=User.findById(vo.token.id)?:throw UserIdError(vo.token.id)
activity=Activity.findById(vo.activityId)?:throw ActivityIdError(vo.activityId)
}
}
}
/**
* 加载评论
*
* @param vo
* @return
*/
fun loadComment(vo: SearchCommentVo):List<BBSVo>{
return transaction {
ActivityComment.find { ActivityComments.activityId eq vo.activityId }.map {
BBSVo(user = UserInfoVo(name=it.user.name,headImg = it.user.headImg?.filepath,desc = it.user.desc),
createTime = it.createTime.toLong(),content = it.content)
}
}
}
/**
* 加载活动照片
*
* @param vo
* @return
*/
fun load(vo:SearchActivityPhotoVo):List<ActivityPhotoVo>{
return transaction {
PhotoAlbum.find { PhotoAlbums.activityId eq vo.activityId }.map {
ActivityPhotoVo(name = it.name,url=it.photo.filepath)
}
}
}
/**
* 活动列表
*
*/
fun load(vo:SearchActivityVo):List<ActivityVo>{
return transaction {
val nextAudit = AuditLeggings.alias("nextAudit")
return@transaction Activities.innerJoin(otherTable = AuditLeggings)
.innerJoin(nextAudit, { AuditLeggings.nextAudit }, { nextAudit[AuditLeggings.id] })
.slice(listOf(Activities.id))
.select {
nextAudit[AuditLeggings.result] eq true and (Activities.associationId eq vo.associationId)
}.map {
val activity=Activity.findById(it[Activities.id])?:throw ActivityIdError(it[Activities.id].value)
toActivityVo(activity = activity)
}
}
}
/**
* 活动详情
*
* @param vo
* @return
*/
fun show(vo:ShowActivityVo):ActivityDetailVo{
return transaction {
(Activity.findById(vo.activityId)?:throw ActivityIdError(vo.activityId)).let {
ActivityDetailVo(activityVo = toActivityVo(it),associationVo = AssociationService.toAssociationVo(it.association))
}
}
}
override fun read(vo: OnlyToken, table: IntIdTable): ActivityCheckVo? {
val nextAudit = AuditLeggings.alias("nextAudit")
return transaction {
table.innerJoin(AuditLeggings)
.innerJoin(nextAudit, { AuditLeggings.nextAudit }, { nextAudit[AuditLeggings.id] })
.innerJoin(Users)
.slice(listOf(table.id))
.select {Users.id eq vo.token.id and (nextAudit[AuditLeggings.result] neq true)}
.firstOrNull()
?.let { it ->
getCheckVo(id = it[table.id])
}
}
}
/**
* 申请活动
*
*/
override fun register(vo: ActivityApplyVo) {
transaction {
val user = User.findById(vo.token.id) ?: throw UserIdError(vo.token.id)
if (vo.activityVo.activityId != null) {
//再次提交
log.info("再次提交【${vo.activityVo.activityName}${dataType}")
val activity = Activity.findById(vo.activityVo.activityId!!) ?: throw ActivityIdError(vo.activityVo.activityId!!)
activity.apply {
activityName = vo.activityVo.activityName
activityTime = vo.activityVo.activityTime.toLocalDateTime()
activityAddress = vo.activityVo.activityAddress
activityDesc = vo.activityVo.activityDesc
activitySize = vo.activityVo.activitySize
this.audit = AuditLogging.new {
this.user = user
}
}
} else {
//首次提交
//申请活动的限制
val activityMember = AssociationMember.find { AssociationMembers.userId eq user.id }.firstOrNull()
when {
activityMember == null -> throw IllegalArgumentException("非社团成员无法申请活动")
!activityMember.isHead -> throw java.lang.IllegalArgumentException("不是社团团长无法申请活动")
else -> {
Activity.new {
activityName = vo.activityVo.activityName
activityTime = vo.activityVo.activityTime.toLocalDateTime()
activityAddress = vo.activityVo.activityAddress
activityDesc = vo.activityVo.activityDesc
activitySize = vo.activityVo.activitySize
association =
Association.findById(vo.associationId) ?: throw AssociationIdError(vo.associationId)
audit = AuditLogging.new {
this.user = user
}
}
}
}
}
foreground(receiverId = vo.token.id, content = "您成功提交了一份${dataType},请耐心等待后台受理")
background(content = "用户${user.name}提交了一份${dataType}需要您进行受理", duty = Duty.PamphaBhusal)
}
}
private fun toActivityVo(activity:Activity):ActivityVo{
return ActivityVo(
activityName = activity.activityName, activityTime = activity.activityTime.toLong(),
activityAddress = activity.activityAddress, activityDesc = activity.activityDesc,
activitySize = activity.activitySize,
activityId = activity.id.value
)
}
override fun audit(vo: OnlyToken): List<AuditActVo> {
return transaction {
//TODO sortedBy这一段需要封装
return@transaction Activity.all().sortedBy {
//按初审受理>等待复审>复审受理>完成审核 排序
when {
it.audit.nextAudit == null && it.audit.manager == null -> 1
it.audit.nextAudit == null && it.audit.manager != null -> 2
it.audit.nextAudit != null && it.audit.nextAudit?.manager == null -> 3
it.audit.nextAudit != null && it.audit.nextAudit?.result == null -> 4
else -> 5
}
}.map {
val audit = toAuditLoggingVo(it.audit) ?: throw IllegalArgumentException("转换审核记录出错!!!!")
AuditActVo(
activityVo = toActivityVo(activity = it), audit = audit, auditId = it.id.value
)
}.apply {
log.info("找到${this.size}${dataType}")
}
}
}
override fun getCheckVo(id: EntityID<Int>): ActivityCheckVo {
return (Activity.findById(id) ?: throw ActivityIdError(id.value)).let {
ActivityCheckVo(
activityVo = toActivityVo(activity = it),
auditCheckVo = toCheckVo(it.audit),
activityId = it.id.value
)
}
}
}
/**
* 通知服务
*/
object NotificationService : AbstractService() {
/**
* 拉取最新通知
*
* @param vo
* @return
*/
fun pull(vo: NotificationDto): List<NotificationVo> {
return transaction {
log.info("通知查询条件[receiverId=${vo.receiverId},receiverClient=${vo.receiverClient.name},pull=false]")
val notifications = Notification.find {
Notifications.pull eq false and
(Notifications.receiverId eq vo.receiverId) and
(Notifications.receiverClient eq vo.receiverClient.name)
}
log.info("获取${notifications.count()}条最新通知")
return@transaction notifications.map {
it.pull = true
NotificationVo(
title = it.title, id = it.id.value, content = it.content,
createTime = it.createTime.toLong()
)
}
}
}
/**
* 未读通知计数
*
* @param vo
* @return
*/
fun count(vo: NotificationDto): Long {
return transaction {
return@transaction Notification.find {
Notifications.read eq false and
(Notifications.receiverId eq vo.receiverId) and
(Notifications.receiverClient eq vo.receiverClient.name)
}.count().apply {
log.info("未读通知${this}")
}
}
}
/**
*
* @param vo
* @return
*/
fun list(vo: NotificationDto): List<NotificationVo> {
return transaction {
return@transaction Notification.find {
(Notifications.receiverId eq vo.receiverId) and
(Notifications.receiverClient eq vo.receiverClient.name)
}.sortedByDescending { it.createTime }.map {
NotificationVo(
title = it.title,
id = it.id.value,
content = it.content,
createTime = it.createTime.toLong()
)
}
}
}
}
/**
* 后台服务
*/
object BackgroundService : AbstractService() {
override fun init(environment: ApplicationEnvironment) {
super.init(environment)
initManager()
}
private fun createManager(duty: Duty, num: Int = 1): MutableList<InitManagerDto> {
val managerList = mutableListOf<InitManagerDto>()
repeat(num) {
val originPassword = randomNum()
Manager.new {
account = randomNum()
password = originPassword.md5()
this.duty = duty.name
this.name = duty.desc
}.apply {
managerList.add(InitManagerDto(account = account, originPassword = originPassword, duty = duty))
}
}
return managerList
}
//初始化管理员
private fun initManager() {
transaction {
val resourcePath =
this::class.java.classLoader.getResource("")?.path ?: throw IllegalArgumentException("初始化资源目录失败")
val file = File(resourcePath, "管理员账号.txt")
try {
if (!file.exists()) {
Manager.count().let { it ->
if (it.toInt() == 0) {
val allManager = mutableListOf<InitManagerDto>()
allManager.addAll(createManager(Duty.Teacher, 1))
allManager.addAll(createManager(Duty.PamphaBhusal, 1))
allManager.addAll(createManager(Duty.SecretaryOfTheMinister, 1))
allManager.addAll(createManager(Duty.PropagandaDepartment, 1))
allManager.addAll(createManager(Duty.LiaisonMinister, 1))
arrayOf(
Duty.SecretaryDepartmentOfficer,
Duty.PublicityDepartmentOfficer,
Duty.LiaisonOfficer
).forEach {
allManager.addAll(createManager(it, 3))
}
allManager.forEach {
file.appendText("${it.account}------${it.originPassword}------${it.duty.desc}\n")
}
log.info("共生成${allManager.size}个管理员账号")
} else {
log.info("不需要生成管理员")
}
}
}
} catch (e: Exception) {
log.error(e)
exitProcess(0)
}
}
}
}