当前位置: 首页 > news >正文

创新项目实训开发日志3

一、开发简介

核心工作内容:前端部分需求分析、前端部分页面设计、前端部分页面实现

工作时间:第八周

二、前端部分需求分析

  • 用户user

名称类型补充
idid
name默认差异处理
phone
passward
avatorurl
  • 对话dialog

名称类型补充
id
user_Id
name名称、默认从第一个提问中提取
  • 消息message

名称类型补充
id
dialog_id标明该消息属于哪个对话
sequence序号,便于得到对话记录
state标记模型回答还是客户提问
content内容
time提问时间
  • 收藏favority

名称类型补充
id
user_Id
message_id
time
  1. 注册
    1. 手机号
    2. 密码
    3. 密码二次确认
  2. 登录
    1. 手机号
    2. 密码
    3. 头像
  3. 重置密码
    1. 由于未开启验证码服务,且此功能并非该项目的核心业务,为了方便,直接重置为123456
  4. 新建对话记录
    1. 对话时间
    2. 用户提问
    3. 模型回答
    4. 对话记录
  5. 查询对话记录
    1. 记录最后一次对话时间
    2. 对话标题
    3. 对话记录
  6. 工具栏
    1. 打开抽屉
    2. 新建对话
    3. 点赞记录
  7. 重命名对话记录
    1. 对话标题
  8. 删除对话记录
  9. 提问模型
    1. 用户
    2. 时间
    3. 提问内容
  10. 模型

    1. 对话名称

    2. 回答

    3. 应答时间

  11. 复制、重新生成、点赞

三、前端部分页面设计

  • 登录界面

登录界面

  • 注册界面

  • 主页界面

  • 工具栏

  • 智能化问答

四、前端部分页面实现

  • 登录界面的实现

<!--* @FileDescription: 登录* @Author: Nevertheless* @Date: 2025.3.25* @LastEditors: Nevertheless* @LastEditTime: 2025.4.10--><script lang="ts" setup>
import { reactive, toRefs, ref } from 'vue'//头像
const state = reactive({circleUrl:'https://cloud-rise.oss-cn-shanghai.aliyuncs.com/001.jpg',
})
const { circleUrl } = toRefs(state)
//登录数据
const loginData = ref({phone: '',password: ''
})
//手机号
const validatePhone = (rule, value, callback) => {const phoneRegex = /^1[3456789]\d{9}$/;if (!value) {callback(new Error('Please input phone number'));} else if (!phoneRegex.test(value)) {callback(new Error('Phone number must be 11 digits'));} else {callback();}
}
//校验规则
const rules = {phone: [{ required: true, message: '请输入手机号', trigger: 'blur' },{ validator: validatePhone, message: '11位数字', trigger: 'blur' }],password: [{ required: true, message: '请输入密码', trigger: 'blur' },{ min: 5, max: 16, message: '长度为5~16位非空字符', trigger: 'blur' }]
}// //调用后台接口,完成登录
// import { loginService } from '../../api/user.js'
// import { ElMessage } from 'element-plus'
// import { useRouter } from 'vue-router'
// import { useTokenStore } from '../../stores/token.js'
// const router = useRouter()
// const tokenStore = useTokenStore();
// const login = async () => {
//     //registerData是一个响应式对象,如果要获取值,需要.value
//     let result = await loginService(loginData.value);
//     ElMessage.success(result.data.message ? result.data.message : '登录成功');
//     //把得到的token存储到pinia中
//     tokenStore.setToken(result.data.data);
//     //跳转到首页 路由完成跳转
//     router.push('/');
// }
</script><template><div id="background"><el-row id="login"><el-col :span="9" id="left"><div id="avatar"><el-avatar :size="150" :src="circleUrl" fit="cover" /></div><el-text id="WELCOME">WELCOME</el-text></el-col><el-col :span="15" id="right"><el-form ref="form" size="large" autocomplete="off" :model="loginData" :rules="rules"><el-form-item prop="phone" id="inputPhone"><!-- <el-input :prefix-icon="User" placeholder="请输入手机号" v-model="registerData.phone" class="rounded-input" input-styles="border-radius: 15px;"></el-input> --><input class="rounded-input" placeholder=" 手机号:" v-model="loginData.phone"></el-form-item><el-form-item prop="password" id="inputPassword"><!-- <el-input name="password" type="password" :prefix-icon="Lock" placeholder="请输入密码"v-model="registerData.password"></el-input> --><input type="password" class="rounded-input" placeholder=" 密  码:" v-model="loginData.password"></el-form-item><el-form-item class="flex"><div class="flex"><el-checkbox style="color: #FFFFFF;" class="myCheckBox">记住密码</el-checkbox><el-link :underline="false" style="color: #FFFFFF;">重置密码?</el-link></div></el-form-item><!-- 登录按钮 --><el-form-item id="loginButton"><el-button id="button1" @click="login">立 即 登 录</el-button></el-form-item></el-form></el-col></el-row></div>
</template><style scoped>
#background {height: 100vh;/*视图高度,1vh 是视口高度的 1%。*/width: 100%;background-image: url("@/assets/images/login_background.jpg");background-size: 100% 100%;/*宽,高(无需使用background-repeat: no-repeat;)*/}#login {height: 45%;width: 38%;position: absolute;top: 0;bottom: 10%;left: 45%;right: 0;margin: auto;background-color: rgba(127, 127, 127, 0.25);/*background:rgba(255,0,0,1);*/border-radius: 40px;border-color: #D9D9D9;border-style: solid;border-width: 5px;
}#left {border-right: 5px solid #D9D9D9;border-top-left-radius: 30px;border-bottom-left-radius: 25px;}#avatar {width: 100%;height: auto;margin-top: 25%;display: flex;justify-content: center;/*水平居中*/
}#WELCOME {font-size: 2rem;font-family: Tahoma,serif;color: #FFFFFF;margin-top: 25%;display: flex;justify-content: center;
}#inputPhone {width: 60%;height: 20%;margin-top: 20%;margin-left: 50%;transform: translateX(-50%);
}#inputPassword {width: 60%;margin-top: 10%;margin-left: 50%;transform: translateX(-50%);
}.rounded-input {width: 100%;height: 175%;border: none;border-radius: 40px;background-color: rgba(255, 255, 255, 0.7);color: rgb(127, 127, 127);text-align: center;
}.rounded-input:focus {outline: none;border: none;
}.flex {width: 120%;margin-top: 5%;margin-left: 50%;transform: translateX(-50%);display: flex;justify-content: space-between;
}#loginButton {width: 40%;height: 10%;margin-left: 50%;transform: translateX(-50%);
}#button1 {width: 100%;border: none;border-radius: 35px;background-color: rgba(51, 63, 80, 0.7);color: #FFFFFF;
}
</style>
<style>
.myCheckBox.is-bordered.is-checked {border-color: rgba(51, 63, 80, 0.7);
}.myCheckBox .el-checkbox__input.is-checked+.el-checkbox__label {color: rgba(51, 63, 80, 0.7);
}.myCheckBox .el-checkbox__input.is-checked .el-checkbox__inner,
.myRedCheckBox .el-checkbox__input.is-indeterminate .el-checkbox__inner {border-color: rgba(51, 63, 80, 0.7);background-color: rgba(51, 63, 80, 0.7);
}.myCheckBox .el-checkbox__input.is-focus .el-checkbox__inner {border-color: rgba(51, 63, 80, 0.7);
}
</style>
  • 布局

<!--* @FileDescription: 布局* @Author: Nevertheless* @Date: 2025.3.25* @LastEditors: Nevertheless* @LastEditTime: 2025.4.10--><script setup>
/**导入组件**/
import {CaretBottom, Crop, EditPen, SwitchButton, User} from '@element-plus/icons-vue'
import {useRouter} from 'vue-router'
import {ElMessage, ElMessageBox} from 'element-plus'/**导入函数**/
import {userInfoService} from '@/api/user.js'
import useUserInfoStore from '@/stores/userInfo.js'
import {useTokenStore} from '@/stores/token.js'
import DarkModeSlider from "@/components/DarkModeSlider.vue";/**初始化**/
const router = useRouter();
const tokenStore = useTokenStore();
const userInfoStore = useUserInfoStore();/**定义函数**///获取用户基本信息
const getUserInfo = async () => {//调用接口let result = await userInfoService();//数据存储到pinia中userInfoStore.setInfo(result.data.data);
}//处理命令
const handleCommand = (command) => {//判断指令if (command === 'logout') {//退出登录ElMessageBox.confirm('您确认要退出吗?','温馨提示',{confirmButtonText: '确认',cancelButtonText: '取消',type: 'warning',}).then(async () => {//退出登录//1.清空pinia中存储的token以及个人信息tokenStore.removeToken()userInfoStore.removeInfo()//2.跳转到登录页面router.push('/login')ElMessage({type: 'success',message: '退出登录成功',})}).catch(() => {ElMessage({type: 'info',message: '用户取消了退出登录',})})} else {//路由router.push('' + command)}
}/**页面初始化**/
getUserInfo();//进入页面获取用户基本信息
</script><template><!-- element-plus中的容器 --><el-container class="layout-container"><!-- 左侧菜单 --><el-aside width="200px"><div class="aside-first">logo+tool</div><el-menubackground-color="#232323"text-color="#fff"active-text-color="#ffd04b"default-active="1"router><!--用户管理--><el-sub-menu index="1"><template #title><el-icon><UserFilled/></el-icon><span>菜单一</span></template><el-menu-item index="/user/Info"><el-icon><User/></el-icon><span>子菜单一</span></el-menu-item></el-sub-menu><el-sub-menu index="2"><template #title><el-icon><UserFilled/></el-icon><span>菜单二</span></template><el-menu-item index="/user/Info"><el-icon><User/></el-icon><span>子菜单一</span></el-menu-item><el-menu-item index="/user/Info"><el-icon><User/></el-icon><span>子菜单二</span></el-menu-item></el-sub-menu></el-menu></el-aside><!-- 右侧主区域 --><el-container><!-- 头部区域 --><el-header><div>云起的管理员:<strong>{{ userInfoStore.info.username }}</strong></div><!-- 模式切换——浅色/深色 --><dark-mode-slider></dark-mode-slider><!-- 下拉菜单 --><!-- command: 条目被点击后会触发,在事件函数上可以声明一个参数,接收条目对应的指令 --><el-dropdown placement="bottom-end" @command="handleCommand"><span class="el-dropdown__box"><el-avatar :src="userInfoStore.info.avatarUrl?userInfoStore.info.avatarUrl:avatar"/><el-icon><CaretBottom/></el-icon></span><template #dropdown><el-dropdown-menu><el-dropdown-item command="/personal/Info" :icon="User">基本资料</el-dropdown-item><el-dropdown-item command="/personal/ChangeAvatar" :icon="Crop">更换头像</el-dropdown-item><el-dropdown-item command="/personal/ChangePassword" :icon="EditPen">重置密码</el-dropdown-item><el-dropdown-item command="logout" :icon="SwitchButton">退出登录</el-dropdown-item></el-dropdown-menu></template></el-dropdown></el-header><!-- 中间区域 --><el-main class="el-main"><router-view></router-view></el-main><!-- 底部区域 --><el-footer>基于Deepseek的408考研小助手</el-footer></el-container></el-container></template><style lang="scss" scoped>
.layout-container {height: 100vh;.el-aside {background-color: $global-background-color-contrast;//&__logo {//  height: 120px;//  background: url('@/images/logo.png') no-repeat center / 120px auto;//}.aside-first {@include hold(100, 10);background-color: #42b983;}.el-menu {border-right: none;//background-color: $global-background-color-contrast;//color: $global-font-color-contrast;////.sub-menu{//  background-color: $global-background-color-contrast;//  color: $global-font-color-contrast;//  .el-menu-item {//    background-color: $global-background-color-contrast;//    color: $global-font-color-contrast;//  }//  .el-menu-item.is-active {//    color: #6681FA;//    background-color: #EAEEFF;//  }//}//.sub-menu:hover{//  background-color: $global-background-color;//}}}.el-header {background-color: $global-background-color;display: flex;align-items: center;justify-content: space-between;.el-dropdown__box {display: flex;align-items: center;.el-icon {color: #999;margin-left: 10px;}&:active,&:focus {outline: none;}}}.el-main {background-color: $global-background-color;}.el-footer {display: flex;align-items: center;justify-content: center;font-size: 14px;color: #666;}
}
</style>
  • 卡片

<!--* @FileDescription: 主页* @Author: Nevertheless* @Date: 2025.4.3* @LastEditors: Nevertheless* @LastEditTime: 2025.4.10--><script setup>
import {testPostmanSever} from "@/api/test";
import DarkModeSlider from "@/components/DarkModeSlider.vue";/*** @description: 测试Postman的后端是否能正常运行* @return void*/
const testPostmanSeverFunction = async () => {let result = await testPostmanSever();console.log(result)
}testPostmanSeverFunction()
</script><template><el-card class="card">这是一个卡片</el-card>
</template><style lang="scss" scoped>
.card {@include content-center-flex;@include hold(99, 99);@include position-center-box("column,row");background-color: $global-background-color;color: $global-font-color;
}
</style>

http://www.xdnf.cn/news/70813.html

相关文章:

  • 深度剖析d3dx9_42.dll错误:从原理到解决d3dx9_42.dll丢失方案
  • 总结设计测试用例的万能公式
  • 企业微信-自建应用
  • opencv 对图片的操作
  • c++学习之---vector
  • 华为认证HCIE考试费用总结
  • 平均精确度(Average Precision, AP)和均值平均精确度(Mean Average Precision, mAP)的区别和联系浅析
  • Spring MVC 一个简单的多文件上传
  • element-ui中的上传组件el-upload非自动上传监听不到success
  • 每天一道面试题@第一天
  • 12.QT-Combo Box|Spin Box|模拟点餐|从文件中加载选项|调整点餐份数(C++)
  • 【数据结构入门训练DAY-19】总结数据结构中的栈
  • 柔和的风光人像静物摄影Lr调色教程,手机滤镜PS+Lightroom预设下载!
  • LX2-编译及下载程序
  • shardingsphere启动报mode错误
  • 软考中级数据库系统工程师学习资料分享
  • 控制系统的结构和关键指标
  • 02_Flask是什么?
  • 【大模型】Browser-Use AI驱动的浏览器自动化工具
  • ORB-SLAM_地图点优化_固定位姿_g2o定义_雅可比矩阵推导
  • Vscode开发STM32标准库
  • 实践项目开发-hbmV4V20250407-项目架构设计
  • 多线程累加探索思考
  • 在统信UOS 1060上实现自动关机
  • Java并发:资源共享
  • 在CSDN的1095天(创作纪念日)
  • ECMAScript
  • 网络结构及安全科普
  • 【MySQL】表的约束(主键、唯一键、外键等约束类型详解)、表的设计
  • 前端工程化:构建高质量 Web 项目的现代方法论