xuminyi
xingyy 1 year ago
parent 2742c317ee
commit 5f37e71be3

@ -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>

@ -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>

@ -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>

@ -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>

@ -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>

@ -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>

@ -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>

@ -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>

@ -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…
Cancel
Save