no message

This commit is contained in:
kuaifan 2022-03-29 22:26:16 +08:00
parent 6ed24ec310
commit 5485f2013e
39 changed files with 576 additions and 324 deletions

75
.github/workflows/electron-generic.yml vendored Normal file
View File

@ -0,0 +1,75 @@
name: Build Generic
on:
push:
tags:
- 'v*'
jobs:
build-mac:
runs-on: macos-latest
environment: build
if: startsWith(github.event.ref, 'refs/tags/v')
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Create changelog text
id: changelog
uses: loopwerk/tag-changelog@v1
with:
token: ${{ secrets.GH_PAT }}
exclude_types: other,chore,build
- name: Use Node.js 16.x
uses: actions/setup-node@v1
with:
node-version: 16.x
- name: Build for MacOS
env:
APPLEID: ${{ secrets.APPLEID }}
APPLEIDPASS: ${{ secrets.APPLEIDPASS }}
CSC_KEY_PASSWORD: ${{ secrets.CSC_KEY_PASSWORD }}
CSC_LINK: ${{ secrets.CSC_LINK }}
PROVIDER: "generic"
RELEASE_BODY: ${{ steps.changelog.outputs.changes }}
run: ./cmd electron build-mac
build-win:
runs-on: windows-latest
environment: build
if: startsWith(github.event.ref, 'refs/tags/v')
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Create changelog text
id: changelog
uses: loopwerk/tag-changelog@v1
with:
token: ${{ secrets.GH_PAT }}
exclude_types: other,chore,build
- name: Use Node.js 16.x
uses: actions/setup-node@v1
with:
node-version: 16.x
- name: Build for Windows
shell: powershell
env:
PROVIDER: "generic"
RELEASE_BODY: ${{ steps.changelog.outputs.changes }}
run: |
npm install
cd electron
npm install
cd ../
mkdir -p ./electron/public
cp ./electron/index.html ./electron/public/index.html
npx mix --production -- --env --electron
node ./electron/build.js build-win

85
.github/workflows/electron-main.yml vendored Normal file
View File

@ -0,0 +1,85 @@
name: Build Main
on:
push:
tags:
- 'v*'
jobs:
release:
runs-on: ubuntu-latest
if: startsWith(github.event.ref, 'refs/tags/v')
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Create changelog text
id: changelog
uses: loopwerk/tag-changelog@v1
with:
token: ${{ secrets.GH_PAT }}
exclude_types: other,chore,build
- name: Create release
uses: actions/create-release@latest
env:
GITHUB_TOKEN: ${{ secrets.GH_PAT }}
with:
tag_name: ${{ github.ref }}
release_name: Release ${{ github.ref }}
body: ${{ steps.changelog.outputs.changes }}
build-mac:
runs-on: macos-latest
environment: build
if: startsWith(github.event.ref, 'refs/tags/v')
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Use Node.js 16.x
uses: actions/setup-node@v1
with:
node-version: 16.x
- name: Build for MacOS
env:
APPLEID: ${{ secrets.APPLEID }}
APPLEIDPASS: ${{ secrets.APPLEIDPASS }}
CSC_KEY_PASSWORD: ${{ secrets.CSC_KEY_PASSWORD }}
CSC_LINK: ${{ secrets.CSC_LINK }}
GH_TOKEN: ${{ secrets.GH_PAT }}
EP_PRE_RELEASE: true
run: ./cmd electron build-mac
build-win:
runs-on: windows-latest
environment: build
if: startsWith(github.event.ref, 'refs/tags/v')
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Use Node.js 16.x
uses: actions/setup-node@v1
with:
node-version: 16.x
- name: Build for Windows
shell: powershell
env:
GH_TOKEN: ${{ secrets.GH_PAT }}
EP_PRE_RELEASE: true
run: |
npm install
cd electron
npm install
cd ../
mkdir -p ./electron/public
cp ./electron/index.html ./electron/public/index.html
npx mix --production -- --env --electron
node ./electron/build.js build-win

View File

@ -1,61 +0,0 @@
name: Build
on:
push:
tags:
- 'v*'
jobs:
release:
runs-on: ubuntu-latest
if: startsWith(github.event.ref, 'refs/tags/v')
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Create changelog text
id: changelog
uses: loopwerk/tag-changelog@v1
with:
token: ${{ secrets.GH_PAT }}
exclude_types: other,chore,build
- name: Create release
uses: actions/create-release@latest
env:
GITHUB_TOKEN: ${{ secrets.GH_PAT }}
with:
tag_name: ${{ github.ref }}
release_name: Release ${{ github.ref }}
body: ${{ steps.changelog.outputs.changes }}
build:
runs-on: ${{ matrix.os }}
environment: build
strategy:
matrix:
os: [macos-11]
platform: [
build-mac,
build-mac-arm,
build-win
]
if: startsWith(github.event.ref, 'refs/tags/v')
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Use Node.js 14.x
uses: actions/setup-node@v1
with:
node-version: 14.x
- name: Build
env:
GH_TOKEN: ${{ secrets.GH_PAT }}
EP_PRE_RELEASE: true
run: ./cmd electron ${{ matrix.platform }}

View File

@ -48,7 +48,7 @@ class IndexController extends InvokeController
return [
'version' => Base::getVersion(),
'owner' => 'kuaifan',
'repo' => 'dootask-test',
'repo' => 'dootask',
];
}

View File

@ -376,7 +376,6 @@ class Project extends AbstractModel
$idc = [];
$hasStart = false;
$hasEnd = false;
$testNum = 0;
$upTaskList = [];
foreach ($flows as $item) {
$id = intval($item['id']);
@ -417,9 +416,6 @@ class Project extends AbstractModel
if ($flow->status == 'end') {
$hasEnd = true;
}
if ($flow->status == 'test') {
$testNum++;
}
if (!$isInsert) {
$upTaskList[$flow->id] = $flow->status . "|" . $flow->name;
}
@ -428,9 +424,6 @@ class Project extends AbstractModel
if (!$hasStart) {
throw new ApiException('至少需要1个开始状态');
}
if ($testNum > 1) {
throw new ApiException('验收/测试状态只能有1个');
}
if (!$hasEnd) {
throw new ApiException('至少需要1个结束状态');
}

122
electron/build.js vendored
View File

@ -1,8 +1,12 @@
const os = require('os')
const fs = require('fs');
const fse = require('fs-extra');
const path = require('path')
const inquirer = require('inquirer');
const child_process = require('child_process');
const ora = require('ora');
const axios = require('axios');
const FormData =require('form-data');
const utils = require('./utils');
const config = require('../package.json')
const argv = process.argv;
@ -13,7 +17,8 @@ const nativeCachePath = path.resolve(__dirname, ".native");
const devloadCachePath = path.resolve(__dirname, ".devload");
const packageFile = path.resolve(__dirname, "package.json");
const packageBakFile = path.resolve(__dirname, "package-bak.json");
const platform = ["build-mac", "build-mac-arm", "build-win"];
const platform = ["build-mac", "build-win"];
const comSuffix = os.type() == 'Windows_NT' ? '.cmd' : '';
// 克隆 Drawio
function cloneDrawio(systemInfo) {
@ -35,12 +40,48 @@ function cloneDrawio(systemInfo) {
fs.writeFileSync(preConfigFile, preConfigString, 'utf8');
}
// 通用发布
function genericPublish(url, version) {
const filePath = path.resolve(__dirname, "dist")
fs.readdir(filePath, async (err, files) => {
if (err) {
console.warn(err)
} else {
for (const filename of files) {
const localFile = path.join(filePath, filename)
const fileStat = fs.statSync(localFile)
if (fileStat.isFile()) {
const uploadOra = ora(`${filename} uploading...`).start()
const formData = new FormData()
formData.append("file", fs.createReadStream(localFile));
await axios({
method: 'post',
url: url,
data: formData,
maxContentLength: Infinity,
maxBodyLength: Infinity,
headers: {
'Generic-Version': version,
'Content-Type': 'multipart/form-data;boundary=' + formData.getBoundary(),
}
}).then(_ => {
uploadOra.succeed(`${filename} upload successful`)
}).catch(_ => {
uploadOra.fail(`${filename} upload fail`)
})
}
}
}
});
}
// 生成配置、编译应用
function startBuild(data, publish) {
// information
console.log("Name: " + data.name);
console.log("AppId: " + data.id);
console.log("Version: " + config.version);
console.log("Publish: " + (publish ? 'Yes' : 'No'));
let systemInfo = {
title: data.name,
version: config.version,
@ -68,12 +109,24 @@ function startBuild(data, publish) {
econfig.build.appId = data.id;
econfig.build.artifactName = utils.getDomain(data.url) + "-v${version}-${os}-${arch}.${ext}";
econfig.build.nsis.artifactName = utils.getDomain(data.url) + "-v${version}-${os}-${arch}.${ext}";
econfig.build.pkg.mustClose = [data.id];
if (publish === false || typeof process.env.APPLEID !== "string" || !process.env.APPLEID) {
delete econfig.build.afterSign;
}
if (publish === true && utils.isJson(data.publish)) {
econfig.build.publish = data.publish
}
if (publish === true && process.env.RELEASE_BODY) {
econfig.build.releaseInfo.releaseNotes = process.env.RELEASE_BODY
}
fs.writeFileSync(packageFile, JSON.stringify(econfig, null, 2), 'utf8');
// build
child_process.spawnSync("npm", ["run", data.platform + (publish === true ? "-publish" : "")], {stdio: "inherit", cwd: "electron"});
child_process.spawnSync("npm" + comSuffix, ["run", data.platform + (publish === true ? "-publish" : "")], {stdio: "inherit", cwd: "electron"});
// package.json Recovery
fse.copySync(packageBakFile, packageFile)
// generic publish
if (econfig.build.publish.provider === "generic") {
genericPublish(econfig.build.publish.url, config.version)
}
}
if (["dev"].includes(argv[2])) {
@ -83,63 +136,62 @@ if (["dev"].includes(argv[2])) {
child_process.spawn("npm", ["run", "start-quiet"], {stdio: "inherit", cwd: "electron"});
} else if (platform.includes(argv[2])) {
// 自动编译
config.app.sites.forEach((data) => {
if (data.name && data.id && data.url) {
let provider = process.env.PROVIDER === "generic" ? "generic" : "github"
config.app.forEach(data => {
if (data.publish.provider === provider) {
data.platform = argv[2];
startBuild(data, true)
}
})
} else {
// 自定义编译
let appChoices = [];
config.app.forEach(data => {
appChoices.push({
name: data.name,
value: data
})
})
const questions = [
{
type: 'input',
name: 'website',
message: "请输入网站地址",
default: () => {
if (fs.existsSync(nativeCachePath)) {
return fs.readFileSync(nativeCachePath, 'utf8');
}
return undefined;
},
validate: function (value) {
if (!utils.rightExists(value, "/")) {
return '网址必须以 "/" 结尾';
}
return value !== ''
}
type: 'list',
name: 'app',
message: "选择编译应用",
choices: appChoices
},
{
type: 'list',
name: 'platform',
message: "选择编译系统平台",
message: "选择编译系统",
choices: [{
name: "MacOS",
value: [platform[0]]
}, {
name: "MacOS arm64",
name: "Window",
value: [platform[1]]
}, {
name: "Window x86_64",
value: [platform[2]]
}, {
name: "All platforms",
value: platform
}]
},
{
type: 'list',
name: 'publish',
message: "选择是否要发布",
choices: [{
name: "No",
value: false
}, {
name: "Yes",
value: true
}]
}
];
inquirer.prompt(questions).then(answers => {
answers.platform.forEach(platform => {
startBuild({
"name": config.name,
"id": config.app.id,
"url": answers.website,
"platform": platform
}, false)
let data = answers.app;
data.platform = platform
startBuild(data, answers.publish)
});
});
}

56
electron/electron.js vendored
View File

@ -3,6 +3,7 @@ const fse = require('fs-extra')
const os = require("os");
const path = require('path')
const {app, BrowserWindow, ipcMain, dialog, clipboard, nativeImage, shell} = require('electron')
const {autoUpdater} = require("electron-updater")
const log = require("electron-log");
const fsProm = require('fs/promises');
const PDFDocument = require('pdf-lib').PDFDocument;
@ -79,11 +80,11 @@ function createMainWindow() {
mainWindow.webContents.setUserAgent(mainWindow.webContents.getUserAgent() + " MainTaskWindow/" + process.platform + "/" + os.arch() + "/1.0");
if (devloadUrl) {
mainWindow.loadURL(devloadUrl).then(r => {
mainWindow.loadURL(devloadUrl).then(_ => {
})
} else {
mainWindow.loadFile('./public/index.html').then(r => {
mainWindow.loadFile('./public/index.html').then(_ => {
})
}
@ -171,13 +172,13 @@ function createSubWindow(args) {
browser.webContents.setUserAgent(browser.webContents.getUserAgent() + " SubTaskWindow/" + process.platform + "/" + os.arch() + "/1.0" + (args.userAgent ? (" " + args.userAgent) : ""));
if (devloadUrl) {
browser.loadURL(devloadUrl + '#' + (args.hash || args.path)).then(r => {
browser.loadURL(devloadUrl + '#' + (args.hash || args.path)).then(_ => {
})
} else {
browser.loadFile('./public/index.html', {
hash: args.hash || args.path
}).then(r => {
}).then(_ => {
})
}
@ -406,6 +407,53 @@ ipcMain.on('setDockBadge', (event, args) => {
event.returnValue = "ok"
})
//================================================================
// Update
//================================================================
let autoUpdating = 0
autoUpdater.logger = log
autoUpdater.autoDownload = false
autoUpdater.on('update-available', info => {
mainWindow.webContents.send("updateAvailable", info)
})
autoUpdater.on('update-downloaded', info => {
mainWindow.webContents.send("updateDownloaded", info)
})
/**
* 检查更新
*/
ipcMain.on('updateCheckAndDownload', (event, args) => {
event.returnValue = "ok"
if (autoUpdating + 3600 > utils.Time()) {
return // 限制1小时仅执行一次
}
if (args.provider) {
autoUpdater.setFeedURL(args)
}
autoUpdater.checkForUpdates().then(info => {
if (args.apiVersion) {
if (utils.compareVersion(info.updateInfo.version, args.apiVersion) === 0) {
autoUpdating = utils.Time()
autoUpdater.downloadUpdate().then(_ => {}).catch(_ => {})
}
} else {
autoUpdating = utils.Time()
autoUpdater.downloadUpdate().then(_ => {}).catch(_ => {})
}
})
})
/**
* 退出并安装更新
*/
ipcMain.on('updateQuitAndInstall', (event) => {
event.returnValue = "ok"
autoUpdater.quitAndInstall()
app.quit()
})
//================================================================
// Pdf export
//================================================================

18
electron/notarize.js vendored Normal file
View File

@ -0,0 +1,18 @@
require('dotenv').config();
const { notarize } = require('electron-notarize');
exports.default = async function notarizing(context) {
const { electronPlatformName, appOutDir } = context;
const appName = context.packager.appInfo.productFilename;
if (electronPlatformName !== 'darwin') {
return;
}
return await notarize({
appBundleId: 'com.dootask.desktop',
appPath: `${appOutDir}/${appName}.app`,
appleId: process.env.APPLEID,
appleIdPassword: process.env.APPLEIDPASS,
});
};

View File

@ -1,6 +1,6 @@
{
"name": "DooTask",
"version": "0.12.28",
"version": "1.0.0",
"description": "DooTask is task management system.",
"main": "electron.js",
"license": "MIT",
@ -9,11 +9,9 @@
"start-quiet": "sleep 3 && electron-forge start &> /dev/null",
"build": "electron-builder",
"build-mac": "electron-builder --mac",
"build-mac-arm": "electron-builder --mac --arm64",
"build-win": "electron-builder --win",
"build-mac-publish": "electron-builder -p always --mac",
"build-mac-arm-publish": "electron-builder -p always --mac --arm64",
"build-win-publish": "electron-builder -p always --win",
"build-mac-publish": "electron-builder --publish always --mac",
"build-win-publish": "electron-builder --publish always --win",
"package": "electron-forge package",
"make": "electron-forge make",
"publish": "electron-forge publish"
@ -33,21 +31,24 @@
"@electron-forge/maker-rpm": "^6.0.0-beta.63",
"@electron-forge/maker-squirrel": "^6.0.0-beta.63",
"@electron-forge/maker-zip": "^6.0.0-beta.63",
"dmg-license": "^1.0.10",
"dotenv": "^16.0.0",
"electron": "^17.1.1",
"electron-builder": "^22.14.13"
"electron": "^17.2.0",
"electron-builder": "^23.0.3",
"electron-notarize": "^1.2.1",
"form-data": "^4.0.0",
"ora": "^4.1.1"
},
"dependencies": {
"axios": "^0.26.0",
"axios": "^0.26.1",
"crc": "^3.8.0",
"electron-squirrel-startup": "^1.0.0",
"electron-log": "^4.4.6",
"fs-extra": "^10.0.0",
"pdf-lib": "^1.16.0"
"electron-squirrel-startup": "^1.0.0",
"electron-updater": "^4.6.5",
"fs-extra": "^10.0.1",
"pdf-lib": "^1.17.1"
},
"build": {
"appId": "com.dootask.task",
"appId": "com.dootask.desktop",
"artifactName": "${productName}-v${version}-${os}-${arch}.${ext}",
"asar": true,
"files": [
@ -60,38 +61,52 @@
"publish": {
"provider": "github"
},
"releaseInfo": {},
"afterSign": "./notarize.js",
"mac": {
"icon": "../resources/assets/statics/public/images/logo-app.png",
"entitlements": "entitlements.plist",
"entitlementsInherit": "entitlements.plist",
"category": "public.app-category.productivity",
"target": [
"zip",
"dmg",
"pkg"
{
"target": "zip",
"arch": [
"x64",
"arm64"
]
},
{
"target": "dmg",
"arch": [
"x64",
"arm64",
"universal"
]
}
]
},
"win": {
"icon": "../resources/assets/statics/public/images/logo-app.ico",
"target": [
"tar.gz",
"nsis"
{
"target": "nsis",
"arch": [
"x64"
]
},
{
"target": "msi",
"arch": [
"x64"
]
}
]
},
"nsis": {
"oneClick": false,
"artifactName": "${productName}-v${version}-${os}-${arch}.${ext}",
"allowToChangeInstallationDirectory": true
},
"pkg": {
"installLocation": "/Applications",
"mustClose": [],
"allowAnywhere": true,
"allowCurrentUserHome": true,
"allowRootDirectory": true,
"isVersionChecked": true,
"isRelocatable": false,
"overwriteAction": "upgrade"
}
},
"config": {

59
electron/utils.js vendored
View File

@ -304,4 +304,63 @@ module.exports = {
event.preventDefault()
}
},
/**
* 版本比较
* @param version1
* @param version2
* @returns number 0: 相同1: version1大-1: version2大
*/
compareVersion(version1, version2) {
let pA = 0, pB = 0;
// 版本号完全相同
if (version1 === version2) {
return 0
}
// 寻找当前区间的版本号
const findDigit = (str, start) => {
let i = start;
while (str[i] !== '.' && i < str.length) {
i++;
}
return i;
}
while (pA < version1.length && pB < version2.length) {
const nextA = findDigit(version1, pA);
const nextB = findDigit(version2, pB);
const numA = +version1.substr(pA, nextA - pA);
const numB = +version2.substr(pB, nextB - pB);
if (numA !== numB) {
return numA > numB ? 1 : -1;
}
pA = nextA + 1;
pB = nextB + 1;
}
// 若arrayA仍有小版本号
while (pA < version1.length) {
const nextA = findDigit(version1, pA);
const numA = +version1.substr(pA, nextA - pA);
if (numA > 0) {
return 1;
}
pA = nextA + 1;
}
// 若arrayB仍有小版本号
while (pB < version2.length) {
const nextB = findDigit(version2, pB);
const numB = +version2.substr(pB, nextB - pB);
if (numB > 0) {
return -1;
}
pB = nextB + 1;
}
// 版本号完全相同
return 0;
}
}

View File

@ -1,32 +1,33 @@
{
"name": "DooTask",
"version": "0.12.28",
"version": "0.12.34",
"description": "DooTask is task management system.",
"scripts": {
"start": "./cmd dev",
"build": "./cmd prod",
"version": "node ./version.js"
},
"app": {
"id": "com.dootask.task",
"sites": [
{
"name": "DooTask",
"id": "com.dootask.task",
"url": "https://www.dootask.com/"
},
{
"name": "HitoseaTask",
"id": "com.hitosea.task",
"url": "https://t.hitosea.com/"
},
{
"name": "PublicDooTask",
"id": "com.dootask.public",
"url": "https://public/"
"app": [
{
"name": "DooTask",
"id": "com.dootask.desktop",
"url": "https://dootask.com/",
"publish": {
"provider": "github",
"owner": "kuaifan",
"repo": "dootask"
}
]
},
},
{
"name": "HitoseaTask",
"id": "com.hitosea.desktop",
"url": "https://t.hitosea.com/",
"publish": {
"provider": "generic",
"url": "https://t.hitosea.com/desktop/publish"
}
}
],
"author": {
"name": "KuaiFan",
"email": "aipaw@live.cn",

2
public/css/app.css vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2
public/js/app.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,5 +1,5 @@
/*!
* clipboard.js v2.0.10
* clipboard.js v2.0.8
* https://clipboardjs.com/
*
* Licensed MIT © Zeno Rocha

File diff suppressed because one or more lines are too long

View File

@ -1,5 +1,5 @@
/*!
* clipboard.js v2.0.10
* clipboard.js v2.0.8
* https://clipboardjs.com/
*
* Licensed MIT © Zeno Rocha

View File

@ -1 +0,0 @@
"use strict";(self.webpackChunkDooTask=self.webpackChunkDooTask||[]).push([[341],{88341:(t,e,s)=>{s.r(e),s.d(e,{default:()=>u});var n=s(20629),i=s(80641);function r(t,e){var s=Object.keys(t);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(t);e&&(n=n.filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable}))),s.push.apply(s,n)}return s}function o(t){for(var e=1;e<arguments.length;e++){var s=null!=arguments[e]?arguments[e]:{};e%2?r(Object(s),!0).forEach((function(e){a(t,e,s[e])})):Object.getOwnPropertyDescriptors?Object.defineProperties(t,Object.getOwnPropertyDescriptors(s)):r(Object(s)).forEach((function(e){Object.defineProperty(t,e,Object.getOwnPropertyDescriptor(s,e))}))}return t}function a(t,e,s){return e in t?Object.defineProperty(t,e,{value:s,enumerable:!0,configurable:!0,writable:!0}):t[e]=s,t}const c={data:function(){return{curPath:this.$route.path,show768Menu:!0,version:window.systemInfo.version}},mounted:function(){},computed:o(o({},(0,n.rn)(["userInfo","userIsAdmin","clientNewVersion"])),{},{menu:function(){var t=[{path:"personal",name:"个人设置"},{path:"password",name:"密码设置"}];return this.userIsAdmin&&t.push.apply(t,[{path:"system",name:"系统设置",divided:!0}]),t},titleNameRoute:function(){var t=this.curPath,e=this.menu,s="";return e.some((function(e){if($A.leftExists(t,"/manage/setting/"+e.path))return s=e.name,!0})),s||"设置"}}),watch:{$route:function(t){this.curPath=t.path}},methods:{toggleRoute:function(t){"version"!=t?(this.show768Menu=!1,this.goForward({path:"/manage/setting/"+t})):i.Store.set("releasesNotification",null)},classNameRoute:function(t,e){return{active:$A.leftExists(this.curPath,"/manage/setting/"+t),divided:!!e}}}};const u=(0,s(51900).Z)(c,(function(){var t=this,e=t.$createElement,s=t._self._c||e;return s("div",{staticClass:"page-setting"},[s("PageTitle",{attrs:{title:t.$L(t.titleNameRoute)}}),t._v(" "),s("div",{staticClass:"setting-head"},[s("div",{staticClass:"setting-titbox"},[s("div",{staticClass:"setting-title"},[s("h1",[t._v(t._s(t.$L("设置")))]),t._v(" "),s("div",{staticClass:"setting-more",on:{click:function(e){t.show768Menu=!t.show768Menu}}},[s("Icon",{attrs:{type:t.show768Menu?"md-close":"md-more"}})],1)])])]),t._v(" "),s("div",{staticClass:"setting-box"},[s("div",{staticClass:"setting-menu",class:{"show768-menu":t.show768Menu}},[s("ul",[t._l(t.menu,(function(e,n){return s("li",{key:n,class:t.classNameRoute(e.path,e.divided),on:{click:function(s){return t.toggleRoute(e.path)}}},[t._v(t._s(t.$L(e.name)))])})),t._v(" "),t.clientNewVersion?s("li",{class:t.classNameRoute("version",!0),on:{click:function(e){return t.toggleRoute("version")}}},[s("AutoTip",{attrs:{disabled:""}},[t._v(t._s(t.$L("版本"))+": "+t._s(t.version))]),t._v(" "),s("Badge",{attrs:{text:t.clientNewVersion}})],1):s("li",{staticClass:"version divided"},[s("AutoTip",[t._v(t._s(t.$L("版本"))+": "+t._s(t.version))])],1)],2)]),t._v(" "),s("div",{staticClass:"setting-content"},[s("div",{staticClass:"setting-content-title"},[t._v(t._s(t.$L(t.titleNameRoute)))]),t._v(" "),s("div",{staticClass:"setting-content-view"},[s("router-view",{staticClass:"setting-router-view"})],1)])])],1)}),[],!1,null,null,null).exports}}]);

File diff suppressed because one or more lines are too long

View File

@ -257,7 +257,7 @@
/** @license
*
* jsPDF - PDF Document creation from JavaScript
* Version 2.5.1 Built on 2022-01-28T15:37:57.791Z
* Version 2.5.0 Built on 2021-12-21T09:44:51.866Z
* CommitID 00000000
*
* Copyright (c) 2010-2021 James Hall <james@parall.ax>, https://github.com/MrRio/jsPDF

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -257,7 +257,7 @@
/** @license
*
* jsPDF - PDF Document creation from JavaScript
* Version 2.5.1 Built on 2022-01-28T15:37:57.791Z
* Version 2.5.0 Built on 2021-12-21T09:44:51.866Z
* CommitID 00000000
*
* Copyright (c) 2010-2021 James Hall <james@parall.ax>, https://github.com/MrRio/jsPDF

File diff suppressed because one or more lines are too long

View File

@ -257,7 +257,7 @@
/** @license
*
* jsPDF - PDF Document creation from JavaScript
* Version 2.5.1 Built on 2022-01-28T15:37:57.791Z
* Version 2.5.0 Built on 2021-12-21T09:44:51.866Z
* CommitID 00000000
*
* Copyright (c) 2010-2021 James Hall <james@parall.ax>, https://github.com/MrRio/jsPDF

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -257,7 +257,7 @@
/** @license
*
* jsPDF - PDF Document creation from JavaScript
* Version 2.5.1 Built on 2022-01-28T15:37:57.791Z
* Version 2.5.0 Built on 2021-12-21T09:44:51.866Z
* CommitID 00000000
*
* Copyright (c) 2010-2021 James Hall <james@parall.ax>, https://github.com/MrRio/jsPDF

File diff suppressed because one or more lines are too long

View File

@ -1 +1 @@
/*! @license DOMPurify 2.3.6 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/2.3.6/LICENSE */
/*! @license DOMPurify 2.3.4 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/2.3.4/LICENSE */

File diff suppressed because one or more lines are too long

View File

@ -257,7 +257,7 @@
/** @license
*
* jsPDF - PDF Document creation from JavaScript
* Version 2.5.1 Built on 2022-01-28T15:37:57.791Z
* Version 2.5.0 Built on 2021-12-21T09:44:51.866Z
* CommitID 00000000
*
* Copyright (c) 2010-2021 James Hall <james@parall.ax>, https://github.com/MrRio/jsPDF

1
public/js/build/963.js vendored Normal file
View File

@ -0,0 +1 @@
"use strict";(self.webpackChunkDooTask=self.webpackChunkDooTask||[]).push([[963],{1963:(t,e,s)=>{s.r(e),s.d(e,{default:()=>u});var n=s(20629),i=s(80641);function r(t,e){var s=Object.keys(t);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(t);e&&(n=n.filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable}))),s.push.apply(s,n)}return s}function o(t){for(var e=1;e<arguments.length;e++){var s=null!=arguments[e]?arguments[e]:{};e%2?r(Object(s),!0).forEach((function(e){a(t,e,s[e])})):Object.getOwnPropertyDescriptors?Object.defineProperties(t,Object.getOwnPropertyDescriptors(s)):r(Object(s)).forEach((function(e){Object.defineProperty(t,e,Object.getOwnPropertyDescriptor(s,e))}))}return t}function a(t,e,s){return e in t?Object.defineProperty(t,e,{value:s,enumerable:!0,configurable:!0,writable:!0}):t[e]=s,t}const c={data:function(){return{curPath:this.$route.path,show768Menu:!0,version:window.systemInfo.version}},mounted:function(){},computed:o(o({},(0,n.rn)(["userInfo","userIsAdmin","clientNewVersion"])),{},{menu:function(){var t=[{path:"personal",name:"个人设置"},{path:"password",name:"密码设置"}];return this.userIsAdmin&&t.push.apply(t,[{path:"system",name:"系统设置",divided:!0}]),t},titleNameRoute:function(){var t=this.curPath,e=this.menu,s="";return e.some((function(e){if($A.leftExists(t,"/manage/setting/"+e.path))return s=e.name,!0})),s||"设置"}}),watch:{$route:function(t){this.curPath=t.path}},methods:{toggleRoute:function(t){"version"!=t?(this.show768Menu=!1,this.goForward({path:"/manage/setting/"+t})):i.Store.set("updateNotification",null)},classNameRoute:function(t,e){return{active:$A.leftExists(this.curPath,"/manage/setting/"+t),divided:!!e}}}};const u=(0,s(51900).Z)(c,(function(){var t=this,e=t.$createElement,s=t._self._c||e;return s("div",{staticClass:"page-setting"},[s("PageTitle",{attrs:{title:t.$L(t.titleNameRoute)}}),t._v(" "),s("div",{staticClass:"setting-head"},[s("div",{staticClass:"setting-titbox"},[s("div",{staticClass:"setting-title"},[s("h1",[t._v(t._s(t.$L("设置")))]),t._v(" "),s("div",{staticClass:"setting-more",on:{click:function(e){t.show768Menu=!t.show768Menu}}},[s("Icon",{attrs:{type:t.show768Menu?"md-close":"md-more"}})],1)])])]),t._v(" "),s("div",{staticClass:"setting-box"},[s("div",{staticClass:"setting-menu",class:{"show768-menu":t.show768Menu}},[s("ul",[t._l(t.menu,(function(e,n){return s("li",{key:n,class:t.classNameRoute(e.path,e.divided),on:{click:function(s){return t.toggleRoute(e.path)}}},[t._v(t._s(t.$L(e.name)))])})),t._v(" "),t.clientNewVersion?s("li",{class:t.classNameRoute("version",!0),on:{click:function(e){return t.toggleRoute("version")}}},[s("AutoTip",{attrs:{disabled:""}},[t._v(t._s(t.$L("版本"))+": "+t._s(t.version))]),t._v(" "),s("Badge",{attrs:{text:t.clientNewVersion}})],1):s("li",{staticClass:"version divided"},[s("AutoTip",[t._v(t._s(t.$L("版本"))+": "+t._s(t.version))])],1)],2)]),t._v(" "),s("div",{staticClass:"setting-content"},[s("div",{staticClass:"setting-content-title"},[t._v(t._s(t.$L(t.titleNameRoute)))]),t._v(" "),s("div",{staticClass:"setting-content-view"},[s("router-view",{staticClass:"setting-router-view"})],1)])])],1)}),[],!1,null,null,null).exports}}]);

View File

@ -5,28 +5,28 @@
{{ $L('使用 SSO 登录') }}
</div>
<template v-if="showDown">
<div v-if="$Electron" class="common-right-bottom-link" @click="updateWinShow=true">
<a v-if="downloadUrl" class="common-right-bottom-link" :href="downloadUrl" target="_blank">
<Icon type="md-download"/>
{{ $L(repoTitle) }}
</div>
<a v-else class="common-right-bottom-link" :href="repoReleases.html_url" target="_blank">
<Icon type="md-download"/>
{{ $L(repoTitle) }}
{{ $L('客户端下载') }}
</a>
<div v-else-if="updateVersion && $Electron" class="common-right-bottom-link" @click="updateShow=true">
<Icon type="md-download"/>
{{ $L('更新客户端') }}
</div>
</template>
<Modal
v-model="updateWinShow"
v-model="updateShow"
:cancel-text="$L('稍后')"
:ok-text="$L('立即升级')"
:closable="false"
:mask-closable="false"
@on-ok="installApplication"
@on-cancel="repoStatus=2"
@on-ok="updateQuitAndInstall"
class-name="common-right-bottom-notification">
<div slot="header" class="notification-head">
<div class="notification-title">{{$L('发现新版本')}}</div>
<Tag color="volcano">{{repoReleases.tag_name}}</Tag>
<Tag color="volcano">v{{systemVersion}} -&gt; v{{updateVersion}}</Tag>
</div>
<MarkdownPreview class="notification-body overlay-y" :initialValue="repoReleases.body"/>
<MarkdownPreview class="notification-body overlay-y" :initialValue="updateNote"/>
</Modal>
</div>
</template>
@ -43,69 +43,123 @@ export default {
data() {
return {
loadIng: 0,
repoName: 'kuaifan/dootask',
repoData: {},
repoStatus: 0, // 0 12
repoReleases: {},
updateWinShow: false,
downloadResult: {},
subscribe: null,
apiVersion: '',
systemVersion: window.systemInfo.version,
updateVersion: '',
updateNote: '',
updateShow: false,
downloadUrl: '',
}
},
mounted() {
this.getReleases();
this.checkVersion()
//
this.subscribe = Store.subscribe('releasesNotification', () => {
this.updateWinShow = true;
});
//
if (this.$Electron) {
this.$Electron.registerMsgListener('downloadDone', ({result}) => {
if (result.name == this.repoData.name && this.repoStatus !== 2) {
this.$store.state.clientNewVersion = this.repoReleases.tag_name
this.downloadResult = result;
this.updateWinShow = true;
}
})
}
this.subscribe = Store.subscribe('updateNotification', _ => {
this.updateShow = true
})
},
beforeDestroy() {
if (this.subscribe) {
this.subscribe.unsubscribe();
this.subscribe = null;
}
},
computed: {
...mapState([
'isDesktop',
'wsOpenNum',
]),
repoTitle() {
return this.repoStatus == 2 ? '更新客户端' : '客户端下载';
},
showSSO() {
return this.$Electron && ['login'].includes(this.$route.name)
},
showDown() {
return this.repoStatus && this.isDesktop && ['login','index', 'manage-dashboard'].includes(this.$route.name)
return this.isDesktop && ['login', 'index', 'manage-dashboard'].includes(this.$route.name)
}
},
watch: {
wsOpenNum(num) {
if (num <= 1) return
this.wsOpenTimeout && clearTimeout(this.wsOpenTimeout)
this.wsOpenTimeout = setTimeout(this.getReleases, 5000)
},
},
methods: {
checkVersion() {
axios.get($A.apiUrl('../version')).then(({status, data}) => {
if (status === 200) {
this.apiVersion = data.version || ''
if (this.$Electron) {
//
this.$Electron.registerMsgListener('updateDownloaded', info => {
this.updateVersion = info.version;
this.updateNote = info.releaseNotes || this.$L('没有更新描述。');
this.updateShow = true;
})
this.$Electron.sendMessage('updateCheckAndDownload', {
apiVersion: this.apiVersion
})
} else {
//
this.getDownloadUrl(data)
}
}
}).catch(_ => {
});
},
getDownloadUrl(data) {
let key = "cacheAppdown::" + this.apiVersion
let cache = $A.getStorageJson(key);
let timeout = 600;
if (cache.time && cache.time + timeout > Math.round(new Date().getTime() / 1000)) {
this.downloadUrl = cache.data.html_url;
setTimeout(this.checkVersion, timeout * 1000)
return;
}
//
if (this.loadIng > 0) {
return;
}
this.loadIng++;
//
axios.get(`https://api.github.com/repos/${data.owner}/${data.repo}/releases`).then(({status, data}) => {
this.loadIng--;
if (status === 200 && $A.isArray(data)) {
cache.time = Math.round(new Date().getTime() / 1000)
cache.data = data.find(({tag_name}) => this.compareVersion(this.tagVersion(tag_name), this.apiVersion) === 0) || {}
$A.setStorage(key, cache);
this.downloadUrl = cache.data.html_url;
}
setTimeout(this.checkVersion, timeout * 1000)
}).catch(() => {
this.loadIng--;
setTimeout(this.checkVersion, timeout * 1000)
});
},
updateQuitAndInstall() {
this.$Electron.sendMessage('updateQuitAndInstall', null)
},
useSSOLogin() {
Store.set('useSSOLogin', true);
},
tagVersion(tag) {
return tag ? $A.leftDelete(tag.toLowerCase(), "v") : ''
},
compareVersion(version1, version2) {
let pA = 0, pB = 0;
//
if (version1 === version2) {
return 0
}
//
const findDigit = (str, start) => {
let i = start;
@ -126,6 +180,7 @@ export default {
pA = nextA + 1;
pB = nextB + 1;
}
// arrayA
while (pA < version1.length) {
const nextA = findDigit(version1, pA);
@ -135,6 +190,7 @@ export default {
}
pA = nextA + 1;
}
// arrayB
while (pB < version2.length) {
const nextB = findDigit(version2, pB);
@ -144,102 +200,10 @@ export default {
}
pB = nextB + 1;
}
//
return 0;
},
getReleases() {
if (this.repoStatus > 0) {
return;
}
if (this.loadIng > 0) {
return;
}
//
let cache = $A.getStorageJson("cacheAppdown");
let timeout = 600;
if (cache.time && cache.time + timeout > Math.round(new Date().getTime() / 1000)) {
this.repoReleases = cache.data;
this.chackReleases()
setTimeout(this.getReleases, timeout * 1000)
return;
}
//
this.loadIng++;
axios.get("https://api.github.com/repos/" + this.repoName + "/releases/latest").then(({status, data}) => {
this.loadIng--;
if (status === 200) {
cache = {
time: Math.round(new Date().getTime() / 1000),
data: data
}
$A.setStorage("cacheAppdown", cache);
this.repoReleases = cache.data;
this.chackReleases()
}
setTimeout(this.getReleases, timeout * 1000)
}).catch(() => {
this.loadIng--;
setTimeout(this.getReleases, timeout * 1000)
});
},
chackReleases() {
let hostName = $A.getDomain(window.systemInfo.homeUrl || window.systemInfo.apiUrl);
if (hostName == "" || $A.leftExists(hostName, '127.0.0.1')) {
hostName = "public"
}
if (this.$Electron) {
//
let match = (window.navigator.userAgent + "").match(/\s+(Main|Sub)TaskWindow\/(.*?)\/(.*?)\//)
if (!match) {
return;
}
let artifactName = null;
if (match[2] === 'darwin') {
artifactName = `${hostName}-${this.repoReleases.tag_name}-mac-${match[3]}.pkg`;
} else if (match[2] === 'win32') {
artifactName = `${hostName}-${this.repoReleases.tag_name}-win-${match[3]}.exe`;
} else {
return;
}
this.repoData = (this.repoReleases.assets || []).find(({name}) => name == artifactName);
if (!this.repoData) {
return;
}
let currentVersion = window.systemInfo.version;
let latestVersion = $A.leftDelete(this.repoReleases.tag_name.toLowerCase(), "v")
if (this.compareVersion(latestVersion, currentVersion) === 1) {
//
console.log("New version: " + latestVersion);
this.$Electron.sendMessage('downloadFile', {
url: this.repoData.browser_download_url
});
}
} else {
//
this.repoData = (this.repoReleases.assets || []).find(({name}) => $A.strExists(name, hostName));
if (this.repoData) {
let latestVersion = $A.leftDelete(this.repoReleases.tag_name.toLowerCase(), "v")
console.log("Exist client: " + latestVersion);
this.repoStatus = 1;
}
}
},
installApplication() {
if (!this.$Electron) {
return;
}
this.$Electron.sendMessage('openFile', {
path: this.downloadResult.savePath
});
this.$Electron.sendMessage('windowQuit');
},
useSSOLogin() {
Store.set('useSSOLogin', true);
}
}
};
</script>

View File

@ -729,7 +729,7 @@ export default {
this.workReportShow = true;
return;
case 'version':
Store.set('releasesNotification', null);
Store.set('updateNotification', null);
return;
case 'clearCache':
this.$store.dispatch("handleClearCache", null).then(() => {

View File

@ -91,7 +91,7 @@ export default {
methods: {
toggleRoute(path) {
if (path == 'version') {
Store.set('releasesNotification', null);
Store.set('updateNotification', null);
return;
}
this.show768Menu = false;

View File

@ -47,6 +47,13 @@
margin-bottom: 16px;
.markdown-preview {
margin: -20px -12px;
h1 {
font-size: 24px;
margin-bottom: 12px;
&:first-child {
padding-top: 0;
}
}
h2 {
font-size: 18px !important;
padding-top: 2px !important;

4
version.js vendored
View File

@ -2,7 +2,6 @@ const fs = require('fs');
const path = require("path");
const exec = require('child_process').exec;
const packageFile = path.resolve(process.cwd(), "package.json");
const packageElectronFile = path.resolve(process.cwd(), "electron/package.json");
function runExec(command, cb) {
exec(command, function (err, stdout, stderr) {
@ -31,8 +30,5 @@ runExec("git rev-list --count HEAD $(git branch | sed -n -e 's/^\* \(.*\)/\1/p')
let newResult = fs.readFileSync(packageFile, 'utf8').replace(/"version":\s*"(.*?)"/, `"version": "${ver}"`);
fs.writeFileSync(packageFile, newResult, 'utf8');
//
let newElectronResult = fs.readFileSync(packageElectronFile, 'utf8').replace(/"version":\s*"(.*?)"/, `"version": "${ver}"`);
fs.writeFileSync(packageElectronFile, newElectronResult, 'utf8');
//
console.log("new version: " + ver);
});