Compare commits
4 Commits
1c1f2f6594
...
aef44a528a
| Author | SHA1 | Date | |
|---|---|---|---|
| aef44a528a | |||
| c26591a06a | |||
| 0b4c3bf8e7 | |||
| 957d349b4b |
@ -1,37 +1,15 @@
|
|||||||
import { Article, ArticleRanking, ArticleView } from "@/types/Article";
|
import { Article, axios, Page, PageResult } from "timi-web";
|
||||||
import { axios, Page, PageResult } from "timi-web";
|
import { ArticleRanking } from "@/types/Article.ts";
|
||||||
|
|
||||||
async function page(page: Page): Promise<PageResult<Article<any>>> {
|
async function page(page: Page): Promise<PageResult<Article<any>>> {
|
||||||
return axios.post("/article/list", page);
|
return axios.post("/article/list", page);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取文章
|
|
||||||
*
|
|
||||||
* @param id 文章 ID
|
|
||||||
* @returns 文章数据
|
|
||||||
*/
|
|
||||||
async function view(id: number): Promise<ArticleView<any>> {
|
|
||||||
return axios.get(`/article/${id}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 喜欢文章,后端有限调用,1240ms 一次
|
|
||||||
*
|
|
||||||
* @param id 文章 ID
|
|
||||||
* @returns 最新喜欢数量
|
|
||||||
*/
|
|
||||||
async function like(id: number): Promise<number> {
|
|
||||||
return axios.get(`/article/like/${id}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function listRanking(): Promise<ArticleRanking[]> {
|
async function listRanking(): Promise<ArticleRanking[]> {
|
||||||
return axios.get("/article/list/ranking");
|
return axios.get("/article/list/ranking");
|
||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
view,
|
|
||||||
like,
|
|
||||||
page,
|
page,
|
||||||
listRanking
|
listRanking
|
||||||
};
|
};
|
||||||
|
|||||||
@ -18,7 +18,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { Article } from "@/types/Article";
|
import { Article } from "timi-web";
|
||||||
|
|
||||||
const props = withDefaults(defineProps<{
|
const props = withDefaults(defineProps<{
|
||||||
list: Article<any>[]
|
list: Article<any>[]
|
||||||
|
|||||||
@ -25,9 +25,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { CommentBizType, MarkdownView, SettingKey, SettingMapper, Time } from "timi-web";
|
import { ArticleAPI, ArticleView, CommentBizType, MarkdownView, SettingKey, SettingMapper, Time } from "timi-web";
|
||||||
import ArticleAPI from "@/api/ArticleAPI";
|
|
||||||
import { ArticleView } from "@/types/Article";
|
|
||||||
import { Comment } from "timi-tdesign-pc";
|
import { Comment } from "timi-tdesign-pc";
|
||||||
|
|
||||||
// 文章
|
// 文章
|
||||||
|
|||||||
@ -55,8 +55,19 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ArticleAttachType, ArticleMusicExtendData, ArticleView } from "@/types/Article.ts";
|
import {
|
||||||
import { CommentBizType, CommonAPI, Icon, MarkdownView, SettingKey, SettingMapper, Time, Toolkit } from "timi-web";
|
ArticleAttachType,
|
||||||
|
ArticleMusicExtendData,
|
||||||
|
ArticleView,
|
||||||
|
CommentBizType,
|
||||||
|
CommonAPI,
|
||||||
|
Icon,
|
||||||
|
MarkdownView,
|
||||||
|
SettingKey,
|
||||||
|
SettingMapper,
|
||||||
|
Time,
|
||||||
|
Toolkit
|
||||||
|
} from "timi-web";
|
||||||
import { Comment } from "timi-tdesign-pc";
|
import { Comment } from "timi-tdesign-pc";
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
@ -73,6 +84,7 @@ const articleTime = computed(() => {
|
|||||||
return "编辑于 " + Time.toPassedDateTime(article.value.updatedAt);
|
return "编辑于 " + Time.toPassedDateTime(article.value.updatedAt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return "";
|
||||||
});
|
});
|
||||||
|
|
||||||
// 专辑封面
|
// 专辑封面
|
||||||
@ -87,7 +99,7 @@ const coverUrl = computed(() => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return undefined;
|
return undefined;
|
||||||
})
|
});
|
||||||
|
|
||||||
// 展开可播放媒体
|
// 展开可播放媒体
|
||||||
const activeMediaIndex = ref();
|
const activeMediaIndex = ref();
|
||||||
|
|||||||
@ -13,8 +13,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { CommentBizType, MarkdownView, SettingKey, SettingMapper, Time } from "timi-web";
|
import { ArticleView, CommentBizType, MarkdownView, SettingKey, SettingMapper, Time } from "timi-web";
|
||||||
import { ArticleView } from "@/types/Article";
|
|
||||||
import { Comment } from "timi-tdesign-pc";
|
import { Comment } from "timi-tdesign-pc";
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
@ -32,6 +31,7 @@ const articleTime = computed(() => {
|
|||||||
return "编辑于 " + Time.toPassedDateTime(article.value.updatedAt);
|
return "编辑于 " + Time.toPassedDateTime(article.value.updatedAt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return "";
|
||||||
});
|
});
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -58,8 +58,19 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ArticleAttachType, ArticleSoftwareExtendData, ArticleView } from "@/types/Article.ts";
|
import {
|
||||||
import { CommentBizType, CommonAPI, IOSize, MarkdownView, SettingKey, SettingMapper, Time, Toolkit } from "timi-web";
|
ArticleAttachType,
|
||||||
|
ArticleSoftwareExtendData,
|
||||||
|
ArticleView,
|
||||||
|
CommentBizType,
|
||||||
|
CommonAPI,
|
||||||
|
IOSize,
|
||||||
|
MarkdownView,
|
||||||
|
SettingKey,
|
||||||
|
SettingMapper,
|
||||||
|
Time,
|
||||||
|
Toolkit
|
||||||
|
} from "timi-web";
|
||||||
import { Comment } from "timi-tdesign-pc";
|
import { Comment } from "timi-tdesign-pc";
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
@ -76,6 +87,7 @@ const articleTime = computed(() => {
|
|||||||
return "编辑于 " + Time.toPassedDateTime(article.value.updatedAt);
|
return "编辑于 " + Time.toPassedDateTime(article.value.updatedAt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return "";
|
||||||
});
|
});
|
||||||
|
|
||||||
const coverUrl = computed(() => {
|
const coverUrl = computed(() => {
|
||||||
@ -89,7 +101,7 @@ const coverUrl = computed(() => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return undefined;
|
return undefined;
|
||||||
})
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
|||||||
@ -1,6 +1,3 @@
|
|||||||
import IndexLayout from "@/layout/IndexLayout.vue";
|
|
||||||
import ArticleDetail from "@/views/ArticleDetail.vue";
|
|
||||||
import ArticleIndex from "@/views/ArticleIndex.vue";
|
|
||||||
import { createRouter, createWebHistory } from "vue-router";
|
import { createRouter, createWebHistory } from "vue-router";
|
||||||
|
|
||||||
export default createRouter({
|
export default createRouter({
|
||||||
@ -9,27 +6,22 @@ export default createRouter({
|
|||||||
{
|
{
|
||||||
path: "/",
|
path: "/",
|
||||||
name: "Index",
|
name: "Index",
|
||||||
component: IndexLayout,
|
component: () => import("@/layout/IndexLayout.vue"),
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: "/",
|
path: "/",
|
||||||
name: "ArticleIndex",
|
name: "ArticleIndex",
|
||||||
component: ArticleIndex
|
component: () => import("@/views/ArticleIndex.vue")
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/aid:id.html",
|
path: "/aid:id.html",
|
||||||
name: "ArticleDetail",
|
name: "ArticleDetail",
|
||||||
component: ArticleDetail
|
component: () => import("@/views/ArticleDetail.vue")
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/about",
|
path: "/about",
|
||||||
name: "About",
|
name: "About",
|
||||||
component: ArticleDetail
|
component: () => import("@/views/ArticleDetail.vue")
|
||||||
},
|
|
||||||
{
|
|
||||||
// 兼容性保留
|
|
||||||
path: "/article/aid:id.html",
|
|
||||||
redirect: to => `/aid${to.params.id}.html`
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,61 +1,4 @@
|
|||||||
import { AttachmentView, Model } from "timi-web";
|
import { Model } from "timi-web";
|
||||||
|
|
||||||
// 文章
|
|
||||||
export type Article<E extends ArticleMusicExtendData | ArticleSoftwareExtendData> = {
|
|
||||||
title?: string;
|
|
||||||
type: ArticleType;
|
|
||||||
classId: number;
|
|
||||||
digest?: string;
|
|
||||||
data?: string;
|
|
||||||
extendData?: E;
|
|
||||||
reads: number;
|
|
||||||
likes: number;
|
|
||||||
showComment: boolean;
|
|
||||||
canComment: boolean;
|
|
||||||
canRanking: boolean;
|
|
||||||
} & Model;
|
|
||||||
|
|
||||||
export type ArticleView<E extends ArticleMusicExtendData | ArticleSoftwareExtendData> = {
|
|
||||||
comments?: number;
|
|
||||||
clazz: ArticleClass;
|
|
||||||
labels: ArticleLabel[];
|
|
||||||
attachmentList: AttachmentView[];
|
|
||||||
} & Article<E>;
|
|
||||||
|
|
||||||
export enum ArticleType {
|
|
||||||
|
|
||||||
/** 关于 */
|
|
||||||
ABOUT,
|
|
||||||
|
|
||||||
/** 公版 */
|
|
||||||
PUBLIC,
|
|
||||||
|
|
||||||
/** 音乐 */
|
|
||||||
MUSIC,
|
|
||||||
|
|
||||||
/** 软件 */
|
|
||||||
SOFTWARE
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum ArticleAttachType {
|
|
||||||
|
|
||||||
COVER,
|
|
||||||
}
|
|
||||||
|
|
||||||
// 文章分类
|
|
||||||
export type ArticleClass = {
|
|
||||||
name?: string;
|
|
||||||
isOther?: boolean;
|
|
||||||
order?: number;
|
|
||||||
|
|
||||||
count?: number;
|
|
||||||
} & Model;
|
|
||||||
|
|
||||||
// 文章标签
|
|
||||||
export type ArticleLabel = {
|
|
||||||
name?: string;
|
|
||||||
count?: number;
|
|
||||||
} & Model;
|
|
||||||
|
|
||||||
// 每周排行
|
// 每周排行
|
||||||
export type ArticleRanking = {
|
export type ArticleRanking = {
|
||||||
@ -63,53 +6,3 @@ export type ArticleRanking = {
|
|||||||
count?: number;
|
count?: number;
|
||||||
recentAt?: number;
|
recentAt?: number;
|
||||||
} & Model;
|
} & Model;
|
||||||
|
|
||||||
export type ArticleMusicExtendData = {
|
|
||||||
title: string;
|
|
||||||
list: ArticleMusicItem[];
|
|
||||||
info: {
|
|
||||||
key: string;
|
|
||||||
value: string;
|
|
||||||
}[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export type ArticleSoftwareExtendData = {
|
|
||||||
url?: string;
|
|
||||||
downloads: ArticleSoftwareDownload[];
|
|
||||||
format: string;
|
|
||||||
runtime: ArticleSoftwareRuntime[];
|
|
||||||
size: number;
|
|
||||||
version: string;
|
|
||||||
password?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum ArticleSoftwareDownloadType {
|
|
||||||
|
|
||||||
TIMI_MONGO,
|
|
||||||
|
|
||||||
TIMI_COS,
|
|
||||||
|
|
||||||
URL
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum ArticleSoftwareRuntime {
|
|
||||||
|
|
||||||
JVM,
|
|
||||||
|
|
||||||
WINDOWS,
|
|
||||||
|
|
||||||
LINUX,
|
|
||||||
|
|
||||||
MAC_OS
|
|
||||||
}
|
|
||||||
|
|
||||||
export type ArticleSoftwareDownload = {
|
|
||||||
type: ArticleSoftwareDownloadType;
|
|
||||||
value: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type ArticleMusicItem = {
|
|
||||||
title: string;
|
|
||||||
audio?: string;
|
|
||||||
video?: string;
|
|
||||||
}
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<article class="article-detail">
|
<article class="article-detail">
|
||||||
<header v-if="!isAbout" class="header">
|
<header v-if="!isAboutRoute" class="header">
|
||||||
<div class="relative">
|
<div class="relative">
|
||||||
<t-button
|
<t-button
|
||||||
class="back"
|
class="back"
|
||||||
@ -37,38 +37,32 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { Icon } from "timi-web";
|
import { ArticleAPI, ArticleView, Icon } from "timi-web";
|
||||||
import ArticleAPI from "@/api/ArticleAPI";
|
|
||||||
import ArticleAbout from "@/components/article/template/ArticleAbout.vue";
|
|
||||||
import ArticleMusic from "@/components/article/template/ArticleMusic.vue";
|
|
||||||
import ArticlePublic from "@/components/article/template/ArticlePublic.vue";
|
|
||||||
import ArticleSoftware from "@/components/article/template/ArticleSoftware.vue";
|
|
||||||
import { ArticleView } from "@/types/Article";
|
|
||||||
import { type Component } from "vue";
|
import { type Component } from "vue";
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
const article = ref<ArticleView<any>>();
|
const article = ref<ArticleView<any>>();
|
||||||
const isAbout = ref<boolean>(false);
|
|
||||||
const template = ref<Component | null>(null);
|
const template = ref<Component | null>(null);
|
||||||
const templates: Record<string, Component> = {
|
const templates: Record<string, () => Promise<Component>> = {
|
||||||
ABOUT: ArticleAbout,
|
ABOUT: () => import("@/components/article/template/ArticleAbout.vue"),
|
||||||
MUSIC: ArticleMusic,
|
MUSIC: () => import("@/components/article/template/ArticleMusic.vue"),
|
||||||
PUBLIC: ArticlePublic,
|
PUBLIC: () => import("@/components/article/template/ArticlePublic.vue"),
|
||||||
SOFTWARE: ArticleSoftware
|
SOFTWARE: () => import("@/components/article/template/ArticleSoftware.vue")
|
||||||
};
|
};
|
||||||
|
const isAboutRoute = computed(() => route.name === "About");
|
||||||
|
|
||||||
watch(article, () => {
|
watch(article, () => {
|
||||||
if (article.value) {
|
if (!article.value) {
|
||||||
template.value = markRaw(templates[article.value.type]);
|
return;
|
||||||
}
|
}
|
||||||
|
const loader = templates[isAboutRoute.value ? "ABOUT" : article.value.type];
|
||||||
|
template.value = defineAsyncComponent(loader);
|
||||||
});
|
});
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
isAbout.value = route.name === "About";
|
const id = isAboutRoute.value ? 1 : route.params.id as any as number;
|
||||||
|
|
||||||
const id = isAbout.value ? 1 : route.params.id as any as number;
|
|
||||||
article.value = await ArticleAPI.view(id);
|
article.value = await ArticleAPI.view(id);
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -68,9 +68,9 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { deviceStore, Icon, Page, PageResult, Toolkit } from "timi-web";
|
import { Article, deviceStore, Icon, Page, PageResult, Toolkit } from "timi-web";
|
||||||
import ArticleAPI from "@/api/ArticleAPI";
|
import ArticleAPI from "@/api/ArticleAPI";
|
||||||
import { Article, ArticleRanking } from "@/types/Article";
|
import { ArticleRanking } from "@/types/Article";
|
||||||
import ArticleList from "@/components/article/ArticleList.vue";
|
import ArticleList from "@/components/article/ArticleList.vue";
|
||||||
import { Friend } from "@/types/Friend.ts";
|
import { Friend } from "@/types/Friend.ts";
|
||||||
import BlogAPI from "@/api/BlogAPI.ts";
|
import BlogAPI from "@/api/BlogAPI.ts";
|
||||||
|
|||||||
Reference in New Issue
Block a user