| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143 |
- import { get, post } from '@/core/http/http-client'
- import { buildRestPath } from '@/core/config/api-paths'
- import parseHtml from '@/core/html/html-parser'
- const ROUTE_DETAILS = buildRestPath('article/details')
- const ROUTE_AD_DETAILS = buildRestPath('article/adDetails')
- const ROUTE_LIST = buildRestPath('article/getList')
- function unwrapListPageBody(data, raw) {
- const candidates = [data, raw?.data, raw?.res?.data]
- for (const c of candidates) {
- if (!c || typeof c !== 'object' || Array.isArray(c)) continue
- if (Array.isArray(c.data) || c.current_page != null || c.last_page != null) {
- return c
- }
- if (c.data && typeof c.data === 'object' && !Array.isArray(c.data)) {
- const inner = c.data
- if (Array.isArray(inner.data) || inner.current_page != null) return inner
- }
- }
- return { data: [], current_page: 1, last_page: 1, total: 0 }
- }
- function normalizeImages(images) {
- if (Array.isArray(images)) return images.filter(Boolean)
- if (typeof images === 'string') {
- try {
- const parsed = JSON.parse(images)
- return Array.isArray(parsed) ? parsed.filter(Boolean) : []
- } catch (_) {
- return []
- }
- }
- return []
- }
- export function normalizeArticleRow(item) {
- if (!item || item.id == null) return null
- const images = normalizeImages(item.images)
- return {
- ...item,
- images,
- image: item.image || images[0] || ''
- }
- }
- export function isExternalArticleUrl(value) {
- return /^https?:\/\//i.test(String(value || '').trim())
- }
- function unwrapArticleBody(data, raw) {
- if (!data || typeof data !== 'object') data = {}
- if (data.id != null && (data.content != null || data.url != null || data.title != null)) {
- return data
- }
- if (data.data && typeof data.data === 'object') {
- const inner = data.data
- if (inner.id != null || inner.content != null || inner.url != null) return inner
- }
- const env = raw?.res?.data ?? raw?.data
- if (env && typeof env === 'object') {
- if (env.id != null || env.content != null || env.url != null) return env
- if (env.data && typeof env.data === 'object') {
- const nested = env.data
- if (nested.id != null || nested.content != null || nested.url != null) return nested
- }
- }
- return data
- }
- function pickArticleContent(article) {
- if (!article || typeof article !== 'object') return ''
- return (
- article.content ??
- article.content_html ??
- article.detail ??
- article.body ??
- ''
- )
- }
- /**
- * @param {string} html
- * @param {(src: string, w?: number, h?: number) => string} [ossFn]
- * @param {{ hideImages?: boolean }} [opts]
- * @returns {{ html: string, nodes: unknown[] }}
- */
- export function formatArticleRichContent(html, ossFn, opts = {}) {
- const raw = pickArticleContent(typeof html === 'object' ? html : { content: html })
- if (!raw) return { html: '', nodes: [] }
- let content = String(raw).replace(/\\/g, '')
- if (opts.hideImages) {
- content = content.replace(/<img/gi, '<img style="display:none;"')
- } else if (ossFn) {
- content = content.replace(/<img[^>]*src=['"]([^'"]+)['"][^>]*>/gi, (match, capture) => {
- const src = ossFn(capture, 500, 0)
- return `<img style="display:block;max-width:100%;height:auto;" src="${src}">`
- })
- }
- let nodes = []
- try {
- nodes = parseHtml(content)
- } catch (_) {
- nodes = [{ type: 'text', text: content.replace(/<[^>]+>/g, '') }]
- }
- return { html: content, nodes }
- }
- /** @deprecated 使用 formatArticleRichContent */
- export function formatArticleHtmlNodes(html, ossFn, opts = {}) {
- return formatArticleRichContent(html, ossFn, opts).nodes
- }
- export async function fetchArticleDetails(id) {
- const { data, raw } = await get(ROUTE_DETAILS, { id })
- const article = unwrapArticleBody(data, raw)
- if (!article.content) {
- const merged = pickArticleContent(article)
- if (merged) article.content = merged
- }
- return article
- }
- export async function fetchAdvertDetails(id) {
- const { data, raw } = await get(ROUTE_AD_DETAILS, { id })
- return unwrapArticleBody(data, raw)
- }
- export async function fetchArticleListPage(page = 1, type = 'new') {
- const { data, raw } = await post(ROUTE_LIST, { page, type })
- const body = unwrapListPageBody(data, raw)
- const rows = (Array.isArray(body.data) ? body.data : [])
- .map(normalizeArticleRow)
- .filter(Boolean)
- return {
- rows,
- total: Number(body.total || rows.length),
- currentPage: Number(body.current_page || page || 1),
- lastPage: Number(body.last_page || body.current_page || 1)
- }
- }
|