Compare commits

..

No commits in common. "master" and "v0.9.83" have entirely different histories.

55 changed files with 142 additions and 280 deletions

View File

@ -70,7 +70,11 @@ class WebSocketDialogMsg extends AbstractModel
public function getPercentageAttribute() public function getPercentageAttribute()
{ {
if (!isset($this->appendattrs['percentage'])) { if (!isset($this->appendattrs['percentage'])) {
$this->generatePercentage(); if ($this->read > $this->send || empty($this->send)) {
$this->appendattrs['percentage'] = 100;
} else {
$this->appendattrs['percentage'] = intval($this->read / $this->send * 100);
}
} }
return $this->appendattrs['percentage']; return $this->appendattrs['percentage'];
} }
@ -94,22 +98,6 @@ class WebSocketDialogMsg extends AbstractModel
return $value; return $value;
} }
/**
* 获取占比
* @param bool $increment 是否新增阅读数
* @return int
*/
public function generatePercentage($increment = false) {
if ($increment) {
$this->increment('read');
}
if ($this->read > $this->send || empty($this->send)) {
return $this->appendattrs['percentage'] = 100;
} else {
return $this->appendattrs['percentage'] = intval($this->read / $this->send * 100);
}
}
/** /**
* 标记已送达 同时 告诉发送人已送达 * 标记已送达 同时 告诉发送人已送达
* @param $userid * @param $userid
@ -139,17 +127,13 @@ class WebSocketDialogMsg extends AbstractModel
if (!$msgRead->read_at) { if (!$msgRead->read_at) {
$msgRead->read_at = Carbon::now(); $msgRead->read_at = Carbon::now();
$msgRead->save(); $msgRead->save();
$this->generatePercentage(true); $this->increment('read');
PushTask::push([ PushTask::push([
'userid' => $this->userid, 'userid' => $this->userid,
'msg' => [ 'msg' => [
'type' => 'dialog', 'type' => 'dialog',
'mode' => 'readed', 'mode' => 'update',
'data' => [ 'data' => $this->toArray(),
'id' => $this->id,
'read' => $this->read,
'percentage' => $this->percentage,
],
] ]
]); ]);
} }

View File

@ -342,15 +342,19 @@ class Base
{ {
if (strtolower($charset) == 'utf-8') { if (strtolower($charset) == 'utf-8') {
if (Base::getStrlen($string) <= $length) return $string; if (Base::getStrlen($string) <= $length) return $string;
$strcut = Base::utf8Substr($string, $length, $start); $strcut = str_replace(array('&amp;', '&quot;', '&lt;', '&gt;'), array('&', '"', '<', '>'), $string);
$strcut = Base::utf8Substr($strcut, $length, $start);
$strcut = str_replace(array('&', '"', '<', '>'), array('&amp;', '&quot;', '&lt;', '&gt;'), $strcut);
return $strcut . $dot; return $strcut . $dot;
} else { } else {
$length = $length * 2; $length = $length * 2;
if (strlen($string) <= $length) return $string; if (strlen($string) <= $length) return $string;
$string = str_replace(array('&amp;', '&quot;', '&lt;', '&gt;'), array('&', '"', '<', '>'), $string);
$strcut = ''; $strcut = '';
for ($i = 0; $i < $length; $i++) { for ($i = 0; $i < $length; $i++) {
$strcut .= ord($string[$i]) > 127 ? $string[$i] . $string[++$i] : $string[$i]; $strcut .= ord($string[$i]) > 127 ? $string[$i] . $string[++$i] : $string[$i];
} }
$strcut = str_replace(array('&', '"', '<', '>'), array('&amp;', '&quot;', '&lt;', '&gt;'), $strcut);
} }
return $strcut . $dot; return $strcut . $dot;
} }

View File

@ -127,11 +127,9 @@ class WebSocketService implements WebSocketHandlerInterface
case 'readMsg': case 'readMsg':
$ids = is_array($data['id']) ? $data['id'] : [$data['id']]; $ids = is_array($data['id']) ? $data['id'] : [$data['id']];
$userid = $this->getUserid($frame->fd); $userid = $this->getUserid($frame->fd);
WebSocketDialogMsg::whereIn('id', $ids)->chunkById(20, function($list) use ($userid) { $list = WebSocketDialogMsg::whereIn('id', $ids)->get();
/** @var WebSocketDialogMsg $item */ $list->transform(function(WebSocketDialogMsg $item) use ($userid) {
foreach ($list as $item) {
$item->readSuccess($userid); $item->readSuccess($userid);
}
}); });
return; return;

31
cmd
View File

@ -13,7 +13,6 @@ Error="${Red}[错误]${Font}"
cur_path="$(pwd)" cur_path="$(pwd)"
cur_arg=$@ cur_arg=$@
COMPOSE="docker-compose"
judge() { judge() {
if [[ 0 -eq $? ]]; then if [[ 0 -eq $? ]]; then
@ -57,23 +56,19 @@ check_docker() {
exit 1 exit 1
fi fi
docker-compose version &> /dev/null docker-compose version &> /dev/null
if [ $? -ne 0 ]; then
docker compose version &> /dev/null
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
echo -e "${Error} ${RedBG} 未安装 Docker-compose${Font}" echo -e "${Error} ${RedBG} 未安装 Docker-compose${Font}"
exit 1 exit 1
fi fi
COMPOSE="docker compose" if [[ -n `docker-compose version | grep "docker-compose" | grep -E "\sv*1"` ]]; then
fi docker-compose version
if [[ -n `$COMPOSE version | grep -E "\sv*1"` ]]; then
$COMPOSE version
echo -e "${Error} ${RedBG} Docker-compose 版本过低请升级至v2+${Font}" echo -e "${Error} ${RedBG} Docker-compose 版本过低请升级至v2+${Font}"
exit 1 exit 1
fi fi
} }
check_node() { check_node() {
npm --version &> /dev/null npm --version > /dev/null
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
echo -e "${Error} ${RedBG} 未安装nodejs${Font}" echo -e "${Error} ${RedBG} 未安装nodejs${Font}"
exit 1 exit 1
@ -81,7 +76,7 @@ check_node() {
} }
docker_name() { docker_name() {
echo `$COMPOSE ps | awk '{print $1}' | grep "\-$1\-"` echo `docker-compose ps | awk '{print $1}' | grep "\-$1\-"`
} }
run_compile() { run_compile() {
@ -277,7 +272,7 @@ if [ $# -gt 0 ]; then
chmod -R 775 "${cur_path}/docker/mysql/data" chmod -R 775 "${cur_path}/docker/mysql/data"
# 启动容器 # 启动容器
[[ "$(arg_get port)" -gt 0 ]] && env_set APP_PORT "$(arg_get port)" [[ "$(arg_get port)" -gt 0 ]] && env_set APP_PORT "$(arg_get port)"
$COMPOSE up php -d docker-compose up php -d
# 安装composer依赖 # 安装composer依赖
run_exec php "composer install" run_exec php "composer install"
if [ ! -f "${cur_path}/vendor/autoload.php" ]; then if [ ! -f "${cur_path}/vendor/autoload.php" ]; then
@ -305,7 +300,7 @@ if [ $# -gt 0 ]; then
run_exec php "php artisan migrate --seed" run_exec php "php artisan migrate --seed"
# 设置初始化密码 # 设置初始化密码
res=`run_exec mariadb "sh /etc/mysql/repassword.sh"` res=`run_exec mariadb "sh /etc/mysql/repassword.sh"`
$COMPOSE up -d docker-compose up -d
supervisorctl_restart php supervisorctl_restart php
echo -e "${OK} ${GreenBG} 安装完成 ${Font}" echo -e "${OK} ${GreenBG} 安装完成 ${Font}"
echo -e "地址: http://${GreenBG}127.0.0.1:$(env_get APP_PORT)${Font}" echo -e "地址: http://${GreenBG}127.0.0.1:$(env_get APP_PORT)${Font}"
@ -319,7 +314,7 @@ if [ $# -gt 0 ]; then
run_exec php "composer update" run_exec php "composer update"
run_exec php "php artisan migrate" run_exec php "php artisan migrate"
supervisorctl_restart php supervisorctl_restart php
$COMPOSE up -d docker-compose up -d
elif [[ "$1" == "uninstall" ]]; then elif [[ "$1" == "uninstall" ]]; then
shift 1 shift 1
read -rp "确定要卸载(含:删除容器、数据库、日志)吗?(y/n): " uninstall read -rp "确定要卸载(含:删除容器、数据库、日志)吗?(y/n): " uninstall
@ -333,7 +328,7 @@ if [ $# -gt 0 ]; then
exit 2 exit 2
;; ;;
esac esac
$COMPOSE down docker-compose down
rm -rf "./docker/mysql/data" rm -rf "./docker/mysql/data"
rm -rf "./docker/log/supervisor" rm -rf "./docker/log/supervisor"
find "./storage/logs" -name "*.log" | xargs rm -rf find "./storage/logs" -name "*.log" | xargs rm -rf
@ -346,7 +341,7 @@ if [ $# -gt 0 ]; then
elif [[ "$1" == "port" ]]; then elif [[ "$1" == "port" ]]; then
shift 1 shift 1
env_set APP_PORT "$1" env_set APP_PORT "$1"
$COMPOSE up -d docker-compose up -d
echo -e "${OK} ${GreenBG} 修改成功 ${Font}" echo -e "${OK} ${GreenBG} 修改成功 ${Font}"
echo -e "地址: http://${GreenBG}127.0.0.1:$(env_get APP_PORT)${Font}" echo -e "地址: http://${GreenBG}127.0.0.1:$(env_get APP_PORT)${Font}"
elif [[ "$1" == "repassword" ]]; then elif [[ "$1" == "repassword" ]]; then
@ -419,11 +414,11 @@ if [ $# -gt 0 ]; then
e="./vendor/bin/phpunit $@" && run_exec php "$e" e="./vendor/bin/phpunit $@" && run_exec php "$e"
elif [[ "$1" == "restart" ]]; then elif [[ "$1" == "restart" ]]; then
shift 1 shift 1
$COMPOSE stop "$@" docker-compose stop "$@"
$COMPOSE start "$@" docker-compose start "$@"
else else
$COMPOSE "$@" docker-compose "$@"
fi fi
else else
$COMPOSE ps docker-compose ps
fi fi

View File

@ -1,6 +1,6 @@
{ {
"name": "DooTask", "name": "DooTask",
"version": "0.10.5", "version": "0.9.83",
"description": "DooTask is task management system.", "description": "DooTask is task management system.",
"main": "electron.js", "main": "electron.js",
"license": "MIT", "license": "MIT",

View File

@ -1,6 +1,6 @@
{ {
"name": "DooTask", "name": "DooTask",
"version": "0.10.5", "version": "0.9.83",
"description": "DooTask is task management system.", "description": "DooTask is task management system.",
"scripts": { "scripts": {
"start": "./cmd dev", "start": "./cmd dev",

2
public/css/app.css vendored

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

File diff suppressed because one or more lines are too long

View File

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

File diff suppressed because one or more lines are too long

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

2
public/js/build/510.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

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

File diff suppressed because one or more lines are too long

View File

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

1
public/js/build/540.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

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 +1 @@
/*! @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 */ /*! @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 */

File diff suppressed because one or more lines are too long

View File

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

2
public/js/build/956.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

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

View File

@ -21,7 +21,6 @@ export default {
}, },
mounted() { mounted() {
tocObj.reset()
this.init(); this.init();
this.createEditor(); this.createEditor();
}, },

View File

@ -1,20 +1,8 @@
<template> <template>
<div class="quick-edit" :class="[alwaysIcon ? 'quick-always' : '']"> <div class="quick-edit" :class="[alwaysIcon ? 'quick-always' : '']">
<div v-if="isEdit" v-clickoutside="onClickOut" class="quick-input"> <div v-if="isEdit" v-clickoutside="onClickOut" class="quick-input">
<TagInput <TagInput v-if="isTag" ref="input" v-model="content" :disabled="isLoad" @on-enter="onEnter" @on-blur="onBlur"/>
v-if="isTag" <Input v-else ref="input" v-model="content" :disabled="isLoad" @on-enter="onEnter" @on-blur="onBlur"/>
ref="input"
v-model="content"
:disabled="isLoad"
@on-keyup="onKeyup"
@on-blur="onBlur"/>
<Input
v-else
ref="input"
v-model="content"
:disabled="isLoad"
@on-keyup="onKeyup"
@on-blur="onBlur"/>
<div v-if="isLoad" class="quick-loading"><Loading/></div> <div v-if="isLoad" class="quick-loading"><Loading/></div>
</div> </div>
<template v-else> <template v-else>
@ -66,6 +54,9 @@ export default {
}, },
watch: { watch: {
isEdit(val) {
this.$emit("on-edit-change", val);
},
autoEdit(val) { autoEdit(val) {
if (val === true) { if (val === true) {
setTimeout(this.onEdit, 0) setTimeout(this.onEdit, 0)
@ -74,14 +65,9 @@ export default {
}, },
methods: { methods: {
onEditChange(val) {
this.isEdit = val;
this.$emit("on-edit-change", val);
},
onEdit() { onEdit() {
this.content = this.value; this.content = this.value;
this.onEditChange(true); this.isEdit = true;
this.$nextTick(() => { this.$nextTick(() => {
this.$refs.input.focus({ this.$refs.input.focus({
cursor: 'all' cursor: 'all'
@ -89,18 +75,9 @@ export default {
}) })
}, },
onKeyup(e) {
if (e.keyCode === 13) {
this.onEnter();
} else if (e.keyCode === 27) {
this.isEdit = false;
this.isLoad = false;
}
},
onEnter() { onEnter() {
if (this.content == this.value) { if (this.content == this.value) {
this.onEditChange(false); this.isEdit = false;
return; return;
} }
if (this.isLoad) { if (this.isLoad) {
@ -109,7 +86,7 @@ export default {
this.isLoad = true; this.isLoad = true;
this.$emit("input", this.content); this.$emit("input", this.content);
this.$emit("on-update", this.content, () => { this.$emit("on-update", this.content, () => {
this.onEditChange(false); this.isEdit = false;
this.isLoad = false; this.isLoad = false;
}) })
}, },
@ -122,7 +99,7 @@ export default {
}, },
onBlur() { onBlur() {
if (this.clickOutSide || !this.isEdit) { if (this.clickOutSide) {
return; return;
} }
this.onEnter(); this.onEnter();

View File

@ -2,7 +2,7 @@
<div class="teditor-wrapper"> <div class="teditor-wrapper">
<div class="teditor-box" :class="[!inline && spinShow ? 'teditor-loadstyle' : 'teditor-loadedstyle']"> <div class="teditor-box" :class="[!inline && spinShow ? 'teditor-loadstyle' : 'teditor-loadedstyle']">
<template v-if="inline"> <template v-if="inline">
<div ref="myTextarea" :id="id" v-html="spinShow ? '' : content"></div> <div ref="myTextarea" :id="id" v-html="content"></div>
<Icon v-if="spinShow" type="ios-loading" :size="18" class="icon-loading icon-inline"></Icon> <Icon v-if="spinShow" type="ios-loading" :size="18" class="icon-loading icon-inline"></Icon>
</template> </template>
<template v-else> <template v-else>
@ -181,7 +181,11 @@
newValue = ""; newValue = "";
} }
if (!this.isTyping) { if (!this.isTyping) {
this.setContent(newValue); if (this.getEditor() !== null) {
this.getEditor().setContent(newValue);
} else{
this.content = newValue;
}
} }
}, },
readOnly(value) { readOnly(value) {
@ -455,14 +459,6 @@
return this.getEditor().getContent(); return this.getEditor().getContent();
}, },
setContent(content) {
if (this.getEditor() === null) {
this.content = content;
} else if (content != this.getEditor().getContent()){
this.getEditor().setContent(content);
}
},
insertImage(src) { insertImage(src) {
this.insertContent('<img src="' + src + '">'); this.insertContent('<img src="' + src + '">');
}, },

View File

@ -11,7 +11,7 @@
:placeholder="tis || placeholderText" :placeholder="tis || placeholderText"
@keydown.enter="downEnter($event)" @keydown.enter="downEnter($event)"
@keydown.delete="delTag(false)" @keydown.delete="delTag(false)"
@keyup="onKeyup" @keyup="addTag($event, content)"
@focus="onFocus" @focus="onFocus"
@blur="onBlur" @blur="onBlur"
:disabled="disabled" :disabled="disabled"
@ -158,22 +158,19 @@
this.addTag(false, this.content) this.addTag(false, this.content)
this.$emit("on-blur", e) this.$emit("on-blur", e)
}, },
onKeyup(e) {
this.addTag(e, this.content);
//
this.$emit("on-keyup", e)
if (e.keyCode === 13) {
this.$nextTick(() => {
this.$emit("on-enter", e)
})
}
},
addTag(e, content) { addTag(e, content) {
if (e === false || e.keyCode === 13) { if (e === false || e.keyCode === 13) {
if (content.trim() != '' && this.disSource.indexOf(content.trim()) === -1) { if (content.trim() != '' && this.disSource.indexOf(content.trim()) === -1) {
this.disSource.push(content.trim()); this.disSource.push(content.trim());
} }
this.content = ''; this.content = '';
//
if (e.keyCode === 13) {
this.$nextTick(() => {
this.$emit("on-enter", e)
})
}
return; return;
} }
if (this.max > 0 && this.disSource.length >= this.max) { if (this.max > 0 && this.disSource.length >= this.max) {

View File

@ -102,7 +102,7 @@
* @returns {*|string} * @returns {*|string}
*/ */
formatTime(date) { formatTime(date) {
let time = $A.Date(date, true), let time = Math.round($A.Date(date).getTime() / 1000),
string = ''; string = '';
if ($A.formatDate('Ymd') === $A.formatDate('Ymd', time)) { if ($A.formatDate('Ymd') === $A.formatDate('Ymd', time)) {
string = $A.formatDate('H:i', time) string = $A.formatDate('H:i', time)
@ -157,10 +157,8 @@
let time = Math.round(this.Date(date).getTime() / 1000) - nowTime; let time = Math.round(this.Date(date).getTime() / 1000) - nowTime;
if (time < 86400 * 7 && time > 0 ) { if (time < 86400 * 7 && time > 0 ) {
return this.formatSeconds(time); return this.formatSeconds(time);
} else if (time < 0) { } else if (time <= 0) {
return '-' + this.formatSeconds(time * -1); return '-' + this.formatSeconds(time * -1);
} else if (time == 0) {
return 0 + 's';
} }
return this.formatTime(date) return this.formatTime(date)
}, },

View File

@ -37,7 +37,7 @@
<i class="taskfont">&#xe689;</i> <i class="taskfont">&#xe689;</i>
</div> </div>
<Dropdown-menu slot="list" class="login-setting-menu"> <Dropdown-menu slot="list" class="login-setting-menu">
<Dropdown placement="right" @on-click="setTheme"> <Dropdown placement="right-start" @on-click="setTheme">
<DropdownItem> <DropdownItem>
<div class="login-setting-item"> <div class="login-setting-item">
{{$L('主题皮肤')}} {{$L('主题皮肤')}}
@ -48,7 +48,7 @@
<Dropdown-item v-for="(item, key) in themeList" :key="key" :name="item.value" :selected="themeMode === item.value">{{$L(item.name)}}</Dropdown-item> <Dropdown-item v-for="(item, key) in themeList" :key="key" :name="item.value" :selected="themeMode === item.value">{{$L(item.name)}}</Dropdown-item>
</DropdownMenu> </DropdownMenu>
</Dropdown> </Dropdown>
<Dropdown placement="right" @on-click="setLanguage"> <Dropdown placement="right-start" @on-click="setLanguage">
<DropdownItem divided> <DropdownItem divided>
<div class="login-setting-item"> <div class="login-setting-item">
{{currentLanguage}} {{currentLanguage}}
@ -114,9 +114,6 @@ export default {
this.subscribe = null; this.subscribe = null;
} }
}, },
activated() {
this.loginType = 'login'
},
deactivated() { deactivated() {
this.loginJump = false; this.loginJump = false;
this.password = ""; this.password = "";

View File

@ -103,9 +103,7 @@
<li @click="toggleRoute('dashboard')" :class="classNameRoute('dashboard')"> <li @click="toggleRoute('dashboard')" :class="classNameRoute('dashboard')">
<i class="taskfont">&#xe6fb;</i> <i class="taskfont">&#xe6fb;</i>
<div class="menu-title">{{$L('仪表盘')}}</div> <div class="menu-title">{{$L('仪表盘')}}</div>
<Badge v-if="dashboardTask.overdue.length > 0" class="menu-badge" type="error" :count="dashboardTask.overdue.length"/> <Badge class="menu-badge" :type="dashboardTask.overdue.length > 0 ? 'error' : 'primary'" :count="dashboardTotal"></Badge>
<Badge v-else-if="dashboardTask.today.length > 0" class="menu-badge" type="info" :count="dashboardTask.today.length"/>
<Badge v-else-if="dashboardTask.all.length > 0" class="menu-badge" type="primary" :count="dashboardTask.all.length"/>
</li> </li>
<li @click="toggleRoute('calendar')" :class="classNameRoute('calendar')"> <li @click="toggleRoute('calendar')" :class="classNameRoute('calendar')">
<i class="taskfont">&#xe6f5;</i> <i class="taskfont">&#xe6f5;</i>
@ -114,7 +112,7 @@
<li @click="toggleRoute('messenger')" :class="classNameRoute('messenger')"> <li @click="toggleRoute('messenger')" :class="classNameRoute('messenger')">
<i class="taskfont">&#xe6eb;</i> <i class="taskfont">&#xe6eb;</i>
<div class="menu-title">{{$L('消息')}}</div> <div class="menu-title">{{$L('消息')}}</div>
<Badge class="menu-badge" :count="msgAllUnread"/> <Badge class="menu-badge" :count="msgAllUnread"></Badge>
</li> </li>
<li @click="toggleRoute('file')" :class="classNameRoute('file')"> <li @click="toggleRoute('file')" :class="classNameRoute('file')">
<i class="taskfont">&#xe6f3;</i> <i class="taskfont">&#xe6f3;</i>
@ -258,15 +256,15 @@
<!--任务详情--> <!--任务详情-->
<Modal <Modal
:value="taskId > 0" :value="taskId > 0"
:mask-closable="false"
:styles="{ :styles="{
width: '90%', width: '90%',
maxWidth: taskData.dialog_id ? '1200px' : '700px' maxWidth: taskData.dialog_id ? '1200px' : '700px'
}" }"
:mask-closable="false" @on-visible-change="taskVisibleChange"
:footer-hide="true" footer-hide>
@on-visible-change="taskVisibleChange">
<div class="page-manage-task-modal" :style="taskStyle"> <div class="page-manage-task-modal" :style="taskStyle">
<TaskDetail ref="taskDetail" :task-id="taskId" :open-task="taskData"/> <TaskDetail :task-id="taskId" :open-task="taskData"/>
</div> </div>
</Modal> </Modal>
@ -465,8 +463,12 @@ export default {
return num; return num;
}, },
dashboardTotal() {
return this.dashboardTask.today.length + this.dashboardTask.overdue.length
},
unreadTotal() { unreadTotal() {
return this.msgAllUnread + this.dashboardTask.overdue.length + this.reportUnreadNumber; return this.msgAllUnread + this.dashboardTotal + this.reportUnreadNumber;
}, },
currentLanguage() { currentLanguage() {
@ -785,13 +787,10 @@ export default {
}, },
shortcutEvent(e) { shortcutEvent(e) {
if (e.metaKey || e.ctrlKey) {
if (e.keyCode === 75 || e.keyCode === 78) { if (e.keyCode === 75 || e.keyCode === 78) {
if (e.metaKey || e.ctrlKey) {
e.preventDefault(); e.preventDefault();
this.onAddTask(0) this.onAddTask(0)
} else if (e.keyCode === 83 && this.taskId > 0) {
e.preventDefault();
this.$refs.taskDetail.checkUpdate(true)
} }
} }
}, },

View File

@ -46,7 +46,6 @@
<div class="time" :title="msgData.created_at">{{$A.formatTime(msgData.created_at)}}</div> <div class="time" :title="msgData.created_at">{{$A.formatTime(msgData.created_at)}}</div>
<Poptip <Poptip
v-if="msgData.send > 1 || dialogType == 'group'" v-if="msgData.send > 1 || dialogType == 'group'"
ref="percent"
class="percent" class="percent"
placement="left-end" placement="left-end"
transfer transfer
@ -135,13 +134,13 @@ export default {
} }
this.msgData._r = true; this.msgData._r = true;
// //
setTimeout(() => { this.$nextTick(() => {
if (!this.$el.offsetParent) { if (!this.$el.offsetParent) {
this.msgData._r = false; this.msgData._r = false;
return return
} }
this.$store.dispatch("dialogMsgRead", this.msgData); this.$store.dispatch("dialogMsgRead", this.msgData);
}, 50) })
}, },
popperShow() { popperShow() {
@ -152,7 +151,6 @@ export default {
}, },
}).then(({data}) => { }).then(({data}) => {
this.read_list = data; this.read_list = data;
this.$refs.percent.updatePopper();
}).catch(() => { }).catch(() => {
this.read_list = []; this.read_list = [];
}); });

View File

@ -238,7 +238,7 @@ export default {
const {times} = this.addData; const {times} = this.addData;
let temp = $A.date2string(times, "Y-m-d H:i"); let temp = $A.date2string(times, "Y-m-d H:i");
if (temp[0] && temp[1]) { if (temp[0] && temp[1]) {
let d = Math.ceil(($A.Date(temp[1], true) - $A.Date(temp[0], true)) / 86400); let d = Math.ceil(($A.Date(temp[1]).getTime() - $A.Date(temp[0]).getTime()) / 86400000);
if (d > 0) { if (d > 0) {
return d; return d;
} }

View File

@ -3,7 +3,6 @@
<li v-if="ready && taskDetail.parent_id > 0"> <li v-if="ready && taskDetail.parent_id > 0">
<div class="subtask-icon"> <div class="subtask-icon">
<TaskMenu <TaskMenu
v-if="taskId > 0"
:ref="`taskMenu_${taskDetail.id}`" :ref="`taskMenu_${taskDetail.id}`"
:task="taskDetail" :task="taskDetail"
:load-status="taskDetail.loading === true" :load-status="taskDetail.loading === true"
@ -73,7 +72,6 @@
<div v-show="taskDetail.id > 0" class="task-info"> <div v-show="taskDetail.id > 0" class="task-info">
<div class="head"> <div class="head">
<TaskMenu <TaskMenu
v-if="taskId > 0"
:ref="`taskMenu_${taskDetail.id}`" :ref="`taskMenu_${taskDetail.id}`"
:task="taskDetail" :task="taskDetail"
class="icon" class="icon"
@ -123,7 +121,6 @@
</ETooltip> </ETooltip>
<div class="menu"> <div class="menu">
<TaskMenu <TaskMenu
v-if="taskId > 0"
:task="taskDetail" :task="taskDetail"
icon="ios-more" icon="ios-more"
completed-icon="ios-more" completed-icon="ios-more"
@ -153,6 +150,7 @@
:option-full="taskOptionFull" :option-full="taskOptionFull"
:placeholder="$L('详细描述...')" :placeholder="$L('详细描述...')"
@on-blur="updateData('content')" @on-blur="updateData('content')"
@editorSave="updateData('content')"
inline/> inline/>
</div> </div>
<Form class="items" label-position="left" label-width="auto" @submit.native.prevent> <Form class="items" label-position="left" label-width="auto" @submit.native.prevent>
@ -263,7 +261,7 @@
<div @click="openTime" class="time">{{taskDetail.end_at ? cutTime : '--'}}</div> <div @click="openTime" class="time">{{taskDetail.end_at ? cutTime : '--'}}</div>
<template v-if="!taskDetail.complete_at && taskDetail.end_at"> <template v-if="!taskDetail.complete_at && taskDetail.end_at">
<Tag v-if="within24Hours(taskDetail.end_at)" color="blue"><i class="taskfont">&#xe71d;</i>{{expiresFormat(taskDetail.end_at)}}</Tag> <Tag v-if="within24Hours(taskDetail.end_at)" color="blue"><i class="taskfont">&#xe71d;</i>{{expiresFormat(taskDetail.end_at)}}</Tag>
<Tag v-if="isOverdue(taskDetail)" color="red">{{$L('超期未完成')}}</Tag> <Tag v-if="taskDetail.overdue" color="red">{{$L('超期未完成')}}</Tag>
</template> </template>
</div> </div>
</DatePicker> </DatePicker>
@ -309,13 +307,7 @@
<i class="taskfont">&#xe6f0;</i>{{$L('子任务')}} <i class="taskfont">&#xe6f0;</i>{{$L('子任务')}}
</div> </div>
<ul class="item-content subtask"> <ul class="item-content subtask">
<TaskDetail <TaskDetail v-for="(task, key) in subList" :key="key" :task-id="task.id" :open-task="task" :main-end-at="taskDetail.end_at"/>
v-for="(task, key) in subList"
:ref="`subTask_${task.id}`"
:key="key"
:task-id="task.id"
:open-task="task"
:main-end-at="taskDetail.end_at"/>
</ul> </ul>
<ul :class="['item-content', subList.length === 0 ? 'nosub' : '']"> <ul :class="['item-content', subList.length === 0 ? 'nosub' : '']">
<li> <li>
@ -624,8 +616,8 @@ export default {
cutTime() { cutTime() {
const {taskDetail} = this; const {taskDetail} = this;
let start_at = $A.Date(taskDetail.start_at, true); let start_at = Math.round($A.Date(taskDetail.start_at).getTime() / 1000);
let end_at = $A.Date(taskDetail.end_at, true); let end_at = Math.round($A.Date(taskDetail.end_at).getTime() / 1000);
let string = ""; let string = "";
if ($A.formatDate('Y/m/d', start_at) == $A.formatDate('Y/m/d', end_at)) { if ($A.formatDate('Y/m/d', start_at) == $A.formatDate('Y/m/d', end_at)) {
string = $A.formatDate('Y/m/d H:i', start_at) + " ~ " + $A.formatDate('H:i', end_at) string = $A.formatDate('Y/m/d H:i', start_at) + " ~ " + $A.formatDate('H:i', end_at)
@ -733,27 +725,29 @@ export default {
}, },
methods: { methods: {
initLanguage() {
},
innerHeightListener() { innerHeightListener() {
this.innerHeight = Math.min(1100, window.innerHeight); this.innerHeight = Math.min(1100, window.innerHeight);
}, },
within24Hours(date) { within24Hours(date) {
return $A.Date(date, true) - this.nowTime < 86400 return Math.round($A.Date(date).getTime() / 1000) - this.nowTime < 86400
}, },
expiresFormat(date) { expiresFormat(date) {
return $A.countDownFormat(date, this.nowTime) return $A.countDownFormat(date, this.nowTime)
}, },
isOverdue(taskDetail) {
if (taskDetail.overdue) {
return true;
}
return $A.Date(taskDetail.end_at, true) < this.nowTime;
},
onNameKeydown(e) { onNameKeydown(e) {
if (e.keyCode === 13) { if (e.keyCode === 83) {
if (e.metaKey || e.ctrlKey) {
e.preventDefault();
this.updateData('name');
}
} else if (e.keyCode === 13) {
if (!e.shiftKey) { if (!e.shiftKey) {
e.preventDefault(); e.preventDefault();
this.updateData('name'); this.updateData('name');
@ -761,40 +755,6 @@ export default {
} }
}, },
checkUpdate(update) {
let isModify = false;
if (this.openTask.name != this.taskDetail.name) {
isModify = true;
if (update) {
this.updateData('name');
} else if (isModify) {
return true
}
}
if (this.$refs.desc && this.$refs.desc.getContent() != this.taskContent) {
isModify = true;
if (update) {
this.updateData('content');
} else if (isModify) {
return true
}
}
if (this.addsubShow && this.addsubName) {
isModify = true;
if (update) {
this.onAddsub();
} else if (isModify) {
return true
}
}
this.subList.some(({id}) => {
if (this.$refs[`subTask_${id}`][0].checkUpdate(update)) {
isModify = true;
}
})
return isModify;
},
updateData(action, params) { updateData(action, params) {
switch (action) { switch (action) {
case 'priority': case 'priority':

View File

@ -15,7 +15,7 @@
</template> </template>
</div> </div>
</slot> </slot>
<EDropdownMenu ref="dropdownMenu" slot="dropdown" class="task-menu-more-dropdown"> <EDropdownMenu slot="dropdown" class="task-menu-more-dropdown">
<li class="task-menu-more-warp" :class="size"> <li class="task-menu-more-warp" :class="size">
<ul> <ul>
<EDropdownItem v-if="!flow" class="load-flow" disabled> <EDropdownItem v-if="!flow" class="load-flow" disabled>
@ -218,9 +218,7 @@ export default {
visibleChange(visible) { visibleChange(visible) {
if (visible) { if (visible) {
this.$store.dispatch("getTaskFlow", this.task.id) this.$store.dispatch("getTaskFlow", this.task.id).catch(() => {})
.then(this.$refs.dropdownMenu.updatePopper)
.catch(this.$refs.dropdownMenu.updatePopper)
} }
}, },

View File

@ -266,7 +266,7 @@ export default {
}, },
completeAtFormat(date) { completeAtFormat(date) {
let time = $A.Date(date, true); let time = Math.round($A.Date(date).getTime() / 1000);
if ($A.formatDate('Y') === $A.formatDate('Y', time)) { if ($A.formatDate('Y') === $A.formatDate('Y', time)) {
return $A.formatDate('m-d H:i', time) return $A.formatDate('m-d H:i', time)
} else { } else {

View File

@ -121,7 +121,7 @@
size="small" size="small"
:disabled="!!item._load" :disabled="!!item._load"
@on-blur="onBlur(item)" @on-blur="onBlur(item)"
@on-keyup="onKeyup($event, item)"/> @on-enter="onEnter(item)"/>
<div v-if="item._load" class="file-load"><Loading/></div> <div v-if="item._load" class="file-load"><Loading/></div>
</div> </div>
<div v-else class="file-name" :title="item.name">{{formatName(item)}}</div> <div v-else class="file-name" :title="item.name">{{formatName(item)}}</div>
@ -959,6 +959,7 @@ export default {
break; break;
case 'rename': case 'rename':
this.$set(item, 'newname', item.name);
this.setEdit(item.id, true) this.setEdit(item.id, true)
this.autoBlur(item.id) this.autoBlur(item.id)
break; break;
@ -1153,21 +1154,9 @@ export default {
}, },
onBlur(item) { onBlur(item) {
if (this.files.find(({id, _edit}) => id == item.id && !_edit)) {
return;
}
this.onEnter(item); this.onEnter(item);
}, },
onKeyup(e, item) {
if (e.keyCode === 13) {
this.onEnter(item);
} else if (e.keyCode === 27) {
this.setLoad(item.id, false)
this.setEdit(item.id, false)
}
},
onEnter(item) { onEnter(item) {
let isCreate = !/^\d+$/.test(item.id); let isCreate = !/^\d+$/.test(item.id);
if (!item.newname) { if (!item.newname) {
@ -1215,9 +1204,6 @@ export default {
let item = this.$store.state.files.find(({id}) => id == fileId) let item = this.$store.state.files.find(({id}) => id == fileId)
if (item) { if (item) {
this.$set(item, '_edit', is); this.$set(item, '_edit', is);
if (is) {
this.$set(item, 'newname', item.name);
}
} }
}, },

View File

@ -74,12 +74,8 @@ export default {
} }
} }
}; };
params.error = (xhr, status) => { params.error = () => {
if (window.navigator.onLine === false || (status === 0 && xhr.readyState === 4)) {
reject({data: {}, msg: $A.L('网络异常,请稍后再试!')})
} else {
reject({data: {}, msg: "System error"}) reject({data: {}, msg: "System error"})
}
}; };
// //
if (params.websocket === true || params.ws === true) { if (params.websocket === true || params.ws === true) {
@ -2050,7 +2046,7 @@ export default {
} }
}); });
state.wsReadWaitList = []; state.wsReadWaitList = [];
}, 50); }, 20);
}, },
/** /**
@ -2178,12 +2174,6 @@ export default {
// 更新最后消息 // 更新最后消息
dispatch("updateDialogLastMsg", data); dispatch("updateDialogLastMsg", data);
break; break;
case 'readed':
// 已读回执
if (state.dialogMsgs.find(({id}) => id == data.id)) {
dispatch("saveDialogMsg", data)
}
break;
} }
})(msgDetail); })(msgDetail);
break; break;

View File

@ -77,13 +77,6 @@
img { img {
max-width: 100%; max-width: 100%;
} }
pre {
padding: 14px;
margin: 7px 0;
overflow: auto;
background: #f5f2f0;
border-radius: 5px;
}
&[data-mce-placeholder]:not(.mce-visualblocks)::before { &[data-mce-placeholder]:not(.mce-visualblocks)::before {
color: #bbbbbb; color: #bbbbbb;
} }

View File

@ -163,13 +163,6 @@
img { img {
max-width: 100%; max-width: 100%;
} }
pre {
padding: 14px;
margin: 7px 0;
overflow: auto;
background: #f5f2f0;
border-radius: 5px;
}
&[data-mce-placeholder]:not(.mce-visualblocks)::before { &[data-mce-placeholder]:not(.mce-visualblocks)::before {
color: #bbbbbb; color: #bbbbbb;
} }

View File

@ -108,8 +108,8 @@
padding: 8px; padding: 8px;
.load-flow-warp { .load-flow-warp {
width: 18px; width: 20px;
height: 18px; height: 20px;
} }
} }
} }

View File

@ -51,6 +51,8 @@
&:last-child { &:last-child {
background-color: #98de6e; background-color: #98de6e;
margin-right: 0; margin-right: 0;
cursor: default;
box-shadow: none;
} }
.block-title { .block-title {
color: rgba(255, 255, 255, 0.6); color: rgba(255, 255, 255, 0.6);

View File

@ -485,7 +485,7 @@
.file-upload-list { .file-upload-list {
display: flex; display: flex;
width: 380px; width: 380px;
padding: 14px 26px 14px 26px; padding: 14px 26px 14px 13px;
border-radius: 8px; border-radius: 8px;
border: 1px solid #ebeef5; border: 1px solid #ebeef5;
position: fixed; position: fixed;
@ -497,7 +497,8 @@
overflow: hidden; overflow: hidden;
.upload-wrap { .upload-wrap {
flex: 1; flex: 1;
width: 100%; margin-left: 13px;
margin-right: 8px;
.title { .title {
font-weight: 700; font-weight: 700;
font-size: 16px; font-size: 16px;
@ -515,18 +516,16 @@
.content { .content {
font-size: 14px; font-size: 14px;
line-height: 21px; line-height: 21px;
margin: 12px 0 0; margin: 12px -16px 0 0;
color: #606266; color: #606266;
max-height: 500px; max-height: 500px;
max-width: 100%;
overflow: auto; overflow: auto;
> li { > li {
list-style: none; list-style: none;
padding: 4px 0; padding: 4px 16px 4px 0;
position: relative; position: relative;
.file-name { .file-name {
line-height: 18px; line-height: 18px;
padding-right: 16px;
} }
.file-error { .file-error {
font-size: 12px; font-size: 12px;
@ -534,9 +533,8 @@
} }
.file-close { .file-close {
position: absolute; position: absolute;
font-size: 14px;
top: 7px; top: 7px;
right: -1px; right: 0;
display: none; display: none;
cursor: pointer; cursor: pointer;
} }