This commit is contained in:
唐明明
2021-09-24 16:46:02 +08:00
53 changed files with 4990 additions and 4338 deletions

View File

@@ -14,6 +14,10 @@
{ {
"launchtype" : "local" "launchtype" : "local"
}, },
"mp-weixin" :
{
"launchtype" : "local"
},
"type" : "uniCloud" "type" : "uniCloud"
} }
] ]

View File

@@ -1,33 +1,33 @@
/** /**
* Web-zdx * Web-zdx
* moduleName:核销相关操作 * moduleName:核销相关操作
*/ */
import { import {
request request
} from '../index' } from '../index'
// 扫码前置条件 get 核销前置 post 表示核销 // 扫码前置条件 get 核销前置 post 表示核销
const scanInfo = (apiUrl, data, method) => { const scanInfo = (apiUrl, data, method) => {
return request({ return request({
url: apiUrl, url: apiUrl,
method: method, method: method,
data: data data: data
}) })
} }
// 核销记录 // 核销记录
const scanList = (apiUrl, data) => { const scanList = (apiUrl, data) => {
return request({ return request({
url: apiUrl, url: apiUrl,
method: 'GET', method: 'GET',
data: data data: data
}) })
} }
export { export {
scanInfo, scanInfo,
scanList scanList
} }

View File

@@ -0,0 +1,84 @@
/**
* Web-zdx
* moduleName: 登录(手机号)
*/
import { request } from '../index'
// 手机号登陆接口
const login = (data) => {
return request({
url: 'user/socialite/login/wechat/mini',
method: 'POST',
data: data
})
}
// 修改用户信息
const wechatbind = (data) => {
return request({
url: 'user/socialite/wechatbind',
method: 'PUT',
data: data
})
}
// 修改用户头像或昵称
const resetUserInfo = (data) => {
return request({
url: 'user/' + data.key,
method: 'PUT',
data: {
value: data.value
}
})
}
// 获取用户的Openid
const getOpenid = (code) => {
return request({
url: 'user/socialite/login/wechat/openid',
method: 'GET',
data: {
code: code
}
})
}
// 隐私条款
const agreementSecret = (data) => {
return request({
url: 'articles/agreement/secret'
})
}
// 注册协议
const agreementLogin = (data) => {
return request({
url: 'articles/agreement/login'
})
}
// 获取用户设置中心的信息
const getUserSettingInfo = () => {
return request({
url: 'user/setting'
})
}
// 关于我们
const aboutUs = () => {
return request({
url: 'articles/about'
})
}
export {
login,
wechatbind,
getOpenid,
agreementSecret,
agreementLogin,
resetUserInfo,
getUserSettingInfo,
aboutUs
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,118 +1,132 @@
{ {
"pages": [{ "pages": [{
"path": "pages/index/index", "path": "pages/index/index",
"name": "Index", "name": "Index",
"aliasPath": "/", "aliasPath": "/",
"style": { "style": {
"navigationBarTitleText":"发现能量" "navigationBarTitleText": "发现能量"
} }
}, { }, {
"path": "pages/found/index", "path": "pages/found/index",
"name": "Found", "name": "Found",
"auth": true, "auth": true,
"style": { "style": {
"navigationBarTitleText":"发现更多" "navigationBarTitleText": "发现更多"
} }
}, { }, {
"path": "pages/user/index", "path": "pages/user/index",
"name": "User", "name": "User",
"auth": true, "auth": true,
"style": { "style": {
"navigationBarTitleText":"节点中心" "navigationBarTitleText": "节点中心"
} }
}, { }, {
"path": "pages/instrument/basics", "path": "pages/instrument/basics",
"name": "instrumentBasics", "name": "instrumentBasics",
"style": { "style": {
"navigationBarTitleText":"企业基础信息" "navigationBarTitleText": "企业基础信息"
} }
}, { }, {
"path": "pages/goods/management", "path": "pages/goods/management",
"name": "goodsManagement", "name": "goodsManagement",
"style": { "style": {
"navigationBarTitleText":"商品权证管理" "navigationBarTitleText": "商品权证管理"
} }
}, { }, {
"path": "pages/goods/addClassify", "path": "pages/goods/addClassify",
"name": "goodsaddClassify", "name": "goodsaddClassify",
"style": { "style": {
"navigationBarTitleText":"发布商品类目" "navigationBarTitleText": "发布商品类目"
} }
}, { }, {
"path": "pages/goods/add", "path": "pages/goods/add",
"name": "goodsAdd", "name": "goodsAdd",
"style": { "style": {
"navigationBarTitleText":"商品权证创建" "navigationBarTitleText": "商品权证创建"
} }
}, { }, {
"path": "pages/goods/goodsAuth", "path": "pages/goods/goodsAuth",
"name": "goodsAddAuth", "name": "goodsAddAuth",
"style": { "style": {
"navigationBarTitleText":"商品权证认证" "navigationBarTitleText": "商品权证认证"
} }
}, { }, {
"path": "pages/coupons/management", "path": "pages/coupons/management",
"name": "couponsManagement", "name": "couponsManagement",
"style": { "style": {
"navigationBarTitleText":"优惠券管理" "navigationBarTitleText": "创建优惠券"
} }
}, { }, {
"path": "pages/coupons/add", "path": "pages/coupons/add",
"name": "couponsAdd", "name": "couponsAdd",
"style": { "style": {
"navigationBarTitleText":"创建优惠券" "navigationBarTitleText": "创建优惠券"
} }
}, { }, {
"path": "pages/coupons/magDetails", "path": "pages/coupons/magDetails",
"name": "couponsDetails", "name": "couponsDetails",
"style": { "style": {
"navigationBarTitleText":"优惠券详情" "navigationBarTitleText": "优惠券详情"
} }
}, { }, {
"path": "pages/coupons/selectGoods", "path": "pages/coupons/selectGoods",
"name": "couponsSelectGoods", "name": "couponsSelectGoods",
"style": { "style": {
"navigationBarTitleText":"关联产品" "navigationBarTitleText": "关联产品"
} }
}, { }, {
"path": "pages/login/login", "path": "pages/login/login",
"name": "Login", "name": "Login",
"style": { "style": {
"navigationBarTitleText":"登录" "navigationBarTitleText": "登录"
} }
}, { }, {
"path" : "pages/certification/personal", "path": "pages/certification/personal",
"name" : "Personal", "name": "Personal",
"auth" : true, "auth": true,
"style": { "style": {
"navigationBarTitleText":"个人认证" "navigationBarTitleText": "个人认证"
} }
}, {
"path": "pages/setting/setting",
"name": "setting",
"auth": true,
"style": {
"navigationBarTitleText": "设置中心"
}
}, {
"path": "pages/setting/aboutUs",
"name": "aboutUs",
"auth": true,
"style": {
"navigationBarTitleText": "关于我们"
}
}], }],
"globalStyle": { "globalStyle": {
"navigationStyle": "custom", "navigationStyle": "custom",
"backgroundColor": "#F5F5F5" "backgroundColor": "#F5F5F5"
}, },
"tabBar": { "tabBar": {
"borderStyle": "white", "borderStyle": "white",
"backgroundColor": "#FFFFFF", "backgroundColor": "#FFFFFF",
"selectedColor" : "#774ffd", "selectedColor": "#774ffd",
"iconWidth":"26px", "iconWidth": "26px",
"spacing": "0", "spacing": "0",
"height":"60px", "height": "60px",
"list": [{ "list": [{
"text": "发现能量", "text": "发现能量",
"iconPath":"static/tabBar/tabBar_icon_00.png", "iconPath": "static/tabBar/tabBar_icon_00.png",
"selectedIconPath":"static/tabBar/tabBar_show_00.png", "selectedIconPath": "static/tabBar/tabBar_show_00.png",
"pagePath": "pages/index/index" "pagePath": "pages/index/index"
}, { }, {
"text": "发现更多", "text": "发现更多",
"iconPath":"static/tabBar/tabBar_icon_01.png", "iconPath": "static/tabBar/tabBar_icon_01.png",
"selectedIconPath":"static/tabBar/tabBar_show_01.png", "selectedIconPath": "static/tabBar/tabBar_show_01.png",
"pagePath": "pages/found/index" "pagePath": "pages/found/index"
}, { }, {
"text": "节点中心", "text": "节点中心",
"iconPath":"static/tabBar/tabBar_icon_02.png", "iconPath": "static/tabBar/tabBar_icon_02.png",
"selectedIconPath":"static/tabBar/tabBar_show_02.png", "selectedIconPath": "static/tabBar/tabBar_show_02.png",
"pagePath": "pages/user/index" "pagePath": "pages/user/index"
}] }]
}, },

View File

@@ -73,9 +73,16 @@
front_card: this.positive.path, front_card: this.positive.path,
back_card: this.reverse.path, back_card: this.reverse.path,
}).then(res=>{ }).then(res=>{
console.log(res) uni.showModal({
title: '提示',
content: '个人认证信息已提交,请耐心等待审核',
showCancel: false,
confirmColor: '#8b64fd',
success: modalRes => {
this.$Router.back()
}
})
}).catch(err => { }).catch(err => {
console.log(err)
uni.showToast({ uni.showToast({
icon: 'none', icon: 'none',
title: err.message title: err.message

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,4 @@
<template> <template>
<view class="content"> <view class="content">
<!-- 商品图片 --> <!-- 商品图片 -->
<view class="form-block"> <view class="form-block">
@@ -19,7 +19,7 @@
</view> </view>
</view> </view>
</view> </view>
</view> </view>
<!-- 商品基本信息 --> <!-- 商品基本信息 -->
<view class="form-block"> <view class="form-block">
<view class="form-box inputs-flex"> <view class="form-box inputs-flex">
@@ -51,7 +51,7 @@
</view> </view>
</view> </view>
</view> </view>
</view> </view>
<!-- 商品价格 --> <!-- 商品价格 -->
<view class="form-block"> <view class="form-block">
<view class="form-box inputs-flex input-unit"> <view class="form-box inputs-flex input-unit">
@@ -69,7 +69,7 @@
<input type="digit" v-model="skus_charge" placeholder="0.00"/> <input type="digit" v-model="skus_charge" placeholder="0.00"/>
<text class="units">{{skus_unit != '' ? '/' + skus_unit : ''}}</text> <text class="units">{{skus_unit != '' ? '/' + skus_unit : ''}}</text>
</view> </view>
</view> </view>
<!-- 商品详情介绍 --> <!-- 商品详情介绍 -->
<view class="form-block"> <view class="form-block">
<view class="form-box picker-flex"> <view class="form-box picker-flex">
@@ -169,15 +169,15 @@
<view class="footer"> <view class="footer">
<button class="footer-btn" type="default" @click="submitAdd">{{type == 2 ? '发布': '发布并认证'}}</button> <button class="footer-btn" type="default" @click="submitAdd">{{type == 2 ? '发布': '发布并认证'}}</button>
<view class="ios-bottom"></view> <view class="ios-bottom"></view>
</view> </view>
</view> </view>
</template> </template>
<script> <script>
import { managesGoodsCreate, managesCreate, managesGoodsEdit, managesGoodsPut } from '@/apis/interfaces/goods' import { managesGoodsCreate, managesCreate, managesGoodsEdit, managesGoodsPut } from '@/apis/interfaces/goods'
import { uploads } from '@/apis/interfaces/uploading' import { uploads } from '@/apis/interfaces/uploading'
export default { export default {
data() { data() {
return { return {
categoryId : '', // 一级分类 categoryId : '', // 一级分类
categoryCid : '', // 二级分类 categoryCid : '', // 二级分类
@@ -206,8 +206,8 @@
tags : [], // 可选商品标签 tags : [], // 可选商品标签
tagsIndex : 0, // 选择标签的下标 tagsIndex : 0, // 选择标签的下标
servicesArr : [], // 可选服务 servicesArr : [], // 可选服务
type : 1, // 1为商品2为服务 type : 1, // 1为商品2为服务
}; };
}, },
created() { created() {
// 编辑状态信息 // 编辑状态信息
@@ -289,7 +289,7 @@
icon : 'none' icon : 'none'
}) })
}) })
}, },
methods: { methods: {
// 选择商品服务 // 选择商品服务
opnePopup(key){ opnePopup(key){
@@ -415,10 +415,10 @@
}) })
}) })
} }
} }
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.content{ .content{
padding-bottom: 150rpx; padding-bottom: 150rpx;
@@ -623,5 +623,5 @@
} }
} }
} }
} }
</style> </style>

View File

@@ -1,4 +1,4 @@
<template> <template>
<view class="content"> <view class="content">
<view class="form-block"> <view class="form-block">
<view class="form-upd"> <view class="form-upd">
@@ -51,22 +51,22 @@
<label class="form-label">生产商地址</label> <label class="form-label">生产商地址</label>
<input type="text" v-model="productAddress" placeholder="输入商品生产商地址"/> <input type="text" v-model="productAddress" placeholder="输入商品生产商地址"/>
</view> </view>
</view> </view>
<!-- 安全区 --> <!-- 安全区 -->
<view class="ios-bottom"></view> <view class="ios-bottom"></view>
<!-- footer --> <!-- footer -->
<view class="footer"> <view class="footer">
<button class="footer-btn" type="default" @click="submitAdd">提交认证审核</button> <button class="footer-btn" type="default" @click="submitAdd">提交认证审核</button>
<view class="ios-bottom"></view> <view class="ios-bottom"></view>
</view> </view>
</view> </view>
</template> </template>
<script> <script>
import { managesGoodsAuth, managesGoodsExtends } from '@/apis/interfaces/goods' import { managesGoodsAuth, managesGoodsExtends } from '@/apis/interfaces/goods'
import { uploads } from '@/apis/interfaces/uploading' import { uploads } from '@/apis/interfaces/uploading'
export default { export default {
data() { data() {
return { return {
productedAt : '', // 生产日期 productedAt : '', // 生产日期
expiriedAt : '', // 过期时间 expiriedAt : '', // 过期时间
@@ -74,7 +74,7 @@
productName : '', // 生产商名称 productName : '', // 生产商名称
productAddress : '', // 生产商地址 productAddress : '', // 生产商地址
extendCover : [] // 实物图片 extendCover : [] // 实物图片
}; };
}, },
created() { created() {
if(this.$Route.query.edit == 'true'){ if(this.$Route.query.edit == 'true'){
@@ -92,7 +92,7 @@
}) })
}) })
} }
}, },
methods: { methods: {
// picker选择 // picker选择
pickerChange(e, key){ pickerChange(e, key){
@@ -163,10 +163,10 @@
}) })
}) })
} }
} }
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.content{ .content{
padding-bottom: 150rpx; padding-bottom: 150rpx;
@@ -371,5 +371,5 @@
} }
} }
} }
} }
</style> </style>

View File

@@ -1,5 +1,5 @@
<template> <template>
<view class="content"> <view class="content">
<!-- 分类 --> <!-- 分类 -->
<view class="tabs"> <view class="tabs">
<view class="item" :class="{'show': status == '0'}" @click="onTabs('0')">已发布</view> <view class="item" :class="{'show': status == '0'}" @click="onTabs('0')">已发布</view>
@@ -33,43 +33,43 @@
</template> </template>
</goodsList> </goodsList>
<!-- 燃烧 增发 弹窗 --> <!-- 燃烧 增发 弹窗 -->
<uni-popup ref="popupLay" :safe-area="true" background-color="#ffffff"> <uni-popup ref="popupLay" :safe-area="true" background-color="#ffffff">
<view class="popup"> <view class="popup">
<view class="title">库存{{stockType == 'goodsMint' ? '增发': '燃烧'}}</view> <view class="title">库存{{stockType == 'goodsMint' ? '增发': '燃烧'}}</view>
<view class="des"> <view class="des">
剩余库存 剩余库存
<text>{{itemGoods.stock}}</text> <text>{{itemGoods.stock}}</text>
</view> </view>
<view class="des"> <view class="des">
数量 数量
<uni-number-box v-model='stock' :min="1" :max="stockType == 'goodsBurn' ? itemGoods.stock : 9999"></uni-number-box> <uni-number-box v-model='stock' :min="1" :max="stockType == 'goodsBurn' ? itemGoods.stock : 9999"></uni-number-box>
</view> </view>
<view class="btn" @click="additionalOrBurning">确认</view> <view class="btn" @click="additionalOrBurning">确认</view>
</view> </view>
</uni-popup> </uni-popup>
</view> </view>
</template> </template>
<script> <script>
import { managesGoodsIndex, managesGoodsDelete, managesGoodsBurn, managesGoodsMint, managesGoodsCreateBefore } from '@/apis/interfaces/goods' import { managesGoodsIndex, managesGoodsDelete, managesGoodsBurn, managesGoodsMint, managesGoodsCreateBefore } from '@/apis/interfaces/goods'
import goodsList from '@/components/goods-list/goods-list' import goodsList from '@/components/goods-list/goods-list'
export default { export default {
components: { components: {
goodsList goodsList
}, },
data() { data() {
return { return {
status : 0, status : 0,
goods : [], goods : [],
pages : {}, pages : {},
itemGoods : {}, itemGoods : {},
stock : 1, stock : 1,
stockType : '' stockType : ''
}; };
}, },
onShow() { onShow() {
this.getList() this.getList()
}, },
methods: { methods: {
// tabs // tabs
onTabs(value){ onTabs(value){
@@ -115,9 +115,9 @@
}, },
// 提交燃烧,增发 // 提交燃烧,增发
additionalOrBurning(){ additionalOrBurning(){
let data = { let data = {
id : this.itemGoods.goods_id, id : this.itemGoods.goods_id,
stock: this.stock stock: this.stock
} }
switch (this.stockType){ switch (this.stockType){
case 'goodsBurn': case 'goodsBurn':
@@ -154,32 +154,32 @@
}, },
// 移出删除商品 // 移出删除商品
goodsRemove(id){ goodsRemove(id){
let index = this.goods.findIndex(val => val.goods_id == id) let index = this.goods.findIndex(val => val.goods_id == id)
managesGoodsDelete(id).then(res => { managesGoodsDelete(id).then(res => {
this.goods.splice(index,1) this.goods.splice(index,1)
if(this.goods.length === 0) this.getList() if(this.goods.length === 0) this.getList()
uni.showToast({ uni.showToast({
title: '商品权证已删除', title: '商品权证已删除',
icon : 'none' icon : 'none'
}) })
}).catch(err => { }).catch(err => {
uni.showToast({ uni.showToast({
title: err.message, title: err.message,
icon: 'none' icon: 'none'
}) })
}) })
} }
}, },
onNavigationBarButtonTap() { onNavigationBarButtonTap() {
this.$Router.push({name: 'addClassify'}) this.$Router.push({name: 'addClassify'})
} }
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.content{ .content{
padding-top: 90rpx; padding-top: 90rpx;
} }
// tabs // tabs
.tabs{ .tabs{
position: fixed; position: fixed;
@@ -223,38 +223,38 @@
} }
} }
} }
// 增发燃烧弹窗 // 增发燃烧弹窗
.popup { .popup {
width: 100%; width: 100%;
background-color: #fff; background-color: #fff;
padding-bottom: $padding; padding-bottom: $padding;
.title { .title {
font-size: 36rpx; font-size: 36rpx;
text-align: center; text-align: center;
padding: 50rpx 30rpx 30rpx 30rpx; padding: 50rpx 30rpx 30rpx 30rpx;
font-weight: bold; font-weight: bold;
} }
.btn { .btn {
background-color: $text-price; background-color: $text-price;
height: 90rpx; height: 90rpx;
line-height: 90rpx; line-height: 90rpx;
text-align: center; text-align: center;
color: #fff; color: #fff;
font-weight: bold; font-weight: bold;
font-size: $title-size; font-size: $title-size;
margin: $padding * 2; margin: $padding * 2;
} }
.des { .des {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
box-sizing: border-box; box-sizing: border-box;
padding: $padding $padding * 2; padding: $padding $padding * 2;
color: $text-gray; color: $text-gray;
text{ text{
color: $text-color; color: $text-color;
} }
} }
} }
</style> </style>

View File

@@ -101,16 +101,16 @@
<style lang="scss"> <style lang="scss">
.block-shadow{ .block-shadow{
box-shadow: 0 0 2rpx 2rpx rgba($color: #000000, $alpha: .02); box-shadow: 0 0 2rpx 2rpx rgba($color: #000000, $alpha: .02);
} }
// 背景 // 背景
.deal-back { .deal-back {
position: fixed; position: fixed;
top: 0; top: 0;
left: 0; left: 0;
z-index: -1; z-index: -1;
width: 100vw; width: 100vw;
height: 100vh; height: 100vh;
background: linear-gradient(to bottom, #009B69, #00562d); background: linear-gradient(to bottom, #009B69, #00562d);
} }
// 区块详情 // 区块详情
.chian-hash{ .chian-hash{
@@ -169,5 +169,5 @@
color: white; color: white;
font-size: $title-size; font-size: $title-size;
} }
} }
</style> </style>

View File

@@ -1,74 +1,74 @@
<template> <template>
<view> <view>
<!-- 区块信息 --> <!-- 区块信息 -->
<view class="info-back"></view> <view class="info-back"></view>
<view class="info-list"> <view class="info-list">
<view class="flex" v-for="(item, index) in assetsList" :key="index"> <view class="flex" v-for="(item, index) in assetsList" :key="index">
<view class="item-name ellipsis"> <view class="item-name ellipsis">
<image class="icon" :src="item.icon" mode="widthFix" /> <image class="icon" :src="item.icon" mode="widthFix" />
{{ item.name || '-' }} {{ item.name || '-' }}
</view> </view>
<view class="item-label"> <view class="item-label">
<view class="number ellipsis">{{ item.balance || '0.00' }}</view> <view class="number ellipsis">{{ item.balance || '0.00' }}</view>
<view class="unit ellipsis">{{ item.symbol || '-' }}</view> <view class="unit ellipsis">{{ item.symbol || '-' }}</view>
</view> </view>
</view> </view>
</view> </view>
<!-- 区块链变化 --> <!-- 区块链变化 -->
<view class="movements"> <view class="movements">
<view class="title">区块链变化</view> <view class="title">区块链变化</view>
<view class="chart"> <view class="chart">
<l-f2 ref="chartChange"></l-f2> <l-f2 ref="chartChange"></l-f2>
</view> </view>
</view> </view>
<!-- 区块记录 --> <!-- 区块记录 -->
<view class="chain-record"> <view class="chain-record">
<view class="title">区块记录</view> <view class="title">区块记录</view>
<chain-list :list="chainList" @onChain="chainInfo"/> <chain-list :list="chainList" @onChain="chainInfo"/>
</view> </view>
<!-- 底部安全区 --> <!-- 底部安全区 -->
<view class="ios-bottom"></view> <view class="ios-bottom"></view>
</view> </view>
</template> </template>
<script> <script>
import { chain, situation } from '@/apis/interfaces/chain' import { chain, situation } from '@/apis/interfaces/chain'
import chainList from '@/components/chain/chain' import chainList from '@/components/chain/chain'
import F2 from '@/uni_modules/lime-f2/components/lime-f2/f2.min.js' import F2 from '@/uni_modules/lime-f2/components/lime-f2/f2.min.js'
import lF2 from '@/uni_modules/lime-f2/components/lime-f2/' import lF2 from '@/uni_modules/lime-f2/components/lime-f2/'
export default { export default {
components: { components: {
chainList, chainList,
lF2 lF2
}, },
data() { data() {
return { return {
data: [{ data: [{
time: '2021-08-08 00:00:00', time: '2021-08-08 00:00:00',
value: 30 value: 30
}, { }, {
time: '2021-08-09 00:10:00', time: '2021-08-09 00:10:00',
value: 36 value: 36
}, { }, {
time: '2021-08-10 00:12:00', time: '2021-08-10 00:12:00',
value: 38 value: 38
}, { }, {
time: '2021-08-11 10:32:00', time: '2021-08-11 10:32:00',
value: 40 value: 40
}, { }, {
time: '2021-08-13 12:30:00', time: '2021-08-13 12:30:00',
value: 40 value: 40
}, { }, {
time: '2021-08-14 11:02:00', time: '2021-08-14 11:02:00',
value: 41 value: 41
}, { }, {
time: '2021-08-15 10:02:00', time: '2021-08-15 10:02:00',
value: 41 value: 41
}], }],
assetsList: [], assetsList: [],
chainList: [] chainList: []
}; };
}, },
mounted() { mounted() {
Promise.all([chain(), situation()]).then(res => { Promise.all([chain(), situation()]).then(res => {
this.chainList = res[0] this.chainList = res[0]
@@ -78,8 +78,8 @@
icon: 'none', icon: 'none',
title: 'err in chain/info.vue ' + err title: 'err in chain/info.vue ' + err
}) })
}) })
this.$refs.chartChange.init(config => { this.$refs.chartChange.init(config => {
const chart = new F2.Chart(config); const chart = new F2.Chart(config);
chart.source(this.data, { chart.source(this.data, {
time: { time: {
@@ -116,8 +116,8 @@
.shape('smooth'); .shape('smooth');
chart.render(); chart.render();
return chart; return chart;
}) })
}, },
methods: { methods: {
// 区块详情 // 区块详情
chainInfo(e){ chainInfo(e){
@@ -125,85 +125,85 @@
url: './deal?hash=' + e.hash url: './deal?hash=' + e.hash
}) })
} }
} }
} }
</script> </script>
<style lang="scss"> <style lang="scss">
// 背景 // 背景
.info-back { .info-back {
position: fixed; position: fixed;
top: 0; top: 0;
left: 0; left: 0;
z-index: -1; z-index: -1;
width: 100vw; width: 100vw;
height: 100vh; height: 100vh;
background: linear-gradient(to bottom, #009B69, #00562d); background: linear-gradient(to bottom, #009B69, #00562d);
} }
// 区块信息 // 区块信息
.info-list { .info-list {
padding: 0 $padding; padding: 0 $padding;
.flex { .flex {
margin: $margin * 2 $margin/2; margin: $margin * 2 $margin/2;
background-color: white; background-color: white;
border-radius: $radius; border-radius: $radius;
padding: $padding * 2; padding: $padding * 2;
box-shadow: 0 0 2rpx 2rpx rgba($color: #000000, $alpha: .02); box-shadow: 0 0 2rpx 2rpx rgba($color: #000000, $alpha: .02);
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
.item-name { .item-name {
width: 50%; width: 50%;
font-size: $title-size; font-size: $title-size;
.icon { .icon {
width: 38rpx; width: 38rpx;
height: 38rpx; height: 38rpx;
vertical-align: middle; vertical-align: middle;
margin-bottom: 5rpx; margin-bottom: 5rpx;
margin-right: $margin; margin-right: $margin;
} }
} }
.item-label { .item-label {
width: 50%; width: 50%;
padding-left: $padding; padding-left: $padding;
text-align: right; text-align: right;
.number { .number {
font-weight: bold; font-weight: bold;
font-size: $title-size; font-size: $title-size;
} }
.unit { .unit {
font-size: $title-size-m; font-size: $title-size-m;
} }
} }
} }
} }
// 区块链信息 // 区块链信息
.chain-record, .chain-record,
.movements { .movements {
padding: $padding; padding: $padding;
.title { .title {
font-weight: bold; font-weight: bold;
text-align: center; text-align: center;
color: white; color: white;
font-size: $title-size; font-size: $title-size;
padding-bottom: $padding; padding-bottom: $padding;
} }
} }
.movements { .movements {
.chart { .chart {
background-color: white; background-color: white;
margin: $margin/2; margin: $margin/2;
height: 350rpx; height: 350rpx;
border-radius: $radius; border-radius: $radius;
} }
} }
</style> </style>

View File

@@ -1,20 +1,20 @@
<template> <template>
<view class="kline"> <view class="kline">
<l-f2 ref="chart"></l-f2> <l-f2 ref="chart"></l-f2>
</view> </view>
</template> </template>
<script> <script>
import F2 from '@/uni_modules/lime-f2/components/lime-f2/f2.min.js' import F2 from '@/uni_modules/lime-f2/components/lime-f2/f2.min.js'
import lF2 from '@/uni_modules/lime-f2/components/lime-f2/' import lF2 from '@/uni_modules/lime-f2/components/lime-f2/'
export default { export default {
components: { components: {
lF2, lF2,
}, },
data() { data() {
return { return {
} }
}, },
async mounted() { async mounted() {
let data = await this.getData() let data = await this.getData()
// 绘制K线 // 绘制K线
@@ -136,28 +136,28 @@
.shape('candle'); .shape('candle');
chart.render(); chart.render();
return chart; return chart;
}); });
}, },
methods: { methods: {
getData() { getData() {
// plus.screen.lockOrientation('landscape-primary') // plus.screen.lockOrientation('landscape-primary')
return new Promise((resolve) => { return new Promise((resolve) => {
uni.request({ uni.request({
url: 'https://gw.alipayobjects.com/os/antfincdn/c4ROEPcthk/candle-sticks.json', url: 'https://gw.alipayobjects.com/os/antfincdn/c4ROEPcthk/candle-sticks.json',
success: (res) => { success: (res) => {
resolve(res.data) resolve(res.data)
} }
}) })
}) })
} }
}, },
onUnload() { onUnload() {
console.log('222') console.log('222')
} }
} }
</script> </script>
<style lang="scss"> <style lang="scss">
.kline{ .kline{
} }
</style> </style>

View File

@@ -1,20 +1,22 @@
<template>
<template>
<view class="content"> <view class="content">
<view class="title">易品新境</view> <!-- <view class="title">易品新境</view> -->
<view class="login-top">
<view class="top-logo-content">
<image class="top-logo" fit="contain" src="/static/imgs/top_logo.png" />
链商星球(中国)
</view>
<image class="top-bg" fit="contain" src="/static/imgs/top_bg.png" />
</view>
<!-- 输入手机号相关 -->
<view class="inputs phone"> <view class="inputs phone">
<label class="label">+86</label> <label class="label">+86</label>
<input type="number" placeholder="输入您的手机号码" v-model="phone"/> <input type="number" placeholder="输入您的手机号码" v-model="phone" />
</view> </view>
<view class="inputs sms"> <view class="inputs sms">
<input type="number" placeholder="输入短信验证码" v-model="code"/> <input type="number" placeholder="输入短信验证码" v-model="code" />
<button <button class="sms-btn" type="default" size="mini" :disabled="phone == '' || getSms"
class="sms-btn" @click="getPhoneCode">{{getSms ? '重新发送' + smsTime + 's': '发送验证码'}}</button>
type="default"
size="mini"
:disabled="phone == '' || getSms"
@click="getPhoneCode"
>{{getSms ? '重新发送' + smsTime + 's': '发送验证码'}}</button>
</view> </view>
<button class="btn" type="default" :disabled="phone == '' || code == ''" @click="login">登录</button> <button class="btn" type="default" :disabled="phone == '' || code == ''" @click="login">登录</button>
<!-- 快捷登录 --> <!-- 快捷登录 -->
@@ -25,86 +27,133 @@
</view> </view>
</view> </view>
<!-- 用户登录注册协议 --> <!-- 用户登录注册协议 -->
<view class="agreement">未注册的手机号验证后将自动创建账号登录即表示同意接收<navigator url="">用户隐私规格</navigator><navigator url="">用户服务协议</navigator></view> <view class="agreement">未注册的手机号验证后将自动创建账号登录即表示同意接收<navigator url="">用户隐私规格</navigator><navigator url="">用户服务协议
</view> </navigator>
</template> </view>
</view>
</template>
<script> <script>
import { getSms, smsAuth } from '@/apis/interfaces/auth' import {
export default { getSms,
data() { smsAuth
} from '@/apis/interfaces/auth'
export default {
data() {
return { return {
phone : "18245180131", phone: "18245180131",
code : "", code: "",
smsTime : 60, smsTime: 60,
getSms : false getSms: false
} }
}, },
methods: { methods: {
// 用户登录 // 用户登录
login(){ login() {
smsAuth({ smsAuth({
mobileNo: this.phone, mobileNo: this.phone,
code : this.code code: this.code
}).then(res => { }).then(res => {
this.$store.commit('setToken', res.token_type + ' ' + res.access_token) this.$store.commit('setToken', res.token_type + ' ' + res.access_token)
if(!res.is_company){ if (!res.is_company) {
this.$Router.replace({name: "Registered"}) this.$Router.replace({
name: "Index"
})
return return
} }
this.$Router.back() this.$Router.back()
}).catch(err => { }).catch(err => {
uni.showToast({ uni.showToast({
title: err.message, title: err.message,
icon : "none" icon: "none"
}) })
}) })
}, },
// 获取验证码 // 获取验证码
getPhoneCode(){ getPhoneCode() {
let outTime let outTime
getSms({ getSms({
mobileNo: this.phone mobileNo: this.phone
}).then(res => { }).then(res => {
uni.showToast({ uni.showToast({
title: res, title: res,
icon : "none" icon: "none"
}) })
this.getSms = true this.getSms = true
outTime = setInterval(()=>{ outTime = setInterval(() => {
if(this.smsTime <= 1){ if (this.smsTime <= 1) {
this.getSms = false this.getSms = false
this.smsTime = 60 this.smsTime = 60
clearInterval('outTime') clearInterval('outTime')
} }
this.smsTime -= 1 this.smsTime -= 1
},1000) }, 1000)
}).catch(err => { }).catch(err => {
uni.showToast({ uni.showToast({
title: err.message, title: err.message,
icon : "none" icon: "none"
}) })
}) })
} }
} }
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.content{ .content {
height: 100vh; height: 100vh;
width: 100vw; width: 100vw;
padding: $padding * 3; padding: $padding * 3;
box-sizing: border-box; box-sizing: border-box;
background: white; background: white;
.inputs{
background: $border-color-lg; .login-top {
height: 36vh;
width: 100%;
display: flex;
flex-direction: row;
align-items: flex-end;
justify-content: center;
box-sizing: border-box;
position: relative;
padding-bottom: 160rpx;
.top-bg {
position: absolute;
bottom: 30rpx;
// left: 2rpx;
z-index: 2;
width: 740rpx;
margin-left: 40rpx;
}
.top-logo-content {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
box-sizing: border-box;
color: #7f56a4;
font-size: 18px;
.top-logo {
margin-bottom: 20rpx;
width: 240rpx;
height: 240rpx;
}
}
}
.inputs {
background:rgba($color: $mian-color, $alpha: 0.05);
border: solid 1rpx $border-color; border: solid 1rpx $border-color;
position: relative; position: relative;
margin-top: $margin; margin-top: $margin;
height: 80rpx; height: 80rpx;
line-height: 80rpx; line-height: 80rpx;
input{
input {
width: 100%; width: 100%;
height: 80rpx; height: 80rpx;
line-height: 80rpx; line-height: 80rpx;
@@ -113,9 +162,11 @@
box-sizing: border-box; box-sizing: border-box;
font-size: $title-size-lg; font-size: $title-size-lg;
} }
&.phone{
&.phone {
padding-left: 120rpx; padding-left: 120rpx;
.label{
.label {
position: absolute; position: absolute;
left: 0; left: 0;
top: 0; top: 0;
@@ -125,9 +176,11 @@
font-size: $title-size-lg; font-size: $title-size-lg;
} }
} }
&.sms{
&.sms {
padding-right: 200rpx; padding-right: 200rpx;
.sms-btn[size='mini']{
.sms-btn[size='mini'] {
width: 200rpx; width: 200rpx;
height: 80rpx; height: 80rpx;
line-height: 80rpx; line-height: 80rpx;
@@ -140,25 +193,29 @@
border-left: solid 1rpx $border-color; border-left: solid 1rpx $border-color;
color: $text-price; color: $text-price;
font-size: $title-size-lg; font-size: $title-size-lg;
&::after{
&::after {
border: none; border: none;
} }
&[disabled]{
&[disabled] {
color: rgba($color: $text-price, $alpha: .6); color: rgba($color: $text-price, $alpha: .6);
background: $border-color-lg; background: $border-color-lg;
} }
} }
} }
} }
.title{
.title {
text-align: center; text-align: center;
font-size: $title-size + 6; font-size: $title-size + 6;
font-weight: bold; font-weight: bold;
color: $text-color; color: $text-color;
margin-bottom: 100rpx; margin-bottom: 100rpx;
} }
.btn{
background: $text-price; .btn {
background: $mian-color;
color: white; color: white;
border-radius: 0; border-radius: 0;
margin-top: $margin; margin-top: $margin;
@@ -166,39 +223,47 @@
line-height: 90rpx; line-height: 90rpx;
height: 90rpx; height: 90rpx;
font-weight: bold; font-weight: bold;
&::after{
&::after {
border: none; border: none;
} }
&[disabled]{
background: rgba($color: $text-price, $alpha: .6); &[disabled] {
background: rgba($color: $mian-color, $alpha: .6);
} }
} }
.quick{
.quick {
padding-top: $padding * 3; padding-top: $padding * 3;
text-align: center; text-align: center;
.quick-title{
.quick-title {
text-align: center; text-align: center;
color: $text-gray; color: $text-gray;
font-size: $title-size-sm; font-size: $title-size-sm;
padding-bottom: $padding; padding-bottom: $padding;
} }
.quick-box{
.quick-box {
display: flex; display: flex;
justify-content: center; justify-content: center;
.quick-icon{
.quick-icon {
width: 78rpx; width: 78rpx;
} }
} }
} }
.agreement{
.agreement {
padding-top: $padding * 4; padding-top: $padding * 4;
font-size: $title-size-sm; font-size: $title-size-sm;
color: $text-gray; color: $text-gray;
navigator{
navigator {
color: $text-price; color: $text-price;
display: inline-block; display: inline-block;
padding: 0 10rpx; padding: 0 10rpx;
} }
} }
} }
</style> </style>

45
pages/setting/aboutUs.vue Normal file
View File

@@ -0,0 +1,45 @@
<template>
<view class="AboutUs">
<u-parse :html="content"></u-parse>
<u-toast ref="uToast" />
</view>
</template>
<script>
import {
aboutUs
} from '@/apis/interfaces/setting'
export default {
data() {
return {
content: ''
};
},
onLoad(e) {
this.getInfo()
},
methods: {
getInfo() {
aboutUs().then(res => {
this.content = res.content
}).catch(err => {
this.$refs.uToast.show({
title: err.message,
type: 'primary',
duration: 3000
})
})
}
}
}
</script>
<style lang="scss" scoped>
.AboutUs{
padding: 30rpx;
width: 100%;
min-height: 100vh;
background-color: #fff;
}
</style>

432
pages/setting/setting.vue Normal file
View File

@@ -0,0 +1,432 @@
<template>
<view class="Setting">
<!-- 更多管理 -->
<view class="list">
<!-- 修改头像 -->
<view class="list-item" @click="updImgs">
<view class="list-item-left">
<image src="/static/imgs/user-avatar.png" mode="widthFix" />
<span>修改头像</span>
</view>
<view class="avatar">
<image :src="avatar.showPath?avatar.showPath:'/static/imgs/no-avatar.png'" mode="aspectFill" />
<u-icon name="arrow-right" color="#f1f1f1" size="28" />
</view>
</view>
<!-- 修改昵称 -->
<view class="list-item">
<view class="list-item-left">
<image src="/static/imgs/mine-self-name.png" mode="widthFix" />
<span>修改昵称</span>
</view>
<view class="input">
<input type="text" :value="nickname" @blur='blur' placeholder="请输入用户的昵称" maxlength="12" />
<u-icon name="arrow-right" color="#f1f1f1" size="28" />
</view>
</view>
<!-- 绑定微信 -->
<button class="list-item" @click="getUser" v-if="false">
<view class="list-item-left">
<image src="/static/imgs/link-wechat.png" mode="widthFix" />
<span>绑定微信</span>
</view>
<u-icon name="arrow-right" color="#f1f1f1" size="28" />
</button>
<!-- 个人认证 -->
<view @click="certification(is_certification)" class="list-item">
<view class="list-item-left">
<image src="/static/imgs/self-icon.png" mode="widthFix" />
<span>个人认证</span>
</view>
<u-icon name="arrow-right" color="#f1f1f1" size="28" />
</view>
<!-- 企业认证 -->
<view @click="company(is_company)" class="list-item">
<view class="list-item-left">
<image src="/static/imgs/company-icon.png" mode="widthFix" />
<span>企业认证</span>
</view>
<u-icon name="arrow-right" color="#f1f1f1" size="28" />
</view>
<!-- 关于我们 -->
<view @click="$router.push({name:'aboutUs'})" class="list-item">
<view class="list-item-left">
<image src="/static/imgs/mine-about.png" mode="widthFix" />
<span>关于链商星球</span>
</view>
<u-icon name="arrow-right" color="#f1f1f1" size="28" />
</view>
<!-- 切换账号 -->
<view @click="loginOut" class="list-item">
<view class="list-item-left">
<image src="/static/imgs/reset-info.png" mode="widthFix" />
<span>切换账户</span>
</view>
<u-icon name="arrow-right" color="#f1f1f1" size="28" />
</view>
</view>
<view class="edition">
链商星球 beta 1.0.0
</view>
<!-- 底部版本 -->
<u-toast ref="uToast" />
</view>
</template>
<script>
import {
wechatbind,
resetUserInfo,
getUserSettingInfo
} from '@/apis/interfaces/setting'
import {
uploads
} from '@/apis/interfaces/uploading'
export default {
name: 'Setting',
data() {
return {
canLogin: true,
nickname: '',
avatar: {
path: '',
showPath: ''
},
is_bind: true, // 微信绑定
is_certification: true, // 个人认证
is_company: true, // 企业认证
}
},
onShow() {
wx.login({
success: res => {
this.loginCode = res.code
}
})
this.getUserInfo()
},
onPullDownRefresh() {
this.getUserInfo()
},
methods: {
// 是否个人认证
certification(is_certfication) {
console.log(is_certfication)
if (is_certfication) {
// 跳转到个人认证信息完成展示页面
this.$router.push({
name: ''
})
} else {
// 跳转到个人认证信息页面
this.$router.push({
name: ''
})
}
},
// 是否展示企业信息
company(is_company) {
console.log(is_company)
if (is_company) {
// 跳转到企业认证完成信息展示页面
this.$router.push({
name: ''
})
} else {
// 跳转到企业认证页面
this.$router.push({
name: ''
})
}
},
// 获取当前用户得基本信息
getUserInfo() {
getUserSettingInfo().then(res => {
this.avatar.showPath = res.avatar
this.nickname = res.nickname
this.is_bind = res.is_bind
this.is_certification = res.is_certification
this.is_company = res.is_company
uni.stopPullDownRefresh()
}).catch(err => {
this.$refs.uToast.show({
title: err.message,
type: 'primary',
duration: 3000
})
})
},
// 点击绑定用户得授权信息,且绑定带修改
getUser() {
uni.getUserProfile({
desc: "获取你的昵称、头像、地区及性别",
success: e => {
if (e.errMsg == "getUserProfile:ok") {
this.userInfo = e.userInfo
// // 检查用户登录Code是否过期
wx.checkSession({
success: res => {
this.userLogin(e)
},
fail: err => {
// 登录过期重新获取code
uni.login({
success: res => {
this.loginCode = res.code
// 登录
this.userLogin()
}
})
}
})
} else {
uni.showToast({
duration: 1500,
title: "绑定手机号失败了",
icon: 'none'
})
}
},
fail() {
uni.showToast({
duration: 1500,
title: "您拒绝了请求",
icon: 'none'
})
}
})
},
// 登陆接口
userLogin(info) {
let that = this
uni.login({
success: res => {
let data = {
iv: info.iv,
encryptedData: info.encryptedData,
code: res.code
}
uni.showLoading({
title: '绑定中'
})
wechatbind(data).then(res => {
setTimeout(res => {
uni.hideLoading()
}, 1000)
this.$refs.uToast.show({
title: '绑定成功',
type: 'primary',
duration: 3000
})
setTimeout(res => {
this.getUserInfo()
}, 3000)
}).catch(err => {
this.$refs.uToast.show({
title: err.message,
type: 'primary',
duration: 3000
})
uni.hideLoading()
})
}
});
},
loginOut() {
uni.removeStorageSync('token')
uni.reLaunch({
url: '/pages/login/login'
})
},
// 上传头像
updImgs(type) {
uni.chooseImage({
success: res => {
let path = res.tempFiles.map((val, index) => {
return {
name: 'uploads' + index,
uri: val.path
}
})
uploads(path).then(pathRes => {
this.avatar.path = pathRes.path[0]
this.avatar.showPath = pathRes.url[0]
this.resetUserInfo('avatar', pathRes.url[0])
}).catch(err => {
uni.showToast({
title: err.message,
icon: 'none'
})
})
}
})
},
// 修改姓名
blur(e) {
let value = e.detail.value
if (value !== this.nickname) {
this.resetUserInfo('nickname', value)
}
},
// 修改头像或昵称
resetUserInfo(key, value) {
let data = {
key: key,
value: value
}
resetUserInfo(data).then(res => {
console.log(res, 'res...')
uni.showToast({
title: res,
icon: 'none'
})
setTimeout(res => {
this.getUserInfo()
}, 2000)
}).catch(err => {
uni.showToast({
title: err.message,
icon: 'none'
})
})
}
}
}
</script>
<style lang="scss" scoped>
.Setting {
width: 100vw;
min-height: 100vh;
position: relative;
background-color: #fff;
// 版本
.edition {
color: #cacaca;
text-align: center;
padding: 20rpx 30rpx;
}
// 更多管理
.list {
display: flex;
flex-direction: column;
align-items: flex-start;
justify-content: flex-start;
box-sizing: border-box;
position: relative;
top: -10rpx;
border-radius: 20rpx;
margin: 0 40rpx;
padding: 30rpx 0;
width: calc(100% - 80rpx);
button::after {
border: none;
background-color: none;
}
button {
position: relative;
display: block;
margin-left: auto;
margin-right: auto;
padding-left: 0;
padding-right: 0;
box-sizing: border-box;
font-size: $title-size *0.9;
text-align: center;
text-decoration: none;
line-height: 1;
border-radius: 5px;
-webkit-tap-highlight-color: transparent;
overflow: hidden;
color: #333;
background-color: #fff;
}
.list-item {
width: 100%;
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
padding: 40rpx 0;
border-bottom: solid 1rpx #f7f7f7;
box-sizing: border-box;
.avatar {
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
box-sizing: border-box;
image {
width: 100rpx;
height: 100rpx;
border-radius: 50%;
margin-right: 20rpx;
}
}
.input {
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
box-sizing: border-box;
text-align: right;
flex: 1;
input {
padding-right: 30rpx;
width: 100%;
}
}
.list-item-left {
display: flex;
flex-direction: row;
align-items: center;
justify-content: flex-start;
box-sizing: border-box;
image {
width: 44rpx;
height: 44rpx;
}
span {
margin-left: 30rpx;
}
}
}
}
// 底部轮播图跳转到其他app
.mine-banner {
position: relative;
width: calc(100% - 80rpx);
top: -20rpx;
margin: 0 40rpx;
box-sizing: border-box;
margin-top: $margin*2;
}
}
.loginOut {
margin: 30rpx 50rpx;
background-color: #fff;
box-shadow: 0 0 20rpx 4rpx rgba($color: $mian-color, $alpha: 0.1);
text-align: center;
padding: 20rpx;
border-radius: 10rpx;
color: #353535;
}
</style>

View File

@@ -8,6 +8,7 @@
<view class="item" @click="$Router.push({name: 'instrumentCustomer'})">成交客户</view> <view class="item" @click="$Router.push({name: 'instrumentCustomer'})">成交客户</view>
<view class="item" @click="$Router.push({name: 'Personal'})">个人认证</view> <view class="item" @click="$Router.push({name: 'Personal'})">个人认证</view>
<view class="item" @click="$Router.push({name: 'instrumentBasics'})">企业认证</view> <view class="item" @click="$Router.push({name: 'instrumentBasics'})">企业认证</view>
<view class="item" @click="$Router.push({name: 'setting'})">设置中心</view>
</view> </view>
</view> </view>
</template> </template>

View File

@@ -1,9 +1,9 @@
/** /**
* Web唐明明 * Web唐明明
* 匆匆数载恍如梦,岁月迢迢华发增。 * 匆匆数载恍如梦,岁月迢迢华发增。
* 碌碌无为枉半生,一朝惊醒万事空。 * 碌碌无为枉半生,一朝惊醒万事空。
* moduleName: 日期 * moduleName: 日期
*/ */
export default getDate = (type) =>{ export default getDate = (type) =>{

View File

@@ -1,16 +1,16 @@
/** /**
* Web唐明明 * Web唐明明
* 匆匆数载恍如梦,岁月迢迢华发增。 * 匆匆数载恍如梦,岁月迢迢华发增。
* 碌碌无为枉半生,一朝惊醒万事空。 * 碌碌无为枉半生,一朝惊醒万事空。
* moduleName: 登录 * moduleName: 登录
*/ */
import { router } from '../router' import { router } from '../router'
import { keyAuth } from '../apis/interfaces/auth' import { keyAuth } from '../apis/interfaces/auth'
import store from '../store' import store from '../store'
class userAuth { class userAuth {
constructor() { constructor() {
this.univerfyConfig = { this.univerfyConfig = {
fullScreen : true, fullScreen : true,
@@ -130,6 +130,6 @@ class userAuth {
updAuthToken(){ updAuthToken(){
} }
} }
export default userAuth export default userAuth

View File

@@ -10,7 +10,7 @@ $text-color: #333;
$text-gray: #555; $text-gray: #555;
$text-gray-m: #999; $text-gray-m: #999;
$text-price: #8b64fd; $text-price: #8b64fd;
$mian-color: #8b64fd; $mian-color: #b11eff;
$mian-color-deep: #824f9a; $mian-color-deep: #824f9a;
// 边框颜色 // 边框颜色

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

BIN
static/imgs/link-wechat.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 956 B

BIN
static/imgs/mine-about.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

BIN
static/imgs/no-avatar.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

BIN
static/imgs/reset-info.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 866 B

BIN
static/imgs/self-icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

BIN
static/imgs/top_bg.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

BIN
static/imgs/top_logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

BIN
static/imgs/user-avatar.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 930 B

View File

@@ -6,18 +6,18 @@
## [代码示例http://liangei.gitee.io/limeui/#/f2-example](http://liangei.gitee.io/limeui/#/f2-example) ## [代码示例http://liangei.gitee.io/limeui/#/f2-example](http://liangei.gitee.io/limeui/#/f2-example)
## 0.4.92021-05-12 ## 0.4.92021-05-12
- fix: 修复 百度平台 多个图表时 只生效一个的bug - fix: 修复 百度平台 多个图表时 只生效一个的bug
## 0.4.82021-05-10 ## 0.4.82021-05-10
- feat: 增加 `destroy` 方法,用于销毁实例 - feat: 增加 `destroy` 方法,用于销毁实例
- feat: 增加 `canvasToTempFilePath` 方法,用于生成图片 - feat: 增加 `canvasToTempFilePath` 方法,用于生成图片
```js ```js
this.$refs.chart.canvasToTempFilePath({success: res => { this.$refs.chart.canvasToTempFilePath({success: res => {
console.log('tempFilePath:', res.tempFilePath) console.log('tempFilePath:', res.tempFilePath)
}}) }})
``` ```
## [代码示例http://liangei.gitee.io/limeui/#/f2-example](http://liangei.gitee.io/limeui/#/f2-example) ## [代码示例http://liangei.gitee.io/limeui/#/f2-example](http://liangei.gitee.io/limeui/#/f2-example)
## 0.4.72021-05-10 ## 0.4.72021-05-10
- chore: F2 版本更新至 3.8.7 - chore: F2 版本更新至 3.8.7
## 0.4.62021-05-05 ## 0.4.62021-05-05
- docs: nvue 使用文档更新 - docs: nvue 使用文档更新
## [代码示例http://liangei.gitee.io/limeui/#/f2-example](http://liangei.gitee.io/limeui/#/f2-example) ## [代码示例http://liangei.gitee.io/limeui/#/f2-example](http://liangei.gitee.io/limeui/#/f2-example)

View File

@@ -1,121 +1,121 @@
import { import {
pixelRatio, pixelRatio,
sleep sleep
} from './utils'; } from './utils';
const UNI_CANVAS_CONTEXT_MAP = { const UNI_CANVAS_CONTEXT_MAP = {
// #ifndef MP-WEIXIN // #ifndef MP-WEIXIN
fillStyle: 'FillStyle', fillStyle: 'FillStyle',
fontSize: 'FontSize', fontSize: 'FontSize',
globalAlpha: 'GlobalAlpha', globalAlpha: 'GlobalAlpha',
opacity: 'GlobalAlpha', opacity: 'GlobalAlpha',
lineCap: 'LineCap', lineCap: 'LineCap',
lineJoin: 'LineJoin', lineJoin: 'LineJoin',
lineWidth: 'LineWidth', lineWidth: 'LineWidth',
miterLimit: 'MiterLimit', miterLimit: 'MiterLimit',
strokeStyle: 'StrokeStyle', strokeStyle: 'StrokeStyle',
textAlign: 'TextAlign', textAlign: 'TextAlign',
textBaseline: 'TextBaseline', textBaseline: 'TextBaseline',
shadow: 'Shadow', shadow: 'Shadow',
// #endif // #endif
// #ifdef MP-TOUTIAO || H5 || APP-PLUS // #ifdef MP-TOUTIAO || H5 || APP-PLUS
font: 'FontSize', font: 'FontSize',
// #endif // #endif
}; };
function strLen(str) { function strLen(str) {
let len = 0; let len = 0;
for (let i = 0; i < str.length; i++) { for (let i = 0; i < str.length; i++) {
if (str.charCodeAt(i) > 0 && str.charCodeAt(i) < 128) { if (str.charCodeAt(i) > 0 && str.charCodeAt(i) < 128) {
len++; len++;
} else { } else {
len += 2; len += 2;
} }
} }
return len; return len;
} }
// 头条小程序目前仅支持 setFontSize // 头条小程序目前仅支持 setFontSize
// f2 会将所有属性整合为 font 简写,从中提取 fontSize 支持 // f2 会将所有属性整合为 font 简写,从中提取 fontSize 支持
const fontSizeReg = /(\d*\.?\d*)px/; const fontSizeReg = /(\d*\.?\d*)px/;
const colorReg = /#([0-9a-fA-F])([0-9a-fA-F])([0-9a-fA-F])\b/g; const colorReg = /#([0-9a-fA-F])([0-9a-fA-F])([0-9a-fA-F])\b/g;
export default (ctx) => { export default (ctx) => {
// #ifdef H5 || APP-PLUS // #ifdef H5 || APP-PLUS
ctx.uniTransform = ctx.transform ctx.uniTransform = ctx.transform
ctx.transform = (...agrs) => { ctx.transform = (...agrs) => {
if (ctx.draw && agrs[6]) { if (ctx.draw && agrs[6]) {
agrs[4] *= pixelRatio agrs[4] *= pixelRatio
agrs[5] *= pixelRatio agrs[5] *= pixelRatio
} }
if (agrs.length > 6) { if (agrs.length > 6) {
agrs.pop() agrs.pop()
} }
ctx.uniTransform(...agrs) ctx.uniTransform(...agrs)
} }
// #endif // #endif
// #ifdef MP-ALIPAY // #ifdef MP-ALIPAY
ctx.canvasGetImageData = ctx.getImageData ctx.canvasGetImageData = ctx.getImageData
ctx.getImageData = null ctx.getImageData = null
// #endif // #endif
if (!ctx.getImageData) { if (!ctx.getImageData) {
ctx.getImageData = (...agrs) => { ctx.getImageData = (...agrs) => {
const [x, y, width, height] = agrs const [x, y, width, height] = agrs
return new Promise(resolve => { return new Promise(resolve => {
const parms = { const parms = {
canvasId: ctx.id || ctx.canvasId, canvasId: ctx.id || ctx.canvasId,
x, x,
y, y,
width, width,
height, height,
success: res => { success: res => {
resolve(res.data) resolve(res.data)
} }
} }
// #ifndef MP-ALIPAY || MP-TOUTIAO // #ifndef MP-ALIPAY || MP-TOUTIAO
uni.canvasGetImageData(parms) uni.canvasGetImageData(parms)
// #endif // #endif
// #ifdef MP-ALIPAY || MP-TOUTIAO // #ifdef MP-ALIPAY || MP-TOUTIAO
ctx.canvasGetImageData(parms) ctx.canvasGetImageData(parms)
// #endif // #endif
}) })
} }
} }
// 钉钉小程序框架不支持 measureText 方法,用此方法 mock // 钉钉小程序框架不支持 measureText 方法,用此方法 mock
if (!ctx.measureText) { if (!ctx.measureText) {
ctx.measureText = text => { ctx.measureText = text => {
let fontSize = 12; let fontSize = 12;
const font = ctx.__font; const font = ctx.__font;
if (font) { if (font) {
fontSize = parseInt(font.split(' ')[3], 10); fontSize = parseInt(font.split(' ')[3], 10);
} }
fontSize /= 2; fontSize /= 2;
return { return {
width: strLen(text) * fontSize width: strLen(text) * fontSize
}; };
} }
} }
Object.keys(UNI_CANVAS_CONTEXT_MAP).forEach(key => { Object.keys(UNI_CANVAS_CONTEXT_MAP).forEach(key => {
Object.defineProperty(ctx, key, { Object.defineProperty(ctx, key, {
set(val) { set(val) {
const name = `set${UNI_CANVAS_CONTEXT_MAP[key]}`; const name = `set${UNI_CANVAS_CONTEXT_MAP[key]}`;
if (!ctx[name]) { if (!ctx[name]) {
return; return;
} }
if (key === 'font' && fontSizeReg.test(val)) { if (key === 'font' && fontSizeReg.test(val)) {
const match = fontSizeReg.exec(val); const match = fontSizeReg.exec(val);
ctx[name](match[1]); ctx[name](match[1]);
return; return;
} }
if (key === 'shadow' && Array.isArray(val)) { if (key === 'shadow' && Array.isArray(val)) {
ctx[name](...val); ctx[name](...val);
return; return;
} }
if(colorReg.test(val)) { if(colorReg.test(val)) {
val = val.replace(colorReg, '#$1$1$2$2$3$3') val = val.replace(colorReg, '#$1$1$2$2$3$3')
} }
ctx[name](val); ctx[name](val);
} }
}); });
}); });
return ctx return ctx
} }

View File

@@ -1,417 +1,417 @@
<template> <template>
<view class="l-f2" :style="customStyle" v-if="canvasId"> <view class="l-f2" :style="customStyle" v-if="canvasId">
<!-- #ifndef APP-NVUE --> <!-- #ifndef APP-NVUE -->
<cover-view class="l-f2__mask" v-if="isMask"></cover-view> <cover-view class="l-f2__mask" v-if="isMask"></cover-view>
<canvas <canvas
class="l-f2__canvas" class="l-f2__canvas"
v-if="use2dCanvas" v-if="use2dCanvas"
type="2d" type="2d"
:id="canvasId" :id="canvasId"
:style="'width:' + width + 'px;height:' + height + 'px'" :style="'width:' + width + 'px;height:' + height + 'px'"
:disable-scroll="isDisableScroll" :disable-scroll="isDisableScroll"
@touchstart="touchStart" @touchstart="touchStart"
@touchmove="touchMove" @touchmove="touchMove"
@touchend="touchEnd" @touchend="touchEnd"
/> />
<canvas <canvas
class="l-f2__canvas" class="l-f2__canvas"
v-else v-else
:width="nodeWidth" :width="nodeWidth"
:height="nodeHeight" :height="nodeHeight"
:style="'width:' + width + 'px;height:' + height + 'px'" :style="'width:' + width + 'px;height:' + height + 'px'"
:canvas-id="canvasId" :canvas-id="canvasId"
:id="canvasId" :id="canvasId"
:disable-scroll="isDisableScroll" :disable-scroll="isDisableScroll"
@touchstart="touchStart" @touchstart="touchStart"
@touchmove="touchMove" @touchmove="touchMove"
@touchend="touchEnd" @touchend="touchEnd"
/> />
<view v-if="isCloud" style="width:2048px; height:2048px; position: fixed; left: 9999px;"> <view v-if="isCloud" style="width:2048px; height:2048px; position: fixed; left: 9999px;">
<canvas v-if="use2dCanvas" type="2d" :canvas-id="canvasId + '_cloud'" :id="canvasId + '_cloud'" class="l-f2__canvas"></canvas> <canvas v-if="use2dCanvas" type="2d" :canvas-id="canvasId + '_cloud'" :id="canvasId + '_cloud'" class="l-f2__canvas"></canvas>
<canvas v-else :canvas-id="canvasId + '_cloud'" :id="canvasId + '_cloud'" class="l-f2__canvas"></canvas> <canvas v-else :canvas-id="canvasId + '_cloud'" :id="canvasId + '_cloud'" class="l-f2__canvas"></canvas>
</view> </view>
<!-- #endif --> <!-- #endif -->
<!-- #ifdef APP-NVUE --> <!-- #ifdef APP-NVUE -->
<web-view <web-view
class="l-f2__canvas" class="l-f2__canvas"
:id="canvasId" :id="canvasId"
ref="webview" ref="webview"
:webviewStyles="webviewStyles" :webviewStyles="webviewStyles"
src="http://liangei.gitee.io/limeui/hybrid/html/lime-ui/lime-f2/index.html?v=0.4.8" src="http://liangei.gitee.io/limeui/hybrid/html/lime-ui/lime-f2/index.html?v=0.4.8"
@pagefinish="isFinish = true" @pagefinish="isFinish = true"
@onPostMessage="onMessage" @onPostMessage="onMessage"
></web-view> ></web-view>
<!-- #endif --> <!-- #endif -->
</view> </view>
</template> </template>
<script> <script>
// #ifndef APP-NVUE // #ifndef APP-NVUE
import extendContext from './canvas'; import extendContext from './canvas';
import { compareVersion, wrapEvent, pixelRatio } from './utils'; import { compareVersion, wrapEvent, pixelRatio } from './utils';
// #endif // #endif
// #ifdef APP-NVUE // #ifdef APP-NVUE
import { base64ToPath } from './utils'; import { base64ToPath } from './utils';
// #endif // #endif
export default { export default {
// version: '0.5.1' // version: '0.5.1'
name: 'l-f2', name: 'l-f2',
props: { props: {
// #ifdef MP-WEIXIN || MP-TOUTIAO // #ifdef MP-WEIXIN || MP-TOUTIAO
type: { type: {
type: String, type: String,
default: '2d' default: '2d'
}, },
// #endif // #endif
// #ifdef APP-NVUE // #ifdef APP-NVUE
webviewStyles: Object, webviewStyles: Object,
params: { params: {
type: Object, type: Object,
default: () => {} default: () => {}
}, },
// #endif // #endif
customStyle: String, customStyle: String,
imageMask: String, imageMask: String,
source: { source: {
type: Array, type: Array,
default: () => [] default: () => []
}, },
isAutoPlay: Boolean, isAutoPlay: Boolean,
isDisableScroll: Boolean, isDisableScroll: Boolean,
isCloud: Boolean, isCloud: Boolean,
onInit: { onInit: {
type: [Function, Object], type: [Function, Object],
default: () => {} default: () => {}
} }
}, },
data() { data() {
return { return {
// #ifdef MP-WEIXIN || MP-TOUTIAO // #ifdef MP-WEIXIN || MP-TOUTIAO
use2dCanvas: true, use2dCanvas: true,
// #endif // #endif
// #ifndef MP-WEIXIN || MP-TOUTIAO // #ifndef MP-WEIXIN || MP-TOUTIAO
use2dCanvas: false, use2dCanvas: false,
// #endif // #endif
// #ifndef APP-NVUE // #ifndef APP-NVUE
width: null, width: null,
height: null, height: null,
nodeWidth: null, nodeWidth: null,
nodeHeight: null, nodeHeight: null,
isMask: false, isMask: false,
isInited: false, isInited: false,
imageData: null, imageData: null,
config: {}, config: {},
// #endif // #endif
// #ifdef APP-NVUE // #ifdef APP-NVUE
isFinish: false, isFinish: false,
file: '' file: ''
// #endif // #endif
}; };
}, },
computed: { computed: {
canvasId() { canvasId() {
return `l-f2${this._uid}`; return `l-f2${this._uid}`;
} }
}, },
watch: { watch: {
isAutoPlay(val) { isAutoPlay(val) {
if (val) { if (val) {
this.changeData(this.source); this.changeData(this.source);
} }
}, },
source: { source: {
handler: function(data) { handler: function(data) {
if (this.isAutoPlay) { if (this.isAutoPlay) {
this.changeData(data); this.changeData(data);
} }
}, },
deep: true deep: true
} }
}, },
beforeDestroy() { beforeDestroy() {
this.clear(); this.clear();
this.destroy(); this.destroy();
}, },
created() { created() {
this.isMask = this.isCloud && this.imageMask; this.isMask = this.isCloud && this.imageMask;
// #ifdef MP-WEIXIN || MP-TOUTIAO // #ifdef MP-WEIXIN || MP-TOUTIAO
const { SDKVersion, version, platform, environment } = uni.getSystemInfoSync(); const { SDKVersion, version, platform, environment } = uni.getSystemInfoSync();
// #endif // #endif
// #ifdef MP-WEIXIN // #ifdef MP-WEIXIN
this.use2dCanvas = this.type === '2d' && compareVersion(SDKVersion, '2.9.2') >= 0 && !((/ios/i.test(platform) && /7.0.20/.test(version)) || /wxwork/i.test(environment)); this.use2dCanvas = this.type === '2d' && compareVersion(SDKVersion, '2.9.2') >= 0 && !((/ios/i.test(platform) && /7.0.20/.test(version)) || /wxwork/i.test(environment));
// #endif // #endif
// #ifdef MP-TOUTIAO // #ifdef MP-TOUTIAO
this.use2dCanvas = this.type === '2d' && compareVersion(SDKVersion, '1.78.0') >= 0; this.use2dCanvas = this.type === '2d' && compareVersion(SDKVersion, '1.78.0') >= 0;
// #endif // #endif
}, },
async mounted() { async mounted() {
if (this.onInit) { if (this.onInit) {
this.init(this.onInit); this.init(this.onInit);
} }
}, },
methods: { methods: {
// #ifdef APP-NVUE // #ifdef APP-NVUE
onMessage(e) { onMessage(e) {
const res = e?.detail?.data[0] || null; const res = e?.detail?.data[0] || null;
if (res?.event) { if (res?.event) {
this.$emit(res.event, JSON.parse(res.data)); this.$emit(res.event, JSON.parse(res.data));
} else if (res?.file) { } else if (res?.file) {
this.file = res.data; this.file = res.data;
} else { } else {
console.error(res); console.error(res);
} }
}, },
// #endif // #endif
async init(func, params = null) { async init(func, params = null) {
// #ifdef APP-NVUE // #ifdef APP-NVUE
this.$watch( this.$watch(
'isFinish', 'isFinish',
(n, o) => { (n, o) => {
(n || o) && (params || this.params) && this.$refs.webview.evalJs(`init(${JSON.stringify(func.toString())}, ${JSON.stringify(params || this.params)})`); (n || o) && (params || this.params) && this.$refs.webview.evalJs(`init(${JSON.stringify(func.toString())}, ${JSON.stringify(params || this.params)})`);
this.isInited = true; this.isInited = true;
}, },
{ {
immediate: true immediate: true
} }
); );
// #endif // #endif
// #ifndef APP-NVUE // #ifndef APP-NVUE
let config = await this.getContext(this.canvasId); let config = await this.getContext(this.canvasId);
if (this.isCloud) { if (this.isCloud) {
let imageMask = null; let imageMask = null;
if (this.imageMask) { if (this.imageMask) {
this.isMask = true; this.isMask = true;
imageMask = await this.getImageMask(config); imageMask = await this.getImageMask(config);
this.imageData = imageMask; this.imageData = imageMask;
this.isMask = false; this.isMask = false;
} }
let cloud = await this.getContext(this.canvasId + '_cloud'); let cloud = await this.getContext(this.canvasId + '_cloud');
config = Object.assign({}, config, { cloud, imageMask }); config = Object.assign({}, config, { cloud, imageMask });
} }
const chart = await func(config); const chart = await func(config);
if (chart) { if (chart) {
// #ifdef H5 || APP-PLUS // #ifdef H5 || APP-PLUS
chart.repaint(); chart.repaint();
// #endif // #endif
this.chart = chart; this.chart = chart;
this.canvasEl = chart.get('el'); this.canvasEl = chart.get('el');
this.isInited = true; this.isInited = true;
} }
// #endif // #endif
}, },
changeData(data) { changeData(data) {
// #ifndef APP-NVUE // #ifndef APP-NVUE
if (this.chart) { if (this.chart) {
this.chart.changeData(data || this.source); this.chart.changeData(data || this.source);
} }
// #endif // #endif
// #ifdef APP-NVUE // #ifdef APP-NVUE
this.$refs.webview.evalJs(`changeData(${JSON.stringify(data || this.source)})`); this.$refs.webview.evalJs(`changeData(${JSON.stringify(data || this.source)})`);
// #endif // #endif
}, },
clear() { clear() {
// #ifndef APP-NVUE // #ifndef APP-NVUE
if (this.chart) { if (this.chart) {
this.chart.clear(); this.chart.clear();
} }
// #endif // #endif
// #ifdef APP-NVUE // #ifdef APP-NVUE
this.$refs.webview.evalJs(`clear()`); this.$refs.webview.evalJs(`clear()`);
// #endif // #endif
}, },
destroy() { destroy() {
// #ifndef APP-NVUE // #ifndef APP-NVUE
if (this.chart) { if (this.chart) {
this.chart.destroy(); this.chart.destroy();
} }
// #endif // #endif
// #ifdef APP-NVUE // #ifdef APP-NVUE
this.$refs.webview.evalJs(`destroy()`); this.$refs.webview.evalJs(`destroy()`);
// #endif // #endif
}, },
repaint() { repaint() {
this.changeData(this.source); this.changeData(this.source);
}, },
reset(func, params = null) { reset(func, params = null) {
// #ifndef APP-NVUE // #ifndef APP-NVUE
this.$watch( this.$watch(
'isInited', 'isInited',
v => v && func(this.chart), v => v && func(this.chart),
{ {
immediate: true immediate: true
} }
); );
// #endif // #endif
// #ifdef APP-NVUE // #ifdef APP-NVUE
this.$refs.webview.evalJs(`reset(${JSON.stringify(func.toString())}, ${JSON.stringify(params || this.params)})`); this.$refs.webview.evalJs(`reset(${JSON.stringify(func.toString())}, ${JSON.stringify(params || this.params)})`);
// #endif // #endif
}, },
canvasToTempFilePath(args = {}) { canvasToTempFilePath(args = {}) {
// #ifndef APP-NVUE // #ifndef APP-NVUE
const { use2dCanvas, canvasId, config } = this; const { use2dCanvas, canvasId, config } = this;
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const copyArgs = Object.assign( const copyArgs = Object.assign(
{ {
canvasId, canvasId,
success: resolve, success: resolve,
fail: reject fail: reject
}, },
args args
); );
if (use2dCanvas) { if (use2dCanvas) {
let { canvas } = config[canvasId]; let { canvas } = config[canvasId];
delete copyArgs.canvasId; delete copyArgs.canvasId;
copyArgs.canvas = canvas; copyArgs.canvas = canvas;
} }
uni.canvasToTempFilePath(copyArgs, this); uni.canvasToTempFilePath(copyArgs, this);
}); });
// #endif // #endif
// #ifdef APP-NVUE // #ifdef APP-NVUE
this.file = ''; this.file = '';
this.$refs.webview.evalJs(`canvasToTempFilePath()`); this.$refs.webview.evalJs(`canvasToTempFilePath()`);
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
this.$watch('file', async file => { this.$watch('file', async file => {
if (file) { if (file) {
const tempFilePath = await base64ToPath(file); const tempFilePath = await base64ToPath(file);
resolve(args.success({ tempFilePath })); resolve(args.success({ tempFilePath }));
} else { } else {
reject(args.fail({ error: `` })); reject(args.fail({ error: `` }));
} }
}); });
}); });
// #endif // #endif
}, },
// #ifndef APP-NVUE // #ifndef APP-NVUE
getImageMask(config) { getImageMask(config) {
return new Promise(resolve => { return new Promise(resolve => {
uni.getImageInfo({ uni.getImageInfo({
src: this.imageMask, src: this.imageMask,
success: async res => { success: async res => {
if (res.path) { if (res.path) {
// #ifdef MP-WEIXIN || MP-BAIDU || MP-QQ || MP-TOUTIAO // #ifdef MP-WEIXIN || MP-BAIDU || MP-QQ || MP-TOUTIAO
const localReg = /^\.|^\/(?=[^\/])/; const localReg = /^\.|^\/(?=[^\/])/;
res.path = localReg.test(this.imageMask) ? `/${res.path}` : res.path; res.path = localReg.test(this.imageMask) ? `/${res.path}` : res.path;
// #endif // #endif
const { context, width, height, canvas } = config; const { context, width, height, canvas } = config;
if (this.use2dCanvas) { if (this.use2dCanvas) {
const imageMask = () => { const imageMask = () => {
const imageMask = canvas.createImage(); const imageMask = canvas.createImage();
imageMask.crossOrigin = ''; imageMask.crossOrigin = '';
imageMask.src = res.path; imageMask.src = res.path;
imageMask.onload = async () => { imageMask.onload = async () => {
context.drawImage(imageMask, 0, 0, res.width, res.height, 0, 0, width, height); context.drawImage(imageMask, 0, 0, res.width, res.height, 0, 0, width, height);
const imageData = context.getImageData(0, 0, width, height).data; const imageData = context.getImageData(0, 0, width, height).data;
context.clearRect(0, 0, width, height); context.clearRect(0, 0, width, height);
resolve(imageData); resolve(imageData);
}; };
}; };
imageMask(); imageMask();
} else { } else {
// #ifndef MP-BAIDU // #ifndef MP-BAIDU
context.drawImage(res.path, 0, 0, res.width, res.height, 0, 0, width, height); context.drawImage(res.path, 0, 0, res.width, res.height, 0, 0, width, height);
// #endif // #endif
// #ifdef MP-BAIDU // #ifdef MP-BAIDU
context.drawImage(res.path, 0, 0, width, height, 0, 0, res.width, res.height); context.drawImage(res.path, 0, 0, width, height, 0, 0, res.width, res.height);
// #endif // #endif
await this.canvasDraw(context); await this.canvasDraw(context);
const imageData = await context.getImageData(0, 0, width, height); const imageData = await context.getImageData(0, 0, width, height);
context.clearRect(0, 0, width, height); context.clearRect(0, 0, width, height);
await this.canvasDraw(context); await this.canvasDraw(context);
resolve(imageData); resolve(imageData);
} }
} }
}, },
fail(err) { fail(err) {
console.error(JSON.stringify(err)); console.error(JSON.stringify(err));
resolve(null); resolve(null);
} }
}); });
}); });
}, },
canvasDraw(ctx) { canvasDraw(ctx) {
return new Promise(resolve => { return new Promise(resolve => {
ctx.draw(false, () => { ctx.draw(false, () => {
setTimeout(() => { setTimeout(() => {
resolve(true); resolve(true);
}, 100); }, 100);
}); });
}); });
}, },
getContext(canvasId) { getContext(canvasId) {
const { use2dCanvas, type = '2d', config } = this; const { use2dCanvas, type = '2d', config } = this;
if (config[canvasId]?.context) { if (config[canvasId]?.context) {
return Promise.resolve(config[canvasId]); return Promise.resolve(config[canvasId]);
} }
if (use2dCanvas) { if (use2dCanvas) {
return new Promise(resolve => { return new Promise(resolve => {
uni.createSelectorQuery() uni.createSelectorQuery()
.in(this) .in(this)
.select(`#${canvasId}`) .select(`#${canvasId}`)
.fields({ .fields({
node: true, node: true,
size: true size: true
}) })
.exec(res => { .exec(res => {
let { node, width, height } = res[0]; let { node, width, height } = res[0];
width = width || 300; width = width || 300;
height = height || 300; height = height || 300;
const context = node.getContext(type); const context = node.getContext(type);
if (!canvasId.includes('_cloud')) { if (!canvasId.includes('_cloud')) {
this.width = width; this.width = width;
this.height = height; this.height = height;
} }
node.width = width * pixelRatio; node.width = width * pixelRatio;
node.height = height * pixelRatio; node.height = height * pixelRatio;
this.config[canvasId] = { context: extendContext(context), width, height, pixelRatio, canvas: node }; this.config[canvasId] = { context: extendContext(context), width, height, pixelRatio, canvas: node };
resolve(this.config[canvasId]); resolve(this.config[canvasId]);
}); });
}); });
} }
return new Promise(resolve => { return new Promise(resolve => {
uni.createSelectorQuery() uni.createSelectorQuery()
.in(this) .in(this)
.select(`#${canvasId}`) .select(`#${canvasId}`)
.boundingClientRect() .boundingClientRect()
.exec(res => { .exec(res => {
if (res) { if (res) {
let { width, height } = res[0]; let { width, height } = res[0];
width = width || 300; width = width || 300;
height = height || 300; height = height || 300;
const context = uni.createCanvasContext(canvasId, this); const context = uni.createCanvasContext(canvasId, this);
if (!canvasId.includes('_cloud')) { if (!canvasId.includes('_cloud')) {
this.width = width; this.width = width;
this.height = height; this.height = height;
// #ifdef MP-ALIPAY // #ifdef MP-ALIPAY
this.nodeWidth = width * pixelRatio; this.nodeWidth = width * pixelRatio;
this.nodeHeight = height * pixelRatio; this.nodeHeight = height * pixelRatio;
// #endif // #endif
} }
this.config[canvasId] = { context: extendContext(context), width, height, pixelRatio }; this.config[canvasId] = { context: extendContext(context), width, height, pixelRatio };
resolve(this.config[canvasId]); resolve(this.config[canvasId]);
} }
}); });
}); });
}, },
touchStart(e) { touchStart(e) {
if (this.canvasEl) { if (this.canvasEl) {
this.canvasEl.dispatchEvent('touchstart', wrapEvent(e)); this.canvasEl.dispatchEvent('touchstart', wrapEvent(e));
} }
}, },
touchMove(e) { touchMove(e) {
if (this.canvasEl) { if (this.canvasEl) {
this.canvasEl.dispatchEvent('touchmove', wrapEvent(e)); this.canvasEl.dispatchEvent('touchmove', wrapEvent(e));
} }
}, },
touchEnd(e) { touchEnd(e) {
if (this.canvasEl) { if (this.canvasEl) {
this.canvasEl.dispatchEvent('touchend', wrapEvent(e)); this.canvasEl.dispatchEvent('touchend', wrapEvent(e));
} }
} }
// #endif // #endif
} }
}; };
</script> </script>
<style scoped lang="stylus"> <style scoped lang="stylus">
full() full()
// #ifndef APP-NVUE // #ifndef APP-NVUE

View File

@@ -1,65 +1,65 @@
// #ifndef APP-NVUE // #ifndef APP-NVUE
// 计算版本 // 计算版本
export function compareVersion(v1, v2) { export function compareVersion(v1, v2) {
v1 = v1.split('.') v1 = v1.split('.')
v2 = v2.split('.') v2 = v2.split('.')
const len = Math.max(v1.length, v2.length) const len = Math.max(v1.length, v2.length)
while (v1.length < len) { while (v1.length < len) {
v1.push('0') v1.push('0')
} }
while (v2.length < len) { while (v2.length < len) {
v2.push('0') v2.push('0')
} }
for (let i = 0; i < len; i++) { for (let i = 0; i < len; i++) {
const num1 = parseInt(v1[i], 10) const num1 = parseInt(v1[i], 10)
const num2 = parseInt(v2[i], 10) const num2 = parseInt(v2[i], 10)
if (num1 > num2) { if (num1 > num2) {
return 1 return 1
} else if (num1 < num2) { } else if (num1 < num2) {
return -1 return -1
} }
} }
return 0 return 0
} }
export function wrapEvent(e) { export function wrapEvent(e) {
if (!e) return; if (!e) return;
if (!e.preventDefault) { if (!e.preventDefault) {
e.preventDefault = function() {}; e.preventDefault = function() {};
} }
return e; return e;
} }
export const pixelRatio = uni.getSystemInfoSync().pixelRatio export const pixelRatio = uni.getSystemInfoSync().pixelRatio
// #endif // #endif
// #ifdef APP-NVUE // #ifdef APP-NVUE
export function base64ToPath(base64) { export function base64ToPath(base64) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const [, format, bodyData] = /data:image\/(\w+);base64,(.*)/.exec(base64) || []; const [, format, bodyData] = /data:image\/(\w+);base64,(.*)/.exec(base64) || [];
const bitmap = new plus.nativeObj.Bitmap('bitmap' + Date.now()) const bitmap = new plus.nativeObj.Bitmap('bitmap' + Date.now())
bitmap.loadBase64Data(base64, () => { bitmap.loadBase64Data(base64, () => {
if (!format) { if (!format) {
reject(new Error('ERROR_BASE64SRC_PARSE')) reject(new Error('ERROR_BASE64SRC_PARSE'))
} }
const time = new Date().getTime(); const time = new Date().getTime();
const filePath = `_doc/uniapp_temp/${time}.${format}` const filePath = `_doc/uniapp_temp/${time}.${format}`
bitmap.save(filePath, {}, bitmap.save(filePath, {},
() => { () => {
bitmap.clear() bitmap.clear()
resolve(filePath) resolve(filePath)
}, },
(error) => { (error) => {
bitmap.clear() bitmap.clear()
console.error(`${JSON.stringify(error)}`) console.error(`${JSON.stringify(error)}`)
reject(error) reject(error)
}) })
}, (error) => { }, (error) => {
bitmap.clear() bitmap.clear()
console.error(`${JSON.stringify(error)}`) console.error(`${JSON.stringify(error)}`)
reject(error) reject(error)
}) })
}) })
} }
// #endif // #endif

View File

@@ -1,82 +1,82 @@
{ {
"id": "lime-f2", "id": "lime-f2",
"displayName": "蚂蚁图表 antv F2", "displayName": "蚂蚁图表 antv F2",
"version": "0.5.1", "version": "0.5.1",
"description": "全端兼容,一个专注于移动,开箱即用的可视化解决方案", "description": "全端兼容,一个专注于移动,开箱即用的可视化解决方案",
"keywords": [ "keywords": [
"蚂蚁金服", "蚂蚁金服",
"AntV", "AntV",
"F2", "F2",
"canvas", "canvas",
"图表" "图表"
], ],
"repository": "https://gitee.com/liangei/lime-f2", "repository": "https://gitee.com/liangei/lime-f2",
"engines": { "engines": {
"HBuilderX": "^3.1.0" "HBuilderX": "^3.1.0"
}, },
"dcloudext": { "dcloudext": {
"category": [ "category": [
"前端组件", "前端组件",
"通用组件" "通用组件"
], ],
"sale": { "sale": {
"regular": { "regular": {
"price": "0.00" "price": "0.00"
}, },
"sourcecode": { "sourcecode": {
"price": "0.00" "price": "0.00"
} }
}, },
"contact": { "contact": {
"qq": "" "qq": ""
}, },
"declaration": { "declaration": {
"ads": "无", "ads": "无",
"data": "无", "data": "无",
"permissions": "无" "permissions": "无"
}, },
"npmurl": "" "npmurl": ""
}, },
"uni_modules": { "uni_modules": {
"dependencies": [], "dependencies": [],
"encrypt": [], "encrypt": [],
"platforms": { "platforms": {
"cloud": { "cloud": {
"tcb": "y", "tcb": "y",
"aliyun": "y" "aliyun": "y"
}, },
"client": { "client": {
"App": { "App": {
"app-vue": "y", "app-vue": "y",
"app-nvue": "y" "app-nvue": "y"
}, },
"H5-mobile": { "H5-mobile": {
"Safari": "y", "Safari": "y",
"Android Browser": "y", "Android Browser": "y",
"微信浏览器(Android)": "y", "微信浏览器(Android)": "y",
"QQ浏览器(Android)": "y" "QQ浏览器(Android)": "y"
}, },
"H5-pc": { "H5-pc": {
"Chrome": "y", "Chrome": "y",
"IE": "u", "IE": "u",
"Edge": "u", "Edge": "u",
"Firefox": "u", "Firefox": "u",
"Safari": "y" "Safari": "y"
}, },
"小程序": { "小程序": {
"微信": "y", "微信": "y",
"阿里": "y", "阿里": "y",
"百度": "y", "百度": "y",
"字节跳动": "y", "字节跳动": "y",
"QQ": "y" "QQ": "y"
}, },
"快应用": { "快应用": {
"华为": "u", "华为": "u",
"联盟": "u" "联盟": "u"
} }
} }
} }
}, },
"dependencies": { "dependencies": {
} }
} }

View File

@@ -2,8 +2,8 @@
> F2一个专注于移动开箱即用的可视化解决方案 [查看更多](http://liangei.gitee.io/limeui/#/f2) > F2一个专注于移动开箱即用的可视化解决方案 [查看更多](http://liangei.gitee.io/limeui/#/f2)
> 基于antv F2 做了兼容处理,更多示例请访问 [uni示例](http://liangei.gitee.io/limeui/#/f2-example) [官方示例](https://f2.antv.vision/zh/examples/gallery) > 基于antv F2 做了兼容处理,更多示例请访问 [uni示例](http://liangei.gitee.io/limeui/#/f2-example) [官方示例](https://f2.antv.vision/zh/examples/gallery)
> Q群1046793420 > Q群1046793420
> antv F2 v3.8.7 > antv F2 v3.8.7
## 平台兼容 ## 平台兼容
@@ -13,7 +13,7 @@
| √ | √ | √ | √ | √ | √ | √ | | √ | √ | √ | √ | √ | √ | √ |
***注意** ***注意**
* 🔔 插件用到了 css 预编译器 [stylus](https://ext.dcloud.net.cn/plugin?name=compile-stylus) 请安装 * 🔔 插件用到了 css 预编译器 [stylus](https://ext.dcloud.net.cn/plugin?name=compile-stylus) 请安装
* 🌈 本插件使用了`webview`支持`nvue` * 🌈 本插件使用了`webview`支持`nvue`
* 📦 本插件没有对F2内部的方法和样式做过改动只是使其兼容uniapp。 * 📦 本插件没有对F2内部的方法和样式做过改动只是使其兼容uniapp。
@@ -249,11 +249,11 @@ export default {
``` ```
## Nvue 使用注意事项 ## Nvue 使用注意事项
- 由于 nvue 使用的是字符串模板传输,打包的时候会被混淆压缩 - 由于 nvue 使用的是字符串模板传输,打包的时候会被混淆压缩
- 所在要保持 **关键词** 不被 **混淆压缩** - 所在要保持 **关键词** 不被 **混淆压缩**
#### 1、F2、DataSet 不需要被引入 #### 1、F2、DataSet 不需要被引入
👎 错误 👎 错误
```js ```js
import F2 from '@/uni_modules/lime-f2/components/lime-f2/f2-all.min.js'; import F2 from '@/uni_modules/lime-f2/components/lime-f2/f2-all.min.js';
@@ -261,19 +261,19 @@ import DataSet from '@/antv/DataSet'
export default { export default {
...code ...code
} }
``` ```
👍 正确 👍 正确
```js ```js
export default { export default {
...code ...code
} }
``` ```
#### 2、引用函数外面数据的**关键词**不需要声明 #### 2、引用函数外面数据的**关键词**不需要声明
👎 错误 👎 错误
```js ```js
const {data} = this const {data} = this
@@ -281,52 +281,52 @@ this.$refs.chart.init(config => {
chart.source(data); chart.source(data);
}) })
``` ```
👍 正确 👍 正确
```js ```js
// 所有用函数外里的数据,只要保持跟 this 里的一致 // 所有用函数外里的数据,只要保持跟 this 里的一致
this.$refs.chart.init(config => { this.$refs.chart.init(config => {
chart.source(data); chart.source(data);
}) })
- or - - or -
this.$refs.chart.init(config => { this.$refs.chart.init(config => {
chart.source(this.data); chart.source(this.data);
}) })
``` ```
#### 3、引用函数外面的数据需要通过**params**或函数的第二个参数传递 #### 3、引用函数外面的数据需要通过**params**或函数的第二个参数传递
👎 错误 👎 错误
```html ```html
<l-f2 /> <l-f2 />
- or - - or -
this.$refs.chart.init(config => {...code}) this.$refs.chart.init(config => {...code})
``` ```
👍 正确 👍 正确
```html ```html
<l-f2 :params="{data}"/> <l-f2 :params="{data}"/>
- or - - or -
this.$refs.chart.init(config => {...code}, {data: this.data}) this.$refs.chart.init(config => {...code}, {data: this.data})
``` ```
## 不支持的功能 ## 不支持的功能
- 目前由于小程序不支持 `document`,所以 `Guide.Html` 辅助元素组件目前仍无法使用,其他 F2 的功能全部支持。 - 目前由于小程序不支持 `document`,所以 `Guide.Html` 辅助元素组件目前仍无法使用,其他 F2 的功能全部支持。
- **Nvue**是通过`webview`实现的,所以它不受影响! - **Nvue**是通过`webview`实现的,所以它不受影响!
- **H5** uni官方 `canvas` 模拟了 小程序 所以也不支持 。 - **H5** uni官方 `canvas` 模拟了 小程序 所以也不支持 。
- 缩放手势暂时不支持,因为原厂也不支持小程序,将来如果有需要考虑修改源码。 - 缩放手势暂时不支持,因为原厂也不支持小程序,将来如果有需要考虑修改源码。
- 词云原厂也是不支持小程序本插件修改源码使得支持但头条小程序需要1.78.0以后。 - 词云原厂也是不支持小程序本插件修改源码使得支持但头条小程序需要1.78.0以后。
## Props ## Props
@@ -334,25 +334,25 @@ this.$refs.chart.init(config => {...code}, {data: this.data})
| --------------- | -------- | ------- | ------------ | ----- | | --------------- | -------- | ------- | ------------ | ----- |
| custom-style | 自定义样式 | `string` | - | - | | custom-style | 自定义样式 | `string` | - | - |
| params | 仅针对nvue的数据传递,同init函数的第二个参数两选一 | `object` | - | - | | params | 仅针对nvue的数据传递,同init函数的第二个参数两选一 | `object` | - | - |
| webviewStyles | 仅针对nvue的webview设置样式 | `object` | - | - | | webviewStyles | 仅针对nvue的webview设置样式 | `object` | - | - |
| source | 图表数据 | `array` | - | 0.3.0 | | source | 图表数据 | `array` | - | 0.3.0 |
| type | canvas 类型 2d 仅针对微信和头条有效 | `string` | `2d` | 0.3.0 | | type | canvas 类型 2d 仅针对微信和头条有效 | `string` | `2d` | 0.3.0 |
| isAutoPlay | 设置了上方的 图表数据 再 设置本参数 ,只要数据发生改动就更新图表 | `boolean` | `false` | 0.3.0 | | isAutoPlay | 设置了上方的 图表数据 再 设置本参数 ,只要数据发生改动就更新图表 | `boolean` | `false` | 0.3.0 |
| is-disable-scroll | 触摸图表时是否禁止页面滚动 | `boolean` | `false` | | | is-disable-scroll | 触摸图表时是否禁止页面滚动 | `boolean` | `false` | |
## 事件 ## 事件
| 参数 | 说明 | | 参数 | 说明 |
| --------------- | --------------- | | --------------- | --------------- |
| init(callback, data) | **callback**: 回调函数 **data**: `nvue` 如果使用了外部数据,需要传递 | | init(callback, data) | **callback**: 回调函数 **data**: `nvue` 如果使用了外部数据,需要传递 |
| changeData(data) | 更新数据 ,传递是数据数组 | | changeData(data) | 更新数据 ,传递是数据数组 |
| clear() | 清除所有 | | clear() | 清除所有 |
| destroy() | 销毁实例 | | destroy() | 销毁实例 |
| repaint() | 用于暂时只更新数据,等需要时再调用重绘 | | repaint() | 用于暂时只更新数据,等需要时再调用重绘 |
| reset(callback, data) | 重新定义图形语法,改变图表类型和各种配置, **callback**: 回调函数 **data**: `nvue` 如果使用了外部数据,需要传递 | | reset(callback, data) | 重新定义图形语法,改变图表类型和各种配置, **callback**: 回调函数 **data**: `nvue` 如果使用了外部数据,需要传递 |
| canvasToTempFilePath(opt) | 用于生成图片 | | canvasToTempFilePath(opt) | 用于生成图片 |
## 打赏 ## 打赏
如果你觉得本插件,解决了你的问题,赠人玫瑰,手留余香。 如果你觉得本插件,解决了你的问题,赠人玫瑰,手留余香。
![输入图片说明](https://cdn.jsdelivr.net/gh/liangei/image@latest/222521_bb543f96_518581.jpeg "微信图片编辑_20201122220352.jpg") ![输入图片说明](https://cdn.jsdelivr.net/gh/liangei/image@latest/222521_bb543f96_518581.jpeg "微信图片编辑_20201122220352.jpg")

View File

@@ -1,132 +1,132 @@
export default { export default {
"pulldown": "\ue588", "pulldown": "\ue588",
"refreshempty": "\ue461", "refreshempty": "\ue461",
"back": "\ue471", "back": "\ue471",
"forward": "\ue470", "forward": "\ue470",
"more": "\ue507", "more": "\ue507",
"more-filled": "\ue537", "more-filled": "\ue537",
"scan": "\ue612", "scan": "\ue612",
"qq": "\ue264", "qq": "\ue264",
"weibo": "\ue260", "weibo": "\ue260",
"weixin": "\ue261", "weixin": "\ue261",
"pengyouquan": "\ue262", "pengyouquan": "\ue262",
"loop": "\ue565", "loop": "\ue565",
"refresh": "\ue407", "refresh": "\ue407",
"refresh-filled": "\ue437", "refresh-filled": "\ue437",
"arrowthindown": "\ue585", "arrowthindown": "\ue585",
"arrowthinleft": "\ue586", "arrowthinleft": "\ue586",
"arrowthinright": "\ue587", "arrowthinright": "\ue587",
"arrowthinup": "\ue584", "arrowthinup": "\ue584",
"undo-filled": "\ue7d6", "undo-filled": "\ue7d6",
"undo": "\ue406", "undo": "\ue406",
"redo": "\ue405", "redo": "\ue405",
"redo-filled": "\ue7d9", "redo-filled": "\ue7d9",
"bars": "\ue563", "bars": "\ue563",
"chatboxes": "\ue203", "chatboxes": "\ue203",
"camera": "\ue301", "camera": "\ue301",
"chatboxes-filled": "\ue233", "chatboxes-filled": "\ue233",
"camera-filled": "\ue7ef", "camera-filled": "\ue7ef",
"cart-filled": "\ue7f4", "cart-filled": "\ue7f4",
"cart": "\ue7f5", "cart": "\ue7f5",
"checkbox-filled": "\ue442", "checkbox-filled": "\ue442",
"checkbox": "\ue7fa", "checkbox": "\ue7fa",
"arrowleft": "\ue582", "arrowleft": "\ue582",
"arrowdown": "\ue581", "arrowdown": "\ue581",
"arrowright": "\ue583", "arrowright": "\ue583",
"smallcircle-filled": "\ue801", "smallcircle-filled": "\ue801",
"arrowup": "\ue580", "arrowup": "\ue580",
"circle": "\ue411", "circle": "\ue411",
"eye-filled": "\ue568", "eye-filled": "\ue568",
"eye-slash-filled": "\ue822", "eye-slash-filled": "\ue822",
"eye-slash": "\ue823", "eye-slash": "\ue823",
"eye": "\ue824", "eye": "\ue824",
"flag-filled": "\ue825", "flag-filled": "\ue825",
"flag": "\ue508", "flag": "\ue508",
"gear-filled": "\ue532", "gear-filled": "\ue532",
"reload": "\ue462", "reload": "\ue462",
"gear": "\ue502", "gear": "\ue502",
"hand-thumbsdown-filled": "\ue83b", "hand-thumbsdown-filled": "\ue83b",
"hand-thumbsdown": "\ue83c", "hand-thumbsdown": "\ue83c",
"hand-thumbsup-filled": "\ue83d", "hand-thumbsup-filled": "\ue83d",
"heart-filled": "\ue83e", "heart-filled": "\ue83e",
"hand-thumbsup": "\ue83f", "hand-thumbsup": "\ue83f",
"heart": "\ue840", "heart": "\ue840",
"home": "\ue500", "home": "\ue500",
"info": "\ue504", "info": "\ue504",
"home-filled": "\ue530", "home-filled": "\ue530",
"info-filled": "\ue534", "info-filled": "\ue534",
"circle-filled": "\ue441", "circle-filled": "\ue441",
"chat-filled": "\ue847", "chat-filled": "\ue847",
"chat": "\ue263", "chat": "\ue263",
"mail-open-filled": "\ue84d", "mail-open-filled": "\ue84d",
"email-filled": "\ue231", "email-filled": "\ue231",
"mail-open": "\ue84e", "mail-open": "\ue84e",
"email": "\ue201", "email": "\ue201",
"checkmarkempty": "\ue472", "checkmarkempty": "\ue472",
"list": "\ue562", "list": "\ue562",
"locked-filled": "\ue856", "locked-filled": "\ue856",
"locked": "\ue506", "locked": "\ue506",
"map-filled": "\ue85c", "map-filled": "\ue85c",
"map-pin": "\ue85e", "map-pin": "\ue85e",
"map-pin-ellipse": "\ue864", "map-pin-ellipse": "\ue864",
"map": "\ue364", "map": "\ue364",
"minus-filled": "\ue440", "minus-filled": "\ue440",
"mic-filled": "\ue332", "mic-filled": "\ue332",
"minus": "\ue410", "minus": "\ue410",
"micoff": "\ue360", "micoff": "\ue360",
"mic": "\ue302", "mic": "\ue302",
"clear": "\ue434", "clear": "\ue434",
"smallcircle": "\ue868", "smallcircle": "\ue868",
"close": "\ue404", "close": "\ue404",
"closeempty": "\ue460", "closeempty": "\ue460",
"paperclip": "\ue567", "paperclip": "\ue567",
"paperplane": "\ue503", "paperplane": "\ue503",
"paperplane-filled": "\ue86e", "paperplane-filled": "\ue86e",
"person-filled": "\ue131", "person-filled": "\ue131",
"contact-filled": "\ue130", "contact-filled": "\ue130",
"person": "\ue101", "person": "\ue101",
"contact": "\ue100", "contact": "\ue100",
"images-filled": "\ue87a", "images-filled": "\ue87a",
"phone": "\ue200", "phone": "\ue200",
"images": "\ue87b", "images": "\ue87b",
"image": "\ue363", "image": "\ue363",
"image-filled": "\ue877", "image-filled": "\ue877",
"location-filled": "\ue333", "location-filled": "\ue333",
"location": "\ue303", "location": "\ue303",
"plus-filled": "\ue439", "plus-filled": "\ue439",
"plus": "\ue409", "plus": "\ue409",
"plusempty": "\ue468", "plusempty": "\ue468",
"help-filled": "\ue535", "help-filled": "\ue535",
"help": "\ue505", "help": "\ue505",
"navigate-filled": "\ue884", "navigate-filled": "\ue884",
"navigate": "\ue501", "navigate": "\ue501",
"mic-slash-filled": "\ue892", "mic-slash-filled": "\ue892",
"search": "\ue466", "search": "\ue466",
"settings": "\ue560", "settings": "\ue560",
"sound": "\ue590", "sound": "\ue590",
"sound-filled": "\ue8a1", "sound-filled": "\ue8a1",
"spinner-cycle": "\ue465", "spinner-cycle": "\ue465",
"download-filled": "\ue8a4", "download-filled": "\ue8a4",
"personadd-filled": "\ue132", "personadd-filled": "\ue132",
"videocam-filled": "\ue8af", "videocam-filled": "\ue8af",
"personadd": "\ue102", "personadd": "\ue102",
"upload": "\ue402", "upload": "\ue402",
"upload-filled": "\ue8b1", "upload-filled": "\ue8b1",
"starhalf": "\ue463", "starhalf": "\ue463",
"star-filled": "\ue438", "star-filled": "\ue438",
"star": "\ue408", "star": "\ue408",
"trash": "\ue401", "trash": "\ue401",
"phone-filled": "\ue230", "phone-filled": "\ue230",
"compose": "\ue400", "compose": "\ue400",
"videocam": "\ue300", "videocam": "\ue300",
"trash-filled": "\ue8dc", "trash-filled": "\ue8dc",
"download": "\ue403", "download": "\ue403",
"chatbubble-filled": "\ue232", "chatbubble-filled": "\ue232",
"chatbubble": "\ue202", "chatbubble": "\ue202",
"cloud-download": "\ue8e4", "cloud-download": "\ue8e4",
"cloud-upload-filled": "\ue8e5", "cloud-upload-filled": "\ue8e5",
"cloud-upload": "\ue8e6", "cloud-upload": "\ue8e6",
"cloud-download-filled": "\ue8e9", "cloud-download-filled": "\ue8e9",
"headphones":"\ue8bf", "headphones":"\ue8bf",
"shop":"\ue609" "shop":"\ue609"
} }

File diff suppressed because one or more lines are too long

View File

@@ -1,45 +1,45 @@
// #ifdef H5 // #ifdef H5
export default { export default {
name: 'Keypress', name: 'Keypress',
props: { props: {
disable: { disable: {
type: Boolean, type: Boolean,
default: false default: false
} }
}, },
mounted () { mounted () {
const keyNames = { const keyNames = {
esc: ['Esc', 'Escape'], esc: ['Esc', 'Escape'],
tab: 'Tab', tab: 'Tab',
enter: 'Enter', enter: 'Enter',
space: [' ', 'Spacebar'], space: [' ', 'Spacebar'],
up: ['Up', 'ArrowUp'], up: ['Up', 'ArrowUp'],
left: ['Left', 'ArrowLeft'], left: ['Left', 'ArrowLeft'],
right: ['Right', 'ArrowRight'], right: ['Right', 'ArrowRight'],
down: ['Down', 'ArrowDown'], down: ['Down', 'ArrowDown'],
delete: ['Backspace', 'Delete', 'Del'] delete: ['Backspace', 'Delete', 'Del']
} }
const listener = ($event) => { const listener = ($event) => {
if (this.disable) { if (this.disable) {
return return
} }
const keyName = Object.keys(keyNames).find(key => { const keyName = Object.keys(keyNames).find(key => {
const keyName = $event.key const keyName = $event.key
const value = keyNames[key] const value = keyNames[key]
return value === keyName || (Array.isArray(value) && value.includes(keyName)) return value === keyName || (Array.isArray(value) && value.includes(keyName))
}) })
if (keyName) { if (keyName) {
// 避免和其他按键事件冲突 // 避免和其他按键事件冲突
setTimeout(() => { setTimeout(() => {
this.$emit(keyName, {}) this.$emit(keyName, {})
}, 0) }, 0)
} }
} }
document.addEventListener('keyup', listener) document.addEventListener('keyup', listener)
this.$once('hook:beforeDestroy', () => { this.$once('hook:beforeDestroy', () => {
document.removeEventListener('keyup', listener) document.removeEventListener('keyup', listener)
}) })
}, },
render: () => {} render: () => {}
} }
// #endif // #endif

View File

@@ -1,263 +1,263 @@
<template> <template>
<view class="uni-popup-dialog"> <view class="uni-popup-dialog">
<view class="uni-dialog-title"> <view class="uni-dialog-title">
<text class="uni-dialog-title-text" :class="['uni-popup__'+dialogType]">{{titleText}}</text> <text class="uni-dialog-title-text" :class="['uni-popup__'+dialogType]">{{titleText}}</text>
</view> </view>
<view v-if="mode === 'base'" class="uni-dialog-content"> <view v-if="mode === 'base'" class="uni-dialog-content">
<slot> <slot>
<text class="uni-dialog-content-text">{{content}}</text> <text class="uni-dialog-content-text">{{content}}</text>
</slot> </slot>
</view> </view>
<view v-else class="uni-dialog-content"> <view v-else class="uni-dialog-content">
<slot> <slot>
<input class="uni-dialog-input" v-model="val" type="text" :placeholder="placeholderText" :focus="focus" > <input class="uni-dialog-input" v-model="val" type="text" :placeholder="placeholderText" :focus="focus" >
</slot> </slot>
</view> </view>
<view class="uni-dialog-button-group"> <view class="uni-dialog-button-group">
<view class="uni-dialog-button" @click="closeDialog"> <view class="uni-dialog-button" @click="closeDialog">
<text class="uni-dialog-button-text">{{cancelText}}</text> <text class="uni-dialog-button-text">{{cancelText}}</text>
</view> </view>
<view class="uni-dialog-button uni-border-left" @click="onOk"> <view class="uni-dialog-button uni-border-left" @click="onOk">
<text class="uni-dialog-button-text uni-button-color">{{okText}}</text> <text class="uni-dialog-button-text uni-button-color">{{okText}}</text>
</view> </view>
</view> </view>
</view> </view>
</template> </template>
<script> <script>
import popup from '../uni-popup/popup.js' import popup from '../uni-popup/popup.js'
import { import {
initVueI18n initVueI18n
} from '@dcloudio/uni-i18n' } from '@dcloudio/uni-i18n'
import messages from '../uni-popup/i18n/index.js' import messages from '../uni-popup/i18n/index.js'
const { t } = initVueI18n(messages) const { t } = initVueI18n(messages)
/** /**
* PopUp 弹出层-对话框样式 * PopUp 弹出层-对话框样式
* @description 弹出层-对话框样式 * @description 弹出层-对话框样式
* @tutorial https://ext.dcloud.net.cn/plugin?id=329 * @tutorial https://ext.dcloud.net.cn/plugin?id=329
* @property {String} value input 模式下的默认值 * @property {String} value input 模式下的默认值
* @property {String} placeholder input 模式下输入提示 * @property {String} placeholder input 模式下输入提示
* @property {String} type = [success|warning|info|error] 主题样式 * @property {String} type = [success|warning|info|error] 主题样式
* @value success 成功 * @value success 成功
* @value warning 提示 * @value warning 提示
* @value info 消息 * @value info 消息
* @value error 错误 * @value error 错误
* @property {String} mode = [base|input] 模式、 * @property {String} mode = [base|input] 模式、
* @value base 基础对话框 * @value base 基础对话框
* @value input 可输入对话框 * @value input 可输入对话框
* @property {String} content 对话框内容 * @property {String} content 对话框内容
* @property {Boolean} beforeClose 是否拦截取消事件 * @property {Boolean} beforeClose 是否拦截取消事件
* @event {Function} confirm 点击确认按钮触发 * @event {Function} confirm 点击确认按钮触发
* @event {Function} close 点击取消按钮触发 * @event {Function} close 点击取消按钮触发
*/ */
export default { export default {
name: "uniPopupDialog", name: "uniPopupDialog",
mixins: [popup], mixins: [popup],
emits:['confirm','close'], emits:['confirm','close'],
props: { props: {
value: { value: {
type: [String, Number], type: [String, Number],
default: '' default: ''
}, },
placeholder: { placeholder: {
type: [String, Number], type: [String, Number],
default: '' default: ''
}, },
type: { type: {
type: String, type: String,
default: 'error' default: 'error'
}, },
mode: { mode: {
type: String, type: String,
default: 'base' default: 'base'
}, },
title: { title: {
type: String, type: String,
default: '' default: ''
}, },
content: { content: {
type: String, type: String,
default: '' default: ''
}, },
beforeClose: { beforeClose: {
type: Boolean, type: Boolean,
default: false default: false
} }
}, },
data() { data() {
return { return {
dialogType: 'error', dialogType: 'error',
focus: false, focus: false,
val: "" val: ""
} }
}, },
computed: { computed: {
okText() { okText() {
return t("uni-popup.ok") return t("uni-popup.ok")
}, },
cancelText() { cancelText() {
return t("uni-popup.cancel") return t("uni-popup.cancel")
}, },
placeholderText() { placeholderText() {
return this.placeholder || t("uni-popup.placeholder") return this.placeholder || t("uni-popup.placeholder")
}, },
titleText() { titleText() {
return this.title || t("uni-popup.title") return this.title || t("uni-popup.title")
} }
}, },
watch: { watch: {
type(val) { type(val) {
this.dialogType = val this.dialogType = val
}, },
mode(val) { mode(val) {
if (val === 'input') { if (val === 'input') {
this.dialogType = 'info' this.dialogType = 'info'
} }
}, },
value(val) { value(val) {
this.val = val this.val = val
} }
}, },
created() { created() {
// 对话框遮罩不可点击 // 对话框遮罩不可点击
this.popup.disableMask() this.popup.disableMask()
// this.popup.closeMask() // this.popup.closeMask()
if (this.mode === 'input') { if (this.mode === 'input') {
this.dialogType = 'info' this.dialogType = 'info'
this.val = this.value this.val = this.value
} else { } else {
this.dialogType = this.type this.dialogType = this.type
} }
}, },
mounted() { mounted() {
this.focus = true this.focus = true
}, },
methods: { methods: {
/** /**
* 点击确认按钮 * 点击确认按钮
*/ */
onOk() { onOk() {
if (this.mode === 'input'){ if (this.mode === 'input'){
this.$emit('confirm', this.val) this.$emit('confirm', this.val)
}else{ }else{
this.$emit('confirm') this.$emit('confirm')
} }
if(this.beforeClose) return if(this.beforeClose) return
this.popup.close() this.popup.close()
}, },
/** /**
* 点击取消按钮 * 点击取消按钮
*/ */
closeDialog() { closeDialog() {
this.$emit('close') this.$emit('close')
if(this.beforeClose) return if(this.beforeClose) return
this.popup.close() this.popup.close()
}, },
close(){ close(){
this.popup.close() this.popup.close()
} }
} }
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.uni-popup-dialog { .uni-popup-dialog {
width: 300px; width: 300px;
border-radius: 15px; border-radius: 15px;
background-color: #fff; background-color: #fff;
} }
.uni-dialog-title { .uni-dialog-title {
/* #ifndef APP-NVUE */ /* #ifndef APP-NVUE */
display: flex; display: flex;
/* #endif */ /* #endif */
flex-direction: row; flex-direction: row;
justify-content: center; justify-content: center;
padding-top: 15px; padding-top: 15px;
padding-bottom: 5px; padding-bottom: 5px;
} }
.uni-dialog-title-text { .uni-dialog-title-text {
font-size: 16px; font-size: 16px;
font-weight: 500; font-weight: 500;
} }
.uni-dialog-content { .uni-dialog-content {
/* #ifndef APP-NVUE */ /* #ifndef APP-NVUE */
display: flex; display: flex;
/* #endif */ /* #endif */
flex-direction: row; flex-direction: row;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
padding: 5px 15px 15px 15px; padding: 5px 15px 15px 15px;
} }
.uni-dialog-content-text { .uni-dialog-content-text {
font-size: 14px; font-size: 14px;
color: #6e6e6e; color: #6e6e6e;
} }
.uni-dialog-button-group { .uni-dialog-button-group {
/* #ifndef APP-NVUE */ /* #ifndef APP-NVUE */
display: flex; display: flex;
/* #endif */ /* #endif */
flex-direction: row; flex-direction: row;
border-top-color: #f5f5f5; border-top-color: #f5f5f5;
border-top-style: solid; border-top-style: solid;
border-top-width: 1px; border-top-width: 1px;
} }
.uni-dialog-button { .uni-dialog-button {
/* #ifndef APP-NVUE */ /* #ifndef APP-NVUE */
display: flex; display: flex;
/* #endif */ /* #endif */
flex: 1; flex: 1;
flex-direction: row; flex-direction: row;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
height: 45px; height: 45px;
} }
.uni-border-left { .uni-border-left {
border-left-color: #f0f0f0; border-left-color: #f0f0f0;
border-left-style: solid; border-left-style: solid;
border-left-width: 1px; border-left-width: 1px;
} }
.uni-dialog-button-text { .uni-dialog-button-text {
font-size: 14px; font-size: 14px;
} }
.uni-button-color { .uni-button-color {
color: #007aff; color: #007aff;
} }
.uni-dialog-input { .uni-dialog-input {
flex: 1; flex: 1;
font-size: 14px; font-size: 14px;
border: 1px #eee solid; border: 1px #eee solid;
height: 40px; height: 40px;
padding: 0 10px; padding: 0 10px;
border-radius: 5px; border-radius: 5px;
color: #555; color: #555;
} }
.uni-popup__success { .uni-popup__success {
color: #4cd964; color: #4cd964;
} }
.uni-popup__warn { .uni-popup__warn {
color: #f0ad4e; color: #f0ad4e;
} }
.uni-popup__error { .uni-popup__error {
color: #dd524d; color: #dd524d;
} }
.uni-popup__info { .uni-popup__info {
color: #909399; color: #909399;
} }
</style> </style>

View File

@@ -1,143 +1,143 @@
<template> <template>
<view class="uni-popup-message"> <view class="uni-popup-message">
<view class="uni-popup-message__box fixforpc-width" :class="'uni-popup__'+type"> <view class="uni-popup-message__box fixforpc-width" :class="'uni-popup__'+type">
<slot> <slot>
<text class="uni-popup-message-text" :class="'uni-popup__'+type+'-text'">{{message}}</text> <text class="uni-popup-message-text" :class="'uni-popup__'+type+'-text'">{{message}}</text>
</slot> </slot>
</view> </view>
</view> </view>
</template> </template>
<script> <script>
import popup from '../uni-popup/popup.js' import popup from '../uni-popup/popup.js'
/** /**
* PopUp 弹出层-消息提示 * PopUp 弹出层-消息提示
* @description 弹出层-消息提示 * @description 弹出层-消息提示
* @tutorial https://ext.dcloud.net.cn/plugin?id=329 * @tutorial https://ext.dcloud.net.cn/plugin?id=329
* @property {String} type = [success|warning|info|error] 主题样式 * @property {String} type = [success|warning|info|error] 主题样式
* @value success 成功 * @value success 成功
* @value warning 提示 * @value warning 提示
* @value info 消息 * @value info 消息
* @value error 错误 * @value error 错误
* @property {String} message 消息提示文字 * @property {String} message 消息提示文字
* @property {String} duration 显示时间,设置为 0 则不会自动关闭 * @property {String} duration 显示时间,设置为 0 则不会自动关闭
*/ */
export default { export default {
name: 'uniPopupMessage', name: 'uniPopupMessage',
mixins:[popup], mixins:[popup],
props: { props: {
/** /**
* 主题 success/warning/info/error 默认 success * 主题 success/warning/info/error 默认 success
*/ */
type: { type: {
type: String, type: String,
default: 'success' default: 'success'
}, },
/** /**
* 消息文字 * 消息文字
*/ */
message: { message: {
type: String, type: String,
default: '' default: ''
}, },
/** /**
* 显示时间,设置为 0 则不会自动关闭 * 显示时间,设置为 0 则不会自动关闭
*/ */
duration: { duration: {
type: Number, type: Number,
default: 3000 default: 3000
}, },
maskShow:{ maskShow:{
type:Boolean, type:Boolean,
default:false default:false
} }
}, },
data() { data() {
return {} return {}
}, },
created() { created() {
this.popup.maskShow = this.maskShow this.popup.maskShow = this.maskShow
this.popup.messageChild = this this.popup.messageChild = this
}, },
methods: { methods: {
timerClose(){ timerClose(){
if(this.duration === 0) return if(this.duration === 0) return
clearTimeout(this.timer) clearTimeout(this.timer)
this.timer = setTimeout(()=>{ this.timer = setTimeout(()=>{
this.popup.close() this.popup.close()
},this.duration) },this.duration)
} }
} }
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.uni-popup-message { .uni-popup-message {
/* #ifndef APP-NVUE */ /* #ifndef APP-NVUE */
display: flex; display: flex;
/* #endif */ /* #endif */
flex-direction: row; flex-direction: row;
justify-content: center; justify-content: center;
} }
.uni-popup-message__box { .uni-popup-message__box {
background-color: #e1f3d8; background-color: #e1f3d8;
padding: 10px 15px; padding: 10px 15px;
border-color: #eee; border-color: #eee;
border-style: solid; border-style: solid;
border-width: 1px; border-width: 1px;
flex: 1; flex: 1;
} }
@media screen and (min-width: 500px) { @media screen and (min-width: 500px) {
.fixforpc-width { .fixforpc-width {
margin-top: 20px; margin-top: 20px;
border-radius: 4px; border-radius: 4px;
flex: none; flex: none;
min-width: 380px; min-width: 380px;
/* #ifndef APP-NVUE */ /* #ifndef APP-NVUE */
max-width: 50%; max-width: 50%;
/* #endif */ /* #endif */
/* #ifdef APP-NVUE */ /* #ifdef APP-NVUE */
max-width: 500px; max-width: 500px;
/* #endif */ /* #endif */
} }
} }
.uni-popup-message-text { .uni-popup-message-text {
font-size: 14px; font-size: 14px;
padding: 0; padding: 0;
} }
.uni-popup__success { .uni-popup__success {
background-color: #e1f3d8; background-color: #e1f3d8;
} }
.uni-popup__success-text { .uni-popup__success-text {
color: #67C23A; color: #67C23A;
} }
.uni-popup__warn { .uni-popup__warn {
background-color: #faecd8; background-color: #faecd8;
} }
.uni-popup__warn-text { .uni-popup__warn-text {
color: #E6A23C; color: #E6A23C;
} }
.uni-popup__error { .uni-popup__error {
background-color: #fde2e2; background-color: #fde2e2;
} }
.uni-popup__error-text { .uni-popup__error-text {
color: #F56C6C; color: #F56C6C;
} }
.uni-popup__info { .uni-popup__info {
background-color: #F2F6FC; background-color: #F2F6FC;
} }
.uni-popup__info-text { .uni-popup__info-text {
color: #909399; color: #909399;
} }
</style> </style>

View File

@@ -1,185 +1,185 @@
<template> <template>
<view class="uni-popup-share"> <view class="uni-popup-share">
<view class="uni-share-title"><text class="uni-share-title-text">{{shareTitleText}}</text></view> <view class="uni-share-title"><text class="uni-share-title-text">{{shareTitleText}}</text></view>
<view class="uni-share-content"> <view class="uni-share-content">
<view class="uni-share-content-box"> <view class="uni-share-content-box">
<view class="uni-share-content-item" v-for="(item,index) in bottomData" :key="index" @click.stop="select(item,index)"> <view class="uni-share-content-item" v-for="(item,index) in bottomData" :key="index" @click.stop="select(item,index)">
<image class="uni-share-image" :src="item.icon" mode="aspectFill"></image> <image class="uni-share-image" :src="item.icon" mode="aspectFill"></image>
<text class="uni-share-text">{{item.text}}</text> <text class="uni-share-text">{{item.text}}</text>
</view> </view>
</view> </view>
</view> </view>
<view class="uni-share-button-box"> <view class="uni-share-button-box">
<button class="uni-share-button" @click="close">{{cancelText}}</button> <button class="uni-share-button" @click="close">{{cancelText}}</button>
</view> </view>
</view> </view>
</template> </template>
<script> <script>
import popup from '../uni-popup/popup.js' import popup from '../uni-popup/popup.js'
import { import {
initVueI18n initVueI18n
} from '@dcloudio/uni-i18n' } from '@dcloudio/uni-i18n'
import messages from '../uni-popup/i18n/index.js' import messages from '../uni-popup/i18n/index.js'
const { t } = initVueI18n(messages) const { t } = initVueI18n(messages)
export default { export default {
name: 'UniPopupShare', name: 'UniPopupShare',
mixins:[popup], mixins:[popup],
emits:['select'], emits:['select'],
props: { props: {
title: { title: {
type: String, type: String,
default: '' default: ''
}, },
beforeClose: { beforeClose: {
type: Boolean, type: Boolean,
default: false default: false
} }
}, },
data() { data() {
return { return {
bottomData: [{ bottomData: [{
text: '微信', text: '微信',
icon: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/c2b17470-50be-11eb-b680-7980c8a877b8.png', icon: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/c2b17470-50be-11eb-b680-7980c8a877b8.png',
name: 'wx' name: 'wx'
}, },
{ {
text: '支付宝', text: '支付宝',
icon: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/d684ae40-50be-11eb-8ff1-d5dcf8779628.png', icon: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/d684ae40-50be-11eb-8ff1-d5dcf8779628.png',
name: 'wx' name: 'wx'
}, },
{ {
text: 'QQ', text: 'QQ',
icon: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/e7a79520-50be-11eb-b997-9918a5dda011.png', icon: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/e7a79520-50be-11eb-b997-9918a5dda011.png',
name: 'qq' name: 'qq'
}, },
{ {
text: '新浪', text: '新浪',
icon: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/0dacdbe0-50bf-11eb-8ff1-d5dcf8779628.png', icon: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/0dacdbe0-50bf-11eb-8ff1-d5dcf8779628.png',
name: 'sina' name: 'sina'
}, },
{ {
text: '百度', text: '百度',
icon: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/1ec6e920-50bf-11eb-8a36-ebb87efcf8c0.png', icon: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/1ec6e920-50bf-11eb-8a36-ebb87efcf8c0.png',
name: 'copy' name: 'copy'
}, },
{ {
text: '其他', text: '其他',
icon: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/2e0fdfe0-50bf-11eb-b997-9918a5dda011.png', icon: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/2e0fdfe0-50bf-11eb-b997-9918a5dda011.png',
name: 'more' name: 'more'
} }
] ]
} }
}, },
created() {}, created() {},
computed: { computed: {
cancelText() { cancelText() {
return t("uni-popup.cancel") return t("uni-popup.cancel")
}, },
shareTitleText() { shareTitleText() {
return this.title || t("uni-popup.shareTitle") return this.title || t("uni-popup.shareTitle")
} }
}, },
methods: { methods: {
/** /**
* 选择内容 * 选择内容
*/ */
select(item, index) { select(item, index) {
this.$emit('select', { this.$emit('select', {
item, item,
index index
}) })
this.close() this.close()
}, },
/** /**
* 关闭窗口 * 关闭窗口
*/ */
close() { close() {
if(this.beforeClose) return if(this.beforeClose) return
this.popup.close() this.popup.close()
} }
} }
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.uni-popup-share { .uni-popup-share {
background-color: #fff; background-color: #fff;
} }
.uni-share-title { .uni-share-title {
/* #ifndef APP-NVUE */ /* #ifndef APP-NVUE */
display: flex; display: flex;
/* #endif */ /* #endif */
flex-direction: row; flex-direction: row;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
height: 40px; height: 40px;
} }
.uni-share-title-text { .uni-share-title-text {
font-size: 14px; font-size: 14px;
color: #666; color: #666;
} }
.uni-share-content { .uni-share-content {
/* #ifndef APP-NVUE */ /* #ifndef APP-NVUE */
display: flex; display: flex;
/* #endif */ /* #endif */
flex-direction: row; flex-direction: row;
justify-content: center; justify-content: center;
padding-top: 10px; padding-top: 10px;
} }
.uni-share-content-box { .uni-share-content-box {
/* #ifndef APP-NVUE */ /* #ifndef APP-NVUE */
display: flex; display: flex;
/* #endif */ /* #endif */
flex-direction: row; flex-direction: row;
flex-wrap: wrap; flex-wrap: wrap;
width: 360px; width: 360px;
} }
.uni-share-content-item { .uni-share-content-item {
width: 90px; width: 90px;
/* #ifndef APP-NVUE */ /* #ifndef APP-NVUE */
display: flex; display: flex;
/* #endif */ /* #endif */
flex-direction: column; flex-direction: column;
justify-content: center; justify-content: center;
padding: 10px 0; padding: 10px 0;
align-items: center; align-items: center;
} }
.uni-share-content-item:active { .uni-share-content-item:active {
background-color: #f5f5f5; background-color: #f5f5f5;
} }
.uni-share-image { .uni-share-image {
width: 30px; width: 30px;
height: 30px; height: 30px;
} }
.uni-share-text { .uni-share-text {
margin-top: 10px; margin-top: 10px;
font-size: 14px; font-size: 14px;
color: #3B4144; color: #3B4144;
} }
.uni-share-button-box { .uni-share-button-box {
/* #ifndef APP-NVUE */ /* #ifndef APP-NVUE */
display: flex; display: flex;
/* #endif */ /* #endif */
flex-direction: row; flex-direction: row;
padding: 10px 15px; padding: 10px 15px;
} }
.uni-share-button { .uni-share-button {
flex: 1; flex: 1;
border-radius: 50px; border-radius: 50px;
color: #666; color: #666;
font-size: 16px; font-size: 16px;
} }
.uni-share-button::after { .uni-share-button::after {
border-radius: 50px; border-radius: 50px;
} }
</style> </style>

View File

@@ -1,6 +1,6 @@
{ {
"uni-popup.cancel": "cancel", "uni-popup.cancel": "cancel",
"uni-popup.ok": "ok", "uni-popup.ok": "ok",
"uni-popup.placeholder": "pleace enter", "uni-popup.placeholder": "pleace enter",
"uni-popup.title": "Hint", "uni-popup.title": "Hint",
"uni-popup.shareTitle": "Share to" "uni-popup.shareTitle": "Share to"

View File

@@ -1,8 +1,8 @@
import en from './en.json' import en from './en.json'
import zhHans from './zh-Hans.json' import zhHans from './zh-Hans.json'
import zhHant from './zh-Hant.json' import zhHant from './zh-Hant.json'
export default { export default {
en, en,
'zh-Hans': zhHans, 'zh-Hans': zhHans,
'zh-Hant': zhHant 'zh-Hant': zhHant
} }

View File

@@ -1,7 +1,7 @@
{ {
"uni-popup.cancel": "取消", "uni-popup.cancel": "取消",
"uni-popup.ok": "确定", "uni-popup.ok": "确定",
"uni-popup.placeholder": "请输入", "uni-popup.placeholder": "请输入",
"uni-popup.title": "提示", "uni-popup.title": "提示",
"uni-popup.shareTitle": "分享到" "uni-popup.shareTitle": "分享到"
} }

View File

@@ -1,7 +1,7 @@
{ {
"uni-popup.cancel": "取消", "uni-popup.cancel": "取消",
"uni-popup.ok": "確定", "uni-popup.ok": "確定",
"uni-popup.placeholder": "請輸入", "uni-popup.placeholder": "請輸入",
"uni-popup.title": "提示", "uni-popup.title": "提示",
"uni-popup.shareTitle": "分享到" "uni-popup.shareTitle": "分享到"
} }

View File

@@ -1,45 +1,45 @@
// #ifdef H5 // #ifdef H5
export default { export default {
name: 'Keypress', name: 'Keypress',
props: { props: {
disable: { disable: {
type: Boolean, type: Boolean,
default: false default: false
} }
}, },
mounted () { mounted () {
const keyNames = { const keyNames = {
esc: ['Esc', 'Escape'], esc: ['Esc', 'Escape'],
tab: 'Tab', tab: 'Tab',
enter: 'Enter', enter: 'Enter',
space: [' ', 'Spacebar'], space: [' ', 'Spacebar'],
up: ['Up', 'ArrowUp'], up: ['Up', 'ArrowUp'],
left: ['Left', 'ArrowLeft'], left: ['Left', 'ArrowLeft'],
right: ['Right', 'ArrowRight'], right: ['Right', 'ArrowRight'],
down: ['Down', 'ArrowDown'], down: ['Down', 'ArrowDown'],
delete: ['Backspace', 'Delete', 'Del'] delete: ['Backspace', 'Delete', 'Del']
} }
const listener = ($event) => { const listener = ($event) => {
if (this.disable) { if (this.disable) {
return return
} }
const keyName = Object.keys(keyNames).find(key => { const keyName = Object.keys(keyNames).find(key => {
const keyName = $event.key const keyName = $event.key
const value = keyNames[key] const value = keyNames[key]
return value === keyName || (Array.isArray(value) && value.includes(keyName)) return value === keyName || (Array.isArray(value) && value.includes(keyName))
}) })
if (keyName) { if (keyName) {
// 避免和其他按键事件冲突 // 避免和其他按键事件冲突
setTimeout(() => { setTimeout(() => {
this.$emit(keyName, {}) this.$emit(keyName, {})
}, 0) }, 0)
} }
} }
document.addEventListener('keyup', listener) document.addEventListener('keyup', listener)
// this.$once('hook:beforeDestroy', () => { // this.$once('hook:beforeDestroy', () => {
// document.removeEventListener('keyup', listener) // document.removeEventListener('keyup', listener)
// }) // })
}, },
render: () => {} render: () => {}
} }
// #endif // #endif

View File

@@ -1,9 +1,9 @@
export default { export default {
data() { data() {
return { return {
} }
}, },
created(){ created(){
this.popup = this.getParent() this.popup = this.getParent()
@@ -22,5 +22,5 @@ export default {
} }
return parent; return parent;
}, },
} }
} }

View File

@@ -1,240 +1,240 @@
<template> <template>
<view v-if="showPopup" class="uni-popup" :class="[popupstyle, isDesktop ? 'fixforpc-z-index' : '']" @touchmove.stop.prevent="clear"> <view v-if="showPopup" class="uni-popup" :class="[popupstyle, isDesktop ? 'fixforpc-z-index' : '']" @touchmove.stop.prevent="clear">
<view @touchstart="touchstart" > <view @touchstart="touchstart" >
<uni-transition key="1" v-if="maskShow" name="mask" mode-class="fade" :styles="maskClass" :duration="duration" :show="showTrans" @click="onTap" /> <uni-transition key="1" v-if="maskShow" name="mask" mode-class="fade" :styles="maskClass" :duration="duration" :show="showTrans" @click="onTap" />
<uni-transition key="2" :mode-class="ani" name="content" :styles="transClass" :duration="duration" :show="showTrans" @click="onTap"> <uni-transition key="2" :mode-class="ani" name="content" :styles="transClass" :duration="duration" :show="showTrans" @click="onTap">
<view class="uni-popup__wrapper" :style="{ backgroundColor: bg }" :class="[popupstyle]" @click="clear"><slot /></view> <view class="uni-popup__wrapper" :style="{ backgroundColor: bg }" :class="[popupstyle]" @click="clear"><slot /></view>
</uni-transition> </uni-transition>
</view> </view>
<!-- #ifdef H5 --> <!-- #ifdef H5 -->
<keypress v-if="maskShow" @esc="onTap" /> <keypress v-if="maskShow" @esc="onTap" />
<!-- #endif --> <!-- #endif -->
</view> </view>
</template> </template>
<script> <script>
// #ifdef H5 // #ifdef H5
import keypress from './keypress.js' import keypress from './keypress.js'
// #endif // #endif
/** /**
* PopUp 弹出层 * PopUp 弹出层
* @description 弹出层组件,为了解决遮罩弹层的问题 * @description 弹出层组件,为了解决遮罩弹层的问题
* @tutorial https://ext.dcloud.net.cn/plugin?id=329 * @tutorial https://ext.dcloud.net.cn/plugin?id=329
* @property {String} type = [top|center|bottom|left|right|message|dialog|share] 弹出方式 * @property {String} type = [top|center|bottom|left|right|message|dialog|share] 弹出方式
* @value top 顶部弹出 * @value top 顶部弹出
* @value center 中间弹出 * @value center 中间弹出
* @value bottom 底部弹出 * @value bottom 底部弹出
* @value left 左侧弹出 * @value left 左侧弹出
* @value right 右侧弹出 * @value right 右侧弹出
* @value message 消息提示 * @value message 消息提示
* @value dialog 对话框 * @value dialog 对话框
* @value share 底部分享示例 * @value share 底部分享示例
* @property {Boolean} animation = [ture|false] 是否开启动画 * @property {Boolean} animation = [ture|false] 是否开启动画
* @property {Boolean} maskClick = [ture|false] 蒙版点击是否关闭弹窗 * @property {Boolean} maskClick = [ture|false] 蒙版点击是否关闭弹窗
* @property {String} backgroundColor 主窗口背景色 * @property {String} backgroundColor 主窗口背景色
* @property {Boolean} safeArea 是否适配底部安全区 * @property {Boolean} safeArea 是否适配底部安全区
* @event {Function} change 打开关闭弹窗触发e={show: false} * @event {Function} change 打开关闭弹窗触发e={show: false}
* @event {Function} maskClick 点击遮罩触发 * @event {Function} maskClick 点击遮罩触发
*/ */
export default { export default {
name: 'uniPopup', name: 'uniPopup',
components: { components: {
// #ifdef H5 // #ifdef H5
keypress keypress
// #endif // #endif
}, },
emits:['change','maskClick'], emits:['change','maskClick'],
props: { props: {
// 开启动画 // 开启动画
animation: { animation: {
type: Boolean, type: Boolean,
default: true default: true
}, },
// 弹出层类型可选值top: 顶部弹出层bottom底部弹出层center全屏弹出层 // 弹出层类型可选值top: 顶部弹出层bottom底部弹出层center全屏弹出层
// message: 消息提示 ; dialog : 对话框 // message: 消息提示 ; dialog : 对话框
type: { type: {
type: String, type: String,
default: 'center' default: 'center'
}, },
// maskClick // maskClick
maskClick: { maskClick: {
type: Boolean, type: Boolean,
default: true default: true
}, },
backgroundColor: { backgroundColor: {
type: String, type: String,
default: 'none' default: 'none'
}, },
safeArea:{ safeArea:{
type: Boolean, type: Boolean,
default: true default: true
} }
}, },
watch: { watch: {
/** /**
* 监听type类型 * 监听type类型
*/ */
type: { type: {
handler: function(type) { handler: function(type) {
if (!this.config[type]) return if (!this.config[type]) return
this[this.config[type]](true) this[this.config[type]](true)
}, },
immediate: true immediate: true
}, },
isDesktop: { isDesktop: {
handler: function(newVal) { handler: function(newVal) {
if (!this.config[newVal]) return if (!this.config[newVal]) return
this[this.config[this.type]](true) this[this.config[this.type]](true)
}, },
immediate: true immediate: true
}, },
/** /**
* 监听遮罩是否可点击 * 监听遮罩是否可点击
* @param {Object} val * @param {Object} val
*/ */
maskClick: { maskClick: {
handler: function(val) { handler: function(val) {
this.mkclick = val this.mkclick = val
}, },
immediate: true immediate: true
} }
}, },
data() { data() {
return { return {
duration: 300, duration: 300,
ani: [], ani: [],
showPopup: false, showPopup: false,
showTrans: false, showTrans: false,
popupWidth: 0, popupWidth: 0,
popupHeight: 0, popupHeight: 0,
config: { config: {
top: 'top', top: 'top',
bottom: 'bottom', bottom: 'bottom',
center: 'center', center: 'center',
left: 'left', left: 'left',
right: 'right', right: 'right',
message: 'top', message: 'top',
dialog: 'center', dialog: 'center',
share: 'bottom' share: 'bottom'
}, },
maskClass: { maskClass: {
position: 'fixed', position: 'fixed',
bottom: 0, bottom: 0,
top: 0, top: 0,
left: 0, left: 0,
right: 0, right: 0,
backgroundColor: 'rgba(0, 0, 0, 0.4)' backgroundColor: 'rgba(0, 0, 0, 0.4)'
}, },
transClass: { transClass: {
position: 'fixed', position: 'fixed',
left: 0, left: 0,
right: 0 right: 0
}, },
maskShow: true, maskShow: true,
mkclick: true, mkclick: true,
popupstyle: this.isDesktop ? 'fixforpc-top' : 'top' popupstyle: this.isDesktop ? 'fixforpc-top' : 'top'
} }
}, },
computed: { computed: {
isDesktop() { isDesktop() {
return this.popupWidth >= 500 && this.popupHeight >= 500 return this.popupWidth >= 500 && this.popupHeight >= 500
}, },
bg() { bg() {
if (this.backgroundColor === '' || this.backgroundColor === 'none') { if (this.backgroundColor === '' || this.backgroundColor === 'none') {
return 'transparent' return 'transparent'
} }
return this.backgroundColor return this.backgroundColor
} }
}, },
mounted() { mounted() {
const fixSize = () => { const fixSize = () => {
const { windowWidth, windowHeight, windowTop, safeAreaInsets } = uni.getSystemInfoSync() const { windowWidth, windowHeight, windowTop, safeAreaInsets } = uni.getSystemInfoSync()
this.popupWidth = windowWidth this.popupWidth = windowWidth
this.popupHeight = windowHeight + windowTop this.popupHeight = windowHeight + windowTop
// 是否适配底部安全区 // 是否适配底部安全区
if(this.safeArea){ if(this.safeArea){
this.safeAreaInsets = safeAreaInsets this.safeAreaInsets = safeAreaInsets
}else{ }else{
this.safeAreaInsets = 0 this.safeAreaInsets = 0
} }
} }
fixSize() fixSize()
// #ifdef H5 // #ifdef H5
// window.addEventListener('resize', fixSize) // window.addEventListener('resize', fixSize)
// this.$once('hook:beforeDestroy', () => { // this.$once('hook:beforeDestroy', () => {
// window.removeEventListener('resize', fixSize) // window.removeEventListener('resize', fixSize)
// }) // })
// #endif // #endif
}, },
created() { created() {
this.mkclick = this.maskClick this.mkclick = this.maskClick
if (this.animation) { if (this.animation) {
this.duration = 300 this.duration = 300
} else { } else {
this.duration = 0 this.duration = 0
} }
// TODO 处理 message 组件生命周期异常的问题 // TODO 处理 message 组件生命周期异常的问题
this.messageChild = null this.messageChild = null
// TODO 解决头条冒泡的问题 // TODO 解决头条冒泡的问题
this.clearPropagation = false this.clearPropagation = false
}, },
methods: { methods: {
/** /**
* 公用方法,不显示遮罩层 * 公用方法,不显示遮罩层
*/ */
closeMask() { closeMask() {
this.maskShow = false this.maskShow = false
}, },
/** /**
* 公用方法,遮罩层禁止点击 * 公用方法,遮罩层禁止点击
*/ */
disableMask() { disableMask() {
this.mkclick = false this.mkclick = false
}, },
// TODO nvue 取消冒泡 // TODO nvue 取消冒泡
clear(e) { clear(e) {
// #ifndef APP-NVUE // #ifndef APP-NVUE
e.stopPropagation() e.stopPropagation()
// #endif // #endif
this.clearPropagation = true this.clearPropagation = true
}, },
open(direction) { open(direction) {
let innerType = ['top', 'center', 'bottom', 'left', 'right', 'message', 'dialog', 'share'] let innerType = ['top', 'center', 'bottom', 'left', 'right', 'message', 'dialog', 'share']
if (!(direction && innerType.indexOf(direction) !== -1)) { if (!(direction && innerType.indexOf(direction) !== -1)) {
direction = this.type direction = this.type
} }
if (!this.config[direction]) { if (!this.config[direction]) {
console.error('缺少类型:', direction) console.error('缺少类型:', direction)
return return
} }
this[this.config[direction]]() this[this.config[direction]]()
this.$emit('change', { this.$emit('change', {
show: true, show: true,
type: direction type: direction
}) })
}, },
close(type) { close(type) {
this.showTrans = false this.showTrans = false
this.$emit('change', { this.$emit('change', {
show: false, show: false,
type: this.type type: this.type
}) })
clearTimeout(this.timer) clearTimeout(this.timer)
// // 自定义关闭事件 // // 自定义关闭事件
// this.customOpen && this.customClose() // this.customOpen && this.customClose()
this.timer = setTimeout(() => { this.timer = setTimeout(() => {
this.showPopup = false this.showPopup = false
}, 300) }, 300)
}, },
// TODO 处理冒泡事件,头条的冒泡事件有问题 ,先这样兼容 // TODO 处理冒泡事件,头条的冒泡事件有问题 ,先这样兼容
touchstart(){ touchstart(){
this.clearPropagation = false this.clearPropagation = false
}, },
onTap() { onTap() {
if (this.clearPropagation) { if (this.clearPropagation) {
// fix by mehaotian 兼容 nvue // fix by mehaotian 兼容 nvue
@@ -242,162 +242,162 @@ export default {
return return
} }
this.$emit('maskClick') this.$emit('maskClick')
if (!this.mkclick) return if (!this.mkclick) return
this.close() this.close()
}, },
/** /**
* 顶部弹出样式处理 * 顶部弹出样式处理
*/ */
top(type) { top(type) {
this.popupstyle = this.isDesktop ? 'fixforpc-top' : 'top' this.popupstyle = this.isDesktop ? 'fixforpc-top' : 'top'
this.ani = ['slide-top'] this.ani = ['slide-top']
this.transClass = { this.transClass = {
position: 'fixed', position: 'fixed',
left: 0, left: 0,
right: 0, right: 0,
backgroundColor: this.bg backgroundColor: this.bg
} }
// TODO 兼容 type 属性 ,后续会废弃 // TODO 兼容 type 属性 ,后续会废弃
if (type) return if (type) return
this.showPopup = true this.showPopup = true
this.showTrans = true this.showTrans = true
this.$nextTick(() => { this.$nextTick(() => {
if (this.messageChild && this.type === 'message') { if (this.messageChild && this.type === 'message') {
this.messageChild.timerClose() this.messageChild.timerClose()
} }
}) })
}, },
/** /**
* 底部弹出样式处理 * 底部弹出样式处理
*/ */
bottom(type) { bottom(type) {
this.popupstyle = 'bottom' this.popupstyle = 'bottom'
this.ani = ['slide-bottom'] this.ani = ['slide-bottom']
this.transClass = { this.transClass = {
position: 'fixed', position: 'fixed',
left: 0, left: 0,
right: 0, right: 0,
bottom: 0, bottom: 0,
paddingBottom: (this.safeAreaInsets && this.safeAreaInsets.bottom) || 0, paddingBottom: (this.safeAreaInsets && this.safeAreaInsets.bottom) || 0,
backgroundColor: this.bg backgroundColor: this.bg
} }
// TODO 兼容 type 属性 ,后续会废弃 // TODO 兼容 type 属性 ,后续会废弃
if (type) return if (type) return
this.showPopup = true this.showPopup = true
this.showTrans = true this.showTrans = true
}, },
/** /**
* 中间弹出样式处理 * 中间弹出样式处理
*/ */
center(type) { center(type) {
this.popupstyle = 'center' this.popupstyle = 'center'
this.ani = ['zoom-out', 'fade'] this.ani = ['zoom-out', 'fade']
this.transClass = { this.transClass = {
position: 'fixed', position: 'fixed',
/* #ifndef APP-NVUE */ /* #ifndef APP-NVUE */
display: 'flex', display: 'flex',
flexDirection: 'column', flexDirection: 'column',
/* #endif */ /* #endif */
bottom: 0, bottom: 0,
left: 0, left: 0,
right: 0, right: 0,
top: 0, top: 0,
justifyContent: 'center', justifyContent: 'center',
alignItems: 'center' alignItems: 'center'
} }
// TODO 兼容 type 属性 ,后续会废弃 // TODO 兼容 type 属性 ,后续会废弃
if (type) return if (type) return
this.showPopup = true this.showPopup = true
this.showTrans = true this.showTrans = true
}, },
left(type) { left(type) {
this.popupstyle = 'left' this.popupstyle = 'left'
this.ani = ['slide-left'] this.ani = ['slide-left']
this.transClass = { this.transClass = {
position: 'fixed', position: 'fixed',
left: 0, left: 0,
bottom: 0, bottom: 0,
top: 0, top: 0,
backgroundColor: this.bg, backgroundColor: this.bg,
/* #ifndef APP-NVUE */ /* #ifndef APP-NVUE */
display: 'flex', display: 'flex',
flexDirection: 'column' flexDirection: 'column'
/* #endif */ /* #endif */
} }
// TODO 兼容 type 属性 ,后续会废弃 // TODO 兼容 type 属性 ,后续会废弃
if (type) return if (type) return
this.showPopup = true this.showPopup = true
this.showTrans = true this.showTrans = true
}, },
right(type) { right(type) {
this.popupstyle = 'right' this.popupstyle = 'right'
this.ani = ['slide-right'] this.ani = ['slide-right']
this.transClass = { this.transClass = {
position: 'fixed', position: 'fixed',
bottom: 0, bottom: 0,
right: 0, right: 0,
top: 0, top: 0,
backgroundColor: this.bg, backgroundColor: this.bg,
/* #ifndef APP-NVUE */ /* #ifndef APP-NVUE */
display: 'flex', display: 'flex',
flexDirection: 'column' flexDirection: 'column'
/* #endif */ /* #endif */
} }
// TODO 兼容 type 属性 ,后续会废弃 // TODO 兼容 type 属性 ,后续会废弃
if (type) return if (type) return
this.showPopup = true this.showPopup = true
this.showTrans = true this.showTrans = true
} }
} }
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.uni-popup { .uni-popup {
position: fixed; position: fixed;
/* #ifndef APP-NVUE */ /* #ifndef APP-NVUE */
z-index: 99; z-index: 99;
/* #endif */ /* #endif */
&.top, &.top,
&.left, &.left,
&.right { &.right {
/* #ifdef H5 */ /* #ifdef H5 */
top: var(--window-top); top: var(--window-top);
/* #endif */ /* #endif */
/* #ifndef H5 */ /* #ifndef H5 */
top: 0; top: 0;
/* #endif */ /* #endif */
} }
.uni-popup__wrapper { .uni-popup__wrapper {
/* #ifndef APP-NVUE */ /* #ifndef APP-NVUE */
display: block; display: block;
/* #endif */ /* #endif */
position: relative; position: relative;
/* iphonex 等安全区设置,底部安全区适配 */ /* iphonex 等安全区设置,底部安全区适配 */
/* #ifndef APP-NVUE */ /* #ifndef APP-NVUE */
// padding-bottom: constant(safe-area-inset-bottom); // padding-bottom: constant(safe-area-inset-bottom);
// padding-bottom: env(safe-area-inset-bottom); // padding-bottom: env(safe-area-inset-bottom);
/* #endif */ /* #endif */
&.left, &.left,
&.right { &.right {
/* #ifdef H5 */ /* #ifdef H5 */
padding-top: var(--window-top); padding-top: var(--window-top);
/* #endif */ /* #endif */
/* #ifndef H5 */ /* #ifndef H5 */
padding-top: 0; padding-top: 0;
/* #endif */ /* #endif */
flex: 1; flex: 1;
} }
} }
} }
.fixforpc-z-index { .fixforpc-z-index {
/* #ifndef APP-NVUE */ /* #ifndef APP-NVUE */
z-index: 999; z-index: 999;
/* #endif */ /* #endif */
} }
.fixforpc-top { .fixforpc-top {
top: 0; top: 0;
} }
</style> </style>

View File

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

View File

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

View File

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

View File

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