mirror of
https://gh-proxy.org/https://github.com/klinsmaya/SQLBot.git
synced 2026-11-08 01:06:59 +08:00
feat(user): user manage
This commit is contained in:
@@ -24,5 +24,5 @@ export const userApi = {
|
||||
delete: (key: string) => request.delete(`/user/${key}`),
|
||||
deleteBatch: (data: any) => request.delete(`/user`, { data }),
|
||||
get: (key: string) => request.get(`/user/${key}`),
|
||||
pwd: (data: any) => request.put('/user/pwd', data),
|
||||
pwd: (id: any) => request.patch(`/user/pwd/${id}`),
|
||||
}
|
||||
|
||||
@@ -24,7 +24,11 @@
|
||||
"simplified_chinese": "Simplified Chinese",
|
||||
"traditional_chinese": "Traditional Chinese",
|
||||
"help": "Help",
|
||||
"language": "Language"
|
||||
"language": "Language",
|
||||
"re_upload": "Re-upload",
|
||||
"not_exceed_50mb": "Supports XLS, XLSX, CSV formats, file size does not exceed 50MB",
|
||||
"reset_password": "Reset password",
|
||||
"password_reset_successful": "Password reset successful"
|
||||
},
|
||||
"dashboard": {
|
||||
"select_dashboard": "Please Select Dashboard",
|
||||
@@ -186,7 +190,9 @@
|
||||
"operate_with_caution": "After being deleted, the data source cannot be intelligently counted. Please operate with caution.",
|
||||
"data_source_de": "Unable to delete data source: {msg}",
|
||||
"cannot_be_deleted": "The chart of the dashboard uses this data source and cannot be deleted.",
|
||||
"got_it": "Got it"
|
||||
"got_it": "Got it",
|
||||
"field_original_notes": "Field original notes",
|
||||
"field_notes_1": "Field notes"
|
||||
},
|
||||
"model": {
|
||||
"default_model": "Default model",
|
||||
@@ -330,4 +336,4 @@
|
||||
"back_community": "Restore to Community Edition",
|
||||
"confirm_tips": "Are you sure to restore to Community Edition?"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -26,7 +26,11 @@
|
||||
"simplified_chinese": "简体中文",
|
||||
"traditional_chinese": "繁體中文",
|
||||
"help": "帮助",
|
||||
"language": "语言"
|
||||
"language": "语言",
|
||||
"re_upload": "重新上传",
|
||||
"not_exceed_50mb": "支持 XLS、XLSX、CSV 格式,文件大小不超过 50MB",
|
||||
"reset_password": "重置密码",
|
||||
"password_reset_successful": "重置密码成功"
|
||||
},
|
||||
"dashboard": {
|
||||
"select_dashboard": "请选择仪表板",
|
||||
@@ -124,14 +128,14 @@
|
||||
"choose_tables": "选择数据表",
|
||||
"name": "名称",
|
||||
"description": "描述",
|
||||
"host": "主机/IP",
|
||||
"host": "主机名/IP地址",
|
||||
"port": "端口",
|
||||
"username": "用户名",
|
||||
"password": "密码",
|
||||
"database": "数据库",
|
||||
"connect_mode": "连接方式",
|
||||
"service_name": "服务名",
|
||||
"extra_jdbc": "额外 JDBC 参数",
|
||||
"extra_jdbc": "额外的 JDBC 连接字符串",
|
||||
"schema": "模式",
|
||||
"get_schema": "获取模式",
|
||||
"file": "文件",
|
||||
@@ -194,7 +198,9 @@
|
||||
"operate_with_caution": "被删除后,将无法对该数据源进行智能问数,请谨慎操作。",
|
||||
"data_source_de": "无法删除数据源:{msg}",
|
||||
"cannot_be_deleted": "仪表板的图表使用了该数据源,不可删除。",
|
||||
"got_it": "知道了"
|
||||
"got_it": "知道了",
|
||||
"field_original_notes": "字段原始备注",
|
||||
"field_notes_1": "字段备注"
|
||||
},
|
||||
"model": {
|
||||
"default_model": "默认模型",
|
||||
|
||||
@@ -27,6 +27,9 @@
|
||||
|
||||
--ed-color-primary: #1cba90 !important;
|
||||
--ed-border-radius-base: 6px !important;
|
||||
--ed-color-primary-light-3: #3ec4a1 !important;
|
||||
--ed-color-primary-dark-2: #189e7a !important;
|
||||
--ed-color-primary-1a: #1cba901a;
|
||||
}
|
||||
|
||||
a {
|
||||
|
||||
@@ -54,3 +54,29 @@ export const getBrowserLocale = () => {
|
||||
export const getLocale = () => {
|
||||
return wsCache.get('user.language') || getBrowserLocale() || 'zh-CN'
|
||||
}
|
||||
|
||||
export const setSize = (size: any) => {
|
||||
let data = ''
|
||||
const _size = Number.parseFloat(size)
|
||||
if (_size < 1 * 1024) {
|
||||
//如果小于0.1KB转化成B
|
||||
data = _size.toFixed(2) + 'B'
|
||||
} else if (_size < 1 * 1024 * 1024) {
|
||||
//如果小于0.1MB转化成KB
|
||||
data = (_size / 1024).toFixed(2) + 'KB'
|
||||
} else if (_size < 1 * 1024 * 1024 * 1024) {
|
||||
//如果小于0.1GB转化成MB
|
||||
data = (_size / (1024 * 1024)).toFixed(2) + 'MB'
|
||||
} else {
|
||||
//其他转化成GB
|
||||
data = (_size / (1024 * 1024 * 1024)).toFixed(2) + 'GB'
|
||||
}
|
||||
const size_str = data + ''
|
||||
const len = size_str.indexOf('.')
|
||||
const dec = size_str.substr(len + 1, 2)
|
||||
if (dec == '00') {
|
||||
//当小数点后为00时 去掉小数部分
|
||||
return size_str.substring(0, len) + size_str.substr(len + 3, 2)
|
||||
}
|
||||
return size_str
|
||||
}
|
||||
|
||||
@@ -52,6 +52,7 @@ const props = withDefaults(
|
||||
const { t } = useI18n()
|
||||
const paramsFormRef = ref()
|
||||
const tableList = ref([] as any[])
|
||||
const loading = ref(false)
|
||||
const keywords = ref('')
|
||||
const tableListWithSearch = computed(() => {
|
||||
if (!keywords.value) return tableList.value
|
||||
@@ -63,7 +64,7 @@ const total = ref(1000)
|
||||
const showNum = ref(100)
|
||||
const currentTable = ref<any>({})
|
||||
const ds = ref<any>({})
|
||||
const btnSelect = ref('q')
|
||||
const btnSelect = ref('d')
|
||||
|
||||
const init = () => {
|
||||
datasourceApi.getDs(props.info.id).then((res) => {
|
||||
@@ -94,13 +95,19 @@ const handleSelectTableList = () => {
|
||||
}
|
||||
|
||||
const clickTable = (table: any) => {
|
||||
loading.value = true
|
||||
currentTable.value = table
|
||||
datasourceApi.fieldList(table.id).then((res) => {
|
||||
fieldList.value = res
|
||||
datasourceApi.previewData(props.info.id, buildData()).then((res) => {
|
||||
previewData.value = res
|
||||
datasourceApi
|
||||
.fieldList(table.id)
|
||||
.then((res) => {
|
||||
fieldList.value = res
|
||||
datasourceApi.previewData(props.info.id, buildData()).then((res) => {
|
||||
previewData.value = res
|
||||
})
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
const closeTable = () => {
|
||||
@@ -228,12 +235,14 @@ const back = () => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="currentTable.table_name" class="info-table">
|
||||
<div v-if="currentTable.table_name" v-loading="loading" class="info-table">
|
||||
<div class="table-name">
|
||||
<div class="name">{{ currentTable.table_name }}</div>
|
||||
<div class="notes">
|
||||
{{ $t('about.remark') }}:
|
||||
{{ currentTable.custom_comment || '-' }}
|
||||
<span :title="currentTable.custom_comment" class="field-notes">{{
|
||||
currentTable.custom_comment || '-'
|
||||
}}</span>
|
||||
<el-icon style="margin-left: 8px; cursor: pointer" size="16" @click="editTable">
|
||||
<edit></edit>
|
||||
</el-icon>
|
||||
@@ -253,11 +262,13 @@ const back = () => {
|
||||
<el-table v-if="btnSelect === 'd'" :data="fieldList" style="width: 100%">
|
||||
<el-table-column prop="field_name" :label="t('datasource.field_name')" width="180" />
|
||||
<el-table-column prop="field_type" :label="t('datasource.field_type')" width="180" />
|
||||
<el-table-column prop="field_comment" :label="t('about.remark')" />
|
||||
<el-table-column :label="t('datasource.custom_notes')">
|
||||
<el-table-column prop="field_comment" :label="t('datasource.field_original_notes')" />
|
||||
<el-table-column :label="t('datasource.field_notes_1')">
|
||||
<template #default="scope">
|
||||
<div class="field-comment">
|
||||
<span>{{ scope.row.custom_comment }}</span>
|
||||
<span :title="scope.row.custom_comment" class="notes-in_table">{{
|
||||
scope.row.custom_comment
|
||||
}}</span>
|
||||
<el-tooltip
|
||||
:offset="14"
|
||||
effect="dark"
|
||||
@@ -441,6 +452,7 @@ const back = () => {
|
||||
right: 0;
|
||||
top: 0;
|
||||
width: calc(100% - 280px);
|
||||
height: 100%;
|
||||
.table-name {
|
||||
height: 80px;
|
||||
padding: 16px 0 0 24px;
|
||||
@@ -459,11 +471,20 @@ const back = () => {
|
||||
color: #646a73;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.field-notes {
|
||||
display: inline-block;
|
||||
max-width: calc(100% - 75px);
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.table-content {
|
||||
padding: 16px 24px;
|
||||
height: calc(100% - 80px);
|
||||
|
||||
.btn-select {
|
||||
height: 32px;
|
||||
@@ -495,33 +516,53 @@ const back = () => {
|
||||
|
||||
.preview-or-schema {
|
||||
margin-top: 16px;
|
||||
height: calc(100% - 50px);
|
||||
overflow-y: auto;
|
||||
|
||||
.field-comment {
|
||||
height: 24px;
|
||||
}
|
||||
.ed-icon {
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
margin-top: 4px;
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
background-color: #1f23291a;
|
||||
position: absolute;
|
||||
border-radius: 6px;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
transform: translate(-50%, -50%);
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
display: none;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
min-height: 24px;
|
||||
.notes-in_table {
|
||||
max-width: 192px;
|
||||
display: -webkit-box;
|
||||
max-height: 66px;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 3; /* 限制行数为3 */
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
&::after {
|
||||
.ed-icon {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
.ed-icon {
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
margin-top: 4px;
|
||||
margin-left: 8px;
|
||||
display: none;
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
background-color: #1f23291a;
|
||||
position: absolute;
|
||||
border-radius: 6px;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
transform: translate(-50%, -50%);
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
display: none;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
&::after {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.preview-num {
|
||||
|
||||
@@ -324,6 +324,7 @@ const back = () => {
|
||||
<DatasourceForm
|
||||
v-if="[1, 2].includes(activeStep)"
|
||||
ref="datasourceFormRef"
|
||||
:isDataTable="false"
|
||||
:active-step="activeStep"
|
||||
:active-name="activeName"
|
||||
:active-type="activeType"
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
import { ref, reactive, onMounted, computed, watch, nextTick } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { datasourceApi } from '@/api/datasource'
|
||||
import icon_upload_outlined from '@/assets/svg/icon_upload_outlined.svg'
|
||||
import icon_searchOutline_outlined from '@/assets/svg/icon_search-outline_outlined.svg'
|
||||
import { encrypted, decrypted } from './js/aes'
|
||||
import { ElMessage } from 'element-plus-secondary'
|
||||
@@ -11,18 +12,23 @@ import FixedSizeList from 'element-plus-secondary/es/components/virtual-list/src
|
||||
import { Plus } from '@element-plus/icons-vue'
|
||||
import { useCache } from '@/utils/useCache'
|
||||
import { dsType, haveSchema } from '@/views/ds/js/ds-type'
|
||||
import { setSize } from '@/utils/utils'
|
||||
import EmptyBackground from '@/views/dashboard/common/EmptyBackground.vue'
|
||||
import icon_fileExcel_colorful from '@/assets/datasource/icon_excel.png'
|
||||
import IconOpeDelete from '@/assets/svg/icon_delete.svg'
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
activeName: string
|
||||
activeType: string
|
||||
activeStep: number
|
||||
isDataTable: boolean
|
||||
}>(),
|
||||
{
|
||||
activeName: '',
|
||||
activeType: '',
|
||||
activeStep: 0,
|
||||
isDataTable: false,
|
||||
}
|
||||
)
|
||||
|
||||
@@ -44,20 +50,55 @@ const headers = ref<any>({ 'X-SQLBOT-TOKEN': `Bearer ${token}`, 'X-SQLBOT-KEY':
|
||||
const dialogTitle = ref('')
|
||||
const getUploadURL = import.meta.env.VITE_API_BASE_URL + '/datasource/uploadExcel'
|
||||
const saveLoading = ref<boolean>(false)
|
||||
|
||||
const uploadLoading = ref(false)
|
||||
const { t } = useI18n()
|
||||
|
||||
const rules = reactive<FormRules>({
|
||||
name: [
|
||||
{ required: true, message: t('ds.form.validate.name_required'), trigger: 'blur' },
|
||||
{
|
||||
required: true,
|
||||
message: t('datasource.please_enter') + t('common.empty') + t('ds.form.name'),
|
||||
trigger: 'blur',
|
||||
},
|
||||
{ min: 1, max: 50, message: t('ds.form.validate.name_length'), trigger: 'blur' },
|
||||
],
|
||||
type: [{ required: true, message: t('ds.form.validate.type_required'), trigger: 'change' }],
|
||||
host: [{ required: true, message: 'Please input host', trigger: 'blur' }],
|
||||
port: [{ required: true, message: 'Please input port', trigger: 'blur' }],
|
||||
database: [{ required: true, message: 'Please input database', trigger: 'blur' }],
|
||||
type: [
|
||||
{
|
||||
required: true,
|
||||
message: t('datasource.Please_select') + t('common.empty') + t('ds.type'),
|
||||
trigger: 'change',
|
||||
},
|
||||
],
|
||||
host: [
|
||||
{
|
||||
required: true,
|
||||
message: t('datasource.please_enter') + t('common.empty') + t('ds.form.port'),
|
||||
trigger: 'blur',
|
||||
},
|
||||
],
|
||||
port: [
|
||||
{
|
||||
required: true,
|
||||
message: t('datasource.please_enter') + t('common.empty') + t('ds.form.host'),
|
||||
trigger: 'blur',
|
||||
},
|
||||
],
|
||||
database: [
|
||||
{
|
||||
required: true,
|
||||
message: t('datasource.please_enter') + t('common.empty') + t('ds.form.database'),
|
||||
trigger: 'blur',
|
||||
},
|
||||
],
|
||||
mode: [{ required: true, message: 'Please choose mode', trigger: 'change' }],
|
||||
dbSchema: [{ required: true, message: 'Please input schema', trigger: 'blur' }],
|
||||
sheets: [{ required: true, message: t('user.upload_file'), trigger: 'change' }],
|
||||
dbSchema: [
|
||||
{
|
||||
required: true,
|
||||
message: t('datasource.please_enter') + t('common.empty') + t('ds.form.schema'),
|
||||
trigger: 'blur',
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
const dialogVisible = ref<boolean>(false)
|
||||
@@ -312,10 +353,12 @@ const preview = () => {
|
||||
}
|
||||
|
||||
const beforeUpload = (rawFile: any) => {
|
||||
setFile(rawFile)
|
||||
if (rawFile.size / 1024 / 1024 > 50) {
|
||||
ElMessage.error('File size can not exceed 50MB!')
|
||||
ElMessage.error(t('common.not_exceed_50mb'))
|
||||
return false
|
||||
}
|
||||
uploadLoading.value = true
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -324,6 +367,11 @@ const onSuccess = (response: any) => {
|
||||
form.value.sheets = response.data.sheets
|
||||
tableList.value = response.data.sheets
|
||||
excelUploadSuccess.value = true
|
||||
uploadLoading.value = false
|
||||
}
|
||||
|
||||
const onError = () => {
|
||||
uploadLoading.value = false
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
@@ -354,6 +402,17 @@ watch(
|
||||
form.value.type = val
|
||||
}
|
||||
)
|
||||
const fileSize = ref('-')
|
||||
const clearFile = () => {
|
||||
fileSize.value = ''
|
||||
form.value.filename = ''
|
||||
form.value.sheets = []
|
||||
tableList.value = []
|
||||
}
|
||||
|
||||
const setFile = (file: any) => {
|
||||
fileSize.value = setSize(file.size)
|
||||
}
|
||||
|
||||
const checkAll = ref(false)
|
||||
const isIndeterminate = ref(false)
|
||||
@@ -396,9 +455,12 @@ defineExpose({
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="model-form" :class="(!isCreate || activeStep === 2) && 'edit-form'">
|
||||
<div
|
||||
class="model-form"
|
||||
v-loading="uploadLoading"
|
||||
:class="(!isCreate || activeStep === 2) && 'edit-form'"
|
||||
>
|
||||
<div v-if="isCreate && activeStep !== 2" class="model-name">{{ activeName }}</div>
|
||||
|
||||
<div class="form-content">
|
||||
<el-form
|
||||
v-show="activeStep === 1"
|
||||
@@ -408,14 +470,78 @@ defineExpose({
|
||||
label-width="auto"
|
||||
:rules="rules"
|
||||
>
|
||||
<div v-if="form.type === 'excel'">
|
||||
<el-form-item prop="sheets" :label="t('ds.form.file')">
|
||||
<div v-if="form.filename" class="pdf-card">
|
||||
<img :src="icon_fileExcel_colorful" width="40px" height="40px" />
|
||||
<div class="file-name">
|
||||
<div class="name">{{ form.filename }}</div>
|
||||
<div class="size">{{ form.filename.split('.')[1] }} - {{ fileSize }}</div>
|
||||
</div>
|
||||
<el-icon class="action-btn" size="16" @click="clearFile">
|
||||
<IconOpeDelete></IconOpeDelete>
|
||||
</el-icon>
|
||||
</div>
|
||||
<el-upload
|
||||
v-if="form.filename"
|
||||
class="upload-user"
|
||||
accept=".xlsx,.xls"
|
||||
:headers="headers"
|
||||
:action="getUploadURL"
|
||||
:before-upload="beforeUpload"
|
||||
:on-error="onError"
|
||||
:on-success="onSuccess"
|
||||
:show-file-list="false"
|
||||
:file-list="form.sheets"
|
||||
>
|
||||
<el-button text style="line-height: 22px; height: 22px">
|
||||
{{ $t('common.re_upload') }}
|
||||
</el-button>
|
||||
</el-upload>
|
||||
<el-upload
|
||||
v-else
|
||||
class="upload-user"
|
||||
accept=".xlsx,.xls"
|
||||
:headers="headers"
|
||||
:action="getUploadURL"
|
||||
:before-upload="beforeUpload"
|
||||
:on-success="onSuccess"
|
||||
:on-error="onError"
|
||||
:show-file-list="false"
|
||||
:file-list="form.sheets"
|
||||
>
|
||||
<el-button secondary>
|
||||
<el-icon size="16" style="margin-right: 4px">
|
||||
<icon_upload_outlined></icon_upload_outlined>
|
||||
</el-icon>
|
||||
{{ t('user.upload_file') }}</el-button
|
||||
>
|
||||
</el-upload>
|
||||
<span v-if="!form.filename" class="not_exceed">{{ $t('common.not_exceed_50mb') }}</span>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<el-form-item :label="t('ds.form.name')" prop="name">
|
||||
<el-input v-model="form.name" />
|
||||
<el-input
|
||||
:placeholder="$t('datasource.please_enter') + $t('common.empty') + t('ds.form.name')"
|
||||
v-model="form.name"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('ds.form.description')">
|
||||
<el-input v-model="form.description" :rows="2" type="textarea" />
|
||||
<el-input
|
||||
:placeholder="
|
||||
$t('datasource.please_enter') + $t('common.empty') + t('ds.form.description')
|
||||
"
|
||||
v-model="form.description"
|
||||
:rows="2"
|
||||
type="textarea"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('ds.type')" prop="type">
|
||||
<el-select v-model="form.type" placeholder="Select Type" :disabled="!isCreate">
|
||||
<el-select
|
||||
v-model="form.type"
|
||||
:placeholder="$t('datasource.Please_select') + $t('common.empty') + t('ds.type')"
|
||||
:disabled="!isCreate"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in dsType"
|
||||
:key="item.value"
|
||||
@@ -424,38 +550,52 @@ defineExpose({
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<div v-if="form.type === 'excel'">
|
||||
<el-form-item label="File">
|
||||
<el-upload
|
||||
:disabled="!isCreate"
|
||||
accept=".xls, .xlsx, .csv"
|
||||
:headers="headers"
|
||||
:action="getUploadURL"
|
||||
:before-upload="beforeUpload"
|
||||
:on-success="onSuccess"
|
||||
>
|
||||
<el-button :disabled="!isCreate">{{ t('ds.form.upload.button') }}</el-button>
|
||||
<template #tip>
|
||||
<div class="el-upload__tip">{{ t('ds.form.upload.tip') }}</div>
|
||||
</template>
|
||||
</el-upload>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<div v-else>
|
||||
<span v-if="form.type !== 'excel'">
|
||||
<span>{{ t('ds.form.support_version') }}: </span>
|
||||
<span v-if="form.type === 'sqlServer'">2012+</span>
|
||||
<span v-else-if="form.type === 'oracle'">12+</span>
|
||||
<span v-else-if="form.type === 'mysql'">5.6+</span>
|
||||
<span v-else-if="form.type === 'pg'">9.6+</span>
|
||||
</span>
|
||||
|
||||
<div style="margin-top: 16px" v-if="form.type !== 'excel'">
|
||||
<el-form-item :label="t('ds.form.host')" prop="host">
|
||||
<el-input v-model="form.host" />
|
||||
<el-input
|
||||
:placeholder="$t('datasource.please_enter') + $t('common.empty') + t('ds.form.host')"
|
||||
v-model="form.host"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('ds.form.port')" prop="port">
|
||||
<el-input v-model="form.port" />
|
||||
<el-input
|
||||
:placeholder="$t('datasource.please_enter') + $t('common.empty') + t('ds.form.port')"
|
||||
v-model="form.port"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('ds.form.username')">
|
||||
<el-input v-model="form.username" />
|
||||
<el-input
|
||||
:placeholder="
|
||||
$t('datasource.please_enter') + $t('common.empty') + t('ds.form.username')
|
||||
"
|
||||
v-model="form.username"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('ds.form.password')">
|
||||
<el-input v-model="form.password" type="password" show-password />
|
||||
<el-input
|
||||
:placeholder="
|
||||
$t('datasource.please_enter') + $t('common.empty') + t('ds.form.password')
|
||||
"
|
||||
v-model="form.password"
|
||||
type="password"
|
||||
show-password
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('ds.form.database')" prop="database">
|
||||
<el-input v-model="form.database" />
|
||||
<el-input
|
||||
:placeholder="
|
||||
$t('datasource.please_enter') + $t('common.empty') + t('ds.form.database')
|
||||
"
|
||||
v-model="form.database"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-if="form.type === 'oracle'"
|
||||
@@ -468,26 +608,29 @@ defineExpose({
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('ds.form.extra_jdbc')">
|
||||
<el-input v-model="form.extraJdbc" />
|
||||
<el-input
|
||||
:placeholder="
|
||||
$t('datasource.please_enter') + $t('common.empty') + t('ds.form.extra_jdbc')
|
||||
"
|
||||
v-model="form.extraJdbc"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-if="haveSchema.includes(form.type)"
|
||||
:label="t('ds.form.schema')"
|
||||
prop="dbSchema"
|
||||
>
|
||||
<el-input v-model="form.dbSchema" />
|
||||
<el-input
|
||||
:placeholder="
|
||||
$t('datasource.please_enter') + $t('common.empty') + t('ds.form.schema')
|
||||
"
|
||||
v-model="form.dbSchema"
|
||||
/>
|
||||
<el-button v-if="false" link type="primary" :icon="Plus">Get Schema</el-button>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('ds.form.timeout')" prop="timeout">
|
||||
<el-input-number v-model="form.timeout" :min="0" :max="300" controls-position="right" />
|
||||
</el-form-item>
|
||||
<span>
|
||||
<span>{{ t('ds.form.support_version') }}: </span>
|
||||
<span v-if="form.type === 'sqlServer'">2012+</span>
|
||||
<span v-else-if="form.type === 'oracle'">12+</span>
|
||||
<span v-else-if="form.type === 'mysql'">5.6+</span>
|
||||
<span v-else-if="form.type === 'pg'">9.6+</span>
|
||||
</span>
|
||||
</div>
|
||||
</el-form>
|
||||
<div v-show="activeStep === 2" v-loading="tableListLoading" class="select-data_table">
|
||||
@@ -554,8 +697,8 @@ defineExpose({
|
||||
</div>
|
||||
</div>
|
||||
<div class="draw-foot">
|
||||
<el-button @click="close">{{ t('common.cancel') }}</el-button>
|
||||
<el-button v-show="form.type !== 'excel'" @click="check">
|
||||
<el-button secondary @click="close">{{ t('common.cancel') }}</el-button>
|
||||
<el-button v-show="form.type !== 'excel' && !isDataTable" @click="check">
|
||||
{{ t('ds.check') }}
|
||||
</el-button>
|
||||
<el-button v-show="activeStep !== 0 && isCreate" secondary @click="preview">
|
||||
@@ -602,6 +745,77 @@ defineExpose({
|
||||
margin: 0 auto;
|
||||
padding-top: 24px;
|
||||
|
||||
.upload-user {
|
||||
height: 32px;
|
||||
.ed-upload {
|
||||
width: 100% !important;
|
||||
}
|
||||
}
|
||||
|
||||
.not_exceed {
|
||||
font-weight: 400;
|
||||
font-size: 14px;
|
||||
line-height: 22px;
|
||||
color: #8f959e;
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.pdf-card {
|
||||
width: 100%;
|
||||
height: 58px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 16px 0 12px;
|
||||
border: 1px solid #dee0e3;
|
||||
border-radius: 6px;
|
||||
|
||||
.file-name {
|
||||
margin-left: 8px;
|
||||
.name {
|
||||
font-weight: 400;
|
||||
font-size: 14px;
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
.size {
|
||||
font-weight: 400;
|
||||
font-size: 12px;
|
||||
line-height: 20px;
|
||||
color: #8f959e;
|
||||
}
|
||||
}
|
||||
|
||||
.action-btn {
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.ed-icon {
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
color: #646a73;
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
background-color: #1f23291a;
|
||||
position: absolute;
|
||||
border-radius: 6px;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
transform: translate(-50%, -50%);
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
display: none;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
&::after {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.ed-form-item--default {
|
||||
margin-bottom: 16px;
|
||||
|
||||
|
||||
@@ -55,6 +55,7 @@ defineExpose({
|
||||
:active-step="2"
|
||||
active-name=""
|
||||
active-type=""
|
||||
isDataTable
|
||||
@change-active-step="changeActiveStep"
|
||||
@refresh="refresh"
|
||||
></DatasourceForm>
|
||||
|
||||
@@ -101,10 +101,12 @@ const formatKeywords = (item: string) => {
|
||||
}
|
||||
const handleAddModel = () => {
|
||||
activeStep.value = 0
|
||||
editModel.value = false
|
||||
modelConfigvVisible.value = true
|
||||
}
|
||||
const handleEditModel = (row: any) => {
|
||||
activeStep.value = 1
|
||||
editModel.value = true
|
||||
activeType.value = row.supplier
|
||||
activeName.value = row.supplier_item.name
|
||||
modelApi.query(row.id).then((res: any) => {
|
||||
@@ -304,7 +306,9 @@ const submit = (item: any) => {
|
||||
:show-close="false"
|
||||
>
|
||||
<template #header="{ close }">
|
||||
<span style="white-space: nowrap">{{ t('model.add_model') }}</span>
|
||||
<span style="white-space: nowrap">{{
|
||||
editModel ? $t('dashboard.edit') + $t('common.empty') + activeName : t('model.add_model')
|
||||
}}</span>
|
||||
<div v-if="!editModel" class="flex-center" style="width: 100%">
|
||||
<el-steps custom style="max-width: 500px; flex: 1" :active="activeStep" align-center>
|
||||
<el-step>
|
||||
@@ -321,7 +325,7 @@ const submit = (item: any) => {
|
||||
</template>
|
||||
<ModelList v-if="activeStep === 0" @click-model="clickModel"></ModelList>
|
||||
<ModelListSide
|
||||
v-if="activeStep === 1"
|
||||
v-if="activeStep === 1 && !editModel"
|
||||
:active-name="activeName"
|
||||
:active-type="activeType"
|
||||
@click-model="supplierChang"
|
||||
@@ -331,11 +335,14 @@ const submit = (item: any) => {
|
||||
ref="modelFormRef"
|
||||
:active-name="activeName"
|
||||
:active-type="activeType"
|
||||
:edit-model="editModel"
|
||||
@submit="submit"
|
||||
></ModelForm>
|
||||
<template #footer>
|
||||
<template v-if="activeStep !== 0" #footer>
|
||||
<el-button secondary @click="cancel"> {{ $t('common.cancel') }} </el-button>
|
||||
<el-button secondary @click="preStep"> {{ $t('ds.previous') }} </el-button>
|
||||
<el-button v-if="!editModel" secondary @click="preStep">
|
||||
{{ $t('ds.previous') }}
|
||||
</el-button>
|
||||
<el-button type="primary" @click="saveModel"> {{ $t('common.save') }} </el-button>
|
||||
</template>
|
||||
</el-drawer>
|
||||
|
||||
@@ -13,9 +13,11 @@ import { useI18n } from 'vue-i18n'
|
||||
withDefaults(
|
||||
defineProps<{
|
||||
activeName: string
|
||||
editModel: boolean
|
||||
}>(),
|
||||
{
|
||||
activeName: '',
|
||||
editModel: false,
|
||||
}
|
||||
)
|
||||
|
||||
@@ -166,8 +168,8 @@ defineExpose({
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="model-form">
|
||||
<div class="model-name">{{ activeName }}</div>
|
||||
<div class="model-form" :class="editModel && 'is-edit_model'">
|
||||
<div class="model-name" v-if="!editModel">{{ activeName }}</div>
|
||||
<div class="form-content">
|
||||
<el-form
|
||||
ref="modelRef"
|
||||
@@ -310,6 +312,10 @@ defineExpose({
|
||||
right: 0;
|
||||
top: 56px;
|
||||
height: 100%;
|
||||
|
||||
&.is-edit_model {
|
||||
width: 100%;
|
||||
}
|
||||
.model-name {
|
||||
height: 56px;
|
||||
width: 100%;
|
||||
|
||||
@@ -98,7 +98,7 @@
|
||||
<el-tooltip
|
||||
:offset="14"
|
||||
effect="dark"
|
||||
:content="$t('user.change_password')"
|
||||
:content="$t('common.reset_password')"
|
||||
placement="top"
|
||||
>
|
||||
<el-icon class="action-btn" size="16" @click="handleEditPassword(scope.row.id)">
|
||||
@@ -205,6 +205,7 @@
|
||||
|
||||
<el-form-item :label="$t('user.workspace')">
|
||||
<el-select
|
||||
clearable
|
||||
v-model="state.form.oid"
|
||||
:placeholder="$t('datasource.Please_select') + $t('common.empty') + $t('user.workspace')"
|
||||
>
|
||||
@@ -218,7 +219,9 @@
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button @click="closeForm">{{ $t('common.cancel') }}</el-button>
|
||||
<el-button type="primary" @click="saveHandler"> {{ $t('model.add') }} </el-button>
|
||||
<el-button type="primary" @click="saveHandler">
|
||||
{{ state.form.id ? $t('common.save') : $t('model.add') }}
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-drawer>
|
||||
@@ -315,13 +318,13 @@ const filterOption = ref<any[]>([
|
||||
type: 'enum',
|
||||
option: [
|
||||
{ id: '0', name: t('user.local_creation') },
|
||||
{ id: 1, name: 'LDAP' },
|
||||
{ id: 2, name: 'OIDC' },
|
||||
{ id: 3, name: 'CAS' },
|
||||
{ id: 9, name: 'OAuth2' },
|
||||
{ id: 4, name: t('user.feishu') },
|
||||
{ id: 5, name: t('user.dingtalk') },
|
||||
{ id: 6, name: t('user.wechat_for_business') },
|
||||
// { id: 1, name: 'LDAP' },
|
||||
// { id: 2, name: 'OIDC' },
|
||||
// { id: 3, name: 'CAS' },
|
||||
// { id: 9, name: 'OAuth2' },
|
||||
// { id: 4, name: t('user.feishu') },
|
||||
// { id: 5, name: t('user.dingtalk') },
|
||||
// { id: 6, name: t('user.wechat_for_business') },
|
||||
],
|
||||
field: 'origins',
|
||||
title: t('user.user_source'),
|
||||
@@ -330,7 +333,7 @@ const filterOption = ref<any[]>([
|
||||
{
|
||||
type: 'select',
|
||||
option: [],
|
||||
field: 'oidist',
|
||||
field: 'oidlist',
|
||||
title: t('user.workspace'),
|
||||
operate: 'in',
|
||||
property: { placeholder: t('common.empty') + t('user.workspace') },
|
||||
@@ -412,8 +415,12 @@ const handleClosePassword = () => {
|
||||
}
|
||||
|
||||
const handleEditPassword = (id: any) => {
|
||||
password.value.id = id
|
||||
dialogVisiblePassword.value = true
|
||||
userApi.pwd(id).then(() => {
|
||||
ElMessage({
|
||||
type: 'success',
|
||||
message: t('common.password_reset_successful'),
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
const handleUserImport = () => {
|
||||
@@ -576,6 +583,9 @@ const configParams = () => {
|
||||
}
|
||||
|
||||
state.conditions.forEach((ele: any) => {
|
||||
if (ele.field === 'status' && ele.value.length === 2) {
|
||||
return
|
||||
}
|
||||
ele.value.forEach((itx: any) => {
|
||||
str += str ? `&${ele.field}=${itx}` : `${ele.field}=${itx}`
|
||||
})
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
</el-icon>
|
||||
</template>
|
||||
</el-input>
|
||||
<div class="mt-8">
|
||||
<div class="mt-8 max-height_workspace">
|
||||
<el-checkbox
|
||||
v-if="!search"
|
||||
v-model="checkAll"
|
||||
@@ -129,6 +129,9 @@ let oid: any = null
|
||||
const open = async (id: any) => {
|
||||
loading.value = true
|
||||
oid = id
|
||||
checkedWorkspace.value = []
|
||||
checkAll.value = false
|
||||
isIndeterminate.value = false
|
||||
const systemWorkspaceList = await workspaceOptionUserList({ oid }, 1, 1000)
|
||||
workspace.value = systemWorkspaceList.items as any
|
||||
loading.value = false
|
||||
@@ -201,6 +204,7 @@ defineExpose({
|
||||
|
||||
.w-full {
|
||||
width: 100%;
|
||||
overflow-y: auto;
|
||||
|
||||
.flex-between {
|
||||
height: 44px;
|
||||
@@ -211,6 +215,11 @@ defineExpose({
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.max-height_workspace {
|
||||
max-height: calc(100% - 24px);
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.align-center {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user