Merge remote-tracking branch 'upstream/dev' into dev_20230206

# Conflicts:
#	mayfly_go_web/src/views/ops/db/SqlExec.vue
#	mayfly_go_web/src/views/ops/db/component/InstanceTree.vue
#	mayfly_go_web/src/views/ops/mongo/MongoInstanceTree.vue
This commit is contained in:
刘宗洋
2023-02-07 10:59:46 +08:00
14 changed files with 838 additions and 773 deletions

View File

@@ -13,7 +13,7 @@
"countup.js": "^2.0.7", "countup.js": "^2.0.7",
"cropperjs": "^1.5.11", "cropperjs": "^1.5.11",
"echarts": "^5.4.0", "echarts": "^5.4.0",
"element-plus": "^2.2.26", "element-plus": "^2.2.29",
"jsencrypt": "^3.2.1", "jsencrypt": "^3.2.1",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"mitt": "^3.0.0", "mitt": "^3.0.0",
@@ -44,10 +44,10 @@
"eslint": "^8.5.0", "eslint": "^8.5.0",
"eslint-plugin-vue": "^8.2.0", "eslint-plugin-vue": "^8.2.0",
"prettier": "^2.3.0", "prettier": "^2.3.0",
"sass": "^1.45.1", "sass": "^1.58.0",
"sass-loader": "^12.4.0", "sass-loader": "^13.2.0",
"typescript": "^4.7.4", "typescript": "^4.7.4",
"vite": "^4.0.4", "vite": "^4.1.1",
"vue-eslint-parser": "^8.0.1" "vue-eslint-parser": "^8.0.1"
}, },
"browserslist": [ "browserslist": [

View File

@@ -1,6 +1,14 @@
function getBaseApiUrl() {
let path = window.location.pathname;
if (path == '/') {
return window.location.host;
}
return window.location.host + path;
}
const config = { const config = {
baseApiUrl: `${(window as any).globalConfig.BaseApiUrl}/api`, baseApiUrl: `${(window as any).globalConfig.BaseApiUrl || location.protocol + '//' + getBaseApiUrl()}/api`,
baseWsUrl: `${(window as any).globalConfig.BaseWsUrl || `${location.protocol == 'https:' ? 'wss:' : 'ws:'}//${location.host}`}/api`, baseWsUrl: `${(window as any).globalConfig.BaseWsUrl || `${location.protocol == 'https:' ? 'wss:' : 'ws:'}//${getBaseApiUrl()}`}/api`,
// 系统版本 // 系统版本
version: 'v1.3.1' version: 'v1.3.1'

View File

@@ -5,73 +5,80 @@
<el-button type="primary" icon="plus" @click="addQueryTab" size="small">新建查询</el-button> <el-button type="primary" icon="plus" @click="addQueryTab" size="small">新建查询</el-button>
</el-col> </el-col>
<el-col :span="4" style="border-left: 1px solid #eee; margin-top: 10px"> <el-col :span="4" style="border-left: 1px solid #eee; margin-top: 10px">
<InstanceTree <InstanceTree :instance-menu-max-height="state.instanceMenuMaxHeight" :instances="state.instances"
:instance-menu-max-height="state.instanceMenuMaxHeight" @init-load-instances="loadInstances" @change-instance="changeInstance" @change-schema="changeSchema"
:instances="state.instances" @load-table-names="loadSchemaTables" @load-table-data="loadTableData" />
@init-load-instances="loadInstances"
@change-instance="changeInstance"
@change-schema="changeSchema"
@load-table-names="loadSchemaTables"
@load-table-data="loadTableData"
/>
</el-col> </el-col>
<el-col :span="20"> <el-col :span="20">
<el-container id="data-exec" style="border-left: 1px solid #eee; margin-top: 10px"> <el-container id="data-exec" style="border-left: 1px solid #eee; margin-top: 10px">
<el-tabs @tab-remove="removeDataTab" @tab-click="onDataTabClick" style="width: 100%" v-model="state.activeName"> <el-tabs @tab-remove="removeDataTab" @tab-click="onDataTabClick" style="width: 100%"
v-model="state.activeName">
<el-tab-pane closable v-for="q in state.queryTabs" :key="q.id" :label="q.label" :name="q.name"> <el-tab-pane closable v-for="q in state.queryTabs" :key="q.id" :label="q.label" :name="q.name">
<div> <div>
<div> <div>
<div class="toolbar"> <div class="toolbar">
<div class="fl"> <div class="fl">
<el-link @click="onRunSql(q.dbId, q.db)" :underline="false" class="ml15" icon="VideoPlay"> <el-link @click="onRunSql(q.dbId, q.db)" :underline="false" class="ml15"
icon="VideoPlay">
</el-link> </el-link>
<el-divider direction="vertical" border-style="dashed" /> <el-divider direction="vertical" border-style="dashed" />
<el-tooltip class="box-item" effect="dark" content="format sql" placement="top"> <el-tooltip class="box-item" effect="dark" content="format sql"
<el-link @click="formatSql(q.dbId, q.db)" type="primary" :underline="false" icon="MagicStick"> placement="top">
<el-link @click="formatSql(q.dbId, q.db)" type="primary"
:underline="false" icon="MagicStick">
</el-link> </el-link>
</el-tooltip> </el-tooltip>
<el-divider direction="vertical" border-style="dashed" /> <el-divider direction="vertical" border-style="dashed" />
<el-tooltip class="box-item" effect="dark" content="commit" placement="top"> <el-tooltip class="box-item" effect="dark" content="commit" placement="top">
<el-link @click="onCommit(q.dbId, q.db)" type="success" :underline="false" icon="CircleCheck"> <el-link @click="onCommit(q.dbId, q.db)" type="success"
:underline="false" icon="CircleCheck">
</el-link> </el-link>
</el-tooltip> </el-tooltip>
<el-divider direction="vertical" border-style="dashed" /> <el-divider direction="vertical" border-style="dashed" />
<el-upload class="sql-file-exec" :before-upload="beforeUpload" <el-upload class="sql-file-exec" :before-upload="beforeUpload"
:on-success="execSqlFileSuccess" :headers="{ Authorization: token }" :data="{ dbId: q.dbId }" :action="getUploadSqlFileUrl(q.dbId, q.db)" :show-file-list="false" name="file" multiple :on-success="execSqlFileSuccess" :headers="{ Authorization: token }"
:limit="100"> :data="{ dbId: q.dbId }" :action="getUploadSqlFileUrl(q.dbId, q.db)"
<el-tooltip class="box-item" effect="dark" content="SQL脚本执行" placement="top"> :show-file-list="false" name="file" multiple :limit="100">
<el-link type="success" :underline="false" icon="Document"></el-link> <el-tooltip class="box-item" effect="dark" content="SQL脚本执行"
placement="top">
<el-link type="success" :underline="false"
icon="Document"></el-link>
</el-tooltip> </el-tooltip>
</el-upload> </el-upload>
</div> </div>
<div style="float: right" class="fl"> <div style="float: right" class="fl">
<el-select v-model="state.sqlName[q.dbId+q.db]" placeholder="选择or输入SQL模板名" @change="changeSqlTemplate(q.dbId, q.db)" <el-select v-model="state.sqlName[q.dbId + q.db]" placeholder="选择or输入SQL模板名"
filterable allow-create default-first-option size="small" class="mr10"> @change="changeSqlTemplate(q.dbId, q.db)" filterable allow-create
<el-option v-for="item in state.sqlNames[q.dbId+q.db]" :key="item" :label="item.database" default-first-option size="small" class="mr10">
:value="item"> <el-option v-for="item in state.sqlNames[q.dbId + q.db]" :key="item"
:label="item.database" :value="item">
{{ item }} {{ item }}
</el-option> </el-option>
</el-select> </el-select>
<el-button @click="saveSql(q.dbId, q.db)" type="primary" icon="document-add" plain size="small">保存 <el-button @click="saveSql(q.dbId, q.db)" type="primary" icon="document-add"
plain size="small">保存
</el-button> </el-button>
<el-button @click="deleteSql(q.dbId, q.db)" type="danger" icon="delete" plain size="small">删除 <el-button @click="deleteSql(q.dbId, q.db)" type="danger" icon="delete"
plain size="small">删除
</el-button> </el-button>
</div> </div>
</div> </div>
</div> </div>
<div class="mt5 sqlEditor"> <div class="mt5 sqlEditor">
<div :id="'MonacoTextarea-'+ q.id" :style="{ height: state.monacoOptions.height }"></div> <div :id="'MonacoTextarea-' + q.id" :style="{ height: state.monacoOptions.height }">
</div>
</div> </div>
<div class="mt5"> <div class="mt5">
<el-row> <el-row>
<el-link v-if="q.nowTableName" @click="onDeleteData(q.dbId, q.db, q.nowTableName)" class="ml5" type="danger" <el-link v-if="q.nowTableName"
icon="delete" :underline="false"></el-link> @click="onDeleteData(q.dbId, q.db, q.nowTableName)" class="ml5"
type="danger" icon="delete" :underline="false"></el-link>
<span v-if="q.execRes.data.length > 0"> <span v-if="q.execRes.data.length > 0">
<el-divider direction="vertical" border-style="dashed" /> <el-divider direction="vertical" border-style="dashed" />
@@ -80,7 +87,8 @@
</span> </span>
<span v-if="q.updatedFields.length > 0"> <span v-if="q.updatedFields.length > 0">
<el-divider direction="vertical" border-style="dashed" /> <el-divider direction="vertical" border-style="dashed" />
<el-link type="success" :underline="false" @click="submitUpdateFields(q.dbId, q.db, q.nowTableName)"><span <el-link type="success" :underline="false"
@click="submitUpdateFields(q.dbId, q.db, q.nowTableName)"><span
style="font-size: 12px">提交</span></el-link> style="font-size: 12px">提交</span></el-link>
</span> </span>
<span v-if="q.updatedFields.length > 0"> <span v-if="q.updatedFields.length > 0">
@@ -89,25 +97,24 @@
style="font-size: 12px">取消</span></el-link> style="font-size: 12px">取消</span></el-link>
</span> </span>
</el-row> </el-row>
<el-table @cell-dblclick="(row, column, cell, event) => cellClick(row, column, cell, event, {dbId: q.dbId, db: q.db, tableName: q.nowTableName})" <el-table
@selection-change="onDataSelectionChange" size="small" @cell-dblclick="(row: any, column: any, cell: any, event: any) => cellClick(row, column, cell, event, { dbId: q.dbId, db: q.db, tableName: q.nowTableName })"
:data="q.execRes.data" v-loading="q.loading" element-loading-text="查询中..." @selection-change="onDataSelectionChange" size="small" :data="q.execRes.data"
empty-text="tips: select *开头的单表查询或点击表名默认查询的数据,可双击数据在线修改" stripe border class="mt5"> v-loading="q.loading" element-loading-text="查询中..."
empty-text="tips: select *开头的单表查询或点击表名默认查询的数据,可双击数据在线修改" stripe border
class="mt5">
<el-table-column v-if="q.execRes.tableColumn.length > 0 && q.nowTableName" <el-table-column v-if="q.execRes.tableColumn.length > 0 && q.nowTableName"
type="selection" width="35" /> type="selection" width="35" />
<el-table-column min-width="100" :width="flexColumnWidth(item, q.execRes.data)" <el-table-column min-width="100" :width="flexColumnWidth(item, q.execRes.data)"
align="center" v-for="item in q.execRes.tableColumn" :key="item" :prop="item" align="center" v-for="item in q.execRes.tableColumn" :key="item"
:label="item" show-overflow-tooltip> :prop="item" :label="item" show-overflow-tooltip>
</el-table-column> </el-table-column>
</el-table> </el-table>
<el-row type="flex" class="mt5" justify="center"> <el-row type="flex" class="mt5" justify="center">
<el-pagination <el-pagination v-show="q.execRes.showPage" small :total="q.execRes.total"
v-show="q.execRes.showPage" small
:total="q.execRes.total"
@current-change="doRunSql(q.dbId, q.db, q.sql)" @current-change="doRunSql(q.dbId, q.db, q.sql)"
layout="prev,pager,next,total,jumper" layout="prev,pager,next,total,jumper"
v-model:current-page="q.execRes.pageNum" v-model:current-page="q.execRes.pageNum" :page-size="defalutLimit">
:page-size="defalutLimit">
</el-pagination> </el-pagination>
</el-row> </el-row>
</div> </div>
@@ -115,39 +122,47 @@
</div> </div>
</el-tab-pane> </el-tab-pane>
<el-tab-pane closable v-for="dt in state.dataTabs" :key="dt.key" :label="dt.label" :name="dt.key"> <el-tab-pane closable v-for="dt in state.dataTabs" :key="dt.key" :label="dt.label"
:name="dt.key">
<el-row> <el-row>
<el-col :span="8"> <el-col :span="8">
<el-link @click="onRefresh(dt.dbId, dt.db,dt.name)" icon="refresh" :underline="false" class="ml5"> <el-link @click="onRefresh(dt.dbId, dt.db, dt.name)" icon="refresh"
:underline="false" class="ml5">
</el-link> </el-link>
<el-divider direction="vertical" border-style="dashed" /> <el-divider direction="vertical" border-style="dashed" />
<el-link @click="addRow(dt.dbId, dt.db, dt.name)" type="primary" icon="plus" :underline="false"></el-link> <el-link @click="addRow(dt.dbId, dt.db, dt.name)" type="primary" icon="plus"
:underline="false"></el-link>
<el-divider direction="vertical" border-style="dashed" /> <el-divider direction="vertical" border-style="dashed" />
<el-link @click="onDeleteData(dt.dbId, dt.db, dt.name)" type="danger" icon="delete" :underline="false"></el-link> <el-link @click="onDeleteData(dt.dbId, dt.db, dt.name)" type="danger" icon="delete"
:underline="false"></el-link>
<el-divider direction="vertical" border-style="dashed" /> <el-divider direction="vertical" border-style="dashed" />
<el-tooltip class="box-item" effect="dark" content="commit" placement="top"> <el-tooltip class="box-item" effect="dark" content="commit" placement="top">
<el-link @click="onCommit(dt.dbId, dt.db)" type="success" icon="CircleCheck" :underline="false"> <el-link @click="onCommit(dt.dbId, dt.db)" type="success" icon="CircleCheck"
:underline="false">
</el-link> </el-link>
</el-tooltip> </el-tooltip>
<el-divider direction="vertical" border-style="dashed" /> <el-divider direction="vertical" border-style="dashed" />
<el-tooltip class="box-item" effect="dark" content="生成insert sql" placement="top"> <el-tooltip class="box-item" effect="dark" content="生成insert sql" placement="top">
<el-link @click="onGenerateInsertSql(dt.dbId, dt.db, dt.name)" type="success" :underline="false">gi</el-link> <el-link @click="onGenerateInsertSql(dt.dbId, dt.db, dt.name)" type="success"
:underline="false">gi</el-link>
</el-tooltip> </el-tooltip>
<el-divider direction="vertical" border-style="dashed" /> <el-divider direction="vertical" border-style="dashed" />
<el-tooltip v-if="state.updatedFields[state.nowTableName]?.length > 0" class="box-item" <el-tooltip v-if="state.updatedFields[state.nowTableName]?.length > 0"
effect="dark" content="提交修改" placement="top"> class="box-item" effect="dark" content="提交修改" placement="top">
<el-link @click="submitUpdateFields(dt.dbId, dt.db, dt.name)" type="success" :underline="false">提交</el-link> <el-link @click="submitUpdateFields(dt.dbId, dt.db, dt.name)" type="success"
:underline="false">提交</el-link>
</el-tooltip> </el-tooltip>
<el-divider v-if="state.updatedFields[state.nowTableName]?.length > 0" direction="vertical" <el-divider v-if="state.updatedFields[state.nowTableName]?.length > 0"
border-style="dashed" /> direction="vertical" border-style="dashed" />
<el-tooltip v-if="state.updatedFields[state.nowTableName]?.length > 0" class="box-item" <el-tooltip v-if="state.updatedFields[state.nowTableName]?.length > 0"
effect="dark" content="取消修改" placement="top"> class="box-item" effect="dark" content="取消修改" placement="top">
<el-link @click="cancelUpdateFields" type="warning" :underline="false">取消</el-link> <el-link @click="cancelUpdateFields" type="warning"
:underline="false">取消</el-link>
</el-tooltip> </el-tooltip>
</el-col> </el-col>
<el-col :span="16"> <el-col :span="16">
@@ -164,9 +179,11 @@
onConditionRowClick(event, dt); onConditionRowClick(event, dt);
} }
" style="cursor: pointer"> " style="cursor: pointer">
<el-table-column property="columnName" label="列名" show-overflow-tooltip> <el-table-column property="columnName" label="列名"
show-overflow-tooltip>
</el-table-column> </el-table-column>
<el-table-column property="columnComment" label="备注" show-overflow-tooltip> <el-table-column property="columnComment" label="备注"
show-overflow-tooltip>
</el-table-column> </el-table-column>
</el-table> </el-table>
</el-popover> </el-popover>
@@ -179,15 +196,16 @@
</el-input> </el-input>
</el-col> </el-col>
</el-row> </el-row>
<el-table @cell-dblclick="(row, column, cell, event) => cellClick(row, column, cell, event, {dbId: dt.dbId, db: dt.db, tableName: dt.name})" <el-table
@sort-change="sort => onTableSortChange(dt.dbId, dt.db, sort, dt.name)" @cell-dblclick="(row: any, column: any, cell: any, event: any) => cellClick(row, column, cell, event, { dbId: dt.dbId, db: dt.db, tableName: dt.name })"
@sort-change="(sort: any) => onTableSortChange(dt.dbId, dt.db, sort, dt.name)"
@selection-change="onDataSelectionChange" :data="dt.datas" size="small" @selection-change="onDataSelectionChange" :data="dt.datas" size="small"
:max-height="state.dataTabsTableHeight" v-loading="dt.loading" element-loading-text="查询中..." :max-height="state.dataTabsTableHeight" v-loading="dt.loading"
empty-text="暂无数据" stripe border class="mt5"> element-loading-text="查询中..." empty-text="暂无数据" stripe border class="mt5">
<el-table-column v-if="dt.datas.length > 0" type="selection" width="35" /> <el-table-column v-if="dt.datas.length > 0" type="selection" width="35" />
<el-table-column min-width="100" :width="flexColumnWidth(item, dt.datas)" align="center" <el-table-column min-width="100" :width="flexColumnWidth(item, dt.datas)" align="center"
v-for="item in dt.columnNames" :key="item" :prop="item" :label="item" show-overflow-tooltip v-for="item in dt.columnNames" :key="item" :prop="item" :label="item"
:sortable="state.nowTableName !== '' ? 'custom' : false"> show-overflow-tooltip :sortable="state.nowTableName !== '' ? 'custom' : false">
<template #header> <template #header>
<el-tooltip raw-content placement="top" effect="customized"> <el-tooltip raw-content placement="top" effect="customized">
<template #content> {{ getColumnTip(dt.name, item) }} </template> <template #content> {{ getColumnTip(dt.name, item) }} </template>
@@ -232,7 +250,8 @@
</template> </template>
</el-dialog> </el-dialog>
<el-dialog @close="state.genSqlDialog.visible = false" v-model="state.genSqlDialog.visible" title="SQL" width="1000px"> <el-dialog @close="state.genSqlDialog.visible = false" v-model="state.genSqlDialog.visible" title="SQL"
width="1000px">
<el-input v-model="state.genSqlDialog.sql" type="textarea" rows="20" /> <el-input v-model="state.genSqlDialog.sql" type="textarea" rows="20" />
</el-dialog> </el-dialog>
</div> </div>
@@ -724,7 +743,7 @@ onMounted(() => {
const setHeight = () => { const setHeight = () => {
// 默认300px // 默认300px
state.monacoOptions.height = window.innerHeight - 550 + 'px' state.monacoOptions.height = window.innerHeight - 550 + 'px'
state.dataTabsTableHeight = window.innerHeight - 219; state.dataTabsTableHeight = window.innerHeight - 219 - 36;
state.instanceMenuMaxHeight = window.innerHeight - 140 + 'px'; state.instanceMenuMaxHeight = window.innerHeight - 140 + 'px';
}; };
@@ -1445,7 +1464,8 @@ const cellClick = (row: any, column: any, cell: any, event: Event, tabInfo: {dbI
const primaryKeyValue = row[primaryKey.columnName]; const primaryKeyValue = row[primaryKey.columnName];
// 更新字段列信息 // 更新字段列信息
const updateColumn = await getColumn(tabInfo.tableName, property); const updateColumn = await getColumn(tabInfo.tableName, property);
const newField = { div, row, const newField = {
div, row,
fieldName: column.rawColumnKey, fieldName: column.rawColumnKey,
fieldType: updateColumn.columnType, fieldType: updateColumn.columnType,
oldValue: text, oldValue: text,
@@ -1460,7 +1480,8 @@ const cellClick = (row: any, column: any, cell: any, event: Event, tabInfo: {dbI
primaryKey: primaryKeyValue, primaryKey: primaryKeyValue,
primaryKeyName: primaryKey.columnName, primaryKeyName: primaryKey.columnName,
primaryKeyType: primaryKey.columnType, primaryKeyType: primaryKey.columnType,
fields: [newField] } fields: [newField]
}
} else { } else {
hasKey = true hasKey = true
let hasField = primaryKeyFields[0].fields.some(a => { let hasField = primaryKeyFields[0].fields.some(a => {
@@ -1833,8 +1854,10 @@ const addQueryTab = async () => {
#data-exec { #data-exec {
min-height: calc(100vh - 155px); min-height: calc(100vh - 155px);
.el-tabs__header { .el-tabs__header {
margin: 0 0 5px; margin: 0 0 5px;
.el-tabs__item { .el-tabs__item {
padding: 0 5px; padding: 0 5px;
} }

View File

@@ -6,53 +6,54 @@
<!-- 第一级tag --> <!-- 第一级tag -->
<el-sub-menu v-for="tag of instances.tags" :index="tag.tagPath" :key="tag.tagPath"> <el-sub-menu v-for="tag of instances.tags" :index="tag.tagPath" :key="tag.tagPath">
<template #title> <template #title>
<el-icon><FolderOpened color="#e6a23c"/></el-icon> <el-icon>
<FolderOpened color="#e6a23c" />
</el-icon>
<span>{{ tag.tagPath }}</span> <span>{{ tag.tagPath }}</span>
</template> </template>
<!-- 第二级数据库实例 --> <!-- 第二级数据库实例 -->
<el-sub-menu v-for="inst in instances.tree[tag.tagId]" <el-sub-menu v-for="inst in instances.tree[tag.tagId]" :index="'instance-' + inst.id"
:index="'instance-' + inst.id" :key="'instance-' + inst.id" @click="changeInstance(inst, ()=>{})">
:key="'instance-' + inst.id"
@click="changeInstance(inst, ()=>{})"
>
<template #title> <template #title>
<el-popover <el-popover placement="right-start" title="数据库实例信息" trigger="hover" :width="210">
placement="right-start"
title="数据库实例信息"
trigger="hover"
:width="210"
>
<template #reference> <template #reference>
<span>&nbsp;&nbsp;<el-icon><MostlyCloudy color="#409eff"/></el-icon>{{ inst.name }}</span> <span>&nbsp;&nbsp;<el-icon>
<MostlyCloudy color="#409eff" />
</el-icon>{{ inst.name }}</span>
</template> </template>
<template #default> <template #default>
<el-form class="instances-pop-form" label-width="55px" :size="'small'"> <el-form class="instances-pop-form" label-width="55px" :size="'small'">
<el-form-item label="类型:">{{ inst.type }}</el-form-item> <el-form-item label="类型:">{{ inst.type }}</el-form-item>
<el-form-item label="链接:">{{ inst.host }}:{{ inst.port }}</el-form-item> <el-form-item label="链接:">{{ inst.host }}:{{ inst.port }}</el-form-item>
<el-form-item label="用户:">{{ inst.username }}</el-form-item> <el-form-item label="用户:">{{ inst.username }}</el-form-item>
<el-form-item v-if="inst.remark" label="备注:">{{inst.remark}}</el-form-item> <el-form-item v-if="inst.remark" label="备注:">{{
inst.remark
}}</el-form-item>
</el-form> </el-form>
</template> </template>
</el-popover> </el-popover>
</template> </template>
<!-- 第三级数据库 --> <!-- 第三级数据库 -->
<el-sub-menu v-for="schema in instances.dbs[inst.id]" <el-sub-menu v-for="schema in instances.dbs[inst.id]" :index="inst.id + schema"
:index="inst.id + schema" :key="inst.id + schema" :class="state.nowSchema === (inst.id + schema) && 'checked'"
:key="inst.id + schema" @click="changeSchema(inst, schema)">
:class="state.nowSchema === (inst.id+schema) && 'checked'"
@click="changeSchema(inst, schema)"
>
<template #title> <template #title>
&nbsp;&nbsp;&nbsp;&nbsp;<el-icon><Coin color="#67c23a"/></el-icon> &nbsp;&nbsp;&nbsp;&nbsp;<el-icon>
<Coin color="#67c23a" />
</el-icon>
<span class="checked-schema">{{ schema }}</span> <span class="checked-schema">{{ schema }}</span>
</template> </template>
<!-- 第四级 01 --> <!-- 第四级 01 -->
<el-sub-menu :index="inst.id + schema + '-table'"> <el-sub-menu :index="inst.id + schema + '-table'">
<template #title> <template #title>
<div style="width: 100%" @click="loadTableNames(inst, schema, ()=>{})"> <div style="width: 100%" @click="loadTableNames(inst, schema, ()=>{})">
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<el-icon><Calendar color="#409eff"/></el-icon> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<el-icon>
<Calendar color="#409eff"/>
</el-icon>
<span></span> <span></span>
<el-icon v-show="state.loading[inst.id + schema]" class="is-loading"><Loading /></el-icon> <el-icon v-show="state.loading[inst.id + schema]" class="is-loading">
<Loading />
</el-icon>
</div> </div>
</template> </template>
<el-menu-item :index="inst.id + schema + '-tableSearch'" <el-menu-item :index="inst.id + schema + '-tableSearch'"
@@ -61,21 +62,25 @@
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<el-input size="small" placeholder="过滤表" clearable <el-input size="small" placeholder="过滤表" clearable
@change="filterTableName(inst.id, schema)" @change="filterTableName(inst.id, schema)"
@keyup="e => filterTableName(inst.id, schema, e)" @keyup="(e: any) => filterTableName(inst.id, schema, e)"
v-model="state.filterParam[inst.id + schema]" /> v-model="state.filterParam[inst.id + schema]" />
</template> </template>
</el-menu-item> </el-menu-item>
<template v-for="tb in instances.tables[inst.id + schema]"> <template v-for="tb in instances.tables[inst.id + schema]">
<el-menu-item :index="inst.id + schema + tb.tableName" <el-menu-item :index="inst.id + schema + tb.tableName"
:key="inst.id + schema + tb.tableName" :key="inst.id + schema + tb.tableName" v-if="tb.show"
v-if="tb.show" @click="loadTableData(inst, schema, tb.tableName)">
@click="loadTableData(inst, schema, tb.tableName)"
>
<template #title> <template #title>
<div style="width: 100%"> <div style="width: 100%">
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<el-icon><Calendar color="#409eff"/></el-icon> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<el-icon>
<span :title="tb.tableComment||''">{{tb.tableName}}</span> <Calendar color="#409eff" />
</el-icon>
<el-tooltip v-if="tb.tableComment" effect="customized"
:content="tb.tableComment" placement="right">
{{ tb.tableName }}
</el-tooltip>
<span v-else>{{ tb.tableName }}</span>
</div> </div>
</template> </template>
</el-menu-item> </el-menu-item>
@@ -84,19 +89,21 @@
<!-- 第四级 02sql --> <!-- 第四级 02sql -->
<el-sub-menu :index="inst.id + schema + '-sql'"> <el-sub-menu :index="inst.id + schema + '-sql'">
<template #title> <template #title>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<el-icon><List color="#f56c6c"/></el-icon> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<el-icon>
<List color="#f56c6c" />
</el-icon>
<span>sql</span> <span>sql</span>
</template> </template>
<template v-for="sql in instances.sqls[inst.id + schema]"> <template v-for="sql in instances.sqls[inst.id + schema]">
<el-menu-item :index="inst.id + schema + sql.name" <el-menu-item :index="inst.id + schema + sql.name"
:key="inst.id + schema + sql.name" :key="inst.id + schema + sql.name" v-if="sql.show"
v-if="sql.show" @click="loadSql(inst, schema, sql.name)">
@click="loadSql(inst, schema, sql.name)"
>
<template #title> <template #title>
<div style="width: 100%"> <div style="width: 100%">
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<el-icon><Calendar color="#409eff"/></el-icon> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<el-icon>
<Calendar color="#409eff" />
</el-icon>
<span>{{ sql.name }}</span> <span>{{ sql.name }}</span>
</div> </div>
</template> </template>
@@ -236,8 +243,9 @@ watch(()=>store.state.sqlExecInfo.dbOptInfo, async newValue => {
<style lang="scss"> <style lang="scss">
.instances-box { .instances-box {
.el-menu { .el-menu {
width: 275px; width: 100%;
} }
.el-sub-menu { .el-sub-menu {
.checked { .checked {
.checked-schema { .checked-schema {
@@ -245,28 +253,34 @@ watch(()=>store.state.sqlExecInfo.dbOptInfo, async newValue => {
} }
} }
} }
.el-sub-menu__title { .el-sub-menu__title {
padding-left: 0 !important; padding-left: 0 !important;
height: 30px !important; height: 30px !important;
line-height: 30px !important; line-height: 30px !important;
} }
.el-menu--vertical:not(.el-menu--collapse):not(.el-menu--popup-container) .el-sub-menu__title { .el-menu--vertical:not(.el-menu--collapse):not(.el-menu--popup-container) .el-sub-menu__title {
padding-right: 10px; padding-right: 10px;
} }
.el-menu-item { .el-menu-item {
padding-left: 0 !important; padding-left: 0 !important;
height: 20px !important; height: 20px !important;
line-height: 20px !important; line-height: 20px !important;
} }
.el-icon { .el-icon {
margin: 0; margin: 0;
} }
.el-sub-menu__icon-arrow { .el-sub-menu__icon-arrow {
top: inherit; top: inherit;
right: 10px; right: 10px;
} }
} }
.instances-pop-form { .instances-pop-form {
.el-form-item { .el-form-item {
margin-bottom: unset; margin-bottom: unset;

View File

@@ -11,7 +11,9 @@
<!-- 第一级tag --> <!-- 第一级tag -->
<el-sub-menu v-for="tag of instances.tags" :index="tag.tagPath" :key="tag.tagPath"> <el-sub-menu v-for="tag of instances.tags" :index="tag.tagPath" :key="tag.tagPath">
<template #title> <template #title>
<el-icon><FolderOpened color="#e6a23c"/></el-icon> <el-icon>
<FolderOpened color="#e6a23c" />
</el-icon>
<span>{{ tag.tagPath }}</span> <span>{{ tag.tagPath }}</span>
</template> </template>
<!-- 第二级数据库实例 --> <!-- 第二级数据库实例 -->
@@ -21,14 +23,11 @@
@click.prevent="changeInstance(inst, ()=>{})" @click.prevent="changeInstance(inst, ()=>{})"
> >
<template #title> <template #title>
<el-popover <el-popover placement="right-start" title="mongo数据库实例信息" trigger="hover" :width="210">
placement="right-start"
title="mongo数据库实例信息"
trigger="hover"
:width="210"
>
<template #reference> <template #reference>
<span>&nbsp;&nbsp;<el-icon><MostlyCloudy color="#409eff"/></el-icon>{{ inst.name }}</span> <span>&nbsp;&nbsp;<el-icon>
<MostlyCloudy color="#409eff" />
</el-icon>{{ inst.name }}</span>
</template> </template>
<template #default> <template #default>
<el-form class="instances-pop-form" label-width="55px" :size="'small'"> <el-form class="instances-pop-form" label-width="55px" :size="'small'">
@@ -39,26 +38,31 @@
</el-popover> </el-popover>
</template> </template>
<!-- 第三级数据库 --> <!-- 第三级数据库 -->
<el-sub-menu v-for="db in instances.dbs[inst.id]" <el-sub-menu v-for="db in instances.dbs[inst.id]" :index="inst.id + db.Name"
:index="inst.id + db.Name" :key="inst.id + db.Name" :class="state.nowSchema === (inst.id + db.Name) && 'checked'"
:key="inst.id + db.Name" @click.prevent="changeSchema(inst, db.Name)">
:class="state.nowSchema === (inst.id+db.Name) && 'checked'"
@click.prevent="changeSchema(inst, db.Name)"
>
<template #title> <template #title>
&nbsp;&nbsp;&nbsp;&nbsp;<el-icon><Coin color="#67c23a"/></el-icon> &nbsp;&nbsp;&nbsp;&nbsp;<el-icon>
<Coin color="#67c23a" />
</el-icon>
<span class="checked-schema"> <span class="checked-schema">
{{ db.Name }} {{ db.Name }}
<span style="color: #8492a6;font-size: 13px">[{{formatByteSize(db.SizeOnDisk)}}]</span> <span style="color: #8492a6;font-size: 13px">[{{
formatByteSize(db.SizeOnDisk)
}}]</span>
</span> </span>
</template> </template>
<!-- 第四级 01 --> <!-- 第四级 01 -->
<el-sub-menu :index="inst.id + db.Name + '-table'"> <el-sub-menu :index="inst.id + db.Name + '-table'">
<template #title> <template #title>
<div style="width: 100%" @click="loadTableNames(inst, db.Name, ()=>{})"> <div style="width: 100%" @click="loadTableNames(inst, db.Name, ()=>{})">
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<el-icon><Calendar color="#409eff"/></el-icon> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<el-icon>
<Calendar color="#409eff"/>
</el-icon>
<span>集合</span> <span>集合</span>
<el-icon v-show="state.loading[inst.id + db.Name]" class="is-loading"><Loading /></el-icon> <el-icon v-show="state.loading[inst.id + db.Name]" class="is-loading">
<Loading />
</el-icon>
</div> </div>
</template> </template>
<el-menu-item :index="inst.id + db.Name + '-tableSearch'" <el-menu-item :index="inst.id + db.Name + '-tableSearch'"
@@ -67,20 +71,20 @@
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<el-input size="small" placeholder="过滤" clearable <el-input size="small" placeholder="过滤" clearable
@change="filterTableName(inst.id, db.Name)" @change="filterTableName(inst.id, db.Name)"
@keyup="e => filterTableName(inst.id, db.Name, e)" @keyup="(e: any) => filterTableName(inst.id, db.Name, e)"
v-model="state.filterParam[inst.id + db.Name]" /> v-model="state.filterParam[inst.id + db.Name]" />
</template> </template>
</el-menu-item> </el-menu-item>
<template v-for="tb in instances.tables[inst.id + db.Name]"> <template v-for="tb in instances.tables[inst.id + db.Name]">
<el-menu-item :index="inst.id + db.Name + tb.tableName" <el-menu-item :index="inst.id + db.Name + tb.tableName"
:key="inst.id + db.Name + tb.tableName" :key="inst.id + db.Name + tb.tableName" v-if="tb.show"
v-if="tb.show" @click="loadTableData(inst, db.Name, tb.tableName)">
@click="loadTableData(inst, db.Name, tb.tableName)"
>
<template #title> <template #title>
<div style="width: 100%"> <div style="width: 100%">
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<el-icon><Calendar color="#409eff"/></el-icon> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<el-icon>
<Calendar color="#409eff" />
</el-icon>
<span :title="tb.tableComment || ''">{{ tb.tableName }}</span> <span :title="tb.tableComment || ''">{{ tb.tableName }}</span>
</div> </div>
</template> </template>
@@ -224,8 +228,9 @@ watch(()=>store.state.mongoDbOptInfo.dbOptInfo, async newValue => {
<style lang="scss"> <style lang="scss">
.instances-box { .instances-box {
.el-menu { .el-menu {
width: 275px; width: 100%;
} }
.el-sub-menu { .el-sub-menu {
.checked { .checked {
.checked-schema { .checked-schema {
@@ -233,28 +238,34 @@ watch(()=>store.state.mongoDbOptInfo.dbOptInfo, async newValue => {
} }
} }
} }
.el-sub-menu__title { .el-sub-menu__title {
padding-left: 0 !important; padding-left: 0 !important;
height: 30px !important; height: 30px !important;
line-height: 30px !important; line-height: 30px !important;
} }
.el-menu--vertical:not(.el-menu--collapse):not(.el-menu--popup-container) .el-sub-menu__title { .el-menu--vertical:not(.el-menu--collapse):not(.el-menu--popup-container) .el-sub-menu__title {
padding-right: 10px; padding-right: 10px;
} }
.el-menu-item { .el-menu-item {
padding-left: 0 !important; padding-left: 0 !important;
height: 20px !important; height: 20px !important;
line-height: 20px !important; line-height: 20px !important;
} }
.el-icon { .el-icon {
margin: 0; margin: 0;
} }
.el-sub-menu__icon-arrow { .el-sub-menu__icon-arrow {
top: inherit; top: inherit;
right: 10px; right: 10px;
} }
} }
.instances-pop-form { .instances-pop-form {
.el-form-item { .el-form-item {
margin-bottom: unset; margin-bottom: unset;

View File

@@ -122,7 +122,6 @@ const cancel = () => {
watch(props, async (newValue: any) => { watch(props, async (newValue: any) => {
state.dialogVisible = newValue.visible; state.dialogVisible = newValue.visible;
state.key = newValue.key;
state.redisId = newValue.redisId; state.redisId = newValue.redisId;
state.db = newValue.db; state.db = newValue.db;
state.key = newValue.keyInfo; state.key = newValue.keyInfo;

View File

@@ -106,7 +106,6 @@ const cancel = () => {
watch(props, async (newValue: any) => { watch(props, async (newValue: any) => {
state.dialogVisible = newValue.visible; state.dialogVisible = newValue.visible;
state.key = newValue.key;
state.redisId = newValue.redisId; state.redisId = newValue.redisId;
state.db = newValue.db; state.db = newValue.db;
state.key = newValue.keyInfo; state.key = newValue.keyInfo;

View File

@@ -120,7 +120,6 @@ watch(
watch(props, async (newValue: any) => { watch(props, async (newValue: any) => {
state.dialogVisible = newValue.visible; state.dialogVisible = newValue.visible;
state.key = newValue.key;
state.redisId = newValue.redisId; state.redisId = newValue.redisId;
state.db = newValue.db; state.db = newValue.db;
state.key = newValue.keyInfo; state.key = newValue.keyInfo;

View File

@@ -772,10 +772,10 @@ echarts@^5.4.0:
tslib "2.3.0" tslib "2.3.0"
zrender "5.4.0" zrender "5.4.0"
element-plus@^2.2.26: element-plus@^2.2.29:
version "2.2.26" version "2.2.29"
resolved "https://registry.npmmirror.com/element-plus/-/element-plus-2.2.26.tgz#5e46aa5d8127786bb158713957f8a253b35bf019" resolved "https://registry.npmmirror.com/element-plus/-/element-plus-2.2.29.tgz#7dd72f9cafdc102ae3f9e4efe612e403ef713a74"
integrity sha512-O/rdY5m9DkclpVg8r3GynyqCunm7MxSR142xSsjrZA77bi7bcwA3SIy6SPEDqHi5R4KqgkGYgKSp4Q4e3irbYg== integrity sha512-g4dcrURrKkR5uUX8n5RVnnqGnimoki9HfqS4yHHG6XwCHBkZGozdq4x+478BzeWUe31h++BO+7dakSx4VnM8RQ==
dependencies: dependencies:
"@ctrl/tinycolor" "^3.4.1" "@ctrl/tinycolor" "^3.4.1"
"@element-plus/icons-vue" "^2.0.6" "@element-plus/icons-vue" "^2.0.6"
@@ -800,7 +800,7 @@ enquirer@^2.3.5:
dependencies: dependencies:
ansi-colors "^4.1.1" ansi-colors "^4.1.1"
esbuild@^0.16.3: esbuild@^0.16.14:
version "0.16.17" version "0.16.17"
resolved "https://registry.npmmirror.com/esbuild/-/esbuild-0.16.17.tgz#fc2c3914c57ee750635fee71b89f615f25065259" resolved "https://registry.npmmirror.com/esbuild/-/esbuild-0.16.17.tgz#fc2c3914c57ee750635fee71b89f615f25065259"
integrity sha512-G8LEkV0XzDMNwXKgM0Jwu3nY3lSTwSGY6XbxM9cr9+s0T/qSV1q1JVPBGzm3dcjhCic9+emZDmMffkwgPeOeLg== integrity sha512-G8LEkV0XzDMNwXKgM0Jwu3nY3lSTwSGY6XbxM9cr9+s0T/qSV1q1JVPBGzm3dcjhCic9+emZDmMffkwgPeOeLg==
@@ -1451,7 +1451,7 @@ postcss@^8.1.10:
picocolors "^1.0.0" picocolors "^1.0.0"
source-map-js "^1.0.1" source-map-js "^1.0.1"
postcss@^8.4.20: postcss@^8.4.21:
version "8.4.21" version "8.4.21"
resolved "https://registry.npmmirror.com/postcss/-/postcss-8.4.21.tgz#c639b719a57efc3187b13a1d765675485f4134f4" resolved "https://registry.npmmirror.com/postcss/-/postcss-8.4.21.tgz#c639b719a57efc3187b13a1d765675485f4134f4"
integrity sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg== integrity sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==
@@ -1533,10 +1533,10 @@ rimraf@^3.0.2:
dependencies: dependencies:
glob "^7.1.3" glob "^7.1.3"
rollup@^3.7.0: rollup@^3.10.0:
version "3.10.0" version "3.12.1"
resolved "https://registry.npmmirror.com/rollup/-/rollup-3.10.0.tgz#6eb19196d8b3b375ca651cb78261faac48e24cd6" resolved "https://registry.npmmirror.com/rollup/-/rollup-3.12.1.tgz#2975b97713e4af98c15e7024b88292d7fddb3853"
integrity sha512-JmRYz44NjC1MjVF2VKxc0M1a97vn+cDxeqWmnwyAF4FvpjK8YFdHpaqvQB+3IxCvX05vJxKZkoMDU8TShhmJVA== integrity sha512-t9elERrz2i4UU9z7AwISj3CQcXP39cWxgRWLdf4Tm6aKm1eYrqHIgjzXBgb67GNY1sZckTFFi0oMozh3/S++Ig==
optionalDependencies: optionalDependencies:
fsevents "~2.3.2" fsevents "~2.3.2"
@@ -1547,18 +1547,18 @@ run-parallel@^1.1.9:
dependencies: dependencies:
queue-microtask "^1.2.2" queue-microtask "^1.2.2"
sass-loader@^12.4.0: sass-loader@^13.2.0:
version "12.4.0" version "13.2.0"
resolved "https://registry.npmmirror.com/sass-loader/download/sass-loader-12.4.0.tgz" resolved "https://registry.npmmirror.com/sass-loader/-/sass-loader-13.2.0.tgz#80195050f58c9aac63b792fa52acb6f5e0f6bdc3"
integrity sha512-7xN+8khDIzym1oL9XyS6zP6Ges+Bo2B2xbPrjdMHEYyV3AQYhd/wXeru++3ODHF0zMjYmVadblSKrPrjEkL8mg== integrity sha512-JWEp48djQA4nbZxmgC02/Wh0eroSUutulROUusYJO9P9zltRbNN80JCBHqRGzjd4cmZCa/r88xgfkjGD0TXsHg==
dependencies: dependencies:
klona "^2.0.4" klona "^2.0.4"
neo-async "^2.6.2" neo-async "^2.6.2"
sass@^1.45.1: sass@^1.58.0:
version "1.48.0" version "1.58.0"
resolved "https://registry.npmmirror.com/sass/download/sass-1.48.0.tgz" resolved "https://registry.npmmirror.com/sass/-/sass-1.58.0.tgz#ee8aea3ad5ea5c485c26b3096e2df6087d0bb1cc"
integrity sha512-hQi5g4DcfjcipotoHZ80l7GNJHGqQS5LwMBjVYB/TaT0vcSSpbgM8Ad7cgfsB2M0MinbkEQQPO9+sjjSiwxqmw== integrity sha512-PiMJcP33DdKtZ/1jSjjqVIKihoDc6yWmYr9K/4r3fVVIEDAluD0q7XZiRKrNJcPK3qkLRF/79DND1H5q1LBjgg==
dependencies: dependencies:
chokidar ">=3.0.0 <4.0.0" chokidar ">=3.0.0 <4.0.0"
immutable "^4.0.0" immutable "^4.0.0"
@@ -1724,15 +1724,15 @@ v8-compile-cache@^2.0.3:
resolved "https://registry.nlark.com/v8-compile-cache/download/v8-compile-cache-2.3.0.tgz" resolved "https://registry.nlark.com/v8-compile-cache/download/v8-compile-cache-2.3.0.tgz"
integrity sha1-LeGWGMZtwkfc+2+ZM4A12CRaLO4= integrity sha1-LeGWGMZtwkfc+2+ZM4A12CRaLO4=
vite@^4.0.4: vite@^4.1.1:
version "4.0.4" version "4.1.1"
resolved "https://registry.npmmirror.com/vite/-/vite-4.0.4.tgz#4612ce0b47bbb233a887a54a4ae0c6e240a0da31" resolved "https://registry.npmmirror.com/vite/-/vite-4.1.1.tgz#3b18b81a4e85ce3df5cbdbf4c687d93ebf402e6b"
integrity sha512-xevPU7M8FU0i/80DMR+YhgrzR5KS2ORy1B4xcX/cXLsvnUWvfHuqMmVU6N0YiJ4JWGRJJsLCgjEzKjG9/GKoSw== integrity sha512-LM9WWea8vsxhr782r9ntg+bhSFS06FJgCvvB0+8hf8UWtvaiDagKYWXndjfX6kGl74keHJUcpzrQliDXZlF5yg==
dependencies: dependencies:
esbuild "^0.16.3" esbuild "^0.16.14"
postcss "^8.4.20" postcss "^8.4.21"
resolve "^1.22.1" resolve "^1.22.1"
rollup "^3.7.0" rollup "^3.10.0"
optionalDependencies: optionalDependencies:
fsevents "~2.3.2" fsevents "~2.3.2"

View File

@@ -21,7 +21,7 @@ mysql:
host: localhost:3306 host: localhost:3306
username: root username: root
password: 111049 password: 111049
db-name: mayfly-go db-name: mayfly_go
config: charset=utf8&loc=Local&parseTime=true config: charset=utf8&loc=Local&parseTime=true
max-idle-conns: 5 max-idle-conns: 5
# 若同时部署多台机器则需要配置redis信息用于缓存权限码、验证码、公私钥等 # 若同时部署多台机器则需要配置redis信息用于缓存权限码、验证码、公私钥等

View File

@@ -1,6 +1,6 @@
module mayfly-go module mayfly-go
go 1.19 go 1.20
require ( require (
github.com/gin-gonic/gin v1.8.2 github.com/gin-gonic/gin v1.8.2

View File

@@ -74,7 +74,6 @@ func InitRouter() *gin.Engine {
sys_router.Init(api) sys_router.Init(api)
// project_router.Init(api)
tag_router.Init(api) tag_router.Init(api)
machine_router.Init(api) machine_router.Init(api)
db_router.Init(api) db_router.Init(api)

View File

@@ -461,7 +461,7 @@ func valueConvert(data []byte, colType *sql.ColumnType) interface{} {
return intV return intV
} }
} }
if strings.Contains(colScanType, "float") { if strings.Contains(colScanType, "float") || strings.Contains(colDatabaseTypeName, "decimal") {
floatV, _ := strconv.ParseFloat(stringV, 64) floatV, _ := strconv.ParseFloat(stringV, 64)
return floatV return floatV
} }

View File

@@ -1,8 +1,11 @@
package starter package starter
import ( import (
"log"
"mayfly-go/pkg/config" "mayfly-go/pkg/config"
"mayfly-go/pkg/global" "mayfly-go/pkg/global"
"os"
"time"
"gorm.io/driver/mysql" "gorm.io/driver/mysql"
"gorm.io/gorm" "gorm.io/gorm"
@@ -30,10 +33,20 @@ func gormMysql() *gorm.DB {
SkipInitializeWithVersion: false, // 根据版本自动配置 SkipInitializeWithVersion: false, // 根据版本自动配置
} }
gormLogger := logger.New(
log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer日志输出的目标前缀和日志包含的内容——译者注
logger.Config{
SlowThreshold: time.Second, // 慢 SQL 阈值
LogLevel: logger.Error, // 日志级别, 改为logger.Info即可显示sql语句
IgnoreRecordNotFoundError: true, // 忽略ErrRecordNotFound记录未找到错误
Colorful: true, // 禁用彩色打印
},
)
ormConfig := &gorm.Config{NamingStrategy: schema.NamingStrategy{ ormConfig := &gorm.Config{NamingStrategy: schema.NamingStrategy{
TablePrefix: "t_", TablePrefix: "t_",
SingularTable: true, SingularTable: true,
}, Logger: logger.Default.LogMode(logger.Error)} // 改为logger.Info即可显示sql语句 }, Logger: gormLogger}
if db, err := gorm.Open(mysql.New(mysqlConfig), ormConfig); err != nil { if db, err := gorm.Open(mysql.New(mysqlConfig), ormConfig); err != nil {
global.Log.Panicf("连接mysql失败! [%s]", err.Error()) global.Log.Panicf("连接mysql失败! [%s]", err.Error())