Compare commits

...
16 changed files with 184 additions and 89 deletions
+2
View File
@@ -17,6 +17,7 @@ type RuntimeCreate struct {
Image string `json:"image"` Image string `json:"image"`
Type string `json:"type"` Type string `json:"type"`
Version string `json:"version"` Version string `json:"version"`
Source string `json:"source"`
} }
type RuntimeDelete struct { type RuntimeDelete struct {
@@ -30,4 +31,5 @@ type RuntimeUpdate struct {
Image string `json:"image"` Image string `json:"image"`
Version string `json:"version"` Version string `json:"version"`
Rebuild bool `json:"rebuild"` Rebuild bool `json:"rebuild"`
Source string `json:"source"`
} }
+1
View File
@@ -6,4 +6,5 @@ type RuntimeRes struct {
model.Runtime model.Runtime
AppParams []AppParam `json:"appParams"` AppParams []AppParam `json:"appParams"`
AppID uint `json:"appId"` AppID uint `json:"appId"`
Source string `json:"source"`
} }
+5 -2
View File
@@ -94,7 +94,7 @@ func (r *RuntimeService) Create(create request.RuntimeCreate) (err error) {
return return
} }
} }
composeContent, envContent, forms, err := handleParams(create.Image, create.Type, newNameDir, create.Params) composeContent, envContent, forms, err := handleParams(create.Image, create.Type, newNameDir, create.Source, create.Params)
if err != nil { if err != nil {
return return
} }
@@ -197,6 +197,9 @@ func (r *RuntimeService) Get(id uint) (*response.RuntimeRes, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
if v, ok := envs["CONTAINER_PACKAGE_URL"]; ok {
res.Source = v
}
for _, form := range appForm.FormFields { for _, form := range appForm.FormFields {
if v, ok := envs[form.EnvKey]; ok { if v, ok := envs[form.EnvKey]; ok {
appParam := response.AppParam{ appParam := response.AppParam{
@@ -252,7 +255,7 @@ func (r *RuntimeService) Update(req request.RuntimeUpdate) error {
return buserr.New(constant.ErrImageExist) return buserr.New(constant.ErrImageExist)
} }
runtimeDir := path.Join(constant.RuntimeDir, runtime.Type, runtime.Name) runtimeDir := path.Join(constant.RuntimeDir, runtime.Type, runtime.Name)
composeContent, envContent, _, err := handleParams(req.Image, runtime.Type, runtimeDir, req.Params) composeContent, envContent, _, err := handleParams(req.Image, runtime.Type, runtimeDir, req.Source, req.Params)
if err != nil { if err != nil {
return err return err
} }
+2 -1
View File
@@ -89,7 +89,7 @@ func buildRuntime(runtime *model.Runtime, oldImageID string, rebuild bool) {
_ = runtimeRepo.Save(runtime) _ = runtimeRepo.Save(runtime)
} }
func handleParams(image, runtimeType, runtimeDir string, params map[string]interface{}) (composeContent []byte, envContent []byte, forms []byte, err error) { func handleParams(image, runtimeType, runtimeDir, source string, params map[string]interface{}) (composeContent []byte, envContent []byte, forms []byte, err error) {
fileOp := files.NewFileOp() fileOp := files.NewFileOp()
composeContent, err = fileOp.GetContent(path.Join(runtimeDir, "docker-compose.yml")) composeContent, err = fileOp.GetContent(path.Join(runtimeDir, "docker-compose.yml"))
if err != nil { if err != nil {
@@ -114,6 +114,7 @@ func handleParams(image, runtimeType, runtimeDir string, params map[string]inter
params["PHP_EXTENSIONS"] = strings.Join(strArray, ",") params["PHP_EXTENSIONS"] = strings.Join(strArray, ",")
} }
} }
params["CONTAINER_PACKAGE_URL"] = source
} }
newMap := make(map[string]string) newMap := make(map[string]string)
handleMap(params, newMap) handleMap(params, newMap)
+3 -2
View File
@@ -884,9 +884,10 @@ func updateRollbackStatus(id uint, status string, message string) {
} }
func cpBinary(src []string, dst string) error { func cpBinary(src []string, dst string) error {
stderr, err := cmd.Exec(fmt.Sprintf("\\cp -f %s %s", strings.Join(src, " "), dst)) global.LOG.Debugf(fmt.Sprintf("\\cp -f %s %s", strings.Join(src, " "), dst))
stdout, err := cmd.Exec(fmt.Sprintf("\\cp -f %s %s", strings.Join(src, " "), dst))
if err != nil { if err != nil {
return errors.New(stderr) return fmt.Errorf("cp file failed, stdout: %v, err: %v", stdout, err)
} }
return nil return nil
} }
+4 -4
View File
@@ -132,25 +132,25 @@ func (u *UpgradeService) Upgrade(req dto.Upgrade) error {
global.LOG.Info("backup original data successful, now start to upgrade!") global.LOG.Info("backup original data successful, now start to upgrade!")
if err := cpBinary([]string{tmpDir + "/1panel"}, "/usr/local/bin/1panel"); err != nil { if err := cpBinary([]string{tmpDir + "/1panel"}, "/usr/local/bin/1panel"); err != nil {
u.handleRollback(fileOp, originalDir, 1)
global.LOG.Errorf("upgrade 1panel failed, err: %v", err) global.LOG.Errorf("upgrade 1panel failed, err: %v", err)
u.handleRollback(fileOp, originalDir, 1)
return return
} }
if err := cpBinary([]string{tmpDir + "/1pctl"}, "/usr/local/bin/1pctl"); err != nil { if err := cpBinary([]string{tmpDir + "/1pctl"}, "/usr/local/bin/1pctl"); err != nil {
u.handleRollback(fileOp, originalDir, 2)
global.LOG.Errorf("upgrade 1pctl failed, err: %v", err) global.LOG.Errorf("upgrade 1pctl failed, err: %v", err)
u.handleRollback(fileOp, originalDir, 2)
return return
} }
if _, err := cmd.Execf("sed -i -e 's#BASE_DIR=.*#BASE_DIR=%s#g' /usr/local/bin/1pctl", global.CONF.System.BaseDir); err != nil { if _, err := cmd.Execf("sed -i -e 's#BASE_DIR=.*#BASE_DIR=%s#g' /usr/local/bin/1pctl", global.CONF.System.BaseDir); err != nil {
u.handleRollback(fileOp, originalDir, 2)
global.LOG.Errorf("upgrade basedir in 1pctl failed, err: %v", err) global.LOG.Errorf("upgrade basedir in 1pctl failed, err: %v", err)
u.handleRollback(fileOp, originalDir, 2)
return return
} }
if err := cpBinary([]string{tmpDir + "/1panel.service"}, "/etc/systemd/system/1panel.service"); err != nil { if err := cpBinary([]string{tmpDir + "/1panel.service"}, "/etc/systemd/system/1panel.service"); err != nil {
u.handleRollback(fileOp, originalDir, 3)
global.LOG.Errorf("upgrade 1panel.service failed, err: %v", err) global.LOG.Errorf("upgrade 1panel.service failed, err: %v", err)
u.handleRollback(fileOp, originalDir, 3)
return return
} }
+3
View File
@@ -1211,6 +1211,9 @@ func (w WebsiteService) UpdatePHPConfigFile(req request.WebsitePHPFileUpdate) er
if err := files.NewFileOp().WriteFile(configPath, strings.NewReader(req.Content), 0755); err != nil { if err := files.NewFileOp().WriteFile(configPath, strings.NewReader(req.Content), 0755); err != nil {
return err return err
} }
if _, err := compose.Restart(runtimeInstall.GetComposePath()); err != nil {
return err
}
return nil return nil
} }
+2
View File
@@ -23,6 +23,7 @@ export namespace Runtime {
export interface RuntimeDTO extends Runtime { export interface RuntimeDTO extends Runtime {
appParams: App.InstallParams[]; appParams: App.InstallParams[];
appId: number; appId: number;
source?: string;
} }
export interface RuntimeCreate { export interface RuntimeCreate {
@@ -36,6 +37,7 @@ export namespace Runtime {
appId?: number; appId?: number;
version?: string; version?: string;
rebuild?: boolean; rebuild?: boolean;
source?: string;
} }
export interface RuntimeUpdate { export interface RuntimeUpdate {
+9
View File
@@ -1658,6 +1658,15 @@ const message = {
phpPluginHelper: phpPluginHelper:
'<a target="_blank" href="https://1panel.cn/docs/user_manual/websites/php/#php_1">View PHP extension list</a> ', '<a target="_blank" href="https://1panel.cn/docs/user_manual/websites/php/#php_1">View PHP extension list</a> ',
rebuild: 'Rebuild PHP App', rebuild: 'Rebuild PHP App',
source: 'PHP extension source',
ustc: 'University of Science and Technology of China',
netease: 'Netease',
aliyun: 'Alibaba Cloud',
default: 'default',
tsinghua: 'Tsinghua University',
xtomhk: 'XTOM Mirror Station (Hong Kong)',
xtom: 'XTOM Mirror Station (Global)',
phpsourceHelper: 'Choose the appropriate source according to your network environment',
}, },
process: { process: {
pid: 'Process ID', pid: 'Process ID',
+9
View File
@@ -1569,6 +1569,15 @@ const message = {
phpPluginHelper: phpPluginHelper:
"<a target=“_blank” href='https://1panel.cn/docs/user_manual/websites/php/#php_1'>查看 PHP 擴展列表</a> ", "<a target=“_blank” href='https://1panel.cn/docs/user_manual/websites/php/#php_1'>查看 PHP 擴展列表</a> ",
rebuild: '重建 PHP 應用', rebuild: '重建 PHP 應用',
source: 'PHP 擴展源',
ustc: '中國科學技術大學',
netease: '網易',
aliyun: '阿里雲',
default: '默認',
tsinghua: '清華大學',
xtomhk: 'XTOM 鏡像站(香港)',
xtom: 'XTOM 鏡像站(全球)',
phpsourceHelper: '根據你的網絡環境選擇合適的源',
}, },
process: { process: {
pid: '進程ID', pid: '進程ID',
+9
View File
@@ -1569,6 +1569,15 @@ const message = {
phpPluginHelper: phpPluginHelper:
"<a target=“_blank” href='https://1panel.cn/docs/user_manual/websites/php/#php_1'>查看 PHP 扩展列表</a> ", "<a target=“_blank” href='https://1panel.cn/docs/user_manual/websites/php/#php_1'>查看 PHP 扩展列表</a> ",
rebuild: '重建 PHP 应用', rebuild: '重建 PHP 应用',
source: 'PHP 扩展源',
ustc: '中国科学技术大学',
netease: '网易',
aliyun: '阿里云',
default: '默认',
tsinghua: '清华大学',
xtomhk: 'XTOM 镜像站(香港)',
xtom: 'XTOM 镜像站(全球)',
phpsourceHelper: '根据你的网络环境选择合适的源',
}, },
process: { process: {
pid: '进程ID', pid: '进程ID',
@@ -401,18 +401,20 @@ const onSubmit = async (formEl: FormInstance | undefined) => {
dialogData.value.rowData!.labels = dialogData.value.rowData!.labelsStr.split('\n'); dialogData.value.rowData!.labels = dialogData.value.rowData!.labelsStr.split('\n');
} }
dialogData.value.rowData!.cmd = []; dialogData.value.rowData!.cmd = [];
if (dialogData.value.rowData?.cmdStr.indexOf(`'`) !== -1) { if (dialogData.value.rowData?.cmdStr) {
let itemCmd = dialogData.value.rowData!.cmdStr.split(`'`); if (dialogData.value.rowData?.cmdStr.indexOf(`'`) !== -1) {
for (const cmd of itemCmd) { let itemCmd = dialogData.value.rowData!.cmdStr.split(`'`);
if (cmd && cmd !== ' ') { for (const cmd of itemCmd) {
if (cmd && cmd !== ' ') {
dialogData.value.rowData!.cmd.push(cmd);
}
}
} else {
let itemCmd = dialogData.value.rowData!.cmdStr.split(` `);
for (const cmd of itemCmd) {
dialogData.value.rowData!.cmd.push(cmd); dialogData.value.rowData!.cmd.push(cmd);
} }
} }
} else {
let itemCmd = dialogData.value.rowData!.cmdStr.split(` `);
for (const cmd of itemCmd) {
dialogData.value.rowData!.cmd.push(cmd);
}
} }
if (dialogData.value.rowData!.entrypointStr) { if (dialogData.value.rowData!.entrypointStr) {
dialogData.value.rowData!.entrypoint = dialogData.value.rowData!.entrypointStr.split(' '); dialogData.value.rowData!.entrypoint = dialogData.value.rowData!.entrypointStr.split(' ');
@@ -228,7 +228,7 @@ const search = async () => {
needLoadStatus = true; needLoadStatus = true;
} }
} }
if (needLoadStatus) { if (supervisorStatus.value.isRunning && needLoadStatus) {
setTimeout(loadStatus, 1000); setTimeout(loadStatus, 1000);
} }
} catch (error) {} } catch (error) {}
@@ -252,7 +252,7 @@ const loadStatus = async () => {
} }
} }
} }
if (needLoadStatus) { if (supervisorStatus.value.isRunning && needLoadStatus) {
setTimeout(loadStatus, 2000); setTimeout(loadStatus, 2000);
} }
} catch (error) {} } catch (error) {}
@@ -63,44 +63,60 @@
</el-col> </el-col>
</el-row> </el-row>
</el-form-item> </el-form-item>
<el-form-item :label="$t('runtime.image')" prop="image">
<el-input v-model="runtime.image"></el-input>
</el-form-item>
<div v-if="initParam"> <div v-if="initParam">
<el-form-item v-if="runtime.type === 'php'"> <div v-if="runtime.type === 'php'">
<el-alert :title="$t('runtime.buildHelper')" type="warning" :closable="false" /> <el-form-item :label="$t('runtime.image')" prop="image">
</el-form-item> <el-input v-model="runtime.image"></el-input>
<Params </el-form-item>
v-if="mode === 'create'" <el-form-item :label="$t('runtime.source')" prop="source">
v-model:form="runtime.params" <el-select v-model="runtime.source" filterable allow-create default-first-option>
v-model:params="appParams" <el-option
v-model:rules="rules" v-for="(source, index) in phpSources"
></Params> :key="index"
<EditParams :label="source.label + ' [' + source.value + ']'"
v-if="mode === 'edit'" :value="source.value"
v-model:form="runtime.params" ></el-option>
v-model:params="editParams" </el-select>
v-model:rules="rules" <span class="input-help">
></EditParams> {{ $t('runtime.phpsourceHelper') }}
<el-form-item v-if="runtime.type === 'php'"> </span>
<el-alert type="info" :closable="false"> </el-form-item>
<span>{{ $t('runtime.extendHelper') }}</span>
<span v-html="$t('runtime.phpPluginHelper')"></span> <Params
<br /> v-if="mode === 'create'"
</el-alert> v-model:form="runtime.params"
</el-form-item> v-model:params="appParams"
<div v-if="runtime.type === 'php' && mode == 'edit'"> v-model:rules="rules"
></Params>
<EditParams
v-if="mode === 'edit'"
v-model:form="runtime.params"
v-model:params="editParams"
v-model:rules="rules"
></EditParams>
<el-form-item> <el-form-item>
<el-checkbox v-model="runtime.rebuild"> <el-alert :title="$t('runtime.buildHelper')" type="warning" :closable="false" />
{{ $t('runtime.rebuild') }}
</el-checkbox>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-alert type="info" :closable="false"> <el-alert type="info" :closable="false">
<span>{{ $t('runtime.rebuildHelper') }}</span> <span>{{ $t('runtime.extendHelper') }}</span>
<span v-html="$t('runtime.phpPluginHelper')"></span>
<br /> <br />
</el-alert> </el-alert>
</el-form-item> </el-form-item>
<div v-if="mode == 'edit'">
<el-form-item>
<el-checkbox v-model="runtime.rebuild">
{{ $t('runtime.rebuild') }}
</el-checkbox>
</el-form-item>
<el-form-item>
<el-alert type="info" :closable="false">
<span>{{ $t('runtime.rebuildHelper') }}</span>
<br />
</el-alert>
</el-form-item>
</div>
</div> </div>
</div> </div>
</div> </div>
@@ -160,23 +176,59 @@ const appReq = reactive({
page: 1, page: 1,
pageSize: 20, pageSize: 20,
}); });
const runtime = ref<Runtime.RuntimeCreate>({ const initData = (type: string) => ({
name: '', name: '',
appDetailId: undefined, appDetailId: undefined,
image: '', image: '',
params: {}, params: {},
type: 'php', type: type,
resource: 'appstore', resource: 'appstore',
rebuild: false, rebuild: false,
source: 'mirrors.ustc.edu.cn',
}); });
let runtime = reactive<Runtime.RuntimeCreate>(initData('php'));
const rules = ref<any>({ const rules = ref<any>({
name: [Rules.appName], name: [Rules.appName],
resource: [Rules.requiredInput], resource: [Rules.requiredInput],
appId: [Rules.requiredSelect], appId: [Rules.requiredSelect],
version: [Rules.requiredInput, Rules.paramCommon], version: [Rules.requiredInput, Rules.paramCommon],
image: [Rules.requiredInput, Rules.imageName], image: [Rules.requiredInput, Rules.imageName],
source: [Rules.requiredSelect],
}); });
const phpSources = [
{
label: i18n.global.t('runtime.ustc'),
value: 'mirrors.ustc.edu.cn',
},
{
label: i18n.global.t('runtime.netease'),
value: 'mirrors.163.com',
},
{
label: i18n.global.t('runtime.aliyun'),
value: 'mirrors.aliyun.com',
},
{
label: i18n.global.t('runtime.tsinghua'),
value: 'mirrors.tuna.tsinghua.edu.cn',
},
{
label: i18n.global.t('runtime.xtomhk'),
value: 'mirrors.xtom.com.hk',
},
{
label: i18n.global.t('runtime.xtom'),
value: 'mirrors.xtom.com',
},
{
label: i18n.global.t('runtime.default'),
value: 'dl-cdn.alpinelinux.org',
},
];
const em = defineEmits(['close']); const em = defineEmits(['close']);
const handleClose = () => { const handleClose = () => {
@@ -186,12 +238,12 @@ const handleClose = () => {
const changeResource = (resource: string) => { const changeResource = (resource: string) => {
if (resource === 'local') { if (resource === 'local') {
runtime.value.appDetailId = undefined; runtime.appDetailId = undefined;
runtime.value.version = ''; runtime.version = '';
runtime.value.params = {}; runtime.params = {};
runtime.value.image = ''; runtime.image = '';
} else { } else {
runtime.value.version = ''; runtime.version = '';
searchApp(null); searchApp(null);
} }
}; };
@@ -201,7 +253,7 @@ const searchApp = (appId: number) => {
apps.value = res.data.items || []; apps.value = res.data.items || [];
if (res.data && res.data.items && res.data.items.length > 0) { if (res.data && res.data.items && res.data.items.length > 0) {
if (appId == null) { if (appId == null) {
runtime.value.appId = res.data.items[0].id; runtime.appId = res.data.items[0].id;
getApp(res.data.items[0].key, mode.value); getApp(res.data.items[0].key, mode.value);
} else { } else {
res.data.items.forEach((item) => { res.data.items.forEach((item) => {
@@ -227,10 +279,10 @@ const changeApp = (appId: number) => {
const changeVersion = () => { const changeVersion = () => {
loading.value = true; loading.value = true;
initParam.value = false; initParam.value = false;
GetAppDetail(runtime.value.appId, runtime.value.version, 'runtime') GetAppDetail(runtime.appId, runtime.version, 'runtime')
.then((res) => { .then((res) => {
runtime.value.appDetailId = res.data.id; runtime.appDetailId = res.data.id;
runtime.value.image = res.data.image + ':' + runtime.value.version; runtime.image = res.data.image + ':' + runtime.version;
appParams.value = res.data.params; appParams.value = res.data.params;
initParam.value = true; initParam.value = true;
}) })
@@ -243,7 +295,7 @@ const getApp = (appkey: string, mode: string) => {
GetApp(appkey).then((res) => { GetApp(appkey).then((res) => {
appVersions.value = res.data.versions || []; appVersions.value = res.data.versions || [];
if (res.data.versions.length > 0) { if (res.data.versions.length > 0) {
runtime.value.version = res.data.versions[0]; runtime.version = res.data.versions[0];
if (mode === 'create') { if (mode === 'create') {
changeVersion(); changeVersion();
} else { } else {
@@ -261,7 +313,7 @@ const submit = async (formEl: FormInstance | undefined) => {
} }
if (mode.value == 'create') { if (mode.value == 'create') {
loading.value = true; loading.value = true;
CreateRuntime(runtime.value) CreateRuntime(runtime)
.then(() => { .then(() => {
MsgSuccess(i18n.global.t('commons.msg.createSuccess')); MsgSuccess(i18n.global.t('commons.msg.createSuccess'));
handleClose(); handleClose();
@@ -271,7 +323,7 @@ const submit = async (formEl: FormInstance | undefined) => {
}); });
} else { } else {
loading.value = true; loading.value = true;
UpdateRuntime(runtime.value) UpdateRuntime(runtime)
.then(() => { .then(() => {
MsgSuccess(i18n.global.t('commons.msg.updateSuccess')); MsgSuccess(i18n.global.t('commons.msg.updateSuccess'));
handleClose(); handleClose();
@@ -287,7 +339,7 @@ const getRuntime = async (id: number) => {
try { try {
const res = await GetRuntime(id); const res = await GetRuntime(id);
const data = res.data; const data = res.data;
runtime.value = { Object.assign(runtime, {
id: data.id, id: data.id,
name: data.name, name: data.name,
appDetailId: data.appDetailId, appDetailId: data.appDetailId,
@@ -298,7 +350,8 @@ const getRuntime = async (id: number) => {
appId: data.appId, appId: data.appId,
version: data.version, version: data.version,
rebuild: true, rebuild: true,
}; source: data.source,
});
editParams.value = data.appParams; editParams.value = data.appParams;
if (mode.value == 'create') { if (mode.value == 'create') {
searchApp(data.appId); searchApp(data.appId);
@@ -312,16 +365,10 @@ const acceptParams = async (props: OperateRrops) => {
mode.value = props.mode; mode.value = props.mode;
initParam.value = false; initParam.value = false;
if (props.mode === 'create') { if (props.mode === 'create') {
runtime.value = { Object.assign(runtime, initData(props.type));
name: '',
appDetailId: undefined,
image: '',
params: {},
type: props.type,
resource: 'appstore',
};
searchApp(null); searchApp(null);
} else { } else {
searchApp(null);
getRuntime(props.id); getRuntime(props.id);
} }
open.value = true; open.value = true;
@@ -5,7 +5,7 @@
:placeholder="$t('commons.msg.noneData')" :placeholder="$t('commons.msg.noneData')"
:indent-with-tab="true" :indent-with-tab="true"
:tabSize="4" :tabSize="4"
style="margin-top: 10px; max-height: 700px" style="max-height: 700px"
:lineWrapping="true" :lineWrapping="true"
:matchBrackets="true" :matchBrackets="true"
theme="cobalt" theme="cobalt"
@@ -13,11 +13,9 @@
:extensions="extensions" :extensions="extensions"
v-model="content" v-model="content"
/> />
<div style="margin-top: 10px"> <el-button type="primary" @click="submit()" class="mt-2.5">
<el-button type="primary" @click="submit()"> {{ $t('nginx.saveAndReload') }}
{{ $t('nginx.saveAndReload') }} </el-button>
</el-button>
</div>
</div> </div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
@@ -5,7 +5,7 @@
:placeholder="$t('commons.msg.noneData')" :placeholder="$t('commons.msg.noneData')"
:indent-with-tab="true" :indent-with-tab="true"
:tabSize="4" :tabSize="4"
style="margin-top: 10px; max-height: 700px" style="max-height: 700px"
:lineWrapping="true" :lineWrapping="true"
:matchBrackets="true" :matchBrackets="true"
theme="cobalt" theme="cobalt"
@@ -13,11 +13,10 @@
:extensions="extensions" :extensions="extensions"
v-model="content" v-model="content"
/> />
<div style="margin-top: 10px"> <el-button type="primary" @click="openUpdate()" class="mt-2.5">
<el-button type="primary" @click="submit()"> {{ $t('nginx.saveAndReload') }}
{{ $t('nginx.saveAndReload') }} </el-button>
</el-button> <ConfirmDialog ref="confirmDialogRef" @confirm="submit()"></ConfirmDialog>
</div>
</div> </div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
@@ -52,9 +51,10 @@ const id = computed(() => {
return props.id; return props.id;
}); });
let data = ref<File.File>(); const data = ref<File.File>();
let loading = ref(false); const loading = ref(false);
let content = ref(''); const content = ref('');
const confirmDialogRef = ref();
const get = () => { const get = () => {
loading.value = true; loading.value = true;
@@ -68,6 +68,14 @@ const get = () => {
}); });
}; };
const openUpdate = async () => {
confirmDialogRef.value!.acceptParams({
header: i18n.global.t('database.confChange'),
operationInfo: i18n.global.t('database.restartNowHelper'),
submitInputInfo: i18n.global.t('database.restartNow'),
});
};
const submit = async () => { const submit = async () => {
loading.value = true; loading.value = true;
UpdatePHPFile({ UpdatePHPFile({