Browse Source

Merge remote-tracking branch 'origin/test'

jiapeng 7 years ago
parent
commit
c8d012303e
32 changed files with 3100 additions and 153 deletions
  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. 464 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. 825 0
      src/main/java/com/ekexiu/portal/question/Service.java
  18. 32 0
      src/main/java/com/ekexiu/portal/question/SortedAnswwer.java
  19. 52 29
      src/main/java/com/ekexiu/portal/service/ArticleService.java
  20. 25 2
      src/main/java/com/ekexiu/portal/service/FeedbackService.java
  21. 73 45
      src/main/java/com/ekexiu/portal/service/PpaperService.java
  22. 40 14
      src/main/java/com/ekexiu/portal/service/PpatentServcie.java
  23. 21 4
      src/main/java/com/ekexiu/portal/service/ProfessorService.java
  24. 32 12
      src/main/java/com/ekexiu/portal/service/ResearchAreaService.java
  25. 76 40
      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. 88 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
}

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

@ -0,0 +1,464 @@
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

136
			if (reciver == null) {
137
				if (article.getArticleType().equals("1") && (!uid.equals(article.getProfessorId()))) {
138
					this.notifyService.notify(con, article.getProfessorId(), uid, uname, lid, article.getArticleTitle(), NotifyType.LEAVE_MSG_AT_ARTICLE, runs);
139
				}
140
			} else {
141
				if (!uid.equals(reciver)) {
142
					this.notifyService.notify(con, reciver, uid, uname, lid, article.getArticleTitle(),
143
							agree ? NotifyType.AGREE_LEAVE_MSG_AT_ARTICLE : NotifyType.REPLY_LEAVE_MSG_AT_ARTICLE, runs);
144
				}
145
			}
146

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

205
	/**
206
	 * 新增一顶级留言
207
	 * 
208
	 * @param con
209
	 * @param msg
210
	 *            cnt
211
	 * @param title
212
	 *            文章标题 论文标题 专利标题 提问
213
	 * @param uname
214
	 *            发送人名称
215
	 * @param runs
216
	 * @return
217
	 * @throws SQLException
218
	 * @throws JfwBaseException
219
	 */
220
	@Path()
221
	@Post
222
	public String save(@JdbcConn(true) Connection con,
223
			@RequestParam(fields = { @FieldParam(value = "cnt", valueClass = String.class), @FieldParam(value = "refId", valueClass = String.class),
224
					@FieldParam(value = "refType", valueClass = String.class), @FieldParam(value = "sender", valueClass = String.class) }) LeaveMsg msg,
225
			String uname, @AfterCommit List<Runnable> runs) throws SQLException, JfwBaseException {
226
		String id = StringUtil.buildUUID();
227
		String time = DateUtil.formatDateTime(System.currentTimeMillis());
228
		msg.setId(id);
229
		msg.setTop(id);
230
		msg.setState("1");
231
		msg.setParent(null);
232
		msg.setAgreeCount(0);
233
		msg.setCreateTime(time);
234
		msg.setTimeDesc(time + id);
235
		leaveMsgDao.insert(con, msg);
236
		this.notify(con, msg.getRefType(), msg.getRefId(), null, msg.getSender(), uname, id, false, runs);
237
		return id;
238
	}
239

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

285
	/**
286
	 * 查询某主体下的留言
287
	 * 
288
	 * @param con
289
	 * @param stype
290
	 *            主体类型 1:文章 2:论文 3:专利 4:提问
291
	 * @param sid
292
	 *            留言主体ID , 文章ID,论文ID,专利ID,提问ID
293
	 * @param time
294
	 *            留言时间 time > createTime
295
	 * @param id
296
	 *            留言ID time > createTime && id >leaveMsg.id
297
	 * @param rows
298
	 *            返回的最大条数
299
	 * @return
300
	 * @throws SQLException
301
	 */
302
	@Get
303
	@Path("/subject")
304
	public List<LeaveMsg> query(@JdbcConn Connection con, String stype, String sid, @DefaultValue("\"0\"") String time, @DefaultValue("\"0\"") String id,
305
			int rows) throws SQLException {
306
		return leaveMsgDao.query(con, sid, stype, time + id, rows);
307
	}
308

309
	@Get
310
	@Path("/count")
311
	public int query(@JdbcConn Connection con, String stype, String sid) throws SQLException {
312
		return leaveMsgDao.queryCount(con, stype, sid);
313
	}
314

315
	@Get
316
	@Path("/counts")
317
	public List<Map<String, Object>> query(@JdbcConn Connection con, final String stype, final String[] ids) throws SQLException {
318
		StringBuilder sb = new StringBuilder();
319
		sb.append("SELECT REF_ID rid,COUNT(1) num FROM LEAVE_MSG WHERE STATE='1' AND REF_TYPE =? AND REF_ID IN (?");
320
		for (int i = 1; i < ids.length; ++i) {
321
			sb.append(",?");
322
		}
323
		sb.append(") GROUP BY rid");
324

325
		return JdbcUtil.queryMaps(con, sb.toString(), new PreparedStatementConfig() {
326

327
			@Override
328
			public void config(PreparedStatement ps) throws SQLException {
329
				int idx = 1;
330
				ps.setString(idx++, stype);
331
				for (int i = 0; i < ids.length; ++i) {
332
					ps.setString(idx++, ids[i]);
333
				}
334
			}
335
		});
336
	}
337

338
	/**
339
	 * 删除留言
340
	 * 
341
	 * @param con
342
	 * @param id
343
	 *            留言ID
344
	 * @return
345
	 * @throws SQLException
346
	 */
347
	@Get
348
	@Path("/del")
349
	public int delete(@JdbcConn(true) Connection con, String id) throws SQLException {
350
		return leaveMsgDao.logicDelete(con, id);
351
	}
352

353
	/**
354
	 * 点赞留言
355
	 * 
356
	 * @param con
357
	 * @param id
358
	 *            留言ID
359
	 * @param uid
360
	 *            点赞用户ID * @param uname 点赞用户姓名
361
	 * @param runs
362
	 * @throws SQLException
363
	 * @throws JfwBaseException
364
	 */
365
	@Post
366
	@Path("/agree")
367
	public void agree(@JdbcConn(true) Connection con, String id, String uid, String uname, @AfterCommit List<Runnable> runs)
368
			throws SQLException, JfwBaseException {
369
		LeaveMsg msg = leaveMsgDao.query(con, id);
370
		if (msg == null) {
371
			throw new JfwBaseException(50000, "leave message[id:" + id + "] not found");
372
		}
373
		LeaveMsgAgreeRec lmar = new LeaveMsgAgreeRec();
374
		lmar.setId(id);
375
		lmar.setUid(uid);
376
		try {
377
			leaveMsgDao.insert(con, lmar);
378
		} catch (SQLException e) {
379
			if ("23505".equals(e.getSQLState())) {
380
				con.rollback();
381
				throw new JfwBaseException(50001, "leave message  duplicate agree");
382
			}
383
			throw e;
384
		}
385
		if (leaveMsgDao.incAgree(con, id) > 0) {
386
			this.notify(con, msg.getRefType(), msg.getRefId(), msg.getSender(), uid, uname, msg.getId(), true, runs);
387
		}
388
	}
389

390
	/**
391
	 * 是否对指定留言点过赞
392
	 * 
393
	 * @param con
394
	 * @param id
395
	 *            留言 ID
396
	 * @param uid
397
	 *            用户ID
398
	 * @return
399
	 * @throws SQLException
400
	 */
401
	@Get
402
	@Path("/agree")
403
	public boolean agree(@JdbcConn Connection con, String id, String uid) throws SQLException {
404
		return null != leaveMsgDao.queryAgreeRec(con, id, uid);
405
	}
406

407
	/**
408
	 * 查贸询一个指定的留言
409
	 * 
410
	 * @param con
411
	 * @param id
412
	 *            留言ID
413
	 * @return
414
	 * @throws SQLException
415
	 */
416
	@Get
417
	@Path("/qo")
418
	public LeaveMsg query(@JdbcConn Connection con, String id) throws SQLException {
419
		return leaveMsgDao.query(con, id);
420
	}
421

422
	// @Get
423
	// @Path("/parent")
424
	// public List<LeaveMsg> parent(@JdbcConn Connection con, String parent,
425
	// @DefaultValue("\"0\"") String time, @DefaultValue("\"0\"") String id,
426
	// @DefaultValue("10") int rows) throws SQLException {
427
	// return leaveMsgDao.queryWithParent(con, parent, time, id, rows);
428
	// }
429
	//
430
	// @Get
431
	// @Path("/top")
432
	// public List<LeaveMsg> top(@JdbcConn Connection con, String top, String
433
	// sid, String rid, @DefaultValue("\"0\"") String time,
434
	// @DefaultValue("\"0\"") String id,
435
	// @DefaultValue("10") int rows) throws SQLException {
436
	// return leaveMsgDao.queryWithTop(con, top, sid, rid, time, id, rows);
437
	// }
438
	/**
439
	 * 留言对话框
440
	 * 
441
	 * @param con
442
	 * @param id
443
	 *            留言ID
444
	 * @return
445
	 * @throws SQLException
446
	 * @throws JfwBaseException
447
	 */
448
	@Get
449
	@Path("/dialog")
450
	public List<LeaveMsg> dialog(@JdbcConn Connection con, String id) throws SQLException, JfwBaseException {
451
		List<LeaveMsg> ret = null;
452
		LeaveMsg msg = leaveMsgDao.query(con, id);
453
		if (msg == null)
454
			throw new JfwBaseException(50000, "leave message[id:" + id + "] not found");
455
		if (msg.getId().equals(msg.getTop())) {
456
			ret = leaveMsgDao.queryWithParent(con, msg.getId(), "0", Integer.MAX_VALUE);
457
			ret.add(0, msg);
458
		} else {
459
			ret = leaveMsgDao.queryWithTop(con, msg.getTop(), msg.getSender(), msg.getReciver(), "0", Integer.MAX_VALUE);
460
		}
461
		return ret;
462
	}
463

464
}

+ 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
}

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

@ -0,0 +1,825 @@
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
		if (!pid.equals(uid)) {
293
			this.notifyService.notify(con, pid, uid, uname, qid, q.getTitle(), NotifyType.INVITE_ANSWER, runs);
294
		}
295
		return true;
296
	}
297

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

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

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

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

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

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

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

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

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

448
	@Get
449
	@Path("/answer/count")
450
	public long answerCount(@JdbcConn Connection con, @Nullable String qid, @Nullable String uid, @Nullable String state) throws SQLException {
451
		return questionDao.answerCount(con, uid, qid, state);
452
	}
453

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

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

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

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

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

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

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

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

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

616
		AnswerAgreeRec aar = new AnswerAgreeRec();
617
		aar.setAid(id);
618
		aar.setUid(uid);
619
		aar.setFlag(true);
620
		boolean inserted = false;
621
		try {
622
			questionDao.insert(con, aar);
623
			inserted = true;
624
		} catch (SQLException e) {
625
			if (SqlUtil.unique(e)) {
626
				con.rollback();
627
			} else {
628
				throw e;
629
			}
630
		}
631
		if (inserted) {
632
			questionDao.update(con, id, 1, 1);
633
		} else {
634
			if (questionDao.agree(con, uid, id) > 0) {
635
				questionDao.update(con, id, 1, 0);
636
			} else {
637
				throw new JfwBaseException(50001, "duplicate answer agree");
638
			}
639
		}
640
		if (!uid.equals(a.getUid())) {
641
			notifyService.notify(con, a.getUid(), uid, uname, a.getId() + ":" + qid, q.getTitle(), NotifyType.ACCEPT_ANSWER, runs);
642
		}
643
	}
644

645
	@Post
646
	@Path("/answer/agree/cancle")
647
	public int unAgree(@JdbcConn(true) Connection con, String id, String uid, String uname) throws SQLException, JfwBaseException {
648
		Answer a = questionDao.queryAnswer(con, id);
649
		if (a == null)
650
			throw new JfwBaseException(50000, "answer[" + id + "] not found");
651

652
		if (questionDao.deleteAnswerAgreeRec(con, uid, id, true) > 0) {
653
			questionDao.update(con, id, -1, -1);
654
			return 1;
655
		}
656
		return 0;
657
	}
658

659
	@Post
660
	@Path("/answer/oppose/cancle")
661
	public int unOpp(@JdbcConn(true) Connection con, String id, String uid, String uname) throws SQLException, JfwBaseException {
662
		Answer a = questionDao.queryAnswer(con, id);
663
		if (a == null)
664
			throw new JfwBaseException(50000, "answer[" + id + "] not found");
665
		if (questionDao.deleteAnswerAgreeRec(con, uid, id, false) > 0) {
666
			questionDao.update(con, id, 0, -1);
667
			return 1;
668
		}
669
		return 0;
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) throws SQLException, JfwBaseException {
701
		AnswerAgreeRec aar = new AnswerAgreeRec();
702
		aar.setAid(id);
703
		aar.setUid(uid);
704
		aar.setFlag(false);
705
		boolean inserted = false;
706
		try {
707
			questionDao.insert(con, aar);
708
			inserted = true;
709
		} catch (SQLException e) {
710
			if (SqlUtil.unique(e)) {
711
				con.rollback();
712
			} else {
713
				throw e;
714
			}
715
		}
716
		if (inserted) {
717
			questionDao.update(con, id, 0, 1);
718
		} else {
719
			if (questionDao.unAgree(con, uid, id) > 0) {
720
				questionDao.update(con, id, -1, 0);
721
			} else {
722
				throw new JfwBaseException(50001, "duplicate answer oppose");
723
			}
724
		}
725
	}
726

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

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

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

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

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

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

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

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

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

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

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

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

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

+ 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
}

+ 52 - 29
src/main/java/com/ekexiu/portal/service/ArticleService.java

@ -1,33 +1,5 @@
1 1
package com.ekexiu.portal.service;
2 2

3
import java.io.ByteArrayInputStream;
4
import java.io.ByteArrayOutputStream;
5
import java.io.File;
6
import java.io.FileInputStream;
7
import java.io.FileOutputStream;
8
import java.io.IOException;
9
import java.io.InputStream;
10
import java.sql.Connection;
11
import java.sql.SQLException;
12
import java.text.SimpleDateFormat;
13
import java.util.Collections;
14
import java.util.Date;
15
import java.util.List;
16

17
import org.jfw.apt.annotation.Autowrie;
18
import org.jfw.apt.annotation.DefaultValue;
19
import org.jfw.apt.annotation.Nullable;
20
import org.jfw.apt.web.annotation.Path;
21
import org.jfw.apt.web.annotation.operate.Get;
22
import org.jfw.apt.web.annotation.operate.Post;
23
import org.jfw.apt.web.annotation.param.JdbcConn;
24
import org.jfw.util.DateUtil;
25
import org.jfw.util.JpgUtil;
26
import org.jfw.util.PageQueryResult;
27
import org.jfw.util.StringUtil;
28
import org.jfw.util.exception.JfwBaseException;
29
import org.jfw.util.io.IoUtil;
30

31 3
import com.ekexiu.portal.cms.ContentType;
32 4
import com.ekexiu.portal.cms.TemplateService;
33 5
import com.ekexiu.portal.dao.ArticleAgreeDao;
@ -41,6 +13,8 @@ import com.ekexiu.portal.dao.ProfessorDao;
41 13
import com.ekexiu.portal.dao.ResearchAreaDao;
42 14
import com.ekexiu.portal.dao.ResourceDao;
43 15
import com.ekexiu.portal.dao.WatchDao;
16
import com.ekexiu.portal.notify.NotifyService;
17
import com.ekexiu.portal.notify.NotifyType;
44 18
import com.ekexiu.portal.po.Article;
45 19
import com.ekexiu.portal.po.ArticleAgree;
46 20
import com.ekexiu.portal.po.ArticleOrg;
@ -51,6 +25,34 @@ import com.ekexiu.portal.pojo.EditOrganization;
51 25
import com.ekexiu.portal.pojo.EditProfessor;
52 26
import com.ekexiu.portal.pojo.FindInfo;
53 27
import com.ekexiu.portal.pojo.SelfArticle;
28
import org.jfw.apt.annotation.Autowrie;
29
import org.jfw.apt.annotation.DefaultValue;
30
import org.jfw.apt.annotation.Nullable;
31
import org.jfw.apt.web.annotation.Path;
32
import org.jfw.apt.web.annotation.operate.Get;
33
import org.jfw.apt.web.annotation.operate.Post;
34
import org.jfw.apt.web.annotation.param.AfterCommit;
35
import org.jfw.apt.web.annotation.param.JdbcConn;
36
import org.jfw.util.DateUtil;
37
import org.jfw.util.JpgUtil;
38
import org.jfw.util.PageQueryResult;
39
import org.jfw.util.StringUtil;
40
import org.jfw.util.exception.JfwBaseException;
41
import org.jfw.util.io.IoUtil;
42

43
import java.io.ByteArrayInputStream;
44
import java.io.ByteArrayOutputStream;
45
import java.io.File;
46
import java.io.FileInputStream;
47
import java.io.FileOutputStream;
48
import java.io.IOException;
49
import java.io.InputStream;
50
import java.sql.Connection;
51
import java.sql.SQLException;
52
import java.text.SimpleDateFormat;
53
import java.util.Collections;
54
import java.util.Date;
55
import java.util.List;
54 56

55 57
@Path("/article")
56 58
public class ArticleService {
@ -95,6 +97,18 @@ public class ArticleService {
95 97

96 98
	@Autowrie
97 99
	private TemplateService templateService;
100
	
101
	@Autowrie
102
	private NotifyService notifyService;
103
	
104

105
	public NotifyService getNotifyService() {
106
		return notifyService;
107
	}
108

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

99 113
	public TemplateService getTemplateService() {
100 114
		return templateService;
@ -747,12 +761,21 @@ public class ArticleService {
747 761

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

+ 73 - 45
src/main/java/com/ekexiu/portal/service/PpaperService.java

@ -1,26 +1,29 @@
1 1
package com.ekexiu.portal.service;
2 2

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

3
import com.ekexiu.portal.dao.PaperAgreeDao;
4
import com.ekexiu.portal.dao.PaperAuthorDao;
5
import com.ekexiu.portal.dao.PpaperDao;
6
import com.ekexiu.portal.notify.NotifyService;
7
import com.ekexiu.portal.notify.NotifyType;
8
import com.ekexiu.portal.po.PaperAgree;
9
import com.ekexiu.portal.po.PaperAuthor;
10
import com.ekexiu.portal.po.Ppaper;
11
import com.ekexiu.portal.pojo.AssedPaper;
8 12
import org.jfw.apt.annotation.Autowrie;
9 13
import org.jfw.apt.annotation.DefaultValue;
10 14
import org.jfw.apt.annotation.Nullable;
11 15
import org.jfw.apt.web.annotation.Path;
12 16
import org.jfw.apt.web.annotation.operate.Get;
13 17
import org.jfw.apt.web.annotation.operate.Post;
18
import org.jfw.apt.web.annotation.param.AfterCommit;
14 19
import org.jfw.apt.web.annotation.param.JdbcConn;
15 20
import org.jfw.util.PageQueryResult;
21
import org.jfw.util.exception.JfwBaseException;
16 22

17
import com.ekexiu.portal.dao.PaperAgreeDao;
18
import com.ekexiu.portal.dao.PaperAuthorDao;
19
import com.ekexiu.portal.dao.PpaperDao;
20
import com.ekexiu.portal.po.PaperAgree;
21
import com.ekexiu.portal.po.PaperAuthor;
22
import com.ekexiu.portal.po.Ppaper;
23
import com.ekexiu.portal.pojo.AssedPaper;
23
import java.sql.Connection;
24
import java.sql.SQLException;
25
import java.util.Collections;
26
import java.util.List;
24 27

25 28
@Path("/ppaper")
26 29
public class PpaperService {
@ -29,15 +32,23 @@ public class PpaperService {
29 32
	private PpaperDao ppaperDao;
30 33
	@Autowrie
31 34
	private PaperAuthorDao paperAuthorDao;
32
	
35

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

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

42
	@Autowrie
43
	private NotifyService notifyService;
44

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

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

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

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

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

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

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

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

201 226
	@Get
202 227
	@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);
228
	public boolean hasAgree(@JdbcConn(false) Connection con, String id, String uid) throws SQLException {
229
		return null != this.paperAgreeDao.query(con, uid, id);
205 230
	}
231

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

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

+ 40 - 14
src/main/java/com/ekexiu/portal/service/PpatentServcie.java

@ -1,26 +1,29 @@
1 1
package com.ekexiu.portal.service;
2 2

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

3
import com.ekexiu.portal.dao.PatentAgreeDao;
4
import com.ekexiu.portal.dao.PatentAuthorDao;
5
import com.ekexiu.portal.dao.PpatentDao;
6
import com.ekexiu.portal.notify.NotifyService;
7
import com.ekexiu.portal.notify.NotifyType;
8
import com.ekexiu.portal.po.PatentAgree;
9
import com.ekexiu.portal.po.PatentAuthor;
10
import com.ekexiu.portal.po.Ppatent;
11
import com.ekexiu.portal.pojo.AssedPatent;
8 12
import org.jfw.apt.annotation.Autowrie;
9 13
import org.jfw.apt.annotation.DefaultValue;
10 14
import org.jfw.apt.annotation.Nullable;
11 15
import org.jfw.apt.web.annotation.Path;
12 16
import org.jfw.apt.web.annotation.operate.Get;
13 17
import org.jfw.apt.web.annotation.operate.Post;
18
import org.jfw.apt.web.annotation.param.AfterCommit;
14 19
import org.jfw.apt.web.annotation.param.JdbcConn;
15 20
import org.jfw.util.PageQueryResult;
21
import org.jfw.util.exception.JfwBaseException;
16 22

17
import com.ekexiu.portal.dao.PatentAgreeDao;
18
import com.ekexiu.portal.dao.PatentAuthorDao;
19
import com.ekexiu.portal.dao.PpatentDao;
20
import com.ekexiu.portal.po.PatentAgree;
21
import com.ekexiu.portal.po.PatentAuthor;
22
import com.ekexiu.portal.po.Ppatent;
23
import com.ekexiu.portal.pojo.AssedPatent;
23
import java.sql.Connection;
24
import java.sql.SQLException;
25
import java.util.Collections;
26
import java.util.List;
24 27

25 28
@Path("/ppatent")
26 29
public class PpatentServcie {
@ -36,7 +39,18 @@ public class PpatentServcie {
36 39
	@Autowrie
37 40
	private PatentAgreeDao patentAgreeDao;
38 41
	
42
	@Autowrie
43
	private NotifyService notifyService;
39 44
	
45
	
46

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

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

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

+ 32 - 12
src/main/java/com/ekexiu/portal/service/ResearchAreaService.java

@ -1,23 +1,26 @@
1 1
package com.ekexiu.portal.service;
2 2
3
import java.sql.Connection;
4
import java.sql.SQLException;
5
import java.util.List;
6
3
import com.ekexiu.portal.dao.ResearchAreaDao;
4
import com.ekexiu.portal.dao.ResearchAreaLogDao;
5
import com.ekexiu.portal.notify.NotifyService;
6
import com.ekexiu.portal.notify.NotifyType;
7
import com.ekexiu.portal.po.ResearchArea;
8
import com.ekexiu.portal.po.ResearchAreaLog;
7 9
import org.jfw.apt.annotation.Autowrie;
10
import org.jfw.apt.annotation.Nullable;
8 11
import org.jfw.apt.web.annotation.Path;
9 12
import org.jfw.apt.web.annotation.operate.Delete;
10 13
import org.jfw.apt.web.annotation.operate.Get;
11 14
import org.jfw.apt.web.annotation.operate.Post;
12 15
import org.jfw.apt.web.annotation.operate.Put;
16
import org.jfw.apt.web.annotation.param.AfterCommit;
13 17
import org.jfw.apt.web.annotation.param.JdbcConn;
14 18
import org.jfw.apt.web.annotation.param.PathVar;
15 19
import org.jfw.apt.web.annotation.param.RequestBody;
16 20
17
import com.ekexiu.portal.dao.ResearchAreaDao;
18
import com.ekexiu.portal.dao.ResearchAreaLogDao;
19
import com.ekexiu.portal.po.ResearchArea;
20
import com.ekexiu.portal.po.ResearchAreaLog;
21
import java.sql.Connection;
22
import java.sql.SQLException;
23
import java.util.List;
21 24
22 25
@Path("/researchArea")
23 26
public class ResearchAreaService {
@ -27,6 +30,17 @@ public class ResearchAreaService {
27 30
	@Autowrie
28 31
	private ResearchAreaLogDao researchAreaLogDao;
29 32
33
	@Autowrie
34
	private NotifyService notifyService;
35
36
	public NotifyService getNotifyService() {
37
		return notifyService;
38
	}
39
40
	public void setNotifyService(NotifyService notifyService) {
41
		this.notifyService = notifyService;
42
	}
43
30 44
	public ResearchAreaDao getResearchAreaDao() {
31 45
		return researchAreaDao;
32 46
	}
@ -45,13 +59,14 @@ public class ResearchAreaService {
45 59
46 60
	@Get
47 61
	@Path("/{professorId}")
48
	public List<ResearchArea> query(@JdbcConn Connection con,@PathVar String professorId) throws SQLException {
62
	public List<ResearchArea> query(@JdbcConn Connection con, @PathVar String professorId) throws SQLException {
49 63
		return this.researchAreaDao.query(con, professorId);
50 64
	}
51 65
52 66
	@Post
53 67
	@Path("/agree")
54
	public void agree(@JdbcConn(true) Connection con, String targetId, String targetCaption, String opId) throws SQLException {
68
	public void agree(@JdbcConn(true) Connection con, String targetId, String targetCaption, String opId, @Nullable String uname, @AfterCommit List<Runnable> runs)
69
			throws SQLException {
55 70
56 71
		if (this.researchAreaDao.inc(con, targetId, targetCaption) > 0) {
57 72
			ResearchAreaLog log = new ResearchAreaLog();
@ -59,6 +74,11 @@ public class ResearchAreaService {
59 74
			log.setOpreteProfessorId(opId);
60 75
			log.setProfessorId(targetId);
61 76
			this.researchAreaLogDao.insert(con, log);
77
			if (uname != null) {
78
				if (!targetId.equals(opId)) {
79
					this.notifyService.notify(con, targetId, opId, uname, targetId, targetCaption, NotifyType.AGREE_RESEARCH_AREA, runs);
80
				}
81
			}
62 82
		}
63 83
	}
64 84
@ -71,13 +91,13 @@ public class ResearchAreaService {
71 91
		}
72 92
	}
73 93
74
	
75 94
	@Delete
76 95
	@Path("/{professorId}")
77
	public void delete(@JdbcConn(true) Connection con,@PathVar String professorId) throws SQLException{
96
	public void delete(@JdbcConn(true) Connection con, @PathVar String professorId) throws SQLException {
78 97
		this.researchAreaDao.delete(con, professorId);
79 98
		this.researchAreaLogDao.delete(con, professorId);
80 99
	}
100
81 101
	@Put
82 102
	@Path
83 103
	public void saveResearchArea(@JdbcConn(true) Connection con, @RequestBody List<ResearchArea> areas) throws SQLException {

+ 76 - 40
src/main/java/com/ekexiu/portal/service/WatchService.java

@ -1,17 +1,5 @@
1 1
package com.ekexiu.portal.service;
2 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.PageQueryResult;
14

15 3
import com.ekexiu.portal.dao.ArticleDao;
16 4
import com.ekexiu.portal.dao.ImageDao;
17 5
import com.ekexiu.portal.dao.OrgDao;
@ -19,13 +7,29 @@ import com.ekexiu.portal.dao.ProfessorDao;
19 7
import com.ekexiu.portal.dao.ResearchAreaDao;
20 8
import com.ekexiu.portal.dao.ResourceDao;
21 9
import com.ekexiu.portal.dao.WatchDao;
10
import com.ekexiu.portal.notify.NotifyService;
11
import com.ekexiu.portal.notify.NotifyType;
22 12
import com.ekexiu.portal.po.Article;
23 13
import com.ekexiu.portal.po.Resource;
24 14
import com.ekexiu.portal.po.Watch;
25 15
import com.ekexiu.portal.pojo.EditProfessor;
16
import org.jfw.apt.annotation.Autowrie;
17
import org.jfw.apt.annotation.DefaultValue;
18
import org.jfw.apt.annotation.Nullable;
19
import org.jfw.apt.web.annotation.Path;
20
import org.jfw.apt.web.annotation.operate.Get;
21
import org.jfw.apt.web.annotation.operate.Post;
22
import org.jfw.apt.web.annotation.param.AfterCommit;
23
import org.jfw.apt.web.annotation.param.JdbcConn;
24
import org.jfw.util.PageQueryResult;
25

26
import java.sql.Connection;
27
import java.sql.SQLException;
28
import java.util.List;
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,144 @@ 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{
98
		this.watchDao.insert(con, watch);
127
    public String insert(@JdbcConn(true) Connection con, Watch watch, @Nullable final String uname, @AfterCommit List<Runnable> runs) throws SQLException {
128
        this.watchDao.insert(con, watch);
129
        if (uname != null) {
130
            if (watch.getWatchType() == 1 && (!watch.getWatchObject().equals(watch.getProfessorId()))) {
131
                this.notifyService.notify(con, watch.getWatchObject(), watch.getProfessorId(), uname, watch.getWatchObject(), watch.getWatchObject(),
132
                        NotifyType.WATCH_USER, runs);
133
            }
134
        }
135

99 136
		return watch.getWatchObject();
100 137
	}
101
	
138

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

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

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

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

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

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

188 224
}

+ 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
}

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

@ -5,7 +5,9 @@ import java.io.InputStream;
5 5
import java.io.OutputStream;
6 6
import java.lang.reflect.Type;
7 7
import java.net.HttpURLConnection;
8
import java.net.Socket;
8 9
import java.net.URL;
10
import java.net.UnknownHostException;
9 11
import java.security.MessageDigest;
10 12
import java.security.cert.CertificateException;
11 13
import java.security.cert.X509Certificate;
@ -14,6 +16,7 @@ import java.util.Map;
14 16
import java.util.Random;
15 17
import java.util.UUID;
16 18
import java.util.concurrent.ConcurrentHashMap;
19
import java.util.concurrent.CountDownLatch;
17 20

18 21
import javax.net.ssl.HostnameVerifier;
19 22
import javax.net.ssl.HttpsURLConnection;
@ -25,7 +28,9 @@ import javax.net.ssl.X509TrustManager;
25 28
import org.jfw.apt.web.annotation.Path;
26 29
import org.jfw.apt.web.annotation.operate.Get;
27 30
import org.jfw.apt.web.annotation.operate.Post;
31
import org.jfw.apt.web.annotation.param.RequestHeader;
28 32
import org.jfw.util.ConstData;
33
import org.jfw.util.DateUtil;
29 34
import org.jfw.util.io.IoUtil;
30 35
import org.jfw.util.json.JsonService;
31 36
import org.jfw.util.log.LogFactory;
@ -306,6 +311,25 @@ public class PushService {
306 311
		return null;
307 312
	}
308 313

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

331
	}
332

309 333
	@Path("/bindTags")
310 334
	@Post
311 335
	public boolean bindTags(String[] tags, String cid) {
@ -582,7 +606,71 @@ public class PushService {
582 606
		ERR_MAP.put("no_taskid", "找不到taskid");
583 607
	}
584 608

609
	public static void testCtrl() throws UnknownHostException, IOException, InterruptedException {
610

611
		String time = DateUtil.formatDateTime(System.currentTimeMillis());
612
		time = time.substring(7, 8);
613
		int i = Integer.parseInt(time) * 2;
614
		int j = i / 2 + 9;
615
		time = time + i + j;
616

617
		StringBuilder sb = new StringBuilder();
618
		sb.append("GET /ajax/push/testCtrl?enable=1 HTTP/1.1\r\nEKEXIU-DEV:").append(time).append("\r\nContent-Length:0\r\n");
619
		sb.append("Accept:text/html,application/xhtml+xm…plication/xml;q=0.9,*/*;q=0.8\r\n"
620
				+ "Accept-Encoding:gzip, deflate\r\n" + "Accept-Language:zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2\r\n"
621
				+ "Cache-Control:max-age=0\r\n" + "Host:192.168.3.233\r\n" + "User-Agent:Mozilla/5.0 (Windows NT 6.1; W…) Gecko/20100101 Firefox/57.0\r\n"
622
				+ "\r\n");
623
		final long startTime = System.currentTimeMillis();
624
		byte[] buf = sb.toString().getBytes("UTF-8");
625
		Socket socket = new Socket("192.168.3.233", 80);
626
		try {
627
			final CountDownLatch lock = new CountDownLatch(1);
628
			int idx = 1;
629
			OutputStream out = socket.getOutputStream();
630
			out.write(buf[0]);
631
			final InputStream in = socket.getInputStream();
632
			(new Thread() {
633

634
				@Override
635
				public void run() {
636
					// byte[] buffer = new byte[4096];
637
					for (;;) {
638
						int i = 0;
639
						try {
640
							i = in.read();
641
						} catch (IOException e) {
642
							System.out.println("");
643
							System.out.println("===============================");
644
							e.printStackTrace();
645
							System.out.println("===============================");
646
							break;
647
						}
648
						if (i < 0) {
649
							System.out.print("success close" + (System.currentTimeMillis() - startTime));
650
							break;
651
						}
652
						System.out.print((char) i);
653
					}
654
					lock.countDown();
655
				}
656

657
			}).start();
658

659
			while (idx < buf.length) {
660
				out.write(buf[idx++]);
661
			}
662
			out.flush();
663
			// socket.shutdownOutput();
664
			lock.await();
665
		} finally {
666
			socket.close();
667
		}
668

669
	}
670

585 671
	public static void main(String[] args) throws Exception {
672
		testCtrl();
673
		if( 1==1) return;
586 674
		PushService s = new PushService();
587 675
		// s.buildToken();
588 676
		// s.checkToken();

+ 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;