Signed-off-by: 1iyc <5212514+liycone@user.noreply.gitee.com>
main
1iyc 3 weeks ago
parent 6cf1c43eb0
commit 79ae0c2d44

@ -65,8 +65,8 @@ export default {
handleQuery() { handleQuery() {
this.$refs.queryForm.validate(valid => { this.$refs.queryForm.validate(valid => {
if (valid) { if (valid) {
// //
console.log('查询参数:', this.queryParams); this.$emit('query', this.queryParams);
} else { } else {
console.log('验证失败'); console.log('验证失败');
} }
@ -74,6 +74,8 @@ export default {
}, },
resetQuery() { resetQuery() {
this.$refs.queryForm.resetFields(); this.$refs.queryForm.resetFields();
//
this.$emit('reset', this.queryParams);
} }
} }
}; };

@ -4,10 +4,10 @@
<el-col :span="3"> <el-col :span="3">
<el-card style="height: calc(100vh - 125px)"> <el-card style="height: calc(100vh - 125px)">
<div slot="header"> <div slot="header">
<span><el-button type="text" size="small" @click="showDialog('add')"></el-button></span> <span><el-button type="text" size="small">新建标签页</el-button></span>
</div> </div>
<el-menu <el-menu
:default-active="active" :default-active="localIndex"
@select="onSelect" @select="onSelect"
mode="horizontal" mode="horizontal"
> >
@ -21,10 +21,10 @@
</el-card> </el-card>
</el-col> </el-col>
<!-- -->
<el-col :span="20"> <el-col :span="20">
<el-card style="height: calc(100vh - 125px)"> <el-card style="height: calc(100vh - 125px)">
<el-tabs v-model="active"
<el-tabs v-model="localIndex"
type="card" type="card"
closable closable
@tab-remove="removeTab" @tab-remove="removeTab"
@ -36,360 +36,148 @@
:name="index.toString()" :name="index.toString()"
:label="tab.title" :label="tab.title"
> >
<!-- 查询条件 -->
<!-- form表单 --> <Search
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="form.length > 0"> :search-fields="searchFields"
<el-form-item v-for="(field, index) in form" :query-params="queryParams"
:key="index" @query="handleQuery"
:label="field.label" @reset="handleReset"
:prop="field.prop" />
v-if="field.type !== 'button'"> <!-- 表格 -->
<component <div class="table-container">
:is="getComponentType(field.type)" <Table
v-bind="field" :columns="columnsFields"
v-model="queryParams[field.prop]" :rows="rows"
:placeholder="field.placeholder" :pagination="true"
> :total="total"
<!-- 下拉框选项 --> :currentPage="currentPage"
<el-option :pageSize="pageSize"
v-if="field.type === 'select'" :loading="loading"
v-for="option in field.options" @sort-change="handleSortChange"
:key="option.value" @page-change="handlePageChange"
:label="option.label"
:value="option.value"
></el-option>
</component>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery"></el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery"></el-button>
</el-form-item>
</el-form>
<!-- 表格 -->
<el-table
:data="tableData"
highlight-current-row
style="width: 100%"
v-loading="loading"
>
<el-table-column label="序号" type="index" width="80" align="center">
<template slot-scope="scope">
<span>{{ (queryParams.pageNum - 1) * queryParams.pageSize + scope.$index + 1 }}</span>
</template>
</el-table-column>
<el-table-column
v-for="(column, index) in columns"
:prop="column.key"
:label="column.title"
:width="column.width"
:align="column.align"
:show-overflow-tooltip="column.tooltip"
/> />
</div>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button
size="mini"
type="text"
icon="el-icon-edit"
@click="handleUpdate(scope.row)"
v-hasPermi="['system:dept:edit']"
>修改
</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-edit"
@click="handleUpdate(scope.row)"
v-hasPermi="['system:dept:edit']"
>同步
</el-button>
</template>
</el-table-column>
</el-table>
</el-tab-pane> </el-tab-pane>
</el-tabs> </el-tabs>
<pagination
v-show="true"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
:page-sizes="[2,5,10]"
@pagination="getList"
/>
</el-card> </el-card>
</el-col> </el-col>
</el-row> </el-row>
<el-dialog
:visible.sync="dialogVisible"
:title="dialogTitle"
:before-close="handleClose"
>
<el-form ref="form" :model="currentTabData" label-width="100px">
<el-form-item label="标题" prop="title" :rules="{ required: true, message: '标题不能为空', trigger: 'blur' }">
<el-input v-model="currentTabData.title" placeholder="请输入标题"></el-input>
</el-form-item>
<el-form-item label="名称" prop="name" :rules="{ required: true, message: '名称不能为空', trigger: 'blur' }">
<el-input v-model="currentTabData.name" placeholder="请输入名称"></el-input>
</el-form-item>
<el-form-item label="数据库类型" prop="dbType"
:rules="{ required: true, message: '数据库类型不能为空', trigger: 'blur' }">
<el-input v-model="currentTabData.dbType" placeholder="请输入数据库类型"></el-input>
</el-form-item>
<el-form-item label="URL" prop="url" :rules="{ required: true, message: 'URL不能为空', trigger: 'blur' }">
<el-input v-model="currentTabData.url" placeholder="请输入URL"></el-input>
</el-form-item>
<el-form-item label="用户名" prop="username"
:rules="{ required: true, message: '用户名不能为空', trigger: 'blur' }">
<el-input v-model="currentTabData.username" placeholder="请输入用户名"></el-input>
</el-form-item>
<el-form-item label="密码" prop="password"
:rules="{ required: true, message: '密码不能为空', trigger: 'blur' }">
<el-input v-model="currentTabData.password" placeholder="请输入密码" type="password"></el-input>
</el-form-item>
<el-form-item label="驱动类名" prop="driverClassName"
:rules="{ required: true, message: '驱动类名不能为空', trigger: 'blur' }">
<el-input v-model="currentTabData.driverClassName" placeholder="请输入驱动类名"></el-input>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="cancel"> </el-button>
<el-button type="primary" @click="submit"> </el-button>
</div>
</el-dialog>
</div> </div>
</template> </template>
<script> <script>
export default { export default {
props: { props: {
name: 'TabComponent', name: 'TabComponent',
initMenuItem: { index: {
type: String,
default: '1'
},
tabs: {
type: Array, type: Array,
default: () => [{ default: () => [{
title: '数据库', title: '数据库',
}] }]
}, },
callBackSelect: { searchFields: {
type: Function,
default: () => ({})
},
initForm: {
type: Array, type: Array,
default: () => [{ default: () => []
type: 'input', },
label: '表名', queryParams: {
prop: 'tableName', type: Object,
placeholder: '请输入表名', default: () => ({})
}]
}, },
initColumns: { columnsFields: {
type: Array, type: Array,
default: () => [{ default: () => []
type: 'id',
width: 55,
align: 'center'
}]
}, },
initTableData: { rows: {
type: Array, type: Array,
default: () => [] default: () => []
}, },
initActive: { currentPage: {
type: String, type: Number,
default: '0' default: 1
},
pageSize: {
type: Number,
default: 20
},
total: {
type: Number,
default: 0
},
loading: {
type: Boolean,
default: false
} }
} },
,
data() { data() {
return { return {
active: this.initActive, localIndex: this.index,
tabs: this.initMenuItem,
form: this.initForm,
columns: this.initColumns,
tableData: this.initTableData,
loading: false,
dialogVisible: false,
dialogTitle: '',
currentTabData: {
title: '',
name: '',
dbType: '',
url: '',
username: '',
password: '',
driverClassName: ''
},
currentTabIndex: null,
total: 0,
queryParams: {
pageNum: 1,
pageSize: 10,
activeTab: {},
},
} }
} },
, watch: {
mounted() { index(newVal) {
// console.log(JSON.stringify(this.initMenuItem)) this.localIndex = newVal;
// console.log(JSON.stringify(this.columns))
this.setDefaultValue()
this.onSelect(this.active)
}
,
methods: {
getComponentType(type) {
switch (type) {
case 'input':
return 'el-input';
case 'textarea':
return 'el-input';
case 'select':
return 'el-select';
case 'checkbox':
return 'el-checkbox';
case 'radio':
return 'el-radio';
case 'date':
return 'el-date-picker';
case 'button':
return 'el-button';
default:
return 'el-input';
}
},
/* 设置默认值*/
setDefaultValue() {
this.form.forEach(field => {
if (field.type === 'select' && field.options) {
const defaultOption = field.options.find(option => option.default);
if (defaultOption) {
this.queryParams[field.prop] = defaultOption.value;
}
}
});
}, },
/* 选中菜单 */ localIndex(newVal) {
this.$emit('update:index', newVal);
}
},
methods: {
onSelect(index) { onSelect(index) {
this.queryParams.activeTab = this.tabs[index] this.localIndex = index;
this.callBackSelect(this.queryParams) this.queryParams.name = this.tabs[index].name;
this.handleQuery();
}, },
/* tabs 单击事件 */
onClick(tab) { onClick(tab) {
this.queryParams.activeTab = this.tabs[tab.name] this.localIndex = tab.name;
this.callBackSelect(this.queryParams) this.queryParams.name = this.tabs[tab.name].name;
this.handleQuery();
}, },
handleQuery(queryParams) {
/* 加载表格数据*/ if (queryParams) {
loadTableData(tableData, total) { this.queryParams = queryParams;
this.tableData = tableData; }
this.total = total; this.$emit('query', this.queryParams);
}, },
handleReset() {
getList() { this.$emit('reset', this.queryParams);
this.callBackSelect(this.queryParams)
}, },
handleUpdate(row) {
alert(row.id);
handleQuery() {
this.getList();
}, },
resetQuery() { handleSortChange() {
this.resetForm("queryForm");
this.handleQuery();
}, },
handlePageChange() {
},
showDialog(mode, index = null) { removeTab(targetName) {
this.dialogTitle = mode === 'add' ? '新建标签页' : '修改标签页'; const tabs = this.tabs;
this.currentTabIndex = index; let activeName = this.localIndex;
if (mode === 'edit') {
this.currentTabData = {...this.tabs[index]}; if (activeName === targetName) {
} else { tabs.forEach((tab, index) => {
this.currentTabData = { if (tab.name === targetName) {
title: '', const nextTab = tabs[index + 1] || tabs[index - 1];
name: '', if (nextTab) {
dbType: '', activeName = nextTab.name;
url: '', }
username: '',
password: '',
driverClassName: ''
};
}
this.dialogVisible = true;
}
,
submit() {
/*this.$refs.form.validate((valid) => {
if (valid) {
if (this.currentTabIndex !== null) {
this.tabs[this.currentTabIndex] = {...this.currentTabData};
this.activeTab = this.currentTabIndex.toString();
} else {
this.tabs.push({...this.currentTabData});
this.activeTab = (this.tabs.length - 1).toString();
this.requestFun(this.currentTabData);
} }
this.dialogVisible = false; });
} else {
const errors = this.$refs.form.fields.filter(field => field.validateState === 'error').map(field => field.validateMessage);
this.$message.error(errors.join(''));
return false;
}
});*/
}
,
cancel() {
this.dialogVisible = false;
this.$refs.form.resetFields();
}
,
removeTab(index) {
this.tabs.splice(index, 1);
if (this.activeTab === index.toString()) {
this.activeTab = Math.max(0, index - 1).toString();
}
}
,
handleClose(done, event) {
if (typeof done === 'function') {
this.$confirm('确认关闭?')
.then(_ => {
this.dialogVisible = false;
done();
})
.catch(_ => {
});
} else {
this.dialogVisible = false;
} }
}
,
handleUpdate(row) {
alert(row.id)
}
this.localIndex = activeName;
this.$emit('update:index', activeName);
this.$emit('remove', targetName);
},
} }
} }
</script> </script>
<style scoped>
.table-container {
height: calc(100vh - 250px); /* 调整高度以适应页面布局 */
overflow-y: auto; /* 添加垂直滚动条 */
}
</style>

@ -0,0 +1,90 @@
<template>
<div>
<el-table
:data="rows"
border
stripe
style="width: 100%"
v-loading="loading"
@sort-change="handleSortChange"
>
<el-table-column
v-for="column in columns"
:key="column.prop"
:prop="column.prop"
:label="column.label"
:width="column.width"
:sortable="column.sortable"
:show-overflow-tooltip="true"
>
<template slot-scope="scope">
<span v-if="column.formatter">{{ column.formatter(scope.row[column.prop]) }}</span>
<span v-else>{{ scope.row[column.prop] }}</span>
</template>
</el-table-column>
</el-table>
<el-pagination
v-if="pagination"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="currentPage"
:page-sizes="[10, 20, 50, 100]"
:page-size="pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
style="margin-top: 20px"
/>
</div>
</template>
<script>
export default {
props: {
columns: {
type: Array,
required: true
},
rows: {
type: Array,
required: true
},
pagination: {
type: Boolean,
default: true
},
currentPage: {
type: Number,
default: 1
},
pageSize: {
type: Number,
default: 10
},
total: {
type: Number,
default: 0
},
loading: {
type: Boolean,
default: false
}
},
methods: {
handleSortChange({prop, order}) {
this.$emit('sort-change', {prop, order});
},
handleSizeChange(newSize) {
this.$emit('update:page-size', newSize);
this.$emit('page-change', {page: this.currentPage, size: newSize});
},
handleCurrentChange(newPage) {
this.$emit('update:current-page', newPage);
this.$emit('page-change', {page: newPage, size: this.pageSize});
}
}
};
</script>
<style scoped>
/* 添加一些样式 */
</style>

@ -42,6 +42,7 @@ import webSite from "@/config/website";
import TabComponent from '@/components/TabComponent' import TabComponent from '@/components/TabComponent'
import Forms from '@/components/Forms' import Forms from '@/components/Forms'
import Search from '@/components/Search' import Search from '@/components/Search'
import Table from '@/components/Table'
// 全局方法挂载 // 全局方法挂载
Vue.prototype.website = webSite; Vue.prototype.website = webSite;
@ -66,6 +67,7 @@ Vue.component('ImagePreview', ImagePreview)
Vue.component('TabComponent', TabComponent) Vue.component('TabComponent', TabComponent)
Vue.component('Forms', Forms) Vue.component('Forms', Forms)
Vue.component('Search', Search) Vue.component('Search', Search)
Vue.component('Table', Table)
Vue.use(directive) Vue.use(directive)
Vue.use(plugins) Vue.use(plugins)

@ -1,17 +1,22 @@
<template> <template>
<div id="app"> <div id="app">
<TabComponent <TabComponent
v-if="tabs.length > 0" v-if="tabs.length > 0"
ref="tabComponent" ref="tabComponent"
:init-menu-item.sync="tabs" :active="active.index.toString()"
:init-form="table.form" :tabs="tabs"
:init-columns="table.column" :search-fields="searchFields"
:call-back-select="backSelect" :query-params="queryParams"
:init-active="'1'" :columns-fields="columnFields"
> :rows="rows"
</TabComponent> :current-page="queryParams.pageNum"
:page-size="queryParams.pageSize"
:total="queryParams.total"
:loading="loading"
@query="handleQuery"
@reset="handleReset"
@toggle="getRows"
/>
</div> </div>
</template> </template>
@ -22,101 +27,65 @@ export default {
name: 'App', name: 'App',
data() { data() {
return { return {
addTabDialogVisible: false, active: {
table: { index: 0, // 0 tabs
form: [
{
type: 'input',
label: '表名',
prop: 'tableName',
placeholder: '请输入表名',
},
{
type: 'input',
label: '表描述',
prop: 'tableDescription',
placeholder: '请输入表描述',
span: 6
},
{
type: 'input',
label: '表注',
prop: 'tableNote',
placeholder: '请输入表注',
},
{
type: 'select',
label: '是否启用',
prop: 'enable',
placeholder: '请选择是否启用',
options: [
{
label: '是',
value: '1',
default: true
},
{
label: '否',
value: '0'
}
]
},
],
column: [
{
type: 'id',
width: 55,
align: 'center'
},
{
title: '表名称',
key: 'tableName',
align: 'center'
},
{
title: '描述',
key: 'tableDescription',
align: 'center'
},
{
title: '表注',
key: 'tableNote',
align: 'center'
},
{
title: '启用',
key: 'enable',
align: 'center',
},
{
title: 'cron (定时)',
key: 'cron',
align: 'center'
}
],
rows: [],
},
initActiveTab: "0",
tabs: [],
activeTab: {
title: undefined,
name: undefined,
dbType: undefined,
url: undefined,
username: undefined,
driverClassName: undefined,
}, },
rows: [],
addTabDialogVisible: false,
searchFields: [
{
type: 'input',
label: '表名称',
prop: 'tableName',
placeholder: '请输入表名称',
gutter: 2,
},
{
type: 'input',
label: '表描述',
prop: 'tableDescription',
placeholder: '请输入表描述',
gutter: 2,
},
{
type: 'input',
label: '表注',
prop: 'tableNote',
placeholder: '请输入表注',
gutter: 2,
},
{
type: 'select',
label: '启用',
prop: 'enable',
placeholder: '请选择',
gutter: 2,
options: [
{label: '是', value: '1'},
{label: '否', value: '0'},
],
},
],
queryParams: { queryParams: {
pageNum: 1, pageNum: 1,
pageSize: 10, pageSize: 10,
total: 0,
name: undefined, name: undefined,
tableName: undefined, tableName: undefined,
enable: undefined, enable: undefined,
tableDescription: undefined, tableDescription: undefined,
tableNote: undefined, tableNote: undefined,
cron: undefined, cron: undefined,
} },
columnFields: [
{label: 'ID', prop: 'id', width: '100', sortable: true},
{label: '表名称', prop: 'tableName', sortable: true},
{label: '表注', prop: 'tableDescription', sortable: true},
{label: '启用', prop: 'enable', formatter: (value) => (value ? '启用' : '禁用'), sortable: true},
{label: '定时', prop: 'cron'},
],
tabs: [],
loading: false, // loading
}; };
}, },
@ -126,45 +95,60 @@ export default {
methods: { methods: {
getNav() { getNav() {
getNav().then(response => { getNav()
this.tabs = response.data.map(item => ({ .then(response => {
title: item.alias, this.tabs = response.data.map(item => ({
name: item.name, title: item.alias,
dbType: item.dbType, name: item.name,
url: item.url, dbType: item.dbType,
username: item.username, url: item.url,
driverClassName: item.driverClassName username: item.username,
})); driverClassName: item.driverClassName
if (this.tabs.length > 0) { }));
this.activeTab = this.tabs[0]; if (this.tabs.length > 0) {
this.queryParams.name = this.activeTab.name this.active.index = 0; //
this.getDataList(); this.queryParams.name = this.tabs[this.active.index].name;
} this.getRows();
}).catch(error => { }
console.error('Failed to fetch navigation data:', error); })
}); .catch(error => {
console.error('Failed to fetch navigation data:', error);
});
}, },
//
backSelect(callBackActiveTab) { handleQuery() {
console.log(JSON.stringify(callBackActiveTab)); this.getRows();
this.activeTab = callBackActiveTab.activeTab
this.queryParams.pageNum = callBackActiveTab.pageNum
this.queryParams.pageSize = callBackActiveTab.pageSize
this.queryParams.enable = callBackActiveTab.enable
this.queryParams.name = this.activeTab.name
this.getDataList();
}, },
//
getDataList() { handleReset() {
console.log('getDataList', JSON.stringify(this.queryParams)); this.queryParams = {
pageNum: 1,
pageSize: 10,
total: 0,
name: undefined,
tableName: undefined,
enable: undefined,
tableDescription: undefined,
tableNote: undefined,
cron: undefined,
};
this.getRows();
},
//
getRows() {
this.loading = true; // loading true
getTasks(this.queryParams) getTasks(this.queryParams)
.then(response => { .then(response => {
this.$refs.tabComponent.loadTableData(response.rows, response.total); this.rows = response.rows;
this.queryParams.total = response.total; //
}) })
.catch(error => { .catch(error => {
console.error('Failed to fetch data list:', error); console.error('Failed to fetch data list:', error);
})
.finally(() => {
this.loading = false; // loading false
}); });
} },
} }
}; };
</script> </script>

Loading…
Cancel
Save