瀏覽代碼

完成供需管理首页

Jing-Jiu 4 年之前
父節點
當前提交
4c78645767

+ 8 - 0
.hbuilderx/launch.json

@@ -2,10 +2,18 @@
   // launchtype项可配置值为local或remote, local代表前端连本地云函数,remote代表前端连云端云函数
     "version": "0.0",
     "configurations": [{
+     	"app-plus" : 
+     	{
+     		"launchtype" : "local"
+     	},
      	"default" : 
      	{
      		"launchtype" : "local"
      	},
+     	"h5" : 
+     	{
+     		"launchtype" : "local"
+     	},
      	"mp-weixin" : 
      	{
      		"launchtype" : "local"

+ 28 - 21
components/foot-tabs/footTabs.vue

@@ -7,8 +7,12 @@
         :key="i"
         @tap="click(i, menu.pagePath)"
       >
-        <img :src="menu.selectedIconPath" v-if="selectedIndex == i" />
-        <img :src="menu.iconPath" v-else />
+        <uni-transition mode-class="fade" show="true" v-if="selectedIndex == i">
+          <img :src="menu.selectedIconPath"/>
+        </uni-transition>
+        <uni-transition mode-class="fade" show="true" v-else >
+          <img :src="menu.iconPath"/>
+        </uni-transition>
       </div>
     </div>
   </div>
@@ -23,15 +27,17 @@
   left: 50%;
   top: 88%;
   transform: translateX(-50%);
-  box-shadow: rgba(100, 100, 111, 0.2) 0px 7px 29px 0px;
+  box-shadow: rgba(100, 100, 111, 0.2) 0rpx 7rpx 29rpx 0rpx;
   background-color: #fff;
   .hover_menu {
     display: flex;
     justify-content: space-around;
     .menu_icon {
+      transition: all 0.5s;
       img {
         width: 60rpx;
         height: 60rpx;
+        border-radius: 100rpx;
       }
     }
   }
@@ -67,9 +73,8 @@ export default {
       getApp().globalData.selectedIndex = index;
       let res_url = this.check(url);
       let res_src = this.check(src);
-      console.log(getApp().globalData.selectedIndex);
       // console.log(res_url,res_src);
-      if (!(res_url&&res_src) && !(res_url == false && res_src == false)) {
+      if (!(res_url && res_src) && !(res_url == false && res_src == false)) {
         uni.navigateTo({
           url: "/" + src,
         });
@@ -77,25 +82,27 @@ export default {
     },
     check(url) {
       let isTure = false;
-      let arr = ["pages/index/index",
-          "pages/park/park_deatil",
-          "pages/appeal/index",
-          "pages/appeal/myAppeal",
-          "pages/appeal/putAppeal",
-          "pages/appeal/appeal_detail",
-          "pages/policy/index",
-          "pages/policy/policy_deatil",
-          "pages/park/index",
-          "pages/park/map_search",
-          "pages/activity/index",
-          "pages/supply/index",
-          "pages/enterprise/index",
-          "pages/service/index"];
+      let arr = [
+        "pages/index/index",
+        "pages/park/park_deatil",
+        "pages/appeal/index",
+        "pages/appeal/myAppeal",
+        "pages/appeal/putAppeal",
+        "pages/appeal/appeal_detail",
+        "pages/policy/index",
+        "pages/policy/policy_deatil",
+        "pages/park/index",
+        "pages/park/map_search",
+        "pages/activity/index",
+        "pages/supply/index",
+        "pages/enterprise/index",
+        "pages/service/index",
+      ];
       for (let i = 0; i < arr.length; i++) {
-        let e = arr[i]
+        let e = arr[i];
         if (e == url) {
           isTure = true;
-          return isTure
+          return isTure;
         }
       }
       return isTure;

+ 27 - 1
pages.json

@@ -88,7 +88,33 @@
 		{
 			"path": "pages/supply/index",
 			"style": {
-				"navigationBarTitleText": "发供需"
+				"navigationBarTitleText": "供需管理",
+				"navigationBarBackgroundColor": "#02A7F0",
+				"navigationBarTextStyle":"white"
+			}
+		},
+		{
+			"path": "pages/supply/putSupply",
+			"style": {
+				"navigationBarTitleText": "发布供需",
+				"navigationBarBackgroundColor": "#02A7F0",
+				"navigationBarTextStyle":"white"
+			}
+		},
+		{
+			"path": "pages/supply/mySupply",
+			"style": {
+				"navigationBarTitleText": "我的供需",
+				"navigationBarBackgroundColor": "#02A7F0",
+				"navigationBarTextStyle":"white"
+			}
+		},
+		{
+			"path": "pages/supply/supply_detail",
+			"style": {
+				"navigationBarTitleText": "供需详情",
+				"navigationBarBackgroundColor": "#02A7F0",
+				"navigationBarTextStyle":"white"
 			}
 		},
 		{

+ 186 - 42
pages/supply/index.vue

@@ -1,49 +1,193 @@
 <template>
-	<view class="content">
-		{{message}}
-	</view>
+  <view class="content">
+    <div class="picker">
+      <picker
+        @change="bindPickerChange"
+        :value="index"
+        :range="array"
+        range-key="name"
+      >
+        <div class="picker_title">
+          <div class="pickername">
+            <div v-if="array[index].name != undefind">
+              {{ array[index].name }}
+            </div>
+            <div v-else>类型</div>
+          </div>
+          <div class="triangle-down"></div>
+        </div>
+      </picker>
+    </div>
+    <div class="supplyList">
+      <div class="supplyCard" v-for="(supply, i) in supplyList" :key="i" @tap="toDetail(i)">
+        <div class="img_content">
+          <img :src="supply.img" />
+        </div>
+        <div class="info">
+          <div class="title">
+            {{ supply.title }}
+          </div>
+          <div class="time">发布时间:{{ supply.time }}</div>
+        </div>
+      </div>
+    </div>
+    <div class="menus">
+      <navigator url="/pages/supply/putSupply">
+        <div class="menu">
+          <div>
+            <img src="/static/supply/putSupply.png" />
+          </div>
+          <div class="menu_title">发布供需</div>
+        </div>
+      </navigator>
+      <navigator url="/pages/supply/mySupply">
+        <div class="menu">
+          <div>
+            <img src="/static/supply/mySupply.png" />
+          </div>
+          <div class="menu_title">我的供需</div>
+        </div>
+      </navigator>
+    </div>
+  </view>
 </template>
 
 <script>
-	export default {
-		data() {
-			return {
-				message:'发供需'
-			}
-		},
-		onLoad() {
-
-		},
-		methods: {
-			
-       }
-	}
+export default {
+  data() {
+    return {
+      supplyList: [
+        {
+          img: "/static/supply/u1779.png",
+          title: "移动式空气消毒机",
+          time: "2021-08-30 14:50:00",
+        },
+        {
+          img: "/static/supply/u1779.png",
+          title: "视频监控产品及解决方案",
+          time: "2021-08-30 14:50:00",
+        },
+        {
+          img: "/static/supply/u1779.png",
+          title: "超声波产品及解决方案",
+          time: "2021-08-30 14:50:00",
+        },
+        {
+          img: "/static/supply/u1779.png",
+          title: "多平台游戏方向盘",
+          time: "2021-08-30 14:50:00",
+        },
+        {
+          img: "/static/supply/u1779.png",
+          title: "超声波产品及解决方案",
+          time: "2021-08-30 14:50:00",
+        },
+        {
+          img: "/static/supply/u1779.png",
+          title: "多平台游戏方向盘",
+          time: "2021-08-30 14:50:00",
+        },
+      ],
+      array: [{ name: "全部" }, { name: "供需" }, { name: "需求" }],
+      index: undefined,
+    };
+  },
+  methods: {
+    bindPickerChange(e) {
+      this.index = e.detail.value;
+    },
+    toDetail(index) {
+      uni.navigateTo({
+        url: "/pages/supply/supply_detail?id=" + index,
+      });
+    },
+  },
+};
 </script>
 
-<style>
-	.content {
-		display: flex;
-		flex-direction: column;
-		align-items: center;
-		justify-content: center;
-	}
-
-	.logo {
-		height: 200rpx;
-		width: 200rpx;
-		margin-top: 200rpx;
-		margin-left: auto;
-		margin-right: auto;
-		margin-bottom: 50rpx;
-	}
-
-	.text-area {
-		display: flex;
-		justify-content: center;
-	}
-
-	.title {
-		font-size: 36rpx;
-		color: #8f8f94;
-	}
+<style lang="scss" scope>
+.content {
+  font-size: 30rpx;
+  margin: 0 5%;
+  .picker {
+    position: fixed;
+    top: 3%;
+    left: 5%;
+    .picker_title {
+      width: 100rpx;
+      display: flex;
+      align-items: center;
+      justify-content: space-between;
+      .triangle-down {
+        width: 0;
+        height: 0;
+        border-top: 15rpx solid rgb(173, 173, 173);
+        border-left: 15rpx solid transparent;
+        border-right: 15rpx solid transparent;
+      }
+      .pickername {
+        font-weight: 100;
+      }
+    }
+  }
+  .supplyList {
+    margin-top: 12%;
+    .supplyCard {
+      display: flex;
+      width: 92%;
+      margin: 2% 0;
+      padding: 4% 4%;
+      height: 5%;
+      border-radius: 50rpx;
+      box-shadow: rgba(100, 100, 111, 0.2) 0rpx 14rpx 50rpx 0rpx;
+      .img_content {
+        margin-right: 5%;
+        img {
+          width: 100rpx;
+          height: 100rpx;
+          border-radius: 20rpx;
+          background-color: rgb(228, 228, 228);
+        }
+      }
+      .info {
+        display: flex;
+        flex-flow: column;
+        justify-content: space-around;
+        .time {
+          font-weight: 100;
+          font-size: 25rpx;
+        }
+      }
+    }
+  }
+  .menus {
+    z-index: 999;
+    display: flex;
+    justify-content: space-around;
+    width: 70%;
+    height: 6%;
+    position: fixed;
+    top: 85%;
+    left: 50%;
+    padding: 3%;
+    border-radius: 40rpx;
+    box-shadow: rgba(100, 100, 111, 0.2) 0rpx 14rpx 50rpx 0rpx;
+    transform: translateX(-50%);
+    background-color: #fff;
+    img {
+      width: 50rpx;
+      height: 50rpx;
+      border-radius: 10rpx;
+    }
+    .menu {
+      display: flex;
+      flex-flow: column;
+      align-items: center;
+      .menu_title {
+        text-align: center;
+        font-size: 25rpx;
+      }
+    }
+  }
+}
 </style>

+ 14 - 0
pages/supply/mySupply.vue

@@ -0,0 +1,14 @@
+<template>
+    <div>
+        {{msg}}
+    </div>
+</template>
+<script>
+export default {
+    data() {
+        return {
+            msg:'my'
+        }
+    },
+}
+</script>

+ 14 - 0
pages/supply/putSupply.vue

@@ -0,0 +1,14 @@
+<template>
+    <div>
+        {{msg}}
+    </div>
+</template>
+<script>
+export default {
+    data() {
+        return {
+            msg:'put'
+        }
+    },
+}
+</script>

+ 5 - 0
pages/supply/supply_detail.vue

@@ -0,0 +1,5 @@
+<template>
+    <div>
+        123
+    </div>
+</template>

二進制
static/supply/mySupply.png


二進制
static/supply/putSupply.png


二進制
static/supply/u1779.png


+ 13 - 0
uni_modules/uni-transition/changelog.md

@@ -0,0 +1,13 @@
+## 1.2.0(2021-07-30)
+- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
+## 1.1.1(2021-05-12)
+- 新增 示例地址
+- 修复 示例项目缺少组件的Bug
+## 1.1.0(2021-04-22)
+- 新增 通过方法自定义动画
+- 新增 custom-class 非 NVUE 平台支持自定义 class 定制样式
+- 优化 动画触发逻辑,使动画更流畅
+- 优化 支持单独的动画类型
+- 优化 文档示例
+## 1.0.2(2021-02-05)
+- 调整为uni_modules目录规范

+ 128 - 0
uni_modules/uni-transition/components/uni-transition/createAnimation.js

@@ -0,0 +1,128 @@
+// const defaultOption = {
+// 	duration: 300,
+// 	timingFunction: 'linear',
+// 	delay: 0,
+// 	transformOrigin: '50% 50% 0'
+// }
+// #ifdef APP-NVUE
+const nvueAnimation = uni.requireNativePlugin('animation')
+// #endif
+class MPAnimation {
+	constructor(options, _this) {
+		this.options = options
+		this.animation = uni.createAnimation(options)
+		this.currentStepAnimates = {}
+		this.next = 0
+		this.$ = _this
+
+	}
+
+	_nvuePushAnimates(type, args) {
+		let aniObj = this.currentStepAnimates[this.next]
+		let styles = {}
+		if (!aniObj) {
+			styles = {
+				styles: {},
+				config: {}
+			}
+		} else {
+			styles = aniObj
+		}
+		if (animateTypes1.includes(type)) {
+			if (!styles.styles.transform) {
+				styles.styles.transform = ''
+			}
+			let unit = ''
+			if(type === 'rotate'){
+				unit = 'deg'
+			}
+			styles.styles.transform += `${type}(${args+unit}) `
+		} else {
+			styles.styles[type] = `${args}`
+		}
+		this.currentStepAnimates[this.next] = styles
+	}
+	_animateRun(styles = {}, config = {}) {
+		let ref = this.$.$refs['ani'].ref
+		if (!ref) return
+		return new Promise((resolve, reject) => {
+			nvueAnimation.transition(ref, {
+				styles,
+				...config
+			}, res => {
+				resolve()
+			})
+		})
+	}
+
+	_nvueNextAnimate(animates, step = 0, fn) {
+		let obj = animates[step]
+		if (obj) {
+			let {
+				styles,
+				config
+			} = obj
+			this._animateRun(styles, config).then(() => {
+				step += 1
+				this._nvueNextAnimate(animates, step, fn)
+			})
+		} else {
+			this.currentStepAnimates = {}
+			typeof fn === 'function' && fn()
+			this.isEnd = true
+		}
+	}
+
+	step(config = {}) {
+		// #ifndef APP-NVUE
+		this.animation.step(config)
+		// #endif
+		// #ifdef APP-NVUE
+		this.currentStepAnimates[this.next].config = Object.assign({}, this.options, config)
+		this.currentStepAnimates[this.next].styles.transformOrigin = this.currentStepAnimates[this.next].config.transformOrigin
+		this.next++
+		// #endif
+		return this
+	}
+
+	run(fn) {
+		// #ifndef APP-NVUE
+		this.$.animationData = this.animation.export()
+		this.$.timer = setTimeout(() => {
+			typeof fn === 'function' && fn()
+		}, this.$.durationTime)
+		// #endif
+		// #ifdef APP-NVUE
+		this.isEnd = false
+		let ref = this.$.$refs['ani'] && this.$.$refs['ani'].ref
+		if(!ref) return
+		this._nvueNextAnimate(this.currentStepAnimates, 0, fn)
+		this.next = 0
+		// #endif
+	}
+}
+
+
+const animateTypes1 = ['matrix', 'matrix3d', 'rotate', 'rotate3d', 'rotateX', 'rotateY', 'rotateZ', 'scale', 'scale3d',
+	'scaleX', 'scaleY', 'scaleZ', 'skew', 'skewX', 'skewY', 'translate', 'translate3d', 'translateX', 'translateY',
+	'translateZ'
+]
+const animateTypes2 = ['opacity', 'backgroundColor']
+const animateTypes3 = ['width', 'height', 'left', 'right', 'top', 'bottom']
+animateTypes1.concat(animateTypes2, animateTypes3).forEach(type => {
+	MPAnimation.prototype[type] = function(...args) {
+		// #ifndef APP-NVUE
+		this.animation[type](...args)
+		// #endif
+		// #ifdef APP-NVUE
+		this._nvuePushAnimates(type, args)
+		// #endif
+		return this
+	}
+})
+
+export function createAnimation(option, _this) {
+	if(!_this) return
+	clearTimeout(_this.timer)
+	return new MPAnimation(option, _this)
+}

+ 277 - 0
uni_modules/uni-transition/components/uni-transition/uni-transition.vue

@@ -0,0 +1,277 @@
+<template>
+	<view v-if="isShow" ref="ani" :animation="animationData" :class="customClass" :style="transformStyles" @click="onClick"><slot></slot></view>
+</template>
+
+<script>
+import { createAnimation } from './createAnimation'
+
+/**
+ * Transition 过渡动画
+ * @description 简单过渡动画组件
+ * @tutorial https://ext.dcloud.net.cn/plugin?id=985
+ * @property {Boolean} show = [false|true] 控制组件显示或隐藏
+ * @property {Array|String} modeClass = [fade|slide-top|slide-right|slide-bottom|slide-left|zoom-in|zoom-out] 过渡动画类型
+ *  @value fade 渐隐渐出过渡
+ *  @value slide-top 由上至下过渡
+ *  @value slide-right 由右至左过渡
+ *  @value slide-bottom 由下至上过渡
+ *  @value slide-left 由左至右过渡
+ *  @value zoom-in 由小到大过渡
+ *  @value zoom-out 由大到小过渡
+ * @property {Number} duration 过渡动画持续时间
+ * @property {Object} styles 组件样式,同 css 样式,注意带’-‘连接符的属性需要使用小驼峰写法如:`backgroundColor:red`
+ */
+export default {
+	name: 'uniTransition',
+	emits:['click','change'],
+	props: {
+		show: {
+			type: Boolean,
+			default: false
+		},
+		modeClass: {
+			type: [Array, String],
+			default() {
+				return 'fade'
+			}
+		},
+		duration: {
+			type: Number,
+			default: 300
+		},
+		styles: {
+			type: Object,
+			default() {
+				return {}
+			}
+		},
+		customClass:{
+			type: String,
+			default: ''
+		}
+	},
+	data() {
+		return {
+			isShow: false,
+			transform: '',
+			opacity: 1,
+			animationData: {},
+			durationTime: 300,
+			config: {}
+		}
+	},
+	watch: {
+		show: {
+			handler(newVal) {
+				if (newVal) {
+					this.open()
+				} else {
+					// 避免上来就执行 close,导致动画错乱
+					if (this.isShow) {
+						this.close()
+					}
+				}
+			},
+			immediate: true
+		}
+	},
+	computed: {
+		// 生成样式数据
+		stylesObject() {
+			let styles = {
+				...this.styles,
+				'transition-duration': this.duration / 1000 + 's'
+			}
+			let transform = ''
+			for (let i in styles) {
+				let line = this.toLine(i)
+				transform += line + ':' + styles[i] + ';'
+			}
+			return transform
+		},
+		// 初始化动画条件
+		transformStyles() {
+			return 'transform:' + this.transform + ';' + 'opacity:' + this.opacity + ';' + this.stylesObject
+		}
+	},
+	created() {
+		// 动画默认配置
+		this.config = {
+			duration: this.duration,
+			timingFunction: 'ease',
+			transformOrigin: '50% 50%',
+			delay: 0
+		}
+		this.durationTime = this.duration
+	},
+	methods: {
+		/**
+		 *  ref 触发 初始化动画
+		 */
+		init(obj = {}) {
+			if (obj.duration) {
+				this.durationTime = obj.duration
+			}
+			this.animation = createAnimation(Object.assign(this.config, obj))
+		},
+		/**
+		 * 点击组件触发回调
+		 */
+		onClick() {
+			this.$emit('click', {
+				detail: this.isShow
+			})
+		},
+		/**
+		 * ref 触发 动画分组
+		 * @param {Object} obj
+		 */
+		step(obj, config = {}) {
+			if (!this.animation) return
+			for (let i in obj) {
+				try {
+					if(typeof obj[i] === 'object'){
+						this.animation[i](...obj[i])
+					}else{
+						this.animation[i](obj[i])
+					}
+				} catch (e) {
+					console.error(`方法 ${i} 不存在`)
+				}
+			}
+			this.animation.step(config)
+			return this
+		},
+		/**
+		 *  ref 触发 执行动画
+		 */
+		run(fn) {
+			if (!this.animation) return
+			this.animation.run(fn)
+		},
+		// 开始过度动画
+		open() {
+			clearTimeout(this.timer)
+			this.transform = ''
+			this.isShow = true
+			let { opacity, transform } = this.styleInit(false)
+			if (typeof opacity !== 'undefined') {
+				this.opacity = opacity
+			}
+			this.transform = transform
+			// 确保动态样式已经生效后,执行动画,如果不加 nextTick ,会导致 wx 动画执行异常
+			this.$nextTick(() => {
+				// TODO 定时器保证动画完全执行,目前有些问题,后面会取消定时器
+				this.timer = setTimeout(() => {
+					this.animation = createAnimation(this.config, this)
+					this.tranfromInit(false).step()
+					this.animation.run()
+					this.$emit('change', {
+						detail: this.isShow
+					})
+				}, 20)
+			})
+		},
+		// 关闭过度动画
+		close(type) {
+			if (!this.animation) return
+			this.tranfromInit(true)
+				.step()
+				.run(() => {
+					this.isShow = false
+					this.animationData = null
+					this.animation = null
+					let { opacity, transform } = this.styleInit(false)
+					this.opacity = opacity || 1
+					this.transform = transform
+					this.$emit('change', {
+						detail: this.isShow
+					})
+				})
+		},
+		// 处理动画开始前的默认样式
+		styleInit(type) {
+			let styles = {
+				transform: ''
+			}
+			let buildStyle = (type, mode) => {
+				if (mode === 'fade') {
+					styles.opacity = this.animationType(type)[mode]
+				} else {
+					styles.transform += this.animationType(type)[mode] + ' '
+				}
+			}
+			if (typeof this.modeClass === 'string') {
+				buildStyle(type, this.modeClass)
+			} else {
+				this.modeClass.forEach(mode => {
+					buildStyle(type, mode)
+				})
+			}
+			return styles
+		},
+		// 处理内置组合动画
+		tranfromInit(type) {
+			let buildTranfrom = (type, mode) => {
+				let aniNum = null
+				if (mode === 'fade') {
+					aniNum = type ? 0 : 1
+				} else {
+					aniNum = type ? '-100%' : '0'
+					if (mode === 'zoom-in') {
+						aniNum = type ? 0.8 : 1
+					}
+					if (mode === 'zoom-out') {
+						aniNum = type ? 1.2 : 1
+					}
+					if (mode === 'slide-right') {
+						aniNum = type ? '100%' : '0'
+					}
+					if (mode === 'slide-bottom') {
+						aniNum = type ? '100%' : '0'
+					}
+				}
+				this.animation[this.animationMode()[mode]](aniNum)
+			}
+			if (typeof this.modeClass === 'string') {
+				buildTranfrom(type, this.modeClass)
+			} else {
+				this.modeClass.forEach(mode => {
+					buildTranfrom(type, mode)
+				})
+			}
+
+			return this.animation
+		},
+		animationType(type) {
+			return {
+				fade: type ? 1 : 0,
+				'slide-top': `translateY(${type ? '0' : '-100%'})`,
+				'slide-right': `translateX(${type ? '0' : '100%'})`,
+				'slide-bottom': `translateY(${type ? '0' : '100%'})`,
+				'slide-left': `translateX(${type ? '0' : '-100%'})`,
+				'zoom-in': `scaleX(${type ? 1 : 0.8}) scaleY(${type ? 1 : 0.8})`,
+				'zoom-out': `scaleX(${type ? 1 : 1.2}) scaleY(${type ? 1 : 1.2})`
+			}
+		},
+		// 内置动画类型与实际动画对应字典
+		animationMode() {
+			return {
+				fade: 'opacity',
+				'slide-top': 'translateY',
+				'slide-right': 'translateX',
+				'slide-bottom': 'translateY',
+				'slide-left': 'translateX',
+				'zoom-in': 'scale',
+				'zoom-out': 'scale'
+			}
+		},
+		// 驼峰转中横线
+		toLine(name) {
+			return name.replace(/([A-Z])/g, '-$1').toLowerCase()
+		}
+	}
+}
+</script>
+
+<style></style>

+ 83 - 0
uni_modules/uni-transition/package.json

@@ -0,0 +1,83 @@
+{
+  "id": "uni-transition",
+  "displayName": "uni-transition 过渡动画",
+  "version": "1.2.0",
+  "description": "元素的简单过渡动画",
+  "keywords": [
+    "uni-ui",
+    "uniui",
+    "动画",
+    "过渡",
+    "过渡动画"
+],
+  "repository": "https://github.com/dcloudio/uni-ui",
+  "engines": {
+    "HBuilderX": ""
+  },
+  "directories": {
+    "example": "../../temps/example_temps"
+  },
+  "dcloudext": {
+    "category": [
+      "前端组件",
+      "通用组件"
+    ],
+    "sale": {
+      "regular": {
+        "price": "0.00"
+      },
+      "sourcecode": {
+        "price": "0.00"
+      }
+    },
+    "contact": {
+      "qq": ""
+    },
+    "declaration": {
+      "ads": "无",
+      "data": "无",
+      "permissions": "无"
+    },
+    "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+  },
+  "uni_modules": {
+    "dependencies": [],
+    "encrypt": [],
+    "platforms": {
+      "cloud": {
+        "tcb": "y",
+        "aliyun": "y"
+      },
+      "client": {
+        "App": {
+          "app-vue": "y",
+          "app-nvue": "y"
+        },
+        "H5-mobile": {
+          "Safari": "y",
+          "Android Browser": "y",
+          "微信浏览器(Android)": "y",
+          "QQ浏览器(Android)": "y"
+        },
+        "H5-pc": {
+          "Chrome": "y",
+          "IE": "y",
+          "Edge": "y",
+          "Firefox": "y",
+          "Safari": "y"
+        },
+        "小程序": {
+          "微信": "y",
+          "阿里": "y",
+          "百度": "y",
+          "字节跳动": "y",
+          "QQ": "y"
+        },
+        "快应用": {
+          "华为": "u",
+          "联盟": "u"
+        }
+      }
+    }
+  }
+}

+ 397 - 0
uni_modules/uni-transition/readme.md

@@ -0,0 +1,397 @@
+
+
+## Transition 过渡动画
+> **组件名:uni-transition**
+> 代码块: `uTransition`
+
+
+元素过渡动画
+
+> **注意事项**
+> 为了避免错误使用,给大家带来不好的开发体验,请在使用组件前仔细阅读下面的注意事项,可以帮你避免一些错误。
+> - 组件需要依赖 `sass` 插件 ,请自行手动安装
+> - rotate 旋转动画不需要填写 deg 单位,在小程序上填写单位动画不会执行
+> - NVUE 下修改宽高动画,不能定位到中心点
+> - 百度小程序下修改宽高 ,可能会影响其他动画,需注意
+> - nvue 不支持 costom-class , 请使用 styles
+> - 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839
+
+
+### 安装方式
+
+本组件符合[easycom](https://uniapp.dcloud.io/collocation/pages?id=easycom)规范,`HBuilderX 2.5.5`起,只需将本组件导入项目,在页面`template`中即可直接使用,无需在页面中`import`和注册`components`。
+
+如需通过`npm`方式使用`uni-ui`组件,另见文档:[https://ext.dcloud.net.cn/plugin?id=55](https://ext.dcloud.net.cn/plugin?id=55)
+
+### 基本用法
+
+在 ``template`` 中使用组件
+
+```html
+<template>
+	<view>
+		<button type="primary" @click="open">fade</button>
+		<uni-transition mode-class="fade" :styles="{'width':'100px','height':'100px','backgroundColor':'red'}" :show="show" @change="change" />
+	</view>
+</template>
+
+<script>
+export default {
+	data() {
+		return {
+			show: false,
+		}
+	},
+	onLoad() {},
+	methods: {
+		open(mode) {
+			this.show = !this.show
+		},
+		change() {
+			console.log('触发动画')
+		}
+	}
+}
+</script>
+```
+
+### 样式覆盖
+
+**注意:`nvue` 不支持 `custom-class` 属性 ,需要使用 `styles` 属性进行兼容**
+
+使用 `custom-class` 属性绑定样式,可以自定义 `uni-transition` 的样式
+
+```html
+<template>
+	<view class="content">
+		<uni-transition custom-class="custom-transition" mode-class="fade" :duration="0" :show="true" />
+	</view>
+</template>
+
+<style>
+/* 常规样式覆盖  */
+.content >>> .custom-transition {
+	width:100px;
+	height:100px;
+	background-color:red;
+}
+</style>
+<style lang="scss">
+/* 如果使用 scss 需要使用 /deep/  */
+.content /deep/ .custom-transition {
+	width:100px;
+	height:100px;
+	background-color:red;
+}
+</style>
+```
+
+
+如果使用 `styles` 注意带’-‘连接符的属性需要使用小驼峰写法如:`backgroundColor:red`
+
+```html
+<template>
+	<view class="content">
+		<uni-transition :styles="styles" mode-class="fade" :duration="0" :show="true" />
+	</view>
+</template>
+<script>
+export default {
+	data() {
+		return {
+			styles:{
+				'width':'100px',
+				'height':'100px',
+				'backgroundColor':'red'
+			}
+		}
+	}
+}
+</script>
+```
+
+### 自定义动画
+当内置动画类型不能满足需求的时候 ,可以使用 `step()` 和 `run()` 自定义动画,入参以及具体用法参考下方属性说明
+
+`init()` 方法可以覆盖默认配置
+
+
+```html
+<template>
+	<view>
+		<button type="primary" @click="run">执行动画</button>
+		<uni-transition ref="ani" :styles="{'width':'100px','height':'100px','backgroundColor':'red'}" :show="show"  />
+	</view>
+</template>
+
+<script>
+export default {
+	data() {
+		return {
+			show: true,
+		}
+	},
+	onReady() {
+		this.$refs.ani.init({
+			duration: 1000,
+			timingFunction: 'linear',
+			transformOrigin: '50% 50%',
+			delay: 500
+		})
+	},
+	methods: {
+		run() {
+			// 同时右平移到 100px,旋转 360 读
+			this.$refs.ani.step({
+				translateX: '100px',
+				rotate: '360'
+			})
+			// 上面的动画执行完成后,等待200毫秒平移到 0px,旋转到 0 读
+			this.$refs.ani.step({
+				translateX: '0px',
+				rotate: '0'
+			},
+			{
+				timingFunction: 'ease-in',
+				duration: 200
+			})
+			// 开始执行动画
+			this.$refs.ani.run(()=>{
+				console.log('动画支持完毕')
+			})
+		}
+	}
+}
+</script>
+```
+
+
+## API
+
+### Transition Props
+
+|属性名		|类型	|默认值	|说明					|
+|:-:	|:-:	|:-:					|:-:|
+|show				|Boolean|false	|控制组件显示或隐藏	|
+|mode-class |Array/String	|-		|内置过渡动画类型			|
+|custom-class |String	|-		|自定义类名	|
+|duration	 |Number	|300	|过渡动画持续时间		|
+|styles		 |Object	|-		|组件样式,同 css 样式,注意带’-‘连接符的属性需要使用小驼峰写法如:`backgroundColor:red`	|
+
+#### mode-class 内置过渡动画类型说明
+**格式为** :`'fade'` 或者 `['fade','slide-top']`
+
+|属性名			|说明			|
+|:-:			|:-:			|
+|fade			|渐隐渐出过渡	|
+|slide-top		|由上至下过渡	|
+|slide-right	|由右至左过渡	|
+|slide-bottom	|由下至上过渡	|
+|slide-left		|由左至右过渡	|
+|zoom-in		|由小到大过渡	|
+|zoom-out		|由大到小过渡	|
+
+**注意** 
+
+组合使用时,同一种类型相反的过渡动画如(slide-top、slide-bottom)同时使用时,只有最后一个生效
+
+### Transition Events
+
+|事件名		|说明				|返回值			|
+|:-:			|:-:				|:-:			|
+|click		|点击组件触发		|-				|
+|change		|过渡动画结束时触发	| e = {detail:true}	|
+
+### Transition Methons
+
+|方法名|说明|参数|
+|:-:|:-:|:-:|
+|init()|手动初始化配置|Function(OBJECT:config)|
+|step()|动画队列|Function(OBJECT:type,OBJECT:config)|
+|run()|执行动画|Function(FUNCTION:callback)	|
+
+### init(OBJECT:config)
+**通过 ref 调用方法**
+
+手动设置动画配置,需要在页面渲染完毕后调用
+
+```javascript
+this.$refs.ani.init({
+	duration: 1000,
+	timingFunction:'ease',
+	delay:500,
+	transformOrigin:'left center'
+})
+```
+
+### step(OBJECT:type,OBJECT:config) 动画队列
+**通过 ref 调用方法**
+
+调用 `step()` 来表示一组动画完成,`step` 第一个参数可以传入任意多个动画方法,一组动画中的所有动画会同时开始,一组动画完成后才会进行下一组动画。`step` 第二个参数可以传入一个跟 `uni.createAnimation()` 一样的配置参数用于指定当前组动画的配置。
+
+Tips
+- 第一个参数支持的动画参考下面的 `支持的动画`
+- 第二个参数参考下面的 `动画配置`,可省略,如果省略继承`init`的配置
+
+
+```javascript
+this.$refs.ani.step({
+	translateX: '100px'
+},{
+	duration: 1000,
+	timingFunction:'ease',
+	delay:500,
+	transformOrigin:'left center'
+})
+```
+
+### run(FUNCTION:callback) 执行动画
+**通过 ref 调用方法**
+
+在执行 `step()` 后,需要调用 `run()` 来运行动画 ,否则动画会一直等待
+
+`run()` 方法可以传入一个 `callback` 函数 ,会在所有动画执行完毕后回调
+
+```javascript
+this.$refs.ani.step({
+	translateX: '100px'
+})
+this.$refs.ani.run(()=>{
+	console.log('动画执行完毕')
+})
+
+```
+
+### 动画配置
+动画配置 , `init()` 与 `step()` 第二个参数配置相同 ,如果配置`step() `第二个参数,将会覆盖 `init()` 的配置
+
+|属性名|值|必填|默认值|说明|平台差异|
+|:-:|:-:|:-:|:-:|:-:|:-:|
+|duration|Number|否|400|动画持续时间,单位ms|-|
+|timingFunction|String|否|"linear"|定义动画的效果|-|
+|delay|Number|否|0|动画延迟时间,单位 ms|-|
+|needLayout|Boolean|否|false	|动画执行是否影响布局|仅 nvue 支持|
+|transformOrigin|String	|否|"center center"|设置	[transform-origin](https://developer.mozilla.org/en-US/docs/Web/CSS/transform-origin)|-|
+
+
+### timingFunction 属性说明
+
+|值|说明|平台差异|
+|:-:|:-:|:-:|
+|linear|动画从头到尾的速度是相同的|-|
+|ease|动画以低速开始,然后加快,在结束前变慢|-|
+|ease-in|	动画以低速开始|-|
+|ease-in-out|	动画以低速开始和结束|-|
+|ease-out|动画以低速结束|-|
+|step-start|动画第一帧就跳至结束状态直到结束|nvue不支持|
+|step-end|动画一直保持开始状态,最后一帧跳到结束状态|nvue不支持|
+
+```javascript
+// init 配置
+this.$refs.ani.init({
+	duration: 1000,
+	timingFunction:'ease',
+	delay:500,
+	transformOrigin:'left center'
+})
+// step 配置
+this.$refs.ani.step({
+	translateX: '100px'
+},{
+	duration: 1000,
+	timingFunction:'ease',
+	delay:500,
+	transformOrigin:'left center'
+})
+```
+
+### 支持的动画
+动画方法 
+
+如果同一个动画方法有多个值,多个值使用数组分隔
+
+```javascript
+this.$refs.ani.step({
+	width:'100px',
+	scale: [1.2,0.8],
+})
+```
+
+**样式:**
+
+|属性名|值|说明|平台差异|
+|:-:|:-:|:-:|:-:|
+|opacity|value|透明度,参数范围 0~1|-|
+|backgroundColor|color|颜色值|-|
+|width|length|长度值,如果传入 Number 则默认使用 px,可传入其他自定义单位的长度值|-|
+|height|length|长度值,如果传入 Number 则默认使用 px,可传入其他自定义单位的长度值|-|
+|top|length|长度值,如果传入 Number 则默认使用 px,可传入其他自定义单位的长度值|nvue 不支持|
+|left|length|长度值,如果传入 Number 则默认使用 px,可传入其他自定义单位的长度值|nvue 不支持|
+|bottom|length|长度值,如果传入 Number 则默认使用 px,可传入其他自定义单位的长度值|nvue 不支持|
+|right|length|长度值,如果传入 Number 则默认使用 px,可传入其他自定义单位的长度值|nvue 不支持|
+
+```javascript
+this.$refs.ani.step({
+	opacity: 1,
+	backgroundColor: '#ff5a5f',
+	widht:'100px',
+	height:'50rpx',
+})
+```
+
+**旋转:**
+
+旋转属性的值不需要填写单位
+
+|属性名|值|说明|平台差异	|
+|:-:|:-:|:-:|:-:|
+|rotate|deg|deg的范围-180~180,从原点顺时针旋转一个deg角度	|-|
+|rotateX|deg|deg的范围-180~180,在X轴旋转一个deg角度				|-|
+|rotateY|deg|deg的范围-180~180,在Y轴旋转一个deg角度				|-|
+|rotateZ|deg|deg的范围-180~180,在Z轴旋转一个deg角度				|nvue不支持|
+|rotate3d|x,y,z,deg| 同	[transform-function rotate3d](https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/rotate3d())		|nvue不支持|
+
+```javascript
+this.$refs.ani.step({
+	rotateX: 45,
+	rotateY: 45
+})
+```
+
+**缩放:**
+
+|属性名|值|说明|平台差异|
+|:-:|:-:|:-:	|:-:|
+|scale|sx,[sy]|一个参数时,表示在X轴、Y轴同时缩放sx倍数;两个参数时表示在X轴缩放sx倍数,在Y轴缩放sy倍数|-|
+|scaleX|sx|在X轴缩放sx倍数|-|
+|scaleY|sy|在Y轴缩放sy倍数|-|
+|scaleZ|sz|在Z轴缩放sy倍数|nvue不支持|
+|scale3d|sx,sy,sz|在X轴缩放sx倍数,在Y轴缩放sy倍数,在Z轴缩放sz倍数|nvue不支持|
+
+```javascript
+this.$refs.ani.step({
+	scale: [1.2,0.8]
+})
+```
+
+**偏移:**
+
+|属性名|值|说明|平台差异|
+|:-:|:-:|:-:|:-:|
+|translate|tx,[ty]|一个参数时,表示在X轴偏移tx,单位px;两个参数时,表示在X轴偏移tx,在Y轴偏移ty,单位px。|-|
+|translateX|tx|	在X轴偏移tx,单位px|-|
+|translateY|ty|	在Y轴偏移tx,单位px|-|
+|translateZ|tz|	在Z轴偏移tx,单位px|nvue不支持|
+|translate3d|tx,ty,tz|	在X轴偏移tx,在Y轴偏移ty,在Z轴偏移tz,单位px|nvue不支持|
+
+```javascript
+this.$refs.ani.step({
+	translateX: '100px'
+})
+```
+
+
+
+## 组件示例
+
+点击查看:[https://hellouniapp.dcloud.net.cn/pages/extUI/transition/transition](https://hellouniapp.dcloud.net.cn/pages/extUI/transition/transition)