mirror of
https://github.com/jumpserver/lina.git
synced 2026-01-14 03:46:26 +00:00
Compare commits
64 Commits
v3.10.9-lt
...
pr@v3@fixe
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3e009c17fd | ||
|
|
66532f4d4b | ||
|
|
42f27eb30f | ||
|
|
57920bf771 | ||
|
|
290772f44e | ||
|
|
f140f2f59e | ||
|
|
7b1883e012 | ||
|
|
352ac7e828 | ||
|
|
1cbd58664c | ||
|
|
e48da6be9b | ||
|
|
fa31b36550 | ||
|
|
6b93a6563d | ||
|
|
d561701049 | ||
|
|
edbf477c1e | ||
|
|
6a2578b339 | ||
|
|
2cb7569cb0 | ||
|
|
9e0c623b9a | ||
|
|
40bf040501 | ||
|
|
efee7c7bbf | ||
|
|
5daecb84ae | ||
|
|
3be325214d | ||
|
|
581509f42f | ||
|
|
654b36b064 | ||
|
|
dcec73ae67 | ||
|
|
00bafa8164 | ||
|
|
da09af79a7 | ||
|
|
b596815ea5 | ||
|
|
cb37273e80 | ||
|
|
c5bf7d0ad2 | ||
|
|
c31195a67a | ||
|
|
1eb59b379a | ||
|
|
b7cee17156 | ||
|
|
f1c8874010 | ||
|
|
5ccaa3b77d | ||
|
|
27d3637330 | ||
|
|
9c8ceb04f0 | ||
|
|
ccd7b319c8 | ||
|
|
55637c7fa1 | ||
|
|
4e95c88318 | ||
|
|
1ff49ca16d | ||
|
|
91c44d0500 | ||
|
|
0b3a9844f7 | ||
|
|
95b58f3c96 | ||
|
|
128b9c79ba | ||
|
|
4eda83f83d | ||
|
|
4cd0071054 | ||
|
|
67a2a9be6a | ||
|
|
f927a2a3cc | ||
|
|
ca40cb34da | ||
|
|
d725e5497d | ||
|
|
56f6c17275 | ||
|
|
e1bde89b29 | ||
|
|
e9da168c9f | ||
|
|
c19ef24ec9 | ||
|
|
fb7c4a8b2a | ||
|
|
428ba49f9c | ||
|
|
7602d6e270 | ||
|
|
7b62ce2d33 | ||
|
|
6ed40c45b0 | ||
|
|
31238e0398 | ||
|
|
676ac2bbf6 | ||
|
|
d5415b84c9 | ||
|
|
5e91917ba4 | ||
|
|
c4361b4c17 |
@@ -10,3 +10,4 @@ jobs:
|
|||||||
- uses: jumpserver/action-generic-handler@master
|
- uses: jumpserver/action-generic-handler@master
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.PRIVATE_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.PRIVATE_TOKEN }}
|
||||||
|
I18N_TOKEN: ${{ secrets.I18N_TOKEN }}
|
||||||
|
|||||||
@@ -34,6 +34,7 @@
|
|||||||
"css-color-function": "^1.3.3",
|
"css-color-function": "^1.3.3",
|
||||||
"decimal.js": "^10.4.3",
|
"decimal.js": "^10.4.3",
|
||||||
"deepmerge": "^4.2.2",
|
"deepmerge": "^4.2.2",
|
||||||
|
"dompurify": "^3.1.6",
|
||||||
"echarts": "4.7.0",
|
"echarts": "4.7.0",
|
||||||
"element-ui": "2.13.2",
|
"element-ui": "2.13.2",
|
||||||
"eslint-plugin-html": "^6.0.0",
|
"eslint-plugin-html": "^6.0.0",
|
||||||
|
|||||||
@@ -151,6 +151,3 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
</style>
|
|
||||||
|
|||||||
@@ -353,7 +353,7 @@ export default {
|
|||||||
name: 'BulkVerify',
|
name: 'BulkVerify',
|
||||||
title: this.$t('accounts.BulkVerify'),
|
title: this.$t('accounts.BulkVerify'),
|
||||||
type: 'primary',
|
type: 'primary',
|
||||||
fa: 'fa-handshake-o',
|
fa: 'fa-link',
|
||||||
can: ({ selectedRows }) => {
|
can: ({ selectedRows }) => {
|
||||||
return selectedRows.length > 0 &&
|
return selectedRows.length > 0 &&
|
||||||
['clickhouse', 'redis', 'website', 'chatgpt'].indexOf(selectedRows[0].asset.type.value) === -1 &&
|
['clickhouse', 'redis', 'website', 'chatgpt'].indexOf(selectedRows[0].asset.type.value) === -1 &&
|
||||||
|
|||||||
@@ -83,6 +83,10 @@ export default {
|
|||||||
type: String,
|
type: String,
|
||||||
default: ''
|
default: ''
|
||||||
},
|
},
|
||||||
|
type: {
|
||||||
|
type: String,
|
||||||
|
default: 'account'
|
||||||
|
},
|
||||||
title: {
|
title: {
|
||||||
type: String,
|
type: String,
|
||||||
default: function() {
|
default: function() {
|
||||||
@@ -136,7 +140,8 @@ export default {
|
|||||||
name: this.secretInfo.name,
|
name: this.secretInfo.name,
|
||||||
secret: encryptPassword(this.modifiedSecret)
|
secret: encryptPassword(this.modifiedSecret)
|
||||||
}
|
}
|
||||||
this.$axios.patch(`/api/v1/accounts/accounts/${this.account.id}/`, params).then(() => {
|
const url = this.type === 'account' ? `/api/v1/accounts/accounts` : `/api/v1/accounts/account-templates`
|
||||||
|
this.$axios.patch(`${url}/${this.account.id}/`, params).then(() => {
|
||||||
this.$message.success(this.$tc('common.updateSuccessMsg'))
|
this.$message.success(this.$tc('common.updateSuccessMsg'))
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<Dialog
|
<Dialog
|
||||||
:close-on-click-modal="false"
|
:close-on-click-modal="false"
|
||||||
|
:loading-status="!isLoaded"
|
||||||
:title="$tc('assets.Assets')"
|
:title="$tc('assets.Assets')"
|
||||||
custom-class="asset-select-dialog"
|
custom-class="asset-select-dialog"
|
||||||
top="2vh"
|
top="2vh"
|
||||||
@@ -21,6 +22,7 @@
|
|||||||
:tree-setting="treeSetting"
|
:tree-setting="treeSetting"
|
||||||
class="tree-table"
|
class="tree-table"
|
||||||
v-bind="$attrs"
|
v-bind="$attrs"
|
||||||
|
@loaded="handleTableLoaded"
|
||||||
/>
|
/>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
</template>
|
</template>
|
||||||
@@ -63,6 +65,7 @@ export default {
|
|||||||
data() {
|
data() {
|
||||||
const vm = this
|
const vm = this
|
||||||
return {
|
return {
|
||||||
|
isLoaded: false,
|
||||||
dialogVisible: false,
|
dialogVisible: false,
|
||||||
rowSelected: _.cloneDeep(this.value) || [],
|
rowSelected: _.cloneDeep(this.value) || [],
|
||||||
rowsAdd: [],
|
rowsAdd: [],
|
||||||
@@ -143,6 +146,9 @@ export default {
|
|||||||
if (selectValueIndex > -1) {
|
if (selectValueIndex > -1) {
|
||||||
this.rowSelected.splice(selectValueIndex, 1)
|
this.rowSelected.splice(selectValueIndex, 1)
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
handleTableLoaded() {
|
||||||
|
this.isLoaded = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,7 +28,6 @@
|
|||||||
<script>
|
<script>
|
||||||
import Select2 from '@/components/Form/FormFields/Select2.vue'
|
import Select2 from '@/components/Form/FormFields/Select2.vue'
|
||||||
import AssetSelectDialog from './dialog.vue'
|
import AssetSelectDialog from './dialog.vue'
|
||||||
import { b } from 'css-color-function/lib/adjusters'
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
componentName: 'AssetSelect',
|
componentName: 'AssetSelect',
|
||||||
@@ -81,7 +80,6 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
b,
|
|
||||||
handleFocus() {
|
handleFocus() {
|
||||||
this.$refs.select2.selectRef.blur()
|
this.$refs.select2.selectRef.blur()
|
||||||
this.dialogVisible = true
|
this.dialogVisible = true
|
||||||
|
|||||||
@@ -31,6 +31,10 @@ export default {
|
|||||||
type: String,
|
type: String,
|
||||||
default: '/api/v1/assets/assets/'
|
default: '/api/v1/assets/assets/'
|
||||||
},
|
},
|
||||||
|
typeUrl: {
|
||||||
|
type: String,
|
||||||
|
default: '/api/v1/assets/nodes/category/tree/'
|
||||||
|
},
|
||||||
nodeUrl: {
|
nodeUrl: {
|
||||||
type: String,
|
type: String,
|
||||||
default: '/api/v1/assets/nodes/'
|
default: '/api/v1/assets/nodes/'
|
||||||
@@ -101,9 +105,9 @@ export default {
|
|||||||
showAssets: false,
|
showAssets: false,
|
||||||
showSearch: false,
|
showSearch: false,
|
||||||
customTreeHeaderName: this.$t('assets.BuiltinTree'),
|
customTreeHeaderName: this.$t('assets.BuiltinTree'),
|
||||||
url: '/api/v1/assets/nodes/category/tree/',
|
url: this.typeUrl,
|
||||||
nodeUrl: this.treeSetting?.nodeUrl || this.nodeUrl,
|
nodeUrl: this.treeSetting?.nodeUrl || this.nodeUrl,
|
||||||
treeUrl: `/api/v1/assets/nodes/category/tree/?assets=${showAssets ? '1' : '0'}&count_resource=${this.treeSetting.countResource || 'asset'}`,
|
treeUrl: `${this.typeUrl}?assets=${showAssets ? '1' : '0'}&count_resource=${this.treeSetting.countResource || 'asset'}`,
|
||||||
callback: {
|
callback: {
|
||||||
onSelected: (event, treeNode) => this.getAssetsUrl(treeNode)
|
onSelected: (event, treeNode) => this.getAssetsUrl(treeNode)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -82,6 +82,7 @@
|
|||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import Dialog from '@/components/Dialog/index.vue'
|
import Dialog from '@/components/Dialog/index.vue'
|
||||||
|
import { encryptPassword } from '@/utils/crypto'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'UserConfirmDialog',
|
name: 'UserConfirmDialog',
|
||||||
@@ -199,7 +200,7 @@ export default {
|
|||||||
const data = {
|
const data = {
|
||||||
confirm_type: this.confirmTypeRequired,
|
confirm_type: this.confirmTypeRequired,
|
||||||
mfa_type: this.confirmTypeRequired === 'mfa' ? this.subTypeSelected : '',
|
mfa_type: this.confirmTypeRequired === 'mfa' ? this.subTypeSelected : '',
|
||||||
secret_key: this.secretValue
|
secret_key: this.confirmTypeRequired === 'password' ? encryptPassword(this.secretValue) : this.secretValue
|
||||||
}
|
}
|
||||||
this.$axios.post(`/api/v1/authentication/confirm/`, data).then(res => {
|
this.$axios.post(`/api/v1/authentication/confirm/`, data).then(res => {
|
||||||
this.callback()
|
this.callback()
|
||||||
|
|||||||
@@ -106,16 +106,28 @@ export default {
|
|||||||
|
|
||||||
if (Array.isArray(value)) {
|
if (Array.isArray(value)) {
|
||||||
if (typeof value[0] === 'object') {
|
if (typeof value[0] === 'object') {
|
||||||
value.forEach(item => {
|
const firstValue = value[0]
|
||||||
const fieldName = `${name}.${item.name}`
|
if (firstValue.hasOwnProperty('name')) {
|
||||||
if (excludes.includes(fieldName)) {
|
value.forEach(item => {
|
||||||
return
|
const fieldName = `${name}.${item.name}`
|
||||||
}
|
if (excludes.includes(fieldName)) {
|
||||||
this.items.push({
|
return
|
||||||
key: item.label,
|
}
|
||||||
value: item.value
|
this.items.push({
|
||||||
|
key: item.label,
|
||||||
|
value: item.value
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
} else {
|
||||||
|
value.forEach((item, index) => {
|
||||||
|
const v = Object.entries(item).map(([key, value]) => `${key}:${value}`).join(', ')
|
||||||
|
const data = { value: v }
|
||||||
|
if (index === 0) {
|
||||||
|
data['key'] = label
|
||||||
|
}
|
||||||
|
this.items.push(data)
|
||||||
|
})
|
||||||
|
}
|
||||||
} else if (typeof value[0] === 'string') {
|
} else if (typeof value[0] === 'string') {
|
||||||
value.forEach((item, index) => {
|
value.forEach((item, index) => {
|
||||||
let data = {}
|
let data = {}
|
||||||
|
|||||||
@@ -9,11 +9,13 @@
|
|||||||
v-bind="$attrs"
|
v-bind="$attrs"
|
||||||
v-on="$listeners"
|
v-on="$listeners"
|
||||||
>
|
>
|
||||||
<slot />
|
<div v-loading="loadingStatus">
|
||||||
|
<slot />
|
||||||
|
</div>
|
||||||
<div slot="footer" class="dialog-footer">
|
<div slot="footer" class="dialog-footer">
|
||||||
<slot name="footer">
|
<slot name="footer">
|
||||||
<el-button v-if="showCancel && showButtons" @click="onCancel">{{ cancelTitle }}</el-button>
|
<el-button v-if="showCancel && showButtons" @click="onCancel">{{ cancelTitle }}</el-button>
|
||||||
<el-button v-if="showConfirm && showButtons" :loading="loadingStatus" type="primary" @click="onConfirm">
|
<el-button v-if="showConfirm && showButtons" :disabled="loadingStatus" type="primary" @click="onConfirm">
|
||||||
{{ confirmTitle }}
|
{{ confirmTitle }}
|
||||||
</el-button>
|
</el-button>
|
||||||
</slot>
|
</slot>
|
||||||
@@ -71,13 +73,16 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {}
|
return {
|
||||||
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
iWidth() {
|
iWidth() {
|
||||||
return this.$store.getters.isMobile ? '1000px' : this.width
|
return this.$store.getters.isMobile ? '1000px' : this.width
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
mounted() {
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
onCancel() {
|
onCancel() {
|
||||||
this.$emit('cancel')
|
this.$emit('cancel')
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import BasicTree from '@/components/Form/FormFields/BasicTree.vue'
|
|||||||
import JsonEditor from '@/components/Form/FormFields/JsonEditor.vue'
|
import JsonEditor from '@/components/Form/FormFields/JsonEditor.vue'
|
||||||
import { assignIfNot } from '@/utils/common'
|
import { assignIfNot } from '@/utils/common'
|
||||||
import TagInput from '@/components/Form/FormFields/TagInput.vue'
|
import TagInput from '@/components/Form/FormFields/TagInput.vue'
|
||||||
import TransferSelect from '@/components/Form/FormFields/TransferSelect.vue'
|
|
||||||
|
|
||||||
export class FormFieldGenerator {
|
export class FormFieldGenerator {
|
||||||
constructor(emit) {
|
constructor(emit) {
|
||||||
@@ -134,9 +133,6 @@ export class FormFieldGenerator {
|
|||||||
case 'comment':
|
case 'comment':
|
||||||
field.el.type = 'textarea'
|
field.el.type = 'textarea'
|
||||||
break
|
break
|
||||||
case 'users':
|
|
||||||
field.component = TransferSelect
|
|
||||||
field.el.label = field.label
|
|
||||||
}
|
}
|
||||||
return field
|
return field
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,18 +7,11 @@
|
|||||||
</el-radio>
|
</el-radio>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item>
|
|
||||||
<el-radio v-model="radioValue" :label="2">
|
|
||||||
{{ this.$t('common.CronTab.from') }}
|
|
||||||
<el-input-number v-model="cycle01" :max="60" :min="0" size="mini" /> -
|
|
||||||
<el-input-number v-model="cycle02" :max="60" :min="0" size="mini" /> {{ this.$t('common.CronTab.min') }}
|
|
||||||
</el-radio>
|
|
||||||
</el-form-item>
|
|
||||||
|
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-radio v-model="radioValue" :label="3">
|
<el-radio v-model="radioValue" :label="3">
|
||||||
{{ this.$t('common.CronTab.from') }}
|
{{ this.$t('common.CronTab.from') }}
|
||||||
<el-input-number v-model="average02" :max="60" :min="1" size="mini" /> {{ this.$t('common.CronTab.min') }}{{ this.$t('common.CronTab.executeOnce') }}
|
<el-input-number v-model="average02" :max="60" :min="1" size="mini" />
|
||||||
|
{{ this.$t('common.CronTab.min') }}{{ this.$t('common.CronTab.executeOnce') }}
|
||||||
</el-radio>
|
</el-radio>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
@@ -33,7 +26,7 @@
|
|||||||
size="small"
|
size="small"
|
||||||
style="width:100%"
|
style="width:100%"
|
||||||
>
|
>
|
||||||
<el-option v-for="item in 60" :key="item" :value="item-1">{{ item-1 }}</el-option>
|
<el-option v-for="item in 60" :key="item" :value="item-1">{{ item - 1 }}</el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-radio>
|
</el-radio>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@@ -158,7 +151,7 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.el-form-item--small.el-form-item {
|
.el-form-item--small.el-form-item {
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -225,9 +225,6 @@ export default {
|
|||||||
handler(newValue, oldValue) {
|
handler(newValue, oldValue) {
|
||||||
},
|
},
|
||||||
deep: true
|
deep: true
|
||||||
},
|
|
||||||
iOptions(val) {
|
|
||||||
this.remote = val.length !== 0
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async mounted() {
|
async mounted() {
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
/>
|
/>
|
||||||
<Dialog
|
<Dialog
|
||||||
v-if="showTransfer"
|
v-if="showTransfer"
|
||||||
|
:loading-status="!isLoaded"
|
||||||
:close-on-click-modal="false"
|
:close-on-click-modal="false"
|
||||||
:title="label"
|
:title="label"
|
||||||
:visible.sync="showTransfer"
|
:visible.sync="showTransfer"
|
||||||
@@ -18,6 +19,7 @@
|
|||||||
width="730px"
|
width="730px"
|
||||||
@cancel="handleTransCancel"
|
@cancel="handleTransCancel"
|
||||||
@confirm="handleTransConfirm"
|
@confirm="handleTransConfirm"
|
||||||
|
v-on="$listeners"
|
||||||
>
|
>
|
||||||
<krryPaging v-if="selectInitialized" ref="pageTransfer" class="transfer" v-bind="pagingTransfer" />
|
<krryPaging v-if="selectInitialized" ref="pageTransfer" class="transfer" v-bind="pagingTransfer" />
|
||||||
</Dialog>
|
</Dialog>
|
||||||
@@ -77,13 +79,16 @@ export default {
|
|||||||
if (keyword) {
|
if (keyword) {
|
||||||
params['search'] = keyword
|
params['search'] = keyword
|
||||||
}
|
}
|
||||||
|
this.isLoaded = false
|
||||||
const data = await this.$axios.get(url, { params })
|
const data = await this.$axios.get(url, { params })
|
||||||
|
this.isLoaded = true
|
||||||
return data['results'].map(item => {
|
return data['results'].map(item => {
|
||||||
const n = transformOption(item)
|
const n = transformOption(item)
|
||||||
return { id: n.value, label: n.label }
|
return { id: n.value, label: n.label }
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
|
isLoaded: false,
|
||||||
showTransfer: false,
|
showTransfer: false,
|
||||||
selectInitialized: false,
|
selectInitialized: false,
|
||||||
select2: {
|
select2: {
|
||||||
@@ -166,7 +171,3 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
|
|
||||||
</style>
|
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ export default {
|
|||||||
patterns.push([/\d/, i18n.t('common.password.NUMBER_REQUIRED')])
|
patterns.push([/\d/, i18n.t('common.password.NUMBER_REQUIRED')])
|
||||||
}
|
}
|
||||||
if (passwordRule['SECURITY_PASSWORD_SPECIAL_CHAR']) {
|
if (passwordRule['SECURITY_PASSWORD_SPECIAL_CHAR']) {
|
||||||
const pattern = new RegExp("[`~!@#$^&*()=|{}':;',\\[\\].<>/?~!@#¥……&*()——|{}【】‘;:”“'。,、?]")
|
const pattern = new RegExp("[`~!@#$^&*()=|{}':;',\\[\\].<>/?~!@#¥……&*()——|{}【】‘;:”“'。,、?_+-]")
|
||||||
patterns.push([pattern, i18n.t('common.password.SPECIAL_CHAR_REQUIRED')])
|
patterns.push([pattern, i18n.t('common.password.SPECIAL_CHAR_REQUIRED')])
|
||||||
}
|
}
|
||||||
for (const [pattern, msg] of patterns) {
|
for (const [pattern, msg] of patterns) {
|
||||||
|
|||||||
@@ -53,27 +53,34 @@ export default {
|
|||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
boxTitle: {
|
boxTitle: {
|
||||||
type: Array
|
type: Array,
|
||||||
|
default: () => []
|
||||||
},
|
},
|
||||||
boxOperation: {
|
boxOperation: {
|
||||||
type: Array
|
type: Array,
|
||||||
|
default: () => []
|
||||||
},
|
},
|
||||||
// 地域数据
|
// 地域数据
|
||||||
dataObj: {
|
dataObj: {
|
||||||
type: Object
|
type: Object,
|
||||||
|
default: () => {}
|
||||||
},
|
},
|
||||||
// 已选数据
|
// 已选数据
|
||||||
selectedData: {
|
selectedData: {
|
||||||
type: Array
|
type: Array,
|
||||||
|
default: () => []
|
||||||
},
|
},
|
||||||
onChangeSelected: {
|
onChangeSelected: {
|
||||||
type: Function
|
type: Function,
|
||||||
|
default: () => () => {}
|
||||||
},
|
},
|
||||||
filterable: {
|
filterable: {
|
||||||
type: Boolean
|
type: Boolean,
|
||||||
|
default: () => false
|
||||||
},
|
},
|
||||||
filterPlaceholder: {
|
filterPlaceholder: {
|
||||||
type: String
|
type: String,
|
||||||
|
default: () => ''
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
|
|||||||
@@ -46,7 +46,7 @@
|
|||||||
<div class="vip-footer">
|
<div class="vip-footer">
|
||||||
<el-button
|
<el-button
|
||||||
type="text"
|
type="text"
|
||||||
:disabled="selectedDistrict.length > 0 ? false : true"
|
:disabled="selectedDistrict.length<=0"
|
||||||
size="small"
|
size="small"
|
||||||
round
|
round
|
||||||
@click="checkedSelected"
|
@click="checkedSelected"
|
||||||
@@ -62,23 +62,29 @@ export default {
|
|||||||
components: {},
|
components: {},
|
||||||
props: {
|
props: {
|
||||||
title: {
|
title: {
|
||||||
type: String
|
type: String,
|
||||||
|
default: () => ''
|
||||||
},
|
},
|
||||||
operation: {
|
operation: {
|
||||||
type: String
|
type: String,
|
||||||
|
default: () => ''
|
||||||
},
|
},
|
||||||
operateId: {
|
operateId: {
|
||||||
type: Number
|
type: Number,
|
||||||
|
default: () => 0
|
||||||
},
|
},
|
||||||
// 区域数据
|
// 区域数据
|
||||||
districtList: {
|
districtList: {
|
||||||
type: Array
|
type: Array,
|
||||||
|
default: () => []
|
||||||
},
|
},
|
||||||
filterable: {
|
filterable: {
|
||||||
type: Boolean
|
type: Boolean,
|
||||||
|
default: () => false
|
||||||
},
|
},
|
||||||
filterPlaceholder: {
|
filterPlaceholder: {
|
||||||
type: String
|
type: String,
|
||||||
|
default: () => ''
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
|
|||||||
@@ -34,12 +34,14 @@ class StrategyNormal extends StrategyAbstract {
|
|||||||
onSelectionChange(val) {
|
onSelectionChange(val) {
|
||||||
this.elDataTable.selected = val
|
this.elDataTable.selected = val
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* toggleRowSelection和clearSelection的表现与el-table一致
|
* toggleRowSelection和clearSelection的表现与el-table一致
|
||||||
*/
|
*/
|
||||||
toggleRowSelection(...args) {
|
toggleRowSelection(...args) {
|
||||||
return this.elTable.toggleRowSelection(...args)
|
return this.elTable.toggleRowSelection(...args)
|
||||||
}
|
}
|
||||||
|
|
||||||
clearSelection() {
|
clearSelection() {
|
||||||
return this.elTable.clearSelection()
|
return this.elTable.clearSelection()
|
||||||
}
|
}
|
||||||
@@ -50,12 +52,12 @@ class StrategyNormal extends StrategyAbstract {
|
|||||||
*/
|
*/
|
||||||
class StrategyPersistSelection extends StrategyAbstract {
|
class StrategyPersistSelection extends StrategyAbstract {
|
||||||
/**
|
/**
|
||||||
* el-table的selection-change事件不适用于开启跨页保存的情况。
|
* el-table 的 selection-change 事件不适用于开启跨页保存的情况。
|
||||||
* 比如,当开启persistSelection时,发生以下两个场景:
|
* 比如,当开启 persistSelection时,发生以下两个场景:
|
||||||
* 1. 用户点击翻页
|
* 1. 用户点击翻页
|
||||||
* 2. 用户点击行首的切换全选项按钮,清空当前页多选项数据
|
* 2. 用户点击行首的切换全选项按钮,清空当前页多选项数据
|
||||||
* 其中场景1应该保持selected不变;而场景2只应该从selected移除当前页所有行,保留其他页面的多选状态。
|
* 其中场景 1 应该保持 selected 不变;而场景 2 只应该从 selected 移除当前页所有行,保留其他页面的多选状态。
|
||||||
* 但el-table的selection-change事件在两个场景中无差别发生,所以这里不处理这个事件
|
* 但 el-table 的 selection-change 事件在两个场景中无差别发生,所以这里不处理这个事件
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -63,13 +65,19 @@ class StrategyPersistSelection extends StrategyAbstract {
|
|||||||
*/
|
*/
|
||||||
onSelect(selection, row) {
|
onSelect(selection, row) {
|
||||||
const isChosen = selection.indexOf(row) > -1
|
const isChosen = selection.indexOf(row) > -1
|
||||||
|
|
||||||
this.toggleRowSelection(row, isChosen)
|
this.toggleRowSelection(row, isChosen)
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* 用户切换当前页的多选
|
* 用户切换当前页的多选
|
||||||
*/
|
*/
|
||||||
onSelectAll(selection, selectable = () => true) {
|
onSelectAll(selection, selectable = () => true) {
|
||||||
const isSelected = !!selection.length
|
// 获取当前所有已选择的项
|
||||||
|
const selectedRows = this.elDataTable.data.filter(r => selection.includes(r))
|
||||||
|
|
||||||
|
// 判断是否已全选
|
||||||
|
const isSelected = this.elDataTable.data.every(r => selectable(r) && selectedRows.includes(r))
|
||||||
|
|
||||||
this.elDataTable.data.forEach(r => {
|
this.elDataTable.data.forEach(r => {
|
||||||
if (selectable(r)) {
|
if (selectable(r)) {
|
||||||
this.toggleRowSelection(r, isSelected)
|
this.toggleRowSelection(r, isSelected)
|
||||||
@@ -83,33 +91,42 @@ class StrategyPersistSelection extends StrategyAbstract {
|
|||||||
toggleRowSelection(row, isSelected) {
|
toggleRowSelection(row, isSelected) {
|
||||||
const { id, selected } = this.elDataTable
|
const { id, selected } = this.elDataTable
|
||||||
const foundIndex = selected.findIndex(r => r[id] === row[id])
|
const foundIndex = selected.findIndex(r => r[id] === row[id])
|
||||||
|
|
||||||
if (typeof isSelected === 'undefined') {
|
if (typeof isSelected === 'undefined') {
|
||||||
isSelected = foundIndex <= -1
|
isSelected = foundIndex <= -1
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isSelected && foundIndex === -1) {
|
if (isSelected && foundIndex === -1) {
|
||||||
selected.push(row)
|
selected.push(row)
|
||||||
} else if (!isSelected && foundIndex > -1) {
|
} else if (!isSelected && foundIndex > -1) {
|
||||||
selected.splice(foundIndex, 1)
|
selected.splice(foundIndex, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
this.elDataTable.$emit('toggle-row-selection', isSelected, row)
|
this.elDataTable.$emit('toggle-row-selection', isSelected, row)
|
||||||
this.updateElTableSelection()
|
this.updateElTableSelection()
|
||||||
}
|
}
|
||||||
|
|
||||||
clearSelection() {
|
clearSelection() {
|
||||||
this.elDataTable.selected = []
|
this.elDataTable.selected = []
|
||||||
this.updateElTableSelection()
|
this.updateElTableSelection()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 将selected状态同步到el-table中
|
* 将selected状态同步到el-table中
|
||||||
*/
|
*/
|
||||||
updateElTableSelection() {
|
updateElTableSelection() {
|
||||||
const { data, id, selected } = this.elDataTable
|
const { data, id, selected } = this.elDataTable
|
||||||
|
|
||||||
// 历史勾选的行已经不在当前页了,所以要将当前页的行数据和selected合并
|
// 历史勾选的行已经不在当前页了,所以要将当前页的行数据和selected合并
|
||||||
const mergeData = _.uniqWith([...data, ...selected], _.isEqual)
|
const mergeData = _.uniqWith([...data, ...selected], _.isEqual)
|
||||||
|
|
||||||
mergeData.forEach(r => {
|
mergeData.forEach(r => {
|
||||||
const isSelected = !!selected.find(r2 => r[id] === r2[id])
|
const isSelected = !!selected.find(r2 => r[id] === r2[id])
|
||||||
|
|
||||||
if (!this.elTable) {
|
if (!this.elTable) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
this.elTable.toggleRowSelection(r, isSelected)
|
this.elTable.toggleRowSelection(r, isSelected)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -153,6 +153,8 @@ export default {
|
|||||||
this.toggleRowSelection(row, true)
|
this.toggleRowSelection(row, true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.$emit('loaded')
|
||||||
},
|
},
|
||||||
handleSizeChange(val) {
|
handleSizeChange(val) {
|
||||||
localStorage.setItem('paginationSize', val)
|
localStorage.setItem('paginationSize', val)
|
||||||
|
|||||||
@@ -48,6 +48,7 @@
|
|||||||
import Dialog from '@/components/Dialog/index.vue'
|
import Dialog from '@/components/Dialog/index.vue'
|
||||||
import { createSourceIdCache } from '@/api/common'
|
import { createSourceIdCache } from '@/api/common'
|
||||||
import * as queryUtil from '@/components/Table/DataTable/compenents/el-data-table/utils/query'
|
import * as queryUtil from '@/components/Table/DataTable/compenents/el-data-table/utils/query'
|
||||||
|
import { download } from '@/utils/common'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'ExportDialog',
|
name: 'ExportDialog',
|
||||||
@@ -187,10 +188,7 @@ export default {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
downloadCsv(url) {
|
downloadCsv(url) {
|
||||||
const a = document.createElement('a')
|
download(url)
|
||||||
a.href = url
|
|
||||||
a.click()
|
|
||||||
window.URL.revokeObjectURL(url)
|
|
||||||
},
|
},
|
||||||
async defaultPerformExport(selectRows, exportOption, q, exportTypeOption) {
|
async defaultPerformExport(selectRows, exportOption, q, exportTypeOption) {
|
||||||
const url = (process.env.VUE_APP_ENV === 'production') ? (`${this.url}`) : (`${process.env.VUE_APP_BASE_API}${this.url}`)
|
const url = (process.env.VUE_APP_ENV === 'production') ? (`${this.url}`) : (`${process.env.VUE_APP_BASE_API}${this.url}`)
|
||||||
|
|||||||
@@ -68,7 +68,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import Dialog from '@/components/Dialog/index.vue'
|
import Dialog from '@/components/Dialog/index.vue'
|
||||||
import ImportTable from '@/components/Table/ListTable/TableAction/ImportTable.vue'
|
import ImportTable from '@/components/Table/ListTable/TableAction/ImportTable.vue'
|
||||||
import { getErrorResponseMsg } from '@/utils/common'
|
import { download, getErrorResponseMsg } from '@/utils/common'
|
||||||
import { createSourceIdCache } from '@/api/common'
|
import { createSourceIdCache } from '@/api/common'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@@ -221,10 +221,7 @@ export default {
|
|||||||
this.$message.success(msg)
|
this.$message.success(msg)
|
||||||
},
|
},
|
||||||
downloadCsv(url) {
|
downloadCsv(url) {
|
||||||
const a = document.createElement('a')
|
download(url)
|
||||||
a.href = url
|
|
||||||
a.click()
|
|
||||||
window.URL.revokeObjectURL(url)
|
|
||||||
},
|
},
|
||||||
async handleImportConfirm() {
|
async handleImportConfirm() {
|
||||||
await this.$refs['importTable'].performUpload()
|
await this.$refs['importTable'].performUpload()
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<el-row>
|
<el-row type="flex" align="center">
|
||||||
<el-col :md="8" :sm="24">
|
<el-col :md="8" :sm="24">
|
||||||
<div class="tableFilter">
|
<div class="tableFilter">
|
||||||
<el-radio-group v-model="importStatusFilter" size="small">
|
<el-radio-group v-model="importStatusFilter" size="small">
|
||||||
@@ -11,7 +11,7 @@
|
|||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</div>
|
</div>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :md="8" :sm="24" style="text-align: center">
|
<el-col :md="16" :sm="24" style="text-align: center; display: flex; align-items: center">
|
||||||
<span class="summary-item summary-total"> {{ $t('common.Total') }}: {{ totalCount }}</span>
|
<span class="summary-item summary-total"> {{ $t('common.Total') }}: {{ totalCount }}</span>
|
||||||
<span class="summary-item summary-success"> {{ $t('common.Success') }}: {{ successCount }}</span>
|
<span class="summary-item summary-success"> {{ $t('common.Success') }}: {{ successCount }}</span>
|
||||||
<span class="summary-item summary-failed"> {{ $t('common.Failed') }}: {{ failedCount }}</span>
|
<span class="summary-item summary-failed"> {{ $t('common.Failed') }}: {{ failedCount }}</span>
|
||||||
|
|||||||
@@ -122,6 +122,9 @@ export default {
|
|||||||
return this.hasLeftActions ? 'right' : 'left'
|
return this.hasLeftActions ? 'right' : 'left'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
created() {
|
||||||
|
this.$emit('done')
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
handleTagSearch(val) {
|
handleTagSearch(val) {
|
||||||
this.searchTable(val)
|
this.searchTable(val)
|
||||||
@@ -144,119 +147,121 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang='scss' scoped>
|
<style lang='scss' scoped>
|
||||||
.table-header {
|
.table-header {
|
||||||
/*display: flex;*/
|
/*display: flex;*/
|
||||||
/*flex-direction: row;*/
|
/*flex-direction: row;*/
|
||||||
/*justify-content: space-between;*/
|
/*justify-content: space-between;*/
|
||||||
}
|
}
|
||||||
|
|
||||||
.right-side-item {
|
.right-side-item {
|
||||||
}
|
}
|
||||||
|
|
||||||
.right-side-actions >>> .el-button {
|
.right-side-actions > > > .el-button {
|
||||||
border: none;
|
border: none;
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
width: 26px;
|
width: 26px;
|
||||||
height: 26px;
|
height: 26px;
|
||||||
color: #888;
|
color: #888;
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
.right-side-actions >>> .fa {
|
.right-side-actions > > > .fa {
|
||||||
height: 16px;
|
height: 16px;
|
||||||
width: 16px;
|
width: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.right-side-actions >>> .el-button:hover {
|
.right-side-actions > > > .el-button:hover {
|
||||||
background-color: rgb(0, 0, 0, 0.05);
|
background-color: rgb(0, 0, 0, 0.05);
|
||||||
}
|
}
|
||||||
|
|
||||||
.action-search >>> .el-input__suffix i {
|
.action-search > > > .el-input__suffix i {
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
color: #888;
|
color: #888;
|
||||||
}
|
}
|
||||||
|
|
||||||
.action-search >>> .el-cascader {
|
.action-search > > > .el-cascader {
|
||||||
line-height: 32px !important;
|
line-height: 32px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.right-side-actions {
|
.right-side-actions {
|
||||||
display: flex;
|
display: flex;
|
||||||
padding-left: 10px;
|
padding-left: 10px;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.table-action-right-side {
|
.table-action-right-side {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.export-item {
|
.export-item {
|
||||||
display: block;
|
display: block;
|
||||||
padding: 5px 20px;
|
padding: 5px 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.datepicker {
|
.datepicker {
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.table-header {
|
.table-header {
|
||||||
line-height: 32px;
|
line-height: 32px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.left-side {
|
.left-side {
|
||||||
float: left;
|
float: left;
|
||||||
display: block;
|
display: block;
|
||||||
&>>> .action-item.el-dropdown {
|
|
||||||
height: 33px;
|
& > > > .action-item.el-dropdown {
|
||||||
&> .el-button {
|
height: 33px;
|
||||||
height: 100%;
|
|
||||||
}
|
& > .el-button {
|
||||||
|
height: 100%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.right-side {
|
.right-side {
|
||||||
float: right;
|
float: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
.search {
|
.search {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mobile .search {
|
.mobile .search {
|
||||||
display: inherit;
|
display: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mobile .search .datepicker {
|
.mobile .search .datepicker {
|
||||||
margin-left: 0;
|
margin-left: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.search.left {
|
.search.left {
|
||||||
float: left;
|
float: left;
|
||||||
padding: 0 !important;
|
padding: 0 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.search.right {
|
.search.right {
|
||||||
float: right;
|
float: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mobile .search.right {
|
.mobile .search.right {
|
||||||
float: none;
|
float: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mobile .search.right .action-search {
|
.mobile .search.right .action-search {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mobile .right-side {
|
.mobile .right-side {
|
||||||
padding-top: 5px;
|
padding-top: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.filter-field.right-side-item.action-search {
|
.filter-field.right-side-item.action-search {
|
||||||
height: 34px;
|
height: 34px;
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -8,9 +8,11 @@
|
|||||||
:selected-rows="selectedRows"
|
:selected-rows="selectedRows"
|
||||||
:table-url="tableUrl"
|
:table-url="tableUrl"
|
||||||
v-bind="iHeaderActions"
|
v-bind="iHeaderActions"
|
||||||
|
@done="handleActionInitialDone"
|
||||||
/>
|
/>
|
||||||
<IBox class="table-content">
|
<IBox class="table-content">
|
||||||
<AutoDataTable
|
<AutoDataTable
|
||||||
|
v-if="actionInit"
|
||||||
ref="dataTable"
|
ref="dataTable"
|
||||||
:config="iTableConfig"
|
:config="iTableConfig"
|
||||||
:filter-table="filter"
|
:filter-table="filter"
|
||||||
@@ -73,7 +75,10 @@ export default {
|
|||||||
return {
|
return {
|
||||||
selectedRows: [],
|
selectedRows: [],
|
||||||
init: false,
|
init: false,
|
||||||
extraQuery: extraQuery
|
isDeactivated: false,
|
||||||
|
extraQuery: extraQuery,
|
||||||
|
actionInit: this.headerActions.has === false,
|
||||||
|
initQuery: {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@@ -166,14 +171,36 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
handleActionInitialDone() {
|
||||||
|
setTimeout(() => {
|
||||||
|
this.actionInit = true
|
||||||
|
}, 100)
|
||||||
|
},
|
||||||
handleSelectionChange(val) {
|
handleSelectionChange(val) {
|
||||||
this.selectedRows = val
|
this.selectedRows = val
|
||||||
},
|
},
|
||||||
reloadTable() {
|
reloadTable() {
|
||||||
this.dataTable.getList()
|
this.dataTable.getList()
|
||||||
},
|
},
|
||||||
|
updateInitQuery(attrs) {
|
||||||
|
if (!this.actionInit) {
|
||||||
|
this.initQuery = attrs
|
||||||
|
for (const key in attrs) {
|
||||||
|
this.$set(this.extraQuery, key, attrs[key])
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
const removeKeys = Object.keys(this.initQuery).filter(key => !attrs[key])
|
||||||
|
for (const key of removeKeys) {
|
||||||
|
this.$delete(this.extraQuery, key)
|
||||||
|
}
|
||||||
|
},
|
||||||
search(attrs) {
|
search(attrs) {
|
||||||
this.$log.debug('ListTable: search table', attrs)
|
this.$log.debug('ListTable: search table', attrs)
|
||||||
|
const init = this.updateInitQuery(attrs)
|
||||||
|
if (init) {
|
||||||
|
return
|
||||||
|
}
|
||||||
this.$emit('TagSearch', attrs)
|
this.$emit('TagSearch', attrs)
|
||||||
this.$refs.dataTable?.$refs.dataTable?.search(attrs, true)
|
this.$refs.dataTable?.$refs.dataTable?.search(attrs, true)
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<span>{{ value }}</span>
|
<span class="date">{{ dateValue }}</span>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@@ -10,24 +10,31 @@ export default {
|
|||||||
name: 'DateFormatter',
|
name: 'DateFormatter',
|
||||||
extends: BaseFormatter,
|
extends: BaseFormatter,
|
||||||
data() {
|
data() {
|
||||||
let value
|
// let value
|
||||||
if (this.cellValue) {
|
// if (this.cellValue) {
|
||||||
value = toSafeLocalDateStr(this.cellValue)
|
// value = toSafeLocalDateStr(this.cellValue)
|
||||||
} else {
|
// } else {
|
||||||
value = '-'
|
// value = '-'
|
||||||
}
|
// }
|
||||||
// const locale = this.$i18n.locale
|
// const locale = this.$i18n.locale
|
||||||
// const value = dt.toLocaleString(locale, { hourCycle: 'h23' })
|
// const value = dt.toLocaleString(locale, { hourCycle: 'h23' })
|
||||||
// debug(this.$i18n.locale)
|
// debug(this.$i18n.locale)
|
||||||
return {
|
// return {
|
||||||
value: value
|
// value: value
|
||||||
}
|
// }
|
||||||
// return {
|
// return {
|
||||||
// value: `${year}-${month}-${date} ${hour}:${minutes}:${seconds}`
|
// value: `${year}-${month}-${date} ${hour}:${minutes}:${seconds}`
|
||||||
// }
|
// }
|
||||||
|
return {}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
dateValue() {
|
||||||
|
if (this.cellValue) {
|
||||||
|
return toSafeLocalDateStr(this.cellValue)
|
||||||
|
} else {
|
||||||
|
return '-'
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style scoped>
|
|
||||||
|
|
||||||
</style>
|
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ export default {
|
|||||||
}
|
}
|
||||||
return text
|
return text
|
||||||
}
|
}
|
||||||
return '-'
|
return this.items?.distribution || '-'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,7 @@
|
|||||||
</a>
|
</a>
|
||||||
<a
|
<a
|
||||||
v-if="formatterArgs.showEditBtn"
|
v-if="formatterArgs.showEditBtn"
|
||||||
class="edit-btn"
|
:class="[{ 'disabled-link': this.$store.getters.currentOrgIsRoot },'edit-btn']"
|
||||||
style="padding-left: 5px"
|
style="padding-left: 5px"
|
||||||
@click="showDialog = true"
|
@click="showDialog = true"
|
||||||
>
|
>
|
||||||
@@ -269,4 +269,11 @@ export default {
|
|||||||
.tag-tip {
|
.tag-tip {
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.disabled-link {
|
||||||
|
pointer-events: none;
|
||||||
|
color: grey;
|
||||||
|
cursor: default;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ export default {
|
|||||||
showRenameBtn: false,
|
showRenameBtn: false,
|
||||||
drag: {
|
drag: {
|
||||||
isCopy: false,
|
isCopy: false,
|
||||||
isMove: false
|
isMove: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
callback: {
|
callback: {
|
||||||
|
|||||||
@@ -18,14 +18,15 @@
|
|||||||
/>
|
/>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col v-show="isShow" :span="span">
|
<el-col v-show="isShow" :span="span">
|
||||||
<VueMarkdown class="result-html" :source="iValue" :show="true" :html="false" />
|
<VueMarkdown class="result-html" :source="sanitizedValue" :html="false" :show="true" />
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
<VueMarkdown v-else class="source" :source="iValue" :html="false" />
|
<VueMarkdown v-else class="source" :html="false" :source="sanitizedValue" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import DOMPurify from 'dompurify'
|
||||||
import VueMarkdown from 'vue-markdown'
|
import VueMarkdown from 'vue-markdown'
|
||||||
import 'github-markdown-css/github-markdown-light.css'
|
import 'github-markdown-css/github-markdown-light.css'
|
||||||
|
|
||||||
@@ -56,6 +57,17 @@ export default {
|
|||||||
iValue: this.value
|
iValue: this.value
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
sanitizedValue() {
|
||||||
|
// 转义特殊字符
|
||||||
|
let content = this.iValue.replace(/\\/g, '\\\\').replace(/\$/g, '\\$')
|
||||||
|
|
||||||
|
// 使用 DOMPurify 进行 XSS 过滤
|
||||||
|
content = DOMPurify.sanitize(content)
|
||||||
|
|
||||||
|
return content
|
||||||
|
}
|
||||||
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.resizeObserver = new ResizeObserver(entries => {
|
this.resizeObserver = new ResizeObserver(entries => {
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ export default {
|
|||||||
fontFamily: 'monaco, Consolas, "Lucida Console", monospace',
|
fontFamily: 'monaco, Consolas, "Lucida Console", monospace',
|
||||||
lineHeight: 1.2,
|
lineHeight: 1.2,
|
||||||
fontSize: 13,
|
fontSize: 13,
|
||||||
|
scrollback: 9999999,
|
||||||
rightClickSelectsWord: true,
|
rightClickSelectsWord: true,
|
||||||
theme: {
|
theme: {
|
||||||
background: '#fff',
|
background: '#fff',
|
||||||
@@ -83,7 +84,7 @@ export default {
|
|||||||
callback: () => {
|
callback: () => {
|
||||||
this.xterm.selectAll()
|
this.xterm.selectAll()
|
||||||
const text = this.xterm.getSelection()
|
const text = this.xterm.getSelection()
|
||||||
const filename = `shortcut_cmd_${this.$route.query?.taskId}.log`
|
const filename = `${this.$route.query?.type}_${this.$route.query?.taskId}.log`
|
||||||
downloadText(text, filename)
|
downloadText(text, filename)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -721,6 +721,7 @@
|
|||||||
"BatchActivate": "Batch activate",
|
"BatchActivate": "Batch activate",
|
||||||
"SyncSelected": "Sync selected",
|
"SyncSelected": "Sync selected",
|
||||||
"bulkDeploy": "Bulk deploy",
|
"bulkDeploy": "Bulk deploy",
|
||||||
|
"BulkVerify": "Bulk verify",
|
||||||
"bulkDeleteErrorMsg": "Bulk delete failed: ",
|
"bulkDeleteErrorMsg": "Bulk delete failed: ",
|
||||||
"bulkDeleteSuccessMsg": "Bulk delete success",
|
"bulkDeleteSuccessMsg": "Bulk delete success",
|
||||||
"bulkRemoveErrorMsg": "Bulk remove failed: ",
|
"bulkRemoveErrorMsg": "Bulk remove failed: ",
|
||||||
@@ -1930,6 +1931,7 @@
|
|||||||
"CheckViewAcceptor": "View more acceptor",
|
"CheckViewAcceptor": "View more acceptor",
|
||||||
"Assignees": "Assignees",
|
"Assignees": "Assignees",
|
||||||
"Close": "Close",
|
"Close": "Close",
|
||||||
|
"CancelTicket": "Cancel Ticket",
|
||||||
"OpenStatus": "Open",
|
"OpenStatus": "Open",
|
||||||
"CloseStatus": "Close",
|
"CloseStatus": "Close",
|
||||||
"Comment": "Comment",
|
"Comment": "Comment",
|
||||||
@@ -2135,7 +2137,8 @@
|
|||||||
"passwordWillExpiredSuffixMsg": " days.Please change your password as soon as possible.",
|
"passwordWillExpiredSuffixMsg": " days.Please change your password as soon as possible.",
|
||||||
"dateLastLogin": "Date last login",
|
"dateLastLogin": "Date last login",
|
||||||
"AddAllMembersWarningMsg": "Are you sure you want to add all members?",
|
"AddAllMembersWarningMsg": "Are you sure you want to add all members?",
|
||||||
"disallowSelfUpdateFields": "Not allowed to modify the current fields oneself"
|
"disallowSelfUpdateFields": "Not allowed to modify the current fields oneself",
|
||||||
|
"GlobalDisableMfaMsg": "Global enforcement has been enabled"
|
||||||
},
|
},
|
||||||
"notifications": {
|
"notifications": {
|
||||||
"MessageType": "Message Type",
|
"MessageType": "Message Type",
|
||||||
@@ -2271,6 +2274,8 @@
|
|||||||
"HostnameStrategy": "Used to produce the asset hostname. For example, 1. Instance name (instanceDemo);2. Instance name and Partial IP (instanceDemo-250.1)",
|
"HostnameStrategy": "Used to produce the asset hostname. For example, 1. Instance name (instanceDemo);2. Instance name and Partial IP (instanceDemo-250.1)",
|
||||||
"IsAlwaysUpdate": "Keep assets up to date",
|
"IsAlwaysUpdate": "Keep assets up to date",
|
||||||
"FullySynchronous": "Assets fully synchronized",
|
"FullySynchronous": "Assets fully synchronized",
|
||||||
|
"ReleaseAssets": "Release assets",
|
||||||
|
"ReleaseAssetsHelpTips": "Whether to automatically delete assets synchronized through this task and released on the cloud at the end of the task",
|
||||||
"AccountCreate": "Create account",
|
"AccountCreate": "Create account",
|
||||||
"AccountList": "Account list",
|
"AccountList": "Account list",
|
||||||
"AccountUpdate": "Update account",
|
"AccountUpdate": "Update account",
|
||||||
|
|||||||
@@ -717,6 +717,7 @@
|
|||||||
"SyncSuccessMsg": "同期に成功しました",
|
"SyncSuccessMsg": "同期に成功しました",
|
||||||
"SyncSelected": "選択した同期",
|
"SyncSelected": "選択した同期",
|
||||||
"bulkDeploy": "一括デプロイ",
|
"bulkDeploy": "一括デプロイ",
|
||||||
|
"BulkVerify": "一括テスト",
|
||||||
"bulkSyncErrorMsg": "一括同期に失敗しました:",
|
"bulkSyncErrorMsg": "一括同期に失敗しました:",
|
||||||
"bulkDeleteErrorMsg": "一括削除に失敗しました:",
|
"bulkDeleteErrorMsg": "一括削除に失敗しました:",
|
||||||
"bulkDeleteSuccessMsg": "一括削除に成功しました",
|
"bulkDeleteSuccessMsg": "一括削除に成功しました",
|
||||||
@@ -1926,6 +1927,7 @@
|
|||||||
"Assignee": "処理者",
|
"Assignee": "処理者",
|
||||||
"Assignees": "処理待ち",
|
"Assignees": "処理待ち",
|
||||||
"Close": "閉じる",
|
"Close": "閉じる",
|
||||||
|
"CancelTicket": "作業指示をキャンセルする",
|
||||||
"OpenStatus": "オン",
|
"OpenStatus": "オン",
|
||||||
"CloseStatus": "閉じる",
|
"CloseStatus": "閉じる",
|
||||||
"Comment": "備考",
|
"Comment": "備考",
|
||||||
@@ -2124,7 +2126,8 @@
|
|||||||
"passwordWillExpiredPrefixMsg": "パスワードはまもなく",
|
"passwordWillExpiredPrefixMsg": "パスワードはまもなく",
|
||||||
"passwordWillExpiredSuffixMsg": "期限が切れた後、できるだけ早くパスワードを変更してください。",
|
"passwordWillExpiredSuffixMsg": "期限が切れた後、できるだけ早くパスワードを変更してください。",
|
||||||
"AddAllMembersWarningMsg": "すべてのメンバーを追加してもよろしいですか?",
|
"AddAllMembersWarningMsg": "すべてのメンバーを追加してもよろしいですか?",
|
||||||
"disallowSelfUpdateFields": "現在のフィールドを自分で変更することは許可されていません"
|
"disallowSelfUpdateFields": "現在のフィールドを自分で変更することは許可されていません",
|
||||||
|
"GlobalDisableMfaMsg": "グローバルでの強制が有効になっています"
|
||||||
},
|
},
|
||||||
"notifications": {
|
"notifications": {
|
||||||
"MessageType": "メッセージタイプ",
|
"MessageType": "メッセージタイプ",
|
||||||
@@ -2267,6 +2270,8 @@
|
|||||||
"HostnameStrategy": "資産を生成するためにホスト名。例: 1. インスタンス名 (instanceDemo) 2.インスタンス名と一部IP (下位2桁) (instanceDemo-250.1)",
|
"HostnameStrategy": "資産を生成するためにホスト名。例: 1. インスタンス名 (instanceDemo) 2.インスタンス名と一部IP (下位2桁) (instanceDemo-250.1)",
|
||||||
"IsAlwaysUpdate": "資産は常に最新です",
|
"IsAlwaysUpdate": "資産は常に最新です",
|
||||||
"FullySynchronous": "資産完全にシンクロします",
|
"FullySynchronous": "資産完全にシンクロします",
|
||||||
|
"ReleaseAssets": "資産の同期解放",
|
||||||
|
"ReleaseAssetsHelpTips": "タスクの終了時に、このタスクを介して同期され、クラウド上で解放された資産を自動的に削除するかどうか",
|
||||||
"AccountCreate": "アカウントの作成",
|
"AccountCreate": "アカウントの作成",
|
||||||
"AccountList": "アカウントリスト",
|
"AccountList": "アカウントリスト",
|
||||||
"AccountUpdate": "アカウントの更新",
|
"AccountUpdate": "アカウントの更新",
|
||||||
@@ -2425,4 +2430,4 @@
|
|||||||
"BindResource": "リソースを関連付ける",
|
"BindResource": "リソースを関連付ける",
|
||||||
"SelectResource": "リソースを選択"
|
"SelectResource": "リソースを選択"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -771,6 +771,7 @@
|
|||||||
"BatchActivate": "批量激活",
|
"BatchActivate": "批量激活",
|
||||||
"SyncSelected": "同步所选",
|
"SyncSelected": "同步所选",
|
||||||
"bulkDeploy": "批量部署",
|
"bulkDeploy": "批量部署",
|
||||||
|
"BulkVerify": "批量测试",
|
||||||
"bulkDeleteErrorMsg": "批量删除失败: ",
|
"bulkDeleteErrorMsg": "批量删除失败: ",
|
||||||
"bulkDeleteSuccessMsg": "批量删除成功",
|
"bulkDeleteSuccessMsg": "批量删除成功",
|
||||||
"bulkRemoveErrorMsg": "批量移除失败: ",
|
"bulkRemoveErrorMsg": "批量移除失败: ",
|
||||||
@@ -1912,6 +1913,7 @@
|
|||||||
"Assignee": "处理人",
|
"Assignee": "处理人",
|
||||||
"Assignees": "待处理人",
|
"Assignees": "待处理人",
|
||||||
"Close": "关闭",
|
"Close": "关闭",
|
||||||
|
"CancelTicket": "取消工单",
|
||||||
"OpenStatus": "审批中",
|
"OpenStatus": "审批中",
|
||||||
"CloseStatus": "已完成",
|
"CloseStatus": "已完成",
|
||||||
"Comment": "备注",
|
"Comment": "备注",
|
||||||
@@ -2115,7 +2117,8 @@
|
|||||||
"passwordExpired": "密码过期了",
|
"passwordExpired": "密码过期了",
|
||||||
"passwordWillExpiredPrefixMsg": "密码即将在 ",
|
"passwordWillExpiredPrefixMsg": "密码即将在 ",
|
||||||
"passwordWillExpiredSuffixMsg": "天 后过期,请尽快修改您的密码。",
|
"passwordWillExpiredSuffixMsg": "天 后过期,请尽快修改您的密码。",
|
||||||
"disallowSelfUpdateFields": "不允许自己修改当前字段"
|
"disallowSelfUpdateFields": "不允许自己修改当前字段",
|
||||||
|
"GlobalDisableMfaMsg": "全局已强制开启"
|
||||||
},
|
},
|
||||||
"notifications": {
|
"notifications": {
|
||||||
"MessageType": "消息类型",
|
"MessageType": "消息类型",
|
||||||
@@ -2186,6 +2189,8 @@
|
|||||||
"HostnameStrategy": "用于生成资产主机名。例如:1. 实例名称 (instanceDemo);2. 实例名称和部分IP(后两位) (instanceDemo-250.1)",
|
"HostnameStrategy": "用于生成资产主机名。例如:1. 实例名称 (instanceDemo);2. 实例名称和部分IP(后两位) (instanceDemo-250.1)",
|
||||||
"IsAlwaysUpdate": "资产保持最新",
|
"IsAlwaysUpdate": "资产保持最新",
|
||||||
"FullySynchronous": "资产完全同步",
|
"FullySynchronous": "资产完全同步",
|
||||||
|
"ReleaseAssets": "同步释放资产",
|
||||||
|
"ReleaseAssetsHelpTips": "是否在任务结束时,自动删除通过此任务同步下来且已经在云上释放的资产",
|
||||||
"AccountCreate": "创建账户",
|
"AccountCreate": "创建账户",
|
||||||
"AccountList": "云账号",
|
"AccountList": "云账号",
|
||||||
"AccountUpdate": "更新账户",
|
"AccountUpdate": "更新账户",
|
||||||
|
|||||||
@@ -771,6 +771,7 @@
|
|||||||
"BatchActivate": "批次啟用",
|
"BatchActivate": "批次啟用",
|
||||||
"SyncSelected": "同步所選",
|
"SyncSelected": "同步所選",
|
||||||
"bulkDeploy": "批次部署",
|
"bulkDeploy": "批次部署",
|
||||||
|
"BulkVerify": "批次測試",
|
||||||
"bulkDeleteErrorMsg": "批次刪除失敗: ",
|
"bulkDeleteErrorMsg": "批次刪除失敗: ",
|
||||||
"bulkDeleteSuccessMsg": "批次刪除成功",
|
"bulkDeleteSuccessMsg": "批次刪除成功",
|
||||||
"bulkRemoveErrorMsg": "批次移除失敗: ",
|
"bulkRemoveErrorMsg": "批次移除失敗: ",
|
||||||
@@ -1912,6 +1913,7 @@
|
|||||||
"Assignee": "處理人",
|
"Assignee": "處理人",
|
||||||
"Assignees": "待處理人",
|
"Assignees": "待處理人",
|
||||||
"Close": "關閉",
|
"Close": "關閉",
|
||||||
|
"CancelTicket": "取消工單",
|
||||||
"OpenStatus": "審批中",
|
"OpenStatus": "審批中",
|
||||||
"CloseStatus": "已完成",
|
"CloseStatus": "已完成",
|
||||||
"Comment": "備註",
|
"Comment": "備註",
|
||||||
|
|||||||
@@ -61,7 +61,6 @@ export default {
|
|||||||
break
|
break
|
||||||
case 'logout':
|
case 'logout':
|
||||||
this.logout()
|
this.logout()
|
||||||
window.location.href = `${process.env.VUE_APP_LOGOUT_PATH}?next=${this.$route.fullPath}`
|
|
||||||
break
|
break
|
||||||
case 'apiKey':
|
case 'apiKey':
|
||||||
this.$router.push('/profile/api-keys')
|
this.$router.push('/profile/api-keys')
|
||||||
@@ -73,7 +72,12 @@ export default {
|
|||||||
this.$router.push('/profile/user/setting')
|
this.$router.push('/profile/user/setting')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
logout() {
|
async logout() {
|
||||||
|
const currentOrg = this.$store.getters.currentOrg
|
||||||
|
if (currentOrg.autoEnter) {
|
||||||
|
await this.$store.dispatch('users/setCurrentOrg', this.$store.getters.preOrg)
|
||||||
|
}
|
||||||
|
window.location.href = `${process.env.VUE_APP_LOGOUT_PATH}?next=${this.$route.fullPath}`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
import { getProfile as apiGetProfile, logout } from '@/api/users'
|
import { getProfile as apiGetProfile, logout } from '@/api/users'
|
||||||
import { getCurrentOrgLocal, getPreOrgLocal, getTokenFromCookie, saveCurrentOrgLocal, setPreOrgLocal } from '@/utils/auth'
|
import {
|
||||||
|
getCurrentOrgLocal, getPreOrgLocal, getTokenFromCookie, saveCurrentOrgLocal, setPreOrgLocal
|
||||||
|
} from '@/utils/auth'
|
||||||
import orgUtil from '@/utils/org'
|
import orgUtil from '@/utils/org'
|
||||||
import { resetRouter } from '@/router'
|
import { resetRouter } from '@/router'
|
||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
@@ -70,7 +72,7 @@ const mutations = {
|
|||||||
},
|
},
|
||||||
SET_CURRENT_ORG(state, org) {
|
SET_CURRENT_ORG(state, org) {
|
||||||
// 系统组织和全局组织不设置成 Pre org
|
// 系统组织和全局组织不设置成 Pre org
|
||||||
if (!state.currentOrg?.autoEnter) {
|
if (!state.currentOrg?.autoEnter && !state.currentOrg?.is_root) {
|
||||||
state.preOrg = state.currentOrg
|
state.preOrg = state.currentOrg
|
||||||
setPreOrgLocal(state.username, state.currentOrg)
|
setPreOrgLocal(state.username, state.currentOrg)
|
||||||
}
|
}
|
||||||
@@ -142,7 +144,7 @@ const actions = {
|
|||||||
const systemOrg = {
|
const systemOrg = {
|
||||||
id: orgUtil.SYSTEM_ORG_ID,
|
id: orgUtil.SYSTEM_ORG_ID,
|
||||||
name: 'SystemSetting',
|
name: 'SystemSetting',
|
||||||
autoEnter: true
|
autoEnter: new Date().getTime()
|
||||||
}
|
}
|
||||||
commit('SET_CURRENT_ORG', systemOrg)
|
commit('SET_CURRENT_ORG', systemOrg)
|
||||||
},
|
},
|
||||||
@@ -157,7 +159,8 @@ const actions = {
|
|||||||
const globalOrg = {
|
const globalOrg = {
|
||||||
id: orgUtil.GLOBAL_ORG_ID,
|
id: orgUtil.GLOBAL_ORG_ID,
|
||||||
name: 'Global',
|
name: 'Global',
|
||||||
autoEnter: true
|
is_root: true,
|
||||||
|
autoEnter: new Date().getTime()
|
||||||
}
|
}
|
||||||
commit('SET_CURRENT_ORG', globalOrg)
|
commit('SET_CURRENT_ORG', globalOrg)
|
||||||
},
|
},
|
||||||
|
|||||||
BIN
src/styles/icons/dameng.png
Normal file
BIN
src/styles/icons/dameng.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.0 KiB |
@@ -92,6 +92,10 @@
|
|||||||
background: url('./icons/db2.png') no-repeat center left transparent;
|
background: url('./icons/db2.png') no-repeat center left transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.dameng_ico_docu {
|
||||||
|
background: url('./icons/dameng.png') no-repeat center left transparent;
|
||||||
|
}
|
||||||
|
|
||||||
&.private_ico_docu {
|
&.private_ico_docu {
|
||||||
background: url('./icons/private.png') no-repeat center left transparent;
|
background: url('./icons/private.png') no-repeat center left transparent;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -363,13 +363,19 @@ export function downloadText(content, filename) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function download(downloadUrl, filename) {
|
export function download(downloadUrl, filename) {
|
||||||
|
const iframe = document.createElement('iframe')
|
||||||
|
iframe.style.display = 'none'
|
||||||
|
document.body.appendChild(iframe)
|
||||||
const a = document.createElement('a')
|
const a = document.createElement('a')
|
||||||
a.href = downloadUrl
|
a.href = downloadUrl
|
||||||
if (filename) {
|
if (filename) {
|
||||||
a.download = filename
|
a.download = filename
|
||||||
}
|
}
|
||||||
|
iframe.contentWindow.document.body.appendChild(a)
|
||||||
a.click()
|
a.click()
|
||||||
window.URL.revokeObjectURL(downloadUrl)
|
setTimeout(() => {
|
||||||
|
document.body.removeChild(iframe)
|
||||||
|
}, 1000 * 60 * 30) // If you can't download it in half an hour, don't download it.
|
||||||
}
|
}
|
||||||
|
|
||||||
export function diffObject(object, base) {
|
export function diffObject(object, base) {
|
||||||
|
|||||||
@@ -8,6 +8,11 @@ export const GLOBAL_ORG_ID = '00000000-0000-0000-0000-000000000000'
|
|||||||
|
|
||||||
function getPropOrg() {
|
function getPropOrg() {
|
||||||
const orgs = store.getters.usingOrgs
|
const orgs = store.getters.usingOrgs
|
||||||
|
const preOrg = store.getters.preOrg || {}
|
||||||
|
const preFound = orgs.find((item) => item.id === preOrg.id)
|
||||||
|
if (preFound) {
|
||||||
|
return preFound
|
||||||
|
}
|
||||||
const defaultOrg = orgs.find((item) => item.is_default)
|
const defaultOrg = orgs.find((item) => item.is_default)
|
||||||
if (defaultOrg) {
|
if (defaultOrg) {
|
||||||
return defaultOrg
|
return defaultOrg
|
||||||
@@ -62,7 +67,7 @@ async function changeOrg(org, reload = true, vm = null) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
location.hash = '#' + path
|
location.hash = '#' + path
|
||||||
setTimeout(() => location.reload(), 400)
|
setTimeout(() => location.reload(), 500)
|
||||||
}
|
}
|
||||||
|
|
||||||
function hasCurrentOrgPermission() {
|
function hasCurrentOrgPermission() {
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import orgs from '@/api/orgs'
|
|||||||
import { getPropView, isViewHasOrgs } from '@/utils/jms'
|
import { getPropView, isViewHasOrgs } from '@/utils/jms'
|
||||||
|
|
||||||
const whiteList = ['/login', process.env.VUE_APP_LOGIN_PATH] // no redirect whitelist
|
const whiteList = ['/login', process.env.VUE_APP_LOGIN_PATH] // no redirect whitelist
|
||||||
|
const autoEnterOrgs = ['00000000-0000-0000-0000-000000000001', '00000000-0000-0000-0000-000000000000']
|
||||||
|
|
||||||
function reject(msg) {
|
function reject(msg) {
|
||||||
return new Promise((resolve, reject) => reject(msg))
|
return new Promise((resolve, reject) => reject(msg))
|
||||||
@@ -23,6 +24,9 @@ async function checkLogin({ to, from, next }) {
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
Vue.$log.error(e)
|
Vue.$log.error(e)
|
||||||
const status = e.response.status
|
const status = e.response.status
|
||||||
|
if (store.getters.currentOrg.autoEnter) {
|
||||||
|
await store.dispatch('users/setCurrentOrg', store.getters.preOrg)
|
||||||
|
}
|
||||||
if (status === 401 || status === 403) {
|
if (status === 401 || status === 403) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
window.location = process.env.VUE_APP_LOGIN_PATH
|
window.location = process.env.VUE_APP_LOGIN_PATH
|
||||||
@@ -42,6 +46,10 @@ async function getPublicSetting({ to, from, next }, isOpen) {
|
|||||||
|
|
||||||
async function refreshCurrentOrg() {
|
async function refreshCurrentOrg() {
|
||||||
return orgs.getCurrentOrg().then(org => {
|
return orgs.getCurrentOrg().then(org => {
|
||||||
|
// Root 就不刷新本地的了, 会影响 autoEnter
|
||||||
|
if (autoEnterOrgs.indexOf(org.id) !== -1) {
|
||||||
|
return
|
||||||
|
}
|
||||||
store.dispatch('users/setCurrentOrg', org)
|
store.dispatch('users/setCurrentOrg', org)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -60,9 +68,16 @@ async function changeCurrentOrgIfNeed({ to, from, next }) {
|
|||||||
Vue.$log.error('Current org is null or not a object: ', currentOrg)
|
Vue.$log.error('Current org is null or not a object: ', currentOrg)
|
||||||
await orgUtil.change2PropOrg({ to, from, next })
|
await orgUtil.change2PropOrg({ to, from, next })
|
||||||
}
|
}
|
||||||
if (currentOrg.name === 'SystemSetting') {
|
const globalOrgPath = [
|
||||||
const preOrg = store.getters.preOrg
|
'/console/perms/login-acls/', '/console/users/roles/',
|
||||||
await orgUtil.changeOrg(preOrg)
|
'/console/perms/connect-method-acls/', '/settings/'
|
||||||
|
]
|
||||||
|
if (autoEnterOrgs.indexOf(currentOrg.id) !== -1 && currentOrg.autoEnter) {
|
||||||
|
const delta = new Date().getTime() - currentOrg.autoEnter
|
||||||
|
const notNeedChange = globalOrgPath.find(path => to.path.indexOf(path) === 0)
|
||||||
|
if (!notNeedChange && delta > 3000) {
|
||||||
|
await orgUtil.change2PropOrg({ to, from, next })
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (!orgUtil.hasCurrentOrgPermission()) {
|
if (!orgUtil.hasCurrentOrgPermission()) {
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
:account="account"
|
:account="account"
|
||||||
:show-password-record="false"
|
:show-password-record="false"
|
||||||
:url="secretUrl"
|
:url="secretUrl"
|
||||||
|
type="template"
|
||||||
:visible.sync="showViewSecretDialog"
|
:visible.sync="showViewSecretDialog"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -31,7 +32,7 @@ export default {
|
|||||||
tableConfig: {
|
tableConfig: {
|
||||||
url: '/api/v1/accounts/account-templates/',
|
url: '/api/v1/accounts/account-templates/',
|
||||||
columns: null,
|
columns: null,
|
||||||
columnsExclude: ['spec_info'],
|
columnsExclude: ['spec_info', 'password_rules', 'push_params'],
|
||||||
columnsShow: {
|
columnsShow: {
|
||||||
min: ['name', 'actions'],
|
min: ['name', 'actions'],
|
||||||
default: ['name', 'username', 'secret_type', 'has_secret', 'privileged', 'actions']
|
default: ['name', 'username', 'secret_type', 'has_secret', 'privileged', 'actions']
|
||||||
|
|||||||
@@ -221,8 +221,7 @@ export default {
|
|||||||
url: `/api/v1/assets/assets/${this.object.id}/`,
|
url: `/api/v1/assets/assets/${this.object.id}/`,
|
||||||
object: this.object,
|
object: this.object,
|
||||||
nested: 'spec_info',
|
nested: 'spec_info',
|
||||||
showUndefine: true,
|
showUndefine: true
|
||||||
excludes: ['script']
|
|
||||||
},
|
},
|
||||||
customInfoConfig: {
|
customInfoConfig: {
|
||||||
title: this.$t('common.CustomInfo'),
|
title: this.$t('common.CustomInfo'),
|
||||||
|
|||||||
@@ -222,6 +222,30 @@ export default {
|
|||||||
getUrlQuery: false
|
getUrlQuery: false
|
||||||
},
|
},
|
||||||
extraMoreActions: [
|
extraMoreActions: [
|
||||||
|
{
|
||||||
|
name: 'BulkVerify',
|
||||||
|
title: this.$t('common.BulkVerify'),
|
||||||
|
type: 'primary',
|
||||||
|
icon: 'fa fa-link',
|
||||||
|
can: ({ selectedRows }) =>
|
||||||
|
this.$hasPerm('assets.test_assetconnectivity') &&
|
||||||
|
!this.$store.getters.currentOrgIsRoot &&
|
||||||
|
selectedRows.length > 0 &&
|
||||||
|
selectedRows[0].auto_config?.ansible_enabled &&
|
||||||
|
selectedRows[0].auto_config?.ping_enabled,
|
||||||
|
callback: function({ selectedRows }) {
|
||||||
|
const ids = selectedRows.map(v => {
|
||||||
|
return v.id
|
||||||
|
})
|
||||||
|
this.$axios.post(
|
||||||
|
'/api/v1/assets/assets/tasks/',
|
||||||
|
{ action: 'test', assets: ids }).then(res => {
|
||||||
|
openTaskPage(res['task'])
|
||||||
|
}).catch(err => {
|
||||||
|
this.$message.error(this.$tc('common.bulkVerifyErrorMsg' + ' ' + err))
|
||||||
|
})
|
||||||
|
}.bind(this)
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'DeactiveSelected',
|
name: 'DeactiveSelected',
|
||||||
title: this.$t('common.BatchDisable'),
|
title: this.$t('common.BatchDisable'),
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ export default {
|
|||||||
[this.$t('xpack.Cloud.CloudSource'), ['account', 'regions']],
|
[this.$t('xpack.Cloud.CloudSource'), ['account', 'regions']],
|
||||||
[this.$t('xpack.Cloud.SaveSetting'), [
|
[this.$t('xpack.Cloud.SaveSetting'), [
|
||||||
'hostname_strategy', 'ip_network_segment_group',
|
'hostname_strategy', 'ip_network_segment_group',
|
||||||
'sync_ip_type', 'is_always_update', 'fully_synchronous'
|
'sync_ip_type', 'is_always_update', 'fully_synchronous', 'release_assets'
|
||||||
]],
|
]],
|
||||||
[this.$t('xpack.Cloud.SyncStrategy'), ['strategy']],
|
[this.$t('xpack.Cloud.SyncStrategy'), ['strategy']],
|
||||||
[this.$t('xpack.Timer'), ['is_periodic', 'crontab', 'interval']],
|
[this.$t('xpack.Timer'), ['is_periodic', 'crontab', 'interval']],
|
||||||
@@ -68,6 +68,11 @@ export default {
|
|||||||
label: this.$t('xpack.Cloud.FullySynchronous'),
|
label: this.$t('xpack.Cloud.FullySynchronous'),
|
||||||
helpTips: this.$t('xpack.Cloud.FullySynchronousHelpTips')
|
helpTips: this.$t('xpack.Cloud.FullySynchronousHelpTips')
|
||||||
},
|
},
|
||||||
|
release_assets: {
|
||||||
|
type: 'switch',
|
||||||
|
label: this.$t('xpack.Cloud.ReleaseAssets'),
|
||||||
|
helpTips: this.$t('xpack.Cloud.ReleaseAssetsHelpTips')
|
||||||
|
},
|
||||||
regions: {
|
regions: {
|
||||||
component: Select2,
|
component: Select2,
|
||||||
el: {
|
el: {
|
||||||
|
|||||||
@@ -10,13 +10,11 @@
|
|||||||
@click="onSetting"
|
@click="onSetting"
|
||||||
/>
|
/>
|
||||||
<Dialog
|
<Dialog
|
||||||
v-if="isVisible"
|
|
||||||
width="60%"
|
width="60%"
|
||||||
:visible.sync="isVisible"
|
:visible.sync="isVisible"
|
||||||
:title="title"
|
:title="title"
|
||||||
:show-cancel="false"
|
:show-cancel="false"
|
||||||
:show-confirm="false"
|
:show-confirm="false"
|
||||||
:destroy-on-close="true"
|
|
||||||
@close="onDialogClose"
|
@close="onDialogClose"
|
||||||
>
|
>
|
||||||
<AutoDataForm
|
<AutoDataForm
|
||||||
@@ -34,7 +32,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import Dialog from '../../../components/Dialog'
|
import Dialog from '../../../components/Dialog'
|
||||||
import AutoDataForm from '../../../components/Form/AutoDataForm'
|
import AutoDataForm from '../../../components/Form/AutoDataForm'
|
||||||
import { DynamicInput } from '../../../components/Form/FormFields'
|
import { DynamicInput, Switcher } from '../../../components/Form/FormFields'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
@@ -147,6 +145,9 @@ export default {
|
|||||||
case 'list':
|
case 'list':
|
||||||
component = DynamicInput
|
component = DynamicInput
|
||||||
break
|
break
|
||||||
|
case 'boolean':
|
||||||
|
component = Switcher
|
||||||
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
if (param) {
|
if (param) {
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ export default {
|
|||||||
this.data.total_count_job_logs = data?.total_count_job_logs
|
this.data.total_count_job_logs = data?.total_count_job_logs
|
||||||
this.data.total_count_job_logs_running = data?.total_count_job_logs_running
|
this.data.total_count_job_logs_running = data?.total_count_job_logs_running
|
||||||
this.data.total_count_job_logs_failed = data?.total_count_job_logs_failed
|
this.data.total_count_job_logs_failed = data?.total_count_job_logs_failed
|
||||||
if (totalCountSession.length > 1) {
|
if (totalCountSession.length > 0) {
|
||||||
this.chartConfig.secondaryData = totalCountSession
|
this.chartConfig.secondaryData = totalCountSession
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,8 +16,7 @@ export default {
|
|||||||
Title,
|
Title,
|
||||||
LineChart
|
LineChart
|
||||||
},
|
},
|
||||||
props: {
|
props: {},
|
||||||
},
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
loading: false,
|
loading: false,
|
||||||
@@ -48,10 +47,10 @@ export default {
|
|||||||
const activeUsers = data?.dates_metrics_total_count_active_users
|
const activeUsers = data?.dates_metrics_total_count_active_users
|
||||||
const activeAssets = data?.dates_metrics_total_count_active_assets
|
const activeAssets = data?.dates_metrics_total_count_active_assets
|
||||||
this.lineChartConfig.datesMetrics = data.dates_metrics_date
|
this.lineChartConfig.datesMetrics = data.dates_metrics_date
|
||||||
if (activeUsers.length > 1) {
|
if (activeUsers.length > 0) {
|
||||||
this.lineChartConfig.primaryData = activeUsers
|
this.lineChartConfig.primaryData = activeUsers
|
||||||
}
|
}
|
||||||
if (activeAssets.length > 1) {
|
if (activeAssets.length > 0) {
|
||||||
this.lineChartConfig.secondaryData = activeAssets
|
this.lineChartConfig.secondaryData = activeAssets
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -64,6 +63,7 @@ export default {
|
|||||||
margin-top: 16px;
|
margin-top: 16px;
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
|
|
||||||
.head {
|
.head {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
|||||||
@@ -128,7 +128,8 @@ export default {
|
|||||||
tip += current.label + ':' + current.total + '<br/>'
|
tip += current.label + ':' + current.total + '<br/>'
|
||||||
}
|
}
|
||||||
return tip
|
return tip
|
||||||
}
|
},
|
||||||
|
appendToBody: true
|
||||||
},
|
},
|
||||||
grid: {
|
grid: {
|
||||||
top: '60%',
|
top: '60%',
|
||||||
|
|||||||
@@ -66,7 +66,16 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async getResourcesCount() {
|
async getResourcesCount() {
|
||||||
return this.$axios.get('/api/v1/index/?total_count=1')
|
return this.$axios.get(
|
||||||
|
'/api/v1/index/',
|
||||||
|
{
|
||||||
|
params: {
|
||||||
|
total_count_online_sessions: 1,
|
||||||
|
total_count_online_users: 1,
|
||||||
|
total_count_today_failed_sessions: 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -119,7 +119,7 @@
|
|||||||
import { TreeTable } from '@/components'
|
import { TreeTable } from '@/components'
|
||||||
import Term from '@/components/Widgets/Term'
|
import Term from '@/components/Widgets/Term'
|
||||||
import Page from '@/layout/components/Page'
|
import Page from '@/layout/components/Page'
|
||||||
import { createJob, getJob, getTaskDetail, JobUploadFile } from '@/api/ops'
|
import { createJob, getTaskDetail, JobUploadFile } from '@/api/ops'
|
||||||
import { formatFileSize } from '@/utils/common'
|
import { formatFileSize } from '@/utils/common'
|
||||||
import store from '@/store'
|
import store from '@/store'
|
||||||
|
|
||||||
@@ -230,28 +230,9 @@ export default {
|
|||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.enableWS()
|
this.enableWS()
|
||||||
this.initData()
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
formatFileSize,
|
formatFileSize,
|
||||||
async initData() {
|
|
||||||
this.recoverStatus()
|
|
||||||
},
|
|
||||||
recoverStatus() {
|
|
||||||
if (this.$route.query.taskId) {
|
|
||||||
this.currentTaskId = this.$route.query.taskId
|
|
||||||
getTaskDetail(this.currentTaskId).then(data => {
|
|
||||||
getJob(data.job_id).then(res => {
|
|
||||||
this.runAsInput.value = res.runas
|
|
||||||
this.runAsInput.callback(res.runas)
|
|
||||||
this.executionInfo.status = data['status']
|
|
||||||
this.executionInfo.timeCost = data['time_cost']
|
|
||||||
this.setCostTimeInterval()
|
|
||||||
this.writeExecutionOutput()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
},
|
|
||||||
enableWS() {
|
enableWS() {
|
||||||
const scheme = document.location.protocol === 'https:' ? 'wss' : 'ws'
|
const scheme = document.location.protocol === 'https:' ? 'wss' : 'ws'
|
||||||
const port = document.location.port ? ':' + document.location.port : ''
|
const port = document.location.port ? ':' + document.location.port : ''
|
||||||
@@ -281,7 +262,7 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
taskStatusStat(summary) {
|
taskStatusStat(summary) {
|
||||||
const { ok, failures, dark, excludes, skipped } = summary
|
const { ok = [], failures = [], dark = [], excludes = [], skipped = [] } = summary
|
||||||
|
|
||||||
const failedKeys = Object.keys(failures)
|
const failedKeys = Object.keys(failures)
|
||||||
const darkKeys = Object.keys(dark)
|
const darkKeys = Object.keys(dark)
|
||||||
@@ -439,6 +420,7 @@ export default {
|
|||||||
this.executionInfo.timeCost = 0
|
this.executionInfo.timeCost = 0
|
||||||
this.executionInfo.status = 'running'
|
this.executionInfo.status = 'running'
|
||||||
this.currentTaskId = res.task_id
|
this.currentTaskId = res.task_id
|
||||||
|
this.$router.replace({ query: { taskId: this.currentTaskId, type: 'file_upload' }})
|
||||||
this.setCostTimeInterval()
|
this.setCostTimeInterval()
|
||||||
this.writeExecutionOutput()
|
this.writeExecutionOutput()
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
|
|||||||
@@ -98,6 +98,7 @@ export default {
|
|||||||
el: {
|
el: {
|
||||||
baseUrl: '/api/v1/perms/users/self/assets/',
|
baseUrl: '/api/v1/perms/users/self/assets/',
|
||||||
baseNodeUrl: '/api/v1/perms/users/self/nodes/',
|
baseNodeUrl: '/api/v1/perms/users/self/nodes/',
|
||||||
|
typeUrl: '/api/v1/perms/users/self/nodes/children-with-assets/category/tree',
|
||||||
value: []
|
value: []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -446,7 +446,7 @@ export default {
|
|||||||
this.executionInfo.timeCost = 0
|
this.executionInfo.timeCost = 0
|
||||||
this.executionInfo.status = 'running'
|
this.executionInfo.status = 'running'
|
||||||
this.currentTaskId = res.task_id
|
this.currentTaskId = res.task_id
|
||||||
this.$router.replace({ query: { taskId: this.currentTaskId }})
|
this.$router.replace({ query: { taskId: this.currentTaskId, type: 'shortcut_cmd' }})
|
||||||
this.setCostTimeInterval()
|
this.setCostTimeInterval()
|
||||||
this.writeExecutionOutput()
|
this.writeExecutionOutput()
|
||||||
this.setBtn()
|
this.setBtn()
|
||||||
@@ -455,7 +455,7 @@ export default {
|
|||||||
stop() {
|
stop() {
|
||||||
StopJob({ task_id: this.currentTaskId }).then(() => {
|
StopJob({ task_id: this.currentTaskId }).then(() => {
|
||||||
this.xterm.write('\x1b[31m' +
|
this.xterm.write('\x1b[31m' +
|
||||||
this.$tc('ops.StopLogOutput').replace('currentTaskId', this.currentTaskId) + '\x1b[0m')
|
this.$tc('ops.StopLogOutput').replace('currentTaskId', this.currentTaskId) + '\x1b[0m')
|
||||||
this.xterm.write(this.wrapperError(''))
|
this.xterm.write(this.wrapperError(''))
|
||||||
this.getTaskStatus()
|
this.getTaskStatus()
|
||||||
}).catch((e) => {
|
}).catch((e) => {
|
||||||
|
|||||||
@@ -105,6 +105,7 @@ export default {
|
|||||||
formatter: AmountFormatter,
|
formatter: AmountFormatter,
|
||||||
formatterArgs: {
|
formatterArgs: {
|
||||||
async: true,
|
async: true,
|
||||||
|
cellValueToRemove: ['@SPEC'],
|
||||||
routeQuery: {
|
routeQuery: {
|
||||||
activeTab: 'AssetPermissionUser'
|
activeTab: 'AssetPermissionUser'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ export default {
|
|||||||
component: PhoneInput
|
component: PhoneInput
|
||||||
},
|
},
|
||||||
mfa_level: {
|
mfa_level: {
|
||||||
hidden: (formValue) => {
|
disabled: (formValue) => {
|
||||||
return formValue.mfa_level === 2
|
return formValue.mfa_level === 2
|
||||||
},
|
},
|
||||||
helpText: this.$t('users.HelpText.MFAOfUserFirstLoginPersonalInformationImprovementPage')
|
helpText: this.$t('users.HelpText.MFAOfUserFirstLoginPersonalInformationImprovementPage')
|
||||||
@@ -90,8 +90,7 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -143,7 +143,7 @@ export default {
|
|||||||
},
|
},
|
||||||
callbacks: {
|
callbacks: {
|
||||||
click: function() {
|
click: function() {
|
||||||
window.location.href = `/core/auth/profile/mfa/`
|
window.open('/core/auth/profile/mfa/', '_blank')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import isFalsey from '@/components/Table/DataTable/compenents/el-data-table/util
|
|||||||
import deepmerge from 'deepmerge'
|
import deepmerge from 'deepmerge'
|
||||||
import * as queryUtil from '@/components/Table/DataTable/compenents/el-data-table/utils/query'
|
import * as queryUtil from '@/components/Table/DataTable/compenents/el-data-table/utils/query'
|
||||||
import { createSourceIdCache } from '@/api/common'
|
import { createSourceIdCache } from '@/api/common'
|
||||||
|
import { download } from '@/utils/common'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'CommandList',
|
name: 'CommandList',
|
||||||
@@ -144,10 +145,7 @@ export default {
|
|||||||
queryUtil.stringify(query, '=', '&')
|
queryUtil.stringify(query, '=', '&')
|
||||||
url = url + queryStr
|
url = url + queryStr
|
||||||
this.$log.debug('Export url: ', this.url, '=>', url)
|
this.$log.debug('Export url: ', this.url, '=>', url)
|
||||||
const a = document.createElement('a')
|
download(url + queryStr)
|
||||||
a.href = url
|
|
||||||
a.click()
|
|
||||||
window.URL.revokeObjectURL(url + queryStr)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -55,8 +55,7 @@ export default {
|
|||||||
fieldsMeta: {
|
fieldsMeta: {
|
||||||
EMAIL_HOST_USER: {
|
EMAIL_HOST_USER: {
|
||||||
rules: [
|
rules: [
|
||||||
rules.EmailCheck,
|
rules.EmailCheck
|
||||||
rules.Required
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
EMAIL_FROM: {
|
EMAIL_FROM: {
|
||||||
|
|||||||
@@ -12,25 +12,24 @@ export default {
|
|||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
config: {
|
config: {
|
||||||
initial: {
|
initial: {},
|
||||||
},
|
|
||||||
url: '/api/v1/orgs/orgs/',
|
url: '/api/v1/orgs/orgs/',
|
||||||
fields: [
|
fields: [
|
||||||
['', ['name', 'comment']]
|
['', ['name', 'comment']]
|
||||||
],
|
],
|
||||||
hasSaveContinue: false,
|
hasSaveContinue: false,
|
||||||
fieldsMeta: {
|
fieldsMeta: {},
|
||||||
},
|
|
||||||
onPerformSuccess(res, method) {
|
onPerformSuccess(res, method) {
|
||||||
|
const order_params = { params: { order: '-date_created' }}
|
||||||
switch (method) {
|
switch (method) {
|
||||||
case 'post':
|
case 'post':
|
||||||
this.$store.dispatch('users/addAdminOrg', { id: res.id, name: res.name })
|
this.$store.dispatch('users/addAdminOrg', { id: res.id, name: res.name })
|
||||||
this.$message.success(this.$tc('common.createSuccessMsg'))
|
this.$message.success(this.$tc('common.createSuccessMsg'))
|
||||||
return this.$router.push({ name: 'OrganizationList' })
|
return this.$router.push({ name: 'OrganizationList', ...order_params })
|
||||||
case 'put':
|
case 'put':
|
||||||
this.$store.dispatch('users/modifyOrg', { id: res.id, name: res.name })
|
this.$store.dispatch('users/modifyOrg', { id: res.id, name: res.name })
|
||||||
this.$message.success(this.$tc('common.updateSuccessMsg'))
|
this.$message.success(this.$tc('common.updateSuccessMsg'))
|
||||||
return this.$router.push({ name: 'OrganizationList' })
|
return this.$router.push({ name: 'OrganizationList', ...order_params })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ export default {
|
|||||||
data() {
|
data() {
|
||||||
const commandType = this.$route.query.type || 'es'
|
const commandType = this.$route.query.type || 'es'
|
||||||
return {
|
return {
|
||||||
successUrl: { name: 'TerminalSetting', params: { activeMenu: 'CommandStorage' }},
|
successUrl: { name: 'Storage', params: { activeMenu: 'CommandStorage' }},
|
||||||
initial: {
|
initial: {
|
||||||
type: commandType,
|
type: commandType,
|
||||||
doc_type: 'command',
|
doc_type: 'command',
|
||||||
|
|||||||
@@ -137,6 +137,14 @@ export default {
|
|||||||
canCreate: this.$hasPerm('tickets.view_ticket'),
|
canCreate: this.$hasPerm('tickets.view_ticket'),
|
||||||
hasBulkDelete: false,
|
hasBulkDelete: false,
|
||||||
searchConfig: {
|
searchConfig: {
|
||||||
|
default: {
|
||||||
|
state: {
|
||||||
|
key: 'state',
|
||||||
|
label: this.$t('tickets.action'),
|
||||||
|
value: 'pending',
|
||||||
|
valueLabel: this.$t('common.Open')
|
||||||
|
}
|
||||||
|
},
|
||||||
exclude: ['id', 'title', 'type', 'applicant'],
|
exclude: ['id', 'title', 'type', 'applicant'],
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
@@ -180,7 +188,7 @@ export default {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: 'relevant_command',
|
value: 'relevant_command',
|
||||||
label: this.$t('tickets.RelevantSystemUser')
|
label: this.$t('tickets.ApplyRunCommand')
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -44,7 +44,7 @@
|
|||||||
<BasicTree
|
<BasicTree
|
||||||
v-model="requestForm.actions"
|
v-model="requestForm.actions"
|
||||||
:tree="treeNodes"
|
:tree="treeNodes"
|
||||||
style="width: 30% !important"
|
style="width: 100%"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|||||||
@@ -48,7 +48,12 @@ export default {
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
select2Option: {
|
select2Option: {
|
||||||
url: '/api/v1/users/users/?oid=root'
|
url: '/api/v1/users/users/?oid=root',
|
||||||
|
ajax: {
|
||||||
|
transformOption: (item) => {
|
||||||
|
return { label: item.name + '(' + item.username + ')', value: item.id }
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
fields: [
|
fields: [
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -27,7 +27,7 @@
|
|||||||
<el-form-item style="float: right">
|
<el-form-item style="float: right">
|
||||||
<template v-if="hasActionPerm">
|
<template v-if="hasActionPerm">
|
||||||
<el-button
|
<el-button
|
||||||
:disabled="object.status.value === 'closed'"
|
:disabled="isDisabled || object.status.value === 'closed'"
|
||||||
size="small"
|
size="small"
|
||||||
type="primary"
|
type="primary"
|
||||||
@click="handleApprove"
|
@click="handleApprove"
|
||||||
@@ -35,7 +35,7 @@
|
|||||||
<i class="fa fa-check" /> {{ $t('tickets.Accept') }}
|
<i class="fa fa-check" /> {{ $t('tickets.Accept') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button
|
<el-button
|
||||||
:disabled="object.status.value === 'closed'"
|
:disabled="isDisabled || object.status.value === 'closed'"
|
||||||
size="small"
|
size="small"
|
||||||
type="warning"
|
type="warning"
|
||||||
@click="handleReject"
|
@click="handleReject"
|
||||||
@@ -45,12 +45,12 @@
|
|||||||
</template>
|
</template>
|
||||||
<el-button
|
<el-button
|
||||||
v-if="isSelfTicket"
|
v-if="isSelfTicket"
|
||||||
:disabled="object.status.value === 'closed'"
|
:disabled="isDisabled || object.status.value === 'closed'"
|
||||||
size="small"
|
size="small"
|
||||||
type="danger"
|
type="danger"
|
||||||
@click="handleClose"
|
@click="handleClose"
|
||||||
>
|
>
|
||||||
<i class="fa fa-times" /> {{ $t('tickets.Close') }}
|
<i class="fa fa-times" /> {{ $t('tickets.CancelTicket') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button
|
<el-button
|
||||||
:disabled="object.status.value === 'closed'"
|
:disabled="object.status.value === 'closed'"
|
||||||
@@ -94,6 +94,7 @@ export default {
|
|||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
isDisabled: false,
|
||||||
comments: '',
|
comments: '',
|
||||||
type_api: '',
|
type_api: '',
|
||||||
imageUrl: require('@/assets/img/avatar.png'),
|
imageUrl: require('@/assets/img/avatar.png'),
|
||||||
@@ -156,17 +157,35 @@ export default {
|
|||||||
this.createComment(function() {
|
this.createComment(function() {
|
||||||
})
|
})
|
||||||
const url = `/api/v1/tickets/${this.type_api}/${this.object.id}/approve/`
|
const url = `/api/v1/tickets/${this.type_api}/${this.object.id}/approve/`
|
||||||
this.$axios.put(url).then(res => this.reloadPage()).catch(err => this.$message.error(err))
|
this.$axios.put(url).then(res => {
|
||||||
|
this.reloadPage()
|
||||||
|
}).catch(err => {
|
||||||
|
this.$message.error(err)
|
||||||
|
}).finally(() => {
|
||||||
|
this.isDisabled = false
|
||||||
|
})
|
||||||
},
|
},
|
||||||
defaultReject() {
|
defaultReject() {
|
||||||
this.createComment(function() {
|
this.createComment(function() {
|
||||||
})
|
})
|
||||||
const url = `/api/v1/tickets/${this.type_api}/${this.object.id}/reject/`
|
const url = `/api/v1/tickets/${this.type_api}/${this.object.id}/reject/`
|
||||||
this.$axios.put(url).then(res => this.reloadPage()).catch(err => this.$message.error(err))
|
this.$axios.put(url).then(res => {
|
||||||
|
this.reloadPage()
|
||||||
|
}).catch(err => {
|
||||||
|
this.$message.error(err)
|
||||||
|
}).finally(() => {
|
||||||
|
this.isDisabled = false
|
||||||
|
})
|
||||||
},
|
},
|
||||||
defaultClose() {
|
defaultClose() {
|
||||||
const url = `/api/v1/tickets/${this.type_api}/${this.object.id}/close/`
|
const url = `/api/v1/tickets/${this.type_api}/${this.object.id}/close/`
|
||||||
this.$axios.put(url).then(res => this.reloadPage()).catch(err => this.$message.error(err))
|
this.$axios.put(url).then(res => {
|
||||||
|
this.reloadPage()
|
||||||
|
}).catch(err => {
|
||||||
|
this.$message.error(err)
|
||||||
|
}).finally(() => {
|
||||||
|
this.isDisabled = false
|
||||||
|
})
|
||||||
},
|
},
|
||||||
createComment(successCallback) {
|
createComment(successCallback) {
|
||||||
const commentText = this.form.comments
|
const commentText = this.form.comments
|
||||||
@@ -187,17 +206,42 @@ export default {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
handleAction(actionType) {
|
||||||
|
if (this.isDisabled) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.isDisabled = true
|
||||||
|
let handler
|
||||||
|
switch (actionType) {
|
||||||
|
case 'approve':
|
||||||
|
handler = this.approve || this.defaultApprove
|
||||||
|
break
|
||||||
|
case 'reject':
|
||||||
|
handler = this.reject || this.defaultReject
|
||||||
|
break
|
||||||
|
case 'close':
|
||||||
|
handler = this.close || this.defaultClose
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
handler = null
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if (handler) {
|
||||||
|
handler()
|
||||||
|
} else {
|
||||||
|
this.$message.error('No handler for action')
|
||||||
|
}
|
||||||
|
},
|
||||||
handleApprove() {
|
handleApprove() {
|
||||||
const handler = this.approve || this.defaultApprove
|
this.handleAction('approve')
|
||||||
handler()
|
|
||||||
},
|
},
|
||||||
handleReject() {
|
handleReject() {
|
||||||
const handler = this.reject || this.defaultReject
|
this.handleAction('reject')
|
||||||
handler()
|
|
||||||
},
|
},
|
||||||
handleClose() {
|
handleClose() {
|
||||||
const handler = this.close || this.defaultClose
|
this.handleAction('close')
|
||||||
handler()
|
|
||||||
},
|
},
|
||||||
handleComment() {
|
handleComment() {
|
||||||
this.createComment(
|
this.createComment(
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { GenericCreateUpdatePage } from '@/layout/components'
|
import { GenericCreateUpdatePage } from '@/layout/components'
|
||||||
import TransSelect from '@/components/Form/FormFields/TransferSelect.vue'
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
@@ -23,7 +22,6 @@ export default {
|
|||||||
],
|
],
|
||||||
fieldsMeta: {
|
fieldsMeta: {
|
||||||
users: {
|
users: {
|
||||||
component: TransSelect,
|
|
||||||
el: {
|
el: {
|
||||||
url: '/api/v1/users/users/?fields_size=mini&order=name',
|
url: '/api/v1/users/users/?fields_size=mini&order=name',
|
||||||
ajax: {
|
ajax: {
|
||||||
@@ -38,8 +36,7 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import { PhoneInput, UserPassword } from '@/components/Form/FormFields'
|
|||||||
import rules from '@/components/Form/DataForm/rules'
|
import rules from '@/components/Form/DataForm/rules'
|
||||||
import { mapGetters } from 'vuex'
|
import { mapGetters } from 'vuex'
|
||||||
import { Select2 } from '@/components'
|
import { Select2 } from '@/components'
|
||||||
|
import store from '@/store'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
@@ -40,6 +41,9 @@ export default {
|
|||||||
return this.$route.params.id || formValue.source !== 'local'
|
return this.$route.params.id || formValue.source !== 'local'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
mfa_level: {
|
||||||
|
disabled: false
|
||||||
|
},
|
||||||
email: {
|
email: {
|
||||||
rules: [
|
rules: [
|
||||||
rules.EmailCheck,
|
rules.EmailCheck,
|
||||||
@@ -148,8 +152,8 @@ export default {
|
|||||||
},
|
},
|
||||||
hidden: () => {
|
hidden: () => {
|
||||||
return !this.$store.getters.hasValidLicense ||
|
return !this.$store.getters.hasValidLicense ||
|
||||||
!this.$hasPerm('rbac.add_orgrolebinding') ||
|
!this.$hasPerm('rbac.add_orgrolebinding') ||
|
||||||
this.$store.getters.currentOrgIsRoot
|
this.$store.getters.currentOrgIsRoot
|
||||||
},
|
},
|
||||||
helpText: this.$t('users.HelpText.OrgRoleHelpText')
|
helpText: this.$t('users.HelpText.OrgRoleHelpText')
|
||||||
},
|
},
|
||||||
@@ -212,6 +216,7 @@ export default {
|
|||||||
this.fieldsMeta.groups.el.disabled = true
|
this.fieldsMeta.groups.el.disabled = true
|
||||||
}
|
}
|
||||||
await this.setDefaultRoles()
|
await this.setDefaultRoles()
|
||||||
|
this.disableMFAFieldIfNeed(null)
|
||||||
this.loading = false
|
this.loading = false
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@@ -229,11 +234,21 @@ export default {
|
|||||||
if (this.$route.query.clone_from) {
|
if (this.$route.query.clone_from) {
|
||||||
this.user.groups = []
|
this.user.groups = []
|
||||||
}
|
}
|
||||||
|
this.disableMFAFieldIfNeed(user)
|
||||||
},
|
},
|
||||||
async setDefaultRoles() {
|
async setDefaultRoles() {
|
||||||
const roles = await this.$axios.get('/api/v1/rbac/roles/')
|
const roles = await this.$axios.get('/api/v1/rbac/roles/')
|
||||||
this.initial.system_roles = roles.filter(role => role.name === 'User').map(role => role.id)
|
this.initial.system_roles = roles.filter(role => role.name === 'User').map(role => role.id)
|
||||||
this.initial.org_roles = roles.filter(role => role.name === 'OrgUser').map(role => role.id)
|
this.initial.org_roles = roles.filter(role => role.name === 'OrgUser').map(role => role.id)
|
||||||
|
},
|
||||||
|
disableMFAFieldIfNeed(user) {
|
||||||
|
// SECURITY_MFA_AUTH 0 不开启 1 全局开启 2 管理员开启
|
||||||
|
const adminUserIsNeed = (user?.is_superuser || user?.is_org_admin) && this.$route.meta.action === 'update' &&
|
||||||
|
store.getters.publicSettings['SECURITY_MFA_AUTH'] === 2
|
||||||
|
if (store.getters.publicSettings['SECURITY_MFA_AUTH'] === 1 || adminUserIsNeed) {
|
||||||
|
this.fieldsMeta['mfa_level'].disabled = true
|
||||||
|
this.fieldsMeta['mfa_level'].helpText = this.$t('users.GlobalDisableMfaMsg')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
37
yarn.lock
37
yarn.lock
@@ -4463,6 +4463,11 @@ domhandler@^4.0.0, domhandler@^4.2.0, domhandler@^4.2.2, domhandler@^4.3.1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
domelementtype "^2.2.0"
|
domelementtype "^2.2.0"
|
||||||
|
|
||||||
|
dompurify@^3.1.6:
|
||||||
|
version "3.1.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-3.1.6.tgz#43c714a94c6a7b8801850f82e756685300a027e2"
|
||||||
|
integrity sha512-cTOAhc36AalkjtBpfG6O8JimdTMWNXjiePT2xQH/ppBGi/4uIpmj8eKyIkMJErXWARyINV/sB38yf8JCLF5pbQ==
|
||||||
|
|
||||||
domready@1.0.8:
|
domready@1.0.8:
|
||||||
version "1.0.8"
|
version "1.0.8"
|
||||||
resolved "https://registry.npmmirror.com/domready/-/domready-1.0.8.tgz#91f252e597b65af77e745ae24dd0185d5e26d58c"
|
resolved "https://registry.npmmirror.com/domready/-/domready-1.0.8.tgz#91f252e597b65af77e745ae24dd0185d5e26d58c"
|
||||||
@@ -12079,7 +12084,7 @@ string-length@^2.0.0:
|
|||||||
astral-regex "^1.0.0"
|
astral-regex "^1.0.0"
|
||||||
strip-ansi "^4.0.0"
|
strip-ansi "^4.0.0"
|
||||||
|
|
||||||
"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
|
"string-width-cjs@npm:string-width@^4.2.0":
|
||||||
version "4.2.3"
|
version "4.2.3"
|
||||||
resolved "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
|
resolved "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
|
||||||
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
|
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
|
||||||
@@ -12097,6 +12102,15 @@ string-width@^1.0.1:
|
|||||||
is-fullwidth-code-point "^1.0.0"
|
is-fullwidth-code-point "^1.0.0"
|
||||||
strip-ansi "^3.0.0"
|
strip-ansi "^3.0.0"
|
||||||
|
|
||||||
|
"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
|
||||||
|
version "4.2.3"
|
||||||
|
resolved "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
|
||||||
|
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
|
||||||
|
dependencies:
|
||||||
|
emoji-regex "^8.0.0"
|
||||||
|
is-fullwidth-code-point "^3.0.0"
|
||||||
|
strip-ansi "^6.0.1"
|
||||||
|
|
||||||
string-width@^2.0.0, string-width@^2.1.0, string-width@^2.1.1:
|
string-width@^2.0.0, string-width@^2.1.0, string-width@^2.1.1:
|
||||||
version "2.1.1"
|
version "2.1.1"
|
||||||
resolved "https://registry.npmmirror.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e"
|
resolved "https://registry.npmmirror.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e"
|
||||||
@@ -12196,7 +12210,7 @@ stringify-package@^1.0.1:
|
|||||||
resolved "https://registry.npmmirror.com/stringify-package/-/stringify-package-1.0.1.tgz#e5aa3643e7f74d0f28628b72f3dad5cecfc3ba85"
|
resolved "https://registry.npmmirror.com/stringify-package/-/stringify-package-1.0.1.tgz#e5aa3643e7f74d0f28628b72f3dad5cecfc3ba85"
|
||||||
integrity sha512-sa4DUQsYciMP1xhKWGuFM04fB0LG/9DlluZoSVywUMRNvzid6XucHK0/90xGxRoHrAaROrcHK1aPKaijCtSrhg==
|
integrity sha512-sa4DUQsYciMP1xhKWGuFM04fB0LG/9DlluZoSVywUMRNvzid6XucHK0/90xGxRoHrAaROrcHK1aPKaijCtSrhg==
|
||||||
|
|
||||||
"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1:
|
"strip-ansi-cjs@npm:strip-ansi@^6.0.1":
|
||||||
version "6.0.1"
|
version "6.0.1"
|
||||||
resolved "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
|
resolved "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
|
||||||
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
|
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
|
||||||
@@ -12224,6 +12238,13 @@ strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
ansi-regex "^4.1.0"
|
ansi-regex "^4.1.0"
|
||||||
|
|
||||||
|
strip-ansi@^6.0.0, strip-ansi@^6.0.1:
|
||||||
|
version "6.0.1"
|
||||||
|
resolved "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
|
||||||
|
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
|
||||||
|
dependencies:
|
||||||
|
ansi-regex "^5.0.1"
|
||||||
|
|
||||||
strip-ansi@^7.0.1, strip-ansi@^7.1.0:
|
strip-ansi@^7.0.1, strip-ansi@^7.1.0:
|
||||||
version "7.1.0"
|
version "7.1.0"
|
||||||
resolved "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45"
|
resolved "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45"
|
||||||
@@ -13616,8 +13637,7 @@ worker-farm@^1.7.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
errno "~0.1.7"
|
errno "~0.1.7"
|
||||||
|
|
||||||
"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0:
|
"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0":
|
||||||
name wrap-ansi-cjs
|
|
||||||
version "7.0.0"
|
version "7.0.0"
|
||||||
resolved "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
|
resolved "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
|
||||||
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
|
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
|
||||||
@@ -13652,6 +13672,15 @@ wrap-ansi@^6.2.0:
|
|||||||
string-width "^4.1.0"
|
string-width "^4.1.0"
|
||||||
strip-ansi "^6.0.0"
|
strip-ansi "^6.0.0"
|
||||||
|
|
||||||
|
wrap-ansi@^7.0.0:
|
||||||
|
version "7.0.0"
|
||||||
|
resolved "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
|
||||||
|
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
|
||||||
|
dependencies:
|
||||||
|
ansi-styles "^4.0.0"
|
||||||
|
string-width "^4.1.0"
|
||||||
|
strip-ansi "^6.0.0"
|
||||||
|
|
||||||
wrap-ansi@^8.1.0:
|
wrap-ansi@^8.1.0:
|
||||||
version "8.1.0"
|
version "8.1.0"
|
||||||
resolved "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214"
|
resolved "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214"
|
||||||
|
|||||||
Reference in New Issue
Block a user