This commit is contained in:
Ubuntu 2025-03-17 17:48:25 +08:00
parent 57baa24f38
commit 0df1343d6a
6 changed files with 186 additions and 12 deletions

29
Dockerfile Normal file
View File

@ -0,0 +1,29 @@
# Use official Node.js LTS image
FROM node:18-alpine
# Set working directory
WORKDIR /app
# Copy package files
COPY package*.json ./
# Install dependencies
RUN npm install
# Copy application files
COPY public/images ./public/images
COPY . .
# Expose the application port
EXPOSE 3000
# Set environment variables
ENV NODE_ENV=production
# Health check endpoint
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s \
CMD curl -f http://localhost:3000/ || exit 1
# Run the application
CMD ["node", "server.js"]

45
myrari/deployment.yaml Normal file
View File

@ -0,0 +1,45 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: myfari-app
namespace: farui
labels:
app: myfari
spec:
replicas: 3
selector:
matchLabels:
app: myfari
template:
metadata:
labels:
app: myfari
spec:
containers:
- name: myfari
image: localhost:32000/public/myfari:v03
ports:
- containerPort: 3000
env:
- name: NODE_ENV
value: "production"
resources:
requests:
cpu: "100m"
memory: "128Mi"
limits:
cpu: "500m"
memory: "512Mi"
livenessProbe:
httpGet:
path: /
port: 3000
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /ready
port: 3000
initialDelaySeconds: 5
periodSeconds: 5

16
myrari/service.yaml Normal file
View File

@ -0,0 +1,16 @@
apiVersion: v1
kind: Service
metadata:
name: myfari-service
namespace: farui
labels:
app: myfari
spec:
selector:
app: myfari
ports:
- protocol: TCP
port: 80
targetPort: 3000
type: ClusterIP

BIN
public/images/law.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View File

@ -3,8 +3,21 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Chat API</title> <title>我的通义法睿</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css" integrity="sha512-DTOQO9RWCH3ppGqcWaEA1BIZOC6xxalwEsw9c2QQeAIftl+Vegovlnee1c9QX4TctnWMn13TZye+giMm8e2LwA==" crossorigin="anonymous" referrerpolicy="no-referrer" /> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css" integrity="sha512-DTOQO9RWCH3ppGqcWaEA1BIZOC6xxalwEsw9c2QQeAIftl+Vegovlnee1c9QX4TctnWMn13TZye+giMm8e2LwA==" crossorigin="anonymous" referrerpolicy="no-referrer" />
<style>
.header-logo {
position: absolute;
top: 20px;
left: 20px;
width: 40px;
height: 40px;
z-index: 1000;
}
</style>
</head>
<body>
<img src="images/law.jpg" alt="Logo" class="header-logo">
<style> <style>
body { body {
font-family: Arial, sans-serif; font-family: Arial, sans-serif;
@ -13,6 +26,7 @@
height: 100vh; height: 100vh;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
position: relative;
} }
.chat-container { .chat-container {
flex: 1; flex: 1;
@ -41,6 +55,8 @@
background: #f5f5f5; background: #f5f5f5;
position: sticky; position: sticky;
bottom: 0; bottom: 0;
display: flex;
align-items: center;
} }
textarea { textarea {
width: calc(100% - 90px); width: calc(100% - 90px);
@ -49,18 +65,19 @@
border: 1px solid #ddd; border: 1px solid #ddd;
border-radius: 4px; border-radius: 4px;
resize: none; resize: none;
margin-right: 10px;
} }
button { button {
width: 40px; width: 20px;
height: 40px; height: 20px;
margin-left: 10px; margin: 10px;
background: #007bff; background: #007bff;
color: white; color: white;
border: none; border: none;
border-radius: 50%; border-radius: 50%;
cursor: pointer; cursor: pointer;
opacity: 0.7; opacity: 0.7;
transition: opacity 0.2s; transition: opacity 0.2s, background-color 0.2s;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
@ -68,28 +85,75 @@
button:hover { button:hover {
opacity: 1; opacity: 1;
} }
button i {
font-size: 10px;
}
button:disabled {
background: #cccccc;
cursor: not-allowed;
opacity: 0.7;
}
.message { .message {
max-width: 70%; width: 100%;
margin-bottom: 15px; margin-bottom: 35px;
padding: 10px; padding: 10px;
border-radius: 8px; border-radius: 8px;
position: relative; position: relative;
box-sizing: border-box;
}
.user-message {
text-align: right;
}
.user-message div {
font-weight: bold; /* 加粗 */
font-style: italic; /* 斜体 */
display: inline-block; /* 确保文本块行为正常 */
}
.bot-message {
text-align: left;
} }
.copy-btn { .copy-btn {
position: absolute; position: absolute;
right: 10px; right: 10px;
bottom: -20px; bottom: -20px;
width: 40px;
height: 40px;
background: none; background: none;
border: none; border: none;
cursor: pointer; cursor: pointer;
color: #007bff; color: #007bff;
font-size: 16px; font-size: 20px;
opacity: 0.7; opacity: 0.7;
transition: opacity 0.2s; transition: opacity 0.2s;
padding: 0; padding: 0;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
margin: 0;
}
.loading-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.3);
display: none;
justify-content: center;
align-items: center;
z-index: 1000;
}
.spinner {
width: 40px;
height: 40px;
border: 4px solid #f3f3f3;
border-top: 4px solid #007bff;
border-radius: 50%;
animation: spin 1s linear infinite;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
} }
</style> </style>
</head> </head>
@ -98,13 +162,15 @@
<div class="message-container" id="messageContainer"></div> <div class="message-container" id="messageContainer"></div>
<div class="input-container"> <div class="input-container">
<textarea id="messageInput" placeholder="请输入您的问题..."></textarea> <textarea id="messageInput" placeholder="请输入您的问题..."></textarea>
<button onclick="sendMessage()" title="发送"><i class="fas fa-paper-plane"></i></button> <button id="sendButton" onclick="sendMessage()" title="发送"><i class="fas fa-paper-plane"></i></button>
<button onclick="clearHistory()" style="margin-left: 10px; background-color: #ff4d4f;" title="清空历史"><i class="fas fa-trash-alt"></i></button> <button onclick="clearHistory()" style="background-color: #ff4d4f;" title="清空历史"><i class="fas fa-trash-alt"></i></button>
</div> </div>
</div> </div>
<div class="loading-overlay" id="loadingOverlay">
<div class="spinner"></div>
</div>
<script> <script>
// 维护对话历史
let conversationHistory = []; let conversationHistory = [];
function formatMarkdown(text) { function formatMarkdown(text) {
@ -119,12 +185,20 @@
async function sendMessage() { async function sendMessage() {
const message = document.getElementById('messageInput').value; const message = document.getElementById('messageInput').value;
const messageContainer = document.getElementById('messageContainer'); const messageContainer = document.getElementById('messageContainer');
const sendButton = document.getElementById('sendButton');
const loadingOverlay = document.getElementById('loadingOverlay');
if (!message) { if (!message) {
alert('请输入消息'); alert('请输入消息');
return; return;
} }
<<<<<<< HEAD
=======
loadingOverlay.style.display = 'flex';
sendButton.disabled = true;
>>>>>>> 19980d6 (update prompt)
const userMessageDiv = document.createElement('div'); const userMessageDiv = document.createElement('div');
userMessageDiv.className = 'message user-message'; userMessageDiv.className = 'message user-message';
userMessageDiv.innerHTML = ` userMessageDiv.innerHTML = `
@ -153,6 +227,10 @@
botMessageDiv.className = 'message bot-message'; botMessageDiv.className = 'message bot-message';
botMessageDiv.innerHTML = ` botMessageDiv.innerHTML = `
<div>${formattedText}</div> <div>${formattedText}</div>
<<<<<<< HEAD
=======
<button class="copy-btn" onclick="copyText(this)" title="复制"><i class="fas fa-copy"></i></button>
>>>>>>> 19980d6 (update prompt)
`; `;
messageContainer.appendChild(botMessageDiv); messageContainer.appendChild(botMessageDiv);
@ -169,6 +247,9 @@
errorMessageDiv.className = 'message bot-message'; errorMessageDiv.className = 'message bot-message';
errorMessageDiv.textContent = '网络错误,请检查连接'; errorMessageDiv.textContent = '网络错误,请检查连接';
messageContainer.appendChild(errorMessageDiv); messageContainer.appendChild(errorMessageDiv);
} finally {
loadingOverlay.style.display = 'none';
sendButton.disabled = false;
} }
document.getElementById('messageInput').value = ''; document.getElementById('messageInput').value = '';
@ -190,6 +271,9 @@
</script> </script>
</body> </body>
</html> </html>
<<<<<<< HEAD
=======
>>>>>>> 19980d6 (update prompt)

View File

@ -18,7 +18,7 @@ app.post('/api/chat', async (req, res) => {
// 构建消息数组,包含系统提示、历史对话和当前消息 // 构建消息数组,包含系统提示、历史对话和当前消息
const messages = [ const messages = [
{ role: "system", content: "You are a helpful assistant." }, { role: "system", content: "You are a senior legal expert and lawyer on domestic legal issues in mainland China. Provide clear, concise, and structured responses based on relevant laws and regulations. Use bullet points, numbered lists, or tables when appropriate. Cite cases from the case library when necessary." },
...(history || []), // 添加历史对话 ...(history || []), // 添加历史对话
{ role: "user", content: message } // 添加当前消息 { role: "user", content: message } // 添加当前消息
]; ];