Merge remote-tracking branch 'origin/dev-hjf'

This commit is contained in:
huxuejian 2026-02-09 15:18:06 +08:00
commit 4c8768d490
2 changed files with 183 additions and 34 deletions

View File

@ -1,7 +1,7 @@
<template> <template>
<view class="bg-gray-100 min-h-screen"> <view class="bg-gray-100 min-h-screen">
<!-- Category Tabs --> <!-- Category Tabs -->
<scroll-view scroll-x class="bg-white whitespace-nowrap px-15 py-10 sticky top-0 z-10 w-full" <!-- <scroll-view scroll-x class="bg-white whitespace-nowrap px-15 py-10 sticky top-0 z-10 w-full"
:show-scrollbar="false"> :show-scrollbar="false">
<view v-for="(tab, index) in tabs" :key="index" <view v-for="(tab, index) in tabs" :key="index"
class="inline-block px-15 py-5 mr-10 text-sm rounded-full border transition-colors" :class="[ class="inline-block px-15 py-5 mr-10 text-sm rounded-full border transition-colors" :class="[
@ -11,7 +11,7 @@
]" @click="selectCate(tab.value)"> ]" @click="selectCate(tab.value)">
{{ tab.name }} {{ tab.name }}
</view> </view>
</scroll-view> </scroll-view> -->
<!-- List --> <!-- List -->
<view v-if="loading && list.length === 0" class="loading-container"> <view v-if="loading && list.length === 0" class="loading-container">
@ -50,7 +50,7 @@
</template> </template>
<script setup> <script setup>
import { ref } from "vue"; import { computed, ref } from "vue";
import { onLoad, onReachBottom } from "@dcloudio/uni-app"; import { onLoad, onReachBottom } from "@dcloudio/uni-app";
import dayjs from "dayjs"; import dayjs from "dayjs";
import api from "@/utils/api.js"; import api from "@/utils/api.js";
@ -60,15 +60,149 @@ const env = __VITE_ENV__;
const defaultCorpId = env.MP_CORP_ID; const defaultCorpId = env.MP_CORP_ID;
const corpId = ref(""); const corpId = ref("");
const enabledIds = ref([]);
const tabs = ref([{ name: "全部", value: "" }]); const tabs = ref([{ name: "全部", value: "" }]);
const activeCateId = ref(""); const activeCateId = ref("");
const allArticles = ref([]);
const list = ref([]); const list = ref([]);
const total = ref(0); const total = ref(0);
const page = ref(1); const page = ref(1);
const pageSize = 20; const pageSize = 20;
const loading = ref(false); const loading = ref(false);
const uniqStrings = (items) => {
const seen = new Set();
const out = [];
for (const item of items) {
const s = typeof item === "string" ? item.trim() : "";
if (!s || seen.has(s)) continue;
seen.add(s);
out.push(s);
}
return out;
};
const parseIdsParam = (raw) => {
if (!raw) return [];
const text = Array.isArray(raw) ? raw.join(",") : String(raw);
const decoded = decodeURIComponent(text);
return uniqStrings(decoded.split(","));
};
const getAllTab = () => ({ name: tabs.value?.[0]?.name || "全部", value: "" });
const getArticleCateIds = (article) => {
const ids = [];
if (!article) return ids;
if (Array.isArray(article.cateIds)) ids.push(...article.cateIds);
if (typeof article.cateIds === "string") ids.push(article.cateIds);
if (typeof article.cateId === "string") ids.push(article.cateId);
if (typeof article.categoryId === "string") ids.push(article.categoryId);
if (Array.isArray(article.categoryIds)) ids.push(...article.categoryIds);
if (typeof article.categoryIds === "string") ids.push(article.categoryIds);
if (Array.isArray(article.cateList)) {
ids.push(
...article.cateList.map((c) => c?._id || c?.id).filter((v) => typeof v === "string")
);
}
if (article.cate && typeof article.cate === "object") {
const v = article.cate._id || article.cate.id;
if (typeof v === "string") ids.push(v);
}
if (typeof article.cate === "string") ids.push(article.cate);
return uniqStrings(ids);
};
const filteredArticles = computed(() => {
const cateId = activeCateId.value;
if (!cateId) return allArticles.value;
return allArticles.value.filter((article) => getArticleCateIds(article).includes(cateId));
});
const relatedCateIdSet = computed(() => {
const set = new Set();
for (const article of allArticles.value) {
for (const cateId of getArticleCateIds(article)) set.add(cateId);
}
return set;
});
const refreshList = (reset = false) => {
if (reset) {
page.value = 1;
list.value = [];
}
const rows = filteredArticles.value || [];
total.value = rows.length;
const start = (page.value - 1) * pageSize;
const end = start + pageSize;
const slice = rows.slice(start, end);
if (page.value === 1) list.value = slice;
else list.value = [...list.value, ...slice];
};
const loadEnabledArticles = async () => {
if (!corpId.value || enabledIds.value.length === 0) {
allArticles.value = [];
tabs.value = [getAllTab()];
refreshList(true);
return;
}
if (loading.value) return;
loading.value = true;
try {
const ids = enabledIds.value;
const res = await api("getArticleByIds", { corpId: corpId.value, ids: ids.join(",") });
const rows = res && Array.isArray(res.list) ? res.list : [];
const order = new Map(ids.map((id, idx) => [id, idx]));
allArticles.value = rows
.map((r) => ({
...r,
time: r?.createTime ? dayjs(r.createTime).format("YYYY-MM-DD") : "",
}))
.sort((a, b) => (order.get(a?._id) ?? 1e9) - (order.get(b?._id) ?? 1e9));
} catch (err) {
console.error("loadEnabledArticles failed:", err);
allArticles.value = [];
} finally {
loading.value = false;
}
};
const loadTabs = async () => {
if (!corpId.value) return;
const related = relatedCateIdSet.value;
if (!related.size) {
tabs.value = [getAllTab()];
return;
}
try {
const res = await api("getArticleCateList", { corpId: corpId.value });
const cates = res && Array.isArray(res.list) ? res.list : [];
const visible = cates.filter((c) => related.has(c?._id));
tabs.value = [
getAllTab(),
...visible.map((i) => ({ name: i.label || i.name || "", value: i._id })),
];
} catch (err) {
console.error("loadTabs failed:", err);
tabs.value = [getAllTab()];
}
};
const loadCates = async () => { const loadCates = async () => {
if (!corpId.value) return; if (!corpId.value) return;
try { try {
@ -118,7 +252,7 @@ const loadList = async (reset = false) => {
const selectCate = async (cateId) => { const selectCate = async (cateId) => {
if (activeCateId.value === cateId) return; if (activeCateId.value === cateId) return;
activeCateId.value = cateId; activeCateId.value = cateId;
await loadList(true); refreshList(true);
}; };
function goToDetail(item) { function goToDetail(item) {
@ -128,15 +262,18 @@ function goToDetail(item) {
onLoad(async (options) => { onLoad(async (options) => {
corpId.value = options?.corpId || defaultCorpId || ""; corpId.value = options?.corpId || defaultCorpId || "";
await loadCates(); enabledIds.value = parseIdsParam(options?.ids);
await loadList(true); activeCateId.value = "";
await loadEnabledArticles();
await loadTabs();
refreshList(true);
}); });
onReachBottom(() => { onReachBottom(() => {
if (loading.value) return; if (loading.value) return;
if (list.value.length >= total.value) return; if (list.value.length >= total.value) return;
page.value += 1; page.value += 1;
loadList(false); refreshList(false);
}); });
</script> </script>

View File

@ -26,7 +26,7 @@
</view> </view>
</template> </template>
<script setup> <script setup>
import { ref, watch } from "vue"; import { computed, ref, watch } from "vue";
import api from '@/utils/api'; import api from '@/utils/api';
const props = defineProps({ const props = defineProps({
@ -38,38 +38,52 @@ const props = defineProps({
const articles = ref([]); const articles = ref([]);
const total = ref(0); const total = ref(0);
const page = ref(1);
const pageSize = ref(3);
const loading = ref(false); const loading = ref(false);
const pageSize = 3;
const qrcode = computed(() => {
const qrcodes = props.team && Array.isArray(props.team.qrcodes) ? props.team.qrcodes : [];
return qrcodes[0] || {};
});
const articleIds = computed(() => {
const configured = qrcode.value && Array.isArray(qrcode.value.articles) ? qrcode.value.articles : [];
const ids = configured.map((item) => item?._id).filter((id) => typeof id === "string" && id.trim());
return qrcode.value?.enableAnnounce === "YES" ? ids : [];
});
function goToDetail(article) { function goToDetail(article) {
if (!article?._id) return; if (!article?._id) return;
uni.navigateTo({ url: `/pages/article/article-detail?id=${article._id}` }); uni.navigateTo({ url: `/pages/article/article-detail?id=${article._id}` });
} }
const loadArticles = async (reset = false) => { const loadArticles = async () => {
const corpId = props.team?.corpId || ""; const corpId = props.team?.corpId || "";
if (!corpId || loading.value) return; const ids = articleIds.value;
if (reset) {
page.value = 1; if (!corpId || ids.length === 0) {
articles.value = []; articles.value = [];
total.value = 0; total.value = 0;
return;
} }
if (loading.value) return;
loading.value = true; loading.value = true;
try { try {
const params = { const res = await api("getArticleByIds", { corpId, ids: ids.join(",") }, false);
corpId, const rows = res && Array.isArray(res.list) ? res.list : [];
page: page.value,
pageSize: pageSize.value, const order = new Map(ids.map((id, idx) => [id, idx]));
enable: true, const sorted = rows
}; .slice()
const res = await api("getArticleList", params, false); .sort((a, b) => (order.get(a?._id) ?? 1e9) - (order.get(b?._id) ?? 1e9));
const list = res && Array.isArray(res.list) ? res.list : [];
total.value = Number(res?.total) || 0; total.value = sorted.length;
if (page.value === 1) articles.value = list; articles.value = sorted.slice(0, pageSize);
else articles.value = [...articles.value, ...list];
} catch (err) { } catch (err) {
console.error("loadArticles failed:", err); console.error("loadArticles failed:", err);
articles.value = [];
total.value = 0;
} finally { } finally {
loading.value = false; loading.value = false;
} }
@ -77,22 +91,20 @@ const loadArticles = async (reset = false) => {
function toMorePage() { function toMorePage() {
const corpId = props.team?.corpId || ""; const corpId = props.team?.corpId || "";
if (!corpId) return; const ids = articleIds.value;
uni.navigateTo({ url: `/pages/article/article-cate-list?corpId=${corpId}` }); if (!corpId || ids.length === 0) return;
uni.navigateTo({ url: `/pages/article/article-cate-list?corpId=${corpId}&ids=${encodeURIComponent(ids.join(","))}` });
} }
watch( watch(
() => props.team?.corpId, () => ({ corpId: props.team?.corpId || "", ids: articleIds.value.join(",") }),
async (corpId) => { async ({ corpId, ids }) => {
if (!corpId) { if (!corpId || !ids) {
articles.value = []; articles.value = [];
total.value = 0; total.value = 0;
page.value = 1;
pageSize.value = 3;
return; return;
} }
pageSize.value = 3; await loadArticles();
await loadArticles(true);
}, },
{ immediate: true } { immediate: true }
); );