Explorar el Código

Merge branch 'master' of http://git.liuniu946.com/cmy/NFT

hwq hace 3 años
padre
commit
7db838cb9d

+ 545 - 0
components/lb-picker/README.md

@@ -0,0 +1,545 @@
+<p align="center">
+  <a href="https://github.com/liub1934/uni-lb-picker">
+    <img src="https://img.shields.io/github/stars/liub1934/uni-lb-picker">
+  </a>
+  <a href="https://github.com/liub1934/uni-lb-picker/fork">
+    <img src="https://img.shields.io/github/forks/liub1934/uni-lb-picker">
+  </a>
+  <a href="https://github.com/liub1934/uni-lb-picker/issues">
+    <img src="https://img.shields.io/github/issues/liub1934/uni-lb-picker">
+  </a>
+  <a href="https://www.npmjs.com/package/uni-lb-picker">
+    <img src="https://img.shields.io/npm/v/uni-lb-picker">
+  </a>
+  <a href="https://npmcharts.com/compare/uni-lb-picker?minimal=true">
+    <img src="https://img.shields.io/npm/dm/uni-lb-picker">
+  </a>
+  <a href="https://standardjs.com">
+    <img src="https://img.shields.io/badge/code%20style-standard-brightgreen">
+  </a>
+  <a href="https://github.com/liub1934/uni-lb-picker/blob/master/LICENSE">
+    <img src="https://img.shields.io/github/license/liub1934/uni-lb-picker">
+  </a>
+</p>
+
+插件市场里面的 picker 选择器不满足自己的需求,所以自己写了一个简单的 picker 选择器,可扩展、可自定义,一般满足日常需要。  
+Github:[点击前往](https://github.com/liub1934/uni-lb-picker)  
+插件市场:[点击前往](https://ext.dcloud.net.cn/plugin?id=1111)  
+H5 Demo:[点击预览](https://github.liubing.me/uni-lb-picker)
+
+> 如果问题最好去 github 反馈,插件市场评论区留下五星好评即可, [点我去反馈](https://github.com/liub1934/uni-lb-picker/issues/new)  
+> 最好提供一下使用的什么端,数据结构及大概的代码,我好复现找问题,不要直接提`怎么xxx报错了`等没意义的问题,神仙也不知道你为啥报错了。
+
+> **由于之前`cancel`拼写失误,写成了`cancle`,`v1.08`现已修正,如果之前版本有使用`cancel`事件的,更新后请及时修正。**
+
+## 兼容性
+
+App + Nvue + H5 + 各平台小程序(快应用及 360 未测试)
+
+## 功能
+
+- 单选
+- 多级联动,非多级联动,理论支持任意级数
+- 省市区选择,基于多级联动
+- 日期选择器,年月日时分秒可自由组合选择(引入了`dayjs`方便处理日期)
+- 自定义选择器头部确定取消按钮颜色及插槽支持
+- 选择器可视区自定义滚动个数
+- 自定义数据字段,满足不同人的需求
+- 自定义选择器样式
+- formatter 格式化自定义显示
+- 单选及非联动选择支持扁平化的简单数据,如下形式:
+
+```javascript
+// 单选列表
+list1: ['选项1', '选项2', '选项2'],
+// 非联动选择列表
+list2: [
+  ['选项1', '选项2', '选项3'],
+  ['选项11', '选项22', '选项33'],
+  ['选项111', '选项222', '选项333']
+]
+```
+
+## 引入插件
+
+单独引入,在需要使用的页面上 import 引入即可
+
+```html
+<template>
+  <view>
+    <lb-picker></lb-picker>
+  </view>
+</template>
+
+<script>
+  import LbPicker from '@/components/lb-picker'
+  export default {
+    components: {
+      LbPicker
+    }
+  }
+</script>
+```
+
+全局引入,`main.js`中 import 引入并注册即可全局使用
+
+```jsvascript
+import LbPicker from '@/components/lb-picker'
+Vue.component("lb-picker", LbPicker)
+```
+
+easycom 引入(推荐使用此方式)
+
+`pages.json`加上如下配置:
+
+```json
+"easycom": {
+  "autoscan": true,
+  "custom": {
+    "lb-picker": "@/components/lb-picker/index.vue"
+  }
+}
+```
+
+npm 安装引入:
+
+```shell
+npm install uni-lb-picker
+```
+
+```jsvascript
+import LbPicker from 'uni-lb-picker'
+```
+
+## 选择器数据格式
+
+### 单选
+
+常规数据
+
+```javascript
+list: [
+  {
+    label: '选项1',
+    value: '1'
+  },
+  {
+    label: '选项2',
+    value: '2'
+  }
+]
+```
+
+扁平化简单数据
+
+```javascript
+list: ['选项1', '选项2']
+```
+
+### 多级联动
+
+```javascript
+list: [
+  {
+    label: '选项1',
+    value: '1',
+    children: [
+      {
+        label: '选项1-1',
+        value: '1-1',
+        children: [
+          {
+            label: '选项1-1-1',
+            value: '1-1-1'
+          }
+        ]
+      }
+    ]
+  }
+]
+```
+
+### 非联动选择
+
+常规数据
+
+```javascript
+list: [
+  [
+    { label: '选项1', value: '1' },
+    { label: '选项2', value: '2' },
+    { label: '选项3', value: '3' }
+  ],
+  [
+    { label: '选项11', value: '11' },
+    { label: '选项22', value: '22' },
+    { label: '选项33', value: '33' }
+  ],
+  [
+    { label: '选项111', value: '111' },
+    { label: '选项222', value: '222' },
+    { label: '选项333', value: '333' }
+  ]
+]
+```
+
+扁平化简单数据
+
+```javascript
+list: [
+  ['选项1', '选项2', '选项3'],
+  ['选项11', '选项22', '选项33'],
+  ['选项111', '选项222', '选项333']
+]
+```
+
+## 调用显示选择器
+
+通过`ref`形式手动调用`show`方法显示,隐藏同理调用`hide`
+
+```html
+<lb-picker ref="picker"></lb-picker>
+```
+
+```javascript
+this.$refs.picker.show() // 显示
+this.$refs.picker.hide() // 隐藏
+```
+
+`v1.1.3`新增,将需要点击的元素包裹在`lb-picker`中即可。
+
+```html
+<lb-picker>
+  <button>点我直接打开选择器</button>
+</lb-picker>
+```
+
+## 绑定值及设置默认值
+
+支持 vue 中`v-model`写法绑定值,无需自己维护选中值的索引。
+
+```javascript
+<lb-picker v-model="value1"></lb-picker>
+<lb-picker v-model="value2"></lb-picker>
+<lb-picker v-model="value3"></lb-picker>
+
+data () {
+  return {
+    value1: '', // 单选
+    value2: [], // 多列联动选择
+    value2: '2021-01-05', // 日期,设置一个具体的日期,留空则默认选中当前日期
+  }
+}
+```
+
+## 多个选择器
+
+通过设置不同的`ref`,然后调用即可
+
+```javascript
+<lb-picker ref="picker1"></lb-picker>
+<lb-picker ref="picker2"></lb-picker>
+
+this.$refs.picker1.show() // picker1显示
+this.$refs.picker2.show() // picker2显示
+```
+
+## 省市区选择
+
+省市区选择是基于多列联动选择,数据来源:[https://github.com/modood/Administrative-divisions-of-China](https://github.com/modood/Administrative-divisions-of-China),  
+省市区文件位于`/pages/demos/area-data-min.js`,自行引入即可,可参考`demo3省市区选择`,  
+也可使用自己已有的省市区数据,如果数据字段不一样,也可以自定义,参考下方自定义数据字段。
+
+## 自定义数据字段
+
+为了满足不同人的需求,插件支持自定义数据字段名称, 插件默认的数据字段如下形式:
+
+```javascript
+list: [
+  {
+    label: '选择1',
+    value: 1,
+    children: []
+  },
+  {
+    label: '选择1',
+    value: 1,
+    children: []
+  }
+]
+```
+
+如果你的数据字段和上面不一样,如下形式:
+
+```javascript
+list: [
+  {
+    text: '选择1',
+    id: 1,
+    child: []
+  },
+  {
+    text: '选择1',
+    id: 1,
+    child: []
+  }
+]
+```
+
+通过设置参数中的`props`即可,如下所示:
+
+```javascript
+<lb-picker :props="myProps"></lb-picker>
+
+data () {
+  return {
+    myProps: {
+      label: 'text',
+      value: 'id',
+      children: 'child'
+    }
+  }
+}
+```
+
+## 插槽使用
+
+选择器支持一些可自定义化的插槽,如选择器的取消和确定文字按钮,如果需要对其自定义处理的话,比如加个 icon 图标之类的,可使用插槽,使用方法如下:
+
+```html
+<lb-picker>
+  <view slot="cancel-text">我是自定义取消</view>
+  <view slot="confirm-text">我是自定义确定</view>
+</lb-picker>
+```
+
+也可参考示例中的`demo5`,自定义插槽元素样式交给开发者自由调整,插槽仅提供预留位置。
+
+其他插槽见下。
+
+## 参数及事件
+
+### Props
+
+#### 通用 Props
+
+| 参数                   | 说明                                                                                                                                                                                                                                                                                                                                                                                                                                                                      | 类型                                      | 可选值                                                                                                | 默认值             |
+| :--------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :---------------------------------------- | :---------------------------------------------------------------------------------------------------- | :----------------- |
+| value/v-model          | 绑定值,联动选择为 Array 类型                                                                                                                                                                                                                                                                                                                                                                                                                                             | String/Number/Array                       | -                                                                                                     | 日期类型为当前日期 |
+| mode                   | 选择器类型                                                                                                                                                                                                                                                                                                                                                                                                                                                                | String                                    | selector 单选/multiSelector 多级联动/unlinkedSelector 多级非联动/dateSelector 日期选择`(v1.1.9 新增)` | selector           |
+| cancel-text            | 取消文字                                                                                                                                                                                                                                                                                                                                                                                                                                                                  | String                                    | -                                                                                                     | 取消               |
+| cancel-color           | 取消文字颜色                                                                                                                                                                                                                                                                                                                                                                                                                                                              | String                                    | -                                                                                                     | #999               |
+| confirm-text           | 确定文字                                                                                                                                                                                                                                                                                                                                                                                                                                                                  | String                                    | -                                                                                                     | 确定               |
+| confirm-color          | 确定文字颜色                                                                                                                                                                                                                                                                                                                                                                                                                                                              | String                                    | -                                                                                                     | #007aff            |
+| empty-text             | `(v1.0.7 新增)`选择器列表为空的时候显示的文字                                                                                                                                                                                                                                                                                                                                                                                                                             | String                                    | -                                                                                                     | 暂无数据           |
+| empty-color            | `(v1.0.7 新增)`暂无数据文字颜色                                                                                                                                                                                                                                                                                                                                                                                                                                           | String                                    | -                                                                                                     | #999               |
+| column-num             | 可视滚动区域内滚动个数,最好设置奇数值                                                                                                                                                                                                                                                                                                                                                                                                                                    | Number                                    | -                                                                                                     | 5                  |
+| radius                 | 选择器顶部圆角,支持 rpx,如 radius="10rpx"                                                                                                                                                                                                                                                                                                                                                                                                                               | String                                    | -                                                                                                     | -                  |
+| column-style           | `(v1.1.6 重新新增)`选择器默认样式,仅`nvue`支持,其他端见下`选择器自定义样式`说明                                                                                                                                                                                                                                                                                                                                                                                         | Object                                    | -                                                                                                     | -                  |
+| active-column-style    | `(v1.1.6 重新新增)`选择器选中样式,仅`nvue`支持,其他端见下`选择器自定义样式`说明                                                                                                                                                                                                                                                                                                                                                                                         | Object                                    | -                                                                                                     | -                  |
+| loading                | 选择器是否显示加载中,可使用 loading 插槽自定义加载效果                                                                                                                                                                                                                                                                                                                                                                                                                   | Boolean                                   | -                                                                                                     | -                  |
+| mask-color             | 遮罩层颜色                                                                                                                                                                                                                                                                                                                                                                                                                                                                | String                                    | -                                                                                                     | rgba(0, 0, 0, 0.4) |
+| show-mask              | `(v1.1.0 新增)`是否显示遮罩层                                                                                                                                                                                                                                                                                                                                                                                                                                             | Boolean                                   | true/false                                                                                            | true               |
+| close-on-click-mask    | 点击遮罩层是否关闭选择器                                                                                                                                                                                                                                                                                                                                                                                                                                                  | Boolean                                   | true/false                                                                                            | true               |
+| ~~change-on-init~~     | ~~(v1.0.7 已弃用)初始化时是否触发 change 事件~~                                                                                                                                                                                                                                                                                                                                                                                                                           | Boolean                                   | true/false                                                                                            | -                  |
+| dataset                | `(v1.0.7 新增)`可以向组件中传递任意的自定义的数据(对象形式数据),如`:dataset="{name:'test'}"`,在`confirm`或`change`事件中可以取到                                                                                                                                                                                                                                                                                                                                      | Object                                    | -                                                                                                     | -                  |
+| show-header            | `(v1.0.8 新增)`是否显示选择器头部                                                                                                                                                                                                                                                                                                                                                                                                                                         | Boolean                                   | -                                                                                                     | true               |
+| inline                 | `(v1.0.8 新增)`inline 模式,开启后默认显示选择器,无需点击弹出,可以配合`show-header`一起使用                                                                                                                                                                                                                                                                                                                                                                             | Boolean                                   | -                                                                                                     | -                  |
+| z-index                | `(v1.0.9 新增)`选择器层级,遮罩层默认-1                                                                                                                                                                                                                                                                                                                                                                                                                                   | Number                                    | -                                                                                                     | 999                |
+| safe-area-inset-bottom | `(v1.1.4 新增)`是否留出底部安全距离(nvue 无效)                                                                                                                                                                                                                                                                                                                                                                                                                          | Boolean                                   | true/false                                                                                            | true               |
+| disabled               | `(v1.1.4 新增)`是否禁用选择器,禁用后无法弹出选择器                                                                                                                                                                                                                                                                                                                                                                                                                       | Boolean                                   | -                                                                                                     | -                  |
+| align                  | `(v1.1.6 新增)`选择器中文字对齐方式,默认居中                                                                                                                                                                                                                                                                                                                                                                                                                             | String                                    | left/center/right                                                                                     | center             |
+| press-enable           | `(v1.1.6 新增)`是否开启长按选择器数据`showtoast`弹出`label`提示,部分情况下选择器数据文字过长会显示省略号,如需查看完整的文字内容,可开启此选项,长按后会`showtoast`弹出完整的文字内容,默认不开启(支付宝小程序暂不支持[详情](https://ask.dcloud.net.cn/question/106237))                                                                                                                                                                                               | Boolean                                   | -                                                                                                     | -                  |
+| press-time             | `(v1.1.6 新增)`长按触发时间,单位毫秒 ms                                                                                                                                                                                                                                                                                                                                                                                                                                  | Number                                    | -                                                                                                     | 500                |
+| formatter              | `(v1.1.7 新增)`格式化自定义选择器文字内容,`Function`类型,`return`一个字符串(日期选择器`百度、支付宝、头条小程序`不支持,其他选择器仅`app` `nvue` `h5`支持),`item`当前项信息,`rowIndex`当前数据所在行数,`columnIndex`当前数据所在列数,写法参考[demo14](https://github.com/liub1934/uni-lb-picker/blob/master/pages/demos/demo14/demo14.vue#L206),日期选择器可参考[demo16](https://github.com/liub1934/uni-lb-picker/blob/master/pages/demos/demo16/demo16.vue#L245) | Function({ item, rowIndex, columnIndex }) | -                                                                                                     |
+
+#### 单选、多级联动、非联动选择 Props
+
+| 参数  | 说明                                                                  | 类型   | 可选值 | 默认值                                            |
+| :---- | :-------------------------------------------------------------------- | :----- | :----- | :------------------------------------------------ |
+| list  | 选择器数据(v1.0.7 单选及非联动多选支持扁平数据:['选项 1', '选项 2']) | Array  | -      | -                                                 |
+| level | 多列联动层级,仅 mode 为 multiSelector 有效                           | Number | -      | 1                                                 |
+| props | 自定义数据字段                                                        | Object | -      | {label:'label',value:'value',children:'children'} |
+
+#### 日期选择 Props
+
+| 参数               | 说明                                                                                                                                                                                                                | 类型    | 可选值     | 默认值                                                                       |
+| :----------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :------ | :--------- | :--------------------------------------------------------------------------- |
+| display-format     | 日期选择显示的颗粒格式,见下方`displayFormat、format说明`,可自由组合,如`YYYY-MM-DD`,显示的就是选择`年月日`。`重要说明:始终是以-为分隔符,始终是以-为分隔符, 始终是以-为分隔符`                                 | String  | -          | YYYY-MM-DD                                                                   |
+| format             | 选择器返回的日期格式,见下方`displayFormat、format说明`,如配置`YYYY年MM月DD日`选择器确定后返回显示的值为`2021年01月05号`或者`YYYY-MM-DD`返回的就是`2021-01-05`,可以自由组合,需要和`display-format`参数配合使用。 | String  | -          | YYYY-MM-DD                                                                   |
+| start-date         | 开始日期,可精确到秒,如`2018-08-08 08:08:08`                                                                                                                                                                       | String  | -          | -                                                                            |
+| end-date           | 结束日期,可精确到秒,如`2021-08-08 08:08:08`                                                                                                                                                                       | String  | -          | -                                                                            |
+| default-time-limit | 默认显示的日期选择范围,默认当前日期前 20 年和后 20 年,配置`start-date`或`end-date`后失效                                                                                                                          | Number  | -          | 20                                                                           |
+| is-show-chinese    | 是否显示日期选择器年月日时分秒中文文字,默认显示                                                                                                                                                                    | Boolean | true/false | true                                                                         |
+| ch-config          | 显示的日期选择器年月日时分秒文字配置                                                                                                                                                                                | Object  | -          | {year: '年', month: '月', day: '日', hour: '时', minute: '分', second: '秒'} |
+
+### displayFormat、format 说明
+
+| 标识 | 示例  | 描述            |
+| :--- | :---- | :-------------- |
+| YY   | 18    | 年,两位数      |
+| YYYY | 2018  | 年,四位数      |
+| M    | 1-12  | 月,从 1 开始   |
+| MM   | 01-12 | 月,两位数字    |
+| D    | 1-31  | 日              |
+| DD   | 01-31 | 日,两位数      |
+| H    | 0-23  | 24 小时         |
+| HH   | 00-23 | 24 小时,两位数 |
+| h    | 1-12  | 12 小时         |
+| hh   | 01-12 | 12 小时,两位数 |
+| m    | 0-59  | 分钟            |
+| mm   | 00-59 | 分钟,两位数    |
+| s    | 0-59  | 秒              |
+| ss   | 00-59 | 秒,两位数      |
+
+### 方法
+
+| 方法名         | 说明                                   | 参数            | 返回值                                                                                                       |
+| :------------- | :------------------------------------- | :-------------- | :----------------------------------------------------------------------------------------------------------- |
+| show           | 打开选择器                             | -               |                                                                                                              |
+| hide           | 关闭选择器                             | -               |                                                                                                              |
+| getColumnsInfo | (v1.1.0 新增)根据 value 获取选择器信息 | 绑定值的`value` | 同`change` `confirm`回调参数,如果传入的`value`获取不到信息则只返回一个含有`dataset`的对象,具体自行打印查看 |
+
+`getColumnsInfo`注意事项:
+
+- 需要组件加载完成后调用才有效,即`console.log(this.$refs.picker)`打印有内容,否则会报错,可在`onReady`中进行调用。
+- 如果动态设置`list`后马上调用`getColumnsInfo`会无法取到相关信息,可以加个`setTimeout`解决,如下形式:
+
+```javascript
+onReady () {
+  this.list = [{ label: '测试', value: 1 }] // 动态设置一个list
+  setTimeout(() => {
+    const info = that.$refs.picker.getColumnsInfo(xx)
+    console.log(info)
+  }, 0)
+}
+```
+
+### Events
+
+| 事件名称 | 说明                                     | 回调参数                                                                                                                                                                                                                                                                                                                                                         |
+| :------- | :--------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| show     | 选择器打开时触发                         | -                                                                                                                                                                                                                                                                                                                                                                |
+| hide     | 选择器隐藏时触发                         | -                                                                                                                                                                                                                                                                                                                                                                |
+| change   | 选择器滚动时触发,此时不会改变绑定的值   | `{ index, item, value, change }` `index`触发滚动后新的索引,单选时是具体的索引值,多列联动选择时为数组。`item`触发滚动后新的的完整内容,包括`label`、`value`等,日期选择器则为日期相关内容,单选时为对象,多列选择时为数组对象。`value`触发滚动后新的 value 值,单列选择时为具体值,多列联动选择时为数组。`change`触发事件的类型,详情参考下面的 change 事件备注 |
+| confirm  | 点击选择器确定时触发,此时会改变绑定的值 | 同上`change`事件说明                                                                                                                                                                                                                                                                                                                                             |
+| cancel   | 点击选择器取消时触发                     | 同上`change`事件说明                                                                                                                                                                                                                                                                                                                                             |
+
+### `change` 事件备注
+
+如果绑定的值是空的,`change`触发后里面的内容都是列表的第一项。  
+`change`事件会在以下情况触发:
+
+- 初始化
+- 绑定值 value 变化
+- 选择器 list 列表变化
+- 滚动选择器
+
+以上情况会在回调函数中都可以取到`change`变化的类型,对应上面的情况包括以下:
+
+- `init`
+- `value`
+- `list`
+- `scroll`
+
+根据这些类型大家可以在`change`的时候按需处理自己的业务逻辑,`init`现在指挥在调用选择器弹出的时候触发。  
+下面的说明情况已失效,如需要在页面显示的时候根据`value`的值显示相应的中文,调用`v1.10`新增的方法`getColumnsInfo`,传入绑定的值即可获取到你想要的所有信息。  
+~~比如一种常见的情况,有默认值的时候需要显示默认值的文字,此时可以`change`事件中判断`change`的类型是否是`init`,如果是的话可以取事件回调中的`item`进行显示绑定值对应的文字信息。~~
+
+```javascript
+handleChange (e) {
+  if (e.change === 'init') {
+    console.log(e.item.label) // 单选 选项1
+    console.log(e.item.map(item => item.label).join('-')) // 多选 选项1-选项11
+  }
+}
+```
+
+### 插槽
+
+| 插槽名        | 说明                   |
+| :------------ | :--------------------- |
+| cancel-text   | 选择器取消文字插槽     |
+| action-center | 选择器顶部中间插槽     |
+| confirm-text  | 选择器确定文字插槽     |
+| loading       | 选择器 loading 插槽    |
+| empty         | 选择器 空数据 插槽     |
+| header-top    | 选择器头部顶部插槽     |
+| header-bottom | 选择器头部底部插槽     |
+| picker-top    | 选择器滚动部分顶部插槽 |
+| picker-bottom | 选择器滚动部分底部插槽 |
+
+### 选择器自定义样式
+
+> nvue 专属写法,需要定义`column-style`和`active-column-style`,写法如下:
+
+```html
+<lb-picker
+  :column-style="columnStyle"
+  :active-column-style="activeColumnStyle"
+></lb-picker>
+```
+
+```javascript
+data () {
+  return {
+    // 默认样式
+    columnStyle: {
+      color: '#f0ad4e'
+    },
+    // 选择样式
+    activeColumnStyle: {
+      color: '#007aff',
+      fontWeight: 700
+    }
+  }
+}
+```
+
+> 其他端写法,覆盖默认样式即可。
+
+```css
+<style lang="scss" scoped>
+/deep/ .lb-picker {
+  .lb-picker-column-label {
+    color: #f0ad4e;
+  }
+  .lb-picker-column-active {
+    .lb-picker-column-label {
+      color: #007aff;
+      font-weight: 700;
+    }
+  }
+}
+</style>
+```
+
+完整代码可以参考`demo9`。
+
+### 获取选中值的文字
+
+`@confirm`事件中可以拿到:
+
+单选:
+
+```javascript
+handleConfirm (e) {
+  console.log(e.item.label) // 选项1
+}
+```
+
+联动选择:
+
+```javascript
+handleConfirm (e) {
+  console.log(e.item.map(item => item.label).join('-')) // 选项1-选项11
+}
+```
+
+## Tips
+
+微信小程序端,滚动时在 iOS 自带振动反馈,可在系统设置 -> 声音与触感 -> 系统触感反馈中关闭
+
+## 其他
+
+其他功能参考示例 Demo 代码。

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 87 - 0
components/lb-picker/index.vue


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 0 - 0
components/lb-picker/lib/custom-parse-format.min.js


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 0 - 0
components/lb-picker/lib/dayjs.min.js


+ 1 - 0
components/lb-picker/lib/object-support.min.js

@@ -0,0 +1 @@
+!function(t,n){"object"==typeof exports&&"undefined"!=typeof module?module.exports=n():"function"==typeof define&&define.amd?define(n):t.dayjs_plugin_objectSupport=n()}(this,function(){"use strict";return function(t,n,e){var i=n.prototype,r=function(t){var n,r=t.date,o=t.utc,a={};if(!((n=r)instanceof Date)&&!(n instanceof Array)&&n instanceof Object){if(!Object.keys(r).length)return new Date;var u=o?e.utc():e();Object.keys(r).forEach(function(t){var n,e;a[(n=t,e=i.$utils().p(n),"date"===e?"day":e)]=r[t]});var c=a.day||(a.year||a.month>=0?1:u.date()),d=a.year||u.year(),f=a.month>=0?a.month:a.year||a.day?0:u.month(),s=a.hour||0,h=a.minute||0,b=a.second||0,y=a.millisecond||0;return o?new Date(Date.UTC(d,f,c,s,h,b,y)):new Date(d,f,c,s,h,b,y)}return r},o=i.parse;i.parse=function(t){t.date=r.bind(this)(t),o.bind(this)(t)};var a=i.set,u=i.add,c=function(t,n,e,i){if(void 0===i&&(i=1),n instanceof Object){var r=this;return Object.keys(n).forEach(function(e){r=t.bind(r)(n[e]*i,e)}),r}return t.bind(this)(n*i,e)};i.set=function(t,n){return n=void 0===n?t:n,c.bind(this)(function(t,n){return a.bind(this)(n,t)},n,t)},i.add=function(t,n){return c.bind(this)(u,t,n)},i.subtract=function(t,n){return c.bind(this)(u,t,n,-1)}}});

+ 93 - 0
components/lb-picker/mixins/index.js

@@ -0,0 +1,93 @@
+import { getColumns, isObject, isFunction } from '../utils'
+export const commonMixin = {
+  data () {
+    return {
+      isConfirmChange: false,
+      indicatorStyle: `height: 34px`,
+      pressTimeout: null
+    }
+  },
+  created () {
+    this.init('init')
+  },
+  methods: {
+    init (changeType) {
+      if (this.list && this.list.length) {
+        const column = getColumns({
+          value: this.value,
+          list: this.list,
+          mode: this.mode,
+          props: this.props,
+          level: this.level
+        })
+        const { columns, value, item, index } = column
+        this.selectValue = value
+        this.selectItem = item
+        this.pickerColumns = columns
+        this.pickerValue = index
+        this.$emit('change', {
+          value: this.selectValue,
+          item: this.selectItem,
+          index: this.pickerValue,
+          change: changeType
+        })
+      }
+    },
+    touchstart (e) {
+      if (!this.pressEnable) return
+      clearTimeout(this.pressTimeout)
+      this.pressTimeout = setTimeout(() => {
+        let item = {}
+        let toastTitle = ''
+        // #ifdef APP-NVUE
+        item = e.target.dataset.item
+        // #endif
+
+        // #ifdef H5
+        item = JSON.parse(e.currentTarget.dataset.item)
+        // #endif
+
+        // #ifndef APP-NVUE || H5
+        item = e.currentTarget.dataset.item
+        // #endif
+
+        // #ifdef APP-PLUS || H5
+        toastTitle = this.getLabel(item)
+        // #endif
+
+        // #ifndef APP-PLUS || H5
+        toastTitle = item[this.props.label] || item
+        // #endif
+        uni.showToast({
+          title: toastTitle,
+          icon: 'none'
+        })
+      }, this.pressTime)
+    },
+    touchmove () {
+      if (!this.pressEnable) return
+      clearTimeout(this.pressTimeout)
+    },
+    touchend () {
+      if (!this.pressEnable) return
+      clearTimeout(this.pressTimeout)
+    },
+    getLabel (item, rowIndex, columnIndex) {
+      if (this.formatter && isFunction(this.formatter)) {
+        return this.formatter({ item, rowIndex, columnIndex })
+      } else {
+        return item[this.props.label] || item
+      }
+    }
+  },
+  watch: {
+    value () {
+      if (!this.isConfirmChange) {
+        this.init('value')
+      }
+    },
+    list () {
+      this.init('list')
+    }
+  }
+}

+ 378 - 0
components/lb-picker/pickers/date-selector-picker.vue

@@ -0,0 +1,378 @@
+<template>
+  <view class="lb-selector-picker lb-picker-item"
+    :style="{ height: height }">
+    <picker-view :value="pickerValue"
+      :style="{ height: height }"
+      :indicator-style="indicatorStyle"
+      @change="handleChange">
+      <picker-view-column v-for="(column, index) in pickerColumns"
+        :key="column.name">
+        <view v-for="item in column.list || []"
+          :class="[
+            'lb-picker-column',
+            item.value === selectValue[index]
+              ? 'lb-picker-column-active'
+              : ''
+          ]"
+          :key="item.value">
+          <!-- #ifdef APP-PLUS || H5 -->
+          <text :class="[
+              'lb-picker-column-label',
+              `lb-picker-column-label-${align}`
+            ]"
+            :style="[
+              item.value === selectValue[index]
+                ? activeColumnStyle
+                : columnStyle
+            ]">{{ item.label }}</text>
+          <!-- #endif -->
+
+          <!-- #ifndef APP-PLUS || H5 -->
+          <text :class="[
+              'lb-picker-column-label',
+              `lb-picker-column-label-${align}`
+            ]">{{ item.label }}</text>
+          <!-- #endif -->
+        </view>
+      </picker-view-column>
+    </picker-view>
+  </view>
+</template>
+
+<script>
+import { isFunction } from '../utils'
+const INVALID_DATE = 'Invalid Date'
+const dayjs = require('../lib/dayjs.min.js')
+const objectSupport = require('../lib/object-support.min.js')
+const customParseFormat = require('../lib/custom-parse-format.min.js')
+dayjs.extend(objectSupport)
+dayjs.extend(customParseFormat)
+export default {
+  props: {
+    value: String,
+    mode: String,
+    visible: Boolean,
+    height: String,
+    columnStyle: Object,
+    activeColumnStyle: Object,
+    align: String,
+    formatter: Function,
+    format: String,
+    displayFormat: String,
+    startDate: String,
+    endDate: String,
+    defaultTimeLimit: Number,
+    isShowChinese: Boolean,
+    chConfig: Object,
+    filter: Function
+  },
+  data () {
+    return {
+      pickerValue: [],
+      pickerColumns: [],
+      selectValue: [],
+      selectItem: null,
+      isConfirmChange: false,
+      indicatorStyle: `height: 34px`,
+      dayjs: dayjs,
+      startInfo: {},
+      endInfo: {}
+    }
+  },
+  created () {
+    this.init('init')
+  },
+  methods: {
+    init (changeType) {
+      this.startInfo = this.toObject(
+        this.startDate
+          ? this.startDate
+          : this.dayjs().subtract(this.defaultTimeLimit, 'year').$d
+      )
+      this.endInfo = this.toObject(
+        this.endDate
+          ? this.endDate
+          : this.dayjs().add(this.defaultTimeLimit, 'year').$d
+      )
+      this.selectDate = this.value
+        ? this.dayjs(this.value, this.format)
+        : new Date()
+      if (!this.validate('date')) {
+        throw new Error('日期格式不合法')
+      }
+      if (!this.validate('displayFormat')) {
+        throw new Error('display-format参数异常')
+      }
+      if (this.startInfo.timestamp > this.endInfo.timestamp) {
+        throw new Error('开始结束日期异常,startDate不得大于endDate')
+      }
+      this.selectItem = this.toObject(this.selectDate)
+      this.setColumnData()
+      const value = this.getValueDate()
+      this.$emit('change', {
+        value: value.format(this.format),
+        valueArr: this.selectValue,
+        item: this.selectItem,
+        index: this.pickerValue,
+        change: changeType
+      })
+    },
+    handleChange (item) {
+      const pickerValue = item.detail.value
+      const columnIndex = pickerValue.findIndex(
+        (item, i) => item !== this.pickerValue[i]
+      )
+      if (columnIndex > -1) {
+        const valueIndex = pickerValue[columnIndex]
+        const columnItem = this.pickerColumns[columnIndex]
+        const columnName = columnItem.name
+        const valueItem = columnItem.list[valueIndex]
+        this.pickerValue = pickerValue
+        this.$set(this.selectValue, columnIndex, valueItem.value)
+        this.$set(this.selectItem, columnName, valueItem.value)
+        this.setColumnData(columnIndex)
+        const value = this.getValueDate()
+        this.$emit('change', {
+          value: value.format(this.format),
+          valueArr: this.selectValue,
+          item: this.selectItem,
+          index: this.pickerValue,
+          change: 'scroll'
+        })
+      }
+    },
+    getLabel (value, name, format, $d, rowIndex, columnIndex) {
+      const ch = this.isShowChinese ? this.chConfig[name] || '' : ''
+      let label =
+        value < 10 && format.length > 1 ? `0${value}${ch}` : value + ch
+      if (this.formatter && isFunction(this.formatter)) {
+        const item = { name, format, value, $d }
+        label = this.formatter({ item, rowIndex, columnIndex }) || label
+      }
+      return label
+    },
+    getValueDate (dateObj = {}) {
+      let selectItem = {
+        ...this.selectItem,
+        ...dateObj
+      }
+      selectItem.month = selectItem.month - 1
+      return this.dayjs(selectItem)
+    },
+    setColumnData (n = 0) {
+      const formatArr = this.displayFormat.split('-')
+      const formatObj = {
+        YY: 'year',
+        YYYY: 'year',
+        M: 'month',
+        MM: 'month',
+        D: 'day',
+        DD: 'day',
+        h: 'hour',
+        HH: 'hour',
+        h: 'hour',
+        hh: 'hour',
+        m: 'minute',
+        mm: 'minute',
+        s: 'second',
+        ss: 'second'
+      }
+      formatArr.forEach((item, index) => {
+        if (index >= n) {
+          const name = formatObj[item]
+          const obj = {
+            name: name,
+            list: this.getColumnData(name, item, index)
+          }
+          let value = this.selectItem[name]
+          if (index !== n) {
+            this.$set(this.pickerColumns, index, obj)
+          }
+          let n = obj.list.findIndex(l => l.value === value)
+          if (n < 0) {
+            const l = obj.list.length - 1
+            const firstValue = obj.list[0].value
+            const lastValue = obj.list[l].value
+            if (value < firstValue) {
+              n = 0
+              value = firstValue
+            }
+            if (value > lastValue) {
+              n = l
+              value = lastValue
+            }
+            if (n < 0) {
+              n = 0
+              value = firstValue
+            }
+          }
+          this.$set(this.pickerValue, index, n)
+          this.$set(this.selectValue, index, value)
+          this.$set(this.selectItem, name, value)
+        }
+      })
+    },
+    isSame (name, type = 'startInfo') {
+      let same = true
+      const arr = ['year', 'month', 'day', 'hour', 'minute', 'second']
+      const index = arr.findIndex(item => item === name)
+      if (index > -1) {
+        const slice = arr.slice(0, index + 1)
+        for (let i = 0; i < slice.length; i++) {
+          same = same && this.selectItem[slice[i]] === this[type][slice[i]]
+        }
+      }
+      return same
+    },
+    getColumnData (name, format, index) {
+      let list = []
+      let start = 0
+      let end = 0
+      let n = 0
+      const obj = {
+        month: 'year',
+        day: 'month',
+        hour: 'day',
+        minute: 'hour',
+        second: 'minute'
+      }
+      switch (name) {
+        case 'year':
+          start = this.startInfo[name]
+          end = this.endInfo[name]
+          break
+        case 'month':
+          start = 1
+          end = 12
+          break
+        case 'day':
+          start = 1
+          end = new Date(
+            this.selectItem.year,
+            this.selectItem.month,
+            0
+          ).getDate()
+          break
+        case 'hour':
+          start = 0
+          end = 23
+          break
+        case 'minute':
+          start = 0
+          end = 59
+          break
+        case 'second':
+          start = 0
+          end = 59
+          break
+      }
+      if (this.isSame(obj[name], 'startInfo')) {
+        start = this.startInfo[name]
+      }
+      if (this.isSame(obj[name], 'endInfo')) {
+        end = this.endInfo[name]
+      }
+      for (let i = start; i <= end; i++) {
+        n++
+        list.push({
+          label: this.getLabel(
+            i,
+            name,
+            format,
+            this.getValueDate({ [name]: i }),
+            n,
+            index
+          ),
+          value: i
+        })
+      }
+      if (this.filter && isFunction(this.filter)) {
+        list = this.filter(name, list) || list
+      }
+      return list
+    },
+    validate (type) {
+      let valid = true
+      switch (type) {
+        case 'date':
+          valid = this.dayjs(this.selectDate).isValid()
+          break
+        case 'displayFormat':
+          if (this[type]) {
+            const arr = [
+              'YY',
+              'YYYY',
+              'M',
+              'MM',
+              'D',
+              'DD',
+              'H',
+              'HH',
+              'h',
+              'hh',
+              'm',
+              'mm',
+              's',
+              'ss'
+            ]
+            const formatArr = this.displayFormat.split('-')
+            for (let i = 0; i < formatArr.length; i++) {
+              const val = formatArr[i]
+              const isIn = arr.includes(val)
+              if (!isIn) {
+                valid = false
+                break
+              }
+            }
+          } else {
+            valid = false
+          }
+          break
+      }
+      return valid
+    },
+    toObject (val) {
+      const d = this.dayjs(val)
+      return {
+        year: d.$y,
+        month: d.$M + 1,
+        day: d.$D,
+        hour: d.$H,
+        minute: d.$m,
+        second: d.$s,
+        timestamp: d.valueOf(),
+        $d: d
+      }
+    }
+  },
+  watch: {
+    value () {
+      if (!this.isConfirmChange) {
+        this.init('value')
+      }
+    },
+    displayFormat () {
+      this.init('displayFormat')
+    },
+    startDate () {
+      this.init('startDate')
+    },
+    endDate () {
+      this.init('endDate')
+    },
+    defaultTimeLimit () {
+      this.init('defaultTimeLimit')
+    },
+    isShowChinese () {
+      this.init('isShowChinese')
+    },
+    chConfig () {
+      this.init('chConfig')
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+@import "../style/picker-item.scss";
+</style>

+ 135 - 0
components/lb-picker/pickers/multi-selector-picker.vue

@@ -0,0 +1,135 @@
+<template>
+  <view class="lb-multi-selector lb-picker-item"
+    :style="{ height: height }">
+    <picker-view :value="pickerValue"
+      :indicator-style="indicatorStyle"
+      :style="{ height: height }"
+      @change="handleChange">
+      <picker-view-column v-for="(column, index) in pickerColumns"
+        :key="index">
+        <!-- #ifdef H5 -->
+        <view v-for="(item, i) in column || []"
+          :class="[
+            'lb-picker-column',
+            item[props.value] === selectValue[index]
+              ? 'lb-picker-column-active'
+              : ''
+          ]"
+          :key="i"
+          :data-item="pressEnable ? JSON.stringify(item) : ''"
+          @touchstart="touchstart"
+          @touchmove="touchmove"
+          @touchend="touchend">
+          <!-- #endif -->
+          <!-- #ifndef H5 -->
+          <view v-for="(item, i) in column || []"
+            :class="[
+            'lb-picker-column',
+            item[props.value] === selectValue[index]
+              ? 'lb-picker-column-active'
+              : ''
+          ]"
+            :key="i"
+            :data-item="item"
+            @touchstart="touchstart"
+            @touchmove="touchmove"
+            @touchend="touchend">
+            <!-- #endif -->
+            <!-- #ifdef APP-PLUS || H5 -->
+            <text :class="[
+              'lb-picker-column-label',
+              `lb-picker-column-label-${align}`
+            ]"
+              :style="[
+              item[props.value] === selectValue[index]
+              ? activeColumnStyle
+              : columnStyle
+            ]">{{ getLabel(item, i, index) }}</text>
+            <!-- #endif -->
+
+            <!-- #ifndef APP-PLUS || H5 -->
+            <text :class="[
+              'lb-picker-column-label',
+              `lb-picker-column-label-${align}`
+            ]">{{ item[props.label] || item }}</text>
+            <!-- #endif -->
+          </view>
+      </picker-view-column>
+    </picker-view>
+  </view>
+</template>
+
+<script>
+import { commonMixin } from '../mixins'
+export default {
+  props: {
+    value: Array,
+    list: Array,
+    mode: String,
+    props: Object,
+    level: Number,
+    visible: Boolean,
+    height: String,
+    columnStyle: Object,
+    activeColumnStyle: Object,
+    align: String,
+    pressEnable: Boolean,
+    pressTime: Number,
+    formatter: Function
+  },
+  mixins: [commonMixin],
+  data () {
+    return {
+      pickerValue: [],
+      pickerColumns: [],
+      selectValue: [],
+      selectItem: []
+    }
+  },
+  methods: {
+    handleChange (item) {
+      const pickerValue = item.detail.value
+      const columnIndex = pickerValue.findIndex(
+        (item, i) => item !== this.pickerValue[i]
+      )
+      const valueIndex = pickerValue[columnIndex]
+      this.setPickerChange(pickerValue, valueIndex, columnIndex)
+    },
+    setPickerChange (pickerValue, valueIndex, columnIndex) {
+      for (let i = 0; i < this.level; i++) {
+        if (i > columnIndex) {
+          pickerValue[i] = 0
+          const column =
+            this.pickerColumns[i - 1][valueIndex] ||
+            this.pickerColumns[i - 1][0]
+          this.$set(this.pickerColumns, i, column[this.props.children] || [])
+          valueIndex = 0
+        }
+        this.$set(this.pickerValue, i, pickerValue[i])
+        const selectItem = this.pickerColumns[i][pickerValue[i]]
+        if (selectItem) {
+          this.selectItem[i] = selectItem
+          this.selectValue[i] = selectItem[this.props.value]
+        } else {
+          const spliceNum = this.level - i
+          this.pickerValue.splice(i, spliceNum)
+          this.selectValue.splice(i, spliceNum)
+          this.selectItem.splice(i, spliceNum)
+          this.pickerColumns.splice(i, spliceNum)
+          break
+        }
+      }
+      this.$emit('change', {
+        value: this.selectValue,
+        item: this.selectItem,
+        index: this.pickerValue,
+        change: 'scroll'
+      })
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+@import "../style/picker-item.scss";
+</style>

+ 108 - 0
components/lb-picker/pickers/selector-picker.vue

@@ -0,0 +1,108 @@
+<template>
+  <view class="lb-selector-picker lb-picker-item"
+    :style="{ height: height }">
+    <picker-view :value="pickerValue"
+      :style="{ height: height }"
+      :indicator-style="indicatorStyle"
+      @change="handleChange">
+      <picker-view-column>
+        <!-- #ifdef H5 -->
+        <view v-for="(item, i) in list"
+          :class="[
+            'lb-picker-column',
+            (item[props.value] || item) === selectValue
+              ? 'lb-picker-column-active'
+              : ''
+          ]"
+          :key="i"
+          :data-item="pressEnable ? JSON.stringify(item) : ''"
+          @touchstart="touchstart"
+          @touchmove="touchmove"
+          @touchend="touchend">
+          <!-- #endif -->
+          <!-- #ifndef H5 -->
+          <view v-for="(item, i) in list"
+            :class="[
+            'lb-picker-column',
+            (item[props.value] || item) === selectValue
+              ? 'lb-picker-column-active'
+              : ''
+          ]"
+            :key="i"
+            :data-item="item"
+            @touchstart="touchstart"
+            @touchmove="touchmove"
+            @touchend="touchend">
+            <!-- #endif -->
+            <!-- #ifdef APP-PLUS || H5 -->
+            <text :class="[
+              'lb-picker-column-label',
+              `lb-picker-column-label-${align}`
+            ]"
+              :style="[
+              (item[props.value] || item) === selectValue
+                ? activeColumnStyle
+                : columnStyle
+            ]">{{ getLabel(item.title, i, 0) }}</text>
+            <!-- #endif -->
+
+            <!-- #ifndef APP-PLUS || H5 -->
+            <text :class="[
+              'lb-picker-column-label',
+              `lb-picker-column-label-${align}`
+            ]">{{ item[props.label] || item }}</text>
+            <!-- #endif -->
+          </view>
+      </picker-view-column>
+    </picker-view>
+  </view>
+</template>
+
+<script>
+import { isObject } from '../utils'
+import { commonMixin } from '../mixins'
+export default {
+  props: {
+    value: [String, Number],
+    list: Array,
+    mode: String,
+    props: Object,
+    visible: Boolean,
+    height: String,
+    columnStyle: Object,
+    activeColumnStyle: Object,
+    align: String,
+    pressEnable: Boolean,
+    pressTime: Number,
+    formatter: Function
+  },
+  mixins: [commonMixin],
+  data () {
+    return {
+      pickerValue: [],
+      selectValue: '',
+      selectItem: null
+    }
+  },
+  methods: {
+    handleChange (item) {
+      const index = item.detail.value[0] || 0
+      this.selectItem = this.list[index]
+      this.selectValue = isObject(this.selectItem)
+        ? this.selectItem[this.props.value]
+        : this.selectItem
+      this.pickerValue = item.detail.value
+      this.$emit('change', {
+        value: this.selectValue,
+        item: this.selectItem,
+        index: index,
+        change: 'scroll'
+      })
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+@import "../style/picker-item.scss";
+</style>

+ 116 - 0
components/lb-picker/pickers/unlinked-selector-picker.vue

@@ -0,0 +1,116 @@
+<template>
+  <view class="lb-selector-picker lb-picker-item"
+    :style="{ height: height }">
+    <picker-view :value="pickerValue"
+      :indicator-style="indicatorStyle"
+      :style="{ height: height }"
+      @change="handleChange">
+      <picker-view-column v-for="(column, index) in pickerColumns"
+        :key="index">
+        <!-- #ifdef H5 -->
+        <view v-for="(item, i) in column || []"
+          :class="[
+            'lb-picker-column',
+            (item[props.value] || item) === selectValue[index]
+              ? 'lb-picker-column-active'
+              : ''
+          ]"
+          :key="i"
+          :data-item="pressEnable ? JSON.stringify(item) : ''"
+          @touchstart="touchstart"
+          @touchmove="touchmove"
+          @touchend="touchend">
+          <!-- #endif -->
+          <!-- #ifndef H5 -->
+          <view v-for="(item, i) in column || []"
+            :class="[
+            'lb-picker-column',
+            (item[props.value] || item) === selectValue[index]
+              ? 'lb-picker-column-active'
+              : ''
+          ]"
+            :key="i"
+            :data-item="item"
+            @touchstart="touchstart"
+            @touchmove="touchmove"
+            @touchend="touchend">
+            <!-- #endif -->
+            <!-- #ifdef APP-PLUS || H5 -->
+            <text :class="[
+              'lb-picker-column-label',
+              `lb-picker-column-label-${align}`
+            ]"
+              :style="[
+              (item[props.value] || item) === selectValue[index]
+              ? activeColumnStyle
+              : columnStyle
+            ]">{{ getLabel(item, i, index) }}</text>
+            <!-- #endif -->
+
+            <!-- #ifndef APP-PLUS || H5 -->
+            <text :class="[
+              'lb-picker-column-label',
+              `lb-picker-column-label-${align}`
+            ]">{{ item[props.label] || item }}</text>
+            <!-- #endif -->
+          </view>
+      </picker-view-column>
+    </picker-view>
+  </view>
+</template>
+
+<script>
+import { isObject } from '../utils'
+import { commonMixin } from '../mixins'
+export default {
+  props: {
+    value: Array,
+    list: Array,
+    mode: String,
+    props: Object,
+    visible: Boolean,
+    height: String,
+    columnStyle: Object,
+    activeColumnStyle: Object,
+    align: String,
+    pressEnable: Boolean,
+    pressTime: Number,
+    formatter: Function
+  },
+  mixins: [commonMixin],
+  data () {
+    return {
+      pickerValue: [],
+      pickerColumns: [],
+      selectValue: [],
+      selectItem: []
+    }
+  },
+  methods: {
+    handleChange (item) {
+      const pickerValue = item.detail.value
+      const columnIndex = pickerValue.findIndex((item, i) => item !== this.pickerValue[i])
+      if (columnIndex > -1) {
+        const valueIndex = pickerValue[columnIndex]
+        const columnItem = this.list[columnIndex][valueIndex]
+        const valueItem = isObject(columnItem)
+          ? columnItem[this.props.value]
+          : columnItem
+        this.pickerValue = pickerValue
+        this.$set(this.selectValue, columnIndex, valueItem)
+        this.$set(this.selectItem, columnIndex, columnItem)
+        this.$emit('change', {
+          value: this.selectValue,
+          item: this.selectItem,
+          index: this.pickerValue,
+          change: 'scroll'
+        })
+      }
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+@import "../style/picker-item.scss";
+</style>

+ 40 - 0
components/lb-picker/style/picker-item.scss

@@ -0,0 +1,40 @@
+.lb-picker-column {
+  height: 34px;
+  padding: 0 10px;
+  /* #ifndef APP-NVUE */
+  display: flex;
+  box-sizing: border-box;
+  white-space: nowrap;
+  overflow: hidden;
+  /* #endif */
+  flex-direction: row;
+  align-items: center;
+}
+
+.lb-picker-column-label {
+  font-size: 16px;
+  text-align: center;
+  flex: 1;
+  /* #ifdef APP-NVUE */
+  lines: 1;
+  /* #endif */
+  text-overflow: ellipsis;
+  transition-property: color;
+  transition-duration: 0.3s;
+  /* #ifndef APP-NVUE */
+  overflow: hidden;
+  white-space: nowrap;
+  /* #endif */
+}
+
+.lb-picker-column-label-left {
+  text-align: left;
+}
+
+.lb-picker-column-label-center {
+  text-align: center;
+}
+
+.lb-picker-column-label-right {
+  text-align: right;
+}

+ 166 - 0
components/lb-picker/style/picker.scss

@@ -0,0 +1,166 @@
+.lb-picker {
+	position: relative;
+}
+
+.lb-picker-mask {
+	background-color: rgba(0, 0, 0, 0.0);
+	position: fixed;
+	top: 0;
+	right: 0;
+	left: 0;
+	bottom: 0;
+}
+
+.lb-picker-mask-animation {
+	transition-property: background-color;
+	transition-duration: 0.3s;
+}
+
+.lb-picker-container {
+	position: relative;
+}
+
+.lb-picker-container-fixed {
+	position: fixed;
+	left: 0;
+	right: 0;
+	bottom: 0;
+	transform: translateY(100%);
+	/* #ifndef APP-NVUE */
+	overflow: hidden;
+	/* #endif */
+}
+
+/* #ifndef APP-NVUE */
+.lb-picker-container-animation {
+	transition-property: transform;
+	transition-duration: 0.3s;
+}
+
+.lb-picker-container-show {
+	transform: translateY(0);
+}
+
+/* #endif */
+
+.lb-picker-header {
+	position: relative;
+	background-color: #fff;
+	/* #ifdef APP-NVUE */
+	border-bottom-width: 1px;
+	border-bottom-style: solid;
+	border-bottom-color: #e5e5e5;
+	border-top-width: 1px;
+	border-top-style: solid;
+	border-top-color: #e5e5e5;
+	/* #endif */
+	/* #ifndef APP-NVUE */
+	box-sizing: border-box;
+	/* #endif */
+
+}
+
+/* #ifndef APP-NVUE */
+
+.lb-picker-header::after {
+	content: "";
+	position: absolute;
+	left: 0;
+	bottom: 0;
+	right: 0;
+	height: 1px;
+	clear: both;
+	border-bottom: 1px solid #e5e5e5;
+	color: #e5e5e5;
+	transform-origin: 0 100%;
+	transform: scaleY(0.5);
+}
+
+/* #endif */
+
+.lb-picker-header-actions {
+	height: 45px;
+	/* #ifndef APP-NVUE */
+	box-sizing: border-box;
+	display: flex;
+	/* #endif */
+	flex-direction: row;
+	justify-content: space-between;
+	flex-wrap: nowrap;
+}
+
+.lb-picker-action {
+	padding-left: 10px;
+	padding-right: 10px;
+	/* #ifndef APP-NVUE */
+	display: flex;
+	/* #endif */
+	flex-direction: row;
+	align-items: center;
+	justify-content: center;
+}
+
+.lb-picker-action-cancel-text {
+	font-size: 16px;
+}
+
+.lb-picker-action-confirm-text {
+	font-size: 16px;
+}
+
+.lb-picker-content {
+	position: relative;
+	background-color: #fff;
+}
+
+/* #ifndef APP-NVUE */
+.lb-picker-content-safe-buttom {
+	padding-bottom: 0;
+	padding-bottom: constant(safe-area-inset-bottom);
+	padding-bottom: env(safe-area-inset-bottom);
+}
+
+/* #endif */
+
+.lb-picker-content-main {
+	position: relative;
+	/* #ifndef APP-NVUE */
+	display: flex;
+	/* #endif */
+	justify-content: center;
+	flex-direction: column;
+}
+
+.lb-picker-loading,
+.lb-picker-empty {
+	/* #ifndef APP-NVUE */
+	display: flex;
+	/* #endif */
+	justify-content: center;
+	align-items: center;
+}
+
+.lb-picker-empty-text {
+	font-size: 16px;
+}
+
+.lb-picker-loading-img {
+	width: 25px;
+	height: 25px;
+	/* #ifndef APP-NVUE */
+	animation: rotating 2s linear infinite;
+	/* #endif */
+}
+
+/* #ifndef APP-NVUE */
+@keyframes rotating {
+	0% {
+		transform: rotate(0deg)
+	}
+
+	100% {
+		transform: rotate(1turn)
+	}
+}
+
+/* #endif */

+ 121 - 0
components/lb-picker/utils.js

@@ -0,0 +1,121 @@
+/**
+ * 判断是否是对象
+ *
+ * @export
+ * @param {*} val
+ * @returns true/false
+ */
+export function isObject (val) {
+  return Object.prototype.toString.call(val) === '[object Object]'
+}
+
+/**
+ * 判断是否是Function
+ *
+ * @export
+ * @param {*} val
+ * @returns true/false
+ */
+export function isFunction (val) {
+  return Object.prototype.toString.call(val) === '[object Function]'
+}
+
+/**
+ * 根据value获取columns信息
+ *
+ * @export
+ * @param {*} { value, list, mode, props, level }
+ * @param {number} [type=2] 查询不到value数据返回数据类型 1空值null 2默认第一个选项
+ * @returns
+ */
+export function getColumns ({ value, list, mode, props, level }, type = 2) {
+  let pickerValue = []
+  let pickerColumns = []
+  let selectValue = []
+  let selectItem = []
+  let columnsInfo = null
+  switch (mode) {
+    case 'selector':
+      let index = list.findIndex(item => {
+        return isObject(item) ? item[props.value] === value : item === value
+      })
+      if (index === -1 && type === 1) {
+        columnsInfo = null
+      } else {
+        index = index > -1 ? index : 0
+        selectItem = list[index]
+        selectValue = isObject(selectItem)
+          ? selectItem[props.value]
+          : selectItem
+        pickerColumns = list
+        pickerValue = [index]
+        columnsInfo = {
+          index: pickerValue,
+          value: selectValue,
+          item: selectItem,
+          columns: pickerColumns
+        }
+      }
+      break
+    case 'multiSelector':
+      const setPickerItems = (data = [], index = 0) => {
+        if (!data.length) return
+        const defaultValue = value || []
+        if (index < level) {
+          const value = defaultValue[index] || ''
+          let i = data.findIndex(item => item[props.value] === value)
+          if (i === -1 && type === 1) return
+          i = i > -1 ? i : 0
+          pickerValue[index] = i
+          pickerColumns[index] = data
+          if (data[i]) {
+            selectValue[index] = data[i][props.value]
+            selectItem[index] = data[i]
+            setPickerItems(data[i][props.children] || [], index + 1)
+          }
+        }
+      }
+      setPickerItems(list)
+      if (!selectValue.length && type === 1) {
+        columnsInfo = null
+      } else {
+        columnsInfo = {
+          index: pickerValue,
+          value: selectValue,
+          item: selectItem,
+          columns: pickerColumns
+        }
+      }
+      break
+    case 'unlinkedSelector':
+      list.forEach((item, i) => {
+        let index = item.findIndex(item => {
+          return isObject(item)
+            ? item[props.value] === value[i]
+            : item === value[i]
+        })
+        if (index === -1 && type === 1) return
+        index = index > -1 ? index : 0
+        const columnItem = list[i][index]
+        const valueItem = isObject(columnItem)
+          ? columnItem[props.value]
+          : columnItem
+        pickerValue[i] = index
+        selectValue[i] = valueItem
+        selectItem[i] = columnItem
+      })
+      pickerColumns = list
+      if (!selectValue.length && type === 1) {
+        columnsInfo = null
+      } else {
+        columnsInfo = {
+          index: pickerValue,
+          value: selectValue,
+          item: selectItem,
+          columns: pickerColumns
+        }
+      }
+      break
+  }
+  return columnsInfo
+}

+ 216 - 0
components/select.vue

@@ -0,0 +1,216 @@
+<template>
+	<view class="easy-select" @click.stop="trigger" :style="[easySelectSize]">
+		<input type="text" v-model="value" :placeholder="placeholder" disabled clearable>
+		<!-- <view class="easy-select-suffix" :style="{border: '1px solid rgba(0,0,0,0)'}" :class="[showSuffix]">
+			<view class="easy-select-down-tag"></view>
+		</view> -->
+		<view class="easy-select-options" v-if="showOptions" :style="{'min-width': boundingClientRect.width + 'px', top: optionsGroupTop, margin: optionsGroupMargin}">
+			<view class="easy-select-options-item" v-for="item in options" :key="item.code" @click.stop="select(item)" :class="{active: currentSelect.name === item.name}">
+				<text>{{item.name}}</text>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	/**
+	 * easy-select
+	 * @author Snoop zhang
+	 * @description Select Component
+	 * */
+	const COMPONENT_NAME = 'easy-select'
+	const MAX_OPTIONS_HEIGHT = 137 // 修改务必也修改easy-select-options的css部分
+	const OPTIONS_ITEM_HEIGHT = 33 // 修改务必也修改easy-select-options-item的css部分
+	const OPTIONS_MARGIN = 10
+	const OPTIONS_PADDING = 6 * 2 + 2 // + 2是border
+	const OPTIONS_OTHER_HEIGHT = OPTIONS_MARGIN + OPTIONS_PADDING
+	const STORAGE_KEY = '_easyWindowHeight'
+	const SIZE = {
+		'medium': {
+			width: '150px',
+			height: '40px'
+		},
+		'small': {
+			width: '200px',
+			height: '30px'
+		},
+		'mini': {
+			width: '160px',
+			height: '30px'
+		}
+	}
+	
+	export default {
+		name: COMPONENT_NAME,
+		props: {
+			windowHeight: {
+				type: [Number, String],
+				default: 0
+			},
+			placeholder: {
+				type: String,
+				default: '选择币种'
+			},
+			value: {
+				type: String,
+				default: '双皮奶'
+			},
+			size: {
+				type: String,
+				default: 'medium'
+			},
+			options: {
+				type: Array,
+				default () {
+					return []
+				}
+			}
+		},
+		data() {
+			return {
+				showOptions: false,
+				boundingClientRect: {},
+				currentSelect: {},
+				optionsGroupTop: 'auto',
+				optionsGroupMargin: ''
+			}
+		},
+		computed: {
+			showSuffix() {
+				return this.showOptions ? 'showOptions' : 'no-showOptions'
+			},
+			easySelectSize() {
+				let size = this.size.toLowerCase()
+				if (size in SIZE) {
+					return {
+						width: SIZE[size].width,
+						height: SIZE[size].height
+					}
+				} else {
+					return {}
+				}
+			}
+		},
+		mounted() {
+			const elQuery = uni.createSelectorQuery().in(this)
+			elQuery.select('.easy-select').boundingClientRect(data => {
+				this.boundingClientRect = data
+			}).exec();
+			try {
+				if (!this.windowHeight) {
+					const storageHeihgt = uni.getStorageSync(STORAGE_KEY)
+					if (storageHeihgt) {
+						this.easyWindowHeight = storageHeihgt
+						return
+					}
+					const res = uni.getSystemInfoSync();
+					this.easyWindowHeight = res.windowHeight
+					uni.setStorageSync(STORAGE_KEY, this.easyWindowHeight)
+				}
+			} catch (e) {
+			    // error
+			}
+		},
+		methods: {
+			trigger(e) {
+				const view = uni.createSelectorQuery().in(this)
+				view.select('.easy-select').fields({rect: true}, data => {
+					let {	top, bottom } = data
+					const thresholdHeight = Math.min(MAX_OPTIONS_HEIGHT + OPTIONS_MARGIN, (this.options.length * OPTIONS_ITEM_HEIGHT) +
+						OPTIONS_OTHER_HEIGHT)
+					bottom = Number(this.windowHeight || this.easyWindowHeight) - (top + this.boundingClientRect.height) // 距离底部的距离等于视口的高度减上top加select组件的高度
+
+					// judge direction
+					if (bottom < thresholdHeight) {
+						this.optionsGroupDirection = 'up'
+						this.optionsGroupTop = -thresholdHeight - 12 + 'px'
+						this.optionsGroupMargin = '0'
+					} else {
+						this.optionsGroupDirection = 'down'
+						this.optionsGroupTop = 'auto'
+						this.optionsGroupMargin = '10px 0 0 0'
+					}
+
+					// if (this.scrollTop < )
+					this.showOptions = !this.showOptions
+				}).exec();
+			},
+			select(options) {
+				this.showOptions = false
+				this.currentSelect = options
+				this.$emit('selectOne', options)
+			},
+			hideOptions() {
+				this.showOptions = false
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.easy-select {
+		position: relative;
+		color: #606266;
+		input{
+			text-align: right;
+		}
+	}
+	.easy-select input {
+		overflow: hidden;
+		white-space: nowrap;
+		text-overflow: ellipsis;
+		height: 100% !important;
+		min-height: 100% !important;
+	}
+
+	.easy-select .easy-select-suffix {
+		position: absolute;
+		box-sizing: border-box;
+		height: 100%;
+		right: 5px;
+		top: 0;
+		display: flex;
+		align-items: center;
+		transform: rotate(180deg);
+		transition: all .3s;
+		transform-origin: center;
+	}
+
+	.easy-select .showOptions {
+		transform: rotate(0) !important;
+	}
+
+	.easy-select .no-showOptions {
+		transform: rotate(180deg) !important;
+	}
+
+	.easy-select .easy-select-options {
+		position: absolute;
+		padding: 6px 0;
+		margin-top: 10px;
+		border: 1px solid #e4e7ed;
+		border-radius: 4px;
+		background-color: #fff;
+		box-shadow: 0 2px 12px 0 rgba(0, 0, 0, .1);
+		box-sizing: border-box;
+		transform-origin: center top;
+		z-index: 2238;
+		overflow: scroll;
+		max-height: 274rpx;
+	}
+
+	.easy-select .easy-select-options-item {
+		padding: 0 20rpx;
+		position: relative;
+		white-space: nowrap;
+		font-size: 14px;
+		color: #606266;
+		height: 33px;
+		line-height: 33px;
+		box-sizing: border-box;
+	}
+
+	.easy-select .active {
+		background-color: #F5F7FA
+	}
+</style>

+ 1 - 1
manifest.json

@@ -73,7 +73,7 @@
         "devServer" : {
             "proxy" : {
                 "/api" : {
-                    "target" : "http://rpg.frp.liuniu946.com/api/",
+                    "target" : "http://kp.liuniu946.com",
                     // "changeOrigin": true,
                     "pathRewrite" : {
                         "/api" : "" // rewrite path

+ 25 - 0
pages.json

@@ -130,6 +130,31 @@
 				"navigationBarTitleText": "我的组队详情"
 			}
 		},
+		{
+			"path": "pages/assets/transfer",
+			"style": {
+				"navigationBarTitleText": "转账",
+				"app-plus": {
+					"titleNView": false
+				}
+			}
+		},
+		{
+			"path": "pages/assets/recharge",
+			"style": {
+				"navigationBarTitleText": "充币"
+				
+			}
+		},
+		{
+			"path": "pages/assets/withdraw",
+			"style": {
+				"navigationBarTitleText": "提币",
+				"app-plus": {
+					"titleNView": false
+				}
+			}
+		},
 		{
 			"path": "pages/set/addressManage",
 			"style": {

+ 8 - 4
pages/assets/assets.vue

@@ -24,16 +24,16 @@
 					</view>
 				</view>
 				<view class="list-tpl flex">
-					<view class="tpl" @click="navTo('/pages/finance/transfer')">
+					<view class="tpl" @click="navTo('/pages/assets/transfer')">
 						<image class="zhuanz" src="../../static/img/zhuan.png"></image>
 						<view class="tpl-name">转账</view>
 					</view>
-					<view class="tpl" @click="navTo('/pages/finance/recharge')">
+					<view class="tpl" @click="navTo('/pages/assets/recharge')">
 						<!-- @click="recharge" -->
 						<image src="../../static/img/chong.png"></image>
 						<view class="tpl-name">充币</view>
 					</view>
-					<view class="tpl" @click="navTo('/pages/finance/withdraw')">
+					<view class="tpl" @click="navTo('/pages/assets/withdraw')">
 						<image src="../../static/img/ti.png"></image>
 						<view class="tpl-name">提币</view>
 					</view>
@@ -282,12 +282,13 @@ page {
 			width: 100%;
 		}
 	}
-	z-index: 10;
 	position: relative;
 	color: #ffffff;
 	border-radius: 20rpx;
 	margin-bottom: 60rpx;
 	.info-box {
+		z-index: 10;
+		position: relative;
 		padding: 31rpx 43rpx;
 		.image {
 			width: 44rpx !important;
@@ -296,6 +297,8 @@ page {
 		.info {
 			width: 80%;
 			.list-title {
+				position: relative;
+				z-index: 10;
 				font-size: 30rpx;
 				font-weight: 500;
 				color: #ffffff;
@@ -422,4 +425,5 @@ page {
 	width: 100%;
 	height: 100%;
 }
+
 </style>

+ 532 - 0
pages/assets/details.vue

@@ -0,0 +1,532 @@
+<template>
+	<view class="container">
+		<view class="logo"><image :src="logo"></image></view>
+		<view class="select-box flex_item">
+			<view @tap="handleTap('picker')">{{ title }}</view>
+			<lb-picker
+				ref="picker"
+				v-model="value"
+				mode="selector"
+				:list="typeList"
+				:dataset="{ name: 'type' }"
+				@change="handleChange"
+				@confirm="handleConfirm"
+				@cancel="handleCancel"
+			></lb-picker>
+			<image src="../../static/img/img37.png"></image>
+		</view>
+		<view class="list" v-show="list.length > 0">
+			<view class="list-box" v-for="(ls, index) in list" :key="index" @click="nav(index)">
+				<view class="flex">
+					<view class="list-tpl flex_item">
+						<image src="../../static/img/img36.png"></image>
+						<view class="tpl-name">{{ ls.title }}</view>
+					</view>
+					<view class="num clamp" v-if="ls.pm === 0">- {{ ls.number }}</view>
+					<view class="num clamp" v-else>+ {{ ls.number }}</view>
+				</view>
+				<view class="tpl-time">{{ ls.add_time }}</view>
+			</view>
+		</view>
+		<view class="empty-box" v-show="list.length == 0"><empty></empty></view>
+		<view class="flex submit-box">
+			<view class="submit" @click="recharge">充币</view>
+			<view class="tip"></view>
+			<view class="submit" @click="withdraw">提币</view>
+		</view>
+		<uni-popup ref="popup" type="center">
+			<view class="popup">
+				<view class="cancel flex" @click="close">
+					<view></view>
+					<view class="tip">x</view>
+				</view>
+				<view class="list-boxs">
+					<view class="popup-text">购买数量:</view>
+					<view class="password"><input type="number" v-model="num" placeholder="请输入算力数量" /></view>
+					<view class="popup-text">币种选择:</view>
+					<view class="content" @click="useOutClickSide"><easy-select ref="easySelect" :options="moneyTypeList" :value="name" @selectOne="selectOne"></easy-select></view>
+					<view class="confirm-btn" @click="pay"><text>确认充币</text></view>
+				</view>
+			</view>
+		</uni-popup>
+		<uni-popup ref="mation" type="center">
+			<view class="popup">
+				<view class="cancel flex" @click="close2"><view class="tip">x</view></view>
+				<view class="list-boxs">
+					<view class="textBox flex">
+						<view class="font">交易前:</view>
+						<view class="number">{{ before * 1 }} {{ code }}</view>
+					</view>
+					<view class="xian"></view>
+					<view class="textBox flex">
+						<view class="font">交易额:</view>
+						<view class="number">{{ pm }}{{ number * 1 }} {{ code }}</view>
+					</view>
+					<view class="xian"></view>
+					<view class="textBox flex">
+						<view class="font">交易后:</view>
+						<view class="number">{{ balance * 1 }} {{ code }}</view>
+					</view>
+					<view class="xian"></view>
+					<scroll-view scroll-y="true" class="textBox">
+						<view class="font">流水详情:</view>
+						<view class="text">{{ text }}</view>
+					</scroll-view>
+				</view>
+			</view>
+		</uni-popup>
+	</view>
+</template>
+<script>
+import { moneyLog, recharge } from '@/api/finance.js';
+import { moneyType } from '@/api/index.js';
+import LbPicker from '@/components/lb-picker';
+import empty from '@/components/empty';
+export default {
+	components: {
+		LbPicker,
+		empty
+	},
+	data() {
+		return {
+			code: '',
+			title: '筛选',
+			type: '',
+			value: '',
+			index: 0,
+			typeList: [],
+			list: '',
+			num: '',
+			moneyTypeList: [],
+			money: '',
+			name: '',
+			logo: '',
+			price: '',
+			mark: '',
+			charge: 0,
+
+			_address_qr: '',
+			__money_address: '',
+			ids: '',
+			keysAddr: '',
+			text: '',
+			balance: '',
+			before: '',
+			number: '',
+			pm: '',
+			way: [],
+			address: '',
+			waypath: '',
+			less: '',
+			page: 1,
+			limit: 5,
+			isLast: true
+		};
+	},
+	onLoad(option) {
+		console.log(option, 'detail-option');
+		this.waypath = option.waypath;
+		console.log(this.waypath, '+++++++++++++++++++++');
+		this.way = option.way;
+		console.log('detail', this.way);
+		this.code = option.code;
+		this.logo = option.logo;
+		this.name = option.name;
+		this.price = option.price;
+		this.charge = option.charge;
+		this.address = option.address;
+		console.log(this.address, 'detail');
+		this._address_qr = option._address_qr;
+		this.__money_address = option.__money_address;
+		this.mark = option.mark;
+		this.ids = option.ids;
+		this.keysAddr = option.keysAddr;
+		this.moneyType();
+		this.loadData();
+	},
+	onShow() {},
+	methods: {
+		async loadData() {
+			let obj = this;
+			moneyLog(
+				{
+					page: 1,
+					limit: 10000,
+					type: obj.type
+				},
+				obj.code
+			).then(({ data }) => {
+				obj.typeList = data.type_list;
+				obj.list = data.list;
+				console.log(obj.list);
+			});
+		},
+		// 所有币种
+		async moneyType() {
+			let obj = this;
+			moneyType({}).then(({ data }) => {
+				obj.moneyTypeList = data;
+			});
+		},
+		pay() {
+			let obj = this;
+			recharge(
+				{
+					num: obj.num,
+					money_type: obj.code
+				},
+				obj.buyId
+			)
+				.then(({ data }) => {
+					obj.$api.msg(data.msg);
+					obj.$refs.popup.close();
+					obj.num = '';
+					obj.code = '';
+					uni.navigateTo({
+						url: '/pages/finance/recharge?LOGO=' + data._address_qr + '&order_id=' + data.order_id + '&ddress=' + data.__money_address + '&id=' + data.id
+					});
+				})
+				.catch(e => {
+					obj.$refs.popup.close();
+				});
+		},
+		selectOne(options) {
+			this.name = options.name;
+			this.code = options.code;
+		},
+		useOutClickSide() {
+			this.$refs.easySelect.hideOptions && this.$refs.easySelect.hideOptions();
+		},
+		handleTap(name) {
+			this.$refs[name].show();
+		},
+		handleChange(e) {
+			// this.title = e.item.title;
+			// this.type = e.item.type;
+		},
+		handleConfirm(e) {
+			this.title = e.item.title;
+			this.type = e.item.type;
+			this.loadData();
+		},
+		handleCancel(e) {},
+		recharge() {
+			let url = '/pages/finance/recharge?logo=' +
+					this.logo +
+					'&name=' +
+					this.name +
+					'&code=' +
+					this.code +
+					'&_address_qr=' +
+					this._address_qr +
+					'&__money_address=' +
+					this.__money_address +
+					'&mark=' +
+					this.mark +
+					'&ids=' +
+					this.ids +
+					'&keysAddr=' +
+					this.keysAddr +
+					'&charge=' +
+					this.charge +
+					'&address=' +
+					this.address +
+					'&way=' +
+					this.way +
+					'&waypath=' +
+					this.waypath
+			if(this.code === 'FIL') {
+				console.log("555555555")
+				url='/pages/finance/recharge'
+			}
+			uni.navigateTo({
+				url:url
+					// '/pages/finance/recharge?logo=' +
+					// this.logo +
+					// '&name=' +
+					// this.name +
+					// '&code=' +
+					// this.code +
+					// '&_address_qr=' +
+					// this._address_qr +
+					// '&__money_address=' +
+					// this.__money_address +
+					// '&mark=' +
+					// this.mark +
+					// '&ids=' +
+					// this.ids +
+					// '&keysAddr=' +
+					// this.keysAddr +
+					// '&charge=' +
+					// this.charge +
+					// '&address=' +
+					// this.address +
+					// '&way=' +
+					// this.way +
+					// '&waypath=' +
+					// this.waypath
+			});
+			// this.$refs.popup.open();
+		},
+		close() {
+			this.$refs.popup.close();
+		},
+		withdraw() {
+			uni.navigateTo({
+				url: '/pages/finance/withdraw?logo=' + this.logo + '&name=' + this.name + '&code=' + this.code + '&money=' + this.price
+			});
+		},
+		navTo(url) {
+			uni.navigateTo({
+				url
+			});
+		},
+		nav(index) {
+			const obj = this;
+			obj.text = obj.list[index].mark;
+			obj.balance = obj.list[index].balance;
+			obj.number = obj.list[index].number;
+			if (obj.list[index].pm == 1) {
+				obj.pm = '+';
+
+				obj.before = obj.subNum(obj.balance, obj.number);
+			} else {
+				obj.pm = '-';
+				obj.before = this.addNum(obj.balance, obj.number);
+			}
+			this.$refs.mation.open();
+		},
+		addNum(num1, num2) {
+			let sq1, sq2, multiple;
+			try {
+				sq1 = num1.toString().split('.')[1].length;
+			} catch (e) {
+				sq1 = 0;
+			}
+			try {
+				sq2 = num2.toString().split('.')[1].length;
+			} catch (e) {
+				sq2 = 0;
+			}
+			multiple = Math.pow(10, Math.max(sq1, sq2) + 1);
+			return (num1 * multiple + num2 * multiple) / multiple;
+		},
+		close2() {
+			this.$refs.mation.close();
+		},
+		subNum(num1, num2) {
+			let sq1, sq2, multiple;
+			try {
+				sq1 = num1.toString().split('.')[1].length;
+			} catch (e) {
+				sq1 = 0;
+			}
+			try {
+				sq2 = num2.toString().split('.')[1].length;
+			} catch (e) {
+				sq2 = 0;
+			}
+			multiple = Math.pow(10, Math.max(sq1, sq2) + 1);
+			return (num1 * multiple - num2 * multiple) / multiple;
+		}
+	}
+};
+</script>
+
+<style lang="scss">
+page {
+	min-height: 100%;
+	background-color: #ffffff;
+
+	.container {
+		width: 100%;
+		padding: 60rpx 30rpx 120rpx 30rpx;
+	}
+}
+
+.logo {
+	text-align: center;
+
+	image {
+		width: 119rpx;
+		height: 119rpx;
+	}
+}
+
+.select-box {
+	position: absolute;
+	right: 0;
+	padding: 30rpx 30rpx;
+	font-size: 32rpx;
+	font-weight: 500;
+	color: #333333;
+
+	image {
+		width: 21rpx;
+		height: 11rpx;
+		margin-left: 15rpx;
+	}
+
+	.select-name {
+		padding-right: 15rpx;
+	}
+}
+
+.list {
+	margin-top: 120rpx;
+}
+
+.list-box {
+	padding: 60rpx 0rpx 30rpx 0rpx;
+	font-size: 30rpx;
+	font-weight: 400;
+	color: #333333;
+	.tpl-time {
+		font-size: 24rpx;
+		font-weight: 400;
+		color: #999999;
+		width: 100%;
+		text-align: right;
+		padding-top: 25rpx;
+	}
+	.list-tpl {
+		image {
+			width: 39rpx;
+			height: 43rpx;
+		}
+		.tpl-name {
+			padding: 0rpx 15rpx 0rpx 30rpx;
+		}
+	}
+	.num {
+		font-size: 36rpx;
+		font-weight: 400;
+		color: #fb3a2f;
+		width: 50%;
+		text-align: right;
+	}
+}
+.empty-box {
+	width: 100%;
+	height: 500rpx;
+	padding-top: 200rpx;
+}
+.submit-box {
+	position: fixed;
+	bottom: 0;
+	left: 0;
+	width: 100%;
+	background-color: #5771df;
+	color: #ffffff;
+
+	.submit {
+		padding: 20rpx 20%;
+	}
+
+	.tip {
+		width: 2rpx;
+		height: 37rpx;
+		background: #ffffff;
+	}
+}
+//弹窗
+.popup {
+	background-color: #ffffff;
+	border-radius: 25rpx;
+	font-size: 30rpx;
+	.cancel {
+		text-align: center;
+		width: 100%;
+		line-height: 60rpx;
+		.tip {
+			background-color: #5771df;
+			color: #ffffff;
+			width: 70rpx;
+			height: 70rpx;
+			border-top-right-radius: 25rpx;
+		}
+	}
+	.list-boxs {
+		padding: 0rpx 80rpx;
+		.password {
+			padding: 50rpx 0rpx;
+			width: 100%;
+			input {
+				width: 70%;
+				height: 80rpx;
+				border: 2rpx solid #999999;
+				padding-left: 25rpx;
+				box-shadow: 0px 3px 5px 0px rgba(0, 0, 0, 0.27);
+				border-radius: 11rpx;
+			}
+		}
+		.confirm-btn {
+			padding-bottom: 120rpx;
+			padding-top: 30rpx;
+			text {
+				background-color: #5771df;
+				color: #ffffff;
+				width: 70%;
+				text-align: center;
+				padding: 25rpx 90rpx;
+				border-radius: 15rpx;
+			}
+		}
+	}
+}
+.popup {
+	height: 618rpx;
+	background: #ffffff;
+	box-shadow: 3rpx 3rpx 6rpx 0rpx rgba(31, 31, 31, 0.17);
+	border-radius: 40rpx;
+	width: 700rpx;
+	.cancel {
+		text-align: center;
+		width: 100%;
+		line-height: 60rpx;
+		position: relative;
+		.tip {
+			color: #000000;
+			width: 70rpx;
+			height: 70rpx;
+			position: absolute;
+			top: 0;
+			right: 0;
+			background-color: #fff;
+		}
+	}
+	.list-boxs {
+		width: 90%;
+		margin: 0 auto;
+		margin-top: 100rpx;
+
+		.textBox {
+			padding: 24rpx 18rpx;
+			.font {
+				font-size: 28rpx;
+				font-family: PingFang SC;
+				font-weight: bold;
+				color: #4f4f4f;
+			}
+			.number {
+				font-size: 28rpx;
+				font-family: PingFang SC;
+				font-weight: bold;
+				color: #fb3a2f;
+			}
+			.text {
+				text-indent: 2em;
+				font-size: 28rpx;
+				font-family: PingFang SC;
+				font-weight: bold;
+				color: #4f4f4f;
+			}
+		}
+		.xian {
+			width: 100%;
+			height: 1px;
+			background: #e7dfe8;
+		}
+	}
+}
+</style>

+ 133 - 0
pages/assets/recharge.vue

@@ -0,0 +1,133 @@
+<template>
+	<view class="center">
+		<view class="top">
+			<view class="title flex">
+				<view class="xian"></view>
+				<view class="title-font">
+					充币二维码
+				</view>
+			</view>
+			<view class="erweima-box">
+				<view class="erweima-font">
+					请转入USDT
+				</view>
+				<view class="erweima">
+					<image src="" mode=""></image>
+				</view>
+			</view>
+			<view class="btn">
+				保存二维码
+			</view>
+		</view>
+		<view class="top">
+			<view class="title flex">
+				<view class="xian"></view>
+				<view class="title-font">
+					充币地址
+				</view>
+			</view>
+			<view class="address">
+				0XJDKHGHDHFH3773HWEHG
+			</view>
+			<view class="btn" style="margin-top: 50rpx;">
+				复制充币地址
+			</view>
+		</view>
+		<view class="top info">
+			请勿向上述地址充值人任何非USDT资产,否则资产将不可追回。<br>
+			USDT冲币仅支持ERC2.0以太坊上的资产,其他USDT将无法上帐,请您谅解。<br>
+			您充值至上述地址后,需要整个网络节点确认,1次网络确认后到账,2次网络确认后即可提币。<br>
+			最小充值金额:100USDT,小于最小金额的充值将不会上帐且无法退回。<br>
+			请通过IMTOKEN充值,充值时在备注栏填写 个人的用户ID,如果用户ID错误,将导致您无法入账,请注意确认。
+		</view>
+	</view>
+</template>
+
+<script>
+export default {
+	data() {
+		return {
+		}
+	},
+	methods:{
+		
+	}
+}
+</script>
+
+<style lang="scss">
+.center,page {
+	height: 100%;
+	background: #F3F3F3;
+}
+.top:first-child {
+	margin-top: 0;
+}
+.top {
+	margin-top: 20rpx;
+	width: 100%;
+	height: auto;
+	background: #FFFFFF;
+	padding: 26rpx 30rpx 50rpx;
+	.erweima-box {
+		margin-top: 77rpx ;
+		.erweima-font {
+			text-align: center;
+			font-size: 30rpx;
+			font-family: PingFang SC;
+			font-weight: bold;
+			color: #333333;
+		}
+		.erweima {
+			margin: 16rpx auto 0;
+			width: 188rpx;
+			height: 188rpx;
+			background: #00BCD4;
+			image {
+				width: 100%;
+				height: 100%;
+			}
+		}
+	}
+	.address {
+		margin-top: 86rpx;
+		text-align: center;
+	}
+}
+.title {
+	justify-content: flex-start;
+	align-items: center;
+	.xian {
+		width: 2rpx;
+		height: 30rpx;
+		background: linear-gradient(90deg, #F95B2F, #60BAB0, #45969B);
+	}
+	.title-font {
+		padding-left: 16rpx;
+		font-size: 30rpx;
+		font-family: PingFang SC;
+		font-weight: bold;
+		color: #333333;
+	}
+}
+.btn{
+	margin: 36rpx auto 0;
+	width: 500rpx;
+	height: 60rpx;
+	background: linear-gradient(90deg, #60BAB0, #60BAB0, #45969B);
+	border-radius: 30px;
+	line-height: 60rpx;
+	text-align: center;
+	font-size: 26rpx;
+	font-family: PingFang SC;
+	font-weight: 500;
+	color: #FFFFFF;
+}
+.info {
+	font-size: 24rpx;
+	font-family: PingFang SC;
+	font-weight: 500;
+	color: #333333;
+	line-height: 42rpx;
+}
+</style>

+ 270 - 0
pages/assets/transfer.vue

@@ -0,0 +1,270 @@
+<template>
+	<view class="container">
+		<view class="goback-box" @click="toBack">
+			<image class="goback" src="../../static/img/fanhui.png" mode=""></image>
+		</view>
+		<view class="header">转账</view>
+		
+		
+		<view class="list-box">
+			<view class="img">
+				<image src="../../static/img/zhuanzhang-bg.png" mode=""></image>
+			</view>
+			<view class="list flex">
+				<view class="flex_item list-item">
+					<image :src="logo"></image>
+					<view>{{ name }}</view>
+				</view>
+				<view class="flex_item list-tpl">
+					<view class="content" @click="useOutClickSide"><selectss ref="easySelect" :options="moneyTypeList" :value="name" @selectOne="selectOne"></selectss></view>
+					<image src="../../static/img/jiantou.png"></image>
+				</view>
+			</view>
+		</view>
+		<view class="from-box">
+			<view class="from-title">对方账号</view>
+			<input class="input-box" type="text" v-model="account" placeholder="请输入对方账号" />
+			<view class="from-title">对方UID</view>
+			<input class="input-box" type="text" v-model="UUID" placeholder="请输入对方UID" />
+			<view class="from-title">交易密码</view>
+			<input class="input-box" type="password" v-model="password" placeholder="请输入交易密码" />
+			<view class="from-title">转账数量</view>
+			<view class="flex input-tpl">
+				<input class="input-box" type="number" v-model="num" placeholder="请输入数量" />
+				<view class="all" @click="num = money">全部</view>
+			</view>
+			<view class="all-num">
+				可用
+				<text>{{ money * 1 }}</text>
+				{{ name }}
+			</view>
+			<view class="submit" @click="transfer">确定</view>
+			<!-- <view class="tpl-box">转账数量10.0个起,手续费:0.0001FIL。</view> -->
+		</view>
+	</view>
+</template>
+<script>
+import { goPay, trade } from '@/api/finance.js';
+import selectss from '@/components/select.vue';
+export default {
+	components: {
+		selectss
+	},
+	data() {
+		return {
+			moneyTypeList: [],
+			logo: '',
+			name: '',
+			code: '',
+			money: '',
+
+			account: '',
+			UUID: '',
+			num: '',
+			password: ''
+		};
+	},
+	onLoad(option) {
+		if (option.name) {
+			this.name = option.name;
+			this.logo = option.logo;
+			this.code = option.code;
+		}
+		this.moneyType();
+	},
+	onShow() {},
+	methods: {
+		// 所有币种
+		async moneyType() {
+			let obj = this;
+			trade({}).then(({ data }) => {
+				obj.moneyTypeList = data;
+				if (obj.logo == '') {
+					obj.logo = obj.moneyTypeList[0].LOGO;
+					obj.name = obj.moneyTypeList[0].name;
+					obj.code = obj.moneyTypeList[0].code;
+					obj.money = obj.moneyTypeList[0].wallet.money;
+				}
+			});
+		},
+		transfer() {
+			let obj = this;
+			if (obj.code == '') {
+				obj.$api.msg('请选择币种!');
+				return;
+			}
+			if (obj.account == '') {
+				obj.$api.msg('请输入对方账号!');
+				return;
+			}
+			if (obj.UUID == '') {
+				obj.$api.msg('请输入对方UUID!');
+				return;
+			}
+			if (obj.password == '') {
+				obj.$api.msg('请输入交易密码!');
+				return;
+			}
+			if (obj.num == '') {
+				obj.$api.msg('请输入转账数量!');
+				return;
+			}
+			goPay({
+				type: obj.code,
+				num: obj.num,
+				to_uid: obj.UUID,
+				trade_psw: obj.password,
+				to_user_account: obj.account
+			}).then(data => {
+				obj.num = '';
+				obj.UUID = '';
+				obj.password = '';
+				obj.account = '';
+				obj.$api.msg(data.msg);
+			});
+		},
+		selectOne(options) {
+			this.logo = options.LOGO;
+			this.name = options.name;
+			this.code = options.code;
+			this.money = options.wallet.money;
+		},
+		useOutClickSide() {
+			this.$refs.easySelect.hideOptions && this.$refs.easySelect.hideOptions();
+		},
+		toBack(){
+			uni.navigateBack({
+			    delta: 1
+			});
+		}
+	}
+};
+</script>
+
+<style lang="scss">
+page {
+	min-height: 100%;
+	background-color: #ffffff;
+	.container {
+		width: 100%;
+	}
+}
+
+.list-box {
+	padding: 104rpx 30rpx 60rpx;
+	height: 350rpx;
+	.img {
+		position: absolute;
+		top: 0;
+		left: 0;
+		right: 0;
+		width: 100%;
+		height: 440rpx;
+		image {
+			width: 100%;
+			height: 100%;
+		}
+	}
+	.list {
+		position: relative;
+		z-index: 10;
+		background-color: #ffffff;
+		border-radius: 15rpx;
+		padding: 15rpx 23rpx;
+		.list-item {
+			font-size: 30rpx;
+			font-weight: bold;
+			color: #333333;
+			image {
+				width: 43rpx;
+				height: 43rpx;
+				margin-right: 15rpx;
+			}
+		}
+		.list-tpl {
+			image {
+				width: 15rpx;
+				height: 25rpx;
+				margin-left: 20rpx;
+			}
+		}
+	}
+}
+.from-box {
+	margin: 74rpx 30rpx;
+	padding: 44rpx 25rpx;
+	background-color: #ffffff;
+	border-radius: 15rpx;
+	position: relative;
+	top: -180rpx;
+	.from-title {
+		font-size: 24rpx;
+		font-weight: bold;
+		color: #333333;
+	}
+	.input-box {
+		font-size: 26rpx;
+		font-weight: 500;
+		color: #666666;
+		margin: 35rpx 0rpx;
+	}
+	.all {
+		font-size: 30rpx;
+		font-weight: 500;
+		color: #44969d;
+	}
+	.all-num {
+		font-size: 24rpx;
+		font-weight: bold;
+		color: #333333;
+		text {
+			font-size: 26rpx;
+			padding: 0rpx 10rpx;
+			color: #44969d;
+		}
+	}
+	.submit {
+		background: linear-gradient(90deg, #60BAB0, #60BAB0, #45969B);
+		margin-top: 160rpx;
+		color: #ffffff;
+		text-align: center;
+		padding: 26rpx 0rpx;
+		border-radius: 15rpx;
+	}
+
+	.tpl-box {
+		text-align: left;
+		font-size: 28rpx;
+		font-weight: 500;
+		color: #fb3a2f;
+		margin-top: 26rpx;
+	}
+}
+.goback-box {
+		position: absolute;
+		left: 18rpx;
+		top: 0;
+		height: 80rpx;
+		display: flex;
+		align-items: center;
+	}
+	.goback {
+		z-index: 100;
+		width: 34rpx;
+		height: 34rpx;
+	}
+	.header {
+		color: #FFFFFF;
+		position: absolute;
+		left: 0;
+		top: 0;
+		width: 100%;
+		height: 80rpx;
+		font-size: 32rpx;
+		font-weight: 700;
+		z-index: 99;
+		display: flex;
+		justify-content: center;
+		align-items: center;
+	}
+</style>

+ 353 - 0
pages/assets/withdraw.vue

@@ -0,0 +1,353 @@
+<template>
+	<view class="container">
+		<view class="goback-box" @click="toBack"><image class="goback" src="../../static/img/fanhui.png" mode=""></image></view>
+		<view class="header">提币 </view>
+
+		<view class="list-box">
+			<view class="img"><image src="../../static/img/zhuanzhang-bg.png" mode=""></image></view>
+			<view class="list flex">
+				<view class="flex_item list-item">
+					<image :src="logo"></image>
+					<view>{{ name }}</view>
+				</view>
+				<view class="flex_item list-tpl">
+					<view class="content" @click="useOutClickSide"><selectss ref="easySelect" :options="moneyTypeList" :value="name" @selectOne="selectOne"></selectss></view>
+					<image src="../../static/img/jiantou.png"></image>
+				</view>
+			</view>
+		</view>
+		<view class="from-box">
+			<view class="from-title">提币地址</view>
+			<input class="input-box" type="text" v-model="addr" placeholder="请输入提币地址" />
+			<view class="from-title">数量</view>
+			<view class="flex input-tpl">
+				<input class="input-box" type="number" v-model="num" :placeholder="'最低数量 ' + less + name" />
+				<view class="all" @click="num = money">全部</view>
+			</view>
+			<view class="all-num">
+				可用
+				<text>{{ money * 1 }}</text>
+				{{ name }}
+			</view>
+			<view class="submit" @click="cash">确定</view>
+			
+			<view class="tpl-box" v-show="showText == true">提币数量在{{ less }}-10000.0个之间,认真核对提币地址;手续费:{{ data.service }}{{ data.service_type }}</view>
+		</view>
+		<view class="curtain" :class="{ ishiden: isHiden }" @touchmove.stop.prevent="moveHandle">
+			<view class="psw-wrapper">
+				<view class="psw-title">请输入支付密码</view>
+				<input type="password" v-model="password" class="psw-ipt" />
+				<view class="psw-btn">
+					<text @click="cancel">取消</text>
+					<text class="psw-qd" @click="pswQd">确定</text>
+				</view>
+			</view>
+		</view>
+	</view>
+</template>
+<script>
+import { cash, cashmoney_type, calculator } from '@/api/finance.js';
+import selectss from '@/components/select.vue';
+export default {
+	components: {
+		selectss
+	},
+	data() {
+		return {
+			moneyTypeList: [],
+			name: '',
+			code: '',
+			logo: '',
+			money: '',
+			less: '',
+			addr: '',
+			num: '',
+			isHiden: true,
+			data: '',
+			showText: false,
+			password: ''
+		};
+	},
+	onLoad(option) {
+		console.log(option);
+		if (option.name) {
+			this.name = option.name;
+			this.logo = option.logo;
+			this.code = option.code;
+			this.money = option.money;
+			this.less = option.less;
+		}
+		this.moneyType();
+	},
+	onShow() {},
+	watch: {
+		num(newVal, oldVal) {
+			this.calculator();
+		}
+	},
+	methods: {
+		// 所有币种
+		async moneyType() {
+			let obj = this;
+			cashmoney_type({}).then(({ data }) => {
+				obj.moneyTypeList = data;
+				if (obj.logo == '') {
+					obj.logo = obj.moneyTypeList[0].LOGO;
+					obj.name = obj.moneyTypeList[0].name;
+					obj.code = obj.moneyTypeList[0].code;
+					obj.money = obj.moneyTypeList[0].wallet.money;
+					obj.less = obj.moneyTypeList[0].less;
+				}
+			});
+		},
+		calculator() {
+			let obj = this;
+			calculator({
+				money_type: obj.code,
+				money: obj.num
+			}).then(({ data }) => {
+				console.log(data);
+				obj.data = data;
+				obj.showText = true;
+			});
+		},
+		cash() {
+			let obj = this;
+			if (obj.code == '') {
+				obj.$api.msg('请选择币种!');
+				return;
+			}
+			if (obj.addr == '') {
+				obj.$api.msg('请输入提币地址!');
+				return;
+			}
+			if (obj.num == '') {
+				obj.$api.msg('请输入提币数量!');
+				return;
+			}
+			if (obj.num < obj.less) {
+				obj.$api.msg('最低数量不能低于' + obj.less + '!');
+				return;
+			}
+			this.isHiden = false;
+		},
+		pswQd() {
+			const obj = this;
+			if (this.password == '') {
+				obj.$api.msg('请输入密码');
+			}
+			cash({
+				money_type: obj.code,
+				money: obj.num,
+				address: obj.addr,
+				password: obj.password
+			}).then(data => {
+				obj.money = '';
+				obj.address = '';
+				obj.password = '';
+				obj.$api.msg(data.msg);
+				this.isHiden = true;
+			});
+		},
+		cancel() {
+			this.password = '';
+			this.isHiden = true;
+		},
+		selectOne(options) {
+			this.logo = options.LOGO;
+			this.name = options.name;
+			this.code = options.code;
+			this.money = options.wallet.money;
+			this.less = options.less;
+		},
+		useOutClickSide() {
+			this.$refs.easySelect.hideOptions && this.$refs.easySelect.hideOptions();
+		},
+		nav(url) {
+			uni.navigateTo({
+				url: url
+			});
+		},
+		toBack(){
+			uni.navigateBack({
+			    delta: 1
+			});
+		}
+	}
+};
+</script>
+
+<style lang="scss">
+page {
+	min-height: 100%;
+	background-color: #ffffff;
+	.container {
+		width: 100%;
+	}
+}
+
+.list-box {
+	padding: 104rpx 30rpx 60rpx;
+	height: 350rpx;
+	.img {
+		position: absolute;
+		top: 0;
+		left: 0;
+		right: 0;
+		width: 100%;
+		height: 440rpx;
+		image {
+			width: 100%;
+			height: 100%;
+		}
+	}
+	.list {
+		position: relative;
+		z-index: 10;
+		background-color: #ffffff;
+		border-radius: 15rpx;
+		padding: 15rpx 23rpx;
+		.list-item {
+			font-size: 30rpx;
+			font-weight: bold;
+			color: #333333;
+			image {
+				width: 43rpx;
+				height: 43rpx;
+				margin-right: 15rpx;
+			}
+		}
+		.list-tpl {
+			image {
+				width: 15rpx;
+				height: 25rpx;
+				margin-left: 20rpx;
+			}
+		}
+	}
+}
+.from-box {
+	margin: 74rpx 30rpx;
+	padding: 44rpx 25rpx;
+	background-color: #ffffff;
+	border-radius: 15rpx;
+	position: relative;
+	top: -180rpx;
+	.from-title {
+		font-size: 24rpx;
+		font-weight: bold;
+		color: #333333;
+	}
+	.input-box {
+		font-size: 26rpx;
+		font-weight: 500;
+		color: #666666;
+		margin: 35rpx 0rpx;
+	}
+	.all {
+		font-size: 30rpx;
+		font-weight: 500;
+		color: #44969D;
+	}
+	.all-num {
+		font-size: 24rpx;
+		font-weight: bold;
+		color: #333333;
+	}
+	.submit {
+		background: linear-gradient(90deg, #60BAB0, #60BAB0, #45969B);
+		margin-top: 165rpx;
+		color: #ffffff;
+		text-align: center;
+		padding: 26rpx 0rpx;
+		border-radius: 15rpx;
+	}
+
+	.tpl-box {
+		text-align: left;
+		font-size: 28rpx;
+		font-weight: 500;
+		color: #fb3a2f;
+		margin-top: 26rpx;
+	}
+}
+.jilv {
+	margin-top: 30rpx;
+	text-align: center;
+	color: #999999;
+	font-size: 30rpx;
+}
+.curtain {
+	position: fixed;
+	width: 100%;
+	height: 100%;
+	top: 0;
+	background-color: rgba($color: #000000, $alpha: 0.2);
+	.psw-wrapper {
+		position: fixed;
+		top: 50%;
+		left: 50%;
+		transform: translate(-50%, -100%);
+		width: 548.6rpx;
+		height: 344.4rpx;
+		background-color: #ffffff;
+		border-radius: 15rpx 15rpx;
+		.psw-title {
+			width: 100%;
+			font-size: 35rpx;
+			padding: 43rpx 0 49rpx;
+			text-align: center;
+			font-weight: 800;
+		}
+		.psw-ipt {
+			display: block;
+			background-color: #dce3ed;
+			height: 90rpx;
+			width: 464rpx;
+			padding-left: 30rpx;
+			margin: 0 auto;
+			font-size: 80rpx;
+		}
+		.psw-btn text {
+			display: inline-block;
+			text-align: center;
+			width: 50%;
+			padding-top: 29rpx;
+			font-size: 35rpx;
+		}
+		.psw-qd {
+			color: #5771df;
+		}
+	}
+}
+.ishiden {
+	display: none;
+}
+.goback-box {
+		position: absolute;
+		left: 18rpx;
+		top: 0;
+		height: 80rpx;
+		display: flex;
+		align-items: center;
+	}
+	.goback {
+		z-index: 100;
+		width: 34rpx;
+		height: 34rpx;
+	}
+	.header {
+		color: #FFFFFF;
+		position: absolute;
+		left: 0;
+		top: 0;
+		width: 100%;
+		height: 80rpx;
+		font-size: 32rpx;
+		font-weight: 700;
+		z-index: 99;
+		display: flex;
+		justify-content: center;
+		align-items: center;
+	}
+</style>

+ 3 - 3
pages/index/index.vue

@@ -3,7 +3,6 @@
 		<view class="box-title">
 			<image src="../../static/img/index7.png" mode=""></image>
 		</view>
-
 		<view class="box-body">
 			<view class="navBox">
 				<view class="navBox-left">
@@ -95,9 +94,10 @@
 </script>
 <style lang="scss">
 	.center {
-		height: 100%;
+		height: auto;
+		min-height: 100%;
 		background-color: #FFFFFF;
-
+		padding-bottom: var(--window-bottom);
 		.box-title {
 			position: relative;
 			z-index: 1;

+ 190 - 21
pages/index/node.vue

@@ -8,7 +8,7 @@
 				:height="70"
 				:show-bar="false"
 				active-color="#44969D"
-				inactive-color='#6D7C88'
+				inactive-color="#6D7C88"
 				:list="tabList"
 				:current="current"
 				@change="tabsChange"
@@ -17,31 +17,76 @@
 		</view>
 		<swiper class="tabSwiper" :current="current" @animationfinish="transition">
 			<swiper-item class="swiper-item">
-				<scroll-view scroll-y @scrolltolower="onreachBottom">
-					<view class="boxItem">
-						<view class="item" v-for="ls in tabList[0].list">
-							<view class="flex title">
-								<view class="tip"></view>
-								<view class="name">{{ ls.name }}</view>
+				<scroll-view class="boxItem" scroll-y @scrolltolower="onreachBottom">
+					<view class="item" v-for="ls in tabList[0].list">
+						<view class="flex title">
+							<view class="tip"></view>
+							<view class="name">{{ ls.name }}</view>
+						</view>
+						<view class="itemConetnt">
+							<view class="ls">
+								认购份额:
+								<text class="text">{{ ls.num + ls.type }}</text>
+							</view>
+							<view class="ls">
+								认
+								<text class="textInterval "></text>
+								购
+								<text class="textInterval "></text>
+								价:
+								<text class="text">1{{ ls.moneyType + '=' + ls.ratio + ls.type }}</text>
 							</view>
-							<view class="itemConetnt">
-								
+							<view class="ls">
+								认购名额:
+								<text class="text">{{ ls.limited }}</text>
+							</view>
+							<view class="ls">
+								认购总额:
+								<text class="text">{{ ls.allMoney + ls.moneyType }}</text>
 							</view>
 						</view>
+						<view class="lsButtom" @click="buy()">立即认购</view>
 					</view>
 					<u-loadmore :status="tabList[0].loding"></u-loadmore>
 				</scroll-view>
 			</swiper-item>
 			<swiper-item class="swiper-item">
-				<scroll-view scroll-y @scrolltolower="onreachBottom"><u-loadmore :status="tabList[1].loding"></u-loadmore></scroll-view>
+				<scroll-view scroll-y @scrolltolower="onreachBottom">
+					<view class="boxItem flex" style=" flex-wrap: wrap;">
+						<view class="item1" v-for="ls in tabList[1].list">
+							<view class="rightTip">进行中</view>
+							<view class="ls1">
+								<view class="name1">{{ ls.name }}</view>
+								<view class="title1">{{ ls.mask }}</view>
+								<view class="title1">
+									认购份额:{{ls.allMoney+ls.type}}
+									<text></text>
+								</view>
+							</view>
+						</view>
+					</view>
+					<u-loadmore :status="tabList[1].loding"></u-loadmore>
+				</scroll-view>
 			</swiper-item>
 		</swiper>
+		<u-popup v-model="show" mode="center" width="548rpx"  border-radius="14">
+				<view class="psw-wrapper">
+					<view class="psw-title">请输入支付密码</view>
+					<input type="password" v-model="password" class="psw-ipt"/>
+					<view class="psw-btn">
+						<text @click="cancel">取消</text>
+						<text class="psw-qd" @click="pswQd">确定</text>
+					</view>
+				</view>
+		</u-popup>
 	</view>
 </template>
 <script>
 export default {
 	data() {
 		return {
+			show: false,
+			password:'',
 			current: 0, //当前选中的标签
 			tabList: [
 				{
@@ -51,7 +96,7 @@ export default {
 							name: '节点认购第一期',
 							num: 1000, //认购份额
 							type: 'LALA', //认购货币类型
-							ratio: 10, //认购名额
+							ratio: 10, //认购比例
 							limited: 20, //限购名额
 							allMoney: 20, //认购总额
 							moneyType: 'USDT' //兑换比例金额
@@ -65,7 +110,36 @@ export default {
 					name: '我的认购',
 					pages: 1,
 					limit: 10,
-					list: [],
+					list: [
+						{
+							name: '节点认购第一期',
+							num: 1000, //认购份额
+							type: 'LALA', //认购货币类型
+							allMoney: 20 ,//认购总额
+							mask:'当前第六关'
+						},
+						{
+							name: '节点认购第一期',
+							num: 1000, //认购份额
+							type: 'LALA', //认购货币类型
+							allMoney: 20 ,//认购总额
+							mask:'当前第六关'
+						},
+						{
+							name: '节点认购第一期',
+							num: 1000, //认购份额
+							type: 'LALA', //认购货币类型
+							allMoney: 20 ,//认购总额
+							mask:'当前第六关'
+						},
+						{
+							name: '节点认购第一期',
+							num: 1000, //认购份额
+							type: 'LALA', //认购货币类型
+							allMoney: 20 ,//认购总额
+							mask:'当前第六关'
+						}
+					],
 					loding: 'loadmore' //loading加载中 nomore没有数据
 				}
 			]
@@ -82,6 +156,7 @@ export default {
 		// 内容框切换事件
 		transition(e) {
 			console.log(e);
+			this.current = e.detail.current;
 		},
 		// tab切换事件
 		tabsChange(e) {
@@ -90,7 +165,13 @@ export default {
 		// 下拉到底部加载事件
 		onreachBottom(e) {
 			console.log(e);
-		}
+		},
+		buy(){
+			this.show = true;
+		},
+		cancel() {
+			this.show = false
+		},
 	}
 };
 </script>
@@ -118,26 +199,114 @@ export default {
 			.item {
 				background-color: #ffffff;
 				line-height: 1;
-				padding:  30rpx;
+				padding: 30rpx;
+				margin-bottom: 30rpx;
 				.title {
 					justify-content: flex-start;
 					padding-bottom: 30rpx;
 					align-items: stretch;
+					.tip {
+						width: 7rpx;
+						border-radius: 99rpx;
+						background-color: $base-color;
+					}
+					.name {
+						margin-left: 20rpx;
+						font-size: 30rpx;
+						font-weight: bold;
+						color: $font-color-dark;
+					}
+				}
+				.itemConetnt {
+					padding: 20rpx 0;
+					font-weight: bold;
+					font-size: 28rpx;
 					border-bottom: 1px solid $border-color-light;
+					border-top: 1px solid $border-color-light;
+					.ls {
+						padding: 10rpx 0;
+						color: $font-color-light;
+						.textInterval {
+							width: 0.5em;
+						}
+						.text {
+							color: $font-color-dark;
+						}
+					}
 				}
-				.tip {
-					width: 7rpx;
+				.lsButtom {
+					font-size: 30rpx;
+					background-image: $bg-green-gradual;
+					text-align: center;
+					color: $font-color-white;
+					padding: 30rpx 0;
 					border-radius: 99rpx;
-					background-color: $base-color;
+					margin: 20rpx 30rpx 0rpx 30rpx;
 				}
-				.name{
-					margin-left: 20rpx;
-					font-size: 30rpx;
+			}
+			.item1:nth-child(odd){
+				margin-right: 30rpx;
+			}
+			.item1 {
+				line-height: 1;
+				.ls1{
 					font-weight: bold;
-					color: $font-color-dark;
+					.name1{
+						color: $font-color-dark;
+						font-size: $font-base;
+						margin-top: -10rpx;
+					}
+					.title1{
+						margin-top: 15rpx;
+						color: $font-color-light;
+						font-size: 22rpx;
+					}
 				}
+				.rightTip{
+				  color:$uni-color-primary ;
+				  text-align: right;
+				  font-size: 24rpx;
+				}
+				flex-grow: 1;
+				min-width: 40%;
+				margin-bottom: 30rpx;
+				border-radius: 10rpx;
+				background-color: #FFFFFF;
+				border: 1px solid $uni-color-primary;
+				padding: 10rpx 10rpx 30rpx 30rpx;
 			}
 		}
 	}
 }
+.psw-wrapper {
+		width: 548rpx;
+		height: 344rpx;
+		background-color: #FFFFFF;
+		.psw-title {
+			width: 100%;
+			font-size: 35rpx;
+			padding: 43rpx 0 49rpx;
+			text-align: center;
+			font-weight: 800;
+		}
+		.psw-ipt {
+			display: block;
+			background-color: #dce3ed;
+			height: 90rpx;
+			width: 464rpx;
+			padding-left: 30rpx;
+			margin: 0 auto;
+			font-size: 80rpx;
+		}
+		.psw-btn text{
+			display: inline-block;
+			text-align: center;
+			width: 50%;
+			padding-top: 29rpx;
+			font-size: 35rpx;
+		}
+		.psw-qd {
+			color:#5771DF;
+		}
+	}
 </style>

+ 0 - 9
pages/public/login.vue

@@ -58,15 +58,6 @@ export default {
 				password: obj.password
 			})
 				.then(function(e) {
-					if (obj.rememberPsw) {
-						uni.setStorageSync('HCuname', obj.phone);
-						uni.setStorageSync('HCpassw', obj.password);
-					} else {
-						uni.removeStorageSync('HCuname');
-						uni.removeStorageSync('HCpassw');
-						obj.phone = '';
-						obj.password = '';
-					}
 					uni.setStorageSync('token', e.data.token);
 					getUserInfo({}).then(e => {
 						obj.login();

+ 1 - 1
pages/user/user.vue

@@ -47,7 +47,7 @@
 				</view>
 			</view>
 		</view>
-		<!-- 申请退款弹窗 -->
+		
 		<uni-popup ref="popup" type="center">
 			<view class="popup">
 				<view class="popup-dox">

BIN
static/img/zhuanzhang-bg.png


+ 1 - 1
uni.scss

@@ -45,7 +45,7 @@ $box-shadow: 0rpx 0rpx 10rpx 10rpx #f3f3f3;
 // 圆角
 $border-radius-sm: 15rpx;
 // 渐变背景颜色
-$bg-green-gradual: linear-gradient(-90edg #60bab0, #45969b);
+$bg-green-gradual: linear-gradient(90deg, #60BAB0, #45969B);
 /* 功能栏字体大小 */
 %font-title {
 	font-size: $font-lg + 2rpx;

Algunos archivos no se mostraron porque demasiados archivos cambiaron en este cambio