feat(user): user manage

This commit is contained in:
dataeaseShu
2025-07-16 11:01:37 +08:00
parent 2966dc5e82
commit da10a49c16
11 changed files with 210 additions and 56 deletions
@@ -4,12 +4,12 @@
<path d="M11.5556 11.1111C11.5556 13.5657 13.5454 15.5556 16 15.5556C18.4546 15.5556 20.4444 13.5657 20.4444 11.1111C20.4444 8.65653 18.4546 6.66669 16 6.66669C13.5454 6.66669 11.5556 8.65653 11.5556 11.1111Z" fill="url(#paint1_linear_477_6741)"/>
<defs>
<linearGradient id="paint0_linear_477_6741" x1="16" y1="6.66669" x2="16" y2="24.8889" gradientUnits="userSpaceOnUse">
<stop stop-color="white"/>
<stop offset="1" stop-color="white" stop-opacity="0"/>
<stop stop-color="#ffffff"/>
<stop offset="1" stop-color="#ffffff" stop-opacity="0"/>
</linearGradient>
<linearGradient id="paint1_linear_477_6741" x1="16" y1="6.66669" x2="16" y2="24.8889" gradientUnits="userSpaceOnUse">
<stop stop-color="white"/>
<stop offset="1" stop-color="white" stop-opacity="0"/>
<stop stop-color="#ffffff"/>
<stop offset="1" stop-color="#ffffff" stop-opacity="0"/>
</linearGradient>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

+11 -4
View File
@@ -9,12 +9,21 @@ import icon_moments_categories_outlined from '@/assets/svg/icon_moments-categori
import icon_side_fold_outlined from '@/assets/svg/icon_side-fold_outlined.svg'
import icon_side_expand_outlined from '@/assets/svg/icon_side-expand_outlined.svg'
import { useRouter } from 'vue-router'
import { useEmitt } from '@/utils/useEmitt'
const router = useRouter()
const collapse = ref(false)
const handleCollapseChange = (val: any = true) => {
collapse.value = val
}
useEmitt({
name: 'collapse-change',
callback: handleCollapseChange,
})
const handleFoldExpand = () => {
collapse.value = !collapse.value
}
const toWorkspace = () => {
router.push('/')
}
@@ -32,7 +41,7 @@ const toWorkspace = () => {
<el-icon size="16">
<icon_moments_categories_outlined></icon_moments_categories_outlined>
</el-icon>
{{ collapse ? '' : '返回工作空间' }}
{{ collapse ? '' : $t('workspace.return_to_workspace') }}
</div>
<div class="personal-info">
<Person :collapse="collapse"></Person>
@@ -82,8 +91,6 @@ const toWorkspace = () => {
line-height: 22px;
width: calc(100% - 32px);
.back-to_workspace {
background-color: #1f23290a;
border: 1px solid #d0d3d6;
display: flex;
align-items: center;
justify-content: center;
+33 -22
View File
@@ -1,6 +1,6 @@
<script lang="ts" setup>
import { ref } from 'vue'
import Default_avatar from '@/assets/svg/icon-member-default.svg'
import Default_avatar from '@/assets/workspace/default_avatar.png'
import icon_admin_outlined from '@/assets/svg/icon_admin_outlined.svg'
import icon_maybe_outlined from '@/assets/svg/icon-maybe_outlined.svg'
import icon_key_outlined from '@/assets/svg/icon-key_outlined.svg'
@@ -8,11 +8,13 @@ import icon_translate_outlined from '@/assets/svg/icon_translate_outlined.svg'
import icon_logout_outlined from '@/assets/svg/icon_logout_outlined.svg'
import icon_right_outlined from '@/assets/svg/icon_right_outlined.svg'
import icon_done_outlined from '@/assets/svg/icon_done_outlined.svg'
import { useI18n } from 'vue-i18n'
defineProps({
collapse: { type: [Boolean], required: true },
})
const { t } = useI18n()
const name = ref('飞小致')
const currentLanguage = ref('zh-CN')
const emit = defineEmits(['selectPerson'])
@@ -22,11 +24,11 @@ const languageList = [
value: 'en',
},
{
name: '简体中文',
name: t('common.simplified_chinese'),
value: 'zh-CN',
},
{
name: '繁體中文',
name: t('common.traditional_chinese'),
value: 'zh-CN',
},
]
@@ -43,18 +45,14 @@ const handleDefaultLanguageChange = (item: any) => {
<el-popover popper-class="system-person" :placement="collapse ? 'right' : 'top'">
<template #reference>
<button class="person" :class="collapse && 'collapse'">
<el-icon size="32" class="default-avatar">
<Default_avatar></Default_avatar>
</el-icon>
<img class="default-avatar" :src="Default_avatar" width="32px" height="32px" />
<span v-if="!collapse" class="name">{{ name }}</span>
</button></template
>
<div class="popover">
<div class="popover-content">
<div class="info">
<el-icon style="transform: scale(1.25)" size="32">
<Default_avatar></Default_avatar>
</el-icon>
<img :src="Default_avatar" width="40px" height="40px" />
<div class="top">{{ name }}</div>
<div class="bottom">feixaozhi</div>
</div>
@@ -62,13 +60,13 @@ const handleDefaultLanguageChange = (item: any) => {
<el-icon size="16">
<icon_admin_outlined></icon_admin_outlined>
</el-icon>
<div class="datasource-name">系统管理</div>
<div class="datasource-name">{{ $t('common.system_manage') }}</div>
</div>
<div class="popover-item">
<el-icon size="16">
<icon_key_outlined></icon_key_outlined>
</el-icon>
<div class="datasource-name">修改密码</div>
<div class="datasource-name">{{ $t('user.change_password') }}</div>
</div>
<el-popover :teleported="false" popper-class="system-language" placement="right">
<template #reference>
@@ -76,7 +74,7 @@ const handleDefaultLanguageChange = (item: any) => {
<el-icon size="16">
<icon_translate_outlined></icon_translate_outlined>
</el-icon>
<div class="datasource-name">语言</div>
<div class="datasource-name">{{ $t('common.language') }}</div>
<el-icon style="transform: scale(1.33)" class="right" size="16">
<icon_right_outlined></icon_right_outlined>
</el-icon>
@@ -102,13 +100,13 @@ const handleDefaultLanguageChange = (item: any) => {
<el-icon size="16">
<icon_maybe_outlined></icon_maybe_outlined>
</el-icon>
<div class="datasource-name">帮助</div>
<div class="datasource-name">{{ $t('common.help') }}</div>
</div>
<div class="popover-item mr4">
<el-icon size="16">
<icon_logout_outlined></icon_logout_outlined>
</el-icon>
<div class="datasource-name">退出登录</div>
<div class="datasource-name">{{ $t('common.logout') }}</div>
</div>
</div>
</div>
@@ -117,7 +115,6 @@ const handleDefaultLanguageChange = (item: any) => {
<style lang="less" scoped>
.person {
border-radius: 6px;
padding: 0 8px;
display: flex;
align-items: center;
@@ -126,6 +123,7 @@ const handleDefaultLanguageChange = (item: any) => {
height: 40px;
border: none;
background-color: transparent;
position: relative;
&.collapse {
min-width: 48px;
@@ -149,15 +147,28 @@ const handleDefaultLanguageChange = (item: any) => {
margin-left: 8px;
}
&::after {
content: '';
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 100%;
height: 100%;
border-radius: 6px;
}
&:hover,
&:active {
background: #1f23291a;
border: 1px solid #1f23291a;
&:focus {
&::after {
background: #1f23291a;
}
}
&:active {
background: #1f232926;
border: 1px solid #1f23291a;
&::after {
background: #1f232926;
}
}
}
</style>
@@ -195,9 +206,9 @@ const handleDefaultLanguageChange = (item: any) => {
height: 62px;
padding: 8px;
.ed-icon {
margin: 6px 8px 0 7px;
img {
float: left;
margin: 3px 8px 0 7px;
}
.top {
@@ -103,6 +103,8 @@ const handleDefaultWorkspaceChange = (item: any) => {
&.collapse {
width: 40px;
background: none;
border: none;
}
.name {
+11 -2
View File
@@ -19,7 +19,11 @@
"logout": "Logout",
"result_count": "result",
"clear_filter": "Clear conditions",
"reset": "Reset"
"reset": "Reset",
"simplified_chinese": "Simplified Chinese",
"traditional_chinese": "Traditional Chinese",
"help": "Help",
"language": "Language"
},
"dashboard": {
"length_1_64_characters": "Name field length must be 1-64 characters",
@@ -270,7 +274,12 @@
"selected_2_people": "Selected: {msg} people",
"clear": "Clear",
"historical_dialogue": "No historical dialogue",
"rename_a_workspace" : "Rename a workspace"
"rename_a_workspace": "Rename a workspace",
"return_to_workspace": "Return to workspace",
"there_are": "There are",
"2_dashboards": "{msg} dashboards",
"smart_data_centers": "{msg} smart data centers",
"confirm_to_delete": "This data source is in use. Deleting it will cause these resources to not work properly. Confirm to delete?"
},
"chat": {
"chart_type": {
+11 -2
View File
@@ -19,7 +19,11 @@
"logout": "退出登录",
"result_count": "个结果",
"clear_filter": "清空条件",
"reset": "重置"
"reset": "重置",
"simplified_chinese": "简体中文",
"traditional_chinese": "繁體中文",
"help": "帮助",
"language": "语言"
},
"dashboard": {
"length_1_64_characters": "名称字段长度1-64个字符",
@@ -273,7 +277,12 @@
"selected_2_people": "已选:{msg} 人",
"clear": "清空",
"historical_dialogue": "暂无历史对话",
"rename_a_workspace" : "重命名工作空间"
"rename_a_workspace": "重命名工作空间",
"return_to_workspace": "返回工作空间",
"there_are": "有 ",
"2_dashboards": "{msg} 个仪表板",
"smart_data_centers": "{msg} 个智能问数",
"confirm_to_delete": "正在使用此数据源,删除后会导致这些资源无法正常使用,确认删除?"
},
"chat": {
"chart_type": {
+22 -1
View File
@@ -165,12 +165,17 @@ const changeStatus = (row: any) => {
})
})
}
const emits = defineEmits(['back'])
const back = () => {
emits('back')
}
</script>
<template>
<div class="data-table no-padding">
<div class="info">
{{ $t('ds.title') }}
<el-button text @click="back">{{ $t('ds.title') }}</el-button>
<el-icon size="12">
<icon_right_outlined></icon_right_outlined>
</el-icon>
@@ -354,8 +359,24 @@ const changeStatus = (row: any) => {
color: #646a73;
border-bottom: 1px solid #1f232926;
.ed-button {
height: 22px;
line-height: 22px;
color: #646a73;
&:hover {
background: #1cba901a;
color: #1cba90;
}
&:active {
color: #189e7a;
background: #1cba9033;
}
}
.name {
color: #1f2329;
margin-left: 4px;
}
}
.content {
+48 -21
View File
@@ -1,5 +1,5 @@
<script lang="ts" setup>
import { ref, computed, shallowRef, nextTick } from 'vue'
import { ref, computed, shallowRef, nextTick, h } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus-secondary'
import icon_searchOutline_outlined from '@/assets/svg/icon_search-outline_outlined.svg'
import arrow_down from '@/assets/svg/arrow-down.svg'
@@ -13,7 +13,9 @@ import DatasourceList from './DatasourceList.vue'
import DatasourceListSide from './DatasourceListSide.vue'
import DatasourceForm from './DatasourceForm.vue'
import { datasourceApi } from '@/api/datasource'
import { useEmitt } from '@/utils/useEmitt'
import Card from './Card.vue'
import DelMessageBox from './DelMessageBox.vue'
import { dsTypeWithImgSort } from './js/ds-type'
import { useI18n } from 'vue-i18n'
@@ -112,33 +114,53 @@ const refresh = () => {
search()
}
const panelClick = () => {
console.log('panelClick')
}
const smartClick = () => {
console.log('smartClick')
}
const deleteHandler = (item: any) => {
ElMessageBox.confirm(t('datasource.data_source', { msg: item.name }), {
ElMessageBox.confirm('', {
confirmButtonType: 'danger',
tip: t('datasource.operate_with_caution'),
confirmButtonText: t('dashboard.delete'),
cancelButtonText: t('common.cancel'),
customClass: 'confirm-no_icon',
autofocus: false,
dangerouslyUseHTMLString: true,
message: h(
DelMessageBox,
{
name: item.name,
panelNum: 1,
smartNum: 4,
onPanelClick: panelClick,
onSmartClick: smartClick,
t,
},
''
),
}).then(() => {
datasourceApi.delete(item.id).then(() => {
ElMessage({
type: 'success',
message: t('dashboard.delete_success'),
})
search()
})
})
.then(() => {
datasourceApi.delete(item.id).then(() => {
ElMessage({
type: 'success',
message: t('dashboard.delete_success'),
})
search()
})
})
.catch(() => {
ElMessageBox.confirm(t('datasource.data_source_de', { msg: item.name }), {
tip: t('datasource.cannot_be_deleted'),
cancelButtonText: t('datasource.got_it'),
showConfirmButton: false,
customClass: 'confirm-no_icon',
autofocus: false,
})
})
// .catch(() => {
// ElMessageBox.confirm(t('datasource.data_source_de', { msg: item.name }), {
// tip: t('datasource.cannot_be_deleted'),
// cancelButtonText: t('datasource.got_it'),
// showConfirmButton: false,
// customClass: 'confirm-no_icon',
// autofocus: false,
// })
// })
}
const clickDatasource = (ele: any) => {
@@ -161,8 +183,13 @@ search()
const currentDataTable = ref()
const dataTableDetail = (ele: any) => {
useEmitt().emitter.emit('collapse-change')
currentDataTable.value = ele
}
const back = () => {
currentDataTable.value = null
}
</script>
<template>
@@ -303,7 +330,7 @@ const dataTableDetail = (ele: any) => {
></DatasourceForm>
</el-drawer>
</div>
<DataTable v-if="currentDataTable" :info="currentDataTable"></DataTable>
<DataTable v-if="currentDataTable" :info="currentDataTable" @back="back"></DataTable>
</template>
<style lang="less" scoped>
+67
View File
@@ -0,0 +1,67 @@
<script lang="ts" setup>
defineProps({
name: {
type: String,
default: '-',
},
panelNum: {
type: Number,
default: 0,
},
smartNum: {
type: Number,
default: 0,
},
t: {
type: Function,
default: () => {},
},
})
const emits = defineEmits(['panelClick', 'smartClick'])
const panelClick = () => {
emits('panelClick')
}
const smartClick = () => {
emits('smartClick')
}
</script>
<template>
<div class="del-box_message">
<div class="del-title">
{{ t('datasource.data_source', { msg: name }) }}
</div>
<div class="use-panel">
{{ t('workspace.there_are') }}
<span @click="panelClick">{{ t('workspace.2_dashboards', { msg: panelNum }) }}</span
>、<span @click="smartClick">{{ t('workspace.smart_data_centers', { msg: smartNum }) }}</span>
{{ t('workspace.confirm_to_delete') }}
</div>
</div>
</template>
<style lang="less" scoped>
.del-box_message {
.del-title {
font-weight: 500;
font-size: 16px;
line-height: 24px;
}
.use-panel {
font-weight: 400;
font-size: 14px;
line-height: 22px;
margin-top: 24px;
span {
text-decoration: underline;
text-decoration-style: solid;
cursor: pointer;
color: #1cba90;
}
}
}
</style>
@@ -130,6 +130,7 @@ const supplierChang = (supplier: any) => {
modelForm.supplier = supplier.id
const config = supplier.model_config[modelForm.model_type || 0]
modelForm.api_domain = config.api_domain
modelForm.base_model = ''
if (!modelForm.id) {
modelForm.name = supplier.name
}