You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
575 lines
14 KiB
575 lines
14 KiB
<template>
|
|
<uni-page-head :uni-page-head-type="type">
|
|
<div
|
|
:style="{transitionDuration:duration,transitionTimingFunction:timingFunc,backgroundColor:bgColor,color:textColor}"
|
|
:class="headClass"
|
|
class="uni-page-head"
|
|
>
|
|
<div class="uni-page-head-hd">
|
|
<div
|
|
v-show="backButton"
|
|
class="uni-page-head-btn"
|
|
@click="_back"
|
|
>
|
|
<i
|
|
:style="{color:color,fontSize:'27px'}"
|
|
class="uni-btn-icon"
|
|
></i>
|
|
</div>
|
|
<template v-for="(btn,index) in btns">
|
|
<div
|
|
v-if="btn.float === 'left'"
|
|
:key="index"
|
|
:style="{backgroundColor: type==='transparent'?btn.background:'transparent',width:btn.width}"
|
|
:badge-text="btn.badgeText"
|
|
:class="{'uni-page-head-btn-red-dot':btn.redDot||btn.badgeText,'uni-page-head-btn-select':btn.select}"
|
|
class="uni-page-head-btn"
|
|
>
|
|
<i
|
|
:style="_formatBtnStyle(btn)"
|
|
class="uni-btn-icon"
|
|
@click="_onBtnClick(index)"
|
|
v-html="_formatBtnFontText(btn)"
|
|
/>
|
|
</div>
|
|
</template>
|
|
</div>
|
|
<div
|
|
v-if="!searchInput"
|
|
class="uni-page-head-bd"
|
|
>
|
|
<div
|
|
:style="{fontSize:titleSize,opacity:type==='transparent'?0:1}"
|
|
class="uni-page-head__title"
|
|
>
|
|
<i
|
|
v-if="loading"
|
|
class="uni-loading"
|
|
/>
|
|
<img
|
|
v-if="titleImage!==''"
|
|
:src="titleImage"
|
|
class="uni-page-head__title_image"
|
|
>
|
|
<template v-else>
|
|
{{ titleText }}
|
|
</template>
|
|
</div>
|
|
</div>
|
|
<div
|
|
v-if="searchInput"
|
|
:style="{'border-radius':searchInput.borderRadius,'background-color':searchInput.backgroundColor}"
|
|
class="uni-page-head-search"
|
|
>
|
|
<div
|
|
:style="{color:searchInput.placeholderColor}"
|
|
:class="[`uni-page-head-search-placeholder-${focus || text ? 'left' : searchInput.align}`]"
|
|
class="uni-page-head-search-placeholder"
|
|
v-text="text || composing ? '' : searchInput.placeholder"
|
|
/>
|
|
<v-uni-input
|
|
ref="input"
|
|
v-model="text"
|
|
:focus="searchInput.autoFocus"
|
|
:disabled="searchInput.disabled"
|
|
:style="{color:searchInput.color}"
|
|
:placeholder-style="`color:${searchInput.placeholderColor}`"
|
|
class="uni-page-head-search-input"
|
|
confirm-type="search"
|
|
@focus="_focus"
|
|
@blur="_blur"
|
|
@update:value="_input"
|
|
/>
|
|
</div>
|
|
<div class="uni-page-head-ft">
|
|
<template v-for="(btn,index) in btns">
|
|
<div
|
|
v-if="btn.float !== 'left'"
|
|
:key="index"
|
|
:style="{backgroundColor: type==='transparent'?btn.background:'transparent',width:btn.width}"
|
|
:badge-text="btn.badgeText"
|
|
:class="{'uni-page-head-btn-red-dot':btn.redDot||btn.badgeText,'uni-page-head-btn-select':btn.select}"
|
|
class="uni-page-head-btn"
|
|
>
|
|
<i
|
|
:style="_formatBtnStyle(btn)"
|
|
class="uni-btn-icon"
|
|
@click="_onBtnClick(index)"
|
|
v-html="_formatBtnFontText(btn)"
|
|
/>
|
|
</div>
|
|
</template>
|
|
</div>
|
|
</div>
|
|
<div
|
|
v-if="type!=='transparent'&&type!=='float'"
|
|
:class="{'uni-placeholder-titlePenetrate': titlePenetrate}"
|
|
class="uni-placeholder"
|
|
/>
|
|
</uni-page-head>
|
|
</template>
|
|
<style>
|
|
uni-page-head {
|
|
display: block;
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
uni-page-head .uni-page-head {
|
|
position: fixed;
|
|
left: var(--window-left);
|
|
right: var(--window-right);
|
|
top: 0;
|
|
height: 44px;
|
|
height: calc(44px + constant(safe-area-inset-top));
|
|
height: calc(44px + env(safe-area-inset-top));
|
|
padding: 7px 3px;
|
|
padding-top: calc(7px + constant(safe-area-inset-top));
|
|
padding-top: calc(7px + env(safe-area-inset-top));
|
|
display: flex;
|
|
overflow: hidden;
|
|
justify-content: space-between;
|
|
box-sizing: border-box;
|
|
z-index: 998;
|
|
color: #fff;
|
|
background-color: #000;
|
|
transition-property: all;
|
|
}
|
|
|
|
uni-page-head .uni-page-head-titlePenetrate,
|
|
uni-page-head .uni-page-head-titlePenetrate .uni-page-head-bd,
|
|
uni-page-head .uni-page-head-titlePenetrate .uni-page-head-bd * {
|
|
pointer-events: none;
|
|
}
|
|
|
|
uni-page-head .uni-page-head-titlePenetrate * {
|
|
pointer-events: auto;
|
|
}
|
|
|
|
uni-page-head .uni-page-head.uni-page-head-transparent .uni-page-head-ft>div {
|
|
justify-content: center;
|
|
}
|
|
|
|
uni-page-head .uni-page-head~.uni-placeholder {
|
|
width: 100%;
|
|
height: 44px;
|
|
height: calc(44px + constant(safe-area-inset-top));
|
|
height: calc(44px + env(safe-area-inset-top));
|
|
}
|
|
|
|
uni-page-head .uni-placeholder-titlePenetrate {
|
|
pointer-events: none;
|
|
}
|
|
|
|
uni-page-head .uni-page-head * {
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
uni-page-head .uni-page-head-hd {
|
|
display: flex;
|
|
align-items: center;
|
|
font-size: 16px;
|
|
}
|
|
|
|
uni-page-head .uni-page-head-bd {
|
|
position: absolute;
|
|
left: 70px;
|
|
right: 70px;
|
|
min-width: 0;
|
|
user-select: auto;
|
|
}
|
|
|
|
.uni-page-head-btn {
|
|
position: relative;
|
|
width: auto;
|
|
margin: 0 2px;
|
|
word-break: keep-all;
|
|
white-space: pre;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.uni-page-head-transparent .uni-page-head-btn {
|
|
display: flex;
|
|
align-items: center;
|
|
width: 32px;
|
|
height: 32px;
|
|
border-radius: 50%;
|
|
background-color: rgba(0, 0, 0, 0.5);
|
|
}
|
|
|
|
uni-page-head .uni-btn-icon {
|
|
overflow: hidden;
|
|
min-width: 1em;
|
|
}
|
|
|
|
.uni-page-head-btn-red-dot::after {
|
|
content: attr(badge-text);
|
|
position: absolute;
|
|
right: 0;
|
|
top: 0;
|
|
background-color: red;
|
|
color: white;
|
|
width: 18px;
|
|
height: 18px;
|
|
line-height: 18px;
|
|
border-radius: 18px;
|
|
overflow: hidden;
|
|
transform: scale(0.5) translate(40%, -40%);
|
|
transform-origin: 100% 0;
|
|
}
|
|
|
|
.uni-page-head-btn-red-dot[badge-text]::after {
|
|
font-size: 12px;
|
|
width: auto;
|
|
min-width: 18px;
|
|
max-width: 42px;
|
|
text-align: center;
|
|
padding: 0 3px;
|
|
transform: scale(0.7) translate(40%, -40%);
|
|
}
|
|
|
|
.uni-page-head-btn-select>.uni-btn-icon::after {
|
|
display: inline-block;
|
|
font-family: "unibtn";
|
|
content: "\e601";
|
|
margin-left: 2px;
|
|
transform: rotate(-90deg) scale(0.8);
|
|
}
|
|
|
|
.uni-page-head-search {
|
|
position: relative;
|
|
display: flex;
|
|
flex: 1;
|
|
margin: 0 2px;
|
|
line-height: 30px;
|
|
font-size: 15px;
|
|
}
|
|
|
|
.uni-page-head-search-input {
|
|
width: 100%;
|
|
height: 100%;
|
|
padding-left: 34px;
|
|
text-align: left;
|
|
}
|
|
|
|
.uni-page-head-search-placeholder {
|
|
position: absolute;
|
|
max-width: 100%;
|
|
height: 100%;
|
|
padding-left: 34px;
|
|
overflow: hidden;
|
|
word-break: keep-all;
|
|
white-space: pre;
|
|
}
|
|
|
|
.uni-page-head-search-placeholder-right {
|
|
right: 0;
|
|
}
|
|
|
|
.uni-page-head-search-placeholder-center {
|
|
left: 50%;
|
|
transform: translateX(-50%);
|
|
}
|
|
|
|
.uni-page-head-search-placeholder::before {
|
|
position: absolute;
|
|
top: 0;
|
|
left: 2px;
|
|
width: 30px;
|
|
content: "\ea0e";
|
|
display: block;
|
|
font-size: 20px;
|
|
font-family: "uni";
|
|
text-align: center;
|
|
}
|
|
|
|
uni-page-head .uni-page-head-ft {
|
|
display: flex;
|
|
align-items: center;
|
|
flex-direction: row-reverse;
|
|
font-size: 13px;
|
|
}
|
|
|
|
uni-page-head .uni-page-head__title {
|
|
font-weight: bold;
|
|
font-size: 16px;
|
|
line-height: 30px;
|
|
text-align: center;
|
|
overflow: hidden;
|
|
white-space: nowrap;
|
|
text-overflow: ellipsis;
|
|
}
|
|
|
|
uni-page-head .uni-page-head__title .uni-loading {
|
|
width: 16px;
|
|
height: 16px;
|
|
margin-top: -3px;
|
|
}
|
|
|
|
uni-page-head .uni-page-head__title .uni-page-head__title_image {
|
|
width: auto;
|
|
height: 26px;
|
|
vertical-align: middle;
|
|
}
|
|
|
|
uni-page-head .uni-page-head-shadow {
|
|
overflow: visible;
|
|
}
|
|
|
|
uni-page-head .uni-page-head-shadow::after {
|
|
content: "";
|
|
position: absolute;
|
|
left: 0;
|
|
right: 0;
|
|
top: 100%;
|
|
height: 5px;
|
|
background-size: 100% 100%;
|
|
}
|
|
|
|
uni-page-head .uni-page-head-shadow-grey::after {
|
|
background-image: url("https://cdn.dcloud.net.cn/img/shadow-grey.png");
|
|
}
|
|
|
|
uni-page-head .uni-page-head-shadow-blue::after {
|
|
background-image: url("https://cdn.dcloud.net.cn/img/shadow-blue.png");
|
|
}
|
|
|
|
uni-page-head .uni-page-head-shadow-green::after {
|
|
background-image: url("https://cdn.dcloud.net.cn/img/shadow-green.png");
|
|
}
|
|
|
|
uni-page-head .uni-page-head-shadow-orange::after {
|
|
background-image: url("https://cdn.dcloud.net.cn/img/shadow-orange.png");
|
|
}
|
|
|
|
uni-page-head .uni-page-head-shadow-red::after {
|
|
background-image: url("https://cdn.dcloud.net.cn/img/shadow-red.png");
|
|
}
|
|
|
|
uni-page-head .uni-page-head-shadow-yellow::after {
|
|
background-image: url("https://cdn.dcloud.net.cn/img/shadow-yellow.png");
|
|
}
|
|
</style>
|
|
<script>
|
|
import appendCss from 'uni-platform/helpers/append-css'
|
|
import getRealPath from 'uni-platform/helpers/get-real-path'
|
|
|
|
import transparent from './transparent'
|
|
|
|
const FONTS = {
|
|
forward: '',
|
|
back: '',
|
|
share: '',
|
|
favorite: '',
|
|
home: '',
|
|
menu: '',
|
|
close: ''
|
|
}
|
|
export default {
|
|
name: 'PageHead',
|
|
mixins: [transparent],
|
|
props: {
|
|
backButton: {
|
|
type: Boolean,
|
|
default: true
|
|
},
|
|
backgroundColor: {
|
|
type: String,
|
|
default () {
|
|
return this.type === 'transparent' ? '#000' : '#F8F8F8'
|
|
}
|
|
},
|
|
textColor: {
|
|
type: String,
|
|
default: '#fff'
|
|
},
|
|
titleText: {
|
|
type: String,
|
|
default: ''
|
|
},
|
|
duration: {
|
|
type: String,
|
|
default: '0'
|
|
},
|
|
timingFunc: {
|
|
type: String,
|
|
default: ''
|
|
},
|
|
loading: {
|
|
type: Boolean,
|
|
default: false
|
|
},
|
|
titleSize: {
|
|
type: String,
|
|
default: '16px'
|
|
},
|
|
type: {
|
|
default: 'default',
|
|
validator (value) {
|
|
return ['default', 'transparent', 'float'].indexOf(value) !== -1
|
|
}
|
|
},
|
|
coverage: {
|
|
type: String,
|
|
default: '132px'
|
|
},
|
|
buttons: {
|
|
type: Array,
|
|
default () {
|
|
return []
|
|
}
|
|
},
|
|
searchInput: {
|
|
type: [Object, Boolean],
|
|
default () {
|
|
return false
|
|
}
|
|
},
|
|
titleImage: {
|
|
type: String,
|
|
default: ''
|
|
},
|
|
titlePenetrate: {
|
|
type: Boolean,
|
|
default: false
|
|
},
|
|
shadow: {
|
|
type: Object,
|
|
default () {
|
|
return {}
|
|
}
|
|
}
|
|
},
|
|
data () {
|
|
return {
|
|
focus: false,
|
|
text: '',
|
|
composing: false
|
|
}
|
|
},
|
|
computed: {
|
|
btns () {
|
|
const btns = []
|
|
const fonts = {}
|
|
if (this.buttons.length) {
|
|
this.buttons.forEach(button => {
|
|
const btn = Object.assign({}, button)
|
|
if (btn.fontSrc && !btn.fontFamily) {
|
|
const fontSrc = btn.fontSrc = getRealPath(btn.fontSrc)
|
|
let fontFamily
|
|
if (fontSrc in fonts) {
|
|
fontFamily = fonts[fontSrc]
|
|
} else {
|
|
fontFamily = `font${Date.now()}`
|
|
fonts[fontSrc] = fontFamily
|
|
const cssText =
|
|
`@font-face{font-family: "${fontFamily}";src: url("${fontSrc}") format("truetype")}`
|
|
appendCss(cssText, 'uni-btn-font-' + fontFamily)
|
|
}
|
|
btn.fontFamily = fontFamily
|
|
}
|
|
btn.color = this.type === 'transparent' ? '#fff' : (btn.color || this.textColor)
|
|
let fontSize = btn.fontSize || (this.type === 'transparent' || /\\u/.test(btn.text) ? '22px' : '27px')
|
|
if (/\d$/.test(fontSize)) {
|
|
fontSize += 'px'
|
|
}
|
|
btn.fontSize = fontSize
|
|
btn.fontWeight = btn.fontWeight || 'normal'
|
|
btns.push(btn)
|
|
})
|
|
}
|
|
return btns
|
|
},
|
|
headClass () {
|
|
const shadowColorType = this.shadow.colorType
|
|
const data = {
|
|
'uni-page-head-transparent': this.type === 'transparent',
|
|
'uni-page-head-titlePenetrate': this.titlePenetrate,
|
|
'uni-page-head-shadow': shadowColorType
|
|
}
|
|
if (shadowColorType) {
|
|
data[`uni-page-head-shadow-${shadowColorType}`] = shadowColorType
|
|
}
|
|
return data
|
|
}
|
|
},
|
|
mounted () {
|
|
if (this.searchInput) {
|
|
const input = this.$refs.input
|
|
input.$watch('composing', val => {
|
|
this.composing = val
|
|
})
|
|
if (this.searchInput.disabled) {
|
|
input.$el.addEventListener('click', () => {
|
|
UniServiceJSBridge.emit('onNavigationBarSearchInputClicked', '')
|
|
})
|
|
} else {
|
|
input.$refs.input.addEventListener('keyup', event => {
|
|
if (event.key.toUpperCase() === 'ENTER') {
|
|
UniServiceJSBridge.emit('onNavigationBarSearchInputConfirmed', {
|
|
text: this.text
|
|
})
|
|
}
|
|
})
|
|
input.$refs.input.addEventListener('focus', () => {
|
|
UniServiceJSBridge.emit('onNavigationBarSearchInputFocusChanged', {
|
|
focus: true
|
|
})
|
|
})
|
|
input.$refs.input.addEventListener('blur', () => {
|
|
UniServiceJSBridge.emit('onNavigationBarSearchInputFocusChanged', {
|
|
focus: false
|
|
})
|
|
})
|
|
}
|
|
}
|
|
},
|
|
methods: {
|
|
_back () {
|
|
if (getCurrentPages().length === 1) {
|
|
uni.reLaunch({
|
|
url: '/'
|
|
})
|
|
} else {
|
|
uni.navigateBack({
|
|
from: 'backbutton'
|
|
})
|
|
}
|
|
},
|
|
_onBtnClick (index) {
|
|
UniServiceJSBridge.emit('onNavigationBarButtonTap', Object.assign({}, this.btns[index], {
|
|
index
|
|
}))
|
|
},
|
|
_formatBtnFontText (btn) {
|
|
if (btn.fontSrc && btn.fontFamily) {
|
|
return btn.text.replace('\\u', '&#x')
|
|
} else if (FONTS[btn.type]) {
|
|
return FONTS[btn.type]
|
|
}
|
|
return btn.text || ''
|
|
},
|
|
_formatBtnStyle (btn) {
|
|
const style = {
|
|
color: btn.color,
|
|
fontSize: btn.fontSize,
|
|
fontWeight: btn.fontWeight
|
|
}
|
|
if (btn.fontFamily) {
|
|
style.fontFamily = btn.fontFamily
|
|
}
|
|
return style
|
|
},
|
|
_focus () {
|
|
this.focus = true
|
|
},
|
|
_blur () {
|
|
this.focus = false
|
|
},
|
|
_input (text) {
|
|
UniServiceJSBridge.emit('onNavigationBarSearchInputChanged', {
|
|
text
|
|
})
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|