feat:封装header及bottombtn组件

master
黄伟杰 1 month ago
parent d5710f1e87
commit 6c4e9d5e8c

@ -0,0 +1,46 @@
<template>
<view class="header-section">
<view class="header-content">
<text class="header-title">{{ title }}</text>
<text v-if="subTitle" class="header-desc">{{ subTitle }}</text>
</view>
</view>
</template>
<script setup>
const props = defineProps({
title: {
type: String,
default: ''
},
subTitle: {
type: String,
default: ''
}
})
</script>
<style lang="scss" scoped>
.header-section {
--status-top: var(--status-bar-height, 0px);
background: linear-gradient(135deg, #1a3a5c 0%, #2d5a87 100%);
padding: calc(40rpx + var(--status-top)) 30rpx 80rpx;
position: relative;
}
.header-content {
.header-title {
display: block;
font-size: 44rpx;
font-weight: bold;
color: #ffffff;
margin-bottom: 16rpx;
}
.header-desc {
display: block;
font-size: 28rpx;
color: rgba(255, 255, 255, 0.7);
}
}
</style>

@ -0,0 +1,92 @@
<template>
<view class="bottom-action-bar">
<view class="action-row">
<view
v-for="(btn, index) in normalizedButtons"
:key="index"
class="action-btn"
:class="btn.type === 'primary' ? 'btn-primary' : 'btn-default'"
@click="handleClick(btn, index)"
>
<text class="btn-text" :class="btn.type === 'primary' ? 'text-primary' : 'text-default'">{{ btn.text }}</text>
</view>
</view>
</view>
</template>
<script setup>
import { computed } from 'vue'
const props = defineProps({
buttons: {
type: Array,
default: () => []
}
})
const emit = defineEmits(['action'])
const normalizedButtons = computed(() => {
if (!Array.isArray(props.buttons) || props.buttons.length === 0) {
return [{ text: '返回', type: 'default', key: 'back' }]
}
return props.buttons.map((b) => ({
text: b && b.text ? b.text : '按钮',
type: b && b.type === 'primary' ? 'primary' : 'default',
key: b && b.key ? b.key : ''
}))
})
function handleClick(btn, index) {
emit('action', { ...btn, index })
}
</script>
<style lang="scss" scoped>
.bottom-action-bar {
position: fixed;
left: 0;
right: 0;
bottom: 0;
background: #ffffff;
box-shadow: 0 -6rpx 24rpx rgba(0, 0, 0, 0.08);
padding: 20rpx 24rpx calc(20rpx + env(safe-area-inset-bottom));
z-index: 99;
}
.action-row {
display: flex;
gap: 20rpx;
}
.action-btn {
flex: 1;
height: 88rpx;
border-radius: 16rpx;
display: flex;
align-items: center;
justify-content: center;
}
.btn-default {
background: #ffffff;
border: 2rpx solid #dcdfe6;
}
.btn-primary {
background: linear-gradient(135deg, #1a3a5c 0%, #2d5a87 100%);
}
.btn-text {
font-size: 30rpx;
font-weight: 600;
}
.text-default {
color: #303133;
}
.text-primary {
color: #ffffff;
}
</style>

@ -1,14 +1,6 @@
<template>
<view class="page-container">
<view class="header-section">
<view class="back-btn" @click="goBack">
<text class="back-icon"></text>
<text class="back-text">返回</text>
</view>
<view class="header-content">
<text class="header-title">设备详情</text>
</view>
</view>
<AppTitleHeader title="设备详情" />
<view class="content-section">
<view class="info-card">
@ -205,12 +197,15 @@
</view>
</view>
</view>
<BottomActionBar @action="goBack" />
</view>
</template>
<script setup>
import { ref, computed } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
import AppTitleHeader from '@/components/common/AppTitleHeader.vue'
import BottomActionBar from '@/components/common/BottomActionBar.vue'
import {
getEquipmentDetail,
getEquipmentInspectionByDeviceId,
@ -514,49 +509,8 @@ function previewImages(list, current) {
background-color: #f0f2f5;
}
.header-section {
background: linear-gradient(135deg, #1a3a5c 0%, #2d5a87 100%);
padding: 40rpx 30rpx 80rpx;
position: relative;
}
.back-btn {
display: flex;
align-items: center;
margin-bottom: 20rpx;
&:active {
opacity: 0.7;
}
.back-icon {
font-size: 48rpx;
color: #ffffff;
margin-right: 8rpx;
}
.back-text {
font-size: 28rpx;
color: #ffffff;
}
}
.header-content {
display: flex;
justify-content: space-between;
align-items: flex-start;
.header-title {
display: block;
font-size: 44rpx;
font-weight: bold;
color: #ffffff;
margin-bottom: 16rpx;
}
}
.content-section {
padding: 0 30rpx 30rpx;
padding: 0 30rpx 200rpx;
}
.info-card {

@ -1,15 +1,6 @@
<template>
<view class="page-container">
<view class="header-section">
<view class="back-btn" @click="goBack">
<text class="back-icon"></text>
<text class="back-text">返回</text>
</view>
<view class="header-content">
<text class="header-title">设备查询</text>
<text class="header-desc">请选择查询方式</text>
</view>
</view>
<AppTitleHeader title="设备查询" subTitle="请选择查询方式" />
<view class="content-section">
<view class="scan-section">
@ -57,11 +48,14 @@
</view>
</view>
</view>
<BottomActionBar @action="goBack" />
</view>
</template>
<script setup>
import { ref } from 'vue';
import AppTitleHeader from '@/components/common/AppTitleHeader.vue'
import BottomActionBar from '@/components/common/BottomActionBar.vue'
const equipmentCode = ref('');
const isScanning = ref(false);
@ -131,51 +125,8 @@ function navigateToDetail(code) {
background-color: #f0f2f5;
}
.header-section {
background: linear-gradient(135deg, #1a3a5c 0%, #2d5a87 100%);
padding: 40rpx 30rpx 80rpx;
position: relative;
}
.back-btn {
display: flex;
align-items: center;
margin-bottom: 20rpx;
&:active {
opacity: 0.7;
}
.back-icon {
font-size: 48rpx;
color: #ffffff;
margin-right: 8rpx;
}
.back-text {
font-size: 28rpx;
color: #ffffff;
}
}
.header-content {
.header-title {
display: block;
font-size: 44rpx;
font-weight: bold;
color: #ffffff;
margin-bottom: 16rpx;
}
.header-desc {
display: block;
font-size: 28rpx;
color: rgba(255, 255, 255, 0.7);
}
}
.content-section {
padding: 40rpx 30rpx;
padding: 40rpx 30rpx 200rpx;
}
.scan-section {

@ -1,14 +1,6 @@
<template>
<view class="page-container">
<view class="header-section">
<view class="back-btn" @click="goBack">
<text class="back-icon"></text>
<text class="back-text">返回</text>
</view>
<view class="header-content">
<text class="header-title">关键件详情</text>
</view>
</view>
<AppTitleHeader title="关键件详情" />
<view class="content-section">
<view class="info-card">
@ -37,6 +29,7 @@
</view>
</view>
</view>
<BottomActionBar @action="goBack" />
</view>
</template>
@ -44,6 +37,8 @@
import { ref } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
import request from '@/utils/request'
import AppTitleHeader from '@/components/common/AppTitleHeader.vue'
import BottomActionBar from '@/components/common/BottomActionBar.vue'
const keypartId = ref(undefined)
const loading = ref(false)
@ -96,51 +91,8 @@ function detailValue(v) {
background-color: #f0f2f5;
}
.header-section {
background: linear-gradient(135deg, #1a3a5c 0%, #2d5a87 100%);
padding: 40rpx 30rpx 80rpx;
position: relative;
}
.back-btn {
display: flex;
align-items: center;
margin-bottom: 20rpx;
&:active {
opacity: 0.7;
}
.back-icon {
font-size: 48rpx;
color: #ffffff;
margin-right: 8rpx;
}
.back-text {
font-size: 28rpx;
color: #ffffff;
}
}
.header-content {
.header-title {
display: block;
font-size: 44rpx;
font-weight: bold;
color: #ffffff;
margin-bottom: 16rpx;
}
.header-code {
display: block;
font-size: 28rpx;
color: rgba(255, 255, 255, 0.7);
}
}
.content-section {
padding: 0 30rpx 30rpx;
padding: 0 30rpx 200rpx;
margin-top: 40rpx;
}

@ -1,15 +1,6 @@
<template>
<view class="page-container">
<view class="header-section">
<view class="back-btn" @click="goBack">
<text class="back-icon"></text>
<text class="back-text">返回</text>
</view>
<view class="header-content">
<text class="header-title">关键件查询</text>
<text class="header-desc">请选择查询方式</text>
</view>
</view>
<AppTitleHeader title="关键件查询" subTitle="请选择查询方式" />
<view class="content-section">
<view class="scan-section">
@ -57,11 +48,14 @@
</view>
</view>
</view>
<BottomActionBar @action="goBack" />
</view>
</template>
<script setup>
import { ref } from 'vue';
import AppTitleHeader from '@/components/common/AppTitleHeader.vue'
import BottomActionBar from '@/components/common/BottomActionBar.vue'
const keypartCode = ref('');
const isScanning = ref(false);
@ -131,51 +125,8 @@ function navigateToDetail(id) {
background-color: #f0f2f5;
}
.header-section {
background: linear-gradient(135deg, #1a3a5c 0%, #2d5a87 100%);
padding: 40rpx 30rpx 80rpx;
position: relative;
}
.back-btn {
display: flex;
align-items: center;
margin-bottom: 20rpx;
&:active {
opacity: 0.7;
}
.back-icon {
font-size: 48rpx;
color: #ffffff;
margin-right: 8rpx;
}
.back-text {
font-size: 28rpx;
color: #ffffff;
}
}
.header-content {
.header-title {
display: block;
font-size: 44rpx;
font-weight: bold;
color: #ffffff;
margin-bottom: 16rpx;
}
.header-desc {
display: block;
font-size: 28rpx;
color: rgba(255, 255, 255, 0.7);
}
}
.content-section {
padding: 40rpx 30rpx;
padding: 40rpx 30rpx 200rpx;
}
.scan-section {

@ -1,14 +1,6 @@
<template>
<view class="page-container">
<view class="header-section">
<view class="back-btn" @click="goBack">
<text class="back-icon"></text>
<text class="back-text">返回</text>
</view>
<view class="header-content">
<text class="header-title">模具详情</text>
</view>
</view>
<AppTitleHeader title="模具详情" />
<view class="content-section">
<view class="info-card">
@ -198,12 +190,15 @@
</view>
</view>
</view>
<BottomActionBar @action="goBack" />
</view>
</template>
<script setup>
import { ref, computed } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
import AppTitleHeader from '@/components/common/AppTitleHeader.vue'
import BottomActionBar from '@/components/common/BottomActionBar.vue'
import {
getMoldDetail,
getMoldInspectionByMoldId,
@ -489,53 +484,6 @@ function previewImages(list, current) {
background-color: #f0f2f5;
}
.header-section {
background: linear-gradient(135deg, #1a3a5c 0%, #2d5a87 100%);
padding: 40rpx 30rpx 80rpx;
position: relative;
}
.back-btn {
display: flex;
align-items: center;
margin-bottom: 20rpx;
&:active {
opacity: 0.7;
}
.back-icon {
font-size: 48rpx;
color: #ffffff;
margin-right: 8rpx;
}
.back-text {
font-size: 28rpx;
color: #ffffff;
}
}
.header-content {
display: flex;
justify-content: space-between;
align-items: flex-start;
.header-title {
display: block;
font-size: 44rpx;
font-weight: bold;
color: #ffffff;
margin-bottom: 16rpx;
}
.header-code {
display: block;
font-size: 28rpx;
color: rgba(255, 255, 255, 0.7);
}
}
.status-tag {
margin-top: 20rpx;
display: flex;
@ -543,7 +491,7 @@ function previewImages(list, current) {
}
.content-section {
padding: 0 30rpx 30rpx;
padding: 0 30rpx 200rpx;
}
.info-card {

@ -1,15 +1,6 @@
<template>
<view class="page-container">
<view class="header-section">
<view class="back-btn" @click="goBack">
<text class="back-icon"></text>
<text class="back-text">返回</text>
</view>
<view class="header-content">
<text class="header-title">模具查询</text>
<text class="header-desc">请选择查询方式</text>
</view>
</view>
<AppTitleHeader title="模具查询" subTitle="请选择查询方式" />
<view class="content-section">
<view class="scan-section">
@ -57,14 +48,18 @@
</view>
</view>
</view>
<BottomActionBar :buttons="bottomButtons" @action="handleBottomAction" />
</view>
</template>
<script setup>
import { ref } from 'vue';
import AppTitleHeader from '@/components/common/AppTitleHeader.vue'
import BottomActionBar from '@/components/common/BottomActionBar.vue'
const moldCode = ref('');
const isScanning = ref(false);
const bottomButtons = ref([{ text: '返回', type: 'default', key: 'back' }])
function goBack() {
uni.navigateBack();
@ -127,6 +122,16 @@ function navigateToDetail(id) {
url: `/pages_function/pages/mold/detail?id=${encodeURIComponent(id)}`
});
}
function handleBottomAction(e) {
if (e && e.key === 'back') {
goBack()
return
}
if (e && e.index === 0) {
goBack()
}
}
</script>
<style lang="scss" scoped>
@ -135,51 +140,8 @@ function navigateToDetail(id) {
background-color: #f0f2f5;
}
.header-section {
background: linear-gradient(135deg, #1a3a5c 0%, #2d5a87 100%);
padding: 40rpx 30rpx 80rpx;
position: relative;
}
.back-btn {
display: flex;
align-items: center;
margin-bottom: 20rpx;
&:active {
opacity: 0.7;
}
.back-icon {
font-size: 48rpx;
color: #ffffff;
margin-right: 8rpx;
}
.back-text {
font-size: 28rpx;
color: #ffffff;
}
}
.header-content {
.header-title {
display: block;
font-size: 44rpx;
font-weight: bold;
color: #ffffff;
margin-bottom: 16rpx;
}
.header-desc {
display: block;
font-size: 28rpx;
color: rgba(255, 255, 255, 0.7);
}
}
.content-section {
padding: 40rpx 30rpx;
padding: 40rpx 30rpx 200rpx;
}
.scan-section {

@ -1,14 +1,6 @@
<template>
<view class="page-container">
<view class="header-section">
<view class="back-btn" @click="goBack">
<text class="back-icon"></text>
<text class="back-text">返回</text>
</view>
<view class="header-content">
<text class="header-title">产品物料详情</text>
</view>
</view>
<AppTitleHeader title="产品物料详情" />
<view class="content-section">
<view class="info-card">
@ -53,6 +45,7 @@
</view>
</view>
</view>
<BottomActionBar @action="goBack" />
</view>
</template>
@ -60,6 +53,8 @@
import { ref, computed } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
import request from '@/utils/request'
import AppTitleHeader from '@/components/common/AppTitleHeader.vue'
import BottomActionBar from '@/components/common/BottomActionBar.vue'
const productId = ref(undefined)
const loading = ref(false)
@ -174,45 +169,8 @@ onLoad((query) => {
background-color: #f0f2f5;
}
.header-section {
background: linear-gradient(135deg, #1a3a5c 0%, #2d5a87 100%);
padding: 40rpx 30rpx 80rpx;
position: relative;
}
.back-btn {
display: flex;
align-items: center;
margin-bottom: 20rpx;
&:active {
opacity: 0.7;
}
.back-icon {
font-size: 48rpx;
color: #ffffff;
margin-right: 8rpx;
}
.back-text {
font-size: 28rpx;
color: #ffffff;
}
}
.header-content {
.header-title {
display: block;
font-size: 44rpx;
font-weight: bold;
color: #ffffff;
margin-bottom: 16rpx;
}
}
.content-section {
padding: 0 30rpx 30rpx;
padding: 0 30rpx 200rpx;
margin-top: 40rpx;
}

@ -1,15 +1,6 @@
<template>
<view class="page-container">
<view class="header-section">
<view class="back-btn" @click="goBack">
<text class="back-icon"></text>
<text class="back-text">返回</text>
</view>
<view class="header-content">
<text class="header-title">产品物料查询</text>
<text class="header-desc">请选择查询方式</text>
</view>
</view>
<AppTitleHeader title="产品物料查询" subTitle="请选择查询方式" />
<view class="content-section">
<view class="scan-section">
@ -57,11 +48,14 @@
</view>
</view>
</view>
<BottomActionBar @action="goBack" />
</view>
</template>
<script setup>
import { ref } from 'vue'
import AppTitleHeader from '@/components/common/AppTitleHeader.vue'
import BottomActionBar from '@/components/common/BottomActionBar.vue'
const productId = ref('')
const isScanning = ref(false)
@ -130,51 +124,8 @@ function navigateToDetail(id) {
background-color: #f0f2f5;
}
.header-section {
background: linear-gradient(135deg, #1a3a5c 0%, #2d5a87 100%);
padding: 40rpx 30rpx 80rpx;
position: relative;
}
.back-btn {
display: flex;
align-items: center;
margin-bottom: 20rpx;
&:active {
opacity: 0.7;
}
.back-icon {
font-size: 48rpx;
color: #ffffff;
margin-right: 8rpx;
}
.back-text {
font-size: 28rpx;
color: #ffffff;
}
}
.header-content {
.header-title {
display: block;
font-size: 44rpx;
font-weight: bold;
color: #ffffff;
margin-bottom: 16rpx;
}
.header-desc {
display: block;
font-size: 28rpx;
color: rgba(255, 255, 255, 0.7);
}
}
.content-section {
padding: 40rpx 30rpx;
padding: 40rpx 30rpx 200rpx;
}
.scan-section {

@ -1,14 +1,6 @@
<template>
<view class="page-container">
<view class="header-section">
<view class="back-btn" @click="goBack">
<text class="back-icon"></text>
<text class="back-text">返回</text>
</view>
<view class="header-content">
<text class="header-title">备件详情</text>
</view>
</view>
<AppTitleHeader title="备件详情" />
<view class="content-section">
<view class="info-card">
@ -45,6 +37,7 @@
</view>
</view>
</view>
<BottomActionBar @action="goBack" />
</view>
</template>
@ -52,6 +45,8 @@
import { ref, computed } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
import request from '@/utils/request'
import AppTitleHeader from '@/components/common/AppTitleHeader.vue'
import BottomActionBar from '@/components/common/BottomActionBar.vue'
const spareId = ref(undefined)
const loading = ref(false)
@ -151,49 +146,6 @@ onLoad((query) => {
background-color: #f0f2f5;
}
.header-section {
background: linear-gradient(135deg, #1a3a5c 0%, #2d5a87 100%);
padding: 40rpx 30rpx 80rpx;
position: relative;
}
.back-btn {
display: flex;
align-items: center;
margin-bottom: 20rpx;
&:active {
opacity: 0.7;
}
.back-icon {
font-size: 48rpx;
color: #ffffff;
margin-right: 8rpx;
}
.back-text {
font-size: 28rpx;
color: #ffffff;
}
}
.header-content {
.header-title {
display: block;
font-size: 44rpx;
font-weight: bold;
color: #ffffff;
margin-bottom: 16rpx;
}
.header-code {
display: block;
font-size: 28rpx;
color: rgba(255, 255, 255, 0.7);
}
}
.status-badge {
position: absolute;
top: 60rpx;
@ -219,7 +171,7 @@ onLoad((query) => {
}
.content-section {
padding: 0 30rpx 30rpx;
padding: 0 30rpx 200rpx;
margin-top: 40rpx;
}

@ -1,15 +1,6 @@
<template>
<view class="page-container">
<view class="header-section">
<view class="back-btn" @click="goBack">
<text class="back-icon"></text>
<text class="back-text">返回</text>
</view>
<view class="header-content">
<text class="header-title">备件查询</text>
<text class="header-desc">请选择查询方式</text>
</view>
</view>
<AppTitleHeader title="备件查询" subTitle="请选择查询方式" />
<view class="content-section">
<view class="scan-section">
@ -57,11 +48,14 @@
</view>
</view>
</view>
<BottomActionBar @action="goBack" />
</view>
</template>
<script setup>
import { ref } from 'vue';
import AppTitleHeader from '@/components/common/AppTitleHeader.vue'
import BottomActionBar from '@/components/common/BottomActionBar.vue'
const spareCode = ref('');
const isScanning = ref(false);
@ -137,51 +131,8 @@ function navigateToDetail(id) {
background-color: #f0f2f5;
}
.header-section {
background: linear-gradient(135deg, #1a3a5c 0%, #2d5a87 100%);
padding: 40rpx 30rpx 80rpx;
position: relative;
}
.back-btn {
display: flex;
align-items: center;
margin-bottom: 20rpx;
&:active {
opacity: 0.7;
}
.back-icon {
font-size: 48rpx;
color: #ffffff;
margin-right: 8rpx;
}
.back-text {
font-size: 28rpx;
color: #ffffff;
}
}
.header-content {
.header-title {
display: block;
font-size: 44rpx;
font-weight: bold;
color: #ffffff;
margin-bottom: 16rpx;
}
.header-desc {
display: block;
font-size: 28rpx;
color: rgba(255, 255, 255, 0.7);
}
}
.content-section {
padding: 40rpx 30rpx;
padding: 40rpx 30rpx 200rpx;
}
.scan-section {

Loading…
Cancel
Save