From bea0ab82fb932bad1602b93bff035db45c76e36c Mon Sep 17 00:00:00 2001 From: Yuikill <105910874+Yuikill@users.noreply.github.com> Date: Wed, 14 Jan 2026 10:17:17 +0800 Subject: [PATCH 01/13] =?UTF-8?q?feat:=20=E6=A0=87=E7=AD=BE=E7=AE=A1?= =?UTF-8?q?=E7=90=86=E5=8A=9F=E8=83=BD=20(#579)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/config/i18n/cn.js | 17 + frontend/src/config/i18n/en.js | 17 + frontend/src/constants/index.js | 8 +- frontend/src/constants/route.js | 6 + frontend/src/store/index.js | 2 + frontend/src/store/modules/label.js | 36 + frontend/src/store/modules/taskList.js | 3 + frontend/src/store/modules/template.js | 12 +- frontend/src/store/modules/templateList.js | 3 + frontend/src/views/admin/Space/Task/index.vue | 717 +++++---- .../Space/Template/CreateTaskSideslider.vue | 480 +++--- .../Space/Template/CreateTemplateDialog.vue | 253 ++- .../src/views/admin/Space/Template/index.vue | 1420 +++++++++-------- .../views/admin/Space/Template/label-cell.vue | 195 +++ .../views/admin/Space/common/LabelCascade.vue | 347 ++++ frontend/src/views/admin/Space/index.vue | 4 +- .../Space/labelManage/CreateLabelDialog.vue | 206 +++ .../views/admin/Space/labelManage/index.vue | 362 +++++ .../TemplateSetting/TabTemplateConfig.vue | 822 ++++++---- .../TemplateEdit/TemplateSetting/index.vue | 11 +- .../src/views/template/TemplateEdit/index.vue | 26 +- 21 files changed, 3367 insertions(+), 1580 deletions(-) create mode 100644 frontend/src/store/modules/label.js create mode 100644 frontend/src/views/admin/Space/Template/label-cell.vue create mode 100644 frontend/src/views/admin/Space/common/LabelCascade.vue create mode 100644 frontend/src/views/admin/Space/labelManage/CreateLabelDialog.vue create mode 100644 frontend/src/views/admin/Space/labelManage/index.vue diff --git a/frontend/src/config/i18n/cn.js b/frontend/src/config/i18n/cn.js index 1578a507a9..7cb3dcded1 100644 --- a/frontend/src/config/i18n/cn.js +++ b/frontend/src/config/i18n/cn.js @@ -1059,6 +1059,23 @@ const cn = { 参数名不能为空: '参数名不能为空', 参数名不能重复: '参数名不能重复', '请输入值或 $ 选择变量': '请输入值或 $ 选择变量', + labelReference: '{0} 个流程在引用,{1} 个任务在引用', + '搜索标签名称、标签范围、系统默认标签': '搜索标签名称、标签范围、系统默认标签', + 新增标签: '新增标签', + 标签名称: '标签名称', + 标签描述: '标签描述', + 标签范围: '标签范围', + 标签引用: '标签引用', + 系统默认标签: '系统默认标签', + 是: '是', + 否: '否', + 任务: '任务', + 流程: '流程', + '确认删除该标签?': '确认删除该标签?', + 关联的流程将同时移出本标签: '关联的流程将同时移出本标签', + '标签删除成功!': '标签删除成功!', + 编辑标签: '编辑标签', + 标签颜色: '标签颜色', }; export default cn; diff --git a/frontend/src/config/i18n/en.js b/frontend/src/config/i18n/en.js index 9ba229c05f..3dd136f8ec 100644 --- a/frontend/src/config/i18n/en.js +++ b/frontend/src/config/i18n/en.js @@ -1057,6 +1057,23 @@ const en = { 参数名不能为空: 'Parameter name cannot be empty', 参数名不能重复: 'Parameter name cannot be duplicated', '请输入值或 $ 选择变量': 'Enter value or $ to select variable', + labelReference: '{0} template is being referenced,{1} task is being referenced', + '搜索标签名称、标签范围、系统默认标签': 'Search Label Name, Label Scope, System Default Label', + 新增标签: 'Add Label', + 标签名称: 'Label Name', + 标签描述: 'Label Description', + 标签范围: 'Label Scope', + 标签引用: 'Label Reference', + 系统默认标签: 'System Default Label', + 是: 'Yes', + 否: 'No', + 任务: 'Task', + 流程: 'Template', + '确认删除该标签?': 'Confirm delete this label?', + 关联的流程将同时移出本标签: 'The associated process will also be removed from this label', + '标签删除成功!': 'Label deleted successfully!', + 编辑标签: 'Edit Label', + 标签颜色: 'Label Color', }; export default en; diff --git a/frontend/src/constants/index.js b/frontend/src/constants/index.js index 039873ec8d..eaf9489a5a 100644 --- a/frontend/src/constants/index.js +++ b/frontend/src/constants/index.js @@ -165,6 +165,12 @@ const COLOR_BLOCK_LIST = [ }, ]; +// 标签范围 +const LABEL_SCOPE = { + template: i18n.t('流程'), + task: i18n.t('任务'), +}; + const NAME_REG = /^[^'"‘’“”$<>]+$/; const PACKAGE_NAME_REG = /^[^\d][\w]*?$/; // celery的crontab时间表达式正则表达式(分钟 小时 星期 日 月)(以空格分割) @@ -178,5 +184,5 @@ const URL_REG = new RegExp('^(https?|ftp|file)://[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[- export { TASK_STATE_DICT, NODE_DICT, SYSTEM_GROUP_ICON, BK_PLUGIN_ICON, NAME_REG, INVALID_NAME_CHAR, PACKAGE_NAME_REG, URL_REG, PERIODIC_REG, STRING_LENGTH, - LABEL_COLOR_LIST, DARK_COLOR_LIST, TASK_CATEGORIES, COLOR_BLOCK_LIST, + LABEL_COLOR_LIST, DARK_COLOR_LIST, TASK_CATEGORIES, COLOR_BLOCK_LIST, LABEL_SCOPE, }; diff --git a/frontend/src/constants/route.js b/frontend/src/constants/route.js index 21697c7097..efec90906f 100644 --- a/frontend/src/constants/route.js +++ b/frontend/src/constants/route.js @@ -40,6 +40,12 @@ export const SPACE_LIST = [ id: 'credential', disabled: false, }, + { + name: i18n.t('标签管理'), + icon: 'common-icon-credential', + id: 'labelManage', + disabled: false, + }, ]; export const MODULES_LIST = [ diff --git a/frontend/src/store/index.js b/frontend/src/store/index.js index 393d366e4a..b8a0be9509 100644 --- a/frontend/src/store/index.js +++ b/frontend/src/store/index.js @@ -21,6 +21,7 @@ import decisionTable from './modules/decisionTable'; import credentialConfig from './modules/credentialConfig'; import plugin from './modules/plugin'; import stageCanvas from './modules/stageCanvas'; +import label from './modules/label'; Vue.use(Vuex); const getAppLang = () => { @@ -44,6 +45,7 @@ const store = new Vuex.Store({ credentialConfig, plugin, stageCanvas, + label, }, // 公共 store state: { diff --git a/frontend/src/store/modules/label.js b/frontend/src/store/modules/label.js new file mode 100644 index 0000000000..1f949b37a9 --- /dev/null +++ b/frontend/src/store/modules/label.js @@ -0,0 +1,36 @@ +/** +* Tencent is pleased to support the open source community by making 蓝鲸智云PaaS平台社区版 (BlueKing PaaS Community +* Edition) available. +* Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved. +* Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* http://opensource.org/licenses/MIT +* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on +* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the +* specific language governing permissions and limitations under the License. +*/ +import axios from 'axios'; + +export default { + namespaced: true, + actions: { + // 获取标签列表 二级标签传入parent_id + loadLabelList({}, params) { + return axios.get('/api/label/', { params }).then(response => response.data); + }, + createLabel({}, data) { + return axios.post('/api/label/', data).then(response => response.data); + }, + updateLabel({}, { id, data }) { + return axios.put(`/api/label/${id}/`, data).then(response => response.data); + }, + deleteLabel({}, id) { + return axios.delete(`/api/label/${id}/`).then(response => response.data); + }, + // 获取标签引用参数 + loadLabelReference({}, params) { + return axios.get('/api/label/get_label_ref_count/', { params }).then(response => response.data); + }, + }, +}; + diff --git a/frontend/src/store/modules/taskList.js b/frontend/src/store/modules/taskList.js index 33ab0f6e30..ce5f6428a2 100644 --- a/frontend/src/store/modules/taskList.js +++ b/frontend/src/store/modules/taskList.js @@ -34,6 +34,9 @@ const taskList = { deleteTask({}, data) { return axios.post('/task_admin/batch_delete_tasks/', data).then(response => response.data); }, + updateTaskLabel({}, data) { + return axios.post(`/task_admin/update_labels/${data.space_id}/${data.task_id}/`, { label_ids: data.label_ids }).then(response => response.data); + }, }, }; diff --git a/frontend/src/store/modules/template.js b/frontend/src/store/modules/template.js index 1bf93ec7c2..5fa8e8aadb 100644 --- a/frontend/src/store/modules/template.js +++ b/frontend/src/store/modules/template.js @@ -9,7 +9,7 @@ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License. */ -import Vue, { ref } from 'vue'; +import Vue, { ref } from 'vue'; import nodeFilter from '@/utils/nodeFilter.js'; import { uuid, random4 } from '@/utils/uuid.js'; import tools from '@/utils/tools.js'; @@ -186,7 +186,7 @@ const template = { category: '', description: '', executor_proxy: '', - template_labels: '', + template_labels: [], subprocess_info: { details: [], subproc_has_update: false, @@ -202,6 +202,9 @@ const template = { setTemplateName(state, name) { state.name = name; }, + setTemplateLabel(state, labels) { + state.template_labels = labels; + }, setReceiversGroup(state, data) { state.notify_receivers.receiver_group = data; }, @@ -326,7 +329,6 @@ const template = { name, id: templateId, pipeline_tree: pipelineData, - template_labels: templateLabels, notify_config: notifyConfig, description, executor_proxy: executorProxy, @@ -351,7 +353,6 @@ const template = { state.notify_type = typeof notifyType === 'string' ? { success: JSON.parse(notifyType), fail: [] } : notifyType; state.description = description; state.executor_proxy = executorProxy; - state.template_labels = templateLabels || []; state.time_out = timeOut; state.category = category; state.subprocess_info = subprocessInfo; @@ -396,7 +397,6 @@ const template = { }; state.description = ''; state.executor_proxy = ''; - state.template_labels = []; state.default_flow_type = 'common'; }, // 重置模板数据 @@ -1050,7 +1050,7 @@ const template = { timeout, description, executor_proxy, - template_labels, + labels: template_labels.map(label => label.id), default_flow_type, pipeline_tree: pipelineTree, space_id: spaceId, diff --git a/frontend/src/store/modules/templateList.js b/frontend/src/store/modules/templateList.js index d0f9c7e8d1..dff502c911 100644 --- a/frontend/src/store/modules/templateList.js +++ b/frontend/src/store/modules/templateList.js @@ -37,6 +37,9 @@ const templateList = { copyTemplate({}, data) { return axios.post('/api/template/admin/template_copy/', data).then(response => response.data); }, + updateTemplateLabel({}, data) { + return axios.post(`/api/template/${data.template_id}/update_labels/`, { label_ids: data.label_ids }).then(response => response.data); + }, }, }; diff --git a/frontend/src/views/admin/Space/Task/index.vue b/frontend/src/views/admin/Space/Task/index.vue index ad2a3439fa..1c2a4fbc6b 100644 --- a/frontend/src/views/admin/Space/Task/index.vue +++ b/frontend/src/views/admin/Space/Task/index.vue @@ -3,7 +3,11 @@ @@ -12,7 +16,7 @@ theme="primary" :disabled="!spaceId" @click="onEngineOperate"> - {{ $t('引擎操作') }} + {{ $t("引擎操作") }} @@ -73,7 +120,7 @@ theme="primary" text @click="onDeleteTask(props.row)"> - {{ $t('删除') }} + {{ $t("删除") }} @@ -97,355 +144,429 @@ diff --git a/frontend/src/views/admin/Space/Template/CreateTaskSideslider.vue b/frontend/src/views/admin/Space/Template/CreateTaskSideslider.vue index ab3ca2f73a..e134fc537b 100644 --- a/frontend/src/views/admin/Space/Template/CreateTaskSideslider.vue +++ b/frontend/src/views/admin/Space/Template/CreateTaskSideslider.vue @@ -27,14 +27,22 @@ property="constants">
- {{ $t('表单模式') }} + {{ $t("表单模式") }} - {{ $t('json模式') }} + {{ $t("json模式") }}
- {{ $t('查看未引用变量') }} + {{ $t("查看未引用变量") }}
+ :options="{ + language: 'json', + placeholder: { '${key}': 'value' }, + }" />

+ + + + + diff --git a/frontend/src/views/admin/Space/Template/CreateTemplateDialog.vue b/frontend/src/views/admin/Space/Template/CreateTemplateDialog.vue index ea057b1e47..cea4a584aa 100644 --- a/frontend/src/views/admin/Space/Template/CreateTemplateDialog.vue +++ b/frontend/src/views/admin/Space/Template/CreateTemplateDialog.vue @@ -42,19 +42,49 @@ :maxlength="64" :show-word-limit="true" /> + + + + + - {{ $t('提交') }} + {{ $t("提交") }} - {{ $t('取消') }} + {{ $t("取消") }} @@ -62,102 +92,161 @@ diff --git a/frontend/src/views/admin/Space/Template/index.vue b/frontend/src/views/admin/Space/Template/index.vue index a463f18a84..e51db59cbc 100644 --- a/frontend/src/views/admin/Space/Template/index.vue +++ b/frontend/src/views/admin/Space/Template/index.vue @@ -3,7 +3,9 @@ @@ -12,12 +14,12 @@ :disabled="!spaceId" class="mr10" @click="showCreateTplDialog = true"> - {{ $t('创建流程') }} + {{ $t("创建流程") }} - {{ $t('删除') }} + {{ $t("删除") }} @@ -45,21 +51,52 @@ :prop="item.id" :render-header="renderTableHeader" :width="item.width" - show-overflow-tooltip + :show-overflow-tooltip="item.id !== 'label'" :min-width="item.min_width"> @@ -120,21 +167,21 @@ theme="primary" text @click="onCreateTask(props.row)"> - {{ $t('新建任务') }} + {{ $t("新建任务") }} - {{ $t('复制') }} + {{ $t("复制") }} - {{ $t('删除') }} + {{ $t("删除") }} @@ -149,11 +196,12 @@ v-if="selectedTpls.length > 0" slot="prepend" class="selected-tpl-num"> - {{ $t('当前已选择 x 条数据', { num: selectedTpls.length }) }}{{ $t(',') }} + {{ $t("当前已选择 x 条数据", { num: selectedTpls.length }) + }}{{ $t(",") }} - {{ $t('清除选择') }} + {{ $t("清除选择") }}
- {{ $t('是否复制该流程?') }} + {{ $t("是否复制该流程?") }}
-
{{ $t('关联的mock数据不会同步复制,暂不支持复制带有决策表节点的流程') }}
+
+ {{ + $t( + "关联的mock数据不会同步复制,暂不支持复制带有决策表节点的流程" + ) + }} +
- - {{ $t('复制包含的子流程') }} + + {{ $t("复制包含的子流程") }} @@ -213,25 +266,52 @@ -
- {{ $t('删除失败') }} +
+ {{ $t("删除失败") }}
-
- - +
+
{{ $t("当前流程被以下流程引用:") }}
+
+ + + + + +
@@ -239,515 +319,550 @@ + diff --git a/frontend/src/views/admin/Space/Template/label-cell.vue b/frontend/src/views/admin/Space/Template/label-cell.vue new file mode 100644 index 0000000000..cef2d639dc --- /dev/null +++ b/frontend/src/views/admin/Space/Template/label-cell.vue @@ -0,0 +1,195 @@ + + + + + + diff --git a/frontend/src/views/admin/Space/common/LabelCascade.vue b/frontend/src/views/admin/Space/common/LabelCascade.vue new file mode 100644 index 0000000000..a9bb1be242 --- /dev/null +++ b/frontend/src/views/admin/Space/common/LabelCascade.vue @@ -0,0 +1,347 @@ + + + + + + + diff --git a/frontend/src/views/admin/Space/index.vue b/frontend/src/views/admin/Space/index.vue index 2b4aa12952..79b8f21831 100644 --- a/frontend/src/views/admin/Space/index.vue +++ b/frontend/src/views/admin/Space/index.vue @@ -14,6 +14,7 @@ import SpaceConfigList from './SpaceConfig/index.vue'; import DecisionTable from './DecisionTable/index.vue'; import CredentialList from './Credential/index.vue'; + import LabelManage from './labelManage/index.vue'; import { mapState } from 'vuex'; export default { @@ -24,6 +25,7 @@ SpaceConfigList, DecisionTable, CredentialList, + LabelManage, }, data() { const { activeTab = 'template' } = this.$route.query; @@ -41,7 +43,7 @@ component = tab === 'decisionTable' ? 'DecisionTable' : component; component = tab === 'template' ? 'TemplateList' : component; component = tab === 'credential' ? 'CredentialList' : component; - + component = tab === 'labelManage' ? 'LabelManage' : component; return component; }, }, diff --git a/frontend/src/views/admin/Space/labelManage/CreateLabelDialog.vue b/frontend/src/views/admin/Space/labelManage/CreateLabelDialog.vue new file mode 100644 index 0000000000..40b7a038bb --- /dev/null +++ b/frontend/src/views/admin/Space/labelManage/CreateLabelDialog.vue @@ -0,0 +1,206 @@ + + + + + diff --git a/frontend/src/views/admin/Space/labelManage/index.vue b/frontend/src/views/admin/Space/labelManage/index.vue new file mode 100644 index 0000000000..e29d1d3293 --- /dev/null +++ b/frontend/src/views/admin/Space/labelManage/index.vue @@ -0,0 +1,362 @@ + + + + + diff --git a/frontend/src/views/template/TemplateEdit/TemplateSetting/TabTemplateConfig.vue b/frontend/src/views/template/TemplateEdit/TemplateSetting/TabTemplateConfig.vue index 973fb01b38..2cd42702cd 100644 --- a/frontend/src/views/template/TemplateEdit/TemplateSetting/TabTemplateConfig.vue +++ b/frontend/src/views/template/TemplateEdit/TemplateSetting/TabTemplateConfig.vue @@ -1,14 +1,13 @@ -/** -* Tencent is pleased to support the open source community by making 蓝鲸智云PaaS平台社区版 (BlueKing PaaS Community -* Edition) available. -* Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved. -* Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* http://opensource.org/licenses/MIT -* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on -* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the -* specific language governing permissions and limitations under the License. -*/ +/** * Tencent is pleased to support the open source community by making +蓝鲸智云PaaS平台社区版 (BlueKing PaaS Community * Edition) available. * +Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved. * +Licensed under the MIT License (the "License"); you may not use this file except +in compliance with the License. * You may obtain a copy of the License at * +http://opensource.org/licenses/MIT * Unless required by applicable law or agreed +to in writing, software distributed under the License is distributed on * an "AS +IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the License for the * specific language governing permissions and +limitations under the License. */