优化teleport拖拽

This commit is contained in:
2025-05-17 18:04:53 +08:00
parent 09fe532bb6
commit aa0290b345
30 changed files with 518 additions and 981 deletions

View File

@@ -0,0 +1,93 @@
<script lang="tsx">
import { defineComponent, ref } from "vue"
import { Modal, Form, FormItem, Input, Space, Button, Alert, Message } from "@arco-design/web-vue"
// 导入替换白名单
import handleSubmit from "./replaceFieldName"
export default defineComponent({
name: "BulkPeplaceModal",
props: {
parentForm: { type: Object, required: true }
},
setup(props, { expose }) {
// ref
const formRef = ref()
// refs
const visible = ref(false)
const formData = ref({
originText: "",
replaceText: ""
})
// inner-functions
const submit = (record: { values: any; error: any }) => {
handleSubmit(record, props.parentForm, formData)
}
// obj-functions
const open = () => {
// 如果已经打开则关闭,清空查询
formData.value = {
originText: "",
replaceText: ""
}
visible.value = visible.value === true ? false : true
}
// expose
expose({ open })
return () => (
<div class="bulk-replace-container">
<Modal
draggable
unmount-on-close
title="替换当前页面文本"
width="500px"
v-model:visible={visible.value}
mask={false}
popup-container="#form-main-id"
modal-class="modal-container-custom-shadow"
modalAnimationName="fade"
footer={false}
>
<Alert type="warning" class="mb-2">
无法替换时间等非文本字段
</Alert>
<Form model={formData.value} onSubmit={submit} ref={formRef}>
<FormItem
field="originText"
label="被替文本"
validate-trigger={["change", "blur"]}
rules={[
{
required: true,
message: "请输入查找和被替换的文本"
}
]}
>
<Input placeholder="请输入被替换文本" v-model={formData.value.originText}></Input>
</FormItem>
<FormItem field="replaceText" label="被替换为" validate-trigger={["change", "blur"]}>
<Input placeholder="请输入替换的文本" v-model={formData.value.replaceText}></Input>
</FormItem>
<FormItem>
<Space>
<Button type="primary" html-type="submit">
全部替换
</Button>
<Button onClick={() => formRef.value.resetFields()}>重置</Button>
</Space>
</FormItem>
</Form>
</Modal>
</div>
)
}
})
</script>
<style lang="less">
.modal-container-custom-shadow {
box-shadow: 0 0 2px rgba(0, 0, 0, 0.5);
}
</style>

View File

@@ -0,0 +1,73 @@
import { Message } from "@arco-design/web-vue"
// 注意该白名单仅支持替换“字符串”and“数组”其他不行!
const replaceField = [
"initialization", // 用例:初始化
"name", // 各个form的名称
"premise", // 用例:前提和约束
"summarize", // 用例:综述
"testStep", // 用例:步骤,数组包含{operation:"",expect:""}
"testDesciption", // 测试项:测试项描述
"testContent" // 测试项:子项
]
const handleSubmit = (record: { values: any; error: any }, parentForm: any, formData: any) => {
if (record.error) return
// 替换逻辑
Object.keys(parentForm).forEach((fieldName) => {
if (replaceField.includes(fieldName)) {
// 如果存在白名单里面,在判断是文本还是数组
const lineData = parentForm[fieldName]
if (typeof lineData === "string") {
// string则直接替换
parentForm[fieldName] = parentForm[fieldName].replaceAll(
formData.value.originText,
formData.value.replaceText
)
} else if (Array.isArray(lineData)) {
parentForm[fieldName].forEach(
(obj: { operation: string; expect: string; result: string; subName: string; subStep: string }) => {
// 用例数组只能替换对象operation、expect、result
if (obj.operation) {
obj.operation = obj.operation.replaceAll(
formData.value.originText,
formData.value.replaceText
)
}
if (obj.expect) {
obj.expect = obj.expect.replaceAll(formData.value.originText, formData.value.replaceText)
}
if (obj.result) {
obj.result = obj.result.replaceAll(formData.value.originText, formData.value.replaceText)
}
// 测试项:嵌套两层
if (obj.subName) {
obj.subName = obj.subName.replaceAll(formData.value.originText, formData.value.replaceText)
if (obj.subStep && Array.isArray(obj.subStep)) {
obj.subStep.forEach((step) => {
if (step.operation) {
step.operation = step.operation.replaceAll(
formData.value.originText,
formData.value.replaceText
)
}
if (step.expect) {
step.expect = step.expect.replaceAll(
formData.value.originText,
formData.value.replaceText
)
}
})
}
}
}
)
} else {
return
}
}
})
Message.success("替换成功")
}
export default handleSubmit

View File

@@ -166,14 +166,16 @@
</div>
</div>
<!-- 修改源码切换显示形态 -->
<a-popover>
<template #title>切换{{ props.component.type === "group" ? "表格" : "聚合" }}显示</template>
<div class="sticky-container" @click="swapTableOrGroupDisplay">
<div class="sticky-button">
<icon-swap />
<Teleport to="body">
<a-popover>
<template #title>切换{{ props.component.type === "group" ? "表格" : "聚合" }}显示</template>
<div class="sticky-container" @click="swapTableOrGroupDisplay">
<div class="sticky-button">
<icon-swap />
</div>
</div>
</div>
</a-popover>
</a-popover>
</Teleport>
</a-form-item>
</template>

View File

@@ -1,5 +1,5 @@
<template>
<div class="w-full">
<div class="w-full" ref="containerRef" id="form-main-id">
<a-spin :loading="formLoading" :tip="options.loadingText" class="w-full ma-form-spin">
<div
v-if="options.showFormTitle"
@@ -69,12 +69,25 @@
<template v-if="parentKey">
<ParentPreview :parent-key="parentKey"></ParentPreview>
</template>
<!-- ctrl+F的替换功能仅支持用例测试项 -->
<template v-if="form.testStep || form.testContent">
<teleport to="body">
<div class="alert-container">
<a-alert show-icon type="info">
<p>支持</p>
<p>Ctrl+F</p>
<p>替换</p>
</a-alert>
</div>
</teleport>
<BulkReplaceModal ref="replaceModalRef" :parent-form="form" />
</template>
</a-spin>
</div>
</template>
<script setup>
import { ref, watch, provide, onMounted, nextTick, getCurrentInstance, inject, computed } from "vue"
import { ref, watch, provide, onMounted, onUnmounted, nextTick, getCurrentInstance, inject, computed } from "vue"
import { isNil, set, get, cloneDeep } from "lodash-es"
import defaultOptions from "./js/defaultOptions.js"
import {
@@ -91,6 +104,8 @@ import ColumnService from "./js/columnService.js"
import { runEvent } from "./js/event.js"
import { Message } from "@arco-design/web-vue"
// 修改源码导入:查找和替换组件
import BulkReplaceModal from "@/components/ma-form/Customs/BulkReplaceModal.vue"
const formLoading = ref(false)
const maFormRef = ref()
@@ -100,7 +115,23 @@ const dictList = ref({})
const cascaderList = ref([])
const form = ref({})
// ~~~custom start - 新增功能利用key强制更新form表单组件
// ~~~custom start0 - 查找和替换组件
const replaceModalRef = ref()
const containerRef = ref()
const handleKeydown = (e) => {
if (e.ctrlKey && e.key === "f") {
e.preventDefault()
replaceModalRef.value && replaceModalRef.value.open()
}
}
onMounted(() => {
document.addEventListener("keydown", handleKeydown)
})
onUnmounted(() => {
document.removeEventListener("keydown", handleKeydown)
})
// ~~~custom start1 - 新增功能利用key强制更新form表单组件
const componentKey = ref(0)
const updateKey = () => {
componentKey.value += 1
@@ -113,7 +144,7 @@ const handleChangeDisplay = (type) => {
}
// ~~~custom end
// ~~~~custom start
// ~~~~custom start2
// 2025年5月14日新增功能hover查看上级节点
import ParentPreview from "@/views/project/ParentPreview/index.vue"
// 判断是否有
@@ -326,8 +357,21 @@ defineExpose({
</script>
<style lang="less" scoped>
div:deep(.arco-modal-container) {
pointer-events: none;
}
:deep(.arco-modal.arco-modal-draggable) {
pointer-events: auto;
}
.ma-form-title {
font-size: 18px;
text-align: center;
}
.alert-container {
position: fixed;
bottom: 50%;
user-select: none;
width: 113px;
z-index: 9999;
}
</style>