Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
开发团队
Flowable Engine
提交
9ecff4d3
F
Flowable Engine
项目概览
开发团队
/
Flowable Engine
通知
9
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
F
Flowable Engine
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
9ecff4d3
编写于
3月 26, 2011
作者:
J
jbarrez
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
ACT-696: Added login page + authentication check
上级
ab6cc11c
变更
9
隐藏空白更改
内联
并排
Showing
9 changed file
with
424 addition
and
68 deletion
+424
-68
modules/activiti-webapp-explorer2/src/main/java/org/activiti/explorer/Constants.java
...lorer2/src/main/java/org/activiti/explorer/Constants.java
+4
-0
modules/activiti-webapp-explorer2/src/main/java/org/activiti/explorer/ExplorerApplication.java
.../main/java/org/activiti/explorer/ExplorerApplication.java
+21
-65
modules/activiti-webapp-explorer2/src/main/java/org/activiti/explorer/MainWindow.java
...orer2/src/main/java/org/activiti/explorer/MainWindow.java
+111
-0
modules/activiti-webapp-explorer2/src/main/java/org/activiti/explorer/ui/MainLayout.java
...r2/src/main/java/org/activiti/explorer/ui/MainLayout.java
+5
-3
modules/activiti-webapp-explorer2/src/main/java/org/activiti/explorer/ui/login/CustomLoginForm.java
.../java/org/activiti/explorer/ui/login/CustomLoginForm.java
+105
-0
modules/activiti-webapp-explorer2/src/main/java/org/activiti/explorer/ui/login/LoginPage.java
...c/main/java/org/activiti/explorer/ui/login/LoginPage.java
+77
-0
modules/activiti-webapp-explorer2/src/main/webapp/VAADIN/themes/activiti/img/explorer-logo.png
.../main/webapp/VAADIN/themes/activiti/img/explorer-logo.png
+0
-0
modules/activiti-webapp-explorer2/src/main/webapp/VAADIN/themes/activiti/layouts/login.html
...src/main/webapp/VAADIN/themes/activiti/layouts/login.html
+17
-0
modules/activiti-webapp-explorer2/src/main/webapp/VAADIN/themes/activiti/styles.css
...plorer2/src/main/webapp/VAADIN/themes/activiti/styles.css
+84
-0
未找到文件。
modules/activiti-webapp-explorer2/src/main/java/org/activiti/explorer/Constants.java
浏览文件 @
9ecff4d3
...
...
@@ -23,14 +23,18 @@ import java.text.SimpleDateFormat;
public
class
Constants
{
public
static
final
String
THEME
=
"activiti"
;
public
static
final
String
LOGIN_LAYOUT
=
"login"
;
// Locations in the general layout
public
static
final
String
LOCATION_LOGIN
=
"login-content"
;
public
static
final
String
LOCATION_CONTENT
=
"content"
;
public
static
final
String
LOCATION_SEARCH
=
"search"
;
public
static
final
String
LOCATION_MAIN_MENU
=
"main-menu"
;
public
static
final
String
LOCATION_HIDDEN
=
"hidden"
;
// Css styles
public
static
final
String
STYLE_LOGIN_PAGE
=
"login-general"
;
public
static
final
String
STYLE_SMALL_TEXTFIELD
=
"small"
;
public
static
final
String
STYLE_SEARCHBOX
=
"searchBox"
;
public
static
final
String
STYLE_LOGOUT_BUTTON
=
"logout"
;
...
...
modules/activiti-webapp-explorer2/src/main/java/org/activiti/explorer/ExplorerApplication.java
浏览文件 @
9ecff4d3
...
...
@@ -18,18 +18,14 @@ package org.activiti.explorer;
import
javax.servlet.http.HttpServletRequest
;
import
javax.servlet.http.HttpServletResponse
;
import
org.activiti.engine.ProcessEngines
;
import
org.activiti.engine.identity.User
;
import
org.activiti.engine.impl.identity.Authentication
;
import
org.activiti.engine.impl.util.LogUtil
;
import
org.activiti.explorer.navigation.NavigationFragmentChangeListener
;
import
org.activiti.explorer.navigation.UriFragment
;
import
org.activiti.explorer.ui.MainLayout
;
import
com.vaadin.Application
;
import
com.vaadin.terminal.gwt.server.HttpServletRequestListener
;
import
com.vaadin.ui.Component
;
import
com.vaadin.ui.UriFragmentUtility
;
import
com.vaadin.ui.Window
;
import
com.vaadin.ui.Window.Notification
;
...
...
@@ -46,30 +42,12 @@ public class ExplorerApplication extends Application implements HttpServletReque
private
static
ThreadLocal
<
ExplorerApplication
>
current
=
new
ThreadLocal
<
ExplorerApplication
>();
protected
Window
mainWindow
;
protected
MainLayout
mainLayout
;
protected
UriFragmentUtility
uriFragmentUtility
;
protected
UriFragment
currentUriFragment
;
protected
MainWindow
mainWindow
;
public
void
init
()
{
// Demo
setUser
(
ProcessEngines
.
getDefaultProcessEngine
().
getIdentityService
()
.
createUserQuery
().
userId
(
"kermit"
).
singleResult
());
ProcessEngines
.
getDefaultProcessEngine
().
getIdentityService
().
setAuthenticatedUserId
(
"kermit"
);
// Demo
// init window
mainWindow
=
new
Window
(
"Explorer - The Next generation"
);
this
.
mainWindow
=
new
MainWindow
();
setMainWindow
(
mainWindow
);
setTheme
(
Constants
.
THEME
);
// init general look and feel
mainLayout
=
new
MainLayout
(
this
);
mainWindow
.
setContent
(
mainLayout
);
// init hidden components
initHiddenComponents
();
mainWindow
.
showLoginPage
();
}
/**
...
...
@@ -95,7 +73,15 @@ public class ExplorerApplication extends Application implements HttpServletReque
}
public
void
switchView
(
Component
component
)
{
mainLayout
.
addComponent
(
component
,
Constants
.
LOCATION_CONTENT
);
mainWindow
.
switchView
(
component
);
}
public
void
showLoginPage
()
{
mainWindow
.
showLoginPage
();
}
public
void
showDefaultContent
()
{
mainWindow
.
showDefaultContent
();
}
public
User
getLoggedInUser
()
{
...
...
@@ -120,10 +106,15 @@ public class ExplorerApplication extends Application implements HttpServletReque
// Set current application object as thread-local to make it easy accessible
current
.
set
(
this
);
// Set thread-local userid of logged in user (needed for Activiti user logic)
// Authentication: check if user is found, otherwise send to login page
User
user
=
(
User
)
getUser
();
if
(
user
!=
null
)
{
Authentication
.
setAuthenticatedUserId
(
"kermit"
);
if
(
user
==
null
)
{
if
(
mainWindow
!=
null
&&
!
mainWindow
.
isShowingLoginPage
())
{
showLoginPage
();
}
}
else
{
// Set thread-local userid of logged in user (needed for Activiti user logic)
Authentication
.
setAuthenticatedUserId
(
user
.
getId
());
}
}
...
...
@@ -135,42 +126,7 @@ public class ExplorerApplication extends Application implements HttpServletReque
// URL handling ---------------------------------------------------------------------------------
protected
void
initHiddenComponents
()
{
// Add the URI Fragent utility
uriFragmentUtility
=
new
UriFragmentUtility
();
mainLayout
.
addComponent
(
uriFragmentUtility
,
Constants
.
LOCATION_HIDDEN
);
// Add listener to control page flow based on URI
uriFragmentUtility
.
addListener
(
new
NavigationFragmentChangeListener
());
}
public
UriFragment
getCurrentUriFragment
()
{
return
currentUriFragment
;
}
/**
* Sets the current {@link UriFragment}.
* Won't trigger navigation, just updates the URI fragment in the browser.
*/
public
void
setCurrentUriFragment
(
UriFragment
fragment
)
{
this
.
currentUriFragment
=
fragment
;
if
(
fragmentChanged
(
fragment
))
{
if
(
fragment
!=
null
)
{
uriFragmentUtility
.
setFragment
(
fragment
.
toString
(),
false
);
}
else
{
uriFragmentUtility
.
setFragment
(
""
,
false
);
}
}
}
private
boolean
fragmentChanged
(
UriFragment
fragment
)
{
String
fragmentString
=
fragment
.
toString
();
if
(
fragmentString
==
null
)
{
return
uriFragmentUtility
.
getFragment
()
!=
null
;
}
else
{
return
!
fragmentString
.
equals
(
uriFragmentUtility
.
getFragment
());
}
mainWindow
.
setCurrentUriFragment
(
fragment
);
}
}
modules/activiti-webapp-explorer2/src/main/java/org/activiti/explorer/MainWindow.java
0 → 100644
浏览文件 @
9ecff4d3
/* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
org.activiti.explorer
;
import
org.activiti.explorer.navigation.NavigationFragmentChangeListener
;
import
org.activiti.explorer.navigation.UriFragment
;
import
org.activiti.explorer.ui.MainLayout
;
import
org.activiti.explorer.ui.login.LoginPage
;
import
com.vaadin.ui.Component
;
import
com.vaadin.ui.UriFragmentUtility
;
import
com.vaadin.ui.Window
;
/**
* @author Joram Barrez
*/
public
class
MainWindow
extends
Window
{
private
static
final
long
serialVersionUID
=
1L
;
protected
MainLayout
mainLayout
;
protected
UriFragmentUtility
uriFragmentUtility
;
protected
UriFragment
currentUriFragment
;
protected
boolean
showingLoginPage
;
public
MainWindow
()
{
super
(
"Explorer - The Next generation"
);
setTheme
(
Constants
.
THEME
);
}
public
void
showLoginPage
()
{
showingLoginPage
=
true
;
addStyleName
(
Constants
.
STYLE_LOGIN_PAGE
);
setContent
(
new
LoginPage
());
}
public
void
showDefaultContent
()
{
showingLoginPage
=
false
;
removeStyleName
(
Constants
.
STYLE_LOGIN_PAGE
);
addStyleName
(
"Default style"
);
// Bug: must set something or old style is not overwritten
// init general look and feel
mainLayout
=
new
MainLayout
();
setContent
(
mainLayout
);
// init hidden components
initHiddenComponents
();
}
// View handling
public
void
switchView
(
Component
component
)
{
mainLayout
.
addComponent
(
component
,
Constants
.
LOCATION_CONTENT
);
}
// URL handling
protected
void
initHiddenComponents
()
{
// Add the URI Fragent utility
uriFragmentUtility
=
new
UriFragmentUtility
();
mainLayout
.
addComponent
(
uriFragmentUtility
,
Constants
.
LOCATION_HIDDEN
);
// Add listener to control page flow based on URI
uriFragmentUtility
.
addListener
(
new
NavigationFragmentChangeListener
());
}
public
UriFragment
getCurrentUriFragment
()
{
return
currentUriFragment
;
}
/**
* Sets the current {@link UriFragment}.
* Won't trigger navigation, just updates the URI fragment in the browser.
*/
public
void
setCurrentUriFragment
(
UriFragment
fragment
)
{
this
.
currentUriFragment
=
fragment
;
if
(
fragmentChanged
(
fragment
))
{
if
(
fragment
!=
null
)
{
uriFragmentUtility
.
setFragment
(
fragment
.
toString
(),
false
);
}
else
{
uriFragmentUtility
.
setFragment
(
""
,
false
);
}
}
}
private
boolean
fragmentChanged
(
UriFragment
fragment
)
{
String
fragmentString
=
fragment
.
toString
();
if
(
fragmentString
==
null
)
{
return
uriFragmentUtility
.
getFragment
()
!=
null
;
}
else
{
return
!
fragmentString
.
equals
(
uriFragmentUtility
.
getFragment
());
}
}
public
boolean
isShowingLoginPage
()
{
return
showingLoginPage
;
}
}
modules/activiti-webapp-explorer2/src/main/java/org/activiti/explorer/ui/MainLayout.java
浏览文件 @
9ecff4d3
...
...
@@ -13,6 +13,7 @@
package
org.activiti.explorer.ui
;
import
org.activiti.engine.identity.User
;
import
org.activiti.explorer.Constants
;
import
org.activiti.explorer.ExplorerApplication
;
import
org.activiti.explorer.Images
;
...
...
@@ -36,7 +37,7 @@ public class MainLayout extends CustomLayout {
protected
MainMenuBar
mainMenuBar
;
public
MainLayout
(
ExplorerApplication
explorerApplication
)
{
public
MainLayout
()
{
super
(
Constants
.
THEME
);
setSizeFull
();
...
...
@@ -61,14 +62,15 @@ public class MainLayout extends CustomLayout {
logoutGrid
.
setStyleName
(
Constants
.
STYLE_LOGOUT_BUTTON
);
// User name + link to profile
Button
userButton
=
new
Button
(
"Kermit The Frog"
);
final
User
user
=
ExplorerApplication
.
getCurrent
().
getLoggedInUser
();
Button
userButton
=
new
Button
(
user
.
getFirstName
()
+
" "
+
user
.
getLastName
());
userButton
.
setIcon
(
Images
.
USER
);
userButton
.
addStyleName
(
Constants
.
STYLE_USER_LABEL
);
userButton
.
addStyleName
(
Reindeer
.
BUTTON_LINK
);
userButton
.
addListener
(
new
ClickListener
()
{
public
void
buttonClick
(
ClickEvent
event
)
{
ExplorerApplication
.
getCurrent
().
switchView
(
new
ProfilePage
(
"kermit"
));
ExplorerApplication
.
getCurrent
().
switchView
(
new
ProfilePage
(
user
.
getId
()
));
}
});
...
...
modules/activiti-webapp-explorer2/src/main/java/org/activiti/explorer/ui/login/CustomLoginForm.java
0 → 100644
浏览文件 @
9ecff4d3
/* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
org.activiti.explorer.ui.login
;
import
org.activiti.explorer.Constants
;
import
com.vaadin.ui.LoginForm
;
/**
* @author Joram Barrez
*/
public
class
CustomLoginForm
extends
LoginForm
{
private
static
final
long
serialVersionUID
=
1L
;
protected
String
usernameCaption
;
protected
String
passwordCaption
;
protected
String
submitCaption
;
protected
static
final
String
STYLE_LOGIN_FIELD
=
"login-field"
;
protected
static
final
String
STYLE_LOGIN_FIELD_CAPTION
=
"login-field-caption"
;
protected
static
final
String
STYLE_LOGIN_BUTTON
=
"login-button"
;
public
CustomLoginForm
()
{
usernameCaption
=
"User ID"
;
passwordCaption
=
"Password"
;
submitCaption
=
"Log in"
;
}
// Hack-alert !! See explanation at http://vaadin.com/book/-/page/components.loginform.html
protected
byte
[]
getLoginHTML
()
{
// Application URI needed for submitting form
String
appUri
=
getApplication
().
getURL
().
toString
()
+
getWindow
().
getName
()
+
"/"
;
String
x
,
h
,
b
;
// XML header, HTML head and body
x
=
"<!DOCTYPE html PUBLIC \"-//W3C//DTD "
+
"XHTML 1.0 Transitional//EN\" "
+
"\"http://www.w3.org/TR/xhtml1/"
+
"DTD/xhtml1-transitional.dtd\">\n"
;
h
=
"<head><script type='text/javascript'>"
+
"var setTarget = function() {"
+
" var uri = '"
+
appUri
+
"loginHandler';"
+
" var f = document.getElementById('loginf');"
+
" document.forms[0].action = uri;"
+
" document.forms[0].username.focus();"
+
"};"
+
""
+
"var styles = window.parent.document.styleSheets;"
+
"for(var j = 0; j < styles.length; j++) {\n"
+
" if(styles[j].href) {"
+
" var stylesheet = document.createElement('link');\n"
+
" stylesheet.setAttribute('rel', 'stylesheet');\n"
+
" stylesheet.setAttribute('type', 'text/css');\n"
+
" stylesheet.setAttribute('href', styles[j].href);\n"
+
" document.getElementsByTagName('head')[0]"
+
" .appendChild(stylesheet);\n"
+
" }"
+
"}\n"
+
"function submitOnEnter(e) {"
+
" var keycode = e.keyCode || e.which;"
+
" if (keycode == 13) {document.forms[0].submit();}"
+
"}\n"
+
"</script>"
+
"</head>"
;
b
=
"<body onload='setTarget();'"
+
" class='"
+
Constants
.
STYLE_LOGIN_PAGE
+
"'>"
// todo
+
"<div>"
+
"<iframe name='logintarget' style='width:0;height:0;"
+
"border:0;margin:0;padding:0;'></iframe>"
+
"<form id='loginf' target='logintarget'"
+
" onkeypress='submitOnEnter(event)'"
+
" method='post'>"
+
"<table>"
+
"<tr><td class='"
+
STYLE_LOGIN_FIELD_CAPTION
+
"'>"
+
usernameCaption
+
"</td>"
+
"<td><input class='"
+
STYLE_LOGIN_FIELD
+
"' type='text' name='username'></td></tr>"
+
"<tr><td class='"
+
STYLE_LOGIN_FIELD_CAPTION
+
"'>"
+
passwordCaption
+
"</td>"
+
" <td><input class='"
+
STYLE_LOGIN_FIELD
+
"'"
+
" type='password'"
+
" name='password'></td></tr>"
+
"</table>"
+
"<div>"
+
"<div onclick='document.forms[0].submit();'"
+
" tabindex='0' class='"
+
STYLE_LOGIN_BUTTON
+
"' role='button'>"
+
"<span>"
+
submitCaption
+
"</span>"
+
"</span></div></div></form></div></body>"
;
return
(
x
+
"<html>"
+
h
+
b
+
"</html>"
).
getBytes
();
}
}
modules/activiti-webapp-explorer2/src/main/java/org/activiti/explorer/ui/login/LoginPage.java
0 → 100644
浏览文件 @
9ecff4d3
/* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
org.activiti.explorer.ui.login
;
import
org.activiti.engine.IdentityService
;
import
org.activiti.engine.ProcessEngines
;
import
org.activiti.engine.identity.User
;
import
org.activiti.explorer.Constants
;
import
org.activiti.explorer.ExplorerApplication
;
import
com.vaadin.ui.CustomLayout
;
import
com.vaadin.ui.LoginForm.LoginEvent
;
import
com.vaadin.ui.LoginForm.LoginListener
;
/**
* @author Joram Barrez
*/
public
class
LoginPage
extends
CustomLayout
{
private
static
final
long
serialVersionUID
=
1L
;
protected
IdentityService
identityService
=
ProcessEngines
.
getDefaultProcessEngine
().
getIdentityService
();
public
LoginPage
()
{
super
(
Constants
.
LOGIN_LAYOUT
);
// Layout is defined in /activiti/login.html + styles.css
addStyleName
(
Constants
.
STYLE_LOGIN_PAGE
);
initUi
();
}
protected
void
initUi
()
{
// Login form is an atypical Vaadin component, since we want browsers to fill the password fields
CustomLoginForm
loginForm
=
new
CustomLoginForm
();
addComponent
(
loginForm
,
Constants
.
LOCATION_LOGIN
);
// Login listener
loginForm
.
addListener
(
new
ActivitiLoginListener
());
}
protected
void
refreshUi
()
{
// Quick and dirty 'refresh'
removeAllComponents
();
initUi
();
}
class
ActivitiLoginListener
implements
LoginListener
{
private
static
final
long
serialVersionUID
=
1L
;
public
void
onLogin
(
LoginEvent
event
)
{
String
userName
=
event
.
getLoginParameter
(
"username"
);
// see the input field names in CustomLoginForm
String
password
=
event
.
getLoginParameter
(
"password"
);
// see the input field names in CustomLoginForm
boolean
success
=
identityService
.
checkPassword
(
userName
,
password
);
if
(
success
)
{
User
user
=
identityService
.
createUserQuery
().
userId
(
userName
).
singleResult
();
ExplorerApplication
.
getCurrent
().
setUser
(
user
);
ExplorerApplication
.
getCurrent
().
showDefaultContent
();
}
else
{
refreshUi
();
ExplorerApplication
.
getCurrent
().
showErrorNotification
(
"Could not log you in"
,
"Invalid user id and/or password"
);
}
}
}
}
modules/activiti-webapp-explorer2/src/main/webapp/VAADIN/themes/activiti/img/explorer-logo.png
0 → 100644
浏览文件 @
9ecff4d3
11.7 KB
modules/activiti-webapp-explorer2/src/main/webapp/VAADIN/themes/activiti/layouts/login.html
0 → 100644
浏览文件 @
9ecff4d3
<div
class=
"login-general"
>
<div
id=
"login-central-components"
>
<div
id=
"login-logo"
>
<img
src=
"../img/explorer-logo.png"
>
</div>
<div
id=
"login-content"
location=
"login-content"
>
</div>
</div>
<div
id=
"login-background"
></div>
</div>
modules/activiti-webapp-explorer2/src/main/webapp/VAADIN/themes/activiti/styles.css
浏览文件 @
9ecff4d3
@import
url(../reindeer/styles.css)
;
/* -----
Login
----- */
/* General backrgound and font settings */
.login-general
{
color
:
white
;
/* color of text */
font-family
:
Helvetica
,
Arial
,
sans-serif
;
background
:
#1b7ec3
;
/* non-white part of page */
font-size
:
16px
;
font-weight
:
bold
;
}
#login-content
{
height
:
200px
;
}
/* white part of background */
#login-background
{
position
:
absolute
;
top
:
0
;
left
:
0
;
background
:
white
;
height
:
250px
;
width
:
100%
;
border-bottom
:
solid
3px
#a9b3ba
;
/* gray-blueish horitzontal line in the middle */
}
#login-central-components
{
margin
:
0
0
0
-185px
;
width
:
370px
;
text-align
:
center
;
position
:
absolute
;
left
:
50%
;
z-index
:
1
;
}
#login-logo
{
height
:
130px
;
padding-top
:
140px
;
}
/* Text fields of input form */
input
.login-field
{
font-size
:
16px
;
height
:
40px
;
width
:
250px
;
margin-left
:
10px
;
padding-left
:
7px
;
/* To start the typing of the text a bit to the right */
float
:
right
;
background
:
white
;
border
:
solid
1px
transparent
;
margin-bottom
:
2px
;
-moz-border-radius
:
4px
;
-webkit-border-radius
:
4px
;
}
.login-field-caption
{
line-height
:
200%
}
/* 'Log in' Button */
.login-button
{
text-align
:
center
;
line-height
:
200%
;
float
:
right
;
width
:
80px
;
height
:
30px
;
margin-top
:
5px
;
color
:
white
;
font-size
:
14px
;
background-color
:
#55ba49
;
border
:
solid
1px
transparent
;
font-weight
:
bold
;
letter-spacing
:
1px
;
cursor
:
pointer
;
-moz-border-radius
:
4px
;
-webkit-border-radius
:
4px
;
}
.login-button
:hover
{
background-color
:
#86e379
;
}
/* ----------
Main layout
----------- */
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录