Merge remote-tracking branch 'origin/main'

This commit is contained in:
wangjiahao
2025-07-28 16:41:00 +08:00
28 changed files with 223 additions and 86 deletions
+1 -1
View File
@@ -60,7 +60,7 @@ def get_chat_predict_data(session: SessionDep, chart_record_id: int):
res = session.query(ChatRecord).options(load_only(ChatRecord.predict_data)).get(chart_record_id)
if res:
try:
return orjson.loads(res.data)
return orjson.loads(res.predict_data)
except Exception:
pass
return ''
+27 -26
View File
@@ -18,12 +18,14 @@ from ..models.datasource import CoreDatasource, CreateDatasource, TableObj, Core
router = APIRouter(tags=["datasource"], prefix="/datasource")
path = "/opt/sqlbot/data/excel"
@router.get("/ws/{oid}", include_in_schema=False)
async def query_by_oid(session: SessionDep, user: CurrentUser, oid: int) -> List[CoreDatasource]:
if not user.isAdmin:
raise Exception("no permission to execute")
return get_datasource_list(session=session, user=user, oid=oid)
@router.get("/list")
async def datasource_list(session: SessionDep, user: CurrentUser):
return get_datasource_list(session=session, user=user)
@@ -134,32 +136,11 @@ async def upload_excel(session: SessionDep, file: UploadFile = File(...)):
with open(save_path, "wb") as f:
f.write(await file.read())
conn = get_data_engine()
sheets = []
if filename.endswith(".csv"):
df = pd.read_csv(save_path)
tableName = f"sheet1_{hashlib.sha256(uuid.uuid4().bytes).hexdigest()[:10]}"
sheets.append({"tableName": tableName, "tableComment": ""})
column_len = len(df.dtypes)
fields = []
for i in range(column_len):
# build fields
fields.append({"name": df.columns[i], "type": str(df.dtypes[i]), "relType": ""})
# create table
create_table(conn, tableName, fields)
data = [
{df.columns[i]: None if pd.isna(row[i]) else (int(row[i]) if "int" in str(df.dtypes[i]) else row[i])
for i in range(len(row))}
for row in df.values
]
# insert data
insert_data(conn, tableName, fields, data)
else:
df_sheets = pd.read_excel(save_path, sheet_name=None)
# build columns and data to insert db
for sheet_name, df in df_sheets.items():
tableName = f"{sheet_name}_{hashlib.sha256(uuid.uuid4().bytes).hexdigest()[:10]}"
with get_data_engine() as conn:
if filename.endswith(".csv"):
df = pd.read_csv(save_path)
tableName = f"sheet1_{hashlib.sha256(uuid.uuid4().bytes).hexdigest()[:10]}"
sheets.append({"tableName": tableName, "tableComment": ""})
column_len = len(df.dtypes)
fields = []
@@ -176,7 +157,27 @@ async def upload_excel(session: SessionDep, file: UploadFile = File(...)):
]
# insert data
insert_data(conn, tableName, fields, data)
conn.close()
else:
df_sheets = pd.read_excel(save_path, sheet_name=None)
# build columns and data to insert db
for sheet_name, df in df_sheets.items():
tableName = f"{sheet_name}_{hashlib.sha256(uuid.uuid4().bytes).hexdigest()[:10]}"
sheets.append({"tableName": tableName, "tableComment": ""})
column_len = len(df.dtypes)
fields = []
for i in range(column_len):
# build fields
fields.append({"name": df.columns[i], "type": str(df.dtypes[i]), "relType": ""})
# create table
create_table(conn, tableName, fields)
data = [
{df.columns[i]: None if pd.isna(row[i]) else (int(row[i]) if "int" in str(df.dtypes[i]) else row[i])
for i in range(len(row))}
for row in df.values
]
# insert data
insert_data(conn, tableName, fields, data)
os.remove(save_path)
return {"filename": filename, "sheets": sheets}
+1 -1
View File
@@ -153,7 +153,7 @@ async def update(session: SessionDep, editor: UserEditor, trans: Trans):
raise Exception(f"User with id [{editor.id}] not found!")
if editor.account != user_model.account:
raise Exception(f"account cannot be changed!")
if editor.email != user_model.email and check_email_exists(session=session, account=editor.email):
if editor.email != user_model.email and check_email_exists(session=session, email=editor.email):
raise Exception(trans('i18n_exist', msg = f"{trans('i18n_user.email')} [{editor.email}]"))
if not check_email_format(editor.email):
raise Exception(trans('i18n_format_invalid', key = f"{trans('i18n_user.email')} [{editor.email}]"))
+1 -1
View File
@@ -138,7 +138,7 @@ template:
predict:
system: |
### 说明:
你是一个数据分析师,你的任务是根据给定的数据进行数据预测,我将以json格式给你一组数据,你帮我预测之后的数据(一段可以展示趋势的数据,至少2个周期),用json格式返回,返回的格式需要与传入的数据格式保持一致。
你是一个数据分析师,你的任务是根据给定的数据进行数据预测,我将以json格式给你一组数据,你帮我预测之后的数据(一段可以展示趋势的数据,至少2个周期),用json数组的格式返回,返回的格式需要与传入的数据格式保持一致。
```json
无法预测或者不支持预测的数据请直接返回(不需要返回JSON格式):"抱歉,该数据无法进行预测。(有原因则返回无法预测的原因)"
@@ -85,6 +85,7 @@ defineExpose({
v-model="pwdForm.pwd"
:placeholder="t('common.please_input', { msg: t('user.upgrade_pwd.old_pwd') })"
type="password"
clearable
show-password
/>
</el-form-item>
@@ -94,6 +95,7 @@ defineExpose({
:placeholder="t('common.please_input', { msg: t('user.upgrade_pwd.new_pwd') })"
type="password"
show-password
clearable
/>
</el-form-item>
<el-form-item prop="confirm_pwd" :label="t('user.upgrade_pwd.confirm_pwd')">
@@ -102,6 +104,7 @@ defineExpose({
:placeholder="t('common.please_input', { msg: t('user.upgrade_pwd.confirm_pwd') })"
type="password"
show-password
clearable
/>
</el-form-item>
</el-form>
+1
View File
@@ -264,6 +264,7 @@ const handleConfirmPassword = () => {
:placeholder="
$t('datasource.please_enter') + $t('common.empty') + $t('qa.conversation_title')
"
clearable
autocomplete="off"
/>
</el-form-item>
@@ -48,11 +48,11 @@ let chartInstance: BaseChart | undefined
function renderChart() {
chartInstance = getChartInstance(params.type, chartId.value)
console.log(chartInstance)
if (chartInstance) {
chartInstance.init(axis.value, params.data)
chartInstance.render()
}
console.debug(chartInstance)
}
function destroyChart() {
+2 -1
View File
@@ -290,6 +290,7 @@
ref="inputRef"
v-model="inputMessage"
:disabled="isTyping"
clearable
class="input-area"
type="textarea"
:rows="1"
@@ -590,7 +591,7 @@ function getChatPredictData(recordId?: number) {
chatApi.get_chart_predict_data(recordId).then((response) => {
currentChat.value.records.forEach((record) => {
if (record.id === recordId) {
record.predict_data = response.data ?? []
record.predict_data = response ?? []
}
})
})
@@ -185,6 +185,7 @@ defineExpose({
<el-input
v-model="resourceForm.name"
:placeholder="state.placeholder"
clearable
@keydown.stop
@keyup.stop
/>
@@ -264,7 +264,12 @@ defineExpose({
:close-on-click-modal="false"
center
>
<el-input v-model="state.textarea" maxlength="50" :placeholder="t('common.input_content')" />
<el-input
v-model="state.textarea"
maxlength="50"
clearable
:placeholder="t('common.input_content')"
/>
<template #footer>
<span class="dialog-footer">
<el-button @click="state.dialogVisible = false">{{ t('common.cancel') }}</el-button>
+2
View File
@@ -431,6 +431,7 @@ const btnSelectClick = (val: any) => {
:placeholder="$t('datasource.please_enter')"
:rows="3"
type="textarea"
clearable
/>
<div style="display: flex; justify-content: flex-end; margin-top: 20px">
<el-button @click="closeTable">{{ t('common.cancel') }}</el-button>
@@ -450,6 +451,7 @@ const btnSelectClick = (val: any) => {
v-model="fieldComment"
:placeholder="$t('datasource.please_enter')"
:rows="3"
clearable
type="textarea"
/>
<div style="display: flex; justify-content: flex-end; margin-top: 20px">
+27 -10
View File
@@ -274,15 +274,15 @@ const save = async (formEl: FormInstance | undefined) => {
}
} else {
requestObj.tables = list
// const a = datasourceApi
// .add(requestObj)
// .then(() => {
// close()
// emit('refresh')
// })
// .finally(() => {
// saveLoading.value = false
// })
datasourceApi
.add(requestObj)
.then(() => {
close()
emit('refresh')
})
.finally(() => {
saveLoading.value = false
})
}
}
})
@@ -558,6 +558,7 @@ defineExpose({
<el-form-item :label="t('ds.form.name')" prop="name">
<el-input
v-model="form.name"
clearable
:placeholder="$t('datasource.please_enter') + $t('common.empty') + t('ds.form.name')"
/>
</el-form-item>
@@ -568,6 +569,9 @@ defineExpose({
$t('datasource.please_enter') + $t('common.empty') + t('ds.form.description')
"
:rows="2"
show-word-limit
maxlength="200"
clearable
type="textarea"
/>
</el-form-item>
@@ -575,18 +579,21 @@ defineExpose({
<el-form-item :label="t('ds.form.host')" prop="host">
<el-input
v-model="form.host"
clearable
:placeholder="$t('datasource.please_enter') + $t('common.empty') + t('ds.form.host')"
/>
</el-form-item>
<el-form-item :label="t('ds.form.port')" prop="port">
<el-input
v-model="form.port"
clearable
:placeholder="$t('datasource.please_enter') + $t('common.empty') + t('ds.form.port')"
/>
</el-form-item>
<el-form-item :label="t('ds.form.username')">
<el-input
v-model="form.username"
clearable
:placeholder="
$t('datasource.please_enter') + $t('common.empty') + t('ds.form.username')
"
@@ -595,6 +602,7 @@ defineExpose({
<el-form-item :label="t('ds.form.password')">
<el-input
v-model="form.password"
clearable
:placeholder="
$t('datasource.please_enter') + $t('common.empty') + t('ds.form.password')
"
@@ -605,6 +613,7 @@ defineExpose({
<el-form-item :label="t('ds.form.database')" prop="database">
<el-input
v-model="form.database"
clearable
:placeholder="
$t('datasource.please_enter') + $t('common.empty') + t('ds.form.database')
"
@@ -623,6 +632,7 @@ defineExpose({
<el-form-item :label="t('ds.form.extra_jdbc')">
<el-input
v-model="form.extraJdbc"
clearable
:placeholder="
$t('datasource.please_enter') + $t('common.empty') + t('ds.form.extra_jdbc')
"
@@ -631,12 +641,19 @@ defineExpose({
<el-form-item v-if="haveSchema.includes(form.type)" label="Schema" prop="dbSchema">
<el-input
v-model="form.dbSchema"
clearable
:placeholder="$t('datasource.please_enter') + $t('common.empty') + 'Schema'"
/>
<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-input-number
v-model="form.timeout"
clearable
:min="0"
:max="300"
controls-position="right"
/>
</el-form-item>
</div>
</el-form>
+3 -2
View File
@@ -14,6 +14,7 @@
</div>
<el-input
v-model="searchValue"
clearable
style="margin: 16px 0"
:placeholder="t('ds.Search Datasource')"
/>
@@ -105,7 +106,7 @@
@closed="closeTable"
>
<div>{{ t('ds.edit.table_comment_label') }}</div>
<el-input v-model="tableComment" :rows="3" type="textarea" />
<el-input v-model="tableComment" clearable :rows="3" type="textarea" />
<div style="display: flex; justify-content: flex-end; margin-top: 20px">
<el-button @click="closeTable">{{ t('common.cancel') }}</el-button>
<el-button type="primary" @click="saveTable">{{ t('common.confirm') }}</el-button>
@@ -121,7 +122,7 @@
@closed="closeField"
>
<div>{{ t('ds.edit.field_comment_label') }}</div>
<el-input v-model="fieldComment" :rows="3" type="textarea" />
<el-input v-model="fieldComment" clearable :rows="3" type="textarea" />
<div style="display: flex; justify-content: flex-end; margin-top: 20px">
<el-button @click="closeField">{{ t('common.cancel') }}</el-button>
<el-button type="primary" @click="saveField">{{ t('common.confirm') }}</el-button>
+16 -10
View File
@@ -34,10 +34,10 @@
@submit.prevent
>
<el-form-item :label="t('ds.form.name')" prop="name">
<el-input v-model="form.name" />
<el-input v-model="form.name" clearable />
</el-form-item>
<el-form-item :label="t('ds.form.description')">
<el-input v-model="form.description" :rows="2" type="textarea" />
<el-input v-model="form.description" clearable :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">
@@ -68,19 +68,19 @@
</div>
<div v-else>
<el-form-item :label="t('ds.form.host')" prop="host">
<el-input v-model="form.host" />
<el-input v-model="form.host" clearable />
</el-form-item>
<el-form-item :label="t('ds.form.port')" prop="port">
<el-input v-model="form.port" />
<el-input v-model="form.port" clearable />
</el-form-item>
<el-form-item :label="t('ds.form.username')">
<el-input v-model="form.username" />
<el-input v-model="form.username" clearable />
</el-form-item>
<el-form-item :label="t('ds.form.password')">
<el-input v-model="form.password" type="password" show-password />
<el-input v-model="form.password" clearable 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 v-model="form.database" clearable />
</el-form-item>
<el-form-item
v-if="form.type === 'oracle'"
@@ -93,18 +93,24 @@
</el-radio-group>
</el-form-item>
<el-form-item :label="t('ds.form.extra_jdbc')">
<el-input v-model="form.extraJdbc" />
<el-input v-model="form.extraJdbc" clearable />
</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 v-model="form.dbSchema" clearable />
<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-input-number
v-model="form.timeout"
clearable
:min="0"
:max="300"
controls-position="right"
/>
</el-form-item>
<span>
<span>{{ t('ds.form.support_version') }}:&nbsp;</span>
@@ -38,6 +38,7 @@ const textareaVal = ref('')
v-model="textareaVal"
:autosize="{ minRows: 1, maxRows: 8.5848 }"
type="textarea"
clearable
:placeholder="$t('embedded.enter_a_question')"
/>
<el-tooltip :offset="10" effect="dark" :content="$t('embedded.send')" placement="top">
+2
View File
@@ -17,6 +17,7 @@
<el-form-item prop="username">
<el-input
v-model="loginForm.username"
clearable
:placeholder="$t('common.your_account_email_address')"
size="large"
></el-input>
@@ -27,6 +28,7 @@
:placeholder="$t('common.enter_your_password')"
type="password"
show-password
clearable
size="large"
></el-input>
</el-form-item>
+3 -2
View File
@@ -6,6 +6,7 @@
v-model="keyword"
class="sqlbot-search"
placeholder="Search"
clearable
prefix-icon="el-icon-search"
@keyup.enter="handleSearch"
>
@@ -68,10 +69,10 @@
@submit.prevent
>
<el-form-item label="Term name">
<el-input v-model="state.form.term" autocomplete="off" />
<el-input v-model="state.form.term" clearable autocomplete="off" />
</el-form-item>
<el-form-item label="Definition">
<el-input v-model="state.form.definition" type="textarea" />
<el-input v-model="state.form.definition" clearable type="textarea" />
</el-form-item>
<el-form-item label="Domain">
<el-select v-model="state.form.domain" placeholder="Please select a domain">
+7 -2
View File
@@ -456,8 +456,6 @@ const saveHandler = () => {
style="width: 240px; margin-right: 12px"
:placeholder="$t('dashboard.search')"
clearable
@keyup.enter="handleSearch"
@blur="handleSearch"
>
<template #prefix>
<el-icon>
@@ -594,6 +592,7 @@ const saveHandler = () => {
$t('common.empty') +
$t('embedded.basic_information')
"
clearable
autocomplete="off"
/>
</el-form-item>
@@ -605,6 +604,7 @@ const saveHandler = () => {
type="textarea"
maxlength="200"
show-word-limit
clearable
:placeholder="$t('datasource.please_enter')"
autocomplete="off"
/>
@@ -613,6 +613,7 @@ const saveHandler = () => {
<el-form-item prop="domain" :label="t('embedded.cross_domain_settings')">
<el-input
v-model="currentEmbedded.domain"
clearable
:placeholder="$t('embedded.third_party_address')"
autocomplete="off"
/>
@@ -636,6 +637,7 @@ const saveHandler = () => {
<el-form-item prop="endpoint" :label="t('embedded.interface_url')">
<el-input
v-model="urlForm.endpoint"
clearable
:placeholder="
$t('datasource.please_enter') + $t('common.empty') + $t('embedded.interface_url')
"
@@ -829,6 +831,7 @@ const saveHandler = () => {
<el-form-item prop="source" :label="t('embedded.credential_name')">
<el-input
v-model="certificateForm.source"
clearable
:placeholder="
$t('datasource.please_enter') + $t('common.empty') + $t('embedded.credential_name')
"
@@ -851,6 +854,7 @@ const saveHandler = () => {
<el-form-item prop="target_key" :label="t('embedded.target_credential_name')">
<el-input
v-model="certificateForm.target_key"
clearable
:placeholder="
$t('datasource.please_enter') +
$t('common.empty') +
@@ -875,6 +879,7 @@ const saveHandler = () => {
<el-form-item prop="target_val" :label="t('embedded.target_credential')">
<el-input
v-model="certificateForm.target_val"
clearable
:placeholder="
$t('datasource.please_enter') + $t('common.empty') + $t('embedded.target_credential')
"
+12 -1
View File
@@ -219,6 +219,7 @@ defineExpose({
</template>
<el-input
v-model="modelForm.name"
clearable
:placeholder="
$t('datasource.please_enter') + $t('common.empty') + $t('model.model_name')
"
@@ -253,6 +254,7 @@ defineExpose({
<el-form-item prop="api_domain" :label="t('model.api_domain_name')">
<el-input
v-model="modelForm.api_domain"
clearable
:placeholder="
$t('datasource.please_enter') + $t('common.empty') + $t('model.api_domain_name')
"
@@ -261,6 +263,7 @@ defineExpose({
<el-form-item prop="api_key" label="API Key">
<el-input
v-model="modelForm.api_key"
clearable
:placeholder="$t('datasource.please_enter') + $t('common.empty') + 'API Key'"
type="password"
show-password
@@ -287,7 +290,11 @@ defineExpose({
</span>
</div>
<div v-if="configExpand" class="params-table">
<div
v-if="configExpand"
class="params-table"
:class="!advancedSettingPagination.length && 'bottom-border'"
>
<el-table :data="advancedSettingPagination" style="width: 100%">
<el-table-column prop="key" :label="t('model.parameters')" width="280" />
<el-table-column prop="name" :label="t('model.display_name')" width="280" />
@@ -451,6 +458,10 @@ defineExpose({
border-top: none;
border-bottom: none;
overflow-y: auto;
&.bottom-border {
border-bottom: 1px solid #dee0e3;
}
:deep(.ed-table .ed-table__cell) {
padding: 7px 0;
}
@@ -81,12 +81,14 @@ defineExpose({
<el-form-item prop="key" :label="$t('model.parameters')">
<el-input
v-model="paramsForm.key"
clearable
:placeholder="$t('datasource.please_enter') + $t('common.empty') + $t('model.parameters')"
/>
</el-form-item>
<el-form-item prop="name" :label="$t('model.display_name')">
<el-input
v-model="paramsForm.name"
clearable
:placeholder="
$t('datasource.please_enter') + $t('common.empty') + $t('model.display_name')
"
@@ -95,6 +97,7 @@ defineExpose({
<el-form-item prop="val" :label="$t('model.parameter_value')">
<el-input
v-model="paramsForm.val"
clearable
:placeholder="
$t('datasource.please_enter') + $t('common.empty') + $t('model.parameter_value')
"
@@ -18,7 +18,6 @@
</el-input>
<div class="mt-8 max-height_workspace">
<el-checkbox
v-if="!search"
v-model="checkAll"
class="mb-8"
:indeterminate="isIndeterminate"
@@ -55,14 +54,14 @@
<div class="p-16 w-full">
<div class="flex-between mb-16">
<span class="lighter">
{{ $t('workspace.selected_2_people', { msg: checkedWorkspace.length }) }}
{{ $t('workspace.selected_2_people', { msg: checkTableList.length }) }}
</span>
<el-button text @click="clearWorkspaceAll">
{{ $t('workspace.clear') }}
</el-button>
</div>
<div v-for="ele in checkedWorkspace" :key="ele.name" class="flex-between">
<div v-for="ele in checkTableList" :key="ele.name" class="flex-between">
<div class="flex align-center ellipsis" style="width: 100%">
<el-icon size="28">
<avatar_personal></avatar_personal>
@@ -84,7 +83,7 @@
</template>
<script lang="ts" setup>
import { ref, computed } from 'vue'
import { ref, computed, watch } from 'vue'
import { workspaceUserList } from '@/api/workspace'
import avatar_personal from '@/assets/svg/avatar_personal.svg'
import Close from '@/assets/svg/icon_close_outlined_w.svg'
@@ -97,32 +96,63 @@ const workspace = ref<any[]>([])
const search = ref('')
const loading = ref(false)
const centerDialogVisible = ref(false)
const checkTableList = ref([] as any[])
const workspaceWithKeywords = computed(() => {
return workspace.value.filter((ele: any) => (ele.name as string).includes(search.value))
})
watch(search, () => {
const tableNameArr = workspaceWithKeywords.value.map((ele: any) => ele.name)
checkedWorkspace.value = checkTableList.value.filter((ele) => tableNameArr.includes(ele.name))
const checkedCount = checkedWorkspace.value.length
checkAll.value = checkedCount === workspaceWithKeywords.value.length
isIndeterminate.value = checkedCount > 0 && checkedCount < workspaceWithKeywords.value.length
})
const handleCheckAllChange = (val: CheckboxValueType) => {
checkedWorkspace.value = val ? workspace.value : []
const tableNameArr = workspaceWithKeywords.value.map((ele: any) => ele.name)
checkedWorkspace.value = val
? [
...new Set([
...workspaceWithKeywords.value,
...checkedWorkspace.value.filter((ele) => !tableNameArr.includes(ele.name)),
]),
]
: []
isIndeterminate.value = false
if (!val) {
clearWorkspaceAll()
}
checkTableList.value = val
? [
...new Set([
...workspaceWithKeywords.value,
...checkTableList.value.filter((ele) => !tableNameArr.includes(ele.name)),
]),
]
: checkTableList.value.filter((ele) => !tableNameArr.includes(ele.name))
}
const handleCheckedWorkspaceChange = (value: CheckboxValueType[]) => {
const checkedCount = value.length
checkAll.value = checkedCount === workspace.value.length
isIndeterminate.value = checkedCount > 0 && checkedCount < workspace.value.length
checkAll.value = checkedCount === workspaceWithKeywords.value.length
isIndeterminate.value = checkedCount > 0 && checkedCount < workspaceWithKeywords.value.length
const tableNameArr = workspaceWithKeywords.value.map((ele: any) => ele.name)
checkTableList.value = [
...new Set([
...checkTableList.value.filter((ele) => !tableNameArr.includes(ele.name)),
...value,
]),
]
}
const open = async (user: any) => {
loading.value = true
checkedWorkspace.value = []
checkAll.value = false
checkTableList.value = []
isIndeterminate.value = false
const systemWorkspaceList = await workspaceUserList({}, 1, 1000)
workspace.value = systemWorkspaceList.items as any
if (user?.length) {
checkedWorkspace.value = workspace.value.filter((ele) => user.includes(ele.id))
checkTableList.value = [...checkedWorkspace.value]
handleCheckedWorkspaceChange(checkedWorkspace.value)
}
loading.value = false
@@ -174,7 +204,7 @@ defineExpose({
.ed-checkbox,
.ed-checkbox__label,
.flex {
width: 100%;
width: 96%;
height: 44px;
}
@@ -172,6 +172,7 @@ const emits = defineEmits(['update:item', 'del'])
style="max-width: 280px; margin-left: 8px"
:placeholder="$t('datasource.please_enter')"
class="input-with-select"
clearable
>
<template #prepend>
<el-select
+9 -2
View File
@@ -7,6 +7,7 @@
v-model="keyword"
style="width: 240px; margin-right: 12px"
:placeholder="$t('user.name_account_email')"
clearable
@keyup.enter="handleSearch"
@blur="handleSearch"
>
@@ -240,6 +241,7 @@
:placeholder="$t('datasource.please_enter') + $t('common.empty') + $t('user.name')"
autocomplete="off"
maxlength="50"
clearable
/>
</el-form-item>
<el-form-item prop="account" :label="t('user.account')">
@@ -249,6 +251,7 @@
:placeholder="$t('datasource.please_enter') + $t('common.empty') + $t('user.account')"
autocomplete="off"
maxlength="50"
clearable
/>
</el-form-item>
<el-form-item prop="email" :label="$t('user.email')">
@@ -256,6 +259,7 @@
v-model="state.form.email"
:placeholder="$t('datasource.please_enter') + $t('common.empty') + $t('user.email')"
autocomplete="off"
clearable
/>
</el-form-item>
<!-- <el-form-item :label="$t('user.phone_number')">
@@ -316,6 +320,7 @@
$t('datasource.please_enter') + $t('common.empty') + $t('user.new_password')
"
autocomplete="off"
clearable
/>
</el-form-item>
<el-form-item prop="old" :label="t('user.confirm_password')">
@@ -325,6 +330,7 @@
$t('datasource.please_enter') + $t('common.empty') + $t('user.confirm_password')
"
autocomplete="off"
clearable
/>
</el-form-item>
</el-form>
@@ -581,6 +587,7 @@ const handleToggleRowSelection = (check: boolean = true) => {
selectionLoading.value = false
}
const handleSearch = () => {
state.pageInfo.currentPage = 1
search()
}
const fillFilterText = () => {
@@ -715,8 +722,8 @@ const search = () => {
})
}
const addTerm = () => {
const { account, email, name, oid, status } = state.form
userApi.add({ account, email, name, oid, status }).then(() => {
const { account, email, name, oid, status, oid_list } = state.form
userApi.add({ account, email, name, oid, status, oid_list }).then(() => {
onFormClose()
search()
ElMessage({
+3 -2
View File
@@ -7,6 +7,7 @@
class="sqlbot-search"
placeholder="Search"
prefix-icon="el-icon-search"
clearable
@keyup.enter="handleSearch"
>
<template #prefix>
@@ -97,10 +98,10 @@
@submit.prevent
>
<el-form-item label="Account">
<el-input v-model="state.form.term" autocomplete="off" />
<el-input v-model="state.form.term" clearable autocomplete="off" />
</el-form-item>
<el-form-item label="Definition">
<el-input v-model="state.form.definition" type="textarea" />
<el-input v-model="state.form.definition" clearable type="textarea" />
</el-form-item>
<el-form-item label="Domain">
<el-select v-model="state.form.domain" placeholder="Please select a domain">
@@ -28,7 +28,6 @@
</el-input>
<div class="mt-8 max-height_workspace">
<el-checkbox
v-if="!search"
v-model="checkAll"
class="mb-8"
:indeterminate="isIndeterminate"
@@ -65,14 +64,14 @@
<div class="p-16 w-full">
<div class="flex-between mb-16">
<span class="lighter">
{{ $t('workspace.selected_2_people', { msg: checkedWorkspace.length }) }}
{{ $t('workspace.selected_2_people', { msg: checkTableList.length }) }}
</span>
<el-button text @click="clearWorkspaceAll">
{{ $t('workspace.clear') }}
</el-button>
</div>
<div v-for="ele in checkedWorkspace" :key="ele.name" class="flex-between align-center">
<div v-for="ele in checkTableList" :key="ele.name" class="flex-between align-center">
<div
:title="`${ele.name}(${ele.account})`"
class="flex align-center ellipsis"
@@ -106,7 +105,7 @@
</template>
<script lang="ts" setup>
import { ref, computed } from 'vue'
import { ref, computed, watch } from 'vue'
import { workspaceOptionUserList, workspaceUwsCreate } from '@/api/workspace'
import avatar_personal from '@/assets/svg/avatar_personal.svg'
import Close from '@/assets/svg/icon_close_outlined_w.svg'
@@ -120,23 +119,51 @@ const listType = ref(0)
const search = ref('')
const loading = ref(false)
const centerDialogVisible = ref(false)
const checkTableList = ref([] as any[])
const workspaceWithKeywords = computed(() => {
return workspace.value.filter((ele: any) =>
(ele.name.toLowerCase() as string).includes(search.value.toLowerCase())
)
})
watch(search, () => {
const tableNameArr = workspaceWithKeywords.value.map((ele: any) => ele.name)
checkedWorkspace.value = checkTableList.value.filter((ele) => tableNameArr.includes(ele.name))
const checkedCount = checkedWorkspace.value.length
checkAll.value = checkedCount === workspaceWithKeywords.value.length
isIndeterminate.value = checkedCount > 0 && checkedCount < workspaceWithKeywords.value.length
})
const handleCheckAllChange = (val: CheckboxValueType) => {
checkedWorkspace.value = val ? workspace.value : []
const tableNameArr = workspaceWithKeywords.value.map((ele: any) => ele.name)
checkedWorkspace.value = val
? [
...new Set([
...workspaceWithKeywords.value,
...checkedWorkspace.value.filter((ele) => !tableNameArr.includes(ele.name)),
]),
]
: []
isIndeterminate.value = false
if (!val) {
clearWorkspaceAll()
}
checkTableList.value = val
? [
...new Set([
...workspaceWithKeywords.value,
...checkTableList.value.filter((ele) => !tableNameArr.includes(ele.name)),
]),
]
: checkTableList.value.filter((ele) => !tableNameArr.includes(ele.name))
}
const handleCheckedWorkspaceChange = (value: CheckboxValueType[]) => {
const checkedCount = value.length
checkAll.value = checkedCount === workspace.value.length
isIndeterminate.value = checkedCount > 0 && checkedCount < workspace.value.length
checkAll.value = checkedCount === workspaceWithKeywords.value.length
isIndeterminate.value = checkedCount > 0 && checkedCount < workspaceWithKeywords.value.length
const tableNameArr = workspaceWithKeywords.value.map((ele: any) => ele.name)
checkTableList.value = [
...new Set([
...checkTableList.value.filter((ele) => !tableNameArr.includes(ele.name)),
...value,
]),
]
}
let oid: any = null
@@ -145,6 +172,7 @@ const open = async (id: any) => {
search.value = ''
oid = id
checkedWorkspace.value = []
checkTableList.value = []
checkAll.value = false
isIndeterminate.value = false
const systemWorkspaceList = await workspaceOptionUserList({ oid }, 1, 1000)
@@ -205,7 +233,7 @@ defineExpose({
.ed-checkbox,
.ed-checkbox__label,
.flex {
width: 100%;
width: 96%;
height: 44px;
}
@@ -69,12 +69,14 @@ defineExpose({
<el-form-item prop="key" :label="$t('model.parameters')">
<el-input
v-model="paramsForm.key"
clearable
:placeholder="$t('datasource.please_enter') + $t('common.empty') + $t('model.parameters')"
/>
</el-form-item>
<el-form-item prop="name" :label="$t('model.display_name')">
<el-input
v-model="paramsForm.name"
clearable
:placeholder="
$t('datasource.please_enter') + $t('common.empty') + $t('model.display_name')
"
@@ -83,6 +85,7 @@ defineExpose({
<el-form-item prop="val" :label="$t('model.parameter_value')">
<el-input
v-model="paramsForm.val"
clearable
:placeholder="
$t('datasource.please_enter') + $t('common.empty') + $t('model.parameter_value')
"
@@ -549,6 +549,7 @@ const handleCurrentChange = (val: number) => {
<el-form-item prop="name" :label="t('workspace.workspace_name')">
<el-input
v-model="workspaceForm.name"
clearable
maxlength="50"
:placeholder="
$t('datasource.please_enter') + $t('common.empty') + $t('workspace.workspace_name')
+6 -1
View File
@@ -55,7 +55,12 @@ const dialogVisible = ref(false)
modal-class="select-datasource_dialog"
>
<div class="search-datasource">
<el-input v-model="datasourceName" style="width: 240px" placeholder="Please input" />
<el-input
v-model="datasourceName"
clearable
style="width: 240px"
placeholder="Please input"
/>
</div>
<div class="datasource-content">
<DatasourceCard