# leju-admin-vue **Repository Path**: bufanxy/leju-admin-vue ## Basic Information - **Project Name**: leju-admin-vue - **Description**: 乐居项目中后台管理系统. 基于vue2.x开发. - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 44 - **Forks**: 10 - **Created**: 2020-12-29 - **Last Updated**: 2024-02-23 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 乐居后台管理项目 ## 项目介绍 ​ 乐居后台管理是基于element-admin-template实现的一套乐居客户端的后台管理系统。后台管理系统包含大屏展示、权限管理、商品管理、订单管理、用户管理、营销管理、内容管理等模块。 ![dashboard](./images/dashboard.png) ### ## 项目演示 前端项目乐居演示地址: http://jinglins.gitee.io/leju 乐居后台项目在线预览地址:http://jinglins.gitee.io/music-center-backstage 乐居项目接口文档地址: http://leju.bufan.cloud/swagger-ui.html 演示账号:admin 密码:123456 > (注:请勿随意删改数据,本项目仅供学习交流使用,禁止商用) ![login](./images/login.png) ## 技术栈 | 技术 | 说明 | 官网 | | ------------- | ------------------------------------------------------------ | ------------------------------------------------------------ | | vue | js前端框架 | [vue](https://cn.vuejs.org/) | | vue-router | 官方的路由管理器。它和 Vue.js 的核心深度集成,让构建单页面应用变得易如反掌 | [vue-router](https://router.vuejs.org/zh/) | | vuex | 一个专为 Vue.js 应用程序开发的状态管理模式 | [vuex](https://vuex.vuejs.org/zh/) | | axios | 一个基于 promise 的 HTTP 库 | [axios](https://www.npmjs.com/package/axios) | | element-ui | 一套为开发者、设计师和产品经理准备的基于 Vue 2.0 的桌面端组件库 | [element-ui](https://element.eleme.cn/#/zh-CN) | | element-admin | 一个后台前端解决方案,它基于 vue 和 element-ui实现。它使用了最新的前端技术栈,内置了 i18 国际化解决方案,动态路由,权限验证,提炼了典型的业务模型,提供了丰富的功能组件,它可以帮助你快速搭建企业级中后台产品原型 | [element-admin](https://panjiachen.gitee.io/vue-element-admin-site/zh/) | | echarts | 百度开发的一款非常强大的数据可视化工具,可以流畅的运行在 PC 和移动设备上,兼容当前绝大部分浏览器,可高度个性化定制的数据可视化图表 | [echarts](https://echarts.apache.org/zh/index.html) | ## 开发运行 ### 前提 主机上需要`git`及`node环境` ### 拷贝及运行 ```shell # 1. 拷贝项目 git clone https://gitee.com/bufanxy/leju-admin-vue.git # 2. 设置淘宝镜像 npm config set registry=https://registry.npmmirror.com # 3. 进入拷贝目录下安装依赖 cnpm i # 4. 更改代理 项目根目录下 => 打开vue.config.js => 找到module.exports => 找到devServer => 找到proxy => 找到target => 修改为target: 'http://leju.bufan.cloud' # 5. 运行 npm run dev ``` ## 目录结构 ``` ├── build // 构建相关   ├── dist // 打包相关 ├── mock // mock 开发时模拟数据 ├── node_modules // 开发依赖包 ├── public // 公共资源目录 │   ├── index.html // 首页文件 ├── tests // 单元测试 ├── src // 源代码 │   ├── api // 所有请求存放目录 │   ├── assets // 静态资源存储目录 │   ├── components // 全局公用组件 │   ├── directive // 全局指令 │   ├── filtres // 全局过滤器 │   ├── icons // 项目所有 svg icons录 │ ├── layout // 全局 layout │ ├── mixins // 全局 mixins │   ├── router // 路由 │   ├── store // 全局store管理 │   ├── styles // 全局样式 │   ├── utils // 全局公用方法 │   ├── view // views 所有页面 │   ├── App.vue // 入口页面 │   └── main.js // 入口 加载组件 初始化等 │   └── permission.js // 权限管理 │   └── settings.js // 其他配置项 ├── .env.xxx // 环境变量配置 ├── .eslintrc.js // eslint 配置项 ├── .babel.config.js // babel-loader 配置 ├── .travis.yml // 自动化CI配置 ├── vue.config.js // vue-cli 配置 ├── postcss.config.js // postcss 配置 └── package.json // package.json ``` ## 主要功能简介 ### 主页 ​ 主要进行一些订单,销量等数据展示,给用户比较直观的数据体验。 ![数据大屏](./images/dashboard.png) ### 权限管理 #### 账号管理 ​ 管理员可以对用户进行增删改查 ​ ![account](./images/account.png) #### 角色管理 在该页面可以对账户分配角色 ![character](./images/character.png) #### 资源管理 权限路由的增删改查和初始化路由 ![resources](./images/resources.png) ### 商品管理 #### 商品列表 对乐居客户端展示的商品进行增删改查,并且可以生成每个商品的sku和对其进行增删改查操作 ![goods](./images/goods.png) #### 商品分类 商品的分类展示 ![category](./images/category.png) #### 品牌管理 对每个商品所属品牌的增删改查的管理 ### 订单管理 #### 订单列表 对乐居客户端商品的订单,进行发货,查看订单详情和物流情况以及关闭订单等操作 #### 退单列表 对乐居客户端进行退货的订单执行同意或者拒绝,以及关闭退单等操作 #### 地址管理 收发货地址的增删改查和默认收发货地址的改变 ### 注册用户管理 #### 用户列表 查看客户端注册用户的基本信息 ### 营销管理 #### 限时活动管理 可以对客户端显示的限时活动的增删改查操作 #### 广告列表 广告的增删改查,类似商品管理 ### 内容管理 #### 文章管理 可以对客户端显示的文章进行增删改查操作 #### 素材管理 素材图片的增删改查 ### 个人中心 #### 个人主页 当前后台管理系统登录的用户的基本信息展示 #### 个人设置 当前后台管理系统登录的用户的个人设置 ## 部分代码展示 ### 登录 1. 首先在vue.config文件配置webpack的proxy实现代理,在module.exports导出的对象里加devServer ```shell devServer: { port: 8080, open: true, overlay: { warnings: false, errors: true }, proxy: { '/(api|admin|lejuAdmin)': { target: host, // 80可以省略不写 所以代理地址和当前项目不是同一个地址!! changeOrigin: true, // 如果是跨域 需要添加 pathRewrite: { // ['/admin']: '/abc' /admin/xx/xx ==> /abc/xx/xx } } } }, ``` 2. 使用axios封装好自己要用的request.js ```shell import axios from 'axios' import { Message } from 'element-ui' import { getToken, clearUserCache } from '@/utils/myAuth' import router from '@/router' // create an axios instance // process.env 指的是当前的运行环境 所对应的 配置文件 const service = axios.create({ // baseURL: 'http://leju.bufan.cloud', // url = base url + request url // withCredentials: true // 跨域携带cookies需要,token认证不需要 timeout: 5000 // 请求超时时间 }) // request interceptor service.interceptors.request.use( config => { // do something before request is sent // 如果本地有token 携带过去 var token = getToken() if (token) { config.headers['token'] = token } return config }, error => { // do something with request error console.log(error) // for debug return Promise.reject(error) } ) // response interceptor service.interceptors.response.use( response => { const res = response.data // token无效 会返回20002 if (res.code === 20002) { Message({ message: res.message + ',请重新登陆!', type: 'error', duration: 5 * 1000 }) // 清除用户缓存 clearUserCache() router.push('/login') } return res }, error => { console.log('err' + error) // for debug Message({ message: error.message, type: 'error', duration: 5 * 1000 }) return Promise.reject(error) } ) /** * 合并get与post提交 * @param {} config */ function http(config) { // 动手脚 const axiosConfig = { url: config.url, method: config.method } // 如果data存在 而且不为空对象 if (config.data) { if (Object.keys(config.data).length > 0) { var key = config.method.toLowerCase() === 'get' ? 'params' : 'data' axiosConfig[key] = config.data } if (config.data.constructor === FormData) { axiosConfig.data = config.data } } if (config.headers) { axiosConfig.headers = config.headers } return service(axiosConfig) } export default http ``` 3. 调用request 封装登录api ```shell import request from '@/api/request' function doLogin(data) { return request({ url: '/lejuAdmin/index/login', // 相对路径 method: 'post', data }) } ``` 4. 在login/index.vue登录页面里调用doLogin方法,并将token和userInfo存入localstorage中 ```shell handleLogin() { loginApi .doLogin({ ...this.loginForm }) .then((res) => { if (res.success) { // 1.获取用户信息 var token = res.data.token var info = res.data.userInfo // 2. 存储用户信息和token 存到哪? 如果用户信息频繁变化建议存储ls/vuex ; 如果不经常变化直接存储ls setToken(token) setUserInfo(info) this.$router.push({ path: '/' }) } else { this.$message.error('登陆失败!') } }) }, ``` 5. 在permission.js全局配置路由导航,判断token存在与否的逻辑 ```shell router.beforeEach(async(to, from, next) => { // start progress bar NProgress.start() // set page title document.title = getPageTitle(to.meta.title) // // shtest // next() // return // 获取token var token = getToken() if (token) { // 如果有token 且跳往 登录页面,则默认跳向主页 if (to.path === '/login') { next('/') NProgress.done() return } // 判断权限 if (store.state.user.asyncRoutes.length > 0) { // 把当前页面的路由权限存入vuex if (to.meta && to.meta.permissionValues) { store.commit('user/RESET_BTN_PERMI', to.meta.permissionValues) } next() } else { // 重新获取 await store.dispatch('user/getInitMenus') .then(res => { // 把当前页面的路由权限存入vuex if (to.meta && to.meta.permissionValues) { store.commit('user/RESET_BTN_PERMI', to.meta.permissionValues) } next(to.path) }).catch(err => { // 如果code等于20001说明 路由有脏数据,需要初始化一次 if (err.code === 20001) { Message.error('权限动态路由出错,请在资源管理初始化路由') next() } else { Message.error('权限动态路由出错') clearUserCache() next('/login') } NProgress.done() }) } } else { console.log('没有token') // 清下页面权限 store.commit('user/CLEAR_BTN_PEREMI') /* has no token*/ if (whiteList.indexOf(to.path) !== -1) { // in the free login whitelist, go directly next() } else { // other pages that do not have permission to access are redirected to the login page. next('/login') NProgress.done() } } }) router.afterEach(() => { // finish progress bar NProgress.done() }) ```