@@ -41,6 +41,8 @@ | |||
"element-ui": "2.13.0", | |||
"ezuikit-js": "^0.6.1", | |||
"jquery": "3.4.1", | |||
"js-cookie": "^2.2.1", | |||
"jsencrypt": "^3.0.0-rc.1", | |||
"ol": "6.1.1", | |||
"proj4": "2.5.0", | |||
"v-scale-screen": "^1.0.2", | |||
@@ -1,10 +1,40 @@ | |||
import request from '@/utils/request'; | |||
import { encrypt } from '@/utils/jsencrypt' // 公钥,私钥都声明在里面 | |||
// 获取用户详细信息 | |||
export function getInfo () { | |||
return request({ | |||
url: 'api/getInfo', | |||
url: '/api/getInfo', | |||
method: 'get' | |||
}) | |||
} | |||
// 登录方法 | |||
export function login (username, password, code, uuid) { | |||
const data = { | |||
username, | |||
password, | |||
code, | |||
uuid | |||
} | |||
data.username = encrypt(username); | |||
data.password = encrypt(password); | |||
return request({ | |||
url: 'api/login', | |||
method: 'post', | |||
data: data | |||
}) | |||
} | |||
export function getCodeImg () { | |||
return request({ | |||
url: '/api/gkyzm', | |||
method: 'get' | |||
}) | |||
} | |||
// 退出方法 | |||
export function logout () { | |||
return request({ | |||
url: '/api/logout', | |||
method: 'post' | |||
}) | |||
} |
@@ -1,18 +1,193 @@ | |||
import router from './router'; | |||
import store from './store'; | |||
const whiteList = ['/login']; // 不重定向白名单 | |||
import router from './router' | |||
import store from './store' | |||
import { Message } from 'element-ui' | |||
import NProgress from 'nprogress' | |||
import 'nprogress/nprogress.css' | |||
import { getToken } from '@/utils/auth' | |||
import { getDicts } from "@/api/system/dict/data"; | |||
import Cookies from "js-cookie"; | |||
NProgress.configure({ showSpinner: false }) | |||
const whiteList = [ | |||
'/login', | |||
'/login_index', | |||
'/auth-redirect', | |||
'/bind', | |||
'/register', | |||
'/login_deposit', | |||
'/loginSingle', | |||
'/login_enforce', | |||
'/login_house', | |||
'/login_trans', | |||
'/login_finance', | |||
'/login_society', | |||
'/login_three', | |||
'/login_land', | |||
'/login_item', | |||
'/login_company', | |||
'/login_entity', | |||
'/login_yinnong', | |||
'/login_chungeng', | |||
// '/login_test', | |||
] | |||
router.beforeEach((to, from, next) => { | |||
if (store.getters.loginInfo) { | |||
NProgress.start() | |||
if (store.getters.systemConfigList.length == 0) { | |||
store.dispatch('systemTitle').then(() => { | |||
document.title = store.getters.browserName == '' ? '农经综合信息管理平台' : store.getters.browserName | |||
}) | |||
} | |||
if (getToken()) { | |||
/* has token*/ | |||
if (to.path === '/login') { | |||
next({ path: '/login' }); | |||
next({ path: '/' }) | |||
NProgress.done() | |||
} else { | |||
next(); | |||
if (store.getters.roles.length === 0) { | |||
// 判断当前用户是否已拉取完user_info信息 | |||
store.dispatch('GetInfo').then(res => { | |||
if (res && res.code && res.code == 200) { | |||
// 拉取user_info | |||
let businessOwnerList = res.user.businessOwnership; | |||
if (businessOwnerList != null) { | |||
getDicts("business_ownership").then((response) => { | |||
let businessOwnerArr = businessOwnerList.split(',') | |||
let businessOwnerArrSort = businessOwnerArr.sort((a, b) => {//升序 | |||
return a - b | |||
}); | |||
let arrLable = [] | |||
response.data.forEach((v, i) => { | |||
businessOwnerArr.forEach((data, length) => { | |||
if (v.dictValue == data) { | |||
arrLable.push({ | |||
dictValue: v.dictValue, | |||
dictLabel: v.dictLabel, | |||
remark: v.remark, | |||
dictSort: v.dictSort | |||
}) | |||
} | |||
}) | |||
}) | |||
let routerId = window.localStorage.getItem("routerId"); | |||
let bookType = res.user.bookType; | |||
let endDictValue; | |||
const viewPagesProfileId = Cookies.get("viewPagesProfileId"); | |||
if ( | |||
viewPagesProfileId == undefined || | |||
viewPagesProfileId == "" || | |||
viewPagesProfileId == null | |||
) { | |||
if (routerId == null || businessOwnerArrSort.includes(routerId) == false) { | |||
if (businessOwnerArrSort.includes("1") || businessOwnerArrSort.includes("2") || businessOwnerArrSort.includes("3")) { | |||
if (bookType == 1) { | |||
endDictValue = 1; | |||
} else if (bookType == 2) { | |||
endDictValue = 2; | |||
} else if (bookType == 3) { | |||
endDictValue = 3; | |||
} else if (bookType == 8) { | |||
endDictValue = 8; | |||
} else { | |||
endDictValue = arrLable[0].dictValue | |||
} | |||
} else { | |||
endDictValue = arrLable[0].dictValue | |||
} | |||
} else { | |||
if (businessOwnerArrSort.includes("1") || businessOwnerArrSort.includes("2") || businessOwnerArrSort.includes("3") || businessOwnerArrSort.includes("8")) { | |||
if (bookType == 1) { | |||
if (routerId == 2 || routerId == 3 || routerId == 8) { | |||
endDictValue = 1; | |||
} else { | |||
endDictValue = routerId; | |||
} | |||
} else if (bookType == 2) { | |||
if (routerId == 1 || routerId == 3 || routerId == 8) { | |||
endDictValue = 2; | |||
} else { | |||
endDictValue = routerId; | |||
} | |||
} else if (bookType == 3) { | |||
if (routerId == 2 || routerId == 1 || routerId == 8) { | |||
endDictValue = 3; | |||
} else { | |||
endDictValue = routerId; | |||
} | |||
} else if (bookType == 8) { | |||
if (routerId == 1 || routerId == 2 || routerId == 3) { | |||
endDictValue = 8; | |||
} else { | |||
endDictValue = routerId; | |||
} | |||
} else { | |||
endDictValue = routerId; | |||
} | |||
} else { | |||
if (routerId) { | |||
endDictValue = routerId; | |||
} else { | |||
endDictValue = arrLable[0].dictValue | |||
} | |||
} | |||
} | |||
} else { | |||
endDictValue = viewPagesProfileId; | |||
} | |||
store.dispatch('GenerateRoutes', endDictValue).then(accessRoutes => { | |||
// 根据roles权限生成可访问的路由表 | |||
router.addRoutes(accessRoutes) // 动态添加可访问路由表 | |||
next({ ...to, replace: true }) // hack方法 确保addRoutes已完成 | |||
}) | |||
}) | |||
} else { | |||
store.dispatch('GenerateRoutes', 'no-router').then(accessRoutes => { | |||
// 根据roles权限生成可访问的路由表 | |||
router.addRoutes(accessRoutes) // 动态添加可访问路由表 | |||
next({ ...to, replace: true }) // hack方法 确保addRoutes已完成 | |||
}) | |||
} | |||
} | |||
}).catch(err => { | |||
store.dispatch('LogOut').then(() => { | |||
Message.error(err) | |||
next({ path: '/' }) | |||
}) | |||
}) | |||
} else { | |||
next() | |||
} | |||
} | |||
} else { | |||
// 没有token | |||
if (whiteList.indexOf(to.path) !== -1) { | |||
next(); | |||
// 在免登录白名单,直接进入 | |||
next() | |||
} else if (to.path.indexOf('dataScreen') != -1) { | |||
next() | |||
} else if (to.path.indexOf('subcontract') != -1) { | |||
next() | |||
} else { | |||
next(`/login?redirect=${to.path}`); // 否则全部重定向到登录页 | |||
if (to.query && to.query.code && to.query.exiturl) { | |||
next(`/login?code=${to.query.code}&exiturl=${to.query.exiturl}`) | |||
} else { | |||
next(`/login?redirect=${to.fullPath}`) // 否则全部重定向到登录页 | |||
} | |||
//next(`/zjdLogin?redirect=${to.fullPath}`) // 否则全部重定向到登录页 | |||
NProgress.done() | |||
} | |||
} | |||
}); | |||
}) | |||
router.afterEach(() => { | |||
NProgress.done() | |||
}) |
@@ -6,7 +6,13 @@ const routes = [ | |||
{ | |||
path: '/', | |||
name: 'root', | |||
redirect: '/capital' | |||
redirect: '/login' | |||
}, | |||
// 资金 | |||
{ | |||
path: '/nav', | |||
name: 'nav', | |||
component: () => import('@/views/nav/index.vue') | |||
}, | |||
// 资金 | |||
{ | |||
@@ -14,6 +20,11 @@ const routes = [ | |||
name: 'capital', | |||
component: () => import('@/views/capital/index.vue') | |||
}, | |||
{ | |||
path: '/login', | |||
name: 'login', | |||
component: () => import('@/views/login/index.vue') | |||
}, | |||
// 资源 | |||
{ | |||
path: '/resources', | |||
@@ -1,27 +0,0 @@ | |||
import { login } from '@/api/login.js'; | |||
import { setToken } from '@/utils/auth'; | |||
import { Message } from 'element-ui'; | |||
export const actions = { | |||
// 登录 | |||
Login ({ commit }, params) { | |||
return new Promise((resolve, reject) => { | |||
login(params).then(response => { | |||
if (response.code !== '0') { | |||
Message({ | |||
message: response.reason, | |||
type: 'error', | |||
duration: 2000 | |||
}); | |||
resolve(); | |||
}; | |||
const data = response.data; | |||
commit('SET_LOGIN_INFO', data); | |||
setToken(data.token); | |||
resolve(); | |||
}).catch(error => { | |||
reject(error); | |||
}); | |||
}); | |||
} | |||
}; |
@@ -1,6 +0,0 @@ | |||
export const getters = { | |||
areaCode: state => state.areaCode, | |||
loginInfo: state => state.loginInfo, | |||
industrialSubjectOccupancy: state => state.industrialSubjectOccupancy, | |||
currentLayerName: state => state.currentLayerName | |||
}; |
@@ -1,11 +0,0 @@ | |||
import { state } from './state'; | |||
import { mutations } from './mutations'; | |||
import { actions } from './actions'; | |||
import { getters } from './getters'; | |||
export default { | |||
state, | |||
mutations, | |||
actions, | |||
getters | |||
}; |
@@ -1,14 +0,0 @@ | |||
export const mutations = { | |||
SET_CURRENT_AREACODE: (state, areaCode) => { // 当前地图层级信息 | |||
state.areaCode = areaCode; | |||
}, | |||
SET_LOGIN_INFO: (state, item) => { | |||
state.loginInfo = item; | |||
}, | |||
RESET_LOGIN_INFO: (state) => { | |||
state.loginInfo = null; | |||
}, | |||
SET_CURRENT_LAYERNAME: (state, currentLayerName) => { | |||
state.currentLayerName = currentLayerName; | |||
}, | |||
}; |
@@ -1,5 +0,0 @@ | |||
export const state = { | |||
areaCode: '', | |||
loginInfo: null, | |||
currentLayerName: '' // 当前操作的图层名 | |||
}; |
@@ -0,0 +1,39 @@ | |||
const getters = { | |||
sidebar: state => state.app.sidebar, | |||
size: state => state.app.size, | |||
device: state => state.app.device, | |||
visitedViews: state => state.tagsView.visitedViews, | |||
cachedViews: state => state.tagsView.cachedViews, | |||
token: state => state.user.token, | |||
avatar: state => state.user.avatar, | |||
name: state => state.user.name, | |||
introduction: state => state.user.introduction, | |||
roles: state => state.user.roles, | |||
userRoles:state => state.user.userRoles, | |||
permissions: state => state.user.permissions, | |||
setUpModuleId: state => state.user.setUpModuleId, | |||
permission_routes: state => state.permission.routes, | |||
bookName: state => state.user.bookName, | |||
sidebarRouters: state => state.permission.sidebarRouters, | |||
nickName: state => state.user.nickName, | |||
businessOwnership: state => state.user.businessOwnership, | |||
deptLevel: state => state.user.deptLevel, | |||
businessLevel: state => state.user.businessLevel, | |||
bookType: state => state.user.bookType, | |||
deptname: state => state.user.deptname, | |||
leader: state => state.user.leader, | |||
parentDeptName: state => state.user.parentDeptName, | |||
deptName: state => state.user.deptName, | |||
userType: state => state.user.userType, | |||
allDeptName: state => state.user.allDeptName, | |||
systemConfigList: state => state.user.systemConfigList, //获取登录页标题 | |||
loginSystemName: state => state.user.loginSystemName, //系统名称 | |||
browserName: state => state.user.browserName, //浏览器页签名称 | |||
technicalSupport: state => state.user.technicalSupport, //技术支持 | |||
noticeThree: state => state.user.noticeThree, //阅读须知 0 未阅读 | |||
baseRoutingUrl: state => state.user.baseRoutingUrl, //资源文件访问前缀 | |||
bigscreenUrl: state => state.user.bigscreenUrl, //大数据指挥舱 | |||
globalLogo: state => state.user.globalLogo, //全局logo | |||
screenLogo: state => state.user.screenLogo, //大屏logo | |||
} | |||
export default getters |
@@ -1,19 +1,23 @@ | |||
import Vue from 'vue'; | |||
import Vuex from 'vuex'; | |||
import VuexPersistence from 'vuex-persist'; | |||
import Vue from 'vue' | |||
import Vuex from 'vuex' | |||
import app from './modules/app' | |||
import user from './modules/user' | |||
import tagsView from './modules/tagsView' | |||
import permission from './modules/permission' | |||
import settings from './modules/settings' | |||
import getters from './getters' | |||
import app from '@/store/app/index.js'; | |||
Vue.use(Vuex) | |||
Vue.use(Vuex); | |||
const vuexLocal = new VuexPersistence({ | |||
key: 'rongxin.nongjing.expo', | |||
modules: ['app'] | |||
}); | |||
export default new Vuex.Store({ | |||
const store = new Vuex.Store({ | |||
modules: { | |||
app | |||
app, | |||
user, | |||
tagsView, | |||
permission, | |||
settings | |||
}, | |||
plugins: [vuexLocal.plugin] | |||
}); | |||
getters | |||
}) | |||
export default store |
@@ -0,0 +1,54 @@ | |||
const state = { | |||
sidebar: { | |||
withoutAnimation: false | |||
}, | |||
device: 'desktop', | |||
} | |||
const mutations = { | |||
TOGGLE_SIDEBAR: state => { | |||
state.sidebar.opened = !state.sidebar.opened | |||
state.sidebar.withoutAnimation = false | |||
}, | |||
CLOSE_SIDEBAR: (state, withoutAnimation) => { | |||
state.sidebar.opened = false | |||
state.sidebar.withoutAnimation = withoutAnimation | |||
}, | |||
OPEN_SIDEBAR: state => { | |||
state.sidebar.opened = true; | |||
state.sidebar.withoutAnimation = false; | |||
}, | |||
TOGGLE_DEVICE: (state, device) => { | |||
state.device = device | |||
}, | |||
SET_SIZE: (state, size) => { | |||
state.size = size | |||
} | |||
} | |||
const actions = { | |||
toggleSideBar ({ commit }) { | |||
commit('TOGGLE_SIDEBAR') | |||
}, | |||
closeSideBar ({ commit }, { withoutAnimation }) { | |||
commit('CLOSE_SIDEBAR', withoutAnimation) | |||
}, | |||
openSideBar ({ commit }) { | |||
commit('OPEN_SIDEBAR') | |||
}, | |||
toggleDevice ({ commit }, device) { | |||
commit('TOGGLE_DEVICE', device) | |||
}, | |||
setSize ({ commit }, size) { | |||
commit('SET_SIZE', size) | |||
} | |||
} | |||
export default { | |||
namespaced: true, | |||
state, | |||
mutations, | |||
actions | |||
} |
@@ -0,0 +1,51 @@ | |||
import { constantRoutes } from '@/router' | |||
const permission = { | |||
state: { | |||
routes: [], | |||
addRoutes: [], | |||
sidebarRouters: [] | |||
}, | |||
mutations: { | |||
SET_ROUTES: (state, routes) => { | |||
state.addRoutes = routes | |||
state.routes = constantRoutes.concat(routes) | |||
}, | |||
SET_SIDEBAR_ROUTERS: (state, routers) => { | |||
state.sidebarRouters = constantRoutes.concat(routers) | |||
}, | |||
}, | |||
actions: { | |||
} | |||
} | |||
function filterChildren (childrenMap) { | |||
var children = [] | |||
childrenMap.forEach((el, index) => { | |||
if (el.children && el.children.length) { | |||
if (el.component === 'ParentView') { | |||
el.children.forEach(c => { | |||
c.path = el.path + '/' + c.path | |||
if (c.children && c.children.length) { | |||
children = children.concat(filterChildren(c.children, c)) | |||
return | |||
} | |||
children.push(c) | |||
}) | |||
return | |||
} | |||
} | |||
children = children.concat(el) | |||
}) | |||
return children | |||
} | |||
export const loadView = (view) => { | |||
if (process.env.NODE_ENV === 'development') { | |||
return (resolve) => require([`@/views/${view}`], resolve) | |||
} else { | |||
// 使用 import 实现生产环境的路由懒加载 | |||
return () => import(`@/views/${view}`) | |||
} | |||
} | |||
export default permission |
@@ -0,0 +1,18 @@ | |||
const state = { | |||
} | |||
const mutations = { | |||
} | |||
const actions = { | |||
} | |||
export default { | |||
namespaced: true, | |||
state, | |||
mutations, | |||
actions | |||
} | |||
@@ -0,0 +1,159 @@ | |||
const state = { | |||
visitedViews: [], | |||
cachedViews: [] | |||
} | |||
const mutations = { | |||
ADD_VISITED_VIEW: (state, view) => { | |||
if (state.visitedViews.some(v => v.path === view.path)) return | |||
state.visitedViews.push( | |||
Object.assign({}, view, { | |||
title: view.meta.title || 'no-name' | |||
}) | |||
) | |||
}, | |||
ADD_CACHED_VIEW: (state, view) => { | |||
if (state.cachedViews.includes(view.name)) return | |||
if (!view.meta.noCache) { | |||
state.cachedViews.push(view.name) | |||
} | |||
}, | |||
DEL_VISITED_VIEW: (state, view) => { | |||
for (const [i, v] of state.visitedViews.entries()) { | |||
if (v.path === view.path) { | |||
state.visitedViews.splice(i, 1) | |||
break | |||
} | |||
} | |||
}, | |||
DEL_CACHED_VIEW: (state, view) => { | |||
const index = state.cachedViews.indexOf(view.name) | |||
index > -1 && state.cachedViews.splice(index, 1) | |||
}, | |||
DEL_OTHERS_VISITED_VIEWS: (state, view) => { | |||
state.visitedViews = state.visitedViews.filter(v => { | |||
return v.meta.affix || v.path === view.path | |||
}) | |||
}, | |||
DEL_OTHERS_CACHED_VIEWS: (state, view) => { | |||
const index = state.cachedViews.indexOf(view.name) | |||
if (index > -1) { | |||
state.cachedViews = state.cachedViews.slice(index, index + 1) | |||
} else { | |||
state.cachedViews = [] | |||
} | |||
}, | |||
DEL_ALL_VISITED_VIEWS: state => { | |||
// keep affix tags | |||
const affixTags = state.visitedViews.filter(tag => tag.meta.affix) | |||
state.visitedViews = affixTags | |||
}, | |||
DEL_ALL_CACHED_VIEWS: state => { | |||
state.cachedViews = [] | |||
}, | |||
UPDATE_VISITED_VIEW: (state, view) => { | |||
for (let v of state.visitedViews) { | |||
if (v.path === view.path) { | |||
v = Object.assign(v, view) | |||
break | |||
} | |||
} | |||
} | |||
} | |||
const actions = { | |||
addView({ dispatch }, view) { | |||
dispatch('addVisitedView', view) | |||
dispatch('addCachedView', view) | |||
}, | |||
addVisitedView({ commit }, view) { | |||
commit('ADD_VISITED_VIEW', view) | |||
}, | |||
addCachedView({ commit }, view) { | |||
commit('ADD_CACHED_VIEW', view) | |||
}, | |||
delView({ dispatch, state }, view) { | |||
return new Promise(resolve => { | |||
dispatch('delVisitedView', view) | |||
dispatch('delCachedView', view) | |||
resolve({ | |||
visitedViews: [...state.visitedViews], | |||
cachedViews: [...state.cachedViews] | |||
}) | |||
}) | |||
}, | |||
delVisitedView({ commit, state }, view) { | |||
return new Promise(resolve => { | |||
commit('DEL_VISITED_VIEW', view) | |||
resolve([...state.visitedViews]) | |||
}) | |||
}, | |||
delCachedView({ commit, state }, view) { | |||
return new Promise(resolve => { | |||
commit('DEL_CACHED_VIEW', view) | |||
resolve([...state.cachedViews]) | |||
}) | |||
}, | |||
delOthersViews({ dispatch, state }, view) { | |||
return new Promise(resolve => { | |||
dispatch('delOthersVisitedViews', view) | |||
dispatch('delOthersCachedViews', view) | |||
resolve({ | |||
visitedViews: [...state.visitedViews], | |||
cachedViews: [...state.cachedViews] | |||
}) | |||
}) | |||
}, | |||
delOthersVisitedViews({ commit, state }, view) { | |||
return new Promise(resolve => { | |||
commit('DEL_OTHERS_VISITED_VIEWS', view) | |||
resolve([...state.visitedViews]) | |||
}) | |||
}, | |||
delOthersCachedViews({ commit, state }, view) { | |||
return new Promise(resolve => { | |||
commit('DEL_OTHERS_CACHED_VIEWS', view) | |||
resolve([...state.cachedViews]) | |||
}) | |||
}, | |||
delAllViews({ dispatch, state }, view) { | |||
return new Promise(resolve => { | |||
dispatch('delAllVisitedViews', view) | |||
dispatch('delAllCachedViews', view) | |||
resolve({ | |||
visitedViews: [...state.visitedViews], | |||
cachedViews: [...state.cachedViews] | |||
}) | |||
}) | |||
}, | |||
delAllVisitedViews({ commit, state }) { | |||
return new Promise(resolve => { | |||
commit('DEL_ALL_VISITED_VIEWS') | |||
resolve([...state.visitedViews]) | |||
}) | |||
}, | |||
delAllCachedViews({ commit, state }) { | |||
return new Promise(resolve => { | |||
commit('DEL_ALL_CACHED_VIEWS') | |||
resolve([...state.cachedViews]) | |||
}) | |||
}, | |||
updateVisitedView({ commit }, view) { | |||
commit('UPDATE_VISITED_VIEW', view) | |||
} | |||
} | |||
export default { | |||
namespaced: true, | |||
state, | |||
mutations, | |||
actions | |||
} |
@@ -0,0 +1,341 @@ | |||
import { login, singleLogin, logout, getInfo, smsLogin, getConfig, systemConfig, chungengUserLogin } from '@/api/login' | |||
import { getToken, setToken, removeToken } from '@/utils/auth' | |||
const user = { | |||
state: { | |||
token: getToken(), | |||
name: '', | |||
avatar: '', | |||
roles: [], | |||
userRoles: [], | |||
permissions: [], | |||
bookName: '', | |||
setUpModuleId: '', | |||
//获取登录页相关标题 | |||
systemConfigList: [], | |||
//系统名称 | |||
loginSystemName: '', | |||
//浏览器页签名称 | |||
browserName: '', | |||
//技术支持 | |||
technicalSupport: '', | |||
//是否阅读须知 | |||
noticeThree: '', | |||
//界面logo | |||
globalLogo: '', | |||
//系统大屏logo | |||
screenLogo: '' | |||
}, | |||
mutations: { | |||
SET_TOKEN: (state, token) => { | |||
state.token = token | |||
}, | |||
SET_SETUPMODULE: (state, setUpModuleId) => { | |||
state.setUpModuleId = setUpModuleId | |||
}, | |||
SET_NAME: (state, name) => { | |||
state.name = name | |||
}, | |||
SET_USERID: (state, userId) => { | |||
state.userId = userId | |||
}, | |||
SET_NICKNAME: (state, nickName) => { | |||
state.nickName = nickName | |||
}, | |||
SET_AVATAR: (state, avatar) => { | |||
state.avatar = avatar | |||
}, | |||
SET_ROLES: (state, roles) => { | |||
state.roles = roles | |||
}, | |||
SET_USERROLES: (state, roles) => { | |||
state.userRoles = roles | |||
}, | |||
SET_PERMISSIONS: (state, permissions) => { | |||
state.permissions = permissions | |||
}, | |||
SET_LOGINDEPTID: (state, loginDeptId) => { | |||
state.loginDeptId = loginDeptId | |||
}, | |||
SET_LOGINBOOKID: (state, loginBookId) => { | |||
state.loginBookId = loginBookId | |||
}, | |||
SET_DEPTNAME: (state, deptName) => { | |||
state.deptName = deptName | |||
}, | |||
SET_DEPT_NAME: (state, deptname) => { | |||
state.deptname = deptname | |||
}, | |||
SET_LEADER: (state, leader) => { | |||
state.leader = leader | |||
}, | |||
SET_DEPTID: (state, deptId) => { | |||
state.deptId = deptId | |||
}, | |||
SET_BOOKNAME: (state, bookName) => { | |||
state.bookName = bookName | |||
}, | |||
SET_BUSINESSOWNERSHIP: (state, businessOwnership) => { | |||
state.businessOwnership = businessOwnership | |||
}, | |||
SET_OFFICIALSEAL: (state, officialSeal) => { | |||
state.officialSeal = officialSeal | |||
}, | |||
SET_DEPTLEVEL: (state, deptLevel) => { | |||
state.deptLevel = deptLevel | |||
}, | |||
SET_BASEROUTINGURL: (state, baseRoutingUrl) => { | |||
state.baseRoutingUrl = baseRoutingUrl | |||
}, | |||
SET_BUSINESSLEVEL: (state, businessLevel) => { | |||
state.businessLevel = businessLevel | |||
}, | |||
SET_BOOKTYPE: (state, bookType) => { | |||
state.bookType = bookType | |||
}, | |||
SET_PARENTDEPTNAME: (state, parentDeptName) => { | |||
state.parentDeptName = parentDeptName | |||
}, | |||
SET_USERTYPE: (state, userType) => { | |||
state.userType = userType | |||
}, | |||
SET_ALLDEPTNAME: (state, allDeptName) => { | |||
state.allDeptName = allDeptName | |||
}, | |||
SET_STSTEMCONFIGlIST: (state, systemConfigList) => { | |||
state.systemConfigList = systemConfigList | |||
}, | |||
SET_LOGINSYSTEMNAME: (state, loginSystemName) => { | |||
state.loginSystemName = loginSystemName | |||
}, | |||
SET_BORWSERNAME: (state, browserName) => { | |||
state.browserName = browserName | |||
}, | |||
SET_TECHNICALSUPPORT: (state, technicalSupport) => { | |||
state.technicalSupport = technicalSupport | |||
}, | |||
SET_BIGSCREENURL: (state, bigscreenUrl) => { | |||
state.bigscreenUrl = bigscreenUrl | |||
}, | |||
SET_NOTICETHREE: (state, noticeThree) => { | |||
state.noticeThree = noticeThree | |||
}, | |||
SET_GLOBALLOGO: (state, globalLogo) => { | |||
state.globalLogo = globalLogo | |||
}, | |||
SET_SCREENLOGO: (state, screenLogo) => { | |||
state.screenLogo = screenLogo | |||
}, | |||
}, | |||
actions: { | |||
// 登录 | |||
Login ({ commit }, userInfo) { | |||
const username = userInfo.username.trim() | |||
const password = userInfo.password | |||
const code = userInfo.code | |||
const uuid = userInfo.uuid | |||
return new Promise((resolve, reject) => { | |||
login(username, password, code, uuid).then(res => { | |||
setToken(res.token) | |||
commit('SET_TOKEN', res.token) | |||
resolve(res) | |||
}).catch(error => { | |||
reject(error) | |||
}) | |||
}) | |||
}, | |||
SingleLogin ({ commit }, userInfo) { | |||
const code = userInfo.code | |||
return new Promise((resolve, reject) => { | |||
singleLogin(code).then(res => { | |||
setToken(res.token) | |||
commit('SET_TOKEN', res.token) | |||
resolve() | |||
}).catch(error => { | |||
reject(error) | |||
}) | |||
}) | |||
}, | |||
//设置用户当前模块系统 | |||
setUpModule ({ commit }, setUpModuleId) { | |||
commit('SET_SETUPMODULE', setUpModuleId) | |||
}, | |||
//短信验证码登录 | |||
SmsLogin ({ commit }, userInfo) { | |||
const mobile = userInfo.mobile.trim() | |||
const smsCode = userInfo.smsCode | |||
const uuid = userInfo.uuid | |||
return new Promise((resolve, reject) => { | |||
smsLogin(mobile, smsCode, uuid).then(res => { | |||
setToken(res.token) | |||
commit('SET_TOKEN', res.token) | |||
resolve() | |||
}).catch(error => { | |||
reject(error) | |||
}) | |||
}) | |||
}, | |||
// 获取用户信息 | |||
GetInfo ({ commit, state }) { | |||
return new Promise((resolve, reject) => { | |||
getInfo(state.token).then(res => { | |||
if (res && res.code && res.code == 200) { | |||
const user = res.user | |||
// const avatar = user.avatar == "" ? require("@/assets/images/profile.jpg") : process.env.VUE_APP_BASE_API + user.avatar; | |||
const avatar = user.avatar == "" ? "" : process.env.VUE_APP_BASE_API + user.avatar; | |||
if (res.roles && res.roles.length > 0) { // 验证返回的roles是否是一个非空数组 | |||
commit('SET_ROLES', res.roles) | |||
commit('SET_PERMISSIONS', res.permissions) | |||
} else { | |||
commit('SET_ROLES', ['ROLE_DEFAULT']) | |||
} | |||
commit('SET_USERROLES', user.roles) | |||
commit('SET_BOOKNAME', user.bookName) | |||
commit('SET_NAME', user.userName) | |||
commit('SET_USERID', user.userId) | |||
commit('SET_NICKNAME', user.nickName) | |||
commit('SET_LOGINDEPTID', user.loginDeptId) | |||
commit('SET_LOGINBOOKID', user.loginBookId) | |||
commit('SET_DEPTNAME', user.deptName) | |||
commit('SET_DEPT_NAME', user.dept.deptName) | |||
commit('SET_LEADER', user.dept.leader) | |||
commit('SET_DEPTID', user.deptId) | |||
commit('SET_AVATAR', avatar) | |||
commit('SET_BUSINESSOWNERSHIP', user.businessOwnership) | |||
commit('SET_BUSINESSLEVEL', user.businessLevel) | |||
commit('SET_BOOKTYPE', user.bookType) | |||
commit('SET_PARENTDEPTNAME', user.parentDeptName) | |||
commit('SET_USERTYPE', user.userType) | |||
commit('SET_ALLDEPTNAME', user.allDeptName) | |||
commit('SET_NOTICETHREE', user.noticeThree) | |||
commit('SET_OFFICIALSEAL', user.officialSeal) | |||
} | |||
getConfig().then((num) => { | |||
// console.log(res) | |||
if (num && num.code == 200) { | |||
let content = num.data; | |||
commit('SET_DEPTLEVEL', content.deptLevel) | |||
} | |||
}) | |||
systemConfig({ configKey: 'system.attachment' }).then((data) => { | |||
if (data.code == 200) { | |||
let content = data.rows; | |||
if (content.length != 0) { | |||
let baseRoutingUrl = content[0].configValue; | |||
commit('SET_BASEROUTINGURL', baseRoutingUrl) | |||
} | |||
} | |||
}) | |||
resolve(res) | |||
}).catch(error => { | |||
reject(error) | |||
}) | |||
}) | |||
}, | |||
//获取登录页相关标题 | |||
systemTitle ({ commit, state }) { | |||
return new Promise((resolve, reject) => { | |||
systemConfig({ configKey: 'system' }).then((data) => { | |||
let content = data.rows; | |||
commit('SET_STSTEMCONFIGlIST', content) | |||
//系统名称 | |||
let loginSystemName = ''; | |||
//浏览器页签名称 | |||
let browserName = ''; | |||
//技术支持 | |||
let technicalSupport = ''; | |||
//大数据指挥舱 | |||
let bigscreenUrl = ''; | |||
//界面logo | |||
let globalLogo = ''; | |||
//系统大屏logo | |||
let screenLogo = ''; | |||
content.forEach((v, i) => { | |||
if (v.configKey == 'system.login.name') { | |||
loginSystemName = v.configValue | |||
} else if (v.configKey == 'system.browser.name') { | |||
browserName = v.configValue | |||
} else if (v.configKey == 'system.company.name') { | |||
technicalSupport = v.configValue | |||
} else if (v.configKey == 'system.bigscreen.url') { | |||
bigscreenUrl = v.configValue | |||
} else if (v.configKey == 'system.logo.pic') { | |||
globalLogo = v.configValue | |||
} else if (v.configKey == 'system.logo5.pic') { | |||
screenLogo = v.configValue | |||
} | |||
}) | |||
commit('SET_LOGINSYSTEMNAME', loginSystemName) | |||
commit('SET_BORWSERNAME', browserName) | |||
commit('SET_TECHNICALSUPPORT', technicalSupport) | |||
commit('SET_BIGSCREENURL', bigscreenUrl) | |||
commit('SET_GLOBALLOGO', globalLogo) | |||
commit('SET_SCREENLOGO', screenLogo) | |||
resolve() | |||
}).catch(error => { | |||
reject(error) | |||
}) | |||
}) | |||
}, | |||
// 退出系统 | |||
LogOut ({ commit, state }) { | |||
return new Promise((resolve, reject) => { | |||
logout(state.token).then(() => { | |||
commit('SET_TOKEN', '') | |||
commit('SET_ROLES', []) | |||
commit('SET_PERMISSIONS', []) | |||
removeToken() | |||
resolve() | |||
}).catch(error => { | |||
reject(error) | |||
}) | |||
}) | |||
}, | |||
// 前端 登出 | |||
FedLogOut ({ commit }) { | |||
return new Promise(resolve => { | |||
commit('SET_TOKEN', '') | |||
commit('SET_ROLES', []) | |||
commit('SET_PERMISSIONS', []) | |||
removeToken() | |||
resolve() | |||
}) | |||
}, | |||
// 更新用户信息 | |||
// 春耕App用户登录 | |||
ChungengLogin ({ commit }, userInfo) { | |||
const code = userInfo.code; | |||
return new Promise((resolve, reject) => { | |||
chungengUserLogin(code).then(res => { | |||
setToken(res.token) | |||
commit('SET_TOKEN', res.token) | |||
resolve(res.data) | |||
}).catch(error => { | |||
reject(error) | |||
}) | |||
}) | |||
}, | |||
} | |||
} | |||
export default user |
@@ -9,11 +9,11 @@ $border_color: rgba(30, 56, 92, 1); | |||
display: block; | |||
.el-input__inner { | |||
height: 60px; | |||
line-height: 60px; | |||
background: $bg_color; | |||
border: 1px solid $border_color; | |||
color: #FFFFFF; | |||
// height: 60px; | |||
// line-height: 60px; | |||
// background: $bg_color; | |||
// border: 1px solid $border_color; | |||
// color: #FFFFFF; | |||
} | |||
.el-input__inner::-webkit-input-placeholder { | |||
@@ -84,11 +84,11 @@ $border_color: rgba(30, 56, 92, 1); | |||
} | |||
.el-input__inner { | |||
width: 100% !important; | |||
color: #DFF2FF; | |||
border: 0; | |||
border-radius: 0; | |||
background: $bg_color; | |||
// width: 100% !important; | |||
// color: #DFF2FF; | |||
// border: 0; | |||
// border-radius: 0; | |||
// background: $bg_color; | |||
} | |||
.el-range-input { | |||
@@ -2,7 +2,7 @@ const TokenKey = 'Admin-Token'; | |||
// 获取token | |||
export function getToken () { | |||
return 'eyJhbGciOiJIUzUxMiJ9.eyJsb2dpbl91c2VyX2tleSI6IjNlMjYwNzA2LTQzZWEtNGJlMS1hZDBiLTQ1YTIzMzk1MmNiOSJ9._B3v74EZpYO8WspNmKtQU1t7AoxrFdRWuhUNojKDrk5gTakfdfS8rcD5USwwvRwDgRaR1DvmP6E2fhspkB-8kg'; // 将token保存在本地 | |||
return localStorage.getItem(TokenKey); | |||
} | |||
// 保存token | |||
export function setToken (token) { | |||
@@ -0,0 +1,30 @@ | |||
import JSEncrypt from 'jsencrypt/bin/jsencrypt.min.js' | |||
// 密钥对生成 http://web.chacuo.net/netrsakeypair | |||
const publicKey = 'MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKoR8mX0rGKLqzcWmOzbfj64K8ZIgOdH\n' + | |||
'nzkXSOVOZbFu/TJhZ7rFAN+eaGkl3C4buccQd/EjEsj9ir7ijT7h96MCAwEAAQ==' | |||
const privateKey = 'MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAqhHyZfSsYourNxaY\n' + | |||
'7Nt+PrgrxkiA50efORdI5U5lsW79MmFnusUA355oaSXcLhu5xxB38SMSyP2KvuKN\n' + | |||
'PuH3owIDAQABAkAfoiLyL+Z4lf4Myxk6xUDgLaWGximj20CUf+5BKKnlrK+Ed8gA\n' + | |||
'kM0HqoTt2UZwA5E2MzS4EI2gjfQhz5X28uqxAiEA3wNFxfrCZlSZHb0gn2zDpWow\n' + | |||
'cSxQAgiCstxGUoOqlW8CIQDDOerGKH5OmCJ4Z21v+F25WaHYPxCFMvwxpcw99Ecv\n' + | |||
'DQIgIdhDTIqD2jfYjPTY8Jj3EDGPbH2HHuffvflECt3Ek60CIQCFRlCkHpi7hthh\n' + | |||
'YhovyloRYsM+IS9h/0BzlEAuO0ktMQIgSPT3aFAgJYwKpqRYKlLDVcflZFCKY7u3\n' + | |||
'UP8iWi1Qw0Y=' | |||
// 加密 | |||
export function encrypt (txt) { | |||
const encryptor = new JSEncrypt() | |||
encryptor.setPublicKey(publicKey) // 设置公钥 | |||
return encryptor.encrypt(txt) // 对数据进行加密 | |||
} | |||
// 解密 | |||
export function decrypt (txt) { | |||
const encryptor = new JSEncrypt() | |||
encryptor.setPrivateKey(privateKey) // 设置私钥 | |||
return encryptor.decrypt(txt) // 对数据进行解密 | |||
} | |||
@@ -0,0 +1,50 @@ | |||
<div class="page bk"> | |||
<h1 class="text">西峡县集体资产监管一张图</h1> | |||
<div class="login"> | |||
<el-form ref="loginForm" :model="loginForm" :rules="loginRules" class="login-form" label-position="right" | |||
label-width="100px"> | |||
<el-form-item prop="username" label="用户名"> | |||
<el-input v-model="loginForm.username" class="loginInput" type="text" auto-complete="off" placeholder="账号"> | |||
</el-input> | |||
</el-form-item> | |||
<el-form-item prop="password" label="密码"> | |||
<el-input v-model="loginForm.password" type="password" class="loginInput" auto-complete="off" placeholder="密码" | |||
@keyup.enter.native="handleLogin" show-password> | |||
</el-input> | |||
</el-form-item> | |||
<el-row :gutter="20" :span="24"> | |||
<el-col :span="16"> | |||
<el-form-item prop="code" label="验证码"> | |||
<el-input v-model="loginForm.code" auto-complete="off" class="loginInput" placeholder="验证码" | |||
@keyup.enter.native="handleLogin"> | |||
</el-input> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="6"> | |||
<div class="img"> | |||
<img :src="codeUrl" @click="getCode" class="login_code_img" /> | |||
</div> | |||
</el-col> | |||
</el-row> | |||
<el-row> | |||
<div class="auxiliary"> | |||
<el-checkbox class="keepMind" v-model="loginForm.rememberMe">记住密码 </el-checkbox> | |||
<div class="sms-login"> | |||
<el-button size="mini" type="text" @click.native.prevent="loginMethod"> | |||
<span>忘记密码</span> | |||
</el-button> | |||
</div> | |||
</div> | |||
</el-row> | |||
<el-form-item style="width: 100%"> | |||
<el-button :loading="loading" size="medium" type="primary" class="submitForm" | |||
@click.native.prevent="handleLogin"> | |||
<span v-if="!loading">立即登录</span> | |||
<span v-else>登 录 中...</span> | |||
</el-button> | |||
</el-form-item> | |||
</el-form> | |||
</div> | |||
<p class="tip">Copyright @ 2022 中农融信 (北京)科技股份有限公司 京ICP备06068185号-8</p> | |||
</div> |
@@ -0,0 +1,162 @@ | |||
import { getCodeImg } from "@/api/login"; | |||
import Cookies from "js-cookie"; | |||
import { encrypt } from '@/utils/jsencrypt' // 公钥,私钥都声明在里面 | |||
export default { | |||
components: { | |||
}, | |||
data () { | |||
return { | |||
isSmsLogin: false, | |||
loginForm: { | |||
username: "", | |||
password: "", | |||
rememberMe: false, | |||
code: "", | |||
uuid: "", | |||
mobile: "", | |||
smsCode: "", | |||
}, | |||
loading: false, | |||
codeUrl: "", | |||
loginRules: { | |||
username: [ | |||
{ required: true, trigger: "blur", message: "账号不能为空" }, | |||
], | |||
mobile: [ | |||
{ required: true, trigger: "blur", message: "手机号不能为空" }, | |||
], | |||
password: [ | |||
{ required: true, trigger: "blur", message: "口令不能为空" }, | |||
], | |||
code: [{ required: true, trigger: "blur", message: "验证码不能为空" }], | |||
// smsCode: [{ required: true, trigger: "blur", message: "验证码不能为空" }] | |||
}, | |||
}; | |||
}, | |||
computed: { | |||
}, | |||
created () { | |||
this.getCode(); | |||
}, | |||
mounted () { | |||
}, | |||
methods: { | |||
getCode () { | |||
getCodeImg().then((res) => { | |||
this.codeUrl = "data:image/gif;base64," + res.img; | |||
this.loginForm.uuid = res.uuid; | |||
}); | |||
}, | |||
handleLogin () { | |||
this.$refs.loginForm.validate((valid) => { | |||
if (valid) { | |||
if (this.isSmsLogin) { | |||
this.loading = true; | |||
if (this.loginForm.rememberMe) { | |||
Cookies.set("mobile", this.loginForm.mobile, { expires: 30 }); | |||
Cookies.set("rememberMe", this.loginForm.rememberMe, { | |||
expires: 30, | |||
}); | |||
} else { | |||
Cookies.remove("mobile"); | |||
Cookies.remove("rememberMe"); | |||
} | |||
if (this.viewChecked == true) { | |||
Cookies.set("cookieViewChecked", this.viewChecked, { | |||
expires: 30, | |||
}); | |||
} else { | |||
Cookies.remove("cookieViewChecked"); | |||
} | |||
this.$store | |||
.dispatch("SmsLogin", this.loginForm) | |||
.then((res) => { | |||
Cookies.remove("viewPagesMonophylyId"); | |||
Cookies.remove("viewPagesMonophyly"); | |||
if (this.viewChecked == true) { | |||
this.$router.push({ path: "/nav" }); | |||
} else { | |||
if (res && res.code && res.code == 200) { | |||
let requireUpdatePassword = res.requireUpdatePassword; | |||
if (requireUpdatePassword) { | |||
//重置密码 | |||
this.$set(this.resetPwd, "open", true); | |||
} else { | |||
this.$router | |||
.push({ path: this.redirect || "/" }) | |||
.catch(() => { }); | |||
} | |||
} | |||
} | |||
}) | |||
.catch((error) => { | |||
const errorString = error + ""; | |||
this.loading = false; | |||
if (errorString.indexOf("证书无效") > -1) { | |||
loginError().then((res) => { | |||
this.upload.open = true; | |||
this.upload.loginJson = res.msg; | |||
}); | |||
} | |||
this.getCode(); | |||
}); | |||
} else { | |||
this.loading = true; | |||
if (this.loginForm.rememberMe) { | |||
Cookies.set("username", this.loginForm.username, { expires: 30 }); | |||
Cookies.set("password", encrypt(this.loginForm.password), { | |||
expires: 30, | |||
}); | |||
Cookies.set("rememberMe", this.loginForm.rememberMe, { | |||
expires: 30, | |||
}); | |||
} else { | |||
Cookies.remove("username"); | |||
Cookies.remove("password"); | |||
Cookies.remove("rememberMe"); | |||
} | |||
if (this.viewChecked == true) { | |||
Cookies.set("cookieViewChecked", this.viewChecked, { | |||
expires: 30, | |||
}); | |||
} else { | |||
Cookies.remove("cookieViewChecked"); | |||
} | |||
this.$store | |||
.dispatch("Login", this.loginForm) | |||
.then((res) => { | |||
Cookies.remove("viewPagesMonophylyId"); | |||
Cookies.remove("viewPagesMonophyly"); | |||
if (this.viewChecked == true) { | |||
this.$router.push({ path: "/nav" }); | |||
} else { | |||
if (res && res.code && res.code == 200) { | |||
let requireUpdatePassword = res.requireUpdatePassword; | |||
if (requireUpdatePassword) { | |||
//重置密码 | |||
this.$set(this.resetPwd, "open", true); | |||
} else { | |||
this.$router | |||
.push({ path: this.redirect || "/nav" }) | |||
} | |||
} | |||
} | |||
}) | |||
.catch((error) => { | |||
console.log(error); | |||
const errorString = error + ""; | |||
this.loading = false; | |||
if (errorString.indexOf("证书无效") > -1) { | |||
loginError().then((res) => { | |||
this.upload.open = true; | |||
this.upload.loginJson = res.msg; | |||
}); | |||
} | |||
this.getCode(); | |||
}); | |||
} | |||
} | |||
}); | |||
}, | |||
} | |||
}; |
@@ -0,0 +1,82 @@ | |||
.bk { | |||
background: url('./bk.png'); | |||
background-size: 100% 100%; | |||
.text { | |||
top: 110px; | |||
position: absolute; | |||
left: 50%; | |||
transform: translateX(-50%); | |||
font-family: Source Han Sans SC; | |||
font-weight: bold; | |||
font-size: 72px; | |||
color: #FEFEFE; | |||
line-height: 111px; | |||
// text-shadow: 0px 3px 3px rgba(30, 63, 112, 0.1); | |||
background: linear-gradient(180deg, #FEFFFF 17.4072265625%, #a0b9e5 99.6337890625%); | |||
-webkit-background-clip: text; | |||
-webkit-text-fill-color: transparent; | |||
} | |||
.tip { | |||
font-size: 16px; | |||
bottom: 110px; | |||
position: absolute; | |||
left: 50%; | |||
transform: translateX(-50%); | |||
} | |||
.login { | |||
padding: 50px 50px; | |||
padding-top: 80px; | |||
position: relative; | |||
left: 50%; | |||
top: 50%; | |||
transform: translate(-50%, -50%); | |||
height: 543px; | |||
width: 660px; | |||
background: url('./login.png'); | |||
background-size: 100% 100%; | |||
padding-right: 100px; | |||
} | |||
} | |||
/deep/ .el-form-item__label { | |||
color: white; | |||
} | |||
/deep/ .el-input__inner { | |||
height: 60px !important; | |||
} | |||
.loginInput { | |||
height: 60px !important; | |||
} | |||
.img { | |||
width: 160px; | |||
max-height: 60px !important; | |||
.login_code_img { | |||
// border: 1px solid red; | |||
width: 100%; | |||
height: 100%; | |||
} | |||
} | |||
.auxiliary { | |||
display: flex; | |||
align-items: center; | |||
justify-content: space-between; | |||
padding-left: 100px; | |||
} | |||
.submitForm { | |||
margin-top: 20px; | |||
background: linear-gradient(90deg, #1097FF 0%, #1233FF 97%); | |||
border-radius: 4px; | |||
height: 60px; | |||
width: 100%; | |||
} |
@@ -0,0 +1,4 @@ | |||
<template src='./index.html'/> | |||
<script lang='js' src='./index.js'></script> | |||
<style lang='scss' src='./index.scss' scoped> | |||
</style> |
@@ -0,0 +1,3 @@ | |||
<div class="page bk"> | |||
导航 | |||
</div> |
@@ -0,0 +1,17 @@ | |||
export default { | |||
components: { | |||
}, | |||
data () { | |||
return { | |||
}; | |||
}, | |||
computed: { | |||
}, | |||
created () { | |||
}, | |||
mounted () { | |||
}, | |||
methods: { | |||
} | |||
}; |
@@ -0,0 +1,4 @@ | |||
<template src='./index.html'/> | |||
<script lang='js' src='./index.js'></script> | |||
<style lang='scss' src='./index.scss' scoped> | |||
</style> |