系统数据迁移、复制功能开发:增加导入类型“租户模式导入”
This commit is contained in:
@ -4,6 +4,8 @@ import { ErrorMessageMode } from '/#/axios';
|
|||||||
enum Api {
|
enum Api {
|
||||||
ExportDatas= '/system/dataMigration/exportDatas',
|
ExportDatas= '/system/dataMigration/exportDatas',
|
||||||
DownloadDatas='/system/dataMigration/downloadDatas',
|
DownloadDatas='/system/dataMigration/downloadDatas',
|
||||||
|
LogList='/system/dataMigration/logList',
|
||||||
|
LogDetails='/system/dataMigration/logDetails',
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -25,10 +27,7 @@ export async function exportDatas(params, mode: ErrorMessageMode = 'modal') {
|
|||||||
/**
|
/**
|
||||||
* @description: 根据uuid(目录名称)下载数据
|
* @description: 根据uuid(目录名称)下载数据
|
||||||
*/
|
*/
|
||||||
export async function downloadDatas(
|
export async function downloadDatas(params?: object, mode: ErrorMessageMode = 'modal') {
|
||||||
params?: object,
|
|
||||||
mode: ErrorMessageMode = 'modal'
|
|
||||||
) {
|
|
||||||
return defHttp.download(
|
return defHttp.download(
|
||||||
{
|
{
|
||||||
url: Api.DownloadDatas+"/"+params.uuid,
|
url: Api.DownloadDatas+"/"+params.uuid,
|
||||||
@ -42,4 +41,39 @@ export async function downloadDatas(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description: 获取日志列表
|
||||||
|
*/
|
||||||
|
export async function getLogList(mode: ErrorMessageMode = 'modal') {
|
||||||
|
return defHttp.get<[]>(
|
||||||
|
{
|
||||||
|
url: Api.LogList
|
||||||
|
},
|
||||||
|
{
|
||||||
|
errorMessageMode: mode,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description: 获取日志详情
|
||||||
|
*/
|
||||||
|
export async function getLogDetails(fileName:String,mode: ErrorMessageMode = 'modal') {
|
||||||
|
return defHttp.get<[]>(
|
||||||
|
{
|
||||||
|
url: Api.LogDetails,
|
||||||
|
params:{
|
||||||
|
fileName
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
errorMessageMode: mode,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -234,16 +234,18 @@
|
|||||||
display:block;
|
display:block;
|
||||||
margin-left:20px;
|
margin-left:20px;
|
||||||
margin-bottom:20px;
|
margin-bottom:20px;
|
||||||
color: rgba(0,0,255,0.8);
|
span{
|
||||||
text-decoration:underline rgba(#0000ff,0.8);
|
color: rgba(0,0,255,0.8);
|
||||||
font-weight: 500;
|
text-decoration:underline rgba(#0000ff,0.8);
|
||||||
font-size: 16px;
|
font-weight: 500;
|
||||||
cursor: pointer;
|
font-size: 16px;
|
||||||
&:hover{
|
cursor: pointer;
|
||||||
color: rgba(0,0,255,1);
|
&:hover{
|
||||||
text-decoration:underline #0000ff;
|
color: rgba(0,0,255,1);
|
||||||
|
text-decoration:underline #0000ff;
|
||||||
}
|
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.list-wrapper{
|
.list-wrapper{
|
||||||
|
|||||||
@ -3,21 +3,31 @@
|
|||||||
<slot></slot>
|
<slot></slot>
|
||||||
<a-modal
|
<a-modal
|
||||||
v-model:visible="data.visible"
|
v-model:visible="data.visible"
|
||||||
:title="t(`导入数据[${coverType=='override'?'覆盖模式':'新增模式'}]`)"
|
:title="t(`导入数据[${importType=='overrideMode'?'覆盖模式':'租户模式'}]`)"
|
||||||
:maskClosable="false"
|
:maskClosable="false"
|
||||||
@ok="doUpload"
|
@ok="doUpload"
|
||||||
@cancel="close"
|
@cancel="close"
|
||||||
@click.stop=""
|
@click.stop=""
|
||||||
>
|
>
|
||||||
|
<div class="tenant-box" v-if="importType=='tenantMode'">
|
||||||
|
<Form ref="formRef" :model="formModel">
|
||||||
|
<FormItem
|
||||||
|
label="租户编码"
|
||||||
|
name="tenantCode"
|
||||||
|
:rules="[{ required: true, message: '请输入租户编码' }]"
|
||||||
|
>
|
||||||
|
<a-input v-model:value="formModel.tenantCode" style="width:300px;" placeholder="请输入租户编码" />
|
||||||
|
</FormItem>
|
||||||
|
</Form>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="upload-box">
|
<div class="upload-box">
|
||||||
<a-upload
|
<a-upload
|
||||||
v-model:file-list="fileList"
|
v-model:file-list="fileList"
|
||||||
class="upload-box"
|
class="upload-box"
|
||||||
name="file"
|
name="file"
|
||||||
accept=".json,.zip"
|
accept=".json,.zip"
|
||||||
:headers="data.headers"
|
|
||||||
:max-count="1"
|
:max-count="1"
|
||||||
@change="handleChange"
|
|
||||||
:before-upload="beforeUpload"
|
:before-upload="beforeUpload"
|
||||||
@remove="handleRemove"
|
@remove="handleRemove"
|
||||||
>
|
>
|
||||||
@ -25,12 +35,14 @@
|
|||||||
<div class="a-upload__text">{{ t('将文件拖到此处,或') }}<em>{{ t('点击上传') }}</em></div>
|
<div class="a-upload__text">{{ t('将文件拖到此处,或') }}<em>{{ t('点击上传') }}</em></div>
|
||||||
</a-upload>
|
</a-upload>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</a-modal>
|
</a-modal>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { reactive,ref} from 'vue';
|
import { reactive,ref} from 'vue';
|
||||||
|
import { Form, FormInstance} from 'ant-design-vue';
|
||||||
import BgImg from '../../assets/sysconfig_import.png';
|
import BgImg from '../../assets/sysconfig_import.png';
|
||||||
import { useI18n } from '/@/hooks/web/useI18n';
|
import { useI18n } from '/@/hooks/web/useI18n';
|
||||||
import { defHttp } from '/@/utils/http/axios';
|
import { defHttp } from '/@/utils/http/axios';
|
||||||
@ -38,11 +50,18 @@
|
|||||||
import { useMessage } from '/@/hooks/web/useMessage';
|
import { useMessage } from '/@/hooks/web/useMessage';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
coverType: {
|
importType: {
|
||||||
type: Boolean
|
type:String,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const formRef = ref<FormInstance>();
|
||||||
|
const formModel=ref({
|
||||||
|
tenantCode:''
|
||||||
|
});
|
||||||
|
const FormItem = Form.Item;
|
||||||
|
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const globSetting = useGlobSetting();
|
const globSetting = useGlobSetting();
|
||||||
const { notification } = useMessage();
|
const { notification } = useMessage();
|
||||||
@ -53,36 +72,38 @@
|
|||||||
visible: false
|
visible: false
|
||||||
});
|
});
|
||||||
|
|
||||||
const fileList=ref([]);
|
const fileList=ref<File[]>([]);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
async function open() {
|
async function open() {
|
||||||
if(props.coverType!=='override'){
|
|
||||||
alert("新增模式导入暂时不可用");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
data.visible = true;
|
data.visible = true;
|
||||||
}
|
}
|
||||||
function close() {
|
function close() {
|
||||||
data.visible = false;
|
data.visible = false;
|
||||||
fileList.value=[];
|
fileList.value=[];
|
||||||
|
formModel.value.tenantCode='';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function handleRemove(file){
|
function handleRemove(file:File){
|
||||||
const index = fileList.value.indexOf(file);
|
const index = fileList.value.indexOf(file);
|
||||||
const newFileList = fileList.value.slice();
|
const newFileList = fileList.value.slice();
|
||||||
newFileList.splice(index, 1);
|
newFileList.splice(index, 1);
|
||||||
fileList.value = newFileList;
|
fileList.value = newFileList;
|
||||||
};
|
};
|
||||||
|
|
||||||
function beforeUpload(file){
|
function beforeUpload(file:File){
|
||||||
fileList.value = [...(fileList.value || []), file];
|
fileList.value = [...(fileList.value || []), file];
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
function doUpload(){
|
async function doUpload(){
|
||||||
|
if(props.importType=='tenantMode'){
|
||||||
|
try{
|
||||||
|
await formRef.value!.validate();
|
||||||
|
}catch(error){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
if(fileList==undefined||fileList.value.length==0){
|
if(fileList==undefined||fileList.value.length==0){
|
||||||
notification.error({
|
notification.error({
|
||||||
message: '提示',
|
message: '提示',
|
||||||
@ -106,8 +127,8 @@
|
|||||||
name: 'file',
|
name: 'file',
|
||||||
file: files,
|
file: files,
|
||||||
data:{
|
data:{
|
||||||
configType:props.configType,
|
importType:props.importType,
|
||||||
cover:props.coverType=='override'?true:false
|
tenantCode:formModel.value.tenantCode
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
).then((data) => {
|
).then((data) => {
|
||||||
@ -125,6 +146,12 @@
|
|||||||
|
|
||||||
</script>
|
</script>
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
.tenant-box{
|
||||||
|
height:100px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
.upload-box {
|
.upload-box {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,30 +1,116 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="import">
|
<div class="import">
|
||||||
<ImportSystemConfig coverType="new">
|
<div class="import-log"><span @click.stop="showLogsDialog">查看导入日志</span></div>
|
||||||
<span class="item-action">新增模式导入</span>
|
<div class="import-type-wrapper">
|
||||||
</ImportSystemConfig>
|
<ImportSystemConfig importType="tenantMode">
|
||||||
<ImportSystemConfig coverType="override">
|
<span class="item-action">租户模式导入</span>
|
||||||
<span class="item-action">覆盖模式导入</span>
|
</ImportSystemConfig>
|
||||||
</ImportSystemConfig>
|
<ImportSystemConfig importType="overrideMode">
|
||||||
|
<span class="item-action">覆盖模式导入</span>
|
||||||
|
</ImportSystemConfig>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<a-modal
|
||||||
|
v-model:visible="logsDialog.visible"
|
||||||
|
:title="t('导入日志')"
|
||||||
|
:maskClosable="false"
|
||||||
|
:width="700"
|
||||||
|
:footer="null"
|
||||||
|
>
|
||||||
|
<div class="logs-content">
|
||||||
|
<template v-for="item in logs" :key="item.index">
|
||||||
|
<div class="log">
|
||||||
|
日志时间:<span class='log-time'>{{item.time}}</span>
|
||||||
|
执行结果:<span :class="{'success':item.result=='success','fail':item.result!=='success'}">{{item.result=='success'?'成功':'失败'}}</span>
|
||||||
|
<span class="view-log-detail" v-if="item.result!=='success'" @click.stop="viewLogDetails(item.fileName)" >查看日志详情</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</a-modal>
|
||||||
|
<a-modal
|
||||||
|
v-model:visible="logDetailsDialog.visible"
|
||||||
|
:title="t('日志详情')"
|
||||||
|
:maskClosable="false"
|
||||||
|
:width="700"
|
||||||
|
:footer="null"
|
||||||
|
>
|
||||||
|
<div class="log-details">
|
||||||
|
<a-textarea v-model:value="logDetails" :style="{whiteSpace:'pre',overflowX: 'auto',color:'red'}" :rows="20" />
|
||||||
|
</div>
|
||||||
|
</a-modal>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
import { reactive,ref} from 'vue';
|
||||||
|
import { useI18n } from '/@/hooks/web/useI18n';
|
||||||
import ImportSystemConfig from './ImportSystemConfig.vue';
|
import ImportSystemConfig from './ImportSystemConfig.vue';
|
||||||
|
import { getLogList,getLogDetails} from '/@/api/system/dataMigration';
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
|
||||||
|
const logsDialog: {
|
||||||
|
visible: boolean;
|
||||||
|
} = reactive({
|
||||||
|
visible: false
|
||||||
|
});
|
||||||
|
|
||||||
|
const logDetailsDialog: {
|
||||||
|
visible: boolean;
|
||||||
|
} = reactive({
|
||||||
|
visible: false
|
||||||
|
});
|
||||||
|
|
||||||
|
const logs=ref([]);
|
||||||
|
const logDetails=ref([]);
|
||||||
|
|
||||||
|
async function showLogsDialog(){
|
||||||
|
logs.value=[];
|
||||||
|
logsDialog.visible=true;
|
||||||
|
let resList=await getLogList();
|
||||||
|
logs.value=resList;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
async function viewLogDetails(fileName:String){
|
||||||
|
let logContent=await getLogDetails(fileName);
|
||||||
|
logDetailsDialog.visible=true;
|
||||||
|
logDetails.value=logContent;
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
.import{
|
.import{
|
||||||
|
height:100%;
|
||||||
|
width:100%;
|
||||||
|
border:1px solid #d6d6d6;
|
||||||
|
border-radius:8px;
|
||||||
|
padding:10px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.import-log{
|
||||||
|
height:100px;
|
||||||
|
width:100%;
|
||||||
|
span{
|
||||||
|
color: rgba(0,0,255,0.8);
|
||||||
|
text-decoration:underline rgba(#0000ff,0.8);
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 16px;
|
||||||
|
cursor: pointer;
|
||||||
|
&:hover{
|
||||||
|
color: rgba(0,0,255,1);
|
||||||
|
text-decoration:underline #0000ff;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.import-type-wrapper{
|
||||||
display:flex;
|
display:flex;
|
||||||
flex-direction:row;
|
flex-direction:row;
|
||||||
align-items:center;
|
align-items:center;
|
||||||
justify-content:center;
|
justify-content:center;
|
||||||
height:100%;
|
height:calc(100% - 100px);
|
||||||
width:100%;
|
width:100%;
|
||||||
gap:100px;
|
gap:100px;
|
||||||
border:1px solid #d6d6d6;
|
|
||||||
border-radius:8px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-action {
|
.item-action {
|
||||||
@ -40,4 +126,37 @@
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.logs-content{
|
||||||
|
width:100%;
|
||||||
|
height:500px;
|
||||||
|
overflow-y:scroll;
|
||||||
|
padding:30px 30px;
|
||||||
|
.log{
|
||||||
|
padding:5px 0px;
|
||||||
|
.log-time{
|
||||||
|
color:rgba(22, 119, 224, 1);
|
||||||
|
margin-right:30px;
|
||||||
|
}
|
||||||
|
.success{
|
||||||
|
color:green;
|
||||||
|
}
|
||||||
|
.fail{
|
||||||
|
color:red;
|
||||||
|
}
|
||||||
|
.view-log-detail{
|
||||||
|
margin-left:30px;
|
||||||
|
color:rgba(22, 119, 224, 1);
|
||||||
|
&:hover{
|
||||||
|
text-decoration:underline;
|
||||||
|
cursor:pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.log-details{
|
||||||
|
height:500px;
|
||||||
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user