Merge branch 'dev' of http://123.132.248.154:10000/HC_YFZX/vue-vben-admin into dev
commit
2aec5bc5ac
|
|
@ -10,6 +10,7 @@
|
||||||
/>
|
/>
|
||||||
<title><%= VITE_GLOB_APP_TITLE %></title>
|
<title><%= VITE_GLOB_APP_TITLE %></title>
|
||||||
<link rel="icon" href="/favicon.ico" />
|
<link rel="icon" href="/favicon.ico" />
|
||||||
|
<link rel="stylesheet" href="learunui/learunui.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="app">
|
<div id="app">
|
||||||
|
|
@ -154,5 +155,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<script type="module" src="/src/main.ts"></script>
|
<script type="module" src="/src/main.ts"></script>
|
||||||
|
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,24 @@
|
||||||
|
import { defHttp } from '@/utils/http/lraxios';
|
||||||
|
import { DemoOptionsItem, selectParams, AccountListGetResultModel, AccountParams } from './model/index';
|
||||||
|
|
||||||
|
enum Api {
|
||||||
|
OPTIONS_LIST = '/data/dataitem/details/FormSort',
|
||||||
|
FORMS_LIST = '/custmerform/scheme/page',
|
||||||
|
DATABASE_LIST = '/data/codetable/page',
|
||||||
|
OUTKEY_LIST = '/data/codetables/lrsystemdb'
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description: Get sample options value
|
||||||
|
*/
|
||||||
|
export const optionsListApi = (params?: selectParams) =>
|
||||||
|
defHttp.get<DemoOptionsItem[]>({ url: Api.OPTIONS_LIST, params });
|
||||||
|
|
||||||
|
export const getFormGroupList = (params: AccountParams) =>
|
||||||
|
defHttp.get<AccountListGetResultModel>({ url: Api.FORMS_LIST, params });
|
||||||
|
|
||||||
|
export const getDataBaseTableList = (params: AccountParams) =>
|
||||||
|
defHttp.get<AccountListGetResultModel>({ url: Api.DATABASE_LIST, params });
|
||||||
|
|
||||||
|
export const getOutKeyList = (params: AccountParams) =>
|
||||||
|
defHttp.get<AccountListGetResultModel>({ url: Api.OUTKEY_LIST, params });
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
import { BasicPageParams, BasicFetchResult } from '@/api/model/baseModel';
|
||||||
|
|
||||||
|
export interface DemoOptionsItem {
|
||||||
|
name: string;
|
||||||
|
id: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface selectParams {
|
||||||
|
id: number | string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type AccountParams = BasicPageParams & {
|
||||||
|
account?: string;
|
||||||
|
nickname?: string;
|
||||||
|
[key: string]: any;
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface AccountListItem {
|
||||||
|
id: string;
|
||||||
|
account: string;
|
||||||
|
email: string;
|
||||||
|
nickname: string;
|
||||||
|
role: number;
|
||||||
|
createTime: string;
|
||||||
|
remark: string;
|
||||||
|
status: number;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @description: Request list return value
|
||||||
|
*/
|
||||||
|
export type DemoOptionsGetResultModel = BasicFetchResult<DemoOptionsItem>;
|
||||||
|
|
||||||
|
export type AccountListGetResultModel = BasicFetchResult<AccountListItem>;
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
import lrLayout from './src/lrLayout.vue'
|
||||||
|
|
||||||
|
lrLayout.install = function(Vue) {
|
||||||
|
Vue.component(lrLayout.name, lrLayout)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default lrLayout
|
||||||
|
|
@ -0,0 +1,208 @@
|
||||||
|
<template>
|
||||||
|
<div class="l-layout" :style="{'padding-left':leftWidth}">
|
||||||
|
<div class="l-layout--left" :style="{'width':leftWidth}" >
|
||||||
|
<div class="l-layout--wrapper" ><slot name="left"></slot></div>
|
||||||
|
<div v-if="leftMove" class="l-layout--move" @mousedown="onMousedown('left',$event)" ></div>
|
||||||
|
</div>
|
||||||
|
<div class="l-layout--container" :style="{'padding-right':rightWidth}" >
|
||||||
|
<div class="l-layout--right" :style="{ 'width':rightWidth}">
|
||||||
|
<div class="l-layout--wrapper" ><slot name="right"></slot></div>
|
||||||
|
<div v-if="rightMove" class="l-layout--move" @mousedown="onMousedown('right',$event)" ></div>
|
||||||
|
</div>
|
||||||
|
<div class="l-layout--container" :style="{'padding-bottom':bottomHight}" >
|
||||||
|
<div class="l-layout--bottom" :style="{'height':bottomHight}" >
|
||||||
|
<div class="l-layout--wrapper" > <slot name="bottom"></slot></div>
|
||||||
|
<div v-if="bottomMove" class="l-layout--move" @mousedown="onMousedown('bottom',$event)" ></div>
|
||||||
|
</div>
|
||||||
|
<div class="l-layout--container" :style="{'padding-top':topHight}" >
|
||||||
|
<div class="l-layout--top" :style="{'height':topHight}" >
|
||||||
|
<div class="l-layout--wrapper" ><slot name="top"></slot></div>
|
||||||
|
<div v-if="topMove" class="l-layout--move" @mousedown="onMousedown('top',$event)" ></div>
|
||||||
|
</div>
|
||||||
|
<div class="l-layout--wrapper" ref="mid">
|
||||||
|
<slot></slot>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name:'l-layout',
|
||||||
|
props: {
|
||||||
|
left: {
|
||||||
|
type: Number,
|
||||||
|
default: 200
|
||||||
|
},
|
||||||
|
leftMove: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
right: {
|
||||||
|
type: Number,
|
||||||
|
default: 200
|
||||||
|
},
|
||||||
|
rightMove:{
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
top: {
|
||||||
|
type: Number,
|
||||||
|
default: 60
|
||||||
|
},
|
||||||
|
topMove:{
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
bottom:{
|
||||||
|
type: Number,
|
||||||
|
default: 60
|
||||||
|
},
|
||||||
|
bottomMove:{
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
mleft:this.left,
|
||||||
|
mright:this.right,
|
||||||
|
mtop:this.top,
|
||||||
|
mbottom:this.bottom,
|
||||||
|
|
||||||
|
move:{
|
||||||
|
type:'',
|
||||||
|
isMove:false,
|
||||||
|
pageX:0,
|
||||||
|
pageY:0,
|
||||||
|
size:0,
|
||||||
|
h:0,
|
||||||
|
w:0,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
mounted () {
|
||||||
|
},
|
||||||
|
watch:{
|
||||||
|
left(val){
|
||||||
|
this.mleft = val;
|
||||||
|
},
|
||||||
|
right(val){
|
||||||
|
this.mright = val;
|
||||||
|
},
|
||||||
|
top(val){
|
||||||
|
this.mtop = val;
|
||||||
|
},
|
||||||
|
bottom(val){
|
||||||
|
this.mbottom = val;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed:{
|
||||||
|
leftWidth:function(){
|
||||||
|
if(this.$slots.left){
|
||||||
|
return this.mleft + 'px'
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
return '0'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
rightWidth:function(){
|
||||||
|
if(this.$slots.right){
|
||||||
|
return this.mright + 'px'
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
return '0'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
topHight:function(){
|
||||||
|
if(this.$slots.top){
|
||||||
|
return this.mtop + 'px'
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
return '0'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
bottomHight:function(){
|
||||||
|
if(this.$slots.bottom){
|
||||||
|
return this.mbottom + 'px'
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
return '0'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods:{
|
||||||
|
onMousedown:function(type,e){
|
||||||
|
this.move.type = type;
|
||||||
|
this.move.isMove = true;
|
||||||
|
this.move.pageX = e.pageX;
|
||||||
|
this.move.pageY = e.pageY;
|
||||||
|
this.move.size = this["m"+type];
|
||||||
|
|
||||||
|
this.move.h = this.$refs.mid.clientHeight;
|
||||||
|
this.move.w = this.$refs.mid.clientWidth;
|
||||||
|
|
||||||
|
document.onmouseup = this.onMouseup;
|
||||||
|
document.onmousemove = this.onMousemove;
|
||||||
|
},
|
||||||
|
onMousemove:function(e){
|
||||||
|
if(this.move.isMove){
|
||||||
|
switch(this.move.type){
|
||||||
|
case 'left':
|
||||||
|
var x1 = e.pageX - this.move.pageX;
|
||||||
|
var left = this.move.size + x1;
|
||||||
|
if(left < 0){
|
||||||
|
left = 4;
|
||||||
|
}
|
||||||
|
else if(left > this.move.size + this.move.w){
|
||||||
|
left = this.move.size + this.move.w
|
||||||
|
}
|
||||||
|
this.mleft = left;
|
||||||
|
break;
|
||||||
|
case 'right':
|
||||||
|
var x2 = e.pageX - this.move.pageX;
|
||||||
|
var right = this.move.size - x2;
|
||||||
|
if(right < 0){
|
||||||
|
right = 4;
|
||||||
|
}
|
||||||
|
else if(right > this.move.size + this.move.w){
|
||||||
|
right = this.move.size + this.move.w
|
||||||
|
}
|
||||||
|
this.mright = right;
|
||||||
|
break;
|
||||||
|
case 'top':
|
||||||
|
var y = e.pageY - this.move.pageY;
|
||||||
|
var top = this.move.size + y;
|
||||||
|
if(top < 0){
|
||||||
|
top = 4;
|
||||||
|
}
|
||||||
|
else if(top > this.move.size + this.move.h){
|
||||||
|
top = this.move.size + this.move.h
|
||||||
|
}
|
||||||
|
this.mtop = top;
|
||||||
|
break;
|
||||||
|
case 'bottom':
|
||||||
|
var y2 = e.pageY - this.move.pageY;
|
||||||
|
var bottom = this.move.size - y2;
|
||||||
|
if(bottom < 0){
|
||||||
|
bottom = 4;
|
||||||
|
}
|
||||||
|
else if(bottom > this.move.size + this.move.h){
|
||||||
|
bottom = this.move.size + this.move.h
|
||||||
|
}
|
||||||
|
this.mbottom = bottom;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onMouseup:function(){
|
||||||
|
this.move.isMove = false;
|
||||||
|
document.onmousemove = document.onmouseup = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style lang="less">
|
||||||
|
// @import './index.less';
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
import lrPanel from './src/lrPanel.vue'
|
||||||
|
|
||||||
|
lrPanel.install = function(Vue) {
|
||||||
|
Vue.component(lrPanel.name, lrPanel)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default lrPanel
|
||||||
|
|
@ -0,0 +1,65 @@
|
||||||
|
<template>
|
||||||
|
<div class="l-panel">
|
||||||
|
<div class="l-panel--warpper" :style="{'padding-top':paddingTop}" >
|
||||||
|
<div v-if="title || $slots.title" class="l-panel--title" >
|
||||||
|
<slot name="title">{{ title }}</slot>
|
||||||
|
</div>
|
||||||
|
<div v-if="$slots.toolLeft || $slots.toolRight" class="l-panel--tool" :style="{'top':toolTop}" >
|
||||||
|
<div class="l-panel--tool-left">
|
||||||
|
<slot name="toolLeft" ></slot>
|
||||||
|
</div>
|
||||||
|
<div class="l-panel--tool-right">
|
||||||
|
<slot name="toolRight" ></slot>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="l-panel--body" >
|
||||||
|
<slot></slot>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name:'l-panel',
|
||||||
|
props: {
|
||||||
|
title:String,
|
||||||
|
loading:{
|
||||||
|
type:Boolean,
|
||||||
|
default:false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
};
|
||||||
|
},
|
||||||
|
mounted () {
|
||||||
|
|
||||||
|
},
|
||||||
|
computed:{
|
||||||
|
paddingTop:function(){
|
||||||
|
var ptop = 0;
|
||||||
|
if(this.title || this.$slots.title){
|
||||||
|
ptop += 40;
|
||||||
|
}
|
||||||
|
if(this.$slots.toolLeft || this.$slots.toolRight){
|
||||||
|
ptop += 40;
|
||||||
|
}
|
||||||
|
return ptop + 'px';
|
||||||
|
},
|
||||||
|
toolTop:function(){
|
||||||
|
if(this.title || this.$slots.title){
|
||||||
|
return '40px'
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
return '0'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods:{
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style lang="less">
|
||||||
|
// @import './index.less';
|
||||||
|
</style>
|
||||||
|
|
@ -3,13 +3,14 @@ import type { GlobConfig } from '#/config';
|
||||||
import { getAppEnvConfig } from '@/utils/env';
|
import { getAppEnvConfig } from '@/utils/env';
|
||||||
|
|
||||||
export const useGlobSetting = (): Readonly<GlobConfig> => {
|
export const useGlobSetting = (): Readonly<GlobConfig> => {
|
||||||
const { VITE_GLOB_APP_TITLE, VITE_GLOB_API_URL, VITE_GLOB_API_URL_PREFIX, VITE_GLOB_UPLOAD_URL } =
|
const { VITE_GLOB_APP_TITLE, VITE_GLOB_API_URL, VITE_GLOB_API_URL_PREFIX, VITE_GLOB_UPLOAD_URL,VITE_LR_API_URL } =
|
||||||
getAppEnvConfig();
|
getAppEnvConfig();
|
||||||
|
|
||||||
// Take global configuration
|
// Take global configuration
|
||||||
const glob: Readonly<GlobConfig> = {
|
const glob: Readonly<GlobConfig> = {
|
||||||
title: VITE_GLOB_APP_TITLE,
|
title: VITE_GLOB_APP_TITLE,
|
||||||
apiUrl: VITE_GLOB_API_URL,
|
apiUrl: VITE_GLOB_API_URL,
|
||||||
|
lrApi: VITE_LR_API_URL,
|
||||||
shortName: VITE_GLOB_APP_TITLE.replace(/\s/g, '_').replace(/-/g, '_'),
|
shortName: VITE_GLOB_APP_TITLE.replace(/\s/g, '_').replace(/-/g, '_'),
|
||||||
urlPrefix: VITE_GLOB_API_URL_PREFIX,
|
urlPrefix: VITE_GLOB_API_URL_PREFIX,
|
||||||
uploadUrl: VITE_GLOB_UPLOAD_URL,
|
uploadUrl: VITE_GLOB_UPLOAD_URL,
|
||||||
|
|
|
||||||
|
|
@ -68,7 +68,6 @@ async function getAsyncMenus() {
|
||||||
}
|
}
|
||||||
if (isRouteMappingMode()) {
|
if (isRouteMappingMode()) {
|
||||||
// 333333
|
// 333333
|
||||||
console.log(permissionStore.getFrontMenuList)
|
|
||||||
return menuFilter(permissionStore.getFrontMenuList);
|
return menuFilter(permissionStore.getFrontMenuList);
|
||||||
}
|
}
|
||||||
return staticMenus;
|
return staticMenus;
|
||||||
|
|
|
||||||
|
|
@ -32,12 +32,14 @@ export function getAppEnvConfig() {
|
||||||
: (window[ENV_NAME] as unknown as GlobEnvConfig);
|
: (window[ENV_NAME] as unknown as GlobEnvConfig);
|
||||||
const { VITE_GLOB_APP_TITLE, VITE_GLOB_API_URL_PREFIX, VITE_GLOB_UPLOAD_URL } = ENV;
|
const { VITE_GLOB_APP_TITLE, VITE_GLOB_API_URL_PREFIX, VITE_GLOB_UPLOAD_URL } = ENV;
|
||||||
let { VITE_GLOB_API_URL } = ENV;
|
let { VITE_GLOB_API_URL } = ENV;
|
||||||
|
let { VITE_LR_API_URL } = ENV;
|
||||||
if (localStorage.getItem(API_ADDRESS)) {
|
if (localStorage.getItem(API_ADDRESS)) {
|
||||||
const address = JSON.parse(localStorage.getItem(API_ADDRESS) || '{}');
|
const address = JSON.parse(localStorage.getItem(API_ADDRESS) || '{}');
|
||||||
if (address?.key) VITE_GLOB_API_URL = address?.val;
|
if (address?.key) VITE_GLOB_API_URL = address?.val;
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
VITE_GLOB_APP_TITLE,
|
VITE_GLOB_APP_TITLE,
|
||||||
|
VITE_LR_API_URL,
|
||||||
VITE_GLOB_API_URL,
|
VITE_GLOB_API_URL,
|
||||||
VITE_GLOB_API_URL_PREFIX,
|
VITE_GLOB_API_URL_PREFIX,
|
||||||
VITE_GLOB_UPLOAD_URL,
|
VITE_GLOB_UPLOAD_URL,
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ import axios from 'axios';
|
||||||
const globSetting = useGlobSetting();
|
const globSetting = useGlobSetting();
|
||||||
const urlPrefix = globSetting.urlPrefix;
|
const urlPrefix = globSetting.urlPrefix;
|
||||||
const { createMessage, createErrorModal, createSuccessModal } = useMessage();
|
const { createMessage, createErrorModal, createSuccessModal } = useMessage();
|
||||||
|
console.log('globSetting',globSetting)
|
||||||
/**
|
/**
|
||||||
* @description: 数据处理,方便区分多种处理方式
|
* @description: 数据处理,方便区分多种处理方式
|
||||||
*/
|
*/
|
||||||
|
|
@ -52,7 +52,6 @@ const transform: AxiosTransform = {
|
||||||
}
|
}
|
||||||
// 这里 code,result,message为 后台统一的字段,需要在 types.ts内修改为项目自己的接口返回格式
|
// 这里 code,result,message为 后台统一的字段,需要在 types.ts内修改为项目自己的接口返回格式
|
||||||
const { code, result, message } = data;
|
const { code, result, message } = data;
|
||||||
|
|
||||||
// 这里逻辑可以根据项目进行修改
|
// 这里逻辑可以根据项目进行修改
|
||||||
const hasSuccess = data && Reflect.has(data, 'code') && code === ResultEnum.SUCCESS;
|
const hasSuccess = data && Reflect.has(data, 'code') && code === ResultEnum.SUCCESS;
|
||||||
if (hasSuccess) {
|
if (hasSuccess) {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,251 @@
|
||||||
|
import type {
|
||||||
|
AxiosRequestConfig,
|
||||||
|
AxiosInstance,
|
||||||
|
AxiosResponse,
|
||||||
|
AxiosError,
|
||||||
|
InternalAxiosRequestConfig,
|
||||||
|
} from 'axios';
|
||||||
|
import type { RequestOptions, Result, UploadFileParams } from '#/axios';
|
||||||
|
import type { CreateAxiosOptions } from './axiosTransform';
|
||||||
|
import axios from 'axios';
|
||||||
|
import qs from 'qs';
|
||||||
|
import { AxiosCanceler } from './axiosCancel';
|
||||||
|
import { isFunction } from '@/utils/is';
|
||||||
|
import { cloneDeep } from 'lodash-es';
|
||||||
|
import { ContentTypeEnum, RequestEnum } from '@/enums/httpEnum';
|
||||||
|
|
||||||
|
export * from './axiosTransform';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description: axios module
|
||||||
|
*/
|
||||||
|
export class VAxios {
|
||||||
|
private axiosInstance: AxiosInstance;
|
||||||
|
private readonly options: CreateAxiosOptions;
|
||||||
|
|
||||||
|
constructor(options: CreateAxiosOptions) {
|
||||||
|
this.options = options;
|
||||||
|
this.axiosInstance = axios.create(options);
|
||||||
|
this.setupInterceptors();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description: Create axios instance
|
||||||
|
*/
|
||||||
|
private createAxios(config: CreateAxiosOptions): void {
|
||||||
|
this.axiosInstance = axios.create(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
private getTransform() {
|
||||||
|
const { transform } = this.options;
|
||||||
|
return transform;
|
||||||
|
}
|
||||||
|
|
||||||
|
getAxios(): AxiosInstance {
|
||||||
|
return this.axiosInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description: Reconfigure axios
|
||||||
|
*/
|
||||||
|
configAxios(config: CreateAxiosOptions) {
|
||||||
|
if (!this.axiosInstance) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.createAxios(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description: Set general header
|
||||||
|
*/
|
||||||
|
setHeader(headers: any): void {
|
||||||
|
if (!this.axiosInstance) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Object.assign(this.axiosInstance.defaults.headers, headers);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description: Interceptor configuration 拦截器配置
|
||||||
|
*/
|
||||||
|
private setupInterceptors() {
|
||||||
|
// const transform = this.getTransform();
|
||||||
|
const {
|
||||||
|
axiosInstance,
|
||||||
|
options: { transform },
|
||||||
|
} = this;
|
||||||
|
if (!transform) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const {
|
||||||
|
requestInterceptors,
|
||||||
|
requestInterceptorsCatch,
|
||||||
|
responseInterceptors,
|
||||||
|
responseInterceptorsCatch,
|
||||||
|
} = transform;
|
||||||
|
|
||||||
|
const axiosCanceler = new AxiosCanceler();
|
||||||
|
|
||||||
|
// Request interceptor configuration processing
|
||||||
|
this.axiosInstance.interceptors.request.use((config: InternalAxiosRequestConfig) => {
|
||||||
|
// If cancel repeat request is turned on, then cancel repeat request is prohibited
|
||||||
|
const requestOptions =
|
||||||
|
(config as unknown as any).requestOptions ?? this.options.requestOptions;
|
||||||
|
const ignoreCancelToken = requestOptions?.ignoreCancelToken ?? true;
|
||||||
|
|
||||||
|
!ignoreCancelToken && axiosCanceler.addPending(config);
|
||||||
|
|
||||||
|
if (requestInterceptors && isFunction(requestInterceptors)) {
|
||||||
|
config = requestInterceptors(config, this.options);
|
||||||
|
}
|
||||||
|
return config;
|
||||||
|
}, undefined);
|
||||||
|
|
||||||
|
// Request interceptor error capture
|
||||||
|
requestInterceptorsCatch &&
|
||||||
|
isFunction(requestInterceptorsCatch) &&
|
||||||
|
this.axiosInstance.interceptors.request.use(undefined, requestInterceptorsCatch);
|
||||||
|
|
||||||
|
// Response result interceptor processing
|
||||||
|
this.axiosInstance.interceptors.response.use((res: AxiosResponse<any>) => {
|
||||||
|
res && axiosCanceler.removePending(res.config);
|
||||||
|
if (responseInterceptors && isFunction(responseInterceptors)) {
|
||||||
|
res = responseInterceptors(res);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}, undefined);
|
||||||
|
|
||||||
|
// Response result interceptor error capture
|
||||||
|
responseInterceptorsCatch &&
|
||||||
|
isFunction(responseInterceptorsCatch) &&
|
||||||
|
this.axiosInstance.interceptors.response.use(undefined, (error) => {
|
||||||
|
return responseInterceptorsCatch(axiosInstance, error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description: File Upload
|
||||||
|
*/
|
||||||
|
uploadFile<T = any>(config: AxiosRequestConfig, params: UploadFileParams) {
|
||||||
|
const formData = new window.FormData();
|
||||||
|
const customFilename = params.name || 'file';
|
||||||
|
|
||||||
|
if (params.filename) {
|
||||||
|
formData.append(customFilename, params.file, params.filename);
|
||||||
|
} else {
|
||||||
|
formData.append(customFilename, params.file);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params.data) {
|
||||||
|
Object.keys(params.data).forEach((key) => {
|
||||||
|
const value = params.data![key];
|
||||||
|
if (Array.isArray(value)) {
|
||||||
|
value.forEach((item) => {
|
||||||
|
formData.append(`${key}[]`, item);
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
formData.append(key, params.data![key]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return this.axiosInstance.request<T>({
|
||||||
|
...config,
|
||||||
|
method: 'POST',
|
||||||
|
data: formData,
|
||||||
|
headers: {
|
||||||
|
'Content-type': ContentTypeEnum.FORM_DATA,
|
||||||
|
// @ts-ignore
|
||||||
|
ignoreCancelToken: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// support form-data
|
||||||
|
supportFormData(config: AxiosRequestConfig) {
|
||||||
|
const headers = config.headers || this.options.headers;
|
||||||
|
const contentType = headers?.['Content-Type'] || headers?.['content-type'];
|
||||||
|
|
||||||
|
if (
|
||||||
|
contentType !== ContentTypeEnum.FORM_URLENCODED ||
|
||||||
|
!Reflect.has(config, 'data') ||
|
||||||
|
config.method?.toUpperCase() === RequestEnum.GET
|
||||||
|
) {
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
...config,
|
||||||
|
data: qs.stringify(config.data, { arrayFormat: 'brackets' }),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
get<T = any>(config: AxiosRequestConfig, options?: RequestOptions): Promise<T> {
|
||||||
|
return this.request({ ...config, method: 'GET' }, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
post<T = any>(config: AxiosRequestConfig, options?: RequestOptions): Promise<T> {
|
||||||
|
return this.request({ ...config, method: 'POST' }, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
put<T = any>(config: AxiosRequestConfig, options?: RequestOptions): Promise<T> {
|
||||||
|
return this.request({ ...config, method: 'PUT' }, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
delete<T = any>(config: AxiosRequestConfig, options?: RequestOptions): Promise<T> {
|
||||||
|
return this.request({ ...config, method: 'DELETE' }, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
request<T = any>(config: AxiosRequestConfig, options?: RequestOptions): Promise<T> {
|
||||||
|
let conf: CreateAxiosOptions = cloneDeep(config);
|
||||||
|
// cancelToken 如果被深拷贝,会导致最外层无法使用cancel方法来取消请求
|
||||||
|
if (config.cancelToken) {
|
||||||
|
conf.cancelToken = config.cancelToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config.signal) {
|
||||||
|
conf.signal = config.signal;
|
||||||
|
}
|
||||||
|
|
||||||
|
const transform = this.getTransform();
|
||||||
|
|
||||||
|
const { requestOptions } = this.options;
|
||||||
|
|
||||||
|
const opt: RequestOptions = Object.assign({}, requestOptions, options);
|
||||||
|
|
||||||
|
const { beforeRequestHook, requestCatchHook, transformResponseHook } = transform || {};
|
||||||
|
if (beforeRequestHook && isFunction(beforeRequestHook)) {
|
||||||
|
conf = beforeRequestHook(conf, opt);
|
||||||
|
}
|
||||||
|
conf.requestOptions = opt;
|
||||||
|
|
||||||
|
conf = this.supportFormData(conf);
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
this.axiosInstance
|
||||||
|
.request<any, AxiosResponse<Result>>(conf)
|
||||||
|
.then((res: AxiosResponse<Result>) => {
|
||||||
|
if (transformResponseHook && isFunction(transformResponseHook)) {
|
||||||
|
try {
|
||||||
|
const ret = transformResponseHook(res, opt);
|
||||||
|
resolve(ret);
|
||||||
|
} catch (err) {
|
||||||
|
reject(err || new Error('request error!'));
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
resolve(res as unknown as Promise<T>);
|
||||||
|
})
|
||||||
|
.catch((e: Error | AxiosError) => {
|
||||||
|
if (requestCatchHook && isFunction(requestCatchHook)) {
|
||||||
|
reject(requestCatchHook(e, opt));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (axios.isAxiosError(e)) {
|
||||||
|
// rewrite error message from axios in here
|
||||||
|
}
|
||||||
|
reject(e);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
import type { AxiosRequestConfig } from 'axios';
|
||||||
|
|
||||||
|
// 用于存储每个请求的标识和取消函数
|
||||||
|
const pendingMap = new Map<string, AbortController>();
|
||||||
|
|
||||||
|
const getPendingUrl = (config: AxiosRequestConfig): string => {
|
||||||
|
return [config.method, config.url].join('&');
|
||||||
|
};
|
||||||
|
|
||||||
|
export class AxiosCanceler {
|
||||||
|
/**
|
||||||
|
* 添加请求
|
||||||
|
* @param config 请求配置
|
||||||
|
*/
|
||||||
|
public addPending(config: AxiosRequestConfig): void {
|
||||||
|
this.removePending(config);
|
||||||
|
const url = getPendingUrl(config);
|
||||||
|
const controller = new AbortController();
|
||||||
|
config.signal = config.signal || controller.signal;
|
||||||
|
if (!pendingMap.has(url)) {
|
||||||
|
// 如果当前请求不在等待中,将其添加到等待中
|
||||||
|
pendingMap.set(url, controller);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清除所有等待中的请求
|
||||||
|
*/
|
||||||
|
public removeAllPending(): void {
|
||||||
|
pendingMap.forEach((abortController) => {
|
||||||
|
if (abortController) {
|
||||||
|
abortController.abort();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 移除请求
|
||||||
|
* @param config 请求配置
|
||||||
|
*/
|
||||||
|
public removePending(config: AxiosRequestConfig): void {
|
||||||
|
const url = getPendingUrl(config);
|
||||||
|
if (pendingMap.has(url)) {
|
||||||
|
// 如果当前请求在等待中,取消它并将其从等待中移除
|
||||||
|
const abortController = pendingMap.get(url);
|
||||||
|
if (abortController) {
|
||||||
|
abortController.abort(url);
|
||||||
|
}
|
||||||
|
pendingMap.delete(url);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 重置
|
||||||
|
*/
|
||||||
|
public reset(): void {
|
||||||
|
pendingMap.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
import { AxiosError, AxiosInstance } from 'axios';
|
||||||
|
/**
|
||||||
|
* 请求重试机制
|
||||||
|
*/
|
||||||
|
|
||||||
|
export class AxiosRetry {
|
||||||
|
/**
|
||||||
|
* 重试
|
||||||
|
*/
|
||||||
|
retry(axiosInstance: AxiosInstance, error: AxiosError) {
|
||||||
|
// @ts-ignore
|
||||||
|
const { config } = error.response;
|
||||||
|
const { waitTime, count } = config?.requestOptions?.retryRequest ?? {};
|
||||||
|
config.__retryCount = config.__retryCount || 0;
|
||||||
|
if (config.__retryCount >= count) {
|
||||||
|
return Promise.reject(error);
|
||||||
|
}
|
||||||
|
config.__retryCount += 1;
|
||||||
|
//请求返回后config的header不正确造成重试请求失败,删除返回headers采用默认headers
|
||||||
|
delete config.headers;
|
||||||
|
return this.delay(waitTime).then(() => axiosInstance(config));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 延迟
|
||||||
|
*/
|
||||||
|
private delay(waitTime: number) {
|
||||||
|
return new Promise((resolve) => setTimeout(resolve, waitTime));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,57 @@
|
||||||
|
/**
|
||||||
|
* Data processing class, can be configured according to the project
|
||||||
|
*/
|
||||||
|
import type {
|
||||||
|
AxiosInstance,
|
||||||
|
AxiosRequestConfig,
|
||||||
|
AxiosResponse,
|
||||||
|
InternalAxiosRequestConfig,
|
||||||
|
} from 'axios';
|
||||||
|
import type { RequestOptions, Result } from '#/axios';
|
||||||
|
|
||||||
|
export interface CreateAxiosOptions extends AxiosRequestConfig {
|
||||||
|
authenticationScheme?: string;
|
||||||
|
transform?: AxiosTransform;
|
||||||
|
requestOptions?: RequestOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
export abstract class AxiosTransform {
|
||||||
|
/**
|
||||||
|
* A function that is called before a request is sent. It can modify the request configuration as needed.
|
||||||
|
* 在发送请求之前调用的函数。它可以根据需要修改请求配置。
|
||||||
|
*/
|
||||||
|
beforeRequestHook?: (config: AxiosRequestConfig, options: RequestOptions) => AxiosRequestConfig;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description: 处理响应数据
|
||||||
|
*/
|
||||||
|
transformResponseHook?: (res: AxiosResponse<Result>, options: RequestOptions) => any;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description: 请求失败处理
|
||||||
|
*/
|
||||||
|
requestCatchHook?: (e: Error, options: RequestOptions) => Promise<any>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description: 请求之前的拦截器
|
||||||
|
*/
|
||||||
|
requestInterceptors?: (
|
||||||
|
config: InternalAxiosRequestConfig,
|
||||||
|
options: CreateAxiosOptions,
|
||||||
|
) => InternalAxiosRequestConfig;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description: 请求之后的拦截器
|
||||||
|
*/
|
||||||
|
responseInterceptors?: (res: AxiosResponse<any>) => AxiosResponse<any>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description: 请求之前的拦截器错误处理
|
||||||
|
*/
|
||||||
|
requestInterceptorsCatch?: (error: Error) => void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description: 请求之后的拦截器错误处理
|
||||||
|
*/
|
||||||
|
responseInterceptorsCatch?: (axiosInstance: AxiosInstance, error: Error) => void;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,80 @@
|
||||||
|
import type { ErrorMessageMode } from '#/axios';
|
||||||
|
import { useMessage } from '@/hooks/web/useMessage';
|
||||||
|
import { useI18n } from '@/hooks/web/useI18n';
|
||||||
|
// import router from '@/router';
|
||||||
|
// import { PageEnum } from '@/enums/pageEnum';
|
||||||
|
import { useUserStoreWithOut } from '@/store/modules/user';
|
||||||
|
import projectSetting from '@/settings/projectSetting';
|
||||||
|
import { SessionTimeoutProcessingEnum } from '@/enums/appEnum';
|
||||||
|
|
||||||
|
const { createMessage, createErrorModal } = useMessage();
|
||||||
|
const error = createMessage.error!;
|
||||||
|
const stp = projectSetting.sessionTimeoutProcessing;
|
||||||
|
|
||||||
|
export function checkStatus(
|
||||||
|
status: number,
|
||||||
|
msg: string,
|
||||||
|
errorMessageMode: ErrorMessageMode = 'message',
|
||||||
|
): void {
|
||||||
|
const { t } = useI18n();
|
||||||
|
const userStore = useUserStoreWithOut();
|
||||||
|
let errMessage = '';
|
||||||
|
|
||||||
|
switch (status) {
|
||||||
|
case 400:
|
||||||
|
errMessage = `${msg}`;
|
||||||
|
break;
|
||||||
|
// 401: Not logged in
|
||||||
|
// Jump to the login page if not logged in, and carry the path of the current page
|
||||||
|
// Return to the current page after successful login. This step needs to be operated on the login page.
|
||||||
|
case 401:
|
||||||
|
userStore.setToken(undefined);
|
||||||
|
errMessage = msg || t('sys.api.errMsg401');
|
||||||
|
if (stp === SessionTimeoutProcessingEnum.PAGE_COVERAGE) {
|
||||||
|
userStore.setSessionTimeout(true);
|
||||||
|
} else {
|
||||||
|
userStore.logout(true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 403:
|
||||||
|
errMessage = t('sys.api.errMsg403');
|
||||||
|
break;
|
||||||
|
// 404请求不存在
|
||||||
|
case 404:
|
||||||
|
errMessage = t('sys.api.errMsg404');
|
||||||
|
break;
|
||||||
|
case 405:
|
||||||
|
errMessage = t('sys.api.errMsg405');
|
||||||
|
break;
|
||||||
|
case 408:
|
||||||
|
errMessage = t('sys.api.errMsg408');
|
||||||
|
break;
|
||||||
|
case 500:
|
||||||
|
errMessage = t('sys.api.errMsg500');
|
||||||
|
break;
|
||||||
|
case 501:
|
||||||
|
errMessage = t('sys.api.errMsg501');
|
||||||
|
break;
|
||||||
|
case 502:
|
||||||
|
errMessage = t('sys.api.errMsg502');
|
||||||
|
break;
|
||||||
|
case 503:
|
||||||
|
errMessage = t('sys.api.errMsg503');
|
||||||
|
break;
|
||||||
|
case 504:
|
||||||
|
errMessage = t('sys.api.errMsg504');
|
||||||
|
break;
|
||||||
|
case 505:
|
||||||
|
errMessage = t('sys.api.errMsg505');
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
|
||||||
|
if (errMessage) {
|
||||||
|
if (errorMessageMode === 'modal') {
|
||||||
|
createErrorModal({ title: t('sys.api.errorTip'), content: errMessage });
|
||||||
|
} else if (errorMessageMode === 'message') {
|
||||||
|
error({ content: errMessage, key: `global_error_message_status_${status}` });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,56 @@
|
||||||
|
/*
|
||||||
|
* @Author: 刘妍
|
||||||
|
* @Date: 2024-01-13 13:04:15
|
||||||
|
* @LastEditors: Do not edit
|
||||||
|
* @LastEditTime: 2024-01-22 08:55:09
|
||||||
|
* @FilePath: \费县天空地大屏正式代码e:\新架构\vue-vben-admin\src\utils\http\axios\helper.ts
|
||||||
|
* @Description:
|
||||||
|
*/
|
||||||
|
import { isObject, isString } from '@/utils/is';
|
||||||
|
|
||||||
|
const DATE_TIME_FORMAT = 'YYYY-MM-DD HH:mm:ss';
|
||||||
|
|
||||||
|
export function joinTimestamp<T extends boolean>(
|
||||||
|
join: boolean,
|
||||||
|
restful: T,
|
||||||
|
): T extends true ? string : object;
|
||||||
|
|
||||||
|
export function joinTimestamp(join: boolean, restful = false): string | object {
|
||||||
|
if (!join) {
|
||||||
|
return restful ? '' : {};
|
||||||
|
}
|
||||||
|
// const now = new Date().getTime();
|
||||||
|
// if (restful) {
|
||||||
|
// return `?_t=${now}`;
|
||||||
|
// }
|
||||||
|
// return { _t: now };
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description: Format request parameter time
|
||||||
|
*/
|
||||||
|
export function formatRequestDate(params: Recordable) {
|
||||||
|
if (Object.prototype.toString.call(params) !== '[object Object]') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const key in params) {
|
||||||
|
const format = params[key]?.format ?? null;
|
||||||
|
if (format && typeof format === 'function') {
|
||||||
|
params[key] = params[key].format(DATE_TIME_FORMAT);
|
||||||
|
}
|
||||||
|
if (isString(key)) {
|
||||||
|
const value = params[key];
|
||||||
|
if (value) {
|
||||||
|
try {
|
||||||
|
params[key] = isString(value) ? value.trim() : value;
|
||||||
|
} catch (error: any) {
|
||||||
|
throw new Error(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isObject(params[key])) {
|
||||||
|
formatRequestDate(params[key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,293 @@
|
||||||
|
// axios配置 可自行根据项目进行更改,只需更改该文件即可,其他文件可以不动
|
||||||
|
// The axios configuration can be changed according to the project, just change the file, other files can be left unchanged
|
||||||
|
|
||||||
|
import type { AxiosInstance, AxiosResponse } from 'axios';
|
||||||
|
import { clone } from 'lodash-es';
|
||||||
|
import type { RequestOptions, Result } from '#/axios';
|
||||||
|
import type { AxiosTransform, CreateAxiosOptions } from './axiosTransform';
|
||||||
|
import { VAxios } from './Axios';
|
||||||
|
import { checkStatus } from './checkStatus';
|
||||||
|
import { useGlobSetting } from '@/hooks/setting';
|
||||||
|
import { useMessage } from '@/hooks/web/useMessage';
|
||||||
|
import { RequestEnum, ResultEnum, ContentTypeEnum } from '@/enums/httpEnum';
|
||||||
|
import { isString, isUndefined, isNull, isEmpty } from '@/utils/is';
|
||||||
|
import { getToken } from '@/utils/auth';
|
||||||
|
import { setObjToUrlParams, deepMerge } from '@/utils';
|
||||||
|
import { useErrorLogStoreWithOut } from '@/store/modules/errorLog';
|
||||||
|
import { useI18n } from '@/hooks/web/useI18n';
|
||||||
|
import { joinTimestamp, formatRequestDate } from './helper';
|
||||||
|
import { useUserStoreWithOut } from '@/store/modules/user';
|
||||||
|
import { AxiosRetry } from '@/utils/http/axios/axiosRetry';
|
||||||
|
import axios from 'axios';
|
||||||
|
|
||||||
|
const globSetting = useGlobSetting();
|
||||||
|
const urlPrefix = globSetting.urlPrefix;
|
||||||
|
const { createMessage, createErrorModal, createSuccessModal } = useMessage();
|
||||||
|
/**
|
||||||
|
* @description: 数据处理,方便区分多种处理方式
|
||||||
|
*/
|
||||||
|
const transform: AxiosTransform = {
|
||||||
|
/**
|
||||||
|
* @description: 处理响应数据。如果数据不是预期格式,可直接抛出错误
|
||||||
|
*/
|
||||||
|
transformResponseHook: (res: AxiosResponse<Result>, options: RequestOptions) => {
|
||||||
|
const { t } = useI18n();
|
||||||
|
const { isTransformResponse, isReturnNativeResponse } = options;
|
||||||
|
// 是否返回原生响应头 比如:需要获取响应头时使用该属性
|
||||||
|
if (isReturnNativeResponse) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
// 不进行任何处理,直接返回
|
||||||
|
// 用于页面代码可能需要直接获取code,data,message这些信息时开启
|
||||||
|
if (!isTransformResponse) {
|
||||||
|
return res.data;
|
||||||
|
}
|
||||||
|
// 错误的时候返回
|
||||||
|
|
||||||
|
const { data } = res;
|
||||||
|
if (!data) {
|
||||||
|
// return '[HTTP] Request has no return value';
|
||||||
|
throw new Error(t('sys.api.apiRequestFailed'));
|
||||||
|
}
|
||||||
|
// 这里 code,result,message为 后台统一的字段,需要在 types.ts内修改为项目自己的接口返回格式
|
||||||
|
const { code, result, message } = data;
|
||||||
|
// 这里逻辑可以根据项目进行修改
|
||||||
|
const hasSuccess = data && Reflect.has(data, 'code') && code === ResultEnum.SUCCESS;
|
||||||
|
if (hasSuccess) {
|
||||||
|
let successMsg = message;
|
||||||
|
|
||||||
|
if (isNull(successMsg) || isUndefined(successMsg) || isEmpty(successMsg)) {
|
||||||
|
successMsg = t(`sys.api.operationSuccess`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.successMessageMode === 'modal') {
|
||||||
|
createSuccessModal({ title: t('sys.api.successTip'), content: successMsg });
|
||||||
|
} else if (options.successMessageMode === 'message') {
|
||||||
|
createMessage.success(successMsg);
|
||||||
|
}
|
||||||
|
if(data.data.rows){
|
||||||
|
return data.data.rows
|
||||||
|
}else{
|
||||||
|
return data.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// 在此处根据自己项目的实际情况对不同的code执行不同的操作
|
||||||
|
// 如果不希望中断当前请求,请return数据,否则直接抛出异常即可
|
||||||
|
let timeoutMsg = '';
|
||||||
|
switch (code) {
|
||||||
|
case ResultEnum.TIMEOUT:
|
||||||
|
timeoutMsg = t('sys.api.timeoutMessage');
|
||||||
|
const userStore = useUserStoreWithOut();
|
||||||
|
userStore.logout(true);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (message) {
|
||||||
|
timeoutMsg = message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// errorMessageMode='modal'的时候会显示modal错误弹窗,而不是消息提示,用于一些比较重要的错误
|
||||||
|
// errorMessageMode='none' 一般是调用时明确表示不希望自动弹出错误提示
|
||||||
|
if (options.errorMessageMode === 'modal') {
|
||||||
|
createErrorModal({ title: t('sys.api.errorTip'), content: timeoutMsg });
|
||||||
|
} else if (options.errorMessageMode === 'message') {
|
||||||
|
createMessage.error(timeoutMsg);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Error(timeoutMsg || t('sys.api.apiRequestFailed'));
|
||||||
|
},
|
||||||
|
|
||||||
|
// 请求之前处理config
|
||||||
|
beforeRequestHook: (config, options) => {
|
||||||
|
const { lrApi, joinPrefix, joinParamsToUrl, formatDate, joinTime = true, urlPrefix } = options;
|
||||||
|
|
||||||
|
if (joinPrefix) {
|
||||||
|
config.url = `${urlPrefix}${config.url}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lrApi && isString(lrApi)) {
|
||||||
|
config.url = `${lrApi}${config.url}`;
|
||||||
|
}
|
||||||
|
const params = config.params || {};
|
||||||
|
const data = config.data || false;
|
||||||
|
formatDate && data && !isString(data) && formatRequestDate(data);
|
||||||
|
if (config.method?.toUpperCase() === RequestEnum.GET) {
|
||||||
|
if (!isString(params)) {
|
||||||
|
// 给 get 请求加上时间戳参数,避免从缓存中拿数据。
|
||||||
|
config.params = Object.assign(params || {}, joinTimestamp(joinTime, false));
|
||||||
|
} else {
|
||||||
|
// 兼容restful风格
|
||||||
|
config.url = config.url + params + `${joinTimestamp(joinTime, true)}`;
|
||||||
|
config.params = undefined;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!isString(params)) {
|
||||||
|
formatDate && formatRequestDate(params);
|
||||||
|
if (
|
||||||
|
Reflect.has(config, 'data') &&
|
||||||
|
config.data &&
|
||||||
|
(Object.keys(config.data).length > 0 || config.data instanceof FormData)
|
||||||
|
) {
|
||||||
|
config.data = data;
|
||||||
|
config.params = params;
|
||||||
|
} else {
|
||||||
|
// 非GET请求如果没有提供data,则将params视为data
|
||||||
|
config.data = params;
|
||||||
|
config.params = undefined;
|
||||||
|
}
|
||||||
|
if (joinParamsToUrl) {
|
||||||
|
config.url = setObjToUrlParams(
|
||||||
|
config.url as string,
|
||||||
|
Object.assign({}, config.params, config.data),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 兼容restful风格
|
||||||
|
config.url = config.url + params;
|
||||||
|
config.params = undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return config;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description: 请求拦截器处理
|
||||||
|
*/
|
||||||
|
requestInterceptors: (config, options) => {
|
||||||
|
// 请求之前处理config
|
||||||
|
const token = getToken();
|
||||||
|
if (token && (config as Recordable)?.requestOptions?.withToken !== false) {
|
||||||
|
// jwt token
|
||||||
|
(config as Recordable).headers.Authorization = options.authenticationScheme
|
||||||
|
? `${options.authenticationScheme} ${token}`
|
||||||
|
: token;
|
||||||
|
config.headers['X-Token'] = token;
|
||||||
|
}
|
||||||
|
return config;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description: 响应拦截器处理
|
||||||
|
*/
|
||||||
|
responseInterceptors: (res: AxiosResponse<any>) => {
|
||||||
|
return res;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description: 响应错误处理
|
||||||
|
*/
|
||||||
|
responseInterceptorsCatch: (axiosInstance: AxiosInstance, error: any) => {
|
||||||
|
const { t } = useI18n();
|
||||||
|
const errorLogStore = useErrorLogStoreWithOut();
|
||||||
|
errorLogStore.addAjaxErrorInfo(error);
|
||||||
|
const { response, code, message, config } = error || {};
|
||||||
|
const errorMessageMode = config?.requestOptions?.errorMessageMode || 'none';
|
||||||
|
const msg: string = response?.data?.error?.message ?? '';
|
||||||
|
const err: string = error?.toString?.() ?? '';
|
||||||
|
let errMessage = '';
|
||||||
|
|
||||||
|
if (axios.isCancel(error)) {
|
||||||
|
return Promise.reject(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (code === 'ECONNABORTED' && message.indexOf('timeout') !== -1) {
|
||||||
|
errMessage = t('sys.api.apiTimeoutMessage');
|
||||||
|
}
|
||||||
|
if (err?.includes('Network Error')) {
|
||||||
|
errMessage = t('sys.api.networkExceptionMsg');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (errMessage) {
|
||||||
|
if (errorMessageMode === 'modal') {
|
||||||
|
createErrorModal({ title: t('sys.api.errorTip'), content: errMessage });
|
||||||
|
} else if (errorMessageMode === 'message') {
|
||||||
|
createMessage.error(errMessage);
|
||||||
|
}
|
||||||
|
return Promise.reject(error);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
throw new Error(error as unknown as string);
|
||||||
|
}
|
||||||
|
|
||||||
|
checkStatus(error?.response?.status, msg, errorMessageMode);
|
||||||
|
|
||||||
|
// 添加自动重试机制 保险起见 只针对GET请求
|
||||||
|
const retryRequest = new AxiosRetry();
|
||||||
|
const { isOpenRetry } = config.requestOptions.retryRequest;
|
||||||
|
config.method?.toUpperCase() === RequestEnum.GET &&
|
||||||
|
isOpenRetry &&
|
||||||
|
// @ts-ignore
|
||||||
|
retryRequest.retry(axiosInstance, error);
|
||||||
|
return Promise.reject(error);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
function createAxios(opt?: Partial<CreateAxiosOptions>) {
|
||||||
|
return new VAxios(
|
||||||
|
// 深度合并
|
||||||
|
deepMerge(
|
||||||
|
{
|
||||||
|
// See https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication#authentication_schemes
|
||||||
|
// authentication schemes,e.g: Bearer
|
||||||
|
// authenticationScheme: 'Bearer',
|
||||||
|
authenticationScheme: '',
|
||||||
|
timeout: 10 * 1000,
|
||||||
|
// 基础接口地址
|
||||||
|
// baseURL: globSetting.lrApi,
|
||||||
|
|
||||||
|
headers: {
|
||||||
|
'Content-Type': ContentTypeEnum.JSON,
|
||||||
|
// 'T-Token':getToken()
|
||||||
|
'Token':"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE3MDk4NTc4MjMsImV4cCI6MTcwOTkwMTAyMywiVXNlcklkIjoiU3lzdGVtIiwiVXNlck5hbWUiOiLotoXnuqfnrqHnkIblkZgiLCJBY2NvdW50IjoiU3lzdGVtIn0.U2mHpvl4cx81XRP4JRmwrUg0dSXNkFv_EXSJQI1mtLI"
|
||||||
|
},
|
||||||
|
// 如果是form-data格式
|
||||||
|
// headers: { 'Content-Type': ContentTypeEnum.FORM_URLENCODED },
|
||||||
|
// 数据处理方式
|
||||||
|
transform: clone(transform),
|
||||||
|
// 配置项,下面的选项都可以在独立的接口请求中覆盖
|
||||||
|
requestOptions: {
|
||||||
|
// 默认将prefix 添加到url
|
||||||
|
joinPrefix: true,
|
||||||
|
// 是否返回原生响应头 比如:需要获取响应头时使用该属性
|
||||||
|
isReturnNativeResponse: false,
|
||||||
|
// 需要对返回数据进行处理
|
||||||
|
isTransformResponse: true,
|
||||||
|
// post请求的时候添加参数到url
|
||||||
|
joinParamsToUrl: false,
|
||||||
|
// 格式化提交参数时间
|
||||||
|
formatDate: true,
|
||||||
|
// 消息提示类型
|
||||||
|
errorMessageMode: 'message',
|
||||||
|
// 接口地址
|
||||||
|
lrApi: globSetting.lrApi,
|
||||||
|
// 接口拼接地址
|
||||||
|
urlPrefix: urlPrefix,
|
||||||
|
// 是否加入时间戳
|
||||||
|
joinTime: true,
|
||||||
|
// 忽略重复请求
|
||||||
|
ignoreCancelToken: true,
|
||||||
|
// 是否携带token
|
||||||
|
withToken: true,
|
||||||
|
retryRequest: {
|
||||||
|
isOpenRetry: true,
|
||||||
|
count: 5,
|
||||||
|
waitTime: 100,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
opt || {},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
export const defHttp = createAxios();
|
||||||
|
|
||||||
|
// other api url
|
||||||
|
// export const otherHttp = createAxios({
|
||||||
|
// requestOptions: {
|
||||||
|
// lrApi: 'xxx',
|
||||||
|
// urlPrefix: 'xxx',
|
||||||
|
// },
|
||||||
|
// });
|
||||||
|
|
@ -0,0 +1,42 @@
|
||||||
|
<template>
|
||||||
|
<BasicModal
|
||||||
|
v-bind="$attrs"
|
||||||
|
@register="registerModal"
|
||||||
|
:canFullscreen="false"
|
||||||
|
:defaultFullscreen="true"
|
||||||
|
:showCancelBtn="false"
|
||||||
|
:showOkBtn="false"
|
||||||
|
:draggable="false"
|
||||||
|
title="慧创 表单设计"
|
||||||
|
>
|
||||||
|
<div class="form-box">
|
||||||
|
<FormPage />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</BasicModal>
|
||||||
|
</template>
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref, computed, unref } from 'vue';
|
||||||
|
|
||||||
|
import { BasicModal, useModalInner } from '/@/components/Modal';
|
||||||
|
import FormPage from './form/index.vue';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
defineOptions({ name: 'FormModal' });
|
||||||
|
|
||||||
|
const emit = defineEmits(['success', 'register']);
|
||||||
|
const [registerModal, { closeModal, setModalProps }] = useModalInner();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</script>
|
||||||
|
<style lang="less">
|
||||||
|
.form-box{
|
||||||
|
width: 100%;
|
||||||
|
height: calc(100% - 55px);
|
||||||
|
position:fixed;
|
||||||
|
top:55px;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,95 @@
|
||||||
|
<template>
|
||||||
|
<div class="m-4 mr-0 overflow-hidden bg-white">
|
||||||
|
<BasicTree ref="asyncExpandTreeRef" title="菜单列表" toolbar search
|
||||||
|
treeWrapperClassName="h-[calc(100%-35px)] overflow-auto" loadData :actionList="actionList"
|
||||||
|
:renderIcon="createIcon" :clickRowToExpand="false" :treeData="treeData" :fieldNames="{ key: 'id', title: 'name' }"
|
||||||
|
:defaultExpandAll="true" @select="handleSelect" />
|
||||||
|
<BasicModal @register="register" title="删除" :helpMessage="['提示1', '提示2']" @ok="handleSubmit">
|
||||||
|
确认要删除菜单吗?
|
||||||
|
</BasicModal>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { onMounted, ref, h, nextTick, unref } from 'vue';
|
||||||
|
import { BasicTree, TreeItem, TreeActionItem } from '@/components/Tree';
|
||||||
|
import { getMenuList, deleteMenu } from '@/api/demo/system';
|
||||||
|
import { FormOutlined, DeleteOutlined } from '@ant-design/icons-vue';
|
||||||
|
import { BasicModal, useModal } from '@/components/Modal';
|
||||||
|
import { router } from '@/router';
|
||||||
|
const [register, { closeModal, openModal }] = useModal();
|
||||||
|
defineOptions({ name: 'DeptTree' });
|
||||||
|
|
||||||
|
const emit = defineEmits(['select', 'edit']);
|
||||||
|
|
||||||
|
const treeData = ref < TreeItem[] > ([]);
|
||||||
|
let selectItemId = ref('')
|
||||||
|
const asyncExpandTreeRef = ref < Nullable < TreeActionType >> (null);
|
||||||
|
|
||||||
|
async function handleSubmit() {
|
||||||
|
var query = [selectItemId.value]
|
||||||
|
const data = await deleteMenu(query);
|
||||||
|
closeModal();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
async function fetch() {
|
||||||
|
treeData.value = (await getMenuList()) as unknown as TreeItem[];
|
||||||
|
// 展开全部
|
||||||
|
nextTick(() => {
|
||||||
|
unref(asyncExpandTreeRef)?.expandAll(true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleSelect(keys) {
|
||||||
|
emit('select', keys[0]);
|
||||||
|
}
|
||||||
|
const btnList = router.currentRoute.value.meta.elements
|
||||||
|
const actionList: TreeActionItem[] = []
|
||||||
|
btnList.forEach(element => {
|
||||||
|
if (element.domId == 'btnEdit') {
|
||||||
|
actionList.push({
|
||||||
|
render: (node) => {
|
||||||
|
return h(FormOutlined, {
|
||||||
|
class: 'ml-2',
|
||||||
|
onClick: () => {
|
||||||
|
emit('edit', node);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
})
|
||||||
|
} else if (element.domId == 'btnDelete') {
|
||||||
|
actionList.push({
|
||||||
|
render: (node) => {
|
||||||
|
return h(DeleteOutlined, {
|
||||||
|
class: 'ml-2',
|
||||||
|
onClick: () => {
|
||||||
|
selectItemId.value = node.id
|
||||||
|
openModal(true, {
|
||||||
|
isUpdate: false,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function createIcon({ level }) {
|
||||||
|
if (level === 1) {
|
||||||
|
return 'ion:git-compare-outline';
|
||||||
|
}
|
||||||
|
if (level === 2) {
|
||||||
|
return 'ion:home';
|
||||||
|
}
|
||||||
|
if (level === 3) {
|
||||||
|
return 'ion:airplane';
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
onMounted(() => {
|
||||||
|
fetch();
|
||||||
|
});
|
||||||
|
defineExpose({
|
||||||
|
fetch
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
@ -0,0 +1,49 @@
|
||||||
|
import { BasicColumn, FormSchema } from '@/components/Table';
|
||||||
|
import { h } from 'vue';
|
||||||
|
import { Tag } from 'ant-design-vue';
|
||||||
|
|
||||||
|
export const columns: BasicColumn[] = [
|
||||||
|
|
||||||
|
{
|
||||||
|
title: '名称',
|
||||||
|
dataIndex: 'f_Name',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '分类',
|
||||||
|
dataIndex: 'f_Category_Name',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '类型',
|
||||||
|
dataIndex: 'status',
|
||||||
|
width: 80,
|
||||||
|
customRender: ({ record }) => {
|
||||||
|
const status = record.f_FormType;
|
||||||
|
const enable = ~~status === 0;
|
||||||
|
const color = enable ? '#67c23a' : '#e6a23c';
|
||||||
|
const text = enable ? '常规表单' : '视图表单';
|
||||||
|
return h(Tag, { color: color }, () => text);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '创建人',
|
||||||
|
dataIndex: 'f_CreateUserName'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '创建时间',
|
||||||
|
dataIndex: 'f_CreateDate'
|
||||||
|
},
|
||||||
|
// {
|
||||||
|
// title: '备注',
|
||||||
|
// dataIndex: 'remark',
|
||||||
|
// },
|
||||||
|
];
|
||||||
|
|
||||||
|
export const searchFormSchema: FormSchema[] = [
|
||||||
|
{
|
||||||
|
field: 'key',
|
||||||
|
label: '关键字',
|
||||||
|
component: 'Input',
|
||||||
|
colProps: { span: 8 },
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
|
@ -0,0 +1,802 @@
|
||||||
|
<template>
|
||||||
|
<div class="l-rblock" >
|
||||||
|
<div v-show="steps(0)" class="l-rblock" style="padding:24px;" >
|
||||||
|
<div class="l-page-panel" >
|
||||||
|
<el-form :model="formData" :rules="rules" size="mini" ref="baseInfo" label-width="88px" >
|
||||||
|
<el-col :span="24">
|
||||||
|
<el-form-item :label="$t('名称')" prop="f_Name">
|
||||||
|
<el-input v-model="formData.f_Name"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="24">
|
||||||
|
<el-form-item :label="$t('分类')" prop="f_Category">
|
||||||
|
<l-tree-select
|
||||||
|
v-model="formData.f_Category"
|
||||||
|
:placeholder="$t('请选择')"
|
||||||
|
:options="lr_dataItemTree(lr_dataItem['FormSort'])"
|
||||||
|
|
||||||
|
>
|
||||||
|
</l-tree-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="24">
|
||||||
|
<el-form-item :label="$t('数据库')" prop="f_DbCode">
|
||||||
|
<el-select v-model="formData.f_DbCode" :placeholder="$t('请选择')">
|
||||||
|
<el-option-group
|
||||||
|
v-for="group in lr_dblinkTree"
|
||||||
|
:key="group.id"
|
||||||
|
:label="group.label">
|
||||||
|
<el-option
|
||||||
|
v-for="item in group.children"
|
||||||
|
:key="item.id"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.id">
|
||||||
|
</el-option>
|
||||||
|
</el-option-group>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="24">
|
||||||
|
<el-form-item :label="$t('状态')" prop="f_EnabledMark">
|
||||||
|
<el-switch
|
||||||
|
:active-value="1"
|
||||||
|
:inactive-value="0"
|
||||||
|
v-model="formData.f_EnabledMark"
|
||||||
|
>
|
||||||
|
</el-switch>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="24">
|
||||||
|
<el-form-item :label="$t('类型')" prop="f_FormType" >
|
||||||
|
<l-radio
|
||||||
|
:options="[{value:0,label:$t('常规表单')},{value:1,label:$t('视图表单')}]"
|
||||||
|
v-model="formData.f_FormType"
|
||||||
|
|
||||||
|
@change="handleFormTypeChange"
|
||||||
|
>
|
||||||
|
</l-radio>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="24">
|
||||||
|
<el-form-item :label="$t('描述')" prop="f_Description">
|
||||||
|
<el-input type="textarea" v-model="formData.f_Description"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-form>
|
||||||
|
<template v-if="formData.f_FormType != 1" >
|
||||||
|
<el-col :span="24">
|
||||||
|
<div class="l-title" >{{$t('添加数据库表(请先选择数据库)')}}</div>
|
||||||
|
</el-col>
|
||||||
|
<el-col :key="1" :span="24">
|
||||||
|
<l-edit-table
|
||||||
|
addBtnText="添加"
|
||||||
|
:dataSource="dbTableData"
|
||||||
|
|
||||||
|
@addRow="addRow"
|
||||||
|
@deleteRow="deleteRow"
|
||||||
|
>
|
||||||
|
<el-table-column
|
||||||
|
prop="type"
|
||||||
|
:label="$t('类别')"
|
||||||
|
width="64"
|
||||||
|
align="center"
|
||||||
|
>
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-tag v-if="scope.row.type == 'main'" size="mini" >主表</el-tag>
|
||||||
|
<el-tag @click="chlidTagClick(scope.row)" v-else size="mini" style="cursor: pointer;" type="warning">子表</el-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
prop="name"
|
||||||
|
:label="$t('表名')"
|
||||||
|
minWidth="100">
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
prop="field"
|
||||||
|
:label="$t('外键')"
|
||||||
|
minWidth="100">
|
||||||
|
<template v-if="scope.row.type != 'main' " slot-scope="scope">
|
||||||
|
<el-select size="mini" v-model="scope.row.field" :placeholder="$t('请选择')">
|
||||||
|
<el-option
|
||||||
|
v-for="item in scope.row.columns || []"
|
||||||
|
:key="item.name"
|
||||||
|
:label="item.name"
|
||||||
|
:value="item.name">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
prop="relationName"
|
||||||
|
:label="$t('关联表')"
|
||||||
|
minWidth="100">
|
||||||
|
<template v-if="scope.row.type != 'main' " slot-scope="scope">
|
||||||
|
<el-select size="mini" v-model="scope.row.relationName" :placeholder="$t('请选择')">
|
||||||
|
<el-option
|
||||||
|
v-for="item in relationTables(scope.row.name)"
|
||||||
|
:key="item.name"
|
||||||
|
:label="item.name"
|
||||||
|
:value="item.name">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
prop="relationField"
|
||||||
|
:label="$t('关联主键')"
|
||||||
|
minWidth="100">
|
||||||
|
<template v-if="scope.row.type != 'main' && scope.row.relationName " slot-scope="scope">
|
||||||
|
<el-select size="mini" v-model="scope.row.relationField" :placeholder="$t('请选择')">
|
||||||
|
<el-option
|
||||||
|
v-for="item in relationTableFields(scope.row.relationName)"
|
||||||
|
:key="item.name"
|
||||||
|
:label="item.name"
|
||||||
|
:value="item.name">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</l-edit-table >
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="24">
|
||||||
|
<div class="l-title" >{{$t('添加数据库关联表,只用来做数据权限设置(请先选择数据库)')}}</div>
|
||||||
|
</el-col>
|
||||||
|
<el-col :key="2" :span="24">
|
||||||
|
<l-edit-table
|
||||||
|
addBtnText="添加"
|
||||||
|
:dataSource="dbTableRData"
|
||||||
|
|
||||||
|
@addRow="addDbTableRData"
|
||||||
|
@deleteRow="deleteDbTableRData"
|
||||||
|
>
|
||||||
|
<el-table-column
|
||||||
|
prop="fname"
|
||||||
|
:label="$t('名称')"
|
||||||
|
minWidth="160" >
|
||||||
|
<template slot-scope="scope" >
|
||||||
|
<el-input size="mini" v-model="scope.row.fname" ></el-input>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
prop="name"
|
||||||
|
:label="$t('表名')"
|
||||||
|
minWidth="160">
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
prop="cfield"
|
||||||
|
:label="$t('比较字段')"
|
||||||
|
minWidth="160">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-select size="mini" v-model="scope.row.cfield" :placeholder="$t('请选择')">
|
||||||
|
<el-option
|
||||||
|
v-for="item in scope.row.columns || []"
|
||||||
|
:key="item.name"
|
||||||
|
:label="item.name"
|
||||||
|
:value="item.name">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
prop="field"
|
||||||
|
:label="$t('外键')"
|
||||||
|
minWidth="160">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-select size="mini" v-model="scope.row.field" :placeholder="$t('请选择')">
|
||||||
|
<el-option
|
||||||
|
v-for="item in scope.row.columns || []"
|
||||||
|
:key="item.name"
|
||||||
|
:label="item.name"
|
||||||
|
:value="item.name">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
prop="relationName"
|
||||||
|
:label="$t('关联表')"
|
||||||
|
minWidth="160">
|
||||||
|
<template v-if="scope.row.type != 'main' " slot-scope="scope">
|
||||||
|
<el-select size="mini" v-model="scope.row.relationName" :placeholder="$t('请选择')">
|
||||||
|
<el-option
|
||||||
|
v-for="item in dbTableData"
|
||||||
|
:key="item.name"
|
||||||
|
:label="item.name"
|
||||||
|
:value="item.name">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
prop="relationField"
|
||||||
|
:label="$t('关联主键')"
|
||||||
|
minWidth="160">
|
||||||
|
<template v-if="scope.row.relationName " slot-scope="scope">
|
||||||
|
<el-select size="mini" v-model="scope.row.relationField" :placeholder="$t('请选择')">
|
||||||
|
<el-option
|
||||||
|
v-for="item in relationTableFields(scope.row.relationName)"
|
||||||
|
:key="item.name"
|
||||||
|
:label="item.name"
|
||||||
|
:value="item.name">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</l-edit-table >
|
||||||
|
</el-col>
|
||||||
|
</template>
|
||||||
|
<template v-else >
|
||||||
|
<el-col :span="24">
|
||||||
|
<div class="l-title" >{{$t('添加数据视图(请先选择数据库)')}}</div>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="24">
|
||||||
|
<l-edit-table
|
||||||
|
addBtnText="添加"
|
||||||
|
|
||||||
|
:dataSource="dbTableData"
|
||||||
|
|
||||||
|
@addRow="addSqlData"
|
||||||
|
@deleteRow="deleteSqlData"
|
||||||
|
>
|
||||||
|
|
||||||
|
<el-table-column
|
||||||
|
prop="type"
|
||||||
|
:label="$t('类别')"
|
||||||
|
width="64"
|
||||||
|
align="center"
|
||||||
|
>
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-tag v-if="scope.row.type == 'main'" size="mini" >主</el-tag>
|
||||||
|
<el-tag v-else size="mini" type="warning">子</el-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
prop="name"
|
||||||
|
:label="$t('名称')"
|
||||||
|
minWidth="160" >
|
||||||
|
<el-button type="text" slot-scope="scope" @click.stop="editSqlData(scope.row)" >{{scope.row.name}}</el-button>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
prop="relationField"
|
||||||
|
:label="$t('关联字段')"
|
||||||
|
minWidth="160" >
|
||||||
|
<el-select v-if="scope.row.type != 'main'" slot-scope="scope" size="mini" v-model="scope.row.relationField" placeholder="请选择">
|
||||||
|
<el-option
|
||||||
|
v-for="item in sqlMainCols || []"
|
||||||
|
:key="item.name"
|
||||||
|
:label="item.name"
|
||||||
|
:value="item.name">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-table-column>
|
||||||
|
</l-edit-table>
|
||||||
|
</el-col>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-show="steps(1)" class="l-rblock" >
|
||||||
|
<l-form-design
|
||||||
|
:dbTables="dbTableData"
|
||||||
|
ref="formDesign"
|
||||||
|
></l-form-design>
|
||||||
|
</div>
|
||||||
|
<l-codetable-selectdialog
|
||||||
|
:visible.sync="dbtableSelectdialog"
|
||||||
|
:dbCode="formData.f_DbCode"
|
||||||
|
:isOkClose="false"
|
||||||
|
@select="dbSelect"
|
||||||
|
>
|
||||||
|
</l-codetable-selectdialog>
|
||||||
|
|
||||||
|
<l-dialog
|
||||||
|
:title="sqlDialogTitle"
|
||||||
|
:visible.sync="addSqlDialog"
|
||||||
|
|
||||||
|
:width="640"
|
||||||
|
|
||||||
|
@ok="sqlDialogSave"
|
||||||
|
@closed="sqlDialogClosed"
|
||||||
|
@opened="sqlDialogOpened"
|
||||||
|
|
||||||
|
>
|
||||||
|
<sql-form ref="sqlForm" ></sql-form>
|
||||||
|
</l-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
const apiScheme = window.$api.custmerForm.scheme
|
||||||
|
const apiCodeTable = window.$api.data.codeTable
|
||||||
|
|
||||||
|
import SqlForm from './sqlForm.vue'
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
stepActive:{
|
||||||
|
type:Number,
|
||||||
|
default:0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
components:{
|
||||||
|
SqlForm
|
||||||
|
},
|
||||||
|
data(){
|
||||||
|
return {
|
||||||
|
formData:{
|
||||||
|
f_Name:'',
|
||||||
|
f_Category:'',
|
||||||
|
f_DbCode:'',
|
||||||
|
f_EnabledMark:1,
|
||||||
|
f_FormType:0,
|
||||||
|
f_Description:''
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
f_Name: [
|
||||||
|
{ required: true, message: this.$t('请输入'), trigger: 'blur' },
|
||||||
|
],
|
||||||
|
f_Category: [
|
||||||
|
{ required: true, message: this.$t('请选择'), trigger: 'change' }
|
||||||
|
],
|
||||||
|
f_DbCode: [
|
||||||
|
{ required: true, message: this.$t('请选择'), trigger: 'change' }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
dbTableData:[],
|
||||||
|
dbtableSelectdialog:false,
|
||||||
|
|
||||||
|
dbTableRData:[], // 关联表数据用于数据权限
|
||||||
|
isAddDbTableRData:false,
|
||||||
|
|
||||||
|
addSqlDialog:false,
|
||||||
|
editSql:false,
|
||||||
|
sqlDialogTitle:'',
|
||||||
|
sqlDialogRow:null,
|
||||||
|
|
||||||
|
isNotFetchTables:false,
|
||||||
|
tableColumns:{} // 缓存列信息
|
||||||
|
|
||||||
|
};
|
||||||
|
},
|
||||||
|
created () {
|
||||||
|
this.initData()
|
||||||
|
},
|
||||||
|
computed:{
|
||||||
|
sqlMainCols(){
|
||||||
|
const table = this.dbTableData.find(t=>t.type == 'main')
|
||||||
|
return table.columns
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods:{
|
||||||
|
initData(){
|
||||||
|
this.lr_loadDblink()
|
||||||
|
},
|
||||||
|
async dbSelect(list,showLoading, hideLoading){
|
||||||
|
showLoading()
|
||||||
|
const tableList = []
|
||||||
|
const notAddTable = []
|
||||||
|
list.forEach(item => {
|
||||||
|
const table = {id:item.f_TableName,name:item.f_TableName,comment:item.f_Description,columns:[]}
|
||||||
|
// 加载表的列信息
|
||||||
|
if(this.tableColumns[table.name]){
|
||||||
|
table.columns = this.tableColumns[table.name]
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
tableList.push(table)
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this.isAddDbTableRData){
|
||||||
|
if(this.dbTableData.find(t => { return t.name == table.name }) == undefined){
|
||||||
|
this.dbTableRData.push(table)
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
notAddTable.push(table.name)
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
if(this.dbTableData.length == 0){
|
||||||
|
table.type = 'main'
|
||||||
|
this.dbTableData.push(table)
|
||||||
|
}
|
||||||
|
else if(this.dbTableData.find(t => { return t.name == table.name }) == undefined){
|
||||||
|
table.type = 'chlid'
|
||||||
|
this.dbTableData.push(table)
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
notAddTable.push(table.name)
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if(tableList.length > 0 ){
|
||||||
|
const codeTables = await this.$awaitWraper(apiCodeTable.getList(this.formData.f_DbCode,String(tableList.map(t=>t.name))))
|
||||||
|
for(const tableItem of tableList){
|
||||||
|
const codeTable = codeTables.find(t=>t.lr_db_codetableEntity.f_TableName == tableItem.name)
|
||||||
|
tableItem.columns = codeTable.lr_db_codecolumnsList.map(t=>({
|
||||||
|
name:t.f_DbColumnName,
|
||||||
|
csType:t.f_CsType,
|
||||||
|
isIdentity:t.f_IsIdentity == 1,
|
||||||
|
isPrimary:t.f_IsPrimaryKey == 1,
|
||||||
|
isNullable:t.f_IsNullable == 1,
|
||||||
|
coment:t.f_Description
|
||||||
|
}))
|
||||||
|
|
||||||
|
this.tableColumns[tableItem.name] = tableItem.columns
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(notAddTable.length > 0){
|
||||||
|
if(this.isAddDbTableRData){
|
||||||
|
this.$message({
|
||||||
|
message: `不能是表单已经绑定的表【${String(notAddTable)}】`,
|
||||||
|
type: 'warning'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
this.$message({
|
||||||
|
message: `重复添加表【${String(notAddTable)}】`,
|
||||||
|
type: 'warning'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.dbtableSelectdialog = false
|
||||||
|
|
||||||
|
hideLoading()
|
||||||
|
},
|
||||||
|
chlidTagClick(row){
|
||||||
|
this.dbTableData.find(t => { return t.type == 'main' }).type = 'chlid';
|
||||||
|
row.type = 'main';
|
||||||
|
this.$set(this.dbTableData, 0, this.dbTableData[0])
|
||||||
|
},
|
||||||
|
addRow(){
|
||||||
|
this.isAddDbTableRData = false
|
||||||
|
if(this.formData.f_DbCode){
|
||||||
|
this.dbtableSelectdialog = true;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
this.$message({
|
||||||
|
message: '请选择数据库',
|
||||||
|
type: 'warning'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
deleteRow(data){
|
||||||
|
this.dbTableData.splice(data.index,1);
|
||||||
|
if(data.row.type == 'main' && this.dbTableData.length > 0){
|
||||||
|
this.dbTableData[0].type = 'main';
|
||||||
|
this.$set(this.dbTableData, 0, this.dbTableData[0]);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
relationTables(myName){
|
||||||
|
let list = [];
|
||||||
|
this.dbTableData.forEach(item =>{
|
||||||
|
if(item.name != myName){
|
||||||
|
list.push(item);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return list;
|
||||||
|
},
|
||||||
|
relationTableFields(tableName){
|
||||||
|
const table = this.dbTableData.find(t => { return t.name == tableName }) || {}
|
||||||
|
return table.columns || []
|
||||||
|
},
|
||||||
|
|
||||||
|
addDbTableRData(){
|
||||||
|
this.isAddDbTableRData = true
|
||||||
|
if(this.formData.f_DbCode){
|
||||||
|
this.dbtableSelectdialog = true
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
this.$message({
|
||||||
|
message: '请选择数据库',
|
||||||
|
type: 'warning'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
deleteDbTableRData(data){
|
||||||
|
this.dbTableRData.splice(data.index,1)
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
validateSteps(){
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
if(this.stepActive == 0){
|
||||||
|
// 判断基础信息是否填写完整
|
||||||
|
this.validateBaseInfo().then(res=>{
|
||||||
|
resolve(res)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
resolve(true)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
steps(num){
|
||||||
|
return this.stepActive == num
|
||||||
|
},
|
||||||
|
validateBaseInfo(){
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
this.$refs.baseInfo.validate((valid) => {
|
||||||
|
if(valid){
|
||||||
|
if(this.isNotFetchTables){
|
||||||
|
this.$message({
|
||||||
|
type: 'error',
|
||||||
|
message: '请将数据表的对象导入,点击数据表添加按钮,导入表重新编辑页面!'
|
||||||
|
})
|
||||||
|
resolve(false)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this.dbTableData.length > 0){
|
||||||
|
if(this.formData.f_FormType != 1){
|
||||||
|
if(this.dbTableData.find(t=>t.type != 'main' && (this.$validatenull(t.field) || this.$validatenull(t.relationName) || this.$validatenull(t.relationField))) != undefined){
|
||||||
|
this.$message({
|
||||||
|
type: 'error',
|
||||||
|
message: '请完善数据库表信息!'
|
||||||
|
})
|
||||||
|
resolve(false)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
if(this.dbTableData.find(t=>t.type != 'main' && this.$validatenull(t.relationField)) != undefined){
|
||||||
|
this.$message({
|
||||||
|
type: 'error',
|
||||||
|
message: '请完善子试图和主视图关联!'
|
||||||
|
});
|
||||||
|
resolve(false)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
this.$message({
|
||||||
|
type: 'error',
|
||||||
|
message: this.formData.f_FormType != 1? '请添加数据库表!':'请添加视图语句'
|
||||||
|
});
|
||||||
|
resolve(false)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this.dbTableRData.length > 0){
|
||||||
|
if(this.dbTableRData.find(t=>this.$validatenull(t.fname) || this.$validatenull(t.cfield) || this.$validatenull(t.field) || this.$validatenull(t.relationName) || this.$validatenull(t.relationField)) != undefined){
|
||||||
|
this.$message({
|
||||||
|
type: 'error',
|
||||||
|
message: '请完善数据库关联表信息!'
|
||||||
|
});
|
||||||
|
resolve(false)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.$nextTick(()=>{
|
||||||
|
this.$refs.formDesign.updateTable()
|
||||||
|
})
|
||||||
|
|
||||||
|
resolve(true)
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
resolve(false)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
resetForm(){
|
||||||
|
this.$refs.formDesign.clear()
|
||||||
|
this.$formClear(this.$refs.baseInfo)
|
||||||
|
this.isNotFetchTables = false
|
||||||
|
this.dbTableData = []
|
||||||
|
this.dbTableRData = []
|
||||||
|
this.tableColumns = {}
|
||||||
|
},
|
||||||
|
validateForm(){
|
||||||
|
return this.$refs.formDesign.validate()
|
||||||
|
},
|
||||||
|
async setForm(id){
|
||||||
|
const data = await this.$awaitWraper(apiScheme.get(id))
|
||||||
|
if(data){
|
||||||
|
let scheme = JSON.parse(data.scheme.f_Scheme)
|
||||||
|
data.info.f_DbCode = scheme.dbCode
|
||||||
|
this.formData = data.info
|
||||||
|
this.dbTableData = scheme.db
|
||||||
|
this.dbTableRData = scheme.rdb || []
|
||||||
|
|
||||||
|
if(this.formData.f_FormType != 1){
|
||||||
|
let tableNames = []
|
||||||
|
tableNames.push(...this.dbTableData.map(t=>t.name))
|
||||||
|
tableNames.push(...this.dbTableRData.map(t=>t.name))
|
||||||
|
|
||||||
|
tableNames = this.$unique(tableNames)
|
||||||
|
// 加载表数据
|
||||||
|
const codeTables = await this.$awaitWraper(apiCodeTable.getList(scheme.dbCode,String(tableNames)))
|
||||||
|
// 新版本加入数据模型这个概念,表单设计模版里不保存列的信息
|
||||||
|
// 当数据对象被改变时会直接影响到表单
|
||||||
|
if(codeTables.length < tableNames.length ){
|
||||||
|
// 表示部分数据表没有加载到,需要导入或添加
|
||||||
|
this.isNotFetchTables = true
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
const tableList = [...this.dbTableData,...this.dbTableRData]
|
||||||
|
for(const table of tableList){
|
||||||
|
const codeTable = codeTables.find(t=>t.lr_db_codetableEntity.f_TableName == table.name)
|
||||||
|
|
||||||
|
table.columns = codeTable.lr_db_codecolumnsList.map(t=>({
|
||||||
|
name:t.f_DbColumnName,
|
||||||
|
csType:t.f_CsType,
|
||||||
|
isIdentity:t.f_IsIdentity == 1,
|
||||||
|
isPrimary:t.f_IsPrimaryKey == 1,
|
||||||
|
isNullable:t.f_IsNullable == 1,
|
||||||
|
coment:t.f_Description
|
||||||
|
}))
|
||||||
|
|
||||||
|
this.tableColumns[table.name] = table.columns
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.$refs.formDesign.setData(scheme.formInfo)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
this.$message({
|
||||||
|
message: '数据加载失败',
|
||||||
|
type: 'warning'
|
||||||
|
})
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
},
|
||||||
|
getForm(isDraft){
|
||||||
|
const db = []
|
||||||
|
const rdb = []
|
||||||
|
let primaryKey = ''
|
||||||
|
if(this.formData.f_FormType != 1){
|
||||||
|
// 普通表单
|
||||||
|
const mainTable = this.dbTableData.find(t=>t.type == 'main')
|
||||||
|
const primaryKeyObj = mainTable.columns.find(t=>t.isPrimary)
|
||||||
|
if(primaryKeyObj){
|
||||||
|
primaryKey = primaryKeyObj.name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const dbTableData = this.$deepClone(this.dbTableData)
|
||||||
|
const dbTableRData = this.$deepClone(this.dbTableRData)
|
||||||
|
|
||||||
|
for(const item of dbTableData){
|
||||||
|
if(this.formData.f_FormType != 1){
|
||||||
|
delete item.columns
|
||||||
|
}
|
||||||
|
db.push(item)
|
||||||
|
}
|
||||||
|
for(const item of dbTableRData){
|
||||||
|
if(this.formData.f_FormType != 1){
|
||||||
|
delete item.columns
|
||||||
|
}
|
||||||
|
rdb.push(item)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
let scheme = {
|
||||||
|
dbCode:this.formData.f_DbCode,
|
||||||
|
db:db,
|
||||||
|
rdb:rdb,
|
||||||
|
primaryKey:primaryKey,
|
||||||
|
formInfo:this.$refs.formDesign.getData(),
|
||||||
|
formType:this.formData.f_FormType
|
||||||
|
}
|
||||||
|
let postData = {
|
||||||
|
info:this.$deepClone(this.formData),
|
||||||
|
scheme:{
|
||||||
|
F_Scheme:JSON.stringify(scheme),
|
||||||
|
F_Type:isDraft?2:1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return postData
|
||||||
|
},
|
||||||
|
|
||||||
|
handleFormTypeChange(){
|
||||||
|
this.dbTableData = []
|
||||||
|
this.dbTableRData = []
|
||||||
|
},
|
||||||
|
|
||||||
|
addSqlData(){// 添加试图语句
|
||||||
|
if(this.formData.f_DbCode){
|
||||||
|
this.editSql = false
|
||||||
|
this.sqlDialogTitle = '添加SQL'
|
||||||
|
this.addSqlDialog = true
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
this.$message({
|
||||||
|
message: '请选择数据库',
|
||||||
|
type: 'warning'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
editSqlData(row){
|
||||||
|
if(this.formData.f_DbCode){
|
||||||
|
this.editSql = true
|
||||||
|
this.sqlDialogRow = row
|
||||||
|
this.sqlDialogTitle = '编辑SQL'
|
||||||
|
this.addSqlDialog = true
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
this.$message({
|
||||||
|
message: '请选择数据库',
|
||||||
|
type: 'warning'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
deleteSqlData({index,row}){// 删除试图语句
|
||||||
|
if(row.type != 'main'){
|
||||||
|
this.dbTableData.splice(index,1)
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
this.$message({
|
||||||
|
message: '主语句无法删除',
|
||||||
|
type: 'warning'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async sqlDialogSave(showLoading,hideLoading){
|
||||||
|
showLoading('保存中...')
|
||||||
|
if(await this.$refs.sqlForm.validateForm()){
|
||||||
|
const data = this.$refs.sqlForm.getForm()
|
||||||
|
if(this.dbTableData.length != 0 && data.type != 'main'){
|
||||||
|
if(data.sql.indexOf('@param') == -1){
|
||||||
|
this.$message({
|
||||||
|
message: '请在语句中设置关联参数',
|
||||||
|
type: 'warning'
|
||||||
|
})
|
||||||
|
hideLoading()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加载列字段
|
||||||
|
const list = await this.$awaitWraper(apiScheme.geColnames(this.formData.f_DbCode,data.sql))
|
||||||
|
if(list == null){
|
||||||
|
hideLoading()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
data.columns = list.map(t=>{ return {name:t}})
|
||||||
|
|
||||||
|
if(this.editSql){
|
||||||
|
const index = this.dbTableData.findIndex(t=>t.id = data.id)
|
||||||
|
this.$set(this.dbTableData, index, data)
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
if(this.dbTableData.length == 0){
|
||||||
|
data.type = 'main'
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
data.type = 'chlid'
|
||||||
|
}
|
||||||
|
data.id = this.$uuid()
|
||||||
|
this.dbTableData.push(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.addSqlDialog = false
|
||||||
|
}
|
||||||
|
|
||||||
|
hideLoading()
|
||||||
|
},
|
||||||
|
sqlDialogClosed(){
|
||||||
|
this.$refs.sqlForm.resetForm()
|
||||||
|
},
|
||||||
|
sqlDialogOpened(){
|
||||||
|
if(this.editSql){
|
||||||
|
this.$refs.sqlForm.setForm(this.sqlDialogRow)
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
this.$refs.sqlForm.resetSql()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
<template>
|
||||||
|
<BasicTable @register="registerContanctTable">
|
||||||
|
<template #bodyCell="{ column, record }">
|
||||||
|
<template v-if="column.key === 'action'">
|
||||||
|
<TableAction :actions="[
|
||||||
|
{
|
||||||
|
label: '删除',
|
||||||
|
color: 'error',
|
||||||
|
popConfirm: {
|
||||||
|
title: '是否删除该数据',
|
||||||
|
confirm: handleDelete.bind(null, record),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
]" />
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
</BasicTable>
|
||||||
|
</template>
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { defineProps } from 'vue';
|
||||||
|
import { BasicTable, useTable, TableAction } from '@/components/Table';
|
||||||
|
import { columns } from './databasetable.data';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
let props = defineProps(["tabList"]);
|
||||||
|
|
||||||
|
console.log('props',props)
|
||||||
|
|
||||||
|
const [registerContanctTable, { reload, setTableData, getColumns }] = useTable({
|
||||||
|
title: '',
|
||||||
|
rowKey: 'id',
|
||||||
|
columns,
|
||||||
|
formConfig: {
|
||||||
|
labelWidth: 120,
|
||||||
|
},
|
||||||
|
useSearchForm: false,
|
||||||
|
showTableSetting: false,
|
||||||
|
bordered: false,
|
||||||
|
pagination: false,
|
||||||
|
actionColumn: {
|
||||||
|
width: 80,
|
||||||
|
title: '操作',
|
||||||
|
dataIndex: 'action',
|
||||||
|
fixed: undefined,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</script>
|
||||||
|
<style lang="less">
|
||||||
|
.form-box{
|
||||||
|
width: 100%;
|
||||||
|
height: calc(100% - 55px);
|
||||||
|
position:fixed;
|
||||||
|
top:55px;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,78 @@
|
||||||
|
<template>
|
||||||
|
<BasicModal
|
||||||
|
v-bind="$attrs"
|
||||||
|
@register="registerModal"
|
||||||
|
:canFullscreen="false"
|
||||||
|
:defaultFullscreen="false"
|
||||||
|
:maskClosable="false"
|
||||||
|
:width="800"
|
||||||
|
title="数据对象选择"
|
||||||
|
@ok="modalSuReClick"
|
||||||
|
>
|
||||||
|
<BasicTable @register="registerDataTable">
|
||||||
|
|
||||||
|
</BasicTable>
|
||||||
|
</BasicModal>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</template>
|
||||||
|
<script lang="ts" setup>
|
||||||
|
|
||||||
|
import { columns } from './dataobject.data';
|
||||||
|
import { BasicTable, useTable } from '@/components/Table';
|
||||||
|
import { getDataBaseTableList } from '@/api/formdesign/index';
|
||||||
|
import { BasicModal, useModalInner } from '/@/components/Modal';
|
||||||
|
|
||||||
|
const emit = defineEmits(['backrows']);
|
||||||
|
|
||||||
|
const [registerModal, { closeModal, setModalProps }] = useModalInner();
|
||||||
|
|
||||||
|
const [registerDataTable, { reload, getSelectRows }] = useTable({
|
||||||
|
title: '',
|
||||||
|
rowKey: 'f_Id',
|
||||||
|
api: getDataBaseTableList,
|
||||||
|
columns,
|
||||||
|
size: 'small',
|
||||||
|
rowSelection: {//多选框
|
||||||
|
type: 'checkbox',
|
||||||
|
// type: 'radio',
|
||||||
|
},
|
||||||
|
useSearchForm: false,
|
||||||
|
showTableSetting: false,
|
||||||
|
bordered: true,
|
||||||
|
pagination:{
|
||||||
|
pageSize: 10
|
||||||
|
},
|
||||||
|
beforeFetch: (data) => {
|
||||||
|
|
||||||
|
// 接口请求前 参数处理
|
||||||
|
var temp = {
|
||||||
|
page: data.page,
|
||||||
|
rows: data.limit,
|
||||||
|
keyword: data.key,
|
||||||
|
dbCode: "lrsystemdb"
|
||||||
|
};
|
||||||
|
return temp;
|
||||||
|
},
|
||||||
|
afterFetch: (data) => {
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
function modalSuReClick(){
|
||||||
|
let rows = getSelectRows();
|
||||||
|
emit('backrows', rows);
|
||||||
|
closeModal()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
</script>
|
||||||
|
<style lang="less">
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,100 @@
|
||||||
|
import { BasicColumn, FormSchema } from '@/components/Table';
|
||||||
|
import { getOutKeyList } from '@/api/formdesign/index'
|
||||||
|
import { h } from 'vue';
|
||||||
|
import { Tag } from 'ant-design-vue';
|
||||||
|
let tabList
|
||||||
|
|
||||||
|
|
||||||
|
export function sendtabledata(data:any[]) {
|
||||||
|
console.log('aaad',data)
|
||||||
|
tabList = data
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export const columns: BasicColumn[] = [
|
||||||
|
{
|
||||||
|
title: '名称',
|
||||||
|
dataIndex: 'status',
|
||||||
|
width: 100,
|
||||||
|
editComponent: 'Select',
|
||||||
|
editable: true,
|
||||||
|
edit: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '表名',
|
||||||
|
dataIndex: 'f_TableName',
|
||||||
|
width: 120,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '外键',
|
||||||
|
editComponent: 'ApiSelect',
|
||||||
|
width: 180,
|
||||||
|
dataIndex: 'field',
|
||||||
|
editable: true,
|
||||||
|
edit: true,
|
||||||
|
editComponentProps: ({ record }) => {
|
||||||
|
return {
|
||||||
|
api: () => getOutKeyList({tableNames: record.f_TableName}).then((data: AreaRespVO[]) => {
|
||||||
|
return data[0].lr_db_codecolumnsList
|
||||||
|
}),
|
||||||
|
params: {},
|
||||||
|
// 接口参数
|
||||||
|
resultField: 'data',
|
||||||
|
labelField: 'f_DbColumnName',
|
||||||
|
valueField: 'f_DbColumnName',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
title: '关联表',
|
||||||
|
dataIndex: 'relationName',
|
||||||
|
editComponent: 'Select',
|
||||||
|
width: 180,
|
||||||
|
editable: true,
|
||||||
|
edit: true,
|
||||||
|
editComponentProps: ({ record }) => {
|
||||||
|
let arr = []
|
||||||
|
tabList.forEach(item =>{
|
||||||
|
if(item.f_TableName !== record.f_TableName){
|
||||||
|
arr.push({
|
||||||
|
label: item.f_TableName,
|
||||||
|
value: item.f_TableName,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return {
|
||||||
|
options: arr,
|
||||||
|
onChange: (e: any) => {
|
||||||
|
tabSelectId = e
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '关联主键',
|
||||||
|
editComponent: 'ApiSelect',
|
||||||
|
width: 180,
|
||||||
|
dataIndex: 'relationField',
|
||||||
|
editable: true,
|
||||||
|
edit: true,
|
||||||
|
editComponentProps: ({ record }) => {
|
||||||
|
|
||||||
|
return {
|
||||||
|
api: () => getOutKeyList({tableNames: record.f_TableName}).then((data: AreaRespVO[]) => {
|
||||||
|
return data[0].lr_db_codecolumnsList
|
||||||
|
}),
|
||||||
|
params: {},
|
||||||
|
// 接口参数
|
||||||
|
resultField: 'data',
|
||||||
|
labelField: 'f_DbColumnName',
|
||||||
|
valueField: 'f_DbColumnName',
|
||||||
|
};
|
||||||
|
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
import { BasicColumn } from '@/components/Table';
|
||||||
|
import { h } from 'vue';
|
||||||
|
import { Tag } from 'ant-design-vue';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export const columns: BasicColumn[] = [
|
||||||
|
{
|
||||||
|
title: '表名',
|
||||||
|
dataIndex: 'f_TableName',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '备注',
|
||||||
|
dataIndex: 'f_Description'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '状态',
|
||||||
|
dataIndex: 'f_State'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,213 @@
|
||||||
|
import { BasicColumn, FormSchema } from '@/components/Table';
|
||||||
|
import { optionsListApi,getOutKeyList } from '@/api/formdesign/index'
|
||||||
|
import { h } from 'vue';
|
||||||
|
import { Tag } from 'ant-design-vue';
|
||||||
|
let tabList
|
||||||
|
let tabSelectId
|
||||||
|
|
||||||
|
export function sendtabledata(data:any[]) {
|
||||||
|
tabList = data
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export const columns: BasicColumn[] = [
|
||||||
|
{
|
||||||
|
title: '类别',
|
||||||
|
dataIndex: 'status',
|
||||||
|
width: 50,
|
||||||
|
customRender: ({ record }) => {
|
||||||
|
const status = record.type;
|
||||||
|
let enable
|
||||||
|
if(status == "main"){
|
||||||
|
enable = true
|
||||||
|
}else{
|
||||||
|
enable = false
|
||||||
|
}
|
||||||
|
const color = enable ? '#67c23a' : '#e6a23c';
|
||||||
|
const text = enable ? '主表' : '子表';
|
||||||
|
return h(Tag, { color: color }, () => text);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '表名',
|
||||||
|
dataIndex: 'f_TableName',
|
||||||
|
width: 120,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '外键',
|
||||||
|
editComponent: 'ApiSelect',
|
||||||
|
width: 180,
|
||||||
|
dataIndex: 'field',
|
||||||
|
editable: true,
|
||||||
|
edit: true,
|
||||||
|
editComponentProps: ({ record }) => {
|
||||||
|
return {
|
||||||
|
api: () => getOutKeyList({tableNames: record.f_TableName}).then((data: AreaRespVO[]) => {
|
||||||
|
return data[0].lr_db_codecolumnsList
|
||||||
|
}),
|
||||||
|
params: {},
|
||||||
|
// 接口参数
|
||||||
|
resultField: 'data',
|
||||||
|
labelField: 'f_DbColumnName',
|
||||||
|
valueField: 'f_DbColumnName',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
title: '关联表',
|
||||||
|
dataIndex: 'relationName',
|
||||||
|
editComponent: 'Select',
|
||||||
|
width: 180,
|
||||||
|
editable: true,
|
||||||
|
edit: true,
|
||||||
|
editComponentProps: ({ record }) => {
|
||||||
|
let arr = []
|
||||||
|
tabList.forEach(item =>{
|
||||||
|
if(item.f_TableName !== record.f_TableName){
|
||||||
|
arr.push({
|
||||||
|
label: item.f_TableName,
|
||||||
|
value: item.f_TableName,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return {
|
||||||
|
options: arr,
|
||||||
|
onChange: (e: any) => {
|
||||||
|
tabSelectId = e
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '关联主键',
|
||||||
|
editComponent: 'ApiSelect',
|
||||||
|
width: 180,
|
||||||
|
dataIndex: 'relationField',
|
||||||
|
editable: true,
|
||||||
|
edit: true,
|
||||||
|
editComponentProps: ({ record }) => {
|
||||||
|
return {
|
||||||
|
api: () => getOutKeyList({tableNames: record.f_TableName}).then((data: AreaRespVO[]) => {
|
||||||
|
return data[0].lr_db_codecolumnsList
|
||||||
|
}),
|
||||||
|
params: {},
|
||||||
|
// 接口参数
|
||||||
|
resultField: 'data',
|
||||||
|
labelField: 'f_DbColumnName',
|
||||||
|
valueField: 'f_DbColumnName',
|
||||||
|
};
|
||||||
|
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
];
|
||||||
|
|
||||||
|
export const formSchema: FormSchema[] = [
|
||||||
|
{
|
||||||
|
field: 'f_Name',
|
||||||
|
component: 'Input',
|
||||||
|
label: '名称',
|
||||||
|
colProps: {
|
||||||
|
span: 24,
|
||||||
|
},
|
||||||
|
defaultValue: '',
|
||||||
|
rules: [{ required: true }],
|
||||||
|
componentProps: {
|
||||||
|
placeholder: '请输入',
|
||||||
|
onChange: (e) => {
|
||||||
|
console.log(e);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'f_Category',
|
||||||
|
component: 'ApiSelect',
|
||||||
|
label: '分类',
|
||||||
|
required: true,
|
||||||
|
colProps: {
|
||||||
|
span: 24,
|
||||||
|
},
|
||||||
|
componentProps: ({ formActionType, formModel }) => {
|
||||||
|
return {
|
||||||
|
api: optionsListApi, // 接口
|
||||||
|
// 接口参数
|
||||||
|
resultField: 'data',
|
||||||
|
labelField: 'f_ItemName',
|
||||||
|
valueField: 'f_ItemId',
|
||||||
|
};
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'f_DbCode',
|
||||||
|
component: 'ApiSelect',
|
||||||
|
label: '数据库',
|
||||||
|
required: true,
|
||||||
|
colProps: {
|
||||||
|
span: 24,
|
||||||
|
},
|
||||||
|
componentProps: {
|
||||||
|
options: [
|
||||||
|
{ label: '系统数据库', value: 'lrsystemdb' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'f_EnabledMark',
|
||||||
|
label: '状态',
|
||||||
|
component: 'RadioButtonGroup',
|
||||||
|
defaultValue: 1,
|
||||||
|
componentProps: {
|
||||||
|
options: [
|
||||||
|
{ label: '是', value: 1 },
|
||||||
|
{ label: '否', value: 0 },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'f_FormType',
|
||||||
|
label: '类型',
|
||||||
|
component: 'ApiRadioGroup',
|
||||||
|
defaultValue: '0',
|
||||||
|
componentProps: {
|
||||||
|
options: [
|
||||||
|
{ label: '常规表单', value: '0' },
|
||||||
|
{ label: '视图表单', value: '1' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
colProps: { lg: 24, md: 24 },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'f_Description',
|
||||||
|
component: 'InputTextArea',
|
||||||
|
label: '描述',
|
||||||
|
colProps: {
|
||||||
|
span: 24,
|
||||||
|
},
|
||||||
|
defaultValue: '',
|
||||||
|
componentProps: {
|
||||||
|
placeholder: '请输入',
|
||||||
|
onChange: (e) => {
|
||||||
|
console.log(e);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'field1',
|
||||||
|
label: '',
|
||||||
|
colProps: {
|
||||||
|
span: 24,
|
||||||
|
},
|
||||||
|
slot: 'addDatabaseTableSlot',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'field1',
|
||||||
|
label: '',
|
||||||
|
colProps: {
|
||||||
|
span: 24,
|
||||||
|
},
|
||||||
|
slot: 'addDatabaseContantSlot',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,160 @@
|
||||||
|
<template>
|
||||||
|
<div class="l-rblock" >
|
||||||
|
<div class="l-page-pane">
|
||||||
|
<BasicForm
|
||||||
|
ref="myDataBaseFormRef"
|
||||||
|
@register="registerForm"
|
||||||
|
>
|
||||||
|
<template #addDatabaseTableSlot="{ model, field }">
|
||||||
|
<div>添加数据库表(请先选择数据库)</div>
|
||||||
|
<BasicTable @register="registerDataBaseTable">
|
||||||
|
<template #bodyCell="{ column, record }">
|
||||||
|
<template v-if="column.key === 'action'">
|
||||||
|
<TableAction :actions="[
|
||||||
|
{
|
||||||
|
label: '删除',
|
||||||
|
color: 'error',
|
||||||
|
popConfirm: {
|
||||||
|
title: '是否删除该数据',
|
||||||
|
confirm: handleDelete.bind(null, record),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
]" />
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
</BasicTable>
|
||||||
|
<div class="addDataBaseTableBox" @click="handleAddDataBase">
|
||||||
|
<a-button size="small" type="link"><template #icon><PlusOutlined /></template>添加</a-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template #addDatabaseContantSlot="{ model, field }">
|
||||||
|
<div>添加数据库关联表,只用来做数据权限设置(请先选择数据库)</div>
|
||||||
|
<DataBaseTable :tabList="tabList" key="databaseKey"></DataBaseTable>
|
||||||
|
<div class="addDataBaseTableBox" @click="handleAddDataBase">
|
||||||
|
<a-button size="small" type="link"><template #icon><PlusOutlined /></template>添加</a-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
|
||||||
|
</BasicForm>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<DataObject @register="registerModal" @backrows="handleBackRows" />
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</template>
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import { PlusOutlined } from '@ant-design/icons-vue';
|
||||||
|
import { message } from 'ant-design-vue';
|
||||||
|
|
||||||
|
|
||||||
|
import { BasicForm, useForm } from '/@/components/Form';
|
||||||
|
import { formSchema , columns , sendtabledata } from './index.data';
|
||||||
|
import { BasicTable, useTable, TableAction } from '@/components/Table';
|
||||||
|
import { BasicModal , useModal , useModalInner } from '/@/components/Modal';
|
||||||
|
import DataObject from './DataObject.vue'
|
||||||
|
import DataBaseTable from './DataBaseTable.vue'
|
||||||
|
|
||||||
|
const [registerModal, { openModal }] = useModal();
|
||||||
|
|
||||||
|
let tabList: any[] = []
|
||||||
|
let tableColumns: any[] = {}
|
||||||
|
let isAddDbTableRData: any[] = false
|
||||||
|
let dbTableData: any[] = []
|
||||||
|
let databaseKey: any[] = 0
|
||||||
|
|
||||||
|
const myDataBaseFormRef = ref<any>();
|
||||||
|
const [registerForm, { resetFields, setFieldsValue, updateSchema, validate }] = useForm({
|
||||||
|
labelWidth: 100,
|
||||||
|
schemas: formSchema,
|
||||||
|
showActionButtonGroup: false,
|
||||||
|
baseColProps: { lg: 24, md: 24 },
|
||||||
|
});
|
||||||
|
|
||||||
|
const [registerDataBaseTable, { reload, setTableData, getColumns }] = useTable({
|
||||||
|
title: '',
|
||||||
|
rowKey: 'id',
|
||||||
|
columns,
|
||||||
|
formConfig: {
|
||||||
|
labelWidth: 120,
|
||||||
|
},
|
||||||
|
useSearchForm: false,
|
||||||
|
showTableSetting: false,
|
||||||
|
bordered: false,
|
||||||
|
pagination: false,
|
||||||
|
actionColumn: {
|
||||||
|
width: 80,
|
||||||
|
title: '操作',
|
||||||
|
dataIndex: 'action',
|
||||||
|
fixed: undefined,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
function handleAddDataBase() {
|
||||||
|
const anyformobj = ref<any>(myDataBaseFormRef.value.getFieldsValue());
|
||||||
|
|
||||||
|
if(anyformobj.value.f_DbCode){
|
||||||
|
openModal(true, {});
|
||||||
|
}else{
|
||||||
|
message.warning("请选择数据库")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
function handleDelete(record: Recordable) {
|
||||||
|
// openAccountModal(true, {
|
||||||
|
// record,
|
||||||
|
// });
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleBackRows(ModuleId = '') {
|
||||||
|
ModuleId.forEach(item =>{
|
||||||
|
tabList.push(item)
|
||||||
|
})
|
||||||
|
tabList.forEach((item,index) =>{
|
||||||
|
if(index == 0){
|
||||||
|
item.type = "main"
|
||||||
|
}else{
|
||||||
|
item.type = 'child'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
setTableData(tabList)
|
||||||
|
reload()
|
||||||
|
databaseKey++
|
||||||
|
console.log('databaseKey',databaseKey)
|
||||||
|
const chart1data1 = sendtabledata(tabList)
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
<style lang="less">
|
||||||
|
.l-rblock{
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background:#f0f2f5;
|
||||||
|
padding: 24px;
|
||||||
|
}
|
||||||
|
.l-page-pane{
|
||||||
|
box-sizing: border-box;
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
max-width: 794px;
|
||||||
|
overflow: hidden auto;
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 4px;
|
||||||
|
margin: auto;
|
||||||
|
padding: 24px;
|
||||||
|
}
|
||||||
|
.addDataBaseTableBox{
|
||||||
|
border: 1px dashed #f0f0f0;
|
||||||
|
text-align: center;
|
||||||
|
cursor: pointer;
|
||||||
|
margin-top: -20px;
|
||||||
|
&:hover {
|
||||||
|
border-color: #409EFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,181 @@
|
||||||
|
<template>
|
||||||
|
<lrlayout class="l-tab-page">
|
||||||
|
<template #left>
|
||||||
|
<lrPanel style="padding-right:0;" >
|
||||||
|
<template #title>
|
||||||
|
{{$t('分类')}}
|
||||||
|
<div class="tree-setting-btn">
|
||||||
|
<Tooltip placement="top" title="设置">
|
||||||
|
<span><SettingOutlined style="color:blue" /></span>
|
||||||
|
</Tooltip>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<BasicTree ref="asyncExpandTreeRef"
|
||||||
|
treeWrapperClassName="h-[calc(100%-35px)] overflow-auto" loadData
|
||||||
|
:clickRowToExpand="false" :treeData="treeData" :fieldNames="{ key: 'f_ItemId', title: 'f_ItemName' }"
|
||||||
|
:defaultExpandAll="true" @select="handleSelect" />
|
||||||
|
</lrPanel>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<BasicTable @register="registerTable" :searchInfo="searchInfo">
|
||||||
|
<template #bodyCell="{ column, record }">
|
||||||
|
<template v-if="column.key === 'action'">
|
||||||
|
<TableAction :actions="[
|
||||||
|
{
|
||||||
|
label: '编辑',
|
||||||
|
onClick: handleEdit.bind(null, record),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '删除',
|
||||||
|
color: 'error',
|
||||||
|
popConfirm: {
|
||||||
|
title: '是否删除该数据',
|
||||||
|
confirm: handleDelete.bind(null, record),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
]" />
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
<template #toolbar>
|
||||||
|
<a-button type="primary" @click="handleAddForm"> 新增 </a-button>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
</BasicTable>
|
||||||
|
|
||||||
|
<FormModal @register="registerModal" />
|
||||||
|
|
||||||
|
</lrlayout>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</template>
|
||||||
|
<script lang="ts" setup>
|
||||||
|
|
||||||
|
import { onMounted, ref, nextTick, unref,reactive } from 'vue';
|
||||||
|
|
||||||
|
import { BasicTable, useTable, TableAction } from '@/components/Table';
|
||||||
|
|
||||||
|
|
||||||
|
import { getFormGroupList } from '@/api/formdesign/index';
|
||||||
|
import { optionsListApi } from '@/api/formdesign/index';
|
||||||
|
|
||||||
|
|
||||||
|
import { SettingOutlined } from '@ant-design/icons-vue';
|
||||||
|
import lrlayout from '@/components/lrLayout';
|
||||||
|
import lrPanel from '@/components/lrPanel';
|
||||||
|
|
||||||
|
|
||||||
|
import FormModal from './FormModal.vue';
|
||||||
|
|
||||||
|
import { BasicTree, TreeItem, TreeActionItem } from '@/components/Tree';
|
||||||
|
|
||||||
|
import { useModal } from '/@/components/Modal';
|
||||||
|
|
||||||
|
import { columns, searchFormSchema } from './form.data';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const [registerModal, { openModal }] = useModal();
|
||||||
|
|
||||||
|
|
||||||
|
const [registerTable, { reload, getSelectRows }] = useTable({
|
||||||
|
title: '表单列表',
|
||||||
|
api: getFormGroupList,
|
||||||
|
rowKey: 'f_Id',
|
||||||
|
columns,
|
||||||
|
formConfig: {
|
||||||
|
labelWidth: 120,
|
||||||
|
schemas: searchFormSchema,
|
||||||
|
},
|
||||||
|
useSearchForm: true,
|
||||||
|
showTableSetting: true,
|
||||||
|
bordered: true,
|
||||||
|
beforeFetch: (data) => {
|
||||||
|
// 接口请求前 参数处理
|
||||||
|
var temp = {
|
||||||
|
page: data.page,
|
||||||
|
rows: data.limit,
|
||||||
|
keyword: data.key,
|
||||||
|
category: data.f_Category
|
||||||
|
};
|
||||||
|
return temp;
|
||||||
|
},
|
||||||
|
afterFetch: (data) => {
|
||||||
|
data.forEach(item =>{
|
||||||
|
let d = item.f_CreateDate ? new Date(item.f_CreateDate) : new Date(),
|
||||||
|
obj = {
|
||||||
|
year: d.getFullYear(),
|
||||||
|
month: d.getMonth() + 1,
|
||||||
|
day: d.getDate(),
|
||||||
|
hours: d.getHours(),
|
||||||
|
min: d.getMinutes(),
|
||||||
|
seconds: d.getSeconds()
|
||||||
|
}
|
||||||
|
Object.keys(obj).forEach(key => {
|
||||||
|
if (obj[key] < 10) obj[key] = `0${obj[key]}`
|
||||||
|
})
|
||||||
|
|
||||||
|
item.f_CreateDate = `${obj.year}-${obj.month}-${obj.day} ${obj.hours}:${obj.min}:${obj.seconds}`
|
||||||
|
item.f_CreateDate = item.f_CreateDate.replace(/T/g, ' ').replace(/.[\d]{3}Z/, ' ')
|
||||||
|
treeData.value.forEach(val =>{
|
||||||
|
if(item.f_Category == val.f_ItemValue){
|
||||||
|
item.f_Category_Name = val.f_ItemName
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
//请求之后对返回值进行处理
|
||||||
|
|
||||||
|
},
|
||||||
|
handleSearchInfoFn(info) {
|
||||||
|
return info;
|
||||||
|
},
|
||||||
|
actionColumn: {
|
||||||
|
width: 180,
|
||||||
|
title: '操作',
|
||||||
|
dataIndex: 'action',
|
||||||
|
// slots: { customRender: 'action' },
|
||||||
|
fixed: undefined,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const searchInfo = reactive < Recordable > ({});
|
||||||
|
|
||||||
|
const treeData = ref < TreeItem[] > ([]);
|
||||||
|
const asyncExpandTreeRef = ref < Nullable < TreeActionType >> (null);
|
||||||
|
|
||||||
|
async function fetch() {
|
||||||
|
treeData.value = (await optionsListApi()) as unknown as TreeItem[];
|
||||||
|
// 展开全部
|
||||||
|
nextTick(() => {
|
||||||
|
unref(asyncExpandTreeRef)?.expandAll(true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function handleSelect(keys) {
|
||||||
|
treeData.value.forEach(item =>{
|
||||||
|
if(keys[0] == item.f_ItemId){
|
||||||
|
searchInfo.f_Category = item.f_Category;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
reload();
|
||||||
|
}
|
||||||
|
function handleEdit(record: Recordable) {
|
||||||
|
// openAccountModal(true, {
|
||||||
|
// record,
|
||||||
|
// });
|
||||||
|
}
|
||||||
|
function handleDelete(record: Recordable) {
|
||||||
|
// openAccountModal(true, {
|
||||||
|
// record,
|
||||||
|
// });
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleAddForm() {
|
||||||
|
openModal(true, {});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
fetch();
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
@ -0,0 +1,198 @@
|
||||||
|
import { BasicColumn, FormSchema } from '@/components/Table';
|
||||||
|
import { h } from 'vue';
|
||||||
|
import { Tag } from 'ant-design-vue';
|
||||||
|
import Icon from '@/components/Icon/Icon.vue';
|
||||||
|
|
||||||
|
export const columns: BasicColumn[] = [
|
||||||
|
{
|
||||||
|
title: '按钮名称',
|
||||||
|
dataIndex: 'name',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'DOMID',
|
||||||
|
dataIndex: 'domId',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '排序',
|
||||||
|
dataIndex: 'sort',
|
||||||
|
},
|
||||||
|
|
||||||
|
];
|
||||||
|
|
||||||
|
const isDir = (type: string) => type === '0';
|
||||||
|
const isMenu = (type: string) => type === '1';
|
||||||
|
const isButton = (type: string) => type === '2';
|
||||||
|
|
||||||
|
export const searchFormSchema: FormSchema[] = [
|
||||||
|
{
|
||||||
|
field: 'key',
|
||||||
|
label: '关键字',
|
||||||
|
component: 'Input',
|
||||||
|
colProps: { span: 8 },
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export const formSchema: FormSchema[] = [
|
||||||
|
{
|
||||||
|
field: 'type',
|
||||||
|
label: '类型',
|
||||||
|
component: 'RadioButtonGroup',
|
||||||
|
defaultValue: '1',
|
||||||
|
componentProps: {
|
||||||
|
options: [
|
||||||
|
// { label: '目录', value: '0' },
|
||||||
|
{ label: '菜单', value: '1' },
|
||||||
|
{ label: '按钮', value: '2' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
colProps: { lg: 24, md: 24 },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'id',
|
||||||
|
label: '名称',
|
||||||
|
component: 'Input',
|
||||||
|
ifShow:false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'name',
|
||||||
|
label: '名称',
|
||||||
|
component: 'Input',
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
field: 'parentId',
|
||||||
|
label: '上级',
|
||||||
|
component: 'TreeSelect',
|
||||||
|
componentProps: {
|
||||||
|
fieldNames: {
|
||||||
|
label: 'name',
|
||||||
|
key: 'id',
|
||||||
|
value: 'id',
|
||||||
|
},
|
||||||
|
getPopupContainer: () => document.body,
|
||||||
|
},
|
||||||
|
ifShow: ({ values }) => !isButton(values.type),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'moduleId',
|
||||||
|
label: '菜单',
|
||||||
|
component: 'TreeSelect',
|
||||||
|
componentProps: {
|
||||||
|
fieldNames: {
|
||||||
|
label: 'name',
|
||||||
|
key: 'id',
|
||||||
|
value: 'id',
|
||||||
|
},
|
||||||
|
getPopupContainer: () => document.body,
|
||||||
|
},
|
||||||
|
ifShow: ({ values }) => isButton(values.type),
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'domId',
|
||||||
|
label: 'DMOID',
|
||||||
|
component: 'Input',
|
||||||
|
required: true,
|
||||||
|
ifShow: ({ values }) => isButton(values.type),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'sortNo',
|
||||||
|
label: '排序',
|
||||||
|
component: 'InputNumber',
|
||||||
|
ifShow: ({ values }) => !isButton(values.type),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'sort',
|
||||||
|
label: '排序',
|
||||||
|
component: 'InputNumber',
|
||||||
|
ifShow: ({ values }) => isButton(values.type),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'class',
|
||||||
|
helpMessage: ['参考参数值', 'success、warning、error'],
|
||||||
|
label: '样式',
|
||||||
|
component: 'Input',
|
||||||
|
ifShow: ({ values }) => isButton(values.type),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'iconName',
|
||||||
|
label: '图标',
|
||||||
|
component: 'IconPicker',
|
||||||
|
ifShow: ({ values }) => !isButton(values.type),
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
field: 'url',
|
||||||
|
label: '路由地址',
|
||||||
|
component: 'Input',
|
||||||
|
required: true,
|
||||||
|
ifShow: ({ values }) => !isButton(values.type),
|
||||||
|
},
|
||||||
|
// {
|
||||||
|
// field: 'component',
|
||||||
|
// label: '组件路径',
|
||||||
|
// component: 'Input',
|
||||||
|
// ifShow: ({ values }) => isMenu(values.type),
|
||||||
|
// },
|
||||||
|
{
|
||||||
|
field: 'code',
|
||||||
|
label: '权限标识',
|
||||||
|
component: 'Input',
|
||||||
|
ifShow: ({ values }) => !isButton(values.type),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'status',
|
||||||
|
label: '是否系统',
|
||||||
|
component: 'RadioButtonGroup',
|
||||||
|
defaultValue: 1,
|
||||||
|
componentProps: {
|
||||||
|
options: [
|
||||||
|
{ label: '是', value: 0 },
|
||||||
|
{ label: '否', value: 1 },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
ifShow: ({ values }) => !isButton(values.type),
|
||||||
|
},
|
||||||
|
// {
|
||||||
|
// field: 'isExt',
|
||||||
|
// label: '是否外链',
|
||||||
|
// component: 'RadioButtonGroup',
|
||||||
|
// defaultValue: '0',
|
||||||
|
// componentProps: {
|
||||||
|
// options: [
|
||||||
|
// { label: '否', value: '0' },
|
||||||
|
// { label: '是', value: '1' },
|
||||||
|
// ],
|
||||||
|
// },
|
||||||
|
// ifShow: ({ values }) => !isButton(values.type),
|
||||||
|
// },
|
||||||
|
|
||||||
|
// {
|
||||||
|
// field: 'keepalive',
|
||||||
|
// label: '是否缓存',
|
||||||
|
// component: 'RadioButtonGroup',
|
||||||
|
// defaultValue: '0',
|
||||||
|
// componentProps: {
|
||||||
|
// options: [
|
||||||
|
// { label: '否', value: '0' },
|
||||||
|
// { label: '是', value: '1' },
|
||||||
|
// ],
|
||||||
|
// },
|
||||||
|
// ifShow: ({ values }) => isMenu(values.type),
|
||||||
|
// },
|
||||||
|
|
||||||
|
// {
|
||||||
|
// field: 'show',
|
||||||
|
// label: '是否显示',
|
||||||
|
// component: 'RadioButtonGroup',
|
||||||
|
// defaultValue: '0',
|
||||||
|
// componentProps: {
|
||||||
|
// options: [
|
||||||
|
// { label: '是', value: '0' },
|
||||||
|
// { label: '否', value: '1' },
|
||||||
|
// ],
|
||||||
|
// },
|
||||||
|
// ifShow: ({ values }) => !isButton(values.type),
|
||||||
|
// },
|
||||||
|
];
|
||||||
|
|
@ -52,7 +52,6 @@
|
||||||
const values = await validate();
|
const values = await validate();
|
||||||
setDrawerProps({ confirmLoading: true });
|
setDrawerProps({ confirmLoading: true });
|
||||||
// TODO custom api
|
// TODO custom api
|
||||||
console.log(values)
|
|
||||||
if (values.type == '1') {
|
if (values.type == '1') {
|
||||||
console.log("新增菜单")
|
console.log("新增菜单")
|
||||||
delete values.type
|
delete values.type
|
||||||
|
|
|
||||||
|
|
@ -117,7 +117,6 @@
|
||||||
nextTick(expandAll);
|
nextTick(expandAll);
|
||||||
}
|
}
|
||||||
function onBtnClicked(domId) {
|
function onBtnClicked(domId) {
|
||||||
console.log(domId)
|
|
||||||
switch (domId) {
|
switch (domId) {
|
||||||
case 'btnAdd':
|
case 'btnAdd':
|
||||||
handleCreate()
|
handleCreate()
|
||||||
|
|
|
||||||
|
|
@ -74,6 +74,7 @@
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
async function editGroup(record: Recordable) {
|
async function editGroup(record: Recordable) {
|
||||||
|
console.log('record',record)
|
||||||
openDrawer(true, {
|
openDrawer(true, {
|
||||||
record,
|
record,
|
||||||
isUpdate: true,
|
isUpdate: true,
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,7 @@
|
||||||
* @Author: 刘妍
|
* @Author: 刘妍
|
||||||
* @Date: 2024-01-13 13:04:15
|
* @Date: 2024-01-13 13:04:15
|
||||||
* @LastEditors: Do not edit
|
* @LastEditors: Do not edit
|
||||||
* @LastEditTime: 2024-01-17 16:06:35
|
* @LastEditTime: 2024-03-08 09:17:00
|
||||||
* @FilePath: \费县天空地大屏正式代码e:\新架构\vue-vben-admin\vite.config.ts
|
|
||||||
* @Description:
|
* @Description:
|
||||||
*/
|
*/
|
||||||
import { defineApplicationConfig } from '@vben/vite-config';
|
import { defineApplicationConfig } from '@vben/vite-config';
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue