This commit is contained in:
18500206848
2024-02-02 14:40:26 +08:00
parent 21a84c3035
commit 8964c6983f
253 changed files with 0 additions and 25212 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 804 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 761 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

View File

@@ -1,154 +0,0 @@
//搜索
<template lang='pug'>
view.item-out-view
view.search-view
view.search-item
image(src='../../static/img/search.svg')
input(
v-model="inputValue"
@input='onInputListen'
:placeholder='placeholder'
:placeholder-class='placeholderClass')
view.search-content(
v-if="historyDatas&&historyDatas.length>0&&inputValue.length<=0")
view.title-view
text 搜索历史
image(src='./icon_delete.png' @tap.stop='onDelete(ALL)')
view.item-view(v-for="(item,index) in historyDatas" :key="index" @tap.stop='onItemClick(item,index)')
text {{item.key}}
image(src='./icon_close.png' @tap.stop='onDelete(index)')
view.search-content(v-if="keyworkDatas&&keyworkDatas.length>0")
view.item-view(v-for="(item,index) in keyworkDatas" :key="index" @tap.stop='onItemClick(item,index)')
text(v-for="textContent in item.keyword"
:key="item.id"
:class="textContent===inputValue?'__vital':''") {{textContent}}
</template>
<script>
export default {
data() {
return {
inputValue: '',
ALL: 'ALL',
SEARCH_DATA: 'SEARCH_DATA'
}
},
props: {
//搜索历史内容
historyDatas: {
type: Array,
default: () => {
return [];
}
},
//搜索关键内容
keyworkDatas: {
type: Array,
default: () => {
return [];
}
},
placeholder: {
type: String,
default: '请输入搜索内容'
},
},
methods: {
//监听输入框内容变化
onInputListen(event) {
let detail = event.detail;
let value = detail.value;
this.inputValue = value;
this.$emit('onInputListen', value);
},
//清除搜索历史
onDelete(event) {
this.$emit('onDelete', event);
},
//列表点击事件
onItemClick(item, index) {
this.$emit('onItemClick', {
item,
index
});
}
},
}
</script>
<style scoped lang='scss'>
.item-out-view {
flex-direction: column;
.search-view {
border-bottom: 1rpx solid #dddddd;
flex-direction: column;
padding: 10rpx 32rpx;
background: rgba(255, 255, 255, 1);
.search-item {
width: 80%;
padding: 0 24rpx;
height: 60rpx;
line-height: 60rpx;
background: rgba(249, 249, 249, 1);
border-radius: 200px;
align-items: center;
input {
padding: 0 24rpx;
height: 80rpx;
font-weight: 400;
flex: 1;
text-align: start;
font-size: 28rpx;
font-family: PingFang-SC-Bold, PingFang-SC;
color: rgba(51, 51, 51, 1);
}
.placeholderClass {
color: #CCCCCC;
}
image {
height: 32rpx;
width: 32rpx;
}
}
.search-content {
padding: 40rpx 0;
flex-direction: column;
.title-view {
text {
color: rgba(51, 51, 51, 1);
}
}
.item-view {
align-items: center;
width: 100%;
padding: 32rpx 0;
border-bottom: 1px solid rgba(245, 245, 245, 1);
text {
color: rgba(102, 102, 102, 1);
}
.next-ico {
width: 24rpx;
height: 24rpx;
}
.__vital {
color: rgba(51, 130, 255, 1);
}
}
image {
margin-left: auto;
width: 44rpx;
height: 44rpx;
}
}
text {
font-size: 28rpx;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
}
view {
flex-direction: row;
display: flex;
}
}
}
</style>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 858 B

View File

@@ -1,208 +0,0 @@
<template>
<view class="body" @click="goInfo(companyitem.missionNo)">
<view class="heads">
<view class="head_left">
<rich-text :nodes="string">
</rich-text>
</view>
<view class="head_right">
{{companyitem.wage}}{{wageUnit[companyitem.wageUnitCategory]}}
</view>
</view>
<view class="ask">
<view class="askList" v-for="(item,index) in skillNames" :key="index">
{{item}}
</view>
</view>
<view class="allName">
{{companyitem.companyName}}
</view>
<view class="timeAddress">
<view>
报名截止日期{{dateFormat(companyitem.etimePub)}}
</view>
<view v-if="near">
{{companyitem.distanceStr}}km
</view>
<view v-else>
{{getCity(companyitem.cityId)}}
</view>
</view>
<view class="comment" v-if='comment' @tap.stop="goComment(companyitem.missionNo)">
<view class="comment_content commentimg" v-if='companyitem.scoreAll>0'>
<image class="commentimg_image" src="../../static/img/star.full.svg" v-for="index1 in companyitem.scoreAll" mode=""
:key="index1"></image>
<image class="commentimg_image" src="../../static/img/star.empty.svg" v-for="index2 in (5-companyitem.scoreAll)"
mode="" :key="index2"></image>
</view>
<view class="comment_content allName gocomment" v-else>
评价
</view>
</view>
</view>
</template>
<script>
import {
toDoller,
dateFormat
} from "../../untils/format.js";
import dictionary from '@/common/textdata.js';
export default {
beforeCreate: function() {},
props: {
companyitem: {
type: Object,
default(){ return [] }
},
comment: {
type: Boolean,
default: false
},
noApply: {
type: Boolean,
default: true
},
near: {
type: Boolean,
default: false
}
},
data() {
return {
...dictionary,
string: "<div style='overflow: hidden;white-space: nowrap;text-overflow: ellipsis;'>" + this.companyitem.missionTitle +
"</div>"
};
},
computed: {
skillNames() {
return this.companyitem.skillNames.split(',')
}
},
methods: {
goComment: function(no) {
uni.navigateTo({
url: `../../pageMy/mycomment/mycomment?missionNo=${encodeURIComponent(no)}`
})
},
goInfo: function(no) {
const isCan = this.noApply === false ? '0' : '1'
uni.navigateTo({
url: `/pages/projectInfo/projectInfo?missionNo=${encodeURIComponent(no)}&isCan=${isCan}`
})
},
getCity: function(val) {
if (val) {
let areas = this.$store.getters.getAreaParents(val)
if (areas.length === 3) {
return areas[0].label + '-' + areas[1].label + '-' + areas[2].label
}
}
},
toDoller,
dateFormat
}
}
</script>
<style>
.commentimg_image {
width: 40rpx;
height: 40rpx;
}
.commentimg {
display: flex;
align-items: center;
justify-content: flex-end;
}
.gocomment {
font-size: 26rpx !important;
border-radius: 5rpx;
border: 1rpx solid #c3c3c3;
width: 160rpx;
text-align: center;
float: right;
height: 50rpx;
line-height: 50rpx;
}
.timeAddress {
display: flex;
align-items: center;
justify-content: space-between;
font-family: PingFangSC-Regular;
font-size: 24rpx;
color: #999999;
margin: 10rpx 0;
}
.allName {
font-family: PingFangSC-Regular;
font-size: 28rpx;
color: #666666;
}
.askList {
width: 14%;
font-family: PingFangSC-Regular;
font-size: 24rpx;
color: #666666;
background-color: #f6f6f6;
padding: 5rpx 15rpx;
margin-right: 10rpx;
margin-bottom: 10rpx;
}
.ask {
overflow: hidden;
width: 100%;
display: flex;
align-items: center;
flex-wrap: wrap;
justify-content: flex-start;
margin: 20rpx 0;
}
.head_right {
ont-family: PingFangSC-Medium;
font-size: 28rpx;
color: #F46161;
font-weight: bold;
}
.head_left {
font-family: PingFangSC-Medium;
font-size: 32rpx;
font-weight: bold;
color: #333333;
width: 400rpx;
overflow: hidden;
white-space: nowrap;
/*不换行*/
text-overflow: ellipsis;
/*超出部分文字以...显示*/
}
.highlight {
color: #F46161;
}
.body {
width: 690rpx;
margin: 0rpx auto;
padding: 20rpx 0;
background-color: #fefefe;
overflow: hidden;
}
.heads {
display: flex;
align-items: center;
justify-content: space-between;
}
</style>

View File

@@ -1,30 +0,0 @@
<template>
<!-- #ifdef MP-WEIXIN -->
<button type="default" open-type="contact">
<image src="../../static/img/cs.svg" class="cs" mode=""></image>
</button>
<!-- #endif -->
<!-- #ifdef H5 || APP-PLUS -->
<!-- #endif -->
</template>
<script>
</script>
<style>
.csimage {
width: 88rpx;
height: 88rpx;
position: fixed;
right: 22rpx;
bottom: 112rpx;
}
.cs {
width: 88rpx;
height: 88rpx;
position: fixed;
right: 22rpx;
bottom: 22rpx;
}
</style>

View File

@@ -1,83 +0,0 @@
<template>
<view :class="className" @click="click">
<slot></slot>
</view>
</template>
<script>
export default {
props: {
loading: {
type: Boolean,
default: false
},
disabled: {
type: Boolean,
default: false
},
type: {
type: String
},
inline: {
Boolean,
default: false,
}
},
methods: {
click(e) {
if (this.loading || this.disabled) {
return;
}
this.$emit('click', e)
}
},
computed: {
className() {
let name = "jl-button"
if (this.inline) {
name += ' inline'
}
if (this.disabled) {
name += ' disabled'
}
if (this.loading) {
name += " loading"
}
if (this.type) {
name += " " + this.type
}
return name
}
},
};
</script>
<style>
.jl-button {
display: inline-block;
padding: 15rpx 47rpx;
border-radius: 10rpx;
text-align: center;
font-size: 32rpx;
color: #666666;
border: 1rpx solid #c8c7cc;
}
.jl-button.inline {
display: block;
height: 80rpx;
line-height: 80rpx;
padding:0;
}
.jl-button.primary {
color: #fefefe;
background-color: #1b66ff;
border-color: #1b66ff;
}
.jl-button.loading,
.jl-button.disabled {
opacity: 0.3;
}
</style>

View File

@@ -1,39 +0,0 @@
<template>
<view class="jl-form-item">
<view class="jl-form-item__label">{{prop}}</view>
<view class="jl-form-item__content">
<slot></slot>
</view>
</view>
</template>
<script>
export default {
props: {
prop: String,
},
};
</script>
<style>
.jl-form-item {
margin-bottom: 30rpx;
}
.jl-form-item__label {
float: left;
font-family: PingFangSC-Regular;
font-size: 32rpx;
color: #333333;
letter-spacing: 0;
line-height: 88rpx;
}
.jl-form-item__content {
position: relative;
}
.jl-form-item__content .jl-input-intext {
padding: 0;
}
</style>

View File

@@ -1,15 +0,0 @@
<template>
<view class="jl-form">
<slot></slot>
</view>
</template>
<script>
export default {};
</script>
<style>
.jl-form {
display: block;
}
</style>

View File

@@ -1,92 +0,0 @@
<template>
<view class="jl-input">
<input class="jl-input-intext" :type="type" :password="pwShow" :value="value" :placeholder="placeholder"
:placeholder-class="placeholderClass" @input="setValue" @blur="setValue" @confirm="$emit('confirm')" :maxlength="maxlength" />
<slot></slot>
<slot name="icon"></slot>
<image v-if="showPassword && pwShow" class="jl-input_image_eye" src="/static/img/eyeopen.svg" mode="" @click="changePasType"></image>
<image v-else-if="showPassword" class="jl-input_image_eye" src="/static/img/eyeclosed.svg" mode="" @click="changePasType"></image>
<image v-if="clearable" class="jl-input_image_delete" src="/static/img/delate.svg" mode="" @click="delpas"></image>
</view>
</template>
<script>
export default {
props: {
maxlength: {
type: Number,
default: -1
},
type: {
type: String,
default: "text",
},
placeholderClass: {
type: String,
default: "jl-input-inPla",
},
placeholder: String,
value: {
type: String,
default: "",
},
clearable: Boolean,
showPassword: Boolean,
},
computed: {},
data() {
return {
pwShow: this.showPassword
}
},
methods: {
setValue(e) {
this.$emit("input", e.detail.value);
},
delpas() {
this.$emit("input", '');
},
changePasType() {
this.pwShow = !this.pwShow
}
},
};
</script>
<style>
.jl-input {
margin: 0 auto;
/* margin-top: 30rpx; */
border-bottom: 1rpx solid #dddddd;
display: flex;
align-items: center;
justify-content: flex-start;
opacity: hidden;
}
.jl-input-intext {
font-family: PingFangSC-Regular;
font-size: 1rem;
padding: 30rpx 0;
color: #333333;
flex-grow: 1;
}
.jl-input-inPla {
font-family: PingFangSC-Regular;
font-size: 1rem;
color: #d8d8d8;
}
.jl-input_image_delete {
width: 32rpx;
height: 32rpx;
margin-left: 20rpx;
}
.jl-input_image_eye {
width: 40rpx;
height: 40rpx;
margin-left: 20rpx;
}
</style>

View File

@@ -1,296 +0,0 @@
<template>
<uni-popup :custom="true" type="bottom" ref="keyboardPackage">
<view class="keyboardbox">
<view class="numkeyboard" v-if="type==='number'">
<view class="num-area">
<view class="row" v-for="(item,index) in numKeybordList" :key="index">
<view :class="['item',ite===0?'z':'',(disableDot && ite==='.')?'disabled':'']" v-for="(ite,idx) in item"
hover-class="active" :hover-start-time="0" :hover-stay-time="5" :key="idx" @tap="input(ite)">{{ite}}</view>
</view>
</view>
<view class="btn-area">
<view :class="['item','del']" hover-class="active" :hover-start-time="0" :hover-stay-time="5" @tap="deleteVal">
删除
</view>
<view class="confirem item" hover-class="active" :hover-start-time="0" :hover-stay-time="5" @tap="confirm">
完成
</view>
</view>
</view>
<view class="numkeyboard" v-if="type==='idCard'">
<view class="num-area">
<view class="row" v-for="(item,index) in idCardList" :key="index">
<view :class="['item',ite===0?'z':'',(disableDot && ite==='.')?'disabled':'']" v-for="(ite,idx) in item"
hover-class="active" :hover-start-time="0" :hover-stay-time="5" :key="idx" @tap="input(ite)">{{ite}}</view>
</view>
</view>
<view class="btn-area">
<view :class="['item','del']" hover-class="active" :hover-start-time="0" :hover-stay-time="5" @tap="deleteVal">
删除
</view>
<view class="confirem item" hover-class="active" :hover-start-time="0" :hover-stay-time="5" @tap="confirm">
完成
</view>
</view>
</view>
<view class="platenumber" v-if="type==='plateNumber'">
<view class="header">
<view @tap="active=active===1?2:1" hover-class="active" :hover-start-time="0" :hover-stay-time="5">{{active===1?'地区':'车牌号'}}</view>
<view hover-class="active" :hover-start-time="0" :hover-stay-time="5" @tap="confirm">完成</view>
</view>
<view class="main">
<view class="normal" v-if="active===1">
<view class="row" v-for="(item,index) in EngKeyBoardList" :key="index">
<view class="item" v-for="(ite,idx) in item" :key="idx" hover-class="active" :hover-start-time="0" :hover-stay-time="5" @tap="input(ite)">
{{ite}}
</view>
<view class="item img" v-if="index===EngKeyBoardList.length-1" hover-class="active" :hover-start-time="0" :hover-stay-time="5" @tap="deleteVal">
<image src="/static/delete.png" mode=""></image>
</view>
</view>
</view>
<view class="area" v-if="active===2">
<view class="row" v-for="(item,index) in areaList" :key="index">
<view class="item" v-for="(ite,idx) in item" :key="idx" hover-class="active" :hover-start-time="0" :hover-stay-time="5" @tap="input(ite)">
{{ite}}
</view>
<view class="item img" v-if="index===EngKeyBoardList.length-1" hover-class="active" :hover-start-time="0" :hover-stay-time="5" @tap="deleteVal">
<image src="/static/delete.png" mode=""></image>
</view>
</view>
</view>
</view>
</view>
</view>
<view class="safe-area" v-if="safeAreaInsetBottom"></view>
</uni-popup>
</template>
<script>
import uniPopup from "@/components/uni-popup/uni-popup.vue"
export default {
components: {
uniPopup
},
props: {
type: {
type: String,
default: 'number'
},
safeAreaInsetBottom: { //是否设置安全区
type: Boolean,
default: false
},
disableDot: { //数字键盘是否禁止点击.仅type为number生效
type: Boolean,
default: false
}
},
data() {
return {
numKeybordList: [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
[0, '.']
],
idCardList: [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
[0, 'X']
],
areaList: [
['京', '沪', '粤', '津', '冀', '豫', '云', '辽', '黑', '湘'],
['皖', '鲁', '苏', '浙', '赣', '鄂', '桂', '甘', '晋', '陕'],
['蒙', '吉', '闽', '贵', '渝', '川', '青', '琼', '宁'],
['藏', '新', '使', '港', '澳', '学']
],
EngKeyBoardList: [
[1, 2, 3, 4, 5, 6, 7, 8, 9, 0],
['Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P'],
['A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L'],
['Z', 'X', 'C', 'V', 'B', 'N', 'M']
],
active: 1
};
},
methods: {
open() {
this.$refs.keyboardPackage.open();
},
confirm() {
this.close();
this.$emit('onConfirm');
},
deleteVal() {
this.$emit('onDelete');
},
input(val) {
if (val === '.' && this.disableDot) return;
this.$emit('onInput', val);
},
close() {
this.$refs.keyboardPackage.close();
}
}
}
</script>
<style lang="scss" scoped>
.keyboardbox {
background-color: #FFFFFF;
.numkeyboard {
height: 432rpx;
display: flex;
background-color: #ebedf0;
.btn-area {
width: 180rpx;
height: 100%;
display: flex;
flex-direction: column;
.item {
width: 100%;
display: flex;
justify-content: center;
align-items: center;
flex-grow: 1;
}
.del {
background-color: #ebedf0;
color: #333;
&.active {
background-color: #f1f3f5;
}
}
.confirem {
background-color: #1989fa;
color: #FFFFFF;
&.active {
background-color: #0570db;
}
}
}
.num-area {
flex-grow: 1;
display: flex;
flex-wrap: wrap;
.row {
width: 100%;
height: 25%;
display: flex;
margin-top: 1px;
.item {
flex-grow: 1;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
background-color: #FFFFFF;
border-right: 1px solid #ebedf0;
width: 33.33%;
&.active {
background-color: #ebedf0;
}
&.z {
flex-grow: 2;
width: 66.66%;
}
&.disabled {
background: #FFFFFF;
color: #B9B9B9;
}
}
}
}
}
}
.safe-area {
padding-bottom: 0rpx;
padding-bottom: constant(safe-area-inset-bottom);
padding-bottom: env(safe-area-inset-bottom);
}
.platenumber {
background-color: #f5f5f5;
.header {
height: 76rpx;
background-color: #FFFFFF;
display: flex;
justify-content: space-between;
align-items: center;
font-size: 28rpx;
border-top: 1px solid #f5f5f5;
&>view {
padding: 0 45rpx;
color: #00a7ea;
height: 100%;
display: flex;
align-items: center;
&.active {
background-color: #ebedf0;
}
}
}
.main {
height: 435rpx;
.row {
margin: 13rpx 0;
display: flex;
justify-content: center;
align-items: center;
.item {
width: 56rpx;
height: 94rpx;
display: flex;
justify-content: center;
align-items: center;
background-color: #FFFFFF;
border-radius: 6rpx;
margin: 0 7rpx;
font-size: 24rpx;
&.active {
background-color: #ebedf0;
}
&.img {
background-color: #c2cacc;
width: 94rpx;
&.active {
background-color: #ddd;
}
&>image {
width: 49rpx;
height: 48rpx;
}
}
}
}
}
}
</style>

View File

@@ -1,59 +0,0 @@
const defaultOptions = {
only: true
}
export default function markSlideListController(options = defaultOptions) {
const instances = {};
const opened = {};
const moving = {};
let index = 0;
const pipelines = {
moving: [],
opened: [],
closed: [],
};
init()
function init() {
if (options.only) {
pipelines.moving.push(only)
}
}
function pipelinesHandler(type, key) {
pipelines[type].forEach(item => {
item.call(this, key)
})
}
function only() {
for (let key in opened) {
const item = opened[key]
item.hide()
}
}
this.reg = ({
instance,
cb
}) => {
instances[index] = instance
cb(index++)
}
this.moving = (key) => {
moving[key] = instances[key]
delete opened[key]
pipelinesHandler('moving', key)
}
this.opened = (key) => {
opened[key] = instances[key]
delete moving[key]
pipelinesHandler('opened', key)
}
this.closed = (key) => {
delete opened[key]
delete moving[key]
pipelinesHandler('closed', key)
}
}

View File

@@ -1,186 +0,0 @@
<template>
<view class="slide-list">
<view class="slide-list-item" @touchstart="touchStart" @touchend="touchEnd" @touchmove="touchMove" :style="{transform}">
<slot></slot>
</view>
<view class="group-btn">
<view class="btn-div" v-for="(btn, key) in button" :key="key" @click.stop="btnClick(btn,key)" :style="{background: btn.background}">
<text class="btn-title">{{btn.title}}</text>
</view>
</view>
</view>
</template>
<script>
import handler from './slideHandler.js'
/**
* m-slide-list 滑动操作列表
* @description 滑动操作列表组件
* @tutorial https://ext.dcloud.net.cn/plugin?id=209
* @property {Array} list 数据源,格式为:[{title: 'xxx', image:'xxx', surname: 'xxx',detail:'xxx', rightDetail: 'xxx', slide_x: 0},{title: 'xxx', image:'xxx', surname: 'xxx',detail:'xxx', rightDetail: 'xxx', slide_x: 0}]
* @property {Array} button 按钮数据源,格式为:[{title: 'xxx', background:'xxx'},{title: 'xxx', background:'xxx'}]
* @property {Boolean} border 边框
*/
export default {
name: 'mark-slide-list',
props: {
button: { //按钮数据list
type: Array,
default () {
return [];
}
}
},
computed: {
windowWidth() {
return uni.getSystemInfoSync().windowWidth;
},
transform() {
return `translate3d(${ this.slide_x }px, 0, 0)`
}
},
data() {
return {
key: null,
moving: false,
btnState: 'hide',
hideLimit: 0,
showLimit: 0,
btnWidth: 0,
slide_x: 0,
handler: null
};
},
mounted() {
this.$emit('controller-reg', {
instance:{
show: this.show,
hide: this.hide
},
cb: (key) => {
this.key = key
}
})
const cb = res => {
this.btnWidth = res[0].width * -1;
this.showLimit = res[0].width / 3;
this.hideLimit = res[0].width / 3;
}
// 按钮宽度
uni.createSelectorQuery().in(this).select('.group-btn').boundingClientRect().exec(cb);
},
methods: {
btnClick(btn, key) {
this.$emit(btn.clickName, {
btn,
key
})
},
setSlideX(offset) {
const val = offset + this.slide_x
if (val < 0 && val >= this.btnWidth) {
this.slide_x = val
} else if (val > 0) {
this.slide_x = 0
}
},
// 滑动开始
touchStart(e) {
this.$emit('controller-moving', this.key)
this.moving = true
this.handler = new handler(e.timeStamp, e.touches[0].pageX, e.touches[0].pageY)
},
// 滑动中
touchMove(e) {
const slide_x = this.handler.move(e.touches[0])
this.setSlideX(slide_x)
},
// 滑动结束
touchEnd(e) {
this.moving = false
const endTime = e.timeStamp,
endY = e.changedTouches[0].pageY,
endX = e.changedTouches[0].pageX;
const x_end_distance = this.startX - this.lastX;
const end = this.handler.endMove(endTime, endX, endY)
if (end.invalid) {} else if ((end.quick && end.dir === 'l') || (end.dir === 'l' && end.move > this.showLimit)) {
this.show()
} else if ((end.quick && end.dir === 'r') || (end.dir === 'r' && end.move > this.hideLimit)) {
this.hide()
} else {
this.recover()
}
this.handler = null
},
// 点击回复原状
recover() {
if (this.btnState === 'show') {
this.show()
} else if (this.btnState === 'hide') {
this.hide()
}
},
show() {
this.btnState = 'show'
this.slide_x = this.btnWidth;
this.$emit('controller-opened', this.key)
},
hide() {
this.btnState = 'hide'
this.slide_x = 0;
this.$emit('controller-closed', this.key)
},
}
};
</script>
<style lang="scss" scoped>
.slide-list {
position: relative;
width: 100%;
.slide-list-item {
width: 100%;
overflow: hidden;
position: relative;
z-index: 2;
transition: all 100ms;
transition-timing-function: ease-out;
}
.group-btn {
position: absolute;
top: 0;
right: 0;
height: 100%;
min-width: 100rpx;
align-items: center;
z-index: 1;
display: flex;
flex-direction: row;
.btn-div {
height: 100%;
color: #fff;
text-align: center;
padding: 0 50rpx;
font-size: 34rpx;
display: table;
.btn-title {
display: table-cell;
vertical-align: middle;
}
}
.top {
background-color: #c4c7cd;
}
.removeM {
background-color: #ff3b32;
}
}
}
</style>

View File

@@ -1,54 +0,0 @@
class handler {
constructor(startTime, startX, startY) {
this.startTime = startTime
this.lastX = this.startX = startX
this.startY = startY
this._moveFunc = this.firstMove
}
move({
timeStamp,
pageX,
pageY
}) {
return this._moveFunc(timeStamp, pageX, pageY)
}
firstMove(timeStamp, pageX, pageY) {
if (Math.abs(pageX - this.startX) > Math.abs(pageY - this.startY)) {
this._moveFunc = this.nextMove
} else {
this._moveFunc = () => {
return 0
}
this.endMove = () => {
return {
invalid: true
}
}
}
return 0
}
nextMove(timeStamp, pageX, pageY) {
const r = pageX - this.lastX
this.lastX = pageX
return r
}
isQuick(endTime, endX) {
return endTime - this.startTime < 200 && Math.abs(endX - this.startX) > 50
}
endMove(endTime, pageX, pageY) {
return {
invalid: false,
quick: this.isQuick(endTime, pageX),
dir: pageX > this.startX ? 'r' : 'l',
move: Math.abs(pageX - this.startX)
}
}
}
export default handler

View File

@@ -1,120 +0,0 @@
<template>
<!-- 首字母检索 -->
<view>
<view class="letter touch" @touchstart.stop="searchStart" @touchmove.stop="searchMove" @touchend.stop="searchEnd">
<!-- 右边字母数据数据 触摸事件-->
<view class="letter-item" v-for="item in options" :key="item.key">{{item.key}}</view>
<!-- 左边字母跟右边字母true时 屏幕中心显示选中的首字母-->
</view>
<!-- 居中首字母样式 -->
<view class="cont-letter" v-if="isShowLetter">
{{showLetter}}
</view>
</view>
</template>
<script>
export default {
props: {
options: {
type: Array
},
length: {
type: Number
}
},
data() {
let windowHeight = uni.getSystemInfoSync().windowHeight
let startHeight = windowHeight * 0.1
return {
startHeight,
letterHeight: windowHeight - startHeight,
isShowLetter: false,
showLetter: ''
}
},
computed: {
letters() {
const arr = []
for (let key in this.options) {
arr.push(this.options[key])
}
return arr.key
}
},
methods: {
getLetter(pageY) {
let index = ((pageY - this.startHeight) / this.letterHeight) * this.options.length
return this.options[parseInt(index)].key
},
/* 检索字母拖动开始 */
searchStart(e) {
let pageY = e.touches[0].clientY;
this.showLetter = this.getLetter(pageY);
this.$emit("touchmove", this.showLetter)
this.isShowLetter = true
return false
},
/* 检索字母拖动中 */
searchMove(e) {
let pageY = e.touches[0].clientY;
this.showLetter = this.getLetter(pageY);
this.$emit("touchmove", this.showLetter)
return false
},
/* 检索字母拖动结束 */
searchEnd() {
setTimeout(() => {
this.isShowLetter = false
}, 1000)
},
}
}
</script>
<style lang="scss" scoped>
/* 首字母样式 */
.letter {
position: absolute;
right: 0;
top: 10%;
width: 30px;
height: 90%;
text-align: center;
justify-content: center;
display: flex;
flex-direction: column;
color: #666;
background-color: transparent;
z-index: 1;
}
/* 右边首字母样式 */
.touch {
color: #666;
font-size: 28rpx;
}
.letter-item {
color: #1B66FF;
flex-grow: 1;
}
/* 居中显示的选中首字母 */
.cont-letter {
background-color: #666;
color: #fff;
display: flex;
justify-content: center;
align-items: center;
position: fixed;
top: 50%;
left: 50%;
margin: -50px;
width: 100px;
height: 100px;
border-radius: 10px;
font-size: 26px;
z-index: 1
}
</style>

View File

@@ -1,192 +0,0 @@
<template>
<view>
<!-- 搜索框 -->
<view class='search'>
搜索<input type='text' v-model="keyValue" placeholder='请输入银行名称' placeholder-style="font-size:32rpx;color:#cccccc" />
</view>
<scroll-view ref="view" scroll-y="true" :scroll-top="scrollTop" :style="{height:`${winHeight}px`}">
<!-- 循环城市数据 -->
<view v-for="group in data.data" :key="group.key">
<!-- 循环首字母检索信息 -->
<view class="list_letter">{{group.key}}</view>
<!-- 城市ID城市名称 -->
<view class="item_city" v-for="item in group.value" :key="item.id" @tap="click(item)">{{item.name}}</view>
</view>
</scroll-view>
<letter-list :options="data.letters" @touchmove="setScrollTop"></letter-list>
</view>
</template>
<script>
import letterList from './letter-list.vue'
function getFirstLetter(str) {
return str[0];
}
function fortmat(data, itemH, tHeight) {
let index = 0
const letters = []
const scrollTop = {}
for (var i = 0; i < data.length; i++) {
const value = data[i].value
const key = data[i].key
letters.push({
key,
value: value.length
})
scrollTop[key] = index
index += value.length
}
return {
data,
letters,
scrollTop
}
}
export default {
components: {
letterList
},
name: "NynCityList",
props: {
options: {
type: Array,
required: true
},
prop: {
type: Object,
default () {
return {
name: 'name'
}
}
}
},
data() {
return {
keyValue: '',
itemH: 0, //字母列表的高度
scrollTop: 0,
tHeight: 0,
winHeight: 0, //城市列表窗口高度
}
},
created() {},
mounted() {
this.initList()
},
methods: {
/* 列表初始化 */
initList() {
const sysInfo = uni.getSystemInfoSync();
const query = uni.createSelectorQuery().in(this);
query.select(".item_city").boundingClientRect(scrollx=>{
this.itemH = scrollx.height
})
query.select(".list_letter").boundingClientRect(scrollx=>{
this.tHeight = scrollx.height
})
query.select('.search').boundingClientRect(data => {
let top = data.height
this.winHeight = sysInfo.windowHeight - top - 1;
}).exec();
},
click(item) {
this.$emit('change', item)
},
/* 设置scroll-view滚动距离 */
setScrollTop(showLetter) {
var letters = this.data.letters
var letterIndex = 0
for (var i = 0; i < letters.length; i++) {
if (showLetter === letters[i].key) {
letterIndex = i
}
}
this.scrollTop = (this.data.scrollTop[showLetter] * this.itemH) + (letterIndex * this.tHeight)
},
},
computed: {
data() {
return fortmat(this.options, this.itemH, this.tHeight)
}
},
watch: {
keyValue(value) {
this.$emit('filter-method', value)
}
}
}
</script>
<style lang="scss" scoped>
.search {
display: flex;
align-items: center;
justify-content: flex-start;
background-color: #ffffff;
font-family: PingFangSC-Regular;
font-size: 32rpx;
color: #333333;
// border-radius:100rpx;
padding: 20rpx 0;
width: 730rpx;
margin-left: 20rpx;
border-bottom: 1rpx solid #ddd;
input {
line-height: 60rpx;
text-align: left;
padding-left: 20rpx;
font-family: PingFangSC-Regular;
font-size: 32rpx !important;
}
}
/* 循环数据首字母检索 */
.list_letter {
display: flex;
background-color: #f8f8f8;
height: 60rpx;
color: #2a2a2a;
font-size: 26rpx;
padding-left: 10px;
align-items: center;
}
/* 城市样式 */
.item_city {
display: flex;
background-color: #fff;
height: 60rpx;
font-family: PingFangSC-Regular;
font-size: 32rpx;
color: #333333;
letter-spacing: 0;
align-items: center;
padding: 10rpx 0;
width: 730rpx;
margin-left: 20rpx;
border-bottom: 2rpx solid #ddd;
}
.list {
.eng {
background: #ffffff;
padding: 30rpx;
color: #212121;
}
.text {
color: #212121;
font-size: 26rpx;
margin: 30rpx 0 0 30rpx;
padding-bottom: 30rpx;
border-bottom: 1px solid #E6E6E6
}
}
</style>

View File

@@ -1,168 +0,0 @@
<!--
自定义验证码输入密码输入使用
使用方法
maxlength输入最大长度
isPwd是否是密码模式
@finish回调函数
<validcode :maxlength="4" :isPwd="false" @finish="finish"></validcode>
-->
<template>
<view class="code-area">
<view class="flex-box">
<input :value="val" type="number" :focus="true" :maxlength="maxlength" class="hide-input" @input="getVal" @focus="focus"
@blur="blur" />
<view :key="index" v-for="(i,index) in maxlength - 1" v-bind:class="['item', { active: focusing && codeIndex === index }]">
<view class="line"></view>
<block v-if="val.length - 1 < index"></block>
<block v-else-if="isPwd">
<text class="dot">.</text>
</block>
<block v-else> {{ val[index] }}</block>
</view>
<view v-bind:class="['item', { active: focusing && codeIndex >= maxlength - 1 }]">
<view class="line" v-if="val.length - 1 < maxlength - 1"></view>
<block v-else-if="isPwd">
<text class="dot">.</text>
</block>
<block v-else> {{ val[maxlength - 1] }}</block>
</view>
</view>
</view>
</template>
<script>
export default {
props: {
//最大长度 值为4或者6
maxlength: {
type: Number,
default: 4
},
//是否是密码
isPwd: {
type: Boolean,
default: false
}
},
data() {
return {
focusing: true,
val: '', //输入框的值
};
},
methods: {
//取值
getVal(e) {
let {
value
} = e.detail;
if (value.length <= this.maxlength) {
this.val = value;
}
},
//清除验证码或者密码
clear() {
this.val = "";
},
blur() {
this.focusing = false
},
focus() {
this.focusing = true
}
},
computed: {
codeIndex() {
return this.val.length
}
},
watch: {
val(val) {
if (val.length === this.maxlength) {
this.$emit('finish', val);
}
}
}
};
</script>
<style lang="scss">
.code-area {
text-align: center;
.flex-box {
display: flex;
flex-wrap: wrap;
position: relative;
justify-content: space-between;
}
.item {
position: relative;
width: 80upx;
height: 80upx;
margin-right: 18upx;
font-size: 30upx;
font-weight: bold;
color: #333333;
line-height: 80upx;
box-sizing: border-box;
border: 2upx solid #cccccc;
}
.item:last-child {
margin-right: 0;
}
.active {
border-color: #1B66FF
}
.active .line {
display: block;
}
.line {
display: none;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
width: 2upx;
height: 40upx;
background: #1B66FF;
animation: twinkling 1s infinite ease;
}
.hide-input {
position: absolute;
top: 0;
left: -100%;
width: 200%;
height: 100%;
text-align: left;
z-index: 9;
opacity: 1;
}
@keyframes twinkling {
0% {
opacity: 0.2;
}
50% {
opacity: 0.5;
}
100% {
opacity: 0.2;
}
}
.dot {
font-size: 80upx;
line-height: 40upx;
}
}
</style>

View File

@@ -1,69 +0,0 @@
<template>
<view class="stepBarWrap">
<view class="stepBarContent" v-for="(item, index) in stepList" :key="index" >
<view class="number" :class="{'activeNum':active >= index}">{{index+1}}</view>
<view :class="{'active':active >= index}" style="color: #979797;margin-top: 20rpx;">{{item}}</view>
<view class="br" v-if="index > 0" :class="{'activeBr': active>=index}"></view>
</view>
</view>
</template>
<script>
export default{
data (){
return {
}
},
props: {
stepList: {
type: Array,
default: []
},
active: 0
},
methods:{
}
}
</script>
<style>
.stepBarWrap{
display: flex;
justify-content: space-between;
padding: 0 15px;
}
.stepBarContent{
flex:1;
display: flex;
flex-flow: column;
align-items: center;
position: relative;
font-size: 14px;
}
.stepBarContent .number{
width:60rpx;
height: 60rpx;
line-height: 30px;
border-radius: 50%;
text-align: center;
color: #FFFFFF;
background-color: #97979747;
}
.stepBarContent .br{
width: 40%;
height:2px;
background-color: #979797;
position: absolute;
top: 28%;
left: -20%;
}
.active{
color: #1C66FF !important;
}
.activeNum{
background-color: #1C66FF !important;
}
.activeBr{
background-color: #1C66FF !important;
}
</style>

View File

@@ -1,96 +0,0 @@
export default {
'contact': '\ue100',
'person': '\ue101',
'personadd': '\ue102',
'contact-filled': '\ue130',
'person-filled': '\ue131',
'personadd-filled': '\ue132',
'phone': '\ue200',
'email': '\ue201',
'chatbubble': '\ue202',
'chatboxes': '\ue203',
'phone-filled': '\ue230',
'email-filled': '\ue231',
'chatbubble-filled': '\ue232',
'chatboxes-filled': '\ue233',
'weibo': '\ue260',
'weixin': '\ue261',
'pengyouquan': '\ue262',
'chat': '\ue263',
'qq': '\ue264',
'videocam': '\ue300',
'camera': '\ue301',
'mic': '\ue302',
'location': '\ue303',
'mic-filled': '\ue332',
'speech': '\ue332',
'location-filled': '\ue333',
'micoff': '\ue360',
'image': '\ue363',
'map': '\ue364',
'compose': '\ue400',
'trash': '\ue401',
'upload': '\ue402',
'download': '\ue403',
'close': '\ue404',
'redo': '\ue405',
'undo': '\ue406',
'refresh': '\ue407',
'star': '\ue408',
'plus': '\ue409',
'minus': '\ue410',
'circle': '\ue411',
'checkbox': '\ue411',
'close-filled': '\ue434',
'clear': '\ue434',
'refresh-filled': '\ue437',
'star-filled': '\ue438',
'plus-filled': '\ue439',
'minus-filled': '\ue440',
'circle-filled': '\ue441',
'checkbox-filled': '\ue442',
'closeempty': '\ue460',
'refreshempty': '\ue461',
'reload': '\ue462',
'starhalf': '\ue463',
'spinner': '\ue464',
'spinner-cycle': '\ue465',
'search': '\ue466',
'plusempty': '\ue468',
'forward': '\ue470',
'back': '\ue471',
'left-nav': '\ue471',
'checkmarkempty': '\ue472',
'home': '\ue500',
'navigate': '\ue501',
'gear': '\ue502',
'paperplane': '\ue503',
'info': '\ue504',
'help': '\ue505',
'locked': '\ue506',
'more': '\ue507',
'flag': '\ue508',
'home-filled': '\ue530',
'gear-filled': '\ue532',
'info-filled': '\ue534',
'help-filled': '\ue535',
'more-filled': '\ue537',
'settings': '\ue560',
'list': '\ue562',
'bars': '\ue563',
'loop': '\ue565',
'paperclip': '\ue567',
'eye': '\ue568',
'arrowup': '\ue580',
'arrowdown': '\ue581',
'arrowleft': '\ue582',
'arrowright': '\ue583',
'arrowthinup': '\ue584',
'arrowthindown': '\ue585',
'arrowthinleft': '\ue586',
'arrowthinright': '\ue587',
'pulldown': '\ue588',
'closefill': '\ue589',
'sound': '\ue590',
'scan': '\ue612'
}

File diff suppressed because one or more lines are too long

View File

@@ -1,47 +0,0 @@
<template>
<!-- #ifdef H5 || APP-PLUS -->
<view class="jl-mask" v-if="maskShow" style="top: 44px;">
<slot></slot>
</view>
<!-- #endif -->
<!-- #ifdef MP-WEIXIN -->
<view class="jl-mask" v-if="maskShow">
<slot></slot>
</view>
<!-- #endif -->
</template>
<script>
export default{
data () {
return {
}
},
props: {
maskShow: false
},
methods:{
clear(e){
return
}
}
}
</script>
<style>
.jl-mask{
position: fixed;
top: 0;
right: 0;
left: 0;
bottom: 0;
background: rgba(0,0,0,.1);
/* overflow: auto; */
z-index: 999;
}
.maskClose{
position: absolute;
right: 100rpx;
top: 100rpx;
}
</style>

View File

@@ -1,206 +0,0 @@
<template>
<view class="uni-navbar">
<view :class="{ 'uni-navbar--fixed': fixed, 'uni-navbar--shadow': shadow, 'uni-navbar--border': border }" :style="{ 'background-color': backgroundColor }"
class="uni-navbar__content">
<uni-status-bar v-if="statusBar" />
<view :style="{ color: color,backgroundColor: backgroundColor }" class="uni-navbar__header uni-navbar__content_view">
<view class="uni-navbar__header-container uni-navbar__content_view">
<view class="uni-navbar__header-container-inner uni-navbar__content_view" v-if="title.length">
<text class="uni-nav-bar-text" :style="{color: color }">{{ title }}</text>
</view>
<!-- 标题插槽 -->
<slot />
</view>
</view>
</view>
<view class="uni-navbar__placeholder" v-if="fixed">
<uni-status-bar v-if="statusBar" />
<view class="uni-navbar__placeholder-view" />
</view>
</view>
</template>
<script>
import uniStatusBar from "../uni-status-bar/uni-status-bar.vue";
import uniIcons from "../uni-icons/uni-icons.vue";
export default {
name: "UniNavBar",
components: {
uniStatusBar,
uniIcons
},
props: {
title: {
type: String,
default: ""
},
leftText: {
type: String,
default: ""
},
rightText: {
type: String,
default: ""
},
leftIcon: {
type: String,
default: ""
},
rightIcon: {
type: String,
default: ""
},
fixed: {
type: [Boolean, String],
default: false
},
color: {
type: String,
default: "#000000"
},
backgroundColor: {
type: String,
default: "#FFFFFF"
},
statusBar: {
type: [Boolean, String],
default: false
},
shadow: {
type: [String, Boolean],
default: false
},
border: {
type: [String, Boolean],
default: true
}
},
mounted() {
if(uni.report && this.title !== '') {
uni.report('title', this.title)
}
},
methods: {
onClickLeft() {
this.$emit("clickLeft");
},
onClickRight() {
this.$emit("clickRight");
}
}
};
</script>
<style lang="scss" scoped>
$nav-height: 44px;
.uni-nav-bar-text {
/* #ifdef APP-PLUS */
font-size: 34rpx;
/* #endif */
/* #ifndef APP-PLUS */
font-size: $uni-font-size-lg;
/* #endif */
}
.uni-nav-bar-right-text {
font-size: $uni-font-size-base;
}
.uni-navbar {
width: 750rpx;
}
.uni-navbar__content {
position: relative;
width: 750rpx;
background-color: $uni-bg-color;
overflow: hidden;
}
.uni-navbar__content_view {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
align-items: center;
flex-direction: row;
// background-color: #FFFFFF;
}
.uni-navbar__header {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
width: 750rpx;
height: $nav-height;
line-height: $nav-height;
font-size: 16px;
justify-content: center;
// background-color: #ffffff;
}
.uni-navbar__header-btns {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-wrap: nowrap;
width: 120rpx;
padding: 0 6px;
justify-content: center;
align-items: center;
}
.uni-navbar__header-btns-left {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
width: 150rpx;
justify-content: flex-start;
}
.uni-navbar__header-btns-right {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
width: 150rpx;
padding-right: 30rpx;
justify-content: flex-end;
}
.uni-navbar__header-container {
flex: 1;
}
.uni-navbar__header-container-inner {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex: 1;
align-items: center;
justify-content: center;
font-size: $uni-font-size-base;
}
.uni-navbar__placeholder-view {
height: $nav-height;
}
.uni-navbar--fixed {
position: fixed;
z-index: 998;
}
.uni-navbar--shadow {
/* #ifndef APP-NVUE */
box-shadow: 0 1px 6px #ccc;
/* #endif */
}
.uni-navbar--border {
// border-bottom-width: 1rpx;
// border-bottom-style: solid;
// border-bottom-color: $uni-border-color;
}
</style>

View File

@@ -1,187 +0,0 @@
<template>
<view v-if="showPopup" class="uni-popup">
<view :class="[ani, animation ? 'ani' : '', !custom ? 'uni-custom' : '']" class="uni-popup__mask" @click="close(true)" />
<view :class="[type, ani, animation ? 'ani' : '', !custom ? 'uni-custom' : '']" class="uni-popup__wrapper" @click="close(true)">
<view class="uni-popup__wrapper-box" @click.stop="clear">
<slot />
</view>
</view>
</view>
</template>
<script>
export default {
name: 'UniPopup',
props: {
// 开启动画
animation: {
type: Boolean,
default: true
},
// 弹出层类型可选值top: 顶部弹出层bottom底部弹出层center全屏弹出层
type: {
type: String,
default: 'center'
},
// 是否开启自定义
custom: {
type: Boolean,
default: false
},
// maskClick
maskClick: {
type: Boolean,
default: true
},
show: {
type: Boolean,
default: true
}
},
data() {
return {
ani: '',
showPopup: false
}
},
watch: {
show(newValue) {
if (newValue) {
this.open()
} else {
this.close()
}
}
},
created() {},
methods: {
clear() {},
open() {
this.$emit('change', {
show: true
})
this.showPopup = true
this.$nextTick(() => {
setTimeout(() => {
this.ani = 'uni-' + this.type
}, 30)
})
},
close(type) {
if (!this.maskClick && type) return
this.$emit('change', {
show: false
})
this.ani = ''
this.$nextTick(() => {
setTimeout(() => {
this.showPopup = false
}, 300)
})
}
}
}
</script>
<style>
@charset "UTF-8";
.uni-popup {
position: fixed;
top: 0;
top: 0;
bottom: 0;
left: 0;
right: 0;
z-index: 99999;
overflow: hidden
}
.uni-popup__mask {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
z-index: 998;
/* background: rgba(0, 0, 0, .4); */
opacity: 0
}
.uni-popup__mask.ani {
transition: all .3s
}
.uni-popup__mask.uni-bottom,
.uni-popup__mask.uni-center,
.uni-popup__mask.uni-top {
opacity: 1
}
.uni-popup__wrapper {
position: absolute;
z-index: 999;
box-sizing: border-box
}
.uni-popup__wrapper.ani {
transition: all .3s
}
.uni-popup__wrapper.top {
top: 0;
left: 0;
width: 100%;
transform: translateY(-100%)
}
.uni-popup__wrapper.bottom {
bottom: 0;
left: 0;
width: 100%;
transform: translateY(100%)
}
.uni-popup__wrapper.center {
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
transform: scale(1.2);
opacity: 0
}
.uni-popup__wrapper-box {
position: relative;
box-sizing: border-box
}
.uni-popup__wrapper.uni-custom .uni-popup__wrapper-box {
padding: 30upx;
background: #fff
}
.uni-popup__wrapper.uni-custom.center .uni-popup__wrapper-box {
position: relative;
max-width: 80%;
max-height: 80%;
overflow-y: scroll
}
.uni-popup__wrapper.uni-custom.bottom .uni-popup__wrapper-box,
.uni-popup__wrapper.uni-custom.top .uni-popup__wrapper-box {
width: 100%;
max-height: 500px;
overflow-y: scroll
}
.uni-popup__wrapper.uni-bottom,
.uni-popup__wrapper.uni-top {
transform: translateY(0)
}
.uni-popup__wrapper.uni-center {
transform: scale(1);
opacity: 1
}
</style>

View File

@@ -1,346 +0,0 @@
<template>
<view class="sealWrapBox">
<view class="wrapper" v-show="showCanvas">
<view class="handBtn">
<view class="lookBtn" @click="look">图例示范</view>
<view class="delBtn" @click="clear">清除</view>
<view v-if="paintBrush" class="saveBtn saveBtnActive" @click="finish">下一步</view>
<view v-else class="saveBtn">下一步</view>
<!-- <view class="previewBtn" @click="close">关闭</view> -->
</view>
<view class="handCenter">
<canvas v-show="!maskShow" canvas-id="canvasid" id="test" class="handWriting" disable-scroll="true" @touchstart="touchstart"
@touchmove="touchmove" @touchend="touchend"></canvas>
</view>
<view class="handRight">
<image src="../../pageMy/static/img/seal/tips.png" mode=""></image>
<view class="handTitle">手写签名需与本人姓名保持一致</view>
</view>
</view>
<uniMask :maskShow="maskShow">
<view class="maskBody" :style="maskBodyStyle">
<view class="closeMask" @click.stop="closeMask">关闭</view>
</view>
</uniMask>
</view>
</template>
<script>
import {
baseUrl
} from '@/config/env.js'
import {
getStore
} from '@/untils/store.js'
import uniMask from '@/components/uni-mask/mask.vue'
var x = 20;
var y = 20;
export default {
data() {
return {
oc: "",
src: "",
//路径点集合
points: [],
maskBodyStyle: '',
showCanvas: true,
maskShow: false,
paintBrush: false
};
},
components: {
uniMask
},
mounted() {
this.initCanvas()
},
methods: {
look() {
uni.getSystemInfo({
success: res => {
var scrollH = res.windowHeight
var scrollW = res.windowWidth
// #ifdef H5
this.maskBodyStyle =
`width:${scrollH-144}px;height:${scrollW-100}px;top:${(scrollW/2)+94}px;left:-${(scrollW-100)/2}px`
// #endif
// #ifdef MP-WEIXIN
this.maskBodyStyle =
`width:${scrollH-144}px;height:${scrollW-100}px;top:${(scrollW/2)}px;left:-${(scrollW-100)/2}px`
// #endif
}
});
this.maskShow = true
},
closeMask() {
this.maskShow = false
},
imgFile() {
var token = getStore({
name: 'token'
})
const that = this
uni.uploadFile({
url: `${baseUrl}/api/jobslink-api/resource/oss/endpoint/put-file?Jobslink-Auth=${token}`,
filePath: that.src,
name: 'file',
success: (uploadFileRes) => {
that.$emit('finish', uploadFileRes)
that.paintBrush = true
}
});
},
finish() {
const that = this
this.paintBrush = false
this.oc.draw(true, uni.canvasToTempFilePath({
destWidth: 300,
destHeight: 300,
quality: 1,
canvasId: 'canvasid',
fileType: 'png',
success: function(res) {
that.src = res.tempFilePath
that.imgFile()
},
fail: function(err) {
console.log(err)
}
}, this))
},
close: function() {
this.showCanvas = false;
this.clear();
},
initCanvas() {
this.showCanvas = true;
this.oc = uni.createCanvasContext('canvasid', this);
//设置画笔样式
this.oc.lineWidth = 10;
this.oc.lineCap = "round";
this.oc.lineJoin = "round";
// 画笔颜色
// this.oc.setStrokeStyle("#ffffff");
},
//触摸开始,获取到起点
touchstart(e) {
const startX = e.changedTouches[0].x;
const startY = e.changedTouches[0].y;
let startPoint = {
X: startX,
Y: startY
};
this.points.push(startPoint);
//每次触摸开始,开启新的路径
this.oc.beginPath();
},
//触摸移动,获取到路径点
touchmove(e) {
let moveX = e.changedTouches[0].x;
let moveY = e.changedTouches[0].y;
let movePoint = {
X: moveX,
Y: moveY
};
this.points.push(movePoint); //存点
let len = this.points.length;
if (len >= 2) {
this.draw(); //绘制路径
}
},
// 触摸结束,将未绘制的点清空防止对后续路径产生干扰
touchend() {
this.points = [];
this.paintBrush = true
},
/*
# 绘制笔迹
# 1.为保证笔迹实时显示,必须在移动的同时绘制笔迹
# 2.为保证笔迹连续每次从路径集合中区两个点作为起点moveTo和终点(lineTo)
# 3.将上一次的终点作为下一次绘制的起点(即清除第一个点)
*/
draw() {
let point1 = this.points[0]
let point2 = this.points[1]
this.points.shift()
this.oc.moveTo(point1.X, point1.Y)
this.oc.lineTo(point2.X, point2.Y)
this.oc.stroke()
this.oc.draw(true)
},
//清空画布
clear() {
let that = this;
uni.getSystemInfo({
success: function(res) {
that.paintBrush = false
let canvasw = res.windowWidth;
let canvash = res.windowHeight;
that.oc.clearRect(0, 0, canvasw, canvash);
that.oc.draw(true);
}
})
}
}
};
</script>
<style>
page {
background: #fbfbfb;
height: auto;
}
.maskBody {
position: fixed;
transform: rotate(90deg);
background: url(../../static/img/anli.png) no-repeat;
background-size: contain;
}
.maskBody .closeMask {
background-color: #FFFFFF;
position: fixed;
right: 16rpx;
top: 12rpx;
width: 108rpx;
height: 45rpx;
font-size: 32rpx;
font-weight: 400;
color: #999999;
line-height: 45rpx;
text-align: right;
}
.sealWrapBox {
background: #FFFFFF;
padding: 15px;
height: -webkit-fill-available;
}
.wrapper {
width: 100%;
overflow: hidden;
display: flex;
align-content: center;
flex-direction: row;
justify-content: center;
font-size: 28rpx;
}
.handWriting {
background: #fff;
width: 100%;
height: 100%;
}
.handRight {
display: inline-flex;
align-items: space-between;
width: 100%;
height: 50rpx;
transform: rotate(90deg);
position: absolute;
left: 300rpx;
bottom: 40%;
}
.handRight image {
width: 40rpx;
height: 40rpx;
}
.handCenter {
border-left: 4rpx dashed #e9e9e9;
flex: 5;
overflow: hidden;
box-sizing: border-box;
}
.handTitle {
flex: 1;
color: #666;
width: 100%;
height: 40rpx;
line-height: 40rpx;
}
.handBtn button {
font-size: 28rpx;
}
.handBtn {
height: 95vh;
display: inline-flex;
flex-direction: column;
justify-content: space-between;
align-content: space-between;
flex: 1;
}
.lookBtn {
position: absolute;
top: 40px;
left: 0;
transform: rotate(90deg);
width: 128rpx;
height: 45rpx;
font-size: 32rpx;
font-weight: 400;
color: #1C66FF;
line-height: 45rpx;
}
.delBtn {
position: absolute;
bottom: 90px;
left: 0rpx;
transform: rotate(90deg);
color: #979797;
width: 120rpx;
height: 60rpx;
line-height: 60rpx;
text-align: center;
}
.delBtn image {
position: absolute;
top: 13rpx;
left: 25rpx;
}
.saveBtnActive {
background-color: #1C66FF !important;
color: #FFFFFF !important;
}
.saveBtn {
position: absolute;
bottom: 37px;
left: 0rpx;
transform: rotate(90deg);
color: #979797;
width: 120rpx;
height: 60rpx;
line-height: 60rpx;
text-align: center;
background: #D6D6D6;
border-radius: 8rpx;
}
.previewBtn {
position: absolute;
top: 500rpx;
left: 0rpx;
transform: rotate(90deg);
color: #666;
}
</style>

View File

@@ -1,183 +0,0 @@
<template>
<view class="uni-searchbar">
<view :style="{borderRadius:radius+'px',backgroundColor: bgColor}" class="uni-searchbar__box" @click="searchClick">
<!-- #ifdef MP-ALIPAY -->
<view class="uni-searchbar__box-icon-search">
<uni-icons color="#999999" size="18" type="search" />
</view>
<!-- #endif -->
<!-- #ifndef MP-ALIPAY -->
<uni-icons color="#999999" class="uni-searchbar__box-icon-search" size="18" type="search" />
<!-- #endif -->
<input v-if="show" :focus="showSync" :placeholder="placeholder" :maxlength="maxlength" @confirm="confirm" class="uni-searchbar__box-search-input"
confirm-type="search" type="text" v-model="searchVal" />
<text v-else class="uni-searchbar__text-placeholder">{{ placeholder }}</text>
<view v-if="show && (clearButton==='always'||clearButton==='auto'&&searchVal!=='')" class="uni-searchbar__box-icon-clear" @click="clear">
<uni-icons color="#999999" class="" size="24" type="clear" />
</view>
</view>
<text @click="cancel" class="uni-searchbar__cancel" v-if="cancelButton ==='always' || show && cancelButton ==='auto'">{{cancelText}}</text>
</view>
</template>
<script>
import uniIcons from "../uni-icons/uni-icons.vue";
export default {
name: "UniSearchBar",
components: {
uniIcons
},
props: {
placeholder: {
type: String,
default: "请输入搜索内容"
},
radius: {
type: [Number, String],
default: 5
},
clearButton: {
type: String,
default: "auto"
},
cancelButton: {
type: String,
default: "auto"
},
cancelText: {
type: String,
default: '取消'
},
bgColor: {
type: String,
default: "#F8F8F8"
},
maxlength: {
type: [Number, String],
default: 100
}
},
data() {
return {
show: false,
showSync: false,
searchVal: ""
}
},
watch: {
searchVal() {
this.$emit("input", {
value: this.searchVal
})
}
},
methods: {
searchClick() {
if (this.show) {
return
}
this.searchVal = ""
this.show = true;
this.$nextTick(() => {
this.showSync = true;
})
},
clear() {
this.searchVal = ""
},
cancel() {
this.$emit("cancel", {
value: this.searchVal
});
this.searchVal = ""
this.show = false
this.showSync = false
// #ifndef APP-PLUS
uni.hideKeyboard()
// #endif
// #ifdef APP-PLUS
plus.key.hideSoftKeybord()
// #endif
},
confirm() {
// #ifndef APP-PLUS
uni.hideKeyboard();
// #endif
// #ifdef APP-PLUS
plus.key.hideSoftKeybord()
// #endif
this.$emit("confirm", {
value: this.searchVal
})
}
}
};
</script>
<style lang="scss" scoped>
$uni-searchbar-height: 36px;
.uni-searchbar {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
position: relative;
padding: $uni-spacing-col-base;
background-color: $uni-bg-color;
}
.uni-searchbar__box {
/* #ifndef APP-NVUE */
display: flex;
box-sizing: border-box;
/* #endif */
overflow: hidden;
position: relative;
flex: 1;
justify-content: center;
flex-direction: row;
align-items: center;
height: $uni-searchbar-height;
padding: 5px 8px 5px 0px;
border-width: 0.5px;
border-style: solid;
border-color: $uni-border-color;
}
.uni-searchbar__box-icon-search {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
width: 32px;
justify-content: center;
align-items: center;
color: $uni-text-color-placeholder;
}
.uni-searchbar__box-search-input {
flex: 1;
font-size: $uni-font-size-base;
color: $uni-text-color;
}
.uni-searchbar__box-icon-clear {
align-items: center;
line-height: 24px;
padding-left: 5px;
}
.uni-searchbar__text-placeholder {
font-size: $uni-font-size-base;
color: $uni-text-color-placeholder;
margin-left: 5px;
}
.uni-searchbar__cancel {
padding-left: 10px;
line-height: $uni-searchbar-height;
font-size: 14px;
color: $uni-text-color;
}
</style>

View File

@@ -1,25 +0,0 @@
<template>
<view :style="{ height: statusBarHeight }" class="uni-status-bar">
<slot />
</view>
</template>
<script>
var statusBarHeight = uni.getSystemInfoSync().statusBarHeight + 'px'
export default {
name: 'UniStatusBar',
data() {
return {
statusBarHeight: statusBarHeight
}
}
}
</script>
<style lang="scss" scoped>
.uni-status-bar {
width: 750rpx;
height: 20px;
// height: var(--status-bar-height);
}
</style>

View File

@@ -1,82 +0,0 @@
## 调用方式
- 视图调用
```html
<v-tabs
:tabs="[1,2,3,4]"
height="45px"
v-model="activeTab"
color="#333"
activeColor="#1abc9c"
fontSize="14px"
activeFontSize="16px"
:lineHeight="4px"
:lineScale="0.8"
lineColor="#1abc9c"
/>
```
- js 调用
```js
import vTabs from '@/components/v-tabs'
export default {
components: {
vTabs,
},
data() {
activeTab: 0
},
}
```
- 参数说明
| 参数 | 类型 | 默认值 | 说明 |
| :-------------: | :--------------: | :-----: | :----------: |
| value | String 或 Number | 0 | 必传 |
| tabs | Array | [] | tabs 数量 |
| height | String | '45px' | tab 高度 |
| backgroundColor | String | '' | 选中背景 |
| borderRadius | String | 5px | 圆角 |
| color | String | #333333 | 默认文字颜色 |
| activeColor | String | #333333 | 选中文字颜色 |
| fontSize | String | 14px | 默认文字大小 |
| activeFontSize | String | 14px | 选中文字大小 |
| lineScale | Number | 0.6 | 下划线缩放 |
| lineHeight | [Number, String] | 3 | 下划线高度 |
| lineColor | Sring | #007AFF | 下划线颜色 |
## 事件
|事件名称|参数|
|:-----:|:-----:|
|@change|activeTab|
## 更新日志
### 2020-06-09
1. 修复小程序端选中的下划线不显示问题
2. 新增 tab 高度设置
3. `lineHeight` 修改为只支持 `String` 方式
### 2020-06-11
1. 添加 `change` 事件
2. 修复插件内容问题
3. 修复下划线不居中问题
### 2020-06-11
1. 添加注释
2. 修复 bug
### 2020-07-05
1. 新增 `padding` 的可配置
2. 修复 `v-model` 双向绑定问题
3. 修复初始化下划线没定位的为题

View File

@@ -1,241 +0,0 @@
<template>
<view class="v-tabs" :style="{ height: height }">
<scroll-view class="scroll-view" :show-scrollbar="false" scroll-x scroll-with-animation :scroll-left="scrollLeft" style="width: auto; height: 100%; overflow: hidden;">
<view class="v-tabs__inner">
<view
class="v-tabs__item"
:style="{
color: activeTab == i ? activeColor : color,
fontSize: activeTab == i ? activeFontSize : fontSize,
backgroundColor: activeTab == i ? backgroundColor : '',
borderRadius,
padding,
}"
:data-index="i"
:class="{ active: activeTab == i }"
@tap="handleTapItem"
v-for="(v, i) in tabs"
:key="i"
>
<view class="">
{{ v }}
</view>
<view class="bottomborder"></view>
</view>
</view>
<!-- <view
class="v-tabs__line"
:style="{ width: `${lineWidth}px`, height: `${lineHeight}`, backgroundColor: lineColor, transform: `translateX(${lineLeft}px)`, top: `calc(${height} - ${lineHeight})` }"
></view> -->
</scroll-view>
</view>
</template>
<script>
/**
* tabs 选项卡
* @description tabs选项卡
* @property {String|Number} value 双向绑定的选中值
* @property {String} height=50px 高度
* @property {Array} tabs 选项卡列表 ['测试1', '测试2', '测试3']
* @property {String} backgroundColor 选中背景色
* @property {String} borderRadius 选中圆角
* @property {String} color 默认文字的颜色
* @property {String} activeColor 选中文字颜色
* @property {String} fontSize 默认文字大小
* @property {String} activeFontSize 选中文字大小
* @property {Number} lineScale 选中标签下划线的缩放级别
* @property {String} lineHeight 选中标签下划线的高度
* @property {String} lineColor 选中下划线的颜色
*
* @event {Function(activeTab)} change 改变标签触发
*/
export default {
name: 'VTabs',
props: {
value: {
type: [String, Number],
default: 0
},
height: {
type: String,
default: '45px'
},
tabs: {
type: Array,
default() {
return []
}
},
backgroundColor: {
type: String,
default: 'transparent'
},
borderRadius: {
type: String,
default: '5px'
},
color: {
type: String,
default: '#333333'
},
activeColor: {
type: String,
default: '#007AFF'
},
fontSize: {
type: String,
default: '14px'
},
activeFontSize: {
type: String,
default: '14px'
},
padding: {
type: String,
default: '10rpx 20rpx'
},
lineScale: {
type: Number,
default: 0.6
},
lineHeight: {
type: String,
default: '3px'
},
lineColor: {
type: String,
default: '#007AFF'
}
},
data() {
return {
scrollLeft: 0,
activeTab: 0,
width: 0,
lineLeft: 0,
lineWidth: 0
}
},
watch: {
activeTab(newVal) {
this.$emit('input', newVal * 1)
},
value(newVal) {
this.activeTab = newVal
this.getTabsWidth(0)
}
},
methods: {
handleTapItem(e) {
const index = e.currentTarget.dataset.index
if (this.activeTab != index) {
this.activeTab = index
this.getTabsWidth(e.currentTarget.offsetLeft)
this.$emit('change', this.activeTab)
}
},
getTabsWidth(offsetLeft) {
const query = uni.createSelectorQuery().in(this)
query
.select('.v-tabs')
.boundingClientRect(data => {
this.width = data.width
})
.exec()
setTimeout(() => {
let i = 0
let width = 0
query
.selectAll('.v-tabs__item')
.boundingClientRect(data => {
width = data.reduce((total, currentValue, currentIndex, arr) => {
if (currentIndex < this.activeTab) {
total = total + currentValue.width
}
return total
}, 0)
const padding = this.padding.split(' ')[0]
const res = /(\d+)(upx|rpx|px)/.exec(padding)
if (res && (res[2] == 'upx' || res[2] == 'rpx')) {
width += uni.upx2px(res[1]) * 2 * this.activeTab
} else {
width += res[1] * this.activeTab
}
})
.exec()
query
.select('.v-tabs__item.active')
.boundingClientRect(data => {
const ol = offsetLeft ? offsetLeft : width
if (data.width) {
this.lineLeft = ol + (data.width * (1 - this.lineScale)) / 2
this.lineWidth = data.width * this.lineScale
this.scrollLeft = ol - (this.width - data.width) / 2
}
})
.exec()
}, 10)
}
},
mounted() {
this.activeTab = this.value
this.getTabsWidth(0)
}
}
</script>
<style lang="scss" scoped>
.v-tabs {
position: relative;
width: 100%;
white-space: nowrap;
overflow: hidden;
border-bottom: 1rpx solid #dddddd;
.v-tabs__inner {
position: relative;
display: flex;
align-items: center;
height: 100%;
justify-content: center;
background-color: #fefefe;
// border-bottom: 1rpx solid #dddddd;
border-bottom: 0;
}
.active{
border-radius: 0 !important;
.bottomborder{
width: 42rpx;
height: 6rpx;
margin: 0 auto;
background-color: #1B66FF;
border-radius: 20rpx;
overflow: hidden;
display: block !important;
margin-top: 10rpx;
}
}
.v-tabs__item {
// display: inline-flex;
margin-right: 20upx;
transition: all 0.3s ease;
&:last-child {
margin-right: 0;
}
}
.v-tabs__line {
position: absolute;
z-index: 99;
transition: all 0.3s linear;
border-radius: 4upx;
}
}
/deep/ ::-webkit-scrollbar {
display: none;
}
</style>