umbrella22

删除无用组件,更新依赖,当前未修正css-loader造成css丢失问题,请勿使用

......@@ -8,7 +8,7 @@ const { dependencies } = require('../package.json')
const webpack = require('webpack')
const MinifyPlugin = require("babel-minify-webpack-plugin");
const HappyPack = require('happypack')
const HappyThreadPool = HappyPack.ThreadPool({ size: os.cpus().length })
const HappyThreadPool = HappyPack.ThreadPool({ size: os.cpus().length > 4 ? 4 : os.cpus().length })
function resolve(dir) {
return path.join(__dirname, '..', dir)
......
......@@ -15,7 +15,7 @@ const HtmlWebpackPlugin = require('html-webpack-plugin')
const TerserPlugin = require('terser-webpack-plugin');
const { VueLoaderPlugin } = require('vue-loader')
const HappyPack = require('happypack')
const HappyThreadPool = HappyPack.ThreadPool({ size: os.cpus().length })
const HappyThreadPool = HappyPack.ThreadPool({ size: os.cpus().length > 4 ? 4 : os.cpus().length })
function resolve(dir) {
return path.join(__dirname, '..', dir)
......
......@@ -13,7 +13,7 @@ const HtmlWebpackPlugin = require('html-webpack-plugin')
const TerserPlugin = require('terser-webpack-plugin');
const { VueLoaderPlugin } = require('vue-loader')
const HappyPack = require('happypack')
const HappyThreadPool = HappyPack.ThreadPool({ size: os.cpus().length })
const HappyThreadPool = HappyPack.ThreadPool({ size: os.cpus().length > 4 ? 4 : os.cpus().length })
function resolve(dir) {
return path.join(__dirname, '..', dir)
......
......@@ -18,7 +18,7 @@
"pack:main": "cross-env NODE_ENV=production webpack --progress --colors --config .electron-vue/webpack.main.config.js",
"pack:renderer": "cross-env NODE_ENV=production webpack --progress --colors --config .electron-vue/webpack.renderer.config.js",
"update:serve": "node server/index.js",
"dep:upgrade":"yarn upgrade-interactive --latest"
"dep:upgrade": "yarn upgrade-interactive --latest"
},
"build": {
"extraFiles": [],
......@@ -116,7 +116,7 @@
"chalk": "^4.0.0",
"copy-webpack-plugin": "^6.0.3",
"cross-env": "^7.0.2",
"css-loader": "^3.5.3",
"css-loader": "^4.0.0",
"del": "^5.1.0",
"electron": "^9.1.1",
"electron-builder": "^22.6.1",
......@@ -142,14 +142,14 @@
"split2": "^3.1.1",
"style-loader": "^1.2.1",
"svg-sprite-loader": "^5.0.0",
"terser-webpack-plugin": "^3.0.7",
"terser-webpack-plugin": "^3.0.8",
"through2-filter": "^3.0.0",
"url-loader": "^4.1.0",
"vue-html-loader": "^1.2.4",
"vue-loader": "^15.9.3",
"vue-style-loader": "^4.1.2",
"vue-template-compiler": "^2.6.11",
"webpack": "^4.43.0",
"webpack": "^4.44.0",
"webpack-cli": "^3.3.12",
"webpack-dev-server": "^3.11.0",
"webpack-hot-middleware": "^2.25.0",
......
<template>
<el-breadcrumb class="app-breadcrumb" separator="/">
<transition-group name="breadcrumb">
<el-breadcrumb-item v-for="(item,index) in levelList" :key="item.path" v-if="item.meta.title">
<span v-if="item.redirect==='noredirect'||index==levelList.length-1" class="no-redirect">{{item.meta.title}}</span>
<router-link v-else :to="item.redirect||item.path">{{item.meta.title}}</router-link>
</el-breadcrumb-item>
</transition-group>
</el-breadcrumb>
</template>
<script>
export default {
created() {
this.getBreadcrumb()
},
data() {
return {
levelList: null
}
},
watch: {
$route() {
this.getBreadcrumb()
}
},
methods: {
getBreadcrumb() {
let matched = this.$route.matched.filter(item => item.name)
const first = matched[0]
if (first && first.name !== 'dashboard') {
matched = [{ path: '/dashboard', meta: { title: '总览' }}].concat(matched)
}
this.levelList = matched
}
}
}
</script>
<style rel="stylesheet/scss" lang="scss" scoped>
.app-breadcrumb.el-breadcrumb {
display: inline-block;
font-size: 14px;
line-height: 50px;
margin-left: 10px;
.no-redirect {
color: #97a8be;
cursor: text;
}
}
</style>
<template>
<div>
<svg t="1492500959545" @click="toggleClick" class="hamburger" :class="{'is-active':isActive}" style="" viewBox="0 0 1024 1024"
version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1691" xmlns:xlink="http://www.w3.org/1999/xlink" width="64" height="64">
<path d="M966.8023 568.849776 57.196677 568.849776c-31.397081 0-56.850799-25.452695-56.850799-56.850799l0 0c0-31.397081 25.452695-56.849776 56.850799-56.849776l909.605623 0c31.397081 0 56.849776 25.452695 56.849776 56.849776l0 0C1023.653099 543.397081 998.200404 568.849776 966.8023 568.849776z"
p-id="1692"></path>
<path d="M966.8023 881.527125 57.196677 881.527125c-31.397081 0-56.850799-25.452695-56.850799-56.849776l0 0c0-31.397081 25.452695-56.849776 56.850799-56.849776l909.605623 0c31.397081 0 56.849776 25.452695 56.849776 56.849776l0 0C1023.653099 856.07443 998.200404 881.527125 966.8023 881.527125z"
p-id="1693"></path>
<path d="M966.8023 256.17345 57.196677 256.17345c-31.397081 0-56.850799-25.452695-56.850799-56.849776l0 0c0-31.397081 25.452695-56.850799 56.850799-56.850799l909.605623 0c31.397081 0 56.849776 25.452695 56.849776 56.850799l0 0C1023.653099 230.720755 998.200404 256.17345 966.8023 256.17345z"
p-id="1694"></path>
</svg>
</div>
</template>
<script>
export default {
name: 'hamburger',
props: {
isActive: {
type: Boolean,
default: false
},
toggleClick: {
type: Function,
default: null
}
}
}
</script>
<style scoped>
.hamburger {
display: inline-block;
cursor: pointer;
width: 20px;
height: 20px;
transform: rotate(90deg);
transition: .38s;
transform-origin: 50% 50%;
}
.hamburger.is-active {
transform: rotate(0deg);
}
</style>
<template>
<div class="scroll-container" ref="scrollContainer" @wheel.prevent="handleScroll" >
<div class="scroll-wrapper" ref="scrollWrapper" :style="{top: top + 'px'}">
<slot></slot>
</div>
</div>
</template>
<script>
const delta = 15
export default {
name: 'scrollBar',
data() {
return {
top: 0
}
},
methods: {
handleScroll(e) {
const eventDelta = e.wheelDelta || -e.deltaY * 3
const $container = this.$refs.scrollContainer
const $containerHeight = $container.offsetHeight
const $wrapper = this.$refs.scrollWrapper
const $wrapperHeight = $wrapper.offsetHeight
if (eventDelta > 0) {
this.top = Math.min(0, this.top + eventDelta)
} else {
if ($containerHeight - delta < $wrapperHeight) {
if (this.top < -($wrapperHeight - $containerHeight + delta)) {
this.top = this.top
} else {
this.top = Math.max(this.top + eventDelta, $containerHeight - $wrapperHeight - delta)
}
} else {
this.top = 0
}
}
}
}
}
</script>
<style rel="stylesheet/scss" lang="scss" scoped>
@import '../../styles/variables.scss';
.scroll-container {
position: relative;
width: 100%;
height: 100%;
background-color: $menuBg;
.scroll-wrapper {
position: absolute;
width: 100%!important;
}
}
</style>
<template>
<div class="upload-container">
<el-button
:style="{background:color,borderColor:color}"
icon="el-icon-upload"
size="mini"
type="primary"
@click=" dialogVisible=true"
>上传图片</el-button>
<el-dialog :visible.sync="dialogVisible">
<el-upload
ref="upload"
:multiple="true"
:file-list="fileList"
:show-file-list="true"
:on-remove="handleRemove"
:on-success="handleSuccess"
:on-error="handleError"
:data="picPostData"
class="editor-slide-upload"
action="https://jsonplaceholder.typicode.com/post/"
list-type="picture-card"
:limit="5"
>
<el-button size="small" type="primary">点击上传</el-button>
</el-upload>
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="handleSubmit">确定</el-button>
</el-dialog>
</div>
</template>
<script>
export default {
name: "EditorSlideUpload",
props: {
color: {
type: String,
default: "#1890ff"
}
},
data() {
return {
dialogVisible: false,
listObj: {},
fileList: [],
picPostData: {}
};
},
methods: {
checkAllSuccess() {
return Object.keys(this.listObj).every(
item => this.listObj[item].hasSuccess
);
},
handleSubmit() {
const arr = Object.keys(this.listObj).map(v => this.listObj[v]);
console.log(arr);
if (!this.checkAllSuccess()) {
this.$message(
"请等待所有图片上传完成,如果存在网络问题请刷新当前页重新上传"
);
return;
}
this.$emit("successCBK", arr);
this.listObj = {};
this.fileList = [];
this.dialogVisible = false;
},
handleSuccess(response, file) {
console.log("file", file);
console.log("handleSuccess", response);
const uid = file.uid;
const objKeyArr = Object.keys(this.listObj);
for (let i = 0, len = objKeyArr.length; i < len; i++) {
if (this.listObj[objKeyArr[i]].uid === uid) {
this.listObj[objKeyArr[i]].url = this.config.qiniuHost + response.key;
this.listObj[objKeyArr[i]].hasSuccess = true;
return;
}
}
},
handleRemove(file) {
const uid = file.uid;
const objKeyArr = Object.keys(this.listObj);
for (let i = 0, len = objKeyArr.length; i < len; i++) {
if (this.listObj[objKeyArr[i]].uid === uid) {
delete this.listObj[objKeyArr[i]];
return;
}
}
},
handleError(err){
this.alert(err)
}
}
};
</script>
<style lang="scss" scoped>
.editor-slide-upload {
margin-bottom: 20px;
::v-deep .el-upload--picture-card {
width: 100%;
}
}
</style>
let callbacks = []
function loadedTinymce () {
// to fixed https://github.com/PanJiaChen/vue-element-admin/issues/2144
// check is successfully downloaded script
return window.tinymce
}
const dynamicLoadScript = (src, callback) => {
const existingScript = document.getElementById(src)
const cb = callback || function () {}
if (!existingScript) {
const script = document.createElement('script')
script.src = src // src url for the third-party library being loaded.
script.id = src
document.body.appendChild(script)
callbacks.push(cb)
const onEnd = 'onload' in script ? stdOnEnd : ieOnEnd
onEnd(script)
}
if (existingScript && cb) {
if (loadedTinymce()) {
cb(null, existingScript)
} else {
callbacks.push(cb)
}
}
function stdOnEnd (script) {
script.onload = function () {
// this.onload = null here is necessary
// because even IE9 works not like others
this.onerror = this.onload = null
for (const cb of callbacks) {
cb(null, script)
}
callbacks = null
}
script.onerror = function () {
this.onerror = this.onload = null
cb(new Error('无法加载 ' + src), script)
}
}
function ieOnEnd (script) {
script.onreadystatechange = function () {
if (this.readyState !== 'complete' && this.readyState !== 'loaded') return
this.onreadystatechange = null
for (const cb of callbacks) {
cb(null, script) // there is no way to catch loading errors in IE8
}
callbacks = null
}
}
}
export default dynamicLoadScript
<template>
<div :class="{fullscreen:fullscreen}" class="tinymce-container" :style="{width:containerWidth}">
<textarea :id="tinymceId" class="tinymce-textarea" />
<div class="editor-custom-btn-container">
<editorImage color="#1890ff" class="editor-upload-btn" @successCBK="imageSuccessCBK" />
</div>
</div>
</template>
<script>
/**
* docs:
* https://panjiachen.github.io/vue-element-admin-site/feature/component/rich-editor.html#tinymce
*/
import editorImage from './components/EditorImage'
import plugins from './plugins'
import toolbar from './toolbar'
import load from './dynamicLoadScript'
// why use this cdn, detail see https://github.com/PanJiaChen/tinymce-all-in-one
const tinymceCDN = 'https://cdn.jsdelivr.net/npm/tinymce-all-in-one@4.9.3/tinymce.min.js'
export default {
name: 'Tinymce',
components: { editorImage },
props: {
id: {
type: String,
default: function() {
return 'vue-tinymce-' + +new Date() + ((Math.random() * 1000).toFixed(0) + '')
}
},
value: {
type: String,
default: ''
},
toolbar: {
type: Array,
required: false,
default() {
return []
}
},
menubar: {
type: String,
default: ''
},
height: {
type: [Number, String],
required: false,
default: 360
},
width: {
type: [Number, String],
required: false,
default: 'auto'
}
},
data() {
return {
hasChange: false,
hasInit: false,
tinymceId: this.id,
fullscreen: false,
languageTypeList: {
'zh': 'zh_CN',
}
}
},
computed: {
containerWidth() {
const width = this.width
if (/^[\d]+(\.[\d]+)?$/.test(width)) { // matches `100`, `'100'`
return `${width}px`
}
return width
}
},
watch: {
value(val) {
if (!this.hasChange && this.hasInit) {
this.$nextTick(() =>
window.tinymce.get(this.tinymceId).setContent(val || ''))
}
}
},
mounted() {
this.init()
},
activated() {
if (window.tinymce) {
this.initTinymce()
}
},
deactivated() {
this.destroyTinymce()
},
destroyed() {
this.destroyTinymce()
},
methods: {
init() {
// dynamic load tinymce from cdn
load(tinymceCDN, (err) => {
if (err) {
this.$message.error(err.message)
return
}
this.initTinymce()
})
},
initTinymce() {
const _this = this
window.tinymce.init({
selector: `#${this.tinymceId}`,
language: this.languageTypeList['zh'],
height: this.height,
body_class: 'panel-body ',
object_resizing: false,
toolbar: this.toolbar.length > 0 ? this.toolbar : toolbar,
menubar: this.menubar,
plugins: plugins,
end_container_on_empty_block: true,
powerpaste_word_import: 'clean',
code_dialog_height: 450,
code_dialog_width: 1000,
advlist_bullet_styles: 'square',
advlist_number_styles: 'default',
imagetools_cors_hosts: ['www.tinymce.com', 'codepen.io'],
default_link_target: '_blank',
link_title: false,
branding:false,
nonbreaking_force_tab: true, // inserting nonbreaking space &nbsp; need Nonbreaking Space Plugin
init_instance_callback: editor => {
if (_this.value) {
editor.setContent(_this.value)
}
_this.hasInit = true
editor.on('NodeChange Change KeyUp SetContent', () => {
this.hasChange = true
this.$emit('input', editor.getContent())
})
},
setup(editor) {
editor.on('FullscreenStateChanged', (e) => {
_this.fullscreen = e.state
})
}
// 整合七牛上传
// images_dataimg_filter(img) {
// setTimeout(() => {
// const $image = $(img);
// $image.removeAttr('width');
// $image.removeAttr('height');
// if ($image[0].height && $image[0].width) {
// $image.attr('data-wscntype', 'image');
// $image.attr('data-wscnh', $image[0].height);
// $image.attr('data-wscnw', $image[0].width);
// $image.addClass('wscnph');
// }
// }, 0);
// return img
// },
// images_upload_handler(blobInfo, success, failure, progress) {
// progress(0);
// const token = _this.$store.getters.token;
// getToken(token).then(response => {
// const url = response.data.qiniu_url;
// const formData = new FormData();
// formData.append('token', response.data.qiniu_token);
// formData.append('key', response.data.qiniu_key);
// formData.append('file', blobInfo.blob(), url);
// upload(formData).then(() => {
// success(url);
// progress(100);
// })
// }).catch(err => {
// failure('出现未知问题,刷新页面,或者联系程序员')
// console.log(err);
// });
// },
})
},
destroyTinymce() {
const tinymce = window.tinymce.get(this.tinymceId)
if (this.fullscreen) {
tinymce.execCommand('mceFullScreen')
}
if (tinymce) {
tinymce.destroy()
}
},
setContent(value) {
window.tinymce.get(this.tinymceId).setContent(value)
},
getContent() {
window.tinymce.get(this.tinymceId).getContent()
},
imageSuccessCBK(arr) {
const _this = this
arr.forEach(v => {
window.tinymce.get(_this.tinymceId).insertContent(`<img class="wscnph" src="${v.url}" >`)
})
}
}
}
</script>
<style scoped>
.tinymce-container {
position: relative;
line-height: normal;
}
.tinymce-container>>>.mce-fullscreen {
z-index: 10000;
}
.tinymce-textarea {
visibility: hidden;
z-index: -1;
}
.editor-custom-btn-container {
position: absolute;
right: 4px;
top: 4px;
}
.fullscreen .editor-custom-btn-container {
z-index: 10000;
position: fixed;
}
.editor-upload-btn {
display: inline-block;
}
</style>
// Any plugins you want to use has to be imported
// Detail plugins list see https://www.tinymce.com/docs/plugins/
// Custom builds see https://www.tinymce.com/download/custom-builds/
const plugins = ['advlist anchor autolink autosave code codesample colorpicker colorpicker contextmenu directionality emoticons fullscreen hr image imagetools insertdatetime link lists media nonbreaking noneditable pagebreak paste preview print save searchreplace spellchecker tabfocus table template textcolor textpattern visualblocks visualchars wordcount']
export default plugins
// Here is a list of the toolbar
// Detail list see https://www.tinymce.com/docs/advanced/editor-control-identifiers/#toolbarcontrols
const toolbar = ['searchreplace bold italic underline strikethrough alignleft aligncenter alignright outdent indent blockquote undo redo removeformat subscript superscript code codesample', 'hr bullist numlist link image charmap preview anchor pagebreak insertdatetime media table emoticons forecolor backcolor fullscreen']
export default toolbar
<template>
<section class="app-main">
<transition name="fade" mode="out-in">
<router-view />
</transition>
</section>
</template>
<script>
export default {
name: "AppMain"
};
</script>
<template>
<el-menu class="navbar-header-fixed" mode="horizontal">
<div class="top-right">
<div class="hb-bd">
<hamburger
class="hamburger-container"
:toggleClick="toggleSideBar"
:isActive="sidebar.opened"
></hamburger>
<breadcrumb></breadcrumb>
</div>
<div class="top-select">
<div class="go-index">{{time}}</div>
<div class="select-right">
<el-dropdown trigger="click">
<div>
<el-image :src="userImage" class="avatar">
<div slot="error" class="image-slot">
<i class="el-icon-picture-outline"></i>
</div>
</el-image>
<div class="el-dropdown-link">
尊敬的: {{name}}
<i class="el-icon-arrow-down el-icon--right"></i>
</div>
</div>
<el-dropdown-menu slot="dropdown">
<router-link to="/">
<el-dropdown-item>返回首页</el-dropdown-item>
</router-link>
<el-dropdown-item @click.native="logout">
<span>切换账号</span>
</el-dropdown-item>
<el-dropdown-item @click.native="logout">
<span>退出登录</span>
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
</div>
</div>
</el-menu>
</template>
<script>
import { format } from "date-fns";
import { mapGetters } from "vuex";
import Breadcrumb from "@/components/Breadcrumb";
import Hamburger from "@/components/Hamburger";
export default {
components: {
Breadcrumb,
Hamburger
},
data: () => ({
time: "",
userImage: require("@/assets/user.png")
}),
mounted() {
this.set_time();
this.timer = setInterval(() => {
this.set_time();
}, 60000);
console.log(this.userImage)
},
methods: {
toggleSideBar() {
this.$store.dispatch("ToggleSideBar");
},
logout() {
this.$store.dispatch("LogOut").then(() => {
this.$message({
message: "退出成功",
type: "success"
});
this.$router.push('/login')
});
},
set_time() {
this.time = format(new Date(), "yyyy/MM/dd HH:mm");
}
},
computed: {
...mapGetters(["name", "role", "sidebar"])
},
beforeDestroy() {
console.log("销毁计时器------------");
clearInterval(this.timer);
this.timer = null;
}
};
</script>
<style rel="stylesheet/scss" lang="scss" scoped>
.navbar-header-fixed {
transition: width 0.28s;
width: calc(100% - 256px);
display: flex;
align-items: center;
position: fixed;
right: 0;
z-index: 1002;
height: 62px;
.hamburger-container {
line-height: 58px;
height: 50px;
float: left;
padding: 0 10px;
}
.logo {
width: 199px;
height: 62px;
}
.top-right {
display: flex;
width: 100%;
height: 100%;
background-color: #ffffff;
justify-content: space-between;
padding: 0 19px;
.hb-bd {
display: flex;
justify-content: center;
align-items: center;
}
.avatar {
width: 30px;
height: 30px;
margin-right: 10px;
::v-deep img {
width: 100%;
height: 100%;
border-radius: 50%;
}
}
.top-select {
display: flex;
align-items: center;
.go-index {
color: #333333;
font-weight: 400;
margin-right: 20px;
padding-right: 20px;
border-right: 1px solid #cccccc;
}
.select-right ::v-deep .el-dropdown > span {
font-size: 6px;
}
.select-right {
.el-dropdown-link {
color: #333333;
font-weight: 400;
}
::v-deep .el-dropdown-selfdefine {
display: flex;
align-items: center;
}
}
}
}
}
</style>
<template>
<div
v-if="!item.hidden&&item.children"
class="menu-wrapper"
:class="collapse?``:`active-menu-wrapper`"
>
<div v-if="item.onlyShowfirst">
<router-link
v-if="OneShowingChild(item.children[0]) && !onlyOneChild.children&&!item.alwaysShow"
:to="resolvePath(onlyOneChild.path)"
>
<el-menu-item
:index="resolvePath(onlyOneChild.path)"
:class="{'submenu-title-noDropdown':!isNest}"
>
<svg-icon
v-if="onlyOneChild.meta&&onlyOneChild.meta.icon"
:icon-class="onlyOneChild.meta.icon"
></svg-icon>
<span
v-if="onlyOneChild.meta&&onlyOneChild.meta.title"
slot="title"
>{{onlyOneChild.meta.title}}</span>
</el-menu-item>
</router-link>
</div>
<div v-else>
<router-link
v-if="hasOneShowingChild(item.children) && !onlyOneChild.children&&!item.alwaysShow"
:to="resolvePath(onlyOneChild.path)"
>
<el-menu-item
:index="resolvePath(onlyOneChild.path)"
:class="{'submenu-title-noDropdown':!isNest}"
>
<svg-icon
v-if="onlyOneChild.meta&&onlyOneChild.meta.icon"
:icon-class="onlyOneChild.meta.icon"
></svg-icon>
<span
v-if="onlyOneChild.meta&&onlyOneChild.meta.title"
slot="title"
>{{onlyOneChild.meta.title}}</span>
</el-menu-item>
</router-link>
<el-submenu v-else :index="item.name||item.path">
<template slot="title">
<svg-icon v-if="item.meta&&item.meta.icon" :icon-class="item.meta.icon"></svg-icon>
<span v-if="item.meta&&item.meta.title" slot="title">{{item.meta.title}}</span>
</template>
<template v-for="child in item.children" v-if="!child.hidden">
<sidebar-item
:is-nest="true"
class="nest-menu"
v-if="child.children&&child.children.length>0"
:item="child"
:key="child.path"
:base-path="resolvePath(child.path)"
></sidebar-item>
<router-link v-else :to="resolvePath(child.path)" :key="child.name">
<el-menu-item :index="resolvePath(child.path)">
<svg-icon v-if="child.meta&&child.meta.icon" :icon-class="child.meta.icon"></svg-icon>
<span v-if="child.meta&&child.meta.title" slot="title">{{child.meta.title}}</span>
</el-menu-item>
</router-link>
</template>
</el-submenu>
</div>
</div>
</template>
<script>
// import path from "path";
export default {
name: "SidebarItem",
props: {
// route配置json
item: {
type: Object,
required: true
},
isNest: {
type: Boolean,
default: false
},
basePath: {
type: String,
default: ""
},
collapse: {
type: Boolean,
required: true
}
},
data() {
return {
onlyOneChild: null
};
},
methods: {
hasOneShowingChild(children) {
const showingChildren = children.filter(item => {
if (item.hidden) {
return false;
} else {
this.onlyOneChild = item;
return true;
}
});
if (showingChildren.length === 1) {
return true;
}
return false;
},
resolvePath(...paths) {
return this.basePath + "/" + paths[0];
},
OneShowingChild(children) {
this.onlyOneChild = children;
return true;
}
}
};
</script>
<style lang="scss" scoped>
.menu-wrapper {
::v-deep .el-menu-item,
.el-submenu__title {
height: 46px;
line-height: 46px;
}
::v-deep .el-menu-item {
padding: 0 20px 0 12px;
}
}
</style>
\ No newline at end of file
<template>
<scroll-bar>
<el-menu
mode="vertical"
:show-timeout="200"
:default-active="$route.path"
:collapse="isCollapse"
>
<Logo :collapse="isCollapse" />
<sidebar-item v-for="route in routes" :key="route.name" :item="route" :base-path="route.path" :collapse="isCollapse"></sidebar-item>
</el-menu>
</scroll-bar>
</template>
<script>
import { mapGetters } from "vuex";
import SidebarItem from "./SidebarItem";
import ScrollBar from "@/components/ScrollBar";
import Logo from "./logo";
export default {
components: { SidebarItem, ScrollBar, Logo },
computed: {
...mapGetters(["sidebar"]),
routes() {
return this.$router.options.routes;
},
isCollapse() {
return !this.sidebar.opened;
}
}
};
</script>
<style rel="stylesheet/scss" lang="scss" scoped>
.title {
text-align: center;
line-height: 64px;
height: 64px;
font-size: 14px;
font-weight: bold;
color: #333333;
background-color: #ffffff;
padding: 0 20px;
.logo-set {
width: 21px;
height: 21px;
}
}
.minititle {
padding: 0 10px;
transition: padding 0.28s;
overflow: hidden;
width: 180px;
}
</style>
\ No newline at end of file
<template>
<div class="sidebar-logo-container" :class="{'collapse':collapse}">
<transition name="sidebarLogoFade">
<router-link v-if="collapse" key="collapse" class="sidebar-logo-link" to="/">
<svg-icon icon-class="logo" class-name="sidebar-logo"></svg-icon>
<div class="sidebar-title">{{ title }}</div>
</router-link>
<router-link v-else key="expand" class="sidebar-logo-link" to="/">
<svg-icon icon-class="logo" class-name="sidebar-logo"></svg-icon>
<div class="sidebar-title">{{ title }}</div>
</router-link>
</transition>
</div>
</template>
<script>
export default {
name: "SidebarLogo",
props: {
collapse: {
type: Boolean,
required: true
}
},
data() {
return {
title: "logo名称",
};
}
};
</script>
<style rel="stylesheet/scss" lang="scss" scoped>
.sidebarLogoFade-enter-active {
transition: opacity .28s;
}
.sidebarLogoFade-enter,
.sidebarLogoFade-leave-to {
opacity: 0;
}
.sidebar-logo-container {
box-shadow: 2px 0 6px rgba(0,21,41,.15);
position: relative;
width: 100%;
height: 61px;
line-height: 61px;
text-align: center;
overflow: hidden;
background-color: #ffffff;
& > .sidebar-logo-link {
height: 100%;
width: 100%;
& > .sidebar-logo {
width: 32px;
height: 32px;
vertical-align: middle;
margin-right: 12px;
}
& > .sidebar-title {
display: inline-block;
margin: 0;
color: #333;
font-weight: 600;
line-height: 50px;
font-size: 14px;
font-family: Avenir, Helvetica Neue, Arial, Helvetica, sans-serif;
vertical-align: middle;
}
}
}
.collapse {
.sidebar-logo {
margin-right: 0px !important;
margin-left: 0px !important;
}
}
</style>
\ No newline at end of file
export { default as Navbar } from './Navbar'
export { default as Sidebar } from './Sidebar'
export { default as AppMain } from './AppMain'
<template>
<div class="app-wrapper" :class="IsUseSysTitle?'UseSysTitle':'NoUseSysTitle'">
<div :class="classObj">
<navbar></navbar>
<div class="container-set">
<sidebar class="sidebar-container" :class="IsUseSysTitle?'UseSysTitle':'NoUseSysTitle'"></sidebar>
<div class="main-container">
<app-main></app-main>
</div>
</div>
</div>
</div>
</template>
<script>
import { Sidebar, AppMain, Navbar } from "./components";
import ResizeMixin from "./mixin/ResizeHandler";
export default {
name: "layout",
components: {
Sidebar,
AppMain,
Navbar
},
mixins: [ResizeMixin],
data: () => ({
IsUseSysTitle: require("./../../../config").IsUseSysTitle
}),
computed: {
sidebar() {
return this.$store.state.app.sidebar;
},
device() {
return this.$store.state.app.device;
},
classObj() {
return {
hideSidebar: !this.sidebar.opened,
openSidebar: this.sidebar.opened
};
}
}
};
</script>
<style rel="stylesheet/scss" lang="scss" scoped>
@import "@/styles/mixin.scss";
.app-wrapper {
@include clearfix;
position: relative;
height: 100%;
width: 100%;
.container-set {
position: relative;
padding-top: 62px;
}
}
.UseSysTitle{
top:0px;
}
.NoUseSysTitle{
top:38px
}
</style>
import store from '@/store'
const { body } = document
const WIDTH = 1024
const RATIO = 3
export default {
watch: {
$route(route) {
if (this.device === 'mobile' && this.sidebar.opened) {
store.dispatch('CloseSideBar', { withoutAnimation: false })
}
}
},
beforeMount() {
window.addEventListener('resize', this.resizeHandler)
},
mounted() {
const isMobile = this.isMobile()
if (isMobile) {
store.dispatch('ToggleDevice', 'mobile')
store.dispatch('CloseSideBar', { withoutAnimation: true })
}
},
methods: {
isMobile() {
const rect = body.getBoundingClientRect()
return rect.width - RATIO < WIDTH
},
resizeHandler() {
if (!document.hidden) {
const isMobile = this.isMobile()
store.dispatch('ToggleDevice', isMobile ? 'mobile' : 'desktop')
if (isMobile) {
store.dispatch('CloseSideBar', { withoutAnimation: true })
}
}
}
}
}
import router from './router'
import store from './store'
import Performance from '@/tools/performance'
var end = null
const whiteList = ['/login'] // 不重定向白名单
router.beforeEach((to, from, next) => {
end = Performance.startExecute(`${from.path} => ${to.path} 路由耗时`) /// 路由性能监控
if (store.getters.token) {
if (to.path === '/login') {
next({ path: '/' })
} else {
next()
}
} else {
if (whiteList.indexOf(to.path) !== -1) {
next()
} else {
next('/login')
}
}
setTimeout(() => {
end()
}, 0)
......
import Layout from '@/layout'
const Login = () => import('@/views/login')
const Notfound = () => import('@/views/404')
/**
* hidden: true if `hidden:true` will not show in the sidebar(default is false)
* alwaysShow: true if set true, will always show the root menu, whatever its child routes length
* if not set alwaysShow, only more than one route under the children
* it will becomes nested mode, otherwise not show the root menu
* redirect: noredirect if `redirect:noredirect` will no redirct in the breadcrumb
* name:'router-name' the name is used by <keep-alive> (must set!!!)
* meta : {
title: 'title' the name show in submenu and breadcrumb (recommend set)
icon: 'svg-name' the icon show in the sidebar,
}
**/
/**
* hidden: true 如果在模板中使用该选项,则不会在侧栏显示该路由(例如:Dashboard),如果是在第一个子路由中使用,侧栏则只显示第一个子路由的名字和图标(例如: Form)
* alwaysShow: true 如果设置为true它则会始终显示根菜单,无视自路由长度,没有设置的话,就会折叠起来(不清楚为什么没有作用,可能是我写错位置了?)
* redirect: noredirect 若设置为noredirect则顶部面包屑不能够为其重定向.
* onlyShowfirst: false 若该设置为true时,将会无视其有多少个孩子路由,只会显示第一个子路由并将其设置为根菜单
* name:'router-name' 路由名称,此项为必须填写项
* meta : {
title: 'title' 这里的名字决定了面包屑和侧栏的名字
icon: 'svg-name' 当你在svg文件夹内加入了你的图标,那么在这里填写图标名他就会显示在侧栏
}
**/
export default [
{ path: '/login', component: Login, hidden: true },
{ path: '*', component: Notfound, hidden: true },
{
path: '/',
component: Layout,
redirect: '/dashboard',
name: '主页',
hidden: true,
children: [{
path: 'dashboard',
name: '总览',
component: () => import('@/components/LandingPage')
}]
},
{
path: '/form',
component: Layout,
meta: { title: '表单', icon: 'form' },
children: [
{
path: 'index',
name: 'Form',
component: () => import('@/views/form/index'),
meta: { title: '表单', icon: 'form' }
},
{
path: 'index2',
name: 'Form2',
component: () => import('@/views/form/index'),
meta: { title: '表单2', icon: 'form' }
}
]
},
{
path: '/table',
component: Layout,
children: [
{
path: 'index',
name: '表格',
component: () => import('@/views/table/index'),
meta: { title: '表格', icon: 'table' }
}
]
}
{ path: '*', component: Notfound },
{ path: '/', name: '总览', component: () => import('@/components/LandingPage') }
]
......
const user = {
state: {
// token: JSON.parse(localStorage.getItem('token')),
// name: JSON.parse(localStorage.getItem('name')),
// roles: JSON.parse(localStorage.getItem('roles'))
token: 'admin',
name: 'Super Admin',
roles: ['admin']
......
// 订单内容页
.order-container {
padding: 0 212px 20px 50px;
}
// 正文顶部的分割线及分割线上面的内容
.top-nav {
display: flex;
height: 80px;
align-items: center;
}
.line {
background-color: #eeeeee;
width: 100%;
height: 1px;
margin-bottom: 30px;
margin-top: 10px;
}
.line-pop {
background-color: #eeeeee;
width: 100%;
height: 1px;
}
.popo-order{
padding-bottom: 8px;
cursor: pointer;
}
.popo-work{
padding-top: 8px;
cursor: pointer;
}
.tip-line {
background-color: #eeeeee;
width: 100%;
height: 1px;
margin-bottom: 10px;
margin-top: 10px;
}
//to reset element-ui default css
.el-upload {
input[type="file"] {
display: none !important;
}
}
.el-upload__input {
display: none;
}
//暂时性解决diolag 问题 https://github.com/ElemeFE/element/issues/2461
.el-dialog {
transform: none;
left: 0;
position: relative;
margin: 0 auto;
}
//element ui upload
.upload-container {
.el-upload {
width: 100%;
.el-upload-dragger {
width: 100%;
height: 200px;
}
}
}
@import './variables.scss';
@import './mixin.scss';
@import './transition.scss';
@import './element-ui.scss';
@import './sidebar.scss';
body {
-moz-osx-font-smoothing: grayscale;
......
@mixin clearfix {
&:after {
content: "";
display: table;
clear: both;
}
}
@mixin scrollBar {
&::-webkit-scrollbar-track-piece {
background: #d3dce6;
}
&::-webkit-scrollbar {
width: 6px;
}
&::-webkit-scrollbar-thumb {
background: #99a9bf;
border-radius: 20px;
}
}
@mixin relative {
position: relative;
width: 100%;
height: 100%;
}
#app {
// 主体区域
.main-container {
min-height: 100%;
transition: margin-left .28s;
margin-left: 256px;
}
// 侧边栏
.sidebar-container {
.horizontal-collapse-transition {
transition: 0s width ease-in-out, 0s padding-left ease-in-out, 0s padding-right ease-in-out;
}
transition: width .28s;
width: 256px !important;
height: 100%;
position: fixed;
font-size: 0px;
bottom: 0;
left: 0;
z-index: 1001;
overflow: hidden;
a {
display: inline-block;
width: 100%;
}
.svg-icon {
margin-left: 14px;
}
.el-menu {
border: none;
width: 100% !important;
}
}
.hideSidebar {
.sidebar-container {
width: 60px !important;
}
.navbar-header-fixed {
width: calc(100% - 60px);
;
}
.main-container {
margin-left: 60px;
}
.submenu-title-noDropdown {
padding-left: 10px !important;
position: relative;
.el-tooltip {
padding: 0 10px !important;
}
}
.el-submenu {
&>.el-submenu__title {
padding-left: 10px !important;
&>span {
height: 0;
width: 0;
overflow: hidden;
visibility: hidden;
display: inline-block;
}
.el-submenu__icon-arrow {
display: none;
}
}
}
}
.sidebar-container .nest-menu .el-submenu>.el-submenu__title,
.sidebar-container .el-submenu .el-menu-item {
min-width: 180px !important;
}
.el-menu--collapse .el-menu .el-submenu {
min-width: 180px !important;
}
//适配移动端
.mobile {
.main-container {
margin-left: 0px;
}
.sidebar-container {
top: 50px;
transition: transform .28s;
width: 180px !important;
}
&.hideSidebar {
.sidebar-container {
transition-duration: 0.3s;
transform: translate3d(-180px, 0, 0);
}
}
}
.withoutAnimation {
.main-container,
.sidebar-container {
transition: none;
}
}
}
\ No newline at end of file
//sidebar
$menuBg:#ffffff;
$subMenuBg:#1f2d3d;
$menuHover:#001528;
<template>
<div class="app-container">
<el-form ref="form" :model="form" label-width="120px">
<el-form-item label="活动名称">
<el-input v-model="form.name"></el-input>
</el-form-item>
<el-form-item label="活动地点">
<el-select v-model="form.region" placeholder="请选择活动地点">
<el-option label="上海" value="上海"></el-option>
<el-option label="北京" value="北京"></el-option>
</el-select>
</el-form-item>
<el-form-item label="活动时间">
<el-col :span="11">
<el-date-picker type="date" placeholder="选择时间" v-model="form.date1" style="width: 100%;"></el-date-picker>
</el-col>
<el-col class="line" :span="2">-</el-col>
<el-col :span="11">
<el-time-picker
type="fixed-time"
placeholder="选择时间"
v-model="form.date2"
style="width: 100%;"
></el-time-picker>
</el-col>
</el-form-item>
<el-form-item label="即时交付">
<el-switch v-model="form.delivery"></el-switch>
</el-form-item>
<el-form-item label="额外选项">
<el-checkbox-group v-model="form.type">
<el-checkbox label="在线活动" name="type"></el-checkbox>
<el-checkbox label="促销活动" name="type"></el-checkbox>
<el-checkbox label="线下活动" name="type"></el-checkbox>
<el-checkbox label="发布会活动" name="type"></el-checkbox>
</el-checkbox-group>
</el-form-item>
<el-form-item label="资源选项">
<el-radio-group v-model="form.resource">
<el-radio label="需要赞助商"></el-radio>
<el-radio label="不需要赞助商"></el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="活动详情">
<tinymce v-model="form.desc" :height="300" />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onSubmit">Create</el-button>
<el-button @click="onCancel">Cancel</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script>
import Tinymce from "@/components/Tinymce";
export default {
components: { Tinymce },
data() {
return {
form: {
name: "",
region: "",
date1: "",
date2: "",
delivery: false,
type: [],
resource: "",
desc: ""
}
};
},
methods: {
onSubmit() {
this.$message("submit!");
},
onCancel() {
this.$message({
message: "cancel!",
type: "warning"
});
}
}
};
</script>
<style scoped>
.line {
text-align: center;
}
</style>
<template>
<div class="login-container">
<div class="login-from-box">
<el-form
class="login-form"
autocomplete="on"
:model="loginForm"
:rules="loginRules"
ref="loginForm"
label-position="left"
>
<h3 class="title">后台管理框架</h3>
<el-form-item prop="username">
<span class="svg-container svg-container_login">
<svg-icon icon-class="user" />
</span>
<el-input
name="username"
type="text"
v-model="loginForm.username"
autocomplete="on"
placeholder="用户名"
/>
</el-form-item>
<el-form-item prop="password">
<span class="svg-container">
<svg-icon icon-class="password"></svg-icon>
</span>
<el-input
name="password"
:type="pwdType"
@keyup.enter.native="handleLogin"
v-model="loginForm.password"
autocomplete="on"
placeholder="密码"
></el-input>
<span class="show-pwd" @click="showPwd">
<svg-icon :icon-class="pwdType ==='password'?'eye':'eye-open'" />
</span>
</el-form-item>
<div class="login-btn">
<button class="btn" @click="handleLogin">登录</button>
</div>
<div class="tips">
<span style="margin-right:20px;">用户名: admin</span>
<span>密码:随便什么都行</span>
</div>
</el-form>
</div>
</div>
</template>
<script>
import { isvalidUsername } from "@/utils/validate";
export default {
name: "login",
data() {
const validateUsername = (rule, value, callback) => {
if (!isvalidUsername(value)) {
callback(new Error("请输入正确的用户名"));
} else {
callback();
}
};
const validatePass = (rule, value, callback) => {
if (value.length < 5) {
callback(new Error("密码不能小于5位"));
} else {
callback();
}
};
return {
loginForm: {
username: "admin",
password: "admin"
},
loginRules: {
username: [
{ required: true, trigger: "blur", validator: validateUsername }
],
password: [{ required: true, trigger: "blur", validator: validatePass }]
},
loading: false,
pwdType: "password"
};
},
methods: {
showPwd() {
if (this.pwdType === "password") {
this.pwdType = "";
} else {
this.pwdType = "password";
}
},
handleLogin() {
console.log(11111);
this.$refs.loginForm.validate(valid => {
console.log(valid);
if (valid) {
this.loading = true;
this.$store
.dispatch("Login", this.loginForm)
.then(() => {
this.loading = false;
this.$router.push({ path: "/" });
})
.catch(() => {
this.loading = false;
});
} else {
console.log("error submit!!");
return false;
}
});
}
}
};
</script>
<style rel="stylesheet/scss" lang="scss" scoped>
$bg: #2d3a4b;
$light_gray: #eee;
$dark_gray: #889aa4;
$light_gray: #eee;
/* reset element-ui css */
.login-container {
position: fixed;
height: 100%;
width: 100%;
top: 0;
left: 0;
background-image: url("https://i.loli.net/2019/10/18/buDT4YS6zUMfHst.jpg");
background-position: center;
::v-deep .el-input {
display: inline-block;
height: 47px;
width: 85%;
input {
background: transparent;
border: 0px;
-webkit-appearance: none;
border-radius: 0px;
padding: 12px 5px 12px 15px;
color: $light_gray;
height: 47px;
&:-webkit-autofill {
-webkit-box-shadow: 0 0 0px 1000px $bg inset !important;
-webkit-text-fill-color: #fff !important;
}
}
}
::v-deep .el-form-item {
border: 1px solid rgba(255, 255, 255, 0.1);
background: rgba(0, 0, 0, 0.1);
border-radius: 5px;
color: #454545;
}
.login-from-box {
position: relative;
backdrop-filter: saturate(180%) blur(20px);
.login-form {
position: absolute;
left: 0;
right: 0;
width: 520px;
padding: 35px 35px 15px 35px;
margin: 120px auto;
align-items: center;
color: white;
background: rgba(0, 0, 0, 0.8);
border-radius: 10px;
box-shadow: 0 0.4px 0.6px rgba(0, 0, 0, 0.141),
0 1px 1.3px rgba(0, 0, 0, 0.202), 0 1.9px 2.5px rgba(0, 0, 0, 0.25),
0 3.4px 4.5px rgba(0, 0, 0, 0.298), 0 6.3px 8.4px rgba(0, 0, 0, 0.359),
0 15px 20px rgba(0, 0, 0, 0.5);
.login-btn {
.btn {
position: relative;
width: 100%;
padding: 6px 0;
margin: 10px 0 36px 0;
font-size: 1.2em;
color: white;
background: transparent;
border: 2px solid hsla(204, 70%, 53%, 1);
outline: none;
cursor: pointer;
overflow: hidden;
transition: 0.5s;
&::before {
position: absolute;
content: "";
top: 0;
left: 0;
width: 100%;
height: 100%;
background: linear-gradient(
120deg,
transparent,
hsla(204, 70%, 53%, 0.5),
transparent
);
transform: translateX(-100%);
transition: 0.5s;
}
&:hover {
box-shadow: 0 0 20px 10px hsla(204, 70%, 53%, 0.5);
}
&:hover::before {
transform: translateX(100%);
}
}
}
}
.tips {
font-size: 14px;
color: #fff;
margin-bottom: 10px;
span {
&:first-of-type {
margin-right: 16px;
}
}
}
.svg-container {
padding: 6px 5px 6px 15px;
color: $dark_gray;
vertical-align: middle;
width: 30px;
display: inline-block;
&_login {
font-size: 20px;
}
}
.title {
font-size: 26px;
font-weight: 400;
color: $light_gray;
margin: 0px auto 40px auto;
text-align: center;
font-weight: bold;
}
.show-pwd {
position: absolute;
right: 10px;
top: 7px;
font-size: 16px;
color: $dark_gray;
cursor: pointer;
user-select: none;
}
}
}
</style>
<!-- -->
<template>
<div></div>
</template>
<script>
export default {
data:()=> ({}),
components: {},
mounted() {},
methods: {}
}
</script>
<style rel='stylesheet/scss' lang='scss' scoped>
</style>
\ No newline at end of file
......@@ -2527,6 +2527,11 @@ camelcase@^5.0.0, camelcase@^5.3.1:
resolved "https://registry.npm.taobao.org/camelcase/download/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320"
integrity sha1-48mzFWnhBoEd8kL3FXJaH0xJQyA=
camelcase@^6.0.0:
version "6.0.0"
resolved "https://registry.npm.taobao.org/camelcase/download/camelcase-6.0.0.tgz?cache=0&sync_timestamp=1589682790492&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcamelcase%2Fdownload%2Fcamelcase-6.0.0.tgz#5259f7c30e35e278f1bdc2a4d91230b37cad981e"
integrity sha1-Uln3ww414njxvcKk2RIws3ytmB4=
caniuse-lite@^1.0.30001093:
version "1.0.30001094"
resolved "https://registry.npm.taobao.org/caniuse-lite/download/caniuse-lite-1.0.30001094.tgz?cache=0&sync_timestamp=1593925649372&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcaniuse-lite%2Fdownload%2Fcaniuse-lite-1.0.30001094.tgz#0b11d02e1cdc201348dbd8e3e57bd9b6ce82b175"
......@@ -2613,7 +2618,7 @@ chardet@^0.7.0:
resolved "https://registry.npm.taobao.org/chardet/download/chardet-0.7.0.tgz?cache=0&sync_timestamp=1594010664806&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fchardet%2Fdownload%2Fchardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e"
integrity sha1-kAlISfCTfy7twkJdDSip5fDLrZ4=
"chokidar@>=2.0.0 <4.0.0", chokidar@^3.4.0:
"chokidar@>=2.0.0 <4.0.0":
version "3.4.0"
resolved "https://registry.npm.taobao.org/chokidar/download/chokidar-3.4.0.tgz#b30611423ce376357c765b9b8f904b9fba3c0be8"
integrity sha1-swYRQjzjdjV8dlubj5BLn7o8C+g=
......@@ -2647,6 +2652,21 @@ chokidar@^2.1.8:
optionalDependencies:
fsevents "^1.2.7"
chokidar@^3.4.1:
version "3.4.1"
resolved "https://registry.npm.taobao.org/chokidar/download/chokidar-3.4.1.tgz?cache=0&sync_timestamp=1594864807174&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fchokidar%2Fdownload%2Fchokidar-3.4.1.tgz#e905bdecf10eaa0a0b1db0c664481cc4cbc22ba1"
integrity sha1-6QW97PEOqgoLHbDGZEgcxMvCK6E=
dependencies:
anymatch "~3.1.1"
braces "~3.0.2"
glob-parent "~5.1.0"
is-binary-path "~2.1.0"
is-glob "~4.0.1"
normalize-path "~3.0.0"
readdirp "~3.4.0"
optionalDependencies:
fsevents "~2.1.2"
chownr@^1.1.1:
version "1.1.4"
resolved "https://registry.npm.taobao.org/chownr/download/chownr-1.1.4.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fchownr%2Fdownload%2Fchownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b"
......@@ -3121,24 +3141,24 @@ crypto-random-string@^2.0.0:
resolved "https://registry.npm.taobao.org/crypto-random-string/download/crypto-random-string-2.0.0.tgz?cache=0&sync_timestamp=1583560482221&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcrypto-random-string%2Fdownload%2Fcrypto-random-string-2.0.0.tgz#ef2a7a966ec11083388369baa02ebead229b30d5"
integrity sha1-7yp6lm7BEIM4g2m6oC6+rSKbMNU=
css-loader@^3.5.3:
version "3.6.0"
resolved "https://registry.npm.taobao.org/css-loader/download/css-loader-3.6.0.tgz?cache=0&sync_timestamp=1592056847239&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcss-loader%2Fdownload%2Fcss-loader-3.6.0.tgz#2e4b2c7e6e2d27f8c8f28f61bffcd2e6c91ef645"
integrity sha1-Lkssfm4tJ/jI8o9hv/zS5ske9kU=
css-loader@^4.0.0:
version "4.0.0"
resolved "https://registry.npm.taobao.org/css-loader/download/css-loader-4.0.0.tgz#814434d4e1e2d5f430c70e85e78268db7f3cced1"
integrity sha1-gUQ01OHi1fQwxw6F54Jo2388ztE=
dependencies:
camelcase "^5.3.1"
camelcase "^6.0.0"
cssesc "^3.0.0"
icss-utils "^4.1.1"
loader-utils "^1.2.3"
loader-utils "^2.0.0"
normalize-path "^3.0.0"
postcss "^7.0.32"
postcss-modules-extract-imports "^2.0.0"
postcss-modules-local-by-default "^3.0.2"
postcss-modules-local-by-default "^3.0.3"
postcss-modules-scope "^2.2.0"
postcss-modules-values "^3.0.0"
postcss-value-parser "^4.1.0"
schema-utils "^2.7.0"
semver "^6.3.0"
semver "^7.3.2"
css-select@^1.1.0:
version "1.2.0"
......@@ -3685,7 +3705,7 @@ end-of-stream@^1.0.0, end-of-stream@^1.1.0:
dependencies:
once "^1.4.0"
enhanced-resolve@^4.1.0, enhanced-resolve@^4.1.1:
enhanced-resolve@^4.1.1:
version "4.2.0"
resolved "https://registry.npm.taobao.org/enhanced-resolve/download/enhanced-resolve-4.2.0.tgz?cache=0&sync_timestamp=1594067886559&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fenhanced-resolve%2Fdownload%2Fenhanced-resolve-4.2.0.tgz#5d43bda4a0fd447cb0ebbe71bef8deff8805ad0d"
integrity sha1-XUO9pKD9RHyw675xvvje/4gFrQ0=
......@@ -3694,6 +3714,15 @@ enhanced-resolve@^4.1.0, enhanced-resolve@^4.1.1:
memory-fs "^0.5.0"
tapable "^1.0.0"
enhanced-resolve@^4.3.0:
version "4.3.0"
resolved "https://registry.npm.taobao.org/enhanced-resolve/download/enhanced-resolve-4.3.0.tgz?cache=0&sync_timestamp=1594972208431&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fenhanced-resolve%2Fdownload%2Fenhanced-resolve-4.3.0.tgz#3b806f3bfafc1ec7de69551ef93cca46c1704126"
integrity sha1-O4BvO/r8HsfeaVUe+TzKRsFwQSY=
dependencies:
graceful-fs "^4.1.2"
memory-fs "^0.5.0"
tapable "^1.0.0"
entities@^1.1.1:
version "1.1.2"
resolved "https://registry.npm.taobao.org/entities/download/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56"
......@@ -7084,15 +7113,15 @@ postcss-modules-extract-imports@^2.0.0:
dependencies:
postcss "^7.0.5"
postcss-modules-local-by-default@^3.0.2:
version "3.0.2"
resolved "https://registry.npm.taobao.org/postcss-modules-local-by-default/download/postcss-modules-local-by-default-3.0.2.tgz#e8a6561be914aaf3c052876377524ca90dbb7915"
integrity sha1-6KZWG+kUqvPAUodjd1JMqQ27eRU=
postcss-modules-local-by-default@^3.0.3:
version "3.0.3"
resolved "https://registry.npm.taobao.org/postcss-modules-local-by-default/download/postcss-modules-local-by-default-3.0.3.tgz?cache=0&sync_timestamp=1595733620602&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-modules-local-by-default%2Fdownload%2Fpostcss-modules-local-by-default-3.0.3.tgz#bb14e0cc78279d504dbdcbfd7e0ca28993ffbbb0"
integrity sha1-uxTgzHgnnVBNvcv9fgyiiZP/u7A=
dependencies:
icss-utils "^4.1.1"
postcss "^7.0.16"
postcss "^7.0.32"
postcss-selector-parser "^6.0.2"
postcss-value-parser "^4.0.0"
postcss-value-parser "^4.1.0"
postcss-modules-scope@^2.2.0:
version "2.2.0"
......@@ -7126,7 +7155,7 @@ postcss-selector-parser@^6.0.0, postcss-selector-parser@^6.0.2:
indexes-of "^1.0.1"
uniq "^1.0.1"
postcss-value-parser@^4.0.0, postcss-value-parser@^4.1.0:
postcss-value-parser@^4.1.0:
version "4.1.0"
resolved "https://registry.npm.taobao.org/postcss-value-parser/download/postcss-value-parser-4.1.0.tgz#443f6a20ced6481a2bda4fa8532a6e55d789a2cb"
integrity sha1-RD9qIM7WSBor2k+oUypuVdeJoss=
......@@ -7141,7 +7170,7 @@ postcss@^5.2.17:
source-map "^0.5.6"
supports-color "^3.2.3"
postcss@^7.0.0, postcss@^7.0.14, postcss@^7.0.16, postcss@^7.0.32, postcss@^7.0.5, postcss@^7.0.6:
postcss@^7.0.0, postcss@^7.0.14, postcss@^7.0.32, postcss@^7.0.5, postcss@^7.0.6:
version "7.0.32"
resolved "https://registry.npm.taobao.org/postcss/download/postcss-7.0.32.tgz#4310d6ee347053da3433db2be492883d62cec59d"
integrity sha1-QxDW7jRwU9o0M9sr5JKIPWLOxZ0=
......@@ -8558,10 +8587,10 @@ terser-webpack-plugin@^1.4.3:
webpack-sources "^1.4.0"
worker-farm "^1.7.0"
terser-webpack-plugin@^3.0.7:
version "3.0.7"
resolved "https://registry.npm.taobao.org/terser-webpack-plugin/download/terser-webpack-plugin-3.0.7.tgz#db23b946dcca8954da3ebda3675360bceebdc78e"
integrity sha1-2yO5RtzKiVTaPr2jZ1NgvO69x44=
terser-webpack-plugin@^3.0.8:
version "3.0.8"
resolved "https://registry.npm.taobao.org/terser-webpack-plugin/download/terser-webpack-plugin-3.0.8.tgz#d1a53442a143e09e00c880e8d77c1e79cb05318b"
integrity sha1-0aU0QqFD4J4AyIDo13weecsFMYs=
dependencies:
cacache "^15.0.5"
find-cache-dir "^3.3.1"
......@@ -9137,15 +9166,15 @@ watchpack-chokidar2@^2.0.0:
dependencies:
chokidar "^2.1.8"
watchpack@^1.6.1:
version "1.7.2"
resolved "https://registry.npm.taobao.org/watchpack/download/watchpack-1.7.2.tgz#c02e4d4d49913c3e7e122c3325365af9d331e9aa"
integrity sha1-wC5NTUmRPD5+EiwzJTZa+dMx6ao=
watchpack@^1.7.4:
version "1.7.4"
resolved "https://registry.npm.taobao.org/watchpack/download/watchpack-1.7.4.tgz?cache=0&sync_timestamp=1595633550112&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fwatchpack%2Fdownload%2Fwatchpack-1.7.4.tgz#6e9da53b3c80bb2d6508188f5b200410866cd30b"
integrity sha1-bp2lOzyAuy1lCBiPWyAEEIZs0ws=
dependencies:
graceful-fs "^4.1.2"
neo-async "^2.5.0"
optionalDependencies:
chokidar "^3.4.0"
chokidar "^3.4.1"
watchpack-chokidar2 "^2.0.0"
wbuf@^1.1.0, wbuf@^1.7.3:
......@@ -9256,10 +9285,10 @@ webpack-sources@^1.0.1, webpack-sources@^1.1.0, webpack-sources@^1.4.0, webpack-
source-list-map "^2.0.0"
source-map "~0.6.1"
webpack@^4.43.0:
version "4.43.0"
resolved "https://registry.npm.taobao.org/webpack/download/webpack-4.43.0.tgz?cache=0&sync_timestamp=1594068677838&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fwebpack%2Fdownload%2Fwebpack-4.43.0.tgz#c48547b11d563224c561dad1172c8aa0b8a678e6"
integrity sha1-xIVHsR1WMiTFYdrRFyyKoLimeOY=
webpack@^4.44.0:
version "4.44.0"
resolved "https://registry.npm.taobao.org/webpack/download/webpack-4.44.0.tgz#3b08f88a89470175f036f4a9496b8a0428668802"
integrity sha1-Owj4iolHAXXwNvSpSWuKBChmiAI=
dependencies:
"@webassemblyjs/ast" "1.9.0"
"@webassemblyjs/helper-module-context" "1.9.0"
......@@ -9269,7 +9298,7 @@ webpack@^4.43.0:
ajv "^6.10.2"
ajv-keywords "^3.4.1"
chrome-trace-event "^1.0.2"
enhanced-resolve "^4.1.0"
enhanced-resolve "^4.3.0"
eslint-scope "^4.0.3"
json-parse-better-errors "^1.0.2"
loader-runner "^2.4.0"
......@@ -9282,7 +9311,7 @@ webpack@^4.43.0:
schema-utils "^1.0.0"
tapable "^1.1.3"
terser-webpack-plugin "^1.4.3"
watchpack "^1.6.1"
watchpack "^1.7.4"
webpack-sources "^1.4.1"
websocket-driver@0.6.5:
......