mirror of
https://github.com/jumpserver/lina.git
synced 2025-09-18 16:32:28 +00:00
@@ -17,6 +17,7 @@
|
||||
:table-config="tableConfig"
|
||||
:tree-url="`${baseNodeUrl}children/tree/`"
|
||||
:url="baseUrl"
|
||||
:tree-setting="treeSetting"
|
||||
class="tree-table"
|
||||
v-bind="$attrs"
|
||||
/>
|
||||
@@ -52,6 +53,10 @@ export default {
|
||||
disabled: {
|
||||
type: [Boolean, Function],
|
||||
default: false
|
||||
},
|
||||
treeSetting: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
}
|
||||
},
|
||||
data() {
|
||||
|
@@ -13,6 +13,7 @@
|
||||
ref="dialog"
|
||||
:base-node-url="baseNodeUrl"
|
||||
:base-url="baseUrl"
|
||||
:tree-setting="treeSetting"
|
||||
:tree-url-query="treeUrlQuery"
|
||||
:value="value"
|
||||
:visible.sync="dialogVisible"
|
||||
@@ -48,6 +49,10 @@ export default {
|
||||
value: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
treeSetting: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
}
|
||||
},
|
||||
data() {
|
||||
|
@@ -60,6 +60,7 @@ export default {
|
||||
const showAssets = this.treeSetting?.showAssets || this.showAssets
|
||||
const treeUrlQuery = this.setTreeUrlQuery()
|
||||
const assetTreeUrl = `${this.treeUrl}?assets=${showAssets ? '1' : '0'}&${treeUrlQuery}`
|
||||
const vm = this
|
||||
|
||||
return {
|
||||
treeTabConfig: {
|
||||
@@ -81,7 +82,13 @@ export default {
|
||||
nodeUrl: this.nodeUrl,
|
||||
treeUrl: assetTreeUrl,
|
||||
callback: {
|
||||
onSelected: (event, treeNode) => this.getAssetsUrl(treeNode)
|
||||
onSelected: (event, treeNode) => this.getAssetsUrl(treeNode),
|
||||
beforeRefresh: () => {
|
||||
const query = { ...this.$route.query, node_id: '', asset_id: '' }
|
||||
setTimeout(() => {
|
||||
vm.$router.replace({ query: query })
|
||||
}, 100)
|
||||
}
|
||||
},
|
||||
...this.treeSetting
|
||||
}
|
||||
|
@@ -5,9 +5,9 @@ import Switcher from '@/components/Form/FormFields/Switcher.vue'
|
||||
import rules from '@/components/Form/DataForm/rules'
|
||||
import BasicTree from '@/components/Form/FormFields/BasicTree.vue'
|
||||
import JsonEditor from '@/components/Form/FormFields/JsonEditor.vue'
|
||||
import TransferSelect from '@/components/Form/FormFields/TransferSelect.vue'
|
||||
import { assignIfNot } from '@/utils/common'
|
||||
import TagInput from '@/components/Form/FormFields/TagInput.vue'
|
||||
import TransferSelect from '@/components/Form/FormFields/TransferSelect.vue'
|
||||
|
||||
export class FormFieldGenerator {
|
||||
constructor(emit) {
|
||||
@@ -45,7 +45,7 @@ export class FormFieldGenerator {
|
||||
break
|
||||
case 'field':
|
||||
type = ''
|
||||
field.component = TransferSelect
|
||||
field.component = ObjectSelect2
|
||||
if (fieldRemoteMeta.required) {
|
||||
field.el.clearable = false
|
||||
}
|
||||
@@ -76,7 +76,7 @@ export class FormFieldGenerator {
|
||||
field.component = ObjectSelect2
|
||||
break
|
||||
case 'm2m_related_field':
|
||||
field.component = TransferSelect
|
||||
field.component = ObjectSelect2
|
||||
field.el.label = field.label
|
||||
break
|
||||
case 'nested object':
|
||||
@@ -134,6 +134,9 @@ export class FormFieldGenerator {
|
||||
case 'comment':
|
||||
field.el.type = 'textarea'
|
||||
break
|
||||
case 'users':
|
||||
field.component = TransferSelect
|
||||
field.el.label = field.label
|
||||
}
|
||||
return field
|
||||
}
|
||||
|
@@ -204,7 +204,12 @@ export default {
|
||||
},
|
||||
formatWeektime(col) {
|
||||
const timeStamp = 1542384000000 // '2018-11-17 00:00:00'
|
||||
const beginStamp = timeStamp + col * 1800000 // col * 30 * 60 * 1000
|
||||
const timezone = 8
|
||||
const offsetGMT = new Date().getTimezoneOffset() // 本地时间和格林威治的时间差,单位为分钟
|
||||
const nowDate = new Date(timeStamp).getTime()
|
||||
const targetStamp = new Date(nowDate + offsetGMT * 60 * 1000 + timezone * 60 * 60 * 1000).getTime()
|
||||
|
||||
const beginStamp = targetStamp + col * 1800000 // col * 30 * 60 * 1000
|
||||
const endStamp = beginStamp + 1800000
|
||||
|
||||
const begin = this.formatDate(new Date(beginStamp), 'hh:mm')
|
||||
|
@@ -3,7 +3,7 @@
|
||||
<el-button v-if="shouldFold" circle class="search-btn" size="mini" @click="handleManualSearch">
|
||||
<svg-icon icon-class="search" />
|
||||
</el-button>
|
||||
<TagSearch v-else :options="iOption" v-bind="$attrs" @tagSearch="handleTagSearch" v-on="$listeners" />
|
||||
<TagSearch v-else :options="iOption" v-bind="$attrs" v-on="$listeners" @tag-search="handleTagSearch" />
|
||||
</span>
|
||||
</template>
|
||||
|
||||
@@ -68,6 +68,9 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
handleTagSearch(tags) {
|
||||
if (_.isEqual(tags, this.tags)) {
|
||||
return
|
||||
}
|
||||
this.tags = tags
|
||||
if (tags.length === 0) {
|
||||
this.manualSearch = false
|
||||
|
@@ -104,7 +104,7 @@ export default {
|
||||
title: this.$t('common.BatchUpdate'),
|
||||
name: 'actionUpdateSelected',
|
||||
has: this.hasBulkUpdate,
|
||||
icon: 'fa fa-refresh',
|
||||
fa: 'batch-update',
|
||||
can: function({ selectedRows }) {
|
||||
let canBulkUpdate = vm.canBulkUpdate
|
||||
if (typeof canBulkUpdate === 'function') {
|
||||
|
@@ -173,12 +173,14 @@ export default {
|
||||
this.dataTable.getList()
|
||||
},
|
||||
search(attrs) {
|
||||
this.$log.debug('ListTable: search table', attrs)
|
||||
this.$emit('TagSearch', attrs)
|
||||
return this.dataTable?.search(attrs, true)
|
||||
this.$refs.dataTable?.$refs.dataTable?.search(attrs, true)
|
||||
},
|
||||
filter(attrs) {
|
||||
this.$emit('TagFilter', attrs)
|
||||
this.$refs.dataTable.$refs.dataTable.search(attrs, true)
|
||||
this.$log.debug('ListTable: found filter change', attrs)
|
||||
this.search(attrs)
|
||||
},
|
||||
hasActionPerm(action) {
|
||||
const permRequired = this.permissions[action]
|
||||
|
@@ -10,14 +10,14 @@
|
||||
<el-tag
|
||||
v-for="(v, k) in filterTags"
|
||||
:key="k"
|
||||
:disable-transitions="true"
|
||||
:name="k"
|
||||
class="filter-tag"
|
||||
closable
|
||||
size="small"
|
||||
class="filter-tag"
|
||||
type="info"
|
||||
:disable-transitions="true"
|
||||
@close="handleTagClose(k)"
|
||||
@click="handleTagClick(v,k)"
|
||||
@close="handleTagClose(k)"
|
||||
>
|
||||
<strong v-if="v.label">{{ v.label + ':' }}</strong>
|
||||
<span v-if="v.valueLabel">{{ v.valueLabel }}</span>
|
||||
@@ -27,14 +27,14 @@
|
||||
<el-input
|
||||
ref="SearchInput"
|
||||
v-model="filterValue"
|
||||
:placeholder="placeholder"
|
||||
class="search-input"
|
||||
:class="options.length < 1 ? 'search-input2': ''"
|
||||
:placeholder="placeholder"
|
||||
:validate-event="false"
|
||||
class="search-input"
|
||||
suffix-icon="el-icon-search"
|
||||
@blur="focus = false"
|
||||
@focus="focus = true"
|
||||
@change="handleConfirm"
|
||||
@focus="focus = true"
|
||||
@keyup.enter.native="handleConfirm"
|
||||
@keyup.delete.native="handleDelete"
|
||||
/>
|
||||
@@ -122,6 +122,12 @@ export default {
|
||||
},
|
||||
deep: true
|
||||
},
|
||||
filterTags: {
|
||||
handler() {
|
||||
this.$emit('tag-search', this.filterMaps)
|
||||
},
|
||||
deep: true
|
||||
},
|
||||
filterValue(newValue, oldValue) {
|
||||
if (newValue === '' && oldValue !== '') {
|
||||
this.emptyCount = 1
|
||||
@@ -210,11 +216,6 @@ export default {
|
||||
...asFilterTags,
|
||||
...routeFilter
|
||||
}
|
||||
if (Object.keys(this.filterTags).length > 0) {
|
||||
setTimeout(() => {
|
||||
return this.$emit('tagSearch', this.filterMaps)
|
||||
}, 400)
|
||||
}
|
||||
},
|
||||
getValueLabel(key, value) {
|
||||
for (const field of this.options) {
|
||||
@@ -252,7 +253,7 @@ export default {
|
||||
if (this.getUrlQuery) {
|
||||
this.checkUrlFields(evt)
|
||||
}
|
||||
this.$emit('tagSearch', this.filterMaps)
|
||||
// this.$emit('tagSearch', this.filterMaps)
|
||||
return true
|
||||
},
|
||||
handleDelete() {
|
||||
@@ -284,7 +285,7 @@ export default {
|
||||
valueLabel: this.valueLabel
|
||||
}
|
||||
this.$set(this.filterTags, this.filterKey, tag)
|
||||
this.$emit('tagSearch', this.filterMaps)
|
||||
// this.$emit('tagSearch', this.filterMaps)
|
||||
|
||||
// 修改查询参数时改变url中保存的参数
|
||||
if (this.getUrlQuery) {
|
||||
|
@@ -167,6 +167,9 @@ export default {
|
||||
},
|
||||
async refresh() {
|
||||
this.treeSearchValue = ''
|
||||
if (this.treeSetting?.callback?.beforeRefresh) {
|
||||
this.treeSetting.callback.beforeRefresh()
|
||||
}
|
||||
if (this.treeSetting?.callback?.refresh) {
|
||||
await this.treeSetting.callback.refresh()
|
||||
}
|
||||
|
@@ -969,29 +969,30 @@
|
||||
"LoginCount": "Login count",
|
||||
"LoginOverview": "Sessions overview",
|
||||
"LoginTo": "Login to",
|
||||
"LoginUsers": "Active accounts",
|
||||
"ActiveUsers": "Active users",
|
||||
"Monthly": "Monthly",
|
||||
"CurrentConnections": "Current connections",
|
||||
"TodayFailedConnections": "Connections failed today",
|
||||
"CurrentConnectionUsers": "Current connection users",
|
||||
"TodayFailedConnections": "Number of failed sessions today",
|
||||
"OnlineSessions": "Online sessions",
|
||||
"OnlineUserDevices": "Online user devices",
|
||||
"RealTimeData": "Real-time data",
|
||||
"UserAssetActivity": "Account/Asset activity",
|
||||
"UserData": "Account data",
|
||||
"UserAssetActivity": "User/asset activity status",
|
||||
"UserData": "User data",
|
||||
"LoginUserToday": "Login account today",
|
||||
"AssetData": "Asset data",
|
||||
"LoginAssetToday": "Active assets today",
|
||||
"LoginAssetToday": "Active asset today",
|
||||
"WeekAdd": "New this week",
|
||||
"ProportionOfAssetTypes": "Proportion of asset types",
|
||||
"Proportion": "Proportion",
|
||||
"LoginUserRanking": "Login account ranking",
|
||||
"ActiveAssetRanking": "Login asset ranking",
|
||||
"LoginUserRanking": "Session user ranking",
|
||||
"ActiveAssetRanking": "Session asset Ranking",
|
||||
"AssetName": "Asset name",
|
||||
"NumberOfVisits": "Number of visits",
|
||||
"ranking": "Ranking",
|
||||
"Today": "Today",
|
||||
"Last7Days": "Last 7 days",
|
||||
"Last30Days": "Last30 days",
|
||||
"Last7Days": "Last 7d",
|
||||
"Last30Days": "Last 30d",
|
||||
"OnlineUsers": "Online accounts",
|
||||
"ConnectUsers": "Connect accounts",
|
||||
"Num": "Num",
|
||||
@@ -1009,13 +1010,14 @@
|
||||
"BatchCommandNotExecuted": "Batch command not executed",
|
||||
"ExecuteFailedCommand": "Execute failed command",
|
||||
"SessionTrend": "Session trend",
|
||||
"SessionConnectTrend": "Session connection trends",
|
||||
"UserLoginTrend": "Account login trend",
|
||||
"TimesWeekUnit": "times/week",
|
||||
"TopAssetsOfWeek": "Top assets of week",
|
||||
"TopUsersOfWeek": "Top user of week",
|
||||
"User": "User",
|
||||
"UserRatio": "User Ratio",
|
||||
"UsersTotal": "Accounts total",
|
||||
"UsersTotal": "User total",
|
||||
"Weekly": "Weekly",
|
||||
"TotalJobFailed": "Total job failed",
|
||||
"TotalJobRunning": "Total job running",
|
||||
@@ -2002,7 +2004,7 @@
|
||||
"Account": "Account",
|
||||
"Existing": "Existing",
|
||||
"UserInformation": "User information",
|
||||
"Authentication": "Account",
|
||||
"Authentication": "Authentication",
|
||||
"Comment": "Comment",
|
||||
"ConfirmPassword": "Confirm password",
|
||||
"DateExpired": "Date expired",
|
||||
|
@@ -971,22 +971,23 @@
|
||||
"LoginCount": "ログイン回数",
|
||||
"LoginOverview": "セッション統計",
|
||||
"LoginTo": "ログインしました",
|
||||
"LoginUsers": "アクティブなアカウント",
|
||||
"ActiveUsers": "アクティブユーザー",
|
||||
"Monthly": "月ごと",
|
||||
"CurrentConnections": "現在の接続数",
|
||||
"TodayFailedConnections": "今日の接続に失敗しました",
|
||||
"CurrentConnectionUsers": "現在のセッションユーザーの数",
|
||||
"TodayFailedConnections": "今日の失敗したセッションの数",
|
||||
"OnlineSessions": "オンラインセッション",
|
||||
"RealTimeData": "リアルタイムデータ",
|
||||
"UserAssetActivity": "アカウント/資産のアクティブ化",
|
||||
"UserData": "アカウントデータ",
|
||||
"LoginUserToday": "今日のログインアカウント数",
|
||||
"UserAssetActivity": "ユーザー/アセットのアクティビティステータス",
|
||||
"UserData": "ユーザーデータ",
|
||||
"LoginUserToday": "今日のログインユーザー数",
|
||||
"AssetData": "資産データ",
|
||||
"LoginAssetToday": "今日のアクティブ資産数",
|
||||
"WeekAdd": "今週の追加",
|
||||
"ProportionOfAssetTypes": "資産タイプの割合",
|
||||
"Proportion": "占有率",
|
||||
"LoginUserRanking": "ログインアカウントランキング",
|
||||
"ActiveAssetRanking": "ログイン資産ランキング",
|
||||
"LoginUserRanking": "セッションユーザーランキング",
|
||||
"ActiveAssetRanking": "セッションアセットランキング",
|
||||
"AssetName": "資産名",
|
||||
"NumberOfVisits": "アクセス回数",
|
||||
"ranking": "ランキング",
|
||||
@@ -1010,13 +1011,14 @@
|
||||
"BatchCommandNotExecuted": "未実行コマンド",
|
||||
"ExecuteFailedCommand": "失敗コマンドの実行",
|
||||
"SessionTrend": "セッショントレンド",
|
||||
"SessionConnectTrend": "セッション接続の傾向",
|
||||
"UserLoginTrend": "アカウントログイントレンド",
|
||||
"TimesWeekUnit": "回/週",
|
||||
"TopAssetsOfWeek": "週間資産TOP10",
|
||||
"TopUsersOfWeek": "週ユーザーTOP10",
|
||||
"User": "ユーザー",
|
||||
"UserRatio": "ユーザー比率統計",
|
||||
"UsersTotal": "アカウント総数",
|
||||
"UsersTotal": "総ユーザー数",
|
||||
"Weekly": "週ごと"
|
||||
},
|
||||
"ops": {
|
||||
|
@@ -960,22 +960,23 @@
|
||||
"LoginCount": "登录次数",
|
||||
"LoginOverview": "会话统计",
|
||||
"LoginTo": "登录了",
|
||||
"LoginUsers": "活跃账号",
|
||||
"ActiveUsers": "活跃用户",
|
||||
"Monthly": "按月",
|
||||
"CurrentConnections": "当前连接数",
|
||||
"TodayFailedConnections": "今日连接失败数",
|
||||
"CurrentConnectionUsers": "当前会话用户数",
|
||||
"TodayFailedConnections": "今日会话失败数",
|
||||
"OnlineSessions": "在线会话数",
|
||||
"RealTimeData": "实时数据",
|
||||
"UserAssetActivity": "账号/资产活跃情况",
|
||||
"UserData": "账号数据",
|
||||
"LoginUserToday": "今日登录账号数",
|
||||
"UserAssetActivity": "用户/资产活跃情况",
|
||||
"UserData": "用户数据",
|
||||
"LoginUserToday": "今日登录用户数",
|
||||
"AssetData": "资产数据",
|
||||
"LoginAssetToday": "今日活跃资产数",
|
||||
"WeekAdd": "本周新增",
|
||||
"ProportionOfAssetTypes": "资产类型占比",
|
||||
"Proportion": "占比",
|
||||
"LoginUserRanking": "登录账号排名",
|
||||
"ActiveAssetRanking": "登录资产排名",
|
||||
"LoginUserRanking": "会话用户排名",
|
||||
"ActiveAssetRanking": "会话资产排名",
|
||||
"AssetName": "资产名称",
|
||||
"NumberOfVisits": "访问次数",
|
||||
"ranking": "排名",
|
||||
@@ -999,13 +1000,13 @@
|
||||
"BatchCommandNotExecuted": "未执行批量命令",
|
||||
"ExecuteFailedCommand": "执行失败命令",
|
||||
"SessionTrend": "会话趋势",
|
||||
"UserLoginTrend": "账号登录趋势",
|
||||
"SessionConnectTrend": "会话连接趋势",
|
||||
"TimesWeekUnit": "次/周",
|
||||
"TopAssetsOfWeek": "周资产 TOP10",
|
||||
"TopUsersOfWeek": "周用户 TOP10",
|
||||
"User": "用户",
|
||||
"UserRatio": "用户占比统计",
|
||||
"UsersTotal": "账号总数",
|
||||
"UsersTotal": "用户总数",
|
||||
"Weekly": "按周"
|
||||
},
|
||||
"ops": {
|
||||
|
@@ -1 +1 @@
|
||||
<svg t="1687315588323" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3119" width="11" height="11"><path d="M302.545455 116.363636h409.6a27.927273 27.927273 0 0 0 0-55.854545h-409.6a27.927273 27.927273 0 1 0 0 55.854545z m-93.09091 102.4h595.781819a27.927273 27.927273 0 0 0 0-55.854545h-595.781819a27.927273 27.927273 0 1 0 0 55.854545z m670.254546 55.854546h-735.418182c-51.414109 0-93.090909 41.686109-93.090909 93.090909v512c0 51.414109 41.6768 93.090909 93.090909 93.090909h735.418182c51.414109 0 93.090909-41.6768 93.090909-93.090909v-512c0-51.4048-41.6768-93.090909-93.090909-93.090909z m37.236364 594.3296a46.545455 46.545455 0 0 1-46.545455 46.545454h-716.8a46.545455 46.545455 0 0 1-46.545455-46.545454V386.327273a46.545455 46.545455 0 0 1 46.545455-46.545455h716.8a46.545455 46.545455 0 0 1 46.545455 46.545455v482.620509zM602.177164 522.621673l-68.9152-64.474764a4.747636 4.747636 0 0 0-1.405673-1.349818 9.234618 9.234618 0 0 0-1.396364-1.163636 11.776 11.776 0 0 0-3.006836-1.7408c-0.996073-0.577164-1.796655-0.772655-2.802036-1.163637-0.605091-0.195491-1.200873-0.390982-2.010764-0.577163-0.390982 0-0.586473-0.195491-0.996073-0.195491-2.196945-0.577164-4.012218-0.577164-5.008291-0.577164h-0.400291c-0.996073 0-3.006836 0-5.408581 0.577164-0.400291 0-0.595782 0.195491-0.996073 0.195491-0.400291 0.195491-1.005382 0.195491-1.405673 0.390981a15.555491 15.555491 0 0 0-3.006836 1.163637c-0.195491 0-0.195491 0.195491-0.400291 0.195491 0 0.195491-0.195491 0.195491-0.195491 0.195491-1.200873 0.577164-2.606545 1.349818-3.611927 2.122472l-0.195491 0.195491a7.000436 7.000436 0 0 0-2.401746 1.7408l-67.314036 64.660946c-4.803491 4.449745-7.614836 10.426182-7.614836 16.7936-0.195491 6.376727 2.606545 12.744145 7.214545 17.370763s10.826473 7.335564 17.435927 7.335564 13.218909-2.513455 18.031709-7.149382l24.641164-23.738182v266.267928c0 13.312 11.226764 24.129164 25.041455 24.129163s25.041455-10.817164 25.041454-24.129163V532.452073l26.046836 24.520145c4.608 4.626618 10.817164 6.953891 17.640728 6.953891 6.795636 0 13.014109-2.513455 17.836218-7.149382l0.186182-0.195491c9.616291-9.644218 9.4208-24.510836-0.400291-33.773381l-0.223418-0.186182z" fill="#2c2c2c" p-id="3120"></path></svg>
|
||||
<svg t="1704873961556" viewBox="0 0 1124 1224" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8913" width="14" height="14"><path stroke-width="150" d="M302.545455 116.363636h409.6a27.927273 27.927273 0 0 0 0-55.854545h-409.6a27.927273 27.927273 0 1 0 0 55.854545z m-93.09091 102.4h595.781819a27.927273 27.927273 0 0 0 0-55.854545h-595.781819a27.927273 27.927273 0 1 0 0 55.854545z m670.254546 55.854546h-735.418182c-51.414109 0-93.090909 41.686109-93.090909 93.090909v512c0 51.414109 41.6768 93.090909 93.090909 93.090909h735.418182c51.414109 0 93.090909-41.6768 93.090909-93.090909v-512c0-51.4048-41.6768-93.090909-93.090909-93.090909z m37.236364 594.3296a46.545455 46.545455 0 0 1-46.545455 46.545454h-716.8a46.545455 46.545455 0 0 1-46.545455-46.545454V386.327273a46.545455 46.545455 0 0 1 46.545455-46.545455h716.8a46.545455 46.545455 0 0 1 46.545455 46.545455v482.620509zM602.177164 522.621673l-68.9152-64.474764a4.747636 4.747636 0 0 0-1.405673-1.349818 9.234618 9.234618 0 0 0-1.396364-1.163636 11.776 11.776 0 0 0-3.006836-1.7408c-0.996073-0.577164-1.796655-0.772655-2.802036-1.163637-0.605091-0.195491-1.200873-0.390982-2.010764-0.577163-0.390982 0-0.586473-0.195491-0.996073-0.195491-2.196945-0.577164-4.012218-0.577164-5.008291-0.577164h-0.400291c-0.996073 0-3.006836 0-5.408581 0.577164-0.400291 0-0.595782 0.195491-0.996073 0.195491-0.400291 0.195491-1.005382 0.195491-1.405673 0.390981a15.555491 15.555491 0 0 0-3.006836 1.163637c-0.195491 0-0.195491 0.195491-0.400291 0.195491 0 0.195491-0.195491 0.195491-0.195491 0.195491-1.200873 0.577164-2.606545 1.349818-3.611927 2.122472l-0.195491 0.195491a7.000436 7.000436 0 0 0-2.401746 1.7408l-67.314036 64.660946c-4.803491 4.449745-7.614836 10.426182-7.614836 16.7936-0.195491 6.376727 2.606545 12.744145 7.214545 17.370763s10.826473 7.335564 17.435927 7.335564 13.218909-2.513455 18.031709-7.149382l24.641164-23.738182v266.267928c0 13.312 11.226764 24.129164 25.041455 24.129163s25.041455-10.817164 25.041454-24.129163V532.452073l26.046836 24.520145c4.608 4.626618 10.817164 6.953891 17.640728 6.953891 6.795636 0 13.014109-2.513455 17.836218-7.149382l0.186182-0.195491c9.616291-9.644218 9.4208-24.510836-0.400291-33.773381l-0.223418-0.186182z" fill="#2c2c2c" p-id="8914"></path></svg>
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
@@ -71,6 +71,11 @@ export default {
|
||||
height: calc(100vh - 50px);
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
|
||||
.el-alert {
|
||||
margin-top: -10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.go-back {
|
||||
|
@@ -8,6 +8,8 @@ import orgUtil from '@/utils/org'
|
||||
import orgs from '@/api/orgs'
|
||||
import { getPropView, isViewHasOrgs } from '@/utils/jms'
|
||||
import request from '@/utils/request'
|
||||
import i18n from '@/i18n/i18n'
|
||||
import { MessageBox } from 'element-ui'
|
||||
|
||||
const whiteList = ['/login', process.env.VUE_APP_LOGIN_PATH] // no redirect whitelist
|
||||
|
||||
@@ -39,12 +41,30 @@ async function checkLogin({ to, from, next }) {
|
||||
return reject('No session mark found in cookie')
|
||||
} else if (sessionExpire === 'close') {
|
||||
let startTime = new Date().getTime()
|
||||
this.newLoginHasOpen = false
|
||||
const intervalId = setInterval(() => {
|
||||
const endTime = new Date().getTime()
|
||||
const delta = (endTime - startTime)
|
||||
startTime = endTime
|
||||
Vue.$log.debug('Set session expire: ', delta)
|
||||
if (!isRenewalExpired(120)) {
|
||||
const currentTimeStamp = Math.floor(endTime / 1000)
|
||||
const sessionExpireTimestamp = VueCookie.get('jms_session_expire_timestamp')
|
||||
if (currentTimeStamp >= parseInt(sessionExpireTimestamp, 10)) {
|
||||
if (!this.newLoginHasOpen) {
|
||||
this.newLoginHasOpen = true
|
||||
MessageBox.confirm(
|
||||
i18n.t('auth.LoginRequiredMsg'),
|
||||
i18n.t('common.Info'),
|
||||
{
|
||||
confirmButtonText: i18n.t('auth.ReLogin'),
|
||||
cancelButtonText: i18n.t('common.Cancel'),
|
||||
type: 'warning'
|
||||
}).finally(() => {
|
||||
window.location = '/core/auth/logout/'
|
||||
clearInterval(intervalId)
|
||||
})
|
||||
}
|
||||
} else if (!isRenewalExpired(120)) {
|
||||
VueCookie.set('jms_session_expire', 'close', { expires: '2m' })
|
||||
} else {
|
||||
clearInterval(intervalId)
|
||||
|
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<GenericListTable :table-config="tableConfig" :header-actions="headerActions" />
|
||||
<GenericListTable :header-actions="headerActions" :table-config="tableConfig" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
@@ -110,7 +110,7 @@ export default {
|
||||
hasSearch: true,
|
||||
hasRefresh: true,
|
||||
hasRightActions: true,
|
||||
hasLeftActions: true,
|
||||
hasLeftActions: false,
|
||||
hasMoreActions: false,
|
||||
hasExport: false,
|
||||
hasImport: false,
|
||||
|
@@ -59,7 +59,7 @@ export default {
|
||||
[this.$t('common.Basic'), ['name', 'address', 'platform', 'nodes']],
|
||||
[this.$t('assets.Protocol'), ['protocols']],
|
||||
[this.$t('assets.Account'), ['accounts']],
|
||||
[this.$t('common.Other'), ['domain', 'is_active', 'comment']]
|
||||
[this.$t('common.Other'), ['domain', 'labels', 'is_active', 'comment']]
|
||||
],
|
||||
fieldsMeta: assetFieldsMeta(this),
|
||||
performSubmit(validValues) {
|
||||
|
@@ -97,8 +97,13 @@ export default {
|
||||
route.query.type = row.type.value
|
||||
route.query.category = row.type.category
|
||||
}
|
||||
const { href } = vm.$router.resolve(route)
|
||||
window.open(href, '_blank')
|
||||
const createInNewPage = this.$route.query.node_id && routeAction === 'Create'
|
||||
if (createInNewPage) {
|
||||
const { href } = vm.$router.resolve(route)
|
||||
window.open(href, '_blank')
|
||||
} else {
|
||||
this.$router.push(route)
|
||||
}
|
||||
}
|
||||
const extraQuery = this.$route.params?.extraQuery || {}
|
||||
return {
|
||||
|
@@ -160,8 +160,12 @@ export default {
|
||||
}
|
||||
|
||||
const router = { name: route, query }
|
||||
const { href } = this.$router.resolve(router)
|
||||
window.open(href, '_blank')
|
||||
if (this.$route.query.node_id) {
|
||||
const { href } = this.$router.resolve(router)
|
||||
window.open(href, '_blank')
|
||||
} else {
|
||||
this.$router.push(router)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -5,7 +5,6 @@
|
||||
<script>
|
||||
import { GenericListPage } from '@/layout/components'
|
||||
import { DetailFormatter } from '@/components/Table/TableFormatters'
|
||||
import AmountFormatter from '@/components/Table/TableFormatters/AmountFormatter.vue'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
@@ -17,20 +16,16 @@ export default {
|
||||
url: '/api/v1/assets/domains/',
|
||||
columnsExclude: ['gateway'],
|
||||
columnsExtra: ['gateway_count'],
|
||||
columns: ['name', 'assets_amount', 'gateway_count', 'comment', 'actions'],
|
||||
columnsShow: {
|
||||
min: ['name', 'actions'],
|
||||
default: ['name', 'assets', 'gateway_count', 'comment', 'actions']
|
||||
default: ['name', 'assets_amount', 'gateway_count', 'comment', 'actions']
|
||||
},
|
||||
columnsMeta: {
|
||||
assets: {
|
||||
assets_amount: {
|
||||
label: this.$t('assets.Assets'),
|
||||
width: '160px',
|
||||
formatter: AmountFormatter,
|
||||
formatterArgs: {
|
||||
routeQuery: {
|
||||
activeTab: 'GroupUser'
|
||||
}
|
||||
}
|
||||
formatter: DetailFormatter
|
||||
},
|
||||
gateway_count: {
|
||||
label: this.$t('assets.Gateway'),
|
||||
|
@@ -123,6 +123,7 @@ export const assetFieldsMeta = (vm) => {
|
||||
name: 'labels',
|
||||
label: vm.$t('assets.Label'),
|
||||
type: 'm2m',
|
||||
component: Select2,
|
||||
el: {
|
||||
multiple: true,
|
||||
url: '/api/v1/labels/labels/',
|
||||
|
@@ -19,8 +19,8 @@ export default {
|
||||
data() {
|
||||
return {
|
||||
config: {
|
||||
title: this.$t('dashboard.UserLoginTrend'),
|
||||
tip: this.$t('dashboard.UserLoginTrend')
|
||||
title: this.$t('dashboard.SessionConnectTrend'),
|
||||
tip: this.$t('dashboard.SessionConnectTrend')
|
||||
},
|
||||
columnChartConfig: {
|
||||
datesMetrics: [],
|
||||
|
@@ -33,7 +33,7 @@ export default {
|
||||
{
|
||||
prop: 'total',
|
||||
label: this.$t('dashboard.LoginCount'),
|
||||
width: '80px'
|
||||
width: '120px'
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -50,7 +50,7 @@ export default {
|
||||
{
|
||||
prop: 'total',
|
||||
label: this.$t('dashboard.NumberOfVisits'),
|
||||
width: '80px'
|
||||
width: '140px'
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@@ -28,7 +28,7 @@ export default {
|
||||
lineChartConfig: {
|
||||
datesMetrics: [],
|
||||
primaryData: [0],
|
||||
primaryName: this.$t('dashboard.LoginUsers'),
|
||||
primaryName: this.$t('dashboard.ActiveUsers'),
|
||||
secondaryData: [0],
|
||||
secondaryName: this.$t('dashboard.LoginAssets')
|
||||
}
|
||||
|
@@ -9,7 +9,7 @@
|
||||
class="table"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-table-column :label="$tc('dashboard.ranking')" width="60px">
|
||||
<el-table-column :label="$tc('dashboard.ranking')" width="90px">
|
||||
<template v-slot="scope">
|
||||
<span>{{ scope.$index + 1 }}</span>
|
||||
</template>
|
||||
|
@@ -44,7 +44,7 @@ export default {
|
||||
}
|
||||
},
|
||||
{
|
||||
title: this.$t('dashboard.CurrentConnections'),
|
||||
title: this.$t('dashboard.CurrentConnectionUsers'),
|
||||
body: {
|
||||
route: { name: `SessionList`, params: { activeMenu: 'OnlineList' }},
|
||||
count: this.counter.total_count_online_users,
|
||||
|
@@ -51,7 +51,7 @@ export default {
|
||||
fontSize: 24,
|
||||
color: '#646A73'
|
||||
},
|
||||
subtext: this.$t('dashboard.Proportion') + percentage + '%',
|
||||
subtext: this.$t('dashboard.Proportion') + ' ' + percentage + '%',
|
||||
subtextStyle: {
|
||||
fontSize: 12,
|
||||
color: '#646A73'
|
||||
|
@@ -121,8 +121,10 @@ export default {
|
||||
}
|
||||
const url = `/api/v1/labels/labels/${this.label.id}/resource-types/${this.select2.value}/resources/`
|
||||
this.$axios.put(url, data).then(res => {
|
||||
this.$message.success(this.$t('common.BindSuccess'))
|
||||
this.$emit('confirm')
|
||||
setTimeout(() => {
|
||||
this.$message.success(this.$tc('common.BindSuccess'))
|
||||
this.$emit('bind-success')
|
||||
}, 100)
|
||||
})
|
||||
},
|
||||
async getResourceTypes() {
|
||||
|
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div>
|
||||
<GenericListPage ref="GenericListPage" :header-actions="headerActions" :table-config="tableConfig" />
|
||||
<BindDialog v-if="bindVisible" :label="label" :visible.sync="bindVisible" @confirm="handleDialogConfirm" />
|
||||
<BindDialog v-if="bindVisible" :label="label" :visible.sync="bindVisible" @bind-success="handleDialogConfirm" />
|
||||
<LabelResourcesDialog
|
||||
v-if="resDialogVisible"
|
||||
:label="label"
|
||||
|
@@ -40,8 +40,12 @@ export default {
|
||||
}
|
||||
},
|
||||
headerActions: {
|
||||
hasImport: false,
|
||||
onCreate: () => {
|
||||
this.$emit('addResource')
|
||||
},
|
||||
searchConfig: {
|
||||
getUrlQuery: false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -76,7 +76,11 @@ export default {
|
||||
required: false
|
||||
}],
|
||||
el: {
|
||||
value: []
|
||||
value: [],
|
||||
treeSetting: {
|
||||
showSearch: false,
|
||||
showRefresh: false
|
||||
}
|
||||
}
|
||||
},
|
||||
nodes: {
|
||||
|
@@ -21,6 +21,7 @@ import PermBulkUpdateDialog from './components/PermBulkUpdateDialog'
|
||||
import AmountFormatter from '@/components/Table/TableFormatters/AmountFormatter'
|
||||
import { mapGetters } from 'vuex'
|
||||
import { AccountLabelMapper, AssetPermissionListPageSearchConfigOptions } from '../const'
|
||||
import { DetailFormatter } from '@/components/Table/TableFormatters'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
@@ -44,11 +45,15 @@ export default {
|
||||
url: '/api/v1/perms/asset-permissions/',
|
||||
hasTree: true,
|
||||
columnsExtra: ['action'],
|
||||
columns: [
|
||||
'name', 'users_amount', 'user_groups_amount', 'assets_amount', 'nodes_amount',
|
||||
'accounts', 'is_expired', 'from_ticket', 'actions'
|
||||
],
|
||||
columnsShow: {
|
||||
min: ['name', 'actions'],
|
||||
default: [
|
||||
'name', 'users', 'user_groups', 'assets',
|
||||
'nodes', 'accounts', 'is_valid', 'actions'
|
||||
'name', 'users_amount', 'user_groups_amount', 'assets_amount',
|
||||
'nodes_amount', 'accounts', 'is_valid', 'actions'
|
||||
]
|
||||
},
|
||||
columnsMeta: {
|
||||
@@ -82,40 +87,40 @@ export default {
|
||||
showFalse: false
|
||||
}
|
||||
},
|
||||
users: {
|
||||
users_amount: {
|
||||
label: this.$t('perms.User'),
|
||||
width: '60px',
|
||||
formatter: AmountFormatter,
|
||||
formatter: DetailFormatter,
|
||||
formatterArgs: {
|
||||
routeQuery: {
|
||||
activeTab: 'AssetPermissionUser'
|
||||
}
|
||||
}
|
||||
},
|
||||
user_groups: {
|
||||
user_groups_amount: {
|
||||
label: this.$t('perms.UserGroups'),
|
||||
width: '100px',
|
||||
formatter: AmountFormatter,
|
||||
formatter: DetailFormatter,
|
||||
formatterArgs: {
|
||||
routeQuery: {
|
||||
activeTab: 'AssetPermissionUser'
|
||||
}
|
||||
}
|
||||
},
|
||||
assets: {
|
||||
assets_amount: {
|
||||
label: this.$t('perms.Asset'),
|
||||
width: '60px',
|
||||
formatter: AmountFormatter,
|
||||
formatter: DetailFormatter,
|
||||
formatterArgs: {
|
||||
routeQuery: {
|
||||
activeTab: 'AssetPermissionAsset'
|
||||
}
|
||||
}
|
||||
},
|
||||
nodes: {
|
||||
nodes_amount: {
|
||||
label: this.$t('perms.Node'),
|
||||
width: '60px',
|
||||
formatter: AmountFormatter,
|
||||
formatter: DetailFormatter,
|
||||
formatterArgs: {
|
||||
routeQuery: {
|
||||
activeTab: 'AssetPermissionAsset'
|
||||
@@ -152,11 +157,17 @@ export default {
|
||||
headerActions: {
|
||||
hasLabelSearch: true,
|
||||
hasBulkDelete: true,
|
||||
createRoute() {
|
||||
return {
|
||||
onCreate: () => {
|
||||
const route = {
|
||||
name: 'AssetPermissionCreate',
|
||||
query: this.$route.query
|
||||
}
|
||||
if (vm.$route.query.node_id) {
|
||||
const { href } = this.$router.resolve(route)
|
||||
window.open(href, '_blank')
|
||||
} else {
|
||||
this.$router.push(route)
|
||||
}
|
||||
},
|
||||
handleImportClick: ({ selectedRows }) => {
|
||||
this.$eventBus.$emit('showImportDialog', {
|
||||
@@ -164,7 +175,6 @@ export default {
|
||||
url: '/api/v1/perms/asset-permissions/'
|
||||
})
|
||||
},
|
||||
createInNewPage: true,
|
||||
searchConfig: {
|
||||
url: '',
|
||||
options: AssetPermissionListPageSearchConfigOptions
|
||||
|
@@ -34,7 +34,7 @@ export default {
|
||||
settings: {
|
||||
visible: false,
|
||||
url: '/api/v1/settings/setting/?category=ldap',
|
||||
fields: ['AUTH_LDAP_SYNC_ORG_IDS', 'AUTH_LDAP_SYNC_IS_PERIODIC', 'AUTH_LDAP_SYNC_CRONTAB', 'AUTH_LDAP_SYNC_INTERVAL'],
|
||||
fields: ['AUTH_LDAP_SYNC_ORG_IDS', 'AUTH_LDAP_SYNC_IS_PERIODIC', 'AUTH_LDAP_SYNC_CRONTAB', 'AUTH_LDAP_SYNC_INTERVAL', 'AUTH_LDAP_SYNC_RECEIVERS'],
|
||||
fieldsMeta: {
|
||||
AUTH_LDAP_SYNC_ORG_IDS: {
|
||||
component: Select2,
|
||||
@@ -63,6 +63,20 @@ export default {
|
||||
AUTH_LDAP_SYNC_INTERVAL: {
|
||||
rules: [Required],
|
||||
helpText: this.$t('xpack.HelpText.IntervalOfCreateUpdatePage')
|
||||
},
|
||||
AUTH_LDAP_SYNC_RECEIVERS: {
|
||||
component: Select2,
|
||||
label: this.$t('accounts.AccountChangeSecret.Addressee'),
|
||||
el: {
|
||||
value: [],
|
||||
multiple: true,
|
||||
ajax: {
|
||||
url: '/api/v1/users/users/?fields_size=mini&oid=ROOT',
|
||||
transformOption: (item) => {
|
||||
return { label: item.name + '(' + item.username + ')', value: item.id }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
submitMethod: () => 'patch'
|
||||
|
@@ -60,8 +60,8 @@ export default {
|
||||
],
|
||||
encryptedFields: ['VAULT_HCP_TOKEN'],
|
||||
fields: [
|
||||
[
|
||||
this.$t('setting.AccountStorage'),
|
||||
[this.$t('common.Basic'), ['HISTORY_ACCOUNT_CLEAN_LIMIT']],
|
||||
[this.$t('setting.AccountStorage'),
|
||||
[
|
||||
'VAULT_ENABLED',
|
||||
'VAULT_HCP_HOST',
|
||||
@@ -71,6 +71,11 @@ export default {
|
||||
]
|
||||
],
|
||||
fieldsMeta: {
|
||||
HISTORY_ACCOUNT_CLEAN_LIMIT: {
|
||||
el: {
|
||||
autocomplete: 'new-password'
|
||||
}
|
||||
},
|
||||
VAULT_ENABLED: {
|
||||
disabled: true,
|
||||
label: this.$t('setting.EnableVaultStorage')
|
||||
|
@@ -38,7 +38,7 @@ export default {
|
||||
{
|
||||
title: this.$t('setting.AccountStorage'),
|
||||
name: 'Vault',
|
||||
hidden: !this.$hasPerm('settings.change_vault') || !this.$store.getters.hasValidLicense
|
||||
hidden: !this.$store.getters.hasValidLicense
|
||||
},
|
||||
{
|
||||
title: this.$t('setting.ChatAI'),
|
||||
|
@@ -36,19 +36,16 @@ export default {
|
||||
[
|
||||
this.$t('common.BasicInfo'),
|
||||
[
|
||||
'EMAIL_HOST', 'EMAIL_PORT', 'EMAIL_HOST_USER',
|
||||
'EMAIL_HOST_PASSWORD'
|
||||
]
|
||||
],
|
||||
[
|
||||
this.$t('setting.Security'),
|
||||
[
|
||||
'EMAIL_USE_SSL', 'EMAIL_USE_TLS'
|
||||
'EMAIL_PROTOCOL', 'EMAIL_HOST', 'EMAIL_PORT', 'EMAIL_HOST_USER',
|
||||
'EMAIL_HOST_PASSWORD', 'EMAIL_USE_SSL', 'EMAIL_USE_TLS'
|
||||
]
|
||||
]
|
||||
],
|
||||
successUrl: { name: 'Settings', params: { activeMenu: 'EmailContent' }},
|
||||
fieldsMeta: {
|
||||
EMAIL_PORT: {
|
||||
hidden: (formValue) => formValue.EMAIL_PROTOCOL !== 'smtp'
|
||||
},
|
||||
EMAIL_HOST_PASSWORD: {
|
||||
component: UpdateToken
|
||||
},
|
||||
@@ -57,6 +54,12 @@ export default {
|
||||
type: 'textarea',
|
||||
rows: 3
|
||||
}
|
||||
},
|
||||
EMAIL_USE_SSL: {
|
||||
hidden: (formValue) => formValue.EMAIL_PROTOCOL !== 'smtp'
|
||||
},
|
||||
EMAIL_USE_TLS: {
|
||||
hidden: (formValue) => formValue.EMAIL_PROTOCOL !== 'smtp'
|
||||
}
|
||||
},
|
||||
url: '/api/v1/settings/setting/?category=email',
|
||||
@@ -75,6 +78,9 @@ export default {
|
||||
if (data['EMAIL_USE_TLS'] === null) {
|
||||
delete data['EMAIL_USE_TLS']
|
||||
}
|
||||
if (data['EMAIL_PORT'] === null) {
|
||||
delete data['EMAIL_PORT']
|
||||
}
|
||||
return data
|
||||
}
|
||||
}
|
||||
|
@@ -4,7 +4,7 @@
|
||||
|
||||
<script>
|
||||
import { GenericListPage } from '@/layout/components'
|
||||
import AmountFormatter from '@/components/Table/TableFormatters/AmountFormatter.vue'
|
||||
import { DetailFormatter } from '@/components/Table/TableFormatters'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
@@ -14,25 +14,27 @@ export default {
|
||||
return {
|
||||
tableConfig: {
|
||||
url: '/api/v1/users/groups/',
|
||||
columns: ['name', 'users_amount', 'comment', 'actions'],
|
||||
columnsShow: {
|
||||
default: ['name', 'users', 'comment', 'actions'],
|
||||
default: ['name', 'users_amount', 'comment', 'actions'],
|
||||
min: ['name', 'action']
|
||||
},
|
||||
columnsMeta: {
|
||||
users_amount: {
|
||||
label: this.$t('users.Users'),
|
||||
width: '120px'
|
||||
},
|
||||
users: {
|
||||
label: this.$t('perms.User'),
|
||||
width: '160px',
|
||||
formatter: AmountFormatter,
|
||||
width: '120px',
|
||||
formatter: DetailFormatter,
|
||||
formatterArgs: {
|
||||
getItem(item) {
|
||||
return item.is_service_account ? null : item.name
|
||||
},
|
||||
routeQuery: {
|
||||
activeTab: 'GroupUser'
|
||||
getRoute({ row }) {
|
||||
return {
|
||||
name: 'UserGroupDetail',
|
||||
params: {
|
||||
id: row.id
|
||||
},
|
||||
query: {
|
||||
activeTab: 'GroupUser'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user