diff --git a/src/api/componentBase.ts b/src/api/componentBase.ts index ea7ad53..02d7281 100644 --- a/src/api/componentBase.ts +++ b/src/api/componentBase.ts @@ -18,4 +18,8 @@ export function compProjectValidate(projectId) { export function compSubmit(params) { return axios.post(`${urlPrefix}/componentBase/submit`, params); -} \ No newline at end of file +} + +export const remove = (ids) => { + return axios.post(`${urlPrefix}/componentBase/remove?ids=${ids}`); +}; \ No newline at end of file diff --git a/src/api/componentDevelopProcess.ts b/src/api/componentDevelopProcess.ts new file mode 100644 index 0000000..9b888ac --- /dev/null +++ b/src/api/componentDevelopProcess.ts @@ -0,0 +1,14 @@ +import axios from 'axios'; + +// 公共路径 +const urlPrefix = '/api/v1/bpms-workbench'; + +// 获取组件设计 +export function getComponentDesign(componentBaseId) { + return axios.get(`${urlPrefix}/componentDevelopProcess/design?componentBaseId=${componentBaseId}`); +} + +// 更新组件设计 +export function updateComponentDesign(params) { + return axios.post(`${urlPrefix}/componentDevelopProcess/design`, params); +} \ No newline at end of file diff --git a/src/const/globalOption.ts b/src/const/globalOption.ts new file mode 100644 index 0000000..750ead1 --- /dev/null +++ b/src/const/globalOption.ts @@ -0,0 +1,13 @@ +export const globalOption = { + border: false, + align: 'left', + menuHeaderAlign: 'left', + size: 'mini', + refreshBtn: false, + filterBtn: false, + columnBtn: false, + searchShowBtn: false, + // labelPosition: "left" +}; +export const TrimReg = /^[^\s]+$/; +export const patternTrim = { pattern: TrimReg, message: '不能输入空格' }; diff --git a/src/const/isdp/componentBase.ts b/src/const/isdp/componentBase.ts new file mode 100644 index 0000000..41ddb72 --- /dev/null +++ b/src/const/isdp/componentBase.ts @@ -0,0 +1,541 @@ +import { globalOption, patternTrim } from '../globalOption'; + +// 组件公开状态码 +export const publishStatusConstant = { + // 未公开 + UNPUBLISHED: -1, + // 已公开 + PUBLISHED: 1, + // 已撤销 + REVOKED: 0, + // 审批中 + APPROVAL: 2 +}; +export const publishStatusDict = [ + { + label: '未公开', + value: publishStatusConstant.UNPUBLISHED + }, + { + label: '未公开', + value: publishStatusConstant.REVOKED + }, + { + label: '已公开', + value: publishStatusConstant.PUBLISHED + }, + { + label: '审批中', + value: publishStatusConstant.APPROVAL + } +]; +// 组价发布的状态码 +export const publicStatus = { + // 未发布 + UNPUBLISHED: -1, + UNPUBLISHED1: 0, + // 已发布 + PUBLISHED: 1, + // 审核中 + REVIEW: 2, + // 审核被拒 + REJECTED: 3 +}; +export const publicStatusDict = [ + { + label: '未发布', + value: publicStatus.UNPUBLISHED + }, + { + label: '未发布', + value: publicStatus.UNPUBLISHED1 + }, + { + label: '已发布', + value: publicStatus.PUBLISHED + }, + { + label: '审核中', + value: publicStatus.REVIEW + }, + { + label: '审核被拒', + value: publicStatus.REJECTED + } +]; +// 组件基本信息状态字段 +export const componentStatusConstant = { + // 未设计 + DEFAULT: 'default', + // 设计中 + DESIGN: 'design', + // 编码中 + CODING: 'coding', + // 已部署 + DEPLOYED: 'deployed', + // 已公开 + PUBLISHED: 'published' +}; +// 组件所处阶段状态 +export const componentStatusDict = [ + { + label: '未设计', + value: componentStatusConstant.DEFAULT + }, + { + label: '设计中', + value: componentStatusConstant.DESIGN + }, + { + label: '编码中', + value: componentStatusConstant.CODING + }, + { + label: '已部署', + value: componentStatusConstant.DEPLOYED + }, + { + label: '已公开', + value: componentStatusConstant.PUBLISHED + } +]; +// 组件所处阶段状态 +export const componentStatusMap = componentStatusDict.reduce((obj, item) => { + obj[item.value] = item.label; + return obj; +}, {}); +// 组件类型字典映射 +export const componentTypeDict = [ + { + dictKey: '普通组件', + dictValue: 'normal' + }, + { + dictKey: '监听组件', + dictValue: 'loop' + } +]; + +// 表格参数 +export const option = { + ...globalOption, + height: 'auto', + calcHeight: 30, + tip: false, + searchShow: true, + searchMenuSpan: 6, + viewBtn: true, + delBtn: false, + selection: false, + dialogClickModal: false, + labelWidth: '100', + menuWidth: 500, + menuHeaderAlign: 'center', + header: true, + addBtn: true, + editBtn: false, + updateBtnText: '保 存', + addBtnText: '新增组件', + addBtnIcon: 'none', + column: [ + { + label: '组件名称', + prop: 'name', + type: 'input', + width: 150, + placeholder: '请输入组件名称', + rules: [ + { + required: true, + message: '组件名称不能为空', + trigger: 'blur' + }, + { + pattern: /^[\u4e00-\u9fa5a-zA-Z0-9_-]+$/, + message: '组件名称只能为中文、字母、数字、"-"、"_"组成' + }, + patternTrim, + { max: 50, message: '组件名称最长为50字符' } + ] + }, + { + label: '组件标识', + prop: 'projectId', + type: 'input', + width: 200, + overHidden: true, + placeholder: '请输入组件标识', + editDisabled: true, + rules: [ + { required: true, message: '组件标识不能为空' }, + { + pattern: /^([a-z][a-z0-9]*[_-]?)+$/, + message: '组件标识由小写字母、数字、"-"、"_"组成,以小写字母开头,且“-”、"_"后第一个字符需为小写字母' + }, + { max: 30, message: '组件标识最长为30个字符' }, + patternTrim + ] + }, + { + label: '分类', + prop: 'componentClassify', + type: 'select', + placeholder: '请选择分类', + width: 200, + dicUrl: '/api/blade-system/dict-biz/dictionary-tree?code=component_classify', + props: { + label: 'dictValue', + value: 'dictKey' + }, + rules: [{ required: true, message: '分类不能为空' }] + }, + { + label: '创建人', + prop: 'createUserName', + type: 'input', + display: false, + overHidden: true, + editDisabled: false, + width: 180, + hide: false + }, + { + label: '代码语言', + prop: 'codeLanguage', + type: 'select', + dicUrl: '/api/blade-system/dict/dictionary?code=language_type', + value: 'Java', + editDisabled: true, + width: 150, + placeholder: '请选择代码语言', + props: { + label: 'dictValue', + value: 'dictKey' + }, + rules: [{ required: true, message: '代码语言不能为空' }] + }, + { + label: '标签', + prop: 'tags', + type: 'select', + remote: true, + multiple: true, + allowCreate: true, + filterable: true, + placeholder: '请选择标签', + width: 200, + dicUrl: '/api/blade-isdp/componentBase/tags', + hide: true + }, + { + label: '组件类型', + prop: 'type', + type: 'select', + dicData: componentTypeDict, + value: 'normal', + editDisabled: true, + width: 150, + placeholder: '请选择组件类型', + props: { + label: 'dictKey', + value: 'dictValue' + }, + rules: [{ required: true, message: '组件类型不能为空' }] + }, + { + label: '图标', + prop: 'logoUrl', + type: 'upload', + hide: true, + listType: 'picture-card', + action: '/api/blade-isdp/fileSystem/fileUpload', + propsHttp: { + res: 'data', + url: 'link' + }, + fileType: 'img', + limit: 1, + fileSize: 1024, + accept: 'image/png, image/jpeg, image/jpg', + tip: '图片尺寸不超过300*300像素,大小限制为1mb以内' + }, + { + label: '描述', + prop: 'desc', + type: 'textarea', + overHidden: true, + placeholder: '请输入描述', + formSlot: true, + hide: true, + minRows: 2, + maxLen: 100, + span: 24 + }, + { + label: '组件状态', + prop: 'componentStatus', + type: 'input', + display: false, + width: 100, + dicData: componentStatusDict + }, + { + label: '创建部门', + prop: 'createDept', + type: 'input', + display: false, + hide: true + }, + { + label: '创建时间', + prop: 'createTime', + type: 'input', + hide: true, + display: false + }, + { + label: '发布状态', + prop: 'publicStatus', + type: 'input', + width: 90, + dicData: [ + { + label: '未发布', + value: publicStatus.UNPUBLISHED + }, + { + label: '未发布', + value: publicStatus.UNPUBLISHED1 + }, + { + label: '已发布', + value: publicStatus.PUBLISHED + }, + { + label: '审核中', + value: publicStatus.REVIEW + }, + { + label: '审核被拒', + value: publicStatus.REJECTED + } + ], + display: false + }, + { + label: '公开状态', + prop: 'publishStatus', + type: 'input', + width: 90, + dicData: [ + { + label: '未公开', + value: publishStatusConstant.UNPUBLISHED + }, + { + label: '未公开', + value: publishStatusConstant.REVOKED + }, + { + label: '已公开', + value: publishStatusConstant.PUBLISHED + }, + { + label: '审批中', + value: publishStatusConstant.APPROVAL + } + ], + display: false + }, + { + label: '修改人', + prop: 'updateUser', + type: 'input', + display: false, + hide: true + }, + { + label: '修改时间', + prop: 'updateTime', + type: 'input', + width: 130, + display: false + }, + { + label: '是否已删除', + prop: 'isDeleted', + type: 'input', + display: false, + hide: true + } + ] +}; + +export const operateOption = { + ...globalOption, + height: '400', + calcHeight: 30, + tip: false, + searchShow: false, + selection: false, + dialogClickModal: false, + header: false, + delBtn: true, + viewBtn: false, + dialogWidth: '55%', + menuWidth: 100, + saveBtn: false, + cancelBtn: false, + editBtn: true, + editBtnIcon: 'none', + delBtnIcon: 'none', + column: [ + { + label: '接口名称', + prop: 'ident', + type: 'input', + placeholder: '请输入名称', + rules: [ + { required: true, message: '名称不能为空' }, + { pattern: /^[a-z][a-zA-Z0-9]*$/, message: '名称符需要为首字母小写的驼峰命名法' }, + { max: 20, message: '名称最长为20个字符' }, + patternTrim + ] + }, + { + label: '描述', + prop: 'desc', + type: 'textarea', + placeholder: '请输入描述', + hide: true, + overHidden: true, + minRows: 2, + rules: [{ max: 200, message: '最长为200个字符' }, patternTrim], + span: 24 + }, + { + label: '输入参数', + prop: 'parameters', + type: 'input', + span: 24, + formSlot: true, + overHidden: true, + value: [], + slot: true + }, + { + label: '输出参数', + prop: 'responses', + type: 'input', + span: 24, + formSlot: true, + overHidden: true, + value: [], + slot: true + } + ] +}; + +export const baseConfigOption = { + ...globalOption, + addBtn: false, + addRowBtn: true, + menu: true, + cellBtn: false, + editBtn: false, + delBtn: false, + dialogWidth: '40%', + menuWidth: '80', + column: [ + { + label: '启动项名称', + prop: 'name', + placeholder: '启动项名称', + width: '150px', + rules: [{ required: true, message: '启动项名称不能为空' }, { + max: 50, + message: '启动项名称最长为50字符' + }, patternTrim], + cell: true, + span: 24 + }, + { + label: '参数名(key)', + prop: 'key', + input: 'input', + width: '200px', + rules: [{ required: true, message: '请输入参数名(key)' }, { + max: 50, + message: '参数名(key)最长为50字符' + }, patternTrim], + cell: true, + span: 24 + }, + { + label: '默认值', + prop: 'value', + width: '200px', + span: 24, + cell: true, + rules: [{ max: 200, message: '默认值最长为200字符' }, patternTrim] + }, + { + label: '描述说明', + prop: 'desc', + overHidden: true, + span: 24, + cell: true, + rules: [{ max: 200, message: '描述说明最长为200字符' }, patternTrim] + } + ] +}; + +export const baseDisplayToEntity = (row) => { + row.desc = row.desc || ''; + row.tags = row.tags || []; + row.logoUrl = row.logoUrl || ''; + return row; +}; + +export const baseEntityToDisplay = (row) => { + row.desc = row.desc || ''; + row.logoUrl = row.logoUrl || ''; + row.tags = row.tags || []; + return row; +}; + +export const toolbars = { + bold: true, // 粗体 + italic: true, // 斜体 + header: true, // 标题 + underline: true, // 下划线 + strikethrough: true, // 中划线 + mark: true, // 标记 + superscript: true, // 上角标 + subscript: true, // 下角标 + quote: true, // 引用 + ol: true, // 有序列表 + ul: true, // 无序列表 + link: true, // 链接 + imagelink: true, // 图片链接 + code: true, // code + table: true, // 表格 + fullscreen: true, // 全屏编辑 + readmodel: true, // 沉浸式阅读 + htmlcode: true, // 展示html源码 + help: false, // 帮助 + /* 1.3.5 */ + undo: true, // 上一步 + redo: true, // 下一步 + trash: true, // 清空 + save: false, // 保存(触发events中的save事件) + /* 1.4.2 */ + navigation: true, // 导航目录 + /* 2.1.8 */ + alignleft: true, // 左对齐 + aligncenter: true, // 居中 + alignright: true, // 右对齐 + /* 2.2.1 */ + subfield: true, // 单双栏模式 + preview: true // 预览 +}; diff --git a/src/const/isdp/componentDeploy.ts b/src/const/isdp/componentDeploy.ts new file mode 100644 index 0000000..1a455a9 --- /dev/null +++ b/src/const/isdp/componentDeploy.ts @@ -0,0 +1,562 @@ +import { globalOption, patternTrim } from '../globalOption'; + +/** + * 实例运行状态 + */ +export const runStatusConstant = { + HEALTHY: 'healthy', + UNKNOWN: 'unknown', + RUN: 'run', + ERROR: 'error', + STOP: 'stop', +}; +export const runStatusDic = [ + { + label: '可用', + value: runStatusConstant.HEALTHY, + }, + { + label: '未知', + value: runStatusConstant.UNKNOWN, + }, + { + // 部署 可停止 + label: '运行', + value: runStatusConstant.RUN, + }, + { + label: '异常', + value: runStatusConstant.ERROR, + }, + { + // 部署 可启用 + label: '停止', + value: runStatusConstant.STOP, + }, +]; +export const runStatusMap = runStatusDic.reduce((obj, item) => { + obj[item.value] = item.label; + return obj; +}, {}); +/** + * 组件运行状态 + */ +export const startStatusConstant = { + RUN: 'run', + STOP: 'stop', +}; +export const startStatusDic = [ + { + label: '启用中', + value: startStatusConstant.RUN, + }, + { + label: '已下架', + value: startStatusConstant.STOP, + }, +]; +export const startStatusMap = startStatusDic.reduce((obj, item) => { + obj[item.value] = item.label; + return obj; +}, {}); + +/** + * 组件编译状态 + * BUILT_DOING, BUILT_IGNORE,BUILT_DOCKER,BUILT_FAIL + */ +export const compileStatusConstant = { + BUILT_DOING: 'built-doing', + BUILT_IGNORE: 'built-ignore', + BUILT_DOCKER: 'built-docker', + BUILT_FAIL: 'built-fail', + // 前端单独使用 + NOT_COMPILED: 'not-compiled', + get(type) { + return compileStatusConstant[type] || compileStatusConstant.NOT_COMPILED; + }, +}; +export const compileStatusDic = [ + { + label: '编译中', + value: compileStatusConstant.BUILT_DOING, + }, + { + label: '免编译', + value: compileStatusConstant.BUILT_IGNORE, + }, + { + label: '已编译', + value: compileStatusConstant.BUILT_DOCKER, + }, + { + label: '编译失败', + value: compileStatusConstant.BUILT_FAIL, + }, +]; +export const compileStatusMap = startStatusDic.reduce((obj, item) => { + obj[item.value] = item.label; + return obj; +}, {}); +/** + * 实例运行类型 + */ +export const runTypeConstant = { + LOCAL: 0, + ONLINE: 1, +}; +export const runTypeDic = [ + { + label: '本地运行', + value: runTypeConstant.LOCAL, + }, + { + label: '线上运行', + value: runTypeConstant.ONLINE, + }, +]; +export const option = { + ...globalOption, + height: '300', + calcHeight: 30, + tip: false, + searchShow: false, + header: false, + viewBtn: false, + delBtn: false, + index: true, + menuWidth: 300, + addBtn: false, + editBtn: false, + submitText: '修改', + emptyText: '暂无数据', + span: 24, + column: [ + { + label: 'id', + prop: 'id', + hide: true, + display: false, + }, + { + label: '标识', + prop: 'identifier', + type: 'input', + overHidden: true, + display: false, + }, + { + label: '实例名称', + prop: 'name', + type: 'input', + overHidden: true, + rules: [ + { required: true, message: '必须填写实例名称' }, + { max: 50, message: '实例名称不能超过50字符' }, + ], + }, + { + label: '运行类型', + prop: 'runType', + type: 'input', + width: 80, + display: false, + dicData: runTypeDic, + }, + { + label: '运行状态', + prop: 'runStatus', + type: 'input', + width: 80, + dicData: runStatusDic, + display: false, + slot: true, + }, + { + label: '创建时间', + prop: 'createTime', + type: 'input', + // width: 160, + display: false, + }, + { + label: '实例描述', + prop: 'description', + type: 'textarea', + hide: true, + minRows: 3, + span: 24, + }, + ], +}; +export const instanceOption = { + ...globalOption, + calcHeight: 'auto', + // height: '300', + // calcHeight: 30, + tip: false, + searchShow: false, + header: false, + viewBtn: false, + delBtn: false, + index: true, + menuWidth: 350, + addBtn: false, + editBtn: false, + submitText: '修改', + emptyText: '取消', + span: 24, + column: [ + ...option.column, + { + label: '图标', + prop: 'logoUrl', + type: 'upload', + hide: true, + listType: 'picture-img', + action: '/api/blade-isdp/fileSystem/fileUpload', + propsHttp: { + res: 'data', + url: 'link', + }, + fileType: 'img', + limit: 1, + fileSize: 1024 * 10, + accept: 'image/png, image/jpeg, image/jpg', + // tip: '图片尺寸不超过300*300像素,大小限制为1mb以内', + // rules: [{ + // required: true, + // message: "请输入图片地址", + // trigger: "blur" + // }] + }, + ], +}; +export const envConfigOption = { + ...globalOption, + height: 300, + calcHeight: 30, + tip: false, + searchShow: false, + addBtn: false, + addRowBtn: false, + cellBtn: false, + index: true, + menuWidth: 80, + editBtn: false, + delBtn: false, + column: [ + { + label: '启动项名称', + prop: 'name', + placeholder: '启动项名称', + formSlot: true, + rules: [ + { required: true, message: '启动项名称不能为空' }, + { max: 50, message: '启动项名称最长为50字符' }, + ], + width: 120, + span: 24, + cell: true, + }, + { + label: '参数名(key)', + prop: 'key', + formSlot: true, + rules: [ + { required: true, message: '请输入参数名(key)' }, + { max: 50, message: '参数名(key)最长为50字符' }, + ], + span: 24, + cell: true, + }, + { + label: '配置值', + prop: 'value', + span: 24, + formSlot: true, + rules: [{ max: 200, message: '配置值最长为200字符' }], + cell: true, + }, + { + label: '描述说明', + prop: 'desc', + type: 'input', + formSlot: true, + span: 24, + rules: [{ max: 200, message: '描述说明最长为200字符' }], + cell: true, + }, + // { + // label: "配置类型", + // prop: "unmodifiable", + // value: false, + // width: 80, + // dicData: [ + // { + // label: "自定义配置", + // value: false + // }, + // { + // label: "必须配置", + // value: true + // } + // ] + // }, + ], +}; +export const addInstanceOption = { + ...globalOption, + submitBtn: false, + emptyBtn: false, + column: [ + { + label: '部署环境', + prop: 'environment', + type: 'select', + value: 'docker-env-prod', + // disabled: true, + dicData: [], + rules: [{ required: true, message: '请选择环境变量' }], + overHidden: true, + }, + { + label: '主机', + prop: 'deployEnvId', + type: 'select', + value: '', + props: { + label: 'name', + value: 'id', + desc: 'ip', + }, + rules: [{ required: true, message: '请输入主机' }], + overHidden: true, + }, + { + label: 'CPU核数', + prop: 'cpuCount', + type: 'slider', + step: 1, + min: 1, + max: 12, + showStops: true, + marks: [1, 4, 8].reduce((obj, pre) => { + obj[pre] = pre + '核'; + return obj; + }, {}), + }, + // { + // label: "容器名称", + // prop: "containerName", + // tip: "为空时自动生成", + // rules: [ + // { min: 1, max: 63, message: "容器名称长度为1-63个字符" }, + // patternTrim, + // ], + // }, + { + label: '是否使用GPU', + prop: 'useGpu', + type: 'switch', + labelWidth: 100, + value: false, + dicData: [ + { label: '否', value: false }, + { label: '是', value: true }, + ], + }, + { + label: '最大内存', + prop: 'memory', + type: 'slider', + step: 64, + min: 64, + max: 8192, + formSlot: true, + span: 24, + marks: { + 64: '64MB', + 1024: '1GB', + 2048: '2GB', + 4096: '4GB', + 6144: '6GB', + }, + showStops: true, + }, + // 网络模式 选择框 + { + label: '网络模式', + prop: 'networkType', + type: 'select', + span: 6, + value: 'bridge', + dicData: [ + { + label: '桥接模式', + value: 'bridge', + }, + { + label: '主机模式', + value: 'host', + }, + { + label: '禁用网络', + value: 'null', + }, + ], + rules: [{ required: true, message: '请选择网络模式' }], + overHidden: true, + }, + // 网卡 + { + label: '网卡', + prop: 'networkMode', + type: 'select', + value: 'bridge', + span: 9, + overHidden: true, + rules: [{ required: true, message: '请选择网卡' }], + }, + // ip + { + label: 'IP', + prop: 'ipv4Address', + type: 'input', + formSlot: true, + value: '', + overHidden: true, + span: 9, + }, + { + label: '端口映射', + prop: 'ports', + type: 'dynamic', + span: 24, + children: { + height: 120, + column: [ + { + label: '主机端口', + prop: 'hostPort', + type: 'number', + value: '80', + max: 65535, + rules: [{ required: true, message: '请输入主机端口' }], + }, + { + label: '容器端口', + prop: 'containerPort', + type: 'number', + max: 65535, + rules: [{ required: true, message: '请输入容器端口' }], + }, + { + label: '备注', + prop: 'remake', + type: 'input', + value: '', + }, + ], + }, + }, + { + label: '目录挂载', + prop: 'volumes', + type: 'dynamic', + span: 24, + children: { + height: 170, + column: [ + { + label: '主机路径', + prop: 'hostPath', + type: 'input', + value: '', + rules: [{ required: true, message: '请输入主机路径' }, patternTrim], + }, + { + label: '容器路径', + prop: 'containerPath', + type: 'input', + value: '', + rules: [{ required: true, message: '请输入容器路径' }, patternTrim], + }, + { + label: '备注', + prop: 'remake', + type: 'input', + }, + ], + }, + }, + { + // 设备挂载 + label: '设备挂载', + prop: 'devices', + type: 'dynamic', + span: 24, + children: { + height: 120, + column: [ + { + label: '主机路径', + prop: 'hostPath', + type: 'input', + value: '', + rules: [{ required: true, message: '请输入主机路径' }, patternTrim], + }, + { + label: '容器路径', + prop: 'containerPath', + type: 'input', + value: '', + rules: [{ required: true, message: '请输入容器路径' }, patternTrim], + }, + { + label: '权限', + prop: 'permissions', + type: 'select', + value: 'rwm', + dicData: [ + { value: 'rwm', label: 'rwm' }, + { value: 'rw', label: 'rw' }, + { value: 'r', label: 'r' }, + ], + rules: [{ required: true, message: '请输入权限' }], + }, + { + label: '备注', + prop: 'remake', + type: 'input', + value: '', + }, + ], + }, + }, + // 重启策略 + { + label: '重启策略', + prop: 'restartPolicy', + type: 'select', + span: 6, + display: false, + hide: true, + value: 'always', + dicData: [ + { + label: '始终', + value: 'always', + }, + { + label: '失败', + value: 'on-failure', + }, + { + label: '无', + value: 'no', + }, + ], + overHidden: true, + }, + ], +}; diff --git a/src/const/isdp/componentRelease.ts b/src/const/isdp/componentRelease.ts new file mode 100644 index 0000000..17b9d1c --- /dev/null +++ b/src/const/isdp/componentRelease.ts @@ -0,0 +1,179 @@ +import { globalOption, patternTrim } from '../globalOption'; +import { componentBaseTagsUrl } from '@/api/isdp/componentBase'; + +export const releaseMaping = { + 0: { + label: '未公开', + type: 'info', + }, + '-1': { + label: '未公开', + type: 'info', + }, + 1: { + label: '已公开', + type: 'success', + }, +}; + +export const option = { + ...globalOption, + height: 'auto', + calcHeight: 30, + tip: false, + searchShow: true, + searchSpan: 5, + searchMenuSpan: 4, + menuWidth: 120, + viewBtn: true, + delBtn: false, + selection: false, + header: false, + editBtn: false, + column: [ + { + label: '组件名称', + prop: 'name', + type: 'input', + overHidden: true, + search: true, + placeholder: '请输入组件名称', + rules: [ + { + required: true, + message: '组件名称不能为空', + trigger: 'blur', + }, + patternTrim, + { max: 20, message: '组件名称最长为20字符' }, + ], + }, + { + label: '项目名', + prop: 'identifier', + type: 'input', + overHidden: true, + search: true, + placeholder: '请输入项目名', + rules: [ + { required: true, message: '项目名不能为空' }, + { + pattern: /^([a-z][a-z0-9]*[_-]?)+$/, + message: '项目名由小写字母、数字、"-"、"_"组成,以小写字母开头,且“-”、"_"后第一个字符需为小写字母', + }, + { max: 30, message: '项目名最长为30个字符' }, + patternTrim, + ], + }, + { + label: '版本号', + prop: 'version', + type: 'input', + overHidden: true, + disabled: true, + value: 'v1', + width: 60, + span: 6, + rules: [ + { + required: true, + message: '请输入组件版本号', + trigger: 'blur', + }, + // { + // pattern: /^\d+(\.\d+){0,3}$/, + // message: "版本只能是由数字组成的x.x或x.x.x格式", + // trigger: "blur" + // }, + { max: 20, message: '版本号最长为20字符' }, + ], + }, + { + label: '分类', + prop: 'componentClassify', + type: 'select', + placeholder: '请选择分类', + search: true, + dicUrl: '/api/blade-system/dict-biz/dictionary-tree?code=component_classify', + props: { + label: 'dictValue', + value: 'dictKey', + }, + span: 9, + rules: [{ required: true, message: '分类不能为空' }], + // search: true, + }, + { + label: '代码语言', + prop: 'codeLanguage', + type: 'select', + search: true, + dicUrl: '/api/blade-system/dict/dictionary?code=language_type', + value: 'Java', + width: 70, + span: 9, + placeholder: '请选择代码语言', + props: { + label: 'dictValue', + value: 'dictKey', + }, + rules: [{ required: true, message: '代码语言不能为空' }], + }, + { + label: '标签', + prop: 'tags', + type: 'select', + remote: true, + multiple: true, + allowCreate: true, + filterable: true, + placeholder: '请选择标签', + span: 24, + dicUrl: componentBaseTagsUrl, + hide: true, + }, + { + label: '描述', + prop: 'desc', + type: 'textarea', + overHidden: true, + placeholder: '请输入描述', + minRows: 2, + maxLen: 100, + rules: [{ max: 200, message: '最长为200个字符' }], + span: 24, + }, + { + label: '图标', + prop: 'logoUrl', + type: 'upload', + hide: true, + listType: 'picture-img', + action: '/api/blade-isdp/fileSystem/fileUpload', + propsHttp: { + res: 'data', + url: 'link', + }, + fileType: 'img', + limit: 1, + fileSize: 1024, + accept: 'image/png, image/jpeg, image/jpg', + tip: '图片尺寸不超过300*300像素,大小限制为1mb以内', + }, + { + label: '公开状态', + prop: 'publishStatus', + type: 'input', + slot: true, + display: false, + width: 90, + }, + { + label: '修改时间', + prop: 'updateTime', + type: 'input', + width: 130, + display: false, + }, + ], +}; diff --git a/src/const/isdp/componentTest.ts b/src/const/isdp/componentTest.ts new file mode 100644 index 0000000..b42c986 --- /dev/null +++ b/src/const/isdp/componentTest.ts @@ -0,0 +1,176 @@ +import { globalOption, patternTrim } from '@/const/globalOption'; +import { runTypeDic, runStatusDic, runStatusConstant } from '@/const/isdp/componentDeploy'; +export const runStatusConstant2 = runStatusConstant; +export const componentTestOption = { + ...globalOption, + height: '400', + calcHeight: 30, + tip: false, + searchShow: false, + selection: false, + dialogClickModal: false, + header: false, + delBtn: true, + viewBtn: true, + editBtn: false, + dialogWidth: '55%', + menuWidth: 230, + saveBtn: false, + cancelBtn: false, + menu: false, + emptyBtn: false, + submitBtn: false, + menuPosition: 'right', + column: [ + { + label: '用例名称', + prop: 'testCaseName', + type: 'select', + allowCreate: true, + filterable: true, + placeholder: '请输入或选择测试用例', + rules: [{ required: true, message: '用例名称不能为空' }, { max: 20, message: '用例名称最长为20个字符' }, patternTrim], + dicData: [ + { + label: '通过用例', + value: '通过用例', + }, + { + label: '失败用例', + value: '失败用例', + }, + { + label: '参数有误', + value: '参数有误', + }, + { + label: '数据为空', + value: '数据为空', + }, + { + label: '缺少参数', + value: '缺少参数', + }, + { + label: '记录不存在', + value: '记录不存在', + }, + ], + span: 12, + }, + { + type: 'none', + display: 'none', + }, + { + label: '输入参数', + prop: 'expectDataIns', + type: 'dynamic', + span: 24, + children: { + height: 250, + addBtn: false, + delBtn: false, + column: [ + { + label: '名称', + prop: 'id', + type: 'input', + width: 100, + }, + { + label: '参数类型', + prop: 'type', + type: 'input', + width: 80, + }, + { + label: '数组类型', + placeholder: '请选择数组类型', + prop: 'generic', + type: 'input', + width: 80, + }, + { + label: '参数值', + prop: 'value', + type: 'input', + cell: true, + }, + ], + }, + }, + { + label: '输出参数', + prop: 'expectDataOuts', + type: 'dynamic', + span: 24, + children: { + height: 250, + addBtn: false, + delBtn: false, + column: [ + { + label: '名称', + prop: 'id', + type: 'input', + width: 100, + }, + { + label: '参数类型', + prop: 'type', + type: 'input', + width: 80, + }, + { + label: '数组类型', + prop: 'generic', + type: 'input', + width: 80, + }, + { + label: '参数值', + prop: 'value', + type: 'input', + cell: true, + }, + ], + }, + }, + ], +}; +export const option = { + ...globalOption, + header: false, + editBtn: false, + delBtn: false, + menuWidth: 100, + column: [ + { + label: '实例标识', + prop: 'identifier', + }, + { + label: '实例名', + prop: 'name', + }, + { + label: '运行类型', + prop: 'runType', + width: 80, + dicData: runTypeDic, + }, + { + label: '实例状态', + prop: 'runStatus', + width: 80, + dicData: runStatusDic, + }, + { + label: '实例测试时间', + width: 130, + prop: 'lastTestTime', + slot: true, + }, + ], +}; diff --git a/src/const/isdp/envManagement.ts b/src/const/isdp/envManagement.ts new file mode 100644 index 0000000..c6ab63f --- /dev/null +++ b/src/const/isdp/envManagement.ts @@ -0,0 +1,153 @@ +import { globalOption, patternTrim } from '../globalOption'; + +export const archDict = [ + { + label: 'x86_64', + value: 'x86_64', + }, + { + label: 'aarch64', + value: 'aarch64', + }, +]; + +export const option = { + ...globalOption, + height: 'auto', + calcHeight: 30, + searchShow: true, + searchMenuSpan: 6, + viewBtn: false, + delBtn: false, + selection: false, + header: true, + addBtn: false, + editBtn: false, + updateBtnText: '保 存', + menuHeaderAlign: 'center', + column: [ + { + label: '环境IP', + prop: 'ip', + type: 'input', + overHidden: true, + span: 12, + rules: [ + { + required: true, + message: '环境IP不能为空', + trigger: 'blur', + }, + { + pattern: /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/, + message: '请输入正确的IP地址:范围在0.0.0.0-255.255.255.255之间', + trigger: 'blur', + }, + ], + }, + { + label: 'docker端口', + prop: 'dockerTcpPort', + type: 'number', + labelWidth: 100, + overHidden: true, + value: 2375, + span: 12, + rules: [ + { + required: true, + message: 'docker端口不能为空', + trigger: 'blur', + }, + { + pattern: /^(?:[1-9]\d{0,3}|[1-5]\d{4}|6[0-4]\d{3}|65[0-4]\d{2}|655[0-2]\d|6553[0-5])$/, + message: 'docker端口只能是1-65535之间', + trigger: 'blur', + }, + ], + }, + { + label: '环境类型', + prop: 'type', + type: 'select', + overHidden: true, + search: true, + span: 12, + dicUrl: '/api/blade-system/dict/dictionary-tree?code=docker-env', + props: { + label: 'dictValue', + value: 'dictKey', + }, + rules: [ + { + required: true, + message: '环境类型不能为空', + trigger: 'blur', + }, + ], + }, + { + label: '架构类型', + prop: 'arch', + type: 'select', + overHidden: true, + search: true, + span: 12, + dicData: archDict, + formSlot: true, + props: { + label: 'label', + value: 'value', + }, + rules: [ + { + required: true, + message: '架构类型不能为空', + trigger: 'blur', + }, + ], + }, + { + label: '环境别名', + prop: 'name', + type: 'input', + search: true, + span: 24, + rules: [ + { + required: true, + message: '环境IP不能为空', + trigger: 'blur', + }, + patternTrim, + // 最大50 + { + max: 50, + message: '环境别名最大长度不能超过50', + trigger: 'blur', + }, + ], + }, + { + label: '备注', + prop: 'description', + type: 'textarea', + span: 24, + rules: [ + { + max: 200, + message: '长度不超过200字符', + trigger: 'blur', + }, + ], + overHidden: true, + }, + { + label: '实例数量', + labelWidth: 20, + span: 24, + prop: 'instanceCount', + display: false, + }, + ], +}; diff --git a/src/const/isdp/mod/AddPropList.ts b/src/const/isdp/mod/AddPropList.ts new file mode 100644 index 0000000..663641e --- /dev/null +++ b/src/const/isdp/mod/AddPropList.ts @@ -0,0 +1,113 @@ +import { globalOption } from '@/const/globalOption'; +/** + * @数据映射 + */ +// 数据显示的映射 +export const typeMap = { + INTEGER: 'INT', + DOUBLE: 'DOU', + STRING: 'STR', + LONG: 'LONG', + FLOAT: 'FLOAT', + DATE: 'DATE', + TIMESTAMP: 'TS', + DATETIME: 'DT', + BOOLEAN: 'BOOL', + ARRAY: 'ARR', + OBJECT: 'OBJ', +}; +export const dataTypeDict = [ + { + label: '整数', + value: 'INTEGER', + }, + { + label: '浮点数', + value: 'DOUBLE', + }, + { + label: '字符串', + value: 'STRING', + }, + { + label: '布尔值', + value: 'BOOLEAN', + }, + { + label: '数组', + value: 'ARRAY', + }, + { + label: '对象', + value: 'OBJECT', + }, + { + label: '日期', + value: 'DATE', + }, + { + label: '日期时间', + value: 'DATETIME', + }, + { + label: '时间戳', + value: 'TIMESTAMP', + }, +]; + +// 显示查看表单 +export const showOption = { + ...globalOption, + minHeight: '100', + calcHeight: 30, + tip: false, + searchShow: false, + searchMenuSpan: 24, + addBtn: false, + viewBtn: false, + selection: false, + editBtn: false, + delBtn: false, + dialogClickModal: false, + header: false, + dialogWidth: '50%', + menuWidth: 60, + // dialogFullscreen: true, + column: [ + { + label: '名称', + prop: 'ident', + span: 12, + trigger: 'blur', + placeholder: '请输入名称', + rules: [ + { required: true, message: '名称不能为空' }, + { pattern: /^[a-z][a-zA-Z0-9]*$/, message: '名称符需要为首字母小写的驼峰命名法' }, + { max: 50, message: '名称最长为50个字符' }, + ], + }, + { + label: '数据类型', + prop: 'type', + type: 'select', + placeholder: '请选择数据类型', + dicData: dataTypeDict, + trigger: 'blur', + rules: [{ required: true, message: '数据类型不能为空' }], + }, + // 需要加上change + { + label: '数组类型', + prop: 'generic', + slot: true, + formSlot: true, + placeholder: '请选择数组类型', + dicData: dataTypeDict.filter((item) => item.value !== 'ARRAY'), + rules: [{ required: true, message: '数组类型不能为空' }], + }, + { + label: '参数描述', + prop: 'desc', + }, + ], +}; diff --git a/src/const/isdp/mod/componentAudit.ts b/src/const/isdp/mod/componentAudit.ts new file mode 100644 index 0000000..d04fb05 --- /dev/null +++ b/src/const/isdp/mod/componentAudit.ts @@ -0,0 +1,72 @@ +import { option as baseOption } from '../componentBase'; +import { deepClone } from '@/utils/common'; + +export const permissionConstant = { + ADMIN: 'admin', + READ: 'read', + WRITE: 'write', +}; + +// 系统模块 +export const permissionDic = [ + { + label: '管理', + value: 'admin', + }, + { + label: '读', + value: 'read', + }, + { + label: '写', + value: 'write', + }, +]; + +export const option = deepClone(baseOption); +option.header = false; +option.addBtn = false; +option.menuWidth = 200; + +const hideArr = ['name', 'componentClassify', 'publicStatus']; +const columnArr = []; +option.column.forEach((element) => { + if (hideArr.includes(element.prop)) { + element.align = 'center'; + columnArr.push(element); + } +}); + +option.column = [ + ...columnArr, + { + label: '组件标识', + prop: 'identifier', + type: 'input', + width: 150, + }, + { + label: '组件版本', + prop: 'componentVersion', + type: 'input', + width: 120, + }, + { + label: '组件描述', + prop: 'recommend', + type: 'input', + width: 150, + }, + { + label: '组件评分', + prop: 'stars', + type: 'input', + width: 100, + }, + { + label: '审核结果', + prop: 'reviewOpinion', + type: 'input', + width: 'auto', + }, +]; diff --git a/src/const/isdp/mod/componentCollaboration.ts b/src/const/isdp/mod/componentCollaboration.ts new file mode 100644 index 0000000..8169ed7 --- /dev/null +++ b/src/const/isdp/mod/componentCollaboration.ts @@ -0,0 +1,59 @@ +import { option as baseOption } from '../componentBase'; +import { deepClone } from '@/util/util'; +import { globalOption } from '@/const/globalOption'; + +export const permissionConstant = { + ADMIN: 'admin', + READ: 'read', + WRITE: 'write', +}; + +// 系统模块 +export const permissionDic = [ + { + label: '管理', + value: 'admin', + }, + { + label: '读', + value: 'read', + }, + { + label: '写', + value: 'write', + }, +]; + +export const userOption = { + ...globalOption, + addBtn: false, + editBtn: false, + viewBtn: false, + header: false, + delBtn: false, + height: 200, + menuWidth: 100, + column: [ + { + label: '用户账号', + prop: 'collaboratorAccount', + }, + { + label: '操作权限', + prop: 'permission', + slot: true, + width: '120px', + }, + ], +}; + +export const option = deepClone(baseOption); +option.header = false; +option.addBtn = false; +option.column.push({ + label: '权限', + prop: 'permission', + type: 'select', + dicData: permissionDic, + display: false, +}); diff --git a/src/const/isdp/repository.ts b/src/const/isdp/repository.ts new file mode 100644 index 0000000..f8c3872 --- /dev/null +++ b/src/const/isdp/repository.ts @@ -0,0 +1,53 @@ +import { globalOption } from '../globalOption'; + +export const option = { + ...globalOption, + height: 'auto', + calcHeight: 30, + tip: false, + dialogClickModal: false, + header: false, + menu: true, + editBtn: false, + delBtn: false, + menuWidth: '100', + column: [ + { + label: '#', + prop: 'index', + fixed: true, + width: 40, + }, + { + label: '名称', + prop: 'name', + overHidden: true, + width: 200, + }, + { + label: '类型', + prop: 'type', + overHidden: true, + width: 100, + }, + { + label: '格式', + prop: 'format', + overHidden: true, + width: 100, + }, + { + label: '状态', + prop: 'status', + overHidden: true, + slot: true, + width: 150, + }, + { + label: 'URL', + prop: 'url', + slot: true, + overHidden: true, + }, + ], +}; diff --git a/src/pages/componentDevelopment/componentList/addApiModal.tsx b/src/pages/componentDevelopment/componentList/addApiModal.tsx new file mode 100644 index 0000000..e5d935a --- /dev/null +++ b/src/pages/componentDevelopment/componentList/addApiModal.tsx @@ -0,0 +1,115 @@ +import React, { useState, useEffect } from 'react'; +import { Modal, Form, Input, Message } from '@arco-design/web-react'; +import EditableTable from '@/pages/componentDevelopment/componentList/editableTable'; +import { updateComponentDesign } from '@/api/componentDevelopProcess'; + +const FormItem = Form.Item; +const TextArea = Input.TextArea; + +const AddApiModal = ({ visible, baseInfo, componentDesignProgress, onCancel, onOk }) => { + const [form] = Form.useForm(); + const [parametersData, setParametersData] = useState([]); + const [responsesData, setResponsesData] = useState([]); + + // 当 visible 或 componentDesignProgress 变化时,设置表单初始值 + useEffect(() => { + if (visible && componentDesignProgress) { + // 设置表单字段值 + form.setFieldsValue({ + ident: componentDesignProgress.ident || '', + desc: componentDesignProgress.desc || '' + }); + + // 设置参数表格数据 + if (componentDesignProgress.parameters && Array.isArray(componentDesignProgress.parameters)) { + setParametersData(componentDesignProgress.parameters.map((param, index) => ({ + key: param.id || index, + ...param + }))); + } + + // 设置响应表格数据 + if (componentDesignProgress.responses && Array.isArray(componentDesignProgress.responses)) { + setResponsesData(componentDesignProgress.responses.map((response, index) => ({ + key: response.id || index, + ...response + }))); + } + } + else if (visible) { + // 重置表单和表格数据 + form.resetFields(); + setParametersData([]); + setResponsesData([]); + } + }, [visible, componentDesignProgress, form]); + + const submit = async () => { + try { + await form.validate(); + const formData = form.getFields(); + const params = { + baseInfo + }; + + params['operates'] = { + ...formData, + type: 'EVENT', + parameters: parametersData, + responses: responsesData + }; + const res: any = await updateComponentDesign(params); + + if (res.code === 200) { + Message.success('新增成功'); + } + else { + Message.error(res.message); + } + + // 调用父组件传递的 onOk 回调,并传递数据 + onOk && onOk(params); + } catch (error) { + console.error('表单验证失败:', error); + Message.error('请检查表单填写是否正确'); + } + }; + + return ( + +
+ + + + +