feat:优化页面代码及版本升级报错处理

main
朱群锋 2025-02-11 08:57:04 +08:00
parent 15a5b4804b
commit 969d9f5d7d
8 changed files with 1008 additions and 931 deletions

View File

@ -1,292 +1,317 @@
<script setup lang="ts"> <script setup lang="ts">
import {reactive, toRefs, watch} from 'vue' import {reactive, toRefs, watch} from 'vue'
import common from '@/utils/common' import common from '@/utils/common'
import {Sort, Setting} from '@element-plus/icons-vue'
const prop = defineProps({ const prop = defineProps({
loading: { loading: {
type: Boolean, type: Boolean,
default: false default: false
}, },
page: { page: {
type: Object, type: Object,
default:{ default: {
current: 1, current: 1,
size: 10, size: 10,
total: 0, total: 0,
}
},
column: {
type: Object,
default: []
},
operation: {
type: Object,
default: {
isShow: false,
width: '220'
}
},
tableHeight: {
type: Number,
default: null
},
headerCellStyle: {
type: Object,
default:{color:'#606266', fontWeight: 700}
},
data: {
type: Array,
default: []
},
})
const emit = defineEmits([
'onSizeChange','onCurrentChange','onSelectionChange','setCellColor',
'onButtonClick','onSwitchChange',
])
const state = reactive({
maxHeight: window.innerHeight - 280,
tableHeight: prop.tableHeight,
headerCellStyle: prop.headerCellStyle,
size: 'default',
columns: prop.column.map((item:any) => {return item.prop}),
checkColAll: true,
isIndeterminate: true,
cellStyle: function(e:any){
let obj:any = {};
emit('setCellColor', e, (color = {}) =>{
obj = color;
});
return obj;
},
})
const {
maxHeight,tableHeight,headerCellStyle,cellStyle,size,columns,checkColAll,isIndeterminate
} = toRefs(state)
const onSizeChange = (e:any) =>{
emit('onSizeChange', e)
} }
const onCurrentChange = (e:any) =>{ },
emit('onCurrentChange', e) column: {
type: Object,
default: []
},
operation: {
type: Object,
default: {
isShow: false,
width: '220'
} }
},
tableHeight: {
type: Number,
default: null
},
headerCellStyle: {
type: Object,
default: {color: '#606266', fontWeight: 700}
},
data: {
type: Array,
default: []
},
})
function onFind(arr:any,val:any){ const emit = defineEmits([
if(!arr) return 'info'; 'onSizeChange', 'onCurrentChange', 'onSelectionChange', 'setCellColor',
return arr.find((item:any)=>{ return item.value == val}).label; 'onButtonClick', 'onSwitchChange',
} ])
function onCheckColAll(val:boolean){ const state = reactive({
const _columns = prop.column.map((item:any) => {return item.prop}) maxHeight: window.innerHeight - 280,
state.columns = val ? _columns : [] tableHeight: prop.tableHeight,
state.isIndeterminate = false headerCellStyle: prop.headerCellStyle,
} size: 'default',
function onCheckedCol(value: string[]){ columns: prop.column.map((item: any) => {
let checkedCount = value.length return item.prop
state.checkColAll = checkedCount === prop.column.length }),
state.isIndeterminate = checkedCount > 0 && checkedCount < prop.column.length checkColAll: true,
} isIndeterminate: true,
cellStyle: function (e: any) {
let obj: any = {};
emit('setCellColor', e, (color = {}) => {
obj = color;
});
return obj;
},
})
const {
maxHeight, tableHeight, headerCellStyle, cellStyle, size, columns, checkColAll, isIndeterminate
} = toRefs(state)
watch(columns, (newValue, oldValue) =>{ const onSizeChange = (e: any) => {
prop.column.filter((item:any) =>{ emit('onSizeChange', e)
item.isShow = newValue.indexOf(item.prop) == -1; }
}) const onCurrentChange = (e: any) => {
}) emit('onCurrentChange', e)
}
function onFind(arr: any, val: any) {
if (!arr) return 'info';
return arr.find((item: any) => {
return item.value == val
}).label;
}
function onCheckColAll(val: boolean) {
const _columns = prop.column.map((item: any) => {
return item.prop
})
state.columns = val ? _columns : []
state.isIndeterminate = false
}
function onCheckedCol(value: string[]) {
let checkedCount = value.length
state.checkColAll = checkedCount === prop.column.length
state.isIndeterminate = checkedCount > 0 && checkedCount < prop.column.length
}
watch(columns, (newValue) => {
prop.column.filter((item: any) => {
item.isShow = newValue.indexOf(item.prop) == -1;
})
})
</script> </script>
<template> <template>
<div class="table-container"> <div class="table-container">
<div class="search-wrap" v-if="$slots.search"> <div class="search-wrap" v-if="$slots.search">
<el-space wrap> <el-space wrap>
<slot name="search"></slot> <slot name="search"></slot>
</el-space> </el-space>
</div> </div>
<div class="table-wrap"> <div class="table-wrap">
<div class="header"> <div class="header">
<el-popover placement="bottom" :width="80" trigger="click"> <el-popover placement="bottom" :width="80" trigger="click">
<template #reference> <template #reference>
<el-button link> <el-button link>
<el-icon :size="20"><Sort /></el-icon> <el-icon :size="20">
</el-button> <Sort/>
</template> </el-icon>
<div> </el-button>
<el-radio-group v-model="size"> </template>
<el-radio label="small">紧凑</el-radio> <div>
<el-radio label="default">默认</el-radio> <el-radio-group v-model="size">
<el-radio label="large">中等</el-radio> <el-radio value="small">紧凑</el-radio>
</el-radio-group> <el-radio value="default">默认</el-radio>
</div> <el-radio value="large">中等</el-radio>
</el-popover> </el-radio-group>
<el-popover placement="bottom" :width="120" trigger="click"> </div>
<template #reference> </el-popover>
<el-button link> <el-popover placement="bottom" :width="120" trigger="click">
<el-icon :size="20"><Setting /></el-icon> <template #reference>
</el-button> <el-button link>
</template> <el-icon :size="20">
<div> <Setting/>
<el-checkbox v-model="checkColAll" :indeterminate="isIndeterminate" @change="onCheckColAll">/</el-checkbox> </el-icon>
<el-scrollbar height="400px"> </el-button>
<el-checkbox-group v-model="columns" @change="onCheckedCol" > </template>
<el-checkbox v-for="col in column" :key="col" :label="col.prop">{{col.label}}</el-checkbox> <div>
</el-checkbox-group> <el-checkbox v-model="checkColAll" :indeterminate="isIndeterminate" @change="onCheckColAll">/
</el-scrollbar> </el-checkbox>
</div> <el-scrollbar height="400px">
</el-popover> <el-checkbox-group v-model="columns" @change="onCheckedCol">
</div> <el-checkbox v-for="col in column" :key="col" :label="col.label" :value="col.prop">{{ col.label }}
<el-table :data="data" border stripe :size="size" :height="tableHeight" :max-height="maxHeight" row-key="id" :tree-props="{children: 'children', hasChildren: 'hasChildren'}" </el-checkbox>
</el-checkbox-group>
</el-scrollbar>
</div>
</el-popover>
</div>
<el-table :data="data" border stripe :size="size" :height="tableHeight" :max-height="maxHeight" row-key="id"
:tree-props="{children: 'children', hasChildren: 'hasChildren'}"
v-loading="loading" :header-cell-style="headerCellStyle" :cell-style="cellStyle" v-loading="loading" :header-cell-style="headerCellStyle" :cell-style="cellStyle"
@selection-change="$emit('onSelectionChange')" style="width: 100%;"> @selection-change="$emit('onSelectionChange')" style="width: 100%;">
<template v-for="item in column" :key="item"> <template v-for="item in column" :key="item">
<el-table-column v-if="!item.prop && !item.label && !item.isShow" :fixed="item.fixed" type="selection" width="45"></el-table-column> <el-table-column v-if="!item.prop && !item.label && !item.isShow" :fixed="item.fixed" type="selection"
<!-- color值 --> width="45"></el-table-column>
<el-table-column v-else-if="item.type == 'color' && !item.isShow" <!-- color值 -->
:label="item.label" :align="item.align != null ? item.align : 'center'" :width="item.width"> <el-table-column v-else-if="item.type == 'color' && !item.isShow"
<template #default="scope"> :label="item.label" :align="item.align != null ? item.align : 'center'" :width="item.width">
<span :style="{color: scope.row[item.prop]}">{{scope.row[item.prop]}}</span> <template #default="scope">
</template> <span :style="{color: scope.row[item.prop]}">{{ scope.row[item.prop] }}</span>
</el-table-column> </template>
<!-- icon图标 --> </el-table-column>
<el-table-column v-else-if="item.type == 'icon' && !item.isShow" <!-- icon图标 -->
:label="item.label" :align="item.align != null ? item.align : 'center'" :width="item.width"> <el-table-column v-else-if="item.type == 'icon' && !item.isShow"
<template #default="scope"> :label="item.label" :align="item.align != null ? item.align : 'center'" :width="item.width">
<el-icon :size="20"> <template #default="scope">
<component :is="scope.row[item.prop]"></component> <el-icon :size="20">
</el-icon> <component :is="scope.row[item.prop]"></component>
</template> </el-icon>
</el-table-column> </template>
<!-- el-statistic --> </el-table-column>
<el-table-column v-else-if="item.type == 'statistic' && !item.isShow" <!-- el-statistic -->
:label="item.label" :align="item.align != null ? item.align : 'center'" :width="item.width"> <el-table-column v-else-if="item.type == 'statistic' && !item.isShow"
<template #default="scope"> :label="item.label" :align="item.align != null ? item.align : 'center'" :width="item.width">
<el-statistic :value="scope.row[item.prop]" <template #default="scope">
<el-statistic :value="scope.row[item.prop]"
:precision="item.option.precision" :precision="item.option.precision"
:formatter="item.option.formatter" :formatter="item.option.formatter"
:prefix="item.option.prefix" :prefix="item.option.prefix"
:suffix="item.option.suffix"/> :suffix="item.option.suffix"/>
</template> </template>
</el-table-column> </el-table-column>
<!-- el-image --> <!-- el-image -->
<el-table-column v-else-if="item.type == 'image' && !item.isShow" <el-table-column v-else-if="item.type == 'image' && !item.isShow"
:label="item.label" :align="item.align != null ? item.align : 'center'" :width="item.width"> :label="item.label" :align="item.align != null ? item.align : 'center'" :width="item.width">
<template #default="scope"> <template #default="scope">
<el-image :src="scope.row[item.prop]" :preview-src-list="[scope.row[item.prop]]" preview-teleported fit="cover" style="width: 50px; height: 50px"/> <el-image :src="scope.row[item.prop]" :preview-src-list="[scope.row[item.prop]]" preview-teleported
</template> fit="cover" style="width: 50px; height: 50px"/>
</el-table-column> </template>
<!-- el-rate --> </el-table-column>
<el-table-column v-else-if="item.type == 'rate' && !item.isShow" <!-- el-rate -->
:label="item.label" :align="item.align != null ? item.align : 'center'" :width="item.width"> <el-table-column v-else-if="item.type == 'rate' && !item.isShow"
<template #default="scope"> :label="item.label" :align="item.align != null ? item.align : 'center'" :width="item.width">
<el-rate v-model="scope.row[item.prop]" disabled allow-half /> <template #default="scope">
</template> <el-rate v-model="scope.row[item.prop]" disabled allow-half/>
</el-table-column> </template>
<!-- el-tag --> </el-table-column>
<el-table-column v-else-if="item.type == 'tag' && !item.isShow" show-overflow-tooltip <!-- el-tag -->
:label="item.label" :align="item.align != null ? item.align : 'center'" :width="item.width"> <el-table-column v-else-if="item.type == 'tag' && !item.isShow" show-overflow-tooltip
<template #default="scope"> :label="item.label" :align="item.align != null ? item.align : 'center'" :width="item.width">
<el-tag :size="item.option.size" <template #default="scope">
:effect="item.option.effect" <el-tag :size="item.option.size"
:type="onFind(item.option.typeList, scope.row[item.prop])"> :effect="item.option.effect"
{{scope.row[item.alias==null?item.prop:item.alias]}} :type="onFind(item.option.typeList, scope.row[item.prop])">
</el-tag> {{ scope.row[item.alias == null ? item.prop : item.alias] }}
</template> </el-tag>
</el-table-column> </template>
<!-- el-button --> </el-table-column>
<el-table-column v-else-if="item.type == 'button' && !item.isShow" show-overflow-tooltip <!-- el-button -->
:label="item.label" :align="item.align != null ? item.align : 'center'" :width="item.width"> <el-table-column v-else-if="item.type == 'button' && !item.isShow" show-overflow-tooltip
<template #default="scope"> :label="item.label" :align="item.align != null ? item.align : 'center'" :width="item.width">
<el-button @click="$emit('onButtonClick',scope.row)" :type="item.option.type" link :size="item.option.size"> <template #default="scope">
{{scope.row[item.alias==null?item.prop:item.alias]}} <el-button @click="$emit('onButtonClick',scope.row)" :type="item.option.type" link
</el-button> :size="item.option.size">
</template> {{ scope.row[item.alias == null ? item.prop : item.alias] }}
</el-table-column> </el-button>
<!-- el-switch --> </template>
<el-table-column v-else-if="item.type == 'switch' && !item.isShow" show-overflow-tooltip </el-table-column>
:label="item.label" :align="item.align != null ? item.align : 'center'" :width="item.width"> <!-- el-switch -->
<template #default="scope"> <el-table-column v-else-if="item.type == 'switch' && !item.isShow" show-overflow-tooltip
<el-switch @change="$emit('onSwitchChange',scope.row)" :inline-prompt="!item.option.inlinePrompt" :label="item.label" :align="item.align != null ? item.align : 'center'" :width="item.width">
:active-value="item.option.activeValue" :active-color="item.option.activeColor" :active-text="item.option.activeText" <template #default="scope">
:inactive-value="item.option.inactiveValue" :inactive-color="item.option.inactiveColor" :inactive-text="item.option.inactiveText" <el-switch @change="$emit('onSwitchChange',scope.row)" :inline-prompt="!item.option.inlinePrompt"
:size="item.option.size" :active-value="item.option.activeValue" :active-color="item.option.activeColor"
v-model="scope.row[item.prop]" :active-text="item.option.activeText"
></el-switch> :inactive-value="item.option.inactiveValue" :inactive-color="item.option.inactiveColor"
</template> :inactive-text="item.option.inactiveText"
</el-table-column> :size="item.option.size"
<!-- el-progress --> v-model="scope.row[item.prop]"
<el-table-column v-else-if="item.type == 'progress' && !item.isShow" show-overflow-tooltip ></el-switch>
:label="item.label" :align="item.align != null ? item.align : 'center'" :width="item.width"> </template>
<template #default="scope"> </el-table-column>
<el-progress :percentage="scope.row[item.alias==null?item.prop:item.alias]" <!-- el-progress -->
:status="item.option.status" <el-table-column v-else-if="item.type == 'progress' && !item.isShow" show-overflow-tooltip
:color="item.option.color"/> :label="item.label" :align="item.align != null ? item.align : 'center'" :width="item.width">
</template> <template #default="scope">
</el-table-column> <el-progress :percentage="scope.row[item.alias==null?item.prop:item.alias]"
<!-- 字典值 --> :status="item.option.status"
<el-table-column v-else-if="item.type == 'dict' && !item.isShow" :color="item.option.color"/>
:label="item.label" :align="item.align != null ? item.align : 'center'" :width="item.width"> </template>
<template #default="scope"> </el-table-column>
<span>{{common.getDictLabel(item.dictType, scope.row[item.prop])}}</span> <!-- 字典值 -->
</template> <el-table-column v-else-if="item.type == 'dict' && !item.isShow"
</el-table-column> :label="item.label" :align="item.align != null ? item.align : 'center'" :width="item.width">
<!-- 其他数据列 --> <template #default="scope">
<el-table-column v-else-if="!item.isShow" show-overflow-tooltip <span>{{ common.getDictLabel(item.dictType, scope.row[item.prop]) }}</span>
:prop="item.alias==null?item.prop:item.alias" </template>
:label="item.label" </el-table-column>
:align="item.align != null ? item.align : 'center'" <!-- 其他数据列 -->
:width="item.width" <el-table-column v-else-if="!item.isShow" show-overflow-tooltip
:fixed="item.fixed" :prop="item.alias==null?item.prop:item.alias"
:formatter="item.function"> :label="item.label"
</el-table-column> :align="item.align != null ? item.align : 'center'"
</template> :width="item.width"
<!-- 自定义插槽 --> :fixed="item.fixed"
<el-table-column v-if="operation.isShow" fixed="right" label="操作" align="center" :width="operation.width"> :formatter="item.function">
<template #default="scope"> </el-table-column>
<slot name="column" v-bind:column="scope"></slot> </template>
</template> <!-- 自定义插槽 -->
</el-table-column> <el-table-column v-if="operation.isShow" fixed="right" label="操作" align="center" :width="operation.width">
</el-table> <template #default="scope">
</div> <slot name="column" v-bind:column="scope"></slot>
<div class="pagination-wrap" v-if="page"> </template>
<el-pagination @size-change="onSizeChange" @current-change="onCurrentChange" </el-table-column>
layout="total, sizes, prev, pager, next, jumper" </el-table>
:current-page="page.current"
:page-sizes="[10, 20, 50, 100]"
:page-size="page.size"
:total="page.total"/>
</div>
</div> </div>
<div class="pagination-wrap" v-if="page">
<el-pagination @size-change="onSizeChange" @current-change="onCurrentChange"
layout="total, sizes, prev, pager, next, jumper"
:current-page="page.current"
:page-sizes="[10, 20, 50, 100]"
:page-size="page.size"
:total="page.total"/>
</div>
</div>
</template> </template>
<style scoped lang="scss"> <style scoped lang="scss">
.table-container{ .table-container {
.search-wrap{ .search-wrap {
// background: var(--bg1); // background: var(--bg1);
border: 1px solid var(--el-border-color); border: 1px solid var(--el-border-color);
border-radius: var(--el-border-radius-base); border-radius: var(--el-border-radius-base);
padding: 1rem; padding: 1rem;
} }
.table-wrap{
padding: 1rem 0;
.header{
float: right;
padding-bottom: 0.4rem;
}
}
.pagination-wrap{
padding-bottom: 0.2rem;
float: right;
}
}
.el-table__body-wrapper::-webkit-scrollbar { .table-wrap {
width: 5px; padding: 1rem 0;
height: 1px;
} .header {
.el-table__body-wrapper::-webkit-scrollbar-thumb { float: right;
background-color: #909399; padding-bottom: 0.4rem;
border-radius: 5px;
}
.el-table__body-wrapper::-webkit-scrollbar-track {
border-radius: 5px;
background: #ededed;
} }
}
.pagination-wrap {
padding-bottom: 0.2rem;
float: right;
}
}
.el-table__body-wrapper::-webkit-scrollbar {
width: 5px;
height: 1px;
}
.el-table__body-wrapper::-webkit-scrollbar-thumb {
background-color: #909399;
border-radius: 5px;
}
.el-table__body-wrapper::-webkit-scrollbar-track {
border-radius: 5px;
background: #ededed;
}
</style> </style>

View File

@ -1,113 +1,115 @@
<template> <template>
<div id="amisid" ref="boxRef"></div> <div id="amisid" ref="boxRef"></div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import {watch,ref} from "vue" import {watch, ref} from "vue"
import {ElMessage} from 'element-plus' import {ElMessage} from 'element-plus'
import 'amis/sdk/sdk.js' import 'amis/sdk/sdk.js'
import 'amis/lib/themes/default.css' import 'amis/lib/themes/default.css'
import 'amis/sdk/color-picker.js' import 'amis/sdk/color-picker.js'
import 'amis/sdk/rest.js' import 'amis/sdk/rest.js'
// import {InputCity} from 'amis/esm/renderers/Form/InputCity.js' import InputCity from 'amis/lib/renderers/Form/InputCity'
// import {InputColor} from 'amis/esm/renderers/Form/InputColor.js' import InputColor from 'amis/lib/renderers/Form/InputColor'
import axios from 'axios' import axios from 'axios'
import copy from 'copy-to-clipboard' import copy from 'copy-to-clipboard'
import {getToken} from '@/api/auth' import {getToken} from '@/api/auth'
const props = defineProps({ const props = defineProps({
formid: { formid: {
type: String, type: String,
default: () => { default: () => {
return '' return ''
} }
},
formjson: {
type: Object,
default: () => {
return {}
}
}
})
// @ts-ignore
const amis = amisRequire('amis/embed');
const boxRef = ref(null)
watch(() => props.formjson, (data) => {
if (Object.keys(data).length !== 0) {
onRendering(data)
}
}, {immediate: true, deep: true}
)
function onRendering(data: any) {
// let amisScoped = amis.embed('#amisid', data);
let theme = 'cxd'
let amisScoped = amis.embed(
'#amisid',
data,
{
updateLocation: (to, replace) => {
}, },
formjson: { },
type: Object, {
default: () => { //
return {} fetcher: ({
}
}
})
// @ts-ignore
const amis = amisRequire('amis/embed');
const boxRef = ref(null)
watch(()=> props.formjson, (data)=>{
onRendering(data)
},
{immediate: true,deep: true}
)
function onRendering(data:any){
// let amisScoped = amis.embed('#amisid', data);
let theme = 'cxd'
let amisScoped = amis.embed(
'#amisid',
data,
{
updateLocation: (to, replace) => {},
},
{
//
fetcher: ({
url, // url, //
method, // getpostputdelete method, // getpostputdelete
data, // data, //
responseType, responseType,
config, // config, //
headers ,// headers,//
updateLocation updateLocation
}) => { }) => {
config = config || {}; config = config || {};
config.withCredentials = true; config.withCredentials = true;
// //
config.baseURL = import.meta.env.VITE_APP_BASE_API; config.baseURL = import.meta.env.VITE_APP_BASE_API;
responseType && (config.responseType = responseType); responseType && (config.responseType = responseType);
if (config.cancelExecutor) { if (config.cancelExecutor) {
config.cancelToken = new (axios).CancelToken( config.cancelToken = new (axios).CancelToken(
config.cancelExecutor config.cancelExecutor
); );
} }
config.headers = headers || {}; config.headers = headers || {};
// token // token
const isToken = (config.headers || {}).isToken === false const isToken = (config.headers || {}).isToken === false
if (getToken() && !isToken) { if (getToken() && !isToken) {
config.headers['token'] = getToken() config.headers['token'] = getToken()
} }
if (method !== 'post' && method !== 'put' && method !== 'patch') { if (method !== 'post' && method !== 'put' && method !== 'patch') {
if (data) { if (data) {
config.params = data; config.params = data;
}
return (axios )[method](url, config);
} else if (data && data instanceof FormData) {
config.headers = config.headers || {};
config.headers['Content-Type'] = 'multipart/form-data';
} else if (data && typeof data !== 'string' && !(data instanceof Blob) && !(data instanceof ArrayBuffer)) {
data = JSON.stringify(data);
config.headers = config.headers || {};
config.headers['Content-Type'] = 'application/json';
}
return (axios )[method](url, data, config);
},
isCancel: (value) => (axios ).isCancel(value),
copy: content => {
copy(content);
ElMessage.success('内容已复制到粘贴板');
},
theme
} }
)
} return (axios)[method](url, config);
} else if (data && data instanceof FormData) {
config.headers = config.headers || {};
config.headers['Content-Type'] = 'multipart/form-data';
} else if (data && typeof data !== 'string' && !(data instanceof Blob) && !(data instanceof ArrayBuffer)) {
data = JSON.stringify(data);
config.headers = config.headers || {};
config.headers['Content-Type'] = 'application/json';
}
return (axios)[method](url, data, config);
},
isCancel: (value) => (axios).isCancel(value),
copy: content => {
copy(content);
ElMessage.success('内容已复制到粘贴板');
},
theme
}
)
}
</script> </script>
<style scoped> <style scoped>
</style> </style>

View File

@ -85,33 +85,33 @@ function onCloseAllTab() {
</script> </script>
<template> <template>
<div class="tabs-menu"> <el-tabs type="card"
<el-tabs type="card" v-model="tabsMenuValue" @tab-click="onTabMenuClick" @tab-remove="onTabMenuRemove"> v-model="tabsMenuValue"
<el-tab-pane v-for="item in tabsMenuList" addable
:key="item.path" @tab-add="onTabMenuRemove"
:path="item.path" @tab-click="onTabMenuClick"
:label="item.title" @tab-remove="onTabMenuRemove">
:name="item.path" <template #add-icon>
:closable="item.close" <el-dropdown>
@node-contextmenu="onTabMenuRemove"> <el-icon><ArrowDown /></el-icon>
<template #label> <template #dropdown>
<el-icon v-if="item.icon" style="vertical-align: middle;"> <el-dropdown-menu>
<component :is="item.icon"></component> <el-dropdown-item icon="CircleCloseFilled" @click="onCloseCurrentTab"></el-dropdown-item>
</el-icon> <el-dropdown-item icon="CircleClose" @click="onCloseOtherTab"></el-dropdown-item>
<el-dropdown :id="item.path" trigger="contextmenu"> <el-dropdown-item icon="CloseBold" @click="onCloseAllTab"></el-dropdown-item>
<span style="vertical-align: middle">{{ item.title }}</span> </el-dropdown-menu>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item icon="CircleCloseFilled" @click="onCloseCurrentTab"></el-dropdown-item>
<el-dropdown-item icon="CircleClose" @click="onCloseOtherTab"></el-dropdown-item>
<el-dropdown-item icon="CloseBold" @click="onCloseAllTab"></el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</template> </template>
</el-tab-pane> </el-dropdown>
</el-tabs> </template>
</div> <el-tab-pane v-for="item in tabsMenuList"
:key="item.path"
:path="item.path"
:label="item.title"
:name="item.path"
:closable="item.close"
@node-contextmenu="onTabMenuRemove">
</el-tab-pane>
</el-tabs>
</template> </template>
<style lang="scss"> <style lang="scss">
.tabs-menu { .tabs-menu {

View File

@ -34,7 +34,7 @@
<div class="home-container"> <div class="home-container">
<el-card shadow="never"> <el-card shadow="never">
<template #header> <template #header>
<span>公告</span> <span>简介</span>
</template> </template>
<div> <div>
<div> <div>
@ -42,10 +42,9 @@
</div> </div>
<div class="text"> <div class="text">
<el-space alignment="normal" direction="vertical"> <el-space alignment="normal" direction="vertical">
<el-text tag="p">基于 SpringBoot2 + magic-api + Vue3 + Element Plus + amis3.0 快速开发管理系统</el-text> <el-text tag="p">基于 SpringBoot2 + Vue3 + Element Plus + amis3.0 快速开发管理系统</el-text>
<el-text tag="p">Tansci-Boot 是一个前后端分离后台管理系统 前端集成 amis 低代码前端框架后端集成 magic-api 的接口快速开发框架包含基础权限安全认证以及常用的一些组件功能项目易上手技术更综合能力更全面</el-text> <el-text tag="p">SCFS-UI 是一个前后端分离后台管理系统 前端集成 amis 低代码前端框架包含基础权限安全认证以及常用的一些组件功能项目易上手技术更综合能力更全面</el-text>
<el-text tag="p">amis 是一个低代码前端框架它使用 JSON 配置来生成页面可以减少页面开发工作量极大提升效率</el-text> <el-text tag="p">amis 是一个低代码前端框架它使用 JSON 配置来生成页面可以减少页面开发工作量极大提升效率</el-text>
<el-text tag="p">magic-api 一个基于 Java 的接口快速开发框架通过 magic-api 提供的 UI 界面完成编写接口无需定义 ControllerServiceDaoMapperXMLVO Java 对象即可完成常见的 HTTP API 接口开发</el-text>
</el-space> </el-space>
</div> </div>
</div> </div>

File diff suppressed because it is too large Load Diff

View File

@ -144,7 +144,7 @@
<template> <template>
<div class="dict-container"> <div class="dict-container">
<Table :data="table.tableData" :column="table.tableTitle" :operation="table.operation" :page="false" :loading="table.loading"> <Table :data="table.tableData" :column="table.tableTitle" :operation="table.operation" :loading="table.loading">
<template #search> <template #search>
<div><el-button @click="onAdd(null)" v-permission="'dict:save'" type="primary"></el-button></div> <div><el-button @click="onAdd(null)" v-permission="'dict:save'" type="primary"></el-button></div>
</template> </template>
@ -155,7 +155,7 @@
</template> </template>
</Table> </Table>
<el-dialog title="字典信息" v-model="form.dictVisible" :show-close="false" width="40%"> <el-dialog title="字典信息" v-model="form.dictVisible" :show-close="false" width="40%">
<el-form :model="form.dictForm" ref="formRef" :rules="rules" label-width="80px" status-icon> <el-form :model="form.dictForm" ref="formRef" label-width="80px" status-icon>
<el-row :gutter="20"> <el-row :gutter="20">
<el-col :span="12"> <el-col :span="12">
<el-form-item label="分组名称" prop="groupName" :rules="[{required: true,message:'请输入分组名称',trigger: 'blur'}]"> <el-form-item label="分组名称" prop="groupName" :rules="[{required: true,message:'请输入分组名称',trigger: 'blur'}]">
@ -165,8 +165,8 @@
<el-col :span="12"> <el-col :span="12">
<el-form-item label="类型" prop="type" :rules="[{required: true,message:'请选择类型',trigger: 'blur'}]"> <el-form-item label="类型" prop="type" :rules="[{required: true,message:'请选择类型',trigger: 'blur'}]">
<el-radio-group v-model="form.dictForm.type"> <el-radio-group v-model="form.dictForm.type">
<el-radio :label="0">系统</el-radio> <el-radio :value="0">系统</el-radio>
<el-radio :label="1">业务</el-radio> <el-radio :value="1">业务</el-radio>
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
</el-col> </el-col>

View File

@ -14,8 +14,7 @@
tableTitle: [ tableTitle: [
{prop:'code',label:'组织编码',align:'left'}, {prop:'code',label:'组织编码',align:'left'},
{prop:'name',label:'组织名称'}, {prop:'name',label:'组织名称'},
{prop:'name',label:'组织名称'}, {prop:'sort',label:'组织级别'},
{prop:'sort',label:'排序'},
{prop:'createTime',label:'创建时间'}, {prop:'createTime',label:'创建时间'},
{prop:'remarks',label:'描述'} {prop:'remarks',label:'描述'}
], ],
@ -126,8 +125,8 @@
</script> </script>
<template> <template>
<div class="org-container"> <div>
<Table :data="table.tableData" :column="table.tableTitle" :operation="table.operation" :page="false" :loading="table.loading"> <Table :data="table.tableData" :column="table.tableTitle" :operation="table.operation" :loading="table.loading">
<template #search> <template #search>
<div><el-button @click="onAdd(null)" v-permission="'org:save'" type="primary"></el-button></div> <div><el-button @click="onAdd(null)" v-permission="'org:save'" type="primary"></el-button></div>
</template> </template>
@ -138,7 +137,7 @@
</template> </template>
</Table> </Table>
<el-dialog title="组织信息" v-model="form.orgVisible" :show-close="false" width="40%"> <el-dialog title="组织信息" v-model="form.orgVisible" :show-close="false" width="40%">
<el-form :model="form.orgForm" ref="formRef" :rules="rules" label-width="80px" status-icon> <el-form :model="form.orgForm" ref="formRef" label-width="80px" status-icon>
<el-form-item label="名称" prop="name" :rules="[{required: true,message:'请输入名称',trigger: 'blur'}]"> <el-form-item label="名称" prop="name" :rules="[{required: true,message:'请输入名称',trigger: 'blur'}]">
<el-input v-model="form.orgForm.name" placeholder="请输入名称" style="width: 100%"/> <el-input v-model="form.orgForm.name" placeholder="请输入名称" style="width: 100%"/>
</el-form-item> </el-form-item>
@ -158,8 +157,3 @@
</el-dialog> </el-dialog>
</div> </div>
</template> </template>
<style lang="scss" scoped>
.org-container{
}
</style>

View File

@ -1,5 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import {onMounted, reactive, ref, unref} from 'vue' import {onMounted, reactive, ref} from 'vue'
import {ElMessage, ElMessageBox} from 'element-plus' import {ElMessage, ElMessageBox} from 'element-plus'
import type {FormInstance} from 'element-plus' import type {FormInstance} from 'element-plus'
import Table from '@/components/Table.vue' import Table from '@/components/Table.vue'
@ -8,7 +8,6 @@
const searchForm = reactive({ const searchForm = reactive({
username: null username: null
}) })
const table = reactive({ const table = reactive({
loading: false, loading: false,
page: { page: {
@ -158,6 +157,8 @@
form.userForm = { form.userForm = {
id: val.column.row.id, id: val.column.row.id,
username: val.column.row.username, username: val.column.row.username,
password: '',
rePassword: '',
nickname: val.column.row.nickname, nickname: val.column.row.nickname,
type: val.column.row.type, type: val.column.row.type,
phone: val.column.row.phone, phone: val.column.row.phone,
@ -232,7 +233,7 @@
</template> </template>
</Table> </Table>
<el-dialog title="用户信息" v-model="form.userVisible" :show-close="false" width="50%"> <el-dialog title="用户信息" v-model="form.userVisible" :show-close="false" width="50%">
<el-form :model="form.userForm" ref="formRef" :rules="rules" label-width="80px" status-icon> <el-form :model="form.userForm" ref="formRef" label-width="80px" status-icon>
<el-row :gutter="20"> <el-row :gutter="20">
<el-col :span="12"> <el-col :span="12">
<el-form-item label="名称" prop="username" :rules="[ <el-form-item label="名称" prop="username" :rules="[
@ -264,16 +265,16 @@
<el-col :span="12"> <el-col :span="12">
<el-form-item label="类型" prop="type" :rules="[{required: true,message:'请选择类型',trigger: 'blur'}]"> <el-form-item label="类型" prop="type" :rules="[{required: true,message:'请选择类型',trigger: 'blur'}]">
<el-radio-group v-model="form.userForm.type"> <el-radio-group v-model="form.userForm.type">
<el-radio :label="1">管理员</el-radio> <el-radio :value="1">管理员</el-radio>
<el-radio :label="2">普通用户</el-radio> <el-radio :value="2">普通用户</el-radio>
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="性别" prop="gender"> <el-form-item label="性别" prop="gender">
<el-radio-group v-model="form.userForm.gender"> <el-radio-group v-model="form.userForm.gender">
<el-radio :label="0"></el-radio> <el-radio :value="0"></el-radio>
<el-radio :label="1"></el-radio> <el-radio :value="1"></el-radio>
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
</el-col> </el-col>
@ -306,7 +307,7 @@
<el-col :span="12"> <el-col :span="12">
<el-form-item label="角色" prop="roleId" :rules="[{required: true,message:'请选择角色',trigger: 'change'}]"> <el-form-item label="角色" prop="roleId" :rules="[{required: true,message:'请选择角色',trigger: 'change'}]">
<el-select v-model="form.userForm.roleId" placeholder="请选角色" style="width: 100%"> <el-select v-model="form.userForm.roleId" placeholder="请选角色" style="width: 100%">
<el-option v-for="item in form.roleList" :key="item.id" :label="item.name" :value="item.id" /> <el-option v-for="item in form.roleList" :key="item['id']" :label="item['name']" :value="item['id']" />
</el-select> </el-select>
</el-form-item> </el-form-item>
</el-col> </el-col>