前端那些事之vue+iview 原

iview UI或者element UI 實現回車鍵盤登入系統

  • 綁定事件用 @keyup.enter.native="方法名"
<Form-item label="密碼" prop="password">
                <Input type="password" v-model="formLogin.password"         
                  @keyup.enter.native="handleLogin('formLogin')">
                    <Icon type="ios-locked-outline" slot="prepend"></Icon>
                </Input>
 </Form-item>

<script>
import store from '../../store';
export default {
    data () {
        return {
            loading:false,
            formLogin: {
                username: '',
                password: ''
            },
            ruleLogin: {
                username: [
                    { required: true, message: '請填寫用戶名', trigger: 'blur' }
                ],
                password: [
                    { required: true, message: '請填寫密碼', trigger: 'blur' },
                    { type: 'string', min: 4, message: '密碼長度不能小於6位', trigger: 'blur' }
                ]
            },
        }
    },
    created:function(){

    },
    methods: {
        handleLogin(name) {
            this.$refs[name].validate((valid) => {
                if (valid) {
                    this.loading = true;
                    this.$store.dispatch('Login', this.formLogin).then(response => {
                        this.loading = false;
                        this.$router.push({ path: '/space/person' })
                    },(response)=>{
                        this.loading = false;
                        this.$Message.error(response.data.message);
                    }).catch(err => {
                        this.loading = false;
                    });
                } else {
                    this.loading = false;
                    this.$Message.error('表單驗證失敗!');
                }
            })
        },
        handleReset(name) {
            this.loading = false;
            this.$refs[name].resetFields();
        },

    }
}
</script>
  • 記住密碼功能(利用cookie)
  data() {
    return {
      loading: false,
      formLogin: {
        username: "",
        password: ""
      },
      checked:true,
      ruleLogin: {
        username: [{ required: true, message: "請填寫用戶名", trigger: "blur" }],
        password: [
          { required: true, message: "請填寫密碼", trigger: "blur" },
          { type: "string", min: 4, message: "密碼長度不能小於6位", trigger: "blur" }
        ]
      }
    };
  },
  methods: {
    handleLogin(name) {
      this.$refs[name].validate(valid => {
        if (valid) {
          this.loading = true;
          this.$store
            .dispatch("Login", this.formLogin)
            .then(
              response => {
                this.loading = false;
                this.$router.push({ path: "/space/person" });
                if(this.checked) {
                  Cookies.set("username", this.formLogin.username, {
                    expires: 7
                  })
                  Cookies.set("password", this.formLogin.password, {
                    expires: 7
                  })
                }else{
                  Cookies.remove("username");
                  Cookies.remove("password");
                }
              },
              response => {
                this.loading = false;
                this.$Message.error(response.data.message);
              }
            )
            .catch(err => {
              this.loading = false;
            });
        } else {
          this.loading = false;
          this.$Message.error("表單驗證失敗!");
        }
      });
    },
    handleReset(name) {
      this.loading = false;
      this.$refs[name].resetFields();
    },

  },
  mounted(){
    let username = Cookies.get("username")
    let password = Cookies.get("password")
    this.formLogin = {
      username: username,
      password: password
    };
  }

vue2.0用jsx語法

  • 第一步下載:
npm install\
  babel-plugin-syntax-jsx\
  babel-plugin-transform-vue-jsx\
  babel-helper-vue-jsx-merge-props\
  babel-preset-es2015\
  --save-dev
  • 第二步在.babelrc添加配置項
{
  "presets": ["es2015"],
  "plugins": ["transform-vue-jsx"]
}

完整的配置如下:

{
  "presets": [
    ["env", {
      "modules": false,
      "targets": {
        "browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
      }
    }],
    "stage-2",
    "es2015"
  ],
  "plugins": [
    "transform-runtime",
    "transform-vue-jsx"
  ],
  "env": {
    "test": {
      "presets": ["env", "stage-2"],
      "plugins": ["istanbul"]
    }
  }
}

  • 具體用法 :在vue render涵數中渲染
render:(h,params)=>{
                    let iconType = params.row.isFile==true ? 'document' : 'folder';
                    let id = params.row.id;
                    let name = params.row.name;
                    let isFile = params.row.isFile;
                    return(
                        <div onClick={()=>this.showDetail(id,isFile)} style={{cursor:'pointer'}}>
                            <Icon type={iconType} style={{ fontSize:'16px'}}></Icon>
                        <span domPropsInnerHTML={name} style={{ marginLeft:'5px',cursor:'pointer'}} onClick=    
                       {(e)=>this.handleResource(id,isFile,e)}></span>
                        </div>
                    )
                }

iview 中動態引用Dropdown組件無法綁定事件

  • 只能用onOn-click={(name,id)=>this.changeSelected(name,resourceId)}
  • 例如:
return (
                        <div style={{ textAlign: 'left' }}>
                            <span style={{ color: '#ccc', display:'inline-block', width:'120px' }}>{fromInfo}</span>

                            {
                                canShare ? 
                                <Button type="text" onClick={()=>this.getShare(isFile,resourceId,resourceName)}>
                                    <Icon size='16' type="android-share-alt"></Icon>
                                </Button>
                                :
                                <Button type="text" disabled>
                                    <Icon size='16' type="android-share-alt"></Icon>
                                </Button>
                            }
                                
                            <a href={resourceURL} style={{ marginRight:'13px'}}><Icon size='16' type="android-download"></Icon></a>
                                 
                            <Dropdown placement="bottom-start" onOn-click={(name,id)=>this.changeSelected(name,resourceId)}>
                                <Icon type="more"></Icon>
                                <Dropdown.Menu slot="list">
                                    <Dropdown.Item name='copy'>Copy</Dropdown.Item>
                                    <Dropdown.Item name='move'>Move</Dropdown.Item>
                                    {canDelete ? <Dropdown.Item name='delete' >Delete</Dropdown.Item> : ""}
                                </Dropdown.Menu>
                            </Dropdown>
                        </div>
                    );

ivew 中實現 無限層插件

數據格式
//準備數據
                let testData = {
                    "department": [
                        {
                            "departmentName": "測試1",
                            "departmentDesc": "盛達康網絡",
                            "parentId": "",
                            "id": "594a28fb1c8652a01f0301"
                        },
                        {
                            "departmentName": "測試-一級子級",
                            "parentId": "594a28fb1c8652a01f0301",
                            "id": "594a3910202469941"
                        },
                        {
                            "departmentName": "測試-二級子級",
                            "parentId": "594a3910202469941",
                            "id": "594a391020246994asasd1"
                        },
                        {
                            "departmentName": "盛達康",
                            "departmentDesc": "盛達康網絡",
                            "parentId": "",
                            "id": "594a28fb1c8652a01f030126"
                        },
                        {
                            "departmentName": "開發",
                            "parentId": "594a28fb1c8652a01f030126",
                            "id": "594a3910202469941c349d7c"
                        },
                        {
                            "departmentName": "運營",
                            "parentId": "594a28fb1c8652a01f030126",
                            "id": "594a4509202469941c349d7f"
                        },
                      
                    ]
                }

<template>
    <Tree :data="baseData" show-checkbox ></Tree>
</template>
<script>
    export default {
        data () {
            return {
                baseData: []
            }
        },
        methods:{
            getTree(){
                //準備數據
        let testData = null;
        ResourceAPI.getTree(this.moveId).then((response) => {
          let resp = response.data;

          if (resp.success == true) {
            testData = resp.data;

            var data = testData.department
            let treedata = []
            //查找最頂層
            let len = data.length
            for(let j=0;j<len;j++){
              data[j].expand = false;
              data[j].title = data[j].departmentName
              if(data[j].parentId == ""){
                treedata.push({
                  "expand":false,
                  "title":data[j].departmentName,
                  "id":data[j].id
                })
              }
            }
            //找到跟最高層id相關的子子孫孫,並給子孫添加lev
            var treedataLevs =[]
            for(let h=0,ls=treedata.length;h<ls;h++){
              treedataLevs.push({
                treedataLev:sonsTree(data,treedata[h].id)
              })
            }
            for(let p=0,lq=treedataLevs.length;p<lq;p++){
              var treedataLev = treedataLevs[p].treedataLev
              //找到最高層的lev
              var maxLev = 0
              for(let i=0,lt=treedataLev.length;i<lt;i++){
                if(parseInt(treedataLev[i].lev) > maxLev){
                  maxLev = parseInt(treedataLev[i].lev)
                }else{
                  maxLev = maxLev
                }
              }
              //比較當前層和上一層的數據,然後做處理
              var needLev = maxLev
              var maxLevTree = []
              var maxLevTreePrev = []
              for(let m=0;m<maxLev;m++){
                maxLevTree = getLevArr(treedataLev,needLev)
                maxLevTreePrev = getLevArr(treedataLev,needLev-1)
                for(var j=0,lp=maxLevTreePrev.length;j<lp;j++){
                  maxLevTreePrev[j].children = new Array()
                  for(var i=0,lm=maxLevTree;i<lm.length;i++){
                    if(maxLevTree[i].parentId == maxLevTreePrev[j].id){
                      maxLevTreePrev[j].children.push(maxLevTree[i])
                    }
                  }
                }
                needLev--
              }
              treedata[p].children = maxLevTreePrev
            }

            this.baseData = treedata
            //找出同一級的數據
            function getLevArr(arr,lev){
              var newarr = []
              for(let i=0,la=arr.length;i<la;i++){
                //這裏對arr 的children 做處理
                arr.children = new Array()
                if(parseInt(arr[i].lev) == lev){
                  newarr.push(arr[i])
                }
              }
              return newarr
            }
            //給每個數據添加一個lev
            function sonsTree(arr,id){
              var temp = [],lev=0;
              var forFn = function(arr, id,lev){
                for (var i = 0; i < arr.length; i++) {
                  var item = arr[i];
                  if (item.parentId==id) {
                    item.lev=lev;
                    temp.push(item);
                    forFn(arr,item.id,lev+1);
                  }
                }
              };
              forFn(arr, id,lev);
              return temp;
            }


          }
        }).catch(error => {

        });
        },
        created:function(){
            this.getTree()
        }
    }
</script>

iview中用遞歸完成tree的請求

<template>
  <Tree :data="baseData" show-checkbox @on-select-change='movecheck' ></Tree>
</template>
<script>
  import ResourceAPI from 'api/resource';
  export default {
    data () {
      return {
        baseData: [],
        self_id:0,
      }
    },
    methods: {
      getTree(){
        ResourceAPI.getTree().then((response) => {
          let resp = response.data;
          this.baseData=response.data.data;
          if (resp.success == true) {
            let datass = resp.data;

            this.generateFolderTree(datass);
          }
        }).catch(error => {

        });
      },
//      回調函數
      generateFolderTree(datasource){
        datasource.forEach((item,index)=>{
            item.expand = true;
            item.id = item.id;
//            item.disabled=true;
            item.checked=false;
            item.title = item.name;
            if(item.children.length>0) {
              this.generateFolderTree(item.children);
            }
        })
        return datasource;
      },
      movecheck(selfID){
        this.self_id= selfID[0].id;
        //把self_id父組件
        this.$emit('get_move_id',this.self_id);
      }
    },
    created(){
      this.getTree();
    }
  }
</script>

vue自動完成搜索功能的數據請求處理

功能描述一下大概是這個樣子的:有一個搜索框,用戶在裏面輸入要查詢的條件,系統會“智能”判斷用戶輸完了,然後自動根據條件去搜索相關的數據返回給用戶。

網上這個自動完成的插件很多,實現自動完成功能也不復雜,特別是像vue、angularjs、react這類可以實現雙向綁定的庫出現以後,實現就更方便了。本文不講自動完成功能的實現,而是介紹自動完成功能後續數據的請求該如何考慮,主要要處理下面兩個問題。

問題1:自動完成搜索觸發頻率如何控制?

問什麼要控制自動完成搜索的觸發頻率呢?大家都知道,自動完成觸發基本上都是鍵盤響應事件,在文本框中輸入一個文本就觸發一次,這個太頻繁了。比如我要輸入的搜索條件是abcdefg,輸入a觸發一次,接着輸入b再觸發一次,接着輸入c又觸發一次...,等到我把這幾個字母全部輸完就觸發了7次,假設請求邏輯沒有限制的話,這就會發生7次數據請求,而實際上只有第7次的結果纔是我想要的,其它6次數據請求完全是浪費資源。在用戶需求上來說,用戶真正希望的是搜索框能自動識別到用戶的abcdefg這一串字符全部輸入完了,然後再觸發請求數據。對於一些變態的輸入,比如按住某一個建不放,還不知道要觸發多少次。

所以控制自動完成搜索的觸發頻率還是很有必要的。當然,搜索框能完全智能的知道用戶所想然後去觸發,在目前來說還是做不到的。

我這裏使用控制空閒時間的間隔的方式來限制自動完成搜索的觸發頻率。使用lodash庫中的debounce方法。

問題2:數據還在請求中時再次觸發請求,上次的請求如何取消?

爲什麼要取消上次的請求你?舉個例了,我輸入了查詢條件"xxx",數據請求發送了,我們暫且把它稱爲請求1。因爲某些原因(比如說網絡不好,這個條件的數據量大等等),請求1響應很慢,我們在請求1還沒用拿到數據的時候又輸入查詢條件"yyy"發送了請求2,沒想到這個請求2數據響應特別快,一下子就得到了數據data,我們準備把data展示出來,這時候請求1的數據回來了,data會被覆蓋掉,也就是說這時候我們用"yyy"的條件查詢得到了"xxx"條件的查詢結果。這個結果其實是超出用戶期望的。所以在發送新的請求之前,如果上次的請求還沒有結束,我們就需要取消掉它。

我這裏使用axios的CancelToken來取消請求。

  • serach組件的調用
<SearchComponent
                    tip='請輸入搜索內容'
                    search-url='search/'
                    :headers-token="searchHeaders"
                    :space-type="space"
                    :search-type="getSelectValue"
                    @outputResult="handleSearchResult" />
                  </SearchComponent>
  • serach組件的引用
<script>
    import SearchComponent from 'views/public/search.vue';
    export default{
         components:{
           SearchComponent,
    },
     methods:{
          handleSearchResult(item){
                    console.log(item.name+"選中的名稱");
            },
        }
    }

</script>
  • serach組件
<template>
    <div style="width: 100%">

        <Input  icon="ios-search" v-model="keyWord" :placeholder="tip" class="searchInput" @on-change="search(requestUrl,keyWord,resultset,headersToken,spaceType,searchType)" @on-blur="inputKeyWord"></Input>
        <div :class="{resultsetContainer:true, resultsetHide:hideResultset}">
            <div v-for="result in resultset" @click='selectResult(result)' class="result">{{result.value}}</div>
        </div>
    </div>
</template>

<script>
//

import _ from 'lodash'; //引入lodash
import axios from 'axios' //引入axios


//請求canceltoken列表
let sources = [];

export default{
    props:{
        tip:{
            type:String
        },
        searchUrl:{
            type:String
        },
        headersToken:{
            type:Object
        },
        spaceType:{
          type:String
        },
        searchType:{
          type:String
        }
    },
    data(){
        let mockResultset = [
            {id:1, value:'name1'},
            {id:2, value:'name2'},
            {id:3, value:'name3'},
        ];

        let selectedResult = {
            id:0,
            value:''
        }
        return {
            // requestUrl
            requestUrl:process.env.BASE_API+this.searchUrl,

            // search value
            keyWord:'',

            // result
            hideResultset:true,
            selectedResult:selectedResult,
            resultset:mockResultset,


          value1: '',
          data1: []
        }
    },
    watch:{
        resultset:function(newValue, oldValue){
            if(newValue.length > 0){
                this.hideResultset = false;
            }
            else{
                this.hideResultset = true;
            }

        },
    },
    methods:{

      handleSearch1 (value) {
        this.data1 = !value ? [] : [
          value,
          value + value,
          value + value + value
        ];
      },


        // 搜索功能
        // 使用_.debounce控制搜索的觸發頻率, 500ms後執行
        // 準備搜索
        search:_.debounce((url,keyword,resultset,headersToken,spaceType,searchType)=>{
            // 沒有就不搜索
            if(keyword==""){
                resultset.length=0;
            }
            else{
                // 刪除已經結束的請求
                _.remove(sources, (n)=>{
                    return n.source === null;
                })
                //  取消還未結束的請求
                sources.forEach(function (item) {
                    if (item !== null && item.source !== null && item.status === 1) {
                        item.status = 0;
                    }
                });

                //創建新的請求cancelToken,並設置狀態請求中
                var sc = {
                    source: axios.CancelToken.source(),
                    status: 1 //狀態1:請求中,0:取消中
                };

                //這個對象加入數組中
                sources.push(sc);

                //開始搜索數據
                url = url+"?space="+spaceType+"&type="+searchType+"&name="+keyword;

                axios.get( url, {
                    cancelToken: sc.source.token,
                     headers:headersToken
                }).then((res)=> {
                    //請求成功
                    sc.source = null; //置空請求canceltoken
                    res = res.data;
                    if(res.success == true){
                        resultset.length = 0;
                        res.data.results.forEach((item)=>{
                            resultset.push({
                                id:item.id,
                                value:item.name
                            });
                        });
                    }
                }).catch((err)=>{
                    //請求失敗
                    sc.source = null; //置空請求canceltoken
                });
            }
        },500),
        // 當失去對搜索框的焦點
        inputKeyWord(){
            if(this.keyWord==""){
                this.hideResultset = true;
                this.resultset.length = 0;
            }
            else{
                let item = {id:0, value:this.keyWord};
                this.$emit("outputResult", this.keyWord);
            }

            // this.hideResultset = true;
        },
        // 選擇篩選出的節點
        selectResult(item){
            this.keyWord = item.value;
            this.selectedResult = item;

            this.$emit("outputResult", item);
            this.hideResultset = true;

        }
    },

}
</script>

<style scoped>
.searchInput{
    border-radius:0px;
}

.resultsetHide{
    display:none;
}

.resultsetContainer{
    border:1px solid #dddee1;
    border-top:none;
    height:100px;
    overflow: auto;
    /*box-shadow: 2px 2px 1px #888888;*/
}

.result{
    padding:2px 5px;
}

.result:hover{
    background-color:#f8f8f9;
}
</style>

兄弟組件之間的通信

  • 1、兄弟之間傳遞數據需要藉助於事件車,通過事件車的方式傳遞數據

  • 2、創建一個Vue的實例,讓各個兄弟共用同一個事件機制。

  • 3、傳遞數據方,通過一個事件觸發bus.$emit(方法名,傳遞的數據)。

  • 4、接收數據方,通過mounted(){}觸發bus.$on(方法名,function(接收數據的參數){用該組件的數據接收傳遞過來的數據}),此時函數中的this已經發生了改變,可以使用箭頭函數。

例如:1:新建rest.js

import Vue from 'vue'

export default new Vue

  • 2:組件 a
<template>
    <Modal v-model="opened" title="更新文件夾" :closable="false" @on-cancel="cancel">
        <Form ref="fAccount" :model="folder" :label-width="80">
          <Form-item label="文件夾名:" prop="foldername">
            <Input v-model="folderName" type="text"></Input>
          </Form-item>
        </Form>
        <div slot="footer">
            <Button type="ghost" @click="cancel" style="margin-left: 8px">取消</Button>
            <Button type="primary" @click="updatefolder" :loading="loading">更新</Button>
        </div>
    </Modal>
</template>
<script>
  import ResourceAPI from 'api/resource';
//引入rest.js
  import RestVue from "../../rest"
export default{
    props:{
        opened:{
            type:Boolean,
            default:false
        },
        folderId:{
            type:Number,
            default:0
        },
        folderName:{
            type:String
        }
    },
    data(){
        return {
            loading:false,
            folder:{
              foldername:'',
            }
        }
    },
    methods: {
      updatefolder() {
          if(this.folderName != ''){
            this.loading = true;
            ResourceAPI.folders_update(this.folderId,this.folderName)
              .then((response)=> {
                this.loading = false;
                if(response.data.success==true){
                  this.$Message.info('文件夾更新成功!');
                  this.$emit('updateFolder');
                   //發送給的方法
                  RestVue.$emit('updateFolderFlag', this.folderName)
                  this.$emit('closedModal');
                }
                else{
                  this.$Message.error(response.data.message);
                }
              })
              .catch(error => {
                this.loading = false;
              });
          }else{
             this.$Message.error("文件夾名稱不能爲空!");
          }
        },
        cancel() {
            this.$refs['fAccount'].resetFields();
            this.$emit('closedModal');
        }
    },
}
</script>


3:組件b

<template>
    <div>
        <Card style="width:350px">

            <p slot="title">
                <Icon :type="icon"></Icon>
                {{this.resource.name}}
            </p>
            <a href="#" slot="extra" @click.prevent="close">
                <Icon type="close" color="#ccc" ></Icon>
            </a>

            <Form ref='fResource' :model="resource" label-position='left' :label-width="70">
                <Row>
                    <Col span='12'>
                        <Form-item label="作者:">
                            <label>{{resource.author}}</label>
                        </Form-item>
                    </Col>
                    <Col span='12'>
                        <Form-item label="大小:">
                            <label>{{resource.size}}</label>
                        </Form-item>
                    </Col>
                  <Col span='12'>
                    <Form-item label="創建時間:">
                        <label >{{resource.create_time}}</label>
                    </Form-item>
                  </Col>
                  <Col span='12'>
                      <Form-item label="更新時間:">
                        <label>{{resource.update_time}}</label>
                      </Form-item>
                  </Col>
                </Row>

                <Form-item v-if="isFile"  label="標籤:">
                    <template v-if="canManageTag===true">
                          <Tag v-for="item in resource.tags" :key="item.id" :name="item.name" color="blue" closable @on-close="deleteTag(item.name)">{{ item.name }}</Tag>
                    </template>
                    <template v-else>
                          <Tag v-for="item in resource.tags" :key="item.id" :name="item.name" color="blue" > {{ item.name }}</Tag>
                    </template>
                    <Button v-if="canManageTag===true" icon="ios-plus-empty" type="dashed" size="small" @click="addingTag=true">設置並添加標籤</Button>
                </Form-item>
            </Form>
        </Card>

        <TagsComponent
            :opened="addingTag"
            :file-id="resourceId"
            @addedTag="addedTag"
            @closedModal="closedModal"
           >
        </TagsComponent>

    </div>
</template>

<script>
import ResourceAPI from 'api/resource';
import TagAPI from 'api/tag';
import CapacityAPI from 'utils/capacity'

import TagsComponent from './tags.vue';

import RestVue from "../../rest"

export default {
    components:{
        TagsComponent
    },
    props:{
        isFile:{
            type:Boolean,
            default:true
        },
        resourceId:{
            type:Number,
            default:0
        },
    },
    data(){
        return {
            icon:'',
            resource:{
                id:0,
                name:'',
                author:'',
                size:0,
                tags:[],
                create_time:'',
                update_time:'',
                description:''
            },
            // tag
            addingTag:false,
            // 權限設置
            canManageTag:false
        }
    },
    created:function(){
        switch(this.$route.meta.space){
            case "public":
//                this.canManageTag = this.$store.getters.permission.public['108'];
                this.canManageTag = true;
                break;
            case "group":
//                this.canManageTag = this.$store.getters.permission.group['108'];
                this.canManageTag = true;
                break;
            case "private":
                this.canManageTag = true;
                break;
        }
    },
    watch:{
        resourceId:function(value,oldValue) {
          // 更新 ICON
          this.icon = this.isFile == true ? 'document' : 'folder';
          // 更新資源信息
            this.getResouce()
        }
    },

    methods:{
        //獲取單標籤信息
        getResouce(){
            ResourceAPI.singleTage(this.resourceId).then(response=>{
                let resp = response.data;
                if(resp.success==true){
                    let resouceObject = resp.data;
                    this.resource.id = resouceObject.id;
                    this.resource.name = resouceObject.name;
                    this.resource.author = resouceObject.uploader.username;
                    this.resource.create_time = resouceObject.create_time;
                    this.resource.update_time = resouceObject.update_time;
                    let size = CapacityAPI.bytesToSize(resouceObject.size);
                    let isFile = resouceObject.is_file;
                    if(isFile == false){
                      size="- -";
                      this.resource.size = size
                    }else{
                      this.resource.size = size
                    }
                    this.resource.tags = [];
                    let tags = resouceObject.tag_set;
                    tags.forEach((item, index)=>{
                    this.resource.tags.push({
                      id:item.id,
                      name:item.name
                    });
                  });
                }
            });
        },
        addedTag(){
            // 添加標籤完成後,更新標籤信息
            this.getResouce();
        },
        deleteTag(tagName){
          this.$Modal.confirm({
            title:'警告',
            content: `確定要刪除標籤【${tagName}】嗎?`,
            okText:'刪除',
            cancelText:'取消',
            loading:this.loading,
            onOk:()=>{
              TagAPI.del(this.resourceId, tagName).then(response=>{
                let resp = response.data;
                if(resp.success==true){
                  this.$Message.info("刪除標籤成功!");
                  // 更新標籤信息
                  this.getResouce();
                }else{
                  this.$Message.error(resp.message);
                }
              }).catch(error=>{

              });
            },
            onCancel:()=>{

            }
          });
        },
        close(){
            this.$emit('closedDetail');
        },
        closedModal(){
            this.addingTag = false;
        },
        getFolderName(){
//接收方法
          RestVue.$on("updateFolderFlag", (message) => {
            if(message != ''){
              this.getResouce();
            }
          })

        }
    },
    created(){
      this.getFolderName()
    }
}
</script>

<style scoped>
.ivu-form .ivu-form-item-label{
    color:#ccc;
}
</style>

ztree實現樹的結構(移除自己的節點)

<template>
  <Modal v-model="opened" title="移動文件" :closable="false" @on-cancel="cancel">
    <Form ref="fMove" :label-width="80">
      <Form-item prop="name">
        <!--<Tree :data="baseData" show-checkbox @on-select-change='movecheck' ></Tree>-->
        <ul id="treeMove" class="ztree" style="margin-top:0; width:160px; height:auto;"></ul>
      </Form-item>
    </Form>
    <div slot="footer">
      <Button type="ghost" @click="cancel" style="margin-left: 8px">取消</Button>
      <Button type="primary" @click="movefile" :loading="loading">移動</Button>
    </div>
  </Modal>
</template>

<script>
  import ResourceAPI from 'api/resource';
  export default{
    props: {
      opened: {
        type: Boolean,
        default: false
      },
      isFile: {
        type: Boolean,
        default: false
      },
      moveId: {
        type: Number,
        defalut: 0
      },
      folderId: {
          type:Number,
          defalut: 0
      },
      serachValue:{
          type:Boolean,
          defalut:false
      }

    },
    data(){
      return {
        loading: false,
        load:null,
        self_id: 0,
        baseData: [],
        settingMove : {
          check: {
            enable: true,
            chkStyle: "radio",
            radioType: "all"
          },
          view: {
            dblClickExpand: this.dblClickExpand
          },
          data: {
            simpleData: {
              enable: true
            }
          },
          callback: {
            onClick: this.onClickNode,
            onCheck: this.onCheck
          }
        },
        zNodes:[],
        selfArray:[]
      }
    },
    watch: {
      opened: function (value, oldValue) {
        if (value == true) {
          this.getTree();
        }
      }
    },
    methods: {
      movefile(){
        if(this.self_id == this.moveId){
          this.$Message.error("文件夾不能移動到本身文件夾中!");
          return;
        }
        if (this.isFile == true) {
          this.loading = true
          this.load = this.$Message.loading({
            content: 'Loading...',
            duration: 0
          });
          ResourceAPI.file_move(this.self_id, this.moveId).then((response, reject) => {
            this.loading = false;
            if (response.data.success == true) {
              this.$Notice.success({
                title: '移動文件成功!',
                duration:2.5
              });
              this.load = this.$Message.destroy();
              this.loading = false
              this.folderId == 0 ?this.$emit("refreshTable"):this.$emit("moveFolder")
              this.serachValue == true?this.$emit("refreshSearch"):this.serachValue = false
              this.$emit('closedModal');
            }
            else {
              this.$Notice.error({
                title: response.data.message,
                duration:2.5
              });
              this.load = setTimeout(() => {
                this.$Message.destroy();
                this.loading = false
              },500)
            }
          }).catch(error => {
            this.loading = false;
          });
        } else {
          this.load = this.$Message.loading({
            content: 'Loading...',
            duration: 0
          });
          this.loading = true
          ResourceAPI.folder_move(this.self_id, this.moveId).then((response, reject) => {

            if (response.data.success == true) {
              this.$Notice.success({
                title: '移動文件夾成功!',
                duration:2.5
              });
              this.load = this.$Message.destroy();
              this.loading = false;
              this.folderId == 0 ?this.$emit("refreshTable"):this.$emit("moveFolder")
              this.$emit('closedModal');
            }
            else {
              this.$Notice.error({
                title: response.data.message,
                duration:2.5
              });
              this.load = setTimeout(() => {
                this.$Message.destroy();
                this.loading = false
              },500)
            }
          }).catch(error => {
            this.loading = false;
          });
        }

      },
      getTree(){
        //準備數據
        ResourceAPI.getTree(this.moveId).then((response) => {
          let resp = response.data;
          if (resp.success == true) {
            let nodes = resp.data.department
            let nodesArray = [{id:"", pId:"", name:"root", open:true}]
            //調用去除自己的方法
            this.removeShelf(this.moveId, nodes)
            //利用差集來去除
            let self_array = new Set(this.selfArray);
            let node_array = new Set(nodes)
            let new_node = new Set([...node_array].filter(x => !self_array.has(x)));
            let new_node_array = Array.from(new_node);
            new_node_array.forEach((item, index, array) =>{
              nodesArray.push({
                "name":item.departmentName,
                "id":item.id,
                "pId":item.parentId,
                "open":true
              })
            })
            this.zNodes= nodesArray
            $.fn.zTree.init($("#treeMove"), this.settingMove, this.zNodes);
//            this.$emit("refreshTable")
          }
        }).catch(error => {

        });

      },
      onClickNode(e, treeId, treeNode){
        var zTree = $.fn.zTree.getZTreeObj("treeMove");
        zTree.checkNode(treeNode, !treeNode.checked, null, true);
        return false;
      },
      onCheck(e, treeId, treeNode){
        let _this = this;
        var zTree = $.fn.zTree.getZTreeObj("treeMove"),
          nodes = zTree.getCheckedNodes(true);
        for (var i = 0, l = nodes.length; i < l; i++) {
//          console.log(nodes[0].id);
          _this.self_id = nodes[0].id
        }
      },
      //根文件的顯示
      dblClickExpand(treeId, treeNode){
        return treeNode.level > 0;
      },
      //去除選擇自己的節點
      removeShelf(id, array){
        for (var i = 0; i < array.length; i++) {
          var _array = array[i];
          if(_array.parentId == id){
            this.selfArray.push(_array)
            this.removeShelf(_array.id, array)
          }
          if(_array.id == id){
            if(this.selfArray.indexOf(_array) ==-1){
              this.selfArray.push(_array)
            }
          }
        }
      },
      cancel(){
        this.$emit('closedModal');
      },
    },

  }

</script>
  • 批量選擇移除自己的節點
<template>
  <Modal v-model="opened" title="批量移動文件" :closable="false" @on-cancel="cancel">
    <Form ref="fMove" :label-width="80">
      <Form-item prop="name">
        <!--<Tree :data="baseData" show-checkbox @on-select-change='movecheck' ></Tree>-->
        <ul id="treeBatchMove" class="ztree" style="margin-top:0; width:160px; height:auto;"></ul>
      </Form-item>
    </Form>
    <div slot="footer">
      <Button type="ghost" @click="cancel" style="margin-left: 8px">取消</Button>
      <Button type="primary" @click="movefile" :loading="loading">移動</Button>
    </div>
  </Modal>
</template>

<script>
  import ResourceAPI from 'api/resource';
  export default{
    props: {
      opened: {
        type: Boolean,
        default: false
      },
      isFile: {
        type: Boolean,
        default: false
      },
      listId:{
        type:Array
      },
      folderId: {
        type:Number,
        defalut: 0
      },
      serachValue:{
        type:Boolean,
        defalut:false
      }

    },
    data(){
      return {
        loading: false,
        load:null,
        self_id: 0,
        baseData: [],
        settingMove : {
          check: {
            enable: true,
            chkStyle: "radio",
            radioType: "all"
          },
          view: {
            dblClickExpand: this.dblClickExpand
          },
          data: {
            simpleData: {
              enable: true
            }
          },
          callback: {
            onClick: this.onClickNode,
            onCheck: this.onCheck
          }
        },
        zNodes:[],
        selfArray:[]
      }
    },
    watch: {
      opened: function (value, oldValue) {
        if (value == true) {
          this.getTree();
        }
      }
    },
    methods: {
      movefile(){
        if(this.self_id == this.moveId){
          this.$Message.error("文件夾不能移動到本身文件夾中!");
          return;
        }
        if (this.isFile == true) {
          this.loading = true
          this.load = this.$Message.loading({
            content: 'Loading...',
            duration: 0
          });
          ResourceAPI.file_move(this.self_id, this.moveId).then((response, reject) => {
            this.loading = false;
            if (response.data.success == true) {
              this.$Notice.success({
                title: '移動文件成功!',
                duration:2.5
              });
              this.load = this.$Message.destroy();
              this.loading = false
              this.folderId == 0 ?this.$emit("refreshTable"):this.$emit("moveFolder")
              this.serachValue == true?this.$emit("refreshSearch"):this.serachValue = false
              this.$emit('closedModal');
            }
            else {
              this.$Notice.error({
                title: response.data.message,
                duration:2.5
              });
              this.load = setTimeout(() => {
                this.$Message.destroy();
                this.loading = false
              },500)
            }
          }).catch(error => {
            this.loading = false;
          });
        } else {
          this.load = this.$Message.loading({
            content: 'Loading...',
            duration: 0
          });
          this.loading = true
          ResourceAPI.folder_move(this.self_id, this.moveId).then((response, reject) => {

            if (response.data.success == true) {
              this.$Notice.success({
                title: '移動文件夾成功!',
                duration:2.5
              });
              this.load = this.$Message.destroy();
              this.loading = false;
              this.folderId == 0 ?this.$emit("refreshTable"):this.$emit("moveFolder")
              this.$emit('closedModal');
            }
            else {
              this.$Notice.error({
                title: response.data.message,
                duration:2.5
              });
              this.load = setTimeout(() => {
                this.$Message.destroy();
                this.loading = false
              },500)
            }
          }).catch(error => {
            this.loading = false;
          });
        }

      },
      getTree(){
        //準備數據
        ResourceAPI.getTree(this.listId[0]).then((response) => {
          let resp = response.data;
          if (resp.success == true) {
            let nodes = resp.data.department
            let nodesArray = [{id:"", pId:"", name:"root", open:true}]
            //調用去除自己的方法
            this.removeShelf(this.listId, nodes)
            //利用差集來去除
            let self_array = new Set(this.selfArray);
            let node_array = new Set(nodes)
            let new_node = new Set([...node_array].filter(x => !self_array.has(x)));
            let new_node_array = Array.from(new_node);
            new_node_array.forEach((item, index, array) =>{
              nodesArray.push({
                "name":item.departmentName,
                "id":item.id,
                "pId":item.parentId,
                "open":true
              })
            })
            this.zNodes= nodesArray
            $.fn.zTree.init($("#treeBatchMove"), this.settingMove, this.zNodes);
//            this.$emit("refreshTable")
          }
        }).catch(error => {

        });

      },
      onClickNode(e, treeId, treeNode){
        var zTree = $.fn.zTree.getZTreeObj("treeBatchMove");
        zTree.checkNode(treeNode, !treeNode.checked, null, true);
        return false;
      },
      onCheck(e, treeId, treeNode){
        let _this = this;
        var zTree = $.fn.zTree.getZTreeObj("treeBatchMove"),
          nodes = zTree.getCheckedNodes(true);
        for (var i = 0, l = nodes.length; i < l; i++) {
//          console.log(nodes[0].id);
          _this.self_id = nodes[0].id
        }
      },
      //根文件的顯示
      dblClickExpand(treeId, treeNode){
        return treeNode.level > 0;
      },
      //去除選擇自己的節點
      removeShelf(id_list, array){
        for (var i = 0; i < array.length; i++) {
          var _array = array[i];
          if(id_list.indexOf(_array.parentId) != -1){
            this.selfArray.push(_array)
            this.removeShelf([_array.id], array)
          }
          if(id_list.indexOf(_array.id) != -1){
            if(this.selfArray.indexOf(_array) ==-1){
              this.selfArray.push(_array)
            }
          }
        }
      },
      cancel(){
        this.$emit('closedModal');
      },
    },

  }

</script>

vue-router 配置404頁面(遇到的問題點)

  • 後端已經配置了history 模式,404頁面不生效,原因是:404頁面的路徑一定要放到最後
import Vue from 'vue'
import Router from 'vue-router'
const _import = require('./_import_' + process.env.NODE_ENV);
// in development env not use Lazy Loading,because Lazy Loading large page will cause webpack hot update too slow.so only in production use Lazy Loading

/* layout */
import Layout from '../views/layout/Layout';

/* login */
const Login = _import('login/index');
// const authRedirect = _import('login/authredirect');

/* finder */
const Finder = _import('finder/index');

/*groupHome 羣主空間頁面*/
const GroupHome = _import('groupHome/index')
/* profile */
const Profile = _import('profile/index');


/* Account & Group */
const Account = _import('account/index');
const Group = _import('group/index');

/* shared */
const Shared = _import('shared/index')

/*otherShared*/
const OtherShared = _import('otherShared/index')

/* Log */
const Log = _import('log/index');

//儲存管理
const Buffer = _import('buffer/index')

/*回收站組件*/
const AccountRecycle = _import('accountRecycle/index');
const GroupRecycle = _import('groupRecycle/index');
const FileRecycle = _import('fileRecycle/index');

//404頁面
const Err404 = _import('errorPage/404');

Vue.use(Router)

 /**
  * icon : the icon show in the sidebar
  * hidden : if hidden:true will not show in the sidebar
  * redirect : if redirect:noredirect will not redirct in the levelbar
  * noDropdown : if noDropdown:true will not has submenu
  * meta : { role: ['admin'] }  will control the page role
  **/

export const constantRouterMap = [
    { path: '/login', name: 'login', component: Login, hidden: true},
    // { path: '/authredirect', component: authRedirect, hidden: true },

    // { path: '/401', component: Err401, hidden: true },
    {
      path: '/',
      redirect: '/space/person/',
      hidden: true
    },
    {
      path: '/space/person',
      component: Layout,
      name: '我的空間',
      hiddenChildren:true,
      icon: 'person',

      children: [
        { path: '/',  component: Finder, meta: { space: 'private', space2: 'person', activatedPath: '/space/person' }}
      ]
    },
    {
      path: '/space/person/:folderId',
      component: Layout,
      name: '我的空間',
      hidden: true,
      hiddenChildren:true,
      children: [
        { path: '/', component: Finder, meta: { space: 'private', space2: 'person', activatedPath: '/space/person' }}
      ]
    },
    {
      path: '/space/group',
      component: Layout,
      name: '羣組空間',
      icon: 'person-stalker',
      hiddenChildren:true,
      children: [
        { path: '/', component: GroupHome, meta: { space: 'group', space2: 'group', activatedPath: '/space/group' }}
      ]
    },
    {
      path: '/space/group/:folderId',
      component: Layout,
      name: '羣組空間',
      hidden: true,
      hiddenChildren:true,
      children: [
        { path: '/', component: GroupHome, meta: { space: 'group', space2: 'group', activatedPath: '/space/group' }}
      ]
    },
    {
      path: '/space/shared',
      component: Layout,
      name: '我分享的文件',
      hiddenChildren:true,
      icon:'android-share-alt',
      children: [
        { path: '/', component:Shared, meta: { space: 'SHARED', space2: 'user', activatedPath: '/space/shared' }}
      ]
    },
    {
      path: '/space/shared/:folderId',
      component: Layout,
      name: '我分享的文件',
      hidden: true,
      hiddenChildren:true,
      children: [
        { path: '/', component: Shared, meta: { space: 'SHARED', space2: 'user', activatedPath: '/space/shared' }}
      ]
    },
   {
     path: '/space/ohtershared',
     component: Layout,
     name: '分享給我的文件',
     icon:'android-share-alt',
     hiddenChildren:true,
     children: [
       { path: '/', component: OtherShared, meta: { space: 'OTHERSHARED', space2: 'othershared', activatedPath: '/space/ohtershared' }}
     ]
   },
    {
     path: '/space/ohtershared/:folderId',
     component: Layout,
     name: '分享給我的文件',
     hidden: true,
     hiddenChildren:true,
     children: [
       { path: '/', component: OtherShared, meta: { space: 'OTHERSHARED', space2: 'othershared', activatedPath: '/space/ohtershared' }}
     ]
   },
    {
      path: '/space/public',
      component: Layout,
      name: '公共空間',
      icon:'ios-list-outline',
      hiddenChildren:true,
      children: [
        { path: '/', component: Finder, meta: { space: 'public', space2: 'public', activatedPath: '/space/public' }}
      ]
    },
    {
      path: '/space/public/:folderId',
      component: Layout,
      name: '公共空間',
      hidden: true,
      hiddenChildren:true,
      children: [
        { path: '/', component: Finder, meta: { space: 'public', space2: 'public', activatedPath: '/space/public' }}
      ]
    },


]

export default new Router({
  mode:'history', //後端支持可開
  scrollBehavior: () => ({ y: 0 }),
  routes: constantRouterMap
})

export const asyncRouterMap = [

  {
    path: '/system',
    component: Layout,
    redirect: '/account',
    name: '系統管理',
    icon: 'android-settings',
    hiddenChildren:false,
    meta: { role: ['admin','group_admin','user'], activatedPath: '/system' },
    children: [
      { path: '/account', component: Account, name: '用戶管理', icon: 'person',  meta: { role: ['admin', 'group_admin'], activatedPath: '/account' }},
      { path: '/group', component: Group, name: '羣組管理',  icon: 'person-stalker', meta: { role: ['admin', 'group_admin'], activatedPath: '/group' }},
      // { path: '/storage', component: Buffer, name: '存儲管理',  icon: 'social-buffer', meta: { role: ['admin','group_admin'], activatedPath: '/storage' }},
      { path: '/log', component: Log, name: '日誌管理',  icon: 'chatbubble-working', meta: { role: ['admin','group_admin','user'], activatedPath: '/log' }},
    ]
  },
  {
    path: '/recycle',
    component: Layout,
    redirect: '/account',
    name: '回收站',
    icon: 'trash-a',
    hiddenChildren:false,
    meta: { role: ['admin','group_admin','user'], activatedPath: '/recycle' },
    children: [
      { path: '/account/recycle', component: AccountRecycle, icon: 'person', name: '用戶回收', meta: { role: ['admin','group_admin'], activatedPath: '/account/recycle' }},
      { path: '/group/recycle', component: GroupRecycle, icon: 'person-stalker', name: '羣組回收', meta: { role: ['admin','group_admin'], activatedPath: '/group/recycle' }},
      { path: '/file/recycle', component: FileRecycle, icon: 'document', name: '文件回收', meta: { role: ['admin','group_admin','user'], activatedPath: '/file/recycle' }},
    ]
  },
  //配置404路由一定要放在最後頁面
  {
    path: '*',
    name: 'error_404',
    meta: {
      title: '404-頁面不存在'
    },
    component: Err404, hidden: true
  },
  //{ path: '*', redirect: '/errorPage', hidden: true }
];

  • 404 組件
  • 404樣式
@keyframes error404animation {
    0% {
        transform: rotateZ(0deg);
    }
    20% {
        transform: rotateZ(-60deg);
    }
    40% {
        transform: rotateZ(-10deg);
    }
    60% {
        transform: rotateZ(50deg);
    }
    80% {
        transform: rotateZ(-20deg);
    }
    100% {
        transform: rotateZ(0deg);
    }
}
.error404{
    &-body-con{
        width: 700px;
        height: 500px;
        position: absolute;
        left: 50%;
        top: 50%;
        transform: translate(-50%,-50%);
        &-title{
            text-align: center;
            font-size: 240px;
            font-weight: 700;
            color: #2d8cf0;
            height: 260px;
            line-height: 260px;
            margin-top: 40px;
            span{
                display: inline-block;
                color: #19be6b;
                font-size: 230px;
                animation: error404animation 3s ease 0s infinite alternate;
            }
        }
        &-message{
            display: block;
            text-align: center;
            font-size: 30px;
            font-weight: 500;
            letter-spacing: 12px;
            color: #dddde2;
        }
    }
    &-btn-con{
        text-align: center;
        padding: 20px 0;
        margin-bottom: 40px;
    }
}

<style lang="less">
    @import './404.less';
</style>

<template>
    <div class="error404">
        <div class="error404-body-con">
            <Card>
                <div class="error404-body-con-title">4<span><Icon type="ios-navigate-outline"></Icon></span>4</div>
                <p class="error404-body-con-message">YOU&nbsp;&nbsp;LOOK&nbsp;&nbsp;LOST</p>
                <div class="error404-btn-con">
                    <Button @click="goHome" type="error" size="large" style="width: 200px;" >返回首頁</Button>
                    <Button @click="backPage" size="large" style="width: 200px;margin-left: 40px;" type="primary">返回上一頁</Button>
                </div>
            </Card>
        </div>
    </div>
</template>

<script>
export default {
    name: 'Error404',
    methods: {
        backPage () {
            this.$router.go(-2);
        },
        goHome () {
            this.$router.push({ path: "/space/person" });
        }
    }
};
</script>

授索功能的完善(自己封裝的組件)

rest.js
import Vue from 'vue'

export default new Vue

  • serarch 組件
<template>
    <span>
      <Input  @keyup.enter.native="handleFilter(searchUrl,pagerSize,pagerIndex,spaceType,searchType,headersToken)"
              @on-change="handleFilter(searchUrl,pagerSize,pagerIndex,spaceType,searchType,headersToken)"
              v-model='inputValue'
              @on-blur="inputKeyWord"
              placeholder="請輸入..." style="width: 20%">
      </Input>
       <Button type="primary"  @click="handleFilter(searchUrl,pagerSize,pagerIndex,spaceType,searchType,headersToken)" >
                  <Icon type="ios-search"></Icon>
                  搜索
       </Button>
    </span>
</template>

<script>
  //探索添加500ms以後請求
  import _ from 'lodash'; //引入lodash
  import axios from 'axios'//引入axios
  import RestVue from "../../rest"

  //請求canceltoken列表
  let sources = [];
    export default {
      props:{
        searchUrl:{
          type:String
        },
        headersToken:{
          type:Object
        },
        spaceType:{
          type:String
        },
        searchType:{
          type:String
        },
        pagerSize:{
            type:Number,
        },
        pagerIndex:{
            type:Number,
        }
      },
        data(){
            return{
              inputValue:'',
            }
        },
        methods:{
          //搜索結果
          handleFilter(searchUrl,pagerSize,pagerIndex,spaceType,searchType,headersToken){
            this.$emit('showIsBatchBth',this.inputValue)
            if(this.inputValue == ''){
                return;
            }else{
              this.searchInputValue(searchUrl,pagerSize,pagerIndex,spaceType,searchType,headersToken)
            }
          },
          // 搜索功能
          // 使用_.debounce控制搜索的觸發頻率, 500ms後執行
          // 準備搜索
          searchInputValue:_.debounce(
            function (requestUrl,pagerSize,pagerIndex,spaceType,searchType,headersToken) {
              let that = this;
              // 刪除已經結束的請求
              _.remove(sources, (n)=>{
                return n.source === null;
              })
              //  取消還未結束的請求
              sources.forEach(function (item) {
                if (item !== null && item.source !== null && item.status === 1) {
                  item.status = 0;
                }
              });

              //創建新的請求cancelToken,並設置狀態請求中
              var sc = {
                source: axios.CancelToken.source(),
                status: 1 //狀態1:請求中,0:取消中
              };

              //這個對象加入數組中
              sources.push(sc);
              //開始搜索數據
              //開始搜索數據
              var url = requestUrl+"?pageSize="+pagerSize+"&page_index="+pagerIndex+"&space="+spaceType+"&type="+searchType+"&name="+that.inputValue;
              axios.get( url, {
                cancelToken: sc.source.token,
                headers:headersToken
              }).then((response)=> {

                if(response.data.success == true){
                  sc.source = null;
                }
                this.$emit("searchResVlaue", response);

              }).catch((err)=>{
                //請求失敗
                sc.source = null; //置空請求canceltoken
              });
            },
            1000),
          //失去焦點
          inputKeyWord(){
            if(this.inputValue == ""){
              this.$emit("openSearchSearch", false);
              this.$emit("showTableopenSearch", true);
            }
          },
        },
      mounted(){
        RestVue.$on("pagerIndexFun", (message) => {
          this.handleFilter(
            this.searchUrl,
            this.pagerSize,
            message,
            this.spaceType,
            this.searchType,
            this.headersToken
          );
        })
        RestVue.$on("refreshResultSerach", (message) => {
          if(message == true){
            this.handleFilter(
              this.searchUrl,
              this.pagerSize,
              this.pagerIndex,
              this.spaceType,
              this.searchType,
              this.headersToken
            );
          }
        })
      }

    }
</script>

<style>

</style>

  • 引用組件
  • html
html
  <Search
                :search-url='requestUrl'
                :pager-size='pager.size'
                :pager-index="pager.index"
                :space-type="space"
                :search-type="getSelectValue||'name'"
                :headers-token="searchHeaders"
                @searchResVlaue='searchResValue'
                @showIsBatchBth='showIsBatchBth'
              ></Search>
  • js
import Search from '@/components/search/search.vue'

import RestVue from "../../rest"

export default {
    name: 'space',
    components:{
        UploadComponent,
        CreateFolderComponent,
        DetailComponent,
        MoveComponent,
        CopyComponent,
        ShareCompoent,
        UpdateFolder,
        UpdateFile,
        BatchShared,
        BatchMove,
        BatchCopy,
        Search
    },
    data () {
      let columns = null;
      if(this.$store.getters.role=='user'&&this.$route.meta.space == "public"){
        columns = [
          {
            title: '文件名',
            width:'25%',
//                sortable: true,
            render:(h,params)=>{
              let iconType = params.row.isFile==true ? 'document' : 'folder';
              let id =params.row.id;
              let name = params.row.name;
              let isFile = params.row.isFile;
              let namePoint = '';
              if(name.length>20){
                namePoint+=name.slice(0, 20)+'...'
              }else{
                namePoint+=name
              }
              return(
                <div onClick={()=>this.showDetail(id,isFile)} style={{cursor:'pointer'}}>
              <Icon type={iconType}  style={{ fontSize:'16px'}}></Icon>
              <span domPropsInnerHTML={namePoint} title={name} style={{ cursor:'pointer',padding:'10px'}} onClick={(e)=>this.handleResource(id,isFile,e)}></span>
              </div>
              )
            }
          },
          {
            title: ' ',
            key: 'action',
            width:'25%',
            render:(h,params)=>{
              let resourceId = params.row.id;
              let resourceName = params.row.name;
              let resourceURL =process.env.BASE_API+params.row.download_url;
              let isFile = params.row.isFile;
              let tags = params.row.tags;
              let shareId = params.row.shardId
              // 來源信息
              let fromInfo = '';
              if (params.row.from){
                fromInfo = "源自:"+ params.row.from.name;
              }
              // 權限控制
              let canDelete = false;
              let canShare = false;
              let share = true;
              let sharePermisson = true;
              switch(this.space){
                case "public":
                  if(this.$store.getters.role=='admin'){
                    share = true;
                    canDelete = true;
                    canShare = false;
                  }else if(this.$store.getters.role=='group_admin'){
                    share = true;
                    canDelete = true;
                    canShare = false;
                    sharePermisson = true;
                  }else if(this.$store.getters.role=='user'){
                    share = false;
                    canDelete = false;
                    canShare = false;
                    sharePermisson = true;
                  }
                  break;
                case "group":
                  if(this.$store.getters.role=='admin'){
                    share = true;
                    canDelete = true;
                    canShare = true;
                  }else if(this.$store.getters.role=='group_admin'){
                    share = true;
                    canDelete = true;
                    canShare = true;
                  }else if(this.$store.getters.role=='user'){
                    share = true;
                    canDelete = true;
                    canShare = true;
                    sharePermisson = true;
                  }
                  break;
                case "private":
                  canDelete = true;
                  canShare = true;
                  break;

              }
              return (
                <div style={{ textAlign: 'left' }}>

              <span style={{ color: '#ccc', display:'inline-block', width:'120px' }}>{fromInfo}</span>


              {
                canShare ?
              <Button type="text" onClick={()=>this.getShare(isFile,resourceId,resourceName)}>
              <Icon size='16' type="android-share-alt"></Icon>
                </Button>
              :
              ''
            }
              {
                sharePermisson ?<span onClick={()=>this.clkicDownload(isFile)}><a href={isFile== true?resourceURL:"javascript:void(0);"} style={{ marginRight:'23px',marginLeft:'13px'}}><Icon size='16' type="android-download"></Icon></a></span> :''
              }

              { share ?
              <Dropdown placement="bottom-start" style={{ padding:'10px'}} onOn-click={(name,id)=>this.changeSelected(name,resourceId,isFile,resourceName,tags)}>
              <Icon type="more"></Icon>
                <Dropdown.Menu slot="list">
                <Dropdown.Item name='copy'><Icon type="ios-copy-outline"></Icon> 複製</Dropdown.Item>
                <Dropdown.Item name='move'><Icon type="arrow-move"></Icon> 移動</Dropdown.Item>
                <Dropdown.Item name='update'><Icon type="android-create"></Icon> 更新</Dropdown.Item>
                {canDelete ? <Dropdown.Item name='delete' ><Icon type="ios-trash"></Icon> 刪除</Dropdown.Item> : ""}
              </Dropdown.Menu>
              </Dropdown>
              : ''
              }
              </div>
              );
            }
          },
          {
            title: '大小',
            key: 'size',
            sortable: true,
            align: 'center',
//                width: "120px"
          },
          {
            title: '修改日期',
            key: 'update_time',
            sortable: true,
            align: 'center',
            width: "20%"
          },
        ]
      }else{
        columns = [
          {
            type: 'selection',
            width: 32,
            align: 'center'
          },
          {
            title: '文件名',
            width:'25%',
//                sortable: true,
            render:(h,params)=>{
              let iconType = params.row.isFile==true ? 'document' : 'folder';
              let id =params.row.id;
              let name = params.row.name;
              let isFile = params.row.isFile;
              let namePoint = '';
              if(name.length>20){
                namePoint+=name.slice(0, 20)+'...'
              }else{
                namePoint+=name
              }
              return(
                <div onClick={()=>this.showDetail(id,isFile)} style={{cursor:'pointer'}}>
              <Icon type={iconType}  style={{ fontSize:'16px'}}></Icon>
              <span domPropsInnerHTML={namePoint} title={name} style={{ cursor:'pointer',padding:'10px'}} onClick={(e)=>this.handleResource(id,isFile,e)}></span>
              </div>
              )
            }
          },
          {
            title: ' ',
            key: 'action',
            width:'45%',
            render:(h,params)=>{
              let resourceId = params.row.id;
              let resourceName = params.row.name;
              let resourceURL =process.env.BASE_API+params.row.download_url;
              let isFile = params.row.isFile;
              let tags = params.row.tags;
              let shareId = params.row.shardId
              // 來源信息
              let fromInfo = '';
              if (params.row.from){
                fromInfo = "源自:"+ params.row.from.name;
              }
              // 權限控制
              let canDelete = false;
              let canShare = false;
              let share = true;
              let sharePermisson = true;
              switch(this.space){
                case "public":
                  if(this.$store.getters.role=='admin'){
                    share = true;
                    canDelete = true;
                    canShare = false;
                  }else if(this.$store.getters.role=='group_admin'){
                    share = true;
                    canDelete = true;
                    canShare = false;
                    sharePermisson = true;
                  }else if(this.$store.getters.role=='user'){
                    share = false;
                    canDelete = false;
                    canShare = false;
                    sharePermisson = true;
                  }
                  break;
                case "group":
                  if(this.$store.getters.role=='admin'){
                    share = true;
                    canDelete = true;
                    canShare = true;
                  }else if(this.$store.getters.role=='group_admin'){
                    share = true;
                    canDelete = true;
                    canShare = true;
                  }else if(this.$store.getters.role=='user'){
                    share = true;
                    canDelete = true;
                    canShare = true;
                    sharePermisson = true;
                  }
                  break;
                case "private":
                  canDelete = true;
                  canShare = true;
                  break;

              }
              return (
                <div style={{ textAlign: 'left' }}>

              <span style={{ color: '#ccc', display:'inline-block', width:'120px' }}>{fromInfo}</span>


              {
                canShare ?
              <Button type="text" onClick={()=>this.getShare(isFile,resourceId,resourceName)}>
              <Icon size='16' type="android-share-alt"></Icon>
                </Button>
              :
              ''
            }
              {
                sharePermisson ? <span onClick={()=>this.clkicDownload(isFile)}><a href={isFile== true?resourceURL:"javascript:void(0);"} style={{ marginRight:'23px',marginLeft:'13px'}}><Icon size='16' type="android-download"></Icon></a></span> :''
              }

              { share ?
              <Dropdown placement="bottom-start" style={{ padding:'10px'}} onOn-click={(name,id)=>this.changeSelected(name,resourceId,isFile,resourceName,tags)}>
              <Icon type="more"></Icon>
                <Dropdown.Menu slot="list">
                <Dropdown.Item name='copy'><Icon type="ios-copy-outline"></Icon> 複製</Dropdown.Item>
                <Dropdown.Item name='move'><Icon type="arrow-move"></Icon> 移動</Dropdown.Item>
                <Dropdown.Item name='update'><Icon type="android-create"></Icon> 更新</Dropdown.Item>
                {canDelete ? <Dropdown.Item name='delete' ><Icon type="ios-trash"></Icon> 刪除</Dropdown.Item> : ""}
              </Dropdown.Menu>
              </Dropdown>
              : ''
              }
              </div>
              );
            }
          },
          {
            title: '大小',
            key: 'size',
            sortable: true,
            align: 'center',
//                width: "120px"
          },
          {
            title: '修改日期',
            key: 'update_time',
            sortable: true,
            align: 'center',
            width: "20%"
          },
        ]
      }
        let resultColumns = [
          {
            type: 'selection',
            width: 32,
            align: 'center'
          },
          {
            title: '文件名',
            width: "20%",
            render:(h,params)=>{
              let iconType = params.row.isFile==true ? 'document' : 'folder';
              let id =params.row.id;
              let name = params.row.name;
              let isFile = params.row.isFile;
              let search = true
              return(
                <div onClick={()=>this.showDetail(id,isFile)} style={{cursor:'pointer'}}>
              <Icon type={iconType}  style={{ fontSize:'16px'}}></Icon>
              <span domPropsInnerHTML={name.slice(0, 14)} title={name} style={{cursor:'pointer',padding:'10px'}} onClick={(e)=>this.handleResource(id,isFile,e)}></span>
              </div>
              )
            }
          },
          {
            title: ' ',
            key: 'action',
            width:'30%',
            render:(h,params)=>{
              let resourceId = params.row.id;
              let resourceName = params.row.name;
              let resourceURL =process.env.BASE_API+params.row.download_url;
              let isFile = params.row.isFile;
              let tags = params.row.tags;
              let shareId = params.row.shardId
              // 來源信息
              let fromInfo = '';
              if (params.row.from){
                fromInfo = "源自:"+ params.row.from.name;
              }
              // 權限控制
              let canDelete = false;
              let canShare = false;
              let share = true;
              let sharePermisson = true;
              let search = true
              switch(this.space){
                case "public":
                  if(this.$store.getters.role=='admin'){
                    share = true;
                    canDelete = true;
                    canShare = false;
                  }else if(this.$store.getters.role=='group_admin'){
                    share = true;
                    canDelete = true;
                    canShare = false;
                    sharePermisson = true;
                  }else if(this.$store.getters.role=='user'){
                    share = false;
                    canDelete = false;
                    canShare = false;
                    sharePermisson = true;
                  }
                  break;
                case "group":
                  if(this.$store.getters.role=='admin'){
                    share = true;
                    canDelete = true;
                    canShare = true;
                  }else if(this.$store.getters.role=='group_admin'){
                    share = true;
                    canDelete = true;
                    canShare = true;
                  }else if(this.$store.getters.role=='user'){
                    share = true;
                    canDelete = true;
                    canShare = true;
                    sharePermisson = true;
                  }
                  break;
                case "private":
                  canDelete = true;
                  canShare = true;
                  break;

              }
              return (
                <div style={{ textAlign: 'left' }}>

              <span style={{ color: '#ccc', display:'inline-block', width:'120px' }}>{fromInfo}</span>


              {
                canShare ?
              <Button type="text" onClick={()=>this.getShare(isFile,resourceId,resourceName)}>
              <Icon size='16' type="android-share-alt"></Icon>
                </Button>
              :
              ''
            }
              {
                sharePermisson ?<a  href={isFile== true?resourceURL:"javascript:void(0);"} style={{ marginRight:'23px',marginLeft:'13px'}}><Icon  size='16' type="android-download"></Icon></a>:''
              }

              { share ?
              <Dropdown placement="bottom-start" style={{ padding:'10px'}} onOn-click={(name,id)=>this.changeSelected(name,resourceId,isFile,resourceName,tags,search)}>
              <Icon type="more"></Icon>
                <Dropdown.Menu slot="list">
                <Dropdown.Item name='copy'><Icon type="ios-copy-outline"></Icon> 複製</Dropdown.Item>
                <Dropdown.Item name='move'><Icon type="arrow-move"></Icon> 移動</Dropdown.Item>
                <Dropdown.Item name='update'><Icon type="android-create"></Icon> 更新</Dropdown.Item>
                {canDelete ? <Dropdown.Item name='delete' ><Icon type="ios-trash"></Icon> 刪除</Dropdown.Item> : ""}
              </Dropdown.Menu>
              </Dropdown>
              : ''
              }
              </div>
              );
            }
          },
          {
            title: '大小',
            key: 'size',
            sortable: true,
            align: 'center',
//                width: "50px"
          },
          {
            title: '修改日期',
            key: 'update_time',
            sortable: true,
            align: 'center',
//            width: "100px"
          },
          {
            title: '路徑',
            width: "20%",
            render:(h,params)=>{
              let directoryName = params.row.directoryName;
              let directoryId = params.row.directoryId;
              let directoryResultName = null;
              let isFile = params.row.isFile;
              if(directoryName == null){
                directoryResultName = '';
              }else{
                directoryResultName =  directoryName;
              }
              let clickPath = true
              return(
                <div  style={{cursor:'pointer'}}  onClick={()=>this.getFolder(directoryId, isFile,clickPath)} >
                    <span  domPropsInnerHTML={ directoryName == null ? 'root'+directoryResultName : 'root '+' > '+directoryResultName} ></span>
                </div>
              )
            }
          },
        ];
        let folder = {
            id:0,
            parentId:0,
            name:'',
            tree:[
                {id:0, name:'root', path:this.$route.meta.activatedPath}
            ],
        };
        return {
            //表格沒有數據時展示內容
            tabNoDataTitle:'載入中。。。',
            //showUser
            showUser:false,
            // status
            load: null,
            uploadDisabled:false,
            uploading:false,
            creatingFolder:false,
            hidingDetail:true,
            shareFolder:false,
            updateFolder:false,
            updateFile:false,
            copingFile:false,
            movingFile:false,
            openSearch:false,
            showTable:true,
            openGroup:false,
            groupDisabled:false,
            serachResult: false,
            showAllShared:true,
            //批量刪除按鈕是否要禁用
            isBatchBth:true,
            //是否批量分享
            isBatchShared:false,
            //是否清空
            isRemoveBatch:false,
            //普通用戶是否顯示批量操作
            isShowBatch:false,
            //是否批量移動
            isBatchMove:false,
            //是否批量移動
            isBatchCopy:false,
            // attributes
            modifyIsFile:true,

            modifyResourceId:0,
            modifyResourceName:'',
            space:this.$route.meta.space,
            groupId: null,
            folder:folder,
            files:[],
            // table
            columns:columns ,
            resultColumns:resultColumns,
            pager:{ total:0, index:1, size:10},
            pagerIndex:null,
            resourceGrid:{table:24, detail:0},
            //tag
            tags:[],
            //folderPath
            folederObj:null,
            //serarch token
            searchHeaders:{
              Authorization:"conspace " + this.$store.getters.token
            },
            requestUrl:process.env.BASE_API+'search/',
            //羣組數據
            groups:[],
            // search result
            searchResult:{
              id:0,name:''
            },
            selectText:'name',
            searchValue:[
              {
                value: 'name',
                label: '文件'
              },
              {
                value: 'tag',
                label: '標籤'
              }
            ],
            getSelectValue:'',
            serachResultValue:[],
            serachAccount:0,
            groupFlag:0,
            folderFlag:null,
            //選中某一個的值
            selectedList:[],
            //全選中以後獲取的值
            selectedAllList:[],
            //去生數組
            repeatArray:[],
            //交集
            selectIntersectionSet:[],
            //記錄羣組標記
            groupName:null,
        }
    },
    mounted: function(){
      // 獲取當前的目錄信息,如果沒有folderID,則是根目錄,則爲0。
        let folderExistIndex = Object.keys(this.$route.params).indexOf('folderId');
        let folderId = folderExistIndex ==-1 ? 0 : parseInt(this.$route.params.folderId);
        this.folder.id = folderId;
        if (folderId!=0){
            // 獲取非根目錄下的文件夾信息。
            this.groupDisabled = true
            this.getFolder(folderId);
        }
        else{
            // 獲取根目錄下的資源。
            this.getResource();
        }
      if(this.$store.getters.role=='user'){
        this.showUser = true
      }
      if(this.space == "public"){
          this.showAllShared = false
      }
      if(this.$store.getters.role=='user'&&this.space == "public"){
          this.isShowBatch = false
      }else{
         this.isShowBatch = true
      }
    },
    methods:{
      //授索回來的值
        searchResValue(response){
          this.serachAccount = 0;
          this.hidingDetail = true
          this.resourceGrid.table = 24
          let resp = response.data;
          this.serachResultValue = [];
          if(resp.success == true){
          //批量刪除按鈕是不要打開
          this.isBatchBth = true
          resp.data.results.forEach((item, index, array) => {
            let isFile = item.is_file;
            let size = CapacityAPI.bytesToSize(item.size);
            if(isFile == false){
              size="- -";
            }else{
              size
            }
            let directoryName = null;
            let directoryId = 0;
            let tags = item.tag_set;
            item.directory.forEach((self,index,array)=>{
              if(index>0){
                directoryName = array[index].name +" > "+ directoryName ;
              }else{
                directoryName = array[index].name;
                directoryId = array[index].id;
              }
            })
            this.serachResultValue.push({
              id:item.id,
              name:item.name,
              size:size,
              isFile:isFile,
              from:item.group,
              directoryName:directoryName,
              directoryId:directoryId,
              update_time:item.update_time,
              download_url:item.download_url,
              tags:tags,
              directory:item.directory,
            });
            this.serachAccount = resp.data.count;
            this.pager.total = resp.data.count;
          })
        }

      },
        //是否有授索值
        showIsBatchBth(value){
          if(value == ''){
            this.isBatchBth = true;
            this.openSearch = false;
            this.showTable = true;
            if(this.folder.id != 0){
              this.refreshFolder()
            }else {
              this.refreshTable()
            }
          }else{
            this.isBatchBth = true
            this.openSearch = true
            this.showTable = false
          }

        },

        handleResource(targetID, isFile, event,obj){
            if(isFile == true){

            }
            else{
                // 阻止事件冒泡
              event.cancelBubble = true;
                // 跳轉到下級目錄
              this.$router.push({ path: this.$route.meta.activatedPath+"/"+targetID })
            }
        },

        getSearchValue(item){
           this.getSelectValue = item;
        },

        getGroupValue(item){
          if(this.folder.id != 0){
            this.groupId = null;
          }else{
            this.groupId = item;
          }

        },

        changePage(pageIndex){
            this.pager.index = pageIndex;
            this.getResource();
        },

        serachChangePage(pageIndex){
          this.pagerIndex = pageIndex;
          RestVue.$emit('pagerIndexFun',  this.pagerIndex)
        },

        getFolder(folderId, isFile,clickPath){
          if(clickPath == true){
            this.$router.push({ path: this.$route.meta.activatedPath+"/"+folderId })
          }
          this.openSearch = false
              this.showTable = true
              ResourceAPI.get(folderId).then(response=>{
                let resp = response.data;
                if(resp.success==true){
                  // 綁定屬性
                  let folderItem = resp.data;
                  this.folder.parentId = folderId;
                  folderItem.results.forEach((item, index, array) => {
                    this.folder.id = item.id;
                    this.folder.name = item.name;
                  })
//                    // 獲取文件夾路徑
                  this.getPathList(folderId, isFile);
                  // 獲取目錄下的資源。
//                    this.getResource();
                  this.handleResourceList(response);
                  this.openSearch = false;
                  this.inputValue = "";
                }
              });
        },

        getPathList(folderId, isFile){
            ResourceAPI.singleTage(folderId).then(response=>{
              let resp = response.data;
              if(resp.success==true){
//              this.folder.tree = [];
                if(isFile) {
                  this.folder.tree = [];
                  this.folder.tree.unshift( {id:0, name:'root', path:this.$route.meta.activatedPath})
                }
                resp.data.directory.reverse().forEach((folerItme, index, array) =>{
                  this.folder.tree.push({
                    id:array[index].id,
                    name:array[index].name,
                    path:this.$route.meta.activatedPath+"/"+array[index].id
                  })
                });
                this.folder.tree.push({
                  id:resp.data.id,
                  name:resp.data.name,
                  path:null
                })
                this.groupName = resp.data.group
                resp.data.group == null? this.groupId = null: this.groupId = resp.data.group.id
              }

            });
        },

        getResource(){
            // 我的空間List
            if(this.space=="private"){
              let privateParams= {
                page_index:this.pager.index,
                pageSize:this.pager.size,
                search:"private",
                ordering:"id",
              }
                ResourceAPI.list(privateParams).then(response=>{
                  this.handleResourceList(response);
                });
            }
            //  公共空間List
            else if(this.space=="public"){
              let publicParams= {
                page_index:this.pager.index,
                pageSize:this.pager.size,
                search:"public",
                ordering:"id"
              }
              ResourceAPI.list(publicParams).then(response=>{
                this.handleResourceList(response);
              });
            }
        },

        handleResourceList(response){
            this.files = []; // clear the file data
            let resp = response.data;
//             console.log(resp);
            if(resp.success == true){
                resp.data.results.forEach((item, index, array) => {
                    let size = CapacityAPI.bytesToSize(item.size);
                    let isFile = item.is_file;
                    if(isFile == false){
                      size="- -";
                    }else{
                      size
                    }
                    let tags = item.tag_set;
                    // Add the user into array
                    this.files.push({
                        id:item.id,
                        name:item.name,
                        size:size,
                        isFile:isFile,
                        from:item.group,
                        update_time:item.update_time,
                        download_url:item.download_url,
                        tags:tags,
                        directory:item.directory,
                    });
                })
                this.pager.total = resp.data.count;
            }
        },

        refreshTable(){
            this.getResource();
        },

        refreshFolder(){
            let tamp_list = [];
            tamp_list.push(this.folder.tree[0]);
            this.folder.tree = tamp_list;
            this.getFolder(this.folder.parentId);
        },

        refreshResultSerach(){
          RestVue.$emit('refreshResultSerach', true)
        },

        changeSelected(name,id,isFile,resourceName,tags,search){
          this.modifyResourceId=id;
          if(name=='delete'&&isFile==true){
            this.delteFile(id,resourceName,search);
          }
          else if(name=='delete'&&isFile==false){
            this.delteFolders(id,resourceName,search);
          }
          else if(name=='update'&&isFile==true){
            this.updateFiles(id,isFile,resourceName,tags,search);
          }
          else if(name=='update'&&isFile==false){
            this.updateFolders(id,isFile,resourceName);
          }
          else if(name=='copy'&&isFile==true){
            this.copingFile =true;
            this.modifyIsFile = true;
            this.serachResult = search

          }
          else if(name=='copy'&&isFile==false){
            this.copingFile =true;
            this.modifyIsFile = false;
          }
          else if(name=='move'&&isFile==true){
            this.movingFile = true;
            this.modifyIsFile = true;
            this.serachResult = search
          }
          else if(name=='move'&&isFile==false){
            this.movingFile = true;
            this.modifyIsFile = false;
          }
        },

      //刪除文件
        delteFile(id,resourceName,search){
          this.$Modal.confirm({
            title:'警告',
            content: `確定要刪除文件【${resourceName}】嗎?`,
            okText:'刪除',
            cancelText:'取消',
            loading:this.loading,
            onOk:()=>{
              this.load = this.$Message.loading({
                content: 'Loading...',
                duration: 0
              });
              ResourceAPI.file_delete(id).then((response)=>{
                if(response.status==204){
                    if( this.folder.id != 0){
                      this.refreshFolder();
                    }
                    else if(search == true){
                      this.refreshResultSerach()
                      this.refreshTable();
                    }
                    else{
                      this.refreshTable(); //更新列表
                    }
                  this.$Notice.success({
                    title: "刪除文件成功!",
                    duration:2.5
                  });
                  this.$Message.destroy();
                }
                else{
                  this.$Notice.error({
                    title: response.data.message,
                    duration:2.5
                  });
                  this.load = setTimeout(() => {
                    this.$Message.destroy();
                  },500)
                }
              }).catch(error => {

              });
            },
            onCancel:()=>{
              this.$Message.destroy();
              this.$Modal.remove()
            }
          });
        },

      //刪除文件夾
        delteFolders(id,resourceName){
        this.$Modal.confirm({
          title:'警告',
          content: `確定要刪除文件夾【${resourceName}】嗎?`,
          cancelText:'取消',
          okText:'刪除',
          loading:this.loading,
          onOk:()=>{
            this.load = this.$Message.loading({
              content: 'Loading...',
              duration: 0
            });
            ResourceAPI.folders_delete(id).then((response)=>{
              this.loading = false;
              if(response.status==204){
                this.$Notice.success({
                  title: "刪除文件夾成功!",
                  duration:2.5
                });
                this.$Message.destroy();
                if( this.folder.id != 0){
                  this.refreshFolder()
                }else{
                  this.refreshTable(); //更新列表
                }
              }
              else{
                this.$Notice.error({
                  title: response.data.message,
                  duration:2.5
                });
                this.load = setTimeout(() => {
                  this.$Message.destroy();
                },500)
              }
            }).catch(error => {
            });
          },
          onCancel:()=>{
            this.$Message.destroy();
            this.$Modal.remove()
          }
        });
      },

      //選中單個事件的時候觸發
      selectedItem(item){
        if(this.isRemoveBatch == true){
          this.selectedList = []
        }
        item.length == 0?this.isBatchBth = true: this.isBatchBth = false
        let tempArr = []
        item.forEach((item,index,array) => {
          tempArr.push(item.id)
          this.selectedList.push(item.id)
          this.repeatArray = Array.from(new Set( this.selectedList));
        })
          let Array1 =  tempArr;
          let Array2 =  this.selectedList;
          let a = new Set(Array1);
          let b = new Set(Array2);
          // 交集
          let intersectionSet = new Set([...a].filter(x => b.has(x)));
          this.selectIntersectionSet = Array.from(intersectionSet);
      },

      //批量刪除
      remvoeAllDelete(){
        this.$Modal.confirm({
          title:'警告',
          content: `您確定要批量刪除嗎?`,
          cancelText:'取消',
          okText:'刪除',
          loading:this.loading,
          onOk:()=>{
            this.load = this.$Message.loading({
              content: 'Loading...',
              duration: 0
            });
            BatchAPI.delBatch(
                this.$store.getters.id,
                this.selectIntersectionSet
            ).then((response)=>{
              this.loading = false;
              if(response.status==204){
                this.$Notice.success({
                  title: "批量刪除成功!",
                  duration:2.5
                });
                this.isRemoveBatch = true
                this.$Message.destroy();
                this.isBatchBth = true
                if( this.folder.id != 0){
                  this.refreshFolder()
                } else if(this.openSearch == true){
                  this.refreshResultSerach()
                }
                else{
                  this.refreshTable(); //更新列表
                }
              }
              else{
                this.$Notice.error({
                  title: response.data.message,
                  duration:2.5
                });
                this.load = setTimeout(() => {
                  this.$Message.destroy();
                },500)
              }
            }).catch(error => {
            });
          },
          onCancel:()=>{
            this.$Message.destroy();
            this.$Modal.remove()
          }
        });
      },

      //更新文件
        updateFiles(id,isFile,resourceName,tags,serach){
          this.serachResult = serach
          this.updateFile = true;
          this.modifyResourceId = id;
          this.modifyResourceName = resourceName;
          this.tags = tags;
        },

      //更新文件夾
        updateFolders(id,isFile,resourceName){
          this.updateFolder = true;
          this.modifyResourceId = id;
          this.modifyResourceName = resourceName;
        },

        //分享
        getShare(isFile,id,name){
            this.shareFolder = true;
            this.modifyIsFile = isFile;
            this.modifyResourceId = id;
            this.modifyResourceName = name;
        },

      //批量分享
      batchShared(){
        this.isBatchShared = true;
      },

//     重至批量分享
      restBatchShared(boolen){
        this.isRemoveBatch = boolen
        if(boolen == true){
          this.isBatchBth = true
        }
      },

      //批量移動
      batchMove(){
          this.isBatchMove = true;
      },

      //批量複製
      batchCopy(){
        this.isBatchCopy = true
      },

      //點擊下載
      clkicDownload(isFile){
        if(isFile&&this.folder.id != 0){
          this.refreshFolder()
          this.isBatchBth = true;
        }else{
          this.refreshTable()
          this.isBatchBth = true ;
        }
      },

        // 關閉Modal
        closedModal () {
            this.uploading = false;
            this.creatingFolder = false;
            this.movingFile = false;
            this.copingFile = false;
            this.shareFolder = false;
            this.updateFolder = false;
            this.updateFile = false;
            this.isBatchShared = false;
            this.isBatchMove = false;
            this.isBatchCopy = false;

        },

        showDetail(targetID,isFile){
              this.hidingDetail = false;
              this.modifyResourceId = targetID;
              this.modifyIsFile = isFile;
              this.resourceGrid.table = 17;
              this.resourceGrid.detail = 7;
        },

        closedDetail(){
            this.hidingDetail = true;
            this.modifyIsFile = true;
            this.modifyResourceId = 0;
            this.modifyResourceName = '';
            this.resourceGrid.table = 24;
            this.resourceGrid.detail = 0;
        },

        isUploadDisabled(value){
           this.uploadDisabled  = value
        }
    },
}

iview upload組件的應用

<template>
    <Modal v-model="opened" :closable="false" :mask-closable="false" @on-cancel="cancel">
        <div slot="header">
            <h3>上傳文件</h3>
        </div>
        <Upload
            ref="upload"
            multiple
            type="drag"
            :data="uploadParams"
            :before-upload="handleUploadBefore"
            :on-progress="handleUploadProgress"
            :on-remove="handleUploadRemove"
            :on-success="handleUploadSuccess"
            :on-error="handleUploadError"
            :action="uploadURL">
           <div style="padding: 20px 0">
                <Icon type="ios-cloud-upload" size="52" style="color: #3399ff"></Icon>
                <p>點擊或將文件拖拽到這裏上傳</p>
            </div>
            
        </Upload>
        <div slot="footer">
            <Button type="ghost" @click="cancel" style="margin-left: 8px">取消</Button>
        </div>
    </Modal>
</template>

<script>
import ResourceAPI from 'api/resource';

export default {
    props:{
        opened:{
            type:Boolean,
            default:false
        },
        space:{
            type:String,  // ['PUB','GRO','PER']
            default:''
        },
        groupId:{
            type:Number,
            default:0
        },
        folderId:{
            type:Number,
            default:0
        }
    },
    data(){
        return{
            uploading:false,
            uploadParams:{},
            uploadURL:process.env.BASE_API+"file_upload/",
            fileList:[],
        }
    },
    watch:{
        opened:function(value,oldValue){
            if(value==true){
                // 更改上傳的額外信息
                this.uploadParams={
                    type:this.space,
                    directory:this.folderId,
                    group:this.groupId,
                }
            }
        }
    },
    methods:{
        handleUploadBefore (file) {
            this.fileList = this.$refs.upload.fileList;
            // return false; // 返回 false則不讓其上傳。
        },
        handleUploadProgress(event, file, fileList) {
        },
        handleUploadRemove(file, fileList){
            console.log("移除文件");
            console.log(file);
        },
        handleUploadSuccess(response, file, fileList){
            console.log("上傳成功");
            console.log(response);
            console.log(file)
            this.$emit('uploaded');
        },
        handleUploadError(error, file, fileList){
            console.log("上傳失敗");
            console.log(response);
            console.log(file)
        },
        cancel(){
            this.$refs.upload.fileList = [];
            this.$emit('closedModal');
        }
    }
}

// <Button type="ghost" icon="ios-cloud-upload-outline">上傳文件</Button>
</script>

vue-cli項目在IE中運行

問題

  • ie11打開vue2.0項目空白,控制檯報錯 vuex requires a Promise polyfill in this browser;

解決方法

  • npm install --save-dev babel-polyfill
  • 在build文件下找到webpack.base.conf.js
  • 如圖:

輸入圖片說明

  • 大約在第10行位置替換
entry: {
    // app: './src/main.js'
     app: ['./node_modules/babel-polyfill/dist/polyfill.js','./src/main.js']
  },

vue-cli項目https協議登錄不進火狐瀏覽器

解決方法

問題點input type='file'的時候,vue怎麼讀取

  • input type='file' @change='importLicense($event)'
  • 在methods裏添加importLicense($event)方法,
 importLicense($event){
            //讀取文件的值
             let _this = this
            let file = $event.target.files
            for (var i = 0, f; f = file[i]; i++) {
              let reader = new FileReader(file);
              reader.onload = (function (file) {
                return function (e) {
                  _this.license = reader.result
                };
              })(f);
              //讀取文件內容
              reader.readAsText(f);
            }
          },
  • 例如:
<template>
  <Modal v-model="opened" title="許可證更新" :closable="false"   @on-cancel="cancel" >
        <Row>
           <textarea v-model='license'  rows="3" cols="20" style="resize: none; height: 150px;width:400px;" >
           </textarea>
          <Button type="primary"  style="position: absolute;display: inline-block;top: 10px;right: 0px;">
            <span>導入</span>
            <input @change='importLicense($event)'  style="position: absolute;height: 30px;right: 0;top: 0;opacity: 0; width: 90px;" name="file" type="file">
          </Button>
        </Row>
        <div slot="footer">
          <Button type="ghost"  @click="cancel"  style="margin-left: 8px;">取消</Button>
          <Button type="primary"  :loading='loading' @click='updateLicense'  style="margin-left: 8px;">提交</Button>
        </div>
  </Modal>
</template>

<script>
    import LicenseApi from '@/api/license'
    export default {
        name: "update",
        props:{
          opened:{
            type:Boolean,
            default:false,
          },
          license:{
            type:String,
            default:''
          }
        },
        data(){
            return{
              licenses:'',
              loading:false,
              load:'',
            }
        },

        methods:{
          //導入license
          importLicense($event){
            //讀取文件的值
             let _this = this
            let file = $event.target.files
            for (var i = 0, f; f = file[i]; i++) {
              let reader = new FileReader(file);
              reader.onload = (function (file) {
                return function (e) {
                  _this.license = reader.result
                };
              })(f);
              //讀取文件內容
              reader.readAsText(f);
            }
          },
          cancel () {
            this.$emit('closedModal');
          },
          //更新license
          updateLicense(){
            if( this.license.split(" ").join("").length == 0){
              this.$Notice.error({
                title: '許可證不能爲空!',
                duration:2.5
              });
            }else{
              this.loading = true
              this.load = this.$Message.loading({
                content: 'Loading...',
                duration: 0
              });
              LicenseApi.update_license({license:this.license}).then(response=>{
                let resp = response.data
                if(resp.success == true){
                  this.$Notice.success({
                    title: '許可證修改成功!',
                    duration:2.5
                  });
                  this.loading = false
                  this.load = this.$Message.destroy();
                  this.$emit('closedModal');
                  this.$emit('refreshLicense');
                }else{
                  this.$Notice.error({
                    title: '許可證修改失敗!',
                    duration:2.5
                  });
                  this.loading = false
                }

              }).catch(err=>{
                console.log(err);
              })
            }
          }
        },
        mounted(){

        }
    }
</script>

<style scoped>

</style>

問題點:webuploader支持上傳文件夾

  • 修改webuploader插件
  • 1.在大概4880行代碼左右,在動態生成的input組件的下面,增加webkitdirectory屬性 如圖:

輸入圖片說明

        return Html5Runtime.register( 'FilePicker', {
            init: function() {
                var container = this.getRuntime().getContainer(),
                    me = this,
                    owner = me.owner,
                    opts = me.options,
                    label = this.label = $( document.createElement('label') ),
                    input =  this.input = $( document.createElement('input') ),
                    arr, i, len, mouseHandler;

                input.attr( 'type', 'file' );
                input.attr( 'name', opts.name );
                input.attr( 'webkitdirectory', '')
                input.addClass('webuploader-element-invisible');

                label.on( 'click', function() {
                    input.trigger('click');
                });

修改以後

輸入圖片說明

問題點:iview 和webuploader實現多文件上傳和選擇目錄上傳

  • 複製一分webuploader.js 更改名:webuploaderFolder.js

輸入圖片說明

  • 更改webuploaderFolder

輸入圖片說明

例如:修改的地方
  origin = root.WebUploaderFolder;
        root.WebUploaderFolder = makeExport();
        root.WebUploaderFolder.noConflict = function() {
            root.WebUploaderFolder = origin;
        };

問題點webuploader只能獲取文件的相對路徑

  • 通過file.source.source.webkitRelativePath拿到文件的相對路徑
   /**
         * 文件剛加進來的時候
         */
        _this.uploaderFolder.on( 'fileQueued', function( file ) {
          file.source.source.webkitRelativePath
          // _this.uploadFileQueued(file)
        });
  • 但是文件路徑只能拿到上一層文件夾的路徑
  • 例如路徑:["b/d/11.txt", "b/c/新建文本文檔.txt", "b/c/e/f/g/11.txt"]
  • 要求完整的路徑是:["b/d", "b/c", "b/c/e/f/g", "b", "b/c/e", "b/c/e/f"]

webkitdirectory屬性支持文件夾上傳,但不是標準的元素

  • 例如:

<!DOCTYPE html>  
<html>  
<head>  
    <meta charset="UTF-8">  
    <title>上傳file屬性</title>  
    <script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
</head>  
<body>  
  <input id="dialog" type="file" webkitdirectory=''  >
</body>

    <script>
    dialog.onchange = function(e) {
        var files = this.files;
        var table = [];

        for (var i = 0; i < files.length; i++) {
            var f = files[i];
            table.push(f.webkitRelativePath)

        }
         let temp = []
         let tempArray  = []
         let new_array = []
        table.forEach((item,index,array)=>{  
                let file =   item.substring(0,item.lastIndexOf('/'))
                temp.push(file)
        })

        console.log(table)
         temp.forEach((item,index,array)=> {
                let list = item.split("/")
                let list_len = list.length
                let lens = Array.from({length:list_len}, (v,k) => k); //動態指定生成數組的大小
                console.log(lens)
            
                lens.forEach((self,index,array)=>{
                    let ele = list.slice(0,index+1).join("/")
                    // console.log(ele)
                   tempArray.push(ele) 
                    //  console.log(ele)
                })
               
         });
          let tempPath = Array.from(new Set(tempArray));
         console.log(tempPath) //["b/d", "b/c", "b/c/e/f/g", "b", "b/c/e", "b/c/e/f"]
    };
</script>  
</html>  

問題點:webpuloader在批量上傳時,切片的順序和切片名稱錯亂問題

  • 解決方法:修改webuploader插件,大約在6758位置,添加你的fordata.task_id後端約定好的字段等於你添加的fromdata屬性

輸入圖片說明

  • 引用
 <script src="/static/wepUpload/js/webuploaderFolder.js"></script>

上傳按鈕的傳參

  • html
<Dropdown @on-click='uploaderTypeOpen' style="margin-left: 5px">
                <Button type="ghost">
                 上傳
                  <Icon type="android-upload"></Icon>
                </Button>
                <DropdownMenu slot="list">
                  <DropdownItem name='file'>文件</DropdownItem>
                  <DropdownItem name='folder' divided>文件夾</DropdownItem>
                </DropdownMenu>
  </Dropdown>
  • js
<script>
    export default {
        data () {
            return{
                uploaderFolder:null,
            }
        },
        methods:{
            //上傳組件的打開
          uploaderTypeOpen(name){
            this.uploading = true
            this.uploaderFolder = name
            },
        }
           
    }
<script>

上傳的組件封裝

<template>
    <Modal v-model="opened" :closable="false" :mask-closable="false" @on-cancel="cancel" >
        <div slot="header">
            <h5>上傳文件</h5>
        </div>
      <div class="uploadContent">
        <div  id="uploadWarp" style=" padding: 20px 0;">
          <Icon type="ios-cloud-upload" size="52" style="color: #3399ff"></Icon>
          <p>點擊或將文件拖拽到這裏上傳</p>
        </div>
      </div>

      <Row style='padding-top: 15px;'>
        <Col span='24'>
          <Row type="flex" justify="start" style='padding-bottom: 15px;'>
            <Col span='6'>
            <span style='margin-bottom: 10px; font-weight: 900;'> 文件列表 </span>
            </Col>
            <Col span='10'  offset="8" >
              <div style='width: 230px;'>
                <span style='position: absolute; left: -72px;top: 0;'>上傳總進度:</span>
                <Progress :percent="allFilePercentage" :status="active"  ></Progress>
              </div>
            </Col>
          </Row>
          <Table :data='fileList' :no-data-text='tabNoDataTitle' size="small"  :columns="columns" border height="260"></Table>
        </Col>
      </Row>
        <div slot="footer">
            <Button id="btn" size="small" :disabled="uploadDisabled"  type="ghost" @click="cancel" style="margin-left: 8px">取消</Button>
            <Button size="small" id="ctlBtn" span="5" offset="7" :disabled="uploadBtnDisabled"  type="primary" :loading='uploading'>{{title}}</Button>
        </div>
    </Modal>
</template>
<style>
  .uploadContent{
    background: #fff;
    border: 1px dashed #dddee1;
    border-radius: 4px;
    text-align: center;
    cursor: pointer;
    position: relative;
    overflow: hidden;
    transition: border-color .2s ease;
  }
  .uploadContent:hover {
    border: 1px dashed dodgerblue;
  }


</style>
<script>
import ResourceAPI from 'api/resource';
import { Icon, Button,Progress } from 'iview';
export default {
    props:{
        opened:{
            type:Boolean,
            default:false
        },
        foldered:{
            type:String,
            default:''
        },
        space:{
            type:String,  // ['PUB','GRO','PER']
            default:''
        },
        groupId:{
            type:Number,
            default:0
        },
        folderId:{
            type:Number,
            default:0
        },
        openSearch:{
          type:Boolean,
          default:false
         }

    },

    data(){
      const columns = [
        { title: '文件名', key: "fileName",width:'20%',
          render:(h,params)=>{
            let fileName = params.row.fileName;
            let namePoint = '';
            if(fileName.length>15){
              namePoint+=fileName.slice(0, 15)+'...'
            }else{
              namePoint+=fileName
            }
            return(
              <div >
                <span domPropsInnerHTML={namePoint} title={fileName}></span>
              </div>
            )
          }

        },
        { title: '大小', key: "fileSize"},
        { title: '進度',textAlign:'center', width:'30%',
          render:(h,params)=>{
            let filePercentage = params.row.filePercentage
            return(
              <div>
                <Progress style={{ width:'150px'}} percent={ filePercentage} ></Progress>
              </div>
          )
          },
        },
        { title: '操作',width:'20%',
          render:(h,params)=>{
            let fileId = params.row.fileId
            let fileName = params.row.fileName
            //   <Button  title='開始上傳' onClick={()=>this.startFile(fileId)} size="small" ><Icon type="close"></Icon> </Button>
            // <Button  title='停止上傳' onClick={()=>this.stopFile(this.uploaderFile,fileId)} size="small" ><Icon type="close"></Icon> </Button>
            return(
              <div  style={{ textAlign: 'center' }}  >
              <Button  title='取消上傳' onClick={()=>this.deleFile(fileId,fileName)} size="small" ><Icon type="close"></Icon> </Button>
              </div>
          )
          },
        },
      ];
        return{
            uploading:false,
            uploadDisabled:false,
            uploadBtnDisabled:false,
            title:'開始上傳',
            uploadParams:{},
            uploadHeaders:{
                Authorization:"conspace " + this.$store.getters.token
            },
            uploadURLServer:process.env.BASE_API+"upload/fragment/",
            uploadURLSend:process.env.BASE_API+"upload/fragment/success/",
            fileList:[],
            uploader:null,
            uploaderFolder:null,
            uploaderId:null,
            netWork:false,
            tabNoDataTitle:'暫無上傳文件',
            columns:columns,
            uploaderFile:[],
            allFilePercentage:0,
            active:'active',
            pathArray:[],
            progressFile:0,
            fileProgressId:0,
            resultPathFile:[],
            resultPathFileCopy:[],
            sendFilePathArray:[],

            fileFolderIdItem:{},
            fileFolderId:0,
            fileIndex:0,
            fileEndIndex:0,
            fileFolderEndIndex:0,


        }
    },
    watch:{
        opened:function(value,oldValue){
            if(value==true){
                // 更改上傳的額外信息
              if(this.foldered == 'file'){
                //上傳文件
                this.initUpload()
              }else{
                //上傳文件夾
                this.initUploadFolder()
              }
            }
        }
    },
    methods:{
      // //開始上傳
      // startFile(fileId){
      //   this.uploader.upload(fileId)
      // },
      // //停止上傳
      // stopFile(file,fileId){
      //   file.forEach((item,index,array) => {
      //       if(fileId == item.id){
      //         this.uploader.stop(item);
      //         this.uploader.refresh()
      //       }else{
      //         return
      //       }
      //   })
      // },

      //刪除文件
      deleFile(fileId,fileName,){
        this.fileList.forEach((item,indexFile,array)=>{
          this.fileIndex = 0
          this.uploaderFile.forEach((self,index,array) =>{
            if(item.fileId ==self.id && item.fileId ==fileId){
              if(this.foldered == 'file'){
                this.uploader.cancelFile(self);
                this.uploader.removeFile(self,true );
                this.uploader.refresh()
                this.fileList.splice(indexFile,1)
              }else{
                this.uploaderFolder.cancelFile(self);
                this.uploaderFolder.removeFile(self,true );
                this.uploaderFolder.refresh()
                this.fileList.splice(indexFile,1)
              }
            }else{
              return
            }
          })
          if(item.fileId ==fileId){
            if(this.fileList.length == 0 || this.fileList.length != 0){
              this.allFilePercentage = 0
            }
          }
        })
      },






      //上傳文件初始化
      initUpload () {
        let _this = this;
        let uploadURLSend = this.uploadURLSend;
        let folderId = this.folderId == 0? '':this.folderId;
        let groupId = this.groupId == 0? '':this.groupId;
        let type = this.space;
        _this.uploader = WebUploader.create({
          server: _this.uploadURLServer,//上傳路徑
          dnd:"#uploadWarp",//上傳的位置
          pick: {
            id:"#uploadWarp",
            multiple:true
          },
          duplicate:false,
          prepareNextFile: true,
          auto: false,
          chunked: true,
          chunkSize: 20 * 1024 * 1024,
          fileNumLimit:100,
          fileSingleSizeLimit: 100* 1024 * 1024*1024,// 限制在100G
          chunkRetry: 2,
          threads: 1,
          compress: false,
          resize: false,
          // formData: {
          //   task_id: fileMd5
          // }
        });

        /**
         * 驗證文件格式以及文件大小
         */
        _this.uploader.on("error",function (type,handler){
          if(type=="F_EXCEED_SIZE"){
            _this.$Notice.error({
              title: '文件大小不能超過100G',
              duration:2.5
            });
          }else if (type === 'Q_EXCEED_NUM_LIMIT') {
            _this.$Notice.error({
              title: '文件上傳已達到最大上限數',
              duration:2.5
            });
          }

          else {
            _this.$Notice.error({
              title: `上傳出錯!請檢查後重新上傳!錯誤代碼${type}`,
              duration:10
            });
          }
        });

        /**
         * 文件剛加進來的時候
         */
        _this.uploader.on( 'fileQueued', function( file ) {
          _this.uploaderFile.push (file)
          _this.fileList.push({
            fileName:file.name,
            fileId:file.id,
            fileSize:WebUploader.Base.formatSize(file.size),
            filePercentage:0,
          })
        });

        /**
         * 文件剛開始的時候上傳的時候
         */
        _this.uploader.on('uploadStart', (file) => {
          // 在這裏可以準備好formData的數據
          _this.uploader.options.formData.task_id = file.id

          //   // _this.keyGenerator(file);
          // task_id = _this.keyGenerator(file)
        });

        // 文件上傳過程中創建進度條實時顯示。
        _this.uploader.on( 'uploadProgress', function( file, percentage ) {
          if(_this.fileIndex < _this.fileList.length){
              if(percentage < 1){
                _this.fileList[_this.fileIndex].filePercentage = parseInt(percentage.toFixed(2) * 100)
              }else{
                _this.fileList[_this.fileIndex].filePercentage = parseInt(percentage.toFixed(2) * 100)
                _this.fileIndex++
              }
              let fileCount = 0
              _this.fileList.forEach((item,index,array)=>{
                fileCount += item.filePercentage
              })
            _this.allFilePercentage = parseInt((fileCount / (_this.fileList.length * 100)).toFixed(2) * 100)
          }
        });

        // 文件上傳成功。
        _this.uploader.on('uploadSuccess', function(file) {
          var data = {
            'task_id':file.id,
            'ext': file.source['ext'],
            'type': file.source['type'],
            'name': file.source['name']
          };
          $.ajax({
            type: "get",
            url: uploadURLSend,
            data: data,
            success: function (data) {
              let fileName = data.data.file_name
              let fileId = data.data.file_id
              if(data.success == true){
                _this.uploadDisabled = true
                _this.$Notice.success({
                  title: "文件:"+fileName+"上傳成功!",
                  duration:2.5
                });

                _this.fileEndIndex++

                if(_this.fileEndIndex == _this.fileList.length){
                  debugger
                  _this.$emit('closedModal');
                  _this.fileList = []
                  _this.allFilePercentage = 0
                  _this.fileIndex = 0
                  _this.uploadDisabled = false
                  _this.fileEndIndex=0;
                  _this.uploader.destroy()
                  _this.uploader.reset()
                  _this.uploader.refresh()
                  _this.$emit("refreshTable")
                  if(_this.folderId == 0 && _this.openSearch == false){
                    _this.$emit("refreshTable")
                  }
                  else if(_this.folderId != 0 && _this.openSearch == false){
                    _this.$emit("uploadedFolder")
                  }
                  else if(_this.openSearch == true){
                    _this.openSearch == true?_this.$emit("refreshSearch"):_this.openSearch = false
                  }

                  if(_this.netWork == true){
                    setTimeout(() => {
                      _this.$router.go(0)
                    },500)
                  }

                }

                // _this.$emit('closedModal');
                uploadSend(fileName,fileId)
              }
            }
          });


        });

        //文件上傳報錯
        _this.uploader.on('uploadError', function(file) {
          _this.uploadDisabled = false
          _this.netWork = true
          _this.uploadBtnDisabled = true
          _this.$Message.destroy()
          _this.$Notice.error({
            title: '上傳出錯,請重新再傳!',
            duration:2.5
          });
          _this.uploading = false;
          _this.title = '上傳終止'
          _this.uploader.destroy()
          _this.uploader.reset()
        });
        //文件上傳完成
        _this.uploader.on('uploadComplete', function(file) {

        });
        //文件加載完成
        _this.uploader.on('uploadFinished', function () {
          //清空隊列
          _this.uploader.reset();
        });

       function uploadSend(fileName,fileId){
          ResourceAPI.upload(fileName,String(groupId) || '',type,fileId,String(folderId) || '').then(response=>{
            let resp = response.data
            if(resp.success == true){

              _this.$Message.destroy();
              _this.uploadDisabled = false
              _this.$Notice.success({
                title: "文件:"+fileName+"校驗成功!",
                duration:2.5
              });
              _this.$emit('uploadDisabled', false)
              _this.$emit('restUpload',true)
              _this.uploading = false

              // if(_this.folderId == 0 && _this.openSearch == false){
              //   _this.$emit("refreshTable")
              // }
              //
              // else if(_this.folderId != 0 && _this.openSearch == false){
              //   _this.$emit("uploadedFolder")
              // }else if(_this.openSearch == true){
              //   _this.openSearch == true?_this.$emit("refreshSearch"):_this.openSearch = false
              // }

            }else{
              if(resp.code == 400){
                _this.$Notice.error({
                  title: response.data.message.slice(7),
                  duration:2.5
                });
              }else{
                _this.$Notice.error({
                  title: response.data.message.slice(7),
                  duration:2.5
                });
              }
              _this.uploading = false
              _this.uploadDisabled = false
              _this.$emit('uploadDisabled', false)
              _this.upload = setTimeout(() => {
                _this.$Message.destroy();
              },500)

              // _this.$emit('closedModal');
            }

          });
        }
      },


      //上傳文件夾初始化
      initUploadFolder () {
        let _this = this;
        _this.uploaderFolder = WebUploaderFolder.create({
          server: this.uploadURLServer,//上傳路徑
          dnd:"#uploadWarp",//上傳的位置
          pick: {
            id:"#uploadWarp",
            multiple:true
          },
          duplicate:false,//同一文件是否可重複選擇
          prepareNextFile: true,
          auto: false,
          chunked: true,
          chunkSize: 20 * 1024 * 1024,
          // fileNumLimit:100,
          fileSingleSizeLimit: 100* 1024 * 1024*1024,// 限制在100G
          chunkRetry: 2,
          threads: 1,
          compress: false,
          resize: false,
          // formData: {
          //   task_id: task_id
          // }
        });

        // /**
        //  * 驗證文件格式以及文件大小
        //  */
        _this.uploaderFolder.on("error",function (type,handler){
            _this.uploadError(type)
        });

        /**
         * 文件剛加進來的時候
         */
        _this.uploaderFolder.on( 'fileQueued', function( file ) {
          _this.uploadFileQueued(file)
        });

        /**
         * 文件剛開始的時候上傳的時候
         */
        _this.uploaderFolder.on('uploadStart', (file) => {
          // 在這裏可以準備好formData的數據
          _this.uploaderFolder.options.formData.task_id = file.id;
          // _this.task_id = _this.keyGenerator(file)
        });

        // 文件上傳過程中創建進度條實時顯示。
        _this.uploaderFolder.on( 'uploadProgress', function( file, percentage ) {
          if(_this.fileIndex < _this.fileList.length){
            if(percentage < 1){
              _this.fileList[_this.fileIndex].filePercentage = parseInt(percentage.toFixed(2) * 100)
            }else{
              _this.fileList[_this.fileIndex].filePercentage = parseInt(percentage.toFixed(2) * 100)
              _this.fileIndex++
            }
            let fileCount = 0
            _this.fileList.forEach((item,index,array)=>{
              fileCount += item.filePercentage
            })
            _this.allFilePercentage = parseInt((fileCount / (_this.fileList.length * 100)).toFixed(2) * 100)

          }
        });
          // 文件上傳成功。
          _this.uploaderFolder.on('uploadSuccess', function(file,respson) {
              let pathFile =file.source.source.webkitRelativePath.substring(0,file.source.source.webkitRelativePath.lastIndexOf('/'))
              let pathAllFile ="/"+pathFile
              for (var path in  _this.fileFolderIdItem){
                if(pathAllFile == path){
                  _this.fileFolderId=_this.fileFolderIdItem[path]
                  _this.uploadSucess(file.id,file.source,_this.fileFolderId)
                  break
                }
              }
          });

        //文件上傳報錯
        _this.uploaderFolder.on('uploadError', function(file) {
          _this.uploadDisabled = false
          _this.netWork = true
          _this.uploadBtnDisabled = true
          _this.$Message.destroy()
          _this.$Notice.error({
            title: '上傳出錯,請重新再傳!',
            duration:2.5
          });
          _this.uploading = false;
          _this.title = '上傳終止'
          _this.uploaderFolder.destroy()
          _this.uploaderFolder.reset()
        });
        //文件上傳完成
        _this.uploaderFolder.on('uploadComplete', function(file) {
        });
        //文件加載完成
        _this.uploaderFolder.on('uploadFinished', function () {
          //清空隊列
          _this.uploaderFolder.reset();
        });

      },

      //添加多文件上傳參數
      keyGenerator(file) {
          const currentTime = new Date().getTime();
          const key = `${currentTime}.${file.name}`;
          return key;
      },
      cancel(){

        this.fileList = []
        this.allFilePercentage = 0
        this.sendFilePathArray = []
        this.fileIndex = 0
        this.uploadDisabled = false

        if(this.foldered == 'file'){
          this.uploader.destroy()
          this.uploader.reset()
          this.uploader.refresh()
        }else{
          this.uploaderFolder.destroy()
          this.uploaderFolder.reset()
          this.uploaderFolder.refresh()
        }
        if(this.netWork == true){
          setTimeout(() => {
            this.$router.go(0)
          },500)
        }
        this.$emit('closedModal');
      },

      //點擊上傳文件
      btnUpload(){
        let _this = this
        this.$Message.destroy();
        $.ajax({
          type: "post",
          url: this.uploadURLServer,
          success: function (data) {
            if(data.code == 1010){
              _this.uploadDisabled = false
              _this.netWork = true
              _this.uploadBtnDisabled = true
              _this.$Message.destroy()
              _this.$Notice.error({
                // title: '',
                desc:data.message,
                duration:2.5
              });
              _this.uploading = false;
              _this.title = '上傳終止'
              if(_this.foldered == "folder"){
                _this.uploaderFolder.destroy()
                _this.uploaderFolder.reset()
              }else{
                _this.uploader.destroy()
                _this.uploader.reset()
              }
            }else{
              if(_this.foldered == "folder"){
                _this.sendFolderPath()
              }else{
                _this.uploader.upload();
              }
            }
          }
        });
        if( this.fileList.length  > 0){
          this.uploadDisabled = true
          this.$Message.loading({
            content: '文件正在上傳中。。。',
            duration: 0
          });
          this.$emit('uploadDisabled', true)
          this.uploading = true
        }else  {
          this.uploadDisabled = false
        }


      },
      //目錄最終上傳方法
      sendFolderPath(){
        if(this.fileList.length > 0){
          this.resultPathFileCopy =[]
          this.resultPathFile.forEach((item,index,array)=>{
            //調用方法
            let file_list_length =  item.split("/")
            this.getfolderPath(file_list_length,file_list_length.length)
          })
          this.sendFilePathArray = Array.from(new Set(this.resultPathFileCopy));
          //獲取創建的目錄方法
          ResourceAPI.create_folder(this.$store.getters.id,this.sendFilePathArray,String(this.groupId == 0? '':this.groupId) || '',this.space,String( this.folderId == 0? '':this.folderId) || '').then(response=>{
            let resp = response.data
            if(resp.success == true){
              this.fileFolderIdItem=resp.data//
              this.uploaderFolder.upload();
            }else{
              this.$Notice.error({
                title: response.data.message.slice(7),
                duration:2.5
              });
            }
          });
        }else{
          return
        }
      },
      //上傳文件錯誤
      uploadError(type){
        /**
         * 驗證文件格式以及文件大小
         */
          if(type=="F_EXCEED_SIZE"){
            this.$Notice.error({
              title: '文件大小不能超過100G',
              duration:2.5
            });
          }else if (type === 'Q_EXCEED_NUM_LIMIT') {
            this.$Notice.error({
              title: '文件上傳已達到最大上限數',
              duration:2.5
            });
          }
          else {
            this.$Notice.error({
              title: '上傳出錯!請檢查後重新上傳!錯誤代碼${type}',
              duration:2.5
            });
          }
      },
      //文件剛加載進來
      uploadFileQueued(file){
        /**
         * 文件剛加進來的時候
         */
          let pathFile = file.source.source.webkitRelativePath
          let pathFileList = pathFile.substring(0,pathFile.lastIndexOf('/'))
          this.pathArray.push(pathFileList)
          this.resultPathFile = Array.from(new Set(this.pathArray));
          this.uploaderFile.push (file)
          this.fileList.push({
            fileName:file.name,
            fileId:file.id,
            fileSize:WebUploaderFolder.Base.formatSize(file.size),
            filePercentage:0,
            filePath:pathFile,
            fileSource:file.source,
            taskId:this.keyGenerator(file)
          })

      },
      //調用成功接口
      uploadSucess(task_id,fileSocure,fileFolderId){
        let _this = this
        let data = {
          'task_id': task_id,
          'ext': fileSocure['ext'],
          'type': fileSocure['type'],
          'name': fileSocure['name'],
        };
        $.ajax({
          type: "get",
          url: this.uploadURLSend,
          data: data,
          success: function (data) {
            let fileName = data.data.file_name
            let fileId = data.data.file_id
            if (data.success == true) {
              _this.uploadDisabled = true
              _this.$Notice.success({
                title: "文件:" + fileName + "上傳成功!",
                duration: 2.5
              });
              _this.fileFolderEndIndex++;
              if(_this.fileFolderEndIndex==_this.fileList.length){
                _this.fileList = []
                _this.allFilePercentage = 0
                _this.sendFilePathArray = []
                _this.fileIndex = 0
                _this.uploadDisabled = false
                _this.fileFolderEndIndex=0;
                _this.uploaderFolder.destroy()
                _this.uploaderFolder.reset()
                _this.uploaderFolder.refresh()

                if(_this.folderId == 0 && _this.openSearch == false){
                  _this.$emit("refreshTable")
                }else if(_this.folderId != 0 && _this.openSearch == false){
                  _this.$emit("uploadedFolder")
                }else if(_this.openSearch == true){
                  _this.openSearch == true?_this.$emit("refreshSearch"):_this.openSearch = false
                }


                if(_this.netWork == true){
                  setTimeout(() => {
                    _this.$router.go(0)
                  },500)
                }
                _this.$emit('closedModal');
              }
              _this.uploadSend(fileName, fileId, fileFolderId)

              // _this.$emit('closedModal');

            }
          }
        })

      },
      //向後端請求
      uploadSend(fileName,fileId,fileFolderId){
        ResourceAPI.upload(fileName,String(this.groupId) || '',this.space,fileId, String(fileFolderId)).then(response=>{
          let resp = response.data
          if(resp.success == true){

            this.$Message.destroy();
            this.uploadDisabled = false
            this.$Notice.success({
              title: "文件:"+fileName+"校驗成功!",
              duration:2.5
            });
            this.$emit('uploadDisabled', false)
            this.$emit('restUpload',true)
            this.uploading = false
          }else{
            if(resp.code == 400){
              this.$Notice.error({
                title: response.data.message.slice(7),
                duration:2.5
              });
            }else{
              this.$Notice.error({
                title: response.data.message.slice(7),
                duration:2.5
              });
            }
            this.uploading = false
            this.uploadDisabled = false
            this.$emit('uploadDisabled', false)
            this.upload = setTimeout(() => {
              this.$Message.destroy();
            },500)

            // _this.$emit('closedModal');
          }

        });
      },
      //獲取文件上一級目錄結構
      getfolderPath(list,length){
        //動態生成數組
        let result_length = Array.from({length:length}, (v,k) => k);
        result_length.forEach((self,index,array)=>{
          let list_val = list.slice(0,index+1).join("/")
          this.resultPathFileCopy.push("/"+list_val)
        })

      },
    }


}
</script>

問題點:上傳的文件實現預覽功能,.text,word,excel,ppt,jpg,等文件

後端將實現好的以text/html形式傳給前端,前端怎麼接收?

例如:
var $iframe =$('<iframe src="about:blank" frameborder=0 />');

          $iframe.ready(function() {

            var doc = $iframe[0].contentDocument;

            var id="_frame_t";

            $iframe.attr('width', '100%');
            $iframe.attr('height', '100%');

            $iframe.attr('id', id);

            doc.write(
              resp
            );
            doc.close();
          });

          $iframe.appendTo($("#content"));

封裝一個組件

<template>
  <Modal v-model="opened" title="預覽" :closable="false" @on-cancel="cancel" width='60%' :mask-closable='false'   >
    <div class="layout"  id='content' style='height: 600px;'>

    </div>
    <div slot="footer">
      <Button type="ghost" @click="cancel" style="margin-left: 8px">確定</Button>
    </div>
  </Modal>
</template>

<script>
  import ResourceAPI from 'api/resource';
  export default{
    props:{
      opened:{
        type:Boolean,
        default:false,
      },
      proviewId: {
        type: Number,
        default: 0
      },
    },
    watch:{
      opened: function (value, oldValue) {
        if (value == true) {
          $("#content").html('')
          this.getPreview()
        }
      }
    },
    data () {
      return{
        load: null,
    }
    },
    computed:{},
    methods:{
      //獲取版本的信息方法
      getPreview(){
        this.load = this.$Message.loading({
          content: 'Loading...',
          duration: 0
        });
        ResourceAPI.proview(this.proviewId).then(response=>{
          let resp = response.data

          var $iframe =$('<iframe src="about:blank" frameborder=0 />');

          $iframe.ready(function() {

            var doc = $iframe[0].contentDocument;

            var id="_frame_t";

            $iframe.attr('width', '100%');
            $iframe.attr('height', '100%');

            $iframe.attr('id', id);

            doc.write(
              resp
            );
            doc.close();
          });

          $iframe.appendTo($("#content"));
          this.load = this.$Message.destroy()
        }).catch()

      },
      cancel () {
        this.$emit('closedModal');
      },
    },
    mounted:function () {

    }
  }
</script>

<style scoped>

</style>

問題點預覽圖片可以打開上一頁,下一頁面旋轉的

用到插件viewerjs,結合vue和iview

<template>
  <Modal v-model="opened" title="預覽" :closable="false" @on-cancel="cancel" width='30%' :mask-closable='false'>
    <div class="" style='height: 250px;'>
          <ul class="pictures" id="galley">
            <li><img :src="viewer_url" :alt="img_name"></li>
         </ul>
    </div>

    <div slot="footer">
      <Button type="ghost" :disabled='img_diabled' @click="cancel" style="margin-left: 8px">確定</Button>
    </div>
  </Modal>
</template>

<script>
  import ResourceAPI from 'api/resource';
  export default{
    props:{
      opened:{
        type:Boolean,
        default:false,
      },
      proviewImgId: {
        type: Number,
        default: 0
      },
      proviewImgName:{
        type:String,
      }
    },
    watch:{
      opened: function (value, oldValue) {
        if (value == true) {
          this.viewer_url = null
          this.get_preview_img()
        }
      }
    },
    data () {
      return{
        load: null,
        viewer:null,
        viewer_url:null,
        img_diabled:false,
        img_name:null,
    }
    },
    computed:{},
    methods:{
      //獲取版本的信息方法
      get_preview_img() {
        this.viewer_url = null
        this.load = this.$Message.loading({
          content: 'Loading...',
          duration: 0
        });
        this.img_diabled = true
        ResourceAPI.proview(this.proviewImgId).then(response=>{
          let resp = response.data
          if(resp.success == true){
            this.viewer_url = resp.data
            this.img_name = this.proviewImgName
            $('#galley').viewer();
            this.load = this.$Message.destroy()
            this.img_diabled = false
          }else{
            this.$Notice.error({
              title: resp.message,
              duration:2.5
            });
            this.load = this.$Message.destroy()
            this.img_diabled = false
          }

        }).catch()

      },
      cancel () {
        this.$emit('closedModal');
        this.viewer_url = null
        this.img_name = null
      },
    },
    mounted:function () {

    }
  }
</script>

<style scoped>
  .pictures {
    width: 200px;
    height: 200px;
    position: absolute;
    top: 90px;
    left: 180px;
  }

  .pictures > li {
    float: left;
    /*width: 33.3%;*/
    /*height: 33.3%;*/
    width: 100%;
    height: 100%;
    margin: 0 -1px -1px 0;
    border: 1px solid transparent;
    overflow: hidden;
  }

  .pictures > li > img {
    width: 100%;
    height: 100%;
    text-align: center;
    cursor: -webkit-zoom-in;
    cursor: zoom-in;
  }
</style>

問題點:預覽視頻和音頻

<template>
  <Modal v-model="opened" title="預覽" :closable="false" @on-cancel="cancel"  :mask-closable='false'>
    <div class="layout video-part" >
      <video :src="viedo_url"  controls="controls" id='medio'>
        <!--<source :src="viedo_url" >-->
      </video>
    </div>

    <div slot="footer">
      <Button type="ghost" :disabled='video_disabled' @click="cancel" style="margin-left: 8px">確定</Button>
    </div>
  </Modal>
</template>

<script>
  import ResourceAPI from 'api/resource';
  export default{
    props:{
      opened:{
        type:Boolean,
        default:false,
      },
      proviewVideoID: {
        type: Number,
        default: 0
      },
    },
    watch:{
      opened: function (value, oldValue) {
        if (value == true) {
          this.get_video_url()
        }
      }
    },
    data () {
      return{
        load: null,
        viedo_url: null,
        video_disabled: false,
      }
    },
    computed:{},
    methods:{
      //獲取版本的信息方法
      get_video_url() {
        this.viedo_url = null
        this.load = this.$Message.loading({
          content: 'Loading...',
          duration: 0
        });
        this.video_disabled = true
        ResourceAPI.proview(this.proviewVideoID).then(response=>{
          let resp = response.data
          if(resp.success == true){
            this.viedo_url = resp.data
            this.load = this.$Message.destroy()
            this.video_disabled = false
          }else{
            this.$Notice.error({
              title: resp.message,
              duration:2.5
            });
            this.load = this.$Message.destroy()
            this.video_disabled = false
          }
        }).catch()
      },
      cancel () {
        this.$emit('closedModal');
        let Medio = document.getElementById("medio");
        Medio.src = null
        Medio.pause()
      },
    },
    mounted:function () {

    }
  }
</script>

<style scoped>
  .video-part{
    width: 488px;
    height:250px;
  }
  video{
    width:100%;
    height: 100%;
    height:500px\0;/* ie 8/9/10/Opera - for ie8/ie10/Opera */
    _height:500px; /* ie 6 - for ie6 */
    object-fit: fill
  }
</style>

# 音頻
<template>
  <Modal v-model="opened" title="預覽" :closable="false" @on-cancel="cancel"  :mask-closable='false'>
    <div class="layout" style='height: 60px;'>
      <audio :src='audio_url' controls="controls" id='audio'>
        <!--<source src="../../../static/movie.mp4" type="audio/mpeg">-->
        <!--<source  src="../../../static/cat1.ogg" type="audio/ogg">-->
      </audio>
    </div>

    <div slot="footer">
      <Button type="ghost" :disabled='audio_disable' @click="cancel" style="margin-left: 8px">確定</Button>
    </div>
  </Modal>
</template>

<script>
  import ResourceAPI from 'api/resource';
  export default{
    props:{
      opened:{
        type:Boolean,
        default:false,
      },
      proviewAideoID: {
        type: Number,
        default: 0
      },
    },
    watch:{
      opened: function (value, oldValue) {
        if (value == true) {
          this.get_preview_audio()
        }
      }
    },
    data () {
      return{
        load: null,
        audio_url: null,
        audio_disable: false,

    }
    },
    computed:{},
    methods:{
      //獲取版本的信息方法
      get_preview_audio() {
        this.audio_url = null
        this.load = this.$Message.loading({
          content: 'Loading...',
          duration: 0
        });
        this.audio_disable = true
        ResourceAPI.proview(this.proviewAideoID).then(response=>{
          let resp = response.data
          if(resp.success == true){
            this.audio_url = resp.data
            this.load = this.$Message.destroy()
            this.audio_disable = false
          }else{
            this.$Notice.error({
              title: resp.message,
              duration:2.5
            });
            this.load = this.$Message.destroy()
            this.audio_disable = false
          }
        }).catch()

      },
      cancel () {
        this.$emit('closedModal');
        this.audio_url = null
        document.getElementById("audio").src = null;
        document.getElementById("audio").pause()
      },
    },
    mounted:function () {

    }
  }
</script>

<style scoped>
  audio{
    margin-top: 0px;
    width:100%;
    height: 100%;
    height:500px\0;/* ie 8/9/10/Opera - for ie8/ie10/Opera */
    _height:500px; /* ie 6 - for ie6 */
    object-fit: fill
  }
</style>

問題點:vue axios 默認阻止cookie請求,導致添加驗證碼以後登不進去

  • 解決方法
import axios from 'axios'
axios.defaults.withCredentials=true;//讓ajax攜帶cookie

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章