Commit f88c3868 by chuzhixin

🎉🎉🎉仓库重置到2020年9月29日,Vue2.6最后一个版本,之前版本不再支持,具体请查阅文档,Vue 3.0版本即将发布请耐心等待!!!

parents
> 1%
last 2 versions
not dead
root = true
[*]
charset = utf-8
end_of_line = lf
indent_size = 2
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true
[*.md]
trim_trailing_whitespace = false
src/assets
src/icons
public
dist
node_modules
module.exports = {
root: true,
env: {
node: true,
},
extends: ["plugin:vue/recommended", "@vue/prettier"],
rules: {
"no-console": process.env.NODE_ENV === "production" ? "warn" : "off",
"no-debugger": process.env.NODE_ENV === "production" ? "warn" : "off",
"vue/no-v-html": "off",
},
parserOptions: {
parser: "babel-eslint",
},
overrides: [
{
files: [
"**/__tests__/*.{j,t}s?(x)",
"**/tests/unit/**/*.spec.{j,t}s?(x)",
],
env: {
jest: true,
},
},
],
};
*.html text eol=lf
*.css text eol=lf
*.js text eol=lf
*.scss text eol=lf
*.vue text eol=lf
*.hbs text eol=lf
*.sh text eol=lf
*.md text eol=lf
*.json text eol=lf
*.yml text eol=lf
patreon: chuzhixin
---
name: 问题提问(不按规范提问不解答)
about: 详细描述你的问题
title: ''
labels: ''
assignees: ''
---
#### 出现的问题
#### 操作了什么以后出现了的
#### 详细的报错截图、控制台截图
#### 是否已经百度过了、是否已经努力尝试解决了
.DS_Store
node_modules
dist
.env.local
.env.*.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.idea
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
public/video
*.zip
*.7z
/src/layouts/components/zx-layouts
/zx-templates
/package-lock.json
module.exports = {
extends: ["stylelint-config-recess-order", "stylelint-config-prettier"],
};
{
"[vue]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"editor.quickSuggestions": {
"strings": true
},
"workbench.colorTheme": "One Monokai",
"editor.tabSize": 2,
"editor.detectIndentation": false,
"emmet.triggerExpansionOnTab": true,
"editor.formatOnSave": true,
"javascript.format.enable": true,
"git.enableSmartCommit": true,
"git.autofetch": true,
"git.confirmSync": false,
"[json]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"liveServer.settings.donotShowInfoMsg": true,
"explorer.confirmDelete": false,
"javascript.updateImportsOnFileMove.enabled": "always",
"typescript.updateImportsOnFileMove.enabled": "always",
"files.exclude": {
"**/.idea": true
},
"editor.codeActionsOnSave": {
"source.fixAll.stylelint": true,
"source.fixAll.eslint": true
},
"[javascript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[scss]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[jsonc]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[html]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"editor.suggest.snippetsPreventQuickSuggestions": false,
"prettier.htmlWhitespaceSensitivity": "ignore",
"prettier.vueIndentScriptAndStyle": true,
"docthis.authorName": "chuzhixin 1204505056@qq.com",
"docthis.includeAuthorTag": true,
"docthis.includeDescriptionTag": true,
"docthis.enableHungarianNotationEvaluation": true,
"docthis.inferTypesFromNames": true,
"vetur.format.defaultFormatter.html": "prettier"
}
This diff is collapsed. Click to expand it.
<div align="center"><img width="200" src="https://gitee.com/chu1204505056/vue-admin-beautiful/raw/master/src/colorfulIcon/svg/vab.svg"/>
<h1> vue-admin-beautiful </h1>
<h3>一款基于 vue+element-ui 的绝佳的通用型、中后台前端框架</h3>
<h3>An excellent general-purpose, middle and background front-end framework based on Vue + element UI</h3>
</div>
[![](https://img.shields.io/github/stars/chuzhixin/vue-admin-beautiful?style=flat-square&label=Stars&logo=github)
](https://github.com/chuzhixin/vue-admin-beautiful)
## 演示地址
### - [🚀 演示地址:vue-admin-beautiful (横向纵向布局无缝切换)](https://chu1204505056.gitee.io/vue-admin-beautiful/?hmsr=%E6%8F%92%E4%BB%B6%E5%B8%82%E5%9C%BA&hmpl=&hmcu=&hmkw=&hmci=)
### - [🚀 vue-admin-beautiful-pro 版演示地址](https://chu1204505056.gitee.io/vue-admin-beautiful-pro/?hmsr=%E6%8F%92%E4%BB%B6%E5%B8%82%E5%9C%BA&hmpl=&hmcu=&hmkw=&hmci=)
### - [🚀 vue-admin-beautiful-mini vue3.0 预览版地址](https://chu1204505056.gitee.io/vue-admin-beautiful-mini/?hmsr=%E6%8F%92%E4%BB%B6%E5%B8%82%E5%9C%BA&hmpl=&hmcu=&hmkw=&hmci=)
## vue-admin-beautiful 前端讨论群-1 972435319
不管您加或者不加,您都可以享受到开源的代码,感谢您的支持和信任,群内提供 vue-admin-beautiful-template 基础版本和详细的基础使用文档适合框架快速入门
![img](https://chu1204505056.gitee.io/vabBooks/img/ewm.png)
## 安装
```bash
# 克隆项目
git clone https://github.com/chuzhixin/vue-admin-beautiful.git
# 进入项目目录
npm vue-admin-beautiful
# 安装依赖
npm i
# 本地开发 启动项目
cnpm run serve
```
#### github 标星增长量统计
[![Stargazers over time](https://starcharts.herokuapp.com/chuzhixin/vue-admin-beautiful.svg)](https://github.com/chuzhixin/vue-admin-beautiful)
#### 开发者评级
[![chuzhixin's github stats](https://github-readme-stats.vercel.app/api?username=chuzhixin)](https://github.com/chuzhixin/vue-admin-beautiful)
This diff is collapsed. Click to expand it.
# Security Policy
## Supported Versions
Use this section to tell people about which versions of your project are
currently being supported with security updates.
| Version | Supported |
| ------- | ------------------ |
| 5.1.x | :white_check_mark: |
| 5.0.x | :x: |
| 4.0.x | :white_check_mark: |
| < 4.0 | :x: |
## Reporting a Vulnerability
Use this section to tell people how to report a vulnerability.
Tell them where to go, how often they can expect to get an update on a
reported vulnerability, what to expect if the vulnerability is accepted or
declined, etc.
module.exports = {
presets: ["@vue/cli-plugin-babel/preset"],
};
#!/usr/bin/env bash
set -e
npm run build
cd dist
touch .nojekyll
git init
git add -A
git commit -m '🎉🎉🎉仓库重置到2020年9月29日,Vue2.6最后一个版本,之前版本不再支持,具体请查阅文档,Vue 3.0版本请耐心等待!!!'
git push -f "https://${access_token}@gitee.com/chu1204505056/vue-admin-beautiful.git" master:gh-pages
start "https://gitee.com/chu1204505056/vue-admin-beautiful/pages"
git push -f "https://${access_token}@github.com/chuzhixin/vue-admin-beautiful.git" master:gh-pages
cd -
exec /bin/bash
###/changeLog/getList###mockServer
POST http://localhost:80/mock-server/changeLog/getList
Content-Type: application/x-www-form-urlencoded
###
mockServer
###/colorfulIcon/list###
POST http://localhost:80/mock-server/colorfulIcon/list
Content-Type: application/x-www-form-urlencoded
###mockServer
###/menu/navigate###
POST http://localhost:80/mock-server/menu/navigate
Content-Type: application/x-www-form-urlenmockServer
###
###/icon/list###
POST http://localhost:80/mock-server/icon/mockServer
Content-Type: application/x-www-form-urlencoded
###
###/face/list###mockServer
POST http://localhost:80/mock-server/face/list
Content-Type: application/x-www-form-urlencoded
###
mockServer
###/table/list###
POST http://localhost:80/mock-server/table/list
Content-Type: application/x-www-form-urlencoded
###mockServer
###/remixicon/getList###
POST http://localhost:80/mock-server/remixicon/getList
Content-Type: application/x-www-form-urlenmockServer
###
###/publicKey###
POST http://localhost:80/mock-server/pumockServer
Content-Type: application/x-www-form-urlencoded
###
###/tree/list###mockServer
POST http://localhost:80/mock-server/tree/list
Content-Type: application/x-www-form-urlencoded
###
mockServer
###/upload###
POST http://localhost:80/mock-server/upload
Content-Type: application/x-www-form-urlencoded
###mockServer
###/login###
POST http://localhost:80/mock-server/login
Content-Type: application/x-www-form-urlenmockServer
###
###/waterfall/list###
POST http://localhost:80/mock-server/waterfall/list
Content-Type: application/x-www-form-urlencoded
###
###/logout###
POST http://localhost:80/mock-server/logout
Content-Type: application/x-www-form-urlencoded
###
###/userInfo###
POST http://localhost:80/mock-server/userInfo
Content-Type: application/x-www-form-urlencoded
###
This diff is collapsed. Click to expand it.
const data = [
{
title: "vue-admin-beautiful-pro beta版本已发布,点我提前体验",
url: "https://chu1204505056.gitee.io/vue-admin-beautiful-pro/#/index",
},
];
module.exports = [
{
url: "/ad/getList",
type: "get",
response() {
return {
code: 200,
msg: "success",
data,
};
},
},
];
const data = [
{
name: "奉/fendou飘逸的梦",
qq: "812770127",
excuse: "上来就开骂,不可原谅",
},
{
name: "江荻",
qq: "2324945654",
excuse: "上来就开骂,不可原谅",
},
{
name: "Diamond",
qq: "494904935",
excuse: "跟我道歉可以选择原谅",
},
{
name: "Mr、无涯",
qq: "2198457489",
excuse: "已原谅",
},
{
name: "玩世不恭丶江小白",
qq: "1779263221",
excuse: "睁眼说瞎话",
},
{
name: "福州客家网络科技有限公司(潘芳林等兄弟二人)",
qq: "1409198410、1778486252",
excuse:
"剽窃、破解框架授权并发布到网上还伪装成善人,公开道歉并尊重我的劳动成果可以选择原谅",
},
{
name: "willina",
qq: "405522648",
excuse:
"上来就开骂道:You and your git submit are just a rubbish,不可原谅",
},
{
name: "7(赵海鹏)",
qq: "252334666",
excuse: "欺骗两个善良的小姑娘,做完项目不付70%的尾款,强烈抵制",
},
{
name: "生活,一半记忆.一半继续",
qq: "252667193",
excuse: "30多岁,不学无术,造谣抹黑,不可原谅",
},
{
name: "AIRLOO",
qq: "5971794",
excuse: "已原谅",
},
{
name: "master Z",
qq: "1832819123",
excuse: "不尊重别人的劳动成果,认为开源就得无偿替他服务,不可原谅",
},
{
name: "想象中。。。",
qq: "329492979",
excuse: "不尊重别人的劳动成果,认为开源就得无偿替他服务,不可原谅",
},
{
name: "苏潍—菏泽微智科技",
qq: "328580081",
excuse: "无言以对",
},
{
name: "罗阳",
qq: "1320168680",
excuse: "不尊重别人的劳动成果,认为开源就得无偿替他服务,不可原谅",
},
];
module.exports = [
{
url: "/blacklist/getList",
type: "post",
response() {
return {
code: 200,
msg: "success",
data,
};
},
},
];
const data = [
{
content: "在github上获得了第一个star,感恩一位名叫Bequiet2014的github用户",
timestamp: "2020-03-23",
},
{
content: "增加更换主题功能",
timestamp: "2020-04-10",
},
{
content: "大幅精简代码",
timestamp: "2020-04-14",
},
{
content: "修复群友反馈的bug",
timestamp: "2020-04-16",
},
{
content: "剔除maptalks",
timestamp: "2020-04-17",
},
{
content:
"换行符统一修改为lf 支持苹果 linux windows协同开发 强制开启最严格eslint规则 不要哭 严格是有好处的",
timestamp: "2020-04-17",
},
{
content: "彻底完成手机端适配,记录这一天熬夜到了晚上三点",
timestamp: "2020-04-18",
},
{
content:
"删除babel-polyfill 提高打包速度 减少压缩体积(放弃ie是这个项目做出的最伟大的决定)",
timestamp: "2020-04-18",
},
{
content: "源码精简至800k",
timestamp: "2020-04-19",
},
{
content: "添加视频播放器组件",
timestamp: "2020-04-20",
},
{
content: "修复路由懒加载 完善主题配色",
timestamp: "2020-04-22",
},
{
content: "修复全局axios拦截 加快动画展示效果 修改登录页样式",
timestamp: "2020-04-24",
},
{
content: "简化权限与登录逻辑 更新mockServer",
timestamp: "2020-04-25",
},
{
content: "优化登录退出逻辑 代码更清晰 退出不再重载网页 改为重载路由形式",
timestamp: "2020-04-26",
},
{
content: "无端的指责只会让我更加努力 修复sidebar 简化permission",
timestamp: "2020-04-28",
},
{
content: "又是一个深夜 实现了表格增删改查的一键生成",
timestamp: "2020-04-30",
},
{
content: "大幅优化tagsview标签动画",
timestamp: "2020-05-02",
},
{
content: "三种图标组件实现mock模拟分页",
timestamp: "2020-05-03",
},
{
content: "添加了markdown编辑器组件",
timestamp: "2020-05-04",
},
{
content: "添加stylelint-plus自动规整排序样式",
timestamp: "2020-05-06",
},
{
content: "添加商城模板",
timestamp: "2020-05-12",
},
{
content: "github标星超过1000 感恩",
timestamp: "2020-05-13",
},
{
content: "添加验证码组件",
timestamp: "2020-05-14",
},
{
content: "修复横向菜单bug",
timestamp: "2020-05-16",
},
{
content: "又被人骂了 挺好的 让我下定决心重写了tagsBar",
timestamp: "2020-05-20",
},
{
content: "仿ant-design 添加雪花屏",
timestamp: "2020-05-26",
},
{
content: "添加人员管理模块",
timestamp: "2020-06-02",
},
{
content: "github标星超过2000 感恩",
timestamp: "2020-06-03",
},
{
content: "添加炫酷地图组件",
timestamp: "2020-06-11",
},
{
content: "抽离更多公共配置,框架使用更顺手",
timestamp: "2020-06-19",
},
{
content: "彻底完成了tagsbar多标签页的重构",
timestamp: "2020-06-22",
},
{
content: "感恩github标星过3.0K 祝大家端午节快乐",
timestamp: "2020-06-25",
},
{
content: "彻底重构了SideBar与TopBar 大幅精简dom渲染逻辑 全球首发",
timestamp: "2020-06-25",
},
{
content: "添加菜单管理",
timestamp: "2020-07-7",
},
{
content: "首次采用sass-loader 9.0写法,感谢github用户 shaonialife",
timestamp: "2020-07-7",
},
{
content: "添加vue-amap组件",
timestamp: "2020-07-11",
},
{
content: "修改zx-layouts引入方式",
timestamp: "2020-07-15",
},
{
content:
"记录这一天vue-admin-beautiful在插件市场、百度已花费超过1万元广告费用,希望一切都值得",
timestamp: "2020-07-18",
},
{
content: "主题配置添加海洋之心、绿荫草场、荣耀典藏、暗黑之子模式",
timestamp: "2020-07-18",
},
{
content: "全局axios请求全面支持Status Code拦截处理",
timestamp: "2020-07-29",
},
{
content: "重构全局loadding加载代码",
timestamp: "2020-07-31",
},
{
content: "升级stylelint自动排序功能",
timestamp: "2020-08-25",
},
{
content: "修复视频播放器组件重载路由失效的bug",
timestamp: "2020-09-03",
},
{
content: "修复极个别情况image-loader打包报错",
timestamp: "2020-09-18",
},
{
content: "全网首个基于vue3.0开发的admin框架已发布,具体请访问github",
timestamp: "2020-09-22",
},
];
module.exports = [
{
url: "/changeLog/getList",
type: "post",
response() {
return {
code: 200,
msg: "success",
totalCount: 999,
data: data,
};
},
},
];
const data = [
"alphabetical_sorting",
"advance",
"address_book",
"alphabetical_sorting",
"advertising",
"alarm_clock",
"area_chart",
"approval",
"answers",
"approve",
"assistant",
"audio_file",
"automotive",
"automatic",
"bad_decision",
"bar_chart",
"bearish",
"biomass",
"biohazard",
"binoculars",
"bookmark",
"briefcase",
"biotech",
"broken_link",
"business",
"bullish",
"business_contact",
"businesswoman",
"cable_release",
"calculator",
"businessman",
"calendar",
"butting_in",
"call_transfer",
"callback",
"camcorder",
"camera",
"camcorder_pro",
"cancel",
"camera_addon",
"camera_identificatio",
"capacitor",
"candle_sticks",
"checkmark",
"circuit",
"charge_battery",
"clear_filters",
"clapperboard",
"clock",
"close_up_mode",
"collaboration",
"cell_phone",
"collapse",
"collect",
"cloth",
"combo_chart",
"comments",
"conference_call",
"compact_camera",
"contacts",
"copyleft",
"copyright",
"crystal_oscillator",
"cursor",
"currency_exchange",
"customer_support",
"dam",
"data_backup",
"data_configuration",
"data_encryption",
"data_protection",
"data_recovery",
"database",
"data_sheet",
"debt",
"decision",
"delete_column",
"delete_database",
"department",
"delete_row",
"deployment",
"dislike",
"disapprove",
"disclaimer",
"display",
"document",
"do_not_insert",
"do_not_mix",
"do_not_inhale",
"donate",
"down",
"doughnut_chart",
"down_left",
"down_right",
"download",
"edit_image",
"electrical_sensor",
"electrical_threshold",
"electricity",
"electro_devices",
"electronics",
"empty_battery",
"empty_filter",
"empty_trash",
"end_call",
"engineering",
"entering_heaven_aliv",
"expand",
"export",
"expired",
"factory",
"factory_breakdown",
"external",
"faq",
"feed_in",
"file",
"feedback",
"film",
"filled_filter",
"filing_cabinet",
"film_reel",
"flash_auto",
"fine_print",
"flash_off",
"flash_on",
"flow_chart",
"folder",
"frame",
"full_battery",
"full_trash",
"gallery",
"generic_sorting_asc",
"generic_sorting_desc",
"genealogy",
"globe",
"good_decision",
"headset",
"grid",
"graduation_cap",
"heat_map",
"high_priority",
"high_battery",
"image_file",
"home",
"idea",
"import",
"in_transit",
"integrated_webcam",
"inspection",
"invite",
"internal",
"ipad",
"info",
"iphone",
"kindle",
"key",
"landscape",
"left",
"left_down",
"left_up",
"leave",
"like_placeholder",
"light_at_the_end_of_",
"library",
"line_chart",
"link",
"like",
"lock",
"list",
"lock_landscape",
"low_battery",
"lock_portrait",
"low_priority",
"make_decision",
"medium_priority",
"manager",
"menu",
"middle_battery",
"minus",
"missed_call",
"mind_map",
"mms",
"multiple_cameras",
"money_transfer",
"music",
"multiple_devices",
"multiple_smartphones",
"multiple_inputs",
"negative_dynamic",
"neutral_decision",
"night_landscape",
"news",
"neutral_trading",
"night_portrait",
"no_idea",
"next",
"no_video",
"nook",
"ok",
"org_unit",
"opened_folder",
"old_time_camera",
"online_support",
"organization",
"package",
"paid",
"parallel_tasks",
"overtime",
"panorama",
"phone",
"phone_android",
"photo_reel",
"pie_chart",
"picture",
"planner",
"plus",
"podium_with_audience",
"podium_without_speak",
"podium_with_speaker",
"previous",
"portrait_mode",
"positive_dynamic",
"privacy",
"process",
"puzzle",
"questions",
"print",
"radar_plot",
"rating",
"ratings",
"reading",
"redo",
"reading_ebook",
"refresh",
"registered_trademark",
"right",
"reuse",
"remove_image",
"right_down",
"right_up",
"rotate_to_portrait",
"rules",
"rotate_camera",
"rotate_to_landscape",
"ruler",
"scatter_plot",
"search",
"safe",
"self_service_kiosk",
"selfie",
"serial_tasks",
"sales_performance",
"settings",
"services",
"share",
"shipped",
"sim_card",
"shop",
"service_mark",
"sim_card_chip",
"signature",
"smartphone_tablet",
"sound_recording_copy",
"sms",
"speaker",
"slr_back_side",
"start",
"stack_of_photos",
"statistics",
"sports_mode",
"support",
"synchronize",
"switch_camera",
"survey",
"tablet_android",
"template",
"trademark",
"todo_list",
"touchscreen_smartpho",
"timeline",
"tree_structure",
"undo",
"up_left",
"two_smartphones",
"unlock",
"up",
"up_right",
"upload",
"video_call",
"video_file",
"view_details",
"video_projector",
"vip",
"voice_presentation",
"webcam",
"voicemail",
"workflow",
"about",
"accept_database",
"add_image",
"add_column",
"add_database",
"add_row",
];
module.exports = [
{
url: "/colorfulIcon/getList",
type: "post",
response(config) {
const { title, pageNo = 1, pageSize = 72 } = config.body;
let mockList = data.filter((item) => {
if (title && item.indexOf(title) < 0) return false;
return true;
});
const pageList = mockList.filter(
(item, index) =>
index < pageSize * pageNo && index >= pageSize * (pageNo - 1)
);
return {
code: 200,
msg: "success",
totalCount: mockList.length,
data: pageList,
};
},
},
];
const { mock } = require("mockjs");
module.exports = [
{
url: "/goodsDetail/getList",
type: "post",
response(config) {
return {
code: 200,
msg: "success",
totalCount: 999,
data: mock({
"data|10": [
{
id: "@id",
},
],
}).data,
};
},
},
{
url: "/goodsDetail/doEdit",
type: "post",
response(config) {
return {
code: 200,
msg: "模拟保存成功",
};
},
},
{
url: "/goodsDetail/doDelete",
type: "post",
response(config) {
return {
code: 200,
msg: "模拟删除成功",
};
},
},
];
const { mock } = require("mockjs");
const List = [];
const count = 999;
let num = 0;
for (let i = 0; i < count; i++) {
List.push(
mock({
uuid: "@uuid",
image: `https://picsum.photos/300/600?random=${num++}`,
title: "@ctitle",
description: "@csentence",
link: "https://www.baidu.com",
price: "@integer(100, 500)",
"status|1": [1, 0],
"isRecommend|1": [1, 0],
})
);
}
module.exports = [
{
url: "/goodsList/getList",
type: "post",
response(config) {
const { title = "", pageNo = 1, pageSize = 20 } = config.body;
let mockList = List.filter((item) => {
if (title && item.title.indexOf(title) < 0) return false;
return true;
});
const pageList = mockList.filter(
(item, index) =>
index < pageSize * pageNo && index >= pageSize * (pageNo - 1)
);
return {
code: 200,
msg: "success",
totalCount: count,
data: pageList,
};
},
},
];
module.exports = [
{
url: "/menuManagement/getTree",
type: "post",
response(config) {
return {
code: 200,
msg: "success",
totalCount: 999,
data: [
{
id: "root",
label: "全部角色",
children: [
{
id: "@id",
permission: "admin",
label: "admin角色",
},
{
id: "@id",
permission: "editor",
label: "editor角色",
},
],
},
],
};
},
},
{
url: "/menuManagement/doEdit",
type: "post",
response(config) {
return {
code: 200,
msg: "模拟保存成功",
};
},
},
{
url: "/menuManagement/doDelete",
type: "post",
response(config) {
return {
code: 200,
msg: "模拟删除成功",
};
},
},
];
const data = [
{
title: "究竟是什么样的终点,才配得上这一路的颠沛流离。。。",
closable: false,
type: "success",
},
{
title:
"作者寄语:感谢Star,感恩相遇,愿世间美好与我们环环相扣,加油!屏幕前的我们,打破桎梏,坚守初心。其实人生改变命运的机会并没有太多,我们并不是不优秀,我们也并不是一无是处,我们也希望驻足山巅被众人仰望,也许我们缺少的只是一个机会,缺少的只是生命中的导师,我希望这个框架帮助到更多的人,希望有一天,我们面试的时候不再胆怯,希望有一天别人看到的不仅仅是你的努力,还有你的功成名就,出人头地。",
closable: false,
type: "warning",
},
{
title:
"鸣谢:尤雨溪、蒋豪群、element-ui、唐金州、花裤衩、贤心、iView、uView的开源项目给我带来的很多的灵感,弱小的人才习惯嘲讽与否定,内心强大的人从不吝啬赞美与鼓励,人生在世,得到每个人的认可几乎是痴心妄想,我也只是一条略懂前端的咸鱼,可我仍一直怀揣着改变世界的梦想,希望我们每个人,不管过程怎样,结局都是美好的。",
closable: false,
type: "success",
},
{
title:
"随笔:我一直在寻找开源的真谛,我一直再想什么是开源,我一开始觉得免费就是开源,好像又不是。我理解的开源是:你也开源,我也开源,大家一起贡献,相互帮助。我最担心的事情是:我一个小人物,去伺候一众的伸手党,我想,这不是开源该有的氛围。我还太年轻,不懂什么是格局,我只知道,无私的帮助他人,能给我带来快乐,却不能给我带来收入,当然,有时候,快乐对我来说就已经足够了。可惜我是一个人,没有精力帮助到每一个人,可惜这个世界需要赚钱,才能过上平凡的生活,可惜了我的梦想,这个物欲横流的时代,理想主义的我们,即使内心坚决如铁,也似乎寸步难行。",
closable: false,
type: "success",
},
];
module.exports = [
{
url: "/notice/getList",
type: "post",
response() {
return {
code: 200,
msg: "success",
data,
};
},
},
];
const { mock } = require("mockjs");
module.exports = [
{
url: "/personalCenter/getList",
type: "post",
response(config) {
return {
code: 200,
msg: "success",
totalCount: 999,
data: mock({
"data|10": [
{
id: "@id",
},
],
}).data,
};
},
},
{
url: "/personalCenter/doEdit",
type: "post",
response(config) {
return {
code: 200,
msg: "模拟保存成功",
};
},
},
{
url: "/personalCenter/doDelete",
type: "post",
response(config) {
return {
code: 200,
msg: "模拟删除成功",
};
},
},
];
const totalCount = 2;
const List = [
{
id: "@id",
permission: "admin",
},
{
id: "@id",
permission: "editor",
},
];
module.exports = [
{
url: "/roleManagement/getList",
type: "post",
response(config) {
const { title = "", pageNo = 1, pageSize = 20 } = config.body;
let mockList = List.filter((item) => {
return !(title && item.title.indexOf(title) < 0);
});
const pageList = mockList.filter(
(item, index) =>
index < pageSize * pageNo && index >= pageSize * (pageNo - 1)
);
return {
code: 200,
msg: "success",
totalCount,
data: pageList,
};
},
},
{
url: "/roleManagement/doEdit",
type: "post",
response() {
return {
code: 200,
msg: "模拟保存成功",
};
},
},
{
url: "/roleManagement/doDelete",
type: "post",
response() {
return {
code: 200,
msg: "模拟删除成功",
};
},
},
];
const { mock } = require("mockjs");
const { handleRandomImage } = require("../utils");
const List = [];
const count = 999;
for (let i = 0; i < count; i++) {
List.push(
mock({
uuid: "@uuid",
id: "@id",
title: "@csentence(1, 2)",
"status|1": ["published", "draft", "deleted"],
author: "@cname",
datetime: "@datetime",
pageViews: "@integer(300, 5000)",
img: handleRandomImage(200, 200),
smallImg: handleRandomImage(40, 40),
switch: "@boolean",
percent: "@integer(80,99)",
})
);
}
module.exports = [
{
url: "/table/getList",
type: "post",
response(config) {
if (!config.body) {
return {
code: 200,
msg: "success",
totalCount: count,
data: mock({
"data|50": [
{
id: "@id",
title: "@csentence(1, 2)",
"status|1": ["published", "draft", "deleted"],
author: "@cname",
datetime: "@datetime",
pageViews: "@integer(300, 5000)",
img: handleRandomImage(200, 200),
smallImg: handleRandomImage(40, 40),
switch: "@boolean",
percent: "@integer(80,99)",
},
],
}).data,
};
}
const { title = "", pageNo = 1, pageSize = 20 } = config.body;
let mockList = List.filter((item) => {
return !(title && item.title.indexOf(title) < 0);
});
const pageList = mockList.filter(
(item, index) =>
index < pageSize * pageNo && index >= pageSize * (pageNo - 1)
);
return {
code: 200,
msg: "success",
totalCount: count,
data: pageList,
};
},
},
{
url: "/table/doEdit",
type: "post",
response() {
return {
code: 200,
msg: "模拟保存成功",
};
},
},
{
url: "/table/doDelete",
type: "post",
response() {
return {
code: 200,
msg: "模拟删除成功",
};
},
},
];
const data = [
{
id: "1",
parentId: "0",
name: "vue-admin-beautiful科技有限公司",
title: "vue-admin-beautiful科技有限公司",
text: "vue-admin-beautiful科技有限公司",
value: "1",
rank: 1,
children: [
{
id: "32816b88ff72423f960e7d492a386131",
parentId: "1",
name: "1103工作室",
title: "1103工作室",
text: "1103工作室",
value: "32816b88ff72423f960e7d492a386131",
rank: 2,
children: [
{
id: "9e11afc35d55475fb0bd3164b9684cbe",
parentId: "32816b88ff72423f960e7d492a386131",
name: "前端牛逼plus小组",
title: "前端牛逼plus小组",
text: "前端牛逼plus小组",
value: "9e11afc35d55475fb0bd3164b9684cbe",
rank: 3,
children: [
{
id: "4cc1b04635e4444292526c5391699077",
parentId: "9e11afc35d55475fb0bd3164b9684cbe",
name: "组员chuzhixin",
title: "组员chuzhixin",
text: "组员chuzhixin",
value: "4cc1b04635e4444292526c5391699077",
rank: 4,
children: [],
},
],
},
],
},
],
},
];
module.exports = [
{
url: "/tree/list",
type: "post",
response() {
return { code: 200, msg: "success", data };
},
},
];
const data = [];
module.exports = [
{
url: "/upload",
type: "post",
response(config) {
return {
code: 200,
msg: "success",
data: data,
};
},
},
];
const accessTokens = {
admin: "admin-accessToken",
editor: "editor-accessToken",
test: "test-accessToken",
};
module.exports = [
{
url: "/publicKey",
type: "post",
response() {
return {
code: 200,
msg: "success",
data: {
mockServer: true,
publicKey:
"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDBT2vr+dhZElF73FJ6xiP181txKWUSNLPQQlid6DUJhGAOZblluafIdLmnUyKE8mMHhT3R+Ib3ssZcJku6Hn72yHYj/qPkCGFv0eFo7G+GJfDIUeDyalBN0QsuiE/XzPHJBuJDfRArOiWvH0BXOv5kpeXSXM8yTt5Na1jAYSiQ/wIDAQAB",
},
};
},
},
{
url: "/login",
type: "post",
response(config) {
const { username } = config.body;
const accessToken = accessTokens[username];
if (!accessToken) {
return {
code: 500,
msg: "帐户或密码不正确。",
};
}
return {
code: 200,
msg: "success",
data: { accessToken },
};
},
},
{
url: "/register",
type: "post",
response() {
return {
code: 200,
msg: "模拟注册成功",
};
},
},
{
url: "/userInfo",
type: "post",
response(config) {
const { accessToken } = config.body;
let permissions = ["admin"];
let username = "admin";
if ("admin-accessToken" === accessToken) {
permissions = ["admin"];
username = "admin";
}
if ("editor-accessToken" === accessToken) {
permissions = ["editor"];
username = "editor";
}
if ("test-accessToken" === accessToken) {
permissions = ["admin", "editor"];
username = "test";
}
return {
code: 200,
msg: "success",
data: {
permissions,
username,
"avatar|1": [
"https://i.gtimg.cn/club/item/face/img/2/15922_100.gif",
"https://i.gtimg.cn/club/item/face/img/8/15918_100.gif",
],
},
};
},
},
{
url: "/logout",
type: "post",
response() {
return {
code: 200,
msg: "success",
};
},
},
];
const totalCount = 3;
const List = [
{
id: "@id",
username: "admin",
password: "admin",
email: "@email",
permissions: ["admin"],
datatime: "@datetime",
},
{
id: "@id",
username: "editor",
password: "editor",
email: "@email",
permissions: ["editor"],
datatime: "@datetime",
},
{
id: "@id",
username: "test",
password: "test",
email: "@email",
permissions: ["admin", "editor"],
datatime: "@datetime",
},
];
module.exports = [
{
url: "/userManagement/getList",
type: "post",
response(config) {
const { title = "", pageNo = 1, pageSize = 20 } = config.body;
let mockList = List.filter((item) => {
if (title && item.title.indexOf(title) < 0) return false;
return true;
});
const pageList = mockList.filter(
(item, index) =>
index < pageSize * pageNo && index >= pageSize * (pageNo - 1)
);
return {
code: 200,
msg: "success",
totalCount,
data: pageList,
};
},
},
{
url: "/userManagement/doEdit",
type: "post",
response() {
return {
code: 200,
msg: "模拟保存成功",
};
},
},
{
url: "/userManagement/doDelete",
type: "post",
response() {
return {
code: 200,
msg: "模拟删除成功",
};
},
},
];
/**
* @copyright chuzhixin 1204505056@qq.com
* @description 导入所有 controller 模块,npm run serve时在node环境中自动输出controller文件夹下Mock接口,请勿修改。
*/
const { handleMockArray } = require("./utils");
const mocks = [];
const mockArray = handleMockArray();
mockArray.forEach((item) => {
const obj = require(item);
mocks.push(...obj);
});
module.exports = {
mocks,
};
const chokidar = require("chokidar");
const bodyParser = require("body-parser");
const chalk = require("chalk");
const path = require("path");
const Mock = require("mockjs");
const { baseURL } = require("../src/config/settings");
const mockDir = path.join(process.cwd(), "mock");
/**
*
* @param app
* @returns {{mockStartIndex: number, mockRoutesLength: number}}
*/
const registerRoutes = (app) => {
let mockLastIndex;
const { mocks } = require("./index.js");
const mocksForServer = mocks.map((route) => {
return responseFake(route.url, route.type, route.response);
});
for (const mock of mocksForServer) {
app[mock.type](mock.url, mock.response);
mockLastIndex = app._router.stack.length;
}
const mockRoutesLength = Object.keys(mocksForServer).length;
return {
mockRoutesLength: mockRoutesLength,
mockStartIndex: mockLastIndex - mockRoutesLength,
};
};
/**
*
* @param url
* @param type
* @param respond
* @returns {{response(*=, *=): void, type: (*|string), url: RegExp}}
*/
const responseFake = (url, type, respond) => {
return {
url: new RegExp(`${baseURL}${url}`),
type: type || "get",
response(req, res) {
res.status(200);
if (JSON.stringify(req.body) !== "{}") {
console.log(chalk.green(`> 请求地址:${req.path}`));
console.log(chalk.green(`> 请求参数:${JSON.stringify(req.body)}\n`));
} else {
console.log(chalk.green(`> 请求地址:${req.path}\n`));
}
res.json(
Mock.mock(respond instanceof Function ? respond(req, res) : respond)
);
},
};
};
/**
*
* @param app
*/
module.exports = (app) => {
app.use(bodyParser.json());
app.use(
bodyParser.urlencoded({
extended: true,
})
);
const mockRoutes = registerRoutes(app);
let mockRoutesLength = mockRoutes.mockRoutesLength;
let mockStartIndex = mockRoutes.mockStartIndex;
chokidar
.watch(mockDir, {
ignored: /mock-server/,
ignoreInitial: true,
})
.on("all", (event) => {
if (event === "change" || event === "add") {
try {
app._router.stack.splice(mockStartIndex, mockRoutesLength);
Object.keys(require.cache).forEach((item) => {
if (item.includes(mockDir)) {
delete require.cache[require.resolve(item)];
}
});
const mockRoutes = registerRoutes(app);
mockRoutesLength = mockRoutes.mockRoutesLength;
mockStartIndex = mockRoutes.mockStartIndex;
} catch (error) {
console.log(chalk.red(error));
}
}
});
};
const { Random } = require("mockjs");
const { join } = require("path");
const fs = require("fs");
/**
* @copyright chuzhixin 1204505056@qq.com
* @description 随机生成图片url。
* @param width
* @param height
* @returns {string}
*/
function handleRandomImage(width = 50, height = 50) {
return `https://picsum.photos/${width}/${height}?random=${Random.guid()}`;
}
/**
* @copyright chuzhixin 1204505056@qq.com
* @description 处理所有 controller 模块,npm run serve时在node环境中自动输出controller文件夹下Mock接口,请勿修改。
* @returns {[]}
*/
function handleMockArray() {
const mockArray = [];
const getFiles = (jsonPath) => {
const jsonFiles = [];
const findJsonFile = (path) => {
const files = fs.readdirSync(path);
files.forEach((item) => {
const fPath = join(path, item);
const stat = fs.statSync(fPath);
if (stat.isDirectory() === true) findJsonFile(item);
if (stat.isFile() === true) jsonFiles.push(item);
});
};
findJsonFile(jsonPath);
jsonFiles.forEach((item) => mockArray.push(`./controller/${item}`));
};
getFiles("mock/controller");
return mockArray;
}
module.exports = {
handleRandomImage,
handleMockArray,
};
{
"name": "vue-admin-beautiful",
"version": "1.0.0",
"author": "chuzhixin 1204505056@qq.com",
"participants": [],
"homepage": "https://chu1204505056.gitee.io/vue-admin-beautiful",
"publishConfig": {
"registry": "https://npm.pkg.github.com/"
},
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"build:report": "vue-cli-service build --report",
"globle": "npm install -g cnpm --registry=https://registry.npm.taobao.org&&cnpm i rimraf npm-check-updates nrm -g&&rimraf node_modules&&cnpm i",
"lint": "vue-cli-service lint --fix",
"lint:style": "stylelint-config-prettier-check",
"inspect": "vue-cli-service inspect",
"template": "plop",
"clear": "rimraf node_modules&&cnpm i&&increase-memory-limit",
"use:npm": "nrm use npm",
"use:taobao": "nrm use taobao",
"update": "ncu -u --concurrency 10 --timeout 80000&&cnpm i",
"update:globle": "ncu -g --concurrency 10 --timeout 80000",
"svgo": "svgo -f src/remixIcon/svg --config=svgo.yml",
"push": "start ./push.sh",
"deploy": "start ./deploy.sh",
"increase-memory-limit": "increase-memory-limit"
},
"repository": {
"type": "git",
"url": "git+https://github.com/chuzhixin/vue-admin-beautiful.git"
},
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"src/**/*.{js,vue}": [
"eslint --fix",
"git add"
]
},
"dependencies": {
"axios": "^0.20.0",
"better-scroll": "^2.0.4",
"clipboard": "^2.0.6",
"codemirror": "^5.58.1",
"core-js": "^3.6.5",
"dayjs": "^1.9.0",
"echarts": "^4.9.0",
"echarts-wordcloud": "^1.1.3",
"element-ui": "^2.13.2",
"file-saver": "^2.0.2",
"js-cookie": "^2.2.1",
"jsencrypt": "^3.0.0-rc.1",
"jsonlint": "^1.6.3",
"lodash": "^4.17.20",
"maptalks": "^0.49.1",
"mapv": "^2.0.57",
"nprogress": "^0.2.0",
"qs": "^6.9.4",
"screenfull": "^5.0.2",
"vue": "^2.6.12",
"vue-amap": "^0.5.10",
"vue-echarts": "^5.0.0-beta.0",
"vue-qart": "^2.2.0",
"vue-router": "^3.4.5",
"vuedraggable": "^2.24.1",
"vuex": "^3.5.1",
"zx-comparison": "^1.0.3",
"zx-count": "^0.3.7",
"zx-icon": "^1.1.9",
"zx-keel": "^0.9.4",
"zx-layouts": "^0.6.13",
"zx-magnifie": "^0.4.0",
"zx-markdown-editor": "^0.0.2",
"zx-player": "^1.0.1",
"zx-quill": "^0.0.2",
"zx-templates": "^0.0.22",
"zx-verify": "^0.0.2"
},
"devDependencies": {
"@babel/register": "^7.11.5",
"@vue/cli-plugin-babel": "^4.5.6",
"@vue/cli-plugin-eslint": "^4.5.6",
"@vue/cli-plugin-router": "^4.5.6",
"@vue/cli-plugin-vuex": "^4.5.6",
"@vue/cli-service": "^4.5.6",
"@vue/eslint-config-prettier": "^6.0.0",
"autoprefixer": "^10.0.1",
"babel-eslint": "^10.1.0",
"babel-plugin-dynamic-import-node": "^2.3.3",
"compression-webpack-plugin": "^6.0.2",
"eslint": "^7.10.0",
"eslint-plugin-prettier": "^3.1.4",
"eslint-plugin-vue": "^6.2.2",
"filemanager-webpack-plugin": "^2.0.5",
"husky": "^4.3.0",
"image-webpack-loader": "^7.0.1",
"increase-memory-limit": "^1.0.7",
"lint-staged": "^10.4.0",
"mockjs": "^1.1.0",
"plop": "^2.7.4",
"prettier": "^2.1.2",
"sass": "^1.26.11",
"sass-loader": "^10.0.2",
"script-loader": "^0.7.2",
"stylelint": "^13.7.2",
"stylelint-config-prettier": "^8.0.2",
"stylelint-config-recess-order": "^2.1.0",
"svg-sprite-loader": "^5.0.0",
"svgo": "^1.3.2",
"vue-template-compiler": "^2.6.12",
"webpackbar": "^4.0.0"
},
"keywords": [
"vue",
"admin",
"dashboard",
"element-ui",
"vue-admin",
"element-admin",
"boilerplate",
"admin-template",
"management-system"
],
"engines": {
"node": ">=8.9",
"npm": ">= 3.0.0"
}
}
const viewGenerator = require("zx-templates/view/prompt");
const curdGenerator = require("zx-templates/curd/prompt");
const componentGenerator = require("zx-templates/component/prompt");
const mockGenerator = require("zx-templates/mock/prompt");
const vuexGenerator = require("zx-templates/vuex/prompt");
module.exports = (plop) => {
plop.setGenerator("view", viewGenerator);
plop.setGenerator("curd", curdGenerator);
plop.setGenerator("component", componentGenerator);
plop.setGenerator("mock&api", mockGenerator);
plop.setGenerator("vuex", vuexGenerator);
};
module.exports = {
printWidth: 80,
tabWidth: 2,
useTabs: false,
semi: true,
singleQuote: false,
quoteProps: "as-needed",
jsxSingleQuote: false,
trailingComma: "es5",
bracketSpacing: true,
jsxBracketSameLine: false,
arrowParens: "always",
htmlWhitespaceSensitivity: "ignore",
vueIndentScriptAndStyle: true,
endOfLine: "lf",
};
<!DOCTYPE html>
<html lang="zh-cmn-Hans">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
<link rel="icon" href="<%= BASE_URL %>favicon.ico" />
<title><%= VUE_APP_TITLE %></title>
<meta
name="keywords"
content="vab,vab官网,后台管理框架,vue后台管理框架,vue-admin-beautiful,vue-admin-beautiful官网,vue-admin-beautiful文档,vue-element-admin,vue-element-admin官网,vue-element-admin文档,vue-admin,vue-admin官网,vue-admin文档"
/>
<meta
name="description"
content="<%= VUE_APP_TITLE %>官网与文档基于vue-admin-beautiful构建,简称vab(是一款超棒的vue+element中后台前端快速开发框架),QQ群972435319,作者:<%= VUE_APP_AUTHOR %>"
/>
<meta name="author" content="<%= VUE_APP_AUTHOR %>" />
<link rel="stylesheet" href="<%= BASE_URL %>static/css/loading.css" />
<script>
var _hmt = _hmt || [];
(function () {
var hm = document.createElement("script");
hm.src = "https://hm.baidu.com/hm.js?7174bade1219f9cc272e7978f9523fc8";
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(hm, s);
})();
</script>
</head>
<body>
<noscript>
非常抱歉鉴于安全考量,您无法查看<%= VUE_APP_TITLE %>
源代码,该系统基于vue-admin-beautiful开发
</noscript>
<div id="vue-admin-beautiful">
<div class="first-loading-wrp">
<div class="loading-wrp">
<span class="dot dot-spin">
<i></i>
<i></i>
<i></i>
<i></i>
</span>
</div>
<h1><%= VUE_APP_TITLE %></h1>
</div>
</div>
<script>
/^http(s*):\/\//.test(location.href) ||
alert("基于vue-admin-beautiful开发的项目需要部署到服务器下访问");
</script>
</body>
</html>
.first-loading-wrp {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 90vh;
min-height: 90vh;
}
.first-loading-wrp > h1 {
font-size: 30px;
font-weight: bolder;
}
.first-loading-wrp .loading-wrp {
display: flex;
align-items: center;
justify-content: center;
padding: 98px;
}
.dot {
position: relative;
box-sizing: border-box;
display: inline-block;
width: 64px;
height: 64px;
font-size: 64px;
transform: rotate(45deg);
animation: antRotate 1.2s infinite linear;
}
.dot i {
position: absolute;
display: block;
width: 28px;
height: 28px;
background-color: #1890ff;
border-radius: 100%;
opacity: 0.3;
transform: scale(0.75);
transform-origin: 50% 50%;
animation: antSpinMove 1s infinite linear alternate;
}
.dot i:nth-child(1) {
top: 0;
left: 0;
}
.dot i:nth-child(2) {
top: 0;
right: 0;
-webkit-animation-delay: 0.4s;
animation-delay: 0.4s;
}
.dot i:nth-child(3) {
right: 0;
bottom: 0;
-webkit-animation-delay: 0.8s;
animation-delay: 0.8s;
}
.dot i:nth-child(4) {
bottom: 0;
left: 0;
-webkit-animation-delay: 1.2s;
animation-delay: 1.2s;
}
@keyframes antRotate {
to {
-webkit-transform: rotate(405deg);
transform: rotate(405deg);
}
}
@-webkit-keyframes antRotate {
to {
-webkit-transform: rotate(405deg);
transform: rotate(405deg);
}
}
@keyframes antSpinMove {
to {
opacity: 1;
}
}
@-webkit-keyframes antSpinMove {
to {
opacity: 1;
}
}
#!/usr/bin/env bash
set -e
git init
git add -A
git commit -m '🎉🎉🎉仓库重置到2020年9月29日,Vue2.6最后一个版本,之前版本不再支持,具体请查阅文档,Vue 3.0版本即将发布请耐心等待!!!'
git push -f "https://${access_token}@github.com/chuzhixin/vue-admin-beautiful.git" master
exec /bin/bash
<template>
<div id="vue-admin-beautiful">
<router-view />
</div>
</template>
<script>
export default {
name: "App",
mounted() {},
};
</script>
import request from "@/utils/request";
export function getList(data) {
return request({
url: "/ad/getList",
method: "get",
data,
});
}
import request from "@/utils/request";
export function getList(data) {
return request({
url: "/blacklist/getList",
method: "post",
data,
});
}
import request from "@/utils/request";
export function getList(data) {
return request({
url: "/changeLog/getList",
method: "post",
data,
});
}
import request from "@/utils/request";
export function getIconList(data) {
return request({
url: "/colorfulIcon/getList",
method: "post",
data,
});
}
import request from "axios";
export function getRepos(params) {
return request({
url: "https://api.github.com/repos/chuzhixin/vue-admin-beautiful",
method: "get",
params,
timeout: 10000,
});
}
export function getStargazers(params) {
return request({
url:
"https://api.github.com/repos/chuzhixin/vue-admin-beautiful/stargazers",
method: "get",
params,
timeout: 10000,
});
}
import request from "@/utils/request";
export function getList(data) {
return request({
url: "/goodsDetail/getList",
method: "post",
data,
});
}
import request from "@/utils/request";
export function getList(data) {
return request({
url: "/goodsList/getList",
method: "post",
data,
});
}
import request from "@/utils/request";
export function getIconList(data) {
return request({
url: "/icon/getList",
method: "post",
data,
});
}
import request from "axios";
export function getList() {
return request({
url: "https://cdn.jsdelivr.net/gh/prettier/prettier@master/docs/options.md",
method: "get",
});
}
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,
});
}
import request from "@/utils/request";
export function getNoticeList() {
return request({
url: "/notice/getList",
method: "post",
});
}
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,
});
}
import request from "@/utils/request";
export function getPublicKey() {
return request({
url: "/publicKey",
method: "post",
});
}
import request from "@/utils/request";
export function getIconList(data) {
return request({
url: "/remixIcon/getList",
method: "post",
data,
});
}
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,
});
}
import request from "@/utils/request";
export function getRouterList(data) {
return request({
url: "/menu/navigate",
method: "post",
data,
});
}
import request from "@/utils/request";
export function getList(data) {
return request({
url: "/table/getList",
method: "post",
data,
});
}
export function doEdit(data) {
return request({
url: "/table/doEdit",
method: "post",
data,
});
}
export function doDelete(data) {
return request({
url: "/table/doDelete",
method: "post",
data,
});
}
import request from "@/utils/request";
export function getTreeList(data) {
return request({
url: "/tree/list",
method: "post",
data,
});
}
import request from "@/utils/request";
import { encryptedData } from "@/utils/encrypt";
import { loginRSA, tokenName } from "@/config/settings";
export async function login(data) {
if (loginRSA) {
data = await encryptedData(data);
}
return request({
url: "/login",
method: "post",
data,
});
}
export function getUserInfo(accessToken) {
return request({
url: "/userInfo",
method: "post",
data: {
[tokenName]: accessToken,
},
});
}
export function logout() {
return request({
url: "/logout",
method: "post",
});
}
export function register() {
return request({
url: "/register",
method: "post",
});
}
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,
});
}
import Vue from "vue";
import { ColorfullIcon } from "@/layouts/components";
Vue.component("vab-colorful-icon", ColorfullIcon);
const req = require.context("./svg", false, /\.svg$/),
requireAll = (requireContext) => {
/*let a = requireContext.keys().map(requireContext);
let arr = [];
for (let i = 0; i < a.length; i++) {
console.log();
let icon = a[i].default.id;
arr.push(icon);
}
console.log(JSON.stringify(arr));*/
return requireContext.keys().map(requireContext);
};
requireAll(req);
<svg class="icon" width="128" height="128" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg"><path d="M358.4 853.333H245.333l-23.466 64H147.2l121.6-324.266h61.867l119.466 324.266h-68.266l-23.467-64zm-98.133-57.6h81.066l-40.533-121.6-40.533 121.6zm4.266-418.133h162.134v53.333H179.2V390.4L341.333 160H179.2v-53.333h243.2v36.266L264.533 377.6z" fill="#2196F3"/><path d="M810.667 704V106.667h-85.334V704h-128L768 917.333 938.667 704z" fill="#546E7A"/></svg>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<svg version="1.1" id="Layer_1"
xmlns="http://www.w3.org/2000/svg"
width="550px" height="400px"
xml:space="preserve">
<g id="PathID_1" transform="matrix(10.7099, 0, 0, 10.7099, 76.4, 396.15)" opacity="1">
<path style="fill: #41b882; fill-opacity: 1;" d="M3.75 -36.65L18.4 -36.65Q22.75 -36.65 24.85 -36.25Q27 -35.9 28.7 -34.75Q30.4 -33.6 31.5 -31.7Q32.65 -29.8 32.65 -27.4Q32.65 -24.85 31.25 -22.7Q29.85 -20.55 27.5 -19.5Q30.85 -18.5 32.65 -16.15Q34.45 -13.8 34.45 -10.6Q34.45 -8.1 33.25 -5.75Q32.1 -3.4 30.1 -1.95Q28.1 -0.55 25.15 -0.25Q23.3 -0.05 16.2 0L3.75 0L3.75 -36.65M11.15 -30.55L11.15 -22.1L16 -22.1Q20.3 -22.1 21.35 -22.2Q23.25 -22.4 24.35 -23.5Q25.45 -24.6 25.45 -26.35Q25.45 -28.05 24.5 -29.1Q23.55 -30.2 21.7 -30.4Q20.6 -30.55 15.4 -30.55L11.15 -30.55M11.15 -16L11.15 -6.2L18 -6.2Q22 -6.2 23.05 -6.4Q24.7 -6.7 25.75 -7.85Q26.8 -9.05 26.8 -11Q26.8 -12.65 26 -13.8Q25.2 -14.95 23.65 -15.45Q22.15 -16 17.1 -16L11.15 -16" />
</g>
<g id="PathID_2" transform="matrix(10.7099, 0, 0, 10.7099, 76.4, 396.15)" opacity="1">
</g>
<g id="PathID_3" transform="matrix(5.31826, 0, 0, 2.59618, 172.9, 161.55)" opacity="1">
<path style="fill: #35495e; fill-opacity: 1;" d="M3.75 -36.65L17.25 -36.65Q21.8 -36.65 24.2 -35.95Q27.45 -35 29.75 -32.55Q32.05 -30.15 33.25 -26.6Q34.45 -23.1 34.45 -17.95Q34.45 -13.45 33.3 -10.15Q31.95 -6.15 29.4 -3.7Q27.45 -1.8 24.2 -0.75Q21.75 0 17.65 0L3.75 0L3.75 -36.65M11.15 -30.45L11.15 -6.2L16.65 -6.2Q19.75 -6.2 21.1 -6.55Q22.9 -6.95 24.1 -8Q25.3 -9.1 26.05 -11.55Q26.8 -14.05 26.8 -18.3Q26.8 -22.55 26.05 -24.8Q25.3 -27.1 23.95 -28.35Q22.6 -29.65 20.5 -30.1Q18.95 -30.45 14.45 -30.45L11.15 -30.45" />
</g>
<g id="PathID_4" transform="matrix(5.31826, 0, 0, 2.59618, 172.9, 161.55)" opacity="1">
</g>
<g id="PathID_5" transform="matrix(5.78477, 0, 0, 3.1825, 171.7, 333.8)" opacity="1">
<path style="fill: #35495e; fill-opacity: 1;" d="M3.75 -36.65L17.25 -36.65Q21.8 -36.65 24.2 -35.95Q27.45 -35 29.75 -32.55Q32.05 -30.15 33.25 -26.6Q34.45 -23.1 34.45 -17.95Q34.45 -13.45 33.3 -10.15Q31.95 -6.15 29.4 -3.7Q27.45 -1.8 24.2 -0.75Q21.75 0 17.65 0L3.75 0L3.75 -36.65M11.15 -30.45L11.15 -6.2L16.65 -6.2Q19.75 -6.2 21.1 -6.55Q22.9 -6.95 24.1 -8Q25.3 -9.1 26.05 -11.55Q26.8 -14.05 26.8 -18.3Q26.8 -22.55 26.05 -24.8Q25.3 -27.1 23.95 -28.35Q22.6 -29.65 20.5 -30.1Q18.95 -30.45 14.45 -30.45L11.15 -30.45" />
</g>
<g id="PathID_6" transform="matrix(5.78477, 0, 0, 3.1825, 171.7, 333.8)" opacity="1">
</g>
</svg>
<template>
<div class="json-editor">
<label>
<textarea ref="textarea" />
</label>
</div>
</template>
<script>
import CodeMirror from "codemirror";
import "codemirror/addon/lint/lint.css";
import "codemirror/lib/codemirror.css";
import "codemirror/theme/rubyblue.css";
import "codemirror/mode/javascript/javascript";
import "codemirror/addon/lint/lint";
import "codemirror/addon/lint/json-lint";
require("script-loader!jsonlint");
export default {
name: "JsonEditor",
props: {
value: {
type: [Array, Object],
default: () => {
return null;
},
},
},
data() {
return {
jsonEditor: false,
};
},
watch: {
value(value) {
const editorValue = this.jsonEditor.getValue();
if (editorValue) {
this.$emit("change", editorValue);
} else {
this.$baseMessage("JSON不能为空,否则无法生成表格", "error");
}
if (value !== editorValue) {
this.jsonEditor.setValue(JSON.stringify(this.value, null, 2));
}
},
},
mounted() {
this.jsonEditor = CodeMirror.fromTextArea(this.$refs.textarea, {
lineNumbers: true,
mode: "application/json",
gutters: ["CodeMirror-lint-markers"],
theme: "rubyblue",
lint: true,
});
this.jsonEditor.setValue(JSON.stringify(this.value, null, 2));
this.jsonEditor.on("change", (cm) => {
if (this.isJsonString(cm.getValue())) {
this.$emit("change", cm.getValue());
}
});
},
methods: {
getValue() {
return this.jsonEditor.getValue();
},
isJsonString(str) {
try {
if (typeof JSON.parse(str) == "object") {
return true;
}
} catch (e) {}
return false;
},
},
};
</script>
<style scoped>
.json-editor {
position: relative;
height: 100%;
}
.json-editor >>> .CodeMirror {
height: auto;
min-height: calc(100vh - 220px);
}
.json-editor >>> .CodeMirror-scroll {
min-height: calc(100vh - 220px);
}
.json-editor >>> .cm-s-rubyblue span.cm-string {
color: #f08047;
}
.json-editor >>> .cm-s-rubyblue .CodeMirror-gutters {
padding-right: 10px;
/* background: transparent; */
border-right: 1px solid #fff;
}
.json-editor >>> .cm-s-rubyblue.CodeMirror {
/* background: #08233e; */
color: white;
}
</style>
<template>
<div class="select-tree-template">
<el-select
v-model="selectValue"
:clearable="clearable"
:collapse-tags="selectType == 'multiple'"
:multiple="selectType == 'multiple'"
class="vab-tree-select"
value-key="id"
@clear="clearHandle"
@remove-tag="removeTag"
>
<el-option :value="selectKey">
<el-tree
id="treeOption"
ref="treeOption"
:current-node-key="currentNodeKey"
:data="treeOptions"
:default-checked-keys="defaultSelectedKeys"
:default-expanded-keys="defaultSelectedKeys"
:highlight-current="true"
:props="defaultProps"
:show-checkbox="selectType == 'multiple'"
node-key="id"
@check="checkNode"
@node-click="nodeClick"
></el-tree>
</el-option>
</el-select>
</div>
</template>
<script>
export default {
name: "SelectTreeTemplate",
props: {
/* 树形结构数据 */
treeOptions: {
type: Array,
default: () => {
return [];
},
},
/* 单选/多选 */
selectType: {
type: String,
default: () => {
return "single";
},
},
/* 初始选中值key */
selectedKey: {
type: String,
default: () => {
return "";
},
},
/* 初始选中值name */
selectedValue: {
type: String,
default: () => {
return "";
},
},
/* 可做选择的层级 */
selectLevel: {
type: [String, Number],
default: () => {
return "";
},
},
/* 可清空选项 */
clearable: {
type: Boolean,
default: () => {
return true;
},
},
},
data() {
return {
defaultProps: {
children: "children",
label: "name",
},
defaultSelectedKeys: [], //初始选中值数组
currentNodeKey: this.selectedKey,
selectValue:
this.selectType == "multiple"
? this.selectedValue.split(",")
: this.selectedValue, //下拉框选中值label
selectKey:
this.selectType == "multiple"
? this.selectedKey.split(",")
: this.selectedKey, //下拉框选中值value
};
},
mounted() {
const that = this;
this.initTree();
},
methods: {
// 初始化树的值
initTree() {
const that = this;
if (that.selectedKey) {
that.defaultSelectedKeys = that.selectedKey.split(","); // 设置默认展开
if (that.selectType == "single") {
that.$refs.treeOption.setCurrentKey(that.selectedKey); // 设置默认选中
} else {
that.$refs.treeOption.setCheckedKeys(that.defaultSelectedKeys);
}
}
},
// 清除选中
clearHandle() {
const that = this;
this.selectValue = "";
this.selectKey = "";
this.defaultSelectedKeys = [];
this.currentNodeKey = "";
this.clearSelected();
if (that.selectType == "single") {
that.$refs.treeOption.setCurrentKey(""); // 设置默认选中
} else {
that.$refs.treeOption.setCheckedKeys([]);
}
},
/* 清空选中样式 */
clearSelected() {
const allNode = document.querySelectorAll("#treeOption .el-tree-node");
allNode.forEach((element) => element.classList.remove("is-current"));
},
// select多选时移除某项操作
removeTag(val) {
this.$refs.treeOption.setCheckedKeys([]);
},
// 点击叶子节点
nodeClick(data, node, el) {
if (data.rank >= this.selectLevel) {
this.selectValue = data.name;
this.selectKey = data.id;
}
},
// 节点选中操作
checkNode(data, node, el) {
const checkedNodes = this.$refs.treeOption.getCheckedNodes();
const keyArr = [];
const valueArr = [];
checkedNodes.forEach((item) => {
if (item.rank >= this.selectLevel) {
keyArr.push(item.id);
valueArr.push(item.name);
}
});
this.selectValue = valueArr;
this.selectKey = keyArr;
},
},
};
</script>
<style lang="scss" scoped>
.el-scrollbar .el-scrollbar__view .el-select-dropdown__item {
height: auto;
max-height: 274px;
padding: 0;
overflow-y: auto;
}
.el-select-dropdown__item.selected {
font-weight: normal;
}
ul li > .el-tree .el-tree-node__content {
height: auto;
padding: 0 20px;
}
.el-tree-node__label {
font-weight: normal;
}
.el-tree > .is-current .el-tree-node__label {
font-weight: 700;
color: #409eff;
}
.el-tree > .is-current .el-tree-node__children .el-tree-node__label {
font-weight: normal;
color: #606266;
}
</style>
<style lang="scss">
/* .vab-tree-select{
.el-tag__close.el-icon-close{
width:0;
overflow:hidden;
}
} */
</style>
<template>
<div class="content">
<div class="g-container" :style="styleObj">
<div class="g-number">
<vab-count
:start-val="startVal"
:end-val="endVal"
:duration="duration"
:separator="separator"
:prefix="prefix"
:suffix="suffix"
:decimals="decimals"
/>
</div>
<div class="g-contrast">
<div class="g-circle"></div>
<ul class="g-bubbles">
<li v-for="(item, index) in 15" :key="index"></li>
</ul>
</div>
</div>
</div>
</template>
<script>
export default {
name: "VabCharge",
props: {
styleObj: {
type: Object,
default: () => {
return {};
},
},
startVal: {
type: Number,
default: 0,
},
endVal: {
type: Number,
default: 100,
},
},
data() {
return {
decimals: 2,
prefix: "",
suffix: "%",
separator: ",",
duration: 3000,
};
},
created() {},
mounted() {},
methods: {},
};
</script>
<style lang="scss" scoped>
.content {
position: relative;
display: flex;
align-items: center; /* 垂直居中 */
justify-content: center; /* 水平居中 */
width: 100%;
background: #000;
.g-number {
position: absolute;
top: 27%;
z-index: 99;
width: 300px;
font-size: 32px;
color: #fff;
text-align: center;
}
.g-container {
position: relative;
width: 300px;
height: 400px;
margin: auto;
}
.g-contrast {
width: 300px;
height: 400px;
overflow: hidden;
background-color: #000;
filter: contrast(15) hue-rotate(0);
animation: hueRotate 10s infinite linear;
}
.g-circle {
position: relative;
box-sizing: border-box;
width: 300px;
height: 300px;
filter: blur(8px);
&::after {
position: absolute;
top: 40%;
left: 50%;
width: 200px;
height: 200px;
content: "";
background-color: #00ff6f;
border-radius: 42% 38% 62% 49% / 45%;
transform: translate(-50%, -50%) rotate(0);
animation: rotate 10s infinite linear;
}
&::before {
position: absolute;
top: 40%;
left: 50%;
z-index: 99;
width: 176px;
height: 176px;
content: "";
background-color: #000;
border-radius: 50%;
transform: translate(-50%, -50%);
}
}
.g-bubbles {
position: absolute;
bottom: 0;
left: 50%;
width: 100px;
height: 40px;
background-color: #00ff6f;
filter: blur(5px);
border-radius: 100px 100px 0 0;
transform: translate(-50%, 0);
}
li {
position: absolute;
background: #00ff6f;
border-radius: 50%;
}
@for $i from 0 through 15 {
li:nth-child(#{$i}) {
$width: 15 + random(15) + px;
top: 50%;
left: 15 + random(70) + px;
width: $width;
height: $width;
transform: translate(-50%, -50%);
animation: moveToTop
#{random(6) +
3}s
ease-in-out -#{random(5000) /
1000}s
infinite;
}
}
@keyframes rotate {
50% {
border-radius: 45% / 42% 38% 58% 49%;
}
100% {
transform: translate(-50%, -50%) rotate(720deg);
}
}
@keyframes moveToTop {
90% {
opacity: 1;
}
100% {
opacity: 0.1;
transform: translate(-50%, -180px);
}
}
@keyframes hueRotate {
100% {
filter: contrast(15) hue-rotate(360deg);
}
}
}
</style>
<template>
<div class="vab-image__outter">
<el-image
:src="bigSrc"
fit="cover"
style="width: 100%; height: 100%"
@click="clickBig"
></el-image>
<el-image
:src="smallSrc"
class="vab-image__outter__small"
fit="cover"
@click="clickSmall"
></el-image>
<span class="vab-image__outter__percent">{{ percent }}%</span>
</div>
</template>
<script>
export default {
name: "VabImage",
components: {},
props: {
bigSrc: {
type: String,
default: "",
},
smallSrc: {
type: String,
default: "",
},
percent: {
type: Number,
default: 97,
},
},
data() {
return {};
},
created() {},
mounted() {},
methods: {
clickBig() {
this.$emit("clickBig");
},
clickSmall() {
this.$emit("clickSmall");
},
},
};
</script>
<style lang="scss" scoped>
.vab-image {
&__outter {
position: relative;
width: 100%;
height: 100%;
::v-deep {
img {
border-radius: $base-border-radius;
}
}
&__small {
position: absolute;
top: 0;
right: 0;
width: 80px;
height: 100px;
border-bottom: 1px solid $base-color-white;
border-left: 1px solid $base-color-white;
border-radius: $base-border-radius;
}
&__percent {
position: absolute;
right: 0;
bottom: 0;
display: inline-block;
min-width: 50px;
height: 25px;
line-height: 25px;
color: $base-color-white;
text-align: center;
background-color: $base-color-red;
border-radius: $base-border-radius;
}
}
}
</style>
<template>
<div class="card" :style="styleObj">
<div class="card-borders">
<div class="border-top"></div>
<div class="border-right"></div>
<div class="border-bottom"></div>
<div class="border-left"></div>
</div>
<div class="card-content">
<el-image :src="avatar" class="avatar"></el-image>
<div class="username">{{ username }}</div>
<div class="social-icons">
<a
v-for="(item, index) in iconArray"
:key="index"
class="social-icon"
:href="item.url"
target="_blank"
>
<vab-icon :icon="['fas', item.icon]" />
</a>
</div>
</div>
</div>
</template>
<script>
export default {
name: "VabProfile",
props: {
styleObj: {
type: Object,
default: () => {
return {};
},
},
username: {
type: String,
default: "",
},
avatar: {
type: String,
default: "",
},
iconArray: {
type: Array,
default: () => {
return [
{ icon: "bell", url: "" },
{ icon: "bookmark", url: "" },
{ icon: "cloud-sun", url: "" },
];
},
},
},
data() {
return {};
},
created() {},
mounted() {},
methods: {},
};
</script>
<style lang="scss" scoped>
.card {
--card-bg-color: hsl(240, 31%, 25%);
--card-bg-color-transparent: hsla(240, 31%, 25%, 0.7);
position: relative;
width: 100%;
height: 100%;
.card-borders {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
overflow: hidden;
.border-top {
position: absolute;
top: 0;
width: 100%;
height: 2px;
background: var(--card-bg-color);
transform: translateX(-100%);
animation: slide-in-horizontal 0.8s cubic-bezier(0.645, 0.045, 0.355, 1)
forwards;
}
.border-right {
position: absolute;
right: 0;
width: 2px;
height: 100%;
background: var(--card-bg-color);
transform: translateY(100%);
animation: slide-in-vertical 0.8s cubic-bezier(0.645, 0.045, 0.355, 1)
forwards;
}
.border-bottom {
position: absolute;
bottom: 0;
width: 100%;
height: 2px;
background: var(--card-bg-color);
transform: translateX(100%);
animation: slide-in-horizontal-reverse 0.8s
cubic-bezier(0.645, 0.045, 0.355, 1) forwards;
}
.border-left {
position: absolute;
top: 0;
width: 2px;
height: 100%;
background: var(--card-bg-color);
transform: translateY(-100%);
animation: slide-in-vertical-reverse 0.8s
cubic-bezier(0.645, 0.045, 0.355, 1) forwards;
}
}
.card-content {
display: flex;
flex-direction: column;
align-items: center;
height: 100%;
padding: 40px 0 40px 0;
background: var(--card-bg-color-transparent);
opacity: 0;
transform: scale(0.6);
animation: bump-in 0.5s 0.8s forwards;
.avatar {
width: 80px;
height: 80px;
border: 1px solid $base-color-white;
border-radius: 50%;
opacity: 0;
transform: scale(0.6);
animation: bump-in 0.5s 1s forwards;
}
.username {
position: relative;
margin-top: 20px;
margin-bottom: 20px;
font-size: 26px;
color: transparent;
letter-spacing: 2px;
animation: fill-text-white 1.2s 2s forwards;
&::before {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
color: black;
content: "";
background: #35b9f1;
transform: scaleX(0);
transform-origin: left;
animation: slide-in-out 1.2s 1.2s cubic-bezier(0.75, 0, 0, 1) forwards;
}
}
.social-icons {
display: flex;
.social-icon {
position: relative;
display: flex;
align-items: center;
justify-content: center;
width: 2.5em;
height: 2.5em;
margin: 0 15px;
color: white;
text-decoration: none;
border-radius: 50%;
@for $i from 1 through 3 {
&:nth-child(#{$i}) {
&::before {
animation-delay: 2s + 0.1s * $i;
}
&::after {
animation-delay: 2.1s + 0.1s * $i;
}
svg {
animation-delay: 2.2s + 0.1s * $i;
}
}
}
&::before,
&::after {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
content: "";
border-radius: inherit;
transform: scale(0);
}
&::before {
background: #f7f1e3;
animation: scale-in 0.5s cubic-bezier(0.75, 0, 0, 1) forwards;
}
&::after {
background: #2c3e50;
animation: scale-in 0.5s cubic-bezier(0.75, 0, 0, 1) forwards;
}
svg {
z-index: 99;
transform: scale(0);
animation: scale-in 0.5s cubic-bezier(0.75, 0, 0, 1) forwards;
}
}
}
}
}
@keyframes bump-in {
50% {
transform: scale(1.05);
}
to {
opacity: 1;
transform: scale(1);
}
}
@keyframes slide-in-horizontal {
50% {
transform: translateX(0);
}
to {
transform: translateX(100%);
}
}
@keyframes slide-in-horizontal-reverse {
50% {
transform: translateX(0);
}
to {
transform: translateX(-100%);
}
}
@keyframes slide-in-vertical {
50% {
transform: translateY(0);
}
to {
transform: translateY(-100%);
}
}
@keyframes slide-in-vertical-reverse {
50% {
transform: translateY(0);
}
to {
transform: translateY(100%);
}
}
@keyframes slide-in-out {
50% {
transform: scaleX(1);
transform-origin: left;
}
50.1% {
transform-origin: right;
}
100% {
transform: scaleX(0);
transform-origin: right;
}
}
@keyframes fill-text-white {
to {
color: white;
}
}
@keyframes scale-in {
to {
transform: scale(1);
}
}
</style>
<template>
<div class="app-container">
<vue-q-art :config="config"></vue-q-art>
</div>
</template>
<script>
import VueQArt from "vue-qart";
import qrImg from "@/assets/qr_logo/lqr_logo.png";
export default {
name: "VabQrCode",
components: {
VueQArt,
},
props: {
imagePath: {
type: String,
default: qrImg,
},
url: {
type: String,
default: "http://www.boyunvision.com/",
},
size: {
type: Number,
default: 500,
},
},
data() {
return {
config: {
value: this.url,
imagePath: this.imagePath,
filter: "color",
size: this.size,
},
};
},
created() {},
mounted() {},
methods: {},
};
</script>
<template>
<div class="content" :style="styleObj">
<div v-for="(item, index) in 200" :key="index" class="snow"></div>
</div>
</template>
<script>
export default {
name: "VabSnow",
props: {
styleObj: {
type: Object,
default: () => {
return {};
},
},
},
data() {
return {};
},
created() {},
mounted() {},
methods: {},
};
</script>
<style lang="scss" scoped>
.content {
position: relative;
width: 100%;
height: 100%;
overflow: hidden;
background: radial-gradient(ellipse at bottom, #1b2735 0%, #090a0f 100%);
filter: drop-shadow(0 0 10px white);
}
@function random_range($min, $max) {
$rand: random();
$random_range: $min + floor($rand * (($max - $min) + 1));
@return $random_range;
}
.snow {
$total: 200;
position: absolute;
width: 10px;
height: 10px;
background: white;
border-radius: 50%;
@for $i from 1 through $total {
$random-x: random(1000000) * 0.0001vw;
$random-offset: random_range(-100000, 100000) * 0.0001vw;
$random-x-end: $random-x + $random-offset;
$random-x-end-yoyo: $random-x + ($random-offset / 2);
$random-yoyo-time: random_range(30000, 80000) / 100000;
$random-yoyo-y: $random-yoyo-time * 100vh;
$random-scale: random(10000) * 0.0001;
$fall-duration: random_range(10, 30) * 1s;
$fall-delay: random(30) * -1s;
&:nth-child(#{$i}) {
opacity: random(10000) * 0.0001;
transform: translate($random-x, -10px) scale($random-scale);
animation: fall-#{$i} $fall-duration $fall-delay linear infinite;
}
@keyframes fall-#{$i} {
#{percentage($random-yoyo-time)} {
transform: translate($random-x-end, $random-yoyo-y)
scale($random-scale);
}
to {
transform: translate($random-x-end-yoyo, 100vh) scale($random-scale);
}
}
}
}
</style>
<template>
<div :style="{ height: height + 'px', zIndex: zIndex }">
<div
:class="className"
:style="{
top: isSticky ? stickyTop + 'px' : '',
zIndex: zIndex,
position: position,
width: width,
height: height + 'px',
}"
>
<slot></slot>
</div>
</div>
</template>
<script>
export default {
name: "VabSticky",
props: {
stickyTop: {
type: Number,
default: 0,
},
zIndex: {
type: Number,
default: 1,
},
className: {
type: String,
default: "",
},
},
data() {
return {
active: false,
position: "",
width: undefined,
height: undefined,
isSticky: false,
};
},
mounted() {
this.height = this.$el.getBoundingClientRect().height;
window.addEventListener("scroll", this.handleScroll);
window.addEventListener("resize", this.handleResize);
},
activated() {
this.handleScroll();
},
destroyed() {
window.removeEventListener("scroll", this.handleScroll);
window.removeEventListener("resize", this.handleResize);
},
methods: {
sticky() {
if (this.active) {
return;
}
this.position = "fixed";
this.active = true;
this.width = this.width + "px";
this.isSticky = true;
},
handleReset() {
if (!this.active) {
return;
}
this.reset();
},
reset() {
this.position = "";
this.width = "auto";
this.active = false;
this.isSticky = false;
},
handleScroll() {
const width = this.$el.getBoundingClientRect().width;
this.width = width || "auto";
const offsetTop = this.$el.getBoundingClientRect().top;
if (offsetTop < this.stickyTop) {
this.sticky();
return;
}
this.handleReset();
},
handleResize() {
if (this.isSticky) {
this.width = this.$el.getBoundingClientRect().width + "px";
}
},
},
};
</script>
<template>
<el-dialog
:title="title"
:visible.sync="dialogFormVisible"
width="909px"
:before-close="handleClose"
:close-on-click-modal="false"
>
<div class="upload">
<el-alert
:closable="false"
:title="`支持jpg、jpeg、png格式,单次可最多选择${limit}张图片,每张不可大于${size}M,如果大于${size}M会自动为您过滤`"
type="info"
></el-alert>
<br />
<el-upload
ref="upload"
class="upload-content"
:name="name"
:data="data"
:action="action"
:headers="headers"
:on-change="handleChange"
:on-preview="handlePreview"
:on-remove="handleRemove"
:on-exceed="handleExceed"
:on-success="handleSuccess"
:on-progress="handleProgress"
:on-error="handleError"
:file-list="fileList"
:multiple="true"
:auto-upload="false"
accept="image/png, image/jpeg"
:limit="limit"
list-type="picture-card"
:close-on-click-modal="false"
>
<i slot="trigger" class="el-icon-plus"></i>
<el-dialog
title="查看大图"
append-to-body
:visible.sync="dialogVisible"
>
<div style="padding-bottom: 20px !important">
<img width="100%" :src="dialogImageUrl" alt="" />
</div>
</el-dialog>
</el-upload>
</div>
<div
slot="footer"
class="dialog-footer"
style="position: relative; padding-right: 15px; text-align: right"
>
<div
v-if="show"
style="position: absolute; top: 10px; left: 15px; color: #999"
>
正在上传中... 当前上传成功数:{{ imgSuccessNum }}张 当前上传失败数:{{
imgErrorNum
}}
</div>
<el-button type="primary" @click="handleClose">关闭</el-button>
<el-button
style="margin-left: 10px"
size="small"
type="success"
:loading="loading"
@click="submitUpload"
>
开始上传
</el-button>
</div>
</el-dialog>
</template>
<script>
import { tokenName } from "@/config/settings";
export default {
name: "VabUpload",
props: {
url: {
type: String,
default: "/upload",
required: true,
},
name: {
type: String,
default: "file",
required: true,
},
limit: {
type: Number,
default: 50,
required: true,
},
size: {
type: Number,
default: 1,
required: true,
},
},
data() {
return {
show: false,
loading: false,
dialogVisible: false,
dialogImageUrl: "",
action: "",
headers: {},
fileList: [],
picture: "picture",
imgNum: 0,
imgSuccessNum: 0,
imgErrorNum: 0,
typeList: null,
title: "上传",
dialogFormVisible: false,
data: {},
};
},
computed: {
percentage() {
if (this.allImgNum == 0) return 0;
return this.$baseLodash.round(this.imgNum / this.allImgNum, 2) * 100;
},
},
created() {
if ("development" === process.env.NODE_ENV) {
this.api = process.env.VUE_APP_BASE_API;
} else {
this.api = `${window.location.protocol}//${window.location.host}`;
}
this.action = this.api + this.url;
this.headers[tokenName] = this.$baseAccessToken();
},
methods: {
submitUpload() {
this.$refs.upload.submit();
},
handleProgress(event, file, fileList) {
this.loading = true;
this.show = true;
},
handleChange(file, fileList) {
if (file.size > 1048576 * this.size) {
fileList.map((item, index) => {
if (item === file) {
fileList.splice(index, 1);
}
});
this.fileList = fileList;
} else {
this.allImgNum = fileList.length;
}
},
handleSuccess(response, file, fileList) {
this.imgNum = this.imgNum + 1;
this.imgSuccessNum = this.imgSuccessNum + 1;
if (fileList.length === this.imgNum) {
setTimeout(() => {
this.$emit("fetchDatas");
this.$baseMessage(
`上传完成! 共上传${fileList.length}张图片`,
"success"
);
}, 1000);
}
setTimeout(() => {
this.loading = false;
this.show = false;
}, 1000);
},
handleError(err, file, fileList) {
this.imgNum = this.imgNum + 1;
this.imgErrorNum = this.imgErrorNum + 1;
this.$baseMessage(
`文件[${file.raw.name}]上传失败,文件大小为${this.$baseLodash.round(
file.raw.size / 1024,
0
)}KB`,
"error"
);
setTimeout(() => {
this.loading = false;
this.show = false;
}, 1000);
},
handleRemove(file, fileList) {
this.imgNum = this.imgNum - 1;
this.allNum = this.allNum - 1;
},
handlePreview(file) {
this.dialogImageUrl = file.url;
this.dialogVisible = true;
},
handleExceed(files, fileList) {
this.$baseMessage(
`当前限制选择 ${this.limit} 个文件,本次选择了
${files.length}
个文件`,
"error"
);
},
handleShow(data) {
this.title = "上传";
this.data = data;
this.dialogFormVisible = true;
},
handleClose() {
this.fileList = [];
this.picture = "picture";
this.allImgNum = 0;
this.imgNum = 0;
this.imgSuccessNum = 0;
this.imgErrorNum = 0;
if ("development" === process.env.NODE_ENV) {
this.api = process.env.VUE_APP_BASE_API;
} else {
this.api = `${window.location.protocol}//${window.location.host}`;
}
this.action = this.api + this.url;
this.headers[tokenName] = this.$baseAccessToken();
this.dialogFormVisible = false;
},
},
};
</script>
<style lang="scss" scoped>
.upload {
height: 600px;
.upload-content {
.el-upload__tip {
display: block;
height: 30px;
line-height: 30px;
}
::v-deep {
.el-upload--picture-card {
width: 128px;
height: 128px;
margin: 3px 8px 8px 8px;
border: 2px dashed #c0ccda;
}
.el-upload-list--picture {
margin-bottom: 20px;
}
.el-upload-list--picture-card {
.el-upload-list__item {
width: 128px;
height: 128px;
margin: 3px 8px 8px 8px;
}
}
}
}
}
</style>
/**
* @copyright chuzhixin 1204505056@qq.com
* @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 "./settings";
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");
}
router.addRoutes(accessRoutes);
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();
});
/**
* @copyright chuzhixin 1204505056@qq.com
* @description 全局变量配置
*/
module.exports = {
// 开发以及部署时的URL
publicPath: "",
// 生产环境构建文件的目录名
outputDir: "dist",
// 放置生成的静态资源 (js、css、img、fonts) 的 (相对于 outputDir 的) 目录。
assetsDir: "static",
// 开发环境每次保存时是否输出为eslint编译警告
lintOnSave: true,
// 进行编译的依赖
transpileDependencies: ["vue-echarts", "resize-detector", "zx-layouts"],
// 默认的接口地址 如果是开发环境和生产环境走vab-mock-server,当然你也可以选择自己配置成需要的接口地址
baseURL:
process.env.NODE_ENV === "development"
? "vab-mock-server"
: "vab-mock-server",
//标题 (包括初次加载雪花屏的标题 页面的标题 浏览器的标题)
title: "vue-admin-beautiful",
//简写
abbreviation: "vab",
//开发环境端口号
devPort: "80",
//版本号
version: process.env.VUE_APP_VERSION,
//烦请保留package.json作者信息 保留版权可免费商用 如需去除并自定义为自己企业的版权请联系群主QQ 1204505056 需支付299元 恶意修改发生纠纷及出现任何问题 由修改人自行承担
copyright: process.env.VUE_APP_AUTHOR,
//是否显示页面底部版权信息,建议您显示,当然您也可以选择不显示,不管您是付费用户还是未付费用户您都有选择显示或者不显示的权利
footerCopyright: process.env.NODE_ENV !== "development",
//是否显示右上角github图标
githubCorner: process.env.NODE_ENV !== "development",
//是否显示顶部进度条
progressBar: true,
//缓存路由的最大数量
keepAliveMaxNum: 99,
// 路由模式,可选值为 history 或 hash
routerMode: "hash",
//不经过token校验的路由
routesWhiteList: ["/login", "/register", "/404", "/401"],
//加载时显示文字
loadingText: "正在加载中...",
//token名称
tokenName: "accessToken",
//token在localStorage、sessionStorage、cookie存储的key的名称
tokenTableName: "vue-admin-beautiful",
//token存储位置localStorage sessionStorage cookie
storage: "localStorage",
//token失效回退到登录页时是否记录本次的路由
recordRoute: true,
//是否显示logo,不显示时设置false,显示时请填写remixIcon图标名称,暂时只支持设置remixIcon
logo: "vuejs-fill",
//是否国定头部 固定fixed 不固定noFixed
header: "fixed",
//横纵布局 horizontal vertical
layout: "vertical",
//是否开启主题配置按钮
themeBar: true,
//是否显示多标签页
tagsBar: true,
//是否显示骨架屏
skeleton: false,
//配后端数据的接收方式application/json;charset=UTF-8或者application/x-www-form-urlencoded;charset=UTF-8
contentType: "application/json;charset=UTF-8",
//消息框消失时间
messageDuration: 3000,
//最长请求时间
requestTimeout: 5000,
//操作正常code,支持String、Array、int多种类型
successCode: [200, 0],
//登录失效code
invalidCode: 402,
//无权限code
noPermissionCode: 401,
//是否显示在页面高亮错误
errorLog: ["development", "test", "production"],
//是否开启登录拦截
loginInterception: true,
//是否开启登录RSA加密
loginRSA: true,
//是否依据mock数据生成webstorm HTTP Request请求文件
httpRequestFile: false,
//intelligence和all两种方式,前者后端权限只控制permissions不控制view文件的import(前后端配合,减轻后端工作量),all方式完全交给后端前端只负责加载
authentication: "intelligence",
//vertical布局时是否只保持一个子菜单的展开
uniqueOpened: true,
//vertical布局时默认展开的菜单path,使用逗号隔开建议只展开一个
defaultOopeneds: ["/vab"],
//需要加loading层的请求,防止重复提交
debounce: ["doEdit"],
//需要自动注入并加载的模块
providePlugin: { maptalks: "maptalks", "window.maptalks": "maptalks" },
//npm run build时是否自动生成7z压缩包
build7z: false,
//代码生成机生成在view下的文件夹名称
templateFolder: "project",
//是否显示终端donation打印
donation: true,
};
/**
* @copyright chuzhixin 1204505056@qq.com
* @description 导入所有 controller 模块,浏览器环境中自动输出controller文件夹下Mock接口,请勿修改。
*/
import Mock from "mockjs";
import { paramObj } from "@/utils";
const mocks = [];
const files = require.context("../../mock/controller", false, /\.js$/);
files.keys().forEach((key) => {
const obj = files(key);
mocks.push(...obj);
});
export function mockXHR() {
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 XHR2ExpressReqWrap(respond) {
return function (options) {
let result = null;
if (respond instanceof Function) {
const { body, type, url } = options;
result = respond({
method: type,
body: JSON.parse(body),
query: paramObj(url),
});
} else {
result = respond;
}
return Mock.mock(result);
};
}
for (const i of mocks) {
Mock.mock(
new RegExp(i.url),
i.type || "get",
XHR2ExpressReqWrap(i.response)
);
}
}
<template>
<router-view />
</template>
<template>
<div class="vab-ad">
<el-carousel
v-if="adList"
height="30px"
direction="vertical"
:autoplay="true"
:interval="3000"
indicator-position="none"
>
<el-carousel-item v-for="(item, index) in adList" :key="index">
<el-tag type="warning">Ad</el-tag>
<a target="_blank" :href="item.url">{{ item.title }}</a>
</el-carousel-item>
</el-carousel>
</div>
</template>
<script>
import { getList } from "@/api/ad";
export default {
data() {
return {
nodeEnv: process.env.NODE_ENV,
adList: [],
};
},
created() {
this.fetchData();
},
methods: {
async fetchData() {
const { data } = await getList();
this.adList = data;
},
},
};
</script>
<style lang="scss" scoped>
.vab-ad {
height: 30px;
padding-right: $base-padding;
padding-left: $base-padding;
line-height: 30px;
cursor: pointer;
background: #eef1f6;
box-shadow: 0 -1px 2px rgba(0, 21, 41, 0.08) inset;
a {
color: #999;
}
}
</style>
/**
* @copyright chuzhixin 1204505056@qq.com
* @description 公共布局导出,已封装成npm,便于此后在线升级,当然也存在一定的弊端,给开发者自定义增加了一定的困难,如果您一定要进行高度自定义,请仔细阅读VIP群文档,layouts本地化篇
*/
export { default as ColorfullIcon } from "zx-layouts/ColorfullIcon";
export { default as RemixIcon } from "zx-layouts/RemixIcon";
export { default as VabDrag } from "zx-layouts/Drag";
export { default as VabPermissions } from "zx-layouts/Permissions";
export { default as VabQueryForm } from "zx-layouts/VabQueryForm/export";
export { default as Logo } from "zx-layouts/Logo";
export { default as Avatar } from "zx-layouts/Avatar";
export { default as Ad } from "./Ad";
export { default as AppMain } from "zx-layouts/AppMain";
export { default as TagsBar } from "zx-layouts/TagsBar";
export { default as SideBar } from "zx-layouts/SideBar";
export { default as Breadcrumb } from "zx-layouts/Breadcrumb";
export { default as FullScreenBar } from "zx-layouts/FullScreenBar";
export { default as ErrorLog } from "zx-layouts/ErrorLog";
export { default as ThemeBar } from "zx-layouts/ThemeBar";
export { default as TopBar } from "zx-layouts/TopBar";
export { default as NavBar } from "zx-layouts/NavBar";
<template>
<div class="vue-admin-beautiful-wrapper" :class="classObj">
<div
v-if="'horizontal' === layout"
class="layout-container-horizontal"
:class="{
fixed: header === 'fixed',
'no-tags-bar': tagsBar === 'false' || tagsBar === false,
}"
>
<div :class="header === 'fixed' ? 'fixed-header' : ''">
<top-bar></top-bar>
<div
v-if="tagsBar === 'true' || tagsBar === true"
:class="{ 'tag-view-show': tagsBar }"
>
<div class="vab-main">
<tags-bar></tags-bar>
</div>
</div>
</div>
<div class="vab-main main-padding">
<ad></ad>
<app-main></app-main>
</div>
</div>
<div
v-else
class="layout-container-vertical"
:class="{
fixed: header === 'fixed',
'no-tags-bar': tagsBar === 'false' || tagsBar === false,
}"
>
<div
v-if="device === 'mobile' && collapse === false"
class="mask"
@click="handleFoldSideBar"
/>
<side-bar></side-bar>
<div class="vab-main" :class="collapse ? 'is-collapse-main' : ''">
<div :class="header === 'fixed' ? 'fixed-header' : ''">
<nav-bar></nav-bar>
<tags-bar v-if="tagsBar === 'true' || tagsBar === true" />
</div>
<ad></ad>
<app-main></app-main>
</div>
</div>
<el-backtop></el-backtop>
</div>
</template>
<script>
import { Ad, AppMain, NavBar, SideBar, TagsBar, TopBar } from "./components";
import { mapActions, mapGetters } from "vuex";
import { tokenName } from "@/config/settings";
export default {
name: "Layout",
components: {
Ad,
TopBar,
NavBar,
SideBar,
AppMain,
TagsBar,
},
data() {
return { oldLayout: "" };
},
computed: {
...mapGetters({
layout: "settings/layout",
tagsBar: "settings/tagsBar",
collapse: "settings/collapse",
header: "settings/header",
device: "settings/device",
}),
classObj() {
return {
mobile: this.device === "mobile",
};
},
},
beforeMount() {
window.addEventListener("resize", this.handleResize);
},
beforeDestroy() {
window.removeEventListener("resize", this.handleResize);
},
mounted() {
this.oldLayout = this.layout;
const userAgent = navigator.userAgent;
if (userAgent.includes("Juejin")) {
this.$baseAlert(
"vue-admin-beautiful不支持在掘金内置浏览器演示,请手动复制以下地址到浏览器中查看http://mpfhrd48.sanxing.uz7.cn/vue-admin-beautiful"
);
}
const isMobile = this.handleIsMobile();
if (isMobile) {
if (isMobile) {
//横向布局时如果是手机端访问那么改成纵向版
this.$store.dispatch("settings/changeLayout", "vertical");
} else {
this.$store.dispatch("settings/changeLayout", this.oldLayout);
}
this.$store.dispatch("settings/toggleDevice", "mobile");
setTimeout(() => {
this.$store.dispatch("settings/foldSideBar");
}, 2000);
} else {
this.$store.dispatch("settings/openSideBar");
}
this.$nextTick(() => {
window.addEventListener(
"storage",
(e) => {
if (e.key === tokenName || e.key === null) window.location.reload();
if (e.key === tokenName && e.value === null)
window.location.reload();
},
false
);
});
},
methods: {
...mapActions({
handleFoldSideBar: "settings/foldSideBar",
}),
handleIsMobile() {
return document.body.getBoundingClientRect().width - 1 < 992;
},
handleResize() {
if (!document.hidden) {
const isMobile = this.handleIsMobile();
if (isMobile) {
//横向布局时如果是手机端访问那么改成纵向版
this.$store.dispatch("settings/changeLayout", "vertical");
} else {
this.$store.dispatch("settings/changeLayout", this.oldLayout);
}
this.$store.dispatch(
"settings/toggleDevice",
isMobile ? "mobile" : "desktop"
);
}
},
},
};
</script>
<style lang="scss" scoped>
@mixin fix-header {
position: fixed;
top: 0;
right: 0;
left: 0;
z-index: $base-z-index - 2;
width: 100%;
overflow: hidden;
}
.vue-admin-beautiful-wrapper {
position: relative;
width: 100%;
height: 100%;
.layout-container-horizontal {
position: relative;
&.fixed {
padding-top: calc(#{$base-top-bar-height} + #{$base-tags-bar-height});
}
&.fixed.no-tags-bar {
padding-top: $base-top-bar-height;
}
::v-deep {
.vab-main {
width: 88%;
margin: auto;
}
.fixed-header {
@include fix-header;
}
.tag-view-show {
background: $base-color-white;
box-shadow: $base-box-shadow;
}
.nav-bar-container {
.fold-unfold {
display: none;
}
}
.main-padding {
.app-main-container {
margin-top: $base-padding;
margin-bottom: $base-padding;
background: $base-color-white;
}
}
}
}
.layout-container-vertical {
position: relative;
.mask {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: $base-z-index - 1;
width: 100%;
height: 100vh;
overflow: hidden;
background: #000;
opacity: 0.5;
}
&.fixed {
padding-top: calc(#{$base-nav-bar-height} + #{$base-tags-bar-height});
}
&.fixed.no-tags-bar {
padding-top: $base-nav-bar-height;
}
.vab-main {
position: relative;
min-height: 100%;
margin-left: $base-left-menu-width;
background: #f6f8f9;
transition: $base-transition;
::v-deep {
.fixed-header {
@include fix-header;
left: $base-left-menu-width;
width: $base-right-content-width;
box-shadow: $base-box-shadow;
transition: $base-transition;
}
.nav-bar-container {
position: relative;
box-sizing: border-box;
}
.tags-bar-container {
box-sizing: border-box;
}
.app-main-container {
width: calc(100% - #{$base-padding} - #{$base-padding});
margin: $base-padding auto;
background: $base-color-white;
border-radius: $base-border-radius;
}
}
&.is-collapse-main {
margin-left: $base-left-menu-width-min;
::v-deep {
.fixed-header {
left: $base-left-menu-width-min;
width: calc(100% - 65px);
}
}
}
}
}
/* 手机端开始 */
&.mobile {
::v-deep {
.el-pager,
.el-pagination__jump {
display: none;
}
.layout-container-vertical {
.el-scrollbar.side-bar-container.is-collapse {
width: 0;
}
.vab-main {
width: 100%;
margin-left: 0;
}
}
.vab-main {
.fixed-header {
left: 0 !important;
width: 100% !important;
}
}
}
}
/* 手机端结束 */
}
</style>
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment