kuaifan hace 5 años
padre
commit
c1dc584646

+ 261 - 0
app/Http/Controllers/Api/ProjectController.php

@@ -1048,4 +1048,265 @@ class ProjectController extends Controller
             }
         }
     }
+
+    /**
+     * 项目文件-列表
+     *
+     * @apiParam {Number} projectid             项目ID
+     * @apiParam {Number} [taskid]              任务ID
+     * @apiParam {String} [name]                文件名称
+     * @apiParam {String} [username]            上传者用户名
+     * @apiParam {Object} [sorts]               排序方式,格式:{key:'', order:''}
+     * - key: name|size|username|indate
+     * - order: asc|desc
+     * @apiParam {Number} [page]                当前页,默认:1
+     * @apiParam {Number} [pagesize]            每页显示数量,默认:20,最大:100
+     */
+    public function files__lists()
+    {
+        $user = Users::authE();
+        if (Base::isError($user)) {
+            return $user;
+        } else {
+            $user = $user['data'];
+        }
+        //
+        $projectid = intval(Request::input('projectid'));
+        $inRes = Project::inThe($projectid, $user['username']);
+        if (Base::isError($inRes)) {
+            return $inRes;
+        }
+        //
+        $orderBy = '`id` DESC';
+        $sorts = Base::json2array(Request::input('sorts'));
+        if (in_array($sorts['key'], ['asc', 'desc'])) {
+            switch ($sorts['key']) {
+                case 'name':
+                case 'size':
+                case 'download':
+                case 'username':
+                case 'indate':
+                    $orderBy = '`' . $sorts['key'] . '` ' . $sorts['key'] . ',`id` DESC';
+                    break;
+            }
+        }
+        //
+        $whereArray = [];
+        $whereArray[] = ['projectid', '=', $projectid];
+        $whereArray[] = ['delete', '=', 0];
+        if (intval(Request::input('taskid')) > 0) {
+            $whereArray[] = ['taskid', '=', intval(Request::input('taskid'))];
+        }
+        if (trim(Request::input('name'))) {
+            $whereArray[] = ['name', 'like', '%' . trim(Request::input('name')) . '%'];
+        }
+        if (trim(Request::input('username'))) {
+            $whereArray[] = ['username', '=', trim(Request::input('username'))];
+        }
+        //
+        $lists = DB::table('project_files')
+            ->where($whereArray)
+            ->orderByRaw($orderBy)->paginate(Min(Max(Base::nullShow(Request::input('pagesize'), 10), 1), 100));
+        $lists = Base::getPageList($lists);
+        if ($lists['total'] == 0) {
+            return Base::retError('未找到任何相关的文件', $lists);
+        }
+        foreach ($lists['lists'] AS $key => $item) {
+            $lists['lists'][$key]['path'] = Base::fillUrl($item['path']);
+            $lists['lists'][$key]['thumb'] = Base::fillUrl($item['thumb']);
+            $lists['lists'][$key]['yetdown'] = intval(Session::get('filesDownload:' . $item['id']));
+        }
+        return Base::retSuccess('success', $lists);
+    }
+
+    /**
+     * 项目文件-上传
+     *
+     * @apiParam {Number} projectid             项目ID
+     * @apiParam {Number} [taskid]              任务ID
+     */
+    public function files__upload()
+    {
+        $user = Users::authE();
+        if (Base::isError($user)) {
+            return $user;
+        } else {
+            $user = $user['data'];
+        }
+        //
+        $projectid = intval(Request::input('projectid'));
+        $taskid = intval(Request::input('taskid'));
+        $inRes = Project::inThe($projectid, $user['username']);
+        if (Base::isError($inRes)) {
+            return $inRes;
+        }
+        //
+        $data = Base::upload([
+            "file" => Request::file('files'),
+            "type" => 'file',
+            "path" => "uploads/projects/" . $projectid . "/",
+        ]);
+        if (Base::isError($data)) {
+            return Base::retError($data['msg']);
+        } else {
+            $fileData = $data['data'];
+            $thumb = 'images/files/file.png';
+            switch ($fileData['ext']) {
+                case "docx":
+                    $thumb = 'images/files/doc.png';
+                    break;
+                case "xlsx":
+                    $thumb = 'images/files/xls.png';
+                    break;
+                case "pptx":
+                    $thumb = 'images/files/ppt.png';
+                    break;
+                case "doc":
+                case "xls":
+                case "ppt":
+                case "txt":
+                case "esp":
+                case "gif":
+                    $thumb = 'images/files/' . $fileData['ext'] . '.png';
+                    break;
+                case "jpg":
+                case "jpeg":
+                case "png":
+                    if (Base::imgThumb($fileData['file'], $fileData['file'] . "_thumb.jpg", 64, 0)) {
+                        $thumb = $fileData['path'] . "_thumb.jpg";
+                    }
+                    break;
+            }
+            $array = [
+                'projectid' => $projectid,
+                'taskid' => $taskid,
+                'name' => $fileData['name'],
+                'size' => $fileData['size'] * 1024,
+                'ext' => $fileData['ext'],
+                'path' => $fileData['path'],
+                'thumb' => $thumb,
+                'username' => $user['username'],
+                'indate' => Base::time(),
+            ];
+            $id = DB::table('project_files')->insertGetId($array);
+            $array['id'] = $id;
+            $array['path'] = Base::fillUrl($array['path']);
+            $array['thumb'] = Base::fillUrl($array['thumb']);
+            $array['yetdown'] = 0;
+            return Base::retSuccess('success', $array);
+        }
+    }
+
+    /**
+     * 项目文件-上传
+     *
+     * @apiParam {Number} fileid                文件ID
+     */
+    public function files__download()
+    {
+        $row = Base::DBC2A(DB::table('project_files')->where('id', intval(Request::input('fileid')))->where('delete', 0)->first());
+        if (empty($row)) {
+            return abort(404, '文件不存在或已被删除!');
+        }
+        $filePath = public_path($row['path']);
+        if (!file_exists($filePath)) {
+            return abort(404, '文件不存在或已被删除。');
+        }
+        if (intval(Session::get('filesDownload:' . $row['id'])) !== 1) {
+            Session::put('filesDownload:' . $row['id'], 1);
+            DB::table('project_files')->where('id', $row['id'])->increment('download');
+        }
+        return response()->download($filePath, $row['name']);
+    }
+
+    /**
+     * 项目文件-重命名
+     *
+     * @apiParam {Number} fileid                文件ID
+     * @apiParam {String} name                  新文件名称
+     */
+    public function files__rename()
+    {
+        $user = Users::authE();
+        if (Base::isError($user)) {
+            return $user;
+        } else {
+            $user = $user['data'];
+        }
+        //
+        $fileDetail = Base::DBC2A(DB::table('project_files')->where('id', intval(Request::input('fileid')))->where('delete', 0)->first());
+        if (empty($fileDetail)) {
+            return Base::retError('文件不存在或已被删除!');
+        }
+        if ($fileDetail['username'] != $user['username']) {
+            $inRes = Project::inThe($fileDetail['projectid'], $user['username'], true);
+            if (Base::isError($inRes)) {
+                return Base::retError('此操作仅支持管理员或上传者!');
+            }
+        }
+        //
+        $name = Base::rightDelete(trim(Request::input('name')), '.' . $fileDetail['ext']);
+        if (empty($name)) {
+            return Base::retError('文件名称不能为空!');
+        } elseif (mb_strlen($name) > 32) {
+            return Base::retError('文件名称最多只能设置32个字!');
+        }
+        //
+        $name .= '.' . $fileDetail['ext'];
+        if (DB::table('project_files')->where('id', $fileDetail['id'])->update([ 'name' => $name ])) {
+            DB::table('project_log')->insert([
+                'type' => '日志',
+                'projectid' => $fileDetail['projectid'],
+                'taskid' => $fileDetail['taskid'],
+                'username' => $user['username'],
+                'detail' => '文件【' . $fileDetail['name'] . '(' . $fileDetail['id'] . ')】重命名【' . $name . '】',
+                'indate' => Base::time()
+            ]);
+        }
+        //
+        return Base::retSuccess('修改成功', [
+            'name' => $name,
+        ]);
+    }
+
+    /**
+     * 项目文件-删除
+     *
+     * @apiParam {Number} fileid                文件ID
+     */
+    public function files__delete()
+    {
+        $user = Users::authE();
+        if (Base::isError($user)) {
+            return $user;
+        } else {
+            $user = $user['data'];
+        }
+        //
+        $fileDetail = Base::DBC2A(DB::table('project_files')->where('id', intval(Request::input('fileid')))->where('delete', 0)->first());
+        if (empty($fileDetail)) {
+            return Base::retError('文件不存在或已被删除!');
+        }
+        if ($fileDetail['username'] != $user['username']) {
+            $inRes = Project::inThe($fileDetail['projectid'], $user['username'], true);
+            if (Base::isError($inRes)) {
+                return Base::retError('此操作仅支持管理员或上传者!');
+            }
+        }
+        //
+        DB::table('project_files')->where('id', $fileDetail['id'])->update([
+            'delete' => 1,
+            'deletedate' => Base::time()
+        ]);
+        DB::table('project_log')->insert([
+            'type' => '日志',
+            'projectid' => $fileDetail['projectid'],
+            'taskid' => $fileDetail['taskid'],
+            'username' => $user['username'],
+            'detail' => '删除文件【' . $fileDetail['name'] . '(' . $fileDetail['id'] . ')】',
+            'indate' => Base::time()
+        ]);
+        //
+        return Base::retSuccess('删除成功');
+    }
 }

+ 3 - 0
app/Http/Middleware/VerifyCsrfToken.php

@@ -14,5 +14,8 @@ class VerifyCsrfToken extends Middleware
     protected $except = [
         //上传图片
         'api/imgupload/',
+
+        //上传项目文件
+        'api/project/files/upload/',
     ];
 }

+ 5 - 1
app/Module/Base.php

@@ -1794,7 +1794,7 @@ class Base
     /**
      * 上传文件
      * @param array $param [ type=[文件类型], file=>Request::file, path=>文件路径, fileName=>文件名称, scale=>[压缩原图宽,高, 压缩方式], size=>限制大小KB, autoThumb=>false不要自动生成缩略图 ]
-     * @return array [name=>原文件名, size=>文件大小(单位KB),file=>绝对地址, path=>相对地址, url=>全路径地址]
+     * @return array [name=>原文件名, size=>文件大小(单位KB),file=>绝对地址, path=>相对地址, url=>全路径地址, ext=>文件后缀名]
      */
     public static function upload($param)
     {
@@ -1830,6 +1830,9 @@ class Base
                 case 'zip':
                     $type = ['zip'];
                     break;
+                case 'file':
+                    $type = ['jpg', 'jpeg', 'png', 'gif', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'txt', 'esp'];
+                    break;
                 default:
                     return Base::retError('错误的类型参数');
             }
@@ -1873,6 +1876,7 @@ class Base
                 "thumb" => '',                                          //缩略图(预览图)               "https://.....hhsKzZ.jpg_thumb.jpg"
                 "width" => -1,                                          //图片宽度
                 "height" => -1,                                         //图片高度
+                "ext" => $extension,                                    //文件后缀名
             ];
             if (!is_file($array['file'])) {
                 return Base::retError('上传失败!');

+ 10 - 5
app/Module/Project.php

@@ -14,19 +14,24 @@ class Project
      * 是否在项目里
      * @param int $projectid
      * @param string $username
+     * @param bool $isowner
      * @return array
      */
-    public static function inThe($projectid, $username)
+    public static function inThe($projectid, $username, $isowner = false)
     {
-        $count = DB::table('project_users')->where([
+        $whereArray = [
             'type' => '成员',
             'projectid' => $projectid,
             'username' => $username,
-        ])->count();
-        if ($count <= 0) {
+        ];
+        if ($isowner) {
+            $whereArray['isowner'] = 1;
+        }
+        $row = Base::DBC2A(DB::table('project_users')->select(['isowner', 'indate'])->where($whereArray)->first());
+        if (empty($row)) {
             return Base::retError('你不在项目成员内!');
         } else {
-            return Base::retSuccess('你在项目内');
+            return Base::retSuccess('你在项目内', $row);
         }
     }
 

+ 41 - 0
package-lock.json

@@ -2357,6 +2357,16 @@
             "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==",
             "dev": true
         },
+        "clipboard": {
+            "version": "2.0.6",
+            "resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.6.tgz",
+            "integrity": "sha512-g5zbiixBRk/wyKakSwCKd7vQXDjFnAMGHoEyBogG/bw9kTD9GvdAvaoRR1ALcEzt3pVKxZR0pViekPMIS0QyGg==",
+            "requires": {
+                "good-listener": "^1.2.2",
+                "select": "^1.1.2",
+                "tiny-emitter": "^2.0.0"
+            }
+        },
         "cliui": {
             "version": "5.0.0",
             "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz",
@@ -3237,6 +3247,11 @@
             "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
             "dev": true
         },
+        "delegate": {
+            "version": "3.2.0",
+            "resolved": "https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz",
+            "integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw=="
+        },
         "delegates": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
@@ -4588,6 +4603,14 @@
                 "minimatch": "~3.0.2"
             }
         },
+        "good-listener": {
+            "version": "1.2.2",
+            "resolved": "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz",
+            "integrity": "sha1-1TswzfkxPf+33JoNR3CWqm0UXFA=",
+            "requires": {
+                "delegate": "^3.1.2"
+            }
+        },
         "graceful-fs": {
             "version": "4.2.4",
             "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz",
@@ -8658,6 +8681,11 @@
                 }
             }
         },
+        "select": {
+            "version": "1.1.2",
+            "resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz",
+            "integrity": "sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0="
+        },
         "select-hose": {
             "version": "2.0.0",
             "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz",
@@ -9802,6 +9830,11 @@
             "integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=",
             "dev": true
         },
+        "tiny-emitter": {
+            "version": "2.1.0",
+            "resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz",
+            "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q=="
+        },
         "tinycolor2": {
             "version": "1.4.1",
             "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.4.1.tgz",
@@ -10285,6 +10318,14 @@
             "integrity": "sha512-VfPwgcGABbGAue9+sfrD4PuwFar7gPb1yl1UK1MwXoQPAw0BKSqWfoYCT/ThFrdEVWoI51dBuyCoiNU9bZDZxQ==",
             "dev": true
         },
+        "vue-clipboard2": {
+            "version": "0.3.1",
+            "resolved": "https://registry.npmjs.org/vue-clipboard2/-/vue-clipboard2-0.3.1.tgz",
+            "integrity": "sha512-H5S/agEDj0kXjUb5GP2c0hCzIXWRBygaWLN3NEFsaI9I3uWin778SFEMt8QRXiPG+7anyjqWiw2lqcxWUSfkYg==",
+            "requires": {
+                "clipboard": "^2.0.0"
+            }
+        },
         "vue-hot-reload-api": {
             "version": "2.3.4",
             "resolved": "https://registry.npmjs.org/vue-hot-reload-api/-/vue-hot-reload-api-2.3.4.tgz",

+ 2 - 1
package.json

@@ -31,6 +31,7 @@
     "dependencies": {
         "tinymce": "^5.2.2",
         "view-design": "^4.2.0",
-        "vuedraggable": "^2.23.2"
+        "vuedraggable": "^2.23.2",
+        "vue-clipboard2": "^0.3.1"
     }
 }

+ 16 - 0
resources/assets/js/common.js

@@ -1505,6 +1505,22 @@
             }
             return $A.formatDate("Y-m-d", parseInt(time / 1000))
         },
+
+        /**
+         * 字节转换
+         * @param bytes
+         * @returns {string}
+         */
+        bytesToSize(bytes) {
+            if (bytes === 0) return '0 B';
+            let k = 1024;
+            let sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
+            let i = Math.floor(Math.log(bytes) / Math.log(k));
+            if (typeof sizes[i] === "undefined") {
+                return '0 B';
+            }
+            return $A.runNum((bytes / Math.pow(k, i)), 2) + ' ' + sizes[i];
+        },
     });
 
     window.$A = $;

+ 1 - 1
resources/assets/js/main/components/project/complete.vue

@@ -85,7 +85,7 @@
                                             },
                                             error: () => {
                                                 this.$Modal.remove();
-                                                this.$Message.error(this.$L('网络繁忙,请稍后再试!'));
+                                                alert(this.$L('网络繁忙,请稍后再试!'));
                                             },
                                             success: (res) => {
                                                 this.$Modal.remove();

+ 1 - 1
resources/assets/js/main/components/project/task/add.vue

@@ -207,7 +207,7 @@
                         this.loadIng--;
                     },
                     error: () => {
-                        this.$Message.error(this.$L('网络繁忙,请稍后再试!'));
+                        alert(this.$L('网络繁忙,请稍后再试!'));
                     },
                     success: (res) => {
                         if (res.ret === 1) {

+ 471 - 0
resources/assets/js/main/components/project/task/files.vue

@@ -0,0 +1,471 @@
+<template>
+    <div class="project-task-file">
+
+        <!-- 搜索 -->
+        <Row class="sreachBox">
+            <div class="item">
+                <div class="item-2">
+                    <sreachTitle :val="keys.name">文件名</sreachTitle>
+                    <Input v-model="keys.name" placeholder="关键词"/>
+                </div>
+                <div class="item-2">
+                    <sreachTitle :val="keys.username">上传者</sreachTitle>
+                    <Input v-model="keys.username" placeholder="用户名"/>
+                </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 type="primary">
+            </div>
+        </Row>
+
+        <!-- 按钮 -->
+        <Row class="butBox" style="float:left;margin-top:-32px;">
+            <Upload
+                name="files"
+                ref="upload"
+                :action="actionUrl"
+                :data="params"
+                multiple
+                :format="uploadFormat"
+                :show-upload-list="false"
+                :max-size="10240"
+                :on-success="handleSuccess"
+                :on-format-error="handleFormatError"
+                :on-exceeded-size="handleMaxSize">
+                <Button :loading="loadIng > 0" type="primary" icon="ios-cloud-upload-outline" @click="">上传文件</Button>
+            </Upload>
+        </Row>
+
+        <!-- 列表 -->
+        <Table class="tableFill" ref="tableRef" :columns="columns" :data="lists" :loading="loadIng > 0" :no-data-text="noDataText" @on-sort-change="sortChange" 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-file {
+        margin: 0 12px;
+        .tableFill {
+            margin: 12px 0 20px;
+        }
+    }
+</style>
+
+<script>
+    import Vue from 'vue'
+    import VueClipboard from 'vue-clipboard2'
+    import WLoading from '../../../components/WLoading'
+
+    Vue.use(VueClipboard)
+    Vue.component('WLoading', WLoading);
+
+    export default {
+        name: 'ProjectTaskFiles',
+        props: {
+            projectid: {
+                default: 0
+            },
+            canload: {
+                type: Boolean,
+                default: true
+            },
+        },
+        data() {
+            return {
+                keys: {},
+                sorts: {key:'', order:''},
+
+                loadYet: false,
+
+                loadIng: 0,
+
+                columns: [],
+
+                lists: [],
+                listPage: 1,
+                listTotal: 0,
+                noDataText: "数据加载中.....",
+
+                uploadFormat: ['jpg', 'jpeg', 'png', 'gif', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'txt'],
+                actionUrl: $A.aUrl('project/files/upload'),
+                params: {'token': $A.token(), projectid:this.projectid},
+                uploadList: [],
+            }
+        },
+
+        created() {
+            this.columns = [{
+                "title": "",
+                "width": 60,
+                render: (h, params) => {
+                    if (!params.row.thumb) {
+                        return h('WLoading', {
+                            style: {
+                                width: "24px",
+                                height: "24px",
+                                verticalAlign: "middle",
+                            },
+                        });
+                    }
+                    return h('img', {
+                        style: {
+                            width: "28px",
+                            height: "28px",
+                            verticalAlign: "middle",
+                        },
+                        attrs: {
+                            src: params.row.thumb
+                        },
+                    });
+                }
+            }, {
+                "title": "文件名",
+                "key": 'name',
+                "minWidth": 100,
+                "tooltip": true,
+                "sortable": true,
+                render: (h, params) => {
+                    let arr = [h('span', params.row.name)];
+                    if (params.row.showProgress === true) {
+                        arr.push(h('Progress', {
+                            style: {
+                                display: 'block',
+                                marginTop: '-3px'
+                            },
+                            props: {
+                                percent: params.row.percentage || 100,
+                            },
+                        }));
+                    }
+                    return h('div', arr);
+                },
+            }, {
+                "title": "大小",
+                "key": 'size',
+                "minWidth": 90,
+                "maxWidth": 120,
+                "align": "right",
+                "sortable": true,
+                render: (h, params) => {
+                    return h('span', $A.bytesToSize(params.row.size));
+                },
+            }, {
+                "title": "下载次数",
+                "key": 'download',
+                "align": "center",
+                "sortable": true,
+                "width": 100,
+            }, {
+                "title": "上传者",
+                "key": 'username',
+                "minWidth": 90,
+                "maxWidth": 130,
+                "sortable": true,
+            }, {
+                "title": "上传时间",
+                "key": 'indate',
+                "width": 160,
+                "sortable": true,
+                render: (h, params) => {
+                    return h('span', $A.formatDate("Y-m-d H:i:s", params.row.indate));
+                }
+            }, {
+                "title": " ",
+                "key": 'action',
+                "align": 'right',
+                "width": 120,
+                render: (h, params) => {
+                    if (!params.row.id) {
+                        return null;
+                    }
+                    return h('div', [
+                        h('Tooltip', {
+                            props: { content: '下载', transfer: true, delay: 600 },
+                            style: { position: 'relative' },
+                        }, [h('Icon', {
+                            props: { type: 'md-arrow-down' },
+                            style: { margin: '0 3px', cursor: 'pointer' },
+                        }), h('a', {
+                            style: { position: 'absolute', top: '0', left: '0', right: '0', bottom: '0', 'zIndex': 1 },
+                            attrs: { href: $A.aUrl('project/files/download?fileid=' + params.row.id), target: '_blank' },
+                            on: {
+                                click: () => {
+                                    if (params.row.yetdown) {
+                                        return;
+                                    }
+                                    params.row.yetdown = 1;
+                                    this.$set(params.row, 'download', params.row.download + 1);
+                                }
+                            }
+                        })]),
+                        h('Tooltip', {
+                            props: { content: '重命名', transfer: true, delay: 600 }
+                        }, [h('Icon', {
+                            props: { type: 'md-create' },
+                            style: { margin: '0 3px', cursor: 'pointer' },
+                            on: {
+                                click: () => {
+                                    this.renameFile(params.row);
+                                }
+                            }
+                        })]),
+                        h('Tooltip', {
+                            props: { content: '复制链接', transfer: true, delay: 600 }
+                        }, [h('Icon', {
+                            props: { type: 'md-link' },
+                            style: { margin: '0 3px', cursor: 'pointer', transform: 'rotate(-45deg)' },
+                            on: {
+                                click: () => {
+                                    this.$copyText($A.aUrl('project/files/download?fileid=' + params.row.id)).then(() => {
+                                        this.$Message.success(this.$L('复制成功!'));
+                                    }, () => {
+                                        this.$Message.error(this.$L('复制失败!'));
+                                    });
+                                }
+                            }
+                        })]),
+                        h('Tooltip', {
+                            props: { content: '删除', transfer: true, delay: 600 }
+                        }, [h('Icon', {
+                            props: { type: 'md-trash' },
+                            style: { margin: '0 3px', cursor: 'pointer' },
+                            on: {
+                                click: () => {
+                                    this.deleteFile(params.row);
+                                }
+                            }
+                        })]),
+                    ]);
+                }
+            }];
+        },
+
+        mounted() {
+            if (this.canload) {
+                this.loadYet = true;
+                this.getLists(true);
+            }
+            this.uploadList = this.$refs.upload.fileList;
+        },
+
+        watch: {
+            projectid() {
+                if (this.loadYet) {
+                    this.getLists(true);
+                }
+            },
+            canload(val) {
+                if (val && !this.loadYet) {
+                    this.loadYet = true;
+                    this.getLists(true);
+                }
+            },
+            uploadList(files) {
+                files.forEach((file) => {
+                    if (typeof file.username === "undefined") {
+                        file.username = $A.getUserName();
+                        file.indate = Math.round(new Date().getTime()/1000);
+                        this.lists.unshift(file)
+                    }
+                });
+            }
+        },
+
+        methods: {
+            sreachTab(clear) {
+                if (clear === true) {
+                    this.keys = {};
+                }
+                this.getLists(true);
+            },
+
+            sortChange(info) {
+                this.sorts = {key:info.key, order:info.order};
+                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;
+                whereData.sorts = this.sorts;
+                $A.aAjax({
+                    url: 'project/files/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;
+                        }
+                    }
+                });
+            },
+
+            renameFile(item) {
+                this.renameValue = "";
+                this.$Modal.confirm({
+                    render: (h) => {
+                        return h('div', [
+                            h('div', {
+                                style: {
+                                    fontSize: '16px',
+                                    fontWeight: '500',
+                                    marginBottom: '20px',
+                                }
+                            }, '重命名文件名'),
+                            h('Input', {
+                                props: {
+                                    value: this.renameValue,
+                                    autofocus: true,
+                                    placeholder: item.name || '请输入新的文件名称'
+                                },
+                                on: {
+                                    input: (val) => {
+                                        this.renameValue = val;
+                                    }
+                                }
+                            })
+                        ])
+                    },
+                    loading: true,
+                    onOk: () => {
+                        if (this.renameValue) {
+                            let oldName = item.name;
+                            let newName = this.renameValue;
+                            if (!$A.rightExists(newName, '.' + item.ext)) {
+                                newName += '.' + item.ext;
+                            }
+                            this.$set(item, 'name', newName);
+                            $A.aAjax({
+                                url: 'project/files/rename',
+                                data: {
+                                    fileid: item.id,
+                                    name: newName,
+                                },
+                                error: () => {
+                                    this.$Modal.remove();
+                                    this.$set(item, 'name', oldName);
+                                    alert(this.$L('网络繁忙,请稍后再试!'));
+                                },
+                                success: (res) => {
+                                    this.$Modal.remove();
+                                    if (res.ret === 1) {
+                                        this.$set(item, 'name', res.data.name);
+                                    } else {
+                                        this.$Modal.error({title: this.$L('温馨提示'), content: res.msg});
+                                        this.$set(item, 'name', oldName);
+                                    }
+                                }
+                            });
+                        } else {
+                            this.$Modal.remove();
+                        }
+                    },
+                });
+            },
+
+            deleteFile(item) {
+                this.$Modal.confirm({
+                    title: '删除文件',
+                    content: '你确定要删除此文件吗?',
+                    loading: true,
+                    onOk: () => {
+                        $A.aAjax({
+                            url: 'project/files/delete',
+                            data: {
+                                fileid: item.id,
+                            },
+                            error: () => {
+                                this.$Modal.remove();
+                                alert(this.$L('网络繁忙,请稍后再试!'));
+                            },
+                            success: (res) => {
+                                this.$Modal.remove();
+                                this.lists.some((temp, index) => {
+                                    if (temp.id == item.id) {
+                                        this.lists.splice(index, 1);
+                                        return true;
+                                    }
+                                });
+                                setTimeout(() => {
+                                    if (res.ret === 1) {
+                                        this.$Message.success(res.msg);
+                                    } else {
+                                        this.$Modal.error({title: this.$L('温馨提示'), content: res.msg });
+                                    }
+                                }, 350);
+                            }
+                        });
+                    }
+                });
+            },
+
+            handleSuccess (res, file) {
+                //上传完成
+                if (res.ret === 1) {
+                    for (let key in res.data) {
+                        if (res.data.hasOwnProperty(key)) {
+                            file[key] = res.data[key];
+                        }
+                    }
+                } else {
+                    this.$Modal.warning({
+                        title: '上传失败',
+                        content: '文件 ' + file.name + ' 上传失败,' + res.msg
+                    });
+                    this.$refs.upload.fileList.pop();
+                }
+                this.uploadList = this.$refs.upload.fileList;
+            },
+
+            handleFormatError (file) {
+                //上传类型错误
+                this.$Modal.warning({
+                    title: '文件格式不正确',
+                    content: '文件 ' + file.name + ' 格式不正确,仅支持上传:' + this.uploadFormat.join(',') + '。'
+                });
+            },
+
+            handleMaxSize (file) {
+                //上传大小错误
+                this.$Modal.warning({
+                    title: '超出文件大小限制',
+                    content: '文件 ' + file.name + ' 太大,不能超过 2M。'
+                });
+            },
+        }
+    }
+</script>

+ 2 - 2
resources/assets/js/main/components/project/users.vue

@@ -120,7 +120,7 @@
                                             },
                                             error: () => {
                                                 this.$Modal.remove();
-                                                this.$Message.error(this.$L('网络繁忙,请稍后再试!'));
+                                                alert(this.$L('网络繁忙,请稍后再试!'));
                                             },
                                             success: (res) => {
                                                 this.$Modal.remove();
@@ -249,7 +249,7 @@
                                 },
                                 error: () => {
                                     this.$Modal.remove();
-                                    this.$Message.error(this.$L('网络繁忙,请稍后再试!'));
+                                    alert(this.$L('网络繁忙,请稍后再试!'));
                                 },
                                 success: (res) => {
                                     this.$Modal.remove();

+ 3 - 3
resources/assets/js/main/mixins/project.js

@@ -14,7 +14,7 @@ export default {
                         url: 'project/out?projectid=' + projectid,
                         error: () => {
                             this.$Modal.remove();
-                            this.$Message.error(this.$L('网络繁忙,请稍后再试!'));
+                            alert(this.$L('网络繁忙,请稍后再试!'));
                         },
                         success: (res) => {
                             this.$Modal.remove();
@@ -41,7 +41,7 @@ export default {
                 },
                 error: () => {
                     this.$Modal.remove();
-                    this.$Message.error(this.$L('网络繁忙,请稍后再试!'));
+                    alert(this.$L('网络繁忙,请稍后再试!'));
                 },
                 success: (res) => {
                     this.$Modal.remove();
@@ -67,7 +67,7 @@ export default {
                         url: 'project/delete?projectid=' + projectid,
                         error: () => {
                             this.$Modal.remove();
-                            this.$Message.error(this.$L('网络繁忙,请稍后再试!'));
+                            alert(this.$L('网络繁忙,请稍后再试!'));
                         },
                         success: (res) => {
                             this.$Modal.remove();

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

@@ -79,6 +79,7 @@
                     <project-task-lists :canload="projectDrawerShow && projectDrawerTab == 'lists'" :projectid="projectid" :labelLists="projectSimpleLabel"></project-task-lists>
                 </TabPane>
                 <TabPane :label="$L('文件列表')" name="files">
+                    <project-task-files :canload="projectDrawerShow && projectDrawerTab == 'files'" :projectid="projectid"></project-task-files>
                 </TabPane>
                 <TabPane :label="$L('项目动态')" name="logs">
                 </TabPane>
@@ -313,9 +314,10 @@
     import WLoading from "../components/WLoading";
     import ProjectAddTask from "../components/project/task/add";
     import ProjectTaskLists from "../components/project/task/lists";
+    import ProjectTaskFiles from "../components/project/task/files";
 
     export default {
-        components: {ProjectTaskLists, ProjectAddTask, draggable, WLoading, WContent, WHeader},
+        components: {ProjectTaskFiles, ProjectTaskLists, ProjectAddTask, draggable, WLoading, WContent, WHeader},
         data () {
             return {
                 loadIng: 0,
@@ -364,8 +366,8 @@
                         this.loadDetailed = true;
                     },
                     error: () => {
-                        this.$Message.error(this.$L('网络繁忙,请稍后再试!'));
                         this.goBack();
+                        alert(this.$L('网络繁忙,请稍后再试!'));
                     },
                     success: (res) => {
                         if (res.ret === 1) {
@@ -463,7 +465,7 @@
                                 },
                                 error: () => {
                                     this.$Modal.remove();
-                                    this.$Message.error(this.$L('网络繁忙,请稍后再试!'));
+                                    alert(this.$L('网络繁忙,请稍后再试!'));
                                 },
                                 success: (res) => {
                                     this.$Modal.remove();
@@ -499,7 +501,7 @@
                             },
                             error: () => {
                                 this.$Modal.remove();
-                                this.$Message.error(this.$L('网络繁忙,请稍后再试!'));
+                                alert(this.$L('网络繁忙,请稍后再试!'));
                             },
                             success: (res) => {
                                 this.$Modal.remove();
@@ -559,7 +561,7 @@
                                 },
                                 error: () => {
                                     this.$Modal.remove();
-                                    this.$Message.error(this.$L('网络繁忙,请稍后再试!'));
+                                    alert(this.$L('网络繁忙,请稍后再试!'));
                                 },
                                 success: (res) => {
                                     this.$Modal.remove();

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

@@ -565,7 +565,7 @@
                                 },
                                 error: () => {
                                     this.$Modal.remove();
-                                    this.$Message.error(this.$L('网络繁忙,请稍后再试!'));
+                                    alert(this.$L('网络繁忙,请稍后再试!'));
                                 },
                                 success: (res) => {
                                     this.$Modal.remove();
@@ -627,7 +627,7 @@
                                 },
                                 error: () => {
                                     this.$Modal.remove();
-                                    this.$Message.error(this.$L('网络繁忙,请稍后再试!'));
+                                    alert(this.$L('网络繁忙,请稍后再试!'));
                                 },
                                 success: (res) => {
                                     this.$Modal.remove();

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

@@ -197,7 +197,7 @@
                                                 url: 'users/team/delete?id=' + params.row.id,
                                                 error: () => {
                                                     this.$Modal.remove();
-                                                    this.$Message.error(this.$L('网络繁忙,请稍后再试!'));
+                                                    alert(this.$L('网络繁忙,请稍后再试!'));
                                                 },
                                                 success: (res) => {
                                                     this.$Modal.remove();