├── src
├── vuex
│ ├── modules
│ │ ├── permission.js
│ │ ├── merchant.js
│ │ ├── user.js
│ │ ├── app.js
│ │ ├── goods.js
│ │ ├── admin-user.js
│ │ └── auth-config.js
│ ├── getters.js
│ ├── mutations.js
│ ├── actions.js
│ ├── store.js
│ └── mutation-types.js
├── utils
│ ├── serverConfig.js
│ ├── storageUtils.js
│ ├── tools.js
│ ├── dateUtils.js
│ └── request.js
├── assets
│ ├── logo.png
│ ├── fonts
│ │ ├── iconfont.eot
│ │ ├── iconfont.ttf
│ │ ├── iconfont.woff
│ │ ├── iconfont.woff2
│ │ ├── iconfont.json
│ │ ├── iconfont.css
│ │ └── demo.css
│ ├── fontss
│ │ ├── iconfont.eot
│ │ ├── iconfont.ttf
│ │ ├── iconfont.woff
│ │ ├── iconfont.woff2
│ │ ├── iconfont.json
│ │ ├── iconfont.css
│ │ ├── iconfont.svg
│ │ └── iconfont.js
│ └── css
│ │ └── reset.css
├── views
│ ├── auth
│ │ ├── Auth.vue
│ │ ├── RoleList.vue
│ │ └── UserList.vue
│ ├── order
│ │ └── Order.vue
│ ├── activity
│ │ ├── Activity.vue
│ │ └── ActivityList.vue
│ ├── comment
│ │ └── Comment.vue
│ ├── goods
│ │ ├── Goods.vue
│ │ ├── GoodsList.vue
│ │ ├── Detail.vue
│ │ └── GoodsService.vue
│ ├── merchant
│ │ └── Merchant.vue
│ ├── banner
│ │ ├── Banner.vue
│ │ └── BannerList.vue
│ ├── category
│ │ ├── Category.vue
│ │ ├── CategoryList.vue
│ │ └── AddCategory.vue
│ ├── home
│ │ └── Home.vue
│ └── login
│ │ └── Login.vue
├── plugins
│ └── element.js
├── styles
│ ├── filter-area.scss
│ ├── dialog.scss
│ ├── header.scss
│ ├── index.scss
│ └── siderbar.scss
├── App.vue
├── api
│ ├── activity.js
│ ├── comment.js
│ ├── merchant.js
│ ├── order.js
│ ├── banner.js
│ ├── category.js
│ ├── index.js
│ ├── goods.js
│ └── user.js
├── main-prod.js
├── main-dev.js
├── components
│ ├── MyBread
│ │ └── MyBread.vue
│ ├── Aside
│ │ ├── Item.vue
│ │ └── Aside.vue
│ └── Header
│ │ └── Header.vue
├── router
│ ├── index.js
│ └── routes.js
├── mixins
│ └── ResizeHandle.js
└── config
│ └── menuConfig.js
├── .browserslistrc
├── public
├── favicon.ico
├── static
│ └── images
│ │ └── weather
│ │ ├── lei.gif
│ │ ├── qing.gif
│ │ ├── wu.gif
│ │ ├── xue.gif
│ │ ├── yin.gif
│ │ ├── yu.gif
│ │ ├── yun.gif
│ │ ├── bingbao.gif
│ │ └── shachen.gif
└── index.html
├── babel.config.js
├── .gitignore
├── .eslintrc.js
├── README.md
├── package.json.bak
├── package.json
├── vue.config.js
└── vue.config.js.bak
/src/vuex/modules/permission.js:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.browserslistrc:
--------------------------------------------------------------------------------
1 | > 1%
2 | last 2 versions
3 |
--------------------------------------------------------------------------------
/src/utils/serverConfig.js:
--------------------------------------------------------------------------------
1 | export const serverURL = 'http://dev.shubuzuo.top/' // 开发环境
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/coder-xc/mini-boss/HEAD/public/favicon.ico
--------------------------------------------------------------------------------
/src/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/coder-xc/mini-boss/HEAD/src/assets/logo.png
--------------------------------------------------------------------------------
/src/views/auth/Auth.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: [
3 | '@vue/cli-plugin-babel/preset'
4 | ]
5 | }
6 |
--------------------------------------------------------------------------------
/src/views/order/Order.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/src/assets/fonts/iconfont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/coder-xc/mini-boss/HEAD/src/assets/fonts/iconfont.eot
--------------------------------------------------------------------------------
/src/assets/fonts/iconfont.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/coder-xc/mini-boss/HEAD/src/assets/fonts/iconfont.ttf
--------------------------------------------------------------------------------
/src/views/activity/Activity.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/src/views/comment/Comment.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/src/views/goods/Goods.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/src/views/merchant/Merchant.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/src/assets/fonts/iconfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/coder-xc/mini-boss/HEAD/src/assets/fonts/iconfont.woff
--------------------------------------------------------------------------------
/src/assets/fonts/iconfont.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/coder-xc/mini-boss/HEAD/src/assets/fonts/iconfont.woff2
--------------------------------------------------------------------------------
/src/assets/fontss/iconfont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/coder-xc/mini-boss/HEAD/src/assets/fontss/iconfont.eot
--------------------------------------------------------------------------------
/src/assets/fontss/iconfont.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/coder-xc/mini-boss/HEAD/src/assets/fontss/iconfont.ttf
--------------------------------------------------------------------------------
/src/assets/fontss/iconfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/coder-xc/mini-boss/HEAD/src/assets/fontss/iconfont.woff
--------------------------------------------------------------------------------
/src/assets/fontss/iconfont.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/coder-xc/mini-boss/HEAD/src/assets/fontss/iconfont.woff2
--------------------------------------------------------------------------------
/src/views/banner/Banner.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/src/views/category/Category.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/public/static/images/weather/lei.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/coder-xc/mini-boss/HEAD/public/static/images/weather/lei.gif
--------------------------------------------------------------------------------
/public/static/images/weather/qing.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/coder-xc/mini-boss/HEAD/public/static/images/weather/qing.gif
--------------------------------------------------------------------------------
/public/static/images/weather/wu.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/coder-xc/mini-boss/HEAD/public/static/images/weather/wu.gif
--------------------------------------------------------------------------------
/public/static/images/weather/xue.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/coder-xc/mini-boss/HEAD/public/static/images/weather/xue.gif
--------------------------------------------------------------------------------
/public/static/images/weather/yin.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/coder-xc/mini-boss/HEAD/public/static/images/weather/yin.gif
--------------------------------------------------------------------------------
/public/static/images/weather/yu.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/coder-xc/mini-boss/HEAD/public/static/images/weather/yu.gif
--------------------------------------------------------------------------------
/public/static/images/weather/yun.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/coder-xc/mini-boss/HEAD/public/static/images/weather/yun.gif
--------------------------------------------------------------------------------
/public/static/images/weather/bingbao.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/coder-xc/mini-boss/HEAD/public/static/images/weather/bingbao.gif
--------------------------------------------------------------------------------
/public/static/images/weather/shachen.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/coder-xc/mini-boss/HEAD/public/static/images/weather/shachen.gif
--------------------------------------------------------------------------------
/src/vuex/getters.js:
--------------------------------------------------------------------------------
1 | export default {
2 | isCollapseMenu: state => state.isCollapseMenu,
3 | sidebar: state => state.app.sidebar,
4 | }
--------------------------------------------------------------------------------
/src/plugins/element.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import Element from 'element-ui'
3 | import 'element-ui/lib/theme-chalk/index.css'
4 |
5 | Vue.use(Element)
6 |
--------------------------------------------------------------------------------
/src/styles/filter-area.scss:
--------------------------------------------------------------------------------
1 | #app {
2 | .filter {
3 | .input {
4 | margin-bottom: 10px;
5 | margin-right: 10px;
6 | }
7 | .search, .add {
8 | margin-bottom: 10px;
9 | }
10 | }
11 | }
--------------------------------------------------------------------------------
/src/styles/dialog.scss:
--------------------------------------------------------------------------------
1 | #app {
2 | .mobile {
3 | .el-dialog {
4 | width: 350px;
5 | }
6 | }
7 | .el-dialog {
8 | width: 650px;
9 | .pre-img {
10 | width: 100%;
11 | }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/vuex/mutations.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 包含n个用于直接更新状态数据的方法的对象
3 | */
4 |
5 | import { TOGGLE_COLLAPSE } from './mutation-types'
6 |
7 | export default {
8 | [TOGGLE_COLLAPSE](state) { // 总state
9 | state.isCollapseMenu = !state.isCollapseMenu;
10 | }
11 | }
--------------------------------------------------------------------------------
/src/vuex/modules/merchant.js:
--------------------------------------------------------------------------------
1 | const state = {
2 |
3 | }
4 |
5 | const mutations = {
6 |
7 | }
8 |
9 | const actions = {
10 |
11 | }
12 |
13 | const getters = {}
14 |
15 | export default {
16 | state,
17 | mutations,
18 | actions,
19 | getters
20 | }
--------------------------------------------------------------------------------
/src/vuex/modules/user.js:
--------------------------------------------------------------------------------
1 | const state = {
2 |
3 | }
4 |
5 | const mutations = {
6 |
7 | }
8 |
9 | const actions = {
10 |
11 | }
12 |
13 | const getters = {}
14 |
15 | export default {
16 | state,
17 | mutations,
18 | actions,
19 | getters
20 | }
--------------------------------------------------------------------------------
/src/vuex/actions.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 包含n个用于间接更新状态数据的方法的对象
3 | * 可以包含异步/逻辑操作代码
4 | */
5 | import { TOGGLE_COLLAPSE } from './mutation-types'
6 | export default {
7 | toggleCollapse({ commit }) { // state是根/总state
8 | commit(TOGGLE_COLLAPSE)
9 | // commit('xxx') // 找到所有同名匹配的mutation执行
10 | }
11 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /dist
4 |
5 | # local env files
6 | .env.local
7 | .env.*.local
8 |
9 | # Log files
10 | npm-debug.log*
11 | yarn-debug.log*
12 | yarn-error.log*
13 |
14 | # Editor directories and files
15 | .idea
16 | .vscode
17 | *.suo
18 | *.ntvs*
19 | *.njsproj
20 | *.sln
21 | *.sw?
22 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | env: {
4 | node: true
5 | },
6 | 'extends': [
7 | 'plugin:vue/essential',
8 | 'eslint:recommended'
9 | ],
10 | rules: {
11 | 'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
12 | 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
13 | 'no-unused-vars': process.env.NODE_ENV === 'production' ? 'error' : 'off'
14 | },
15 | parserOptions: {
16 | parser: 'babel-eslint'
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/utils/storageUtils.js:
--------------------------------------------------------------------------------
1 | /**
2 | 操作loacl数据的工具函数模块
3 | */
4 | import store from 'store'
5 |
6 |
7 | const TOKEN = 'token'
8 |
9 | export default {
10 | // 保存token
11 | saveToken(token) {
12 | store.set(TOKEN, token)
13 | },
14 |
15 |
16 | // 需要返回一个 token,如果没有,返回空字符串
17 | getToken() {
18 | return store.get(TOKEN) || ""
19 | },
20 |
21 | // 删除保存的user
22 | removeToken() {
23 | // localStorage.removeItem(USER_KEY)
24 | store.remove(TOKEN)
25 | },
26 | }
--------------------------------------------------------------------------------
/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
10 |
11 |
--------------------------------------------------------------------------------
/src/styles/header.scss:
--------------------------------------------------------------------------------
1 | #app {
2 | .mobile {
3 | .el-header {
4 | .el-row--flex {
5 | display: block;
6 | }
7 | .time-weather-toggle {
8 | display: flex;
9 | align-items: center;
10 | font-size: 14px;
11 | padding: 0 20px;
12 | margin-top: 10px;
13 | }
14 | .userinfo {
15 | margin-top: 10px;
16 | }
17 | }
18 | .welcome {
19 | display: flex;
20 | height: 100%;
21 | justify-content: center;
22 | align-items: center;
23 | font-size: 20px;
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/api/activity.js:
--------------------------------------------------------------------------------
1 | import request from '@/utils/request'
2 |
3 | /**
4 | * 获取活动列表
5 | */
6 | export const reqActiveList = (query) => request({
7 | url: `/actions?query=${JSON.stringify(query)}`
8 | })
9 |
10 | /**
11 | * 添加/修改活动
12 | */
13 | export const addUpdateActive = ({ title, icon, _id }) => request({
14 | url: `/actions${_id ? `/${_id}` : ''}`,
15 | method: `${_id ? 'PUT' : 'POST'}`,
16 | data: {
17 | title,
18 | icon
19 | }
20 | })
21 |
22 | /**
23 | * 删除活动
24 | */
25 | export const delActive = ({ _id }) => request({
26 | url: `/actions/${_id}`,
27 | method: 'DELETE'
28 | })
--------------------------------------------------------------------------------
/src/api/comment.js:
--------------------------------------------------------------------------------
1 | import request from '@/utils/request'
2 |
3 | /**
4 | * 获取评论
5 | */
6 | export const reqComment = (query) => request({
7 | url: `/comments?query=${JSON.stringify(query)}`
8 | })
9 |
10 | /**
11 | * 添加/修改评论
12 | */
13 | export const reqAddUpdateComment = ({ order, message, images, _id }) => request({
14 | url: `/comments${_id ? `/${_id}` : ""}`,
15 | method: `${_id ? "PUT" : "POST"}`,
16 | data: {
17 | order,
18 | message,
19 | images
20 | }
21 | })
22 |
23 | /**
24 | * 删除评论
25 | */
26 | export const reqDelComment = ({ _id }) => request({
27 | url: `/comments/${_id}`,
28 | method: 'DELETE'
29 | })
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 此项目为小程序商城后台管理系统
2 | 1. 该项目使用的技术栈为Vue全家桶 + ES6 + Element UI + Axios
3 | 2. 包含了商品分类,商品管理,商家管理,订单管理和用户管理等子模块
4 | 3. 采用模块化、组件化、工程化的模式开发(模块化、组件化和工程化详解戳:[谈谈前端工程化、组件化、模块化以及自动化](https://www.xcio.cn/index.php/archives/62/).)
5 |
6 | ## 项目依赖安装
7 | ```
8 | npm install
9 |
10 | cnpm install
11 |
12 | yarn install
13 | ```
14 |
15 | ### 启动项目(开发环境)
16 | ```
17 | npm run serve
18 | ```
19 |
20 | ### 项目打包(生产环境打包)
21 | ```
22 | npm run build
23 | ```
24 |
25 | ### 生产环境运行
26 | ```
27 | serve -s dist
28 | ```
29 |
30 | ### Lints and fixes files
31 | ```
32 | yarn lint
33 |
34 | ```
35 |
36 | ### Customize configuration
37 | See [Configuration Reference](https://cli.vuejs.org/config/).
38 |
--------------------------------------------------------------------------------
/src/utils/tools.js:
--------------------------------------------------------------------------------
1 | /* 工具方法模块 */
2 |
3 |
4 | /**
5 | * 合并数组并去重
6 | * @param {Array} origin 要被合并的数组
7 | * @param {Array} newArr 合并到origin的数组
8 | * @returns 返回一个新的数组(已经合并+去重)
9 | */
10 | export function merge(origin, newArr) {
11 | let tempObj = {};
12 | const resultArr = [...origin];
13 | if (!newArr || newArr.length === 0) {
14 | return resultArr;
15 | }
16 | resultArr.forEach(item => {
17 | if(!tempObj[item._id]) {
18 | tempObj[item._id] = true;
19 | }
20 | })
21 | return newArr.reduce((pre, item) => {
22 | if(!tempObj[item._id]) {
23 | tempObj[item._id] = true;
24 | pre.push(item)
25 | }
26 | return pre;
27 | }, resultArr);
28 | }
--------------------------------------------------------------------------------
/src/styles/index.scss:
--------------------------------------------------------------------------------
1 | @import "@/styles/siderbar.scss";
2 | @import "@/styles/header.scss";
3 | @import "@/styles/filter-area.scss";
4 | @import "@/styles/dialog.scss";
5 |
6 | /* 全局公共样式 */
7 | #app,
8 | body,
9 | html {
10 | color: rgba(0, 0, 0, 0.65);
11 | }
12 |
13 | .el-card {
14 | margin-top: 15px;
15 | box-shadow: 0 1px 1px rgba(0, 0, 0, 0.15) !important;
16 | }
17 |
18 | .el-pagination,
19 | .el-table {
20 | margin-top: 15px;
21 | }
22 |
23 | .el-table {
24 | font-size: 12px;
25 | }
26 |
27 | .ql-editor {
28 | min-height: 300px;
29 | }
30 |
31 | .el-upload-list__item {
32 | transition: none !important;
33 | }
34 |
35 | .el-message-box {
36 | max-width: 100%;
37 | }
38 |
--------------------------------------------------------------------------------
/src/main-prod.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import App from './App.vue'
3 | import MyBread from 'components/MyBread/MyBread.vue'
4 | import router from './router'
5 | import store from './vuex/store'
6 | import './styles/index.scss'
7 | import './assets/css/reset.css';
8 | import './assets/fonts/iconfont.css'
9 |
10 |
11 |
12 |
13 | // 引入富文本编辑器
14 | import VueQuillEditor from 'vue-quill-editor'
15 |
16 | // require styles
17 | import 'quill/dist/quill.core.css'
18 | import 'quill/dist/quill.snow.css'
19 | import 'quill/dist/quill.bubble.css'
20 |
21 | Vue.config.productionTip = false
22 |
23 | Vue.use(VueQuillEditor)
24 | Vue.component(MyBread.name, MyBread)
25 |
26 |
27 | new Vue({
28 | router,
29 | render: h => h(App),
30 | store
31 | }).$mount('#app')
--------------------------------------------------------------------------------
/src/utils/dateUtils.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 包含n个日期时间处理的工具函数模块
3 | */
4 |
5 | /**
6 | * 格式化日期
7 | */
8 | export function formateDate(time) {
9 | if (!time) return ''
10 | const date = new Date(time)
11 | let month = date.getMonth() + 1;
12 | let day = date.getDate();
13 | let hour = date.getHours();
14 | let min = date.getMinutes();
15 | let seconds = date.getSeconds();
16 |
17 | if (seconds < 10) {
18 | seconds = `0${seconds}`;
19 | }
20 | if (min < 10) {
21 | min = `0${min}`;
22 | }
23 | if (hour < 10) {
24 | hour = `0${hour}`;
25 | }
26 | if (month < 10) {
27 | month = `0${month}`;
28 | }
29 | if (day < 10) {
30 | day = `0${day}`;
31 | }
32 | return `${date.getFullYear()}-${month}-${day} ${hour}:${min}:${seconds}`;
33 | }
--------------------------------------------------------------------------------
/src/main-dev.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import App from './App.vue'
3 | import MyBread from 'components/MyBread/MyBread.vue'
4 | import router from './router'
5 | import store from './vuex/store'
6 | // 全局css
7 | import './styles/index.scss'
8 | // 基本样式
9 | import './assets/css/reset.css';
10 | // iconfont图标库
11 | import './assets/fonts/iconfont.css'
12 | // 引入富文本编辑器
13 | import VueQuillEditor from 'vue-quill-editor'
14 | // 引入富文本编辑器 css 样式
15 | import 'quill/dist/quill.core.css'
16 | import 'quill/dist/quill.snow.css'
17 | import 'quill/dist/quill.bubble.css'
18 |
19 | Vue.config.productionTip = false
20 |
21 | Vue.use(VueQuillEditor)
22 | Vue.component(MyBread.name, MyBread)
23 |
24 |
25 | new Vue({
26 | router,
27 | render: h => h(App),
28 | store
29 | }).$mount('#app')
--------------------------------------------------------------------------------
/src/api/merchant.js:
--------------------------------------------------------------------------------
1 | import request from '@/utils/request'
2 |
3 |
4 | /**
5 | * 获取店铺列表
6 | */
7 | export const reqMerchants = (query) => request(`/selles?query=${JSON.stringify(query)}`);
8 |
9 | /**
10 | * 添加/修改店铺
11 | */
12 | export const reqAddUpdateMerchant = ({ name, logo, commodities, salesVolume, commoditiesCount, appraise, collectCount, _id }) => request({
13 | url: `/selles${_id ? `/${_id}` : ""}`,
14 | method: `${_id ? "PUT" : "POST"}`,
15 | data: {
16 | name,
17 | logo,
18 | commodities,
19 | salesVolume,
20 | commoditiesCount,
21 | appraise,
22 | collectCount
23 | }
24 | })
25 |
26 | /**
27 | * 删除店铺
28 | */
29 | export const reqDelMerchant = ({ _id }) => request({
30 | url: `/selles/${_id}`,
31 | method: 'DELETE'
32 | })
33 |
--------------------------------------------------------------------------------
/src/api/order.js:
--------------------------------------------------------------------------------
1 | import request from '@/utils/request'
2 |
3 | /**
4 | * 获取订单列表
5 | */
6 | export const reqOrders = (query) => {
7 | const params = JSON.parse(JSON.stringify(query))
8 | // if(!params.where.orderNum.$regex) {
9 | // delete params.where
10 | // }
11 | return request({
12 | url: `/orders?query=${JSON.stringify(params)}`
13 | })
14 | }
15 |
16 | /**
17 | * 添加/修改订单
18 | */
19 | export const reqAddUpdateOrder = ({ commoditis, user, _id }) => request({
20 | url: `/orders${_id ? `/${_id}` : ""}`,
21 | method: `${_id ? 'PUT' : 'POST'}`,
22 | data: {
23 | commoditis,
24 | user
25 | }
26 | })
27 |
28 | /**
29 | * 删除订单
30 | */
31 | export const reqDelOrder = ({ _id }) => request({
32 | url: `/orders/${_id}`,
33 | method: 'DELETE'
34 | })
--------------------------------------------------------------------------------
/src/api/banner.js:
--------------------------------------------------------------------------------
1 | import request from '@/utils/request'
2 |
3 | /**
4 | * 获取轮播图
5 | */
6 | export const reqBanner = (query) => {
7 | // debugger
8 | return request({
9 | url: `/banners?query=${JSON.stringify(query)}`,
10 | headers: {
11 | checkToken: true
12 | }
13 | })
14 | }
15 |
16 | /**
17 | * 添加或修改轮播图
18 | */
19 | export const addUpdateBanner = ({ title, url, index, _id }) => request({
20 | url: `/banners${_id ? `/${_id}` : ''}`,
21 | method: `${_id ? 'PUT' : 'POST'}`,
22 | data: {
23 | title,
24 | url,
25 | index
26 | },
27 | headers: {
28 | checkToken: true
29 | }
30 | })
31 |
32 | /**
33 | * 删除轮播图
34 | */
35 | export const delBanner = (_id) => request({
36 | url: `/banners/${_id}`,
37 | method: 'DELETE',
38 | headers: {
39 | checkToken: true
40 | }
41 | })
--------------------------------------------------------------------------------
/package.json.bak:
--------------------------------------------------------------------------------
1 | {
2 | "name": "mini-boss",
3 | "version": "0.1.0",
4 | "private": true,
5 | "scripts": {
6 | "serve": "vue-cli-service serve",
7 | "build": "vue-cli-service build",
8 | "lint": "vue-cli-service lint"
9 | },
10 | "dependencies": {
11 | "core-js": "^3.4.4",
12 | "element-ui": "^2.4.5",
13 | "sass-loader": "^8.0.2",
14 | "vue": "^2.6.10",
15 | "vue-router": "^3.1.3"
16 | },
17 | "devDependencies": {
18 | "@vue/cli-plugin-babel": "^4.1.0",
19 | "@vue/cli-plugin-eslint": "^4.1.0",
20 | "@vue/cli-plugin-router": "^4.1.0",
21 | "@vue/cli-service": "^4.1.0",
22 | "babel-eslint": "^10.0.3",
23 | "eslint": "^5.16.0",
24 | "eslint-plugin-vue": "^5.0.0",
25 | "vue-cli-plugin-element": "^1.0.1",
26 | "vue-template-compiler": "^2.6.10"
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/vuex/store.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue';
2 | import Vuex from 'vuex';
3 |
4 | import mutations from './mutations';
5 | import actions from './actions';
6 | import getters from './getters'
7 |
8 | import goods from './modules/goods';
9 | import merchant from './modules/merchant';
10 | import adminUser from './modules/admin-user';
11 | import user from './modules/user';
12 | import app from './modules/app'
13 | // import permission from './modules/permission'
14 | import authConfig from './modules/auth-config'
15 |
16 | Vue.use(Vuex);
17 |
18 | export default new Vuex.Store({
19 | state: {
20 | isCollapseMenu: false,
21 | },
22 | mutations,
23 | actions,
24 | getters,
25 | modules: {
26 | goods,
27 | merchant,
28 | adminUser,
29 | user,
30 | app,
31 | // permission,
32 | authConfig
33 | }
34 | })
--------------------------------------------------------------------------------
/src/api/category.js:
--------------------------------------------------------------------------------
1 | import request from '@/utils/request'
2 |
3 | /**
4 | * 获取分类列表
5 | */
6 | export const reqCategories = (query) => request({
7 | url: `/categories?query=${JSON.stringify(query)}`,
8 | headers: {
9 | checkToken: true
10 | }
11 | })
12 |
13 | /**
14 | * 添加或修改分类
15 | */
16 | export const reqAddUpdateCategory = ({ parent = '', categoryName: name, url = '', attributes, _id }) => request({
17 | url: `/categories${_id ? `/${_id}` : ''}`,
18 | method: `${_id ? 'PUT' : 'POST'}`,
19 | data: {
20 | parent,
21 | name,
22 | url,
23 | attributes
24 | },
25 | headers: {
26 | checkToken: true
27 | }
28 | })
29 |
30 | /**
31 | * 删除分类
32 | */
33 | export const deleteCategory = (_id) => request({
34 | url: `/categories/${_id}`,
35 | method: 'DELETE',
36 | headers: {
37 | checkToken: true
38 | }
39 | })
--------------------------------------------------------------------------------
/src/components/MyBread/MyBread.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{item.meta.title}}
5 |
6 |
7 |
8 |
38 |
--------------------------------------------------------------------------------
/src/vuex/mutation-types.js:
--------------------------------------------------------------------------------
1 | export const RECEIVE_TOKEN = 'receive_token';
2 | export const RECEIVE_ADMIN_USER = 'receive_admin_user';
3 | export const LOGOUT = 'logout';
4 | export const RECEIVE_USER_LIST = 'receive_user_list';
5 | export const DELETE_USER = 'delete_user'
6 | export const RECEIVE_ACTIVE_LIST = 'receive_active_list';
7 | export const RECEIVE_GOODS_LIST = 'receive_goods_list'
8 | export const RECEIVE_GOODS = 'receive_goods'
9 | export const TOGGLE_COLLAPSE = 'toggle_collapse'
10 | export const RECEIVE_GOODS_SERVICE = 'receive_goods_service';
11 | export const RECEIVE_CATEGORIES = 'receive_categorise';
12 | export const RECEIVE_MERCHANTS = 'receive_merchants';
13 | export const RECEIVE_ORDERS = 'receive_orders';
14 | export const RECEIVE_BACK_ROUTE_PATH = 'receive_back_route_path'
15 | export const RECEIVE_COMMENTS = 'receive_comments';
16 | export const RECEIVE_ROLE_LIST = 'receive_role_list';
17 | export const PERMISSION_MAPPING_VIEW = 'permission_mapping_view';
18 | export const CLEAR_CACHE = 'clear_cache';
--------------------------------------------------------------------------------
/src/api/index.js:
--------------------------------------------------------------------------------
1 | import request from '@/utils/request'
2 | import jsonp from 'jsonp'
3 | import { Message } from 'element-ui'
4 |
5 | // 发送 jsonp 请求得到天气信息
6 | export const reqWeather = () => {
7 | return new Promise((resolve) => {
8 | // 执行器函数:内部去执行异步任务,
9 | // 成功了调用 resolve(), 失败了不调用 reject(),直接提示错误
10 | const url = `https://tianqiapi.com/api?version=v6&appid=81661511&appsecret=0oTDWd9T&vue=1`
11 | jsonp(url, {}, (err, data) => {
12 | if (!err) {
13 | const { wea_img, wea } = data;
14 | resolve({ wea_img, wea });
15 | } else {
16 | Message.error('获取天气信息失败');
17 | }
18 | })
19 | })
20 | }
21 |
22 | /**
23 | * 上传图片
24 | */
25 | export const uploadImg = (file) => {
26 | let param = new FormData() // 创建form对象
27 | param.append('file', file) // 通过append向form对象添加数据
28 | let config = {
29 | headers: {
30 | 'Content-Type': 'multipart/form-data',
31 | checkToken: true
32 | }
33 | }
34 | return request.post('/upload', param, config)
35 | }
--------------------------------------------------------------------------------
/src/router/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import VueRouter from 'vue-router'
3 | import routes from './routes'
4 | import store from '@/vuex/store'
5 |
6 | Vue.use(VueRouter)
7 |
8 | // 修改路由push方法,阻止重复点击报错
9 | const originalPush = VueRouter.prototype.push;
10 | VueRouter.prototype.push = function push(location) {
11 | return originalPush.call(this, location).catch(err => err);
12 | };
13 |
14 | // 修改路由replace方法,阻止重复点击报错
15 | const originalReplace = VueRouter.prototype.replace;
16 | VueRouter.prototype.replace = function replace(location) {
17 | return originalReplace.call(this, location).catch(err => err);
18 | };
19 |
20 | const router = new VueRouter({
21 | mode: 'history',
22 | routes,
23 | // base: '/shopadmin/', // 生产环境打包设置
24 | })
25 |
26 | router.beforeEach((to, from, next) => {
27 | const token = store.state.adminUser.token;
28 | if (to.path === '/login') {
29 | if (token) {
30 | next('/home')
31 | } else {
32 | next()
33 | }
34 | }
35 | next()
36 | })
37 |
38 | export default router
39 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "mini-boss",
3 | "version": "0.1.0",
4 | "private": true,
5 | "scripts": {
6 | "serve": "vue-cli-service serve",
7 | "build": "vue-cli-service build",
8 | "lint": "vue-cli-service lint"
9 | },
10 | "dependencies": {
11 | "axios": "^0.19.0",
12 | "core-js": "^3.4.4",
13 | "element-ui": "^2.4.5",
14 | "jsonp": "^0.2.1",
15 | "lodash": "^4.17.15",
16 | "store": "^2.0.12",
17 | "vue": "^2.6.10",
18 | "vue-quill-editor": "^3.0.6",
19 | "vue-router": "^3.1.3",
20 | "vuex": "^3.1.2"
21 | },
22 | "devDependencies": {
23 | "@vue/cli-plugin-babel": "^4.1.0",
24 | "@vue/cli-plugin-eslint": "^4.1.0",
25 | "@vue/cli-plugin-router": "^4.1.0",
26 | "@vue/cli-service": "^4.1.0",
27 | "babel-eslint": "^10.0.3",
28 | "eslint": "^5.16.0",
29 | "eslint-plugin-vue": "^5.0.0",
30 | "node-sass": "^4.13.1",
31 | "sass-loader": "^8.0.2",
32 | "vue-cli-plugin-element": "^1.0.1",
33 | "vue-template-compiler": "^2.6.10"
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/vue.config.js:
--------------------------------------------------------------------------------
1 | // vue.config.js
2 | const path = require('path')
3 |
4 | /* 根据指定目录名得到根目录的绝对路径 */
5 | function resolve(dir) {
6 | return path.join(__dirname, dir)
7 | }
8 |
9 | module.exports = {
10 | /* 编写webpack支持的配置 */
11 | configureWebpack: {
12 | resolve: {
13 | extensions: ['.js', '.vue', '.json'],
14 | alias: {
15 | '@': resolve('src'),
16 | 'components': resolve('src/components'),
17 | 'views': resolve('src/views'),
18 | 'api': resolve('src/api')
19 | }
20 | },
21 | externals: {
22 | 'vue': 'Vue',
23 | 'element-ui': 'ELEMENT',
24 | 'vue-quill-editor': "VueQuillEditor"
25 | },
26 | },
27 | chainWebpack: config => { //修改webpack打包的入口文件。需要在根目录建两个对应入口js文件
28 | config.when(process.env.NODE_ENV === 'production', config => {
29 | config.entry('app').clear().add('./src/main-prod.js') //生产环境
30 | })
31 | config.when(process.env.NODE_ENV === 'development', config => {
32 | config.entry('app').clear().add('./src/main-dev.js') //开发环境
33 | })
34 | },
35 | productionSourceMap: false,
36 | }
--------------------------------------------------------------------------------
/src/mixins/ResizeHandle.js:
--------------------------------------------------------------------------------
1 | import store from '@/vuex/store'
2 |
3 | const { body } = document
4 | const WIDTH = 992 // refer to Bootstrap's responsive design
5 |
6 | export default {
7 | beforeMount() {
8 | window.addEventListener('resize', this.$_resizeHandler)
9 | },
10 | beforeDestroy() {
11 | window.removeEventListener('resize', this.$_resizeHandler)
12 | },
13 | mounted() {
14 |
15 | const isMobile = this.$_isMobile()
16 | if (isMobile) {
17 | store.dispatch('app/toggleDevice', 'mobile')
18 | store.dispatch('app/closeSideBar', { withoutAnimation: true })
19 | }
20 | },
21 | methods: {
22 | $_isMobile() {
23 | const rect = body.getBoundingClientRect()
24 | return rect.width - 1 < WIDTH
25 | },
26 | $_resizeHandler() {
27 | if (!document.hidden) {
28 | const isMobile = this.$_isMobile()
29 | store.dispatch('app/toggleDevice', isMobile ? 'mobile' : 'desktop')
30 | if (isMobile) {
31 | store.dispatch('app/closeSideBar', { withoutAnimation: true })
32 | }
33 | }
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/vue.config.js.bak:
--------------------------------------------------------------------------------
1 | // vue.config.js
2 | const path = require('path')
3 |
4 | /* 根据指定目录名得到根目录的绝对路径 */
5 | function resolve(dir) {
6 | return path.join(__dirname, dir)
7 | }
8 |
9 | module.exports = {
10 | // publicPath: '/shopadmin', // 生产环境打包设置
11 | /* 编写webpack支持的配置 */
12 | configureWebpack: {
13 | resolve: {
14 | extensions: ['.js', '.vue', '.json'],
15 | alias: {
16 | '@': resolve('src'),
17 | 'components': resolve('src/components'),
18 | 'views': resolve('src/views'),
19 | 'api': resolve('src/api')
20 | }
21 | },
22 | externals: {
23 | 'vue': 'Vue',
24 | 'element-ui': 'ELEMENT',
25 | 'vue-quill-editor': "VueQuillEditor"
26 | },
27 | },
28 | chainWebpack: config => { //修改webpack打包的入口文件。需要在根目录建两个对应入口js文件
29 | config.when(process.env.NODE_ENV === 'production', config => {
30 | config.entry('app').clear().add('./src/main-prod.js') //生产环境
31 | })
32 | config.when(process.env.NODE_ENV === 'development', config => {
33 | config.entry('app').clear().add('./src/main-dev.js') //开发环境
34 | })
35 | },
36 | productionSourceMap: false,
37 | }
--------------------------------------------------------------------------------
/src/vuex/modules/app.js:
--------------------------------------------------------------------------------
1 |
2 | const state = {
3 | sidebar: {
4 | opened: true,
5 | withoutAnimation: false
6 | },
7 | device: 'desktop',
8 | // size: 'medium'
9 | }
10 |
11 | const mutations = {
12 | TOGGLE_SIDEBAR: state => {
13 | state.sidebar.opened = !state.sidebar.opened
14 | state.sidebar.withoutAnimation = false
15 | },
16 | CLOSE_SIDEBAR: (state, withoutAnimation) => {
17 | state.sidebar.opened = false
18 | state.sidebar.withoutAnimation = withoutAnimation
19 | },
20 | TOGGLE_DEVICE: (state, device) => {
21 | state.device = device
22 | },
23 | // SET_SIZE: (state, size) => {
24 | // state.size = size
25 | // }
26 | }
27 |
28 | const actions = {
29 | toggleSideBar({ commit }) {
30 | commit('TOGGLE_SIDEBAR')
31 | },
32 | closeSideBar({ commit }, { withoutAnimation }) {
33 | commit('CLOSE_SIDEBAR', withoutAnimation)
34 | },
35 | toggleDevice({ commit }, device) {
36 | commit('TOGGLE_DEVICE', device)
37 | },
38 | // setSize({ commit }, size) {
39 | // commit('SET_SIZE', size)
40 | // }
41 | }
42 |
43 | export default {
44 | namespaced: true,
45 | state,
46 | mutations,
47 | actions
48 | }
49 |
--------------------------------------------------------------------------------
/src/api/goods.js:
--------------------------------------------------------------------------------
1 | import request from '@/utils/request'
2 |
3 | /**
4 | * 获取商品
5 | */
6 | export const reqGoods = (query) => request({
7 | url: `/commodities?query=${JSON.stringify(query)}`,
8 | })
9 |
10 | /**
11 | * 添加/修改商品
12 | */
13 | export const reqAddUpdateGoods = (params) => {
14 | const { _id } = params;
15 | return request({
16 | url: `/commodities${_id ? `/${_id}` : ''}`,
17 | method: `${_id ? 'PUT' : 'POST'}`,
18 | data: params
19 | })
20 | }
21 |
22 | /**
23 | * 删除商品
24 | */
25 | export const reqDelGoods = ({ _id }) => request({
26 | url: `/commodities/${_id}`,
27 | method: 'DELETE'
28 | })
29 |
30 | /**
31 | * 获取商品服务
32 | */
33 | export const reqGoodsServices = (query) => request(`/services?query=${JSON.stringify(query)}`)
34 |
35 | /**
36 | * 添加/修改商品服务
37 | */
38 | export const reqAddUpdateGoodsService = ({ name, message, icon, _id }) => request({
39 | url: `/services${_id ? `/${_id}` : ''}`,
40 | method: `${_id ? 'PUT' : 'POST'}`,
41 | data: {
42 | name,
43 | message,
44 | icon
45 | },
46 | headers: {
47 | checkToken: true
48 | }
49 | })
50 |
51 | /**
52 | * 删除商品服务
53 | */
54 | export const reqDelGoodsService = ({ _id }) => request({
55 | url: `/services/${_id}`,
56 | method: 'DELETE'
57 | })
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | 小程序商城后台管理系统
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/src/assets/fontss/iconfont.json:
--------------------------------------------------------------------------------
1 | {
2 | "id": "",
3 | "name": "",
4 | "font_family": "iconfont",
5 | "css_prefix_text": "icon-",
6 | "description": "",
7 | "glyphs": [
8 | {
9 | "icon_id": "182088",
10 | "name": "商家",
11 | "font_class": "shangjia",
12 | "unicode": "e6bd",
13 | "unicode_decimal": 59069
14 | },
15 | {
16 | "icon_id": "479390",
17 | "name": "订单管理",
18 | "font_class": "dingdanguanli",
19 | "unicode": "e60e",
20 | "unicode_decimal": 58894
21 | },
22 | {
23 | "icon_id": "689262",
24 | "name": "类目 品类 分类 类别",
25 | "font_class": "leimupinleifenleileibie",
26 | "unicode": "e7f9",
27 | "unicode_decimal": 59385
28 | },
29 | {
30 | "icon_id": "1567679",
31 | "name": "user",
32 | "font_class": "user",
33 | "unicode": "e6b2",
34 | "unicode_decimal": 59058
35 | },
36 | {
37 | "icon_id": "2848763",
38 | "name": "权限管理",
39 | "font_class": "quanxianguanli",
40 | "unicode": "e641",
41 | "unicode_decimal": 58945
42 | },
43 | {
44 | "icon_id": "7155561",
45 | "name": "密码",
46 | "font_class": "mima",
47 | "unicode": "e658",
48 | "unicode_decimal": 58968
49 | },
50 | {
51 | "icon_id": "9851598",
52 | "name": "活动",
53 | "font_class": "huodong",
54 | "unicode": "e611",
55 | "unicode_decimal": 58897
56 | },
57 | {
58 | "icon_id": "11903650",
59 | "name": "toggle-left",
60 | "font_class": "toggle-left",
61 | "unicode": "e6f5",
62 | "unicode_decimal": 59125
63 | },
64 | {
65 | "icon_id": "11903653",
66 | "name": "toggle-right",
67 | "font_class": "toggle-right",
68 | "unicode": "e6f6",
69 | "unicode_decimal": 59126
70 | }
71 | ]
72 | }
73 |
--------------------------------------------------------------------------------
/src/styles/siderbar.scss:
--------------------------------------------------------------------------------
1 | // mobile responsive
2 | #app {
3 | .el-menu--collapse .el-menu .el-submenu {
4 | min-width: 64px !important;
5 | }
6 | .sidebar-container {
7 | // transition: width 0.28s;
8 | width: 256px !important;
9 | height: 100%;
10 | position: fixed;
11 | font-size: 0px;
12 | top: 0;
13 | bottom: 0;
14 | left: 0;
15 | z-index: 1001;
16 | // overflow: hidden;
17 | & .el-submenu .el-menu-item {
18 | min-width: 64px !important;
19 | }
20 | }
21 | // .withoutAnimation {
22 | // .sidebar-container {
23 | // transition: none !important;
24 | // }
25 | // }
26 | .main-container {
27 | min-height: 100%;
28 | transition: margin-left 0.28s;
29 | margin-left: 256px;
30 | position: relative;
31 | }
32 | .hideSidebar {
33 | .sidebar-container {
34 | width: 64px !important;
35 | }
36 | .main-container {
37 | margin-left: 64px;
38 | }
39 | }
40 | .mobile {
41 | .main-container {
42 | margin-left: 0px;
43 | }
44 | .sidebar-container {
45 | transition: transform 0.28s;
46 | width: 256px !important;
47 | }
48 |
49 | &.hideSidebar {
50 | .sidebar-container {
51 | pointer-events: none;
52 | // transition-duration: 0.3s;
53 | transform: translate3d(-256px, 0, 0);
54 | }
55 | }
56 | }
57 |
58 | .withoutAnimation {
59 | .main-container,
60 | .sidebar-container {
61 | transition: none;
62 | }
63 | }
64 |
65 | .hideSidebar {
66 | .sidebar-container {
67 | .el-menu-item.is-active {
68 | color: rgb(64, 158, 255) !important;
69 | background-color: rgb(0, 21, 41) !important;
70 | }
71 | }
72 | }
73 |
74 | .openSidebar {
75 | .el-menu-item.is-active {
76 | background-color: #409eff !important;
77 | color: #fff !important;
78 | }
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/src/assets/fonts/iconfont.json:
--------------------------------------------------------------------------------
1 | {
2 | "id": "",
3 | "name": "",
4 | "font_family": "iconfont",
5 | "css_prefix_text": "icon-",
6 | "description": "",
7 | "glyphs": [
8 | {
9 | "icon_id": "182088",
10 | "name": "商家",
11 | "font_class": "shangjia",
12 | "unicode": "e6bd",
13 | "unicode_decimal": 59069
14 | },
15 | {
16 | "icon_id": "479390",
17 | "name": "订单管理",
18 | "font_class": "dingdanguanli",
19 | "unicode": "e60e",
20 | "unicode_decimal": 58894
21 | },
22 | {
23 | "icon_id": "689262",
24 | "name": "类目 品类 分类 类别",
25 | "font_class": "leimupinleifenleileibie",
26 | "unicode": "e7f9",
27 | "unicode_decimal": 59385
28 | },
29 | {
30 | "icon_id": "1567679",
31 | "name": "user",
32 | "font_class": "user",
33 | "unicode": "e6b2",
34 | "unicode_decimal": 59058
35 | },
36 | {
37 | "icon_id": "2848763",
38 | "name": "权限管理",
39 | "font_class": "quanxianguanli",
40 | "unicode": "e641",
41 | "unicode_decimal": 58945
42 | },
43 | {
44 | "icon_id": "7155561",
45 | "name": "密码",
46 | "font_class": "mima",
47 | "unicode": "e658",
48 | "unicode_decimal": 58968
49 | },
50 | {
51 | "icon_id": "9851598",
52 | "name": "活动",
53 | "font_class": "huodong",
54 | "unicode": "e611",
55 | "unicode_decimal": 58897
56 | },
57 | {
58 | "icon_id": "11683673",
59 | "name": "评论",
60 | "font_class": "ziyuan",
61 | "unicode": "e608",
62 | "unicode_decimal": 58888
63 | },
64 | {
65 | "icon_id": "11903650",
66 | "name": "toggle-left",
67 | "font_class": "toggle-left",
68 | "unicode": "e6f5",
69 | "unicode_decimal": 59125
70 | },
71 | {
72 | "icon_id": "11903653",
73 | "name": "toggle-right",
74 | "font_class": "toggle-right",
75 | "unicode": "e6f6",
76 | "unicode_decimal": 59126
77 | }
78 | ]
79 | }
80 |
--------------------------------------------------------------------------------
/src/api/user.js:
--------------------------------------------------------------------------------
1 | import request from '@/utils/request'
2 |
3 |
4 | /**
5 | * 登录接口
6 | */
7 | export const login = ({ username, password }) => request({
8 | url: '/auth/login',
9 | method: 'POST',
10 | data: {
11 | username,
12 | password
13 | }
14 | })
15 |
16 | /**
17 | * 根据token获取用户信息
18 | */
19 | export const getUserInfo = () => request({
20 | url: '/auth/user',
21 | headers: {
22 | checkToken: true
23 | }
24 | })
25 |
26 | /**
27 | * 获取所有后台系统的用户
28 | */
29 | export const getAdminUser = (query) => request({
30 | url: `/auth/users?query=${JSON.stringify(query)}`,
31 | headers: {
32 | checkToken: true
33 | }
34 | })
35 |
36 | /**
37 | * 添加用户
38 | */
39 | export const addUser = ({ username, password, roles, permission }) => request({
40 | url: '/auth/register',
41 | method: 'POST',
42 | data: {
43 | username,
44 | password,
45 | roles,
46 | permission
47 | },
48 | })
49 |
50 | /**
51 | * 修改用户
52 | */
53 | export const updateUser = ({ username, password, roles, permission, _id }) => request({
54 | url: `/auth/users/${_id}`,
55 | method: 'PUT',
56 | data: {
57 | username,
58 | password,
59 | roles,
60 | permission
61 | },
62 | headers: {
63 | checkToken: true
64 | }
65 | })
66 |
67 | /**
68 | * 删除用户
69 | */
70 | export const delUser = ({ _id }) => request({
71 | url: `/auth/users/${_id}`,
72 | method: 'DELETE',
73 | headers: {
74 | checkToken: true
75 | }
76 | })
77 |
78 | /**
79 | * 获取角色列表
80 | */
81 | export const reqRoles = (query) => request({
82 | url: `/roles?query=${JSON.stringify(query)}`
83 | })
84 |
85 | /**
86 | * 添加角色
87 | */
88 | export const reqAddRole = ({ name, description, status, permission, _id }) => request({
89 | url: `/roles${_id ? `/${_id}` : ''}`,
90 | method: `${_id ? 'PUT' : 'POST'}`,
91 | data: {
92 | name,
93 | description,
94 | status,
95 | permission
96 | }
97 | })
98 |
99 | /**
100 | * 删除角色
101 | */
102 | export const reqDelRole = ({ _id }) => request({
103 | url: `/roles/${_id}`,
104 | method: 'DELETE',
105 | })
--------------------------------------------------------------------------------
/src/components/Aside/Item.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 首页
6 |
7 |
8 |
9 |
10 |
11 | {{ item.title }}
12 |
13 |
14 |
15 |
16 |
17 | {{ _item.title }}
18 |
19 |
20 |
21 |
22 |
23 |
24 |
82 |
--------------------------------------------------------------------------------
/src/views/home/Home.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
欢迎来到小程序商城后台管理系统
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
57 |
58 |
59 |
60 |
61 |
--------------------------------------------------------------------------------
/src/utils/request.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 封装axios的模块
3 | */
4 | import Vue from 'vue'
5 | import axios from 'axios';
6 | import router from '@/router'
7 | import store from '@/vuex/store'
8 | import { serverURL } from '@/utils/serverConfig'
9 | import { Message } from 'element-ui'
10 |
11 | const instance = axios.create({
12 | baseURL: serverURL
13 | })
14 |
15 | // 存放axios的cancel对象,用于取消请求
16 | Vue.prototype._axiosPromiseArr = []
17 |
18 | /**
19 | * 添加请求拦截器, 处理请求参数问题以及token问题
20 | */
21 | instance.interceptors.request.use((config) => {
22 | // 处理请求参数
23 | // debugger
24 | if (config.data && (config.data instanceof FormData) === false) {
25 | config.data = JSON.parse(JSON.stringify(config.data))
26 | for (let item in config.data) {
27 | if (config.data[item] === "") {
28 | delete config.data[item]
29 | }
30 | }
31 | }
32 |
33 | /**
34 | * new一个Cancel对象,并push到Vue.prototype._axiosPromiseArr中
35 | */
36 | config.cancelToken = new axios.CancelToken(cancel => {
37 | Vue.prototype._axiosPromiseArr.push(cancel)
38 | })
39 |
40 | // 处理token
41 | const token = store.state.adminUser.token
42 | if (token) {
43 | config.headers['Authorization'] = token
44 | } else {
45 | if (config.headers.checkToken) {
46 | throw new Error('授权失败,请重新登录')
47 | }
48 | }
49 | return config
50 | })
51 | /**
52 | * 添加响应拦截器
53 | * 成功回调: 成功的结果不再是response, 而是response.data
54 | * 失败回调: 统一处理请求异常
55 | */
56 | instance.interceptors.response.use(
57 | response => {
58 | // debugger
59 | return response.data
60 | },
61 | error => {
62 | // debugger
63 | // 1. 没有token直接发请求的错误
64 | if (!error.response) {
65 | // 取消请求特殊处理
66 | if (error.message.code === 600) {
67 | Message.warning(error.message.msg)
68 | return;
69 | }
70 | // 提示错误, 并且跳转到登录页
71 | Message.error('没有授权, 请重新登录', error.message)
72 | store.dispatch('logout')
73 | router.replace('/login')
74 | } else {
75 | // 2. 发了请求, 但账号密码错误
76 | if (error.response.status === 400) return Promise.reject(error) // 返回一个reject状态的promise
77 | if (error.response.status === 401) {
78 | // 3. 发了请求, 但token失效了
79 | store.dispatch('logout')
80 | Message.error('授权失败,请重新登录,错误码:' + error.response.status)
81 | router.replace('/login')
82 | } else if (error.response.status === 404) {
83 | // 4. 发了请求, 资源不存在404
84 | Message.error('您请求的资源不存在,错误码:' + error.response.status)
85 | } else if (error.response.status === 500) {
86 | Message.error('服务器内部错误,错误码:' + error.response.status)
87 | } else {
88 | Message.error('请求错误,请检查网络后重试,错误码:' + error.response.status)
89 | }
90 | }
91 | return new Promise(() => { }) // 返回一个pedding状态的promise
92 | }
93 | )
94 |
95 | export default instance;
--------------------------------------------------------------------------------
/src/assets/css/reset.css:
--------------------------------------------------------------------------------
1 | /**
2 | * Eric Meyer's Reset CSS v2.0 (http://meyerweb.com/eric/tools/css/reset/)
3 | * http://cssreset.com
4 | */
5 | html,
6 | body,
7 | div,
8 | span,
9 | applet,
10 | object,
11 | iframe,
12 | h1,
13 | h2,
14 | h3,
15 | h4,
16 | h5,
17 | h6,
18 | p,
19 | blockquote,
20 | pre,
21 | a,
22 | abbr,
23 | acronym,
24 | address,
25 | big,
26 | cite,
27 | code,
28 | del,
29 | dfn,
30 | em,
31 | img,
32 | ins,
33 | kbd,
34 | q,
35 | s,
36 | samp,
37 | small,
38 | strike,
39 | strong,
40 | sub,
41 | sup,
42 | tt,
43 | var,
44 | b,
45 | u,
46 | i,
47 | center,
48 | dl,
49 | dt,
50 | dd,
51 | ol,
52 | ul,
53 | li,
54 | fieldset,
55 | form,
56 | label,
57 | legend,
58 | table,
59 | caption,
60 | tbody,
61 | tfoot,
62 | thead,
63 | tr,
64 | th,
65 | td,
66 | article,
67 | aside,
68 | canvas,
69 | details,
70 | embed,
71 | figure,
72 | figcaption,
73 | footer,
74 | header,
75 | menu,
76 | nav,
77 | output,
78 | ruby,
79 | section,
80 | summary,
81 | time,
82 | mark,
83 | audio,
84 | video,
85 | input {
86 | margin: 0;
87 | padding: 0;
88 | border: 0;
89 | font-size: 100%;
90 | font-weight: normal;
91 | vertical-align: baseline;
92 | }
93 |
94 | /* HTML5 display-role reset for older browsers */
95 | article,
96 | aside,
97 | details,
98 | figcaption,
99 | figure,
100 | footer,
101 | header,
102 | menu,
103 | nav,
104 | section {
105 | display: block;
106 | }
107 |
108 | body {
109 | line-height: 1;
110 | }
111 |
112 | blockquote,
113 | q {
114 | quotes: none;
115 | }
116 |
117 | blockquote:before,
118 | blockquote:after,
119 | q:before,
120 | q:after {
121 | content: none;
122 | }
123 |
124 | table {
125 | border-collapse: collapse;
126 | border-spacing: 0;
127 | }
128 |
129 | /* custom */
130 | a {
131 | color: #7e8c8d;
132 | text-decoration: none;
133 | -webkit-backface-visibility: hidden;
134 | }
135 |
136 | li {
137 | list-style: none;
138 | }
139 |
140 | ::-webkit-scrollbar {
141 | width: 5px;
142 | height: 5px;
143 | }
144 |
145 | ::-webkit-scrollbar-track-piece {
146 | background-color: rgba(0, 0, 0, 0.2);
147 | -webkit-border-radius: 6px;
148 | }
149 |
150 | ::-webkit-scrollbar-thumb:vertical {
151 | height: 5px;
152 | background-color: rgba(125, 125, 125, 0.7);
153 | -webkit-border-radius: 6px;
154 | }
155 |
156 | ::-webkit-scrollbar-thumb:horizontal {
157 | width: 5px;
158 | background-color: rgba(125, 125, 125, 0.7);
159 | -webkit-border-radius: 6px;
160 | }
161 |
162 | #app,
163 | html,
164 | body {
165 | width: 100%;
166 | height: 100%;
167 | /* min-width: 1024px; */
168 | }
169 |
170 | body {
171 | -webkit-text-size-adjust: none;
172 | -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
173 | }
174 |
175 |
176 |
177 | /*显示省略号*/
178 | .ellipsis {
179 | overflow: hidden;
180 | text-overflow: ellipsis;
181 | white-space: nowrap;
182 | }
183 |
--------------------------------------------------------------------------------
/src/config/menuConfig.js:
--------------------------------------------------------------------------------
1 | const menuList = [
2 | // {
3 | // title: '首页', // 菜单标题名称
4 | // key: '/home', // 对应的path
5 | // icon: 'el-icon-s-home', // 图标名称
6 | // public: true, // 公开的
7 | // },
8 | {
9 | title: '轮播图',
10 | key: '/banner',
11 | icon: 'el-icon-picture',
12 | children: [ // 子菜单列表
13 | {
14 | title: '首页轮播图',
15 | key: '/banner/bannerlist',
16 | icon: 'el-icon-picture'
17 | },
18 | ]
19 | },
20 | {
21 | title: '分类管理',
22 | key: '/category',
23 | icon: 'el-icon- iconfont icon-leimupinleifenleileibie',
24 | children: [ // 子菜单列表
25 | {
26 | title: '分类列表',
27 | key: '/category/categorylist',
28 | icon: ''
29 | },
30 | ]
31 | },
32 | {
33 | title: '商品管理',
34 | key: '/goods',
35 | icon: 'el-icon-goods',
36 | children: [ // 子菜单列表
37 | {
38 | title: '商品列表',
39 | key: '/goods/goodslist',
40 | icon: ''
41 | },
42 | {
43 | title: '商品服务',
44 | key: '/goods/goodsservice',
45 | icon: ''
46 | },
47 | ]
48 | },
49 | {
50 | title: '商家管理',
51 | key: '/merchant',
52 | icon: 'el-icon- iconfont icon-shangjia',
53 | children: [ // 子菜单列表
54 | {
55 | title: '店铺列表',
56 | key: '/metchant/merchantlist',
57 | icon: ''
58 | },
59 | ]
60 | },
61 | {
62 | title: '权限管理',
63 | key: '/auth',
64 | icon: 'el-icon- iconfont icon-quanxianguanli',
65 | children: [ // 子菜单列表
66 | {
67 | title: '用户管理',
68 | key: '/auth/userlist',
69 | icon: ''
70 | },
71 | ]
72 | },
73 | {
74 | title: '活动管理',
75 | key: '/active',
76 | icon: 'el-icon- iconfont icon-huodong',
77 | children: [ // 子菜单列表
78 | {
79 | title: '用户管理',
80 | key: '/active/activelist',
81 | icon: ''
82 | },
83 | ]
84 | },
85 | {
86 | title: '订单管理',
87 | key: '/order',
88 | icon: 'el-icon- iconfont icon-dingdanguanli',
89 | children: [ // 子菜单列表
90 | {
91 | title: '订单列表',
92 | key: '/order/orderlist',
93 | icon: ''
94 | },
95 | ]
96 | },
97 | {
98 | title: '评论管理',
99 | key: '/comment',
100 | icon: 'el-icon- iconfont icon-ziyuan',
101 | children: [ // 子菜单列表
102 | {
103 | title: '评论列表',
104 | key: '/comment/commentlist',
105 | icon: ''
106 | },
107 | ]
108 | },
109 | ]
110 |
111 | export default menuList
--------------------------------------------------------------------------------
/src/vuex/modules/goods.js:
--------------------------------------------------------------------------------
1 | import { reqActiveList } from 'api/activity';
2 | import { reqGoods, reqGoodsServices } from 'api/goods';
3 | import { reqCategories } from 'api/category';
4 | import { reqMerchants } from 'api/merchant';
5 | import { reqOrders } from 'api/order';
6 | import { reqComment } from 'api/comment';
7 |
8 | import {
9 | RECEIVE_ACTIVE_LIST,
10 | RECEIVE_GOODS_LIST,
11 | RECEIVE_GOODS,
12 | RECEIVE_GOODS_SERVICE,
13 | RECEIVE_CATEGORIES,
14 | RECEIVE_MERCHANTS,
15 | RECEIVE_ORDERS,
16 | RECEIVE_BACK_ROUTE_PATH,
17 | RECEIVE_COMMENTS
18 | } from '../mutation-types';
19 |
20 | const state = {
21 | activeList: [],
22 | activeTotal: 0,
23 | goodsList: null,
24 | goodsTotal: 0,
25 | currentGoods: JSON.parse(sessionStorage.getItem('goods') || '{}'),
26 | goodsService: null,
27 | servicesTotal: 0,
28 | categoryList: [],
29 | categoryTotal: 0,
30 | merchantList: [],
31 | merchantTotal: 0,
32 | orderList: null,
33 | orderTotal: 0,
34 | backRoutePath: sessionStorage.getItem('backRoutePath') || "",
35 | commentList: null,
36 | commentTotal: 0
37 | };
38 |
39 |
40 | const actions = {
41 | async getActiveList({ commit }, query) {
42 | const result = await reqActiveList(query);
43 | commit(RECEIVE_ACTIVE_LIST, result);
44 | },
45 | async getGoods({ commit }, query) {
46 | const result = await reqGoods(query)
47 | commit(RECEIVE_GOODS_LIST, result);
48 | },
49 | saveGoods({ commit }, goods) {
50 | commit(RECEIVE_GOODS, goods);
51 | },
52 | async getGoodsService({ commit }, query) {
53 | const result = await reqGoodsServices(query);
54 | commit(RECEIVE_GOODS_SERVICE, result);
55 | },
56 | async getCategory({ commit }, query) {
57 | const result = await reqCategories(query);
58 | commit(RECEIVE_CATEGORIES, result)
59 | },
60 | async getMerchants({ commit }, query) {
61 | const result = await reqMerchants(query);
62 | commit(RECEIVE_MERCHANTS, result);
63 | },
64 | async getOrders({ commit }, query) {
65 | const result = await reqOrders(query);
66 | commit(RECEIVE_ORDERS, result);
67 | },
68 | async getComments({ commit }, query) {
69 | const result = await reqComment(query);
70 | commit(RECEIVE_COMMENTS, result);
71 | },
72 |
73 | };
74 |
75 | const mutations = {
76 | [RECEIVE_ACTIVE_LIST](state, { total, data }) {
77 | state.activeTotal = total;
78 | state.activeList = data;
79 | },
80 | [RECEIVE_GOODS_LIST](state, { total, data }) {
81 | state.goodsList = data;
82 | state.goodsTotal = total;
83 | },
84 | [RECEIVE_GOODS](state, goods) {
85 | sessionStorage.removeItem('goods')
86 | state.currentGoods = goods;
87 | sessionStorage.setItem('goods', JSON.stringify(goods));
88 | },
89 | [RECEIVE_GOODS_SERVICE](state, { data, total }) {
90 | state.goodsService = data;
91 | state.servicesTotal = total;
92 | },
93 | [RECEIVE_CATEGORIES](state, { data, total }) {
94 | state.categoryList = data;
95 | state.categoryTotal = total;
96 | },
97 | [RECEIVE_MERCHANTS](state, { data, total }) {
98 | state.merchantList = data;
99 | state.merchantTotal = total;
100 | },
101 | [RECEIVE_ORDERS](state, { data, total }) {
102 | state.orderList = data;
103 | state.orderTotal = total;
104 | },
105 | [RECEIVE_BACK_ROUTE_PATH](state, path) {
106 | state.backRoutePath = path;
107 | sessionStorage.setItem('backRoutePath', path);
108 | },
109 | [RECEIVE_COMMENTS](state, { data, total }) {
110 | state.commentList = data;
111 | state.commentTotal = total;
112 | }
113 | };
114 |
115 | const getters = {};
116 |
117 | export default {
118 | state,
119 | mutations,
120 | actions,
121 | getters
122 | };
--------------------------------------------------------------------------------
/src/assets/fontss/iconfont.css:
--------------------------------------------------------------------------------
1 | @font-face {font-family: "iconfont";
2 | src: url('iconfont.eot?t=1583412488775'); /* IE9 */
3 | src: url('iconfont.eot?t=1583412488775#iefix') format('embedded-opentype'), /* IE6-IE8 */
4 | url('data:application/x-font-woff2;charset=utf-8;base64,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') format('woff2'),
5 | url('iconfont.woff?t=1583412488775') format('woff'),
6 | url('iconfont.ttf?t=1583412488775') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */
7 | url('iconfont.svg?t=1583412488775#iconfont') format('svg'); /* iOS 4.1- */
8 | }
9 |
10 | .iconfont {
11 | font-family: "iconfont" !important;
12 | font-size: 16px;
13 | font-style: normal;
14 | -webkit-font-smoothing: antialiased;
15 | -moz-osx-font-smoothing: grayscale;
16 | }
17 |
18 | .icon-shangjia:before {
19 | content: "\e6bd";
20 | }
21 |
22 | .icon-dingdanguanli:before {
23 | content: "\e60e";
24 | }
25 |
26 | .icon-leimupinleifenleileibie:before {
27 | content: "\e7f9";
28 | }
29 |
30 | .icon-user:before {
31 | content: "\e6b2";
32 | }
33 |
34 | .icon-quanxianguanli:before {
35 | content: "\e641";
36 | }
37 |
38 | .icon-mima:before {
39 | content: "\e658";
40 | }
41 |
42 | .icon-huodong:before {
43 | content: "\e611";
44 | }
45 |
46 | .icon-toggle-left:before {
47 | content: "\e6f5";
48 | }
49 |
50 | .icon-toggle-right:before {
51 | content: "\e6f6";
52 | }
53 |
54 |
--------------------------------------------------------------------------------
/src/vuex/modules/admin-user.js:
--------------------------------------------------------------------------------
1 | import {
2 | RECEIVE_ADMIN_USER,
3 | RECEIVE_TOKEN,
4 | LOGOUT,
5 | RECEIVE_USER_LIST,
6 | RECEIVE_ROLE_LIST
7 | } from '../mutation-types'
8 |
9 | import {
10 | getAdminUser,
11 | getUserInfo,
12 | reqRoles
13 | } from 'api/user'
14 |
15 | import storageUtils from '@/utils/storageUtils'
16 |
17 | const state = {
18 | token: storageUtils.getToken(), // 登录token标识,
19 | adminUser: {},
20 | adminUserList: null,
21 | adminUserListTotal: 0,
22 | menus: [],
23 | roleList: null,
24 | roleTotal: 0
25 | }
26 | /**
27 | * 包含同步action和异步action
28 | */
29 | const actions = {
30 | saveToken({ commit }, token) {
31 | storageUtils.saveToken(token)
32 | commit(RECEIVE_TOKEN, { token })
33 | },
34 | async saveUser({ commit }) {
35 | const user = await getUserInfo();
36 | const menus = [];
37 | user.permission.forEach(item => {
38 | switch (item.path) {
39 | case 'banners':
40 | if (!menus.find(item => item === '/banner')) {
41 | menus.push('/banner')
42 | menus.push('/banner/bannerlist')
43 | }
44 | break;
45 | case 'actions':
46 | if (!menus.find(item => item === '/active')) {
47 | menus.push('/active')
48 | menus.push('/active/activelist')
49 | }
50 |
51 | break;
52 | case 'categories':
53 | if (!menus.find(item => item === '/category')) {
54 | menus.push('/category')
55 | menus.push('/category/categorylist')
56 | }
57 |
58 | break;
59 | case 'comments':
60 | if (!menus.find(item => item === '/comment')) {
61 | menus.push('/comment')
62 | menus.push('/comment/commentlist')
63 | }
64 | break;
65 | case 'commodities':
66 | if (!menus.find(item => item === '/goods')) {
67 | menus.push('/goods')
68 | menus.push('/goods/goodslist')
69 | }
70 | break;
71 | case 'orders':
72 | if (!menus.find(item => item === '/order')) {
73 | menus.push('/order')
74 | menus.push('/order/orderlist')
75 | }
76 | break;
77 | case 'selles':
78 | if (!menus.find(item => item === '/merchant')) {
79 | menus.push('/merchant')
80 | menus.push('/merchant/merchantlist')
81 | }
82 | break;
83 | case 'services':
84 | if (!menus.find(item => item === '/goods/goodsservice')) {
85 | menus.push('/goods/goodsservice')
86 | }
87 | break;
88 | case 'roles':
89 | if (!menus.find(item => item === '/auth')) {
90 | menus.push('/auth')
91 | menus.push('/auth/rolelist')
92 | }
93 | break;
94 | default:
95 | break;
96 | }
97 | })
98 | commit(RECEIVE_ADMIN_USER, { user, menus })
99 | },
100 | logout({ commit }) {
101 | storageUtils.removeToken()
102 | commit(LOGOUT)
103 | },
104 | async getUserList({ commit }, query) {
105 | const result = await getAdminUser(query)
106 | commit(RECEIVE_USER_LIST, result)
107 | },
108 | async getRoleList({ commit }, query) {
109 | const result = await reqRoles(query)
110 | commit(RECEIVE_ROLE_LIST, result)
111 | }
112 | }
113 |
114 | const mutations = {
115 | [RECEIVE_TOKEN](state, { token }) {
116 | state.token = token
117 | },
118 | [RECEIVE_ADMIN_USER](state, { user, menus }) {
119 | state.menus = menus
120 | state.adminUser = user
121 | },
122 | [LOGOUT](state) {
123 | state.token = ''
124 | state.adminUser = {}
125 | },
126 | [RECEIVE_USER_LIST](state, { data, total }) {
127 | state.adminUserList = data;
128 | state.adminUserListTotal = total;
129 | },
130 | [RECEIVE_ROLE_LIST](state, { data, total }) {
131 | state.roleList = data;
132 | state.roleTotal = total;
133 | }
134 | }
135 |
136 |
137 |
138 | const getters = {}
139 |
140 | export default {
141 | state,
142 | mutations,
143 | actions,
144 | getters
145 | }
--------------------------------------------------------------------------------
/src/assets/fonts/iconfont.css:
--------------------------------------------------------------------------------
1 | @font-face {font-family: "iconfont";
2 | src: url('iconfont.eot?t=1583474376955'); /* IE9 */
3 | src: url('iconfont.eot?t=1583474376955#iefix') format('embedded-opentype'), /* IE6-IE8 */
4 | url('data:application/x-font-woff2;charset=utf-8;base64,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') format('woff2'),
5 | url('iconfont.woff?t=1583474376955') format('woff'),
6 | url('iconfont.ttf?t=1583474376955') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */
7 | url('iconfont.svg?t=1583474376955#iconfont') format('svg'); /* iOS 4.1- */
8 | }
9 |
10 | .iconfont {
11 | font-family: "iconfont" !important;
12 | font-size: 16px;
13 | font-style: normal;
14 | -webkit-font-smoothing: antialiased;
15 | -moz-osx-font-smoothing: grayscale;
16 | }
17 |
18 | .icon-shangjia:before {
19 | content: "\e6bd";
20 | }
21 |
22 | .icon-dingdanguanli:before {
23 | content: "\e60e";
24 | }
25 |
26 | .icon-leimupinleifenleileibie:before {
27 | content: "\e7f9";
28 | }
29 |
30 | .icon-user:before {
31 | content: "\e6b2";
32 | }
33 |
34 | .icon-quanxianguanli:before {
35 | content: "\e641";
36 | }
37 |
38 | .icon-mima:before {
39 | content: "\e658";
40 | }
41 |
42 | .icon-huodong:before {
43 | content: "\e611";
44 | }
45 |
46 | .icon-ziyuan:before {
47 | content: "\e608";
48 | }
49 |
50 | .icon-toggle-left:before {
51 | content: "\e6f5";
52 | }
53 |
54 | .icon-toggle-right:before {
55 | content: "\e6f6";
56 | }
57 |
58 |
--------------------------------------------------------------------------------
/src/components/Header/Header.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
{{currentTime}}
11 |
![weather]()
12 |
{{weather}}
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 | 退出
22 |
23 |
24 | 欢迎你,{{user.username}}
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
99 |
100 |
--------------------------------------------------------------------------------
/src/views/login/Login.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |

7 |
8 |
9 |
17 |
18 |
19 |
24 |
25 |
26 |
27 |
33 |
34 |
35 |
36 | 登录
37 | 重置
38 |
39 |
40 |
41 |
42 |
43 |
44 |
111 |
112 |
162 |
--------------------------------------------------------------------------------
/src/components/Aside/Aside.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
18 |
19 |
20 | 首页
21 |
22 |
23 |
24 |
25 |
26 | {{ item.title }}
27 |
28 |
29 |
30 |
31 |
32 | {{ _item.title }}
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
96 |
97 |
--------------------------------------------------------------------------------
/src/views/goods/GoodsList.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
16 |
17 |
18 |
19 |
22 |
23 | 添加商品
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 | 详情
44 | 修改
50 | 删除
56 |
57 |
58 |
59 |
60 |
61 |
62 |
70 |
71 |
72 |
73 |
74 |
75 |
152 |
--------------------------------------------------------------------------------
/src/router/routes.js:
--------------------------------------------------------------------------------
1 | const Home = () => import('views/home/Home');
2 | const Banner = () => import('views/banner/Banner');
3 | const BannerList = () => import('views/banner/BannerList');
4 | const Login = () => import('views/login/Login');
5 | const Category = () => import('views/category/Category');
6 | const CategoryList = () => import('views/category/CategoryList');
7 | const Goods = () => import('views/goods/Goods');
8 | const Acitve = () => import('views/activity/Activity');
9 | const AcitveList = () => import('views/activity/ActivityList');
10 | const Auth = () => import('views/auth/Auth');
11 | const UserList = () => import('views/auth/UserList');
12 | const RoleList = () => import('views/auth/RoleList');
13 | const AddCategory = () => import('views/category/AddCategory');
14 | const GoodsList = () => import('views/goods/GoodsList');
15 | const Detail = () => import('views/goods/Detail');
16 | const GoodsService = () => import("views/goods/GoodsService");
17 | const AddUpdateGoods = () => import('views/goods/AddUpdateGoods');
18 | const Merchant = () => import('views/merchant/Merchant');
19 | const MerchantList = () => import('views/merchant/MerchantList');
20 | const Order = () => import('views/order/Order')
21 | const OrderList = () => import('views/order/OrderList')
22 | const Comment = () => import('views/comment/Comment')
23 | const CommentList = () => import('views/comment/CommentList')
24 |
25 | export default [
26 | { path: '/', redirect: '/login' },
27 | { path: '/login', component: Login },
28 | {
29 | path: '/home',
30 | name: 'home',
31 | component: Home,
32 | meta: { title: '首页' },
33 | children: [
34 | {
35 | path: '/banner',
36 | component: Banner,
37 | redirect: '/banner/bannerlist',
38 | meta: { title: '轮播图' },
39 | children: [
40 | {
41 | path: '/banner/bannerlist',
42 | component: BannerList,
43 | meta: { title: '首页轮播图' },
44 | }
45 | ]
46 | },
47 | {
48 | path: '/category',
49 | component: Category,
50 | redirect: '/category/categorylist',
51 | meta: { title: '分类管理' },
52 | children: [
53 | {
54 | path: '/category/categorylist',
55 | component: CategoryList,
56 | meta: {
57 | title: '分类列表',
58 | activeMenu: '/categorylist',
59 | activeChildMenu: '/category/addcategory'
60 | }
61 | },
62 | {
63 | path: '/category/addcategory',
64 | name: 'addCategory',
65 | component: AddCategory,
66 | meta: {
67 | title: '添加分类',
68 | activeMenu: '/category',
69 | activeChildMenu: '/category/addcategory'
70 | }
71 | },
72 | ]
73 | },
74 | {
75 | path: '/auth',
76 | component: Auth,
77 | redirect: '/auth/userlist',
78 | meta: { title: '权限管理' },
79 | children: [
80 | {
81 | path: '/auth/userlist',
82 | component: UserList,
83 | meta: { title: '用户管理' },
84 | },
85 | {
86 | path: '/auth/rolelist',
87 | component: RoleList,
88 | meta: { title: '角色管理' },
89 | },
90 |
91 | ]
92 | },
93 | {
94 | path: '/active',
95 | component: Acitve,
96 | redirect: '/active/activelist',
97 | meta: { title: '活动管理' },
98 | children: [{
99 | path: '/active/activelist',
100 | component: AcitveList,
101 | meta: { title: '首页活动' },
102 | }]
103 |
104 | },
105 | {
106 | path: '/goods',
107 | component: Goods,
108 | redirect: '/goods/goodslist',
109 | meta: { title: '商品管理' },
110 | children: [
111 | {
112 | path: '/goods/goodslist',
113 | component: GoodsList,
114 | meta: { title: '商品列表' },
115 | },
116 | {
117 | path: '/goods/detail',
118 | name: 'detail',
119 | component: Detail,
120 | meta: { title: '商品详情' },
121 | },
122 | {
123 | path: '/goods/goodsservice',
124 | component: GoodsService,
125 | meta: { title: '商品服务' },
126 | },
127 | {
128 | path: '/goods/addupdategoods',
129 | name: 'addUpdateGoods',
130 | component: AddUpdateGoods,
131 | },
132 | ]
133 | },
134 |
135 | {
136 | path: '/merchant',
137 | component: Merchant,
138 | redirect: '/merchant/merchantlist',
139 | meta: { title: '商家管理' },
140 | children: [
141 | {
142 | path: '/merchant/merchantlist',
143 | component: MerchantList,
144 | meta: { title: '店铺列表' },
145 | },
146 | ]
147 | },
148 | {
149 | path: '/order',
150 | component: Order,
151 | redirect: '/order/orderlist',
152 | meta: { title: '订单管理' },
153 | children: [
154 | {
155 | path: '/order/orderlist',
156 | component: OrderList,
157 | meta: { title: '订单列表' },
158 | },
159 | ]
160 | },
161 | {
162 | path: '/comment',
163 | component: Comment,
164 | redirect: '/comment/commentlist',
165 | meta: { title: '评论管理' },
166 | children: [
167 | {
168 | path: '/comment/commentlist',
169 | component: CommentList,
170 | meta: { title: '评论列表' },
171 | },
172 | ]
173 | }
174 | ]
175 | },
176 | ]
--------------------------------------------------------------------------------
/src/views/category/CategoryList.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
17 |
18 |
19 |
20 |
23 |
24 | 添加分类
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 | {{slotProps.row.parent ? '二级分类' : '一级分类'}}
36 |
37 |
38 |
39 |
40 |
41 |
47 |
48 |
49 |
50 |
51 | 编辑
57 | 删除
63 |
64 |
65 |
66 |
67 |
68 |
69 |
77 |
78 |
79 |
80 |
81 |
82 |
--------------------------------------------------------------------------------
/src/views/goods/Detail.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | {{currentGoods.title}}
10 |
11 |
12 | {{currentGoods.category.name}}
13 |
14 |
15 | {{currentGoods.prices.initPrice}}元
16 |
17 |
18 | {{currentGoods.prices.nowPrice}}元
19 |
20 |
21 | {{currentGoods.prices.hotPrice}}元
22 |
23 |
24 |
30 |
31 |
32 |
33 |
34 |
40 |
41 |
42 | 多选框
43 | 单选框
44 | 输入框
45 |
46 |
47 | 数组
48 | 数字
49 | 字符串
50 |
51 |
52 |
53 |
54 | {{list}}
55 | ,
56 |
57 |
58 | {{item.message}}
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 | {{item.name}}
71 |
72 |
73 | {{item.message}}
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 | 无
82 |
83 |
84 |
104 | 无
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
158 |
159 |
185 |
186 |
187 |
--------------------------------------------------------------------------------
/src/vuex/modules/auth-config.js:
--------------------------------------------------------------------------------
1 | import { PERMISSION_MAPPING_VIEW } from '../mutation-types'
2 | import { CLEAR_CACHE } from '../mutation-types'
3 | import { getUserInfo } from 'api/user'
4 |
5 | const state = {
6 | cache: false,
7 | cacheData: {},
8 | mandatoryRefresh: false,
9 | menuList: [],
10 | activity: {},
11 | banner: {},
12 | category: {},
13 | comment: {},
14 | goods: {},
15 | order: {},
16 | merchant: {},
17 | services: {},
18 | role: {},
19 | auth: {},
20 | }
21 |
22 | //权限 -> 对应视图是否渲染
23 | /**
24 | *
25 | * data
26 | * menuList : []
27 | * banner : {}
28 | * category : {}
29 | * goods : {}
30 | * service : {}
31 | * order : {}
32 | * merchant : {}
33 | * comment : {}
34 | * auth : {}
35 | * activity : {}
36 | * role : null
37 | */
38 | const permissionMappingView = (data) => {
39 |
40 | let mapObj = {
41 | actions: 'activity',
42 | banners: 'banner',
43 | categories: 'category',
44 | comments: 'comment',
45 | commodities: 'goods',
46 | orders: 'order',
47 | selles: 'merchant',
48 | services: 'services',
49 | roles: 'role'
50 | }
51 |
52 | //合并 去重
53 | data.roles.forEach(role => {
54 | role.permission.forEach(permission => {
55 | var has = data.permission.some(item => {
56 | return item._id == permission._id
57 | })
58 | if (!has)
59 | data.permission.push(permission)
60 | })
61 | })
62 |
63 |
64 | data.permission.forEach(item => {
65 | switch (item.method) {
66 | case 'get': state[mapObj[item.path]].find = true
67 | break
68 | case 'post': state[mapObj[item.path]].create = true
69 | break
70 | case 'put': state[mapObj[item.path]].update = true
71 | break
72 | case 'delete': state[mapObj[item.path]].delete = true
73 | break
74 | }
75 | // console.log('重求', state)
76 | })
77 |
78 | let menuListMapObj = {
79 | auth: {
80 | title: '权限管理',
81 | key: '/auth',
82 | icon: 'el-icon- iconfont icon-quanxianguanli',
83 | children: [ // 子菜单列表
84 | {
85 | title: '用户管理',
86 | key: '/auth/userlist',
87 | icon: ''
88 | },
89 | ]
90 | },
91 | activity: {
92 | title: '活动管理',
93 | key: '/active',
94 | icon: 'el-icon- iconfont icon-huodong',
95 | children: [ // 子菜单列表
96 | {
97 | title: '活动管理',
98 | key: '/active/activelist',
99 | icon: ''
100 | },
101 | ]
102 | },
103 | banner: {
104 | title: '轮播图',
105 | key: '/banner',
106 | icon: 'el-icon-picture',
107 | children: [ // 子菜单列表
108 | {
109 | title: '首页轮播图',
110 | key: '/banner/bannerlist',
111 | icon: 'el-icon-picture'
112 | },
113 | ]
114 | },
115 | category: {
116 | title: '分类管理',
117 | key: '/category',
118 | icon: 'el-icon- iconfont icon-leimupinleifenleileibie',
119 | children: [ // 子菜单列表
120 | {
121 | title: '分类列表',
122 | key: '/category/categorylist',
123 | icon: ''
124 | },
125 | ]
126 | },
127 | comment: {
128 | title: '评论管理',
129 | key: '/comment',
130 | icon: 'el-icon- iconfont icon-ziyuan',
131 | children: [ // 子菜单列表
132 | {
133 | title: '评论列表',
134 | key: '/comment/commentlist',
135 | icon: ''
136 | },
137 | ]
138 | },
139 | goodsAndServices: {
140 | title: '商品管理',
141 | key: '/goods',
142 | icon: 'el-icon-goods',
143 | children: [ // 子菜单列表
144 | ]
145 | },
146 | goods: {
147 | title: '商品列表',
148 | key: '/goods/goodslist',
149 | icon: ''
150 | },
151 | order: {
152 | title: '订单管理',
153 | key: '/order',
154 | icon: 'el-icon- iconfont icon-dingdanguanli',
155 | children: [ // 子菜单列表
156 | {
157 | title: '订单列表',
158 | key: '/order/orderlist',
159 | icon: ''
160 | },
161 | ]
162 | },
163 | merchant: {
164 | title: '商家管理',
165 | key: '/merchant',
166 | icon: 'el-icon- iconfont icon-shangjia',
167 | children: [ // 子菜单列表
168 | {
169 | title: '店铺列表',
170 | key: '/merchant/merchantlist',
171 | icon: ''
172 | },
173 | ]
174 | },
175 | services: {
176 | title: '商品服务',
177 | key: '/goods/goodsservice',
178 | icon: ''
179 | },
180 | role: {
181 | title: '角色管理',
182 | key: '/auth/rolelist',
183 | icon: ''
184 | }
185 | }
186 |
187 | let flag = true
188 |
189 | if (state.menuList.length != 0) {
190 | return
191 | }
192 |
193 | for (const key in menuListMapObj) {
194 | // console.log(state[key].find)
195 | const standard = key == 'goods' || key == 'services' || key == 'goodsAndServices'
196 | if (standard && flag) {
197 | if (state.goods.find || state.services.find) {
198 | if (state.goods.find) {
199 | menuListMapObj.goodsAndServices.children.push(menuListMapObj.goods)
200 | }
201 | if (state.services.find) {
202 | menuListMapObj.goodsAndServices.children.push(menuListMapObj.services)
203 | }
204 | state.menuList.push(menuListMapObj.goodsAndServices)
205 | flag = false
206 | } else {
207 | state.menuList.push(menuListMapObj.goodsAndServices)
208 | flag = false
209 | }
210 | } else if (!standard) {
211 | //模块 中 只有一项 而且不是 其他模块子项
212 | //权限菜单
213 | if (key == 'role') {
214 | if (state['role']['find']) {
215 | menuListMapObj.auth.children.push(menuListMapObj.role)
216 | state.menuList.push(menuListMapObj.auth)
217 | } else {
218 | state.menuList.push(menuListMapObj.auth)
219 | }
220 | } else if (state[key].hasOwnProperty('find') && state[key]['find']) {
221 | state.menuList.push(menuListMapObj[key])
222 | }
223 | }
224 | }
225 | // console.log(state.menuList, state)
226 | }
227 |
228 | const mutations = {
229 | [PERMISSION_MAPPING_VIEW](state, data) {
230 | // console.log(func)
231 | permissionMappingView(data)
232 | },
233 | [CLEAR_CACHE](state) {
234 | state.cache = false
235 | state.menuList = []
236 | state.role = {}
237 | state.menuList = []
238 | state.activity = {}
239 | state.banner = {}
240 | state.category = {}
241 | state.comment = {}
242 | state.goods = {}
243 | state.order = {}
244 | state.merchant = {}
245 | state.services = {}
246 | state.role = {}
247 | state.auth = {}
248 | }
249 | }
250 |
251 | const actions = {
252 | async getThisUserAuth({ commit }) {
253 | //缓存中没有数据 并且 不是强制刷新 重新请求数据
254 | if (!state.cache || state.mandatoryRefresh) {
255 | const result = await getUserInfo()
256 | state.cache = true
257 | state.cacheData = result
258 | commit(PERMISSION_MAPPING_VIEW, result, permissionMappingView)
259 | } else {
260 | //以前拿到过接口的数据 防止多次请求 增加接口压力
261 | commit(PERMISSION_MAPPING_VIEW, state.cacheData, permissionMappingView)
262 | }
263 | },
264 | clearCache({ commit }) {
265 | commit(CLEAR_CACHE)
266 | }
267 | }
268 |
269 | const getters = {}
270 |
271 | export default {
272 | state,
273 | mutations,
274 | actions,
275 | getters
276 | };
--------------------------------------------------------------------------------
/src/views/activity/ActivityList.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
16 |
17 |
18 |
19 |
22 |
23 | 添加活动
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
40 |
41 |
42 |
43 |
44 | 修改
50 | 删除
56 |
57 |
58 |
59 |
60 |
61 |
62 |
70 |
71 |
72 |
73 |
79 |
80 |
81 |
82 |
83 |
84 |
94 | 点击上传
95 |
96 |
97 |
98 |
99 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
277 |
--------------------------------------------------------------------------------
/src/views/auth/RoleList.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
17 |
18 |
19 |
20 |
21 | 添加角色
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 | 修改
39 | 删除
45 |
46 |
47 |
48 |
49 |
50 |
51 |
59 |
60 |
61 |
62 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 | 全选
79 |
89 |
90 |
91 |
95 |
96 |
97 |
98 |
292 |
--------------------------------------------------------------------------------
/src/views/banner/BannerList.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
17 |
18 |
19 |
20 |
23 |
24 | 添加轮播图
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 | 修改
47 | 删除
53 |
54 |
55 |
56 |
57 |
58 |
59 |
67 |
68 |
69 |
70 |
71 |
76 |
77 |
78 |
79 |
80 |
81 |
91 |
92 |
93 |
![]()
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
322 |
323 |
324 |
326 |
--------------------------------------------------------------------------------
/src/assets/fonts/demo.css:
--------------------------------------------------------------------------------
1 | /* Logo 字体 */
2 | @font-face {
3 | font-family: "iconfont logo";
4 | src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834');
5 | src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834#iefix') format('embedded-opentype'),
6 | url('https://at.alicdn.com/t/font_985780_km7mi63cihi.woff?t=1545807318834') format('woff'),
7 | url('https://at.alicdn.com/t/font_985780_km7mi63cihi.ttf?t=1545807318834') format('truetype'),
8 | url('https://at.alicdn.com/t/font_985780_km7mi63cihi.svg?t=1545807318834#iconfont') format('svg');
9 | }
10 |
11 | .logo {
12 | font-family: "iconfont logo";
13 | font-size: 160px;
14 | font-style: normal;
15 | -webkit-font-smoothing: antialiased;
16 | -moz-osx-font-smoothing: grayscale;
17 | }
18 |
19 | /* tabs */
20 | .nav-tabs {
21 | position: relative;
22 | }
23 |
24 | .nav-tabs .nav-more {
25 | position: absolute;
26 | right: 0;
27 | bottom: 0;
28 | height: 42px;
29 | line-height: 42px;
30 | color: #666;
31 | }
32 |
33 | #tabs {
34 | border-bottom: 1px solid #eee;
35 | }
36 |
37 | #tabs li {
38 | cursor: pointer;
39 | width: 100px;
40 | height: 40px;
41 | line-height: 40px;
42 | text-align: center;
43 | font-size: 16px;
44 | border-bottom: 2px solid transparent;
45 | position: relative;
46 | z-index: 1;
47 | margin-bottom: -1px;
48 | color: #666;
49 | }
50 |
51 |
52 | #tabs .active {
53 | border-bottom-color: #f00;
54 | color: #222;
55 | }
56 |
57 | .tab-container .content {
58 | display: none;
59 | }
60 |
61 | /* 页面布局 */
62 | .main {
63 | padding: 30px 100px;
64 | width: 960px;
65 | margin: 0 auto;
66 | }
67 |
68 | .main .logo {
69 | color: #333;
70 | text-align: left;
71 | margin-bottom: 30px;
72 | line-height: 1;
73 | height: 110px;
74 | margin-top: -50px;
75 | overflow: hidden;
76 | *zoom: 1;
77 | }
78 |
79 | .main .logo a {
80 | font-size: 160px;
81 | color: #333;
82 | }
83 |
84 | .helps {
85 | margin-top: 40px;
86 | }
87 |
88 | .helps pre {
89 | padding: 20px;
90 | margin: 10px 0;
91 | border: solid 1px #e7e1cd;
92 | background-color: #fffdef;
93 | overflow: auto;
94 | }
95 |
96 | .icon_lists {
97 | width: 100% !important;
98 | overflow: hidden;
99 | *zoom: 1;
100 | }
101 |
102 | .icon_lists li {
103 | width: 100px;
104 | margin-bottom: 10px;
105 | margin-right: 20px;
106 | text-align: center;
107 | list-style: none !important;
108 | cursor: default;
109 | }
110 |
111 | .icon_lists li .code-name {
112 | line-height: 1.2;
113 | }
114 |
115 | .icon_lists .icon {
116 | display: block;
117 | height: 100px;
118 | line-height: 100px;
119 | font-size: 42px;
120 | margin: 10px auto;
121 | color: #333;
122 | -webkit-transition: font-size 0.25s linear, width 0.25s linear;
123 | -moz-transition: font-size 0.25s linear, width 0.25s linear;
124 | transition: font-size 0.25s linear, width 0.25s linear;
125 | }
126 |
127 | .icon_lists .icon:hover {
128 | font-size: 100px;
129 | }
130 |
131 | .icon_lists .svg-icon {
132 | /* 通过设置 font-size 来改变图标大小 */
133 | width: 1em;
134 | /* 图标和文字相邻时,垂直对齐 */
135 | vertical-align: -0.15em;
136 | /* 通过设置 color 来改变 SVG 的颜色/fill */
137 | fill: currentColor;
138 | /* path 和 stroke 溢出 viewBox 部分在 IE 下会显示
139 | normalize.css 中也包含这行 */
140 | overflow: hidden;
141 | }
142 |
143 | .icon_lists li .name,
144 | .icon_lists li .code-name {
145 | color: #666;
146 | }
147 |
148 | /* markdown 样式 */
149 | .markdown {
150 | color: #666;
151 | font-size: 14px;
152 | line-height: 1.8;
153 | }
154 |
155 | .highlight {
156 | line-height: 1.5;
157 | }
158 |
159 | .markdown img {
160 | vertical-align: middle;
161 | max-width: 100%;
162 | }
163 |
164 | .markdown h1 {
165 | color: #404040;
166 | font-weight: 500;
167 | line-height: 40px;
168 | margin-bottom: 24px;
169 | }
170 |
171 | .markdown h2,
172 | .markdown h3,
173 | .markdown h4,
174 | .markdown h5,
175 | .markdown h6 {
176 | color: #404040;
177 | margin: 1.6em 0 0.6em 0;
178 | font-weight: 500;
179 | clear: both;
180 | }
181 |
182 | .markdown h1 {
183 | font-size: 28px;
184 | }
185 |
186 | .markdown h2 {
187 | font-size: 22px;
188 | }
189 |
190 | .markdown h3 {
191 | font-size: 16px;
192 | }
193 |
194 | .markdown h4 {
195 | font-size: 14px;
196 | }
197 |
198 | .markdown h5 {
199 | font-size: 12px;
200 | }
201 |
202 | .markdown h6 {
203 | font-size: 12px;
204 | }
205 |
206 | .markdown hr {
207 | height: 1px;
208 | border: 0;
209 | background: #e9e9e9;
210 | margin: 16px 0;
211 | clear: both;
212 | }
213 |
214 | .markdown p {
215 | margin: 1em 0;
216 | }
217 |
218 | .markdown>p,
219 | .markdown>blockquote,
220 | .markdown>.highlight,
221 | .markdown>ol,
222 | .markdown>ul {
223 | width: 80%;
224 | }
225 |
226 | .markdown ul>li {
227 | list-style: circle;
228 | }
229 |
230 | .markdown>ul li,
231 | .markdown blockquote ul>li {
232 | margin-left: 20px;
233 | padding-left: 4px;
234 | }
235 |
236 | .markdown>ul li p,
237 | .markdown>ol li p {
238 | margin: 0.6em 0;
239 | }
240 |
241 | .markdown ol>li {
242 | list-style: decimal;
243 | }
244 |
245 | .markdown>ol li,
246 | .markdown blockquote ol>li {
247 | margin-left: 20px;
248 | padding-left: 4px;
249 | }
250 |
251 | .markdown code {
252 | margin: 0 3px;
253 | padding: 0 5px;
254 | background: #eee;
255 | border-radius: 3px;
256 | }
257 |
258 | .markdown strong,
259 | .markdown b {
260 | font-weight: 600;
261 | }
262 |
263 | .markdown>table {
264 | border-collapse: collapse;
265 | border-spacing: 0px;
266 | empty-cells: show;
267 | border: 1px solid #e9e9e9;
268 | width: 95%;
269 | margin-bottom: 24px;
270 | }
271 |
272 | .markdown>table th {
273 | white-space: nowrap;
274 | color: #333;
275 | font-weight: 600;
276 | }
277 |
278 | .markdown>table th,
279 | .markdown>table td {
280 | border: 1px solid #e9e9e9;
281 | padding: 8px 16px;
282 | text-align: left;
283 | }
284 |
285 | .markdown>table th {
286 | background: #F7F7F7;
287 | }
288 |
289 | .markdown blockquote {
290 | font-size: 90%;
291 | color: #999;
292 | border-left: 4px solid #e9e9e9;
293 | padding-left: 0.8em;
294 | margin: 1em 0;
295 | }
296 |
297 | .markdown blockquote p {
298 | margin: 0;
299 | }
300 |
301 | .markdown .anchor {
302 | opacity: 0;
303 | transition: opacity 0.3s ease;
304 | margin-left: 8px;
305 | }
306 |
307 | .markdown .waiting {
308 | color: #ccc;
309 | }
310 |
311 | .markdown h1:hover .anchor,
312 | .markdown h2:hover .anchor,
313 | .markdown h3:hover .anchor,
314 | .markdown h4:hover .anchor,
315 | .markdown h5:hover .anchor,
316 | .markdown h6:hover .anchor {
317 | opacity: 1;
318 | display: inline-block;
319 | }
320 |
321 | .markdown>br,
322 | .markdown>p>br {
323 | clear: both;
324 | }
325 |
326 |
327 | .hljs {
328 | display: block;
329 | background: white;
330 | padding: 0.5em;
331 | color: #333333;
332 | overflow-x: auto;
333 | }
334 |
335 | .hljs-comment,
336 | .hljs-meta {
337 | color: #969896;
338 | }
339 |
340 | .hljs-string,
341 | .hljs-variable,
342 | .hljs-template-variable,
343 | .hljs-strong,
344 | .hljs-emphasis,
345 | .hljs-quote {
346 | color: #df5000;
347 | }
348 |
349 | .hljs-keyword,
350 | .hljs-selector-tag,
351 | .hljs-type {
352 | color: #a71d5d;
353 | }
354 |
355 | .hljs-literal,
356 | .hljs-symbol,
357 | .hljs-bullet,
358 | .hljs-attribute {
359 | color: #0086b3;
360 | }
361 |
362 | .hljs-section,
363 | .hljs-name {
364 | color: #63a35c;
365 | }
366 |
367 | .hljs-tag {
368 | color: #333333;
369 | }
370 |
371 | .hljs-title,
372 | .hljs-attr,
373 | .hljs-selector-id,
374 | .hljs-selector-class,
375 | .hljs-selector-attr,
376 | .hljs-selector-pseudo {
377 | color: #795da3;
378 | }
379 |
380 | .hljs-addition {
381 | color: #55a532;
382 | background-color: #eaffea;
383 | }
384 |
385 | .hljs-deletion {
386 | color: #bd2c00;
387 | background-color: #ffecec;
388 | }
389 |
390 | .hljs-link {
391 | text-decoration: underline;
392 | }
393 |
394 | /* 代码高亮 */
395 | /* PrismJS 1.15.0
396 | https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript */
397 | /**
398 | * prism.js default theme for JavaScript, CSS and HTML
399 | * Based on dabblet (http://dabblet.com)
400 | * @author Lea Verou
401 | */
402 | code[class*="language-"],
403 | pre[class*="language-"] {
404 | color: black;
405 | background: none;
406 | text-shadow: 0 1px white;
407 | font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
408 | text-align: left;
409 | white-space: pre;
410 | word-spacing: normal;
411 | word-break: normal;
412 | word-wrap: normal;
413 | line-height: 1.5;
414 |
415 | -moz-tab-size: 4;
416 | -o-tab-size: 4;
417 | tab-size: 4;
418 |
419 | -webkit-hyphens: none;
420 | -moz-hyphens: none;
421 | -ms-hyphens: none;
422 | hyphens: none;
423 | }
424 |
425 | pre[class*="language-"]::-moz-selection,
426 | pre[class*="language-"] ::-moz-selection,
427 | code[class*="language-"]::-moz-selection,
428 | code[class*="language-"] ::-moz-selection {
429 | text-shadow: none;
430 | background: #b3d4fc;
431 | }
432 |
433 | pre[class*="language-"]::selection,
434 | pre[class*="language-"] ::selection,
435 | code[class*="language-"]::selection,
436 | code[class*="language-"] ::selection {
437 | text-shadow: none;
438 | background: #b3d4fc;
439 | }
440 |
441 | @media print {
442 |
443 | code[class*="language-"],
444 | pre[class*="language-"] {
445 | text-shadow: none;
446 | }
447 | }
448 |
449 | /* Code blocks */
450 | pre[class*="language-"] {
451 | padding: 1em;
452 | margin: .5em 0;
453 | overflow: auto;
454 | }
455 |
456 | :not(pre)>code[class*="language-"],
457 | pre[class*="language-"] {
458 | background: #f5f2f0;
459 | }
460 |
461 | /* Inline code */
462 | :not(pre)>code[class*="language-"] {
463 | padding: .1em;
464 | border-radius: .3em;
465 | white-space: normal;
466 | }
467 |
468 | .token.comment,
469 | .token.prolog,
470 | .token.doctype,
471 | .token.cdata {
472 | color: slategray;
473 | }
474 |
475 | .token.punctuation {
476 | color: #999;
477 | }
478 |
479 | .namespace {
480 | opacity: .7;
481 | }
482 |
483 | .token.property,
484 | .token.tag,
485 | .token.boolean,
486 | .token.number,
487 | .token.constant,
488 | .token.symbol,
489 | .token.deleted {
490 | color: #905;
491 | }
492 |
493 | .token.selector,
494 | .token.attr-name,
495 | .token.string,
496 | .token.char,
497 | .token.builtin,
498 | .token.inserted {
499 | color: #690;
500 | }
501 |
502 | .token.operator,
503 | .token.entity,
504 | .token.url,
505 | .language-css .token.string,
506 | .style .token.string {
507 | color: #9a6e3a;
508 | background: hsla(0, 0%, 100%, .5);
509 | }
510 |
511 | .token.atrule,
512 | .token.attr-value,
513 | .token.keyword {
514 | color: #07a;
515 | }
516 |
517 | .token.function,
518 | .token.class-name {
519 | color: #DD4A68;
520 | }
521 |
522 | .token.regex,
523 | .token.important,
524 | .token.variable {
525 | color: #e90;
526 | }
527 |
528 | .token.important,
529 | .token.bold {
530 | font-weight: bold;
531 | }
532 |
533 | .token.italic {
534 | font-style: italic;
535 | }
536 |
537 | .token.entity {
538 | cursor: help;
539 | }
540 |
--------------------------------------------------------------------------------
/src/views/auth/UserList.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
18 |
19 |
20 |
21 |
24 |
25 | 添加用户
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 | {{slotProps.row.createdAt | formateDate}}
36 |
37 |
38 | {{slotProps.row.updatedAt | formateDate}}
39 |
40 |
41 |
42 | 修改
48 | 删除
54 |
55 |
56 |
57 |
58 |
59 |
60 |
69 |
70 |
71 |
72 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
92 |
93 |
94 |
95 | 全选
96 |
106 |
107 |
108 |
112 |
113 |
114 |
115 |
342 |
--------------------------------------------------------------------------------
/src/views/category/AddCategory.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
15 |
16 |
17 |
18 |
25 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
48 | 点击上传
49 |
50 |
51 |
52 |
53 |
54 |
55 | 添加属性
59 |
60 |
61 |
67 |
68 |
69 |
70 |
71 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
100 |
101 |
102 | 新增属性值
108 |
109 |
110 |
111 |
117 |
123 | 删除
128 |
129 |
130 |
131 |
132 |
138 |
139 |
140 | 删除
145 |
146 |
147 |
148 |
149 |
150 |
151 | 保存
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
328 |
--------------------------------------------------------------------------------
/src/views/goods/GoodsService.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
22 |
23 |
24 |
25 |
28 |
29 | 添加服务
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 | 修改
52 | 删除
58 |
59 |
60 |
61 |
62 |
63 |
64 |
72 |
73 |
74 |
75 |
76 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
101 | 点击上传
102 |
103 |
104 |
105 |
106 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
359 |
--------------------------------------------------------------------------------
/src/assets/fontss/iconfont.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
54 |
--------------------------------------------------------------------------------
/src/assets/fontss/iconfont.js:
--------------------------------------------------------------------------------
1 | !function(a){var c,n='',l=(c=document.getElementsByTagName("script"))[c.length-1].getAttribute("data-injectcss");if(l&&!a.__iconfont__svg__cssinject__){a.__iconfont__svg__cssinject__=!0;try{document.write("")}catch(c){console&&console.log(c)}}!function(c){if(document.addEventListener)if(~["complete","loaded","interactive"].indexOf(document.readyState))setTimeout(c,0);else{var l=function(){document.removeEventListener("DOMContentLoaded",l,!1),c()};document.addEventListener("DOMContentLoaded",l,!1)}else document.attachEvent&&(t=c,i=a.document,o=!1,(n=function(){try{i.documentElement.doScroll("left")}catch(c){return void setTimeout(n,50)}e()})(),i.onreadystatechange=function(){"complete"==i.readyState&&(i.onreadystatechange=null,e())});function e(){o||(o=!0,t())}var t,i,o,n}(function(){var c,l,e,t,i,o;(c=document.createElement("div")).innerHTML=n,n=null,(l=c.getElementsByTagName("svg")[0])&&(l.setAttribute("aria-hidden","true"),l.style.position="absolute",l.style.width=0,l.style.height=0,l.style.overflow="hidden",e=l,(t=document.body).firstChild?(i=e,(o=t.firstChild).parentNode.insertBefore(i,o)):t.appendChild(e))})}(window);
--------------------------------------------------------------------------------