Merge pull request #4311 from dataease/feat_app-class-move

feat(应用): 应用支持移动到其他分类
This commit is contained in:
王嘉豪 2023-01-06 18:45:28 +08:00 committed by GitHub
commit 6cfc4bb8e9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 306 additions and 7 deletions

View File

@ -8,6 +8,7 @@ import io.dataease.service.panel.PanelAppTemplateService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.List;
@ -57,7 +58,14 @@ public class PanelAppTemplateController {
@PostMapping("/nameCheck")
@I18n
public String nameCheck(@RequestBody PanelAppTemplateRequest request) {
return panelAppTemplateService.nameCheck(request);
return panelAppTemplateService.nameCheck(request);
}
@ApiOperation("移动")
@PostMapping("/move")
@I18n
public void move(@RequestBody PanelAppTemplateRequest request) {
panelAppTemplateService.move(request);
}
}

View File

@ -120,6 +120,16 @@ public class PanelAppTemplateService {
}
public void move(PanelAppTemplateRequest request) {
if (!CommonConstants.CHECK_RESULT.NONE.equals(nameCheck(CommonConstants.OPT_TYPE.INSERT, request.getName(), request.getPid(), request.getId()))) {
throw new RuntimeException("当前名称在目标分类中已经存在!请选择其他分类或修改名称");
}
PanelAppTemplateWithBLOBs appTemplate = new PanelAppTemplateWithBLOBs();
appTemplate.setId(request.getId());
appTemplate.setPid(request.getPid());
panelAppTemplateMapper.updateByPrimaryKeySelective(appTemplate);
}
//名称检查
public String nameCheck(String optType, String name, String pid, String id) {
PanelAppTemplateExample example = new PanelAppTemplateExample();

View File

@ -56,3 +56,11 @@ export function nameCheck(data) {
method: 'post'
})
}
export function move(data) {
return request({
url: '/appTemplate/move',
data: data,
method: 'post'
})
}

View File

@ -2787,6 +2787,8 @@ export default {
'I18N_USER_TEMPLATE_ERROR': 'Template file error',
'i18n_max_user_import_size': 'File size exceeds 10M',
app_template: {
move: 'Move',
move_item: 'Move App',
datasource_new: 'New',
datasource_history: 'Multiplexing',
datasource_from: 'Datasource From',

View File

@ -2781,6 +2781,8 @@ export default {
'I18N_USER_TEMPLATE_ERROR': '模版錯誤',
'i18n_max_user_import_size': '文件最大不能超過10M',
app_template: {
move: '移動',
move_item: '移動應用',
datasource_new: '新建',
datasource_history: '復用',
datasource_from: '數據來源',

View File

@ -2781,6 +2781,8 @@ export default {
'I18N_USER_TEMPLATE_ERROR': '模版错误',
'i18n_max_user_import_size': '文件最大不能超过10M',
app_template: {
move: '移动',
move_item: '移动应用',
datasource_new: '新建',
datasource_history: '复用',
datasource_from: '数据来源',

View File

@ -77,7 +77,7 @@
:label="dialogTitleLabel"
prop="name"
>
<el-input v-model="templateEditForm.name" />
<el-input v-model="templateEditForm.name"/>
</el-form-item>
<el-form-item
:label="$t('app_template.app_group_icon')"
@ -95,7 +95,7 @@
:http-request="upload"
:file-list="fileList"
>
<i class="el-icon-plus" />
<i class="el-icon-plus"/>
</el-upload>
<el-dialog
top="25vh"
@ -147,6 +147,23 @@
@closeEditTemplateDialog="closeEditTemplateDialog"
/>
</el-dialog>
<!--导入templatedialog-->
<el-dialog
:title="$t('app_template.move_item') "
:visible.sync="moveItemDialogShow"
:show-close="true"
class="de-dialog-form"
width="300px"
>
<template-move-list
:template-list="templateList"
:source-template-info="currentMoveItem"
@closeDialog="moveItemDialogShow=false"
@templateMoveClose="templateMoveClose"
>
</template-move-list>
</el-dialog>
</div>
</template>
@ -159,10 +176,11 @@ import elementResizeDetectorMaker from 'element-resize-detector'
import msgCfm from '@/components/msgCfm/index'
import { uploadFileResult } from '@/api/staticResource/staticResource'
import { imgUrlTrans } from '@/components/canvas/utils/utils'
import TemplateMoveList from '@/views/panel/appTemplate/component/TemplateMoveList'
export default {
name: 'AppTemplateContent',
components: { TemplateList, TemplateItem, TemplateImport },
components: { TemplateMoveList, TemplateList, TemplateItem, TemplateImport },
mixins: [msgCfm],
props: {
showPosition: {
@ -173,6 +191,8 @@ export default {
},
data() {
return {
moveItemDialogShow: false,
currentMoveItem: {},
templateOptType: 'add',
currentAppTemplateInfo: null,
fileList: [],
@ -302,6 +322,9 @@ export default {
case 'update':
this.updateAppTemplate(data)
break
case 'move':
this.moveTo(data)
break
default:
break
}
@ -312,6 +335,10 @@ export default {
this.currentAppTemplateInfo = data
this.templateDialog.pid = data.pid
},
moveTo(data) {
this.moveItemDialogShow = true
this.currentMoveItem = data
},
templateDeleteConfirm(template) {
const options = {
title: '是否卸载当前应用?',
@ -349,6 +376,10 @@ export default {
})
}
},
templateMoveClose() {
this.moveItemDialogShow = false
this.showCurrentTemplate(this.currentTemplateId, this.currentTemplateLabel)
},
showTemplateEditDialog(type, templateInfo) {
this.templateEditForm = null
this.formType = type

View File

@ -29,20 +29,26 @@
trigger="click"
@command="handleCommand"
>
<i class="el-icon-more" />
<i class="el-icon-more"/>
<el-dropdown-menu
slot="dropdown"
class="de-card-dropdown"
>
<slot>
<el-dropdown-item command="update">
<i class="el-icon-edit" />
<i class="el-icon-edit"/>
{{ $t('commons.update') }}
</el-dropdown-item>
<el-dropdown-item command="delete">
<i class="el-icon-delete" />
<i class="el-icon-delete"/>
{{ $t('commons.uninstall') }}
</el-dropdown-item>
<el-dropdown-item
icon="el-icon-right"
command="move"
>
{{ $t('app_template.move') }}
</el-dropdown-item>
</slot>
</el-dropdown-menu>
</el-dropdown>
@ -84,6 +90,7 @@
</template>
<script>
import { imgUrlTrans } from '@/components/canvas/utils/utils'
export default {
props: {
showPosition: {

View File

@ -0,0 +1,229 @@
<template xmlns:el-col="http://www.w3.org/1999/html">
<div class="de-template-list">
<el-input
v-model="templateFilterText"
:placeholder="$t('system_parameter_setting.search_keywords')"
size="small"
class="de-input-search"
clearable
>
<svg-icon
slot="prefix"
icon-class="de-search"
/>
</el-input>
<el-empty
v-if="!templateListComputed.length && templateFilterText === ''"
:image="noneImg"
:description="$t('components.no_classification')"
/>
<el-empty
v-if="!templateListComputed.length && templateFilterText !== ''"
:image="nothingImg"
:description="$t('components.relevant_content_found')"
/>
<ul>
<li
v-for="ele in templateListComputed"
:key="ele.name"
:class="[{ select: activeTemplate === ele.id }]"
@click="nodeClick(ele)"
>
<img
:src="iconImgRul(ele.icon)"
style="margin-right: 8px;border-radius: 4px"
width="24"
height="24"
>
<span>{{ ele.name }}</span>
</li>
</ul>
<el-row class="de-root-class">
<deBtn
secondary
@click="cancel()"
>{{
$t('commons.cancel')
}}
</deBtn>
<deBtn
type="primary"
@click="save()"
:disabled="!activeTemplate"
>{{
$t('commons.confirm')
}}
</deBtn>
</el-row>
</div>
</template>
<script>
import msgCfm from '@/components/msgCfm/index'
import { imgUrlTrans } from '@/components/canvas/utils/utils'
import { move } from '@/api/system/appTemplate'
export default {
name: 'TemplateMoveList',
components: {},
mixins: [msgCfm],
props: {
sourceTemplateInfo: {
type: Object
},
templateList: {
type: Array,
default: function() {
return []
}
}
},
data() {
return {
templateFilterText: '',
activeTemplate: '',
noneImg: require('@/assets/None.png'),
nothingImg: require('@/assets/nothing.png')
}
},
computed: {
templateListComputed() {
if (!this.templateFilterText) {
return this.templateList.filter((ele) =>
ele.id !== this.sourceTemplateInfo.pid
)
}
return this.templateList.filter((ele) =>
ele.name.includes(this.templateFilterText) && ele.id !== this.sourceTemplateInfo.pid
)
}
},
methods: {
iconImgRul(iconUrl) {
return imgUrlTrans(iconUrl)
},
cancel() {
this.$emit('closeDialog')
},
save() {
const request = {
id: this.sourceTemplateInfo.id,
pid: this.activeTemplate,
name: this.sourceTemplateInfo.name
}
move(request).then((response) => {
this.$emit('templateMoveClose')
})
},
showPositionCheck(requiredPosition) {
return this.showPosition === requiredPosition
},
nodeClick({ id, name }) {
this.activeTemplate = id
}
}
}
</script>
<style scoped lang="scss">
.de-template-list {
height: 380px;
overflow-y: hidden;
position: relative;
ul {
margin: 16px 0 20px 0;
padding: 0;
overflow-y: auto;
max-height: calc(100% - 90px);
}
li {
list-style: none;
width: 100%;
box-sizing: border-box;
height: 40px;
padding: 0 30px 0 12px;
display: flex;
align-items: center;
border-radius: 4px;
color: var(--deTextPrimary, #1f2329);
font-family: "PingFang SC";
font-style: normal;
font-weight: 500;
font-size: 14px;
cursor: pointer;
position: relative;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
.folder {
color: #8f959e;
margin-right: 9px;
}
.more {
position: absolute;
top: 50%;
right: 10px;
transform: translateY(-50%);
display: none;
.el-icon-more {
width: 24px;
height: 24px;
line-height: 24px;
text-align: center;
font-size: 12px;
color: #646a73;
cursor: pointer;
}
.el-icon-more:hover {
background: rgba(31, 35, 41, 0.1);
border-radius: 4px;
}
.el-icon-more:active {
background: rgba(31, 35, 41, 0.2);
border-radius: 4px;
}
}
&:hover {
background: rgba(31, 35, 41, 0.1);
.more {
display: block;
}
}
}
li.select {
background: var(--deWhiteHover, #3370ff);
color: var(--TextActive, #f4f4f5);
}
.de-btn-fix {
position: absolute;
bottom: 0;
left: 0;
}
}
.de-template-dropdown {
margin-top: 0 !important;
.popper__arrow {
display: none !important;
}
}
.de-root-class {
bottom: 0;
width: 100%;
position: absolute;
text-align: right;
}
</style>