Merge branch 'pro' of github.com:hitosea/dootask into pro

This commit is contained in:
spylecym 2023-07-19 10:47:03 +08:00
commit aebcca76e4
18 changed files with 710 additions and 452 deletions

View File

@ -1051,6 +1051,7 @@ class ProjectController extends AbstractController
* @apiGroup project
* @apiName task__easylists
* @apiParam {String} [taskid] 排除的任务ID
* @apiParam {String} [userid] 用户ID1,2
* @apiParam {String} [timerange] 时间范围2022-03-01 12:12:12,2022-05-01 12:12:12
*
@ -1062,24 +1063,31 @@ class ProjectController extends AbstractController
{
User::auth();
//
$userid = trim(Request::input('userid'));
$taskid = trim(Request::input('taskid'));
$userid = Request::input('userid');
$timerange = Request::input('timerange');
//
$list = ProjectTask::query()
->select('project_tasks.id', 'project_tasks.name', 'project_tasks.created_at', 'project_tasks.updated_at')
$list = ProjectTask::with(['taskUser'])
->select('projects.name as project_name', 'project_tasks.id', 'project_tasks.name', 'project_tasks.start_at', 'project_tasks.end_at')
->join('projects','project_tasks.project_id','=','projects.id')
->leftJoin('project_task_users', function ($query) {
$query->on('project_tasks.id', '=', 'project_task_users.task_id');
$query->on('project_tasks.id', '=', 'project_task_users.task_id')->where('project_task_users.owner', '=', 1);
})
->whereIn('project_task_users.userid', explode(',', $userid))
->whereIn('project_task_users.userid', is_array($userid) ? $userid : explode(',', $userid) )
->when(!empty($timerange), function ($query) use ($timerange) {
if (!is_array($timerange)) {
$timerange = explode(',', $timerange);
}
if (Base::isDateOrTime($timerange[0]) && Base::isDateOrTime($timerange[1])) {
$query->whereBetween('project_tasks.created_at', [Carbon::parse($timerange[0])->startOfDay(), Carbon::parse($timerange[1])->endOfDay()]);
$query->where('project_tasks.start_at', '>=', Carbon::parse($timerange[0])->startOfDay());
$query->where('project_tasks.end_at', '<=', Carbon::parse($timerange[1])->endOfDay());
}
})
->when(!empty($taskid), function ($query) use ($taskid) {
$query->where('project_tasks.id', "!=", $taskid);
})
->whereNull('complete_at')
->distinct()
->orderByDesc('project_tasks.id')
->paginate(Base::getPaginate(200, 100));
//

View File

@ -1249,3 +1249,6 @@ Markdown 格式发送
继续
退出
会议组件加载失败!
以下人员已存在任务
确定

View File

@ -16883,5 +16883,16 @@
"de": "Geladen mit fallender fracht des meetings!",
"fr": "Échec du chargement du composant conférence!",
"id": "Perakitan perakitan gagal!"
},
{
"key": "以下人员已存在任务",
"zh": "",
"zh-CHT": "以下人員已存在任務",
"en": "The following personnel already have tasks",
"ko": "다음 구성원에 대한 작업이 이미 있습니다",
"ja": "次の者には任務があります",
"de": "Die folgenden personen haben den auftrag erledigt",
"fr": "Les personnes suivantes ont déjà une mission",
"id": "Yang berikut ini ada tugas"
}
]

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

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 @@
if(typeof window.LANGUAGE_DATA==="undefined")window.LANGUAGE_DATA={};window.LANGUAGE_DATA["zh"]=["","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","",""]
if(typeof window.LANGUAGE_DATA==="undefined")window.LANGUAGE_DATA={};window.LANGUAGE_DATA["zh"]=["","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","",""]

View File

@ -1,8 +1,15 @@
<template>
<div class="common-tag-input" :class="{focus:isFocus}" @paste="pasteText($event)" @click="focus">
<div class="tags-item" v-for="(text, index) in disSource">
<span class="tags-content" @click.stop="">{{text}}</span><span class="tags-del" @click.stop="delTag(index)">&times;</span>
<Draggable
:list="disSource"
:animation="150"
tag="ul"
draggable=".column-item"
>
<div class="tags-item column-item" v-for="(text, index) in disSource">
<span class="tags-content" @click.stop="edit(disSource,index)">{{text}}</span><span class="tags-del" @click.stop="delTag(index)">&times;</span>
</div>
</Draggable>
<textarea
ref="myTextarea"
class="tags-input"
@ -22,8 +29,10 @@
</template>
<script>
import Draggable from 'vuedraggable'
export default {
name: 'TagInput',
components: {Draggable},
props: {
value: {
default: ''
@ -52,11 +61,13 @@
},
data() {
const disSource = [];
if( this.value ){
this.value?.split(",").forEach(item => {
if (item) {
disSource.push(item)
}
});
}
return {
minWidth: 80,
@ -69,7 +80,19 @@
disSource,
isFocus: false
isFocus: false,
editShow: false,
editData:{
index:0,
disSource:[],
name:""
},
addRule: {
name: [
{ required: true, message: this.$L('请填写名称!'), trigger: 'change' },
]
},
}
},
mounted() {
@ -80,6 +103,7 @@
this.wayMinWidth();
},
value(val) {
if( val && typeof val == 'string' ){
let disSource = [];
val?.split(",").forEach(item => {
if (item) {
@ -87,6 +111,7 @@
}
});
this.disSource = disSource;
}
},
disSource(val) {
let temp = '';
@ -109,6 +134,26 @@
}
},
methods: {
edit(disSource,index){
this.editData.disSource = disSource
this.editData.index = index
this.editData.name = disSource[index] + ''
$A.modalInput({
title: `编辑`,
placeholder: `请输入名称`,
okText: "确定",
value: disSource[index] + '',
onOk: (desc) => {
if (!desc) {
return `请输入名称`
}
this.editData.name = desc
this.editData.disSource[this.editData.index] = desc
this.$set(this.disSource,this.editData.index,desc)
return false
},
});
},
focus(option) {
const $el = this.$refs.myTextarea;
$el.focus(option);

View File

@ -199,6 +199,8 @@
</ButtonGroup>
</div>
</div>
<TaskExistTips ref="taskExistTipsRef" @onAdd="onAdd(again,true)"/>
</div>
</template>
@ -206,10 +208,11 @@
import TEditor from "../../../components/TEditor";
import {mapState} from "vuex";
import UserSelect from "../../../components/UserSelect.vue";
import TaskExistTips from "./TaskExistTips.vue";
export default {
name: "TaskAdd",
components: {UserSelect, TEditor},
components: {UserSelect, TEditor, TaskExistTips},
props: {
value: {
type: Boolean,
@ -276,6 +279,8 @@ export default {
isMounted: false,
beforeClose: [],
again: false
}
},
@ -515,12 +520,30 @@ export default {
this.addData = Object.assign({}, this.addData, data);
},
onAdd(again) {
async onAdd(again,affirm=false) {
if (!this.addData.name) {
$A.messageError("任务描述不能为空");
return;
}
this.loadIng++;
//
if(!affirm && this.addData.owner.length>0){
this.$refs['taskExistTipsRef'].isExistTask({
userids: this.addData.owner,
timerange: this.addData.times
}).then(res=>{
if(!res){
this.onAdd(again,true)
}else{
this.loadIng--;
this.again = again
}
});
return;
}
this.$store.dispatch("taskAdd", this.addData).then(({msg}) => {
this.loadIng--;
$A.messageSuccess(msg);

View File

@ -1,4 +1,5 @@
<template>
<div>
<!--子任务-->
<li v-if="ready && taskDetail.parent_id > 0">
<div class="subtask-icon">
@ -452,6 +453,9 @@
</div>
<div v-if="!taskDetail.id" class="task-load"><Loading/></div>
</div>
<!-- 提示 -->
<TaskExistTips ref="taskExistTipsRef" @onAdd="updateData('times', updateParams)"/>
</div>
</template>
<script>
@ -465,12 +469,21 @@ import {Store} from "le5le-store";
import TaskMenu from "./TaskMenu";
import ChatInput from "./ChatInput";
import UserSelect from "../../../components/UserSelect.vue";
import TaskExistTips from "./TaskExistTips.vue";
export default {
name: "TaskDetail",
components: {
UserSelect,
ChatInput, TaskMenu, ProjectLog, DialogWrapper, TaskUpload, TaskPriority, TEditor},
TaskExistTips,
ChatInput,
TaskMenu,
ProjectLog,
DialogWrapper,
TaskUpload,
TaskPriority,
TEditor
},
props: {
taskId: {
type: Number,
@ -574,6 +587,8 @@ export default {
{key: 'year', label: '每年'},
{key: 'custom', label: '自定义'},
],
updateParams: {},
}
},
@ -957,7 +972,16 @@ export default {
if (!desc) {
return `请输入修改备注`
}
this.updateData("times", Object.assign(params, {desc}))
this.updateParams = Object.assign(params, {desc})
this.$refs['taskExistTipsRef'].isExistTask({
taskid: this.taskDetail.id,
userids: this.taskDetail.owner_userid,
timerange: [params.start_at,params.end_at]
}).then(res=>{
if(!res){
this.updateData("times", this.updateParams)
}
});
return false
},
});

View File

@ -0,0 +1,103 @@
<template>
<Modal v-model="show" :title="$L('以下人员已存在任务')" class="task-exist-tips" width="640">
<List :split="false" size="small">
<ListItem v-for="(items, userid) in tipsTask" :key="userid">
<div class="list-content">
<UserAvatar :userid="userid" :size="28" :show-icon="true" :show-name="true" tooltipDisabled />
<div class="list-task" v-for="(item, key) in items" :key="key">
<div class="list-task-info">
<span>[{{ item.project_name }}] </span>
<span>{{ item.name }}</span>
</div>
<div class="list-task-date">{{ getCutTime(item) }}</div>
</div>
</div>
</ListItem>
</List>
<div slot="footer">
<Button type="default" @click="show = false">{{ $L('取消') }}</Button>
<Button type="primary" @click="onAdd()">{{ $L('确定') }}</Button>
</div>
</Modal>
</template>
<script>
import TEditor from "../../../components/TEditor";
import UserSelect from "../../../components/UserSelect.vue";
export default {
name: "TaskExistTips",
components: { UserSelect, TEditor },
props: {
value: {
type: Boolean,
default: false
},
},
data() {
return {
isExist: false,
show: false,
tipsTask: [],
loadIng: false,
}
},
methods: {
onAdd() {
this.$emit('onAdd', {})
this.show = false;
},
getCutTime(item) {
let start_at = $A.Date(item.start_at, true);
let end_at = $A.Date(item.end_at, true);
let string = "";
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)
} else if ($A.formatDate('Y', start_at) == $A.formatDate('Y', end_at)) {
string = $A.formatDate('Y/m/d', start_at) + " ~ " + $A.formatDate('m/d', end_at)
string = string.replace(/( 00:00| 23:59)/g, "")
} else {
string = $A.formatDate('Y/m/d H:i', start_at) + " ~ " + $A.formatDate('Y/m/d H:i', end_at)
string = string.replace(/( 00:00| 23:59)/g, "")
}
return string
},
isExistTask({ userids, timerange, taskid }) {
this.isExist = false;
return new Promise(async resolve => {
this.$store.dispatch("call", {
url: 'project/task/easylists',
data: {
userid: userids,
timerange: timerange,
taskid: taskid
},
method: 'get',
}).then(({ data }) => {
if (data.data.length > 0) {
this.show = true;
let taskObj = {}
userids.map(userid => {
data.data.map(h => {
if ((h.task_user || []).map(k => k.owner ? k.userid : 0).indexOf(userid) !== -1) {
if (!taskObj[userid]) {
taskObj[userid] = [];
}
taskObj[userid].push(h);
}
});
});
this.tipsTask = taskObj
this.isExist = true;
}
resolve(this.isExist)
});
});
}
}
}
</script>

View File

@ -23,3 +23,4 @@
@import "task-priority";
@import "team-management";
@import "update-log";
@import "task-exist-tips";

View File

@ -0,0 +1,40 @@
.task-exist-tips {
.ivu-modal-body {
padding: 0px 26px 16px 26px !important;
max-height: 500px;
overflow: auto;
}
.list-content {
flex: 1;
width: 100%;
}
.list-task {
@media (min-width: 450px) {
display: flex;
}
margin-left: 34px;
margin-top: 10px;
width: calc(100% - 34px);
}
.list-task-info {
min-width: 135px;
flex: 1;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
span:first-child {
color: #A7ABB5;
}
}
.list-task-date {
min-width: 135px;
text-align: left;
}
}