Unverified Commit 2f3ef296 authored by 端午安康's avatar 端午安康 Committed by GitHub
Browse files

Merge pull request #1 from linlinjava/master

update
parents a2f77152 83711ec2
......@@ -6,7 +6,7 @@ spring:
datasource:
druid:
url: jdbc:mysql://localhost:3306/litemall?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC&allowPublicKeyRetrieval=true&verifyServerCertificate=false&useSSL=false
driver-class-name: com.mysql.jdbc.Driver
driver-class-name: com.mysql.cj.jdbc.Driver
username: litemall
password: litemall123456
initial-size: 10
......
......@@ -16,10 +16,16 @@ cat $LITEMALL_HOME/litemall-db/sql/litemall_schema.sql > $LITEMALL_HOME/deploy/d
cat $LITEMALL_HOME/litemall-db/sql/litemall_table.sql >> $LITEMALL_HOME/deploy/db/litemall.sql
cat $LITEMALL_HOME/litemall-db/sql/litemall_data.sql >> $LITEMALL_HOME/deploy/db/litemall.sql
cd $LITEMALL_HOME/litemall-admin
# 安装阿里node镜像工具
npm install -g cnpm --registry=https://registry.npm.taobao.org
# 安装node项目依赖环境
# 打包litemall-admin
cd $LITEMALL_HOME/litemall-admin
cnpm install
cnpm run build:dep
# 打包litemall-vue
cd $LITEMALL_HOME/litemall-vue
cnpm install
cnpm run build:dep
......
......@@ -8,7 +8,7 @@
* vue-router
* axios
* element
* vue-element-admin 4.2.1
* vue-element-admin 4.3.0
* 其他,见package.json
* 管理后台后端, 即litemall-admin-api模块
* Spring Boot 2.x
......@@ -18,9 +18,6 @@
* `缺失`首页中实现一些小组件,同时点击能够跳转相应页面
* `缺失`支持导出表所有数据
* `改善`管理员登录页面打开慢,优化速度
* `改善`地址优化,目前每一次点击都会请求后台,应该缓存已有的数据
* `改善`vue和vue-element-admin等及时更新
## 4.1 litemall-admin-api
......
......@@ -1339,11 +1339,11 @@ litemall-admin编译得到的前端文件在第一次加载时相当耗时,这
这里deploy部署方式比较简单不灵活,开发者可以参考开发自己的项目脚本。
#### 1.7.2.2 .gitlab-ci.yml部署
#### 1.7.2.2 docker部署
目前不支持
当前项目存在docker部署文件夹,这个是上述1.5.1节部署腾讯云服务器所采取的一些脚本。
#### 1.7.2.3 docker部署
#### 1.7.2.3 .gitlab-ci.yml部署
目前不支持
......
......@@ -5,8 +5,8 @@ spring:
encoding: UTF-8
datasource:
druid:
url: jdbc:mysql://mysql:3306/litemall?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC&allowPublicKeyRetrieval=true&verifyServerCertificate=false&useSSL=false
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://mysql:3306/litemall?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC&allowPublicKeyRetrieval=true&verifyServerCertificate=false&useSSL=true
driver-class-name: com.mysql.cj.jdbc.Driver
username: litemall
password: litemall123456
initial-size: 10
......
......@@ -16,10 +16,16 @@ cat $LITEMALL_HOME/litemall-db/sql/litemall_schema.sql > $LITEMALL_HOME/docker/d
cat $LITEMALL_HOME/litemall-db/sql/litemall_table.sql >> $LITEMALL_HOME/docker/db/init-sql/litemall.sql
cat $LITEMALL_HOME/litemall-db/sql/litemall_data.sql >> $LITEMALL_HOME/docker/db/init-sql/litemall.sql
cd $LITEMALL_HOME/litemall-admin
# 安装阿里node镜像工具
npm install -g cnpm --registry=https://registry.npm.taobao.org
# 安装node项目依赖环境
# 打包litemall-admin
cd $LITEMALL_HOME/litemall-admin
cnpm install
cnpm run build:dep
# 打包litemall-vue
cd $LITEMALL_HOME/litemall-vue
cnpm install
cnpm run build:dep
......
......@@ -12,12 +12,16 @@ import org.linlinjava.litemall.db.service.LitemallUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import javax.validation.constraints.NotNull;
@RestController
@RequestMapping("/admin/user")
@Validated
......@@ -38,4 +42,17 @@ public class AdminUserController {
List<LitemallUser> userList = userService.querySelective(username, mobile, page, limit, sort, order);
return ResponseUtil.okList(userList);
}
@RequiresPermissions("admin:user:list")
@RequiresPermissionsDesc(menu = {"用户管理", "会员管理"}, button = "详情")
@GetMapping("/detail")
public Object userDetail(@NotNull Integer id) {
LitemallUser user=userService.findById(id);
return ResponseUtil.ok(user);
}
@RequiresPermissions("admin:user:list")
@RequiresPermissionsDesc(menu = {"用户管理", "会员管理"}, button = "编辑")
@PostMapping("/update")
public Object userUpdate(@RequestBody LitemallUser user) {
return ResponseUtil.ok(userService.updateById(user));
}
}
{
"name": "litemall-admin",
"version": "1.0.0",
"description": "litemall-admin basing on vue-element-admin 4.2.1",
"description": "litemall-admin basing on vue-element-admin 4.3.0",
"author": "linlinjava <linlinjava@163.com>",
"license": "MIT",
"scripts": {
......@@ -50,13 +50,14 @@
"clipboard": "2.0.4",
"connect": "3.6.6",
"echarts": "4.2.1",
"element-ui": "2.12.0",
"element-ui": "2.13.2",
"file-saver": "1.3.8",
"js-cookie": "2.2.0",
"normalize.css": "7.0.0",
"nprogress": "0.2.0",
"path-to-regexp": "2.4.0",
"screenfull": "4.2.0",
"script-loader": "0.7.2",
"vue": "2.6.10",
"vue-count-to": "1.0.13",
"vue-router": "3.0.2",
......@@ -83,11 +84,10 @@
"html-webpack-plugin": "3.2.0",
"husky": "1.3.1",
"lint-staged": "8.1.5",
"node-sass": "^4.9.0",
"sass": "^1.26.2",
"runjs": "^4.3.2",
"sass-loader": "^7.1.0",
"script-ext-html-webpack-plugin": "2.1.3",
"script-loader": "0.7.2",
"serve-static": "^1.13.2",
"svg-sprite-loader": "4.1.3",
"svgo": "1.2.0",
......
......@@ -8,6 +8,22 @@ export function fetchList(query) {
})
}
export function userDetail(id) {
return request({
url: '/user/detail',
method: 'get',
params: {id}
})
}
export function updateUser(data) {
return request({
url: '/user/update',
method: 'post',
data
})
}
export function listAddress(query) {
return request({
url: '/address/list',
......@@ -47,4 +63,3 @@ export function listHistory(query) {
params: query
})
}
......@@ -42,7 +42,7 @@ export default {
</script>
<style lang="scss" scoped>
/deep/ .el-badge__content.is-fixed.is-dot {
::v-deep .el-badge__content.is-fixed.is-dot {
right: 5px;
top: 10px;
}
......
<template>
<el-scrollbar ref="scrollContainer" :vertical="false" class="scroll-container" @wheel.native.prevent="handleScroll">
<slot/>
<slot />
</el-scrollbar>
</template>
......@@ -80,7 +80,7 @@ export default {
position: relative;
overflow: hidden;
width: 100%;
/deep/ {
::v-deep {
.el-scrollbar__bar {
bottom: 0px;
}
......
......@@ -28,7 +28,7 @@ router.beforeEach((to, from, next) => {
store.dispatch('GetUserInfo').then(res => { // 拉取user_info
const perms = res.data.data.perms // note: perms must be a array! such as: ['GET /aaa','POST /bbb']
store.dispatch('GenerateRoutes', { perms }).then(() => { // 根据perms权限生成可访问的路由表
router.addRoutes(store.getters.addRouters) // 动态添加可访问路由表
router.addRoutes(store.getters.addRoutes) // 动态添加可访问路由表
next({ ...to, replace: true }) // hack方法 确保addRoutes已完成 ,set the replace: true so the navigation will not leave a history record
})
}).catch((err) => {
......
......@@ -24,14 +24,14 @@ import Layout from '@/views/layout/Layout'
noCache: true if true ,the page will no be cached(default is false)
}
**/
export const constantRouterMap = [
export const constantRoutes = [
{
path: '/redirect',
component: Layout,
hidden: true,
children: [
{
path: '/redirect/:path*',
path: '/redirect/:path(.*)',
component: () => import('@/views/redirect/index')
}
]
......@@ -71,13 +71,7 @@ export const constantRouterMap = [
}
]
export default new Router({
// mode: 'history', // require service support
scrollBehavior: () => ({ y: 0 }),
routes: constantRouterMap
})
export const asyncRouterMap = [
export const asyncRoutes = [
{
path: '/user',
component: Layout,
......@@ -612,3 +606,19 @@ export const asyncRouterMap = [
{ path: '*', redirect: '/404', hidden: true }
]
const createRouter = () => new Router({
// mode: 'history', // require service support
scrollBehavior: () => ({ y: 0 }),
routes: constantRoutes
})
const router = createRouter()
// Detail see: https://github.com/vuejs/vue-router/issues/1234#issuecomment-357941465
export function resetRouter() {
const newRouter = createRouter()
router.matcher = newRouter.matcher // reset router
}
export default router
......@@ -8,12 +8,9 @@ const getters = {
token: state => state.user.token,
avatar: state => state.user.avatar,
name: state => state.user.name,
introduction: state => state.user.introduction,
status: state => state.user.status,
roles: state => state.user.roles,
perms: state => state.user.perms,
setting: state => state.user.setting,
permission_routers: state => state.permission.routers,
addRouters: state => state.permission.addRouters
permission_routes: state => state.permission.routes,
addRoutes: state => state.permission.addRoutes
}
export default getters
import { asyncRouterMap, constantRouterMap } from '@/router'
import { asyncRoutes, constantRoutes } from '@/router'
/**
* 通过meta.perms判断是否与当前用户权限匹配
......@@ -15,16 +15,16 @@ function hasPermission(perms, route) {
/**
* 递归过滤异步路由表,返回符合用户角色权限的路由表
* @param routes asyncRouterMap
* @param routes asyncRoutes
* @param perms
*/
function filterAsyncRouter(routes, perms) {
function filterAsyncRoutes(routes, perms) {
const res = []
routes.forEach(route => {
const tmp = { ...route }
if (tmp.children) {
tmp.children = filterAsyncRouter(tmp.children, perms)
tmp.children = filterAsyncRoutes(tmp.children, perms)
if (tmp.children && tmp.children.length > 0) {
res.push(tmp)
}
......@@ -40,26 +40,26 @@ function filterAsyncRouter(routes, perms) {
const permission = {
state: {
routers: constantRouterMap,
addRouters: []
routes: constantRoutes,
addRoutes: []
},
mutations: {
SET_ROUTERS: (state, routers) => {
state.addRouters = routers
state.routers = constantRouterMap.concat(routers)
SET_ROUTES: (state, routes) => {
state.addRoutes = routes
state.routes = constantRoutes.concat(routes)
}
},
actions: {
GenerateRoutes({ commit }, data) {
return new Promise(resolve => {
const { perms } = data
let accessedRouters
let accessedRoutes
if (perms.includes('*')) {
accessedRouters = asyncRouterMap
accessedRoutes = asyncRoutes
} else {
accessedRouters = filterAsyncRouter(asyncRouterMap, perms)
accessedRoutes = filterAsyncRoutes(asyncRoutes, perms)
}
commit('SET_ROUTERS', accessedRouters)
commit('SET_ROUTES', accessedRoutes)
resolve()
})
}
......
import { loginByUsername, logout, getUserInfo } from '@/api/login'
import { getToken, setToken, removeToken } from '@/utils/auth'
import router, { resetRouter } from '@/router'
const user = {
state: {
user: '',
status: '',
code: '',
token: getToken(),
name: '',
avatar: '',
introduction: '',
roles: [],
perms: [],
setting: {
articlePlatform: []
}
perms: []
},
mutations: {
SET_CODE: (state, code) => {
state.code = code
},
SET_TOKEN: (state, token) => {
state.token = token
},
SET_INTRODUCTION: (state, introduction) => {
state.introduction = introduction
},
SET_SETTING: (state, setting) => {
state.setting = setting
},
SET_STATUS: (state, status) => {
state.status = status
},
SET_NAME: (state, name) => {
state.name = name
},
......@@ -78,7 +61,6 @@ const user = {
commit('SET_ROLES', data.roles)
commit('SET_NAME', data.name)
commit('SET_AVATAR', data.avatar)
commit('SET_INTRODUCTION', data.introduction)
resolve(response)
}).catch(error => {
reject(error)
......@@ -86,28 +68,20 @@ const user = {
})
},
// 第三方验证登录
// LoginByThirdparty({ commit, state }, code) {
// return new Promise((resolve, reject) => {
// commit('SET_CODE', code)
// loginByThirdparty(state.status, state.email, state.code).then(response => {
// commit('SET_TOKEN', response.data.token)
// setToken(response.data.token)
// resolve()
// }).catch(error => {
// reject(error)
// })
// })
// },
// 登出
LogOut({ commit, state }) {
LogOut({ commit, state, dispatch }) {
return new Promise((resolve, reject) => {
logout(state.token).then(() => {
commit('SET_TOKEN', '')
commit('SET_ROLES', [])
commit('SET_PERMS', [])
removeToken()
resetRouter()
// reset visited views and cached views
// to fixed https://github.com/PanJiaChen/vue-element-admin/issues/2485
dispatch('tagsView/delAllViews', null, { root: true })
resolve()
}).catch(error => {
reject(error)
......@@ -119,6 +93,7 @@ const user = {
FedLogOut({ commit }) {
return new Promise(resolve => {
commit('SET_TOKEN', '')
commit('SET_ROLES', [])
removeToken()
resolve()
})
......@@ -126,19 +101,23 @@ const user = {
// 动态修改权限
ChangeRoles({ commit, dispatch }, role) {
return new Promise(resolve => {
return new Promise(async resolve => {
commit('SET_TOKEN', role)
setToken(role)
getUserInfo(role).then(response => {
const data = response.data
commit('SET_ROLES', data.roles)
commit('SET_PERMS', data.perms)
commit('SET_NAME', data.name)
commit('SET_AVATAR', data.avatar)
commit('SET_INTRODUCTION', data.introduction)
dispatch('GenerateRoutes', data) // 动态修改权限后 重绘侧边菜单
resolve()
})
const { roles } = await dispatch('GetUserInfo')
resetRouter()
const accessRoutes = await dispatch('permission/generateRoutes', roles, { root: true })
// dynamically add accessible routes
router.addRoutes(accessRoutes)
// reset visited views and cached views
dispatch('tagsView/delAllViews', null, { root: true })
resolve()
})
}
}
......
......@@ -31,7 +31,7 @@
.fixed-width {
.el-button--mini {
padding: 7px 10px;
width: 60px;
min-width: 60px;
}
}
......
......@@ -6,7 +6,7 @@
/* theme color */
$--color-primary: #1890ff;
$--color-success: #13ce66;
$--color-warning: #FFBA00;
$--color-warning: #ffba00;
$--color-danger: #ff4949;
// $--color-info: #1E1E1E;
......@@ -17,10 +17,10 @@ $--button-font-weight: 400;
$--border-color-light: #dfe4ed;
$--border-color-lighter: #e6ebf5;
$--table-border:1px solid#dfe6ec;
$--table-border: 1px solid #dfe6ec;
/* icon font path, required */
$--font-path: '~element-ui/lib/theme-chalk/fonts';
$--font-path: "~element-ui/lib/theme-chalk/fonts";
@import "~element-ui/packages/theme-chalk/src/index";
......
......@@ -57,6 +57,11 @@
margin-right: 16px;
}
.sub-el-icon {
margin-right: 12px;
margin-left: -2px;
}
.el-menu {
border: none;
height: 100%;
......@@ -105,6 +110,11 @@
.svg-icon {
margin-left: 20px;
}
.sub-el-icon {
margin-right: 12px;
margin-left: -2px;
}
}
}
......@@ -118,6 +128,11 @@
margin-left: 20px;
}
.sub-el-icon {
margin-right: 12px;
margin-left: -2px;
}
.el-submenu__icon-arrow {
display: none;
}
......@@ -178,6 +193,10 @@
.svg-icon {
margin-right: 16px;
}
.sub-el-icon {
margin-right: 12px;
margin-left: -2px;
}
}
.nest-menu .el-submenu>.el-submenu__title,
......
/* eslint-disable */
require('script-loader!file-saver');
import { saveAs } from 'file-saver'
import XLSX from 'xlsx'
function generateArray(table) {
......@@ -145,20 +145,34 @@ export function export_table_to_excel(id) {
}
export function export_json_to_excel({
multiHeader = [],
header,
data,
filename,
merges = [],
autoWidth = true,
bookType= 'xlsx'
bookType = 'xlsx'
} = {}) {
/* original data */
filename = filename || 'excel-list'
data = [...data]
data.unshift(header);
for (let i = multiHeader.length - 1; i > -1; i--) {
data.unshift(multiHeader[i])
}
var ws_name = "SheetJS";
var wb = new Workbook(),
ws = sheet_from_array_of_arrays(data);
if (merges.length > 0) {
if (!ws['!merges']) ws['!merges'] = [];
merges.forEach(item => {
ws['!merges'].push(XLSX.utils.decode_range(item))
})
}
if (autoWidth) {
/*设置worksheet每列的最大宽度*/
const colWidth = data.map(row => row.map(val => {
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment