2025-07-27 21:56:11 +08:00

396 lines
8.8 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!-- src/pages/view/notice/index.vue -->
<template>
<view class="jl-list-page">
<!-- 列表内容 -->
<BasicListLayout @register="register" v-model="dataList">
<template v-slot="{ data }">
<view class="jl-card">
<view class="card-header">
<text class="jl-title">{{ data.jlmc }}</text>
<text class="jl-status" :class="getStatusClass(data.jlStatus)">
{{ getStatusText(data.jlStatus) }}
</text>
</view>
<view class="card-body">
<image
v-if="data.jlfm"
:src="imagUrl(data.jlfm)"
mode="aspectFill"
class="cover-thumbnail"
></image>
<rich-text class="jl-excerpt" :nodes="data.jlms"></rich-text>
</view>
<view class="card-footer">
<text class="footer-item">发布者: {{ data.jsxm || '未知' }}</text>
<text class="footer-item">{{ formatTime(data.jlFbtime) }}</text>
<text class="footer-item" v-if="data.bjmc"
>范围: {{ data.njmc + data.bjmc }}</text
>
<view class="footer-actions">
<image
src="@/static/base/details.png"
mode="aspectFit"
class="footer-action-icon"
style="width:22px;height:22px;"
@click="goToFeedback(data.id)"
/>
<image
v-if="data.jlStatus === 'A'"
src="@/static/base/push.png"
mode="aspectFit"
class="footer-action-icon"
style="width:22px;height:22px;"
@click="goToPush(data.id)"
/>
</view>
</view>
</view>
</template>
<template #bottom>
<view class="flex-row items-center pb-10 pt-5">
<u-button
text="新增接龙"
class="mx-15"
type="primary"
@click="goToPublish"
/>
</view>
</template>
</BasicListLayout>
<!-- 用uniqueList渲染 -->
<template v-for="item in uniqueList" :key="item.id">
<!-- 这里可以加自定义渲染内容做二次验证 -->
</template>
</view>
</template>
<script lang="ts" setup>
import { useLayout } from "@/components/BasicListLayout/hooks/useLayout";
import { mobilejllistApi } from "@/api/base/server";
import { imagUrl } from "@/utils";
import { computed, watch } from "vue";
import { onShow } from "@dcloudio/uni-app";
interface JlItem {
id: string;
jlmc: string; // 接龙名称
jlms: string; // 接龙描述
jlStatus: string; // 发布状态A待推送B暂存C已推送
jlFbr: string; // 发布人
jlFbtime: string; // 发布时间
jlfm: string; // 接龙封面
njmc: string;
bjmc: string; // 班级名称
jlkstime: string; // 接龙开始时间
jljstime: string; // 接龙结束时间
jsxm?: string;
}
// 使用 BasicListLayout
const [register, { reload }] = useLayout({
api: mobilejllistApi, // 必须提供 api即使使用了 query
componentProps: {},
});
// 兜底去重逻辑
const dataList = ref<JlItem[]>([]);
const uniqueList = computed(() => {
const map = new Map();
(dataList.value || []).forEach(item => {
if (item && item.id != null) map.set(String(item.id), item);
});
return Array.from(map.values());
});
// 日志每次dataList变化时打印
watch(dataList, (val) => {
// 监听数据变化
});
// 跳转到详情页
const goToDetail = (jlId: string) => {
uni.navigateTo({
url: `/pages/view/notice/detail?id=${jlId}`,
});
};
// 跳转到发布页
const goToPublish = () => {
uni.navigateTo({
url: "/pages/view/notice/publish",
});
};
// 跳转到接龙反馈detail
const goToFeedback = (jlId: string) => {
uni.navigateTo({
url: `/pages/view/notice/detail?id=${jlId}`,
});
};
// 跳转到消息推送页
const goToPush = (jlId: string) => {
uni.navigateTo({
url: `/pages/view/notice/push-list?jlId=${jlId}`,
});
};
// 根据状态获取对应的 CSS 类
const getStatusClass = (status: string) => {
if (status === "A") return "status-published";
if (status === "B") return "status-draft";
return "status-ended";
};
// 根据状态获取状态文字
const getStatusText = (status: string) => {
if (status === "A") return "待推送";
if (status === "B") return "暂存";
return "已推送";
};
// 格式化时间
const formatTime = (timeStr: string) => {
if (!timeStr) return "";
const date = new Date(timeStr);
return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(
2,
"0"
)}-${String(date.getDate()).padStart(2, "0")}`;
};
onShow(() => {
reload();
});
</script>
<style scoped lang="scss">
.jl-list-page {
position: relative;
min-height: 100vh;
background-color: #f5f7fa;
padding: 12px;
box-sizing: border-box;
}
.jl-card {
background-color: #ffffff;
border-radius: 12px;
padding: 16px;
margin-bottom: 12px;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
border: 1px solid #f0f0f0;
transition: all 0.3s ease;
position: relative;
overflow: hidden;
&:active {
transform: translateY(1px);
box-shadow: 0 1px 6px rgba(0, 0, 0, 0.12);
}
&::before {
content: '';
position: absolute;
left: 0;
top: 0;
bottom: 0;
width: 4px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border-radius: 2px;
}
}
.card-header {
display: flex;
justify-content: space-between;
align-items: flex-start;
margin-bottom: 12px;
gap: 12px;
.jl-title {
font-size: 16px;
font-weight: 600;
color: #2c3e50;
flex: 1;
line-height: 1.4;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
word-break: break-word;
}
.jl-status {
font-size: 11px;
padding: 4px 8px;
border-radius: 12px;
color: #fff;
white-space: nowrap;
flex-shrink: 0;
font-weight: 500;
letter-spacing: 0.5px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
&.status-published {
background: linear-gradient(135deg, #ff6b6b 0%, #ee5a52 100%);
}
&.status-draft {
background: linear-gradient(135deg, #ffa726 0%, #ff9800 100%);
}
&.status-ended {
background: linear-gradient(135deg, #66bb6a 0%, #4caf50 100%);
}
}
}
.card-body {
margin-bottom: 12px;
.cover-thumbnail {
width: 80px;
height: 60px;
border-radius: 8px;
margin-right: 12px;
float: left;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
object-fit: cover;
}
.jl-excerpt {
font-size: 14px;
color: #5a6c7d;
line-height: 1.6;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
word-break: break-word;
}
}
.card-footer {
display: flex;
flex-wrap: wrap;
gap: 8px 16px;
align-items: center;
padding-top: 12px;
border-top: 1px solid #f0f0f0;
.footer-item {
white-space: nowrap;
font-size: 13px;
color: #7f8c8d;
overflow: hidden;
text-overflow: ellipsis;
max-width: 180px;
display: flex;
align-items: center;
&::before {
content: '';
width: 4px;
height: 4px;
background-color: #bdc3c7;
border-radius: 50%;
margin-right: 6px;
flex-shrink: 0;
}
}
.footer-actions {
display: flex;
justify-content: flex-end;
align-items: center;
gap: 18px;
width: 100%;
flex-basis: 100%;
margin-top: 8px;
padding: 0;
background: none;
border: none;
}
.footer-action-icon {
cursor: pointer;
transition: transform 0.1s;
background: none !important;
border: none !important;
padding: 0 !important;
margin: 0 !important;
}
.footer-action-icon:active {
transform: scale(0.92);
}
}
// 底部按钮区域优化
.white-bg-color {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border-radius: 16px;
margin: 16px 12px;
padding: 16px;
box-shadow: 0 4px 16px rgba(102, 126, 234, 0.3);
.flex-row {
justify-content: center;
}
.u-button {
background: rgba(255, 255, 255, 0.9);
color: #667eea;
border: none;
font-weight: 600;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
transition: all 0.3s ease;
&:active {
background: rgba(255, 255, 255, 1);
transform: translateY(1px);
}
}
}
// 响应式优化
@media (max-width: 375px) {
.jl-list-page {
padding: 8px;
}
.jl-card {
padding: 12px;
margin-bottom: 8px;
}
.card-header .jl-title {
font-size: 15px;
}
.card-footer .footer-item {
max-width: 150px;
font-size: 12px;
}
}
// 加载动画
.jl-card {
animation: fadeInUp 0.3s ease-out;
}
@keyframes fadeInUp {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
</style>