公告列表页面和公告详细页面

This commit is contained in:
WindowBird 2025-08-21 09:35:13 +08:00
parent 449f86727a
commit e326254bd6
7 changed files with 277 additions and 37 deletions

View File

@ -64,3 +64,28 @@ export function getNewAnnouncement(params = {}) {
},
})
}
/**
* 获取文章列表
* @param {Object} params - 查询参数
* @param {string} params.appId - 应用ID
* @param {string} params.pageNum - 页码
* @param {string} params.pageSize - 每页数量
* @param {string} params.orderByColumn - 排序字段
* @param {string} params.isAsc - 升序/降序
* @returns {Promise} 返回文章列表数据
*/
export function getArticleList(params = {}) {
return request({
url: '/app/article/list',
method: 'GET',
params: {
appId: '1',
pageNum: '1',
pageSize: '10',
orderByColumn: 'create_time',
isAsc: 'descending',
...params,
},
})
}

View File

@ -1,7 +1,8 @@
// 开发环境配置
export const DEV_CONFIG = {
// 临时token用于开发测试
TEMP_TOKEN: 'eyJhbGciOiJIUzUxMiJ9.eyJsb2dpbl91c2VyX2tleSI6IjY2M2UzOWVkLTg4N2MtNGUxOS1iZDBiLWFmZTY1ZmI3Mjk2YiJ9.nMIcrWJK3l5itjQH-okwKL2X4Tresr_sKmgMQ66nHsjYGHK9Xyz5YHO2oDeF-sPt1BxHbz4fyBXcSWhr1HwWTQ',
TEMP_TOKEN:
'eyJhbGciOiJIUzUxMiJ9.eyJsb2dpbl91c2VyX2tleSI6IjI0ZmI0M2NjLWUwZjktNDUxYi1iMWJjLWE0YThmMTk2OTNmMSJ9.anZvFb0DyonGBmQPeh2ZizaoNPj_FpynlFNJ_I0PHxqOb2kXpI8CLmbHoelb5P8gdaRcLvonWhtpbjUFCwkLlQ',
// 是否使用临时token
USE_TEMP_TOKEN: true,

View File

@ -80,6 +80,20 @@
"style": {
"navigationStyle": "custom"
}
},
{
"path" : "pages/announcementList/announcementList",
"style" :
{
"navigationBarTitleText": "公告列表"
}
},
{
"path" : "pages/announcementList/announcementDetail",
"style" :
{
"navigationBarTitleText" : "公告详细"
}
}
],
"tabBar": {

View File

@ -0,0 +1,157 @@
<template>
<view class="container">
<view class="header">
<view class="title">{{ announcementDetail.title }}</view>
<view class="meta">
<text class="time">{{ announcementDetail.createTime }}</text>
</view>
</view>
<view class="content">
<rich-text :nodes="announcementDetail.content" class="rich-content"></rich-text>
</view>
</view>
</template>
<script setup>
import { ref, onMounted } from 'vue'
const announcementDetail = ref({
id: '',
title: '',
content: '',
createTime: ''
})
//
const getPageParams = () => {
const pages = getCurrentPages()
const currentPage = pages[pages.length - 1]
const options = currentPage.options
announcementDetail.value = {
id: options.id || '',
title: decodeURIComponent(options.title || ''),
content: decodeURIComponent(options.content || ''),
createTime: decodeURIComponent(options.createTime || '')
}
}
onMounted(() => {
getPageParams()
})
</script>
<style lang="scss" scoped>
.container {
padding: 30rpx;
background-color: #f5f5f5;
min-height: 100vh;
}
.header {
background-color: #fff;
padding: 30rpx;
border-radius: 16rpx;
margin-bottom: 20rpx;
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.1);
}
.title {
font-size: 36rpx;
font-weight: bold;
color: #333;
line-height: 1.4;
margin-bottom: 20rpx;
}
.meta {
display: flex;
align-items: center;
justify-content: space-between;
}
.time {
font-size: 24rpx;
color: #999;
}
.content {
background-color: #fff;
padding: 30rpx;
border-radius: 16rpx;
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.1);
}
.rich-content {
font-size: 28rpx;
line-height: 1.8;
color: #333;
:deep(img) {
max-width: 100%;
height: auto;
border-radius: 8rpx;
margin: 20rpx 0;
}
:deep(p) {
margin-bottom: 20rpx;
}
:deep(h1, h2, h3, h4, h5, h6) {
font-weight: bold;
margin: 30rpx 0 20rpx 0;
color: #333;
}
:deep(ul, ol) {
padding-left: 40rpx;
margin-bottom: 20rpx;
}
:deep(li) {
margin-bottom: 10rpx;
}
:deep(blockquote) {
border-left: 8rpx solid #007aff;
padding-left: 20rpx;
margin: 20rpx 0;
color: #666;
font-style: italic;
}
:deep(code) {
background-color: #f0f0f0;
padding: 4rpx 8rpx;
border-radius: 4rpx;
font-family: 'Courier New', monospace;
}
:deep(pre) {
background-color: #f0f0f0;
padding: 20rpx;
border-radius: 8rpx;
overflow-x: auto;
margin: 20rpx 0;
}
:deep(table) {
width: 100%;
border-collapse: collapse;
margin: 20rpx 0;
}
:deep(th, td) {
border: 1rpx solid #ddd;
padding: 16rpx;
text-align: left;
}
:deep(th) {
background-color: #f8f8f8;
font-weight: bold;
}
}
</style>

View File

@ -0,0 +1,56 @@
<template>
<view class="container">
<view v-for="item in announcementList" :key="item.id" class="item">
<uni-card :extra="item.createTime" :title="item.title" @click="detail(item)"></uni-card>
</view>
</view>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import { getArticleList } from '@/api/article/article.js'
const announcementList = ref([])
//
const fetchAnnouncementList = async () => {
try {
const res = await getArticleList({
pageNum: '1',
pageSize: '10',
})
console.log('文章列表:', res.rows)
announcementList.value = res.rows || []
} catch (error) {
console.error('获取公告列表失败:', error)
}
}
const detail = (item) => {
uni.navigateTo({
url: `/pages/announcementList/announcementDetail?id=${item.id}&title=${encodeURIComponent(item.title)}&content=${encodeURIComponent(item.content)}&createTime=${encodeURIComponent(item.createTime)}`
})
}
//
onMounted(() => {
fetchAnnouncementList()
})
</script>
<style lang="scss" scoped>
.container {
overflow: hidden;
padding: 20rpx;
}
.item {
margin-bottom: 20rpx;
}
.uni-body {
font-size: 28rpx;
line-height: 1.6;
color: #666;
}
</style>

View File

@ -213,13 +213,8 @@ export default {
onAnnouncementClick() {
if (this.currentAnnouncement) {
//
uni.showModal({
title: this.currentAnnouncement.title || '公告详情',
content: this.currentAnnouncement.content
? this.currentAnnouncement.content.replace(/<[^>]*>/g, '')
: '暂无公告内容',
showCancel: false,
confirmText: '知道了',
uni.navigateTo({
url:'/pages/announcementList/announcementList'
})
} else {
uni.showToast({

View File

@ -7,7 +7,7 @@
<!-- 登录按钮 -->
<button :disabled="loginLoading" class="login-btn" @click="getPhoneNumber">
<text class="btn-text">{{ loginLoading ? '登录中...' : '微信用户一键登录' }}</text>
</button>
</button>
</view>
<!-- 底部协议 -->
@ -74,7 +74,6 @@
</template>
<script>
import { navigateToPage } from '@/utils/router.js'
import { wxLogin } from '@/api/auth/auth.js'
import { forceHideLoading, AutoLoadingManager } from '@/utils/request.js'
import { getServiceTerms, getPrivacyPolicy } from '@/api/article/article.js'
@ -233,7 +232,7 @@ export default {
// 使this
uni.login({
success: (res) => {
success: res => {
if (res.code) {
console.log('登录!', res)
const data = {
@ -245,45 +244,46 @@ export default {
}
wxLogin(data)
.then((res) => {
.then(res => {
if (this.pageLoading) {
this.pageLoading.hide()
}
}
forceHideLoading()
if (res.code === 200) {
console.log(res, 'resres')
uni.setStorageSync('token', res.token)
uni.showToast({
title: '登录成功',
icon: 'success',
uni.showToast({
title: '登录成功',
icon: 'success',
duration: 1500,
})
setTimeout(() => {
this.ceshi()
}, 1500)
} else {
uni.showToast({
title: res.msg || '登录失败',
uni.switchTab({
url: '/pages/index/index',
})
console.log('123')
} else {
uni.showToast({
title: res.msg || '登录失败',
icon: 'none',
})
}
}
})
.catch((error) => {
.catch(error => {
if (this.pageLoading) {
this.pageLoading.hide()
}
}
forceHideLoading()
console.error('登录失败:', error)
uni.showToast({
title: '登录失败',
uni.showToast({
title: '登录失败',
icon: 'none',
})
})
}
},
fail: (err) => {
fail: err => {
console.error('微信登录失败:', err)
uni.showToast({
title: '微信登录失败',
@ -292,14 +292,6 @@ export default {
},
})
},
async ceshi() {
if (this.pageLoading) {
this.pageLoading.hide()
}
forceHideLoading()
navigateToPage('index')
},
},
}
</script>
@ -329,7 +321,7 @@ page {
.logo-image {
width: 276rpx;
height: 276rpx;
}
}
.main-content {
padding: 0 53rpx;