diff --git a/src/App.vue b/src/App.vue new file mode 100644 index 0000000..3486431 --- /dev/null +++ b/src/App.vue @@ -0,0 +1,12 @@ + + + diff --git a/src/api/ad.js b/src/api/ad.js new file mode 100644 index 0000000..55cd5e7 --- /dev/null +++ b/src/api/ad.js @@ -0,0 +1,8 @@ +import request from '@/utils/request' + +export function getList() { + return request({ + url: 'https://api.vuejs-core.cn/getAd', + method: 'get', + }) +} diff --git a/src/api/colorfulIcon.js b/src/api/colorfulIcon.js new file mode 100644 index 0000000..c2b6d5b --- /dev/null +++ b/src/api/colorfulIcon.js @@ -0,0 +1,9 @@ +import request from '@/utils/request' + +export function getIconList(data) { + return request({ + url: '/colorfulIcon/getList', + method: 'post', + data, + }) +} diff --git a/src/api/github.js b/src/api/github.js new file mode 100644 index 0000000..8d7e49d --- /dev/null +++ b/src/api/github.js @@ -0,0 +1,19 @@ +import request from 'axios' + +export function getRepos(params) { + return request({ + url: 'https://api.github.com/repos/zxwk1998/vue-admin-better', + method: 'get', + params, + timeout: 10000, + }) +} + +export function getStargazers(params) { + return request({ + url: 'https://api.github.com/repos/zxwk1998/vue-admin-better/stargazers', + method: 'get', + params, + timeout: 10000, + }) +} diff --git a/src/api/goodsList.js b/src/api/goodsList.js new file mode 100644 index 0000000..3a40f8f --- /dev/null +++ b/src/api/goodsList.js @@ -0,0 +1,9 @@ +import request from '@/utils/request' + +export function getList(data) { + return request({ + url: '/goodsList/getList', + method: 'post', + data, + }) +} diff --git a/src/api/icon.js b/src/api/icon.js new file mode 100644 index 0000000..fe1d186 --- /dev/null +++ b/src/api/icon.js @@ -0,0 +1,9 @@ +import request from '@/utils/request' + +export function getIconList(data) { + return request({ + url: '/icon/getList', + method: 'post', + data, + }) +} diff --git a/src/api/markdown.js b/src/api/markdown.js new file mode 100644 index 0000000..4359eaf --- /dev/null +++ b/src/api/markdown.js @@ -0,0 +1,8 @@ +import request from 'axios' + +export function getList() { + return request({ + url: 'https://gcore.jsdelivr.net/gh/prettier/prettier@master/docs/options.md', + method: 'get', + }) +} diff --git a/src/api/menuManagement.js b/src/api/menuManagement.js new file mode 100644 index 0000000..32b22d3 --- /dev/null +++ b/src/api/menuManagement.js @@ -0,0 +1,25 @@ +import request from '@/utils/request' + +export function getTree(data) { + return request({ + url: '/menuManagement/getTree', + method: 'post', + data, + }) +} + +export function doEdit(data) { + return request({ + url: '/menuManagement/doEdit', + method: 'post', + data, + }) +} + +export function doDelete(data) { + return request({ + url: '/menuManagement/doDelete', + method: 'post', + data, + }) +} diff --git a/src/api/notice.js b/src/api/notice.js new file mode 100644 index 0000000..280d7ce --- /dev/null +++ b/src/api/notice.js @@ -0,0 +1,17 @@ +import request from '@/utils/request' + +export function getNoticeList() { + return request({ + url: 'https://api.vuejs-core.cn/getNotice', + method: 'get', + }) +} + + + +export function getOrderList() { + return request({ + url: 'https://dev.wagoo.pet/wagoo/1.1/membership/types', + method: 'post', + }) +} diff --git a/src/api/personalCenter.js b/src/api/personalCenter.js new file mode 100644 index 0000000..804c679 --- /dev/null +++ b/src/api/personalCenter.js @@ -0,0 +1,25 @@ +import request from '@/utils/request' + +export function getList(data) { + return request({ + url: '/personalCenter/getList', + method: 'post', + data, + }) +} + +export function doEdit(data) { + return request({ + url: '/personalCenter/doEdit', + method: 'post', + data, + }) +} + +export function doDelete(data) { + return request({ + url: '/personalCenter/doDelete', + method: 'post', + data, + }) +} diff --git a/src/api/publicKey.js b/src/api/publicKey.js new file mode 100644 index 0000000..44df792 --- /dev/null +++ b/src/api/publicKey.js @@ -0,0 +1,8 @@ +import request from '@/utils/request' + +export function getPublicKey() { + return request({ + url: "/publicKey", + method: 'post', + }) +} diff --git a/src/api/remixIcon.js b/src/api/remixIcon.js new file mode 100644 index 0000000..c62ea70 --- /dev/null +++ b/src/api/remixIcon.js @@ -0,0 +1,9 @@ +import request from '@/utils/request' + +export function getIconList(data) { + return request({ + url: '/remixIcon/getList', + method: 'post', + data, + }) +} diff --git a/src/api/roleManagement.js b/src/api/roleManagement.js new file mode 100644 index 0000000..4aac23e --- /dev/null +++ b/src/api/roleManagement.js @@ -0,0 +1,25 @@ +import request from '@/utils/request' + +export function getList(data) { + return request({ + url: '/roleManagement/getList', + method: 'post', + data, + }) +} + +export function doEdit(data) { + return request({ + url: '/roleManagement/doEdit', + method: 'post', + data, + }) +} + +export function doDelete(data) { + return request({ + url: '/roleManagement/doDelete', + method: 'post', + data, + }) +} diff --git a/src/api/router.js b/src/api/router.js new file mode 100644 index 0000000..4d34d48 --- /dev/null +++ b/src/api/router.js @@ -0,0 +1,9 @@ +import request from '@/utils/request' + +export function getRouterList(data) { + return request({ + url: '/menu/navigate', + method: 'post', + data, + }) +} diff --git a/src/api/table.js b/src/api/table.js new file mode 100644 index 0000000..7023660 --- /dev/null +++ b/src/api/table.js @@ -0,0 +1,284 @@ +import request from '@/utils/request' + +export function getList(data) { + return request({ + url: '/get/order_details', + method: 'post', + data, + }) +} +// 上门洗护单 +export function getdoorList(data) { + return request({ + url: '/get/home_service_orders', + method: 'post', + data, + }) +} + +// 注册用户 +export function getUsere(data) { + return request({ + url: '/get/users', + method: 'post', + data, + }) +} + +// 商城列表 +export function getmallList(data) { + return request({ + url: '/get/product_orders', + method: 'post', + data, + }) +} + +// 小哇列表 +export function waList(data) { + return request({ + url: '/get/waInfo', + method: 'post', + data, + }) +} + + + +export function goodsListList(data) { + return request({ + url: '/get/membership_instances', + method: 'post', + data, + }) +} + +export function walletList(data) { + return request({ + url: '/get/wallet_instances', + method: 'post', + data, + }) +} + +export function archiveList(data) { + return request({ + url: '/get/pets', + method: 'post', + data, + }) +} + +export function commentList(data) { + return request({ + url: '/get/comments_info', + method: 'post', + data, + }) +} + +export function messageList(data) { + return request({ + url: '/get/notice', + method: 'post', + data, + }) +} + +export function couponList(data) { + return request({ + url: '/get/coupons', + method: 'post', + data, + }) +} + +export function couponPackage(data) { + return request({ + url: '/get/products', + method: 'post', + data, + }) +} + +/** 商城订单列表 pageNo、pageSize 必传;status_Inquiry、time 为搜索项 */ +export function getProductOrders(data) { + return request({ + url: '/get/product_orders', + method: 'post', + data, + }) +} + +export function unreadOtice(data) { + return request({ + url: '/unread_notice', + method: 'post', + data, + }) +} + +export function markNotice(data) { + return request({ + url: '/update/notice', + method: 'post', + data, + }) +} + + + + + +export function recordList(data) { + return request({ + url: '/get/delivery', + method: 'post', + data, + }) +} + +export function couponstList(data) { + return request({ + url: '/get/coupons', + method: 'post', + data, + }) +} + +export function additional(data) { + return request({ + url: '/get/additional_services', + method: 'post', + data, + }) +} + + +export function distributeEdit(data) { + return request({ + url: '/delivery/coupons', + method: 'post', + data, + }) +} +// 洗护订单导出 +export function exportUserOperateAdmin(data, headers) { + return request({ + url: '/download/order_details', + method: 'get', + data: data, + }) +} + +// 上门订单导出 +export function expordoortodoorOrdern(data, headers) { + return request({ + url: '/download/home_service_orders', + method: 'get', + data: data, + }) +} +// 商城订单导出 +export function expormallOrdern(data, headers) { + return request({ + url: '/download/product_orders', + method: 'get', + data: data, + }) +} + +// 注册用户导出 +export function exportRegisterUser(data, headers) { + return request({ + url: '/download/users', + method: 'get', + data: data, + }) +} + +export function exportUserMembership(data, headers) { + return request({ + url: '/download/membership_instances', + method: 'get', + data: data, + }) +} + +export function doEdit(data) { + return request({ + url: '/update/order_details', + method: 'post', + data, + }) +} + +export function additionalEdit(data) { + return request({ + url: '/update/additional_services', + method: 'post', + data, + }) +} + +export function addPackage(data) { + return request({ + url: '/add/package', + method: 'post', + data, + }) +} + +// 商城列表编辑接口 +export function addproduct(data) { + return request({ + url: '/update/product', + method: 'post', + data, + }) +} + +// 商城订单编辑 +export function addOrder(data) { + return request({ + url: '/update/product_order_status', + method: 'post', + data, + }) +} + +export function editPackage(data) { + return request({ + url: '/edit/package', + method: 'post', + data, + }) +} + +export function deletePackage(data) { + return request({ + url: '/delete/package', + method: 'post', + data, + }) +} + +// 商品列表 +export function deleteProduct(data) { + return request({ + url: '/update/product_status', + method: 'post', + data, + }) +} + + + + +export function doDelete(data) { + return request({ + url: '/table/doDelete', + method: 'post', + data, + }) +} diff --git a/src/api/tree.js b/src/api/tree.js new file mode 100644 index 0000000..e29ad38 --- /dev/null +++ b/src/api/tree.js @@ -0,0 +1,9 @@ +import request from '@/utils/request' + +export function getTreeList(data) { + return request({ + url: '/tree/list', + method: 'post', + data, + }) +} diff --git a/src/api/user.js b/src/api/user.js new file mode 100644 index 0000000..7772397 --- /dev/null +++ b/src/api/user.js @@ -0,0 +1,46 @@ +import request from '@/utils/request' +import { encryptedData } from '@/utils/encrypt' +import { loginRSA, tokenName } from '@/config' + +export async function login(data) { + // if (loginRSA) { + // data = await encryptedData(data) + // } + + return request({ + url: '/admin/login', + method: 'post', + data, + }) +} +export function members(data) { + return request({ + url: '/daily/new_membership_number', + method: 'post', + data, + }) +} + +export function getUserInfo(accessToken) { + return request({ + url: '/get/user_info', + method: 'post', + data: { + [tokenName]: accessToken, + }, + }) +} + +export function logout() { + return request({ + url: '/admin/logout', + method: 'post', + }) +} + +export function register() { + return request({ + url: '/register', + method: 'post', + }) +} diff --git a/src/api/userManagement.js b/src/api/userManagement.js new file mode 100644 index 0000000..9eaca6e --- /dev/null +++ b/src/api/userManagement.js @@ -0,0 +1,25 @@ +import request from '@/utils/request' + +export function getList(data) { + return request({ + url: '/userManagement/getList', + method: 'post', + data, + }) +} + +export function doEdit(data) { + return request({ + url: '/userManagement/doEdit', + method: 'post', + data, + }) +} + +export function doDelete(data) { + return request({ + url: '/userManagement/doDelete', + method: 'post', + data, + }) +} diff --git a/src/assets/Wagoo.png b/src/assets/Wagoo.png new file mode 100644 index 0000000..f758a39 Binary files /dev/null and b/src/assets/Wagoo.png differ diff --git a/src/assets/comparison/left.jpg b/src/assets/comparison/left.jpg new file mode 100644 index 0000000..f5133cf Binary files /dev/null and b/src/assets/comparison/left.jpg differ diff --git a/src/assets/comparison/right.jpg b/src/assets/comparison/right.jpg new file mode 100644 index 0000000..625a53f Binary files /dev/null and b/src/assets/comparison/right.jpg differ diff --git a/src/assets/error_images/401.png b/src/assets/error_images/401.png new file mode 100644 index 0000000..90bbf6e Binary files /dev/null and b/src/assets/error_images/401.png differ diff --git a/src/assets/error_images/404.png b/src/assets/error_images/404.png new file mode 100644 index 0000000..14fa725 Binary files /dev/null and b/src/assets/error_images/404.png differ diff --git a/src/assets/error_images/cloud.png b/src/assets/error_images/cloud.png new file mode 100644 index 0000000..247c06b Binary files /dev/null and b/src/assets/error_images/cloud.png differ diff --git a/src/assets/ewm.png b/src/assets/ewm.png new file mode 100644 index 0000000..a97a6ad Binary files /dev/null and b/src/assets/ewm.png differ diff --git a/src/assets/g.png b/src/assets/g.png new file mode 100644 index 0000000..5ee025a Binary files /dev/null and b/src/assets/g.png differ diff --git a/src/assets/login_images/background.jpg b/src/assets/login_images/background.jpg new file mode 100644 index 0000000..87ac496 Binary files /dev/null and b/src/assets/login_images/background.jpg differ diff --git a/src/assets/qr_logo/lqr_logo.png b/src/assets/qr_logo/lqr_logo.png new file mode 100644 index 0000000..f81db46 Binary files /dev/null and b/src/assets/qr_logo/lqr_logo.png differ diff --git a/src/assets/vuejs-fill.svg b/src/assets/vuejs-fill.svg new file mode 100644 index 0000000..0e6787a --- /dev/null +++ b/src/assets/vuejs-fill.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/assets/zfb_kf.jpg b/src/assets/zfb_kf.jpg new file mode 100644 index 0000000..a850a5e Binary files /dev/null and b/src/assets/zfb_kf.jpg differ diff --git a/src/components/SelectTree/index.vue b/src/components/SelectTree/index.vue new file mode 100644 index 0000000..4679d93 --- /dev/null +++ b/src/components/SelectTree/index.vue @@ -0,0 +1,187 @@ + + + + + + diff --git a/src/components/VabCharge/index.vue b/src/components/VabCharge/index.vue new file mode 100644 index 0000000..a90c90a --- /dev/null +++ b/src/components/VabCharge/index.vue @@ -0,0 +1,178 @@ + + + + + diff --git a/src/components/VabPageHeader/index.vue b/src/components/VabPageHeader/index.vue new file mode 100644 index 0000000..42d207e --- /dev/null +++ b/src/components/VabPageHeader/index.vue @@ -0,0 +1,101 @@ + + + + + diff --git a/src/components/VabProfile/index.vue b/src/components/VabProfile/index.vue new file mode 100644 index 0000000..3c7505e --- /dev/null +++ b/src/components/VabProfile/index.vue @@ -0,0 +1,305 @@ + + + + + diff --git a/src/components/VabSnow/index.vue b/src/components/VabSnow/index.vue new file mode 100644 index 0000000..96516ad --- /dev/null +++ b/src/components/VabSnow/index.vue @@ -0,0 +1,81 @@ + + + + + diff --git a/src/components/VabUpload/index.vue b/src/components/VabUpload/index.vue new file mode 100644 index 0000000..7e353ff --- /dev/null +++ b/src/components/VabUpload/index.vue @@ -0,0 +1,217 @@ + + + + + diff --git a/src/config/index.js b/src/config/index.js new file mode 100644 index 0000000..86e58d6 --- /dev/null +++ b/src/config/index.js @@ -0,0 +1,7 @@ +/** + * @description 3个子配置,通用配置|主题配置|网络配置导出 + */ +const setting = require('./setting.config') +const theme = require('./theme.config') +const network = require('./net.config') +module.exports = Object.assign({}, setting, theme, network) diff --git a/src/config/net.config.js b/src/config/net.config.js new file mode 100644 index 0000000..6ee57e4 --- /dev/null +++ b/src/config/net.config.js @@ -0,0 +1,25 @@ +/** + * @description 导出默认网路配置 + **/ +const network = { + // 默认的接口地址 如果是开发环境和生产环境走vab-mock-server,当然你也可以选择自己配置成需要的接口地址 + // 生产环境 + // 開發環境走本地代理 /api,避免跨域;生產環境直連 + baseURL: process.env.NODE_ENV === 'development' ? '/api' : 'https://admin-api.wagoo.pet/', + // 测试环境 + // baseURL: process.env.NODE_ENV === 'development' ? 'https://dev.wagoo.pet/wagoo/1.1/' : 'https://dev.wagoo.pet/wagoo/1.1/', + + //配后端数据的接收方式application/json;charset=UTF-8或者application/x-www-form-urlencoded;charset=UTF-8 + contentType: 'application/json;charset=UTF-8', + //消息框消失时间 + messageDuration: 3000, + //最长请求时间 + requestTimeout: 15000, + //操作正常code,支持String、Array、int多种类型 + successCode: [200, 0], + //登录失效code + invalidCode: 402, + //无权限code + noPermissionCode: 401, +} +module.exports = network diff --git a/src/config/permission.js b/src/config/permission.js new file mode 100644 index 0000000..387588e --- /dev/null +++ b/src/config/permission.js @@ -0,0 +1,76 @@ +/** + * @author https://github.com/zxwk1998/vue-admin-better (不想保留author可删除) + * @description 路由守卫,目前两种模式:all模式与intelligence模式 + */ +import router from '@/router' +import store from '@/store' +import VabProgress from 'nprogress' +import 'nprogress/nprogress.css' +import getPageTitle from '@/utils/pageTitle' +import { authentication, loginInterception, progressBar, recordRoute, routesWhiteList } from '@/config' + +VabProgress.configure({ + easing: 'ease', + speed: 500, + trickleSpeed: 200, + showSpinner: false, +}) +router.beforeResolve(async (to, from, next) => { + if (progressBar) VabProgress.start() + let hasToken = store.getters['user/accessToken'] + + if (!loginInterception) hasToken = true + + if (hasToken) { + if (to.path === '/login') { + next({ path: '/' }) + if (progressBar) VabProgress.done() + } else { + const hasPermissions = store.getters['user/permissions'] && store.getters['user/permissions'].length > 0 + if (hasPermissions) { + next() + } else { + try { + let permissions + if (!loginInterception) { + //settings.js loginInterception为false时,创建虚拟权限 + await store.dispatch('user/setPermissions', ['admin']) + permissions = ['admin'] + } else { + permissions = await store.dispatch('user/getUserInfo') + } + + let accessRoutes = [] + if (authentication === 'intelligence') { + accessRoutes = await store.dispatch('routes/setRoutes', permissions) + } else if (authentication === 'all') { + accessRoutes = await store.dispatch('routes/setAllRoutes') + } + accessRoutes.forEach((item) => { + router.addRoute(item) + }) + next({ ...to, replace: true }) + } catch { + await store.dispatch('user/resetAccessToken') + if (progressBar) VabProgress.done() + } + } + } + } else { + if (routesWhiteList.indexOf(to.path) !== -1) { + next() + } else { + if (recordRoute) { + next(`/login?redirect=${to.path}`) + } else { + next('/login') + } + + if (progressBar) VabProgress.done() + } + } + document.title = getPageTitle(to.meta.title) +}) +router.afterEach(() => { + if (progressBar) VabProgress.done() +}) diff --git a/src/config/setting.config.js b/src/config/setting.config.js new file mode 100644 index 0000000..ac70f1a --- /dev/null +++ b/src/config/setting.config.js @@ -0,0 +1,66 @@ +/** + * @description 导出默认通用配置 + */ +const setting = { + // 开发以及部署时的URL + publicPath: '', + // 生产环境构建文件的目录名 + outputDir: 'dist', + // 放置生成的静态资源 (js、css、img、fonts) 的 (相对于 outputDir 的) 目录。 + assetsDir: 'static', + // 开发环境每次保存时是否输出为eslint编译警告 + lintOnSave: true, + // 进行编译的依赖 + transpileDependencies: [], + //标题 (包括初次加载雪花屏的标题 页面的标题 浏览器的标题) + title: 'Wagoo管理后台', + //简写 + abbreviation: 'vab', + //开发环境端口号 + devPort: '8090', + //copyright + copyright: 'zxwk1998', + //是否显示页面底部自定义版权信息 + footerCopyright: true, + //是否显示顶部进度条 + progressBar: true, + //缓存路由的最大数量 + keepAliveMaxNum: 99, + // 路由模式,可选值为 history 或 hash + routerMode: 'hash', + //不经过token校验的路由 + routesWhiteList: ['/login', '/register', '/404', '/401'], + //加载时显示文字 + loadingText: '正在加载中...', + //token名称 + tokenName: 'accessToken', + //token在localStorage、sessionStorage存储的key的名称 + tokenTableName: 'vue-admin-better-2024', + //token存储位置localStorage sessionStorage + storage: 'localStorage', + //token失效回退到登录页时是否记录本次的路由 + recordRoute: true, + //是否显示logo,不显示时设置false,显示时请填写remixIcon图标名称,暂时只支持设置remixIcon + logo: 'vuejs-fill', + //是否显示在页面高亮错误 + errorLog: ['development'], + //是否开启登录拦截 + loginInterception: true, + //是否开启登录RSA加密 + loginRSA: true, + //intelligence和all两种方式,前者后端权限只控制permissions不控制view文件的import(前后端配合,减轻后端工作量),all方式完全交给后端前端只负责加载 + authentication: 'intelligence', + //vertical布局时是否只保持一个子菜单的展开 + uniqueOpened: true, + //vertical布局时默认展开的菜单path,使用逗号隔开建议只展开一个 + defaultOopeneds: ['/vab'], + //需要加loading层的请求,防止重复提交 + debounce: ['doEdit'], + //需要自动注入并加载的模块 + providePlugin: {}, + //代码生成机生成在view下的文件夹名称 + templateFolder: 'project', + //是否显示终端donation打印 + donation: true, +} +module.exports = setting diff --git a/src/config/settings.js b/src/config/settings.js new file mode 100644 index 0000000..c070a66 --- /dev/null +++ b/src/config/settings.js @@ -0,0 +1,6 @@ +/** + * @description 3个子配置,通用配置|主题配置|网络配置 + */ +//默认配置 +const { setting, theme, network } = require('./') +module.exports = Object.assign({}, setting, theme, network) diff --git a/src/config/theme.config.js b/src/config/theme.config.js new file mode 100644 index 0000000..b6a69d2 --- /dev/null +++ b/src/config/theme.config.js @@ -0,0 +1,14 @@ +/** + * @description 导出默认主题配置 + */ +const theme = { + //是否国定头部 固定fixed 不固定noFixed + header: 'fixed', + //横纵布局 horizontal vertical + layout: 'vertical', + //是否开启主题配置按钮 + themeBar: true, + //是否显示多标签页 + tabsBar: true, +} +module.exports = theme diff --git a/src/layouts/EmptyLayout.vue b/src/layouts/EmptyLayout.vue new file mode 100644 index 0000000..98240ae --- /dev/null +++ b/src/layouts/EmptyLayout.vue @@ -0,0 +1,3 @@ + diff --git a/src/layouts/components/VabAd/index.vue b/src/layouts/components/VabAd/index.vue new file mode 100644 index 0000000..25d0132 --- /dev/null +++ b/src/layouts/components/VabAd/index.vue @@ -0,0 +1,56 @@ + + + diff --git a/src/layouts/components/VabAppMain/index.vue b/src/layouts/components/VabAppMain/index.vue new file mode 100644 index 0000000..c1a7983 --- /dev/null +++ b/src/layouts/components/VabAppMain/index.vue @@ -0,0 +1,106 @@ + + + + + diff --git a/src/layouts/components/VabAvatar/index.vue b/src/layouts/components/VabAvatar/index.vue new file mode 100644 index 0000000..506fc80 --- /dev/null +++ b/src/layouts/components/VabAvatar/index.vue @@ -0,0 +1,254 @@ + + + + + diff --git a/src/layouts/components/VabBreadcrumb/index.vue b/src/layouts/components/VabBreadcrumb/index.vue new file mode 100644 index 0000000..d6d6d43 --- /dev/null +++ b/src/layouts/components/VabBreadcrumb/index.vue @@ -0,0 +1,61 @@ + + + + + diff --git a/src/layouts/components/VabColorfullIcon/index.vue b/src/layouts/components/VabColorfullIcon/index.vue new file mode 100644 index 0000000..840de3c --- /dev/null +++ b/src/layouts/components/VabColorfullIcon/index.vue @@ -0,0 +1,65 @@ + + + + + diff --git a/src/layouts/components/VabErrorLog/index.vue b/src/layouts/components/VabErrorLog/index.vue new file mode 100644 index 0000000..e2681ce --- /dev/null +++ b/src/layouts/components/VabErrorLog/index.vue @@ -0,0 +1,128 @@ + + + + + diff --git a/src/layouts/components/VabFullScreen/index.vue b/src/layouts/components/VabFullScreen/index.vue new file mode 100644 index 0000000..b5885af --- /dev/null +++ b/src/layouts/components/VabFullScreen/index.vue @@ -0,0 +1,47 @@ + + + diff --git a/src/layouts/components/VabGithubCorner/index.vue b/src/layouts/components/VabGithubCorner/index.vue new file mode 100644 index 0000000..d2dfb31 --- /dev/null +++ b/src/layouts/components/VabGithubCorner/index.vue @@ -0,0 +1,75 @@ + + + + diff --git a/src/layouts/components/VabLogo/index.vue b/src/layouts/components/VabLogo/index.vue new file mode 100644 index 0000000..b79ebd0 --- /dev/null +++ b/src/layouts/components/VabLogo/index.vue @@ -0,0 +1,95 @@ + + + diff --git a/src/layouts/components/VabNav/index.vue b/src/layouts/components/VabNav/index.vue new file mode 100644 index 0000000..822e76a --- /dev/null +++ b/src/layouts/components/VabNav/index.vue @@ -0,0 +1,196 @@ + + + + + diff --git a/src/layouts/components/VabQueryForm/VabQueryFormBottomPanel.vue b/src/layouts/components/VabQueryForm/VabQueryFormBottomPanel.vue new file mode 100644 index 0000000..327dc83 --- /dev/null +++ b/src/layouts/components/VabQueryForm/VabQueryFormBottomPanel.vue @@ -0,0 +1,20 @@ + + + diff --git a/src/layouts/components/VabQueryForm/VabQueryFormLeftPanel.vue b/src/layouts/components/VabQueryForm/VabQueryFormLeftPanel.vue new file mode 100644 index 0000000..38795e4 --- /dev/null +++ b/src/layouts/components/VabQueryForm/VabQueryFormLeftPanel.vue @@ -0,0 +1,25 @@ + + + diff --git a/src/layouts/components/VabQueryForm/VabQueryFormRightPanel.vue b/src/layouts/components/VabQueryForm/VabQueryFormRightPanel.vue new file mode 100644 index 0000000..0e3c4e3 --- /dev/null +++ b/src/layouts/components/VabQueryForm/VabQueryFormRightPanel.vue @@ -0,0 +1,25 @@ + + + diff --git a/src/layouts/components/VabQueryForm/VabQueryFormTopPanel.vue b/src/layouts/components/VabQueryForm/VabQueryFormTopPanel.vue new file mode 100644 index 0000000..7a48e3f --- /dev/null +++ b/src/layouts/components/VabQueryForm/VabQueryFormTopPanel.vue @@ -0,0 +1,20 @@ + + + diff --git a/src/layouts/components/VabQueryForm/index.vue b/src/layouts/components/VabQueryForm/index.vue new file mode 100644 index 0000000..f49a6bb --- /dev/null +++ b/src/layouts/components/VabQueryForm/index.vue @@ -0,0 +1,63 @@ + + + + + diff --git a/src/layouts/components/VabSide/components/VabMenuItem.vue b/src/layouts/components/VabSide/components/VabMenuItem.vue new file mode 100644 index 0000000..fc34144 --- /dev/null +++ b/src/layouts/components/VabSide/components/VabMenuItem.vue @@ -0,0 +1,84 @@ + + + diff --git a/src/layouts/components/VabSide/components/VabSideItem.vue b/src/layouts/components/VabSide/components/VabSideItem.vue new file mode 100644 index 0000000..21af61e --- /dev/null +++ b/src/layouts/components/VabSide/components/VabSideItem.vue @@ -0,0 +1,96 @@ + + + + + diff --git a/src/layouts/components/VabSide/components/VabSubmenu.vue b/src/layouts/components/VabSide/components/VabSubmenu.vue new file mode 100644 index 0000000..7e67e3a --- /dev/null +++ b/src/layouts/components/VabSide/components/VabSubmenu.vue @@ -0,0 +1,48 @@ + + + diff --git a/src/layouts/components/VabSide/index.vue b/src/layouts/components/VabSide/index.vue new file mode 100644 index 0000000..6b9cffc --- /dev/null +++ b/src/layouts/components/VabSide/index.vue @@ -0,0 +1,141 @@ + + + diff --git a/src/layouts/components/VabTabs/index.vue b/src/layouts/components/VabTabs/index.vue new file mode 100644 index 0000000..49545a3 --- /dev/null +++ b/src/layouts/components/VabTabs/index.vue @@ -0,0 +1,761 @@ + + + + + + + diff --git a/src/layouts/components/VabTheme/index.vue b/src/layouts/components/VabTheme/index.vue new file mode 100644 index 0000000..7d9c380 --- /dev/null +++ b/src/layouts/components/VabTheme/index.vue @@ -0,0 +1,600 @@ + + + + + + diff --git a/src/layouts/components/VabTop/index.vue b/src/layouts/components/VabTop/index.vue new file mode 100644 index 0000000..60d970d --- /dev/null +++ b/src/layouts/components/VabTop/index.vue @@ -0,0 +1,221 @@ + + + + diff --git a/src/layouts/export.js b/src/layouts/export.js new file mode 100644 index 0000000..1f7e4bd --- /dev/null +++ b/src/layouts/export.js @@ -0,0 +1,20 @@ +/** + * @author https://github.com/zxwk1998/vue-admin-better (不想保留author可删除) + * @description 公共布局及样式自动引入 + */ + +import Vue from 'vue' + +const requireComponents = require.context('./components', true, /\.vue$/) +requireComponents.keys().forEach((fileName) => { + const componentConfig = requireComponents(fileName) + const componentName = componentConfig.default.name + Vue.component(componentName, componentConfig.default || componentConfig) +}) + +// 使用 require.context 安全地导入主题文件 +const requireThemes = require.context('@/styles/themes', true, /\.scss$/) +requireThemes.keys().forEach((fileName) => { + // 使用 require.context 直接引入,避免动态字符串拼接 + requireThemes(fileName) +}) diff --git a/src/layouts/index.vue b/src/layouts/index.vue new file mode 100644 index 0000000..c5a7e34 --- /dev/null +++ b/src/layouts/index.vue @@ -0,0 +1,298 @@ + + + + + diff --git a/src/main.js b/src/main.js new file mode 100644 index 0000000..d303984 --- /dev/null +++ b/src/main.js @@ -0,0 +1,47 @@ +import Vue from 'vue' +import App from './App' +import store from './store' +import router from './router' +import './plugins' +import '@/layouts/export' +import { printLayoutsInfo } from '@/utils/printInfo' +import JSEncrypt from 'jsencrypt'; + +/** + * @author https://github.com/zxwk1998/vue-admin-better (不想保留author可删除) + * @description 生产环境默认都使用mock,如果正式用于生产环境时,记得去掉 + */ + +// 检测环境变量或默认使用mock +// 生产环境 +// const useMock = process.env.VUE_APP_MOCK_ENABLE === 'true' || process.env.NODE_ENV === 'development' +// development +// production +// 测试环境 +const useMock = process.env.VUE_APP_MOCK_ENABLE === 'true' || process.env.NODE_ENV === 'production' +if (useMock) { + // 使用动态import替代require + import('@/utils/static').then(({ mockXHR }) => { + mockXHR() + console.log('已启用Mock拦截,所有接口请求将被Mock拦截') + // 打印layouts/index.js中的信息到控制台 + printLayoutsInfo() + Vue.config.productionTip = false + Vue.prototype.$jsEncrypt = JSEncrypt; + new Vue({ + el: '#vue-admin-better', + router, + store, + render: (h) => h(App), + }) + }) +} else { + // 未启用Mock时直接打印layouts/index.js中的信息到控制台 + printLayoutsInfo() + new Vue({ + el: '#vue-admin-better', + router, + store, + render: (h) => h(App), + }) +} diff --git a/src/plugins/echarts.js b/src/plugins/echarts.js new file mode 100644 index 0000000..f600f83 --- /dev/null +++ b/src/plugins/echarts.js @@ -0,0 +1,4 @@ +import 'echarts' +import VabChart from 'vue-echarts' + +export default VabChart diff --git a/src/plugins/element.js b/src/plugins/element.js new file mode 100644 index 0000000..349da86 --- /dev/null +++ b/src/plugins/element.js @@ -0,0 +1,7 @@ +import Vue from 'vue' +import ElementUI from 'element-ui' +import 'element-ui/lib/theme-chalk/index.css' + +Vue.use(ElementUI, { + size: 'small', +}) diff --git a/src/plugins/index.js b/src/plugins/index.js new file mode 100644 index 0000000..b5dace4 --- /dev/null +++ b/src/plugins/index.js @@ -0,0 +1,13 @@ +/* 公共引入,勿随意修改,修改时需经过确认 */ +import Vue from 'vue' +import './element' +import './support' +import '@/styles/vab.scss' +import '@/config/permission' +import '@/utils/errorLog' +import './vabIcon' +import VabPermissions from 'layouts/Permissions' +import Vab from '@/utils/vab' + +Vue.use(Vab) +Vue.use(VabPermissions) diff --git a/src/plugins/support.js b/src/plugins/support.js new file mode 100644 index 0000000..14e8d1f --- /dev/null +++ b/src/plugins/support.js @@ -0,0 +1,16 @@ +import { MessageBox } from 'element-ui' + +if (!!window.ActiveXObject || 'ActiveXObject' in window) { + MessageBox({ + title: '温馨提示', + message: + '自2015年3月起,微软已宣布弃用IE,且不再对IE提供任何更新维护,请点击此处访问微软官网更新浏览器,如果您使用的是双核浏览器,请您切换浏览器内核为极速模式', + type: 'warning', + showClose: false, + showConfirmButton: false, + closeOnClickModal: false, + closeOnPressEscape: false, + closeOnHashChange: false, + dangerouslyUseHTMLString: true, + }) +} diff --git a/src/plugins/vabIcon.js b/src/plugins/vabIcon.js new file mode 100644 index 0000000..634bca7 --- /dev/null +++ b/src/plugins/vabIcon.js @@ -0,0 +1,4 @@ +import Vue from 'vue' +import VabIcon from 'vab-icon' + +Vue.component('VabIcon', VabIcon) diff --git a/src/router/index.js b/src/router/index.js new file mode 100644 index 0000000..dab4452 --- /dev/null +++ b/src/router/index.js @@ -0,0 +1,539 @@ +/** + * @author https://github.com/zxwk1998/vue-admin-better (不想保留author可删除) + * @description router全局配置,如有必要可分文件抽离,其中asyncRoutes只有在intelligence模式下才会用到,vip文档中已提供路由的基础图标与小清新图标的配置方案,请仔细阅读 + */ + +import Vue from 'vue' +import VueRouter from 'vue-router' +import Layout from '@/layouts' +import EmptyLayout from '@/layouts/EmptyLayout' +import { publicPath, routerMode } from '@/config' + +Vue.use(VueRouter) +export const constantRoutes = [ + { + path: '/login', + component: () => import('@/views/login/index'), + hidden: true, + }, + { + path: '/register', + component: () => import('@/views/register/index'), + hidden: true, + }, + { + path: '/401', + name: '401', + component: () => import('@/views/401'), + hidden: true, + }, + { + path: '/404', + name: '404', + component: () => import('@/views/404'), + hidden: true, + }, +] + +export const asyncRoutes = [ + { + path: '/', + component: Layout, + redirect: '/index', + children: [ + { + path: 'index', + + name: 'Index', + component: () => import('@/views/index/index'), + meta: { + title: '首页', + icon: 'home', + affix: true, + }, + }, + ], + }, + { + path: '/mall', + component: Layout, + redirect: 'noRedirect', + name: 'Mall', + meta: { + title: '预约数据', + icon: 'book', + permissions: ['admin'], + }, + + children: [ + { + path: 'pay', + name: 'Pay', + component: () => import('@/views/mall/pay/index'), + meta: { + title: '洗护订单管理', + noKeepAlive: true, + }, + children: null, + }, + { + path: 'doorOrder', + name: 'doorOrder', + component: () => import('@/views/mall/doorOrder/index'), + meta: { + title: '上门订单管理', + noKeepAlive: true, + }, + children: null, + }, + { + path: 'registerUser', + name: 'registerUser', + component: () => import('@/views/mall/registerUser/index'), + meta: { + title: '注册用户', + noKeepAlive: true, + }, + children: null, + }, + + { + path: 'goodsList', + name: 'GoodsList', + component: () => import('@/views/mall/goodsList/index'), + meta: { + title: '钱包管理', + }, + }, + { + path: 'points', + name: 'points', + component: () => import('@/views/mall/points/index'), + meta: { + title: '积分管理', + }, + }, + { + path: 'member', + name: 'Member', + component: () => import('@/views/mall/member/index'), + meta: { + title: '会员管理', + }, + + }, + { + path: 'time', + name: 'time', + component: () => import('@/views/mall/time/index'), + meta: { + title: '时段管理', + }, + + }, + { + path: 'additional', + name: 'Additional', + component: () => import('@/views/mall/additional/index'), + meta: { + title: '附加项管理', + }, + }, + { + path: 'archive', + name: 'Archive', + component: () => import('@/views/mall/archive/index'), + meta: { + title: '宠物档案管理', + }, + }, + ], + }, + { + path: '/coupon', + component: Layout, + redirect: 'noRedirect', + name: 'Coupon', + meta: { + title: '券管理', + icon: 'cog', + permissions: ['admin'], + }, + children: [ + // { + // path: 'couponlist', + // name: 'Couponlist', + // component: () => import('@/views/Coupon/couponlist/index'), + // meta: { + // title: '券包', + // }, + // }, + // { + // path: 'distribution', + // name: 'distribution', + // component: () => import('@/views/Coupon/distribution/index'), + // meta: { + // title: '优惠券', + // }, + // }, + { + path: 'redemption', + name: 'redemption', + component: () => import('@/views/Coupon/redemption/index'), + meta: { + title: '兑换码', + }, + }, + { + path: 'distribute', + name: 'Distribute', + component: () => import('@/views/Coupon/distribute/index'), + meta: { + title: '派券管理', + }, + }, + { + path: 'record', + name: 'Record', + component: () => import('@/views/Coupon/record/index'), + meta: { + title: '派券记录', + }, + }, + + ], + }, + + { + path: '/careManagement', + component: Layout, + redirect: 'careManagement', + name: 'Comment', + meta: { + title: '洗护管理', + icon: 'sleigh', + permissions: ['admin'], + }, + children: [ + { + path: 'therapist', + name: 'therapist', + component: () => import('@/views/careManagement/therapist/index'), + meta: { + title: '洗护师管理', + }, + }, + { + path: 'vehicle', + name: 'vehicle', + component: () => import('@/views/careManagement/vehicle/index'), + meta: { + title: '车辆洗护师关系绑定', + }, + } + ], + }, + { + path: '/publicWelfare', + component: Layout, + redirect: 'publicWelfare', + name: 'Comment', + meta: { + title: '公益管理', + icon: 'bahai', + permissions: ['admin'], + }, + children: [ + { + path: 'adopt', + name: 'adopt', + component: () => import('@/views/publicWelfare/adopt/index'), + meta: { + title: '领养宠物管理', + }, + }, + { + path: 'points', + name: 'points', + component: () => import('@/views/publicWelfare/points/index'), + meta: { + title: '积分捐助管理', + }, + }, + { + path: 'public', + name: 'public', + component: () => import('@/views/publicWelfare/public/index'), + meta: { + title: '公益行管理', + }, + } + ], + }, + + { + path: '/franchisee', + component: Layout, + redirect: 'franchisee', + name: 'Comment', + meta: { + title: '加盟商管理', + icon: 'book-reader', + permissions: ['admin'], + }, + children: [ + { + path: 'xiaowa', + name: 'Xiaowa', + component: () => import('@/views/xiaowa/index'), + meta: { + title: '小哇管理', + }, + }, + { + path: 'vehicle', + name: 'Vehicle', + component: () => import('@/views/vehicle/index'), + meta: { + title: '车辆管理', + }, + }, + // { + // path: 'order', + // name: 'Order', + // component: () => import('@/views/order/index'), + // meta: { + // title: '订单管理', + // }, + // }, + { + path: 'information', + name: 'Information', + component: () => import('@/views/information/index'), + + meta: { + title: '信息管理', + permissions: ['admin', ], + }, + }, + + ], + }, + { + path: '/administrator', + component: Layout, + redirect: 'administrator', + name: 'Comment', + meta: { + title: '管理员权限管理', + icon: 'paper-plane', + permissions: ['admin'], + }, + children: [ + { + path: 'role', + name: 'role', + component: () => import('@/views/administrator/role/index'), + meta: { + title: '角色管理', + }, + }, + { + path: 'user', + name: 'user', + component: () => import('@/views/administrator/user/index'), + meta: { + title: '用户列表', + }, + } + ], + }, + { + path: '/pricing', + component: Layout, + redirect: 'pricing', + name: 'Comment', + meta: { + title: '定价管理', + icon: 'pen-square', + permissions: ['admin'], + }, + children: [ + { + path: 'care', + name: 'care', + component: () => import('@/views/pricing/care/index'), + meta: { + title: '洗护价格列表', + }, + }, + { + path: 'commission', + name: 'commission', + component: () => import('@/views/pricing/commission/index'), + meta: { + title: '佣金列表', + }, + } + ], + }, + { + path: '/commodity', + component: Layout, + redirect: 'noRedirect', + name: 'commodity', + meta: { + title: '商城管理', + icon: 'comment-dots', + permissions: ['admin'], + }, + children: [ + { + path: 'malllist', + name: 'malllist', + component: () => import('@/views/commodity/malllist/index'), + meta: { + title: '商品列表', + }, + }, + { + path: 'orderlist', + name: 'orderlist', + component: () => import('@/views/commodity/orderlist/index'), + meta: { + title: '商城订单', + }, + }, + ], + }, + { + path: '/comment', + component: Layout, + redirect: 'noRedirect', + name: 'Comment', + meta: { + title: '评论管理', + icon: 'comment-dots', + permissions: ['admin'], + }, + children: [ + { + path: 'comment', + name: 'Comment', + component: () => import('@/views/comment/index'), + meta: { + title: '评论列表', + }, + }, + ], + }, + + { + path: '/payment', + component: Layout, + redirect: 'payment', + name: 'Comment', + meta: { + title: '支付管理', + icon: 'comment-dots', + permissions: ['admin'], + }, + children: [ + { + path: 'paymentList', + name: 'paymentList', + component: () => import('@/views/payment/paymentList/index'), + meta: { + title: '支付列表', + }, + } + ], + }, + + { + path: '/settlement', + component: Layout, + redirect: 'settlement', + name: 'Comment', + meta: { + title: '结算管理', + icon: 'comment-dots', + permissions: ['admin'], + }, + children: [ + { + path: 'sett', + name: 'sett', + component: () => import('@/views/settlement/sett/index'), + meta: { + title: '结算列表', + }, + } + ], + }, + + { + path: '/certificate', + component: Layout, + redirect: 'certificate', + name: 'Comment', + meta: { + title: '证书管理', + icon: 'comment-dots', + permissions: ['admin'], + }, + children: [ + { + path: 'ficate', + name: 'ficate', + component: () => import('@/views/certificate/ficate/index'), + meta: { + title: '证书列表', + }, + } + ], + }, + + { + path: '/holidays', + component: Layout, + redirect: 'holidays', + name: 'Comment', + meta: { + title: '节假日管理', + icon: 'comment-dots', + permissions: ['admin'], + }, + children: [ + { + path: 'day', + name: 'day', + component: () => import('@/views/holidays/day/index'), + meta: { + title: '节假日列表', + }, + } + ], + }, + + { + path: '*', + redirect: '/404', + hidden: true, + }, +] + +const router = new VueRouter({ + base: publicPath, + mode: routerMode, + scrollBehavior: () => ({ + y: 0, + }), + routes: constantRoutes, +}) + +export function resetRouter() { + location.reload() +} + +export default router diff --git a/src/store/index.js b/src/store/index.js new file mode 100644 index 0000000..efc3487 --- /dev/null +++ b/src/store/index.js @@ -0,0 +1,22 @@ +/** + * @author https://github.com/zxwk1998/vue-admin-better (不想保留author可删除) + * @description 导入所有 vuex 模块,自动加入namespaced:true,用于解决vuex命名冲突,请勿修改。 + */ + +import Vue from 'vue' +import Vuex from 'vuex' + +Vue.use(Vuex) +const files = require.context('./modules', false, /\.js$/) +const modules = {} + +files.keys().forEach((key) => { + modules[key.replace(/(\.\/|\.js)/g, '')] = files(key).default +}) +Object.keys(modules).forEach((key) => { + modules[key]['namespaced'] = true +}) +const store = new Vuex.Store({ + modules, +}) +export default store diff --git a/src/store/modules/errorLog.js b/src/store/modules/errorLog.js new file mode 100644 index 0000000..08c7c03 --- /dev/null +++ b/src/store/modules/errorLog.js @@ -0,0 +1,28 @@ +/** + * @author https://github.com/zxwk1998/vue-admin-better (不想保留author可删除) + * @description 异常捕获的状态拦截,请勿修改 + */ + +const state = () => ({ + errorLogs: [], +}) +const getters = { + errorLogs: (state) => state.errorLogs, +} +const mutations = { + addErrorLog(state, errorLog) { + state.errorLogs.push(errorLog) + }, + clearErrorLog: (state) => { + state.errorLogs.splice(0) + }, +} +const actions = { + addErrorLog({ commit }, errorLog) { + commit('addErrorLog', errorLog) + }, + clearErrorLog({ commit }) { + commit('clearErrorLog') + }, +} +export default { state, getters, mutations, actions } diff --git a/src/store/modules/routes.js b/src/store/modules/routes.js new file mode 100644 index 0000000..586b6d1 --- /dev/null +++ b/src/store/modules/routes.js @@ -0,0 +1,63 @@ +/** + * @author https://github.com/zxwk1998/vue-admin-better (不想保留author可删除) + * @description 路由拦截状态管理,目前两种模式:all模式与intelligence模式 + */ +import { asyncRoutes, constantRoutes } from '@/router' +import { getRouterList } from '@/api/router' +import { convertRouter, filterAsyncRoutes } from '@/utils/handleRoutes' + +const state = () => ({ + routes: [], + partialRoutes: [], +}) +const getters = { + routes: (state) => state.routes, + partialRoutes: (state) => state.partialRoutes, +} +const mutations = { + setRoutes(state, routes) { + state.routes = constantRoutes.concat(routes) + }, + setAllRoutes(state, routes) { + state.routes = constantRoutes.concat(routes) + }, +} +const actions = { + /** + * @author https://github.com/zxwk1998/vue-admin-better (不想保留author可删除) + * @description intelligence模式设置路由 + * @param {*} { commit } + * @param {*} permissions + * @returns + */ + async setRoutes({ commit }, permissions) { + //根据permissions做路由筛选 + let accessedRoutes = filterAsyncRoutes(asyncRoutes, permissions) + commit('setRoutes', accessedRoutes) + return accessedRoutes + }, + /** + * @author https://github.com/zxwk1998/vue-admin-better (不想保留author可删除) + * @description all模式设置路由 + * @param {*} { commit } + * @returns + */ + async setAllRoutes({ commit }) { + try { + let { data } = await getRouterList() + if (!data || !Array.isArray(data)) { + console.error('后端返回的路由数据格式不正确', data) + data = [] + } + + const accessedRoutes = convertRouter(data) + commit('setAllRoutes', accessedRoutes) + return accessedRoutes + } catch (error) { + console.error('获取路由列表失败', error) + commit('setAllRoutes', []) + return [] + } + }, +} +export default { state, getters, mutations, actions } diff --git a/src/store/modules/settings.js b/src/store/modules/settings.js new file mode 100644 index 0000000..183fbc0 --- /dev/null +++ b/src/store/modules/settings.js @@ -0,0 +1,74 @@ +/** + * @author https://github.com/zxwk1998/vue-admin-better (不想保留author可删除) + * @description 所有全局配置的状态管理,如无必要请勿修改 + */ + +import defaultSettings from '@/config' + +const { tabsBar, logo, layout, header, themeBar } = defaultSettings +const theme = JSON.parse(localStorage.getItem('vue-admin-better-theme')) || '' +const state = () => ({ + tabsBar: theme.tabsBar || tabsBar, + logo, + collapse: false, + layout: theme.layout || layout, + header: theme.header || header, + device: 'desktop', + themeBar, +}) +const getters = { + collapse: (state) => state.collapse, + device: (state) => state.device, + header: (state) => state.header, + layout: (state) => state.layout, + logo: (state) => state.logo, + tabsBar: (state) => state.tabsBar, + themeBar: (state) => state.themeBar, +} +const mutations = { + changeLayout: (state, layout) => { + if (layout) state.layout = layout + }, + changeHeader: (state, header) => { + if (header) state.header = header + }, + changeTabsBar: (state, tabsBar) => { + if (tabsBar) state.tabsBar = tabsBar + }, + changeCollapse: (state) => { + state.collapse = !state.collapse + }, + foldSideBar: (state) => { + state.collapse = true + }, + openSideBar: (state) => { + state.collapse = false + }, + toggleDevice: (state, device) => { + state.device = device + }, +} +const actions = { + changeLayout({ commit }, layout) { + commit('changeLayout', layout) + }, + changeHeader({ commit }, header) { + commit('changeHeader', header) + }, + changeTabsBar({ commit }, tabsBar) { + commit('changeTabsBar', tabsBar) + }, + changeCollapse({ commit }) { + commit('changeCollapse') + }, + foldSideBar({ commit }) { + commit('foldSideBar') + }, + openSideBar({ commit }) { + commit('openSideBar') + }, + toggleDevice({ commit }, device) { + commit('toggleDevice', device) + }, +} +export default { state, getters, mutations, actions } diff --git a/src/store/modules/table.js b/src/store/modules/table.js new file mode 100644 index 0000000..616eda5 --- /dev/null +++ b/src/store/modules/table.js @@ -0,0 +1,23 @@ +/** + * @author https://github.com/zxwk1998/vue-admin-better (不想保留author可删除) + * @description 代码生成机状态管理 + */ + +const state = () => ({ + srcCode: '', +}) +const getters = { + srcTableCode: (state) => state.srcCode, +} + +const mutations = { + setTableCode(state, srcCode) { + state.srcCode = srcCode + }, +} +const actions = { + setTableCode({ commit }, srcCode) { + commit('setTableCode', srcCode) + }, +} +export default { state, getters, mutations, actions } diff --git a/src/store/modules/tabsBar.js b/src/store/modules/tabsBar.js new file mode 100644 index 0000000..a1097e1 --- /dev/null +++ b/src/store/modules/tabsBar.js @@ -0,0 +1,110 @@ +/** + * @author https://github.com/zxwk1998/vue-admin-better (不想保留author可删除) + * @description tabsBar多标签页逻辑,前期借鉴了很多开源项目发现都有个共同的特点很繁琐并不符合框架设计的初衷,后来在github用户hipi的启发下完成了重构,请勿修改 + */ + +const state = () => ({ + visitedRoutes: [], +}) +const getters = { + visitedRoutes: (state) => state.visitedRoutes, +} +const mutations = { + addVisitedRoute(state, route) { + let target = state.visitedRoutes.find((item) => item.path === route.path) + if (target) { + if (route.fullPath !== target.fullPath) Object.assign(target, route) + return + } + state.visitedRoutes.push(Object.assign({}, route)) + }, + delVisitedRoute(state, route) { + state.visitedRoutes.forEach((item, index) => { + if (item.path === route.path) state.visitedRoutes.splice(index, 1) + }) + }, + delOthersVisitedRoute(state, route) { + state.visitedRoutes = state.visitedRoutes.filter((item) => item.meta.affix || item.path === route.path) + }, + delLeftVisitedRoute(state, route) { + let index = state.visitedRoutes.length + state.visitedRoutes = state.visitedRoutes.filter((item) => { + if (item.name === route.name) index = state.visitedRoutes.indexOf(item) + return item.meta.affix || index <= state.visitedRoutes.indexOf(item) + }) + }, + delRightVisitedRoute(state, route) { + let index = state.visitedRoutes.length + state.visitedRoutes = state.visitedRoutes.filter((item) => { + if (item.name === route.name) index = state.visitedRoutes.indexOf(item) + return item.meta.affix || index >= state.visitedRoutes.indexOf(item) + }) + }, + delAllVisitedRoutes(state) { + state.visitedRoutes = state.visitedRoutes.filter((item) => item.meta.affix) + }, + updateVisitedRoute(state, route) { + state.visitedRoutes.forEach((item) => { + if (item.path === route.path) item = Object.assign(item, route) + }) + }, +} +const actions = { + addVisitedRoute({ commit }, route) { + commit('addVisitedRoute', route) + }, + async delRoute({ dispatch, state }, route) { + await dispatch('delVisitedRoute', route) + return { + visitedRoutes: [...state.visitedRoutes], + } + }, + delVisitedRoute({ commit, state }, route) { + commit('delVisitedRoute', route) + return [...state.visitedRoutes] + }, + async delOthersRoutes({ dispatch, state }, route) { + await dispatch('delOthersVisitedRoute', route) + return { + visitedRoutes: [...state.visitedRoutes], + } + }, + async delLeftRoutes({ dispatch, state }, route) { + await dispatch('delLeftVisitedRoute', route) + return { + visitedRoutes: [...state.visitedRoutes], + } + }, + async delRightRoutes({ dispatch, state }, route) { + await dispatch('delRightVisitedRoute', route) + return { + visitedRoutes: [...state.visitedRoutes], + } + }, + delOthersVisitedRoute({ commit, state }, route) { + commit('delOthersVisitedRoute', route) + return [...state.visitedRoutes] + }, + delLeftVisitedRoute({ commit, state }, route) { + commit('delLeftVisitedRoute', route) + return [...state.visitedRoutes] + }, + delRightVisitedRoute({ commit, state }, route) { + commit('delRightVisitedRoute', route) + return [...state.visitedRoutes] + }, + async delAllRoutes({ dispatch, state }, route) { + await dispatch('delAllVisitedRoutes', route) + return { + visitedRoutes: [...state.visitedRoutes], + } + }, + delAllVisitedRoutes({ commit, state }) { + commit('delAllVisitedRoutes') + return [...state.visitedRoutes] + }, + updateVisitedRoute({ commit }, route) { + commit('updateVisitedRoute', route) + }, +} +export default { state, getters, mutations, actions } diff --git a/src/store/modules/user.js b/src/store/modules/user.js new file mode 100644 index 0000000..ba65c1d --- /dev/null +++ b/src/store/modules/user.js @@ -0,0 +1,85 @@ +/** + * @author https://github.com/zxwk1998/vue-admin-better (不想保留author可删除) + * @description 登录、获取用户信息、退出登录、清除accessToken逻辑,不建议修改 + */ + +import Vue from 'vue' +import { getUserInfo, login, logout } from '@/api/user' +import { getPublicKey } from '@/api/publicKey' +import { getAccessToken, removeAccessToken, setAccessToken } from '@/utils/accessToken' +import { resetRouter } from '@/router' +import { title, tokenName } from '@/config' + +const state = () => ({ + accessToken: getAccessToken(), + username: '', + avatar: '', + permissions: [], +}) +const getters = { + accessToken: (state) => state.accessToken, + username: (state) => state.username, + avatar: (state) => state.avatar, + permissions: (state) => state.permissions, +} +const mutations = { + setAccessToken(state, accessToken) { + state.accessToken = accessToken + setAccessToken(accessToken) + }, + setUsername(state, username) { + state.username = username + }, + setAvatar(state, avatar) { + state.avatar = avatar + }, + setPermissions(state, permissions) { + state.permissions = permissions + }, +} +const actions = { + setPermissions({ commit }, permissions) { + commit('setPermissions', permissions) + }, + async login({ commit }, userInfo) { + const { data } = await login(userInfo) + const accessToken = data.tokenName + console.log(data,'--/-----111') + if (accessToken) { + commit('setAccessToken', accessToken) + const hour = new Date().getHours() + const thisTime = hour < 8 ? '早上好' : hour <= 11 ? '上午好' : hour <= 13 ? '中午好' : hour < 18 ? '下午好' : '晚上好' + Vue.prototype.$baseNotify(`欢迎登录${title}`, `${thisTime}!`) + } else { + Vue.prototype.$baseMessage(`登录接口异常,未正确返回${tokenName}...`, 'error') + } + }, + async getUserInfo({ commit, state }) { + const { data } = await getUserInfo(state.accessToken) + if (!data) { + Vue.prototype.$baseMessage('验证失败,请重新登录...', 'error') + return false + } + let { permissions, username, avatar } = data + if (permissions && username && Array.isArray(permissions)) { + commit('setPermissions', permissions) + commit('setUsername', username) + commit('setAvatar', avatar) + return permissions + } else { + Vue.prototype.$baseMessage('用户信息接口异常', 'error') + return false + } + }, + async logout({ dispatch }) { + await logout(state.accessToken) + await dispatch('resetAccessToken') + await resetRouter() + }, + resetAccessToken({ commit }) { + commit('setPermissions', []) + commit('setAccessToken', '') + removeAccessToken() + }, +} +export default { state, getters, mutations, actions } diff --git a/src/styles/loading.scss b/src/styles/loading.scss new file mode 100644 index 0000000..4aceb61 --- /dev/null +++ b/src/styles/loading.scss @@ -0,0 +1,346 @@ +/** + * @author https://github.com/zxwk1998/vue-admin-better (不想保留author可删除) + * @description 全局加载动画 + */ + +@charset "utf-8"; + +@import './spinner/dots.css'; +@import './spinner/gauge.css'; +@import './spinner/inner-circles.css'; +@import './spinner/plus.css'; + +$base-loading: '.vab-loading-type'; + +/* 自定义loading开始 */ +#{$base-loading}1 { + display: flex; + width: 36px; + height: 36px; + margin: 0 auto 15px; + border: 3px solid transparent; + border-top-color: $base-color-blue; + border-bottom-color: $base-color-blue; + border-radius: 50%; + animation: vabLoading1-0 0.8s linear infinite; +} + +#{$base-loading}1::before { + display: block; + width: 8px; + height: 8px; + margin: auto; + content: ''; + border: 3px solid $base-color-blue; + border-radius: 50%; + animation: vabLoading1 0.5s alternate ease-in infinite; +} + +@keyframes vabLoading1-0 { + to { + transform: rotate(360deg); + } +} + +@keyframes vabLoading1 { + from { + transform: scale(0.5); + } + + to { + transform: scale(1.2); + } +} + +#{$base-loading}2 { + width: 20px; + height: 20px; + margin-top: -40px; + margin-left: -10px; + animation: vabLoading2 1s linear reverse infinite; +} + +#{$base-loading}2::before { + display: block; + width: 36px; + height: 36px; + margin-top: -17px; + margin-left: -18px; + content: ''; + animation: vabLoading2 0.4s linear infinite; +} + +#{$base-loading}2::after { + display: block; + width: 8px; + height: 8px; + margin-top: -3px; + margin-left: -4px; + content: ''; + animation: vabLoading2 0.4s linear infinite; +} + +#{$base-loading}2::before, +#{$base-loading}2, +#{$base-loading}2::after { + position: absolute; + top: 40%; + left: 50%; + border: 3px solid transparent; + border-top-color: $base-color-blue; + border-right-color: $base-color-blue; + border-radius: 50%; +} + +@keyframes vabLoading2 { + to { + transform: rotate(360deg); + } +} + +#{$base-loading}3 { + display: inline-block; + width: 2.5em; + height: 3em; + margin-bottom: 15px; + border: 3px solid transparent; + border-top-color: $base-color-blue; + border-bottom-color: $base-color-blue; + border-radius: 50%; + animation: vabLoading3 2s ease infinite; +} + +@keyframes vabLoading3 { + 50% { + border-width: 8px; + transform: rotate(360deg) scale(0.4, 0.33); + } + + 100% { + border-width: 3px; + transform: rotate(720deg) scale(1, 1); + } +} + +#{$base-loading}4 { + display: inline-block; + width: 30px; + height: 30px; + margin: 0 auto 10px; + border: 8px solid transparent; + border-bottom-color: $base-color-blue; + border-left-color: $base-color-blue; + border-radius: 50%; + animation: vabLoading4 1s linear infinite normal; +} + +#{$base-loading}4::after { + display: block; + width: 15px; + height: 15px; + margin: 0; + content: ' '; + border: 6px solid $base-color-blue; + border-bottom-color: transparent; + border-left-color: transparent; + border-radius: 50%; +} + +@keyframes vabLoading4 { + 0% { + opacity: 0.2; + transform: rotate(0deg); + } + + 50% { + opacity: 1; + transform: rotate(180deg); + } + + 100% { + opacity: 0.2; + transform: rotate(360deg); + } +} + +#{$base-loading}5 { + display: block; + width: 0; + height: 0; + margin: 0 auto 15px; + border: solid 1.5em $base-color-blue; + border-right: solid 1.5em transparent; + border-left: solid 1.5em transparent; + border-radius: 100%; + animation: vabLoading5 1s linear infinite; +} + +@keyframes vabLoading5 { + 0% { + transform: rotate(0deg); + } + + 50% { + transform: rotate(60deg); + } + + 100% { + transform: rotate(360deg); + } +} + +#{$base-loading}6 { + display: block; + width: 0; + height: 0; + margin: 0 auto 25px auto; + perspective: 200px; +} + +#{$base-loading}6::before, +#{$base-loading}6::after { + position: absolute; + width: 20px; + height: 20px; + content: ''; + background: rgba(0, 0, 0, 0); + animation: vabLoading6 0.5s infinite alternate; +} + +#{$base-loading}6::before { + left: 0; +} + +#{$base-loading}6::after { + right: 0; + animation-delay: 0.15s; +} + +@keyframes vabLoading6 { + 0% { + box-shadow: 0 0 0 rgba(0, 0, 0, 0); + transform: scale(1) translateY(0) rotateX(0deg); + } + + 100% { + background: $base-color-blue; + box-shadow: 0 25px 40px rgba($base-color-blue, 0.5); + transform: scale(1.2) translateY(-25px) rotateX(45deg); + } +} + +#{$base-loading}7 { + display: block; + width: 25px; + height: 25px; + margin: 0 auto 15px auto; + border: 2px solid $base-color-blue; + border-top-color: rgba($base-color-blue, 0.2); + border-right-color: rgba($base-color-blue, 0.2); + border-bottom-color: rgba($base-color-blue, 0.2); + border-radius: 100%; + animation: vabLoading7 infinite 0.75s linear; +} + +@keyframes vabLoading7 { + 0% { + transform: rotate(0); + } + + 100% { + transform: rotate(360deg); + } +} + +#{$base-loading}8 { + position: relative; + box-sizing: border-box; + display: block; + width: 20px; + height: 20px; + margin: 0 auto 15px auto; + background-color: $base-color-blue; + border-radius: 50%; + box-shadow: 30px 0 0 0 $base-color-blue; + transform: translateX(-15px); +} + +#{$base-loading}8::after { + position: absolute; + top: 8px; + left: 9px; + width: 10px; + height: 10px; + content: ''; + background-color: $base-color-white; + border-radius: 50%; + box-shadow: 30px 0 0 0 $base-color-white; + animation: vabLoading8 2s ease-in-out infinite alternate; +} + +@keyframes vabLoading8 { + 0% { + left: 9px; + } + + 100% { + left: 1px; + } +} + +#{$base-loading}9 { + position: relative; + box-sizing: border-box; + display: block; + width: 20px; + height: 20px; + margin: 0 auto 15px auto; + border: 1px $base-color-blue solid; + animation: vabLoading9 5s linear infinite; +} + +#{$base-loading}9::after { + position: absolute; + top: -8px; + left: 0; + width: 4px; + height: 4px; + content: ''; + background-color: $base-color-blue; + animation: vabLoading9_check 1s ease-in-out infinite; +} + +@keyframes vabLoading9_check { + 25% { + top: -8px; + left: 22px; + } + + 50% { + top: 22px; + left: 22px; + } + + 75% { + top: 22px; + left: -9px; + } + + 100% { + top: -7px; + left: -9px; + } +} + +@keyframes vabLoading9 { + 0% { + box-shadow: inset 0 0 0 0 rgba($base-color-blue, 0.5); + opacity: 0.5; + } + + 100% { + box-shadow: inset 0 -20px 0 0 $base-color-blue; + } +} + +/* 自定义loading结束 */ diff --git a/src/styles/normalize.scss b/src/styles/normalize.scss new file mode 100644 index 0000000..8112c9b --- /dev/null +++ b/src/styles/normalize.scss @@ -0,0 +1,353 @@ +@charset "utf-8"; + +/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */ + +/* Document + ========================================================================== */ + +/** + * 1. Correct the line height in all browsers. + * 2. Prevent adjustments of font size after orientation changes in iOS. + */ + +html { + line-height: 1.15; /* 1 */ + -webkit-text-size-adjust: 100%; /* 2 */ +} + +/* Sections + ========================================================================== */ + +/** + * Remove the margin in all browsers. + */ + +body { + margin: 0; +} + +/** + * Render the `main` element consistently in IE. + */ + +main { + display: block; +} + +/** + * Correct the font size and margin on `h1` elements within `section` and + * `article` contexts in Chrome, Firefox, and Safari. + */ + +h1 { + margin: 0.67em 0; + font-size: 2em; +} + +/* Grouping content + ========================================================================== */ + +/** + * 1. Add the correct box sizing in Firefox. + * 2. Show the overflow in Edge and IE. + */ + +hr { + box-sizing: content-box; /* 1 */ + height: 0; /* 1 */ + overflow: visible; /* 2 */ +} + +/** + * 1. Correct the inheritance and scaling of font size in all browsers. + * 2. Correct the odd `em` font sizing in all browsers. + */ + +pre { + font-family: monospace; /* 1 */ + font-size: 1em; /* 2 */ +} + +/* Text-level semantics + ========================================================================== */ + +/** + * Remove the gray background on active links in IE 10. + */ + +a { + background-color: transparent; +} + +/** + * 1. Remove the bottom border in Chrome 57- + * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari. + */ + +abbr[title] { + text-decoration: underline; /* 2 */ + text-decoration: underline dotted; /* 2 */ + border-bottom: none; /* 1 */ +} + +/** + * Add the correct font weight in Chrome, Edge, and Safari. + */ + +b, +strong { + font-weight: bolder; +} + +/** + * 1. Correct the inheritance and scaling of font size in all browsers. + * 2. Correct the odd `em` font sizing in all browsers. + */ + +code, +kbd, +samp { + font-family: monospace; /* 1 */ + font-size: 1em; /* 2 */ +} + +/** + * Add the correct font size in all browsers. + */ + +small { + font-size: 80%; +} + +/** + * Prevent `sub` and `sup` elements from affecting the line height in + * all browsers. + */ + +sub, +sup { + position: relative; + font-size: 75%; + line-height: 0; + vertical-align: baseline; +} + +sub { + bottom: -0.25em; +} + +sup { + top: -0.5em; +} + +/* Embedded content + ========================================================================== */ + +/** + * Remove the border on images inside links in IE 10. + */ + +img { + border-style: none; +} + +/* Forms + ========================================================================== */ + +/** + * 1. Change the font styles in all browsers. + * 2. Remove the margin in Firefox and Safari. + */ + +button, +input, +optgroup, +select, +textarea { + margin: 0; /* 2 */ + font-family: inherit; /* 1 */ + font-size: 100%; /* 1 */ + line-height: 1.15; /* 1 */ +} + +/** + * Show the overflow in IE. + * 1. Show the overflow in Edge. + */ + +button, +input { + /* 1 */ + overflow: visible; +} + +/** + * Remove the inheritance of text transform in Edge, Firefox, and IE. + * 1. Remove the inheritance of text transform in Firefox. + */ + +button, +select { + /* 1 */ + text-transform: none; +} + +/** + * Correct the inability to style clickable types in iOS and Safari. + */ + +button, +[type='button'], +[type='reset'], +[type='submit'] { + -webkit-appearance: button; +} + +/** + * Remove the inner border and padding in Firefox. + */ + +button::-moz-focus-inner, +[type='button']::-moz-focus-inner, +[type='reset']::-moz-focus-inner, +[type='submit']::-moz-focus-inner { + padding: 0; + border-style: none; +} + +/** + * Restore the focus styles unset by the previous rule. + */ + +button:-moz-focusring, +[type='button']:-moz-focusring, +[type='reset']:-moz-focusring, +[type='submit']:-moz-focusring { + outline: 1px dotted ButtonText; +} + +/** + * Correct the padding in Firefox. + */ + +fieldset { + padding: 0.35em 0.75em 0.625em; +} + +/** + * 1. Correct the text wrapping in Edge and IE. + * 2. Correct the color inheritance from `fieldset` elements in IE. + * 3. Remove the padding so developers are not caught out when they zero out + * `fieldset` elements in all browsers. + */ + +legend { + box-sizing: border-box; /* 1 */ + display: table; /* 1 */ + max-width: 100%; /* 1 */ + padding: 0; /* 3 */ + color: inherit; /* 2 */ + white-space: normal; /* 1 */ +} + +/** + * Add the correct vertical alignment in Chrome, Firefox, and Opera. + */ + +progress { + vertical-align: baseline; +} + +/** + * Remove the default vertical scrollbar in IE 10+. + */ + +textarea { + overflow: auto; +} + +/** + * 1. Add the correct box sizing in IE 10. + * 2. Remove the padding in IE 10. + */ + +[type='checkbox'], +[type='radio'] { + box-sizing: border-box; /* 1 */ + padding: 0; /* 2 */ +} + +/** + * Correct the cursor style of increment and decrement buttons in Chrome. + */ + +[type='number']::-webkit-inner-spin-button, +[type='number']::-webkit-outer-spin-button { + height: auto; +} + +/** + * 1. Correct the odd appearance in Chrome and Safari. + * 2. Correct the outline style in Safari. + */ + +[type='search'] { + -webkit-appearance: textfield; /* 1 */ + outline-offset: -2px; /* 2 */ +} + +/** + * Remove the inner padding in Chrome and Safari on macOS. + */ + +[type='search']::-webkit-search-decoration { + -webkit-appearance: none; +} + +/** + * 1. Correct the inability to style clickable types in iOS and Safari. + * 2. Change font properties to `inherit` in Safari. + */ + +::-webkit-file-upload-button { + -webkit-appearance: button; /* 1 */ + font: inherit; /* 2 */ +} + +/* Interactive + ========================================================================== */ + +/* + * Add the correct display in Edge, IE 10+, and Firefox. + */ + +details { + display: block; +} + +/* + * Add the correct display in all browsers. + */ + +summary { + display: list-item; +} + +/* Misc + ========================================================================== */ + +/** + * Add the correct display in IE 10+. + */ + +template { + display: none; +} + +/** + * Add the correct display in IE 10. + */ + +[hidden] { + display: none; +} diff --git a/src/styles/spinner/dots.css b/src/styles/spinner/dots.css new file mode 100644 index 0000000..f9e9de7 --- /dev/null +++ b/src/styles/spinner/dots.css @@ -0,0 +1,68 @@ +.dots-loader:not(:required) { + position: relative; + display: inline-block; + width: 7px; + height: 7px; + margin-bottom: 30px; + overflow: hidden; + text-indent: -9999px; + background: transparent; + border-radius: 100%; + box-shadow: #f86 -14px -14px 0 7px, #fc6 14px -14px 0 7px, #6d7 14px 14px 0 7px, #4ae -14px 14px 0 7px; + transform-origin: 50% 50%; + animation: dots-loader 5s infinite ease-in-out; +} + +@keyframes dots-loader { + 0% { + box-shadow: #f86 -14px -14px 0 7px, #fc6 14px -14px 0 7px, #6d7 14px 14px 0 7px, #4ae -14px 14px 0 7px; + } + + 8.33% { + box-shadow: #f86 14px -14px 0 7px, #fc6 14px -14px 0 7px, #6d7 14px 14px 0 7px, #4ae -14px 14px 0 7px; + } + + 16.67% { + box-shadow: #f86 14px 14px 0 7px, #fc6 14px 14px 0 7px, #6d7 14px 14px 0 7px, #4ae -14px 14px 0 7px; + } + + 25% { + box-shadow: #f86 -14px 14px 0 7px, #fc6 -14px 14px 0 7px, #6d7 -14px 14px 0 7px, #4ae -14px 14px 0 7px; + } + + 33.33% { + box-shadow: #f86 -14px -14px 0 7px, #fc6 -14px 14px 0 7px, #6d7 -14px -14px 0 7px, #4ae -14px -14px 0 7px; + } + + 41.67% { + box-shadow: #f86 14px -14px 0 7px, #fc6 -14px 14px 0 7px, #6d7 -14px -14px 0 7px, #4ae 14px -14px 0 7px; + } + + 50% { + box-shadow: #f86 14px 14px 0 7px, #fc6 -14px 14px 0 7px, #6d7 -14px -14px 0 7px, #4ae 14px -14px 0 7px; + } + + 58.33% { + box-shadow: #f86 -14px 14px 0 7px, #fc6 -14px 14px 0 7px, #6d7 -14px -14px 0 7px, #4ae 14px -14px 0 7px; + } + + 66.67% { + box-shadow: #f86 -14px -14px 0 7px, #fc6 -14px -14px 0 7px, #6d7 -14px -14px 0 7px, #4ae 14px -14px 0 7px; + } + + 75% { + box-shadow: #f86 14px -14px 0 7px, #fc6 14px -14px 0 7px, #6d7 14px -14px 0 7px, #4ae 14px -14px 0 7px; + } + + 83.33% { + box-shadow: #f86 14px 14px 0 7px, #fc6 14px -14px 0 7px, #6d7 14px 14px 0 7px, #4ae 14px 14px 0 7px; + } + + 91.67% { + box-shadow: #f86 -14px 14px 0 7px, #fc6 14px -14px 0 7px, #6d7 14px 14px 0 7px, #4ae -14px 14px 0 7px; + } + + 100% { + box-shadow: #f86 -14px -14px 0 7px, #fc6 14px -14px 0 7px, #6d7 14px 14px 0 7px, #4ae -14px 14px 0 7px; + } +} diff --git a/src/styles/spinner/gauge.css b/src/styles/spinner/gauge.css new file mode 100644 index 0000000..5457bf9 --- /dev/null +++ b/src/styles/spinner/gauge.css @@ -0,0 +1,104 @@ +.gauge-loader:not(:required) { + position: relative; + display: inline-block; + width: 64px; + height: 32px; + margin-bottom: 10px; + overflow: hidden; + text-indent: -9999px; + background: #6ca; + border-top-left-radius: 32px; + border-top-right-radius: 32px; +} + +.gauge-loader:not(:required)::before { + position: absolute; + top: 5px; + left: 30px; + width: 4px; + height: 27px; + content: ''; + background: white; + border-radius: 2px; + transform-origin: 50% 100%; + animation: gauge-loader 4000ms infinite ease; +} + +.gauge-loader:not(:required)::after { + position: absolute; + top: 26px; + left: 26px; + width: 13px; + height: 13px; + content: ''; + background: white; + -moz-border-radius: 8px; + -webkit-border-radius: 8px; + border-radius: 8px; +} + +@keyframes gauge-loader { + 0% { + transform: rotate(-50deg); + } + + 10% { + transform: rotate(20deg); + } + + 20% { + transform: rotate(60deg); + } + + 24% { + transform: rotate(60deg); + } + + 40% { + transform: rotate(-20deg); + } + + 54% { + transform: rotate(70deg); + } + + 56% { + transform: rotate(78deg); + } + + 58% { + transform: rotate(73deg); + } + + 60% { + transform: rotate(75deg); + } + + 62% { + transform: rotate(70deg); + } + + 70% { + transform: rotate(-20deg); + } + + 80% { + transform: rotate(20deg); + } + + 83% { + transform: rotate(25deg); + } + + 86% { + transform: rotate(20deg); + } + + 89% { + transform: rotate(25deg); + } + + 100% { + transform: rotate(-50deg); + } +} diff --git a/src/styles/spinner/inner-circles.css b/src/styles/spinner/inner-circles.css new file mode 100644 index 0000000..a7955f5 --- /dev/null +++ b/src/styles/spinner/inner-circles.css @@ -0,0 +1,51 @@ +.inner-circles-loader:not(:required) { + position: relative; + display: inline-block; + width: 50px; + height: 50px; + margin-bottom: 10px; + overflow: hidden; + text-indent: -9999px; + background: rgba(25, 165, 152, 0.5); + border-radius: 50%; + transform: translate3d(0, 0, 0); +} + +.inner-circles-loader:not(:required)::before, +.inner-circles-loader:not(:required)::after { + position: absolute; + top: 0; + display: inline-block; + width: 50px; + height: 50px; + content: ''; + border-radius: 50%; +} + +.inner-circles-loader:not(:required)::before { + left: 0; + background: #c7efcf; + transform-origin: 0 50%; + animation: inner-circles-loader 3s infinite; +} + +.inner-circles-loader:not(:required)::after { + right: 0; + background: #eef5db; + transform-origin: 100% 50%; + animation: inner-circles-loader 3s 0.2s reverse infinite; +} + +@keyframes inner-circles-loader { + 0% { + transform: rotate(0deg); + } + + 50% { + transform: rotate(360deg); + } + + 100% { + transform: rotate(0deg); + } +} diff --git a/src/styles/spinner/plus.css b/src/styles/spinner/plus.css new file mode 100644 index 0000000..2659c9c --- /dev/null +++ b/src/styles/spinner/plus.css @@ -0,0 +1,341 @@ +.plus-loader:not(:required) { + position: relative; + display: inline-block; + width: 48px; + height: 48px; + margin-bottom: 10px; + overflow: hidden; + text-indent: -9999px; + background: #f86; + -moz-border-radius: 24px; + -webkit-border-radius: 24px; + border-radius: 24px; + -moz-transform: rotateZ(90deg); + -ms-transform: rotateZ(90deg); + -webkit-transform: rotateZ(90deg); + transform: rotateZ(90deg); + -moz-transform-origin: 50% 50%; + -ms-transform-origin: 50% 50%; + -webkit-transform-origin: 50% 50%; + transform-origin: 50% 50%; + -moz-animation: plus-loader-background 3s infinite ease-in-out; + -webkit-animation: plus-loader-background 3s infinite ease-in-out; + animation: plus-loader-background 3s infinite ease-in-out; +} + +.plus-loader:not(:required)::after { + position: absolute; + top: 0; + right: 50%; + width: 50%; + height: 100%; + content: ''; + background: #f86; + -moz-border-radius: 24px 0 0 24px; + -webkit-border-radius: 24px; + border-radius: 24px 0 0 24px; + -moz-transform-origin: 100% 50%; + -ms-transform-origin: 100% 50%; + -webkit-transform-origin: 100% 50%; + transform-origin: 100% 50%; + -moz-animation: plus-loader-top 3s infinite linear; + -webkit-animation: plus-loader-top 3s infinite linear; + animation: plus-loader-top 3s infinite linear; +} + +.plus-loader:not(:required)::before { + position: absolute; + top: 0; + right: 50%; + width: 50%; + height: 100%; + content: ''; + background: #fc6; + -moz-border-radius: 24px 0 0 24px; + -webkit-border-radius: 24px; + border-radius: 24px 0 0 24px; + -moz-transform-origin: 100% 50%; + -ms-transform-origin: 100% 50%; + -webkit-transform-origin: 100% 50%; + transform-origin: 100% 50%; + -moz-animation: plus-loader-bottom 3s infinite linear; + -webkit-animation: plus-loader-bottom 3s infinite linear; + animation: plus-loader-bottom 3s infinite linear; +} + +@keyframes plus-loader-top { + 2.5% { + background: #f86; + -moz-transform: rotateY(0deg); + -ms-transform: rotateY(0deg); + -webkit-transform: rotateY(0deg); + transform: rotateY(0deg); + -moz-animation-timing-function: ease-in; + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in; + } + + 13.75% { + background: #ff430d; + -moz-transform: rotateY(90deg); + -ms-transform: rotateY(90deg); + -webkit-transform: rotateY(90deg); + transform: rotateY(90deg); + -moz-animation-timing-function: step-start; + -webkit-animation-timing-function: step-start; + animation-timing-function: step-start; + } + + 13.76% { + background: #ffae0d; + -moz-transform: rotateY(90deg); + -ms-transform: rotateY(90deg); + -webkit-transform: rotateY(90deg); + transform: rotateY(90deg); + -moz-animation-timing-function: ease-out; + -webkit-animation-timing-function: ease-out; + animation-timing-function: ease-out; + } + + 25% { + background: #fc6; + -moz-transform: rotateY(180deg); + -ms-transform: rotateY(180deg); + -webkit-transform: rotateY(180deg); + transform: rotateY(180deg); + } + + 27.5% { + background: #fc6; + -moz-transform: rotateY(180deg); + -ms-transform: rotateY(180deg); + -webkit-transform: rotateY(180deg); + transform: rotateY(180deg); + -moz-animation-timing-function: ease-in; + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in; + } + + 41.25% { + background: #ffae0d; + -moz-transform: rotateY(90deg); + -ms-transform: rotateY(90deg); + -webkit-transform: rotateY(90deg); + transform: rotateY(90deg); + -moz-animation-timing-function: step-start; + -webkit-animation-timing-function: step-start; + animation-timing-function: step-start; + } + + 41.26% { + background: #2cc642; + -moz-transform: rotateY(90deg); + -ms-transform: rotateY(90deg); + -webkit-transform: rotateY(90deg); + transform: rotateY(90deg); + -moz-animation-timing-function: ease-out; + -webkit-animation-timing-function: ease-out; + animation-timing-function: ease-out; + } + + 50% { + background: #6d7; + -moz-transform: rotateY(0deg); + -ms-transform: rotateY(0deg); + -webkit-transform: rotateY(0deg); + transform: rotateY(0deg); + } + + 52.5% { + background: #6d7; + -moz-transform: rotateY(0deg); + -ms-transform: rotateY(0deg); + -webkit-transform: rotateY(0deg); + transform: rotateY(0deg); + -moz-animation-timing-function: ease-in; + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in; + } + + 63.75% { + background: #2cc642; + -moz-transform: rotateY(90deg); + -ms-transform: rotateY(90deg); + -webkit-transform: rotateY(90deg); + transform: rotateY(90deg); + -moz-animation-timing-function: step-start; + -webkit-animation-timing-function: step-start; + animation-timing-function: step-start; + } + + 63.76% { + background: #1386d2; + -moz-transform: rotateY(90deg); + -ms-transform: rotateY(90deg); + -webkit-transform: rotateY(90deg); + transform: rotateY(90deg); + -moz-animation-timing-function: ease-out; + -webkit-animation-timing-function: ease-out; + animation-timing-function: ease-out; + } + + 75% { + background: #4ae; + -moz-transform: rotateY(180deg); + -ms-transform: rotateY(180deg); + -webkit-transform: rotateY(180deg); + transform: rotateY(180deg); + } + + 77.5% { + background: #4ae; + -moz-transform: rotateY(180deg); + -ms-transform: rotateY(180deg); + -webkit-transform: rotateY(180deg); + transform: rotateY(180deg); + -moz-animation-timing-function: ease-in; + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in; + } + + 91.25% { + background: #1386d2; + -moz-transform: rotateY(90deg); + -ms-transform: rotateY(90deg); + -webkit-transform: rotateY(90deg); + transform: rotateY(90deg); + -moz-animation-timing-function: step-start; + -webkit-animation-timing-function: step-start; + animation-timing-function: step-start; + } + + 91.26% { + background: #ff430d; + -moz-transform: rotateY(90deg); + -ms-transform: rotateY(90deg); + -webkit-transform: rotateY(90deg); + transform: rotateY(90deg); + -moz-animation-timing-function: ease-in; + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in; + } + + 100% { + background: #f86; + -moz-transform: rotateY(0deg); + -ms-transform: rotateY(0deg); + -webkit-transform: rotateY(0deg); + transform: rotateY(0deg); + -moz-animation-timing-function: step-start; + -webkit-animation-timing-function: step-start; + animation-timing-function: step-start; + } +} + +@keyframes plus-loader-bottom { + 0% { + background: #fc6; + -moz-animation-timing-function: step-start; + -webkit-animation-timing-function: step-start; + animation-timing-function: step-start; + } + + 50% { + background: #fc6; + -moz-animation-timing-function: step-start; + -webkit-animation-timing-function: step-start; + animation-timing-function: step-start; + } + + 75% { + background: #4ae; + -moz-animation-timing-function: step-start; + -webkit-animation-timing-function: step-start; + animation-timing-function: step-start; + } + + 100% { + background: #4ae; + -moz-animation-timing-function: step-start; + -webkit-animation-timing-function: step-start; + animation-timing-function: step-start; + } +} + +@keyframes plus-loader-background { + 0% { + background: #f86; + -moz-transform: rotateZ(180deg); + -ms-transform: rotateZ(180deg); + -webkit-transform: rotateZ(180deg); + transform: rotateZ(180deg); + } + + 25% { + background: #f86; + -moz-transform: rotateZ(180deg); + -ms-transform: rotateZ(180deg); + -webkit-transform: rotateZ(180deg); + transform: rotateZ(180deg); + -moz-animation-timing-function: step-start; + -webkit-animation-timing-function: step-start; + animation-timing-function: step-start; + } + + 27.5% { + background: #6d7; + -moz-transform: rotateZ(90deg); + -ms-transform: rotateZ(90deg); + -webkit-transform: rotateZ(90deg); + transform: rotateZ(90deg); + } + + 50% { + background: #6d7; + -moz-transform: rotateZ(90deg); + -ms-transform: rotateZ(90deg); + -webkit-transform: rotateZ(90deg); + transform: rotateZ(90deg); + -moz-animation-timing-function: step-start; + -webkit-animation-timing-function: step-start; + animation-timing-function: step-start; + } + + 52.5% { + background: #6d7; + -moz-transform: rotateZ(0deg); + -ms-transform: rotateZ(0deg); + -webkit-transform: rotateZ(0deg); + transform: rotateZ(0deg); + } + + 75% { + background: #6d7; + -moz-transform: rotateZ(0deg); + -ms-transform: rotateZ(0deg); + -webkit-transform: rotateZ(0deg); + transform: rotateZ(0deg); + -moz-animation-timing-function: step-start; + -webkit-animation-timing-function: step-start; + animation-timing-function: step-start; + } + + 77.5% { + background: #f86; + -moz-transform: rotateZ(270deg); + -ms-transform: rotateZ(270deg); + -webkit-transform: rotateZ(270deg); + transform: rotateZ(270deg); + } + + 100% { + background: #f86; + -moz-transform: rotateZ(270deg); + -ms-transform: rotateZ(270deg); + -webkit-transform: rotateZ(270deg); + transform: rotateZ(270deg); + -moz-animation-timing-function: step-start; + -webkit-animation-timing-function: step-start; + animation-timing-function: step-start; + } +} diff --git a/src/styles/themes/default.scss b/src/styles/themes/default.scss new file mode 100644 index 0000000..7061af3 --- /dev/null +++ b/src/styles/themes/default.scss @@ -0,0 +1 @@ +/* 绿荫草场主题、荣耀典藏主题、暗黑之子主题加QQ讨论群972435319、1139183756后私聊群主获取,获取后将主题放到themes文件夹根目录即可 */ diff --git a/src/styles/transition.scss b/src/styles/transition.scss new file mode 100644 index 0000000..ea742ce --- /dev/null +++ b/src/styles/transition.scss @@ -0,0 +1,19 @@ +/** + * @author https://github.com/zxwk1998/vue-admin-better (不想保留author可删除) + * @description vue过渡动画 + */ + +@charset "utf-8"; + +.fade-transform-leave-active, +.fade-transform-enter-active { + transition: $base-transition; +} + +.fade-transform-enter { + opacity: 0; +} + +.fade-transform-leave-to { + opacity: 0; +} diff --git a/src/styles/vab.scss b/src/styles/vab.scss new file mode 100644 index 0000000..784266e --- /dev/null +++ b/src/styles/vab.scss @@ -0,0 +1,532 @@ +/** + * @author https://github.com/zxwk1998/vue-admin-better (不想保留author可删除) + * @description 全局样式 + */ + +@charset "utf-8"; + +@import './normalize.scss'; +@import './transition.scss'; +@import './loading.scss'; +@import 'element-ui/lib/theme-chalk/display.css'; + +@mixin scrollbar { + max-height: 88vh; + margin-bottom: 0.5vh; + overflow-y: auto; + + &::-webkit-scrollbar { + width: 0; + height: 0; + background: transparent; + } + + &::-webkit-scrollbar-thumb { + background-color: rgba(144, 147, 153, 0.3); + border-radius: 10px; + } + + &::-webkit-scrollbar-thumb:hover { + background-color: rgba(144, 147, 153, 0.3); + } +} + +@mixin base-scrollbar { + &::-webkit-scrollbar { + width: 13px; + height: 13px; + } + + &::-webkit-scrollbar-thumb { + background-color: rgba(0, 0, 0, 0.4); + background-clip: padding-box; + border: 3px solid transparent; + border-radius: 7px; + } + + &::-webkit-scrollbar-thumb:hover { + background-color: rgba(0, 0, 0, 0.5); + } + + &::-webkit-scrollbar-track { + background-color: rgba(0, 0, 0, 0.05); + border-radius: 4px; + } + + &::-webkit-scrollbar-track:hover { + background-color: rgba(0, 0, 0, 0.08); + } +} + +img { + object-fit: cover; + border-radius: 6px; +} + +a { + color: $base-color-blue; + text-decoration: none; + cursor: pointer; + transition: color 0.3s ease; + + &:hover { + color: darken($base-color-blue, 10%); + } +} + +* { + transition: $base-transition; +} + +svg { + transition: none; + + * { + transition: none; + } +} + +html { + body { + position: relative; + height: 100vh; + padding: 0; + margin: 0; + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; + font-size: $base-font-size-default; + color: #2c3e50; + background: #f0f2f5; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + + @include base-scrollbar; + + div { + @include base-scrollbar; + } + + svg, + i { + &:hover { + opacity: 0.8; + } + } + + .v-modal { + backdrop-filter: blur(10px); + } + + .el-tag + .el-tag { + margin-left: 10px; + } + + .editor-toolbar { + .no-mobile, + .fa-question-circle { + display: none; + } + } + + .el-divider--horizontal { + margin: 15px 0 25px 0; + + .el-divider__text { + display: -webkit-box; + overflow: hidden; + text-overflow: ellipsis; + -webkit-line-clamp: 1; + -webkit-box-orient: vertical; + } + } + + .el-image-viewer { + &__close { + .el-icon-circle-close { + color: $base-color-white; + } + } + } + + .vue-admin-better-wrapper { + .app-main-container { + @include base-scrollbar; + + > [class*='-container'] { + * { + transition: none; + } + + padding: $base-padding; + background: $base-color-white; + border-radius: 12px; + box-shadow: 0 1px 6px rgba(0, 0, 0, 0.06); + border: 1px solid rgba(0, 0, 0, 0.02); + } + } + } + + /* 进度条开始 */ + #nprogress { + position: fixed; + z-index: $base-z-index; + + .bar { + background: linear-gradient(90deg, $base-color-blue, lighten($base-color-blue, 20%)) !important; + height: 3px !important; + } + + .peg { + box-shadow: 0 0 14px $base-color-blue, 0 0 8px $base-color-blue !important; + } + } + + .el-table { + .el-table__body-wrapper { + @include base-scrollbar; + } + + th { + background: #f8fafc; + } + + td, + th { + position: relative; + box-sizing: border-box; + padding: 10px 0; + + .cell { + font-size: $base-font-size-default; + font-weight: normal; + color: #555; + + .el-image { + width: 50px; + height: 50px; + border-radius: 8px; + } + } + } + + &::before { + height: 0; + } + + .el-table__fixed-right { + height: 100% !important; + box-shadow: -2px 0 8px rgba(0, 0, 0, 0.08); + } + + .el-table__fixed { + height: 100% !important; + box-shadow: 2px 0 8px rgba(0, 0, 0, 0.08); + } + } + + .el-pagination { + padding: 2px 5px; + margin: 20px 0 0 0; + font-weight: normal; + color: $base-color-black; + text-align: center; + } + + .el-menu.el-menu--popup.el-menu--popup-right-start { + @include scrollbar; + border-radius: 6px; + border: none; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); + } + + .el-menu.el-menu--popup.el-menu--popup-bottom-start { + @include scrollbar; + border-radius: 6px; + border: none; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); + } + + .el-submenu__title i { + color: $base-color-white; + } + + .el-dialog, + .el-message-box { + border-radius: 10px; + box-shadow: 0 10px 30px rgba(0, 0, 0, 0.15); + + &__body { + border-top: 1px solid $base-border-color; + + .el-form { + padding-right: 30px; + } + } + + &__footer { + padding: $base-padding; + text-align: right; + border-top: 1px solid $base-border-color; + } + + &__content { + padding: 20px 20px 20px 20px; + } + } + + .el-card { + margin-bottom: 16px; + border-radius: 12px; + border: none; + box-shadow: 0 2px 10px rgba(0, 0, 0, 0.06); + transition: all 0.3s ease; + + &:hover { + box-shadow: 0 4px 16px rgba(0, 0, 0, 0.09); + transform: translateY(-2px); + } + + &__body { + padding: $base-padding; + } + } + + /* VabPageHeader 全局样式 - 高优先级 */ + .page-header { + background: linear-gradient(135deg, #518df1 0%, #667eea 100%) !important; + border-radius: 16px !important; + padding: 32px !important; + margin-bottom: 24px !important; + color: white !important; + box-shadow: 0 8px 32px rgba(102, 126, 234, 0.3) !important; + border: none !important; + position: relative; + overflow: hidden; + + &::before { + content: ''; + position: absolute; + top: -50%; + right: -50%; + bottom: -50%; + left: -50%; + background: linear-gradient(to bottom, rgba(255, 255, 255, 0.1) 0%, rgba(255, 255, 255, 0.05) 100%); + transform: rotate(30deg); + } + + .header-content { + position: relative; + display: flex !important; + justify-content: space-between !important; + align-items: center !important; + + .header-left { + .page-title { + font-size: 2.2rem !important; + font-weight: 700 !important; + margin: 0 0 10px 0 !important; + display: flex !important; + align-items: center !important; + gap: 14px !important; + color: white !important; + + .vab-icon { + font-size: 2rem !important; + color: white !important; + background: rgba(255, 255, 255, 0.2); + border-radius: 12px; + padding: 8px; + } + } + + .page-description { + font-size: 1.1rem !important; + opacity: 0.95 !important; + margin: 0 !important; + color: white !important; + font-weight: 300; + } + } + + .header-right { + display: flex !important; + align-items: center !important; + gap: 10px !important; + font-size: 1.2rem !important; + font-weight: 500 !important; + color: white !important; + background: rgba(255, 255, 255, 0.2); + padding: 12px 20px; + border-radius: 12px; + backdrop-filter: blur(10px); + + .vab-icon { + font-size: 1.4rem !important; + color: white !important; + } + } + } + } + + /* 响应式设计 */ + @media (max-width: 768px) { + .page-header { + padding: 22px !important; + border-radius: 12px !important; + + .header-content { + flex-direction: column !important; + gap: 18px !important; + text-align: center !important; + + .header-left { + .page-title { + font-size: 1.7rem !important; + } + } + + .header-right { + width: 100%; + justify-content: center; + } + } + } + } + + .select-tree-popper { + .el-scrollbar { + .el-scrollbar__view { + .el-select-dropdown__item { + height: auto; + max-height: 274px; + padding: 0; + overflow-y: auto; + line-height: 26px; + } + } + } + } + + /* 扩展 el-divider 样式 */ + .el-divider { + position: relative; + border: none; + background: linear-gradient(90deg, transparent, #e4e7ed, transparent); + + &--horizontal { + height: 1px; + margin: 24px 0 32px 0; + + .el-divider__text { + position: relative; + padding: 0 18px; + font-size: 14px; + font-weight: 500; + color: #606266; + background: #fff; + border-radius: 6px; + + &::before { + content: ''; + position: absolute; + top: 50%; + left: -8px; + width: 4px; + height: 4px; + margin-top: -2px; + background: #409eff; + border-radius: 50%; + } + } + } + + &--vertical { + width: 1px; + height: 1em; + margin: 0 16px; + background: #e4e7ed; + } + + /* 主题变体 */ + &--primary { + background: linear-gradient(90deg, transparent, #409eff, transparent); + + .el-divider__text { + color: #409eff; + + &::before { + background: #409eff; + } + } + } + + &--success { + background: linear-gradient(90deg, transparent, #67c23a, transparent); + + .el-divider__text { + color: #67c23a; + + &::before { + background: #67c23a; + } + } + } + + &--warning { + background: linear-gradient(90deg, transparent, #e6a23c, transparent); + + .el-divider__text { + color: #e6a23c; + + &::before { + background: #e6a23c; + } + } + } + + &--danger { + background: linear-gradient(90deg, transparent, #f56c6c, transparent); + + .el-divider__text { + color: #f56c6c; + + &::before { + background: #f56c6c; + } + } + } + + /* 虚线样式 */ + &--dashed { + background: none; + border-top: 1px dashed #e4e7ed; + + .el-divider__text { + background: #fff; + } + } + + /* 粗线样式 */ + &--thick { + height: 2px; + background: linear-gradient(90deg, transparent, #409eff, transparent); + } + } + } + + .side-container { + .el-menu-item, + .el-submenu { + margin: 7px !important; + border-radius: 5px !important; + transition: all 0.3s ease; + + &:hover { + border-radius: 5px !important; + } + + &.is-active { + background: linear-gradient(90deg, $base-color-default, lighten($base-color-default, 10%)) !important; + } + } + } +} diff --git a/src/styles/variables.scss b/src/styles/variables.scss new file mode 100644 index 0000000..e32034c --- /dev/null +++ b/src/styles/variables.scss @@ -0,0 +1,70 @@ +/** + * @author https://github.com/zxwk1998/vue-admin-better (不想保留author可删除) + * @description 全局主题变量配置 + */ +/* stylelint-disable */ +@charset "utf-8"; +//框架默认主题色 +$base-color-default: #4d8af0; +//默认层级 +$base-z-index: 1000; +//横向布局纵向布局时菜单背景色 +$base-menu-background: #191a23; +//菜单文字颜色 +$base-menu-color: hsla(0, 0%, 100%, 0.95); +//菜单选中文字颜色 +$base-menu-color-active: hsla(0, 0%, 100%, 0.95); +//菜单选中背景色 +$base-menu-background-active: $base-color-default; +//标题颜色 +$base-title-color: #fff; +//字体大小配置 +$base-font-size-small: 12px; +$base-font-size-default: 14px; +$base-font-size-big: 16px; +$base-font-size-bigger: 18px; +$base-font-size-max: 22px; +$base-font-color: #606266; +$base-color-blue: $base-color-default; +$base-color-green: #52c41a; +$base-color-white: #fff; +$base-color-black: #000; +$base-color-yellow: #faad14; +$base-color-orange: #fa8c16; +$base-color-red: #f5222d; +$base-color-gray: rgba(0, 0, 0, 0.65); +$base-main-width: 1279px; +$base-border-radius: 6px; +$base-border-color: #ebeef5; +//输入框高度 +$base-input-height: 36px; +//默认paddiing +$base-padding: 22px; +//默认阴影 +$base-box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1); +//横向布局时top-bar、logo、一级菜单的高度 +$base-top-bar-height: 64px; +//纵向布局时logo的高度 +$base-logo-height: 70px; +//顶部nav-bar的高度 +$base-nav-bar-height: 60px; +//顶部多标签页tabs-bar的高度 +$base-tabs-bar-height: 50px; +//顶部多标签页tabs-bar中每一个item的高度 +$base-tag-item-height: 32px; +//菜单li标签的高度 +$base-menu-item-height: 50px; +//app-main的高度 +$base-app-main-height: calc(100vh - #{$base-nav-bar-height} - #{$base-tabs-bar-height} - #{$base-padding} - #{$base-padding} - 55px - 55px); +//纵向布局时左侧导航未折叠时的宽度 +$base-left-menu-width: 240px; +//纵向布局时左侧导航未折叠时右侧内容的宽度 +$base-right-content-width: calc(100% - #{$base-left-menu-width}); +//纵向布局时左侧导航已折叠时的宽度 +$base-left-menu-width-min: 64px; +//纵向布局时左侧导航已折叠时右侧内容的宽度 +$base-right-content-width-min: calc(100% - #{$base-left-menu-width-min}); +//默认动画 +$base-transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1), border 0s, background 0s, color 0s, font-size 0s; +//默认动画长 +$base-transition-time: 0.3s; \ No newline at end of file diff --git a/src/utils/accessToken.js b/src/utils/accessToken.js new file mode 100644 index 0000000..548ebb6 --- /dev/null +++ b/src/utils/accessToken.js @@ -0,0 +1,59 @@ +import { storage, tokenTableName } from '@/config' + +/** + * @author https://github.com/zxwk1998/vue-admin-better (不想保留author可删除) + * @description 获取accessToken + * @returns {string|ActiveX.IXMLDOMNode|Promise|any|IDBRequest|MediaKeyStatus|FormDataEntryValue|Function|Promise} + */ +export function getAccessToken() { + if (storage) { + if ('localStorage' === storage) { + return localStorage.getItem(tokenTableName) + } else if ('sessionStorage' === storage) { + return sessionStorage.getItem(tokenTableName) + } else { + return localStorage.getItem(tokenTableName) + } + } else { + return localStorage.getItem(tokenTableName) + } +} + +/** + * @author https://github.com/zxwk1998/vue-admin-better (不想保留author可删除) + * @description 存储accessToken + * @param accessToken + * @returns {void|*} + */ +export function setAccessToken(accessToken) { + if (storage) { + if ('localStorage' === storage) { + return localStorage.setItem(tokenTableName, accessToken) + } else if ('sessionStorage' === storage) { + return sessionStorage.setItem(tokenTableName, accessToken) + } else { + return localStorage.setItem(tokenTableName, accessToken) + } + } else { + return localStorage.setItem(tokenTableName, accessToken) + } +} + +/** + * @author https://github.com/zxwk1998/vue-admin-better (不想保留author可删除) + * @description 移除accessToken + * @returns {void|Promise} + */ +export function removeAccessToken() { + if (storage) { + if ('localStorage' === storage) { + return localStorage.removeItem(tokenTableName) + } else if ('sessionStorage' === storage) { + return sessionStorage.clear() + } else { + return localStorage.removeItem(tokenTableName) + } + } else { + return localStorage.removeItem(tokenTableName) + } +} diff --git a/src/utils/clipboard.js b/src/utils/clipboard.js new file mode 100644 index 0000000..4c86324 --- /dev/null +++ b/src/utils/clipboard.js @@ -0,0 +1,31 @@ +import Vue from 'vue' +import Clipboard from 'clipboard' + +function clipboardSuccess() { + Vue.prototype.$baseMessage('复制成功', 'success') +} + +function clipboardError() { + Vue.prototype.$baseMessage('复制失败', 'error') +} + +/** + * @author https://github.com/zxwk1998/vue-admin-better (不想保留author可删除) + * @description 复制数据 + * @param text + * @param event + */ +export default function handleClipboard(text, event) { + const clipboard = new Clipboard(event.target, { + text: () => text, + }) + clipboard.on('success', () => { + clipboardSuccess() + clipboard.destroy() + }) + clipboard.on('error', () => { + clipboardError() + clipboard.destroy() + }) + clipboard.onClick(event) +} diff --git a/src/utils/encrypt.js b/src/utils/encrypt.js new file mode 100644 index 0000000..7e61b1e --- /dev/null +++ b/src/utils/encrypt.js @@ -0,0 +1,42 @@ +import JSEncrypt from 'jsencrypt' +import { getPublicKey } from '@/api/publicKey' + +const privateKey = + 'MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAMFPa+v52FkSUXvcUnrGI/XzW3EpZRI0s9BCWJ3oNQmEYA5luWW5p8h0uadTIoTyYweFPdH4hveyxlwmS7oefvbIdiP+o+QIYW/R4Wjsb4Yl8MhR4PJqUE3RCy6IT9fM8ckG4kN9ECs6Ja8fQFc6/mSl5dJczzJO3k1rWMBhKJD/AgMBAAECgYEAucMakH9dWeryhrYoRHcXo4giPVJsH9ypVt4KzmOQY/7jV7KFQK3x//27UoHfUCak51sxFw9ek7UmTPM4HjikA9LkYeE7S381b4QRvFuf3L6IbMP3ywJnJ8pPr2l5SqQ00W+oKv+w/VmEsyUHr+k4Z+4ik+FheTkVWp566WbqFsECQQDjYaMcaKw3j2Zecl8T6eUe7fdaRMIzp/gcpPMfT/9rDzIQk+7ORvm1NI9AUmFv/FAlfpuAMrdL2n7p9uznWb7RAkEA2aP934kbXg5bdV0R313MrL+7WTK/qdcYxATUbMsMuWWQBoS5irrt80WCZbG48hpocJavLNjbtrjmUX3CuJBmzwJAOJg8uP10n/+ZQzjEYXh+BszEHDuw+pp8LuT/fnOy5zrJA0dO0RjpXijO3vuiNPVgHXT9z1LQPJkNrb5ACPVVgQJBALPeb4uV0bNrJDUb5RB4ghZnIxv18CcaqNIft7vuGCcFBAIPIRTBprR+RuVq+xHDt3sNXdsvom4h49+Hky1b0ksCQBBwUtVaqH6ztCtwUF1j2c/Zcrt5P/uN7IHAd44K0gIJc1+Csr3qPG+G2yoqRM8KVqLI8Z2ZYn9c+AvEE+L9OQY=' + +/** + * @author https://github.com/zxwk1998/vue-admin-better (不想保留author可删除) + * @description RSA加密 + * @param data + * @returns {Promise<{param: PromiseLike}|*>} + */ +export async function encryptedData(data) { + let publicKey = '' + const res = await getPublicKey() + publicKey = res.data.publicKey + if (res.data.mockServer) { + publicKey = '' + } + if (publicKey == '') { + return data + } + const encrypt = new JSEncrypt() + encrypt.setPublicKey(`-----BEGIN PUBLIC KEY-----${publicKey}-----END PUBLIC KEY-----`) + data = encrypt.encrypt(JSON.stringify(data)) + return { + param: data, + } +} + +/** + * @author https://github.com/zxwk1998/vue-admin-better (不想保留author可删除) + * @description RSA解密 + * @param data + * @returns {PromiseLike} + */ +export function decryptedData(data) { + const decrypt = new JSEncrypt() + decrypt.setPrivateKey(`-----BEGIN RSA PRIVATE KEY-----${privateKey}-----END RSA PRIVATE KEY-----`) + data = decrypt.decrypt(JSON.stringify(data)) + return data +} diff --git a/src/utils/errorLog.js b/src/utils/errorLog.js new file mode 100644 index 0000000..751a6fd --- /dev/null +++ b/src/utils/errorLog.js @@ -0,0 +1,52 @@ +import Vue from 'vue' +import store from '@/store' +import { isArray, isString } from '@/utils/validate' +import { errorLog } from '@/config' + +const needErrorLog = errorLog +const checkNeed = () => { + const env = process.env.NODE_ENV + if (isString(needErrorLog)) { + return env === needErrorLog + } + if (isArray(needErrorLog)) { + return needErrorLog.includes(env) + } + return false +} + +// 检查是否是Chrome扩展相关错误 +const isChromeExtensionError = (err) => { + if (!err) return false + + // 错误消息是字符串 + if (typeof err.message === 'string') { + return ( + err.message.includes('runtime.lastError') || + err.message.includes('message port closed') || + err.message.includes('The message port closed') + ) + } + + // 错误本身是字符串 + if (typeof err === 'string') { + return err.includes('runtime.lastError') || err.includes('message port closed') || err.includes('The message port closed') + } + + return false +} + +if (checkNeed()) { + Vue.config.errorHandler = (err, vm, info) => { + // 过滤Chrome扩展相关错误 + if (isChromeExtensionError(err)) { + return + } + + console.error('vue-admin-better错误拦截:', err, vm, info) + const url = window.location.href + Vue.nextTick(() => { + store.dispatch('errorLog/addErrorLog', { err, vm, info, url }) + }) + } +} diff --git a/src/utils/handleRoutes.js b/src/utils/handleRoutes.js new file mode 100644 index 0000000..3c37560 --- /dev/null +++ b/src/utils/handleRoutes.js @@ -0,0 +1,110 @@ +/** + * @author https://github.com/zxwk1998/vue-admin-better (不想保留author可删除) + * @description all模式渲染后端返回路由 + * @param constantRoutes + * @returns {*} + */ + +// import { pcaData } from "@/utils/rouList"; + +// console.log(pcaData,'--=') + + +export function convertRouter(asyncRoutes) { + console.log(asyncRoutes,'--=11?') + // 处理空值情况 + if (!asyncRoutes || !Array.isArray(asyncRoutes)) { + console.warn('后端返回的路由格式不正确或为空') + return [] + } + + return asyncRoutes + .map((route) => { + if (!route) return null + + if (route.component) { + if (route.component === 'Layout') { + route.component = () => import('@/layouts') + } else if (route.component === 'EmptyLayout') { + route.component = () => import('@/layouts/EmptyLayout') + } else { + try { + const index = route.component.indexOf('views') + const path = index > 0 ? route.component.slice(index) : `views/${route.component}` + route.component = () => + import(`@/${path}`).catch((err) => { + console.error(`路由组件加载失败: @/${path}`, err) + return import('@/views/404') + }) + } catch (err) { + console.error(`路由组件解析失败: ${route.component}`, err) + route.component = () => import('@/views/404') + } + } + } + + if (route.children) { + if (Array.isArray(route.children) && route.children.length) { + route.children = convertRouter(route.children) + // 过滤掉空路由 + route.children = route.children.filter((child) => child !== null) + } + if (!route.children || route.children.length === 0) delete route.children + } + + return route + }) + .filter((route) => route !== null) // 过滤掉无效路由 +} + +/** + * @author https://github.com/zxwk1998/vue-admin-better (不想保留author可删除) + * @description 判断当前路由是否包含权限 + * @param permissions + * @param route + * @returns {boolean|*} + */ +function hasPermission(permissions, route) { + // 确保permissions是数组 + if (!permissions || !Array.isArray(permissions)) { + return false + } + + if (route.meta && route.meta.permissions) { + return permissions.some((role) => route.meta.permissions.includes(role)) + } else { + return true + } +} + +/** + * @author https://github.com/zxwk1998/vue-admin-better (不想保留author可删除) + * @description intelligence模式根据permissions数组拦截路由 + * @param routes + * @param permissions + * @returns {[]} + */ +export function filterAsyncRoutes(routes, permissions) { + // 处理无效参数 + if (!routes || !Array.isArray(routes)) { + return [] + } + + if (!permissions || !Array.isArray(permissions)) { + return [] + } + + const finallyRoutes = [] + routes.forEach((route) => { + if (!route) return + + const item = { ...route } + if (hasPermission(permissions, item)) { + if (item.children && Array.isArray(item.children)) { + item.children = filterAsyncRoutes(item.children, permissions) + } + finallyRoutes.push(item) + } + }) + return finallyRoutes +} diff --git a/src/utils/index.js b/src/utils/index.js new file mode 100644 index 0000000..3d826f7 --- /dev/null +++ b/src/utils/index.js @@ -0,0 +1,242 @@ +/** + * @author https://github.com/zxwk1998/vue-admin-better (不想保留author可删除) + * @description 格式化时间 + * @param time + * @param cFormat + * @returns {string|null} + */ +export function parseTime(time, cFormat) { + if (arguments.length === 0) { + return null + } + const format = cFormat || '{y}-{m}-{d} {h}:{i}:{s}' + let date + if (typeof time === 'object') { + date = time + } else { + if (typeof time === 'string' && /^[0-9]+$/.test(time)) { + time = parseInt(time) + } + if (typeof time === 'number' && time.toString().length === 10) { + time = time * 1000 + } + date = new Date(time) + } + const formatObj = { + y: date.getFullYear(), + m: date.getMonth() + 1, + d: date.getDate(), + h: date.getHours(), + i: date.getMinutes(), + s: date.getSeconds(), + a: date.getDay(), + } + const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => { + let value = formatObj[key] + if (key === 'a') { + return ['日', '一', '二', '三', '四', '五', '六'][value] + } + if (result.length > 0 && value < 10) { + value = `0${value}` + } + return value || 0 + }) + return time_str +} + +/** + * @author https://github.com/zxwk1998/vue-admin-better (不想保留author可删除) + * @description 格式化时间 + * @param time + * @param option + * @returns {string} + */ +export function formatTime(time, option) { + if (`${time}`.length === 10) { + time = parseInt(time) * 1000 + } else { + time = +time + } + const d = new Date(time) + const now = Date.now() + + const diff = (now - d) / 1000 + + if (diff < 30) { + return '刚刚' + } else if (diff < 3600) { + // less 1 hour + return `${Math.ceil(diff / 60)}分钟前` + } else if (diff < 3600 * 24) { + return `${Math.ceil(diff / 3600)}小时前` + } else if (diff < 3600 * 24 * 2) { + return '1天前' + } + if (option) { + return parseTime(time, option) + } else { + return `${d.getMonth() + 1}月${d.getDate()}日${d.getHours()}时${d.getMinutes()}分` + } +} + +/** + * @author https://github.com/zxwk1998/vue-admin-better (不想保留author可删除) + * @description 将url请求参数转为json格式 + * @param url + * @returns {{}|any} + */ +export function paramObj(url) { + const search = url.split('?')[1] + if (!search) { + return {} + } + return JSON.parse(`{"${decodeURIComponent(search).replace(/"/g, '\\"').replace(/&/g, '","').replace(/=/g, '":"').replace(/\+/g, ' ')}"}`) +} + +/** + * @author https://github.com/zxwk1998/vue-admin-better (不想保留author可删除) + * @description 父子关系的数组转换成树形结构数据 + * @param data + * @returns {*} + */ +export function translateDataToTree(data) { + const parent = data.filter((value) => value.parentId === 'undefined' || value.parentId == null) + const children = data.filter((value) => value.parentId !== 'undefined' && value.parentId != null) + const translator = (parent, children) => { + parent.forEach((parent) => { + children.forEach((current, index) => { + if (current.parentId === parent.id) { + const temp = JSON.parse(JSON.stringify(children)) + temp.splice(index, 1) + translator([current], temp) + typeof parent.children !== 'undefined' ? parent.children.push(current) : (parent.children = [current]) + } + }) + }) + } + translator(parent, children) + return parent +} + +/** + * @author https://github.com/zxwk1998/vue-admin-better (不想保留author可删除) + * @description 树形结构数据转换成父子关系的数组 + * @param data + * @returns {[]} + */ +export function translateTreeToData(data) { + const result = [] + data.forEach((item) => { + const loop = (data) => { + result.push({ + id: data.id, + name: data.name, + parentId: data.parentId, + }) + const child = data.children + if (child) { + for (let i = 0; i < child.length; i++) { + loop(child[i]) + } + } + } + loop(item) + }) + return result +} + +/** + * @author https://github.com/zxwk1998/vue-admin-better (不想保留author可删除) + * @description 10位时间戳转换 + * @param time + * @returns {string} + */ +export function tenBitTimestamp(time) { + const date = new Date(time * 1000) + const y = date.getFullYear() + let m = date.getMonth() + 1 + m = m < 10 ? `${m}` : m + let d = date.getDate() + d = d < 10 ? `${d}` : d + let h = date.getHours() + h = h < 10 ? `0${h}` : h + let minute = date.getMinutes() + let second = date.getSeconds() + minute = minute < 10 ? `0${minute}` : minute + second = second < 10 ? `0${second}` : second + return `${y}年${m}月${d}日 ${h}:${minute}:${second}` //组合 +} + +/** + * @author https://github.com/zxwk1998/vue-admin-better (不想保留author可删除) + * @description 13位时间戳转换 + * @param time + * @returns {string} + */ +export function thirteenBitTimestamp(time) { + const date = new Date(time / 1) + const y = date.getFullYear() + let m = date.getMonth() + 1 + m = m < 10 ? `${m}` : m + let d = date.getDate() + d = d < 10 ? `${d}` : d + let h = date.getHours() + h = h < 10 ? `0${h}` : h + let minute = date.getMinutes() + let second = date.getSeconds() + minute = minute < 10 ? `0${minute}` : minute + second = second < 10 ? `0${second}` : second + return `${y}年${m}月${d}日 ${h}:${minute}:${second}` //组合 +} + +/** + * @author https://github.com/zxwk1998/vue-admin-better (不想保留author可删除) + * @description 获取随机id + * @param length + * @returns {string} + */ +export function uuid(length = 32) { + const num = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890' + let str = '' + for (let i = 0; i < length; i++) { + str += num.charAt(Math.floor(Math.random() * num.length)) + } + return str +} + +/** + * @author https://github.com/zxwk1998/vue-admin-better (不想保留author可删除) + * @description m到n的随机数 + * @param m + * @param n + * @returns {number} + */ +export function random(m, n) { + return Math.floor(Math.random() * (m - n) + n) +} + +/** + * @author https://github.com/zxwk1998/vue-admin-better (不想保留author可删除) + * @description addEventListener + * @type {function(...[*]=)} + */ +export const on = (function () { + return function (element, event, handler, useCapture = false) { + if (element && event && handler) { + element.addEventListener(event, handler, useCapture) + } + } +})() + +/** + * @author https://github.com/zxwk1998/vue-admin-better (不想保留author可删除) + * @description removeEventListener + * @type {function(...[*]=)} + */ +export const off = (function () { + return function (element, event, handler, useCapture = false) { + if (element && event) { + element.removeEventListener(event, handler, useCapture) + } + } +})() diff --git a/src/utils/pageTitle.js b/src/utils/pageTitle.js new file mode 100644 index 0000000..3fb78c1 --- /dev/null +++ b/src/utils/pageTitle.js @@ -0,0 +1,12 @@ +import { title } from '@/config' + +/** + * @author https://github.com/zxwk1998/vue-admin-better (不想保留author可删除) + * @description 设置标题 + * @param pageTitle + * @returns {string} + */ +export default function getPageTitle(pageTitle) { + if (pageTitle) return `${pageTitle}-${title}` + return `${title}` +} diff --git a/src/utils/permission.js b/src/utils/permission.js new file mode 100644 index 0000000..04fae07 --- /dev/null +++ b/src/utils/permission.js @@ -0,0 +1,20 @@ +import store from '@/store' + +/** + * @author https://github.com/zxwk1998/vue-admin-better (不想保留author可删除) + * @description 检查权限 + * @param value + * @returns {boolean} + */ +export default function checkPermission(value) { + if (value && value instanceof Array && value.length > 0) { + const permissions = store.getters['user/permissions'] + const permissionPermissions = value + + return permissions.some((role) => { + return permissionPermissions.includes(role) + }) + } else { + return false + } +} diff --git a/src/utils/printInfo.js b/src/utils/printInfo.js new file mode 100644 index 0000000..22efb09 --- /dev/null +++ b/src/utils/printInfo.js @@ -0,0 +1,9 @@ +/** + * @description 只在控制台打印layouts/index.js中的内容 + */ +import { donationConsole } from 'layouts' + +export function printLayoutsInfo() { + // 只在控制台打印 + donationConsole() +} diff --git a/src/utils/request.js b/src/utils/request.js new file mode 100644 index 0000000..be88b02 --- /dev/null +++ b/src/utils/request.js @@ -0,0 +1,175 @@ +import Vue from 'vue' +import axios from 'axios' +import { + baseURL, + contentType, + debounce, + invalidCode, + loginInterception, + noPermissionCode, + requestTimeout, + successCode, + tokenName, +} from '@/config' +import store from '@/store' +import qs from 'qs' +import router from '@/router' +import { isArray } from '@/utils/validate' + +let loadingInstance + +/** + * @author https://github.com/zxwk1998/vue-admin-better (不想保留author可删除) + * @description 处理code异常 + * @param {*} code + * @param {*} msg + */ +const handleCode = (code, msg) => { + switch (code) { + case invalidCode: + Vue.prototype.$baseMessage(msg || `后端接口${code}异常`, 'error') + store.dispatch('user/resetAccessToken').catch(() => {}) + if (loginInterception) { + location.reload() + } + break + case noPermissionCode: + router.push({ path: '/401' }).catch(() => {}) + break + default: + Vue.prototype.$baseMessage(msg || `后端接口${code}异常`, 'error') + break + } +} + +// 请求重试配置 +const retryConfig = { + retry: 3, // 重试次数 + retryDelay: 1000, // 重试间隔时间 +} + +// 创建axios实例 +const instance = axios.create({ + baseURL, + timeout: requestTimeout, + headers: { + 'Content-Type': contentType, + }, +}) + +// 请求重试方法 +instance.defaults.retry = retryConfig.retry +instance.defaults.retryDelay = retryConfig.retryDelay + +// 请求拦截器 +instance.interceptors.request.use( + (config) => { + if (store.getters['user/accessToken']) { + config.headers[tokenName] = store.getters['user/accessToken'] + } + //这里会过滤所有为空、0、false的key,如果不需要请自行注释 + if (config.data) config.data = Vue.prototype.$baseLodash.pickBy(config.data, Vue.prototype.$baseLodash.identity) + if (config.data && config.headers['Content-Type'] === 'application/x-www-form-urlencoded;charset=UTF-8') + config.data = qs.stringify(config.data) + if (debounce.some((item) => config.url.includes(item))) loadingInstance = Vue.prototype.$baseLoading() + return config + }, + (error) => { + return Promise.reject(error) + } +) + +// 响应拦截器 +instance.interceptors.response.use( + (response) => { + if (loadingInstance) loadingInstance.close() + + const { data, config } = response + + // 判断data是否为undefined或null + if (data === undefined || data === null) { + Vue.prototype.$baseMessage('后端接口返回数据为空', 'error') + return Promise.reject('后端接口返回数据为空') + } + + // 安全地解构code和msg,避免undefined异常 + const code = data.code !== undefined ? data.code : null + const msg = data.msg !== undefined ? data.msg : '未知错误' + + // 操作正常Code数组 + const codeVerificationArray = isArray(successCode) ? [...successCode] : [...[successCode]] + + // 是否操作正常 + if (code !== null && codeVerificationArray.includes(code)) { + return data + } else { + handleCode(code, msg) + return Promise.reject( + `vue-admin-better请求异常拦截:${JSON.stringify({ + url: config.url, + code, + msg, + })}` || 'Error' + ) + } + }, + (error) => { + if (loadingInstance) loadingInstance.close() + + // 处理请求重试 + const { config } = error + if (config && config.retry) { + // 设置当前重试次数 + config.__retryCount = config.__retryCount || 0 + + // 检查是否可以重试 + if (config.__retryCount < config.retry) { + // 增加重试次数 + config.__retryCount += 1 + + // 创建新的Promise进行重试 + const backoff = new Promise((resolve) => { + setTimeout(() => { + console.log(`重试请求: ${config.url}, 尝试次数: ${config.__retryCount}`) + resolve() + }, config.retryDelay || 1000) + }) + + // 重新发起请求 + return backoff.then(() => instance(config)) + } + } + + // 处理undefined或无法解析的错误情况 + if (!error) { + Vue.prototype.$baseMessage('发生未知错误', 'error') + return Promise.reject('发生未知错误') + } + + const { response, message } = error + if (response && response.data) { + + const { status, data } = response + handleCode(status, data.msg || message || '未知错误') + return Promise.reject(error) + } else { + let errorMsg = '后端接口未知异常' + + if (message) { + if (message === 'Network Error') { + errorMsg = '后端接口连接异常' + } else if (message.includes('timeout')) { + errorMsg = '后端接口请求超时' + } else if (message.includes('Request failed with status code')) { + const code = message.substr(message.length - 3) + errorMsg = `后端接口${code}异常` + } + } + + Vue.prototype.$baseMessage(errorMsg, 'error') + return Promise.reject(error) + } + } +) + +export default instance diff --git a/src/utils/rouList.js b/src/utils/rouList.js new file mode 100644 index 0000000..bb665f6 --- /dev/null +++ b/src/utils/rouList.js @@ -0,0 +1,62 @@ +export const pcaData = { + "code": 0, + "message": "success", + "data": [ + { + "path": "/mall", + "name": "Mall", + "component": "Layout", + "meta": { + "title": "预约数据", + "icon": "book", + "permissions": ['admin'], + }, + "children": [ + { + "path": "pay", + "name": "Pay", + "component": "@/views/mall/pay/index", + "meta": { + "title": "订单管理", + } + }, + { + "path":'goodsList', + "name":'GoodsList', + "component":'@/views/mall/goodsList/index', + "meta": { + "title":'钱包管理', + }, + }, + ] + }, + { + "path": "/coupon", + "name": "Coupon", + "component": "Layout", + "meta": { + "title": "券管理", + "icon": "cog", + "permissions":['admin'], + }, + "children": [ + { + "path": "couponlist", + "name": "Couponlist", + "component": "@/views/Coupon/couponlist/index", + "meta": { + "title": "券包" + } + }, + { + "path": "distribution", + "name": "distribution", + "component": "@/views/Coupon/distribution/index", + "meta": { + "title": "优惠券" + } + } + ] + } + ] +} \ No newline at end of file diff --git a/src/utils/static.js b/src/utils/static.js new file mode 100644 index 0000000..c646f9b --- /dev/null +++ b/src/utils/static.js @@ -0,0 +1,81 @@ +/** + * @author https://vuejs-core.cn + * @description 导入所有 controller 模块,浏览器环境中自动输出controller文件夹下Mock接口,请勿修改。 + */ +import Mock from 'mockjs' +import { paramObj } from '@/utils' + +const mocks = [] +// 使用兼容 rspack 的方式导入 mock 控制器 +const files = require.context('../../mock/controller', false, /\.js$/) + +files.keys().forEach((key) => { + mocks.push(...files(key)) +}) + +export function mockXHR() { + // 设置Mock响应延迟 + Mock.setup({ + timeout: '200-600', + }) + + // 保存原始的XHR send方法 + Mock.XHR.prototype.proxy_send = Mock.XHR.prototype.send + Mock.XHR.prototype.send = function () { + if (this.custom.xhr) { + this.custom.xhr.withCredentials = this.withCredentials || false + + if (this.responseType) { + this.custom.xhr.responseType = this.responseType + } + } + this.proxy_send(...arguments) + } + + function XHRHttpRequst(respond) { + return function (options) { + let result + try { + if (respond instanceof Function) { + const { body, type, url } = options + // 安全解析body + let parsedBody = {} + if (body) { + try { + parsedBody = JSON.parse(body) + } catch (e) { + console.warn('无法解析请求体:', e) + } + } + + result = respond({ + method: type, + body: parsedBody, + query: paramObj(url), + }) + } else { + result = respond + } + } catch (error) { + console.error('Mock处理请求时发生错误:', error) + // 返回默认错误响应 + result = { + code: 500, + message: '服务器内部错误', + } + } + return Mock.mock(result) + } + } + + // 注册所有的mock服务 + mocks.forEach((item) => { + Mock.mock(new RegExp(item.url), item.type || 'get' || 'post' , XHRHttpRequst(item.response)) + }) + + // 记录mock设置完成 + console.info(`[Mock] 成功设置 ${mocks.length} 个模拟接口`) +} + +// 导出mocks列表,便于调试 +export const mockList = mocks diff --git a/src/utils/vab.js b/src/utils/vab.js new file mode 100644 index 0000000..cbbd4da --- /dev/null +++ b/src/utils/vab.js @@ -0,0 +1,156 @@ +import { loadingText, messageDuration, title } from '@/config' +import * as lodash from 'lodash' +import { Loading, Message, MessageBox, Notification } from 'element-ui' +import store from '@/store' +import { getAccessToken } from '@/utils/accessToken' + +const accessToken = store.getters['user/accessToken'] +const layout = store.getters['settings/layout'] + +const install = (Vue) => { + /* 全局accessToken */ + Vue.prototype.$baseAccessToken = () => { + return accessToken || getAccessToken() + } + /* 全局标题 */ + Vue.prototype.$baseTitle = (() => { + return title + })() + /* 全局加载层 */ + Vue.prototype.$baseLoading = (index, text) => { + let loading + if (!index) { + loading = Loading.service({ + lock: true, + text: text || loadingText, + background: 'hsla(0,0%,100%,.8)', + }) + } else { + loading = Loading.service({ + lock: true, + text: text || loadingText, + spinner: `vab-loading-type${index}`, + background: 'hsla(0,0%,100%,.8)', + }) + } + return loading + } + /* 全局多彩加载层 */ + Vue.prototype.$baseColorfullLoading = (index, text) => { + let loading + if (!index) { + loading = Loading.service({ + lock: true, + text: text || loadingText, + spinner: 'dots-loader', + background: 'hsla(0,0%,100%,.8)', + }) + } else { + switch (index) { + case 1: + index = 'dots' + break + case 2: + index = 'gauge' + break + case 3: + index = 'inner-circles' + break + case 4: + index = 'plus' + break + } + loading = Loading.service({ + lock: true, + text: text || loadingText, + spinner: `${index}-loader`, + background: 'hsla(0,0%,100%,.8)', + }) + } + return loading + } + /* 全局Message */ + Vue.prototype.$baseMessage = (message, type) => { + Message({ + offset: 60, + showClose: true, + message: message, + type: type, + dangerouslyUseHTMLString: true, + duration: messageDuration, + }) + } + + /* 全局Alert */ + Vue.prototype.$baseAlert = (content, title, callback) => { + MessageBox.alert(content, title || '温馨提示', { + confirmButtonText: '确定', + dangerouslyUseHTMLString: true, + callback: () => { + if (callback) { + callback() + } + }, + }) + } + + /* 全局Confirm */ + Vue.prototype.$baseConfirm = (content, title, callback1, callback2) => { + MessageBox.confirm(content, title || '温馨提示', { + confirmButtonText: '确定', + cancelButtonText: '取消', + closeOnClickModal: false, + type: 'warning', + }) + .then(() => { + if (callback1) { + callback1() + } + }) + .catch(() => { + if (callback2) { + callback2() + } + }) + } + + /* 全局Notification */ + Vue.prototype.$baseNotify = (message, title, type, position) => { + Notification({ + title: title, + message: message, + position: position || 'top-right', + type: type || 'success', + duration: messageDuration, + }) + } + + /* 全局TableHeight */ + Vue.prototype.$baseTableHeight = (formType) => { + let height = window.innerHeight + let paddingHeight = 400 + const formHeight = 50 + + if (layout === 'vertical') { + paddingHeight = 365 + } + + if ('number' == typeof formType) { + height = height - paddingHeight - formHeight * formType + } else { + height = height - paddingHeight + } + return height + } + + /* 全局lodash */ + Vue.prototype.$baseLodash = lodash + /* 全局事件总线 */ + Vue.prototype.$baseEventBus = new Vue() +} + +if (typeof window !== 'undefined' && window.Vue) { + install(window.Vue) +} + +export default install diff --git a/src/utils/validate.js b/src/utils/validate.js new file mode 100644 index 0000000..4a6030a --- /dev/null +++ b/src/utils/validate.js @@ -0,0 +1,53 @@ +/** + * @author zxwk1998 (不想保留author可删除) + * @description 判读是否为外链 + * @param path + * @returns {boolean} + */ +export function isExternal(path) { + return /^(https?:|mailto:|tel:)/.test(path) +} + +/** + * @author https://github.com/zxwk1998/vue-admin-better (不想保留author可删除) + * @description 校验密码是否小于6位 + * @param str + * @returns {boolean} + */ +export function isPassword(str) { + return str.length >= 6 +} + +/** + * @author zxwk1998 (不想保留author可删除) + * @description 判断是否是字符串 + * @param str + * @returns {boolean} + */ +export function isString(str) { + return typeof str === 'string' || str instanceof String +} + +/** + * @author zxwk1998 (不想保留author可删除) + * @description 判断是否是数组 + * @param arg + * @returns {arg is any[]|boolean} + */ +export function isArray(arg) { + if (typeof Array.isArray === 'undefined') { + return Object.prototype.toString.call(arg) === '[object Array]' + } + return Array.isArray(arg) +} + +/** + * @author zxwk1998 (不想保留author可删除) + * @description 判断是否是手机号 + * @param str + * @returns {boolean} + */ +export function isPhone(str) { + const reg = /^1\d{10}$/ + return reg.test(str) +} diff --git a/src/views/401.vue b/src/views/401.vue new file mode 100644 index 0000000..496b849 --- /dev/null +++ b/src/views/401.vue @@ -0,0 +1,290 @@ + + + + + diff --git a/src/views/404.vue b/src/views/404.vue new file mode 100644 index 0000000..59c6da8 --- /dev/null +++ b/src/views/404.vue @@ -0,0 +1,286 @@ + + + + + diff --git a/src/views/administrator/role/components/TableEdit.vue b/src/views/administrator/role/components/TableEdit.vue new file mode 100644 index 0000000..13b7ad0 --- /dev/null +++ b/src/views/administrator/role/components/TableEdit.vue @@ -0,0 +1,222 @@ + + + + diff --git a/src/views/administrator/role/index.vue b/src/views/administrator/role/index.vue new file mode 100644 index 0000000..2fe4eed --- /dev/null +++ b/src/views/administrator/role/index.vue @@ -0,0 +1,263 @@ + + + diff --git a/src/views/administrator/user/components/TableEdit.vue b/src/views/administrator/user/components/TableEdit.vue new file mode 100644 index 0000000..7438819 --- /dev/null +++ b/src/views/administrator/user/components/TableEdit.vue @@ -0,0 +1,189 @@ + + + diff --git a/src/views/administrator/user/index.vue b/src/views/administrator/user/index.vue new file mode 100644 index 0000000..5c593e9 --- /dev/null +++ b/src/views/administrator/user/index.vue @@ -0,0 +1,263 @@ + + + diff --git a/src/views/careManagement/therapist/components/TableEdit.vue b/src/views/careManagement/therapist/components/TableEdit.vue new file mode 100644 index 0000000..86252f3 --- /dev/null +++ b/src/views/careManagement/therapist/components/TableEdit.vue @@ -0,0 +1,214 @@ + + + + diff --git a/src/views/careManagement/therapist/index.vue b/src/views/careManagement/therapist/index.vue new file mode 100644 index 0000000..2fbe424 --- /dev/null +++ b/src/views/careManagement/therapist/index.vue @@ -0,0 +1,255 @@ + + + diff --git a/src/views/careManagement/vehicle/components/TableEdit.vue b/src/views/careManagement/vehicle/components/TableEdit.vue new file mode 100644 index 0000000..184c28d --- /dev/null +++ b/src/views/careManagement/vehicle/components/TableEdit.vue @@ -0,0 +1,211 @@ + + + diff --git a/src/views/careManagement/vehicle/index.vue b/src/views/careManagement/vehicle/index.vue new file mode 100644 index 0000000..42f7415 --- /dev/null +++ b/src/views/careManagement/vehicle/index.vue @@ -0,0 +1,255 @@ + + + diff --git a/src/views/certificate/ficate/components/TableEdit.vue b/src/views/certificate/ficate/components/TableEdit.vue new file mode 100644 index 0000000..a559633 --- /dev/null +++ b/src/views/certificate/ficate/components/TableEdit.vue @@ -0,0 +1,214 @@ + + + + diff --git a/src/views/certificate/ficate/index.vue b/src/views/certificate/ficate/index.vue new file mode 100644 index 0000000..d6eb4ed --- /dev/null +++ b/src/views/certificate/ficate/index.vue @@ -0,0 +1,255 @@ + + + diff --git a/src/views/comment/components/TableEdit.vue b/src/views/comment/components/TableEdit.vue new file mode 100644 index 0000000..d8d3e79 --- /dev/null +++ b/src/views/comment/components/TableEdit.vue @@ -0,0 +1,109 @@ + + + + diff --git a/src/views/comment/index.vue b/src/views/comment/index.vue new file mode 100644 index 0000000..6b6b43a --- /dev/null +++ b/src/views/comment/index.vue @@ -0,0 +1,289 @@ + + + diff --git a/src/views/commodity/malllist/components/TableEdit.vue b/src/views/commodity/malllist/components/TableEdit.vue new file mode 100644 index 0000000..7c60a56 --- /dev/null +++ b/src/views/commodity/malllist/components/TableEdit.vue @@ -0,0 +1,184 @@ + + + + diff --git a/src/views/commodity/malllist/index.vue b/src/views/commodity/malllist/index.vue new file mode 100644 index 0000000..186b4a6 --- /dev/null +++ b/src/views/commodity/malllist/index.vue @@ -0,0 +1,300 @@ + + diff --git a/src/views/commodity/orderlist/components/TableEdit.vue b/src/views/commodity/orderlist/components/TableEdit.vue new file mode 100644 index 0000000..f911730 --- /dev/null +++ b/src/views/commodity/orderlist/components/TableEdit.vue @@ -0,0 +1,160 @@ + + + + diff --git a/src/views/commodity/orderlist/index.vue b/src/views/commodity/orderlist/index.vue new file mode 100644 index 0000000..a98aba7 --- /dev/null +++ b/src/views/commodity/orderlist/index.vue @@ -0,0 +1,283 @@ + + diff --git a/src/views/coupon/couponlist/components/TableEdit.vue b/src/views/coupon/couponlist/components/TableEdit.vue new file mode 100644 index 0000000..16f9ce4 --- /dev/null +++ b/src/views/coupon/couponlist/components/TableEdit.vue @@ -0,0 +1,215 @@ + + + + diff --git a/src/views/coupon/couponlist/index.vue b/src/views/coupon/couponlist/index.vue new file mode 100644 index 0000000..e5069d2 --- /dev/null +++ b/src/views/coupon/couponlist/index.vue @@ -0,0 +1,252 @@ + + diff --git a/src/views/coupon/distribute/components/TableAdd.vue b/src/views/coupon/distribute/components/TableAdd.vue new file mode 100644 index 0000000..da7c193 --- /dev/null +++ b/src/views/coupon/distribute/components/TableAdd.vue @@ -0,0 +1,187 @@ + + + + diff --git a/src/views/coupon/distribute/components/TableEdit.vue b/src/views/coupon/distribute/components/TableEdit.vue new file mode 100644 index 0000000..32a4359 --- /dev/null +++ b/src/views/coupon/distribute/components/TableEdit.vue @@ -0,0 +1,91 @@ + + + diff --git a/src/views/coupon/distribute/index.vue b/src/views/coupon/distribute/index.vue new file mode 100644 index 0000000..87fdafa --- /dev/null +++ b/src/views/coupon/distribute/index.vue @@ -0,0 +1,223 @@ + + + diff --git a/src/views/coupon/distribution/components/TableEdit.vue b/src/views/coupon/distribution/components/TableEdit.vue new file mode 100644 index 0000000..16f9ce4 --- /dev/null +++ b/src/views/coupon/distribution/components/TableEdit.vue @@ -0,0 +1,215 @@ + + + + diff --git a/src/views/coupon/distribution/index.vue b/src/views/coupon/distribution/index.vue new file mode 100644 index 0000000..e5069d2 --- /dev/null +++ b/src/views/coupon/distribution/index.vue @@ -0,0 +1,252 @@ + + diff --git a/src/views/coupon/record/components/TableEdit.vue b/src/views/coupon/record/components/TableEdit.vue new file mode 100644 index 0000000..3521335 --- /dev/null +++ b/src/views/coupon/record/components/TableEdit.vue @@ -0,0 +1,98 @@ + + + diff --git a/src/views/coupon/record/index.vue b/src/views/coupon/record/index.vue new file mode 100644 index 0000000..09ae759 --- /dev/null +++ b/src/views/coupon/record/index.vue @@ -0,0 +1,228 @@ + + + diff --git a/src/views/coupon/redemption/components/TableEdit.vue b/src/views/coupon/redemption/components/TableEdit.vue new file mode 100644 index 0000000..16f9ce4 --- /dev/null +++ b/src/views/coupon/redemption/components/TableEdit.vue @@ -0,0 +1,215 @@ + + + + diff --git a/src/views/coupon/redemption/index.vue b/src/views/coupon/redemption/index.vue new file mode 100644 index 0000000..d4bc164 --- /dev/null +++ b/src/views/coupon/redemption/index.vue @@ -0,0 +1,252 @@ + + diff --git a/src/views/holidays/day/components/TableEdit.vue b/src/views/holidays/day/components/TableEdit.vue new file mode 100644 index 0000000..a559633 --- /dev/null +++ b/src/views/holidays/day/components/TableEdit.vue @@ -0,0 +1,214 @@ + + + + diff --git a/src/views/holidays/day/index.vue b/src/views/holidays/day/index.vue new file mode 100644 index 0000000..d6eb4ed --- /dev/null +++ b/src/views/holidays/day/index.vue @@ -0,0 +1,255 @@ + + + diff --git a/src/views/index/components/VersionInformation.vue b/src/views/index/components/VersionInformation.vue new file mode 100644 index 0000000..de40e73 --- /dev/null +++ b/src/views/index/components/VersionInformation.vue @@ -0,0 +1,85 @@ + + + + + diff --git a/src/views/index/index.vue b/src/views/index/index.vue new file mode 100644 index 0000000..0a03968 --- /dev/null +++ b/src/views/index/index.vue @@ -0,0 +1,1506 @@ + + + + diff --git a/src/views/information/components/TableEdit.vue b/src/views/information/components/TableEdit.vue new file mode 100644 index 0000000..aea1ad3 --- /dev/null +++ b/src/views/information/components/TableEdit.vue @@ -0,0 +1,214 @@ + + + + diff --git a/src/views/information/index.vue b/src/views/information/index.vue new file mode 100644 index 0000000..4ec9553 --- /dev/null +++ b/src/views/information/index.vue @@ -0,0 +1,255 @@ + + + diff --git a/src/views/login/index.vue b/src/views/login/index.vue new file mode 100644 index 0000000..68d9b2c --- /dev/null +++ b/src/views/login/index.vue @@ -0,0 +1,919 @@ + + + + + diff --git a/src/views/mall/additional/components/TableEdit.vue b/src/views/mall/additional/components/TableEdit.vue new file mode 100644 index 0000000..acb86ab --- /dev/null +++ b/src/views/mall/additional/components/TableEdit.vue @@ -0,0 +1,83 @@ + + + diff --git a/src/views/mall/additional/index.vue b/src/views/mall/additional/index.vue new file mode 100644 index 0000000..a321585 --- /dev/null +++ b/src/views/mall/additional/index.vue @@ -0,0 +1,232 @@ + + + diff --git a/src/views/mall/archive/components/TableEdit.vue b/src/views/mall/archive/components/TableEdit.vue new file mode 100644 index 0000000..68df2dc --- /dev/null +++ b/src/views/mall/archive/components/TableEdit.vue @@ -0,0 +1,108 @@ + + + diff --git a/src/views/mall/archive/index.vue b/src/views/mall/archive/index.vue new file mode 100644 index 0000000..4ba020c --- /dev/null +++ b/src/views/mall/archive/index.vue @@ -0,0 +1,232 @@ + + + diff --git a/src/views/mall/doorOrder/components/TableEdit.vue b/src/views/mall/doorOrder/components/TableEdit.vue new file mode 100644 index 0000000..487b91c --- /dev/null +++ b/src/views/mall/doorOrder/components/TableEdit.vue @@ -0,0 +1,145 @@ + + + diff --git a/src/views/mall/doorOrder/index.vue b/src/views/mall/doorOrder/index.vue new file mode 100644 index 0000000..f3b2491 --- /dev/null +++ b/src/views/mall/doorOrder/index.vue @@ -0,0 +1,285 @@ + + + diff --git a/src/views/mall/goodsList/components/TableEdit.vue b/src/views/mall/goodsList/components/TableEdit.vue new file mode 100644 index 0000000..68df2dc --- /dev/null +++ b/src/views/mall/goodsList/components/TableEdit.vue @@ -0,0 +1,108 @@ + + + diff --git a/src/views/mall/goodsList/index.vue b/src/views/mall/goodsList/index.vue new file mode 100644 index 0000000..30109d8 --- /dev/null +++ b/src/views/mall/goodsList/index.vue @@ -0,0 +1,230 @@ + + + diff --git a/src/views/mall/member/components/TableEdit.vue b/src/views/mall/member/components/TableEdit.vue new file mode 100644 index 0000000..68df2dc --- /dev/null +++ b/src/views/mall/member/components/TableEdit.vue @@ -0,0 +1,108 @@ + + + diff --git a/src/views/mall/member/index.vue b/src/views/mall/member/index.vue new file mode 100644 index 0000000..1948c3d --- /dev/null +++ b/src/views/mall/member/index.vue @@ -0,0 +1,308 @@ + + + diff --git a/src/views/mall/pay/components/TableEdit.vue b/src/views/mall/pay/components/TableEdit.vue new file mode 100644 index 0000000..40a30e0 --- /dev/null +++ b/src/views/mall/pay/components/TableEdit.vue @@ -0,0 +1,145 @@ + + + diff --git a/src/views/mall/pay/index.vue b/src/views/mall/pay/index.vue new file mode 100644 index 0000000..25a4eb4 --- /dev/null +++ b/src/views/mall/pay/index.vue @@ -0,0 +1,334 @@ + + + diff --git a/src/views/mall/points/components/TableEdit.vue b/src/views/mall/points/components/TableEdit.vue new file mode 100644 index 0000000..a559633 --- /dev/null +++ b/src/views/mall/points/components/TableEdit.vue @@ -0,0 +1,214 @@ + + + + diff --git a/src/views/mall/points/index.vue b/src/views/mall/points/index.vue new file mode 100644 index 0000000..d6eb4ed --- /dev/null +++ b/src/views/mall/points/index.vue @@ -0,0 +1,255 @@ + + + diff --git a/src/views/mall/registerUser/components/TableEdit.vue b/src/views/mall/registerUser/components/TableEdit.vue new file mode 100644 index 0000000..487b91c --- /dev/null +++ b/src/views/mall/registerUser/components/TableEdit.vue @@ -0,0 +1,145 @@ + + + diff --git a/src/views/mall/registerUser/index.vue b/src/views/mall/registerUser/index.vue new file mode 100644 index 0000000..8f8ddf7 --- /dev/null +++ b/src/views/mall/registerUser/index.vue @@ -0,0 +1,298 @@ + + + diff --git a/src/views/mall/time/components/TableEdit.vue b/src/views/mall/time/components/TableEdit.vue new file mode 100644 index 0000000..a559633 --- /dev/null +++ b/src/views/mall/time/components/TableEdit.vue @@ -0,0 +1,214 @@ + + + + diff --git a/src/views/mall/time/index.vue b/src/views/mall/time/index.vue new file mode 100644 index 0000000..d6eb4ed --- /dev/null +++ b/src/views/mall/time/index.vue @@ -0,0 +1,255 @@ + + + diff --git a/src/views/message/components/TableEdit.vue b/src/views/message/components/TableEdit.vue new file mode 100644 index 0000000..d8d3e79 --- /dev/null +++ b/src/views/message/components/TableEdit.vue @@ -0,0 +1,109 @@ + + + + diff --git a/src/views/message/index.vue b/src/views/message/index.vue new file mode 100644 index 0000000..c69e0a0 --- /dev/null +++ b/src/views/message/index.vue @@ -0,0 +1,288 @@ + + + diff --git a/src/views/order/components/TableEdit.vue b/src/views/order/components/TableEdit.vue new file mode 100644 index 0000000..86252f3 --- /dev/null +++ b/src/views/order/components/TableEdit.vue @@ -0,0 +1,214 @@ + + + + diff --git a/src/views/order/index.vue b/src/views/order/index.vue new file mode 100644 index 0000000..83303d5 --- /dev/null +++ b/src/views/order/index.vue @@ -0,0 +1,255 @@ + + + diff --git a/src/views/payment/paymentList/components/TableEdit.vue b/src/views/payment/paymentList/components/TableEdit.vue new file mode 100644 index 0000000..13b7ad0 --- /dev/null +++ b/src/views/payment/paymentList/components/TableEdit.vue @@ -0,0 +1,222 @@ + + + + diff --git a/src/views/payment/paymentList/index.vue b/src/views/payment/paymentList/index.vue new file mode 100644 index 0000000..2fe4eed --- /dev/null +++ b/src/views/payment/paymentList/index.vue @@ -0,0 +1,263 @@ + + + diff --git a/src/views/personalCenter/index.vue b/src/views/personalCenter/index.vue new file mode 100644 index 0000000..842093f --- /dev/null +++ b/src/views/personalCenter/index.vue @@ -0,0 +1,30 @@ + + + diff --git a/src/views/personnelManagement/menuManagement/components/MenuManagementEdit.vue b/src/views/personnelManagement/menuManagement/components/MenuManagementEdit.vue new file mode 100644 index 0000000..c27585d --- /dev/null +++ b/src/views/personnelManagement/menuManagement/components/MenuManagementEdit.vue @@ -0,0 +1,64 @@ + + + diff --git a/src/views/personnelManagement/menuManagement/index.vue b/src/views/personnelManagement/menuManagement/index.vue new file mode 100644 index 0000000..42bdf6e --- /dev/null +++ b/src/views/personnelManagement/menuManagement/index.vue @@ -0,0 +1,152 @@ + + + diff --git a/src/views/personnelManagement/roleManagement/components/RoleManagementEdit.vue b/src/views/personnelManagement/roleManagement/components/RoleManagementEdit.vue new file mode 100644 index 0000000..284149a --- /dev/null +++ b/src/views/personnelManagement/roleManagement/components/RoleManagementEdit.vue @@ -0,0 +1,62 @@ + + + diff --git a/src/views/personnelManagement/roleManagement/index.vue b/src/views/personnelManagement/roleManagement/index.vue new file mode 100644 index 0000000..be45b86 --- /dev/null +++ b/src/views/personnelManagement/roleManagement/index.vue @@ -0,0 +1,137 @@ + + + diff --git a/src/views/personnelManagement/userManagement/components/UserManagementEdit.vue b/src/views/personnelManagement/userManagement/components/UserManagementEdit.vue new file mode 100644 index 0000000..24766be --- /dev/null +++ b/src/views/personnelManagement/userManagement/components/UserManagementEdit.vue @@ -0,0 +1,80 @@ + + + diff --git a/src/views/personnelManagement/userManagement/index.vue b/src/views/personnelManagement/userManagement/index.vue new file mode 100644 index 0000000..0e17b06 --- /dev/null +++ b/src/views/personnelManagement/userManagement/index.vue @@ -0,0 +1,146 @@ + + + diff --git a/src/views/pricing/care/components/TableEdit.vue b/src/views/pricing/care/components/TableEdit.vue new file mode 100644 index 0000000..13b7ad0 --- /dev/null +++ b/src/views/pricing/care/components/TableEdit.vue @@ -0,0 +1,222 @@ + + + + diff --git a/src/views/pricing/care/index.vue b/src/views/pricing/care/index.vue new file mode 100644 index 0000000..aca3bf7 --- /dev/null +++ b/src/views/pricing/care/index.vue @@ -0,0 +1,262 @@ + + + diff --git a/src/views/pricing/commission/components/TableEdit.vue b/src/views/pricing/commission/components/TableEdit.vue new file mode 100644 index 0000000..7438819 --- /dev/null +++ b/src/views/pricing/commission/components/TableEdit.vue @@ -0,0 +1,189 @@ + + + diff --git a/src/views/pricing/commission/index.vue b/src/views/pricing/commission/index.vue new file mode 100644 index 0000000..5c593e9 --- /dev/null +++ b/src/views/pricing/commission/index.vue @@ -0,0 +1,263 @@ + + + diff --git a/src/views/publicWelfare/adopt/components/TableEdit.vue b/src/views/publicWelfare/adopt/components/TableEdit.vue new file mode 100644 index 0000000..86252f3 --- /dev/null +++ b/src/views/publicWelfare/adopt/components/TableEdit.vue @@ -0,0 +1,214 @@ + + + + diff --git a/src/views/publicWelfare/adopt/index.vue b/src/views/publicWelfare/adopt/index.vue new file mode 100644 index 0000000..49f342b --- /dev/null +++ b/src/views/publicWelfare/adopt/index.vue @@ -0,0 +1,255 @@ + + + diff --git a/src/views/publicWelfare/points/components/TableEdit.vue b/src/views/publicWelfare/points/components/TableEdit.vue new file mode 100644 index 0000000..184c28d --- /dev/null +++ b/src/views/publicWelfare/points/components/TableEdit.vue @@ -0,0 +1,211 @@ + + + diff --git a/src/views/publicWelfare/points/index.vue b/src/views/publicWelfare/points/index.vue new file mode 100644 index 0000000..175ebdf --- /dev/null +++ b/src/views/publicWelfare/points/index.vue @@ -0,0 +1,255 @@ + + + diff --git a/src/views/publicWelfare/public/components/TableEdit.vue b/src/views/publicWelfare/public/components/TableEdit.vue new file mode 100644 index 0000000..a559633 --- /dev/null +++ b/src/views/publicWelfare/public/components/TableEdit.vue @@ -0,0 +1,214 @@ + + + + diff --git a/src/views/publicWelfare/public/index.vue b/src/views/publicWelfare/public/index.vue new file mode 100644 index 0000000..a250cee --- /dev/null +++ b/src/views/publicWelfare/public/index.vue @@ -0,0 +1,255 @@ + + + diff --git a/src/views/register/index.vue b/src/views/register/index.vue new file mode 100644 index 0000000..3082603 --- /dev/null +++ b/src/views/register/index.vue @@ -0,0 +1,692 @@ + + + + + diff --git a/src/views/settlement/sett/components/TableEdit.vue b/src/views/settlement/sett/components/TableEdit.vue new file mode 100644 index 0000000..13b7ad0 --- /dev/null +++ b/src/views/settlement/sett/components/TableEdit.vue @@ -0,0 +1,222 @@ + + + + diff --git a/src/views/settlement/sett/index.vue b/src/views/settlement/sett/index.vue new file mode 100644 index 0000000..2fe4eed --- /dev/null +++ b/src/views/settlement/sett/index.vue @@ -0,0 +1,263 @@ + + + diff --git a/src/views/test/index.vue b/src/views/test/index.vue new file mode 100644 index 0000000..cd3fc66 --- /dev/null +++ b/src/views/test/index.vue @@ -0,0 +1,16 @@ + + diff --git a/src/views/vab/backToTop/index.vue b/src/views/vab/backToTop/index.vue new file mode 100644 index 0000000..d9efe2a --- /dev/null +++ b/src/views/vab/backToTop/index.vue @@ -0,0 +1,27 @@ + + + + diff --git a/src/views/vab/chart/index.vue b/src/views/vab/chart/index.vue new file mode 100644 index 0000000..7b21b8f --- /dev/null +++ b/src/views/vab/chart/index.vue @@ -0,0 +1,231 @@ + + + + + \ No newline at end of file diff --git a/src/views/vab/editor/index.vue b/src/views/vab/editor/index.vue new file mode 100644 index 0000000..5dc0e9e --- /dev/null +++ b/src/views/vab/editor/index.vue @@ -0,0 +1,339 @@ + + + + + diff --git a/src/views/vab/element/index.vue b/src/views/vab/element/index.vue new file mode 100644 index 0000000..d2bbe25 --- /dev/null +++ b/src/views/vab/element/index.vue @@ -0,0 +1,185 @@ + + + + + diff --git a/src/views/vab/errorLog/components/ErrorTest.vue b/src/views/vab/errorLog/components/ErrorTest.vue new file mode 100644 index 0000000..3f653e8 --- /dev/null +++ b/src/views/vab/errorLog/components/ErrorTest.vue @@ -0,0 +1,13 @@ + + + diff --git a/src/views/vab/errorLog/index.vue b/src/views/vab/errorLog/index.vue new file mode 100644 index 0000000..c1808f2 --- /dev/null +++ b/src/views/vab/errorLog/index.vue @@ -0,0 +1,34 @@ + + + diff --git a/src/views/vab/form/index.vue b/src/views/vab/form/index.vue new file mode 100644 index 0000000..adc7476 --- /dev/null +++ b/src/views/vab/form/index.vue @@ -0,0 +1,104 @@ + + + diff --git a/src/views/vab/icon/colorfulIcon.vue b/src/views/vab/icon/colorfulIcon.vue new file mode 100644 index 0000000..8c90a0b --- /dev/null +++ b/src/views/vab/icon/colorfulIcon.vue @@ -0,0 +1,145 @@ + + + + + diff --git a/src/views/vab/icon/index.vue b/src/views/vab/icon/index.vue new file mode 100644 index 0000000..6fd0efd --- /dev/null +++ b/src/views/vab/icon/index.vue @@ -0,0 +1,134 @@ + + + + + diff --git a/src/views/vab/loading/index.vue b/src/views/vab/loading/index.vue new file mode 100644 index 0000000..0c79148 --- /dev/null +++ b/src/views/vab/loading/index.vue @@ -0,0 +1,69 @@ + + + + + diff --git a/src/views/vab/lodash/index.vue b/src/views/vab/lodash/index.vue new file mode 100644 index 0000000..5a4d56c --- /dev/null +++ b/src/views/vab/lodash/index.vue @@ -0,0 +1,240 @@ + + + + diff --git a/src/views/vab/more/index.vue b/src/views/vab/more/index.vue new file mode 100644 index 0000000..f4acb4c --- /dev/null +++ b/src/views/vab/more/index.vue @@ -0,0 +1,603 @@ + + + + + diff --git a/src/views/vab/nested/menu1/index.vue b/src/views/vab/nested/menu1/index.vue new file mode 100644 index 0000000..13aa922 --- /dev/null +++ b/src/views/vab/nested/menu1/index.vue @@ -0,0 +1,20 @@ + + + diff --git a/src/views/vab/nested/menu1/menu1-1/index.vue b/src/views/vab/nested/menu1/menu1-1/index.vue new file mode 100644 index 0000000..b8d00c6 --- /dev/null +++ b/src/views/vab/nested/menu1/menu1-1/index.vue @@ -0,0 +1,27 @@ + + + + + diff --git a/src/views/vab/nested/menu1/menu1-1/menu1-1-1/index.vue b/src/views/vab/nested/menu1/menu1-1/menu1-1-1/index.vue new file mode 100644 index 0000000..767fed1 --- /dev/null +++ b/src/views/vab/nested/menu1/menu1-1/menu1-1-1/index.vue @@ -0,0 +1,25 @@ + + + + + diff --git a/src/views/vab/permissions/index.vue b/src/views/vab/permissions/index.vue new file mode 100644 index 0000000..b626ebb --- /dev/null +++ b/src/views/vab/permissions/index.vue @@ -0,0 +1,414 @@ + + + + + diff --git a/src/views/vab/qrCode/index.vue b/src/views/vab/qrCode/index.vue new file mode 100644 index 0000000..93ef4f3 --- /dev/null +++ b/src/views/vab/qrCode/index.vue @@ -0,0 +1,442 @@ + + + + + diff --git a/src/views/vab/tab/index.vue b/src/views/vab/tab/index.vue new file mode 100644 index 0000000..1b1cfbb --- /dev/null +++ b/src/views/vab/tab/index.vue @@ -0,0 +1,300 @@ + + + + + diff --git a/src/views/vab/table/components/TableEdit.vue b/src/views/vab/table/components/TableEdit.vue new file mode 100644 index 0000000..ce7cb38 --- /dev/null +++ b/src/views/vab/table/components/TableEdit.vue @@ -0,0 +1,70 @@ + + + diff --git a/src/views/vab/table/index.vue b/src/views/vab/table/index.vue new file mode 100644 index 0000000..c7b31ae --- /dev/null +++ b/src/views/vab/table/index.vue @@ -0,0 +1,223 @@ + + + diff --git a/src/views/vab/tree/index.vue b/src/views/vab/tree/index.vue new file mode 100644 index 0000000..139149b --- /dev/null +++ b/src/views/vab/tree/index.vue @@ -0,0 +1,449 @@ + + + diff --git a/src/views/vab/upload/index.vue b/src/views/vab/upload/index.vue new file mode 100644 index 0000000..c947714 --- /dev/null +++ b/src/views/vab/upload/index.vue @@ -0,0 +1,30 @@ + + + diff --git a/src/views/vab/webSocket/index.vue b/src/views/vab/webSocket/index.vue new file mode 100644 index 0000000..b9bef3b --- /dev/null +++ b/src/views/vab/webSocket/index.vue @@ -0,0 +1,91 @@ + + + diff --git a/src/views/vehicle/components/TableEdit.vue b/src/views/vehicle/components/TableEdit.vue new file mode 100644 index 0000000..184c28d --- /dev/null +++ b/src/views/vehicle/components/TableEdit.vue @@ -0,0 +1,211 @@ + + + diff --git a/src/views/vehicle/index.vue b/src/views/vehicle/index.vue new file mode 100644 index 0000000..becf033 --- /dev/null +++ b/src/views/vehicle/index.vue @@ -0,0 +1,255 @@ + + + diff --git a/src/views/xiaowa/components/TableEdit.vue b/src/views/xiaowa/components/TableEdit.vue new file mode 100644 index 0000000..a559633 --- /dev/null +++ b/src/views/xiaowa/components/TableEdit.vue @@ -0,0 +1,214 @@ + + + + diff --git a/src/views/xiaowa/index.vue b/src/views/xiaowa/index.vue new file mode 100644 index 0000000..d6eb4ed --- /dev/null +++ b/src/views/xiaowa/index.vue @@ -0,0 +1,255 @@ + + +