Compare commits

...

170 Commits

Author SHA1 Message Date
0fa0f4ae3d [发布权证改版] 2021-12-14 16:35:10 +08:00
zhangmanman
faa6c23826 Merge branch 'main' of https://git.yuzhankeji.cn/TmOct5/BlockChainH5 into main 2021-11-30 15:09:57 +08:00
zhangmanman
1e474cb82f [修改任务] 2021-11-30 15:09:46 +08:00
b22df1d58d ['同步线上'] 2021-11-26 12:02:50 +08:00
86ef1ed56a ['同步下'] 2021-11-26 11:52:36 +08:00
47667b9177 [发布商品认证及商品认证展示,详情页面水晶展示位置] 2021-11-26 11:33:51 +08:00
唐明明
4f2b502ce8 代码检查器 2021-11-24 16:05:09 +08:00
唐明明
842332ef6b 钱包提现 2021-11-24 10:48:07 +08:00
唐明明
a5a6b924a2 merge 2021-11-24 10:37:29 +08:00
唐明明
bcd57cffb1 remove/unpackage 2021-11-24 10:36:17 +08:00
zhangmanman
5af586650c Merge branch 'main' of https://git.yuzhankeji.cn/TmOct5/BlockChainH5 into main 2021-11-24 10:33:43 +08:00
zhangmanman
480a920171 [修改优惠券管理,添加我的优惠券,修改签到页面] 2021-11-24 10:33:38 +08:00
唐明明
0533ac5715 移出node模块文件 2021-11-24 10:32:27 +08:00
唐明明
b13e8ab0c7 调整git过滤文件 2021-11-24 10:29:56 +08:00
zhangmanman
33368111c0 [修改优惠券管理,添加我的优惠券,修改签到页面] 2021-11-24 10:23:46 +08:00
zhangmanman
4bc4b07628 [修改优惠券管理,添加我的优惠券,修改签到页面] 2021-11-24 10:20:07 +08:00
唐明明
eba5f59956 更新 '.gitignore' 2021-11-24 10:19:45 +08:00
zhangmanman
324193a919 [修改优惠券管理,添加我的优惠券,修改签到页面] 2021-11-24 10:03:47 +08:00
c85f1bccc0 同步数据'] 2021-11-24 09:39:59 +08:00
08965725ff 修改钻石大小及组件图片调整 2021-11-23 14:20:36 +08:00
02a59e7720 ['红包提现,红包转化默认值处理优化'] 2021-11-23 10:59:20 +08:00
4611cb984e [商品详情交易数量/领取优惠券状态/隐藏交易次数,位置改为水晶贡献值/改商品认证] 2021-11-23 09:10:23 +08:00
11dd119d0c [合并代码] 2021-11-22 17:31:28 +08:00
d4c12b5499 []... 2021-11-22 17:28:41 +08:00
唐明明
6cda5421c9 商品权证管理多余注释 2021-11-22 17:24:28 +08:00
47eb0d9ec7 ['处理搜索全部类型及查看全部跳转页面逻辑处理'] 2021-11-22 17:23:46 +08:00
唐明明
754dc91d5c 调整购物列表组件 2021-11-22 17:22:40 +08:00
唐明明
53ba8eae67 merge 2021-11-22 16:36:25 +08:00
唐明明
a683d8effc 调整首页图表 2021-11-22 16:35:33 +08:00
feb7e1a42e ['同步线上数据'] 2021-11-22 15:35:50 +08:00
2e108d2540 ['同步最新数据'] 2021-11-22 15:34:44 +08:00
唐明明
a5688f6ff8 领取水晶增加队列处理,增加批量领取 2021-11-17 15:32:21 +08:00
唐明明
0f9b01274f ts队列组件,兼容安卓小米升级方案 2021-11-15 17:17:18 +08:00
唐明明
24b23ac13c 变更商品数量,调整字段错误,推荐关系页面调整 2021-11-12 16:23:35 +08:00
唐明明
1def6bcbfc 商品权证兑换bug 2021-11-11 18:43:32 +08:00
唐明明
8dec48f748 调整购物商品兑换,节点中心调整,权证转让管理增加筛选,调整交易市场 2021-11-11 16:40:19 +08:00
唐明明
d3ca6422a0 页面调整 2021-11-10 19:24:56 +08:00
唐明明
f543bed848 调整更新信息 2021-11-10 18:58:11 +08:00
唐明明
039fb6300c 调整发货单物流信息查询 2021-11-10 18:57:51 +08:00
唐明明
c11511e1fa 修复VIP折扣价销售价的字段错误问题 2021-11-10 17:45:08 +08:00
唐明明
c1c0d720f7 调整会员页面,重构会员页面,移出会员页面冗余代码 2021-11-10 17:02:13 +08:00
唐明明
ddd62f8995 调整路由 2021-11-10 14:23:46 +08:00
唐明明
ec43dcb71c 发货单退货单模块设置 2021-11-10 13:50:03 +08:00
唐明明
87369721b8 变更退货提示信息组件,调整提示信息显示异常bug 2021-11-10 13:43:56 +08:00
唐明明
ea94e54d2b 调整版本更新,修复鉴权显示bug,调整商品认证页面样式错误 2021-11-10 11:50:51 +08:00
唐明明
273386e99f 调整节点中心页面 2021-11-09 18:06:10 +08:00
唐明明
65f0d0d059 退化货管理 2021-11-09 17:03:14 +08:00
唐明明
9749aec218 调整提现提示信息 2021-11-09 09:35:45 +08:00
唐明明
92ea90697f merge 2021-11-05 18:07:48 +08:00
唐明明
33098708f2 商品权证管理新增数据统计 2021-11-05 18:07:10 +08:00
883b032d8d 修改物流弹窗及个人中心企业工具弹窗及员工模块的发货单管理,退换货管理新增 2021-11-05 17:30:48 +08:00
唐明明
786419212f merge 2021-11-05 17:25:16 +08:00
唐明明
f8500192b3 支付宝提现 2021-11-05 17:24:40 +08:00
e4d777887b 现金红包提示 2021-11-05 15:06:19 +08:00
50b0322d95 Merge branch 'main' of https://git.yuzhankeji.cn/TmOct5/BlockChainH5 2021-11-05 14:46:54 +08:00
4c77d25ceb 节点中心t-1错误提示处理 2021-11-05 14:46:45 +08:00
唐明明
0717891b31 merge 2021-11-05 10:32:47 +08:00
唐明明
5e390f2474 同步代码 2021-11-05 10:32:18 +08:00
30ff4209ab 同步最新 2021-11-04 18:18:57 +08:00
495d3ba586 ['解决打包文件冲突'] 2021-11-04 18:02:41 +08:00
b1c0e12afa ['门店列表可滚动'] 2021-11-04 18:01:56 +08:00
唐明明
24a3f809a6 调整部分页面颜色 2021-11-04 17:11:14 +08:00
唐明明
5f7c8c36ca 交易市场新增微信支付 2021-11-04 16:49:09 +08:00
唐明明
f8aed4d12c 店铺router 2021-11-04 16:20:18 +08:00
36c7d5019c [...] 2021-11-04 16:17:29 +08:00
唐明明
cc8833e353 创建商品转跳店铺状态维护 2021-11-04 16:15:24 +08:00
唐明明
217f7fa920 调整企业认证样式错误问题 2021-11-04 15:58:24 +08:00
1a7211d1e4 [处理冲突删除打包无意义文件] 2021-11-04 15:57:15 +08:00
a1c05786c7 ['发布商品必须企业店铺处理'] 2021-11-04 15:56:04 +08:00
唐明明
f0ac413d89 调整login颜色 2021-11-04 11:33:53 +08:00
唐明明
3de021f92f 交易市场支付 2021-11-04 11:31:50 +08:00
唐明明
d9b4d459ae 调整全局支付收银class 2021-11-04 11:30:15 +08:00
c011538220 兼容合作商品和价格贡献值并排搜索 2021-11-04 11:27:57 +08:00
9ee77c73fc 搜索列表及商品列表筛选条件优化,及商品详情页处理服务报错原因和顶部颜色; 2021-11-04 10:53:34 +08:00
f8aa690216 Merge branch 'main' of https://git.yuzhankeji.cn/TmOct5/BlockChainH5 2021-11-04 08:59:00 +08:00
5a478ed794 同步代码 2021-11-04 08:58:49 +08:00
唐明明
cbe6cc912b merge 2021-11-03 20:13:25 +08:00
唐明明
c7cacd2c9c 调整全局颜色,调整部分pagesJson,调整样式 2021-11-03 20:13:03 +08:00
3e22daa807 ['解决冲突'] 2021-11-03 19:00:38 +08:00
87b8fe22d0 解决冲突 2021-11-03 18:43:00 +08:00
1df114459c 商品列表筛选,贡献值筛选,贡献值图标,区块链证书信息完善,商品溯源信息新增接口,时间轴处理等细节完善 2021-11-03 18:36:04 +08:00
唐明明
72a3d53a17 merge 2021-11-03 16:56:55 +08:00
唐明明
2a6cd3a959 调整全局颜色,新增转让市场 2021-11-03 16:56:06 +08:00
唐明明
6cb32203bf 更新 2021-11-03 10:18:31 +08:00
416fc09bab 【商品规格调整】 2021-11-02 20:34:51 +08:00
0d44c66396 ['不上传打包文件,及不处理商品权证规格字段变更问题'] 2021-11-02 18:13:54 +08:00
4509f47165 [同步最新] 2021-11-02 18:11:05 +08:00
唐明明
d0596bd8a2 调整universallinks 2021-11-02 17:25:12 +08:00
唐明明
84c4b3a097 同步代码 2021-11-02 16:49:34 +08:00
唐明明
531b0ab03f 调整支付,调整版本热更 2021-11-02 14:54:41 +08:00
f156aed14d Merge branch 'main' of https://git.yuzhankeji.cn/TmOct5/BlockChainH5 2021-11-02 09:21:55 +08:00
2aa4c594c0 ['同步最新的'] 2021-11-02 09:21:37 +08:00
唐明明
a6e97583ee 调整版本更新url地址 2021-11-01 19:28:34 +08:00
唐明明
634f7c33e4 调整商品支付失败转跳方式 2021-11-01 18:51:37 +08:00
唐明明
4acbd258b2 新增引导图调整购买转跳 2021-11-01 18:48:47 +08:00
唐明明
ff8870b9bb merge 2021-11-01 17:25:15 +08:00
唐明明
61366da9d2 版本检测接口 2021-11-01 17:24:30 +08:00
f47eb531b7 ['用户提现、通证兑换红包等个人认证限制'] 2021-11-01 16:33:43 +08:00
267f9cf17f [节点中心的我的伙伴板块中,伙伴文字变更为粉丝。个人中心个人认证去掉,直接跳转到会员购买页面] 2021-11-01 16:03:57 +08:00
唐明明
cb0da38a87 merge 2021-10-29 16:54:35 +08:00
唐明明
5960d1cf8c 系统版本号 2021-10-29 16:54:00 +08:00
b3690d82a8 [统一分享格式] 2021-10-29 16:35:43 +08:00
0682a04664 [商品分享微信好友和朋友圈处理邀请码和商品id] 2021-10-29 16:17:05 +08:00
18fc1f2239 完善商品邀请 2021-10-29 15:21:09 +08:00
f2eafd91f1 调整商品邀请 2021-10-29 15:15:35 +08:00
d45410e6f2 [同步代码] 2021-10-29 14:28:53 +08:00
唐明明
6e6a772931 merge 2021-10-29 14:28:17 +08:00
唐明明
2a0d37dff6 邀请关系 2021-10-29 14:27:37 +08:00
e5ba70c517 [...] 2021-10-29 13:15:35 +08:00
67faa74463 Merge branch 'main' of https://git.yuzhankeji.cn/TmOct5/BlockChainH5 2021-10-29 11:54:24 +08:00
8b5ff33e31 [支付宝支付0元支付和有金额支付两种,] 2021-10-29 11:54:17 +08:00
唐明明
7ec26ffa3a merge 2021-10-29 11:46:08 +08:00
唐明明
ac75d21177 merge 2021-10-29 11:45:51 +08:00
efdd8e61cb [...] 2021-10-29 10:47:43 +08:00
e79bb6df78 [解决冲突] 2021-10-29 10:32:10 +08:00
a811147c6b [去掉所有console和替换所有积分换成贡献值] 2021-10-29 10:21:41 +08:00
46279dd3d8 [报单模块添加及筛选条件,及权证管理模块没有报单兼容插件] 2021-10-28 16:48:12 +08:00
唐明明
549f59199a 移出冗余代码 2021-10-28 14:19:52 +08:00
唐明明
3913695a26 merge 2021-10-28 14:17:59 +08:00
唐明明
bd50ffcf4d 支付宝支付 2021-10-28 14:15:47 +08:00
58ec38837a [下单微信支付处理及首页隐藏优惠券和更多] 2021-10-27 17:31:29 +08:00
e4b1f33c6c [企业认证格式修改及企业认证range默认值处理同步易货] 2021-10-27 15:45:22 +08:00
011eeedcc4 [商品列表刷选一级分类和二级分类要分别处理!] 2021-10-27 15:00:08 +08:00
2c1f11afd7 [商城整个模块,及个人中心相应的模块调整] 2021-10-27 14:18:46 +08:00
e6181694d2 [发布商品新增预计到账金额] 2021-10-27 10:47:24 +08:00
d441ce2430 [同步线上文件] 2021-10-27 10:15:57 +08:00
29f5a1e755 [去升级换字段判断用is_top判断] 2021-10-27 09:53:29 +08:00
61a417065a [...] 2021-10-26 17:46:03 +08:00
961ce2b0b0 [...] 2021-10-26 17:45:16 +08:00
唐明明
89cb4bea28 更新 2021-10-26 17:26:01 +08:00
bcff29b5a9 [ 2021-10-26 17:18:29 +08:00
43813f1f50 [商品权证分页及刷新处理] 2021-10-26 17:14:33 +08:00
唐明明
422427f549 merge 2021-10-26 14:18:41 +08:00
唐明明
84fe826e1b 同步代码 2021-10-26 14:13:55 +08:00
6860a9e43c [剩余碎片文字改积分] 2021-10-26 11:40:22 +08:00
6c3add5e5a [过期跳转处理,replace不好用] 2021-10-26 11:36:14 +08:00
f4f3bb8de1 [...] 2021-10-26 10:03:05 +08:00
e4b8a33d7c [权证核销模块样式调整] 2021-10-26 09:51:28 +08:00
唐明明
97dc6226da merge 2021-10-26 09:26:03 +08:00
唐明明
6e5d0bcce5 新增员工扫码核销 2021-10-26 09:24:06 +08:00
9b1cb130d8 [...长按删除视频。基础信息李] 2021-10-25 17:21:05 +08:00
ad67333bbf [...] 2021-10-25 16:23:23 +08:00
2bc9ea63c0 [个人认证vip会员开通,企业认证才能发布权证首页,] 2021-10-25 14:59:19 +08:00
cbfca1ad21 [权证认证跳转处理] 2021-10-25 13:08:55 +08:00
680ab05102 [修改商品权证商品规格和商品名称一致及权证认证的时候状态调整] 2021-10-25 13:08:04 +08:00
b93f540824 [二维码可分享] 2021-10-25 11:50:52 +08:00
b80e1d69e4 [权证驳回跳转及驳回修改详情报错处理及选择银行卡重新处理] 2021-10-25 10:44:41 +08:00
唐明明
4056f67853 同步代码 2021-10-22 14:40:21 +08:00
唐明明
6c2c7c6b94 修复首页转跳企业认证方式错误 2021-10-21 11:05:26 +08:00
唐明明
660ed885d3 一键登录调整优化 2021-10-20 11:03:30 +08:00
唐明明
9052c3001b 一键登录 2021-10-20 10:41:49 +08:00
唐明明
0fb9a41178 微信支付 2021-10-19 10:06:44 +08:00
唐明明
d363bb8cd7 调整一键登录 2021-10-15 16:05:25 +08:00
唐明明
440ce824d8 调整区块链电商App兼容优化 2021-10-15 15:58:04 +08:00
5c5e110a27 Merge branch 'main' of https://git.yuzhankeji.cn/TmOct5/BlockChainH5 2021-10-15 09:51:32 +08:00
9a89f3dded ['对接现金红包接口及样式处理'] 2021-10-15 09:49:18 +08:00
唐明明
c6bb2df889 merge 2021-10-15 09:42:37 +08:00
唐明明
045eb8b139 调整配置项支付 2021-10-15 09:38:47 +08:00
01a9d8eb40 ['现金红包部分页面添加及发现更多微调app端样式'] 2021-10-14 09:44:55 +08:00
50fb945707 [开通节点模块样式调整及底部按钮状态处理及申请状态处理及支未完付] 2021-10-13 16:31:58 +08:00
3bfa9a7e20 [...] 2021-10-13 13:13:35 +08:00
9e2c2bd30d [...] 2021-10-13 13:12:21 +08:00
1e57b9272a [会员中心修改样式及调节] 2021-10-13 13:11:12 +08:00
唐明明
7ee3ddee63 调整复制用户中心兼容 2021-10-13 12:04:45 +08:00
3c7ad35631 Merge branch 'main' of https://git.yuzhankeji.cn/TmOct5/BlockChainH5 2021-10-13 10:06:10 +08:00
唐明明
b6e58b2431 调整页面 2021-10-12 17:11:28 +08:00
d6253a8d8b [解决冲突] 2021-10-11 09:34:08 +08:00
c5605c568d [...] 2021-10-11 09:30:02 +08:00
唐明明
452a397a77 调整为app版本 2021-10-09 17:51:21 +08:00
唐明明
91a1ad3748 调整日期 2021-10-09 17:29:14 +08:00
738 changed files with 28555 additions and 101774 deletions

2
.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
/unpackage
/node_modules

View File

@@ -12,7 +12,7 @@
},
"h5" :
{
"launchtype" : "local"
"launchtype" : "remote"
},
"mp-weixin" :
{

120
App.vue
View File

@@ -1,36 +1,124 @@
<script>
import { getVersions } from './apis/interfaces/versions'
export default {
onLaunch: function() {
onLaunch() {
//#ifdef H5
if (typeof WeixinJSBridge == 'object' && typeof WeixinJSBridge.invoke == 'function') {
handleFontSize();
handleFontSize()
} else {
document.addEventListener('WeixinJSBridgeReady', handleFontSize, false);
}
function handleFontSize() {
// 设置网页字体为默认大小
WeixinJSBridge.invoke('setFontSizeCallback', { fontSize: 0 });
WeixinJSBridge.invoke('setFontSizeCallback', {
fontSize: 0
})
// 重写设置网页字体大小的事件
WeixinJSBridge.on('menu:setfont', function() {
WeixinJSBridge.invoke('setFontSizeCallback', { fontSize: 0 });
});
WeixinJSBridge.invoke('setFontSizeCallback', {
fontSize: 0
})
})
}
//#endif
//#ifdef APP-PLUS
// 获取系统版本号
getVersions({
platform: plus.os.name,
version : plus.runtime.versionCode
}).then(res => {
if(res.update){
uni.showModal({
title: "更新提示",
content: res.note || '版本更新信息',
confirmText: "更新",
success: modalRes => {
if (modalRes.confirm) {
if (plus.os.name == "Android") {
uni.showToast({
title: '新版本下载中,将在下载完成后自动为您安装更新包',
icon : 'none'
})
uni.downloadFile({
url : res.info.download,
success : apkPick=> {
plus.runtime.install(apkPick.tempFilePath, '', installRES => {
// 安装完成用于提示新版本引导,暂时无用
}, installERR => {
// 安装失败
})
},
onShow: function() {
console.log('App Show')
fail(err){
uni.showToast({
title: '安装包下载失败,请检查您的网络或稍后重试',
icon : 'none'
})
}
})
// plus.runtime.openURL(res.info.download, err => {
// console.log(err)
// }, 'com.android.browser');
} else{
uni.showToast({
title: 'IOS应用暂未上架请打开测试(TestFlight)工具点击更新',
icon : 'none'
})
}
}
}
})
}
}).catch(err => {
uni.showToast({
title: err.message,
icon : 'none'
})
})
//#endif
},
onHide: function() {
console.log('App Hide')
onShow() {
uni.getClipboardData({
success: res=> {
// 包含分享邀请码
if(res.data.indexOf('$InviTaTiOn$CoDe/$-?') === 2){
let parentId = res.data.replace('$InviTaTiOn$CoDe/$-?', '')
this.globalData.parentId = parentId.substr(0, 10)
if(res.data.indexOf('^GoodsId/$-?') === 30){
let goodsId = res.data.substr(42, res.data.length - 1)
setTimeout(() => {
if(this.$Route.name === 'goodsDetails' && this.$Route.query.id === goodsId) return
this.$Router.push({name: 'goodsDetails', params: {id: goodsId}})
}, 1000)
}
return
}
// 不包含用户信息
if(res.data.indexOf('^GoodsId/$-?') > -1){
let goodsId = res.data.substr(12, res.data.length - 1)
setTimeout(() => {
if(this.$Route.name === 'goodsDetails' && this.$Route.query.id === goodsId) return
this.$Router.push({name: 'goodsDetails', params: {id: goodsId}})
}, 1000)
}
}
})
},
onHide() {
console.log('App Hide');
},
globalData: {
mainColor: 'white',
parentId:''
}
};
</script>
<style>
page{
background: #F5F5F5;
<style lang="scss">
@import 'uview-ui/index.scss';
page {
background: #f5f5f5;
-webkit-text-size-adjust: 100% !important;
}
</style>
<style lang="scss">
@import "uview-ui/index.scss";
</style>

View File

@@ -6,10 +6,12 @@
*/
import store from '@/store'
import router from '../router'
// 基础配置
const config = {
apiUrl : 'https://oapi.lianshang.vip/api/', // 正式环境
// apiUrl : 'http://api.ahxh.shangkelian.cn/api/', // 测试环境
apiUrls : 'https://storage.lianshang.vip/', // 图片路径(测试/正式)
timeout : 60000
}
@@ -17,7 +19,7 @@ const config = {
let loginHintState = false
// 网络请求
const request = (parameter) => {
const request = (parameter, hideLoding) => {
// 检查url配置
if(parameter.url === 'undefined' || parameter.url === ''){
uni.showToast({
@@ -32,10 +34,11 @@ const request = (parameter) => {
'Authorization': store.getters.getToken || ''
}
// 加载提示
uni.showLoading({
if(!hideLoding) uni.showLoading({
title: '加载中',
mask : true
});
// 请求实例
return new Promise((resolve, reject) => {
uni.request({
@@ -143,7 +146,11 @@ const loginHint = () => {
showCancel:false,
success: res=> {
loginHintState = false
if (res.confirm) this.$Router.replace({name: 'Index'})
if (res.confirm) {
uni.reLaunch({
url:'/pages/index/index'
})
}
}
})
}

View File

@@ -0,0 +1,62 @@
/**
* zdx
* moduleName: 地址
*/
import { request } from '../index'
// 地址列表
const addresses = () => {
return request({
url: 'mall/addresses',
method: 'GET'
})
}
// 新增地址
const addAddresses = (data) => {
return request({
url: 'mall/addresses',
method: 'post',
data: data
})
}
// 根据地址id获取地址的详细信息
const getAddresses = (id) => {
return request({
url: 'mall/addresses/'+id,
method: 'get'
})
}
// 编辑
const editAddresses = (id,data) => {
return request({
url: 'mall/addresses/'+id,
method: 'put',
data:data
})
}
// 删除
const delAddresses = (id) => {
return request({
url: 'mall/addresses/'+id,
method: 'DELETE'
})
}
// 默认
const defaultAddresses = (id) => {
return request({
url: 'mall/addresses/'+id+'/default',
method: 'post'
})
}
export {
addresses,
addAddresses,
getAddresses,
editAddresses,
delAddresses,
defaultAddresses
}

22
apis/interfaces/alipay.js Normal file
View File

@@ -0,0 +1,22 @@
/**
* Web唐明明
* 匆匆数载恍如梦,岁月迢迢华发增。
* 碌碌无为枉半生,一朝惊醒万事空。
* moduleName: 支付宝
*/
import { request } from '../index'
// 支付宝下单
const getAliPayConfig = (orderId, data) => {
return request({
url: 'user/identities/pay/' + orderId + '/alipay',
data
})
}
export {
getAliPayConfig
}

View File

@@ -26,7 +26,7 @@ const getSms = (data) =>{
})
}
// 用户隐私协议 articles/agreement/secret 用户服务协议 articles/agreement/service
// 用户隐私,用户服务协议
const secretService = (name) =>{
return request({
@@ -34,9 +34,19 @@ const secretService = (name) =>{
})
}
// 一键登录
const keyAuth = (data) => {
return request({
url: 'user/socialite/login/unicloud/app',
method: 'POST',
data: data
}, true)
}
export {
smsAuth,
getSms,
secretService
secretService,
keyAuth
}

View File

@@ -28,11 +28,29 @@ const thawlog = (data) => {
url: 'user/account/thawlog',
method: 'POST',
data
}, true)
}
// 获取新的一批水晶
const crystalsBefore = (data) => {
return request({
url: 'user/account/crystals/before',
})
}
// 批量领取水晶
const allThawall = (data) => {
return request({
url: 'user/account/thawall',
method: 'POST',
data
})
}
export {
chain,
crystals,
thawlog
thawlog,
crystalsBefore,
allThawall
}

View File

@@ -39,9 +39,27 @@ const appliesCategory = data => {
})
}
// 企业广场
const companies = data => {
return request({
url: 'companies',
data
})
}
// 企业列表
const companiesList = data => {
return request({
url: 'companies/lists',
data
})
}
export {
appliesCreate,
applies,
appliesInfo,
appliesCategory
appliesCategory,
companies,
companiesList
}

83
apis/interfaces/coupon.js Normal file
View File

@@ -0,0 +1,83 @@
/**
* Web-zdx
* moduleName: 优惠券相关
*/
import { request } from '../index'
// 我的优惠券
const myCoupon = (data) => {
return request({
url: 'coupons/user/coupons',
method: 'get',
data: data
})
}
// 优惠券分组列表
const getCouponsListById = (id,data) => {
return request({
url: 'coupons/user/coupons/'+id+'/list',
data:data
})
}
// 根据优惠券id获取优惠券的详情信息
const getCouponsInfoById = (id) => {
return request({
url: 'coupons/user/coupons/'+id,
})
}
// 根据企业id获取企业首页的轮播图列表
const couponsByCompanyId = (data) => {
return request({
url: 'coupons/all',
method: 'get',
data: data
})
}
// 领取优惠券
const couponsGrant = (id) => {
return request({
url: 'coupons/'+id+'/grant',
method: 'POST'
})
}
// 获取优惠券可使用商品
const getGoodsByGrantId = (data) => {
return request({
url: 'user/coupons/goods',
data: data
})
}
// 使用提货券兑换商品
const exchangeGoods = (data) => {
return request({
url: 'user/coupons/exchange',
method: 'POST',
data: data
})
}
// 获取核销二维码
const getQrcodeByGrantId = (data) => {
return request({
url: 'coupons/user/coupons/qrcode',
data: data
})
}
export {
myCoupon,
couponsByCompanyId,
couponsGrant,
getGoodsByGrantId,
exchangeGoods,
getCouponsListById,
getCouponsInfoById,
getQrcodeByGrantId
}

View File

@@ -56,11 +56,20 @@ const magCouponsRecommend = id => {
})
}
// 优惠券删除
const magCouponsDel = (coupon_id) => {
return request({
url: 'coupons/tools/coupons/' + coupon_id,
method: 'DELETE'
})
}
export {
toolsCoupons,
pushCoupons,
couponsGoods,
magCouponsInfo,
magCouponsStatus,
magCouponsRecommend
magCouponsRecommend,
magCouponsDel
}

View File

@@ -1,4 +1,3 @@
/**
* Web唐明明
* 匆匆数载恍如梦,岁月迢迢华发增。
@@ -6,32 +5,34 @@
* moduleName: 商品
*/
import { request } from '../index'
import {
request
} from '../index'
// 商品管理-商品列表
const managesGoodsIndex = data => {
return request({
url: 'manages/goods/index',
data:data
data: data
})
}
// 商品管理-商品增发
const managesGoodsMint = data => {
return request({
url: 'manages/goods/'+data.id+'/mint',
data:data,
method:'POST'
url: 'manages/goods/' + data.id + '/mint',
data: data,
method: 'POST'
})
}
// 商品管理-商品燃烧
const managesGoodsBurn = data => {
return request({
url: 'manages/goods/'+data.id+'/burn',
data:data,
method:'POST'
url: 'manages/goods/' + data.id + '/burn',
data: data,
method: 'POST'
})
}
@@ -46,8 +47,8 @@ const managesGoodsCreateBefore = () => {
const managesGoodsCreate = (data) => {
return request({
url: 'manages/goods',
method:'POST',
data:data
method: 'POST',
data: data
})
}
@@ -70,7 +71,7 @@ const managesCreate = (data) => {
const managesGoodsAuth = (id, data) => {
return request({
url: 'manages/goods/' + id + '/extends',
method:'POST',
method: 'POST',
data
})
}
@@ -79,7 +80,7 @@ const managesGoodsAuth = (id, data) => {
const managesGoodsDelete = id => {
return request({
url: 'manages/goods/' + id,
method:'DELETE'
method: 'DELETE'
})
}
@@ -106,6 +107,112 @@ const managesGoodsExtends = id => {
})
}
// 领取优惠券
const managesCoupons = (id) => {
return request({
url: 'coupons/' + id + '/grant',
method: 'POST'
})
}
// 商城首页
const mall = data => {
return request({
url: "mall"
})
}
// 商品列表
const list = data => {
return request({
url: "mall/goods",
data
})
}
// 通证权益 搜索页面
const searchUrl = (apiUrl, data) => {
return request({
url: apiUrl,
data: data
})
}
// 企业行业分类
const companyCategory = () => {
return request({
url: 'companies/industry'
})
}
// 商品分类搜索-默认关键字
const randgoodsUrl = (apiUrl, data) => {
return request({
url: apiUrl,
data: data
})
}
// 商品详情
const goods = id => {
return request({
url: 'mall/goods/' + id
})
}
// 商品分类
const goodsCategory = () => {
return request({
url: 'mall/categories'
})
}
// 商品确认商品信息页面get 下单页 post
const mallBuyGoods = (data, method) => {
return request({
url: 'mall/buy/goods',
method: method,
data: data
})
}
// 区块链证书
const managesChain = (id) => {
return request({
url: 'mall/goods/' + id + '/chain'
})
}
// 商品认证
const managesAttestation = (id) => {
return request({
url: 'mall/goods/' + id + '/message'
})
}
// 商品溯源
const managesTracedTo = (id,page) => {
return request({
url: 'mall/goods/' + id + '/trace',
data:{
page: page
}
})
}
// 商品第一条溯源
const checkmessage = (id) => {
return request({
url: 'mall/goods/' + id + '/checkmessage'
})
}
// 商品类型 0全1自营2合作
const shopself = () => {
return request({
url: 'mall/shopself'
})
}
// 商品服务类型调整
const goodsExtendsCreate = (id) => {
return request({
url: 'manages/goods/' + id + '/extends/create'
})
}
export {
managesGoodsIndex,
managesGoodsMint,
@@ -118,5 +225,20 @@ export {
managesGoodsEdit,
managesCreate,
managesGoodsPut,
managesGoodsExtends
managesGoodsExtends,
managesCoupons,
mall,
list,
searchUrl,
companyCategory,
randgoodsUrl,
goods,
goodsCategory,
mallBuyGoods,
managesChain,
managesAttestation,
managesTracedTo,
checkmessage,
shopself,
goodsExtendsCreate
}

21
apis/interfaces/guide.js Normal file
View File

@@ -0,0 +1,21 @@
/**
* Web唐明明
* 匆匆数载恍如梦,岁月迢迢华发增。
* 碌碌无为枉半生,一朝惊醒万事空。
* moduleName: 启动页
*/
import { request } from '../index'
// 欢迎图
const guide = data => {
return request({
url: 'cms/banners',
data
})
}
export {
guide
}

102
apis/interfaces/market.js Normal file
View File

@@ -0,0 +1,102 @@
/**
* Web唐明明
* 匆匆数载恍如梦,岁月迢迢华发增。
* 碌碌无为枉半生,一朝惊醒万事空。
* moduleName: 转让市场
*/
import { request } from '../index'
// 转让市场
const markets = data => {
return request({
url: 'markets',
data
})
}
// 转让市场记录
const marketsLogs = data => {
return request({
url: 'markets/orders',
data
})
}
// 转让详情
const marketsInfo = id => {
return request({
url: 'markets/' + id
})
}
// 提交支付订单
const marketsBuy = (id, data) => {
return request({
url: 'markets/' + id + '/create',
method: 'POST',
data
})
}
// 转让市场支付
const marketsPay = (id, platform) => {
return request({
url: 'markets/pay/' + id + '/' + platform
})
}
// 转让权证信息
const marketsCreateInfo = symbol => {
return request({
url: 'markets/user/markets/create',
data: { symbol }
})
}
// 提交权证转让
const marketsCreate = data => {
return request({
url: 'markets/user/markets/create',
method: 'POST',
data
})
}
// 转让管理
const marketsMag = data => {
return request({
url: 'markets/user/markets',
data
})
}
// 取消转让
const marketsCancel = id => {
return request({
url: 'markets/' + id + '/cancel',
method: 'POST'
})
}
// 我的成交理事
const marketsOrdersLogs = (data, name) => {
return request({
url: 'markets/orders/' + name,
data
})
}
export {
markets,
marketsLogs,
marketsInfo,
marketsBuy,
marketsPay,
marketsCreateInfo,
marketsCreate,
marketsMag,
marketsCancel,
marketsOrdersLogs
}

View File

@@ -0,0 +1,146 @@
/**
* Web-zdx
* moduleName: 我的数权
*/
import { request } from '../index'
// 我的数权
const mallWarrants = (data) => {
return request({
url: 'mall/warrants',
method: 'GET',
data: data
})
}
// 我的数权Id获取数权详情
const mallWarrantsList = (symbol) => {
return request({
url: 'mall/warrants/exchange',
method: 'GET',
data: {
symbol:symbol
}
})
}
// 确认提货
const mallWarrantsSure = (data) => {
return request({
url: 'mall/warrants/exchange',
method: 'POST',
data: data
})
}
// 我的邮寄订单,我的提货单
const mallShipmentsPostShop = (apiUrl,data) => {
return request({
url: apiUrl,
method: 'GET',
data: data
})
}
// 根据提货单的no 获取提货单的详情
const mallShipmentsInfo = (no) => {
return request({
url: 'mall/shipments/'+no,
method: 'GET'
})
}
// 取消提货单
const mallShipmentsCancel = (shipmentNo) => {
return request({
url: 'mall/shipments/'+ shipmentNo+'/cancel',
method: 'POST'
})
}
// 签收提货单
const mallShipmentsSign = (shipmentNo) => {
return request({
url: 'mall/shipments/'+ shipmentNo+'/sign',
method: 'POST'
})
}
// 退货单申请退货
const mallShipmentsRefund = (data) => {
return request({
url: 'mall/shipments/'+ data.shipment_no+'/refund',
method: 'POST',
data:data
})
}
// 退货单申请退货前置条件
const mallShipmentsRefundInfo = (shipmentNo) => {
return request({
url: 'mall/shipments/'+ shipmentNo+'/refund',
method: 'GET'
})
}
// 查看物流接口
const mallShipmentsLogistic = (shipmentNo) => {
return request({
url: 'mall/shipments/'+ shipmentNo+'/logistic',
method: 'GET'
})
}
// 我的退货单 mall/refunds
const mallRefunds = (data) => {
return request({
url: 'mall/refunds',
method: 'GET',
data: data
})
}
//退货单详情页
const mallRefundsInfo = (no) => {
return request({
url: 'mall/refunds/'+no,
method: 'GET'
})
}
// 确认退货mall/refunds/{refund}/deliver
const mallRefundsDeliver = (data) => {
return request({
url: 'mall/refunds/'+data.refund+'/deliver',
method: 'POST',
data:data
})
}
// 提货单或者服务单生成提货二维码
const mallWarrantsQrcode = (data) => {
return request({
url: 'mall/warrants/qrcode',
method: 'GET',
data:data
})
}
export {
mallWarrants,
mallWarrantsList,
mallWarrantsSure,
mallShipmentsPostShop,
mallShipmentsInfo,
mallShipmentsCancel,
mallShipmentsSign,
mallShipmentsRefund,
mallShipmentsRefundInfo,
mallShipmentsLogistic,
mallRefunds,
mallRefundsInfo,
mallRefundsDeliver,
mallWarrantsQrcode
}

58
apis/interfaces/order.js Normal file
View File

@@ -0,0 +1,58 @@
/**
* Web唐明明
* 匆匆数载恍如梦,岁月迢迢华发增。
* 碌碌无为枉半生,一朝惊醒万事空。
* moduleName: 订单
*/
import {
request
} from '../index'
// 创建,确认订单
const buy = (data, method) => {
return request({
url: 'mall/buy/goods',
method,
data
})
}
// eb支付
const eb = (no) => {
return request({
url: 'mall/pay/' + no + '/eb',
})
}
// 微信支付
const wxPay = (data) => {
return request({
url: 'mall/pay/' + data.order_no + '/wechat',
data: data,
method: 'get'
})
}
//支付宝支付
const aliPay = (data) => {
return request({
url: 'mall/pay/' + data.order_no + '/alipay',
data: data,
method: 'get'
})
}
// EB支付
const ebPay = (data) => {
return request({
url: 'mall/pay/' + data.order_no + '/eb'
})
}
export {
buy,
eb,
wxPay,
aliPay,
ebPay
}

View File

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

View File

@@ -55,12 +55,10 @@ const companiesCode = () => {
}
// 退货单列表
const storeReturn = (state) => {
const storeReturn = data => {
return request({
url: 'manages/refunds',
data: {
state
}
data
})
}
@@ -102,12 +100,10 @@ const storeAudit = (refund_id, data) => {
}
// 提货单列表
const storeDeliver = (state) => {
const storeDeliver = (data) => {
return request({
url: 'manages/shipments',
data: {
state
}
data
})
}

View File

@@ -58,6 +58,37 @@ const userPartne = (data) => {
})
}
// 我的优惠券
const userCoupon = (data) => {
return request({
url: 'coupons/user/coupons',
data: data
})
}
// 我的优惠券-详情
const couponsInfo = (coupon_grant_id) => {
return request({
url: 'coupons/user/coupons/' + coupon_grant_id
})
}
// 我的优惠券-二维码
const getQrcodeByGrantId = (data) => {
return request({
url: 'coupons/user/coupons/qrcode',
data: data
})
}
// 我的优惠券-列表
const userCouponList = (coupon_id, data) => {
return request({
url: 'coupons/user/coupons/' + coupon_id + '/list',
data: data
})
}
export {
userIndex,
userNotice,
@@ -65,5 +96,9 @@ export {
userHelp,
userClause,
userInvite,
userPartne
userPartne,
userCoupon,
couponsInfo,
getQrcodeByGrantId,
userCouponList
}

View File

@@ -0,0 +1,23 @@
/**
* Web唐明明
* 匆匆数载恍如梦,岁月迢迢华发增。
* 碌碌无为枉半生,一朝惊醒万事空。
* moduleName: 版本信息
*/
import { request } from '../index'
// 版本检测
const getVersions = data => {
return request({
url: 'app/version',
method: 'POST',
data
})
}
export {
getVersions
}

View File

@@ -1,4 +1,3 @@
/**
* Web唐明明
* 匆匆数载恍如梦,岁月迢迢华发增。
@@ -6,7 +5,9 @@
* moduleName: 会员
*/
import { request } from '../index'
import {
request
} from '../index'
// 会员身份信息
const identities = () => {
@@ -15,37 +16,46 @@ const identities = () => {
})
}
// 开通会员
const vipOrder = (id, data) =>{
// 提交开通订单
const vipOrder = (id, data) => {
return request({
url : 'user/identities/create/' + id,
method : 'POST',
data : data
url: 'user/identities/create/' + id,
method: 'POST',
data: data
})
}
// 开通会员微信支付
const vipWechatPay = (id, data) => {
// 获取微信支付配置
const vipWechatPay = (order_id, data) => {
return request({
url: 'user/identities/pay/' + id + '/wechat',
url: 'user/identities/pay/' + order_id + '/wechat',
data
})
}
// 开通身份内容
const vipCont = (id, data) =>{
const vipCont = (id, data) => {
return request({
url : 'user/identities/create/' + id,
data : data
url: 'user/identities/create/' + id,
data: data
})
}
// 上传打款凭证
const vipVoucher = (data) =>{
const vipVoucher = (data) => {
return request({
url : 'user/voucher/store',
method : 'POST',
data : data
url: 'user/voucher/store',
method: 'POST',
data: data
})
}
// 编辑凭证
const vipVoucherUpdate = (id, data) => {
return request({
url: 'user/voucher/' + id + '/update',
method: 'POST',
data: data
})
}
@@ -62,5 +72,6 @@ export {
vipWechatPay,
vipCont,
vipVoucher,
userAgree
userAgree,
vipVoucherUpdate
}

View File

@@ -138,6 +138,13 @@ const keyrules = () => {
})
}
// 通证转红包前置,获取通证的基本信息
const accountCashs = (data) => {
return request({
url: 'user/account/cashs',
data:data
})
}
export {
seed,
hash,
@@ -154,6 +161,7 @@ export {
securityCheck,
securityReset,
cmsWithdraw,
keyrules
keyrules,
accountCashs
}

View File

@@ -82,7 +82,7 @@ const withdrawsIndexLists = (data) => {
})
}
// 能量碎片记录
// 贡献值记录
const userAccoutScores = (data) => {
return request({
url: 'user/account/scores',
@@ -91,6 +91,22 @@ const withdrawsIndexLists = (data) => {
})
}
// 通证转红包前置
const cashsCreate = () => {
return request({
url: 'user/account/cashs/create',
method: 'get'
})
}
// 通证转红包
const accountCashs = (data) => {
return request({
url: 'user/account/cashs',
method: 'POST',
data: data
})
}
export {
accountsCreate,
withdrawsAccounts,
@@ -101,5 +117,7 @@ export {
withdrawsIndexCreate,
withdrawsIndex,
withdrawsIndexLists,
userAccoutScores
userAccoutScores,
accountCashs,
cashsCreate
}

View File

@@ -0,0 +1,11 @@
{
"applinks": {
"apps": [],
"details": [
{
"appID": "io.lianshang.app",
"paths": [ "https://www.lianshang.vip/ulink/*"]
}
]
}
}

BIN
components/.DS_Store vendored Normal file

Binary file not shown.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,4 +1,3 @@
<template>
<view class="goods--list">
<block v-if="list.length > 0">
@@ -6,18 +5,30 @@
<view class="cover">
<image class="cover--src" :src="item.cover" mode="aspectFill" />
</view>
<template v-if='notag === ""'>
<span class='is_self' v-if='item.specal_tags.is_self'>{{item.specal_tags.is_self}}</span>
</template>
<template v-if='notag === ""'>
<span class='is_allow_values' v-if='item.specal_tags.is_allow_values'>
<image src="/static/imgs/baodan_hot.png" mode="widthFix" />
</span>
</template>
<view class="content">
<view class="title">{{item.name}}</view>
<view class="title">
{{item.name}}
</view>
<view class="content-flex">
<view class="price eb" v-if="priceType === 'EB'">
{{item.price}}<text>易币</text>
</view>
<view class="price cny" v-if="priceType === 'CNY'">
<text></text>{{item.original_price}}
<text></text>{{item.price.price_min}}
</view>
<view class="sales">
<slot name="statistics" :value="item">
{{item.sales}}
{{item.sales}}
<!-- 贡献值:{{item.price.pv}} <image style="width: 30rpx;" src="/static/icons/crystal-icon.png" mode="widthFix" /> -->
</slot>
</view>
</view>
@@ -34,52 +45,83 @@
</template>
<script>
export default {
name : 'goodsList',
props : {
export default {
name: 'goodsList',
props: {
notag: {
type: String,
default: ''
},
// 数据列表
list: {
type : Array,
default : () => {
type: Array,
default: () => {
return new Array
}
},
// 价格类型
priceType: {
type : String,
default : 'EB'
type: String,
default: 'EB'
},
// 列表空提示
toast : {
type : String,
default : '暂无商品数据 -_-!'
toast: {
type: String,
default: '暂无商品数据 -_-!'
}
},
methods:{
goods(e){
methods: {
goods(e) {
this.$emit('on-goods', e)
}
}
};
};
</script>
<style lang="scss" scoped>
.goods--list{
.goods--list {
padding: calc(#{$padding} - 10rpx);
display: flex;
flex-wrap: wrap;
.goods--item{
.goods--item {
background: white;
box-sizing: border-box;
width: calc(50% - 20rpx);
margin: 10rpx;
border-radius: $radius/2;
overflow: hidden;
.cover{
position: relative;
.is_self {
position: absolute;
top: 0;
right: 20rpx;
background-image: linear-gradient(to bottom, #ee4c47, #f80000);
// background-color: #ee4c47;
box-shadow: 0 4rpx 10rpx 2rpx rgba($color: #000, $alpha: .3);
color: #fff;
font-size: 26;
padding: 2rpx 20rpx 10rpx 20rpx;
border-radius: 0 0 50rpx 50rpx;
}
.is_allow_values {
position: absolute;
top: 264rpx;
left: 0;
image {
width: 180rpx;
}
}
.cover {
position: relative;
width: 100%;
padding-top: 100%;
.cover--src{
.cover--src {
position: absolute;
height: 100%;
width: 100%;
@@ -87,47 +129,63 @@ export default {
left: 0;
}
}
.content{
.content {
padding: $padding/2;
.title{
.title {
font-size: $title-size-lg;
line-height: 40rpx;
height: 80rpx;
text-align: justify;
@extend .ellipsis;
// .is_allow_values {
// color: #fff;
// background-image: linear-gradient(to left, $mian-color, $mian-color-light);
// padding: 2rpx 14rpx;
// font-size: 20rpx;
// text-align: center;
// border-radius: 30rpx;
// margin-right: 20rpx;
// }
}
.content-flex{
.content-flex {
width: 100%;
display: flex;
justify-content: space-between;
padding-top: $padding/2;
.price{
.price {
width: 50%;
color: $text-price;
font-weight: bold;
font-size: $title-size;
@extend .nowrap;
text{
text {
font-size: $title-size-sm;
font-weight: normal;
padding-left: $padding/4;
line-height: 50rpx;
}
}
.sales{
.sales {
width: 50%;
font-size: $title-size-sm;
color: $text-gray;
line-height: 50rpx;
text-align: right;
@extend .nowrap;
}
}
}
}
}
// 数据空
.goods--null{
.goods--null {
width: 100%;
padding: 200rpx 0;
text-align: center;

View File

@@ -0,0 +1,225 @@
<template>
<view class="industry--list">
<block v-if="list.length > 0">
<view class="industry--box" v-for="(item, index) in list" :key="index" @click="industry(item)">
<image class="industry--cover" :src="item.cover" mode="aspectFill"></image>
<view class="industry--vip">{{item.level.name}}</view>
<view class="industry--content">
<view class="industry--title nowrap">{{item.name}}</view>
<view class="industry--credit">信用值 {{item.integrity}}</view>
<view class="industry--trade nowrap" v-if="item.industry">行业{{item.industry.title}}</view>
<view class="industry--bar">
<view class="industry--color">
<view class="industry--strip" :style="{width: item.process + '%'}"></view>
</view>
<view class="industry--per">{{item.process}}%</view>
</view>
<!-- <view class="industry--credibility">
<uni-rate
:readonly="true"
color="#ddd"
active-color="#e93340"
:value="item.star"
:size="14"
/>
</view> -->
<!-- <uni-icons class="industry--arrow" type="arrowright" color="#ddd" size="14" /> -->
<view class="industry--tool">
<view class="industry--deal">
权证数<text class="industry--number">{{item.goodsCount}}</text>
</view>
</view>
</view>
</view>
</block>
<block v-else>
<view class="industry--null">
</view>
</block>
</view>
</template>
<script>
export default {
name: "industry-list",
props: {
// 数据列表
list: {
type: Array,
default: () => {
return new Array
}
},
// 列表空提示
toast: {
type: String,
default: '暂无商品数据 -_-!'
}
},
methods: {
industry(e) {
this.$emit('on-industry', e)
}
}
}
</script>
<style lang="scss" scoped>
// 列表信息
.industry--list {
padding-bottom: $padding;
}
.industry--box {
position: relative;
margin: $margin - 10 $margin;
background: white;
border-radius: $radius/2;
padding: $padding ($padding*3) $padding ($padding * 2 + 128);
min-height: 128rpx;
.industry--vip {
position: absolute;
top: $padding;
left: $padding;
background-color: #191919;
color: #f3c8a8;
font-size: 24rpx;
line-height: 32rpx;
padding: 0 8rpx;
border-radius: 6rpx 6rpx 6rpx 0;
}
.industry--cover {
position: absolute;
left: $padding;
top: $padding;
width: 128rpx;
height: 128rpx;
}
.industry--title {
font-weight: bold;
font-size: $title-size-lg;
width: 80%;
line-height: 40rpx;
}
.industry--credit {
font-size: 22rpx;
display: inline-block;
font-weight: normal;
color: #ec652f;
border: 2rpx solid #ec652f;
line-height: 36rpx;
border-radius: 6rpx;
padding: 0 6rpx;
margin: 10rpx 0;
}
.industry--trade {
font-size: 24rpx;
color: $text-gray;
line-height: 40rpx;
}
.industry--bar {
display: flex;
width: 70%;
margin-top: 4rpx;
.industry--color {
background: #ebebeb;
border-left: 2rpx solid transparent;
border-right: 2rpx solid transparent;
width: calc(100% - 50rpx);
border-radius: 60rpx;
margin: 6rpx 10rpx 0 0;
height: 18rpx;
.industry--strip {
background-color: #ff8562;
border: 1px solid #ff8562;
border-radius: 10px;
box-shadow: 1vw 3vh 10vh rgba(168, 7, 7, 0.8);
background-size: 3em 3em;
background-image: linear-gradient(-45deg, transparent 0em, transparent 0.8em, #ec3950 0.9em, #ec3950 2.1em, transparent 2.1em, transparent 2.9em, #ec3950 3.1em);
height: 14rpx;
border-radius: 60rpx;
position: relative;
&::after {
content: '';
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
z-index: 1;
height: 100%;
background-image: linear-gradient(to bottom, #db152e, rgba(168, 7, 7, 0.6) 15%, transparent 60%, #db152e);
border-radius: 20rpx;
}
}
}
.industry--per {
font-size: 20rpx;
color: rgba(0, 0, 0, 0.8);
transform: scale(.8);
}
}
.industry--tool {
position: absolute;
top: 60rpx;
right: $padding;
.industry--deal {
width: 120rpx;
height: 120rpx;
text-align: center;
background: linear-gradient(to bottom, #e1293f, #f85d31);
box-shadow: 0 0 14rpx rgba(260, 60, 80, .9);
color: #FFFFFF;
font-size: 26rpx;
border-radius: 50%;
padding-top: 25rpx;
box-sizing: border-box;
font-size: 24rpx;
.industry--number {
font-size: 28rpx;
font-weight: 600;
display: block;
margin-top: 4rpx;
}
}
}
.industry--credibility {
padding-top: 8rpx;
height: 48rpx;
box-sizing: border-box;
}
.industry--arrow {
position: absolute;
right: $margin;
top: 50%;
margin-top: -7px;
}
}
// 数据空
.industry--null {
width: 100%;
padding: 20vh 0;
text-align: center;
font-size: $title-size-m;
color: $text-gray;
}
</style>

View File

@@ -0,0 +1,175 @@
<template>
<view class="MallRefundsTemplate">
<view class="top">
<view class="company">
<view class="company-logo">
<image :src="item.shop.cover" mode="aspectFill" />
<view class="name ellipsis">{{item.shop.name}}</view>
</view>
<view class="no ellipsis">退货单号 {{item.refund_no}}</view>
</view>
<view class="status" style="color:#ff5500;">{{item.state.text}}</view>
</view>
<view class="goods-info" @click="goDetail(item.goods_sku.goods_id)">
<image class="goods-img" :src="item.goods_sku.cover" mode="aspectFill" />
<view class="goods">
<view class="name">
<view class="name1 ellipsis-2">{{item.goods_sku.goods_name}}</view>
<!-- <span>{{item.account.balance}}</span> -->
</view>
<view class="sku">权证个数 <span>x {{item.qty}}</span> </view>
<!-- <view class="sku">提货方式 <span> {{item.type_text}}</span> </view> -->
</view>
</view>
</view>
</template>
<script>
export default {
name: "MallRefundsTemplate",
data() {
return {
};
},
props: {
item: Object
},
methods: {
// 跳转到商品详情页面
goDetail(id) {
uni.navigateTo({
url: '/pages/goods/details?id=' + id
})
}
}
}
</script>
<style lang="scss" scoped>
.MallRefundsTemplate{
position: relative;
z-index: 0;
}
// 顶部信息
.top {
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
box-sizing: border-box;
padding-bottom: 20rpx;
border-bottom: solid 1rpx #f7f7f7;
position: relative;
z-index: 0;
.company-logo {
display: flex;
flex-direction: row;
align-items: center;
justify-content: flex-start;
box-sizing: border-box;
image {
width: 40rpx;
height: 40rpx;
border-radius: 50%;
margin-right: 20rpx;
}
.name {
width: 460rpx;
font-size: 30rpx;
color: #484848;
font-weight: bold;
}
}
.no {
margin-top: 10rpx;
font-size: $title-size*0.8;
color: #999;
width: 500rpx;
}
.status {
color: #999;
font-size: $title-size*.9;
position: absolute;
top: 0;
right: 0;
}
}
// 商品信息
.goods-info {
display: flex;
flex-direction: row;
align-items: flex-start;
justify-content: flex-start;
box-sizing: border-box;
margin-top: 36rpx;
.goods-img {
width: 120rpx;
height: 120rpx;
border-radius: 10rpx;
}
.goods {
flex: 1;
margin-left: 20rpx;
margin-bottom: 10rpx;
.name {
width: 100%;
display: flex;
flex-direction: row;
align-items: flex-start;
justify-content: space-between;
box-sizing: border-box;
font-size: 30rpx;
// font-weight: bold;
.name1 {
// width: 340rpx;
}
span {
font-size: 32rpx;
font-weight: normal;
}
}
.sku {
flex: 1;
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
box-sizing: border-box;
margin-top: 10rpx;
font-size: 28rpx;
color: #999;
}
}
}
.flexrow {
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
box-sizing: border-box;
width: 100%;
.copy {
color: $mian-color;
font-size: $title-size*0.8;
font-weight: 400;
padding: 0 30rpx;
}
}
</style>

View File

@@ -0,0 +1,172 @@
<template>
<view class="MallShipmentTemplate" >
<view class="top" >
<view class="company">
<view class="company-logo">
<image :src="item.shop.cover" mode="aspectFill" />
<view class="name ellipsis">{{item.shop.name}}</view>
</view>
<view class="no ellipsis">发货单号 {{item.shipment_no}}</view>
<!-- <view class="no ellipsis">创建时间 {{item.created_at}}</view> -->
</view>
<view class="status" style="color:#DD524D;">{{item.state_text}}</view>
</view>
<view class="goods-info" @click="goDetail(item.goods_sku.goods_id)">
<image class="goods-img" :src="item.goods_sku.cover" mode="aspectFill" />
<view class="goods">
<view class="name">
<view class="name1 ellipsis-2">{{item.goods_sku.goods_name}}</view>
<!-- <span>{{item.account.balance}}</span> -->
</view>
<view class="sku">权证个数 <span>x {{item.qty}}</span> </view>
<view class="sku" v-if="item.goods_type === 2">使用方式 <span> 门店使用</span> </view>
<view class="sku" v-else>提货方式 <span> {{item.type_text}}</span> </view>
</view>
</view>
</view>
</template>
<script>
export default {
name: "MallShipmentTemplate",
data() {
return {
};
},
props:{
item:Object
},
methods: {
// 跳转到商品详情页面
goDetail(id) {
uni.navigateTo({
url: '/pages/goods/details?id='+id
})
}
}
}
</script>
<style lang="scss" scoped>
// 顶部信息
.top {
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
box-sizing: border-box;
padding-bottom: 20rpx;
border-bottom: solid 1rpx #f7f7f7;
position: relative;
z-index: 0;
.company-logo {
display: flex;
flex-direction: row;
align-items: center;
justify-content: flex-start;
box-sizing: border-box;
image {
width: 40rpx;
height: 40rpx;
border-radius: 50%;
margin-right: 20rpx;
}
.name {
width: 460rpx;
font-size: 30rpx;
color: #484848;
font-weight: bold;
}
}
.no {
margin-top: 10rpx;
font-size: $title-size*0.8;
color: #999;
width: 530rpx;
}
.status {
color: #999;
font-size: $title-size*.9;
position: absolute;
top: 0;
right: 0;
}
}
// 商品信息
.goods-info {
display: flex;
flex-direction: row;
align-items: flex-start;
justify-content: flex-start;
box-sizing: border-box;
margin-top: 36rpx;
.goods-img {
width: 120rpx;
height: 120rpx;
border-radius: 10rpx;
}
.goods {
flex: 1;
margin-left: 20rpx;
margin-bottom: 10rpx;
.name {
width: 100%;
display: flex;
flex-direction: row;
align-items: flex-start;
justify-content: space-between;
box-sizing: border-box;
font-size: 30rpx;
// font-weight: bold;
.name1 {
// width: 340rpx;
}
span {
font-size: 32rpx;
font-weight: normal;
}
}
.sku {
flex: 1;
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
box-sizing: border-box;
margin-top: 10rpx;
font-size: 28rpx;
color: #999;
}
}
}
.flexrow{
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
box-sizing: border-box;
width: 100%;
.copy{
color: $mian-color;
font-size: $title-size*0.8;
font-weight: 400;
padding: 0 30rpx;
}
}
</style>

View File

@@ -21,7 +21,6 @@
* no-goods没有商品
* no-list没有订单列表
* no-news没有任何消息
* no-new1没有任何消息1
* no-chain (没有区块链信息)
* no-collection没有任何收藏信息
* no-foot (没有足迹信息)

View File

@@ -0,0 +1,182 @@
<template>
<view class="OrderTemplate">
<view class="top" v-if="isTop">
<view class="company">
<view class="company-logo">
<image :src="item.shop.cover" mode="aspectFill" />
<view class="name ellipsis">{{ item.shop.name }}</view>
</view>
<view class="flexrow">
<view class="no ellipsis">区块链地址 {{ item.account.addr }}</view>
<span class="copy" @click="copy(item.account.addr)">复制</span>
</view>
</view>
</view>
<view class="goods-info" @click="goDetail(item.goods.goods_id)">
<image class="goods-img" :src="item.goods.cover" mode="aspectFill" />
<view class="goods">
<view class="name">
<view class="name1 ellipsis-2">{{ item.goods.goods_name }}</view>
<!-- <span>{{item.account.balance}}</span> -->
</view>
<view class="sku">
权证个数
<span>x {{ item.account.balance }}</span>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
name: 'OrderTemplate',
data() {
return {};
},
props: {
item: Object,
isTop: {
type: Boolean,
default: true
}
},
onShow() {
console.log(this.item, 'onshow,numtempa');
},
methods: {
// 跳转到商品详情页面
goDetail(id) {
uni.navigateTo({
url: '/pages/goods/details?id=' + id
});
},
// 复制
copy(e) {
uni.setClipboardData({
data: e,
success: res => {
console.log('res', res);
}
});
}
}
};
</script>
<style lang="scss" scoped>
// 顶部信息
.top {
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
box-sizing: border-box;
padding-bottom: 20rpx;
border-bottom: solid 1rpx #f7f7f7;
.company-logo {
display: flex;
flex-direction: row;
align-items: center;
justify-content: flex-start;
box-sizing: border-box;
image {
width: 40rpx;
height: 40rpx;
border-radius: 50%;
margin-right: 20rpx;
}
.name {
width: 600rpx;
font-size: 30rpx;
color: #484848;
font-weight: bold;
}
}
.no {
margin-top: 10rpx;
font-size: $title-size * 0.8;
color: #999;
width: 500rpx;
}
.status {
color: #999;
font-size: $title-size;
}
}
// 商品信息
.goods-info {
display: flex;
flex-direction: row;
align-items: flex-start;
justify-content: flex-start;
box-sizing: border-box;
margin-top: 36rpx;
.goods-img {
width: 120rpx;
height: 120rpx;
border-radius: 10rpx;
}
.goods {
flex: 1;
margin-left: 20rpx;
margin-bottom: 10rpx;
.name {
width: 100%;
display: flex;
flex-direction: row;
align-items: flex-start;
justify-content: space-between;
box-sizing: border-box;
font-size: 30rpx;
// font-weight: bold;
.name1 {
// width: 340rpx;
}
span {
font-size: 32rpx;
font-weight: normal;
}
}
.sku {
flex: 1;
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
box-sizing: border-box;
margin-top: 10rpx;
font-size: 28rpx;
color: #999;
}
}
}
.flexrow {
position: relative;
padding-right: 200rpx;
line-height: 50rpx;
.no{
white-space:nowrap;
}
.copy {
line-height: 50rpx;
position: absolute;
right: 30rpx;
top: 0;
color: $mian-color;
font-size: $title-size * 0.8;
font-weight: 400;
padding: 0 30rpx;
}
}
</style>

View File

@@ -1,35 +1,49 @@
<template>
<view>
<block v-if="list.length > 0">
<view class="record--item" v-for="(item, index) in list" :key="index" v-if="item">
<view class="title ellipsis">{{item.hash || '-'}}</view>
<view class="time ellipsis">{{item.block_time || '-'}}</view>
<view class="record--item" v-for="(item, index) in list" :key="index" v-if="item && !hash">
<view class="title ellipsis-1">{{item.rule.title}} <span> {{item.coin?' ('+item.coin+'个通证) ':''}} </span></view>
<view class="time ellipsis-1">{{item.created_at || '-'}}</view>
<view class="webkit-box variation">
<view class="ellipsis" :class="item.is_in ? 'add': 'remove'">{{item.is_in ? '+': '-'}}{{item.amount}}</view>
<view class="ellipsis" :class="item.amount<0 ? 'add': 'remove'">{{item.amount}}</view>
<view class="symbol">{{item.amount>0?'现金红包收入':'现金红包支出'}}</view>
</view>
</view>
<view class="record--item record--item1" v-for="(item, index) in list" :key="index" v-if="item && hash">
<view class="title ellipsis-1">{{item.hash}}</view>
<view class="time ellipsis-1">{{item.block_time || '-'}}</view>
<view class="webkit-box variation">
<view class="ellipsis" :class="item.is_in ? 'add': 'remove'">
{{item.is_in ? '+': '-'}}{{item.amount}}</view>
<view class="symbol">{{item.assets.symbol}}</view>
</view>
</view>
</block>
<block v-else>
<no-list v-if='logsType === 0' name='no-record' txt="没有任何记录~" />
<no-list v-if='logsType === 2' name='no-in' txt="没有任何收入记录~" />
<no-list v-if='logsType === 1' name='no-out' txt="没有任何支出记录~" />
<no-list v-if='logsType === ""' name='no-record' txt="没有任何记录~" />
<no-list v-if='logsType === "in"' name='no-in' txt="没有任何收入记录~" />
<no-list v-if='logsType === "out"' name='no-out' txt="没有任何支出记录~" />
</block>
</view>
</template>
<script>
export default {
name:"property",
props:{
name: "property",
props: {
list: {
type: Array,
default: () => {
return []
}
},
logsType:{
type:Number
logsType: {
type: String
},
hash: {
type: Boolean
}
},
data() {
@@ -41,12 +55,17 @@
</script>
<style lang="scss" scoped>
.record--item{
padding: $padding 320rpx $padding 0;
border-bottom: solid 1rpx $border-color;
.record--item1 {
padding: $padding 330rpx $padding 0 !important;
}
.record--item {
padding: $padding 220rpx $padding 0;
border-bottom: solid 1rpx #f7f7f7;
position: relative;
min-height: 50rpx;
.variation{
.variation {
position: absolute;
right: 0;
top: $margin;
@@ -54,31 +73,47 @@
width: 300rpx;
text-align: right;
font-weight: bold;
&>label{
&>label {
font-size: 80%;
}
.symbol{
color: $mian-color;
.symbol {
color: #666;
font-weight: normal;
font-size: $title-size-m;
}
.add{
.add {
color: $mian-color;
font-size: 36rpx;
}
.remove{
.remove {
font-size: 36rpx;
color: $mian-color;
}
}
.title{
.title {
line-height: 50rpx;
}
.time{
font-size: $title-size-m;
color: $mian-color;
font-size: 30rpx;
word-break: break-word;
span{
font-size: 24rpx;
color: #999;
}
}
.time {
font-size: 26rpx;
color: #999;
padding-top: 6rpx;
}
}
// 数据空
.record--null{
.record--null {
padding-top: $padding * 3;
text-align: center;
color: $mian-color;
@@ -86,7 +121,8 @@
height: 50vh;
box-sizing: border-box;
line-height: 60rpx;
image{
image {
width: 168rpx;
}
}

View File

@@ -0,0 +1,269 @@
<template>
<view>
<view class="OrderInfo">
<!-- 订单状态 -->
<view class="order-status">
<block v-if="listType == 'deliver'">
<view class="info">
{{info.state_text}}
</view>
</block>
<block v-else>
<view class="info" v-if="info.state">
{{info.state.text}}
<span>{{info.state.remark}}</span>
</view>
</block>
<image src="../../static/icons/fire.png" mode="widthFix"></image>
</view>
<!-- 订单信息 -->
<view class="goods-info1">
<view class="top">
<view class="company">
<view class="company-logo" v-if="info.shop">
<image :src="info.shop.cover" mode="aspectFill" />
<view class="name nowrap">{{info.shop.name}}</view>
</view>
<view class="flexrow">
<view class="no nowrap" v-if="listType == 'deliver'">发货单号 {{info.shipment_no}}</view>
<view class="no nowrap" v-else>退货单号 {{info.refund_no}}</view>
</view>
</view>
</view>
<view class="goods-info">
<image class="goods-img" v-if="info.goods_sku" :src="info.goods_sku.cover" mode="aspectFill" />
<view class="goods" v-if="info.goods_sku">
<view class="nowrap name">{{info.goods_sku.goods_name}}</view>
<view class="sku">数权个数 <span>x {{info.qty}}</span> </view>
</view>
</view>
</view>
<view class="goods-info1" >
<view class="goods-type">创建{{listType == 'deliver'?'发货':'退货'}}时间 <span>{{info.created_at}}</span></view>
<view class="goods-type">运费 <span>自行承担运费</span></view>
<view class="goods-type">{{listType === 'deliver'?'发货':'退货'}}数量 <span>{{info.qty}}</span></view>
</view>
<view class="goods-info1" v-if="listType === 'deliver' && info.express">
<view class="goods-type" v-if="info.express">收件人姓名 <span>{{info.express.name || '--'}}</span></view>
<view class="goods-type" v-if="info.express" @click="call(info.express.mobile)">收件人电话 <span>{{info.express.mobile || '--'}}</span></view>
<view class="goods-type" v-if="info.express">收货地址 <span>{{info.express.full_address || '--'}}</span></view>
<view class="goods-type" v-if="info.express">发货快递 <span>{{info.express.express_name || '--'}}</span></view>
<view class="goods-type" v-if="info.express">快递单号 <span>{{info.express.express_no || '--'}}</span></view>
</view>
<view class="goods-info1" v-else>
<view class="goods-type" v-if="info.express">退货单快递<span>{{info.express.company || '--'}}</span></view>
<view class="goods-type" v-if="info.express">退货快递单号 <span>{{info.express.number || '--'}}</span></view>
</view>
<!-- 操作相关 -->
<view class="actions">
<view class="nowPay" @click="orderRun">返回列表</view>
<view v-if="listType != 'deliver'" @click="$Router.push({name: 'storeJournal', params: {id: info.refund_id}})" class="nowPay">查看退货日志</view>
</view>
</view>
</view>
</template>
<script>
export default {
name:"storeOrderDet",
props:{
// 数据列表
info : {},
listType: ''
},
created() {
},
methods: {
// 返回上一页
orderRun() {
uni.navigateBack({
delta: 1
})
},
call(number){
uni.makePhoneCall({
phoneNumber:number
})
}
}
}
</script>
<style lang="scss" scoped>
.OrderInfo {
width: 100%;
min-height: 100vh;
box-sizing: border-box;
background-color: #F7F7F7;
padding-bottom: 80rpx;
}
.order-status {
width: 100%;
height: 300rpx;
background-image: linear-gradient(to bottom, $mian-color,$mian-color-light);
color: #Fff;
font-size: 36rpx;
padding: 30rpx 50rpx;
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
box-sizing: border-box;
.info {
font-size: 36rpx;
display: flex;
flex-direction: column;
align-items: flex-start;
justify-content: space-between;
box-sizing: border-box;
span {
font-size: 28rpx;
padding-top: 30rpx;
}
}
image {
width: 200rpx;
}
}
// 订单信息
.goods-info1 {
padding: 20rpx 40rpx;
background-color: #fff;
margin-bottom: $margin;
.top {
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
box-sizing: border-box;
padding: 30rpx 0;
border-bottom: solid 1rpx #EFF4F2;
.company-logo {
display: flex;
flex-direction: row;
align-items: center;
justify-content: flex-start;
box-sizing: border-box;
image {
width: 40rpx;
height: 40rpx;
border-radius: 50%;
margin-right: 20rpx;
}
.name {
width: 600rpx;
font-size: 30rpx;
color: #484848;
font-weight: bold;
}
.no {
margin-top: 30rpx !important;
font-size: $title-size*0.8;
color: #999;
}
}
}
.goods-info {
display: flex;
flex-direction: row;
align-items: flex-start;
justify-content: flex-start;
box-sizing: border-box;
margin-top: 40rpx;
.goods-img {
width: 120rpx;
height: 120rpx;
border-radius: 10rpx;
}
.goods {
width: calc(100% - 120rpx);
padding: 0 20rpx;
box-sizing: border-box;
.sku {
flex: 1;
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
box-sizing: border-box;
margin-top: 20rpx;
font-size: 28rpx;
color: #999;
}
}
}
.goods-type {
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
box-sizing: border-box;
padding: 30rpx 0;
border-bottom: solid 1rpx #f7f7f7;
}
}
// 操作按钮
.actions {
position: fixed;
bottom: 0;
left: 0;
right: 0;
border-top: solid 1rpx #f2f2f2;
padding-top: 18rpx;
padding-right: 30rpx;
padding-left: 30rpx;
height: 110rpx;
background: white;
display: flex;
flex-wrap: wrap;
flex-direction: row-reverse;
.nowPay {
margin-left: 20rpx;
height: 54rpx;
line-height: 50rpx;
box-sizing: border-box;
border: solid 1rpx #747788;
padding: 0 20rpx;
font-size: 26rpx;
border-radius: 40rpx;
margin-top: 10rpx;
&.actions-color {
color: #e1293f;
border-color: #ec96a0;
}
}
.cancelOrder {
padding: 10rpx 30rpx;
border-radius: 40rpx;
margin-left: 20rpx;
margin-top: 20rpx;
background-color: #DD524D;
}
.logistics {
background-color: $mian-color;
padding: 10rpx 30rpx;
border-radius: 40rpx;
margin-left: 20rpx;
margin-top: 20rpx;
}
.sign {
background-color: #DD524D;
padding: 10rpx 30rpx;
border-radius: 40rpx;
margin-left: 20rpx;
margin-top: 20rpx;
}
.evaluate {
background-color: $mian-color;
padding: 10rpx 30rpx;
border-radius: 40rpx;
margin-left: 20rpx;
margin-top: 20rpx;
}
}
</style>

View File

@@ -0,0 +1,290 @@
<template>
<view class="returnCont">
<block v-if="list.length > 0">
<view class="returnList" v-for="(item, index) in list" :key="index">
<view class="MallRefundsTemplate">
<view class="top">
<view class="company">
<view class="company-logo" v-if="item.shop">
<image :src="item.shop.cover" mode="aspectFill" />
<view class="company-name nowrap">{{item.shop.name}}</view>
</view>
<view class="no nowrap" v-if="listType == 'deliver'">退货单号 {{item.shipment_no}}</view>
<view class="no nowrap" v-else>退货单号 {{item.refund_no}}</view>
</view>
<view class="status" style="color:#ee4c47;" v-if="listType == 'deliver'">{{item.state_text}}
</view>
<view class="status" style="color:#ee4c47;" v-else>{{item.state.text}}</view>
</view>
<view class="goods-info" @click="goDetail(item.goods_sku.goods_id)" v-if="item.goods_sku">
<image class="goods-img" :src="item.goods_sku.cover" mode="aspectFill" />
<view class="goods">
<view class="name nowrap">{{item.goods_sku.goods_name}}</view>
<view class="sku">数权个数 <span>x {{item.qty}}</span> </view>
</view>
</view>
</view>
<view class="actions">
<view v-if="item.can">
<view v-if="item.can.audit" @click="$Router.push({name: 'storeExamine', params: {id: item.refund_id}})"
class="nowPay actions-color">订单审核</view>
<view v-if="item.can.sign" @click="goSigns(item.refund_id, index)" class="nowPay actions-color">
订单签收</view>
<view v-if="item.can.reToken" @click="goReTokens(item.refund_id, index)"
class="nowPay actions-color">确认退货</view>
<view v-if="item.can.logistic"
@click="$Router.push({name: 'Logistic', params: {id: item.shipment_no}})"
class="nowPay actions-color">查看物流</view>
<view v-if="item.can.deliver"
@click="$Router.push({name: 'DeliverForm', params: {id: item.shipment_no}})"
class="nowPay actions-color">我要发货</view>
</view>
<view v-if="listType == 'deliver'" class="nowPay"
@click="$Router.push({name: 'storeOrderDetails', params: {id: item.shipment_no, type: listType}})">
查看详情</view>
<view v-else class="nowPay"
@click="$Router.push({name: 'storeOrderDetails', params: {id: item.refund_id, type: 'return'}})">
查看详情</view>
</view>
</view>
</block>
<view v-else class="pack-center">
<image src="/static/icons/order-null.png"></image>
<view>{{toast}}</view>
</view>
</view>
</template>
<script>
export default {
name: "goodsList",
props: {
// 数据列表
list: {
type: Array,
default: () => {
return new Array
}
},
listType: '',
// 列表空提示
toast: {
type: String,
default: '暂无订单数据 -_-!'
},
},
created() {},
methods: {
goSigns(id,index) {
this.$emit('goSign',{id:id,index:index});
},
goReTokens(id,index){
this.$emit('goReToken',{id:id,index:index});
},
goDetail(id){
this.$emit('navDetail', {id: id})
}
}
}
</script>
<style lang="scss" scoped>
// 列表
.returnList {
background-color: #FFFFFF;
padding: $padding;
box-sizing: border-box;
margin-top: $margin;
}
.MallRefundsTemplate {
position: relative;
z-index: 0;
}
// 顶部信息
.top {
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
box-sizing: border-box;
padding-bottom: 20rpx;
border-bottom: solid 1rpx #f7f7f7;
position: relative;
z-index: 0;
.company-logo {
display: flex;
width: 90%;
image {
width: 40rpx;
height: 40rpx;
border-radius: 50%;
margin-right: 20rpx;
}
.company-name {
font-size: 30rpx;
color: #484848;
font-weight: bold;
width: calc(100% - 40rpx);
padding: 0 20rpx;
box-sizing: border-box;
}
}
.no {
margin-top: 10rpx;
font-size: $title-size*0.8;
color: #999;
}
.status {
color: #999;
font-size: $title-size*.9;
position: absolute;
top: 0;
right: 0;
}
}
// 商品信息
.goods-info {
display: flex;
flex-direction: row;
align-items: flex-start;
justify-content: flex-start;
box-sizing: border-box;
margin-top: 36rpx;
.goods-img {
width: 120rpx;
height: 120rpx;
border-radius: 10rpx;
}
.goods {
flex: 1;
width: calc(100% - 120rpx);
padding: 0 20rpx;
box-sizing: border-box;
margin-bottom: 10rpx;
.name {
width: 100%;
font-size: 30rpx;
span {
font-size: 32rpx;
font-weight: normal;
}
}
.sku {
flex: 1;
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
box-sizing: border-box;
margin-top: 10rpx;
font-size: 28rpx;
color: #999;
}
}
}
.flexrow {
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
box-sizing: border-box;
width: 100%;
.copy {
color: $mian-color;
font-size: $title-size*0.8;
font-weight: 400;
padding: 0 30rpx;
}
}
// 操作按钮
.actions {
display: flex;
flex-direction: row;
align-items: center;
justify-content: flex-end;
box-sizing: border-box;
flex-wrap: wrap;
flex: 1;
font-size: 28rpx;
color: #fff;
border-top: solid 1rpx #EFF4F2;
margin-top: $margin;
.nowPay {
padding: 4rpx 20rpx;
border-radius: 40rpx;
margin-left: 20rpx;
margin-top: 20rpx;
color: #999;
border: solid 1rpx #cacaca;
&.actions-color {
color: #e1293f;
border-color: #ec96a0;
}
}
.cancelOrder {
padding: 10rpx 30rpx;
border-radius: 40rpx;
margin-left: 20rpx;
margin-top: 20rpx;
background-color: #DD524D;
}
.logistics {
background-color: $mian-color;
padding: 10rpx 30rpx;
border-radius: 40rpx;
margin-left: 20rpx;
margin-top: 20rpx;
}
.sign {
background-color: #DD524D;
padding: 10rpx 30rpx;
border-radius: 40rpx;
margin-left: 20rpx;
margin-top: 20rpx;
}
.evaluate {
background-color: $mian-color;
padding: 10rpx 30rpx;
border-radius: 40rpx;
margin-left: 20rpx;
margin-top: 20rpx;
}
}
// 暂无订单
.pack-center {
text-align: center;
font-size: $title-size-sm;
color: $text-gray;
padding-top: 50%;
image {
width: $uni-img-size-lg * 2;
height: $uni-img-size-lg * 2;
border-radius: $uni-border-radius-circle;
margin-bottom: $margin;
}
}
</style>

BIN
components/v-tabs/.DS_Store vendored Normal file

Binary file not shown.

182
components/v-tabs/readme.md Normal file
View File

@@ -0,0 +1,182 @@
## 插件说明
> 这是 `v-tabs` 插件的升级版本,参数上有很大变动,支持 `H5` `小程序` `手机端`,如果是在之前的插件上升级的话,请注意参数的变更,触发的事件没有变更。
## 使用说明
### 1、最基本用法
- 视图文件
```html
<v-tabs v-model="current" :tabs="tabs" @change="changeTab"></v-tabs>
```
- 脚本文件
```js
export default {
data() {
return {
current: 0,
tabs: ['军事', '国内', '新闻新闻', '军事', '国内', '新闻', '军事', '国内', '新闻']
}
},
methods: {
changeTab(index) {
console.log('当前选中的项:' + index)
}
}
}
```
### 2、平铺整个屏幕
- 视图文件
```html
<v-tabs v-model="activeTab" :scroll="false" :tabs="['全部', '进行中', '已完成']"></v-tabs>
```
- 脚本文件
```js
export default {
data() {
return {
activeTab: 0
}
}
}
```
### 3、胶囊用法
- 视图文件
```html
<v-tabs v-model="current" :tabs="tabs" :pills="true" line-height="0" activeColor="#fff" @change="changeTab"></v-tabs>
```
- 脚本文件
```js
data() {
return {
current: 2,
tabs: [
'军事',
'国内',
'新闻新闻',
'军事',
'国内',
'新闻',
'军事',
'国内',
'新闻',
],
},
methods: {
changeTab(index) {
console.log('当前选中索引:' + index)
}
}
}
```
## 文档说明
### 1、属性说明
| 参数 | 类型 | 默认值 | 说明 |
| :---------------: | :-----: | :-------: | :----------------------------------------: |
| value | Number | 0 | 必传(双向绑定的值) |
| color | String | '#333' | 默认文字颜色 |
| activeColor | String | '#2979ff' | 选中文字的颜色 |
| fontSize | String | '28rpx' | 默认文字大小(rpx 或 px) |
| bold | Boolean | true | 是否加粗选中项 |
| scroll | Boolean | true | 是否显示滚动条,平铺设置 false |
| height | String | '70rpx' | tab 高度(rpx 或 px) |
| lineHeight | String | '10rpx' | 滑块高度(rpx 或 px) |
| lineColor | String | '#2979ff' | 滑块的颜色 |
| lineScale | Number | 0.5 | 滑块宽度缩放值 |
| lineRadius | String | '10rpx' | 滑块圆角宽度(rpx 或 px) |
| pills | Boolean | false | 是否开启胶囊 |
| pillsColor | String | '#2979ff' | 胶囊背景颜色(rpx 或 px) |
| pillsBorderRadius | String | '10rpx' | 胶囊圆角宽度(rpx 或 px) |
| field | String | '' | 如果 tabs 子项是对象,输入需要展示的键名 |
| bgColor | String | '#fff' | 背景色,支持 linear-gradient 渐变 |
| padding | String | '0' | 整个 tab padding 属性 |
| fixed | Boolean | false | 是否固定在顶部 |
| paddingItem | String | '0 22rpx' | 选项的边距(设置上下不生效,需要设置高度) |
### 2、事件说明
| 名称 | 参数 | 说明 |
| :----: | :---: | :--------------------------------: |
| change | index | 改变选中项触发, index 选中项的下标 |
## 更新日志
### 2020-09-24
1. 修复 `v-tabs` 第一次可能出现第一个标签显示不完整的情况
2. 修改了 `pages/tabs/order` 示例文件
### 2020-09-21
1. 修复添加 `fixed` 属性后,滚动条无效
2. 修复选项很少的情况下,下划线计算计算错误
3. 新增 `paddingItem` 属性,设置选项左右边距(上下边距需要设置 `height` 属性,或者设置 `padding` 属性)
**写在最后:**
欢迎各位老铁反馈 bug ,本人后端 PHP 一枚,只是应为感兴趣前端,自己琢磨,自己搞。如果你在使用的过程中有什么不合理,需要优化的,都可以在下面评论(或加我 QQ: 1207791534本人看见后回复、修正感谢。
### 2020-09-17
1. 紧急修复 bug横向滑动不了的情况
### 2020-09-16
1. 新增 `fixed` 属性,是否固定在顶部,示例地址:`pages/tabs/tabs-static`
2. 优化之前的页面结构
**注意:**
1. 使用 `padding` 属性的时候,尽量不要左右边距,会导致下划线位置不对
2. 如果不绑定 `v-model` 会导致 `change` 事件改变的时候,下划线不跟随问题
### 2020-09-09
1. 修复 `width` 错误dom 加载的时候没有及时获取到 `data` 属性导致的。
### 2020-08-29
1. 优化异步改变 `tabs` 后,下划线不初始化问题
2. `github` 地址上有图 2 的源码,需要的自行下载,页面路径:`pages/tabs/order`
### 2020-08-20
1. 优化 `节点查询``选中渲染`
2. 优化支付宝中 `createSelectorQuery()` 的影响
### 2020-08-19
1. 优化 `change` 事件触发机制
### 2020-08-16
1. 修改默认高度为 `70rpx`
2. 新增属性 `bgColor`,可设置背景颜色,默认 `#fff`
3. 新增整个 `tab``padding` 属性,默认 `0`
### 2020-08-13
1. 全新的 `v-tabs 2.0`
2. 支持 `H5` `小程序` `APP`
3. 属性高度可配置
## 预览
![v-tabs 2.0.1.gif](https://tva1.sinaimg.cn/large/007S8ZIlgy1ghsv40mj76g30ai0i2tsd.gif)
![v-tabs 2.0.2.gif](https://img-cdn-aliyun.dcloud.net.cn/stream/plugin_screens/42f3a920-a674-11ea-8a24-ffee00625e2e_1.png?v=1597912963)

View File

@@ -0,0 +1,339 @@
<template>
<view :id="elId" class="v-tabs">
<scroll-view
id="scrollContainer"
:scroll-x="scroll"
:scroll-left="scroll ? scrollLeft : 0"
:scroll-with-animation="scroll"
:style="{ position: fixed ? 'fixed' : 'relative', zIndex: 1993 }"
>
<view
class="v-tabs__container"
:style="{
display: scroll ? 'inline-flex' : 'flex',
whiteSpace: scroll ? 'nowrap' : 'normal',
background: bgColor,
height,
padding
}"
>
<view
class="v-tabs__container-item"
v-for="(v, i) in tabs"
:key="i"
:style="{
color: current == i ? activeColor : color,
fontSize: current == i ? fontSize : fontSize,
fontWeight: bold && current == i ? 'bold' : '',
justifyContent: !scroll ? 'center' : '',
flex: scroll ? '' : 1,
padding: paddingItem
}"
@click="change(i)"
>
{{ field ? v[field] : v }}
</view>
<view
v-if="!pills"
class="v-tabs__container-line"
:style="{
background: lineColor,
width: lineWidth + 'px',
height: lineHeight,
borderRadius: lineRadius,
left: lineLeft + 'px',
transform: `translateX(-${lineWidth / 2}px)`
}"
></view>
<view
v-else
class="v-tabs__container-pills"
:style="{
background: pillsColor,
borderRadius: pillsBorderRadius,
left: pillsLeft + 'px',
width: currentWidth + 'px',
height
}"
></view>
</view>
</scroll-view>
<view
class="v-tabs__placeholder"
:style="{
height: fixed ? height : '0',
padding
}"
></view>
</view>
</template>
<script>
/**
* v-tabs
* @property {Number} value 选中的下标
* @property {Array} tabs tabs 列表
* @property {String} bgColor = '#fff' 背景颜色
* @property {String} color = '#333' 默认颜色
* @property {String} activeColor = '#2979ff' 选中文字颜色
* @property {String} fontSize = '28rpx' 默认文字大小
* @property {String} activeFontSize = '28rpx' 选中文字大小
* @property {Boolean} bold = [true | false] 选中文字是否加粗
* @property {Boolean} scroll = [true | false] 是否滚动
* @property {String} height = '60rpx' tab 的高度
* @property {String} lineHeight = '10rpx' 下划线的高度
* @property {String} lineColor = '#2979ff' 下划线的颜色
* @property {Number} lineScale = 0.5 下划线的宽度缩放比例
* @property {String} lineRadius = '10rpx' 下划线圆角
* @property {Boolean} pills = [true | false] 是否胶囊样式
* @property {String} pillsColor = '#2979ff' 胶囊背景色
* @property {String} pillsBorderRadius = '10rpx' 胶囊圆角大小
* @property {String} field 如果是对象,显示的键名
* @property {Boolean} fixed = [true | false] 是否固定
* @property {String} paddingItem = '0 22rpx' 选项的边距
*
* @event {Function(current)} change 改变标签触发
*/
export default {
props: {
value: {
type: Number,
default: 0
},
tabs: {
type: Array,
default() {
return []
}
},
bgColor: {
type: String,
default: '#fff'
},
padding: {
type: String,
default: '0'
},
color: {
type: String,
default: '#333'
},
activeColor: {
type: String,
default: '#2979ff'
},
fontSize: {
type: String,
default: '28rpx'
},
activeFontSize: {
type: String,
default: '32rpx'
},
bold: {
type: Boolean,
default: true
},
scroll: {
type: Boolean,
default: true
},
height: {
type: String,
default: '70rpx'
},
lineColor: {
type: String,
default: '#2979ff'
},
lineHeight: {
type: String,
default: '10rpx'
},
lineScale: {
type: Number,
default: 0.5
},
lineRadius: {
type: String,
default: '10rpx'
},
pills: {
type: Boolean,
deafult: false
},
pillsColor: {
type: String,
default: '#2979ff'
},
pillsBorderRadius: {
type: String,
default: '10rpx'
},
field: {
type: String,
default: ''
},
fixed: {
type: Boolean,
default: false
},
paddingItem: {
type: String,
default: '0 22rpx'
}
},
data() {
return {
elId: '',
lineWidth: 30,
currentWidth: 0, // 当前选项的宽度
lineLeft: 0, // 滑块距离左侧的位置
pillsLeft: 0, // 胶囊距离左侧的位置
scrollLeft: 0, // 距离左边的位置
containerWidth: 0, // 容器的宽度
current: 0 // 当前选中项
}
},
watch: {
value(newVal) {
this.current = newVal
this.$nextTick(() => {
this.getTabItemWidth()
})
},
current(newVal) {
this.$emit('input', newVal)
},
tabs(newVal) {
this.$nextTick(() => {
this.getTabItemWidth()
})
}
},
methods: {
// 产生随机字符串
randomString(len) {
len = len || 32
let $chars =
'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678' /****默认去掉了容易混淆的字符oOLl,9gq,Vv,Uu,I1****/
let maxPos = $chars.length
let pwd = ''
for (let i = 0; i < len; i++) {
pwd += $chars.charAt(Math.floor(Math.random() * maxPos))
}
return pwd
},
// 切换事件
change(index) {
if (this.current !== index) {
this.current = index
this.$emit('change', index)
}
},
// 获取左移动位置
getTabItemWidth() {
let query = uni
.createSelectorQuery()
// #ifndef MP-ALIPAY
.in(this)
// #endif
// 获取容器的宽度
query
.select(`#scrollContainer`)
.boundingClientRect((data) => {
if (!this.containerWidth && data) {
this.containerWidth = data.width
}
})
.exec()
// 获取所有的 tab-item 的宽度
query
.selectAll('.v-tabs__container-item')
.boundingClientRect((data) => {
if (!data) {
return
}
let lineLeft = 0
let currentWidth = 0
if (data) {
for (let i = 0; i < data.length; i++) {
if (i < this.current) {
lineLeft += data[i].width
} else if (i == this.current) {
currentWidth = data[i].width
} else {
break
}
}
}
// 当前滑块的宽度
this.currentWidth = currentWidth
// 缩放后的滑块宽度
this.lineWidth = currentWidth * this.lineScale * 1
// 滑块作移动的位置
this.lineLeft = lineLeft + currentWidth / 2
// 胶囊距离左侧的位置
this.pillsLeft = lineLeft
// 计算滚动的距离左侧的位置
if (this.scroll) {
this.scrollLeft = this.lineLeft - this.containerWidth / 2
}
})
.exec()
}
},
mounted() {
this.elId = 'xfjpeter_' + this.randomString()
this.current = this.value
this.$nextTick(() => {
this.getTabItemWidth()
})
}
}
</script>
<style lang="scss" scoped>
.v-tabs {
width: 100%;
box-sizing: border-box;
overflow: hidden;
::-webkit-scrollbar {
display: none;
}
&__container {
min-width: 100%;
position: relative;
display: inline-flex;
align-items: center;
white-space: nowrap;
overflow: hidden;
&-item {
display: flex;
align-items: center;
height: 100%;
position: relative;
z-index: 10;
// padding: 0 11px;
transition: all 0.3s;
white-space: nowrap;
}
&-line {
position: absolute;
bottom: 0;
transition: all 0.3s linear;
}
&-pills {
position: absolute;
transition: all 0.3s linear;
z-index: 9;
}
}
}
</style>

View File

@@ -0,0 +1,355 @@
<template>
<view class="wrapper" v-show="isShowMask">
<transition name="content">
<view class="content_view" v-show="isShow">
<view class="title_view">
<view class="title">请选择所在地区</view>
<view class="close_view" @click="hidden">
<icon class="close_icon" :type="'clear'" size="26" />
</view>
</view>
<view class="select_top">
<view class="select_top_item" ref="select_top_item" v-for="(item,index) in dataList" :key="index"
@click="select_top_item_click(index)">
<text class="address_value">{{item.name || '请选择'}}</text>
<view :class="index === currentIndex?'indicator':'no-indicator'" ref="indicator"></view>
</view>
</view>
<swiper class="swiper" :current="currentIndex" @change="swiperChange">
<swiper-item v-for="(swiper_item,swiper_index) in dataList" :key="swiper_index">
<view class="swiper-item">
<scroll-view class="scroll-view-item" scroll-y="true">
<view class="address_item" v-for="(item,index) in cityAreaArray[swiper_index]" :key="index"
@click="address_item_click(swiper_index,index)">
{{item.name}}
<uni-icons class="address_item_icon" v-if="selectIndexArr[swiper_index] === index"
type="checkmarkempty" color="#009b69"></uni-icons>
</view>
</scroll-view>
</view>
</swiper-item>
</swiper>
</view>
</transition>
<view class="mask" @click="hidden" v-show="isShowMask"></view>
</view>
</template>
<script>
import cityData from '../../static/yixuan-selectAddress/city.json'
export default {
data() {
return {
isShow: false,
isShowMask: false,
dataList: ['请选择'],
currentIndex: 0,
cityData: {}, // 省市区对象
cityAreaArray: [], // 省市区数组
selectIndexArr: [], // 省市区index
indicatorStyleLeft: 16
};
},
props: {
addressIdList: {
type: Array
}
},
methods: {
show() {
this.isShow = true
this.isShowMask = true
},
hidden() {
this.isShow = false
setTimeout(() => {
this.isShowMask = false
}, 500);
},
select_top_item_click(index) {
console.log('select_top_item_click')
this.currentIndex = index
this.$nextTick(() => {
this.changeIndicator(index)
})
},
swiperChange(event) {
let index = event.detail.current
this.currentIndex = index
this.changeIndicator(index)
},
changeIndicator(index) {
let indicatorWidth = 30
const query = uni.createSelectorQuery().in(this);
let arr = query.selectAll('.select_top_item .address_value')
arr.fields({
size: true,
scrollOffset: false
}, data => {
let itemWidth = data[index]["width"] > 80 ? 70 : data[index]["width"]
let itemCenterX = 10 + index * 80 + itemWidth / 2
let left = itemCenterX - indicatorWidth / 2
// console.log('changeIndicator',itemWidth,index)
this.indicatorStyleLeft = left
}).exec();
},
address_item_click(swiper_index, index) {
this.selectIndexArr.splice(swiper_index, 5, index)
//判断当前是否为最下一级
if (swiper_index === 0) { //第一级
let currentObj = this.cityData[index]
let city = {
name: currentObj.name,
id: currentObj.region_id
}
console.log(city)
this.dataList.splice(swiper_index, 5, city)
this.dataList.splice(swiper_index + 1, 0, '请选择')
this.cityAreaArray.splice(swiper_index + 1, 1, currentObj["city"])
console.log(this.cityAreaArray)
setTimeout(() => {
this.currentIndex = 1
this.changeIndicator(1)
}, 50);
} else {
let currentAreaArray = this.cityAreaArray[swiper_index]
let currentObj = currentAreaArray[index]
let area = currentObj["area"]
console.log(currentAreaArray)
if (area !== undefined) {
let city = {
name: currentObj.name,
id: currentObj.region_id
}
this.dataList.splice(swiper_index, 5, city)
this.dataList.splice(swiper_index + 1, 0, '请选择')
this.cityAreaArray.splice(swiper_index + 1, 1, currentObj["area"])
setTimeout(() => {
this.currentIndex = swiper_index + 1
this.changeIndicator(swiper_index + 1)
}, 50);
} else { //是最下一级
let city = {
name: currentObj.name,
id: currentObj.region_id
}
this.dataList.splice(swiper_index, 1, city)
//选择成功返回数据
this.$emit("selectAddress", this.dataList)
this.$nextTick(() => {
this.changeIndicator(swiper_index)
})
setTimeout(() => {
this.isShow = false
}, 100);
setTimeout(() => {
this.isShowMask = false
}, 500);
}
}
}
},
created() {
this.cityData = cityData
this.cityAreaArray.push(cityData)
if (this.addressIdList.length > 0) {
const privinceId = this.addressIdList[0] // 省份id请求接口返回
const cityId = this.addressIdList[1] // 城市id请求接口返回
const areaId = this.addressIdList[2] // 区域id请求接口返回
const privince = cityData // 省份数组
let city = [] // 城市数组
let area = [] // 区域数组
let cityAreaArray = []
let selectIndexArr = []
let dataList = []
let pIndex = privince.findIndex((item) => item.region_id === privinceId) // 省份的id
cityAreaArray.push(privince)
selectIndexArr.push(pIndex)
dataList.push(privince[pIndex])
city = privince[pIndex].city
let cIndex = city.findIndex((item) => item.region_id === cityId) // 城市的id
cityAreaArray.push(city)
selectIndexArr.push(cIndex)
dataList.push(city[cIndex])
area = city[cIndex].area
let aIndex = area.findIndex((item) => item.region_id === areaId) // 城市的id
cityAreaArray.push(area)
selectIndexArr.push(aIndex)
dataList.push(area[aIndex])
this.cityAreaArray = cityAreaArray
this.selectIndexArr = selectIndexArr
this.dataList = dataList
this.$emit("selectAddress", this.dataList)
}
}
}
</script>
<style lang="scss">
// 不换行
@mixin no-wrap() {
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
.wrapper {
z-index: 1999;
position: absolute;
top: -44px;
left: 0;
bottom: 0;
right: 0;
.content_view {
z-index: 999;
background: white;
position: absolute;
height: 60%;
left: 0;
bottom: 0;
right: 0;
border-top-left-radius: 20px;
border-top-right-radius: 20px;
.title_view {
height: 120rpx;
display: flex;
justify-content: center;
align-items: center;
padding: 0 $uni-spacing-row-sm;
position: relative;
border-bottom: solid 1rpx #f8f8f8;
.title {
font-size: uni-font-size-sm;
}
.close_view {
height: 60px;
width: 60px;
display: flex;
justify-content: center;
align-items: center;
position: absolute;
right: 0;
}
}
.select_top {
height: 8%;
display: flex;
justify-content: flex-start;
align-items: center;
padding: 0 20rpx 0 20rpx;
position: relative;
margin: 30rpx 0 50rpx 0;
box-sizing: border-box;
.select_top_item {
max-width: 33.33%;
float: left;
font-size: $title-size - 1;
color: $text-price;
text-align: left;
@include no-wrap();
margin-right: $margin*1;
// display: flex;
// flex-direction: column;
// justify-content: center;
// align-items: center;
// box-sizing: border-box;
}
.indicator {
width: 30px;
height: 2px;
margin-top: 20rpx;
background: $text-price;
transition: left 0.5s ease;
}
.no-indicator {
background: #fff;
width: 30px;
height: 2px;
margin-top: 20rpx;
transition: left 0.5s ease;
}
}
.swiper {
height: 70%;
position: relative;
left: 0;
top: 0;
bottom: 0;
right: 0;
.swiper-item {
height: 100%;
.scroll-view-item {
height: 100%;
padding: 0 10px;
.address_item {
padding: $padding*1.5 0;
border-bottom: solid 0.2rpx #f7f7f7;
font-size: $title-size - 1;
display: flex;
align-items: center;
.address_item_icon {
margin-left: 20rpx;
// width: 20px;
// height: 20px;
// margin-right: 10px;
}
}
}
}
}
}
.mask {
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
background: $uni-text-color-grey;
opacity: 0.7;
}
}
.content-enter {
transform: translateY(100%);
}
.content-enter-to {
transform: translateY(0%);
}
.content-enter-active {
transition: transform 0.5s;
}
.content-leave {
transform: translateY(0%);
}
.content-leave-to {
transform: translateY(100%);
}
.content-leave-active {
transition: transform 0.5s;
}
</style>

View File

@@ -1,14 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0" />
<title></title>
<!--preload-links-->
<!--app-context-->
</head>
<body>
<div id="app"><!--app-html--></div>
<script type="module" src="/main.js"></script>
</body>
</html>

View File

@@ -1,23 +1,10 @@
{
"name" : "BlockChainH5",
"name" : "链商星球",
"appid" : "__UNI__1F65101",
"description" : "",
"versionName" : "1.0.0",
"versionCode" : "100",
"description" : "安徽星煌,链商星球商家工具",
"versionName" : "1.2.1",
"versionCode" : 121,
"transformPx" : false,
"h5" : {
"title" : "链商星球",
"router" : {
"mode" : "history"
},
"sdkConfigs" : {
"maps" : {
"qqmap" : {
"key" : "RY5BZ-7XNKS-IBMO6-637EZ-SMFQE-43FGN"
}
}
}
},
/* 5+App */
"app-plus" : {
"usingComponents" : true,
@@ -29,34 +16,140 @@
"autoclose" : true,
"delay" : 0
},
"safearea" : {
"bottom" : {
"offset" : "none"
}
},
/* */
"modules" : {},
"modules" : {
"OAuth" : {},
"LivePusher" : {},
"VideoPlayer" : {},
"Push" : {},
"Share" : {},
"Payment" : {},
"Geolocation" : {},
"Maps" : {}
},
/* */
"distribute" : {
/* android */
"android" : {
"permissions" : [
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
"<uses-permission android:name=\"android.permission.VIBRATE\"/>",
"<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
"<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.CAMERA\"/>",
"<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
"<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
"<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
"<uses-feature android:name=\"android.hardware.camera\"/>",
"<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_COARSE_LOCATION\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
"<uses-permission android:name=\"android.permission.CAMERA\"/>",
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
"<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
"<uses-permission android:name=\"android.permission.INTERNET\"/>",
"<uses-permission android:name=\"android.permission.MODIFY_AUDIO_SETTINGS\"/>",
"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
"<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
"<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
"<uses-permission android:name=\"android.permission.RECORD_AUDIO\"/>",
"<uses-permission android:name=\"android.permission.VIBRATE\"/>",
"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
"<uses-permission android:name=\"android.permission.WRITE_EXTERNAL_STORAGE\"/>",
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
]
},
/* ios */
"ios" : {},
"ios" : {
"privacyDescription" : {
"NSPhotoLibraryUsageDescription" : "上传图片",
"NSPhotoLibraryAddUsageDescription" : "下载图片",
"NSCameraUsageDescription" : "扫描二维码",
"NSLocationAlwaysAndWhenInUseUsageDescription" : "定位您的店铺地址",
"NSRemindersUsageDescription" : "及时通知提醒内容",
"NSLocalNetworkUsageDescription" : "使用您的网络获取服务数据"
}
},
/* SDK */
"sdkConfigs" : {}
"sdkConfigs" : {
"ad" : {},
"payment" : {
"weixin" : {
"__platform__" : [ "ios", "android" ],
"appid" : "wxd8b146e0a37bab50",
"UniversalLinks" : "https://lianshang/app/"
},
"alipay" : {
"__platform__" : [ "ios", "android" ]
}
},
"oauth" : {
"univerify" : {},
"weixin" : {
"appid" : "wxd8b146e0a37bab50",
"appsecret" : "6896afa5d57be13aecaf179c3547a940",
"UniversalLinks" : "https://lianshang/app/"
}
},
"push" : {
"unipush" : {}
},
"share" : {
"weixin" : {
"appid" : "wxd8b146e0a37bab50",
"UniversalLinks" : "https://lianshang/app/"
}
},
"maps" : {
"amap" : {
"appkey_ios" : "450192db4bea0af2f226b8c1e1f7b769",
"appkey_android" : "6ff79685204ba5f14ae2e898e0d3b8a0"
}
},
"geolocation" : {
"amap" : {
"__platform__" : [ "ios", "android" ],
"appkey_ios" : "450192db4bea0af2f226b8c1e1f7b769",
"appkey_android" : "6ff79685204ba5f14ae2e898e0d3b8a0"
}
}
},
"icons" : {
"android" : {
"hdpi" : "unpackage/res/icons/72x72.png",
"xhdpi" : "unpackage/res/icons/96x96.png",
"xxhdpi" : "unpackage/res/icons/144x144.png",
"xxxhdpi" : "unpackage/res/icons/192x192.png"
},
"ios" : {
"appstore" : "unpackage/res/icons/1024x1024.png",
"ipad" : {
"app" : "unpackage/res/icons/76x76.png",
"app@2x" : "unpackage/res/icons/152x152.png",
"notification" : "unpackage/res/icons/20x20.png",
"notification@2x" : "unpackage/res/icons/40x40.png",
"proapp@2x" : "unpackage/res/icons/167x167.png",
"settings" : "unpackage/res/icons/29x29.png",
"settings@2x" : "unpackage/res/icons/58x58.png",
"spotlight" : "unpackage/res/icons/40x40.png",
"spotlight@2x" : "unpackage/res/icons/80x80.png"
},
"iphone" : {
"app@2x" : "unpackage/res/icons/120x120.png",
"app@3x" : "unpackage/res/icons/180x180.png",
"notification@2x" : "unpackage/res/icons/40x40.png",
"notification@3x" : "unpackage/res/icons/60x60.png",
"settings@2x" : "unpackage/res/icons/58x58.png",
"settings@3x" : "unpackage/res/icons/87x87.png",
"spotlight@2x" : "unpackage/res/icons/80x80.png",
"spotlight@3x" : "unpackage/res/icons/120x120.png"
}
}
},
"splashscreen" : {
"androidStyle" : "common",
"iosStyle" : "common"
}
}
},
/* */
@@ -81,5 +174,12 @@
"uniStatistics" : {
"enable" : false
},
"vueVersion" : "2"
"vueVersion" : "2",
"h5" : {
"router" : {
"mode" : "history"
}
}
}
/* SDK */

View File

@@ -1,30 +0,0 @@
# jweixin-module
微信JS-SDK
## 安装
### NPM
```shell
npm install jweixin-module --save
```
### UMD
```http
https://unpkg.com/jweixin-module/out/index.js
```
## 使用
```js
var jweixin = require('jweixin-module')
jweixin.ready(function(){
// TODO
});
```
## 完整API
>[微信JS-SDK说明文档](https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115)

File diff suppressed because one or more lines are too long

View File

@@ -1,54 +0,0 @@
{
"_from": "jweixin-module",
"_id": "jweixin-module@1.6.0",
"_inBundle": false,
"_integrity": "sha512-dGk9cf+ipipHmtzYmKZs5B2toX+p4hLyllGLF6xuC8t+B05oYxd8fYoaRz0T30U2n3RUv8a4iwvjhA+OcYz52w==",
"_location": "/jweixin-module",
"_phantomChildren": {},
"_requested": {
"type": "tag",
"registry": true,
"raw": "jweixin-module",
"name": "jweixin-module",
"escapedName": "jweixin-module",
"rawSpec": "",
"saveSpec": null,
"fetchSpec": "latest"
},
"_requiredBy": [
"#USER",
"/"
],
"_resolved": "https://registry.npmjs.org/jweixin-module/-/jweixin-module-1.6.0.tgz",
"_shasum": "4a7ea614083e3c9c3f49e2fdc2bb882cfa58dfcd",
"_spec": "jweixin-module",
"_where": "/Users/WebTmm/Desktop/BlockChainH5",
"author": {
"name": "Shengqiang Guo"
},
"bugs": {
"url": "https://github.com/zhetengbiji/jweixin-module/issues"
},
"bundleDependencies": false,
"deprecated": false,
"description": "微信JS-SDK",
"devDependencies": {},
"homepage": "https://github.com/zhetengbiji/jweixin-module#readme",
"keywords": [
"wxjssdk",
"weixin",
"jweixin",
"wechat",
"jssdk",
"wx"
],
"license": "ISC",
"main": "lib/index.js",
"name": "jweixin-module",
"repository": {
"type": "git",
"url": "git+https://github.com/zhetengbiji/jweixin-module.git"
},
"scripts": {},
"version": "1.6.0"
}

108
node_modules/uni-read-pages/README.md generated vendored
View File

@@ -1,108 +0,0 @@
# uni-read-pages
![coverage](https://img.shields.io/badge/coverage%20-98%25-green) ![npm](https://img.shields.io/badge/npm%20-v2.6.11-blue) ![license](https://img.shields.io/badge/license-MIT-red) ![size](https://img.shields.io/badge/size-1.48%20kb-yellowgreen)
通过 [vue.config.js](https://cli.vuejs.org/zh/config/) 配合此库,可以随心所欲的读取 `pages.json` 下的所有配置
## 安装
您可以使用 `Yarn``npm` 安装该软件包(选择一个):
##### Yarn
```sh
yarn add uni-read-pages
```
##### npm
```sh
npm install uni-read-pages
```
## 开始
配置 `vue.config.js` 通过 `webpack` 注入全局变量 [查看文档](https://www.webpackjs.com/plugins/define-plugin/)
#### 配置 `vue.config.js`
```js
//vue.config.js
const TransformPages = require('uni-read-pages')
const tfPages = new TransformPages()
module.exports = {
configureWebpack: {
plugins: [
new tfPages.webpack.DefinePlugin({
ROUTES: JSON.stringify(tfPages.routes)
})
]
}
}
```
借助`webpack.DefinePlugin` 轻松注入全局变量。`ROUTES` 及可全局使用
#### 使用
```js
// xxx.vue
<script>
export default {
data() {
return {
title: 'Hello'
}
},
onLoad() {
console.log(ROUTES)
},
}
</script>
```
## API
#### options
```js
//默认值
const CONFIG={
cli:false, //当前是否为脚手架初始化的项目
includes:['path','aliasPath','name'] //需要获取包涵的字段
}
```
#### Instance method
* **getPagesRoutes**
* 通过读取 `pages.json` 文件 生成直接可用的routes
* **parsePages(pageCallback, subPageCallback)**
* 单条page对象解析
* **resolvePath(dir)**
* 解析绝对路径
#### Instance attr
* **CONFIG**
* 当前配置项
* **webpack**
* 当前工程下需要用到 `webpack`
* **uniPagesJSON**
* 当前 `uni-app` 内置对象,可以通过此属性调用一些内置方法
* **routes**
* 通过 **includes** 解析后得到的路由表 **可直接使用**
#### getter
* **pagesJson**
* 获取所有 `pages.json` 下的内容 返回 `json`
#### uniPagesJSON method
* getMainEntry()
* getNVueMainEntry()
* parsePages (pagesJson, pageCallback, subPageCallback)
* parseEntry (pagesJson)
* getPagesJson()
* parsePagesJson (content, loader)
#### uniPagesJSON attr
* pagesJsonJsFileName //默认值 pages.js

83
node_modules/uni-read-pages/index.js generated vendored
View File

@@ -1,83 +0,0 @@
const path = require('path')
const CONFIG = {
includes: ['path', 'aliasPath', 'name']
}
const rootPath = path.resolve(process.cwd(), 'node_modules');
/** 解析绝对路径
* @param {Object} dir
*/
function resolvePath(dir) {
return path.resolve(rootPath, dir);
}
class TransformPages {
constructor(config) {
config = {
...CONFIG,
...config
};
this.CONFIG = config;
this.webpack = require(resolvePath('webpack'));
this.uniPagesJSON = require(resolvePath('@dcloudio/uni-cli-shared/lib/pages.js'));
this.routes = this.getPagesRoutes().concat(this.getNotMpRoutes());
}
/**
* 获取所有pages.json下的内容 返回json
*/
get pagesJson() {
return this.uniPagesJSON.getPagesJson();
}
/**
* 通过读取pages.json文件 生成直接可用的routes
*/
getPagesRoutes(pages = this.pagesJson.pages, rootPath = null) {
const routes = [];
for (let i = 0; i < pages.length; i++) {
const item = pages[i];
const route = {};
for (let j = 0; j < this.CONFIG.includes.length; j++) {
const key = this.CONFIG.includes[j];
let value = item[key];
if (key === 'path') {
value = rootPath ? `/${rootPath}/${value}` : `/${value}`
}
if (key === 'aliasPath' && i == 0 && rootPath == null) {
route[key] = route[key] || '/'
} else if (value !== undefined) {
route[key] = value;
}
}
routes.push(route);
}
return routes;
}
/**
* 解析小程序分包路径
*/
getNotMpRoutes() {
const {
subPackages
} = this.pagesJson;
let routes = [];
if (subPackages == null || subPackages.length == 0) {
return [];
}
for (let i = 0; i < subPackages.length; i++) {
const subPages = subPackages[i].pages;
const root = subPackages[i].root;
const subRoutes = this.getPagesRoutes(subPages, root);
routes = routes.concat(subRoutes)
}
return routes
}
/**
* 单条page对象解析
* @param {Object} pageCallback
* @param {Object} subPageCallback
*/
parsePages(pageCallback, subPageCallback) {
this.uniPagesJSON.parsePages(this.pagesJson, pageCallback, subPageCallback)
}
}
module.exports = TransformPages

View File

@@ -1,51 +0,0 @@
{
"_from": "uni-read-pages",
"_id": "uni-read-pages@1.0.5",
"_inBundle": false,
"_integrity": "sha512-GkrrZ0LX0vn9R5k6RKEi0Ez3Q3e2vUpjXQ8Z6/K/d28KudI9ajqgt8WEjQFlG5EPm1K6uTArN8LlqmZTEixDUA==",
"_location": "/uni-read-pages",
"_phantomChildren": {},
"_requested": {
"type": "tag",
"registry": true,
"raw": "uni-read-pages",
"name": "uni-read-pages",
"escapedName": "uni-read-pages",
"rawSpec": "",
"saveSpec": null,
"fetchSpec": "latest"
},
"_requiredBy": [
"#USER",
"/"
],
"_resolved": "https://registry.npmjs.org/uni-read-pages/-/uni-read-pages-1.0.5.tgz",
"_shasum": "452c8dcaa8977bbaef600909be926c8d9704387c",
"_spec": "uni-read-pages",
"_where": "/Users/WebTmm/Desktop/BlockChainH5",
"author": "",
"bugs": {
"url": "https://github.com/SilurianYang/uni-read-pages/issues"
},
"bundleDependencies": false,
"deprecated": false,
"description": "read `pages.json` file to generate the routes table",
"directories": {
"example": "examples"
},
"homepage": "https://github.com/SilurianYang/uni-read-pages#readme",
"keywords": [],
"license": "ISC",
"main": "index.js",
"name": "uni-read-pages",
"repository": {
"type": "git",
"url": "git+https://github.com/SilurianYang/uni-read-pages.git"
},
"scripts": {
"build": "webpack --progress --config webpack/webpack.prod.js",
"dev": "webpack --watch --progress --config webpack/webpack.dev.js",
"postinstall": "node -e \"console.log('\\x1b[91m','\\n\\n uni-simple-router 垫脚片,欢迎下载!\\n \\n 开源不易,需要鼓励。去给 uni-read-pages 项目 点个 star 吧 \\n\\n')\""
},
"version": "1.0.5"
}

View File

@@ -1,6 +0,0 @@
dist
/node_modules
/webpack
/src/global.d.ts
/test
/jest.config.js

View File

@@ -1,257 +0,0 @@
module.exports = {
root: true,
env: {
browser: true,
node: true,
es6: true
},
globals: {
uni: true,
plus: true,
getCurrentPages: true,
getApp: true,
__uniConfig: true,
__uniRoutes: true,
$npm_package_name: true
},
parser: '@typescript-eslint/parser',
extends: ['eslint:recommended'],
plugins: ['@typescript-eslint'],
rules: {
'@typescript-eslint/consistent-type-definitions': [
'error',
'interface'
],
'accessor-pairs': 2,
'arrow-spacing': [
2,
{
before: true,
after: true
}
],
'block-spacing': [2, 'always'],
'brace-style': [
2,
'1tbs',
{
allowSingleLine: true
}
],
camelcase: [
0,
{
properties: 'always'
}
],
'comma-dangle': [2, 'never'],
'comma-spacing': [
2,
{
before: false,
after: true
}
],
'comma-style': [2, 'last'],
'constructor-super': 2,
curly: [2, 'multi-line'],
'dot-location': [2, 'property'],
'eol-last': 2,
eqeqeq: ['error', 'always', {null: 'ignore'}],
'generator-star-spacing': [
2,
{
before: true,
after: true
}
],
'handle-callback-err': [2, '^(err|error)$'],
indent: ['error', 4],
'jsx-quotes': [2, 'prefer-single'],
'key-spacing': [
2,
{
beforeColon: false,
afterColon: true
}
],
'keyword-spacing': [
2,
{
before: true,
after: true
}
],
'new-cap': [
2,
{
newIsCap: true,
capIsNew: false
}
],
'new-parens': 2,
'no-array-constructor': 2,
'no-caller': 2,
'no-console': 'off',
'no-class-assign': 2,
'no-cond-assign': 2,
'no-const-assign': 2,
'no-control-regex': 0,
'no-delete-var': 2,
'no-dupe-args': 2,
'no-dupe-class-members': 2,
'no-dupe-keys': 2,
'no-duplicate-case': 2,
'no-empty-character-class': 2,
'no-empty-pattern': 2,
'no-eval': 2,
'no-ex-assign': 2,
'no-extend-native': 2,
'no-extra-bind': 2,
'no-extra-boolean-cast': 2,
'no-extra-parens': [2, 'functions'],
'no-fallthrough': 2,
'no-floating-decimal': 2,
'no-func-assign': 2,
'no-implied-eval': 2,
'no-inner-declarations': [2, 'functions'],
'no-invalid-regexp': 2,
'no-irregular-whitespace': 2,
'no-iterator': 2,
'no-label-var': 2,
'no-labels': [
2,
{
allowLoop: false,
allowSwitch: false
}
],
'no-lone-blocks': 2,
'no-mixed-spaces-and-tabs': 2,
'no-multi-spaces': 2,
'no-multi-str': 2,
'no-multiple-empty-lines': [
2,
{
max: 1
}
],
'no-native-reassign': 2,
'no-negated-in-lhs': 2,
'no-new-object': 2,
'no-new-require': 2,
'no-new-symbol': 2,
'no-new-wrappers': 2,
'no-obj-calls': 2,
'no-octal': 2,
'no-octal-escape': 2,
'no-path-concat': 2,
'no-proto': 2,
'no-redeclare': 2,
'no-regex-spaces': 2,
'no-return-assign': [2, 'except-parens'],
'no-self-assign': 2,
'no-self-compare': 2,
'no-sequences': 2,
'no-shadow-restricted-names': 2,
'no-spaced-func': 2,
'no-sparse-arrays': 2,
'no-this-before-super': 2,
'no-throw-literal': 2,
'no-trailing-spaces': 2,
'no-undef': 2,
'no-undef-init': 2,
'no-unexpected-multiline': 2,
'no-unmodified-loop-condition': 2,
'no-unneeded-ternary': [
2,
{
defaultAssignment: false
}
],
'no-unreachable': 2,
'no-unsafe-finally': 2,
'no-unused-vars': [
2,
{
vars: 'all',
args: 'none'
}
],
'no-useless-call': 2,
'no-useless-computed-key': 2,
'no-useless-constructor': 2,
'no-useless-escape': 0,
'no-whitespace-before-property': 2,
'no-with': 2,
'one-var': [
2,
{
initialized: 'never'
}
],
'operator-linebreak': [
2,
'after',
{
overrides: {
'?': 'before',
':': 'before'
}
}
],
'padded-blocks': [2, 'never'],
quotes: [
2,
'single',
{
avoidEscape: true,
allowTemplateLiterals: true
}
],
semi: 'off',
'semi-spacing': [
2,
{
before: false,
after: true
}
],
'space-before-blocks': [2, 'always'],
'space-before-function-paren': [2, 'never'],
'space-in-parens': [2, 'never'],
'space-infix-ops': 2,
'space-unary-ops': [
2,
{
words: true,
nonwords: false
}
],
'spaced-comment': [
2,
'always',
{
markers: [
'global',
'globals',
'eslint',
'eslint-disable',
'*package',
'!',
','
]
}
],
'template-curly-spacing': [2, 'never'],
'use-isnan': 2,
'valid-typeof': 2,
'wrap-iife': [2, 'any'],
'yield-star-spacing': [2, 'both'],
yoda: [2, 'never'],
'prefer-const': 2,
'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0,
'object-curly-spacing': 'off',
'array-bracket-spacing': [2, 'never']
}
};

View File

@@ -1,39 +0,0 @@
---
name: 报告问题Bug report
about: 详细描述你遇到的问题并寻求社区帮助
title: ''
labels: ''
assignees: ''
---
**问题描述**
[问题描述:尽可能简洁清晰地把问题描述清楚]
**复现步骤**
[复现问题的步骤]
1. 启动 '...'
2. 点击 '....'
3. 查看
[或者可以直接贴源代码]
**预期结果**
[使用简洁清晰的语言描述你希望生效的预期结果]
**实际结果**
[这里请贴上你的报错截图或文字]
**系统信息:**
- 发行平台: [如 微信小程序、H5平台、5+ App等]
- 操作系统 [如 iOS 12.1.2、Android 7.0]
- HBuilderX版本 [如使用HBuilderX则需提供 HBuilderX 版本号]
- 项目创建方法 [如使用Vue-cli创建/HBuilderX]
- 设备信息 [如 iPhone8 Plus]
- uni-simple-router版本 [如 v1.5.4]
**补充信息**
[可选]
[根据你的分析,出现这个问题的原因可能在哪里?]

View File

@@ -1,21 +0,0 @@
---
name: 建议新功能Feature Request
about: 对 uni-simple-router 提出改善建议
title: ''
labels: ''
assignees: ''
---
**新功能描述**
简洁描述你希望补充完善的增强功能
**现状及问题**
[当前现状及由此导致的不便]
**尝试方案**
[如果你有尝试绕开或其它解决方案,在这里描述你的建议方案]
**补充信息**
[其它你认为有参考价值的信息]

View File

@@ -1,76 +0,0 @@
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, sex characteristics, gender identity and expression,
level of experience, education, socio-economic status, nationality, personal
appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment
include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or
advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at 1606726660@qq.com. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see
https://www.contributor-covenant.org/faq

View File

@@ -1,21 +0,0 @@
MIT License
Copyright (c) 2019 hhyang
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -1,49 +0,0 @@
# uni-simple-router
> 一个更为简洁的[Vue-router](https://router.vuejs.org/zh/),专为 [uni-app](https://uniapp.dcloud.io/) 量身打造
## 介绍
`uni-simple-router` 是专为 [uni-app](https://uniapp.dcloud.io/) 打造的路由器。它与 [uni-app](https://uniapp.dcloud.io/) 核心深度集成,使使用 [uni-app](https://uniapp.dcloud.io/) 轻松构建单页应用程序变得轻而易举。功能包括:
* `H5端` 能完全使用 `vue-router` 进行开发。
* 模块化,基于组件的路由器配置。
* 路由参数,查询,通配符。
* `H5端` 查看由 `uni-simple-router` 过渡系统提供动力的过渡效果。
* 更细粒度的导航控制。
* `H端`自动控制活动的CSS类链接。
* 通配小程序端、APP端、H5端。
开始使用 [查看文档](http://hhyang.cn),或 [使用示例](https://github.com/SilurianYang/uni-simple-router/tree/master/examples)(请参见下面的示例)。
## 问题
在提交问题的之前,请确保阅读 [“问题报告清单”](https://github.com/SilurianYang/uni-simple-router/issues/new?assignees=&labels=&template=bug_report.md&title=) 。不符合准则的问题可能会立即被解决。
## 贡献
提出拉取请求之前,请务必先阅读 [查看文档](http://hhyang.cn)(请参见下面的示例)。。
## 变更日志
[发行说明](https://github.com/SilurianYang/uni-simple-router/releases) 中记录了每个发行版的详细信息更改。
## 特别感谢
特别感谢 [markrgba](https://github.com/markrgba) 一直以来对文档和相关测试的维护。
## 技术交流
<a target="_blank" href="//shang.qq.com/wpa/qunwpa?idkey=0f4d7f38e5d15dd49bf7c3032c80ed3f54ecfa3dd800053d6ae145c869f9eb47"><img border="0" src="http://pub.idqqimg.com/wpa/images/group.png" alt="uni-app 插件" title="uni-app 插件"></a>
## 成品预览
<div style="display: -webkit-box;display: flex; flex-direction: column;align-items: center;">
<p style="color: #3eaf7c;font-size:18px">uni-simple-router@2.0+ts+uni-app</p>
<img src="https://hhyang.cn/images/ad1.jpg" width="200" height="200">
</div>

View File

@@ -1,38 +0,0 @@
```flow
st=>start: 开始跳转
e=>end: 跳转结束
platform=>operation: 平台选择
H5=>condition: H5
APP=>condition: APP
applets=>condition: 小程序
routerBeforeEach=>operation: routerBeforeEach
lock=>condition: 跳转加锁
runH5=>operation: H5
runAPP=>parallel: APP
runapplets=>parallel: 小程序
beforeRouteLeave=>condition: beforeRouteLeave
beforeEach=>condition: beforeEach
beforeEnter=>condition: beforeEnter
afterEach=>operation: afterEach
runJump=>condition: 执行跳转成功或者失败
stopJump=>operation: next(false) 停止跳转
errorJump=>operation: 跳转失败
routerErrorEach=>operation: routerErrorEach
routerAfterEach=>operation: routerAfterEach
st->platform(right)->applets(yes)->routerBeforeEach
applets(no)->APP(yes)->routerBeforeEach
APP(no)->H5(yes)->routerBeforeEach
routerBeforeEach->lock(yes)->runAPP(path1)->runapplets(path1)->beforeRouteLeave
lock(no)->runH5->beforeRouteLeave(no)->stopJump->routerErrorEach
beforeRouteLeave(yes)->beforeEach(no)->stopJump->routerErrorEach
beforeEach(yes)->beforeEnter(no)->stopJump->routerErrorEach
beforeEnter(yes)->runJump(no)->errorJump->routerErrorEach
runJump(yes)->afterEach->routerAfterEach
routerAfterEach->e
routerErrorEach->e
```

View File

@@ -1,50 +0,0 @@
// this the shared base config for all packages.
{
"$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json",
"mainEntryPointFilePath": "./dist/src/index.d.ts",
"apiReport": {
"enabled": true,
"reportFolder": "./temp/"
},
"docModel": {
"enabled": true
},
"dtsRollup": {
"enabled": true,
"untrimmedFilePath": "./dist/<unscopedPackageName>.d.ts"
},
"tsdocMetadata": {
"enabled": false
},
"messages": {
"compilerMessageReporting": {
"default": {
"logLevel": "warning"
}
},
"extractorMessageReporting": {
"default": {
"logLevel": "warning",
"addToApiReportFile": true
},
"ae-missing-release-tag": {
"logLevel": "none"
}
},
"tsdocMessageReporting": {
"default": {
"logLevel": "warning"
}
}
}
}

View File

@@ -1,79 +0,0 @@
<template>
<view @click="gotoPage()"><slot></slot></view>
</template>
<script>
const navType = {
push: 'push',
replace: 'replace',
replaceAll: 'replaceAll',
pushTab: 'pushTab',
back:'back'
};
export default {
props: {
to: {
type: [String, Object],
required: true
},
stopNavto: {
type: Boolean,
default: false,
},
navType: {
type: String,
default: 'push',
},
level: {
type: Number,
default: 1,
},
append: {
type: Boolean,
default: false,
},
},
methods: {
formatNav(text) {
if (text != null && text.constructor === String) {
text = text.replace(/\'/g, '');
text = text.replace(/(\w+)(?=:)/g, function (val) {
return `"${val}"`;
});
text = text.replace(/:\s*([^,{}\s"]+)/g, function (val) {
const arr = val.split(':');
return `:"${arr[1].trim()}"`;
});
try {
text = JSON.parse(text);
} catch (e) {}
}
if (this.append) {
let pathArr = this.$Route.path.split('/');
pathArr.splice(pathArr.length - this.level, this.level);
pathArr = pathArr.join('/');
if (text.constructor === Object) {
if (text.path) {
text.path = pathArr + text.path;
}
} else {
text = pathArr + text;
}
}
return text;
},
gotoPage() {
if (this.stopNavto) {
return true;
}
const type = navType[this.navType];
if (type == null) {
return console.error(` "navType" unknown type \n\n value${Object.values(navType).join('、')}`);
}
const navInfo = this.formatNav(this.to);
this.$Router[type](navInfo);
},
},
};
</script>

View File

@@ -1,312 +0,0 @@
export declare interface AppConfig {
registerLoadingPage?: boolean;
loadingPageStyle?: () => object;
loadingPageHook?: (view: any) => void;
launchedHook?: () => void;
animation?: startAnimationRule;
}
export declare interface appletConfig {
animationDuration?: number;
}
export declare type backTypeRule = 'backbutton' | 'navigateBack';
export declare function createRouter(params: InstantiateConfig): Router;
export declare interface debuggerArrayConfig {
error?: boolean;
warn?: boolean;
log?: boolean;
}
export declare type debuggerConfig = boolean | debuggerArrayConfig;
export declare interface endAnimationRule {
animationType?: endAnimationType;
animationDuration?: number;
}
export declare type endAnimationType = 'slide-out-right' | 'slide-out-left' | 'slide-out-top' | 'slide-out-bottom' | 'pop-out' | 'fade-out' | 'zoom-in' | 'zoom-fade-in' | 'none';
export declare type guardHookRule = (to: totalNextRoute, from: totalNextRoute, next: (rule?: navtoRule | false) => void) => void;
export declare interface H5Config {
paramsToQuery?: boolean;
vueRouterDev?: boolean;
vueNext?: boolean;
mode?: string;
base?: string;
linkActiveClass?: string;
linkExactActiveClass?: string;
scrollBehavior?: Function;
fallback?: boolean;
}
export declare interface h5NextRule {
fullPath?: string | undefined;
hash?: string | undefined;
matched?: Array<object>;
meta?: object;
name?: undefined | string;
type?: undefined | string;
}
export declare type hookListRule = Array<(router: Router, to: totalNextRoute, from: totalNextRoute, toRoute: RoutesRule, next: Function) => void>;
export declare interface hookObjectRule {
options: Array<any>;
hook: Function;
}
export declare enum hookToggle {
'beforeHooks' = "beforeEach",
'afterHooks' = "afterEach",
'enterHooks' = "beforeEnter"
}
export declare interface InstantiateConfig {
[key: string]: any;
keepUniOriginNav?: boolean;
platform: platformRule;
h5?: H5Config;
APP?: AppConfig;
applet?: appletConfig;
debugger?: debuggerConfig;
routerBeforeEach?: (to: navtoRule, from: navtoRule, next: (rule?: navtoRule | false) => void) => void;
routerAfterEach?: (to: navtoRule, from: navtoRule, next?: Function) => void;
routerErrorEach?: (error: navErrorRule, router: Router) => void;
resolveQuery?: (jsonQuery: objectAny) => objectAny;
parseQuery?: (jsonQuery: objectAny) => objectAny;
detectBeforeLock?: (router: Router, to: string | number | totalNextRoute | navRoute, navType: NAVTYPE) => void;
routes: RoutesRule[];
}
export declare interface LifeCycleConfig {
beforeHooks: hookListRule;
afterHooks: hookListRule;
routerBeforeHooks: hookListRule;
routerAfterHooks: hookListRule;
routerErrorHooks: Array<(error: navErrorRule, router: Router) => void>;
}
export declare interface navErrorRule {
type: navRuleStatus;
msg: string;
to?: totalNextRoute;
from?: totalNextRoute;
nextTo?: any;
[propName: string]: any;
}
export declare type navMethodRule = Promise<void | undefined | navRuleStatus>;
export declare interface navRoute extends h5NextRule, navtoRule {
}
export declare type navRuleStatus = 0 | 1 | 2 | 3;
export declare interface navtoRule {
NAVTYPE?: NAVTYPE;
path?: string;
name?: string | undefined;
query?: objectAny;
params?: objectAny;
animationType?: startAnimationType | endAnimationType;
animationDuration?: number;
events?: objectAny;
success?: Function;
fail?: Function;
complete?: Function;
}
export declare type NAVTYPE = 'push' | 'replace' | 'replaceAll' | 'pushTab' | 'back';
export declare enum navtypeToggle {
'push' = "navigateTo",
'replace' = "redirectTo",
'replaceAll' = "reLaunch",
'pushTab' = "switchTab",
'back' = "navigateBack"
}
export declare type objectAny = {
[propName: string]: any;
};
export declare interface originMixins extends uniNavApiRule {
BACKTYPE: '' | backTypeRule;
}
export declare type pageTypeRule = 'app' | 'page' | 'component';
export declare type platformRule = 'h5' | 'app-plus' | 'app-lets' | 'mp-weixin' | 'mp-baidu' | 'mp-alipay' | 'mp-toutiao' | 'mp-qq' | 'mp-360';
export declare type PromiseResolve = (value?: void | PromiseLike<void> | undefined) => void;
export declare type proxyDepsRule = {
resetIndex: Array<number>;
hooks: {
[key: number]: {
proxyHook: () => void;
callHook: (enterPath: string) => void;
resetHook: () => void;
};
};
options: {
[key: number]: Array<any>;
};
};
export declare type proxyHookName = 'beforeHooks' | 'afterHooks';
export declare type reloadNavRule = totalNextRoute | false | undefined | string;
export declare type reNavMethodRule = 'navigateTo' | 'redirectTo' | 'reLaunch' | 'switchTab';
export declare type reNotNavMethodRule = 'navigateBack';
export declare enum rewriteMethodToggle {
'navigateTo' = "push",
'navigate' = "push",
'redirectTo' = "replace",
'reLaunch' = "replaceAll",
'switchTab' = "pushTab",
'navigateBack' = "back"
}
export declare interface Router {
[key: string]: any;
readonly lifeCycle: LifeCycleConfig;
readonly options: InstantiateConfig;
$lockStatus: boolean;
$route: object | null;
enterPath: string;
Vue: any;
appMain: {
NAVTYPE: reNavMethodRule | reNotNavMethodRule;
path: string;
} | {};
proxyHookDeps: proxyDepsRule;
routesMap: routesMapRule | {};
mount: Array<{
app: any;
el: string;
}>;
install(Vue: any): void;
push(to: totalNextRoute | navRoute | string, from?: totalNextRoute): void;
replace(to: totalNextRoute | navRoute | string, from?: totalNextRoute): void;
replaceAll(to: totalNextRoute | navRoute | string, from?: totalNextRoute): void;
pushTab(to: totalNextRoute | navRoute | string, from?: totalNextRoute): void;
back(level: number | undefined, origin?: uniBackRule | uniBackApiRule): void;
forceGuardEach(navType: NAVTYPE | undefined, forceNav: boolean): void;
beforeEach(userGuard: guardHookRule): void;
afterEach(userGuard: (to: totalNextRoute, from: totalNextRoute) => void): void;
}
export declare function RouterMount(Vim: any, router: Router, el?: string | undefined): void | never;
export declare interface routeRule {
name: string | undefined;
meta: objectAny;
path: string;
query: objectAny;
params: objectAny;
fullPath: string;
NAVTYPE: NAVTYPE | '';
BACKTYPE?: backTypeRule | '';
[propName: string]: any;
}
export declare type routesMapKeysRule = 'finallyPathList' | 'finallyPathMap' | 'aliasPathMap' | 'pathMap' | 'nameMap' | 'vueRouteMap';
export declare interface routesMapRule {
[key: string]: any;
finallyPathList: Array<string>;
finallyPathMap: RoutesRule;
aliasPathMap: RoutesRule;
pathMap: RoutesRule;
nameMap: RoutesRule;
vueRouteMap: objectAny;
}
export declare interface RoutesRule {
path: string;
component?: object;
name?: string;
components?: object;
redirect?: string | Function;
props?: boolean | object | Function;
aliasPath?: string;
alias?: string | Array<string>;
children?: Array<RoutesRule>;
beforeEnter?: guardHookRule;
meta?: any;
[propName: string]: any;
}
export declare function runtimeQuit(title?: string | undefined): void;
export declare interface startAnimationRule {
animationType?: startAnimationType;
animationDuration?: number;
}
export declare type startAnimationType = 'slide-in-right' | 'slide-in-left' | 'slide-in-top' | 'slide-in-bottom' | 'pop-in' | 'fade-in' | 'zoom-out' | 'zoom-fade-out' | 'none';
export declare interface totalNextRoute extends h5NextRule, navtoRule {
path: string;
delta?: number;
[propName: string]: any;
}
export declare interface uniBackApiRule {
delta?: number;
animationDuration?: number;
animationType?: endAnimationType;
}
export declare interface uniBackRule {
from: backTypeRule;
}
export declare interface uniNavApiRule {
url: string;
openType?: 'appLaunch';
query?: objectAny;
path?: string;
delta?: number;
detail?: {
[propName: string]: any;
};
animationType?: startAnimationType;
animationDuration?: number;
events?: {
[propName: string]: any;
};
success?: Function;
fail?: Function;
complete?: Function;
animation?: {
animationType?: startAnimationType;
animationDuration?: number;
};
}
export declare type vueHookNameRule = 'onLaunch' | 'onShow' | 'onHide' | 'onError' | 'onInit' | 'onLoad' | 'onReady' | 'onUnload' | 'onResize' | 'created' | 'beforeMount' | 'mounted' | 'beforeDestroy' | 'destroyed';
export declare type vueOptionRule = {
[propName in vueHookNameRule]: Array<Function> | undefined;
};
export { }
// @ts-ignore
declare module 'vue/types/vue' {
interface Vue {
$Router: Router;
$Route: routeRule;
}
}

File diff suppressed because one or more lines are too long

View File

@@ -1,107 +0,0 @@
#!/bin/bash
# author hhyang
# home https://github.com/SilurianYang
printf "\n -------------- Ctrl+D可以退出程序 --------------- \n\n"
select name in "auto" "status" "add" "commit" "push" "pull" "branch" "checkout" "*"; do
case "$name" in
# 自动同步文件
"auto")
cp -avx ./examples/node_modules/uni-simple-router/* ./npm-package
rm -rf ./npm-package/package-lock.json
cp -avx ./README.md ./npm-package
cp -avx ./package.json ./npm-package
cp -avx ./npm-package/* ./src
rm -rf ./src/README.md
rm -rf ./src/package.json
printf "\n -------------- 自动化构建目录完毕 --------------- \n\n"
;;
# 查询status
"status")
git status
printf "\n -------------- 查询完毕 --------------- \n\n"
;;
# 添加文件 .或* 全部文件 可自定义文件路径
"add")
while read -p "请输入更多提交命令 【默认全部.】 " add; do
if [[ "$add" == "" ]]; then
eval "git add ."
else
eval "git add ${add}"
fi
printf "\n -------------- 添加完成 --------------- \n\n"
break
done
;;
# 提交文件
"commit")
while read -p "请输入提交信息:" readme; do
if [[ "$readme" != "" ]]; then
eval "git commit -m '${readme}'"
printf "\n -------------- 提交本地完成 --------------- \n\n"
break
else
printf "\n警告====> 提交信息不能为空! \n \n"
fi
done
;;
# 推送到服务端
"push")
read -p "请输入提交的分支(不输入默认主分支 [master] )" branch
printf "\n\n -------------- 正在推送github,请稍后.... --------------- \n\n"
if [[ "$branch" == "" ]]; then
git push
else
eval "git push origin ${branch}"
fi
printf "\n -------------- 推送github完成 --------------- \n\n"
;;
# 拉取最新代码
"pull")
printf "\n\n -------------- 正在拉取,请稍后.... --------------- \n\n"
git pull
printf "\n -------------- 正在拉取完成 --------------- \n\n"
;;
# 切换分支操作
"branch")
read -p "请输入添加更多指令 【分支】 " branchs
if [[ "$branchs" == "" ]]; then
printf "\n分支列表如下\n\n"
git branch
else
eval "git branch ${branchs}"
fi
printf "\n -------------- 分支操作完毕 --------------- \n\n"
;;
#
"checkout")
read -p "请输入添加更多指令 【默认切换到master】 " out
if [[ "$out" == "" ]]; then
git checkout master
else
eval "git checkout ${out}"
fi
printf "\n -------------- 执行完毕 --------------- \n\n"
;;
# 自定义指令
*)
while read -p "请输入自定义命令 【输入:q退出】" code; do
if [[ "$code" == ":q" ]];then
printf "\n"
break
fi
printf "\n\n -------------- 正在执行,请稍后.... --------------- \n\n"
eval "$code"
printf "\n -------------- 执行完毕 --------------- \n\n"
done
esac
done

View File

@@ -1,5 +0,0 @@
module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
moduleDirectories:['node_modules','src']
};

View File

@@ -1,62 +0,0 @@
{
"_from": "uni-simple-router",
"_id": "uni-simple-router@2.0.7",
"_inBundle": false,
"_integrity": "sha512-8FKv5dw7Eoonm0gkO8udprrxzin0fNUI0+AvIphFkFRH5ZmP5ZWJ2pvnWzb2NiiqQSECTSU5VSB7HhvOSwD5eA==",
"_location": "/uni-simple-router",
"_phantomChildren": {},
"_requested": {
"type": "tag",
"registry": true,
"raw": "uni-simple-router",
"name": "uni-simple-router",
"escapedName": "uni-simple-router",
"rawSpec": "",
"saveSpec": null,
"fetchSpec": "latest"
},
"_requiredBy": [
"#USER",
"/"
],
"_resolved": "https://registry.npmjs.org/uni-simple-router/-/uni-simple-router-2.0.7.tgz",
"_shasum": "04e0b5be6cd733a1ecb9d35a3dbe82f27f48204e",
"_spec": "uni-simple-router",
"_where": "/Users/WebTmm/Desktop/BlockChainH5",
"author": {
"name": "hhyang"
},
"bugs": {
"url": "https://github.com/SilurianYang/uni-simple-router/issues"
},
"bundleDependencies": false,
"deprecated": false,
"description": "> 一个更为简洁的[Vue-router](https://router.vuejs.org/zh/),专为 [uni-app](https://uniapp.dcloud.io/) 量身打造",
"homepage": "https://github.com/SilurianYang/uni-simple-router#readme",
"keywords": [
"router",
"uni-app-router",
"interceptor",
"uni-app",
"uniapp"
],
"license": "MIT",
"main": "dist/uni-simple-router.js",
"name": "uni-simple-router",
"repository": {
"type": "git",
"url": "git+https://github.com/SilurianYang/uni-simple-router.git"
},
"scripts": {
"build": "node ./publish/build.js",
"dev": "webpack --watch --progress --config webpack/webpack.dev.js",
"dist": "webpack --progress --config webpack/webpack.prod.js",
"dist:dts": "api-extractor run --local --verbose",
"lint": "eslint --ext .js,.ts src",
"lintFix": "eslint --ext .js,.ts src --fix",
"publish": "node ./publish/index.js",
"test": "jest test/query-toggle.spec.ts"
},
"types": "dist/uni-simple-router.d.ts",
"version": "2.0.7"
}

View File

@@ -1,16 +0,0 @@
## Fixes bug
* `小程序``onLoad``onShow` 执行不标准的BUG。(#206,#224,#291)
* `小程序` 端 启动页必须写 `onLoad` 才会执行的BUG。
* `APP` 端 tab 拦截后无法自动还原选中区域现在已修复。
* H5端设置 `aliasPath` 后,无法使用 `aliasPath` 跨端跳转 (#302)
* 重写代理生命周期逻辑、保证执行各端执行顺序 (#312)
## Revise
* 参数可以直接传递 `null`。但是需要注意:**在非深度对象传参的情况下,小程序会将 `null` 解析为字符串`undefined`**
* 多端情况下自定义启动参数不仅限制于 `query` 传递深度参数,任何组合都可以 (#307,#301)
* 去除 `keyword` 白名单字段
* 调整小程序启动页面生命周期的执行让在小程序下的生命周期能更贴近App、H5
* `routerErrorEach` 新增回调参数、包括:`NAVTYPE``uniActualData``level`
## Known Issues
* `APP` 端启动页为tab时拦截到其他页面后底部tabbar 还依然存在,请避免把原生 `tabbar` 页设置成启动页。你可以在 `beforeEach` 中使用 next 到tabbar页效果一致

View File

@@ -1,76 +0,0 @@
import {RoutesRule, Router, routesMapRule, totalNextRoute, hookToggle, navtoRule} from '../options/base';
import {H5Config} from '../options/config';
import {warn} from '../helpers/warn'
import {getDataType, getRoutePath} from '../helpers/utils'
import { onTriggerEachHook } from '../public/hooks';
export function buildVueRoutes(router: Router, vueRouteMap:RoutesRule):RoutesRule {
const {pathMap, finallyPathList} = (router.routesMap as routesMapRule);
const vueRoutePathList:Array<string> = Object.keys(vueRouteMap);
for (let i = 0; i < vueRoutePathList.length; i++) {
const path = vueRoutePathList[i];
const myRoute:RoutesRule = pathMap[path];
const vueRoute:RoutesRule = vueRouteMap[path];
if (!myRoute) {
warn(`${path} 路由地址在路由表中未找到,确定是否传递漏啦`, router, true);
} else {
const {finallyPath} = getRoutePath(myRoute, router);
if (finallyPath instanceof Array) {
throw new Error(`非 vueRouterDev 模式下alias、aliasPath、path 无法提供数组类型! ${JSON.stringify(myRoute)}`);
}
if (myRoute.name != null) {
vueRoute.name = myRoute.name;
}
const vuePath = vueRoute['path'];
const vueAlias = vueRoute['alias'];
delete vueRoute['alias'];
vueRoute['path'] = (finallyPath as string);
if (vuePath === '/' && vueAlias != null) {
vueRoute['alias'] = vueAlias;
vueRoute['path'] = vuePath;
}
const beforeEnter = myRoute.beforeEnter;
if (beforeEnter) {
vueRoute['beforeEnter'] = function(
to:totalNextRoute,
from: totalNextRoute,
next:(rule?: navtoRule|false)=>void,
):void{
onTriggerEachHook(to, from, router, hookToggle['enterHooks'], next)
};
}
}
}
if (finallyPathList.includes('*')) {
vueRouteMap['*'] = pathMap['*']
}
return vueRouteMap
}
export function buildVueRouter(router:Router, vueRouter:any, vueRouteMap:RoutesRule|RoutesRule[]) :void |never {
let routes:RoutesRule[] = [];
if (getDataType<RoutesRule|RoutesRule[]>(vueRouteMap) === '[object Array]') {
routes = (vueRouteMap as RoutesRule[]);
} else {
routes = Object.values(vueRouteMap);
}
const {scrollBehavior, fallback} = router.options.h5 as H5Config;
const oldScrollBehavior = vueRouter.options.scrollBehavior;
vueRouter.options.scrollBehavior = function proxyScrollBehavior(
to:totalNextRoute,
from:totalNextRoute,
savedPosition:any
) {
oldScrollBehavior && oldScrollBehavior(to, from, savedPosition);
return (scrollBehavior as Function)(to, from, savedPosition)
}
vueRouter.fallback = fallback;
// Detail see: https://github.com/vuejs/vue-router/issues/1234#issuecomment-357941465
const newVueRouter:any = new vueRouter.constructor({
...router.options.h5,
base: vueRouter.options.base,
mode: vueRouter.options.mode,
routes
});
vueRouter.matcher = newVueRouter.matcher;
}

View File

@@ -1,71 +0,0 @@
import {Router, proxyHookName, totalNextRoute, navtoRule} from '../options/base';
export class MyArray extends Array {
constructor(
private router:Router,
private vueEachArray:Array<Function>,
private myEachHook:Function,
private hookName:'beforeHooks'| 'afterHooks',
) {
super();
Object.setPrototypeOf(this, MyArray.prototype)
}
push(v:any):any {
this.vueEachArray.push(v);
const index = this.length;
this[this.length] = (to: totalNextRoute, from: totalNextRoute, next:(rule?: navtoRule|false)=>void) => {
if (index > 0) {
this.vueEachArray[index](to, from, () => {
next && next()
});
} else {
this.myEachHook(to, from, (nextTo?:navtoRule|false) => {
// Fixe https://github.com/SilurianYang/uni-simple-router/issues/241 2021年3月6日22:15:27
// 目前不调用uni-app的守卫函数因为会丢失页面栈信息
if (nextTo === false) {
next(false);
} else {
this.vueEachArray[index](to, from, (uniNextTo?:navtoRule|false) => {
next(nextTo);
})
}
}, this.router, true);
}
};
}
}
export function proxyEachHook(router:Router, vueRouter:any):void {
const hookList:Array<'beforeHooks'| 'afterHooks'> = ['beforeHooks', 'afterHooks'];
for (let i = 0; i < hookList.length; i++) {
const hookName = hookList[i];
const myEachHook = router.lifeCycle[(hookName as proxyHookName)][0];
if (myEachHook) {
const vueEachArray:Array<Function> = vueRouter[hookName];
vueRouter[hookName] = new MyArray(router, vueEachArray, myEachHook, hookName);
}
}
}
export function proxyH5Mount(router:Router):void {
if (router.mount.length === 0) {
if (router.options.h5?.vueRouterDev) {
return
}
const uAgent = navigator.userAgent;
const isIos = !!uAgent.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/)
if (isIos) {
// 【Fixe】 https://github.com/SilurianYang/uni-simple-router/issues/109
setTimeout(() => {
const element = document.getElementsByTagName('uni-page');
if (element.length > 0) {
return false
}
window.location.reload();
}, 0);
}
} else {
const [{app}] = router.mount;
app.$mount();
router.mount = [];
}
}

View File

@@ -1,75 +0,0 @@
import { objectAny, Router, totalNextRoute } from '../options/base';
import { AppConfig } from '../options/config';
let quitBefore:number|null = null;
let TABBAR:objectAny|null = null;
export function registerLoddingPage(
router:Router,
):void{
if (router.options.registerLoadingPage) {
const { loadingPageHook, loadingPageStyle } = router.options.APP as AppConfig; // 获取app所有配置
const view = new plus.nativeObj.View('router-loadding', {
top: '0px',
left: '0px',
height: '100%',
width: '100%',
...(loadingPageStyle as Function)()
});
(loadingPageHook as Function)(view); // 触发等待页面生命周期
}
}
export function runtimeQuit(
title:string|undefined = '再按一次退出应用'
):void{
const nowTime = +new Date();
if (!quitBefore) {
quitBefore = nowTime;
uni.showToast({
title,
icon: 'none',
position: 'bottom',
duration: 1000
});
setTimeout(() => { quitBefore = null }, 1000);
} else {
if (nowTime - quitBefore < 1000) {
plus.runtime.quit();
}
}
}
export function tabIndexSelect(
to:totalNextRoute,
from:totalNextRoute
):boolean {
if (!(__uniConfig.tabBar && Array.isArray(__uniConfig.tabBar.list))) {
return false
}
const tabBarList = __uniConfig.tabBar.list;
const routes:Array<totalNextRoute> = [];
let activeIndex:number = 0;
for (let i = 0; i < tabBarList.length; i++) {
const route:totalNextRoute = tabBarList[i];
if ('/' + route.pagePath === to.path || '/' + route.pagePath === from.path) {
if (route.pagePath === from.path) {
activeIndex = i;
}
routes.push(route);
}
if (routes.length === 2) {
break
}
}
if (routes.length !== 2) {
return false
}
if (TABBAR == null) {
TABBAR = uni.requireNativePlugin('uni-tabview')
}
(TABBAR as objectAny).switchSelect({
index: activeIndex
})
return true
}

View File

@@ -1,18 +0,0 @@
import { Router} from '../options/base';
export function getEnterPath(
vueVim:any,
router:Router,
) :string {
switch (router.options.platform) {
case 'mp-alipay':
case 'mp-weixin':
case 'mp-toutiao':
case 'mp-qq':
return vueVim.$options.mpInstance.route;
case 'mp-baidu':
// 【Fixe】 https://github.com/SilurianYang/uni-simple-router/issues/251
return vueVim.$options.mpInstance.is || vueVim.$options.mpInstance.pageinstance.route;
}
return vueVim.$options.mpInstance.route; // 这是暂时的 因为除了以上的小程序 其他没测试 先这样写
}

View File

@@ -1,79 +0,0 @@
<template>
<view @click="gotoPage()"><slot></slot></view>
</template>
<script>
const navType = {
push: 'push',
replace: 'replace',
replaceAll: 'replaceAll',
pushTab: 'pushTab',
back:'back'
};
export default {
props: {
to: {
type: [String, Object],
required: true
},
stopNavto: {
type: Boolean,
default: false,
},
navType: {
type: String,
default: 'push',
},
level: {
type: Number,
default: 1,
},
append: {
type: Boolean,
default: false,
},
},
methods: {
formatNav(text) {
if (text != null && text.constructor === String) {
text = text.replace(/\'/g, '');
text = text.replace(/(\w+)(?=:)/g, function (val) {
return `"${val}"`;
});
text = text.replace(/:\s*([^,{}\s"]+)/g, function (val) {
const arr = val.split(':');
return `:"${arr[1].trim()}"`;
});
try {
text = JSON.parse(text);
} catch (e) {}
}
if (this.append) {
let pathArr = this.$Route.path.split('/');
pathArr.splice(pathArr.length - this.level, this.level);
pathArr = pathArr.join('/');
if (text.constructor === Object) {
if (text.path) {
text.path = pathArr + text.path;
}
} else {
text = pathArr + text;
}
}
return text;
},
gotoPage() {
if (this.stopNavto) {
return true;
}
const type = navType[this.navType];
if (type == null) {
return console.error(` "navType" unknown type \n\n value${Object.values(navType).join('、')}`);
}
const navInfo = this.formatNav(this.to);
this.$Router[type](navInfo);
},
},
};
</script>

View File

@@ -1,7 +0,0 @@
declare var uni:any;
declare var plus:any;
declare var __uniConfig:any;
declare var __uniRoutes:any;
declare function getCurrentPages(isAll:boolean|undefined=false):any;
declare function getApp(args?:{allowDefault: true}):any;
declare var $npm_package_name:string;

View File

@@ -1,78 +0,0 @@
import {err} from './warn'
import { InstantiateConfig, LifeCycleConfig} from '../options/config'
import { vueHookNameRule, proxyDepsRule } from '../options/base';
export const mpPlatformReg = '(^mp-weixin$)|(^mp-baidu$)|(^mp-alipay$)|(^mp-toutiao$)|(^mp-qq$)|(^mp-360$)' // 小程序下不能直接导出正则 需要重新组装成正则 不然bug一推 诡异
export const baseConfig:InstantiateConfig = {
h5: {
paramsToQuery: false,
vueRouterDev: false,
vueNext: false,
mode: 'hash',
base: '/',
linkActiveClass: 'router-link-active',
linkExactActiveClass: 'router-link-exact-active',
scrollBehavior: (to:any, from:any, savedPostion:Function) => ({ x: 0, y: 0 }),
fallback: true
},
APP: {
registerLoadingPage: true,
loadingPageStyle: () => JSON.parse('{"backgroundColor":"#FFF"}'),
loadingPageHook: (view:any) => { view.show(); },
launchedHook: () => { plus.navigator.closeSplashscreen(); },
animation: {}
},
applet: {
animationDuration: 300
},
platform: 'h5',
keepUniOriginNav: false,
debugger: false,
routerBeforeEach: (to, from, next) => { next() },
routerAfterEach: (to, from) => {},
routerErrorEach: (error, router) => { router.$lockStatus = false; err(error, router, true); },
detectBeforeLock: (router, to, navType) => {},
routes: [
{
path: '/choose-location'
},
{
path: '/open-location'
},
{
path: '/preview-image'
}
]
}
export const lifeCycle:LifeCycleConfig = {
beforeHooks: [],
afterHooks: [],
routerBeforeHooks: [],
routerAfterHooks: [],
routerErrorHooks: []
};
export const proxyHookDeps:proxyDepsRule = {
resetIndex: [], // 还原时执行的生命周期的索引
hooks: {},
options: {}
}
export const proxyHookName:Array<vueHookNameRule> = [
'onLaunch',
'onShow',
'onHide',
'onError',
'onInit',
'onLoad',
'onReady',
'onUnload',
'onResize',
'created',
'beforeMount',
'mounted',
'beforeDestroy',
'destroyed'
]

View File

@@ -1,47 +0,0 @@
import {RoutesRule, Router, routesMapRule} from '../options/base';
import {H5Config} from '../options/config';
import {warn} from './warn'
import {getRoutePath} from './utils'
export function createRouteMap(
router: Router,
routes: RoutesRule[],
): routesMapRule|never {
const routesMap:routesMapRule = {
finallyPathList: [],
finallyPathMap: Object.create(null),
aliasPathMap: Object.create(null),
pathMap: Object.create(null),
vueRouteMap: Object.create(null),
nameMap: Object.create(null)
}
routes.forEach(route => {
const { finallyPath, aliasPath, path} = getRoutePath(route, router);
if (path == null) {
throw new Error(`请提供一个完整的路由对象,包括以绝对路径开始的 path 字符串 ${JSON.stringify(route)}`);
}
if (finallyPath instanceof Array) {
if (!(router.options.h5 as H5Config).vueRouterDev && router.options.platform === 'h5') {
throw new Error(`非 vueRouterDev 模式下route.alias 目前无法提供数组类型! ${JSON.stringify(route)}`);
}
}
const strFinallyPath = (finallyPath as string);
const strAliasPath = (aliasPath as string);
if (router.options.platform !== 'h5') {
if (strFinallyPath.indexOf('/') !== 0 && path !== '*') {
warn(`当前路由对象下route${JSON.stringify(route)} 是否缺少了前缀 /`, router, true);
}
}
if (!routesMap.finallyPathMap[strFinallyPath]) {
routesMap.finallyPathMap[strFinallyPath] = route;
routesMap.aliasPathMap[strAliasPath] = route;
routesMap.pathMap[path] = route;
routesMap.finallyPathList.push(strFinallyPath);
if (route.name != null) {
routesMap.nameMap[route.name] = route;
}
}
})
return routesMap;
}

View File

@@ -1,36 +0,0 @@
import { navtoRule, navErrorRule, Router, proxyHookName, guardHookRule, totalNextRoute, hookToggle} from '../options/base';
import { LifeCycleConfig, InstantiateConfig} from '../options/config';
import {onTriggerEachHook} from '../public/hooks'
export function registerHook(list:Array<Function>, fn:Function):void {
list[0] = fn;
}
export function registerRouterHooks<T extends LifeCycleConfig>(cycleHooks:T, options:InstantiateConfig):T {
registerHook(cycleHooks.routerBeforeHooks, function(to:totalNextRoute, from: totalNextRoute, next:(rule?: navtoRule|false)=>void):void {
(options.routerBeforeEach as Function)(to, from, next);
})
registerHook(cycleHooks.routerAfterHooks, function(to:totalNextRoute, from: totalNextRoute):void {
(options.routerAfterEach as Function)(to, from);
})
registerHook(cycleHooks.routerErrorHooks, function(error:navErrorRule, router:Router):void {
(options.routerErrorEach as Function)(error, router);
})
return cycleHooks;
}
export function registerEachHooks(router:Router, hookType:proxyHookName, userGuard:guardHookRule) {
registerHook(router.lifeCycle[hookType], function(
to:totalNextRoute,
from: totalNextRoute,
next:(rule?: navtoRule|false)=>void,
router:Router,
auto:boolean,
):void {
if (auto) { // h5端 vue-router自动触发 非自己调用触发
onTriggerEachHook(to, from, router, hookToggle[hookType], next)
} else {
userGuard(to, from, next)
}
})
}

View File

@@ -1,109 +0,0 @@
import { Router, routesMapRule, RoutesRule, pageTypeRule} from '../options/base';
import {createRouteMap} from '../helpers/createRouteMap'
import {buildVueRoutes, buildVueRouter} from '../H5/buildRouter'
import {proxyEachHook} from '../H5/proxyHook'
import {registerLoddingPage} from '../app/appPatch';
import { proxyPageHook } from '../public/page';
import { forceGuardEach } from '../public/methods';
import { assertParentChild, voidFun } from './utils';
import { getEnterPath } from '../applets/appletPatch';
import { mpPlatformReg } from './config';
let registerRouter:boolean = false;
let onloadProxyOk:boolean = false;
const appletProxy:{
app:boolean;
page:string;
} = {
app: false,
page: ''
}
export function getMixins(Vue:any, router: Router):{
beforeCreate(this: any): void;
} | {
beforeCreate(): void;
} | {
onLaunch(): void;
} {
let platform = router.options.platform;
if (new RegExp(mpPlatformReg, 'g').test(platform)) {
platform = 'app-lets';
}
const toggleHooks = {
h5: {
beforeCreate(this: any): void {
if (this.$options.router) {
router.$route = this.$options.router; // 挂载vue-router到路由对象下
let vueRouteMap:RoutesRule[]|RoutesRule = [];
if (router.options.h5?.vueRouterDev) {
vueRouteMap = router.options.routes;
} else {
vueRouteMap = createRouteMap(router, this.$options.router.options.routes).finallyPathMap;
(router.routesMap as routesMapRule).vueRouteMap = vueRouteMap;
buildVueRoutes(router, vueRouteMap);
}
buildVueRouter(router, this.$options.router, vueRouteMap);
proxyEachHook(router, this.$options.router);
}
}
},
'app-plus': {
beforeCreate(this: any): void {
if (!registerRouter) {
registerRouter = true;
proxyPageHook(this, router, 'app');
registerLoddingPage(router);
}
}
},
'app-lets': {
beforeCreate(this: any): void {
// 保证这个函数不会被重写
const pluginMark = $npm_package_name;
voidFun(pluginMark);
let isProxy:boolean = true;
const pageType:pageTypeRule = this.$options.mpType;
if (onloadProxyOk) {
return
}
if (pageType === 'component') {
isProxy = assertParentChild(appletProxy['page'], this);
} else {
if (pageType === 'page') {
appletProxy[pageType] = getEnterPath(this, router);
router.enterPath = appletProxy[pageType]; // 我不确定在不同端是否都是同样的变现?可能有的为非绝对路径?
} else {
appletProxy[pageType] = true;
}
}
if (isProxy) {
proxyPageHook(this, router, pageType);
}
},
onLoad(this: any):void{
// 保证这个函数不会被重写否则必须在启动页写onLoad
const pluginMark = $npm_package_name;
voidFun(pluginMark);
if (!onloadProxyOk && assertParentChild(appletProxy['page'], this)) {
onloadProxyOk = true;
forceGuardEach(router);
}
}
}
};
return toggleHooks[(platform as 'h5'|'app-plus'|'app-lets')];
}
export function initMixins(Vue: any, router: Router) {
const routesMap = createRouteMap(router, router.options.routes);
router.routesMap = routesMap; // 挂载自身路由表到路由对象下
// Vue.util.defineReactive(router, '_Route', createRoute(router, 19970806))
Vue.mixin({
...getMixins(Vue, router)
});
}

View File

@@ -1,452 +0,0 @@
import {H5Config, InstantiateConfig} from '../options/config';
import {RoutesRule, routesMapRule, routesMapKeysRule, Router, totalNextRoute, objectAny, navErrorRule, NAVTYPE, navRoute, uniBackApiRule, uniBackRule} from '../options/base';
import {baseConfig} from '../helpers/config';
import {ERRORHOOK} from '../public/hooks'
import {warnLock} from '../helpers/warn'
import { createRoute, navjump } from '../public/methods';
const Regexp = require('path-to-regexp');
export function voidFun(...args:any):void{}
export function def(
defObject:objectAny,
key:string,
getValue:Function
) {
Object.defineProperty(defObject, key, {
get() {
return getValue();
}
})
}
export function timeOut(time:number):Promise<void> {
return new Promise(resolve => {
setTimeout(() => {
resolve();
}, time)
})
}
export function mergeConfig<T extends InstantiateConfig>(baseConfig: T, userConfig: T): T {
const config: {[key: string]: any} = Object.create(null);
const baseConfigKeys: Array<string> = Object.keys(baseConfig).concat(['resolveQuery', 'parseQuery']);
for (let i = 0; i < baseConfigKeys.length; i += 1) {
const key = baseConfigKeys[i];
if (userConfig[key] != null) {
if (userConfig[key].constructor === Object) {
config[key] = {
...baseConfig[key],
...userConfig[key]
};
} else if (key === 'routes') {
config[key] = [
...baseConfig[key],
...userConfig[key]
];
} else {
config[key] = userConfig[key];
}
} else {
config[key] = baseConfig[key];
}
}
return config as T;
}
export function notDeepClearNull<T>(object:T):T {
for (const key in object) {
if (object[key] == null) {
delete object[key];
}
}
return object;
}
export function getRoutePath(route: RoutesRule, router:Router): {
finallyPath: string | string[];
aliasPath: string;
path: string;
alias: string | string[] | undefined;
} {
let finallyPath = route.aliasPath || route.alias || route.path;
if (router.options.platform !== 'h5') {
finallyPath = route.path
}
return {
finallyPath,
aliasPath: route.aliasPath || route.path,
path: route.path,
alias: route.alias
}
}
export function assertNewOptions<T extends InstantiateConfig>(
options: T
): T | never {
const {platform, routes} = options;
if (platform == null) {
throw new Error(`你在实例化路由时必须传递 'platform'`);
}
if (routes == null || routes.length === 0) {
throw new Error(`你在实例化路由时必须传递 routes 为空,这是无意义的。`);
}
if (options.platform === 'h5') {
if (options.h5?.vueRouterDev) {
baseConfig.routes = [];
}
}
const mergeOptions = mergeConfig<T>(baseConfig as T, options);
return mergeOptions;
}
export function getWildcardRule(
router:Router,
msg?:navErrorRule
):RoutesRule|never {
const routesMap = (router.routesMap as routesMapRule);
const route = routesMap.finallyPathMap['*'];
if (route) { // 有写通配符
return route
}
if (msg) {
ERRORHOOK[0](msg, router);
}
throw new Error(`当前路由表匹配规则已全部匹配完成,未找到满足的匹配规则。你可以使用 '*' 通配符捕捉最后的异常`);
}
export function notRouteTo404(
router:Router,
toRoute:RoutesRule|{
redirect:any;
path:string
},
parseToRule:totalNextRoute,
navType:NAVTYPE
):RoutesRule|totalNextRoute|never {
if (toRoute.path !== '*') { // 不是通配符 正常匹配成功
return (toRoute as RoutesRule);
}
const redirect = toRoute.redirect;
if (typeof redirect === 'undefined') {
throw new Error(` * 通配符必须配合 redirect 使用。redirect: string | Location | Function`);
}
let newRoute = redirect;
if (typeof newRoute === 'function') {
newRoute = newRoute(parseToRule) as totalNextRoute;
}
const redirectRule = navjump(newRoute as totalNextRoute, router, navType, undefined, undefined, undefined, false);
return (redirectRule as totalNextRoute);
}
export function routesForMapRoute(
router: Router,
path: string,
mapArrayKey:Array<routesMapKeysRule>,
deepFind:boolean|undefined = false
):RoutesRule|never {
if (router.options.h5?.vueRouterDev) {
return {path}
}
// 【Fixe】 https://github.com/SilurianYang/uni-simple-router/issues/252
const startPath = path.split('?')[0];
let wildcard = '';
const routesMap = (router.routesMap as routesMapRule);
for (let i = 0; i < mapArrayKey.length; i++) {
const mapKey = mapArrayKey[i];
const mapList = routesMap[mapKey];
for (const [key, value] of Object.entries(mapList)) {
if (key === '*') {
if (wildcard === '') {
wildcard = '*'
}
continue;
}
const route:string|RoutesRule = value;
let rule:string = key;
if (getDataType<Array<string>|objectAny>(mapList) === '[object Array]') {
rule = (route as string);
}
const pathRule:RegExp = Regexp(rule);
const result = pathRule.exec(startPath);
if (result != null) {
if (getDataType<string|RoutesRule>(route) === '[object String]') {
return routesMap.finallyPathMap[(route as string)];
}
return (route as RoutesRule);
}
}
}
// 【Fixe】 https://github.com/SilurianYang/uni-simple-router/issues/302 2021-8-4 16:38:44
if (deepFind) {
return ({} as RoutesRule);
}
if (routesMap['aliasPathMap']) {
const results = routesForMapRoute(router, path, ['aliasPathMap'], true);
if (Object.keys(results).length > 0) {
return results;
}
}
if (wildcard !== '') {
return getWildcardRule(router);
}
throw new Error(`${path} 路径无法在路由表中找到!检查跳转路径及路由表`);
}
export function getDataType<T>(data:T):string {
return Object.prototype.toString.call(data)
}
export function copyData<T>(object:T): T {
return JSON.parse(JSON.stringify(object))
}
export function getUniCachePage<T extends objectAny>(pageIndex?:number):T|[] {
const pages:T = getCurrentPages();
if (pageIndex == null) {
return pages
}
if (pages.length === 0) {
return pages;
}
const page = pages.reverse()[pageIndex];
if (page == null) {
return []
}
return page;
}
export function urlToJson(url :string):{
path:string;
query:objectAny
} {
const query:objectAny = {};
const [path, params] = url.split('?');
if (params != null) {
const parr = params.split('&');
for (const i of parr) {
const arr = i.split('=');
query[arr[0]] = arr[1];
}
}
return {
path,
query
}
}
export function forMatNextToFrom<T extends totalNextRoute>(
router:Router,
to:T,
from:T
):{
matTo:T;
matFrom: T;
} {
let [matTo, matFrom] = [to, from];
if (router.options.platform === 'h5') {
const {vueNext, vueRouterDev} = (router.options.h5 as H5Config);
if (!vueNext && !vueRouterDev) {
matTo = createRoute(router, undefined, matTo) as T;
matFrom = createRoute(router, undefined, matFrom) as T;
}
} else {
matTo = createRoute(router, undefined, deepClone<T>(matTo)) as T;
matFrom = createRoute(router, undefined, deepClone<T>(matFrom)) as T;
}
return {
matTo: matTo,
matFrom: matFrom
}
}
export function paramsToQuery(
router:Router,
toRule:totalNextRoute|string
):totalNextRoute|string {
if (router.options.platform === 'h5' && !router.options.h5?.paramsToQuery) {
return toRule;
}
if (getDataType<totalNextRoute|string>(toRule) === '[object Object]') {
const {name, params, ...moreToRule} = (toRule as totalNextRoute);
let paramsQuery = params;
if (router.options.platform !== 'h5' && paramsQuery == null) {
paramsQuery = {};
}
if (name != null && paramsQuery != null) {
let route = (router.routesMap as routesMapRule).nameMap[name];
if (route == null) {
route = getWildcardRule(router, { type: 2, msg: `命名路由为:${name} 的路由,无法在路由表中找到!`, toRule});
}
const {finallyPath} = getRoutePath(route, router);
if (finallyPath.includes(':')) { // 动态路由无法使用 paramsToQuery
ERRORHOOK[0]({ type: 2, msg: `动态路由:${finallyPath} 无法使用 paramsToQuery`, toRule}, router);
} else {
return {
...moreToRule,
path: finallyPath as string,
query: paramsQuery
}
}
}
}
return toRule
}
export function assertDeepObject(object:objectAny):boolean {
let arrMark = null;
try {
arrMark = JSON.stringify(object).match(/\{|\[|\}|\]/g);
} catch (error) {
warnLock(`传递的参数解析对象失败。` + error)
}
if (arrMark == null) {
return false
}
if (arrMark.length > 3) {
return true;
}
return false
}
export function baseClone<
T extends {
[key:string]:any
}, K extends keyof T
>(
source:T,
target:Array<any>|objectAny
):Array<any>|objectAny|null {
// 【Fixe】 https://github.com/SilurianYang/uni-simple-router/issues/292
// 小程序会将null解析为字符串 undefined 建议不要在参数中传递 null
if (source == null) {
target = source;
} else {
for (const key of Object.keys(source)) {
const dyKey = key as T[K];
if (source[key] === source) continue
if (typeof source[key] === 'object') {
target[dyKey] = getDataType<T>(source[key]) === '[object Array]' ? ([] as Array<any>) : ({} as objectAny)
target[dyKey] = baseClone(source[key], target[dyKey])
} else {
target[dyKey] = source[key]
}
}
}
return target;
}
export function deepClone<T>(source:T):T {
const __ob__ = getDataType<T>(source) === '[object Array]' ? ([] as Array<any>) : ({} as objectAny);
baseClone(source, __ob__)
return __ob__ as T
}
export function lockDetectWarn(
router:Router,
to:string|number|totalNextRoute|navRoute,
navType:NAVTYPE,
next:Function,
uniActualData:uniBackApiRule|uniBackRule|undefined = {},
passiveType?:'beforeHooks'| 'afterHooks'
):void{
if (passiveType === 'afterHooks') {
next();
} else {
const {detectBeforeLock} = router.options;
detectBeforeLock && detectBeforeLock(router, to, navType);
if (router.$lockStatus) {
(router.options.routerErrorEach as (error: navErrorRule, router:Router) => void)({
type: 2,
msg: '当前页面正在处于跳转状态,请稍后再进行跳转....',
NAVTYPE: navType,
uniActualData
}, router);
} else {
next();
}
}
}
export function assertParentChild(
parentPath:string,
vueVim:any,
):boolean {
while (vueVim.$parent != null) {
const mpPage = vueVim.$parent.$mp;
if (mpPage.page && mpPage.page.is === parentPath) {
return true;
}
vueVim = vueVim.$parent;
}
try {
if (vueVim.$mp.page.is === parentPath || vueVim.$mp.page.route === parentPath) {
return true
}
} catch (error) {
return false
}
return false
}
export function resolveAbsolutePath(
path:string,
router:Router
):string|never {
const reg = /^\/?([^\?\s]+)(\?.+)?$/;
const trimPath = path.trim();
if (!reg.test(trimPath)) {
throw new Error(`${path}】 路径错误,请提供完整的路径(10001)。`);
}
const paramsArray = trimPath.match(reg);
if (paramsArray == null) {
throw new Error(`${path}】 路径错误,请提供完整的路径(10002)。`);
}
const query:string = paramsArray[2] || '';
if (/^\.\/[^\.]+/.test(trimPath)) { // 当前路径下
const navPath:string = router.currentRoute.path + path;
return navPath.replace(/[^\/]+\.\//, '');
}
const relative = paramsArray[1].replace(/\//g, `\\/`).replace(/\.\./g, `[^\\/]+`).replace(/\./g, '\\.');
const relativeReg = new RegExp(`^\\/${relative}$`);
const route = router.options.routes.filter(it => relativeReg.test(it.path));
if (route.length !== 1) {
throw new Error(`${path}】 路径错误,尝试转成绝对路径失败,请手动转成绝对路径(10003)。`);
}
return route[0].path + query;
}
export function deepDecodeQuery(
query:objectAny
):objectAny {
const formatQuery:objectAny = getDataType<objectAny>(query) === '[object Array]' ? [] : {};
const keys = Object.keys(query);
for (let i = 0; i < keys.length; i++) {
const key = keys[i];
const it = query[key];
if (typeof it === 'string') {
try {
let json = JSON.parse(decodeURIComponent(it));
if (typeof json !== 'object') {
json = it;
}
formatQuery[key] = json;
} catch (error) {
try {
formatQuery[key] = decodeURIComponent(it)
} catch (error) {
formatQuery[key] = it
}
}
} else if (typeof it === 'object') {
const childQuery = deepDecodeQuery(it);
formatQuery[key] = childQuery
} else {
formatQuery[key] = it
}
}
return formatQuery
}

View File

@@ -1,37 +0,0 @@
import {debuggerConfig, debuggerArrayConfig} from '../options/config'
import {Router} from '../options/base'
type callType='error'|'warn'|'log';
export function isLog(type:callType, dev:debuggerConfig, errText:any, enforce:boolean = false):boolean {
if (!enforce) {
const isObject = dev.toString() === '[object Object]';
if (dev === false) {
return false
} else if (isObject) {
if ((dev as debuggerArrayConfig)[type] === false) {
return false;
}
}
}
console[type](errText);
return true;
}
export function err(errText:any, router:Router, enforce?:boolean):void {
const dev = (router.options.debugger as debuggerConfig);
isLog('error', dev, errText, enforce);
}
export function warn(errText:any, router:Router, enforce?:boolean):void {
const dev = (router.options.debugger as debuggerConfig);
isLog('warn', dev, errText, enforce);
}
export function log(errText:any, router:Router, enforce?:boolean):void {
const dev = (router.options.debugger as debuggerConfig);
isLog('log', dev, errText, enforce);
}
export function warnLock(errText:any):void {
console.warn(errText);
}

View File

@@ -1,11 +0,0 @@
export * from './options/base'
export * from './options/config'
export {
runtimeQuit
} from './app/appPatch'
export {
RouterMount,
createRouter
} from './public/router'

View File

@@ -1,245 +0,0 @@
import {InstantiateConfig, LifeCycleConfig} from '../options/config';
export enum hookToggle{
'beforeHooks'='beforeEach',
'afterHooks'='afterEach',
'enterHooks'='beforeEnter'
}
export enum navtypeToggle{
'push'='navigateTo',
'replace'='redirectTo',
'replaceAll'='reLaunch',
'pushTab'='switchTab',
'back'='navigateBack'
}
export enum rewriteMethodToggle{
'navigateTo'='push',
'navigate'='push',
'redirectTo'='replace',
'reLaunch'='replaceAll',
'switchTab'='pushTab',
'navigateBack'='back',
}
export type proxyDepsRule={
resetIndex:Array<number>;
hooks: {
[key: number]:{
proxyHook:()=>void;
callHook:(enterPath:string)=>void;
resetHook: ()=>void
}
};
options: {[key: number]: Array<any>;};
};
export type backTypeRule='backbutton'|'navigateBack'
export type pageTypeRule='app'|'page'|'component';
export type vueHookNameRule='onLaunch'|'onShow'|'onHide'|'onError'|'onInit'|'onLoad'|'onReady'|'onUnload'|'onResize'|'created'|'beforeMount'|'mounted'|'beforeDestroy'|'destroyed'
export type reNavMethodRule='navigateTo'|'redirectTo'|'reLaunch'|'switchTab';
export type reNotNavMethodRule='navigateBack';
export type reloadNavRule=totalNextRoute | false | undefined|string;
export type hookListRule=Array<(router:Router, to:totalNextRoute, from: totalNextRoute, toRoute:RoutesRule,next:Function)=>void>
export type guardHookRule=(to: totalNextRoute, from: totalNextRoute, next:(rule?: navtoRule|false)=>void)=>void;
export type navRuleStatus= 0|1|2|3; //0: next(false) 1:next(unknownType) 2:加锁状态,禁止跳转 3:在获取页面栈的时候页面栈不够level获取
export type proxyHookName='beforeHooks'|'afterHooks';
export type navMethodRule = Promise<void | undefined | navRuleStatus>;
export type objectAny={[propName: string]: any;};
export type NAVTYPE = 'push' | 'replace' | 'replaceAll' | 'pushTab'|'back';
export type startAnimationType =
| 'slide-in-right'
| 'slide-in-left'
| 'slide-in-top'
| 'slide-in-bottom'
| 'pop-in'
| 'fade-in'
| 'zoom-out'
| 'zoom-fade-out'
| 'none';
export type endAnimationType =
| 'slide-out-right'
| 'slide-out-left'
| 'slide-out-top'
| 'slide-out-bottom'
| 'pop-out'
| 'fade-out'
| 'zoom-in'
| 'zoom-fade-in'
| 'none';
export type vueOptionRule = {
[propName in vueHookNameRule]: Array<Function> | undefined;
};
// 跳转api时传递的跳转规则
export interface navtoRule {
NAVTYPE?: NAVTYPE; // 跳转类型 v1.1.0+
path?: string; // 跳转路径 绝对路径
name?: string | undefined; // 跳转路径名称
query?: objectAny; // 跳转使用path时 query包含需要传递的参数
params?: objectAny; // 跳转使用name时 params包含需要传递的参数
animationType?: startAnimationType|endAnimationType;
animationDuration?: number;
events?: objectAny;
success?: Function;
fail?: Function;
complete?: Function;
}
// h5 next管道函数中传递的from及to对象
export interface h5NextRule {
fullPath?: string | undefined;
hash?: string | undefined;
matched?: Array<object>;
meta?: object;
name?: undefined | string;
type?: undefined | string;
}
export interface totalNextRoute extends h5NextRule, navtoRule {
path:string;
delta?:number;
[propName: string]: any;
}
export interface navRoute extends h5NextRule, navtoRule {
}
// 开始切换窗口动画 app端可用
export interface startAnimationRule {
animationType?: startAnimationType; // 窗口关闭的动画效果
animationDuration?: number; // 窗口关闭动画的持续时间
}
// 关闭窗口时的动画 app端可用
export interface endAnimationRule {
animationType?: endAnimationType; // 窗口关闭的动画效果
animationDuration?: number; // 窗口关闭动画的持续时间
}
export interface hookObjectRule {
options:Array<any>;
hook:Function;
}
// 执行路由跳转失败或者 next(false) 时走的规则
export interface navErrorRule {
type: navRuleStatus;
msg: string;
to?:totalNextRoute;
from?:totalNextRoute;
nextTo?:any;
[propName:string]:any;
}
// uni原生api跳转时的规则
export interface uniNavApiRule {
url: string;
openType?:'appLaunch',
query?:objectAny;
path?:string;
delta?:number;
detail?:{[propName:string]:any};
animationType?:startAnimationType;
animationDuration?:number;
events?:{[propName:string]:any};
success?:Function;
fail?:Function;
complete?:Function;
animation?:{
animationType?:startAnimationType;
animationDuration?:number;
}
}
export interface originMixins extends uniNavApiRule{
BACKTYPE:''|backTypeRule
}
// uni-app 原始返回api 回调参数
export interface uniBackRule{
from:backTypeRule;
}
export interface uniBackApiRule{
delta?: number;
animationDuration?: number;
animationType?:endAnimationType;
}
export type routesMapKeysRule=
'finallyPathList'|
'finallyPathMap'|
'aliasPathMap'|
'pathMap'|
'nameMap'|
'vueRouteMap';
export interface routesMapRule{
[key:string]:any;
finallyPathList: Array<string>;
finallyPathMap:RoutesRule;
aliasPathMap: RoutesRule;
pathMap: RoutesRule;
nameMap:RoutesRule,
vueRouteMap:objectAny
}
export interface routeRule{
name:string|undefined;
meta:objectAny;
path:string;
query:objectAny;
params:objectAny;
fullPath:string;
NAVTYPE:NAVTYPE|'';
BACKTYPE?:backTypeRule|''; // v2.0.5 +
[propName: string]: any;
}
export interface RoutesRule {
path: string; // pages.json中的path 必须加上 '/' 开头
component?: object; // H5端可用
name?: string; // 命名路由
components?: object; // 命名视图组件H5端可用
redirect?: string | Function; // H5端可用
props?: boolean | object | Function; // H5端可用
aliasPath?: string; // h5端 设置一个别名路径来替换 uni-app的默认路径
alias?: string | Array<string>; // H5端可用
children?: Array<RoutesRule>; // 嵌套路由H5端可用
beforeEnter?:guardHookRule; // 路由元守卫
meta?: any; // 其他格外参数
[propName: string]: any;
}
export interface Router {
[key:string]:any;
readonly lifeCycle: LifeCycleConfig;
readonly options: InstantiateConfig;
$lockStatus:boolean;
$route: object | null;
enterPath:string;
Vue:any;
appMain:{
NAVTYPE:reNavMethodRule|reNotNavMethodRule,
path:string
}|{};
proxyHookDeps: proxyDepsRule;
routesMap: routesMapRule|{};
mount: Array<{app: any; el: string}>;
install(Vue: any): void;
push(to: totalNextRoute|navRoute | string,from?:totalNextRoute): void; // 动态的导航到一个新 URL 保留浏览历史
replace(to: totalNextRoute|navRoute | string,from?:totalNextRoute): void; // 动态的导航到一个新 URL 关闭当前页面,跳转到的某个页面。
replaceAll(to: totalNextRoute|navRoute | string,from?:totalNextRoute): void; // 动态的导航到一个新 URL 关闭所有页面,打开到应用内的某个页面
pushTab(to: totalNextRoute|navRoute | string,from?:totalNextRoute): void; // 动态的导航到一个新 url 关闭所有页面打开到应用内的某个tab
back(level:number|undefined,origin?:uniBackRule|uniBackApiRule):void;
forceGuardEach(navType:NAVTYPE|undefined,forceNav:boolean):void; //强制触发当前守卫
beforeEach(userGuard:guardHookRule): void; // 添加全局前置路由守卫
afterEach(userGuard:(to: totalNextRoute, from: totalNextRoute)=>void): void; // 添加全局后置路由守卫
}
export type PromiseResolve=(value?: void | PromiseLike<void> | undefined) => void;
// @ts-ignore
declare module 'vue/types/vue' {
interface Vue {
$Router: Router;
$Route: routeRule;
}
}

View File

@@ -1,57 +0,0 @@
import {startAnimationRule, hookListRule, RoutesRule, navtoRule, navErrorRule, Router, objectAny, NAVTYPE, totalNextRoute, navRoute} from './base';
export type debuggerConfig=boolean|debuggerArrayConfig;
export type platformRule='h5'|'app-plus'|'app-lets'|'mp-weixin'|'mp-baidu'|'mp-alipay'|'mp-toutiao'|'mp-qq'|'mp-360';
export interface H5Config {
paramsToQuery?: boolean; // h5端上通过params传参时规则是vue-router 刷新会丢失 开启此开关将变成?连接的方式
vueRouterDev?: boolean; // 完全使用采用vue-router的开发模式
vueNext?: boolean; // 在next管道函数中是否获取vueRouter next的原本参数
mode?: string;
base?: string;
linkActiveClass?: string;
linkExactActiveClass?: string;
scrollBehavior?: Function;
fallback?: boolean;
}
export interface AppConfig {
registerLoadingPage?:boolean; // 是否注册过渡加载页 +v2.0.6
loadingPageStyle?: () => object; // 当前等待页面的样式 必须返回一个json
loadingPageHook?: (view:any)=>void; // 刚刚打开页面处于等待状态,会触发此函数
launchedHook?:()=>void; // 首次启动app完成
animation?: startAnimationRule; // 页面切换动画
}
export interface appletConfig {
animationDuration?:number; // 页面切换时间,有助于路由锁精准解锁
}
export interface debuggerArrayConfig{
error?:boolean;
warn?:boolean;
log?:boolean;
}
export interface InstantiateConfig {
[key:string]:any;
keepUniOriginNav?:boolean; // 重写uni-app的跳转方法关闭后使用uni-app的原始方法跳转和插件api跳转等同
platform:platformRule; // 当前运行平台
h5?: H5Config;
APP?: AppConfig;
applet?:appletConfig;
debugger?: debuggerConfig; // 是否处于开发阶段 设置为true则打印日志
routerBeforeEach?: (to:navtoRule, from:navtoRule, next:(rule?: navtoRule|false)=>void) => void; // router 前置路由函数 每次触发跳转前先会触发此函数
routerAfterEach?: (to:navtoRule, from:navtoRule, next?: Function) => void; // router 后置路由函数 每次触发跳转后会触发此函数
routerErrorEach?: (error: navErrorRule, router:Router) => void;
resolveQuery?:(jsonQuery:objectAny)=>objectAny; // 跳转之前把参数传递给此函数、返回最终的数据!有此函数不走默认方法
parseQuery?:(jsonQuery:objectAny)=>objectAny; // 读取值之前把参数传递给此函数,返回最终的数据!有此函数不走默认方法
detectBeforeLock?:(router:Router, to:string|number|totalNextRoute|navRoute, navType:NAVTYPE)=>void; // 在检测路由锁之前触发的函数
routes: RoutesRule[];
}
export interface LifeCycleConfig{
beforeHooks: hookListRule;
afterHooks: hookListRule;
routerBeforeHooks: hookListRule;
routerAfterHooks: hookListRule;
routerErrorHooks: Array<(error:navErrorRule, router:Router)=>void>;
}

View File

@@ -1,177 +0,0 @@
import {
Router,
hookListRule,
navtoRule,
reloadNavRule,
totalNextRoute,
hookToggle,
NAVTYPE,
navErrorRule,
objectAny
} from '../options/base';
import {
routesForMapRoute,
getDataType,
forMatNextToFrom,
getUniCachePage,
voidFun
} from '../helpers/utils'
import { navjump } from './methods';
import { proxyH5Mount } from '../H5/proxyHook';
import { tabIndexSelect } from '../app/appPatch';
export const ERRORHOOK:Array<(error:navErrorRule, router:Router)=>void> = [
(error, router) => router.lifeCycle.routerErrorHooks[0](error, router)
]
export const HOOKLIST: hookListRule = [
(router, to, from, toRoute, next) => callHook(router.lifeCycle.routerBeforeHooks[0], to, from, router, next),
(router, to, from, toRoute, next) => callBeforeRouteLeave(router, to, from, next),
(router, to, from, toRoute, next) => callHook(router.lifeCycle.beforeHooks[0], to, from, router, next),
(router, to, from, toRoute, next) => callHook(toRoute.beforeEnter, to, from, router, next),
(router, to, from, toRoute, next) => callHook(router.lifeCycle.afterHooks[0], to, from, router, next, false),
(router, to, from, toRoute, next) => {
router.$lockStatus = false;
if (router.options.platform === 'h5') {
proxyH5Mount(router);
}
return callHook(router.lifeCycle.routerAfterHooks[0], to, from, router, next, false)
}
];
export function callBeforeRouteLeave(
router:Router,
to:totalNextRoute,
from:totalNextRoute,
resolve:Function
):void {
const page = getUniCachePage<objectAny>(0);
let beforeRouteLeave;
if (Object.keys(page).length > 0) {
let leaveHooks:Array<Function>|undefined|Function;
if (router.options.platform === 'h5') {
leaveHooks = (page as objectAny).$options.beforeRouteLeave;
} else {
if ((page as objectAny).$vm != null) {
leaveHooks = (page as objectAny).$vm.$options.beforeRouteLeave;
}
}
switch (getDataType<Array<Function>>((leaveHooks as Array<Function>))) {
case '[object Array]': // h5端表现
beforeRouteLeave = (leaveHooks as Array<Function>)[0];
beforeRouteLeave = beforeRouteLeave.bind(page)
break;
case '[object Function]': // 目前app端表现
beforeRouteLeave = (leaveHooks as Function).bind((page as objectAny).$vm);
break
}
}
return callHook(beforeRouteLeave, to, from, router, resolve);
}
export function callHook(
hook:Function|undefined,
to:totalNextRoute,
from: totalNextRoute,
router:Router,
resolve:Function,
hookAwait:boolean|undefined = true
):void {
if (hook != null && hook instanceof Function) {
if (hookAwait === true) {
hook(to, from, resolve, router, false);
} else {
hook(to, from, () => {}, router, false);
resolve();
}
} else {
resolve();
}
}
export function onTriggerEachHook(
to:totalNextRoute,
from: totalNextRoute,
router:Router,
hookType:hookToggle,
next:(rule?: navtoRule|false)=>void,
):void {
let callHookList:hookListRule = [];
switch (hookType) {
case 'beforeEach':
callHookList = HOOKLIST.slice(0, 3);
break;
case 'afterEach':
callHookList = HOOKLIST.slice(4);
break
case 'beforeEnter':
callHookList = HOOKLIST.slice(3, 4);
break;
}
transitionTo(router, to, from, 'push', callHookList, next);
}
export function transitionTo(
router:Router,
to:totalNextRoute,
from: totalNextRoute,
navType:NAVTYPE,
callHookList:hookListRule,
hookCB:Function
) :void{
const {matTo, matFrom} = forMatNextToFrom<totalNextRoute>(router, to, from);
if (router.options.platform === 'h5') {
loopCallHook(callHookList, 0, hookCB, router, matTo, matFrom, navType);
} else {
loopCallHook(callHookList.slice(0, 4), 0, () => {
hookCB(() => { // 非H5端等他跳转完才触发最后两个生命周期
loopCallHook(callHookList.slice(4), 0, voidFun, router, matTo, matFrom, navType);
});
}, router, matTo, matFrom, navType);
}
}
export function loopCallHook(
hooks:hookListRule,
index:number,
next:Function,
router:Router,
matTo:totalNextRoute,
matFrom: totalNextRoute,
navType:NAVTYPE,
): void|Function {
const toRoute = routesForMapRoute(router, matTo.path, ['finallyPathMap', 'pathMap']);
if (hooks.length - 1 < index) {
return next();
}
const hook = hooks[index];
const errHook = ERRORHOOK[0];
hook(router, matTo, matFrom, toRoute, (nextTo:reloadNavRule) => {
if (router.options.platform === 'app-plus') {
if (nextTo === false || (typeof nextTo === 'string' || typeof nextTo === 'object')) {
tabIndexSelect(matTo, matFrom);
}
}
if (nextTo === false) {
if (router.options.platform === 'h5') {
next(false);
}
errHook({ type: 0, msg: '管道函数传递 false 导航被终止!', matTo, matFrom, nextTo }, router)
} else if (typeof nextTo === 'string' || typeof nextTo === 'object') {
let newNavType = navType;
let newNextTo = nextTo;
if (typeof nextTo === 'object') {
const {NAVTYPE: type, ...moreTo} = nextTo;
newNextTo = moreTo;
if (type != null) {
newNavType = type;
}
}
navjump(newNextTo, router, newNavType, {from: matFrom, next})
} else if (nextTo == null) {
index++;
loopCallHook(hooks, index, next, router, matTo, matFrom, navType)
} else {
errHook({ type: 1, msg: '管道函数传递未知类型,无法被识别。导航被终止!', matTo, matFrom, nextTo }, router)
}
});
}

View File

@@ -1,258 +0,0 @@
import {
NAVTYPE,
Router,
totalNextRoute,
objectAny,
routeRule,
reNavMethodRule,
rewriteMethodToggle,
navtypeToggle,
navErrorRule,
uniBackApiRule,
uniBackRule,
navRoute
} from '../options/base'
import {
queryPageToMap,
resolveQuery,
parseQuery
} from './query'
import {
voidFun,
paramsToQuery,
getUniCachePage,
routesForMapRoute,
copyData,
lockDetectWarn,
getDataType,
notRouteTo404,
deepDecodeQuery
} from '../helpers/utils'
import { transitionTo } from './hooks';
import {createFullPath, createToFrom} from '../public/page'
import {HOOKLIST} from './hooks'
export function lockNavjump(
to:string|totalNextRoute|navRoute,
router:Router,
navType:NAVTYPE,
forceNav?:boolean,
animation?:uniBackApiRule|uniBackRule
):void{
lockDetectWarn(router, to, navType, () => {
if (router.options.platform !== 'h5') {
router.$lockStatus = true;
}
navjump(to as totalNextRoute, router, navType, undefined, forceNav, animation);
}, animation);
}
export function navjump(
to:string|totalNextRoute,
router:Router,
navType:NAVTYPE,
nextCall?:{
from:totalNextRoute;
next:Function;
},
forceNav?:boolean,
animation?:uniBackApiRule|uniBackRule,
callHook:boolean|undefined = true
) :void|never|totalNextRoute {
if (navType === 'back') {
let level:number = 1;
if (typeof to === 'string') {
level = +to;
} else {
level = to.delta || 1;
}
if (router.options.platform === 'h5') {
(router.$route as any).go(-level);
// Fixe https://github.com/SilurianYang/uni-simple-router/issues/266 2021年6月3日11:14:38
// @ts-ignore
const success = (animation || {success: voidFun}).success || voidFun;
// @ts-ignore
const complete = (animation || {complete: voidFun}).complete || voidFun;
success({errMsg: 'navigateBack:ok'});
complete({errMsg: 'navigateBack:ok'});
return;
} else {
to = backOptionsBuild(router, level, animation);
}
}
const {rule} = queryPageToMap(to, router);
rule.type = navtypeToggle[navType];
const toRule = paramsToQuery(router, rule);
let parseToRule = resolveQuery(toRule as totalNextRoute, router);
if (router.options.platform === 'h5') {
if (navType !== 'push') {
navType = 'replace';
}
if (nextCall != null) { // next 管道函数拦截时 直接next即可
nextCall.next({
replace: navType !== 'push',
...parseToRule
})
} else {
// Fixe https://github.com/SilurianYang/uni-simple-router/issues/240 2021年3月7日14:45:36
if (navType === 'push' && Reflect.has(parseToRule, 'events')) {
if (Reflect.has(parseToRule, 'name')) {
throw new Error(`在h5端上使用 'push'、'navigateTo' 跳转时,如果包含 events 不允许使用 name 跳转,因为 name 实现了动态路由。请更换为 path 或者 url 跳转!`);
} else {
uni['navigateTo'](parseToRule, true, voidFun, forceNav);
}
} else {
(router.$route as any)[navType](parseToRule, (parseToRule as totalNextRoute).success || voidFun, (parseToRule as totalNextRoute).fail || voidFun)
}
}
} else {
let from:totalNextRoute = {path: ''};
if (nextCall == null) {
let toRoute = routesForMapRoute(router, parseToRule.path, ['finallyPathMap', 'pathMap']);
toRoute = notRouteTo404(router, toRoute, parseToRule, navType);
parseToRule = { ...toRoute, ...{params: {}}, ...parseToRule, ...{path: toRoute.path} }
from = createToFrom(parseToRule, router);
} else {
from = nextCall.from;
}
createFullPath(parseToRule, from);
if (callHook === false) {
return parseToRule;
}
transitionTo(router, parseToRule, from, navType, HOOKLIST, function(
callOkCb:Function
):void {
uni[navtypeToggle[navType]](parseToRule, true, callOkCb, forceNav);
})
}
}
export function backOptionsBuild(
router:Router,
level:number,
animation:uniBackApiRule|uniBackRule|undefined = {},
):totalNextRoute {
const toRule = createRoute(router, level, undefined, {NAVTYPE: 'back', ...animation});
const navjumpRule:totalNextRoute = {
...animation,
path: toRule.path,
query: toRule.query,
delta: level
}
if (getDataType<any>(animation) === '[object Object]') {
const {animationDuration, animationType} = (animation as uniBackApiRule)
if (animationDuration != null) {
navjumpRule.animationDuration = animationDuration;
}
if (animationType != null) {
navjumpRule.animationType = animationType;
}
const {from} = (animation as uniBackRule)
if (from != null) {
navjumpRule.BACKTYPE = from;
}
}
return navjumpRule;
}
export function forceGuardEach(
router:Router,
navType:NAVTYPE|undefined = 'replaceAll',
forceNav:undefined|boolean = false
):void|never {
if (router.options.platform === 'h5') {
throw new Error(`在h5端上使用forceGuardEach 是无意义的,目前 forceGuardEach 仅支持在非h5端上使用`);
}
const currentPage = getUniCachePage<objectAny>(0);
if (Object.keys(currentPage).length === 0) {
(router.options.routerErrorEach as (error: navErrorRule, router:Router) => void)({
type: 3,
NAVTYPE: navType,
uniActualData: {},
level: 0,
msg: `不存在的页面栈,请确保有足够的页面可用,当前 level:0`
}, router);
}
const {route, options} = currentPage as objectAny;
lockNavjump({
path: `/${route}`,
query: deepDecodeQuery(options || {})
}, router, navType, forceNav);
}
export function createRoute(
router:Router,
level:number|undefined = 0,
orignRule?:totalNextRoute,
uniActualData:objectAny|undefined = {},
):routeRule|never {
const route:routeRule = {
name: '',
meta: {},
path: '',
fullPath: '',
NAVTYPE: '',
query: {},
params: {},
BACKTYPE: (orignRule || {BACKTYPE: ''}).BACKTYPE || '' // v2.0.5 +
};
if (level === 19970806) { // 首次构建响应式 页面不存在 直接返回
return route
}
if (router.options.platform === 'h5') {
let vueRoute:totalNextRoute = {path: ''};
if (orignRule != null) {
vueRoute = orignRule;
} else {
vueRoute = (router.$route as objectAny).currentRoute;
}
const matRouteParams = copyData(vueRoute.params as objectAny);
delete matRouteParams.__id__;
const toQuery = parseQuery({...matRouteParams, ...copyData(vueRoute.query as objectAny)}, router);
vueRoute = {...vueRoute, query: toQuery}
route.path = vueRoute.path;
route.fullPath = vueRoute.fullPath || '';
route.query = deepDecodeQuery(vueRoute.query || {});
route.NAVTYPE = rewriteMethodToggle[vueRoute.type as reNavMethodRule || 'reLaunch'];
} else {
let appPage:objectAny = {};
if (orignRule != null) {
appPage = {...orignRule, openType: orignRule.type};
} else {
const page = getUniCachePage<objectAny>(level);
if (Object.keys(page).length === 0) {
const {NAVTYPE: _NAVTYPE, ..._args} = uniActualData;
const errorMsg:string = `不存在的页面栈,请确保有足够的页面可用,当前 level:${level}`;
(router.options.routerErrorEach as (error: navErrorRule, router:Router) => void)({
type: 3,
msg: errorMsg,
NAVTYPE: _NAVTYPE,
level,
uniActualData: _args
}, router);
throw new Error(errorMsg);
}
// Fixes: https://github.com/SilurianYang/uni-simple-router/issues/196
const pageOptions:objectAny = (page as objectAny).options || {};
appPage = {
...(page as objectAny).$page || {},
query: deepDecodeQuery(pageOptions),
fullPath: decodeURIComponent(((page as objectAny).$page || {}).fullPath || '/' + (page as objectAny).route)
}
if (router.options.platform !== 'app-plus') {
appPage.path = `/${(page as objectAny).route}`
}
}
const openType:reNavMethodRule|'navigateBack' = appPage.openType;
route.query = appPage.query;
route.path = appPage.path;
route.fullPath = appPage.fullPath;
route.NAVTYPE = rewriteMethodToggle[openType || 'reLaunch'];
}
const tableRoute = routesForMapRoute(router, route.path, ['finallyPathMap', 'pathMap'])
const perfectRoute = { ...route, ...tableRoute};
perfectRoute.query = parseQuery(perfectRoute.query, router);
return perfectRoute;
}

View File

@@ -1,103 +0,0 @@
import { proxyHookName } from '../helpers/config';
import { getDataType, getUniCachePage, deepClone} from '../helpers/utils';
import { objectAny, pageTypeRule, Router, totalNextRoute, vueOptionRule } from '../options/base';
import {createRoute} from './methods'
import { stringifyQuery } from './query';
export function createToFrom(
to:totalNextRoute,
router:Router,
):totalNextRoute {
let fromRoute:totalNextRoute = {path: ''};
const page = getUniCachePage<Array<any>|objectAny>(0);
if (getDataType<Array<any>|objectAny>(page) === '[object Array]') {
fromRoute = deepClone<totalNextRoute>(to)
} else {
fromRoute = createRoute(router) as totalNextRoute;
}
return fromRoute;
}
export function createFullPath(
to:totalNextRoute,
from:totalNextRoute
):void{
if (to.fullPath == null) {
const strQuery = stringifyQuery(to.query as objectAny);
to.fullPath = to.path + strQuery;
}
if (from.fullPath == null) {
const strQuery = stringifyQuery(from.query as objectAny);
from.fullPath = from.path + strQuery;
}
}
export function proxyPageHook(
vueVim:any,
router:Router,
pageType:pageTypeRule
):void {
const hookDeps = router.proxyHookDeps;
const pageHook:vueOptionRule = vueVim.$options;
for (let i = 0; i < proxyHookName.length; i++) {
const hookName = proxyHookName[i];
const hookList = pageHook[hookName];
if (hookList) {
for (let k = 0; k < hookList.length; k++) {
const originHook = hookList[k];
if (originHook.toString().includes($npm_package_name)) {
continue
}
const resetIndex = Object.keys(hookDeps.hooks).length + 1
const proxyHook = (...args:Array<any>):void => {
hookDeps.resetIndex.push(resetIndex);
hookDeps.options[resetIndex] = args;
}
const [resetHook] = hookList.splice(k, 1, proxyHook);
hookDeps.hooks[resetIndex] = {
proxyHook,
callHook: (enterPath:string) :void => {
if (router.enterPath.replace(/^\//, '') !== enterPath.replace(/^\//, '') && pageType !== 'app') {
return;
}
const options = hookDeps.options[resetIndex];
resetHook.apply(vueVim, options);
},
resetHook: () :void => {
hookList.splice(k, 1, resetHook)
}
};
}
}
}
}
export function resetAndCallPageHook(
router:Router,
enterPath:string,
reset:boolean|undefined = true
):void{
// Fixe: https://github.com/SilurianYang/uni-simple-router/issues/206
const pathInfo = enterPath.trim().match(/^(\/?[^\?\s]+)(\?[\s\S]*$)?$/);
if (pathInfo == null) {
throw new Error(`还原hook失败。请检查 【${enterPath}】 路径是否正确。`);
}
enterPath = pathInfo[1];
const proxyHookDeps = router.proxyHookDeps;
const resetHooksArray = proxyHookDeps.resetIndex
for (let i = 0; i < resetHooksArray.length; i++) {
const index = resetHooksArray[i];
const {callHook} = proxyHookDeps.hooks[index];
callHook(enterPath);
}
if (reset) {
resetPageHook(router);
}
}
export function resetPageHook(
router:Router
) {
const proxyHookDeps = router.proxyHookDeps;
for (const [, {resetHook}] of Object.entries(proxyHookDeps.hooks)) {
resetHook();
}
}

View File

@@ -1,200 +0,0 @@
import {
objectAny,
Router,
routesMapRule,
RoutesRule,
totalNextRoute
} from '../options/base';
import {
getDataType,
urlToJson,
routesForMapRoute,
getRoutePath,
assertDeepObject,
copyData,
getWildcardRule,
deepDecodeQuery
} from '../helpers/utils'
import {ERRORHOOK} from './hooks'
import {warn} from '../helpers/warn'
const encodeReserveRE = /[!'()*]/g
const encodeReserveReplacer = (c:string) => '%' + c.charCodeAt(0).toString(16)
const commaRE = /%2C/g
const encode = (str:string) =>
encodeURIComponent(str)
.replace(encodeReserveRE, encodeReserveReplacer)
.replace(commaRE, ',')
export function queryPageToMap(
toRule:string|totalNextRoute,
router:Router
) :{
rule:totalNextRoute;
route:RoutesRule,
query:objectAny
} {
let query:objectAny = {};
let route:RoutesRule|string = '';
let successCb = (toRule as totalNextRoute).success;
let failCb = (toRule as totalNextRoute).fail;
if (getDataType<string|totalNextRoute>(toRule) === '[object Object]') {
const objNavRule = (toRule as totalNextRoute);
if (objNavRule.path != null) {
const {path, query: newQuery} = urlToJson(objNavRule.path);
route = routesForMapRoute(router, path, ['finallyPathList', 'pathMap']);
query = {...newQuery, ...((toRule as totalNextRoute).query || {})};
objNavRule.path = path;
objNavRule.query = query;
delete (toRule as totalNextRoute).params;
} else if (objNavRule.name != null) {
route = (router.routesMap as routesMapRule).nameMap[objNavRule.name];
if (route == null) {
route = getWildcardRule(router, { type: 2, msg: `命名路由为:${objNavRule.name} 的路由,无法在路由表中找到!`, toRule});
} else {
query = (toRule as totalNextRoute).params || {};
delete (toRule as totalNextRoute).query;
}
} else {
route = getWildcardRule(router, { type: 2, msg: `${toRule} 解析失败,请检测当前路由表下是否有包含。`, toRule});
}
} else {
toRule = urlToJson((toRule as string)) as totalNextRoute;
route = routesForMapRoute(router, toRule.path, ['finallyPathList', 'pathMap'])
query = toRule.query as objectAny;
}
if (router.options.platform === 'h5') {
const {finallyPath} = getRoutePath(route as RoutesRule, router);
if (finallyPath.includes(':') && (toRule as totalNextRoute).name == null) {
ERRORHOOK[0]({ type: 2, msg: `当有设置 alias或者aliasPath 为动态路由时,不允许使用 path 跳转。请使用 name 跳转!`, route}, router)
}
const completeCb = (toRule as totalNextRoute).complete;
const cacheSuccess = (toRule as totalNextRoute).success;
const cacheFail = (toRule as totalNextRoute).fail;
if (getDataType<Function|undefined>(completeCb) === '[object Function]') {
const publicCb = function(this:any, args:Array<any>, callHook:Function|undefined):void {
if (getDataType<Function|undefined>(callHook) === '[object Function]') {
(callHook as Function).apply(this, args);
}
(completeCb as Function).apply(this, args);
}
successCb = function(this:any, ...args:any):void{
publicCb.call(this, args, cacheSuccess);
};
failCb = function(this:any, ...args:any):void{
publicCb.call(this, args, cacheFail);
};
}
}
const rule = (toRule as totalNextRoute);
if (getDataType<Function|undefined>(rule.success) === '[object Function]') {
rule.success = successCb;
}
if (getDataType<Function|undefined>(rule.fail) === '[object Function]') {
rule.fail = failCb;
}
return {
rule,
route: (route as RoutesRule),
query
}
}
export function resolveQuery(
toRule:totalNextRoute,
router:Router
):totalNextRoute {
let queryKey:'params'|'query' = 'query';
if (toRule.params as objectAny != null) {
queryKey = 'params';
}
if (toRule.query as objectAny != null) {
queryKey = 'query';
}
const query = copyData(toRule[queryKey] || {});
const {resolveQuery: userResolveQuery} = router.options;
if (userResolveQuery) {
const jsonQuery = userResolveQuery(query);
if (getDataType<objectAny>(jsonQuery) !== '[object Object]') {
warn('请按格式返回参数: resolveQuery?:(jsonQuery:{[propName: string]: any;})=>{[propName: string]: any;}', router)
} else {
toRule[queryKey] = jsonQuery;
}
} else {
const deepObj = assertDeepObject(query as objectAny);
if (!deepObj) {
return toRule;
}
const encode = JSON.stringify(query);
toRule[queryKey] = {
query: encode
}
}
return toRule
}
export function parseQuery(
query:objectAny,
router:Router,
):objectAny {
const {parseQuery: userParseQuery} = router.options;
if (userParseQuery) {
query = userParseQuery(copyData(query));
if (getDataType<objectAny>(query) !== '[object Object]') {
warn('请按格式返回参数: parseQuery?:(jsonQuery:{[propName: string]: any;})=>{[propName: string]: any;}', router)
}
} else {
if (Reflect.get(query, 'query')) { // 验证一下是不是深度对象
let deepQuery = Reflect.get(query, 'query');
if (typeof deepQuery === 'string') {
try {
deepQuery = JSON.parse(deepQuery);
} catch (error) {
warn('尝试解析深度对象失败,按原样输出。' + error, router)
}
}
if (typeof deepQuery === 'object') {
return deepDecodeQuery(deepQuery);
}
}
}
return query
}
export function stringifyQuery(obj:objectAny): string {
const res = obj
? Object.keys(obj)
.map(key => {
const val = obj[key]
if (val === undefined) {
return ''
}
if (val === null) {
return encode(key)
}
if (Array.isArray(val)) {
const result:Array<any> = []
val.forEach(val2 => {
if (val2 === undefined) {
return
}
if (val2 === null) {
result.push(encode(key))
} else {
result.push(encode(key) + '=' + encode(val2))
}
})
return result.join('&')
}
return encode(key) + '=' + encode(val)
})
.filter(x => x.length > 0)
.join('&')
: null
return res ? `?${res}` : ''
}

View File

@@ -1,158 +0,0 @@
import {
uniNavApiRule,
reNavMethodRule,
reNotNavMethodRule,
Router,
rewriteMethodToggle,
uniBackRule,
uniBackApiRule,
navtoRule,
totalNextRoute,
originMixins,
objectAny
} from '../options/base'
import {
routesForMapRoute,
getRoutePath,
getDataType,
notDeepClearNull,
resolveAbsolutePath,
getUniCachePage,
timeOut
} from '../helpers/utils'
import {
warn
} from '../helpers/warn'
import {uniOriginJump} from './uniOrigin'
const rewrite: Array<reNavMethodRule|reNotNavMethodRule> = [
'navigateTo',
'redirectTo',
'reLaunch',
'switchTab',
'navigateBack'
];
export function rewriteMethod(
router:Router
): void {
if (router.options.keepUniOriginNav === false) {
rewrite.forEach(name => {
const oldMethod: Function = uni[name];
uni[name] = function(
params:originMixins|{from:string}|navtoRule,
originCall:boolean = false,
callOkCb?:Function,
forceNav?:boolean
):void {
if (originCall) {
uniOriginJump(router, oldMethod, name, params as originMixins, callOkCb, forceNav)
} else {
if (router.options.platform === 'app-plus') {
if (Object.keys(router.appMain).length === 0) {
router.appMain = {
NAVTYPE: name,
path: (params as uniNavApiRule).url
}
}
}
callRouterMethod(params as uniNavApiRule, name, router);
}
};
})
}
}
function callRouterMethod(
option: uniNavApiRule|uniBackRule|uniBackApiRule,
funName:reNavMethodRule|reNotNavMethodRule,
router:Router
): void {
if (router.options.platform === 'app-plus') {
let openType = null;
if (option) {
openType = (option as uniNavApiRule).openType;
}
if (openType != null && openType === 'appLaunch') {
funName = 'reLaunch'
}
}
if (funName === 'reLaunch' && JSON.stringify(option) === '{"url":"/"}') {
warn(
`uni-app 原生方法reLaunch({url:'/'}) 默认被重写啦!你可以使用 this.$Router.replaceAll() 或者 uni.reLaunch({url:'/?xxx=xxx'})`,
router,
true
);
funName = 'navigateBack';
option = {
from: 'backbutton'
}
}
if (funName === 'navigateBack') {
let level:number = 1;
if (option == null) {
option = {delta: 1};
}
if (getDataType<number|undefined>((option as uniBackApiRule).delta) === '[object Number]') {
level = ((option as uniBackApiRule).delta as number);
}
router.back(level, (option as uniBackRule|uniBackApiRule));
} else {
const routerMethodName = rewriteMethodToggle[(funName as reNavMethodRule)]
let path = (option as uniNavApiRule).url;
if (!path.startsWith('/')) {
const absolutePath = resolveAbsolutePath(path, router);
path = absolutePath;
(option as uniNavApiRule).url = absolutePath;
}
if (funName === 'switchTab') {
const route = routesForMapRoute(router, path, ['pathMap', 'finallyPathList'])
const {finallyPath} = getRoutePath(route, router);
if (getDataType<string | string[]>(finallyPath) === '[object Array]') {
warn(
`uni-app 原生方法跳转路径为:${path}。此路为是tab页面时不允许设置 alias 为数组的情况,并且不能为动态路由!当然你可以通过通配符*解决!`,
router,
true
);
}
if ((finallyPath as string) === '*') {
warn(
`uni-app 原生方法跳转路径为:${path}。在路由表中找不到相关路由表!当然你可以通过通配符*解决!`,
router,
true
);
}
// Fixe h5 端无法触发 onTabItemTap hook 2021年6月3日17:26:47
if (router.options.platform === 'h5') {
const {success: userSuccess} = option as uniNavApiRule;
(option as uniNavApiRule).success = (...args:Array<any>) => {
userSuccess?.apply(null, args);
timeOut(150).then(() => {
const cbArgs = (option as uniNavApiRule).detail || {};
if (Object.keys(cbArgs).length > 0 && Reflect.has(cbArgs, 'index')) {
const cachePage = getUniCachePage(0);
if (Object.keys(cachePage).length === 0) {
return false
}
const page = cachePage as objectAny;
const hooks = page.$options.onTabItemTap;
if (hooks) {
for (let j = 0; j < hooks.length; j++) {
hooks[j].call(page, cbArgs)
}
}
}
});
}
}
path = (finallyPath as string);
}
const {events, success, fail, complete, animationType, animationDuration} = option as uniNavApiRule;
const jumpOptions:totalNextRoute = {path, events, success, fail, complete, animationDuration, animationType};
router[routerMethodName](
notDeepClearNull<totalNextRoute>(jumpOptions)
)
}
}

View File

@@ -1,129 +0,0 @@
import {PromiseResolve, Router, uniBackApiRule, uniBackRule} from '../options/base';
import {InstantiateConfig, LifeCycleConfig} from '../options/config';
import { lifeCycle, proxyHookDeps} from '../helpers/config';
import {assertNewOptions, def, getDataType} from '../helpers/utils';
import {registerRouterHooks, registerEachHooks} from '../helpers/lifeCycle';
import {initMixins} from '../helpers/mixins'
import {lockNavjump, forceGuardEach, createRoute} from '../public/methods'
import {rewriteMethod} from '../public/rewrite'
let AppReadyResolve:PromiseResolve = () => {};
const AppReady:Promise<void> = new Promise(resolve => (AppReadyResolve = resolve));
function createRouter(params: InstantiateConfig):Router {
const options = assertNewOptions<InstantiateConfig>(params);
const router:Router = {
options,
mount: [],
Vue: null,
proxyHookDeps: proxyHookDeps,
appMain: {},
enterPath: '',
$route: null,
$lockStatus: false,
routesMap: {},
lifeCycle: registerRouterHooks<LifeCycleConfig>(lifeCycle, options),
push(to) {
lockNavjump(to, router, 'push');
},
replace(to) {
lockNavjump(to, router, 'replace');
},
replaceAll(to) {
lockNavjump(to, router, 'replaceAll');
},
pushTab(to) {
lockNavjump(to, router, 'pushTab');
},
back(level = 1, animation) {
if (getDataType(animation) !== '[object Object]') {
const backRule:uniBackRule = {
from: 'navigateBack'
}
animation = backRule;
} else {
if (!Reflect.has((animation as uniBackRule | uniBackApiRule), 'from')) {
animation = {
...animation,
from: 'navigateBack'
};
}
}
lockNavjump(level + '', router, 'back', undefined, animation)
},
forceGuardEach(navType, forceNav) {
forceGuardEach(router, navType, forceNav)
},
beforeEach(userGuard):void {
registerEachHooks(router, 'beforeHooks', userGuard);
},
afterEach(userGuard):void {
registerEachHooks(router, 'afterHooks', userGuard);
},
install(Vue:any):void{
router.Vue = Vue;
rewriteMethod(this);
initMixins(Vue, this);
Object.defineProperty(Vue.prototype, '$Router', {
get() {
const actualData = router;
Object.defineProperty(this, '$Router', {
value: actualData,
writable: false,
configurable: false,
enumerable: false
});
return Object.seal(actualData);
}
});
Object.defineProperty(Vue.prototype, '$Route', {
get() {
return createRoute(router);
}
});
// 【Fixe】 https://github.com/SilurianYang/uni-simple-router/issues/254
Object.defineProperty(Vue.prototype, '$AppReady', {
get() {
if (router.options.platform === 'h5') {
return Promise.resolve();
}
return AppReady;
},
set(value:boolean) {
if (value === true) {
AppReadyResolve();
}
}
});
}
}
def(router, 'currentRoute', () => createRoute(router));
router.beforeEach((to, from, next) => next());
router.afterEach(() => {});
return router;
}
function RouterMount(Vim:any, router:Router, el:string | undefined = '#app') :void|never {
if (getDataType<Array<any>>(router.mount) === '[object Array]') {
router.mount.push({
app: Vim,
el
})
} else {
throw new Error(`挂载路由失败router.app 应该为数组类型。当前类型:${typeof router.mount}`);
}
if (router.options.platform === 'h5') {
const vueRouter = (router.$route as any);
vueRouter.replace({
path: vueRouter.currentRoute.fullPath
});
} // 其他端目前不需要做啥
}
export {
RouterMount,
createRouter
}

View File

@@ -1,112 +0,0 @@
import { originMixins, reNavMethodRule, reNotNavMethodRule, Router, startAnimationRule, uniNavApiRule } from '../options/base';
import { stringifyQuery } from './query';
import {notDeepClearNull, timeOut} from '../helpers/utils'
import { mpPlatformReg } from '../helpers/config';
import { resetAndCallPageHook, resetPageHook } from './page';
let routerNavCount:number = 0;
let lastNavType:reNavMethodRule|reNotNavMethodRule = 'reLaunch'
export function uniOriginJump(
router:Router,
originMethod:Function,
funName:reNavMethodRule|reNotNavMethodRule,
options: originMixins,
callOkCb?:Function,
forceNav?:boolean
):void {
const {complete, ...originRule} = formatOriginURLQuery(router, options, funName);
const platform = router.options.platform;
if (forceNav != null && forceNav === false) {
if (routerNavCount === 0) {
routerNavCount++
if (platform !== 'h5') {
resetAndCallPageHook(router, originRule.url) // 还原及执行app.vue及首页下已经重写后的生命周期
// 【Fixe】 https://github.com/SilurianYang/uni-simple-router/issues/254
// 在小程序端 next 直接放行会执行这个
router.Vue.prototype.$AppReady = true;
}
}
complete && complete.apply(null, {msg: 'forceGuardEach强制触发并且不执行跳转'});
callOkCb && callOkCb.apply(null, {msg: 'forceGuardEach强制触发并且不执行跳转'})
} else {
if (routerNavCount === 0) {
if (platform === 'app-plus') {
resetAndCallPageHook(router, originRule.url) // 还原及执行app.vue下已经重写后的生命周期
} else {
if (new RegExp(mpPlatformReg, 'g').test(platform)) {
// 其他就是在小程序下,首次启动发生跳转会走这里
// 我们先将app.vue的生命周期执行
resetAndCallPageHook(router, originRule.url, false)
}
}
}
originMethod({
...originRule,
from: options.BACKTYPE,
complete: async function(...args:Array<any>) {
if (routerNavCount === 0) {
routerNavCount++
if (platform !== 'h5') {
if (new RegExp(mpPlatformReg, 'g').test(platform)) { // 跳转完成后小程序下还原生命周期
resetPageHook(router);
}
// 【Fixe】 https://github.com/SilurianYang/uni-simple-router/issues/254
// 在小程序端 第一次 next 做跳转 会触发这个 、在app端首次必定会触发这个
router.Vue.prototype.$AppReady = true;
if (platform === 'app-plus') {
const waitPage = plus.nativeObj.View.getViewById('router-loadding');
waitPage && waitPage.close();
const launchedHook = router.options.APP?.launchedHook;
launchedHook && launchedHook();
}
}
}
let time:number = 0;
if (new RegExp(mpPlatformReg, 'g').test(platform)) {
time = (router.options.applet?.animationDuration) as number
} else if (platform === 'app-plus') {
if (funName === 'navigateBack' && lastNavType === 'navigateTo') {
time = (router.options.APP?.animation?.animationDuration) as number
}
}
if (funName === 'navigateTo' || funName === 'navigateBack') {
if (time !== 0) {
await timeOut(time);
}
}
lastNavType = funName;
complete && complete.apply(null, args);
callOkCb && callOkCb.apply(null, args)
}
});
}
}
export function formatOriginURLQuery(
router:Router,
options:uniNavApiRule,
funName:reNavMethodRule|reNotNavMethodRule
):uniNavApiRule {
const {url, path, query, animationType, animationDuration, events, success, fail, complete, delta, animation} = options;
const strQuery = stringifyQuery(query || {});
const queryURL = strQuery === '' ? (path || url) : (path || url) + strQuery;
let animationRule:startAnimationRule = {};
if (router.options.platform === 'app-plus') {
if (funName !== 'navigateBack') {
animationRule = router.options.APP?.animation || {};
animationRule = {...animationRule, ...animation || {}};
}
}
return notDeepClearNull<uniNavApiRule>({
delta,
url: queryURL,
animationType: animationType || animationRule.animationType,
animationDuration: animationDuration || animationRule.animationDuration,
events,
success,
fail,
complete
})
}

View File

@@ -1,70 +0,0 @@
import {createRouter, routesMapKeysRule} from '../src/index';
import {routesForMapRoute} from '../src/helpers/utils';
const routes = [
{path: '/pages/login/login', name: 'login', aliasPath: '/'},
{path: '/pages/page2/page2', name: 'page2', aliasPath: '/page2/:id'},
{path: '/pages/page3/page3', aliasPath: '/:name/page3/:id'},
{path: '/pages/animation/animation', aliasPath: '/an-(\\d+)-on'},
{path: '/static/1/1', aliasPath: '/static/(.*)'},
{path: '/dynamic/1/1', aliasPath: '/dynamic-*'},
{path: '/dynamic/3/3', aliasPath: '/dynamic3'},
{path: '*'}
];
const router = createRouter({
platform: 'app-plus',
keepUniOriginNav: true,
routes,
});
const Vue = function () {};
Vue.mixin = () => {};
router.install(Vue);
const rules: routesMapKeysRule[] = ['finallyPathMap', 'pathMap'];
it('别名路径匹配',()=>{
const toRoute1 = routesForMapRoute(router, '/dynamic3', rules);
expect(toRoute1).toEqual(routes[6]);
const toRoute2 = routesForMapRoute(router, '/dynamic/3/3', rules);
expect(toRoute2).toEqual(routes[6]);
})
it('全局匹配', () => {
const toRoute1 = routesForMapRoute(router, '/pages/login/login', rules);
expect(toRoute1).toEqual(routes[0]);
const toRoute2 = routesForMapRoute(router,'/pages/login/login?id=666',rules);
expect(toRoute2).toEqual(routes[0]);
const toRoute3 = routesForMapRoute(router, '/page2/6666', rules);
expect(toRoute3).toEqual(routes[1]);
const toRoute4 = routesForMapRoute(router, '/page2/6666?id=555', rules);
expect(toRoute4).toEqual(routes[1]);
const toRoute5 = routesForMapRoute(router, '/pages/page3/page3', rules);
expect(toRoute5).toEqual(routes[2]);
const toRoute6 = routesForMapRoute(router, '/test/page3/123', rules);
expect(toRoute6).toEqual(routes[2]);
const toRoute7 = routesForMapRoute(router, '/an-123-on', rules);
expect(toRoute7).toEqual(routes[3]);
const toRoute8 = routesForMapRoute(router, '/static/aaa/bbb?id=1444&name=999', rules);
expect(toRoute8).toEqual(routes[4]);
const toRoute9 = routesForMapRoute(router, '/dynamic-6666-5555', rules);
expect(toRoute9).toEqual(routes[5]);
const toRoute10 = routesForMapRoute(router, '/aaaaaa', rules);
expect(toRoute10).toEqual(routes[7]);
const toRoute11 = routesForMapRoute(router, '---48848--14545', rules);
expect(toRoute11).toEqual(routes[7]);
});

View File

@@ -1,83 +0,0 @@
import {deepDecodeQuery} from '../src/helpers/utils';
it('编码回转',()=>{
const query={
str:'%E7%9A%84%E6%8C%A5%E6%B4%92U%E7%9B%BE%E5%A5%BD%E6%92%92%E7%AC%AC%E4%B8%89%E5%A4%A7%E5%8E%A6%E5%8F%91%E7%9A%84%E6%92%92321312%2a%EF%BC%88%EF%BF%A5%23%254'
}
const result = deepDecodeQuery(query);
expect(JSON.stringify(result)).toEqual(JSON.stringify({
str:'的挥洒U盾好撒第三大厦发的撒321312*(¥#%4'
}))
})
it('一些乱码字符',()=>{
const query={
str:`~!@#$%^&*()_+-,./|][]`
}
const result = deepDecodeQuery(query);
expect(JSON.stringify(result)).toEqual(JSON.stringify({
str:`~!@#$%^&*()_+-,./|][]`
}))
})
it('单个加密参数',()=>{
const query={
name:'%7B%22status%22%3Atrue%2C%22list%22%3A%5B%7B%22id%22%3A1%7D%5D%7D'
}
const result = deepDecodeQuery(query);
expect(JSON.stringify(result)).toEqual(JSON.stringify({
name:{
status:true,
list:[
{
id:1
},
]
}
}));
})
it('单个普通参数',()=>{
const query={
name:'hhyang',
ages:22,
open:true
}
const result = deepDecodeQuery(query);
expect(JSON.stringify(result)).toEqual(JSON.stringify(query));
})
it('深度参数加混乱',()=>{
const query={
list:[
1,'2',true,encodeURIComponent(JSON.stringify({name:111})),{
name:'hhyang',
strObj:encodeURIComponent(JSON.stringify({name:222}))
}
],
obj:{
strObj2:encodeURIComponent(JSON.stringify({name:333})),
number:1,
boolean:false,
},
str4:encodeURIComponent(JSON.stringify({name:444}))
}
const result = deepDecodeQuery(query);
expect(JSON.stringify(result)).toEqual(JSON.stringify({
list:[
1,'2',true,{name:111},{
name:'hhyang',
strObj:{name:222}
}
],
obj:{
strObj2:{name:333},
number:1,
boolean:false,
},
str4:{name:444}
}));
})

View File

@@ -1,19 +0,0 @@
{
"compilerOptions": {
"target": "es5",
"module": "CommonJS",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"lib": ["ES2015", "DOM"],
"outDir": "dist/src",
"declaration": true,
"declarationMap": false,
"rootDir": "./src",
"baseUrl": ".",
"paths": {}
},
"include": ["./src/global.d.ts", "./src/*"],
"exclude": ["node_modules", "**/*.spec.ts"]
}

View File

@@ -1,41 +0,0 @@
const {resolve} = require('path');
const CopyPlugin = require('copy-webpack-plugin');
const webpack =require('webpack');
module.exports = {
entry: './src/index.ts',
output: {
library: 'Router',
libraryTarget: 'umd',
},
resolve: {
extensions: ['.tsx', '.ts', 'd.ts', '.js', '.json'],
},
module: {
rules: [
{
test: /\.tsx?$/,
use: [
{
loader: 'ts-loader',
},
],
exclude: /node_modules/,
},
],
},
plugins: [
new CopyPlugin([
{
force: true,
from: resolve(__dirname, '../src/component'),
to: resolve(__dirname, '../dist'),
},
]),
new webpack.DefinePlugin({
$npm_package_name: webpack.DefinePlugin.runtimeValue(() => {
return JSON.stringify(process.env.npm_package_name.toLocaleUpperCase())
}, true )
})
],
};

View File

@@ -1,22 +0,0 @@
const {merge} = require("webpack-merge");
const {resolve} = require('path');
const common = require("./webpack.common.js");
const CopyPlugin = require('copy-webpack-plugin');
const output=resolve(__dirname, '../examples/uni-simple-router2.0/dist');
module.exports = merge(common, {
mode: 'development',
devtool: 'source-map',
output: {
path:output ,
filename: 'uni-simple-router.js',
},
plugins: [
new CopyPlugin([{
force: true,
from: resolve(__dirname, '../src/component'),
to: output,
}]),
]
});

View File

@@ -1,19 +0,0 @@
const {resolve} = require('path');
const {merge} = require("webpack-merge");
const common = require("./webpack.common.js");
const rimraf = require('rimraf');
function resolvePath(dir) {
return resolve(__dirname, '../', dir)
}
rimraf('dist', () => {});
module.exports = merge(common, {
mode: "production",
output: {
path: resolvePath('dist'),
filename: 'uni-simple-router.js',
},
})

21
node_modules/uview-ui/LICENSE generated vendored
View File

@@ -1,21 +0,0 @@
MIT License
Copyright (c) 2020 www.uviewui.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

106
node_modules/uview-ui/README.md generated vendored
View File

@@ -1,106 +0,0 @@
<p align="center">
<img alt="logo" src="https://uviewui.com/common/logo.png" width="120" height="120" style="margin-bottom: 10px;">
</p>
<h3 align="center" style="margin: 30px 0 30px;font-weight: bold;font-size:40px;">uView</h3>
<h3 align="center">多平台快速开发的UI框架</h3>
## 说明
uView UI是[uni-app](https://uniapp.dcloud.io/)生态优秀的UI框架全面的组件和便捷的工具会让您信手拈来如鱼得水
## 特性
- 兼容安卓iOS微信小程序H5QQ小程序百度小程序支付宝小程序头条小程序
- 60+精选组件,功能丰富,多端兼容,让您快速集成,开箱即用
- 众多贴心的JS利器让您飞镖在手召之即来百步穿杨
- 众多的常用页面和布局,让您专注逻辑,事半功倍
- 详尽的文档支持,现代化的演示效果
- 按需引入,精简打包体积
## 安装
```bash
# npm方式安装
npm i uview-ui
```
## 快速上手
1. `main.js`引入uView库
```js
// main.js
import uView from 'uview-ui';
Vue.use(uView);
```
2. `App.vue`引入基础样式(注意style标签需声明scss属性支持)
```css
/* App.vue */
<style lang="scss">
@import "uview-ui/index.scss";
</style>
```
3. `uni.scss`引入全局scss变量文件
```css
/* uni.scss */
@import "uview-ui/theme.scss";
```
4. `pages.json`配置easycom规则(按需引入)
```js
// pages.json
{
"easycom": {
// npm安装的方式不需要前面的"@/",下载安装的方式需要"@/"
// npm安装方式
"^u-(.*)": "uview-ui/components/u-$1/u-$1.vue"
// 下载安装方式
// "^u-(.*)": "@/uview-ui/components/u-$1/u-$1.vue"
},
// 此为本身已有的内容
"pages": [
// ......
]
}
```
请通过[快速上手](https://uviewui.com/components/quickstart.html)了解更详细的内容
## 使用方法
配置easycom规则后自动按需引入无需`import`组件,直接引用即可。
```html
<template>
<u-button>按钮</u-button>
</template>
```
请通过[快速上手](https://uviewui.com/components/quickstart.html)了解更详细的内容
## 链接
- [官方文档](https://uviewui.com/)
- [更新日志](https://uviewui.com/components/changelog.html)
- [升级指南](https://uviewui.com/components/changelog.html)
- [关于我们](https://uviewui.com/cooperation/about.html)
## 预览
您可以通过**微信**扫码,查看最佳的演示效果。
<br>
<br>
<img src="https://uviewui.com/common/weixin_mini_qrcode.png" width="220" height="220" >
<!-- ## 捐赠uView的研发
uView文档和源码全部开源免费如果您认为uView帮到了您的开发工作您可以捐赠uView的研发工作捐赠无门槛哪怕是一杯可乐也好(相信这比打赏主播更有意义)。
<img src="https://uviewui.com/common/wechat.png" width="220" >
<img style="margin-left: 100px;" src="https://uviewui.com/common/alipay.png" width="220" >
-->
## 版权信息
uView遵循[MIT](https://en.wikipedia.org/wiki/MIT_License)开源协议意味着您无需支付任何费用也无需授权即可将uView应用到您的产品中。

View File

@@ -1,190 +0,0 @@
<template>
<u-popup mode="bottom" :border-radius="borderRadius" :popup="false" v-model="value" :maskCloseAble="maskCloseAble"
length="auto" :safeAreaInsetBottom="safeAreaInsetBottom" @close="popupClose" :z-index="uZIndex">
<view class="u-tips u-border-bottom" v-if="tips.text" :style="[tipsStyle]">
{{tips.text}}
</view>
<block v-for="(item, index) in list" :key="index">
<view
@touchmove.stop.prevent
@tap="itemClick(index)"
:style="[itemStyle(index)]"
class="u-action-sheet-item u-line-1"
:class="[index < list.length - 1 ? 'u-border-bottom' : '']"
:hover-stay-time="150"
>
<text>{{item.text}}</text>
<text class="u-action-sheet-item__subtext u-line-1" v-if="item.subText">{{item.subText}}</text>
</view>
</block>
<view class="u-gab" v-if="cancelBtn">
</view>
<view @touchmove.stop.prevent class="u-actionsheet-cancel u-action-sheet-item" hover-class="u-hover-class"
:hover-stay-time="150" v-if="cancelBtn" @tap="close">{{cancelText}}</view>
</u-popup>
</template>
<script>
/**
* actionSheet 操作菜单
* @description 本组件用于从底部弹出一个操作菜单供用户选择并返回结果。本组件功能类似于uni的uni.showActionSheetAPI配置更加灵活所有平台都表现一致。
* @tutorial https://www.uviewui.com/components/actionSheet.html
* @property {Array<Object>} list 按钮的文字数组,见官方文档示例
* @property {Object} tips 顶部的提示文字,见官方文档示例
* @property {String} cancel-text 取消按钮的提示文字
* @property {Boolean} cancel-btn 是否显示底部的取消按钮默认true
* @property {Number String} border-radius 弹出部分顶部左右的圆角值单位rpx默认0
* @property {Boolean} mask-close-able 点击遮罩是否可以关闭默认true
* @property {Boolean} safe-area-inset-bottom 是否开启底部安全区适配默认false
* @property {Number String} z-index z-index值默认1075
* @property {String} cancel-text 取消按钮的提示文字
* @event {Function} click 点击ActionSheet列表项时触发
* @event {Function} close 点击取消按钮时触发
* @example <u-action-sheet :list="list" @click="click" v-model="show"></u-action-sheet>
*/
export default {
name: "u-action-sheet",
props: {
// 点击遮罩是否可以关闭actionsheet
maskCloseAble: {
type: Boolean,
default: true
},
// 按钮的文字数组可以自定义颜色和字体大小字体单位为rpx
list: {
type: Array,
default () {
// 如下
// return [{
// text: '确定',
// color: '',
// fontSize: ''
// }]
return [];
}
},
// 顶部的提示文字
tips: {
type: Object,
default () {
return {
text: '',
color: '',
fontSize: '26'
}
}
},
// 底部的取消按钮
cancelBtn: {
type: Boolean,
default: true
},
// 是否开启底部安全区适配开启的话会在iPhoneX机型底部添加一定的内边距
safeAreaInsetBottom: {
type: Boolean,
default: false
},
// 通过双向绑定控制组件的弹出与收起
value: {
type: Boolean,
default: false
},
// 弹出的顶部圆角值
borderRadius: {
type: [String, Number],
default: 0
},
// 弹出的z-index值
zIndex: {
type: [String, Number],
default: 0
},
// 取消按钮的文字提示
cancelText: {
type: String,
default: '取消'
}
},
computed: {
// 顶部提示的样式
tipsStyle() {
let style = {};
if (this.tips.color) style.color = this.tips.color;
if (this.tips.fontSize) style.fontSize = this.tips.fontSize + 'rpx';
return style;
},
// 操作项目的样式
itemStyle() {
return (index) => {
let style = {};
if (this.list[index].color) style.color = this.list[index].color;
if (this.list[index].fontSize) style.fontSize = this.list[index].fontSize + 'rpx';
// 选项被禁用的样式
if (this.list[index].disabled) style.color = '#c0c4cc';
return style;
}
},
uZIndex() {
// 如果用户有传递z-index值优先使用
return this.zIndex ? this.zIndex : this.$u.zIndex.popup;
}
},
methods: {
// 点击取消按钮
close() {
// 发送input事件并不会作用于父组件而是要设置组件内部通过props传递的value参数
// 这是一个vue发送事件的特殊用法
this.popupClose();
this.$emit('close');
},
// 弹窗关闭
popupClose() {
this.$emit('input', false);
},
// 点击某一个item
itemClick(index) {
// disabled的项禁止点击
if(this.list[index].disabled) return;
this.$emit('click', index);
this.$emit('input', false);
}
}
}
</script>
<style lang="scss" scoped>
@import "../../libs/css/style.components.scss";
.u-tips {
font-size: 26rpx;
text-align: center;
padding: 34rpx 0;
line-height: 1;
color: $u-tips-color;
}
.u-action-sheet-item {
@include vue-flex;;
line-height: 1;
justify-content: center;
align-items: center;
font-size: 32rpx;
padding: 34rpx 0;
flex-direction: column;
}
.u-action-sheet-item__subtext {
font-size: 24rpx;
color: $u-tips-color;
margin-top: 20rpx;
}
.u-gab {
height: 12rpx;
background-color: rgb(234, 234, 236);
}
.u-actionsheet-cancel {
color: $u-main-color;
}
</style>

View File

@@ -1,256 +0,0 @@
<template>
<view class="u-alert-tips" v-if="show" :class="[
!show ? 'u-close-alert-tips': '',
type ? 'u-alert-tips--bg--' + type + '-light' : '',
type ? 'u-alert-tips--border--' + type + '-disabled' : '',
]" :style="{
backgroundColor: bgColor,
borderColor: borderColor
}">
<view class="u-icon-wrap">
<u-icon v-if="showIcon" :name="uIcon" :size="description ? 40 : 32" class="u-icon" :color="uIconType" :custom-style="iconStyle"></u-icon>
</view>
<view class="u-alert-content" @tap.stop="click">
<view class="u-alert-title" :style="[uTitleStyle]">
{{title}}
</view>
<view v-if="description" class="u-alert-desc" :style="[descStyle]">
{{description}}
</view>
</view>
<view class="u-icon-wrap">
<u-icon @click="close" v-if="closeAble && !closeText" hoverClass="u-type-error-hover-color" name="close" color="#c0c4cc"
:size="22" class="u-close-icon" :style="{
top: description ? '18rpx' : '24rpx'
}"></u-icon>
</view>
<text v-if="closeAble && closeText" class="u-close-text" :style="{
top: description ? '18rpx' : '24rpx'
}">{{closeText}}</text>
</view>
</template>
<script>
/**
* alertTips 警告提示
* @description 警告提示,展现需要关注的信息
* @tutorial https://uviewui.com/components/alertTips.html
* @property {String} title 显示的标题文字
* @property {String} description 辅助性文字颜色比title浅一点字号也小一点可选
* @property {String} type 关闭按钮(默认为叉号icon图标)
* @property {String} icon 图标名称
* @property {Object} icon-style 图标的样式,对象形式
* @property {Object} title-style 标题的样式,对象形式
* @property {Object} desc-style 描述的样式,对象形式
* @property {String} close-able 用文字替代关闭图标close-able为true时有效
* @property {Boolean} show-icon 是否显示左边的辅助图标
* @property {Boolean} show 显示或隐藏组件
* @event {Function} click 点击组件时触发
* @event {Function} close 点击关闭按钮时触发
*/
export default {
name: 'u-alert-tips',
props: {
// 显示文字
title: {
type: String,
default: ''
},
// 主题success/warning/info/error
type: {
type: String,
default: 'warning'
},
// 辅助性文字
description: {
type: String,
default: ''
},
// 是否可关闭
closeAble: {
type: Boolean,
default: false
},
// 关闭按钮自定义文本
closeText: {
type: String,
default: ''
},
// 是否显示图标
showIcon: {
type: Boolean,
default: false
},
// 文字颜色如果定义了color值icon会失效
color: {
type: String,
default: ''
},
// 背景颜色
bgColor: {
type: String,
default: ''
},
// 边框颜色
borderColor: {
type: String,
default: ''
},
// 是否显示
show: {
type: Boolean,
default: true
},
// 左边显示的icon
icon: {
type: String,
default: ''
},
// icon的样式
iconStyle: {
type: Object,
default() {
return {}
}
},
// 标题的样式
titleStyle: {
type: Object,
default() {
return {}
}
},
// 描述文字的样式
descStyle: {
type: Object,
default() {
return {}
}
},
},
data() {
return {
}
},
computed: {
uTitleStyle() {
let style = {};
// 如果有描述文字的话,标题进行加粗
style.fontWeight = this.description ? 500 : 'normal';
// 将用户传入样式对象和style合并传入的优先级比style高同属性会被覆盖
return this.$u.deepMerge(style, this.titleStyle);
},
uIcon() {
// 如果有设置icon名称就使用否则根据type主题推定一个默认的图标
return this.icon ? this.icon : this.$u.type2icon(this.type);
},
uIconType() {
// 如果有设置图标的样式优先使用没有的话则用type的样式
return Object.keys(this.iconStyle).length ? '' : this.type;
}
},
methods: {
// 点击内容
click() {
this.$emit('click');
},
// 点击关闭按钮
close() {
this.$emit('close');
}
}
}
</script>
<style lang="scss" scoped>
@import "../../libs/css/style.components.scss";
.u-alert-tips {
@include vue-flex;
align-items: center;
padding: 16rpx 30rpx;
border-radius: 8rpx;
position: relative;
transition: all 0.3s linear;
border: 1px solid #fff;
&--bg--primary-light {
background-color: $u-type-primary-light;
}
&--bg--info-light {
background-color: $u-type-info-light;
}
&--bg--success-light {
background-color: $u-type-success-light;
}
&--bg--warning-light {
background-color: $u-type-warning-light;
}
&--bg--error-light {
background-color: $u-type-error-light;
}
&--border--primary-disabled {
border-color: $u-type-primary-disabled;
}
&--border--success-disabled {
border-color: $u-type-success-disabled;
}
&--border--error-disabled {
border-color: $u-type-error-disabled;
}
&--border--warning-disabled {
border-color: $u-type-warning-disabled;
}
&--border--info-disabled {
border-color: $u-type-info-disabled;
}
}
.u-close-alert-tips {
opacity: 0;
visibility: hidden;
}
.u-icon {
margin-right: 16rpx;
}
.u-alert-title {
font-size: 28rpx;
color: $u-main-color;
}
.u-alert-desc {
font-size: 26rpx;
text-align: left;
color: $u-content-color;
}
.u-close-icon {
position: absolute;
top: 20rpx;
right: 20rpx;
}
.u-close-hover {
color: red;
}
.u-close-text {
font-size: 24rpx;
color: $u-tips-color;
position: absolute;
top: 20rpx;
right: 20rpx;
line-height: 1;
}
</style>

View File

@@ -1,290 +0,0 @@
<template>
<view class="content">
<view class="cropper-wrapper" :style="{ height: cropperOpt.height + 'px' }">
<canvas
class="cropper"
:disable-scroll="true"
@touchstart="touchStart"
@touchmove="touchMove"
@touchend="touchEnd"
:style="{ width: cropperOpt.width, height: cropperOpt.height, backgroundColor: 'rgba(0, 0, 0, 0.8)' }"
canvas-id="cropper"
id="cropper"
></canvas>
<canvas
class="cropper"
:disable-scroll="true"
:style="{
position: 'fixed',
top: `-${cropperOpt.width * cropperOpt.pixelRatio}px`,
left: `-${cropperOpt.height * cropperOpt.pixelRatio}px`,
width: `${cropperOpt.width * cropperOpt.pixelRatio}px`,
height: `${cropperOpt.height * cropperOpt.pixelRatio}`
}"
canvas-id="targetId"
id="targetId"
></canvas>
</view>
<view class="cropper-buttons safe-area-padding" :style="{ height: bottomNavHeight + 'px' }">
<!-- #ifdef H5 -->
<view class="upload" @tap="uploadTap">选择图片</view>
<!-- #endif -->
<!-- #ifndef H5 -->
<view class="upload" @tap="uploadTap">重新选择</view>
<!-- #endif -->
<view class="getCropperImage" @tap="getCropperImage(false)">确定</view>
</view>
</view>
</template>
<script>
import WeCropper from './weCropper.js';
export default {
props: {
// 裁剪矩形框的样式其中可包含的属性为lineWidth-边框宽度(单位rpx)color: 边框颜色,
// mask-遮罩颜色一般设置为一个rgba的透明度如"rgba(0, 0, 0, 0.35)"
boundStyle: {
type: Object,
default() {
return {
lineWidth: 4,
borderColor: 'rgb(245, 245, 245)',
mask: 'rgba(0, 0, 0, 0.35)'
};
}
}
// // 裁剪框宽度单位rpx
// rectWidth: {
// type: [String, Number],
// default: 400
// },
// // 裁剪框高度单位rpx
// rectHeight: {
// type: [String, Number],
// default: 400
// },
// // 输出图片宽度单位rpx
// destWidth: {
// type: [String, Number],
// default: 400
// },
// // 输出图片高度单位rpx
// destHeight: {
// type: [String, Number],
// default: 400
// },
// // 输出的图片类型,如果发现裁剪的图片很大,可能是因为设置为了"png",改成"jpg"即可
// fileType: {
// type: String,
// default: 'jpg',
// },
// // 生成的图片质量
// // H5上无效目前不考虑使用此参数
// quality: {
// type: [Number, String],
// default: 1
// }
},
data() {
return {
// 底部导航的高度
bottomNavHeight: 50,
originWidth: 200,
width: 0,
height: 0,
cropperOpt: {
id: 'cropper',
targetId: 'targetCropper',
pixelRatio: 1,
width: 0,
height: 0,
scale: 2.5,
zoom: 8,
cut: {
x: (this.width - this.originWidth) / 2,
y: (this.height - this.originWidth) / 2,
width: this.originWidth,
height: this.originWidth
},
boundStyle: {
lineWidth: uni.upx2px(this.boundStyle.lineWidth),
mask: this.boundStyle.mask,
color: this.boundStyle.borderColor
}
},
// 裁剪框和输出图片的尺寸,高度默认等于宽度
// 输出图片宽度单位px
destWidth: 200,
// 裁剪框宽度单位px
rectWidth: 200,
// 输出的图片类型,如果'png'类型发现裁剪的图片太大,改成"jpg"即可
fileType: 'jpg',
src: '', // 选择的图片路径,用于在点击确定时,判断是否选择了图片
};
},
onLoad(option) {
let rectInfo = uni.getSystemInfoSync();
this.width = rectInfo.windowWidth;
this.height = rectInfo.windowHeight - this.bottomNavHeight;
this.cropperOpt.width = this.width;
this.cropperOpt.height = this.height;
this.cropperOpt.pixelRatio = rectInfo.pixelRatio;
if (option.destWidth) this.destWidth = option.destWidth;
if (option.rectWidth) {
let rectWidth = Number(option.rectWidth);
this.cropperOpt.cut = {
x: (this.width - rectWidth) / 2,
y: (this.height - rectWidth) / 2,
width: rectWidth,
height: rectWidth
};
}
this.rectWidth = option.rectWidth;
if (option.fileType) this.fileType = option.fileType;
// 初始化
this.cropper = new WeCropper(this.cropperOpt)
.on('ready', ctx => {
// wecropper is ready for work!
})
.on('beforeImageLoad', ctx => {
// before picture loaded, i can do something
})
.on('imageLoad', ctx => {
// picture loaded
})
.on('beforeDraw', (ctx, instance) => {
// before canvas draw,i can do something
});
// 设置导航栏样式以免用户在page.json中没有设置为黑色背景
uni.setNavigationBarColor({
frontColor: '#ffffff',
backgroundColor: '#000000'
});
uni.chooseImage({
count: 1, // 默认9
sizeType: ['compressed'], // 可以指定是原图还是压缩图,默认二者都有
sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有
success: res => {
this.src = res.tempFilePaths[0];
// 获取裁剪图片资源后给data添加src属性及其值
this.cropper.pushOrign(this.src);
}
});
},
methods: {
touchStart(e) {
this.cropper.touchStart(e);
},
touchMove(e) {
this.cropper.touchMove(e);
},
touchEnd(e) {
this.cropper.touchEnd(e);
},
getCropperImage(isPre = false) {
if(!this.src) return this.$u.toast('请先选择图片再裁剪');
let cropper_opt = {
destHeight: Number(this.destWidth), // uni.canvasToTempFilePath要求这些参数为数值
destWidth: Number(this.destWidth),
fileType: this.fileType
};
this.cropper.getCropperImage(cropper_opt, (path, err) => {
if (err) {
uni.showModal({
title: '温馨提示',
content: err.message
});
} else {
if (isPre) {
uni.previewImage({
current: '', // 当前显示图片的 http 链接
urls: [path] // 需要预览的图片 http 链接列表
});
} else {
uni.$emit('uAvatarCropper', path);
this.$u.route({
type: 'back'
});
}
}
});
},
uploadTap() {
const self = this;
uni.chooseImage({
count: 1, // 默认9
sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认二者都有
sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有
success: (res) => {
self.src = res.tempFilePaths[0];
// 获取裁剪图片资源后给data添加src属性及其值
self.cropper.pushOrign(this.src);
}
});
}
}
};
</script>
<style scoped lang="scss">
@import '../../libs/css/style.components.scss';
.content {
background: rgba(255, 255, 255, 1);
}
.cropper {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 11;
}
.cropper-buttons {
background-color: #000000;
color: #eee;
}
.cropper-wrapper {
position: relative;
@include vue-flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
width: 100%;
background-color: #000;
}
.cropper-buttons {
width: 100vw;
@include vue-flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
position: fixed;
bottom: 0;
left: 0;
font-size: 28rpx;
}
.cropper-buttons .upload,
.cropper-buttons .getCropperImage {
width: 50%;
text-align: center;
}
.cropper-buttons .upload {
text-align: left;
padding-left: 50rpx;
}
.cropper-buttons .getCropperImage {
text-align: right;
padding-right: 50rpx;
}
</style>

File diff suppressed because it is too large Load Diff

View File

@@ -1,244 +0,0 @@
<template>
<view class="u-avatar" :style="[wrapStyle]" @tap="click">
<image
@error="loadError"
:style="[imgStyle]"
class="u-avatar__img"
v-if="!uText && avatar"
:src="avatar"
:mode="imgMode"
></image>
<text class="u-line-1" v-else-if="uText" :style="{
fontSize: '38rpx'
}">{{uText}}</text>
<slot v-else></slot>
<view class="u-avatar__sex" v-if="showSex" :class="['u-avatar__sex--' + sexIcon]" :style="[uSexStyle]">
<u-icon :name="sexIcon" size="20"></u-icon>
</view>
<view class="u-avatar__level" v-if="showLevel" :style="[uLevelStyle]">
<u-icon :name="levelIcon" size="20"></u-icon>
</view>
</view>
</template>
<script>
let base64Avatar = "data:image/jpg;base64,/9j/4QAYRXhpZgAASUkqAAgAAAAAAAAAAAAAAP/sABFEdWNreQABAAQAAAA8AAD/4QMraHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLwA8P3hwYWNrZXQgYmVnaW49Iu+7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI/PiA8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJBZG9iZSBYTVAgQ29yZSA1LjMtYzAxMSA2Ni4xNDU2NjEsIDIwMTIvMDIvMDYtMTQ6NTY6MjcgICAgICAgICI+IDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+IDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bXA6Q3JlYXRvclRvb2w9IkFkb2JlIFBob3Rvc2hvcCBDUzYgKFdpbmRvd3MpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjREMEQwRkY0RjgwNDExRUE5OTY2RDgxODY3NkJFODMxIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjREMEQwRkY1RjgwNDExRUE5OTY2RDgxODY3NkJFODMxIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6NEQwRDBGRjJGODA0MTFFQTk5NjZEODE4Njc2QkU4MzEiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6NEQwRDBGRjNGODA0MTFFQTk5NjZEODE4Njc2QkU4MzEiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz7/7gAOQWRvYmUAZMAAAAAB/9sAhAAGBAQEBQQGBQUGCQYFBgkLCAYGCAsMCgoLCgoMEAwMDAwMDBAMDg8QDw4MExMUFBMTHBsbGxwfHx8fHx8fHx8fAQcHBw0MDRgQEBgaFREVGh8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx//wAARCADIAMgDAREAAhEBAxEB/8QAcQABAQEAAwEBAAAAAAAAAAAAAAUEAQMGAgcBAQAAAAAAAAAAAAAAAAAAAAAQAAIBAwICBgkDBQAAAAAAAAABAhEDBCEFMVFBYXGREiKBscHRMkJSEyOh4XLxYjNDFBEBAAAAAAAAAAAAAAAAAAAAAP/aAAwDAQACEQMRAD8A/fAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHbHFyZ/Dam+yLA+Z2L0Pjtyj2poD4AAAAAAAAAAAAAAAAAAAAAAAAKWFs9y6lcvvwQeqj8z9wFaziY1n/HbUX9XF97A7QAGXI23EvJ1goyfzR0YEfN269jeZ+a03pNe0DIAAAAAAAAAAAAAAAAAAAACvtO3RcVkXlWutuL9YFYAAAAAOJRjKLjJVi9GmB5/csH/mu1h/in8PU+QGMAAAAAAAAAAAAAAAAAAaMDG/6MmMH8C80+xAelSSVFolwQAAAAAAAHVlWI37ErUulaPk+hgeYnCUJuElSUXRrrQHAAAAAAAAAAAAAAAAABa2Oz4bM7r4zdF2ICmAAAAAAAAAg7zZ8GX41wuJP0rRgYAAAAAAAAAAAAAAAAAD0m2R8ODaXU33tsDSAAAAAAAAAlb9HyWZcnJd9PcBHAAAAAAAAAAAAAAAAAPS7e64Vn+KA0AAAAAAAAAJm+v8Ftf3ewCKAAAAAAAAAAAAAAAAAX9muqeGo9NttP06+0DcAAAAAAAAAjb7dTu2ra+VOT9P8AQCWAAAAAAAAAAAAAAAAAUNmyPt5Ltv4bui/kuAF0AAAAAAADiUlGLlJ0SVW+oDzOXfd/Ind6JPRdS0QHSAAAAAAAAAAAAAAAAAE2nVaNcGB6Lbs6OTao9LsF51z60BrAAAAAABJ3jOVHjW3r/sa9QEgAAAAAAAAAAAAAAAAAAAPu1duWriuW34ZR4MC9hbnZyEoy8l36XwfYBsAAADaSq9EuLAlZ+7xSdrGdW9Hc5dgEdtt1erfFgAAAAAAAAAAAAAAAAADVjbblX6NR8MH80tEBRs7HYivyzlN8lovaBPzduvY0m6eK10TXtAyAarO55lpJK54orolr+4GqO/Xaea1FvqbXvA+Z77kNeW3GPbV+4DJfzcm/pcm3H6Vou5AdAFLC2ed2Pjv1txa8sV8T6wOL+yZEKu1JXFy4MDBOE4ScZxcZLinoB8gAAAAAAAAAAAB242LeyJ+C3GvN9C7QLmJtePYpKS+5c+p8F2IDYAANJqj1T4oCfk7Nj3G5Wn9qXJax7gJ93Z82D8sVNc4v30A6Xg5i42Z+iLfqARwcyT0sz9MWvWBps7LlTf5Grce9/oBTxdtxseklHxT+uWr9AGoAB138ezfj4bsFJdD6V2MCPm7RdtJzs1uW1xXzL3gTgAAAAAAAAADRhYc8q74I6RWs5ckB6GxYtWLat21SK731sDsAAAAAAAAAAAAAAAASt021NO/YjrxuQXT1oCOAAAAAAABzGLlJRSq26JAelwsWONYjbXxcZvmwO8AAAAAAAAAAAAAAAAAAef3TEWPkVivx3NY9T6UBiAAAAAABo2+VmGXblddIJ8eivRUD0oAAAAAAAAAAAAAAAAAAAYt4tKeFKVNYNSXfRgefAAAAAAAAr7VuSSWPedKaW5v1MCsAAAAAAAAAAAAAAAAAAIe6bj96Ts2n+JPzSXzP3ATgAAAAAAAAFbbt1UUrOQ9FpC4/UwK6aaqtU+DAAAAAAAAAAAAAAA4lKMIuUmoxWrb4ARNx3R3q2rLpa4Sl0y/YCcAAAAAAAAAAANmFud7G8r89r6X0dgFvGzLGRGtuWvTF6NAdwAAAAAAAAAAAy5W442PVN+K59EePp5ARMvOv5MvO6QXCC4AZwAAAAAAAAAAAAAcxlKLUotprg1owN+PvORborq+7Hnwl3gUbO74VzRydt8pKn68ANcJwmqwkpLmnUDkAAAAfNy9atqtyagut0AxXt5xIV8Fbj6lRd7Am5G65V6qUvtwfyx94GMAAAAAAAAAAAAAAAAAAAOU2nVOj5gdsc3LiqRvTpyqwOxbnnrhdfpSfrQB7pnv/AGvuS9gHXPMy5/Fem1yq0v0A6W29XqwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAf//Z";
/**
* avatar 头像
* @description 本组件一般用于展示头像的地方,如个人中心,或者评论列表页的用户头像展示等场所。
* @tutorial https://www.uviewui.com/components/avatar.html
* @property {String} bg-color 背景颜色,一般显示文字时用(默认#ffffff
* @property {String} src 头像路径,如加载失败,将会显示默认头像
* @property {String Number} size 头像尺寸,可以为指定字符串(large, default, mini)或者数值单位rpx默认default
* @property {String} mode 显示类型见上方说明默认circle
* @property {String} sex-icon 性别图标man-男woman-女默认man
* @property {String} level-icon 等级图标默认level
* @property {String} sex-bg-color 性别图标背景颜色
* @property {String} level-bg-color 等级图标背景颜色
* @property {String} show-sex 是否显示性别图标默认false
* @property {String} show-level 是否显示等级图标默认false
* @property {String} img-mode 头像图片的裁剪类型与uni的image组件的mode参数一致如效果达不到需求可尝试传widthFix值默认aspectFill
* @property {String} index 用户传递的标识符值如果是列表循环可穿v-for的index值
* @event {Function} click 头像被点击
* @example <u-avatar :src="src"></u-avatar>
*/
export default {
name: 'u-avatar',
props: {
// 背景颜色
bgColor: {
type: String,
default: 'transparent'
},
// 头像路径
src: {
type: String,
default: ''
},
// 尺寸large-大default-中等mini-小如果为数值则单位为rpx
// 宽度等于高度
size: {
type: [String, Number],
default: 'default'
},
// 头像模型square-带圆角方形circle-圆形
mode: {
type: String,
default: 'circle'
},
// 文字内容
text: {
type: String,
default: ''
},
// 图片的裁剪模型
imgMode: {
type: String,
default: 'aspectFill'
},
// 标识符
index: {
type: [String, Number],
default: ''
},
// 右上角性别角标man-男woman-女
sexIcon: {
type: String,
default: 'man'
},
// 右下角的等级图标
levelIcon: {
type: String,
default: 'level'
},
// 右下角等级图标背景颜色
levelBgColor: {
type: String,
default: ''
},
// 右上角性别图标的背景颜色
sexBgColor: {
type: String,
default: ''
},
// 是否显示性别图标
showSex: {
type: Boolean,
default: false
},
// 是否显示等级图标
showLevel: {
type: Boolean,
default: false
}
},
data() {
return {
error: false,
// 头像的地址因为如果加载错误需要赋值为默认图片props值无法修改所以需要一个中间值
avatar: this.src ? this.src : base64Avatar,
}
},
watch: {
src(n) {
// 用户可能会在头像加载失败时,再次修改头像值,所以需要重新赋值
if(!n) {
// 如果传入null或者''或者undefined显示默认头像
this.avatar = base64Avatar;
this.error = true;
} else {
this.avatar = n;
this.error = false;
}
}
},
computed: {
wrapStyle() {
let style = {};
style.height = this.size == 'large' ? '120rpx' : this.size == 'default' ?
'90rpx' : this.size == 'mini' ? '70rpx' : this.size + 'rpx';
style.width = style.height;
style.flex = `0 0 ${style.height}`;
style.backgroundColor = this.bgColor;
style.borderRadius = this.mode == 'circle' ? '500px' : '5px';
if(this.text) style.padding = `0 6rpx`;
return style;
},
imgStyle() {
let style = {};
style.borderRadius = this.mode == 'circle' ? '500px' : '5px';
return style;
},
// 取字符串的第一个字符
uText() {
return String(this.text)[0];
},
// 性别图标的自定义样式
uSexStyle() {
let style = {};
if(this.sexBgColor) style.backgroundColor = this.sexBgColor;
return style;
},
// 等级图标的自定义样式
uLevelStyle() {
let style = {};
if(this.levelBgColor) style.backgroundColor = this.levelBgColor;
return style;
}
},
methods: {
// 图片加载错误时,显示默认头像
loadError() {
this.error = true;
this.avatar = base64Avatar;
},
click() {
this.$emit('click', this.index);
}
}
}
</script>
<style lang="scss" scoped>
@import "../../libs/css/style.components.scss";
.u-avatar {
/* #ifndef APP-NVUE */
display: inline-flex;
/* #endif */
align-items: center;
justify-content: center;
font-size: 28rpx;
color: $u-content-color;
border-radius: 10px;
position: relative;
&__img {
width: 100%;
height: 100%;
}
&__sex {
position: absolute;
width: 32rpx;
color: #ffffff;
height: 32rpx;
@include vue-flex;
justify-content: center;
align-items: center;
border-radius: 100rpx;
top: 5%;
z-index: 1;
right: -7%;
border: 1px #ffffff solid;
&--man {
background-color: $u-type-primary;
}
&--woman {
background-color: $u-type-error;
}
&--none {
background-color: $u-type-warning;
}
}
&__level {
position: absolute;
width: 32rpx;
color: #ffffff;
height: 32rpx;
@include vue-flex;
justify-content: center;
align-items: center;
border-radius: 100rpx;
bottom: 5%;
z-index: 1;
right: -7%;
border: 1px #ffffff solid;
background-color: $u-type-warning;
}
}
</style>

View File

@@ -1,153 +0,0 @@
<template>
<view @tap="backToTop" class="u-back-top" :class="['u-back-top--mode--' + mode]" :style="[{
bottom: bottom + 'rpx',
right: right + 'rpx',
borderRadius: mode == 'circle' ? '10000rpx' : '8rpx',
zIndex: uZIndex,
opacity: opacity
}, customStyle]">
<view class="u-back-top__content" v-if="!$slots.default && !$slots.$default">
<u-icon @click="backToTop" :name="icon" :custom-style="iconStyle"></u-icon>
<view class="u-back-top__content__tips">
{{tips}}
</view>
</view>
<slot v-else />
</view>
</template>
<script>
export default {
name: 'u-back-top',
props: {
// 返回顶部的形状circle-圆形square-方形
mode: {
type: String,
default: 'circle'
},
// 自定义图标
icon: {
type: String,
default: 'arrow-upward'
},
// 提示文字
tips: {
type: String,
default: ''
},
// 返回顶部滚动时间
duration: {
type: [Number, String],
default: 100
},
// 滚动距离
scrollTop: {
type: [Number, String],
default: 0
},
// 距离顶部多少距离显示单位rpx
top: {
type: [Number, String],
default: 400
},
// 返回顶部按钮到底部的距离单位rpx
bottom: {
type: [Number, String],
default: 200
},
// 返回顶部按钮到右边的距离单位rpx
right: {
type: [Number, String],
default: 40
},
// 层级
zIndex: {
type: [Number, String],
default: '9'
},
// 图标的样式,对象形式
iconStyle: {
type: Object,
default() {
return {
color: '#909399',
fontSize: '38rpx'
}
}
},
// 整个组件的样式
customStyle: {
type: Object,
default() {
return {}
}
}
},
watch: {
showBackTop(nVal, oVal) {
// 当组件的显示与隐藏状态发生跳变时,修改组件的层级和不透明度
// 让组件有显示和消失的动画效果如果用v-if控制组件状态将无设置动画效果
if(nVal) {
this.uZIndex = this.zIndex;
this.opacity = 1;
} else {
this.uZIndex = -1;
this.opacity = 0;
}
}
},
computed: {
showBackTop() {
// 由于scrollTop为页面的滚动距离默认为px单位这里将用于传入的top(rpx)值
// 转为px用于比较如果滚动条到顶的距离大于设定的距离就显示返回顶部的按钮
return this.scrollTop > uni.upx2px(this.top);
},
},
data() {
return {
// 不透明度,为了让组件有一个显示和隐藏的过渡动画
opacity: 0,
// 组件的z-index值隐藏时设置为-1就会看不到
uZIndex: -1
}
},
methods: {
backToTop() {
uni.pageScrollTo({
scrollTop: 0,
duration: this.duration
});
}
}
}
</script>
<style lang="scss" scoped>
@import "../../libs/css/style.components.scss";
.u-back-top {
width: 80rpx;
height: 80rpx;
position: fixed;
z-index: 9;
@include vue-flex;
flex-direction: column;
justify-content: center;
background-color: #E1E1E1;
color: $u-content-color;
align-items: center;
transition: opacity 0.4s;
&__content {
@include vue-flex;
flex-direction: column;
align-items: center;
&__tips {
font-size: 24rpx;
transform: scale(0.8);
line-height: 1;
}
}
}
</style>

Some files were not shown because too many files have changed in this diff Show More