mirror of
https://github.com/getrebuild/rebuild.git
synced 2024-09-20 15:35:55 +08:00
bugfix
Better Language. Fixs cache of User
This commit is contained in:
parent
0a531a5e4d
commit
2bcd2920d2
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
|
@ -24,7 +24,8 @@
|
|||
"html"
|
||||
],
|
||||
"prettier.eslintIntegration": true,
|
||||
"workbench.editor.enablePreview": false
|
||||
"workbench.editor.enablePreview": false,
|
||||
"java.configuration.updateBuildConfiguration": "disabled"
|
||||
}
|
||||
// node and eslint(-g)
|
||||
// Plugins: Beautify and ESLint
|
|
@ -195,6 +195,8 @@ public class SMSender {
|
|||
}
|
||||
|
||||
/**
|
||||
* 短信服务可用
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static boolean availableSMS() {
|
||||
|
@ -202,6 +204,8 @@ public class SMSender {
|
|||
}
|
||||
|
||||
/**
|
||||
* 邮件服务可用
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static boolean availableMail() {
|
||||
|
|
|
@ -24,7 +24,7 @@ import com.rebuild.server.helper.cache.CommonCache;
|
|||
import org.apache.commons.lang.math.RandomUtils;
|
||||
|
||||
/**
|
||||
* 验证码
|
||||
* 验证码助手
|
||||
*
|
||||
* @author devezhao
|
||||
* @since 11/05/2018
|
||||
|
@ -40,12 +40,14 @@ public class VCode {
|
|||
}
|
||||
|
||||
/**
|
||||
* 生成验证码
|
||||
*
|
||||
* @param key
|
||||
* @param level complexity 1<2<3
|
||||
* @return
|
||||
*/
|
||||
public static String generate(String key, int level) {
|
||||
String vcode = null;
|
||||
String vcode;
|
||||
if (level == 3) {
|
||||
vcode = CodecUtils.randomCode(20);
|
||||
} else if (level == 2) {
|
||||
|
@ -55,6 +57,7 @@ public class VCode {
|
|||
vcode = vcode.substring(0, 6);
|
||||
}
|
||||
|
||||
// 缓存 10 分钟
|
||||
Application.getCommonCache().put("VCode-" + key, vcode, CommonCache.TS_HOUR / 6);
|
||||
return vcode;
|
||||
}
|
||||
|
@ -63,12 +66,15 @@ public class VCode {
|
|||
* @param key
|
||||
* @param vcode
|
||||
* @return
|
||||
* @see #verfiy(String, String, boolean)
|
||||
*/
|
||||
public static boolean verfiy(String key, String vcode) {
|
||||
return verfiy(key, vcode, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证是否有效
|
||||
*
|
||||
* @param key
|
||||
* @param vcode
|
||||
* @param keepAlive
|
||||
|
@ -76,7 +82,11 @@ public class VCode {
|
|||
* @see #clean(String)
|
||||
*/
|
||||
public static boolean verfiy(String key, String vcode, boolean keepAlive) {
|
||||
String ckey = "VCode-" + key;
|
||||
if (Application.devMode() && "rebuild".equalsIgnoreCase(vcode)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
final String ckey = "VCode-" + key;
|
||||
String exists = Application.getCommonCache().get(ckey);
|
||||
if (exists == null) {
|
||||
return false;
|
||||
|
@ -92,6 +102,8 @@ public class VCode {
|
|||
}
|
||||
|
||||
/**
|
||||
* 清除验证码
|
||||
*
|
||||
* @param key
|
||||
* @return
|
||||
*/
|
||||
|
|
|
@ -111,6 +111,17 @@ public class LanguageBundle implements JSONable {
|
|||
return lang;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param key
|
||||
* @param args
|
||||
* @return
|
||||
* @see String#format(String, Object...)
|
||||
*/
|
||||
public String formatLang(String key, Object... args) {
|
||||
String lang = lang(key);
|
||||
return String.format(lang, args);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param key
|
||||
* @return
|
||||
|
|
|
@ -138,8 +138,27 @@ public class Languages {
|
|||
* @param key
|
||||
* @param insideKeys
|
||||
* @return
|
||||
* @see #currentBundle()
|
||||
*/
|
||||
public static String lang(String key, String...insideKeys) {
|
||||
return instance.getCurrentBundle().lang(key, insideKeys);
|
||||
return currentBundle().lang(key, insideKeys);
|
||||
}
|
||||
|
||||
/**
|
||||
* 当前用户语言
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static LanguageBundle currentBundle() {
|
||||
return instance.getCurrentBundle();
|
||||
}
|
||||
|
||||
/**
|
||||
* 默认语言
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static LanguageBundle defaultBundle() {
|
||||
return instance.getDefaultBundle();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@ import com.rebuild.server.helper.BlackList;
|
|||
import com.rebuild.server.helper.ConfigurableItem;
|
||||
import com.rebuild.server.helper.SMSender;
|
||||
import com.rebuild.server.helper.SysConfiguration;
|
||||
import com.rebuild.server.helper.language.Languages;
|
||||
import com.rebuild.server.helper.task.TaskExecutors;
|
||||
import com.rebuild.server.metadata.EntityHelper;
|
||||
import com.rebuild.server.service.DataSpecificationException;
|
||||
|
@ -61,12 +62,24 @@ public class UserService extends SystemEntityService {
|
|||
|
||||
@Override
|
||||
public Record create(Record record) {
|
||||
return create(record, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param record
|
||||
* @param notifyUser
|
||||
* @return
|
||||
*/
|
||||
private Record create(Record record, boolean notifyUser) {
|
||||
final String passwd = record.getString("password");
|
||||
saveBefore(record);
|
||||
Record r = super.create(record);
|
||||
record = super.create(record);
|
||||
Application.getUserStore().refreshUser(record.getPrimary());
|
||||
notifyNewUser(r, passwd);
|
||||
return r;
|
||||
|
||||
if (notifyUser) {
|
||||
notifyNewUser(record, passwd);
|
||||
}
|
||||
return record;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -99,7 +112,7 @@ public class UserService extends SystemEntityService {
|
|||
}
|
||||
|
||||
if (record.hasValue("email") && Application.getUserStore().exists(record.getString("email"))) {
|
||||
throw new DataSpecificationException("邮箱重复");
|
||||
throw new DataSpecificationException(Languages.lang("Repeated", "Email"));
|
||||
}
|
||||
|
||||
if (record.getPrimary() == null && !record.hasValue("fullName")) {
|
||||
|
@ -136,7 +149,7 @@ public class UserService extends SystemEntityService {
|
|||
*/
|
||||
public void checkPassword(String password) throws DataSpecificationException {
|
||||
if (password.length() < 6) {
|
||||
throw new DataSpecificationException("密码不能小于6位");
|
||||
throw new DataSpecificationException(Languages.lang("PasswordLevel1Tip"));
|
||||
}
|
||||
|
||||
int policy = SysConfiguration.getInt(ConfigurableItem.PasswordPolicy);
|
||||
|
@ -161,14 +174,13 @@ public class UserService extends SystemEntityService {
|
|||
}
|
||||
|
||||
if (policy >= 2 && (countUpper == 0 || countLower == 0 || countDigit == 0)) {
|
||||
throw new DataSpecificationException("密码必须包含数字和大小写字母");
|
||||
throw new DataSpecificationException(Languages.lang("PasswordLevel2Tip"));
|
||||
}
|
||||
if (policy >= 3 && (countSpecial == 0 || password.length() < 8)) {
|
||||
throw new DataSpecificationException("密码不能小于8位,且必须包含特殊字符");
|
||||
throw new DataSpecificationException(Languages.lang("PasswordLevel3Tip"));
|
||||
}
|
||||
}
|
||||
|
||||
private static final String MSG_NEWUSER = "<p>系统管理员已经为你开通了 %s 账号!以下为你的登录信息,请妥善保管。</p><div style='margin:10px 0'>登录账号 <b>%s</b><br>登录密码 <b>%s</b><br>登录地址 <a href='%s'>%s</a></div><p>首次登陆,建议你立即修改登陆密码。修改方式:登陆后点击右上角头像 - 个人设置 - 安全设置 - 更改密码</p>";
|
||||
/**
|
||||
* @param newUser
|
||||
* @param passwd
|
||||
|
@ -179,39 +191,18 @@ public class UserService extends SystemEntityService {
|
|||
return false;
|
||||
}
|
||||
|
||||
String subject = "你的 " + SysConfiguration.get(ConfigurableItem.AppName) + " 账号已就绪";
|
||||
String content = String.format(MSG_NEWUSER,
|
||||
SysConfiguration.get(ConfigurableItem.AppName),
|
||||
newUser.getString("loginName"), passwd,
|
||||
SysConfiguration.getHomeUrl(),
|
||||
SysConfiguration.getHomeUrl());
|
||||
String appName = SysConfiguration.get(ConfigurableItem.AppName);
|
||||
String homeUrl = SysConfiguration.getHomeUrl();
|
||||
|
||||
String subject = Languages.defaultBundle().formatLang("YourAccountReady",
|
||||
appName);
|
||||
String content = Languages.defaultBundle().formatLang("NewUserAddedNotify",
|
||||
appName, newUser.getString("loginName"), passwd, homeUrl, homeUrl);
|
||||
|
||||
SMSender.sendMail(newUser.getString("email"), subject, content);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 改变部门
|
||||
*
|
||||
* @param user
|
||||
* @param deptNew
|
||||
* @see #updateEnableUser(ID, ID, ID, Boolean)
|
||||
*/
|
||||
public void updateDepartment(ID user, ID deptNew) {
|
||||
updateEnableUser(user, deptNew, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 改变角色
|
||||
*
|
||||
* @param user
|
||||
* @param roleNew
|
||||
* @see #updateEnableUser(ID, ID, ID, Boolean)
|
||||
*/
|
||||
public void updateRole(ID user, ID roleNew) {
|
||||
updateEnableUser(user, null, roleNew, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 入参值为 null 表示不做修改
|
||||
*
|
||||
|
@ -252,8 +243,7 @@ public class UserService extends SystemEntityService {
|
|||
|
||||
// 改变记录的所属部门
|
||||
if (deptOld != null) {
|
||||
TaskExecutors.submit(
|
||||
new ChangeOwningDeptTask(user, deptNew), Application.getCurrentUser());
|
||||
TaskExecutors.submit(new ChangeOwningDeptTask(user, deptNew), Application.getCurrentUser());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -262,20 +252,15 @@ public class UserService extends SystemEntityService {
|
|||
*
|
||||
* @param record
|
||||
*/
|
||||
public void txSignUp(Record record) {
|
||||
if (!SysConfiguration.getBool(ConfigurableItem.OpenSignUp)) {
|
||||
throw new DataSpecificationException("管理员未开放公开注册");
|
||||
}
|
||||
|
||||
record = this.create(record);
|
||||
public ID txSignUp(Record record) {
|
||||
record = this.create(record, false);
|
||||
|
||||
ID newUserId = record.getPrimary();
|
||||
String content = String.format(
|
||||
"用户 @%s 提交了注册申请。请验证用户有效性后为其启用并指定部门和角色,以便用户登录使用。如果这是一个无效的注册申请请忽略。"
|
||||
+ "[点击此处激活](%s/admin/bizuser/users#!/View/User/%s)",
|
||||
newUserId, AppUtils.getContextPath(), newUserId);
|
||||
String viewUrl = AppUtils.getContextPath() + "/app/list-and-view?id=" + newUserId;
|
||||
String content = Languages.defaultBundle().formatLang("NewUserSignupNotify", newUserId, viewUrl);
|
||||
|
||||
Message message = MessageBuilder.createMessage(ADMIN_USER, content);
|
||||
Message message = MessageBuilder.createMessage(ADMIN_USER, content, newUserId);
|
||||
Application.getNotifications().send(message);
|
||||
return newUserId;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -246,19 +246,21 @@ public class UserStore {
|
|||
.unique();
|
||||
final User newUser = new User(
|
||||
userId, (String) o[1], (String) o[2], (String) o[3], (String) o[4], (Boolean) o[5]);
|
||||
final ID deptId = (ID) o[6];
|
||||
final ID roleId = (ID) o[7];
|
||||
|
||||
final User oldUser = exists(userId) ? getUser(userId) : null;
|
||||
if (oldUser != null) {
|
||||
Role role = oldUser.getOwningRole();
|
||||
if (role != null) {
|
||||
role.removeMember(oldUser);
|
||||
role.addMember(newUser);
|
||||
}
|
||||
|
||||
Department dept = oldUser.getOwningDept();
|
||||
if (dept != null) {
|
||||
dept.removeMember(oldUser);
|
||||
dept.addMember(newUser);
|
||||
}
|
||||
|
||||
for (Team team : oldUser.getOwningTeams().toArray(new Team[0])) {
|
||||
team.removeMember(oldUser);
|
||||
team.addMember(newUser);
|
||||
|
@ -268,13 +270,13 @@ public class UserStore {
|
|||
if (oldUser.getEmail() != null) {
|
||||
USERs_MAIL2ID.remove(normalIdentifier(oldUser.getEmail()));
|
||||
}
|
||||
} else {
|
||||
if (o[6] != null) {
|
||||
getDepartment((ID) o[6]).addMember(newUser);
|
||||
}
|
||||
if (o[7] != null) {
|
||||
getRole((ID) o[7]).addMember(newUser);
|
||||
|
||||
if (deptId != null) {
|
||||
getDepartment(deptId).addMember(newUser);
|
||||
}
|
||||
if (roleId != null) {
|
||||
getRole(roleId).addMember(newUser);
|
||||
}
|
||||
|
||||
store(newUser);
|
||||
|
@ -530,7 +532,7 @@ public class UserStore {
|
|||
}
|
||||
}
|
||||
|
||||
// 组织关系
|
||||
// 组织部门关系
|
||||
for (Map.Entry<ID, Set<ID>> e : parentTemp.entrySet()) {
|
||||
BusinessUnit parent = getDepartment(e.getKey());
|
||||
for (ID child : e.getValue()) {
|
||||
|
|
|
@ -116,7 +116,7 @@ public class MessageBuilder {
|
|||
Matcher atMatcher = AT_PATTERN.matcher(message);
|
||||
while (atMatcher.find()) {
|
||||
String at = atMatcher.group();
|
||||
String atLabel = parseAtId(at.substring(1));
|
||||
String atLabel = parseAtsId(at.substring(1));
|
||||
if (atLabel != null && !atLabel.equals(at)) {
|
||||
message = message.replace(at, atLabel);
|
||||
}
|
||||
|
@ -132,7 +132,7 @@ public class MessageBuilder {
|
|||
* @param atid
|
||||
* @return
|
||||
*/
|
||||
static String parseAtId(String atid) {
|
||||
protected static String parseAtsId(String atid) {
|
||||
if (!ID.isId(atid)) {
|
||||
return atid;
|
||||
}
|
||||
|
|
|
@ -68,6 +68,11 @@ public class UserControll extends BaseEntityControll {
|
|||
@RequestMapping("check-user-status")
|
||||
public void checkUserStatus(HttpServletRequest request, HttpServletResponse response) throws IOException {
|
||||
ID id = getIdParameterNotNull(request, "id");
|
||||
if (!Application.getUserStore().exists(id)) {
|
||||
writeFailure(response);
|
||||
return;
|
||||
}
|
||||
|
||||
User checkedUser = Application.getUserStore().getUser(id);
|
||||
|
||||
Map<String, Object> ret = new HashMap<>();
|
||||
|
|
|
@ -118,6 +118,8 @@ public class GeneralDataListControll extends BaseEntityControll {
|
|||
url = MessageFormat.format("{0}/list#!/View/{0}/{1}", entity.getName(), id);
|
||||
} else if (entity.getEntityCode() == EntityHelper.Feeds) {
|
||||
url = "../feeds/home#s=" + id;
|
||||
} else if (entity.getEntityCode() == EntityHelper.User) {
|
||||
url = MessageFormat.format("../admin/bizuser/users#!/View/{0}/{1}", entity.getName(), id);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@ import com.rebuild.server.helper.ConfigurableItem;
|
|||
import com.rebuild.server.helper.SMSender;
|
||||
import com.rebuild.server.helper.SysConfiguration;
|
||||
import com.rebuild.server.helper.VCode;
|
||||
import com.rebuild.server.helper.language.Languages;
|
||||
import com.rebuild.server.metadata.EntityHelper;
|
||||
import com.rebuild.server.service.DataSpecificationException;
|
||||
import com.rebuild.server.service.bizz.UserService;
|
||||
|
@ -47,7 +48,7 @@ import java.io.IOException;
|
|||
import static com.rebuild.server.helper.language.Languages.lang;
|
||||
|
||||
/**
|
||||
* 注册
|
||||
* 用户自助注册
|
||||
*
|
||||
* @author devezhao
|
||||
* @since 11/01/2018
|
||||
|
@ -57,7 +58,7 @@ import static com.rebuild.server.helper.language.Languages.lang;
|
|||
public class SignUpControll extends BasePageControll {
|
||||
|
||||
@RequestMapping("signup")
|
||||
public ModelAndView pageSignup(HttpServletRequest request, HttpServletResponse response) throws IOException {
|
||||
public ModelAndView pageSignup(HttpServletResponse response) throws IOException {
|
||||
if (!SysConfiguration.getBool(ConfigurableItem.OpenSignUp)) {
|
||||
response.sendError(400, lang("SignupNotOpenTip"));
|
||||
return null;
|
||||
|
@ -119,7 +120,8 @@ public class SignUpControll extends BasePageControll {
|
|||
Application.getBean(UserService.class).txSignUp(userNew);
|
||||
|
||||
String homeUrl = SysConfiguration.getHomeUrl();
|
||||
String content = String.format(lang("SignupPending"), fullName, loginName, passwd, homeUrl, homeUrl);
|
||||
String content = Languages.currentBundle().formatLang("SignupPending",
|
||||
fullName, loginName, passwd, homeUrl, homeUrl);
|
||||
SMSender.sendMail(email, lang("AdminReviewSignup"), content);
|
||||
writeSuccess(response);
|
||||
} catch (DataSpecificationException ex) {
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
"ReturnHome": "Go Home",
|
||||
"ReportIssue": "Report an issue",
|
||||
"SignupNotOpenTip": "Administrator has not opened public signup",
|
||||
"UnsetEmailTip": "If you forgot or did not configure your email, please contact the administrator to reset your password",
|
||||
"UnsetEmailTip": "If you forgot or unfilled email, please contact your administrator to reset your password",
|
||||
"InputEmailPls": "Please enter email",
|
||||
"InputNewPasswordPls": "Enter new password",
|
||||
"PasswordNotMatch": "The new password not match.",
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
"ReturnHome": "返回首页",
|
||||
"ReportIssue": "报告此问题",
|
||||
"SignupNotOpenTip": "管理员未开放公开注册",
|
||||
"UnsetEmailTip": "如果你忘记或未配置邮箱,请联系管理员重置密码",
|
||||
"UnsetEmailTip": "如果你忘记或未填写邮箱,请联系管理员重置密码",
|
||||
"InputEmailPls": "请输入邮箱",
|
||||
"InputNewPasswordPls": "请输入新密码",
|
||||
"PasswordNotMatch": "两次输入的新密码不一致",
|
||||
|
@ -62,5 +62,12 @@
|
|||
"Retry": "重试",
|
||||
"ErrorUnknow": "未知错误,请稍后重试",
|
||||
"Error404": "访问的地址/资源不存在",
|
||||
"Error403": "权限不足,访问被阻止"
|
||||
"Error403": "权限不足,访问被阻止",
|
||||
"NewUserAddedNotify": "<p>系统管理员已经为你开通了 %s 账号!以下为你的登录信息,请妥善保管。</p><div style='margin:10px 0'>登录账号 <b>%s</b><br>登录密码 <b>%s</b><br>登录地址 <a href='%s'>%s</a></div><p>首次登陆,建议你立即修改登陆密码。修改方式:登陆后点击右上角头像 - 个人设置 - 安全设置 - 更改密码</p>",
|
||||
"YourAccountReady": "你的 %s 账号已就绪",
|
||||
"NewUserSignupNotify": "用户 @%s 提交了注册申请。请验证用户有效性后为其启用并指定部门和角色,以便用户登录使用。如果这是一个无效申请请忽略。[点击此处激活](%s)",
|
||||
"PasswordLevel1Tip": "密码不能小于6位",
|
||||
"PasswordLevel2Tip": "密码必须包含数字和大小写字母",
|
||||
"PasswordLevel3Tip": "密码不能小于8位,且必须包含特殊字符",
|
||||
"Repeated": "{0}重复"
|
||||
}
|
|
@ -82,7 +82,11 @@ window.__PageConfig = {
|
|||
<script src="${baseUrl}/assets/js/rb-forms.exts.jsx" type="text/babel"></script>
|
||||
<script src="${baseUrl}/assets/js/bizuser/dept-tree.js"></script>
|
||||
<script type="text/babel">
|
||||
RbForm.postAfter = loadDeptTree
|
||||
let RbForm_postAfter = RbForm.postAfter
|
||||
RbForm.postAfter = function () {
|
||||
RbForm_postAfter()
|
||||
loadDeptTree()
|
||||
}
|
||||
$(document).ready(loadDeptTree)
|
||||
clickDept = function(depts) {
|
||||
if (depts[0] == '$ALL$') depts = []
|
||||
|
|
|
@ -53,36 +53,6 @@ window.__PageConfig = {
|
|||
<script src="${baseUrl}/assets/js/rb-forms.jsx" type="text/babel"></script>
|
||||
<script src="${baseUrl}/assets/js/rb-forms.exts.jsx" type="text/babel"></script>
|
||||
<script src="${baseUrl}/assets/js/rb-view.jsx" type="text/babel"></script>
|
||||
<script type="text/babel">
|
||||
let RbForm_postAfter = RbForm.postAfter
|
||||
RbForm.postAfter = function() {
|
||||
RbForm_postAfter()
|
||||
if (parent && parent.loadDeptTree) parent.loadDeptTree()
|
||||
}
|
||||
$(document).ready(function() {
|
||||
$('.J_delete').off('click').click(function() {
|
||||
$.get(rb.baseUrl + '/admin/bizuser/delete-checks?id=${id}', function(res) {
|
||||
if (res.data.hasMember == 0 && res.data.hasChild == 0){
|
||||
RbAlert.create('此部门可以被安全的删除', '删除部门', { type: 'danger', confirmText: '删除', confirm: function(){ deleteDept(this) } })
|
||||
} else {
|
||||
let msg = '此部门下有 '
|
||||
if (res.data.hasMember > 0) msg += '<b>' + res.data.hasMember + '</b> 个用户' + (res.data.hasMember > 0 ? '和 ' : ' ')
|
||||
if (res.data.hasMember > 0) msg += '<b>' + res.data.hasMember + '</b> 个子部门'
|
||||
msg += '<br>需要先将他们转移至其他部门,然后才能安全删除'
|
||||
RbAlert.create(msg, '无法删除', { type: 'warning', html: true })
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
let deleteDept = function(dlg){
|
||||
dlg.disabled(true)
|
||||
$.post(rb.baseUrl + '/admin/bizuser/dept-delete?transfer=&id=${id}', function(res){
|
||||
if (res.error_code == 0) {
|
||||
parent.location.hash = '!/View/'
|
||||
parent.location.reload()
|
||||
} else RbHighbar.error(res.error_msg)
|
||||
})
|
||||
}
|
||||
</script>
|
||||
<script src="${baseUrl}/assets/js/bizuser/dept-view.jsx" type="text/babel"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -89,15 +89,15 @@ window.__PageConfig = {
|
|||
<script src="${baseUrl}/assets/js/bizuser/dept-tree.js"></script>
|
||||
<script type="text/babel">
|
||||
let formPostType = 1
|
||||
RbForm.postAfter = function(){
|
||||
if (formPostType == 1) RbListPage._RbList.reload()
|
||||
let RbForm_postAfter = RbForm.postAfter
|
||||
RbForm.postAfter = function() {
|
||||
if (formPostType == 1) RbForm_postAfter()
|
||||
else loadDeptTree()
|
||||
}
|
||||
$(document).ready(function(){
|
||||
loadDeptTree()
|
||||
|
||||
$('.J_new').click(function(){ formPostType = 1 })
|
||||
$('.J_new-dept').click(function(){
|
||||
$('.J_new').click(function() { formPostType = 1 })
|
||||
$('.J_new-dept').click(function() {
|
||||
formPostType = 2
|
||||
RbFormModal.create({ title: '新建部门', entity: 'Department', icon: 'accounts' })
|
||||
})
|
||||
|
|
|
@ -11587,7 +11587,7 @@ canvas {
|
|||
}
|
||||
|
||||
.rb-top-header .navbar-nav>li.dropdown .dropdown-menu {
|
||||
border-radius: 3px;
|
||||
border-radius: 2px;
|
||||
margin-top: 12px;
|
||||
line-height: 20px
|
||||
}
|
||||
|
@ -12511,13 +12511,13 @@ a.avatar.x48 img {
|
|||
border-bottom: 1px solid #ebebeb
|
||||
}
|
||||
|
||||
.rb-notifications .notification>a {
|
||||
.rb-notifications .notification>.a {
|
||||
padding: 10px 15px;
|
||||
display: block;
|
||||
overflow: hidden
|
||||
}
|
||||
|
||||
.rb-notifications .notification>a .image {
|
||||
.rb-notifications .notification>.a .image {
|
||||
height: 38px;
|
||||
width: 38px;
|
||||
border-radius: 50%;
|
||||
|
@ -12529,7 +12529,7 @@ a.avatar.x48 img {
|
|||
width: 32px;
|
||||
}
|
||||
|
||||
.rb-notifications .notification>a .image img {
|
||||
.rb-notifications .notification>.a .image img {
|
||||
height: 38px;
|
||||
width: 38px;
|
||||
font-size: 1.923rem;
|
||||
|
@ -12540,24 +12540,24 @@ a.avatar.x48 img {
|
|||
line-height: 32px;
|
||||
}
|
||||
|
||||
.rb-notifications .notification>a .notification-info {
|
||||
.rb-notifications .notification>.a .notification-info {
|
||||
padding-left: 50px;
|
||||
line-height: 14px;
|
||||
padding-left: 44px;
|
||||
}
|
||||
|
||||
.rb-notifications .notification>a .notification-info .text {
|
||||
.rb-notifications .notification>.a .notification-info .text {
|
||||
color: #8a8a8a;
|
||||
font-size: .9231rem;
|
||||
line-height: 16px
|
||||
}
|
||||
|
||||
.rb-notifications .notification>a .notification-info .user-name {
|
||||
.rb-notifications .notification>.a .notification-info .user-name {
|
||||
color: #4285f4;
|
||||
font-size: 1rem
|
||||
}
|
||||
|
||||
.rb-notifications .notification>a .notification-info .date {
|
||||
.rb-notifications .notification>.a .notification-info .date {
|
||||
color: #8a8a8a;
|
||||
display: block;
|
||||
font-size: .6923rem;
|
||||
|
@ -12572,11 +12572,11 @@ a.avatar.x48 img {
|
|||
border-bottom: 1px solid #dce9fd
|
||||
}
|
||||
|
||||
.rb-notifications .notification.notification-unread>a {
|
||||
.rb-notifications .notification.notification-unread>.a {
|
||||
position: relative
|
||||
}
|
||||
|
||||
.rb-notifications .notification.notification-unread>a:after {
|
||||
.rb-notifications .notification.notification-unread>.a:after {
|
||||
content: '';
|
||||
display: block;
|
||||
position: absolute;
|
||||
|
@ -12597,25 +12597,25 @@ a.avatar.x48 img {
|
|||
color: #fff
|
||||
}
|
||||
|
||||
.rb-notifications .notification:hover>a .logo {
|
||||
.rb-notifications .notification:hover>.a .logo {
|
||||
background-color: #206ff2
|
||||
}
|
||||
|
||||
.rb-notifications .notification:hover>a .logo .icon {
|
||||
.rb-notifications .notification:hover>.a .logo .icon {
|
||||
color: #fff
|
||||
}
|
||||
|
||||
.rb-notifications .notification:hover>a .notification-info .circle {
|
||||
.rb-notifications .notification:hover>.a .notification-info .circle {
|
||||
background: #fff
|
||||
}
|
||||
|
||||
.rb-notifications .notification:hover>a .notification-info .date,
|
||||
.rb-notifications .notification:hover>a .notification-info .text,
|
||||
.rb-notifications .notification:hover>a .notification-info .user-name {
|
||||
.rb-notifications .notification:hover>.a .notification-info .date,
|
||||
.rb-notifications .notification:hover>.a .notification-info .text,
|
||||
.rb-notifications .notification:hover>.a .notification-info .user-name {
|
||||
color: #fff
|
||||
}
|
||||
|
||||
.rb-notifications .notification:hover>a:after {
|
||||
.rb-notifications .notification:hover>.a:after {
|
||||
background-color: #fff
|
||||
}
|
||||
|
||||
|
|
|
@ -1974,8 +1974,7 @@ form {
|
|||
z-index: 1090;
|
||||
}
|
||||
|
||||
.rb-notifications .notification>a .notification-info .text>p,
|
||||
.card-body.rb-notifications .notification>a .text>p {
|
||||
.rb-notifications .notification .text>p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
|
@ -2456,7 +2455,7 @@ form {
|
|||
padding-top: 45px
|
||||
}
|
||||
|
||||
.notification-list .notification>a {
|
||||
.notification-list .notification>.a {
|
||||
cursor: default;
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
@ -2535,6 +2534,11 @@ form {
|
|||
right: 0
|
||||
}
|
||||
|
||||
@media (max-width:768px) {
|
||||
.float-right .rb-notifications {
|
||||
right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.select2-sm .select2-container--default .select2-selection--single,
|
||||
.select2-sm .select2-container--default .select2-selection--multiple {
|
||||
|
|
41
src/main/webapp/assets/js/bizuser/dept-view.jsx
Normal file
41
src/main/webapp/assets/js/bizuser/dept-view.jsx
Normal file
|
@ -0,0 +1,41 @@
|
|||
/* global RbForm */
|
||||
let RbForm_postAfter = RbForm.postAfter
|
||||
RbForm.postAfter = function () {
|
||||
RbForm_postAfter()
|
||||
if (parent && parent.loadDeptTree) parent.loadDeptTree()
|
||||
}
|
||||
|
||||
const deleteDept = function (alert) {
|
||||
alert && alert.disabled(true)
|
||||
$.post(`${rb.baseUrl}/admin/bizuser/dept-delete?transfer=&id=${dept_id}`, (res) => {
|
||||
if (res.error_code === 0) {
|
||||
parent.location.hash = '!/View/'
|
||||
parent.location.reload()
|
||||
} else RbHighbar.error(res.error_msg)
|
||||
})
|
||||
}
|
||||
|
||||
const dept_id = window.__PageConfig.recordId
|
||||
$(document).ready(function () {
|
||||
$('.J_delete').off('click').click(() => {
|
||||
$.get(`${rb.baseUrl}/admin/bizuser/delete-checks?id=${dept_id}`, (res) => {
|
||||
if (res.data.hasMember === 0 && res.data.hasChild === 0) {
|
||||
RbAlert.create('此部门可以被安全的删除', '删除部门', {
|
||||
icon: 'alert-circle-o',
|
||||
type: 'danger',
|
||||
confirmText: '删除',
|
||||
confirm: function () { deleteDept(this) }
|
||||
})
|
||||
} else {
|
||||
let msg = '此部门下有 '
|
||||
if (res.data.hasMember > 0) msg += '<b>' + res.data.hasMember + '</b> 个用户' + (res.data.hasChild > 0 ? '和 ' : ' ')
|
||||
if (res.data.hasChild > 0) msg += '<b>' + res.data.hasChild + '</b> 个子部门'
|
||||
msg += '<br>需要先将他们转移至其他部门,然后才能安全删除'
|
||||
RbAlert.create(msg, '无法删除', {
|
||||
type: 'danger',
|
||||
html: true
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
|
@ -81,18 +81,16 @@ const loadRoles = function () {
|
|||
|
||||
action.find('a.J_del').click(function () {
|
||||
let alertExt = {
|
||||
type: 'danger', confirmText: '删除', confirm: function () {
|
||||
deleteRole(_id, this)
|
||||
}
|
||||
type: 'danger',
|
||||
confirmText: '删除',
|
||||
confirm: function () { deleteRole(_id, this) }
|
||||
}
|
||||
$.get(rb.baseUrl + '/admin/bizuser/delete-checks?id=' + _id, function (res) {
|
||||
if (res.data.hasMember === 0) {
|
||||
RbAlert.create('此角色可以被安全的删除', '删除角色', alertExt)
|
||||
RbAlert.create('此角色可以被安全的删除', '删除角色', { ...alertExt, icon: 'alert-circle-o' })
|
||||
} else {
|
||||
let url = rb.baseUrl + '/admin/bizuser/users#!/Filter/roleId=' + _id
|
||||
let msg = '有 <a href="' + url + '" target="_blank"><b>' + res.data.hasMember + '</b></a> 个用户使用了此角色<br>删除将导致这些用户被禁用,直到你为他们指定了新的角色'
|
||||
alertExt.html = true
|
||||
RbAlert.create(msg, '删除角色', alertExt)
|
||||
let msg = '有 <b>' + res.data.hasMember + '</b> 个用户使用了此角色<br>删除将导致这些用户被禁用,直到你为他们指定了新的角色'
|
||||
RbAlert.create(msg, '删除角色', { ...alertExt, html: true })
|
||||
}
|
||||
})
|
||||
})
|
||||
|
|
|
@ -4,30 +4,36 @@ $(document).ready(function () {
|
|||
$.get(rb.baseUrl + '/admin/bizuser/delete-checks?id=' + user_id, function (res) {
|
||||
if (res.data.hasMember === 0) {
|
||||
RbAlert.create('此用户可以被安全的删除', '删除用户', {
|
||||
icon: 'alert-circle-o',
|
||||
type: 'danger',
|
||||
confirmText: '删除',
|
||||
confirm: function () { deleteUser(user_id, this) }
|
||||
})
|
||||
} else {
|
||||
RbAlert.create('此用户已被使用过,因此不能删除。建议你可以将其停用', '无法删除', {
|
||||
type: 'warning',
|
||||
icon: 'alert-circle-o',
|
||||
type: 'danger',
|
||||
confirmText: '停用',
|
||||
confirm: () => { toggleDisabled(true) }
|
||||
confirm: function () { toggleDisabled(true, this) }
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
$('.J_disable').click(() => {
|
||||
RbAlert.create('确定要停用此用户吗?', { type: 'warning', confirm: () => { toggleDisabled(true) } })
|
||||
RbAlert.create('确定要停用此用户吗?', {
|
||||
confirmText: '停用',
|
||||
confirm: function () { toggleDisabled(true, this) }
|
||||
})
|
||||
$('.J_enable').click(() => { toggleDisabled(false) })
|
||||
})
|
||||
$('.J_enable').click(() => toggleDisabled(false))
|
||||
|
||||
$('.J_changeRole').click(() => { renderRbcomp(<DlgEnableUser user={user_id} role={true} />) })
|
||||
$('.J_changeDept').click(() => { renderRbcomp(<DlgEnableUser user={user_id} dept={true} />) })
|
||||
|
||||
if (rb.isAdminVerified === true) {
|
||||
$.get(rb.baseUrl + '/admin/bizuser/check-user-status?id=' + user_id, (res) => {
|
||||
if (res.error_code > 0) return
|
||||
if (res.data.system === true && rb.isAdminVerified === true) {
|
||||
$('.J_tips').removeClass('hide').find('.message p').text('系统内建超级管理员,不允许修改。此用户拥有最高级系统权限,请谨慎使用')
|
||||
$('.view-action').remove()
|
||||
|
@ -57,19 +63,20 @@ $(document).ready(function () {
|
|||
})
|
||||
|
||||
// 启用/禁用
|
||||
const toggleDisabled = function (disabled) {
|
||||
const toggleDisabled = function (disabled, alert) {
|
||||
alert && alert.disabled(true)
|
||||
let _data = { user: user_id, enable: !disabled }
|
||||
$.post(rb.baseUrl + '/admin/bizuser/enable-user', JSON.stringify(_data), (res) => {
|
||||
if (res.error_code === 0) {
|
||||
RbHighbar.create('用户已' + (disabled ? '停用' : '启用'), 'success')
|
||||
setTimeout(() => { location.reload() }, 500)
|
||||
}
|
||||
RbHighbar.success('用户已' + (disabled ? '停用' : '启用'))
|
||||
setTimeout(() => location.reload(), 500)
|
||||
} else RbHighbar.error(res.error_msg)
|
||||
})
|
||||
}
|
||||
|
||||
// 删除用户
|
||||
const deleteUser = function (id, dlg) {
|
||||
dlg.disabled(true)
|
||||
const deleteUser = function (id, alert) {
|
||||
alert && alert.disabled(true)
|
||||
$.post(rb.baseUrl + '/admin/bizuser/user-delete?id=' + id, (res) => {
|
||||
if (res.error_code === 0) {
|
||||
parent.location.hash = '!/View/'
|
||||
|
|
|
@ -43,20 +43,25 @@ class MessageList extends React.Component {
|
|||
renderItem(item) {
|
||||
// const append = item[6] === 30
|
||||
const append = item[5] && ~~item[5].substr(0, 3) !== 29 // 过滤审批步骤ID
|
||||
return <li className={`notification ${item[3] ? 'notification-unread' : ''} ${append ? 'append' : ''}`} key={item[4]} onClick={item[3] ? () => this._makeRead(item[4]) : null}><a>
|
||||
let clazz = 'notification'
|
||||
if (item[3]) clazz += ' notification-unread'
|
||||
if (append) clazz += ' append'
|
||||
return <li className={clazz} key={item[4]} onClick={item[3] ? () => this.makeRead(item(4)) : null}>
|
||||
<span className="a">
|
||||
<div className="image"><img src={`${rb.baseUrl}/account/user-avatar/${item[0][0]}`} title={item[0][1]} alt="Avatar" /></div>
|
||||
<div className="notification-info">
|
||||
<div className="text" dangerouslySetInnerHTML={{ __html: item[1] }}></div>
|
||||
<div className="date">{item[2]}</div>
|
||||
{append && <a title="查看相关记录" className="badge link" href={`${rb.baseUrl}/app/list-and-view?id=${item[5]}`}>查看</a>}
|
||||
</div>
|
||||
</a></li>
|
||||
</span>
|
||||
</li>
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
// eslint-disable-next-line react/prop-types
|
||||
if (this.props.lazy !== true) this.fetchList()
|
||||
$('.read-all').click(() => this._makeRead('ALL'))
|
||||
$('.read-all').click(() => this.makeRead('ALL'))
|
||||
}
|
||||
|
||||
fetchList(page, type) {
|
||||
|
@ -69,7 +74,12 @@ class MessageList extends React.Component {
|
|||
})
|
||||
})
|
||||
}
|
||||
__setLink = () => $(this._list).find('.notification-info a').attr('target', '_blank').addClass('link')
|
||||
__setLink = () => {
|
||||
$(this._list).find('.notification-info a').attr('target', '_blank').addClass('link')
|
||||
.click('click', (e) => {
|
||||
if (e && e.stopPropagation) e.stopPropagation()
|
||||
})
|
||||
}
|
||||
|
||||
gotoPage(p) {
|
||||
if (p === -1 && this.state.page === 1) return
|
||||
|
@ -77,7 +87,7 @@ class MessageList extends React.Component {
|
|||
this.fetchList(this.state.page + p, null)
|
||||
}
|
||||
|
||||
_makeRead(id) {
|
||||
makeRead(id) {
|
||||
if (!id) return
|
||||
$.post(`${rb.baseUrl}/notification/make-read?id=${id}`, () => {
|
||||
let list = (this.state.list || []).map((item) => {
|
||||
|
|
|
@ -155,10 +155,7 @@ class RbFormHandler extends RbModalHandler {
|
|||
|
||||
// ~~ 提示框
|
||||
class RbAlert extends React.Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
this.state = { disable: false }
|
||||
}
|
||||
state = { ...this.props, disable: false }
|
||||
render() {
|
||||
let style = {}
|
||||
if (this.props.width) style.maxWidth = ~~this.props.width
|
||||
|
@ -177,11 +174,12 @@ class RbAlert extends React.Component {
|
|||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
renderContent() {
|
||||
let icon = this.props.type === 'danger' ? 'alert-triangle' : 'help-outline'
|
||||
if (this.props.type === 'warning') icon = 'alert-circle-o'
|
||||
if (this.props.type === 'primary') icon = 'info-outline'
|
||||
let type = this.props.type || 'primary'
|
||||
const type = this.props.type || 'primary'
|
||||
let icon = this.props.icon
|
||||
if (!icon) icon = type === 'danger' ? 'alert-triangle' : (type === 'primary' ? 'help-outline' : 'alert-circle-o')
|
||||
|
||||
let content = this.props.htmlMessage ?
|
||||
<div className="mt-3" style={{ lineHeight: 1.8 }} dangerouslySetInnerHTML={{ __html: this.props.htmlMessage }} />
|
||||
: <p>{this.props.message || 'INMESSAGE'}</p>
|
||||
|
@ -190,9 +188,7 @@ class RbAlert extends React.Component {
|
|||
let confirm = (this.props.confirm || this.hide).bind(this)
|
||||
|
||||
return <div className="text-center ml-6 mr-6">
|
||||
{this.props.showIcon === false ? null :
|
||||
<div className={'text-' + type}><span className={'modal-main-icon zmdi zmdi-' + icon} /></div>
|
||||
}
|
||||
<div className={`text-${type}`}><i className={`modal-main-icon zmdi zmdi-${icon}`} /></div>
|
||||
{this.props.title && <h4 className="mb-2 mt-3">{this.props.title}</h4>}
|
||||
<div className={this.props.title ? '' : 'mt-3'}>{content}</div>
|
||||
<div className="mt-4 mb-3">
|
||||
|
|
|
@ -187,7 +187,7 @@ var __loadMessages = function () {
|
|||
$(res.data).each(function (idx, item) {
|
||||
var o = $('<li class="notification"></li>').appendTo(dest)
|
||||
if (item[3] === true) o.addClass('notification-unread')
|
||||
o = $('<a href="' + rb.baseUrl + '/notifications#id=' + item[4] + '"></a>').appendTo(o)
|
||||
o = $('<a class="a" href="' + rb.baseUrl + '/notifications#' + (item[3] ? 'unread' : 'read') + '"></a>').appendTo(o)
|
||||
$('<div class="image"><img src="' + rb.baseUrl + '/account/user-avatar/' + item[0][0] + '" alt="Avatar"></div>').appendTo(o)
|
||||
o = $('<div class="notification-info"></div>').appendTo(o)
|
||||
$('<div class="text text-truncate">' + item[1] + '</div>').appendTo(o)
|
||||
|
|
|
@ -32,11 +32,13 @@ public class SMSenderTest extends TestSupport {
|
|||
@Ignore
|
||||
@Test
|
||||
public void testSendSMS() throws Exception {
|
||||
SMSender.availableSMS();
|
||||
SMSender.sendSMS("17187472172", "SMSenderTest#testSendSMS");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSendMail() throws Exception {
|
||||
SMSender.availableMail();
|
||||
SMSender.sendMail("getrebuild@sina.com", "SMSenderTest#testSendMail", "test content");
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue