Merge remote-tracking branch 'origin/main'

This commit is contained in:
wangjiahao
2025-07-23 18:07:43 +08:00
19 changed files with 264 additions and 179 deletions
+1 -1
View File
@@ -341,7 +341,7 @@
"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?",
"confirm_to_delete": "After the data source is deleted, the related questions can no longer be asked and the charts in the dashboard cannot be displayed normally. Please operate with caution!",
"id_account_to_add": "Search user ID/account to add",
"find_user": "Find user",
"add_successfully": "Add successfully",
+1 -1
View File
@@ -354,7 +354,7 @@
"there_are": "有 ",
"2_dashboards": "{msg} 个仪表板",
"smart_data_centers": "{msg} 个智能问数",
"confirm_to_delete": "正在使用此数据源,删除后会导致这些资源无法正常使用,确认删除?",
"confirm_to_delete": "数据源删除后,相关的问数不可继续提问,仪表板中的图表无法正常显示,请谨慎操作!",
"id_account_to_add": "搜索用户ID/账号添加",
"find_user": "查找用户",
"add_successfully": "添加成功",
+31 -1
View File
@@ -308,6 +308,36 @@ class HttpService {
}
public loadRemoteScript(url: string, id?: string, cb?: any): Promise<HTMLElement> {
if (!url) {
return Promise.reject(new Error('URL is required to load remote script'))
}
if (id && document.getElementById(id)) {
return Promise.resolve(document.getElementById(id) as HTMLElement)
}
if (url.startsWith('/')) {
const real_url = import.meta.env.VITE_API_BASE_URL.replace('/api/v1', '')
url = real_url + url
}
return new Promise<HTMLElement>((resolve, reject) => {
// 改用传统的script标签加载方式
const script = document.createElement('script')
script.src = url
script.id = id || `remote-script-${Date.now()}`
script.onload = () => {
if (cb) cb()
resolve(script)
}
script.onerror = (error) => {
console.error(`Failed to load script from ${url}:`, error)
reject(new Error(`Failed to load script from ${url}`))
}
document.head.appendChild(script)
})
}
/* public loadRemoteScript(url: string, id?: string, cb?: any): Promise<HTMLElement> {
if (!url) {
return Promise.reject(new Error('URL is required to load remote script'))
}
@@ -337,7 +367,7 @@ class HttpService {
reject(new Error(`Failed to load script from ${url}: ${error.message}`))
})
})
}
} */
}
// Create singleton instance
+3 -2
View File
@@ -57,11 +57,11 @@ const onClickOutside = () => {
<div class="name-icon">
<img :src="icon" width="32px" height="32px" />
<div class="info">
<div class="name">{{ name }}</div>
<div :title="name" class="name ellipsis">{{ name }}</div>
<div class="type">{{ typeName }}</div>
</div>
</div>
<div class="type-value">
<div :title="description" class="type-value">
{{ description }}
</div>
@@ -140,6 +140,7 @@ const onClickOutside = () => {
font-weight: 500;
font-size: 16px;
line-height: 24px;
max-width: 250px;
}
.type {
font-weight: 400;
+61 -18
View File
@@ -58,7 +58,7 @@ const keywords = ref('')
const tableListWithSearch = computed(() => {
if (!keywords.value) return tableList.value
return tableList.value.filter((ele) =>
ele.name.toLowerCase().includes(keywords.value.toLowerCase())
ele.table_name.toLowerCase().includes(keywords.value.toLowerCase())
)
})
const total = ref(1000)
@@ -181,6 +181,31 @@ const emits = defineEmits(['back', 'refresh'])
const back = () => {
emits('back')
}
const btnSelectClick = (val: any) => {
btnSelect.value = val
loading.value = true
if (val === 'd') {
datasourceApi
.fieldList(currentTable.value.id)
.then((res) => {
fieldList.value = res
})
.finally(() => {
loading.value = false
})
} else {
datasourceApi
.previewData(props.info.id, buildData())
.then((res) => {
previewData.value = res
})
.finally(() => {
loading.value = false
})
}
}
</script>
<template>
@@ -217,24 +242,26 @@ const back = () => {
</el-input>
<div v-loading="initLoading" class="list-content">
<div
v-for="ele in tableListWithSearch"
:key="ele.table_name"
class="model"
:class="currentTable.table_name === ele.table_name && 'isActive'"
:title="ele.table_name"
@click="clickTable(ele)"
>
<el-icon size="16">
<icon_form_outlined></icon_form_outlined>
</el-icon>
<span class="name">{{ ele.table_name }}</span>
</div>
<el-scrollbar v-if="tableListWithSearch.length">
<div
v-for="ele in tableListWithSearch"
:key="ele.table_name"
class="model"
:class="currentTable.table_name === ele.table_name && 'isActive'"
:title="ele.table_name"
@click="clickTable(ele)"
>
<el-icon size="16">
<icon_form_outlined></icon_form_outlined>
</el-icon>
<span class="name">{{ ele.table_name }}</span>
</div>
</el-scrollbar>
<EmptyBackground
v-if="!!keywords && !tableListWithSearch.length"
:description="$t('datasource.relevant_content_found')"
img-type="tree"
style="width: 100%; margin-top: 100px"
style="width: 100%"
/>
<div v-else-if="!initLoading && !tableListWithSearch.length" class="no-data">
<div class="no-data-msg">
@@ -264,10 +291,18 @@ const back = () => {
</div>
<div class="table-content">
<div class="btn-select">
<el-button :class="[btnSelect === 'd' && 'is-active']" text @click="btnSelect = 'd'">
<el-button
:class="[btnSelect === 'd' && 'is-active']"
text
@click="btnSelectClick('d')"
>
{{ t('ds.table_schema') }}
</el-button>
<el-button :class="[btnSelect === 'q' && 'is-active']" text @click="btnSelect = 'q'">
<el-button
:class="[btnSelect === 'q' && 'is-active']"
text
@click="btnSelectClick('q')"
>
{{ t('ds.preview') }}
</el-button>
</div>
@@ -312,7 +347,7 @@ const back = () => {
<div class="preview-num">
{{ t('ds.pieces_in_total', { msg: total, ms: showNum }) }}
</div>
<el-table :data="previewData.data" style="width: 100%; height: 600px">
<el-table :data="previewData.data" style="width: 100%">
<el-table-column
v-for="(c, index) in previewData.fields"
:key="index"
@@ -431,6 +466,14 @@ const back = () => {
.list-content {
height: calc(100% - 100px);
.no-result {
margin-top: 72px;
font-weight: 400;
font-size: 14px;
line-height: 22px;
text-align: center;
color: #646a73;
}
.model {
width: 100%;
height: 32px;
-10
View File
@@ -19,13 +19,6 @@ defineProps({
})
const emits = defineEmits(['panelClick', 'smartClick'])
const panelClick = () => {
emits('panelClick')
}
const smartClick = () => {
emits('smartClick')
}
</script>
<template>
@@ -34,9 +27,6 @@ const smartClick = () => {
{{ 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>
+1 -1
View File
@@ -714,7 +714,7 @@ const saveHandler = () => {
</el-select>
</el-form-item>
<el-form-item class="private-list_form" prop="private_list">
<el-form-item class="private-list_form">
<template #label>
<div class="private-list">
{{ t('embedded.set_data_source') }}
+23 -22
View File
@@ -70,7 +70,7 @@ const deleteBatchUser = () => {
})
}
const deleteHandler = (row: any) => {
if (row.weight === 1) return
if (row.weight === 1 && +userStore.getUid !== 1) return
ElMessageBox.confirm(t('workspace.member_feng_yibudao', { msg: row.name }), {
confirmButtonType: 'danger',
confirmButtonText: t('dashboard.delete'),
@@ -177,6 +177,7 @@ const addWorkspace = () => {
}
const handleSizeChange = (val: number) => {
pageInfo.currentPage = 1
pageInfo.pageSize = val
search()
}
@@ -261,7 +262,7 @@ const handleCurrentChange = (val: number) => {
>
<el-icon
class="action-btn"
:class="scope.row.weight === 1 && 'not-allow'"
:class="+userStore.getUid !== 1 && scope.row.weight === 1 && 'not-allow'"
size="16"
@click="deleteHandler(scope.row)"
>
@@ -286,18 +287,18 @@ const handleCurrentChange = (val: number) => {
</template>
</el-table>
</div>
<div class="pagination-container">
<el-pagination
v-model:current-page="pageInfo.currentPage"
v-model:page-size="pageInfo.pageSize"
:page-sizes="[10, 20, 30]"
:background="true"
layout="total, sizes, prev, pager, next, jumper"
:total="pageInfo.total"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
/>
</div>
</div>
<div class="pagination-container">
<el-pagination
v-model:current-page="pageInfo.currentPage"
v-model:page-size="pageInfo.pageSize"
:page-sizes="[10, 20, 30]"
:background="true"
layout="total, sizes, prev, pager, next, jumper"
:total="pageInfo.total"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
/>
</div>
<div v-if="multipleSelectionAll.length" class="bottom-select">
<el-checkbox
@@ -369,15 +370,15 @@ const handleCurrentChange = (val: number) => {
line-height: 28px;
}
}
.pagination-container {
display: flex;
justify-content: end;
align-items: center;
margin-top: 16px;
}
.table-content {
height: calc(100% - 104px);
.pagination-container {
display: flex;
justify-content: end;
align-items: center;
margin-top: 16px;
}
max-height: calc(100% - 104px);
overflow-y: auto;
.preview-or-schema {
.user-status-container {
+2 -1
View File
@@ -256,7 +256,7 @@ const submit = (item: any) => {
@click="handleDefaultModelChange(ele)"
>
<img :src="ele.supplier_item.icon" width="24px" height="24px" />
<div class="model-name" v-html="formatKeywords(ele.name)"></div>
<div class="model-name ellipsis" v-html="formatKeywords(ele.name)"></div>
<el-icon size="16" class="done">
<icon_done_outlined></icon_done_outlined>
</el-icon>
@@ -420,6 +420,7 @@ const submit = (item: any) => {
font-weight: 400;
font-size: 14px;
line-height: 22px;
max-width: 220px;
}
.done {
+7 -1
View File
@@ -66,7 +66,12 @@
<el-table-column prop="email" show-overflow-tooltip :label="$t('user.email')" />
<!-- <el-table-column prop="phone" :label="$t('user.phone_number')" width="280" /> -->
<!-- <el-table-column prop="user_source" :label="$t('user.user_source')" width="280" /> -->
<el-table-column prop="oid_list" :label="$t('user.workspace')" width="280">
<el-table-column
show-overflow-tooltip
prop="oid_list"
:label="$t('user.workspace')"
width="280"
>
<template #default="scope">
<span>{{ formatSpaceName(scope.row.oid_list) }}</span>
</template>
@@ -671,6 +676,7 @@ const saveHandler = () => {
}
const handleSizeChange = (val: number) => {
state.pageInfo.pageSize = val
state.pageInfo.currentPage = 1
search()
}
const handleCurrentChange = (val: number) => {
+1
View File
@@ -238,6 +238,7 @@ const saveHandler = () => {
}
}
const handleSizeChange = (val: number) => {
state.pageInfo.currentPage = 1
state.pageInfo.pageSize = val
search()
}
@@ -171,6 +171,10 @@ defineExpose({
margin-bottom: 8px;
}
.ed-checkbox {
margin-right: 0;
}
.mt-16 {
margin-top: 16px;
}
@@ -269,6 +269,7 @@ const addWorkspace = (row: any) => {
const handleSizeChange = (val: number) => {
pageInfo.pageSize = val
pageInfo.currentPage = 1
search()
}
const handleCurrentChange = (val: number) => {