submit
This commit is contained in:
parent
2742c317ee
commit
5f37e71be3
111
components/fl-image-show/fl-image-show.vue
Normal file
111
components/fl-image-show/fl-image-show.vue
Normal file
@ -0,0 +1,111 @@
|
||||
<template>
|
||||
<view>
|
||||
<u-popup :closeable="true"
|
||||
:show="showImg"
|
||||
mode="center"
|
||||
@close="dialogClose">
|
||||
<view style="height: 1130rpx;width:684rpx"
|
||||
class="row items-center justify-center">
|
||||
<u--image :src="imageUrlArr[activeIdx]"
|
||||
style="margin-top:70rpx"
|
||||
width="606rpx"
|
||||
height="938rpx"></u--image>
|
||||
|
||||
<view class="col-10 fl-mt-xs row items-center fl-mb-md">
|
||||
<view style="border-radius:4rpx;width:30rpx;height:30rpx;background: #EBEBEB;"
|
||||
class="row items-center justify-center">
|
||||
<u-image src="../../static/arrow-left.png"
|
||||
width="10rpx"
|
||||
height="20rpx"
|
||||
style="margin-right:10rpx"
|
||||
@click="handleLeftClick"></u-image>
|
||||
</view>
|
||||
|
||||
<view style="width:calc(100% - 80rpx);flex-flow: nowrap;overflow: auto;"
|
||||
class="row">
|
||||
<u-image v-for="(img,imgIdx) in imageUrlArr"
|
||||
:key="imgIdx"
|
||||
:src="img"
|
||||
style="margin: 8rpx 0 0 16rpx"
|
||||
width="60rpx"
|
||||
height="60rpx"
|
||||
@click="activeIdx=imgIdx"></u-image>
|
||||
</view>
|
||||
|
||||
<u-image src="../../static/arrow-right.png"
|
||||
width="30rpx"
|
||||
height="30rpx"
|
||||
style="margin-left:10rpx"
|
||||
@click="handleRightClick"></u-image>
|
||||
</view>
|
||||
</view>
|
||||
</u-popup>
|
||||
|
||||
</view>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
pimageUrl: String,
|
||||
pimageUrlArr: Array,
|
||||
pactiveIdx: Number,
|
||||
pshowImg: Boolean,
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
showImg: false,
|
||||
activeIdx: 0,
|
||||
imageUrlArr: [],
|
||||
};
|
||||
},
|
||||
created () {
|
||||
this.imageUrlArr = this.pimageUrlArr;
|
||||
this.activeIdx = this.pactiveIdx;
|
||||
},
|
||||
watch: {
|
||||
pimageUrlArr () {
|
||||
this.imageUrlArr = this.pimageUrlArr;
|
||||
},
|
||||
pactiveIdx () {
|
||||
this.activeIdx = this.pactiveIdx;
|
||||
},
|
||||
pshowImg () {
|
||||
this.showImg = this.pshowImg;
|
||||
},
|
||||
activeIdx () {
|
||||
this.$emit("triggerShowActiveImgChange", this.activeIdx);
|
||||
},
|
||||
},
|
||||
onShow () {
|
||||
this.showImg = false
|
||||
},
|
||||
methods: {
|
||||
dialogClose () {
|
||||
this.showImg = false;
|
||||
this.$emit("triggerShowImgClose");
|
||||
},
|
||||
handleLeftClick () {
|
||||
if (this.activeIdx > 0) {
|
||||
this.activeIdx = this.activeIdx - 1
|
||||
}
|
||||
},
|
||||
handleRightClick () {
|
||||
if (this.activeIdx < this.imageUrlArr.length - 1) {
|
||||
this.activeIdx = this.activeIdx + 1
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
::v-deep .u-popup__content__close--top-right {
|
||||
border-radius: 50%;
|
||||
border: solid 1px #777171;
|
||||
padding: 3px;
|
||||
top: 8px;
|
||||
right: 15px;
|
||||
}
|
||||
</style>
|
52
components/fl-input-number/fl-input-number.vue
Normal file
52
components/fl-input-number/fl-input-number.vue
Normal file
@ -0,0 +1,52 @@
|
||||
<template>
|
||||
<u-input type="number"
|
||||
v-model="value"
|
||||
:placeholder="placeholder"
|
||||
:border="border"
|
||||
:readonly="readonly"
|
||||
:disabled="disabled"
|
||||
clearable
|
||||
@blur="handleBlur"
|
||||
@change="handleChange"
|
||||
@focus="handleFocus" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
border: String,
|
||||
placeholder: String,
|
||||
readonly: Boolean,
|
||||
disabled: Boolean,
|
||||
val: [Number, String],
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
value: null,
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
val () {
|
||||
this.value = this.val;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
handleBlur (e) {
|
||||
this.$emit("triggerInputBlue", e);
|
||||
},
|
||||
handleFocus (e) {
|
||||
this.$emit("triggerInputFocus", e);
|
||||
},
|
||||
handleChange (e) {
|
||||
if (Number(e)) {
|
||||
let val = parseInt(e);
|
||||
this.$emit("triggerInputChange", val);
|
||||
return;
|
||||
}
|
||||
this.$emit("triggerInputChange", e);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
74
components/fl-page-header/fl-page-header.vue
Normal file
74
components/fl-page-header/fl-page-header.vue
Normal file
@ -0,0 +1,74 @@
|
||||
<template>
|
||||
<view>
|
||||
<view class="status_bar">
|
||||
<!-- 这里是状态栏 -->
|
||||
</view>
|
||||
<view style="height: 110upx">
|
||||
<u-navbar :bgColor="bgColor"
|
||||
@rightClick="rightClick"
|
||||
:autoBack="autoback">
|
||||
<view v-if="left"
|
||||
slot="left">
|
||||
<slot name="left"></slot>
|
||||
</view>
|
||||
|
||||
<view v-if="center"
|
||||
slot="center">
|
||||
<slot name="center"></slot>
|
||||
</view>
|
||||
|
||||
<view v-if="right"
|
||||
slot="right">
|
||||
<slot name="right"></slot>
|
||||
</view>
|
||||
</u-navbar>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
left: {
|
||||
type: Boolean,
|
||||
default () {
|
||||
return true;
|
||||
},
|
||||
},
|
||||
center: {
|
||||
type: Boolean,
|
||||
default () {
|
||||
return true;
|
||||
},
|
||||
},
|
||||
right: {
|
||||
type: Boolean,
|
||||
default () {
|
||||
return true;
|
||||
},
|
||||
},
|
||||
autoback: {
|
||||
type: Boolean,
|
||||
default () {
|
||||
return true;
|
||||
},
|
||||
},
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
bgColor: "null",
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
leftClick () { },
|
||||
rightClick () { },
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
::v-deep .u-navbar__content {
|
||||
background: none !important;
|
||||
}
|
||||
</style>
|
93
components/fl-tabbar/fl-tabbar.vue
Normal file
93
components/fl-tabbar/fl-tabbar.vue
Normal file
@ -0,0 +1,93 @@
|
||||
<template>
|
||||
<view>
|
||||
<view class="status_bar">
|
||||
<!-- 这里是状态栏 -->
|
||||
</view>
|
||||
<u-tabbar :value="current"
|
||||
@change="changeTab"
|
||||
:fixed="true"
|
||||
:placeholder="false"
|
||||
:safeAreaInsetBottom="true"
|
||||
:border="false"
|
||||
activeColor="#FFC748"
|
||||
inactiveColor="#1D1D1D">
|
||||
<u-tabbar-item v-for="(item,index) in tabBarList"
|
||||
:key="index"
|
||||
:text="item.text">
|
||||
<image class="u-page__item__slot-icon"
|
||||
slot="inactive-icon"
|
||||
:src="item.iconPath"></image>
|
||||
<image class="u-page__item__slot-icon"
|
||||
slot="active-icon"
|
||||
:src="item.selectedIconPath"></image>
|
||||
</u-tabbar-item>
|
||||
</u-tabbar>
|
||||
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
currentPage: String
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
current: 0,
|
||||
tabBarList: [{
|
||||
pagePath: "pages/home/index",
|
||||
iconPath: "../../static/tabbar/home.png",
|
||||
selectedIconPath: "../../static/tabbar/home-active.png",
|
||||
text: '首页',
|
||||
customIcon: false,
|
||||
},
|
||||
{
|
||||
pagePath: "pages/mine/index",
|
||||
iconPath: "../../static/tabbar/my.png",
|
||||
selectedIconPath: "../../static/tabbar/my-active.png",
|
||||
text: '我的',
|
||||
customIcon: false,
|
||||
}
|
||||
]
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
changeTab (e) {
|
||||
let page = '/' + this.tabBarList[e].pagePath
|
||||
console.log(page);
|
||||
uni.switchTab({
|
||||
url: page,
|
||||
success: () => {
|
||||
},
|
||||
fail: (e) => {
|
||||
console.log(e);
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
created () {
|
||||
//隐藏原生tabbar
|
||||
uni.hideTabBar();
|
||||
// 当前选中的菜单
|
||||
this.tabBarList.forEach((i, index) => {
|
||||
if (i.pagePath == this.currentPage) {
|
||||
this.current = index
|
||||
}
|
||||
})
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.u-page__item__slot-icon {
|
||||
width: 76rpx;
|
||||
height: 76rpx;
|
||||
}
|
||||
|
||||
.u-tabbar /deep/ .u-tabbar--fixed {
|
||||
width: 100%;
|
||||
height: 88rpx;
|
||||
padding: 20px 0;
|
||||
background: #ffffff;
|
||||
}
|
||||
</style>
|
287
components/fl-upload/fl-upload.vue
Normal file
287
components/fl-upload/fl-upload.vue
Normal file
@ -0,0 +1,287 @@
|
||||
<template>
|
||||
<view class="row">
|
||||
<view v-if="fileList.length === 0 && domS"
|
||||
class="row items-center justify-center"
|
||||
:class="uploadClass + ' ' + sfClass"
|
||||
@click="uploadChoose"
|
||||
style="
|
||||
width: 272rpx;
|
||||
height: 160rpx;
|
||||
background-color: #f4f5f7;
|
||||
border-radius: 2px;
|
||||
">
|
||||
<view class="col-12 u-upload__button"
|
||||
:class="uploadClass?'':'cross'">
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<u-upload v-else-if="sfslot"
|
||||
:fileList="fileList"
|
||||
:maxCount="maxCount"
|
||||
:deletable="deletable"
|
||||
:multiple="multiple"
|
||||
:disabled="disabled"
|
||||
:accept="accept"
|
||||
:width="width"
|
||||
:height="height"
|
||||
@afterRead="afterRead"
|
||||
@delete="deletePic">
|
||||
<slot name="imagecontent"></slot>
|
||||
</u-upload>
|
||||
|
||||
<u-upload v-else
|
||||
:class="[uploadClass, 'border-4']"
|
||||
:fileList="fileList"
|
||||
:maxCount="maxCount"
|
||||
:deletable="deletable"
|
||||
:uploadText="uploadText"
|
||||
:multiple="multiple"
|
||||
:disabled="disabled"
|
||||
uploadIcon="plus"
|
||||
uploadIconColor="#3c9cff"
|
||||
:accept="accept"
|
||||
:width="width"
|
||||
:height="height"
|
||||
@afterRead="afterRead"
|
||||
@delete="deletePic">
|
||||
</u-upload>
|
||||
|
||||
<u-toast ref="uToast" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { postDataByParams } from "@/util/axios/index";
|
||||
import { baseUrl } from "@/common/config";
|
||||
|
||||
export default {
|
||||
props: {
|
||||
uploadText: String,
|
||||
deletable: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
uploadUrl: String,
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
val: {
|
||||
type: String,
|
||||
},
|
||||
accept: String,
|
||||
width: {
|
||||
type: [String, Number],
|
||||
default: 80,
|
||||
},
|
||||
height: {
|
||||
type: [String, Number],
|
||||
default: 80,
|
||||
},
|
||||
// 类身份证背景
|
||||
uploadClass: String,
|
||||
// 其他样式
|
||||
sfClass: String,
|
||||
domS: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
sfslot: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
|
||||
created () {
|
||||
if (this.uploadUrl) {
|
||||
this.uploadApi = baseUrl + this.uploadUrl;
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
uploadApi: baseUrl + "api/uploadpic",
|
||||
fileList: [],
|
||||
maxCount: 1,
|
||||
multiple: false,
|
||||
requestErr: ['{"errMsg":"uploadFile:fail timeout","data":" "}', '{"errMsg":"uploadFile:fail","data":" "}']
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
val () {
|
||||
let defalut = this.val;
|
||||
if (!defalut) {
|
||||
defalut = null;
|
||||
}
|
||||
if (defalut) {
|
||||
this.fileList = [];
|
||||
let fileObj = { url: this.accept !== 'video' ? (defalut + '?x-bce-process=image/format,f_webp') : defalut };
|
||||
this.fileList.push(fileObj);
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
// 删除图片
|
||||
deletePic (event) {
|
||||
this[`fileList`].splice(event.index, 1);
|
||||
this.$emit("triggerUploadSuccess", "");
|
||||
},
|
||||
// 新增图片
|
||||
async afterRead (event) {
|
||||
// 当设置 multiple 为 true 时, file 为数组格式,否则为对象格式
|
||||
let lists = [].concat(event.file);
|
||||
if (this.domS) {
|
||||
event.type === "image/png" ? event.type === "image" : event.type;
|
||||
let obj = {
|
||||
name: event.name,
|
||||
size: event.size,
|
||||
thumb: event.path,
|
||||
type: event.type,
|
||||
url: event.path,
|
||||
};
|
||||
lists = [].concat(obj);
|
||||
}
|
||||
let fileListLen = this[`fileList`].length;
|
||||
lists.map((item) => {
|
||||
this[`fileList`].push({
|
||||
...item,
|
||||
status: "uploading",
|
||||
message: "上传中",
|
||||
});
|
||||
});
|
||||
for (let i = 0; i < lists.length; i++) {
|
||||
const result = await this.uploadFilePromise(lists[i].url);
|
||||
if (this.requestErr.includes(result)) {
|
||||
this.$refs.uToast.show({
|
||||
type: "error",
|
||||
message: "上传失败,请稍后再试!",
|
||||
});
|
||||
this.$emit("triggerUploadFailed");
|
||||
}
|
||||
else if (JSON.parse(result).code !== 0) {
|
||||
this.$refs.uToast.show({
|
||||
type: "error",
|
||||
message: "上传失败",
|
||||
});
|
||||
this.$emit("triggerUploadFailed");
|
||||
} else {
|
||||
this.$emit("triggerUploadSuccess", JSON.parse(result).data);
|
||||
}
|
||||
let item = this[`fileList`][fileListLen];
|
||||
this[`fileList`].splice(
|
||||
fileListLen,
|
||||
1,
|
||||
Object.assign(item, {
|
||||
status: this.requestErr.includes(result) ? 'failed' : (JSON.parse(result).code === 0 ? "success" : "failed"),
|
||||
message: "",
|
||||
url: this.accept !== 'video' ? (JSON.parse(result).data + '?x-bce-process=image/format,f_webp') : JSON.parse(result).data,
|
||||
})
|
||||
);
|
||||
fileListLen++;
|
||||
}
|
||||
},
|
||||
uploadFilePromise (url) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const Authorization = uni.getStorageSync("Authorization");
|
||||
let a = uni.uploadFile(
|
||||
{
|
||||
url: this.uploadApi,
|
||||
filePath: url,
|
||||
name: "file",
|
||||
formData: {},
|
||||
header: {
|
||||
Authorization,
|
||||
},
|
||||
success: (res) => {
|
||||
resolve(res.data);
|
||||
},
|
||||
fail: (err) => {
|
||||
Object.assign(err, { data: " " })
|
||||
resolve(JSON.stringify(err));
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
},
|
||||
uploadChoose () {
|
||||
if (this.disabled) {
|
||||
return
|
||||
}
|
||||
if (this.accept === 'video') {
|
||||
uni.chooseVideo({
|
||||
sourceType: ['album', "camera"],
|
||||
maxDuration: 180,
|
||||
success: (res) => {
|
||||
if (!res.tempFile) {
|
||||
res.tempFile = {}
|
||||
res.tempFile.path = res.tempFilePath
|
||||
res.tempFile.name = res.tempFilePath
|
||||
res.tempFile.size = res.size
|
||||
res.tempFile.type = 'video/mp4'
|
||||
} else {
|
||||
res.tempFile.path = res.tempFilePath
|
||||
}
|
||||
this.afterRead(res.tempFile);
|
||||
},
|
||||
fail: (e) => {
|
||||
if (e.errMsg == "chooseVideo:fail No Permission") {
|
||||
return uni.$u.toast('请您在"设置"中手动开启权限,完成上传功能!');
|
||||
}
|
||||
},
|
||||
});
|
||||
return
|
||||
}
|
||||
uni.chooseImage({
|
||||
count: 1, //默认9
|
||||
sizeType: ["original", "compressed"], //可以指定是原图还是压缩图,默认二者都有
|
||||
sourceType: ["album", "camera"], //从相册选择
|
||||
success: (res) => {
|
||||
this.afterRead(res.tempFiles[0]);
|
||||
},
|
||||
fail: (e) => {
|
||||
if (e.errMsg == "chooseImage:fail No Permission") {
|
||||
return uni.$u.toast('请您在"设置"中手动开启权限,完成上传功能!');
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.cross {
|
||||
position: relative;
|
||||
width: 26px;
|
||||
height: 26px;
|
||||
}
|
||||
|
||||
.cross::before,
|
||||
.cross::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 2px;
|
||||
background-color: #3c9cff;
|
||||
}
|
||||
|
||||
.cross::before {
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
|
||||
.cross::after {
|
||||
transform: translateY(-50%) rotate(90deg);
|
||||
}
|
||||
/deep/ .u-upload__button {
|
||||
margin: 0 !important;
|
||||
}
|
||||
/deep/ .u-upload__wrap {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
/deep/ .u-upload__wrap__preview {
|
||||
margin: 0 !important;
|
||||
}
|
||||
</style>
|
463
components/inputSelect/inputSelect.vue
Normal file
463
components/inputSelect/inputSelect.vue
Normal file
@ -0,0 +1,463 @@
|
||||
<template>
|
||||
<view class="superwei-combox"
|
||||
:class="border ? '' : 'superwei-combox__no-border'">
|
||||
<view v-if="label"
|
||||
class="superwei-combox__label"
|
||||
:style="labelStyle">
|
||||
<text>{{ label }}</text>
|
||||
</view>
|
||||
<view class="superwei-combox__input-box">
|
||||
<input class="superwei-combox__input"
|
||||
type="text"
|
||||
:placeholder="placeholder"
|
||||
placeholder-class="superwei-combox__input-plac"
|
||||
v-model="inputVal"
|
||||
@input="onInput"
|
||||
@focus="onFocus"
|
||||
@blur="onBlur" />
|
||||
<uni-icons :type="showSelector ? 'top' : 'bottom'"
|
||||
size="14"
|
||||
color="#999"
|
||||
@click="toggleSelector"
|
||||
v-if="!inputVal"></uni-icons>
|
||||
<image src="../../static/close-icon.png"
|
||||
mode=""
|
||||
style="width: 28upx; height: 28upx"
|
||||
v-if="inputVal"
|
||||
@click="clear"></image>
|
||||
</view>
|
||||
<view class="superwei-combox__selector"
|
||||
v-if="showSelector">
|
||||
<view class="uni-popper__arrow"></view>
|
||||
<scroll-view scroll-y="true"
|
||||
class="superwei-combox__selector-scroll">
|
||||
<view class="superwei-combox__selector-empty"
|
||||
v-if="filterCandidatesLength === 0">
|
||||
<text>{{ emptyTips }}</text>
|
||||
</view>
|
||||
<view class="superwei-combox__selector-item"
|
||||
v-for="(item, index) in filterCandidates"
|
||||
:key="index">
|
||||
<template v-if="isJSON ? (item.disabled ? true : false) : false">
|
||||
<text :style="'color:' + disabledColor + ';cursor: not-allowed;'">{{
|
||||
isJSON
|
||||
? item[keyName]
|
||||
? item[keyName]
|
||||
: "字段" + keyName + "不存在"
|
||||
: item
|
||||
}}</text>
|
||||
</template>
|
||||
<template v-else>
|
||||
<text @click="onSelectorClick(index)"
|
||||
:style="
|
||||
(
|
||||
isJSON
|
||||
? item[keyName]
|
||||
? item[keyName] == inputVal
|
||||
: false
|
||||
: item == inputVal
|
||||
)
|
||||
? 'font-weight: bold;background-color: ' +
|
||||
selectedBackground +
|
||||
';color: ' +
|
||||
selectedColor
|
||||
: ''
|
||||
">{{
|
||||
isJSON
|
||||
? item[keyName]
|
||||
? item[keyName]
|
||||
: "字段" + keyName + "不存在"
|
||||
: item
|
||||
}}</text>
|
||||
</template>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- <view class="search-combox">
|
||||
<view class="uni-combox__input-box" :style="showSelector ?'z-index: 997;': ''">
|
||||
<input class="uni-combox__input" type="text" :placeholder="placeholder" placeholder-class="uni-combox__input-plac"
|
||||
v-model="inputVal" @input="onInput" @focus="onFocus" @blur="onBlur" />
|
||||
<view class="icon-box">
|
||||
<uni-icons :type="showSelector? 'top' : 'bottom'" size="14" color="#fff" @click="toggleSelector" v-if="!inputVal && icon=='icon'"></uni-icons>
|
||||
<image src="../../static/image/order/search.png" mode="" style="width: 28upx;height: 28upx;" v-if="iconShow && icon =='search'" @click="searchGet"></image>
|
||||
<image src="../../static/image/close-icon.png" mode="" style="width: 28upx;height: 28upx;" v-if="inputVal" @click="clear"></image>
|
||||
</view>
|
||||
</view>
|
||||
<view class="uni-combox__selector" v-if="showSelector">
|
||||
<view class="uni-popper__arrow"></view>
|
||||
<scroll-view scroll-y="true" class="uni-combox__selector-scroll">
|
||||
<view class="uni-combox__selector-empty" v-if="searchList.length == 0">
|
||||
<text>{{emptyTips}}</text>
|
||||
</view>
|
||||
<view class="uni-combox__selector-item" v-for="(item,index) in searchList" :key="index" @click="onSelectorClick(index)">
|
||||
<text>{{item.value}}</text>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</view> -->
|
||||
</template>
|
||||
|
||||
<script>
|
||||
/**
|
||||
* Combox 组合输入框
|
||||
* @description 组合输入框一般用于既可以输入也可以选择的场景
|
||||
* @property {String} label 左侧文字
|
||||
* @property {String} labelWidth 左侧内容宽度
|
||||
* @property {String} placeholder 输入框占位符
|
||||
* @property {Array} candidates 候选项列表
|
||||
* @property {String} emptyTips 筛选结果为空时显示的文字
|
||||
* @property {String} value 组合框的值
|
||||
* @property {String} selectedBackground 选中项背景颜色
|
||||
* @property {String} selectedColor 选中项文字颜色
|
||||
* @property {Boolean} isJSON 是否是json数组
|
||||
* @property {String} keyName json数组显示的字段值
|
||||
* @property {String} disabledColor 禁用项文字颜色
|
||||
* @property {Boolean} isAllowCreate 是否允许用户创建新条目
|
||||
*/
|
||||
export default {
|
||||
name: "inputSelect",
|
||||
emits: ["input", "update:modelValue", "select"],
|
||||
props: {
|
||||
isAllowCreate: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
disabledColor: {
|
||||
type: String,
|
||||
default: "#ababac",
|
||||
},
|
||||
isJSON: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
keyName: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
selectedBackground: {
|
||||
type: String,
|
||||
default: "#f5f7fa",
|
||||
},
|
||||
selectedColor: {
|
||||
type: String,
|
||||
default: "#409eff",
|
||||
},
|
||||
border: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
label: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
labelWidth: {
|
||||
type: String,
|
||||
default: "auto",
|
||||
},
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
candidates: {
|
||||
type: Array,
|
||||
default () {
|
||||
return [];
|
||||
},
|
||||
},
|
||||
emptyTips: {
|
||||
type: String,
|
||||
default: "无匹配项",
|
||||
},
|
||||
// #ifndef VUE3
|
||||
value: {
|
||||
type: [String, Number],
|
||||
default: "",
|
||||
},
|
||||
// #endif
|
||||
// #ifdef VUE3
|
||||
modelValue: {
|
||||
type: [String, Number],
|
||||
default: "",
|
||||
},
|
||||
// #endif
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
isInput: false,
|
||||
showSelector: false,
|
||||
isSelector: false,
|
||||
inputVal: "",
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
labelStyle () {
|
||||
if (this.labelWidth === "auto") {
|
||||
return "";
|
||||
}
|
||||
return `width: ${this.labelWidth}`;
|
||||
},
|
||||
filterCandidates () {
|
||||
if (this.isInput) {
|
||||
if (this.isJSON) {
|
||||
return this.candidates.filter((item) => {
|
||||
return item[this.keyName].toString().indexOf(this.inputVal) > -1;
|
||||
});
|
||||
} else {
|
||||
return this.candidates.filter((item) => {
|
||||
return item.toString().indexOf(this.inputVal) > -1;
|
||||
});
|
||||
}
|
||||
} else {
|
||||
return this.candidates;
|
||||
}
|
||||
},
|
||||
filterCandidatesLength () {
|
||||
return this.filterCandidates.length;
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
// #ifndef VUE3
|
||||
value: {
|
||||
handler (newVal) {
|
||||
this.inputVal = newVal;
|
||||
this.isInput = true;
|
||||
},
|
||||
immediate: true,
|
||||
},
|
||||
// #endif
|
||||
// #ifdef VUE3
|
||||
modelValue: {
|
||||
handler (newVal) {
|
||||
this.inputVal = newVal;
|
||||
this.isInput = true;
|
||||
},
|
||||
immediate: true,
|
||||
},
|
||||
// #endif
|
||||
},
|
||||
methods: {
|
||||
toggleSelector () {
|
||||
this.showSelector = !this.showSelector;
|
||||
this.isInput = false;
|
||||
},
|
||||
onFocus () {
|
||||
this.showSelector = true;
|
||||
this.isInput = false;
|
||||
},
|
||||
onChange () {
|
||||
setTimeout(() => {
|
||||
this.showSelector = false;
|
||||
this.isInput = false;
|
||||
}, 200);
|
||||
},
|
||||
onBlur () {
|
||||
if (!this.isInput) {
|
||||
this.onChange();
|
||||
} else {
|
||||
if (this.inputVal && !this.isAllowCreate) {
|
||||
let index = this.candidates.findIndex((item) => {
|
||||
if (this.isJSON) {
|
||||
return (
|
||||
item[this.keyName].toString() == this.inputVal && !item.disabled
|
||||
);
|
||||
} else {
|
||||
return item.toString() == this.inputVal;
|
||||
}
|
||||
});
|
||||
if (index == -1) {
|
||||
if (this.filterCandidatesLength > 0) {
|
||||
setTimeout(() => {
|
||||
this.showSelector = false;
|
||||
this.isInput = false;
|
||||
if (!this.isSelector) {
|
||||
this.inputVal = "";
|
||||
this.$emit("input", this.inputVal);
|
||||
this.$emit("update:modelValue", this.inputVal);
|
||||
}
|
||||
}, 200);
|
||||
this.isSelector = false;
|
||||
} else {
|
||||
this.showSelector = false;
|
||||
this.isInput = false;
|
||||
this.inputVal = "";
|
||||
this.$emit("input", this.inputVal);
|
||||
this.$emit("update:modelValue", this.inputVal);
|
||||
}
|
||||
} else {
|
||||
this.onChange();
|
||||
}
|
||||
} else {
|
||||
this.onChange();
|
||||
}
|
||||
}
|
||||
},
|
||||
onSelectorClick (index) {
|
||||
let item = this.filterCandidates[index];
|
||||
if (this.isJSON) {
|
||||
this.inputVal = item[this.keyName];
|
||||
} else {
|
||||
this.inputVal = item;
|
||||
}
|
||||
this.showSelector = false;
|
||||
this.isSelector = true;
|
||||
this.$emit("input", this.inputVal);
|
||||
this.$emit("update:modelValue", this.inputVal);
|
||||
this.$emit("select", item);
|
||||
},
|
||||
onInput () {
|
||||
setTimeout(() => {
|
||||
this.$emit("input", this.inputVal);
|
||||
this.$emit("update:modelValue", this.inputVal);
|
||||
});
|
||||
},
|
||||
searchGet () {
|
||||
this.iconShow = false;
|
||||
this.$emit("search", true);
|
||||
},
|
||||
clear () {
|
||||
this.inputVal = "";
|
||||
this.iconShow = true;
|
||||
this.$emit("input", this.inputVal);
|
||||
this.$emit("update:modelValue", this.inputVal);
|
||||
this.$emit("select", {});
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.superwei-combox {
|
||||
font-size: 24upx;
|
||||
// border: 1px solid #DCDFE6;
|
||||
position: relative;
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
// height: 40px;
|
||||
flex-direction: row;
|
||||
box-sizing: border-box;
|
||||
align-items: center;
|
||||
border-radius: 32upx;
|
||||
height: 60upx;
|
||||
padding: 0 20upx;
|
||||
background: #ffffff;
|
||||
z-index: 99999999999;
|
||||
// border-bottom: solid 1px #DDDDDD;
|
||||
}
|
||||
|
||||
.superwei-combox__label {
|
||||
font-size: 24upx;
|
||||
line-height: 22px;
|
||||
padding-right: 10px;
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
.superwei-combox__input-box {
|
||||
position: relative;
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex: 1;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.superwei-combox__input {
|
||||
flex: 1;
|
||||
font-size: 24upx;
|
||||
height: 22px;
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
.superwei-combox__input-plac {
|
||||
font-size: 24upx;
|
||||
color: #ccc; //placeholder-style="color:#FFFFFF"
|
||||
}
|
||||
|
||||
.superwei-combox__selector {
|
||||
/* #ifndef APP-NVUE */
|
||||
box-sizing: border-box;
|
||||
/* #endif */
|
||||
position: absolute;
|
||||
top: calc(100% + 12px);
|
||||
left: 0;
|
||||
width: 100%;
|
||||
background-color: #ffffff;
|
||||
border: 1px solid #ebeef5;
|
||||
border-radius: 6px;
|
||||
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
||||
z-index: 2;
|
||||
padding: 4px 0;
|
||||
}
|
||||
|
||||
.superwei-combox__selector-scroll {
|
||||
/* #ifndef APP-NVUE */
|
||||
max-height: 200px;
|
||||
box-sizing: border-box;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.superwei-combox__selector-empty,
|
||||
.superwei-combox__selector-item {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
cursor: pointer;
|
||||
/* #endif */
|
||||
line-height: 36px;
|
||||
font-size: 14px;
|
||||
text-align: center;
|
||||
// border-bottom: solid 1px #DDDDDD;
|
||||
padding: 0px 0px;
|
||||
}
|
||||
|
||||
.superwei-combox__selector-empty text,
|
||||
.superwei-combox__selector-item text {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.superwei-combox__selector-item:hover {
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
|
||||
.superwei-combox__selector-empty:last-child,
|
||||
.superwei-combox__selector-item:last-child {
|
||||
/* #ifndef APP-NVUE */
|
||||
border-bottom: none;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
// picker 弹出层通用的指示小三角
|
||||
.uni-popper__arrow,
|
||||
.uni-popper__arrow::after {
|
||||
position: absolute;
|
||||
display: block;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-color: transparent;
|
||||
border-style: solid;
|
||||
border-width: 6px;
|
||||
}
|
||||
|
||||
.uni-popper__arrow {
|
||||
filter: drop-shadow(0 2px 12px rgba(0, 0, 0, 0.03));
|
||||
top: -6px;
|
||||
left: 10%;
|
||||
margin-right: 3px;
|
||||
border-top-width: 0;
|
||||
border-bottom-color: #ebeef5;
|
||||
}
|
||||
|
||||
.uni-popper__arrow::after {
|
||||
content: " ";
|
||||
top: 1px;
|
||||
margin-left: -6px;
|
||||
border-top-width: 0;
|
||||
border-bottom-color: #fff;
|
||||
}
|
||||
|
||||
.superwei-combox__no-border {
|
||||
border: none;
|
||||
}
|
||||
</style>
|
188
components/mask-guide-uni/mask-guide-uni.vue
Normal file
188
components/mask-guide-uni/mask-guide-uni.vue
Normal file
@ -0,0 +1,188 @@
|
||||
<template>
|
||||
<view>
|
||||
<view v-if="showGuide" class="outer" @click="nextGuide" @touchmove.stop.prevent="moveHandle">
|
||||
<view class="inner" :style="[innerStyle]"></view>
|
||||
<view class="innerText" :style="[innerTextStyle]">
|
||||
<view v-if="nextBtnPosition === 'top' && showNextButton" class="next-btn-wrap">
|
||||
<slot name='nextButton'>
|
||||
<view class="next-btn">我知道啦~</view>
|
||||
</slot>
|
||||
</view>
|
||||
<text :style="[textStyle]">{{innerText}}</text>
|
||||
<view v-if="nextBtnPosition === 'bottom' && showNextButton" class="next-btn-wrap">
|
||||
<slot name='nextButton'>
|
||||
<view class="next-btn">我知道啦~</view>
|
||||
</slot>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "mask-guide-uni",
|
||||
data() {
|
||||
return {
|
||||
innerStyle: {},
|
||||
innerTextStyle: {},
|
||||
guide: 0,
|
||||
showGuide: false,
|
||||
innerText: '',
|
||||
deviceInfo: {},
|
||||
textStyle: {},
|
||||
showNextButton: true,
|
||||
nextBtnPosition: 'top'
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
start(props) {
|
||||
for (let k in props) {
|
||||
this[k] = props[k];
|
||||
};
|
||||
this.deviceInfo = uni.getSystemInfoSync();
|
||||
this.showGuide = true;
|
||||
this.nextGuide();
|
||||
},
|
||||
moveHandle(){
|
||||
},
|
||||
nextGuide() {
|
||||
|
||||
const index = this.guide;
|
||||
uni.createSelectorQuery().select(`#guide-container #guide_${index}`).fields({
|
||||
id: true,
|
||||
dataset: true,
|
||||
rect: true,
|
||||
size: true,
|
||||
scrollOffset: true,
|
||||
context: true,
|
||||
properties: ['scrollX', 'scrollY'],
|
||||
computedStyle: ['borderRadius'],
|
||||
}, data => {
|
||||
if (data) {
|
||||
let {
|
||||
left,
|
||||
right,
|
||||
top,
|
||||
width,
|
||||
height,
|
||||
borderRadius,
|
||||
dataset
|
||||
} = data;
|
||||
//判断是否需要滚动
|
||||
const { windowHeight } = this.deviceInfo;
|
||||
this.innerStyle = {
|
||||
'left': `${left}px`,
|
||||
'top': `${top}px`,
|
||||
'width': `${width}px`,
|
||||
'height': `${height}px`,
|
||||
'borderRadius': borderRadius
|
||||
};
|
||||
//根据位置设置显示的位置
|
||||
const leftRpx = this.pxToRpx(left);
|
||||
let innerTextStyle = {
|
||||
'top': `${top + height + 5}px`,
|
||||
}
|
||||
if(leftRpx > 400){
|
||||
innerTextStyle.textAlign = 'right';
|
||||
innerTextStyle.right = `${750 - this.pxToRpx(right)}rpx`;
|
||||
innerTextStyle.marginLeft = `10px`;
|
||||
}else{
|
||||
innerTextStyle.textAlign = 'left';
|
||||
innerTextStyle.left = `${left}px`;
|
||||
innerTextStyle.marginRight = `10px`;
|
||||
}
|
||||
//如果长度够长 居中显示
|
||||
if(width > 300){
|
||||
innerTextStyle.width = `${width}px`;
|
||||
innerTextStyle.textAlign = 'center';
|
||||
}
|
||||
//内容在可视区域以下
|
||||
if(windowHeight < top){
|
||||
uni.pageScrollTo({
|
||||
scrollTop: top - windowHeight + height + 10,
|
||||
duration: 0
|
||||
});
|
||||
this.innerStyle.top = `${windowHeight - height - 10}px`;
|
||||
}
|
||||
//内容在可视区域以上
|
||||
if(top < 0){
|
||||
uni.pageScrollTo({
|
||||
scrollTop: top,
|
||||
duration: 0
|
||||
});
|
||||
this.nextGuide();
|
||||
return;
|
||||
}
|
||||
//如果在可视区域下方,提示文字显示在上方
|
||||
if(parseFloat(this.innerStyle.top) > windowHeight / 2){
|
||||
innerTextStyle.bottom = `${windowHeight - parseFloat(this.innerStyle.top) + 10}px`;
|
||||
delete innerTextStyle.top;
|
||||
this.nextBtnPosition = 'top';
|
||||
}else{
|
||||
this.nextBtnPosition = 'bottom';
|
||||
}
|
||||
this.innerTextStyle = innerTextStyle;
|
||||
this.innerText = dataset.guideText ?? '';
|
||||
|
||||
this.guide++;
|
||||
} else {
|
||||
this.showGuide = false;
|
||||
this.$emit('update:showGuide', this.showGuide);
|
||||
uni.pageScrollTo({
|
||||
scrollTop: 0,
|
||||
duration: 0
|
||||
});
|
||||
this.guide = 0;
|
||||
}
|
||||
}).exec()
|
||||
},
|
||||
pxToRpx(val){
|
||||
return val/(uni.upx2px(100)/100);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.outer {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
background: transparent;
|
||||
overflow: hidden;
|
||||
z-index: 99999;
|
||||
}
|
||||
|
||||
.inner {
|
||||
position: absolute;
|
||||
box-shadow: rgba(0, 0, 0, .8) 0 0 0 2021px;
|
||||
z-index: 99999;
|
||||
}
|
||||
.innerText {
|
||||
color: #fff;
|
||||
position: absolute;
|
||||
z-index: 99999;
|
||||
font-size: 28rpx;
|
||||
letter-spacing: 2rpx;
|
||||
text-align: center;
|
||||
}
|
||||
.next-btn-wrap{
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
.next-btn{
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 60rpx;
|
||||
padding: 0 30rpx;
|
||||
border: 2rpx solid #ddd;
|
||||
border-radius: 10rpx;
|
||||
margin: 10rpx;
|
||||
font-size: 26rpx;
|
||||
}
|
||||
</style>
|
113
components/page-nav/page-nav.vue
Normal file
113
components/page-nav/page-nav.vue
Normal file
@ -0,0 +1,113 @@
|
||||
<template>
|
||||
<view class="nav-wrap">
|
||||
<view class="nav-title">
|
||||
<u--image :showLoading="true" src="https://cdn.uviewui.com/uview/common/logo.png" width="70px"
|
||||
height="70px" />
|
||||
<view class="nav-info">
|
||||
<view class="nav-info__title" @tap="jumpToWx">
|
||||
<text class="nav-info__title__text">uView {{version}}</text>
|
||||
<!-- #ifdef MP-WEIXIN -->
|
||||
<!-- uni-app不支持text内部的text组件的tap事件,所以放到外部响应tap -->
|
||||
<text class="nav-info__title__jump">查看1.x演示</text>
|
||||
<!-- #endif -->
|
||||
</view>
|
||||
<text class="nav-slogan">多平台快速开发的UI框架</text>
|
||||
</view>
|
||||
</view>
|
||||
<text class="nav-desc">{{desc}}</text>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
desc: String,
|
||||
title: String,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
version: uni.$u.config.v
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
jumpToWx() {
|
||||
// #ifdef MP-WEIXIN
|
||||
uni.navigateToMiniProgram({
|
||||
appId: 'wx3be833c4a263e0c2'
|
||||
})
|
||||
// #endif
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.nav-wrap {
|
||||
padding: 15px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.lang {
|
||||
position: absolute;
|
||||
top: 15px;
|
||||
right: 15px;
|
||||
}
|
||||
|
||||
.nav-title {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.nav-info {
|
||||
margin-left: 15px;
|
||||
|
||||
&__title {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
|
||||
&__text {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
color: $u-main-color;
|
||||
font-size: 25px;
|
||||
font-weight: bold;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
&__jump {
|
||||
font-size: 12px;
|
||||
color: $u-primary;
|
||||
font-weight: normal;
|
||||
margin-left: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.logo {
|
||||
width: 70px;
|
||||
height: 70px;
|
||||
/* #ifndef APP-NVUE */
|
||||
height: auto;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.nav-slogan {
|
||||
color: $u-tips-color;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.nav-desc {
|
||||
margin-top: 10px;
|
||||
font-size: 14px;
|
||||
color: $u-content-color;
|
||||
line-height: 20px;
|
||||
}
|
||||
</style>
|
321
components/yixuan-selectAddress/yixuan-selectAddress.vue
Normal file
321
components/yixuan-selectAddress/yixuan-selectAddress.vue
Normal file
@ -0,0 +1,321 @@
|
||||
<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 }}</text>
|
||||
</view>
|
||||
<view class="indicator"
|
||||
:style="{ left: indicatorStyleLeft + 'px' }"
|
||||
ref="indicator"></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)">
|
||||
<image v-if="selectIndexArr[swiper_index] === index"
|
||||
class="address_item_icon"
|
||||
src="../../static/yixuan-selectAddress/gou.png"
|
||||
mode=""></image>
|
||||
{{ item.name }}
|
||||
</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 {
|
||||
props: {
|
||||
limit: {
|
||||
type: String,
|
||||
},
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
isShow: false,
|
||||
isShowMask: false,
|
||||
dataList: ["请选择"],
|
||||
currentIndex: 0,
|
||||
cityData: {},
|
||||
cityAreaArray: [],
|
||||
selectIndexArr: [],
|
||||
indicatorStyleLeft: 16,
|
||||
};
|
||||
},
|
||||
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 itemWidth = this.$refs.select_top_item[index].$children[0].$el.offsetWidth
|
||||
if (itemWidth > 80){
|
||||
itemWidth = 80
|
||||
}
|
||||
let itemCenterX = 10 + index * 80 + itemWidth / 2
|
||||
let indicatorWidth = this.$refs.indicator.$el.offsetWidth
|
||||
this.$refs.indicator.$el.style.left = itemCenterX - indicatorWidth / 2 + 'px'
|
||||
*/
|
||||
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;
|
||||
|
||||
this.indicatorStyleLeft = left;
|
||||
}
|
||||
)
|
||||
.exec();
|
||||
},
|
||||
address_item_click (swiper_index, index) {
|
||||
// console.log(swiper_index,index)
|
||||
this.selectIndexArr.splice(swiper_index, 5, index);
|
||||
|
||||
//判断当前是否为最下一级
|
||||
if (swiper_index === 0) {
|
||||
//第一级
|
||||
|
||||
let currentObj = this.cityData[index];
|
||||
let city = currentObj.name;
|
||||
this.dataList.splice(swiper_index, 5, city);
|
||||
this.dataList.splice(swiper_index + 1, 0, "请选择");
|
||||
this.cityAreaArray.splice(swiper_index + 1, 1, currentObj["city"]);
|
||||
setTimeout(() => {
|
||||
this.currentIndex = 1;
|
||||
this.changeIndicator(1);
|
||||
}, 50);
|
||||
} else {
|
||||
let currentAreaArray = this.cityAreaArray[swiper_index];
|
||||
let currentObj = currentAreaArray[index];
|
||||
let area = currentObj["area"];
|
||||
if (this.limit === 'city') {
|
||||
area = undefined
|
||||
}
|
||||
if (area !== undefined) {
|
||||
let city = currentObj.name;
|
||||
|
||||
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 = currentObj.name;
|
||||
this.dataList.splice(swiper_index, 1, city);
|
||||
|
||||
//选择成功返回数据
|
||||
this.$emit("selectAddress", this.dataList);
|
||||
console.log("", 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);
|
||||
},
|
||||
mounted () {
|
||||
// this.changeIndicator(0)
|
||||
},
|
||||
};
|
||||
</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: 80%;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
border-top-left-radius: 20px;
|
||||
border-top-right-radius: 20px;
|
||||
.title_view {
|
||||
height: 12%;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 0 $uni-spacing-row-sm;
|
||||
.title {
|
||||
font-size: uni-font-size-sm;
|
||||
}
|
||||
.close_view {
|
||||
height: 60px;
|
||||
width: 60px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
.select_top {
|
||||
height: 8%;
|
||||
display: flex;
|
||||
justify-content: start;
|
||||
align-items: center;
|
||||
padding: 10px;
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
.select_top_item {
|
||||
width: 80px;
|
||||
font-size: 14px;
|
||||
@include no-wrap();
|
||||
}
|
||||
.indicator {
|
||||
position: absolute;
|
||||
width: 30px;
|
||||
height: 2px;
|
||||
background: $uni-color-error;
|
||||
left: 16px;
|
||||
bottom: 0;
|
||||
transition: left 0.5s ease;
|
||||
}
|
||||
}
|
||||
.swiper {
|
||||
height: 80%;
|
||||
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: 5px 0;
|
||||
font-size: 14px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.address_item_icon {
|
||||
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>
|
Loading…
Reference in New Issue
Block a user