第二章:写作按钮、底部导航栏和顶部侧滑头像

  • 本章结束后实现的效果
    20240807_090022

1、基本的页面文件结构

  • 根据原型图来创建有的基础页面,下面操作能够实现不用输入代码就能在路由中注册页面路径

image-20240805201759800

image-20240805201956155

image-20240806091805618

  • 然后就能发现在pages中,出现新的页面路径

image-20240806101018086

创建好如以下页面的页面结构

在这里插入图片描述

https://www.iconfont.cn/

在这里插入图片描述

2、使用tabBar实现底部导航栏

image-20240806111732949

image-20240806110859685

  • 这个是说你页面没有被使用,不用担心的
  • 想要解决也很简单

image-20240806113013235

  • 先复制下面的代码,然后加上关闭过滤无依赖文件
    // 关闭过滤无依赖文件功能
    "disableDependencyAnalysis": true

pages.json代码

{
  "pages": [
    //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
    {
      "path": "pages/index/index",
      "style": {
        "navigationBarTitleText": "uni-app"
      }
    },
    {
      "path": "pages/message/message",
      "style": {
        "navigationBarTitleText": "message"
      }
    },
    {
      "path": "pages/organizations/organizations",
      "style": {
        "navigationBarTitleText": "organizations"
      }
    },
    {
      "path": "pages/test/test",
      "style": {
        "navigationBarTitleText": "test"
      }
    }
  ],
  "globalStyle": {
    "navigationBarTextStyle": "black",
    "navigationBarTitleText": "uni-app",
    "navigationBarBackgroundColor": "#F8F8F8",
    "backgroundColor": "#F8F8F8"
  },
  "tabBar": {
    // 底部导航栏
    "color": "#333333",
    "selectedColor": "#333333",
    "backgroundColor": "#ffffff",
    "borderStyle": "white",
    "list": [
      {
        "text": "首页",
        "pagePath": "pages/index/index",
        "iconPath": "static/tabbar/home.png",
        "selectedIconPath": "static/tabbar/home.png"
      },
      {
        "text": "组织",
        "pagePath": "pages/organizations/organizations",
        "iconPath": "static/tabbar/organizations.png",
        "selectedIconPath": "static/tabbar/organizations.png"
      },
      {
        "text": "消息",
        "pagePath": "pages/message/message",
        "iconPath": "static/tabbar/news.png",
        "selectedIconPath": "static/tabbar/news.png"
      },
      {
        "text": "test",
        "pagePath": "pages/test/test",
        "iconPath": "static/logo.png",
        "selectedIconPath": "static/logo.png"
      }
    ]
  }
}

3、编写写作按钮

image-20240817000114296

导入按钮本身

<!-- 我是一个写作按钮 -->
<template>
  <view class="container">
    <!-- 页面其他内容 -->
    <image class="add-button" :src="buttonImage" @click="handleClick"></image>
  </view>
</template>

<script setup lang="ts">
import { ref, computed, nextTick } from 'vue'

// 定义响应式变量
const isAddButton1 = ref(true)

// 切换图片和跳转页面的方法
const handleClick = () => {
  isAddButton1.value = !isAddButton1.value

  // 如果切换后的状态是 AddButton1,进行页面跳转
  if (isAddButton1.value) {
    nextTick(() => {
      setTimeout(() => {
        uni.navigateTo({
          url: '/pages/writing/writing',
          fail: (err) => {
            console.error('Navigation Error:', err)
          },
        })
      }, 100) // 延迟时间可以根据实际需要调整
    })
  }
}

// 预加载图片
function preloadImage(src: string) {
  if (typeof Image !== 'undefined') {
    const img = new Image()
    img.src = src
  } else {
    console.warn('Image is not defined in this environment')
  }
}

// 预加载图片
preloadImage('/static/add/AddButton1.png')
preloadImage('/static/add/AddButton2.png')

// 图片路径的计算属性
const buttonImage = computed(() =>
  isAddButton1.value ? '/static/add/AddButton1.png' : '/static/add/AddButton2.png',
)
</script>

<style scoped>
.container {
  position: relative;
  width: 100%;
  height: 100vh;
  background-color: #f0f0f0;
}

.add-button {
  position: fixed;
  right: 5%; /* 调整按钮的水平位置 */
  bottom: 5%; /* 调整按钮的位置,使其在导航栏上方 */
  width: 20vw; /* 相对屏幕宽度的按钮宽度 */
  height: 20vw; /* 相对屏幕宽度的按钮高度 */
  cursor: pointer;
}
</style>

  • 这个按钮会用到两张图片

image-20240807085832432

导入writing代码

在这里插入图片描述

<!-- 我是写作页 后面使用富文本插件 -->
<script setup lang="ts">
import { ref, computed } from 'vue'
import { useRouter } from 'vue-router'

// 使用路由
const router = useRouter()

// 定义响应式变量
const title = ref('')
const content = ref('')

// 计算属性,判断发帖按钮是否可点击
const canPost = computed(() => title.value.trim() !== '' && content.value.trim() !== '')

// 返回原本页面
const goBack = () => {
  uni.navigateBack()
}

// 发帖方法
const postArticle = () => {
  if (canPost.value) {
    // 发帖逻辑示例
    console.log('发帖', { title: title.value, content: content.value })
    // 发帖成功后,可以进行页面跳转等操作
  }
}

// 选择图片方法
const chooseImage = () => {
  uni.chooseImage({
    count: 1,
    sourceType: ['album'],
    success: (res) => {
      console.log('选择的图片', res.tempFilePaths)
    },
  })
}
</script>

<template>
  <view class="container">
    <!-- 顶部导航栏 -->
    <view class="navbar">
      <text class="back-button" @click="goBack">X</text>
    </view>

    <!-- 输入框 -->
    <view class="input-container">
      <input
        class="title-input"
        type="text"
        :maxlength="120"
        placeholder="输入标题..."
        v-model="title"
      />
      <textarea
        class="content-input"
        :maxlength="100000"
        placeholder="输入内容..."
        v-model="content"
      ></textarea>
    </view>

    <!-- 底部图标按钮 -->
    <view class="bottom-bar">
      <view class="button-container">
        <view class="post-button-container">
          <button
            class="post-button"
            :disabled="!canPost"
            @click="postArticle"
            :class="{ active: canPost }"
          >
            发帖
          </button>
        </view>
        <button class="image-button" @click="chooseImage">图片</button>
      </view>
    </view>
  </view>
</template>

<style lang="scss" scoped>
.container {
  display: flex;
  flex-direction: column;
  height: 100vh;
  padding: 10rpx;
  margin-top: 30rpx; /* 上边框外边距 */
}

.navbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 20rpx;
}
.back-button {
  font-size: 40rpx;
}

.post-button-container {
  margin-left: auto;
}

.post-button {
  background-color: #007bff;
  border-radius: 50rpx;
  padding: 10rpx 20rpx;
  color: white;
  font-size: 32rpx;
  border: none;
  opacity: 0.5;
  transition: opacity 0.3s;
}

.post-button:enabled {
  opacity: 1;
}

.post-button.active {
  opacity: 1;
}

.input-container {
  display: flex;
  flex-direction: column;
  margin-top: 20rpx;
}

.title-input,
.content-input {
  font-size: 32rpx;
  border: none;
  border-radius: 10rpx;
  padding: 10rpx;
}

.title-input {
  height: 80rpx;
  margin-bottom: 20rpx;
}

.content-input {
  flex: 1;
  min-height: 300rpx; /* 最小高度,确保可以完整显示内容 */
  margin-bottom: 20rpx; /* 底部留白 */
}

.bottom-bar {
  display: flex;
  justify-content: center;
  padding: 20rpx;
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  background-color: #fff;
  box-shadow: 0 -2rpx 5rpx rgba(0, 0, 0, 0.1); /* 添加底部阴影效果 */
  margin-bottom: 20rpx; /* 下边框外边距 */
}

.button-container {
  display: flex;
  justify-content: space-between;
  width: 100%;
}

.button-container .post-button {
  background-color: #007bff;
  border-radius: 50rpx;
  padding: 10rpx 20rpx;
  color: white;
  font-size: 32rpx;
  border: none;
}

.button-container .image-button {
  background-color: #007bff;
  border-radius: 50rpx;
  padding: 10rpx 20rpx;
  color: white;
  font-size: 32rpx;
  border: none;
}
</style>


报错解决
pnpm install vue-router --save

# 安装 vue-router 的类型声明
pnpm install @types/vue-router --save-dev
index页面导入组件

image-20240817000415508

<script setup lang="ts">
import AddButton from '@/components/AddButton.vue'
</script>

<template>
  <AddButton />
</template>

<style></style>

解决顶部不是自定义导航栏问题

image-20240806215014105

        "navigationStyle": "custom",

https://cdn.jsdelivr.net/gh/Qiu-JW/NotePicture/2024/08/image-20240806215014105.png

  • 也加上那行代码

在这里插入图片描述

  • 最终效果

4、引入编写侧滑头像组件

  • 因为我们要实现得效果如下图

20240807_090022

  • 想要实现这个效果,就要引入uni-ui。自己能手写出来,但使用组件会更快

image-20240806223304568

  • 我们已经导入过uni-ui的依赖,因此想要使用uniapp的组件有两种方法

方法一 这样一个个导入

image-20240806223336767

方法二 配置自动导入规则

image-20240807084417524

  • 具体看uniapp的官网,这里能看到使用uniui的详细配置
https://zh.uniapp.dcloud.io/component/uniui/quickstart.html

 npm i sass -D 
 
 
 npm i sass-loader@10.1.1 -D 
 
 npm i @dcloudio/uni-ui
// pages.json
{
	"easycom": {
		"autoscan": true,
		"custom": {
			// uni-ui 规则如下配置
			"^uni-(.*)": "@dcloudio/uni-ui/lib/uni-$1/uni-$1.vue"
		}
	},
	
	// 其他内容
	pages:[
		// ...
	]
}

  • 然后就可以使用插件了
  <uni-card>
    <text>这是一个基础卡片示例,内容较少,此示例展示了一个没有任何属性不带阴影的卡片。</text>
  </uni-card>

image-20240807085259377

抽象问题- 样式未生效

image-20240807085317395

  • 你可以会看到这样的场景,这是因为你的依赖里面有uniapp自动导入的依赖(按道理来说应该没有依赖才不显示,但uniapp就不一样了)
{
  "name": "fuxincampusconnect",
  "version": "0.0.0",
  "author": {
    "name": "Qiuner"
  },
  "keywords": [
    "福信校园通"
  ],
  "scripts": {
    "lint": "eslint .",
    "lint:fix": "eslint . --fix",
    "dev:app": "uni -p app",
    "dev:app-android": "uni -p app-android",
    "dev:app-ios": "uni -p app-ios",
    "dev:custom": "uni -p",
    "dev:h5": "uni",
    "dev:h5:ssr": "uni --ssr",
    "dev:mp-alipay": "uni -p mp-alipay",
    "dev:mp-baidu": "uni -p mp-baidu",
    "dev:mp-jd": "uni -p mp-jd",
    "dev:mp-kuaishou": "uni -p mp-kuaishou",
    "dev:mp-lark": "uni -p mp-lark",
    "dev:mp-qq": "uni -p mp-qq",
    "dev:mp-toutiao": "uni -p mp-toutiao",
    "dev:mp-weixin": "uni -p mp-weixin",
    "dev:mp-xhs": "uni -p mp-xhs",
    "dev:quickapp-webview": "uni -p quickapp-webview",
    "dev:quickapp-webview-huawei": "uni -p quickapp-webview-huawei",
    "dev:quickapp-webview-union": "uni -p quickapp-webview-union",
    "build:app": "uni build -p app",
    "build:app-android": "uni build -p app-android",
    "build:app-ios": "uni build -p app-ios",
    "build:custom": "uni build -p",
    "build:h5": "uni build",
    "build:h5:ssr": "uni build --ssr",
    "build:mp-alipay": "uni build -p mp-alipay",
    "build:mp-baidu": "uni build -p mp-baidu",
    "build:mp-jd": "uni build -p mp-jd",
    "build:mp-kuaishou": "uni build -p mp-kuaishou",
    "build:mp-lark": "uni build -p mp-lark",
    "build:mp-qq": "uni build -p mp-qq",
    "build:mp-toutiao": "uni build -p mp-toutiao",
    "build:mp-weixin": "uni build -p mp-weixin",
    "build:mp-xhs": "uni build -p mp-xhs",
    "build:quickapp-webview": "uni build -p quickapp-webview",
    "build:quickapp-webview-huawei": "uni build -p quickapp-webview-huawei",
    "build:quickapp-webview-union": "uni build -p quickapp-webview-union",
    "type-check": "vue-tsc --noEmit"
  },
  "dependencies": {
    "@dcloudio/uni-app": "3.0.0-alpha-3081220230802001",
    "@dcloudio/uni-app-plus": "3.0.0-alpha-3081220230802001",
    "@dcloudio/uni-components": "3.0.0-alpha-3081220230802001",
    "@dcloudio/uni-h5": "3.0.0-alpha-3081220230802001",
    "@dcloudio/uni-mp-alipay": "3.0.0-alpha-3081220230802001",
    "@dcloudio/uni-mp-baidu": "3.0.0-alpha-3081220230802001",
    "@dcloudio/uni-mp-jd": "3.0.0-alpha-3081220230802001",
    "@dcloudio/uni-mp-kuaishou": "3.0.0-alpha-3081220230802001",
    "@dcloudio/uni-mp-lark": "3.0.0-alpha-3081220230802001",
    "@dcloudio/uni-mp-qq": "3.0.0-alpha-3081220230802001",
    "@dcloudio/uni-mp-toutiao": "3.0.0-alpha-3081220230802001",
    "@dcloudio/uni-mp-weixin": "3.0.0-alpha-3081220230802001",
    "@dcloudio/uni-mp-xhs": "3.0.0-alpha-3081220230802001",
    "@dcloudio/uni-quickapp-webview": "3.0.0-alpha-3081220230802001",
    "@dcloudio/uni-ui": "^1.5.5",
    "pinia": "2.0.27",
    "pinia-plugin-persistedstate": "^3.2.0",
    "vue": "^3.2.47",
    "vue-i18n": "^9.2.2",
    "vue-router": "^4.4.2"
  },
  "devDependencies": {
    "@dcloudio/types": "^3.3.3",
    "@dcloudio/uni-automator": "3.0.0-alpha-3081220230802001",
    "@dcloudio/uni-cli-shared": "3.0.0-alpha-3081220230802001",
    "@dcloudio/uni-stacktracey": "3.0.0-alpha-3081220230802001",
    "@dcloudio/uni-vue-devtools": "3.0.0-alpha-3080220230511001",
    "@dcloudio/vite-plugin-uni": "3.0.0-alpha-3081220230802001",
    "@rushstack/eslint-patch": "^1.1.4",
    "@types/node": "^18.11.9",
    "@types/vue-router": "^2.0.0",
    "@uni-helper/uni-app-types": "^0.5.8",
    "@uni-helper/uni-ui-types": "^0.5.11",
    "@vue/eslint-config-prettier": "^7.0.0",
    "@vue/eslint-config-typescript": "^11.0.0",
    "@vue/runtime-core": "^3.2.45",
    "@vue/tsconfig": "^0.4.0",
    "eslint": "^8.22.0",
    "eslint-plugin-vue": "^9.3.0",
    "husky": "^8.0.0",
    "lint-staged": "^13.0.3",
    "miniprogram-api-typings": "^3.12.0",
    "prettier": "^2.7.1",
    "sass": "^1.77.8",
    "sass-loader": "10.1.1",
    "typescript": "^5.1.6",
    "vite": "^4.4.9",
    "vue-tsc": "^1.8.8"
  }
}


  • 将以上依赖复制到package.json中即可、

image-20240807085531811

导入其他代码

TabHeader

<script setup lang="ts">
import { ref } from 'vue'
import uniPopup from '@dcloudio/uni-ui/lib/uni-popup/uni-popup.vue'
import PopupContent from '@/components/HeadPortrait/HeadPopupContent.vue'

const currentTab = ref('whole')

const changeTab = (tab: string) => {
  currentTab.value = tab
}

const popup: Ref<InstanceType<typeof uniPopup> | null> = ref(null)

const openPopup = () => {
  if (popup.value) {
    popup.value.open()
  }
}

const closePopup = () => {
  if (popup.value) {
    popup.value.close()
  }
}

const props = defineProps({
  type: {
    type: Number,
    required: true,
  },
})

// 存储输入的搜索关键字
const searchKeyword = ref('')

// 处理搜索确认事件 TODO类型判断
const search = (event: { detail: { value: any } }) => {
  const keyword = event.detail.value
  console.log('搜索关键词:', keyword)
  // 搜索逻辑
}

// 处理输入事件
const input = (event: { detail: { value: string } }) => {
  searchKeyword.value = event.detail.value
  console.log('当前输入:', searchKeyword.value)
  // 输入逻辑
}
</script>

<template>
  <view class="navbar">
    <view class="logo">
      <view class="avatar-container" @click="openPopup">
        <image class="head-portrait-image" src="/static/logo.png"></image>
      </view>
      <template v-if="type === 2">
        <text class="logo-image">消息</text>
      </template>
      <template v-if="type === 3">
        <uni-search-bar :radius="100" @confirm="search"></uni-search-bar>
      </template>
    </view>

    <view class="header">
      <view class="tab-container">
        <template v-if="type === 2">
          <view class="tab" :class="{ active: currentTab === 'whole' }" @click="changeTab('whole')">
            <text>全部</text>
          </view>
          <view
            class="tab"
            :class="{ active: currentTab === 'interaction' }"
            @click="changeTab('interaction')"
          >
            <text>互动</text>
          </view>
          <view
            class="tab"
            :class="{ active: currentTab === 'follow' }"
            @click="changeTab('follow')"
          >
            <text>关注</text>
          </view>
        </template>
        <template v-else-if="type === 1">
          <view class="tab" :class="{ active: currentTab === 'whole' }" @click="changeTab('whole')">
            <text>为您推荐</text>
          </view>
          <view
            class="tab"
            :class="{ active: currentTab === 'interaction' }"
            @click="changeTab('interaction')"
          >
            <text>正在关注</text>
          </view>
        </template>
      </view>
    </view>

    <uni-popup ref="popup" type="left" :style="{ width: '80%' }">
      <PopupContent @close="closePopup" />
    </uni-popup>
  </view>
</template>

<style lang="scss">
/* 自定义导航条 */
.navbar {
  background-size: cover;
  position: relative;
  display: flex;
  flex-direction: column;
  padding-top: 20px;

  .logo {
    display: flex;
    align-items: center;
    height: 100rpx; /* 增加导航栏的高度 */
    padding-left: 30rpx;
    padding-top: 20rpx;

    .avatar-container {
      margin-right: 20rpx;
    }

    .head-portrait-image {
      width: 80rpx; /* 增加头像的大小 */
      height: 80rpx; /* 增加头像的大小 */
      border-radius: 50%;
      cursor: pointer;
    }

    .logo-image {
      line-height: 28rpx;
      color: #000;
      margin-left: 28rpx;
      padding-left: 20rpx;
      font-size: 45rpx;
    }
  }

  .header {
    display: flex;
    flex-direction: row;
    align-items: center;
    padding: 10px;
    background-color: #fff;
    border-bottom: 1px solid #eee;
  }

  .tab-container {
    flex: 1;
    display: flex;
    justify-content: space-around;
  }

  .tab {
    flex: 1;
    text-align: center;
    padding: 5px 0;
    cursor: pointer;
  }

  .tab.active {
    border-bottom: 2px solid blue;
    font-weight: bold;
  }
}
</style>


HeadPopupContent

<script setup lang="ts">
import { defineEmits } from 'vue'

const emit = defineEmits(['close'])
const goToEditing = () => {
  // 使用uniapp的导航方法跳转到指定页面
  uni.navigateTo({
    url: '/components/HeadPortrait/profile',
  })
}
</script>

<template>
  <view class="popup-content">
    <view class="profile-section">
      <image class="profile-image" src="/static/logo.png"></image>
      <!-- TODO 和后端获取账号 -->
      <view class="profile-name">Qiuner</view>
      <!-- TODO 和后端获取账号 -->
      <view class="profile-username">@wsjw3635</view>
    </view>
    <view class="profile-stats">
      <!-- TODO 和后端交互 -->
      <view>3 正在关注 0 关注者</view>
    </view>
    <view class="menu-items">
      <view class="menu-item" @click="goToEditing">个人资料</view>
      <view class="menu-item">列表</view>
    </view>
  </view>
</template>

<style scoped>
.popup-content {
  padding: 20px;
  background-color: #fff;
  height: 100%;
}

.profile-section {
  display: flex;
  align-items: center;
  margin-bottom: 20px;
}

.profile-image {
  width: 50px;
  height: 50px;
  border-radius: 50%;
}

.profile-name {
  font-size: 18px;
  font-weight: bold;
  margin-left: 10px;
}

.profile-username {
  font-size: 14px;
  color: #888;
  margin-left: 10px;
}

.profile-stats {
  margin-bottom: 20px;
}

.menu-items {
  display: flex;
  flex-direction: column;
}

.menu-item {
  padding: 10px 0;
  border-bottom: 1px solid #eee;
  cursor: pointer;
}
</style>

EditingInformation

<script setup>
import { ref } from 'vue'

const avatar = ref('/static/logo.png') // 默认头像路径
const name = ref('')
const bio = ref('')
const location = ref('')
const website = ref('')
const birthdate = ref('')

// 返回上一页
const goBack = () => {
  uni.navigateBack()
}

// 保存资料
const saveProfile = () => {
  console.log('保存资料', {
    name: name.value,
    bio: bio.value,
    location: location.value,
    website: website.value,
    birthdate: birthdate.value,
  })
  // 保存逻辑
}

// 选择头像图片
const chooseAvatarImage = () => {
  uni.chooseImage({
    count: 1,
    sourceType: ['album'],
    success: (res) => {
      avatar.value = res.tempFilePaths[0]
    },
  })
}

// 选择背景图片
const chooseBackgroundImage = () => {
  uni.chooseImage({
    count: 1,
    sourceType: ['album'],
    success: (res) => {
      console.log('选择的背景图片', res.tempFilePaths)
    },
  })
}
</script>
<template>
  <div class="profile-edit-container">
    <div class="navbar">
      <div class="navbar-back" @click="goBack">返回</div>
      <div class="navbar-title">编辑个人资料</div>
      <div class="navbar-save" @click="saveProfile">保存</div>
    </div>
    <div class="header">
      <div class="background-image">
        <div class="change-bg-icon" @click="chooseBackgroundImage">选择图片</div>
      </div>
      <div class="profile-info">
        <img class="avatar" :src="avatar" alt="头像" @click="chooseAvatarImage" />
      </div>
    </div>
    <div class="user-details">
      <div class="user-detail-item">
        <label>姓名</label>
        <input type="text" v-model="name" />
      </div>
      <div class="user-detail-item">
        <label>简介</label>
        <input type="text" v-model="bio" />
      </div>
      <div class="user-detail-item">
        <label>位置</label>
        <input type="text" v-model="location" />
      </div>
      <div class="user-detail-item">
        <label>加入时间</label>
        <input type="text" v-model="website" />
      </div>
      <div class="user-detail-item">
        <label>出生日期</label>
        <input type="date" v-model="birthdate" />
      </div>
    </div>
  </div>
</template>

<style scoped>
.profile-edit-container {
  width: 100%;
  font-family: Arial, sans-serif;
}

.navbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 1rem;
  margin-top: 2rem; /* 添加顶部外边距,适配不同手机 */
  background-color: #fff;
}

.navbar-back,
.navbar-save {
  cursor: pointer;
  color: #1da1f2;
}

.navbar-title {
  font-weight: bold;
  font-size: 1.2rem; /* 调整字体大小 */
}

.header {
  position: relative;
  width: 100%;
  height: 20vh;
  background-color: #1da1f2;
}

.background-image {
  position: absolute;
  width: 100%;
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
  background-color: #1da1f2;
}

.change-bg-icon {
  color: white;
  font-size: 2rem;
  cursor: pointer;
}

.profile-info {
  position: absolute;
  bottom: -5vh;
  left: 2vw;
  display: flex;
  align-items: center;
}

.avatar {
  width: 16vw;
  height: 16vw;
  border-radius: 50%;
  border: 0.5vw solid white;
  cursor: pointer;
}

.user-details {
  margin-top: 10vh;
  padding: 0 2vw;
}

.user-detail-item {
  margin-bottom: 1.2rem;
}

.user-detail-item label {
  display: block;
  color: #999; /* 淡化处理 */
  margin-bottom: 0.5rem;
  font-size: 0.8rem; /* 调整字体大小 */
}

.user-detail-item input {
  width: 100%;
  padding: 0.5rem;
  font-size: 1rem; /* 调整字体大小 */
  border: none; /* 去除边框 */
  border-bottom: 0.1rem solid #ccc; /* 只保留底部边框 */
  border-radius: 0; /* 去除边框圆角 */
}

/* 使用媒体查询适配不同设备 */
@media (min-width: 768px) {
  .navbar {
    margin-top: 3rem; /* 平板设备上增加更大的顶部外边距 */
  }
}

@media (min-width: 1024px) {
  .navbar {
    margin-top: 4rem; /* 桌面设备上增加更大的顶部外边距 */
  }
}
</style>

profile

<script setup lang="ts">
import { ref } from 'vue'

const selectedTab = ref('帖子')

const selectTab = (tab: string) => {
  selectedTab.value = tab
}

const goToEditing = () => {
  // 使用uniapp的导航方法跳转到指定页面
  uni.navigateTo({
    url: '/components/HeadPortrait/EditingInformation',
  })
}
const goBack = () => {
  uni.navigateBack()
}
</script>
<template>
  <div class="profile-container">
    <div class="header">
      <div class="navbar-back" @click="goBack">返回</div>
      <div class="background-image"></div>
      <div class="profile-info">
        <img class="avatar" src="/static/logo.png" alt="头像" />
        <div class="edit-button" @click="goToEditing">编辑个人资料</div>
      </div>
    </div>
    <div class="user-details">
      <h2>Qiuner</h2>
      <!-- <p>@wsjw3635</p> -->
      <p>出生于 2004年3月15日 | 2023年1月 加入</p>
      <p>3 正在关注 | 0 关注者</p>
    </div>
    <div class="tabs">
      <div class="tab" :class="{ active: selectedTab === '帖子' }" @click="selectTab('帖子')">
        帖子
      </div>
      <div class="tab" :class="{ active: selectedTab === '回复' }" @click="selectTab('回复')">
        回复
      </div>
      <div class="tab" :class="{ active: selectedTab === '媒体' }" @click="selectTab('媒体')">
        媒体
      </div>
      <div class="tab" :class="{ active: selectedTab === '喜欢' }" @click="selectTab('喜欢')">
        喜欢
      </div>
    </div>
  </div>
</template>

<style scoped>
.profile-container {
  width: 100%;
  font-family: Arial, sans-serif;
}

.header {
  position: relative;
  width: 100%;
  height: 20vh;
  background-color: #1da1f2;
}

.navbar-back {
  position: absolute;
  top: 10px;
  left: 10px;
  font-size: 1.5rem;
  color: white;
  cursor: pointer;
  padding: 0.5rem;
  z-index: 10; /* 确保按钮在最上层 */
}

.background-image {
  position: absolute;
  width: 100%;
  height: 100%;
  background-size: cover;
}

.profile-info {
  position: absolute;
  bottom: -5vh;
  left: 2vw;
  display: flex;
  align-items: center;
  width: 100%;
  padding-right: 2vw;
}

.avatar {
  width: 16vw;
  height: 16vw;
  border-radius: 50%;
  border: 0.5vw solid white;
}

.edit-button {
  margin-left: auto;
  margin-right: 2vw;
  padding: 0.5rem 1rem;
  background-color: white;
  border: 0.1rem solid #ccc;
  border-radius: 2rem;
  cursor: pointer;
}

.user-details {
  margin-top: 8vh;
  padding: 0 2vw;
}

.user-details h2 {
  margin: 0;
  font-size: 2rem;
}

.user-details p {
  margin: 0.5rem 0;
  color: #555;
}

.tabs {
  display: flex;
  justify-content: space-around;
  margin-top: 2rem;
  border-top: 0.1rem solid #ccc;
}

.tab {
  padding: 1rem 0;
  cursor: pointer;
  font-weight: bold;
}

.tab.active {
  color: #1da1f2;
  border-bottom: 0.2rem solid #1da1f2;
}

.tab:hover {
  color: #1da1f2;
}
</style>


到目前为止项目结构图

  • 注意 看到没有的不要惊讶 因为我这是做了后面内容回来检查前面博客写得怎么样,因此只需要检查已有的文件位置是不是对的

image-20240817000547058

pages.json文件

  • 直接复制会报错哦,因为有没有的东西。小伙伴们可以自己尝试一下怎么修复能不报错
{
  "easycom": {
    "autoscan": true,
    "custom": {
      // uni-ui 规则如下配置
      "^uni-(.*)": "@dcloudio/uni-ui/lib/uni-$1/uni-$1.vue"
    }
  },
  "pages": [
    {
      "path": "pages/index/index",
      "style": {
        "navigationStyle": "custom",
        "navigationBarTitleText": "uni-app"
      }
    },
    {
      "path": "pages/message/message",
      "style": {
        "navigationStyle": "custom",
        "navigationBarTitleText": "message"
      }
    },
    {
      "path": "pages/organization/organization",
      "style": {
        "navigationStyle": "custom",
        "navigationBarTitleText": "organization"
      }
    },
    {
      "path": "pages/test/test",
      "style": {
        "navigationStyle": "custom",
        "navigationBarTitleText": "test"
      }
    },
    {
      "path": "pages/writing/writing",
      "style": {
        "navigationStyle": "custom",
        "navigationBarTitleText": "writing"
      } 
    },
    {
      "path": "components/HeadPortrait/profile",
      "style": {
        "navigationStyle": "custom",
        "navigationBarTitleText": "profile"
      }
    },
    {
      "path": "components/HeadPortrait/EditingInformation",
      "style": {
        "navigationStyle": "custom",
        "navigationBarTitleText": "EditingInformation"
      }
    },
    {
      "path": "pages/organization/components/OrganizationDetails",
      "style": {
        "navigationStyle": "custom",
        "navigationBarTitleText": "OrganizationDetails"
      }
    },
    {
      "path": "components/Post/Post",
      "style": {
        "navigationStyle": "custom",

        "navigationBarTitleText": "Post"
      }
    },
    {
      "path": "components/Post/PostDetails",
      "style": {
        "navigationStyle": "custom",
        "navigationBarTitleText": "PostDetails"
      }
    }
  ],
  "globalStyle": {
    "navigationBarTextStyle": "black",
    "navigationBarTitleText": "uni-app",
    "navigationBarBackgroundColor": "#F8F8F8",
    "backgroundColor": "#F8F8F8"
  },
  "tabBar": {
    "color": "#333333",
    "selectedColor": "#333333",
    "backgroundColor": "#ffffff",
    "borderStyle": "white",
    "list": [
      {
        "text": "首页",
        "pagePath": "pages/index/index",
        "iconPath": "static/tabbar/home.png",
        "selectedIconPath": "static/tabbar/home.png"
      },
      {
        "text": "组织",
        "pagePath": "pages/organization/organization",
        "iconPath": "static/tabbar/organization.png",
        "selectedIconPath": "static/tabbar/organization.png"
      },
      {
        "text": "消息",
        "pagePath": "pages/message/message",
        "iconPath": "static/tabbar/message.png",
        "selectedIconPath": "static/tabbar/message.png"
      },
      {
        "text": "test",
        "pagePath": "pages/test/test",
        "iconPath": "static/logo.png",
        "selectedIconPath": "static/logo.png"
      }
    ]
  }
}


img

你好,我是Qiuner. 为帮助别人少走弯路而写博客 这是我的 github https://github.com/Qiuner⭐ gitee https://gitee.com/Qiuner 🌹

如果本篇文章帮到了你 不妨点个吧~ 我会很高兴的 😄 (^ ~ ^) 。想看更多 那就点个关注吧 我会尽力带来有趣的内容 😎。

代码都在github或gitee上,如有需要可以去上面自行下载。记得给我点星星哦😍

如果你遇到了问题,自己没法解决,可以去我掘金评论区问。私信看不完,CSDN评论区可能会漏看 掘金账号 https://juejin.cn/user/1942157160101860 掘金账号

更多专栏:

掘金账号 CSDN账号

感谢订阅专栏 三连文章
Logo

助力广东及东莞地区开发者,代码托管、在线学习与竞赛、技术交流与分享、资源共享、职业发展,成为松山湖开发者首选的工作与学习平台

更多推荐