Parcourir la Source

Merge remote-tracking branch 'origin/dev' into test

jiapeng 7 ans auparavant
Parent
commit
2e7562c648
32 fichiers modifiés avec 2933 ajouts et 76 suppressions
  1. 54 0
      src/main/java/com/ekexiu/portal/found/Service.java
  2. 159 0
      src/main/java/com/ekexiu/portal/leavemsg/LeaveMsg.java
  3. 40 0
      src/main/java/com/ekexiu/portal/leavemsg/LeaveMsgAgreeRec.java
  4. 80 0
      src/main/java/com/ekexiu/portal/leavemsg/LeaveMsgDao.java
  5. 448 0
      src/main/java/com/ekexiu/portal/leavemsg/Service.java
  6. 87 0
      src/main/java/com/ekexiu/portal/notify/NotifyMsgCnt.java
  7. 51 0
      src/main/java/com/ekexiu/portal/notify/NotifyMsgDao.java
  8. 44 0
      src/main/java/com/ekexiu/portal/notify/NotifyMsgIdx.java
  9. 101 0
      src/main/java/com/ekexiu/portal/notify/NotifyService.java
  10. 57 0
      src/main/java/com/ekexiu/portal/notify/NotifyType.java
  11. 127 0
      src/main/java/com/ekexiu/portal/question/Answer.java
  12. 37 0
      src/main/java/com/ekexiu/portal/question/AnswerAgreeRec.java
  13. 29 0
      src/main/java/com/ekexiu/portal/question/QetKeyWord.java
  14. 153 0
      src/main/java/com/ekexiu/portal/question/Question.java
  15. 185 0
      src/main/java/com/ekexiu/portal/question/QuestionDao.java
  16. 46 0
      src/main/java/com/ekexiu/portal/question/QuestionInviteRec.java
  17. 826 0
      src/main/java/com/ekexiu/portal/question/Service.java
  18. 32 0
      src/main/java/com/ekexiu/portal/question/SortedAnswwer.java
  19. 24 1
      src/main/java/com/ekexiu/portal/service/ArticleService.java
  20. 25 2
      src/main/java/com/ekexiu/portal/service/FeedbackService.java
  21. 60 33
      src/main/java/com/ekexiu/portal/service/PpaperService.java
  22. 26 1
      src/main/java/com/ekexiu/portal/service/PpatentServcie.java
  23. 21 4
      src/main/java/com/ekexiu/portal/service/ProfessorService.java
  24. 17 1
      src/main/java/com/ekexiu/portal/service/ResearchAreaService.java
  25. 61 27
      src/main/java/com/ekexiu/portal/service/WatchService.java
  26. 8 0
      src/main/java/com/ekexiu/portal/util/DebugService.java
  27. 13 0
      src/main/java/com/ekexiu/portal/util/SqlUtil.java
  28. 21 0
      src/main/java/com/ekexiu/push/service/PushService.java
  29. 96 4
      src/main/resources/database.sql
  30. 2 1
      src/main/resources/project-test-dev.properties
  31. 2 1
      src/main/resources/project-test.properties
  32. 1 1
      src/main/resources/project.properties

+ 54 - 0
src/main/java/com/ekexiu/portal/found/Service.java

@ -0,0 +1,54 @@
1
package com.ekexiu.portal.found;
2

3
import java.sql.Connection;
4
import java.sql.PreparedStatement;
5
import java.sql.SQLException;
6
import java.util.List;
7
import java.util.Map;
8

9
import org.jfw.apt.annotation.DefaultValue;
10
import org.jfw.apt.web.annotation.Path;
11
import org.jfw.apt.web.annotation.operate.Get;
12
import org.jfw.apt.web.annotation.param.JdbcConn;
13
import org.jfw.util.jdbc.JdbcUtil;
14
import org.jfw.util.jdbc.PreparedStatementConfig;
15

16
@Path("/found")
17
public class Service {
18
/**
19
 * 查询新发现(含提问)
20
 * @param con
21
 * @param time 下拉加载上一次返回的最后一条数据的tm,首次不传
22
 * @param id 下拉加载上一次返回的最后一条数据的id,首次不传
23
 * @param rows 下拉加载返回的数据条数,默认20
24
 * @param ex 排除的文章ID
25
 * @return [{ctype:"1:专家文章,2:企业文章  3, 提问"
26
 *                 id:"文章id 或  提问ID ",
27
 *                 uid:"专家ID 或 企业id 或 提问人ID ",
28
 *                 tm:"文章发布时间 或 提问时间,
29
 *                 num:0 ,//提问回答数
30
 *                 img:"图片",
31
 *                 col:0,//文章栏目
32
 *                  }....]
33
 * @throws SQLException
34
 */
35
	@Get
36
	@Path("/index")
37
	public List<Map<String,Object>> query(@JdbcConn Connection con,@DefaultValue("\"9\"") final String time,@DefaultValue("\"0\"") final String id,@DefaultValue("20") final int rows,final String ex)throws SQLException{
38
		return JdbcUtil.queryMaps(con, "SELECT * FROM 	( "+
39
		"SELECT ID id,'3' ctype,uid uid,title title,	last_reply_time tm,reply_count num,img img,null col	FROM question where state='1' UNION ALL "+
40
		"SELECT ARTICLE_ID id,	'1' ctype,professor_id uid,article_title title,publish_time tm,	0 num,article_img img,col_num col FROM article WHERE status = '1' AND article_type = '1' AND article_id <>? UNION ALL "+
41
		"SELECT ARTICLE_ID id,	'2' ctype,org_id uid,article_title title,publish_time tm,0 num,article_img img,col_num col FROM article WHERE status = '1' AND article_type = '2' AND article_id <>? 	) T "+
42
        "WHERE T.tm<? OR (T.tm = ? AND T.id > ?) ORDER BY tm DESC LIMIT ?", new PreparedStatementConfig() {
43
			@Override
44
			public void config(PreparedStatement ps) throws SQLException {
45
				ps.setString(1,ex);
46
				ps.setString(2, ex);
47
				ps.setString(3, time);
48
				ps.setString(4, time);
49
				ps.setString(5, id);
50
				ps.setInt(6,rows);
51
			}
52
		});
53
	}
54
}

+ 159 - 0
src/main/java/com/ekexiu/portal/leavemsg/LeaveMsg.java

@ -0,0 +1,159 @@
1
package com.ekexiu.portal.leavemsg;
2

3
import org.jfw.apt.orm.annotation.entry.Column;
4
import org.jfw.apt.orm.annotation.entry.PrimaryKey;
5
import org.jfw.apt.orm.annotation.entry.Table;
6
import org.jfw.apt.orm.core.enums.DE;
7

8
import com.ekexiu.portal.basepo.ModifyTimeSupported;
9

10
@PrimaryKey("id")
11
@Table
12
public class LeaveMsg implements ModifyTimeSupported {
13

14
	private String id;
15
	private String cnt;
16
	private String refId;
17
	private String refType;
18
	private String top;
19
	private String parent;
20
	private String sender;
21
	private String reciver;
22
	private String createTime;
23
	private String modifyTime;
24
	private String state;
25
	private long  agreeCount;
26
	
27
	private transient String timeDesc;
28
	
29
	@Column(DE.text_de)
30
	public String getTimeDesc() {
31
		return timeDesc;
32
	}
33
	public void setTimeDesc(String timeDesc) {
34
		this.timeDesc = timeDesc;
35
	}
36
	/**
37
	 * id
38
	 * @return
39
	 */
40
	@Column(DE.id_32)
41
	public String getId() {
42
		return id;
43
	}
44
	public void setId(String id) {
45
		this.id = id;
46
	}
47
	/**
48
	 * 留言内容
49
	 * @return
50
	 */
51
	@Column(DE.text_de)
52
	public String getCnt() {
53
		return cnt;
54
	}
55
	public void setCnt(String cnt) {
56
		this.cnt = cnt;
57
	}
58
	/**
59
	 * 留言主体ID ,  文章ID,论文ID,专利ID,提问ID
60
	 * @return
61
	 */
62
	@Column(DE.text_de)
63
	public String getRefId() {
64
		return refId;
65
	}
66
	public void setRefId(String refId) {
67
		this.refId = refId;
68
	}
69
	/**
70
	 * 留言主体类型,1:文章   2:论文   3:专利      4:回答
71
	 * @return
72
	 */
73
	@Column(DE.singleChar)
74
	public String getRefType() {
75
		return refType;
76
	}
77
	public void setRefType(String refType) {
78
		this.refType = refType;
79
	}
80
	/**
81
	 * 顶级留言ID
82
	 * @return
83
	 */
84
	@Column(DE.text_de)
85
	public String getTop() {
86
		return top;
87
	}
88
	public void setTop(String top) {
89
		this.top = top;
90
	}
91
	/**
92
	 * 上级留言ID
93
	 * @return
94
	 */
95
	@Column(DE.Text_de)
96
	public String getParent() {
97
		return parent;
98
	}
99
	public void setParent(String parent) {
100
		this.parent = parent;
101
	}
102
	/**
103
	 * 留言人ID
104
	 * @return
105
	 */
106
	@Column(DE.text_de)
107
	public String getSender() {
108
		return sender;
109
	}
110
	public void setSender(String sender) {
111
		this.sender = sender;
112
	}
113
	/**
114
	 * 上级留言的留言人ID
115
	 * @return
116
	 */
117
	@Column(DE.Text_de)
118
	public String getReciver() {
119
		return reciver;
120
	}
121
	public void setReciver(String reciver) {
122
		this.reciver = reciver;
123
	}
124
	@Column(DE.text_de)
125
	public String getCreateTime() {
126
		return createTime;
127
	}
128
	public void setCreateTime(String createTime) {
129
		this.createTime = createTime;
130
	}
131
	public String getModifyTime() {
132
		return modifyTime;
133
	}
134
	public void setModifyTime(String modifyTime) {
135
		this.modifyTime = modifyTime;
136
	}
137
	/**
138
	 * 状态  1: 发布中   0 :删除的
139
	 * @return
140
	 */
141
	@Column(DE.singleChar)
142
	public String getState() {
143
		return state;
144
	}
145
	public void setState(String state) {
146
		this.state = state;
147
	}
148
	/**
149
	 * 留言语的点赞数
150
	 * @return
151
	 */
152
	@Column(DE.long_de)
153
	public long getAgreeCount() {
154
		return agreeCount;
155
	}
156
	public void setAgreeCount(long agreeCount) {
157
		this.agreeCount = agreeCount;
158
	}
159
}

+ 40 - 0
src/main/java/com/ekexiu/portal/leavemsg/LeaveMsgAgreeRec.java

@ -0,0 +1,40 @@
1
package com.ekexiu.portal.leavemsg;
2

3
import org.jfw.apt.orm.annotation.entry.Column;
4
import org.jfw.apt.orm.annotation.entry.PrimaryKey;
5
import org.jfw.apt.orm.annotation.entry.Table;
6
import org.jfw.apt.orm.core.enums.DE;
7

8
import com.ekexiu.portal.basepo.CreateTimeSupported;
9

10
@Table
11
@PrimaryKey({"id","uid"})
12
public class LeaveMsgAgreeRec  implements CreateTimeSupported{
13

14
	private String id;
15
	private String uid;
16
	private String createTime;
17

18
	@Column(DE.text_de)
19
	public String getId() {
20
		return id;
21
	}
22
	public void setId(String id) {
23
		this.id = id;
24
	}
25
	@Column(DE.text_de)
26
	public String getUid() {
27
		return uid;
28
	}
29
	public void setUid(String uid) {
30
		this.uid = uid;
31
	}
32
	@Override
33
	public String getCreateTime() {
34
		return this.createTime;
35
	}
36
	@Override
37
	public void setCreateTime(String createTime) {
38
		this.createTime = createTime;
39
	}
40
}

+ 80 - 0
src/main/java/com/ekexiu/portal/leavemsg/LeaveMsgDao.java

@ -0,0 +1,80 @@
1
package com.ekexiu.portal.leavemsg;
2

3
import java.sql.Connection;
4
import java.sql.SQLException;
5
import java.util.List;
6

7
import org.jfw.apt.annotation.DefaultValue;
8
import org.jfw.apt.annotation.Nullable;
9
import org.jfw.apt.orm.annotation.dao.Column;
10
import org.jfw.apt.orm.annotation.dao.DAO;
11
import org.jfw.apt.orm.annotation.dao.method.From;
12
import org.jfw.apt.orm.annotation.dao.method.IncludeFixSet;
13
import org.jfw.apt.orm.annotation.dao.method.OrderBy;
14
import org.jfw.apt.orm.annotation.dao.method.SetSentence;
15
import org.jfw.apt.orm.annotation.dao.method.Where;
16
import org.jfw.apt.orm.annotation.dao.method.operator.Insert;
17
import org.jfw.apt.orm.annotation.dao.method.operator.LimitSelect;
18
import org.jfw.apt.orm.annotation.dao.method.operator.QueryVal;
19
import org.jfw.apt.orm.annotation.dao.method.operator.SelectOne;
20
import org.jfw.apt.orm.annotation.dao.method.operator.UpdateWith;
21
import org.jfw.apt.orm.annotation.dao.param.GreaterThan;
22
import org.jfw.apt.orm.annotation.dao.param.GroupSqlColumn;
23
import org.jfw.apt.orm.core.defaultImpl.IntHandler;
24
import org.jfw.apt.orm.core.defaultImpl.StringHandler;
25

26
@DAO
27
public interface LeaveMsgDao {
28

29
	@Insert
30
	int insert(Connection con, LeaveMsg msg) throws SQLException;
31

32
	@UpdateWith
33
	@From(LeaveMsg.class)
34
	@SetSentence("STATE = '0'")
35
	@Where("STATE = '1' ")
36
	@IncludeFixSet
37
	int logicDelete(Connection con, String id) throws SQLException;
38

39
	@UpdateWith
40
	@From(LeaveMsg.class)
41
	@SetSentence("AGREE_COUNT = AGREE_COUNT + 1")
42
	@IncludeFixSet
43
	int incAgree(Connection con, String id) throws SQLException;
44

45
	@LimitSelect
46
	@Where("STATE='1'")
47
	@OrderBy("ORDER BY TIME_DESC ASC")
48
	List<LeaveMsg> query(Connection con, String refId, String refType, @GreaterThan String timeDesc, int rows) throws SQLException;
49

50
	@Nullable
51
	@SelectOne
52
	LeaveMsg query(Connection con, String id) throws SQLException;
53

54
	@Insert
55
	int insert(Connection con, LeaveMsgAgreeRec rec) throws SQLException;
56

57
	@Nullable
58
	@SelectOne
59
	LeaveMsgAgreeRec queryAgreeRec(Connection con, String id, String uid) throws SQLException;
60

61
	@LimitSelect
62
	@OrderBy("ORDER BY TIME_DESC ASC")
63
	List<LeaveMsg> queryWithParent(Connection con, String parent, @GreaterThan String timeDesc, int rows) throws SQLException;
64

65
	@LimitSelect
66
	@OrderBy("ORDER BY TIME_DESC ASC")
67
	List<LeaveMsg> queryWithTop(Connection con, String top,
68
			@GroupSqlColumn(handlerClass = StringHandler.class, isAnd = false, value = { "SENDER=?", "RECIVER=?" }, force = true) String sid,
69
			@GroupSqlColumn(handlerClass = StringHandler.class, isAnd = false, value = { "SENDER=?", "RECIVER=?" }, force = true) String rid,
70
			 @GreaterThan String timeDesc,int rows) throws SQLException;
71

72
	@QueryVal
73
	@From(LeaveMsg.class)
74
	@DefaultValue("0")
75
	@Column(value="COUNT(ID)",handlerClass=IntHandler.class)
76
	@Where("STATE='1'")
77
	int queryCount(Connection con,String refType,String refId) throws SQLException;
78
	
79
	
80
}

+ 448 - 0
src/main/java/com/ekexiu/portal/leavemsg/Service.java

@ -0,0 +1,448 @@
1
package com.ekexiu.portal.leavemsg;
2

3
import java.sql.Connection;
4
import java.sql.PreparedStatement;
5
import java.sql.SQLException;
6
import java.util.List;
7
import java.util.Map;
8

9
import org.jfw.apt.annotation.Autowrie;
10
import org.jfw.apt.annotation.DefaultValue;
11
import org.jfw.apt.web.annotation.Path;
12
import org.jfw.apt.web.annotation.operate.Get;
13
import org.jfw.apt.web.annotation.operate.Post;
14
import org.jfw.apt.web.annotation.param.AfterCommit;
15
import org.jfw.apt.web.annotation.param.FieldParam;
16
import org.jfw.apt.web.annotation.param.JdbcConn;
17
import org.jfw.apt.web.annotation.param.RequestParam;
18
import org.jfw.util.DateUtil;
19
import org.jfw.util.StringUtil;
20
import org.jfw.util.exception.JfwBaseException;
21
import org.jfw.util.jdbc.JdbcUtil;
22
import org.jfw.util.jdbc.PreparedStatementConfig;
23

24
import com.ekexiu.portal.dao.ArticleDao;
25
import com.ekexiu.portal.dao.PaperAuthorDao;
26
import com.ekexiu.portal.dao.PatentAuthorDao;
27
import com.ekexiu.portal.dao.PpaperDao;
28
import com.ekexiu.portal.dao.PpatentDao;
29
import com.ekexiu.portal.notify.NotifyService;
30
import com.ekexiu.portal.notify.NotifyType;
31
import com.ekexiu.portal.po.Article;
32
import com.ekexiu.portal.po.PaperAuthor;
33
import com.ekexiu.portal.po.PatentAuthor;
34
import com.ekexiu.portal.po.Ppaper;
35
import com.ekexiu.portal.po.Ppatent;
36
import com.ekexiu.portal.question.Answer;
37
import com.ekexiu.portal.question.Question;
38
import com.ekexiu.portal.question.QuestionDao;
39

40
@Path("/leavemsg")
41
public class Service {
42
	@Autowrie
43
	private LeaveMsgDao leaveMsgDao;
44

45
	@Autowrie
46
	private ArticleDao articleDao;
47

48
	@Autowrie
49
	private PpatentDao ppatentDao;
50
	@Autowrie
51
	private PpaperDao ppaperDao;
52
	@Autowrie
53
	private QuestionDao questionDao;
54

55
	@Autowrie
56
	private NotifyService notifyService;
57

58
	@Autowrie
59
	private PaperAuthorDao paperAuthorDao;
60
	@Autowrie
61
	private PatentAuthorDao patentAuthorDao;
62

63
	public PaperAuthorDao getPaperAuthorDao() {
64
		return paperAuthorDao;
65
	}
66

67
	public void setPaperAuthorDao(PaperAuthorDao paperAuthorDao) {
68
		this.paperAuthorDao = paperAuthorDao;
69
	}
70

71
	public PatentAuthorDao getPatentAuthorDao() {
72
		return patentAuthorDao;
73
	}
74

75
	public void setPatentAuthorDao(PatentAuthorDao patentAuthorDao) {
76
		this.patentAuthorDao = patentAuthorDao;
77
	}
78

79
	public ArticleDao getArticleDao() {
80
		return articleDao;
81
	}
82

83
	public void setArticleDao(ArticleDao articleDao) {
84
		this.articleDao = articleDao;
85
	}
86

87
	public PpatentDao getPpatentDao() {
88
		return ppatentDao;
89
	}
90

91
	public void setPpatentDao(PpatentDao ppatentDao) {
92
		this.ppatentDao = ppatentDao;
93
	}
94

95
	public PpaperDao getPpaperDao() {
96
		return ppaperDao;
97
	}
98

99
	public void setPpaperDao(PpaperDao ppaperDao) {
100
		this.ppaperDao = ppaperDao;
101
	}
102

103
	public QuestionDao getQuestionDao() {
104
		return questionDao;
105
	}
106

107
	public void setQuestionDao(QuestionDao questionDao) {
108
		this.questionDao = questionDao;
109
	}
110

111
	public NotifyService getNotifyService() {
112
		return notifyService;
113
	}
114

115
	public void setNotifyService(NotifyService notifyService) {
116
		this.notifyService = notifyService;
117
	}
118

119
	public LeaveMsgDao getLeaveMsgDao() {
120
		return leaveMsgDao;
121
	}
122

123
	public void setLeaveMsgDao(LeaveMsgDao leaveMsgDao) {
124
		this.leaveMsgDao = leaveMsgDao;
125
	}
126

127
	// 1:文章 2:论文 3:专利 4:回答
128
	public void notify(Connection con, String type, String id, String reciver, String uid, String uname, String lid,boolean agree, List<Runnable> runs)
129
			throws SQLException, JfwBaseException {
130
		if (type.equals("1")) {
131
			Article article = this.articleDao.queryOne(con, id);
132
			if (article == null) {
133
				throw new JfwBaseException(50000, "article[" + id + "] not found");
134
			}
135
			if (article.getArticleType().equals("1")) {
136
				if (reciver == null) {
137
					this.notifyService.notify(con, article.getProfessorId(), uid, uname, lid, article.getArticleTitle(), NotifyType.LEAVE_MSG_AT_ARTICLE, runs);
138
				} else {
139
					this.notifyService.notify(con, reciver, uid, uname, lid, article.getArticleTitle(),agree?NotifyType.AGREE_LEAVE_MSG_AT_ARTICLE: NotifyType.REPLY_LEAVE_MSG_AT_ARTICLE, runs);
140
				}
141
			}
142

143
		} else if (type.equals("2")) {
144
			Ppaper paper = this.ppaperDao.query(con, id);
145
			if (paper == null) {
146
				throw new JfwBaseException(50000, "paper[" + id + "] not found");
147
			}
148
			if (reciver == null) {
149
				for (PaperAuthor pa : this.paperAuthorDao.query(con, id)) {
150
					if (!pa.getProfessorId().startsWith("#")) {
151
						this.notifyService.notify(con, pa.getProfessorId(), uid, uname, lid, paper.getName(), NotifyType.LEAVE_MSG_AT_PAPER, runs);
152
					}
153
				}
154
			} else {
155
				this.notifyService.notify(con, reciver, uid, uname, lid, paper.getName(),agree?NotifyType.AGREE_LEAVE_MSG_AT_PAPER: NotifyType.REPLY_LEAVE_MSG_AT_PAPER, runs);
156
			}
157
		} else if (type.equals("3")) {
158
			Ppatent patent = this.ppatentDao.query(con, id);
159
			if (patent == null) {
160
				throw new JfwBaseException(50000, "patent[" + id + "] not found");
161
			}
162
			if (reciver == null) {
163
				for (PatentAuthor pa : this.patentAuthorDao.query(con, id)) {
164
					if (!pa.getProfessorId().startsWith("#")) {
165
						this.notifyService.notify(con, pa.getProfessorId(), uid, uname, lid, patent.getName(), NotifyType.LEAVE_MSG_AT_PARENT, runs);
166
					}
167
				}
168
			} else {
169
				this.notifyService.notify(con, reciver, uid, uname, lid, patent.getName(),agree?NotifyType.AGREE_LEAVE_MSG_AT_PARENT: NotifyType.REPLY_LEAVE_MSG_AT_PARENT, runs);
170
			}
171
		} else if (type.equals("4")) {
172
			Answer a = this.questionDao.queryAnswer(con, id);
173
			if(a ==null){
174
				throw new JfwBaseException(50000, "answer[" + id + "] not found");
175
			}
176
			Question q = this.questionDao.query(con, a.getQid());
177
			if (q == null) {
178
				throw new JfwBaseException(50000, "answer[" + id + "]'question not found");
179
			}
180
			if (reciver == null) {
181
				this.notifyService.notify(con,a.getUid(), uid, uname, lid, q.getTitle(), NotifyType.LEAVE_MSG_AT_ANSWER, runs);
182
			} else {
183
				this.notifyService.notify(con, reciver, uid, uname, lid, q.getTitle(),agree?NotifyType.AGREE_LEAVE_MSG_AT_ANSWER: NotifyType.REPLY_LEAVE_MSG_AT_ANSWER, runs);
184
			}
185
		} else {
186
			throw new IllegalArgumentException();
187
		}
188
	}
189

190
	/**
191
	 * 新增一顶级留言
192
	 * 
193
	 * @param con
194
	 * @param msg
195
	 *            cnt
196
	 * @param title
197
	 *            文章标题 论文标题 专利标题 提问
198
	 * @param uname
199
	 *            发送人名称
200
	 * @param runs
201
	 * @return
202
	 * @throws SQLException
203
	 * @throws JfwBaseException
204
	 */
205
	@Path()
206
	@Post
207
	public String save(@JdbcConn(true) Connection con,
208
			@RequestParam(fields = { @FieldParam(value = "cnt", valueClass = String.class), @FieldParam(value = "refId", valueClass = String.class),
209
					@FieldParam(value = "refType", valueClass = String.class), @FieldParam(value = "sender", valueClass = String.class) }) LeaveMsg msg,
210
			 String uname, @AfterCommit List<Runnable> runs) throws SQLException, JfwBaseException {
211
		String id = StringUtil.buildUUID();
212
		String time = DateUtil.formatDateTime(System.currentTimeMillis());
213
		msg.setId(id);
214
		msg.setTop(id);
215
		msg.setState("1");
216
		msg.setParent(null);
217
		msg.setAgreeCount(0);
218
		msg.setCreateTime(time);
219
		msg.setTimeDesc(time+id);
220
		leaveMsgDao.insert(con, msg);
221
		this.notify(con, msg.getRefType(), msg.getRefId(), null, msg.getSender(), uname, id,false, runs);
222
		return id;
223
	}
224

225
	/**
226
	 * 回复留言
227
	 * 
228
	 * @param con
229
	 * @param cnt
230
	 *            留言内容
231
	 * @param id
232
	 *            被回复留言ID
233
	 * @param uid
234
	 *            用户ID
235
	 * @param title
236
	 *            留言主体 文章标题 论文标题 专利标题 提问
237
	 * @param uname
238
	 *            用户姓名
239
	 * @param runs
240
	 * @return
241
	 * @throws SQLException
242
	 * @throws JfwBaseException
243
	 */
244
	@Path("/reply")
245
	@Post
246
	public String reply(@JdbcConn(true) Connection con, String cnt, String id, String uid, String uname,
247
			@AfterCommit List<Runnable> runs) throws SQLException, JfwBaseException {
248
		final LeaveMsg msg = leaveMsgDao.query(con, id);
249
		if (msg == null)
250
			throw new JfwBaseException(50000, "leave message[id:" + id + "] not found");
251
		if (msg.getSender().equals(uid)) {
252
			throw new JfwBaseException(50001, "can't reply self");
253
		}
254
		String nid = StringUtil.buildUUID();
255
		msg.setParent(id);
256
		msg.setReciver(msg.getSender());
257
		msg.setSender(uid);
258
		msg.setState("1");
259
		msg.setCnt(cnt);
260
		msg.setId(nid);
261
		String time = DateUtil.formatDateTime(System.currentTimeMillis());
262
		msg.setCreateTime(time);
263
		msg.setTimeDesc(time+nid);
264
		leaveMsgDao.insert(con, msg);
265
		this.notify(con, msg.getRefType(), msg.getRefId(), msg.getReciver(), uid, uname, id,false, runs);
266
		return nid;
267
	}
268

269
	/**
270
	 * 查询某主体下的留言
271
	 * 
272
	 * @param con
273
	 * @param stype
274
	 *            主体类型 1:文章 2:论文 3:专利 4:提问
275
	 * @param sid
276
	 *            留言主体ID , 文章ID,论文ID,专利ID,提问ID
277
	 * @param time
278
	 *            留言时间 time > createTime
279
	 * @param id
280
	 *            留言ID time > createTime && id >leaveMsg.id
281
	 * @param rows
282
	 *            返回的最大条数
283
	 * @return
284
	 * @throws SQLException
285
	 */
286
	@Get
287
	@Path("/subject")
288
	public List<LeaveMsg> query(@JdbcConn Connection con, String stype, String sid, @DefaultValue("\"0\"") String time, @DefaultValue("\"0\"") String id,
289
			int rows) throws SQLException {
290
		return leaveMsgDao.query(con, sid, stype, time+id, rows);
291
	}
292

293
	@Get
294
	@Path("/count")
295
	public int query(@JdbcConn Connection con, String stype, String sid) throws SQLException {
296
		return leaveMsgDao.queryCount(con, stype, sid);
297
	}
298

299
	@Get
300
	@Path("/counts")
301
	public List<Map<String, Object>> query(@JdbcConn Connection con, final String stype, final String[] ids) throws SQLException {
302
		StringBuilder sb = new StringBuilder();
303
		sb.append("SELECT REF_ID rid,COUNT(1) num FROM LEAVE_MSG WHERE REF_TYPE =? AND REF_ID IN (?");
304
		for (int i = 1; i < ids.length; ++i) {
305
			sb.append(",?");
306
		}
307
		sb.append(") GROUP BY rid");
308

309
		return JdbcUtil.queryMaps(con, sb.toString(), new PreparedStatementConfig() {
310

311
			@Override
312
			public void config(PreparedStatement ps) throws SQLException {
313
				int idx = 1;
314
				ps.setString(idx++, stype);
315
				for (int i = 0; i < ids.length; ++i) {
316
					ps.setString(idx++, ids[i]);
317
				}
318
			}
319
		});
320
	}
321

322
	/**
323
	 * 删除留言
324
	 * 
325
	 * @param con
326
	 * @param id
327
	 *            留言ID
328
	 * @return
329
	 * @throws SQLException
330
	 */
331
	@Get
332
	@Path("/del")
333
	public int delete(@JdbcConn(true) Connection con, String id) throws SQLException {
334
		return leaveMsgDao.logicDelete(con, id);
335
	}
336

337
	/**
338
	 * 点赞留言
339
	 * 
340
	 * @param con
341
	 * @param id
342
	 *            留言ID
343
	 * @param uid
344
	 *            点赞用户ID * @param uname 点赞用户姓名
345
	 * @param runs
346
	 * @throws SQLException
347
	 * @throws JfwBaseException
348
	 */
349
	@Post
350
	@Path("/agree")
351
	public void agree(@JdbcConn(true) Connection con, String id, String uid, String uname, @AfterCommit List<Runnable> runs)
352
			throws SQLException, JfwBaseException {
353
		LeaveMsg msg = leaveMsgDao.query(con, id);
354
		if (msg == null) {
355
			throw new JfwBaseException(50000, "leave message[id:" + id + "] not found");
356
		}
357
		LeaveMsgAgreeRec lmar = new LeaveMsgAgreeRec();
358
		lmar.setId(id);
359
		lmar.setUid(uid);
360
		try {
361
			leaveMsgDao.insert(con, lmar);
362
		} catch (SQLException e) {
363
			if ("23505".equals(e.getSQLState())) {
364
				con.rollback();
365
				throw new JfwBaseException(50001, "leave message  duplicate agree");
366
			}
367
			throw e;
368
		}
369
		if (leaveMsgDao.incAgree(con, id) > 0) {
370
			this.notify(con, msg.getRefType(), msg.getRefId(), msg.getSender(), uid, uname, msg.getId(), true, runs);
371
		}
372
	}
373

374
	/**
375
	 * 是否对指定留言点过赞
376
	 * 
377
	 * @param con
378
	 * @param id
379
	 *            留言 ID
380
	 * @param uid
381
	 *            用户ID
382
	 * @return
383
	 * @throws SQLException
384
	 */
385
	@Get
386
	@Path("/agree")
387
	public boolean agree(@JdbcConn Connection con, String id, String uid) throws SQLException {
388
		return null != leaveMsgDao.queryAgreeRec(con, id, uid);
389
	}
390

391
	/**
392
	 * 查贸询一个指定的留言
393
	 * 
394
	 * @param con
395
	 * @param id
396
	 *            留言ID
397
	 * @return
398
	 * @throws SQLException
399
	 */
400
	@Get
401
	@Path("/qo")
402
	public LeaveMsg query(@JdbcConn Connection con, String id) throws SQLException {
403
		return leaveMsgDao.query(con, id);
404
	}
405

406
	// @Get
407
	// @Path("/parent")
408
	// public List<LeaveMsg> parent(@JdbcConn Connection con, String parent,
409
	// @DefaultValue("\"0\"") String time, @DefaultValue("\"0\"") String id,
410
	// @DefaultValue("10") int rows) throws SQLException {
411
	// return leaveMsgDao.queryWithParent(con, parent, time, id, rows);
412
	// }
413
	//
414
	// @Get
415
	// @Path("/top")
416
	// public List<LeaveMsg> top(@JdbcConn Connection con, String top, String
417
	// sid, String rid, @DefaultValue("\"0\"") String time,
418
	// @DefaultValue("\"0\"") String id,
419
	// @DefaultValue("10") int rows) throws SQLException {
420
	// return leaveMsgDao.queryWithTop(con, top, sid, rid, time, id, rows);
421
	// }
422
	/**
423
	 * 留言对话框
424
	 * 
425
	 * @param con
426
	 * @param id
427
	 *            留言ID
428
	 * @return
429
	 * @throws SQLException
430
	 * @throws JfwBaseException
431
	 */
432
	@Get
433
	@Path("/dialog")
434
	public List<LeaveMsg> dialog(@JdbcConn Connection con, String id) throws SQLException, JfwBaseException {
435
		List<LeaveMsg> ret = null;
436
		LeaveMsg msg = leaveMsgDao.query(con, id);
437
		if (msg == null)
438
			throw new JfwBaseException(50000, "leave message[id:" + id + "] not found");
439
		if (msg.getId().equals(msg.getTop())) {
440
			ret = leaveMsgDao.queryWithParent(con, msg.getId(), "0", Integer.MAX_VALUE);
441
			ret.add(0, msg);
442
		} else {
443
			ret = leaveMsgDao.queryWithTop(con, msg.getId(), msg.getSender(), msg.getReciver(), "0", Integer.MAX_VALUE);
444
		}
445
		return ret;
446
	}
447

448
}

+ 87 - 0
src/main/java/com/ekexiu/portal/notify/NotifyMsgCnt.java

@ -0,0 +1,87 @@
1
package com.ekexiu.portal.notify;
2

3
import org.jfw.apt.orm.annotation.entry.Column;
4
import org.jfw.apt.orm.annotation.entry.PrimaryKey;
5
import org.jfw.apt.orm.annotation.entry.Table;
6
import org.jfw.apt.orm.core.enums.DE;
7

8
@Table
9
@PrimaryKey("id")
10
public class NotifyMsgCnt{
11

12
	private String id;
13
	private String cnt;
14
	private String reciver;
15
	private boolean readed;
16
	private String pid;
17
	private String uid;
18
	private String createTime;
19
	private int opType;
20
	
21
	private transient String timeDesc;
22
	@Column(DE.text_de)
23
	public String getTimeDesc() {
24
		return timeDesc;
25
	}
26
	public void setTimeDesc(String timeDesc) {
27
		this.timeDesc = timeDesc;
28
	}
29
	@Column(DE.id_32)
30
	public String getId() {
31
		return id;
32
	}
33
	public void setId(String id) {
34
		this.id = id;
35
	}
36
	@Column(DE.text_de)
37
	public String getCnt() {
38
		return cnt;
39
	}
40
	public void setCnt(String cnt) {
41
		this.cnt = cnt;
42
	}
43
	@Column(DE.text_de)
44
	public String getReciver() {
45
		return reciver;
46
	}
47
	public void setReciver(String reciver) {
48
		this.reciver = reciver;
49
	}
50
	@Column(DE.boolean_de)
51
	public boolean isReaded() {
52
		return readed;
53
	}
54
	public void setReaded(boolean readed) {
55
		this.readed = readed;
56
	}
57
	@Column(DE.text_de)
58
	public String getPid() {
59
		return pid;
60
	}
61
	public void setPid(String pid) {
62
		this.pid = pid;
63
	}
64
	@Column(DE.text_de)
65
	public String getUid() {
66
		return uid;
67
	}
68
	public void setUid(String uid) {
69
		this.uid = uid;
70
	}
71
	@Column(DE.text_de)
72
	public String getCreateTime() {
73
		return createTime;
74
	}
75
	public void setCreateTime(String createTime) {
76
		this.createTime = createTime;
77
	}
78
	@Column(DE.int_de)
79
	public int getOpType() {
80
		return opType;
81
	}
82
	public void setOpType(int opType) {
83
		this.opType = opType;
84
	}
85

86
	
87
}

+ 51 - 0
src/main/java/com/ekexiu/portal/notify/NotifyMsgDao.java

@ -0,0 +1,51 @@
1
package com.ekexiu.portal.notify;
2

3
import java.sql.Connection;
4
import java.sql.SQLException;
5
import java.util.List;
6

7
import org.jfw.apt.annotation.Nullable;
8
import org.jfw.apt.orm.annotation.dao.DAO;
9
import org.jfw.apt.orm.annotation.dao.method.From;
10
import org.jfw.apt.orm.annotation.dao.method.OrderBy;
11
import org.jfw.apt.orm.annotation.dao.method.SetSentence;
12
import org.jfw.apt.orm.annotation.dao.method.Where;
13
import org.jfw.apt.orm.annotation.dao.method.operator.Insert;
14
import org.jfw.apt.orm.annotation.dao.method.operator.LimitSelect;
15
import org.jfw.apt.orm.annotation.dao.method.operator.SelectOne;
16
import org.jfw.apt.orm.annotation.dao.method.operator.UpdateWith;
17
import org.jfw.apt.orm.annotation.dao.param.LessThan;
18
import org.jfw.apt.orm.annotation.dao.param.LtEq;
19
import org.jfw.apt.orm.annotation.dao.param.Set;
20

21
@DAO
22
public interface NotifyMsgDao {
23

24
	@Insert
25
	int insert(Connection con,NotifyMsgIdx msg)throws SQLException;
26
	@Insert
27
	int insert(Connection con,NotifyMsgCnt msg)throws SQLException;
28
	@UpdateWith
29
	@From(NotifyMsgIdx.class)
30
	@SetSentence("UN_READ = UN_READ +1")
31
	int updateIdx(Connection con,@Set String lastCnt,@Set String lastTime,String reciver ) throws SQLException;
32
	
33
	@UpdateWith
34
	@From(NotifyMsgIdx.class)
35
	int decUnRead(Connection con,String reciver, @Set(" = UN_READ - ?") int unRead ) throws SQLException;
36
	
37
	@SelectOne
38
	@Nullable
39
	NotifyMsgIdx queryIdx(Connection con,String reciver)throws SQLException;
40
	
41
	
42
	@LimitSelect
43
	@OrderBy("ORDER BY TIME_DESC DESC")
44
	List<NotifyMsgCnt> queryCnt(Connection con,String reciver,@LessThan String timeDesc,int rows)throws SQLException;
45
	
46
	@UpdateWith
47
	@From(NotifyMsgCnt.class)
48
	@SetSentence("READED='1'")
49
	@Where("READED<>'1'")
50
	int readed(Connection con,String reciver ,@LtEq String timeDesc)throws SQLException; 
51
}

+ 44 - 0
src/main/java/com/ekexiu/portal/notify/NotifyMsgIdx.java

@ -0,0 +1,44 @@
1
package com.ekexiu.portal.notify;
2

3
import org.jfw.apt.orm.annotation.entry.Column;
4
import org.jfw.apt.orm.annotation.entry.PrimaryKey;
5
import org.jfw.apt.orm.annotation.entry.Table;
6
import org.jfw.apt.orm.core.enums.DE;
7

8
@Table
9
@PrimaryKey("reciver")
10
public class NotifyMsgIdx {
11
	private String reciver;
12
	private String lastCnt;
13
	private String lastTime;
14
	private int unRead;
15
	@Column(DE.text_de)
16
	public String getReciver() {
17
		return reciver;
18
	}
19
	public void setReciver(String reciver) {
20
		this.reciver = reciver;
21
	}
22
	@Column(DE.text_de)
23
	public String getLastCnt() {
24
		return lastCnt;
25
	}
26
	public void setLastCnt(String lastCnt) {
27
		this.lastCnt = lastCnt;
28
	}
29
	@Column(DE.text_de)
30
	public String getLastTime() {
31
		return lastTime;
32
	}
33
	public void setLastTime(String lastTime) {
34
		this.lastTime = lastTime;
35
	}
36
	@Column(DE.int_de)
37
	public int getUnRead() {
38
		return unRead;
39
	}
40
	public void setUnRead(int unRead) {
41
		this.unRead = unRead;
42
	}
43
	
44
}

+ 101 - 0
src/main/java/com/ekexiu/portal/notify/NotifyService.java

@ -0,0 +1,101 @@
1
package com.ekexiu.portal.notify;
2

3
import java.sql.Connection;
4
import java.sql.SQLException;
5
import java.util.List;
6

7
import org.jfw.apt.annotation.Autowrie;
8
import org.jfw.apt.annotation.DefaultValue;
9
import org.jfw.apt.web.annotation.Path;
10
import org.jfw.apt.web.annotation.operate.Get;
11
import org.jfw.apt.web.annotation.operate.Post;
12
import org.jfw.apt.web.annotation.param.JdbcConn;
13
import org.jfw.util.DateUtil;
14
import org.jfw.util.StringUtil;
15
import org.jfw.util.json.JsonService;
16

17
import com.ekexiu.portal.util.WebMsgSocketServlet;
18
import com.ekexiu.push.service.PushService;
19

20
@Path("/notify")
21
public class NotifyService {
22

23
	@Autowrie
24
	private NotifyMsgDao notifyMsgDao;
25
	@Autowrie
26
	private PushService pushService;
27

28
	public NotifyMsgDao getNotifyMsgDao() {
29
		return notifyMsgDao;
30
	}
31

32
	public void setNotifyMsgDao(NotifyMsgDao notifyMsgDao) {
33
		this.notifyMsgDao = notifyMsgDao;
34
	}
35

36
	public PushService getPushService() {
37
		return pushService;
38
	}
39

40
	public void setPushService(PushService pushService) {
41
		this.pushService = pushService;
42
	}
43

44
	public void notify(Connection con, final String rid, String uid, String uname, String pid, String pname, NotifyType type,List<Runnable> runs) throws SQLException {
45
		String time = DateUtil.formatDateTime(System.currentTimeMillis());
46
		String id = StringUtil.buildUUID();
47
		String tCnt = type.format(uname, pname);
48
		final NotifyMsgCnt cnt = new NotifyMsgCnt();
49
		cnt.setId(id);
50
		cnt.setCnt(tCnt);
51
		cnt.setCreateTime(time);
52
		cnt.setOpType(type.getType());
53
		cnt.setPid(pid);
54
		cnt.setReaded(false);
55
		cnt.setReciver(rid);
56
		cnt.setUid(uid);
57
		cnt.setTimeDesc(time+id);
58
		notifyMsgDao.insert(con, cnt);
59
		final NotifyMsgIdx idx = new NotifyMsgIdx();
60
		idx.setLastCnt(tCnt);
61
		idx.setLastTime(time);
62
		idx.setReciver(rid);
63
		idx.setUnRead(1);
64
		if (notifyMsgDao.updateIdx(con, tCnt, time, rid) < 1) {
65
			notifyMsgDao.insert(con, idx);
66
		}
67

68
		final Runnable ret = new Runnable() {
69
			public void run() {
70
				WebMsgSocketServlet.sendMessage(rid, JsonService.toJson(cnt));
71
				try {
72
					pushService.pushWithAlias("通知", "您收到了一条通知", "msgsend", rid);
73
				} catch (Throwable thr) {
74
				}
75
			}
76
		};
77
		runs.add(ret);
78
	}
79

80
	@Path("/idx")
81
	@Get
82
	public NotifyMsgIdx query(@JdbcConn Connection con, String id) throws SQLException {
83
		return notifyMsgDao.queryIdx(con, id);
84
	}
85

86
	@Path()
87
	@Get
88
	public List<NotifyMsgCnt> query(@JdbcConn Connection con, String uid, @DefaultValue("\"99999999999999\"") String time, @DefaultValue("\"0\"") String mid,
89
			@DefaultValue("20") int rows) throws SQLException {
90
		return notifyMsgDao.queryCnt(con, uid, time+mid, rows);
91
	}
92
	@Post
93
	@Path("/readed")
94
	public int read(@JdbcConn(true) Connection con,String uid,String time,String mid)throws SQLException{
95
		int num = this.notifyMsgDao.readed(con, uid,time+mid);
96
		if(num>0){
97
			this.notifyMsgDao.decUnRead(con, uid,num);
98
		}
99
		return num;
100
	}
101
}

+ 57 - 0
src/main/java/com/ekexiu/portal/notify/NotifyType.java

@ -0,0 +1,57 @@
1
package com.ekexiu.portal.notify;
2

3
public enum NotifyType {
4
	AGREE_LEAVE_MSG_AT_ANSWER("%s  点赞了您在回答 <span>%s</span> 下的留言",19, 2) ,
5
	AGREE_LEAVE_MSG_AT_PAPER("%s  点赞了您在论文 <span>%s</span> 下的留言",18, 2) ,
6
	AGREE_LEAVE_MSG_AT_PARENT("%s  点赞了您在专利 <span>%s</span> 下的留言",17, 2) ,
7
	AGREE_LEAVE_MSG_AT_ARTICLE("%s  点赞了您在文章 <span>%s</span> 下的留言",16, 2) ,
8
	REPLY_LEAVE_MSG_AT_ANSWER("%s  回复了您在回答 <span>%s</span> 下的留言",15, 2) ,
9
	REPLY_LEAVE_MSG_AT_PAPER("%s  回复了您在论文 <span>%s</span> 下的留言",14, 2) ,
10
	REPLY_LEAVE_MSG_AT_PARENT("%s  回复了您在专利 <span>%s</span> 下的留言",13, 2) ,
11
	REPLY_LEAVE_MSG_AT_ARTICLE("%s  回复了您在文章 <span>%s</span> 下的留言",12, 2) ,
12
	LEAVE_MSG_AT_ANSWER("%s  给您的回答 <span>%s</span> 留言了",11, 2) ,
13
	LEAVE_MSG_AT_PAPER("%s  给您的论文 <span>%s</span> 留言了",10, 2) ,
14
	LEAVE_MSG_AT_PARENT("%s  给您的专利 <span>%s</span> 留言了", 9, 2) ,
15
	LEAVE_MSG_AT_ARTICLE("%s  给您的文章 <span>%s</span> 留言了", 8, 2) ,
16
	AGREE_PAPER("%s 点赞了您的论文 <span>%s</span>", 7, 2) ,
17
	AGREE_PATENT("%s 点赞了您的专利 <span>%s</span>", 6, 2) ,
18
	INVITE_ANSWER("%s 邀请您回答问题 <span>%s</span>", 5, 2) ,
19
	ACCEPT_ANSWER("%s 点赞了您在问题 <span>%s</span> 下的回答", 4, 2) ,
20
	ANSWER_QUESTION("%s 回答了您的提问 <span>%s</span>", 3, 2) ,
21
	AGREE_ARTICLE("%s 点赞了您的文章 <span>%s</span>", 2, 2) ,
22
	AGREE_RESEARCH_AREA("%s 点赞了您的研究方向 <span>%s</span>", 1, 2) ,
23
	WATCH_USER("<span>%s</span> 关注了您", 0, 1);
24

25
	private String template;
26
	private int type;
27
	private int paramSize;
28

29
	NotifyType(String template, int type, int paramSize) {
30
		this.template = template;
31
		this.type = type;
32
		this.paramSize = paramSize;
33
	}
34

35
	public String getTemplate() {
36
		return template;
37
	}
38

39
	public int getType() {
40
		return type;
41
	}
42

43
	public String format(String user, String title) {
44
		return paramSize == 1 ? String.format(this.template, html(user)) : String.format(this.template, html(user), html(title));
45
	}
46

47
	private static String html(String html) {
48
		html = html.replaceAll("&", "&amp;");
49
		html = html.replace("\"", "&quot;"); // "
50
		html = html.replace("\t", "&nbsp;&nbsp;");// 替换跳格
51
		html = html.replace(" ", "&nbsp;");// 替换空格
52
		html = html.replace("<", "&lt;");
53
		html = html.replaceAll(">", "&gt;");
54
		return html;
55
	}
56

57
}

+ 127 - 0
src/main/java/com/ekexiu/portal/question/Answer.java

@ -0,0 +1,127 @@
1
package com.ekexiu.portal.question;
2

3
import org.jfw.apt.orm.annotation.entry.Column;
4
import org.jfw.apt.orm.annotation.entry.PrimaryKey;
5
import org.jfw.apt.orm.annotation.entry.Table;
6
import org.jfw.apt.orm.annotation.entry.Unique;
7
import org.jfw.apt.orm.annotation.entry.Uniques;
8
import org.jfw.apt.orm.core.enums.DE;
9

10
@PrimaryKey("id")
11
@Uniques({@Unique(clolumns={"qid","uid"},name="UNI_ANSWER_QID_UID")})
12
@Table
13
public class Answer {
14
	private String id;
15
	private String qid;
16
	private String uid;
17
	private String state;
18
	private String cnt;
19
	private long agree;
20
	private long  ballot;
21
	private String createTime;
22
	private String modifyTime;
23
	private transient String timeDesc;
24
	
25
	@Column(DE.text_de)
26
	public String getTimeDesc() {
27
		return timeDesc;
28
	}
29
	public void setTimeDesc(String timeDesc) {
30
		this.timeDesc = timeDesc;
31
	}
32
	/**
33
	 * ID
34
	 * @return
35
	 */
36
	@Column(DE.id_32)
37
	public String getId() {
38
		return id;
39
	}
40
	public void setId(String id) {
41
		this.id = id;
42
	}
43
	/**
44
	 * 问题ID
45
	 * @return
46
	 */
47
	@Column(DE.text_de)
48
	public String getQid() {
49
		return qid;
50
	}
51
	public void setQid(String qid) {
52
		this.qid = qid;
53
	}
54
	/**
55
	 * 回答人ID
56
	 * @return
57
	 */
58
	@Column(DE.text_de)
59
	public String getUid() {
60
		return uid;
61
	}
62
	public void setUid(String uid) {
63
		this.uid = uid;
64
	}
65
	/**
66
	 * 状态 1:发布中   
67
	 * @return
68
	 */
69
	@Column(DE.singleChar)
70
	public String getState() {
71
		return state;
72
	}
73
	public void setState(String state) {
74
		this.state = state;
75
	}
76
	/**
77
	 * 回答内容
78
	 * @return
79
	 */
80
	@Column(DE.text_de)
81
	public String getCnt() {
82
		return cnt;
83
	}
84
	public void setCnt(String cnt) {
85
		this.cnt = cnt;
86
	}
87
	/**
88
	 * 点赞数量
89
	 */
90
	@Column(DE.long_de)
91
	public long getAgree() {
92
		return agree;
93
	}
94
	public void setAgree(long agree) {
95
		this.agree = agree;
96
	}
97
	/**
98
	 * 总数投票数
99
	 * @return
100
	 */
101
	@Column(DE.long_de)
102
	public long getBallot() {
103
		return ballot;
104
	}
105
	public void setBallot(long ballot) {
106
		this.ballot = ballot;
107
	}
108
	@Column(DE.text_de)
109
	public String getCreateTime() {
110
		return createTime;
111
	}
112
	public void setCreateTime(String createTime) {
113
		this.createTime = createTime;
114
	}
115
	@Column(DE.text_de)
116
	public String getModifyTime() {
117
		return modifyTime;
118
	}
119
	public void setModifyTime(String modifyTime) {
120
		this.modifyTime = modifyTime;
121
	}
122
	
123
	
124
	
125
	
126
	
127
}

+ 37 - 0
src/main/java/com/ekexiu/portal/question/AnswerAgreeRec.java

@ -0,0 +1,37 @@
1
package com.ekexiu.portal.question;
2

3
import org.jfw.apt.orm.annotation.entry.Column;
4
import org.jfw.apt.orm.annotation.entry.PrimaryKey;
5
import org.jfw.apt.orm.annotation.entry.Table;
6
import org.jfw.apt.orm.core.enums.DE;
7

8
@PrimaryKey({"uid","aid"})
9
@Table
10
public class AnswerAgreeRec{
11

12
	private String uid;
13
	private String aid;
14
	private boolean flag;
15
	@Column(DE.text_de)
16
	public String getUid() {
17
		return uid;
18
	}
19
	public void setUid(String uid) {
20
		this.uid = uid;
21
	}
22
	@Column(DE.text_de)
23
	public String getAid() {
24
		return aid;
25
	}
26
	public void setAid(String aid) {
27
		this.aid = aid;
28
	}
29
	@Column(DE.boolean_de)
30
	public boolean isFlag() {
31
		return flag;
32
	}
33
	public void setFlag(boolean flag) {
34
		this.flag = flag;
35
	}
36
	
37
}

+ 29 - 0
src/main/java/com/ekexiu/portal/question/QetKeyWord.java

@ -0,0 +1,29 @@
1
package com.ekexiu.portal.question;
2

3
import org.jfw.apt.orm.annotation.entry.Column;
4
import org.jfw.apt.orm.annotation.entry.PrimaryKey;
5
import org.jfw.apt.orm.annotation.entry.Table;
6
import org.jfw.apt.orm.core.enums.DE;
7

8
@PrimaryKey({"id","kw"})
9
@Table
10
public class QetKeyWord {
11
	private String id;
12
	private String kw;
13
	@Column(DE.text_de)
14
	public String getId() {
15
		return id;
16
	}
17
	public void setId(String id) {
18
		this.id = id;
19
	}
20
	@Column(DE.text_de)
21
	public String getKw() {
22
		return kw;
23
	}
24
	public void setKw(String kw) {
25
		this.kw = kw;
26
	}
27
	
28
	
29
}

+ 153 - 0
src/main/java/com/ekexiu/portal/question/Question.java

@ -0,0 +1,153 @@
1
package com.ekexiu.portal.question;
2

3
import org.jfw.apt.orm.annotation.entry.Column;
4
import org.jfw.apt.orm.annotation.entry.PrimaryKey;
5
import org.jfw.apt.orm.annotation.entry.Table;
6
import org.jfw.apt.orm.core.defaultImpl.FixLenStringHandler;
7
import org.jfw.apt.orm.core.enums.DE;
8

9
import com.ekexiu.portal.basepo.ModifyTimeSupported;
10

11
@PrimaryKey("id")
12
@Table
13
public class Question implements ModifyTimeSupported{
14
	
15
	private String id;
16
	private String title;
17
	private String cnt;
18
	private String img;
19
	private String createTime;
20
	private String modifyTime;
21
	private String keys;
22
	private String uid;	
23
	private String lastReplyTime;
24
	private long replyCount;
25
	private String state;
26
	private long pageViews;
27
	private transient String timeDesc;
28
	
29
	
30
	@Column(DE.long_de)
31
	public long getPageViews() {
32
		return pageViews;
33
	}
34
	public void setPageViews(long pageViews) {
35
		this.pageViews = pageViews;
36
	}
37
	@Column(DE.text_de)
38
	public String getTimeDesc() {
39
		return timeDesc;
40
	}
41
	public void setTimeDesc(String timeDesc) {
42
		this.timeDesc = timeDesc;
43
	}
44
	/**
45
	 * ID
46
	 * @return
47
	 */
48
	@Column(DE.id_32)
49
	public String getId() {
50
		return id;
51
	}
52
	public void setId(String id) {
53
		this.id = id;
54
	}
55
	@Column(DE.text_de)
56
	public String getTitle() {
57
		return title;
58
	}
59
	public void setTitle(String title) {
60
		this.title = title;
61
	}
62
	/**
63
	 * 提问内容
64
	 * @return
65
	 */
66
	@Column(DE.Text_de)
67
	public String getCnt() {
68
		return cnt;
69
	}
70
	public void setCnt(String cnt) {
71
		this.cnt = cnt;
72
	}
73
	/**
74
	 * 图片 用英文豆号分隔
75
	 * @return
76
	 */
77
	@Column(DE.Text_de)
78
	public String getImg() {
79
		return img;
80
	}
81
	public void setImg(String img) {
82
		this.img = img;
83
	}
84
	@Column(DE.text_de)
85
	public String getCreateTime() {
86
		return createTime;
87
	}
88
	public void setCreateTime(String createTime) {
89
		this.createTime = createTime;
90
	}
91
	public String getModifyTime() {
92
		return modifyTime;
93
	}
94
	public void setModifyTime(String modifyTime) {
95
		this.modifyTime = modifyTime;
96
	}
97
	/**
98
	 * 关键词,以英文逗号分隔
99
	 * @return
100
	 */
101
	@Column(DE.text_de)
102
	public String getKeys() {
103
		return keys;
104
	}
105
	public void setKeys(String keys) {
106
		this.keys = keys;
107
	}
108
	/**
109
	 * 发布人ID
110
	 * @return
111
	 */
112
	@Column(DE.text_de)
113
	public String getUid() {
114
		return uid;
115
	}
116
	public void setUid(String uid) {
117
		this.uid = uid;
118
	}
119
	/**
120
	 * 最后回答时间
121
	 * @return
122
	 */
123
	@Column(handlerClass = FixLenStringHandler.class, dbType = "CHAR(14)", fixSqlValueWithUpdate = "TO_CHAR(NOW(),'YYYYMMDDHH24MISS')", insertable = false, nullable = true, queryable = true, renewable = true)
124
	public String getLastReplyTime() {
125
		return lastReplyTime;
126
	}
127
	public void setLastReplyTime(String lastReplyTime) {
128
		this.lastReplyTime = lastReplyTime;
129
	}
130
	/**
131
	 * 回答次数
132
	 * @return
133
	 */
134
	@Column(DE.long_de)
135
	public long getReplyCount() {
136
		return replyCount;
137
	}
138
	public void setReplyCount(long replyCount) {
139
		this.replyCount = replyCount;
140
	}
141
	/**
142
	 * 提问状态  1:发布中
143
	 * @return
144
	 */
145
	@Column(DE.singleChar)
146
	public String getState() {
147
		return state;
148
	}
149
	public void setState(String state) {
150
		this.state = state;
151
	}
152
	
153
}

+ 185 - 0
src/main/java/com/ekexiu/portal/question/QuestionDao.java

@ -0,0 +1,185 @@
1
package com.ekexiu.portal.question;
2

3
import java.sql.Connection;
4
import java.sql.SQLException;
5
import java.util.List;
6

7
import org.jfw.apt.annotation.DefaultValue;
8
import org.jfw.apt.annotation.Nullable;
9
import org.jfw.apt.orm.annotation.dao.Batch;
10
import org.jfw.apt.orm.annotation.dao.Column;
11
import org.jfw.apt.orm.annotation.dao.DAO;
12
import org.jfw.apt.orm.annotation.dao.method.From;
13
import org.jfw.apt.orm.annotation.dao.method.IncludeFixSet;
14
import org.jfw.apt.orm.annotation.dao.method.OrderBy;
15
import org.jfw.apt.orm.annotation.dao.method.SetSentence;
16
import org.jfw.apt.orm.annotation.dao.method.Where;
17
import org.jfw.apt.orm.annotation.dao.method.operator.DeleteWith;
18
import org.jfw.apt.orm.annotation.dao.method.operator.Insert;
19
import org.jfw.apt.orm.annotation.dao.method.operator.LimitQuery;
20
import org.jfw.apt.orm.annotation.dao.method.operator.LimitSelect;
21
import org.jfw.apt.orm.annotation.dao.method.operator.QueryVal;
22
import org.jfw.apt.orm.annotation.dao.method.operator.SelectList;
23
import org.jfw.apt.orm.annotation.dao.method.operator.SelectOne;
24
import org.jfw.apt.orm.annotation.dao.method.operator.UpdateWith;
25
import org.jfw.apt.orm.annotation.dao.param.In;
26
import org.jfw.apt.orm.annotation.dao.param.LessThan;
27
import org.jfw.apt.orm.annotation.dao.param.Set;
28
import org.jfw.apt.orm.annotation.dao.param.SqlColumn;
29
import org.jfw.apt.orm.core.defaultImpl.LongHandler;
30
import org.jfw.apt.orm.core.defaultImpl.StringHandler;
31

32

33
@DAO
34
public interface QuestionDao {
35

36
	@Insert
37
	int insert(Connection con, Question qen) throws SQLException;
38

39
	@DeleteWith
40
	@From(QetKeyWord.class)
41
	int deleteKeys(Connection con, String id) throws SQLException;
42
	
43
	
44
	@UpdateWith
45
	@From(Question.class)
46
	@IncludeFixSet
47
	@SetSentence("REPLY_COUNT=REPLY_COUNT+1")
48
	int incQuestionReply(Connection con,String id)throws SQLException;
49
	
50
	@UpdateWith
51
	@From(Question.class)
52
	@SetSentence("REPLY_COUNT=REPLY_COUNT+1")
53
	int onlyIncQuestionReply(Connection con,String id)throws SQLException;
54
	
55
	
56
	
57
	@UpdateWith
58
	@From(Question.class)
59
	@SetSentence("REPLY_COUNT=REPLY_COUNT-1")
60
	@Where("REPLY_COUNT >0")
61
	int decQuestionReply(Connection con,String id)throws SQLException;
62
	
63
	@UpdateWith
64
	@From(Question.class)
65
	@SetSentence("PAGE_VIEWS=PAGE_VIEWS+1")
66
	int incQuestionPageViews(Connection con,String id)throws SQLException;
67

68
	@Insert
69
	@Batch
70
	int[] insert(Connection con, QetKeyWord[] kws) throws SQLException;
71

72
	@LimitSelect
73
	@OrderBy("ORDER BY TIME_DESC DESC")
74
	List<Question> query(Connection con, @Nullable String state, @Nullable String uid, @LessThan String timeDesc, int rows) throws SQLException;
75

76
	@LimitSelect
77
	@OrderBy("ORDER BY TIME_DESC DESC")
78
	@Where(" STATE='1'")
79
	List<Question> watch(Connection con,
80
			@SqlColumn(handlerClass = StringHandler.class, value = {
81
					" ID IN (SELECT WATCH_OBJECT FROM WATCH WHERE WATCH_TYPE='8' AND PROFESSOR_ID=?)" }) String uid,
82
			@LessThan String timeDesc, int rows) throws SQLException;
83

84
	@SelectOne
85
	@Nullable
86
	Question query(Connection con, String id) throws SQLException;
87
	
88
	@UpdateWith
89
	@From(Answer.class)
90
	@SetSentence("STATE='0'")
91
	@Where("STATE ='1'")
92
	int logicDeleteAnswer(Connection con,String id,String qid)throws SQLException;
93
	
94
	@UpdateWith
95
	@From(Answer.class)
96
	@SetSentence("STATE='1'")
97
	@Where("STATE <>'1'")
98
	int unDeleteAnswer(Connection con,String id,String qid)throws SQLException;
99

100
	
101
	@SelectOne
102
	@Nullable
103
	Answer queryAnswer(Connection con,String id)throws SQLException;
104

105
	@SelectList
106
	List<Question> query(Connection con, @In String[] id) throws SQLException;
107
	
108
	@LimitSelect
109
	@OrderBy("ORDER BY TIME_DESC DESC")
110
	@Where("QID IN(SELECT ID FROM QUESTION WHERE STATE='1') AND STATE='1'")
111
	List<Answer> answer(Connection con,@LessThan String timeDesc, int rows) throws SQLException;
112

113
	@LimitSelect
114
	@OrderBy("ORDER BY TIME_DESC DESC")
115
	@Where("QID IN(SELECT ID FROM QUESTION WHERE STATE='1') AND STATE='1'")
116
	List<Answer> answerSelf(Connection con, String uid, @LessThan String timeDesc, int rows) throws SQLException;
117
	
118
	@SelectOne
119
	@Nullable
120
	Answer answer(Connection con,String uid,String qid)throws SQLException;
121

122
	@LimitSelect
123
	@OrderBy("ORDER BY TIME_DESC DESC")
124
	@Where("QID IN(SELECT ID FROM QUESTION WHERE STATE='1') AND STATE='1'")
125
	List<Answer> watchAnswer(Connection con,
126
			@SqlColumn(handlerClass = StringHandler.class, value = {
127
					" ID IN (SELECT WATCH_OBJECT FROM WATCH WHERE WATCH_TYPE='9' AND PROFESSOR_ID=?)" }) String uid,
128
			@LessThan String timeDesc, int rows) throws SQLException;
129

130
	@LimitSelect
131
	@Where("STATE='1'")
132
	@OrderBy("ORDER BY TIME_DESC DESC")
133
	List<Answer> byQes(Connection con, String qid, @LessThan String timeDesc, int rows) throws SQLException;
134
	@LimitQuery
135
	@OrderBy("ORDER BY SCORE_DESC DESC")
136
	@Where("STATE='1'")
137
	List<SortedAnswwer> byQesScore(Connection con, String qid, @SqlColumn(handlerClass = StringHandler.class, value = { "(case when ballot=0 then '00000'  else  TO_CHAR(10000 *AGREE / BALLOT,'00009') end  || ID) < ?  " })  String score, int rows) throws SQLException;
138

139
	@Insert
140
	int insert(Connection con,AnswerAgreeRec aar)throws SQLException;
141
	@UpdateWith
142
	@From(AnswerAgreeRec.class)
143
	@Where("FLAG<>'1'")
144
	@SetSentence("FLAG='1'")
145
	int agree(Connection con,String uid,String aid)throws SQLException;
146
	@UpdateWith
147
	@From(AnswerAgreeRec.class)
148
	@Where("FLAG='1'")
149
	@SetSentence("FLAG='0'")
150
	int unAgree(Connection con,String uid,String aid)throws SQLException;
151
	
152
	@UpdateWith
153
	@From(Answer.class)
154
	int update(Connection con,String id, @Set( " = AGREE +?" ) long agree,@Set("=BALLOT+?") long ballot)throws SQLException;
155
	
156
	
157
	@Insert
158
	int insert(Connection con, Answer answer) throws SQLException;
159

160
	@UpdateWith
161
	@From(Answer.class)
162
	@Where("STATE='1'")
163
	@SetSentence("MODIFY_TIME=TO_CHAR(NOW(),'YYYYMMDDHH24MISS')")
164
	int updateAnswer(Connection con, String id, @Set String cnt) throws SQLException;
165
	
166
	@Insert
167
	int insert(Connection con,QuestionInviteRec rec)throws SQLException;
168
	
169
	@SelectList
170
	List<QuestionInviteRec> queryInviteRec(Connection con,String qid,String uid,@In String[] pid)throws SQLException;
171
	
172
	@SelectOne
173
	@Nullable
174
	AnswerAgreeRec queryAswerAgreRec(Connection con,String uid,String aid)throws SQLException;
175
	
176
	@DeleteWith
177
	@From(AnswerAgreeRec.class)
178
	int deleteAnswerAgreeRec(Connection con,String uid,String aid,boolean flag)throws SQLException;
179
	
180
	@DefaultValue("0")
181
	@QueryVal
182
	@Column(value="COUNT(1)",handlerClass=LongHandler.class)
183
	@From(Answer.class)
184
	long answerCount(Connection con,@Nullable String uid,@Nullable String qid, @Nullable String state)throws SQLException;
185
}

+ 46 - 0
src/main/java/com/ekexiu/portal/question/QuestionInviteRec.java

@ -0,0 +1,46 @@
1
package com.ekexiu.portal.question;
2

3
import org.jfw.apt.orm.annotation.entry.Column;
4
import org.jfw.apt.orm.annotation.entry.PrimaryKey;
5
import org.jfw.apt.orm.annotation.entry.Table;
6
import org.jfw.apt.orm.core.enums.DE;
7

8
import com.ekexiu.portal.basepo.CreateTimeSupported;
9

10
@PrimaryKey({"uid","qid","pid"})
11
@Table
12
public class QuestionInviteRec implements CreateTimeSupported {
13

14
	private String uid;
15
	private String qid;
16
	private String pid;
17
	private String createTime;
18
	@Column(DE.text_de)
19
	public String getUid() {
20
		return uid;
21
	}
22
	public void setUid(String uid) {
23
		this.uid = uid;
24
	}
25
	@Column(DE.text_de)
26
	public String getQid() {
27
		return qid;
28
	}
29
	public void setQid(String qid) {
30
		this.qid = qid;
31
	}
32
	@Column(DE.text_de)
33
	public String getPid() {
34
		return pid;
35
	}
36
	public void setPid(String pid) {
37
		this.pid = pid;
38
	}
39
	public String getCreateTime() {
40
		return createTime;
41
	}
42
	public void setCreateTime(String createTime) {
43
		this.createTime = createTime;
44
	}
45
	
46
}

+ 826 - 0
src/main/java/com/ekexiu/portal/question/Service.java

@ -0,0 +1,826 @@
1
package com.ekexiu.portal.question;
2

3
import java.io.ByteArrayInputStream;
4
import java.io.File;
5
import java.io.FileInputStream;
6
import java.io.FileOutputStream;
7
import java.io.IOException;
8
import java.io.InputStream;
9
import java.io.OutputStream;
10
import java.sql.Connection;
11
import java.sql.PreparedStatement;
12
import java.sql.SQLException;
13
import java.util.ArrayList;
14
import java.util.LinkedList;
15
import java.util.List;
16
import java.util.Map;
17
import java.util.concurrent.atomic.AtomicInteger;
18

19
import org.jfw.apt.annotation.Autowrie;
20
import org.jfw.apt.annotation.DefaultValue;
21
import org.jfw.apt.annotation.Nullable;
22
import org.jfw.apt.web.annotation.Path;
23
import org.jfw.apt.web.annotation.operate.Get;
24
import org.jfw.apt.web.annotation.operate.Post;
25
import org.jfw.apt.web.annotation.param.AfterCommit;
26
import org.jfw.apt.web.annotation.param.FieldParam;
27
import org.jfw.apt.web.annotation.param.JdbcConn;
28
import org.jfw.apt.web.annotation.param.RequestParam;
29
import org.jfw.apt.web.annotation.param.Upload;
30
import org.jfw.util.DateUtil;
31
import org.jfw.util.JpgUtil;
32
import org.jfw.util.ListUtil;
33
import org.jfw.util.StringUtil;
34
import org.jfw.util.exception.JfwBaseException;
35
import org.jfw.util.io.IoUtil;
36
import org.jfw.util.jdbc.JdbcUtil;
37
import org.jfw.util.jdbc.PreparedStatementConfig;
38
import org.jfw.util.web.fileupload.Item;
39
import org.jfw.util.web.fileupload.UploadItemIterator;
40

41
import com.ekexiu.portal.notify.NotifyService;
42
import com.ekexiu.portal.notify.NotifyType;
43
import com.ekexiu.portal.util.SqlUtil;
44

45
@Path("/question")
46
public class Service {
47

48
	private static final AtomicInteger FN_IDX = new AtomicInteger(1);
49

50
	@Autowrie
51
	private QuestionDao questionDao;
52

53
	@Autowrie
54
	private NotifyService notifyService;
55

56
	private File imgPath;
57

58
	private int imgMaxWidth = 70;
59

60
	public int getImgMaxWidth() {
61
		return imgMaxWidth;
62
	}
63

64
	public void setImgMaxWidth(int imgMaxWidth) {
65
		this.imgMaxWidth = imgMaxWidth;
66
	}
67

68
	public NotifyService getNotifyService() {
69
		return notifyService;
70
	}
71

72
	public void setNotifyService(NotifyService notifyService) {
73
		this.notifyService = notifyService;
74
	}
75

76
	public File getImgPath() {
77
		return imgPath;
78
	}
79

80
	public void setImgPath(File imgPath) {
81
		this.imgPath = imgPath;
82
	}
83

84
	public QuestionDao getQuestionDao() {
85
		return questionDao;
86
	}
87

88
	public void setQuestionDao(QuestionDao questionDao) {
89
		this.questionDao = questionDao;
90
	}
91

92
	/**
93
	 * 上传文件
94
	 * 
95
	 * @param it
96
	 * @return
97
	 * @throws Exception
98
	 */
99
	@Path("/upload")
100
	@Post
101
	public List<UploadFile> upload(@Upload UploadItemIterator it) throws Exception {
102
		List<UploadFile> ret = new LinkedList<UploadFile>();
103
		try {
104
			while (it.hasNext()) {
105
				Item item = it.next();
106
				if (!item.isFormField()) {
107
					String name = normalizeFileName(item.getName());
108
					int index = name.lastIndexOf('.');
109
					String ext = index >= 0 ? name.substring(index + 1) : "";
110
					ext = ext.trim();
111
					long fileLen = 0;
112
					int len = 0;
113
					UploadFile uf = this.buildTargetFile(ext);
114
					uf.setName(name);
115
					File file = uf.getFn();
116
					ret.add(uf);
117
					byte[] buf = new byte[8092];
118
					OutputStream of = new FileOutputStream(file);
119
					try {
120
						InputStream in = item.getInputStream();
121
						try {
122
							while ((len = in.read(buf)) >= 0) {
123
								if (len > 0) {
124
									of.write(buf, 0, len);
125
									fileLen += len;
126
								}
127
							}
128
							uf.setSize(fileLen);
129
						} finally {
130
							in.close();
131
						}
132
					} finally {
133
						of.close();
134
					}
135
				}
136
			}
137
			return ret;
138
		} catch (Exception e) {
139
			this.remove(ret);
140
			throw e;
141
		} finally {
142
			if (it != null)
143
				it.clean();
144
		}
145
	}
146

147
	private void saveSmallImg(String imgs) throws IOException {
148
		if (imgs != null) {
149
			List<String> list = ListUtil.splitTrimExcludeEmpty(imgs, ',');
150
			if (list.size() > 0) {
151
				String oname = list.get(0);
152
				if (oname != null) {
153
					if (oname.startsWith("/")) {
154
						oname = oname.substring(1);
155
						int idx = oname.indexOf('.');
156
						if (idx > 0) {
157
							String dname = oname.substring(0, idx) + "_s.jpg";
158
							File dest = new File(this.imgPath, dname);
159
							if (dest.exists())
160
								return;
161
							File src = new File(this.imgPath, oname);
162
							if (src.exists()) {
163
								byte[] obs = IoUtil.readStream(new FileInputStream(src), true);
164
								obs = JpgUtil.read(obs);
165
								FileOutputStream out = new FileOutputStream(dest);
166
								try {
167
									JpgUtil.scalingZoom(new ByteArrayInputStream(obs), out, this.imgMaxWidth);
168
									out.flush();
169
								} finally {
170
									IoUtil.close(out);
171
								}
172
							}
173
						}
174
					}
175
				}
176
			}
177
		}
178
	}
179

180
	/**
181
	 * 新增一提问
182
	 * 
183
	 * @param con
184
	 * @param q
185
	 *            title 标题 ,cnt 描述 img 图片 以英文逗号分隔, keys 关键字 以英文逗号分隔 ,uid 用户ID
186
	 * @return
187
	 * @throws SQLException
188
	 * @throws IOException 
189
	 */
190
	@Path()
191
	@Post
192
	public String save(@JdbcConn(true) Connection con,
193
			@RequestParam(fields = { @FieldParam(value = "title", valueClass = String.class),
194
					@FieldParam(value = "cnt", valueClass = String.class, required = false),
195
					@FieldParam(value = "img", valueClass = String.class, required = false), @FieldParam(value = "keys", valueClass = String.class),
196
					@FieldParam(value = "uid", valueClass = String.class) }) Question q)
197
			throws SQLException, IOException {
198
		String id = StringUtil.buildUUID();
199
		q.setId(id);
200
		q.setReplyCount(0);
201
		q.setState("1");
202
		q.setPageViews(0);
203
		String time = DateUtil.formatDateTime(System.currentTimeMillis());
204
		q.setCreateTime(time);
205
		q.setTimeDesc(time + id);
206
		List<String> kws = ListUtil.splitTrimExcludeEmpty(q.getKeys(), ',');
207
		if (kws.isEmpty())
208
			throw new IllegalArgumentException("param keys invalid");
209
		this.saveSmallImg(q.getImg());
210
		questionDao.insert(con, q);
211
		questionDao.insert(con, build(id, kws));
212
		return id;
213
	}
214

215
	@Path("/pageViews")
216
	@Post
217
	public void incQuestionPageView(@JdbcConn(true) Connection con, String qid) throws SQLException {
218
		questionDao.incQuestionPageViews(con, qid);
219
	}
220

221
	/**
222
	 * 默认的邀请专家
223
	 * 
224
	 * @param con
225
	 * @param id
226
	 *            提问ID
227
	 * @param uid
228
	 *            本人ID
229
	 * @param count
230
	 *            limit 查询 返回最后一条的 kws ,首次不传
231
	 * @param pid
232
	 *            limit 查询 返回最后一条的 id 首次可不传
233
	 * @param rows
234
	 *            limit查询返回的最大数据条数
235
	 * @return
236
	 * @throws SQLException
237
	 */
238
	@Get
239
	@Path("/commendatoryPro")
240
	public List<Map<String, Object>> professor(@JdbcConn Connection con, final String id, final String uid, final @DefaultValue("Integer.MAX_VALUE") int count,
241
			final @DefaultValue("\"0\"") String pid, final @DefaultValue("Integer.MAX_VALUE") int rows) throws SQLException {
242
		return JdbcUtil.queryMaps(con,
243
				"select id, kws from(select id,count(1) kws from pro_key_word where id <> ? and kw in (select kw from qet_key_word where id =?) group by id ) t where kws<= ? and id >? order by kws desc,id asc limit ?",
244
				new PreparedStatementConfig() {
245
					@Override
246
					public void config(PreparedStatement ps) throws SQLException {
247
						ps.setString(1, uid);
248
						ps.setString(2, id);
249
						ps.setInt(3, count);
250
						ps.setString(4, pid);
251
						ps.setInt(5, rows);
252
					}
253
				});
254
	}
255

256
	/**
257
	 * 邀请专家回答提问
258
	 * 
259
	 * @param con
260
	 * @param qid
261
	 *            提问id
262
	 * @param pid
263
	 *            专家id(被邀请人)
264
	 * @param uid
265
	 *            操作人(邀请人
266
	 * @param uname
267
	 *            操作人(邀请人)姓名
268
	 * @return
269
	 * @throws SQLException
270
	 * @throws JfwBaseException
271
	 */
272
	@Post
273
	@Path("/invite")
274
	public boolean invite(@JdbcConn(true) Connection con, String qid, String pid, String uid, String uname, @AfterCommit List<Runnable> runs)
275
			throws SQLException, JfwBaseException {
276
		Question q = questionDao.query(con, qid);
277
		if (q == null) {
278
			throw new JfwBaseException(50000, "question[" + qid + "] not found");
279
		}
280
		QuestionInviteRec rec = new QuestionInviteRec();
281
		rec.setUid(uid);
282
		rec.setPid(pid);
283
		rec.setQid(qid);
284
		try {
285
			questionDao.insert(con, rec);
286
		} catch (SQLException e) {
287
			if (SqlUtil.unique(e)) {
288
				throw new JfwBaseException(50001, "duplicate invite");
289
			}
290
			throw e;
291
		}
292

293
		this.notifyService.notify(con, pid, uid, uname, qid, q.getTitle(), NotifyType.INVITE_ANSWER, runs);
294
		return true;
295
	}
296

297
	@Get
298
	@Path("/invite")
299
	public List<QuestionInviteRec> queryInviteRec(@JdbcConn Connection con, String uid, String qid, String[] pid) throws SQLException {
300
		return questionDao.queryInviteRec(con, qid, uid, pid);
301
	}
302

303
	/**
304
	 * 回答一个提问
305
	 * 
306
	 * @param con
307
	 * @param qid
308
	 *            提问ID
309
	 * @param cnt
310
	 *            回答内容
311
	 * @param uid
312
	 *            回答 人ID
313
	 * @param uname
314
	 *            回答人姓名
315
	 * @return
316
	 * @throws SQLException
317
	 * @throws JfwBaseException
318
	 */
319
	@Post
320
	@Path("/answer")
321
	public String answer(@JdbcConn(true) Connection con, String qid, String cnt, String uid, String uname, @AfterCommit List<Runnable> runs)
322
			throws SQLException, JfwBaseException {
323
		Question q = questionDao.query(con, qid);
324
		if (q == null) {
325
			throw new JfwBaseException(50000, "question[" + qid + "] not found");
326
		}
327
		String id = StringUtil.buildUUID();
328
		String time = DateUtil.formatDateTime(System.currentTimeMillis());
329
		Answer a = new Answer();
330
		a.setId(id);
331
		a.setAgree(0);
332
		a.setBallot(0);
333
		a.setCnt(cnt);
334
		a.setQid(qid);
335
		a.setState("1");
336
		a.setUid(uid);
337
		a.setCreateTime(time);
338
		a.setTimeDesc(time + id);
339
		a.setModifyTime(time);
340
		try {
341
			questionDao.insert(con, a);
342
		} catch (SQLException e) {
343
			if (SqlUtil.unique(e)) {
344
				throw new JfwBaseException(50001, "duplicate answer");
345
			}
346
			throw e;
347
		}
348
		questionDao.incQuestionReply(con, qid);
349
		notifyService.notify(con, q.getUid(), uid, uname,id+":"+qid, q.getTitle(), NotifyType.ANSWER_QUESTION, runs);
350
		return id;
351
	}
352

353
	@Get
354
	@Path("/answer")
355
	public Answer answer(@JdbcConn Connection con, @Nullable String id, @Nullable String uid, @Nullable String qid) throws SQLException {
356
		if (id != null) {
357
			return questionDao.queryAnswer(con, id);
358
		} else if (qid != null && uid != null) {
359
			return questionDao.answer(con, uid, qid);
360
		}
361
		return null;
362
	}
363

364
	@Get
365
	@Path("/answer/exists")
366
	public boolean existsAnswer(@JdbcConn Connection con, String uid, String qid) throws SQLException {
367
		return null != questionDao.answer(con, uid, qid);
368
	}
369

370
	/**
371
	 * 修改一个回答
372
	 * 
373
	 * @param con
374
	 * @param id
375
	 *            回答ID
376
	 * @param cnt
377
	 *            回答内容
378
	 * @param uid
379
	 *            用户ID
380
	 * @param uname
381
	 *            用户姓名
382
	 * @return
383
	 * @throws SQLException
384
	 */
385
	@Post
386
	@Path("/answer/modify")
387
	public int answerUpdate(@JdbcConn(true) Connection con, String id, String cnt, String uid, String uname) throws SQLException {
388
		return questionDao.updateAnswer(con, id, cnt);
389
	}
390

391
	@Get
392
	@Path("/qo")
393
	public Question queryOne(@JdbcConn Connection con, String id) throws SQLException {
394
		return questionDao.query(con, id);
395
	}
396

397
	@Get
398
	@Path("/qm")
399
	public List<Question> query(@JdbcConn Connection con, String[] ids) throws SQLException {
400
		return questionDao.query(con, ids);
401
	}
402

403
	/**
404
	 * 等您回答 1、只显示“发布中”的问题 按问题发布时间,由新到旧排序。
405
	 * 
406
	 * @param con
407
	 * @param time
408
	 *            limit查询最后一条的createTime 首次不传
409
	 * @param id
410
	 *            limit查询最后一条的id 首次不传
411
	 * @param rows
412
	 *            limit查询最后一条的最大返回条数
413
	 * @return
414
	 * @throws SQLException
415
	 */
416
	@Get
417
	@Path()
418
	public List<Question> query(@JdbcConn Connection con, @DefaultValue("\"99999999999999\"") String time, @DefaultValue("\"0\"") String id,
419
			@DefaultValue("10000000") int rows) throws SQLException {
420
		return questionDao.query(con, "1", null, time + id, rows);
421
	}
422

423
	/**
424
	 * 我提出的 1、只显示“发布中”的问题 按问题发布时间,由新到旧排序。
425
	 * 
426
	 * @param con
427
	 * @param uid
428
	 *            用户ID
429
	 * @param time
430
	 *            limit查询最后一条的createTime 首次不传
431
	 * @param id
432
	 *            limit查询最后一条的id 首次不传
433
	 * @param rows
434
	 *            limit查询最后一条的最大返回条数
435
	 * @return
436
	 * @throws SQLException
437
	 */
438
	@Get
439
	@Path("/my")
440
	public List<Question> querySelf(@JdbcConn Connection con, String uid, @DefaultValue("\"99999999999999\"") String time, @DefaultValue("\"0\"") String id,
441
			@DefaultValue("10000000") int rows) throws SQLException {
442
		return questionDao.query(con, "1", uid, time + id, rows);
443
	}
444
	
445
	@Get
446
	@Path("/answer/count")
447
	public long answerCount(@JdbcConn Connection con,@Nullable String qid,@Nullable String uid,@Nullable String state) throws SQLException{
448
		return questionDao.answerCount(con, uid, qid, state);
449
	}
450

451
	/**
452
	 * 我关注的 1、只显示“发布中”的问题 按问题发布时间,由新到旧排序。
453
	 * 
454
	 * @param con
455
	 * @param uid
456
	 *            用户ID
457
	 * @param time
458
	 *            limit查询最后一条的createTime 首次不传
459
	 * @param id
460
	 *            limit查询最后一条的id 首次不传
461
	 * @param rows
462
	 *            limit查询最后一条的最大返回条数
463
	 * @return
464
	 * @throws SQLException
465
	 */
466
	@Get
467
	@Path("/watch")
468
	public List<Question> watch(@JdbcConn Connection con, String uid, @DefaultValue("\"99999999999999\"") String time, @DefaultValue("\"0\"") String id,
469
			@DefaultValue("10000000") int rows) throws SQLException {
470
		return questionDao.watch(con, uid, time + id, rows);
471
	}
472

473
	/**
474
	 * 我回答的
475
	 * 
476
	 * @param con
477
	 * @param uid
478
	 *            用户ID
479
	 * @param time
480
	 *            limit查询最后一条的createTime 首次不传
481
	 * @param id
482
	 *            limit查询最后一条的id 首次不传
483
	 * @param rows
484
	 *            limit查询最后一条的最大返回条数
485
	 * @return
486
	 * @throws SQLException
487
	 */
488
	@Get
489
	@Path("/answer/bySelf")
490
	public List<Answer> answerSelf(@JdbcConn Connection con, String uid, @DefaultValue("\"99999999999999\"") String time, @DefaultValue("\"0\"") String id,
491
			@DefaultValue("10000000") int rows) throws SQLException {
492
		return questionDao.answerSelf(con, uid, time + id, rows);
493
	}
494

495
	/**
496
	 * 我关注的回答
497
	 * 
498
	 * @param con
499
	 * @param uid
500
	 *            用户ID
501
	 * @param time
502
	 *            limit查询最后一条的createTime 首次不传
503
	 * @param id
504
	 *            limit查询最后一条的id 首次不传
505
	 * @param rows
506
	 *            limit查询最后一条的最大返回条数
507
	 * @return
508
	 * @throws SQLException
509
	 */
510
	@Get
511
	@Path("/answer/byWatch")
512
	public List<Answer> answerWatch(@JdbcConn Connection con, String uid, @DefaultValue("\"99999999999999\"") String time, @DefaultValue("\"0\"") String id,
513
			@DefaultValue("10000000") int rows) throws SQLException {
514
		return questionDao.watchAnswer(con, uid, time + id, rows);
515
	}
516

517
	/**
518
	 * 查询所有合法的回答(“发布中”的问题下的“发布中”的回答。); 按最新回答时间,由新到旧排序 })
519
	 * 
520
	 * @param con
521
	 * @param time
522
	 * @param id
523
	 * @param rows
524
	 * @return
525
	 * @throws SQLException
526
	 */
527
	@Get
528
	@Path("/answer/byTime")
529
	public List<Answer> answerByTime(@JdbcConn Connection con, @DefaultValue("\"99999999999999\"") String time, @DefaultValue("\"0\"") String id,
530
			@DefaultValue("10000000") int rows) throws SQLException {
531
		return questionDao.answer(con, time + id, rows);
532
	}
533

534
	/**
535
	 * 指定提问的回答(按最新回答时间,由新到旧排序)
536
	 * 
537
	 * @param con
538
	 * @param qid
539
	 *            提问ID
540
	 * @param time
541
	 *            limit查询最后一条的createTime 首次不传
542
	 * @param id
543
	 *            limit查询最后一条的id 首次不传
544
	 * @param rows
545
	 *            limit查询最后一条的最大返回条数
546
	 * @return
547
	 * @throws SQLException
548
	 */
549
	@Get
550
	@Path("/answer/qes/byTime")
551
	public List<Answer> byQes(@JdbcConn Connection con, String qid, @DefaultValue("\"99999999999999\"") String time, @DefaultValue("\"0\"") String id,
552
			@DefaultValue("10000000") int rows) throws SQLException {
553
		return questionDao.byQes(con, qid, time + id, rows);
554
	}
555

556
	/**
557
	 * 指定提问的回答(按最新回答时间,由新到旧排序)
558
	 * 
559
	 * @param con
560
	 * @param qid
561
	 *            提问ID
562
	 * @param score
563
	 *            limit查询最后一条的score 首次不传
564
	 * @param id
565
	 *            limit查询最后一条的id 首次不传
566
	 * @param rows
567
	 *            limit查询最后一条的最大返回条数
568
	 * @return
569
	 * @throws SQLException
570
	 */
571
	@Get
572
	@Path("/answer/qes/byScore")
573
	public List<SortedAnswwer> byQes(@JdbcConn Connection con, String qid, @DefaultValue("99999") int score, @DefaultValue("\"Z\"") String id,
574
			@DefaultValue("10000000") int rows) throws SQLException {
575
		String p = "000000" + score;
576
		p = p.substring(p.length() - 5) + id;
577
		return questionDao.byQesScore(con, qid, p, rows);
578
	}
579

580
	/**
581
	 * 我的回答总点赞数
582
	 * 
583
	 * @param con
584
	 * @param id
585
	 *            用户ID
586
	 * @return
587
	 * @throws SQLException
588
	 */
589
	@Get
590
	@Path("/answer/my/agree/count")
591
	public int queryCountWithMyAnswer(@JdbcConn Connection con, final String id) throws SQLException {
592
		return JdbcUtil.queryInt(con, "SELECT SUM(AGREE) FROM ANSWER WHERE UID=?", new PreparedStatementConfig() {
593
			@Override
594
			public void config(PreparedStatement ps) throws SQLException {
595
				ps.setString(1, id);
596
			}
597
		}, 0);
598
	}
599

600
	@Post
601
	@Path("/answer/agree")
602
	public void agree(@JdbcConn(true) Connection con, String id, String uid, String uname, @AfterCommit List<Runnable> runs)
603
			throws SQLException, JfwBaseException {
604
		Answer a = questionDao.queryAnswer(con, id);
605
		if (a == null)
606
			throw new JfwBaseException(50000, "answer[" + id + "] not found");
607

608
		String qid = a.getQid();
609
		Question q = questionDao.query(con, qid);
610
		if (q == null)
611
			throw new JfwBaseException(50000, "answer[" + id + "] ' question  not found");
612

613
		AnswerAgreeRec aar = new AnswerAgreeRec();
614
		aar.setAid(id);
615
		aar.setUid(uid);
616
		aar.setFlag(true);
617
		boolean inserted = false;
618
		try {
619
			questionDao.insert(con, aar);
620
			inserted = true;
621
		} catch (SQLException e) {
622
			if (SqlUtil.unique(e)) {
623
				con.rollback();
624
			} else {
625
				throw e;
626
			}
627
		}
628
		if (inserted) {
629
			questionDao.update(con, id, 1, 1);
630
		} else {
631
			if (questionDao.agree(con, uid, id) > 0) {
632
				questionDao.update(con, id, 1, 0);
633
			} else {
634
				throw new JfwBaseException(50001, "duplicate answer agree");
635
			}
636
		}
637
		notifyService.notify(con, a.getUid(), uid, uname, a.getId()+":"+qid, q.getTitle(), NotifyType.ACCEPT_ANSWER, runs);
638
	}
639
	
640
	
641
	@Post
642
	@Path("/answer/agree/cancle")
643
	public int unAgree(@JdbcConn(true) Connection con, String id, String uid, String uname)
644
			throws SQLException, JfwBaseException {
645
		Answer a = questionDao.queryAnswer(con, id);
646
		if (a == null)
647
			throw new JfwBaseException(50000, "answer[" + id + "] not found");
648

649
		
650
		if(questionDao.deleteAnswerAgreeRec(con, uid, id, true)>0){
651
			questionDao.update(con, id, -1, -1);
652
			return 1;
653
		}
654
		return 0;
655
	}
656
	@Post
657
	@Path("/answer/oppose/cancle")
658
	public int unOpp(@JdbcConn(true) Connection con, String id, String uid, String uname)
659
			throws SQLException, JfwBaseException {
660
		Answer a = questionDao.queryAnswer(con, id);
661
		if (a == null)
662
			throw new JfwBaseException(50000, "answer[" + id + "] not found");
663
		if(questionDao.deleteAnswerAgreeRec(con, uid, id, false)>0){
664
			questionDao.update(con, id, 0, -1);
665
			return 1;
666
		}
667
		return 0;
668
	}
669
	
670
	
671

672
	@Get
673
	@Path("/answer/agree")
674
	public AnswerAgreeRec isAgree(@JdbcConn Connection con, String aid, String uid) throws SQLException {
675
		return questionDao.queryAswerAgreRec(con, uid, aid);
676
	}
677

678
	@Get
679
	@Path("/answer/delete")
680
	public int logicDelete(@JdbcConn(true) Connection con, String id, String qid) throws SQLException {
681
		if (questionDao.logicDeleteAnswer(con, id, qid) > 0) {
682
			questionDao.decQuestionReply(con, qid);
683
			return 1;
684
		}
685
		return 0;
686
	}
687

688
	@Get
689
	@Path("/answer/unDel")
690
	public int unDelete(@JdbcConn(true) Connection con, String id, String qid) throws SQLException {
691
		if (questionDao.unDeleteAnswer(con, id, qid) > 0) {
692
			questionDao.onlyIncQuestionReply(con, qid);
693
			return 1;
694
		}
695
		return 0;
696
	}
697

698
	@Post
699
	@Path("/answer/oppose")
700
	public void oppose(@JdbcConn(true) Connection con, String id, String uid, String uname)
701
			throws SQLException, JfwBaseException {
702
		AnswerAgreeRec aar = new AnswerAgreeRec();
703
		aar.setAid(id);
704
		aar.setUid(uid);
705
		aar.setFlag(false);
706
		boolean inserted = false;
707
		try {
708
			questionDao.insert(con, aar);
709
			inserted = true;
710
		} catch (SQLException e) {
711
			if (SqlUtil.unique(e)) {
712
				con.rollback();
713
			} else {
714
				throw e;
715
			}
716
		}
717
		if (inserted) {
718
			questionDao.update(con, id, 0, 1);
719
		} else {
720
			if (questionDao.unAgree(con, uid, id) > 0) {
721
				questionDao.update(con, id, -1, 0);
722
			} else {
723
				throw new JfwBaseException(50001, "duplicate answer oppose");
724
			}
725
		}
726
	}
727

728
	public QetKeyWord[] build(String id, List<String> ss) {
729
		List<QetKeyWord> qKws = new ArrayList<>(ss.size());
730
		for (String s : ss) {
731
			QetKeyWord kw = new QetKeyWord();
732
			kw.setId(id);
733
			kw.setKw(s);
734
			qKws.add(kw);
735
		}
736
		return qKws.toArray(new QetKeyWord[qKws.size()]);
737
	}
738

739
	private void remove(List<UploadFile> list) {
740
		for (UploadFile file : list) {
741
			if (file.fn != null)
742
				file.fn.delete();
743
		}
744
	}
745

746
	private UploadFile buildTargetFile(String ext) {
747
		StringBuilder sb = new StringBuilder();
748
		sb.append(System.currentTimeMillis() / (1000 * 60 * 60 * 24));
749
		File path = new File(this.imgPath, sb.toString());
750
		if (!path.exists()) {
751
			synchronized (this) {
752
				if (!path.mkdirs())
753
					throw new RuntimeException("mkdir error[" + path + "]");
754
				FN_IDX.set(1);
755
			}
756
		}
757
		File file;
758
		do {
759
			String fn = FN_IDX.toString();
760
			if (ext.isEmpty()) {
761
				file = new File(path, fn);
762
			} else {
763
				file = new File(path, fn + "." + ext);
764
			}
765
			FN_IDX.incrementAndGet();
766
		} while (file.exists());
767
		sb.append("/").append(file.getName());
768
		UploadFile uf = new UploadFile();
769
		uf.setFn(file);
770
		uf.setUri("/" + sb.toString());
771
		return uf;
772
	}
773

774
	private String normalizeFileName(String fn) {
775
		int index = fn.indexOf('\\');
776
		if (index >= 0) {
777
			fn = fn.substring(fn.lastIndexOf('\\') + 1);
778
		}
779
		index = fn.indexOf('/');
780
		if (index >= 0) {
781
			fn = fn.substring(fn.lastIndexOf('/') + 1);
782
		}
783
		if (fn.length() == 0)
784
			throw new RuntimeException("invalid filename in Multipart/data request");
785
		return fn;
786
	}
787

788
	public static class UploadFile {
789
		private String name;
790
		private String uri;
791
		private long size;
792
		private transient File fn;
793

794
		public File getFn() {
795
			return fn;
796
		}
797

798
		public void setFn(File fn) {
799
			this.fn = fn;
800
		}
801

802
		public String getName() {
803
			return name;
804
		}
805

806
		public void setName(String name) {
807
			this.name = name;
808
		}
809

810
		public String getUri() {
811
			return uri;
812
		}
813

814
		public void setUri(String uri) {
815
			this.uri = uri;
816
		}
817

818
		public long getSize() {
819
			return size;
820
		}
821

822
		public void setSize(long size) {
823
			this.size = size;
824
		}
825
	}
826
}

+ 32 - 0
src/main/java/com/ekexiu/portal/question/SortedAnswwer.java

@ -0,0 +1,32 @@
1
package com.ekexiu.portal.question;
2

3
import org.jfw.apt.orm.annotation.entry.CalcColumn;
4
import org.jfw.apt.orm.annotation.entry.ExtendTable;
5
import org.jfw.apt.orm.core.defaultImpl.LongHandler;
6
import org.jfw.apt.orm.core.defaultImpl.StringHandler;
7

8
@ExtendTable
9
public class SortedAnswwer extends Answer {
10
	private long score ;
11
	private transient String scoreDesc;
12
	
13
	
14
	@CalcColumn(nullable=false,handlerClass=StringHandler.class,column=" case when ballot=0 then '00000' else  TO_CHAR(10000 *AGREE / BALLOT,'00009') end  || ID SCORE_DESC")
15
	public String getScoreDesc() {
16
		return scoreDesc;
17
	}
18

19
	public void setScoreDesc(String scoreDesc) {
20
		this.scoreDesc = scoreDesc;
21
	}
22

23
	@CalcColumn(nullable=false,handlerClass=LongHandler.class,column="case when ballot=0 then 0 else  10000 *AGREE / BALLOT end SCORE")
24
	public long getScore() {
25
		return score;
26
	}
27

28
	public void setScore(long score) {
29
		this.score = score;
30
	}
31
   
32
}

+ 24 - 1
src/main/java/com/ekexiu/portal/service/ArticleService.java

@ -20,11 +20,13 @@ import org.jfw.apt.annotation.Nullable;
20 20
import org.jfw.apt.web.annotation.Path;
21 21
import org.jfw.apt.web.annotation.operate.Get;
22 22
import org.jfw.apt.web.annotation.operate.Post;
23
import org.jfw.apt.web.annotation.param.AfterCommit;
23 24
import org.jfw.apt.web.annotation.param.JdbcConn;
24 25
import org.jfw.util.DateUtil;
25 26
import org.jfw.util.JpgUtil;
26 27
import org.jfw.util.PageQueryResult;
27 28
import org.jfw.util.StringUtil;
29
import org.jfw.util.codec.JfwInvalidCodecKeyException;
28 30
import org.jfw.util.exception.JfwBaseException;
29 31
import org.jfw.util.io.IoUtil;
30 32

@ -41,6 +43,8 @@ import com.ekexiu.portal.dao.ProfessorDao;
41 43
import com.ekexiu.portal.dao.ResearchAreaDao;
42 44
import com.ekexiu.portal.dao.ResourceDao;
43 45
import com.ekexiu.portal.dao.WatchDao;
46
import com.ekexiu.portal.notify.NotifyService;
47
import com.ekexiu.portal.notify.NotifyType;
44 48
import com.ekexiu.portal.po.Article;
45 49
import com.ekexiu.portal.po.ArticleAgree;
46 50
import com.ekexiu.portal.po.ArticleOrg;
@ -95,6 +99,18 @@ public class ArticleService {
95 99

96 100
	@Autowrie
97 101
	private TemplateService templateService;
102
	
103
	@Autowrie
104
	private NotifyService notifyService;
105
	
106

107
	public NotifyService getNotifyService() {
108
		return notifyService;
109
	}
110

111
	public void setNotifyService(NotifyService notifyService) {
112
		this.notifyService = notifyService;
113
	}
98 114

99 115
	public TemplateService getTemplateService() {
100 116
		return templateService;
@ -747,12 +763,19 @@ public class ArticleService {
747 763

748 764
	@Post
749 765
	@Path("/agree")
750
	public void agree(@JdbcConn(true) Connection con, String operateId, String articleId) throws SQLException {
766
	public void agree(@JdbcConn(true) Connection con, String operateId, String articleId,String uname,@AfterCommit List<Runnable> runs) throws SQLException {
767
		final Article article = this.articleDao.queryOne(con, articleId);
768
		if(article==null){
769
			throw new IllegalArgumentException("not found article["+articleId+ "]");
770
		}
751 771
		if (this.articleDao.incAgree(con, articleId) > 0) {
752 772
			ArticleAgree articleAgree = new ArticleAgree();
753 773
			articleAgree.setOperateId(operateId);
754 774
			articleAgree.setArticleId(articleId);
755 775
			this.articleAgreeDao.insert(con, articleAgree);
776
			if(article.getArticleType().equals("1")){
777
				this.notifyService.notify(con, article.getProfessorId(), operateId, uname, articleId, article.getArticleTitle(), NotifyType.AGREE_ARTICLE, runs);
778
			}
756 779
		}
757 780
	}
758 781


+ 25 - 2
src/main/java/com/ekexiu/portal/service/FeedbackService.java

@ -125,8 +125,31 @@ public class FeedbackService {
125 125
		fb.setState("0");
126 126
		fb.setContent(cnt);
127 127
		fb.setUserId(user);
128
		fb.setSchema(7);
129
		return this.feedbackDao.insert(con, fb);
130
	}
131
	@Post
132
	@Path("/error/question")
133
	public long errorQuestion(@JdbcConn(true) Connection con,String cnt,String id,@Nullable String user)throws SQLException{
134
		Feedback fb = new Feedback();
135
		fb.setCategory(1);
136
		fb.setParam(id);
137
		fb.setState("0");
138
		fb.setContent(cnt);
139
		fb.setUserId(user);
140
		fb.setSchema(8);
141
		return this.feedbackDao.insert(con, fb);
142
	}
143
	@Post
144
	@Path("/error/answer")
145
	public long errorAnswer(@JdbcConn(true) Connection con,String cnt,String id,@Nullable String user)throws SQLException{
146
		Feedback fb = new Feedback();
147
		fb.setCategory(1);
148
		fb.setParam(id);
149
		fb.setState("0");
150
		fb.setContent(cnt);
151
		fb.setUserId(user);
152
		fb.setSchema(9);
128 153
		return this.feedbackDao.insert(con, fb);
129 154
	}
130
	
131
	
132 155
}

+ 60 - 33
src/main/java/com/ekexiu/portal/service/PpaperService.java

@ -11,12 +11,16 @@ import org.jfw.apt.annotation.Nullable;
11 11
import org.jfw.apt.web.annotation.Path;
12 12
import org.jfw.apt.web.annotation.operate.Get;
13 13
import org.jfw.apt.web.annotation.operate.Post;
14
import org.jfw.apt.web.annotation.param.AfterCommit;
14 15
import org.jfw.apt.web.annotation.param.JdbcConn;
15 16
import org.jfw.util.PageQueryResult;
17
import org.jfw.util.exception.JfwBaseException;
16 18

17 19
import com.ekexiu.portal.dao.PaperAgreeDao;
18 20
import com.ekexiu.portal.dao.PaperAuthorDao;
19 21
import com.ekexiu.portal.dao.PpaperDao;
22
import com.ekexiu.portal.notify.NotifyService;
23
import com.ekexiu.portal.notify.NotifyType;
20 24
import com.ekexiu.portal.po.PaperAgree;
21 25
import com.ekexiu.portal.po.PaperAuthor;
22 26
import com.ekexiu.portal.po.Ppaper;
@ -29,15 +33,23 @@ public class PpaperService {
29 33
	private PpaperDao ppaperDao;
30 34
	@Autowrie
31 35
	private PaperAuthorDao paperAuthorDao;
32
	
36

33 37
	@Autowrie
34 38
	private KeyWordService keyWordService;
35
	
39

36 40
	@Autowrie
37 41
	private PaperAgreeDao paperAgreeDao;
38
	
39
	
40
	
42

43
	@Autowrie
44
	private NotifyService notifyService;
45

46
	public NotifyService getNotifyService() {
47
		return notifyService;
48
	}
49

50
	public void setNotifyService(NotifyService notifyService) {
51
		this.notifyService = notifyService;
52
	}
41 53

42 54
	public PaperAgreeDao getPaperAgreeDao() {
43 55
		return paperAgreeDao;
@ -164,57 +176,72 @@ public class PpaperService {
164 176
	@Path("/kw")
165 177
	public void update(@JdbcConn(true) Connection con, String id, @Nullable String keywords) throws SQLException {
166 178
		this.ppaperDao.update(con, id, keywords);
167
		this.keyWordService.refreshPaper(con, id, KeyWordService.splitKeyWord(keywords));		
179
		this.keyWordService.refreshPaper(con, id, KeyWordService.splitKeyWord(keywords));
168 180
	}
169 181

170 182
	@Get
171 183
	@Path("/byShareId")
172
	public Ppaper query(@JdbcConn Connection con,long id) throws SQLException{
173
		return this.ppaperDao.query(con,id);
184
	public Ppaper query(@JdbcConn Connection con, long id) throws SQLException {
185
		return this.ppaperDao.query(con, id);
174 186
	}
187

175 188
	@Get
176 189
	@Path("/ralatePapers")
177
	public List<Ppaper> ralatePapers(@JdbcConn Connection con,String paperId,@DefaultValue("5") int rows)throws SQLException{
190
	public List<Ppaper> ralatePapers(@JdbcConn Connection con, String paperId, @DefaultValue("5") int rows) throws SQLException {
178 191
		String[] ids = this.ppaperDao.queryPaperIdWithSameKeyWord(con, paperId, rows);
179
		if(ids!=null){
180
			return this.ppaperDao.query(con,ids);
192
		if (ids != null) {
193
			return this.ppaperDao.query(con, ids);
181 194
		}
182
		return Collections.<Ppaper>emptyList();
195
		return Collections.<Ppaper> emptyList();
183 196
	}
184
	
185
	
197

186 198
	@Post
187 199
	@Path("/agree")
188
	public void agree(@JdbcConn(true) Connection con,String id,String uid)throws SQLException{
200
	public void agree(@JdbcConn(true) Connection con, String id, String uid, String uname, @AfterCommit List<Runnable> runs) throws SQLException, JfwBaseException {
201
		Ppaper p = this.ppaperDao.query(con, id);
202
		if (p == null) {
203
			throw new JfwBaseException(50000, "paper[" + id + "] not found");
204
		}
189 205
		PaperAgree pa = new PaperAgree();
190 206
		pa.setOpId(uid);
191 207
		pa.setPaperId(id);
192
		this.paperAgreeDao.insert(con, pa);		
193
	}
194
	
195
//	@Post
196
//	@Path("/unAgree")
197
//	public void unAgree(@JdbcConn(true) Connection con,String id,String uid)throws SQLException{
198
//		this.paperAgreeDao.delete(con,uid, id);
199
//	}
200
	
208
		this.paperAgreeDao.insert(con, pa);
209

210
		List<PaperAuthor> pas = this.paperAuthorDao.query(con, id);
211
		for (PaperAuthor au : pas) {
212
			if (!au.getProfessorId().startsWith("#")) {
213
				this.notifyService.notify(con, au.getProfessorId(), uid, uname, id, p.getName(), NotifyType.AGREE_PAPER, runs);
214
			}
215
		}
216
	}
217

218
	// @Post
219
	// @Path("/unAgree")
220
	// public void unAgree(@JdbcConn(true) Connection con,String id,String
221
	// uid)throws SQLException{
222
	// this.paperAgreeDao.delete(con,uid, id);
223
	// }
224

201 225
	@Get
202 226
	@Path("/agree")
203
	public boolean hasAgree(@JdbcConn(false) Connection con,String id,String uid)throws SQLException{
204
		return null!= this.paperAgreeDao.query(con,uid, id);
227
	public boolean hasAgree(@JdbcConn(false) Connection con, String id, String uid) throws SQLException {
228
		return null != this.paperAgreeDao.query(con, uid, id);
205 229
	}
230

206 231
	@Get
207 232
	@Path("/agreeCount")
208
	public int agreeCount(@JdbcConn(false) Connection con,String id)throws SQLException{
209
		return this.paperAgreeDao.query(con,id);
233
	public int agreeCount(@JdbcConn(false) Connection con, String id) throws SQLException {
234
		return this.paperAgreeDao.query(con, id);
210 235
	}
211
	
236

212 237
	@Get
213 238
	@Path("/assPapers")
214
	public List<Ppaper> assPapers(@JdbcConn Connection con,String[] kws,@DefaultValue("5") int rows) throws SQLException{
215
		if(kws==null || kws.length==0) return Collections.<Ppaper>emptyList();		
239
	public List<Ppaper> assPapers(@JdbcConn Connection con, String[] kws, @DefaultValue("5") int rows) throws SQLException {
240
		if (kws == null || kws.length == 0)
241
			return Collections.<Ppaper> emptyList();
216 242
		String[] ids = this.ppaperDao.queryPatentIdWithKeyWord(con, kws, rows);
217
		if(ids==null || ids.length==0) return Collections.<Ppaper>emptyList();
218
		return this.ppaperDao.query(con, ids);		
243
		if (ids == null || ids.length == 0)
244
			return Collections.<Ppaper> emptyList();
245
		return this.ppaperDao.query(con, ids);
219 246
	}
220 247
}

+ 26 - 1
src/main/java/com/ekexiu/portal/service/PpatentServcie.java

@ -11,12 +11,16 @@ import org.jfw.apt.annotation.Nullable;
11 11
import org.jfw.apt.web.annotation.Path;
12 12
import org.jfw.apt.web.annotation.operate.Get;
13 13
import org.jfw.apt.web.annotation.operate.Post;
14
import org.jfw.apt.web.annotation.param.AfterCommit;
14 15
import org.jfw.apt.web.annotation.param.JdbcConn;
15 16
import org.jfw.util.PageQueryResult;
17
import org.jfw.util.exception.JfwBaseException;
16 18

17 19
import com.ekexiu.portal.dao.PatentAgreeDao;
18 20
import com.ekexiu.portal.dao.PatentAuthorDao;
19 21
import com.ekexiu.portal.dao.PpatentDao;
22
import com.ekexiu.portal.notify.NotifyService;
23
import com.ekexiu.portal.notify.NotifyType;
20 24
import com.ekexiu.portal.po.PatentAgree;
21 25
import com.ekexiu.portal.po.PatentAuthor;
22 26
import com.ekexiu.portal.po.Ppatent;
@ -36,8 +40,19 @@ public class PpatentServcie {
36 40
	@Autowrie
37 41
	private PatentAgreeDao patentAgreeDao;
38 42
	
43
	@Autowrie
44
	private NotifyService notifyService;
45
	
39 46
	
40 47

48
	public NotifyService getNotifyService() {
49
		return notifyService;
50
	}
51

52
	public void setNotifyService(NotifyService notifyService) {
53
		this.notifyService = notifyService;
54
	}
55

41 56
	public PatentAgreeDao getPatentAgreeDao() {
42 57
		return patentAgreeDao;
43 58
	}
@ -178,11 +193,21 @@ public class PpatentServcie {
178 193
	
179 194
	@Post
180 195
	@Path("/agree")
181
	public void agree(@JdbcConn(true) Connection con,String id,String uid)throws SQLException{
196
	public void agree(@JdbcConn(true) Connection con,String id,String uid,String uname,@AfterCommit List<Runnable> runs)throws SQLException, JfwBaseException{
197
		Ppatent p = ppatentDao.query(con, id);
198
		if(p==null){
199
			throw new JfwBaseException(50000, "patent["+id+"] not found");
200
		}
182 201
		PatentAgree pa = new PatentAgree();
183 202
		pa.setOpId(uid);
184 203
		pa.setPatentId(id);
185 204
		this.patentAgreeDao.insert(con, pa);		
205
		List<PatentAuthor> authors = this.patentAuthorDao.query(con,id);
206
		for(PatentAuthor pau:authors){
207
			if(!pau.getProfessorId().startsWith("#")){
208
				this.notifyService.notify(con,pau.getProfessorId(), uid, uname, id,p.getName(), NotifyType.AGREE_PATENT, runs);
209
			}
210
		}
186 211
	}
187 212
	
188 213
//	@Post

+ 21 - 4
src/main/java/com/ekexiu/portal/service/ProfessorService.java

@ -28,6 +28,7 @@ import org.jfw.apt.web.annotation.param.RequestBody;
28 28
import org.jfw.util.PageQueryResult;
29 29
import org.jfw.util.StringUtil;
30 30
import org.jfw.util.jdbc.JdbcUtil;
31
import org.jfw.util.jdbc.PreparedStatementConfig;
31 32

32 33
import com.ekexiu.portal.dao.ArticleDao;
33 34
import com.ekexiu.portal.dao.DemandDao;
@ -726,8 +727,8 @@ public class ProfessorService {
726 727

727 728
	@Get
728 729
	@Path("/pqBaseInfo")
729
	PageQueryResult<EditProfessor> queryEditBaseInfo(@JdbcConn(false) Connection con, @Nullable String key, @Nullable String subject, @Nullable String industry,
730
			@Nullable String address, @DefaultValue("1") Integer authType, @DefaultValue("10") int pageSize, @DefaultValue("1") int pageNo)
730
	public PageQueryResult<EditProfessor> queryEditBaseInfo(@JdbcConn(false) Connection con, @Nullable String key, @Nullable String subject,
731
			@Nullable String industry, @Nullable String address, @Nullable Integer authType, @DefaultValue("10") int pageSize, @DefaultValue("1") int pageNo)
731 732
			throws SQLException {
732 733
		if (key != null) {
733 734
			key = "%" + key + "%";
@ -756,7 +757,7 @@ public class ProfessorService {
756 757

757 758
	@Get
758 759
	@Path("/pqUserInfo")
759
	PageQueryResult<UserInfo> queryUserInfo(@JdbcConn(false) Connection con, @Nullable String key, @Nullable String address, @Nullable String orgName,
760
	public PageQueryResult<UserInfo> queryUserInfo(@JdbcConn(false) Connection con, @Nullable String key, @Nullable String address, @Nullable String orgName,
760 761
			@Nullable Integer activeState, @Nullable Integer authType, @DefaultValue("20") int pageSize, @DefaultValue("1") int pageNo) throws SQLException {
761 762
		if (key != null) {
762 763
			key = "%" + key + "%";
@ -772,7 +773,7 @@ public class ProfessorService {
772 773

773 774
	@Get
774 775
	@Path("/pq")
775
	PageQueryResult<Professor> query(@JdbcConn(false) Connection con, @Nullable String key, @Nullable String subject, @Nullable String industry,
776
	public PageQueryResult<Professor> query(@JdbcConn(false) Connection con, @Nullable String key, @Nullable String subject, @Nullable String industry,
776 777
			@Nullable String address, @DefaultValue("10") int pageSize, @DefaultValue("1") int pageNo) throws SQLException {
777 778
		// System.out.println("key==["+(key==null?"":key)+"]");
778 779
		// System.out.println("subject==["+(subject==null?"":subject)+"]");
@ -788,6 +789,22 @@ public class ProfessorService {
788 789
		return this.professorDao.query(con, key, subject, industry, address, pageSize, pageNo);
789 790
	}
790 791

792
	@Get
793
	@Path("/agree/sum")
794
	public long agreeSum(@JdbcConn Connection con, final String id) throws SQLException {
795
		return JdbcUtil.queryLong(con,
796
				" select SUM(agree) from (SELECT article_agree agree FROM ARTICLE WHERE STATUS ='1' AND professor_id =? UNION ALL SELECT AGREE FROM ANSWER WHERE STATE='1' AND UID =? ) t",
797
				new PreparedStatementConfig() {
798
					@Override
799
					public void config(PreparedStatement ps) throws SQLException {
800
						ps.setString(1, id);
801
						ps.setString(2, id);
802

803
					}
804
				}, 0);
805

806
	}
807

791 808
	@Get
792 809
	@Path("/editInfo/{id}")
793 810
	public ProfessorInfo editInfo(@JdbcConn(false) Connection con, @PathVar String id) throws SQLException {

+ 17 - 1
src/main/java/com/ekexiu/portal/service/ResearchAreaService.java

@ -10,12 +10,15 @@ import org.jfw.apt.web.annotation.operate.Delete;
10 10
import org.jfw.apt.web.annotation.operate.Get;
11 11
import org.jfw.apt.web.annotation.operate.Post;
12 12
import org.jfw.apt.web.annotation.operate.Put;
13
import org.jfw.apt.web.annotation.param.AfterCommit;
13 14
import org.jfw.apt.web.annotation.param.JdbcConn;
14 15
import org.jfw.apt.web.annotation.param.PathVar;
15 16
import org.jfw.apt.web.annotation.param.RequestBody;
16 17
17 18
import com.ekexiu.portal.dao.ResearchAreaDao;
18 19
import com.ekexiu.portal.dao.ResearchAreaLogDao;
20
import com.ekexiu.portal.notify.NotifyService;
21
import com.ekexiu.portal.notify.NotifyType;
19 22
import com.ekexiu.portal.po.ResearchArea;
20 23
import com.ekexiu.portal.po.ResearchAreaLog;
21 24
@ -27,6 +30,18 @@ public class ResearchAreaService {
27 30
	@Autowrie
28 31
	private ResearchAreaLogDao researchAreaLogDao;
29 32
33
	@Autowrie
34
	private NotifyService notifyService;
35
	
36
	
37
	public NotifyService getNotifyService() {
38
		return notifyService;
39
	}
40
41
	public void setNotifyService(NotifyService notifyService) {
42
		this.notifyService = notifyService;
43
	}
44
30 45
	public ResearchAreaDao getResearchAreaDao() {
31 46
		return researchAreaDao;
32 47
	}
@ -51,7 +66,7 @@ public class ResearchAreaService {
51 66
52 67
	@Post
53 68
	@Path("/agree")
54
	public void agree(@JdbcConn(true) Connection con, String targetId, String targetCaption, String opId) throws SQLException {
69
	public void agree(@JdbcConn(true) Connection con, String targetId, String targetCaption, String opId,String uname,@AfterCommit List<Runnable> runs) throws SQLException {
55 70
56 71
		if (this.researchAreaDao.inc(con, targetId, targetCaption) > 0) {
57 72
			ResearchAreaLog log = new ResearchAreaLog();
@ -59,6 +74,7 @@ public class ResearchAreaService {
59 74
			log.setOpreteProfessorId(opId);
60 75
			log.setProfessorId(targetId);
61 76
			this.researchAreaLogDao.insert(con, log);
77
			this.notifyService.notify(con, targetId, opId, uname, targetId, targetCaption,NotifyType.AGREE_RESEARCH_AREA, runs);
62 78
		}
63 79
	}
64 80

+ 61 - 27
src/main/java/com/ekexiu/portal/service/WatchService.java

@ -9,6 +9,7 @@ import org.jfw.apt.annotation.DefaultValue;
9 9
import org.jfw.apt.web.annotation.Path;
10 10
import org.jfw.apt.web.annotation.operate.Get;
11 11
import org.jfw.apt.web.annotation.operate.Post;
12
import org.jfw.apt.web.annotation.param.AfterCommit;
12 13
import org.jfw.apt.web.annotation.param.JdbcConn;
13 14
import org.jfw.util.PageQueryResult;
14 15

@ -19,6 +20,8 @@ import com.ekexiu.portal.dao.ProfessorDao;
19 20
import com.ekexiu.portal.dao.ResearchAreaDao;
20 21
import com.ekexiu.portal.dao.ResourceDao;
21 22
import com.ekexiu.portal.dao.WatchDao;
23
import com.ekexiu.portal.notify.NotifyService;
24
import com.ekexiu.portal.notify.NotifyType;
22 25
import com.ekexiu.portal.po.Article;
23 26
import com.ekexiu.portal.po.Resource;
24 27
import com.ekexiu.portal.po.Watch;
@ -26,6 +29,7 @@ import com.ekexiu.portal.pojo.EditProfessor;
26 29

27 30
@Path("/watch")
28 31
public class WatchService {
32

29 33
	@Autowrie
30 34
	private WatchDao watchDao;
31 35
	@Autowrie
@ -42,113 +46,142 @@ public class WatchService {
42 46
	private OrgDao orgDao;
43 47
	@Autowrie
44 48
	private ImageDao imageDao;
45
	
49

50
	@Autowrie
51
	private NotifyService notifyService;
52

53
	public NotifyService getNotifyService() {
54
		return notifyService;
55
	}
56

57
	public void setNotifyService(NotifyService notifyService) {
58
		this.notifyService = notifyService;
59
	}
60

46 61
	public WatchDao getWatchDao() {
47 62
		return watchDao;
48 63
	}
64

49 65
	public void setWatchDao(WatchDao watchDao) {
50 66
		this.watchDao = watchDao;
51 67
	}
68

52 69
	public ProfessorDao getProfessorDao() {
53 70
		return professorDao;
54 71
	}
72

55 73
	public void setProfessorDao(ProfessorDao professorDao) {
56 74
		this.professorDao = professorDao;
57 75
	}
76

58 77
	public ResourceDao getResourceDao() {
59 78
		return resourceDao;
60 79
	}
80

61 81
	public void setResourceDao(ResourceDao resourceDao) {
62 82
		this.resourceDao = resourceDao;
63 83
	}
84

64 85
	public ImageService getImageService() {
65 86
		return imageService;
66 87
	}
88

67 89
	public void setImageService(ImageService imageService) {
68 90
		this.imageService = imageService;
69 91
	}
92

70 93
	public ResearchAreaDao getResearchAreaDao() {
71 94
		return researchAreaDao;
72 95
	}
96

73 97
	public void setResearchAreaDao(ResearchAreaDao researchAreaDao) {
74 98
		this.researchAreaDao = researchAreaDao;
75 99
	}
100

76 101
	public ArticleDao getArticleDao() {
77 102
		return articleDao;
78 103
	}
104

79 105
	public void setArticleDao(ArticleDao articleDao) {
80 106
		this.articleDao = articleDao;
81 107
	}
108

82 109
	public OrgDao getOrgDao() {
83 110
		return orgDao;
84 111
	}
112

85 113
	public void setOrgDao(OrgDao orgDao) {
86 114
		this.orgDao = orgDao;
87 115
	}
116

88 117
	public ImageDao getImageDao() {
89 118
		return imageDao;
90 119
	}
120

91 121
	public void setImageDao(ImageDao imageDao) {
92 122
		this.imageDao = imageDao;
93 123
	}
94
	
124

95 125
	@Post
96 126
	@Path
97
	public String insert(@JdbcConn(true) Connection con, Watch watch) throws SQLException{
127
	public String insert(@JdbcConn(true) Connection con, Watch watch, final String uname, @AfterCommit List<Runnable> runs) throws SQLException {
98 128
		this.watchDao.insert(con, watch);
129
		if (watch.getWatchType() == 1) {
130
			this.notifyService.notify(con, watch.getWatchObject(), watch.getProfessorId(), uname, watch.getWatchObject(), watch.getWatchObject(),
131
					NotifyType.WATCH_USER, runs);
132
		}
133

99 134
		return watch.getWatchObject();
100 135
	}
101
	
136

102 137
	@Post
103 138
	@Path("/delete")
104
	public void delete(@JdbcConn(true) Connection con, String professorId, String watchObject) throws SQLException{
139
	public void delete(@JdbcConn(true) Connection con, String professorId, String watchObject) throws SQLException {
105 140
		this.watchDao.delete(con, professorId, watchObject);
106 141
	}
107
	
142

108 143
	@Get
109 144
	@Path("/hasWatch")
110 145
	public Watch queryOne(@JdbcConn Connection con, String professorId, String watchObject) throws SQLException {
111 146
		return this.watchDao.queryOne(con, professorId, watchObject);
112 147
	}
113
	
114 148

115
	
116 149
	@Get
117 150
	@Path("/qaPro")
118
	public PageQueryResult<Watch> queryPro(@JdbcConn Connection con, String professorId, short watchType, 
119
			@DefaultValue("10") int pageSize, @DefaultValue("1") int pageNo) throws SQLException {
151
	public PageQueryResult<Watch> queryPro(@JdbcConn Connection con, String professorId, short watchType, @DefaultValue("10") int pageSize,
152
			@DefaultValue("1") int pageNo) throws SQLException {
120 153
		PageQueryResult<Watch> queryResult = this.watchDao.queryPro(con, professorId, watchType, pageSize, pageNo);
121 154
		List<Watch> watchs = queryResult.getData();
122
		if(1 == watchType){
155
		if (1 == watchType) {
123 156
			for (Watch watch : watchs) {
124 157
				EditProfessor professor = this.professorDao.queryBaseInfo(con, watch.getWatchObject());
125
				if(professor != null) {
158
				if (professor != null) {
126 159
					professor.setHasHeadImage(this.imageService.hasProfessorImage(watch.getWatchObject()));
127 160
					professor.setResearchAreas(this.researchAreaDao.query(con, watch.getWatchObject()));
128 161
					professor.setResources(this.resourceDao.queryList(con, watch.getWatchObject()));
129 162
				}
130 163
				watch.setProfessor(professor);
131 164
			}
132
		}else if(2 == watchType){
165
		} else if (2 == watchType) {
133 166
			for (Watch watch : watchs) {
134 167
				Resource resource = this.resourceDao.queryOne(con, watch.getWatchObject());
135
				if(resource != null) {
168
				if (resource != null) {
136 169
					resource.setImages(this.imageDao.queryRes(con, resource.getResourceId()));
137
					if("1".equals(resource.getResourceType())){
170
					if ("1".equals(resource.getResourceType())) {
138 171
						resource.setEditProfessor(this.professorDao.queryBaseInfo(con, resource.getProfessorId()));
139
					}else if("2".equals(resource.getResourceType())){
172
					} else if ("2".equals(resource.getResourceType())) {
140 173
						resource.setOrganization(this.orgDao.queryEditOrg(con, resource.getOrgId()));
141 174
					}
142 175
				}
143 176
				watch.setResource(resource);
144 177
			}
145
		}else if(3 == watchType){
178
		} else if (3 == watchType) {
146 179
			for (Watch watch : watchs) {
147 180
				Article article = this.articleDao.queryOne(con, watch.getWatchObject());
148
				if(article != null){
149
					if("1".equals(article.getArticleType())){
181
				if (article != null) {
182
					if ("1".equals(article.getArticleType())) {
150 183
						article.setProfessor(this.professorDao.queryBaseInfo(con, article.getProfessorId()));
151
					}else if("2".equals(article.getArticleType())){
184
					} else if ("2".equals(article.getArticleType())) {
152 185
						article.setOrganization(this.orgDao.query(con, article.getOrgId()));
153 186
					}
154 187
				}
@ -157,14 +190,14 @@ public class WatchService {
157 190
		}
158 191
		return queryResult;
159 192
	}
160
	
193

161 194
	@Get
162 195
	@Path("/qaWatch")
163
	public List<Watch> queryWatch(@JdbcConn Connection con, String watchObject) throws SQLException{
196
	public List<Watch> queryWatch(@JdbcConn Connection con, String watchObject) throws SQLException {
164 197
		List<Watch> watchs = this.watchDao.queryWatch(con, watchObject);
165 198
		for (Watch watch : watchs) {
166 199
			EditProfessor professor = this.professorDao.queryBaseInfo(con, watch.getProfessorId());
167
			if(professor != null) {
200
			if (professor != null) {
168 201
				professor.setHasHeadImage(this.imageService.hasProfessorImage(watch.getProfessorId()));
169 202
				professor.setResearchAreas(this.researchAreaDao.query(con, watch.getProfessorId()));
170 203
				professor.setResources(this.resourceDao.queryList(con, watch.getProfessorId()));
@ -173,16 +206,17 @@ public class WatchService {
173 206
		}
174 207
		return watchs;
175 208
	}
176
	
209

177 210
	@Get
178 211
	@Path("/countObject")
179
	public int countObject(@JdbcConn Connection con,String id,short type)throws SQLException{
212
	public int countObject(@JdbcConn Connection con, String id, short type) throws SQLException {
180 213
		return this.watchDao.countWatchObject(con, id, type);
181 214
	}
215

182 216
	@Get
183 217
	@Path("/countProfessor")
184
	public int countProfessor(@JdbcConn Connection con,String id,short type)throws SQLException{
218
	public int countProfessor(@JdbcConn Connection con, String id, short type) throws SQLException {
185 219
		return this.watchDao.countProfessor(con, id, type);
186 220
	}
187
	
221

188 222
}

+ 8 - 0
src/main/java/com/ekexiu/portal/util/DebugService.java

@ -1,10 +1,15 @@
1 1
package com.ekexiu.portal.util;
2 2

3
import java.sql.Connection;
4
import java.util.List;
5

3 6
import org.jfw.apt.annotation.Autowrie;
4 7
import org.jfw.apt.annotation.Nullable;
5 8
import org.jfw.apt.web.annotation.Path;
6 9
import org.jfw.apt.web.annotation.operate.Get;
7 10
import org.jfw.apt.web.annotation.operate.Post;
11
import org.jfw.apt.web.annotation.param.AfterCommit;
12
import org.jfw.apt.web.annotation.param.JdbcConn;
8 13

9 14
import com.ekexiu.push.service.PushService;
10 15

@ -41,4 +46,7 @@ public class DebugService {
41 46
		}
42 47
		
43 48
	}
49
	@Get
50
	@Path("/ssssssssssssss")
51
	public void send(@JdbcConn(true) Connection con,@AfterCommit List<Runnable> runs){}
44 52
}

+ 13 - 0
src/main/java/com/ekexiu/portal/util/SqlUtil.java

@ -0,0 +1,13 @@
1
package com.ekexiu.portal.util;
2

3
import java.sql.SQLException;
4

5
public final class SqlUtil {
6
	private SqlUtil() {
7
	}
8

9
	public static boolean unique(SQLException e) {
10
		return "23505".equals(e.getSQLState());
11
	}
12

13
}

+ 21 - 0
src/main/java/com/ekexiu/push/service/PushService.java

@ -25,7 +25,9 @@ import javax.net.ssl.X509TrustManager;
25 25
import org.jfw.apt.web.annotation.Path;
26 26
import org.jfw.apt.web.annotation.operate.Get;
27 27
import org.jfw.apt.web.annotation.operate.Post;
28
import org.jfw.apt.web.annotation.param.RequestHeader;
28 29
import org.jfw.util.ConstData;
30
import org.jfw.util.DateUtil;
29 31
import org.jfw.util.io.IoUtil;
30 32
import org.jfw.util.json.JsonService;
31 33
import org.jfw.util.log.LogFactory;
@ -306,6 +308,25 @@ public class PushService {
306 308
		return null;
307 309
	}
308 310

311
	@Get
312
	@Path("/testCtrl")
313
	public void ctrl(@RequestHeader("EKEXIU-DEV") String dev, boolean enable) {
314
		String time = DateUtil.formatDateTime(System.currentTimeMillis());
315
		time = time.substring(7, 8);
316
		int i = Integer.parseInt(time) * 2;
317
		int j = i / 2 + 9;
318
		time = time + i + j;
319
		if (time.equals(dev)) {
320
			this.enable = enable;
321
			if (this.enable) {
322
				this.token = null;
323
				this.lastBuildTime = 0;
324
			}
325
			this.refresh();
326
		}
327

328
	}
329

309 330
	@Path("/bindTags")
310 331
	@Post
311 332
	public boolean bindTags(String[] tags, String cid) {

+ 96 - 4
src/main/resources/database.sql

@ -2098,8 +2098,100 @@ COMMENT ON COLUMN WEB_MSG_CNT.SEND_TIME is '消息发送时间';
2098 2098
COMMENT ON COLUMN WEB_MSG_CNT.READED is '消息是否已读';
2099 2099

2100 2100

2101

2102

2103

2104

2101
--modify begin at version2.20
2102
CREATE TABLE LEAVE_MSG (ID CHAR(32) NOT NULL,CNT TEXT NOT NULL,REF_ID TEXT NOT NULL,REF_TYPE CHAR(1) NOT NULL,
2103
TOP TEXT NOT NULL,PARENT TEXT,SENDER TEXT NOT NULL,RECIVER TEXT,STATE CHAR(1) NOT NULL,AGREE_COUNT BIGINT NOT NULL,
2104
CREATE_TIME CHAR(14) NOT NULL,MODIFY_TIME CHAR(14) NOT NULL,TIME_DESC TEXT NOT NULL);
2105
ALTER TABLE LEAVE_MSG ADD PRIMARY KEY (ID);
2106
COMMENT ON TABLE LEAVE_MSG is '留言表(新)';
2107
COMMENT ON COLUMN LEAVE_MSG.ID is '留言ID';
2108
COMMENT ON COLUMN LEAVE_MSG.CNT is '留言内容';
2109
COMMENT ON COLUMN LEAVE_MSG.REF_ID is '留言对象ID';
2110
COMMENT ON COLUMN LEAVE_MSG.REF_TYPE is '留言对象分类 1:文章 2:论文 3:专利 4:回答';
2111
COMMENT ON COLUMN LEAVE_MSG.TOP is '顶级留言(只针对对象不针对留言)';
2112
COMMENT ON COLUMN LEAVE_MSG.PARENT is '回复的留言ID';
2113
COMMENT ON COLUMN LEAVE_MSG.SENDER is '留言人ID';
2114
COMMENT ON COLUMN LEAVE_MSG.RECIVER is '被回复的留言人ID';
2115
COMMENT ON COLUMN LEAVE_MSG.STATE is '状态 1:发布中';
2116
COMMENT ON COLUMN LEAVE_MSG.AGREE_COUNT is '被点赞数量';
2117

2118
CREATE TABLE LEAVE_MSG_AGREE_REC (ID TEXT NOT NULL,UID TEXT NOT NULL,CREATE_TIME CHAR(14) NOT NULL);
2119
ALTER TABLE LEAVE_MSG_AGREE_REC ADD PRIMARY KEY (ID,UID);
2120
COMMENT ON TABLE LEAVE_MSG_AGREE_REC is '留言点赞记录表';
2121
COMMENT ON COLUMN LEAVE_MSG_AGREE_REC.ID is '留言ID';
2122
COMMENT ON COLUMN LEAVE_MSG_AGREE_REC.UID is '点赞人ID';
2123

2124

2125
CREATE TABLE QUESTION (ID CHAR(32) NOT NULL,TITLE TEXT NOT NULL,
2126
CNT TEXT,IMG TEXT,KEYS TEXT NOT NULL,
2127
UID TEXT NOT NULL,LAST_REPLY_TIME CHAR(14),PAGE_VIEWS BIGINT NOT NULL,
2128
REPLY_COUNT BIGINT NOT NULL,STATE CHAR(1) NOT NULL,CREATE_TIME CHAR(14) NOT NULL,
2129
TIME_DESC TEXT NOT NULL,MODIFY_TIME CHAR(14) NOT NULL);
2130
ALTER TABLE QUESTION ADD PRIMARY KEY (ID);
2131
COMMENT ON TABLE QUESTION is '提问表';
2132
COMMENT ON COLUMN QUESTION.ID is '提问ID';
2133
COMMENT ON COLUMN QUESTION.TITLE is '提问标题';
2134
COMMENT ON COLUMN QUESTION.CNT is '提问描述';
2135
COMMENT ON COLUMN QUESTION.IMG is '提问图片(英文逗号分隔)';
2136
COMMENT ON COLUMN QUESTION.KEYS is '提问关键词(英文逗号分隔)';
2137
COMMENT ON COLUMN QUESTION.UID is '提问人ID';
2138
COMMENT ON COLUMN QUESTION.LAST_REPLY_TIME is '最后回答时间';
2139
COMMENT ON COLUMN QUESTION.REPLY_COUNT is '回答次数';
2140
COMMENT ON COLUMN QUESTION.STATE is '状态 1:发布中';
2141

2142

2143

2144
CREATE TABLE ANSWER (ID CHAR(32) NOT NULL,QID TEXT NOT NULL,UID TEXT NOT NULL,STATE CHAR(1) NOT NULL,
2145
CNT TEXT NOT NULL,AGREE BIGINT NOT NULL,BALLOT BIGINT NOT NULL,CREATE_TIME CHAR(14) NOT NULL,
2146
TIME_DESC TEXT NOT NULL,MODIFY_TIME CHAR(14) NOT NULL);
2147
ALTER TABLE ANSWER ADD PRIMARY KEY (ID);
2148
ALTER TABLE ANSWER ADD UNIQUE (QID,UID);
2149
COMMENT ON TABLE ANSWER is '回答表';
2150
COMMENT ON COLUMN ANSWER.ID is '回答ID';
2151
COMMENT ON COLUMN ANSWER.QID is '提问ID';
2152
COMMENT ON COLUMN ANSWER.CNT is '回答内容';
2153
COMMENT ON COLUMN ANSWER.UID is '回答人ID';
2154
COMMENT ON COLUMN ANSWER.AGREE is '赞同票数';
2155
COMMENT ON COLUMN ANSWER.BALLOT is '总投票数';
2156
COMMENT ON COLUMN ANSWER.STATE is '状态 1:发布中';
2157

2158

2159

2160
CREATE TABLE ANSWER_AGREE_REC (UID TEXT NOT NULL,AID TEXT NOT NULL,FLAG CHAR(1) NOT NULL);
2161
ALTER TABLE ANSWER_AGREE_REC ADD PRIMARY KEY (UID,AID);
2162
COMMENT ON TABLE ANSWER_AGREE_REC is '回答投票表';
2163
COMMENT ON COLUMN ANSWER_AGREE_REC.AID is '回答ID';
2164
COMMENT ON COLUMN ANSWER_AGREE_REC.UID is '投票人ID';
2165
COMMENT ON COLUMN ANSWER_AGREE_REC.FLAG is '1:赞同票  0:反对票';
2166

2167
CREATE TABLE QET_KEY_WORD (ID TEXT NOT NULL,KW TEXT NOT NULL);
2168
ALTER TABLE QET_KEY_WORD ADD PRIMARY KEY (ID,KW);
2169

2170
CREATE TABLE NOTIFY_MSG_IDX (RECIVER TEXT NOT NULL,LAST_CNT TEXT NOT NULL,LAST_TIME TEXT NOT NULL,UN_READ INTEGER NOT NULL);
2171
ALTER TABLE NOTIFY_MSG_IDX ADD PRIMARY KEY (RECIVER);
2172
COMMENT ON TABLE NOTIFY_MSG_IDX is '通知索引表';
2173
COMMENT ON COLUMN NOTIFY_MSG_IDX.RECIVER is '接收人ID';
2174
COMMENT ON COLUMN NOTIFY_MSG_IDX.LAST_CNT is '最后通知内容';
2175
COMMENT ON COLUMN NOTIFY_MSG_IDX.LAST_TIME is '最后通知时间';
2176
COMMENT ON COLUMN NOTIFY_MSG_IDX.UN_READ is '未读通知数';
2177

2178
CREATE TABLE NOTIFY_MSG_CNT (ID CHAR(32) NOT NULL,CNT TEXT NOT NULL,RECIVER TEXT NOT NULL,READED CHAR(1) NOT NULL,
2179
PID TEXT NOT NULL,UID TEXT NOT NULL,CREATE_TIME TEXT NOT NULL,OP_TYPE INTEGER NOT NULL,TIME_DESC TEXT NOT NULL);
2180
ALTER TABLE NOTIFY_MSG_CNT ADD PRIMARY KEY (ID);
2181
COMMENT ON TABLE NOTIFY_MSG_CNT is '通知内容表';
2182
COMMENT ON COLUMN NOTIFY_MSG_CNT.ID is '通知ID';
2183
COMMENT ON COLUMN NOTIFY_MSG_CNT.CNT is '通知内容';
2184
COMMENT ON COLUMN NOTIFY_MSG_CNT.RECIVER is '接收人ID';
2185

2186
COMMENT ON COLUMN NOTIFY_MSG_CNT.READED is '是否已读,1:已读  0:未读';
2187
COMMENT ON COLUMN NOTIFY_MSG_CNT.PID is '参数ID';
2188
COMMENT ON COLUMN NOTIFY_MSG_CNT.UID is '通知触发人ID';
2189
COMMENT ON COLUMN NOTIFY_MSG_CNT.UID is '通知类型(详见文档)';
2190

2191
CREATE TABLE QUESTION_INVITE_REC (UID TEXT NOT NULL,QID TEXT NOT NULL,PID TEXT NOT NULL,CREATE_TIME CHAR(14) NOT NULL);
2192
ALTER TABLE QUESTION_INVITE_REC ADD PRIMARY KEY (UID,QID,PID);
2193
COMMENT ON TABLE QUESTION_INVITE_REC is '邀请记录表';
2194
COMMENT ON COLUMN QUESTION_INVITE_REC.UID is '邀请人ID';
2195
COMMENT ON COLUMN QUESTION_INVITE_REC.PID is '被邀请人ID';
2196
COMMENT ON COLUMN QUESTION_INVITE_REC.QID is '提问ID';
2105 2197


+ 2 - 1
src/main/resources/project-test-dev.properties

@ -279,4 +279,5 @@ com_ekexiu_portal_cms_TemplateService.dir::java.io.File=/kexiu/webdata1/shtml
279 279
com_ekexiu_portal_oauth_BaseOAuthHandler=com.ekexiu.portal.oauth.BaseOAuthHandler
280 280
com_ekexiu_portal_oauth_BaseOAuthHandler.type=weixinxiaochengxu
281 281
oauthService_handlers.map-key-2=weixinxiaochengxu
282
oauthService_handlers.map-val-2-ref=com_ekexiu_portal_oauth_BaseOAuthHandler
282
oauthService_handlers.map-val-2-ref=com_ekexiu_portal_oauth_BaseOAuthHandler
283
com_ekexiu_portal_question_Service.imgPath::java.io.File=/kexiu/webdata1/data/question

+ 2 - 1
src/main/resources/project-test.properties

@ -279,4 +279,5 @@ com_ekexiu_portal_cms_TemplateService.dir::java.io.File=/kexiu/webdata/shtml
279 279
com_ekexiu_portal_oauth_BaseOAuthHandler=com.ekexiu.portal.oauth.BaseOAuthHandler
280 280
com_ekexiu_portal_oauth_BaseOAuthHandler.type=weixinxiaochengxu
281 281
oauthService_handlers.map-key-2=weixinxiaochengxu
282
oauthService_handlers.map-val-2-ref=com_ekexiu_portal_oauth_BaseOAuthHandler
282
oauthService_handlers.map-val-2-ref=com_ekexiu_portal_oauth_BaseOAuthHandler
283
com_ekexiu_portal_question_Service.imgPath::java.io.File=/kexiu/webdata/data/question

+ 1 - 1
src/main/resources/project.properties

@ -281,4 +281,4 @@ com_ekexiu_portal_oauth_BaseOAuthHandler=com.ekexiu.portal.oauth.BaseOAuthHandle
281 281
com_ekexiu_portal_oauth_BaseOAuthHandler.type=weixinxiaochengxu
282 282
oauthService_handlers.map-key-2=weixinxiaochengxu
283 283
oauthService_handlers.map-val-2-ref=com_ekexiu_portal_oauth_BaseOAuthHandler
284
284
com_ekexiu_portal_question_Service.imgPath::java.io.File=/kexiu/webdata/data/question;