kuaifan hace 5 años
padre
commit
14abb71258

+ 11 - 1
app/Http/Controllers/Api/ProjectController.php

@@ -100,6 +100,7 @@ class ProjectController extends Controller
         }
         //子分类
         $label = Base::DBC2A(DB::table('project_label')->where('projectid', $projectid)->orderBy('inorder')->orderBy('id')->get());
+        $simpleLabel = [];
         //任务
         $task = Base::DBC2A(DB::table('project_task')->where([ 'projectid' => $projectid, 'delete' => 0, 'complete' => 0 ])->orderBy('level')->orderBy('id')->get());
         //任务归类
@@ -112,11 +113,13 @@ class ProjectController extends Controller
                 }
             }
             $label[$index]['taskLists'] = Project::sortTask($taskLists);
+            $simpleLabel[] = ['id' => $temp['id'], 'title' => $temp['title']];
         }
         //
         return Base::retSuccess('success', [
             'project' => $projectDetail,
             'label' => $label,
+            'simpleLabel' => $simpleLabel,
         ]);
     }
 
@@ -780,6 +783,7 @@ class ProjectController extends Controller
      * - 未完成
      * - 已超期
      * - 已完成
+     * @apiParam {String} [username]            负责人用户名
      * @apiParam {Number} [statistics]          是否获取统计数据(1:获取)
      * @apiParam {Number} [levelsort]           是否按紧急排序(1:是)
      * @apiParam {Number} [page]                当前页,默认:1
@@ -808,14 +812,20 @@ class ProjectController extends Controller
         if (intval(Request::input('labelid')) > 0) {
             $whereArray[] = ['project_task.labelid', '=', intval(Request::input('labelid'))];
         }
+        if (intval(Request::input('level')) > 0) {
+            $whereArray[] = ['project_task.level', '=', intval(Request::input('level'))];
+        }
+        if (trim(Request::input('username'))) {
+            $whereArray[] = ['project_task.username', '=', trim(Request::input('username'))];
+        }
         $archived = trim(Request::input('archived'));
+        if (empty($archived)) $archived = "未归档";
         switch ($archived) {
             case '已归档':
                 $whereArray[] = ['project_task.archived', '=', 1];
                 $orderBy = '`archiveddate` DESC';
                 break;
             case '未归档':
-            default:
                 $whereArray[] = ['project_task.archived', '=', 0];
                 break;
         }

+ 36 - 0
resources/assets/js/main/App.vue

@@ -28,6 +28,10 @@
                     this.sessionStorage(hash, this.sessionStorage('::count') + 1);
                 }
             }
+            //
+            setInterval(() => {
+                this.searchEnter();
+            }, 1000);
         },
         watch: {
             '$route' (To, From) {
@@ -106,6 +110,38 @@
                 for(let key in history){ if (history.hasOwnProperty(key) && key !== '::count') { conut++; } }
                 history['::count'] = Math.max(num, conut);
                 window.sessionStorage['__history__'] = JSON.stringify(history);
+            },
+
+            searchEnter() {
+                let row = $A(".sreachBox");
+                if (row.length === 0) {
+                    return;
+                }
+                if (row.attr("data-enter-init") === "init") {
+                    return;
+                }
+                row.attr("data-enter-init", "init");
+                //
+                let buttons = row.find("button[type='button']");
+                let button = null;
+                if (buttons.length === 0) {
+                    return;
+                }
+                buttons.each((index, item) => {
+                    if ($A(item).text().indexOf("搜索")) {
+                        button = $A(item);
+                    }
+                });
+                if (button === null) {
+                    return;
+                }
+                row.find("input.ivu-input").keydown(function(e) {
+                    if (e.keyCode == 13) {
+                        if (!button.hasClass("ivu-btn-loading") ) {
+                            button.click();
+                        }
+                    }
+                });
             }
         }
     }

+ 3 - 0
resources/assets/js/main/app.js

@@ -14,8 +14,11 @@ Vue.use(Language);
 
 import Title from '../_components/Title.vue'
 import UseridInput from './components/UseridInput'
+import sreachTitle from '../_components/sreachTitle.vue'
+
 Vue.component('VTitle', Title);
 Vue.component('UseridInput', UseridInput);
+Vue.component('sreachTitle', sreachTitle);
 
 const router = new VueRouter({routes});
 

+ 259 - 0
resources/assets/js/main/components/project/task/lists.vue

@@ -0,0 +1,259 @@
+<template>
+    <div class="project-task-lists">
+
+        <!-- 搜索 -->
+        <Row class="sreachBox">
+            <div class="item">
+                <div class="item-4">
+                    <sreachTitle :val="keys.type">状态</sreachTitle>
+                    <Select v-model="keys.type" placeholder="全部">
+                        <Option value="">全部</Option>
+                        <Option value="未完成">未完成</Option>
+                        <Option value="已超期">已超期</Option>
+                        <Option value="已完成">已完成</Option>
+                    </Select>
+                </div>
+                <div class="item-4">
+                    <sreachTitle :val="keys.username">负责人</sreachTitle>
+                    <Input v-model="keys.username" placeholder="用户名"/>
+                </div>
+                <div class="item-4">
+                    <sreachTitle :val="keys.level">级别</sreachTitle>
+                    <Select v-model="keys.level" placeholder="全部">
+                        <Option value="">全部</Option>
+                        <Option value="1">P1</Option>
+                        <Option value="2">P2</Option>
+                        <Option value="3">P3</Option>
+                        <Option value="4">P4</Option>
+                    </Select>
+                </div>
+                <div class="item-4">
+                    <sreachTitle :val="keys.labelid">阶段</sreachTitle>
+                    <Select v-model="keys.labelid" placeholder="全部">
+                        <Option value="">全部</Option>
+                        <Option
+                            v-for="item in labelLists"
+                            :value="item.id"
+                            :key="item.id">{{ item.title }}</Option>
+                    </Select>
+                </div>
+            </div>
+            <div class="item item-button">
+                <Button type="text" v-if="$A.objImplode(keys)!=''" @click="sreachTab(true)">取消筛选</Button>
+                <Button type="primary" icon="md-search" :loading="loadIng > 0" @click="sreachTab">搜索</Button>
+            </div>
+        </Row>
+
+        <!-- 列表 -->
+        <Table class="tableFill" ref="tableRef" :columns="columns" :data="lists" :loading="loadIng > 0" :no-data-text="noDataText" stripe></Table>
+
+        <!-- 分页 -->
+        <Page class="pageBox" :total="listTotal" :current="listPage" :disabled="loadIng > 0" @on-change="setPage" @on-page-size-change="setPageSize" :page-size-opts="[10,20,30,50,100]" placement="top" show-elevator show-sizer show-total transfer></Page>
+
+    </div>
+</template>
+<style lang="scss" scoped>
+    .project-task-lists {
+        margin: 0 12px;
+        .tableFill {
+            margin: 12px 0 20px;
+        }
+    }
+</style>
+
+<script>
+
+    export default {
+        name: 'ProjectTaskLists',
+        props: {
+            projectid: {
+                default: 0
+            },
+            canload: {
+                type: Boolean,
+                default: true
+            },
+            labelLists: {
+                type: Object,
+            },
+        },
+        data() {
+            return {
+                keys: {},
+
+                loadYet: false,
+
+                loadIng: 0,
+
+                columns: [],
+
+                lists: [],
+                listPage: 1,
+                listTotal: 0,
+                noDataText: "数据加载中.....",
+            }
+        },
+
+        created() {
+            this.columns = [{
+                "title": "任务名称",
+                "key": 'title',
+                "minWidth": 100,
+            }, {
+                "title": "阶段",
+                "key": 'labelid',
+                "minWidth": 80,
+                render: (h, params) => {
+                    let labelid = params.row.labelid;
+                    let labelDetail = this.labelLists.find((item) => { return item.id === labelid});
+                    return h('span', labelDetail ? labelDetail.title : labelid);
+                }
+            }, {
+                "title": "计划时间",
+                "width": 160,
+                "align": "center",
+                render: (h, params) => {
+                    return h('span', params.row.enddate ? $A.formatDate("Y-m-d H:i:s", params.row.enddate) : '-');
+                }
+            }, {
+                "title": "负责人",
+                "key": 'username',
+                "minWidth": 80,
+            }, {
+                "title": "优先级",
+                "key": 'level',
+                "align": "center",
+                "maxWidth": 80,
+                render: (h, params) => {
+                    let level = params.row.level;
+                    let color;
+                    switch (level) {
+                        case "1":
+                            color = "#ff0000";
+                            break;
+                        case "2":
+                            color = "#BB9F35";
+                            break;
+                        case "3":
+                            color = "#449EDD";
+                            break;
+                        case "4":
+                            color = "#84A83B";
+                            break;
+                    }
+                    return h('span', {
+                        style: {
+                            color: color
+                        }
+                    }, "P" + level);
+                },
+            }, {
+                "title": "状态",
+                "key": 'complete',
+                "align": "center",
+                "maxWidth": 80,
+                render: (h, params) => {
+                    let color;
+                    let status;
+                    if (params.row.overdue) {
+                        color = "#ff0000";
+                        status = "已超期";
+                    } else if (params.row.complete) {
+                        color = "";
+                        status = "已完成";
+                    } else {
+                        color = "#19be6b";
+                        status = "未完成";
+                    }
+                    return h('span', {
+                        style: {
+                            color: color
+                        }
+                    }, status);
+                },
+            }, {
+                "title": "创建时间",
+                "width": 160,
+                render: (h, params) => {
+                    return h('span', $A.formatDate("Y-m-d H:i:s", params.row.indate));
+                }
+            }];
+        },
+
+        mounted() {
+            if (this.canload) {
+                this.loadYet = true;
+                this.getLists(true);
+            }
+        },
+
+        watch: {
+            projectid() {
+                if (this.loadYet) {
+                    this.getLists(true);
+                }
+            },
+            canload(val) {
+                if (val && !this.loadYet) {
+                    this.loadYet = true;
+                    this.getLists(true);
+                }
+            }
+        },
+
+        methods: {
+            sreachTab(clear) {
+                if (clear === true) {
+                    this.keys = {};
+                }
+                this.getLists(true);
+            },
+
+            setPage(page) {
+                this.listPage = page;
+                this.getLists();
+            },
+
+            setPageSize(size) {
+                if (Math.max($A.runNum(this.listPageSize), 10) != size) {
+                    this.listPageSize = size;
+                    this.getLists();
+                }
+            },
+
+            getLists(resetLoad) {
+                if (resetLoad === true) {
+                    this.listPage = 1;
+                }
+                if (this.projectid == 0) {
+                    this.lists = [];
+                    this.listTotal = 0;
+                    this.noDataText = "没有相关的数据";
+                    return;
+                }
+                this.loadIng++;
+                let whereData = $A.cloneData(this.keys);
+                whereData.page = Math.max(this.listPage, 1);
+                whereData.pagesize = Math.max($A.runNum(this.listPageSize), 10);
+                whereData.projectid = this.projectid;
+                $A.aAjax({
+                    url: 'project/task/lists',
+                    data: whereData,
+                    complete: () => {
+                        this.loadIng--;
+                    },
+                    success: (res) => {
+                        if (res.ret === 1) {
+                            this.lists = res.data.lists;
+                            this.listTotal = res.data.total;
+                        } else {
+                            this.lists = [];
+                            this.listTotal = 0;
+                            this.noDataText = res.msg;
+                        }
+                    }
+                });
+            },
+        }
+    }
+</script>

+ 30 - 5
resources/assets/js/main/pages/project-panel.vue

@@ -15,10 +15,10 @@
                 </div>
                 <div class="w-nav-flex"></div>
                 <div class="w-nav-right">
-                    <span class="ft hover"><i class="ft icon">&#xE6E7;</i> 任务看板</span>
-                    <span class="ft hover"><i class="ft icon">&#xE89E;</i> 任务列表</span>
-                    <span class="ft hover"><i class="ft icon">&#xE705;</i> 甘特图</span>
-                    <span class="ft hover"><i class="ft icon">&#xE7A7;</i> 设置</span>
+                    <span class="ft hover" @click="openProjectDrawer('lists')"><i class="ft icon">&#xE89E;</i> 任务列表</span>
+                    <span class="ft hover" @click="openProjectDrawer('files')"><i class="ft icon">&#xE701;</i> 文件列表</span>
+                    <span class="ft hover" @click="openProjectDrawer('logs')"><i class="ft icon">&#xE753;</i> 项目动态</span>
+                    <span class="ft hover" @click="openProjectDrawer('setting')"><i class="ft icon">&#xE7A7;</i> 设置</span>
                 </div>
             </div>
         </div>
@@ -64,6 +64,19 @@
             </draggable>
         </w-content>
 
+        <Drawer v-model="projectDrawerShow" width="80%">
+            <Tabs v-if="projectDrawerShow" v-model="projectDrawerTab">
+                <TabPane :label="$L('任务列表')" name="lists">
+                    <project-task-lists :canload="projectDrawerShow && projectDrawerTab == 'lists'" :projectid="projectid" :labelLists="projectSimpleLabel"></project-task-lists>
+                </TabPane>
+                <TabPane :label="$L('文件列表')" name="files">
+                </TabPane>
+                <TabPane :label="$L('项目动态')" name="logs">
+                </TabPane>
+                <TabPane :label="$L('项目设置')" name="setting">
+                </TabPane>
+            </Tabs>
+        </Drawer>
     </div>
 </template>
 
@@ -265,9 +278,10 @@
     import WContent from "../components/WContent";
     import WLoading from "../components/WLoading";
     import ProjectAddTask from "../components/project/task/add";
+    import ProjectTaskLists from "../components/project/task/lists";
 
     export default {
-        components: {ProjectAddTask, draggable, WLoading, WContent, WHeader},
+        components: {ProjectTaskLists, ProjectAddTask, draggable, WLoading, WContent, WHeader},
         data () {
             return {
                 loadIng: 0,
@@ -276,6 +290,10 @@
                 projectid: 0,
                 projectDetail: {},
                 projectLabel: [],
+                projectSimpleLabel: [],
+
+                projectDrawerShow: false,
+                projectDrawerTab: 'lists',
             }
         },
         mounted() {
@@ -295,6 +313,7 @@
                 }
                 this.projectDetail = {};
                 this.projectLabel = [];
+                this.projectSimpleLabel = [];
                 this.getDetail();
             }
         },
@@ -318,6 +337,7 @@
                         if (res.ret === 1) {
                             this.projectDetail = res.data.project;
                             this.projectLabel = res.data.label;
+                            this.projectSimpleLabel = res.data.simpleLabel;
                         } else {
                             this.$Modal.error({title: this.$L('温馨提示'), content: res.msg});
                             this.goBack();
@@ -520,6 +540,11 @@
                         }
                     }
                 });
+            },
+
+            openProjectDrawer(tab) {
+                this.projectDrawerTab = tab;
+                this.projectDrawerShow = true;
             }
         },
     }

+ 2 - 2
resources/assets/js/main/pages/team.vue

@@ -120,8 +120,8 @@
                 render: (h, params) => {
                     return h('img', {
                         style: {
-                            width: "36px",
-                            height: "36px",
+                            width: "32px",
+                            height: "32px",
                             verticalAlign: "middle",
                             objectFit: "cover",
                             borderRadius: "50%"

+ 74 - 0
resources/assets/sass/main.scss

@@ -172,3 +172,77 @@
     text-align: center;
     margin-bottom: 12px;
 }
+.sreachBox {
+    > .item {
+        margin-bottom: 8px;
+    }
+    .item {
+        > div {
+            display: block;
+            float: left;
+            padding-right: 10px;
+            &:last-child {
+                padding-right: 0;
+            }
+            .ivu-input-wrapper,.ivu-select {
+                margin-top: 2px;
+            }
+            input,.ivu-select-placeholder {
+                font-weight: normal;
+            }
+        }
+        .item-1 {
+            width: 100%;
+        }
+        .item-2 {
+            width: 50%;
+        }
+        .item-3 {
+            width: 33.33%;
+        }
+        .item-4 {
+            width: 25%;
+        }
+        .item-5 {
+            width: 20%;
+        }
+        &:after {
+            content: '';
+            display: block;
+            height: 0;
+            clear: both;
+            visibility: hidden;
+        }
+    }
+    .item-title,
+    .item-title-active {
+        display: block;
+        overflow: hidden;
+        text-overflow:ellipsis;
+        white-space: nowrap;
+        font-weight: 600;
+    }
+    .item-title-active {
+        color: #ff0000;
+    }
+    .item-button {
+        text-align: right;
+        margin-top: 10px;
+        margin-bottom: 0;
+        .ivu-input-wrapper {
+            float: none;
+            width: 150px;
+            display:inline-block;
+        }
+    }
+    .ivu-date-picker {
+        width: 100%;
+        position: relative;
+        vertical-align: middle;
+    }
+    .item-button {
+        .ivu-btn {
+            margin-left: 8px;
+        }
+    }
+}