研发图纸文件管理系统-前端项目
iczer
2020-06-18 ce3ee754f53aa2c8064444542f0511629ff280fa
新增: 全局动画切换功能;
16个文件已修改
3个文件已添加
299 ■■■■ 已修改文件
package.json 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/App.vue 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/checkbox/ColorCheckbox.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/menu/Contextmenu.vue 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/setting/Setting.vue 53 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/transition/PageToggleTransition.vue 91 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/config/animates.js 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/config/index.js 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layouts/GlobalLayout.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layouts/MenuView.vue 19 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layouts/PageLayout.vue 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layouts/PageView.vue 13 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layouts/RouteView.vue 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main.js 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/components/TaskCard.vue 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/store/modules/setting.js 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/themeUtil.js 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
vue.config.js 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yarn.lock 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
package.json
@@ -9,6 +9,7 @@
  },
  "dependencies": {
    "@antv/data-set": "^0.11.4",
    "animate.css": "^4.1.0",
    "ant-design-vue": "^1.6.2",
    "axios": "^0.19.2",
    "clipboard": "^2.0.6",
src/App.vue
@@ -19,30 +19,4 @@
</script>
<style lang="less">
  :global{
    //拖拽控件全局样式
    .dragable-ghost{
      border: 1px dashed #aaaaaa;
      opacity: 0.65;
    }
    .dragable-chose{
      border: 1px dashed #aaaaaa;
      opacity: 0.65;
    }
    .dragable-drag{
      border: 1px dashed #aaaaaa;
      opacity: 0.65;
    }
    //页面切换动画
    .page-toggle-enter-active{
      transition: all 0.2s ease-in 0.25s;
    }
    .page-toggle-leave-active{
      transition: all 0.2s ease-out 0s;
    }
    .page-toggle-enter, .page-toggle-leave-to{
      opacity: 0;
      padding: 0px;
    }
  }
</style>
src/components/checkbox/ColorCheckbox.vue
@@ -94,7 +94,7 @@
      required: true
    },
    value: {
      type: String,
      type: [String, Number],
      required: true
    },
    checked: {
src/components/menu/Contextmenu.vue
@@ -64,8 +64,8 @@
  .contextmenu{
    position: fixed;
    z-index: 1;
    border: 1px solid #9e9e9e;
    border-radius: 4px;
    box-shadow: 2px 2px 10px #aaaaaa !important;
    box-shadow: -4px 4px 16px 1px #e6e6e6 !important;
  }
</style>
src/components/setting/Setting.vue
@@ -7,15 +7,8 @@
      </img-checkbox-group>
    </setting-item>
    <setting-item title="主题色">
      <color-checkbox-group @change="onColorChange" :defaultValues="['6']" :multiple="false">
        <color-checkbox color="#f5222d" value="1" />
        <color-checkbox color="#fa541c" value="2" />
        <color-checkbox color="#faad14" value="3" />
        <color-checkbox color="#13c2c2" value="4" />
        <color-checkbox color="#52c41a" value="5" />
        <color-checkbox color="#1d92ff" value="6" />
        <color-checkbox color="#2f54eb" value="7" />
        <color-checkbox color="#722ed1" value="8" />
      <color-checkbox-group @change="onColorChange" :defaultValues="[0]" :multiple="false">
        <color-checkbox v-for="(color, index) in colors" :key="index" :color="color" :value="index" />
      </color-checkbox-group>
    </setting-item>
    <a-divider/>
@@ -62,6 +55,22 @@
      </a-list>
    </setting-item>
    <a-divider />
    <setting-item title="页面切换动画">
      <a-list :split="false">
        <a-list-item>
          动画效果
          <a-select v-model="animate" @change="setAnimate" class="select-item" size="small" slot="actions">
            <a-select-option :key="index" :value="index" v-for="(item, index) in animates">{{item.alias}}</a-select-option>
          </a-select>
        </a-list-item>
        <a-list-item>
          动画方向
          <a-select v-model="direction" @change="setAnimate" class="select-item" size="small" slot="actions">
            <a-select-option :key="index" :value="index" v-for="(item, index) in animateCfg.directions">{{item}}</a-select-option>
          </a-select>
        </a-list-item>
      </a-list>
    </setting-item>
    <a-button id="copyBtn" data-clipboard-text="Sorry, you have copied nothing O(∩_∩)O~" @click="copyCode" style="width: 100%" icon="copy" >拷贝代码</a-button>
  </a-layout-sider>
</template>
@@ -72,6 +81,7 @@
import ImgCheckbox from '../checkbox/ImgCheckbox'
import Clipboard from 'clipboard'
import themeUtil from '../../utils/themeUtil';
import { mapState } from 'vuex'
const ColorCheckboxGroup = ColorCheckbox.Group
const ImgCheckboxGroup = ImgCheckbox.Group
@@ -79,10 +89,18 @@
export default {
  name: 'Setting',
  components: {ImgCheckboxGroup, ImgCheckbox, ColorCheckboxGroup, ColorCheckbox, SettingItem},
  computed: {
    multiPage () {
      return this.$store.state.setting.multiPage
  data() {
    return {
      animate: 0,
      direction: 0,
      colors: ['#f5222d', '#fa541c', '#faad14', '#13c2c2', '#52c41a', '#1d92ff', '#2f54eb', '#722ed1'],
    }
  },
  computed: {
    animateCfg() {
      return this.animates[this.animate]
    },
    ...mapState('setting', ['animates', 'multiPage'])
  },
  methods: {
    onColorChange (values, colors) {
@@ -107,6 +125,14 @@
    },
    setMultiPage (checked) {
      this.$store.commit('setting/setMultiPage', checked)
    },
    setAnimate() {
      let animation = this.animates[this.animate]
      let animate = {
        name: animation.name,
        direction: animation.directions[this.direction]
      }
      this.$store.commit('setting/setAnimate', animate)
    }
  }
}
@@ -124,5 +150,8 @@
    .flex{
      display: flex;
    }
    .select-item{
      width: 80px;
    }
  }
</style>
src/components/transition/PageToggleTransition.vue
New file
@@ -0,0 +1,91 @@
<template>
  <transition
    :enter-active-class="`animated ${enterAnimate} page-toggle-enter-active`"
    :leave-active-class="`animated ${leaveAnimate} page-toggle-leave-active`"
  >
    <slot></slot>
  </transition>
</template>
<script>
  import {animates} from '@/config'
  export default {
    name: 'PageToggleTransition',
    props: {
      animate: {
        type: String,
        validator(value) {
          return animates.find(item => item.name == value) != -1
        },
        default: 'bounce'
      },
      direction: {
        type: String,
        validator(value) {
          return ['x', 'y', 'left', 'right', 'up', 'down', 'downLeft', 'upRight', 'downRight', 'upLeft', 'downBig',
            'upBig', 'downLeft', 'downRight', 'topRight', 'bottomLeft', 'topLeft', 'bottomRight', 'default'].indexOf(value) > -1
        }
      },
      reverse: {
        type: Boolean,
        default: true
      }
    },
    computed: {
      enterAnimate() {
        return this.activeClass(false)
      },
      leaveAnimate() {
        return this.activeClass(true)
      }
    },
    methods: {
      activeClass(isLeave) {
        let animate = animates.find(item => this.animate == item.name)
        if (animate == undefined) {
          return ''
        }
        let direction = ''
        if (this.direction == undefined) {
          direction = animate.directions[0]
        } else {
          direction = animate.directions.find(item => item == this.direction)
          direction = (direction == undefined || direction === 'default') ? '' : direction
        }
        window.console.log(direction)
        if (direction != '') {
          direction = isLeave && this.reverse ? this.reversePosition(direction, animate.directions) : direction
          direction = direction[0].toUpperCase() + direction.substring(1)
        }
        let t = isLeave ? 'Out' : 'In'
        return animate.name + t + direction
      },
      reversePosition(direction, directions) {
        if(direction.length == 0 || direction == 'x' || direction == 'y') {
          return direction
        }
        let index = directions.indexOf(direction)
        index = (index % 2 == 1) ? index - 1 : index + 1
        return directions[index]
      }
    }
  }
</script>
<style lang="less">
  .page-toggle-enter-active{
    position: absolute !important;
    animation-duration: 0.6s !important;
    width: calc(100% - 48px);
  }
  .page-toggle-leave-active{
    position: absolute !important;
    animation-duration: 0.6s !important;
    width: calc(100% - 48px);
  }
  .page-toggle-enter{
  }
  .page-toggle-leave-to{
  }
</style>
src/config/animates.js
New file
@@ -0,0 +1,17 @@
const direct_s = ['left', 'right']
const direct_1 = ['down', 'up', 'left', 'right']
const direct_1_b = ['downBig', 'upBig', 'leftBig', 'rightBig']
const direct_2 = ['topLeft', 'bottomRight', 'topRight', 'bottomLeft']
const direct_3 = ['downLeft', 'upRight', 'downRight', 'upLeft']
module.exports = [
  {name: 'back', alias: '后位', directions: direct_1},
  {name: 'bounce', alias: '弹跳', directions: direct_1.concat('default')},
  {name: 'fade', alias: '淡化', directions: direct_1.concat(direct_1_b).concat(direct_2).concat('default')},
  {name: 'flip', alias: '翻转', directions: ['x', 'y', 'default']},
  {name: 'lightSpeed', alias: '光速', directions: direct_s},
  {name: 'rotate', alias: '旋转', directions: direct_3.concat('default')},
  {name: 'roll', alias: '翻滚', directions: ['default']},
  {name: 'zoom', alias: '缩放', directions: direct_1.concat('default')},
  {name: 'slide', alias: '滑动', directions: direct_1},
]
src/config/index.js
New file
@@ -0,0 +1,11 @@
// 系统配置
module.exports = {
  themeColor: '#1890ff',
  animates: require('./animates'),
  footerLinks: [
    {link: 'https://pro.ant.design', name: 'Pro首页'},
    {link: 'https://github.com/iczer/vue-antd-admin', icon: 'github'},
    {link: 'https://ant.design', name: 'Ant Design'}
  ],
}
src/layouts/GlobalLayout.vue
@@ -12,7 +12,7 @@
    </drawer>
    <a-layout>
      <global-header :menuData="menuData" :collapsed="collapsed" @toggleCollapse="toggleCollapse"/>
      <a-layout-content :style="{minHeight: minHeight, margin: '24px 24px 0'}">
      <a-layout-content :style="{minHeight: minHeight, padding: '24px 24px 0', position: 'relative'}">
        <slot></slot>
      </a-layout-content>
      <a-layout-footer style="padding: 0px">
src/layouts/MenuView.vue
@@ -10,25 +10,28 @@
      type="editable-card"
      @change="changePage"
      @edit="editPage">
      <a-tab-pane :id="page.fullPath" :key="page.fullPath" v-for="page in pageList">
      <a-tab-pane :key="page.fullPath" v-for="page in pageList">
        <span slot="tab" :pagekey="page.fullPath">{{page.name}}</span>
      </a-tab-pane>
    </a-tabs>
    <transition name="page-toggle">
    <page-toggle-transition :animate="animate.name" :direction="animate.direction">
      <keep-alive v-if="multiPage">
        <router-view />
      </keep-alive>
      <router-view v-else />
    </transition>
    </page-toggle-transition>
  </global-layout>
</template>
<script>
import GlobalLayout from './GlobalLayout'
import Contextmenu from '../components/menu/Contextmenu'
import PageToggleTransition from '../components/transition/PageToggleTransition'
import {mapState} from 'vuex'
export default {
  name: 'MenuView',
  components: {Contextmenu, GlobalLayout},
  components: {PageToggleTransition, Contextmenu, GlobalLayout},
  data () {
    return {
      pageList: [],
@@ -43,9 +46,7 @@
    }
  },
  computed: {
    multiPage () {
      return this.$store.state.setting.multiPage
    }
    ...mapState('setting', ['multiPage', 'animate'])
  },
  created () {
    this.pageList.push(this.$route)
@@ -63,8 +64,8 @@
        this.pageList.push(newRoute)
      }
    },
    'activePage': function () {
      // this.$router.push(key)
    'activePage': function (key) {
      this.$router.push(key)
    },
    'multiPage': function (newVal) {
      if (!newVal) {
src/layouts/PageLayout.vue
@@ -14,7 +14,7 @@
      <slot v-if="this.$refs.extra" slot="extra" name="extra"></slot>
    </page-header>
    <div ref="page" :class="['page-content', layout]" >
      <slot ></slot>
      <slot></slot>
    </div>
  </div>
</template>
@@ -63,11 +63,12 @@
    }
  }
  .page-content{
    position: relative;
    &.side{
      margin: 24px 24px 0px;
      padding: 24px 24px 0;
    }
    &.head{
      margin: 24px auto 0;
      padding: 24px 0 0;
      max-width: 1400px;
    }
  }
src/layouts/PageView.vue
@@ -3,20 +3,23 @@
    <div slot="extra" class="extraImg">
      <img :src="extraImage"/>
    </div>
    <transition name="page-toggle">
    <page-toggle-transition :animate="animate.name" :direction="animate.direction">
      <keep-alive v-if="multiPage">
        <router-view ref="page" />
      </keep-alive>
      <router-view ref="page" v-else />
    </transition>
    </page-toggle-transition>
  </page-layout>
</template>
<script>
import PageLayout from './PageLayout'
import PageToggleTransition from '../components/transition/PageToggleTransition';
import {mapState} from 'vuex'
export default {
  name: 'PageView',
  components: {PageLayout},
  components: {PageToggleTransition, PageLayout},
  data () {
    return {
      title: '',
@@ -26,9 +29,7 @@
    }
  },
  computed: {
    multiPage () {
      return this.$store.state.setting.multiPage
    }
    ...mapState('setting', ['multiPage', 'animate'])
  },
  mounted () {
    this.getPageHeaderInfo()
src/layouts/RouteView.vue
@@ -1,19 +1,21 @@
<template>
  <transition name="page-toggle">
  <page-toggle-transition :animate="animate.name" :direction="animate.direction">
    <keep-alive v-if="multiPage">
      <router-view />
    </keep-alive>
    <router-view v-else />
  </transition>
  </page-toggle-transition>
</template>
<script>
import PageToggleTransition from '../components/transition/PageToggleTransition';
import {mapState} from 'vuex'
export default {
  name: 'RouteView',
  components: {PageToggleTransition},
  computed: {
    multiPage () {
      return this.$store.state.setting.multiPage
    }
    ...mapState('setting', ['multiPage', 'animate'])
  }
}
</script>
src/main.js
@@ -8,6 +8,7 @@
import '@/mock'
import store from './store'
import PouchDB from 'pouchdb'
import 'animate.css/source/animate.css'
Vue.prototype.$axios = axios
Vue.config.productionTip = false
src/pages/components/TaskCard.vue
@@ -35,4 +35,16 @@
  .task-group{
    margin: 0 48px;
  }
  .dragable-ghost{
    border: 1px dashed red;
    opacity: 1;
  }
  .dragable-chose{
    border: 1px dashed red;
    opacity: 0.8;
  }
  .dragable-drag{
    border: 1px dashed red;
    opacity: 1;
  }
</style>
src/store/modules/setting.js
@@ -1,3 +1,4 @@
import {footerLinks, animates} from '@/config'
export default {
  namespaced: true,
  state: {
@@ -6,12 +7,13 @@
    layout: 'side',
    systemName: 'Vue Antd Admin',
    copyright: '2018 ICZER 工作室出品',
    footerLinks: [
      {link: 'https://pro.ant.design', name: 'Pro首页'},
      {link: 'https://github.com/iczer/vue-antd-admin', icon: 'github'},
      {link: 'https://ant.design', name: 'Ant Design'}
    ],
    multiPage: true
    footerLinks: footerLinks,
    multiPage: true,
    animates: animates,
    animate: {
      name: 'back',
      direction: 'left'
    }
  },
  mutations: {
    setDevice (state, isMobile) {
@@ -25,6 +27,9 @@
    },
    setMultiPage (state, multiPage) {
      state.multiPage = multiPage
    },
    setAnimate (state, animate) {
      state.animate = animate
    }
  }
}
src/utils/themeUtil.js
@@ -1,9 +1,10 @@
const ThemeColorReplacer = require('webpack-theme-color-replacer')
const client = require('webpack-theme-color-replacer/client')
const generate =  require('@ant-design/colors/lib/generate').default
const themeColor = require('../config').themeColor
module.exports = {
  primaryColor: '#1890ff',
  primaryColor: themeColor,
  getThemeColors(color) {
    const lightens = new Array(9).fill().map((t, i) => {
      return ThemeColorReplacer.varyColor.lighten(color, i / 10)
vue.config.js
@@ -1,6 +1,7 @@
// let path = require('path')
const ThemeColorReplacer = require('webpack-theme-color-replacer')
const getThemeColors = require('./src/utils/themeUtil').getThemeColors
const themeColor = require('./src/config').themeColor
module.exports = {
  pluginOptions: {
@@ -15,7 +16,7 @@
    config.plugins.push(
      new ThemeColorReplacer({
        fileName: 'css/theme-colors.css',
        matchColors: getThemeColors('#1890ff')
        matchColors: getThemeColors(themeColor)
      })
    )
  },
yarn.lock
@@ -1620,6 +1620,11 @@
  resolved "https://registry.npm.taobao.org/amdefine/download/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5"
  integrity sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=
animate.css@^4.1.0:
  version "4.1.0"
  resolved "https://registry.npm.taobao.org/animate.css/download/animate.css-4.1.0.tgz#dec2aabe4babfc6f6777f9a5cccd132838729b50"
  integrity sha1-3sKqvkur/G9nd/mlzM0TKDhym1A=
ansi-colors@^3.0.0:
  version "3.2.4"
  resolved "https://registry.npm.taobao.org/ansi-colors/download/ansi-colors-3.2.4.tgz#e3a3da4bfbae6c86a9c285625de124a234026fbf"