[商城整个模块,及个人中心相应的模块调整]

This commit is contained in:
2021-10-27 14:18:46 +08:00
parent e6181694d2
commit 2c1f11afd7
77 changed files with 14646 additions and 46 deletions

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

@@ -17,7 +17,7 @@
</view>
<view class="sales">
<slot name="statistics" :value="item">
{{item.sales}}
{{item.sales}}
</slot>
</view>
</view>

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: $main-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: $main-color;
font-size: $title-size*0.8;
font-weight: 400;
padding: 0 30rpx;
}
}
</style>

View File

@@ -0,0 +1,178 @@
<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{
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
box-sizing: border-box;
width: 100%;
.copy{
color: $main-color;
font-size: $title-size*0.8;
font-weight: 400;
padding: 0 30rpx;
}
}
</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>