Merge branch 'master' of https://github.com/zouzhibin/vue-admin-perfect into vue-i18n
Conflicts: src/layout/TagsView/components/MoreButton.vue src/views/home/index.vue
This commit is contained in:
commit
cd3688d055
Binary file not shown.
|
After Width: | Height: | Size: 218 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 4.7 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 96 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 4.7 KiB |
|
|
@ -0,0 +1,269 @@
|
|||
<template>
|
||||
<div ref="chartsRef" class="echarts"/>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import * as echarts from 'echarts'
|
||||
import { EChartsType } from 'echarts/core'
|
||||
import { onMounted, ref } from 'vue'
|
||||
const chartsRef = ref<HTMLElement | null>()
|
||||
|
||||
let colorList = ['#46ea91', '#2ba0ff', '#ed593b', '#7357ff', '#f2d750'];
|
||||
const options = {
|
||||
legend: {
|
||||
icon: 'circle',
|
||||
top: '5%',
|
||||
right: '5%',
|
||||
itemWidth: 6,
|
||||
itemGap: 5,
|
||||
textStyle: {
|
||||
color: '#fff',
|
||||
padding: [3, 0, 0, 0],
|
||||
},
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
},
|
||||
grid: {
|
||||
top: '14%',
|
||||
left: '3%',
|
||||
right: '4%',
|
||||
bottom: '10%',
|
||||
containLabel: true,
|
||||
},
|
||||
xAxis: [
|
||||
{
|
||||
type: 'category',
|
||||
data: ['1', '2', '3', '4', '5', '6', '7', '8'],
|
||||
axisLine: {
|
||||
lineStyle: {
|
||||
color: '#33BBFF',
|
||||
},
|
||||
},
|
||||
axisTick: {
|
||||
show: false,
|
||||
},
|
||||
axisLabel: {
|
||||
interval: 0,
|
||||
textStyle: {
|
||||
color: '#5FBBEB',
|
||||
},
|
||||
// 默认x轴字体大小
|
||||
fontSize: 12,
|
||||
// margin:文字到x轴的距离
|
||||
margin: 10,
|
||||
},
|
||||
axisPointer: {
|
||||
label: {
|
||||
// padding: [11, 5, 7],
|
||||
padding: [0, 0, 0, 0],
|
||||
// 这里的margin和axisLabel的margin要一致!
|
||||
margin: 10,
|
||||
// 移入时的字体大小
|
||||
fontSize: 12,
|
||||
backgroundColor: 'rgba(0,0,0,0)',
|
||||
},
|
||||
},
|
||||
boundaryGap: false,
|
||||
},
|
||||
],
|
||||
yAxis: [
|
||||
{
|
||||
name: '单位/件',
|
||||
axisTick: {
|
||||
show: false,
|
||||
},
|
||||
axisLine: {
|
||||
show: true,
|
||||
lineStyle: {
|
||||
color: '#05D5FF',
|
||||
},
|
||||
},
|
||||
axisLabel: {
|
||||
textStyle: {
|
||||
color: '#5FBBEB',
|
||||
},
|
||||
},
|
||||
splitLine: {
|
||||
show: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
series: [
|
||||
{
|
||||
name: '咨询',
|
||||
type: 'line',
|
||||
data: [100, 20, 30, 102, 15, 30, 20, 18],
|
||||
symbolSize: 1,
|
||||
symbol: 'circle',
|
||||
smooth: true,
|
||||
showSymbol: false,
|
||||
lineStyle: {
|
||||
width: 2,
|
||||
color: new echarts.graphic.LinearGradient(1, 1, 0, 0, [
|
||||
{
|
||||
offset: 0,
|
||||
color: '#90ffc6',
|
||||
},
|
||||
{
|
||||
offset: 1,
|
||||
color: '#46ea91',
|
||||
},
|
||||
]),
|
||||
shadowColor: 'rgba(144, 255, 198, .3)',
|
||||
shadowBlur: 5,
|
||||
shadowOffsetY: 5,
|
||||
},
|
||||
itemStyle: {
|
||||
normal: {
|
||||
color: colorList[0],
|
||||
borderColor: colorList[0],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '求助',
|
||||
type: 'line',
|
||||
data: [20, 12, 11, 14, 25, 16, 10, 20],
|
||||
symbolSize: 1,
|
||||
symbol: 'circle',
|
||||
smooth: true,
|
||||
showSymbol: false,
|
||||
lineStyle: {
|
||||
width: 2,
|
||||
color: new echarts.graphic.LinearGradient(1, 1, 0, 0, [
|
||||
{
|
||||
offset: 0,
|
||||
color: '#67bcfc',
|
||||
},
|
||||
{
|
||||
offset: 1,
|
||||
color: '#2ba0ff',
|
||||
},
|
||||
]),
|
||||
shadowColor: 'rgba(105, 188, 252,.3)',
|
||||
shadowBlur: 5,
|
||||
shadowOffsetY: 5,
|
||||
},
|
||||
itemStyle: {
|
||||
normal: {
|
||||
color: colorList[1],
|
||||
borderColor: colorList[1],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '无效',
|
||||
type: 'line',
|
||||
data: [150, 120, 170, 140, 100, 160, 110, 110],
|
||||
symbolSize: 1,
|
||||
symbol: 'circle',
|
||||
smooth: true,
|
||||
showSymbol: false,
|
||||
lineStyle: {
|
||||
width: 2,
|
||||
color: new echarts.graphic.LinearGradient(1, 1, 0, 0, [
|
||||
{
|
||||
offset: 0,
|
||||
color: '#fc937e ',
|
||||
},
|
||||
{
|
||||
offset: 1,
|
||||
color: '#ed593b',
|
||||
},
|
||||
]),
|
||||
shadowColor: 'rgb(252, 147, 126,.3)',
|
||||
shadowBlur: 2,
|
||||
shadowOffsetY: 2,
|
||||
},
|
||||
itemStyle: {
|
||||
normal: {
|
||||
color: colorList[2],
|
||||
borderColor: colorList[2],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '投诉举报',
|
||||
type: 'line',
|
||||
data: [200, 80, 100, 30, 60, 50, 110, 20],
|
||||
symbolSize: 1,
|
||||
symbol: 'circle',
|
||||
smooth: true,
|
||||
showSymbol: false,
|
||||
lineStyle: {
|
||||
width: 2,
|
||||
color: new echarts.graphic.LinearGradient(1, 1, 0, 0, [
|
||||
{
|
||||
offset: 0,
|
||||
color: '#a390ff',
|
||||
},
|
||||
{
|
||||
offset: 1,
|
||||
color: '#7357ff',
|
||||
},
|
||||
]),
|
||||
shadowColor: 'rgba(115, 87, 255, .1)',
|
||||
shadowBlur: 5,
|
||||
shadowOffsetY: 5,
|
||||
},
|
||||
itemStyle: {
|
||||
normal: {
|
||||
color: colorList[3],
|
||||
borderColor: colorList[3],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '建议',
|
||||
type: 'line',
|
||||
data: [20, 80, 150, 30, 60, 50, 50, 20],
|
||||
symbolSize: 1,
|
||||
symbol: 'circle',
|
||||
smooth: true,
|
||||
showSymbol: false,
|
||||
lineStyle: {
|
||||
width: 2,
|
||||
color: new echarts.graphic.LinearGradient(1, 1, 0, 0, [
|
||||
{
|
||||
offset: 0,
|
||||
color: '#ffeb86',
|
||||
},
|
||||
{
|
||||
offset: 1,
|
||||
color: '#f2d750',
|
||||
},
|
||||
]),
|
||||
shadowColor: 'rgba(255, 235, 134, .5)',
|
||||
shadowBlur: 5,
|
||||
shadowOffsetY: 5,
|
||||
},
|
||||
itemStyle: {
|
||||
normal: {
|
||||
color: colorList[4],
|
||||
borderColor: colorList[4],
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
let chart: EChartsType
|
||||
const initChart = () => {
|
||||
const chart = echarts.init(chartsRef.value)
|
||||
chart.setOption(options)
|
||||
return chart
|
||||
}
|
||||
onMounted(() => {
|
||||
chart = initChart()
|
||||
window.addEventListener('resize', function () {
|
||||
chart && chart.resize()
|
||||
})
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.echarts{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,179 @@
|
|||
<template>
|
||||
<div ref="chartsRef" class="echarts"/>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import * as echarts from 'echarts'
|
||||
import { EChartsType } from 'echarts/core'
|
||||
import { onMounted, ref } from 'vue'
|
||||
const chartsRef = ref<HTMLElement | null>()
|
||||
var trafficWay = [
|
||||
{
|
||||
name: 'Ⅰ类',
|
||||
value: 20,
|
||||
},
|
||||
{
|
||||
name: 'Ⅱ类',
|
||||
value: 20,
|
||||
},
|
||||
{
|
||||
name: 'Ⅲ类',
|
||||
value: 20,
|
||||
},
|
||||
{
|
||||
name: 'Ⅳ类',
|
||||
value: 20,
|
||||
},
|
||||
{ name: 'Ⅴ类', value: 20 },
|
||||
{ name: '劣Ⅴ类', value: 20 },
|
||||
];
|
||||
|
||||
var data = [];
|
||||
var color = ['#fd566a', '#9787ff', '#fdb36a', '#fdd56a', '#6da7ff', '#63e1f2', '#ff3000'];
|
||||
for (var i = 0; i < trafficWay.length; i++) {
|
||||
data.push(
|
||||
{
|
||||
value: trafficWay[i].value,
|
||||
name: trafficWay[i].name,
|
||||
itemStyle: {
|
||||
normal: {
|
||||
borderWidth: 5,
|
||||
shadowBlur: 20,
|
||||
borderColor: color[i],
|
||||
shadowColor: color[i],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
value: 2,
|
||||
name: '',
|
||||
itemStyle: {
|
||||
normal: {
|
||||
label: {
|
||||
show: false,
|
||||
},
|
||||
labelLine: {
|
||||
show: false,
|
||||
},
|
||||
color: 'rgba(0, 0, 0, 0)',
|
||||
borderColor: 'rgba(0, 0, 0, 0)',
|
||||
borderWidth: 0,
|
||||
},
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
var seriesOption = [
|
||||
{
|
||||
name: '',
|
||||
type: 'pie',
|
||||
clockWise: false,
|
||||
radius: [105, 109],
|
||||
hoverAnimation: false,
|
||||
itemStyle: {
|
||||
normal: {
|
||||
label: {
|
||||
show: true,
|
||||
position: 'outside',
|
||||
|
||||
formatter: function (params) {
|
||||
var percent = 0;
|
||||
var total = 0;
|
||||
for (var i = 0; i < trafficWay.length; i++) {
|
||||
total += trafficWay[i].value;
|
||||
}
|
||||
percent = ((params.value / total) * 100).toFixed(0);
|
||||
if (params.name !== '') {
|
||||
return params.name + '\t' + percent + '%';
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
},
|
||||
},
|
||||
labelLine: {
|
||||
length: 10,
|
||||
length2: 20,
|
||||
show: true,
|
||||
color: '#00ffff',
|
||||
},
|
||||
},
|
||||
},
|
||||
data: data,
|
||||
},
|
||||
];
|
||||
let options = {
|
||||
color: color,
|
||||
title: [{
|
||||
text: '水质监测',
|
||||
top: '44%',
|
||||
textAlign: 'center',
|
||||
left: '49.50%',
|
||||
backgroundColor: '#163253',
|
||||
borderRadius: 100,
|
||||
textStyle: {
|
||||
color: '#fff',
|
||||
fontSize: 20,
|
||||
fontWeight: '400',
|
||||
},
|
||||
}, {
|
||||
text: '水环境监测站',
|
||||
top: '49%',
|
||||
textAlign: 'center',
|
||||
left: '49.50%',
|
||||
textStyle: {
|
||||
color: '#fff',
|
||||
fontSize: 20,
|
||||
fontWeight: '400',
|
||||
},
|
||||
}, {
|
||||
text: '9',
|
||||
top: '53%',
|
||||
textAlign: 'center',
|
||||
left: '48%',
|
||||
textStyle: {
|
||||
color: '#f6ea2f',
|
||||
fontSize: 25,
|
||||
fontWeight: '800',
|
||||
fontStyle: 'italic'
|
||||
},
|
||||
}, {
|
||||
text: '个',
|
||||
top: '53.5%',
|
||||
textAlign: 'center',
|
||||
left: '50.5%',
|
||||
textStyle: {
|
||||
color: '#fff',
|
||||
fontSize: 16,
|
||||
fontWeight: '400',
|
||||
},
|
||||
}],
|
||||
tooltip: {
|
||||
show: false,
|
||||
},
|
||||
|
||||
toolbox: {
|
||||
show: false,
|
||||
},
|
||||
series: seriesOption,
|
||||
};
|
||||
|
||||
let chart: EChartsType
|
||||
const initChart = () => {
|
||||
const chart = echarts.init(chartsRef.value)
|
||||
chart.setOption(options)
|
||||
return chart
|
||||
}
|
||||
onMounted(() => {
|
||||
chart = initChart()
|
||||
window.addEventListener('resize', function () {
|
||||
chart && chart.resize()
|
||||
})
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.echarts{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
}
|
||||
</style>
|
||||
|
|
@ -30,7 +30,6 @@
|
|||
/>
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
|
|
@ -117,4 +116,4 @@ const resetForm = (formEl: FormInstance | undefined) => {
|
|||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@
|
|||
<template #default="scope">
|
||||
<el-button
|
||||
v-if="scope.row.edit"
|
||||
type="success"
|
||||
type="primary"
|
||||
size="small"
|
||||
icon="CircleCheckFilled"
|
||||
@click="confirmEdit(scope.row)"
|
||||
|
|
|
|||
|
|
@ -1,14 +1,18 @@
|
|||
<template>
|
||||
<div class="zb-pro-table">
|
||||
<div class="header">
|
||||
<el-form :inline="true" :model="formInline" class="demo-form-inline search-form" ref="ruleFormRef" >
|
||||
<el-form :inline="true"
|
||||
class="search-form"
|
||||
:model="formInline" 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-select
|
||||
style="width: 100%"
|
||||
v-model="formInline[item.name]" :placeholder="`请选择${item.label}`">
|
||||
<el-option
|
||||
v-for="ite in item.options"
|
||||
:key="ite.value"
|
||||
|
|
@ -192,7 +196,18 @@ const deleteAction = (row) => {
|
|||
border-radius: 4px;
|
||||
background: white;
|
||||
box-shadow: 0 0 12px rgb(0 0 0 / 5%);
|
||||
|
||||
.search-form{
|
||||
flex: 1;
|
||||
::v-deep{
|
||||
.el-input--default{
|
||||
width: 200px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.search{
|
||||
flex-shrink: 0;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
.footer{
|
||||
flex: 1;
|
||||
|
|
@ -203,6 +218,7 @@ const deleteAction = (row) => {
|
|||
overflow: hidden;
|
||||
background: white;
|
||||
box-shadow: 0 0 12px rgb(0 0 0 / 5%);
|
||||
min-height: 300px;
|
||||
.operator{
|
||||
margin-bottom: 15px
|
||||
}
|
||||
|
|
@ -215,13 +231,6 @@ const deleteAction = (row) => {
|
|||
height: 100%;
|
||||
}
|
||||
}
|
||||
.search-form{
|
||||
flex: 1;
|
||||
}
|
||||
.search{
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
::v-deep{
|
||||
.el-table__header th{
|
||||
font-size: 15px;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,19 @@
|
|||
<template>
|
||||
<div class="footer ">
|
||||
<span href="/" target="_blank"> 2022 © VUE-ADMIN-PERFECT By ZB Technology. </span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.footer{
|
||||
height: 40px;
|
||||
font-size: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: #ffffff;
|
||||
border-top: 1px solid #e4e7ed;
|
||||
flex-shrink: 0;
|
||||
color: rgba(0, 0, 0, 0.45);
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,18 +1,22 @@
|
|||
<template>
|
||||
<div class="app-main" v-if="isReload">
|
||||
<router-view v-slot="{ Component, route }">
|
||||
<transition name="fade-slide" mode="out-in" appear>
|
||||
<keep-alive :include="cacheRoutes">
|
||||
<component :is="Component" :key="route.path" />
|
||||
</keep-alive>
|
||||
</transition>
|
||||
</router-view>
|
||||
<div class="app-main-inner">
|
||||
<router-view v-slot="{ Component, route }">
|
||||
<transition name="fade-slide" mode="out-in" appear>
|
||||
<keep-alive :include="cacheRoutes">
|
||||
<component :is="Component" :key="route.path" />
|
||||
</keep-alive>
|
||||
</transition>
|
||||
</router-view>
|
||||
</div>
|
||||
<Theme />
|
||||
<Footer/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import Theme from '@/components/Theme/index.vue'
|
||||
import Footer from '../Footer/index.vue'
|
||||
import { computed, ref } from 'vue'
|
||||
import {useSettingStore} from "@/store/modules/setting"
|
||||
import {usePermissionStore} from "@/store/modules/permission"
|
||||
|
|
@ -32,5 +36,13 @@
|
|||
flex-direction: column;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
.app-main-inner{
|
||||
flex: 1;
|
||||
display: flex;
|
||||
overflow-x: hidden;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -6,10 +6,10 @@
|
|||
</el-button>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item @click="refresh">{{ $t("tagsView.refresh") }}</el-dropdown-item>
|
||||
<el-dropdown-item @click="closeCurrentTab">{{ $t("tagsView.closeCurrent") }}</el-dropdown-item>
|
||||
<el-dropdown-item @click="closeOtherTab">{{ $t("tagsView.closeOther") }}</el-dropdown-item>
|
||||
<el-dropdown-item @click="closeAllTab">{{ $t("tagsView.closeAll") }}</el-dropdown-item>
|
||||
<el-dropdown-item @click="refresh"><el-icon :size="14"><Refresh /></el-icon> {{ $t("tagsView.refresh") }}</el-dropdown-item>
|
||||
<el-dropdown-item @click="closeCurrentTab"><el-icon :size="14"><FolderRemove/></el-icon> {{ $t("tagsView.closeCurrent") }}</el-dropdown-item>
|
||||
<el-dropdown-item @click="closeOtherTab"><el-icon :size="14"><Close /></el-icon>{{ $t("tagsView.closeOther") }}</el-dropdown-item>
|
||||
<el-dropdown-item @click="closeAllTab"><el-icon :size="14"><FolderDelete /></el-icon>{{ $t("tagsView.closeAll") }}</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
|
|
@ -18,7 +18,9 @@
|
|||
import {computed} from "vue";
|
||||
import {useSettingStore} from "@/store/modules/setting"
|
||||
import {useTagsViewStore} from "@/store/modules/tagsView"
|
||||
|
||||
import { useRouter,useRoute } from 'vue-router'
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
const SettingStore = useSettingStore()
|
||||
const TagsViewStore = useTagsViewStore()
|
||||
const visitedViews = computed(() => TagsViewStore.visitedViews)
|
||||
|
|
@ -27,24 +29,19 @@ const refresh = () => {
|
|||
}
|
||||
// 关闭当前
|
||||
const closeCurrentTab = (event)=>{
|
||||
closeSelectedTag(event,route)
|
||||
TagsViewStore.toLastView(route.path)
|
||||
TagsViewStore.delView(route.path)
|
||||
|
||||
}
|
||||
// 关闭其他
|
||||
const closeOtherTab= async ()=>{
|
||||
const { name } = route
|
||||
for(let item of visitedViews.value){
|
||||
if(item.name!==name){
|
||||
await closeSelectedTag(null,item)
|
||||
}
|
||||
}
|
||||
TagsViewStore.delOtherViews(route.path)
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 关闭所有 去首页
|
||||
const closeAllTab = async ()=>{
|
||||
let visitedViews = await TagsViewStore.delAllViews()
|
||||
await TagsViewStore.goHome()
|
||||
await TagsViewStore.delAllViews()
|
||||
TagsViewStore.goHome()
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
|
|
|
|||
|
|
@ -109,7 +109,6 @@ function toLastView(activeTabPath) {
|
|||
router.push(nextTab.path);
|
||||
TagsViewStore.addVisitedView(nextTab)
|
||||
}
|
||||
// Tab Click
|
||||
const tabClick = (tabItem: TabsPaneContext) => {
|
||||
let path = tabItem.props.name as string;
|
||||
router.push(path);
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
<div :style="{ height:`${showTag?90:50}px` }" v-if="SettingStore.themeConfig.fixedHeader"></div>
|
||||
<u-header />
|
||||
<div class="m-container-content" :class="{ 'app-main-hide-tag': !showTag }">
|
||||
<u-main />
|
||||
<Main />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -22,7 +22,7 @@
|
|||
import {useSettingStore} from "@/store/modules/setting"
|
||||
import Sidebar from './Sidebar/index.vue'
|
||||
import UHeader from './Header/index.vue'
|
||||
import UMain from './Main/index.vue'
|
||||
import Main from './Main/index.vue'
|
||||
|
||||
import { useResizeHandler } from './hooks/useResizeHandler'
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,237 @@
|
|||
export const userData =[
|
||||
{
|
||||
username:'zzb',
|
||||
nickname:'林峰',
|
||||
sex:'男',
|
||||
role:'超级管理员',
|
||||
status:true,
|
||||
},
|
||||
{
|
||||
username:'zhangsan',
|
||||
nickname:'张三',
|
||||
sex:'女',
|
||||
role:'管理员',
|
||||
status:true,
|
||||
},
|
||||
{
|
||||
username:'lisi',
|
||||
nickname:'李四',
|
||||
sex:'男',
|
||||
role:'管理员',
|
||||
status:true,
|
||||
},
|
||||
{
|
||||
username:'wangwu',
|
||||
nickname:'王五',
|
||||
sex:'男',
|
||||
role:'超级管理员',
|
||||
status:false,
|
||||
},
|
||||
{
|
||||
username:'zhaoliu',
|
||||
nickname:'赵柳',
|
||||
sex:'男',
|
||||
role:'普通用户',
|
||||
status:false,
|
||||
},
|
||||
|
||||
]
|
||||
|
||||
|
||||
export const roleData =[
|
||||
{
|
||||
roleName:'超级管理员',
|
||||
roleId:'admin',
|
||||
createTime:'2022-09-02',
|
||||
},
|
||||
{
|
||||
roleName:'管理员',
|
||||
roleId:'role',
|
||||
createTime:'2022-09-02',
|
||||
},
|
||||
{
|
||||
roleName:'普通用户',
|
||||
roleId:'other',
|
||||
createTime:'2022-09-02',
|
||||
},
|
||||
|
||||
]
|
||||
|
||||
|
||||
export const menuData =[
|
||||
{
|
||||
menuName:'首页',
|
||||
menuType:'菜单',
|
||||
menuRouter:'/home',
|
||||
identification:'menu:home',
|
||||
parentId:0,
|
||||
level:1,
|
||||
id:0,
|
||||
createTime:'2022-09-02',
|
||||
},
|
||||
{
|
||||
menuName:'表格',
|
||||
menuType:'目录',
|
||||
menuRouter:'/table',
|
||||
identification:'menu:table',
|
||||
parentId:0,
|
||||
level:1,
|
||||
id:1,
|
||||
createTime:'2022-09-02',
|
||||
children:[
|
||||
{
|
||||
menuName:'菜单1',
|
||||
menuType:'菜单',
|
||||
menuRouter:'/table',
|
||||
identification:'menu1:view',
|
||||
parentId:1,
|
||||
level:2,
|
||||
id:10,
|
||||
createTime:'2022-09-02',
|
||||
children:[
|
||||
{
|
||||
menuName:'按钮1',
|
||||
menuType:'按钮',
|
||||
menuRouter:'/table',
|
||||
identification:'menu1:view:btn1',
|
||||
parentId:10,
|
||||
id:20,
|
||||
level:3,
|
||||
createTime:'2022-09-02',
|
||||
},
|
||||
{
|
||||
menuName:'按钮2',
|
||||
menuType:'按钮',
|
||||
menuRouter:'/table',
|
||||
identification:'menu1:view:btn2',
|
||||
parentId:10,
|
||||
id:21,
|
||||
level:3,
|
||||
createTime:'2022-09-02',
|
||||
},
|
||||
{
|
||||
menuName:'按钮3',
|
||||
menuType:'按钮',
|
||||
menuRouter:'/table',
|
||||
identification:'menu1:view:btn2',
|
||||
parentId:10,
|
||||
id:22,
|
||||
level:3,
|
||||
createTime:'2022-09-02',
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
menuName:'可视化图表',
|
||||
menuType:'目录',
|
||||
menuRouter:'/charts',
|
||||
identification:'menu:charts',
|
||||
parentId:0,
|
||||
level:1,
|
||||
id:1,
|
||||
createTime:'2022-09-02',
|
||||
children:[
|
||||
{
|
||||
menuName:'菜单1',
|
||||
menuType:'菜单',
|
||||
menuRouter:'/charts',
|
||||
identification:'menu1:view',
|
||||
parentId:1,
|
||||
level:2,
|
||||
id:10,
|
||||
createTime:'2022-09-02',
|
||||
children:[
|
||||
{
|
||||
menuName:'按钮1',
|
||||
menuType:'按钮',
|
||||
menuRouter:'/charts',
|
||||
identification:'menu1:view:btn1',
|
||||
parentId:10,
|
||||
id:20,
|
||||
level:3,
|
||||
createTime:'2022-09-02',
|
||||
},
|
||||
{
|
||||
menuName:'按钮2',
|
||||
menuType:'按钮',
|
||||
menuRouter:'/charts',
|
||||
identification:'menu1:view:btn2',
|
||||
parentId:10,
|
||||
id:21,
|
||||
level:3,
|
||||
createTime:'2022-09-02',
|
||||
},
|
||||
{
|
||||
menuName:'按钮3',
|
||||
menuType:'按钮',
|
||||
menuRouter:'/charts',
|
||||
identification:'menu1:view:btn2',
|
||||
parentId:10,
|
||||
id:22,
|
||||
level:3,
|
||||
createTime:'2022-09-02',
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
menuName:'基础组件',
|
||||
menuType:'目录',
|
||||
menuRouter:'/components',
|
||||
identification:'menu:components',
|
||||
parentId:0,
|
||||
level:1,
|
||||
id:1,
|
||||
createTime:'2022-09-02',
|
||||
children:[
|
||||
{
|
||||
menuName:'菜单1',
|
||||
menuType:'菜单',
|
||||
menuRouter:'/components',
|
||||
identification:'menu1:view',
|
||||
parentId:1,
|
||||
level:2,
|
||||
id:10,
|
||||
createTime:'2022-09-02',
|
||||
children:[
|
||||
{
|
||||
menuName:'按钮1',
|
||||
menuType:'按钮',
|
||||
menuRouter:'/components',
|
||||
identification:'menu1:view:btn1',
|
||||
parentId:10,
|
||||
id:20,
|
||||
level:3,
|
||||
createTime:'2022-09-02',
|
||||
},
|
||||
{
|
||||
menuName:'按钮2',
|
||||
menuType:'按钮',
|
||||
menuRouter:'/components',
|
||||
identification:'menu1:view:btn2',
|
||||
parentId:10,
|
||||
id:21,
|
||||
level:3,
|
||||
createTime:'2022-09-02',
|
||||
},
|
||||
{
|
||||
menuName:'按钮3',
|
||||
menuType:'按钮',
|
||||
menuRouter:'/components',
|
||||
identification:'menu1:view:btn2',
|
||||
parentId:10,
|
||||
id:22,
|
||||
level:3,
|
||||
createTime:'2022-09-02',
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,132 @@
|
|||
export const tableList = [
|
||||
{
|
||||
date: '2016-05-02',
|
||||
name: '王五',
|
||||
price: 20,
|
||||
province: '上海',
|
||||
admin: 'admin',
|
||||
sex: 1,
|
||||
id: 1,
|
||||
age: 18,
|
||||
city: '普陀区',
|
||||
address: '上海市普陀区金沙江路 1518 弄',
|
||||
zip: 200333,
|
||||
},
|
||||
{
|
||||
date: '2018-06-11',
|
||||
name: '梦琪',
|
||||
price: 20,
|
||||
province: '上海',
|
||||
admin: 'admin',
|
||||
sex: 1,
|
||||
id: 2,
|
||||
age: 22,
|
||||
city: '普陀区',
|
||||
address: '上海市普陀区金沙江路 1519 弄',
|
||||
zip: 200333,
|
||||
},
|
||||
{
|
||||
date: '2022-05-23',
|
||||
name: '忆柳',
|
||||
price: 22,
|
||||
province: '上海',
|
||||
admin: 'admin',
|
||||
sex: 0,
|
||||
id: 3,
|
||||
age: 23,
|
||||
city: '普陀区',
|
||||
address: '上海市普陀区金沙江路 1520 弄',
|
||||
zip: 200333,
|
||||
},
|
||||
{
|
||||
date: '2022-01-24',
|
||||
name: '之桃',
|
||||
price: 33,
|
||||
province: '上海',
|
||||
admin: 'admin',
|
||||
sex: 1,
|
||||
id: 4,
|
||||
age: 24,
|
||||
city: '普陀区',
|
||||
address: '上海市普陀区金沙江路 2222 弄',
|
||||
zip: 200333,
|
||||
},
|
||||
{
|
||||
date: '2022-07-22',
|
||||
name: '慕青',
|
||||
price: 45,
|
||||
province: '上海',
|
||||
admin: 'admin',
|
||||
sex: 0,
|
||||
id: 5,
|
||||
age: 25,
|
||||
city: '普陀区',
|
||||
address: '上海市普陀区金沙江路 2223 弄',
|
||||
zip: 200333,
|
||||
},
|
||||
{
|
||||
date: '2016-05-02',
|
||||
name: '问兰',
|
||||
price: 47,
|
||||
province: '上海',
|
||||
admin: 'admin',
|
||||
sex: 1,
|
||||
id: 6,
|
||||
age: 26,
|
||||
city: '普陀区',
|
||||
address: '上海市普陀区金沙江路 2224 弄',
|
||||
zip: 200333,
|
||||
},
|
||||
{
|
||||
date: '2016-08-02',
|
||||
name: '元香',
|
||||
price: 45,
|
||||
province: '上海',
|
||||
admin: 'admin',
|
||||
sex: 0,
|
||||
id: 7,
|
||||
age: 27,
|
||||
city: '普陀区',
|
||||
address: '上海市普陀区金沙江路 2225 弄',
|
||||
zip: 200333,
|
||||
},
|
||||
{
|
||||
date: '2019-11-11',
|
||||
name: '初夏',
|
||||
price: 23,
|
||||
province: '上海',
|
||||
admin: 'admin',
|
||||
sex: 1,
|
||||
id: 8,
|
||||
age: 28,
|
||||
city: '普陀区',
|
||||
address: '上海市普陀区金沙江路 2226 弄',
|
||||
zip: 200333,
|
||||
},
|
||||
{
|
||||
date: '2018-08-02',
|
||||
name: '沛菡',
|
||||
price: 33,
|
||||
province: '上海',
|
||||
admin: 'other',
|
||||
sex: 0,
|
||||
id: 9,
|
||||
age: 29,
|
||||
city: '普陀区',
|
||||
address: '上海市普陀区金沙江路 2227 弄',
|
||||
zip: 200339,
|
||||
},
|
||||
{
|
||||
date: '2022-11-03',
|
||||
name: '傲珊',
|
||||
price: 222,
|
||||
province: '浙江',
|
||||
admin: 'admin',
|
||||
sex: 1,
|
||||
id: 10,
|
||||
age: 30,
|
||||
city: '杭州',
|
||||
address: '杭州市滨江区建业路228号',
|
||||
zip: 200433,
|
||||
}
|
||||
]
|
||||
|
|
@ -16,8 +16,6 @@ import chatRouter from './modules/chat'
|
|||
import othersRouter from './modules/other'
|
||||
import externalLink from './modules/externalLink'
|
||||
import formRouter from './modules/from'
|
||||
import zipRoutes from './modules/zip'
|
||||
import clipboardTable from './modules/clipboard'
|
||||
|
||||
// 异步组件
|
||||
export const asyncRoutes = [
|
||||
|
|
@ -29,14 +27,12 @@ export const asyncRoutes = [
|
|||
...othersRouter,
|
||||
...nestedRouter,
|
||||
...excelRouter,
|
||||
...zipRoutes,
|
||||
...errorRouter,
|
||||
...externalLink,
|
||||
...clipboardTable,
|
||||
...systemRouter,
|
||||
{
|
||||
path: '/:pathMatch(.*)',
|
||||
redirect: '/error/404'
|
||||
redirect: '/404'
|
||||
}
|
||||
]
|
||||
|
||||
|
|
|
|||
|
|
@ -25,12 +25,12 @@ const chartsRouter = [{
|
|||
name: 'charts-simple',
|
||||
meta: { title: '简单图表', roles:['other'] , icon: 'MenuIcon'}
|
||||
},
|
||||
{
|
||||
path: 'complex',
|
||||
component: () => import('@/views/charts/complex.vue'),
|
||||
name: 'charts-complex',
|
||||
meta: { title: '复杂图表', roles:['other'] , icon: 'MenuIcon'}
|
||||
},
|
||||
// {
|
||||
// path: 'complex',
|
||||
// component: () => import('@/views/charts/complex.vue'),
|
||||
// name: 'charts-complex',
|
||||
// meta: { title: '复杂图表', roles:['other'] , icon: 'MenuIcon'}
|
||||
// },
|
||||
// {
|
||||
// path: 'animation',
|
||||
// component: () => import('@/views/charts/animation.vue'),
|
||||
|
|
|
|||
|
|
@ -1,23 +0,0 @@
|
|||
import Layout from '@/layout/index.vue'
|
||||
|
||||
const clipboardTable = [{
|
||||
path: '/clipboard',
|
||||
component: Layout,
|
||||
redirect: '/clipboard/index',
|
||||
name: 'clipboard',
|
||||
meta: {
|
||||
title: 'clipboard',
|
||||
icon: 'document-copy',
|
||||
roles:['other']
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: 'index',
|
||||
component: () => import('@/views/clipboard/index.vue'),
|
||||
name: 'map',
|
||||
meta: { title: '剪贴板', roles:['other'] ,icon: 'document-copy',}
|
||||
},
|
||||
|
||||
]
|
||||
}]
|
||||
export default clipboardTable
|
||||
|
|
@ -1,32 +1,33 @@
|
|||
|
||||
|
||||
/** When your routing table is too long, you can split it into small modules**/
|
||||
|
||||
import { RouteRecordRaw } from "vue-router";
|
||||
import Layout from "@/layout/index.vue";
|
||||
|
||||
const errorRouter = [{
|
||||
path: '/error',
|
||||
component: Layout,
|
||||
redirect: '/error/404',
|
||||
name: 'error',
|
||||
meta: {
|
||||
title: '错误页面',
|
||||
icon: 'School'
|
||||
// 扩展继承属性
|
||||
interface extendRoute {
|
||||
hidden?:boolean
|
||||
}
|
||||
const errorRouter : Array<RouteRecordRaw&extendRoute> = [
|
||||
{
|
||||
path: "/403",
|
||||
name: "403",
|
||||
component: () => import("@/views/error/403.vue"),
|
||||
hidden:true,
|
||||
meta: {
|
||||
requiresAuth: true,
|
||||
title: "403页面",
|
||||
key: "403"
|
||||
}
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: '404',
|
||||
component: () => import('@/views/error/404.vue'),
|
||||
name: '404',
|
||||
meta: { title: '404', icon: 'MenuIcon' }
|
||||
},
|
||||
{
|
||||
path: '401',
|
||||
component: () => import('@/views/error/401.vue'),
|
||||
name: '401',
|
||||
meta: { title: '401', icon: 'MenuIcon'}
|
||||
},
|
||||
]
|
||||
}]
|
||||
{
|
||||
path: "/404",
|
||||
name: "404",
|
||||
component: () => import("@/views/error/404.vue"),
|
||||
hidden:true,
|
||||
meta: {
|
||||
requiresAuth: true,
|
||||
title: "404页面",
|
||||
key: "404"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
export default errorRouter
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
|
||||
|
||||
/** When your routing table is too long, you can split it into small modules**/
|
||||
|
||||
import Layout from "@/layout/index.vue";
|
||||
|
||||
const excelRouter = [{
|
||||
|
|
@ -10,33 +8,39 @@ const excelRouter = [{
|
|||
redirect: '/excel/export-excel',
|
||||
name: 'excel',
|
||||
meta: {
|
||||
title: 'Excel',
|
||||
title: 'Excel&Zip',
|
||||
icon: 'School'
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: 'export-excel',
|
||||
component: () => import('@/views/excel/export-excel.vue'),
|
||||
component: () => import('@/views/excel/exportExcel/index.vue'),
|
||||
name: 'export-excel',
|
||||
meta: { title: '导出 Excel', icon: 'MenuIcon'}
|
||||
},
|
||||
{
|
||||
path: 'export-merge-header',
|
||||
component: () => import('@/views/excel/export-merge-header.vue'),
|
||||
component: () => import('@/views/excel/exportMergeHeader/index.vue'),
|
||||
name: 'export-merge-header',
|
||||
meta: { title: '导出 多级表头', icon: 'MenuIcon' }
|
||||
},
|
||||
{
|
||||
path: 'upload-style-excel',
|
||||
component: () => import('@/views/excel/exportStyleExcel/index.vue'),
|
||||
name: 'upload-style-excel',
|
||||
meta: { title: '自定义样式导出 Excel', icon: 'MenuIcon' }
|
||||
},
|
||||
{
|
||||
path: 'upload-excel',
|
||||
component: () => import('@/views/excel/upload-excel.vue'),
|
||||
component: () => import('@/views/excel/uploadExcel/index.vue'),
|
||||
name: 'upload-excel',
|
||||
meta: { title: '上传 Excel', icon: 'MenuIcon' }
|
||||
},
|
||||
{
|
||||
path: 'upload-style-excel',
|
||||
component: () => import('@/views/excel/export-style-excel.vue'),
|
||||
name: 'upload-style-excel',
|
||||
meta: { title: '自定义样式导出 Excel', icon: 'MenuIcon' }
|
||||
path: 'zip',
|
||||
component: () => import('@/views/excel/zip/index.vue'),
|
||||
name: 'Zip',
|
||||
meta: { title: 'Zip', roles:['other'] ,icon: 'MenuIcon',}
|
||||
},
|
||||
]
|
||||
}]
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
/** When your routing table is too long, you can split it into small modules**/
|
||||
|
||||
|
||||
import Layout from "@/layout/index.vue";
|
||||
|
||||
|
|
|
|||
|
|
@ -8,10 +8,16 @@ const othersRouter = [{
|
|||
redirect: '/other/editor',
|
||||
name: 'other',
|
||||
meta: {
|
||||
title: '扩展组件',
|
||||
title: '常用组件',
|
||||
icon: 'management'
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: 'clipboard',
|
||||
component: () => import('@/views/other/clipboard/index.vue'),
|
||||
name: 'clipboard',
|
||||
meta: { title: '剪贴板', roles:['other'] ,icon: 'MenuIcon',}
|
||||
},
|
||||
{
|
||||
path: 'editor',
|
||||
component: () => import('@/views/other/editor/index.vue'),
|
||||
|
|
|
|||
|
|
@ -15,19 +15,19 @@ const tableRouter = [{
|
|||
children: [
|
||||
{
|
||||
path: 'comprehensive',
|
||||
component: () => import('@/views/table/ComprehensiveTable.vue'),
|
||||
component: () => import('@/views/table/ComprehensiveTable/index.vue'),
|
||||
name: 'comprehensive',
|
||||
meta: { title: '综合表格', keepAlive: true , icon: 'MenuIcon'}
|
||||
},
|
||||
{
|
||||
path: 'inline-table',
|
||||
component: () => import('@/views/table/InlineEditTable.vue'),
|
||||
component: () => import('@/views/table/InlineEditTable/index.vue'),
|
||||
name: 'inline-table',
|
||||
meta: { title: '行内编辑', keepAlive: true , icon: 'MenuIcon'}
|
||||
},
|
||||
{
|
||||
path: 'editableProTable',
|
||||
component: () => import('@/views/table/EditableProTable.vue'),
|
||||
component: () => import('@/views/table/EditableProTable/index.vue'),
|
||||
name: 'edit-table',
|
||||
meta: { title: '可编辑表格', keepAlive: true , icon: 'MenuIcon'}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,27 +0,0 @@
|
|||
import Layout from '@/layout/index.vue'
|
||||
|
||||
const zipRoutes = [{
|
||||
path: '/zip',
|
||||
component: Layout,
|
||||
isShow:true,
|
||||
redirect: 'noRedirect',
|
||||
name: 'zip',
|
||||
alwaysShow:true,
|
||||
meta: {
|
||||
title: 'Zip',
|
||||
icon: 'document-copy',
|
||||
roles:['other']
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: 'download',
|
||||
component: () => import('@/views/zip/download.vue'),
|
||||
name: 'download',
|
||||
meta: { title: 'Zip', roles:['other'] ,icon: 'document-copy',}
|
||||
},
|
||||
|
||||
]
|
||||
}]
|
||||
|
||||
|
||||
export default zipRoutes
|
||||
|
|
@ -1,6 +1,5 @@
|
|||
import {defineStore} from 'pinia'
|
||||
import { useRouter } from "vue-router";
|
||||
const router = useRouter()
|
||||
import router from "@/router/index";
|
||||
|
||||
export const useTagsViewStore = defineStore({
|
||||
// id: 必须的,在所有 Store 中唯一
|
||||
|
|
@ -52,6 +51,13 @@ export const useTagsViewStore = defineStore({
|
|||
})
|
||||
|
||||
},
|
||||
toLastView(activeTabPath){
|
||||
let index = this.visitedViews.findIndex(item=>item.path===activeTabPath)
|
||||
const nextTab = this.visitedViews[index + 1] || this.visitedViews[index - 1];
|
||||
if (!nextTab) return;
|
||||
router.push(nextTab.path);
|
||||
this.addVisitedView(nextTab)
|
||||
},
|
||||
delVisitedView(path){
|
||||
return new Promise(resolve => {
|
||||
this.visitedViews = this.visitedViews.filter(v=>{
|
||||
|
|
@ -82,9 +88,17 @@ export const useTagsViewStore = defineStore({
|
|||
resolve([...this.visitedViews])
|
||||
})
|
||||
},
|
||||
async goHome() {
|
||||
router.push('/home');
|
||||
delOtherViews(path){
|
||||
this.visitedViews = this.visitedViews.filter(item => {
|
||||
return item.path === path || item.meta.affix;
|
||||
});
|
||||
this.cachedViews = this.visitedViews.filter(item => {
|
||||
return item.path === path || item.meta.affix;
|
||||
});
|
||||
},
|
||||
goHome() {
|
||||
this.activeTabsValue = '/home';
|
||||
router.push({path: '/home'});
|
||||
},
|
||||
updateVisitedView(view){
|
||||
for (let v of this.visitedViews) {
|
||||
|
|
|
|||
|
|
@ -55,6 +55,8 @@ body{
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* nprogress样式 */
|
||||
#nprogress .bar {
|
||||
background: $primaryColor !important;
|
||||
|
|
@ -66,3 +68,19 @@ body{
|
|||
#nprogress .peg {
|
||||
box-shadow: 0 0 10px $primaryColor, 0 0 5px $primaryColor !important;
|
||||
}
|
||||
|
||||
.app-container {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
padding: 10px 12px;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.app-container-inner{
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
box-shadow: 0 2px 12px 0 rgb(0 0 0 / 10%);
|
||||
background: white;
|
||||
padding: 20px;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,3 +3,7 @@
|
|||
color: #252525;
|
||||
background: #fafafa;
|
||||
}
|
||||
|
||||
.el-table .el-table__header th {
|
||||
background: var(--el-fill-color-light)!important;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,160 @@
|
|||
.m-data-screen{
|
||||
width: 1920px;
|
||||
height: 1080px;
|
||||
box-sizing: border-box;
|
||||
overflow:hidden;
|
||||
//background: url("/static/screen/bg.png") no-repeat center center;
|
||||
background: #041c4a;
|
||||
.header{
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
height: 91px;
|
||||
background: url("/static/screen/header-bg.png");
|
||||
background-size:contain ;
|
||||
background-repeat:no-repeat;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
.header-bg-title{
|
||||
font-size: 42px;
|
||||
font-weight: normal;
|
||||
font-stretch: normal;
|
||||
letter-spacing: 2px;
|
||||
color: #ffffff;
|
||||
margin-bottom: 14px;
|
||||
}
|
||||
.date{
|
||||
top: 25px;
|
||||
line-height: 68px;
|
||||
font-size: 18px;
|
||||
position: absolute;
|
||||
letter-spacing: 0px;
|
||||
color: #87caff;
|
||||
right: 20px;
|
||||
}
|
||||
}
|
||||
.circle-bg{
|
||||
animation:rotate 5s infinite linear;
|
||||
}
|
||||
@keyframes rotate{
|
||||
0%{transform:rotate(0deg);}
|
||||
100%{transform:rotate(360deg);}
|
||||
}
|
||||
.center{
|
||||
padding-left: 40px;
|
||||
padding-right: 50px;
|
||||
padding-bottom: 40px;
|
||||
padding-top: 50px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
.circle-bg {
|
||||
animation: rotate 5s infinite linear;
|
||||
}
|
||||
@keyframes rotate {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
.item {
|
||||
display: flex;
|
||||
/*align-items: center;*/
|
||||
.item-icon {
|
||||
width: 117px;
|
||||
height: 109px;
|
||||
}
|
||||
.item-icon1 {
|
||||
background: url('@/assets/image/center-inner1.png') no-repeat center 43%;
|
||||
}
|
||||
.item-right {
|
||||
margin-left: 20px;
|
||||
.item-right-inner {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.text-title {
|
||||
font-size: 20px;
|
||||
letter-spacing: 1px;
|
||||
color: #ffffff;
|
||||
/*margin-bottom: 6px;*/
|
||||
/*height: 20px;*/
|
||||
}
|
||||
.text-number {
|
||||
font-size: 44px;
|
||||
letter-spacing: 2px;
|
||||
color: #00e4ff;
|
||||
}
|
||||
.text-der {
|
||||
overflow: hidden;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
font-size: 16px;
|
||||
color: #ffffff;
|
||||
letter-spacing: 1px;
|
||||
.left {
|
||||
margin-right: 10px;
|
||||
}
|
||||
img {
|
||||
margin-right: 4px;
|
||||
margin-top: 4px;
|
||||
width: 11px;
|
||||
height: 15px;
|
||||
}
|
||||
.right {
|
||||
color: #ff0000;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.footer{
|
||||
position: relative;
|
||||
padding: 0 30px 0 24px;
|
||||
display: flex;
|
||||
|
||||
.left{
|
||||
box-sizing: border-box;
|
||||
padding: 32px 0;
|
||||
width: 568px;
|
||||
//height: 701px;
|
||||
|
||||
background-size: contain;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
.middle{
|
||||
flex: 1;
|
||||
position: relative;
|
||||
.migration{
|
||||
left: -18%;
|
||||
top:-15%;
|
||||
width: 900px;
|
||||
height: 900px;
|
||||
position: absolute;
|
||||
}
|
||||
}
|
||||
.right{
|
||||
width: 568px;
|
||||
align-items: flex-end;
|
||||
box-sizing: border-box;
|
||||
padding: 32px 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
background-size:contain ;
|
||||
background-repeat:no-repeat;
|
||||
}
|
||||
.item-complex {
|
||||
width: 558px;
|
||||
height: 362px;
|
||||
background-image: url('@/assets/image/charts/1-1-bg.png');
|
||||
background-color: #042750;
|
||||
background-size: contain;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -31,7 +31,7 @@
|
|||
<line-charts width="100%" height="100%" />
|
||||
</div>
|
||||
<div class="item-complex">
|
||||
<bar-charts width="100%" height="100%" />
|
||||
<MultilineCharts />
|
||||
</div>
|
||||
</div>
|
||||
<div class="middle">
|
||||
|
|
@ -41,10 +41,10 @@
|
|||
</div>
|
||||
<div class="right">
|
||||
<div class="item-complex" style="margin-bottom: 20px">
|
||||
<line-charts width="100%" height="100%" />
|
||||
<BarCharts width="100%" height="100%" />
|
||||
</div>
|
||||
<div class="item-complex">
|
||||
<bar-charts width="100%" height="100%" />
|
||||
<PieCharts />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -58,6 +58,8 @@ import CountTo from '@/components/CountTo/index.vue'
|
|||
import LineCharts from '@/views/charts/components/complex/line/index.vue'
|
||||
import BarCharts from '@/views/charts/components/complex/bar/index.vue'
|
||||
import MigrationCharts from '@/views/charts/components/migration/index.vue'
|
||||
import MultilineCharts from '@/components/DataScreen/Multiline/index'
|
||||
import PieCharts from '@/components/DataScreen/Pie/index'
|
||||
|
||||
const timeDate = ref()
|
||||
const hourTime = ref()
|
||||
|
|
@ -93,171 +95,5 @@ onBeforeUnmount(()=>{
|
|||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.m-data-screen{
|
||||
width: 1920px;
|
||||
height: 1080px;
|
||||
box-sizing: border-box;
|
||||
overflow:hidden;
|
||||
//background: url("/static/screen/bg.png") no-repeat center center;
|
||||
background: #041c4a;
|
||||
.header{
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
height: 91px;
|
||||
background: url("/static/screen/header-bg.png");
|
||||
background-size:contain ;
|
||||
background-repeat:no-repeat;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
.header-bg-title{
|
||||
font-size: 42px;
|
||||
font-weight: normal;
|
||||
font-stretch: normal;
|
||||
letter-spacing: 2px;
|
||||
color: #ffffff;
|
||||
margin-bottom: 14px;
|
||||
}
|
||||
.date{
|
||||
top: 25px;
|
||||
line-height: 68px;
|
||||
font-size: 18px;
|
||||
position: absolute;
|
||||
letter-spacing: 0px;
|
||||
color: #87caff;
|
||||
right: 20px;
|
||||
}
|
||||
}
|
||||
//.header{
|
||||
// width: 100%;
|
||||
// .header-bg-title{
|
||||
// width: 100%;
|
||||
// }
|
||||
//
|
||||
//}
|
||||
.circle-bg{
|
||||
animation:rotate 5s infinite linear;
|
||||
}
|
||||
@keyframes rotate{
|
||||
0%{transform:rotate(0deg);}
|
||||
100%{transform:rotate(360deg);}
|
||||
}
|
||||
.center{
|
||||
padding-left: 40px;
|
||||
padding-right: 50px;
|
||||
padding-bottom: 40px;
|
||||
padding-top: 50px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
.circle-bg {
|
||||
animation: rotate 5s infinite linear;
|
||||
}
|
||||
@keyframes rotate {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
.item {
|
||||
display: flex;
|
||||
/*align-items: center;*/
|
||||
.item-icon {
|
||||
width: 117px;
|
||||
height: 109px;
|
||||
}
|
||||
.item-icon1 {
|
||||
background: url('@/assets/image/center-inner1.png') no-repeat center 43%;
|
||||
}
|
||||
.item-right {
|
||||
margin-left: 20px;
|
||||
.item-right-inner {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.text-title {
|
||||
font-size: 20px;
|
||||
letter-spacing: 1px;
|
||||
color: #ffffff;
|
||||
/*margin-bottom: 6px;*/
|
||||
/*height: 20px;*/
|
||||
}
|
||||
.text-number {
|
||||
font-size: 44px;
|
||||
letter-spacing: 2px;
|
||||
color: #00e4ff;
|
||||
}
|
||||
.text-der {
|
||||
overflow: hidden;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
font-size: 16px;
|
||||
color: #ffffff;
|
||||
letter-spacing: 1px;
|
||||
.left {
|
||||
margin-right: 10px;
|
||||
}
|
||||
img {
|
||||
margin-right: 4px;
|
||||
margin-top: 4px;
|
||||
width: 11px;
|
||||
height: 15px;
|
||||
}
|
||||
.right {
|
||||
color: #ff0000;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.footer{
|
||||
position: relative;
|
||||
padding: 0 30px 0 24px;
|
||||
display: flex;
|
||||
|
||||
.left{
|
||||
box-sizing: border-box;
|
||||
padding: 32px 0;
|
||||
width: 568px;
|
||||
//height: 701px;
|
||||
|
||||
background-size: contain;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
.middle{
|
||||
flex: 1;
|
||||
position: relative;
|
||||
.migration{
|
||||
left: -18%;
|
||||
top:-15%;
|
||||
width: 900px;
|
||||
height: 900px;
|
||||
position: absolute;
|
||||
}
|
||||
}
|
||||
.right{
|
||||
width: 568px;
|
||||
align-items: flex-end;
|
||||
box-sizing: border-box;
|
||||
padding: 32px 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
background-size:contain ;
|
||||
background-repeat:no-repeat;
|
||||
}
|
||||
.item-complex {
|
||||
width: 558px;
|
||||
height: 362px;
|
||||
background-image: url('@/assets/image/charts/1-1-bg.png');
|
||||
background-color: #042750;
|
||||
background-size: contain;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
}
|
||||
}
|
||||
@import "./index";
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,236 @@
|
|||
<template>
|
||||
<div class="wscn-http403-container">
|
||||
<div class="wscn-http403">
|
||||
<div class="pic-403">
|
||||
<img
|
||||
class="pic-403__parent"
|
||||
src="@/assets/403_images/403.png"
|
||||
alt="403"
|
||||
/>
|
||||
<img
|
||||
class="pic-403__child left"
|
||||
src="@/assets/403_images/403_cloud.png"
|
||||
alt="403"
|
||||
/>
|
||||
<img
|
||||
class="pic-403__child mid"
|
||||
src="@/assets/403_images/403_cloud.png"
|
||||
alt="403"
|
||||
/>
|
||||
<img
|
||||
class="pic-403__child right"
|
||||
src="@/assets/403_images/403_cloud.png"
|
||||
alt="403"
|
||||
/>
|
||||
</div>
|
||||
<div class="bullshit">
|
||||
<div class="bullshit__oops">您没有访问权限!</div>
|
||||
<div class="bullshit__info">
|
||||
请检查URL地址是否正确, 或点击回到首页。
|
||||
</div>
|
||||
<router-link to="/" class="bullshit__return-home">回到首页</router-link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.wscn-http403-container {
|
||||
transform: translate(-50%, -50%);
|
||||
position: absolute;
|
||||
top: 40%;
|
||||
left: 50%;
|
||||
}
|
||||
.wscn-http403 {
|
||||
position: relative;
|
||||
width: 1200px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 0 50px;
|
||||
overflow: hidden;
|
||||
.pic-403 {
|
||||
position: relative;
|
||||
float: left;
|
||||
width: 600px;
|
||||
overflow: hidden;
|
||||
&__parent {
|
||||
width: 100%;
|
||||
}
|
||||
&__child {
|
||||
position: absolute;
|
||||
&.left {
|
||||
width: 80px;
|
||||
top: 17px;
|
||||
left: 220px;
|
||||
opacity: 0;
|
||||
animation-name: cloudLeft;
|
||||
animation-duration: 2s;
|
||||
animation-timing-function: linear;
|
||||
animation-fill-mode: forwards;
|
||||
animation-delay: 1s;
|
||||
}
|
||||
&.mid {
|
||||
width: 46px;
|
||||
top: 10px;
|
||||
left: 420px;
|
||||
opacity: 0;
|
||||
animation-name: cloudMid;
|
||||
animation-duration: 2s;
|
||||
animation-timing-function: linear;
|
||||
animation-fill-mode: forwards;
|
||||
animation-delay: 1.2s;
|
||||
}
|
||||
&.right {
|
||||
width: 62px;
|
||||
top: 100px;
|
||||
left: 500px;
|
||||
opacity: 0;
|
||||
animation-name: cloudRight;
|
||||
animation-duration: 2s;
|
||||
animation-timing-function: linear;
|
||||
animation-fill-mode: forwards;
|
||||
animation-delay: 1s;
|
||||
}
|
||||
@keyframes cloudLeft {
|
||||
0% {
|
||||
top: 17px;
|
||||
left: 220px;
|
||||
opacity: 0;
|
||||
}
|
||||
20% {
|
||||
top: 33px;
|
||||
left: 188px;
|
||||
opacity: 1;
|
||||
}
|
||||
80% {
|
||||
top: 81px;
|
||||
left: 92px;
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
top: 97px;
|
||||
left: 60px;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@keyframes cloudMid {
|
||||
0% {
|
||||
top: 10px;
|
||||
left: 420px;
|
||||
opacity: 0;
|
||||
}
|
||||
20% {
|
||||
top: 40px;
|
||||
left: 360px;
|
||||
opacity: 1;
|
||||
}
|
||||
70% {
|
||||
top: 130px;
|
||||
left: 180px;
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
top: 160px;
|
||||
left: 120px;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@keyframes cloudRight {
|
||||
0% {
|
||||
top: 100px;
|
||||
left: 500px;
|
||||
opacity: 0;
|
||||
}
|
||||
20% {
|
||||
top: 120px;
|
||||
left: 460px;
|
||||
opacity: 1;
|
||||
}
|
||||
80% {
|
||||
top: 180px;
|
||||
left: 340px;
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
top: 200px;
|
||||
left: 300px;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.bullshit {
|
||||
position: relative;
|
||||
float: left;
|
||||
width: 300px;
|
||||
padding: 30px 0;
|
||||
overflow: hidden;
|
||||
&__oops {
|
||||
font-size: 32px;
|
||||
font-weight: bold;
|
||||
line-height: 40px;
|
||||
color: #1482f0;
|
||||
opacity: 0;
|
||||
margin-bottom: 20px;
|
||||
animation-name: slideUp;
|
||||
animation-duration: 0.5s;
|
||||
animation-fill-mode: forwards;
|
||||
}
|
||||
&__headline {
|
||||
font-size: 20px;
|
||||
line-height: 24px;
|
||||
color: #222;
|
||||
font-weight: bold;
|
||||
opacity: 0;
|
||||
margin-bottom: 10px;
|
||||
animation-name: slideUp;
|
||||
animation-duration: 0.5s;
|
||||
animation-delay: 0.1s;
|
||||
animation-fill-mode: forwards;
|
||||
}
|
||||
&__info {
|
||||
font-size: 13px;
|
||||
line-height: 21px;
|
||||
color: grey;
|
||||
opacity: 0;
|
||||
margin-bottom: 30px;
|
||||
animation-name: slideUp;
|
||||
animation-duration: 0.5s;
|
||||
animation-delay: 0.2s;
|
||||
animation-fill-mode: forwards;
|
||||
}
|
||||
&__return-home {
|
||||
display: block;
|
||||
float: left;
|
||||
width: 110px;
|
||||
height: 36px;
|
||||
background: #1482f0;
|
||||
border-radius: 100px;
|
||||
text-align: center;
|
||||
color: #ffffff;
|
||||
opacity: 0;
|
||||
font-size: 14px;
|
||||
line-height: 36px;
|
||||
cursor: pointer;
|
||||
animation-name: slideUp;
|
||||
animation-duration: 0.5s;
|
||||
animation-delay: 0.3s;
|
||||
animation-fill-mode: forwards;
|
||||
}
|
||||
@keyframes slideUp {
|
||||
0% {
|
||||
transform: translateY(60px);
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
transform: translateY(0);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,58 +1,218 @@
|
|||
<template>
|
||||
<u-container-layout>
|
||||
<div class="error-page">
|
||||
<div class="img">
|
||||
<img :src="fourPng" style="width: 100%" />
|
||||
<div class="wscn-http404-container">
|
||||
<div class="wscn-http404">
|
||||
<div class="pic-404">
|
||||
<img class="pic-404__parent" src="@/assets/404_images/404.png" alt="404">
|
||||
<img class="pic-404__child left" src="@/assets/404_images/404_cloud.png" alt="404">
|
||||
<img class="pic-404__child mid" src="@/assets/404_images/404_cloud.png" alt="404">
|
||||
<img class="pic-404__child right" src="@/assets/404_images/404_cloud.png" alt="404">
|
||||
</div>
|
||||
<div class="bullshit">
|
||||
<div class="bullshit__oops">页面不存在!</div>
|
||||
<div class="bullshit__headline">{{ message }}</div>
|
||||
<div class="bullshit__info">请检查URL地址是否正确, 或点击回到首页。</div>
|
||||
<router-link to="/" class="bullshit__return-home">回到首页</router-link>
|
||||
</div>
|
||||
<div>
|
||||
<div class="oops">抱歉!</div>
|
||||
<div class="text">当前页面不存在...</div>
|
||||
<div style="margin-bottom: 20px; font-size: 13px; color: grey"
|
||||
>请检查您输入的URL是否正确,或单击下面的按钮返回主页。</div
|
||||
>
|
||||
<el-button type="primary" @click="goBackHome">返回首页</el-button></div
|
||||
>
|
||||
</div>
|
||||
</u-container-layout>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import fourPng from '@/assets/image/error/404s.png'
|
||||
import { useRouter } from 'vue-router'
|
||||
const router = useRouter()
|
||||
|
||||
const goBackHome = () => {
|
||||
router.push({
|
||||
path: '/',
|
||||
})
|
||||
}
|
||||
<script lang="ts">
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.error-page {
|
||||
height: 100%;
|
||||
.wscn-http404-container{
|
||||
transform: translate(-50%,-50%);
|
||||
position: absolute;
|
||||
top: 40%;
|
||||
left: 50%;
|
||||
}
|
||||
.wscn-http404 {
|
||||
position: relative;
|
||||
width: 1200px;
|
||||
padding: 0 50px;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.img {
|
||||
width: 500px;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
.pic-404 {
|
||||
position: relative;
|
||||
float: left;
|
||||
width: 600px;
|
||||
overflow: hidden;
|
||||
&__parent {
|
||||
width: 100%;
|
||||
}
|
||||
.oops {
|
||||
&__child {
|
||||
position: absolute;
|
||||
&.left {
|
||||
width: 80px;
|
||||
top: 17px;
|
||||
left: 220px;
|
||||
opacity: 0;
|
||||
animation-name: cloudLeft;
|
||||
animation-duration: 2s;
|
||||
animation-timing-function: linear;
|
||||
animation-fill-mode: forwards;
|
||||
animation-delay: 1s;
|
||||
}
|
||||
&.mid {
|
||||
width: 46px;
|
||||
top: 10px;
|
||||
left: 420px;
|
||||
opacity: 0;
|
||||
animation-name: cloudMid;
|
||||
animation-duration: 2s;
|
||||
animation-timing-function: linear;
|
||||
animation-fill-mode: forwards;
|
||||
animation-delay: 1.2s;
|
||||
}
|
||||
&.right {
|
||||
width: 62px;
|
||||
top: 100px;
|
||||
left: 500px;
|
||||
opacity: 0;
|
||||
animation-name: cloudRight;
|
||||
animation-duration: 2s;
|
||||
animation-timing-function: linear;
|
||||
animation-fill-mode: forwards;
|
||||
animation-delay: 1s;
|
||||
}
|
||||
@keyframes cloudLeft {
|
||||
0% {
|
||||
top: 17px;
|
||||
left: 220px;
|
||||
opacity: 0;
|
||||
}
|
||||
20% {
|
||||
top: 33px;
|
||||
left: 188px;
|
||||
opacity: 1;
|
||||
}
|
||||
80% {
|
||||
top: 81px;
|
||||
left: 92px;
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
top: 97px;
|
||||
left: 60px;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@keyframes cloudMid {
|
||||
0% {
|
||||
top: 10px;
|
||||
left: 420px;
|
||||
opacity: 0;
|
||||
}
|
||||
20% {
|
||||
top: 40px;
|
||||
left: 360px;
|
||||
opacity: 1;
|
||||
}
|
||||
70% {
|
||||
top: 130px;
|
||||
left: 180px;
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
top: 160px;
|
||||
left: 120px;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@keyframes cloudRight {
|
||||
0% {
|
||||
top: 100px;
|
||||
left: 500px;
|
||||
opacity: 0;
|
||||
}
|
||||
20% {
|
||||
top: 120px;
|
||||
left: 460px;
|
||||
opacity: 1;
|
||||
}
|
||||
80% {
|
||||
top: 180px;
|
||||
left: 340px;
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
top: 200px;
|
||||
left: 300px;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.bullshit {
|
||||
position: relative;
|
||||
float: left;
|
||||
width: 300px;
|
||||
padding: 30px 0;
|
||||
overflow: hidden;
|
||||
&__oops {
|
||||
font-size: 32px;
|
||||
font-weight: bold;
|
||||
line-height: 40px;
|
||||
color: #1482f0;
|
||||
opacity: 0;
|
||||
margin-bottom: 20px;
|
||||
-webkit-animation-fill-mode: forwards;
|
||||
animation-name: slideUp;
|
||||
animation-duration: 0.5s;
|
||||
animation-fill-mode: forwards;
|
||||
}
|
||||
.text {
|
||||
&__headline {
|
||||
font-size: 20px;
|
||||
line-height: 24px;
|
||||
color: #222;
|
||||
font-weight: bold;
|
||||
opacity: 0;
|
||||
margin-bottom: 10px;
|
||||
-webkit-animation-delay: 0.1s;
|
||||
animation-name: slideUp;
|
||||
animation-duration: 0.5s;
|
||||
animation-delay: 0.1s;
|
||||
-webkit-animation-fill-mode: forwards;
|
||||
animation-fill-mode: forwards;
|
||||
}
|
||||
&__info {
|
||||
font-size: 13px;
|
||||
line-height: 21px;
|
||||
color: grey;
|
||||
opacity: 0;
|
||||
margin-bottom: 30px;
|
||||
animation-name: slideUp;
|
||||
animation-duration: 0.5s;
|
||||
animation-delay: 0.2s;
|
||||
animation-fill-mode: forwards;
|
||||
}
|
||||
&__return-home {
|
||||
display: block;
|
||||
float: left;
|
||||
width: 110px;
|
||||
height: 36px;
|
||||
background: #1482f0;
|
||||
border-radius: 100px;
|
||||
text-align: center;
|
||||
color: #ffffff;
|
||||
opacity: 0;
|
||||
font-size: 14px;
|
||||
line-height: 36px;
|
||||
cursor: pointer;
|
||||
animation-name: slideUp;
|
||||
animation-duration: 0.5s;
|
||||
animation-delay: 0.3s;
|
||||
animation-fill-mode: forwards;
|
||||
}
|
||||
@keyframes slideUp {
|
||||
0% {
|
||||
transform: translateY(60px);
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
transform: translateY(0);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,123 +0,0 @@
|
|||
<template>
|
||||
<u-container-layout>
|
||||
<div class="header">
|
||||
<el-input
|
||||
v-model="input"
|
||||
placeholder="请输入文件名"
|
||||
style="width: 200px; margin-right: 10px"
|
||||
/>
|
||||
<div>
|
||||
<label style="margin-right: 10px">导出格式</label>
|
||||
<el-select
|
||||
v-model="format"
|
||||
class="m-2"
|
||||
placeholder="导出格式"
|
||||
style="width: 200px; margin-right: 10px"
|
||||
>
|
||||
<el-option label="xlsx" value="xlsx" />
|
||||
<el-option label="csv" value="csv" />
|
||||
</el-select>
|
||||
</div>
|
||||
<el-button @click="exportExcelAction" type="primary">
|
||||
<el-icon style="margin-right: 10px"><document-remove /></el-icon>导出 Excel
|
||||
</el-button>
|
||||
</div>
|
||||
<div class="footer">
|
||||
<el-table :data="list" border class="table">
|
||||
<template v-for="(item, index) in column" :key="index">
|
||||
<el-table-column :prop="item.name" :label="item.label" :width="item.width" />
|
||||
</template>
|
||||
</el-table>
|
||||
</div>
|
||||
</u-container-layout>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, reactive } from 'vue'
|
||||
import * as dayjs from 'dayjs'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import { exportExcel } from '@/utils/exprotExcel'
|
||||
const data = []
|
||||
for (let i = 0; i < 10; i++) {
|
||||
data.push({
|
||||
date: '2016-05-02',
|
||||
name: '王五' + i,
|
||||
price: 1 + i,
|
||||
province: '上海',
|
||||
admin: 'admin',
|
||||
sex: i % 2 ? 1 : 0,
|
||||
checked: true,
|
||||
id: i + 1,
|
||||
age: 0,
|
||||
city: '普陀区',
|
||||
address: '上海市普上海',
|
||||
zip: 200333,
|
||||
})
|
||||
}
|
||||
const column = [
|
||||
{ name: 'id', label: 'id' },
|
||||
{ name: 'name', label: '姓名', inSearch: true, valueType: 'input' },
|
||||
{ name: 'age', label: '年龄', align: 'right' },
|
||||
{
|
||||
name: 'sex',
|
||||
label: '性别',
|
||||
slot: true,
|
||||
inSearch: true,
|
||||
options: [
|
||||
{
|
||||
value: 1,
|
||||
label: '男',
|
||||
},
|
||||
{
|
||||
value: 0,
|
||||
label: '女',
|
||||
},
|
||||
],
|
||||
valueType: 'select',
|
||||
},
|
||||
{
|
||||
name: 'price',
|
||||
label: '价格',
|
||||
inSearch: true,
|
||||
valueType: 'input',
|
||||
},
|
||||
{ name: 'admin', label: '账号', inSearch: true, valueType: 'input' },
|
||||
{ name: 'address', label: '地址', inSearch: true, valueType: 'input' },
|
||||
{ name: 'date', label: '日期', sorter: true, inSearch: true, valueType: 'input' },
|
||||
{ name: 'province', label: '省份' },
|
||||
{ name: 'city', label: '城市' },
|
||||
{ name: 'zip', label: '邮编' },
|
||||
]
|
||||
const list = ref(data)
|
||||
const input = ref('')
|
||||
const format = ref('xlsx')
|
||||
const exportExcelAction = () => {
|
||||
exportExcel({
|
||||
column,
|
||||
data,
|
||||
filename: input.value || '导出 excel',
|
||||
format: format.value,
|
||||
autoWidth: true,
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.header{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 15px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.footer{
|
||||
flex: 1;
|
||||
position: relative;
|
||||
.table{
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
.header{
|
||||
display: flex;
|
||||
padding: 16px 16px 16px 16px;
|
||||
margin-bottom: 16px;
|
||||
border-radius: 4px;
|
||||
background: white;
|
||||
box-shadow: 0 0 12px rgb(0 0 0 / 5%);
|
||||
}
|
||||
.footer{
|
||||
flex: 1;
|
||||
display: flex;
|
||||
padding: 16px;
|
||||
flex-direction: column;
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
background: white;
|
||||
box-shadow: 0 0 12px rgb(0 0 0 / 5%);
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
.footer-inner{
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.table{
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
<template>
|
||||
<div class="app-container">
|
||||
<div class="header">
|
||||
<el-input
|
||||
v-model="input"
|
||||
placeholder="请输入文件名"
|
||||
style="width: 200px; margin-right: 10px"
|
||||
/>
|
||||
<div>
|
||||
<label style="margin-right: 10px">导出格式</label>
|
||||
<el-select
|
||||
v-model="format"
|
||||
class="m-2"
|
||||
placeholder="导出格式"
|
||||
style="width: 200px; margin-right: 10px"
|
||||
>
|
||||
<el-option label="xlsx" value="xlsx" />
|
||||
<el-option label="csv" value="csv" />
|
||||
</el-select>
|
||||
</div>
|
||||
<el-button @click="exportExcelAction" type="primary">
|
||||
<el-icon style="margin-right: 6px"><Download /></el-icon>导出 Excel
|
||||
</el-button>
|
||||
</div>
|
||||
<div class="footer">
|
||||
<div class="footer-inner">
|
||||
<el-table :data="list" border class="table">
|
||||
<template v-for="(item, index) in column" :key="index">
|
||||
<el-table-column :prop="item.name" :label="item.label" :width="item.width" />
|
||||
</template>
|
||||
</el-table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import {tableList} from "@/mock/table"
|
||||
import { ref } from 'vue'
|
||||
import { exportExcel } from '@/utils/exprotExcel'
|
||||
const column = [
|
||||
{ name: 'id', label: 'id' },
|
||||
{ name: 'name', label: '姓名' },
|
||||
{ name: 'age', label: '年龄', align: 'right' },
|
||||
{name: 'price', label: '价格', },
|
||||
{ name: 'admin', label: '账号' },
|
||||
{ name: 'address', label: '地址',width:250 },
|
||||
{ name: 'date', label: '日期' ,width:140},
|
||||
{ name: 'province', label: '省份' },
|
||||
{ name: 'city', label: '城市' },
|
||||
{ name: 'zip', label: '邮编' },
|
||||
]
|
||||
const list = ref(tableList)
|
||||
const input = ref('')
|
||||
const format = ref('xlsx')
|
||||
const exportExcelAction = () => {
|
||||
exportExcel({
|
||||
column,
|
||||
data:list.value,
|
||||
filename: input.value || '导出 excel',
|
||||
format: format.value,
|
||||
autoWidth: true,
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "./index";
|
||||
</style>
|
||||
|
|
@ -1,34 +1,35 @@
|
|||
<template>
|
||||
<u-container-layout>
|
||||
<div style="margin-bottom: 15px">
|
||||
<div class="app-container">
|
||||
<div class="header">
|
||||
<el-input
|
||||
v-model="input"
|
||||
placeholder="请输入文件名"
|
||||
style="width: 200px; margin-right: 10px"
|
||||
/>
|
||||
<el-button @click="exportExcelAction" type="primary">
|
||||
<el-icon style="margin-right: 10px"><document-remove /></el-icon>导出 Excel
|
||||
<el-icon style="margin-right: 6px"><Download /></el-icon>导出 Excel
|
||||
</el-button>
|
||||
</div>
|
||||
<el-table :data="list" style="width: 100%" border>
|
||||
<template v-for="(item, index) in column" :key="index">
|
||||
<template v-if="item.children">
|
||||
<el-table-column :prop="item.name" :label="item.label" :width="item.width">
|
||||
<template v-for="(ite, i) in item.children" :key="i">
|
||||
<el-table-column :prop="ite.name" :label="ite.label" :width="ite.width" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<div class="footer">
|
||||
<el-table :data="list" style="width: 100%" border>
|
||||
<template v-for="(item, index) in column" :key="index">
|
||||
<template v-if="item.children">
|
||||
<el-table-column :prop="item.name" :label="item.label" :width="item.width">
|
||||
<template v-for="(ite, i) in item.children" :key="i">
|
||||
<el-table-column :prop="ite.name" :label="ite.label" :width="ite.width" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
</template>
|
||||
<el-table-column :prop="item.name" :label="item.label" :width="item.width" v-else />
|
||||
</template>
|
||||
<el-table-column :prop="item.name" :label="item.label" :width="item.width" v-else />
|
||||
</template>
|
||||
</el-table>
|
||||
</u-container-layout>
|
||||
</el-table>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, reactive } from 'vue'
|
||||
import * as dayjs from 'dayjs'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import { exportMultiHeaderExcel } from '@/utils/exprotExcel'
|
||||
const data = []
|
||||
for (let i = 0; i < 10; i++) {
|
||||
|
|
@ -73,4 +74,23 @@
|
|||
}
|
||||
</script>
|
||||
|
||||
<style></style>
|
||||
<style lang="scss" scoped>
|
||||
.header{
|
||||
display: flex;
|
||||
padding: 16px 16px 16px 16px;
|
||||
margin-bottom: 12px;
|
||||
border-radius: 4px;
|
||||
background: white;
|
||||
box-shadow: 0 0 12px rgb(0 0 0 / 5%);
|
||||
}
|
||||
.footer{
|
||||
flex: 1;
|
||||
display: flex;
|
||||
padding: 16px;
|
||||
flex-direction: column;
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
background: white;
|
||||
box-shadow: 0 0 12px rgb(0 0 0 / 5%);
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,23 +1,25 @@
|
|||
<template>
|
||||
<u-container-layout>
|
||||
<div class=".header">
|
||||
<div class="app-container">
|
||||
<div class="header">
|
||||
<el-input
|
||||
v-model="input"
|
||||
placeholder="请输入文件名"
|
||||
placeholder="默认文件名导出 excel"
|
||||
style="width: 200px; margin-right: 10px"
|
||||
/>
|
||||
<el-button @click="exportExcelAction" type="primary">
|
||||
<el-icon style="margin-right: 10px"><document-remove /></el-icon>导出样式 Excel
|
||||
<el-icon style="margin-right: 6px"><Download /></el-icon>导出样式 Excel
|
||||
</el-button>
|
||||
</div>
|
||||
<div class="footer">
|
||||
<el-table :data="list" class="table" border>
|
||||
<template v-for="(item, index) in column" :key="index">
|
||||
<el-table-column :prop="item.name" :label="item.label" :width="item.width" />
|
||||
</template>
|
||||
</el-table>
|
||||
<div class="footer-inner">
|
||||
<el-table :data="list" class="table" border>
|
||||
<template v-for="(item, index) in column" :key="index">
|
||||
<el-table-column :prop="item.name" :label="item.label" :width="item.width" />
|
||||
</template>
|
||||
</el-table>
|
||||
</div>
|
||||
</div>
|
||||
</u-container-layout>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
|
@ -44,34 +46,12 @@
|
|||
}
|
||||
const column = [
|
||||
{ name: 'id', label: 'id' },
|
||||
{ name: 'name', label: '姓名', inSearch: true, valueType: 'input' },
|
||||
{ name: 'name', label: '姓名' },
|
||||
{ name: 'age', label: '年龄', align: 'right' },
|
||||
{
|
||||
name: 'sex',
|
||||
label: '性别',
|
||||
slot: true,
|
||||
inSearch: true,
|
||||
options: [
|
||||
{
|
||||
value: 1,
|
||||
label: '男',
|
||||
},
|
||||
{
|
||||
value: 0,
|
||||
label: '女',
|
||||
},
|
||||
],
|
||||
valueType: 'select',
|
||||
},
|
||||
{
|
||||
name: 'price',
|
||||
label: '价格',
|
||||
inSearch: true,
|
||||
valueType: 'input',
|
||||
},
|
||||
{ name: 'admin', label: '账号', inSearch: true, valueType: 'input' },
|
||||
{ name: 'address', label: '地址', inSearch: true, valueType: 'input' },
|
||||
{ name: 'date', label: '日期', sorter: true, inSearch: true, valueType: 'input' },
|
||||
{name: 'price', label: '价格', },
|
||||
{ name: 'admin', label: '账号' },
|
||||
{ name: 'address', label: '地址',width:180 },
|
||||
{ name: 'date', label: '日期' ,width:140},
|
||||
{ name: 'province', label: '省份' },
|
||||
{ name: 'city', label: '城市' },
|
||||
{ name: 'zip', label: '邮编' },
|
||||
|
|
@ -93,13 +73,28 @@
|
|||
<style lang="scss" scoped>
|
||||
.header{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 15px;
|
||||
flex-shrink: 0;
|
||||
padding: 16px 16px 16px 16px;
|
||||
margin-bottom: 16px;
|
||||
border-radius: 4px;
|
||||
background: white;
|
||||
box-shadow: 0 0 12px rgb(0 0 0 / 5%);
|
||||
}
|
||||
.footer{
|
||||
flex: 1;
|
||||
display: flex;
|
||||
padding: 16px;
|
||||
flex-direction: column;
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
background: white;
|
||||
box-shadow: 0 0 12px rgb(0 0 0 / 5%);
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
.footer-inner{
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.table{
|
||||
position: absolute;
|
||||
left: 0;
|
||||
|
|
@ -0,0 +1,108 @@
|
|||
<template>
|
||||
<div class="app-container">
|
||||
<div class="header">
|
||||
<el-input
|
||||
v-model="zipName"
|
||||
placeholder="请输入文件名"
|
||||
style="width: 200px; margin-right: 10px"
|
||||
/>
|
||||
<el-button @click="exportExcelAction" type="primary">
|
||||
<el-icon style="margin-right: 6px"><Download/></el-icon>导出 zip
|
||||
</el-button>
|
||||
</div>
|
||||
<div class="footer">
|
||||
<el-table :data="list" style="width: 100%" border>
|
||||
<template v-for="(item, index) in column" :key="index">
|
||||
<el-table-column
|
||||
:prop="item.name"
|
||||
:label="item.label"
|
||||
:width="item.width" />
|
||||
</template>
|
||||
</el-table>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, reactive } from 'vue'
|
||||
import * as dayjs from 'dayjs'
|
||||
import { downloadFiles2Zip } from '@/utils/downloadzip'
|
||||
const data = []
|
||||
for (let i = 0; i < 10; i++) {
|
||||
data.push({
|
||||
date: '2016-05-02',
|
||||
name: '王五' + i,
|
||||
price: 1 + i,
|
||||
province: '上海',
|
||||
admin: 'admin',
|
||||
checked: true,
|
||||
id: i + 1,
|
||||
age: 0,
|
||||
city: '普陀区',
|
||||
address: '上海市普上海',
|
||||
zip: 200333,
|
||||
})
|
||||
}
|
||||
const column = [
|
||||
{ name: 'id', label: 'id' },
|
||||
{ name: 'name', label: '姓名' },
|
||||
{ name: 'age', label: '年龄', align: 'right' },
|
||||
{name: 'price', label: '价格', },
|
||||
{ name: 'admin', label: '账号' },
|
||||
{ name: 'address', label: '地址',width:180 },
|
||||
{ name: 'date', label: '日期' ,width:140},
|
||||
{ name: 'province', label: '省份' },
|
||||
{ name: 'city', label: '城市' },
|
||||
{ name: 'zip', label: '邮编' },
|
||||
]
|
||||
const list = ref(data)
|
||||
const zipName = ref('下载zip')
|
||||
const format = ref('xlsx')
|
||||
const exportExcelAction = () => {
|
||||
downloadFiles2Zip({
|
||||
zipName: zipName.value,
|
||||
files: [
|
||||
{
|
||||
filename: 'test',
|
||||
sheets: [
|
||||
{
|
||||
sheetName: 'test',
|
||||
columns: column,
|
||||
dataSource: data,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.app-container{
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
padding: 10px 12px;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
.header{
|
||||
display: flex;
|
||||
padding: 16px 16px 16px 16px;
|
||||
margin-bottom: 16px;
|
||||
border-radius: 4px;
|
||||
background: white;
|
||||
box-shadow: 0 0 12px rgb(0 0 0 / 5%);
|
||||
}
|
||||
.footer{
|
||||
flex: 1;
|
||||
display: flex;
|
||||
padding: 16px;
|
||||
flex-direction: column;
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
background: white;
|
||||
box-shadow: 0 0 12px rgb(0 0 0 / 5%);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -48,14 +48,17 @@
|
|||
><el-icon style="font-size: 24px; color: white"><user /></el-icon
|
||||
></div>
|
||||
<div class="right">
|
||||
<h2 style="color: #2d8cf0"
|
||||
<div
|
||||
class="h2"
|
||||
style="color: #2d8cf0"
|
||||
>
|
||||
><count-to
|
||||
:start-val="0"
|
||||
:end-val="5268"
|
||||
:duration="2000"
|
||||
:autoplay="true"
|
||||
></count-to
|
||||
></h2>
|
||||
></div>
|
||||
<div>用户访问量 </div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -68,14 +71,17 @@
|
|||
><el-icon style="font-size: 24px; color: white"><user /></el-icon
|
||||
></div>
|
||||
<div class="right">
|
||||
<h2 style="color: #64d572"
|
||||
<div
|
||||
class="h2"
|
||||
style="color: #64d572"
|
||||
>
|
||||
><count-to
|
||||
:start-val="0"
|
||||
:end-val="9599"
|
||||
:duration="2000"
|
||||
:autoplay="true"
|
||||
></count-to
|
||||
></h2>
|
||||
></div>
|
||||
<div>系统消息 </div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -88,14 +94,16 @@
|
|||
><el-icon style="font-size: 24px; color: white"><user /></el-icon
|
||||
></div>
|
||||
<div class="right">
|
||||
<h2 style="color: #f25e43"
|
||||
<div
|
||||
class="h2"
|
||||
style="color: #f25e43"
|
||||
><count-to
|
||||
:start-val="0"
|
||||
:end-val="595453"
|
||||
:duration="2000"
|
||||
:autoplay="true"
|
||||
></count-to
|
||||
></h2>
|
||||
></div>
|
||||
<div>数量 </div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -202,6 +210,10 @@
|
|||
flex-direction: column;
|
||||
padding-left: 20px;
|
||||
justify-content: center;
|
||||
.h2{
|
||||
font-size: 24px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.custom {
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@
|
|||
<u-container-layout>
|
||||
<el-card style="margin-bottom: 20px">
|
||||
<div style="margin-bottom: 10px">输入内容,并点击复制按钮</div>
|
||||
<el-input v-model="inputData" placeholder="请输入" style="width: 400px; max-width: 100%" />
|
||||
<el-button type="primary" @click="handleCopy(inputData, $event)">
|
||||
<el-input v-model="copyValue" placeholder="请输入" style="width: 400px; max-width: 100%" />
|
||||
<el-button type="primary" @click="handleCopy(copyValue, $event)">
|
||||
<el-icon style="margin-right: 6px"><document-copy /></el-icon> 复制
|
||||
</el-button>
|
||||
</el-card>
|
||||
|
|
@ -14,12 +14,12 @@
|
|||
</u-container-layout>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { ref } from 'vue'
|
||||
import clip from '@/utils/clipboard'
|
||||
const inputData = ref('https://github.com/zouzhibin/vue-admin-perfect')
|
||||
const testValue = ref('')
|
||||
import { ref } from 'vue'
|
||||
import clip from '@/utils/clipboard'
|
||||
const copyValue = ref('https://github.com/zouzhibin/vue-admin-perfect')
|
||||
const testValue = ref('')
|
||||
|
||||
const handleCopy = (text, event) => {
|
||||
clip(text, event)
|
||||
}
|
||||
const handleCopy = (text, event) => {
|
||||
clip(text, event)
|
||||
}
|
||||
</script>
|
||||
|
|
@ -1,223 +0,0 @@
|
|||
<template>
|
||||
<div>
|
||||
<input ref="input" type="file" name="image" accept="image/*" @change="setImage" />
|
||||
|
||||
<div class="content">
|
||||
<section class="cropper-area">
|
||||
<div class="img-cropper">
|
||||
<vue-cropper ref="cropper" :aspect-ratio="16 / 9" :src="imgSrc" preview=".preview" />
|
||||
</div>
|
||||
<div class="actions">
|
||||
<a href="#" role="button" @click.prevent="zoom(0.2)"> Zoom In </a>
|
||||
<a href="#" role="button" @click.prevent="zoom(-0.2)"> Zoom Out </a>
|
||||
<a href="#" role="button" @click.prevent="move(-10, 0)"> Move Left </a>
|
||||
<a href="#" role="button" @click.prevent="move(10, 0)"> Move Right </a>
|
||||
<a href="#" role="button" @click.prevent="move(0, -10)"> Move Up </a>
|
||||
<a href="#" role="button" @click.prevent="move(0, 10)"> Move Down </a>
|
||||
<a href="#" role="button" @click.prevent="rotate(90)"> Rotate +90deg </a>
|
||||
<a href="#" role="button" @click.prevent="rotate(-90)"> Rotate -90deg </a>
|
||||
<a ref="flipX" href="#" role="button" @click.prevent="flipX"> Flip X </a>
|
||||
<a ref="flipY" href="#" role="button" @click.prevent="flipY"> Flip Y </a>
|
||||
<a href="#" role="button" @click.prevent="cropImage"> Crop </a>
|
||||
<a href="#" role="button" @click.prevent="reset"> Reset </a>
|
||||
<a href="#" role="button" @click.prevent="getData"> Get Data </a>
|
||||
<a href="#" role="button" @click.prevent="setData"> Set Data </a>
|
||||
<a href="#" role="button" @click.prevent="getCropBoxData"> Get CropBox Data </a>
|
||||
<a href="#" role="button" @click.prevent="setCropBoxData"> Set CropBox Data </a>
|
||||
<a href="#" role="button" @click.prevent="showFileChooser"> Upload Image </a>
|
||||
</div>
|
||||
|
||||
<textarea v-model="data" />
|
||||
</section>
|
||||
<section class="preview-area">
|
||||
<p>Preview</p>
|
||||
<div class="preview" />
|
||||
<p>Cropped Image</p>
|
||||
<div class="cropped-image">
|
||||
<img v-if="cropImg" :src="cropImg" alt="Cropped Image" />
|
||||
<div v-else class="crop-placeholder" />
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import VueCropper from 'vue-cropperjs'
|
||||
import 'cropperjs/dist/cropper.css'
|
||||
// import imgSrc from "@/assets/image/berserk.jpg"
|
||||
import imgSrc from '@/assets/image/im1.jpeg'
|
||||
export default {
|
||||
components: {
|
||||
VueCropper,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
imgSrc: imgSrc,
|
||||
cropImg: '',
|
||||
data: null,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
cropImage() {
|
||||
// get image data for post processing, e.g. upload or setting image src
|
||||
this.cropImg = this.$refs.cropper.getCroppedCanvas().toDataURL()
|
||||
},
|
||||
flipX() {
|
||||
const dom = this.$refs.flipX
|
||||
let scale = dom.getAttribute('data-scale')
|
||||
scale = scale ? -scale : -1
|
||||
this.$refs.cropper.scaleX(scale)
|
||||
dom.setAttribute('data-scale', scale)
|
||||
},
|
||||
flipY() {
|
||||
const dom = this.$refs.flipY
|
||||
let scale = dom.getAttribute('data-scale')
|
||||
scale = scale ? -scale : -1
|
||||
this.$refs.cropper.scaleY(scale)
|
||||
dom.setAttribute('data-scale', scale)
|
||||
},
|
||||
getCropBoxData() {
|
||||
this.data = JSON.stringify(this.$refs.cropper.getCropBoxData(), null, 4)
|
||||
},
|
||||
getData() {
|
||||
this.data = JSON.stringify(this.$refs.cropper.getData(), null, 4)
|
||||
},
|
||||
move(offsetX, offsetY) {
|
||||
this.$refs.cropper.move(offsetX, offsetY)
|
||||
},
|
||||
reset() {
|
||||
this.$refs.cropper.reset()
|
||||
},
|
||||
rotate(deg) {
|
||||
this.$refs.cropper.rotate(deg)
|
||||
},
|
||||
setCropBoxData() {
|
||||
if (!this.data) return
|
||||
|
||||
this.$refs.cropper.setCropBoxData(JSON.parse(this.data))
|
||||
},
|
||||
setData() {
|
||||
if (!this.data) return
|
||||
|
||||
this.$refs.cropper.setData(JSON.parse(this.data))
|
||||
},
|
||||
setImage(e) {
|
||||
const file = e.target.files[0]
|
||||
|
||||
if (file.type.indexOf('image/') === -1) {
|
||||
alert('Please select an image file')
|
||||
return
|
||||
}
|
||||
|
||||
if (typeof FileReader === 'function') {
|
||||
const reader = new FileReader()
|
||||
|
||||
reader.onload = (event) => {
|
||||
this.imgSrc = event.target.result
|
||||
// rebuild cropperjs with the updated source
|
||||
this.$refs.cropper.replace(event.target.result)
|
||||
}
|
||||
|
||||
reader.readAsDataURL(file)
|
||||
} else {
|
||||
alert('Sorry, FileReader API not supported')
|
||||
}
|
||||
},
|
||||
showFileChooser() {
|
||||
this.$refs.input.click()
|
||||
},
|
||||
zoom(percent) {
|
||||
this.$refs.cropper.relativeZoom(percent)
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
||||
<style scoped>
|
||||
body {
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
width: 1024px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
input[type='file'] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 10px 0 5px 0;
|
||||
}
|
||||
|
||||
.header h2 {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.header a {
|
||||
text-decoration: none;
|
||||
color: black;
|
||||
}
|
||||
|
||||
.content {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.cropper-area {
|
||||
width: 614px;
|
||||
}
|
||||
|
||||
.actions {
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
.actions a {
|
||||
display: inline-block;
|
||||
padding: 5px 15px;
|
||||
background: #0062cc;
|
||||
color: white;
|
||||
text-decoration: none;
|
||||
border-radius: 3px;
|
||||
margin-right: 1rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
textarea {
|
||||
width: 100%;
|
||||
height: 100px;
|
||||
}
|
||||
|
||||
.preview-area {
|
||||
width: 307px;
|
||||
}
|
||||
|
||||
.preview-area p {
|
||||
font-size: 1.25rem;
|
||||
margin: 0;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.preview-area p:last-of-type {
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
.preview {
|
||||
width: 100%;
|
||||
height: calc(372px * (9 / 16));
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.crop-placeholder {
|
||||
width: 100%;
|
||||
height: 200px;
|
||||
background: #ccc;
|
||||
}
|
||||
|
||||
.cropped-image img {
|
||||
max-width: 100%;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,167 +0,0 @@
|
|||
<template>
|
||||
<div class="m-cropper">
|
||||
<div class="left">
|
||||
<div class="cropper-content">
|
||||
<vue-cropper
|
||||
ref="cropper"
|
||||
:src="options.imgSrc"
|
||||
@crop="cropmove"
|
||||
:minCropBoxWidth="options.minCropBoxWidth"
|
||||
preview=".preview"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<el-button type="primary" @click.prevent="zoom(0.2)">放大</el-button>
|
||||
<el-button type="primary" @click.prevent="zoom(-0.2)">缩小</el-button>
|
||||
<el-button type="primary" @click.prevent="move(-10, 0)">向左移动</el-button>
|
||||
<el-button type="primary" @click.prevent="move(10, 0)">向右移动</el-button>
|
||||
<el-button type="primary" @click.prevent="move(0, -10)">向上移动</el-button>
|
||||
<el-button type="primary" @click.prevent="move(0, 10)">向下移动</el-button>
|
||||
<el-button type="primary" @click.prevent="rotate(90)">旋转90度</el-button>
|
||||
<el-button type="primary" @click.prevent="rotate(-90)">旋转-90度</el-button>
|
||||
<el-button type="primary" ref="flipX" @click.prevent="flipXAction">翻转 X</el-button>
|
||||
<el-button type="primary" ref="flipY" @click.prevent="flipYAction">翻转 Y</el-button>
|
||||
<el-button type="primary" @click.prevent="reset">重置</el-button>
|
||||
<el-button type="primary" @click.prevent="cropImage">获取结果</el-button>
|
||||
<el-upload class="upload-demo" :show-file-list="false" action :before-upload="beforeUpload">
|
||||
<el-button type="primary">选择上传图片</el-button>
|
||||
</el-upload>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div class="preview"> </div>
|
||||
<h4 style="margin-top: 10px">得到结果</h4>
|
||||
<div style="background: #ccc; width: 100px; height: 100px">
|
||||
<img :src="options.cropImg" style="width: 100%; height: 100%" v-if="options.cropImg" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
// http://github.xyxiao.cn/vue-cropper/example/
|
||||
// https://codepen.io/xyxiao001/pen/yLooYKg
|
||||
import VueCropper from 'vue-cropperjs'
|
||||
import imgSrc from '@/assets/image/cro.jpg'
|
||||
import 'cropperjs/dist/cropper.css'
|
||||
import { reactive, ref } from 'vue'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import type { UploadProps, UploadUserFile } from 'element-plus'
|
||||
|
||||
const cropper = ref()
|
||||
const flipX = ref()
|
||||
const flipY = ref()
|
||||
|
||||
const options = reactive({
|
||||
cropImg: null,
|
||||
imgSrc: imgSrc,
|
||||
minCropBoxWidth: 200,
|
||||
})
|
||||
|
||||
const handleRemove: UploadProps['onRemove'] = (file, uploadFiles) => {
|
||||
console.log(file, uploadFiles)
|
||||
}
|
||||
|
||||
const handlePreview: UploadProps['onPreview'] = (uploadFile) => {
|
||||
console.log(uploadFile)
|
||||
}
|
||||
|
||||
const handleExceed: UploadProps['onExceed'] = (files, uploadFiles) => {
|
||||
ElMessage.warning(
|
||||
`The limit is 3, you selected ${files.length} files this time, add up to ${
|
||||
files.length + uploadFiles.length
|
||||
} totally`,
|
||||
)
|
||||
}
|
||||
|
||||
const beforeRemove: UploadProps['beforeRemove'] = (uploadFile, uploadFiles) => {
|
||||
return ElMessageBox.confirm(`Cancel the transfert of ${uploadFile.name} ?`).then(
|
||||
() => true,
|
||||
() => false,
|
||||
)
|
||||
}
|
||||
|
||||
const cropmove = (e) => {
|
||||
// console.log('eeeeee',e)
|
||||
}
|
||||
|
||||
const zoom = (percent) => {
|
||||
cropper.value.relativeZoom(percent)
|
||||
}
|
||||
|
||||
const move = (offsetX, offsetY) => {
|
||||
cropper.value.move(offsetX, offsetY)
|
||||
}
|
||||
|
||||
const rotate = (deg) => {
|
||||
cropper.value.rotate(deg)
|
||||
}
|
||||
|
||||
const flipXAction = () => {
|
||||
const dom = flipX.value
|
||||
let scale = dom.getAttribute('data-scale')
|
||||
scale = scale ? -scale : -1
|
||||
cropper.value.scaleX(scale)
|
||||
dom.setAttribute('data-scale', scale)
|
||||
}
|
||||
const flipYAction = () => {
|
||||
const dom = flipY.value
|
||||
let scale = dom.getAttribute('data-scale')
|
||||
scale = scale ? -scale : -1
|
||||
cropper.value.scaleY(scale)
|
||||
dom.setAttribute('data-scale', scale)
|
||||
}
|
||||
|
||||
const cropImage = () => {
|
||||
options.cropImg = cropper.value.getCroppedCanvas().toDataURL()
|
||||
}
|
||||
|
||||
const reset = () => {
|
||||
cropper.value.reset()
|
||||
}
|
||||
|
||||
const beforeUpload = (file, fileList) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
var reader = new FileReader()
|
||||
// let res = !/\.(gif|jpg|jpeg|png|bmp|GIF|JPG|PNG)$/
|
||||
let reg = /\.jpg$|\.jpeg$|\.gif$|\.png$/i
|
||||
reader.readAsDataURL(file)
|
||||
let name = file.name
|
||||
if (reg.test(name)) {
|
||||
reader.onload = (e: FileReader) => {
|
||||
resolve(e.target.result)
|
||||
options.imgSrc = e.target.result
|
||||
cropper.value.replace(e.target.result)
|
||||
}
|
||||
} else {
|
||||
ElMessage.error('请上传图片')
|
||||
reject()
|
||||
}
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.cropper-content {
|
||||
display: flex;
|
||||
width: 400px;
|
||||
text-align: center;
|
||||
}
|
||||
::v-deep(.el-button) {
|
||||
margin-top: 15px;
|
||||
}
|
||||
.m-cropper {
|
||||
display: flex;
|
||||
.left {
|
||||
width: 400px;
|
||||
margin-right: 30px;
|
||||
}
|
||||
.preview {
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
margin-top: 20px;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,220 +0,0 @@
|
|||
<template>
|
||||
<div class="m-cropper">
|
||||
<div class="left">
|
||||
<div class="cropper-content">
|
||||
<vue-cropper
|
||||
ref="cropper"
|
||||
:img="option.img"
|
||||
:output-size="option.size"
|
||||
:output-type="option.outputType"
|
||||
:info="true"
|
||||
:full="option.full"
|
||||
:fixed="fixed"
|
||||
:fixed-number="fixedNumber"
|
||||
:can-move="option.canMove"
|
||||
:can-move-box="option.canMoveBox"
|
||||
:autoCropWidth="option.autoCropWidth"
|
||||
:autoCropHeight="option.autoCropHeight"
|
||||
:fixed-box="option.fixedBox"
|
||||
:auto-crop="option.autoCrop"
|
||||
:auto-crop-height="option.autoCropHeight"
|
||||
:center-box="option.centerBox"
|
||||
@real-time="realTime"
|
||||
/>
|
||||
</div>
|
||||
<!-- <div>-->
|
||||
<el-button type="primary" @click.prevent="zoom(1)">放大</el-button>
|
||||
<el-button type="primary" @click.prevent="zoom(-1)">缩小</el-button>
|
||||
<el-button type="primary" @click.prevent="rotateLeft">向左旋转</el-button>
|
||||
<el-button type="primary" @click.prevent="rotateRight">向右旋转</el-button>
|
||||
<!-- <el-button type="primary" @click.prevent="move(0, -10)">向上移动</el-button>-->
|
||||
<!-- <el-button type="primary" @click.prevent="move(0, 10)">向下移动</el-button>-->
|
||||
<!-- <el-button type="primary" @click.prevent="rotate(90)">旋转90度</el-button>-->
|
||||
<!-- <el-button type="primary" @click.prevent="rotate(-90)">旋转-90度</el-button>-->
|
||||
<!-- <el-button type="primary"-->
|
||||
<!-- ref="flipX"-->
|
||||
<!-- @click.prevent="flipXAction">翻转 X</el-button>-->
|
||||
<!-- <el-button type="primary"-->
|
||||
<!-- ref="flipY"-->
|
||||
<!-- @click.prevent="flipYAction">翻转 Y</el-button>-->
|
||||
<el-button type="primary" @click.prevent="reset">重置</el-button>
|
||||
<el-button type="primary" @click.prevent="cropImage">获取结果</el-button>
|
||||
<el-button type="primary" @click.prevent="down('base64')">下载图片</el-button>
|
||||
<el-upload class="upload-demo" :show-file-list="false" action :before-upload="beforeUpload">
|
||||
<el-button type="primary">选择上传图片</el-button>
|
||||
</el-upload>
|
||||
<!-- </div>-->
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h4 style="margin-top: 10px">实时预览</h4>
|
||||
<div
|
||||
class="show-preview"
|
||||
:style="{
|
||||
width: option.previews.w + 'px',
|
||||
height: option.previews.h + 'px',
|
||||
overflow: 'hidden',
|
||||
margin: '5px',
|
||||
}"
|
||||
>
|
||||
<div :style="option.previews.div">
|
||||
<img :src="option.previews.url" :style="option.previews.img" />
|
||||
</div>
|
||||
</div>
|
||||
<h4 style="margin-top: 10px">获取结果</h4>
|
||||
<div style="background: #ccc; width: 100px; height: 100px">
|
||||
<img :src="option.cropImg" style="width: 100%; height: 100%" v-if="option.cropImg" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
// http://github.xyxiao.cn/vue-cropper/example/
|
||||
// https://codepen.io/xyxiao001/pen/yLooYKg
|
||||
import 'vue-cropper/dist/index.css'
|
||||
import { VueCropper } from 'vue-cropper'
|
||||
import imgSrc from '@/assets/image/cro.jpg'
|
||||
import { reactive, ref } from 'vue'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import type { UploadProps, UploadUserFile } from 'element-plus'
|
||||
|
||||
const cropper = ref()
|
||||
const flipX = ref()
|
||||
const flipY = ref()
|
||||
|
||||
const option = reactive({
|
||||
img: imgSrc,
|
||||
size: 1,
|
||||
full: false, // 是否输出原图比例的截图
|
||||
outputType: 'png',
|
||||
canMove: true,
|
||||
info: true, // 裁剪框的大小信息
|
||||
outputSize: 0.8, // 裁剪生成图片的质量
|
||||
fixedBox: false, // 固定截图框大小 不允许改变
|
||||
original: false, // 上传图片按照原始比例渲染
|
||||
canMoveBox: true, // 截图框能否拖动
|
||||
autoCrop: true, // 是否默认生成截图框
|
||||
autoCropWidth: 300, // 默认生成截图框宽度
|
||||
autoCropHeight: 300, // 默认生成截图框高度
|
||||
// 只有自动截图开启 宽度高度才生效
|
||||
centerBox: false, // 截图框是否被限制在图片里面
|
||||
high: true,
|
||||
max: 99999,
|
||||
previews: {
|
||||
url: '',
|
||||
},
|
||||
cropImg: '',
|
||||
})
|
||||
|
||||
const realTime = (data) => {
|
||||
option.previews = data
|
||||
}
|
||||
|
||||
const cropmove = (e) => {
|
||||
// console.log('eeeeee',e)
|
||||
}
|
||||
|
||||
const zoom = (percent) => {
|
||||
cropper.value.changeScale(percent)
|
||||
}
|
||||
const rotateLeft = () => {
|
||||
cropper.value.rotateLeft()
|
||||
}
|
||||
const rotateRight = () => {
|
||||
cropper.value.rotateRight()
|
||||
}
|
||||
|
||||
const move = (offsetX, offsetY) => {
|
||||
cropper.value.move(offsetX, offsetY)
|
||||
}
|
||||
|
||||
const down = (type) => {
|
||||
// event.preventDefault()
|
||||
var aLink = document.createElement('a')
|
||||
aLink.download = 'demo'
|
||||
// 输出
|
||||
if (type === 'blob') {
|
||||
this.$refs.cropper.getCropBlob((data) => {
|
||||
// this.downImg = window.URL.createObjectURL(data);
|
||||
aLink.href = window.URL.createObjectURL(data)
|
||||
aLink.click()
|
||||
})
|
||||
} else {
|
||||
cropper.value.getCropData((data) => {
|
||||
// this.downImg = data;
|
||||
aLink.href = data
|
||||
aLink.click()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const rotate = (deg) => {
|
||||
cropper.value.rotate(deg)
|
||||
}
|
||||
|
||||
const cropImage = () => {
|
||||
cropper.value.getCropData((data) => {
|
||||
option.cropImg = data
|
||||
})
|
||||
}
|
||||
|
||||
const reset = () => {
|
||||
option.img = ''
|
||||
option.cropImg = ''
|
||||
}
|
||||
|
||||
const beforeUpload = (file, fileList) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
var reader = new FileReader()
|
||||
// let res = !/\.(gif|jpg|jpeg|png|bmp|GIF|JPG|PNG)$/
|
||||
let reg = /\.jpg$|\.jpeg$|\.gif$|\.png$/i
|
||||
reader.readAsDataURL(file)
|
||||
let name = file.name
|
||||
if (reg.test(name)) {
|
||||
reader.onload = (e: FileReader) => {
|
||||
let data
|
||||
if (typeof e.target.result === 'object') {
|
||||
// 把Array Buffer转化为blob 如果是base64不需要
|
||||
data = window.URL.createObjectURL(new Blob([e.target.result]))
|
||||
} else {
|
||||
data = e.target.result
|
||||
}
|
||||
resolve(e.target.result)
|
||||
option.imgSrc = data
|
||||
option.img = data
|
||||
}
|
||||
} else {
|
||||
ElMessage.error('请上传图片')
|
||||
reject()
|
||||
}
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.cropper-content {
|
||||
display: flex;
|
||||
width: 400px;
|
||||
height: 400px;
|
||||
text-align: center;
|
||||
}
|
||||
::v-deep(.el-button) {
|
||||
margin-top: 15px;
|
||||
}
|
||||
.m-cropper {
|
||||
width: 100%;
|
||||
height: 500px;
|
||||
display: flex;
|
||||
.left {
|
||||
width: 400px;
|
||||
margin-right: 30px;
|
||||
}
|
||||
.preview {
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
margin-top: 20px;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,51 +1,53 @@
|
|||
<template>
|
||||
<u-container-layout>
|
||||
<el-form ref="formRef" :model="dynamicValidateForm" label-width="80px" class="demo-dynamic">
|
||||
<el-form-item
|
||||
prop="title"
|
||||
label="标题"
|
||||
:rules="[{ required: true, message: '请输入标题', trigger: 'blur' }]"
|
||||
<div class="app-container">
|
||||
<div class="app-container-inner">
|
||||
<el-form ref="formRef" :model="dynamicValidateForm" label-width="80px" class="demo-dynamic">
|
||||
<el-form-item
|
||||
prop="title"
|
||||
label="标题"
|
||||
:rules="[{ required: true, message: '请输入标题', trigger: 'blur' }]"
|
||||
>
|
||||
<el-input v-model="dynamicValidateForm.title" />
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
prop="content"
|
||||
label="标题"
|
||||
:rules="[{ required: true, message: '请输入内容', trigger: 'blur' }]"
|
||||
>
|
||||
<wang-edior v-model="dynamicValidateForm.content" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="submitForm(formRef)">保存</el-button>
|
||||
<el-button type="primary" @click="preview(formRef)">预览</el-button>
|
||||
<el-button @click="resetForm(formRef)">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-descriptions title="配置项 " :column="1" border class="descriptions">
|
||||
<el-descriptions-item label="value"> 双向绑定的 value 值,使用示例:v-model='content' </el-descriptions-item>
|
||||
<el-descriptions-item label="参考文档"> <a href="https://www.wangeditor.com/v5/for-frame.html" target="_blank"> https://www.wangeditor.com/v5/for-frame.html </a> </el-descriptions-item>
|
||||
|
||||
</el-descriptions>
|
||||
|
||||
|
||||
|
||||
<el-dialog
|
||||
v-model="dialogVisible"
|
||||
title="预览"
|
||||
width="60%"
|
||||
>
|
||||
<el-input v-model="dynamicValidateForm.title" />
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
prop="content"
|
||||
label="标题"
|
||||
:rules="[{ required: true, message: '请输入内容', trigger: 'blur' }]"
|
||||
>
|
||||
<wang-edior v-model="dynamicValidateForm.content" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="submitForm(formRef)">保存</el-button>
|
||||
<el-button type="primary" @click="preview(formRef)">预览</el-button>
|
||||
<el-button @click="resetForm(formRef)">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-descriptions title="配置项 " :column="1" border class="descriptions">
|
||||
<el-descriptions-item label="value"> 双向绑定的 value 值,使用示例:v-model='content' </el-descriptions-item>
|
||||
<el-descriptions-item label="参考文档"> <a href="https://www.wangeditor.com/v5/for-frame.html" target="_blank"> https://www.wangeditor.com/v5/for-frame.html </a> </el-descriptions-item>
|
||||
|
||||
</el-descriptions>
|
||||
|
||||
|
||||
|
||||
<el-dialog
|
||||
v-model="dialogVisible"
|
||||
title="预览"
|
||||
width="60%"
|
||||
>
|
||||
<div style="display: flex;align-items: center;margin-bottom: 20px">
|
||||
<span style="width: 50px;font-weight: bold">标题:</span>
|
||||
<div>{{dynamicValidateForm.title}}</div>
|
||||
</div>
|
||||
<div style="display: flex;align-items: center;margin-bottom: 20px">
|
||||
<span style="width: 50px;font-weight: bold">内容</span>
|
||||
<div v-html="dynamicValidateForm.content"></div>
|
||||
</div>
|
||||
<template #footer>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</u-container-layout>
|
||||
<div style="display: flex;align-items: center;margin-bottom: 20px">
|
||||
<span style="width: 50px;font-weight: bold">标题:</span>
|
||||
<div>{{dynamicValidateForm.title}}</div>
|
||||
</div>
|
||||
<div style="display: flex;align-items: center;margin-bottom: 20px">
|
||||
<span style="width: 50px;font-weight: bold">内容</span>
|
||||
<div v-html="dynamicValidateForm.content"></div>
|
||||
</div>
|
||||
<template #footer>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
|
@ -96,3 +98,5 @@ const resetForm = (formEl: FormInstance | undefined) => {
|
|||
formEl.resetFields()
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,33 +1,39 @@
|
|||
<template>
|
||||
<u-container-layout class="components-container">
|
||||
<el-form :inline="true" :model="formInline" class="demo-form-inline" ref="ruleFormRef1">
|
||||
<el-form-item label="用户名" prop="username">
|
||||
<el-input v-model="formInline.username" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button @click="reset(ruleFormRef1)">重置</el-button>
|
||||
<el-button type="primary" @click="onSubmit">查询</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div style="margin-bottom: 15px; display: flex; justify-content: flex-end">
|
||||
<el-button type="primary" @click="add">新增</el-button>
|
||||
<div class="app-container">
|
||||
<div class="header">
|
||||
<el-form :inline="true" :model="formInline" class="demo-form-inline" ref="ruleFormRef1">
|
||||
<el-form-item label="用户名" prop="username">
|
||||
<el-input v-model="formInline.username" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="onSubmit" :icon="Search">查询</el-button>
|
||||
<el-button @click="reset(ruleFormRef1)">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<div class="footer">
|
||||
<div class="util">
|
||||
<el-button type="primary" @click="add">新增</el-button>
|
||||
</div>
|
||||
<div class="table-wrap">
|
||||
<el-table :data="tableData" style="width: 100%" border default-expand-all row-key="id" class="table">
|
||||
<el-table-column prop="menuName" label="权限名称" />
|
||||
<el-table-column prop="menuType" label="权限类型" />
|
||||
<el-table-column prop="menuRouter" label="权限路由" />
|
||||
<el-table-column prop="identification" label="权限标识" />
|
||||
<el-table-column prop="status" label="操作">
|
||||
<template #default="scope">
|
||||
<el-button type="primary" size="small" icon="Edit" @click="edit(scope.row)">
|
||||
编辑
|
||||
</el-button>
|
||||
<el-button @click="del(scope.row)" type="danger" size="small" icon="Delete">
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</div>
|
||||
<el-table :data="tableData" style="width: 100%" border default-expand-all row-key="id">
|
||||
<el-table-column prop="menuName" label="权限名称" />
|
||||
<el-table-column prop="menuType" label="权限类型" />
|
||||
<el-table-column prop="menuRouter" label="权限路由" />
|
||||
<el-table-column prop="identification" label="权限标识" />
|
||||
<el-table-column prop="status" label="操作">
|
||||
<template #default="scope">
|
||||
<el-button type="primary" size="small" icon="Edit" @click="edit(scope.row)">
|
||||
编辑
|
||||
</el-button>
|
||||
<el-button @click="del(scope.row)" type="danger" size="small" icon="Delete">
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-drawer v-model="dialogVisible" :title="title" width="50%">
|
||||
<el-form
|
||||
ref="ruleFormRef"
|
||||
|
|
@ -61,13 +67,14 @@
|
|||
</span>
|
||||
</template>
|
||||
</el-drawer>
|
||||
</u-container-layout>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ElMessageBox, ElMessage, FormInstance } from 'element-plus'
|
||||
import { reactive, ref } from 'vue'
|
||||
import { menuData } from './data/user'
|
||||
import {Search } from '@element-plus/icons-vue'
|
||||
import { menuData } from '@/mock/system'
|
||||
import * as dayjs from 'dayjs'
|
||||
const tableData = ref(menuData)
|
||||
const dialogVisible = ref(false)
|
||||
|
|
@ -159,4 +166,49 @@
|
|||
}
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
<style scoped lang="scss">
|
||||
.header{
|
||||
display: flex;
|
||||
padding: 16px 16px 0px 16px;
|
||||
margin-bottom: 16px;
|
||||
border-radius: 4px;
|
||||
background: white;
|
||||
box-shadow: 0 0 12px rgb(0 0 0 / 5%);
|
||||
}
|
||||
.footer{
|
||||
flex: 1;
|
||||
display: flex;
|
||||
padding: 16px;
|
||||
flex-direction: column;
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
background: white;
|
||||
box-shadow: 0 0 12px rgb(0 0 0 / 5%);
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
.util{
|
||||
margin-bottom: 15px;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.table-wrap{
|
||||
flex: 1;
|
||||
display: flex;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
.table-inner{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
}
|
||||
.table{
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,31 +1,37 @@
|
|||
<template>
|
||||
<u-container-layout class="components-container">
|
||||
<el-form :inline="true" :model="formInline" class="demo-form-inline" ref="ruleFormRef1">
|
||||
<el-form-item label="角色名称" prop="roleName">
|
||||
<el-input v-model="formInline.roleName" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button @click="reset(ruleFormRef1)">重置</el-button>
|
||||
<el-button type="primary" @click="onSubmit">查询</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div style="margin-bottom: 15px; display: flex; justify-content: flex-end">
|
||||
<el-button type="primary" @click="add">新增</el-button>
|
||||
<div class="app-container">
|
||||
<div class="header">
|
||||
<el-form :inline="true" :model="formInline" class="demo-form-inline" ref="ruleFormRef1">
|
||||
<el-form-item label="角色名称" prop="roleName">
|
||||
<el-input v-model="formInline.roleName" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="onSubmit" :icon="Search">查询</el-button>
|
||||
<el-button @click="reset(ruleFormRef1)">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<div class="footer">
|
||||
<div class="util">
|
||||
<el-button type="primary" @click="add">新增</el-button>
|
||||
</div>
|
||||
<div class="table-inner">
|
||||
<el-table :data="tableData" style="width: 100%" border>
|
||||
<el-table-column prop="roleName" label="角色名称" />
|
||||
<el-table-column prop="createTime" label="创建时间" />
|
||||
<el-table-column prop="status" label="操作">
|
||||
<template #default="scope">
|
||||
<el-button type="primary" size="small" icon="Edit" @click="edit(scope.row)">
|
||||
编辑
|
||||
</el-button>
|
||||
<el-button @click="del(scope.row)" type="danger" size="small" icon="Delete">
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</div>
|
||||
<el-table :data="tableData" style="width: 100%" border>
|
||||
<el-table-column prop="roleName" label="角色名称" />
|
||||
<el-table-column prop="createTime" label="创建时间" />
|
||||
<el-table-column prop="status" label="操作">
|
||||
<template #default="scope">
|
||||
<el-button type="primary" size="small" icon="Edit" @click="edit(scope.row)">
|
||||
编辑
|
||||
</el-button>
|
||||
<el-button @click="del(scope.row)" type="danger" size="small" icon="Delete">
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-drawer v-model="dialogVisible" :title="title" width="50%">
|
||||
<el-form
|
||||
ref="ruleFormRef"
|
||||
|
|
@ -58,13 +64,14 @@
|
|||
</span>
|
||||
</template>
|
||||
</el-drawer>
|
||||
</u-container-layout>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ElMessageBox, ElMessage, FormInstance } from 'element-plus'
|
||||
import {Search } from '@element-plus/icons-vue'
|
||||
import { reactive, ref } from 'vue'
|
||||
import { roleData, menuData } from './data/user'
|
||||
import { roleData } from '@/mock/system'
|
||||
import * as dayjs from 'dayjs'
|
||||
const tableData = ref(roleData)
|
||||
const dialogVisible = ref(false)
|
||||
|
|
@ -155,4 +162,43 @@
|
|||
}
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
<style scoped lang="scss">
|
||||
.header{
|
||||
display: flex;
|
||||
padding: 16px 16px 0px 16px;
|
||||
margin-bottom: 16px;
|
||||
border-radius: 4px;
|
||||
background: white;
|
||||
box-shadow: 0 0 12px rgb(0 0 0 / 5%);
|
||||
}
|
||||
.footer{
|
||||
flex: 1;
|
||||
display: flex;
|
||||
padding: 16px;
|
||||
flex-direction: column;
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
background: white;
|
||||
box-shadow: 0 0 12px rgb(0 0 0 / 5%);
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
.util{
|
||||
margin-bottom: 15px;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.table-inner{
|
||||
flex: 1;
|
||||
position: relative;
|
||||
}
|
||||
.table{
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,38 +1,44 @@
|
|||
<template>
|
||||
<u-container-layout class="components-container">
|
||||
<el-form :inline="true" :model="formInline" class="demo-form-inline" ref="ruleFormRef1">
|
||||
<el-form-item label="用户名" prop="username">
|
||||
<el-input v-model="formInline.username" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button @click="reset(ruleFormRef1)">重置</el-button>
|
||||
<el-button type="primary" @click="onSubmit">查询</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div style="margin-bottom: 15px; display: flex; justify-content: flex-end">
|
||||
<el-button type="primary" @click="add">新增</el-button>
|
||||
<div class="app-container">
|
||||
<div class="header">
|
||||
<el-form :inline="true" :model="formInline" ref="ruleFormRef1">
|
||||
<el-form-item label="用户名" prop="username">
|
||||
<el-input v-model="formInline.username" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="onSubmit" :icon="Search">查询</el-button>
|
||||
<el-button @click="reset(ruleFormRef1)">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<div class="footer">
|
||||
<div class="util">
|
||||
<el-button type="primary" @click="add">新增</el-button>
|
||||
</div>
|
||||
<div class="table-inner">
|
||||
<el-table :data="tableData" style="width: 100%" border>
|
||||
<el-table-column prop="username" label="用户名" />
|
||||
<el-table-column prop="nickname" label="昵称" />
|
||||
<el-table-column prop="sex" label="性别" />
|
||||
<el-table-column prop="role" label="角色" />
|
||||
<el-table-column prop="status" label="状态">
|
||||
<template #default="scope">
|
||||
<el-switch v-model="scope.row.status" @change="changeStatus(scope.row)" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="status" label="操作">
|
||||
<template #default="scope">
|
||||
<el-button type="primary" size="small" icon="Edit" @click="edit(scope.row)">
|
||||
编辑
|
||||
</el-button>
|
||||
<el-button @click="del(scope.row)" type="danger" size="small" icon="Delete">
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</div>
|
||||
<el-table :data="tableData" style="width: 100%" border>
|
||||
<el-table-column prop="username" label="用户名" />
|
||||
<el-table-column prop="nickname" label="昵称" />
|
||||
<el-table-column prop="sex" label="性别" />
|
||||
<el-table-column prop="role" label="角色" />
|
||||
<el-table-column prop="status" label="状态">
|
||||
<template #default="scope">
|
||||
<el-switch v-model="scope.row.status" @change="changeStatus(scope.row)" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="status" label="操作">
|
||||
<template #default="scope">
|
||||
<el-button type="primary" size="small" icon="Edit" @click="edit(scope.row)">
|
||||
编辑
|
||||
</el-button>
|
||||
<el-button @click="del(scope.row)" type="danger" size="small" icon="Delete">
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-dialog @close="close" v-model="dialogVisible" :title="title" width="50%">
|
||||
<el-form
|
||||
ref="ruleFormRef"
|
||||
|
|
@ -69,13 +75,14 @@
|
|||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</u-container-layout>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ElMessageBox, ElMessage, FormInstance } from 'element-plus'
|
||||
import {Search } from '@element-plus/icons-vue'
|
||||
import { reactive, ref } from 'vue'
|
||||
import { userData } from './data/user'
|
||||
import { userData } from '@/mock/system'
|
||||
import * as dayjs from 'dayjs'
|
||||
const tableData = ref(userData)
|
||||
const dialogVisible = ref(false)
|
||||
|
|
@ -168,4 +175,43 @@
|
|||
}
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
<style scoped lang="scss">
|
||||
.header{
|
||||
display: flex;
|
||||
padding: 16px 16px 0px 16px;
|
||||
margin-bottom: 16px;
|
||||
border-radius: 4px;
|
||||
background: white;
|
||||
box-shadow: 0 0 12px rgb(0 0 0 / 5%);
|
||||
}
|
||||
.footer{
|
||||
flex: 1;
|
||||
display: flex;
|
||||
padding: 16px;
|
||||
flex-direction: column;
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
background: white;
|
||||
box-shadow: 0 0 12px rgb(0 0 0 / 5%);
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
.util{
|
||||
margin-bottom: 15px;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.table-inner{
|
||||
flex: 1;
|
||||
position: relative;
|
||||
}
|
||||
.table{
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -273,7 +273,6 @@ onMounted(() => {
|
|||
width: 100%;
|
||||
padding: 16px;
|
||||
box-sizing: border-box;
|
||||
|
||||
}
|
||||
.cancel-btn {
|
||||
position: absolute;
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<u-container-layout>
|
||||
<div class="inline-edit-table">
|
||||
<el-form :inline="true" :model="formInline1" class="demo-form-inline">
|
||||
<div class="app-container">
|
||||
<div class="header">
|
||||
<el-form :inline="true" :model="formInline1" >
|
||||
<el-form-item label="姓名">
|
||||
<el-input v-model="formInline1.username" placeholder="请输入姓名" />
|
||||
</el-form-item>
|
||||
|
|
@ -9,9 +9,14 @@
|
|||
<el-button type="primary" @click="onSubmit">搜索</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-table :data="list" style="width: 100%" :border="true" v-loading="loading">
|
||||
<el-table-column prop="id" width="60" label="id" />
|
||||
<el-table-column prop="name" label="姓名" min-width="200px">
|
||||
</div>
|
||||
<div class="footer">
|
||||
|
||||
<el-table
|
||||
:data="list"
|
||||
style="width: 100%" :border="true" v-loading="loading">
|
||||
<el-table-column prop="id" width="60" label="id" align="center"/>
|
||||
<el-table-column prop="name" label="姓名" min-width="200px" align="center">
|
||||
<template #default="scope">
|
||||
<template v-if="scope.row.edit">
|
||||
<div style="display: flex; align-items: center">
|
||||
|
|
@ -29,19 +34,21 @@
|
|||
<template v-else>{{ scope.row.name }}</template>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="age" label="年龄" />
|
||||
<el-table-column prop="sex" label="性别">
|
||||
<el-table-column prop="age" label="年龄" align="center"/>
|
||||
<el-table-column prop="sex" label="性别" align="center">
|
||||
<template #default="scope">
|
||||
{{ scope.row.sex ? '男' : '女' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="price" label="价格" />
|
||||
<el-table-column prop="admin" label="账号" />
|
||||
<el-table-column prop="address" label="地址" width="180"/>
|
||||
<el-table-column prop="date" label="日期" width="180"/>
|
||||
<el-table-column prop="province" label="省份" width="120"/>
|
||||
<el-table-column prop="city" label="城市" />
|
||||
<el-table-column prop="operator" label="操作" width="180px" fixed="right">
|
||||
<el-table-column prop="price" label="价格" align="center"/>
|
||||
<el-table-column prop="admin" label="账号" align="center"/>
|
||||
<el-table-column prop="address"
|
||||
:show-overflow-tooltip="true"
|
||||
label="地址" width="180" align="center"/>
|
||||
<el-table-column prop="date" label="日期" width="180" align="center"/>
|
||||
<el-table-column prop="province" label="省份" width="120" align="center"/>
|
||||
<el-table-column prop="city" label="城市" align="center"/>
|
||||
<el-table-column prop="operator" label="操作" width="180px" fixed="right" align="center">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
v-if="scope.row.edit"
|
||||
|
|
@ -80,7 +87,7 @@
|
|||
/>
|
||||
</div>
|
||||
</div>
|
||||
</u-container-layout>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup name="inline-table">
|
||||
import { computed, ref } from 'vue'
|
||||
|
|
@ -99,7 +106,7 @@
|
|||
img: 'https://img1.baidu.com/it/u=300787145,1214060415&fm=253&fmt=auto&app=138&f=JPEG?w=800&h=500',
|
||||
age: 0,
|
||||
city: '普陀区',
|
||||
address: '上海市普上海',
|
||||
address: `上海市普陀区金沙江路 222${i} 弄`,
|
||||
zip: 200333,
|
||||
})
|
||||
}
|
||||
|
|
@ -121,7 +128,6 @@
|
|||
return arr.splice((currentPage1.value - 1) * 10, 10)
|
||||
})
|
||||
|
||||
const listLoading = ref(false)
|
||||
|
||||
const confirmEdit = (row) => {
|
||||
row.edit = false
|
||||
|
|
@ -160,16 +166,23 @@
|
|||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.edit-input {
|
||||
padding-right: 100px;
|
||||
}
|
||||
.cancel-btn {
|
||||
position: absolute;
|
||||
right: 15px;
|
||||
top: 10px;
|
||||
}
|
||||
.inline-edit-table {
|
||||
width: 100%;
|
||||
}
|
||||
<style scoped lang="scss">
|
||||
.header{
|
||||
display: flex;
|
||||
padding: 16px 16px 0px 16px;
|
||||
margin-bottom: 16px;
|
||||
border-radius: 4px;
|
||||
background: white;
|
||||
box-shadow: 0 0 12px rgb(0 0 0 / 5%);
|
||||
}
|
||||
.footer{
|
||||
flex: 1;
|
||||
display: flex;
|
||||
padding: 16px;
|
||||
flex-direction: column;
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
background: white;
|
||||
box-shadow: 0 0 12px rgb(0 0 0 / 5%);
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,99 +0,0 @@
|
|||
<template>
|
||||
<u-container-layout>
|
||||
<div style="margin-bottom: 15px; display: flex; align-items: center">
|
||||
<el-input
|
||||
v-model="input"
|
||||
placeholder="请输入文件名"
|
||||
style="width: 200px; margin-right: 10px"
|
||||
/>
|
||||
<el-button @click="exportExcelAction" type="primary">
|
||||
<el-icon style="margin-right: 10px"><document-remove /></el-icon>导出 zip
|
||||
</el-button>
|
||||
</div>
|
||||
<el-table :data="list" style="width: 100%" border>
|
||||
<template v-for="(item, index) in column" :key="index">
|
||||
<el-table-column :prop="item.name" :label="item.label" :width="item.width" />
|
||||
</template>
|
||||
</el-table>
|
||||
</u-container-layout>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, reactive } from 'vue'
|
||||
import * as dayjs from 'dayjs'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import { downloadFiles2Zip } from '@/utils/downloadzip'
|
||||
const data = []
|
||||
for (let i = 0; i < 10; i++) {
|
||||
data.push({
|
||||
date: '2016-05-02',
|
||||
name: '王五' + i,
|
||||
price: 1 + i,
|
||||
province: '上海',
|
||||
admin: 'admin',
|
||||
sex: i % 2 ? 1 : 0,
|
||||
checked: true,
|
||||
id: i + 1,
|
||||
age: 0,
|
||||
city: '普陀区',
|
||||
address: '上海市普上海',
|
||||
zip: 200333,
|
||||
})
|
||||
}
|
||||
const column = [
|
||||
{ name: 'id', label: 'id' },
|
||||
{ name: 'name', label: '姓名', inSearch: true, valueType: 'input' },
|
||||
{ name: 'age', label: '年龄', align: 'right' },
|
||||
{
|
||||
name: 'sex',
|
||||
label: '性别',
|
||||
slot: true,
|
||||
inSearch: true,
|
||||
options: [
|
||||
{
|
||||
value: 1,
|
||||
label: '男',
|
||||
},
|
||||
{
|
||||
value: 0,
|
||||
label: '女',
|
||||
},
|
||||
],
|
||||
valueType: 'select',
|
||||
},
|
||||
{
|
||||
name: 'price',
|
||||
label: '价格',
|
||||
inSearch: true,
|
||||
valueType: 'input',
|
||||
},
|
||||
{ name: 'admin', label: '账号', inSearch: true, valueType: 'input' },
|
||||
{ name: 'address', label: '地址', inSearch: true, valueType: 'input' },
|
||||
{ name: 'date', label: '日期', sorter: true, inSearch: true, valueType: 'input' },
|
||||
{ name: 'province', label: '省份' },
|
||||
{ name: 'city', label: '城市' },
|
||||
{ name: 'zip', label: '邮编' },
|
||||
]
|
||||
const list = ref(data)
|
||||
const input = ref('')
|
||||
const format = ref('xlsx')
|
||||
const exportExcelAction = () => {
|
||||
downloadFiles2Zip({
|
||||
zipName: '压缩包',
|
||||
files: [
|
||||
{
|
||||
filename: 'test',
|
||||
sheets: [
|
||||
{
|
||||
sheetName: 'test',
|
||||
columns: column,
|
||||
dataSource: data,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style></style>
|
||||
Loading…
Reference in New Issue