快乐的梦鱼 vor 1 Monat
Ursprung
Commit
cacb1190bc

+ 1 - 1
scripts/UpdateScript/postConfig.mjs

@@ -34,7 +34,7 @@ export const config = {
     },
   },
   buildWebCommand: 'npm run nuxt-build', //构建命令
-  buildWebOutDir: '../../../.output', //构建输出目录。相对于当前文件目录
+  buildWebOutDir: '../../.output', //构建输出目录。相对于当前文件目录
   buildWebOptions: {
     skipFiles: [
       '/server/node_modules',

+ 14 - 0
src/assets/scss/main.scss

@@ -689,6 +689,8 @@ footer {
 }
 
 .news-detail {
+  position: relative;
+
   h1 {
     text-align: center;
     font-size: 30px;
@@ -709,8 +711,20 @@ footer {
     }
   }
 
+  .head-image {
+    width: 100%;
+    height: 300px;
+    object-fit: cover;
+    border-radius: 8px;
+    margin-bottom: 20px;
+  }
+
   .content {
+    position: relative;
 
+    img, video {
+      max-width: 100%;
+    }
   }
 }
 

+ 13 - 6
src/pages/page/[id].vue

@@ -58,16 +58,23 @@
               </div>
               
               <SimplePageContentLoader :loader="articlesData">
-                <div class="news-detail">
-                  <h1>{{ articlesData.content.value?.title }}</h1>
+                <div v-if="articlesData.content.value"  class="news-detail">
+                  <h1>{{ articlesData.content.value.title }}</h1>
                   <div class="times">
                     <p class="date">时间:{{ DateUtils.formatDate(new Date(
-                      (articlesData.content.value?.publishtime ||  
-                      articlesData.content.value?.createtime  || 0) * 1000), 'yyyy-MM-dd') }}</p>
-                    <p class="views">浏览量: {{ articlesData.content.value?.views }} </p>
+                      (articlesData.content.value.publishtime ||  
+                      articlesData.content.value.createtime  || 0) * 1000), 'yyyy-MM-dd') }}</p>
+                    <p class="views">浏览量: {{ articlesData.content.value.views }} </p>
                   </div>
-                  <div class="content" v-html="articlesData.content.value?.content">
+                  <div v-if="!articlesData.content.value.content &&articlesData.content.value.image" class="head-image">
+                    <img :src="articlesData.content.value.image" />
                   </div>
+
+                  <div class="content" v-html="articlesData.content.value.content">
+                  </div>
+                  <a-empty v-if="!articlesData.content.value.content"
+                    description="暂无内容"
+                  />
                 </div>
               </SimplePageContentLoader>
             </div>

+ 0 - 4
src/scripts/.gitignore

@@ -1,4 +0,0 @@
-node_modules
-_config.json
-_token.json
-upload.zip

+ 0 - 22
src/scripts/UpdateScript/deprecate.html

@@ -1,22 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-  <head>
-    <meta charset="UTF-8" />
-    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
-    <title>提示</title>
-    <style>.global-error{position:fixed;left:0;right:0;bottom:100px;top:0;display:flex;flex-direction:column;justify-content:center;align-items:center;background-color:#fff;-webkit-app-region:drag}.global-error span{margin-top:20px;font-size:16px}button{margin-top:20px;padding:0;display:inline-block;-webkit-app-region:no-drag;height:40px;width:120px;appearance:none;outline:none;border:none;background-color:#0083da;color:#fff;cursor:pointer}button:hover{background-color:#005c99}</style>
-  </head>
-  <body>
-    <script>
-      function relaunch() {
-        if (typeof api.relaunch == 'function') 
-          api.relaunch();
-        else
-          location.reload();
-      }
-    </script>
-    <div class="global-error">
-      <span>系统已更新,请重启</span>
-      <button id="load-confirm-button" onclick="relaunch()">确定</button>
-    </div>
-</html>

+ 0 - 524
src/scripts/UpdateScript/index.mjs

@@ -1,524 +0,0 @@
-/**
- * 更新发布工具
- * 
- * Copyright © 2025 imengyu.top imengyu-update-server
- */
-
-import { program } from 'commander';
-import { password, input, confirm, select } from '@inquirer/prompts';
-import { writeFile, readFile } from 'node:fs/promises';
-import { postAppUpdate, postWebUpdate } from './postUpdate.mjs';
-import Table from 'cli-table3';
-import md5 from 'md5';
-import axios from 'axios';
-import path from 'path';
-import { dirname } from 'node:path';
-import { fileURLToPath } from 'node:url';
-
-//基础配置
-//========================================
-
-const __filename = fileURLToPath(import.meta.url);
-const __dirname = dirname(__filename);
-const constant = {
-  ServerUrl: 'http://update-server1.imengyu.top/',
-  TokenSave: path.resolve(__dirname, './_token.json'),
-};
-let currentData = {
-  token: '',
-  identifier: '',
-};
-
-readFile(constant.TokenSave).then((res) => {
-  currentData = JSON.parse(res);
-  if (!currentData.identifier) 
-    currentData.identifier = `commandClient${Math.floor(Math.random() * 1000)}`;
-  start();
-}).catch(() => {
-  start();
-})
-
-const axiosInstance = axios.create({
-  baseURL: constant.ServerUrl,
-  timeoutErrorMessage: '请求超时,请检查网络连接',
-  responseType: 'json',
-  withCredentials: false,
-  validateStatus: () => true,
-});
-
-axiosInstance.interceptors.request.use((value) => {
-  value.headers['authorization'] = JSON.stringify({
-    auth: currentData?.token?.authName,
-    validity: currentData?.token?.authKey,
-    nonce: "aaaaaaaaaa",
-    identifier: currentData.identifier,
-    key: 'abc123',
-  });  
-  value.url = value.url + (value.url.includes('?') ? '&' : '?' ) + `identifier=${currentData.identifier}`
-  return value;
-});
-axiosInstance.interceptors.response.use((value) => {
-  if (value.data.success) 
-    return value.data;
-  else
-    return Promise.reject(value.data);
-});
-
-function getErrorMessage(e) {
-  return e instanceof Error ? e.message : (typeof e === 'object' ? e : ('' + e));
-}
-
-//登录相关
-//========================================
-
-async function checkLogged() {
-  try {
-    await axiosInstance.get('/auth');
-    console.log('已登录');
-  } catch (e) {
-    console.error('获取状态失败:', getErrorMessage(e));
-  }
-}
-async function login(user) {
-  try {
-    const pass = await password({ message: '输入密码' });
-    const res = await axiosInstance.post('/auth?rember=true', {
-      method: 'key',
-      key: `${user}@${md5(pass)}`,
-    })
-    currentData.token = {
-      authName: res.data.authName,
-      authKey: res.data.authKey,
-    };
-    writeFile(constant.TokenSave, JSON.stringify(currentData));
-    console.log('登录成功');
-  } catch (e) {
-    console.error('登录失败', getErrorMessage(e));
-  }
-}
-async function logout() {
-  currentToken = '';
-  writeFile(constant.TokenSave, JSON.stringify(currentData));
-  try {
-    await axiosInstance.delete('/auth');
-    console.log('退出登录成功');
-  } catch(e) {
-    console.error('退出登录失败', getErrorMessage(e));
-  }
-}
-
-//版本相关
-//========================================
-
-async function viewVersion(type) {
-  if (type === 'all' || !type) {
-    const data = await axiosInstance.get('/version/list');
-    const table = new Table({
-      head: ['ID', '版本'], 
-      colWidths: [10, 20 ]
-    });
-
-    data.data.forEach((d) => {
-      table.push([ d.id, d.version ]);
-    })
-    console.log(table.toString());
-  } else {
-    let data = null;
-    try {
-      if (Number.isNaN(Number(type)))
-        data = await axiosInstance.get('/version/get-by-name?name=' + type);
-      else
-        data = await axiosInstance.get('/version/' + type);
-    }
-    catch (e) {
-      console.error('Failed to load version info', e);
-      return;
-    }
-    const table = new Table({
-      head: ['key', 'data'], 
-      colWidths: [30, 60]
-    });
-    table.push(
-      [ 'ID', data.data.id ],
-      [ '状态', stateConstant[data.data.status] ],
-      [ '版本号', data.data.version ],
-      [ '创建时间', new Date(data.data.createAt).toString() ],
-      [ '设置', data.data.config ],
-      [ '激活的Web更新ID', data.data.webUpdateId ],
-      [ '激活的App更新ID', data.data.appUpdateId ],
-      [ '激活的下一个App更新ID', data.data.appUpdateNextId ],
-    );
-    console.log(table.toString());
-  }
-}
-async function getVersion(action, type) {
-  switch(action) {
-    case 'view':
-      await viewVersion(type);
-      break;
-    case 'new': {
-      const version = await input({ message: 'Enter version name, like (1.0.0)' });
-      try {
-        await axiosInstance.post('/version', {
-          version: version,
-          status: 1,
-          config: "{}",
-        });
-        console.log('Add version success');
-      } catch (e) {
-        console.error('Failed to add version', e);
-      }
-      break;
-    }
-    case 'delete': {
-      const versionId = type ? type : await input({ message: '输入版本ID' });
-      if (!await confirm({ message: `确定删除版本 ${versionId}?`, default: false }))
-        return;
-      if (!await confirm({ message: '确认删除版本?此操作会删除所属版本的所有更新项目、存储等,无法恢复,是否确定删除?', default: false }))
-        return;
-      try {
-        await axiosInstance.delete('/version/' + versionId);
-        console.log('删除版本成功');
-      } catch (e) {
-        console.error('删除版本失败', e);
-      }
-      break;
-    }
-    case 'set-state': {
-      const versionId = type ? type : await input({ message: '输入版本ID' });
-      const state = await select({
-        message: '设置状态',
-        choices: [
-          {
-            name: 'NotEnable',
-            value: 0,
-          },
-          {
-            name: 'Normal',
-            value: 1,
-          },
-          {
-            name: 'Deprecated',
-            value: 2,
-          },
-        ],
-      });
-
-      try {
-        await axiosInstance.put('/version/' + versionId, {
-          status: state
-        });
-        console.log('设置状态成功');
-      } catch (e) {
-        console.error('设置状态失败', e);
-      }
-      break;
-    }
-    case 'set-config': {
-      const versionId = type ? type : await input({ message: '输入版本ID' });
-      const config = await input({ message: '输入配置Json' });
-      try {
-        await axiosInstance.put('/version/' + versionId, {
-          config: config,
-        });
-        console.log('设置配置成功');
-      } catch (e) {
-        console.error('设置配置失败', e);
-      }
-      break;
-    }
-    case 'set-active-app-update': {
-      const versionId = await input({ message: '输入版本ID' });
-      const updateId = await input({ message: '输入更新ID' });
-      const isNext = await confirm({ message: 'Set as next active?', default: false });
-
-      try {
-        await axiosInstance.post('/update/active/app', { versionId, updateId, isNext });
-        console.log('成功');
-      } catch (e) {
-        console.error('失败', e);
-      }
-      break;
-    }
-    case 'set-active-web-update': {
-      const versionId = await input({ message: '输入版本ID' });
-      const updateId = await input({ message: '输入更新ID' });
-
-      try {
-        await axiosInstance.post('/update/active/web', { versionId, updateId });
-        console.log('成功');
-      } catch (e) {
-        console.error('失败', e);
-      }
-      break;
-    }
-    default:
-      console.error('未知参数', action);
-      break;
-  }
-}
-
-//选择方法
-//========================================
-
-export async function selectVersion(requireString = false, defaultVersionId = null) {
-  const data = (await axiosInstance.get('/version/list')).data;
-  if (data.length === 0) {
-    console.error('没有版本');
-    return;
-  }
-  const resultId = (await select({
-    choices: data.map(p => ({
-      value: p.id,
-      name: p.version,
-    })),
-    default: defaultVersionId,
-    message: '选择一个版本',
-  }));
-  if (requireString) {
-    return data.find(p => p.id === resultId).version
-  }
-  return resultId;
-}
-export async function selectUpdate() {
-  const versionId = await selectVersion();
-  const data = (await axiosInstance.get('/version/update?search=' + JSON.stringify({ versionId }))).data;
-  if (data.length === 0) {
-    console.error('没有更新');
-    return;
-  }
-  const resultId = (await select({
-    choices: data.map(p => ({
-      value: p.id,
-      name: p.version,
-    })),
-    default: defaultVersionId,
-    message: '选择一个更新',
-  }));
-  return resultId;
-}
-
-//更新相关
-//========================================
-
-const stateConstant = [ 'Deleted', 'Normal', 'Deprecated' ];
-const typeConstant = [ 'Unknow', 'Web', 'app' ];
-const storageTypeConstant = [ 'Unknow', 'LocalStorage', 'AliOSS' ];
-
-async function postUpdate(type, options) {
-  switch (type) {
-    case 'web': {
-      await postWebUpdate(axiosInstance, options);
-      break;
-    }
-    case 'app': {
-      await postAppUpdate(axiosInstance, options);
-      break;
-    }
-    default:
-      console.error('Unknow type', type);
-      break;
-  }
-}
-async function deprecateOrDeleteUpdate(updateId) {
-  if (!updateId)
-    updateId = await selectUpdate();
-
-  const { currentUpdateInfo, currentVersionInfo } = await viewUpdate(updateId);
-
-  const deprecate = (await select({
-    choices: [
-      {
-        name: 'Deprecate',
-        value: 0,
-      },
-      {
-        name: 'Delete',
-        value: 1,
-      },
-    ],
-    message: '删除或弃用?',
-  })) === 0;
-
-  if (deprecate && currentUpdateInfo.type !== 1) {
-    console.log('只有Web更新允许弃用');
-    return;
-  }
-  if (currentUpdateInfo.status === 0) {
-    console.log(`当前状态 ${stateConstant[currentUpdateInfo.status]} 无法弃用`);
-    return;
-  }
-
-  if (deprecate) {
-    if (!await confirm({ message: `确定弃用当前版本 ${currentUpdateInfo.versionCode} ?弃用会删除存储文件以及备份。此操作无法恢复!`, default: false }))
-      return;
-  } else {
-    if (!await confirm({ message: `确定删除当前版本 ${currentUpdateInfo.versionCode} ?此操作无法恢复!`, default: false }))
-      return;
-  }
-
-  try {
-    await axiosInstance.post(`/update/${deprecate ? 'deprecate' : 'delete'}`, { updateId });
-    console.log(`${deprecate ? '弃用' : '删除'} 成功`);
-  } catch (e) {
-    console.error(`操作失败`, e);
-  }
-}
-async function viewUpdate(updateId) {
-  
-  let currentUpdateInfo = null
-  let currentVersionInfo = null
-
-  try {
-    currentUpdateInfo = (await axiosInstance.get('/update/' + updateId)).data;
-  } catch (e) {
-    console.error('加载更新信息失败', updateId);
-  }
-  try {
-    currentVersionInfo = (await axiosInstance.get('/version/' + currentUpdateInfo.versionId)).data;
-  } catch (e) {
-    console.error('加载版本信息失败', currentUpdateInfo.versionId);
-  }
-
-  const table = new Table({
-    head: ['key', 'data'], 
-    colWidths: [20, 40]
-  });
-  table.push(
-    [ 'ID', currentUpdateInfo.id ],
-    [ '所属应用', currentUpdateInfo.name ],
-    [ '更新信息', currentUpdateInfo.updateInfo ],
-    [ '版本号', currentUpdateInfo.versionCode ],
-    [ '创建时间', new Date(currentUpdateInfo.createAt).toString() ],
-    [ '类型', typeConstant[currentUpdateInfo.type] ],
-    [ '状态', stateConstant[currentUpdateInfo.status] ],
-    [ '强制更新', currentUpdateInfo.force ],
-    [ '公共访问路径', currentUpdateInfo.publicUrl ],
-    [ '存储类型', storageTypeConstant[currentUpdateInfo.storageType] ],
-    [ '存储路径', currentUpdateInfo.storagePath ],
-  );
-
-  console.log(table.toString());
-
-  if (currentUpdateInfo.activeWebVersionName) {
-    table.push(
-      [ '使用中的Web版本', currentUpdateInfo.activeWebVersionName ],
-    );
-  }
-  if (currentUpdateInfo.activeAppVersionName) {
-    table.push(
-      [ '使用中的App版本', currentUpdateInfo.activeAppVersionName ],
-    );
-  }
-
-  return {
-    currentUpdateInfo,
-    currentVersionInfo,
-  }
-}
-async function getUpdate(action, type, all, options) {
-  const typeNotANumber = isNaN(new Number(type)); 
-
-  if (action === 'view' && (!type || typeNotANumber)) {
-
-    let hasSerch = false;
-    const search = {};
-    const sort = {
-      field: "createAt",
-      order: "descend"
-    }
-    if (typeNotANumber && type !== 'all') {
-      hasSerch = true;
-      search.version = type;
-    }
-
-    const data = await axiosInstance.get('/update/list?full=true' + (hasSerch ? ('&search=' + JSON.stringify(search)) : '') + '&sort=' + JSON.stringify(sort));
-    const table = new Table({
-      head: ['ID', '版本', '版本号', '类型', '状态'], 
-      colWidths: [10, 10, 20, 10, 15 ]
-    });
-
-    if (type !== 'all' && all !== 'all' && data.data.length > 10) {
-      data.data = data.data.slice(0, 10);
-      console.log('filter!', all);
-    }
-
-    data.data.forEach((d) => {
-      table.push([ 
-        d.id, 
-        (d.activeAppVersionName ? `${d.activeAppVersionName} (App)` : (
-          d.activeWebVersionName? `${d.activeWebVersionName} (Web)` : '无'
-        )),  
-        d.versionCode, typeConstant[d.type], stateConstant[d.status] 
-      ]);
-    })
-    
-    console.log(table.toString());
-  } else {
-    switch (action) {
-      case 'post': {
-        await postUpdate(type, options);
-        break;
-      }
-      case 'delete': {
-        await deprecateOrDeleteUpdate(type);
-        break;
-      }
-      case 'view': {
-        viewUpdate(type);
-        break;
-      }
-      default: 
-        console.error('Unknow action', action);
-        break;
-    }
-  }
-}
-async function testVersion(version) {
-  try {
-    const data = await axiosInstance.get('/update-get-info?version=' + version);
-    console.log('版本信息', data.data);
-  } catch(e) {
-    console.log('获取失败', e);
-  }
-}
-
-//程序入口
-//============================================
-
-program
-  .command('login <user>')
-  .description('登录')
-  .action(login);
-program
-  .command('logstate')
-  .description('检查登录状态')
-  .action(checkLogged);
-program
-  .command('logout')
-  .description('退出登录')
-  .action(logout);
-
-program
-  .command('test <version>')
-  .description('测试更新入口')
-  .action(testVersion);
-
-program
-  .command('version <action> [type]')
-  .description('查看版本信息/发布版本/删除版本/设置版本, action 可选 view/new/delete/set-web-update/set-app-update/set-next-app-update')
-  .action(getVersion);
-program
-  .command('update <action> [type] [all]')
-  .description('查看更新信息/发布更新, action 可选 view/post, view type 可选 id/all; post type 可选 web/app')
-  .option('--skip', '跳过构建')
-  .option('--ndelete', '不删除构建文件')
-  .action(getUpdate);
-
-function start() {
-  program.parse(process.argv);
-}
-
-process.on('unhandledRejection', (reason, p) => {
-  console.error('Promise: ', p, 'Reason: ', reason)
-})

+ 0 - 66
src/scripts/UpdateScript/postConfig.mjs

@@ -1,66 +0,0 @@
-import { readFileSync } from 'node:fs';
-import { pad } from './postUpdate.mjs';;
-import { dirname } from 'node:path';
-import { fileURLToPath } from 'node:url';
-import path from 'node:path';
-
-//基础配置
-//========================================
-
-const __filename = fileURLToPath(import.meta.url);
-const __dirname = dirname(__filename);
-
-//提交更新配置
-//========================================
-
-export const config = {
-  submitKey: '',
-  uploadWebConfig: {
-    storageAction: 'override',
-    storageProps: {
-      overrideMode: 'overrideAll',
-      overrideFiles: [ ],
-      newFolderNameGenerateType: 'hash',
-    },
-    deprecateConfig: {
-      indexFile: 'index.html',
-      updateHtml: readFileSync(path.resolve(__dirname, './deprecate.html'), 'utf8')
-    },
-  },
-  buildWebCommand: 'npm run nuxt-build', //构建命令
-  buildWebOutDir: '../../../.output', //构建输出目录。相对于当前文件目录
-  buildWebOptions: {
-    skipFiles: [
-      '/server/node_modules',
-    ],
-  },
-  buildWebOutVersionPath: '', //版本号输出目录,输出版本号至文件以供项目使用。相对于当前文件目录
-  /**
-   * 自定义生成Web版本号的方法。
-   * @param {Date} now 当前日期
-   * @param {Number} lastTodaySubVersion 今天上传的之前版本数量
-   * @returns 
-   */
-  buildWebVersionGenerateCommand: async (now, lastTodaySubVersion) => {
-    //生成Web版本号
-    const version = `${now.getFullYear().toString().substring(2)}${pad(now.getMonth() + 1, 2)}${pad(now.getDate(), 2)}.${pad(lastTodaySubVersion, 2)}`;
-    return version;
-  },
-  buildAppCallback: async (param, versionCode, lastTodaySubVersion) => {
-    //构建App
-    throw new Error('未实现buildAppCallback方法');
-  }, 
-  buildAppGetUploadFile: async (param) => {
-    //获取上传文件路径
-    throw new Error('未实现buildAppGetUploadFile方法');
-  }, 
-  buildAppGetOSSFileName: async (param) => {
-    //生成OSS保存路径
-    throw new Error('buildAppGetOSSFileName');
-  },//构建命令
-  buildAppOutDir: './dist', //构建输出目录。相对于当前文件目录
-  buildAppGetVersion: async () => {
-    //获取版本号
-    throw new Error('未实现buildAppGetVersion方法');
-  },
-} 

+ 0 - 430
src/scripts/UpdateScript/postUpdate.mjs

@@ -1,430 +0,0 @@
-/**
- * 更新发布工具
- * 
- * Copyright © 2025 imengyu.top imengyu-update-server
- */
-
-import { confirm , input } from '@inquirer/prompts';
-import { writeFile, readFile, access, unlink, readdir, stat, constants } from 'node:fs/promises';
-import { exec } from 'node:child_process';
-import fs from 'fs';
-import archiver from 'archiver';
-import path, { resolve } from 'node:path';
-import OSS from 'ali-oss';
-import cliProgress from 'cli-progress';
-import { selectVersion } from './index.mjs';
-import { config } from './postConfig.mjs';
-import { dirname } from 'node:path';
-import { fileURLToPath } from 'node:url';
-
-//基础配置
-//========================================
-
-const __filename = fileURLToPath(import.meta.url);
-const __dirname = dirname(__filename);
-
-function readFileRange(file, start, length) {
-  return new Promise((resolve, reject) => {
-    fs.open(file, 'r', (err, fd) => {
-      if (err) {
-        reject('Error opening file:', er);
-        return;
-      }
-      const buffer = Buffer.alloc(length);
-      fs.read(fd, buffer, 0, length, start, (err, bytesRead, buffer) => {
-        if (err) {
-          reject('Error reading file:', err)
-          return;
-        }
-        fs.close(fd, (err) => {
-          if (err) {
-            reject('Error closing file:', err)
-            return ;
-          }
-          resolve(buffer);
-        });
-      });
-    });
-  })
-  
-}
-export function pad(num, n) {
-  var strNum = num.toString();
-  var len = strNum.length;
-  while (len < n) {
-    strNum = "0" + strNum;
-    len++;
-  }
-  return strNum;
-}
-async function getConfig() {
-  let postConfig = {
-    lastVersion: '',
-    lastUpdateInfo: '',
-    lastSubmitDay: '',
-    lastTodaySubVersion: 0,
-  };
-  try {
-    postConfig = JSON.parse(await readFile(path.resolve(__dirname, './_config.json')));
-  } catch {
-    //
-  }
-  if (postConfig.lastSubmitDay != new Date().getDate()) 
-    postConfig.lastTodaySubVersion = 0;
-  return postConfig;
-}
-async function saveConfig(postConfig) {
-  postConfig.lastSubmitDay = new Date().getDate();
-  await writeFile(path.resolve(__dirname, './_config.json'), JSON.stringify(postConfig));
-}
-
-async function getUpdateInfo(postConfig) {
-  let updateInfo = await input({ message: '输入更新信息', default: postConfig.lastUpdateInfo });
-  if (updateInfo === 'git') {
-    console.log('开始获取git提交信息');
-    updateInfo = await new Promise((resolve, reject) => {
-      exec('git log -1 --pretty=format:"%h %s"', (error, stdout, stderr) => {
-        if (error) {
-          reject(error);
-          return;
-        }
-        resolve(stdout);
-      });
-    });
-    console.log('使用git提交信息作为更新信息');
-  }
-  return updateInfo;
-}
-
-//App更新与提交
-//========================================
-
-export async function postAppUpdate(axiosInstance, param) {
-  const postConfig = await getConfig();
-  const versionId = await selectVersion(false, postConfig.lastVersion);
-  const updateInfo = await getUpdateInfo(postConfig);
-
-  await axiosInstance.post('/update-post', { config: { type: 2, test: true, versionId, uploadWebConfig: config.uploadWebConfig, submitKey: config.submitKey } });
-
-  postConfig.lastVersion = versionId;
-  postConfig.lastUpdateInfo = updateInfo;
-  postConfig.lastTodaySubVersion++;
-
-  const updateSource = (await select({
-    choices: [
-      {
-        name: '重新构建',
-        value: 'rebuild',
-      },
-      {
-        name: '已上传的阿里OSS文件路径',
-        value: 'uploaded-alioss',
-      },
-    ],
-    message: '选择上传来源',
-    default: 'rebuild',
-  }));
-
-  const force = await confirm({ message: '强制更新?', default: false });
-  const updateNext = hotfix ? false : await confirm({ message: '作为下个版本?', default: false });
-  const versionCode = config.buildAppGetVersion();
-
-  await saveConfig(postConfig);
-
-  if (updateSource === 'rebuild') 
-    await config.buildAppCallback(param, versionCode, postConfig.lastTodaySubVersion);
-  else if (updateSource === 'uploaded-alioss') {
-    const fileName = await input({ message: '输入已上传的阿里OSS文件路径' });
-    try {
-      const result = (await axiosInstance.post('/update-post', {
-        type: 2,
-        ossConfig: {
-          ossPath: fileName,
-          ossPublic: '',
-        },
-        uploadAppConfig: {
-          updateAsNext: updateNext,
-        },
-        versionId,
-        updateInfo,
-        versionCode: versionCode
-      })).data;
-      console.log('上传成功');
-      console.log('新更新ID: ' + result.updateId);
-    } catch (e) {
-      console.error('上传失败', e);
-    }
-    return;
-  }
-  else {
-    console.error('错误的选择');
-    return;
-  }
-
-  const uploadFile = await config.buildAppGetUploadFile(param);
-  try {
-    await access(uploadFile, constants.R_OK)
-  } catch {
-    console.error(`Failed to access ${uploadFile}, did you created it?`);
-    return;
-  }
-
-  console.log('开始上传');
-
-  //小于8mb则小文件上传,否则使用阿里OSS上传
-  const fileInfo = await stat(uploadFile);
-  if (fileInfo.size < 8 * 1024 * 1024) {
-    const appData = (await readFile(uploadFile));
-
-    const formData = new FormData();
-    formData.append("file", new Blob([ appData ], { type : 'application/zip' }));
-    formData.append("type", 2);
-    formData.append("versionId", versionId);
-    formData.append("updateInfo", updateInfo);
-    formData.append("uploadAppConfig", { updateAsNext: updateNext });
-    formData.append("force", force);
-    formData.append("versionCode", versionCode);
-
-    try {
-      const result = (await axiosInstance.post('/update-post', formData, {
-        headers: { 'Content-Type': 'multipart/form-data' }
-      })).data;
-      console.log('上传成功');
-      console.log('新更新ID: ' + result.updateId);
-      console.log('删除构建文件');
-
-      await unlink(uploadFile);
-    } catch (e) {
-      console.error('上传失败', e);
-    }
-
-  } else {
-    //阿里OSS上传
-    //请求STS进行临时授权
-    const stsToken = (await axiosInstance.post('/update-ali-oss-sts')).data;
-    const client = new OSS({
-      region: stsToken.Region,
-      accessKeyId: stsToken.AccessKeyId,
-      accessKeySecret: stsToken.AccessKeySecret,
-      stsToken: stsToken.SecurityToken,
-      bucket: stsToken.Bucket,
-      refreshSTSToken: async () => {
-        const refreshToken = (await axiosInstance.get("/update-ali-oss-sts")).data;
-        return {
-          accessKeyId: refreshToken.AccessKeyId,
-          accessKeySecret: refreshToken.AccessKeySecret,
-          stsToken: refreshToken.SecurityToken,
-        };
-      },
-    });
-    
-    //小于96mb则直接上传,否则分片上传
-    const fileName = `/${await config.buildAppGetOSSFileName(param)}`;
-
-    console.log('Start upload to ali oss');
-
-    let returnUrl = '';
-    if (fileInfo.size < 96 * 1024 * 1024) {
-      const result = await client.put(fileName, uploadFile);
-      returnUrl = result.url;
-    } else {
-      const bar1 = new cliProgress.SingleBar({}, cliProgress.Presets.shades_classic);
-      bar1.start(100, 0);
-      await aliOSSMultipartUpload(client, fileName, uploadFile, (p) => {
-        bar1.update(p * 100);
-      });
-      bar1.update(100);
-      bar1.stop();
-    }
-
-    console.log('Upload to ali oss done');
-  
-    try {
-      const result = (await axiosInstance.post('/update-post', {
-        type: 2,
-        ossConfig: {
-          ossPath: fileName,
-          ossPublic: returnUrl,
-        },
-        uploadAppConfig: {
-          updateAsNext: updateNext,
-        },
-        versionId,
-        updateInfo,
-        versionCode: versionCode
-      })).data;
-      console.log('上传成功');
-      console.log('新更新ID: ' + result.updateId);
-    } catch (e) {
-      console.error('上传失败', e);
-    }
-  }
-}
-
-//Web更新与提交
-//========================================
-
-export async function postWebUpdate(axiosInstance, param) {
-  const skipBuild = param.skip
-  const noDelete = param.ndelete;
-  
-  const postConfig = await getConfig();
-  const versionId = await selectVersion(false, postConfig.lastVersion);
-  const updateInfo = await getUpdateInfo(postConfig);
-
-  postConfig.lastVersion = versionId;
-  postConfig.lastUpdateInfo = updateInfo;
-  postConfig.lastTodaySubVersion++;
-
-  await axiosInstance.post('/update-post', { config: { type: 1, test: true, versionId, uploadWebConfig: config.uploadWebConfig, submitKey: config.submitKey } });
-
-  const now = new Date();
-  const versionCode = await config.buildWebVersionGenerateCommand(now, postConfig.lastTodaySubVersion);
-
-  if (config.buildWebOutVersionPath)
-    await writeFile(path.resolve(__dirname, config.buildWebOutVersionPath), versionCode);
-
-  await saveConfig(postConfig);
-  
-  if (!skipBuild && config.buildWebCommand) {
-    console.log('正在执行构建...');
-
-    await new Promise((resolve, reject) => {
-      exec(config.buildWebCommand, function(err, stdout) {
-        if (err)
-          reject(err);
-        else 
-          resolve();
-      });
-    });
-
-    console.log('构建完成');
-  }
-
-  const distDir = path.resolve(__dirname, config.buildWebOutDir);
-
-  try {
-    await access(distDir, constants.R_OK)
-  } catch {
-    console.error(`Failed to access ${distDir}`);
-    return;
-  }
-
-  const outputPath = __dirname + '/upload.zip';
-  const skipFiles = config?.buildWebOptions?.skipFiles ?? [];
-
-  function checkPathSkip(path) {
-    if (!skipFiles || skipFiles.length === 0)
-      return;
-    return skipFiles.find((item) => path.startsWith(item));
-  }
-
-  if (!skipBuild) {
-    console.log('开始压缩zip...');
-
-    const output = fs.createWriteStream(outputPath);
-    const archive = archiver('zip', {
-      zlib: { level: 9 } // Sets the compression level.
-    });
-    archive.pipe(output);
-
-    async function loopDir(path, subPrefix) {
-      const files = await readdir(path);
-      for (const file of files) {
-        const subPath = subPrefix + '/' + file;
-        if (checkPathSkip(subPath))
-          continue;
-        const filestat = await stat(distDir + subPath);
-        if (filestat.isDirectory()) {
-          await loopDir(distDir + subPath, subPath);
-        } else {
-          archive.file(distDir + subPath, { name: subPath });
-        }
-      }
-    }
-    await loopDir(distDir, '')
-
-    console.log('等待压缩zip...');
-
-    const waitArchive = new Promise((resolve, reject) => {
-      output.on('close', function() {
-        console.log(archive.pointer() + ' total bytes');
-        console.log('archiver has been finalized and the output file descriptor has closed.');
-        resolve();
-      });
-      archive.on('error', function(err) {
-        reject(err);
-      });
-    })
-
-    await archive.finalize();
-    await waitArchive;
-  }
-
-  console.log('开始上传zip');
-
-  let success = false;
-
-  //小于8mb则小文件上传,否则分片上传
-  const fileInfo = await stat(outputPath);
-  const formData = new FormData();
-  const submitConfig = {
-    type: 1,
-    versionId,
-    updateInfo,
-    versionCode,
-    uploadWebConfig: config.uploadWebConfig,
-  }
-
-  if (fileInfo.size < 8 * 1024 * 1024) {
-    const uploadZipContent = await readFile(outputPath);
-    formData.append("file", new Blob([ uploadZipContent ], { type : 'application/zip' }), 'upload.zip');
-  } else {
-    const multuploadInfo = (await axiosInstance.post('/update-large-token', {
-      fileSize: fileInfo.size,
-      fileName: path.basename(outputPath)
-    })).data;
-    const chunkSize = multuploadInfo.splitPartSize;
-
-    const bar1 = new cliProgress.SingleBar({}, cliProgress.Presets.shades_classic);
-    bar1.start(100, 0);
-
-    for (let i = 0; i < multuploadInfo.allChunks; i++) {
-      const start = i * chunkSize;
-      const len = Math.min(start + chunkSize, fileInfo.size) - start;
-      const uploadZipContent = await readFileRange(outputPath, start, len);
-      const subFormData = new FormData();
-      subFormData.append("file", new Blob([ uploadZipContent ], { type : 'application/zip' }), 'upload.zip');
-      subFormData.append("key", multuploadInfo.key);
-      subFormData.append("info", JSON.stringify({}));
-      
-      (await axiosInstance.post('/update-large', subFormData, {
-        headers: { 'Content-Type': 'multipart/form-data' }
-      })).data;
-      
-      bar1.update(Math.floor(i / multuploadInfo.allChunks * 100));
-    }
-
-    bar1.update(100);
-    bar1.stop();
-
-    submitConfig.multuploadedKey = multuploadInfo.key;
-  }
-
-  try {
-    formData.append("config", JSON.stringify(submitConfig));
-    const result = (await axiosInstance.post('/update-post', formData, {
-      headers: { 'Content-Type': 'multipart/form-data' }
-    })).data;
-    console.log('上传成功');
-    console.log('新更新ID: ' + result.updateId);
-    success = true;
-  } catch (e) {
-    console.error('上传失败', e);
-  }
-  if (!success || noDelete) 
-    return;
-    
-  console.log('删除zip');
-  await unlink(outputPath);
-}