Merge branch 'master' of https://github.com/zouzhibin/vue-admin-perfect into vue-i18n
Conflicts: src/layout/TagsView/index.vue
This commit is contained in:
commit
d1ed7b3927
11
src/App.vue
11
src/App.vue
|
|
@ -25,13 +25,6 @@
|
||||||
-moz-osx-font-smoothing: grayscale;
|
-moz-osx-font-smoothing: grayscale;
|
||||||
color: #2c3e50;
|
color: #2c3e50;
|
||||||
}
|
}
|
||||||
html,
|
|
||||||
body {
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
body{
|
|
||||||
background: #f6f8f9;
|
|
||||||
}
|
|
||||||
.el-pager li:focus {
|
.el-pager li:focus {
|
||||||
border: none;
|
border: none;
|
||||||
}
|
}
|
||||||
|
|
@ -43,8 +36,4 @@
|
||||||
border: none!important;
|
border: none!important;
|
||||||
outline: none!important;
|
outline: none!important;
|
||||||
}
|
}
|
||||||
* {
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,218 @@
|
||||||
|
<template>
|
||||||
|
<div class="zb-pro-table">
|
||||||
|
<div class="header">
|
||||||
|
<el-form :inline="true" :model="formInline" class="demo-form-inline search-form" ref="ruleFormRef" >
|
||||||
|
<template v-for="(item, index) in formSearchData" :key="index">
|
||||||
|
<el-form-item :label="item.label" v-show="isExpand ? isExpand : index < 2">
|
||||||
|
<template v-if="item.valueType === 'input'">
|
||||||
|
<el-input v-model="formInline[item.name]" :placeholder="`请输入${item.label}`" />
|
||||||
|
</template>
|
||||||
|
<template v-if="item.valueType === 'select'">
|
||||||
|
<el-select v-model="formInline[item.name]" :placeholder="`请选择${item.label}`">
|
||||||
|
<el-option
|
||||||
|
v-for="ite in item.options"
|
||||||
|
:key="ite.value"
|
||||||
|
:label="ite.label"
|
||||||
|
:value="ite.value"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</template>
|
||||||
|
</el-form-item>
|
||||||
|
</template>
|
||||||
|
</el-form>
|
||||||
|
<div class="search">
|
||||||
|
<el-button type="primary" @click="onSubmit" :icon="Search">查询</el-button>
|
||||||
|
<el-button @click="reset(ruleFormRef)">重置</el-button>
|
||||||
|
<el-button link type="primary" @click="isExpand = !isExpand">{{ isExpand ? '合并' : '展开'}}<el-icon>
|
||||||
|
<arrow-down v-if="!isExpand" />
|
||||||
|
<arrow-up v-else /> </el-icon
|
||||||
|
></el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!----------底部---------------------->
|
||||||
|
<div class="footer">
|
||||||
|
<!-----------工具栏操作工具----------------->
|
||||||
|
<div class="operator">
|
||||||
|
<slot name="btn"></slot>
|
||||||
|
</div>
|
||||||
|
<!-- ------------表格--------------->
|
||||||
|
<el-table
|
||||||
|
v-loading="loading"
|
||||||
|
@selection-change="(val) => emit('selection-change', val)"
|
||||||
|
:data="list"
|
||||||
|
:border="true"
|
||||||
|
>
|
||||||
|
<template v-for="item in columns">
|
||||||
|
<el-table-column
|
||||||
|
v-if="item.type"
|
||||||
|
:type="item.type"
|
||||||
|
:width="item.width"
|
||||||
|
:align="item.align"
|
||||||
|
:fixed="item.fixed"
|
||||||
|
:label="item.label"
|
||||||
|
/>
|
||||||
|
<el-table-column
|
||||||
|
v-else
|
||||||
|
:prop="item.name"
|
||||||
|
:width="item.width"
|
||||||
|
:align="item.align"
|
||||||
|
:fixed="item.fixed"
|
||||||
|
:label="item.label"
|
||||||
|
>
|
||||||
|
<template #default="scope">
|
||||||
|
<span v-if="!item.slot">{{ scope.row[item.name] }}</span>
|
||||||
|
<slot v-else :name="item.name" :item="item" :row="scope.row"></slot>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</template>
|
||||||
|
</el-table>
|
||||||
|
<div class="pagination">
|
||||||
|
<el-pagination
|
||||||
|
v-model:currentPage="currentPage1"
|
||||||
|
:page-size="10"
|
||||||
|
background
|
||||||
|
layout="total, sizes, prev, pager, next, jumper"
|
||||||
|
:total="data.length"
|
||||||
|
@size-change="handleSizeChange"
|
||||||
|
@current-change="handleCurrentChange"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { computed, ref } from 'vue'
|
||||||
|
import {Search } from '@element-plus/icons-vue'
|
||||||
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||||
|
import type { FormInstance } from 'element-plus'
|
||||||
|
const ruleFormRef = ref<FormInstance>()
|
||||||
|
const emit = defineEmits(['reset', 'onSubmit', 'selection-change'])
|
||||||
|
let props = defineProps({
|
||||||
|
columns: {
|
||||||
|
type: Array,
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
type: Array,
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
|
loading: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const currentPage1 = ref(1)
|
||||||
|
// 收缩展开
|
||||||
|
const isExpand = ref(false)
|
||||||
|
const handleSizeChange = (val: number) => {
|
||||||
|
console.log(`${val} items per page`)
|
||||||
|
}
|
||||||
|
const handleCurrentChange = (val: number) => {
|
||||||
|
console.log(`current page: ${val}`)
|
||||||
|
currentPage1.value = val
|
||||||
|
}
|
||||||
|
|
||||||
|
const list = computed(() => {
|
||||||
|
let arr = JSON.parse(JSON.stringify(props.data))
|
||||||
|
return arr.splice((currentPage1.value - 1) * 10, 10)
|
||||||
|
})
|
||||||
|
|
||||||
|
const listLoading = ref(false)
|
||||||
|
const confirmEdit = (row) => {
|
||||||
|
row.edit = false
|
||||||
|
}
|
||||||
|
const cancelEdit = (row) => {
|
||||||
|
row.edit = false
|
||||||
|
}
|
||||||
|
|
||||||
|
import { reactive } from 'vue'
|
||||||
|
|
||||||
|
let obj = {}
|
||||||
|
let search = []
|
||||||
|
for (let item of props.columns) {
|
||||||
|
if (item.inSearch) {
|
||||||
|
obj[item.name] = null
|
||||||
|
}
|
||||||
|
if (item.inSearch) {
|
||||||
|
search.push(item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const formSearchData = ref(search)
|
||||||
|
const formInline = reactive(obj)
|
||||||
|
|
||||||
|
const onSubmit = () => {
|
||||||
|
console.log('submit!', formInline)
|
||||||
|
emit('onSubmit', formInline)
|
||||||
|
}
|
||||||
|
|
||||||
|
const reset = (formEl: FormInstance | undefined) => {
|
||||||
|
formSearchData.value.forEach((item) => {
|
||||||
|
formInline[item.name] = null
|
||||||
|
})
|
||||||
|
emit('reset')
|
||||||
|
}
|
||||||
|
const deleteAction = (row) => {
|
||||||
|
ElMessageBox.confirm('你确定要删除当前项吗?', '温馨提示', {
|
||||||
|
confirmButtonText: '确定',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
type: 'warning',
|
||||||
|
draggable: true,
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
list.value = list.value.filter((item) => item.id !== row.id)
|
||||||
|
ElMessage.success('删除成功')
|
||||||
|
})
|
||||||
|
.catch(() => {})
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.edit-input {
|
||||||
|
padding-right: 100px;
|
||||||
|
}
|
||||||
|
.cancel-btn {
|
||||||
|
position: absolute;
|
||||||
|
right: 15px;
|
||||||
|
top: 10px;
|
||||||
|
}
|
||||||
|
.zb-pro-table {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display:flex;
|
||||||
|
flex-direction:column;
|
||||||
|
|
||||||
|
.header{
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
.footer{
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
overflow: hidden;
|
||||||
|
.operator{
|
||||||
|
margin-bottom: 15px
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.search-form{
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
.search{
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
::v-deep{
|
||||||
|
.el-table__header th{
|
||||||
|
font-size: 15px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #252525;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.pagination{
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
padding-top: 20px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<el-breadcrumb class="app-breadcrumb" separator="/">
|
<el-breadcrumb class="app-breadcrumb" separator="/">
|
||||||
<transition-group name="breadcrumb">
|
<transition-group name="breadcrumb" mode="out-in">
|
||||||
<el-breadcrumb-item v-for="(item, index) in obj.levelList" :key="item.path">
|
<el-breadcrumb-item v-for="(item, index) in obj.levelList" :key="item.path">
|
||||||
<span
|
<span
|
||||||
v-if="item.redirect === 'noRedirect' || index == obj.levelList.length - 1"
|
v-if="item.redirect === 'noRedirect' || index == obj.levelList.length - 1"
|
||||||
|
|
|
||||||
|
|
@ -10,17 +10,20 @@
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.m-container-layout {
|
.m-container-layout {
|
||||||
padding: 20px;
|
|
||||||
box-sizing: border-box;
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
padding: 20px;
|
||||||
|
box-sizing: border-box;
|
||||||
.m-container-layout-inner {
|
.m-container-layout-inner {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
||||||
background: white;
|
background: white;
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
min-height: 100%;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -131,8 +131,9 @@
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
.header {
|
.header {
|
||||||
height: 60px;
|
height: 50px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
border-bottom: 1px solid #eee;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 0 10px;
|
padding: 0 10px;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<section class="app-main" v-if="isReload">
|
<div class="app-main" v-if="isReload">
|
||||||
<router-view v-slot="{ Component, route }">
|
<router-view v-slot="{ Component, route }">
|
||||||
<transition name="fade-slide" mode="out-in" appear>
|
<transition name="fade-slide" mode="out-in" appear>
|
||||||
<keep-alive v-if="route.meta && route.meta.keepAlive">
|
<keep-alive v-if="route.meta && route.meta.keepAlive">
|
||||||
|
|
@ -9,7 +9,7 @@
|
||||||
</transition>
|
</transition>
|
||||||
</router-view>
|
</router-view>
|
||||||
<u-theme />
|
<u-theme />
|
||||||
</section>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
|
@ -29,18 +29,11 @@
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.app-main {
|
.app-main {
|
||||||
//padding: 20px;
|
flex: 1;
|
||||||
/*padding-top: 110px;*/
|
display: flex;
|
||||||
//min-height: 100%;
|
|
||||||
//overflow: auto;
|
|
||||||
//flex: 1;
|
|
||||||
//overflow: auto;
|
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
height: 100%;
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
//padding-top: 70px;
|
|
||||||
// background: white;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//// 主内容区动画
|
//// 主内容区动画
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ defineProps<{ isCollapse: boolean }>();
|
||||||
.sidebar-logo-container {
|
.sidebar-logo-container {
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 60px;
|
height: 50px;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
background: #2b2f3a;
|
background: #2b2f3a;
|
||||||
|
|
|
||||||
|
|
@ -26,9 +26,9 @@
|
||||||
</better-scroll>
|
</better-scroll>
|
||||||
</div>
|
</div>
|
||||||
<el-dropdown trigger="click">
|
<el-dropdown trigger="click">
|
||||||
<el-button class="el-dropdown-link" type="primary">
|
<div class="item-tag-wrap more">
|
||||||
{{ $t("tagsView.more") }} <el-icon class="el-icon--right"><arrow-down /></el-icon>
|
<div class="tags-view-item"> {{ $t("tagsView.more") }} <el-icon class="el-icon--right"><arrow-down /></el-icon></div>
|
||||||
</el-button>
|
</div>
|
||||||
<template #dropdown>
|
<template #dropdown>
|
||||||
<el-dropdown-menu>
|
<el-dropdown-menu>
|
||||||
<el-dropdown-item @click="refresh">{{ $t("tagsView.refresh") }}</el-dropdown-item>
|
<el-dropdown-item @click="refresh">{{ $t("tagsView.refresh") }}</el-dropdown-item>
|
||||||
|
|
@ -252,7 +252,10 @@
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding-left: 10px;
|
padding-left: 10px;
|
||||||
.tags-view {
|
.tags-view {
|
||||||
|
height: 30px;
|
||||||
background: white;
|
background: white;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
@ -280,7 +283,7 @@
|
||||||
position: relative;
|
position: relative;
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 6px 10px;
|
padding: 4px 12px;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
|
|
@ -308,10 +311,19 @@
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
font-size: 12px;
|
||||||
.tags-inner {
|
.tags-inner {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.more{
|
||||||
|
background-color: $primaryColor;
|
||||||
|
color: white;
|
||||||
|
.tags-view-item{
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,10 @@
|
||||||
hideSliderLayout: mode === 'horizontal',
|
hideSliderLayout: mode === 'horizontal',
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
|
<div
|
||||||
|
:style="{
|
||||||
|
height:`${showTag?80:50}px`
|
||||||
|
}"></div>
|
||||||
<u-header />
|
<u-header />
|
||||||
<div class="m-container-content" :class="{ 'app-main-hide-tag': !showTag }">
|
<div class="m-container-content" :class="{ 'app-main-hide-tag': !showTag }">
|
||||||
<u-main />
|
<u-main />
|
||||||
|
|
@ -25,29 +29,29 @@
|
||||||
|
|
||||||
import { useResizeHandler } from './hooks/useResizeHandler'
|
import { useResizeHandler } from './hooks/useResizeHandler'
|
||||||
|
|
||||||
const SettingStore = useSettingStore()
|
const SettingStore = useSettingStore()
|
||||||
|
|
||||||
// 是否折叠
|
// 是否折叠
|
||||||
const isCollapse = computed(() => {
|
const isCollapse = computed(() => {
|
||||||
return !SettingStore.isCollapse
|
return !SettingStore.isCollapse
|
||||||
})
|
})
|
||||||
let { device } = useResizeHandler()
|
let { device } = useResizeHandler()
|
||||||
// 当屏幕切换的时候进行变换
|
// 当屏幕切换的时候进行变换
|
||||||
const classObj = computed(() => {
|
const classObj = computed(() => {
|
||||||
return {
|
return {
|
||||||
hideSidebar: !SettingStore.isCollapse,
|
hideSidebar: !SettingStore.isCollapse,
|
||||||
openSidebar: SettingStore.isCollapse,
|
openSidebar: SettingStore.isCollapse,
|
||||||
withoutAnimation: SettingStore.withoutAnimation,
|
withoutAnimation: SettingStore.withoutAnimation,
|
||||||
mobile: device.value === 'mobile',
|
mobile: device.value === 'mobile',
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
// 移动端点击
|
// 移动端点击
|
||||||
const handleClickOutside = () => {
|
const handleClickOutside = () => {
|
||||||
SettingStore.closeSideBar({ withoutAnimation: false })
|
SettingStore.closeSideBar({ withoutAnimation: false })
|
||||||
}
|
}
|
||||||
const showTag = computed(() => SettingStore.themeConfig.showTag)
|
const showTag = computed(() => SettingStore.themeConfig.showTag)
|
||||||
|
|
||||||
const mode = computed(() => SettingStore.themeConfig.mode)
|
const mode = computed(() => SettingStore.themeConfig.mode)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|
@ -81,14 +85,9 @@
|
||||||
z-index: 90;
|
z-index: 90;
|
||||||
}
|
}
|
||||||
.m-container-content {
|
.m-container-content {
|
||||||
//padding: 20px;
|
display: flex;
|
||||||
/*background: #f6f8f9;*/
|
flex: 1;
|
||||||
padding-top: 93px;
|
|
||||||
box-sizing: border-box;
|
|
||||||
height: 100vh;
|
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
box-sizing: border-box;
|
||||||
.app-main-hide-tag {
|
|
||||||
padding-top: 80px;
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@ interface extendRoute {
|
||||||
|
|
||||||
// 引入组件
|
// 引入组件
|
||||||
//
|
//
|
||||||
import permissionRouter from './modules/permission'
|
|
||||||
import tableRouter from './modules/table'
|
import tableRouter from './modules/table'
|
||||||
import dataScreenRouter from './modules/dataScreen'
|
import dataScreenRouter from './modules/dataScreen'
|
||||||
import errorRouter from './modules/error'
|
import errorRouter from './modules/error'
|
||||||
|
|
@ -110,9 +109,7 @@ export const asyncRoutes = [
|
||||||
dataScreenRouter,
|
dataScreenRouter,
|
||||||
chartsRouter,
|
chartsRouter,
|
||||||
tableRouter,
|
tableRouter,
|
||||||
|
|
||||||
chatRouter,
|
chatRouter,
|
||||||
// componentsRouter,
|
|
||||||
othersRouter,
|
othersRouter,
|
||||||
nestedRouter,
|
nestedRouter,
|
||||||
excelRouter,
|
excelRouter,
|
||||||
|
|
@ -121,8 +118,6 @@ export const asyncRoutes = [
|
||||||
externalLink,
|
externalLink,
|
||||||
clipboardTable,
|
clipboardTable,
|
||||||
systemRouter,
|
systemRouter,
|
||||||
permissionRouter,
|
|
||||||
|
|
||||||
{
|
{
|
||||||
path: '/:pathMatch(.*)',
|
path: '/:pathMatch(.*)',
|
||||||
redirect: '/error/404'
|
redirect: '/error/404'
|
||||||
|
|
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
/** When your routing table is too long, you can split it into small modules**/
|
|
||||||
|
|
||||||
import Layout from "@/layout/index.vue";
|
|
||||||
|
|
||||||
const permissionRouter = {
|
|
||||||
path: '/permission',
|
|
||||||
component: Layout,
|
|
||||||
redirect: 'noRedirect',
|
|
||||||
name: 'permission',
|
|
||||||
alwaysShow: true, // 总是显示根目录
|
|
||||||
meta: {
|
|
||||||
title: '权限测试页',
|
|
||||||
icon: 'trend-charts', roles:['other']
|
|
||||||
},
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: 'page',
|
|
||||||
component: () => import('@/views/permission/page.vue'),
|
|
||||||
name: 'page',
|
|
||||||
meta: { title: '页面权限', icon: 'trend-charts', roles:['other'] }
|
|
||||||
},
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
export default permissionRouter
|
|
||||||
|
|
@ -12,6 +12,12 @@ const systemRouter = {
|
||||||
icon: 'ElementPlus'
|
icon: 'ElementPlus'
|
||||||
},
|
},
|
||||||
children: [
|
children: [
|
||||||
|
{
|
||||||
|
path: 'page',
|
||||||
|
component: () => import('@/views/system/page.vue'),
|
||||||
|
name: 'page',
|
||||||
|
meta: { title: '页面权限', icon: 'trend-charts', roles:['other'] }
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: 'user',
|
path: 'user',
|
||||||
component: () => import('@/views/system/user.vue'),
|
component: () => import('@/views/system/user.vue'),
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,13 @@ export const useUserStore = defineStore({
|
||||||
resolve(this.roles)
|
resolve(this.roles)
|
||||||
} )
|
} )
|
||||||
},
|
},
|
||||||
|
// 获取用户信息 ,如实际应用中 可以通过token通过请求接口在这里获取用户信息
|
||||||
|
getInfo(roles) {
|
||||||
|
return new Promise((resolve, reject) =>{
|
||||||
|
this.roles = roles
|
||||||
|
resolve(roles)
|
||||||
|
} )
|
||||||
|
},
|
||||||
// 退出
|
// 退出
|
||||||
logout() {
|
logout() {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,18 @@
|
||||||
|
html,
|
||||||
|
body {
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
overflow: visible;
|
||||||
|
overflow-x: hidden;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
body{
|
||||||
|
background: #f6f8f9;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* 常用 flex */
|
/* 常用 flex */
|
||||||
.flex-center {
|
.flex-center {
|
||||||
|
|
@ -15,9 +30,42 @@
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 移动端的时候由于屏幕变小隐藏头部导航栏 */
|
||||||
@media screen and ( max-width: 540px ) {
|
@media screen and ( max-width: 540px ) {
|
||||||
.app-breadcrumb{
|
.app-breadcrumb{
|
||||||
display: none!important;
|
display: none!important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** 设置滚动条 **/
|
||||||
|
::-webkit-scrollbar {
|
||||||
|
width: 7px;
|
||||||
|
height: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
::-webkit-scrollbar-track {
|
||||||
|
background-color: rgb(0 0 0 / 5%);
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-thumb {
|
||||||
|
// background: rgba(0, 0, 0, 0.6);
|
||||||
|
background-color: rgb(144 147 153 / 30%);
|
||||||
|
// background-color: rgba(144, 147, 153, 0.3);
|
||||||
|
border-radius: 2px;
|
||||||
|
box-shadow: inset 0 0 6px rgb(0 0 0 / 20%);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* nprogress样式 */
|
||||||
|
#nprogress .bar {
|
||||||
|
background: $primaryColor !important;
|
||||||
|
}
|
||||||
|
#nprogress .spinner-icon {
|
||||||
|
border-top-color: $primaryColor !important;
|
||||||
|
border-left-color: $primaryColor !important;
|
||||||
|
}
|
||||||
|
#nprogress .peg {
|
||||||
|
box-shadow: 0 0 10px $primaryColor, 0 0 5px $primaryColor !important;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
@import "./common.scss";
|
|
||||||
@import './variables.scss';
|
@import './variables.scss';
|
||||||
@import './sidebar.scss';
|
@import './sidebar.scss';
|
||||||
@import './transition.scss';
|
@import './transition.scss';
|
||||||
|
@import "./common.scss";
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -40,15 +40,30 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// 面包屑动画
|
// 面包屑动画 方案1
|
||||||
.breadcrumb-enter-active {
|
//.breadcrumb-enter-active {
|
||||||
transition: all 0.25s;
|
// transition: all 0.25s;
|
||||||
|
//}
|
||||||
|
//.breadcrumb-enter-from,
|
||||||
|
//.breadcrumb-leave-active {
|
||||||
|
// opacity: 0;
|
||||||
|
// transform: translateX(30px) skewX(-50deg);
|
||||||
|
//}
|
||||||
|
/* 面包屑动画 方案2 */
|
||||||
|
.breadcrumb-enter-active,
|
||||||
|
.breadcrumb-leave-active {
|
||||||
|
transition: all 0.2s ease;
|
||||||
}
|
}
|
||||||
.breadcrumb-enter-from,
|
.breadcrumb-enter-from,
|
||||||
.breadcrumb-leave-active {
|
.breadcrumb-leave-active {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transform: translateX(30px) skewX(-50deg);
|
transform: translateX(10px);
|
||||||
}
|
}
|
||||||
|
.breadcrumb-leave-active {
|
||||||
|
position: absolute;
|
||||||
|
z-index: -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
.fade-transform-leave-active,
|
.fade-transform-leave-active,
|
||||||
.fade-transform-enter-active {
|
.fade-transform-enter-active {
|
||||||
|
|
|
||||||
|
|
@ -11,12 +11,12 @@
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.echarts-map {
|
.echarts-map {
|
||||||
box-sizing: border-box;
|
position: relative;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
background: #001540;
|
background: #001540;
|
||||||
height: calc(100vh - 93px);
|
box-sizing: border-box;
|
||||||
position: relative;
|
|
||||||
.info {
|
.info {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 0;
|
left: 0;
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,14 @@
|
||||||
<template>
|
<template>
|
||||||
<u-container-layout>
|
<u-container-layout>
|
||||||
<el-input v-model="inputData" placeholder="请输入" style="width: 400px; max-width: 100%" />
|
<div style="display: flex">
|
||||||
<el-button type="primary" @click="handleQrcode(1)">
|
<el-input v-model="inputData" placeholder="请输入" style="width: 400px; max-width: 100%" />
|
||||||
<el-icon style="margin-right: 6px"><collection /></el-icon> 生成普通二维码
|
<el-button type="primary" @click="handleQrcode(1)">
|
||||||
</el-button>
|
<el-icon style="margin-right: 6px"><collection /></el-icon> 生成普通二维码
|
||||||
<el-button type="primary" @click="handleQrcode(2)">生成带logo</el-button>
|
</el-button>
|
||||||
<el-button type="primary" @click="handleQrcode(3)">生成随机颜色二维码</el-button>
|
<el-button type="primary" @click="handleQrcode(2)">生成带logo</el-button>
|
||||||
<el-button type="primary" @click="handleQrcode(4)">下载</el-button>
|
<el-button type="primary" @click="handleQrcode(3)">生成随机颜色二维码</el-button>
|
||||||
|
<el-button type="primary" @click="handleQrcode(4)">下载</el-button>
|
||||||
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<vue-qr :logoSrc="logoSrc" :text="inputData" :size="200" :callback="qrcodeCallback" :color-dark="randomColor" ></vue-qr>
|
<vue-qr :logoSrc="logoSrc" :text="inputData" :size="200" :callback="qrcodeCallback" :color-dark="randomColor" ></vue-qr>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<u-container-layout class="m-permission-page">
|
<u-container-layout class="m-permission-page">
|
||||||
<div style="margin-bottom: 20px"> 权限列表{{ store.getters.roles }} </div>
|
<div style="margin-bottom: 20px"> 权限列表{{ UserStore.roles }} </div>
|
||||||
<el-radio-group v-model="switchRoles">
|
<el-radio-group v-model="switchRoles">
|
||||||
<el-radio-button label="other" />
|
<el-radio-button label="other" />
|
||||||
<el-radio-button label="admin" />
|
<el-radio-button label="admin" />
|
||||||
|
|
@ -1,83 +1,89 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="inline-edit-table">
|
<div class="inline-edit-table">
|
||||||
<el-form :inline="true" :model="formInline" class="demo-form-inline" ref="ruleFormRef">
|
<div class="header">
|
||||||
<template v-for="(item, index) in formSearchData" :key="index">
|
<el-form :inline="true" :model="formInline" class="demo-form-inline search-form" ref="ruleFormRef" >
|
||||||
<el-form-item :label="item.label" v-show="isExpand ? isExpand : index < 2">
|
<template v-for="(item, index) in formSearchData" :key="index">
|
||||||
<template v-if="item.valueType === 'input'">
|
<el-form-item :label="item.label" v-show="isExpand ? isExpand : index < 2">
|
||||||
<el-input v-model="formInline[item.name]" :placeholder="`请输入${item.label}`" />
|
<template v-if="item.valueType === 'input'">
|
||||||
</template>
|
<el-input v-model="formInline[item.name]" :placeholder="`请输入${item.label}`" />
|
||||||
<template v-if="item.valueType === 'select'">
|
</template>
|
||||||
<el-select v-model="formInline[item.name]" :placeholder="`请选择${item.label}`">
|
<template v-if="item.valueType === 'select'">
|
||||||
<el-option
|
<el-select v-model="formInline[item.name]" :placeholder="`请选择${item.label}`">
|
||||||
v-for="ite in item.options"
|
<el-option
|
||||||
:key="ite.value"
|
v-for="ite in item.options"
|
||||||
:label="ite.label"
|
:key="ite.value"
|
||||||
:value="ite.value"
|
:label="ite.label"
|
||||||
/>
|
:value="ite.value"
|
||||||
</el-select>
|
/>
|
||||||
</template>
|
</el-select>
|
||||||
</el-form-item>
|
</template>
|
||||||
</template>
|
</el-form-item>
|
||||||
<el-form-item>
|
</template>
|
||||||
<el-button @click="reset(ruleFormRef)">重置</el-button>
|
</el-form>
|
||||||
<el-button type="primary" @click="onSubmit">查询</el-button>
|
<div class="search">
|
||||||
<el-button link @click="isExpand = !isExpand"
|
<el-button type="primary" @click="onSubmit" :icon="Search">查询</el-button>
|
||||||
>{{ isExpand ? '合并' : '展开'
|
<el-button @click="reset(ruleFormRef)">重置</el-button>
|
||||||
}}<el-icon>
|
<el-button link type="primary" @click="isExpand = !isExpand">{{ isExpand ? '合并' : '展开'}}<el-icon>
|
||||||
<arrow-down v-if="!isExpand" />
|
<arrow-down v-if="!isExpand" />
|
||||||
<arrow-up v-else /> </el-icon
|
<arrow-up v-else /> </el-icon
|
||||||
></el-button>
|
></el-button>
|
||||||
</el-form-item>
|
</div>
|
||||||
</el-form>
|
|
||||||
<div style="margin-bottom: 15px">
|
|
||||||
<slot name="btn"></slot>
|
|
||||||
</div>
|
</div>
|
||||||
<el-table
|
<!----------底部---------------------->
|
||||||
v-loading="loading"
|
<div class="footer">
|
||||||
@selection-change="(val) => emit('selection-change', val)"
|
<!-----------工具栏操作工具----------------->
|
||||||
:data="list"
|
<div class="operator">
|
||||||
style="width: 100%"
|
<slot name="btn"></slot>
|
||||||
:border="true"
|
</div>
|
||||||
>
|
<!-- ------------表格--------------->
|
||||||
<template v-for="item in columns">
|
<el-table
|
||||||
<el-table-column
|
height="585"
|
||||||
v-if="item.type"
|
v-loading="loading"
|
||||||
:type="item.type"
|
@selection-change="(val) => emit('selection-change', val)"
|
||||||
:width="item.width"
|
:data="list"
|
||||||
:align="item.align"
|
:border="true"
|
||||||
:fixed="item.fixed"
|
>
|
||||||
:label="item.label"
|
<template v-for="item in columns">
|
||||||
|
<el-table-column
|
||||||
|
v-if="item.type"
|
||||||
|
:type="item.type"
|
||||||
|
:width="item.width"
|
||||||
|
:align="item.align"
|
||||||
|
:fixed="item.fixed"
|
||||||
|
:label="item.label"
|
||||||
|
/>
|
||||||
|
<el-table-column
|
||||||
|
v-else
|
||||||
|
:prop="item.name"
|
||||||
|
:width="item.width"
|
||||||
|
:align="item.align"
|
||||||
|
:fixed="item.fixed"
|
||||||
|
:label="item.label"
|
||||||
|
>
|
||||||
|
<template #default="scope">
|
||||||
|
<span v-if="!item.slot">{{ scope.row[item.name] }}</span>
|
||||||
|
<slot v-else :name="item.name" :item="item" :row="scope.row"></slot>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</template>
|
||||||
|
</el-table>
|
||||||
|
<div class="pagination">
|
||||||
|
<el-pagination
|
||||||
|
v-model:currentPage="currentPage1"
|
||||||
|
:page-size="10"
|
||||||
|
background
|
||||||
|
layout="total, sizes, prev, pager, next, jumper"
|
||||||
|
:total="data.length"
|
||||||
|
@size-change="handleSizeChange"
|
||||||
|
@current-change="handleCurrentChange"
|
||||||
/>
|
/>
|
||||||
<el-table-column
|
</div>
|
||||||
v-else
|
|
||||||
:prop="item.name"
|
|
||||||
:width="item.width"
|
|
||||||
:align="item.align"
|
|
||||||
:fixed="item.fixed"
|
|
||||||
:label="item.label"
|
|
||||||
>
|
|
||||||
<template #default="scope">
|
|
||||||
<span v-if="!item.slot">{{ scope.row[item.name] }}</span>
|
|
||||||
<slot v-else :name="item.name" :item="item" :row="scope.row"></slot>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
</template>
|
|
||||||
</el-table>
|
|
||||||
<div style="width: 100%; display: flex; justify-content: center; padding-top: 20px">
|
|
||||||
<el-pagination
|
|
||||||
v-model:currentPage="currentPage1"
|
|
||||||
:page-size="10"
|
|
||||||
background
|
|
||||||
layout="total, sizes, prev, pager, next, jumper"
|
|
||||||
:total="data.length"
|
|
||||||
@size-change="handleSizeChange"
|
|
||||||
@current-change="handleCurrentChange"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed, ref } from 'vue'
|
import { computed, ref } from 'vue'
|
||||||
|
import {Search } from '@element-plus/icons-vue'
|
||||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||||
import type { FormInstance } from 'element-plus'
|
import type { FormInstance } from 'element-plus'
|
||||||
const ruleFormRef = ref<FormInstance>()
|
const ruleFormRef = ref<FormInstance>()
|
||||||
|
|
@ -98,7 +104,8 @@
|
||||||
})
|
})
|
||||||
|
|
||||||
const currentPage1 = ref(1)
|
const currentPage1 = ref(1)
|
||||||
const isExpand = ref(true)
|
// 收缩展开
|
||||||
|
const isExpand = ref(false)
|
||||||
const handleSizeChange = (val: number) => {
|
const handleSizeChange = (val: number) => {
|
||||||
console.log(`${val} items per page`)
|
console.log(`${val} items per page`)
|
||||||
}
|
}
|
||||||
|
|
@ -160,7 +167,7 @@
|
||||||
.catch(() => {})
|
.catch(() => {})
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style scoped>
|
<style scoped lang="scss">
|
||||||
.edit-input {
|
.edit-input {
|
||||||
padding-right: 100px;
|
padding-right: 100px;
|
||||||
}
|
}
|
||||||
|
|
@ -171,5 +178,41 @@
|
||||||
}
|
}
|
||||||
.inline-edit-table {
|
.inline-edit-table {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display:flex;
|
||||||
|
flex-direction:column;
|
||||||
|
|
||||||
|
.header{
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
.footer{
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
.operator{
|
||||||
|
margin-bottom: 15px
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.search-form{
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
.search{
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
::v-deep{
|
||||||
|
.el-table__header th{
|
||||||
|
font-size: 15px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #252525;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.pagination{
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
padding-top: 20px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,21 @@
|
||||||
<template>
|
<template>
|
||||||
<u-container-layout>
|
<u-container-layout>
|
||||||
<div class="app-container">
|
<div class="app-container" ref="appContainer">
|
||||||
<comprehensive-table
|
<PropTable
|
||||||
:loading="loading"
|
:loading="loading"
|
||||||
@selection-change="selectionChange"
|
@selection-change="selectionChange"
|
||||||
:columns="column"
|
:columns="column"
|
||||||
:data="list"
|
:data="list"
|
||||||
@reset="reset"
|
@reset="reset"
|
||||||
@onSubmit="onSubmit"
|
@onSubmit="onSubmit"
|
||||||
>
|
>
|
||||||
<template v-slot:btn>
|
<template v-slot:btn>
|
||||||
<div style="display: flex; justify-content: flex-end">
|
<div style="display: flex; justify-content: flex-end">
|
||||||
<el-button type="primary" @click="add"
|
<el-button type="primary" @click="add"
|
||||||
><el-icon><plus /></el-icon> 添加</el-button
|
><el-icon><plus /></el-icon> 添加</el-button
|
||||||
>
|
>
|
||||||
<el-button type="danger" @click="batchDelete"
|
<el-button type="danger" @click="batchDelete"
|
||||||
><el-icon><delete /></el-icon>删除</el-button
|
><el-icon><delete /></el-icon>删除</el-button
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -28,16 +28,16 @@
|
||||||
删除
|
删除
|
||||||
</el-button>
|
</el-button>
|
||||||
</template>
|
</template>
|
||||||
</comprehensive-table>
|
</PropTable>
|
||||||
|
|
||||||
<el-dialog v-model="dialogVisible" :title="title" width="50%">
|
<el-dialog v-model="dialogVisible" :title="title" width="50%">
|
||||||
<el-form
|
<el-form
|
||||||
ref="ruleFormRef"
|
ref="ruleFormRef"
|
||||||
:model="ruleForm"
|
:model="ruleForm"
|
||||||
:rules="rules"
|
:rules="rules"
|
||||||
label-width="120px"
|
label-width="120px"
|
||||||
class="demo-ruleForm"
|
class="demo-ruleForm"
|
||||||
:size="formSize"
|
:size="formSize"
|
||||||
>
|
>
|
||||||
<el-form-item label="活动名称" prop="name">
|
<el-form-item label="活动名称" prop="name">
|
||||||
<el-input v-model="ruleForm.name" />
|
<el-input v-model="ruleForm.name" />
|
||||||
|
|
@ -63,12 +63,13 @@
|
||||||
</u-container-layout>
|
</u-container-layout>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup name="comprehensive">
|
<script lang="ts" setup name="comprehensive">
|
||||||
import { ref, reactive, onMounted } from 'vue'
|
import {ref, reactive, onMounted, nextTick} from 'vue'
|
||||||
import * as dayjs from 'dayjs'
|
import * as dayjs from 'dayjs'
|
||||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||||
import type { FormInstance } from 'element-plus'
|
import type { FormInstance } from 'element-plus'
|
||||||
const loading = ref(true)
|
const loading = ref(true)
|
||||||
import ComprehensiveTable from './components/comprehensive.vue'
|
const appContainer = ref(null)
|
||||||
|
import PropTable from '@/components/Table/PropTable/index.vue'
|
||||||
const data = []
|
const data = []
|
||||||
for (let i = 0; i < 100; i++) {
|
for (let i = 0; i < 100; i++) {
|
||||||
data.push({
|
data.push({
|
||||||
|
|
@ -120,7 +121,7 @@
|
||||||
{ name: 'province', label: '省份' },
|
{ name: 'province', label: '省份' },
|
||||||
{ name: 'city', label: '城市' },
|
{ name: 'city', label: '城市' },
|
||||||
{ name: 'zip', label: '邮编' },
|
{ name: 'zip', label: '邮编' },
|
||||||
{ name: 'operation', slot: true, fixed: 'right', width: 200 },
|
{ name: 'operation', slot: true, fixed: 'right', width: 200,label: '操作' },
|
||||||
]
|
]
|
||||||
const list = ref(data)
|
const list = ref(data)
|
||||||
|
|
||||||
|
|
@ -257,6 +258,9 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
nextTick(()=>{
|
||||||
|
// let data = appContainer.value.
|
||||||
|
})
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
loading.value = false
|
loading.value = false
|
||||||
}, 500)
|
}, 500)
|
||||||
|
|
@ -267,6 +271,14 @@
|
||||||
.edit-input {
|
.edit-input {
|
||||||
padding-right: 100px;
|
padding-right: 100px;
|
||||||
}
|
}
|
||||||
|
.app-container{
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
padding: 20px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
|
||||||
|
}
|
||||||
.cancel-btn {
|
.cancel-btn {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 15px;
|
right: 15px;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue