nju-softeng / dingtalk-app-server Goto Github PK
View Code? Open in Web Editor NEW🥝 基于钉钉的实验室绩效管理系统 (Spring Boot)
🥝 基于钉钉的实验室绩效管理系统 (Spring Boot)
如下,一个Application
包含多个AcItem
。前端如何一次性将这一对多的关系提交?
public class Application {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private int month;
private int week;
private int DC;
private boolean isCheck; // 是否已审核
@Column(columnDefinition = "TIMESTAMP DEFAULT CURRENT_TIMESTAMP", updatable = false, insertable = false)
private LocalDateTime insertTime; //插入时间
@ManyToOne
private User applicant; // 申请人
@ManyToOne
private User auditor; // 审核人
@OneToMany(mappedBy = "application")
private List<AcItem> acItems; //本次绩效申请包含的 AC申请
}
public class AcItem {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private int AC;
private String reason;
@ManyToOne
private Application application; //ac申请属于的周绩效申请
}
websocket
是否正常如何启动该项目
问题:ac_items表是多余的,信息和ac_record表重复
方案:删除ac_items表,在ac_record表中加入类似dc_record表的status字段
另外:status应该增加状态,比如增加审核不通过状态
select ac_record_id FROM paper_detail WHERE paper_id = 6
select * FROM ac_record ac RIGHT JOIN (select ac_record_id FROM paper_detail WHERE paper_id = 6) t on ac.id = t.ac_record_id
update ac_record a, (select ac_record_id FROM paper_detail WHERE paper_id = 6) t set a.create_time = '2021-01-15' WHERE a.id = t.ac_record_id
dingtalk-app-server/src/main/java/com/softeng/dingtalk/component/Timer.java
Lines 115 to 121 in ebdeb99
SELECT
ac_record_id,
vote_id,
result AS v_res
FROM
vote_detail
WHERE
ac_record_id IS NOT NULL
SELECT
v.id,
p.title,
p.result AS p_res
FROM
paper p
LEFT JOIN vote v ON p.vote_id = v.id
SELECT
title,
ac_record_id,
user_id,
case
when B.p_res = 4 and A.v_res = 1 or B.p_res = 3 and A.v_res = 0 then
1
else
0
END
as res
FROM
( SELECT ac_record_id, vote_id, user_id, result AS v_res FROM vote_detail WHERE ac_record_id IS NOT NULL ) A
INNER JOIN (
SELECT
v.id,
p.title,
p.result AS p_res
FROM
paper p
LEFT JOIN vote v ON p.vote_id = v.id
) B ON A.vote_id = B.id
UPDATE ac_record a,
(
SELECT
title,
ac_record_id,
CASE
WHEN B.p_res = 4
AND A.v_res = 1
OR B.p_res = 3
AND A.v_res = 0 THEN
1 ELSE 0
END AS res
FROM
( SELECT ac_record_id, vote_id, user_id, result AS v_res FROM vote_detail WHERE ac_record_id IS NOT NULL ) A
INNER JOIN (
SELECT
v.id,
p.title,
p.result AS p_res
FROM
paper p
LEFT JOIN vote v ON p.vote_id = v.id
) B ON A.vote_id = B.id
) tmp
SET a.reason = if(res = 1, CONCAT('投票预测正确:' , tmp.title ), CONCAT('投票预测错误:' , tmp.title ))
WHERE
a.id = tmp.ac_record_id
为了避免序列化Application
时出现循环引用,在application
类的acItems
属性上加上了@JsonIgnore
结果 ApplicationController
的addApplication
方法出现了空指针异常
。
发现是因为@JsonIgnore
导致反序列化时acItems
被忽略了,导致acItems
为空
#6 的第一个解决方案有问题,还是需要将application
和acItems
分开来传给后台,但是可以封装起来
select ac_record_id, vote_id FROM vote_detail WHERE ac_record_id is not null
SELECT id from vote WHERE external = 0
SELECT v.id, p.title from paper p LEFT JOIN vote v on p.vote_id = v.id
SELECT * FROM (select ac_record_id, vote_id FROM vote_detail WHERE ac_record_id is not null
) A INNER JOIN (SELECT v.id, p.title from paper p LEFT JOIN vote v on p.vote_id = v.id ) B on A.vote_id = B.id
UPDATE ac_record a, (SELECT * FROM (select ac_record_id, vote_id FROM vote_detail WHERE ac_record_id is not null
) A INNER JOIN (SELECT v.id, p.title from paper p LEFT JOIN vote v on p.vote_id = v.id ) B on A.vote_id = B.id) tmp set a.reason = CONCAT(tmp.title, a.reason) WHERE a.id = tmp.ac_record_id
SELECT v.id, p.title from external_paper p LEFT JOIN vote v on p.vote_id = v.id
SELECT * FROM (select ac_record_id, vote_id FROM vote_detail WHERE ac_record_id is not null
) A INNER JOIN (SELECT v.id, p.title from external_paper p LEFT JOIN vote v on p.vote_id = v.id ) B on A.vote_id = B.id
UPDATE ac_record a, (SELECT * FROM (select ac_record_id, vote_id FROM vote_detail WHERE ac_record_id is not null
) A INNER JOIN (SELECT v.id, p.title from external_paper p LEFT JOIN vote v on p.vote_id = v.id ) B on A.vote_id = B.id) tmp set a.reason = CONCAT(tmp.title, a.reason) WHERE a.id = tmp.ac_record_id
项目前期因为 钉钉小程序只支持 GET,POST,我调研也不够,导致controller接口设计不遵循规范,建议重构接口。
从源码中解耦发往钉钉的消息,用模板渲染#66 (comment)
注意到用户投一张票,调用一次poll函数,只会在vote_detail表中添加一条记录,不会产生ac_record,这段代码没有必要。
调用钉钉服务端API需要配置合法IP列表,因为开发环境没有公网IP, 需要进行内网穿透
对学生不利的情况将要出现(扣分……),提前提醒学生规避
maven项目通过在pom添加依赖导入本地jar包。项目部署打成 jar包后,运行时会出现java.lang.NoClassDefFoundError
, 并且解压jar包发现BOOT-INF/lib下没有之前引入jar包
<!--添加外部依赖-->
<dependency>
<groupId>com.dingtalk.open</groupId>
<artifactId>taobao-sdk-java-auto</artifactId>
<version>2019.12.05</version>
<scope>system</scope>
<systemPath>${basedir}/src/main/resources/lib/taobao-sdk-java-auto.jar</systemPath>
</dependency>
解决方案
我们需要在pom中给springboot的打包插件设置includeSystemScope参数
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<includeSystemScope>true</includeSystemScope>
</configuration>
</plugin>
</plugins>
</build>
重点在于
<configuration>
<includeSystemScope>true</includeSystemScope>
</configuration>
经测试后,验证被触发的事件也可以回滚,棒~
需要对Application 表的 month, week, applican_id, auditorid 列建立唯一约束,但是担心会影响性能
问题:外部论文和内部论文两张表没多大差别,代码冗余。
方案:合成一张表,加个is_external字段,前端增加相应的是否是外部论文的选项,如果不是,扩展必填字段,如果是,直接提交。
将service层中的根据实验室规则算分的逻辑抽取整合成一层,前端做一个单独的管理后台页面,用来动态配置这一层参数(所有硬编码参数改掉,动态配置)。
避免每次调用钉钉服务端API是都要重新获取access_token
,access_token
有效期为7200秒
不然每次调用 dingtalk API 都要异常处理
接口重构成RESTFul风格
文档:https://www.ruanyifeng.com/blog/2014/05/restful_api.html
问题:计算某周dc时没有排除未审核的dc,即没有加上where status <> 0
。没出问题是因为未审核的dc记录c值为0
请问mysql 数据库文件在哪可以下载?
尊敬的开发者:
您好!非常感谢您能抽出宝贵的时间来阅读此Issue,我们是来自西北工业大学软件学院硕士课题组的科研团队,正在进行一项关于Java开源项目中方法(函数)名称一致性检查和建议的科研研究,方法(函数)名称的可读性对开发人员理解代码至关重要,我们在本开源项目中随机选择了一些文件作为我们研发工具DMName的实验验证对象,共发现了以下存在的15个方法(函数)命名问题,原始的建议修改的方法名称是第3列original_name,建议的方法名称为第4列suggest_name::
path | line | original_name | suggest_name |
---|---|---|---|
dingtalk-app-server/src/test/java/com/softeng/dingtalk/service/ApplicationServiceTests.java | 93 | testSetByAuditor | testSetApplicationByAuditor |
dingtalk-app-server/src/test/java/com/softeng/dingtalk/service/PaperServiceTest.java | 59 | testUpdateExternalPaperShouldOk | testUpdateExternalPaper |
dingtalk-app-server/src/test/java/com/softeng/dingtalk/service/PerformanceServiceTest.java | 38 | test1 | testListDcSummaryData |
dingtalk-app-server/src/test/java/com/softeng/dingtalk/DingtalkApplicationTests.java | 34 | test | testEncryptor |
dingtalk-app-server/src/test/java/com/softeng/dingtalk/DingtalkApplicationTests.java | 39 | test2 | testAddInternalPaper |
dingtalk-app-server/src/main/java/com/softeng/dingtalk/api/BaseApi.java | 53 | setCORPID | setCorpId |
dingtalk-app-server/src/main/java/com/softeng/dingtalk/api/BaseApi.java | 73 | setAGENTID | setAgentId |
dingtalk-app-server/src/main/java/com/softeng/dingtalk/api/BaseApi.java | 78 | setDOMAIN | setDomain |
dingtalk-app-server/src/main/java/com/softeng/dingtalk/api/BaseApi.java | 194 | sign | getSignature |
dingtalk-app-server/src/main/java/com/softeng/dingtalk/api/BaseApi.java | 214 | authentication | authSignature |
dingtalk-app-server/src/main/java/com/softeng/dingtalk/config/FabricConfig.java | 36 | FabricConfig | configFabric |
dingtalk-app-server/src/main/java/com/softeng/dingtalk/entity/AbsentOA.java | 45 | AbsentOA | setAbsentOA |
dingtalk-app-server/src/main/java/com/softeng/dingtalk/entity/AcItem.java | 45 | AcItem | setAcItem |
dingtalk-app-server/src/main/java/com/softeng/dingtalk/entity/Bug.java | 55 | Bug | setBugId |
dingtalk-app-server/src/main/java/com/softeng/dingtalk/entity/BugDetail.java | 37 | BugDetail | setBugDetail |
如果您认可或反对上述所涉及的问题和命名建议,可以发邮件([email protected])联系我们或直接在本Issue下回复,我们由衷地希望能够得到您宝贵的意见反馈,期待您的回复!
SELECT
u.NAME AS NAME,
a.ac,
a.reason,
create_time
FROM
( SELECT * FROM `user` WHERE is_deleted = 0 ) u
INNER JOIN ( SELECT * FROM ac_record WHERE create_time > "2020-12-31" and create_time < "2021-02-01") a ON a.user_id = u.id
ORDER BY
user_id DESC
EXTRACT() 函数用于返回日期/时间的单独部分,比如年、月、日、小时、分钟等等。
EXTRACT(unit FROM date)
link
DcRecord的表字段:id、dvalue、cvalue、dc、ac、status、insert_time、yearmonth、week、weekdate、version、datecode、applicant_id、auditor_id、(ac_items)
重构为:id、dvalue、cvalue、status、insert_time、year_month_week、version、applicant_id、auditor_id
说明:
select dvalue * cvalue as dc ……
算出来nju-softeng/dingtalk-app-web#29
进入投票页面后,第一次投票,页面没有变化;第二次投票出现异常,但前端异常信息为null, (这里其实是后端 Duplicate entry 'v_id-u_id' for key
, 重复投票的异常)
投票后确实发送到后端了,但是前端没有正确切换到投票状态页面,后端异常信息也没提示 ”用户已投票“
POST http://47.104.103.33:8089/api/vote/52 500 ()
{timestamp: "2021-12-03", status: 500, error: "Internal Server Error", message: "", path: "/api/vote/52"}
Duplicate entry '52-27' for key 'vote_detail.UK61vpx1woxr2v6exm8a2hxwtgb'
Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [vote_detail.UK61vpx1woxr2v6exm8a2hxwtgb]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement] with root cause
java.sql.SQLIntegrityConstraintViolationException: Duplicate entry '52-27' for key 'vote_detail.UK61vpx1woxr2v6exm8a2hxwtgb'
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:117)
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:97)
at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122)
at com.mysql.cj.jdbc.ClientPreparedStatement.executeInternal(ClientPreparedStatement.java:953)
at com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdateInternal(ClientPreparedStatement.java:1092)
........
个人想法:
实现分页查询用户自己的申请记录,而不是一次全部查询出来
分别将springboot和mysql部署到docker容器上,却发现springboot连接不上数据库???
使用存储过程link
实践:
1.创建测试数据库
create database test charset=utf8;
use test;
2.创建数据表
CREATE TABLE `dc_record` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`dc` double DEFAULT NULL,
`insert_time` datetime NOT NULL,
`week` int(11) DEFAULT NULL,
`application_id` int(11) DEFAULT NULL,
`user_id` int(11) DEFAULT NULL,
`auditor_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=166104 DEFAULT CHARSET=utf8;
3.创建存储过程
CREATE DEFINER=`root`@`localhost` PROCEDURE `insertdata`(IN n int)
BEGIN
DECLARE i INT DEFAULT 1;
DECLARE j INT;
WHILE (i <= n ) DO
WHILE (j <= 100) DO
INSERT into dc_record (application_id, auditor_id, user_id,insert_time, week, dc) VALUES (i, i, j ,now(), 1, FLOOR(RAND() * 100) );
SET j=j+1;
END WHILE;
SET i=i+1;
SET j = 1;
END WHILE;
END
使用sftp
: 参考
sftp username@remote_hostname_or_IP
sftp> put -r d:/xxx
(-r 表示文件夹) 即将d:/xxx 文件夹传到linux服务器上
select ifnull((select id from tableName where conditions limit 1 ), 0)
可能出现并发问题
select * FROM paper_detail WHERE paper_id = 4
select * FROM ac_record ac RIGHT JOIN (select ac_record_id FROM paper_detail WHERE paper_id = 4) t on ac.id = t.ac_record_id
update ac_record a, (select ac_record_id FROM paper_detail WHERE paper_id = 4) t set a.reason = CONCAT('(AC待分配)', a.reason), a.ac = 0 WHERE a.id = t.ac_record_id
createVote方法需要同步
Hibernate分页存在一对多关系时,可能引起的性能问题。解决方法
虽然很多博客不建议使用触发器和存储过程,不过我觉得我的业务并发量不大,使用触发器可以极大简化后端的业务逻辑。值的去尝试~
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.