前端模拟辩论页面完成

main
chantouRichard 2 months ago
parent 2bee93f3be
commit 700e5370b7

@ -231,7 +231,7 @@ ai:
debate:
url: https://api.deepseek.com/chat/completions
headers:
header:
Authorization: "Bearer sk-53428f3b07ff426f8c11d988f649b5e7"
body:
message:

@ -1,2 +0,0 @@
# 主要配置在application.yml中
# 此文件用于避免IDE报错

@ -107,6 +107,7 @@ ai:
top_p: 1
tool_choice: "none"
logprobs: false
review:
url: https://api.deepseek.com/chat/completions
header:
@ -227,6 +228,137 @@ ai:
top_p: 1
tool_choice: "none"
logprobs: false
debate:
url: https://api.deepseek.com/chat/completions
header:
Authorization: "Bearer sk-53428f3b07ff426f8c11d988f649b5e7"
body:
message:
role-sys: system
content-sys: |
竞技辩论指导手册(简洁版)
现在假设你是一个专业的华语辩论辩手,你需要阅读下面的竞技辩论指导手册,学习如何坚守自己的立场,打出一场精彩的比赛。(注意,所有交锋环节,包括质询,接质,自由辩论你一次都只能输出一个问题的内容,模拟场上真实的比赛节奏)
一、基础准备
1. 理解辩题
- 先拆解核心概念(比如"语词平等"要明确指什么)
- 列出正反方可能的论点
- 准备2-3种定义方式预防定义战
2. 证据收集
- 每个论点配1-2个具体案例
- 找近年的学术研究(心理学/社会学优先)
- 准备可比数据(比如"实施前vs实施后"对比)
二、辩论策略
1. 立论结构
1. 定义关键概念
2. 论证必要性(为什么这问题重要)
3. 提出解决机制(具体怎么做)
4. 比较优势(比对方方案好在哪)
5. 价值升华(对社会/个人的意义)
2. 反驳技巧
- 直接反驳:指出对方逻辑漏洞
- 替代解释:提供其他可能性
- 削弱影响:证明对方论点不重要
三、实用话术
1. 定义争夺
"对方对XX的理解过于狭隘实际上应该包含..."
"这个定义在XX学者的研究中明确指..."
2. 数据质疑
"该研究样本量仅200人代表性不足"
"过去五年的新数据显示..."
3. 价值比较
"短期可能有效,但长期会导致..."
"解决了A问题却恶化了B问题"
四、常见错误避免
1. 逻辑问题
- 不偷换概念
- 不循环论证
- 不稻草人谬误(歪曲对方观点)
2. 表达问题
- 避免绝对化表述("绝对""永远"
- 复杂理论简单化解释
- 关键数据要说明来源
五、临场技巧
1. 质询要领
- 问题要封闭(让对方只能答是/否)
- 连续追问不超过3个
- 提前准备"杀手锏问题"
2. 自由辩论
- 30秒内完成一个论点
- 标记战场("关于XX问题我方认为..."
- 不纠缠细节,保持主线
六、经典辩论场景应对
1. 当对方说"现实做不到"
回应方向:
- 已有试点成功案例(举例)
- 技术/制度可行性分析
- 反问"那更好的解决方案是什么"
2. 当对方强调"特殊情况"
回应策略:
- 证明不具代表性
- 展示整体数据
- 指出例外不能否定原则
七、评委说服技巧
1. 专业评委
- 多引用学术研究
- 展示逻辑推导过程
- 使用专业术语
2. 大众评委
- 多讲生活案例
- 用比喻解释复杂概念
- 适当情感共鸣
八、自我检查清单
1. 每个论点是否有证据支持?
2. 反驳是否针对对方核心主张?
3. 价值主张是否清晰有力?
4. 时间分配是否合理?
九、备用锦囊
1. 万能案例库准备5个跨领域案例
2. 名人名言各领域3-5句
3. 紧急话术(当卡壳时:"这个问题需要分三个层面来看..."
十、赛后提升
1. 记录被反驳成功的论点
2. 收集新的证据材料
3. 优化表达方式(哪些话评委反应好)
[使用说明]
1. 比赛前通读"基础准备"和"策略"部分
2. 场上根据情况调用对应话术
3. 赛后完成"自我检查"和"提升"
总字数约3500字可根据需要增减
这份手册的特点:
1. 说人话,不装高深
2. 直接可用,不需要翻译
3. 重点突出实战技巧
4. 兼顾新手和老手需求
使用时只需要告诉我:
- 你的持方(正方/反方)
- 辩题类型(政策/价值/事实)
- 特别需求(如重点攻定义/数据)
role-user: user
model: deepseek-chat
frequency_penalty: 0
max_tokens: 2048
presence_penalty: 0
response_format: text
stream: false
temperature: 1
top_p: 1
tool_choice: "none"
logprobs: false
# JWT配置
jwt:
secret: yoursecretkey123456789abcdefghijklmnopqrstuvwxyz

@ -56,7 +56,12 @@ export default {
data() {
return {
input: "",
messages: [],
messages: [
{
role:"ai",
content:"哈喽~ 我是辩论助手,很高兴为你服务!请告诉我你想立论的立场和题目。"
}
],
scrollToView: "",
position: "",

@ -0,0 +1,317 @@
<template>
<view class="argument-component">
<view class="content-card">
<view class="card-title">辩论功能</view>
<view class="card-content">在这里可以和AI进行激烈的交流~</view>
</view>
<!-- 聊天展示区 -->
<scroll-view
class="chat-area"
scroll-y
:scroll-into-view="scrollToView"
scroll-with-animation
>
<view
v-for="(msg, index) in messages"
:key="index"
:id="'msg' + index"
class="chat-message"
:class="msg.role === 'user' ? 'from-user' : 'from-ai'"
>
<view class="bubble">
<block v-if="msg.loading">
<view class="dot-flashing"></view>
</block>
<block v-else>
{{ msg.content }}
</block>
</view>
</view>
</scroll-view>
<!-- 输入框与发送按钮 -->
<view class="chat-input">
<view class="input-group">
<textarea
class="textarea-box"
v-model="content"
placeholder="请输入辩论的过程"
auto-height
maxlength="1000"
/>
</view>
<button class="send-button" @click="sendMessage()"></button>
</view>
</view>
</template>
<script>
export default {
data() {
return {
input: "",
messages: [
{
role: "ai",
content: "在这里你可以和我进行辩论,现在,辩论开始!"
}
],
scrollToView: "",
content: "",
};
},
methods: {
async sendMessage() {
//
this.messages.push({
role: "user",
content: this.content,
});
this.scrollToBottom();
// AI loading
const aiIndex = this.messages.length;
this.messages.push({ role: "ai", content: "", loading: true });
this.scrollToBottom();
//
let history = this.messages
.slice(0, aiIndex) // loading
.filter((msg) => !msg.loading)
.map((msg) => {
if (msg.role === "user") {
return `用户:${msg.content}`;
} else if (msg.role === "ai") {
return `AI${msg.content}`;
}
return "";
})
.join("\n");
// AI
const reply = await this.callAI(history, this.content);
// loading AI
this.messages.splice(aiIndex, 1, { role: "ai", content: reply });
this.scrollToBottom();
},
async callAI(history, content) {
this.content = "";
return new Promise((resolve, reject) => {
console.log("callAI:", history, content);
uni.request({
url: "http://localhost:8080/api/ai/debate",
method: "POST",
header: {
"Content-Type": "application/json",
},
data: {
history: history,
content: content,
},
success: (res) => {
console.log("res:", res);
let reviewJson = JSON.parse(res.data.data.debate);
this.scrollToBottom();
if (res.statusCode === 200 && res.data.code === 200) {
resolve(
reviewJson.choices[0].message.content || "AI 没有返回有效内容"
);
} else {
reject("请求失败:" + (res.data.msg || "未知错误"));
}
},
fail: (err) => {
reject("请求失败:" + err.errMsg);
},
});
});
},
scrollToBottom() {
this.$nextTick(() => {
this.scrollToView = "msg" + (this.messages.length - 1);
});
},
},
};
</script>
<style scoped>
.argument-component {
width: 100%;
padding: 20rpx;
display: flex;
flex-direction: column;
height: 78vh;
background: linear-gradient(135deg, #2c3e50, #c6c333);
overflow-x: hidden; /* 禁止横向滚动 */
box-sizing: border-box; /* 避免 padding 导致溢出 */
}
.content-card {
background-color: rgba(255, 255, 255, 0.1);
border-radius: 20rpx;
padding: 30rpx;
width: 90%;
margin: 0 auto 30rpx;
backdrop-filter: blur(10px);
}
.card-title {
font-size: 36rpx;
color: #ffffff;
font-weight: bold;
margin-bottom: 20rpx;
}
.card-content {
font-size: 28rpx;
color: rgba(255, 255, 255, 0.8);
}
/* 聊天区域 */
.chat-area {
flex: 1;
width: 90%;
margin: 0 auto;
background-color: rgba(255, 255, 255, 0.05);
border-radius: 20rpx;
padding: 20rpx;
overflow-y: auto;
}
/* 消息通用样式 */
.chat-message {
display: flex;
margin-bottom: 20rpx;
}
/* 用户消息靠右 */
.from-user {
justify-content: flex-end;
}
/* AI消息靠左 */
.from-ai {
justify-content: flex-start;
}
/* 气泡样式 */
.bubble {
max-width: 70%;
padding: 20rpx;
border-radius: 20rpx;
font-size: 28rpx;
line-height: 1.6;
word-break: break-word;
}
/* 用户气泡颜色 */
.from-user .bubble {
background-color: #00c4ff;
color: white;
border-bottom-right-radius: 0;
}
/* AI气泡颜色 */
.from-ai .bubble {
background-color: #ffd54f;
color: #333;
border-bottom-left-radius: 0;
min-width: 80px;
}
/* 输入区域 */
.chat-input {
display: flex;
padding: 20rpx;
background-color: rgba(255, 255, 255, 0.05);
border-top: 1rpx solid #ccc;
align-items: flex-end;
}
.input-group {
flex: 1;
display: flex;
flex-direction: column;
gap: 10rpx;
}
.input-box {
background-color: #fff;
border-radius: 10rpx;
padding: 10rpx 20rpx;
margin-bottom: 20rpx;
font-size: 28rpx;
border: none;
}
.textarea-box {
background-color: #fff;
border-radius: 10rpx;
padding: 10rpx 20rpx;
font-size: 28rpx;
min-height: 80rpx;
border: none;
}
.send-button {
margin-left: 20rpx;
background-color: #00bcd4;
color: #fff;
border-radius: 10rpx;
padding: 20rpx;
font-size: 28rpx;
white-space: nowrap;
}
/* AI loading 动画 */
.dot-flashing {
width: 20rpx;
height: 20rpx;
border-radius: 50%;
background-color: #333;
animation: dotFlashing 1s infinite linear alternate;
position: relative;
margin-left: auto;
margin-right: auto;
}
.dot-flashing::before,
.dot-flashing::after {
content: "";
display: inline-block;
position: absolute;
top: 0;
width: 20rpx;
height: 20rpx;
border-radius: 50%;
background-color: #333;
}
.dot-flashing::before {
left: -30rpx;
animation: dotFlashing 1s infinite linear alternate;
animation-delay: 0.2s;
}
.dot-flashing::after {
left: 30rpx;
animation: dotFlashing 1s infinite linear alternate;
animation-delay: 0.4s;
}
@keyframes dotFlashing {
0% {
background-color: #333;
}
50%,
100% {
background-color: rgba(51, 51, 51, 0.3);
}
}
</style>

@ -38,6 +38,7 @@
v-model="content"
placeholder="请输入辩论的过程"
auto-height
maxlength="20000"
/>
</view>
<button class="send-button" @click="sendMessage()"></button>
@ -50,7 +51,13 @@ export default {
data() {
return {
input: "",
messages: [],
messages: [
{
role: "ai",
content:
"辩论过程复盘功能,可以帮你回顾和总结辩论过程中的关键点、亮点以及可能的改进之处。",
},
],
scrollToView: "",
content: "",
};
@ -89,11 +96,12 @@ export default {
"Content-Type": "application/json",
},
data: {
content: content
content: content,
},
success: (res) => {
console.log("res:", res);
let reviewJson = JSON.parse(res.data.data.review);
this.scrollToBottom();
if (res.statusCode === 200 && res.data.code === 200) {
resolve(
reviewJson.choices[0].message.content || "AI 没有返回有效内容"

@ -29,7 +29,7 @@ import { ref } from 'vue';
import PageOfHome from '../../components/HomeCom.vue';
import PageOfArgument from '../../components/ArgumentCom.vue';
import PageOfReview from '../../components/ReviewCom.vue';
// import PageOfDebate from '../../components/DebateCom.vue';
import PageOfDebate from '../../components/DebateCom.vue'
//
const currentComponent = ref('PageOfHome');

Loading…
Cancel
Save