style(mpuniapp): 移动浏览器全量页面UI/UX审视与瑞士国际主义排版优化

这个提交包含在:
wikiboss
2026-09-21 10:36:42 +08:00
父节点 088a5f05e1
当前提交 41b2596761
共有 831 个文件被更改,包括 1031 次插入 和 150442 次删除

查看文件

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