|
|
@@ -15,7 +15,7 @@
|
|
|
mode="widthFix"></image>
|
|
|
|
|
|
<view class="dropdown-menu" v-if="showDropdown">
|
|
|
- <view class="dropdown-item" @tap="handleOption('report')">举报内容</view>
|
|
|
+ <view class="dropdown-item" @tap="handleOption('report')">举报内容</view>
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
@@ -30,7 +30,7 @@
|
|
|
<view v-if="shouldShowTime(idx)" class="cs-time-bar">
|
|
|
<view class="cs-time-inner">{{ formatTime(msg.time) }}</view>
|
|
|
</view>
|
|
|
- <template v-if="msg.type === 'orderCard'">
|
|
|
+ <template v-if="msg.message_type == 5">
|
|
|
<view class="cs-msg-order-card-box">
|
|
|
<image class="order-card-avatar" :src="msg.avatar" />
|
|
|
<view class="cs-msg-order-card">
|
|
|
@@ -60,7 +60,34 @@
|
|
|
msg.type === 'user' ? 'cs-msg-self' : 'cs-msg-other',
|
|
|
]">
|
|
|
<image class="cs-avatar" :src="msg.avatar" />
|
|
|
- <view class="cs-msg-bubble">{{ msg.content }}</view>
|
|
|
+ <view class="cs-msg-bubble">
|
|
|
+ <!-- 文本消息 -->
|
|
|
+ <template v-if="msg.message_type === 1">
|
|
|
+ {{ msg.content }}
|
|
|
+ </template>
|
|
|
+ <!-- 图片消息 -->
|
|
|
+ <template v-else-if="msg.message_type === 2">
|
|
|
+ <view style="position:relative;display:inline-block;">
|
|
|
+ <image :src="msg.media_url" mode="aspectFit" style="max-width: 180rpx; max-height: 180rpx; border-radius: 8rpx;" @tap="!msg.uploading && previewImage(msg.media_url)" />
|
|
|
+ <view v-if="msg.uploading" style="position:absolute;left:0;top:0;width:100%;height:100%;background:rgba(255,255,255,0.7);display:flex;align-items:center;justify-content:center;">
|
|
|
+ <text style="color:#a6e22e;font-size:24rpx;">{{ msg.progress || 0 }}%</text>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </template>
|
|
|
+ <!-- 语音消息 -->
|
|
|
+ <template v-else-if="msg.message_type === 3">
|
|
|
+ <view class="cs-msg-voice">[语音消息] <text style="color:#a6e22e">(暂不支持播放)</text></view>
|
|
|
+ </template>
|
|
|
+ <!-- 视频消息 -->
|
|
|
+ <template v-else-if="msg.message_type === 4">
|
|
|
+ <video :src="msg.media_url" controls style="max-width: 220rpx; max-height: 180rpx; border-radius: 8rpx;" />
|
|
|
+ </template>
|
|
|
+
|
|
|
+ <!-- 其它未知类型 -->
|
|
|
+ <template v-else>
|
|
|
+ <text style="color:#bbb">[未知消息类型]</text>
|
|
|
+ </template>
|
|
|
+ </view>
|
|
|
</view>
|
|
|
</template>
|
|
|
</view>
|
|
|
@@ -96,19 +123,33 @@
|
|
|
</view>
|
|
|
</view>
|
|
|
|
|
|
- <view class="cs-input-area">
|
|
|
+ <!-- 假输入框 -->
|
|
|
+ <view v-if="!showRealInput" class="fake-input-bar" @click="showInputAndFocus">
|
|
|
+ <view class="fake-input-placeholder">在这里输入新消息</view>
|
|
|
+ <view class="fake-input-icons">
|
|
|
+ <image src="/static/icon/icon-picture.png" class="fake-input-icon" />
|
|
|
+ <image src="/static/icon/icon-expression.png" class="fake-input-icon" />
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <!-- 真输入框 -->
|
|
|
+ <view v-else class="cs-input-area">
|
|
|
<textarea class="cs-textarea" v-model="inputValue" placeholder="在这里输入新消息" :focus="inputFocused"
|
|
|
:adjust-position="false" @focus="onInputFocus" @blur="onInputBlur"
|
|
|
@keyboardheightchange="onKeyboardHeightChange" maxlength="300" auto-height
|
|
|
:style="{ 'max-height': '120rpx', 'overflow-y': 'auto' }"></textarea>
|
|
|
- <view class="emoji-trigger" @tap="toggleEmojiPanel">
|
|
|
- <text class="fa fa-smile-o"></text>
|
|
|
+ <view class="bottom-bar">
|
|
|
+ <view>
|
|
|
+ <image @tap="upload" src="/static/icon/icon-picture.png" class="fake-input-icon" />
|
|
|
+ <image @tap="toggleEmojiPanel" src="/static/icon/icon-expression.png" class="fake-input-icon" />
|
|
|
+ </view>
|
|
|
+ <view :class="['send_btn', inputValue.trim() ? '' : 'prohibit']" @tap="sendMsg">发送</view>
|
|
|
</view>
|
|
|
- <view class="send_btn" @tap="sendMsg">发送</view>
|
|
|
</view>
|
|
|
</view>
|
|
|
|
|
|
<view class="emoji-panel" :class="{ show: showEmojiPanel }" v-if="showEmojiPanel">
|
|
|
+ <view class="emoji-mask" @click="showEmojiPanel = false"></view>
|
|
|
<view class="emoji-grid">
|
|
|
<view class="emoji-item" v-for="(emoji, index) in emojiList" :key="index" @tap="selectEmoji(emoji)">
|
|
|
{{ emoji }}
|
|
|
@@ -119,111 +160,33 @@
|
|
|
</template>
|
|
|
|
|
|
<script>
|
|
|
+import permission from '@/common/permission.js';
|
|
|
+
|
|
|
export default {
|
|
|
data() {
|
|
|
return {
|
|
|
- chatList: [
|
|
|
- {
|
|
|
- id: 1,
|
|
|
- content: "哈哈哈哈哈哈哈哈红红火火恍恍惚惚",
|
|
|
- type: "customerService",
|
|
|
- avatar: "/static/home/avator.png",
|
|
|
- time: "2025-05-21 20:01",
|
|
|
- },
|
|
|
- {
|
|
|
- id: 2,
|
|
|
- content: "哈哈哈哈哈哈哈哈红红火火恍恍惚惚",
|
|
|
- type: "customerService",
|
|
|
- avatar: "/static/home/avator.png",
|
|
|
- time: "2025-05-21 20:05",
|
|
|
- },
|
|
|
- {
|
|
|
- id: 3,
|
|
|
- content: "你好请问可以怎么帮助你",
|
|
|
- type: "user",
|
|
|
- avatar: "/static/makedetail/characterProfilePicture.png",
|
|
|
- time: "2025-05-21 20:10",
|
|
|
- },
|
|
|
- {
|
|
|
- id: 4,
|
|
|
- content:
|
|
|
- "哈哈哈哈哈哈哈哈红红火火恍恍惚惚哈哈哈哈哈哈哈哈红红火火恍恍惚惚哈哈哈哈哈哈哈哈红红火火恍恍惚惚哈哈哈哈哈哈哈哈红红火火恍恍惚惚哈哈哈哈哈哈哈哈红红火火恍恍惚惚哈哈哈哈哈哈哈哈红红火火恍恍惚惚哈哈哈哈哈哈哈哈红红火火恍恍惚惚哈哈哈哈哈哈哈哈红红火火恍恍惚惚哈哈哈哈哈哈哈哈红红火火恍恍惚惚哈哈哈哈哈哈哈哈红红火火恍恍惚惚哈哈哈哈哈哈哈哈红红火火恍恍惚惚",
|
|
|
- type: "user",
|
|
|
- avatar: "/static/makedetail/characterProfilePicture.png",
|
|
|
- time: "2025-05-21 20:10",
|
|
|
- },
|
|
|
- {
|
|
|
- id: 5,
|
|
|
- content: "哈哈哈哈哈哈哈哈红红火火恍恍惚惚",
|
|
|
- type: "customerService",
|
|
|
- avatar: "/static/home/avator.png",
|
|
|
- time: "2025-05-21 20:01",
|
|
|
- },
|
|
|
- {
|
|
|
- id: 6,
|
|
|
- content: "哈哈哈哈哈哈哈哈红红火火恍恍惚惚",
|
|
|
- type: "customerService",
|
|
|
- avatar: "/static/home/avator.png",
|
|
|
- time: "2025-05-21 20:05",
|
|
|
- },
|
|
|
- {
|
|
|
- id: 7,
|
|
|
- content: "哈哈哈哈哈哈哈哈红红火火恍恍惚惚",
|
|
|
- type: "customerService",
|
|
|
- avatar: "/static/home/avator.png",
|
|
|
- time: "2025-05-21 20:01",
|
|
|
- },
|
|
|
- {
|
|
|
- id: 8,
|
|
|
- content:
|
|
|
- "哈哈哈哈哈哈哈哈红红火火恍恍惚惚哈哈哈哈哈哈哈哈红红火火恍恍惚惚哈哈哈哈哈哈哈哈红红火火恍恍惚惚哈哈哈哈哈哈哈哈红红火火恍恍惚惚哈哈哈哈哈哈哈哈红红火火恍恍惚惚哈哈哈哈哈哈哈哈红红火火恍恍惚惚哈哈哈哈哈哈哈哈红红火火恍恍惚惚哈哈哈哈哈哈哈哈红红火火恍恍惚惚哈哈哈哈哈哈哈哈红红火火恍恍惚惚哈哈哈哈哈哈哈哈红红火火恍恍惚惚哈哈哈哈哈哈哈哈红红火火恍恍惚惚",
|
|
|
- type: "customerService",
|
|
|
- avatar: "/static/home/avator.png",
|
|
|
- time: "2025-05-21 20:05",
|
|
|
- },
|
|
|
- {
|
|
|
- id: 9,
|
|
|
- content: "你好请问可以怎么帮助你",
|
|
|
- type: "user",
|
|
|
- avatar: "/static/makedetail/characterProfilePicture.png",
|
|
|
- time: "2025-05-21 21:10",
|
|
|
- },
|
|
|
- {
|
|
|
- id: 13,
|
|
|
- content: "你好请问可以怎么帮助你",
|
|
|
- type: "user",
|
|
|
- avatar: "/static/makedetail/characterProfilePicture.png",
|
|
|
- time: "2025-05-21 20:10",
|
|
|
- },
|
|
|
- {
|
|
|
- id: 10,
|
|
|
- content: "哈哈哈哈哈哈哈哈红红火火恍恍惚惚",
|
|
|
- type: "customerService",
|
|
|
- avatar: "/static/home/avator.png",
|
|
|
- time: "2025-05-21 20:01",
|
|
|
- },
|
|
|
- {
|
|
|
- id: 11,
|
|
|
- content: "哈哈哈哈哈哈哈哈红红火火恍恍惚惚",
|
|
|
- type: "customerService",
|
|
|
- avatar: "/static/home/avator.png",
|
|
|
- time: "2025-05-21 23:05",
|
|
|
- },
|
|
|
- ],
|
|
|
+ chatList: [],
|
|
|
inputValue: "",
|
|
|
pollTimer: null,
|
|
|
scrollToView: "bottom-anchor",
|
|
|
adShow: true,
|
|
|
keyboardHeight: 0,
|
|
|
inputFocused: false,
|
|
|
- orderCardHeight: 260, // rpx,实际高度可根据广告条内容微调
|
|
|
+ orderCardHeight: 260,
|
|
|
showEmojiPanel: false,
|
|
|
- showDropdown: false, // 控制下拉菜单显示状态
|
|
|
- emojiList: ["😀", "😁", "😂", "🤣", "😃", "😄", "😅", "😆", "😉", "😊", "😋", "😎", "😍", "😘", "🥰", "😗", "😙", "😚", "🙂", "🤗", "🤩", "🤔", "🤨", "😐", "😑", "😶", "🙄", "😏", "😣", "😥", "😮", "🤐", "😯", "😪", "😫", "🥱", "😴", "😌", "😛", "😜", "😝", "🤤", "😒", "😓", "😔", "😕", "🙃", "🤑", "😲", "☹️", "🙁", "😖", "😞", "😟", "😤", "😢", "😭", "😦", "😧", "😨", "😩", "🤯", "😬", "😰", "😱", "🥵", "🥶", "😳", "🤪", "😵", "😡", "😠", "🤬", "😷", "🤒", "🤕", "🤢", "🤮", "🥴", "😇", "🥳", "🥺", "🤠", "😈", "👿", "👹", "👺", "💀", "👻", "👽", "🤖", "💩", "😺", "😸", "😹", "😻", "😼", "😽", "🙀", "😿", "😾", "🙈", "🙉", "🙊", "💋", "💌", "💘", "💝", "💖", "💗", "💓", "💞", "💕", "💟", "❣️", "💔", "❤️", "🧡", "💛", "💚", "💙", "💜", "🤎", "🖤", "🤍", "💯", "💢", "💥", "💫", "💦", "💨", "🕳️", "💣", "💬", "👋", "🤚", "🖐️", "✋", "🖖", "👌", "🤏", "✌️", "🤞", "🤟", "🤘", "🤙", "👈", "👉", "👆", "🖕", "👇", "☝️", "👍", "👎", "✊", "👊", "🤛", "🤜", "👏", "🙌", "👐", "🤲", "🙏", "✍️", "💅", "🤳", "💪", "🦾", "🦵", "🦶", "👂", "👃", "🧠", "🦷", "🦴", "👀", "👁️", "👅", "👄",
|
|
|
- ],
|
|
|
+ showDropdown: false,
|
|
|
+ emojiList: ["😀", "😁", "😂", "🤣", "😃", "😄", "😅", "😆", "😉", "😊", "😋", "😎", "😍", "😘", "🥰", "😗", "😙", "😚", "🙂", "🤗", "🤩", "🤔", "🤨", "😐", "😑", "😶", "🙄", "😏", "😣", "😥", "😮", "🤐", "😯", "😪", "😫", "🥱", "😴", "😌", "😛", "😜", "😝", "🤤", "😒", "😓", "😔", "😕", "🙃", "🤑", "😲", "☹️", "🙁", "😖", "😞", "😟", "😤", "😢", "😭", "😦", "😧", "😨", "😩", "🤯", "😬", "😰", "😱", "🥵", "🥶", "😳", "🤪", "😵", "😡", "😠", "🤬", "😷", "🤒", "🤕", "🤢", "🤮", "🥴", "😇", "🥳", "🥺", "🤠", "😈", "👿", "👹", "👺", "💀", "👻", "👽", "🤖", "💩", "😺", "😸", "😹", "😻", "😼", "😽", "🙀", "😿", "😾", "🙈", "🙉", "🙊", "💋", "💌", "💘", "💝", "💖", "💗", "💓", "💞", "💕", "💟", "❣️", "💔", "❤️", "🧡", "💛", "💚", "💙", "💜", "🤎", "🖤", "🤍", "💯", "💢", "💥", "💫", "💦", "💨", "🕳️", "💣", "💬", "👋", "🤚", "🖐️", "✋", "🖖", "👌", "🤏", "✌️", "🤞", "🤟", "🤘", "🤙", "👈", "👉", "👆", "🖕", "👇", "☝️", "👍", "👎", "✊", "👊", "🤛", "🤜", "👏", "🙌", "👐", "🤲", "🙏", "✍️", "💅", "🤳", "💪", "🦾", "🦵", "🦶", "👂", "👃", "🧠", "🦷", "🦴", "��", "👁️", "👅", "👄"],
|
|
|
+ conversationId: 0,
|
|
|
+ creatorId: 0,
|
|
|
+ lastMsgId: 0,
|
|
|
+ pageSize: 20,
|
|
|
+ userInfo: {},
|
|
|
+ showRealInput: false, // 控制显示真输入框还是假输入框
|
|
|
};
|
|
|
},
|
|
|
- onShow() {
|
|
|
+ onLoad(options) {
|
|
|
+ this.creatorId = options.id || 0;
|
|
|
+ this.fetchMessages();
|
|
|
this.startPolling();
|
|
|
},
|
|
|
onHide() {
|
|
|
@@ -239,8 +202,8 @@ export default {
|
|
|
// 轮询获取消息
|
|
|
startPolling() {
|
|
|
this.clearPolling();
|
|
|
- this.pollTimer = setInterval(this.fetchMessages, 30000);
|
|
|
- this.fetchMessages();
|
|
|
+ this.pollTimer = setInterval(() => this.fetchMessages(false), 5000);
|
|
|
+ this.fetchMessages(false);
|
|
|
},
|
|
|
clearPolling() {
|
|
|
if (this.pollTimer) {
|
|
|
@@ -248,29 +211,98 @@ export default {
|
|
|
this.pollTimer = null;
|
|
|
}
|
|
|
},
|
|
|
- fetchMessages() {
|
|
|
- // TODO: 替换为实际接口获取消息的接口
|
|
|
- // uni.request({ ... })
|
|
|
- // 假设新消息加入chatList
|
|
|
- // this.chatList.push(...)
|
|
|
- // 滚动到底部
|
|
|
- this.$nextTick(() => {
|
|
|
- this.scrollToView = "bottom-anchor";
|
|
|
+ // 获取消息
|
|
|
+ fetchMessages(isAppend = false) {
|
|
|
+ uni.request({
|
|
|
+ url: this.$apiHost + '/App/kefuGetMessages',
|
|
|
+ method: 'GET',
|
|
|
+ data: {
|
|
|
+ uuid: getApp().globalData.uuid,
|
|
|
+ skey: getApp().globalData.skey,
|
|
|
+ creator_id: this.creatorId,
|
|
|
+ conversation_id: this.conversationId,
|
|
|
+ last_id: isAppend ? this.lastMsgId : 0,
|
|
|
+ page_size: this.pageSize,
|
|
|
+ zc_id: this.creatorId
|
|
|
+ },
|
|
|
+ success: (res) => {
|
|
|
+ if (res.data && res.data.success === 'yes' && res.data.data) {
|
|
|
+ const { messages, conversation, user_info } = res.data.data;
|
|
|
+ this.userInfo = user_info || {};
|
|
|
+ this.conversationId = conversation?.id || 0;
|
|
|
+ // 格式化消息,保留 message_type、media_url 等字段
|
|
|
+ const msgList = (messages || []).map(msg => ({
|
|
|
+ id: msg.id,
|
|
|
+ content: msg.content,
|
|
|
+ type: msg.from_type === 1 ? 'user' : 'customerService',
|
|
|
+ avatar: msg.from_type === 1 ? (user_info.avatar || '/static/makedetail/characterProfilePicture.png') : '/static/home/avator.png',
|
|
|
+ time: msg.create_time,
|
|
|
+ message_type: msg.message_type, // 消息类型
|
|
|
+ media_url: msg.media_url, // 媒体文件URL
|
|
|
+ progress: msg.progress,
|
|
|
+ uploading: msg.uploading
|
|
|
+ }));
|
|
|
+ // 合并未上传完成的临时消息
|
|
|
+ const tempMsgs = this.chatList.filter(m => m.uploading);
|
|
|
+ let newList;
|
|
|
+ if (isAppend) {
|
|
|
+ newList = [...msgList.reverse(), ...this.chatList.filter(m => !m.uploading), ...tempMsgs];
|
|
|
+ } else {
|
|
|
+ newList = [...msgList.reverse(), ...tempMsgs];
|
|
|
+ }
|
|
|
+ this.chatList = newList;
|
|
|
+ // 记录最后一条消息ID
|
|
|
+ if (messages && messages.length > 0) {
|
|
|
+ this.lastMsgId = messages[0].id;
|
|
|
+ }
|
|
|
+ this.$nextTick(() => {
|
|
|
+ this.scrollToView = "bottom-anchor";
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ // 只保留临时消息
|
|
|
+ this.chatList = this.chatList.filter(m => m.uploading);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ fail: () => {
|
|
|
+ // 只保留临时消息
|
|
|
+ this.chatList = this.chatList.filter(m => m.uploading);
|
|
|
+ }
|
|
|
});
|
|
|
},
|
|
|
+ // 发送消息
|
|
|
sendMsg() {
|
|
|
if (!this.inputValue.trim()) return;
|
|
|
- this.chatList.push({
|
|
|
- id: Date.now(),
|
|
|
- content: this.inputValue,
|
|
|
- type: "user",
|
|
|
- avatar: "/static/avatar/cs2.png",
|
|
|
- });
|
|
|
+ const content = this.inputValue;
|
|
|
this.inputValue = "";
|
|
|
- this.$nextTick(() => {
|
|
|
- this.scrollToView = "bottom-anchor";
|
|
|
+ uni.request({
|
|
|
+ url: this.$apiHost + '/App/kefuSendMessage',
|
|
|
+ method: 'POST',
|
|
|
+ header: {
|
|
|
+ "content-type": "application/x-www-form-urlencoded",
|
|
|
+ uuid: getApp().globalData.uuid,
|
|
|
+ skey: getApp().globalData.skey,
|
|
|
+ },
|
|
|
+ data: {
|
|
|
+ uuid: getApp().globalData.uuid,
|
|
|
+ skey: getApp().globalData.skey,
|
|
|
+ creator_id: this.creatorId,
|
|
|
+ conversation_id: this.conversationId,
|
|
|
+ message_type: 1, // 文本
|
|
|
+ content: content,
|
|
|
+ zc_id: this.creatorId
|
|
|
+ },
|
|
|
+ success: (res) => {
|
|
|
+ if (res.data && res.data.success === 'yes') {
|
|
|
+ // 发送成功后刷新消息
|
|
|
+ this.fetchMessages(false);
|
|
|
+ } else {
|
|
|
+ uni.showToast({ title: res.data.str || '发送失败', icon: 'none' });
|
|
|
+ }
|
|
|
+ },
|
|
|
+ fail: () => {
|
|
|
+ uni.showToast({ title: '网络错误', icon: 'none' });
|
|
|
+ }
|
|
|
});
|
|
|
- // TODO: 发送消息到后端接口
|
|
|
},
|
|
|
closeOrderCard() {
|
|
|
this.adShow = false;
|
|
|
@@ -374,8 +406,152 @@ export default {
|
|
|
uni.navigateTo({
|
|
|
url: '/pages/my/feedback?isReportContent=true'
|
|
|
});
|
|
|
- break;
|
|
|
+ break;
|
|
|
}
|
|
|
+ },
|
|
|
+ showInputAndFocus() {
|
|
|
+ this.showRealInput = true;
|
|
|
+ this.$nextTick(() => {
|
|
|
+ this.inputFocused = true;
|
|
|
+ });
|
|
|
+ },
|
|
|
+ // 上传图片并发送图片消息,增加进度展示
|
|
|
+ async upload() {
|
|
|
+ uni.showActionSheet({
|
|
|
+ itemList: ['拍照', '从相册选择'],
|
|
|
+ success: async (res) => {
|
|
|
+ const sourceType = res.tapIndex === 0 ? 'camera' : 'album';
|
|
|
+ let hasPermission = false;
|
|
|
+
|
|
|
+ try {
|
|
|
+ if (sourceType === 'camera') {
|
|
|
+ hasPermission = await permission.request(permission.PermissionType.CAMERA, {
|
|
|
+ title: '“萌创星球”想访问你的相机',
|
|
|
+ describe: '萌创星球想访问您的摄像头,便于拍摄获取图片来与其他用户进行交流'
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ hasPermission = await permission.request(permission.PermissionType.PHOTO_LIBRARY, {
|
|
|
+ title: '“萌创星球”想访问你的照片图库',
|
|
|
+ describe: '萌创星球想访问您本地照片图库,便于获取图片来与其他用户进行交流'
|
|
|
+ });
|
|
|
+ }
|
|
|
+ if (!hasPermission) {
|
|
|
+ uni.showToast({
|
|
|
+ title: sourceType === 'camera' ? '未获得相机权限' : '未获得相册权限',
|
|
|
+ icon: 'none'
|
|
|
+ });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ // 权限通过后,选择图片
|
|
|
+ uni.chooseImage({
|
|
|
+ count: 1,
|
|
|
+ sizeType: ['compressed'],
|
|
|
+ sourceType: [sourceType],
|
|
|
+ success: (res) => {
|
|
|
+ const filePath = res.tempFilePaths[0];
|
|
|
+ // 1. 先插入临时消息
|
|
|
+ const tempMsgId = 'temp_' + Date.now();
|
|
|
+ this.chatList.push({
|
|
|
+ id: tempMsgId,
|
|
|
+ type: 'user',
|
|
|
+ avatar: this.userInfo.avatar || '/static/makedetail/characterProfilePicture.png',
|
|
|
+ time: this.getNowTime(),
|
|
|
+ message_type: 2,
|
|
|
+ media_url: filePath,
|
|
|
+ progress: 0,
|
|
|
+ uploading: true
|
|
|
+ });
|
|
|
+ this.$nextTick(() => {
|
|
|
+ this.scrollToView = "bottom-anchor";
|
|
|
+ });
|
|
|
+ // 2. 上传图片
|
|
|
+ uni.uploadFile({
|
|
|
+ url: this.$apiHost + '/Xweb/upload_img?skey=' + getApp().globalData.skey,
|
|
|
+ filePath: filePath,
|
|
|
+ name: 'file',
|
|
|
+ // 上传进度
|
|
|
+ progress: (e) => {
|
|
|
+ const idx = this.chatList.findIndex(m => m.id === tempMsgId);
|
|
|
+ if (idx !== -1) this.$set(this.chatList, idx, { ...this.chatList[idx], progress: e.progress });
|
|
|
+ },
|
|
|
+ success: (uploadFileRes) => {
|
|
|
+ let resdata = JSON.parse(uploadFileRes.data);
|
|
|
+ const idx = this.chatList.findIndex(m => m.id === tempMsgId);
|
|
|
+ if (resdata.success == 'no') {
|
|
|
+ if (idx !== -1) this.chatList.splice(idx, 1);
|
|
|
+ uni.showToast({ title: resdata.str, icon: 'none' });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (resdata.code == 0) {
|
|
|
+ // 替换为正式消息
|
|
|
+ if (idx !== -1) this.$set(this.chatList, idx, {
|
|
|
+ id: Date.now(),
|
|
|
+ type: 'user',
|
|
|
+ avatar: this.userInfo.avatar || '/static/makedetail/characterProfilePicture.png',
|
|
|
+ time: this.getNowTime(),
|
|
|
+ message_type: 2,
|
|
|
+ media_url: resdata.data.path,
|
|
|
+ progress: 100,
|
|
|
+ uploading: false
|
|
|
+ });
|
|
|
+ // 发送图片消息到服务端
|
|
|
+ this.sendImageMsg(resdata.data.path);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ fail: () => {
|
|
|
+ const idx = this.chatList.findIndex(m => m.id === tempMsgId);
|
|
|
+ if (idx !== -1) this.chatList.splice(idx, 1);
|
|
|
+ uni.showToast({ title: '图片上传失败', icon: 'none' });
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ });
|
|
|
+ } catch (error) {
|
|
|
+ uni.showToast({
|
|
|
+ title: '权限检查失败',
|
|
|
+ icon: 'none'
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ },
|
|
|
+ sendImageMsg(imgUrl) {
|
|
|
+ uni.request({
|
|
|
+ url: this.$apiHost + '/App/kefuSendMessage',
|
|
|
+ method: 'POST',
|
|
|
+ header: {
|
|
|
+ "content-type": "application/x-www-form-urlencoded",
|
|
|
+ uuid: getApp().globalData.uuid,
|
|
|
+ skey: getApp().globalData.skey,
|
|
|
+ },
|
|
|
+ data: {
|
|
|
+ uuid: getApp().globalData.uuid,
|
|
|
+ skey: getApp().globalData.skey,
|
|
|
+ creator_id: this.creatorId,
|
|
|
+ conversation_id: this.conversationId,
|
|
|
+ message_type: 2, // 2为图片
|
|
|
+ content: '', // 图片消息content可为空
|
|
|
+ media_url: imgUrl, // 图片地址
|
|
|
+ zc_id: this.creatorId
|
|
|
+ },
|
|
|
+ success: (res) => {
|
|
|
+ if (res.data && res.data.success === 'yes') {
|
|
|
+ this.fetchMessages(false);
|
|
|
+ } else {
|
|
|
+ uni.showToast({ title: res.data.str || '发送失败', icon: 'none' });
|
|
|
+ }
|
|
|
+ },
|
|
|
+ fail: () => {
|
|
|
+ uni.showToast({ title: '网络错误', icon: 'none' });
|
|
|
+ }
|
|
|
+ });
|
|
|
+ },
|
|
|
+ // 图片预览
|
|
|
+ previewImage(url) {
|
|
|
+ uni.previewImage({
|
|
|
+ current: url,
|
|
|
+ urls: [url]
|
|
|
+ });
|
|
|
},
|
|
|
},
|
|
|
};
|
|
|
@@ -629,10 +805,42 @@ export default {
|
|
|
right: 0;
|
|
|
bottom: 0;
|
|
|
z-index: 10;
|
|
|
+ padding-bottom: calc(12rpx + var(--window-bottom));
|
|
|
+
|
|
|
+ .fake-input-bar {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ background: #f6f7f9;
|
|
|
+ border-radius: 24rpx;
|
|
|
+ padding: 12rpx 20rpx;
|
|
|
+ margin: 0 12rpx;
|
|
|
+ flex: 1;
|
|
|
+ min-height: 64rpx;
|
|
|
+ border: 1rpx solid #ededed;
|
|
|
+
|
|
|
+ .fake-input-placeholder {
|
|
|
+ color: #bbb;
|
|
|
+ font-size: 28rpx;
|
|
|
+ flex: 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ .fake-input-icons {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .fake-input-icon {
|
|
|
+ width: 40rpx;
|
|
|
+ height: 40rpx;
|
|
|
+ margin-left: 16rpx;
|
|
|
+ }
|
|
|
|
|
|
.cs-input-area {
|
|
|
display: flex;
|
|
|
align-items: flex-end;
|
|
|
+ flex-direction: column;
|
|
|
background: #fff;
|
|
|
border-radius: 32rpx;
|
|
|
padding: 8rpx 12rpx;
|
|
|
@@ -649,14 +857,15 @@ export default {
|
|
|
border-radius: 24rpx;
|
|
|
padding: 12rpx 20rpx;
|
|
|
resize: none;
|
|
|
+ width: 100%;
|
|
|
}
|
|
|
|
|
|
- .emoji-trigger {
|
|
|
- margin: 0 12rpx;
|
|
|
- font-size: 36rpx;
|
|
|
- color: #999;
|
|
|
+ .bottom-bar {
|
|
|
+ width: 100%;
|
|
|
+ padding: 12rpx 0;
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
+ justify-content: space-between;
|
|
|
}
|
|
|
|
|
|
.send_btn {
|
|
|
@@ -664,10 +873,15 @@ export default {
|
|
|
color: #fff;
|
|
|
border-radius: 32rpx;
|
|
|
font-size: 28rpx;
|
|
|
- padding: 0 32rpx;
|
|
|
- height: 64rpx;
|
|
|
- line-height: 64rpx;
|
|
|
- margin-left: 8rpx;
|
|
|
+ padding: 26rpx 32rpx;
|
|
|
+ line-height: 0;
|
|
|
+ border: 1rpx solid transparent;
|
|
|
+
|
|
|
+ &.prohibit {
|
|
|
+ background: #fff;
|
|
|
+ border: 1rpx solid #999;
|
|
|
+ color: #999;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -677,27 +891,42 @@ export default {
|
|
|
left: 0;
|
|
|
right: 0;
|
|
|
bottom: 0;
|
|
|
- max-height: 50vh;
|
|
|
- width: 100vw;
|
|
|
- background: #fff;
|
|
|
- padding: 12rpx 0 0 0;
|
|
|
- border-top: 1rpx solid #ededed;
|
|
|
z-index: 1000;
|
|
|
- box-shadow: 0 -4rpx 24rpx rgba(0, 0, 0, 0.08);
|
|
|
- overflow-y: auto;
|
|
|
- transform: translateY(100%);
|
|
|
- transition: transform 0.25s cubic-bezier(0.4, 0, 0.2, 1);
|
|
|
- border-top: 20rpx solid #fff;
|
|
|
+ width: 100vw;
|
|
|
+ height: 100vh;
|
|
|
|
|
|
&.show {
|
|
|
transform: translateY(0);
|
|
|
}
|
|
|
|
|
|
+ .emoji-mask {
|
|
|
+ position: fixed;
|
|
|
+ left: 0;
|
|
|
+ right: 0;
|
|
|
+ top: 0;
|
|
|
+ bottom: 0;
|
|
|
+ background: rgba(0, 0, 0, 0.1);
|
|
|
+ z-index: 1001;
|
|
|
+ }
|
|
|
+
|
|
|
.emoji-grid {
|
|
|
+ position: relative;
|
|
|
+ z-index: 1002;
|
|
|
display: flex;
|
|
|
flex-wrap: wrap;
|
|
|
justify-content: center;
|
|
|
padding-bottom: 24rpx;
|
|
|
+ max-height: 50vh;
|
|
|
+ width: 100vw;
|
|
|
+ border-top: 1rpx solid #ededed;
|
|
|
+
|
|
|
+ background: #fff;
|
|
|
+ padding: 12rpx 0 0 0;
|
|
|
+ box-shadow: 0 -4rpx 24rpx rgba(0, 0, 0, 0.08);
|
|
|
+ overflow-y: auto;
|
|
|
+ transform: translateY(100%);
|
|
|
+ transition: transform 0.25s cubic-bezier(0.4, 0, 0.2, 1);
|
|
|
+ border-top: 20rpx solid #fff;
|
|
|
|
|
|
.emoji-item {
|
|
|
width: 60rpx;
|