提交 9b188bb7 编写于 作者: aaronchen2k2k's avatar aaronchen2k2k

copy, paste and delete tree node

上级 8cfcc360
此差异已折叠。
......@@ -6,6 +6,7 @@ import (
"fmt"
"github.com/easysoft/zentaoatf/internal/pkg/consts"
commonUtils "github.com/easysoft/zentaoatf/internal/pkg/lib/common"
cp "github.com/otiai10/copy"
"io"
"io/ioutil"
"os"
......@@ -144,29 +145,41 @@ func GetFilesFromParams(arguments []string) []string {
return ret
}
func CopyFile(src, dst string) (int64, error) {
func CopyFile(src, dst string) (nBytes int64, err error) {
sourceFileStat, err := os.Stat(src)
if err != nil {
return 0, err
return
}
if !sourceFileStat.Mode().IsRegular() {
return 0, fmt.Errorf("%s is not a regular file", src)
err = fmt.Errorf("%s is not a regular file", src)
return
}
source, err := os.Open(src)
if err != nil {
return 0, err
return
}
defer source.Close()
destination, err := os.Create(dst)
if err != nil {
return 0, err
return
}
defer destination.Close()
nBytes, err := io.Copy(destination, source)
return nBytes, err
nBytes, err = io.Copy(destination, source)
return
}
func CopyDir(src, dest string) (err error) {
opt := cp.Options{
Skip: func(src string) (bool, error) {
return strings.HasSuffix(src, ".git"), nil
},
}
err = cp.Copy(src, dest, opt)
return
}
func GetFileName(pathOrUrl string) string {
......
......@@ -124,6 +124,23 @@ func (c *TestScriptCtrl) UpdateName(ctx iris.Context) {
ctx.JSON(c.SuccessResp(nil))
}
func (c *TestScriptCtrl) Paste(ctx iris.Context) {
req := serverDomain.PasteScriptReq{}
err := ctx.ReadJSON(&req)
if err != nil {
ctx.JSON(c.ErrResp(commConsts.CommErr, err.Error()))
}
err = c.TestScriptService.Paste(req)
if err != nil {
ctx.JSON(c.ErrResp(commConsts.CommErr, err.Error()))
return
}
ctx.JSON(c.SuccessResp(nil))
}
func (c *TestScriptCtrl) Move(ctx iris.Context) {
req := serverDomain.MoveScriptReq{}
......@@ -132,8 +149,8 @@ func (c *TestScriptCtrl) Move(ctx iris.Context) {
ctx.JSON(c.ErrResp(commConsts.CommErr, err.Error()))
}
bizErr := c.TestScriptService.Move(req)
if bizErr != nil {
err = c.TestScriptService.Move(req)
if err != nil {
ctx.JSON(c.ErrResp(commConsts.CommErr, err.Error()))
return
}
......
......@@ -28,6 +28,17 @@ type CreateScriptReq struct {
ProductId int `json:"productId"`
}
type PasteScriptReq struct {
SrcKey string `json:"srcKey"`
SrcType commConsts.TreeNodeType `json:"srcType"`
SrcWorkspaceId int `json:"srcWorkspaceId"`
DistKey string `json:"distKey"`
DistType commConsts.TreeNodeType `json:"distType"`
DistWorkspaceId int `json:"distWorkspaceId"`
Action string `json:"action"`
}
type MoveScriptReq struct {
DragKey string `json:"dragKey"`
DropKey string `json:"dropKey"`
......
......@@ -28,6 +28,7 @@ func (m *TestScriptModule) Party() module.WebModule {
index.Put("/updateCode", m.TestScriptCtrl.UpdateCode).Name = "更新脚本"
index.Put("/updateName", m.TestScriptCtrl.UpdateName).Name = "重命令脚本"
index.Put("/paste", m.TestScriptCtrl.Paste).Name = "粘贴脚本"
index.Put("/move", m.TestScriptCtrl.Move).Name = "移动脚本"
index.Get("/extract", m.TestScriptCtrl.Extract).Name = "抽取脚本"
......
......@@ -178,7 +178,7 @@ func (s *TestScriptService) UpdateName(script serverDomain.TestScript) (err erro
}
func (s *TestScriptService) Delete(pth string) (bizErr *domain.BizError) {
err := os.Remove(pth)
err := os.RemoveAll(pth)
_, ok := err.(*os.PathError)
if ok {
......@@ -207,3 +207,23 @@ func (s *TestScriptService) Move(req serverDomain.MoveScriptReq) (err error) {
return
}
func (s *TestScriptService) Paste(req serverDomain.PasteScriptReq) (err error) {
distPath := filepath.Join(req.DistKey, filepath.Base(req.SrcKey))
if distPath == req.SrcKey {
return
}
if req.Action == "copy" {
if req.SrcType == commConsts.File {
fileUtils.CopyFile(req.SrcKey, distPath)
} else {
fileUtils.CopyDir(req.SrcKey, distPath)
}
} else if req.Action == "cut" {
os.Rename(req.SrcKey, distPath)
}
return
}
......@@ -215,6 +215,7 @@ export default {
'input_keyword_to_search': 'Input Keyword To Search',
'tips_test_cmd': 'Please run "{cmd}" with command line.',
'node': 'Node',
'sync-from-zentao': 'Sync From Zentao',
'sync-to-zentao': 'Sync To Zentao',
'copy': 'Copy',
......
......@@ -226,6 +226,7 @@ export default {
'switch_display_bottom_side': '切换显示底部边栏',
'switch_display_right_side': '切换显示右侧边栏',
'node': '节点',
'sync-from-zentao': '从禅道同步',
'sync-to-zentao': '同步到禅道',
'copy': '复制',
......
......@@ -17,9 +17,12 @@
<div v-if="treeNode.type != 'workspace'" @click="menuClick('cut')" class="menu-item">
<span>{{t('cut')}}</span>
</div>
<div v-if="clipboard?.id && treeNode?.type != 'dir'" @click="menuClick('paste')" class="menu-item">
<div v-if="clipboardData?.id && (treeNode?.type == 'workspace' || treeNode?.type == 'dir')" @click="menuClick('paste')" class="menu-item">
<span>{{t('paste')}}</span>
</div>
<div v-if="treeNode?.type != 'workspace'" @click="menuClick('delete')" class="menu-item">
<span>{{t('delete')}}</span>
</div>
<div @click="menuClick('open-in-explore')" class="menu-item">
<span>{{t('open-in-explore')}}</span>
......@@ -46,7 +49,7 @@ export default defineComponent({
type: Function as PropType<(menuKey: string, targetId: number) => void>,
required: true
},
clipboard: {
clipboardData: {
type: Object,
required: false
},
......
......@@ -21,7 +21,7 @@
/>
<div v-if="contextNode.id && rightVisible" :style="menuStyle">
<TreeContextMenu :treeNode="contextNode" :onMenuClick="menuClick"/>
<TreeContextMenu :treeNode="contextNode" :clipboardData="clipboardData" :onMenuClick="menuClick"/>
</div>
</div>
</template>
......@@ -50,7 +50,7 @@ import {
import {
getCaseIdsFromReport,
getNodeMap,
listFilterItems,
listFilterItems, pasteNode,
} from "@/views/script/service";
import { useRouter } from "vue-router";
import { isWindows } from "@/utils/comm";
......@@ -421,11 +421,12 @@ const expandNode = (expandedKeysMap) => {
setExpandedKeys(currSite.value.id, currProduct.value.id, expandedKeys.value)
}
let menuStyle = ref({} as any)
let contextNode = ref({} as any)
let targetModelId = 0
const menuStyle = ref({} as any)
const contextNode = ref({} as any)
const clipboardAction = ref('')
const clipboardData = ref({} as any)
let rightVisible = ref(false)
const rightVisible = ref(false)
const onRightClick = (e) => {
console.log('onRightClick', e)
const {event, node} = e
......@@ -446,8 +447,43 @@ const onRightClick = (e) => {
}
const menuClick = (menuKey: string, targetId: number) => {
console.log('menuClick', menuKey, targetId)
targetModelId = targetId
console.log('menuClick', menuKey, treeDataMap.value[targetId])
const contextNodeData = treeDataMap.value[targetId]
if (menuKey === 'copy' || menuKey === 'cut') {
clipboardAction.value = menuKey
clipboardData.value = contextNodeData
} else if (menuKey === 'paste') {
console.log(clipboardData.value)
const data = {
srcKey: clipboardData.value.id,
srcType: clipboardData.value.type,
srcWorkspaceId: clipboardData.value.workspaceId,
distKey: contextNodeData.id,
distType: contextNodeData.type,
distWorkspaceId: contextNodeData.workspaceId,
action: clipboardAction.value,
}
store.dispatch('Script/pasteScript', data)
} else if (menuKey === 'delete') {
Modal.confirm({
title: t("confirm_delete", {
name: contextNodeData.title,
typ: t("node"),
}),
okText: t("confirm"),
cancelText: t("cancel"),
onOk: async () => {
store.dispatch('Script/deleteScript', contextNodeData.id)
},
});
} else {
clipboardAction.value = ''
clipboardData.value = {}
}
clearMenu()
}
......
......@@ -74,6 +74,14 @@ export async function updateNameReq(path: string, name: string): Promise<any> {
});
}
export async function paste(data: any): Promise<any> {
return request({
url: `/${apiPath}/paste`,
method: 'PUT',
data
});
}
export async function move(data: any): Promise<any> {
return request({
url: `/${apiPath}/move`,
......
......@@ -3,7 +3,19 @@ import { StoreModuleType } from "@/utils/store";
import { ResponseData } from '@/utils/request';
import {
list, get, extract, create, update, remove, loadChildren, updateCode, syncFromZentao, syncToZentao, move, scriptTreeAddAttr, getNodeMap
list,
get,
extract,
create,
update,
remove,
loadChildren,
updateCode,
syncFromZentao,
syncToZentao,
paste, move,
scriptTreeAddAttr,
getNodeMap,
} from './service';
import {ScriptFileNotExist} from "@/utils/const";
......@@ -39,6 +51,7 @@ export interface ModuleType extends StoreModuleType<ScriptData> {
createScript: Action<ScriptData, ScriptData>;
updateScript: Action<ScriptData, ScriptData>;
deleteScript: Action<ScriptData, ScriptData>;
pasteScript: Action<ScriptData, ScriptData>;
moveScript: Action<ScriptData, ScriptData>;
updateCode: Action<ScriptData, ScriptData>;
};
......@@ -188,6 +201,17 @@ const StoreModel: ModuleType = {
}
},
async pasteScript({ commit , dispatch, state}, data: any ) {
try {
await paste(data);
await dispatch('listScript', state.queryParams)
return true;
} catch (error) {
return false;
}
},
async moveScript({ commit , dispatch, state}, data: any ) {
try {
await move(data);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册