diff --git a/src/core/components/clickable-operation-id.jsx b/src/core/components/clickable-operation-id.jsx
new file mode 100644
index 00000000000..e46ed2d213c
--- /dev/null
+++ b/src/core/components/clickable-operation-id.jsx
@@ -0,0 +1,52 @@
+import React, { Component } from "react"
+import { CopyToClipboard } from "react-copy-to-clipboard"
+import PropTypes from "prop-types"
+
+/**
+ * 可点击复制的 operationId 组件
+ * 点击 operationId 文本即可复制到剪贴板
+ */
+export default class ClickableOperationId extends Component {
+ constructor(props) {
+ super(props)
+ this.state = {
+ copied: false
+ }
+ }
+
+ handleCopy = () => {
+ this.setState({ copied: true })
+ // 2秒后重置状态
+ setTimeout(() => {
+ this.setState({ copied: false })
+ }, 2000)
+ }
+
+ render() {
+ const { operationId, originalOperationId } = this.props
+ const { copied } = this.state
+
+ const idToCopy = originalOperationId || operationId
+
+ if (!idToCopy) {
+ return null
+ }
+
+ return (
+
+
+ {idToCopy}
+ {copied && ✓}
+
+
+ )
+ }
+
+ static propTypes = {
+ operationId: PropTypes.string,
+ originalOperationId: PropTypes.string,
+ }
+}
\ No newline at end of file
diff --git a/src/core/components/copy-operation-id-btn.jsx b/src/core/components/copy-operation-id-btn.jsx
new file mode 100644
index 00000000000..c622b4818a3
--- /dev/null
+++ b/src/core/components/copy-operation-id-btn.jsx
@@ -0,0 +1,35 @@
+import React from "react"
+import { CopyToClipboard } from "react-copy-to-clipboard"
+import PropTypes from "prop-types"
+
+/**
+ * 专门用于复制 operationId 的按钮组件
+ * @param {{ getComponent: func, operationId: string, title?: string }} props
+ * @returns {JSX.Element}
+ * @constructor
+ */
+export default class CopyOperationIdBtn extends React.Component {
+ render() {
+ let { getComponent, operationId, title = "Copy operationId to clipboard" } = this.props
+
+ if (!operationId) {
+ return null
+ }
+
+ const CopyIcon = getComponent("CopyIcon")
+
+ return (
+
+
+
+
+
+ )
+ }
+
+ static propTypes = {
+ getComponent: PropTypes.func.isRequired,
+ operationId: PropTypes.string,
+ title: PropTypes.string,
+ }
+}
\ No newline at end of file
diff --git a/src/core/components/operation-summary.jsx b/src/core/components/operation-summary.jsx
index d31f56d3f9c..ae86bfbf0a7 100644
--- a/src/core/components/operation-summary.jsx
+++ b/src/core/components/operation-summary.jsx
@@ -59,6 +59,8 @@ export default class OperationSummary extends PureComponent {
const OperationSummaryPath = getComponent("OperationSummaryPath")
const JumpToPath = getComponent("JumpToPath", true)
const CopyToClipboardBtn = getComponent("CopyToClipboardBtn", true)
+ const CopyOperationIdBtn = getComponent("CopyOperationIdBtn", true)
+ const ClickableOperationId = getComponent("ClickableOperationId", true)
const ArrowUpIcon = getComponent("ArrowUpIcon")
const ArrowDownIcon = getComponent("ArrowDownIcon")
@@ -83,9 +85,18 @@ export default class OperationSummary extends PureComponent {
}
- {displayOperationId && (originalOperationId || operationId) ? {originalOperationId || operationId} : null}
+ {displayOperationId && (originalOperationId || operationId) ?
+ : null}
+ {displayOperationId && (originalOperationId || operationId) ?
+ : null}
{
allowAnonymous ? null :
({
License,
JumpToPath,
CopyToClipboardBtn,
+ CopyOperationIdBtn,
+ ClickableOperationId,
onlineValidatorBadge: OnlineValidatorBadge,
operations: Operations,
operation: Operation,
diff --git a/src/style/_buttons.scss b/src/style/_buttons.scss
index 7806d17ee1d..667c9f81c92 100644
--- a/src/style/_buttons.scss
+++ b/src/style/_buttons.scss
@@ -197,3 +197,18 @@ button {
height: 26px;
position: unset;
}
+
+// styles for copy operation id button
+.opblock .opblock-summary .view-line-link.copy-operation-id {
+ height: 26px;
+ position: unset;
+ background: #49cc90; // 使用绿色来区分 operationId 复制按钮
+
+ &:hover {
+ background: #3ea876;
+ }
+
+ &:active {
+ background: #2e8a5f;
+ }
+}
diff --git a/src/style/_layout.scss b/src/style/_layout.scss
index b6f3ba7727f..9a2cbd91362 100644
--- a/src/style/_layout.scss
+++ b/src/style/_layout.scss
@@ -300,6 +300,28 @@
.opblock-summary-operation-id {
font-size: 14px;
+
+ &.clickable {
+ cursor: pointer;
+ transition: all 0.2s ease;
+ padding: 2px 4px;
+ border-radius: 3px;
+
+ &:hover {
+ background-color: rgba(0, 0, 0, 0.05);
+ color: #3b4151;
+ }
+
+ &.copied {
+ background-color: #4caf50;
+ color: white;
+ }
+
+ .copy-feedback {
+ font-size: 12px;
+ margin-left: 4px;
+ }
+ }
}
.opblock-summary-description {