Skip to content

Commit 48e2e01

Browse files
feat: Add MySQL character set and collation configuration during application installation (#11062)
1 parent d6b0096 commit 48e2e01

File tree

10 files changed

+75
-26
lines changed

10 files changed

+75
-26
lines changed

agent/app/dto/app.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ type AppDatabase struct {
1212
DbUser string `json:"PANEL_DB_USER"`
1313
Password string `json:"PANEL_DB_USER_PASSWORD"`
1414
DatabaseName string `json:"DATABASE_NAME"`
15+
Format string `json:"format"`
16+
Collation string `json:"collation"`
1517
}
1618

1719
type AuthParam struct {

agent/app/service/app_utils.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -300,10 +300,11 @@ func createLink(ctx context.Context, installTask *task.Task, app model.App, appI
300300
createMysql.Name = dbConfig.DbName
301301
createMysql.Username = dbConfig.DbUser
302302
createMysql.Database = database.Name
303-
createMysql.Format = "utf8mb4"
303+
createMysql.Format = dbConfig.Format
304304
createMysql.Permission = "%"
305305
createMysql.Password = dbConfig.Password
306306
createMysql.From = database.From
307+
createMysql.Collation = dbConfig.Collation
307308
mysqldb, err := NewIMysqlService().Create(ctx, createMysql)
308309
if err != nil {
309310
return err

agent/init/migration/migrations/init.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -730,6 +730,6 @@ var AddGPUMonitor = &gormigrate.Migration{
730730
var UpdateDatabaseMysql = &gormigrate.Migration{
731731
ID: "20251125-update-database-mysql",
732732
Migrate: func(tx *gorm.DB) error {
733-
return tx.AutoMigrate(&model.Database{})
733+
return tx.AutoMigrate(&model.DatabaseMysql{})
734734
},
735735
}

frontend/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@
8787
"vite-plugin-compression": "^0.5.1",
8888
"vite-plugin-eslint": "^1.8.1",
8989
"vite-plugin-html": "^3.2.2",
90+
"vite-plugin-monaco-editor": "^1.1.0",
9091
"vite-plugin-vue-setup-extend": "^0.4.0",
9192
"vite-svg-loader": "^5.1.0",
9293
"vue-tsc": "^0.29.8"

frontend/src/views/app-store/detail/form/index.vue

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,7 @@ const formRules = ref<FormRules>({
201201
memoryLimit: [Rules.requiredInput, checkNumberRange(0, 9999999999)],
202202
specifyIP: [Rules.ipv4orV6],
203203
restartPolicy: [Rules.requiredSelect],
204+
format: [Rules.requiredInput],
204205
});
205206
206207
const initFormData = () => ({

frontend/src/views/app-store/detail/install/index.vue

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ const formData = ref({
4949
taskID: '',
5050
gpuConfig: false,
5151
specifyIP: '',
52+
format: 'utf8mb4',
53+
collation: '',
5254
});
5355
5456
const handleClose = () => {

frontend/src/views/app-store/detail/params/index.vue

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,17 @@
118118
</div>
119119
<span class="input-help" v-if="p.description">{{ getDescription(p) }}</span>
120120
</el-form-item>
121+
<el-form-item v-if="form[p.envKey] == 'mysql'" :label="$t('database.format')" prop="format">
122+
<el-select filterable v-model="form.format" @change="loadCollations()">
123+
<el-option v-for="item of formatOptions" :key="item.format" :label="item.format" :value="item.format" />
124+
</el-select>
125+
</el-form-item>
126+
<el-form-item v-if="form[p.envKey] == 'mysql'" :label="$t('database.collation')" prop="collation">
127+
<el-select filterable v-model="form.collation">
128+
<el-option v-for="item of collationOptions" :key="item" :label="item" :value="item" />
129+
</el-select>
130+
<span class="input-help">{{ $t('database.collationHelper', [form.format]) }}</span>
131+
</el-form-item>
121132
</div>
122133
</template>
123134
<script lang="ts" setup>
@@ -128,6 +139,7 @@ import { Rules } from '@/global/form-rules';
128139
import { App } from '@/api/interface/app';
129140
import { getDBName, getLabel, getDescription } from '@/utils/util';
130141
import { getPathByType } from '@/api/modules/files';
142+
import { loadFormatCollations } from '@/api/modules/database';
131143
132144
interface ParamObj extends App.FromField {
133145
services: App.AppService[];
@@ -163,7 +175,9 @@ const props = defineProps({
163175
},
164176
});
165177
166-
const form = reactive({});
178+
const form = reactive({
179+
format: '',
180+
});
167181
let rules = reactive({});
168182
const params = computed({
169183
get() {
@@ -241,6 +255,10 @@ const handleParams = () => {
241255
242256
const getServices = async (childKey: string, key: string | undefined, pObj: ParamObj | undefined) => {
243257
pObj.services = [];
258+
appKey.value = key || '';
259+
if (appKey.value == 'mysql') {
260+
form.format = 'utf8mb4';
261+
}
244262
await getAppService(key).then((res) => {
245263
pObj.services = res.data || [];
246264
form[childKey] = '';
@@ -268,13 +286,32 @@ const changeService = (value: string, services: App.AppService[]) => {
268286
});
269287
}
270288
});
289+
if (appKey.value == 'mysql') {
290+
loadOptions(value);
291+
}
271292
updateParam();
272293
};
273294
274295
const toPage = (key: string) => {
275296
window.location.href = '/apps/all?install=' + key;
276297
};
277298
299+
const formatOptions = ref();
300+
const collationOptions = ref();
301+
const appKey = ref('');
302+
303+
const loadOptions = async (database: string) => {
304+
const defaultOptions = [{ format: 'utf8mb4' }, { format: 'utf8mb3' }, { format: 'gbk' }, { format: 'big5' }];
305+
await loadFormatCollations(database).then((res) => {
306+
formatOptions.value = res.data || defaultOptions;
307+
loadCollations();
308+
});
309+
};
310+
311+
const loadCollations = async () => {
312+
collationOptions.value = formatOptions.value?.find((item) => item.format === form.format)?.collations || [];
313+
};
314+
278315
onMounted(() => {
279316
handleParams();
280317
});

frontend/src/views/app-store/installed/index.vue

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -417,10 +417,6 @@
417417
</template>
418418

419419
<script lang="ts" setup>
420-
import { searchAppInstalled, installedOp, appInstalledDeleteCheck, getAppIconUrl } from '@/api/modules/app';
421-
import { onMounted, onUnmounted, reactive, ref } from 'vue';
422-
import i18n from '@/lang';
423-
import { ElMessageBox } from 'element-plus';
424420
import Backups from '@/components/backup/index.vue';
425421
import Uploads from '@/components/upload/index.vue';
426422
import PortJumpDialog from '@/components/port-jump/index.vue';
@@ -429,20 +425,25 @@ import AppDelete from './delete/index.vue';
429425
import AppParams from './detail/index.vue';
430426
import AppUpgrade from './upgrade/index.vue';
431427
import AppIgnore from './ignore/index.vue';
428+
import Status from '@/components/status/index.vue';
429+
import TaskLog from '@/components/log/task/index.vue';
430+
import Detail from '@/views/app-store/detail/index.vue';
431+
import Tags from '@/views/app-store/components/tag.vue';
432+
import SvgIcon from '@/components/svg-icon/svg-icon.vue';
433+
import MainDiv from '@/components/main-div/index.vue';
432434
import ComposeLogs from '@/components/log/compose/index.vue';
435+
import IgnoreApp from '@/views/app-store/installed/ignore/create/index.vue';
433436
import TerminalDialog from '@/views/container/container/terminal/index.vue';
437+
438+
import { searchAppInstalled, installedOp, appInstalledDeleteCheck, getAppIconUrl } from '@/api/modules/app';
439+
import { onMounted, onUnmounted, reactive, ref } from 'vue';
440+
import i18n from '@/lang';
441+
import { ElMessageBox } from 'element-plus';
434442
import { App } from '@/api/interface/app';
435-
import Status from '@/components/status/index.vue';
436443
import { getAge, jumpToPath, toLink } from '@/utils/util';
437444
import { useRouter } from 'vue-router';
438445
import { MsgSuccess } from '@/utils/message';
439-
import TaskLog from '@/components/log/task/index.vue';
440-
import Detail from '@/views/app-store/detail/index.vue';
441-
import IgnoreApp from '@/views/app-store/installed/ignore/create/index.vue';
442446
import { getAgentSettingByKey } from '@/api/modules/setting';
443-
import Tags from '@/views/app-store/components/tag.vue';
444-
import SvgIcon from '@/components/svg-icon/svg-icon.vue';
445-
import MainDiv from '@/components/main-div/index.vue';
446447
import { routerToFileWithPath, routerToNameWithQuery } from '@/utils/router';
447448
import { useGlobalStore } from '@/composables/useGlobalStore';
448449
const { currentNode, isMaster, currentNodeAddr } = useGlobalStore();

frontend/src/views/app-store/installed/upgrade/index.vue

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,10 @@
7979
<TaskLog ref="taskLogRef" />
8080
</template>
8181
<script lang="ts" setup>
82+
import Diff from './diff/index.vue';
83+
import TaskLog from '@/components/log/task/index.vue';
84+
import CodemirrorPro from '@/components/codemirror-pro/index.vue';
85+
8286
import { App } from '@/api/interface/app';
8387
import { getAppUpdateVersions, ignoreUpgrade, installedOp } from '@/api/modules/app';
8488
import { getAppStoreConfig } from '@/api/modules/setting';
@@ -87,10 +91,7 @@ import { ElMessageBox, FormInstance } from 'element-plus';
8791
import { reactive, ref, onBeforeUnmount } from 'vue';
8892
import { MsgSuccess } from '@/utils/message';
8993
import { Rules } from '@/global/form-rules';
90-
import Diff from './diff/index.vue';
9194
import bus from '@/global/bus';
92-
import CodemirrorPro from '@/components/codemirror-pro/index.vue';
93-
import TaskLog from '@/components/log/task/index.vue';
9495
import { v4 as uuidv4 } from 'uuid';
9596
9697
const composeDiffRef = ref();

frontend/vite.config.ts

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import Components from 'unplugin-vue-components/vite';
1616
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers';
1717
import svgLoader from 'vite-svg-loader';
1818

19-
const prefix = `monaco-editor/esm/vs`;
19+
import monacoEditorPlugin from 'vite-plugin-monaco-editor';
2020

2121
const { dependencies, devDependencies, name, version } = pkg;
2222
const __APP_INFO__ = {
@@ -44,14 +44,16 @@ export default defineConfig(({ mode }: ConfigEnv): UserConfig => {
4444
scss: {
4545
additionalData: `@use "@/styles/var.scss" as *;`,
4646
silenceDeprecations: ['legacy-js-api'],
47-
api: 'modern',
4847
},
4948
},
5049
},
5150
server: {
5251
port: viteEnv.VITE_PORT,
5352
open: viteEnv.VITE_OPEN,
5453
host: '0.0.0.0',
54+
sourcemapIgnoreList: (sourcePath) => {
55+
return sourcePath.includes('node_modules');
56+
},
5557
proxy: {
5658
'/api/v2': {
5759
target: 'http://localhost:9999/',
@@ -95,12 +97,16 @@ export default defineConfig(({ mode }: ConfigEnv): UserConfig => {
9597
svgLoader({
9698
defaultImport: 'url',
9799
}),
100+
monacoEditorPlugin({
101+
languageWorkers: ['editorWorkerService', 'typescript', 'json', 'html', 'css'],
102+
}),
98103
],
99104
esbuild: {
100105
pure: viteEnv.VITE_DROP_CONSOLE ? ['console.log'] : [],
101106
drop: viteEnv.VITE_DROP_CONSOLE && process.env.NODE_ENV === 'production' ? ['debugger'] : [],
102107
},
103108
build: {
109+
sourcemap: false,
104110
outDir: '../core/cmd/server/web',
105111
minify: 'esbuild',
106112
target: 'esnext',
@@ -110,15 +116,12 @@ export default defineConfig(({ mode }: ConfigEnv): UserConfig => {
110116
chunkFileNames: 'assets/js/[name]-[hash].js',
111117
entryFileNames: 'assets/js/[name]-[hash].js',
112118
assetFileNames: 'assets/[ext]/[name]-[hash].[ext]',
113-
manualChunks: {
114-
jsonWorker: [`${prefix}/language/json/json.worker`],
115-
cssWorker: [`${prefix}/language/css/css.worker`],
116-
htmlWorker: [`${prefix}/language/html/html.worker`],
117-
tsWorker: [`${prefix}/language/typescript/ts.worker`],
118-
editorWorker: [`${prefix}/editor/editor.worker`],
119-
},
120119
},
121120
},
122121
},
122+
optimizeDeps: {
123+
include: ['monaco-editor/esm/vs/editor/editor.api'],
124+
exclude: ['monaco-editor'],
125+
},
123126
};
124127
});

0 commit comments

Comments
 (0)