Signed-off-by: 1iyc <5212514+liycone@user.noreply.gitee.com>
main
1iyc 3 weeks ago
parent 8092217e8a
commit 0b866ed102

@ -48,6 +48,7 @@
"js-beautify": "1.13.0", "js-beautify": "1.13.0",
"js-cookie": "3.0.1", "js-cookie": "3.0.1",
"jsencrypt": "3.0.0-rc.1", "jsencrypt": "3.0.0-rc.1",
"micromatch": "^4.0.8",
"nprogress": "0.2.0", "nprogress": "0.2.0",
"quill": "2.0.2", "quill": "2.0.2",
"screenfull": "5.0.2", "screenfull": "5.0.2",

@ -0,0 +1,27 @@
import request from "@/utils/request";
export function getNav(query) {
return request({
url: '/gather/nav',
method: 'get',
params: query
})
}
export function getTasks(queryParams) {
return request({
url: '/gather/task/page/',
method: 'GET',
params: queryParams,
});
}
export function getDataList(dataSource, queryParams) {
return request({
url: '/kis/supplier/list/' + dataSource,
method: 'GET',
params: queryParams,
});
}

@ -1,81 +1,90 @@
<template> <template>
<div class="container"> <div class="app-container">
<el-row :gutter="10"> <el-row :gutter="10">
<el-col :span="3"> <el-col :span="3">
<el-card class="full-height"> <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" @click="showDialog('add')"></el-button></span>
</div> </div>
<el-menu <el-menu
:default-active="activeTab" :default-active="active"
@select="handleSelect" @select="onSelect"
default-active="2" mode="horizontal"
style="overflow:auto"
> >
<el-menu-item v-for="(tab, index) in tabs" :key="index" :index="index.toString()"> <el-menu-item v-for="(tab, index) in tabs"
<span>{{ tab.title }}</span> :key="index"
:index="index.toString()"
>
<span>{{ tab.title }}{{ index }}</span>
</el-menu-item> </el-menu-item>
</el-menu> </el-menu>
</el-card> </el-card>
</el-col> </el-col>
<!-- -->
<el-col :span="20"> <el-col :span="20">
<el-card class="full-height"> <el-card style="height: calc(100vh - 125px)">
<el-tabs v-model="activeTab" type="card" closable @tab-remove="removeTab" size="small"> <el-tabs v-model="active"
<el-tab-pane v-for="(tab, index) in tabs" :key="index" :label="tab.title" :name="index.toString()"> type="card"
closable
@tab-remove="removeTab"
size="small"
@tab-click="onClick"
>
<el-tab-pane v-for="(tab, index) in tabs"
:key="index"
:label="tab.title"
:name="index.toString()"
>
<el-button type="text" @click.stop="showDialog('edit', index)">修改</el-button> <el-button type="text" @click.stop="showDialog('edit', index)">修改</el-button>
<el-button type="text" @click.stop="disconnectTab(index)">断开</el-button> <el-button type="text" @click.stop="disconnectTab(index)">断开</el-button>
<el-button type="text" @click.stop="disconnectTab(index)">打开</el-button> <el-button type="text" @click.stop="disconnectTab(index)">打开</el-button>
<el-table v-loading="false"
:data="tableList" <el-table
highlight-current-row :data="tableData"
style="width: 100%" highlight-current-row
style="width: 100%"
v-loading="loading"
> >
<el-table-column type="selection" align="center" width="55"></el-table-column>
<el-table-column label="序号" type="index" width="50" align="center"> <el-table-column label="序号" type="index" width="80" align="center">
<template slot-scope="scope"> <template slot-scope="scope">
<span>{{ (queryParams.pageNum - 1) * queryParams.pageSize + scope.$index + 1 }}</span> <span>{{ (queryParams.pageNum - 1) * queryParams.pageSize + scope.$index + 1 }}</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column
label="表名称" v-for="(column, index) in columns"
align="center" :prop="column.key"
prop="ffullName" :label="column.title"
:show-overflow-tooltip="true" :width="column.width"
width="120" :align="column.align"
/> :show-overflow-tooltip="column.tooltip"
<el-table-column >
label="表名称"
align="center"
prop="fname"
:show-overflow-tooltip="true"
width="120"
/>
<el-table-column
label="表描述"
align="center"
prop="fhelpCode"
:show-overflow-tooltip="true"
width="120"
/>
</el-table>
<pagination
v-show="true"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
</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 <el-dialog
:visible.sync="dialogVisible" :visible.sync="dialogVisible"
:title="dialogTitle" :title="dialogTitle"
@ -118,36 +127,41 @@
<script> <script>
import request from "@/utils/request";
export default { export default {
props: { props: {
name: 'TabComponent', name: 'TabComponent',
initialTabs: { initMenuItem: {
type: Array, type: Array,
default: () => [] default: () => []
}, },
reqFun: { callBackSelect: {
type: Function, type: Function,
default: () => ({}) default: () => ({})
},
initColumns: {
type: Array,
default: () => []
},
initTableData: {
type: Array,
default: () => []
},
initActive: {
type: String,
default: '0'
} }
}, }
,
data() { data() {
return { return {
activeTab: '0', active: this.initActive,
tabs: this.initialTabs.map(tab => ({ tabs: this.initMenuItem,
title: tab.title || '', columns: this.initColumns,
name: tab.name || '', tableData: this.initTableData,
dbType: tab.dbType || '', loading: false,
url: tab.url || '',
username: tab.username || '',
password: tab.password || '',
driverClassName: tab.driverClassName || ''
})),
requestFun: this.reqFun,
dialogVisible: false, dialogVisible: false,
dialogTitle: '', dialogTitle: '',
activeTabData: {},
currentTabData: { currentTabData: {
title: '', title: '',
name: '', name: '',
@ -158,15 +172,47 @@ export default {
driverClassName: '' driverClassName: ''
}, },
currentTabIndex: null, currentTabIndex: null,
tableList: [],
total: 0, total: 0,
queryParams: { queryParams: {
pageNum: 1, pageNum: 1,
pageSize: 10 pageSize: 10
}, },
} }
}, }
,
mounted() {
// console.log(JSON.stringify(this.initMenuItem))
// console.log(JSON.stringify(this.columns))
}
,
methods: { methods: {
/* 选中菜单 */
onSelect(index) {
this.active = index
this.loading = true
this.callBackSelect(this.active, this.queryParams)
this.loading = false
},
/* tabs 单击实践 */
onClick(tab) {
this.active = tab.name;
this.loading = true
this.callBackSelect(this.active, this.queryParams)
this.loading = false
},
/* 加载表格数据*/
loadTableData(tableData, total) {
this.tableData = tableData;
this.total = total;
},
getList() {
this.callBackSelect(this.active, this.queryParams)
},
showDialog(mode, index = null) { showDialog(mode, index = null) {
this.dialogTitle = mode === 'add' ? '新建标签页' : '修改标签页'; this.dialogTitle = mode === 'add' ? '新建标签页' : '修改标签页';
this.currentTabIndex = index; this.currentTabIndex = index;
@ -174,19 +220,20 @@ export default {
this.currentTabData = {...this.tabs[index]}; this.currentTabData = {...this.tabs[index]};
} else { } else {
this.currentTabData = { this.currentTabData = {
title: '1', title: '',
name: '1', name: '',
dbType: '1', dbType: '',
url: '1', url: '',
username: '1', username: '',
password: '1', password: '',
driverClassName: '1' driverClassName: ''
}; };
} }
this.dialogVisible = true; this.dialogVisible = true;
}, }
,
submit() { submit() {
this.$refs.form.validate((valid) => { /*this.$refs.form.validate((valid) => {
if (valid) { if (valid) {
if (this.currentTabIndex !== null) { if (this.currentTabIndex !== null) {
this.tabs[this.currentTabIndex] = {...this.currentTabData}; this.tabs[this.currentTabIndex] = {...this.currentTabData};
@ -202,24 +249,28 @@ export default {
this.$message.error(errors.join('')); this.$message.error(errors.join(''));
return false; return false;
} }
}); });*/
}, }
,
cancel() { cancel() {
this.dialogVisible = false; this.dialogVisible = false;
this.$refs.form.resetFields(); this.$refs.form.resetFields();
}, }
,
removeTab(index) { removeTab(index) {
this.tabs.splice(index, 1); this.tabs.splice(index, 1);
if (this.activeTab === index.toString()) { if (this.activeTab === index.toString()) {
this.activeTab = Math.max(0, index - 1).toString(); this.activeTab = Math.max(0, index - 1).toString();
} }
}, }
handleSelect(index) {
this.activeTab = index; ,
},
disconnectTab(index) { disconnectTab(index) {
console.log(`断开标签页 ${index}`); console.log(`断开标签页 ${index}`);
}, }
,
handleClose(done, event) { handleClose(done, event) {
if (typeof done === 'function') { if (typeof done === 'function') {
this.$confirm('确认关闭?') this.$confirm('确认关闭?')
@ -232,41 +283,10 @@ export default {
} else { } else {
this.dialogVisible = false; this.dialogVisible = false;
} }
},
getActiveTab() {
const currentTabIndex = parseInt(this.activeTab);
this.activeTabData = this.tabs[currentTabIndex];
},
getList() {
request({
url: '/kis/supplier/list/' + this.activeTabData.name,
method: 'GET',
params: this.queryParams,
}).then(response => {
this.tableList = response.rows;
this.total = response.total;
})
} }
}, ,
created() {
this.getActiveTab();
},
mounted() {
this.getList();
}
};
</script>
<style scoped>
.container { }
padding: 20px;
}
.full-height {
height: calc(100vh - 125px);
display: flex;
flex-direction: column;
} }
</style> </script>

@ -0,0 +1,22 @@
import micromatch from "micromatch";
/**
* 全局配置文件
*/
export default {
// 白名单
whitelist(url) {
const excludeUrl = [
"/login",
"/getInfo",
"/getRouters",
"/getUploadLogoUrl",
"/register",
"/*/page",
"/*/list",
"/release/download/*",
];
const result = micromatch(url, excludeUrl, {}).length > 0;
return result;
},
};

@ -12,13 +12,13 @@ import store from './store'
import router from './router' import router from './router'
import directive from './directive' // directive import directive from './directive' // directive
import plugins from './plugins' // plugins import plugins from './plugins' // plugins
import { download } from '@/utils/request' import {download} from '@/utils/request'
import './assets/icons' // icon import './assets/icons' // icon
import './permission' // permission control import './permission' // permission control
import { getDicts } from "@/api/system/dict/data"; import {getDicts} from "@/api/system/dict/data";
import { getConfigKey } from "@/api/system/config"; import {getConfigKey} from "@/api/system/config";
import { parseTime, resetForm, addDateRange, selectDictLabel, selectDictLabels, handleTree } from "@/utils/ruoyi"; import {addDateRange, handleTree, parseTime, resetForm, selectDictLabel, selectDictLabels} from "@/utils/ruoyi";
// 分页组件 // 分页组件
import Pagination from "@/components/Pagination"; import Pagination from "@/components/Pagination";
// 自定义表格工具组件 // 自定义表格工具组件
@ -39,8 +39,11 @@ import VueMeta from 'vue-meta'
import DictData from '@/components/DictData' import DictData from '@/components/DictData'
// tab组件 // tab组件
import TabComponent from '@/components/TabComponent' import TabComponent from '@/components/TabComponent'
//
import webSite from "@/config/website";
// 全局方法挂载 // 全局方法挂载
Vue.prototype.website = webSite;
Vue.prototype.getDicts = getDicts Vue.prototype.getDicts = getDicts
Vue.prototype.getConfigKey = getConfigKey Vue.prototype.getConfigKey = getConfigKey
Vue.prototype.parseTime = parseTime Vue.prototype.parseTime = parseTime

@ -1,15 +1,18 @@
import axios from 'axios' import axios from 'axios'
import { Notification, MessageBox, Message, Loading } from 'element-ui' import {Loading, Message, MessageBox, Notification} from 'element-ui'
import store from '@/store' import store from '@/store'
import { getToken } from '@/utils/auth' import {getToken} from '@/utils/auth'
import errorCode from '@/utils/errorCode' import errorCode from '@/utils/errorCode'
import { tansParams, blobValidate } from "@/utils/ruoyi"; import {blobValidate, tansParams} from "@/utils/ruoyi";
import cache from '@/plugins/cache' import cache from '@/plugins/cache'
import { saveAs } from 'file-saver' import {saveAs} from 'file-saver'
import Website from "@/config/website";
let downloadLoadingInstance; let downloadLoadingInstance;
let globalLoadingInstance;
// 是否显示重新登录 // 是否显示重新登录
export let isRelogin = { show: false }; export let isRelogin = {show: false};
axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8' axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8'
// 创建axios实例 // 创建axios实例
@ -22,6 +25,15 @@ const service = axios.create({
// request拦截器 // request拦截器
service.interceptors.request.use(config => { service.interceptors.request.use(config => {
const whitelist = Website.whitelist(config.url);
// 开启全局加载指示器
if (!whitelist && config.method !== "get") {
globalLoadingInstance = Loading.service({
text: "Loading",
spinner: "el-icon-loading",
background: "hsla(0,0%,100%,.9)",
});
}
// 是否需要设置 token // 是否需要设置 token
const isToken = (config.headers || {}).isToken === false const isToken = (config.headers || {}).isToken === false
// 是否需要防止数据重复提交 // 是否需要防止数据重复提交
@ -67,49 +79,64 @@ service.interceptors.request.use(config => {
} }
return config return config
}, error => { }, error => {
console.log(error) console.log(error)
Promise.reject(error) if (globalLoadingInstance) {
globalLoadingInstance.close();
}
Promise.reject(error)
}) })
// 响应拦截器 // 响应拦截器
service.interceptors.response.use(res => { service.interceptors.response.use(res => {
if (globalLoadingInstance) {
globalLoadingInstance.close();
}
// 未设置状态码则默认成功状态 // 未设置状态码则默认成功状态
const code = res.data.code || 200; const code = res.data.code || 200;
// 获取错误信息 // 获取错误信息
const msg = errorCode[code] || res.data.msg || errorCode['default'] const msg = errorCode[code] || res.data.msg || errorCode['default']
// 二进制数据则直接返回 // 二进制数据则直接返回
if (res.request.responseType === 'blob' || res.request.responseType === 'arraybuffer') { if (res.request.responseType === 'blob' || res.request.responseType === 'arraybuffer') {
return res.data return res.data
} }
if (code === 401) { if (code === 401) {
if (!isRelogin.show) { if (!isRelogin.show) {
isRelogin.show = true; isRelogin.show = true;
MessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', { confirmButtonText: '重新登录', cancelButtonText: '取消', type: 'warning' }).then(() => { MessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', {
confirmButtonText: '重新登录',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
isRelogin.show = false; isRelogin.show = false;
store.dispatch('LogOut').then(() => { store.dispatch('LogOut').then(() => {
location.href = '/index'; location.href = '/index';
}) })
}).catch(() => { }).catch(() => {
isRelogin.show = false; isRelogin.show = false;
}); });
} }
return Promise.reject('无效的会话,或者会话已过期,请重新登录。') return Promise.reject('无效的会话,或者会话已过期,请重新登录。')
} else if (code === 500) { } else if (code === 500) {
Message({ message: msg, type: 'error' }) Message({message: msg, type: 'error'})
return Promise.reject(new Error(msg)) return Promise.reject(new Error(msg))
} else if (code === 601) { } else if (code === 601) {
Message({ message: msg, type: 'warning' }) Message({message: msg, type: 'warning'})
return Promise.reject('error') return Promise.reject('error')
} else if (code !== 200) { } else if (code !== 200) {
Notification.error({ title: msg }) Notification.error({title: msg})
return Promise.reject('error') return Promise.reject('error')
} else { } else {
return res.data return res.data
} }
}, },
error => { error => {
if (globalLoadingInstance) {
globalLoadingInstance.close();
}
console.log('err' + error) console.log('err' + error)
let { message } = error; let {message} = error;
if (message == "Network Error") { if (message == "Network Error") {
message = "后端接口连接异常"; message = "后端接口连接异常";
} else if (message.includes("timeout")) { } else if (message.includes("timeout")) {
@ -117,17 +144,23 @@ service.interceptors.response.use(res => {
} else if (message.includes("Request failed with status code")) { } else if (message.includes("Request failed with status code")) {
message = "系统接口" + message.substr(message.length - 3) + "异常"; message = "系统接口" + message.substr(message.length - 3) + "异常";
} }
Message({ message: message, type: 'error', duration: 5 * 1000 }) Message({message: message, type: 'error', duration: 5 * 1000})
return Promise.reject(error) return Promise.reject(error)
} }
) )
// 通用下载方法 // 通用下载方法
export function download(url, params, filename, config) { export function download(url, params, filename, config) {
downloadLoadingInstance = Loading.service({ text: "正在下载数据,请稍候", spinner: "el-icon-loading", background: "rgba(0, 0, 0, 0.7)", }) downloadLoadingInstance = Loading.service({
text: "正在下载数据,请稍候",
spinner: "el-icon-loading",
background: "rgba(0, 0, 0, 0.7)",
})
return service.post(url, params, { return service.post(url, params, {
transformRequest: [(params) => { return tansParams(params) }], transformRequest: [(params) => {
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, return tansParams(params)
}],
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
responseType: 'blob', responseType: 'blob',
...config ...config
}).then(async (data) => { }).then(async (data) => {

@ -1,57 +1,113 @@
<template> <template>
<div id="app"> <div id="app">
<TabComponent <TabComponent
v-if="tabs.length > 0"
ref="tabComponent" ref="tabComponent"
:initial-tabs="tabs" :init-menu-item.sync="tabs"
:req-fun="openDB" :init-columns="column"
/> :call-back-select="backSelect"
>
</TabComponent>
</div> </div>
</template> </template>
<script> <script>
import {getNav, getTasks} from "@/api/gather/pool/pool";
export default { export default {
name: 'App', name: 'App',
data() { data() {
return { return {
tabs: [ addTabDialogVisible: false,
tabs: [],
currentActiveTab: {},
column: [
{
type: 'id',
width: 55,
align: 'center'
},
{ {
"title": "开发KIS", title: '表名称',
"name": "kisMssql", key: 'tableName',
"dbType": "mssql", align: 'center'
"url": "jdbc:sqlserver://192.168.3.28:1433;DatabaseName=KIS;encrypt=true;trustServerCertificate=true;",
"username": "sa",
"password": "mssql_whdZeB",
"driverClassName": "com.microsoft.sqlserver.jdbc.SQLServerDriver"
}, },
{ {
"title": "本地KIS", title: '描述',
"name": "localKis", key: 'tableDescription',
"dbType": "mssql", align: 'center'
"url": "jdbc:sqlserver://192.168.3.252:1433;DatabaseName=KIS_Sample;trustServerCertificate=true;sslProtocol=TLSv1.2;",
"username": "sa",
"password": "abc123456.",
"driverClassName": "com.microsoft.sqlserver.jdbc.SQLServerDriver"
}, },
{
title: '表注',
key: 'tableNote',
align: 'center'
},
{
title: '启用',
key: 'enable',
align: 'center'
},
{
title: 'cron (定时)',
key: 'cron',
align: 'center'
},
{
title: '操作',
key: 'oper',
align: 'center'
}
], ],
addTabDialogVisible: false, total: 0,
activeTab: null rows: [],
initActiveTab: "0",
queryParams: {
pageNum: 1,
pageSize: 10
}
}; };
}, },
mounted() {
this.getNav();
},
methods: { methods: {
async openDB(data) { getNav() {
await this.closeDialog(); getNav().then(response => {
this.tabs = response.data.map(item => ({
title: item.alias,
name: item.name,
dbType: item.dbType,
url: item.url,
username: item.username,
driverClassName: item.driverClassName
}));
if (this.tabs.length > 0) {
this.currentActiveTab = this.tabs[0];
this.getDataList(this.queryParams);
}
}).catch(error => {
console.error('Failed to fetch navigation data:', error);
});
}, },
async closeDialog() {
if (this.$refs.tabComponent) { backSelect(index, queryParams) {
this.$refs.tabComponent.handleClose(); this.currentActiveTab = this.tabs[index];
} else { this.getDataList(queryParams);
console.error('TabComponent ref is not defined'); },
}
getDataList(queryParams) {
getTasks(queryParams)
.then(response => {
this.rows = response.rows;
this.total = response.total;
this.$refs.tabComponent.loadTableData(this.rows, this.total);
})
.catch(error => {
console.error('Failed to fetch data list:', error);
});
} }
},
mounted() {
// console.log('App mounted', this.$refs.tabComponent);
} }
}; };
</script> </script>

@ -118,19 +118,20 @@
type="text" type="text"
icon="el-icon-refresh-right" icon="el-icon-refresh-right"
@click="handleClearCacheAll()" @click="handleClearCacheAll()"
>清理全部</el-button >清理全部
</el-button
> >
</div> </div>
<el-form :model="cacheForm"> <el-form :model="cacheForm">
<el-row :gutter="32"> <el-row :gutter="32">
<el-col :offset="1" :span="22"> <el-col :offset="1" :span="22">
<el-form-item label="缓存名称:" prop="cacheName"> <el-form-item label="缓存名称:" prop="cacheName">
<el-input v-model="cacheForm.cacheName" :readOnly="true" /> <el-input v-model="cacheForm.cacheName" :readOnly="true"/>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :offset="1" :span="22"> <el-col :offset="1" :span="22">
<el-form-item label="缓存键名:" prop="cacheKey"> <el-form-item label="缓存键名:" prop="cacheKey">
<el-input v-model="cacheForm.cacheKey" :readOnly="true" /> <el-input v-model="cacheForm.cacheKey" :readOnly="true"/>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :offset="1" :span="22"> <el-col :offset="1" :span="22">
@ -152,7 +153,14 @@
</template> </template>
<script> <script>
import { listCacheName, listCacheKey, getCacheValue, clearCacheName, clearCacheKey, clearCacheAll } from "@/api/monitor/cache"; import {
clearCacheAll,
clearCacheKey,
clearCacheName,
getCacheValue,
listCacheKey,
listCacheName
} from "@/api/monitor/cache";
export default { export default {
name: "CacheList", name: "CacheList",

Loading…
Cancel
Save