This commit is contained in:
2023-05-04 14:12:52 +08:00
commit 7fb77e5b6d
135 changed files with 24465 additions and 0 deletions

View File

@@ -0,0 +1,255 @@
<template>
<div class="dropdown-menu" :class="{'toggle_disabled': disabled === true}" ref="elemId">
<div v-if="inputed === false" class="dropdown-menu__item dropdown-menu__item_1">
<div class="dropdown-menu__title" :class="{'dropdown-menu__title_up': up === true,'dropdown-menu__title--active': open === true,'dropdown-menu__title--active_up': up === true && open === true}" @click="toggleItem">
<div class="ellipsis chose_T">{{active === '' ? '请选择' : option[active].label}}</div>
<div class="iconfont dropdown_icon"></div>
</div>
<div v-show="active !== '' && cancleShow === true" class="iconfont error_icon" @click="cancleDropdown"></div>
</div>
<div v-if="inputed === true" class="fxrow dropdown-menu__item dropdown-menu__item_2">
<input
type="text"
placeholder="请输入"
class="fxcol drop_input"
:value="value"
@input="handleChange($event)">
<span class="fxcol dropdown-menu__title dropdown-menu__title_2" :class="{'dropdown-menu__title_up': up === true,'dropdown-menu__title--active': open === true,'dropdown-menu__title--active_up': up === true && open === true}" @click="toggleItem">
<div class="ellipsis">&nbsp;</div>
<div class="iconfont dropdown_icon"></div>
</span>
</div>
<div v-show="open" class="dropdown-item" :style="up === false ? 'top:' + gap : 'bottom:' + gap">
<div ref="dropdown" class="dropdown-item__content">
<div v-show="option.length > 0" v-for="(e, i) in option" :key="e.value" @click="$emit('dropdownMenu', i)" class="fxrow dropdown-item__option dropdown-item__option--active" :style="{height: gap, lineHeight: gap}">
<div class="cell__title" :class="{'cell__title--active': i + '' === active}"><span>{{e.label}}</span></div>
<div class="iconfont check_icon" :class="{'check_icon--checked': i + '' === active}"></div>
</div>
<div v-show="option.length === 0" class="fxrow dropdown-item__option dropdown-item__option--active" :style="{height: gap, lineHeight: gap}" @click="handleBlur">
<div class="cell__title"><span>无匹配数据</span></div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'DropdownMenu',
model: {
prop: 'value',
event: 'input'
},
props: {
value: String,
option: Array,
active: String,
open: Boolean,
up: {
type: Boolean,
default: false
},
disabled: {
type: Boolean,
default: false
},
inputed: {
type: Boolean,
default: false
},
gap: {
type: String,
default: '.9rem'
},
autoHeight: {
type: Boolean,
default: false
},
cancleShow: {
type: Boolean,
default: false
}
},
methods: {
toggleItem () {
let cheight = document.body.clientHeight
let bottom = this.$refs.elemId.getBoundingClientRect().bottom
if (!this.autoHeight) {
this.$refs.dropdown.style.maxHeight = (cheight - bottom - 20) + 'px'
}
this.$emit('toggleItem')
},
handleChange ($event) {
let cheight = document.body.clientHeight
let bottom = this.$refs.elemId.getBoundingClientRect().bottom
if (!this.autoHeight) {
this.$refs.dropdown.style.maxHeight = (cheight - bottom - 20) + 'px'
}
this.$emit('input', $event.target.value)
this.$emit('handleChange', $event.target.value)
},
handleBlur () {
this.$emit('handleBlur')
},
cancleDropdown () {
this.$emit('cancleDropdown')
}
}
}
</script>
<style lang="stylus" scoped>
@import '~@style/mixin'
.dropdown-menu
position relative
height .9rem
border .02rem solid #dcdfe6
border-radius 4px
background-color #fff
user-select none
width 100%
// padding 0 .15rem
.selectopt
// _font(.3rem, .9rem, #606266)
.selectbtn
position relative
flex 0 0 1rem
_wh(.8rem, .8rem)
vertical-align top
background-color #cccccc
&::before
content ''
width 0
height 0
border-left .5rem solid transparent
border-right .5rem solid transparent
border-top .5rem solid white
position absolute
right .15rem
top .15rem
pointer-events none
z-index 3
.options
position absolute
z-index 100000
top .9rem
width 100%
li
width 100%
_font(.12rem, .35rem, #000000)
background-color #cccccc
border-top 1px solid #ffffff
padding 0 .3rem 0 .1rem
user-select none
&:hover
background:#999
.dropdown-menu__item
justify-content center
height inherit
width 100%
.dropdown-menu__item_1
_fj()
.dropdown-menu__item_2
align-items flex-start
.drop_input
height .86rem
width calc(100% - 3rem)
padding 0 .15rem
color #606266
font-size .3rem
line-height .86rem
.dropdown-menu__title
position relative
width calc(100% - .5rem)
padding-left .15rem
color #606266
font-size .3rem
line-height .44rem
width 100%
_fj()
// display block
// &::after
// position absolute
// top 50%
// right .16rem
// margin-top -.1rem
// border .06rem solid
// border-color transparent transparent #606266 #606266
// transform rotate(-45deg)
// opacity 0.8
// content ''
.dropdown-menu__title_2
line-height .9rem
max-width 1.4rem
&::after
right .16rem
.dropdown-menu__title_up
&::after
transform rotate(135deg)
top calc(50% + .06rem)
.dropdown-menu__title--active, .dropdown-menu__title--active div
color $red !important
&::after
border-color transparent transparent currentColor currentColor
margin-top -.02rem
transform rotate(135deg)
.dropdown-menu__title--active_up, .dropdown-menu__title--active_up div
&::after
transform rotate(-45deg)
top calc(50% - .06rem)
.dropdown-item
position absolute
left 0
width 100%
z-index 10
border-radius 4px
overflow hidden
box-shadow 0 0 .08rem 0.02rem rgba(160,160,160,0.9)
.dropdown-item__content
position relative
width 100%
height auto
z-index 2047
overflow-y auto
background-color #fff
transition transform 0.3s
.dropdown-item__option
width 100%
// height .9rem
padding 0 .15rem
overflow hidden
.cell__title
height inherit
overflow hidden
span
_font(.3rem, inherit, #606266)
.cell__title--active span
color $red
.toggle_disabled
background-color #f5f7fa
border 0.02rem solid #e4e7ed
cursor not-allowed
.dropdown-menu__title
div
color #929292
&::after
border-color transparent transparent #929292 #929292
.chose_T
width 100%
overflow hidden
.top
top .9rem
.bottom
top .9rem
.dropdown_icon
font-size .25rem
color #dcdfe6
.error_icon
width .3rem
height .3rem
font-size .25rem
line-height .3rem
color #dcdfe6
border .01rem solid #dcdfe6
margin-right .15rem
</style>

View File

@@ -0,0 +1,52 @@
<template>
<div>
<input
type="number"
class="sin_input"
:value="value"
:disabled = "disabled"
@focus="handleFocus($event)"
@blur="handleBlur($event)"
@input="handleInput($event)"/>
</div>
</template>
<script>
export default {
name: 'input-number',
props: {
value: String,
disabled: {type: Boolean, default: false},
min: {type: String, default: '0.000'},
max: {type: String}
},
data () {
return {
cur: ''
}
},
methods: {
handleFocus ($event) {
this.cur = $event.target.value
$event.target.value = ''
this.$emit('input', $event.target.value)
},
handleBlur ($event) {
if ($event.target.value === '') {
$event.target.value = this.cur
}
if (Number($event.target.value) < Number(this.min)) {
$event.target.value = Number(this.min).toFixed(3)
}
this.$emit('input', $event.target.value)
},
handleInput ($event) {
$event.target.value = ($event.target.value.match(/^\d*(\.?\d{0,3})/g)[0]) || null
if (Number($event.target.value) > Number(this.max)) {
$event.target.value = Number(this.max).toFixed(3)
}
this.$emit('input', $event.target.value)
}
}
}
</script>

View File

@@ -0,0 +1,85 @@
<template>
<div class="fxcol">
<input
class="filter-input i-border"
:disabled="disabled"
:type="type"
ref="input"
:value="numberValue"
:placeholder="placeholder"
oninput="value=value.replace(/[^\d.]/g,'')"
@input="handleChange"
/>
</div>
</template>
<script>
export default {
name: 'limitInput',
props: {
disabled: Boolean,
type: String,
placeholder: String,
value: '', // 传过来的值
max: Number,
min: Number,
defaultValue: '' // 默认值
},
data () {
return {
numberValue: this.value
}
},
watch: {
value (val) { // 监听传来的value值并传递给新定义的值
// debugger
this.numberValue = Number(val)
},
max (val) { // 因为最大值是根据上个值输入而变化的,所以要监听相应变化
this.max = val
},
min (val) { // 因为最小值是根据上个值输入而变化的,所以要监听相应变化
this.min = val
},
numberValue (val) { // emit input事件,可令父组件进行v-model绑定
this.$emit('input', val)
},
disabled (val) {
this.disabled = val
},
defaultValue (val) { // 要根据上面的值变化而相应变化,所以要监听
this.numberValue = val
}
},
methods: {
handleChange (event) {
let val = event.target.value.trim()
if (val < 0 || isNaN(val)) {
this.numberValue = 0
return
}
if (val) {
val = Number(val)
this.numberValue = val
if (val > Number(this.max)) this.numberValue = this.max
if (val < Number(this.min)) this.numberValue = this.min
} else {
this.numberValue = 0
}
}
},
mounted () {
if (this.defaultValue) {
this.numberValue = this.defaultValue
}
}
}
</script>
<style lang="stylus" scoped>
// input
// width 100%
.i-border
border 1px solid #a1a1a1
border-radius 3px
text-align center
</style>

69
src/components/Modal.vue Normal file
View File

@@ -0,0 +1,69 @@
<template>
<div class="md-modal" v-if="mdShow">
<transition name="bounce">
<div class="modal-inner">
<div class="modal-content">
<!-- <div class="modal-message">{{question}}</div> -->
<slot></slot>
</div>
<div class="mgt15 fxrow">
<button class="fxcol btn btn-disabled submit-button" @click="closeModal">取消</button>
<button class="btn btn-disabled submit-button bl1px" v-if="comfirmDisable">确认</button>
<button class="btn submit-button" v-if="!comfirmDisable" @click="comfirm">确认</button>
</div>
</div>
</transition>
<transition name="fade">
<div class="overlay"></div>
</transition>
</div>
</template>
<script>
export default {
name: 'Modal',
props: {
// question: String,
mdShow: Boolean,
comfirmDisable: Boolean,
type: String
},
methods: {
closeModal () {
this.$emit('closeModalCallback')
},
comfirm () {
this.$emit('comfirmCallback', this.type)
}
}
}
</script>
<style lang="stylus" scoped>
.modal-inner
position fixed
top 50%
left 50%
width 80%
font-size .28rem
overflow hidden
transition .3s
border-radius 4px
background-color #fff
transform translate3d(-50%, -50%, 0)
z-index 2018
.overlay
position fixed
top 0
left 0
width 100%
height 100%
background-color rgba(0, 0, 0, .7)
z-index 11
>>>.btn
border-radius 0
>>>.submit-button
margin 0
.bl1px
border-left 1px solid #fff
</style>

53
src/components/NavBar.vue Normal file
View File

@@ -0,0 +1,53 @@
<template>
<header>
<span @click="goBack" class="icon-back"></span>
<span class="fxcol">{{title}}</span>
<div class="icon-home" @click="goHome"></div>
</header>
</template>
<script>
export default {
name: 'NavBar',
props: {
title: String,
path: String,
inner: {
type: Boolean,
default: false
},
inner2: {
type: Boolean,
default: false
}
},
methods: {
goBack () {
if (this.inner) {
this.$router.back()
} else if (this.inner2) {
this.$emit('goIn')
} else {
this.$router.push('/home')
}
},
goHome () {
this.$store.dispatch('setKeepAlive', [])
this.$router.push('/home')
}
}
}
</script>
<style lang="stylus">
@import '~@style/mixin'
.icon-back
flex 0 0 .42rem
height .86rem
_bis('../images/back.png',.42rem)
.icon-home
cursor pointer
flex 0 0 .4rem
height .86rem
_bis('../images/home.png', .4rem)
</style>

View File

@@ -0,0 +1,137 @@
<template>
<div class="bottom-filter-tip">
<div class="filter-label txtjustify">{{label}}</div>
<div class="fxcol mgl20 relative">
<input
type="text"
class="filter-input filter-scan-input search_input"
ref="scaninput"
:placeholder="keyCode === '' ? placeholder : keyCode"
:disabled="disabled"
:value="value"
@focus="handleFocus($event)"
@blur="handleBlur($event)"
@input="handleChange($event)">
<div class="button_box">
<button class="search_box_icon fxcol" @click="handleScan">
<span class="iconfont scan_icon" :class="{'scan_icon_checked': type === true}"></span>
</button>
<button class="search_box_icon fxcol" @click="handleKey">
<span class="iconfont key_icon" :class="{'key_icon_checked': type === false}"></span>
</button>
<button v-show="seaShow === true" class="search_box_icon fxcol" @click="handleSearch">
<span class="iconfont search_icon" :class="{'key_icon_checked': type === false}"></span>
</button>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'SearchBox',
model: {
prop: 'value',
event: 'input'
},
props: {
value: String,
label: String,
focused: {
type: Boolean,
default: false
},
seaShow: {
type: Boolean,
default: true
},
keyCode: {
type: String,
default: ''
},
disabled: {
type: Boolean,
default: false
}
},
data () {
return {
placeholder: '',
type: '',
cur: ''
}
},
mounted () {
if (!this.focused) this.handleScan()
},
methods: {
handleScan () {
this.$refs.scaninput.focus()
this.placeholder = '请扫码键输入'
this.type = true
this.$emit('input', '')
},
handleKey () {
this.$refs.scaninput.focus()
this.placeholder = '请键盘输入'
this.type = false
// this.$emit('input', this.cur)
},
handleFocus ($event) {
this.cur = $event.target.value
this.placeholder = '请扫码键输入'
this.type = false
// $event.target.value = ''
// this.$emit('input', $event.target.value)
},
handleBlur ($event) {
this.type = ''
this.placeholder = ''
// if ($event.target.value === '') {
// $event.target.value = this.cur
// }
this.$emit('input', $event.target.value)
},
handleChange ($event) {
if ($event.target.value) {
if (this.type) {
this.cur = $event.target.value.split('##')[0]
let _this = this
setTimeout(() => {
_this.$emit('input', this.cur)
_this.$emit('handleChange', this.cur, true)
_this.$emit('getScanTxt', $event.target.value)
}, 20)
this.$refs.scaninput.blur()
} else if (!this.type) {
this.cur = $event.target.value
this.$emit('input', this.cur)
this.$emit('handleChange', this.cur, false)
} else {
this.cur = $event.target.value
}
}
},
handleSearch () {
this.$emit('handleChange', this.cur, true)
this.$refs.scaninput.blur()
}
}
}
</script>
<style lang="stylus" scoped>
@import '~@style/mixin'
.search_input
padding-right 2.1rem
.button_box
_fj()
position absolute
top 50%
transform translateY(-50%)
right 1px
// height .9rem
.search_box_icon
_wh(.7rem, 100%)
background-color #fff
</style>

114
src/components/alert.vue Normal file
View File

@@ -0,0 +1,114 @@
<template>
<div>
<transition name="bounce">
<div class="alert-wrap">
<div class="text">{{alertMsg}}</div>
<div class="hairline--top">
<button class="button--large" @click="onClose"><span>确认</span></button>
</div>
</div>
</transition>
<transition name="fade">
<div class="overlay"></div>
</transition>
</div>
</template>
<script>
import { mapState } from 'vuex'
export default {
data () {
return {}
},
computed: mapState({
alertMsg: state => state.com.alertMsg
}),
methods: {
onClose () {
this.$store.dispatch('showAlert', false)
}
}
}
</script>
<style lang="stylus" scoped>
@keyframes fade-in {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@keyframes fade-out {
from {
opacity: 1;
}
to {
opacity: 0;
}
}
.bounce-enter {
opacity 0
transform translate3d(-50%, -50%, 0) scale(0.7)
}
.bounce-leave-active {
opacity 0
transform translate3d(-50%, -50%, 0) scale(0.9)
}
.fade-enter-active
animation 0.3s fade-in
.fade-leave-active
animation 0.3s fade-out
.overlay
position fixed
top 0
left 0
width 100%
height 100%
background-color rgba(0, 0, 0, 0.7)
z-index 2012
.alert-wrap
position fixed
top 50%
left 50%
width 80%
transition .3s
transform translate3d(-50%, -50%, 0)
overflow hidden
border-radius 4px
border 1px solid #ebeef5
background-color #fff
box-shadow 0 2px 12px 0 rgba(0,0,0,.3)
font-size .28rem
line-height .42rem
color #929292
z-index 2019
.text
padding .5rem
max-height 60vh
overflow-y auto
text-align center
-webkit-overflow-scrolling touch
white-space pre-wrap
[class*='hairline']
position relative
[class*='hairline']::after
content ' '
position absolute
pointer-events none
box-sizing border-box
top -50%
left -50%
right -50%
bottom -50%
transform scale(0.5)
border 0 solid #ebedf0
.hairline--top::after
border-top-width 1px
.button--large
width 100%
height 1rem
line-height 1rem
color #e74f1a
</style>

View File

@@ -0,0 +1,30 @@
<template>
<div class="loading">
<div class="loader-inner">
<img src="../images/oval-white.svg">
</div>
</div>
</template>
<style lang="stylus" scoped>
.loading
position fixed
width 100%
height 100%
z-index 100000
.loader-inner
position absolute
z-index 100000
height 50px
width 50px
padding 10px
transform translate(-25px, -25px)
left 50%
top 50%
overflow hidden
background-color rgba(0, 0, 0, .5)
border-radius 3px
img
width 100%
height 100%
</style>

43
src/components/toast.vue Normal file
View File

@@ -0,0 +1,43 @@
<template>
<div class="toast">
<div class="toast-wrap">
<div class="text">
{{toastMsg}}
</div>
</div>
</div>
</template>
<script>
import { mapState } from 'vuex'
export default {
data () {
return {}
},
computed: mapState({
toastMsg: state => state.com.toastMsg
})
}
</script>
<style lang="stylus" scoped>
.toast
.toast-wrap
position fixed
z-index 10000
width 100%
height .64rem
line-height .64rem
text-align center
left 50%
top 50%
transform translate(-50%, -50%)
.text
display inline-block
width auto
padding 0 10px
border-radius 10px
background rgba(0, 0, 0, 0.6)
font-size .28rem
color #fff
</style>