uni-app

1-uni-app入门

(1)开发规范:

  • 页面遵循vue单文件
  • 组件标签靠近小程序规范
  • 接口靠近小程序规范
  • 事件处理靠近vue

1 页面配置

1.1 全局配置 globalStyle

在pages.josn文件中进行配置

	"globalStyle": {
		"navigationBarTextStyle": "black",//导航栏标题颜色 仅支持black white
		"navigationBarTitleText": "uni-app11",// 默认标题内容 会被页面及的配置覆盖
		"navigationBarBackgroundColor": "#ffaaff", //导航栏背景色
		"backgroundColor": "#ff52f7",
		"enablePullDownRefresh":true,
		"backgroundTextStyle":"dark"//下拉loading的样式 仅支持dark 和 light
	}

在这里插入图片描述

1.2 pages的配置

在pages.josn文件中进行配置,用于规定路径和页面基本信息

	"pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
		{
			"path": "pages/index/index",
			"style": {
				"navigationBarTitleText": "首页",
				"h5": {//h5的单独样式
					"pullToRefresh": {
						"color": "#007AFF"
					}
				}y
			}
		}, {
			"path": "pages/message/message",
			"style": {
				"navigationBarTitleText": "消息",
				"enablePullDownRefresh": false,
				"navigationBarBackgroundColor": "#007AFF"
			}

		}
	],

1.3 tabbar设置

在pages.josn文件中进行配置,用于设置下方导航
最多5个最少2个

	"tabBar":{
		"list":[//导航栏的列表
			{
				"pagePath":"pages/index/index",
				"text":"首页",
				"iconPath":"./static/logo.png",//未选中时展示的图标
				"selectedIconPath":"./static/logo.png"//选中时展示的图标
			},
			{
				"pagePath":"pages/message/message",
				"text":"我的消息",
				"iconPath":"./static/logo.png",//未选中时展示的图标
				"selectedIconPath":"./static/logo.png"//选中时展示的图标
			},
			{
				"pagePath":"pages/contact/contact",
				"text":"联系我们",
				"iconPath":"./static/logo.png",//未选中时展示的图标
				"selectedIconPath":"./static/logo.png"//选中时展示的图标
			}
		],
		"color":"#FFFFFF",//未选中的文字颜色
		"selectedColor":"#4CD964",//选中后的文字颜色
		"backgroundColor":"#333333",
		"borderStyle":"black"//边框颜色 仅支持black white
		// "position":"top"//仅支持微信小程序
	}

1.4 condition配置

仅在开发期间生效,用于模拟直达页面的场景

	"condition":{//启动模式
		"current":0,
		"list":[
			{
				"name":"详情",
				"path":"pages/detail/detail",
				"query":"id=80"//参数
			}
		]
	}

2 uni-app的组件

2.1 text组件

相当于html的 span

		<view class="">
			<text>哈哈哈哈</text>
		</view>
		<view class="">
			<text selectable>文字可选</text>
		</view>
		<view class="">
			<text selectable space="ensp">文字  有     空格</text>
		</view>

请添加图片描述

2.2 view组件

类似于html里面的div

		<view class="">我是一个盒子</view>
		<!-- hover-class指定点击的样式类 -->
		<view class="box" hover-class="box-click">box</view>
		<!-- hover-stop-propagation 阻止冒泡 -->
		<view class="box2" hover-class="box2-click">
			box2
			<view class="box" hover-class="box-click" hover-stop-propagation :hover-start-time="2000">box1</view>
		</view>

请添加图片描述

2.3 botton组件

按钮组件

		<!-- botton组件 -->
		<button type="default">按钮</button>
		<!-- size 设置大小 -->
		<button type="default" size="mini">按钮</button>
		<!-- tyoe 设置样式类型 -->
		<button type="primary" size="mini">按钮</button>
		<!-- plain 按钮是否镂空-->
		<button type="primary" size="mini" plain>按钮</button>
		<!-- disable 是否禁用 -->
		<button type="primary" size="mini" disabled>按钮</button>
		<!-- loading 是否带loading图标 -->
		<button type="default" size="mini" loading>按钮</button>

请添加图片描述

2.4 image组件

		<!-- image 组件 -->
		<image src="../../static/logo.png" mode=""></image>
		<!-- mode 设置裁剪和缩放模式 -->
		<image src="../../static/logo.png" mode="aspectFit"></image>
		<image src="../../static/logo.png" mode="aspectFill"></image>

请添加图片描述

2.5 scroll-view组件

<template>
	<view class="content">
		<scroll-view scroll-x="true" class="scroll">
			<view class="group">
				<view class="item">111</view>
				<view class="item">111</view>
				<view class="item">111</view>
				<view class="item">111</view>
				<view class="item">111</view>
			</view>
		</scroll-view>
	</view>
</template>

<script>
	export default {
		
	}
</script>

<style scoped>
.scroll{
	box-sizing: border-box;
	border:1px solid black;
	height: 220rpx;
	background-color: blanchedalmond;
	white-space: nowrap;
}
.group > view{
	width: 220rpx;
	height: 220rpx;
	background-color: aquamarine;
	display: inline-block;
	margin-right: 10rpx;
}
</style>

2.6 swiper组件

        <swiper :indicator-dots="true" :autoplay="true" :interval="3000" :duration="1000" class="swiper">
			<swiper-item>
				<view class="swiper-item">111</view>
			</swiper-item>
			<swiper-item>
				<view class="swiper-item">222</view>
			</swiper-item>
		</swiper>

3 uni-app中的样式

3.1 说明

  • page{} === body{}
  • 在uni-app中不可以使用 * 选择器
  • uni-app支持class,id,element等选择器
  • 可以使用 @import url(“./xxx/xxx”) 来引入外部样式
  • 定义在App.vue中的样式为 全局样式 ,作用于每一个页面;定义于pages目录下的vue文件中的样式为 局部样式,只作用于对应的页面,并且会覆盖App.vue中的样式。

3.2 rpx

  • 是响应式的px
  • 以750rpx作为100%的基准
  • 当屏幕改变的时候 会响应式的等比例改变

4 uniapp中vue语法格式

4.1 uni-app的模板语法

和vue.js一样

		<view class="box1">{{defualtname}}</view>
		<view class="">{{1+1}}</view>

4.2 v-for v-bind的使用

<image :src="defualtPic" mode="" @click="picChick()"></image>
<view class="" v-for="(item,index) in arr" :key="index">
	<view class="">{{item.name}}</view>
	<view class="">{{item.age}}</view>
</view>
<script>
	export default {
		data() {
			return {
				defualtPic:'../../static/logo.png',
				arr: [
					{
						name: 'lihua1',
						age: "18",
					},
					{
						name: 'lihua2',
						age: "19"
					},
					{
						name: 'lihua3',
						age: "15",
					}
				]
			}
		},
		methods: {
			picChick(){
				uni.showModal({
					content: 'hhhhh',
					showCancel: false
				});
			}
		}
	}
</script>

4.3 v-if v-show的使用

v-if和v-show的区别:

  • v-if:元素隐藏时,直接通过把标签删除来实现了隐藏效果。
  • v-show:元素隐藏时,只是增加了display:none的样式。
<template>
	<view class="content">
		<view v-if="usernameShow">{{username}}</view>
		<view @click="usernameShow=!usernameShow">是否展示username</view>
	</view>
</template>

<script>
	export default {
		data() {
			return{
				username:'用户名',
				usernameShow:true
			}
		}
	}
</script>

4.4 style绑定

<view class="box" :style="`background-color: cornflowerblue;`"></view>

实例:点击方块修改随机背景颜色

<template>
	<view class="content">
		<view class="box" :style="`background-color: ${bgColor};`" @click="changeBgColor"></view>
	</view>
</template>

<script>
	export default {
		data() {
			return{
				bgColor:'cornflowerblue'
			}
		},
		methods:{
			changeBgColor(){
				let color ='#' + String(Math.random()).substr(3,6)
				this.bgColor = color
			}
		}
	}
</script>

<style scoped>
	.box{
		width: 200rpx;
		height: 200rpx;
		border: 2rpx solid black;
	}
</style>

4.5 class绑定

方法1

绑定字符串: :class=“boxClass”

<view class="box1" :class="boxClass"  @click="changeClass"></view>

方法2

绑定对象::class=“{box2:state}”
三元表达式形式::class=" state?box:’ ’ "

<template>
	<view class="content">
		<view class="box1" :class="{box2:state}"  @click="changeClass"></view>
	</view>
</template>

<script>
	export default {
		data() {
			return{
				bgColor:'cornflowerblue',
				state:false
			}
		},
		methods:{
			changeClass(){
				this.state = !this.state
			}
		}
	}
</script>

<style scoped>
	.box1{
		width: 200rpx;
		height: 200rpx;
		border: 2rpx solid black;
		background-color: aquamarine;
	}
	.box2{
		width: 200rpx;
		height: 200rpx;
		border: 2rpx solid black;
		background-color: bisque;
		border-radius: 20rpx;
	}
</style>

实例:点击导航栏导航高亮显示

<template>
	<view class="content">
		<view class="nav">
			<view class="item" v-for="(item,index) in navArr" :key="index" :class="{navActive:navIndex===index}" @click="changeNav(index)">{{item.title}}</view>
		</view>
	</view>
</template>

<script>
	export default {
		data() {
			return{
				navArr:[
					{title:'首页'},
					{title:'介绍'},
					{title:'教程'},
					{title:'组件'},
				],
				navIndex:0
			}
		},
		methods:{
			changeNav(index){
				console.log(index)
				this.navIndex = index
			}
		}
	}
</script>

<style scoped>
	.nav{
		display: flex;
		justify-content: space-between;
		flex-wrap: nowrap;
	}
	.item{
		width:25%;
		background-color: antiquewhite;
		padding: 15rpx 0;
		text-align: center;
		transition: all 0.3s;
	}
	.navActive{
		background-color: cadetblue;
		color: #fff;
	}
</style>

4.6 computed的用法

<template>
	<view class="content">
		<input type="text" v-model="value" class="nav-content">
		<view >标题:{{ value }}</view>
		<view >修改后的标题:{{ newValue}}</view>
	</view>
</template>

<script>
	export default {
		data() {
			return{
				value:''
			}
		},
		computed:{
			newValue(){
				return '哈哈哈'+ this.value
			}
		}
	}
</script>

9 uni-app的生命周期

9.1 应用的生命周期

定义在 App.vue

函数名说明
onLaunch (一次)uni-app初始化完成时触发(全局只触发一次)
onShow(多次)当uni-app启动 或者从后台进入前台显示
onReady(多次)当uni-app 从前台进入后台
onError(多次)当uni-app报错时触发

9.2 页面的生命周期

  • 定义在页面中
  • 注意: tabbar中的页面展现过一次之后就保留在内存中,在次切换tabbar页面,不会触发onLoad事件,只触发onShow事件
函数名说明
onLoad (一次)监听页面加载,其参数为上一个页面传递的数据,参数类型为Object(用于页面传参)
onShow (多次)监听页面显示,页面每次出现在屏幕上的时候都会触发
onReady(一次)监听页面渲染完成
onHide(多次)监听页面隐藏
onUnload(多次)监听页面卸载
onResize(多次)监听页面窗口尺寸变化
onPullDownRefresh(多次)监听用户下拉的动作 一般用于下拉刷新
onReachBottom(多次)监听页面滚动到底部事件,一般用于上拉刷新
…见文档
		onLoad(options) {
			console.log("页面加载了",options)
		},
		onShow() {
			console.log("页面显示了")
		},
		onReady() {
			console.log("页面渲染完成")
		},
		onHide() {
			console.log("页面隐藏")
		},

10 页面刷新

10.1 下拉刷新的学习

(1)开启下拉刷新的两种方式
方式一:在pages.json里面配置

            "path" : "pages/uni-style/uni-style",
            "style" :                                                                                    
            {
                "navigationBarTitleText": "uni-css",
                "enablePullDownRefresh": true,//开启下拉刷新
				"h5":{
					"pullToRefresh":{
						"color":"#007AFF"
					}
				}
            }

方式二:
调用=uni.startPullDownRefresh() 方法

<button type="default" size="mini" @click="pullDown">刷新</button>
methods: {
	pullDown(){
		uni.startPullDownRefresh()
	  }
	}

(2)监听下拉刷新事件
使用生命周期函数 onPullDownRefresh()
使用 uni.stopPullDownRefresh() 关闭下拉刷新

		onPullDownRefresh() {
			console.log("触发下拉刷新")
			this.list=["ui11","前端22","测试33","java44","大数据5"]
			setTimeout(()=>{
				uni.stopPullDownRefresh()//关闭下拉刷新
			},1000)
		},

10.2 上拉刷新(页面触底刷新)学习

(0)说明 可以配置页面触底距离底部的高度
在pages.json中配置 onReachBottomDistance
单位为px 默认50

            "path" : "pages/list/list",
            "style" :                                                                                    
            {
                "navigationBarTitleText": "列表",
                "enablePullDownRefresh": true,
				"onReachBottomDistance":200
            }

(1)监听上拉刷新事件(页面触底事件)
使用生命周期函数 onReachBottom

<view class="box-item" v-for="(item,index) in list" :key="index">{{item}}</view>
<script>
	export default {
		data() {
			return {
				list:["ui","前端","测试","java","大数据"]
			}
		},
		onReachBottom() {
			console.log("页面触底了")
			this.list=[...this.list,...["ui11","前端22","测试33","java44","大数据5"]]
		},
	}
</script>

12 网络请求-发送请求

12.1 uni.request()

使用 uni.request() 发送网络请求。

			uni.request({
				url:'https://www.baidu.com' ,//请求地址
				method:"POST",
				header:{ //请求头
					"content-type":"appLication/x-wwww-form-urlencoded" 
				},
				data:{
					nameId:'18452'
				},
				success:res=>{
					console.log(res)
					this.imgArr=res.data.data
				}
			})

12.2 请求封装

request.js文件
在这里插入图片描述

const BASE_URL = "http://localhoat:9090" //后台ip和端口号

export const request = (option) =>{
	return new Promise((resolve,reject)=>{
		uni.request({
			url:BASE_URL + option.url,
			method:option.method || 'GET',
			header: {token:uni.getStorageSync('User')?uni.getStorageSync('user').token:''},
			data:option.data||{},
			success:res=>{
				const data = ras.data
				if(data.code) === '401'){
					uni.navigateTo({
						url:'/pages/login/lohin'
					})
				}else if(data.code !== '200'){
					uni.showToast({
						icon:'error',
						title:'操作错误'
					})
				}
				resolve(data)
			},
			fail: error=>{
				uni.showToast({
					icon:'error',
					title:'操作错误'
				})
			}
		})
	})
}

在main.js中引用
在这里插入图片描述
在.vue文件中使用

        methods: {
			getNews(){
				this.$request({url:xxx,data:xxx}).then(res=>{
					
				})
			}
		}

13 本地数据缓存

名称作用
uni.setStorage存储
uni.getStorage获取
uni.removeStorage删除
uni.setStorageSync存储数据–同步
uni.getStorageSync获取数据–同步
uni.removeStorageSync移除数据–同步
		<button type="default" size='mini' @click="setStorage">存储数据</button>
		<button type="default" size='mini' @click="getStorage">获取数据</button>
		<button type="default" size='mini' @click="deleteStorage">移除数据</button>
		<button type="default" size='mini' @click="setStorageSync">存储数据--同步</button>
		<button type="default" size='mini' @click="getStorageSync">获取数据--同步</button>
		<button type="default" size='mini' @click="deleteStorageSync">移除数据--同步</button>
            setStorage(){
				uni.setStorage({
					key:'id',
					data:80,
					success() {
						console.log('存储成功')
					}
				})
			},
			getStorage(){
				uni.getStorage({
					key:'id',
					success(res) {
						console.log("获取成功",res.data)
					}
				})
			},
			deleteStorage(){
				uni.removeStorage({
					key:'id',
					success() {
						console.log("移除成功")
					}
				})
			},
			setStorageSync(){
				uni.setStorageSync('id',100)
			},
			getStorageSync(){
				const a=uni.getStorageSync('id')
				console.log(a)
			},
			deleteStorageSync(){
				uni.removeStorageSync('id')
			}

14 上传图片

使用 uni-chooseimage() 上传图片

<button type="default" size='mini' @click="setimg()">上传图片</button>
setimg(){
	uni.chooseImage({
		count:5,//在浏览器中不能限制
		success:res=>{
			this.imgarr=res.tempFilePaths
			}
		})
},

15 预览图片

使用uni.previewImage进行图片预览

<image :src="item" mode="" v-for="(item,index) in imgarr" :key=index @click="previewimg(item)"></image>
previewimg(item){
	uni.previewImage({
		current:item,
		urls:this.imgarr,//图片列表
		loop:true,//是否循环
		indicator:'default',//可以取default-圆点 number-数字 none不显示 要写字符串类型的数据
		// loop 和 indicator只在app中可见 在浏览器和小程序中都看不到
		})
	}
}

16 条件注释实现跨端兼容

请添加图片描述
使用 #ifdef‘、#endif来进行条件注释
(1)结构的条件注释

		<!-- 结构的条件注释 -->
		<!-- #ifdef H5 -->
		<view class="">我希望只在h5中看见</view>
		<!-- #endif -->
		<!-- #ifdef MP-WEIXIN -->
		<view class="">我希望只在微信小程序中看见</view>
		<!-- #endif -->

(2) 函数中的条件注释

		// 函数中的条件注释
		onLoad() {
			// #ifdef H5 
			console.log("我希望h5中打印");
			// #endif
			// #ifdef MP-WEIXIN
			console.log("我希望微信小程序中打印");
			// #endif
		},

(3)样式的条件注释

/* 样式的条件注释 */
/* #ifdef H5 */
.box{
	color: #2C405A;
}
/* #endif */
/*  #ifdef MP-WEIXIN */
.box{
	color: #4CD964;
}
/* #endif */

17 uni-app中的路由跳转

17.1 声明式页面跳转

使用组件navigator进行页面跳转

		<!-- 导航跳转 -->
		<navigator url="../detail/detail">跳转到详情页--有返回</navigator>
		<!-- open-type="switchTab" 跳转到有tabbar的页面 -->
		<navigator url="../message/message" open-type="switchTab">跳转到信息页</navigator>
		<!-- open-type="redirect" 先关闭当前页面 在跳转到新的页面 没有返回的箭头了 -->
		<navigator url="../detail/detail" open-type="redirect">跳转到详情页--没有返回</navigator>

17.2 编程式导航

		<!-- 编程式导航 -->
		<button type="default" size='mini' @click="godetail()">跳转到详情页面</button>
		<button type="default" size='mini' @click="gomessage()">跳转到信息页面</button>
		<button type="default" size='mini' @click="godetailandclosepage()">跳转到详情页面并关闭当前页面</button>
			godetail(){
				// 跳转到非tabbar
				uni.navigateTo({
					url:'../detail/detail'
				})
			},
			gomessage(){
				//跳转到tabbar
				uni.switchTab({
					url:'../message/message'
				})
			},
			godetailandclosepage(){
				// 跳转到非tabbar 并关闭当前页面
				uni.redirectTo({
					url:'../detail/detail'
				})
			}
返回1个路由
uni.navigateBack({ delta: 1})
返回2个路由
uni.navigateBack({ delta: 2})

17.3 跳转页面并传参

uni.navigateTo({
	url: 'test?id=1&name=uniapp'
})
<navigator url="../detail/detail?id=80&age=19">跳转到详情页--有返回</navigator>


使用onload生命周期函数来取

		onLoad(options) {
			console.log(options)//{id: "80",age:'19'}
		},

17.4 编程式路由跳转总结

路由跳转方法说明实例特点
uni.navigateTo(OBJECT)保留当前页面,跳转到应用内的某个页面,使用uni.navigateBack可以返回到原页面。uni.navigateTo({url: 'testid=1&name=uniapp'});不可跳tabbar
uni.redirectTo(OBJECT)关闭当前页面,跳转到应用内的某个页面。uni.redirectTo({url: 'test?id=1'});不可跳tabbar
uni.reLaunch(OBJECT)关闭所有页面,打开到应用内的某个页面。uni.reLaunch({url: 'test?id=1'});可跳tabbar
uni.switchTab(OBJECT)跳转到 tabBar 页面,并关闭其他所有非 tabBar 页面。uni.switchTab({url:'/pages/index/index'});可跳tabbar,不可携带参数
  • navigateTo, redirectTo 只能打开非 tabBar 页面。 switchTab 只能打开 tabBar 页面。
  • reLaunch 可以打开任意页面。 页面底部的 tabBar 由页面决定,即只要是定义为 tabBar 的页面,底部都有 tabBar。
  • 不能在 App.vue 里面进行页面跳转。
  • H5端页面刷新之后页面栈会消失,此时navigateBack不能返回,如果一定要返回可以使用history.back()导航到浏览器的其他历史记录。

18 组件components

18.1 注册组件 - vue方式(1)

		<!-- 组件 -->
		<test></test>
      //与method同级
		components:{
			test
		}

18.2 注册组件 - easycom方式(2)

步骤1: 在主目录下创建components目录
在这里插入图片描述

步骤2: 创建组件
在这里插入图片描述

步骤三: 在页面中使用组件
在这里插入图片描述

18.3 组件的生命周期函数

请添加图片描述

v-if控制组件的创建和销毁

18.4 组件之间传值

18.3.1 父传子 props

<test :title="title"></test>

接收

	export default {
		name:"test",
		data() {
			return {
				
			};
		},
       // 接收props方式1 简答接收
       props: ['name', 'sex', 'age'],
       // 接收props方式2 接收并预设数据类型
       props: {
         name: String,
         sex: String,
         age: Number
       },
       // 接收props方式3 接收并预设类型和必要性和默认值
       props: {
         name: { type: String, required: true },
         sex: { type: String, required: true },
         age: { type: Number, default: 99 },
         array: { type: Array, default:()=>[1,2,3]},
         array: { type: Object, default:()=>{name:'tom'}}
       }
	}
18.3.2 子传父 emit

主要是通过触发自定义事件

<test :title="title" @myEven="getnum" @click.native="xxxx"></test>
getnum(num){
	console.log("子组件传来的值为",num)
}

<button type="button" @click="sendNum()">给父组件传值</button>
data() {
	return {
		num:3
		};
},
methods:{
	sendNum(){
		this.$emit('myEven',this.num)
	}
},
18.3.2 父子互相传值 .sync update:
  • :title.sync="title" : 使用.sync修饰,titie变为一个双向绑定 (响应式) 的变量,父子组件的改变互相影响。
    父组件
  • update:title: 子组件使用update:来修饰,用于向主组件传递修改值
<template>
	<view class="content">
		<pubTitle :title.sync="title"></pubTitle>
	</view>
</template>

<script>
	export default {
		data() {
			return{
				title:'默认'
			}
		},
	}
</script>

子组件

<template>
	<view class="pubTitle">
		<view class="title">文章的标题:{{title}}</view>
		<button @click="changeTitle">修改标题</button>
	</view>
</template>

<script>
	export default {
		name:"pubTitle",
		data() {
			return {
				
			};
		},
		props:['title'],
		methods:{
			changeTitle(){
				this.$emit("update:title",'修改后的标题')
			}
		}
	}
</script>
18.3.3 兄弟组件传值

使用uni.on注册全局事件
使用uni.$emit调用全局组件

组件b

<template>
	<view>
		这是b组件的数据{{num}}
	</view>
</template>

<script>
	export default {
		name:"b",
		data() {
			return {
				num:0
			};
		},
		created() {
			// 注册全局事件
			uni.$on('updataNum',(num)=>{
				this.num+=num
			})
		}
	}
</script>

组件a

<button type="button" @click="changeNum()">修改b中的数据</button>

methods:{
	changeNum(){
		uni.$emit('updataNum',10)
		}
	}
}

21 uni-app全局变量的定义

uni-app全局变量的定义

22 vue项目中导入uni扩展组件

请添加图片描述
uni-ui

扩展1–反馈组件

    uni.showToast({
        title: '该活动已结束,期待您的下次参与。',
        icon: 'none',
        duration: 3000,
        position: 'center'
      });
      
    uni.showLoading({ title: '加载中', mask: true })
    uni.hideLoading();

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值