Taro.navigateTo({url: `./index?id=${item.navigationId}`})}
+ onClick={() => Taro.navigateTo({url: `/${item.model}/index?id=${item.navigationId}`})}
>
{/* 图片容器 */}
diff --git a/src/honor/list.tsx b/src/honor/list.tsx
index b973b13..d356a77 100644
--- a/src/honor/list.tsx
+++ b/src/honor/list.tsx
@@ -102,8 +102,8 @@ const List = () => {
}}>
{item.title}
{item.comments || '暂无'}
diff --git a/src/pages/ai/index.scss b/src/pages/ai/index.scss
index 39e932f..9a6455c 100644
--- a/src/pages/ai/index.scss
+++ b/src/pages/ai/index.scss
@@ -149,6 +149,108 @@ html {
.message-text {
flex: 1;
white-space: pre-wrap;
+
+ .message-markdown {
+ // 通用Markdown样式
+ .markdown-paragraph {
+ margin-bottom: 8px;
+ }
+
+ .markdown-list-item,
+ .markdown-ordered-list-item {
+ margin-bottom: 4px;
+ }
+
+ .markdown-heading {
+ margin: 12px 0 6px 0;
+
+ &.markdown-h1 {
+ font-size: 1.2rem;
+ border-bottom: 1px solid #ddd;
+ padding-bottom: 2px;
+ }
+
+ &.markdown-h2 {
+ font-size: 1.1rem;
+ }
+
+ &.markdown-h3 {
+ font-size: 1rem;
+ }
+ }
+
+ // AI消息特定样式
+ &.ai-markdown {
+ .markdown-code-block {
+ background-color: #f8f9fa;
+ border: 1px solid #e9ecef;
+ border-radius: 4px;
+ padding: 8px;
+ margin: 8px 0;
+ font-size: 0.9rem;
+ }
+
+ .markdown-inline-code {
+ background-color: #f1f3f4;
+ padding: 2px 4px;
+ border-radius: 3px;
+ font-size: 0.9rem;
+ color: #d73a49;
+ }
+
+ .markdown-blockquote {
+ border-left: 3px solid #3498db;
+ padding-left: 8px;
+ margin: 8px 0;
+ background-color: rgba(52, 152, 219, 0.1);
+ }
+
+ .markdown-link {
+ color: #3498db;
+ text-decoration: underline;
+ }
+ }
+
+ // 用户消息特定样式
+ &.user-markdown {
+ .markdown-code-block {
+ background-color: rgba(255, 255, 255, 0.2);
+ border: 1px solid rgba(255, 255, 255, 0.3);
+ border-radius: 4px;
+ padding: 8px;
+ margin: 8px 0;
+ font-size: 0.9rem;
+ }
+
+ .markdown-inline-code {
+ background-color: rgba(255, 255, 255, 0.2);
+ padding: 2px 4px;
+ border-radius: 3px;
+ font-size: 0.9rem;
+ color: #fff;
+ }
+
+ .markdown-blockquote {
+ border-left: 3px solid rgba(255, 255, 255, 0.5);
+ padding-left: 8px;
+ margin: 8px 0;
+ background-color: rgba(255, 255, 255, 0.1);
+ }
+
+ .markdown-link {
+ color: #fff;
+ text-decoration: underline;
+ }
+
+ .markdown-bold {
+ color: #fff;
+ }
+
+ .markdown-text {
+ color: #fff;
+ }
+ }
+ }
}
.typing-cursor {
@@ -194,10 +296,8 @@ html {
.message-input {
width: 100%;
- min-height: 90px;
- max-height: 120px;
padding: 10px 16px;
- border: 1px solid #e0e0e0;
+ border: 2px solid #424242;
border-radius: 20px;
font-size: 1rem; // 使用 rem 单位
line-height: 1.8;
@@ -249,7 +349,7 @@ html {
.stop-button {
min-width: 60px;
- height: 40px;
+ height: 60px;
border-radius: 20px;
background: linear-gradient(135deg, #ff6b6b 0%, #ee5a52 100%);
border: none;
diff --git a/src/pages/ai/index.tsx b/src/pages/ai/index.tsx
index 2193efe..3ee910c 100644
--- a/src/pages/ai/index.tsx
+++ b/src/pages/ai/index.tsx
@@ -1,11 +1,14 @@
import {useEffect, useState, useRef} from "react";
-import {View, Textarea} from '@tarojs/components';
+import {Textarea} from '@tarojs/components';
import Taro from '@tarojs/taro';
import {Button} from '@nutui/nutui-react-taro';
-import {User, ArrowUp, Home} from '@nutui/icons-react-taro';
-import {sendAiMessage, stopAiMessage} from '@/api/ai';
+import {User, Home} from '@nutui/icons-react-taro';
+import {sendAiMessage} from '@/api/ai';
import {createWebSocket} from '@/utils/websocket';
import {getAiToken} from '@/utils/aiToken';
+import MarkdownRenderer from '@/components/MarkdownRenderer';
+// 显示html富文本
+import {View, RichText} from '@tarojs/components'
import './index.scss';
import {WSS_API_URL} from "@/utils/server";
@@ -27,7 +30,7 @@ const AiChat = () => {
const [messages, setMessages] = useState
([]);
const [inputValue, setInputValue] = useState('');
const [isLoading, setIsLoading] = useState(false);
- const [currentTaskId, setCurrentTaskId] = useState('');
+ // const [currentTaskId, setCurrentTaskId] = useState('');
const [wsConnected, setWsConnected] = useState(false);
const [isInitialized, setIsInitialized] = useState(false);
const messagesEndRef = useRef(null);
@@ -84,7 +87,7 @@ const AiChat = () => {
msg.isTyping ? {...msg, isTyping: false} : msg
));
setIsLoading(false);
- setCurrentTaskId('');
+ // setCurrentTaskId('');
} else {
// 实时更新AI回复消息
setMessages(prev => {
@@ -109,7 +112,7 @@ const AiChat = () => {
});
if (data.taskId) {
- setCurrentTaskId(data.taskId);
+ // setCurrentTaskId(data.taskId);
}
}
@@ -270,20 +273,20 @@ const AiChat = () => {
};
// 停止AI回复
- const handleStopMessage = async () => {
- if (currentTaskId) {
- try {
- await stopAiMessage({taskId: currentTaskId});
- setIsLoading(false);
- setCurrentTaskId('');
- setMessages(prev => prev.map(msg =>
- msg.isTyping ? {...msg, isTyping: false} : msg
- ));
- } catch (error) {
- console.error('停止消息失败:', error);
- }
- }
- };
+ // const handleStopMessage = async () => {
+ // if (currentTaskId) {
+ // try {
+ // await stopAiMessage({taskId: currentTaskId});
+ // setIsLoading(false);
+ // setCurrentTaskId('');
+ // setMessages(prev => prev.map(msg =>
+ // msg.isTyping ? {...msg, isTyping: false} : msg
+ // ));
+ // } catch (error) {
+ // console.error('停止消息失败:', error);
+ // }
+ // }
+ // };
// 处理快捷问题点击
const handleQuickQuestion = (question: string) => {
@@ -341,7 +344,10 @@ const AiChat = () => {
- {message.query || (message.isTyping && message.type === 'ai' ? '正在思考中...' : '')}
+
{message.isTyping && message.type === 'ai' && message.query && (
|
@@ -365,7 +371,10 @@ const AiChat = () => {
className="question-item"
onClick={() => handleQuickQuestion(question)}
>
- {question}
+
))}
@@ -373,45 +382,33 @@ const AiChat = () => {
)}
-
-
-
- {isLoading ? (
-
- ) : (
-
);
};
diff --git a/src/photo/index.tsx b/src/photo/index.tsx
index 49aa380..9bf17f4 100644
--- a/src/photo/index.tsx
+++ b/src/photo/index.tsx
@@ -60,7 +60,7 @@ const Index = () => {
Taro.navigateTo({url: `./index?id=${item.navigationId}`})}
+ onClick={() => Taro.navigateTo({url: `/${item.model}/index?id=${item.navigationId}`})}
>
{/* 图片容器 */}
diff --git a/src/zzjy/detail.config.ts b/src/zzjy/detail.config.ts
new file mode 100644
index 0000000..349c0e2
--- /dev/null
+++ b/src/zzjy/detail.config.ts
@@ -0,0 +1,4 @@
+export default definePageConfig({
+ navigationBarTitleText: '详情',
+ navigationBarBackgroundColor: '#ffe0e0'
+})
diff --git a/src/zzjy/detail.scss b/src/zzjy/detail.scss
new file mode 100644
index 0000000..2b461ff
--- /dev/null
+++ b/src/zzjy/detail.scss
@@ -0,0 +1,6 @@
+.content{
+ img{
+ box-shadow: 0 0 4px rgba(0, 0, 0, 0.1);
+ margin-bottom: 40px !important;
+}
+}
diff --git a/src/zzjy/detail.tsx b/src/zzjy/detail.tsx
new file mode 100644
index 0000000..5617037
--- /dev/null
+++ b/src/zzjy/detail.tsx
@@ -0,0 +1,50 @@
+import {useEffect, useState} from 'react'
+// import {Tag} from '@nutui/nutui-react-taro'
+import {useRouter} from '@tarojs/taro'
+import {Divider} from '@nutui/nutui-react-taro'
+import {CmsArticle} from "@/api/cms/cmsArticle/model"
+// import {Eye} from '@nutui/icons-react-taro'
+// 显示html富文本
+import {View, RichText} from '@tarojs/components'
+import {getCmsArticle} from "@/api/cms/cmsArticle";
+import './detail.scss';
+
+function Detail() {
+ const {params} = useRouter();
+ // 文章详情
+ const [item, setItem] = useState
()
+ // 浏览量
+ // const [views, setViews] = useState()
+
+ const reload = () => {
+ getCmsArticle(Number(params.id)).then(data => {
+ if (data) {
+ setItem(data)
+ // setViews(data.actualViews)
+ }
+ })
+ }
+
+ useEffect(() => {
+ reload();
+ }, []);
+
+ return (
+
+
{item?.title}
+ {/*
*/}
+ {/*
{item?.categoryName}*/}
+ {/*
{views}
*/}
+ {/*
*/}
+
+
+
+
+
+ )
+}
+
+export default Detail
diff --git a/src/zzjy/index.config.ts b/src/zzjy/index.config.ts
new file mode 100644
index 0000000..6a4ec55
--- /dev/null
+++ b/src/zzjy/index.config.ts
@@ -0,0 +1,5 @@
+export default definePageConfig({
+ navigationBarTitleText: '政治教育',
+ navigationBarBackgroundColor: '#d32f2f',
+ navigationBarTextStyle: 'white'
+})
diff --git a/src/zzjy/index.scss b/src/zzjy/index.scss
new file mode 100644
index 0000000..1345fe3
--- /dev/null
+++ b/src/zzjy/index.scss
@@ -0,0 +1,186 @@
+.veteran-page {
+ min-height: 100vh;
+ background: linear-gradient(135deg, #d32f2f 0%, #b71c1c 100%);
+
+ .hero-section {
+ position: relative;
+ padding: 40px 20px 60px;
+ background: linear-gradient(135deg, #d32f2f 0%, #b71c1c 100%);
+ overflow: hidden;
+
+ .hero-content {
+ position: relative;
+ z-index: 2;
+ text-align: center;
+
+ .hero-title {
+ font-size: 28px;
+ font-weight: bold;
+ color: #fff;
+ margin-bottom: 20px;
+ text-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
+ }
+
+ .hero-subtitle {
+ font-size: 14px;
+ line-height: 1.6;
+ color: rgba(255, 255, 255, 0.9);
+ margin: 0 auto;
+ max-width: 320px;
+ text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
+ }
+ }
+
+ .hero-decoration {
+ position: absolute;
+ top: 0;
+ right: 0;
+ width: 100%;
+ height: 100%;
+ pointer-events: none;
+
+ .decoration-circle {
+ position: absolute;
+ top: -50px;
+ right: -50px;
+ width: 150px;
+ height: 150px;
+ border: 2px solid rgba(255, 255, 255, 0.1);
+ border-radius: 50%;
+ animation: rotate 20s linear infinite;
+ }
+
+ .decoration-star {
+ position: absolute;
+ bottom: 20px;
+ right: 30px;
+ width: 0;
+ height: 0;
+ border-left: 15px solid transparent;
+ border-right: 15px solid transparent;
+ border-bottom: 10px solid rgba(255, 255, 255, 0.1);
+ transform: rotate(35deg);
+
+ &::before {
+ content: '';
+ position: absolute;
+ left: -15px;
+ top: 3px;
+ width: 0;
+ height: 0;
+ border-left: 15px solid transparent;
+ border-right: 15px solid transparent;
+ border-bottom: 10px solid rgba(255, 255, 255, 0.1);
+ transform: rotate(-70deg);
+ }
+ }
+ }
+ }
+
+ .veteran-list {
+ padding: 20px 15px;
+
+ .veteran-card {
+ background: #fff;
+ border-radius: 12px;
+ margin-bottom: 15px;
+ padding: 20px;
+ display: flex;
+ align-items: flex-start;
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
+ border: 2px solid #d32f2f;
+ transition: all 0.3s ease;
+ cursor: pointer;
+
+ &:hover {
+ transform: translateY(-2px);
+ box-shadow: 0 6px 20px rgba(0, 0, 0, 0.15);
+ }
+
+ .veteran-avatar {
+ flex-shrink: 0;
+ margin-right: 15px;
+
+ .avatar-img {
+ width: 60px;
+ height: 60px;
+ border-radius: 50%;
+ object-fit: cover;
+ border: 3px solid #d32f2f;
+ background: #f5f5f5;
+ }
+ }
+
+ .veteran-info {
+ flex: 1;
+
+ .veteran-name {
+ font-size: 18px;
+ font-weight: bold;
+ color: #d32f2f;
+ margin: 0 0 8px 0;
+ }
+
+ .veteran-description {
+ font-size: 13px;
+ line-height: 1.5;
+ color: #666;
+ text-align: justify;
+ }
+ }
+ }
+ }
+}
+
+@keyframes rotate {
+ from {
+ transform: rotate(0deg);
+ }
+ to {
+ transform: rotate(360deg);
+ }
+}
+
+/* 响应式设计 */
+@media (max-width: 375px) {
+ .veteran-page {
+ .hero-section {
+ padding: 30px 15px 50px;
+
+ .hero-content {
+ .hero-title {
+ font-size: 24px;
+ }
+
+ .hero-subtitle {
+ font-size: 13px;
+ }
+ }
+ }
+
+ .veteran-list {
+ padding: 15px 10px;
+
+ .veteran-card {
+ padding: 15px;
+
+ .veteran-avatar {
+ .avatar-img {
+ width: 50px;
+ height: 50px;
+ }
+ }
+
+ .veteran-info {
+ .veteran-name {
+ font-size: 16px;
+ }
+
+ .veteran-description {
+ font-size: 12px;
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/src/zzjy/index.tsx b/src/zzjy/index.tsx
new file mode 100644
index 0000000..011114b
--- /dev/null
+++ b/src/zzjy/index.tsx
@@ -0,0 +1,91 @@
+import {useEffect, useState} from "react";
+import {pageCmsArticle} from "@/api/cms/cmsArticle";
+import {CmsArticle} from "@/api/cms/cmsArticle/model";
+import Taro from '@tarojs/taro'
+import {useRouter} from '@tarojs/taro'
+import {Image,InfiniteLoading} from '@nutui/nutui-react-taro'
+import {getCmsNavigation} from "@/api/cms/cmsNavigation";
+import {CmsNavigation} from "@/api/cms/cmsNavigation/model";
+
+/**
+ * 文章终极列表
+ * @constructor
+ */
+const Index = () => {
+ const {params} = useRouter();
+ const [navigation, setNavigation] = useState()
+ const [list, setList] = useState([])
+
+ const reload = async () => {
+ // 获取栏目ID
+ const categoryId = Number(params.id);
+ // 当前栏目信息
+ const navs = await getCmsNavigation(categoryId);
+ // 终极新闻列表
+ const articles = await pageCmsArticle({categoryId,limit: 50});
+
+ // 当前栏目信息
+ if (navs) {
+ setNavigation(navs);
+ }
+ // 新闻列表
+ if (articles) {
+ setList(articles?.list || [])
+ }
+ }
+
+ useEffect(() => {
+ reload()
+ }, [])
+
+ return (
+
+
+
+
+
+
+ {
+ // 终极文章列表
+ list.map((item, index) => {
+ return (
+
Taro.navigateTo({url: `./detail?id=${item.articleId}`})}
+ >
+ {/* 图片容器 */}
+ {/*
*/}
+ {/*

*/}
+ {/*
*/}
+ {/* 标题 */}
+
+
+ )
+ })
+ }
+
+
+
+ )
+}
+export default Index