fix: 文章页面调整
This commit is contained in:
parent
748cb68bbf
commit
6951e9d023
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<view class="article-detail-page">
|
||||
<full-page :customScroll="true" pageStyle="background:#fff">
|
||||
<view v-if="loading" class="loading-container">
|
||||
<uni-icons type="spinner-cycle" size="40" color="#999" />
|
||||
<text class="loading-text">加载中...</text>
|
||||
@ -10,7 +10,7 @@
|
||||
<button class="retry-btn" @click="loadArticle">重试</button>
|
||||
</view>
|
||||
|
||||
<scroll-view v-else scroll-y class="article-content">
|
||||
<view v-else class="article-content">
|
||||
<view class="article-header">
|
||||
<text class="article-title">{{ articleData.title }}</text>
|
||||
<text class="article-date">{{ articleData.date }}</text>
|
||||
@ -20,13 +20,33 @@
|
||||
<rich-text :nodes="articleData.content"></rich-text>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</view>
|
||||
<template #footer>
|
||||
<button-footer :showConfirm="showStar" cancelText="关闭" @cancel="back()">
|
||||
<template #confirm>
|
||||
<view class="flex justify-center items-center h-full border-primary rounded bg-primary" @click="star()">
|
||||
<uni-icons class="flex-shrinl-0" :type="article.star ? 'star-filled' : 'star'" color="#FFD700"
|
||||
size="20"></uni-icons>
|
||||
<view class="text-base text-white">{{ article.star ? '已收藏' : '收藏' }}</view>
|
||||
</view>
|
||||
</template>
|
||||
</button-footer>
|
||||
</template>
|
||||
</full-page>
|
||||
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed } from "vue";
|
||||
import { onLoad } from "@dcloudio/uni-app";
|
||||
import { storeToRefs } from "pinia";
|
||||
import fullPage from '@/components/full-page.vue';
|
||||
import buttonFooter from '@/components/button-footer.vue';
|
||||
import useAccountStore from "@/store/account.js";
|
||||
import useGuard from "@/hooks/useGuard.js";
|
||||
import api from "@/utils/api.js";
|
||||
import { toast, loading as showLoading, hideLoading } from "@/utils/widget";
|
||||
|
||||
import { ref } from "vue";
|
||||
const env = __VITE_ENV__;
|
||||
const corpId = env.MP_CORP_ID;
|
||||
@ -39,6 +59,17 @@ const articleData = ref({
|
||||
});
|
||||
|
||||
let articleId = "";
|
||||
const article = ref({});
|
||||
const accountStore = useAccountStore();
|
||||
const { doctorInfo, account } = storeToRefs(accountStore);
|
||||
const userId = computed(() => doctorInfo.value?.userid || "");
|
||||
const { useLoad } = useGuard()
|
||||
|
||||
const showStar = computed(() => {
|
||||
const isMine = article.value && article.value.creatorSignature && article.value.creatorSignature.person && article.value.creatorSignature.person.userId === userId.value;
|
||||
return userId.value && !isMine;
|
||||
})
|
||||
|
||||
|
||||
// 处理富文本内容,使图片自适应
|
||||
const processRichTextContent = (html) => {
|
||||
@ -75,7 +106,7 @@ const loadArticle = async () => {
|
||||
loading.value = true;
|
||||
error.value = "";
|
||||
try {
|
||||
const res = await api("getArticle", { id: articleId, corpId });
|
||||
const res = await api("getArticle", { id: articleId, corpId, userId: userId.value });
|
||||
|
||||
if (res.success && res.data) {
|
||||
// 格式化日期
|
||||
@ -87,7 +118,7 @@ const loadArticle = async () => {
|
||||
const day = String(d.getDate()).padStart(2, "0");
|
||||
date = `${year}-${month}-${day}`;
|
||||
}
|
||||
|
||||
article.value = res.data;
|
||||
articleData.value = {
|
||||
title: res.data.title || "宣教文章",
|
||||
content: processRichTextContent(res.data.content || ""),
|
||||
@ -104,7 +135,23 @@ const loadArticle = async () => {
|
||||
}
|
||||
};
|
||||
|
||||
onLoad((options) => {
|
||||
async function star() {
|
||||
showLoading();
|
||||
const res = await api("starArticle", { articleId: articleId, userId: userId.value, star: !article.value.star });
|
||||
hideLoading();
|
||||
if (res.success) {
|
||||
uni.$emit('changeArticleStar', article.value._id);
|
||||
loadArticle()
|
||||
} else {
|
||||
toast(res.message || "操作失败");
|
||||
}
|
||||
}
|
||||
|
||||
function back() {
|
||||
uni.navigateBack();
|
||||
}
|
||||
|
||||
useLoad((options) => {
|
||||
if (options.id) {
|
||||
articleId = options.id;
|
||||
loadArticle();
|
||||
@ -116,12 +163,11 @@ onLoad((options) => {
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.article-detail-page {
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
background-color: #fff;
|
||||
.ml-15 {
|
||||
margin-left: 30rpx;
|
||||
}
|
||||
|
||||
|
||||
.loading-container,
|
||||
.error-container {
|
||||
display: flex;
|
||||
|
||||
@ -18,26 +18,20 @@
|
||||
<empty-data title="暂无文章" />
|
||||
</view>
|
||||
<view v-else>
|
||||
<view v-for="article in searchList" :key="article._id" class="article-item ">
|
||||
<view v-for="article in searchList" :key="article._id" class="article-item" @click="previewArticle(article)">
|
||||
<view>
|
||||
<view class="flex items-center py-12 px-15">
|
||||
<view class="text-lg leading-normal font-semibold w-0 flex-grow truncate mr-10">
|
||||
{{ article.title }}
|
||||
</view>
|
||||
<view @click.stop="star(article)">
|
||||
<view v-if="!article.isMine" @click.stop="star(article)">
|
||||
<uni-icons class="flex-shrinl-0" :type="article.star ? 'star-filled' : 'star'"
|
||||
:color="article.star ? '#FFD700' : '#999'" size="20"></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="article.authorName" class="px-15 mb-10 truncate text-base text-dark">{{ article.authorName }}
|
||||
</view>
|
||||
<view class="border-b"></view>
|
||||
<view class="flex items-center justify-between py-10 px-15">
|
||||
<view class="flex items-center" @click="previewArticle(article)">
|
||||
<view class="text-base text-primary">文章详情</view>
|
||||
<uni-icons type="right" color="#0074ff" size="16"></uni-icons>
|
||||
</view>
|
||||
<view class="bg-primary text-white text-base px-15 py-5 rounded-sm"
|
||||
<view class="flex items-center px-15 pb-10">
|
||||
<view class="mr-10 w-0 flex-growt runcate text-base text-dark">{{ article.authorName }}</view>
|
||||
<view class="bg-primary text-white text-sm px-10 leading-normal rounded-sm"
|
||||
@click.stop="handlePrimaryAction(article)">
|
||||
{{ isSelectMode ? '选择' : '发送' }}
|
||||
</view>
|
||||
@ -75,20 +69,25 @@
|
||||
</view>
|
||||
|
||||
<view v-else>
|
||||
<view v-for="article in articleList" :key="article._id" class="article-item ">
|
||||
<view v-for="article in articleList" :key="article._id" class="article-item" @click="previewArticle(article)">
|
||||
<view>
|
||||
<view class="flex items-center py-12 px-15">
|
||||
<view class="text-lg leading-normal font-semibold w-0 flex-grow truncate mr-10">
|
||||
{{ article.title }}
|
||||
</view>
|
||||
<view @click.stop="star(article)">
|
||||
<view v-if="!article.isMine" @click.stop="star(article)">
|
||||
<uni-icons class="flex-shrinl-0" :type="article.star ? 'star-filled' : 'star'"
|
||||
:color="article.star ? '#FFD700' : '#999'" size="20"></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="article.authorName" class="px-15 mb-10 truncate text-base text-dark">{{ article.authorName }}
|
||||
<view class="flex items-center px-15 pb-10">
|
||||
<view class="mr-10 w-0 flex-grow truncate text-base text-dark">{{ article.authorName }}</view>
|
||||
<view class="bg-primary text-white text-sm px-10 leading-normal rounded-sm"
|
||||
@click.stop="handlePrimaryAction(article)">
|
||||
{{ isSelectMode ? '选择' : '发送' }}
|
||||
</view>
|
||||
</view>
|
||||
<view class="border-b"></view>
|
||||
<!-- <view class="border-b"></view>
|
||||
<view class="flex items-center justify-between py-10 px-15">
|
||||
<view class="flex items-center" @click="previewArticle(article)">
|
||||
<view class="text-base text-primary">文章详情</view>
|
||||
@ -98,7 +97,7 @@
|
||||
@click.stop="handlePrimaryAction(article)">
|
||||
{{ isSelectMode ? '选择' : '发送' }}
|
||||
</view>
|
||||
</view>
|
||||
</view> -->
|
||||
<!-- <view class="article-footer">
|
||||
<text class="article-date">{{ article.date }}</text>
|
||||
<button class="send-btn" size="mini" type="primary" @click.stop="handlePrimaryAction(article)">
|
||||
@ -156,7 +155,7 @@
|
||||
<script setup>
|
||||
import { ref, computed, watch } from "vue";
|
||||
import { storeToRefs } from "pinia";
|
||||
import { onLoad } from "@dcloudio/uni-app";
|
||||
import { onLoad, onUnload, onShow } from "@dcloudio/uni-app";
|
||||
import api from "@/utils/api.js";
|
||||
import useAccountStore from "@/store/account.js";
|
||||
import useGuard from "@/hooks/useGuard.js";
|
||||
@ -166,7 +165,6 @@ import fullPage from '@/components/full-page.vue';
|
||||
import EmptyData from "@/components/empty-data.vue";
|
||||
import { toast, loading as showLoading, hideLoading } from "@/utils/widget";
|
||||
|
||||
|
||||
const accountStore = useAccountStore();
|
||||
const env = __VITE_ENV__;
|
||||
const corpId = env.MP_CORP_ID;
|
||||
@ -186,6 +184,7 @@ const pageParams = ref({
|
||||
});
|
||||
const currentCateId = ref("my"); // 默认选中"全部"(_id 为空字符串)
|
||||
const teams = ref([])
|
||||
const showRefresh = ref(false);
|
||||
|
||||
const cateList = computed(() => {
|
||||
const arr = [{ label: '我的文章', value: 'my', type: 'mine' }, { label: '团队文章', value: 'team', type: 'team' }];
|
||||
@ -282,31 +281,9 @@ const processRichTextContent = (html) => {
|
||||
|
||||
// 预览文章
|
||||
const previewArticle = async (article) => {
|
||||
try {
|
||||
uni.showLoading({ title: "加载中..." });
|
||||
const res = await api("getArticle", { id: article._id, corpId: corpId });
|
||||
uni.hideLoading();
|
||||
|
||||
if (res.success && res.data) {
|
||||
previewArticleData.value = {
|
||||
title: res.data.title || article.title,
|
||||
content: processRichTextContent(res.data.content || ""),
|
||||
};
|
||||
previewPopup.value?.open();
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: res.message || "预览文章失败",
|
||||
icon: "none",
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
uni.hideLoading();
|
||||
console.error("预览文章失败:", error);
|
||||
uni.showToast({
|
||||
title: "预览失败,请重试",
|
||||
icon: "none",
|
||||
});
|
||||
}
|
||||
uni.navigateTo({
|
||||
url: `/pages/message/article-detail?id=${article._id}`,
|
||||
});
|
||||
};
|
||||
|
||||
// 关闭预览
|
||||
@ -470,6 +447,9 @@ async function star(article) {
|
||||
hideLoading();
|
||||
if (res.success) {
|
||||
article.star = !article.star;
|
||||
if (currentCateId.value === 'my') {
|
||||
getMyArticleList();
|
||||
}
|
||||
} else {
|
||||
toast(res.message || "操作失败");
|
||||
}
|
||||
@ -479,6 +459,7 @@ function formatArticles(articles) {
|
||||
return articles.map(article => {
|
||||
const item = { ...article };
|
||||
if (article.creatorSignature && article.creatorSignature.type === 'personal') {
|
||||
item.isMine = article.creatorSignature.person.userId === userId.value;
|
||||
item.authorName = article.creatorSignature.person ? article.creatorSignature.person.userName : '';
|
||||
} else if (article.creatorSignature && article.creatorSignature.type === 'institution') {
|
||||
item.authorName = article.creatorSignature.institution ? article.creatorSignature.institution.name : '';
|
||||
@ -521,11 +502,27 @@ onLoad((options) => {
|
||||
pageParams.value.teamId = options.teamId;
|
||||
}
|
||||
ensureTeamId();
|
||||
uni.$on('changeArticleStar', (articleId) => {
|
||||
if (articleList.value.some(i => i._id === articleId)) {
|
||||
showRefresh.value = true;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
useLoad(() => {
|
||||
|
||||
useLoad(() => { });
|
||||
onUnload(() => {
|
||||
uni.$off('changeArticleStar');
|
||||
});
|
||||
|
||||
onShow(() => {
|
||||
if (showRefresh.value) {
|
||||
page.value = 1;
|
||||
getArticleList();
|
||||
showRefresh.value = false;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
watch(userId, n => {
|
||||
if (n) {
|
||||
getArticleList();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user