liwei 3 years ago
parent
commit
4e179a2171
10 changed files with 9459 additions and 9180 deletions
  1. +2
    -1
      package.json
  2. +81
    -72
      src/components/IconSelect/index.vue
  3. +42
    -0
      src/components/SvgIcon/index.vue
  4. +2
    -8
      src/icons/index.js
  5. +0
    -22
      src/icons/svgo.yml
  6. +6
    -1
      src/main.js
  7. +198
    -196
      src/views/system/menu/addOrEdit.vue
  8. +2
    -6
      src/views/system/menu/index.vue
  9. +19
    -0
      vue.config.js
  10. +9107
    -8874
      yarn.lock

+ 2
- 1
package.json View File

@ -33,6 +33,7 @@
"eslint-plugin-vue": "^7.0.0",
"less": "^3.0.4",
"less-loader": "^5.0.0",
"prettier": "^2.2.1"
"prettier": "^2.2.1",
"svg-sprite-loader": "^6.0.9"
}
}

+ 81
- 72
src/components/IconSelect/index.vue View File

@ -1,72 +1,81 @@
<template>
<div class="icon-body">
<el-input v-model="name" style="position: relative;" clearable placeholder="请输入图标名称" @clear="filterIcons" @input="filterIcons">
<template #suffix>
<i class="el-icon-search el-input__icon" />
</template>
</el-input>
<div class="icon-list">
<div v-for="(item, index) in iconList" :key="index" @click="selectedIcon(item)">
<svg-icon :icon-class="item" style="height: 30px;width: 16px;" />
<span>{{ item }}</span>
</div>
</div>
</div>
</template>
<script>
import icons from './requireIcons'
export default {
name: 'IconSelect',
data() {
return {
name: '',
iconList: icons
}
},
methods: {
filterIcons() {
if (this.name) {
this.iconList = this.iconList.filter(item => item.includes(this.name))
} else {
this.iconList = icons
}
},
selectedIcon(name) {
this.$emit('selected', name)
document.body.click()
},
reset() {
this.name = ''
this.iconList = icons
}
}
}
</script>
<style lang="less" scoped>
.icon-body {
width: 100%;
box-sizing: border-box;
padding: 10px;
.icon-list {
height: 200px;
overflow-y: auto;
div {
height: 30px;
line-height: 30px;
margin-bottom: -5px;
cursor: pointer;
width: 33%;
float: left;
}
span {
display: inline-block;
vertical-align: -0.15em;
fill: currentColor;
overflow: hidden;
}
}
}
</style>
<template>
<div class="icon-body">
<el-input
v-model="name"
style="position: relative"
clearable
placeholder="请输入图标名称"
@clear="filterIcons"
@input="filterIcons"
suffix-icon="el-icon-search el-input__icon"
/>
<div class="icon-list">
<div
v-for="(item, index) in iconList"
:key="index"
@click="selectedIcon(item)"
>
<svg-icon :icon-class="item" />
<span>{{ item }}</span>
</div>
</div>
</div>
</template>
<script>
import icons from "./requireIcons";
export default {
name: "IconSelect",
data() {
return {
name: "",
iconList: icons,
};
},
methods: {
filterIcons() {
if (this.name) {
this.iconList = this.iconList.filter((item) =>
item.includes(this.name)
);
} else {
this.iconList = icons;
}
},
selectedIcon(name) {
this.$emit("selected", name);
document.body.click();
},
reset() {
this.name = "";
this.iconList = icons;
},
},
};
</script>
<style lang="less" scoped>
.icon-body {
width: 100%;
box-sizing: border-box;
padding: 10px;
.icon-list {
height: 200px;
overflow-y: scroll;
div {
height: 30px;
line-height: 30px;
margin-bottom: -5px;
cursor: pointer;
width: 33%;
float: left;
}
span {
display: inline-block;
vertical-align: -0.15em;
fill: currentColor;
overflow: hidden;
}
}
}
</style>

+ 42
- 0
src/components/SvgIcon/index.vue View File

@ -0,0 +1,42 @@
<template>
<svg :class="svgClass" aria-hidden="true">
<use :xlink:href="iconName"></use>
</svg>
</template>
<script>
export default {
name: 'svg-icon',
props: {
iconClass: {
type: String,
required: true
},
className: {
type: String
}
},
computed: {
iconName() {
return `#icon-${this.iconClass}`
},
svgClass() {
if (this.className) {
return 'svg-icon ' + this.className
} else {
return 'svg-icon'
}
}
}
}
</script>
<style scoped>
.svg-icon {
width: 30px;
height: 16px;
vertical-align: 0.3em;
fill: currentColor;
overflow: hidden;
}
</style>

+ 2
- 8
src/icons/index.js View File

@ -1,9 +1,3 @@
import Vue from 'vue'
import SvgIcon from '@/components/SvgIcon'// svg component
// register globally
Vue.component('svg-icon', SvgIcon)
const req = require.context('./svg', false, /\.svg$/)
const requireAll = requireContext => requireContext.keys().map(requireContext)
requireAll(req)
const req = require.context('./svg', false, /\.svg$/)
requireAll(req)

+ 0
- 22
src/icons/svgo.yml View File

@ -1,22 +0,0 @@
# replace default config
# multipass: true
# full: true
plugins:
# - name
#
# or:
# - name: false
# - name: true
#
# or:
# - name:
# param1: 1
# param2: 2
- removeAttrs:
attrs:
- 'fill'
- 'fill-rule'

+ 6
- 1
src/main.js View File

@ -3,19 +3,24 @@ import App from "./App.vue";
import router from "./router";
import store from "./store";
import ElementPlus from "element-plus";
import './icons'
import "element-plus/lib/theme-chalk/index.css";
import "dayjs/locale/zh-cn";
import locale from "element-plus/lib/locale/lang/zh-cn";
import "./assets/css/base.css";
import locale from "element-plus/lib/locale/lang/zh-cn";
import Pagination from "@/components/Pagination";
import { getStanderOne } from "@/server/api.js";
import { getColumnName } from "@/utils/allField.js";
import { parseTime, resetForm } from "@/utils/costum";
import SvgIcon from '@/components/SvgIcon' // svg组件
// 注册到全局
const app = createApp(App);
app.use(store);
app.use(router);
app.use(ElementPlus, { locale });
app.component('svg-icon', SvgIcon)
app.component("Pagination", Pagination);
app.config.globalProperties.getStanderOne = getStanderOne;
app.config.globalProperties.getColumnName = getColumnName;


+ 198
- 196
src/views/system/menu/addOrEdit.vue View File

@ -1,197 +1,199 @@
<template>
<el-dialog
title="配置菜单"
model-value
width="600px"
:before-close="handleClose"
>
<el-form ref="form" :model="formData" :rules="rules" label-width="80px">
<el-row>
<el-col :span="24">
<el-form-item label="上级菜单">
<el-select
v-model="formData.parent_name"
placeholder="选择上级菜单"
>
<el-option value="" />
<el-tree
:data="treeMenu"
:props="defaultProps"
:expand-on-click-node="false"
@node-click="handleNodeClick"
></el-tree>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="菜单标题" prop="title">
<el-input v-model="formData.title" placeholder="请输入菜单标题" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="显示排序">
<el-input-number
v-model="formData.sort"
controls-position="right"
:min="0"
/>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="菜单类型" prop="menu_type">
<el-radio-group v-model="formData.menu_type">
<el-radio label="M">目录</el-radio>
<el-radio label="C">菜单</el-radio>
<el-radio label="F">按钮</el-radio>
<el-radio label="A">接口</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="24" v-if="formData.menu_type == 'A'">
<el-form-item label="请求方式">
<el-radio-group v-model="formData.action">
<el-radio label="GET">GET</el-radio>
<el-radio label="POST">POST</el-radio>
<el-radio label="PUT">PUT</el-radio>
<el-radio label="DELETE">DELETE</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="菜单图标">
<el-popover
placement="bottom"
width="440px"
v-model:visible="visible"
>
<IconSelect ref="iconSelect" @selected="selected" />
<template #reference>
<el-input v-model="formData.icon" placeholder="点击选择图标" readonly>
<template #prefix>
<svg-icon v-if="formData.icon" :icon-class="formData.icon" style="height: 30px;width: 16px;" />
<i v-else class="el-icon-search el-input__icon" />
</template>
</el-input>
</template>
</el-popover>
</el-form-item>
</el-col>
<el-col
:span="12"
v-if="formData.menu_type == 'M' || formData.menu_type == 'C'"
>
<el-form-item label="路由名称" prop="menu_name">
<el-input
v-model="formData.menu_name"
placeholder="请输入路由名称"
/>
</el-form-item>
</el-col>
<el-col
v-if="formData.menu_type == 'M' || formData.menu_type == 'C'"
:span="12"
>
<el-form-item label="组件路径" prop="component">
<el-input
v-model="formData.component"
placeholder="请输入组件路径"
/>
</el-form-item>
</el-col>
<el-col :span="12" v-if="formData.menu_type != 'F'">
<el-form-item label="路由地址" prop="path">
<el-input v-model="formData.path" placeholder="请输入路由地址" />
</el-form-item>
</el-col>
<el-col
:span="12"
v-if="formData.menu_type == 'F' || formData.menu_type == 'C'"
>
<el-form-item label="权限标识">
<el-input
v-model="formData.permission"
placeholder="请权限标识"
maxlength="50"
/>
</el-form-item>
</el-col>
</el-row>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button
type="primary"
class="dialog-submit-button"
@click="submitForm"
> </el-button
>
<el-button class="dialog-cancel-button" @click="handleClose"
> </el-button
>
</span>
</template>
</el-dialog>
</template>
<script>
import { getTreeMenu } from "@/server/system/menu";
import IconSelect from '@/components/IconSelect'
export default {
components: { IconSelect },
data() {
return {
formData: {},
//
treeMenu: [],
defaultProps: {
children: 'children',
label: 'title',
disabled:'disabled'
},
};
},
methods: {
//
submitForm() {
console.log(this.formData);
},
// /
handleClose() {
this.$emit('setIsAddOrEdit')
},
//
getTreeMenu() {
getTreeMenu().then(({code, data}) => {
if(code ==200 && data){
let treeMenu = [{ menu_id: 0, disabled:true, title: '主类目', children: [] }]
treeMenu[0].children = data;
this.treeMenu=treeMenu;
}
})
},
//
handleNodeClick({parent_id, title}) {
this.formData.parent_id=parent_id;
this.formData.parent_name=title;
},
//
selected(name){
console.log(name);
this.formData.icon=name;
}
},
created(){
this.getTreeMenu();
}
};
</script>
<style lang="less" scoped>
/* 去除tree上面的一行高度 */
.el-scrollbar .el-scrollbar__view .el-select-dropdown__item {
height: auto;
padding: 0;
}
<template>
<el-dialog
title="配置菜单"
model-value
width="600px"
:before-close="handleClose"
>
<el-form ref="form" :model="formData" :rules="rules" label-width="80px">
<el-row>
<el-col :span="24">
<el-form-item label="上级菜单">
<el-select
v-model="formData.parent_name"
placeholder="选择上级菜单"
>
<el-option value="" />
<el-tree
:data="treeMenu"
:props="defaultProps"
:expand-on-click-node="false"
@node-click="handleNodeClick"
></el-tree>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="菜单标题" prop="title">
<el-input v-model="formData.title" placeholder="请输入菜单标题" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="显示排序">
<el-input-number
v-model="formData.sort"
controls-position="right"
:min="0"
/>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="菜单类型" prop="menu_type">
<el-radio-group v-model="formData.menu_type">
<el-radio label="M">目录</el-radio>
<el-radio label="C">菜单</el-radio>
<el-radio label="F">按钮</el-radio>
<el-radio label="A">接口</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="24" v-if="formData.menu_type == 'A'">
<el-form-item label="请求方式">
<el-radio-group v-model="formData.action">
<el-radio label="GET">GET</el-radio>
<el-radio label="POST">POST</el-radio>
<el-radio label="PUT">PUT</el-radio>
<el-radio label="DELETE">DELETE</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="菜单图标">
<el-popover
placement="bottom"
width="440px"
v-model:visible="visible"
>
<IconSelect ref="iconSelect" @selected="selected" />
<template #reference>
<el-input v-model="formData.icon" placeholder="点击选择图标" readonly>
<template #prefix>
<svg-icon v-if="formData.icon" :icon-class="formData.icon" style="margin-top: 12px;" />
<i v-else class="el-icon-search el-input__icon" />
</template>
</el-input>
</template>
</el-popover>
</el-form-item>
</el-col>
<el-col
:span="12"
v-if="formData.menu_type == 'M' || formData.menu_type == 'C'"
>
<el-form-item label="路由名称" prop="menu_name">
<el-input
v-model="formData.menu_name"
placeholder="请输入路由名称"
/>
</el-form-item>
</el-col>
<el-col
v-if="formData.menu_type == 'M' || formData.menu_type == 'C'"
:span="12"
>
<el-form-item label="组件路径" prop="component">
<el-input
v-model="formData.component"
placeholder="请输入组件路径"
/>
</el-form-item>
</el-col>
<el-col :span="12" v-if="formData.menu_type != 'F'">
<el-form-item label="路由地址" prop="path">
<el-input v-model="formData.path" placeholder="请输入路由地址" />
</el-form-item>
</el-col>
<el-col
:span="12"
v-if="formData.menu_type == 'F' || formData.menu_type == 'C'"
>
<el-form-item label="权限标识">
<el-input
v-model="formData.permission"
placeholder="请权限标识"
maxlength="50"
/>
</el-form-item>
</el-col>
</el-row>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button
type="primary"
class="dialog-submit-button"
@click="submitForm"
> </el-button
>
<el-button class="dialog-cancel-button" @click="handleClose"
> </el-button
>
</span>
</template>
</el-dialog>
</template>
<script>
import { getTreeMenu } from "@/server/system/menu";
import IconSelect from '@/components/IconSelect';
export default {
components:{
IconSelect
},
data() {
return {
formData: {},
//
treeMenu: [],
defaultProps: {
children: 'children',
label: 'title',
disabled:'disabled'
},
};
},
methods: {
//
submitForm() {
console.log(this.formData);
},
// /
handleClose() {
this.$emit('setIsAddOrEdit')
},
//
getTreeMenu() {
getTreeMenu().then(({code, data}) => {
if(code ==200 && data){
let treeMenu = [{ menu_id: 0, disabled:true, title: '主类目', children: [] }]
treeMenu[0].children = data;
this.treeMenu=treeMenu;
}
})
},
//
handleNodeClick({parent_id, title}) {
this.formData.parent_id=parent_id;
this.formData.parent_name=title;
},
//
selected(name){
console.log(name);
this.formData.icon=name;
}
},
created(){
this.getTreeMenu();
}
};
</script>
<style lang="less" scoped>
/* 去除tree上面的一行高度 */
.el-scrollbar .el-scrollbar__view .el-select-dropdown__item {
height: auto;
padding: 0;
}
</style>

+ 2
- 6
src/views/system/menu/index.vue View File

@ -56,13 +56,9 @@
<el-table-column
label="创建时间"
align="center"
prop="createtime"
prop="create_by"
width="180"
>
<template #default="scope">
<span>{{ parseTime(scope.row.createtime) }}</span>
</template>
</el-table-column>
/>
<el-table-column
label="操作"
align="center"


+ 19
- 0
vue.config.js View File

@ -1,4 +1,23 @@
const path = require('path')
function resolve(dir) {
return path.join(__dirname, '.', dir)
}
module.exports = {
chainWebpack: config => {
config.module.rules.delete("svg"); //重点:删除默认配置中处理svg,
config.module
.rule('svg-sprite-loader')
.test(/\.svg$/)
.include
.add(resolve('src/icons')) //处理svg目录(根据你建的文件路径)
.end()
.use('svg-sprite-loader')
.loader('svg-sprite-loader')
.options({
symbolId: 'icon-[name]'
})
},
// 基本路径
publicPath: "./",
// 构建输出目录


+ 9107
- 8874
yarn.lock
File diff suppressed because it is too large
View File


Loading…
Cancel
Save