fis3学习笔记

11月7日

安装fis3:
- 1.在Windows系统中,开始菜单的搜索框中输入cmd打开命令行,在打开的命令行窗口中输入npm install -g fis3,然后按回车,然后fis3自己进行安装,等待十分钟左右,安装完毕。
- 2.在命令行中输入fis3 -v可以查看fis3的版本,检查是否安装成功。如果出现FIS的图标就表示安装成功,如果出现’fis3’ 不是内部或外部命令,也不是可运行的程序或批处理文件,则表示没有安装成功。
需要重新安装的话,重复执行1、2两步。需要升级 FIS3 在命令行中输入npm update -g fis3

11月8日:

起步构建:fis3的构建不会修改源码,而是会通过用户设置,将构建结果输出到指定的目录
  • 在官网下载例子:使用git下载例子: git clone
    https://github.com/hefangshi/fis-quickstart-demo.git
  • 项目根目录:FIS3 配置文件(默认fis-conf.js)所在的目录为项目根目录
  • 构建发布到项目目录的 output 目录下:fis3 release –d .output
  • 构建发布到项目父级目录的 dist 子目录下:fis3 release -d ../dist
构建过程中对资源 URI 进行了替换,替换成了绝对 URL。(把点去掉了)
通俗点讲就是相对路径换成了绝对路径。
相对路径与绝对路径:
    相对路径使用的特殊符号以下为建立路径所使用的几个特殊符号,及其所代表的意义。
"./":代表目前所在的目录。
"../":代表上一层目录。
以"/"开头:代表根目录。
绝对路径是指文件在硬盘上真正存在的路径
这是一个 FIS 的很重要的特性,资源定位。

FIS3 的构建是不会对源码做修改的,而是构建产出到了另外一个目录,并且构建的结果才是用来上线使用的。

11.9.2017

配置文件:
默认配置文件为 fis-conf.js, FIS3 编译的整个流程都是通过配置来控制的。FIS3 定义了一种类似 CSS 的配置方式。固化了构建流程,让工程构建变得简单。
设置规则的配置接口
fis.match(selector, props);
selector :FIS3 把匹配文件路径的路径作为selector,
props :编译规则属性,包括文件属性和插件属性,更多属性
规则覆盖

假设有两条规则 A 和 B,它俩同时命中了文件 test.js,如果 A 在 B 前面,B 的属性会覆盖 A 的同名属性。不同名属性追加到 test.js 的 File 对象上.

fis.media() 
接口提供多种状态功能,比如有些配置是仅供开发环境下使用,有些则是仅供生产环境使用的。

fis3 inspect 来查看文件命中属性的情况。

文件指纹:
文件指纹,唯一标识一个文件。
对 js、css、png 图片引用 URL 添加 md5 戳,

配置如下;

//清除其他配置,只剩下如下配置
fis.match('*.{js,css,png}', {
  useHash: true
});
构建出的index.html文档里的url也有了变化;
文件压缩:
功能组合:
如何用 FIS3 做压缩、文件指纹、图片合并、资源定位,现在把这些功能组合起来,配置文件如下;

// 加 md5
fis.match('*.{js,css,png}', {
  useHash: true
});

// 启用 fis-spriter-csssprites 插件
fis.match('::package', {
  spriter: fis.plugin('csssprites')
});

// 对 CSS 进行图片合并
fis.match('*.css', {
  // 给匹配到的文件分配属性 `useSprite`
  useSprite: true
});

fis.match('*.js', {
  // fis-optimizer-uglify-js 插件进行压缩,已内置
  optimizer: fis.plugin('uglify-js')
});

fis.match('*.css', {
  // fis-optimizer-clean-css 插件进行压缩,已内置
  optimizer: fis.plugin('clean-css')
});

fis.match('*.png', {
  // fis-optimizer-png-compressor 插件进行压缩,已内置
  optimizer: fis.plugin('png-compressor')

调试:
构建时不指定输出目录,即不指定 -d 参数时即:fis3 release,构建结果被发送到内置 Web Server 的根目录下。此目录可以通过执行以下命令打开fis3 server open

fis3 server start启动本地 Web Server,当此 Server 启动后,会自动浏览器打开 http://127.0.0.1:8080,默认监听端口 8080

FIS3 内置的 Server 是常驻的,如果不重启计算机或者调用命令关闭是不会关闭的。

为了方便开发,FIS3 支持文件监听,当启动文件监听时,修改文件会构建发布。而且其编译是增量的,编译花费时间少。fis3 release –w 停止程序用快捷键 CTRL+c

FIS3 支持浏览器自动刷新功能,只需要给 release 命令添加 -L 参数,通常 -w 和 -L 一起使用fis3 release -wL

内置语法:
支持前端开发所需要的编译能力 只有三种
//资源定位:获取任何开发中所使用资源的线上路径;
//内容嵌入:把一个文件的内容(文本)或者 base64 编码(图片)嵌入到另一个文件中;
//依赖声明:在一个文本文件内标记对其他资源的依赖关系;
嵌入资源
嵌入资源即内容嵌入,可以为工程师提供诸如图片base64嵌入到css、js里,前端模板编译到js文件中,将js、css、html拆分成几个文件最后合并到一起的能力。有了这项能力,可以有效的减少http请求数,提升工程的可维护性。 fis不建议用户使用内容嵌入能力作为组件化拆分的手段,因为声明依赖能力会更适合组件化开发。

在html中嵌入资源
在html中可以嵌入其他文件内容或者base64编码值,可以在资源定位的基础上,给资源加 ?__inline 参数来标记资源嵌入需求。
例如:

html中嵌入图片base64:
<img title="百度logo" src="images/logo.gif?__inline"/>
html中嵌入样式文件:
<link rel="stylesheet" type="text/css" href="demo.css?__inline">
html中嵌入脚本资源:
<script type="text/javascript" src="demo.js?__inline"></script>
html中嵌入页面文件:
<link rel="import" href="demo.html?__inline">

在js中,使用编译函数 __inline() 来提供内容嵌入能力。可以利用这个函数嵌入图片的base64编码、嵌入其他js或者前端模板文件的编译内容, 这些处理对html中script标签里的内容同样有效。

例如:
在js中嵌入js文件  __inline('demo.js');
在js中嵌入图片base64var img = __inline('images/logo.gif');
在js中嵌入其他文本文件var css = __inline('a.css');

在css中嵌入资源:

例如:
在css文件中嵌入其他css文件:@import url('demo.css?__inline');
在css中嵌入图片的base64  .style {background: url(images/logo.gif?__inline);}

资源定位:
js语言中,可以使用编译函数 __uri(path) 来定位资源,fis分析js文件或 html中的script标签内内容 时会替换该函数所指向文件的线上url路径。

资源定位结果可以被fis的配置文件控制,比如添加配置,调整文件发布路径

11.13星期一

在html中声明依赖:
用户可以在html的注释中声明依赖关系,这些依赖关系最终会被记录下来,当某个文件中包含字符 RESOURCE_MAP 那么这个记录会被字符串化后替换 RESOURCE_MAP

在js中声明依赖:
fis支持识别js文件中的 注释中的@require字段 标记的依赖关系,这些分析处理对 html的script标签内容 同样有效。

在css中声明依赖:
fis支持识别css文件 注释中的@require字段 标记的依赖关系,这些分析处理对 html的style标签内容 同样有效。

工作原理:
整个 FIS3 的构建流程大体概括分为三个阶段:
   扫描项目目录拿到文件并初始化出一个文件对象列表
   对文件对象中每一个文件进行单文件编译
   获取用户设置的 package 插件,进行打包处理(包括合并图片)
其中打包处理开了四个扩展点,通过用户配置启用某些插件:
   prepackager 打包前处理插件扩展点
   packager 打包插件扩展点,通过此插件收集文件依赖信息、合并信息产出静态资源映射表
   spriter 图片合并扩展点,如 csssprites
   postpackager 打包后处理插件扩展点
其中插件扩展点包括:
   lint:代码校验检查,比较特殊,所以需要 release 命令命令行添加 -l 参数
   parser:预处理阶段,比如 less、sass、es6、react 前端模板等都在此处预编译处理
   preprocessor:标准化前处理插件
   standard:标准化插件,处理内置语法
   postprocessor:标准化后处理插件
预处理阶段一般是对异构语言等进行预编译,如 less、sass 编译为标准的 css;前端模板被编译为 js 等等

初级使用:
1. fis-parser-less:例子引入一个 less 文件,需要 less 预处理插件
2. fis3-postpackager-loader:可对页面散列文件进行合并

FIS3 的构建不会修改源码,而是会通过用户设置,将构建结果输出到指定的目录。

1.  编译工具扩展:根据不同前端模块化框架,扩展声明依赖能力
2.  静态资源管理:解析静态资源映射表加载页面用到的组件及其组件的依赖
3.  目录规范:设置某个文件夹下资源标记为依赖
工具扩展、目录规范,前后端的前端工程项目都需要,其不同之处就在于静态资源管理这部分。
解决方案:解决一系列特定问题的工具、规范、开发、上线支持的方案,被称为 解决方案。前端工程的解决方案一般包括:

研发规范 + 模块化框架 + 测试套件 + 辅助开发工具

高级使用
接口处文档

配置:
1. 默认情况下,配置文件写到 fis-conf.js文件中,此文件放到项目的根目录下
2. 通过 API fis.match() FIS3 在处理的时候首先会加载项目内的所有文件,然后通过 fis.match() 来为某一个文件分配不同的属性,这些属性叫做文件属性。
3. 多状态,刚才说到过,FIS3 中都靠给文件分配不同属性来决定这个文件经过哪些处理的;那么 media 就能让我们在不同状态(情形)下给文件分配不同属性;这个任务就由 fis.media() 完成;
4. fis.match() 的第三个参数就是设置 !important 的,那么设置了这个属性后,后面的规则就无法覆盖了。

::package

fis.match('::package', {
   packager: fis.plugin('map')
});
表示当 packager 阶段所有的文件都分配某些属性
::image

// 所有被标注为图片的文件添加 hash
fis.match('::image', {
  useHash: true
});
project.fileType.image
::text

// 所有被标注为文本的文件去除 hash
fis.match('::text', {
  useHash: false
});
project.fileType.text
:js

匹配模板中的内联 js,支持 isHtmlLike 的所有模板

// 压缩 index.html 内联的 js
fis.match('index.html:js', {
  optimizer: fis.plugin('uglify-js')
});

// 压缩 index.tpl 内联的 js
fis.match('index.tpl:js', {
  optimizer: fis.plugin('uglify-js')
})
:css

匹配模板中内联 css,支持 isHtmlLike 的所有模板

// 压缩 index.html 内联的 css
fis.match('index.html:css', {
  optimizer: fis.plugin('clean-css')
});

// 压缩 index.tpl 内联的 css
fis.match('index.tpl:css', {
  optimizer: fis.plugin('clean-css')
})

配置api
1. 设置一些配置,如系统内置属性 project、namespace、modules、settings。 fis.set 设置的值通过fis.get()获取fis.set(key, value)
2. 获取已经配置的属性,和 fis.set() 成对使用语法fis.get(key)
3. fis.match()给匹配到的文件分配属性,文件属性决定了这个文件进行怎么样的操作;
4. fis.media 是模仿自 css 的 @media,表示不同的状态。这是 fis3 中的一个重要概念,其意味着有多份配置,每一份配置都可以让 fis3 进行不同的编译;比如开发时和上线时的配置不同,比如部署测试机时测试机器目录不同,比如测试环境和线上机器的静态资源 domain 不同,一切这些不同都可以设定特定的 fis.media 来搞定;fis.media(mode)
5. fis.plugin()插件调用接口fis.plugin(name [, props [, position]])

name:
   插件名,插件名需要特殊说明一下,fis3 固定了插件扩展点,每一个插件都有个类型,体现在插件发布的 npm 包名字上;比如 fis-parser-less 插件,parser指的是在 parser 扩展点做了个解析 .less 的插件。
那么设置插件的时候,插件名 less,比如设置一个 parser 类型的插件是这么设置的;

  fis.match('*.less', {
      parser: fis.plugin('less', {}) //属性 parser 表示了插件的类型
  })
props:对象,给插件设置用户属性

fis.match('*.less', {
   parser: fis.plugin('less', {});
});
position:
   设置插件位置,如果目标文件已经设置了某插件,默认再次设置会覆盖掉。如果希望在已设插件执行之前插入或者之后插入,请传入 prepend 或者 append

全局属性通过 fis.set 设置,通过 fis.get 获取;

project.charset:
解释:指定项目编译后产出文件的编码。
值类型:string
默认值:'utf8'
用法:在项目的fis-conf.js里可以覆盖为
 fis.set('project.charset', 'gbk');
project.md5Length
解释:文件MD5戳长度。
值类型:number
默认值:7
用法:在项目的fis-conf.js里可以修改为
 fis.set('project.md5Length', 8);
project.md5Connector
解释:设置md5与文件的连字符。
值类型:string
默认值:_
用法:在项目的fis-conf.js里可以修改为
  fis.set('project.md5Connector ', '.');
project.files
解释:设置项目源码文件过滤器。
值类型:Array
默认值:'**'
用法:fis.set('project.files', ['*.html']);
project.ignore
解释:排除某些文件
值类型:Array
默认值:['node_modules/**', 'output/**', 'fis-conf.js']
用法 fis.set('project.ignore', ['*.bak']); // set 为覆盖不是叠加
project.fileType.text
解释:追加文本文件后缀列表。
值类型:Array | string
默认值:无
说明:fis系统在编译时会对文本文件和图片类二进制文件做不同的处理,文件分类依据是后缀名。虽然内部已列出一些常见的文本文件后缀,但难保用户有其他的后缀文件,内部已列入文本文件后缀的列表为: [ 'css', 'tpl', 'js', 'php', 'txt', 'json', 'xml', 'htm', 'text', 'xhtml', 'html', 'md', 'conf', 'po', 'config', 'tmpl', 'coffee', 'less', 'sass', 'jsp', 'scss', 'manifest', 'bak', 'asp', 'tmp' ],用户配置会 追加,而非覆盖内部后缀列表。
用法:编辑项目的fis-conf.js配置文件fis.set('project.fileType.text', 'tpl, js, css');

11.14.2017

文件属性:
fis3 以文件属性控制文件的编译合并以及各种操作;文件属性包括基本属性和插件属性,插件属性是为了方便在不同的插件扩展点设置插件

release
解释:设置文件的产出路径。默认是文件相对项目根目录的路径,以 / 开头。该值可以设置为 false ,表示为不产出(unreleasable)文件。
值类型:string
默认值:无
  fis.match('/widget/{*,**/*}.js', {
      isMod: true,
      release: '/static/$0'
  });
packTo
解释:分配到这个属性的文件将会合并到这个属性配置的文件中
值类型:string
默认值:无
  fis.match('/widget/{*,**/*}.js', {
      packTo: '/static/pkg_widget.js'
  })
packOrder
解释:用来控制合并时的顺序,值越小越在前面。配合 packTo 一起使用。
值类型:Integer
默认值:0
fis.match('/*.js', {
  packTo: 'pkg/script.js'
})

fis.match('/mod.js', {
  packOrder: -100
})
query
解释:指定文件的资源定位路径之后的query,比如'?t=123124132'。
值类型:string
默认值:无
  fis.set('new date', Date.now());
  fis.match('*.js', {
      query: '?=t' + fis.get('new date')
  });
id
解释:指定文件的资源id。默认是 namespace + subpath 的值
值类型:string
默认值:namespace + subpath
如下方例子,假设 /static/lib/jquery.js 设定了特定的 id jquery, 那么在使用这个组件的时候,可以直接用这个 id;
  fis.match('/static/lib/jquery.js', {
      id: 'jquery',
      isMod: true
  });
使用
  var $ = require('jquery');
moduleId
解释:指定文件资源的模块id。在插件fis3-hook-module里面自动包裹define的时候会用到,默认是 id 的值。
类型:string
默认值:**namespace + subpath**
  fis.match('/static/lib/a.js', {
      id: 'a',
      moduleId: 'a'
      isMod: true
  });
编译前
  exports.a = 10
编译后
  define('a',function(require,exports,module){
    exports.a = 10
  })
url
解释:指定文件的资源定位路径,以 / 开头。默认是 release 的值,url可以与发布路径 release 不一致。
值类型:string
默认值:无
  fis.match('*.{js,css}', {
      release: '/static/$0',
      url: '/static/new_project/$0'
  })
charset
解释:指定文本文件的输出编码。默认是 utf8,可以制定为 gbk 或 gb2312等。
值类型:string
默认值:无
  fis.match('some/file/path', {
      charset: 'gbk'
  });
isHtmlLike
解释:指定对文件进行 html 相关语言能力处理
值类型:bool
默认值:无
isCssLike
解释:指定对文件进行 css 相关的语言能力处理
值类型:bool
默认值:无
isJsLike
解释:指定对文件进行 js 相关的语言能力处理
值类型:string
默认值:无
useHash
解释:文件是否携带 md5 戳
值类型:bool
默认值:false
说明:文件分配到此属性后,其 url 及其产出带 md5 戳;
  fis.match('*.css', {
      useHash: false
  });
  fis.media('prod').match('*.css', {
      useHash: true
  });
fis3 release 时不带hash
fis3 release prod 时带 hash
domain
解释:给文件 URL 设置 domain 信息
值类型:string
默认值:无
说明:如果需要给某些资源添加 cdn,分配到此属性的资源 url 会被添加 domain;
  fis.media('prod').match('*.js', {
      domain: 'http://cdn.baidu.com/'
  });
fis3 release prod 时添加cdn
rExt
解释:设置最终文件产出后的后缀
值类型:string
默认值:无
说明:分配到此属性的资源的真实产出后缀
  fis.match('*.less', {
      rExt: '.css'
  });
源码为.less文件产出后修改为.css文件;
useMap
解释:文件信息是否添加到 map.json
值类型:bool
默认值:无
说明: 分配到此属性的资源出现在静态资源表中,现在对 js、css 等文件默认加入了静态资源表中;
  fis.match('logo.png', {
      useMap: true
  });
isMod
解释:标示文件是否为组件化文件。
值类型:bool
默认值:无
说明:标记文件为组件化文件。被标记成组件化的文件会入map.json表。并且会对js文件进行组件化包装。
  fis.match('/widget/{*,**/*}.js', {
      isMod: true
  });
extras
注释:在[静态资源映射表][]中的附加数据,用于扩展[静态资源映射表][]表的功能。
值类型:Object
默认值:无
说明:无
  fis.match('/page/layout.tpl', {
      extras: {
          isPage: true
      }
  });
requires

注释:默认依赖的资源id表
值类型:Array
默认值:无
说明:
  fis.match('/widget/*.js', {
      requires: [
          'static/lib/jquery.js'
      ]
  });
useSameNameRequire
注释:开启同名依赖
值类型:bool
默认值:false
说明:当设置开启同名依赖,模板会依赖同名css、js;js 会依赖同名 css,不需要显式引用。
  fis.match('/widget/**', {
      useSameNameRequire: true
  });
useCache
注释: 文件是否使用编译缓存
值类型:bool
默认值: true
说明:当设置使用编译缓存,每个文件的编译结果均会在磁盘中保存以供下次编译使用。设置为 false 后,则该文件每次均会被编译。
  fis.match('**.html', {
      useCache: false
  });
useCompile
注释: FIS是否对文件进行编译
值类型:bool
默认值: true
说明:设置为 false 后文件会通过FIS发布,但是FIS不对文件做任何修改
  fis.match('**.html', {
      useCompile: false
  });

插件属性插件属性决定了匹配的文件进行哪些插件的处理;

lint
启用 lint 插件进行代码检查
fis.match('*.js', {
    lint: fis.plugin('js', {

    })
})
parser
启用 parser 插件对文件进行处理;
如编译less文件
fis.match('*.less', {
   parser: fis.plugin('less'), //启用fis-parser-less插件
   rExt: '.css'
});
如编译sass文件

fis.match('*.sass', {
    parser: fis.plugin('node-sass'), //启用fis-parser-node-sass插件
    rExt: '.css'
});
preprocessor
标准化前处理
fis.match('*.{css,less}', {
    preprocessor: fis.plugin('image-set')
});
standard
自定义标准化,可以自定义 uri、embed、require 等三种能力,可自定义三种语言能力的语法;
postprocessor
标准化后处理
fis.match('*.{js,tpl}', {
   postprocessor: fis.plugin('require-async')
});
optimizer
启用优化处理插件,并配置其属性
fis.match('*.css', {
    optimizer: fis.plugin('clean-css')
});

打包阶段插件打包阶段插件设置时必须分配给所有文件,设置时必须 match ::package,不然不做处理。

fis.match(‘::package’, {
packager: fis.plugin(‘map’),
spriter: fis.plugin(‘csssprites’)
});

prepackager
解释:打包预处理插件
值类型:Array | fis.plugin | function
默认值:无
用法:
  fis.match('::package', {
      prepackager: fis.plugin('plugin-name')
  })
packager
解释:打包插件
值类型:Array | fis.plugin | function
默认值:无
用法:
  fis.match('::package', {
      packager: fis.plugin('map')
  })
例子
  fis.media('prod').match('::package', {
      packager: fis.plugin('map')
  });
fis3 release prod 当在 prod 状态下进行打包
spriter
解释:打包后处理csssprite的插件。
值类型:Array | fis.plugin | function
默认值:无
用法:
  fis.match('::package', {
      spriter: fis.plugin('csssprites')
  })
例子
  fis.media('prod').match('::package', {
      spriter: fis.plugin('csssprites')
  });
fis3 release prod 当在 prod 状态下进行 csssprites 处理
postpackager
解释:打包后处理插件。
值类型:Array | fis.plugin | function
默认值:无
用法:
  fis.match('::package', {
      postpackager: fis.plugin('plugin-name')
  })
例子
  fis.media('prod').match('::package', {
      postpackager: fis.plugin('plugin-name')
  });
fis3 release prod 当在 prod 状态下调用打包后处理插件
deploy
解释:设置项目发布方式
值类型:Array | fis.plugin | function
默认值:fis.plugin('local-deliver')
说明:编译打包后,新增发布阶段,这个阶段主要决定了资源的发布方式,而这些方式都是以插件的方式提供的。比如你想一键部署到远端或者是把文件打包到 Tar/Zip 又或者是直接进行 Git 提交,都可以通过设置此属性,调用相应的插件就能搞定了。
用法:
假设项目开发完后,想部署到其他机器上,我们选择 http 提交数据的方式部署
  fis.match('**', {
      deploy: fis.plugin('http-push', {
          receiver: 'http://target-host/receiver.php', // 接收端
          to: '/home/work/www' // 将部署到服务器的这个目录下
      })
  })
规范目录:
•   page 放置页面模板
•   widget 一切组件,包括模板、css、js、图片以及其他前端资源
•   test 一些测试数据、用例
•   static 放一些组件公用的静态资源
•   static/lib 放置一些公共库,例如 jquery, zepto, lazyload
static 所有的静态资源都放到这个目录下
template 所有的模板都放到这个目录下
test 还是一些测试数据、用例
异构语言 less 的使用
fis.match('**.less', {
    parser: fis.plugin('less'), // invoke `fis-parser-less`,
    rExt: '.css'
});
异构语言 sass 的使用
fis.match('**.sass', {
    parser: fis.plugin('sass'), // invoke `fis-parser-sass`,
    rExt: '.css'
});
前端模板的使用
fis.match('**.tmpl', {
    parser: fis.plugin('utc'), // invoke `fis-parser-utc`
    isJsLike: true    
});
某些资源不产出
fis.match('*.inline.css', {
  // 设置 release 为 FALSE,不再产出此文件
  release: false
})
某些资源从构建中去除
FIS3 会读取全部项目目录下的资源,如果有些资源不想被构建,通过以下方式排除。
fis.set('project.ignore', [
  'output/**',
  'node_modules/**',
  '.git/**',
  '.svn/**'
]);

资源合并

packTo命中目标文件,设置 packTo 即能完成简单的合并操作。
fis3-packager-map
packTo 其实用的就是这个插件,fis3 内部其实就是把 packTo 转成了这个插件的配置。
以下配置完全等价于上面 packTo 的配置。
fis.match('::package', {
  packager: fis.plugin('map', {
    '/static/pkg/folderA.js': '/static/folderA/**.js'
  })
})
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值