初始化项目

This commit is contained in:
zhihao
2025-12-11 15:37:54 +08:00
parent f9988ae675
commit 5d85ddfa83
28 changed files with 2102 additions and 9 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,3 @@
{
"usingComponents": {}
}

View File

@@ -0,0 +1,167 @@
<!--顶部栏-->
<view class="top-bar " >
<view class="user-info " style="flex: 4; display: flex;justify-content: flex-start;">
<view class="avatar-box " style="margin-left:10rpx;">
<button open-type="chooseAvatar" bindchooseavatar="onAvatar" style="margin: 0; padding: 0;height: 32px;width:90%; ">
<image src="{{avatarUrl}}" style="height: 30px;width: 30px;" />
</button>
</view>
<text style="color: dimgrey; margin-left:5rpx;">{{weChatName}}</text>
</view>
<view style="flex: 4; display: flex;justify-content: flex-end;">
<scroll-view scroll-x class=" nav text-center">
<view class="cu-item {{TabCur==1?'text-blue curline':''}}" bindtap="tabSelect" data-id="{{1}}">
全部信息
</view >
<view class="cu-item {{TabCur==2?'text-blue curline':''}}" bindtap="tabSelect" data-id="{{2}}">
公开信息
</view >
<view class="cu-item {{TabCur==3?'text-blue curline':''}}" bindtap="tabSelect" data-id="{{3}}">
个人信息
</view >
</scroll-view>
</view>
</view>
<!--消息区-->
<scroll-view class="msg-area"
id="myScroll"
scroll-y
refresher-enabled
refresher-threshold="80"
refresher-default-style="none"
refresher-triggered="{{triggered}}"
bindrefresherpulling="onPulling"
bindrefresherrefresh="onRefresh"
bindrefresherrestore="onRestore"
scroll-into-view="{{toView}}" style="height: {{scrollHeight}}px;">
<view class="refresh" style="height: 70rpx; width: 100%;text-align: center;" wx:if="{{pulling}}">
<!-- <image class="refresh-icon" src="/assets/refresh.png" animation="{{rotateAni}}" /> -->
<text>{{ pullText }}</text>
</view>
<block wx:for="{{msgList}}" wx:key="id">
<!-- 日期分隔条 -->
<!-- 修改消息展示,添加状态图标 -->
<view class="msg-item {{item.isSelf === 1 ? 'self' : ''}} {{item.isSelf === 2 ? 'self1' : ''}}" id="msg-{{index}}">
<view class="bubble" id="{{item.id}}" bindlongpress="handleLongPressmsg">
<view style=" text-align:{{item.isSelf === 1 ? 'right' :item.isSelf === 2 ? 'right' : 'left'}} ;">
<image wx:if="{{item.lock=='Unlock'}}" src="/images/unlock_blue.png" style=" width:16rpx;height:16rpx;margin-left: 10rpx;" ></image>
<image wx:else src="/images/lock_r.png" style=" width:16rpx;height:16rpx;margin-left: 10rpx;" ></image>
<image wx:if="{{item.sendMethod=='voice'}}" src="/images/Voice.png" style=" width:25rpx;height:25rpx;margin-left: 10rpx;" ></image>
<image wx:else src="/images/Keyboard.png" style=" width:25rpx;height:25rpx;margin-left: 10rpx;" ></image>
<text class="time">({{!item.voicetime? 0:item.voicetime}} s)</text>
<text class="time">{{item.time}}</text>
</view>
<text id="{{item.id}}" bindlongpress="handleLongPressmsg">{{item.content}}</text>
<text wx:if="{{item.status === 'sending'}}" class="msg-status">发送中...</text>
<text wx:elif="{{item.status === 'failed'}}" class="msg-status error" bindtap="retryMessage" data-id="{{item.id}}">发送失败,点击重发</text>
</view>
</view>
</block>
</scroll-view>
<!-- 实时语音转文字显示区域 -->
<view class="recording-toast" wx:if="{{(recording || recording1) }}">
<view class="recording-text">
<text wx:if="{{resultText}}">{{resultText}}</text>
<text wx:else style="color: beige;">正在转换中...</text>
</view>
</view>
<!--底部输入栏-->
<view class="input-bar" id="BottomFrame">
<!-- 语音/键盘切换 -->
<button class="switch-btn" style="width: 65rpx; height: 80%;display: flex; flex-direction:column; justify-content: center; " bindtap="switchInputMode">
<!-- <text style="line-height: 100%; " wx:if="{{!voiceMode}}"> 🎤 </text>
<text style="top: 25%;" wx:else>⌨</text> -->
<image wx:if="{{!voiceMode}}" src="/images/Keyboard.png" style=" width: 60rpx;height:60rpx;" ></image>
<image wx:else src="/images/Voice.png" style=" width: 60rpx;height:60rpx;" ></image>
</button>
<!-- 文字模式 -->
<view wx:if="{{!voiceMode}}" class="text-row">
<view class="input-box" style="border: 1rpx solid #ddd;">
<textarea class="textarea" maxlength="-1" confirm-type="search" bindinput="qonInput" value="{{qinputTxt}}" placeholder="输入消息" />
</view>
<view style="width: 20%;">
<button class="send-btn" style="width:100%;background-color:#ADD8E6;color: black;" bindtap="gsendText">
<text>个人发送</text>
</button>
<button class="send-btn" style="width: 100%; background-color: #95ec69;color: black;" bindtap="qsendText">
<text>公开发送</text>
</button>
</view>
</view>
<!-- 语音模式 -->
<view wx:else class="voice-row">
<view class="voice-btn-group" style="height: 100%; " >
<button
class="voice-record-btn {{recording1?'recording':''}} {{cancelSend1?'cancel':''}}"
catchtouchstart="handleTouchStart1"
catchtouchmove="handleTouchMove1"
catchtouchend="handleTouchEnd1"
catchtouchcancel="handleTouchCancel1"
style="width: 45%;height: 100%;display: flex; flex-direction:column; justify-content: center;background-color:#ADD8E6;color: black;"
>
<text style="font-size: 15px;font-weight: bold;"> {{recording1?(cancelSend1?'松开手指,取消发送':'松开 结束'):'按住说话\n个人消息'}}</text>
</button>
<button
class="voice-record-btn {{recording?'recording':''}} {{cancelSend?'cancel':''}}"
catchtouchstart="handleTouchStart"
catchtouchmove="handleTouchMove"
catchtouchend="handleTouchEnd"
catchtouchcancel="handleTouchCancel"
style="width: 45%;height: 100%;display: flex; flex-direction:column; justify-content: center;background-color: #95ec69;color: black; "
>
<text style="font-size: 15px;font-weight: bold;"> {{recording?(cancelSend?'松开手指,取消发送':'松开 结束'):'按住说话\n公开消息'}}</text>
</button>
</view>
</view>
</view>
<view class="cu-modal {{modalName=='DialogModal1'?'show':''}}" >
<view class="cu-dialog" style="top: {{isFocused ? '2vh':'30vh'}};">
<view class="cu-bar bg-white justify-end">
<view class="content">修改信息</view>
</view>
<!-- <input class="solids cu-btn1" focus="true" bindinput="inputSearchForHotels" confirm-type="search" style="width: 100%;"/> -->
<textarea class="Btextarea" maxlength="-1" confirm-type="search" auto-height bindinput="inputSearchForHotels" style="width: 100%;" bindfocus="onTextareaFocus"
bindblur="onTextareaBlur" value="{{inputValue}}" />
<view class="cu-bar bg-white justify-end">
<view class="action">
<button id="Withdrawal" class="cu-btn line-green text-red" bindtap="hideModal">撤回</button>
<button id="no" class="cu-btn line-green text-green" bindtap="hideModal">取消</button>
<button id="ok" class="cu-btn bg-green margin-left" bindtap="hideModal">确定</button>
</view>
</view>
</view>
</view>

View File

@@ -0,0 +1,408 @@
page{background:#ededed;}
.top-bar{
height:88rpx;
line-height:88rpx;
text-align:center;
color :#000;
background:#f0f5f5;
font-size:34rpx;
display: flex;
}
.msg-area{
position:fixed;
top:88rpx;
bottom:20rpx;
left:0;
right:0;
padding:20rpx;
box-sizing:border-box;
}
.date-bar{
text-align:center;
font-size:24rpx;
color:#888;
background:#e5e5e5;
line-height:44rpx;
border-radius:22rpx;
margin:20rpx auto;
padding:0 20rpx;
display:inline-block;
}
.msg-item{
display:flex;
flex-direction:column;
margin-bottom:20rpx;
}
.msg-item.self{
align-items:flex-end;
}
.msg-item.self1{
align-items:flex-end;
}
.bubble{
max-width:70%;
padding: 0rpx 20rpx 12rpx 20rpx;
border-radius:12rpx;
background:#fff;
font-size:32rpx;
}
.msg-item.self .bubble{
background:#95ec69;
}
.msg-item.self1 .bubble{
background:#ADD8E6;
}
.time{
font-size:24rpx;
color:#888;
margin-top:8rpx;
margin-left:10rpx;
}
/* 底部整体 */
.input-bar{
position: fixed;
bottom: 0;
left: 0;
right: 0;
height: 180rpx;
background: #fff;
display: flex;
align-items: center;
padding: 0 20rpx;
border-top: 1rpx solid #e0e0e0;
}
/* 语音/键盘切换 */
.switch-btn{
width: 36rpx; /* 微信同宽 */
height: 76rpx;
line-height: 76rpx;
background: #f5f5f5;
border-radius: 12rpx;
margin-right: 16rpx;
padding: 0;
font-size: 40rpx;
flex-shrink: 0; /* 防止被挤压 */
flex: 1;
align-items: center;
justify-content: center;
}
/* 文字模式容器 */
.text-row{
flex: 9;
display: flex;
align-items: center;
}
/* 输入框:占满剩余空间 */
.input-box{
flex: 4;
height: 150rpx;
background: #f5f5f5;
border-radius: 18rpx;
padding: 6 6rpx;
margin-right: 16rpx;
margin: 8rpx;
}
/* 发送按钮:固定 76 rpx */
.send-btn{
width: 36rpx;
height: 70rpx;
line-height: 76rpx;
padding: 0;
background: #07c160;
color: #fff;
font-size: 26rpx;
border-radius: 12rpx;
flex-shrink: 0;
flex: 1;
margin: 8rpx;
}
/* 语音模式大按钮 */
.voice-row{
flex: 9;
height: 80%;
align-items: center;
justify-content: center;
}
.voice-record-btn{
font-size: 20rpx;
width: 50%;
height: 100%;
/* flex: 1; */
/*
height: 76rpx;
line-height: 76rpx;
border-radius: 12rpx;
background: #f5f5f5;
padding: 0 12rpx;
white-space: pre-line;
transition: background .15s; */
}
.voice-record-btn.recording{
background: #FF3B30;
color: #fff;
}
.voice-record-btn.cancel{
background: #FF3B30;
color: #fff;
}
.voice-btn-group{
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
width: 100%;
gap: 1rpx; /* 两按钮间距 10 rpx */
}
.nav {
white-space: nowrap;
}
.nav .cu-item {
height: 90%;
display: inline-block;
line-height: 90rpx;
margin: 0 10rpx;
padding: 0 5rpx;
font-size: 26rpx;
}
.text-center {
text-align: center;
}
.text-blue {
color: #007aff;
}
.curline {
border-bottom: 10rpx solid #007aff; /* 蓝色,粗细 5rpx */
}
/* 实时语音转文字显示区域 */
.recording-toast {
position: fixed;
top: 50%;
left: 50%;
/* height: 50rpx; */
width: 100vw;
transform: translate(-30%, -30%);
background-color: rgba(0, 0, 0, 0.7);
padding: 30rpx;
border-radius: 16rpx;
z-index: 1000;
/* max-width: 80%;
min-width: 300rpx; */
max-height: 50vh;
min-height: 50rpx;
display: flex;
justify-content: center;
align-items: center;
}
/* 添加消息状态样式 */
.msg-status {
font-size: 24rpx;
margin-left: 10rpx;
}
.msg-status.error {
color: #ff3b30;
}
.recording-text {
color: #fff;
font-size: 34rpx;
text-align: center;
line-height: 1.4;
word-wrap: break-word;
word-break: break-all;
}
/* 实时语音转文字显示区域 */
.recording-toast {
position: fixed;
top: 40%;
left: 50%;
transform: translate(-50%, -50%);
background-color: rgba(0, 0, 0, 0.7);
padding: 30rpx;
border-radius: 16rpx;
z-index: 1000;
max-width: 80%;
min-width: 300rpx;
display: flex;
justify-content: center;
align-items: center;
}
.recording-text {
color: #fff;
font-size: 34rpx;
text-align: center;
line-height: 1.4;
word-wrap: break-word;
word-break: break-all;
}
.cu-modal {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 1110;
opacity: 0;
outline: 0;
text-align: center;
-ms-transform: scale(1);
transform: scale(1);
backface-visibility: hidden;
perspective: 2000rpx;
background: rgba(0, 0, 0, 0.6);
transition: all 0.3s ease-in-out 0s;
pointer-events: none;
}
.cu-modal::before {
content: "\200B";
display: inline-block;
/* height: 100%; */
vertical-align: middle;
}
.cu-modal.show {
opacity: 1;
transition-duration: 0.3s;
-ms-transform: scale(1);
transform: scale(1);
overflow-x: hidden;
overflow-y: auto;
pointer-events: auto;
}
.user-info {
display: flex;
align-items: center;
}
.cu-dialog {
position: relative;
display: inline-block;
vertical-align: middle;
margin-left: auto;
margin-right: auto;
width: 680rpx;
max-width: 100%;
background-color: #f8f8f8;
border-radius: 10rpx;
overflow: hidden;
}
.cu-modal.bottom-modal::before {
vertical-align: bottom;
}
.cu-modal.bottom-modal .cu-dialog {
width: 100%;
border-radius: 0;
}
.cu-modal.bottom-modal {
margin-bottom: -1000rpx;
}
.cu-modal.bottom-modal.show {
margin-bottom: 0;
}
.bg-white {
background-color: #ffffff;
color: #666666;
}
.justify-end {
justify-content: flex-end;
}
.justify-between {
justify-content: space-between;
}
.cu-bar .action {
display: flex;
align-items: center;
height: 100%;
justify-content: center;
max-width: 100%;
}
.cu-bar .content {
position: absolute;
text-align: center;
width: calc(100% - 340rpx);
left: 0;
right: 0;
bottom: 0;
top: 0;
margin: auto;
height: 60rpx;
font-size: 32rpx;
line-height: 60rpx;
cursor: none;
pointer-events: none;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
.cu-bar {
display: flex;
position: relative;
align-items: center;
min-height: 100rpx;
justify-content: space-between;
}
.cu-bar .action {
display: flex;
align-items: center;
height: 100%;
justify-content: center;
max-width: 100%;
}
.text-red,
.line-red,
.lines-red {
color: #ff3b30;
}
.cu-bar .action>text[class*="cuIcon-"],
.cu-bar .action>view[class*="cuIcon-"] {
font-size: 36rpx;
}
[class*="cuIcon-"] {
font-family: "cuIcon";
font-size: inherit;
font-style: normal;
}
.cuIcon-close:before {
content: "\e646";
}
.textarea {
width: 100%;
height: 150rpx;
padding: 10rpx;
box-sizing: border-box; /* 确保内边距不影响总宽度 */
word-wrap: break-word; /* 确保长内容也能换行 */
/*border: 1rpx solid #ddd; 可选,添加边框 */
border-radius: 8rpx; /* 可选,圆角 */
}
.Btextarea {
width: 100%;
height: 150rpx;
padding: 10rpx;
box-sizing: border-box; /* 确保内边距不影响总宽度 */
word-wrap: break-word; /* 确保长内容也能换行 */
border: 1rpx solid #ddd; /*可选,添加边框 */
border-radius: 8rpx; /* 可选,圆角 */
}

View File

@@ -0,0 +1,30 @@
/**
* 本地历史消息 Mock
* 字段与真实接口保持一致,方便后续直接替换
*/
module.exports = [
{
id: 1,
content: '你好,这是本地历史消息!',
date: '2025-10-31',
time: '2025-10-31 10:30',
isSelf: 2,
showDate: true
},
{
id: 2,
content: '收到,准备替换为接口数据~',
date: '2025-10-31',
time: '2025-10-31 10:32',
isSelf: 1,
showDate: false
},
{
id: 3,
content: '跨天消息示例',
date: '2025-11-01',
time: '2025-11-01 09:00',
isSelf: 2,
showDate: true
}
]

View File

@@ -1,6 +1,6 @@
import { authorizeBatch } from '../../utils/authorize'
const util = require('../../utils/util.js')
const app = getApp()
Page({
data: {
isAgree: false,
@@ -8,7 +8,6 @@ Page({
showAuthModal: false,
userInfo: null,
needReg: false,
openid: '',
avatarUrl: '/images/Blvlogo.png',
nickName: '',
form: {
@@ -17,6 +16,14 @@ Page({
}
},
onLoad() {
const isAgree = wx.getStorageSync('isAgree');
if (typeof isAgree !== 'undefined'){
this.setData({ isAgree:isAgree });
}
this.handleLogin()
},
onAvatar(e) {
@@ -61,13 +68,18 @@ Page({
UserKey: openid,
WeChatName:nickName,
PhoneNumber:form.phone,
AvatarUrl:avatarUrl
AvatarUrl:""
},
success: res =>{
if (res.data.success && res.data.data.userName && res.data.data.weChatName && res.data.data.phoneNumber) {
this.uploadAvatarToServer(avatarUrl,res.data.data.userKey)
if (res.data.success && res.data.data.userName && res.data.data.weChatName && res.data.data.phoneNumber) {
wx.setStorageSync('openid', res.data.data.userKey);
this.setData({openid:res.data.data.userKey});
this.setData({openid:res.data.data.userKey});
app.globalData.userKey=res.data.data.userKey
app.globalData.weChatName=res.data.data.weChatName
app.globalData.avatarUrl=this.data.avatarUrl
wx.navigateTo({url: '/pages/chat/chat'});
}
else{
@@ -99,6 +111,8 @@ Page({
console.log(e)
this.setData({ isAgree: e.detail.value.length > 0 });
wx.setStorageSync('isAgree', this.data.isAgree);
},
openContract() {
@@ -134,6 +148,7 @@ Page({
//////////debugger
// 保存到全局
getApp().globalData.userInfo = userInfo;
await this.onGetAuth()
// 继续登录流程
await this.completeLogin();
@@ -162,7 +177,40 @@ async onGetAuth() {
})
}
},
uploadAvatarToServer(tempFilePath,userKey) {
// 显示加载提示,提升用户体验
wx.showLoading({ title: '上传中...' });
wx.uploadFile({
url: 'https://wx-xcx-check.blv-oa.com:4433/api/Check/UploadFile', // 你的服务器上传接口
filePath: tempFilePath,
name: 'file', // 与后端约定的文件参数名
formData: {
'rootPathType': 'Avatar', // 指定保存到 wwwroot/Avatar 目录
'userKey': userKey // 指定要更新头像的用户
},
success: (res) => {
wx.hideLoading();
const data = JSON.parse(res.data); // 注意: uploadFile返回的data是字符串需解析
if (data.success) {
// 上传成功,拿到服务器返回的永久链接
const permanentUrl = data.url;
this.setData({
avatarUrl: permanentUrl // 更新为永久链接
});
// 接下来可以将 permanentUrl 保存到本地缓存或发送给后端更新用户信息
wx.showToast({ title: '上传成功' });
} else {
wx.showToast({ title: '上传失败: ' + data.message, icon: 'none' });
}
},
fail: (err) => {
wx.hideLoading();
console.error('上传接口调用失败', err);
wx.showToast({ title: '网络错误', icon: 'none' });
}
});
},
// 完整的登录流程
async completeLogin() {
@@ -190,14 +238,20 @@ async completeLogin() {
success: res =>{
wx.hideLoading()
if (res.data.success){
this.setData({openid: res.data.data.userKey});
console.log(this.data.openid)
wx.setStorageSync('openid', res.data.data.userKey);
app.globalData.userKey=res.data.data.userKey
app.globalData.weChatName=res.data.data.weChatName
app.globalData.avatarUrl=res.data.data.avatarUrl
}
if (res.data.success && res.data.data.userName && res.data.data.weChatName && res.data.data.phoneNumber) {
wx.navigateTo({url: '/pages/chat/chat'});
}
else{
wx.showToast({
title: `登录失败: 用户未注册。请先填写完整信息再进行登录`,

View File

@@ -112,7 +112,7 @@ page {
.tip {
margin-top: 8rpx;
font-size: 24rpx;
font-size: 28rpx;
color: #888;
}
/* wxss */