初始化
10
.hbuilderx/launch.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"version" : "1.0",
|
||||
"configurations" : [
|
||||
{
|
||||
"customPlaygroundType" : "device",
|
||||
"playground" : "standard",
|
||||
"type" : "uni-app:app-android"
|
||||
}
|
||||
]
|
||||
}
|
17
App.vue
Normal file
@@ -0,0 +1,17 @@
|
||||
<script>
|
||||
export default {
|
||||
onLaunch: function() {
|
||||
console.log('App Launch')
|
||||
},
|
||||
onShow: function() {
|
||||
console.log('App Show')
|
||||
},
|
||||
onHide: function() {
|
||||
console.log('App Hide')
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
/*每个页面公共css */
|
||||
</style>
|
20
index.html
Normal file
@@ -0,0 +1,20 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<script>
|
||||
var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') ||
|
||||
CSS.supports('top: constant(a)'))
|
||||
document.write(
|
||||
'<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' +
|
||||
(coverSupport ? ', viewport-fit=cover' : '') + '" />')
|
||||
</script>
|
||||
<title></title>
|
||||
<!--preload-links-->
|
||||
<!--app-context-->
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"><!--app-html--></div>
|
||||
<script type="module" src="/main.js"></script>
|
||||
</body>
|
||||
</html>
|
24
main.js
Normal file
@@ -0,0 +1,24 @@
|
||||
import App from './App'
|
||||
|
||||
// #ifndef VUE3
|
||||
import Vue from 'vue'
|
||||
import './uni.promisify.adaptor'
|
||||
Vue.config.productionTip = false
|
||||
App.mpType = 'app'
|
||||
const app = new Vue({
|
||||
...App
|
||||
})
|
||||
app.$mount()
|
||||
// #endif
|
||||
|
||||
// #ifdef VUE3
|
||||
import {
|
||||
createSSRApp
|
||||
} from 'vue'
|
||||
export function createApp() {
|
||||
const app = createSSRApp(App)
|
||||
return {
|
||||
app
|
||||
}
|
||||
}
|
||||
// #endif
|
72
manifest.json
Normal file
@@ -0,0 +1,72 @@
|
||||
{
|
||||
"name" : "AIchat",
|
||||
"appid" : "",
|
||||
"description" : "",
|
||||
"versionName" : "1.0.0",
|
||||
"versionCode" : "100",
|
||||
"transformPx" : false,
|
||||
/* 5+App特有相关 */
|
||||
"app-plus" : {
|
||||
"usingComponents" : true,
|
||||
"nvueStyleCompiler" : "uni-app",
|
||||
"compilerVersion" : 3,
|
||||
"splashscreen" : {
|
||||
"alwaysShowBeforeRender" : true,
|
||||
"waiting" : true,
|
||||
"autoclose" : true,
|
||||
"delay" : 0
|
||||
},
|
||||
/* 模块配置 */
|
||||
"modules" : {},
|
||||
/* 应用发布信息 */
|
||||
"distribute" : {
|
||||
/* android打包配置 */
|
||||
"android" : {
|
||||
"permissions" : [
|
||||
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
|
||||
"<uses-permission android:name=\"android.permission.VIBRATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
|
||||
"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
|
||||
"<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
|
||||
"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.CAMERA\"/>",
|
||||
"<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
|
||||
"<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
|
||||
"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
|
||||
"<uses-feature android:name=\"android.hardware.camera\"/>",
|
||||
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
|
||||
]
|
||||
},
|
||||
/* ios打包配置 */
|
||||
"ios" : {},
|
||||
/* SDK配置 */
|
||||
"sdkConfigs" : {}
|
||||
}
|
||||
},
|
||||
/* 快应用特有相关 */
|
||||
"quickapp" : {},
|
||||
/* 小程序特有相关 */
|
||||
"mp-weixin" : {
|
||||
"appid" : "",
|
||||
"setting" : {
|
||||
"urlCheck" : false
|
||||
},
|
||||
"usingComponents" : true
|
||||
},
|
||||
"mp-alipay" : {
|
||||
"usingComponents" : true
|
||||
},
|
||||
"mp-baidu" : {
|
||||
"usingComponents" : true
|
||||
},
|
||||
"mp-toutiao" : {
|
||||
"usingComponents" : true
|
||||
},
|
||||
"uniStatistics" : {
|
||||
"enable" : false
|
||||
},
|
||||
"vueVersion" : "3"
|
||||
}
|
13
pages.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"pages": [{
|
||||
"path": "pages/chat/chat",
|
||||
"navigationBarTitleText": "AI辅导员" // 直接设置为页面配置对象的属性
|
||||
}],
|
||||
"globalStyle": {
|
||||
"navigationBarTextStyle": "black",
|
||||
"navigationBarTitleText": "智水AI辅导员",
|
||||
"navigationBarBackgroundColor": "#fff",
|
||||
"backgroundColor": "#F8F8F8"
|
||||
},
|
||||
"uniIdRouter": {}
|
||||
}
|
237
pages/chat/chat.vue
Normal file
@@ -0,0 +1,237 @@
|
||||
<template>
|
||||
<view class="chat-container">
|
||||
<!-- 消息列表 -->
|
||||
<!-- :style="{ height: messageListHeight + 'px' }" -->
|
||||
<scroll-view scroll-y class="message-list">
|
||||
<block v-for="(item, index) in messages" :key="index">
|
||||
<view :class="['message-item', item.sender === 'user' ? 'user-message' : 'ai-message']">
|
||||
<image class="avatar" :src="item.avatar"></image>
|
||||
<view class="message-content">
|
||||
{{ item.content }}
|
||||
<view v-if="item.sender === 'ai'" class="ai-hint">
|
||||
<text class="quote-icon">▌▌引用来源:{{ item.source }}</text>
|
||||
<view class="ai-actions">
|
||||
<text class="ai-text">回答由AI生成</text>
|
||||
<view class="icon-group">
|
||||
<img src="/static/voice.svg" class="button-icon" />
|
||||
<img src="/static/good.svg" class="button-icon" />
|
||||
<img src="/static/tread.svg" class="button-icon" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</block>
|
||||
</scroll-view>
|
||||
|
||||
<!-- 输入框和发送按钮 -->
|
||||
<view class="input-container">
|
||||
<input type="text" v-model="inputMessage" placeholder="输入消息..." @confirm="sendMessage"
|
||||
confirm-type="send" />
|
||||
<img src="/static/send.png" class="btn-icon" @click="sendMessage" />
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
inputMessage: '',
|
||||
messages: [],
|
||||
messageListHeight: 0 // 动态计算消息列表高度
|
||||
};
|
||||
},
|
||||
onLoad() {
|
||||
const systemInfo = uni.getSystemInfoSync();
|
||||
// 修改这里:计算消息列表高度时减去输入框的高度(假设输入框高度为60px)
|
||||
this.messageListHeight = systemInfo.windowHeight - 60;
|
||||
this.initConversation();
|
||||
},
|
||||
methods: {
|
||||
initConversation() {
|
||||
// 初始化对话,添加第一条AI消息
|
||||
this.messages.push({
|
||||
sender: 'ai',
|
||||
avatar: '/static/AI.png',
|
||||
content: '你好!我是你的 AI 助手,有什么我可以帮你的吗?',
|
||||
isAI: true // 标记为 AI 回复
|
||||
});
|
||||
},
|
||||
sendMessage() {
|
||||
if (this.inputMessage.trim() === '') return;
|
||||
|
||||
// 添加用户消息
|
||||
this.messages.push({
|
||||
sender: 'user',
|
||||
avatar: '/static/yonghu.png',
|
||||
content: this.inputMessage
|
||||
});
|
||||
|
||||
// 清空输入框
|
||||
this.inputMessage = '';
|
||||
|
||||
// 模拟AI回复
|
||||
setTimeout(() => {
|
||||
this.messages.push({
|
||||
sender: 'ai',
|
||||
avatar: '/static/AI.png',
|
||||
content: '根据最新数据显示,消费市场正在逐步恢复,线上零售增长显著。特别是在数字化服务、智能设备和健康产品领域,消费需求持续上升。建议关注这些领域的投资机会。',
|
||||
source: '123123123'
|
||||
});
|
||||
}, 1000);
|
||||
},
|
||||
|
||||
handleVoiceClick() {
|
||||
// 实现语音功能的逻辑
|
||||
},
|
||||
handleThumbUpClick() {
|
||||
// 实现点赞功能的逻辑
|
||||
},
|
||||
handleThumbDownClick() {
|
||||
// 实现踩功能的逻辑
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.chat-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
.message-list {
|
||||
height: 90vh;
|
||||
flex: 1;
|
||||
padding: 10px;
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
.message-item {
|
||||
margin-bottom: 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
/* height: 95vh; */
|
||||
}
|
||||
|
||||
.user-message {
|
||||
flex-direction: row-reverse;
|
||||
/* 反转子元素的排列顺序 */
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
.ai-message {
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: 50%;
|
||||
margin-left: 10px;
|
||||
/* 调整头像与消息内容的间距 */
|
||||
}
|
||||
|
||||
.message-content {
|
||||
max-width: 70%;
|
||||
padding: 10px;
|
||||
border-radius: 10px;
|
||||
background-color: #fff;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.user-message .message-content {
|
||||
background-color: #007aff;
|
||||
color: #fff;
|
||||
margin-left: 10px;
|
||||
/* 添加左侧间距 */
|
||||
}
|
||||
|
||||
.input-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 10px;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 -2px 5px rgba(0, 0, 0, 0.1);
|
||||
position: fixed;
|
||||
width: 95%;
|
||||
height: 40px;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: 10;
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
input {
|
||||
flex: 1;
|
||||
padding: 10px;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 20px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
button {
|
||||
padding: 0 20px;
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
background-color: #007aff;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.btn-icon {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
/* AI 提示语样式 */
|
||||
.ai-hint {
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
.source-quote {
|
||||
font-size: 12px;
|
||||
color: #666;
|
||||
margin-top: 5px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.quote-icon {
|
||||
font-weight: bold;
|
||||
margin-right: 5px;
|
||||
background: #f5f5f5;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.ai-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
/* 文字靠左,图标靠右 */
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
.ai-text {
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
margin-right: 10px;
|
||||
/* 文字和图标之间留点空隙 */
|
||||
}
|
||||
|
||||
.button-icon {
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
margin-left: 8px;
|
||||
/* 图标之间的小间距 */
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.icon-group {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
BIN
static/AI.png
Normal file
After Width: | Height: | Size: 1.1 MiB |
1
static/good.svg
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1753693561642" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="11887" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M64 483.04V872c0 37.216 30.144 67.36 67.36 67.36H192V416.32l-60.64-0.64A67.36 67.36 0 0 0 64 483.04zM857.28 344.992l-267.808 1.696c12.576-44.256 18.944-83.584 18.944-118.208 0-78.56-68.832-155.488-137.568-145.504-60.608 8.8-67.264 61.184-67.264 126.816v59.264c0 76.064-63.84 140.864-137.856 148L256 416.96v522.4h527.552a102.72 102.72 0 0 0 100.928-83.584l73.728-388.96a102.72 102.72 0 0 0-100.928-121.824z" p-id="11888" fill="#4F46E5"></path></svg>
|
After Width: | Height: | Size: 782 B |
BIN
static/logo.png
Normal file
After Width: | Height: | Size: 3.9 KiB |
BIN
static/send.png
Normal file
After Width: | Height: | Size: 3.5 KiB |
1
static/tread.svg
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1753693581732" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="13840" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M611.188364 651.962182h226.56a93.090909 93.090909 0 0 0 91.834181-108.334546l-61.905454-372.689454A93.090909 93.090909 0 0 0 775.889455 93.090909H372.968727v558.871273c82.152727 81.338182 72.866909 210.571636 88.832 242.338909 15.941818 31.767273 47.616 36.119273 55.621818 36.608 39.703273 0 179.665455-32.395636 93.789091-278.946909zM313.832727 651.636364V93.090909H202.891636a93.090909 93.090909 0 0 0-92.997818 88.901818l-16.709818 372.363637A93.090909 93.090909 0 0 0 186.181818 651.636364h127.650909z" fill="#4F46E5" p-id="13841"></path></svg>
|
After Width: | Height: | Size: 883 B |
1
static/voice.svg
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1753693546032" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="9939" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M216.064 418.816c-50.176 0-91.136 40.96-91.136 91.136s40.96 91.136 91.136 91.136 91.136-40.96 91.136-91.136-40.96-91.136-91.136-91.136zM415.232 815.104c-21.504 0-42.496-8.704-57.344-25.6-27.648-31.744-24.064-79.36 7.168-107.52 50.176-43.52 78.848-106.496 78.848-172.032 0-64.512-27.648-125.952-75.776-168.96-31.232-28.16-33.792-76.288-5.632-107.52s76.288-33.792 107.52-5.632c79.36 71.68 125.44 174.592 125.44 281.6 0 109.568-47.616 214.016-130.56 286.208-14.336 13.312-31.744 19.456-49.664 19.456z" p-id="9940" fill="#4F46E5"></path><path d="M601.088 985.088c-30.208-29.184-31.232-77.312-2.048-107.52 95.744-99.328 148.48-229.888 148.48-367.616 0-136.192-51.2-265.216-144.896-364.544-28.672-30.72-27.648-78.848 3.072-107.52s78.848-27.648 107.52 3.072c120.32 126.976 186.368 293.888 186.368 468.48 0 177.664-67.584 345.6-190.464 473.088-14.848 15.36-35.328 23.04-54.784 23.04-19.456 1.024-38.4-6.144-53.248-20.48z" p-id="9941" fill="#4F46E5"></path></svg>
|
After Width: | Height: | Size: 1.3 KiB |
BIN
static/yonghu.png
Normal file
After Width: | Height: | Size: 37 KiB |
13
uni.promisify.adaptor.js
Normal file
@@ -0,0 +1,13 @@
|
||||
uni.addInterceptor({
|
||||
returnValue (res) {
|
||||
if (!(!!res && (typeof res === "object" || typeof res === "function") && typeof res.then === "function")) {
|
||||
return res;
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
res.then((res) => {
|
||||
if (!res) return resolve(res)
|
||||
return res[0] ? reject(res[0]) : resolve(res[1])
|
||||
});
|
||||
});
|
||||
},
|
||||
});
|
76
uni.scss
Normal file
@@ -0,0 +1,76 @@
|
||||
/**
|
||||
* 这里是uni-app内置的常用样式变量
|
||||
*
|
||||
* uni-app 官方扩展插件及插件市场(https://ext.dcloud.net.cn)上很多三方插件均使用了这些样式变量
|
||||
* 如果你是插件开发者,建议你使用scss预处理,并在插件代码中直接使用这些变量(无需 import 这个文件),方便用户通过搭积木的方式开发整体风格一致的App
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* 如果你是App开发者(插件使用者),你可以通过修改这些变量来定制自己的插件主题,实现自定义主题功能
|
||||
*
|
||||
* 如果你的项目同样使用了scss预处理,你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件
|
||||
*/
|
||||
|
||||
/* 颜色变量 */
|
||||
|
||||
/* 行为相关颜色 */
|
||||
$uni-color-primary: #007aff;
|
||||
$uni-color-success: #4cd964;
|
||||
$uni-color-warning: #f0ad4e;
|
||||
$uni-color-error: #dd524d;
|
||||
|
||||
/* 文字基本颜色 */
|
||||
$uni-text-color:#333;//基本色
|
||||
$uni-text-color-inverse:#fff;//反色
|
||||
$uni-text-color-grey:#999;//辅助灰色,如加载更多的提示信息
|
||||
$uni-text-color-placeholder: #808080;
|
||||
$uni-text-color-disable:#c0c0c0;
|
||||
|
||||
/* 背景颜色 */
|
||||
$uni-bg-color:#ffffff;
|
||||
$uni-bg-color-grey:#f8f8f8;
|
||||
$uni-bg-color-hover:#f1f1f1;//点击状态颜色
|
||||
$uni-bg-color-mask:rgba(0, 0, 0, 0.4);//遮罩颜色
|
||||
|
||||
/* 边框颜色 */
|
||||
$uni-border-color:#c8c7cc;
|
||||
|
||||
/* 尺寸变量 */
|
||||
|
||||
/* 文字尺寸 */
|
||||
$uni-font-size-sm:12px;
|
||||
$uni-font-size-base:14px;
|
||||
$uni-font-size-lg:16px;
|
||||
|
||||
/* 图片尺寸 */
|
||||
$uni-img-size-sm:20px;
|
||||
$uni-img-size-base:26px;
|
||||
$uni-img-size-lg:40px;
|
||||
|
||||
/* Border Radius */
|
||||
$uni-border-radius-sm: 2px;
|
||||
$uni-border-radius-base: 3px;
|
||||
$uni-border-radius-lg: 6px;
|
||||
$uni-border-radius-circle: 50%;
|
||||
|
||||
/* 水平间距 */
|
||||
$uni-spacing-row-sm: 5px;
|
||||
$uni-spacing-row-base: 10px;
|
||||
$uni-spacing-row-lg: 15px;
|
||||
|
||||
/* 垂直间距 */
|
||||
$uni-spacing-col-sm: 4px;
|
||||
$uni-spacing-col-base: 8px;
|
||||
$uni-spacing-col-lg: 12px;
|
||||
|
||||
/* 透明度 */
|
||||
$uni-opacity-disabled: 0.3; // 组件禁用态的透明度
|
||||
|
||||
/* 文章场景相关 */
|
||||
$uni-color-title: #2C405A; // 文章标题颜色
|
||||
$uni-font-size-title:20px;
|
||||
$uni-color-subtitle: #555555; // 二级标题颜色
|
||||
$uni-font-size-subtitle:26px;
|
||||
$uni-color-paragraph: #3F536E; // 文章段落颜色
|
||||
$uni-font-size-paragraph:15px;
|
8
unpackage/dist/cache/.vite/deps/_metadata.json
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"hash": "a7f0eada",
|
||||
"configHash": "54ac4d7d",
|
||||
"lockfileHash": "e3b0c442",
|
||||
"browserHash": "cc30fbe7",
|
||||
"optimized": {},
|
||||
"chunks": {}
|
||||
}
|
3
unpackage/dist/cache/.vite/deps/package.json
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"type": "module"
|
||||
}
|