diff --git a/src/components/AccountCreateUpdateForm/index.vue b/src/components/AccountCreateUpdateForm/index.vue index 9c316f29f..3bd0ad13b 100644 --- a/src/components/AccountCreateUpdateForm/index.vue +++ b/src/components/AccountCreateUpdateForm/index.vue @@ -60,7 +60,7 @@ export default { ] }, url: '/api/v1/accounts/accounts/', - form: Object.assign({ 'on_invalid': 'skip' }, this.account || {}), + form: Object.assign({ 'on_invalid': 'error' }, this.account || {}), encryptedFields: ['secret'], fields: [ [this.$t('assets.Asset'), ['assets']], diff --git a/src/components/AccountListTable/AccountCreateUpdate.vue b/src/components/AccountListTable/AccountCreateUpdate.vue index 478e0897a..49888f718 100644 --- a/src/components/AccountListTable/AccountCreateUpdate.vue +++ b/src/components/AccountListTable/AccountCreateUpdate.vue @@ -97,16 +97,17 @@ export default { } } this.$axios.post(url, data, { - disableFlashErrorMsg: true + disableFlashErrorMsg: iVisible }).then((data) => { this.handleResult(data, null) + this.iVisible = iVisible + if (!iVisible) { + this.$emit('add', true) + } }).catch(error => { + this.iVisible = iVisible this.handleResult(null, error) }) - this.iVisible = iVisible - if (!iVisible) { - this.$emit('add', true) - } }, editAccount(form) { const data = { ...form } diff --git a/src/components/AccountListTable/AccountList.vue b/src/components/AccountListTable/AccountList.vue index 720f23268..d95add6ec 100644 --- a/src/components/AccountListTable/AccountList.vue +++ b/src/components/AccountListTable/AccountList.vue @@ -321,7 +321,6 @@ export default { { name: 'add-template', title: this.$t('common.TemplateAdd'), - type: 'primary', has: !(this.platform || this.asset), can: () => { return vm.$hasPerm('accounts.add_account') && !this.$store.getters.currentOrgIsRoot diff --git a/src/components/AccountListTable/BulkCreateResultDialog.vue b/src/components/AccountListTable/BulkCreateResultDialog.vue index 860242ea0..0c368dfb9 100644 --- a/src/components/AccountListTable/BulkCreateResultDialog.vue +++ b/src/components/AccountListTable/BulkCreateResultDialog.vue @@ -113,4 +113,8 @@ export default { .color-default { } +::v-deep .el-data-table .el-table .el-table__row > td > div > span { + white-space: inherit; +} + diff --git a/src/components/FormFields/TextReadonly.vue b/src/components/FormFields/TextReadonly.vue new file mode 100644 index 000000000..75daefc53 --- /dev/null +++ b/src/components/FormFields/TextReadonly.vue @@ -0,0 +1,36 @@ + + + + + diff --git a/src/components/ListTable/TableAction/ImportTable.vue b/src/components/ListTable/TableAction/ImportTable.vue index 51d25a1df..a7d8740f9 100644 --- a/src/components/ListTable/TableAction/ImportTable.vue +++ b/src/components/ListTable/TableAction/ImportTable.vue @@ -285,7 +285,9 @@ export default { const data = [] // eslint-disable-next-line prefer-const for (let [key, value] of Object.entries(errorData)) { - if (typeof value === 'object') { + if (Array.isArray(value)) { + value = JSON.stringify(value) + } else if (typeof value === 'object') { value = this.beautifyErrorData(value) } let label = this.tableColumnNameMapper[key] diff --git a/src/components/TableFormatters/EditableInputFormatter.vue b/src/components/TableFormatters/EditableInputFormatter.vue index fbb119344..e7b8cc33e 100644 --- a/src/components/TableFormatters/EditableInputFormatter.vue +++ b/src/components/TableFormatters/EditableInputFormatter.vue @@ -63,9 +63,9 @@ export default { this.inEditMode = true }, getCellValue(val) { - let v + let v = '' if (val && typeof val === 'object') { - v = val['name'] || val['display_name'] || '' + v = val['name'] || val['display_name'] || JSON.stringify(val) } return v || val }, diff --git a/src/i18n/langs/en.json b/src/i18n/langs/en.json index f830583cb..f18757510 100644 --- a/src/i18n/langs/en.json +++ b/src/i18n/langs/en.json @@ -141,7 +141,7 @@ "users": "User", "Rules": "Rule", "Action": "Action", - "ip_group_help_text": "The format is a comma-separated string, * means match all. Example: 192.168.10.1, 192.168.1.0/24, 10.1.1.1-10.1.1.20, 2001:db8:2de::e13, 2001:db8:1a:1110::/64", + "ip_group_help_text": "* means match all. Example: 192.168.10.1, 192.168.1.0/24, 10.1.1.1-10.1.1.20, 2001:db8:2de::e13, 2001:db8:1a:1110::/64", "apply_login_account": "Apply login account" }, "applications": { @@ -1720,7 +1720,9 @@ "UpdateNodeAssetHardwareInfo": "Update node asset hardware information" }, "users": { + "SetStatus": "Set status", "Set": "Set", + "NotSet": "Not set", "Login": "Users login", "InviteSuccess": "Invite success", "inputPhone": "Please enter your mobile phone number", diff --git a/src/i18n/langs/ja.json b/src/i18n/langs/ja.json index fc9890b59..ac5a16c70 100644 --- a/src/i18n/langs/ja.json +++ b/src/i18n/langs/ja.json @@ -120,7 +120,7 @@ "AccountUsername": "アカウント (ユーザー名)", "username": "ユーザー名", "ip_group": "IPグループ", - "ip_group_help_text": "コンマ区切りの文字列で、 * はすべてにマッチすることを示します。例: 192.168.10.1、192.168.1.0/24、10.1.1-10.1.1. 20、2001:db8:2de::e 13、2001:db8:1a:1110::/64", + "ip_group_help_text": "* はすべてにマッチすることを示します。例: 192.168.10.1、192.168.1.0/24、10.1.1-10.1.1. 20、2001:db8:2de::e 13、2001:db8:1a:1110::/64", "action": "アクション", "Rules": "ルール", "Action": "アクション", @@ -1712,7 +1712,9 @@ "UpdateNodeAssetHardwareInfo": "ノード資産ハードウェア情報の更新" }, "users": { + "SetStatus": "ステータスの設定", "Set": "設定", + "NotSet": "未設定", "Login": "ユーザー登録", "InviteSuccess": "成功招待", "inputPhone": "携帯電話の番号をお願いします", diff --git a/src/i18n/langs/zh.json b/src/i18n/langs/zh.json index 28183aaed..25e7fbef9 100644 --- a/src/i18n/langs/zh.json +++ b/src/i18n/langs/zh.json @@ -121,7 +121,7 @@ "reviewer": "审批人", "username": "用户名", "ip_group": "IP 组", - "ip_group_help_text": "格式为逗号分隔的字符串, * 表示匹配所有。例如: 192.168.10.1, 192.168.1.0/24, 10.1.1.1-10.1.1.20, 2001:db8:2de::e13, 2001:db8:1a:1110::/64", + "ip_group_help_text": "* 表示匹配所有。例如: 192.168.10.1, 192.168.1.0/24, 10.1.1.1-10.1.1.20, 2001:db8:2de::e13, 2001:db8:1a:1110::/64", "action": "动作", "Rules": "规则", "Action": "动作", @@ -1708,7 +1708,9 @@ "UpdateNodeAssetHardwareInfo": "更新节点资产硬件信息" }, "users": { + "SetStatus": "设置状态", "Set": "已设置", + "NotSet": "未设置", "Login": "用户登录", "InviteSuccess": "邀请成功", "inputPhone": "请输入手机号码", diff --git a/src/layout/components/NavHeader/SiteMessages.vue b/src/layout/components/NavHeader/SiteMessages.vue index 60ee95122..e0554e680 100644 --- a/src/layout/components/NavHeader/SiteMessages.vue +++ b/src/layout/components/NavHeader/SiteMessages.vue @@ -62,6 +62,7 @@ :title="currentMsg.content.subject" :visible.sync="msgDetailVisible" @cancel="cancelRead" + @close="markAsRead([currentMsg])" @confirm="markAsRead([currentMsg])" >
diff --git a/src/router/workbench/index.js b/src/router/workbench/index.js index 2506f8e4e..02e50c0f0 100644 --- a/src/router/workbench/index.js +++ b/src/router/workbench/index.js @@ -132,7 +132,7 @@ export default { } }, { - path: 'update', + path: ':id/update', component: () => import('@/views/ops/Job/JobUpdateCreate'), name: 'JobUpdate', hidden: true, @@ -217,11 +217,22 @@ export default { activeMenu: '/workbench/ops/templates' } }, + { + path: 'playbook/create', + name: 'PlaybookCreate', + hidden: true, + component: () => import('@/views/ops/Template/Playbook/PlaybookCreateUpdate'), + meta: { + title: i18n.t('ops.PlaybookCreate'), + permissions: ['ops.add_playbook'], + activeMenu: '/workbench/ops/templates' + } + }, { path: 'playbook/:id/update', name: 'PlaybookUpdate', hidden: true, - component: () => import('@/views/ops/Template/Playbook/PlaybookUpdate'), + component: () => import('@/views/ops/Template/Playbook/PlaybookCreateUpdate'), meta: { title: i18n.t('ops.PlaybookUpdate'), permissions: ['ops.change_playbook'], diff --git a/src/views/accounts/Account/AccountDetail/Detail.vue b/src/views/accounts/Account/AccountDetail/Detail.vue index be5021e1d..0e8906d07 100644 --- a/src/views/accounts/Account/AccountDetail/Detail.vue +++ b/src/views/accounts/Account/AccountDetail/Detail.vue @@ -196,7 +196,7 @@ export default { callbacks: Object.freeze({ change: (value) => { const relationUrl = `/api/v1/accounts/accounts/${this.object.id}/` - return this.$axios.patch(relationUrl, { su_from: value }) + return this.$axios.patch(relationUrl, { su_from: value, name: this.object.name }) } }) } @@ -205,7 +205,7 @@ export default { url: `/api/v1/accounts/accounts/${this.object.id}`, excludes: [ 'template', 'privileged', 'secret', - 'passphrase', 'spec_info' + 'passphrase', 'spec_info', 'params' ], formatters: { asset: (item, value) => { @@ -214,6 +214,9 @@ export default { params: { id: this.object.asset.id } } return { value } + }, + su_from: (item, value) => { + return {value?.name ? value?.name + `(${value?.username})` : ''} } } } diff --git a/src/views/accounts/AccountChangeSecret/AccountChangeSecretDetail/AccountChangeSecretAsset/index.vue b/src/views/accounts/AccountChangeSecret/AccountChangeSecretDetail/AccountChangeSecretAsset/index.vue index 7c0594d9b..3cdb886ed 100644 --- a/src/views/accounts/AccountChangeSecret/AccountChangeSecretDetail/AccountChangeSecretAsset/index.vue +++ b/src/views/accounts/AccountChangeSecret/AccountChangeSecretDetail/AccountChangeSecretAsset/index.vue @@ -143,6 +143,7 @@ export default { that.select2.disabledValues.splice(i, 1) } this.$message.success(this.$tc('common.deleteSuccessMsg')) + window.location.reload() this.$refs.listTable.reloadTable() } } diff --git a/src/views/acl/AssetAcl/AssetAclCreateUpdate.vue b/src/views/acl/AssetAcl/AssetAclCreateUpdate.vue index 24cdfb5cf..a987f0d9d 100644 --- a/src/views/acl/AssetAcl/AssetAclCreateUpdate.vue +++ b/src/views/acl/AssetAcl/AssetAclCreateUpdate.vue @@ -5,9 +5,7 @@ diff --git a/src/views/assets/Platform/PlatformCreateUpdate.vue b/src/views/assets/Platform/PlatformCreateUpdate.vue index 8425c49a9..a2579a450 100644 --- a/src/views/assets/Platform/PlatformCreateUpdate.vue +++ b/src/views/assets/Platform/PlatformCreateUpdate.vue @@ -8,6 +8,7 @@ :fields-meta="fieldsMeta" :has-detail-in-msg="false" :initial="initial" + :has-reset="false" :url="url" />
@@ -113,6 +114,7 @@ export default { async updateSuMethods(constrains) { this.suMethodLimits = constrains['su_methods'] || [] this.updateSuMethodOptions() + this.initial.su_method = this.suMethodLimits[0] }, async setCategories() { const category = this.$route.query.category @@ -170,5 +172,17 @@ export default { width: 100%; } } +>>> .itemMethodKey.el-form-item { + display: inline-block; + width: 100%; + .el-form-item__content { + width: 70%; + } +} +>>> .itemParamsKey.el-form-item { + display: inline-block; + position: absolute; + right: 20px; +} diff --git a/src/views/assets/Platform/PlatformList.vue b/src/views/assets/Platform/PlatformList.vue index 94537e5e5..a67f29cf9 100644 --- a/src/views/assets/Platform/PlatformList.vue +++ b/src/views/assets/Platform/PlatformList.vue @@ -24,6 +24,23 @@ export default { const vm = this return { loading: true, + nameComponentMap: { + host: { + icon: 'fa-inbox' + }, + device: { + icon: 'fa-microchip' + }, + database: { + icon: 'fa-database' + }, + cloud: { + icon: 'fa-cloud' + }, + web: { + icon: 'fa-globe' + } + }, tab: { submenu: [], activeMenu: 'host' @@ -86,6 +103,7 @@ export default { } }, headerActions: { + hasBulkDelete: false, hasRightActions: true, createRoute: 'PlatformCreate', canCreate: () => { @@ -134,12 +152,13 @@ export default { }, async setCategories() { const state = await this.$store.dispatch('assets/getAssetCategories') - this.tab.submenu = state.assetCategories.map(item => { - return { - title: item.label, - name: item.value - } - }) + for (const item of state.assetCategories) { + const name = item.value + this.nameComponentMap[name]['name'] = name + this.nameComponentMap[name]['title'] = item.label + } + + this.tab.submenu = _.toArray(this.nameComponentMap) } } } diff --git a/src/views/assets/Platform/const.js b/src/views/assets/Platform/const.js index f8817f5a3..826d29dc0 100644 --- a/src/views/assets/Platform/const.js +++ b/src/views/assets/Platform/const.js @@ -32,7 +32,7 @@ export const platformFieldsMeta = (vm) => { gather_facts_method: {}, push_account_method: {}, push_account_params: { - label: vm.$t('assets.PushParams') + label: '' }, change_secret_method: { on: { @@ -42,7 +42,7 @@ export const platformFieldsMeta = (vm) => { } }, change_secret_params: { - label: vm.$t('assets.ChangeSecretParams'), + label: '', el: { title: vm.$t('assets.ChangeSecretParams'), method: 'change_secret_posix' @@ -125,6 +125,8 @@ export const setAutomations = (vm) => { _.set(autoFieldsMeta, `${itemMethodKey}.hidden`, (formValue) => { return !formValue[itemEnabledKey] || !formValue['ansible_enabled'] }) + // 设置 enableMethod className + _.set(autoFieldsMeta, `${itemMethodKey}.attrs.class`, 'itemMethodKey') // 设置 enableParams Hidden _.set(autoFieldsMeta, `${itemParamsKey}.hidden`, (formValue) => { return !formValue[itemEnabledKey] || !formValue['ansible_enabled'] @@ -139,6 +141,10 @@ export const setAutomations = (vm) => { // 设置 params 类型字段的组件和组件参数 if (needSettingParamsFields.includes(item)) { + // 设置 enableParams label + _.set(autoFieldsMeta, `${itemParamsKey}.label`, '') + // 设置 enableParams className + _.set(autoFieldsMeta, `${itemParamsKey}.attrs.class`, 'itemParamsKey') _.set(autoFieldsMeta, `${itemParamsKey}.component`, AutomationParamsSetting) _.set(autoFieldsMeta, `${itemParamsKey}.el.method`, initial[itemMethodKey]) } diff --git a/src/views/assets/const.js b/src/views/assets/const.js index 2c79473bc..ab51e4ad8 100644 --- a/src/views/assets/const.js +++ b/src/views/assets/const.js @@ -29,7 +29,7 @@ export const filterSelectValues = (values) => { export const assetFieldsMeta = (vm) => { const platformProtocols = [] const secretTypes = [] - const platformType = vm?.$route.query.type + const platformType = vm?.$route.query?.type return { address: { rules: [rules.specialEmojiCheck, rules.RequiredChange] diff --git a/src/views/ops/Template/Playbook.vue b/src/views/ops/Template/Playbook.vue index 078ff9b01..9d162fac4 100644 --- a/src/views/ops/Template/Playbook.vue +++ b/src/views/ops/Template/Playbook.vue @@ -2,7 +2,6 @@
-
@@ -10,13 +9,11 @@ import GenericListTable from '@/layout/components/GenericListTable' import UploadDialog from '@/views/ops/Template/Playbook/UploadDialog' import { ActionsFormatter } from '@/components/TableFormatters' -import CreatePlaybookDialog from '@/views/ops/Template/Playbook/CreatePlaybookDialog.vue' export default { components: { UploadDialog, - GenericListTable, - CreatePlaybookDialog + GenericListTable }, data() { return { @@ -49,18 +46,16 @@ export default { } }, headerActions: { + createRoute: 'PlaybookCreate', hasRefresh: true, hasExport: false, hasImport: false, hasMoreActions: true, - onCreate: () => { - this.uploadDialogVisible = true - }, moreCreates: { callback: (item) => { switch (item.name) { case 'create': - this.createDialogVisible = true + this.$router.push({ name: 'PlaybookCreate' }) break case 'upload': this.uploadDialogVisible = true diff --git a/src/views/ops/Template/Playbook/CreatePlaybookDialog.vue b/src/views/ops/Template/Playbook/CreatePlaybookDialog.vue deleted file mode 100644 index e2b23c9ad..000000000 --- a/src/views/ops/Template/Playbook/CreatePlaybookDialog.vue +++ /dev/null @@ -1,79 +0,0 @@ - - - - - diff --git a/src/views/ops/Template/Playbook/PlaybookUpdate.vue b/src/views/ops/Template/Playbook/PlaybookCreateUpdate.vue similarity index 100% rename from src/views/ops/Template/Playbook/PlaybookUpdate.vue rename to src/views/ops/Template/Playbook/PlaybookCreateUpdate.vue diff --git a/src/views/profile/ProfileUpdate/SecretKeyUpdate.vue b/src/views/profile/ProfileUpdate/SecretKeyUpdate.vue index 382cddf8e..81188bc37 100644 --- a/src/views/profile/ProfileUpdate/SecretKeyUpdate.vue +++ b/src/views/profile/ProfileUpdate/SecretKeyUpdate.vue @@ -15,6 +15,7 @@