Compare commits
No commits in common. "0a26673111848b40e5f2a777a522437a6e7be949" and "bae9098fed4ce841a6868af739147d5f668b18ec" have entirely different histories.
0a26673111
...
bae9098fed
@ -240,21 +240,10 @@ function onSearchInput() {
|
|||||||
|
|
||||||
function canToggleFavorite(plan) {
|
function canToggleFavorite(plan) {
|
||||||
if (!plan || !plan._id) return false;
|
if (!plan || !plan._id) return false;
|
||||||
if (isCreatedByCurrentUser(plan)) return false;
|
|
||||||
if (activeViewType.value !== 'my') return true;
|
if (activeViewType.value !== 'my') return true;
|
||||||
return Boolean(plan.isFavorite);
|
return Boolean(plan.isFavorite);
|
||||||
}
|
}
|
||||||
|
|
||||||
function isCreatedByCurrentUser(plan = {}) {
|
|
||||||
const userId = getUserId();
|
|
||||||
if (!userId) return false;
|
|
||||||
if (String(plan.createor || plan.creator || '') === userId) return true;
|
|
||||||
const signature = plan.creatorSignature && typeof plan.creatorSignature === 'object'
|
|
||||||
? plan.creatorSignature
|
|
||||||
: null;
|
|
||||||
return signature?.type === 'personal' && String(signature.person?.userId || '') === userId;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function toggleFavorite(plan) {
|
async function toggleFavorite(plan) {
|
||||||
const corpId = getCorpId();
|
const corpId = getCorpId();
|
||||||
const userId = getUserId();
|
const userId = getUserId();
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<full-page :customScroll="true" pageStyle="background:#fff">
|
<view class="article-detail-page">
|
||||||
<view v-if="loading" class="loading-container">
|
<view v-if="loading" class="loading-container">
|
||||||
<uni-icons type="spinner-cycle" size="40" color="#999" />
|
<uni-icons type="spinner-cycle" size="40" color="#999" />
|
||||||
<text class="loading-text">加载中...</text>
|
<text class="loading-text">加载中...</text>
|
||||||
@ -10,7 +10,7 @@
|
|||||||
<button class="retry-btn" @click="loadArticle">重试</button>
|
<button class="retry-btn" @click="loadArticle">重试</button>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<view v-else class="article-content">
|
<scroll-view v-else scroll-y class="article-content">
|
||||||
<view class="article-header">
|
<view class="article-header">
|
||||||
<text class="article-title">{{ articleData.title }}</text>
|
<text class="article-title">{{ articleData.title }}</text>
|
||||||
<text class="article-date">{{ articleData.date }}</text>
|
<text class="article-date">{{ articleData.date }}</text>
|
||||||
@ -20,33 +20,13 @@
|
|||||||
<rich-text :nodes="articleData.content"></rich-text>
|
<rich-text :nodes="articleData.content"></rich-text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</scroll-view>
|
||||||
<template #footer>
|
</view>
|
||||||
<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>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { computed } from "vue";
|
|
||||||
import { onLoad } from "@dcloudio/uni-app";
|
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 api from "@/utils/api.js";
|
||||||
import { toast, loading as showLoading, hideLoading } from "@/utils/widget";
|
|
||||||
|
|
||||||
import { ref } from "vue";
|
import { ref } from "vue";
|
||||||
const env = __VITE_ENV__;
|
const env = __VITE_ENV__;
|
||||||
const corpId = env.MP_CORP_ID;
|
const corpId = env.MP_CORP_ID;
|
||||||
@ -59,17 +39,6 @@ const articleData = ref({
|
|||||||
});
|
});
|
||||||
|
|
||||||
let articleId = "";
|
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) => {
|
const processRichTextContent = (html) => {
|
||||||
@ -106,7 +75,7 @@ const loadArticle = async () => {
|
|||||||
loading.value = true;
|
loading.value = true;
|
||||||
error.value = "";
|
error.value = "";
|
||||||
try {
|
try {
|
||||||
const res = await api("getArticle", { id: articleId, corpId, userId: userId.value });
|
const res = await api("getArticle", { id: articleId, corpId });
|
||||||
|
|
||||||
if (res.success && res.data) {
|
if (res.success && res.data) {
|
||||||
// 格式化日期
|
// 格式化日期
|
||||||
@ -118,7 +87,7 @@ const loadArticle = async () => {
|
|||||||
const day = String(d.getDate()).padStart(2, "0");
|
const day = String(d.getDate()).padStart(2, "0");
|
||||||
date = `${year}-${month}-${day}`;
|
date = `${year}-${month}-${day}`;
|
||||||
}
|
}
|
||||||
article.value = res.data;
|
|
||||||
articleData.value = {
|
articleData.value = {
|
||||||
title: res.data.title || "宣教文章",
|
title: res.data.title || "宣教文章",
|
||||||
content: processRichTextContent(res.data.content || ""),
|
content: processRichTextContent(res.data.content || ""),
|
||||||
@ -135,23 +104,7 @@ const loadArticle = async () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
async function star() {
|
onLoad((options) => {
|
||||||
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) {
|
if (options.id) {
|
||||||
articleId = options.id;
|
articleId = options.id;
|
||||||
loadArticle();
|
loadArticle();
|
||||||
@ -163,11 +116,12 @@ useLoad((options) => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
.ml-15 {
|
.article-detail-page {
|
||||||
margin-left: 30rpx;
|
width: 100%;
|
||||||
|
height: 100vh;
|
||||||
|
background-color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.loading-container,
|
.loading-container,
|
||||||
.error-container {
|
.error-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
@ -18,20 +18,26 @@
|
|||||||
<empty-data title="暂无文章" />
|
<empty-data title="暂无文章" />
|
||||||
</view>
|
</view>
|
||||||
<view v-else>
|
<view v-else>
|
||||||
<view v-for="article in searchList" :key="article._id" class="article-item" @click="previewArticle(article)">
|
<view v-for="article in searchList" :key="article._id" class="article-item ">
|
||||||
<view>
|
<view>
|
||||||
<view class="flex items-center py-12 px-15">
|
<view class="flex items-center py-12 px-15">
|
||||||
<view class="text-lg leading-normal font-semibold w-0 flex-grow truncate mr-10">
|
<view class="text-lg leading-normal font-semibold w-0 flex-grow truncate mr-10">
|
||||||
{{ article.title }}
|
{{ article.title }}
|
||||||
</view>
|
</view>
|
||||||
<view v-if="!article.isMine" @click.stop="star(article)">
|
<view @click.stop="star(article)">
|
||||||
<uni-icons class="flex-shrinl-0" :type="article.star ? 'star-filled' : 'star'"
|
<uni-icons class="flex-shrinl-0" :type="article.star ? 'star-filled' : 'star'"
|
||||||
:color="article.star ? '#FFD700' : '#999'" size="20"></uni-icons>
|
:color="article.star ? '#FFD700' : '#999'" size="20"></uni-icons>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="flex items-center px-15 pb-10">
|
<view v-if="article.authorName" class="px-15 mb-10 truncate text-base text-dark">{{ article.authorName }}
|
||||||
<view class="mr-10 w-0 flex-growt runcate text-base text-dark">{{ article.authorName }}</view>
|
</view>
|
||||||
<view class="bg-primary text-white text-sm px-10 leading-normal rounded-sm"
|
<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"
|
||||||
@click.stop="handlePrimaryAction(article)">
|
@click.stop="handlePrimaryAction(article)">
|
||||||
{{ isSelectMode ? '选择' : '发送' }}
|
{{ isSelectMode ? '选择' : '发送' }}
|
||||||
</view>
|
</view>
|
||||||
@ -69,25 +75,20 @@
|
|||||||
</view>
|
</view>
|
||||||
|
|
||||||
<view v-else>
|
<view v-else>
|
||||||
<view v-for="article in articleList" :key="article._id" class="article-item" @click="previewArticle(article)">
|
<view v-for="article in articleList" :key="article._id" class="article-item ">
|
||||||
<view>
|
<view>
|
||||||
<view class="flex items-center py-12 px-15">
|
<view class="flex items-center py-12 px-15">
|
||||||
<view class="text-lg leading-normal font-semibold w-0 flex-grow truncate mr-10">
|
<view class="text-lg leading-normal font-semibold w-0 flex-grow truncate mr-10">
|
||||||
{{ article.title }}
|
{{ article.title }}
|
||||||
</view>
|
</view>
|
||||||
<view v-if="!article.isMine" @click.stop="star(article)">
|
<view @click.stop="star(article)">
|
||||||
<uni-icons class="flex-shrinl-0" :type="article.star ? 'star-filled' : 'star'"
|
<uni-icons class="flex-shrinl-0" :type="article.star ? 'star-filled' : 'star'"
|
||||||
:color="article.star ? '#FFD700' : '#999'" size="20"></uni-icons>
|
:color="article.star ? '#FFD700' : '#999'" size="20"></uni-icons>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="flex items-center px-15 pb-10">
|
<view v-if="article.authorName" class="px-15 mb-10 truncate text-base text-dark">{{ article.authorName }}
|
||||||
<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>
|
||||||
<!-- <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 justify-between py-10 px-15">
|
||||||
<view class="flex items-center" @click="previewArticle(article)">
|
<view class="flex items-center" @click="previewArticle(article)">
|
||||||
<view class="text-base text-primary">文章详情</view>
|
<view class="text-base text-primary">文章详情</view>
|
||||||
@ -97,7 +98,7 @@
|
|||||||
@click.stop="handlePrimaryAction(article)">
|
@click.stop="handlePrimaryAction(article)">
|
||||||
{{ isSelectMode ? '选择' : '发送' }}
|
{{ isSelectMode ? '选择' : '发送' }}
|
||||||
</view>
|
</view>
|
||||||
</view> -->
|
</view>
|
||||||
<!-- <view class="article-footer">
|
<!-- <view class="article-footer">
|
||||||
<text class="article-date">{{ article.date }}</text>
|
<text class="article-date">{{ article.date }}</text>
|
||||||
<button class="send-btn" size="mini" type="primary" @click.stop="handlePrimaryAction(article)">
|
<button class="send-btn" size="mini" type="primary" @click.stop="handlePrimaryAction(article)">
|
||||||
@ -155,7 +156,7 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { ref, computed, watch } from "vue";
|
import { ref, computed, watch } from "vue";
|
||||||
import { storeToRefs } from "pinia";
|
import { storeToRefs } from "pinia";
|
||||||
import { onLoad, onUnload, onShow } from "@dcloudio/uni-app";
|
import { onLoad } from "@dcloudio/uni-app";
|
||||||
import api from "@/utils/api.js";
|
import api from "@/utils/api.js";
|
||||||
import useAccountStore from "@/store/account.js";
|
import useAccountStore from "@/store/account.js";
|
||||||
import useGuard from "@/hooks/useGuard.js";
|
import useGuard from "@/hooks/useGuard.js";
|
||||||
@ -165,6 +166,7 @@ import fullPage from '@/components/full-page.vue';
|
|||||||
import EmptyData from "@/components/empty-data.vue";
|
import EmptyData from "@/components/empty-data.vue";
|
||||||
import { toast, loading as showLoading, hideLoading } from "@/utils/widget";
|
import { toast, loading as showLoading, hideLoading } from "@/utils/widget";
|
||||||
|
|
||||||
|
|
||||||
const accountStore = useAccountStore();
|
const accountStore = useAccountStore();
|
||||||
const env = __VITE_ENV__;
|
const env = __VITE_ENV__;
|
||||||
const corpId = env.MP_CORP_ID;
|
const corpId = env.MP_CORP_ID;
|
||||||
@ -184,7 +186,6 @@ const pageParams = ref({
|
|||||||
});
|
});
|
||||||
const currentCateId = ref("my"); // 默认选中"全部"(_id 为空字符串)
|
const currentCateId = ref("my"); // 默认选中"全部"(_id 为空字符串)
|
||||||
const teams = ref([])
|
const teams = ref([])
|
||||||
const showRefresh = ref(false);
|
|
||||||
|
|
||||||
const cateList = computed(() => {
|
const cateList = computed(() => {
|
||||||
const arr = [{ label: '我的文章', value: 'my', type: 'mine' }, { label: '团队文章', value: 'team', type: 'team' }];
|
const arr = [{ label: '我的文章', value: 'my', type: 'mine' }, { label: '团队文章', value: 'team', type: 'team' }];
|
||||||
@ -281,9 +282,31 @@ const processRichTextContent = (html) => {
|
|||||||
|
|
||||||
// 预览文章
|
// 预览文章
|
||||||
const previewArticle = async (article) => {
|
const previewArticle = async (article) => {
|
||||||
uni.navigateTo({
|
try {
|
||||||
url: `/pages/message/article-detail?id=${article._id}`,
|
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",
|
||||||
|
});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 关闭预览
|
// 关闭预览
|
||||||
@ -447,9 +470,6 @@ async function star(article) {
|
|||||||
hideLoading();
|
hideLoading();
|
||||||
if (res.success) {
|
if (res.success) {
|
||||||
article.star = !article.star;
|
article.star = !article.star;
|
||||||
if (currentCateId.value === 'my') {
|
|
||||||
getMyArticleList();
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
toast(res.message || "操作失败");
|
toast(res.message || "操作失败");
|
||||||
}
|
}
|
||||||
@ -459,7 +479,6 @@ function formatArticles(articles) {
|
|||||||
return articles.map(article => {
|
return articles.map(article => {
|
||||||
const item = { ...article };
|
const item = { ...article };
|
||||||
if (article.creatorSignature && article.creatorSignature.type === 'personal') {
|
if (article.creatorSignature && article.creatorSignature.type === 'personal') {
|
||||||
item.isMine = article.creatorSignature.person.userId === userId.value;
|
|
||||||
item.authorName = article.creatorSignature.person ? article.creatorSignature.person.userName : '';
|
item.authorName = article.creatorSignature.person ? article.creatorSignature.person.userName : '';
|
||||||
} else if (article.creatorSignature && article.creatorSignature.type === 'institution') {
|
} else if (article.creatorSignature && article.creatorSignature.type === 'institution') {
|
||||||
item.authorName = article.creatorSignature.institution ? article.creatorSignature.institution.name : '';
|
item.authorName = article.creatorSignature.institution ? article.creatorSignature.institution.name : '';
|
||||||
@ -502,27 +521,11 @@ onLoad((options) => {
|
|||||||
pageParams.value.teamId = options.teamId;
|
pageParams.value.teamId = options.teamId;
|
||||||
}
|
}
|
||||||
ensureTeamId();
|
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 => {
|
watch(userId, n => {
|
||||||
if (n) {
|
if (n) {
|
||||||
getArticleList();
|
getArticleList();
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user