kuaifan 5 lat temu
rodzic
commit
01dd4adc02

+ 101 - 14
app/Http/Controllers/Api/ProjectController.php

@@ -431,8 +431,14 @@ class ProjectController extends Controller
         return Base::retSuccess('删除成功!');
     }
 
-
-
+    /**
+     * 排序任务
+     *
+     * @apiParam {Number} projectid     项目ID
+     * @apiParam {String} oldsort       旧排序数据
+     * @apiParam {String} newsort       新排序数据
+     * @apiParam {Number} label         赋值表示排序分类,否则排序任务(调整任务所属分类)
+     */
     public function sort()
     {
         $user = Users::authE();
@@ -529,6 +535,88 @@ class ProjectController extends Controller
     }
 
     /**
+     * 排序任务(todo待办)
+     *
+     * @apiParam {String} oldsort       旧排序数据
+     * @apiParam {String} newsort       新排序数据
+     */
+    public function sort__todo()
+    {
+        $user = Users::authE();
+        if (Base::isError($user)) {
+            return $user;
+        } else {
+            $user = $user['data'];
+        }
+        //
+        $oldSort = explode(";", Request::input('oldsort'));
+        $newSort = explode(";", Request::input('newsort'));
+        if (count($oldSort) != count($newSort)) {
+            return Base::retError('参数错误!');
+        }
+        //
+        $levels = [];
+        $logArray = [];
+        foreach ($newSort AS $sort => $item) {
+            list($newLevel, $newTask) = explode(':', $item);
+            list($oldLevel, $oldTask) = explode(':', $oldSort[$sort]);
+            if ($newTask != $oldTask) {
+                $newTask = explode('-', $newTask);
+                $oldTask = explode('-', $oldTask);
+                $userorder = intval(DB::table('project_task')->select('userorder')->where([
+                    'delete' => 0,
+                    'archived' => 0,
+                    'level' => $newLevel,
+                    'username' => $user['username'],
+                ])->orderByDesc('userorder')->value('userorder'));
+                if (count($newTask) < count($oldTask)) {
+                    $userorder--;
+                } else {
+                    $userorder++;
+                }
+                foreach ($newTask AS $taskid) {
+                    $task = Base::DBC2A(DB::table('project_task')->select(['id', 'title', 'projectid', 'level', 'userorder'])->where([
+                        'id' => $taskid,
+                        'username' => $user['username']
+                    ])->first());
+                    $upArray = [];
+                    if ($task) {
+                        if ($task['level'] != $newLevel) {
+                            $upArray['level'] = $newLevel;
+                            $logArray[] = [
+                                'type' => '日志',
+                                'projectid' => $task['projectid'],
+                                'taskid' => $task['id'],
+                                'username' => $user['username'],
+                                'detail' => '调整任务等级为【P' . $newLevel . '】',
+                                'indate' => Base::time(),
+                                'other' => Base::array2string([
+                                    'type' => 'task',
+                                    'id' => $task['id'],
+                                    'title' => $task['title'],
+                                ])
+                            ];
+                        }
+                        if ($task['userorder'] != $userorder) {
+                            $upArray['userorder'] = $userorder;
+                        }
+                    }
+                    if ($upArray) {
+                        DB::table('project_task')->where('id', $taskid)->update($upArray);
+                    }
+                    $userorder--;
+                }
+                $levels[] = $newLevel;
+            }
+        }
+        if ($logArray) {
+            DB::table('project_log')->insert($logArray);
+        }
+        //
+        return Base::retSuccess('保存成功!', $levels);
+    }
+
+    /**
      * 退出项目
      *
      * @apiParam {Number} projectid     项目ID
@@ -889,13 +977,14 @@ class ProjectController extends Controller
      * - 已完成
      * @apiParam {Number} [attention]           是否仅获取关注数据(1:是)
      * @apiParam {Number} [statistics]          是否获取统计数据(1:获取)
+     * @apiParam {String} [startdate]           任务开始时间,格式:YYYY-MM-DD
+     * @apiParam {String} [enddate]             任务结束时间,格式:YYYY-MM-DD
+     *
      * @apiParam {Object} [sorts]               排序方式,格式:{key:'', order:''}
-     * - key: title|labelid|enddate|username|level|indate|type
+     * - key: title|labelid|enddate|username|level|indate|type|inorder(默认)|userorder
      * - order: asc|desc
      * - 【archived=已归档】或【startdate和enddate赋值】时无效
-     * @apiParam {String} [startdate]           任务开始时间,格式:YYYY-MM-DD
-     * @apiParam {String} [enddate]             任务结束时间,格式:YYYY-MM-DD
-     * @apiParam {Number} [idlater]             获取数据ID之后的数据
+     *
      * @apiParam {Number} [page]                当前页,默认:1
      * @apiParam {Number} [pagesize]            每页显示数量,默认:20,最大:100
      */
@@ -917,9 +1006,6 @@ class ProjectController extends Controller
         }
         //
         $orderBy = '`inorder` DESC,`id` DESC';
-        if (intval(Request::input('labelid')) == 0) {
-            $orderBy = '`indate` DESC,`id` DESC';
-        }
         $sorts = Base::json2array(Request::input('sorts'));
         if (in_array($sorts['order'], ['asc', 'desc'])) {
             switch ($sorts['key']) {
@@ -929,6 +1015,8 @@ class ProjectController extends Controller
                 case 'username':
                 case 'level':
                 case 'indate':
+                case 'inorder':
+                case 'userorder':
                     $orderBy = '`' . $sorts['key'] . '` ' . $sorts['order'] . ',`id` DESC';
                     break;
                 case 'type':
@@ -956,9 +1044,6 @@ class ProjectController extends Controller
         if (intval(Request::input('level')) > 0) {
             $whereArray[] = ['project_task.level', '=', intval(Request::input('level'))];
         }
-        if (intval(Request::input('idlater')) > 0) {
-            $whereArray[] = ['project_task.id', '<', intval(Request::input('idlater'))];
-        }
         if (intval(Request::input('attention')) === 1) {
             $whereRaw.= $whereRaw ? ' AND ' : '';
             $whereRaw.= "`username` in (select username from `" . env('DB_PREFIX') . "project_users` where `type`='关注' AND `username`='" . $user['username'] . "')";
@@ -1084,14 +1169,16 @@ class ProjectController extends Controller
             return Base::retError('任务标题最多只能设置255个字!');
         }
         //
+        $level = max(1, min(4, intval(Request::input('level'))));
         $inArray = [
             'projectid' => $projectid,
             'labelid' => $labelid,
             'createuser' => $user['username'],
             'username' => $username,
             'title' => $title,
-            'level' => max(1, min(4, intval(Request::input('level')))),
-            'inorder' => intval(DB::table('project_task')->where('projectid', $projectid)->orderByDesc('inorder')->value('inorder')) + 1,
+            'level' => $level,
+            'inorder' => empty($projectid) ? 0 : intval(DB::table('project_task')->where('projectid', $projectid)->orderByDesc('inorder')->value('inorder')) + 1,
+            'userorder' => intval(DB::table('project_task')->where('username', $user['username'])->where('level', $level)->orderByDesc('userorder')->value('userorder')) + 1,
             'indate' => Base::time(),
             'startdate' => Base::time(),
             'subtask' => Base::array2string([]),

+ 4 - 4
app/Module/Users.php

@@ -57,7 +57,7 @@ class Users
         $authorization = Base::getToken();
         $id = 0;
         if ($authorization) {
-            list($id, $username, $encrypt, $timestamp) = explode("@", base64_decode($authorization));
+            list($id, $username, $encrypt, $timestamp) = explode("@", base64_decode($authorization) . "@@@@");
         }
         return intval($id);
     }
@@ -71,7 +71,7 @@ class Users
         $authorization = Base::getToken();
         $username = '';
         if ($authorization) {
-            list($id, $username, $encrypt, $timestamp) = explode("@", base64_decode($authorization));
+            list($id, $username, $encrypt, $timestamp) = explode("@", base64_decode($authorization) . "@@@@");
         }
         return Base::isMobile($username) ? $username : '';
     }
@@ -88,8 +88,8 @@ class Users
         }
         $authorization = Base::getToken();
         if ($authorization) {
-            list($id, $username, $encrypt, $timestamp) = explode("@", base64_decode($authorization));
-            if ($id > 0 && $timestamp + 2592000 > Base::time()) {
+            list($id, $username, $encrypt, $timestamp) = explode("@", base64_decode($authorization) . "@@@@");
+            if (intval($id) > 0 && intval($timestamp) + 2592000 > Base::time()) {
                 $userinfo = DB::table('users')->where(['id' => $id, 'username' => $username, 'encrypt' => $encrypt])->first();
                 Base::coll2array($userinfo);
                 if ($userinfo['token']) {

+ 17 - 2
resources/assets/js/main/pages/project-panel.vue

@@ -25,7 +25,14 @@
         </div>
 
         <w-content>
-            <draggable v-if="projectLabel.length > 0" v-model="projectLabel" class="label-box" draggable=".label-draggable" :animation="150" :disabled="projectSortDisabled" @sort="projectSortUpdate(true)">
+            <draggable
+                v-if="projectLabel.length > 0"
+                v-model="projectLabel"
+                class="label-box"
+                draggable=".label-draggable"
+                :animation="150"
+                :disabled="projectSortDisabled"
+                @sort="projectSortUpdate(true)">
                 <div v-for="label in projectLabel" :key="label.id" class="label-item label-draggable">
                     <div class="label-body">
                         <div class="title-box">
@@ -42,7 +49,15 @@
                                 </DropdownMenu>
                             </Dropdown>
                         </div>
-                        <draggable v-model="label.taskLists" class="task-box" group="task" draggable=".task-draggable" :animation="150" :disabled="projectSortDisabled" @sort="projectSortUpdate(false)" @remove="projectSortUpdate(false)">
+                        <draggable
+                            v-model="label.taskLists"
+                            class="task-box"
+                            group="task"
+                            draggable=".task-draggable"
+                            :animation="150"
+                            :disabled="projectSortDisabled"
+                            @sort="projectSortUpdate(false)"
+                            @remove="projectSortUpdate(false)">
                             <div v-for="task in label.taskLists" :key="task.id" class="task-item task-draggable">
                                 <div class="task-shadow" :class="[
                                         'p'+task.level,

+ 111 - 26
resources/assets/js/main/pages/todo.vue

@@ -22,8 +22,8 @@
 
         <w-content>
             <div class="todo-main">
-                <ul v-for="subs in [['1', '2'], ['3', '4']]">
-                    <li v-for="index in subs">
+                <div v-for="subs in [['1', '2'], ['3', '4']]" class="todo-ul">
+                    <div v-for="index in subs" class="todo-li">
                         <div class="todo-card">
                             <div class="todo-card-head" :class="['p' + index]">
                                 <i class="ft icon flag">&#xE753;</i>
@@ -40,21 +40,30 @@
                                 </label>
                             </div>
                             <div class="todo-card-content">
-                                <ul v-if="taskDatas[index].lists.length > 0">
-                                    <li v-for="task in taskDatas[index].lists" :key="task.id" :class="{complete:task.complete}">
+                                <draggable
+                                    v-if="taskDatas[index].lists.length > 0"
+                                    v-model="taskDatas[index].lists"
+                                    class="content-ul"
+                                    group="task"
+                                    draggable=".task-draggable"
+                                    :animation="150"
+                                    :disabled="taskSortDisabled"
+                                    @sort="taskSortUpdate"
+                                    @remove="taskSortUpdate">
+                                    <div v-for="task in taskDatas[index].lists" class="content-li task-draggable" :key="task.id" :class="{complete:task.complete}">
                                         <Icon v-if="task.complete" class="task-check" type="md-checkbox-outline" />
                                         <Icon v-else class="task-check" type="md-square-outline" />
                                         <div v-if="task.overdue" class="task-overdue">[超期]</div>
-                                        <div class="task-title">{{task.title}}</div>
-                                    </li>
-                                    <li v-if="taskDatas[index].hasMorePages === true" class="more" @click="getTask(index, true)">加载更多</li>
-                                </ul>
+                                        <div class="task-title">{{task.id}}、{{task.title}}</div>
+                                    </div>
+                                    <div v-if="taskDatas[index].hasMorePages === true" class="content-li more" @click="getTaskLists(index, true)">加载更多</div>
+                                </draggable>
                                 <div v-else-if="taskDatas[index].loadIng == 0" class="content-empty">{{$L('恭喜你!已完成了所有待办')}}</div>
                                 <div v-if="taskDatas[index].loadIng > 0" class="content-loading"><w-loading></w-loading></div>
                             </div>
                         </div>
-                    </li>
-                </ul>
+                    </div>
+                </div>
             </div>
         </w-content>
 
@@ -93,14 +102,14 @@
             height: 100%;
             min-height: 500px;
             padding: 5px;
-            ul {
+            .todo-ul {
                 flex: 1;
                 display: flex;
                 flex-direction: row;
                 align-items: center;
                 justify-content: center;
                 width: 100%;
-                li {
+                .todo-li {
                     flex: 1;
                     height: 100%;
                     position: relative;
@@ -201,10 +210,10 @@
                             border-radius: 0 0 4px 4px;
                             overflow: auto;
                             transform: translateZ(0);
-                            ul {
+                            .content-ul {
                                 display: flex;
                                 flex-direction: column;
-                                li {
+                                .content-li {
                                     display: flex;
                                     flex-direction: row;
                                     align-items: flex-start;
@@ -262,9 +271,9 @@
         @media (max-width: 780px) {
             .todo-main {
                 height: auto;
-                ul {
+                .todo-ul {
                     flex-direction: column;
-                    li {
+                    .todo-li {
                         width: 100%;
                         .todo-card {
                             position: static;
@@ -285,14 +294,17 @@
     }
 </style>
 <script>
+    import draggable from 'vuedraggable'
+
     import WHeader from "../components/WHeader";
     import WContent from "../components/WContent";
     import WLoading from "../components/WLoading";
     import TodoCalendar from "../components/project/todo/calendar";
     import TodoComplete from "../components/project/todo/complete";
     import TodoAttention from "../components/project/todo/attention";
+
     export default {
-        components: {TodoAttention, TodoComplete, TodoCalendar, WContent, WHeader, WLoading},
+        components: {draggable, TodoAttention, TodoComplete, TodoCalendar, WContent, WHeader, WLoading},
         data () {
             return {
                 userInfo: {},
@@ -304,6 +316,9 @@
                     "4": {lists: [], hasMorePages: false},
                 },
 
+                taskSortData: '',
+                taskSortDisabled: false,
+
                 todoDrawerShow: false,
                 todoDrawerTab: 'calendar',
             }
@@ -311,10 +326,8 @@
         mounted() {
             this.userInfo = $A.getUserInfo((res) => {
                 this.userInfo = res;
+                this.refreshTask();
             });
-            for (let i = 1; i <= 4; i++) {
-                this.getTask(i.toString());
-            }
         },
         computed: {
 
@@ -336,26 +349,41 @@
                 }
             },
 
-            getTask(index, isNext) {
+            refreshTask() {
+                this.taskDatas = {
+                    "1": {lists: [], hasMorePages: false},
+                    "2": {lists: [], hasMorePages: false},
+                    "3": {lists: [], hasMorePages: false},
+                    "4": {lists: [], hasMorePages: false},
+                };
+                for (let i = 1; i <= 4; i++) {
+                    this.getTaskLists(i.toString());
+                }
+            },
+
+            getTaskLists(index, isNext) {
                 let taskData = this.taskDatas[index];
-                let idlater = 0;
+                let currentPage = 1;
                 if (isNext === true) {
                     if (taskData.hasMorePages !== true) {
                         return;
                     }
-                    idlater = taskData.lists[taskData.lists.length - 1].id
+                    currentPage = Math.max(1, $A.runNum(taskData['currentPage']));
+                    currentPage++;
                 }
                 this.$set(taskData, 'hasMorePages', false);
                 this.$set(taskData, 'loadIng', $A.runNum(taskData.loadIng) + 1);
+                this.taskSortDisabled = true;
                 $A.aAjax({
                     url: 'project/task/lists',
                     data: {
                         level: index,
-                        idlater: idlater,
-                        page: 1,
+                        sorts: {key:'userorder', order:'desc'},
+                        page: currentPage,
                         pagesize: 10,
                     },
                     complete: () => {
+                        this.taskSortDisabled = false;
                         this.$set(taskData, 'loadIng', $A.runNum(taskData.loadIng) - 1);
                     },
                     success: (res) => {
@@ -373,6 +401,8 @@
                                     taskData.lists.push(data);
                                 }
                             });
+                            this.taskSortData = this.getTaskSort();
+                            this.$set(taskData, 'currentPage', res.data.currentPage);
                             this.$set(taskData, 'hasMorePages', res.data.hasMorePages);
                         } else {
                             this.$set(taskData, 'lists', []);
@@ -397,12 +427,16 @@
                     title: title,
                     loadIng: true,
                 });
+                this.taskSortDisabled = true;
                 $A.aAjax({
                     url: 'project/task/add',
                     data: {
                         title: title,
                         level: index,
                     },
+                    complete: () => {
+                        this.taskSortDisabled = false;
+                    },
                     error: () => {
                         taskData.lists.some((item, i) => {
                             if (item.id == tempId) {
@@ -428,10 +462,26 @@
                                 return true;
                             }
                         });
+                        this.taskSortData = this.getTaskSort();
                     }
                 });
             },
 
+            getTaskSort() {
+                let sortData = "",
+                    taskData = "";
+                for (let level in this.taskDatas) {
+                    taskData = "";
+                    this.taskDatas[level].lists.forEach((task) => {
+                        if (taskData) taskData += "-";
+                        taskData += task.id;
+                    });
+                    if (sortData) sortData += ";";
+                    sortData += level + ":" + taskData;
+                }
+                return sortData;
+            },
+
             handleTodo(event) {
                 switch (event) {
                     case 'calendar':
@@ -442,7 +492,42 @@
                         break;
                     }
                 }
-            }
+            },
+
+            taskSortUpdate() {
+                let oldSort = this.taskSortData;
+                let newSort = this.getTaskSort();
+                if (oldSort == newSort) {
+                    return;
+                }
+                this.taskSortData = newSort;
+                this.taskSortDisabled = true;
+                $A.aAjax({
+                    url: 'project/sort/todo',
+                    data: {
+                        oldsort: oldSort,
+                        newsort: newSort,
+                    },
+                    complete: () => {
+                        this.taskSortDisabled = false;
+                    },
+                    error: () => {
+                        this.refreshTask();
+                        alert(this.$L('网络繁忙,请稍后再试!'));
+                    },
+                    success: (res) => {
+                        if (res.ret === 1) {
+                            this.$Message.success(res.msg);
+                            res.data.forEach((level) => {
+                                this.getTaskLists(level.toString());
+                            });
+                        } else {
+                            this.refreshTask();
+                            this.$Modal.error({title: this.$L('温馨提示'), content: res.msg});
+                        }
+                    }
+                });
+            },
         },
     }
 </script>