| @@ -4,7 +4,8 @@ | |||
| "pages/logs/logs", | |||
| "pages/payOrder/payOrder", | |||
| "pages/payHistory/payHistory", | |||
| "pages/chat/chat" | |||
| "pages/chat/chat", | |||
| "pages/orderDetail/orderDetail" | |||
| ], | |||
| "window": { | |||
| "backgroundTextStyle": "light", | |||
| @@ -1,4 +1,4 @@ | |||
| // pages/chat/chat.ts | |||
| import { scrollToID } from '../../utils/util' | |||
| Page({ | |||
| /** | |||
| @@ -9,7 +9,7 @@ Page({ | |||
| message: "", | |||
| waitingMessage: "", | |||
| isResponing: false, | |||
| reLoadSocket: false, | |||
| chatOver: false, | |||
| messageFlag: true | |||
| }, | |||
| @@ -113,7 +113,7 @@ Page({ | |||
| success: function (res) { | |||
| console.log(res) | |||
| if (!that.data.reLoadSocket) { | |||
| that.sayHello('Hello,我是GPT-Agent,你可以和我聊天,😘😘😘(出现这条消息,则WebSocket连接已成功)') | |||
| that.sayHello('Hello,我是小闲聊,你可以和我聊天,😘😘😘') | |||
| } | |||
| if (that.data.waitingMessage) { | |||
| @@ -35,7 +35,7 @@ page { | |||
| position: absolute; | |||
| top: 0; | |||
| left: -25rpx; | |||
| height: 100rpx; | |||
| height: 80rpx; | |||
| border-radius: 50% 50%; | |||
| &.isResponing { | |||
| @@ -50,7 +50,7 @@ page { | |||
| text-align: left; | |||
| &.left { | |||
| left: 100rpx; | |||
| left: 80rpx; | |||
| color: #000000; | |||
| background-color: #ffffff; | |||
| padding: 20rpx; | |||
| @@ -58,7 +58,7 @@ page { | |||
| } | |||
| &.right { | |||
| right: 100rpx; | |||
| right: 80rpx; | |||
| color: #ffffff; | |||
| background-color: #07c160; | |||
| padding: 20rpx; | |||
| @@ -70,11 +70,21 @@ page { | |||
| position: absolute; | |||
| top: 0; | |||
| right: -25rpx; | |||
| height: 100rpx; | |||
| height: 80rpx; | |||
| border-radius: 50% 50%; | |||
| } | |||
| } | |||
| } | |||
| .over { | |||
| width: 170rpx; | |||
| font-size: 23rpx; | |||
| border-radius: 12rpx; | |||
| background-color: #0000001c; | |||
| padding: 10rpx 0; | |||
| text-align: center; | |||
| margin: 0 auto; | |||
| } | |||
| } | |||
| .chatBox { | |||
| @@ -86,21 +96,25 @@ page { | |||
| padding-top: 20rpx; | |||
| background-color: #f5f5f5; | |||
| .inputBox { | |||
| display: inline-block; | |||
| width: 500rpx; | |||
| height: 60rpx; | |||
| border-radius: 10rpx; | |||
| margin-right: 15rpx; | |||
| padding-left: 10rpx; | |||
| background-color: #ffffff; | |||
| } | |||
| .boxOutside { | |||
| margin-bottom: 20rpx; | |||
| .inputBox { | |||
| display: inline-block; | |||
| width: 500rpx; | |||
| height: 60rpx; | |||
| border-radius: 10rpx; | |||
| margin-right: 15rpx; | |||
| padding-left: 10rpx; | |||
| background-color: #ffffff; | |||
| } | |||
| .sendBtn { | |||
| display: inline-block; | |||
| width: 150rpx; | |||
| height: 60rpx; | |||
| line-height: 50rpx; | |||
| padding: 5rpx 0; | |||
| .sendBtn { | |||
| display: inline-block; | |||
| width: 150rpx; | |||
| height: 60rpx; | |||
| line-height: 50rpx; | |||
| padding: 5rpx 0; | |||
| } | |||
| } | |||
| } | |||
| @@ -2,14 +2,17 @@ | |||
| <view class="content"> | |||
| <view class="chatItem" wx:for="{{chatList}}" wx:key="index"> | |||
| <view class="{{item.id == 1 ? 'chatContent right' : 'chatContent left'}}"> | |||
| <image class="{{isResponing ? 'chatGpt isResponing' : 'chatGpt'}}" wx:if="{{!item.id}}" src="../../asset/icon/chatGpt.png" mode="heightFix" /> | |||
| <image class="{{isResponing ? 'chatGpt isResponing' : 'chatGpt'}}" wx:if="{{!item.id}}" src="../../asset/icon/tiny-Chat-rotate.png" mode="heightFix" /> | |||
| <text class="{{item.id == 1 ? 'message right' : 'message left'}}">{{item.message}}</text> | |||
| <image class="userAvatar" wx:if="{{item.id && item.id == 1}}" src="../../asset/icon/user.png" mode="heightFix" /> | |||
| </view> | |||
| </view> | |||
| <view class='over' wx:if="{{reLoadSocket}}">聊天已结束</view> | |||
| </view> | |||
| <view class="chatBox"> | |||
| <input class="inputBox" type="text" bindinput="input" value="{{message}}" /> | |||
| <button class="sendBtn" type="primary" bindtap="send">发送</button> | |||
| <view class="boxOutside"> | |||
| <input class="inputBox" type="text" bindinput="input" value="{{message}}" /> | |||
| <button class="sendBtn" type="primary" bindtap="send">发送</button> | |||
| </view> | |||
| </view> | |||
| @@ -15,9 +15,9 @@ | |||
| .introduction { | |||
| width: 600rpx; | |||
| height: 900rpx; | |||
| height: 830rpx; | |||
| margin: 50rpx auto; | |||
| padding-top: 20rpx; | |||
| padding: 0 20rpx; | |||
| border: 1px dashed #747474; | |||
| border-radius: 60rpx; | |||
| @@ -25,43 +25,47 @@ | |||
| text-align: center; | |||
| font-size: 45rpx; | |||
| color: #585858; | |||
| margin-bottom: 0rpx; | |||
| margin-bottom: 10rpx; | |||
| margin-top: 20rpx; | |||
| } | |||
| .contain { | |||
| width: 500rpx; | |||
| height: 600rpx; | |||
| height: 520rpx; | |||
| font-size: 30rpx; | |||
| color: #585858; | |||
| text-indent: 1cm; | |||
| margin: auto; | |||
| margin: 0 auto; | |||
| padding: 20rpx; | |||
| font-family: Verdana, Geneva, Tahoma, sans-serif; | |||
| } | |||
| .chatGptICon { | |||
| position: relative; | |||
| text-align: center; | |||
| image { | |||
| position: absolute; | |||
| left: 50%; | |||
| top: 50%; | |||
| transform: translate(-50%, 50%); | |||
| width: 80rpx; | |||
| } | |||
| } | |||
| .notice { | |||
| text-indent: 44rpx; | |||
| font-size: 22rpx; | |||
| color: #929292; | |||
| padding: 0 50rpx; | |||
| margin-top: 80rpx; | |||
| margin-top: 20rpx; | |||
| } | |||
| } | |||
| .tinyChatICon { | |||
| position: relative; | |||
| top: -85rpx; | |||
| text-align: center; | |||
| image { | |||
| position: absolute; | |||
| left: 50%; | |||
| transform: translate(-50%, 50%); | |||
| width: 100rpx; | |||
| } | |||
| } | |||
| .buttons { | |||
| font-size: 25rpx; | |||
| margin-top: 150rpx; | |||
| .userPhone { | |||
| text-align: center; | |||
| margin-bottom: 15rpx; | |||
| @@ -1,27 +1,23 @@ | |||
| <!--index.wxml--> | |||
| <view class="content"> | |||
| <view class="logo"> | |||
| 𝑮𝑷𝑻-𝑨𝒈𝒆𝒏𝒕 | |||
| 𝑺𝒎𝒂𝒓𝒕-𝑪𝒉𝒂𝒕 | |||
| </view> | |||
| <view class="introduction"> | |||
| <view class="title">欢迎使用𝑮𝑷𝑻</view> | |||
| <view class="title">欢迎使用小闲聊</view> | |||
| <view class="contain"> | |||
| <view> | |||
| ChatGPT是一个基于大规模预训练语言模型的对话系统,由OpenAI开发。 | |||
| "小闲聊"是一款基于人工智能技术开发的智能聊天机器人应用,用户可以通过文字聊天方式与机器人进行交互。该小程序不仅可以与用户进行简单的闲聊,还可以通过学习用户的行为和偏好,提供个性化的推荐服务。例如,如果用户喜欢科技内容,"小闲聊"可以根据用户的兴趣爱好,为用户推荐相关的科技内容。总之,"小闲聊"是一款功能全面、交互便捷、智能化的聊天小程序,让用户可以随时随地与机器人或好友进行交流,获得各种信息和娱乐。 | |||
| </view> | |||
| <view> | |||
| 它的核心技术是GPT模型,英文全称为(Generative Pre-trained Transformer)是一种基于深度学习的自然语言处理技术。GPT模型采用Transformer架构,利用无监督学习从大规模语料库中学习语言知识,具有强大的语言理解和生成能力。 | |||
| </view> | |||
| <view> | |||
| ChatGPT将GPT模型应用于对话生成,可以进行自然流畅的对话,具有人类般的语言交互能力。 | |||
| </view> | |||
| <view class="chatGptICon"> | |||
| <image src="../../asset/icon/chatGpt.png" mode="widthFix" /> | |||
| </view> | |||
| <view class="notice">严格遵守国家法律法规,自觉遵守中国互联网协会《文明上网自律公约》,不发布危害国家安全、违反法律法规、影响社会和谐稳定的有害信息</view> | |||
| </view> | |||
| <view class="notice">严格遵守国家法律法规,自觉遵守中国互联网协会《文明上网自律公约》,不发布危害国家安全、违反法律法规、影响社会和谐稳定的有害信息</view> | |||
| </view> | |||
| <view class="tinyChatICon"> | |||
| <image src="../../asset/icon/tiny-Chat.png" mode="widthFix" /> | |||
| </view> | |||
| <view class="buttons"> | |||
| <block wx:if="{{!userInfo.phone}}"> | |||
| <button type="primary" open-type="getPhoneNumber" bindgetphonenumber="getUserPhone">申请使用</button> | |||
| @@ -44,4 +40,5 @@ | |||
| <button type="primary" bindtap="goToBuy">购买会员</button> | |||
| </block> | |||
| </view> | |||
| </view> | |||
| @@ -0,0 +1,70 @@ | |||
| // pages/orderDetail/orderDetail.ts | |||
| Page({ | |||
| /** | |||
| * 页面的初始数据 | |||
| */ | |||
| data: { | |||
| detail: null | |||
| }, | |||
| /** | |||
| * 生命周期函数--监听页面加载 | |||
| */ | |||
| onLoad(option) { | |||
| if (option.detail && typeof option.detail == 'string') { | |||
| this.setData({ | |||
| detail: JSON.parse(option.detail) | |||
| }) | |||
| } | |||
| }, | |||
| /** | |||
| * 生命周期函数--监听页面初次渲染完成 | |||
| */ | |||
| onReady() { | |||
| }, | |||
| /** | |||
| * 生命周期函数--监听页面显示 | |||
| */ | |||
| onShow() { | |||
| }, | |||
| /** | |||
| * 生命周期函数--监听页面隐藏 | |||
| */ | |||
| onHide() { | |||
| }, | |||
| /** | |||
| * 生命周期函数--监听页面卸载 | |||
| */ | |||
| onUnload() { | |||
| }, | |||
| /** | |||
| * 页面相关事件处理函数--监听用户下拉动作 | |||
| */ | |||
| onPullDownRefresh() { | |||
| }, | |||
| /** | |||
| * 页面上拉触底事件的处理函数 | |||
| */ | |||
| onReachBottom() { | |||
| }, | |||
| /** | |||
| * 用户点击右上角分享 | |||
| */ | |||
| onShareAppMessage() { | |||
| } | |||
| }) | |||
| @@ -0,0 +1,4 @@ | |||
| { | |||
| "navigationBarTitleText": "订单详情", | |||
| "usingComponents": {} | |||
| } | |||
| @@ -0,0 +1,33 @@ | |||
| page { | |||
| background-color: #f4f5f9; | |||
| font-size: 28rpx; | |||
| } | |||
| .detail { | |||
| padding: 40rpx; | |||
| background-color: #fff; | |||
| border-radius: 20rpx; | |||
| font-weight: 600; | |||
| view { | |||
| margin-bottom: 50rpx; | |||
| color: #a5a5a5; | |||
| } | |||
| .flex { | |||
| display: flex; | |||
| justify-content: space-between; | |||
| } | |||
| .black { | |||
| color: #000; | |||
| } | |||
| .green { | |||
| color: #07c160; | |||
| } | |||
| .red { | |||
| color: #ff0000; | |||
| } | |||
| } | |||
| @@ -0,0 +1,32 @@ | |||
| <!--pages/orderDetail/orderDetail.wxml--> | |||
| <view style="padding: 30rpx;"> | |||
| <view class="detail"> | |||
| <view> | |||
| 用户手机号:<text class="black">{{detail.cUserPhone}}</text> | |||
| </view> | |||
| <view> | |||
| 支付金额:<text class="black">{{detail.payAmount / 100}} 元</text> | |||
| </view> | |||
| <view> | |||
| 支付时间:<text class="black">{{detail.payTime}}</text> | |||
| </view> | |||
| <view> | |||
| 创建时间:<text class="black">{{detail.createTime}}</text> | |||
| </view> | |||
| <view> | |||
| 更新时间:<text class="black">{{detail.updateTime}}</text> | |||
| </view> | |||
| <view> | |||
| 生效开始时间:<text class="green">{{detail.validStartTime}}</text> | |||
| </view> | |||
| <view> | |||
| 生效结束时间:<text class="red">{{detail.validEndTime}}</text> | |||
| </view> | |||
| <view> | |||
| 备注:<text class="black">{{detail.remark}}</text> | |||
| </view> | |||
| <view> | |||
| 订单号:<text class="black">{{detail.transactionId}}</text> | |||
| </view> | |||
| </view> | |||
| </view> | |||
| @@ -1,5 +1,6 @@ | |||
| const app = getApp() | |||
| import request from '../../utils/request' | |||
| import { timestampToTime } from '../../utils/util' | |||
| Page({ | |||
| @@ -18,6 +19,13 @@ Page({ | |||
| this.getPayOrderList(1) | |||
| }, | |||
| goCheckDetail(e) { | |||
| const item = JSON.stringify(e.currentTarget.dataset.item) | |||
| wx.navigateTo({ | |||
| url: `/pages/orderDetail/orderDetail?detail=${item}`, | |||
| }) | |||
| }, | |||
| getPayOrderList(pageNum) { | |||
| const that = this | |||
| request.get({ | |||
| @@ -27,11 +35,28 @@ Page({ | |||
| pageSize: 10 | |||
| } | |||
| }).then(res => { | |||
| wx.stopPullDownRefresh() | |||
| wx.hideLoading() | |||
| console.log(res, 'getPayOrderList'); | |||
| res.data.list.forEach(item => { | |||
| item.payTime = timestampToTime(item.payTime, 'YYYY-MM-DD hh:mm:ss') | |||
| item.validStartTime = timestampToTime(item.validStartTime, 'YYYY-MM-DD hh:mm:ss') | |||
| item.validEndTime = timestampToTime(item.validEndTime, 'YYYY-MM-DD hh:mm:ss') | |||
| item.createTime = timestampToTime(item.createTime, 'YYYY-MM-DD hh:mm:ss') | |||
| item.updateTime = timestampToTime(item.updateTime, 'YYYY-MM-DD hh:mm:ss') | |||
| }) | |||
| if (res.data.list && res.data.list.length > 0) { | |||
| that.setData({ | |||
| orderList: res.data.list | |||
| }) | |||
| if (pageNum == 1) { | |||
| const tempArr = res.data.list | |||
| that.setData({ | |||
| orderList: res.data.list | |||
| }) | |||
| } else { | |||
| const tempArr = that.data.orderList | |||
| that.setData({ | |||
| orderList: tempArr | |||
| }) | |||
| } | |||
| } | |||
| }).catch(err => { | |||
| console.log(err, 'err'); | |||
| @@ -70,14 +95,20 @@ Page({ | |||
| * 页面相关事件处理函数--监听用户下拉动作 | |||
| */ | |||
| onPullDownRefresh() { | |||
| wx.showLoading() | |||
| this.getPayOrderList(1) | |||
| }, | |||
| /** | |||
| * 页面上拉触底事件的处理函数 | |||
| */ | |||
| onReachBottom() { | |||
| const that = this; | |||
| that.data.pageNum++; | |||
| that.setData({ | |||
| pageNum: that.data.pageNum | |||
| }); | |||
| that.getPayOrderList(that.data.pageNum); | |||
| }, | |||
| /** | |||
| @@ -1,4 +1,5 @@ | |||
| { | |||
| "navigationBarTitleText": "购买历史", | |||
| "usingComponents": {} | |||
| "usingComponents": {}, | |||
| "enablePullDownRefresh": true | |||
| } | |||
| @@ -1,19 +1,26 @@ | |||
| .content { | |||
| padding-top: 50rpx; | |||
| padding: 50rpx 0; | |||
| .list { | |||
| padding: 0 50rpx; | |||
| font-size: 25rpx; | |||
| color: #747474; | |||
| .item { | |||
| position: relative; | |||
| border: 1px solid #000; | |||
| border: 1px dashed #999999; | |||
| padding: 20rpx; | |||
| border-radius: 10rpx; | |||
| margin-bottom: 25rpx; | |||
| .payAmount { | |||
| margin-bottom: 15rpx; | |||
| } | |||
| .payTime { | |||
| margin-bottom: 15rpx; | |||
| } | |||
| .check { | |||
| position: absolute; | |||
| width: 100rpx; | |||
| @@ -1,10 +1,11 @@ | |||
| <view class="content"> | |||
| <view class="list"> | |||
| <block wx:if="{{orderList && orderList.length > 0}}"> | |||
| <view class="item" wx:for="{{orderList}}"> | |||
| <view class="payAmount">支付金额:{{item.payAmount}}</view> | |||
| <view>支付时间:{{item.payTime}}</view> | |||
| <button class="check" type="primary" data-id="{{item.id}}" bindtap="goCheckDetail">查看</button> | |||
| <view class="item" wx:for="{{orderList}}" wx:key="index"> | |||
| <view class="payAmount">支付金额:{{item.payAmount / 100}} 元</view> | |||
| <view class="payTime">支付时间:{{item.payTime}}</view> | |||
| <view>到期时间:{{item.validEndTime}}</view> | |||
| <button class="check" type="primary" data-item="{{item}}" bindtap="goCheckDetail">查看</button> | |||
| </view> | |||
| </block> | |||
| <block wx:else> | |||
| @@ -71,8 +71,8 @@ Page({ | |||
| duration: 2000 | |||
| }) | |||
| setTimeout(() => { | |||
| wx.navigateTo({ | |||
| url: '/pages/payHistory/payHistory', | |||
| wx.redirectTo({ | |||
| url: '/pages/index/index', | |||
| }) | |||
| }, 2000); | |||
| wx.hideLoading(); | |||
| @@ -1,19 +1,58 @@ | |||
| export const formatTime = (date) => { | |||
| const year = date.getFullYear() | |||
| const month = date.getMonth() + 1 | |||
| const day = date.getDate() | |||
| const hour = date.getHours() | |||
| const minute = date.getMinutes() | |||
| const second = date.getSeconds() | |||
| return ( | |||
| [year, month, day].map(formatNumber).join('/') + | |||
| ' ' + | |||
| [hour, minute, second].map(formatNumber).join(':') | |||
| ) | |||
| /** | |||
| * @description 根据时间戳获取时间 | |||
| * @param {*} timestamp 必传,number类型,时间戳数据(10位及以下,10位至13位);若不传,则返回:“无时间戳” | |||
| * @param {*} format 选传,string类型,提供以下时间格式:YYYY-MM-DD hh:mm:ss、YYYY/MM/DD hh:mm:ss、YYYY.MM.DD hh:mm:ss、YYYY MM DD hh:mm:ss、YYYY年MM月DD日 hh:mm:ss、YYYY-MM-DD、YYYY/MM/DD、YYYY.MM.DD、YYYY MM DD、YYYY年MM月DD日;若不传,则默认为:YYYY-MM-DD | |||
| * @returns 根据要求的时间格式 | |||
| * @version V 1.0, Created by YWQ, 2022.10.20 | |||
| */ | |||
| export const timestampToTime = (timestamp, format) => { | |||
| //时间戳为10位需*1000,时间戳为13位不需乘1000 | |||
| const length = timestamp.length | |||
| if (length <= 10) { | |||
| var date = new Date(timestamp * 1000) | |||
| } else { | |||
| var date = new Date(timestamp) | |||
| } | |||
| let Y = String(date.getFullYear()) | |||
| let M = String(date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1) | |||
| let D = String(date.getDate() + 1 < 10 ? '0' + (date.getDate()) : date.getDate()) | |||
| let h = String(date.getHours() + 1 < 10 ? '0' + (date.getHours()) : date.getHours()) | |||
| let m = String(date.getMinutes() + 1 < 10 ? '0' + (date.getMinutes()) : date.getMinutes()) | |||
| let s = String(date.getSeconds() + 1 < 10 ? '0' + (date.getSeconds()) : date.getSeconds()) | |||
| // return Y + M + D + h + m + s | |||
| if (format == "YYYY-MM-DD hh:mm:ss") { | |||
| return Y + "-" + M + "-" + D + " " + h + ":" + m + ":" + s | |||
| } else if (format == "YYYY/MM/DD hh:mm:ss") { | |||
| return Y + "/" + M + "/" + D + " " + h + ":" + m + ":" + s | |||
| } else if (format == "YYYY.MM.DD hh:mm:ss") { | |||
| return Y + "." + M + "." + D + " " + h + ":" + m + ":" + s | |||
| } else if (format == "YYYY MM DD hh:mm:ss") { | |||
| return Y + " " + M + " " + D + " " + h + ":" + m + ":" + s | |||
| } else if (format == "YYYY年MM月DD日 hh:mm:ss") { | |||
| return Y + "年" + M + "月" + D + "日" + " " + h + ":" + m + ":" + s | |||
| } else if (format == "YYYY-MM-DD") { | |||
| return Y + "-" + M + "-" + D | |||
| } else if (format == "YYYY/MM/DD") { | |||
| return Y + "/" + M + "/" + D | |||
| } else if (format == "YYYY.MM.DD") { | |||
| return Y + "." + M + "." + D | |||
| } else if (format == "YYYY MM DD") { | |||
| return Y + " " + M + " " + D | |||
| } else if (format == "YYYY年MM月DD日") { | |||
| return Y + "年" + M + "月" + D + "日" | |||
| } else { | |||
| return Y + "-" + M + "-" + D | |||
| } | |||
| } | |||
| const formatNumber = (n) => { | |||
| const s = n.toString() | |||
| return s[1] ? s : '0' + s | |||
| /** | |||
| * @description:滚动到对应id的位置 | |||
| * @param {type} id | |||
| */ | |||
| export const scrollToID = id => { | |||
| wx.createSelectorQuery().select("#" + id).scrollIntoView({ | |||
| behavior: "smooth", | |||
| block: "start", | |||
| inline: "nearest", | |||
| }); | |||
| } | |||
| @@ -33,6 +33,7 @@ | |||
| "miniprogram/pages/payOrder/payOrder.js", | |||
| "miniprogram/pages/payHistory/payHistory.js", | |||
| "miniprogram/pages/chat/chat.js", | |||
| "miniprogram/pages/orderDetail/orderDetail.js", | |||
| ], | |||
| "exclude": [ | |||
| "node_modules" | |||