style(mpuniapp): 移动浏览器全量页面UI/UX审视与瑞士国际主义排版优化
这个提交包含在:
@@ -1,225 +0,0 @@
|
||||
<template>
|
||||
<view class="uni-padding-wrap">
|
||||
<page-head :title="title"></page-head>
|
||||
<button class="button" @click="setTabBarBadge">{{ !hasSetTabBarBadge ? '设置tab徽标' : '移除tab徽标' }}</button>
|
||||
<button class="button" @click="showTabBarRedDot">{{ !hasShownTabBarRedDot ? '显示红点' : '移除红点'}}</button>
|
||||
<button class="button" @click="customStyle">{{ !hasCustomedStyle ? '自定义Tab样式' : '移除自定义样式'}}</button>
|
||||
<button class="button" @click="customItem">{{ !hasCustomedItem ? '自定义Tab信息' : '移除自定义信息' }}</button>
|
||||
<button class="button" @click="hideTabBar">{{ !hasHiddenTabBar ? '隐藏TabBar' : '显示TabBar' }}</button>
|
||||
<!-- #ifdef APP-ANDROID || APP-IOS || WEB || APP-HARMONY -->
|
||||
<button class="button" @click="hideTabBarItem">{{ !hasHiddenTabBarItem ? '隐藏接口Item' : '显示接口Item' }}</button>
|
||||
<!-- #endif -->
|
||||
<button class="button" @click="setTabBarTitle">{{ !hasSetLongTitle ? '自定义超长标题' : '移除自定义信息' }}</button>
|
||||
<view class="btn-area">
|
||||
<!-- <button class="button" type="primary" @click="navigateBack">关闭</button> -->
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script lang="uts" setup>
|
||||
const title = ref('tababr')
|
||||
const hasSetTabBarBadge = ref(false)
|
||||
const hasShownTabBarRedDot = ref(false)
|
||||
const hasCustomedStyle = ref(false)
|
||||
const hasCustomedItem = ref(false)
|
||||
const hasHiddenTabBar = ref(false)
|
||||
const hasHiddenTabBarItem = ref(false)
|
||||
const hasSetLongTitle = ref(false)
|
||||
|
||||
onUnmounted(() => {
|
||||
if (hasSetTabBarBadge.value) {
|
||||
uni.removeTabBarBadge({
|
||||
index: 1
|
||||
})
|
||||
}
|
||||
if (hasShownTabBarRedDot.value) {
|
||||
uni.hideTabBarRedDot({
|
||||
index: 1
|
||||
})
|
||||
}
|
||||
if (hasHiddenTabBar.value) {
|
||||
uni.showTabBar()
|
||||
}
|
||||
if (hasCustomedStyle.value) {
|
||||
uni.setTabBarStyle({
|
||||
color: '#7A7E83',
|
||||
selectedColor: '#007AFF',
|
||||
backgroundColor: '#F8F8F8',
|
||||
borderStyle: 'black'
|
||||
})
|
||||
}
|
||||
|
||||
if (hasCustomedItem.value) {
|
||||
let tabBarOptions = {
|
||||
index: 1,
|
||||
text: '接口',
|
||||
iconPath: '/static/api.png',
|
||||
selectedIconPath: '/static/apiHL.png'
|
||||
} as SetTabBarItemOptions
|
||||
uni.setTabBarItem(tabBarOptions)
|
||||
}
|
||||
|
||||
if (hasHiddenTabBarItem.value || hasSetLongTitle.value) {
|
||||
let tabBarOptions = {
|
||||
visible: true,
|
||||
index: 1,
|
||||
text: '接口',
|
||||
iconPath: '/static/api.png',
|
||||
selectedIconPath: '/static/apiHL.png'
|
||||
} as SetTabBarItemOptions
|
||||
uni.setTabBarItem(tabBarOptions)
|
||||
}
|
||||
})
|
||||
|
||||
const setTabBarTitle = () => {
|
||||
let tabBarOptions = {
|
||||
visible: true,
|
||||
index: 1,
|
||||
text: '接口',
|
||||
iconPath: '/static/api.png',
|
||||
selectedIconPath: '/static/apiHL.png'
|
||||
} as SetTabBarItemOptions
|
||||
|
||||
if (!hasSetLongTitle.value) {
|
||||
tabBarOptions.text = "超长标题内容超长标题内容超长标题内容超长标题测试";
|
||||
tabBarOptions.iconPath = "";
|
||||
tabBarOptions.selectedIconPath = "";
|
||||
} else {
|
||||
tabBarOptions.text = "接口";
|
||||
tabBarOptions.iconPath = "/static/api.png";
|
||||
tabBarOptions.selectedIconPath = "/static/apiHL.png";
|
||||
}
|
||||
uni.setTabBarItem(tabBarOptions)
|
||||
hasSetLongTitle.value = !hasSetLongTitle.value
|
||||
}
|
||||
|
||||
const hideTabBarItem = () => {
|
||||
// #ifdef APP-HARMONY
|
||||
uni.showToast({
|
||||
title: "暂不支持"
|
||||
})
|
||||
// #endif
|
||||
|
||||
// #ifndef APP-HARMONY
|
||||
let tabBarOptions = {
|
||||
visible: true,
|
||||
index: 1,
|
||||
text: '接口',
|
||||
iconPath: '/static/api.png',
|
||||
selectedIconPath: '/static/apiHL.png'
|
||||
} as SetTabBarItemOptions
|
||||
|
||||
if (!hasHiddenTabBarItem.value) {
|
||||
tabBarOptions.visible = false;
|
||||
} else {
|
||||
tabBarOptions.visible = true;
|
||||
}
|
||||
uni.setTabBarItem(tabBarOptions)
|
||||
hasHiddenTabBarItem.value = !hasHiddenTabBarItem.value
|
||||
// #endif
|
||||
}
|
||||
const emit = defineEmits(['unmount'])
|
||||
|
||||
const navigateBack = () => {
|
||||
emit('unmount')
|
||||
}
|
||||
|
||||
const setTabBarBadge = () => {
|
||||
if (hasShownTabBarRedDot.value) {
|
||||
uni.hideTabBarRedDot({
|
||||
index: 1
|
||||
})
|
||||
hasShownTabBarRedDot.value = !hasShownTabBarRedDot.value
|
||||
}
|
||||
if (!hasSetTabBarBadge.value) {
|
||||
uni.setTabBarBadge({
|
||||
index: 1,
|
||||
text: '1'
|
||||
})
|
||||
} else {
|
||||
uni.removeTabBarBadge({
|
||||
index: 1
|
||||
})
|
||||
}
|
||||
hasSetTabBarBadge.value = !hasSetTabBarBadge.value
|
||||
}
|
||||
|
||||
const showTabBarRedDot = () => {
|
||||
if (hasSetTabBarBadge.value) {
|
||||
uni.removeTabBarBadge({
|
||||
index: 1
|
||||
})
|
||||
hasSetTabBarBadge.value = !hasSetTabBarBadge.value
|
||||
}
|
||||
if (!hasShownTabBarRedDot.value) {
|
||||
uni.showTabBarRedDot({
|
||||
index: 1
|
||||
})
|
||||
} else {
|
||||
uni.hideTabBarRedDot({
|
||||
index: 1
|
||||
})
|
||||
}
|
||||
hasShownTabBarRedDot.value = !hasShownTabBarRedDot.value
|
||||
}
|
||||
|
||||
const hideTabBar = () => {
|
||||
if (!hasHiddenTabBar.value) {
|
||||
uni.hideTabBar()
|
||||
} else {
|
||||
uni.showTabBar()
|
||||
}
|
||||
hasHiddenTabBar.value = !hasHiddenTabBar.value
|
||||
}
|
||||
|
||||
const customStyle = () => {
|
||||
if (hasCustomedStyle.value) {
|
||||
uni.setTabBarStyle({
|
||||
color: '#7A7E83',
|
||||
selectedColor: '#007AFF',
|
||||
backgroundColor: '#F8F8F8',
|
||||
borderStyle: 'black',
|
||||
// 新增 borderColor,优先级高于 borderStyle
|
||||
// borderColor:'red'
|
||||
})
|
||||
} else {
|
||||
uni.setTabBarStyle({
|
||||
color: '#FFF',
|
||||
selectedColor: '#007AFF',
|
||||
backgroundColor: '#000000',
|
||||
borderStyle: 'black',
|
||||
})
|
||||
}
|
||||
hasCustomedStyle.value = !hasCustomedStyle.value
|
||||
}
|
||||
|
||||
const customItem = () => {
|
||||
let tabBarOptions = {
|
||||
index: 1,
|
||||
text: '接口',
|
||||
iconPath: '/static/api.png',
|
||||
selectedIconPath: '/static/apiHL.png'
|
||||
} as SetTabBarItemOptions
|
||||
if (hasCustomedItem.value) {
|
||||
uni.setTabBarItem(tabBarOptions)
|
||||
} else {
|
||||
tabBarOptions.text = 'API'
|
||||
uni.setTabBarItem(tabBarOptions)
|
||||
}
|
||||
hasCustomedItem.value = !hasCustomedItem.value
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.button {
|
||||
margin-top: 15px;
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.btn-area {
|
||||
padding-top: 15px;
|
||||
}
|
||||
</style>
|
||||
@@ -1,54 +0,0 @@
|
||||
<script setup lang="uts">
|
||||
import { isDarkMode, darkModeClass } from '@/composables/useDark.uts'
|
||||
|
||||
// 样式隔离配置: 受全局样式影响
|
||||
defineOptions({
|
||||
styleIsolation: 'app'
|
||||
})
|
||||
const emit = defineEmits(['change'])
|
||||
const props = defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
defaultValue: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
})
|
||||
|
||||
const _checked = ref(false)
|
||||
|
||||
onMounted(() => {
|
||||
_checked.value = props.defaultValue
|
||||
})
|
||||
|
||||
// @ts-ignore
|
||||
function _change(e : UniSwitchChangeEvent) {
|
||||
_checked.value = e.detail.value;
|
||||
emit('change', _checked.value)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<view class="button-data-main uni-row" :class="darkModeClass">
|
||||
<text class="uni-title" style="width:80%">{{ title }}</text>
|
||||
<switch :checked="_checked" :disabled="disabled" :color="isDarkMode ? '#a8a8b7' : '#007AFF'" @change="_change" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
.button-data-main {
|
||||
justify-content: space-between;
|
||||
padding: 10px;
|
||||
border-bottom: 1px solid var(--border-color, rgba(0, 0, 0, .06));
|
||||
align-items: center;
|
||||
}
|
||||
.uni-title {
|
||||
color: var(--text-color, #333333);
|
||||
}
|
||||
</style>
|
||||
@@ -1,10 +0,0 @@
|
||||
<template>
|
||||
<view class="scroll-view_bottom-fixed"></view>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
.scroll-view_bottom-fixed {
|
||||
height: var(--uni-safe-area-inset-bottom, 20px);
|
||||
min-height: 20px;
|
||||
}
|
||||
</style>
|
||||
@@ -1,40 +0,0 @@
|
||||
<template>
|
||||
<view style="flex-direction: row;">
|
||||
<view @click="onClickWrong" class="btn">
|
||||
<text class="btn-text">点击测试,错误写法</text>
|
||||
</view>
|
||||
<view @click="onClickRight" class="btn">
|
||||
<text class="btn-text">点击测试,正确写法</text>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
const props = defineProps({
|
||||
name: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
})
|
||||
|
||||
const testName = props.name // 开发者如果意识不到item会被复用,错误的存储了初次传入的name,在触发onClick事件时会一直使用初次传入的name
|
||||
function onClickWrong() {
|
||||
console.log('current name is ' + testName)
|
||||
}
|
||||
function onClickRight() {
|
||||
console.log('current name is ' + props.name)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.btn {
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.btn-text {
|
||||
font-size: 12px;
|
||||
color: #ccc;
|
||||
border-radius: 3px;
|
||||
border: solid 1px #ccc;
|
||||
}
|
||||
</style>
|
||||
@@ -1 +0,0 @@
|
||||
export type ItemType = { value : number; name : string, checked?: boolean }
|
||||
@@ -1,82 +0,0 @@
|
||||
<script setup lang="uts">
|
||||
import { ItemType } from './enum-data-types'
|
||||
import { isDarkMode, darkModeClass } from '@/composables/useDark.uts'
|
||||
// 样式隔离配置,app: 受全局样式影响
|
||||
defineOptions({
|
||||
styleIsolation: 'app'
|
||||
})
|
||||
const emit = defineEmits(['change'])
|
||||
const props = defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
items: {
|
||||
type: Array as PropType<Array<ItemType>>,
|
||||
required: true
|
||||
},
|
||||
// 用于控制单选项的显示模式,为true时紧凑横排显示,自动换行。默认false,垂直列表布局,每个选项占一行
|
||||
compact: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
})
|
||||
|
||||
const current = ref(0)
|
||||
|
||||
// @ts-ignore
|
||||
function _change(e : RadioGroupChangeEvent) {
|
||||
const selected = props.items.find((item : ItemType) : boolean => {
|
||||
return item.value.toString() == e.detail.value
|
||||
})
|
||||
if (selected != null) {
|
||||
emit('change', selected.value)
|
||||
uni.showToast({
|
||||
icon: 'none',
|
||||
title: '当前选中:' + selected.name,
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<view class="uni-padding-wrap" :class="darkModeClass">
|
||||
<view class="uni-title uni-common-mt">
|
||||
<text class="uni-title-text"> {{title}} </text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="uni-list uni-common-pl" :class="darkModeClass">
|
||||
<radio-group @change="_change" :class="[{'compact-container': compact}]">
|
||||
<radio :disabled="props.disabled" class="uni-list-cell uni-list-cell-pd" v-for="(item, index) in items" :key="item.name"
|
||||
:class="[{'compact-item': compact, 'uni-list-cell-line': !compact && index < items.length - 1}]"
|
||||
:value="item.value + ''" :checked="item.checked" :color="isDarkMode ? '#a8a8b7' : '#007AFF'">
|
||||
<text class="radio-text">{{ item.name }}</text>
|
||||
</radio>
|
||||
</radio-group>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
.radio-text {
|
||||
color: var(--text-color, #333333);
|
||||
}
|
||||
|
||||
/* 紧凑横排模式 */
|
||||
.compact-container {
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
margin: 10px 0;
|
||||
}
|
||||
|
||||
.compact-item {
|
||||
margin: 6px;
|
||||
padding: 4px 10px !important;
|
||||
border-radius: 4px;
|
||||
background-color: var(--background-color, #f5f5f5);
|
||||
border: 1px solid var(--border-color, #e0e0e0);
|
||||
}
|
||||
</style>
|
||||
@@ -1,49 +0,0 @@
|
||||
<template>
|
||||
<view style="position: fixed;right: 10px;top: 10px;z-index: 999;flex-direction: column;align-items: flex-end;pointer-events: none;">
|
||||
<text style="font-size: 24px;color: green;">FPS: {{ fps }}</text>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="uts">
|
||||
const props = defineProps({
|
||||
interval: {
|
||||
type: Number,
|
||||
default: 1000
|
||||
}
|
||||
})
|
||||
|
||||
let animationId : number = -1
|
||||
const fps = ref<number>(0)
|
||||
let frameCount: number = 0
|
||||
let fpsUpdateTime: number = 0
|
||||
|
||||
let calculateFPS = (currentTime : number) => { }
|
||||
calculateFPS = (currentTime : number) => {
|
||||
if (fpsUpdateTime == (0 as number)) {
|
||||
fpsUpdateTime = currentTime
|
||||
animationId = requestAnimationFrame(calculateFPS)
|
||||
return
|
||||
}
|
||||
frameCount++
|
||||
const delta = currentTime - fpsUpdateTime
|
||||
if (delta >= props.interval) {
|
||||
const value = Math.round(frameCount * 1000 / delta)
|
||||
fps.value = value
|
||||
frameCount = 0
|
||||
fpsUpdateTime = currentTime
|
||||
}
|
||||
animationId = requestAnimationFrame(calculateFPS)
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
animationId = requestAnimationFrame(calculateFPS)
|
||||
})
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
cancelAnimationFrame(animationId)
|
||||
})
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
||||
@@ -136,10 +136,10 @@ async function handleChoose(): Promise<void> {
|
||||
position: absolute;
|
||||
top: 4px;
|
||||
right: 4px;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border-radius: 10px;
|
||||
background-color: rgba(0, 0, 0, 0.6);
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
border-radius: 12px;
|
||||
background-color: rgba(16, 24, 40, 0.65);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
@@ -1,116 +0,0 @@
|
||||
<script setup lang="uts">
|
||||
type InputValue = string | number
|
||||
const emit = defineEmits(['confirm'])
|
||||
// 样式隔离配置,app: 受全局样式影响
|
||||
defineOptions({
|
||||
styleIsolation: 'app'
|
||||
})
|
||||
const props = defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
defaultValue: {
|
||||
type: String,
|
||||
required: true,
|
||||
default: ''
|
||||
}
|
||||
})
|
||||
|
||||
const inputClearValue = ref<InputValue>('')
|
||||
const showClearIcon = ref(false)
|
||||
const inputType = ref('text')
|
||||
|
||||
function _getValue(value : InputValue) : InputValue {
|
||||
switch (props.type) {
|
||||
case 'number':
|
||||
return parseFloat(value as string)
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
switch (props.type) {
|
||||
case 'number':
|
||||
inputType.value = 'number'
|
||||
break;
|
||||
}
|
||||
inputClearValue.value = _getValue(props.defaultValue)
|
||||
})
|
||||
|
||||
function input(event : InputEvent) {
|
||||
// @ts-ignore
|
||||
inputClearValue.value = event.detail.value
|
||||
if ((inputClearValue.value as string).length > 0) {
|
||||
showClearIcon.value = true
|
||||
} else {
|
||||
showClearIcon.value = false
|
||||
}
|
||||
emit('confirm', _getValue(inputClearValue.value))
|
||||
}
|
||||
|
||||
function clearIcon() {
|
||||
inputClearValue.value = ''
|
||||
showClearIcon.value = false
|
||||
emit('confirm', _getValue(inputClearValue.value))
|
||||
}
|
||||
|
||||
function blur() {
|
||||
showClearIcon.value = false
|
||||
}
|
||||
|
||||
function focus() {
|
||||
let inputValue = inputClearValue.value
|
||||
if (typeof inputValue !== 'string') {
|
||||
inputValue = inputValue.toString()
|
||||
}
|
||||
if (inputValue.length > 0) {
|
||||
showClearIcon.value = true
|
||||
} else {
|
||||
showClearIcon.value = false
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<view class="uni-padding-wrap">
|
||||
<view class="uni-title uni-common-mt">
|
||||
<text class="uni-title-text"> {{title}} </text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="input-wrapper">
|
||||
<input class="uni-input" :type="inputType" :value="inputClearValue" :placeholder="title" :maxlength="-1" @input="input" @blur="blur"
|
||||
@focus="focus" />
|
||||
<!-- #ifdef WEB || MP -->
|
||||
<image class="input-wrapper_image" src="/static/icons/clear.png" v-if="showClearIcon" @touchstart="clearIcon" @mousedown="clearIcon">
|
||||
<!-- #endif -->
|
||||
<!-- #ifndef WEB || MP -->
|
||||
<image class="input-wrapper_image" src="/static/icons/clear.png" v-if="showClearIcon" @touchstart="clearIcon">
|
||||
<!-- #endif -->
|
||||
</image>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
|
||||
<style>
|
||||
.input-wrapper {
|
||||
border: 1px solid rgba(0, 0, 0, .08);
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
padding: 0;
|
||||
margin: 0 10px;
|
||||
flex-wrap: nowrap;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
.input-wrapper_image {
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
align-self: center;
|
||||
margin-right: 5px;
|
||||
}
|
||||
</style>
|
||||
@@ -1,19 +0,0 @@
|
||||
<template>
|
||||
<view>
|
||||
<text>在uts组件中使用 native-button</text>
|
||||
<button type="primary" @tap="testCallMethod">调用组件方法</button>
|
||||
<native-button id="helloView1" class="native-button" text="自定义组件"></native-button>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="uts">
|
||||
import { createNativeButtonContext } from "@/uni_modules/native-button";
|
||||
const title = ref('组件能力封装示例');
|
||||
const ontap = (e : UniNativeViewEvent) => {
|
||||
console.log("ontap----------" + e.type)
|
||||
};
|
||||
const testCallMethod = () => {
|
||||
let context = createNativeButtonContext("helloView1", getCurrentInstance()?.proxy)
|
||||
context?.updateText("test code")
|
||||
};
|
||||
</script>
|
||||
@@ -1,28 +0,0 @@
|
||||
<template>
|
||||
<view class="common-page-head">
|
||||
<view class="common-page-head-title-box">
|
||||
<text class="common-page-head-title">{{title}}</text>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<script lang="uts" setup>
|
||||
const props = defineProps({
|
||||
title: { type: String, default: "" }
|
||||
})
|
||||
</script>
|
||||
<style>
|
||||
.common-page-head {
|
||||
padding: 20px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.common-page-head-title-box {
|
||||
padding: 0 20px;
|
||||
border-bottom: 1px solid #D8D8D8;
|
||||
}
|
||||
|
||||
.common-page-head-title {
|
||||
line-height: 40px;
|
||||
color: #BEBEBE;
|
||||
}
|
||||
</style>
|
||||
@@ -1,83 +0,0 @@
|
||||
<script setup lang="uts">
|
||||
import { darkModeClass } from '@/composables/useDark.uts'
|
||||
|
||||
const props = defineProps({
|
||||
content: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
})
|
||||
|
||||
const expanded = ref(false)
|
||||
|
||||
const toggle = () => {
|
||||
expanded.value = !expanded.value
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<view class="page-intro" :class="darkModeClass" @click="toggle">
|
||||
<view class="page-intro-header">
|
||||
<text class="page-intro-label">页面介绍</text>
|
||||
<text class="page-intro-arrow">{{ expanded ? '▲' : '▼' }}</text>
|
||||
</view>
|
||||
<view v-if="expanded" class="page-intro-body">
|
||||
<text class="page-intro-content">{{ content }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
.page-intro.theme-light {
|
||||
--page-intro-border-color: #91caff;
|
||||
--page-intro-bg-color: #e6f4ff;
|
||||
--page-intro-title-color: #0958d9;
|
||||
--page-intro-divider-color: #91caff;
|
||||
--page-intro-content-color: #1d39c4;
|
||||
}
|
||||
|
||||
.page-intro.theme-dark {
|
||||
--page-intro-border-color: #1d39c4;
|
||||
--page-intro-bg-color: #0b1b3a;
|
||||
--page-intro-title-color: #91caff;
|
||||
--page-intro-divider-color: rgba(145, 202, 255, 0.35);
|
||||
--page-intro-content-color: rgba(145, 202, 255, 0.9);
|
||||
}
|
||||
|
||||
.page-intro {
|
||||
margin: 10px;
|
||||
border-radius: 4px;
|
||||
border-left: 4px solid var(--page-intro-border-color, #91caff);
|
||||
background-color: var(--page-intro-bg-color, #e6f4ff);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.page-intro-header {
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 9px 12px;
|
||||
}
|
||||
|
||||
.page-intro-label {
|
||||
font-size: 13px;
|
||||
color: var(--page-intro-title-color, #0958d9);
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.page-intro-arrow {
|
||||
font-size: 11px;
|
||||
color: var(--page-intro-title-color, #0958d9);
|
||||
}
|
||||
|
||||
.page-intro-body {
|
||||
padding: 12px 10px;
|
||||
border-top: 1px solid var(--page-intro-divider-color, #91caff);
|
||||
}
|
||||
|
||||
.page-intro-content {
|
||||
font-size: 13px;
|
||||
color: var(--page-intro-content-color, #1d39c4);
|
||||
line-height: 22px;
|
||||
}
|
||||
</style>
|
||||
@@ -1,49 +0,0 @@
|
||||
<template>
|
||||
<!-- 带圆圈的返回箭头组件。旋转边框的view实现返回箭头。因需要扩大点击区域,外面多套了一层 -->
|
||||
<view class="back-circle" @click="handleClick">
|
||||
<view class="back-arrow" :class="props.arrowClass"></view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script lang="uts" setup>
|
||||
defineOptions({
|
||||
externalClasses: ['arrow-class']
|
||||
})
|
||||
|
||||
type Props = {
|
||||
arrowClass ?: string.ClassString
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
arrowClass: '',
|
||||
})
|
||||
|
||||
const emit = defineEmits(['click'])
|
||||
|
||||
const handleClick = () => {
|
||||
emit('click')
|
||||
// 默认行为:返回上一页
|
||||
uni.navigateBack({})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.back-circle {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
border-radius: 14px;
|
||||
background-color: rgba(220, 220, 220, 0.3);
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin: 6px;
|
||||
padding-left: 4px;
|
||||
}
|
||||
|
||||
.back-arrow {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
transform: rotate(45deg);
|
||||
border-left: 2px solid #000000;
|
||||
border-bottom: 2px solid #000000;
|
||||
}
|
||||
</style>
|
||||
在新工单中引用
屏蔽一个用户